OmniAICreator/Qiita-1.07M huggingface dataset:
Amazon ECR/ECSの利用


Services > Compute > EC2 Container Service
から

- レジストリーを作成
- awscliをインストール

```.bash
aws configure # 認証情報をセット
```

```.bash
aws ecr get-login --no-include-email --region ap-northeast-1 
# => docker login -u AWS -p ??..??= -e none https://??.dkr.ecr.ap-northeast-1.amazonaws.com
```
の実行結果をコピーし、`e`オプションを消したものを実行

```
docker tag [IMAGE_ID] [USERID].dkr.ecr.ap-northeast-1.amazonaws.com/[REPOSITORY_NAME]:latest
docker push [USERID].dkr.ecr.ap-northeast-1.amazonaws.com/[REPOSITORY_NAME]
```
多分できる。
Heroku環境でSendGridを使ってメール送信

## はじめに
※2017/08/20時点
Heroku環境からは**デフォルトだとメール送信ができない**ため、
SendGridアドオンを入れてメールを送信する流れを記載します。(言語：PHP）
基本的には、↓公式サイトに手順が記載されているので、それに沿って行っていきます。
https://devcenter.heroku.com/articles/sendgrid
以下がざっくりした流れ＋備忘録です。

## 流れ
0. SendGridアドオンを追加する
    - ※ **Freeプランが最大12000通/月**
    - ※ プランの詳細⇒https://elements.heroku.com/addons/sendgrid
0. SendGridのサイトに行って、APIキーを作成する
    - ※ 環境変数にSendGridのID,パスワードが書き込まれるが、Herokuサイトの自分のAppの"SendGrid"をクリックすればシングルサインオンできる。
0. 作成したSendGridのAPIキーを自分のAppの環境変数に追加する
    - ※ ブラウザからなら、自分のAppのSettings＞Config Variablesから追加ができる。
0. ComposerでSendGridのライブラリを取得
0. autoload.phpでライブラリを読み込み、環境変数から取得したAPIキーを渡してメールを送信

```php
<?php
require 'vendor/autoload.php';

$from = new SendGrid\Email(null, "test@example.com");
$subject = "Hello World from the SendGrid PHP Library!";
$to = new SendGrid\Email(null, "test@example.com");
$content = new SendGrid\Content("text/plain", "Hello, Email!");
$mail = new SendGrid\Mail($from, $subject, $to, $content);

$apiKey = getenv('SENDGRID_API_KEY');
$sg = new \SendGrid($apiKey);

$response = $sg->client->mail()->send()->post($mail);
echo $response->statusCode();
echo $response->headers();
echo $response->body();
```
Neural Network ConsoleでNVIDIAGPUの動作確認まで

先日、ソニーから[Neural Network Console](https://dl.sony.com/ja/)が無償提供されることになった。
今回はこのNNCをGPUで動作できるように設定する。

https://dl.sony.com/ja/

このサイトにアクセス、メールアドレスを記入し送信する。
メールにファイルダウンロード用のURLが添付されいているのでそれアクセスしダウンロードする。

zipファイルを解凍しneural_network_console.exeを実行。
![nnc3.png](https://qiita-image-store.s3.amazonaws.com/0/176377/c44c097a-f8f9-8d17-2924-da6c2d5ecbc5.png)

###GPU設定有効化
右上の設定マークをクリック。
![nnc4.png](https://qiita-image-store.s3.amazonaws.com/0/176377/93b3f6e0-b8a9-21cb-6bfa-6f401b977c0b.png)

CPUとなっているところをGPUに変更。

###MNISTで動作確認
ホームに戻りProjectを起動(何でもよい)
ダウンロードが終わり次第以下の画面になったら「F5」キーを押し実行。
![nnc6.png](https://qiita-image-store.s3.amazonaws.com/0/176377/e6c87b87-7d71-bc29-bf31-c4acbbe66528.png)
GPUで処理
![nnc7g.png](https://qiita-image-store.s3.amazonaws.com/0/176377/bff33507-f27c-042a-40d5-322678d0a211.png)
CPUで処理
![nnc8c.png](https://qiita-image-store.s3.amazonaws.com/0/176377/dd6c89a1-473f-1aaf-5081-2c8fe6c1dcc0.png)

###結果
GPUとCPUとでは実行時間にかなりの差があることが分かった。参考までにマシンスペックをまとめる。

CPU:core i7-6700k
GPU:GTX970 ×2
メモリ:16GB
OS:Windows10 64bit

###まとめ
自分のPCはkerasを動かすことが出来るように環境構築してあるが、今回のNNCはその環境構築の手間が省けるので技術者でない研究目的に利用するのに最適だと感じた。
またGUIで作業することが出来るのはkerasより強みを感じる。

今後neet-AIで組んだモデルをこちらで試してみたいと思っている。

寄付していただければ幸いです！
仮想通貨
BTC 18c58m54Lf5AKFqSqhEDU548heoTcUJZk
ETH 0x291d860d920c68fb5387d8949a138ee95c8d3f03
ZEC t1KtTRKy9w1Sv5zqi3MYnxZ3zugo54G4gXn
REP 0x291d860d920c68fb5387d8949a138ee95c8d3f03
Raspbian Stretch(2017/8/16リリース版)でIP固定にする

これまでは`eth0`だったが、`enxb827eba2dfe7`に変更になった。
(Raspberry Pi 1にて確認。)
`kernel 4.9.41+`に上がったのが原因かと思われる。

```
$ ip a s | grep glo
```

にてどのインタフェース名で認識しているか確認。自分の場合は`enxb827eba2dfe7`だった。

```diff:/etc/dhcpcd.conf
- interface eth0
+ interface enxb827eba2dfe7
  static ip_address=192.168.0.115/24
  static routers=192.168.0.1
  static domain_name_servers=192.168.0.1
```

上記を `/etc/dhcpcd.conf` に記述しOS再起動すればよい。
TensorFlowチュートリアルをやってみた　第1回


[TensorFlowの公式チュートリアル](https://www.tensorflow.org/get_started/get_started)をやってみました
簡単な計算グラフの話のみです。
TensoFlowをインストール済みとしてください。

## TensorFlow入門

ターミナルで`python`を実行(以降インタプリタで行う)

### Tensorflowインポート
```python
>>>import tensorflow as tf
```


### 計算グラフ
```python
>>>node1 = tf.constant(3.0, dtype=tf.float32) #定数3.0を設定
>>>node2 = tf.constant(4.0)
>>>print(node1, node2)
```
ノードは評価されると3.0と4.0を生成する。
ノードを実際に評価するには、セッション内で計算グラフを実行する必要がある。

```python:printの出力
Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32)
```

Sessionオブジェクトを作成し、runメソッドを呼び出して評価する計算グラフ(node1,node2)を実行する。

```python
>>>sess = tf.Session()
>>>print(sess.run([node1, node2]))
```

```python:printの出力
[3.0, 4.0]
```

これらのノード(node1,node2)を組み合わせることによって複雑な計算(新しい計算グラフ)を作成する。
とりあえずAdd(足し算を作成する)

```python
>>>node3 = tf.add(node1, node2) # node1 + node2
>>>print("node3:", node3)
>>>print("sess.run(node3):", sess.run(node3))
```

```python:printの出力
node3: Tensor("Add:0", shape=(), dtype=float32)
sess.run(node3): 7.0
```

このグラフのままでは定数が設定されているため、`placeholder`を利用して、外部入力を受け付けるようにする。

```python
>>>a = tf.placeholder(tf.float32)
>>>b = tf.placeholder(tf.float32)
>>>adder_node = a + b  # + provides a shortcut for tf.add(a, b)
>>>print(sess.run(adder_node, {a: 3, b: 4.5}))
>>>print(sess.run(adder_node, {a: [1, 3], b: [2, 4]}))
```

```python:printの出力
7.5
[ 3.  7.]
```


より計算グラフを複雑にしてみる。

```python
>>>add_and_triple = adder_node * 3.
>>>print(sess.run(add_and_triple, {a: 3, b: 4.5}))
```

実際に数式に直してみるとこんな計算をしている。`(a + b) * 3`

```python:printの出力
22.5
```

機械学習では同じ入力で新しい出力が得られるためにグラフを修正できる必要がある。変数を使用すると訓練可能なパラメータをグラフに追加できる。

`tf.constant`は呼び出すと初期化され定数が設定されるため、変更ができない。
`tf.Variable`は変数は呼び出しても変数は初期化されず、更新ができる。

```python
>>>W = tf.Variable([.3], dtype=tf.float32)
>>>b = tf.Variable([-.3], dtype=tf.float32)
>>>x = tf.placeholder(tf.float32)
>>>linear_model = W * x + b
>>>init = tf.global_variables_initializer()
>>>sess.run(init)
>>>print(sess.run(linear_model, {x: [1, 2, 3, 4]}))
```

`init = ..~`の部分はTensorFlowプログラムのすべての変数を初期化するための変数。`sess.run(init)`を呼び出すまで変数は初期化されない

```python:printの出力
[ 0.          0.30000001  0.60000002  0.90000004]
```

目的の値(教師データ)の値を提供するためのプレースホルダーが必要であり、損失関数も必要である。

### 損失関数
現在のモデルが出力した値が教師データからどれだけ離れているかを測定します。モデルが出力した値と教師データの線形回帰の標準損失モデルを使用する。`linear_model - y` は各要素がタイオする誤差のベクトルを計算し、`tf.square`でそのエラーを二乗する。その後ｍすべての誤差を抽象化する単一スカラーを生成する`tf.reduce_sum`を呼ぶ。

```python
>>>y = tf.placeholder(tf.float32)
>>>squared_deltas = tf.square(linear_model - y)
>>>loss = tf.reduce_sum(squared_deltas)
>>>print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
```

printの出力は損失関数の値を返しています。

```python:printの出力
23.66
```

`{x: [1, 2, 3, 4], y: [0, -1, -2, -3]}`入力の2つの値を見ると,`W = -1 b = 1`の時に損失が0になりそうです。
`tf.assign`を利用して、重みとバイアスを変更できる。

```python
>>>fixW = tf.assign(W, [-1.])
>>>fixb = tf.assign(b, [1.])
>>>sess.run([fixW, fixb])
>>>print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
```

```python:printの出力
0.0
```
GoでLチカ


ググって出てくるのがPythonの例ばかりで少し飽きてきたのでGoでやってみたメモ。

----

## インストール

```bash
cd /opt

curl -L -O https://storage.googleapis.com/golang/go1.8.3.linux-armv6l.tar.gz

diff \
  <(sha256sum go1.8.3.linux-armv6l.tar.gz | awk '$0=$1') \
  <(echo '3c30a3e24736ca776fc6314e5092fb8584bd3a4a2c2fa7307ae779ba2735e668')

tar xzf go1.8.3.linux-armv6l.tar.gz

mv go go-1.8.3

# `/usr/local/go`に入れなさい、と公式サイトに書いてあるので。
ln -s /opt/go-1.8.3 /usr/local/go

rm go1.8.3.linux-armv6l.tar.gz
```

### 確認

```bash
# `/usr/local/go`にあるならGOROOTの設定はいらないらしいが、一応。
cat >> ~/.bashrc <<'END'
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin
END

source ~/.bashrc

go version
#> go version go1.8.3 linux/arm
```

### hello world

```bash
cat > hello.go <<'END'
package main

import "fmt"

func main() {
    fmt.Printf("hello, world\n")
}
END

go run hello.go
#> hello, world
```

### GOPATH

以下のようなディレクトリ構成にするのがGoの流儀らしい。

```
~/go
├── bin # `go install` コマンドでできたバイナリが配置される
├── pkg # 依存するパッケージがビルドされたものが置かれるっぽい
└── src # Goのソースコード
```

で、 `~/go` を `$GOPATH` に設定して、これを起点にいろいろ探しに行くそうな。

`hello.go` をGoの流儀に合わせる。

```bash
cat >> ~/.bashrc <<'END'
export GOPATH=~/go
export PATH=$PATH:$GOPATH/bin
END

source ~/.bashrc

mkdir -p $GOPATH/src/hello

mv hello.go $GOPATH/src/hello/

# `$GOPATH/bin` にhelloコマンドができる
go install hello

hello
#> hello, world
```

----

## Lチカ

ここからが本題。

### go-rpio

https://github.com/stianeikeland/go-rpio

GPIOをコントロールするライブラリを作ってくれている方がおられるので 
ありがたく使わせてもらいます。

```bash
go get -v github.com/stianeikeland/go-rpio

cd $GOPATH/src/github.com/stianeikeland/go-rpio

# v3.0.0を使う
git checkout -b v3.0.0 refs/tags/v3.0.0
```

### チカチカするソース

```bash
mkdir -p $GOPATH/src/gpio/blinkled
cat $GOPATH/src/gpio/blinkled/blinkled.go
```

```go
package main

import (
	"fmt"
	"github.com/stianeikeland/go-rpio"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	fmt.Println("start")

	err := rpio.Open()

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pin := rpio.Pin(21) // GPIO21ピンを使う
	pin.Output()

	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGINT)
	loop := true

	for loop {
		select {
		case s := <-ch:
			fmt.Printf("signal receive: %v\n", s)
			if s == syscall.SIGINT { // SIGINT受け取ったらループ抜ける
				loop = false
				pin.Low()
			}
		default:
			pin.Toggle()
			time.Sleep(1 * time.Second)
		}
	}

	rpio.Close()
	fmt.Println("stop")
}
```

### 実行

GPIO21ピンにLEDを繋いで、以下実行。

```bash
cd $GOPATH/src/snippet/gpio/blinkled

go install

blinkled
# 1秒置きにチカチカするはず。
# 停止はCtrl-Cで。
```

----
----

> 少しGo勉強したのでコード直した。
OpenPose のDNN部分をChainer CPUで動かしてみた

こちらの記事は[当方blog](http://blog.mizumasa.net/dev_memo/openpose_cpu/)からの転載になります。

# はじめに

今回はMacで、OpenPoseをchainerを使って実行してみます。
(全体ではなく検出ヒートマップを生成する一部の機能になります)

１． Caffeの学習済みモデルをダウンロードする
２． ChainerからCaffeのモデルを読み込む
３． Chainerのネットワークに画像を適用する

CVPR2017で発表された単眼カメラによる骨格推定アルゴリズムのOpenPose、すでにUbuntu, Windowsでのリアルタイムな処理が実現することが報告されています。ですがGPUが必要だったりMacは対応してなかったりなので、どうにかMac やCPUでも動かせないかと思い、CaffeのモデルをChainerで読み込んで前半のDNNの部分だけ実行してみます。

# 実行環境 (Linuxでも動くはず)

Mac book Pro  (2.7 GHz Intel Core i5,16 GB 1867 MHz DDR3)
Python2.7 (Chainer, Numpy)

# 作業

１． Caffeの学習済みモデルをダウンロードする

[こちら](https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/installation.md)にWindows向けの実行バイナリがあるのでダウンロードします。この中にCaffeのパラメータファイルが含まれています。
（直リンクが気になる方は https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/installation.md の中程にあるDownload and unzip the portable OpenPose demo 1.0.1.から落としてください）

２． ChainerからCaffeのモデルを読み込む

今回は、骨格18点を推定するCOCOモデルを使用します。(MPIモデルも同様の手順で可能)
Caffeのモデルが以下のディレクトリに保存されています。

OpenPose_demo_1.0.1/models/pose/coco/pose_iter_440000.caffemodel

これをchainerから読み込みます。

```
from chainer.functions import caffe
func = caffe.CaffeFunction('pose_iter_440000.caffemodel')
```

３． Chainerのネットワークに画像を適用する

OpenPose_demo_1.0.1/models/pose/coco/pose_deploy_linevec.prototxt
を読むとネットワークの構成が書かれており、最後の出力層をみてみると

```
layer {
   name: "concat_stage7"
   type: "Concat"
   bottom: "Mconv7_stage6_L2"
   bottom: "Mconv7_stage6_L1"
   # top: "concat_stage7"
   top: "net_output"
   concat_param {
     axis: 1
   }
 }
```

となっており、出力ノードの１つ目はMconv7_stage6_L2 という名前で定義されています。
（Mconv7_stage6_L1の方はボーンっぽい）

というわけで、これをfuncの出力層に指定することで(1,19,h,w)の出力マップを得ることができます。

```
x = chainer.Variable([画像のnumpy配列])
y, = func(inputs={'data': x}, outputs=['Mconv7_stage6_L2'])
print y.data.shape #(1,19,h,w)
```

画像のnumpy配列は、サイズが(1, 4, height, width) で値が0〜255ではなく0.0〜1.0
さらにdtypeがnp.float32になっていないといけないことに注意してください。
(RGBではなくRGBAが想定されているのか分かりませんが、4番目には0を埋めて入力しています)

↓試してみたのがこちらの画像
![paku2-200x300.jpg](https://qiita-image-store.s3.amazonaws.com/0/197729/6f069cfb-3ab2-8671-110f-4855a7cf2c2e.jpeg)

![testout-768x228.png](https://qiita-image-store.s3.amazonaws.com/0/197729/dca0eaa7-1f3d-89b1-1882-99f254da6851.png)

```
    POSE_COCO_BODY_PARTS {
        {0,  "Nose"},
        {1,  "Neck"},
        {2,  "RShoulder"},
        {3,  "RElbow"},
        {4,  "RWrist"},
        {5,  "LShoulder"},
        {6,  "LElbow"},
        {7,  "LWrist"},
        {8,  "RHip"},
        {9,  "RKnee"},
        {10, "RAnkle"},
        {11, "LHip"},
        {12, "LKnee"},
        {13, "LAnkle"},
        {14, "REye"},
        {15, "LEye"},
        {16, "REar"},
        {17, "LEar"},
        {18, "Bkg"},
    }
```

ヒートマップは上の構造体に書かれた体の部位のそれぞれの存在確率を示しています。
１枚あたり１０秒ぐらいかかりますが、CPUでも動くので使い道が広がりそうです。
goでWindows APIを実行する覚書

golangでWindows APIを実行するための覚書(入り口)です。

# やってみたこと

まずは、感覚を知りたかったのでWindowsのKernel32.dllからGetTickCount関数を実行してOSの起動時間をmsで取得するプログラムを描いてみました。

# ソース

```go
package main

import (
	"fmt"
	"syscall"
)

func main() {
	// golang.org/x/sys/windows(参考)
	// https://godoc.org/golang.org/x/sys/windows
	// Win32 API 一覧(参考)
	// http://www.pinvoke.net/index.aspx

	// kernel32.dllをロード
	kernel32, err := syscall.LoadDLL("Kernel32.dll")
	if err != nil {
		panic(err)
	}
	// 一番最後に読み込んだDLLをメモリからアンロード
	// https://godoc.org/golang.org/x/sys/windows#DLL.Release
	defer kernel32.Release()

	// システムが起動してから経過した時間をミリ秒(ms)で取得する関数を指定
	// http://www.pinvoke.net/default.aspx/kernel32.GetTickCount
	proc, err := kernel32.FindProc("GetTickCount")
	if err != nil {
		panic(err)
	}

	// 起動時間を取得
	r, _, _ := proc.Call()

	// 起動時間を表示(ms)
	fmt.Println(r)
}
```

DLLをロードして、定義されている関数を見つけて実行する感じ。

# 実行

```powerhell
PS C:\Users\Administrator\Desktop> go run .\get_os_uptime.go
6439736
```

# 参考

[Windows DLL一覧参考](http://www.pinvoke.net/index.aspx)
[GoのWindows syscallドキュメント](https://godoc.org/golang.org/x/sys/windows)
Gitでマージコミットを取り消す方法

## はじめに
gitのコンフリクト解消でミスした時に、mergeコミットを取り消す方法について。

## 状況
自分のブランチ（abcブランチ）をmasterにマージしようとする際に、コンフリクトが発生したので、

```
$ git checkout abc
$ git merge master
```

としたところ、コンフリクトが発生したため修正し、

```
$ git commit -m "solve conflict with master"
$ git push origin abc
```

と（いつも通り）pushしましたが、ここでコンフリクト解消時のミスに気づきました。
ここからミスを直して再pushしてもよかったところですが、頭が混乱してきたので、ここは一旦先ほどのmergeコミットを取り消して再度コンフリクト解消をやり直した方が良いと思いトライしましたが、思いの外苦労したので、いかに直した順序をメモします。

## 解決に至る道のり
### 1. git resetを試す


```
$ git reset --hard HEAD^
```

としてcommitを消してしまいました。pushしていなければ全く問題のないところですが、すでにpushしてしまったので、これではpushできません。
push -fを使っても良いところですが、複数人で管理しているプロジェクトなので、使いたくありません。

ということで、リモート上でも元の状態に戻すには、

- resetして消したcommitをローカルで取り戻す
- 取り戻したcommitのrevertコミットを作る
- リモートにpushする

の3STEPが必要になってしまいました。

### 2. git reflogしたのち、git resetする
すでに

```
$ git reset --hard HEAD^
```

でcommitを消してしまっているので、今更 `git log` してももう消したcommitは残っていません。ところが、 `git reflog` すれば、

```
$ git reflog
d5575k8f6 HEAD@{0}: reset
5728le21e HEAD@{1}: merge
...
d9d2e75d4 HEAD@{m}: commit
072fe4t0h HEAD@{m+1}: commit
```

のように消してしまったcommitも含めて履歴を見ることができるので、ここで改めて、

```
$ git reset --hard HEAD@{n}
```

のようにすれば、戻りたいところまで戻れる。

### 3. 取り戻したmergeコミットのrevertコミットを作る

```
$ git revert { mergeコミットのcommit id }
```

ここまでくれば、mergeコミットのrevertを作れば良いのですが、
mergeコミットをrevertするといっても、マージしたmasterブランチとマージされたabcブランチのどちらの履歴を残したいかこれだけではわかりません。

そこで、 -m オプションが必要になります。
-m は mainline の略で、2つの履歴のどちらをmainlineとして残したいかを 1 か 2 で指定します。
1 がマージされた側のブランチ（今回でいうとabcブランチ）、2がマージした側のブランチ（今回でいうとmasterブランチ）を指します。
今回のようにmergeコミットをrevertしたい場合は、1を指定すればOKです。

というわけで

```
$ git revert -m 1 { mergeコミットのcommit id }
```

として、一件落着しました。
さくらインターネットレンタルサーバでLaravel5.4を動かすメモ

## 前置き

以下の単語は適宜自分の環境のものに読み替えてください

- {accountname}
    - さくらのアカウント名
- {dbname}
    - DB名
- {dbpass}
    - DBパスワード
- {gituser}
    - gitアカウント名
- {appname}
    - リポジトリ名
    - Laravelプロジェクト名
-　{domain}

## データベース初期設定

- https://secure.sakura.ad.jp/rscontrol/main/db
- データベースの新規作成
    - データベースバージョン: MySQL5.5
    - データベース名: {accountname}_{dbname}
    - データベース文字コード: UTF-8

## デフォルトPHP設定

- https://secure.sakura.ad.jp/rscontrol/main/phpver
- 新しいバージョン を PHP7.1 を選択して変更ボタンを押下
- ただし、今回は既存のアプリを動作したままにしたいので当面は変更はしないことにする
    - バージョン上げたら既存アプリは全く動かなかったもので。。。

## Laravelプロジェクトを初回デプロイ

- ローカルマシンで開発した前提
- すでにgit入ってるようなのでcloneすることにする

```
% cd ~
% git clone https://{gituser}@bitbucket.org/{gituser}/{appname}.git
```

# composerインストール

- 古いPHPバージョンだとパイプの後ろのPHPに食わせるところが上手く動かなかったのでPHP7を指定してインストール
- ssh でサーバにログイン後に以下のコマンドを実行していく

```bash
% cd ~
% mkdir ~/bin
% curl -sS https://getcomposer.org/installer | /usr/local/php/7.1/bin/php -- --install-dir=bin --filename=composer

# cloneしたリポジトリのディレクトリへ移動

% cd ~/{appname}
% /usr/local/php/7.1/bin/php ~/bin/composer install

Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postInstall
> php artisan optimize
Script php artisan optimize handling the post-install-cmd event returned with error code 255

# 怒られたので指示通りに以下を叩く

% /usr/local/php/7.1/bin/php artisan optimize

# 再度叩く

% /usr/local/php/7.1/bin/php ~/bin/composer install
% ls -la vendor

# 諸々入ってればOK
```

### PHP７対応

- デフォルトPHPバージョンはそのままのため www/{appname} だけでPHP7を有効にする

```bash
% cd ~/{appname}/public
% vi php71.cgi

#!/bin/sh
exec /usr/local/php/7.1/bin/php-cgi

% chmod 705 php71.cgi
% vi .htaccess
```

```bash:.htaccess
# 追記
Action myphp-script /{appname}/php71.cgi
AddHandler myphp-script .php .html

# コメントアウト
    #<IfModule mod_negotiation.c>
    #    Options -MultiViews
    #</IfModule>

...
```
```bash
# symlink を貼る
% ln -s ~/{appname}/public ~/www/{appname}
```

## 初期設定など

```
% cd ~/{appname}

# .env ファイルを用意
% cp .env-sample .env
% /usr/local/php/7.1/bin/php artisan key:generate

## DBの設定などを更新する
% vi .env
```
```php:.env
APP_ENV=production
APP_KEY={生成されたキー}
APP_DEBUG=false
APP_LOG_LEVEL=info
APP_URL=http://{domain}/{appname}

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE={accountname}_{dbname}
DB_USERNAME={accountname}
DB_PASSWORD={dbpass}

...
```

- http://{domain}/{appname}/ へアクセスして画面が表示されることを確認

## DBマイグレーション

```
% /usr/local/php/7.1/bin/php artisan migrate
```

## デプロイ方法

- masterをデプロイする場合

```bash
% cd ~/{appname}
% git checkout master
% git pull origin master
```

## JSモジュール更新

- nodejs をインストールしようと思ったが、ソースからインストールする必要があり、makeしてもエラーになるので諦めた
- やりたいことは本番環境用のjsやcssを生成することだけなのでローカル環境で実施することにする

```bash
$ yarn run production

# 完了後に CTRL+C
```

- public/ 配下をまとめて　scp などでサーバへデプロイ
- public 配下を `git add` しちゃえばサーバで `git pull` するだけなので楽かもしれないがポリシーとご相談を
Python :  lambdaの中でも繰り返しできた

参照記事：
[全要素が移動する（同じ位置に残らない）shuffle](http://qiita.com/a_hasimoto/items/7ec3fe15967f61bb12c8)
あんまり他の方の記事でだらだらコメントしても失礼かなと思い、別の記事にしました。

こんなのを書きました。シャッフルしたリストを返す関数です。

```Python:
import random

def shuffle_all_move( items ):
  length = len( items )
  res = [ 0 ] * length
  rand_ord = random.sample( range( length ), k=length )
  for i in range(  length  ) :
    res[ rand_ord[ i ] ] = items[ rand_ord[ ( i + 1 ) % length ] ]
  return res
```

これをラムダ式で書くとどうなるかな?と思いやってみました。

ところで、
##繰り返しの処理はラムダ式の中ではどうするんだろ?

いろいろ試した結果：

+ やりたい処理(式に限る)をタプルにいれて、
+ リスト内包表記にする。(かっこは``` [ ] ```に限る。```( )```だとジェネレータになってしまって各要素が評価されない。)

ということでした。

``` Python:
import random

shuffle_all_move = ( lambda items :
  ( lambda
      length = len( items )
      , res = [ 0 ] * len( items )
      , rand_ord = random.sample( range( len( items ) ), k=len( items ) )
    :
    (
      [ ( res.pop( rand_ord[ i ] )
        , res.insert(rand_ord[ i ], items[ rand_ord[ ( i + 1 ) % length ] ])
        ) for i in range(  length  )
      ]
      , res
    )[-1]
  )()
)  
```

※ 代入もできますが、無理矢理pop,insertで実現しています。実用性は?です。
SmartGit > タグの付け替え

```txt:動作環境
Windows 7 Pro (32bit)
SmartGit Version 17.0.5 #10143
```

[git > バージョンTagをどこまで残すのか > git タグの付け替え > $git tag v2.0 v1.0 > foo/barタグ / {old}/v0.3.2タグ](http://qiita.com/7of9/items/0745bba8445facb4c3dd)で教えていただいたタグの付け替えをSmartGitではどうするのか。

### 手順

`v0.9_170815`を`{old}/v0.9_170815`にする例。

1. Logウィンドウを表示する
2. BranchesペインにおいてTagsを表示する
3. Tagsの変更対象タグにて右クリック > Copy
   - 例: v0.9_170815
   - タグ文字列がコピーされる
4. FilterにおいてCtrl+v
   - **補足: タグ文字の最後に`「: 」`などが追加される場合がある。適宜削除する**
   - 該当のタグを持つコミットがMessageペインに表示される
5. Messageペインのコミット上で右クリック > Add Tag
   - タグ名を入力 (例: {old}/v0.9_170815)
   - Add Tag & PushでリモートにPush
6. Messageペインのコミットの消したいタグ上で右クリック > Delete 'タグ名'
   - 例: v0.9_170815
   - Delete from remote 'origin'を選択してDelete
Railsで外部キー制約のついたカラムを作る時のmigrationの書き方

確認した環境はRails5.1.3です。

# テーブル作成時

外部キー制約をかけるカラム名により、多少書き方が異なります。
カラム名が `#{参照先テーブル名の単数形}_id` (e.g. 参照先がusers.id なら user_id)の場合が基本形で、参照先テーブル指定が省略できます。
それ以外の場合は、参照先テーブルが推測不可能なので、 オプションで指定する必要があります。

```ruby
class CreateTasks < ActiveRecord::Migration[5.1]
  def change
    create_table :tasks do |t|
      t.string :name, null: false

      # 基本形: user_idという名前で users.id への外部キー制約をはる
      t.references :user, foreign_key: true

      # 応用形: user_id以外の名前(assignee_id)という名前で users.id への外部キー制約をはる
      t.references :assignee, foreign_key: { to_table: :users }

      t.timestamps
    end
  end
end
```

# カラム追加時

既存テーブルにカラムを追加する時の書き方です。

```ruby
class AddUserIdToTasks < ActiveRecord::Migration[5.1]
   def change
    # 基本形: user_idという名前で users.id への外部キー制約をはる
    add_reference :tasks, :user, foreign_key: true

    # 応用形: user_id以外の名前(assignee_id)という名前で users.id への外部キー制約をはる
    add_reference :applicants, :assignee, foreign_key: { to_table: :users }
  end
end
```

# 注意事項

- `foreign_key` オプションを省略してしまうと、外部キー制約がはられません。忘れないようにしましょう。

# 豆知識

- `create_table` 内での `t.references` や　 `add_reference` を使うとdefaultでindexが作られます
    - indexを作りたくない場合はオプションで明示的に `index: false` しましょう
    - (  `ActiveRecord::ConnectionAdapters::ReferenceDefinition#initialize` の default値で `index: true` になってるからのようです → 
   [ここ](https://github.com/rails/rails/blob/5.1.3/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L80) )

# 番外編

## カラム名に `*_id` 以外の名前を使いたい

実は `t.references` や `add_reference` を使った時には、カラム名の後ろに自動で `_id` が付与され、外せません。
( `ActiveRecord::ConnectionAdapters::ReferenceDefinition#column_name` で、固定的に `_id` という suffix を付与しています → [ここ](https://github.com/rails/rails/blob/5.1.3/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L144)　)

そのような場合は、今のところ、外部キー制約のないカラムを追加した後に `add_foreign_key` で別途外部キー制約を追加する方式をとらざるを得ないようです。

```ruby
# テーブル作成時に、 assigned_to カラムを作り、外部キー制約をはる
class CreateTasks < ActiveRecord::Migration[5.1]
  def change
    create_table :tasks do |t|
      t.string :name, null: false
      t.bigint :assigned_to, index: true
      t.timestamps
    end
    add_foreign_key :tasks, :users, column: :assigned_to
  end
end
```

```ruby
# 既存テーブルに assigned_to カラムを追加し、外部キー制約をはる
class AddAssignedToToTasks < ActiveRecord::Migration[5.1]
  def change
    # assigned_to カラムを追加
    add_column :tasks, :assigned_to, :bigint, index: true
    # 別途外部キー制約を追加
    add_foreign_key :tasks, :users, column: :assigned_to
  end
end
```
jsdoでdeeplearn.js その2

#概要
jsdoでdeeplearn.jsやってみた。
xorを学習させてみた。
結果が安定しない。どっか、間違ってる。

#サンプルコード

```
var dl = deeplearn;
var gr = new dl.Graph();
var math = new dl.NDArrayMathCPU();

var inputShape = [2];
var inputTensor = gr.placeholder('input', inputShape);
var labelShape = [1];
var labelTensor = gr.placeholder('label', labelShape);

var w = gr.variable('w', dl.Array2D.randNormal([2, 20]));
var b = gr.variable('b', dl.Array1D.randNormal([20]));
var w1 = gr.variable('w1', dl.Array2D.randNormal([20, 1]));
var b1 = gr.variable('b', dl.Array1D.randNormal([1]));
var h = gr.relu(gr.add(gr.matmul(inputTensor, w), b));
var h1 = gr.relu(gr.add(gr.matmul(h, w1), b1));
var cost2 = gr.meanSquaredCost(h1, labelTensor);

var learningRate = 0.0001;
var optimizer = new dl.SGDOptimizer(learningRate);

var inputs = [dl.Array1D.new([1.0, 0.0]), dl.Array1D.new([0.0, 1.0]), dl.Array1D.new([0.0, 0.0]), dl.Array1D.new([1.0, 1.0])];
var labels = [dl.Array1D.new([1.0]), dl.Array1D.new([1.0]), dl.Array1D.new([0.0]), dl.Array1D.new([0.0])];
var shuffledInputProviderBuilder = new dl.InCPUMemoryShuffledInputProviderBuilder([inputs, labels]);
var [inputProvider, labelProvider] = shuffledInputProviderBuilder.getInputProviders();
var feedEntries = [{
    tensor: inputTensor,
    data: inputProvider
}, {
    tensor: labelTensor, 
    data: labelProvider
}];
var sess = new dl.Session(gr, math);
var batchSize = 4;
for (var i = 0; i < 4001; i++)
{
    math.scope(() => {
        var cost = sess.train(cost2, feedEntries, batchSize, optimizer, dl.CostReduction.MEAN);
        if (i % 2000 == 0)  alert('last average cost: ' + cost.get());
    });
}
math.scope((keep, track) => {
    var testInput = track(dl.Array1D.new([1.0, 1.0]));
    var testFeedEntries = [{
        tensor: inputTensor, 
        data: testInput
    }];
    var testOutput = sess.eval(h1, testFeedEntries);
    alert('xor 1 1 -> ' + testOutput.getValues());
});
math.scope((keep, track) => {
    var testInput = track(dl.Array1D.new([1.0, 0.0]));
    var testFeedEntries = [{
        tensor: inputTensor, 
        data: testInput
    }];
    var testOutput = sess.eval(h1, testFeedEntries);
    alert('xor 1 0 -> ' + testOutput.getValues());
});
math.scope((keep, track) => {
    var testInput = track(dl.Array1D.new([0.0, 1.0]));
    var testFeedEntries = [{
        tensor: inputTensor, 
        data: testInput
    }];
    var testOutput = sess.eval(h1, testFeedEntries);
    alert('xor 0 1 -> ' + testOutput.getValues());
});
math.scope((keep, track) => {
    var testInput = track(dl.Array1D.new([0.0, 0.0]));
    var testFeedEntries = [{
        tensor: inputTensor, 
        data: testInput
    }];
    var testOutput = sess.eval(h1, testFeedEntries);
    alert('xor 0 0 -> ' + testOutput.getValues());
});



```

成果物

http://jsdo.it/ohisama1/aP8H
OpenCVを使って画像の射影変換をしてみるwithPython

# はじめに

[OpenCVを使ったパターンマッチングで画像中の物体抽出 with Python](http://qiita.com/mix_dvd/items/b2b50ced80be1dcdbf2e)

上記の記事を作成するにあたりOpenCVについて調べてみると、本当にいろいろなことができるみたいなので、とりあえず思いついたことを試してみることにしました。

...ということで、名刺をカメラで撮影した画像を正面から撮影したかのように補正する「射影変換」の手順を以下にまとめます。

# 動作環境

|項目|内容|
|---|---|
|マシン|MacBook Air (13-inch, Early 2015)|
|プロセッサ|2.2 GHz Intel Core i7|
|メモリ|8 GB 1600 MHz DDR3|
|Python|3.6.0 :: Anaconda 4.3.1 (x86_64)|
|Jupyter Notebook|4.2.1|
|OpenCV|3.3.0-rc|

# 環境構築手順

いつもの手前味噌ですが、以下のURLをご参照下さい。

- [Macで深層学習の環境をさくっと作る手順 with TensorFlow and OpenCV](http://qiita.com/mix_dvd/items/b49651cf1181a986506c)

- [Ubuntu 16.04で機械学習の環境をさくっと作る手順](http://qiita.com/mix_dvd/items/4bf7f6e7fa19068ea1d4)

# 使用した写真

自分の名刺の裏側をiPhoneのカメラで撮影したものを使用します。（IMG_4778.JPG）

![IMG_4778.jpg](https://qiita-image-store.s3.amazonaws.com/0/114240/e6a6b00f-3053-6a73-a7ac-143b513606fa.jpeg)

# ライブラリ読込

```py3:
import cv2
import numpy as np

from IPython.display import display, Image

def display_cv_image(image, format='.png'):
    decoded_bytes = cv2.imencode(format, image)[1].tobytes()
    display(Image(data=decoded_bytes))
```

# 画像読込

```py3:
img = cv2.imread("IMG_4778.JPG")
display_cv_image(img)
```

# 色の二値化と輪郭抽出

```py3:
# グレイスケール化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二値化
ret,th1 = cv2.threshold(gray,200,255,cv2.THRESH_BINARY)
display_cv_image(th1)
```

二値化した結果は以下のとおりです。

![Unknown-1.png](https://qiita-image-store.s3.amazonaws.com/0/114240/d4bfd5be-7b93-4be9-e043-f2620c11fbbd.png)


```py3:
# 輪郭抽出
image, contours, hierarchy = cv2.findContours(th1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 面積の大きいもののみ選別
areas = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    if area > 10000:
        epsilon = 0.1*cv2.arcLength(cnt,True)
        approx = cv2.approxPolyDP(cnt,epsilon,True)
        areas.append(approx)

cv2.drawContours(img,areas,-1,(0,255,0),3)
display_cv_image(img)
```

正しく輪郭が抽出され、赤い枠で囲むことができました。

![Unknown-2.png](https://qiita-image-store.s3.amazonaws.com/0/114240/23bcd5cf-2338-2034-8cd1-04edc31385cf.png)

# 射影変換

枠の各点を対応する座標にあわせて射影変換します。

```py3:
img = cv2.imread("IMG_4778.JPG")

dst = []

pts1 = np.float32(areas[0])
pts2 = np.float32([[600,300],[600,0],[0,0],[0,300]])

M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(600,300))

display_cv_image(dst)
```

変換した結果は以下のとおり。

![Unknown.png](https://qiita-image-store.s3.amazonaws.com/0/114240/addd4d31-b169-0944-e23d-e2a682700fc6.png)

できた！

# おまけ

tesseract-ocrというライブラリを使用して、認識した名刺の文字をORCしてみました。

[tesseract-oct](https://github.com/tesseract-ocr/tesseract)

上述のソースコードに続けて以下のコードを追記します。

```py3:
import pyocr
from PIL import Image
tools = pyocr.get_available_tools()
tool = tools[0]
print(tool.image_to_string(Image.fromarray(dst), lang="jpn"))
```

結果は...

```
〔保有賓格】
ヽ/寸 トゥェア開莞技術肴
惰報せ‡ュ‥ティ7ド
第三種電氣主任枝術者
乙穫鷺4顆危礦鞠取扱着
空手初段

 

二ス 卜 レ一タ
```

...改善の余地ありですね（汗）
画像認識技術を簡単に体験できるMSのCustom Visionと京セラのLabellioを使ってみた

人工知能に対する興味が日に日に増してきていて、触ってみたい欲求が高まっていたので、簡単に画像判別ができるサービスを使ってみました。

1.使ってみたサービス

Labellio(京セラ)

Custom Vision Servise(Microsoft)

この2つのサービスを使ってみました。というより結果が気に食わず2つ使ってみたというのが事実です。
結果から申し上げるとMicrosoftのCustom Vision Serviseの方が精度が良いと感じました。

2.やったこと


人物の判別をしました。乃木坂46が好きなので乃木坂メンバーの判別ができるモデルを作成しました。

Labellio
まず、学習をしてもらうために教師データを用意する必要があるのですがLabellioは教師データを用意していなくても「Bing」か「Flickr」で検索して勝手に持ってきてくれます。他にもZIPファイルやTSVファイルも使えます。

今回はBingから勝手に検索して持ってきてもらいました。Labellioにtagになる今回の場合人名を入力し、教師データの数を入力して、あとは勝手に学習してもらって終わるのを待つだけです。

<img width="1280" alt="スクリーンショット 2017-08-20 15.32.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/117128/e8aad540-9475-8f5f-2382-249b9b3e06b6.png">

終わるとこんな感じに表示されます。結果があまり良くなかったので以下のように複数のモデルを作って試しました。

① label 2人　教師データ各5枚
② label 7人　教師データ各50枚
③ label 3人　教師データ各100枚

当たるものもある一方で外すときは盛大に外すといった印象です。

<img width="529" alt="スクリーンショット 2017-08-20 15.42.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/117128/609c9424-1ffe-f138-a1ae-3d572b8f207c.png">

例えばこれなんかは、齋藤飛鳥さんの写真をあげたにもかかわらず、Scoreがまさかの0.00でした。迷って間違えたという感じではありません。もちろん当たるときは当たります。
(検証に使った画像もあげようか迷ったのですが権利の関係があったのでやめておきました。)

Custom Vision
Custom Visionでは教師データをLabellioのように勝手に検索して持ってきてくれないので、めんどくさかったのでlabel2人でそれぞれ5枚の教師データをアップロードして学習してもらいました。割といい感じに正解を出しました。12枚の写真を使って検証した結果10枚正解でした。


最後にLabellioとCustom Visionで与えた教師データは異なるのですがlabel数2人、教師データ数各5枚で学習させたモデルを利用して同じ12枚の写真を使ってどちらの正解数が多いか検証しました。

Labellio(正解率67%)
正解 : 8 不正解 : 4

Custom Vision(正解率 : 83%)
正解 : 10 不正解 : 2


検証したデータの数が少ないのでよくないのですがCustom Visionの方が正解が多くなりました。全く同じものをやったわけではないので一概には言えませんがLabellioは「正解もあるけど不正解もある」といった印象で、Custom Visionは「不正解は時々あるけど正解が多い」といった印象でした。
人物の判別って、肩までしか写っていないもの、全身写っているもの、横から撮ったもの、正面から撮ったもの、笑ったもの、真顔のもの、メガネの有無、衣装の違いなど同じ人物でも違いがかなりあると思うのですがそれでもこれぐらいの数字がですのですごいなと思いました。
GPU環境でKeras 2.0とOpenCV 3.2を動かせるようにする

Python2.7でKeras(GPU版)とOpenCV 3.2を動かせるようにするまでの作業メモです．

## 検証環境&ライブラリ

- Ubuntu 16.04(docker-image: nvidia/cuda, image_id: 0877f562ab17)
- GeForce GTX 1080
- CUDA 8.0
- cuDNN v6.0
- Python 2.7.12
- TensorFlow 1.3.0
- Keras 2.0.6
- OpenCV: 3.2.0

## CuDNNのダウンロード

https://developer.nvidia.com/rdp/cudnn-download

から"Download cuDNN v6.0 (April 27, 2017), for CUDA 8.0"の
"cuDNN v6.0 Library for Linux"をダウンロードしておく必要があります．
(cuDNN v7.0はTensorFlow1.3.0では未対応みたいです[^1])

ダウンロードしたファイルを"/tmp/cudnn-8.0-linux-x64-v6.0.tgz"に置いたとします．

## Dockerコンテナの作成

`nvidia-docker`のインストール方法は下記リンクに記載されています．

https://github.com/NVIDIA/nvidia-docker

```bash
nvidia-docker pull nvidia/cuda
nvidia-docker run -it -v /tmp:/tmp nvidia/cuda bash
```

## Kerasのインストール

```bash
apt-get update -y
apt-get upgrade -y
apt-get install -y python-dev python-setuptools curl
curl -kL https://bootstrap.pypa.io/get-pip.py | python
pip install tensorflow-gpu==1.3.0
tar -xvzf /tmp/cudnn-8.0-linux-x64-v6.0.tgz
mv cuda/lib64/libcudnn* /usr/local/cuda/lib64/
mv cuda/include/cudnn.h /usr/local/cuda/include/
chmod a+r /usr/local/cuda/include/cudnn.h 
chmod a+r /usr/local/cuda/lib64/libcudnn* 
echo "export LD_LIBRARY_PATH='$LD_LIBRARY_PATH:/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64'" >> ~/.bashrc
echo "export CUDA_HOME=/usr/local/cuda" >> ~/.bashrc
source ~/.bashrc
pip install Keras==2.0.6
```

#### Kerasの動作確認

```bash
python -c "import keras; print(keras.__version__)"
```

で`2.0.6`と表示されたら成功です．

## OpenCV 3.2のインストール

以降は全てDockerコンテナ内での作業です．記事[^2]を参考にしています．

```bash
apt-get install -y build-essential cmake git pkg-config libjpeg8-dev libtiff5-dev libjasper-dev libpng12-dev libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libxvidcore-dev libx264-dev libgtk-3-dev libatlas-base-dev gfortran python2.7-dev zip libhdf5-dev libprotobuf-dev libprotoc-dev protobuf-compiler xserver-xorg doxygen wget
```

途中で

```
Country of origin for the keyboard: 50
Keyboard layout: 1
```

というメッセージが出るので，自身の環境に合わせて選択する必要があります．
私の場合は50(Japanese), 1(Japanese)に設定しました．

### OpenCVのビルド

```
wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.2.0.zip
unzip opencv.zip
cd opencv-3.2.0
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D BUILD_CUDA_STUBS=OFF -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_FFMPEG=OFF -D BUILD_opencv_python2=ON -D BUILD_EXAMPLES=OFF -DBUILD_opencv_dnn=OFF ..
make -j $(nproc)
make install
```

cmake時のオプションについては，コード[^3]が参考になります．

#### OpenCVの動作確認

```bash
python -c "import cv2; print(cv2.__version__)"
```

にて`3.2.0`と表示されたら成功です．



## References

[^1]: Allaire, [TensorFlow](https://github.com/tensorflow/tensorflow/blob/master/third_party/toolchains/gpus/cuda/BUILD), 2016.
[^2]: Rosebrock, [Ubuntu 16.04: How to install OpenCV](http://www.pyimagesearch.com/2016/10/24/ubuntu-16-04-how-to-install-opencv/), 2016.
[^3]: atinfinity, [opencv3.2_build-ubuntu16.04.sh](https://gist.github.com/atinfinity/0aea057af98dcf5a838da23becfdffbe).
Common Lisp + OpenGLでSTGを作った


# Common LispでSTGを作った

[こちらの記事](http://qiita.com/fireflower0/items/5dd68a0736166154edab)に触発されて、[以前](http://qiita.com/kedama17/items/6405790323b6e2917391)からいろいろ調べてたCommon LispとOpenGLである程度まとまったものを公開しようと思って作ってみました。
こちらはSDLではなくOpenGLを使っています。

[GitHubで公開](https://github.com/singy15/ministg)しています。
若干（かなり？）コードは汚いですが、サンプルになるところもあるかなと思います。
MITライセンスですので煮るなり焼くなりお好きにお使いください。

## 動かし方

GitHubのREADMEにも一応書いてありますが。

```shell-session
cd ~/quicklisp/local-projects/ministg
(ql:quicklisp :ministg) 
(ministg:main)
```

[追記]
guicho271828さんがRoswellスクリプトを書いてくれました。

```shell-session
ros install singy15/ministg
ros exec ministg
# ~/.roswell/binにパスを通してある場合は以下のようにしても実行できる
ministg
```


![screenshot.png](https://qiita-image-store.s3.amazonaws.com/0/74246/2b16064d-9ac5-7e66-6b11-4e96d33130a3.png)

こんな画面がでればOKです。
初回起動時はちょっと時間かかります。
操作はWSADで自機移動、Jで発射です。
なるべく簡単になるように作ってるので自機と敵機との当たり判定とかメニュー画面とかサウンドとかそういうのは一切なしです。（ミサイルは出来心です）

## 技術的なこと

### 開発環境・使用ライブラリ

* Steel Bank Common Lisp 1.3.10
* cl-opengl
* cl-glut
* cl-glu
* cl-singleton-mixin

### ASDF／QuickLisp

ASDファイルを作って、ASDFでファイルの読み込み順だったり他systemへの依存性の解決をしています。
QuickLispでライブラリ管理をしています。

[SBCL ＋ ASDF3 ＋QuickLispでプロジェクトの作り方](http://qiita.com/kedama17/items/bca1a601fa4c35d81580)

### CLOS

CLOSを使い、OOP（？）なスタイルで書いています（つもりです）。
accessorは名前衝突が起きやすそうなので名前にキーワードを使っています

[CLOSでaccessorとmethodの名前衝突を回避する](http://qiita.com/kedama17/items/dd218766e0562f31c557)。
[Common LispでSingletonなクラスを作る（CLOS）](http://qiita.com/kedama17/items/9b7bc6c9a5202e2e3914)

### グラフィックス

cl-openglを使いOpenGLで描画をしています。

[cl-openglでグラフィックス](http://qiita.com/kedama17/items/6405790323b6e2917391)
[cl-openglで入力を拾う](http://qiita.com/kedama17/items/fffbad80d198df951a5b)
Cloud9にGo言語(1.8.3)をインストールする

#はじめに
[cloud9](https://c9.io/)、ブラウザだけで開発できてしまうお手頃環境と思いつつ、しっかりと開発できてしまうのでスゴイです。

普段はCloud9のphp環境でLaravelを使っているのですが、速度が必要な処理があったのでphpで並列処理できないかな？と調べていたところ、php7.0で並列処理をするには、[pthreads](http://php.net/manual/ja/book.pthreads.php)というライブラリがあってphpでも並列処理はできる模様。でも通常インストールしたphp7.0はNTS(Non Thread Safety)でZTS(Zend Thread Safety)ではないため、pthreadsが動かない。

ZTSなphp7.0をインストールするには自分でコンパイルする必要があるっぽい。せっかくお手軽な環境のCloud9を使っているのに自分でコンパイルして～となるとお手軽さが削がれてしまうし、どうせ面倒なことをやるならphpじゃなくてもいいなと思い、Go言語をインストールして 時間のかかっている処理部分をGo言語で作ることに。

Cloud9のGo言語(golang)のバージョンは1.2.1がインストールされていた。けど2017年8月20日現在に[リリースされているGo言語](https://golang.org/doc/devel/release.html)は1.8.3。どうせGo言語を使うなら新しいものを使ってみたかったので、Cloud9にGo言語の1.8.3を新しくインストールしました。

その手順を残します。

# Cloud9のGo言語入れ替え方法
```shell-session
# ダウンロード
wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
tar xvzf go1.8.3.linux-amd64.tar.gz

# インストール済みのgo言語を削除
sudo rm -rf /opt/go
sudo mv go/ /opt/

# goのシンボリックリンクを更新(削除して作成)
sudo rm /usr/bin/go
sudo ln -s /opt/go/bin/go /usr/bin/go
```
今日のスケジュールを毎朝教えてほしい

# はじめに

最近予定を忘れやすい・・・

これじゃあいかんということで
きちんと管理することにした。

更に、毎朝その日のスケジュールを通知して
絶対に忘れないようにする。

---

# さてどうする

予定はGoogleカレンダーを使うことにした。

Googleカレンダー自体に通知機能はあるが
その日の予定をまとめて通知してくれる機能はあるのか・・・？？

良く分からなかったので別の方法を検討。

GASでSlackに連携して通知することにした。

---

# 流れ

予定はGoogleカレンダーで自分で管理。

GASでカレンダーを読み取って
全部まとめてからSlackに通知。

それを毎朝AM07:00にセットしておけば
必ず通知を見るので忘れる心配なし！！

（※今回は「カレンダーに入れ忘れる」という
残念な忘れ方については対象外とした。）

---

# 早速やってみよう

GASの基本的な操作とスケジューリングは
こちらのページを参考にした。

https://www.sakana.tech/entry/make-cron-use-googleappsscript

あとはscriptでカレンダーから取って
まとめてSlackに投げる部分を作ればOK。

---

# 実際のコード

フォーマットや書き方はダサいが
とりあえず実用性重視ということで・・・

```
function mySchedule() {
  var calendar = CalendarApp.getCalendarById('{GoogleカレンダーID}');
  var schedule = calendar.getEventsForDay(new Date());
  var message = '@{Slackで付けたいメンション}\n本日の予定：' + Utilities.formatDate(new Date(), 'JST', 'yyyy/MM/dd') + '\n';
  for(var i=0; i<schedule.length; i++) {
    var title = schedule[i].getTitle();
    var start = Utilities.formatDate(schedule[i].getStartTime(), 'JST', 'HH:mm');
    var end = Utilities.formatDate(schedule[i].getEndTime(), 'JST', 'HH:mm');
    message = message + start + ' - ' + end + ' ' + title + '\n';
  }
  
  var slackApp = SlackApp.create('{SlackのToken}');
  slackApp.postMessage('#{Slackで通知するチャネル}', message, {
    username : '{通知する時の名前}'
  });
}
```

---

# 実行したら

こんな感じで予定が通知されました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/163142/a9f1dfb5-6b55-d6db-016d-78f11c42355a.png)

スマホにもSlackを入れているので
目を覚ましたらすぐにでも確認できる感じです。

---

# 最後に

GASもSlack連携も初めてだったので
色々やれてよかったです。

でも・・・全部終わったあとに
標準のSlack連携でもできるのかと調べてみたら
普通にできちゃいました💦

【参考記事】
https://get.slack.help/hc/ja/articles/206329808-Slack-%E3%81%A8-Google-%E3%82%AB%E3%83%AC%E3%83%B3%E3%83%80%E3%83%BC%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B

やりたかったことはこれで十分なので
今回の記事は「はじめてのGAS」程度で見てださい (^▽^;)
Slackでファイルを削除するBotを作成した

#経緯
会社で使っているslackのファイル容量がオーバーしそうになった。
調べたら、Slackにアップロードしたファイルは一括削除ができないらしい。
そしたら、どこからともなく`GASでSlackのファイルを削除するBotが作れるらしいよ`というメッセージと共に、URLが送られてきた。
>Slackの古くなったファイルを自動で削除してみた
http://lyncs.hateblo.jp/entry/2017/06/04/191421

~~なんで俺が……と思いながら~~、GAS(GoogleAppsScript)で1ヶ月経過したファイルを削除するbotを作った。その際にfiles.listではまったので、メモ。

# やりたいこと
* 指定した日数(1ヶ月)、経過したファイルを削除
* 指定したタイプのファイル以外、削除(今回は、画像とPOSTは残したい)

# 作業の流れ
だいたい[送られてきたページ](http://lyncs.hateblo.jp/entry/2017/06/04/191421)を参考にするとそれらしいものが完成する。
作業の手順を手短にまとめると、

* [Tokenの発行ページ](https://api.slack.com/custom-integrations/legacy-tokens)でTokenを発行する
* GoogleAppsScriptを新規作成して[APIドキュメント](https://api.slack.com/methods)とにらめっこしながらせっせと実装する
* 適当なSlackで挙動を確認する

みたいな感じですかね。

#ソースコード
[作成したソースコード](https://github.com/satougashi/SlackDeleteFile/blob/master/SlackDeleteFile.gs)

* GASで呼ぶメソッド以外はオブジェクトにまとめた
* ライブラリ使うより、URLで直接API叩いた方が早いらしいので、そのように

【2017/10/29追記】
パラメータにchannelidを指定し忘れるという痛恨のミスが発覚。(↓コメント参照)
修正しておきました。
~~確認したら会社のSlackも全てのチャンネルが削除対象となっていた模様。（ゝω・）~~

【201803/18追記】
修正をリモートにpushし忘れていたことが発覚。(↓コメント参照)
遅ればせながらpushしておきました。m(_ _;)m
加えて、全チャンネル削除(channelId指定しない)とした場合でも、 **自アカウントが参加していないチャンネルのファイルは削除されない** という仕様であることが発覚したので、合わせて報告しておきます。

# types
APIドキュメントによると、files.listメソッドで指定できるtypeは、以下の7種類とのこと。（POSTもファイルとして扱われるよ）

* all - All files
* spaces - Posts
* snippets - Snippets
* images - Image files
* gdocs - Google docs
* zips - Zip files
* pdfs - PDF files

しかし、一見良くわからなかったので、よく使いそうな拡張子のファイルを準備して、指定したオプションでどれが取ってこれるのかをテストした。
用意したのは以下のファイル

|形式|拡張子|
|:--|:--|
|Excelファイル|.xlsx|
|zipファイル|.zip|
|画像ファイル|.jpg .png .gif .bmp|
|テキストファイル|.txt|
|dumpファイル|.sql|
|pdfファイル|.pdf|
|謎の拡張子|.hoge|
|SlackのPOST|(拡張子無し)|

結果

|オプション|取得できた拡張子|
|:------------|:--------------|
|all|全部|
|snippets|.txt .sql|
|images|.jpg .png .gif|
|zips|.zip|
|pdfs|.pdf|
|gdocs||
|spaces|SlackのPOST|


つまり、「画像以外が削除したい」、みたいな場合は
　1. すべてのファイルを取得
　2. 削除したくないファイルを取得
　3. 1と2の差分をとる
という処理が必要ということが分かった。（.bmpは画像として認識してくれない）

あと、typeオプションを利用して「xlsxは削除するけどdocxは残す」
 みたいなことは**出来ない**ということが分かった。

もし、そういう処理がしたいなら「ファイル名から拡張子を取り出して個別に指定する」みたいにすれば出来ると思う。
他に良い方法があれば教えてくださいまし。
Effekseerでパワーが溢れるようなエフェクトを作る

ゲームにおいてチャージが完了していたり魔法の詠唱中だったりするときには、
キャラからパワーが溢れているようなエフェクトを付けたいですよね。

そういったエフェクトをEffekseerを使ってサクッと作りたいと思います。
今回はUnityへの組み込みまで行います。

# エフェクトを作る

![Power01.gif](https://qiita-image-store.s3.amazonaws.com/0/11172/2fbb64da-ecdb-2929-cebf-3acad247f523.gif)

こういう良い感じのエフェクトを作ります。

## 衝撃波
![efk3.png](https://qiita-image-store.s3.amazonaws.com/0/11172/e1dc9d04-6af3-d74e-413a-61c211fabebb.png)

ノードタイプはリングです。
立体的な輪が広がって消えていく感じです。

## パーティクル
![efk4.png](https://qiita-image-store.s3.amazonaws.com/0/11172/2efe07c3-7fbf-b69e-655b-a3d06db432b3.png)

ノードタイプはスプライトです。
周囲にランダムに散らしてゆっくり上に上がりつつ消えていく感じです。

## ノードの生成数を無限に設定

こういう纏う系エフェクトは無限に続いて、必要になったら消えるようにして欲しいです。
↓のスクショのように、生成数のところの無限にチェックを入れて一定時間で終わらないようにしましょう。

![efk.png](https://qiita-image-store.s3.amazonaws.com/0/11172/af8d0b07-15ee-47e5-b779-3ae5be2327a2.png)

# ゲームに組み込む

今回はUnityを使用します。
SDユニティちゃんを借りてきました。

![efk2.png](https://qiita-image-store.s3.amazonaws.com/0/11172/43c06214-e71d-19dd-d698-21f376b635e5.png)

SDユニティちゃんに子GameObjectを付けて、コンポーネントとしてEffekseerEmitterを追加します。
今回On/Offをコントロールしたかったので、Play On StartはOffにして、代わりにEffectControl.csを追加しました。


また、こういう無限に続くタイプは手動で停止させる必要があります。
その際Stop()を使うと瞬時に全部消えてしまい不自然です。

そういうときはStopRoot()を使いましょう。
ルートノードのみを停止させることで、子ノードの生成が止まり寿命で少しずつ消えていく演出が実現できます。

```csharp:EffectControl.cs
public class EffectControl : MonoBehaviour
{
	private void OnGUI()
	{
		var emitter = GetComponent<EffekseerEmitter>();

		if (GUILayout.Button("Start Effect")) {
			emitter.Play();
		}
		
		if (GUILayout.Button("Stop")) {
			emitter.Stop();         // 瞬時に消える
		}
		
		if (GUILayout.Button("Stop Root")) {
			emitter.StopRoot();     // 少しずつ消える
		}
	}
}
```

## 実行した結果

1回目がStop()で止めたとき、2回目がStopRoot()で止めたときです。
2回目の方が自然にエフェクトが消えていきますね。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">エフェクトを止めるときに呼ぶStop()とStopRoot()の違い。Stop()は即時全ノード停止。StopRoot()はルートノードのみを停止→子ノードの生成が止まってフェードアウトになる <a href="https://twitter.com/hashtag/Effekseer?src=hash">#Effekseer</a> <a href="https://t.co/zG6HARgmMH">pic.twitter.com/zG6HARgmMH</a></p>&mdash; うえした (@ueshita) <a href="https://twitter.com/ueshita/status/899095831520845824">2017年8月20日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

# ライセンス
![imageLicenseLogo.png](https://qiita-image-store.s3.amazonaws.com/0/11172/278b3949-74fb-293f-0035-b3f792d1be12.png)
この作品はユニティちゃんライセンス条項の元に提供されています
PlamtUML使用時の覚書


## コマンドラインでの実行時にハマったこと

### ・ファイルをUTF-8で保存したとき、エラーになる

日本語を使っており、UTF-8で保存したらエラーになった。Visual Studio Codeでは正常なのに。
SHIFT-JISで保存すると正常実行できる。
ただ、UTF-8でファイルを作成したいため、いろいろ調査。
結果「-charset UTF-8」とつけてやればうまく動作した。
```ps1:コマンド
java -jar C:\JavaLib\plantuml.jar -charset UTF-8 .\PlantUML_シーケンス図サンプル.uml
```
supervisor - http-serverで動かすswagger-uiを永続化する

## やったこと

swagger-uiをnodeのhttp-serverで動かしていたものを
supervisor使って勝手に立ち上がるようにした

## 環境

- Mac OS X
- node v8.4.0

## 手順

__http-serverのインストール__

```bash
$ npm install -g http-server
```

__swagger-uiを持ってくる__

```bash
$ cd path/to
$ git clone https://github.com/swagger-api/swagger-ui
$ cd swagger-ui/dist
```

dist/をルートにして動かします

```bash
$ http-server -p 9090
Starting up http-server, serving ./
Available on:
  http://127.0.0.1:9090
  http://*.*.*.*:9090 # macに振られているIP
```

これで、swagger-uiにアクセスすることができるようになりました。
今回はこのプロセスを永続化したいわけです

__supervisorのインストール__

この方のdocを参考にしてすんなり行きました

https://gist.github.com/yoggy/21230e5eae5e7ee7ea59

__永続化するプロセスの設定ファイルを作成__

```bash
$ /usr/local/etc/supervisor/conf.d
$ sudo vi swagger-ui.conf
$ cat swagger-ui.conf
[program:swagger-ui] 
directory=/path/to/swagger-ui/dist
command=http-server -p 9090
numprocs=1 
autostart=true
autorestart=true
user=user ; 実行ユーザー
redirect_stderr=true
stdout_logfile=/var/log/supervisor/swagger-ui.log
```

__supervisorに設定を再読込させる__

```bash
$ supervisorctl
supervisor>
# 設定読み込み
supervisor> reread
swagger-ui: available # conf.dに設定したプロセスが表示される

# 再起動
supervisor> reload
Really restart the remote supervisord process y/N? y
Restarted supervisord

# 確認
supervisor> status
swagger-ui                       RUNNING   pid 724, uptime 0:00:03
```

__再起動するのかテスト__

```bash
$ ps ax | grep http-server
 1198   0.0  0.0  2452260    832 s010  S+    2:58PM   0:00.01 grep http-server
 1035   0.0  0.1  3041256  11824   ??  S     2:50PM   0:00.27 node ~/.nvm/versions/node/v8.4.0/bin/http-server -p 9090
$ pgrep node
1035
$ pgrep node | xargs kill -9
$ ps ax | grep http-server | grep -v grep
 1276   0.0  0.3  3041256  22556   ??  S     3:00PM   0:00.26 node ~/.nvm/versions/node/v8.4.0/bin/http-server -p 9090
```

あたらしくプロセスIDが振られているので勝手に立ち上がっていることが確認できました
Swiftで genstrings を使いつつ NSLocalizedString を安全に使う

## 序
genstringsを使いつつNSLocalizedStringを安全に使う方法をいろいろ考えていたのだが、一つ思いついたので書き記す。

## ソース
```swift:Localizable.swift
import Foundation

protocol Localizable {
    
    var key: String { get }
    var table: String? { get }
    var bundle: Bundle { get }
    var comment: String { get }
    
    var string: String { get }
}

extension Localizable {
    
    var string: String {
        
        return NSLocalizedString(key, tableName: table, bundle: bundle, comment: comment)
    }
}

struct LocalizedString: Localizable {
    
    let key: String
    let table: String? = nil
    let bundle: Bundle = .main
    let comment: String
    
    
    init(_ string: String, comment: String) {
        self.key = string
        self.comment = comment
    }
}

struct LocalizedStringFromTable: Localizable {
    
    let key: String
    let table: String?
    let bundle: Bundle = .main
    let comment: String
    
    
    init(_ string: String, tableName: String, comment: String) {
        self.key = string
        self.table = tableName
        self.comment = comment
    }
}

// これはなくていい。というかない方がいい？
struct LocalizedStringFromTableInBundle: Localizable {
    
    let key: String
    let table: String?
    let bundle: Bundle
    let comment: String
    
    
    init(_ string: String, tableName: String, bundle: Bundle, comment: String) {
        self.key = string
        self.table = tableName
        self.bundle = bundle
        self.comment = comment
    }
}

// NSLocalizedStringWithDefaultValue を使う人はここに書くんだ！　僕は使わない！！！
```

```swift:LocalizedStrings.swift

struct LocalizedStrings {
    
    static let Hoge = LocalizedString("Hoge", comment: "Hoge Comment")
    static let Fuga = LocalizedStringFromTable("Fuga", tableName: "TableA", comment: "Fuga Comment")
    static let Piyo = LocalizedStringFromTableInBundle("Piyo", tableName: "TableB", bundle: Bundle(for: NSObject.self), comment: "Piyo Comment")
}
```

## 注意
Localizable.swiftとLocalizedStrings.swiftは必ず２つのファイルに分けてください。
genstringsがクラッシュします。

## 使用法
### ローカライズ用stringsファイルの生成
下のコマンドを実行することでローカライズ用stringsファイルが生成される

```sh
genstrings -s LocalizedString LocalizedStrings.swift
```

テーブル名が同じならバンドルが別のものでも一つのファイルにマージされます。

### ローカライズされた文字列の取得
```swift

let localized = LocalizedStrings.Hoge.string

```
でローカライズされた文字列が取得できる。

`LocalizedStrings`に必要な値を追加して行く。（別に`LocalizedStrings`に追加でなくてもいい）

## おもったこと
### genstrings
swiftとgenstringsを組み合わせて使ってる人っているのだろうか。
というかgenstrings自体使っている人いるのだろうか。
甚だ疑問である。

swiftだとCの関数の形式でさらにラベルがつくのでgenstringsが使えそうにないのに使えてしまうのは、バグなのか、仕様なのか、なんなのか。
sw-precacheで外部サイトのファイルをキャッシュ

(2018/9/14追記)
sw-precache, sw-toolboxは既に更新を終了していますので、Workboxに移行してください。
https://github.com/GoogleChrome/workbox


環境
- Node.js v7.3.0
- クライアントはChrome v60.0

予めsw-precacheに加えてsw-toolboxをインストールしておく

```
npm install sw-precache
npm install sw-toolbox
```

下記スクリプトをrollupなどの適当なビルドスクリプトに含めておく

```js:build.js

const precache = require('sw-precache');
const home = 'path/to/home';

precache.write(`${home}/precache.js`, {
  staticFileGlobs: [
    `${home}/*.{js,html,css}`,
    `${home}/assets/**/*.{png,jpg,gif}`
  ],
  stripPrefix: `${home}/`,
  runtimeCaching: [
    {urlPattern: /^https:\/\/maxcdn\.bootstrapcdn\.com/, handler: 'cacheFirst'},
    {urlPattern: /^https:\/\/code\.jquery\.com/, handler: 'cacheFirst'},
  ]
}, () => {});
```

生成されたprecache.jsをserviceWorkerに登録する。

staticFileGlobsで指定したパスのファイルは全てprecache.jsに記載され、ServiceWorker登録時に自動的にキャッシュされる。クロスオリジンの制約があるので、同じドメインのファイルしかキャッシュできない。

一方、runtimeCachingのurlPatternで指定したドメインのファイルは、handlerで指定したstrategyに従って、初回アクセス時にキャッシュされる。これは他ドメインのファイル（例えばCDNに置いてあるライブラリ）にも適用可能。

strategyについては、Offline cookbook参照のこと
https://jakearchibald.com/2014/offline-cookbook/

なお、sw-toolboxで対応しているstrategyは次の５つ

- networkFirst（Network falling back to cache、ネットワークが利用できない場合キャッシュを利用）
- cacheFirst（Cache falling back to network、キャッシュが利用できない場合ネットワークから取得）
- fastest（Cache & network race、ネットワーク接続とキャッシュを同時に要求し、レスポンスが早い方を採用）
- cacheOnly（オンライン接続せずキャッシュのみを使用）
- networkOnly(キャッシュしない)
秀丸ファイラーでフォルダ・ファイルのパスをBash on Ubuntu on Windowsで使えるフォーマットでコピーするマクロ

ファイラーでファイルを選択してそれをコンソールや他アプリに貼り付けるという事はよくあるけど、ファイルパスの形式が複数あってつらい。そんな時の秀丸ファイラー用マクロ。

秀丸ファイラー1.26 Beta7で確認。Bash on Ubuntu on Windowsのパスは、ドライブレター部分を小文字にする必要があるので注意。

ソースコードはこちら
https://github.com/fushihara/hidemaru-filer-file-path-copy-macro

![image.png](https://qiita-image-store.s3.amazonaws.com/0/5825/4484dee3-bd42-13bb-0579-5414940a9ff9.png)

欲しいと思ったけど、秀丸ファイラーの機能制限で出来なかった事

- メニューの表示位置をファイルの位置、もしくはマウスカーソルの位置に合わせたい
- デフォルト選択肢が無い状態だけど、デフォルトで二番目(選択中のファイル ダブルクオートなし)を選びたい