OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニアじゃない人がVimを学ぶメリット

こんにちは。
こちらは[LIGのアドベントカレンダー](https://qiita.com/advent-calendar/2017/lig)3日目の記事です。　
謎の力によって3日目に移りました。
[株式会社LIG](https://liginc.co.jp/)でWebディレクターをやっている[ともぞう](https://liginc.co.jp/member/member_detail?user=tomoki)といいます。
私はエンジニア出身でもなんでもないんですが使用するエディターはVimです。

本稿では下記の3つについて雑く書いていきます。

1. 使えるようになってよかったこと
2. なぜVimを使えるようなろうと思ったのか
3. 使えようになるまでの道のりを

Vim自体の説明はしません。ここはQiitaですしおすし。

## 使えるようになってよかったこと

### 文字の一括編集が楽

矩形選択はいい機能ですね。
接頭辞、接尾辞を一気に入れるときに大変便利です。

### 番号リストつくるの楽

`g` + `control` + `a`

数字を矩形選択してこのコマンドをやってみましょう。
たしか最近のアップデートで追加された機能です。
Vimはいまだに進化をするエディタです。

### 他のアプリケーションのショートカットの肥やしになる

`j` , `k` を使えるアプリケーションは多いです。

* ChatWork
* Gmail
* Google Drive

の上下選択は `j` , `k`が有効です。

### エンジニアっぽくなれる

黒い画面を開いておくとエンジニアっぽさがでます。
そのおかげでしょうか。なんでか初見の人にエンジニアですか？　と間違えられることも増えます。
新しく入ったエンジニアの人にいきなりSassの質問されたのはいい思い出です。

### プレーンテキストを用意できる

`⌘` + `Shift` + `v`でスタイルを継承せずにコピペができるはずですが、
困ったことにKeynoteだと画像貼り付けのショートカットになります。
そこで一回Vimに貼っつけてからKeynoteへ挑むようにしています。

まあVimじゃなくてもできます。

### とりあえずいきなりメモを書ける

ターミナル上で`vim`と打つだけでメモを書ける環境ができるのですごいです。
ゴミファイルが作成されないのでとてもエコです。
私は`v`にvimの`alias`を割り当てています。

プレーンテキストを用意するときとかすっごい楽です。
なので、他のエディタでもできるんですがVimでプレーンテキストを用意することが多いです。

## 使えるようになりたいと思った理由

「 **なんかカッコよさそう** 」の一言に尽きます。
カッコイイことは重要ですよね。　モチベーションがあがります。
なんとなくVimでメモとか書けたらカッコイイんじゃね？　
黒い画面触っている感じがカッコイイじゃね？　という発想だけで覚えました。
モチベーションはすごいです。

## 使えるようになるまでの道のり

だいたいこんな感じでした。

1. 秘伝のタレ(.vimrc)を誰かからもらう
1. Vim矯正ギブス(メモはすべてVimで書くようにする)
1. 師匠をみつける
1. 本を読む

2週間ほどで最適化が完了します。

## おわり

正直はじめてVimを使ったときは変態すぎて泣きました。 まず終了方法がわからないし、文字が入力できないとか意味がわからなかったです。
そして覚えてよかったと思っていますが、劇的に何かは変わっていないので、覚える必要はなかっただろうなというのも本音です。

ちなみのこの記事は[IA Writer](https://itunes.apple.com/jp/app/ia-writer/id775737590?mt=12)というMacのアプリで書きました。
IA Writerは便利ですね。

明日は誰かの何かです。
楽しみですね。
pdf.jsでリンクを押せるようにする

# はじめに
[pdf.js](https://github.com/mozilla/pdf.js/)で、PDF上のリンクを押せるようにするためのメモ
＊）pdf.jsはv1.9.426を利用

# 方法
ざっくりと言うと、
1. PDFを描画しているcanvas要素上に、透明なdiv要素を配置
2. リンクにしたい場所に、透明なaタグ要素をdiv要素上から重ねて配置

# ソース（ポイント箇所のみ抜粋）
### HTML

```html
<div id="pdfContainer" class="pdf-content">
    <canvas id="pdfCanvas"></canvas>
    <div class="annotationLayer"></div>
</div>
```

### CSS

```css
.linkAnnotation {
    position: absolute;
}
.annotationLayer .linkAnnotation > a {
    position: absolute;
    font-size: 1em;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
```

### js

```js
PDFJS.workerSrc = 'pdf.worker.js';

$(function () {
    var pdfData = "sample.pdf";
    PDFJS.getDocument(pdfData).then(function (pdf) {
        return pdf.getPage(1);
    }).then(function (page) {
        var scale = 1;
        var viewport = page.getViewport(scale);
        var $canvas = $('#pdfCanvas');
        var canvas = $canvas.get(0);
        var context = canvas.getContext("2d");
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        var renderContext = {
                canvasContext: context,
                viewport: viewport
        };
        page.render(renderContext);
        setupAnnotations(page, viewport, canvas, $('.annotationLayer'));
    });

  function setupAnnotations(page, viewport, canvas, $annotationLayerDiv) {
    var promise = page.getAnnotations().then(function (annotationsData) {
    viewport = viewport.clone({
        dontFlip: true
    });
    // 全てのリンクは新規ウィンドウで開く
    for(var i = 0; i < annotationsData.length; i++) {
        annotationsData[i].newWindow = true;
    }
    var param = {
        div: $annotationLayerDiv.get(0),
        page: page,
        viewport: viewport,
        annotations: annotationsData,
      };
      PDFJS.AnnotationLayer.render(param);
    });
    return promise;
  }
});
```
X-Packを無効化したElasticsearch 5とKibanaをDocker Composeで起動する

# はじめに

ローカルの開発環境ではElasticsearchのX-Packは無効にしたいです。

Elasticsearch 6からはX-Packがインストールされていない`elasticsearch-oss`イメージが存在する[^1]のですが、5には存在しないため、起動時に無効化するかアンインストールしたイメージを作成します。

[^1]: https://www.elastic.co/guide/en/elasticsearch/reference/6.0/docker.html

この記事ではそれぞれのComposeファイルのサンプルを示します。

# 対象ソフトウェアバージョン

- Elasticsearch 5.6.4
- Docker for Mac 17.09.0-ce-mac35


# X-Packを無効化する

## 起動時に無効化する場合

`environments`にX-Packの各機能を無効にするパラメーターを渡すことで無効化します。[^2]
シングルノード構成でよいので`discovery.type=single-node`も渡しています。[^3]

[^2]: https://www.elastic.co/guide/en/x-pack/5.6/installing-xpack.html#xpack-enabling
[^3]: https://www.elastic.co/guide/en/elasticsearch/reference/5.6/docker.html#docker-cli-run-dev-mode

```yaml:docker-compose.yml
version: "3.3"
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:5.6.4
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.graph.enabled=false
      - xpack.ml.enabled=false
      - xpack.monitoring.enabled=false
      - xpack.security.enabled=false
      - xpack.watcher.enabled=false
    ports:
      - "9200:9200"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es-data:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:5.6.4
    environment:
      - xpack.graph.enabled=false
      - xpack.ml.enabled=false
      - xpack.monitoring.enabled=false
      - xpack.reporting.enabled=false
      - xpack.security.enabled=false
      - xpack.monitoring.report_stats=false
      - xpack.monitoring.ui.enabled=false
    ports:
      - "5601:5601"
    links:
      - elasticsearch:elasticsearch

volumes:
  es-data:
    driver: local
```


## アンインストールしたイメージを作成する場合

X-PackをアンインストールしたElasticsearchとKibanaをビルドするDockerfileを作成し、それを利用するようにします。
こちらもシングルノード構成でよいので`environments`に`discovery.type=single-node`を渡しています。

```yaml:docker-compose.yml
version: "3.3"
services:
  elasticsearch:
    build:
      context: ./dockerfiles
      dockerfile: Dockerfile-elasticsearch
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - es-data:/usr/share/elasticsearch/data

  kibana:
    build:
      context: ./dockerfiles
      dockerfile: Dockerfile-kibana
    ports:
      - "5601:5601"
    links:
      - elasticsearch:elasticsearch

volumes:
  es-data:
    driver: local
```

```dockerfile:dockerfiles/Dockerfile-elasticsearch
FROM docker.elastic.co/elasticsearch/elasticsearch:5.6.4

RUN elasticsearch-plugin remove x-pack
```

```dockerfile:dockerfiles/Dockerfile-kibana
FROM docker.elastic.co/kibana/kibana:5.6.4

RUN kibana-plugin remove x-pack
```
Node.jsとsocket.ioでネットワーク多人数対戦リバーシを制作中

#はじめに
この記事はNode.jsとsocket.ioで、ネットワーク多人数対戦リバーシを制作していたときに気づいた事などを書いていきます。

#socket.io
コマを置いたことやチャット書き込みなどは io.sockets.emit() を使い全員に知らせる。
ゲーム中、順番がきたことを個別に知らせるために io.sockets.connected[socketID].emit() を使う

#クライアント側の外部ファイル
クライアント側はsocket.ioを使うと他のjsファイルを外部から読み込めなくなるのでindex.htmlに直接書かないといけなくなり、index.htmlが大きくなりがち。と、思っていたら expressを使って外部ファイルを読み込めました。
例えば index.html から test2.js を読み込む場合、server.js などから

```js
var express = require('express');
var app = express();
app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});
app.get('/test2.js', function(req, res){
  res.sendFile(__dirname + '/test2.js');
});
```
という感じに書いておくとクライアント側でも外部ファイルを読み込めます。
これをやってないとクライアント側が syntax error などになり外部ファイルを読み込めなくなります。

#setInterval()とthis
[setInterval() → this でひっかかった - Web系がおもしろい。](http://d.hatena.ne.jp/esperia/20100321/1269203457)

```js
var hoge={};
hoge={
	prop:123,
	foo:function() {
		this.id = setInterval(this.bar, 2000);
	},
	bar:function() {
		alert(this.prop); // ←コレ
	}
};
hoge.foo();
```
このプログラムを動かすと２秒毎に123と表示されて欲しいのですが、undefinedになります。
この問題でドハマリしました。
esperiaさんが解決してくれていました。

```js
var hoge={};
hoge={
	prop:123,
	foo:function() {
		var self=this;
		this.id = setInterval(function(){self.bar()}, 2000);
	},
	bar:function() {
		alert(this.prop); // ←コレ
	}
};
hoge.foo();
```
これで２秒毎に123と表示されるようになります。
そして、この解決のコードを書かれていたesperiaさんは、友人です。世間は狭いですね^_^;

#意外だったこと１
ゲーム開始までにクライアントとサーバでやり取りする回数が結構多い。
ゲーム開始までに遊ぶテーブル決めたり、人数決めたりするところでクライアントとサーバのやりとりが多い。

#意外だったこと２
今はサーバ側でsetInterval使って敵AI（ランダムに置くだけ）を１秒ごとに更新しているのだが、VPSのレンタルサーバから怒られて止られるかビビっていた。動かしてみると止められなかったのでOKっぽい。１秒毎の更新は許容範囲なのかも。



#今後やりたいこと
AIを強くするために評価の重みを作ってそれを優先してコマを置くようにする。
評価はランダムに置くコンピューター同士を対戦させて、勝った方の棋譜を評価に加えていく。
1,000回〜10,000回ぐらいの対戦結果があればいいらしい。

#おわりに
Qiitaに初めて投稿しました。
この記事を書いていた同じ時期に東京Node学園祭2017が開催されて、コミュニティではNode.jsへのコントリビューターになる道がサポートされていたりして、参加してなかったけど刺激を受けました。
Node.jsのgithubにプルリク出してみたいなと思って色々ドキュメントやガイドラインを読みましたがプルリク出すまでには至りませんでした。その代わりにgithubのラベルの使い方や、プルリクは海外ではPRと書く場合が多いことや、「good first issue」のラベルを目印にissueを探すことなど、githubの勉強になった気がします。今のところ独りでgithubを使っている状態ですが、自分のプロジェクトにコントリビューターを招いたり、自分がどこかのコントリビューターになったりすることを目標にしていこうと思います。
まず自分のコードを読んでもらいやすいように書き直して早くpushしようと思います。
まだ稚拙な状態ですがネットワーク多人数対戦リバーシのプロジェクトです。
https://github.com/minmin0530/networkMultiReversi

こっちが新しくて、トップページとか他のページもあるやつ。
https://github.com/minmin0530/ai6
dcodeIO/webassembly内のツールチェーンでzlibをビルドしてみる

[dcodeIO/webassembly: A minimal toolkit and runtime to produce and run WebAssembly modules\.](https://github.com/dcodeIO/webassembly)内のツールチェーンを使用してzlibをビルドしてみました。

## dcodeIO/webassemblyとは

曰く、実験的でミニマルなツールキットとランタイムを持っていて、cのファイルをwasmにコンパイルして実行できますとのこと。`malloc`とか最低限欲しいものは入っているので、ちょっとしたプログラムを書きたいがemscripten使うほどでもないときに便利です。

## zlibをビルドする

[サンプルレポジトリ](https://github.com/ukyo/zlib-wasm-without-emscripten-sample)を作ったので`git clone`してきてビルドします。Windows Subsystem for Linux, macOS High Sierraで動作確認をしています。

```
$ git clone https://github.com/ukyo/zlib-wasm-without-emscripten-sample.git
$ cd zlib-wasm-without-emsripten-sample
$ npm install
$ npm run build
```

[ビルドスクリプト](https://github.com/ukyo/zlib-wasm-without-emsripten-sample/blob/master/build.js)は[webassembly/build\.js at master · dcodeIO/webassembly](https://github.com/dcodeIO/webassembly/blob/master/lib/build.js)を参考にして組んでみました(流れは以下図を参照)。

![build](https://qiita-image-store.s3.amazonaws.com/0/380/07792a35-d0c8-39f9-21cc-7559a35e0db2.png)

`<stdio.h>`がないとか言われてちょっとハマったりしましたが、ヘッダーファイルをでっち上げて`-isystem path/to/include`して回避しました。importObjectに入れる関数を定義したい場合は、[import\.h](https://github.com/ukyo/zlib-wasm-without-emsripten-sample/blob/master/src/import.h)のようなヘッダーファイルだけ作るとインポートする扱いになるみたいです。

## ベンチマーク

wasm, pako, nodeのzlibで比較。生のdeflate, inflateでベンチマークを取ってみました。

* Node: v8.9.1
* OS: MacBook Pro High Sierra
* CPU: Intel Core i5 2.4GHz 
* Memory: 16GB

```
$ npm run bench

## lorem_1mb.txt size: 1000205
wasm x 9.61 ops/sec ±4.48% (27 runs sampled)
pako x 8.70 ops/sec ±2.26% (25 runs sampled)
native x 15.21 ops/sec ±3.15% (41 runs sampled)
Deflate: Fastest is native
## deflated lorem_1mb.txt size: 257012
wasm x 120 ops/sec ±10.26% (60 runs sampled)
pako x 106 ops/sec ±8.56% (67 runs sampled)
native x 211 ops/sec ±2.68% (74 runs sampled)
Inflate: Fastest is native
```

なんとかpakoに勝ててますね(このくらいの規模だとさすがにJavaScriptには勝てるらしい)。ちなみにファイルサイズは60.4KB(wasm) + 3.6KB(js)。wasmのほうはgzipして28KBくらいなので、かなり許せる範囲じゃないでしょうか。

## まとめ

Emscriptenとか使わずに[dcodeIO/webassembly](https://github.com/dcodeIO/webassembly)内のツールチェーンでzlibをwasmにコンパイルしてみました。emsdkに環境を汚染されずに、`npm i && npm run build`程度でビルドできるのが良いですね。
[個人的な備忘録とコピペ用]nginxのインストールから基本設定・静的ファイル

#目的

- nginxの基本的なことを知っておく。
- nginxのインストールする。
- nginxの設定ファイルの位置を知っておく。
- 一番簡単な静的ファイルのHTTPサーバーを立てる。
- 静的なファイルをどこのパスに置くか知る。
- できる限りコピペで動くようにする。

#作業ログ
今回は、RaspberryPi3上で作業する。

外へ見せるポートは8080
基本となるイメージがresin/rpi-raspbian
イメージ名がnginx_test

```
sudo docker run --name nginx_test -p 8080:80 -it -d resin/rpi-raspbian
```

パッケージをインストールする。vimを入れているのは編集用

```
$ sudo apt-get update
$ sudo apt-get install vim nginx
```

#nginx.confを編集する

自分が参考にしたデフォルト設定を表示

```
root@6daa0cf05992:/# cat /etc/nginx/nginx.conf 
user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;
	gzip_disable "msie6";

	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}


#mail {
#	# See sample authentication script at:
#	# http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
# 
#	# auth_http localhost/auth.php;
#	# pop3_capabilities "TOP" "USER";
#	# imap_capabilities "IMAP4rev1" "UIDPLUS";
# 
#	server {
#		listen     localhost:110;
#		protocol   pop3;
#		proxy      on;
#	}
# 
#	server {
#		listen     localhost:143;
#		protocol   imap;
#		proxy      on;
#	}
#}
```

一応バックアップをとる

```
$ cp nginx.conf nginx.conf.orig
```

nginx.confの変更。
ポート80番で待つ。
サーバー名はとりあえずhogehoge.com
静的ファイルは/var/www/htmlにおく。

```
root@6daa0cf05992:/# diff /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig 
11,18d10
< 	server { 
< 		listen 80;
< 		server_name hogehoge.com;
< 
< 		location / {
< 			root /var/www/html/;		
< 		}
< 	}
```

#テスト用の静的なhtmlファイルを置く

静的なhtmlは/var/www/html/に置くと良い。

```
$ echo "Hello" > /var/www/html/hello.html
```


#設定反映
とりあえずnginx自体を再起動して設定反映

```
$ sudo service nginx restart
```

#動作確認

```
$curl 192.168.0.7:8080/hello.html -H "Host:hogehoge.com"
Hello
```
AWSの利用料金をサっと確認するワンライナー

# 概要
- AWSの利用料金をサっと確認したい
- AWS CLIとjqでサッと見やすく

# 準備
- AWSアカウント
- AWS CLIと利用準備
- jq

## awscliのバージョン

```bash
$ aws --version
aws-cli/1.12.2 Python/2.7.12 Linux/4.9.58-18.51.amzn1.x86_64 botocore/1.8.2
```

もちろんCygwinでも大丈夫です

```
$ aws --version
aws-cli/1.12.2 Python/2.7.13 CYGWIN_NT-10.0/2.9.0(0.318/5/3) botocore/1.8.2
```

# jsonフォーマットでサッと
コマンド

```
aws ce get-cost-and-usage \
--region us-east-1 \
--time-period Start=`date '+%Y-%m'`-01,End=`date -d 'next month' '+%Y-%m'`-01 \
--granularity MONTHLY \
--metrics BlendedCost \
--group-by Type=DIMENSION,Key=SERVICE \
| jq -c '.ResultsByTime[].Groups[] | {(.Keys[]): .Metrics.BlendedCost.Amount}'
```

結果

```json
{"AWS CloudTrail":"0"}
{"Amazon Elastic Block Store":"2.6873538247"}
{"Amazon Elastic Compute Cloud - Compute":"5.9323839592"}
{"Amazon Route 53":"0.5563328"}
{"Amazon Simple Email Service":"0"}
{"Amazon Simple Notification Service":"0.0000107185"}
{"Amazon Simple Queue Service":"0.0000004264"}
{"Amazon Simple Storage Service":"0.0428270202"}
{"AmazonCloudWatch":"0"}
{"Tax":"0.73"}
```

# CSVでサッと
コマンド

```bash
aws ce get-cost-and-usage \
--region us-east-1 \
--time-period Start=`date '+%Y-%m'`-01,End=`date -d 'next month' '+%Y-%m'`-01 \
--granularity MONTHLY --metrics BlendedCost \
--group-by Type=DIMENSION,Key=SERVICE \
| jq -r '.ResultsByTime[].Groups[] | [(.Keys[]), .Metrics.BlendedCost.Amount] | @csv'
```

結果

```csv
"AWS CloudTrail","0"
"Amazon Elastic Block Store","2.6873538247"
"Amazon Elastic Compute Cloud - Compute","5.9323839592"
"Amazon Route 53","0.5563328"
"Amazon Simple Email Service","0"
"Amazon Simple Notification Service","0.0000107185"
"Amazon Simple Queue Service","0.0000004264"
"Amazon Simple Storage Service","0.0428270202"
"AmazonCloudWatch","0"
"Tax","0.73"
```

# メモと振り返り
- エンドポイントは us-east-1
- 期間指定(--time-period)のEndは範囲の次の日を指定します
    - Endの指定日は期間に含まれません（The end date is exclusive.）
    - 式で書くと 日付 >= Start AND 日付 < End みたいに評価されるということですね
- 日付までコマンドに埋め込んだのは、やり過ぎたかもしれないと反省している（見づらい）


# リンク
## AWS
- [AWS Blog インタラクティブな AWS コストエクスプローラー API](https://aws.amazon.com/jp/blogs/news/new-interactive-aws-cost-explorer-api/)
- [Using the AWS Cost Explorer API](http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-explorer-api.html)
- [http://docs.aws.amazon.com/cli/latest/reference/ce/index.html](http://docs.aws.amazon.com/cli/latest/reference/ce/index.html)

## jq
- 下記の記事にコンパクトに欲しい部分が書いてあり、参考にさせて頂きました。
- [jq コマンドを使う日常のご紹介](https://qiita.com/takeshinoda@github/items/2dec7a72930ec1f658af)
RxJava の combineLatest のコード例

RxJava の ``combineLatest``、overload がたくさんあって一発で書けた試しがないので、うまく書けた例を置いておきます。

``name`` と ``age`` のいずれかの ``Observable<T>`` が変化したときに、 "name - 歳:age" な文字列を push するというものです。

```kotlin
val name = PublishSubject.create<String>()
val age = PublishSubject.create<Int>()

// 型引数指定と BiFunction は省略できないみたい
Observable.combineLatest<String, Int, String>(
        name, age, BiFunction { n, a -> "$n - 歳:${a}" })
        .subscribe({
            Log.d("combineLatest", "onNext - ${it}")
        })

// RxKotlin を導入すると型推論が効くとコメントで教えてもらいました
Observables.combineLatest(name, age) { n, a -> "$n - 歳:${a}" }
        .subscribe({
            Log.d("combineLatest", "onNext - ${it}")
        })

// Observable<T> を配列で渡せるけど、第2引数の combiner が Any な配列になっちゃう
Observable.combineLatest(arrayOf(name, age), {
    val n = it[0] as String
    val a = it[1] as Int
    "$n - age:${a}" })
        .subscribe({
            Log.d("combineLatest", "onNext - ${it}")
        })


name.onNext("saito")
age.onNext(24)
name.onNext("yoshida")
```
3v4lでPHPの動作検証

Web上でプログラムの動作を確認できるツールもいくつか存在しますが、今回は[3v4l](https://3v4l.org/)を紹介します。

# 入力部のUI

https://3v4l.org/ を開けば、さっそく最上部に`<?php`とだけ書かれたエディタが出現します。つまり、このサイトは**PHP専用**です。コードを入力して、下にある`eval();`ボタンを押せば、実行が始まります。明示的な保存はないのですが、実行するとURLが生成されるので、それでコードを共有することができます。

# 真骨頂

paiza.ioなど、PHPを含む多言語でこのようなことができるサービスもありますが、3v4lの真骨頂はこの先です。実行結果の上部に「Output for hhvm-3.18.5 - 3.22.0, 7.0.0 - 7.2.0rc6」のように出ますが、複数のバージョンを一気に実行して、それぞれを比較してくれます。

たとえば、PHP 7で使えるようになった「`int`のタイプヒント」も、[このように](https://3v4l.org/jEv2b)PHP 7とPHP 5での実行結果の違いがはっきり出ます。

さらに、入力画面の下の方にある「eol versions」にチェックを付ければ、サポート切れになっている古いPHPでも実行してくれます（なんと、PHP 4.3からあります）。

## 詳細情報

タブを切り替えれば、実行結果だけでなく、バージョンごとの実行時間の分析や、実行するオペコードの表示もあって、PHPコードの分析全般に役立つサイトとなっています。

# その他

「3v4l」という名前は、「eval」を数字に書き換えてもじったもの、とのことです。
flagdayという日本の祝日を Go で扱うライブラリを作った

Original: [flagdayという日本の祝日を Go で扱うライブラリを作った \| tail \-f pinzo\.log](https://pinzolo.github.io/2017/11/28/flagday-library-for-japanese-public-holiday.html)

---

お仕事で祝日を扱う処理を書いたついでに Go で祝日を扱うライブラリを作った。

[pinzolo/flagday: flagday is library for public holidays in Japan\.](https://github.com/pinzolo/flagday)

[najeira/jpholiday: A package for Japanese holidays with Go](https://github.com/najeira/jpholiday) の存在を知ったのは作った後だった。

気にしない気にしない。
C# + ReactiveProperty vs Kotlin + RxProperty : Command 編

ボタンを押したら、数値が１ずつ加算されていく、というやつの ViewModel 側

## C# + ReactiveProperty の場合

``Counter`` がラベルにバインドする数値、 ``Increment`` がボタンにバインドするコマンド。

```csharp
public class MainViewModel
{
    public ReactiveProperty<int> Counter { get; } = new ReactiveProperty<int>(0);
    public ReactiveCommand Increment { get; } 

    public MainViewModel()
    {
        // Increment コマンドは、 Counter が 10 未満の間、使用可能
        Increment = Counter.Select(x => x < 10).ToReactiveCommand();
        // Increment コマンドが実行されたら Counter を +1 してく
        Increment.Subscribe(x => Counter.Value = Counter.Value + 1);
    }
}
```

## Kotlin + RxProperty の場合

``counter`` がラベルにバインドする数値、 ``increment`` がボタンにバインドするコマンド。

```kotlin
class MainViewModel {
    val counter = RxProperty<Int>(0)

    // Increment コマンドは、 Counter が 10 未満の間、使用可能
    val increment = RxCommand<Unit>(counter.map { it < 10 }).apply {
        // Increment コマンドが実行されたら Counter を +1 してく
        this.subscribe({ counter.set(counter.get()!! + 1) })
    }
}
```

C# は言語の仕様？で、読み取り専用プロパティの定義のなかで他のプロパティを参照できない。のでコンストラクタに書く。

Kotlin はその辺のしがらみが少ないので、思った通りに書ける感じ。
さらに ``.apply`` 関数で Command の subscribe 処理も定義できるので、結果コンストラクタに書くことがなくなりました、スッキリ。

Android + Kotlin な人は、 RxProperty もっと使っていきましょー

* [RxPropertyでRxJavaとAndroid Data Bindingを連携する - Qiita](https://qiita.com/k-kagurazaka@github/items/3fc1fc19ea608cac9913)

コードの短さだと Kotlin だし、この C# の ``MainViewModel.cs`` は、Xamarin(Android, iOS, Mac) や Windows など全部共通実装でいけちゃう。

どちらも良い。
Pythonプログラムのシーケンスを可視化してみる

こちらの記事はPythonプログラムのシーケンスの確認できる便利なWEBサイトの紹介になります。
自分が初心者の頃、Python独特の内包表記やmap関数、filter関数を用いたエレガントなコードを見て
これは何をしているんだろうと不思議になり振る舞いを確認するために試行錯誤した経験がみなさんあると思います。
そう言う時に下記のWEBサイトを利用するとコードの理解の助けになると思い紹介させていただきます。
[Visualize Python tutor](http://pythontutor.com/visualize.html#)

## 対象読者

主にPython学習中の初心者・中級者の方を対象にしています。

## 環境

Python3.6 も Python2.7 どちらのコードでも動作させることが可能です。
ただし本文中のプログラムはPython3.6でのみ動作を確認しております。
こちらからコードを引用しました。
[pythonの内包表記を少し詳しく](https://qiita.com/y__sama/items/a2c458de97c4aa5a98e7)

## サンプルコード(map関数)
```python
print(list(map(lambda i:i**2,range(1,11))))
>>> [1, 4, 9, 16, 25, 36, 49, 64, 100]

```
![map_function.gif](https://qiita-image-store.s3.amazonaws.com/0/40310/3dcb448b-491a-8791-4fcf-aca8da21eccc.gif)
上のようにプログラムがどのように動くかを可視化できます。
録画したものが以下のページリンクになります。
[Visualize Python tutor - map関数](https://goo.gl/MQwtCR)
### あとがき
Pythonをはじめたころに知っていたら理解の助けになっただろうなぁと思いました。
golangでcrqs+esにチャレンジしてみる　解説編？

# はじめに
[前々回](https://qiita.com/Mamoru-Izuka/items/473c8d76466d089d662c)、[前回](https://qiita.com/Mamoru-Izuka/items/a3f707f5f6a8e090ea2e)とあまりに走り書きすぎたので一応解説いれておこう編です。

## そもそもcqrs+esってなんじゃいな
### CQRSとは
　CQRS（Command Query Responsibility Segregation）はコマンド/クエリ責務分離と言われるもので、コマンド層とクエリ層に責務を分けることで、通常起こりがちなアプリ～データベース間等の[インピーダンスミスマッチ](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%94%E3%83%BC%E3%83%80%E3%83%B3%E3%82%B9%E3%83%9F%E3%82%B9%E3%83%9E%E3%83%83%E3%83%81)を吸収しちゃおうという考えだと個人的には理解してます。
　CQRSをDDD(ドメイン駆動設計)に持ち込むことで、コマンド層ではドメインに集中した開発、クエリ層ではユーザーインターフェースに集中した開発が可能となり（関心の分離）、ごっちゃ煮感溢れるインフラ層もそれぞれに分割することが可能となります。

### ESとは
　ES(Event Sourcing)は従来型の常に最新の状態をRDB等に保存する方法とは異なり、そのオブジェクトに発生したイベントを積み上げ型に保存する方法です（DDDの場合、ドメインになるはず）。オブジェクトに起こったことは全て記録し、オブジェクトの状態は常にその積み上げの結果となります。
　DDD+CQRSにおいてはコマンド側でドメインに変化が起こった場合、それを何らかの方法でクエリ側に通知する必要があります。ESであればドメインの変化を全て網羅しているのでクエリ側もドメインで起こった出来事をイベントをたどることで全て知ることができるようになります。それにより自身のDTOを更新するかどうかも自身で判断できます。

## 今回の設計
　上記を踏まえて・・・

![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/94252/8e9355d8-867f-3fce-85a7-f5d66bd1aaaa.png)

　前回、アクターシステムがって突然出しましたが、CQRSのScala(or Java)向けフレームワークで[Akka](https://akka.io/)というものがありまして、それから派生したというか分離した？golangで書かれた[Proto.Actor](http://proto.actor/)というものをヒントにして作った関係でこんな感じになりました。Proto.Actorではアクター自身がprotocol-bufferを使ってやり取りする感じなんですが、今回は使わず上辺だけ真似ています（互いのアクターに依存する部分が出たりしたので）。

### コマンド側
　アクター(TodoActor)がドメイン(Todo)に対する実権を握っています。プレゼン層からコマンドを受け付け、イベントを生成し、ドメインに流し、永続化機構(Persistence)に保存した後でメッセージング機構(MessagingPublisher)へイベントの発生を通知します。
　アクター以外はドメインのことは知りませんし、関係ありませんって感じです。

### クエリ側
　こちらもアクター(TodoActor)がDTO(TodoQuery）に対する実権を持ちます。メッセージング機構(MessagingConsumer)から通知を受けると永続化機構(PersistenceQuery)にイベントを問合せ、DTOに適用し、永続化します。
　プレゼン層は当然それらのことに関知せず、DTOの最新の状態のみが関心毎になります。

# おわりに
　解説になってない気もする。
Haskell で標準入力（メモ）

# Haskell で標準入力（メモ）
標準入力を使って遊ぶことが多いけど、始めたての頃は値の受け取りに苦労してなかなか本題に進まなかったので、今の自分の実力で書けるレベルの標準入力を列挙していく。
不正入力には対応していないので注意。

## 整数型半角スペース区切り

```
 1 2 3 4 5 6
```
みたいな半角スペースの羅列を1行分受け取りたい。できれば何個の数字が入力されるかを知らない状態で入力を受け取りたい。

```hs
-- [Char]あるいは String を Int にする
toInt :: (String -> Int)
toInt x = read x ::Int

--入力を受け取り、[Int]にする
getInts = do
  x <- getLine
  let y = (map$toInt)$words x -- 半角スペースで分割してInt にする
  return y

--使用例
main = do
  x <- getInts -- < 1 2 3 4 5 6
  print x      -- > [1,2,3,4,5,6]
  print$sum x  -- > 21
```
少しいじれば float にできる

## 行列（数字）
半角スペース区切りの行列を[[Int]]の2次元リストに受け取る。
先ほどの関数も使います。途中、words の代わりにlinesを使うと短く書けるけど、型を指定して受け取っているので何行から何行までこのフォーマットで受け取る、みたいに書きたい。

```hs
getMat :: (Int -> IO [[Int]])
getMat 1 = do
  y <- getInts
  return [y]
getMat x = do
  y <- getInts
  z <- getMat (x-1)
  let w = [y] ++ z
  return w

--使用例
main = do 
  a <- getMat 3 -- < 1 2 3\n4 5 6\n7 8
  print a -- > [[1,2,3],[4,5,6],[7,8]]

--先ほど作ったやつ
toInt :: (String -> Int);toInt x = read x ::Int;
getInts = do
  x <- getLine;let z = (map$toInt)$words x
  return z
```


## 短縮バージョン
```hs
getInts = do
  x <- getLine
  let y = (map$toInt)$words x
  return y
    where
      toInt x = read x ::Int
getMat x
  |x==1 = do
    y <- getInts
    return [y]
  |otherwise = do
    y <- getInts
    z <- getMat (x-1)
    let w = [y] ++ z
    return w
```

とりあえず、この２つを駆使して書きまくってもっと理解を深めていきます。
rcredstash を用いて hako の環境変数を暗号化する

Advent Calendar の季節ですね。
年末の大掃除の心持ちで、なんとなく技術的なメモみたいなものを残していこうと思います。

なお、さだまさしの話は、先日**「さだまさし コンサートツアー2017 惠百福(たくさんのしあわせ)」**を観覧してきて放心状態なので、今年は割愛します。

ここでは、個人的に簡単に AWS 上にサーバー環境構築を行う際に用いている hako と credstash の組み合わせに関する話を書きます。

# hako
https://github.com/eagletmt/hako

hako は AWS ECS (Elastic Container Service) を便利に使うための docker オーケストレーション実装のひとつです。
ドキュメントが極めて少ない印象がありますが、非常に良く出来たツールです。

ECS の API をラップして、以下の機能を実現しています。

- ECS の環境の包括的な構築処理。設定ファイルは DSL(yaml) で記述可能
  - task definition
  - service
  - auto scaling
  - alb
- backend の port direct mapping に対応
- blue / green deployment を標準でサポート
- 自動 rollback 機能を標準でサポート
- hako oneshot という機能で一時的な container 起動が可能 
  - バッチ処理などに用いることを想定

ECS 同種のツールとしては他に blox ( https://blox.github.io/ ) というものが有名なのですが、hako の方はコマンドラインだけで完結できシンプルであることや blue / green deployment を完全にサポートしているため便利です。

ドキュメントやサンプル設定ファイルなどは、上述の公式 github の内容が参考になります。

# credstash
AWS の DynamoDB と KMS を組み合わせて、情報を暗号化して保存するための仕組みを提供するツールです。
詳しくは、以下の記事などを参照ください。

[credstash について](https://qiita.com/moaikids/items/bdd2de79f48ba4c1b890)

# hako-rcredstash
https://github.com/moaikids/hako-rcredstash

hako において、credstash で暗号化した情報を用いて環境変数の情報を設定できるように拡張した実装になります。

こちらを用いると、Ruby 製の credstash ライブラリである rcredstash ( https://github.com/adorechic/rcredstash )を通じて hako で暗号化された情報を扱えるようになります。

## install
```
$ gem install hako
$ gem install rcredstash
$ gem install hako-rcredstash
```

実際は Gemfile にまとめて bundle install で入れることを推奨します。


## set encrypted value using rcredstash
(r)credstash に情報を追加します。
"veryverysecret" という文字列は実際は暗号化されて "AQIBAHidXVv5qOYRYiIP2jXGm3AcDXunTO9…" というかたちで保存されています。

```
$ rcredstash put encrypted.some_password
secret value> veryverysecret
$ rcredstash get encrypted.some_password
veryverysecret
```


## config hako
credstash で暗号化された値を hako で使う場合は、env_provider で rcredstash を指定すれば OK です。
あとは、使用したい暗号化済みの値を保持している key 文字列を以下のように #{.......} という形で指定すれば、その値が復号化されて使われます。

```
env:
    $providers:
      - type: rcredstash
    SOME_PASSWORD: ‘#{encrypted.some_password}'
```

## deploy using hako
あとは、通常の hako の使い方と同じです。

# まとめにかえて
credstash の記事にも書きましたが、今はこれらの暗号化・復号化処理は **Parameter Store** を使った方が自然かな、とも感じています。
必要に応じて、 hako-parameterstore みたいなプラグインを書いてみようかな、と思っています。
Sublime Text 3 > Goto Symbolで見つからないシンボル > Goto Symbol in Projectでは見つかる

```txt:動作環境
Windows 7 Pro (32bit)
Sublime Text 3 Build 3143
```

cのソースファイルにてdefine定義しているシンボルがある。

Ctrl+R(Goto Symbol)にて一覧表示してもそのシンボルは表示されない。
Ctrl+Shift+R(Goto Symbol in Project)ではそのシンボルは検索できた。

同じソースファイルをVisual Studio Code(v1.16.0)で開いて「ファイル内のシンボルへ移動」を実行すると「シンボルが見つかりません」となった。
同じフォルダにある別のcソースファイルではシンボル一覧は取得できる。
俺でも登録できたダンズナンバー(D-U-N-S Number)

俺です。

[前回](https://qiita.com/gamisan9999/items/4cad02463d5478e3b528)から一世紀近く経ってしまいましたが、
Apple Deployment Programの加入に必要なダンズナンバーを登録することにします。

# 前提要件

- 法人番号を取得していること

# 申請

- 東京商工リサーチへアクセス

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42755/95a30d14-ba03-da76-1ebc-93486973412e.png)

- スタンダードサービスを選びます。

自分の企業情報を記入してドーンです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42755/912ceec5-907a-179c-67e0-0e966163a157.png)

大体3営業日後ぐらいにどーんとメールで届きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/42755/f353b91f-6edc-6d12-9e6b-f62d6d9559cf.png)

まってろApple Deployment Program
ということで続きます。
dplyr::group_byでグループ化したものをループする

group_byしたものは、基本的にはsummarizeするのが順当な使い方ですが、group_byされたグループごとに、処理を回したい場合はどうすればよいでしょうか？
# summarize()

標準の方法ではどこまでできるのでしょうか？
[doc](https://www.rdocumentation.org/packages/dplyr/versions/0.7.3/topics/summarise)にあるように、以下のような集約関数が用意されています。

Center: mean(), median()
Spread: sd(), IQR(), mad()
Range: min(), max(), quantile()
Position: first(), last(), nth(),
Count: n(), n_distinct()
Logical: any(), all()

これらの集約処理ではなく、groupごとに、フィルターをかけたり、再集約をかけたりもできるとは思いますが、処理が入れ子になりすぎると、結果が想像しがたくなるのは難点です。groupごとにシンプルに処理したい場合はどうすればよいでしょうか？

# 無理やりtidyr::nestする

いくら探しても、grouped_df形式のままイテレートする方法が無かったので、tidyrのnestを使って、フラット化してばらしてしまう方法を使いました。
実はforeachでグループごとに並列化したかったのが、動機でしたので、以下のようにしてみました。

```R
    grouped_df <- df %>% group_by(key) 
    cl <- makeCluster(cores)
    registerDoParallel(cl)
    groups <- grouped_df %>% nest
    applied <- foreach(i = 1:nrow(groups)) %dopar% {
        some_function(groups$data[i])
    }
```

そもそも、この場合はgroup_byせずに、splitでやればよさそうだと、書きながら気づきました。
[Alibaba Ant Design Pro] コンポーネント言語を変更 (Change The Language of Components )


Ant Designのコンポーネントの既定言語は **中国語**で、
**日本語**に直したい場合は、下記２つのファイルを変更すればOKです。

## `/src/index.js` ファイルを変更

```
import 'moment/locale/zh-cn';
```

を

```
import 'moment/locale/ja';
```

に変更。

## `/src/router.js`　ファイルを変更



### 変更１

```
import zhCN from 'antd/lib/locale-provider/zh_CN';
```

を

```
import jaJP from 'antd/lib/locale-provider/ja_JP';
```

に変更。

### 変更２

```
<LocaleProvider locale={zhCN}>
```

を

```
<LocaleProvider locale={jaJP}>
```

に変更。
GNU Parallel のエラー処理

シェルスクリプトで並列処理をしたいとき、便利なのがxargs -P ですがエラー時に終了させることができません。
（できるようでしたら教えてください）

GNU Parallel を使うと簡単にエラー時の制御ができます。

例）3並列で long_job を実行。エラー時は 即座に終了

```
$ cat list.txt | parallel --halt now,fail=1 --jobs 3 ./long_job {}
```

なお、実行中の他の処理の終了を待って終了するには、now の代わりに soon を指定します。


例）3並列で long_job を実行。エラー時は 他のプロセスの終了を待って終了

```
$ cat list.txt | parallel --halt soon,fail=1 --jobs 3 ./long_job {}
```

## 参考

* [GNU Parallel tutorial](https://www.gnu.org/software/parallel/parallel_tutorial.html)
* [「今日から使い切る」ための GNU Parallelによる並列処理入門](https://www.slideshare.net/koji_matsuda/gnu-parallel)
jsdoでbpmn

#概要
jsdoでbpmn-jsやってみた。
viewerやってみた。

#写真
![](http://jsdo-static-contents.s3.amazonaws.com/images/capture/W/c/8/Wc86.jpg?t=1511858147)

#成果物
http://jsdo.it/ohisama1/Wc86

以上。
Joobyで全リクエストに対してヘッダを出力するModuleのサンプル

Joobyで全リクエストに対してヘッダを出力する、というようなことをしたい時、Moduleを実装する必要があるようです。
そういうModuleを実装してみたので、ご参考まで。

```kotlin
class AppendAccessControlForDevEnv : Jooby.Module {
    override fun configure(env: Env?, conf: Config?, binder: Binder?) {
        if (env != null) {
            env.router().get("*") {req, rsp ->
                rsp.header("Access-Control-Allow-Origin", "http://localhost:8090")
            }
        }
    }
}



class App : Kooby({
    use(AppendAccessControlForDevEnv())

    get("/hello") { "Hello" }
})
```
複数の DB に対してクエリでエビデンスを取得するバッチ

## 背景

- テストの際に、複数の SELECT 文の結果をテキストで保存してエビデンスとする。
- 確認したいデータベースは MySQL と Oracle の二つ。
- 開発時の確認のためだけに使用するクエリなので、速度や脆弱性は度外視する。

... といった場合に必要となるオプションをまとめた。備忘録で乱文。

PostgreSQL については業務ができたら追記する。

## クエリ

例として MySQL 用に q1.sql、Oracle 用に q2.sql の二つを用意する。

### MySQL 用クエリの書き方

```sql:MySQL用q1.sql
SELECT '● users' as "Table Name";
SELECT
      LEFT(FIRST_NAME, 10) AS "FIRST_NAME"
    , LEFT(LAST_NAME, 10) AS "LAST_NAME"
FROM users
ORDER BY
      LAST_NAME
    , FIRST_NAME
;
```

どのテーブルのエビデンスとなるかを出力するため、最初にテーブル名を出力している。

[MySQL文の中でechoのようなことをしたい - Qiita](https://qiita.com/rita_cano_bika/items/a3c8c61ef5debe397ac5)

上記のようにテーブル一つだけなら、後述するバッチ内に echo があっても良い。
通常は複数のテーブルを一緒に確認するだろうから上記のようにすればいいと思う。
テーブルごとに .sql ファイルを作り、バッチで echo なんてことは死ぬ。

カラムの幅が大きい場合、たとえば varchar(80) だったりすると、データ内容がそれ以下でも 80 桁分の空白が表示されてしまう。
それを防ぐために上記のように LEFT() 関数をかませる。

[formatting - change mysql output column width - Stack Overflow](https://stackoverflow.com/questions/21103180/change-mysql-output-column-width)

### Oracle（SQL*Plus） 用クエリの書き方

```sql:Oracle用q2.sql
SET TAB OFF;

SET HEADING OFF;
SELECT '● users' AS "TableName" FROM Dual;
SET HEADING ON;

COLUMN FIRST_NAME FORMAT A10
COLUMN LAST_NAME  FORMAT A10
SELECT
      FIRST_NAME
    , LAST_NAME
FROM users
ORDER BY
      LAST_NAME
    , FIRST_NAME
;
EXIT;
```

こちらも、どのテーブルのエビデンスとなるかを出力するため、最初にテーブル名を出力している。
ただしこちらは `SET HEADING OFF;` によってヘッダーを省略している。より echo のイメージに近い。
mysql にはこれに該当する機能は -N オプションしかないようだ。

テストの最初から最後まで確実に検索結果がある場合は以下のような方法もある。

```sql:Oracle用q2.sql
SET TAB OFF;

COLUMN FIRST_NAME HEADING '● users|FIRST_NAME'
COLUMN FIRST_NAME FORMAT A10
COLUMN LAST_NAME  FORMAT A10
SELECT
      FIRST_NAME
    , LAST_NAME
FROM users
ORDER BY
      LAST_NAME
    , FIRST_NAME
;
EXIT;
```

[SQL*Plusレポートの書式設定](http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/server.102/B19277-01/ch6.html)

ただし、こっちの方法だと検索結果レコードが無い場合に何も表示されない。テスト中は「レコードがないこと」を確認したいこともあるだろうからこの方法は通常お勧めできない。

SQL*Plus はデフォルトで長い空白を TAB を用いて出力するため、最初に `SET TAB OFF;` をしている。エビデンスを何で確認するかによるが、表示が崩れることがあるので OFF にしておくのが無難。

こちらもカラムの幅が大きい場合に余計な空白が表示されないように設定しているが、MySQL でのやり方とは異なる。`COLUMN FIRST_NAME FORMAT A10` がそれにあたる部分で、10桁だけを表示するようにしている。

[COLUMN フォーマット例 - オラクル・Oracle SQL*Plus リファレンス](https://www.shift-the-oracle.com/sqlplus/command/column/format-sample.html)

最後に `EXIT;` をしないと、バッチはそこでとまってしまう。

## バッチ

上記二つのクエリを連続して実行するバッチのコードは以下の通り。

```bat:1.bat
@echo off
"C:\Path\To\mysql" --table --silent --host=localhost --database=foo --user=bar -pbaz < q1.sql
"C:\Path\To\sqlplus" -S bar/baz@foo @q2.sql
```

このバッチを実行し、結果をリダイレクトしてファイルに保存すれば簡単なエビデンスとなる。
テキストなので実行前後で比較することも容易だ。

### MySQL のオプション

--table,検索結果を「表」形式で出力する。
--silent,mysql 起動時に表示されるバージョン番号などのメッセージを表示しない。
--host,MySQL サーバーのホスト名を指定する。上の例では localhost がその値。
--database,MySQL データベース名を指定する。上の例では foo がその値。
--user,MySQL に接続するユーザー名を指定する。上の例では bar がその値。
-p,パスワードを指定する。パスワード "baz" と -p との間に空白を入れないように注意する。
クエリの指定,"<" を使って mysql コマンドにクエリを渡す。

### Oracle（SQL*Plus）のオプション

-S,SQL*Plus 起動時に表示されるバージョン番号などのメッセージを表示しない。
ユーザー名,上の例では bar がユーザー名。
パスワード,上の例では baz がユーザー名。
接続先スキーマ,上の例では foo がその値。tnsnames.ora にて指定した値と同じ。
クエリの指定,頭に @ をつけて実行したいクエリファイル名を指定する。
Google Safe Browsing ListにCSVから取得したマルチバイト文字を含んだURLを渡す

Python2.7でやってます。3系はもっと簡単に出来そう。

# ソースコード

```
from urlparse import urlparse
import urllib

def toGSBL(str_url, character_code)
  scheme, netloc, path, params, query, fragments = urlparse(unicode(str_url, character_code, 'ignore'))

  netloc = netloc.encode('idna')
  path = urllib.quote_plus(path.encode('utf-8'), '')　if len(path) > 0 else '/'
  query = urllib.quote_plus(query.encode('utf-8'), '')　if len(query) > 0 else ''

  return scheme + '://' + netloc + path + query
```

- urlparseして必要なところを細工したらくっつけてるだけです。
- charactor_codeにshift-jisとかutf-8とか入れれば思い思いに使えます。
- pathやqueryなど他にもマルチバイト文字が含まれていることを想定していますが、ここで欲しいのはあくまでnetlocをpunycodeにしたものです。
- 文字コードにもよりますが、日本語・韓国語・中国語で期待した結果が得られたので大体できると思いますが確認していません。

## ハマりポイント
UnicodeDecodeError、UnicodeEncodeErrorにはすっごく悩まされました…
というのも、urlparseをするのに環境の都合上どうしてもstr-unicode変換を強いられるため、その辺りの関係をきちんと理解しておかないとだめでした。
普段文字コードを気にしないで開発しているとこういう細かいところでハマります。

楽にするなら文頭に「# -*- coding: utf-8 -*-」とか書ければいいんですが、今回はそれはナシということでこの形で実現しています。

あと、URLLIBを知らない場合は便利だから見ておいたほうがいいと思います。

# 参考
敬称略
大変助かりました！

Pythonで日本語を含む国際化ドメイン（IDNA）をPunycode変換する（ServersMan@VPS（CentOS）でお気楽サーバー運営 (^^♪　　(忘れっぽいので個人メモ用)）
http://d.hatena.ne.jp/addition/20130327/1364353289

日本語文字列コード問題まとめ　ニホンジンは文字コードにうるさい（PythonMatrixJp for Pythonista!）
http://python.matrix.jp/pages/tips/string/encoding.html

20.16. urlparse — Parse URLs into components（Python 2.7.14 Documentation）
https://docs.python.org/2.7/library/urlparse.html#module-urlparse

urllib.parse.quote関数使用時の注意（@FGtatsuro）
https://qiita.com/FGtatsuro/items/75a4593fec954a32c10c

urllib – ネットワークリソースへのシンプルなインタフェース（PyMOTW）
http://ja.pymotw.com/2/urllib/

pythonで三項演算子のネスト（@u1and0）
https://qiita.com/u1and0/items/e47e3de059e27d4ebd74
Pythonで確率分布を計算・描画する備忘録


色々な確率分布をPythonで計算、描画する際の備忘録。
※随時追加予定


##正規分布（ガウス分布）

###scipyで正規分布を計算


```python:python
from scipy import stats

#平均100、分散50の正規分布

#ダイレクトに確率密度を取り出す
stats.norm.pdf(x=100, loc=100, scale=50)
#0.0079788456080286535

stats.norm.pdf(x=50, loc=100, scale=50)
#0.0048394144903828673

stats.norm.pdf(x=150, loc=100, scale=50)
#0.0048394144903828673

stats.norm.pdf(x=0, loc=100, scale=50)
#0.0010798193302637613

#正規分布の確率密度関数のオブジェクトを生成し、後で値を取り出す
norm = stats.norm(loc=100, scale=50)

print(norm.pdf(100))
#0.00797884560803

print(norm.pdf(5))
#0.00131231629549

#配列・リストも渡せる
list = [70, 100, 150]
norm = stats.norm(loc=100, scale=50)
print(norm.pdf(list))
#[ 0.00666449  0.00797885  0.00483941]
```

x：横軸の点（xに入れた値に対応する確率密度が出力される）
loc：平均
scale：分散

###matplotlibで描画

```python:python
import matplotlib.pyplot as plt
%matplotlib inline

x = np.linspace(-100, 300, num=800)
norm = stats.norm.pdf(x=x, loc=100, scale=50)

plt.plot(x, norm)
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/187504/b366bdbf-c89e-791a-0c10-07f5877dfbd5.png)
SE歴8年の無職がSilexでログイン処理に挑む（失敗）


前段はこれ

- [SE歴8年の無職がSilexでサイト構築に挑む - Qiita](https://qiita.com/ragingalpaca/items/d6b6c721eae4127992ff)

今回の参考資料はこれ

- [PHPマイクロフレームワークのSilexでログイン処理をささっとつくる | | リーテラトバリタブログ](http://elsur.xyz/silex2-loginform)

できる人が言う「ささっ」は信用ならないんですよね。
知ってる知ってる。

なおサイトがリンク切れをしていたため、続行不能になりました。

#なにをするの
サイトを参考にして実際にやってみた記録です。

曰く、

> Silexでは、組み込みの機能（Provider）を使えば、比較的簡単にHTMLフォームを使ったログイン処理機能をWebサイトに持たせることが可能です。

とのことなので試してみます。
最終的にはFacebook認証とかしたいんだけど、とりあえず。

ざっくり眺めた感じだと、

- 前回のサイト構築の手順をどこまで踏めばいいのか？
- データベースがなんの説明もなく出てくるんですけど……。

ってあたりが不安です。
え、大丈夫かな。
とりあえず進めてみます。

##前回の手順はまるごとコピー
よくわからんけど多分一通り動くものがあったほうがよさそうなので、まるごとコピーします。

	cd ..
	cp -r sample2 login_sample
	cd login_sample


##データベースは？

**立ち合いは強く当たって、あとは流れでお願いします。**



#SecurityServiceProviderを使う
なんのこっちゃって感じですが、例によってcomposerさんがなんとかしてくれるらしいです。

インストールはつつがなく終了。

> そして、Silexアプリのルートファイル(index.php)にプロバイダを下記のように登録します。

**つまり……どういうことだってばよ！？**
 
一瞬またファビョりかけましたが、これは普通にindex.phpのことですねたぶん。
たぶん。
きっとそう。

というわけで修正します。

もともとあったapp->registerは消せばいいのかな。

##ルーティングの設定とか
login_pathの説明にこんな感じの但し書き。

> ログイン情報を入力するフォームが記載されているページのパスになります。ルーティングの設定は自分で。

ん……？
ルーティングはだいたい分かるんですけど、どこで必要になるのかいまいちわかりません。
**っていうかまだログインページとか作ってないので設定しようがありません。**

とりあえず後になったら都合よく思い出せることを期待しつつスルーします。

##要注意と言われましても
check_pathのところにこんな一文。

> また、ログインフォームのアクション先のPATHをここで指定したものと同じようになるようにしないといけないので要注意。

ログインフォームのところになったら都合よく（ry


##データベースあった
> ログインユーザーをデータベースと照合します。UserProviderの引数には、ユーザー情報が登録されているデータベースを渡します。

**つまり、データベースを接続するような処理が必要になるし、それは調べてこいってことですかね？**

おk。

#ログインユーザー情報をデータベースと照合する
##UserProviderを作成？
なんかサンプルが提示されてます。
見てみましょう。

![スクリーンショット 2017-11-28 17.56.49.jpg](https://qiita-image-store.s3.amazonaws.com/0/214031/61f3c571-0814-90d7-b494-10cc4994b3d6.jpeg "スクリーンショット 2017-11-28 17.56.49.jpg")

**メディイイイイイイイイイイック！！！**

リンク切れてますね。


#ダメでした。
というわけでダメでした。
どっちみちデータベースつないだりなんだりで詰んでだとは思いますが。
**あとなんかQiitaのコメントで、Silexとかオワコンって教えてもらいました。**

GCPさんが使ってるからなんかそういう問題があるとは思いませんでした。

二重の意味で、終わりましたので、別の方法を探してみようと思います。
南無三！
「Windows 10不具合」スタートメニューが開けない場合の対処方法3選

<p><a href="https://www.e-soft.net/products/detail/23">Windows 10</a>でスタートメニューが表示されなかったり、開けなくなかったりして、クリックしても反応しないという場合の三つの対処方法を紹介していきます。</p>
<h2>コマンドプロンプトで表示される</h2>
<p>少し面倒な方法になるけど、その分不具合が解消される可能性もグンと高くなるよ。</p>
<p>「スタート」ボタンを右クリック　→　「タスクマネージャー」→「詳細」→「ファイル」→「新しい」タスクの実行という順にクリック</p>
<p>次に「開く」という欄に「cmd」と入力してから、「このタスクに管理者特権を付与して作成します」という項目にチェックを入れて、さらに「OK」という項目をクリックします。</p>
![240510351_org.v1472898659.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/6e856692-aedb-2dba-d2b8-6420f2197abf.jpeg)
<p>コマンドプロンプトを開いたら『dism /online /cleanup-image /restorehealth』の文字列をコピーして『system32>』の続きにそのまま貼り付け、「Enter」ボタンを押します。</p><p>画面に「操作は正常に完了しました」というメッセージが表示されてから、「sfc /scannow」を入力して、「Enter」を押します。</p><p>これにはしばらく時間がかかります。システムスキャンの検証フェーズを開始しています。</p><p>スキャンが完了したら「powershell」を入力して、「Enter」を押します。</p>
<p>最後に、「Get-AppXPackage -AllUsers  |Where-Object {$.InstallLocation -like "SystemApps"} | Foreach  {Add-AppxPackage -DisableDevelopmentMode -Register "$($.InstallLocation)\AppXManifest.xml"}  」を入力します。</p>
<p>次にコマンドプロンプト画面が赤枠項目のように表示されてから、コマンドプロンプト画面を閉じてください。</p>
![246955588_org.v1492258581.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/ef41690a-52ec-8abb-542b-fb7b2a3b7454.jpeg)
<p>ここまで作業が完了したら、PCを再起動してスタートメニューが正常に開けるようになっているか確認してみよう。</p><p>大抵はこのやり方を実行すれば、スタートメニューの不具合は解消されますが、解消されない場合は、このまま記事を読み進めてみよう。</p>
<h2>アカウントを追加してログインする</h2><p>新しくユーザーアカウント作成し、そのアカウントでログインすれば、スタートメニューが表示される場合もあります。</p><p>「スタート」ボタンを右クリック　→　「コンピューターの管理」→「ローカルユーザーとグループ」の順にクリック</p><p>画面の右側に「ユーザー」と「グループ」が表示されますが、「ユーザー」をダブルクリックします。</p>
![2017-03-07_15h32_22.png](https://qiita-image-store.s3.amazonaws.com/0/217125/c91a0a4f-be2b-065a-21fd-c988caf667b0.png)
<p>「ユーザー」の一覧が表示されるので何もないところで、右クリックし、表示されたメニューから「新しいユーザー」をクリックします。</p>
![スタートメニュー不具合2-4.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/7791ae2f-fac1-7b70-d0ba-b07e5742d1a1.jpeg)
<p>新しいユーザー登録画面にて「ユーザー名」と「パスワード」、「パスワードの確認入力」をそれぞれ入力して、「作成」をクリックしてください。</p><p>これで新しくアカウントを作成することが出来たね。アカウントを作成したら、今のユーザーは一旦ログアウトして、新しく作ったユーザーでログインしてみよう。これでスタートメニューが正常に動作してくれれば問題解決だね。</p>
<h2>スタートメニュー修復ツールを実行する</h2><p>Windows 10のスタートメニューを開けない場合に、マイクロソフトが公開する「スタートメニュー修復ツール」を実行することにより、「Windows 10」のスタートメニューを開けないという不具合を修復するという対策方法になります。</p><p><a href="https://support.microsoft.com/ja-jp/help/12385/windows-10-troubleshoot-problems-opening-start-menu-cortana">スタートメニュー修復ツール実行ファイル</a>にアクセスして、ダウンロードします。</p><p>次にダウンロードしたスタートメニュー修復ツールの実行ファイルを実行してください。</p>
![246950168_org.v1492249147.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/496f9d2f-220e-0792-bf47-a62a0a52ca42.jpeg)
<p>「次へ」をクリックします。</p><p>スタートメニューが正常な状態であれば『問題を特定できませんでした』というメッセージが表示されます。</p>
![2017-03-07_15h21_26.png](https://qiita-image-store.s3.amazonaws.com/0/217125/fd714c63-f7b7-5e45-b079-26430041ee18.png)
<p>この場合は、『トラブルシューティングツールを終了する』をクリックすればいいなんだけど、何かしらの問題があれば、画面の指示通りに操作を進めていこう。</p>
<p>ここまでご紹介した三つの対処方法を試していただければいずれかの方法で、スタートメニューが表示されない不具合が解決できます。<br>
困った時のお役に立てれば幸いです。</p>
軽量ドキュメントデータベースTinyDBが便利

#TinyDBとは
TinyDBはPure Pythonなドキュメント型データベース．サーバーを立てる必要が無いのが特徴で，手軽にDBライクな操作ができる点がおすすめ．個人でDBを使用する場合や試験環境ですぐに使いたい場合など，手間なく導入できるのでとにかく早い．ドキュメントは[こちら](http://tinydb.readthedocs.io/en/latest/intro.html#why-use-tinydb).

#参考サイト
http://symfoware.blog68.fc2.com/blog-entry-1830.html
http://esu-ko.hatenablog.com/entry/2016/03/01/Python%E3%81%A7mongo%E3%82%84json%E3%81%AE%E4%BB%A3%E3%82%8F%E3%82%8A%E3%81%ABtinydb%E3%82%92%E4%BD%BF%E3%81%86


#導入
```.py
pip install tinydb
```

#使い方
基本的な使い方

```.py
#モジュールのインポート
from tinydb import TinyDB, Query

#データベースの作成
db = TinyDB('sample.json')

#名前と年齢に関するデータの作成
#辞書型で挿入
db.insert({'name':'Bob', 'age':31})
db.insert({'name':'Jane', 'age':22})

#全データの取得
db.all()
'''[{'age': 31, 'name': 'Bob'}, {'age': 22, 'name': 'Jane'}]'''

#複数渡すとき
dic_list = [{'name':'John', 'age':25}, {'name':'Elen', 'age':40}]
db.insert_multiple(dic_list)

#ループ処理
for item in db:
    print(item)
'''
{'name': 'Bob', 'age': 31}
{'name': 'Jane', 'age': 22}
{'name': 'John', 'age': 25}
{'name': 'Elen', 'age': 40}
'''
```

Queryオブジェクトを使用したデータの検索

```.py
#Queryオブジェクトを作成
que = Query()

#'name'=='Bob'のデータを検索
db.search(que.name == 'Bob')
'''[{'age': 31, 'name': 'Bob'}]'''

#条件式を指定できる
#'age'<30のデータを検索
db.search(que.age < 30)
'''[{'age': 22, 'name': 'Jane'}, {'age': 25, 'name': 'John'}]'''

#ループ処理したいとき
for item in db.search(que.age < 30):
    print(item)
'''
{'name': 'Jane', 'age': 22}
{'name': 'John', 'age': 25}
'''
```

データの変更，削除

```.py
#データの更新
#'name'=='John'の'age'を26に変更
db.update({'age':'26'}, que.name == 'John')

#データの削除
#'age'<30のデータを削除
db.remove(que.age < 30)

db.all()
'''[{'age': 31, 'name': 'Bob'}, {'age': 40, 'name': 'Elen'}]'''

#全データを削除
db.purge()

db.all()
'''[]'''
```

テーブルの作成

```.py
#テーブルの作成
table = db.table('table')
#データの挿入
table.insert(dict)
#全データの表示
table.all()
#全テーブルの削除
db.purge_tables()
```

インメモリーで使用する場合

```.py
from tinydb.storages import MemoryStorage
db = TinyDB(storage = MemoryStorage)
```




おわり
ElastiCacheのredisをEC2で使う

EC2二台が使用するキャッシュサーバーとしてElastiCacheを導入しました。
今まではセッションをsessionsテーブルに持っていたのをredisに移行するすることが主な目的だったのですが、将来的によく利用するデータはredisに持たせたりしたいなという目論みもありました。

# redisのインスタンス作成

ElastiCacheの左側のメニューでredisを選択して「作成」からredisのインスタンスを作成します。

[![https://gyazo.com/13a7c619258295da8987420a5b5fa9bf](https://i.gyazo.com/13a7c619258295da8987420a5b5fa9bf.png)](https://gyazo.com/13a7c619258295da8987420a5b5fa9bf)

Amazon ElastiCache クラスターの作成 画面が表示されます。
入力すべきは以下の項目です。

- 名前
- ノードタイプ

パラメータグループもチューニングして設定すべきできすが、今のところデフォルトで困っていないので後回しにしています。

ElastiCacheの料金表は以下のリンクから確認してください。
https://aws.amazon.com/jp/elasticache/pricing/

[![https://gyazo.com/ccabd8b9a00296012311929f5ba806a8](https://i.gyazo.com/ccabd8b9a00296012311929f5ba806a8.png)](https://gyazo.com/ccabd8b9a00296012311929f5ba806a8)

詳細設定に進みます。

[![https://gyazo.com/1e6addedd11d2c1266685e2997b8dab3](https://i.gyazo.com/1e6addedd11d2c1266685e2997b8dab3.png)](https://gyazo.com/1e6addedd11d2c1266685e2997b8dab3)

入力すべきは以下の項目です。

- サブネットグループ
- セキュリティグループ

セキュリティグループはインバウンドでredisのポート(6379)を開けてあげたものを設定します。

# EC2からElastiCacheのredisへの疎通確認

```
$ redis-cli -h redis-name.xxx.xx.9999.xxxx.cache.amazonaws.com
$ ping
PONG
```

redis-cliが入っていない場合はインストールする必要があります。
（ubuntuの場合は ` $ sudo apt-get install redis-tools -y ` ）

# Railsの設定変更

config/initializers/session_store.rb

```
Rails.application.config.session_store :redis_store, servers: ENV['REDIS_URL'], expire_after: 3.months
```

redisのURLは環境変数で設定しているので、各サーバーの環境変更（REDIS_URL）にredisのエンドポイント（portは不要）を入れてあげればOKです。

エンドポイントはダッシュボードのプライマリエンドポイントを見てください。

[![https://gyazo.com/cc04366daa59f9c63ead12d31db1bfb5](https://i.gyazo.com/cc04366daa59f9c63ead12d31db1bfb5.png)](https://gyazo.com/cc04366daa59f9c63ead12d31db1bfb5)

<br>
_この記事は[ElastiCacheのredisをEC2で使う](https://tackeyy.com/blog/posts/use-elasti-cache-with-ec2)をQiita用に加筆修正したものです_
teratailで関わった技術たち

Leverages、teratailの新卒一年目エンジニアの[tkow](https://twitter.com/tkow39)です。Leveragesを技術力に定評のある会社に押し上げるべく入社しました。

技術の会社として認められるためにまずやることと言ったらQiitaで色々発信するべきだろうということで、有志でAdventカレンダーを作りました。**やる気がありすぎてほぼ一人で半分以上の枠を埋めてしまいました**。なるべく記事のクオリティを担保できるように頑張ります。

# teratailのインフラ

Google Cloud Platformを使っています。
インフラ構成はGCEインスタンスをItamaeサーバを使って管理しており、
teratail本体に関わるサービスはkubernetesを使用しています。

# teratailのフロントエンド

webpackを使ってフロントエンドのバンドルを行なっています。
理由は、共通化されていないファイルが多く存在する環境から
依存関係を把握できるように、module化されていないファイルを
整理するためにwebpackで整理しました。基本的にはbabel-loader
でes6を使用しています。全て、.jsでbuildを有効にしたいところ
でしたが、use strictモード制約に引っかかるようなスコープ汚染の
あるコードが多く、リファクタリング時に拡張子.esにすることで、有効に
なるようにローダーをセッティングして、レガシーなJSをモダンに変えています。
gulpの資産があるので、gulpからwebpackのbuildを叩く設定を作ってい
ますが、マイクロサービス化を目指しwebpack設定を分離して作成しています。

# teratailのバックエンド

PHPを使用しています。一部キャンペーンページなどを、micro service化してnuxtjs+expressサーバに移す試みをしています。また、それぞれのサービスはGCEまたは,GKEのL7ロードバランサーで管理されています。GCEとは別にGKEのIngressでL7ロードバランサーを噛ませる構成に変えたいと思っていますが、試行錯誤中です。

# teratailのCD

CIツールとして、Circle CIを使用しています。deployはGoogle Container Registryのgithubフックによって、releaseタグを作成したタイミングで、Docker Imageを作成し、```kubectl set image image:latest_tag```を利用してデプロイを簡易化しています。この手順で手動更新の作業が発生するのでもっとうまいやり方がないか考案中です。

公式の方に聞いたところ、CDの押しは[Spinnaker](https://www.spinnaker.io/)らしいです。buildオプションによってコンテンツデリバリーを設定していませんが、別プロジェクトで[Wercker](http://www.wercker.com/)で遊んでいて、パイプラインを自作するということができるのを知って、調べてみたら、Circle CIでもbuild工程でkubenetesのデプロイをできることを知ったので、ちょっと大変そうですが、やってみています。

# 何を考えて設計しているか

インフラの再生性や簡易性に重点を置いています。
[Infrastracture as Code](https://www.oreilly.co.jp/books/9784873117966/)で紹介されている概念を元に考えています。
構成管理設定ファイルのバージョン管理、フェニックス交換やカナリヤリリースが容易に設定できるkubernetesを選択しています。

### これらのそれぞれの技術の詳細についてはいくつかは後続の記事で書くつもりなので、後続のカレンダーをお楽しみにしていてください。
おまえ、もしかしてまだ、beginTransactionが死なないとでも思ってるんじゃないかね？


### ほんぺ

```php
try {
    $dbh->beginTransaction();

    // この間に色々処理が書いてある。

    $dbh->commit();
} catch (Exception $e) {
    $dbh->rollBack();
    log::write('ダメみたいですね…');
    log::write($e);
    throw $e;
}
```
っていう感じでPDOを操作しているPHPの処理があったんですが、
beginTransactionが失敗していてまともにログ出力出来ていなくて久々にキレそうになったので、怒りの殴り書きヽ(`Д´)ﾉﾌﾟﾝﾌﾟﾝ

---

`beginTransaction()`が失敗していた場合、`commit()`を実行する際に有効なトランザクションが存在しないため、`PDOException`がスローされます。

その後、catch処理に入った後、`rollBack()`が呼ばれますがここでも有効なトランザクションが存在しないため、PDOExceptionがスローされます。
どうなるかというと`rollBack()`以下の処理が一切実行されずに本来スローしたい例外が`PDOException`に置き換わります。

`beginTransaction()`から`commit()`までの間に何も無ければ被害は少ないですが、その間で例外が発生した場合は例外が`PDOException`に置き換わっているばかりかログに何も記載されておらず死が見えますよ…。

```php
$dbh->beginTransaction();

if (!$dbh->inTransaction()) {
    throw new \Exception('あ、おい待てい！');
}

try {
    // この間に色々処理が書いてある。

    $dbh->commit();
} catch (Exception $e) {
    $dbh->rollBack();
    log::write('ダメみたいですね…');
    log::write($e);
    throw $e;
}
```

ちょー適当だけど、コレだけでも最悪の事態は防げる。
ちゃんと適切な処理になっているか確認しましょう。というお話。

### 蛇足

トランザクションが必要な処理はトランザクションにちゃんと入っているか確認してほしい。
こんなウンコードでもいいからさ書いておくと違うんだしさ。頼むよ〜。

```php

function oreoreBeginTransaction($dbh){
    $dbh->beginTransaction();

    if (!$dbh->inTransaction()) {
        log::write('何か足んねぇよなぁ？');
        throw new Exception();
    }
}

function oreoreCommit($dbh){
    if (!$dbh->inTransaction()) {
        log::write('ファッ！？');
        throw new Exception();
    }
    $dbh->commit();
}

function oreoreRollBack($dbh){
    if (!$dbh->inTransaction()) {
        log::write('あのさぁ・・・');
        throw new Exception();
    }
    $dbh->rollBack();
}
```