OmniAICreator/Qiita-1.07M huggingface dataset:
slack用hubot作成時のメモ

とりあえず、メンションしたらランダムで何かを返してくれるbotでも作る。

# 開発環境の準備
## vagrant 
``` vagrantfile
  config.vm.box = "centos/7"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
    vb.cpus = 2
  end
```

## node v8指定
```
curl -sL https://rpm.nodesource.com/setup_8.x | bash -
yum install -y nodejs gcc-c++ make
npm install -g jsfmt sails node-dev pm2 
npm install -g hubot hubot-slack yo generator-hubot coffee-script grunt-cli bower coffe-script
npm update
```

## herokuも準備
```
npm install -g heroku-cli
```

## アプリ用のユーザを作成
rootで作ると権限関係で怒られるっぽい

```
useradd huboter
su - huboter
```

# アプリ作成

## テンプレ作る
```
mkdir rbot
cd rbot
yo hubot
... (適当に入力)
Bot adapter: (campfire) slack
... (適当に入力) 
```

## スクリプト作成
```rbot.coffee
random = (n) -> Math.floor(Math.random() * n)
module.exports = (robot) ->
  robot.hear /@rbot/i, (msg) ->
    words = [
     'なぁに？',
     '見てるぞ',
     'いくら出す？',
     '誠意',
     '誠意だよ誠意'
    ]
    result = words[random(5)]
    msg.send "#{result}"
```

# slack側設定
app - hubot を追加し名前(rbot)などをセット。APIトークンを控えておく。

# herokuへ

```
heroku login
heroku create rbot
heroku git:remote -a rbot
git init
git add .
git commit -m "first commit"
git push heroku master
```

と、そのままpushしようとしたら下記のエラー

```
[huboter@localhost rbot]$ git push heroku master
Counting objects: 20, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (17/17), done.
Writing objects: 100% (20/20), 17.90 KiB | 0 bytes/s, done.
Total 20 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Node.js app detected
remote: 
remote: -----> Creating runtime environment
remote:        
remote:        NPM_CONFIG_LOGLEVEL=error
remote:        NPM_CONFIG_PRODUCTION=true
remote:        NODE_VERBOSE=false
remote:        NODE_ENV=production
remote:        NODE_MODULES_CACHE=true
remote: 
remote: -----> Installing binaries
remote:        engines.node (package.json):  0.10.x
remote:        engines.npm (package.json):   unspecified (use default)
remote:        
remote:        Resolving node version 0.10.x...
remote:        Downloading and installing node 0.10.48...
remote:        Detected package-lock.json: defaulting npm to version 5.x.x
remote:        Bootstrapping npm 5.x.x (replacing 2.15.1)...
remote: 
remote: /tmp/build_869d142be7596a803ffd10a84edac8f4/.heroku/node/lib/node_modules/npm/lib/utils/unsupported.js:27
remote:         console.error(`a bug known to break npm. Please update to at least ${r
remote:                       ^
remote: SyntaxError: Unexpected token ILLEGAL
remote:     at Module._compile (module.js:439:25)
remote:     at Object.Module._extensions..js (module.js:474:10)
```

なにやら、package.jsonで指定されているnodeとnpmのバージョンを何とかしようとしてエラーになっている模様。
んじゃとりあえず現状の環境のnodeとnpmのバージョン指定しておけばいいんじゃね？と下記の様に修正したら解消。

``` package.json抜粋(元)
  "engines": {
    "node": "0.10.x"
  }
```

```package.json抜粋(修正版)
  "engines": {
    "node": "8.9.1",
    "npm": "5.5.1"
  }
```

## slackと繋ぐための環境変数を指定する(heroku側のsettingでも良い）
```
heroku config:set HUBOT_SLACK_TOKEN=（控えておいたAPIトークン）
heroku config:set HUBOT_SLACK_BOTNAME=rbot
```
バニラJSでcollapseアニメーション

```html:html
<div class=”wrapper”>
  <div class="body">
    あいうえお
  </div>
</div>
```

```css:css
.wrapper {
  height: 0;
  overflow: hidden;
  transition: お好み;
}
```

```js:js
const eWrapper = document.body.querySelector('.wrapper');
const eBody = eWrapper.querySelector('.body');
let isCollapsed = true;

function getBodyHeight() {
  return eBody.getBoundingClientRect().height;
}

function toggle() {
  const height = isCollapsed ? getBodyHeight() : 0;
  eWrapper.style.height = `${height}px`;
  isCollapsed = !isCollapsed;
}
```
pandas.DataFrame.histでx軸目盛りを変更する

# pandas.DataFrame.histは非常に便利
データをpandasで読み込んだら最初に.histを使ってデータを確認する癖がついている
###例
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({'norm': np.random.normal(0,100,10000)})
df.norm.hist(bins=50, figsize=(12,8))
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/45398/d204cf1c-c3a2-4549-aa4c-583f7c4073b6.png)

# x軸目盛りを変更したい
形を見るだけなら↑の例で十分だけどx軸の目盛りをもっと増やして見たい時がある（ある値以上でのデータは使わないなどのしきい値を決めるときとか）
###例: 目盛りを増やす
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({'norm': np.random.normal(0,100,10000)})
df.norm.hist(bins=50, figsize=(12,8))
plt.xticks(np.arange(int(df.norm.min()), int(df.norm.max()), 50))
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/45398/681cbed0-0ddb-b6bd-baa1-6ce5c9a06189.png)

こちらからは以上です。
スクラム スターターキット

# スクラム スターターキット

スクラム本読んで色々とやるべきことが多くて頭混乱してきたので、最低限必要そうなことだけをまとめてみた。
あとはスプリント回していろんなプラクティスを追加してカスタマイズしていけばいい感じになるんじゃないかな。

1. メンバーを集める
	- スクラムマスター
		- スクラムについて知識がある人
			- なくても学ぶつもりがあればOK
		- 人のために仕事をするのが好きな人
			- 縁の下の力持ち的な立場なので
		- 説明が得意or好き
			- スクラムについて説明できることが望ましい
	- プロダクトオーナー
		- プロダクトについて把握している人
		- プロダクトに価値を感じている人
		- プロダクトに期待している人
		- エンドユーザーの要望をまとめられる人
		- 協調性のある人
			- 全部満たしてなくてもOK
	- 開発チーム
		- 協調性のある人
		- 人の話を聞ける人
		- 新しいことへの興味が強い人
		- フルスタックエンジニア
			- チームで全体を見れるとやりやすいんで
				- チームの各メンバーでカバーできるのであればそれでもOK
				- スキルが偏ると大変かも
2. インセプションデッキのたたき台を作る(PO,SM)
	- プロジェクトの全体像(目的、背景、優先順位、方向性等)を端的に伝えるためのドキュメント
		- 全体でプロジェクトの全体像の認識共有と不安事項などの共有が目的
	- テンプレート [support/blank-inception-deck at master · agile-samurai-ja/support](https://github.com/agile-samurai-ja/support/tree/master/blank-inception-deck)
3. メンバー全員でインセプションデッキを確認(ALL)
	- 追記・修正はどんどんやる
	- 思ったことはどんどんいう
	- メンバー全員が何のために何を作るかを共有しましょう
4. プロダクトバックログの作成・整理(PO,SM)
	- POが必要な機能(とその価値・目的)をプロダクトバックログとしてまとめる
		- ユーザーストーリーで
		- デモのシナリオもあるとよし
	- バックログの項目を大まかに分類する
		- 必須
		- 超重要
		- 重要
		- 普通
		- できれば
	- 必須・超重要（・重要）の項目を順位づける
	- バックログの内容を説明する上で資料が必要そうなら用意する
5. スプリント計画の1部 開催(ALL)
	- POがプロダクトバックログの各項目について説明
		- 順位の高いものから
			- この説明は開発チームが実際に作るものについて把握するためのものなので、疑問点などがあればその場で確認取る
		- 説明している最中に必要なバックログが増えたら追加しても良い
	- プロダクトバックログの各項目を見積もる
		- ベースとなるバックログを決める
			- チーム全体でどれくらいかかるのかの認識が大体揃うものを使う
			- 大きすぎたり小さすぎたりしたら使いづらいので中程度のもので
			- 一応ベースとなるバックログについての認識があってるか、チーム全体で確認とった方が良いかも
		- 各バックログについて、ベースと比較してどれくらいかかりそうか見積もる
			- チームメンバー全員で見積もる
				- プラニングポーカー使うと効率的
	- プロダクトバックログからスプリントバックログの項目と抽出する
		- 順位の高いものから
		- どれくらいやれそうかは見積もりのベースとしてバックログにかかる時間を基準にして判断
			- スプリント期間内の営業日10日、メンバー4人、であれば10日*6時間*4人=240時間
			- ベースにかかる時間が8時間であれば、ベース*30のバックログができるはず
				- スクラムに慣れてないうちは少なめに
				- 完璧な見積もりはできないので、ここの想定通り進まなくても無理をしない（残業ましましNG）
			- かかる時間がわからない場合はとりあえずベースのバックログをやって見て時間を図る
6. スプリント計画の2部 開催(開発チーム+α)
	- 開発チームがスプリントバックログの項目を詳細なタスクとして分割する
	- 分割したタスクから、実際にスプリント内で終わらせそうか判断する
		- 難しい場合はPOに相談してスプリントバックログの項目を調整
7. スプリント実施(開発チーム)
	- やり方はとりあえずなんでもOK
		- 改善は振り返りとかで出して次スプリントで行なっていけば良い
			- 次スプリント待たずに改善して行っても良い
	- 最低限、朝回はやった方が良い
	- デモの準備は時間かけたほうがいいかも
8. レビュー(ALL)
	- スプリントで作った機能を実際にデモして確認する
	- 思うところがあれば意見を出す
	- チーム全員でバックログが完了となったか判断する
9. 振り返り(ALL)
	- KPTでとりあえずやる
		- 改善案とか出ればバックログに追記する
	- 終わったらPOがバックログを整理した後、次のスプリント計画を行う
Google Compute Engine(GCE)からCloud SQL接続でハマった

Google Cloud Platform(以下GCP)のGoogle Compute Engine(以下GCE)からCloud SQLへ接続する場合、Cloud SQL Proxy経由で接続することで以下の恩恵が受けられます。

* 安全な接続: プロキシは、データベースとの間で送受信されるトラフィックを自動的に暗号化します。クライアントとサーバーの ID の確認には、SSL 証明書が使用されます。
* 簡単な接続管理: プロキシが Google Cloud SQL との認証を処理するので、静的な IP アドレスを提供する必要がなくなります。

イメージは以下です。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/0fe06221-0757-2122-3e52-92458a16bb55.png)
※https://cloud.google.com/sql/docs/sql-proxy?hl=ja#gce

プロキシの設定も簡単で以下の流れで出来ます。

```プロキシをダウンロード.
wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64
```

```プロキシの名前を標準のファイル名に変更.
mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy
```

```プロキシを実行可能にする.
chmod +x cloud_sql_proxy
```

ここまで来たらプロキシを開始します。
言語や環境に応じて、TCPソケットまたはUnixソケットのどちらかを使用してプロキシを開始できます。ここではUnixソケットを利用します。

```プロキシソケットを格納するディレクトリを作成.
sudo mkdir /cloudsql; sudo chmod 777 /cloudsql
```

```新しいターミナルウィンドウを開きプロキシを開始.
./cloud_sql_proxy -dir=/cloudsql -instances=<INSTANCE_CONNECTION_NAME>
```

※INSTANCE_CONNECTION_NAMEは自身のCloud SQLのインスタンス接続名です。

実際に上記の流れでプロキシを開始しCloud SQLへ接続を試みると、以下のようなエラーに遭遇しました。
![キャプチsssャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/e63ad867-7813-3d9e-9ad7-08f60875b3c0.png)
見にくいですが、内容は以下です。

```message.
2017/11/15 17:06:27 errors parsing config:
        googleapi: Error 403: The client is not authorized to make this request., notAuthorized
```

認証に失敗していることは分かります。
これだけではちょっと・・・ってことでここでかなりハマりましたが、真面目に公式ドキュメントを読んでみたら案外簡単に解決しました。

>Cloud SQL に Compute Engine インスタンスから接続している場合、プロキシは Compute Engine インスタンスに関連付けられているサービス アカウントを使用できます。Cloud SQL インスタンスに対する少なくとも Editor 権限がサービス アカウントにある場合、プロキシの認証は成功します。

>Compute Engine インスタンスが Cloud SQL インスタンスと同じプロジェクトにある場合、Compute Engine インスタンスのデフォルトのサービス アカウントはプロキシの認証に必要な権限を持っています。2 つのインスタンスが異なるプロジェクトにある場合は、Editor 権限を持つ Cloud SQL インスタンスを含むプロジェクトにサービス アカウントを追加する必要があります。


※https://cloud.google.com/sql/docs/sql-proxy?hl=ja#environment

つまり、サービスアカウントをプロジェクトに追加して編集者権限の付与が必要ということのようです。IAMで確認してみると、案の定ユーザが1人いるだけでサービスアカウントがプロジェクトに存在していませんでした。
![キャsssssプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/17dbeb57-876d-fc60-988c-0b71e105b08a.png)

そのため、以下のようにサービスアカウントをプロジェクトに追加して編集者権限を付与し、
![キャaaaプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/6f0d4346-9bd2-7575-ab3a-e283534f66a8.png)

再度、SSHでコンソールからプロキシを開始しCloud SQLへ接続してみると、うまくいきました。
![キャssssプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/6105a82e-dd81-ebc5-7ddd-066ff38792c1.png)

2017/11/17 追記
Cloud SQLへの接続はCloud SQL Client (roles/cloudsql.client) というロールがあるので、それでも接続可能です。
https://cloud.google.com/sql/docs/mysql/sql-proxy?hl=en#permissions
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/23101/00cce8c3-ec12-6710-efe0-d39f6c9903cd.png)



以上です。
MATLAB > NxM array > 比較 > y1 == y2 | 行列なのかarrayなのか

```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)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
```

```matlab
>> y1 = [ 3 1 4; 1 5 9];
>> y2 = [ 3 1 4; 2 6 9];
>> y1 == y2

ans =

  2×3 logical array

   1   1   1
   0   0   1
```

相異があるところが0になるようだ。

### 備考

言葉として「行列」なのか「array」なのか。
上記の結果からは「array」という表記。

https://jp.mathworks.com/help/matlab/math/creating-and-concatenating-matrices.html
を見ると「行列」。

？？？

https://jp.mathworks.com/help/matlab/learn_matlab/matrices-and-arrays.html?lang=en
> All MATLAB variables are multidimensional arrays, no matter what type of data. A matrix is a two-dimensional array often used for linear algebra.

二次元限定の場合を「行列」と呼ぶようだ。

https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.ndarray.html
MATLAB > Error: Too many output arguments. > 関数の戻り値を指定することで対処する

```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)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
```

### 関連

[MATLAB > 実装 > 二次元arrayを10回シャッフルする](https://qiita.com/7of9/items/f13e623a16edc5f01109)

### Error

```shuffle_171115.m
% v0.1 Nov. 15, 2017
%    - shuffle 10 times

function shuffle_171115(tri)
    [len1, len2] = size(tri);
    for loop = 1:10
        % get index of [1:N-1]
        pos = round(rand()* (len1 - 2)) + 1;
        % swap
        tri([pos pos+1],:) = tri([pos+1 pos],:)
    end
```

```matlab
>> tri = [1 1 1; 2 2 2;];
>> res = shuffle_171115(tri)
Error using shuffle_171115
Too many output arguments.
```

問題の原因は、shuffle_171115()において戻り値を指定していないこと。

### code v0.2

```shuffle_171115.m
% v0.2 Nov. 16, 2017
%    - shuffle_171115() returns values
% v0.1 Nov. 15, 2017
%    - shuffle 10 times

function [res] = shuffle_171115(tri)
    [len1, len2] = size(tri);
    for loop = 1:10
        % get index of [1:N-1]
        pos = round(rand()* (len1 - 2)) + 1;
        % swap
        tri([pos pos+1],:) = tri([pos+1 pos],:);
    end
    res = tri;
```

```matlab
>> res = shuffle_171115(tri)

res =

     1     1     1
     2     2     2

```
Perlのバージョンを5.14.4にあげる in CentOS

# はじめに
Perlの学習を始めるにあたり、CentOSに入ってるPerlのバージョンが5.10.1だったので
「初めてのPerl」（リャマ本）第6版で扱ってる5.14系にあげたので手順のメモ。
※2017年11月16日時点の5系最新バージョンは5.26.1

# 環境

## OS
```
$ cat /etc/redhat-release 
CentOS release 6.8 (Final)
```
## Perl
```
$ perl -v

This is perl, v5.10.1 (*) built for i386-linux-thread-multi

Copyright 1987-2009, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
```

# 手順
まずはインストールまで。gitから対象バージョンのタグをcheckoutしてmake install。

```
# git clone git://perl5.git.perl.org/perl.git perl
# git tag -l
# git checkout -b v5.14.4 refs/tags/v5.14.4
# sh Configure -des -Dusethreads -Dinc_version_list=none
# make
# make test
# make install
```

バージョンチェック

```
# /usr/local/bin/perl -v

This is perl 5, version 14, subversion 4 (v5.14.4) built for i686-linux-thread-multi

Copyright 1987-2013, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
```

無事インストールされました。

でもこのままだと古いバージョン残ってしまってるので
元のモジュールを退避させつつ、シンボリックリンクを貼って切り替えます。

```
# cd /usr/bin
# mv perl perl-5.10.1
# ln -s /usr/local/bin/perl .
```

# 最終確認

```
# perl -v

This is perl 5, version 14, subversion 4 (v5.14.4) built for i686-linux-thread-multi

Copyright 1987-2013, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
```

これでバージョンアップ完了。
とりあえずリャマ本進めるにあたってこのバージョンにしたけど
終わったら最新バージョンにあげようかな。
pandasのDataFrameの列の追加

## 列の追加
```python
df = pd.DataFrame([], columns=['col1', 'col2', 'col3']) #空のを作成
for i in range(3):
  df2 = pd.DataFrame([[i, i, i]], columns=['col1', 'col2', 'col3'], index=["row" + str(i+1)])
  df = df.append(df2)

#     col1 col2 col3
#row1    0    0    0
#row2    1    1    1
#row3    2    2    2
```
uwsgiのemperorモードのservice化メモ

どっからコピペしたのかも
なぜ動いてるのかもよくわからないけど
今使ってるuwsgiのemperorモードでのservice化のためのファイル(uwsgi.service)をメモしておく。

~/.venv/ 下にuwsgiのためだけのvenv設定済みという前提

```
$ cd ~
$ mkdir .venv
$ python3.6 -m venv .venv/uwsgi
$ source .venv/uwsgi/bin/activate
$ (uwsgi) pip install uwsgi
```


/etc/systemd/system/uwsgi.service
権限は644 root:root

```
[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown nginx:nginx /run/uwsgi'
ExecStart=/home/yourname/.venv/uwsgi/bin/uwsgi --emperor /etc/uwsgi/vassals
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

```
mysql5.7, centos7でクライアント証明書で認証したい

結論、以下の通りにやりましょう。
https://www.howtoforge.com/tutorial/how-to-enable-ssl-and-remote-connections-for-mysql-on-centos-7/

mysql5.7はデフォルトでyasslというものを採用しているようで、
centOS7デフォルトのopensslで証明書関連の作業をするとすんなりいかない。

ので、作業の途中に
`openssl rsa -in server-key.pem -out server-key.pem`
`openssl rsa -in client-key.pem -out client-key.pem`
といった感じに一手間必要。


あとはmy.cnfの`[mysqld]` セクションに

```
bind-address = *
require_secure_transport = ON
```

とでも書けばオッケー
OpenMP並列での擬似乱数の生成方法

## 出発点: シリアルコード

Boost.Randomを使うと、(0,1]の実数乱数を生成するコードは以下のように書ける。

```cpp:serial.cpp
#include <boost/random.hpp>
#include <iostream>

int main(int argc, char **argv) {
  unsigned long seed = 1234;
  boost::minstd_rand seed_gen(seed);
  boost::mt19937 gen(seed_gen);

  int count = 16;
  boost::uniform_real<> dist;
  for (int i = 0; i < count; ++i) {
    std::cout << i << ' ' << dist(gen) << std::endl;
  }
}
```

`boost::mt19937`は、初期化の際に直接シード(整数)を渡すこともできるが、ここでは`seed`で初期化したシーケンス`seed_gen`を用いて初期化している。

## OpenMPによる並列化

スレッド毎に擬似乱数発生機を準備し、それぞれをシード列の異なる部分を使って初期化を行う。

```cpp:parallel.cpp
#include <boost/random.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <vector>

#ifdef _OPENMP
# include <omp.h>
#else
  int omp_get_max_threads() { return 1; }
  int omp_get_thread_num() { return 0; }
#endif

int main(int argc, char **argv) {
  int num_threads = omp_get_max_threads();
  std::cout << "# num_threads = " << num_threads << std::endl;
  
  unsigned long seed = 1234;
  boost::minstd_rand seed_gen(seed);
  std::vector<boost::shared_ptr<boost::mt19937> > gens(num_threads);
  #pragma omp parallel
  {
    int tid = omp_get_thread_num();
    for (int p = 0; p < num_threads; ++p) {
      if (p == tid)
        gens[p].reset(new boost::mt19937(seed_gen));
      #pragma omp barrier
    }
  }

  int count = 16;
  #pragma omp parallel
  {
    int tid = omp_get_thread_num();
    boost::mt19937& gen = *gens[tid];
    boost::uniform_real<> dist;
    for (int i = 0; i < count; ++i) {
      #pragma omp critical
      std::cout << tid << ' ' << i << ' ' << dist(gen) << std::endl;
    }
  }
}
```

`gens`は`num_threads`個の乱数発生器へのポインタを保持する配列である。乱数発生機の初期化

```cpp
  #pragma omp parallel
  {
    int tid = omp_get_thread_num();
    for (int p = 0; p < num_threads; ++p) {
      if (p == tid)
        gens[p].reset(new boost::mt19937(seed_gen));
      #pragma omp barrier
    }
  }
```

は単に

```cpp
  for (int p = 0; p < num_threads; ++p) {
    gens[p].reset(new boost::mt19937(seed_gen));
  }
```

と書いても論理的には同じであり、実際、実行結果も等しくなるが、各乱数発生器を各スレッドの「近く」のメモリ上に配置するために、`parallel`領域の中で順番にオブジェクトを`new`している。(ファーストタッチ)

乱数生成器を使う際は、

```cpp
  #pragma omp parallel
  {
    int tid = omp_get_thread_num();
    boost::mt19937& gen = *gens[tid];
    // do some work
  }
```

のようにリファレンス`gen`を定義すると、その後のコードがシリアルの場合と全く同じように書けて便利である。

なお、上のコード例`parallel.cpp`では、各スレッドからの出力が1行の中で混じり合ってしまわないように、`critical`ディレクティブを挿入しているが、実際の計算では不要であり、性能低下の原因となるので入れるべきではない。
zsh の killring を拡張する

# はじめに

zsh の killring はかなり使い辛いと前々から思っていたので、改善してみました。

# killring のサイズを増やす

zsh の killring はデフォルトでサイズが 8 に固定されているので、まずはこれを増やします。

```zsh:.zshrc
function expand-killring(){
    killring+=( '' )
    zle ${WIDGET#expand-}
}

function {
    local widget

    for widget in kill-{buffer,line,region,whole-line} {backward-,}kill-word copy-region-as-kill; do
        zle -N expand-$widget expand-killring
    done
}

# キーバインドはお好みで
bindkey '^X^K' expand-kill-buffer
bindkey '^K'   expand-kill-line
bindkey '^W'   expand-kill-region
bindkey '^U'   expand-kill-whole-line
bindkey '^[d'  expand-kill-word
bindkey '^[h'  expand-backward-kill-word
bindkey '^[w'  expand-copy-region-as-kill
```

これで killring のサイズ制限がなくなりました。

# yank 時に killring の一覧から選択する

killring に保存できるテキストが増えたら、yank 時に一覧から選択したくなるのが人情ってもんです。peco を使っている場合はこんな感じです。

```zsh:.zshrc
function peco-yank(){
    local -U texts=( $CUTBUFFER $killring )
    local selected="$(peco --prompt 'Kill Ring>' <<< ${(F)texts})"

    if [[ -n "$selected" ]]; then
        zle -f yank
        YANK_START="$CURSOR"
        LBUFFER+="$selected"
        YANK_END="$CURSOR"
        CUTBUFFER="$selected"
        killring=( $texts )
    fi

    zle clear-screen
}

zle -N peco-yank
bindkey '^[Y' peco-yank
```

直前に kill したテキストは `killring` ではなく `CUTBUFFER` に保存されているので、まとめて選択候補にするようにしてます。また yank したテキストを `CUTBUFFER` に設定し直すことで `Ctl-y` で連続して yank できるようにしてあります。

# まとめ

上記設定はまだ使い込んでいないので改善の余地があるかもしれませんが、これだけで killring の使い勝手がかなり向上した気がします:metal:
ライフゲームをOpenMP, CUDAで実装したときのベンチマーク

# 比較内容
ライフゲームを、C++, OpenMP, CUDAを使用して実装した時のベンチマークです。描画にはOpenGLを使用しました。参考としてJavaScriptを使用したときの数値も載せていますが、アルゴリズムが異なるので参考程度です。

## CUDA最適化内容
- メモリ配置 (pinned memory)
- Shared Memory
- Stream (パイプライン化)
- メモリコピー回数の削減

# 実行環境
- Core i7-6400 @3.4GHz
    - 4 cores (8 logical cores)
- GeForce GTX 1070 @1.531GHz
    - 1920 CUDA Cores
    - 15 SMs
    - 256GByte/s (256 bit x 8Gbps)

# 結果
Generation Per Second (この数字が大きいほど高速)

| Size     |   512 x 512 | 1024 x 1024 | 2048 x 2048 | 4096 x 4096 | 8192 x 8192 |
|:---------|------------:|------------:|------------:|------------:|------------:|
|JavaScript| 34          | 9           | 2.6         | 0.63        | 0           |
| C++      | 500         | 83          | 19          | 5.35        | 1.2         |
| OpenMP   | 1000        | 250         | 66          | 19.61       | 4.5         |
| CUDA     | 1000        | 1000        | 250         | 76.92       | 18.18       |
| CUDA + Optimization | 1000 | 1000 | 1000 | 125 | 43.48 |

縦軸は対数です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/db6dee32-37c5-6a61-5d06-4ffd243bdf1d.png)

# ソースコードと実行結果ビデオ
Youtube [![Link to Youtube](http://img.youtube.com/vi/XFuT3gJwPT0/0.jpg)](http://www.youtube.com/watch?v=XFuT3gJwPT0)
https://github.com/take-iwiw/LifeGameFast
プログラムを書く時に気をつけること４つ

詰まることが多いので自戒の念を込めてメモ

# 影響範囲
自分が書いたコードにどれだけの影響力があるのか。
例えば、

* グローバルなオブジェクトを直接触って本当に他のところに支障をきたさないのか
* 定義されてる関数の命名ちょっと変えた時にその関数他の所で使われてないのか
* testを書いたほうがいい場所

など

# アプローチ
一つの課題に対するアプローチを、コードを書く前に考える習慣。みたいなものが全然なくて残念な資産を生み出してしまいがちなので、すごく大事なのでは？と思っている。

* そのコードはそこに書いて本当に適切なのか
* そもそもそんなこと書く必要あるのか
* その機能は理想的か

自分がなぜそうやって書いたのか理由を説明できるコードを書く。
# コンテキスト
コンテキスト(文脈)を意識していないとアクセスできないデータにアクセスしようとしてハマリがち。
データ自身が置かれているコンテキストを意識しながら書けばそういう所で詰まらなくなるはず。
# データ構造
データを操作する時は

* 配列なのか
* オブジェクトなのか
* 入れ子になっているのか、なっていないのか

などがわかっていないとできないので大事。
特に引数と戻り値のデータ構造は把握して置くと詰まる回数が変わるはず。
型のある言語にする選択肢もあり。

## まとめ
当たり前なのかもしれないけど、意識していきたい。
LSTMを用いた不正アクセス検知を考察してみる。

前回はcharacter-level CNNによる悪性URLの検出について考えてみましたが、
今回はLSTMを用いた不正アクセスの検知を考えてみたいと思います。

自分の考えをまとめているだけなので読みづらいとこなどあるかもしれませんがご了承下さい。


#LSTMによる異常検知手法

①過去の時系列データを学習させる。
②LSTMによる予測させたデータと実際に観測された実データを比べる
③予測データと実データの差が閾値を以内であれば正常、超えれば異常とみなす。

というのが大まかな流れです。


#LSTMを用いた不正アクセス発見の手法の提案

今回はあるIPアドレスから、ログに保存されたGET先のURLとPOST先のURLがあるとして進めていきます。
例として

```url_log.txt
①http://google.com/~~~~
②http://google.com/~~~~
③http://google.com/~~~~
④http://giita.com
⑤http://giita.com
⑥http://yahoo.co.jp
.
.
.
```
があったとします。実際のログは凄まじい量だとおもいます。
ここからLSTMに読ませるための時系列データを作成します。
まずはモデルの学習の入力に用いるデータをX_trainとしております。


```
X_train1=[[①http://google.com/~~~~],
         [②http://google.com/~~~~],
         [③http://google.com/~~~~],
         ]
X_train2=[[②http://google.com/~~~~],
         [③http://google.com/~~~~],
         [④http://qiita.com/~~~~],
         ]
X_train3=[[③http://google.com/~~~~],
         [④http://qiita.com/~~~~],
         [⑤http://qiita.com/~~~~],
         ]
```
こんな感じに一つずつズラして行くようなイメージです。
LSTMは文字列を直接文字として入力することができないので文字を数字に変換したりする必要があります。

入力データX_trainに対する出力をY_trainとすると

```
Y_train1=[④http://qiita.com/~~~~]
Y_train2=[⑤http://qiita.com/~~~~]
Y_train3=[⑥http://yahoo.co.jp]
```
となります。各X_trainの次に現れるデータを示しています。

これをLSTMに学習させて接続先のパターンを学習させます。
予測値と実データが大きく異なればウイルスによる不正アクセスが行われているのではないか？と考えることができます。
データを１年分ぐらい食わせてみれば面白い結果が出そうです。

#問題点
・食わせるデータが正しいという保証が必要になる。
→不正アクセスが行われているデータを学習させたら不正アクセスを検知できない。

・新規の接続先に対して有用なのか？
→LSTMは過去に現れた接続先のパターンを学習して次の予測で接続先を決定します。仮に安全でも過去にないアクセス先が現れたら異常とみなすのでは。


#個人的結論

新規のアクセス先が現れるたびに異常検知とみなしていれば、わざわざLSTMを使う必要もない。
新規アクセス先が現れてそれが正常か異常かを判断する仕組みが必要。
メモリの少ないマイコンでもフレームバッファを使いたい

STM32でデジカメを作成した時の小技

# 背景と問題点
- STM32F4 DiscoveryボードにはRAMが192KBしかない。
- 320x240x16bitのフレームバッファ(153.6 KB)として使用するのは無理
- JPEGエンコードなどの重い処理を、カメラ撮像と同時にやるのは無理 (Hブランキングを増やせば、ライン単位ならいけるかも?)
- そのため、1フレームの画をマイコン外のどこかに保持する必要がある。

# 解決策
- 電子工作で使用するような液晶ディスプレイは通常、GRAMとコントローラが一緒になったモジュールになっている
- LCDモジュールのGRAMをフレームバッファとして使う。

普段はこんな感じで、カメラ(DCMI)->LCD(FSMC)に画データを垂れ流す (ライブビューを想定)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/3795a469-5257-414c-027b-4d6730a32b75.png)

いざ画像データを使用して処理するタイミングになったら、カメラ撮像を止める。LCDモジュール内のメモリを使って、重い処理もゆっくり実行可能。また、FSMCを使用しているので、通常のメモリアクセスと同様に扱うことが可能。 (シャッターボタンを押したときの静止画撮影を想定)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/6c2febd1-9368-e25d-ecba-ebd1f8a84295.png)

↑の図だと読み込みのピクセルフォーマットをRGB565と書いてしまっていますが、実際にはRGB888になります。たとえ書き込みがRGB565フォーマットでも、読み出すときはRGB888になるようです(仕様書にそのような記述は見当たらなかったのですが、実際にこのように動いていました)。
[このパワポ](https://www.slideshare.net/TakeshiIwanari/how-to-create-digital-camera-with-stm32f4-discovery-board)に、タイミングチャートなど、もう少し詳細を記載しています。
STM32マイコンでFSMCを使用する際のアドレスについて

STMマイコンを使用して液晶ディスプレイ(LCD)などを制御する際に、FSMC (Flexible Static Memory Controller)を使用すると制御を簡単にできます。16-bitモードの時には、アドレスが1ビットシフトするので注意が必要です。 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/1556b5df-8116-f3be-2abb-2719163bf029.png)


下記設定を考えます。
- 使用するマイコンはSTM32F407 (メモリマップは下記)
- FSMCのbank1を使用する
- LCDのRS (制御コマンドとデータ通信の切り替え信号)をA16に割り当てる
- ビット幅は16-bitモード

![image.png](https://qiita-image-store.s3.amazonaws.com/0/214268/67bc48fc-255a-18e8-1d00-a4c238342f03.png)


このとき、制御コマンドのためにRS = 0とするには、0x60000000にアクセスすればOKだとメモリマップからわかります。一方、データ通信のためにRS = 1とするには、0x60020000にアクセスする必要があります。

A16をRSに割り当てたので、ベースアドレス(0x60000000) + 2^16で0x60010000が対象アドレスだと思ってしまいがちですが、データシートをよく見ると下記のような記載がありました。つまり、1ビットシフトされるのです。そのため、実際にアクセスすべきアドレスは0x60020000となります。
> In 16-bit mode, data address issued to the memory is HADDR[25:1] >> 1

[このパワポ](https://www.slideshare.net/TakeshiIwanari/how-to-create-digital-camera-with-stm32f4-discovery-board)に、もう少し詳細を記載しています。
プログラミングをよく知らない初心者が開発スピードをほんのちょっと上げた話

#すぐ終わります
自己紹介とかは特にいらないかと。
前ちらっと書いた記事載せておきます。
[コチラ](https://qiita.com/minakenty321/items/da213cac83bce9884a67)

#じゃあどうしたのか
PHPerならみなさんこれは知ってますよね。

```php
var_dump
```

変数とかぶち込んでvar_dumpして中身を確認してました。
もちろんこれ便利です。型を確認したり中身何入ってるのか見れます。

実際どう使うかっていうと

```php
$hoge = rand(1,10);
var_dump($hoge);
```

としておくと$hogeに入ってる1~10までの整数が見れるっていう感じです。
**もちろん便利ですよね？**

はい。便利です。でも中身確認して、それ以降の処理したくない時ってあるじゃないですか。
そうしたときは

```php
$hoge = rand(1,10);
var_dump($hoge);
exit('OK');
```

とかってやってたんです。というか開発したことある人にとっては当たり前なのかもしれません。僕にはなんか楽しくて、すごいことだと思ってました。

でもある時、毎回exit;ってかくのめんどくさいって思ってしまい、別の方法を取ることにしました。

それがこれです。

```php
$hoge = rand(1,10);
dd($hoge);
```

最初使った時はすげーってなってました(笑)
手間減ったなーって思いました。
ブレーク？っていうのかexitのかわりに止めてくれるらしいのでありがたいし、見やすかった!

あとたまにddしてても画面に表示されない処理があって、
**どうすんの…まじムリ…**
って嘆いてた時に

```php
Log::info($hogehoge);
```

ってのがあって、logに吐き出してくれるっていうものも知りました。
たしか、storage/log/laravel.logに出してくれた気がします(曖昧ですみません)

これならtailコマンドで追っかけていれば変化も分かりやすいかな―とか思ったり。
僕だけかもしれないのですが、どの処理でエラーになっているのか、どこが変な挙動をしているのかすぐに判明できないんですよね。やっと場所が特定できて、中身見たらお前コレクションやないかい。みたいな気づきもあったりします。なのでvar_dumpしまくってたんですが、若干文字少なくて見やすいということでddに変えたらほんの少しスピードが上がりましたよ！塵も積もれば山となる！
というお話でした。

自分はこういうの使ってるよ。とかアドバイス等頂けたら嬉しいです。
いいねもモチベにつながります！
STM32マイコンでOV7670などとSCCB通信する際の注意点

# STM32 (HAL)によるSCCB通信
OmniVisionのカメラは制御用のインタフェースとしてSCCBを採用しています。SCCBはI2Cとほぼ同じですが、最終ビットにACK/NACKがありません。HALのI2C関数で単純にカメラからREADすると、ACK待ちでタイムアウトが発生します。

HAL_I2C_Mem_Readを使わずに、HAL_I2C_Master_TransmitとHAL_I2C_Master_Receiveに通信を分けてあげることで対処できます。

```c:ov7670.c
static RET ov7670_read(uint8_t regAddr, uint8_t *data)
{
  HAL_StatusTypeDef ret;
  do {
    // HAL_I2C_Mem_Read doesn't work (because of SCCB protocol(doesn't have ack))? */
//    ret = HAL_I2C_Mem_Read(sp_hi2c, SLAVE_ADDR, regAddr, I2C_MEMADD_SIZE_8BIT, data, 1, 1000);
    ret = HAL_I2C_Master_Transmit(sp_hi2c, SLAVE_ADDR, &regAddr, 1, 100);
    ret |= HAL_I2C_Master_Receive(sp_hi2c, SLAVE_ADDR, data, 1, 100);
  } while (ret != HAL_OK && 0);
  return ret;
}
```
Google AutoMLのNASNetでObjectDetection

Google社のAutoMLで自動学習されたNASNetが、人間が構築してきたモデルよりも精度が高いということで、早速試してみました。

### 実行環境
- AWS EC2 p3.2xlarge
- Ubuntu16.04
- cuda-9.0, cuDNN-7.0
- tensorflow r1.4 (ソースビルド)
- python 3.5.2

精度と実行速度は下記を参照してます（テスト画像とは無関係のベンチマーク結果）。
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md 

### faster_rcnn_nas(1833ms, mAP=43%)
![frcnn_nasnet_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/8c4fa64f-2403-cf8c-1fe5-f21df4ae382d.png)

![frcnn_nasnet_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/0c355571-064d-c737-ce6c-1651003e446f.png)

### faster_rcnn_nas_lowproposals_coco(540ms, mAP=NaN)
こちらはregion proposal数を落として、総局所分類数を減らして高速化したモデルになってるようです。
テスト画像ではほぼ差は見られませんでした。
![frcnn_nasnet_lowproposals_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/d3b8f885-ebac-aa57-d0bb-73d661585188.png)

![frcnn_nasnet_lowproposals_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/9f68e745-332d-de0a-2ead-ea6a1c90a624.png)

参考までに他のモデルの結果も

### faster_rcnn_inception_resnet_v2_atrous_coco(620ms, mAP=37%)
![frcnn_resnetv2_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/4c8697e4-4a9d-4c1e-2d3a-e58b9bf1ee31.png)

![frcnn_resnetv2_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/b6da9e21-b49f-98dc-04ef-3e1fbd7c11b2.png)

### faster_rcnn_resnet101_coco(106ms, mAP=32%)
![resnet101_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/72d8a393-a6d4-dd75-5518-40e92e2dca04.png)

![resnet101_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/60895d8b-00bd-25f8-785e-db5fc01502ec.png)

### rfcn_resnet101_coco(92ms, mAP=30%)
![rfcn_resnet101_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/6505a97c-fc58-0231-3bb0-9a2a9a967253.png)

![rfcn_resnet101_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/5cb1e071-fe56-5d98-c6c8-1fcaeecc1d41.png)

### ssd_inception_v2_coco(42ms, mAP=24%)
![ssd_inception_v2_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/ffd5e1aa-0b4a-e202-5bd8-f76650763c55.png)

![ssd_inception_v2_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/f1913470-9018-3802-d75a-4382242eafa3.png)

### ssd_mobilenet_v1_coco(30ms, mAP=21%)
![ssd_mobilenet_1.png](https://qiita-image-store.s3.amazonaws.com/0/100746/60b179d6-71d7-60b3-fa32-c0ba81ed70d5.png)

![ssd_mobilenet_2.png](https://qiita-image-store.s3.amazonaws.com/0/100746/cf11e091-6bed-f7bc-1564-3989b988b408.png)

NASNetは精度は高い（特にresion proposalにおけるfalse positiveの低減が顕著）のですが、ネットワークの規模が大きく推論速度が遅いので、2017年11月現在ではJetson(TegraX2,X1)のようなデバイス(SoC)への搭載や、リアルタイム物体認識用途にはまだまだ厳しいと思われますね。
NASNetのエッジ側での応用には、さらなるプロセッサの高性能化、ネットワークの縮小、処理の最適化（目的に応じたregion proposal数の調整等）などが望まれると思います。

一方で、リアルタイム性の要件がそこまで厳しくないものについて、画像認識WebAPIの推論エンジンとしての応用は適性が高いかと思いました。

参考:
https://arxiv.org/pdf/1707.07012.pdf
https://github.com/tensorflow/models/tree/master/research/object_detection
https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/detection_model_zoo.md
Jenkins”だけ”でほんとうにできること

#はじめに
グーグル先生に「Jenkinsとは」って聞いてみると、大体、

<b>「継続的インテグレーションですごい！」
「自動化出来て効率アップ！」
「ビルド、テスト、デプロイまで自動で出来る！」</b>

・・・という情報ばかりで、「実際使えるの？どうやって使うの？」って部分が見えてこないので、実際に使ってみようとした結果です。

#インストールして、1日触ってわかったこと
「これ、ただのcronですやん・・・」

#もう少し詳しく
色んなサイトで語られている「便利」を具体的に落とすと、

自動化出来る⇒〇
ビルド自動化⇒△
テスト自動化⇒△
評価自動化⇒×
デプロイ自動化⇒△

自動化出来る⇒〇　Jenkinsはいろんなトリガをもった便利なcron/タスクスケジューラみたいな感じで、外部連携も得意っぽいので<b>（頑張れば）</b>色々自動化できる。

>↓こんな感じでcron風に定時起動させたり（定期的に実行）、他のジョブの後に実行するように設定してジョブ連携させたり（他プロジェクトの後にビルド）、ポーリング監視してソースコードの更新があったら動くように（SCMをポーリング）、とか設定できる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/8c250545-9562-7a7e-83fd-558bad41b1e5.png)
>
>↓Jenkinsの中にシェルやバッチを書いて実行させることも出来る。AntやMavenの呼び出しもここから。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/0d84097e-1f2e-c35e-83d2-10ffcaa44b51.png)

<br>
ビルド自動化⇒△　基本的にant,MavenといったビルドツールをJenkinsが呼び出して自動化するという方法が主流（Jenkinsはただの実行トリガ）。makeファイルやコンパイルファイルを自前で作って、Jenkinsに設定した起動条件に当てはまれば自動実行する、というようなことをビルド自動化っていう風に言っているだけ（たとえば定時に実行する、ソースファイルに変更が入ったら実行する等）。
<br>
テスト自動化⇒△　JUnit等のテストツールをJenkinsが呼び出して自動化するという方法が主流（Jenkinsはただの実行トリガに過ぎない）。テストプログラムを自前で作って、Jenkinsに設定した起動条件に当てはまれば自動実行する、というようなことをテスト自動化っていう風に言っているだけ（たとえばビルドジョブが成功したら実行する、等）。
<br>
評価自動化⇒×　Cobertura、Checkstyle、FindBugs、JavaNCSSなどの外部ツールを起動し、その結果を受け取ることはJenkinsで出来る。Jenkins本体に評価ツール等があるわけではない。

>↓ジョブの実行結果を一覧で見るぐらいは出来る
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/313dc493-930c-3902-672c-570218c872e5.png)
>
>↓ジョブの実行結果コマンドを見ることも出来はする
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/7116a926-db80-eeec-5318-4342baaeaae9.png)

<br>
デプロイ自動化⇒△　コピーやムーブのコマンドを書いたバッチやシェルを、Jenkinsから起動すればデプロイ自動化を実施できる。って感じ。ただし、そのバッチやシェルは一から自前で作る必要あり。

※Jenkinsを便利に使うためにはいろんな外部ツールを入れないといけないので、基盤屋さんからすれば「なんでもかんでも入れんじゃねぇ！」って怒られるかなと思います。管理対象物が増えるので。

#結論
「これ、ただのcronですやん・・・」（２回目）

もちろん、自動化するための設定を作ってしまえば、あとは簡単なGUI操作で何億回でもJenkinsが再実行して、その結果を連携してくれます。そこは超便利でコスト抑制になると思います。

ただし、あくまで自動実行までの大量のお膳立てを、ほぼ手作業で実施することが大前提になります。もちろん、そのお膳立て（＋Jenkins側の実行設定）はヒトが管理するので、そこの属人化を避ける運用も考える必要があるかと。

なので、「何でもかんでも出来るすごいやつ」って考え方は早々に修正すべきと思います。思いました。（そうさせるウェブサイトが多すぎるのも問題ですかね）

参考：
Jenkins実践入門
http://gihyo.jp/book/2011/978-4-7741-4891-5

オープンソースの自動テストツール／Jenkinsとは
https://www.ossnews.jp/oss_info/Jenkins
↑こことかほんとひどい
s2sをdockerで試してみたメモ


[さよならボイラープレート。s2sによる高速reduxアプリケーション構築][*2]が面白そうなので試してみた。
最近パッケージを直接インストールしたくないドッカーマンになりつつある。

ツイッターで作者さんが活動的なので、詰まったところで声かけたら即答で回答がもらえた。
すごい。

## 動作環境

* windows10
* vagrant1.9.7
* virtualbox5.1.26
* ubuntu-16.04
* Docker version 17.09.0-ce, build afdb6d4
* docker-compose version 1.17.1, build 6d101fb

### ディレクトリ構成

```
- app
  - docker
    - s2s
      - Dockerfile
    - docker-compose.yml
  - src
    - index.js
```

## Dockerの設定

[クイックスタート](https://github.com/akameco/s2s/tree/master/docs/ja#クイックスタート)を参考にdockerfileを作成。

最初に試したときはファイルの更新が検知できていなかったので、ファイルをwatchしているchokidarのポーリング設定を有効にしておく。[*][*1]

```docker:docker/s2s/Dockerfile
FROM node:9.1.0

# コンテナ上の作業ディレクトリ作成
WORKDIR /app

# ソースダウンロード
RUN git clone --depth=1 https://github.com/akameco/s2s.git

# chokidarのポーリング設定
RUN sed -i -e "s/\(ignoreInitial: true,\)/\1\n    usePolling: true, /g" /app/s2s/packages/s2s-cli/src/index.js

# s2sをビルド
WORKDIR /app/s2s/
RUN yarn

# example用設定
WORKDIR /app/s2s/examples/getting-started
RUN yarn
RUN yarn run flow
```

ディレクトリはexampleのsrcとローカルのsrcを同期させるように設定しておく。

```yaml:docker/docker-compose.yml
version: '3'
services:
  s2s:
    build: ./s2s
    volumes:
      - ../src:/app/s2s/examples/getting-started/src
    command: [yarn, run, s2s]
```

dockerのビルド、実行を行う。

```
cd docker
docker-compose build
docker-compose up
```

srcディレクトリに、exampleのjsを設置して保存。

```js:src/index.js
/*
 * @flow
 * Welcome to s2s https://github.com/akameco/s2s.
 * This example is very small. However Useful :)
 * This plugin is that initializing variable with flow information. 
*/

type User = { id: number, name: string }
// type `var user: User` and save!
var user: User 
```

[この時点のソース](https://github.com/hibohiboo/develop/tree/b930408f521a8ae11254bf7a5f87bf3e3782bb55/tutorial/lesson/s2s)

保存したら、無事コード補完成功！

![s2s.png](https://qiita-image-store.s3.amazonaws.com/0/99876/89402525-aa80-6f40-a698-e6bb87f836d0.png)


今日は遅いので続きを試すのはまた後日。

## 参考

[nfsをgulp watchできない時にやったこと][*1]
[さよならボイラープレート。s2sによる高速reduxアプリケーション構築][*2]

[*1]:https://www.kimurak.net/wordpress/angularjs/2372/
[*2]:https://qiita.com/akameco/items/e1489c6bbf3439ec6ca4
CUDA 9.0のインストール方法 (Visual Studio 2017用)

CUDA 9.0をWindows10上でVisual Studio 2017向けにインストールする方法です。過去のバージョンだと色々とやる必要があったのですが、このバージョンの組み合わせでは特に問題なくインストールできます。ただ、一点だけ引っかかるポイントがあったので、そのメモ代わりです。

下記動画でも説明しています。  
[![Link to Youtube](http://img.youtube.com/vi/GmgfjWJmpf8/0.jpg)](http://www.youtube.com/watch?v=GmgfjWJmpf8)

## Visual Studio
### Visual Studioインストーラのダウンロード
下記サイトから環境に合ったインストーラをダウンロードする。無料のVisual Studio Community 2017でOK。  
https://www.visualstudio.com/downloads/

## Visual Studioのインストール
<strong> 重要なポイントです </strong>  
Visual Studioをインストールする際には、<strong>Windows 10 SDK</strong>のコンポーネントを必ずインストールするようにしてください。デフォルトでは無効になっているようです。”C++によるデスクトップ開発"の下にあります。これをインストールしないと、後でCUDAプロジェクトをビルドするときに、`fatal error LNK1104: cannot open file 'gdi32.lib'`が出ます。
<img width="60%" alt="VS Install" src="https://qiita-image-store.s3.amazonaws.com/0/214268/2d71a761-7c51-bf43-3fab-b34d595a6cd7.jpeg">

## CUDA Toolkit
### CUDA Toolkitインストーラのダウンロード
下記サイトから環境に合ったインストーラをダウンロードする。  
https://developer.nvidia.com/cuda-downloads  
<img width="60%" alt="CUDA Download" src="https://qiita-image-store.s3.amazonaws.com/0/214268/d5686ab6-eaa8-5946-318a-8f87bb598bda.jpeg">

### CUDA Toolkitのインストール
特に引っかかるポイントはないです。全てデフォルトでOKをクリックしていけば大丈夫です。

## CUDAプロジェクトの作成
インストールに成功したら、VSの新規プロジェクトの追加画面に、CUDA用のテンプレートが追加されているはずです。  
<img width="60%" alt="CUDA Project" src="https://qiita-image-store.s3.amazonaws.com/0/214268/96f1d020-0136-b98b-96a9-9f1977052786.jpeg">

## 実際のプロジェクトに取り込む
CUDAプロジェクト単体だと使いづらいと思います。CUDA処理をライブラリ化するのがいいかと思います。こちらもご参考にしてください。
https://qiita.com/take-iwiw/items/7f4e5a84b3e49aa7fbb1

# 追記 (2018/2/2)
最近のバージョンのVisual StudioとCUDAの組み合わせだと、ビルド時にバージョンチェックでエラーが発生するっぽい。`_MSC_VER`の値がおかしい? `vcvars64.bat`を実行すれば治るかも。

↓で語られている。
https://devtalk.nvidia.com/default/topic/1022648/cuda-9-unsupported-visual-studio-version-error/ 

# 追記 (2018/9/30)
今現在においても、Visaul Studio 2017のマイナーバージョン(_MSC_VER>1911)とCUDA9.0のバージョン問題は解決されていない模様。
CUDA10だと_MSC_VER=1920までサポートされているようなので、素直に乗り換えた方がいいっぽい。
スペイン語とポルトガル語の動詞の活用(tener/ter, ir)

いずれ自然言語処理とかで使うかもしれないので、自分のためにまとめておきます。
スペイン語とポルトガル語は似ているので、並べて見たいのも動機にあります。

# tener/ter(持つ)
## 直接法
| 人称  | 現在(ス) | 点過去(ス) | 線過去(ス) | 現在(ポ) | 完了過去(ポ) | 不完了過去(ポ) |
|:----------|:-------|:---------|:--------|:------|:--------|:--------|
| 1人称単数 | tengo  | tuve     | tenía   | tenho | tive    | tinha   |
| 2人称単数 | tienes | tuviste  | tenías  | tens  | tiveste | tinhas  |
| 3人称単数 | tiene  | tuvo     | tenía   | tem   | teve    | tinha   |
| 1人称複数 | tenemos| tuvimos  | teníamos| temos | tivemos | tínhamos|
| 2人称複数 | tenéis | tuvisteis| teníais | tendes| tivestes| tínheis |
| 3人称複数 | tienen | tuvieron | tenían  | têm   | tiveram | tinham  |

## 分詞
| 分詞  | (ス) | (ポ) |
|:---------|:--------|:-----|
| 現在分詞 | teniendo| tendo|
| 過去分詞 | tenido  | tido |


# ir(行く)
## 直接法
| 人称  | 現在(ス) | 点過去(ス) | 線過去(ス) | 現在(ポ) | 完了過去(ポ) | 不完了過去(ポ) |
|:----------|:-----|:--------|:------|:-----|:------|:-----|
| 1人称単数 | voy  | fui     | iba   | vou  | fui   | ia   |
| 2人称単数 | vas  | fuiste  | ibas  | vais | foste | ias  |
| 3人称単数 | va   | fue     | iba   | vai  | foi   | ia   |
| 1人称複数 | vamos| fuimos  | íbamos| vamos| fomos | íamos|
| 2人称複数 | vais | fuisteis| ibais | ides | fostes| íeis |
| 3人称複数 | van  | fueron  | iban  | vão  | foram | iam  |

## 分詞
| 分詞  | (ス) | (ポ) |
|:---------|:-----|:----|
| 現在分詞 | yendo| indo|
| 過去分詞 | ido  | ido |
スペイン語とポルトガル語の動詞の活用(規則動詞)

いずれ自然言語処理とかで使うかもしれないので、自分のためにまとめておきます。
スペイン語とポルトガル語は似ているので、並べて見たいのも動機にあります。

# -ar型動詞　amar(愛する)
## 直接法
| 人称  | 現在(ス) | 点過去(ス) | 線過去(ス) | 現在(ポ) | 完了過去(ポ) | 不完了過去(ポ) |
|:----------|:------|:--------|:--------|:------|:-------|:-----|
| 1人称単数 | amo   | amé     | amaba   | amo   | amei   | amava|
| 2人称単数 | amas  | amaste  | amabas  | amas  | amaste | amavas|
| 3人称単数 | ama   | amó     | amaba   | ama   | amou   | amava|
| 1人称複数 | amamos| amamos  | amábamos| amamos| amamos | amávamos|
| 2人称複数 | amáis | amasteis| amabais | amais | amastes| amáveis|
| 3人称複数 | aman  | amaron  | amaban  | amam  | amaram | amavam|

## 分詞
| 分詞  | (ス) | (ポ) |
|:---------|:------|:------|
| 現在分詞 | amando| amando|
| 過去分詞 | amado | amado |


# -er型動詞　comer(食べる)
## 直接法
| 人称  | 現在(ス) | 点過去(ス) | 線過去(ス) | 現在(ポ) | 完了過去(ポ) | 不完了過去(ポ) |
|:----------|:-------|:---------|:--------|:-------|:--------|:--------|
| 1人称単数 | como   | comí     | comía   | como   | comi    | comia   |
| 2人称単数 | comes  | comiste  | comías  | comes  | comeste | comias  |
| 3人称単数 | come   | comió    | comía   | come   | comeu   | comia   |
| 1人称複数 | comemos| comimos  | comíamos| comemos| comemos | comíamos|
| 2人称複数 | coméis | comisteis| comíais | comeis | comestes| comíeis |
| 3人称複数 | comen  | comieron | comían  | comem  | comeram | comiam  |

## 分詞
| 分詞  | (ス) | (ポ) |
|:---------|:--------|:-------|
| 現在分詞 | comiendo| comendo|
| 過去分詞 | comido  | comido |


# -ir型動詞　partir(出発する)
## 直接法
| 人称  | 現在(ス) | 点過去(ス) | 線過去(ス) | 現在(ポ) | 完了過去(ポ) | 不完了過去(ポ) |
|:----------|:--------|:----------|:---------|:--------|:---------|:---------|
| 1人称単数 | parto   | partí     | partía   | parto   | parti    | partia   |
| 2人称単数 | partes  | partiste  | partías  | partes  | partiste | partias  |
| 3人称単数 | parte   | partió    | partía   | parte   | partiu   | partia   |
| 1人称複数 | partimos| partimos  | partíamos| partimos| partimos | partíamos|
| 2人称複数 | partís  | partisteis| partíais | partis  | partistes| partíeis |
| 3人称複数 | parten  | partieron | partían  | partem  | partiram | partiam  |

## 分詞
| 分詞  | (ス) | (ポ) |
|:---------|:---------|:--------|
| 現在分詞 | partiendo| partindo|
| 過去分詞 | partido  | partido |
Ebeanでテーブルを結合し、フィールドの値を比較したい

## eq()はフィールド = 値

EbeanでWhere句を用いて条件を指定する手段の1つにeqメソッドがあり、テーブルの結合にも利用することが可能です。
しかし、フィールド同士の比較でeqメソッドを使用することは不可能です。

例えば、「親テーブルと結合し、親テーブルのフィールドAとBの値が等しい場合、子テーブルのレコードを取得する」SQLを実行したい場合、

```java:例
ChildrenModel.where().eq("parent.columnA", "parent.ColumnB").findList();
```

↓

```sql:実際に出力されるSQL文
select
    t0.id c0, t0.text c1, t0.create_time c2, t0.update_time c3, t0.parent_id c8, t1.id c9
from
    children t0
left outer join
    parent t1
on
    t1.id = t0.parent_id
where
    (t1.columnA = 'parent.columnB')
```
なんと左辺の`parent.columnA`は、結合したテーブルだと認識され`t1.columnA`として変換されますが、右辺の`parent.ColumnB`がそのままの形で値となってしまっています…

そもそもeqメソッドは、eq(フィールド, 値)のように、渡された値を特定のフィールドから検索するような役割になっているため、上記の目的とは若干違っています。

そこで、raw()メソッドを使用することで、この問題が解決できます。

## raw()ならフィールド同士の値を比較できる

```java:例
ChildrenModel.where().raw("parent.columnA = parent.ColumnB").findList();
```

↓

```sql:実際に出力されるSQL文
select
    t0.id c0, t0.text c1, t0.create_time c2, t0.update_time c3, t0.parent_id c8, t1.id c9
from
    children t0
left outer join
    parent t1
on
    t1.id = t0.parent_id
where
    (t1.columnA = t1.columnB)
```
ちゃんとフィールド同士の値を比較できているのが確認出来ました！


## 参考URL
[Ebeans where columnA equals columnB in same table - stack overflow](https://stackoverflow.com/questions/25319922/ebeans-where-columna-equals-columnb-in-same-table)
IIS10のPHPでファイルのアップロード

IIS10のPHP7でファイルのアップロードを行おうとすると、権限が足りずにエラーが出る。
これは、IIS10のPHP7の一時ファイルのアップロード先がC:\Windows\Tempだからである。
ここに権限を付与すると、アップロードが可能になる。

ブログ始めました。
[図解つきでの解説](https://nnahito.com/article/3/)はそちらにのせております。
Flaskを用いたwebサイトでのサイト内検索の実装

Flaskを使ってWebページを構築していると、サイト内検索を実装したくなった。
Googleカスタム検索で実装してもよかったが、折角なのでMongoDBとflask-mongoengineを使って構築した。

## 構築環境
- python
- flask
- mongoDB
- flask-mongoengine

データベースのコレクションはsampleだとする。
フィールドは performer,Genre,title があるとする。

コードは以下の通り

```py3:search.py
import flask
from flask import *
from flask_mongoengine import MongoEngine
from mongoengine.queryset.visitor import Q

@app.route('/search', methods=['GET'])
def search():
    #GETメソッドで取得した値があれば、スペースで区切った配列にする
    if request.args.get('message') != None:
        search_list = request.args.get('message').split()
    page_num = int(flask.request.args.get('page') or 1)
    result = sample.objects()
    for i in search_list:
        #繰り返しクエリを投げることでAnd検索を表現。
        #Like検索は　/'検索したい文字'/。しかし、ここでは変数を使っているので、'/' + i + '/' と書くと'/検索したい文字/'となってしまうので'$regex'ノーテーションを使う
        #Q() | Q() で or 条件にできる。
        result = result(Q(__raw__ ={'performer':{'$regex': i }}) | Q(__raw__ = {'title': {'$regex': i }}) | Q(__raw__ = {'Genre': {'$regex': i }}))
    result = result.paginate(page=page_num, per_page=30)
    return flask.render_template("search.html", result=result)
```
flask-mongoengine のpaginateメソッドを用いて検索結果のコンテンツを１ページに30個表示するように設定している。
見たとおり、or検索は実装していないが、あまり使わないので必要ないかと感じた。

あまり日本語でflaskとmongodbを組み合わせてwebサイトを作るといった趣旨の情報が少ないので、少しでも同胞の助けになれば。
プログラミング未経験者がエンジニア目指す（その5）

# 勉強会に参加してみた

- paizaで有名なギノ株式会社が開催する、初心者向けの無料勉強会に本日行ってきた。
- 内容としてはpaizaラーニングを通してRubyに触れる。
- 参加予定者10名だったが実際に参加したのは4名（男性1名、女性3名）だった。

##参加しようと思ったわけ

- N予備校でもまだRubyを勉強したことはなかったけど、勉強会ってどんなものか興味があったから参加してみた。
- 「勉強をせざるを得ない」環境で勉強がしたかったから。

## 内容

[Ruby入門1: プログラミングを学ぶ](https://paiza.jp/works/ruby/primerfemale/beginner-ruby1-female)
無料版のpaizaラーニング(Ruby)を実際にやってみる。seachanが1時間で進められたのは05変数を使えるようになろう、まで。

## 疑問

- Rubyの言葉の由来はなんだろう？

## 感想

- Rubyのコンセプトは「楽しくプログラミングをしよう」ということを学んだけど、本当にそうだと思った。開発した方がすごいと思った。
- Hello wordでプログラミングが始まるのは気持ちが良いと思う。

## 終わりに

- なんでかわからないけどもっとRubyを勉強したい。N予備校でもRuby勉強するのも、なんだか楽しみ。
- ギノ株式会社の現職のエンジニアさんとお話することができ、プログラミング未経験だけどエンジニア目指したいっていう話をしたらすごく喜んでくれて、こっちが嬉しくなった。
- 勉強会で現職のエンジニアさんと関わることも勉強だと思う。
ソーシャルログイン時のユーザーテーブルとログイン管理

# 概要

OAuthでログインする方法は検索すれば出てきますが、そのあとのログイン管理をどうしたら良いのだろうかと考えてみました。

# ログインとログイン後の流れ

1. ログイン時にユーザー情報を得る。
OAuthは以下を参考に行えばユーザー情報を得ることは可能という前提とします。
http://oauth2-client.thephpleague.com/providers/league/

2. ユーザー情報を元にアプリケーション側に通常ユーザーを作る。（アプリケーション側に該当ユーザーが存在しなければ）

3. ユーザーが既に存在している場合はgoogle_idやfacebook_idが未登録であれば登録する。（これで通常ログインもソーシャルログインも対応できる）

4. アプリケーション側の通常ユーザーと同様にアプリケーション側のユーザーIDで振る舞いを行う。アプリ内ではアプリのユーザーIDで管理する。

# ユーザーテーブル設計例

|  | id | display_id | google_id | facebook_id | mailadress | name | password | その他アプリに必要だと思われる情報<br>password_update_datetime<br>(パスワード有効期限判定)、<br>lastlogin_datetime<br>(アクティブユーザー)<br>等 | create_datetime | update_datetime | delete_datetime | delete_flag |
|:-----------:|:-----------:|:-----------:|:------------:|:------------:|:------------:|:------------:|:------------:|:------------:|:------------:|:------------:|:------------:|:------------:|
| 型 | INT | VARCHAR(255) | VARCHAR(255) | VARCHAR(255) | VARCHAR(255) | VARCHAR(255) | VARCHAR(255) |  | DATETIME | DATETIME | DATETIME | TINYINT(1) |
| 初期値 |  |  | NULL | NULL |  |  |  |  | CURRENT_TIMESTAMP | CURRENT_TIMESTAMP | NULL | 0 |
| その他 | AUTO_INCREMENT<br>UNSIGNED<br>NOT NULL | NOT NULL |  |  | NOT NULL | NOT NULL |  |  | NOT NULL | NOT NULL |  |  |

idでPRIMARY KEY
display_idでUNIQUE　表示用ID　uniqid()等で作る
facebook_idでUNIQUE
google_idでUNIQUE
password　パスワードハッシュ　null許可　password_hash()で作成
mailadressでUNIQUE（mailadressをキーにする）
初回ログイン時には名前は登録させる。

* 名前は取得してきた情報により本名になってしまうかもしれないので改めて登録させる
* ソーシャルログインの場合はパスワードは不要（取得したgoogle_idやfacebook_idが既に登録されているかでログイン処理を行う。idで登録されていなければemailメールアドレスで判定し登録済みならgoogle_idやfacebook_idを登録する）



**保存する(保存しても良い)情報等の扱いは利用するサービスの規約に従ってください**

海外のサービスには個人情報についての取り扱い等の記述は見当たりませんでしたが、
Oauthでの認可は個人情報を渡すことの許可にあたるそうなので許可が出れば保存しても問題なさそうです。

# アクセストークンの保持について

アクセストークンをDB等に保存して期限切れまで再利用する際は可逆暗号化すべきとのことです。また、保存するかしないかはアプリ側に委ねられているそうです。
危ういものは持ちたくないということで私は毎回トークンを取得しに行く方法でも良いかと感じました。

https://security.stackexchange.com/questions/72475/should-we-store-accesstoken-in-our-database-for-oauth2

# 参考

* [facebook id](https://stackoverflow.com/questions/7138119/saving-facebook-id-as-int-or-varchar)
* [google id](https://stackoverflow.com/questions/6872310/whats-the-best-column-type-for-google-user-id)

アクセストークン

* Facebook

https://developers.facebook.com/docs/facebook-login/access-tokens#errors
有効期限切れのトークンを処理する最善の方法は、APIによるエラーメッセージを取り込むことです。エラーが発生するごとに、APIはHTTP 400ステータスコード、コード、サブコードを、エラーの特徴を説明するJSON本体に含めて返します
https://developers.facebook.com/docs/facebook-login/access-tokens/debugging-and-error-handling#errors

* Google

無効なアクセストークンの際は401
https://cloud.google.com/docs/authentication#error_handling
今日学んだことを投稿する（echo -n)

メモリ使用量の調査を行ってたのですが
vmstatでfree領域だけ見ているとどんどん減っている。。。

DISKキャッシュも含まれているので右肩下がりでfree領域が減っていく。
今日は何もアプリケーションを動かしていない、おかしい。
ということで調べたらやっぱりそのとおりでした。

で、代わりに何を使うかなのですが
freeコマンドで対処します。

~~~Bash
free
              total        used        free      shared  buff/cache   available
Mem:        8053472     1349456     3173156       70792     3530860     6289800
Swap:             0           0           0
~~~

実に扱いにくいです。
加工します。

~~~Bash
free | grep -v total |cut -d : -f 2 
        8053472     1366300     3155696       70432     3531476     6273288
             0           0           0
~~~

複数行にまたがったデータを１行にまとめます。

~~~Bash
free | grep -v total |cut -d : -f 2 | xargs echo -n

8053472 1369856 3151772 70204 3531844 6269824 0 0 0

~~~

うまいところ１行で出力ができました！！　なかなか強烈 echo -n と　xargsの組み合わせ！