OmniAICreator/Qiita-1.07M huggingface dataset:
【UE4】AI Perception の紹介と使い方 その２

#はじめに
この記事は[AI Perception の紹介と使い方](http://qiita.com/Dv7Pavilion/items/741402f4da609ec595a2)の続きとなります。
実は記事を書いて以来AIPerceptionを使っていなかったのですが、最近[Twitter](https://twitter.com/Dv7Pavilion/status/886236102398328832)で「AI Perceptionに新しい機能が実装されてる～」とありましたので、簡単に使い方を調べてみました。

プロジェクトに関しては前回と同じもので構いません。

#AISense_Prediction
これは「指定されたアクタが指定秒数後に予測される位置」を教えてくれるものです。
AIPerceptionに刺激を与えるには**Request Pawn Prediction Event**を使用します。

![2017-07-17_16h54_32.png](https://qiita-image-store.s3.amazonaws.com/0/104467/f63f61eb-f7e4-a1c2-03b8-4739d15939d1.png)

Request Pawn Prediction Eventにより刺激情報を与えることが出来ました。次は受け取る方法です。
SightやHearingと同じ手順で結果を受け取ることが出来ます。

![2017-07-17_17h07_40.png](https://qiita-image-store.s3.amazonaws.com/0/104467/6e6eca93-65c3-af4f-b3d4-5bf7a4a449dd.png)

結果は**Stimulus Location**に格納されています。
以下はデバッグ表示まで含めた使い方の例です。AI Controller側に処理を書いています。

![2017-07-17_17h10_17.png](https://qiita-image-store.s3.amazonaws.com/0/104467/c63c95a0-88c1-2049-9ff3-c87455b0382e.png)

配列のGetで**2**を指定していますが、この数値は

![2017-07-17_17h08_06.png](https://qiita-image-store.s3.amazonaws.com/0/104467/4c594c10-9425-ca7f-694c-481324ddd85c.png)

AIPerceptionコンポーネントの**Senses Config**から由来しています。

##AISense_Predictionの使い所
使い所としてはシューターゲームにあるような**障害物に隠れたプレイヤーを炙り出すためのグレネード投擲位置**を求める時や**逃げ回るプレイヤーを追い詰めるための爆発物設置**とかにも使えると思います。


#AISense_Damage
続いてご紹介するのはダメージ情報を知覚するためのAISense_Damageです。
このSenseに対し刺激情報を与えるためには**Report Damage Event**を使用します。
![2017-07-17_17h57_14.png](https://qiita-image-store.s3.amazonaws.com/0/104467/209c27f8-b53e-10e8-5c59-4a0e0e4f2e34.png)

こんな感じで使います。
![2017-07-17_18h00_42.png](https://qiita-image-store.s3.amazonaws.com/0/104467/f49dc6c1-b87a-07bb-8998-e8683a07a943.png)

Report Damage Eventで与えられた刺激情報を受け取る方法は、他のSenseと同じです。
![2017-07-17_18h04_25.png](https://qiita-image-store.s3.amazonaws.com/0/104467/97599001-0771-bb4b-7056-e6eeff8efa23.png)

**Strength**ではReport Damage Eventにて指定した**Amount**が取得出来ます。
**Stimulus Location**は**Event Location**。**Receiver Location**では**Hit Location**が取得できます。


##AISense_Damageについて
正直な所「**Apply Damage**とか**Any Damage**で良くねぇ？」って感じです。
使い所に関しても思いつかないです。


#AIPerceptionStimuliSourceComponent
このコンポーネントはAI Perceptionを解説している[こちらの海外のサイト](https://denisrizov.com/2017/05/08/ai-perception-in-unreal-engine-4-how-to-setup/)や[書籍](https://www.packtpub.com/game-development/unreal-engine-4-ai-programming-essentials)でも**刺激情報源となるアクタに追加してください**と紹介されるコンポーネントなのですが、自分が今回の記事を書くために作ったプロジェクトでは**追加しなくても普通に動いてました**。（追加するのを忘れてた）
ですので、追加しなかった場合は追加した場合と比べてどのような変化があるのかというのが分かりません。

とりあえず他のサイトでは追加するように紹介されているので、追加しておいたほうが良いと思います。
何かこのコンポーネントについてわかったことがあれば追記していきます。

#おまけ
UE4.18.3ではCharacter側にAIPerceptionを付けても動作しますが、ここで紹介した２つのAISenseについてはAIController側に付いたAIPerceptionでないと動作しません。
詳しくは[【UE4】AIPerceptionをAIControllerとCharacterにアタッチした時の違い](https://qiita.com/Dv7Pavilion/items/63ae78dbee298642eccb)を見ていただければと思います。
Zabbix Agentのインストーラーをinno setupeで作ってみた

Zabbix AgentのWindows版はバイナリで配布されていて、コマンドでのインストールが必要なためインストーラーのように自動でインストール出来る仕組みが作れないかと思いOSSの `inno setup` を使って簡易的なインストーラーを作って見ました。
ここでは、inno setupのインストール手順は省略します。
inno setupは、TeratermやWinSCPなどでも使われているようです。

# inno setup

http://www.jrsoftware.org/ishelp/

# ドキュメント

## 公式

http://www.jrsoftware.org/ishelp/

## 日本語

http://inno-setup.sidefeed.com/
http://www.line-eng.com/technical/index.html#installer_reference

# 検証方針

* inno setupで簡易的なインストーラーを作成する
* 64bit環境にインストールするので、Zabbix Agentは64bit版を使用する
* 作成したインストーラーのインストール及びアンインストールが問題なく動作することを確認する

# 実行環境

| 項目         | バージョン |
|:-------------|:-----------|
| inno setup   | 5.5.9      |
| Windows      | 2012R2     |
| Zabbix Agent | 3.2        |

# 検証

## ソース

簡易インストーラー用に以下を作成してみました。

```
; Zabbix Agent Installer
#define AppName "Zabbix Agent"
#define Version "3.2"
#define InstallerName "Zabbix Agent Installer"
#define SourceDirectory "zabbix_agents_3.2.0.win"
#define Archi "win64"

[Setup]
AppName = {#AppName}
AppVerName = {#AppName} {#Version}
OutputBaseFilename = {#InstallerName}
DefaultDirName = {pf}\{#AppName}
AppendDefaultDirName = no

[Files]
Source: "{#SourceDirectory}\bin\{#Archi}\*" ; DestDir: "{app}/bin" ; permissions:admins-full
Source: "{#SourceDirectory}\conf\*" ; DestDir: "{app}/conf" ; permissions:admins-full

[Languages]
Name: japanese; MessagesFile: compiler:Languages\Japanese.isl

[Run]
Filename: "{app}\bin\zabbix_agentd.exe" ; Parameters: "--config ""{app}\conf\zabbix_agentd.win.conf"" --install"

[UninstallRun]
Filename: "{app}\bin\zabbix_agentd.exe" ; Parameters: "-x"
Filename: "{app}\bin\zabbix_agentd.exe" ; Parameters: "-d"

[Code]
function InitializeSetup(): Boolean;
begin
    Result := MsgBox('Zabbix Agent' #13#13 'インストールを開始しますか？', mbConfirmation, MB_YESNO) = idYes;
    if RESULT = False then
        MsgBox('Zabbix Agent' #13#13 'インストールを中断します。', mbInformation, MB_OK);
end;
```

## インストーラー作成

(1) inno setupを起動します。

(2) 上記ソースを貼り付けて `compile` します。

(3) issファイルの保存先はZabbix Agentを解凍したフォルダと同じ階層（カレントフォルダ）に保存してください。

```
C:\USERS\ADMINISTRATOR\DESKTOP
│  zabbix_agent_installer.iss
│
└─zabbix_agents_3.2.0.win
    ├─bin
    │  ├─win32
    │  │  │  zabbix_agentd.exe
    │  │  │  zabbix_get.exe
    │  │  │  zabbix_sender.exe
    │  │  │
    │  │  └─dev
    │  │          zabbix_sender.dll
    │  │          zabbix_sender.lib
    │  │
    │  └─win64
    │      │  zabbix_agentd.exe
    │      │  zabbix_get.exe
    │      │  zabbix_sender.exe
    │      │
    │      └─dev
    │              zabbix_sender.dll
    │              zabbix_sender.lib
    │
    └─conf
            zabbix_agentd.win.conf
```

(4) 問題なくコンパイルが実行できれば、issファイルが保存されたカレントフォルダに `Output` フォルダが作成されます。その中のインストーラーを実行します。

(5) `サービス` や `プログラムと機能` にZabbix Agentが表示されていることを確認します。

![](https://sky-joker.tech/wp-content/uploads/2017/07/65c29e48527e68adb81280a200511dca.png)

![](https://sky-joker.tech/wp-content/uploads/2017/07/17f023504872936bf9a026b9ec9ebe0c.png)

(6) 次に `プログラムと機能` からZabbix Agentを削除して `サービス` や `プログラムと機能` から削除されたことを確認します。

単純なインストールは出来たけど、もう少し色々と工夫する必要があるなぁ :-(
Jupyterでよく使う設定とか

# はじめに

Anaconda3をインストール後にJupyterの設定をいじったのでメモ

# 環境

* Windows 7 SP1
* Anaconda3 4.4.0 Windows(Jupyter Notebook 5)

# インストール

## Anaconda3のインストール
* [ここ](https://www.continuum.io/downloads#windows)からAnaconda3をダウンロードする
* 任意の場所にインストールする

## Jupyterの設定
### 設定ファイルを作成する
```bash:AnacondaPrompt
jupyter notebook --generate-config
```
この時点でWindowsのユーザフォルダ直下に「.jupyter」というフォルダが作られる
このフォルダ内にjupyter_notebook_config.pyができます
(例：AdministratorであればC:\Users\Administrator\.jupyterなど)

### 作業フォルダを設定する

```text:jupyter_notebook_config.py
c.NotebookApp.notebook_dir=<作業フォルダ>
```

### 外側からみれるようにする

```text:jupyter_notebook_config.py
c.NotebookApp.ip='*'
```

### パスワードを設定する

```bash:AnacondaPrompt
jupyter notebook password
```

### テーマを変更する(jupyter-themes)
[jupyter-themes](https://github.com/dunovank/jupyter-themes)を参考にインストールする

```bash:AnacondaPrompt
pip install lesscpy
pip install jupyterthemes
```

* テーマを調べる

```bash:AnacondaPrompt
jt -l
```

* テーマを選ぶ(chesterishを選んだ場合)

```bash:AnacondaPrompt
jt -t chesterish
```

* ヘルプ表示

```bash:AnacondaPrompt
jt -h
```

### nbextensionsをインストールする
jupyterの拡張機能として[nbextensions](https://github.com/ipython-contrib/jupyter_contrib_nbextensions)をインストールする

```bash:AnacondaPrompt
conda install -y -c conda-forge jupyter_contrib_nbextensions
```
webpack-dev-server: コマンドが見つかりませんの対処法

```
> webpack-dev-server -d --config webpack.dev.config.js --content-base public/ --progress --colors

sh: webpack-dev-server: command not found

npm ERR! Darwin 14.4.0
npm ERR! argv "node" "/usr/local/bin/npm" "run" "devserve"
npm ERR! node v0.12.4
npm ERR! npm  v2.10.1
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! Blabber@0.0.1 devserve: `webpack-dev-server -d --config webpack.dev.config.js --content-base public/ --progress --colors`
npm ERR! spawn ENOENT
```
こんなエラーがでたら、

```
$ npm install webpack-dev-server -g
```
失敗のリスクを減らす目標の設定を

失敗する事例を見ていると、失敗するだけの理由があって失敗しているのが分かる。
[「負けに不思議の負けなし」](https://ja.wikiquote.org/wiki/%E9%87%8E%E6%9D%91%E5%85%8B%E4%B9%9F)
というように、失敗を繰り返しているときはそれだけの理由がある。

### 多数の改変を同時に行なえば失敗の率は高くなる。
- 主旨の異なる改変を５つ同時に行えば、1つずつ行なう場合よりも格段に成功する率は低下する。
- ハードウェアの改変とソフトウェアの改変とを同時に実施すれば、それぞれ単独で実施する場合よりも失敗の比率は高まるし、原因の切り分けはできなくなる。
- 当然、失敗する可能性も高まる。


開発テーマのマネジメントをするリーダーは、そのことを承知して開発目標を立てて欲しい。
開発メンバーの方としては、失敗の可能性を減らす目標の設定を、リーダー対して働きかけよう。
問題の切り分けができるように自分の担当分のコードを書くこと。
単体テストを実施すること。

潜在的な危険についての情報を、他のメンバーと共有すること。

自分の担当のコードで失敗をしないことは大切。
でも、仕事が成功するためには、全ての部分のコードで失敗させないことが大切。


### 失敗をおびき寄せる行為

-  全体で１つのシステムであるものを、対等な関係の3社に分割して発注する。そうするとその3社を調整する仕組みは働かなくなる。
    -  某銀行のシステムです。
-  技術の評価と入札金額とがある官公庁の案件の開発で、入札金額が安いが技術の評価も一番低い業者を選択する。
-  「現行業務の延長でシステムを開発してほしい」と契約後に開発方針を大幅に変更してしまうこと。
    -  某官公庁のシステムです。
- 現行の業務システムの業務手順の自体の見直しをすることなしに、新システムだけに無茶な期待をする。
    - 新しいシステムで例外的な記述の少ない一貫性のある記述をしたいと望むのならば、現行の業務手順自体を単純化することが必要。
    - もう既に意味をなさなくなっているコード、意味をなさなくなっている規定を削除して、実際の部分を単純化することなしに、新システムならばうまくできるだろうと期待すること。
   

### 失敗している事例に共通しているように思えること
- 要件定義に失敗している。
    - 「要件定義が十分に明確である。その特定のモジュールの実装にだけ失敗している」ことで開発に断念となった事例は聞いたことがなし。
    - 「要件定義が十分に明確である。その特定のモジュールに実装にバグを生じた」のが、本番の運用時に露見して失敗する事例はある。

- 変更の生じやすい部分と、変更の生じにくい部分とに設計を分離しないために、何か変更があるといたるところに設計変更を生じてしまう。
    - 例：[Model View Controller](https://ja.wikipedia.org/wiki/Model_View_Controller)は、View　（ユーザーインタフェース）を置き換えやすくするようになっている。
    - [オープン・クローズドの原則（OCP: Open-Closed Principle）](http://mizoguche.info/2015/01/agile-development-reading-2/)

> なんかオブジェクト指向という枠組みの中での話なので「抽象」という概念がフォーカスされてる感じあるけど、「（仕様）変更が起きた時に修正が少なく済むように設計する」というコンセプトが一番重要っぽい。そう解釈すると、プログラミングという行為において一番重要な原則に感じる。

- ハードウェアも含む場合だと開発目標を十分に明確に絞り込めないままに、あいまいな開発をしてしまう。うまく行っているのかいないのか、うまくいかない理由が何なのかがはっきりしない状況を生み出してしまって、問題を解決することができなくなる。
 

### 開発内容の要件定義の重要性
ハードウェア・ソフトウェアの両方についてだと思うが、開発内容の要件定義をどれだけきちんと行なえるかというのが、開発において一番重要なことだと思う。要件定義は開発者に対してこう作ってあれば十分だよと言い切れるものでなくてはなりません。

チェックポイント

- [ ] 市場において意味を持つものに仕上がっているか
- [ ] 既存のものに比べ優位性はどこにもっているのか、強みははっきりしているか
- [ ] 作りやすいものになっているのか
一つ一つの技術的な要素に対して、これだけ作れば必要条件を満たし十分だとと第3者が判定できるだけの条件を
満たさなくてはならない。

#### ボトルネックとなっている技術要素は明快であるか？ 明快である場合：
明快になっている技術要素は、調べまくる・聞きまくるで解決できる可能性がある。

#### ボトルネックとなっている技術要素は明快であるか？ 明快ではない場合：
　明快になっていないということは、何が課題なのかを自力で考えまくるということです。


不明確な部分が一部に残るということは十分ありがちな状況です。
　しかし、その不明確な部分の影響を一部におさえて、
　それ以外の部分は、不安要因がなく確定していると言い切れる状況を作ることです。


私がかつて関わったプロジェクトの中では、、どうやってもその不安定な要素に対して解決策を見出すことができなくて断念したものもありました。


---
付記：**多数の改変を同時に行なえば失敗の率は高くなる**のに対して、ソフトウェアの場合には工夫のしかたがあります。

バージョン管理ツールにgitを使って、ローカルでの管理をすることです。コンフリクトが生じないように分業しつつ開発をすることです。そして、それぞれの改変に対してテストを行なうことで、失敗しやすくなるのを防ぎやすくなります。

そうなる理由の違いは、SVNとgitのバージョン管理の違いです。gitの方がローカルでの開発がやりやすいのです。その様子については、既に書かれている記事を参照してください。

[SVNを捨ててGitを使うべき5つの理由](https://qiita.com/YusukeHosonuma/items/14c59f3878d640a401a1)
create-react-native-app + ExpoでAndroidアプリのビルドから公開まで

# 前書き
ReactNativeの登場で、アプリ開発が容易になりました。
Webアプリの技術を用いて、IOS,Androidアプリの開発が出来てしまいます。
今回は、create-react-native-appでサンプルアプリを作成してビルドから公開まで行なったので
記事にします。

# 前準備
ReactNativeアプリ作成のため、以下のcliをインストールします。

```bash
# npm
$ npm install -g create-react-native-app
$ npm install -g exp
# yarn
$ yarn global add creact-react-native-app
$ yarn global add exp
```

# サンプルアプリ作成
create-react-native-appを利用して、サンプルアプリを作成します。

```
$ create-react-native-app sampleApp
$ cd sampleApp
```

そして、startすればQRコードが表示されますので、スマホのExpoアプリで読み取れば
実機デバッグが可能になります。

# ビルド
expを用いて、以下のコマンドでAndroidアプリのビルドを行います。
その前に、app.jsonに以下の記述を行います。

```json
{
  "expo": {
    "name": "{YOUR APP NAME}",
    "sdkVersion": "18.0.0",
    "ios": {
      "bundleIdentifier": ""
    },
    "android": {
      "package": "com.samplecompany.sampleappname"
    }
  }
}
```
以上のjsonを作成して、以下のビルドを行います。

```
exp build:android
```

以下が表示されたらビルド中です。

```bash
[exp] Building...
[exp] Build started, it may take a few minutes to complete.
[exp] Build ID: {YOUR BUILD ID}
[exp] Run `exp build:status` to monitor it.
```

Expoのサーバーないでビルドされるのか、ビルドには結構時間がかかります。
このビルドが終われば、apkファイルが作成されます。

ビルドの状態は、

```bash
$ exp build:status
```
で確認できます。

以下のようにURLが発行されれば、ビルド成功です。
URLにアクセスして、apkファイルを取得しましょう。

```bash
[exp] ============
[exp] Build Status
[exp] ============

[exp] Android:
[exp] APK: https://exp-shell-app-assets.s3-us-west-1.amazonaws.com/{URL}.apk
```

# Google PlayStoreで公開する
apkファイルが用意できたので、あとは公開するだけです！

Google Play ConsoleのDeveloperアカウントが必要なので
以下を参考に、取得しておきましょう。
https://support.google.com/googleplay/android-developer/answer/6112435?hl=ja

GooglePlayConsoleにログインできるようになれば、アプリの作成から
名前や詳細情報を入力して、apkファイルをアップロードすれば
すぐにPlayStoreで公開できるようになります。
詳しい公開の手順は、以下を参考にしてください。
https://techacademy.jp/magazine/2255

以上で、create-react-native-appとExpoを利用したアプリの作成から公開まででした。

# あとがき
公開の部分を端折ってしまいましたが、
思ったよりもやはり、簡単にアプリを作って公開ができてしまいました。
create-react-native-appとExpoの連携は、今後も便利になっていきそうなので
調査し、記事にあげたいと思います。
お読み頂き、ありがとうございました。
sed, awk, grepの使い分け

#概要
 初心にかえってsed, awk, grepのざっくりとした使い方を記述する

#sed
- 文字列を置換

```
例1: sample.logファイル内のabcをdefに変換
sed s/abc/def/g sample.log
```

#awk
- 文字列を抽出
- 区切り文字を-Fで指定(指定しないとスペース区切りになる)

```
例2: コロン区切りのsample2.logファイル内で左から3番目の文字列を抽出
awk -F':' '{print $3}' sample2.log
例3: スペース区切りのsample3.logファイル内で左から3番目の文字列を抽出
awk '{print $3}' sample3.log
```

#grep
- 文字列を検索

```
例4: 文字列abcが含まれる行を検索する
grep abc sample4.log
```

#応用
- パイプでつなげると、出力結果を渡すことができ、複数の処理をつなげることができる

```
例5: 文字列abcが含まれる行を検索後それぞれの行に対して文字列aaaをbbbに変換、
    さらにスペース区切りで左から2番目と3番目の文字列を抽出する
cat sample5.log | grep abc | sed s/aaa/bbb/g | awk '{print $2, $3}'
```
githubでユーザー名とパスワードを毎回聞かれる問題解消

#gitで毎回ユーザー名(アカウント名)とパスワードを聞かれてしまう

gitの鍵認証も済ませたのにも関わらず、pushするにしてもpullするにしても毎回gitから<font color="DarGreen">ユーザー名(アカウント名)</font>や<font color="DarGreen">パスワード</font>を聞かれてしまう。

    [root@www ◯◯]# git pull
    Username for 'https://github.com': △△××(ユーザー名)
    Password for 'https://△△××@github.com': 

githubのユーザー名(△△××)とパスワードを毎回入力しないとpullやpushができない状態

#原因と解決策

http通信になっているため。これをsshプロトコル通信に変えることで解決

#現在のgitの通信確認

    [root@www ◯◯]# git remote -v
    origin	https://github.com/△△××/◯◯△△.git (fetch)
    origin	https://github.com/△△××/◯◯△△.git (push)
    [root@www ◯◯]#

上記だと、gitに毎回ユーザー名とパスワードを聞かれてしまう。
<font color="Red">https://</font>から始まっていることがダメ

※△△××はgithubのユーザー名
※◯◯△△はgithubのリモートのレポジトリ名

config --list でも確認できる。

    [root@www ◯◯]# git config --list
    user.name=△△××
    user.email=△△××@gmail.com
    remote.origin.url=https://github.com/△△××/◯◯△△.git
    remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

`user.name`等がしっかり設定していても、`remote.origin.url`が<font color="Red">https://</font>から始まっているとダメ。

#gitに毎回ユーザー名とパスワードを聞かれないようにする（解決への流れとコマンド)

##1.まずは通信をsshに変える

    [root@www ◯◯]# git remote set-url origin git@github.com:
    [root@www ◯◯]# 
    [root@www ◯◯]# git remote -v
    origin	git@github.com: (fetch)
    origin	git@github.com: (push)

これでhttp通信でなくなったのが分かる。
<font color="Red">https://</font>ではなく<font color="blue">git@</font>になったことが重要。

##2.リモートレポジトリをセットしてあげる

※ここは一番初めに確認した`origin`のユーザー名から後ろをそのまま持って来れば良い。

    [root@www ◯◯]# git remote set-url origin git@github.com:△△××/◯◯△△.git
    [root@www ◯◯]# 
    [root@www ◯◯]# git remote -v
    origin	git@github.com:△△××/◯◯△△.git (fetch)
    origin	git@github.com:△△××/◯◯△△.git (push)
 
これでssh通信で、ユーザー名と対象のレポジトリも含まれているのが分かる。

config --list でも確認できる。

    [root@www ◯◯]# git config --list
    user.name=△△××
    user.email=△△××@gmail.com
    remote.origin.url=git@github.com:△△××/◯◯△△.git
    remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*

#git pull で確認してみよう

    [root@www ◯◯]# git pull
    Already up-to-date.

ユーザー名もパスワードも聞かれなくなった。
コミットメッセージのフォーマットをウツクシク保つには


**注意：`type`/`scope`はアルファベットのみしか対応していないようです**

コミット時のメッセージのフォーマットをそろえておくと、デバッグ/rollback時などに分かりやすいだけではなく、
[コミット履歴からchangelogを自動生成する](https://github.com/conventional-changelog/conventional-changelog)などの運用も可能になります。

いちいちコミット文のフォーマットを確認するのは面倒くさいですが、
`pre-commit hook`を使えば、コミットする前に自動でチェックしてくれるようになります。

今回は以下のようなフォーマットで統一することを目指しますが、設定をいじれば編集可能です。

```
<type>(<scope>): <subject>
test(staging): 〇〇の機能のテストを追加
```



## [husky](https://github.com/typicode/husky)をインストール

`npm install husky --save-dev`

こうすると、コミット前に関連したnpm scriptが走るようになります。


## [validate-commit-msg](https://github.com/conventional-changelog/validate-commit-msg)をインストール

`npm install --save-dev validate-commit-msg
`
インストールした後は、package.jsonで`"commitmsg": validate-commit-msg`コマンドを追加します。


```package.json
{
"scripts": {
    "commitmsg": "validate-commit-msg"
  }
 }
```

コミットメッセージのフォーマットは、ここで設定できます。
詳しくは[公式参照](https://github.com/conventional-changelog/validate-commit-msg#usage)ですが、
`types`や`scope`の単語を変更したり、`subjectPattern`に入れたい単語を指定することでわりと必要な情報がそろったコミットになると思います。
（ただ、こちらで`types`を日本語にカスタマイズしてみたところ、認識されませんでした・・・）


```package.json
{  
  "config": {
    "validate-commit-msg": {
    "types": ["feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert"],
    "scope": {
    	"required": false,
	    "allowed": ["*"],
	    "validate": false,
	    "multiple": false
	 },
    "warnOnFail": false,
    "maxSubjectLength": 100,
    "subjectPattern": ".+",
    "subjectPatternErrorMsg": "subject does not match subject pattern!",
    "helpMessage": "",
    "autoFix": false
    }
  }
 }
```





## ちなみに

`husky`の機能を使えば、precommit以外でもprepushなどのタイミングでnpm scriptを実行することができます。

```package.json
{
  "scripts": {
    "precommit": "npm test",
    "prepush": "npm test",
    "...": "..."
  }
}
```
`git-hook`との対応表はこちら。
https://github.com/typicode/husky/blob/master/HOOKS.md
バッチファイルにC#コードを書く

# 注意
実用性は不明です。

# 方法
バッチファイル内にPowerShellスクリプトを書くことができます。
　(参考 : [バッチファイルから PowerShell を呼び出す方法](http://qiita.com/cd01/items/82829ba0ec0f59e1b04d) )

PowerShellスクリプト内にC#プログラムを書くことができます。
　(参考 : [PowerShellメモ　C#コードを実行](http://qiita.com/Kosen-amai/items/d68b9590c9e8e8b06377) )

組み合わせると、
バッチファイル内にC#コードを書くことができます。

# サンプル

以下をバッチファイル "hello.bat" に保存して、"hello.bat 1" を実行すると、"hello 1 world" が2行表示されます。

```ps1
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof

# http://qiita.com/cd01/items/82829ba0ec0f59e1b04d
# http://qiita.com/Kosen-amai/items/d68b9590c9e8e8b06377

Param($argBat)

$src = @'
using System;
public static class HelloClass
{
    public static string HelloMethod(string arg)
    {
        string msg = "hello " + arg + " world";
        Console.WriteLine(msg);
        return msg;
    }
}
'@
Add-Type -TypeDefinition $src -Language CSharp

$helloResult = [HelloClass]::HelloMethod($argBat)
Write-Output -InputObject $helloResult

exit 0
```

# 関連情報
* [バッチファイルから PowerShell を呼び出す方法](http://qiita.com/cd01/items/82829ba0ec0f59e1b04d)
* [PowerShellメモ　C#コードを実行](http://qiita.com/Kosen-amai/items/d68b9590c9e8e8b06377)
* [gist batファイル内のPowerShell内のC#プログラムを動かす](https://gist.github.com/cat2151/7adeddee28664472b331fbd1655dc7c5)
* [バッチファイルにJavascriptコードを書く](http://qiita.com/cat2151/items/eab77d24c5317fc24729)
CotEditor 上で書いた Ruby のコードを動かして結果を後ろに挿入する


# はじめに

テキストエディターで何かを編集中，ちょっと何かを計算させたり，何らかのプログラムを実行させてその結果を使ったりしたいときがある。

いちいちコマンドラインに移ってやるのは面倒。

ここでは，Mac 用テキストエディターである [CotEditor](https://coteditor.com/) 上で選択状態にしたテキストを Ruby の式として評価した結果をうしろに挿入させる，ということを CotEditor のスクリプトで実現させてみる。

他の言語にも簡単に応用できる。


# スクリプトのコード

CotEditor のスクリプトはいろんな言語で書けるが，Ruby の式を評価させたいのだから，Ruby を使ってみよう。

以下のようなファイルを CotEditor のスクリプトフォルダーに入れると，スクリプトメニューから呼び出すことができる。


```rb:ruby-eval.rb
#!/usr/bin/ruby
#
# %%%{CotEditorXInput=Selection}%%%
# %%%{CotEditorXOutput=InsertAfterSelection}%%%

begin
  print " # => ", eval(STDIN.set_encoding("UTF-8").read)
rescue
  print " # => ERROR:\n", $!
end
```

先頭行には Ruby 処理系のパスを書く。rbenv で入れた Ruby のパスも書けるが，`which ruby` とかで調べた `shims` を含むパスを書いてもダメで，rbenv のルートの下にある `versions/3.3.4/bin/ruby` みたいなパスを指定する。

それに続くコメント部分が入出力の指定。

`CotEditorXInput` は，何を入力とするかを指定する。`Selection` の場合，現在開いているファイルの選択部分を入力とする。

`CotEditorXOutput` は出力をどう使うかを指定する。`InsertAfterSelection` の場合，選択部分の直後に挿入する。

このやり取りはスクリプトの標準入力・標準出力で行われるので，`STDIN.read` で受け取り，`print` で書き出せばよい。その際，念のためエンコーディングを UTF-8 にしておく。

なお，例外が発生した場合はエラーメッセージを挿入するようにした。

# より詳しくは

入出力の指定方法などは CotEditor ヘルプの「UNIX スクリプトとの連携」を見ればよい。

また，スクリプトファイルのファイル名を工夫することで，メニュー上の並び順を制御したり，サブメニュー化したり，キーボードショートカットに対応させたりすることができる。その使用についてはヘルプの「CotEditor スクリプトのファイル名規則」を参照。

# 関連記事

[EmEditor 上で書いた Ruby のコードを動かして結果を後ろに挿入する - Qiita](http://qiita.com/scivola/items/f42888bc288e6092d1b6)
C#:攪乱順列を求める


## 攪乱順列とは

1,2,3,4..Nの要素からなる順列において、i番目の要素が iでない順列を攪乱(かくらん)順列といいます。完全順列とも言うようです。 

複数人でプレゼントを交換する場合のパターンだと言えば具体的イメージが湧くと思います。

## C#のコード

```csharp
    public static class Derangement {
        // 攪乱順列（完全順列ともいう）を列挙する
        public static IEnumerable<T[]> Enumerate<T>(IEnumerable<T> items) {
            var original = items.ToArray();
            foreach (var element in Permutation.Enumerate(items, items.Count(), false)) {
                bool isComplete = element.Zip(original, (a, b) => a.Equals(b))
                                         .All(x => x == false);
                if (isComplete)
                    yield return element;
            }
        }
    }

    public static class Permutation {
        public static IEnumerable<T[]> Enumerate<T>(IEnumerable<T> items, int k, bool withRepetition) {
            if (k == 1) {
                foreach (var item in items) {
                    yield return new T[] { item };
                }
                yield break;
            }
            foreach (var item in items) {
                var leftside = new T[] { item };
                var unused = withRepetition ? items : items.Except(leftside);
                foreach (var rightside in Enumerate(unused, k - 1, withRepetition)) {
                    yield return leftside.Concat(rightside).ToArray();
                }
            }
        }
    }
```

ソースコードは、[GitHub](https://github.com/gushwell/CSharpAlgorithmCollection)でも公開しています。

## 簡単な解説

攪乱順列を求めるのに、「[n個の異なった要素の中から k個を選ぶ順列](http://qiita.com/gushwell/items/cd1facc829a895a919cc)」で示したPermutationクラスをそのまま利用しています。

攪乱順列を求めるDerangementクラスでは、まず、このPermutationクラスを使い、普通の(重複のない)順列を求め、次に、i 番目の要素が、オリジナルの i番目の要素と一致する場合を取り除くという当たり前すぎる方法で、攪乱順列を求めています。

このi番目の要素と一致する場合を取り除くところで、LINQの ZipメソッドとAllメソッドを使っています。Zipメソッドで２つの要素を比較しているのがミソですね。

ジェネリックメソッドにしていますので、== 使えないので、Equalsメソッドで2つの値を比較しています。


## Derangementの利用サンプル 

以下、Derangementクラスの利用サンプルです。

```csharp
  static void Main(string[] args) {
      int n = 4;
      var nums = Enumerable.Range(1, n).ToArray();
      var derangements = Derangement.Enumerate(nums);

      int i = 1;
      foreach (var elem in derangements) {
          string s = "(" + string.Join(",", elem.Select(x => x.ToString()).ToArray()) + ")";
          Console.WriteLine("{0} : {1}", i++, s);
      }
  }
```

結果は以下の通りです。

<pre>
1 : (2,1,4,3)
2 : (2,3,4,1)
3 : (2,4,1,3)
4 : (3,1,4,2)
5 : (3,4,1,2)
6 : (3,4,2,1)
7 : (4,1,2,3)
8 : (4,3,1,2)
9 : (4,3,2,1)
</pre>

-------------------------
この記事は、Gushwell's C# Programming Pageで公開したものを加筆・修正したものです。
cocoaPodsでpod install後にApple Mach-O Linker (ld) Error Groupと出た時

# 概要

[Swift3.0 Realmデータベースを使う](http://qiita.com/daisukenagata/items/46bde08c8d5b384157b1#3pod-file%E3%81%AE%E4%BD%9C%E6%88%90) に沿って Swift プロジェクトに Realm を導入しようと思ったが、何故か Realm 追加後にビルドした際に下記エラーが出てしまったので、原因と解決方法を共有する。

```
Apple Mach-O Linker (ld) Error Group

clang: error: linker command failed with exit code 1 (use -v to see invocation)
```

# 原因と解決策

pod install をした際に生成される `プロジェクト.xcworkspace` を開いていなかった為。
cocoaPods を使用する際は pod install の前に xcode を閉じ、下記コマンドから `プロジェクト.xcworkspace` を開いて作業する必要がある。

```
open プロジェクト.xcworkspace
```
moqで モック化したメソッドが受けとる引数を処理 + 本来の実装を動かす


# はじめに

扱っているシステムのオリジナルなログサービスにて、出力するログメッセージ内容をUTでテストする必要がありました。

そのときにC#のモックツールであるmoqを利用。

この記事はその際のまとめメモになります。

【注意】
この記事のコードは、実際のコードを記事用に改変し抽出したものでそのままでは動きません。ご了承ください。

# テスト対象コード

## ログサービス提供側

モック化対象クラスのコードです。

```LogService.cs
public class LogService
{
    // 利用されるメソッド
    public void WriteSystemMessageException(SystemMessageException exception)
    {
        Write(exception.SystemMessage);  // モック化したいメソッド
    }

    // モック化したいメソッド
    public void Write(SystemMessage)
    {
        WriteCore(SystemMessage);  // 実際にログを出力するメソッド
    }
}
```

`Write`メソッドで直接ログが出力できますが、`SystemMessageException`という例外クラス経由でログ出力を行いたいため、`WriteSystemMessageException`メソッドが用意されています。

今回は、`Write`をモック化したいと考えています。

## ログサービス利用側

```ConsumerOfLogService.cs
public class ConsumerOfLogService
{
    public LogService logService = new LogService();
    
    public void Index()
    {
        try
        {
            raiseError();  // SystemMessageExceptionが発生する処理
        }
        catch (SystemMessageException sme)
        {
            logService.WriteSystemMessageException(sme);  // ログサービスでログを出力
        }
    }
}
```

テスト対象のクラスとメソッドです。

`SystemMessageException`例外クラスにログメッセージが含まれており、このログメッセージをテストコード内で取得したいと考えています。

また、利用側のコードでは、`LogService`クラスの`WriteSystemMessageException`メソッドのみが利用されており、`Write`メソッドは直接利用されていません。

# moqでテストを書く

ログメッセージを取得し検証するテストコードを書いていきます。

```ConsumerOfLogServiceTests.cs
[TestClass]
public class ConsumerOfLogServiceTests
{
    [TestMethod]
    public void LogService_test()
    {
        var mock_Log = new Mock<LogService>() { CallBase = true };  // ①
        string logMessage = null;  // ログメッセージを格納する変数
        mock_Log
            .Setup(c => c.Write(It.IsAny<SystemMessage>()))
            .Callback<SystemMessage>(sm => logMessage = sm.Message);  // ②

        ConsumerOfLogService target = new ConsumerOfLogService{ logService = mock_Log.Object };
        target.Index();  // テスト対象メソッドを実行
        mock_Log.Verify(c => c.Write(It.IsAny<SystemMessage>()), Times.Once());  // モックが実行されたか確認
        Assert.AreEqual("期待するログメッセージ", logMessage);  // 受け取ったログメッセージで期待値検証する
    }
}    
```

ポイントとして2点あります。

## ポイント①: `CallBase = true` で本来の実装を実行させる

①にある、`{ CallBase = true }`がないと、今回の場合、モック化した`Write`が実行されません。なぜなら、moqのデフォルトではモック化していない`WriteSystemMessageException`は何も処理しない動作となるためです。今回は、`Write`メソッドが`WriteSystemMessageException`メソッドの裏にいます。

そこで、`{ CallBase = true }`を記述することで、本来の`WriteSystemMessageException`メソッドの実装のコードを実行され、処理が`Write`メソッドまで到達します。

## ポイント②: `Callback`でモック化したメソッドが受け取る引数を処理する

②のように、Mockインスタンスの`Callback`メソッドを利用することで、テスト内変数の`logMessage`に`Write`メソッドが受け取った引数を受取り、処理することができます。

# まとめ

moqの機能を利用してオリジナルなログサービスのログメッセージをテストすることができました。

# 参考

* [moq Quickstart](https://github.com/Moq/moq4/wiki/Quickstart)
APIKitとCodableとの連携

たとえば、以下のような`JSON`を返却するAPIを`APIKit`と **Swift4**で新しく追加された`Codable`を組み合わせて実装する。

```users.json
{
    "id": 1,
    "login": "starwars",
    "url": "https://example.com/starwars",
}
```

## APIKitとCodableを組み合わせる場合の注意

`JSONDecoder#decode`は`Data`型を引数にとる。

`JSON`をパースする`APIKit`組み込みの`JSONDataParser`は内部で`JSONSerialization.jsonObject`を利用しており、戻り値はルートオブジェクトが`Dictionary`や`Array`となる。

したがってパースされた値をモデルオブジェクトに変換する

`func response(from object: Any, urlResponse: HTTPURLResponse) throws -> Response`

の引数`object`は`Data`型ではなくなる。

## `Data`型の値を返す`JSONDataParser`の作成

`JSONDecoder#decode`の引数にレスポンスの`JSON`を引き渡せるように`Data`型の値を返す`DataParser`プロトコルに準拠したパーサオブジェクトを作成する。

* `DataParser`プロトコル

```DataParser.swift
public protocol DataParser {
    var contentType: String? { get }
    func parse(data: Data) throws -> Any
}
```

`Data`型の値をそのまま返す`DataParser`を作成する。

```JSONDataParser.swift
class JSONDataParser: APIKit.DataParser {
    var contentType: String? {
        return "application/json"
    }

    func parse(data: Data) throws -> Any {
        // ここではデコードせずにそのまま返す
        return data
    }
}
```

## `Request`プロトコルの`func response(from object: Any, urlResponse: HTTPURLResponse) throws -> Response`を実装する。

`Codable`を適用した`User`モデルを作成。

```User.swift
struct User: Codable {
    let id: Int
    let login: String
    let url: String
}
```

これまでの内容を踏まえ`Request`プロトコルを適用したリクエストオブジェクトを作成する。

```UserRequest.swift
struct UserRequest: APIKit.Request {
    typealias Response = User

    // MARK: - APIKit.Request

    var baseURL: URL { ... }
    var method: APIKit.HTTPMethod { ... }

    ...（省略）...

    // 作成したJSONDataParserをパーサとして適用する
    // （APIKit.JSONDataParserではない）
    var dataParser: DataParser {
        return JSONDataParser()
    }

    func response(from object: Any, urlResponse: HTTPURLResponse) throws -> User {
        let decoder = JSONDecoder()
        return try decoder.decode(User.self, from: object as! Data)
    }
}

```

もしくは個々のリクエストに実装せずに、型制約つきprotocol extensionsを利用する。

```swift
extension APIKit.Request where Response: Decodable {
    // 作成したJSONDataParserをパーサとして適用する
    var dataParser: DataParser {
        return JSONDataParser()
    }

    func response(from object: Any, urlResponse: HTTPURLResponse) throws -> Response {
        let decoder = JSONDecoder()
        return try decoder.decode(Response.self,
                                  from: object as! Data)
    }
}
```

### リクエストの実行

リクエストを実行すると`JSONDecoder`と`Codable`によってマッピングされたモデルオブジェクトを手軽に取得できる。

```swift
let request = UserRequest(name: "starwars")

Session.send(request) { result in
    switch result {
    case .success(let response):
        // responseはUserオブジェクト
    case .failure(let error):
        ...
    }
}
```
sudoが使えなくなった

# 状況説明
あるディレクトリ配下のファイルの所有者を全て自分に変更するスクリプト書いて実行した。

その後sudoコマンド使おうとしたら

「sudo: 実効 uid が 0 ではありません、sudo は setuid root を設定してインストールされていますか？」

こんな感じのメッセージが......。　当時(これ書いてる2周間くらい前)焦りまくってエラーメッセージのログ取ってない。

なにやらsudoが使えなくなったらしい。



# 原因
先の所有者を変更するコマンドが原因だった。

/usr/bin/sudo の所有者を自分にしてしまったようだ。

# 対処法

下記サイトを参考にsuコマンドでrootに切り替えようと試みたが、私は/bin/suまで所有者を自分に変えていたため
ここでもエラーが出た。

[sudoを実行できなくなった](http://hamuhamuengineer.blogspot.jp/2014/02/sudo.html)


# 対処法2

Ctrl + Alt + F1 でCUI画面に切り替える。

そこでユーザー名を聞かれるのでrootと入力。

パスワードは変更していなければ、そのPCをセットアップした最初のユーザーの物と同じだと思う。

ログインして下記のコマンドを実行する。

chown -R root:root /usr/

chown -R root:root /bin/

chmod 4111 /usr/bin/sudo

たぶんこれでsudo出来るようになるはず。

後は

Ctrl + Alt + F7(Linux MintだとF8だったような)
でGUIに戻れる。

# あとがき
chown -R の"-R"は再帰的に所有者を変更するオプションで、わざわざスクリプト書かなくてもコマンド一発だった.......。

途中でCUIに切り替えているのはGUIだとrootにログインする方法がわからなかったため。
DockerComposeの基本

# 概要

CircleCI2.0がリリースされて、よりDockerの必要性を感じています。
社内の基本インフラをきちっと管理する為にも、Dockerの再復習のターンがやってきました。
今回はdocker-compose.ymlの主な記法、DockerComposeの主なコマンドをまとめました。

# DockerCompose概要

* ホスト上の複数のコンテナを一元管理する為のツール
* Docker社が提供
* docker-compose.ymlで設定を書く
* たこ

![download.png](https://qiita-image-store.s3.amazonaws.com/0/129216/0bc76b6b-a019-2450-c5fa-7960035df57f.png)


## docker-compose.yml

DockerComposeの設定を書く為のファイル。

### image / build

* ベースイメージを指定する
* buildの場合はDockerfileのパスを指定する

### command

* コンテナで動かすコマンドを指定する

### links / external_links

* コンテナ間のリンク連携
* 同一docker-compose.yml内にないコンテナと連携する時は、external_linksを使う

### ports / expose

* コンテナが公開するポートを指定する
* ""で囲む
    * "8000:80"
* コンテナポートのみを指定した場合は、ホスト側のポートはランダムで指定される
* ホスト側に連携せず、リンク機能を使って連携するコンテナにのみポートを公開する時はexposeを利用する

### volumes / volumes_from

* コンテナにボリュームをマウントする時に指定する
* ホスト側とマウントする場合は、```ホスト側のパス:コンテナ側のパス```で指定する
* ボリュームの後ろに```:ro```とする事で読み取り専用にする事ができる
    * 設定ファイルが格納されているボリュームなど
* 別のコンテナから全てのボリュームをマウントする時はvolumes_formを利用する

### enviroment / env_file

* コンテナ内の環境変数を指定する
* enviromentは別ファイルの読み込みにも対応している
    * env_file

### container_name / labels

* DockerComposeで作成したコンテナに名前をつける
* labelsでラベルを設定する子も可能
    * docker inspectで確認可能

## Docker Compose コマンド

Dockerと同様にDockerComposeにもコマンドで様々な操作が行える。
ダウンロードは[こちら](http://docs.docker.jp/compose/install.html)で。

* docker-composeコマンドは、docker-compose.ymlを保存したディレクトリで発火
    * -fでファイルパスを指定する事もできる
* サブコマンドの後ろにコンテナ名を付けると指定したコンテナのみを操作可能

```
docker-compose start web-container
```

### up コマンド

* コンテナ群の生成+起動を行う

#### 主なオプション

* -d
    * バックグラウンドで実行
    * プロンプト画面に戻る
* --no-deps
    * リンクのサービスを起動しない
* --no-build
    * イメージをビルドしない
* -t
    * コンテナのタイムアウトを指定

```
docker-compose up -d
```

### scale コマンド

* コンテナを生成する数を指定する

```
docker-compose scale web-container=10 db-container=20
```

### ps / logs コマンド

* psコマンドで複数コンテナの一覧表示を行う

##### 主なコマンド

* -q
    * コンテナIDのみを表示する

```
docker-compose ps
```

* logsコマンドでログが確認できる

### runコマンド

* DockerComposeで起動したコンテナで、新たにコマンドを実行したい時に指定する

```
docker-compose run web-container echo "hello"
```

### start / stop / restart コマンド

* 複数のコンテナを一括で起動/停止/再起動できる
* 一部のコンテナのみももちろん可能

```
docker-compose stop
```

```
docker-compsose restart web-container
```

### kill / rm コマンド

* killコマンドで実行中のコンテナを強制終了できる
    * コンテナにシグナルを送る
        * プロセス間で連絡を取り合う為の仕組み
        * Linuxカーネルで実装されている
* rmコマンドで複数のコンテナを削除できる

```
docker kill
```

```
docker rm
```

# あとがき

バージョンやインフラ部分で悩むのが一番嫌だし、無駄な時間だと思います。
チーム開発をより効率的にする為にもDockerでインフラ構成を可視化してきちっと管理していきたいですね。
Datadogとも連携したので、また別記事にまとめます。

amazonlinuxベースで社内開発用のDockerfile作成しました。
https://hub.docker.com/r/gemcook/development/
mac OSXでbitcoindをコンパイルする際にboostでハマった時に見るtips


max OSXでbitcoindをコンパイルしていると、makeが通って「さあやるぞ！」となってるのに、make checkしたらFAILが出てしまう・・・ログを見るとboostライブラリがリンク出来ないエラーによく遭遇する気がします。解決方法を何度か調べなおしたりしたので備忘録として保存。

```
==============================================
   Bitcoin Core 0.14.99: src/test-suite.log
==============================================

# TOTAL: 1
# PASS:  0
# SKIP:  0
# XFAIL: 0
# FAIL:  1
# XPASS: 0
# ERROR: 0

.. contents:: :depth: 2

FAIL: test/test_bitcoin
=======================

dyld: Library not loaded: libboost_system-mt.dylib
  Referenced from: /usr/local/lib/libboost_unit_test_framework-mt.dylib
  Reason: image not found
FAIL test/test_bitcoin (exit status: 134)

```

これはboostというc++のライブラリが、bicoindのコンパイル時にうまくリンク出来てない為に発生します。otoolで確認するとやはりリンクがされてないようです。

```
$ otool -L src/bitcoin-cli
src/bitcoin-cli:
	libboost_program_options-mt.dylib (compatibility version 0.0.0, current version 0.0.0)
```

stack overflow辺りを見ると色々と解決方法はあるのですが、個人的に採用している方法はbrewでboostを入れてconfigureでパスを指定する方法です。

```
# 既にboostがある場合はupgrade等を試して下さい
$ brew install boost

# 一応リンクし直す
$ brew unlink boost
$ brew link boost

# configureする時にbrewで入れたboostのパスを指定
$ ./configure --with-boost-libdir=/usr/local/Cellar/boost/1.64.0_1/lib

```

configureでエラーが無ければ、再度makeしてmake checkを確認します。正常に通ればbitcoindを起動できます！
既存のMySQL から migration ファイルを作成する手順。

# 概要
バックエンド環境を Ruby に変更することになったため、既存の MySQL から migration ファイルを作成するための手順を調べました。

## 環境
- ruby: 2.4.1
- Rails: 5.0.4

# 手順
###1. 既存データベースの接続情報を登録

```yaml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: '既存DBのユーザ名'
  password: '既存DBのパスワード'
  host: '既存DBのホスト名'

development:
  <<: *default
  database: '既存DBのスキーマ名'
```

###2.　schema.rbを作成

```
$ rake db:schema:dump
```

上記コマンドで ```db/schema.rb``` が作成されます。

###3.　migration ファイルを作成

```
$ rails g migration create_tables
Running via Spring preloader in process 41947
      invoke  active_record
      create    db/migrate/20170717043602_create_tables.rb
```

###4.　schema.rb の内容を migration ファイルにコピー

```schema.rb``` 内の ```create_table "XXXXXX" ... ``` となっている箇所をコピーして、 migration ファイルの ```def change``` の中身を書き換えます。

###5.　migration ファイルからテーブルを作成

```
$ rake db:migrate
````

上記コマンドで migration ファイルからテーブルが作成されます。
そのまま既存のDBに向けて実行すると、テーブルを再作成するので既存のデータが消えるので注意してください。
【初心者向け】【備忘用】AlexaとLambdaの連携 -シミュレータツール(echosim.io)でのテストまで-

# **最初に**
この記事は、Amazon echo(echo show)のためのサービスを作ってみたい！けど、まず最初になにやればいいの？？って人向けの記事です。基本、自分の備忘用です。間違った内容などあれば指摘してもらえるとありがたいです。

Amazon echoは、現在、日本未発売かつ、日本語自体も未対応です。
(2017/07/17現在)※英語(US,UK),ドイツ語には対応

ただ、echoに限らずですが、スマートスピーカー周りは今後面白くなりそうなので、
今のうちにフライングで触っておいてみようと思って触ってみました。

触るにあたり、導入からテストまで一連の流れでわかりやすい記事がなかなか見つけられなかったのでそれならば書いてしまおうと思って書きました。
最終的に、github上に、とてもわかりやすい記事があったので導入に関しては、そちらの記事を参照してもらえれば誰でも出来ると思います。

##**対象者**
・AWSは触ったことあるけど、Lambdaは触ったことない人(僕です）
※コード一切書かずにテストするところまでは出来るので、プログラマ・エンジニアじゃなくても出来ます。ぜひ触ってみて下さい。

##**用語**
**Alexa**
Amazonが提供している音声認識サービスです。Alexa対応デバイス(echo など)からの音声入力をもとに作動します。
**Skill**
ユーザのAlexa対応デバイスに向けた動作にあわせて動くプログラムです。
Lambda(ラムダと読みます)で作るのが一番簡単かと思います。
作ったskillは、Alexa App上に公開出来ます。（amazonの審査あり）
echoでやりたいことを作ることが出来ます。
例)東京都にある図書館の開館、閉館時間を確認できるようにしたいなど。
現状、大きく分けて、
以下の4つのスキルを作れます。
・Custom Skills
 自分がやりたいことを自由に作成できる。
・Smart Home Skills
 スマートホーム機能に特化したスキル
・Flash Briefing Skills
 ニュースの配信サービス用のスキル
・Video Skill
 ユーザーがクラウド対応ビデオサービスを制御できるスキル

##触るにあたり登録が必要なもの
・**AWS**※登録していない人は、以下参考に登録。
　https://aws.amazon.com/jp/register-flow/
  →とりあえず、lambda,S3,Iamを触ります。
　2017/07/17現在、alexa対応は、バージニア北部、北アイルランドリージョンしか対応していません。今のところ、その２つで作成しておいたほうが良いです。
・**amazon.developer**(スキルを作成)
 https://developer.amazon.com/ja/
・**Alexa App**(作成したスキルを確認、有効にするために触る)
http://alexa.amazon.com/spa/index.html
・**echosim.io**(シミュレータツール)
https://echosim.io

触ってみて、一番いけていないなと思ったのは、この点。全部同じAmazonが出しているのに、
(echosim.ioはサードパーティ製とamazon公式ドキュメントには書いているが、amazonが作ったシミュレータとか書いている記事もあるので実際どうかは不明)
4つも行き来するのはかなりめんどくさい。

##**導入**
とりあえず、シミュレータ動かしてみたいくらいならば、以下の記事を参考にすれば、基本すんなり出来ると思います。
本当に分かりやすかったです。ありがとうございます。
https://github.com/sparkgene/jawsdays-ask-handson-advanced/wiki
※記事の中でも書いていますが、jawsdays-ask-handson-advanced-master.zipを解凍し、その中にfunc.zipがあるのでそれをアップロードして下さい。

##**参考**
以下を主に参考にして、学習、導入させてもらいました。
・**amazon developoer公式ドキュメント**
alexaスキルキットでスキルを磨く
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide
・**Amazon Alexaの基礎知識**
http://dev.classmethod.jp/cloud/aws/amazon-alexa-basic-knowledge/
[CircleCI 2.0][Java][Maven][JUnit] CircleCI 2.0でJUnitのテスト結果を集計する

Javaの自動テスト実施のためにCircleCI 2.0を使ってみたんですが、公式ドキュメントの方法だと`mkdir`のところでpermission deniedとなってしまったので対応手順をメモ。（たぶんドキュメントのミスか情報不足だと思うんですけど・・・）

[Collecting Test Metadata - CircleCI](https://circleci.com/docs/2.0/collect-test-data/#maven-surefire-plugin-for-java-junit-results)

```yaml:公式ドキュメントの方法
    steps:
      - run: |
          mkdir -p /junit/
          find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} /junit/ \;
      - store_test_results:
          path: /junit
      - store_artifacts:
          path: /junit   
```

```yaml:修正した方法(ルートディレクトリからではなく、ワークスペース内のディレクトリ以下に作成）
       - run: |
          mkdir -p ~/repo/junit/
          find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/repo/junit/ \;

       - store_test_results:
          path: ~/repo/junit

       - store_artifacts:
          path: ~/repo/junit 
```

[1.0のとき](https://circleci.com/docs/1.0/test-metadata/#maven-surefire-plugin-for-java-junit-results)は `$CIRCLE_TEST_REPORTS` というのがあってそちらを指定していたんですが、この環境変数は2.0だと削除されている様子です。

# Java 8環境向けの `.circleci/config.yml`

テストの集計部分だけだとあれなので、今回検証した設定全文も載せときます。
（サンプルにMaven向けのテスト集計タスクを追加しただけです）

```yaml
# Java Maven CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
 version: 2
 jobs:
   build:
     docker:
       # specify the version you desire here
       - image: circleci/openjdk:8-jdk

       # Specify service dependencies here if necessary
       # CircleCI maintains a library of pre-built images
       # documented at https://circleci.com/docs/2.0/circleci-images/
       # - image: circleci/postgres:9.4

     working_directory: ~/repo

     environment:
       # Customize the JVM maximum heap limit
       MAVEN_OPTS: -Xmx3200m

     steps:
       - checkout

       # Download and cache dependencies
       - restore_cache:
           keys:
           - v1-dependencies-{{ checksum "pom.xml" }}
           # fallback to using the latest cache if no exact match is found
           - v1-dependencies-

       - run: mvn dependency:go-offline

       - save_cache:
           paths:
             - ~/.m2
           key: v1-dependencies-{{ checksum "pom.xml" }}

       # run tests!
       - run: mvn integration-test

       - run: |
          mkdir -p ~/repo/junit/
          find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/repo/junit/ \;

       - store_test_results:
          path: ~/repo/junit

       - store_artifacts:
          path: ~/repo/junit
```
PythonControlで2自由度系の伝達関数を求める。

##目的
2自由度系(バネマスダンバ系)の状態方程式を立式し、
Python Controlで、状態方程式から伝達関数へと変換する。

###事前準備
[PythonControlをインストールする](https://qiita.com/nnn112358/items/ada16e29ef8282498bb7)


##状態方程式
![Banemasu2.jpg](https://qiita-image-store.s3.amazonaws.com/0/73020/ecab63de-9e88-7046-6dd8-36f209d43b97.jpeg)

上図のような連成振動を考える。状態方程式を立式する。

>m1:質量[kg]
>k1:ばね定数[N/m]
>c1:粘性減衰係数[N・s/m]
>m2:質量[kg]
>k2:ばね定数[N/m]
>c2:粘性減衰係数[N・s/m]
>f：力[N]


とおくと、
上記の運動方程式は、

```math
m_{1}\ddot{x}_{1}+c_{1}\dot{x}_{1}+k_{1}x_{1}-c_{2}(\dot x_{2}-\dot x_{1})-k_{2}(x_{2}-x_{1})=0 \\
m_{2}\ddot{x}_{2}+c_{2}(\dot x_{2}-\dot x_{1})+k_{2}(x_{2}-x_{1})= +f \\
```

```math
m_{1}\ddot{x}_{1}=-(c_{1}+c_{2})\dot{x}_{1}-(k_{1}+k_{2})x_{1}+c_{2}\dot x_{2}+k_{2}x_{2} \\
m_{2}\ddot{x}_{2}=c_{2}\dot x_{1}+k_{2}x_{1} -c_{2}\dot x_{2}-k_{2}x_{2} +f\\
```

```math

\begin{bmatrix}
\dot{x}_{1} \\
\ddot{x}_{1} \\
\dot{x}_{2} \\
\ddot{x}_{2} \\
\end{bmatrix}
 =

\begin{bmatrix}
0 & 1 & 0& 0\\
\ -\frac{k_{1}+k_{2}}{m_{1}} & -\frac{c_{1}+c_{2}}{m_{1}} & \frac{k_{2}}{m_{1}} & \frac{c_{2}}{m_{1}}\\
0 & 0 & 0& 1\\
\ \frac{k_{2}}{m_{2}} & \frac{c_{2}}{m_{2}} & -\frac{k_{2}}{m_{2}} & -\frac{c_{2}}{m_{2}}\\
\end{bmatrix}

\begin{bmatrix}
{x}_{1} \\
\dot{x}_{1} \\
{x}_{2} \\
\dot{x}_{2} \\
\end{bmatrix}

+
\begin{bmatrix}
0 \\
0 \\
0 \\
1/m_{2} \\
\end{bmatrix}
f

```

出力方程式を、m2質点の位置x2を観測する方程式とすると、


```math
y=
\begin{bmatrix}
0 & 0 & 1 & 0
\end{bmatrix}
\begin{bmatrix}
{x}_{1} \\
\dot{x}_{1} \\
{x}_{2} \\
\dot{x}_{2} \\
\end{bmatrix}
```

となる。

これを状態方程式

```math
\dot{x}(t)=Ax(t)+Bu(t) \\
y(t)=Cx(t)+Du(t)
```

に当てはめると

```math
A=
\begin{bmatrix}
0 & 1 & 0& 0\\
\ -\frac{k_{1}+k_{2}}{m_{1}} & -\frac{c_{1}+c_{2}}{m_{1}} & \frac{k_{2}}{m_{1}} & \frac{c_{2}}{m_{1}}\\
0 & 0 & 0& 1\\
\ \frac{k_{2}}{m_{2}} & \frac{c_{2}}{m_{2}} & -\frac{k_{2}}{m_{2}} & -\frac{c_{2}}{m_{2}}\\
\end{bmatrix}
,
B=
\begin{bmatrix}
0 \\
0 \\
0 \\
1/m_{2} \\
\end{bmatrix}
,
C=
\begin{bmatrix}
0 & 0 & 1 & 0
\end{bmatrix}
,
D=[０]
```

とする。


これをPythonControlに入力して、伝達関数を求める。

dual_degree_of_freedom_system.py

```
#!/usr/bin/env python
from control.matlab import *
from matplotlib import pyplot as plt
    
def main():
    k1=3.0
    m1=0.1
    c1=0.01
    k2=3.0
    m2=0.1
    c2=0.01
    A = [[0., 1,0,0], [-(k1+k2)/m1, -(c1+c2)/m1,k2/m1,c2/m1],[0., 0,0,1],
    	[-k2/m2,c2/m2,-k2/m2,-c2/m2] ]
    B = [[0.], [0.], [0.], [1./m2]]
    C = [[0,0,1., 0.0]]
    D = [[0.]]
    sys1 = ss2tf(A, B, C, D)
    print sys1
    mag, phase, omega = bode(sys1) 
    plt.show()
            
if __name__ == "__main__":
  main()


```

```
$ ./dual_degree_of_freedom_system.py

          10 s^2 + 2 s + 600
--------------------------------------
s^4 + 0.3 s^3 + 90.01 s^2 + 12 s + 2700
```

![Figure_2.png](https://qiita-image-store.s3.amazonaws.com/0/240874/18bc7aff-6320-f9e1-45f2-d208c908cdfe.png)
メモ: 機械学習ってなんだろう？


## はじめに

機械学習に関する個人的な学習過程を書いていきます。
完全にこの記事自体はただの感想です。

### 目的

データに関することをやりたいなーという気持ちだけ抱えて早5年。なんだかんだHadoopとか弄ったりはしていたけど、そこまで踏み込んで来なかったのです。だいぶ一般的な情報も揃ってきてるし、ちょっとやってみようかな？っていう温度感で勉強していく過程を綴ります。

### 注意点

これから勉強していくための個人の感想みたいなことを書くので、情報の信憑性とか正確性という意味では参考にされないことをお勧めします。

----

## 学習前に

### 初めの状態

まず、機械学習とはなんぞや、というところから。イメージとしては機械になんか学習させて、そのデータを基にして何かしらの出力を得る、程度。でもこれって結局のところ、「InputしたらなんかOutputされるよね」っていうレベルでしかないんだよなーってことにずっともやもやしていました。要するになんもわかってない（

求められた機能を作ること自体は泥臭くがりがり書いてやってきたけど、機械学習として体系化された手法とかライブラリとかはよく知らないんだよネー。

### 取っ掛かり

さて、良く分らないものは仕方がないので、とりあえず入門本を読んでみることろから始めます。なんかどっかでおすすめされてたのでとりあえずなんでもいいから取っ掛かりを。。。という感じで購入。

[機械学習入門](http://amzn.asia/2ny15kz)
　　※なんかアマゾンの商品枠みたいな感じで貼れないのかなこいつ。。。

ざっくりと感想。誰かの役に立つことでもないと思うので、読みやすさとかはあんまり考慮してませんｗ

- 中盤あたりまではおおよそ理解できた。
    - どうやって実装するんだろうっていう疑問は常に付きまとった。
- 最後1/4くらいほとんど理解できなかった。
- 「美しさ」を体現する多くの要素を数値化して、各要素を組み合わせて「美しさ」という総合点数みたいのを出力する。。。なんか大変だなあ。
    - って思ってたら最後は「え、簡単にできますけど？」みたいな感じで終わってすごく釈然としなかった。（最後のほう理解できてないからなおさら）
    - 要するに理解できた序盤の手法は時代遅れってことなんだろうか。
- それ以外にもいくつか例は出てきたけど結局のところ
    - 何を学習させて、 (Input)
    - 学習して溜め込んだデータでどんな処理をさせて、 (Function)
    - どういった結果を出したいのか。 (Output)
- みたいのが明確になっている必要があるなぁ、って印象。
    - 要するにあんまり前進してない。
- 話に出てきたアルゴリズムとかはなるほどなーって感じだけどまぁ実感わかないよね。
- 実例を交えて実際のデータとか、多層化するとどうなるんだーとか、具体的なところに突っ込まないとこの程度でしょうかね。

----

## 総括

入門だし、事前の知識がほとんどないとこんなもんかなぁ。
初めの状態と本を読んだ後の感想がほとんど同じっていうのが切ない気もするけど、とりあえずもう一度調べなおしてみるところから始めます。
ただまぁ要点は何となく理解したのでそこから掘っていく感じでいこうかな。。。
【入門者向け解説】プーリング処理入門(TensorFlowで説明)

#入門者向けに「プーリング」処理について解説
TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)を実行して、「畳み込み」と同様にわかりにくいのが「プーリング」処理でした。畳み込みと同様に文系卒からすると一般用語でもないですし、少しつまづきましたが、分かれば簡単です。畳み込みと違ってフィルタを使わないため、畳み込みよりも簡単です。
[「【入門者向け解説】TensorFlowチュートリアルDeep MNIST」](http://qiita.com/FukuharaYohei/items/0aef74a0411273705512)記事で、畳み込みニューラルネットワークの処理について、[「【入門者向け解説】畳み込み処理入門(TensorFlowで説明)」](http://qiita.com/FukuharaYohei/items/702eb2430ee9dfbe763a)で畳み込み処理に特化したを解説していますので参考にしてください。
<sup>※TensorBoardで出力した画像を参考に載せました(2017/7/27)</sup>
#概説
###概要
[「【入門者向け解説】TensorFlowチュートリアルDeep MNIST」](http://qiita.com/FukuharaYohei/items/0aef74a0411273705512)の記事で解説しましたが、「プーリング」処理では画像の特徴を粗く整理します。画像だけでなく音声やデータでもいいですのですが、画像の方が視覚的でわかりやすいので、画像を使って解説します。
![10.Overview.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/45c8cad3-a42f-29f6-4543-e3487da28df1.jpeg)

###プーリング処理の入出力
畳み込み処理は特徴を出すためにフィルターをかけます。画像をインプットとしてフィルターを使って、フィルターの枚数分の画像を出力します。MNISTデータを使った場合は、下記のとおりです。
![10.Pooling_Overview01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/a1360949-e98d-a929-fa89-0a169827411b.jpeg)

TensorBoardに出した実際のプーリング処理入出力画像を整理したらこんな感じでした。畳み込み処理と違って、荒くしているだけなのでわかりやすいです。
![30.Pooling_image.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/c5062207-81e9-b89a-ed59-fa084f1857dc.jpeg)


#具体的な処理
TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)の以下の箇所がプーリング処理です。第1層でも第2層でも同じです。TensorFlowのAPIを使うことでこの程度で実装することができます。

```py3
# Max Pooling
def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
```

###画像例
入力画像例として縦4×横4×1色(黒のみ)の斜め棒画像を使って、プーリング前に畳み込み処理をした場合は以下の結果となります。結果をわかりやすくするために、"1"と"-1"の2つで表現しています。
![20.Pooling_Convolve01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/02b38f1e-c574-ed17-ebf8-84b8bc3d24fb.jpeg)

###Max Pooling
では、本題のプーリングです。TensorFlowエキスパート向けチュートリアル[Deep MNIST for Experts](https://www.tensorflow.org/get_started/mnist/pros)ではプーリングの種類として、Max Poolingを使っています。Max Poolingは各範囲で最大値を選択して圧縮するだけです。
![20.Pooling02_MaxPool.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/43e40649-b03b-943a-d21a-618e3c130357.jpeg)
図にあるように、斜め棒の特徴が4(縦)×4(横)から2(縦)×2(横)に特徴を残したまま半分に圧縮できました。これが、「特徴を粗く整理」と表現していた内容です。
ちなみに平均プーリングもあって、その場合は下図のとおりです。
![20.Pooling03_AvePool.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/26331419-87ec-9f65-6786-c01c76691ace.jpeg)
WindowsのRでunknown timezoneのエラーが出た

素人の備忘録。
検索しても全然情報がなかったので。

# 状況
WindowsのRでSys.time()を使ったらGMTで返されたうえにエラーが出た。

```R
> Sys.time()
[1] "2017-07-17 04:25:22 GMT"
 警告メッセージ: 
1:  as.POSIXlt.POSIXct(x, tz) で:  unknown timezone 'Asia/Tokyo'
2:  as.POSIXlt.POSIXct(x, tz) で:  unknown timezone 'GMT'
3:  as.POSIXlt.POSIXct(x, tz) で:  unknown timezone 'America/New_York'
```

# 原因
timezoneの情報は`%R_HOME%/share/zoneinfo`以下にある。

`%R_HOME%/etc/Rcmd_environ`をコピーして`.Renviron`を作成していたが、その中の以下の部分が問題だった。

```
R_SHARE_DIR=${R_HOME}/share
```

`Sys.getenv("R_SHARE_DIR")`で見てみると、なぜか`/`で区切られてないパスが出てきた。  
(推測：Rのインストールディレクトリが`\`マーク区切りでレジストリに登録されているのが問題？）

# 解決
`.Renviron`の該当の行を削除したらJSTの時間が出てきた。
Railsのdeviseでサインアップ時に「利用規約に同意する」のチェックボックスを追加する

## acceptedカラムを追加
rails g migration AddAcceptedToUsers accepted:boolean 
rails g migration Addカラム名Toテーブル名 カラム名:boolean

必要なオプション default: false, null: false

```マイグレーション.rb
def change
  add_column :users, :accepted, :boolean, default: false, null: false
end
```

bundle exec rake db:migrate

## ストロングパラメータを追加
```application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?
  protect_from_forgery with: :exception

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:email, :password, :password_confirmation, :accepted)}
  end

end
```

## バリデーションを追加
```user.rb
  validates :accepted, presence: {message: 'を入力してください'}
```

## カラムを日本語化
```ja.yml
user:
  accepted: 利用規約、及び、個人情報の取扱に同意する
```

## サインアップ後のリダイレクト先をrootに変更
```registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController

  protected

  # サインアップ後のリダイレクト先をrootに変更
  def after_sign_up_path_for(resource)
    root_path
  end

  def after_update_path_for(resource)
    user_path(current_user)
  end

  def update_resource(resource, params)
    resource.update_without_password(params)
  end

end
```

## フォームを追加

```views/devise/registrations/new.html.erb
<div class="field text-left">
  <%= f.check_box :accepted ,{},checked_value = "true",unchecked_value = "false" %>
  <%= f.label '利用規約、及び、個人情報の取扱に同意する' %>
</div>
```