OmniAICreator/Qiita-1.07M huggingface dataset:
Windows×IntelliJ×KotlinでSelenium環境構築

#はじめに
ちょっと~~レベリングをサボりたく~~
UIテストを自動化したくてSelenium環境作ったので書きたいと思います。
Kotlinで書いてますがJavaでも同じようにできます。

#環境
まずは自分のPC環境（2018年3月時点）
- Windows:10
- IntelliJ:2017.2.6
- kotlin:1.2.21
- ChromeDriver:2.36
- Chrome:65

#環境構築
まずはIntelliJでプロジェクトを作ります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240643/3754ba16-7af9-fcde-78d2-9885fc3b10f1.png)
GroupidとArtifactidを入力して、プロジェクトを作成。

``build.gradle``にSeleniumのライブラリを追加します。

```
compile "org.seleniumhq.selenium:selenium-java:3.5.3"
```

次にChromeDriverをダウンロードします。インストール済みのChromeに対応したバージョンのものが必要です。
https://sites.google.com/a/chromium.org/chromedriver/downloads

ダウンロードした、``chromedriver.exe``をプロジェクトに入れます。
今回はプロジェクトのルートにdriverというディレクトリを作成してその中に入れました。

次にテストコードを作成します。
Chromeの実行ファイルのパス、先ほどダウンロードしたChromeDriverのパスを入力する必要があります。


```kotlin:SeleniumSample.kt
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions

class SeleniumSample {
    private lateinit var driver: WebDriver

    @Before
    fun setUp() {
        //chrome driverの指定
        System.setProperty("webdriver.chrome.driver", ".\\driver\\chromedriver.exe")

        driver = ChromeDriver(ChromeOptions().apply {
            //chromeのパスを指定
            setBinary(java.io.File("C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"))
        })
    }

    @After
    fun tearDown() {
        driver.quit()
    }

    @Test
    fun test_sample() {
        driver.get("https://www.yahoo.co.jp/")
        Thread.sleep(1000)
    }
}
```

あとは、コード`` fun test_sample() ``の左側にある実行ボタンを押すとChromeが起動しYahoo!Japanが表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/240643/a8fa8fb3-7578-0b59-54f1-6c3299c4b37c.png)
以上環境構築完了です。

#おわりに
手でポチポチやっていたのを自動化できるとめちゃくちゃ楽になりました。
たまに安定しなくなったりしますが、Chromeが自動更新したりしてて対応バージョンのdriverに更新したりすると治ったりしました。
GCP > Cloud Launcher > redmine 設定　






# smtp server



[Google Compute Engine では、ポート 25、465、587 での送信接続は許可されません。](https://cloud.google.com/compute/docs/tutorials/sending-mail/?hl=ja) とのこと。
メール送信はSendGrid、Mailgun、Mailjet などを使えとな。


ちなみに設定方法は以下

[Bitnami Redmine for Google Cloud Platform](https://docs.bitnami.com/google/apps/redmine/#how-to-configure-outbound-email-settings)



`vi /opt/bitnami/apps/redmine/htdocs/config/configuration.yml`


```
default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      enable_starttls_auto: true
      address: "smtp.gmail.com"
      port: 587
      domain: "smtp.gmail.com"
      authentication: :plain
      user_name: "username@gmail.com"
      password: "password"
```


メール通知のテスト
「管理」→「設定」画面で「メール通知」タブを開き、画面左下の「テストメールを送信」というリンクをクリックしてください。




# phpMyAdmin

```
sudo su
```


### change config

```
vi /opt/bitnami/apps/phpmyadmin/conf/httpd-app.conf
```

allow all

```
Allow from 127.0.0.1 → Allow from all
Require local → Require all granted
```

### restart

```
sudo su
/opt/bitnami/ctlscript.sh restart apache
```


access blowser

https://xxxx.com/phpMyAdmin


## plugin


### update gem

```
gem -v
gem install rubygems-update --source http://rubygems.org/
update_rubygems
gem -v
```


けっこう時間かかる。10分以上

##

cd /opt/bitnami/apps/redmine/htdocs/plugins


## ファイル配置

ファイルの権限を変えておく

sudo chown -R bitnami *
sudo chgrp -R daemon *


## bundle install

```
sudo bundle install
sudo bundle install --no-deployment
sudo gem update --system 
sudo bundle install

sudo bundle exec rake db:migrate RAILS_ENV=production
sudo bundle exec rake redmine:plugins:migrate RAILS_ENV=production
```



mysql2のバージョンが古いというエラーがで場合
```
sudo gem install mysql2 -v '0.4.10'
```


その際、以下のようなエラーが出る事がある。
```
/bin/install -c -m 0755 mysql2.so ./.gem.20180707-5833-lu4pnq/mysql2
make: /bin/install: Command not found
```


[Gem install mysql2 \-v '0\.4\.10' make "DESTDIR=" install make: /bin/install :Command not found \- Redmine \- Bitnami Community](https://community.bitnami.com/t/gem-install-mysql2-v-0-4-10-make-destdir-install-make-bin-install-command-not-found/54811)


#### 解決策

/opt/bitnami/ruby/lib/ruby/2.3.0/x86_64-linux/rbconfig.rb 
を編集する。

CONFIR[‘INSTALL’] = ‘/bin/install -C ‘
を以下に
CONFIG[‘INSTALL’] = ‘/usr/bin/install -C ‘


### 今回インストールしたもの 2018/7/7
```
sudo gem install mysql2 -v '0.4.10'
sudo gem install rmagick -v '2.16.0'
```




## 再起動

```
sudo /opt/bitnami/ctlscript.sh restart
```


## エラーが出る場合

Usabilityでundefined method `rmp_render_previous' とエラーが出る場合の対処　

[Usability \- Plugins \- Redmine](https://www.redmine.org/plugins/usability)

```
sudo git clone https://bitbucket.org/dkuk/a_common_libs.git
```

オーナーを変更して、
sudo chown -R bitnami *
sudo chgrp -R daemon *

sudo bundle installを一通りやって、
再起動で動作した。
自社 Web サイトのテストケース作成時に悩むこと小メモ


毎回悩むところのメモです。
皆さん、どんな感じでされているのでしょう？

## ステージングと本番で同じテストをすべき？

もちろんテストが自動化されていて、ステージングでも本番でも同じテストができる、というのが理想なのですが、そういった仕組みが整っていない場合、私は基本、本番はスモークテスト程度にしています。
最低限コレだけは死守したいというレベル、例えば EC サイトだったら注文できる、といったレベル感です。
もちろん本番でも綿密にテストするに越したことは無いのですが、それだったらステージングのテストの意味が無いような気がします。
ただし、ステージングと本番で環境が違うことも結構あるので、その部分は目を凝らしてしっかりテストを行っています。

### 環境が違うことで起きるあるある (PHP 編)

- 本番は IP アドレスが違うので通信先にブロックされた:cry:
    + リリース前に疎通確認は基本ですね
- 本番で必要なモジュール (sftp 関数など) が入っていなくてエラー:cry:
    + ステージングに誰かがこっそり入れていて、それが本番にも入っているものだと思って開発・・
- 本番で curl がコケる:cry:
    + 古いサーバーで古い PHP を動かした時によく発生
- 本番でパーミッションの設定がされていなくてエラー:cry:
    + バッチファイルの実行権限とかログフォルダの書き込み権限とか

## どのブラウザでテストする？ (MVC の V を変更した場合)

当たり前かと思いますが、まずはその Web サイトの対応ブラウザを決めて、部やチームで共有するのが大切ですね。
それに基づいて機械的にチェックするのがポイントで、テスト中にこのブラウザでも見たほうが良いかな？とかそういう邪念が沸き起こってテストに集中できなくなるのを防止します(笑

参考までに、私は大体以下で行っています。

### SP (実機で)

- iPhone Safari
- Android Chrome

### PC

- Windows Chrome
- Windows FireFox
- Windows IE
- Mac Chrome
- Mac Safari

本来ならば上記に OS やブラウザのバージョンを明記すべきだと思うのですが、所々の都合で (そこまでテストに時間をかけられない、手元に端末がないなど) 上記の最新版という形でやっています。
タブレットやアプリ内ブラウザ (Line とか facebook とか)も確認した方が良いなあと思っていますが、やっていないことが多いです。。

## どこまでテストを自動化する？

再利用性が高いテストは Jenkins + Selenium や puppeteer 等で自動化しています。
内容的にはスモークテストやレグレッションテストが多いと思います。

また、手でやるとミスしそうなテストも自動化しています。
例えば EC サイトだと小計と送料と手数料を足した金額からクーポンの割引額を引いて合計がちゃんと合っているか計算する、などの場合です。

逆に 1 年に 1 - 2 回程度の頻度が低いテストは、あまり自動化するメリットが無いかもしれません。

感覚的で古い考えかもしれませんが、手でテストして気づくことも多いです。
特に一人で要件定義からリリースまで行っている場合は、開発時に気づかなかったけど、ステージングのテスト時に手でやって気づくことも多いです。。

その Web サイトにとって死守すべき機能を明確にし、まずはそこを自動化していくと、自ずと利用回数が多く、メリットが多いのでは無いかなと感じます。また、付随する事務的な部分 (例えば EC サイトの自動注文テストの場合だったら、注文後のキャンセルなど) を自動化できれば恩恵が高いように思います。

## 手作業のテストケース、どこまで作り込む？

基本的には他の人が見てもわかるようにテストケースを作成します。

明らかに再利用性が無さそうな場合でもテストケースを残す以上は、1 年後とかにそれを他の人が発見してくれて、コレどういう意味？と聞かれて自分も覚えていないパターンが多いので(笑)、意味がわかるようにしといた方がいいと思います。

当たり前ですが最低限、手順と期待値と出力結果は書いています。

成果物は取引先や上司がエクセル好きであればエクセルで作りますが、そうでなければ Google スプレッドシートで十分な気がします。

見栄えにこだわり出すと作り込みたくなるので(笑)、自社内のテストケースであれば、余計な装飾をせずなるべくシンプルにするようにしています。
Perlのcaller()の返り値が覚えられないあなたへ

先ほどCPANモジュールをリリースしました。ええ、またとてもニッチです。

Caller::Easy（仮）というモジュールで、（主に私のような）組み込み関数である`caller()`の返り値を覚えられない人が対象です。

[CPAN](http://search.cpan.org/~worthmine/Caller-Easy/lib/Caller/Easy.pm)と[github](https://github.com/worthmine/Caller-Easy)へのリンクを貼っておきます。

#要約

`caller`のリストコンテキストの返り値が何番目が何かしょっちゅうわからなくなるのでその度リファレンスをみています。

これをコピペして使う部分だけ使えばいいのかもしれませんが、

```
( $package, $filename, $line,
    $subroutine, $hasargs, $wantarray, $evaltext, $is_require,
    $hints, $bitmask, $hinthash
) = caller(1);
```

11個ある返り値のうち使いたい部分だけ切り取ろうとすると、

```
my $subroutine =( caller(1) )[3];
```

だとか、可読性の低いコードを書かざるを得ないわけです。
で、保守しようとするとリファレンス見て「あ、これサブルーチンであってるわ」とかになりがち。

そこで、本モジュールはその問題を解決し、下記のような書き方を可能にします。

```
my $package = caller(1)->package();
my $subroutine = caller(1)->subroutine();
```

#メリット

上記がほぼ全てなんですが、一応実装時に気をつけたこととして、互換性ですかね？
需要があるかどうかはさておき、OOPで通したい（コンストラクタがないと気持ち悪い）人には

```
my $c = Caller::Easy->new(1);
my $package = $c->package();
my $subroutine = $c->subroutine();
```

という感じのインターフェースを提供します。

[gfxさんが共有されていたイレギュラーな使い方](http://d.hatena.ne.jp/gfx/20130930/1380518261)にも対応しまして、特に工夫することなく

```
my $args = caller(1)->args();
```

などとして、呼び出し元のサブルーチンの引数を取得できたりします。

#デメリット

特にベンチマークとかは撮ってませんが、手っ取り早く書くためにMooseを使ってしまったので重いかもしれません。
でも大丈夫。Mooseを使わずに[同様のことができるモジュールが2007年にリリースされてます。](http://search.cpan.org/~ovid/Perl6-Caller/)
違いは`@DB::args`に触れてない点くらいじゃないですかね？

え？なんで車輪の再発明しちゃったの？って？

調べるよりも書くほうが早かったからです。

githubレポジトリがないし、久しくメンテされていないようなので、新しく作っても差し支えないと判断しました。

#名前募集中
構想段階でつけた仮称のまま、良い名前が思いつかなくてそのままリリースしちゃいました。
【HTML】dialogでモーダルを作ってみる

## はじめに
HTML5.2でいろいろ機能が変更されたHTMLの`dialog `タグ
いろんな使い方があると思いますが、モーダルを作っている人がいたので、真似して作ってみました(みたかった)

[DEMO](https://sengokukun.github.io/share_dir/dialog.html)

## そもそもdialogって？
> dialog要素は閲覧者が操作可能なダイアログを表す。

`open`属性を指定すれば、dialogが初期状態で表示される。
操作はJavaScriptで行う。

※ブラウザによっては、正しく表示されないかもしれません。


```
<dialog open>
	hogehoge
</dialog>
```

<p data-height="500" data-theme-id="0" data-slug-hash="NYRPrB" data-default-tab="html,result" data-user="sengoku" data-embed-version="2" data-pen-title="dialog_sample" class="codepen">See the Pen <a href="https://codepen.io/sengoku/pen/NYRPrB/">dialog_sample</a> by kizuku sengoku (<a href="https://codepen.io/sengoku">@sengoku</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## 今回やってみたもの

<p data-height="500" data-theme-id="0" data-slug-hash="aYmzzb" data-default-tab="css,result" data-user="sengoku" data-embed-version="2" data-pen-title="dialog_modal" class="codepen">See the Pen <a href="https://codepen.io/sengoku/pen/aYmzzb/">dialog_modal</a> by kizuku sengoku (<a href="https://codepen.io/sengoku">@sengoku</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### HTML
`<dialog>`の中に書いていきます。特に指定するものはないと思います。

### CSS
`::backdrop` を指定することによって、dialogを表示した「背景」のスタイルを指定する擬似クラス

### js
- `dialog.showModal()` や`dialog.close()`など、dialog要素を表示するメソッドが存在する

- `dialog.returnValue`
`dialog.close()`の引数に値を渡すと、`returnValue`にセットされる
その他formとの連携も簡単にできそう。

## まとめ
正しい使い方なのかはわからないですが、モーダルを簡単に実装できそうでビビりました。HTML5.2で新機能が追加されたdialog
今後の実装方法など、注目していきたいと思います。

## 参考
[HTML 5.2の新機能・削除された機能、変更された記述ルールのまとめ](https://coliss.com/articles/build-websites/operation/work/whats-new-in-html-5-2.html)

[HTML 5.2で新しく登場した<dialog>要素で、ダイアログ ボックスを実装する方法と注意点](https://coliss.com/articles/build-websites/operation/work/how-to-use-dialog-element.html)
Google Colaboratoryを使ってみる(1日目)

# 最初に

流行りの機械学習に手を出してみたかったので、ブラウザからPythonが利用可能かつGPUも使えるGoogle Colaboratoryが気になった。

以前、ローカルにJupyter Note環境を作ったこともあるけど、ブラウザでアクセス可能 & Googleドライブにノートや結果を保存出来るのでこっちの方が便利そう。

# 試したこと

## 初期設定

- https://colab.research.google.com にアクセスして適当なノートブックを新規作成
- デフォルトだとGPUがOFFなので下記で変更
    - 「編集」 -> 「ノートブックの設定」　 -> 「ハードウェア アクセラレータ」で"GPU"を選択

## kerasのインストール

- TensorFlowはデフォルトで使えるようなので、kerasをインストールする。
- 下記を"コード"ブロックとして追加して実行する。

```python
!pip install -q keras
import keras
```

## MNISTのロード

- 機械学習界隈での"Hello, World!"であろう手書き文字画像データセットのMNISTを使えるようにする。

```python
from keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
```

## データの内容を画像として表示

- なんとなく気になるので画像として表示してみる。

```python
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8, 8))
fig.subplots_adjust(left=0, right=1, bottom=0, top=0.5, hspace=0.05, wspace=0.05)
for i in range(100):
    image = fig.add_subplot(10, 10, i + 1, xticks=[], yticks=[])
    image.imshow(x_train[i].reshape((28, 28)), cmap='gray')
```

## 学習させてみる

- 下記のCNN(畳み込みニューラルネットワーク)のサンプルコードをコピペして結果取得用に一部だけ変更して実行させてみる
    - https://raw.githubusercontent.com/fchollet/keras/master/examples/mnist_cnn.py 
変更箇所

```python
変更前 : model.fit(x_train, y_train,
変更後 : history = model.fit(x_train, y_train,
```

## 結果をプロット

- 学習結果をグラフ表示してみる。

```python
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
```
PowerShellコマンド集

#PowerShellのコマンド色々
たまに使うけど、いつもコマンドを調べるのは時間がもったいないので残しておく。
覚えておくと便利そうなコマンドがあれば追記していく。

###フォルダ内をgrepする
```powershell:コマンド
sls "検索ワード" (dir -recurse .\Form\*.aspx)

#大文字小文字区別する
sls "検索ワード" -CaseSensitive (dir -recurse .\Form\*.aspx)
```

###フォルダ内をgrepして、ファイルにリダイレクトする
ただファイルをリダイレクト先に指定するだけだと、「勝手に改行」が入ってしまう。
参考URL：
https://qiita.com/gimKondo/items/20e1a5a1b2898c5c5fbd

```powershell:コマンド
sls "検索ワード" (dir -recurse .\*.aspx) | % { $_.ToString() } > リダイレクト先ファイル
```
###特定の拡張子を除外してgrep
```powershell:コマンド
sls "検索ワード" (dir -recurse *.* -Exclude *.dll, *.xml, *.pdb) | % { $_.ToString() }
```

###特定の拡張子を指定してgrep
```powershell:コマンド
sls "検索ワード" (dir -recurse *.cs, *.aspx, *.ascx ) | % { $_.ToString() }
```

###ファイルのタイムスタンプ変える
※あんまり使うことはないけどね...

```powershell:コマンド
Set-ItemProperty "ファイル名" -Name LastWriteTime -Value "2018/02/07 10:00"
```

###ディレクトリ内のファイル一覧を取得
```powershell:
Get-ChildItem * -Recurse
```

```powershell
Get-ChildItem *.aspx, *.ascx  -Recurse | select-object fullname
```

###コンソールのエラー表示制御
```powershell:表示しない
$ErrorActionPreference = "silentlycontinue"
```
```powershell:表示する
$ErrorActionPreference = "continue"
```



#参考サイト
[grepコマンドとPowerShellのsls (Select-String)の比較](http://tech.sanwasystem.com/entry/2016/07/05/185717 "grepコマンドとPowerShellのsls (Select-String)の比較")
[【備忘録】PowerShell　指定したフォルダ以下の全てのファイルの絶対パスを取得する](https://qiita.com/gyokufoo/items/56ea98116f9e559126f0)

[PowerShellコンソールエラーを非表示にする方法](https://qiita.com/a-hiroyuki/items/8acb873de60f8e4976db)
【雑記】XON LOG-1 Angular Rate Z　不具合調査

XON LOG-1と言う6軸センサ(3軸加速度+3軸回転角)で遊び始めました。
取り付け対象の運動を記録して色々と解析などしてみようかと。
当面は動画に合成して表示させるのが目的です。

で、どうもAngular Rate Z[dps]の値がおかしい。

メーカーサポートに連絡したら故障かもしれないから送り返せと。
代品を送るから、と。

承諾して代品を受け取り、動作確認。
やはりAngular Rate Zの値がおかしい。

なんかやたら小さい。

・・・！！！
Accelerration(X)[g]の値の‐1倍と等しい！！

こりゃなんか変換ミスじゃねーの？

と疑い、USBキャプチャしました。

キャプチャはWireshark ⁺ USBPcap 
いつの間にかWiresharkに同梱でインストールされるようになったんですね。
(そういえば本格的に使ってたのはもう10年近く前だった・・・)


```
//USB通信キャプチャ　データ部
0000   01 15 80 01 40 3d 64 01 32 3d 08 c1 83 bf 39 41  ....@=d.2=....9A
0010   9c bf f4 01 7a bf 8c 3f 46 41 33 33 b5 41 7a 09  ....z..?FA33.Az.
0020   7f 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00  .D..............
0030   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
```

適当な値を適当に変換してみます。

有意な値っぽい数値を2byteや4byteビッグエンディアン、リトルエンディアンでやってみた結果以下のような推測が一番自然と思われます


```
//データ分解
01 15 ？
//以下リトルエンディアンで浮動小数点変換してみた結果
80 01 40 3d = 0x3d400180 = Decimal: 0.04687643051147461
64 01 32 3d = 0x3d320164 = Decimal: 0.04345835745334625
08 c1 83 bf = 0xbf83c108 = Decimal: -1.0293283462524414
39 41 9c bf = 0xbf9c4139 = Decimal: -1.2207404375076294
f4 01 7a bf = 0xbf7a01f4 = Decimal: -0.9765923023223877
8c 3f 46 41 = 0x41463f8c = Decimal: 12.390514373779297
33 33 b5 41 = 0x41b53333 = Decimal: 22.649999618530273
7a 09 7f 44 = 0x447f097a = Decimal: 1020.1480712890625

```

以下該当行と思われるデータ。

```
//該当行と思われるデータ
line : 228
time : 0:00:18.24
Acceleration(X)[g] : 0.04345836
Acceleration(Y)[g] : 0.04687643
Acceleration(Z)[g] : 1.029328
AngularRate(X)[dps] : -0.9765923
AngularRate(Y)[dps] : 1.22074
AngularRate(Z)[dps] : -0.04345836
Temperature[degree] : 22.65
Pressure[hPa] : 1020.148
MagnetCount   : 0
MagnetSwitch  : 0
```


おお、だいぶそれっぽい。
すると12.390514373779297の部分がAngular Rate Zではなかろうかと思うわけです。

~~メーカーサポートに連絡したのでUtilityソフトのアップデートを期待して待ちます。~~
->バージョンアップで修正が入りました。


さすがにその他のプロトコルまで解析するのは面倒なので・・・。
gitのユーザ登録忘れたらおいで

git 登録などでググっても
ご丁寧にgithubを画像付きで教えてるうっとうしいのばかり出てきます。
なのでメモ

## git ユーザ登録
```
$ git config --global user.name "Sample takeshi"
$ git config --global user.email sample@example.com
```

## おまけ
あとコミットは、addをオプションの-aでやると作業が減るのでお勧めです。

```
$ git commit -am 'test commit'
```
数列として得るフィボナッチ数

# 記事について

関数型記述なんやらの記事を見て触発されてfizzbuzzなんかを考えたりした流れで、昔フィボナッチ数列のコードで同僚と盛り上がってたなーと思ってフィボナッチ数列のコードについて再考してみたのの記録。
(本稿自体は関数型云々に言及する内容ではないです)

# 普通に実装

$n$ 番目のフィボナッチ数を得る再帰関数。($n = 10$ の例)

```python
fibonacci = lambda n: n if n<2 else fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(10))
```

同僚は**数列**として結果を得たかったようなので、数列を得るなら `print(list(map(fibonacci, range(1, 11))))` のように引数列のrangeオブジェクトをmapでfibonacciに食わせたり、forでループ回したりすることになる。

しかし、数列の上位からトップダウンで計算していくこの実装の場合、下位のフィボナッチ数を何度も計算するため計算リソースがなんかもったいない気がする。
実際、$n=40$ くらいになると実行完了がだいぶ遅くなる。

当時はググって得た結論がメモ化再帰かなーとか思ってたものの、グローバル配列を用意しておかなければならないのは関数機能としての独立性とかのことを考えると抵抗感もあった。(FPの参照透明性ってこういうことだろうか)

# ボトムアップ式

トップダウンが駄目ならボトムアップにすればいいじゃないということで、今回はすんなり別解が浮かんだ。
(大したパラダイムシフトでもないので、当時も発想自体はあったと思うのだけど、多分引数と返却値の取り回しを上手く再帰構造に組み込めなかったのだと思う)

```python
fibonacci = lambda n, v=[0,1]: fibonacci(n-1, v+[v[-1]+v[-2]]) if n > 1 else v[1:]
print(fibonacci(10))
```

この場合、生の返却値がListオブジェクトで表現される**数列**なので、**フィボナッチ数**が欲しければ `print(fibonacci(10)[-1])` とする。

Reducerとして書いた方がスッキリするかも？って思ったけど、イテレートアイテムと返却値の型の不一致がそもそもなためあまり変わらなかった。

```python
fibonacci = lambda v, n: v+[v[-1]+v[-2]] if len(v) > 1 else v+[1]
print(reduce(fibonacci, range(1,11), []))
```

# 公式による導出

計算量について調べているとフィボナッチ数の公式があるらしく、以下の $F_n$ について解けば $n$ 番目のフィボナッチ数が得られるとのこと。

$$
F_n = \frac{1}{\sqrt{5}}\biggl(\;
\Bigl(\frac{1+\sqrt{5}}{2}\Bigr)^n - \Bigl(\frac{1-\sqrt{5}}{2}\Bigr)^n
\biggr)
$$

実装すると以下。($n$乗根 = $n$の逆数の累乗)

```python
fibonacci = lambda n: int((((1+5**0.5)/2)**n - ((1-5**0.5)/2)**n)/(5**0.5))
print(fibonacci(10))
```

これなら時間計算量 $O(1)$ になるということらしい。[^1]
最初と同じく、数列の解が欲しいならrangeオブジェクトをmapでfibonacciに食わせる。

でも、$n=72$ あたりから誤差が…

```shell-session
$ ./fibonacci-bottomup.py 72   # ボトムアップ式実装
498454011879264
$ ./fibonacci-fomula.py 72     # 公式実装
498454011879265
```

そもそもこの公式、数学的には整数解が得られるらしく、キャストしなきゃいけない時点で実装間違ってるのか。

# 時間計算量について

フィボナッチ数列の時間計算量について自力で求めるのが数学力の無い自分には出来なかったので簡単にググった感じ、数列として言及された記事は見当たらなかったが、$n$ 番目のフィボナッチ数を導出する時間計算量は、

$$
O_n\Biggl(\quad
\Bigl(\frac{1+\sqrt{5}}{2}\Bigr)^{n-1}
\Biggr)
$$

ということらしいので[^2]、数列版の時間計算量は以下ということ？

$$
O_n\Biggl(\quad
\sum_{i=1}^{n}{\Bigl(\frac{1+\sqrt{5}}{2}\Bigr)^{i-1}}
\;\Biggr)
$$

実数でみたいなーと思ったので、$n$ をコマンドライン引数で受け取って $O_n$ を得るスクリプトを作成。

```python:fibonacci-sequence-order.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys

n = int(sys.argv[1])

order = lambda x: ((1+5**0.5)/2)**(x-1)
print(round(sum(list(map(order, range(1,n+1)))),3))
```

$1 \leqq n \leqq 10$ までの各々の $O_n$ を導出。

```shell-session
$ seq 1 10 | xargs -L 1 ./fibonacci-sequence-order.py
1.0
2.618
5.236
9.472
16.326
27.416
45.361
74.395
121.374
197.387
```

# 参考

:link: http://www.aoni.waseda.jp/ichiji/2012/java-01/java-14-3.html
:link: http://d.hatena.ne.jp/shunsuk/20090220/1235135606

[^1]: 過去これに対して疑問視されたようで、$O(n)$ 説もあったが $O(1)$ で決着したっぽい…？ (参考リンク下段)

[^2]: 簡易的?には $O(2^n)$ ということらしい
スレッドセーフまとめ　〜Java〜

ユーザー系のSIerです。
先日、保守をしているシステムにおいて、ユーザー間で個人情報が共有されている疑惑があり、スレッドセーフかどうか調査した時に参照したサイトをまとめました。
※他の方がすでにスレッドセーフについてまとめていたので、キュレーションのような形にしました

# スレッドセーフとは？
複数のスレッドが同時並行に処理を実行しても問題が発生しないこと。
例えば、AさんとBさんが同時に処理を実行した際に、共有データに両者がアクセスできてしまうと問題が発生してしまうため、どちらか一方のみがアクセスできるように制御する必要があります。

# 参照
・JavaのThreadLocalとスレッドセーフについて
https://qiita.com/yoshi-naoyuki/items/507c5c3ea6027033f4bb
・スレッドセーフにすることを忘れてはいけない
http://tech.nikkeibp.co.jp/it/article/COLUMN/20070820/279950/
【Linux】catコマンドとリダイレクトを使いこなして作業効率アップ！

大量のデータを加工・編集しなければいけないときに、Excelやテキストエディタを使用することがあるかもしれません。  
以下のLinuxコマンドを覚えておくと、作業効率がアップするかもしれません。  
catコマンドで標準出力→出力内容を加工する　という技を覚えると、
欲しいデータ形式が簡単に整えられます。  

# cat
**処理概要**
ファイルの内容を表示する。

## コマンド例
```
$ cat test.txt
aaaa
bbbb
cccc

```

## 用途
- とりあえずファイルの中身を見たい時
- ファイルの内容をリダイレクトして加工したい時
  
# リダイレクト
## 処理概要
標準出力を別ファイルに出力する。

## コマンド例(catとの組み合わせ)
```
$ cat test.txt > new.txt  
```

## 用途
- 出力結果を抽出・加工して別ファイルを作成したい時


# grep
##  処理概要
文字列を検索する。

## コマンド例(catとの組み合わせ)
```
# 対象ファイル
test.txt
aaaa
bbbb
cccc

$ cat test.txt | grep a
aaaa

```

## 用途
- 元ファイルのデータを絞り込みたい時


# cut
##  処理概要
ファイルから一部分を抜き出す。

## コマンド例
```
# 対象ファイル
test.csv
aaa,bbb,ccc
ddd,eee,fff
ggg,hhh,iii

# csvの2カラム目を取得する
$ cat test.csv | cut -d ',' -f 2
bbb
eee
hhh
```
### オプション
- -d ：区切り文字を設定する
- -f ：n番目のカラムを取得する

## 用途
- csvなど規則的なデータの一部分を抜粋したい時
- 日時（YYYY/MM/DD HH:MM:SS）のYYYY/MM/DD HHだけ抽出するなど
サマリデータを作るための元ネタを用意したい時

# paste
##  処理概要
ファイルを連結する。

## コマンド例
```
#ファイルをカンマ区切りで結合させる
paste -d, 1.csv 2.csv 3.csv 4.csv > join.csv
```
### オプション
- -d ：区切り文字を設定する

## 用途
- csvファイルを再形成したい時
jsのクラス要素解析

# はじめに
jsのclassに関して以下の情報を得たい
- getterの有無とその関数
- setterの有無とその関数
- methodの関数
- static methohd の関数
- class の宣言時の名前
- constructor の引数名

主に以下の関数を用いることで解析できます.
- `Reflect.getOwnPropertyDescriptor`
- `Reflect.ownKeys`
- ~~`Function.toString()`~~

# コード
クラス雛形用意

```js
class Piyo {
  constructor(argA, argB) {
    console.log('@constructor :: ', Reflect.ownKeys(this));
    this.memberA = argA;
  }
  get getA() {
    console.log('@getA :: ', Reflect.ownKeys(this));
  }
  set setA(value) {
    console.log('@setA :: ', Reflect.ownKeys(this));
  }
  static staticA() {
    console.log('@staticA :: ', Reflect.ownKeys(this));
  }
  methodA() {
    console.log('@methodA :: ', Reflect.ownKeys(this));
  }
}
```


```js
function listupTest(Hoge) {
  let hoge = new Hoge('ARG_A', 'ARG_B');
  // members: [ 'memberA' ]
  console.log('members:', Reflect.ownKeys(hoge));
  // methods: [ 'constructor', 'getA', 'setA', 'methodA' ]
  console.log('methods:', Reflect.ownKeys(Hoge.prototype));
  // statics: [ 'length', 'prototype', 'staticA', 'name' ]
  console.log('statics:', Reflect.ownKeys(Hoge));
  // name is: Piyo
  console.log('name is:', Hoge.name);
  let reflectHoge = k => Reflect.getOwnPropertyDescriptor(Hoge.prototype, k);
  let res = {};
  res.memberA = hoge.memberA;
  res.methodA = reflectHoge('methodA').value;
  res.getA = reflectHoge('getA').get;
  res.setA = reflectHoge('setA').set;
  res.staticA = Hoge.staticA;
  res.props = getParams(Hoge, true);
  // @methodA ::  [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
  res.methodA();
  // @getA ::  [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
  res.getA();
  // @setA ::  [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
  res.setA();
  // @staticA ::  [ 'memberA', 'methodA', 'getA', 'setA', 'staticA', 'props' ]
  res.staticA();
  // [ 'argA', 'argB' ]
  console.log(res.props);
}
listupTest(Piyo);
```

# 参考
`getParams` は以下を参考にしました.(constructor系functionに未対応だったのでそこの処理は追加しました)
https://qiita.com/chick307/items/1902fb32d252310d516d

```js
function getParams(func, isConstructor = false) {
  // コメントと空白を取り除いて正規化
  let source = func.toString().replace(/\/\/.*$|\/\*[\s\S]*?\*\/|\s/gm, '');
  if (!isConstructor) {
    // 最初の丸かっこのもの
    let params = source.match(/\((.*?)\)/)[1].split(',');
    if (params.length === 1 && params[0] === '') return [];
    return params;
  }
  let firstName = source.replace(/^.*?\{/, "").replace(/\(.*$/, "");
  // constructor 系
  if (firstName === "constructor") return getParams(func, false);
  // babel系
  if (firstName === "_classCallCheck") return getParams(func, false);
  console.assert(false, "declare consturctor first!!");
}
```
JIS配列のMacで、バックスラッシュをさくっと入力する方法(JetBrainsのIDE対応)

# 2018/05/03 追記

当初書いていたやり方は既存のルールを追加してから設定ファイルを書き換えるというものだったんですが、 @tanakahisateru さんが専用のルールを本家に pull-req にしてくださいました！

- https://github.com/pqrs-org/KE-complex_modifications/pull/351
- https://twitter.com/tanakahisateru/status/991700342352969728

ということで、以下の手順はその取り込まれた専用ルールを使ったものに書き換えてます。

# 目的

JIS配列のMacで、バックスラッシュを入力するには、`option + ¥` という入力が必要となるのだが、円マークとバックスラッシュだとどちらが使うかというと、バックスラッシュの方なので、これを入れ替えたい。(PHPer としては、\ の入力がめんどくさいといろいろつらい)

単純にこれだけであれば、ことえりやGoogle日本語入力で変更可能なのだが、JetBrains製のIDE(IntelliJやPhpStorm)では、IMEの設定が反映されない。

その為、なんらかの設定を行う必要があるが、[Karabiner](https://pqrs.org/osx/karabiner/) が長らく Sierra 以降に対応してない期間があって困っていたのだが、気がついたらできるようになっていたので、やり方をまとめておく。

# 設定手順

設定手順は以下の通り。

1. 最新の Karabiner-Elements をダウンロード/インストール
2. Karabiner-Elements を起動し、キーボード設定ウィザードで JIS を選択
3. Karabiner-Elements の Preferences の Complex Modifications タブを開き、準備された設定を Add rule し、Add rule したものを Enable にする

## 最新の Karabiner-Elements をダウンロード/インストール

以下のURLから Karabiner-Elements をダウンロードし、インストールする

- https://pqrs.org/osx/karabiner/

## Karabiner-Elements を起動し、キーボード設定ウィザードで JIS を選択

以前は Virtual Keyboard のタブを開き、 ANSI/ISO/JIS の3タイプから JIS を選択していましたが、Karabiner-Elements がバージョンアップして、キーボード設定ウィザードから設定するようになりました

## Karabiner-Elements の Preferences の Complex Modifications タブを開き、準備された設定を Add rule する

Complex Modifications のタブを開き、 画面下の "Add rule" をおすとダイアログが表示されるので、 ダイアログ上部の "Import more rules from internet (open a web browser)" ボタンを押す。

そうすると、予め準備されたルール一覧のページがブラウザで表示されるので、"Swap ¥ and \ always on JIS Keyboards" というルールを探して、そのルールの "Import" ボタンを押す

<img width="1195" alt="karabiner_web.png" src="https://qiita-image-store.s3.amazonaws.com/0/111934/35425db1-cb1b-3614-3b92-01179fae5235.png">

Karabiner-Elements.app を開くかどうかのポップアップが表示されるので、 "Karabiner-Elements.app を開く" ボタンを押す。

ボタンを押すと、Karabiner-Elements 側で import するか聞かれるので、"Import" ボタンを押す。

Importを行うと、もともと例として表示されている3つのルールの下に、 "Swap ¥ and \ always on JIS Keyboards" ルールの2つのサブルールが表示されるので、 "Enable All" ボタンを押して、2つともEnableにする。

<img width="1112" alt="スクリーンショット 2018-05-03 7.58.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/111934/f0464258-6b8a-0256-087f-29295d448e29.png">

# まとめ

Karabiner-Elements が使えなかった期間は、以下の記事を参考に Hammerspoon を使っていたが、おそらく Karabiner-Elements のほうが軽いと思うので、こちらを使っていこうと思う。

- [IntelliJとかJVMのIDE使いでもKarabinerなしでバックスラッシュを片手入力したい](https://qiita.com/tanakahisateru/items/d8a67ad89c07baf8c0da)
docker-composeを使ってAnsibleの実行環境を作る

こんにちは。

Ansibleをチームで利用していると

- 昔に作ったPlaybookがAnsibleのバージョンアップにより動かない
- 複数メンバーでの環境の統一が難しい

などの問題にぶつかった事がありませんか？
そこで、DockerとDocker-Composeを使って、Ansibleの実行環境の配布を考えてみました。

## 構成
```
├ docker-compose.yml
└ ansible-images
 　　　└ Dockerfile
```

###`./ansible-images/Dockerfile`
```
FROM amazonlinux

RUN yum install python27-pip.noarch python27-PyYAML openssh-clients -y && \
    pip install --upgrade pip && \
    pip install ansible==2.5.0 && \
    yum clean all && \
    mkdir /playbooks

WORKDIR /playbooks

ENTRYPOINT ["/usr/local/bin/ansible-playbook"]
CMD ["--version]
```
#### 解説
- `pip install ansible==2.5.0`PIPのオプションを利用し、Ansibleのバージョンを指定しています。
- `RUN`Ansibleに必要パッケージ一式をインストールしています。
- 作成された`/playbooks`をカレントディレクトリとするため`WORKDIR`で`/playbooks`を指定します。
  - `WORKDIR` は、`RUN` `CMD` `ENTRYPOINT` `COPY` `ADD`を実行する際のワーキングディレクトリを指定します。
  - `/playbooks`はdocker-composeにて、ホストのディレクトリのマウント用です。
- `ENTRYPOINT`はAnsibleへのパスを指定しています。
- `CMD`は`docker run`の実行時に引数がない際に実行されるコマンドオプションです。コマンドに引数を指定すれば、上書きされます。

### `./docker-compose.yml`
```
version: '2'
services:
 ansible:
    build: ./ansible-images
    image: ansible-images:latest
    volumes:
      - /PATH/TO/YOUR/ANSIBLE-PLAYBOOK:/playbooks
    command:
      "--check -i ./hosts/inventory.yml ./setup.yml"
```
#### 解説
- `volumes:` インスタンスににホスト上のPlaybookを読み込ませるためマウントをしています。
- `command:` `Dockerfile`で指定した`CMD`を上書きします。

## 実行
カレントディレクトリにて
`docker-compose up`　を実行すると、Ansibleが実行されます。
Numpyの様々な乱数生成方法[正規分布、配列内から、二項分布に従って]

この記事では様々な種類の乱数の生成方法を学びます.
また、ここでは、MatplotlibとNumpyを使用しますのでこれらをインストールしていない方は、
[こちらの記事を参考にしてください](https://qiita.com/techiromen0/items/be0ab096f1c4889d58f5)←Anacondaからのインストールです.
#今回説明する関数３つ
>
1. numpy.random.randn()
**正規分布**に従った乱数の生成
>
2. numpy.random.choice()
 **リスト型のデータの中からランダム**に選んだ結果を渡した整数値の数だけ返します.
>
3. numpy.random.binomial()
**二項分布**に従う乱数
>

##本題に入る前に~numpy.random.seed()について~
>乱数を生成する前に**`numpy.random.seed()`**を用いてシード値を固定することが出来ます.
シード を固定することでつねに `同じ乱数列` を生成することができます.同じ乱数列を使用することによって、同じ条件であれば乱数を用いていても同様の計算結果を再現できるようになります.

##1. 正規分布に従った乱数の生成
`numpy.random.randn()`に整数を渡すと、 正規分布 に従う乱数を渡した値の数だけ返します.

```python:example.py
import numpy as np #npをnumpyとして使用
import matplotlib.pyplot as plt #グラフ描写のために.pyplotをインポート

np.random.seed(0)#予めseed値を設定する

x = np.random.randn(10000)# 正規分布に従う乱数を10000個生成





#可視化
plt.hist(x, bins='auto')#xをヒストグラムにプロットする。ヒストグラムの本数は'auto'
plt.show()#グラフを表示
```
| seed値を０にした時の結果     |
|:-----------------|
|    ![figure1.png](https://qiita-image-store.s3.amazonaws.com/0/240708/133ab038-d65c-4084-b19b-ab2e96ac34e9.png)    |


---


##2. リスト（配列）からランダムに値を抽出
`numpy.random.choice()`にリスト型のデータxと整数値nを渡すと、渡したリスト型のデータの中からランダムに選んだ結果を渡した整数値の数だけ返します.

![gatag-00010569.jpg](https://qiita-image-store.s3.amazonaws.com/0/240708/8546d2ef-73dc-ac95-7323-2c933dcdce5e.jpeg)

```py:sample2.py
import numpy as np

x = ['One', 'Two', 'Three', 'Four', 'Five']
# xの中からランダムに5個選んでyに代入してください
y1 = np.random.choice(x,5)
y2 = np.random.choice(x,5)
print(y1)
print(y2)
```
```py:result
['Five' 'One' 'Two' 'Two' 'Three']
['Four' 'One' 'Five' 'Five' 'Three']
```

seed値を固定していないので異なる結果が出てきます.

---

##3. 二項分布に従う乱数を生成する

`numpy.random.binomial()`はある試行が成功かであるか失敗であるかのいずれかを返します.
例えば、コインを投げた時は必ず表か裏しか出ません.

そして、失敗も成功も確率は0.5です.numpy.random.binomial()に整数nと0以上1以下の実数pを渡すと、渡した整数nの回数だけ成功率pの試行を行い、成功する回数を返します。第3引数に`size=整数値`を渡すと、n回試行したときの成功数を指定した整数値分だけ返します.
![binomial.jpg](https://qiita-image-store.s3.amazonaws.com/0/240708/6e59a51f-e54a-f042-adbd-0c77b80d249a.jpeg)

```py:sample3.py
import numpy as np

np.random.seed(0)# シード値を設定
# 0.5の確率で成功する試行を100回行なったときの成功数を変数nums1に代入
nums1 = np.random.binomial(100,0.5)
# 0.3の確率で成功する試行を100回行なったときの成功数を5回分求めて変数nums2に代入
nums2 = np.random.binomial(100,0.3,size=5)
#nums1,nums2を出力
print(nums1)
print(nums2)

# 成功率の平均を出力
print(nums2.mean()/100)
```
nums2のように第三引数を用いると簡単に成功率の平均を`.mean()`メソッドを用いて計算できます.

```py:result
52
[29 36 38 29 34]
0.332
```
---

ここで今回は終了です.この記事が参考になれば幸いです！
homebrewでhttpdとphp7.2入れたら上手く連携しなかった

# macOS High Sierraって不具合多すぎませんか？

macOS High Sierraになると、色々と開発環境整えるのが難しくなったと感じる昨今です。
さて表題通り、homebrewでhttpdとphp(ver7.2)を入れたら、上手く動きませんでした。

# brewのコマンド

```
brew install httpd
brew install php
```

いくつかの過去記事だと、--with-httpdつけろって書いてあるんだけれど、2018/4/5時点ではこのオプション効かなくなっています。
php72とかでのインストールも出来ないし、よー分からん（分からんまま使うな）



# phpインストール後のhomebrewのメッセージ

```
LoadModule php7_module /usr/local/opt/php/lib/httpd/modules/libphp7.so
```

/usr/local/etc/httpd/httpd.confに上記を追加して、apachectrl startしても、上手く動きませんでした。


# 修正

```
LoadModule php7_module /usr/local/opt/php@7.2/lib/httpd/modules/libphp7.so
```

~~とりあえず、暫定対応として、実態のある所を指したら動きました。~~
phpじゃなくて、php@7.2にしたら、上手く指してくれました。~~何だこれ~~
多分、表記的にはhomebrewの指示通りでも動くと思うのですが、自分の環境では上手く動きませんでした。
もし、homebrewでハマっている人がいたら、何かの参考にしてください。
すごく気持ち悪いNuxt.js用のライブラリnuxtendがもっと気持ち悪くなりました。

[nuxtend](https://github.com/dotneet/nuxtend)という気持ち悪いNuxt.jsのライブラリを作っていますが、先ほどもっと気持ち悪くなったので紹介します。

nuxtendにはもともと下記の機能があります。

 - mixinにasyncData()/fetch()を書いても反映されない問題を解決
 - asyncData()/fetch() でthisを通してmapActions()したアクションを呼べない問題を解決

そして新たに下記のような(気持ち悪い)書き方が可能になりました。
Nuxtに慣れている人ほど気持ち悪く感じると思います。

```js
export default nuxnted({
  nuxtend: {
    actions: ['apple']　 // メソッドを生成するための定義
  },
  async asyncData () {
    // 'apples/get' アクションが存在すれば呼びます。なければ、$axios.get('/apples/10') を呼びます
    const res = await this.getApple(10)

    // 同様に下記のように呼び出しできます
    // action: 'apples/getList'  api: $axios.get('/apples', {params: {status: 'dropped'}})
    this.getAppleList({status: 'dropped'})
    // action: 'apples/create'  api: $axios.post('/apples', {status: 'dropped'})
    await this.postApple({status: 'dropped'})
    // action: 'apples/update'  api: $axios.put('/apples/10', {status: 'dropped'})
    await this.putApple({id: 10, params: {status: 'dropped'}})
    // action: 'apples/delete'  api: $axios.delete('/apples/10')
    await this.deleteApple(10)

    return {
      apple: res.data
    }
  }
})
```

裏では禍々しいことをしていますが、pagesのコードが綺麗な感じに書けます。
PhpStormとHomesteadとXdebugでDebugできるようにする

そろそろソースコード単位で動きを追いたい年頃になって来ました。

# Debugできるようにする
- [PhpStorm から Vagrant VM の PHP アプリケーションをリモートデバッグする（Web & CLI） - Shin x blog](http://www.1x1.jp/blog/2014/08/how-to-setup-php-remote-debug-with-vagrant-vm.html)

最初はこれ見てやろうとしたんですがレポジトリがどうのこうのとか言い出してよくわからなくなりました。
そもそも2014年というあたりで回れ右すべきだった。

いや流石にHomesteadさんはなんかあるやろと検索したらズバリなタイトルが出て来ましたのでこれを参考にしてみます。

- [Homestead + Xdebug + PhpStorm でリモートデバッグ環境をつくる - ラボラジアン](https://laboradian.com/remote-debug-setting-for-homestead-xdebug-phpstorm/)

## PHP7.2にはXdebugがない？
上記資料では7.1だったんですが、Homesteadは7.2を指してるんですよね。
で、7.1のフォルダにはxdebugのiniファイルがあるんですが7.2にはありません。
なんでやねんって調べたらそれっぽいのが出て来ました。

- [Ubuntu 16.04.3 LTS + PHP 7.2 の環境に Xdebug をインストールする - ラボラジアン](https://laboradian.com/install-xdebug-in-ubuntu-php-env/)

php7.2に対応するxdebugはbeta版なので自分で設定する必要があると。
マジですか。

参考にして入れてみます。

```shell
$ sudo pecl install xdebug
# インストールされる

$ sudo vi /etc/php/7.2/mods-available/xdebug.ini
# 先頭に以下を追加
# zend_extension=/usr/lib/php/20170718/xdebug.so

$ cd /etc/php/7.2/fpm/conf.d/
$ sudo ln -s /etc/php/7.2/mods-available/xdebug.ini ./20-xdebug.ini
# シンボリックリンク作成

$ sudo service php7.2-fpm restart
#　再起動
```

あっさりできました。

# 改めて設定
iniファイルに追記して再起動します。

```shell
$ sudo vi /etc/php/7.2/fpm/conf.d/20-xdebug.ini
# 末尾に追記
# xdebug.idekey = "PHPSTORM"

$ sudo service php7.2-fpm restart
# また再起動
```

# 資料はWindowsだった
macだとどうなるんでしょう。

- [【手順】PHPのデバッグで便利なXdebugをMacに入れてみました | Mobile First Marketing Labo](http://www.aiship.jp/knowhow/archives/25695)

とりあえずこれを参考にして入れてみました。

```shell
$ php -v
PHP 7.0.27 (cli) (built: Jan  7 2018 19:44:58) ( ZTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Xdebug v2.6.0, Copyright (c) 2002-2018, by Derick Rethans
```

入ってる……っぽい。

# PhpStormの設定
Homesteadがphp7.2で、僕の環境だとphp7.0か7.1しかPhpStormには表示されてません。
が、とりあえずメジャーバージョンだけ揃ってれば動くようなので適当なバージョンを指定しておきます。

## Interpreters
- `PhpStorm > Preferences...`
- Languages & Frameworksを開いてPHPをクリック
- PHPのバージョンを選ぶ
- Interpreterの脇の『．．．』ボタンをクリック
- Default interpretersが開くので、左ウィンドウの『＋』をクリックして新しいのを追加
- 名前を適当に決める
- PHP executableで、xdebugを設定したphpを選択する
    - 参考までに、うちは`/usr/local/bin/php`でした（多分なんの参考にもならない）
- OK

## Server
- `PhpStorm > Preferences...`
- Languages & Frameworksを開いてPHPを開く
- Serverをクリック
- PHPのバージョンを選ぶ
- 『＋』をクリックして新しいサーバーを追加
- 名前を適当に決める
- HOSTを入力
- 下のチェックボックスをチェック
- プロジェクトファイルに対応する仮想環境のパスを入力
- OK

## Debug Configurations
- `Run > Edit Configurations...`
- 『＋』をクリックして新しいデバッグ設定を追加
- 名前を適当に決める
- Serversを選択
- Ide keyにPHPSTORMを入力
- OK

# 設定完了したので実行
PｈｐStorm側で、窓の上にいる虫アイコンをクリック。
その後、URLに`XDEBUG_SESSION_START=PHPSTORM`のパラメータを付けてHomesteadにアクセス。
一回アクセスしたらphp側でcookie全消しとかセッション切れとかしなければそのままDEBUGできる。

あとはその状態で、PHPファイルの適当なところにブレイクを入れると止まる。
やったー！

F8で同一ファイルの次の処理（Step Over）。
F7で処理内部に遷移する（Step in）。
option+command+RでF5（Visual Studio的表現）。
Force Step intoとかはよくわかりません。

ともあれデバッグできるようになりました。
CGI::Session のバックエンドデータベースに SQLite を使う

2018年になっても、小規模な CGI を書く時には CGI::Session は重宝するのですが、問題はセッションを格納するバックエンドデータベースです。流石に、複数の CGI が同時に動作するケースを考えないわけにはいかないので、SQLite を使おうとしたのですが、[CGI::Session::Driver::sqlite のマニュアル](http://search.cpan.org/~markstos/CGI-Session/lib/CGI/Session/Driver/sqlite.pm)通りに記述しても動作しませんでした…。

散々試行錯誤して、ようやく sessions というテーブルが必要だということが分かりました。そのテーブルを作成する SQL 文も含むコード例を示します。

```pl:session-example.cgi
#!/usr/bin/perl

use CGI;
use CGI::Session qw/ -ip-match /;
use DBI;
use strict;
use warnings;
use utf8;
use open qw/ :utf8 :std /;

my $filename = "データベースファイル名";

my $dbh = DBI->connect( sprintf( 'dbi:SQLite:dbname=%s', $filename ), undef, undef ) or die;
$dbh->do( <<'__create_table__' );
CREATE TABLE if not exists sessions (
    id CHAR(32) NOT NULL UNIQUE,
    a_session TEXT NOT NULL
);
__create_table__

my $cgi = CGI->new();
my $session = CGI::Session->new( 'driver:SQLite', $cgi, { Handle => $dbh } );
$session->param( 'count' => ( $session->param('count') || 0 ) + 1 );
print $cgi->header( -status => 200,
                    -type => 'text/plain',
                    -charset => 'UTF-8',
                    -cookie => $cgi->cookie( -name => $session->name,
                                             -value => $session->id,
                                             -domain => $cgi->server_name,
                                             -path => $cgi->script_name ) );
printf "Current Session ID = %s\n", $session->id;
printf "Current Counter = %d\n", $session->param('count');
```
`git grep -e`で`--not`を使う場合の書き方

# 概要

表題の通り。ググってもあまり情報なかったので書いておく。


# 記法

```bash
git grep --not -e "__IGNORE__"
```


# 実践

「"A"を含み、且つ"B"を含まない」といった条件を与えたい場合、以下のように書く。
要は、`--and`/`--or`/`--not`で、`-e __KEYWORD__`を演算子的に結ぶように書くイメージ。`()`も使えるので、複雑な条件も表現しようと思えばできる。

```bash
git grep -e "A" --and --not -e "B"
```

「"A"を含まない」的な`--not`のみの条件も書ける。大量にヒットするので、これだけで使うかどうかは微妙だけど。

```bash
git grep --not -e "A"
```


# 参考

- [Git grepを便利に使う\-eオプションについて \- Qiita](https://qiita.com/tbaba/items/a67c8d79c6c4d0dc9b73)
【Python3】配列の先頭と最後尾に要素を追加する

<h1>先頭に追加</h1>


```python
array=[2,3]
array.insert(0,1)

#結果
array=[1,2,3]
```

<h1>最後尾に追加</h1>

```python
array=[1,2]
array.append(3)

#結果
array=[1,2,3]
```
<h1>おまけ　任意の位置xに要素yを追加</h1>

```python
array=[1,2,3,...n]
array.insert(x,y)
```
Azure WebAppsのJavaアプリケーションをリモートデバッグ


tl;dr
----------

https://github.com/Azure/azure-websites-java-remote-debugging

ここの作業を行うだけです。



手順
----------

### WebAppsの設定でWebSocketを有効化

AzureポータルからWebAppのアプリケーション設定を開き、「Webソケット」をオンにしておきます。

![2018-04-05-21-05-49.png](https://qiita-image-store.s3.amazonaws.com/0/52527/dead1965-9a5d-ba59-c632-4086ae6543c9.png)

デバッグ時にWebSocketを通してリモートとやり取りを行うため、この設定が必要です。


### App Service上に `site\wwwroot\web.config` を作る。

WebAppの裏で暗躍しているkuduにアクセスして作るのが楽です。

[kudu](https://github.com/projectkudu/kudu)はざっくりいえば、AppServiceを裏で支えるソフトウェアで、デプロイの制御やWebJobsの動作等の面倒を見たり、開発に便利なブラウザから利用できるコンソールも提供しています。


- ブラウザを開き、`https://YOURAPP.scm.azurewebsites.net/DebugConsole` にアクセス
  - （※`YOURAPP`はWebAppリソース作成時の名前になる。公開用URLの間にscmが入っただけと覚えるとよい。）
- `site`→`wwwroot`に移動
- `[+]`アイコンから「New File」で`web.config`ファイルを作成。
  - `%programfiles(x86)%` の箇所は、32bitの場合で、64bitの場合は異なる。(Free等格安プランだと32bit)
  - `apache-tomcat-8.0.46`の箇所は、tomcatのバージョンで変わる。

``` xml:web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <add name="httppPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
        </handlers>
        
        <httpPlatform processPath="%programfiles(x86)%\apache-tomcat-8.0.46\bin\startup.bat">
            <environmentVariables>
                <environmentVariable name="CATALINA_HOME" value="%programfiles(x86)%\apache-tomcat-8.0.46"/>
                <environmentVariable name="JAVA_OPTS" value="-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=127.0.0.1:%HTTP_PLATFORM_DEBUG_PORT%"/>
                <environmentVariable name="CATALINA_OPTS" value="-Dport.http=%HTTP_PLATFORM_PORT%"/>
            </environmentVariables>
        </httpPlatform>
    </system.webServer>
</configuration>
```


### アプリケーションの再起動

ポータル上から再起動を行う。

再起動後、1度アクセスしてJavaプロセスが動いている状態にしておく。kudu上のProcess Explorerで確認可能

WebApp側の作業はここまで。


### DebugSessionクライアントの起動

ここからはローカルマシン上の作業。

https://github.com/Azure/azure-websites-java-remote-debugging/releases からDebugSessionクライアントをダウンロード。

binの中にあるDebugSessin.batに以下の引数を与えて起動。環境変数の`JAVA_HOME`を設定しておく。

※`-s`と`-u`と`-w`の値は適宜置き換えてください。

``` 
DebugSession.bat ^
  --auto ^
  -p 8000 ^
  -s YOURAPP.scm.azurewebsites.net ^
  -u $YOURAPP ^
  -w ****
```

> 情報: Waiting for debugger to connect on 8000 ...

・・・と出ていたら、準備はOK。

なお、接続情報(PublishURL/User/Pass)はAzure CLIなら`az webapp deployment list-publishing-profiles ...`あたりで得られる`MSDeploy`の値を使えばOK


### デバッガを起動

後は、Eclipse上のデバッガ等からDebugSessionクライアント(localhost:8080)に接続することで、リモートデバッグが行えるようになる。

ただ、リモートなので動作がもっさりしている。（freeプランだったからかもしれない。）
Python3で開始日と終了日からその間の日付リスト（あるいは時間リスト）を得る

Python3で二つの日付からその間に含まれる日付リストを作成します。
開始日と日数から作成する場合にも使えます。

例えば
開始日 = 2018-02-24
終了日 = 2018-03-05
という情報から次のようなリストを得る処理です
2018-02-24
2018-02-25
2018-02-26
2018-02-27
2018-02-28
2018-03-01
2018-03-02
2018-03-03
2018-03-04
2018-03-05

## 3つの方法を紹介します

 - シンプルにforとappendを使う場合
 - lambdaを使う場合
 - リスト内包表記を使う場合

## 共通部分

モジュールのインポート、日付条件の設定と日数の算出を行います。

```{Python}
# 使用するモジュールのインポート
from datetime import datetime as dt
from datetime import timedelta

# 日付条件の設定
strdt = dt.strptime("2018-02-24", '%Y-%m-%d')  # 開始日
enddt = dt.strptime("2018-03-5", '%Y-%m-%d')  # 終了日

# 日付差の日数を算出（リストに最終日も含めたいので、＋１しています）
days_num = (enddt - strdt).days + 1  # （参考）括弧の部分はtimedelta型のオブジェクトになります
```

## 方法１、シンプルにforとappendを使う場合

```{Python}
# シンプルにforとappendを使用した場合
datelist = []
for i in range(days_num):
    datelist.append(strdt + timedelta(days=i))


# 確認用
for d in datelist:
    print(d.strftime("%Y-%m-%d (%A)"))

# 実行結果
# 2018-02-24 (Saturday)
# 2018-02-25 (Sunday)
# 2018-02-26 (Monday)
# 2018-02-27 (Tuesday)
# 2018-02-28 (Wednesday)
# 2018-03-01 (Thursday)
# 2018-03-02 (Friday)
# 2018-03-03 (Saturday)
# 2018-03-04 (Sunday)
# 2018-03-05 (Monday)
```

差の日数分、開始日に差の日数を加算しながらリストを作成しています。

## 方法２、lambdaを使う場合

```{Python}
# lambdaを使用う場合
datelist = map(lambda x, y=strdt: y + timedelta(days=x), range(days_num))


# 確認用（datelistはmapオブジェクトになります）
for d in datelist:
    print(d.strftime("%Y-%m-%d (%A)"))

# 実行結果
# 2018-02-24 (Saturday)
# 2018-02-25 (Sunday)
# 2018-02-26 (Monday)
# 2018-02-27 (Tuesday)
# 2018-02-28 (Wednesday)
# 2018-03-01 (Thursday)
# 2018-03-02 (Friday)
# 2018-03-03 (Saturday)
# 2018-03-04 (Sunday)
# 2018-03-05 (Monday)
```

開始日＋差の日数を計算して返す無名関数を作成し、mapを用いて差の日数リストを適用しています。

## 方法３、リスト内包表記を使う場合

```{Python}
# リスト内包表記を使用する場合
datelist = [strdt + timedelta(days=x) for x in range(days_num)]


# 確認用（datelistはmapオブジェクトになります）
for d in datelist:
    print(d.strftime("%Y-%m-%d (%A)"))

# 実行結果
# 2018-02-24 (Saturday)
# 2018-02-25 (Sunday)
# 2018-02-26 (Monday)
# 2018-02-27 (Tuesday)
# 2018-02-28 (Wednesday)
# 2018-03-01 (Thursday)
# 2018-03-02 (Friday)
# 2018-03-03 (Saturday)
# 2018-03-04 (Sunday)
# 2018-03-05 (Monday)
```

lambdaを使用した場合と考え方は同じです。

# おまけ（時間リストの作成）

lambda式内のdaysとなっている部分をhoursにすると、日付差の時間リストを得られます。

```{Python}
# 時間数を計算
hours_num = ((enddt - strdt).days + 1) * 24

# timedeltaのオプションをhoursに変更
hourlist = map(lambda x, y=strdt: y + timedelta(hours=x), range(hours_num))

for d in hourlist:
    print(d.strftime("%Y-%m-%d %H"))

# 実行結果
# 2018-02-24 00
# 2018-02-24 01
# 2018-02-24 02
# ...
# 2018-03-05 21
# 2018-03-05 22
# 2018-03-05 23
```
gitについて

#初期設定
gitを使用（リポジトリをアップ）するには、最初にユーザー名とメールアドレスを設定する必要がある。(基本的には[github](https://github.com)アカウントのユーザー名とメールアドレス)

```zsh
git config --global user.name "ユーザー名"
git config --global user.email メールアドレス
```
`--global`オプションを指定すると
その後、全ての操作に対して常にこの情報を使うようになる。

もし、違う名前とE-mailアドレスを特定のプロジェクトで上書きしたいのであれば、そのプロジェクトの中で、--globalオプション無しでこのコマンドを実行する。
[最初のGitの構成](https://git-scm.com/book/ja/v1/使い始める-最初のGitの構成)

`--global`で設定した情報の確認は

```zsh
vim ~/.gitconfig
```


#設定ファイル
- `.gitconfig` 
gitの仕様設定を記述する。上記の初期設定以外にも、gitの機能挙動について設定できる。

- `.gitignore` 
バージョン管理から外すファイルを設定する。

>[gitの設定](https://qiita.com/asonas/items/f86740dacb909a244b14)
[[Git] .gitignoreの仕様詳解](https://qiita.com/anqooqie/items/110957797b3d5280c44f)
[.gitignoreの存在を我々は見過ごしてはならない。](https://qiita.com/asonas/items/abdbf1208e832b5dd0eb)



#コマンド
[gitコマンドまとめ](https://qiita.com/ntkgcj/items/9b8129e62e104e1f77a6)

#ツールなど
[tig操作 超簡易版
](https://qiita.com/ntkgcj/items/3da4a4ae6f354c31ea9a)
[.gitignore.io - 適切な設定を簡易生成](https://www.gitignore.io)

#markdown記述
[Basic writing and formatting syntax | GitHub Help](https://help.github.com/articles/basic-writing-and-formatting-syntax/)
`README.md`ファイル編集時の参考
静的サイトを AWS で (S3+CloudFront+Route53+CertificateManager)

## 使うサービスなど
* AWS: S3 (ファイルストレージ)
* AWS: CloudFront (キャッシュサーバ)
* AWS: Route53 (サブドメインのネームサーバ)
* AWS: CertificateManager (SSL化)
* お名前.com (ドメインの取得)

### 概略図
![サーバレス概略図](https://qiita-image-store.s3.amazonaws.com/0/71497/a89b67a1-1bf5-5270-0912-b89c98790759.png)

## なぜこサービス群？
### S3
そんなに更新頻度が高くないサイトなら、 WordPress をはじめとした CMS などは必要ないのでは？と思った。
なにより自分でサーバを管理するのがだるくなった。
メンテナンスフリー最高！

### CloudFront
S3 を独自ドメインで運用し、かつ SSL 化したかった。
S3 で発行される URL も HTTPS でアクセスできる(一部例外あり)が、独自ドメインには対応していない。

### Route53
後述する CertificateManager を用いた SSL 化する際に手続きがお手軽になるため。
これを使わなくても S3 の独自ドメインと SSL 化は可能。

### CertificateManager
Route53 を使っていると無料で使えるし、自動更新が有効になるらしいので。
メンテナンスフリー最高！！

### お名前.com
もともとここでドメインを取得していた。
全部 Route53 に移管しても良かったのだが、メインのドメインは別で使うかもしれないので、とりあえずサブドメインだけ名前解決を Route53 に移譲した。

## 課題
この構成で静的サイトを運用するにあたって解決できていない点がある。

1. S3 には直接アクセスさせたくない
1. ディレクトリにアクセスした時に index.html を自動的に割り当てたい
1. www や index.html の正規化 (SEO 対策)

### 模索
実は 1 と 2 は、それぞれ単独でなら解決できる。
1 は S3 でウェブサイトのホスティング設定をやめ、 CloudFront でバケットを指定するだけ。
2 は S3 でウェブサイトのホスティング設定をして、 CloudFront でバケットではなく S3 の URL を指定すれば良い。
だが両方の要件を満たす方法が今のところ探し出せていない。
要研究。

### SEO
また、 SEO を考えて、 index.html の正規化などもうまくできない。
S3 は Apache ではないので .htaccess などを置いても当然むだである。

SEO だけを考えるなら、カノニカルを使えば良いのだが、下記の通りジェネレータを使っているため、一筋縄にはいかない。
ペライチのサイトならサクッとカノニカルをキメよう。

## 費用
まだ構築したばかりなので、数ヶ月後にまた記事として書く予定。
現時点(4月2日構築、4月5日記述)での請求ダッシュボードによる予測だと、月額150円くらいになりそう。

### 内訳
* Route53 による固定料金
* Route53 による従量課金
* CloudFront による従量課金
* S3 による従量課金

### 現時点での費用感
期間も短く手探りで色々試しているため、正確な運用費は出せないが、現在のところ以下の感じ。
Route53 による固定料金 >> S3 による従量課金 > CloudFront による従量課金 > Route53 による従量課金

S3 はアップロード・ダウンロード共に費用がかかるが、ブログという性質上アップロードの頻度はそんなに高くない。
そして CloudFront を使っているので、ダウンロードもそんなにかかるとは思えない。
最終的には 「CloudFront による従量課金」 と 「Route53 による固定料金」が費用のほぼ全てを締めることになるのではないかと予測している。
Route53 の従量課金も名前解決の方法を考えるとそんなにかからないのではないかと楽観中。
(これで大量アクセスがあったりしたら死ぬかも?)

## 静的サイト
### 実際のサイト
こちら -> [黒柴の柚子](https://yuzu.shibainu.love/)

### 静的サイトジェネレータ
静的サイトを構築するにあたって、 Hexo というブログジェネレータを利用した。
node とマークダウン記法の知識がある人なら、お手軽に静的なブログを構築できる。
テーマやプラグインが色々あるので、気に入ったものを探すといいかも。
Hexo については別記事にして書くかも。
Linux標準教科書(Ver.3.0.0)のまとめ ~第2章~

## はじめに

Linux 標準教科書 (Ver.3.0.0) は、 Linux ディストリビューションの CentOS をインストールするようになっています。私は Mac を使用しており、環境を汚したくないので、今回は Docker for Mac を使用して、 CentOS をインストールしました。

## Docker for Mac のインストール

まずは Docker for Mac を Mac にダウンロードします。
こちらの URL からダウンロードページに移動できます。
=> https://docs.docker.com/docker-for-mac/install/#download-docker-for-mac

- Stable channel
- Edge channel

以上の2種類を選択できますが、私は Stable channel の方をダウンロードしました。
ダウンロードされた Docker.dmg ファイルを実行して、指示通りに操作すれば完了です。

![スクリーンショット 2018-04-05 10.23.58.png](https://qiita-image-store.s3.amazonaws.com/0/186009/1ea594b6-6ffd-cf0a-6885-67d538915c58.png)

## Docker の起動

アプリケーションディレクトリにある Docker をダブルクリックして起動すると、ウィンドウが表示されるので、 Next をクリックします。

![スクリーンショット 2018-04-05 10.32.20.png](https://qiita-image-store.s3.amazonaws.com/0/186009/77aed236-d34e-c4fd-dd47-191050244aa3.png)

すると、またウィンドウが表示されるので、OKを押してください。すぐ後に PC のパスワードを要求されるので、入力してください。

![スクリーンショット 2018-04-05 10.35.22.png](https://qiita-image-store.s3.amazonaws.com/0/186009/bb0d74ff-eba8-212d-7b17-ebf604147063.png)

次はメニューバーからモーダルが表示されるので、 Docker ID と Password を入力すれば完了です。

![スクリーンショット 2018-04-05 10.37.42.png](https://qiita-image-store.s3.amazonaws.com/0/186009/cdcb34b1-1a11-0b8b-94d1-c34091c51143.png)

## Docker を使って CentOS をダウンロードする

`docker pull centos:7` コマンドを実行して、 CentOS をダウンロードしてください。

**注意**: 以下のようなエラーが発生する場合があります。

>Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.

このエラーが発生した場合は `docker login` コマンドを実行して、 Username と Password を入力すれば大丈夫です！


## Docker でコンテナを起動

`docker run -i -t centos:7 /bin/bash` コマンドを実行して、コンテナを起動します。

すると、コンソール上に以下のような表示がされます。 CentOS の世界に入ったことなります。

```
[root@8127f7cfa5d3 /]#
```

これで、Linux標準教科書(Ver.3.0.0)の学習環境はこれで整いました。