OmniAICreator/Qiita-1.07M huggingface dataset:
Tiny Core Linux 4.7.7のcp932対応

[Tiny Core Linux 4.7.7をHDDにインストール＆日本語入力](3556101ce532353d80d7)でインストールしたLinuxでUSBメモリをマウントしてみたところ日本語が化けているようです。unicode対応のrxvtをインストールしてbusyboxをunicode対応にしても、USBメモリはFATでSJIS(cp932)だったため化けてしまうようです。cp932に対応するにはcp932に対応したカーネルモジュールを作成しインストールする必要がある事が分かりましたので、作成＆インストールに挑戦してみたいと思います。

※Tiny Core Linuxでは起動時にホームディレクトリのパーミッションやオーナーを強制的に変更してしまいます。作業ディレクトリとしてホームディレクトリ/home/tcを使う場合は気をつけて下さい。可能であれば別のディレクトリを使う事をお勧めいたします。

## 事前準備
カーネルモジュールをコンパイルするために必要なソースコードとパッケージをダウンロード＆インストールします。

カーネルモジュールのコンパイルにはcompiletc.tczがあればOKなようですのでインストールします。

```console
$ tce-load -wi compiletc
```

カーネルモジュールのソースコードを取得します。

```console
$ wget http://distro.ibiblio.org/tinycorelinux/4.x/x86/archive/4.7.7/src/kernel/linux-3.0.21-patched.txz
$ wget http://distro.ibiblio.org/tinycorelinux/4.x/x86/archive/4.7.7/src/kernel/config-3.0.21-tinycore
```

カーネルモジュールのソースコードを解凍します。

```console
$ tar xvf linux-3.0.21-patched.txz
```

cp932対応にするために設定ファイルを変更します。

```console
$ cd linux-3.0.21
$ cp ../config-3.0.21-tinycore .config
```
```console
$ vi .config
```
```diff:.config
@@ -4317,7 +4317,7 @@
 # CONFIG_NLS_CODEPAGE_869 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
+CONFIG_NLS_CODEPAGE_932=m
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
```

コンパイルします。

```console
$ make oldconfig
$ make fs/nls/nls_cp932.ko
```

## パッケージの作成とインストール

パッケージに必要なファイルを集めます。

```console
$ cd ..
$ mkdir -p nls_cp932/lib/modules/`uname -r`/kernel/fs/nls
$ cp linux-3.0.21/fs/nls/nls_cp932.ko nls_cp932/lib/modules/`uname -r`/kernel/fs/nls
$ mkdir -p nls_cp932/usr/local/tce.installed/
```

インストールスクリプトを作成します。

```console
$ vi nls_cp932/usr/local/tce.installed/nls_cp932
```
```text:nls_cp932/usr/local/tce.installed/nls_cp932
#!/bin/sh

echo kernel/fs/nls/nls_cp932.ko: >> /lib/modules/`uname -r`/modules.dep

/sbin/insmod /lib/modules/`uname -r`/kernel/fs/nls/nls_cp932.ko

sed -i "s/umask=000/umask=000,iocharset=utf8/" /usr/sbin/rebuildfstab
sed -i "/vfat/ s/umask=000/umask=000,codepage=932/" /usr/sbin/rebuildfstab
```

インストールスクリプトに実行権限を付与します。

```console
$ chmod 755 nls_cp932/usr/local/tce.installed/nls_cp932
```

パッケージ化します。

```console
$ rm -f nls_cp932.tcz
$ mksquashfs nls_cp932 nls_cp932.tcz
$ md5sum nls_cp932.tcz > nls_cp932.tcz.md5.txt
```

起動時にパッケージが読み込まれるようにします。

```console
$ /bin/cp -f nls_cp932.tcz* /mnt/sda1/tce/optional/
$ echo nls_cp932.tcz >> /mnt/sda1/tce/onboot.lst
```

## 動作チェック
再起動し、USBメモリをマウントしls -Alなどのコマンドを試して日本語が化けていない事を確認します。この時、ターミナルはurxvtである必要があります。
Bashショートカットチートシート

# Bashショートカットのチートシート
 Bashのショートカットは、よく忘れるので、備忘録として、記載します。
 「+」は、同時押し。「/」は、どちらかのショートカット。「,」は、続けて入力をするキーの場合に記載しています。 わかりにくいですが、日本語キーボードで、shiftを押さなければならないキーは、「shift」を記載しています。

**よく使うショートカット**

| ショートカット | 説明 |
|:-:|:--|
| Ctrl + z | プロセスを一時中断  |
| Ctrl + c | コマンド/アプリケーションを強制終了  |
| ← / Ctrl + b | カーソルを左に移動  |
| → / Ctrl + f | カーソルを右に移動  |
| Alt + f / Esc, f | カーソルを次の単語に移動  |
| Alt + b / Esc, b | カーソルを前の単語に移動  |
| backspace / Ctrl + h | カーソル位置の前の文字を削除  |
| Ctrl + d | カーソル位置の文字を削除  |
| Ctrl + a | 行の先頭に移動  |
| Ctrl + e | 行の末尾に移動  |
| Ctrl + l | 改ページを行う  |
| Tab / Ctrl + i | コマンド補完  |
| ↑ / Ctrl + p | 一つ前に実行したコマンドを表示  |
| ↓ / Ctrl + n | 一つ後ろに実行したコマンドを表示  |

**その他、使えそうなもの**

| ショートカット | 説明 |
|:-:|:--|
| Alt + shift + ! / Esc, shift + ! | コマンド名を補完  |
| Alt + shift + ~ / Esc, shift + ~ | ユーザ名を補完  |
| Alt + shift + \$ / Esc, shift + \$ | 変数を補完  |
| Ctrl + u | 文字列を切り取り  |
| Ctrl + y | 文字列を貼り付け  |
| Ctrl + w | カーソル位置より前の文字列を切り取り  |
| Ctrl + k | カーソル位置より後ろ文字列を切り取り  |
| Ctrl + d | シェルを強制終了  |
| Alt + c / Esc, c | カーソル位置にある文字を大文字に変更  |
| Ctrl + x, shift + ! | コマンド名を表示  |
| Ctrl + x, shift + ~ | ユーザ名を表示  |
| Ctrl + x, / | ファイル名または、ディレクトリ名を表示  |
| Ctrl + x, shift + $ | 変数を表示  |
| Ctrl + x, Ctrl + v| バージョンを表示  |
プロトタイピングツールの探し方

立て続けにプロトタイピングツールとDBデザインツールを探すことになったので、調べたことまとめておく。まずはプロトタイピングツール編。結論から言うと、[Prototypr](http://www.prototypr.io/prototyping-tools/)という比較サイトが最高でした。以上。

ちょっとだけ詳細。

# ステップ
1. 要件決める
2. ロングリスト作る
3. ショートリスト作る（短時間で）
4. 実際に触って決める（えいやで）

## 1. 要件決める
要件決めてないとまだ見ぬ最高のツール探し続けることになる。もしその系統のツールの経験が浅いなら少なくとも外せないもの1つ書く。ツール使った経験が多くて要件が多くても、その中で何が1番かを明確にする。

### 要件の例
大まかな背景は、これまでPCサイトで動きはあるけど、単純なデザインをAdobe CCのXd＋イラレでやっていた。MobileかつIntarctiveなデザインが必要になって、Xdで細かい動き表現するの辛い、ってなった。なので要件は以下。

- Mobile で Intaractiveなデザインやりたい
- （できれば無料、安価）
- （できれば学習コスト低め）

## 2. ロングリスト作る
これがめんどい、と思いきや今回は最高のサイトを見つけたので、一瞬で終わった。

<img width="1348" alt="Screen Shot 2016-11-15 at 11.55.46 AM.png" src="https://qiita-image-store.s3.amazonaws.com/0/88965/aa39b111-c395-eb41-0a13-966d84f634ff.png">

### ロングリストの例
http://www.prototypr.io/prototyping-tools/

## 3. ショートリスト作る（短時間で） 
触る前に、オフィシャルのサイトでデモムービー見て、機能確認。参考にwebで評判などをざっと拾う。ただ評判とかレビューは個人的な評価（好み）か、何らかの評価軸かのどっちかで、今、評価するのは自分なので、参考にとどめる。2の時点で同時に絞り込めていれば、スキップしても可。

ちなみに、調べてるうちに要件追加、ってのが出ることも割とあるので、必要に応じて追記。「あ、この評価軸考えてなかったけど入れた方がいいな」みたいな。

### ショートリストの例
今回はorigami, protopie, fuseをピックアップ
参考URL：

- [F8で発表されたプロトタイピングツール Origami Studioの気になる機能いくつか](http://yo-ry.hateblo.jp/entry/2016/04/14/122314)
- [Qiita: プロトタイピングツール集
](http://qiita.com/usagimaru/items/b5485589550787820348)

## 4. 実際に触って決める（えいやで）
3まではできるだけ早く。そして最後に触るが、これも早く。ツール選んでる時間って結局何も進んでないからね。ある程度使ってみてダメだったら変えればいい。

### 触ってみた例

結局最初に触ったorigamiで決めた（やりたいことができると判断）ので、protopieとfuseは触ってすらいない。これは私の場合だけど、どうせプロトタイピングそのものは何回もやるし、多分新たな要件も出てくるから、その時ショートリストしてまたprotopieがいる、となったら使えばいいや、という判断。

あとorigami触っていて、ついでにSketchも導入。この辺はXd＋イラレでめんどかったこと（パーツ化して管理）ができる上に、それがorigamiにつなげるので決めた。

## TIPS
- 「できれば学習コスト低め」って？

この要件は複合的な判断になるけど、代表的なのは「機能が少ない（もしくは該当機能だけの学習で使える）」「ユーザが多い（もしくは増えそう）」「ドキュメンテーションしっかりしてる」あたりを見てる。なので、機能がリッチで学ぶこと多そうなものでも意外と目的達成までの学習コストは小さいことがある。あとは学習「すべき」コストはケチるものじゃない。（モバイルのインタラクションにどういった表現があるか、など）

- ツール選定は軽い気持ちで

ステップ4でも書いたけど、「ツール選定」の時間は短い方がいい。技術選定と違って割とやり直しがきくし、使う前にあれこれ考えるより、いいから使え、って話。チームとか会社全体で使うツールは予算とか移行とかややこしいから個人、もしくはチーム内で少人数の話ね。

- 意思決定って面白い。

ツール選定は意思決定プロセスだ。今回書いたステップはツール以外でも使える。忘年会のお店決める時とか旅行先で何するか決める時とか。無意識に、もしくは適当にやってた人はちょいと意識するとおもろいと思う。
機械学習論文読みメモ_15

[Asynchronous Methods for Deep Reinforcement Learning](https://arxiv.org/pdf/1602.01783.pdf)
asynchronous gradient descentを用いたreinforcement learningの学習手法を提案する。
experience replayは過去の観測を定期的に再利用して学習する事で時間依存性を回避し学習性能を向上可能で、よく使われてきた。
本論では代わりにマルチエージェントをマルチCPU上でそれぞれ走らせ、異なった環境の観測を同時に与える事で時間依存性を回避した学習を可能にする。
これによりさらなる性能向上が可能で、かつGPUに頼らずCPUのみで計算時間を減らす事が可能である。

[Learning and Inference via Maximum Inner Product Search](http://jmlr.org/proceedings/papers/v48/mussmann16.pdf), ICML2016
log-linear modelの学習を行う際、逐次的な確率推論を行う必要がある。
しかしその際必要になる正規化係数の計算はintractableな場合が多く、特に出力空間が大きい場合にはボトルネックとなる。
本論では、データベース系手法でsimilarity searchをもとにする事でこれを解決する。
それはmaximum inner product search(MIPS)に基いており、random perturbedされたMIPSを用いる事で、誤差がboundされた形で一般的なlog-linear modelからのサンプリングを可能にする。
またMIPSはその従来研究により低コストな計算も可能になっている。

[Pixel Recurrent Neural Networks](https://arxiv.org/pdf/1601.06759.pdf), ICML2016
教師なし学習における画像の分布学習を行う。
このモデルでは、画像のピクセルを逐次的に推定する。
画像なので縦横ピクセル間にリンクを持つ２次元のrecurrent networkを構成する。
また画像全体を考慮した依存関係も学習する。
ピクセル間のリンク構造はマルチスケール性、過去に生成したピクセルとの依存などを考慮したもの、などいくつかある。
このモデルはまたresnet構造も上手く取り入れている。
Power BI で地理的解析（応用編１）


# はじめに

[前回](http://qiita.com/Masutani/items/d91361db4d59d6721d09)に続いて、Power BIの一機能である地理的解析の機能を紹介します。今回は応用編で、少し凝ったマッピングを行う場合に活用できる内容になっています。

前回、紹介したPowerBIの標準ビジュアルである「マップ」「塗り分け地図」では対応できないような分析タスクの場合に、他のビジュアルが用意されています。今回紹介するのは、以下の Power BIのプレビュー機能として用意されているものですが、使ってみたところ、十分実用に耐えうるものとなっていました。

* マップのシェイプ（プレビュー）
* ArcGIS Maps for PowerBI（プレビュー）

# 3.マップのシェイプ

日本語だと名前が変ですが、[MSの解説](https://powerbi.microsoft.com/ja-jp/documentation/powerbi-desktop-shape-map/#-1)では「図形マップ」などとなっている表記も見られます。英語ではそのまま"Shape Map"ですので、形状を強調したマップ表現というくらいに思っていると良いと思います。
形状を洗わずものとして、基礎編で紹介した都道府県マップのようなものもありますが、こちらでは地物の形状などを正確に表した上でコロプレス図を描くことを可能にしています。

このビジュアルを使うには、[MSのページ](https://powerbi.microsoft.com/ja-jp/documentation/powerbi-desktop-shape-map/#-1)にあるように、オプション画面からマップのシェイプ機能をオンにする必要があります。

また、使い方としては、まずマップのシェイプビジュアルを選択します。
そして、対応するデータソースをフィールドに読み込みます。場所バケット（視覚化ペインに存在する入力ボックス）にフィールドをドラッグアンドドロップします。
これで、デフォルトでは米国の州に関するコロプレス図が出現します。もしカラムに州を表す文字列が入っていれば、ここでコロプレス図が作成できます。

![mapng.PNG](https://qiita-image-store.s3.amazonaws.com/0/146939/f835aa3f-178d-a4d9-3005-2d974f3246e1.png)

## カスタムマップの表示

さて、マップのシェイプでは米国に加えて、カナダ、英国、ドイツ、フランス、イタリア、オランダ、オーストリア、アイルランド、オーストラリア、ブラジルの州の白地図が用意されていますが、日本などその他の地域のマップはありません。
そこで、このマップのシェイプでは、カスタムマップを取り込む機能があります。

![cutommap.PNG](https://qiita-image-store.s3.amazonaws.com/0/146939/8d544449-981b-b4ac-b039-a0849591204f.png)

カスタムマップを使うには、視覚化ペインにて、シェイプセクションから「マップの追加」を選びます。

さて、カスタムマップとしては、標準で用意されていないシェイプの他の行政区画の他、各社独自の管理区画（JRの管区とか）、メッシュなど人工的な境界やフロアマップ、レイアウト図など、図形で表せるものはほぼ何でも活用できます。

ここでは例として、日本の地図、しかも廃藩置県前の藩地図を使ってみましょう。結果は以下です。対応するテーブルデータがなかったので、一部の藩しか色付けしていませんが、対応する藩の名称フィールドがあれば、他のデータ同様マッピングが簡単に可能です。

![japankunibi.PNG](https://qiita-image-store.s3.amazonaws.com/0/146939/704b80b1-1b5e-3296-e08f-d18a14fdc827.png)

## カスタムマップの作り方

今回使った藩地図のソースは、ハーバード大の[China Historical GIS](http://www.fas.harvard.edu/~chgis/)サイトから入手しました。
ESRI社のShapeファイルとして、用意されていますので、ArcGISやQGISなどのGISツールで読み込んでみます。
PowerBIのカスタムマップはTopoJSONというGeoJSONの派生形式を使っています。残念ながらQGISなどでは、直接TopoJSONに変換できませので、shapeからTopoJSONに変換できる[MapShaper](http://mapshaper.org/)などのツールを利用します。

Tipsですが、日本語のレコードがあるとうまく読み込めないので、２バイト文字を一度削除して変換をかけるようにすると良いです。今回のデータもそのまま変換してもPowerBIで読み込みエラーになりましたが、日本語の地名があったので、英語の読みフィールドのみ残して読み込むと大丈夫でした。

これで、任意のシェイプに対するマッピングが可能になりました。これが行えると大抵の地図表現に対応できるようになりますね。

[Power BI で地理的解析（基礎編）](https://qiita.com/Masutani/items/d91361db4d59d6721d09)
[Power BI で地理的解析（応用編１）](https://qiita.com/Masutani/items/34cad3287fba9ba44ff4)
[Power BI で地理的解析（応用編２）](https://qiita.com/Masutani/items/513ed61afbf0f316c936)
ソート条件のテストデータの作り方

# ソートテストのテストデータの考え方

友人が質問してくれたのでパッと考えてみたことをまとめた.

ツッコみ歓迎します.

## 結論

ソートされる/されないの分岐を増やしていけば良い.
ソートにかぎらず、シンプルに考え始めて複雑にしていけばOK.

## 実践

もしSQLが

```SQL
SELECT
... -- なにかのすごい処理
ORDER BY ID1,     -- 何かのID
         ID2,     -- 何かのID
         DATE1,   -- 何かの日付
         COMMENT  -- コメント
```

みたいな感じだとしたら、それぞれの場合にちゃんとソースが効いてるか確認すれば良い. 最初から全部考えるとややこしくなるから、シンプルにいこう.

### まずソート条件が一つなら？

ソート条件が一つだけの場合から始めよう.

```SQL
ORDER BY ID1 -- ID1の昇順
```

それなら、2つのデータを用意してちゃんと順番どおりに並べばOK.

```SQL
SQL> SELECT ID1, NAME FROM T ORDER BY ID1;
+-----+------+
| ID1 | NAME |
+-----+------+
|   1 |  one |
|   2 |  two |
+-----+------+
```

っていう順番で取れていれば、仕様通りのソートをしてくれていることが分かる.
ちなみにORACLEはORDEY BYをつけない限り取得される要素の順序は保証されないから、テストデータを入れる順番は気にしなくて良い.

### 次に2つに条件を増やすと？

2つになったらどうしよう？SQLは

```SQL
ORDER BY ID1,     -- 何かのID
         ID2      -- 何かのID
```

になる. さっきのデータは2件だったけど、ID2がソートされることもテストしたいなら、もう1件データを増やそう.

```SQL
SQL> SELECT ID1, ID2, NAME FROM T ORDER BY ID1, ID2;
+-----+-----+-------+
| ID1 | ID2 | NAME  |
+-----+-----+-------+
|   1 |   1 |   one |
|   1 |   2 |   two | -- New!
|   2 |   1 | three |
+-----+-----+-------+
```

こんな並び順で取れてればOK. まずID1でソートされて、ID1が同じなら次はID2でソートされてる.

もし実装を間違えてて、まずID2でソートされていたとしたら

```SQL
+-----+-----+-------+
| ID1 | ID2 | NAME  |
+-----+-----+-------+
|   1 |   1 |   one |
|   2 |   1 | three | -- これと
|   1 |   2 |   two | -- これの順番が変わるはず.
+-----+-----+-------+
```

こんなふうに、ミスしてたら必ずテストが失敗するから、テストデータの量はこれで十分.

### 3つになってもコトは同じ.

なんか雰囲気が分かってきたね. 3つになっても話は同じ.
まずID1、次にID2、そして最後にDATE1、という順にソートが効いていれば良いから

```SQL
SQL> SELECT ID1, ID2, DATE1, NAME FROM T ORDER BY ID1, ID2, DATE1;
+-----+-----+-------------------------------+-------+
| ID1 | ID2 | DATE1                         | NAME  |
+-----+-----+-------------------------------+-------+
|   1 |   1 | 2016-11-15T09:00:00.000+09:00 |   one |
|   1 |   2 | 2016-11-15T09:00:00.000+09:00 |   two |
|   1 |   2 | 2016-11-15T10:00:00.000+09:00 | three | -- New!
|   2 |   1 | 2016-11-15T09:00:00.000+09:00 |  four |
+-----+-----+-------------------------------+-------+
```

ソート条件を間違えていれば必ずこれ以外の順番になるから、良いテストデータといえると思う.

### 最後に、4つのソート.

もう答えだけ書いておく.

```SQL
SQL> SELECT ID1, ID2, DATE1, COMMENT, NAME FROM T ORDER BY ID1, ID2, DATE1, COMMENT;
+-----+-----+-------------------------------+---------+-------+
| ID1 | ID2 | DATE1                         | COMMENT | NAME  |
+-----+-----+-------------------------------+---------+-------+
|   1 |   1 | 2016-11-15T09:00:00.000+09:00 |     aaa |   one |
|   1 |   2 | 2016-11-15T09:00:00.000+09:00 |     aaa |   two |
|   1 |   2 | 2016-11-15T10:00:00.000+09:00 |     aaa | three |
|   1 |   2 | 2016-11-15T10:00:00.000+09:00 |     bbb |  four | -- New!
|   2 |   1 | 2016-11-15T09:00:00.000+09:00 |     aaa |  five |
+-----+-----+-------------------------------+---------+-------+
```

### ただし、条件が不足していても気づけない

でも気づけない部分もある. 4つの条件のうち一つを実装し忘れてたら？つまり

```SQL
SQL> SELECT ID1, ID2, DATE1, COMMENT, NAME FROM T ORDER BY ID1, ID2, DATE1; -- COMMENT のソート条件を書き忘れている.
```

みたいなミスがあったとしたら？ ORACLEは取得の順序を保証しない. つまり、うっかり期待通りの順序でデータを取得してしまう場合もありえる.
でもこれは何個テストデータを追加しても防げない問題だから... どうしたらいいんだろうなぁ.
sierraで ショートカットなど karabiner に頼ってて死んでしまった人へ

# Sierraの弊害

キーバインド(ショートカットキーなど)を設定していた人たち、特に[Karabiner](https://pqrs.org/osx/karabiner/)で色々やってた人は死んだ。死んだのだ。

主に僕。

# 死んで困ったキー

USキーボードの私。

右オプション(Option_R)をファンクションキー(Fn)にしていた。
=> Fn+DELETEで、ForwardDeleteしたかった

# Karabinerの代替を探す

[Karabiner](https://pqrs.org/osx/karabiner/)は、Sierraに対応していない(2016/11/15時点)。

Qiitaなどでも色々あったがいくつか方法があるそうです。

1. OSの標準設定でなんとかなる
2. Keyhac(というアプリ)を使う
3. Karabiner-Elementsを使う(僕はこれになった)

## OSの標準設定でなんとか

参考：
[Karabinerもkeyhacも捨てました。macOS Sierraのキーボード設定について。 | しま★りん.blog @ayurina](https://blog.ayurina.net/2016/10/02/karabiner%E3%82%82keyhac%E3%82%82%E6%8D%A8%E3%81%A6%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82macos-sierra%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A%E3%81%AB%E3%81%A4%E3%81%84/)

こちらのブログにはOS標準設定で出来ることがあるじゃん！ということで。

> ・caps lockと左controlの入れ替え：修飾キーの設定を変える
> ・Ctrl-Oで日本語入力切り替え：キーボードショートカットの設定「前の入力ソースに切り替える」のバインドを変える

これぐらいであれば、OS標準設定で。

## Keyhac(というアプリ)を使う

なんか僕はインストールが出来なかった。クソゲー。

## Karabiner-Elementsを使う(僕はこれになった)

Optionキー自体を別のキーに変更というのはOS標準の設定でいけるんですが、"右の"みたいに限定してキー操作を変更させようとすると何かしらアプリが必要。

Karabinerが標準対応していないのは先に書いたとおり。
ただ公式に「[Karabiner-Elements](https://github.com/tekezo/Karabiner-Elements)」という非常に単純な機能だけをつけたライト版がgitで出ている。

ということでこれをインストしました。

<img width="912" alt="スクリーンショット 2016-11-15 13.02.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/7137/3e618245-d7f5-94e9-9626-9252523dd55f.png">

設定はシンプルにこんなもんです。
これをインストしたら、OS側で殺していたCaps_lockが蘇りやがったので再度心臓に杭ぶちこんでおきました。
Swiftで配列をキャスト(型変換)する

# Swiftで配列の型をキャストする
タイトルの通りですが、[ProtocolA]　→　[StructB]みたいな形にキャストして、StructB以外を除いた配列を作るやり方です。
O(N)で処理時間増えます。

## サンプルコード
```Swift
import Foundation

protocol ProtocolA {
	var title: String { get }
}

struct StructA: ProtocolA {
	var title: String
}

struct StructB: ProtocolA {
	var title: String
	var subTitle: String
}

let ob1 = StructA(title: "1")
let ob2 = StructB(title: "2", subTitle: "2")
let ob3 = StructB(title: "3", subTitle: "3")

let arr: [ProtocolA] = [ob1, ob2, ob3]

// [StructB]
let arr2 = arr.flatMap { $0 as? StructB }

arr2.forEach { print($0.subTitle) }
```

## 実行結果
```
2
3
```
JSでデフォルトカリー化

JS(ES2015)でデフォルトカリー化を味わうためには、関数定義は以下のようにするものだ、と自分に言いきかせます。

`func = arg1 => arg2 => .. 関数本体`

たとえば、以下のように関数を定義して…

```
func = x => y => z => x+y+z;
```

呼び出しは以下のようにします。

```
console.log(func(3)(4)(5)); // ==> 12
```

これでOK。
え?呼び出しが煩雑だって?
ならば、以下のように$プロパティをFunctionに定義すると…

```
uncurry = (func) => {
    return new Proxy(func,
                     {
                         apply(target, thisArg, argsList) {
                             return argsList.reduce((last, arg)=>{
                                 return last.call(thisArg, arg);
                             }, target);
                         }
                     }
                    );
};


Object.defineProperty(Function.prototype, "$", {
    get: function() {return uncurry(this); },
});
```

こんな風にできます。

```
console.log(func.$(3,4,5)); // ==> 12 
console.log(func(3).$(4,5)); // ==> 12 
console.log(func(3)(4).$(5)); // ==> 12 
console.log(func.$(3,4)(5)); // ==> 12
```

`$`はhaskellの$のイメージ。

# 追記

NPMパッケージ化しました。

https://www.npmjs.com/package/uncurry-apply
爆速でSlack用のHubot作成からHerokuにデプロイするシェルスクリプト

Herokuにボットをいっぱい作りたいので、自動化スクリプトをつくってみました

 1. Slack用のHubot作成
 2. Herokuにデプロイ

# 必要なもの
 - Herokuアカウント
 - SlackのHUBOT_SLACK_TOKEN

# スクリプト

```bash:make_hubot.sh
function install(){
    if ! which $1 > /dev/null 2>&1 ; then  brew install -g $1 ; fi
    if ! which $1 > /dev/null 2>&1 ; then  npm  install -g $1 ; fi
}

function yo_hubot(){
    expect -c "
set timeout -1
spawn yo hubot
expect \"Owner\";        send \"${HUBOT_NAME}\n\"
expect \"Bot name\";     send \"${HUBOT_NAME}\n\"
expect \"Description\";  send \"${HUBOT_NAME}\n\"
expect \"Bot adapter\";  send \"slack\n\"
expect \"Everything looks all right!\";    exit 0
"
}

HUBOT_NAME=my_hubot
HUBOT_SLACK_TEAM=my_team
export HUBOT_SLACK_TOKEN=xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

declare -a apps=("node" "npm" "hubot" "yo" "generator-hubot" "coffee-script" "redis" "expect")
for app in ${apps[@]}; do
    echo $app
    install $app
done

bot_dir=`pwd`/hubot-${HUBOT_NAME}
script_path=`pwd`/${HUBOT_NAME}.coffee
rm -rf $bot_dir
mkdir  $bot_dir
cd     $bot_dir

yo_hubot
rm hubot-scripts.json
# カレントディレクトリに`${HUBOT_NAME}.coffee`があれば設置
cp $script_path $bot_dir/scripts/${HUBOT_NAME}.coffee

redis-cli shutdown
redis-server &
ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.redis.plist

./bin/hubot --adapter slack

git init
git add .
git commit -m "init ${HUBOT_NAME}"

heroku login
heroku create $HUBOT_NAME
heroku config:set \
HUBOT_SLACK_TOKEN=$HUBOT_SLACK_TOKEN \
HUBOT_SLACK_TEAM=$HUBOT_SLACK_TEAM \
HUBOT_SLACK_BOTNAME=$HUBOT_NAME \
HUBOT_HEROKU_KEEPALIVE_URL=$(heroku apps:info -s  | grep web_url | cut -d= -f2)
git push heroku master
heroku logs -t
```

# 実行

```shell-session
vi make_hubot.sh # ボット名やトークンを編集します
sh make_hubot.sh
```
CircleCI で Yarn 0.17.0 のインストールに失敗する

多分すぐ直されるバグですが、Yarn 0.17.0 を CircleCI 上でインストールスクリプトからインストールする際に失敗する問題が起きています。

```
Error: ENOENT: no such file or directory, open '/home/ubuntu/.cache/yarn/.roadrunner.json'
    at Error (native)
    at Object.fs.openSync (fs.js:549:18)
    at Object.fs.writeFileSync (fs.js:1156:15)
    at /home/ubuntu/.yarn/node_modules/roadrunner/index.js:25:6
    at /home/ubuntu/.yarn/node_modules/roadrunner/index.js:12:12
    at emitOne (events.js:82:20)
    at process.emit (events.js:169:7)
    at processEmit [as emit] (/home/ubuntu/.yarn/node_modules/signal-exit/index.js:140:35)
    at process.exit (node.js:749:17)
    at Command.<anonymous> (/home/ubuntu/.yarn/node_modules/commander/index.js:825:13)
> Yarn was installed, but doesn't seem to be working :(.
```

依存関係の設定時に、以下の1行を入れることで回避できるようです。

```circle.yml
dependencies:
  pre:
    - mkdir -p ~/.cache/yarn
```

参考: https://github.com/HowNetWorks/uriteller/commit/bff79c351af695d055dbe442f07f8d2b94d0839b
python3でcsvをgzip圧縮する方法

をしようとしてググって出て来る情報がだいたいpython2系だったので、python3で書く方法を記録しておく。

```
import csv
import gzip
import io
import numpy as np

header = ["foo", "bar", "hoge"]
body = np.random.rand(3, 3)
csv_array = np.vstack([header, body])

stringio = io.StringIO()
writer = csv.writer(stringio)

writer.writerows(csv_array)

data = gzip.compress(stringio.getvalue().encode("utf-8"))
f = open("foo.csv.gz", "wb")
f.write(data)
f.close()
```

軽くググッた感じだとpython2系だとｃｓｖの書き込みはstringじゃなくてbyteらしいので、もっと簡単にできるんだけど、3系は少し手間がかかる。
gitのリポジトリがデカすぎてリモートにpushできない時の解決法


web制作をやってると、お客さんが作ったサイトをまるっと渡されて、追加ページだけ作成することがある。
この時git管理しようとサイト全てのファイルをaddしてしまうと、すごく重くなってリモートリポジトリにpushできなくなることがある。

## 解決法

### 不要なファイルのgit管理をやめる

`git rm`すればgit管理から外すことができるが、一度コミットしているファイルは取り消せない。
下記のコマンドで、今までのコミット全てから任意のファイル（フォルダ）を取り除くことができる。

```
$ git filter-branch -f --tree-filter 'rm -rf path/to/delete/folder'
```


### 履歴も消す
上記の操作をしてもバックアップが履歴が残ってるので、まだ重すぎてpushできない。
以下のコマンドでバックアップも削除する

```
$ git update-ref -d refs/original/refs/heads/master
$ git gc --aggressive --prune=now
```
（`refs/original/refs/heads/master`は、logで確認できるref名を指定）

これで、リポジトリが軽くなるので、リモートにpushできる。

__一連の操作は歴史の改変な上に、バックアップの削除まで行っているので、下手すれば元に戻すことができない。
別のフォルダにコピーしてgitに頼らないバックアップをしてから作業するなど、慎重にやろう。__
Ruby on Rails 開発環境構築手順

# Ruby on Rails 開発環境構築手順

## 基本、このとおり
https://www.oiax.jp/rails/zakkan/rails_4_2_installation_on_ubunt.html

```
> sudo dpkg --add-architecture i386
> sudo apt-get update
> sudo apt-get -y install git curl g++ make
> sudo apt-get -y install zlib1g-dev libssl-dev:i386
> sudo apt-get -y install libruby2.3:i386 libreadline-dev:i386
> sudo apt-get -y install libyaml-dev libxml2-dev libxslt-dev
> sudo apt-get -y install sqlite3 libsqlite3-dev nodejs
```

### rbenv のインストール
```
> cd
> git clone http://github.com/sstephenson/rbenv.git .rbenv
> echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
> echo 'eval "$(rbenv init -)"' >> ~/.bashrc
> exec $SHELL
```

### ruby-build のインストール
```
> mkdir -p ~/.rbenv/plugins
> cd ~/.rbenv/plugins
> git clone http://github.com/sstephenson/ruby-build.git
```

### ruby のインストール
```
> rbenv install 2.3.1
> rbenv global 2.3.1
> rbenv version
	2.3.1 (set by /home/joho/.rbenv/version)
> which ruby
	/home/[ユーザ]/.rbenv/shims/ruby
> ruby -v
	ruby 2.3.1p112 (2016-04-26 revision 54768) [i686-linux]
```

### .gemrc の作成
```
> cd
> vim .gemrc
	以下の内容を記入
	install: --no-ri --no-rdoc
	update: --no-ri --no-rdoc
```

### Ruby on Rails 4.2 のインストール
```
> gem install rails --version="~> 4.2"
> rbenv rehash
```

### 作業フォルダの作成
```
> cd
> mkdir work
```

### 動作確認用の新規アプリケーションの作成
```
> cd work
> rails new foo --skip-bundle
> cd foo
```

### 依存パッケージのインストール
```
> bundle install
```

### 簡単なユーザー管理機能の作成
```
> rails g scaffold user name:string email:string
> rake db:migrate
```

### アプリケーションの起動
```
> rails server -b 0.0.0.0
```

### 動作確認
http://[ipアドレス]:3000/users
Apache経由でのMysql接続時に「[2002]Permission denied」というエラーが起きてしまう場合の対処法

# 症状
Apache+PHP+MySQLという構成のWebアプリケーションにて, MySQLへのコネクション要求時に

```
SQLSTATE[HY000] [2002] Permission denied
```

というエラーが発生し, 接続に失敗する.
しかし, コマンドラインのmysqlクライアント等からの接続には成功する.

# 環境

```
$ cat /etc/redhat-release
CentOS release 6.8 (Final)

$ httpd -v
Server version: Apache/2.2.15 (Unix)
Server built:   Jul 18 2016 15:24:00

$ php -v
PHP 5.6.28 (cli) (built: Nov  9 2016 07:23:55)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
```

MySQLはAmazonのRDSを使用

# 原因
SELinuxが有効になっており, httpd経由のネットワーク接続が無効になっていた

# 対処法
この機能は「httpd_can_network_connect」という変数で制御しているようなので, 
この値を変更する

```
$ getsebool httpd_can_network_connect
httpd_can_network_connect --> off
$
$ sudo setsebool -P httpd_can_network_connect 1
$
$ getsebool httpd_can_network_connect
httpd_can_network_connect --> on
$ 
```

これでおそらく接続できるようになります

# 参考
http://k-1-ne-jp.blogspot.jp/2013/02/selinuxmysql.html
javaのMongoDriverを使ったときのread preference設定

小ネタです。

バージョンは以下のような感じ。

``` pom.xml
<dependencies>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.2.1</version>
    </dependency>
</dependencies> 
```

# おことわり
以下全ての例について、MongoDB接続先はこのように定義済みであるものとします。

```java
//初号機(primary)
String ip_pri = "hogehoge";

//弐号機(secondary)
String ip_sec = "fugafuga";

//共通
int port = 27017;
ServerAddress pri = new ServerAddress(ip_pri, port);
ServerAddress sec = new ServerAddress(ip_sec, port);
List<ServerAddress> addressList = new ArrayList<>(Arrays.asList(pri, sec));
```

# 概要
MongoDBのレプリカセットを構築している場合、データの読み出し元について規定するのがread preferenceです。
(詳しくは→ http://qiita.com/y13i/items/78c9f45acd07a9478d2d#read-preference )
これをJavaのMongoDBDriverを使用して実装する際どうするかというと、接続先のMongoDBのコレクションを指定するときに一緒にくっつけます。

順番的には

- MongoCliantインスタンス作成
- 接続先データベース指定
- データベースの中の接続先コレクション(テーブル)指定←ここ

になります。
MongoCollectionクラスに``withReadPreference()``APIがあるので、以下のように記述すればOK。


```java

String dbname = "dbname";
String collname = "collname";

MongoClient cliant = new MongoClient(addressList);
MongoDatabase database = cliant.getDatabase(dbname);

MongoCollection<Document> coll = db.getCollection(collname).withReadPreference(ReadPreference.secondary());
```

# ちなみに
MongoDatabaseクラスにも全く同じAPIがあるので、そちらを使ってもよいです。どちらも同じように動作します。違いはよく調べてません。すみません・・・

```java
MongoClient cliant = new MongoClient(addressList);
MongoDatabase database = cliant.getDatabase(dbname).withReadPreference(ReadPreference.secondary());

MongoCollection<Document> coll = db.getCollection(collname);
```

# (12/1追記)第3の選択肢について

~~なんかビールみたいだな~~

上記の他に、もう一つread preference設定ができる方法がありました。
MongoCliantインスタンスを作成する時に、MongoCliantOptionsのAPIからread preferenceを呼び出すこともできます。

```java
MongoCliantOptions option = MongoClientOptions.builder().readPreference(ReadPreference.secondary()).build();
MongoClient cliant = new MongoClient(addressList, option);

MongoDatabase database = cliant.getDatabase(dbname);
MongoCollection<Document> coll = db.getCollection(collname);
```

しかし長い・・・


```java
MongoClient cliant = new MongoClient(addressList);
cliant.setReadPreference(ReadPreference.secondary());
```

公式には上記の書き方が載っていますが、これだと**var3.3以降では非推奨になっている**だけでなく、以前であっても**(少なくとも自分の環境では)ReadPreferenceが機能しなかった**ので、お気をつけください・・・

# 公式ドキュメント
http://mongodb.github.io/mongo-java-driver/3.0/driver/reference/crud/#immutability-of-mongodatabase-and-mongocollection

http://api.mongodb.com/java/current/com/mongodb/MongoClient.html
独自ドメインのコンタクトフォームを作ったときの備忘録

CMSのプラグイン使うのも面倒くさかったし、GAS使えば簡単にできそうだったから。
また、タダでいけそうだったので、独自ドメインのメールサーバーにZohoを使用した。

# やった流れ
1. Zoho mailの設定
2. Gmailの設定
3. フォームの作成

# 1. Zoho mailの設定
1. 独自ドメインを用意する(私はお名前.comを使った)
2. DNSサーバーを用意する(私はお名前.comを使った)
3. Zoho mailの案内に従ってメールサーバー(独自ドメイン)の設定する
4. Zoho mailの管理画面からPOP3とSMTPプロトコルを使用可能に設定する

# 2. Gmailの設定
1. Googleアカウントを用意する
2. Gmailにアカウントを追加する
3. Zohoのドキュメントを見てPOP3とSMTPの設定をする
4. Aliasに登録をする(これをシないとGASから送信できなかったので注意)

# 3. フォームの作成
1. Google Formを作る
2. Google Formに紐づくSpreadsheetを作る
3. Spreadsheetに紐づくGASプロジェクトを作る
4. HTMLテンプレートをGASプロジェクトに作る
5. GASでメールの送信処理を書く(autoreply.gs)
6. GASのトリガー（フォーム送信時）を設定する


```gas:autoreply.gs
~~ 省略 ~~
  html = HtmlService.createHtmlOutputFromFile("template").getContent();
  GmailApp.sendEmail( // MailAppではなくGmailAppを使用する
    to,
    subject,
    textBody, // textメール用 
    {
      htmlBody: html, // htmlメールができる場合はtextBodyが上書きされる
      from: from,
      name: name,
    }
  );
```


# References
http://www.workabroad.jp/tech/559
https://www.zoho.com/mail/help/pop-access.html
https://www.zoho.com/mail/help/zoho-smtp.html
https://developers.google.com/apps-script/guides/html/
jq で JSON を操作する

[Menual](https://stedolan.github.io/jq/manual/)

```
% cat messages.json
{
  "A": {
    "message": "hoge"
  },
  "B": {
    "message": "piyo"
  }
}
```

object value から object key を逆引き

```
% jq 'to_entries[] | select(.value.message == "hoge")' messages.json
{
  "key": "A",
  "value": {
    "message": "hoge"
  }
}
```

object を編集

```
 % jq 'to_entries[] | if .key == "A" then .value.message |= "fuga" else . end | {(.key): .value}' test.json
{
  "A": {
    "message": "fuga"
  }
}
{
  "B": {
    "message": "piyo"
  }
}
```
mongodbでのexplain

ど忘れしたのですぐに見つかるようにメモ。
クエリの最適化をするときに使うため。

# find

インデックスを使ってソートされているか、スキャンの範囲がどのくらいを見るなら
`db.collection.find({}).explain()`

クエリプランなどもみたければ
`db.collection.find({}).explain(true)`

# aggregate

`db.collection.aggregate([],{explain: true})`
【Xcode8.1】tccdによるフリーズを解決した話

##Xcodeが固まる！
Xcode8.1 / macOS Sierra 10.12にて
突然Xcodeが3分に1回落ちるようになりました。
全く作業にならない！！！

アクティビティログを見ると、謎の「tccd」がCPUを食いまくっている。
Xcodeが落ちるとCPU使用量98%とかになってました。

その状態でもXcode以外はサクサク動く。
どうにかこうにか解決したので書き留め。

##解決法
「システム環境設定」→「セキュリティとプライバシー」→「連絡先」タブ内の
「Xcode」のチェックを外すだけ。
理由はよーわからんのですが、これで改善しました。

![スクリーンショット 2016-11-15 10.10.48.png](https://qiita-image-store.s3.amazonaws.com/0/144427/07b38100-b9fa-fce3-b1fb-7d2c77d8382c.png)

tccdとは何者なのか・・・


参考URL：[tccd](https://origin-discussions-jp.apple.com/thread/10179663?start=0&tstart=0)
Spacemacsが素晴らしいのでさくらのレンタルサーバにインストールしてみた

# ポエム
ひと月ほど前にSpacemacsに出会いました。おっさんですが遅まきながら数年前にVim「再発見」し、若い頃の拒絶反応が嘘のようにカラダがVimに染まってしまいました。「やっぱりオトナは楽しいなぁ」などと思いながらいい気になってVimにプラグインてんこ盛り、AtomもVimキーバインド入れてプラグイン三昧にしたら起動が遅い！「これならEmacsでいいんじゃない？確かEvilってあったよなー」とググっていたらSpacemacsが啓示のように現れました。
で、少しでも貢献したいと思ったので、テストとしてレンサバにインストールした手順をまとめておきます。レイヤーを追加したりすると動かないものもあるかもしれませんが、デフォルト＋japaneseレイヤーでは今のところ問題ないようです。普段使いとしてはiMacにインストールしたものを使っているので、まぁ「インストールできました」というところまでの報告です。


# 前提
- さくらのレンタルサーバスタンダード
- ssh接続はできるようになっている
- bash使用中

# Emacsを最新版に
（参考：http://bty.sakura.ne.jp/wp/archives/818）

```
$ mkdir tmp
$ cd tmp
$ wget http://ftp.gnu.org/gnu/emacs/emacs-25.1.tar.gz
$ tar zxvf emacs-25.1.tar.gz
```

解凍したディレクトリに移動してから、configureしてmake。下記中、「バージョン確認」はemacs内での操作です。

```
$ cd emacs-25.1
$ ./configure --without-x --prefix=/home/ユーザ名/local
$ gmake
$ src/emacs -Q
# C-h C-aでバージョン確認
$ gmake install
$ gmake clean
```

~/local/binにPATHを通し、日本語も通るようにしておく。

```
$ cd ~
$ vim .bashrc
```

以下を追加

```
export PATH=$HOME/bin:$HOME/local/bin:$PATH
export LANG=ja_JP.UTF-8
```
(cshの場合は.cshrcに以下を記述）

```
setenv PATH $HOME/bin:$HOME/local/bin:$PATH）
setenv LANG ja_JP.UTF-8
```

設定を読み込み直す（source .bashrcなど）して確認。問題がなければ、.bash_profileに移し変えておくと、ログイン時に便利。

# いよいよSpacemacs導入

公式サイトに従い、githubからクローン。既存の.emacs.dがある場合は、バックアップを取るなり、削除しておくなりしてください。

```
git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d
```


# 日本語環境

http://qiita.com/kenjimyzk/items/2429f74451a35c9f12fd
に従い、日本語レイヤーを導入しました。[kenjimyzk](http://qiita.com/kenjimyzk)に感謝！

```
git clone https://github.com/kenjimyzk/spacemacs-japanese ~/.emacs.d/private/japanese
```

（migemoは導入していないので動きません。ddskkを使うには、別途辞書の導入が必要かと思います。なお、japaneseレイヤーを入れなくても、簡易的な日本語入力はC-\で可能なようです）

# 設定など

追加の設定などは先人たちの記事にまかせます。

- http://qiita.com/ryosukes/items/d0ec5094a9d3d636f7bb
- http://qiita.com/konnyakmannan/items/87a2859a5f137d1b0a6d
- http://qiita.com/p-baleine@github/items/4ef3ccf84b4e8a7fb419

# 起動

```
emacs
```

ぼくはここまでの設定で起動しました。
MockMvcを使ったControllerのUnitTestでCsrfトークンをRequestする

# 概要

SpringSecurityを使用している場合、SpringのMockMvcを使ってControllerのテストを書く と、
PostリクエストはCSRF Tokenがないと403になってしまうので、その対応。

## テスト対象メソッド

```java
@PostMapping(value = "hoge", consumes = MediaType.APPLICATION_JSON_VALUE)
public void hoge(@RequestBody Hoge hoge) {
    System.out.println("hoge");
}
```

## `spring-security-test` を依存に追加

下記はMavenの場合。
pom.xmlに追加する。

```xml
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <version>4.0.0.RELEASE</version>
</dependency>
```

## `SecurityMockMvcRequestPostProcessors`を使う

下記はSpockでの例。

```groovy
def "CSRFトークンを使ったPostリクエスト"() {
    setup:
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(new Hoge());

    expect:
    mockMvc.perform(MockMvcRequestBuilders
        .post('/hoge')
        .contentType(MediaType.APPLICATION_JSON)
        .content(json)
        // CSRFトークンをセット
        .with(SecurityMockMvcRequestPostProcessors.csrf())
    ).andExpect(
        MockMvcResultMatchers.status().is(HttpStatus.OK.value()),
    )
}
```

## 参考

- [Why I received an Error 403 with MockMvc and JUnit?](http://stackoverflow.com/questions/21749781/why-i-received-an-error-403-with-mockmvc-and-junit)
- [Preview Spring Security Test: Web Security](https://spring.io/blog/2014/05/23/preview-spring-security-test-web-security)
docker runでhost osのディレクトリをマウントする際に注意すること

久しぶりにDockerに触ってハマったこと。

以下のようにrunコマンドの-vオプションを渡すことで、コンテナとホストOS側でデータ共有できます。

```bash
$ docker run -v /host/dir:/container/dir ...
```

**/host/dirの部分を絶対パスで指定する必要があります。**

`docker run -v ./host_dir:/container/dir ...` のような指定をするとエラーとなります。

```bash
$ docker run -v ./host_dir:/container_dir
docker: Error response from daemon: create ./host_dir: "./host_dir" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed.
See 'docker run --help'.
```

また、 `docker run -v host_dir:/container/dir` のような指定をするとエラーにはなりませんが、container側にディレクトリが作成されるものの、ファイルシェアが行われません。

```bash
$ mkdir host_dir

$ echo hoge > host_dir/test

$ docker run -v host_dir:/container_dir xxxxx cat /container_dir/test
cat: /container_dir/test: No such file or directory

```

ということで冒頭書いたように、ホストOS側のディレクトリは絶対パスで指定しましょう。

```bash
$ mkdir host_dir

$ echo hoge > host_dir/test

$ docker run -v `pwd`/host_dir:/container_dir -t -i xxxxx cat /container_dir/test
hoge

```
WindowsでAnnovar

Windows 10 のPower shellからannovarを実行するときのメモ
・PerlはWindowsに標準ではインストールされていない
・Active Perlというのがメジャーらしい
というわけで、[Active Perl](http://www.activestate.com/activeperl)をインストールする。公式サイトからCommunity Editionをダウンロードしてインストールする。Environment VariableにPathを通すかどうか聞かれるが、これはYesにしておく。

[Annovar](http://annovar.openbioinformatics.org/en/latest/)をダウンロードして適当なフォルダに展開しておく。

PowerShellを起動して、ディレクトリを移動

```
cd /PATH_TO/annovar/
```

以降は下記コマンドを実行していく。
official siteに詳細なドキュメントがある。

サンプルファイルをアノテーションしてみる。annotate_variation.plでのアノテーションは
・データベースファイルのダウンロード（遺伝子情報そのものと、アレル頻度の情報）
・.vcfファイルの.avinputへの変換
・アノテーション
の三つの段階に分かれる。

---
####データベースのダウンロード
データベースファイルのダウンロードを行う。ブロードバンドでも数十分かかる。

```
perl ./annotate_variation.pl -buildver hg19 -downdb -webfrom annovar refGene humandb/
perl ./annotate_variation.pl -buildver hg19 -downdb cytoBand humandb/
perl ./annotate_variation.pl -buildver hg19 -downdb genomicSuperDups humandb/ 
perl ./annotate_variation.pl -buildver hg19 -downdb -webfrom annovar esp6500siv2_all humandb/
perl ./annotate_variation.pl -buildver hg19 -downdb -webfrom annovar 1000g2014oct humandb/
perl ./annotate_variation.pl -buildver hg19 -downdb -webfrom annovar snp138 humandb/ 
perl ./annotate_variation.pl -buildver hg19 -downdb -webfrom annovar ljb26_all humandb/
```
---
####ファイルフォーマットの変更
annovar/example内に3つの変異の情報を含んだex2.vcfというサンプルファイルがある。
これをconvert2annovar.plを用いて.avinputファイルに変換する。

```
perl ./convert2annovar.pl -format vcf4 ./example/ex2.vcf > ./example/ex2.avinput
```
---
####変異のアノテーション
.avinputファイルについて、annotate_variationを用いてアノテーションを行う。上記で作成したex2.avinputは複数サンプルのデータが含まれているため、今回はサンプルが一つだけのex1.avinputを用いた。

```
.\annotate_variation.pl example\ex1.avinput humandb -build hg19 -out ex1 --dbtype refGene
```

以下の三つのファイルができる。
ex1.variant_function：すべて変異情報
ex1.exonic_variant_function：エクソン上の変異情報（翻訳への影響を含む）
ex1.invalid_input：うまくアノテーションできなかった変異情報

というわけでwindowsでAnnovarが動いたが、正直なところUNIXでやったほうがよっぽど良い。
json_decodeで作ったオブジェクトを配列にキャストしたらハマった

PHP5.6.27にて以下のコードを書いたら困ったことになった。

```php
>>> $a = (array)json_decode('{"0":"test"}')
=> [
     "0" => "test",
   ]
>>> $a[0]
PHP error:  Undefined offset: 0 on line 1
>>> $a["0"]
PHP error:  Undefined offset: 0 on line 1
```
$aの中身が取り出せない…。
キャスト使うこと自体が悪手なのだとは思うけど、とりあえずarray_valuesを使って対処した。

```php
>>> $a = array_values($a)
=> [
     "test",
   ]
>>> $a[0]
=> "test"
>>> $a["0"]
=> "test"
```
Skype for Business (Lync) の会話履歴の文字化けを直す

なおった！なおった！なおった！
とうとうなおった！

アプリの会話履歴の一覧画面やOffice365での会話履歴の文字化けの原因と解決方法がわかりました！

# 症状

送受信したメッセージ履歴が明らかに文字コード誤りの、難しい漢字ばかりに文字化けする。
`・/span>`などが現れるので、HTMLとして扱おうともしているように見える。

## 化ける箇所

* アプリの会話履歴一覧の1行の会話内容表示
* Office365 Outlookに保存される会話履歴の会話内容

## 化けない箇所

* アプリの会話履歴を開いた会話履歴全文
* Office365 Outlookに保存される会話履歴の、システムメッセージ

## 何が困るか

* アプリの会話履歴一覧から話題が見えず、目的の会話履歴が探せない
* アプリの会話履歴が押し流された場合、Outlookの会話履歴しかあてがないが、アプリの会話履歴と異なり本文も文字化けているので意味がない

過去ログ追えない！！

# 発生時期

インストール直後から。もう一年以上経過。
全社内で自分のみ。

再インストールも効果なし。

# 過去の原因調査

アプリの設定からそれらしいものを探してみるが、エンコード設定など無し。
せいぜいフォントを変えてみるが意味なし。

## 絶望

Microsoftのサポートフォーラムに同様の質問があったのですが(現在検索しても出てこないです…)
その時の回答が**原因不明**。

# 希望

ついこの間も過去の会話ログが必要となりムキー！として手癖で検索したのですが、更新日が新しいサイトが…

[Lync 2013 で生成された会話履歴が文字化けする – Skype/Lync Support Team Blog JAPAN]

これだー！

Lyncがエンコードすることもわからなければその設定がWordのものを使うなんて知るか！
共通コンポーネントがあるのはいいとして、Word経由で触るの！？

とにかく、過去にプログラムが
**デフォルトの文字エンコード設定とは異なるOfficeファイル、メールを正常に処理できるか**
というテストをしたとき、SJISからあれこれいじっていて、そのままだったようで…。

WordのエンコードをEUCからSJISに変え、アプリも一旦再起動し、おもむろに自身にチャットを打って確認。

…見慣れた文字化け。

この報告は私にとってはショックだった。

Office 共通コンポーネントでググってもなんだか難しいし、
共通なのにWord依存というのも怪しいし、
他にもエンコードいじった記憶があるし、
と他製品も確認して、(365じゃない)OutlookのエンコードもSJISに戻した。(というかWordとOutlookしかありませんでした)
アプリを再起動して再度メッセージをやり取りすると、アプリの会話履歴にも365のOutlookの会話履歴にも文字化けず保存されました！！

ありがとう！だが不完全だった！

1. Officeの文字コードを変更する
2. 変更したままもとに戻さない(あるいは変更したままにする必要がある)
3. Skype for Business(Lync)を使っている[^1]

というレアケースですが、ノーモア悲しみ。悲しみよさようなら。あるいはやさしさに。
QiitaのSEOぢからに頼って少なかろう同輩のために拡散します。




Microsoft Teams導入間近なのも悲しみの一因。

[Lync 2013 で生成された会話履歴が文字化けする – Skype/Lync Support Team Blog JAPAN]:https://blogs.msdn.microsoft.com/lync_support_team_blog_japan/2016/10/07/l2013conversationhistorydbcsissue/

[^1]: 裏返せばSlackとか使えない…
Node.js + express + ectの環境を作る


## 前提として

Node.jsはインストールされているものを前提としています。

## Expressインストール

express本体とexpressコマンドを使えるようにgeneratorのインストールを行います。

```bash
$ npm install -g express express-generator
```

### expressスケルトン生成からectのインストール

スケルトン生成時はejsオプションをつけていますがデフォルではjadeが適用されます。
オプションにectがないため、比較的書き方の近いejsをオプションをしてします。

```bash
$ express <myapp> --ejs
$ cd <myapp>
$ npm install
$ npm install --save ect
$ npm uninstall --save ejs
```

## スケルトン生成されたファイルをectに書き換え

### app.jsでビューエンジンを変更

```js:app.js
// view engine setup
// -- ejs
//app.set('views', path.join(__dirname, 'views'));
//app.set('view engine', 'ejs');
// -- ect
app.set('views', path.join(__dirname, 'views'));
app.engine('ect', ECT({ watch: true, root: __dirname + '/views', ext: '.ect' }).render);
app.set('view engine', 'ect');

```

### スケルトン生成ファイルの拡張子を変更

スケルトンで生成されるビューファイルは2つです。
まずは拡張子を変更します。

> /views
> index.ejs -> index.ect
> error.ejs -> error.ect

あとは各ファイルでパラメータ受け取り部分に@をつけます。

```js:index.ect
<!DOCTYPE html>
<html>
  <head>
    <title><%= @title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= @title %></h1>
    <p>Welcome to <%= @title %></p>
  </body>
</html>
```

## 実行

環境は整ったのでNode.jsを起動します。

```bash
$ npm run start
```

以下にアクセスして画面表示されたらひとまずの環境は出来上がりです。
http://localhost:3000
C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（３）　平均画像作成編

今回は、平均画像の作成に関してです。

# 平均画像
学習を行うとき、入力画像に偏りがあると、認識精度が悪くなることがあります。
そこで、明るさやコントラストの偏りを平均化するために、事前に平均画像というものを用意して、学習するときに利用します。

具体的には、まず全学習画像の平均画像と標準偏差を求めます。
そして学習する際に、学習する画像から平均画像の画素値を引き標準偏差で割ることで、各画像の画素の平均が0、分散が1になります。
ちなみにこれを、「平均化（標準化）」と呼びます。

※他の機械学習でも、この「平均化（標準化）」は重要になります。

Caffeでは、この平均画像を求めるために「compute_image_mean.exe」を使用します。

# 引数
「compute_image_mean.exe」のシンタックスは以下のようになっています。

```
compute_image_mean [FLAGS] INPUT_DB [OUTPUT_FILE]
```

## FLAGS
代表的な引数は以下の通りです。
（全てを知りたい人は「compute_image_mean -help」を実行）

| FLAGS | 意味 | 設定例 |
|:--|:--|:--|
| -backend | データベースの種類 | -backend lmdb |

## INPUT_DB
学習に使用するDB名です。
前回の「convert_imageset」の「DB_NAME」になります。
※ファイル名ではない
また、通常DBにはトレーニング用とテスト用の2つがありますが、ここではトレーニング用のDBを指定します。

## OUTPUT_FILE
出力する平均画像データのファイル名です。
フォーマットはProtocolBuffers（バイナリ）になります。

# その他
実は平均画像なしでも学習は行うことができます。
しかし、認識精度を高めるためにも、是非とも用意するようにしてください。

# 関連記事
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（１）](http://qiita.com/mine820/items/37862e45aa66c2ad8b80)
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（２）](http://qiita.com/mine820/items/9ea5812fc25a70419f31)
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（４）](http://qiita.com/mine820/items/41347cd99278d0dc6715)
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（５）](http://qiita.com/mine820/items/e8857fee3fa0b4ada170)
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（６）](http://qiita.com/mine820/items/01a275d1065d299702fc)
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（７）](http://qiita.com/mine820/items/1e100330d163f9959c65)
[C++プログラマがWindows上でCaffeを使ってDeep Learningするお話（８）](http://qiita.com/mine820/items/30fcc4e5f794c42b4bd7)
【Swift】UISearchBarのtextField内にボタンを設置する

以下の画像のようにUISearchBar、textField内の一番右に任意のボタンを追加する方法。

![スクリーンショット 2016-11-15 8.25.29.png](https://qiita-image-store.s3.amazonaws.com/0/135478/ec4c6c7b-e10e-139a-46f9-670ece9f9216.png)

ここには本来ブックマークボタンが表示されますので、このブックマークボタンを表示させて、任意の画像に置き換えるという形を取ります。


## コード

```.swift
// ブックマークボタンを表示させる
searchController.searchBar.showsBookmarkButton = true

// ブックマークボタンに任意の画像を設定
searchController.searchBar.setImage(UIImage(named:"wood.ico"), for: .bookmark, state: .normal)


func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) {

    print("このボタンを押した時の処理")

}
```
TensorFlow > sine curveの学習 > v0.4 > tf.train.shuffle_batch()を使ったコード

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 14.04 LTS desktop amd64
TensorFlow v0.11
cuDNN v5.1 for Linux
CUDA v8.0
Python 2.7.6
IPython 5.1.0 -- An enhanced Interactive Python.
```

v0.1 http://qiita.com/7of9/items/b364d897b95476a30754

http://qiita.com/7of9/items/cad6a45704b1d52d350e
の続き。

tf.placeholder()使用のコードに変更中。
v0.1のコードにあったtf.train.shuffle_batch()を使おうとしている。

- inputs_rsに与えるものをinputsからinputs_batchに変更
- output_rsに与えるものをoutputsからoutput_batchに変更

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

import tensorflow as tf
import tensorflow.contrib.slim as slim

# ファイル名の Queue を作成
filename_queue = tf.train.string_input_producer(["input.csv"])

# CSV を parse
reader = tf.TextLineReader()
key, value = reader.read(filename_queue)
input1, output = tf.decode_csv(value, record_defaults=[[0.], [0.]])
inputs = tf.pack([input1])
output = tf.pack([output])

batch_size=4 # [4]
inputs_batch, output_batch = tf.train.shuffle_batch([inputs, output], batch_size, capacity=40, min_after_dequeue=batch_size)

input_ph = tf.placeholder("float", [None,1])
output_ph = tf.placeholder("float",[None,1])

#inputs_rs = tf.reshape(inputs, [-1, 1])
#output_rs = tf.reshape(output, [-1, 1])
inputs_rs = tf.reshape(inputs_batch, [-1, 1])
output_rs = tf.reshape(output_batch, [-1, 1])

## NN のグラフ生成
hiddens = slim.stack(input_ph, slim.fully_connected, [1,7,7,7], 
  activation_fn=tf.nn.sigmoid, scope="hidden")
prediction = slim.fully_connected(hiddens, 1, activation_fn=tf.nn.sigmoid, scope="output")
loss = tf.contrib.losses.mean_squared_error(prediction, output_ph)

def feed_dict(train, inputs, output):
#    if train:
#
    return {input_ph: inputs.eval(), output_ph: output.eval()}

#train_op = slim.learning.create_train_op(loss, tf.train.AdamOptimizer(0.01))
train_op = slim.learning.create_train_op(loss, tf.train.AdamOptimizer(0.001))

init_op = tf.initialize_all_variables()

with tf.Session() as sess:
  coord = tf.train.Coordinator()
  threads = tf.train.start_queue_runners(sess=sess, coord=coord)

  try:
    sess.run(init_op)
    for i in range(30000): #[10000]
      _, t_loss = sess.run([train_op, loss], feed_dict=feed_dict(True, inputs_rs, output_rs))
      if (i+1) % 100 == 0:
        print("%d,%f" % (i+1, t_loss))
#        print("%d,%f,#step, loss" % (i+1, t_loss))
  finally:
    coord.request_stop()

  coord.join(threads)
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/81b1091f-957b-91b6-673f-f963fe212fd0.png)

v0.1ではlossが0.2付近だったが、上の結果は0.4付近。

コードにまだ間違いがありそうだ。
TensorFlow > Link > tf.train.shuffle_batch() の使用例 @ indico

TensorFlowというDeep Learningフーレムワークにてsine curveを学習しようとしている。
tf.train.shuffle_batch()を使うようにしたが、思ったような結果になっていない。

tf.train.shuffle_batch()の情報を探したが、[本家のページ](https://www.tensorflow.org/versions/r0.11/how_tos/reading_data/index.html)は読みにくかった。コードもコメントも全部同じ黒色で表示されているのが、コードの読みにくさの一因だろう。

以下のページは右上に余計なメッセージが表示されるが、コードの説明としてはわかりやすい。

https://indico.io/blog/tensorflow-data-inputs-part1-placeholders-protobufs-queues/
ブラウザのHTTPヘッダーに外部から認証情報を設定する



サーバ認証するためにブラウザ(WebView)のヘッダー情報を利用することはよくあります。
[SwiftからJavascript(Ajax)で利用する認証情報を設定する](http://qiita.com/utwang/items/a7cdbe85d923456bc5d7)ではWebViewのヘッダー、js空間に外側(iOSネイティブ)から認証情報を渡してあげていました。

同じことをブラウザで行いたいケースがあります。
例えば、WebViewでloadするコンテンツの動作確認やデバッグを行いたい場合などです。

- ブラウザでloadするHTMLを取得するための認証情報をヘッダーにセットする
- load後に非同期通信を行うための認証情報をjsの実行空間に渡す

いちいち、アプリを通して確認するのは面倒だし、使い慣れたChromeのDeveloperToolを使いたいというのもあります。

---

### 前提
- ブラウザ: Chrome (ver 54.0)
- 開発環境などで認証に利用するtokenの値がわかっている

### ブラウザでloadするHTMLを取得するための認証情報をヘッダーにセットする
[ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj?hl=en)というChrome拡張を利用してHeader情報を書き換えます。
Request Headersに必要な情報を入力します。こうすることでHTMLロード時にHTTPリクエストのヘッダー情報にAuth-Tokenがセットされた状態になります。


![スクリーンショット 2016-11-15 7.15.18.png](https://qiita-image-store.s3.amazonaws.com/0/15133/75457f91-8fdf-498d-1048-b1ca56576fba.png "スクリーンショット 2016-11-15 7.15.18.png")



### load後に非同期通信を行うための認証情報をjsの実行空間に渡す
UserScriptを利用して、jsの実行空間にオブジェクトをセットすることで実現できます。
今回は[TamperMonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?hl=en)というChrome拡張を利用して、認証情報を渡します。

![スクリーンショット 2016-11-15 7.15.48.png](https://qiita-image-store.s3.amazonaws.com/0/15133/0906300c-a8bc-4e8c-aef5-2abad9c5084f.png "スクリーンショット 2016-11-15 7.15.48.png")

TamperMonkeyではUserScriptを管理するためのツールなので、スクリプトは別に用意する必要があります。以下はlocalhost:3000/spa/*のURLの時だけ実行されるスクリプトになります。
任意のオブジェクトを作成して認証情報を渡します。

```javascript
// ==UserScript==
// @name         AuthToken Injection
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        http://localhost:3000/spa/*
// @grant        none
// @run-at document-start
// ==/UserScript==

(function() {
    'use strict';
　　　window.AppConfig = window.AppConfig || {};
　　　window.AppConfig.authToken = "xxxxx-11111";
})();

```

ポイントは`@run-at`でスクリプトの実行タイミングを`document-start`に指定することです。
DOMの構築が終わって他のコンテンツのロードが始まる前にオブジェクトを注入する必要があります。


### 最後に
サーバ側で開発時は認証情報を無視するといったこともできるので、今回の方法以外にもいろいろあると思います。
JavaからWinShotを利用する


## WinShotのコマンドライン引数
WinShotは常駐型のソフトだという印象が強いですが、実はコマンドラインからも利用できます。

コマンドラインには以下のオプションを指定します。

#### 機能オプション(必須)
| 引数 | 動作 |
|----|----|
| -Print または -P | 印刷 |
| -Preview または -V | プレビュー表示 |
| -Copy または -C | クリップボードへコピー |
| -Bitmap または -B | ビットマップ保存 |
| -Jpeg または -J | ＪＰＥＧ保存 | 

#### 対象オプション(必須)
| 引数 | 動作 |
|-----|------|
| -ActiveWindow または-A | アクティブウィンドウ|
| -Desktop または -D | デスクトップ |
| -Rectangle または -R| 矩形範囲指定 |
| -Client または -CL | クライアント領域 |

#### その他オプション(任意)
| 引数 | 動作 |
|-----|------|
| -Negative または -N | ネガポジ反転 |
| -Grayscale または -G | グレースケール変換 |
| -Close または -X | キャプチャ後、常駐せずに終了 |

例えば、アクティブウィンドウをbitmapで保存したい場合は次のように実行します。

```bat
WinShot.exe -B -A -X
```

`-X`が味噌です。WinShotは多重起動できないので`-X`オプションで毎回終了させるようにしなければなりません。また、WinShotが起動した状態ではこのコマンドは利用できません。

出力ディレクトリや細かいオプションはコマンドラインからは指定できません。ちょっと残念。

## Javaからの利用
Javaから利用するには愚直にexecします。はい。それだけです。

```java
Process process = Runtime.getRuntime().exec(new String[]{"[WinShot.exeのパス]", "-J", "-A", "-X"});
process.waitFor();
```

## Javaからの利用例
これの使い所は自動テストのキャプチャでしょう。もちろんテストフレームワークに付属しているスクリーンキャプチャメソッドを使えば良いのでしょうが、界隈によてテストエビデンスはWinShotで取るという暗黙の了解があったりします。暗黙の了解は満たしつつ自動化するための妥協案というわけです。

以下にSelenideと組み合わせた場合の例を示します。この例では次の3箇所でWinShotを使ってスクリーンキャプチャを取る例です。

* Googleのページを開いた直後
* 検索ワードを入力した直後
* 検索結果を表示した直後

```java
import static com.codeborne.selenide.Selenide.*;
import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;

import org.junit.After;
import org.junit.Test;

import com.codeborne.selenide.Condition;

public class HogeTest {

	private static final String WINSHOT_EXE = "C:\\Program Files (x86)\\WinShot\\WinShot.exe";
	private static final String WINSHOT_DEST_DIR = "C:\\winshot";
	private static final String REPORT_DIR = "report";

	@After
	public void スクリーンショットを保存用ディレクトリへ() {
		File reportDir = new File(REPORT_DIR);
		reportDir.mkdirs();
		File winshotDir = new File(WINSHOT_DEST_DIR);
		for (File child : winshotDir.listFiles()) {
			File destFile = new File(reportDir, child.getName());
			child.renameTo(destFile);
		}
	}

	@Test
	public void test() {
		open("http://www.google.co.jp/");
		printScreen();

		$("input[type=text]").val("テスト");
		printScreen();

		$("input[type=text]").pressEnter();
		$("#resultStats").waitUntil(Condition.appear, 5000);
		printScreen();
	}

	private void printScreen() {
		try {
			Process process = Runtime.getRuntime().exec(
					new String[] { WINSHOT_EXE, "-J", "-A", "-X" });
			process.waitFor();
			int exitCode = process.exitValue();
			if (exitCode != 0) {
				fail("スクリーンショットを撮るのに失敗。終了コード:" + exitCode);
			}
		} catch (IOException | InterruptedException e) {
			fail("スクリーンショットを撮るのに失敗。");
		}
	}

}
```

【結果】
<img src="https://qiita-image-store.s3.amazonaws.com/0/29682/5d47087d-baf2-08c8-fdd2-e66254f766a1.jpeg" width="70%">
<img src="https://qiita-image-store.s3.amazonaws.com/0/29682/dfd8476e-d732-46f8-fb44-7f0a496bd4a6.jpeg" width="70%">
<img src="https://qiita-image-store.s3.amazonaws.com/0/29682/5f12b067-3b6b-a3fd-3df5-18865255ce5c.jpeg" width="70%">

実行すると定数`REPORT_DIR`に定義したディレクトリにキャプチャした画像が格納されます。テスト内ではだだだっとキャプチャをとって、`@After`でファイルを移動するように作っています。実際は複数のテストがあるでしょうから、ファイル移動の部分はもう少し作り込む必要があるでしょう。


今回は以上