OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleHomeで使える（not 有用）アプリの作り方

# はじめに
先日、日本でも発売されたGoogle Home。
何が出来るのかいまいちわからずに買っちゃったけど、自分でアプリ（って言うのかな？）作れるらしいので
試してみました。
あんまり情報が無かったので何かちょっとでも今後の参考になれば幸いです。

# アプリの作り方
1. [Action On Google](https://developers.google.com/actions/?utm_campaign=product%20area_launch_actionsgoogle_120816&utm_source=gdev&utm_medium=blog)のサイトを開く
2. GoogleHomeにログインしているのと同じアカウントでログイン
3. 右上にActions Consoleってボタンがあるのでポチー
4. Add/Import Porjectをポチー
5. Project Nameは適当に、Country/regionはJapanを選んでCreate Projectをポチー
6. DialogFlow、Actions SDK、Converse.AIとか色々出てくると思うので、好きなもののBUILDを選んでポチー（今回はDialogFlowを選びました）
7. CREATE ACTIONS ON DIALOGFLOWをポチー
8. Agent Nameをよしなに決めてDEFAULT LANGUAGEでJapaneseを選んだらSAVEをポチー
9. 画面左側のIntentsってところの＋ボタンをポチーしてIntentsを追加する
10. Intents Nameは適当、User Saysに自分が言うセリフ、Text ResponseにGoogleHomeに返してほしいセリフを入れてSAVEをポチー

以上でアプリは完成です。画面右にTry it nowってところがあると思うので試しにUser Saysに入れたセリフを入れてみましょう。
間違いがなければDEFAULT RESPONSEに望んだ答えが返ってくるはずです。

# アプリをGoogle Homeで試す
これだけではまだ実機で試せないので、以下の手順を実行します。
1. Dialog flowで画面左側にIntegrationsという項目があるのでポチー
2. Google Assistantが一番左上にあるので選んで、UPDATE DRAFTをポチー
3. Action On Googleのページに飛ばされるのでAppInformationのADDをポチー
4. 必要な情報を適当に埋めてSAVEをポチー（情報が足りないと怒られるので地道に埋めてください。プライバシーポリシーとかはhoge.comとかでも大丈夫です）
5. Account linkingでImplicitを選んで適当に情報を入れる（これも全部hogeでいけました）
6. TEST DRAFTをポチー
これで実機で試せるようになるはずです。
実機に向かって「Ok, google. (アプリ名)に繋いで」と話しかければアプリが起動するのでLet's対話！

# 実行イメージ
youtubeに音声のみ動画をあげてみました。
こんな感じで会話ができます。
https://youtu.be/Q6PT7BzC4_8

#最後に
まだ決め打ちの会話しかできないし、特に有益なことは出来てませんが、
思ったより簡単に作ることが出来たので個人的には割りと満足してます。
まだまだ情報が少ないので今後に期待したいところです（他力本願）
最初から使える設計をしよう

ソースコードなるべく最初から使える設計にしたいものです。

そのような設計をするために個人的に思っていることをメモします。
　いったんチーム内にリリースしていまうと、なかなかディレクトリ構成でさえ、変えにくくなったりすることがあります。ですから、最初から問題のないディレクトリ構成で、問題のない関数・メソッドのインターフェースでリリースすることです。最初から使える設計にする指針があると考えます。それをこの記事で紹介します。

（今までに、このサイトの記事に書いていることとダブっているかと思います。）

## ディレクトリ構成
### **バージョン管理しているディレクトリの中に出力データを書き込まない**

ソースコード・入力データのサンプルなどはバージョン管理の対象ですし、必要な一式をまとめて圧縮して配布したりします。
そのときに、実行結果の出力が、それらのディレクトリのツリー構造の中にあると、必要な一式をまとめて圧縮して配布する前に、出力データを取り除く作業が必要になってしまいます。

### **出力データディレクトリは入力データディレクトリと別のディレクトリにする。**
理由：出力ディレクトリはバージョン管理の必要がない。
　clean するときに、出力データが特定の出力ディレクトリに集中していれば、clean しやすい。
　入力データは時として大容量で、バージョン管理の対象外になる。
　入力データディレクトリには、入力データ以外のものを書き込まない。そうすれば、入力データディレクトリをまとめて圧縮して管理すればよくなる。圧縮したものを、ネットワークの共有保管場所におけばよくなる。

### **出力データディレクトリはスクリプトのディレクトリ、ソースコードディレクトリとも別のディレクトリにする。**
バージョン管理するディレクトリに出力データを書き込まないようにする。そうすることで、スクリプトディレクトリやソースコードディレクトリに余分なものが入ることを防げる。
そうすることでバージョン管理が楽になる。

## 関数・メソッドの引数

### **画像の入力、文字列の入力、独自型の入力には全てconst 属性をつける。**

### **入力の引数には全てconst 属性をつける。**

### **インスタンスを引数渡しするときは、参照渡しする。**
参照渡しすることで、不要なオブジェクトのコピーを生成することを予防する。
参照渡しにすることで、ポインタ渡しを使わない。このことでポインタにまつわる様々なやっかいごとを予防する。

## ループ
### **std::vectorの各要素にアクセスする際には、for 文の上限を .size()メソッドをfor文の外で一回呼べば十分なようにする。**
以下は推奨しないコード

```c++
auto a=std::vector<cv::Point3d>;
何かデータを追加する処理;

for (size_t i=0 ; i <a.size() ; i++){
   // a[i] にアクセスする処理
   std::cout << a[i] << std::endl;
}
```

```c++
auto a=std::vector<cv::Point3d>;

何かデータを追加する処理;

size_t n = a.size();
for (size_t i=0 ; i < n ; i++){
   // a[i] にアクセスする処理
   std::cout << a[i] << std::endl;
}
```

### **std::forward_list, std::listの各要素に全てアクセスする際には、イテレータを使う。**
listの添え字でアクセスすると、a[i] をa[0]から毎回リスト構造を最初から順にたどっていくので、その分の処理で遅くなってしまう。

イテレータを使うことでその分が回避される。

[比較1：「■番目の要素にアクセスする」ための時間](https://qiita.com/h_hiro_/items/a83a8fd2391d4a3f0e1c#%E6%AF%94%E8%BC%831%E7%95%AA%E7%9B%AE%E3%81%AE%E8%A6%81%E7%B4%A0%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E6%99%82%E9%96%93)

[C++ 単方向リストクラス std::forward_list 入門](http://vivi.dyndns.org/tech/cpp/forward_list.html)

### **事前に大きさが分かっているstd::vector型は最初から領域を確保する**
reserve() を使う。


以上のように、予めわかっている設計指針を実装してからリリースするのが得策だと思っています。

付記：
　以上、分かっている人にとっては自明なことだとは思いますが、そうでない人のために書いてみました。

----

class の実装をするときには、１つのクラスになんでもかんでもぶちこまない。１つの意味あいが明確な範囲でクラスに実装する。


参考記事: [C++高速化](https://heavywatal.github.io/cxx/speed.html)
スクリプト内でpartedを使ってパーティション作成

シェルスクリプト上でパーティションを区切る場面があったので、メモついでに
スクリプトでは対話でのパーティション作成は使えないので、非対話ができるものを調べた結果`parted`コマンドを使用しました。

`parted`はあまり詳しく理解できてないため、やり方のみを記述します。
スクリプトでパーティション作成を急いでる方や、その場しのぎでパーティション作成をしたい方などは見ていった方がいいかもしれません。



# 参考にさせてもらったサイト
・https://qiita.com/ngyuki/items/93da394fd0847ed5155e
・https://www.xmisao.com/2013/09/27/parted-warning-the-resulting-partition-is-not-properly-aligned-for-best-performance.html

# パーティション構成
とりあえずLinuxが起動するような構成にしてあります。
HDDは500GB 、メモリは8GBを想定しています。

| マウントポイント | ファイルシステム | サイズ (byte) | デバイス名 |
|:-:|:-:|:-:|:-:|
| /boot  | ext4  | 500 M  | /dev/sda1  |
| /  | ext4  | 490 G  | /dev/Vol00/LogVol00  |
| swap  | swap  | 8 G  | /dev/Vol00/LogVol01  |


# パーティションを区切る
#### ---`/boot`のパーティション作成---

```
# parted -s -a optimal /dev/sda -- mklabel msdos mkpart primary ext4 2048s 501M set 1 boot on
```
2048セクタから始めないと警告が出ます。詳しくは参考サイトの2つ目を参照してください。

<br>
#### ---`/`と`swap`をLVMで作成---


```
# parted -s -a optimal /dev/sda -- mkpart primary 501M -1 set 2 lvm on

# pvcreate /dev/sda2
# vgcreate Vol00 /dev/sda2
# lvcreate -L 490000m -n LogVol00 Vol00
# lvcreate -L 8000m -n LogVol01 Vol00
```
ファイルシステムを作成

```
# mkfs.ext4 -j /dev/sda1
# mkfs.ext4 -j /dev/Vol00/LogVol00
# mkswap /dev/Vol00/LogVol01
```
<br>
これらをシェルスクリプトにまとめたら、僕と同じパーティション構成ができると思います。


# ひとりごと
最初の`/boot`パーティションを区切る段階で`ext4`を指定してるのでファイルシステムをわざわざ作らなくてもいいかな〜♪　って思っていたら、`MondoRescue`でマシンをリストアする際に`/dev/sda1`でエラー吐かれました。
`/dev/sda1`に結局ファイルシステムを作ることにしたけど、それだったら`parted`の段階で`ext4`の指定をしなくてもいいのでは、と思いながらも検証しませんでした。ごめんなさい
正規表現を使った辞書キー指定

# 使い方
ありそうでなかったので書いた。メモとして残します。
辞書を`rdict`型にキャストすれば正規表現もキー値として使えるようになるやつです。
標準辞書型を継承しているので、普通の機能も使えると思います。


```py
>>d = {'#a': 'item1', '#b': 'item2','q#': 'item3'}
>>rd = rdict(d)

>>print rd[".*"]
['item2', 'item1', 'item3']

>>print rd["#.*"]
['item2', 'item1']

>>print rd["#a"]
item1

>>print rd.keys()
['#b', '#a', 'q#']
```


# ソース
```py:rdict.py
#もっといいやり方あれば教えて欲しいです。
import re
class rdict(dict):
	def __getitem__(self, key):
		try:
			return super(rdict, self).__getitem__(key)
		except:
			try:
				ret=[]
				for i in self.keys():
					m= re.match("^"+key+"$",i)
					if m:ret.append( super(rdict, self).__getitem__(m.group(0)) )
			except:raise(KeyError(key))
		return ret
```

#制限
辞書にキー`.*`が含まれていると、正規表現`.*`ではそのキーの値のみを返します。（キー全てにマッチできない）
FileSystemObject多用時はキャッシュすると良い

# 発端

MSDNを見ていると「[FileSystemObject のプログラミング](https://msdn.microsoft.com/ja-jp/library/cc392177.aspx "FileSystemObject のプログラミング")」のページに以下のような記述がありました。

> FileSystemObject のインスタンスは、ほかのインスタンスを何回作成しても 1 つしか作成されません。

この記述の内容を確認するために、簡単に検証を行ってみました。

# 検証

## 1. 同じインスタンスなのか？

おもむろに以下のコードを実行してみましたが、Falseになりました。

```vbnet
Debug.Print CreateObject("Scripting.FileSystemObject") Is CreateObject("Scripting.FileSystemObject")
' -> False
```

少なくともGetObjectのように同じインスタンスを返すわけでは無さそうです。

## 2. インスタンスにかかる時間は？

以下のコードでインスタンス（CreateObject）にかかる時間を簡単に計測してみました。

普通にインスタンスをして即破棄[^1]する場合と、1個インスタンスを確保してからインスタンスをする場合の2パターンの確認です。

[^1]: VBAでは参照カウント方式でオブジェクトの寿命を管理しているはずなので、変数に入れなければ破棄される。

### 使ったコード

```vbnet:インスタンス時間計測
Sub Test_CreateObjectTime()
    Const CREATE_COUNT& = 1000&
    Const PROG_ID$ = "Scripting.FileSystemObject"
    
    Dim i&, startTime!, timeSpanSec!
    
    '毎回新規インスタンス
    startTime = Timer
    For i = 1 To CREATE_COUNT
        Call CreateObject(PROG_ID)
    Next i
    timeSpanSec = Timer - startTime
    Debug.Print "キャッシュなし", timeSpanSec; "sec"
    
    
    '1個インスタンスを保持しつつ新規インスタンス
    startTime = Timer
    
    Dim cache As Object
    Set cache = CreateObject(PROG_ID)
    
    For i = 1 To CREATE_COUNT
        Call CreateObject(PROG_ID)
    Next i
    
    Set cache = Nothing
    
    timeSpanSec = Timer - startTime
    Debug.Print "キャッシュあり", timeSpanSec; "sec"
    
End Sub
```

### 結果

私のPCで実行した場合、以下のような結果となりました。

```text:結果（イミディエイトウィンドウ）
キャッシュなし               0.9960938 sec
キャッシュあり               0.0078125 sec
```

キャッシュあり（インスタンスを保持した方）の方が明らかに、処理時間が短くなっていることがわかります。

# この挙動を有効利用するには？

処理中に何度も`Scripting.FileSystemObject`を使用する場合は、毎回インスタンスを破棄するのでは無く、どこかでインスタンスを保持しておいた方が処理時間的には良いということになります（その分メモリを使用しますが）。

## `Microsoft Scripting Runtime`を参照している場合

```vbnet
Public FSO As New Scripting.FileSystemObject
```

New 付き型宣言でグローバル変数を宣言しておき、宣言した変数経由で使用することで VBA側にインスタンスと参照の保持を任せることができます。

## 参照設定なしの場合

以下のように静的変数を使うことでキャッシュのようなことができます。

```vbnet
Property Get FSO() As Object 'Scripting.FileSystemObject
    Static fso_ As Object
    If fso_ Is Nothing Then Set fso_ = CreateObject("Scripting.FileSystemObject")
    Set FSO = fso_
End Property
```

Static宣言の是非もあるので、一つの考え方としてどうぞ。

## WSH

WSF形式を使用すると、object タグでグローバルなオブジェクト定数を宣言できます。

```xml:fsotest.wsf
<?XML version="1.0" standalone="yes" ?>
<package>
	<job id="fsoTestJob">
		<!-- グローバルで宣言・インスタンスされるオブジェクト -->
		<object id="FSO" progid="Scripting.FileSystemObject" reference="yes" />
		<script language="VBScript"><![CDATA[
Option Explicit

'後は普通のVBScript
MsgBox TypeName(FSO)

		]]></script>
	</job>
</package>
```

通常のVBScript（.vbs）だと、グローバル変数は外部から書き換えの可能性があるため少々面倒になりそうです。
CPS/IoTの総合展示会二年目のCEATEC JAPANにみる新技術

10月3日～6日、幕張メッセで開催されたCEATEC JAPAN。これまでの家電見本市からCPS/IoTの総合展示会に変わって二年目、「つながる社会、共創する未来」をメッセージとして、日本の成長戦略や未来を世界に発信する「Society 5.0」の展示会として、どのような新たな「CEATEC体験」が経験できたのか、オンラインメディアの記事をピックアツプしてご紹介します。

※下記サイトからの転載。ビッグデータ・AIなどに関するトピックを毎週取り上げています。
[TechCrowd: https://www.techcrowd.jp/related/](https://www.techcrowd.jp/related/)

#[IoTのパナソニックとTVのシャープ、両社に見るCEATECのゆくえ] (http://news.mynavi.jp/articles/2017/10/12/pana_sharp/)

マイナビニュースのCEATEC JAPNレポート記事です。CPS/IoTの総合展示会にコンセプトを変更して二年目の展示会の様子を、対照的な展示の仕方をしたパナソニックとシャープを例にとって紹介しています。

パナソニックブースの特徴を、薄型テレビを1台も展示しなかったことをまず指摘して説明の導入としています。またメインステージとなる部分を「Open Innovation Lab」と呼ぶステージとして「来場者との対話を通してオープンイノベーションの創出を目指す」内容としているとしていると指摘しています。展示としてピツクアップしているものは以下の通り
・B2B向けIoTサービス「μSockets」を活用したソリューション展示
・RFIDプロトコルを利用して端末への給電と通信を同時に行うマイクロ無線給電
・幼児向けソーシャルロボット「cocotto」
・温度・湿度などの計測が可能なデバイスを衣服に縫い付けることができるウェアラブルメーカーパッチ
・顔を撮影した静止画上で、本物のメイクをするかのように自由にデザインができる「メイクアップデザインツール」
など

#[三菱UFJ、仮想通貨 MUFGコイン初公開　スマホアプリで送金] (http://www.itmedia.co.jp/news/articles/1710/02/news105.html)

ITmedia NEWSのCEATEC JAPANレポートです。CEATEC JAPANでは、三大メガバンクが初めてそろって出展や講演を行ったことも各種メディアで取り上げられていますが、三菱東京UFJ銀行が今年5月に試験導入した仮想通貨「MUFGコイン」のデモンストレーションを披露したことをレポートしている記事です。

CEATECのブースでは、ジムのポイントとMUFGコインをひも付ける仮想の事例を紹介。ジムのトレーニング中、ダンベルを持ち上げた回数に応じ、ポイントをMUFGコインとして付与。自動販売機での飲料購入に使えるというデモンストレーションを行っていました。一般向けイベントでの初めての公開。

MUFGコインは、ブロックチェーン技術を活用した、1コイン = 1円の価値をもつデジタル通貨。MUFGコインは、三菱東京UFJ銀行が2017年5月から同行員向けに試験導入中。スマホアプリの画面上で預金口座の残高を1円＝1コインに交換し、事前登録した「友達」と取引できる。Suicaなどの電子マネーとは違い、コインから円に還元することも可能。友達同士で食事代などを精算できる「ワリカン」機能も搭載。


#[CEATEC 2017で見えた次世代のIoT活用、7社ブースを詳細レポート] (https://www.sbbit.jp/article/cont1/34103)

ビジネス+ITのCEATEC 2017レポート記事です。CEATECのコンセプトのひとつでもある
IoTに関連した展示を行っていた、オムロン、デンソー、KDDI、シャープ、富士通、ユカイ工学研究所、カシオなどの展示を紹介しています。

まずはオムロンブースで行われていた、卓球ロボットの紹介。各種メディアでも紹介されていたものです。また、オムロンブースでの注目展示として紹介しているのが、来るべき自動運転時代を見据えた、「ドライバー見守り車載センサー」を搭載したコックピットの展示。時系列ディープラーニングをさらに進化させ、ドライバーの運転集中状態に関して、「運転の状況を注視しているか」「どれだけ早く運転に復帰できるか」「運転席にちゃんと着いているか」という3つの指標で同時に判断しているとのこと。

自動車部品関連メーカー大手のデンソーの展示としては、超小型EVに、VRシステムをまるごと実装して空飛ぶ車から世界旅行を体感できるデモをとりあげています。

KDDIブースではテレイグジスタンスのデモをピックアップ。遠隔地から自分の分身となるアバターロボットを動かせるというもので、もうすぐやってくる5G時代の高速通信を活用した新技術の例としての展示のようです。


#[社会実装に向け着実に進化、CEATEC 2017で見たAI] (http://eetimes.jp/ee/articles/1710/12/news078.html)

EETimes JapanのCEATEC JAPANレポートです。CEATECの「AI-人工知能パビリオン」で展示されていた、産業技術総合研究所(産総研)やNextremerのロボット制御システムや対話システムなどを紹介しています。

まずは、産総研のタオルを折りたたむことができるロボットを紹介しています。深層学習(ディープラーニング)技術を応用したロボットで、これまでのロボットでは扱うことが困難といわれてきたタオルやシャツのような柔らかいものも扱うことをデモしています。折りたたみ作業を事前に人手で30回学習させておくことにより、かなり高い確率でタオルの折りたたみに成功していたとのこと。

またNextremerが行っていた、AI技術を用いた移動マニピュレーターのデモも紹介しています。シミュレーションで学習した結果に基づき、カメラが捉えた映像から円筒形や直方体、立方体といった形状や色を見極め、形状ごとに異なるつかみ方などの動作方法を判断して、マニピュレーター(ロボットの腕)を適切に制御しているとのこと。


#[CEATEC 2017で見た「明日の技術」いろいろ] (http://news.mynavi.jp/articles/2017/10/09/ceatec02/)

こちらもマイナビニュースのCEATEC JAPANレポートです。最初に紹介しているのは、三菱電機ブースの「AIを用いた音声分離技術」。独自の「ディープクラスタリング」技術によって、一本のマイクに対して複数人が同時に話しかけても、その音声を話者ごとに分離するとのこと。

すでに「3人が同時に話している場合の音声分離まで実証している」とのこと。いわゆる深層学習(ディープラーニング)に類する技術のようです。

その他、MUFGの展示の中からAIによる為替予測などを紹介しています。
Unityで画像をPOSTし，PHPでサーバに保存する

Unityから画像データをPOSTし，httpサーバーにファイルとして保存する方法です．データベースは用いません．画像以外にも応用可能です．

# 環境
* クライアント側
  + macOS Sierra 10.12.6
  + Unity 5.6.3p2
* サーバー側
  + CentOS Linux release 7.4.1708
  + Apache/2.4.6
  + PHP 7.1.5
  + IPアドレスは192.168.0.10とします

# クライアント側
```csharp:FileUploader.cs
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using System.IO;

public class FileUploader : MonoBehaviour {

	void Start() {
		StartCoroutine (UploadFile ());
	}

	IEnumerator UploadFile() {
		string fileName = "hoge.jpg";
		string filePath = Application.dataPath + "/" + fileName;
		// 画像ファイルをbyte配列に格納
		byte[] img = File.ReadAllBytes (filePath);

		// formにバイナリデータを追加
		WWWForm form = new WWWForm ();
		form.AddBinaryData ("file", img, fileName, "image/jpeg");
		// HTTPリクエストを送る
		UnityWebRequest request = UnityWebRequest.Post ("http://192.168.0.10/upload.php", form);
		yield return request.Send ();

		if (request.isError) {
			// POSTに失敗した場合，エラーログを出力
			Debug.Log (request.error);
		} else {
			// POSTに成功した場合，レスポンスコードを出力
			Debug.Log (request.responseCode);
		}
	}
}
```
新メソッドのIMultipartFormSectionを使って実装したかったのですが，うまく動かなかったのでレガシーメソッドのWWWFormを使用しています．
とりあえず使ってみたい場合は，Assetsディレクトリ直下にhoge.jpgを配置し，FileUploader.csをMainCameraにアタッチして下さい．

# サーバー側
```php:upload.php
<?php
    // アップロードされたファイルがjpeg形式か確認
    if ($_FILES["file"]["type"] == "image/jpeg") {
        if ($_FILES["file"]["error"] > 0) {
            echo "Return Code:" . $_FILES["file"]["error"] . "";
        } else {
            echo "Upload:" . $_FILES["file"]["name"] . "";
            echo "Type:" . $_FILES["file"]["type"] . "";
            echo "Size:" . ($_FILES["file"]["size"] / 1024) . "Kb";
            echo "Temp file:" . $_FILES["file"]["tmp_name"] . "";
            
            // サーバー上に既にファイルが存在していないか確認
            if (file_exists("upload/" . $_FILES["file"]["name"])) {
                echo $_FILES["file"]["name"] . "already exists.";
            } else {
                move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
                echo "Stored in:" . "upload/" . $_FILES["file"]["name"];
            }
        }
    } else {
        echo "Invalid file";
    }
?>
```

Apacheのドキュメント・ルートは/var/www/html，アップロード先のディレクトリは/var/www/html/uploadとしています．アップロード先のディレクトリにはapacheの権限で書き込みができることが必要です．
新人フロントエンジニアがdockerに挑戦した話

#経緯
今携わってる案件でvagrantからdockerへの乗り換えがあり
担当された先輩が全てやってくれたおかげで
dockerが使えるようになりましたが
結局dockerの導入がわからずじまいで…

##宣伝
アプリ作るまでのお話を書きました。
読んでいただけると嬉しです☺️
[【3日で実装・公開】エモいアートな画像生成アプリ開発 - Qiita](https://qiita.com/rantaro/items/fdb7bbd55a57c68db834)

#今回の目標
独りで土日の間でdockerを落としてきて苦手なコマンド周りを触ってみる

#やってみたこと
いきなり触っても分からなくなるのが目に見えてたので
他の方の記事を参考にさせて頂きました

　Mac OS X へのDockerのインストール方法
　　https://qiita.com/hshimo/items/e24b1fbfbf775ec7c941
　(初心者向け)Dockerの使い方
　　https://qiita.com/butada/items/3e6cd338cb703eef64b4

###まずはdockerをダウンロード
　https://docs.docker.com/
 　まぁまずは問題なし！見慣れたクジラさんをドラッグ&ドロップ。
<img width="918" alt="docker.png" src="https://qiita-image-store.s3.amazonaws.com/0/199085/4bc899cf-ab7e-a7ed-bdfa-89b41d471889.png">

###落としてきたdockerを起動
　・PCに落としてきたdockerを起動
　・PCに変更を加えるとかでパスワード入力
　・バーに見慣れたクジラマークが追加されて
　・docker running が出ました！
<img width="342" alt="docker2.png" src="https://qiita-image-store.s3.amazonaws.com/0/199085/8944c97b-4b78-9ecc-4073-eea7f1381951.png">
　
正直ここまで来れるか不安だったので一安心:relaxed:

###えっ？ID作った覚えないけど？
<img width="492" alt="docker3.png" src="https://qiita-image-store.s3.amazonaws.com/0/199085/cafa8e67-e226-fc8d-ad05-3772430339a9.png">

下にアカウント作れって書いてありますね、はい。
というわけで作成
<img width="1217" alt="docker4.png" src="https://qiita-image-store.s3.amazonaws.com/0/199085/165014f4-26bf-fe8f-6216-7e84bf340ec0.png">

###アカウント作成
ユーザーネームで少し手間取りましたが
アカウントを無事作成できログインできました。
アカウントがちゃんとできるとメールが届きました。
<img width="535" alt="docker5.png" src="https://qiita-image-store.s3.amazonaws.com/0/199085/9467fb0b-9a20-7268-273f-140243719ad5.png">

作成したアカウン無事でログインできました！

##さあ触ってみよう！

と思いましたが長くなったので今度続きを書こうと思います。

先日参加したPHPカンファレンス２０１７で
docoker関連の講話を聞き興味が湧いたので
（半分くらいちんぷんかんだったのは自分だけの秘密）

今回dockerを触ってみました！

諸先輩方に教わりつつ参考記事を読みながら
今後も勉強して行こうと思います。

##宣伝
アプリ作るまでのお話を書きました。
読んでいただけると嬉しです☺️
[【3日で実装・公開】エモいアートな画像生成アプリ開発 - Qiita](https://qiita.com/rantaro/items/fdb7bbd55a57c68db834)
herokuコマンド集

## ログを見る

```
heroku logs --tail
```

アプリを指定する場合は

```
heroku logs -t --app アプリ名
```

## マイグレート実行

```
heroku run rails db:migrate
```

アプリ指定

```
heroku run rails db:migrate --app アプリ名
```

## アプリ作成

```
$ heroku create
Creating app... done.
```

# アプリを更新する

```
$ git push heroku master
```
RaspberryでNASを構築するために参照したリンクまとめ

#動機
Linuxサーバを扱うプロジェクトに半年ほど在籍した経験をプライベートにも活かしたいと思い、放置していたRaspberrypiを活用する方法を考えた。

#ゴール
・嫁のItunesと私のItunesの参照先を統一
・画像フォルダの統一（クリスマスに親戚にフォトフレームを送る準備）

#前提
Raspberry pi 2

#手順
##Raspberry pi に NOOBSをインストールする
第56回「改めましてラズベリーパイの基本！(1) Raspberry Pi　NOOBSインストール 2017年度版」
http://deviceplus.jp/hobby/raspberrypi_entry_056/

##wifi接続のセットアップ
raspberry pi2 で 無線 LAN 設定まで
https://qiita.com/hotchpotch/items/dfcb9bd02baf67223eb0

##ハードディスクを認識させる
RaspberryPi2でMacとWindows両対応のNASを構築する
https://qiita.com/rkonno/items/54b2e4b8770c8b0b2bcd

##トラブル
Vimで方向キーを押すとABCDが出る問題を直す
http://marupeke296.com/IKDADV_PI_ABCDProb.html

#参考文献
2017年ラズベリーパイ各種OS・ディストリビューションまとめ1(汎用編)
https://itdecoboconikki.com/2017/03/17/2017-raspberry-pi-os-curate-1/

Raspberry PiにSambaをセットアップ！NASは実用レベルで使えるか？
http://yurugadge-channel.com/article/179603903.html

Raspberry PiでRAID1付きのNASを構築してみた
http://monakaice88.hatenablog.com/entry/2017/04/10/070000

ラズベリーパイで外付けHDDをNAS化するよ！
http://raspberrypi.blog.fc2.com/blog-entry-51.html
Rails で JS を Webpacker 管理にしたら、 data-confirm が動かなくなった

JS と CSS を Webpacker 管理にしたら、
`link_to, method: :delete, data: { confirm: 'Are you sure?' }` が動かなくなった。

```haml:application.html.haml(diff)
-    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
-    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
+    = javascript_pack_tag 'application'
+    = stylesheet_pack_tag 'application'
```

# 環境

- Rails 5.1.4

# 原因

[Ruby on Rails 5\.1リリースノート \| Rails ガイド](https://railsguides.jp/5_1_release_notes.html#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%A7%E3%81%AEjquery%E4%BE%9D%E5%AD%98%E3%82%92%E5%BB%83%E6%AD%A2)

> 従来のRailsでは、data-remoteやdata-confirmについてはjQueryに依存し、その他の機能をUnobtrusive JavaScript（UJS: 控えめなJavaScript）に依存する形で機能を提供していました。Rails 5.1からはこれらの依存が解消され、UJSはvanilla JavaScript（=純粋なJavaScript）で書き直されました。このコードはAction View内部でrails-ujsとしてリリースされています。

Rails5.1 では、 `data-remote` や `data-confirm` は rails-ujs に依存している。
`app/assets/javascripts/application.js` で `rails-ujs` を読み込んでいるが、
`application.html.haml` で `app/assets/javascripts/application.js` の読み込みを外したため。

# 解決策

**※2017/12/05に修正しました**

rails-ujs を yarn で入れて、読み込む。

```bash
yarn add rails-ujs
```

```js:app/javascript/packs/application.js
import Rails from 'rails-ujs';
Rails.start();
```

これで、 `javascript_include_tag` は削除できる。

```js:app/views/layouts/application.html.haml(diff)
     %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
     %title PomodoroRails
     = csrf_meta_tags
-    = javascript_include_tag 'application'
     = javascript_pack_tag 'application'
     = stylesheet_pack_tag 'application'
   %body
```

- 参考
    - [import Rails from 'rails\-ujs';
Rails\.start\(\);](http://docs.komagata.org/5456)
    - [rails/actionview/app/assets/javascripts at master · rails/rails](https://github.com/rails/rails/tree/master/actionview/app/assets/javascripts)
MacにNode.jsのセットアップ（Homebrewは使ってはいけない）

MacにNode.jsのセットアップをするにあたり、下記の記事が非常に参考になりますが、2017/10/13現時点でつまずいたので、インストールメモ。

- [Macにnode.jsをインストールする手順](https://qiita.com/akakuro43/items/600e7e4695588ab2958d)

- でてくるツール
 - Homebrew: macのパッケージ管理ソフト
 - Nodebrew: Node.jsのバージョン管理ソフト



# 結論から

下記の公式のインストール手順どおり、Homebrewではなくcurlコマンドでインストールが必要です

```
$ curl -L git.io/nodebrew | perl - setup

set PATH

$ echo 'export PATH=$PATH:$HOME/.nodebrew/current/bin' >> ~/.bash_profile
$ source ~/.bash_profile
$ echo $PATH

check

$ nodebrew -v
```

- ref: https://github.com/hokaccha/nodebrew#install

# Homebrewを使った場合

- Homebrewでnodeberewをいれると、下記エラーでnodeが入れられない。


```
$ nodebrew install-binary latest
〜〜
curl: (23) Failed writing body (0 != 3568)
```

- もし、Homebrewでnodeberewをいれてしまったら、アンインストール

```
$ homebrew  uninstall nodebrew
$ nodebrew -v
```
gulpで「Error: Invalid glob argument: undefined」エラーが出た時に解決した方法



gulpgile.jsをいじっていたらエラーが出て解決に時間がかかったが、結果的に本当に単純なミスだった。


エラーの内容は以下

```
Error: Invalid glob argument: undefined
    at Gulp.src (/xxxx/xxxx/xxxx/node_modules/vinyl-fs/lib/src/index.js:20:11)
    at Gulp.<anonymous> (/xxxx/xxxx/xxxx/gulpfile.js:103:7)
    at module.exports (/xxxx/xxxx/xxxx/node_modules/orchestrator/lib/runTask.js:34:7)
    at Gulp.Orchestrator._runTask (/xxxx/xxxx/xxxx/node_modules/orchestrator/index.js:273:3)
    at Gulp.Orchestrator._runStep (/xxxx/xxxx/xxxx/node_modules/orchestrator/index.js:214:10)
    at Gulp.Orchestrator.start (/xxxx/xxxx/xxxx/node_modules/orchestrator/index.js:134:8)
    at /usr/local/lib/node_modules/gulp/bin/gulp.js:129:20
    at nextTickCallbackWith0Args (node.js:453:9)
    at process._tickCallback (node.js:382:13)
```

原因がわからずにnode_modulesを再インストールしたりなどいろいろ試したけど解決せず。
なんやかんやで数時間かかってふと気付いた、
呼び出した変数の名前が間違っていたという単純なミス！

``` Wrong
var paths = {
'sassDir' : 'dev/scss/**/*.scss',
};


{中略}
gulp.src(paths.sassSrc)
{中略}

```

``` Correct
var paths = {
'sassDir' : 'dev/scss/**/*.scss',
};


{中略}
gulp.src(paths. sassDir)
{中略}

```


エラーの内容から原因がわからずにものすごく時間を無駄にしてしまいました。
[Python]matplotlibで左右に２つの軸があるグラフを書く方法

二つの軸があるグラフを書くには、１つ目は通常通りの方法でグラフを書き、ax2=ax1.twinx()のようにして生成したax2を使ってx軸が共通で異なるy軸のグラフを書く。

```python
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
%matplotlib inline

fig = plt.figure()
ax1 = fig.add_subplot(111)
t = np.linspace(0.0,10.0,1000)
fs = 1.0
y1 = np.sin(2.0*np.pi*fs*t)
ln1=ax1.plot(t, y1,'C0',label=r'$y=sin(2\pi fst)$')

ax2 = ax1.twinx()
y2 = 10.0*t + 5.0
ln2=ax2.plot(t,y2,'C1',label=r'$y=at+b$')

h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax1.legend(h1+h2, l1+l2, loc='lower right')

ax1.set_xlabel('t')
ax1.set_ylabel(r'$y=sin(2\pi fst)$')
ax1.grid(True)
ax2.set_ylabel(r'$y=at+b$')

```

![download(156).png](https://qiita-image-store.s3.amazonaws.com/0/100523/1f3c8898-bd10-661f-c9bb-92a8049f9674.png)
gulp-sassで「throw er; // Unhandled 'error' event」表示された時に解決した方法


いくつかモジュールのアップデートをしたらいきなりエラーが出るようになりましたが、
node.jsのバージョンを上げることで対応できました。


##同じくgulp-autoprefixerでもエラーが出てしまいまいました

```
Plumber found unhandled error:
 TypeError in plugin 'gulp-autoprefixer'
```

こちらもnode.jsのバージョンを上げたら解消しました。



##node.jsのバージョンを上げる

参考サイト：
http://chaika.hatenablog.com/entry/2016/02/13/073850


##node-sass を rebuild
バージョンを上げるだけだと以下のエラーが出てしまいます。
めっちゃエラー出て焦ります。

```
/xxxxx/xxxxx/xxxx/node_modules/node-sass/lib/binding.js:15
      throw new Error(errors.missingBinary());
      ^

Error: Missing binding /xxxxx/xxxxx/xxxx/node_modules/node-sass/vendor/darwin-x64-48/binding.node
Node Sass could not find a binding for your current environment: OS X 64-bit with Node.js 6.x

Found bindings for the following environments:
  - OS X 64-bit with Node.js 5.x
```

参考：
https://qiita.com/pugiemonn/items/a0ec9b93addfaea3ce78

node-sassをrebuildします。
実行するのはプロジェクトのフォルダでOK。

```
npm rebuild node-sass
```
WindowsでVirtualBoxのターミナルのショートカットキー

本当に大したことないんだけどググってもなかなか出て来ず、結局VirtualBoxを色々いじってわかったことをメモ。

WindowsのVirtualBoxのターミナルのショートカットキー

コピー
>ctrl+shift+c


ペースト
>ctrl+shift+v
Pythonで簡単なユニットテスト（超初心者向け）

最近Pythonでユニットテストの勉強をしたので備忘録も兼ねて簡単に記事にしておく

## 実行環境
- Python 3.5.1

## ライブラリ
今回Pythonでユニットテストを行うにあたって[unittest](https://docs.python.jp/3/library/unittest.html)というライブラリを使用する。
unittestは標準でインストールされているライブラリのためpipでインストールする必要がなく非常にお手軽である。

## 実践
まずはこの簡単な足し算のプログラムをテストする。

```py3:math.py
def add(a, b):
    return a + b
```
テストするプログラムはこんな感じ

```py3:test_math.py
import unittest
from Math import *


class TestMath(unittest.TestCase):
    def test_add(self):
        value1 = 2
        value2 = 6
        expected = 8
        actual = add(value1, value2)
        self.assertEqual(expected, actual)


if __name__ == "__main__":
    unittest.main()
```

### 手順

- `import unittest`で`unittest`を読み込みます。
- `unittest.TestCase`を継承したクラスを作成します。
- テストを行う関数を定義します。
- `unittest.main()`でテストを実行します。

### 実行

```
$ python test_math.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
```

テストが成功するとこのように表示されます。

## テストの前後に処理を行う

それぞれのユニットテストを行うにあたってテストの前後に処理を挟みたい時があります。
`unittest`にはそのためのメソッドが用意されており、ユニットテスト開始前に実行されるメソッドは`setUp()`、終了時に実行されるメソッドは`tearDown()`が使用できます。
実際に実行して見ましょう。

```py3:math.py
def add(a, b):
    return a + b


def sub(a, b):
    return a - b
```

先ほどの`math.py`にsub（引き算）メソッドを追加しました。
`add()`と`sub()`を一つのテストクラスで実行した場合に、それぞれのユニットテスト実行前後に処理を挟めるようにして見ましょう。

```py3:test_math.py
import unittest
from Math import *


class TestMath(unittest.TestCase):
    def setUp(self):
        print("setup!")

    def test_add(self):
        print("add!")
        value1 = 2
        value2 = 6
        expected = 8
        actual = add(value1, value2)
        self.assertEqual(expected, actual)

    def test_sub(self):
        print("sub!")
        value1 = 6
        value2 = 2
        expected = 4
        actual = sub(value1, value2)
        self.assertEqual(expected, actual)

    def tearDown(self):
        print("teardown!\n")


if __name__ == "__main__":
    unittest.main()
```

これを実行してやると下記のようになります。

```
setup!
add!
teardown!

.setup!
sub!
teardown!

.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
```

上手くそれぞれのユニットテストの前後に処理が挟まれました。

## まとめて実行
テストモジュールが大量に存在する場合に、いちいち全てを叩いてテストしていてはキリがないので、`unittest`にはまとめて実行できる機能が用意されている。

`$ python -m unittest discover`
上記のように`discover`を使ってやればテストモジュールを一気に実行してくれます。

## 最後に
今回は同じ値だった場合にOKを返す`assertEqual()`メソッドを使いましたが、他にも値が一致しない場合にOKを返す`assertNotEqual()`メソッドなど様々のものがあります。詳しくは公式の[ドキュメント](https://docs.python.jp/3/library/unittest.html)を参照してください。
geometry > 連番から分岐経路番号を取得する実装 (上部:4分岐, 最下部のみ:3分岐)> v0.1, v0.2

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
```

### やろうとしていること

[geometry > sub-triangles > Triangular van der Corput列 > v0.1 > for文のネスト](https://qiita.com/7of9/items/ed5d8146aa03a5be2221)
の方法を使う場合、連番から分岐経路番号(d値)を取得する必要がある。

```math
T(d1, d2) = (T(d1))(d2)
```

```math
T(d1, d2, d3) = ((T(d1))(d2))(d3)
```

のような感じ。

ただし、d1,..d{n_1}は{0..3}の値を取り、最後のdn(例: d3)だけ{1..3}の値を持つとする。
(d値が0となる点は若い連番ですでに取得しているという理由から)

### code v0.1

```idxToDary_171014.py
import numpy as np
import math

# on Python 3.5.2

# v0.1 Oct. 14, 2017
#  - add show_darrays()
#  - add get_depth()


def get_depth(idx):
    if idx == 0:
        return 1
    depth = int(math.log(idx, 4))+1
    return depth


def show_darrays(idx):
    depth = get_depth(idx)
    print(idx, depth, end=': ')

    # MSB
    d1 = 0
    if depth == 1:
        d1 = idx % 4
    else:
        d1 = (idx - 4**(depth-1)) // 4**(depth-2) // (4-1)
    print(d1, end=' ')

    # inbetween
    for mi in range(depth-1, 1, -1):
        dm = (idx - 4**(depth-1)) // (4**(mi-2)) // (4-1) % 4
        print(dm, end=' ')

    # LSB
    last = (idx - 4**(depth-1)) % (4-1) + 1
    if depth > 1:
        print("", last, end='')
    print()


# test
for idx in range(18):
    show_darrays(idx)

show_darrays(63)
show_darrays(64)

show_darrays(255)
show_darrays(256)

show_darrays(1023)
show_darrays(1024)

```

結果[連番、深さ: d値(d1, d2, ...)]の表示順番

```txt:run
0 1: 0 
1 1: 1 
2 1: 2 
3 1: 3 
4 2: 0  1
5 2: 0  2
6 2: 0  3
7 2: 1  1
8 2: 1  2
9 2: 1  3
10 2: 2  1
11 2: 2  2
12 2: 2  3
13 2: 3  1
14 2: 3  2
15 2: 3  3
16 3: 0 0  1
17 3: 0 0  2
63 3: 3 3  3
64 4: 0 0 0  1
255 4: 3 3 3  3
256 5: 0 0 0 0  1
1023 5: 3 3 3 3  3
1024 6: 0 0 0 0 0  1
```

### TODO

きちんとしたテスト関数を作り、本当に正しいか確認する。

## code v0.2

refactoringした。

```idxToDary_171014.py
import numpy as np
import math

# on Python 3.5.2

# v0.2 Oct. 14, 2017
#  - refactor
# v0.1 Oct. 14, 2017
#  - add show_darrays()
#  - add get_depth()


def get_depth(idx):
    if idx == 0:
        return 1
    depth = int(math.log(idx, 4))+1
    return depth


def show_darrays(idx):
    depth = get_depth(idx)
    print(idx, depth, end=': ')

    # MSB
    if depth == 1:
        d1 = idx % 4
        print(d1)
        return d1
    remnant = (idx - 4**(depth-1))
    d1 = remnant // 4**(depth-2) // (4-1)
    print(d1, end=' ')

    # inbetween
    for mi in range(depth-1, 1, -1):
        dm = remnant // (4**(mi-2)) // (4-1) % 4
        print(dm, end=' ')

    # LSB
    last = remnant % (4-1) + 1
    print("", last)


# test
for idx in range(18):
    show_darrays(idx)

show_darrays(63)
show_darrays(64)

show_darrays(255)
show_darrays(256)

show_darrays(1023)
show_darrays(1024)

```
Pandasのデータフレームのカラム追加

▽目的
データフレーム内のカラム(列)のデータを元に新たなカラム(列)を追加する方法の紹介

▽説明
イテレータを用いて1行ずつデータを読み込んで処理する方法もありますが、処理に時間を要しました。
その為、極力pythonのイテレータは使用せず、numpyの行列演算を用いて、処理を行なっています。

今回読み込むcsvデータは、kaggleのタイタニックのデータを用いました。
事前準備として、以下のURLのtrain.csvをダウンロードし、ローカル環境の所定のパスに配置しています。
https://www.kaggle.com/c/titanic/data

処理の概要としては、SibSp列とParch列の数値に+1し、新たに追加したFamilySizeという列に
代入する流れとなっています。

``` Python
import pandas as pd
df = pd.read_csv("train.csv")

print(df.head())

df['FamilySize'] = df['SibSp'] + df['Parch'] + 1
df['IsAlone'] = 0
df.loc[df['FamilySize'] == 1, 'IsAlone'] = 1

print(df.head())
``` 

▽FamilySize列追加前
![追加前.JPG](https://qiita-image-store.s3.amazonaws.com/0/204915/aae8ee59-8789-93ed-3ac5-8d518d12f969.jpeg)

▽FamilySize列追加後
![追加後.JPG](https://qiita-image-store.s3.amazonaws.com/0/204915/10b52aa9-1f6a-8e12-b696-12baa0c66322.jpeg)
Windows版のvagrantでproviderをvirtualboxにした場合、共有フォルダ下にシンボリックリンクが張れない場合の対処方法

# 問題

Windows版のvagrantでproviderをvirtualboxにした場合、共有フォルダにはシンボリックリンクを作成することができません。そのため、npmやbundler、composer等でパッケージを導入する際、シンボリックリンクを作成するようなパッケージが依存関係に含まれていると導入できずに困るケースがあります。これについては、

* 共有フォルダでシンボリックリンクを有効にする(https://qiita.com/tuttieee/items/ab9b198cd2aaccb446ff)
* vagrant-winnfsdを利用する(https://qiita.com/fagai/items/9d491c139298e6f6e527)
* npm、bundlerの導入先を別ディレクトリにする

など、いくつか解決方法があるようですが、プラグインの導入が必要だったり、Windowsの管理者権限での操作が必要だったりちょっと面倒だなと感じていました。

# mount --bindを使った解決方法

最初に挙げたリンク先のコメントで

https://medium.com/@dtinth/isolating-node-modules-in-vagrant-9e646067b36

こちらの記事を知ったのですが、この方法をベースにVagrantfileの記述のみで共有フォルダの下にゲストマシンの特定ディレクトリをマウントすることができます。

# 設定例

共有フォルダ:
/home/vagrant/webroot

のnode_modules以下をゲストマシンの/home/vagrant/mount_point/node_modulesにマウントする場合、以下のようにVagrantfileを編集します。

```ruby:Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # ..中略.. #
  config.vm.synced_folder "./", "/home/vagrant/webroot"
  config.vm.provision :shell,
    inline: "mkdir -p /home/vagrant/mount_point/node_modules"
  config.vm.provision :shell,
    inline: "mount --bind /home/vagrant/mount_point/node_modules /home/vagrant/webroot/node_modules",
    run: "always"
  # 実際のprovisonはmountの後に記述します
  # ..中略.. #
end

```
TypeScript 2.5.3 での疑似文字列 enum の書き方

あれこれ試した結果、 `const` インスタンスを作って Mapped Types で型付けする方法に落ち着きました。

```ts
export type StringEnumAdapter<T> = { readonly [K in keyof T]: keyof T };

const FooKeyRaw = {
  ITEM_1: 'ITEM_1',
  ITEM_2: 'ITEM_2',
  ITEM_3: 'ITEM_31', // こういうミスは通ってしまう
};
export type FooKeyType = keyof typeof FooKeyRaw;
export const FooKey = FooKeyRaw as StringEnumAdapter<typeof FooKeyRaw>;

// これは (TypeScript 2.5.3 では) NG
const aKey: FooKeyType = FooKeyRaw.ITEM_1;

// これは OK
const bKey: FooKeyType = FooKey.ITEM_1;
console.log(bKey);

// これは NG
const cKey: FooKeyType = FooKey.NOT_EXIST;

// これも NG
FooKey.ITEM_1 = 'ITEM_2';

// ITEM_31
console.log(FooKey.ITEM_3);
```

# その他の方法
## namespace + export const
TypeScriptでのイベント名を管理・指定するもう一つの方法(＋ストリングリテラル型にも対応)
https://qiita.com/ConquestArrow/items/02826db3ddbe98d280bd

## class の static メンバ
TypeScriptでのイベント名をclickで指定するのはもう辞めよう
https://qiita.com/tonkotsuboy_com/items/b32801246ec14f444514

## const でキーだけ宣言して関数で初期化
typo 等でキーと値が乖離するミスは防げます。が、2017-10-15 現在、uglifyjs-webpack-plugin を通してもコンパイル時解決されないので実行コストが...

```ts
declare global {
  interface ObjectConstructor {
    keys<T>(t: T): Array<keyof T>;
  }
}

export type StringEnumAdapter<T> = { readonly [K in keyof T]: keyof T };
type StringEnumAdapterMutable<T> = { [K in keyof T]: keyof T };

export function asStringEnum<T>(t: T): StringEnumAdapter<T> {
  const tt = t as any as StringEnumAdapterMutable<T>;
  for (const k of Object.keys(tt)) {
    tt[k] = k;
  }
  return tt;
}

const BarKeyRaw = {
  BAZ: null,
  CUX: null,
};
export type BarKeyType = keyof typeof BarKeyRaw;
export const BarKey = asStringEnum(BarKeyRaw);

// これは OK
const aaKey: BarKeyType = BarKey.BAZ;

// BAZ
console.log(aaKey);

// これはNG
const bbKey: BarKeyType = 'BAZOOKA';

// これもNG
BarKey.BAZ = BarKey.CUX;
```
NICT の自動翻訳 API を Rails で使う

NICTの自動翻訳APIのページでは色々な言語で利用例の紹介がされているけれど，PythonとかJavaとかの紹介しかなくて，Rubyから利用する方法は書いてなかったので書いてみた．Railsで使えるようになるとWebサービスと連携するときも便利．

# NICT のサイトで登録
1. [NICTのサイト](https://mt-auto-minhon-mlt.ucri.jgn-x.jp/)でユーザ登録．
2. ログインしてから，「ツール」>「WebAPI」>「自動翻訳リクエスト」の「登録」の順にクリック
1. 用途に合わせてどれかクリック．今回は「汎用NMT 【日本語 - 英語】」の右にある「URL」をクリック
2. リクエストURL，API key, API secret の三つをメモ．あとは，ログインのときのユーザ名も必要．

# Railsのサイトを作成
rails new sampleApp でサイトを作成
 
```shell-session
% rails new sampleApp
```

Gemfile に gem 'oauth' を追加して，oauth をインストール．

```ruby:Gemfile
gem 'oauth'
```

```shell-session
% bundle install
```

適当にコントローラーを作成．ここでは，Welcome というコントローラに index というメソッドを定義した．

```shell-session
% rails g controller welcome index
```

welcome controller 関係のファイルを次のように変更．動作確認するだけなので，まずは ruby ファイルに直接keyとかpasswordとか書いてしまう．このままgithubなどに上げないように注意！

```ruby:app/controllers/welcome_controller.rb
require 'json'
require 'oauth'

class WelcomeController < ApplicationController
  def index
    consumer_key = 'API key'
    consumer_secret = 'API secret'
    url = 'リクエストURL(https://....)'
    name = 'ログインのときのユーザ名'
    text = '隣の客はよく柿食う客だ'

    consumer = OAuth::Consumer.new(consumer_key, consumer_secret)
    endpoint = OAuth::AccessToken.new(consumer)

    response = endpoint.post(url,{key: consumer_key, type: 'json', name: name, text: text})
    @result = JSON.parse(response.body)
  end
end

```

```ruby:app/views/welcome/index.html.erb
<%= @result['resultset']['result']['text'] %>
```

# 動作確認
Rails サーバを起動．
```shell-session
% bundle exex rails server
```

http://localhost:3000/welcome/index を見て，テキストが翻訳されていることを確認．たぶんこんなことが書いてある．

```text:
Our neighbor's guest is a guest who eats lots of persimmons.
```

# 問題点・注意点
+ API Key をrubyソースに直接書くべきではないので，secrets.ymlなどから読み込むように改良すべし
+ 翻訳したいテキストが直接rubyのソースに書いてあるのは変なので，フォームで入力できるようにするなり，どこかから取ってくるなり適当に変更すべし
+ 思いがけない翻訳結果が出てきたりして面白い
+ 商用に使う場合にはお問い合わせを
「Ruby クイズ 5問 (初級)」が難問である件

[Ruby クイズ 5問 (初級)](https://qiita.com/YumaInaura/items/8abf7e39408608ca9691#q-puts-%E3%81%A8-p-%E3%81%AE%E9%81%95%E3%81%84%E3%81%AF) に挑戦してみたのですが、とても難しかったです。

私の回答は下の方に書いてみました。回答を見る前に、皆さんもチャレンジしてみてください。

:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:
:arrow_down:

# 問題と回答

## Q. puts と p の違いは？

### A. 引数に対しての処理が大きく異なります。

`p`の場合の方が簡単なので、初めに説明します。

1. 各引数について次を繰り返す。
    1. 引数に対して、`inspect`メソッドを呼び出し、文字列を得る。
    2. 得られた文字列を標準出力に表示する。
    3. 改行を標準出力に表示する。

`puts`の場合は引数が文字列か配列かそのどれでもないかによって異なります。

* 引数が0個の場合
    1. 改行を標準出力に表示する。
* 引数が1個以上の場合
    1. 各引数について次を繰り返す。
       * 引数が文字列の場合
           1. 引数の文字列を標準出力に表示する。
           2. 改行を標準出力に表示する。
       * 引数が配列の場合
           * 配列の要素が0個の場合
               1. (何もしない)
           * 配列の要素が1個以上の場合
               1. 配列の各要素を引数として再帰的に処理を行う。
        * 引数が文字列でも配列でもない場合
            * 引数に`to_ary`メソッドが定義されている場合
                1. 引数に対して、`to_ary`メソッドを呼び出し、配列を得る。
                2. 得られた配列を引数として再帰的に処理する。
            * 引数に`to_ary`メソッドが定義されていない場合<br>
                1. 引数に対して、`to_s`メソッドを呼び出し、文字列を得る。
                2. 得られた文字列を引数として再帰的に処理する。

`to_s`が文字列を返さないなどのイレギュラーな処理を含めるともっと複雑になります。

## Q. exit と exit! の違いは？

### A. exit!はRuby上での終了処理を一切行わずにCでの[_exit(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/_exit.html)で終了する。

`exit`によって行われるRubyの[終了処理](https://docs.ruby-lang.org/ja/latest/doc/spec=2fterminate.html)は単純ではありません。SystemExit例外、擬似シグナル、ENDブロック、ファイナライザ、[exit(3)](http://pubs.opengroup.org/onlinepubs/009695399/functions/exit.html)によるストリームのフラッシュなど多くの処理があります。それら全てを無視して終了するのが、`exit!`です。

## Q. メソッド名のビックリ ( ! ) は何を表す？

### A. メソッド名の一部。慣習により注意すべきメソッドに付けられます。

Rubyのメソッド名の末尾に`!`を付けることができます。`!`を含めてメソッド名であり、分離できません。慣習により次のようなメソッドに`!`を付けるようになっています。

* 非破壊的メソッドと破壊的メソッドの両方がある場合、破壊的メソッドに付ける。
* 安全なメソッドと危険なメソッドの両方がある場合、危険なメソッドに付ける。
* その他、注意すべきメソッドに付ける。

対応する`!`がないメソッドがない場合もあります。また、メソッド名から破壊性や危険性が明確である場合は`!`を付けない場合があります。`!`がついていないから破壊しない、安全である、とは限りません。

あくまで慣習であり、組み込み以外の各ライブラリがこの慣習に従っているとは限りません。

## Q. メソッド名のクエスチョン ( ? ) は何を表す？

### A. メソッド名の一部。慣習により真偽値を返すメソッドに付けられます。

Rubyでは真偽値というひとくくりの型(クラス)はありません。どのようなオブジェクトであっても、真または偽のいずれかであるとみなされます。`true`は真であるオブジェクトの代表、`false`は偽であるオブジェクトの代表という扱いです。

`?`を含むメソッドは、慣習によりこの`true`または`false`のいずれかを返すメソッドに付けるようになっています。しかし、メソッド名から真偽値を返すことが期待できる場合は`?`を付けていない場合があります。

これもあくまで慣習であり、組み込み以外の各ライブラリがこの慣習に従っているとは限りません。

## Q. インスタンスメソッドとクラスメソッドの違いは？

### A. クラスメソッドはクラスの特異メソッド(特異クラスのインスタンスメソッド)です。

Rubyのメソッドは例外なく何かのインスタンスメソッドです。特異クラスのインスタンスメソッドを特異メソッド、クラスの特異メソッドをクラスメソッドと呼びますが、突き詰めれば、やはりそれは何かのインスタンスメソッドに過ぎません。

あるクラスのインスタンスメソッドとクラスメソッドの違いはと言われた場合、インスタンスメソッドはそのクラスのインスタンスから呼び出すことができますが、クラスメソッドは、そのクラスの特異クラスのインスタンスメソッドですので、そのクラスの特異クラスのインスタンス(それはそのクラスそのものただ一つです)から呼び出すことができる、となります。

---

初級でこのレベルと言うことは、中級や上級はどれだけ難しいお題になるのでしょうか…。
tensorflowのHParams

tensorflowには機械学習で共通して使われるような高レベルAPIが含まれている．その中の１つに[`tf.contrib.training.HParams`](https://www.tensorflow.org/api_docs/python/tf/contrib/training/HParams)がある．公式のドキュメントには簡単な使い方が載っているが，jsonファイルへの保存・読み込みを加えたサンプルを作ってみる．

```python:hprams_test.py
import os
import tensorflow as tf
import argparse
import json

def init_hparams():
    """ get default hparams """
    hparams = tf.contrib.training.HParams(
            learning_rate=0.1,
            num_hidden_units=100,
            activations=['relu', 'tanh'],
            test=False
            )
    return hparams

def print_hparams(hparams):
    """ print hparams to stdout """
    values = hparams.values()

    keys = values.keys()
    keys = sorted(keys)

    print("=================================================")
    for key in keys:
        print("{} : {}".format(key, values[key]))
    print("=================================================")

def save_hparams(filename, hparams):
    """ save to json file """
    if not os.path.exists(os.path.dirname(filename)):
        raise ValueError('There is no directory to save {}'.format(filename))

    with open(filename, 'w') as f:
        json.dump(hparams.values(), f, sort_keys=True, separators=(',', ': '), indent=4)

def load_hparams(filename):
    """ load hparams from json file """
    hparams = init_hparams()
    with open(filename, 'r') as f:
        hparams.parse_json(f.read())
    return hparams

# parse user's arguments. ex. python test.py --hparams test=true
parser = argparse.ArgumentParser(description='Train my model.')
parser.add_argument('--hparams', type=str,
                            help='Comma separated list of "name=value" pairs.')
args = parser.parse_args()

# get default params
hparams = init_hparams()

# overwrite by user's arguments
if not args.hparams is None:
    hparams.parse(args.hparams)

print_hparams(hparams)

filename = 'args.json'

# save as json file
save_hparams(filename, hparams)

# load from json file
hparams = load_hparams(filename)

print_hparams(hparams)
```

実行する場合には`python hparams_test.py --hparams test=true`などとすればデフォルトの値に上書きをすることができる．保存されたjsonファイルは以下のようになる：

```args.json
{
    "activations": [
        "relu",
        "tanh"
    ],
    "learning_rate": 0.1,
    "num_hidden_units": 100,
    "test": true
}
```


また素の`HParams`では値の順番が保証されないので，表示や保存をするときにソートをするようにしておくと読みやすくなる．
Swift コマンドラインから文字列を取得する

# 環境
* Xcode9.0
* macOS High Sierra 10.13
* CommandLineTool

# スペース区切りで型が異なる入力がされた場合
## nilを除く配列取得
``` Swift
func readLineArrayWithoutNil<T: LosslessStringConvertible>() -> [T] {
    return readLine()!.split(separator: " ").flatMap{ T.init(String($0)) }
}
```

## nilを含む配列取得　(入力数が知りたい場合など)
``` Swift
func readLineArrayIncludeNil<T: LosslessStringConvertible>() -> [T?] {
    return readLine()!.split(separator: " ").map{ T.init(String($0)) }
}
```

## 実行結果
入力 "1 a 1.125"

``` Swift
let ints: [Int] = readLineArrayWithoutNil() 
// [1]

let ints: [Double] = readLineArrayWithoutNil() 
// [1.0, 1.125]

let ints: [String] = readLineArrayWithoutNil() 
// ["1", "a", "1.125"]
```
``` Swift
let ints: [Int] = readLineArrayIncludeNil() 
// [Optional(1), nil, nil]

let ints: [Double] = readLineArrayIncludeNil() 
// [Optional(1.0), nil, Optional(1.125)]

let ints: [String] = readLineArrayIncludeNil() 
// [Optional("1"), Optional("a"), Optional("1.125")]
```

# コマンドラインの入力を１文字ずつStringで取得するには
``` Swift
readLine()!.flatMap{ String($0) }
```
## 実行結果
入力 "1 a 1.125"

``` Swift
readLine()!.flatMap{ String($0) } 
//["1", " ", "a", " ", "1", ".", "1", "2", "5"]
```

# おまけ
readLineArrayの関数を作っていて、編集後コンパイルすると初回だけ出力がおかしい時がありました。Xcodeのバグだろうか。
再度コンパイルするとうまくいきます（謎
ping 成功時にビープ音を鳴らす

# 方法

`-a` オプションを付ける。

```
$ ping -a google.com
```

ちなみに `-a` オプションの代わりに `-A` オプションを使用することで、成功時ではなく失敗時にビープ音を鳴らすこともできる。

# 何の役に立つの？

例えば手元にあるマシンの LAN ケーブルをつなぎ変える場合に、`ping` コマンドをビープ音を鳴らしながら実行しておく。そうすると、つなぎ変えが成功したことを、マシンのディスプレイを見ることなく音で確認できる。

![20171014_ping.png](https://qiita-image-store.s3.amazonaws.com/0/6697/7671926e-6215-a307-3595-721b11208353.png)
anaconda環境にtensorflowをインストールする

## 実行環境
- MacOS Sierra 10.12.6
- pyenv anaconda3-4.2.0
- python3.5.2

## tensorflowのインストール
以下のコマンドでインストールできる
```pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.6.0-py3-none-any.whl```

しかし以下のエラーが出る
```Cannot remove entries from nonexistent file /Users/xxxxxx/.pyenv/versions/anaconda3-4.2.0/lib/python3.5/site-packages/easy-install.pth```

エラーの原因はパッケージの依存関係のコンフリクトらしい ([参考](http://datalove.hatenadiary.jp/entry/python/anaconda/install-tensorflow-into-anaconda-environment))

以下引用 ([参考](http://datalove.hatenadiary.jp/entry/python/anaconda/install-tensorflow-into-anaconda-environment))

```
このエラーは、すでに setuptools がインストールされていながら、
TensorFlow インストール時に別バージョンの setuptools をバンドルでインストールしようとして発生しているもの。
```

### エラー回避方法
```pip install --upgrade -I setuptools```
を行った後に
```pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.6.0-py3-none-any.whl```
で解決

### アップデート
`sudo pip3 install --ignore-installed --upgrade  https://storage.googleapis.com/tensorflow/mac/cpu/tensorflow-1.3.0-py3-none-any.whl`
Ruby学習日記

#Ruby学習日記
2017.10.14
###プログラミング学習記録
今日からプログラミング学習の一環として日記をつけることにしました。
理由としては、知識の定着とモチベーション維持のためです。
###日誌の内容
プログラム学習内容
　- 学習した内容
　- 分かったこと
　- 分からなかったこと

こんな内容を徒然に綴って行きます。

今、何も知らない状況からQiitaに登録し、マークダウン方式ってなに？って思いながら恐る恐る文面を書いていますw

同じくQiitaに投稿されているThermidorさんの[記事](https://qiita.com/Thermidor/items/b684cfabe0f2fde0c67b#%E4%BA%8C%E9%87%8D%E5%BC%95%E7%94%A8)でマークダウン方式での書き方のまとめがありましたのでそちらを見ながら書いています。
こういうページは本当にありがたいです。即ブックマークですw
私もこんな記事をかけるように精進して行きます。


超メンドくさがりやな私が継続できるのか、不安もありますがまずはベビーステップとして記念すべき第一回投稿でした。
Rails5.1 +  Webpacker で Bootstrap4-beta を読み込む

JS と CSS を Webpacker 管理にする場合に、
Bootstrap を読み込む際にハマったのでメモする。

# 環境

- Rails : 5.1.4
- Webpacker : 3.0.2
- Bootstrap : 4.0.0-beta

# Webpacker の導入

```:Gemfile
gem 'webpacker'
```

```
$ bin/bundle
$ bin/rails webpacker:install
```

`rails new` する時に導入することもできる。

```
# Available Rails 5.1+
rails new myapp --webpack
```

- 参考
    - https://github.com/rails/webpacker#installation 

# Bootstrap の導入

```
$ yarn add bootstrap@next
```

現在(2017/10/13) は、 `next` タグをつけることで `4.0.0-beta` を指定できる。

- 参考
    - https://yarnpkg.com/en/package/bootstrap

# Bootstrap を 読み込む

ディレクトリ構成

```
app/javascript/
├── packs
│   └── application.js
└── src
    └── application.scss
```

```js:app/javascript/packs/application.js
import 'src/application' // application.scss の読み込み
import 'bootstrap/dist/js/bootstrap'
```

```scss:app/javascript/src/application.scss
@import '~bootstrap/dist/css/bootstrap'
```

```haml:app/views/layouts/application.html.haml
= javascript_pack_tag 'application'
= stylesheet_pack_tag 'application'
```

- 参考
    - https://github.com/rails/webpacker

# jQuery と Popper.js を読み込む

Bootstrap4.0.0-beta では、 jQuery と Popper.js が必要。

```
yarn add jquery
yarn add popper.js
```

`jQuery` と `Popper` がグローバル変数として参照できないと、 
Bootstrap のエラーが console.log に吐かれて正常に読み込まれない。

```js:config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

environment.plugins.set( // Webpacker 3.3.0 以降は set ではなく prepend を使用する
  'Provide',
  new webpack.ProvidePlugin({
    jQuery: 'jquery/dist/jquery',
    Popper: 'popper.js/dist/popper'
  })
)

module.exports = environment
```

- 参考
    - https://github.com/rails/webpacker/blob/master/docs/webpack.md#plugins

**追記**

[webpackerを使ったrailsアプリを実行するとき、TypeError: environment\.plugins\.set is not a functionというエラーが出る \- Qiita](https://qiita.com/hidehiro98/items/fb52be640e82e5a06100) によると、 `Webpacker 3.3.0` で `set` が remove されたらしいので、 `environment.plugins.set` ではなく `environment.plugins.prepend` を使うと良いみたいです。

# ビルド

`bin/webpack-dev-server` でビルドし、変更を自動でブラウザに反映してくれる。

- 参考
    - https://github.com/rails/webpacker#development
【統計モデリング】2章 確率分布と統計モデルの最尤推定

[統計モデリング](https://www.amazon.co.jp/%E3%83%87%E3%83%BC%E3%82%BF%E8%A7%A3%E6%9E%90%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E7%B5%B1%E8%A8%88%E3%83%A2%E3%83%87%E3%83%AA%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80%E2%80%95%E2%80%95%E4%B8%80%E8%88%AC%E5%8C%96%E7%B7%9A%E5%BD%A2%E3%83%A2%E3%83%87%E3%83%AB%E3%83%BB%E9%9A%8E%E5%B1%A4%E3%83%99%E3%82%A4%E3%82%BA%E3%83%A2%E3%83%87%E3%83%AB%E3%83%BBMCMC-%E7%A2%BA%E7%8E%87%E3%81%A8%E6%83%85%E5%A0%B1%E3%81%AE%E7%A7%91%E5%AD%A6-%E4%B9%85%E4%BF%9D-%E6%8B%93%E5%BC%A5/dp/400006973X)(通称：緑本)を勉強したので、1章ずつ記事にしておく。

緑本を読んだことがない人も理解できるように書いていく。
教えることが最強の勉強法らしいからね。

## 統計モデリングの流れ
観測データを得てから、良い統計モデルを作るまでの流れをざっくり説明

- どのような確率分布・統計モデルで観測データを説明するか
- 確率分布のパラメータはどうやって決めるか
- 決めた統計モデルが、推測データを説明できる良いものかを評価

## パラメータの最尤推定
確率分布のパラメータを推定する。
そのためには **尤度関数** が必要となる。

#### 尤度
ちなみに、尤度とは、 **「観測データへの当てはまりの良さ」** である。

最尤推定に戻ると、、、
尤度関数を求める
=> 対数変換した対数尤度関数にする
=> 対数尤度を最大化
=> 最尤推定量のパラメータを導き出す

## 尤度と最尤推定の一般化
θをパラメータとする確率分布から、観測データ $y_i$ が発生した場合
- 確率は、 $p(y_i| \theta)$
- 尤度は、 $L(\theta|Y) = \Pi p(y_i| \theta)$ 
- 対数尤度は、 $\log L(\theta|Y) = \sum \log p(y_i| \theta)$

そして、対数尤度を最大にする $\hat{\theta}$ を導き出す

## 確率分布の導入は第一歩
統計モデルの基本部分である **確率分布** はどんな役割があるんだろう。

数字の羅列を見たとき、「こういうばらつきのあるデータは、何かの確率分布から発生したと考えれば、扱いやすいだろうなぁ」と考えるのが、統計モデリングの第一歩である。

## データ取得から予測までの流れ
では、実際にデータが集まったら、どのような手順で予測まで行うかを追っていく。

1. 観測データを見たときに、「○○分布で説明できる」と仮定する。
2. 「パラメータ○はどんな値だろう？」と気にする。
3. **推定** する。 
(今回は最尤推定により、パラメータの最尤推定量を取得している)
4. 推定で得られたパラメータを使って、統計モデルを作る。
5. **予測** する。
統計モデルを使って、同じ調査方法で得られる次のデータの分布を見積もる
6. 予測の良さを評価する。

## 推定と予測の違い
僕は今まで、統計とか機械学習を勉強してきたが、「推定」と「予測」の違いが、イマイチつかめなかった。

ということで、ここではっきりさせておく。
### 推定
手元にある限定された個数のデータから元の確率分布に近い確率分布を探すこと。
つまり、パラメータを見つけ出すこと。
### 予測
推定された確率分布(統計モデル)をうまく図示することが、予測と言ってもいい。
つまり、次に得られるデータを作ること。

### 確率分布の選び方
統計モデルの基本部品である確率分布の選ぶ基準を3つ紹介する。

- 説明したい量は、離散か連続か？
- 説明したい量の範囲は？
- 説明したい量の標本分散と標本平均の関係は？

## ゴール
この章を学習した上で、到達したゴールは、

**「この統計モデリングでは、このような理由で、この確率分布を使いました。」** 

と人に説明できるようになることだ。