OmniAICreator/Qiita-1.07M huggingface dataset:
C言語で再帰的な総当りプログラムを書く

# 1. 総当りプログラムの概要

N桁のM進数が取りうるすべての整数を出力します。

たとえば3桁の2進数なら、
{000, 001, 010, 011, 100, 101, 110, 111}
を出力します。

forループ1回で、1桁のM進数が取りうるすべての整数を出力できるので、
総当りプログラムをforループで書くと、実にN重ループのコードになってしまいます。

今回はそんな問題を、再帰構造にすることで綺麗にまとめてしまいましょう。

# 2. ソースコード

はじめにソースコードを提示します。
マクロの値を変えることで、パラメータを変更できます。

* MAX_IDX : N桁
* MAX_VAL : M進数
* INIT    : M進数の初期値(基本は0)

```c:recursive_brute_force.c
#include <stdio.h>

#define MAX_IDX 2
#define MAX_VAL 1
#define INIT 0

void print_a(int* a){

	int i = 0;

	for (i = 0; i < MAX_IDX+1; i++){
		printf("%d ", a[i]);
	}
	printf("\n");

}

int check_init(int* a){

	int i;

	for (i = 0; i <= MAX_IDX; i++){
		if (a[i] != INIT) return 0;
	}

	return 1;

}

int recursive_increment(int idx, int* a){

	if (idx < MAX_IDX) {
		while (1){
			a[idx] += recursive_increment(idx + 1, a);
			if (a[idx] > MAX_VAL){
				a[idx] = INIT;
				return 1;
			}
			if (check_init(a)) break;
		}
		return 0;
	}
	else {
		print_a(a);
		if (a[idx] == MAX_VAL){
			a[idx] = INIT;
			return 1;
		}
		else{
			a[idx]++;
			return 0;
		}
	}

	return -1;
}

int main(void){

	int a[MAX_IDX + 1];
	int buf, i;
	
	for (i = 0; i < MAX_IDX + 1; i++){
		a[i] = INIT;
	}

	buf = recursive_increment(0, a);

	return 0;
}

```

# 3. 解説

上記のソース（recursive_brute_force.c）の詳細を説明します。

# 3.1. アプローチ

まずは簡単な例として、3桁の2進数を考えましょう。

冒頭に示したとおり、この場合に取りうる値は
{000, 001, 010, 011, 100, 101, 110, 111}
となります。

この集合を総当りで表示するには、次のアルゴリズムが考えられます。

1. 取りうる最も低い値（000）で初期化する。2に進む。
2. 1桁目をインクリメントする。3に進む。
3. 1桁目が最大値(1)を超えたら、4に進む。そうでない場合、2に進む。
4. 1桁目を初期値(0)にし、2桁目をインクリメントする。2桁目が最大値を超えたら、5に進む。そうでない場合、2に進む。
5. 1桁目と2桁目を初期値にし、3桁目をインクリメントする。3桁目が最大値を超えたら、終了する。そうでない場合、2に進む。

当たり前と言えば当たり前ですが、このアルゴリズムが基本になります。
上の例では3桁の2進数と状況を限定しているので、手計算でも、forループでも簡単に計算できますが、
一般化するとなると少々難しくなります。

# 3.2. 再帰的に一般化

3.1.で示したアルゴリズムを再帰的に一般化すると、下記のようになります。

1. 取りうる最も低い値で初期化する。桁を表わす変数idxを0で初期化する(idx=0は最上位桁)。2に進む。
2. idxが最下位桁を指していなければ、再帰する。idxをインクリメントし、再び2に進む。最下位桁なら、3に進む。 
3. 最下位桁の値が最大値なら、最下位桁を初期値にし、1を返す。それ以外なら、最下位桁をインクリメントし、0を返す。4に進む。
4. 返り値をidx桁に足す。最大値を超えたら、idx桁を初期値にし、1を返して、再び4に進む。それ以外なら、5に進む。
5. すべての桁が初期値なら、0を返して、4に進む。

スタック上の関数がmain関数のみとなったとき、このアルゴリズムは終了します。

再帰をするたびにidxがインクリメントしてより低い桁を指すようになり、
再帰から返るたびに桁がひとつずつ上がっていく、というイメージが理解できれば、掴みやすいです。
plenvの基本メモ書き


plenvの簡単なメモ書きがあったので、アップ。
このくらいあれば、基本は使えるはず。

### plenvをインストール
gitからplenvをインストールする。
「Perl-Build」はperlのバージョンをインストールするときに、ビルドするために必要。

> $SHELLは「/bin/bash」であり、-lは以下である。(man参照)
>> ログインシェル (後述の 起動 セクションを参照)  として起動されたかのように bash を動作させます。

```Bash
git clone git://github.com/tokuhirom/plenv.git ~/.plenv
git clone git://github.com/tokuhirom/Perl-Build.git ~/.plenv/plugins/perl-build/
echo 'export PATH="$HOME/.plenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(plenv init -)"' >> ~/.bash_profile
exec $SHELL -l
```

### インストール可能なperlバージョン確認

plenvからインストールできるバージョンの一覧を表示する。

```Bash
plenv install -l
```

### バージョン指定でperlインストール

バージョン指定でインストールする。

```Bash
plenv install 5.25.3
```

### バージョン指定でperlアンインストール

インストール済みのperlをアンインストールする。

```Bash
plenv uninstall 5.25.3
```

### インストール済みのperlバージョン確認

インストール済みのバージョンを一覧化する。

```Bash
plenv versions
```

### 利用するperlのバージョン指定

グローバルで利用するperlのバージョンを設定する。

```Bash
plenv global 5.25.3
```

ローカルで利用するperlのバージョンを設定する。
実行するとカレントディレクトリに「.perl-version」が作成され、そのフォルダにおいてglobal指定より優先される。

```Bash
plenv local 5.25.3
```

実行中のshellで利用するperlのバージョンを設定する。
※ global、localよりも優先度高らしい。

```Bash
plenv shell 5.25.3
```

### cpanmをインストール

cpanmをインストールする。

```Bash
plenv install-cpanm
```

### cpanモジュールをインストール

cpanmを使って、cpanモジュールをインストール

```Bash
cpanm Unicode::Japanese
```

### cpanモジュールをアンインストール

cpanmを使って、アンインストール

```Bash
cpanm -U Unicode::Japanese
```

### インストール済みのcpanモジュール一覧化

#### cpanモジュールの一覧化

cpanモジュールの一覧化には、個別のコマンドは存在しておらず@INCからpmファイルを検索する。
```Bash
find `perl -e 'print "@INC"'` -name '*.pm' -print
```


#### cpanm配下を一覧化するスクリプト

cpanmを使ってインストールしたモジュール名のみを取得するスクリプトは以下。

```Bash
find `perl -e 'print "@INC"'` -name '*.pm' -print | grep "\.\/\.cpanm/*/*/*" | awk -F'/' '{print $5}' | sort | uniq
```

### シバンの書き方。

「#!/usr/bin/perl」とやってしまうと、せっかく使っているplenvが役に立たないので、シバンに書くときは環境変数のperlを直接読み込むようにする。

```bash
#!/bin/env perl
```
【Win32API】透過色を指定して画像を描画する

#概要
簡単なゲーム作ったり，GUIツールを作ったりする際に，`Win32API`でイメージを表示することがあるが，
`LoadImage`関数などで読み込む画像はαチャンネルがないので，そのままでは透過処理ができない．
その際に，通常はマスク画像を使った透過処理を施すが，一々マスク画像を作る必要がある．
そこで，マスク画像作成をすっ飛ばして，透過色を指定して透過処理を行う方法を紹介する．

`DirectX`を使えば，αチャンネルを持っている画像も扱えるとは思うが，
GUIツール作るのに`DirectX`使う人はそうそういないだろう…
文章中の例は，とりあえずゲームを作っている想定で書く．

#マスク画像を用いて透過する方法
まずは通常のやり方を．
といっても調べれば出てくるので，ここでは簡単に原理だけ．

用意するのは以下の画像．
●背景画像
●キャラ画像(表示したい絵以外の部分は白で塗られている)
●キャラ画像のマスク(表示したい絵の部分は白で塗られていて，それ以外は黒で塗られている)

まず背景を描画する．

次にマスクを論理積(OR)で合成する．
こうすると，マスクの黒い部分は背景と論理積を取ることで全て背景に統一され，
白い部分は全て白で統一される．
(例：背景 | 黒 = 1001 | 0000 = 1001，背景 | 白 = 1001 | 1111 = 1111)

つまり，キャラ画像の白いシルエットが背景の中に表示されている状態になる．

最後にキャラ画像と論理和(AND)を取ることで，
白いシルエットの上に，色が付いた画像が合成される．
(例：背景 & 白 = 1001 & 1111 = 1001，白 & キャラ = 1111 & 1100 = 1100)

#マスク画像を用いずに透過する方法
あくまでユーザがマスク画像を用意せずに，という意味だが．
以下にサンプルを示す．

```cpp:main.cpp
#include <wingdi.h> 

//画像透過用のライブラリ.
#pragma	comment(lib,"msimg32.lib")

//イメージ作成．
HDC		dstHdc		= CreateCompatibleDC( srcHdc );
HBITMAP oldImage	= (HBITMAP)SelectObject( dstHdc, loadedBmp );
	
//透過色指定描画.
TransparentBlt( 
	srcHdc, srcX, srcY, srcW, srcH, 
	dstHdc, dstX, dstY, dstW, dstH, RGB( 0, 0, 0 ) );
	
//イメージ削除.
SelectObject( dstHdc, oldImage );
DeleteDC( dstHdc );
```

無論上記のサンプルは動かない．
非常にシンプルな関数で，転写先の位置，サイズと転写元の位置，サイズを指定して，
後は何色を透過するかを渡せば，勝手に透過した画像を転写してくれる．

#注意点
●`#include`やライブラリの読み込みは忘れずに行うこと．といっても忘れたらコンパイルエラーになるので，そこまで注意する必要もないが．
●実際には，自動的に指定色に合わせたマスク画像を生成して，それを使ってマスク画像を用いた透過を行っている模様．遅くなることは間違いない．

#発展
指定色に合わせてマスク画像を生成するツールを作成して，
前もってマスク画像を用意し，描画時はマスク画像を用いた透過を行えば，
画像作成もめんどくさくないし，速い処理が可能になる．
SERVERLESSフレームワークを使って15分でLINE Bot作る

# 背景
1. この記事を見かけて、SERVERLESS使えばもっと簡単に早く作れるんじゃないかと思った。このURL参考にすれば基本的に作れます、おすすめ。
[LINE BOT APIを使ってAWS Lambdaでサーバレスな版画風写真加工BOTを作る(Node.js)](http://qiita.com/akihito_nagai/items/f284ef495da380f368cc#35-%E7%94%BB%E5%83%8F%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E9%80%81%E4%BF%A1)

1. LINE Developerアカウントを持て余していた。

1. SlackのBot作ってて楽しいってなってた。
[Hubot × Raspberry Pi2で電車の遅延情報をSlackに流す](http://qiita.com/seiya_orz/items/663b86e4ede6d4d0814e)

# 大まかな手順
1. serverlessをインストール
2. aws-cliをインストール
3. aws configure
4. sls project create
5. sls function create hogehoge
6. s-function.jsonのmethodをPOSTにする（LINEのCallbackはPOSTリクエストで飛んでくる）
6. npm install --save serverless-cors-plugin（CORS設定しとかないと403になっちゃう）
7. s-project.jsonにplugin書く（SERVERLESSのGithubに書いてある）
8. handler.jsに処理書く
8. sls function deploy
9. sls endpoint deploy -a（初回だけ-aしないと、CORSの設定が反映されない）
10. LINEのCallbackにendpointのURLを書く。（※ポート番号を443にする必要あり。要するにhttps.....amazonaws.com:443/dev/hogehogeにする。)

以上。handler.jsに書く処理量によりますが、疎通確認するだけなら15分もかからない。SERVERLESSすごい。

# Botでできるようにしたこと
## 誕生花教えてくれる
疎通確認も含めて、下記記事で作った自前の誕生花APIをLINE Botが叩く
## 電車が遅延していたら教えてくれる
[Hubot × Raspberry Pi2で電車の遅延情報をSlackに流す](http://qiita.com/seiya_orz/items/663b86e4ede6d4d0814e)で作った機能を流用。LINE BotのCallback用EndpointをPOSTで叩けば、Lambdaが呼び出されるので、遅延発生時にSlackだけじゃなくLINE用EndpointにもPOSTすれば呼び出せる。ただ、LINEではユーザをmidで管理しているため、自分の普段使っているLINEアカウントのmidをデバッグで見て、マジックナンバー化してそいつに投げてる。LINE用のLambdaにcronとか埋め込んでもいいが、リクエスト回数で課金されるので、常に起動しているSlack Bot（Raspberry Pi）にポーリングさせてる。ただ、作ってからまだ電車遅延してないので動作未確認。

# 今後やりたいこと
結構反応が鈍いので、なんとかしたいが原因はよくわからない。いろいろ拡張したいが、仕事中はLINE使わないので、結局使わない気がする。全部Slack Botの機能になりそう。

なんか思いついたらやります。
npm-check でpackageの更新情報と未使用を検出する

npm-check package で依存 package の更新情報と未使用を検出します

## <i class='fa fa-download'></i> インストール
```bash
$ npm install -g npm-check
```

## <i class='fa fa-flask'></i> サンプル
npm 版の cowsay に対して試してみます。  
2件の更新対象がみつかりました。  

```bash
$ pwd
<cowsay project root>
$ npm-check
get-stdin   😎  MAJOR UP  Major update available. https://github.com/sindresorhus/get-stdin
                         npm install --save get-stdin@5.0.1 to go from 4.0.1 to 5.0.1

nodeunit    😎  NEW VER!  NonSemver update available. https://github.com/caolan/nodeunit#readme
                         npm install --save-dev nodeunit@0.10.0 to go from 0.9.3 to 0.10.0

Use npm-check -u for interactive update.
```

![npm-check.gif](https://qiita-image-store.s3.amazonaws.com/0/43480/f16e58ca-13f5-e08d-56b6-618bf5cc5074.gif)

## <i class='fa fa-graduation-cap'></i> まとめ
更新情報を検出するだけなら `npm outdated` と変わりませんが、
package.json にあるが未使用の Package や、逆にコード内で利用しているが
package.json に依存の記載がない Package も警告してくれます。
ただし精度に問題があるようです。

依存性のチェックは <a href="https://github.com/depcheck/depcheck" target="\_blank">depcheck/depcheck</a> package で行っていますが、
このリポジトリのREADMEでも以下のように明言しています。

>The logic of a special is not perfect. There might be false alerts. If this happens, please open an issue for us.

とはいえ、有益であることに変わらないのでしょう。
npm-check の star が 2016/08/31 現在で 2,697 もついているので。

## <i class="fa fa-book" style="font-size:1em;"></i> 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [npm-check - npm](https://www.npmjs.com/package/npm-check)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [depcheck/depcheck - GitHub](https://github.com/depcheck/depcheck)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [piuccio/cowsay - GitHub](https://github.com/piuccio/cowsay)
ruby tracepoint

http://ruby-doc.org/core-2.0.0/TracePoint.html

http://kgrz.io/2014/04/19/ruby-trace-leave-oh-my.html

```rb
RubyVM::InstructionSequence.compile_option = {
  trace_instruction: false
}

trace = TracePoint.new(:raise) do |tp|
	puts "lalala"
end

trace.enable

0 / 0
```

但是把trace禁用了，还是可以tracepoint
[Unity] Asset Bundle をビルドしてAWS S3 にアップロードする

実行すると、Asset Bundle をビルドし、ビルドしたファイルを AWS S3 にアップロードするエディタ拡張

[UnityAssetBundleBuilder.cs](https://gist.github.com/tkyaji/115fd06c8a180cb0636af923a1894978)

# 使い方

上記スクリプトをダウンロードして、以下の項目を入力します。

* s3Bucket
* s3KeyBase
* s3AccessKeyId
* s3SecretAccessKey

入力したら、スクリプトを `Assets/Editor` に配置します。
メニューに `Build` -> `Build Asset Bundles` が出てくるので、
実行すると、Asseet Bundle のビルド -> S3へのアップロードが実行されます。


ビルド時のオプションとかは、いい感じに変更して使ってください。
配列をリストに追加するベンチマーク

配列をリストに追加する以下ふたつの方法のベンチマークをとってみました。

- `Collections.addAll(...)`
- `List#addAll(...)` と `Arrays.asList(...)` の組み合わせ

## ベンチマーク方法

* 10000 の配列を 100 回 List に追加

## 結果

| 方法          | 時間（ナノ秒） |
|:--------------|------------:|
| Collections   |     8974267 |
| List + Arrays |     2480949 |

List が ArrayList の場合、Collections よりも List + Arrays の方が高速でした。

実装を見ると、Collections は for ループでひとつずつ追加しているのに対し、List は System.arraycopy で追加しています。速度の差はこのためです。Collections.addAll は Collection 全般に利用できるメソッドで、かつ要素が追加されたかどうかを boolean で返すので、ループで回すのは仕方がないです。

少なくとも、自分でループを回して追加するのはやめましょう。

## 検証コード

```Java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Main {
	public static void main(String... args) {
		String[] array = new String[10000];
		List<String> list = new ArrayList<>();

		long total1 = 0;
		for (int i = 0; i < 100; i++) {
			long start = System.nanoTime();
			Collections.addAll(list, array);
			long end = System.nanoTime();
			total1 += (end - start);
			list.clear();
		}
		
		long total2 = 0;
		for (int i = 0; i < 100; i++) {
			long start = System.nanoTime();
			list.addAll(Arrays.asList(array));
			long end = System.nanoTime();
			total2 += (end - start);
			list.clear();
		}
		
		
		System.out.println("total1: " + total1);
		System.out.println("total2: " + total2);
	}
}
```

## 補足

List が LinkedList の場合、Collections の方が若干速くなりました。

| 方法          | 時間（ナノ秒） |
|:--------------|------------:|
| Collections   |    19991340 |
| List + Arrays |    21064007 |

ただし、こうした用途に LinkedList は向いていないので参考までに。
RaspberryPiでUX302NCを使う


UX302NCを入手したので、構成をメモしておく。[参考](http://qiita.com/air-gh/items/5b7e1dc28261fef722e5)

ファームウェアを 1.0.7 に更新した現在は、gobi1k として認識されるようにしないと使えない。L-02C と同様。scsi コマンドは vendor specific なやつですね。

```/etc/udev/rules.d/75-modem.rules
# UX302NC
SUBSYSTEMS=="scsi", ATTRS{vendor}=="USBModem", KERNEL=="sg*", RUN+="/bin/sleep 1", RUN+="/usr/bin/sg_raw /dev/%k 06 f5 04 02 52 70"
SUBSYSTEM=="usb", ATTR{idVendor}=="11f6", ATTR{idProduct}=="1034", RUN+="/sbin/modprobe -b qmi_wwan"
SUBSYSTEM=="drivers", ENV{DEVPATH}=="/bus/usb/drivers/qmi_wwan", ATTR{new_id}="11f6 1034"
SUBSYSTEM=="usb", ATTR{idVendor}=="11f6", ATTR{idProduct}=="1034", RUN+="/sbin/modprobe -b qcserial"
SUBSYSTEM=="drivers", ENV{DEVPATH}=="/bus/usb-serial/drivers/qcserial", ATTR{new_id}="11f6 1034 0000 05c6 9212"
```

`usb-devices` では、こうなった。AT コマンドのインターフェースと NDIS は排他で動作する様子。

```
T:  Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 10 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=11f6 ProdID=1034 Rev=02.32
S:  Manufacturer=NCXX Inc.
S:  Product=NCXX UX302NC
C:  #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=500mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
I:  If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
I:  If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qcserial
I:  If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
```

対応バンドを眺めてみる。L-02Cより広いですね。

```
# qmicli -d /dev/cdc-wdm0 --dms-get-band-capabilities
[/dev/cdc-wdm0] Device band capabilities retrieved:
        Bands: 'gsm-dcs-1800, gsm-900-extended, gsm-900-primary, gsm-850, gsm-pcs-1900, wcdma-2100, wcdma-850-us, wcdma-800, wcdma-1700-japan, wcdma-850-japan'
        LTE bands: '1, 3, 18, 19, 21'
```

`modemmanager`, `libqmi-proxy`, `policykit-1` をインストールして `mmcli` で繋ぐ。接続確立後 `dhcpcd` を起こすと `wwan0` にアドレスが割当たる。dual-stack です。

```
# mmcli -m 0 --simple-connect=apn=iijmio.jp,user=mio@iij,password=iij,ip-type=ipv4v6
# dhcpcd
```

IPv4, IPv6 dual-stack にしたい場合は `qmicli` よりも `mmcli` を使ったほうが良さそう。dual-stack を構成するときは、IPv4, IPv6 それぞれに wds client を[生成する](https://cgit.freedesktop.org/ModemManager/ModemManager/tree/src/mm-bearer-qmi.c#n960)。`qmicli` はコマンド一つで wds client 一つしか作らない（client-idひとつずつ処理するように設計されている）ので、両方一気に用意したい場合は `mmcli` のほうが便利。

Windows環境
-------------
公式のドライバでは、こう認識されている。

| ハードウェアID | 名前 |
|:--|:--|
| usb\vid_11f6&pid_1034&mi_00 | NCXX UX302NC HS-USB Diagnostics    |
| USB\VID_11F6&PID_1034&REV_0232&MI_01 | NCXX UX302NC HS-USB Modem |
| usb\vid_11f6&pid_1034&mi_02 | NCXX UX302NC HS-USB Application    |
| USB\VID_11F6&PID_1034&MI_03 | NCXX UX203NC Ethernet Adapter      |
AWS CLI でファイルを暗号化して s3 へアップロード



```
$ aws s3 cp himitsu.txt s3://{バケット名}/himitsu.txt --sse
```


`aws configure` であらかじめリージョンを設定しておくこと。
コマンドを実行するのがEC2インスタンスでIAMロールが割り当てられている場合、アクセスキーID,シークレットアクセスキーは設定不要。
Dockerfileのベストプラクティス

Dockerfileのベストプラクティスについて以下のページに記載されているので、自分用にピックアップ。
http://docs.docker.jp/engine/articles/dockerfile_best-practice.html

| ガイドライン・推奨 | 備考 |
|:---|:----|
| コンテナはエフェメラルであるべき | |
|.dockerignore ファイルを使う|ディレクトリには Dockerfile が構築に必要なファイルだけ追加 |
| 不要なパッケージのインストールを避ける |   |
|コンテナ毎に１つのプロセスだけ実行||
|レイヤの数を最小に  |   |
|複数行の引数   |複数行の引数をアルファベット順にする。これにより、パッケージが重複しないようにしたり、リストの更新を簡単にする。   |

Dockerfile命令

| 命令 | 備考 |
|:-----|:-----|
| FROM  |  自分のイメージの元として現在の公式レポジトリを使う。Debian イメージ 推奨 |
| RUN   | 複雑な RUN 命令はバックスラッシュを使い複数行に分割。RUN apt-get update と apt-get install は常に同じ RUN 命令文で連結。RUN apt-get update && apt-get install -y を使う。  |
| CMD  | CMD は常に CMD [“executable”, “param1”, “param2”…] のような形式で使うべきである  |
| EXPOSE  | アプリケーションが一般的に使う、あるいは、伝統的なポートを使うべきである  |
| ADDとCOPY  |  COPY が望ましい。 |
| WORKDIR  |常に WORKDIR からの絶対パスを使うべきである   |
asarを使ってみる

## asarとは

複数のファイル・ディレクトリを一つのファイルにパックする、tarのような仕組みです。[Electron](https://github.com/electron/electron)でアプリをパッケージ化するためにGitHubが作りました。リポジトリは[こちら](https://github.com/electron/asar)。

zip等と違ってファイルを圧縮せずにオリジナルのまま保持するのでランダムアクセスが容易です。ファイル構造が単純なため、パーサーを書くのも簡単です。
とりあえず基本的な使い方だけさくっと覚えましょう。

## インストール

Node.jsをインストールしていない場合は先にインストールしてください。
ターミナルで以下のコマンドを実行すると、`asar`コマンドが使用できるようになります。

    npm install -g asar

## アーカイブを作成する

例:`mydir`ディレクトリを`archive.asar`ファイルにパックするには以下のコマンドを実行します。

    asar pack mydir archive.asar

## アーカイブを展開する

例:`archive.asar`ファイルを`output`ディレクトリに展開するには、以下のコマンドを実行します。

    asar extract archive.asar output
Atomでユーザ補助機能を作るためのモジュール作った

[user-support-helper](https://www.npmjs.com/package/atom-user-support-helper)

![](http://hiroakimikami.github.io/atom-user-support-helper/interactive-configuration-panel.gif)

Atomパッケージの初期設定などの支援機能を作るためのモジュールを作った．
初期設定が必要なパッケージってそれなりの数あると思う．[自分のパッケージ](http://qiita.com/MikamiHiroaki/items/7620023e6a870ac17e90)におけるMS TranslatorのIDとSecretとか，pandocを使うパッケージにおけるpandocのパスとか．しかし，そのうち大半（自分の知る限り全て）のパッケージでは，そういった初期設定はREADMEを見ながら，Settings画面から自分で設定する以外の方法がない．
そのため，

1. 自分でインストールしたパッケージに追加する設定を見落として暫く悩む．
2. [translator-plus-dictionary](https://atom.io/packages/translator-plus-dictionary)に「翻訳動かないんだけど」って問い合わせがあってエラーメッセージ見るとIDとSecretの登録がされていない．

のような問題が起きてしまっていた．これへの対応策として，初期設定パネルなどを作るモジュールを作った（上Screenshot参考）．必要な設定がなされてない時，エラーメッセージが出るのではなく，このようなパネルが出て，interactiveに初期設定ができる方が便利でないかなと．

このようなユーザ補助機能を実装するのは面倒で，後回しにされがちだと思うので（少なくとも自分は後回しにする），機能よりも記述するコード量が少なくなることを優先して実装したつもり．例えば，pandocのパスが必要なら，

```javascript
const panel = new UserSUpportHelper().getInteractiveConfigurationPanel()
panel.add('package-name.pandocPath', {
  type: 'input',
  name: 'The path of the pandoc command'
})

if (!atom.config.get('package-name.pandocPath')) {
  panel.show(['package-name.pandoncPath'])
}

```

のように書けば以下のようなパネルが表示される（translator-plus-dictionaryでは設定項目が5つもあるので数十行の記述が必要だった）．

![example.png](https://qiita-image-store.s3.amazonaws.com/0/111070/989438f3-6650-40a6-b90b-279f257ad64c.png)

基本的に自分が使いたいから作ったパッケージですが，Atomパッケージ書く人で使いたいなと思う人がいたら是非使ってやってください．
Dockerでクレデンシャル情報を渡す方法

既存のアプリケーションをコンテナ化する際、GitHubからプログラムをクローンするケースがある。このとき、Dockerfileにアカウント名、クレデンシャル/Tokenを記載してしまうとセキュリティ的に問題がある。
これを回避するために、DockerEngine1.9から実装されたbuild-time argumentsの機能を用いる。build-time argumentsを利用することにより、Dockerfileのビルド時にパラメータを設定することができる。

Dockerfile

```
・・・
# Deploy application
ARG GITHUB_ACCOUNT
ARG GITHUB_CREDENTIAL
RUN git clone -b develop https://$GITHUB_ACCOUNT:$GITHUB_CREDENTIAL@github.com/XXXX/YYYY/ZZZ.git
・・・
```

以下のコマンドを実行し、コンテナイメージのビルドを行う。

```
sudo docker build --build-arg GITHUB_ACCOUNT={GitHub Account} --build-arg GITHUB_CREDENTIAL={GitHub Credential/Token} -t gcr.io/{GCP PJ Name}/{Application}:{version} {Dockerfileが含まれるフォルダ}
```

これでDockerfileにクレデンシャル情報を記載せずに、builｄ時にGitHubからソースをcloneしてアプリを利用することができる。

よりセキュアな方法があるかは引き続き調査を行う。
リンクサーバへアクセスするSQL Serverユーザーエージェントジョブを実行した際の「現在のセキュリティ コンテキストは信頼されていないので、リモート サーバーへのアクセスが拒否されました」というエラーを解決する

# はじめに

リンクサーバへアクセスするSQL Serverユーザーエージェントジョブを実行すると、「現在のセキュリティ コンテキストは信頼されていないので、リモート サーバーへのアクセスが拒否されました」というエラーになる場合があります。

このエラーの解決方法をググると、おおむね以下のような内容のものが見つかります。

- リンクサーバのセキュリティ設定を「このセキュリティ コンテキストを使用する」にする
- 「リモート ログイン」と「パスワード」にリモートサーバのユーザー名とパスワードを設定する

![figure1.png](https://qiita-image-store.s3.amazonaws.com/0/42710/8bdb17e1-e09b-8b91-0874-b6bc9d971479.png)

これで接続できるようになるということは、なにかジョブ特有の制限などによって失敗しているということではなく、単に接続の設定がうまくいっていないということのようです。確かにこれでエラー無く接続できるようになりますが、要はこのサーバにログインできるユーザーを無条件でリモートサーバにアクセスできるようにしているわけで、セキュリティ的には微妙です。

こういう何らかの制限を全開放することで解決するみたいなやり方は負けた感じがするので、全開放しないやり方を調べてみました。

# そもそもなぜマッピングか使われないのか

リンクサーバへの接続はローカルのログインにリモートのログイン情報をマッピングするという方法で行います。さっきの設定はこのマッピングに該当しないユーザーのための設定です。

![figure2.png](https://qiita-image-store.s3.amazonaws.com/0/42710/ccf54a1f-7b9a-2756-efe4-002c2e8d740d.png)

このマッピングの設定が間違っている場合、ジョブ以外のところでも、たとえばリンクサーバに対するクエリーの実行やManagement Studioのリンクサーバのカタログを見たりなども失敗するはずです。これらができるということは、このマッピングの設定は間違っていないと言えるでしょう。ということは、ジョブがマッピングで設定されているユーザーで実行されていないことが考えられます。

ジョブに指定するユーザーの情報としては、ステップの設定にある何も選べない「実行するアカウント名」が真っ先に目に付きますが、これは罠です。

![figure3.png](https://qiita-image-store.s3.amazonaws.com/0/42710/25eed18a-78f3-c1d6-0633-a6fa1b960f5c.png)

この設定はステップの種類が外部コマンドなどの場合に実行するWindowsのアカウントを指定するもので、「Transact-SQL スクリプト」の場合は指定することはできません。種類を別のものに変えてから「Transact-SQL スクリプト」に戻すとグレーアウトされて選択できなくなります。

その他の設定としては詳細設定にある「実行時のユーザー」がそれっぽい感じがしますが、これも違います。SQL Serverにはサーバへの接続に使用する「ログイン」と、データベースへの権限などを指定する「ユーザー」との2種類のユーザーがあります。マッピングで使用するのは「ログイン」の方で、「実行時のユーザー」はデータベースの「ユーザー」なので違います。

ではどこで指定するのかというと、以下の引用にあるように「ジョブの所有者」です。引用中の「SQL Server エージェント プロキシ」というのは先ほどの「実行するアカウント名」の設定のことです。

ジョブ ステップの管理 | Transact-SQL ジョブ ステップ
https://technet.microsoft.com/ja-jp/library/ms187056(v=sql.110).aspx#Anchor_2
> Transact-SQL ジョブ ステップでは SQL Server エージェント プロキシを使用しません。このジョブ ステップはジョブ ステップの所有者として実行されるか、ジョブ ステップの所有者が sysadmin 固定サーバー ロールのメンバーの場合には SQL Server エージェント サービス アカウントとして実行されます。

ジョブの所有者の初期値はジョブを作成したユーザーですが、ジョブを作成できるユーザーはおおむね sysadmin になっていますから、SQL Server エージェントサービスアカウント(NT SERVICE\SQLAgentみたいなやつ)として実行されていたわけです。リンクサーバのマッピングにそんなユーザーは設定していないのでリンクサーバへの接続に失敗していたというわけです。

# 正しく動作する設定方法

ということで、正しく動作する適切な設定は以下になります。

+ ジョブの所有者に適切なユーザーを設定する
+ リンクサーバのログインのマッピングにジョブの所有者を追加する


[参考]
リンク サーバーの作成 (SQL Server データベース エンジン)
https://msdn.microsoft.com/ja-jp/library/ff772782.aspx
Get-ChildItem | Export-CSV で出力されるものが変わる

ざーっと特定ディレクトリ配下のファイルの一覧を出力してそのファイルの状態を比較しようと思った時の話

~~~tree
C:.
│  text1.txt
│
├─dir2
│  │  text2.txt
│  │
│  └─dir4
│          text4.txt
│
└─dir3
        text3.txt
~~~
的な状態で、

~~~
Get-ChildItem dir2 | Export-Csv dir2.csv -Encoding UTF8
Get-ChildItem dir3 | Export-Csv dir3.csv -Encoding UTF8
~~~
をやると、dir2.csvとdir3.csvの項目は異なるものが作成される。
具体的には、Get-ChildItemの最初(?)のオブジェクトの違い、
\#TYPE System.IO.DirectoryInfo
\#TYPE System.IO.FileInfo
の差がでるため。
プロパティの差はそんなに大きくはないのだが、ファイルにはあってディレクトリにはない Length が結構(個人的には)致命的。

エレガントなやり方ではないかもしれないが、Select-Objectを間に挟んで、

~~~
Get-ChildItem dir2 | Select-Object PSDrive, BaseName, Mode, Name, Length, DirectoryName, Directory, IsReadOnly, Exists, FullName, Extension, CreationTime, CreationTimeUtc, LastAccessTime, LastAccessTimeUtc, LastWriteTime, LastWriteTimeUtc, Attributes | Export-Csv dir2.csv -Encoding UTF8
~~~
とかやってあげる必要がありそうな気がしている。
実際にはもう少し必要なプロパティにだけ絞り込んであげればよいかな。
EclipseにPydev5.2を追加してもPydevが表示されないとき（2016/8/30)

#症状
　EclipseにPyDevプラグインをインストールしても、Perspective一覧や設定（の左ペインのツリー）にPyDevが表示されない。

#原因
Pydevプラグインはバージョン（2016年8月最新はv5.2.0）によって対応するJava・Eclipseバージョンが異なり、対応があっていないとPyDevパースペクティブが表示されないため。

#対策
　以下のような組み合わせでインストール・起動すること。

 - PyDev 5.2 の場合
    - （Eclipseを起動する）Javaランタイム　　　Java 8
    - Eclipseバージョン　　　　　　　　　　　　Eclipse 4.5以降
 - PyDev 4.x の場合
    - （Eclipseを起動する）Javaランタイム　　　Java 7
    - Eclipseバージョン　　　　　　　　　　　　Eclipse 3.8 ~ 4.4


#参考
PyDev公式サイト　（上記の内容はここから引用）
http://www.pydev.org/download.html

最新版PyDevプラグイン
http://pydev.org/updates


<!--
#補足
素直に「Pleiades All in One 日本語ディストリビューション」のPython版をインストールする。
http://mergedoc.osdn.jp/
![image](https://qiita-image-store.s3.amazonaws.com/0/53676/2538047b-a38c-466a-2d81-450739e3eaed.png)

やってみたけど、ダウンロードしたZIPを展開したときに正常に展開できなかった。
-->
BeautifulSoup4 メモ


``` html
# list.html
<html>
  <head><title></title></head>
  <body>
    <a href="http://www.example.com/index.html" title="link title a">Example A</a>
    <a href="http://wwww.example.org/" title="link title b" target="_blank">Example B</a>
    <a href="http://www.example.net/" title="link title c">Example C</a>
  </body>
</html>
```




``` python
from bs4 import BeautifulSoup

soup = BeautifulSoup(open("list.html"))

link = soup.find("a")
print(link["title"])
# link title a
print(link["href"])
# http://www.example.com/index.html
print(link.string)
# Example A

link = soup.find("a", target="_blank")
print(link.string)
# Example B
print(link["title"])
# link title b
print(link["href"])
# http://wwww.example.org/

i = [ {"title": x["title"], "url": x["href"], "content": x.string } for x in soup.find_all("a")]
print(i)
# [{'content': 'Example A', 'url': 'http://www.example.com/index.html', 'title': 'link title a'}, {'content': 'Example B', 'url': 'http://wwww.example.org/', 'title': 'link title b'}, {'content': 'Example C', 'url': 'http://www.example.net/', 'title': 'link title c'}]
```
Macのローカルサーバー立ち上げ


## httpd.conf編集
```bash
$ sudo vi /etc/apache2/httpd.conf
```

## Apache起動
```bash
$ sudo apachectl start
```

## 自動起動設定
chkconfig的なやつです。

```bash
$ sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist
```

## 参考
- [Macでローカルサーバを立ち上げる方法](http://qiita.com/shuntaro_tamura/items/bdabcb77926dc92617b1#3-4-httpd%E8%87%AA%E5%8B%95%E8%B5%B7%E5%8B%95%E8%A8%AD%E5%AE%9A)
- [Mac OS Xのhttpd.confとDocumentRootの場所](http://qiita.com/utano320/items/d6dc09b9e9b533a212fc)
iPad 2 を最新の iOS にアップデート

## 地味に困っていた件。
検証用の iPad 2 の iOS が「7.0.4」なのに、なぜか『最新バージョンです！！！』と言い張ってて、アップデートができずにいました。

あちこち調べてて、なんとなく解決したのでメモ。
（なんだかんだで 2〜3時間かかったw）

## 解決方法
**【1】**
一旦、電源を落とす。

**【2】**
起動後、「設定」→「一般」→「ソフトウェアアップデート」で、「iOS 8.4.1」が選択できるようになるので、アップデート。

**【3】**
再起動後、アクティベート。（基本的に全部スキップで可）

**【4】**
「設定」→「一般」→「ソフトウェアアップデート」を見に行くと、今度は「iOS 9.5.3」が選択できるようになるので、アップデート。

**【5】**
再起動後、アクティベート。（基本的に全部スキップで可）
※必要な設定は後で行う。
無事、iOS 9.5.3 にアップデートできました！
iTerm2を閉じても別窓のEmacsを強制終了させない方法

いつもMacからEmacsを使うとき，`emacs &`って入力していた．
これだと，一作業終えてiTerm2のタブを閉じるとEmacsを起動していたタブを閉じてしまい，強制終了してしまうことが多々あったので…

# 環境
別窓でEmacsを使いたいので，次のような感じでEmacsをインストールしている．(OS X El capitan 10.11.6, Emacs 24.5.1)
`$ brew install emacs --with-cocoa`
`$ brew linkapps emacs`

# そもそもDockとかから起動するEmacs.appの動作がおかしい…
これで/ApplicationsにEmacs.appが入るのだが，そこから起動した場合，httpでのアクセスに失敗するようでpackage.elの更新とかうまく動作しない．

なので，僕はいつもEmacsを使うときにはiTerm2を起動して
`$ emacs &`
って入力をして使っている．
で，iTerm2でこのまま作業して，一作業終え余分なタブを消す…というときに，誤って`emacs &`してたタブまで閉じてしまい，Emacsが強制終了…ということが多々ある．
だからといって，`$ emacs -nw`みたいに，iTerm2上でEmacsを動かすのはすごく嫌だ．

# 対策
`$ open /Applications/Emacs.app`
とすると，別窓でEmacsを起動しつつ，起動したiTerm2のタブを閉じてもなんともない．
もちろんpackage.elの更新とかもきちんと動作する．
売れるサービスの導入方法


#はじめに
お金を本気で稼ぐためには高品質かつ効率よくサービスを作る必要がある。

##作り方

AARRR理論にのっとたサービスを作成する

- A アクイジション
    - ユーザー獲得
        - プレスリリース（アプり紹介サイト）
        - PR動画作成（youtube）
        - SNS告知（Unity雑談所、自分の投稿）
- A アクティベーション
    - サービスの面白さ、利用価値
        - **ここが今まで作成してきたゲーム部分(学生はここしか作らない)**
- R リテンション
    - 継続率、再訪問
        - ログインボーナス
- R リフェール
    - ユーザー紹介
        - SNSでスコアの投稿
- R リべニュー
    - 広告
        - AdMob
        - appCcloud
        - UnityAds

![c4107702-57d3-f98e-aa56-2111af89920f.png](https://qiita-image-store.s3.amazonaws.com/0/93934/d956d09d-a48c-86e8-30be-48fdbf55003d.png)

この作成フローにあったテンプレートを作成すると円滑に複数のゲームを作れると考える
（広告の配置や出すタイミングも固定する）
![スクリーンショット_083116_063520_PM.jpg](https://qiita-image-store.s3.amazonaws.com/0/93934/720e3818-2fe6-b0f8-ef2b-d75028178af3.jpeg)

一番最初に行うことはテンプレートを作成することからである。

###【懸念事項】
- データベースをどうやって用意するか？（firebase,,,,）
- UI素材の調達（使い回ししたいので独自で容易したい）
- 素材の管理をどう行うか
- Bitbucketで管理するか



###【参考URL】
[アプリマーケティング部](http://appmarketinglabo.net/)
[SEO 検索の重要性](http://qiita.com/Dvolition/private/a61eeb0d2d0d26f6f218)
【GAS】郵便局のサイトから郵便番号データをそのままスプレッドシートに取り込む

　これから時々GASについて投稿していこうと思います。GASの読み方ですが私は「ギャス」と呼ぶようにしています（「ガス」よりも格好いい響きではないかと）。

　さて、郵便局のサイトのなかにある、郵便番号データのダウンロードページです。
　http://www.post.japanpost.jp/zipcode/dl/kogaki-zip.html

![スクリーンショット 2016-08-31 17.53.37.png](https://qiita-image-store.s3.amazonaws.com/0/139134/1ee51365-dfaa-d506-3535-1ba8bbf3adcf.png)

　通常はここからファイルをドライブにダウンロードして開いてという流れになろうかと思いますが直接ここからスプレッドシートに引っ張ってこれないものかと思い、やってみました。

　全国一括は12万件超あり、さすがにGASでは読取りに5分くらいかかってしまいましたが、個々の都道府県ならわりとスムーズにできました。

　東京都を例にやってみました。

~~~js:コード.gs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();

function getPostData() {

  // zipファイル取得
  var url = "http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/13tokyo.zip";
  var zipblob = UrlFetchApp.fetch(url).getBlob();

  // 解凍
  var unzipblob = Utilities.unzip(zipblob);

  // データ取得
  var data = unzipblob[0].getDataAsString("Shift_JIS");

  // 行ごとに配列に格納
  var ary = data.split("\n");

  // 最後の空配列除去
  ary.pop();

  // 2次元配列に組み直し
  var ary2 = [];
  var ary3 = [];
  for (var i in ary) {
    ary2 = ary[i].split(",");
    ary3.push(ary2);
    ary2 = [];
  }

  // シートに反映
  sh.getRange(1,1,ary.length,15).setValues(ary3);

}
~~~

　実はUtilities.parseCsv()を使えばもっとシンプルにできます。

~~~js:コード.gs
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();

function getPostData() {

  // zipフィアル取得
  var url = "http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/13tokyo.zip";
  var zipblob = UrlFetchApp.fetch(url).getBlob();

  // 解凍
  var unzipblob = Utilities.unzip(zipblob);

  // データ取得
  var data = unzipblob[0].getDataAsString("Shift_JIS");

  // 2次元配列に転換
  var ary = Utilities.parseCsv(data);

  // シートに反映
  sh.getRange(1,1,ary.length,15).setValues(ary);

}
~~~

　取り込んだ結果です。3810行でした。

![スクリーンショット 2016-08-31 18.17.02.png](https://qiita-image-store.s3.amazonaws.com/0/139134/4f5bab65-ff79-5f86-40ee-3c92a1ca06d7.png)
HDFSのDataNodeで、ディスクの空きが多い方からデータを書き込む方法

HDFSにおける DataNode(以下DN) に対する分散書き込みを、DNのディスクボリューム間で釣り合いがとれるようにするよう設定することができる。

# 環境

- CDH 5.8.0
- Hadoop 2.6.0 ベース


# 概要

デフォルトではDNはラウンドロビンで新しいブロックレプリカをディスクボリュームに書き込む。
新しいレプリカの場所を決定するときにそれぞれのボリュームの空き容量を考慮してボリュームを選択するポリシーをDNに設定することができる。

設定できる内容は以下の通り。

- DNボリューム同士の空きディスク容量の差分の許容範囲(バイト)
- 新しいブロック割り当てが、より空きディスク容量の大きいボリュームに送られる割合(パーセント)


# プロパティの説明

以下、プロパティと設定に必要な変更の値についての一覧を示す。プロパティの説明については Cloudera Manager の説明文を引用した。

## DataNodeボリューム選択ポリシー

プロパティ: dfs.datanode.fsdataset.volume.choosing.policy
デフォルト値: org.apache.hadoop.hdfs.server.datanode.fsdataset.RoundRobinVolumeChoosingPolicy
設定値: org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy

新しいブロックを取得するボリュームを決定するための DataNode ポリシーです。

## 空き容量バランス維持ポリシーしきい値

プロパティ: dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold
デフォルト値: 10737418240
設定値: 10737418240

DataNode ボリューム選択ポリシーを［空き容量］に設定した場合にのみ使用されます。DataNode ボリュームの間で、ディスクの空き容量の差異として許容するバイト数を制御します。この値を超えると、ボリューム間のバランスが崩れたと判断されます。すべてのボリュームの空き容量が互いにこの範囲内の場合、ボリュームはバランスがとれていると判断され、ブロックの割り当ては正規のラウンドロビン方式で行われます。


## 空き容量バランス維持ポリシー設定

プロパティ: dfs.datanode.available-space-volume-choosing-policy.balanced-space-preference-fraction
デフォルト値: 0.75
設定値: 0.75

DataNode ボリューム選択ポリシーを［空き容量］に設定した場合にのみ使用されます。利用可能なディスクスペースが他のボリュームよりも多いボリュームに、新しいブロック割り当てからどのような割合で送信するかを制御します。この設定は、0.0～1.0 の範囲で指定する必要があります。ただし、利用可能なディスクスペースが少ないボリュームに対して、ブロックの割り当てを大きくする理由はないため、実際は 0.5～1.0 の範囲で指定します。


# 既に書き込まれたデータをディスク間でバランシングするには？

残念ながら、CDH5.8.0 時点ではディスク間バランシングの方法はない。
一度デコミッションしてデータを削除してからリコミッションするという形でバランシングするしかない。

アップストリームでは [HDFS-1312](https://issues.apache.org/jira/browse/HDFS-1312) でパッチが作成され、Hadoop 3.0.0 ターゲットでクローズしているため、CDH にバックポートされる日も遠くはないだろう。

[2016/10/20追記]
CDH 5.8.2 でディスク間バランシングがバックポートされました。詳しくは下記をご覧ください。
http://blog.cloudera.com/blog/2016/10/how-to-use-the-new-hdfs-intra-datanode-disk-balancer-in-apache-hadoop/

# 参考

Configuring Storage Balancing for DataNodes
http://www.cloudera.com/documentation/enterprise/latest/topics/admin_dn_storage_balancing.html
[Android] リサイズ後のImageのSizeを取得

#ImageViewの実際のサイズを取得したい
Viewを生成する時は何かとViewSizeを取得したい場面が多い。
AndroidではImageViewやImageButtonをscaleTypeで定義することが多いが、リサイズ後のImageSizeを知るメソッドは用意されていない。(多分)

以下のメソッドをUtilityクラスとかで定義しておけば簡単に取得できる。

```java:Utility.java
public static final Point getBitmapSizeFromImageLayer(ImageButton imageLayer) {
        final int actualHeight, actualWidth;
        final int imageLayerHeight = imageLayer.getHeight(), imageLayerWidth = imageLayer.getWidth();
        final int bitmapHeight = imageLayer.getDrawable().getIntrinsicHeight(), bitmapWidth = imageLayer.getDrawable().getIntrinsicWidth();
        if (imageLayerHeight * bitmapWidth <= imageLayerWidth * bitmapHeight) {
            actualWidth = bitmapWidth * imageLayerHeight / bitmapHeight;
            actualHeight = imageLayerHeight;
        } else {
            actualHeight = bitmapHeight * imageLayerWidth / bitmapWidth;
            actualWidth = imageLayerWidth;
        }
        return new Point(actualWidth, actualHeight);
    }


public static final Point getBitmapSizeFromDynamicImageLayer(ImageButton imageLayer) {
        final int actualHeight, actualWidth;
        final int imageLayerHeight = imageLayer.getLayoutParams().height, imageLayerWidth = imageLayer.getLayoutParams().width;
        final int bitmapHeight = imageLayer.getDrawable().getIntrinsicHeight(), bitmapWidth = imageLayer.getDrawable().getIntrinsicWidth();
        if (imageLayerHeight * bitmapWidth <= imageLayerWidth * bitmapHeight) {
            actualWidth = bitmapWidth * imageLayerHeight / bitmapHeight;
            actualHeight = imageLayerHeight;
        } else {
            actualHeight = bitmapHeight * imageLayerWidth / bitmapWidth;
            actualWidth = imageLayerWidth;
        }
        return new Point(actualWidth, actualHeight);
    }
```

このメソッドはImageButtonオブジェクトを引数で渡すことによってリサイズ後(実際に表示されている)のBitmap画像のサイズを`Point(横幅, 縦幅)`で返してくれる。ImageViewの大きさが欲しい場合も引数部分を`ImageButton -> ImageView`にするだけで対応できる。

上のメソッドはxml上で定義されているImageButton、
下のメソッドはプログラム上で動的(sizeをlayoutParamsで定義しているオブジェクト)に生成したImageButton
に対応している。

###締め
調べても全然出てこなかった。自分はタッチ判定領域(Region)とか設定する時に利用していますが皆どうやってるんでしょうか。。
変な所があったり、この様なメソッドが既にあったりしたらご教授願います。
VRと人工知能


CEDEC2016の[人工知能の未来へ　－全脳アーキテクチャ、ディープラーニングを用いた人工生命、ゲームAI －](http://cedec.cesa.or.jp/2016/session/ENG/14380.html)を聴いて、講演の最後に説明のあったVRと人工知能の関係が興味深かったので色々調べてみました。

##VRの入力インターフェース

VRの入力方法の例として、以下の３点があげられます。

- 音声：聴覚
- ジェスチャー：触覚
- 視点：視覚

この３つの入力方法は、人間の聴覚、触覚、視覚といった五感に大きく関わる動作です。こういった知覚によって入力を行う分、より自然な形の入力を行うことができます。

こういった入力方法は、 **ナチュラルユーザーインターフェース** と呼ばれ、注目が高まっています。

###ナチュラルユーザーインターフェースとは？
NUI(Natural User Interface )
人間にとってより自然な・直感的な動作で操作可能な仕組みや方法のこと。
>引用　[BINARY](http://www.sophia-it.com/content/NUI)

とりあえず、VRにおけるNUIは、「コントローラーほどの気軽さはなく、精度の向上に期待する」とのことでした。

もちろん、人間にとって「自然」で「直感的」とは、機械にとっては自然でも直感的でもありません。
人間の常識や簡単な知識をシステムに学習させる必要がでてきます。
>例：何をしゃべっているのかを認識する、体の位置を認識する、何を見ているのかを認識する。

人工知能の研究自体、「絶賛研究中！」なので今は技術に合わせたゲームデザインにとどまっているようです。

精度もそうですが、入力する人がどんな人物（喋り方、年齢、服装）等を人工知能が見極めて入力フォームが口調を変えてくる、といった人間がより人間らしい対応から入力ができても面白いなーと感じました。（こういう所も含めてNUIなのかは謎）


##VRのキャラクター

従来のゲームより、VRに出てくるキャラクターの「そこにいる」感は圧倒的に高いです。
ゲームだとわかっていても、キャラクターに微笑まれると微笑んでしまうし、手を振られたら振り返したりする人もいるようです。
こういったキャラクターと人間との関わりを **ヒューマンエージェントインタラクション** と呼びます。

###ヒューマンエージェントインタラクションとは？
HAI(Human-Agent Interaction)
人間、擬似エージェント、ロボットが接する状況で起こる問題を解決する研究分野。
>引用　[HAIシンポジウム2015](http://hai-conference.net/symp2015/whatshai.php)

人間ーロボットだけでなく、人間ー人間の関係をロボットが介するとどうなるか、も含めた研究分野らしいです。（マツコロイド思い出した）

こっちはNUIの時と違って、「キャラクターがより人間に近いのが正解」とは限らないように思います。むしろ、相手がロボットだから、美少女キャラクターだから、人間だから、でユーザーの対応が変わってきそうですね。
より、コンテンツに合わせたキャラクター作りが必須に思えました。

##VRのコンテンツ

人の知覚、体感に大きく関わってくるVRだからこそ
コンテンツの感じ方も人によって極端に違います。

>講演であげられた例：ホラーゲームの場合
体験者A「めっちゃ恐かった」
体験者B「ぜんぜん恐くなかった」
→ユーザーの心拍数を元に恐がらせるタイミングを制御して、人に合わせた恐怖体験を提供するといい

また面白いことに、実際に起きていないことですら体験してる感覚に陥る場合もあります。

サマーレッスンで話題になった「女の子と自分が至近距離になった時に、ホストは女の子の息づかいを感じ、普通の大学生は息づかいを感じなかった」ことがそれにあたります。

こういった現象を **クロスモーダル現象** といいます。

###クロスモーダル現象とは？
仮想体験によって実際には怒っていない感覚を得る現象。
>引用　[VR で脳が完全に騙される『クロスモーダル現象』とは?](http://vr.cravelweb.com/column/crossmodal-perception)

VRコンテンツをよりリアルにするには、コンテンツの対象となるユーザーが体験したことのあるものをどれだけ盛り込めるかも鍵となりそうです。

単純にVRの中でキャラクターと遊ぶだけでは、ユーザーによっては従来のゲームと変わらないものとなってしまいます。
例えば、コーヒーを持ったり（香り、熱を錯覚させる）、砂埃をまいたり（におい、不快感を錯覚させる）、よりユーザーの身近にある五感を刺激するものを少しずつ配置することで、リアルに近いコンテンツを提供できるのではないかと思いました。

ただ、記憶がなければリアルに感じないかというと全ての人がそういうわけではないようです。妄想力で補えるパターンもあるようなので、意外にVRは女性向けなのかもしれません。
Python で boto3 を使う際に AWS の profile_name ベースで認証する方法

## profile_name ベースで認証

```
import boto3
from boto3.session import Session
session = Session(profile_name=<AWS_PROFILE_NAME>)
swf = session.client('swf')
```

## profile_name ベースではない認証(Environment variables などで)

```
import boto3
swf = boto3.client('swf')
```
[Rails] [RDB] キー・複合キーをきちんと利用する

## 環境
Rails 5.0.0.1, MySQL 5.6

## 概要
Railsでは主キーは基本的にidをサロゲートキーとして用いる。

そのことの良し悪しはここでは論じないが、自然キーや複合キーがあるのであれば、それを意識し、正しく扱うことが重要であることは変わらない。

といっても基本的にはunique indexはるだけではある、それについてのメモ。

## 本編

ユーザが本質的に1日1回しかできない投稿がある、という例で考える。
users と daily_posts というテーブルがある。
usersのテーブル定義は省略し、daily_postsのmigrationファイルを正しく作る。

まず複合キーのことを考えずに、daily_postsのmigrationを作るとこんな感じになる。(作っただけでまだ `db:migrate` していない状態。)

```rb
def change
  create_table :daily_posts do |t|
    t.references :user, foreign_key: true, null: false
    t.date :date, null: false
    t.string :title, null: false

    t.timestamps
  end
end
```

### 1. キーを認識する
「本質的にuserが1日1回しかpostできない」ので、user_id + date は複合キーである。

これに対して、忘れずにunique indexをはるのが重要である。

注意: indexは、リレーショナルモデルに直接関係ない。一方、キーや複合キーはリレーショナルモデル上の重要な概念であり、それに「unique制約をつける」のが重要である。
unique制約のために、実質的にindexが必要であるから、unique indexをはる。

(ここまで書いて思ったが、unique制約は `a + b` だけどindexは `a -> b -> c` ではりたいときに、railsでどうできるのかは知らない、、)

### 2. (複合キーの場合) unique indexの順序を決める

理論的には `user_id -> date` でも `date -> user_id` でもどちらでも良い。使えそうな順序にする。
今回は `user_id -> date` にする。

### 3. キーに対してunique indexをはる
migrationに、 `add_index :table_name, [:key1, :key2, ...], unique: true` と書くことで実現できる。

```rb
def change
  create_table :daily_posts do |t|
    t.references :user, foreign_key: true, null: false
    t.date :date, null: false
    t.string :title, null: false

    t.timestamps
  end

  add_index :daily_posts, [:user_id, :date], unique: true
end
```

### 4. 無駄なindexが残っていないか注意する

複合のunique indexをはると、元あったindexが無駄になることがある。

上の例では、

- `t.references` は、外部キーをはりながらindexをはってくれる機能。
- `t.references :user` により、 `user_id` に対しindexがはられている。
- 今 `user_id -> date` のindexをはった。したがって `user_id` だけのindexは無駄である。

よって、 `t.references`をやめて、単に外部キーをはるだけにする。
すなわち、普通にカラムを定義したあとに `add_foreign_key`をするように変更する。

```rb
def change
  create_table :daily_posts do |t|
    t.integer :user_id, null: false
    t.date :date, null: false
    t.string :title, null: false

    t.timestamps

  end

  add_index :daily_posts, [:user_id, :date], unique: true
  add_foreign_key :daily_posts, :users
end
```

追記: 以下のように、t.referencesにindex:falseのオプションを追加しても問題ありません。こちらのほうが簡単だったかもしれません。

```rb
def change
  create_table :daily_posts do |t|
    t.references :user, foreign_key: true, index: false, null: false
    t.date :date, null: false
    t.string :title, null: false

    t.timestamps
  end

  add_index :daily_posts, [:user_id, :date], unique: true
end
```

## まとめ
テーブル設計=>migration作る=>unique indexはる=>不要なindexが生成されないか注意。

unique制約はテーブル設計のうちなので、migration作った段階で必ずはるようにすると良いと思う。
ラジコン無線をラズパイから送出する方法

この記事ではraspberry pi 3とDJIのPhantom2を使用しています

# なぜラジコン無線を送出することになったか
まずはじめになぜこのようなことをすることになったかについて少し掲載させていただきたいと思います。
大学で開催されたハッカソンに出展するため[DJI Phantom2](http://www.dji.com/jp/product/phantom-2-vision)を[Leap Motion](https://www.leapmotion.com/?lang=jp)で操作しようとしたためです。

# 基本的な構成
大まかな構造については以下のとおりになります。![q.jpg](https://qiita-image-store.s3.amazonaws.com/0/113969/9d7f1528-ffc8-34ae-3b2d-300aa7f7d676.jpeg)
ラズパイ側のプログラミングにはNode-REDを使用していますが今回はラズパイから送出する部分にのみフォーカスします。

# ラズパイから送出される信号
ラズパイから送出される信号はPWMと呼ばれるもので、そのままだと信号は以下の様になっている。
![image](https://qiita-image-store.s3.amazonaws.com/0/113969/55c85a6c-8a97-119d-be64-88b17fde0e1e.png)
https://hekilledmywire.wordpress.com/2011/08/03/introduction-to-pwm-part-7/

この信号はONにしている時間の割合を調節している。
この信号を凹凸のない平均的なものすることで任意の電圧を作り出すことが可能になる。
このようなことを平滑化という。

# PWMの平滑化
この信号を平滑化する方法はいくつかあるものの最も安価でシンプルな方法として自作のアナログローパスフィルタを制作してみた。

![プレゼンテーション1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113969/f828e0fb-7dea-cb79-48d7-649691a2af8d.jpeg)

ちょっと配線が汚いのでFritzingで書いてみました。

![Untitled Sketch_ブレッドボード.jpg](https://qiita-image-store.s3.amazonaws.com/0/113969/14b0a6af-6a1d-8710-642c-e0700d009d34.jpeg)

信号線をラズパイとつなぐとこんな感じ

![Untitled Sketch_ブレッドボード_with_wire.jpg](https://qiita-image-store.s3.amazonaws.com/0/113969/b109e9e6-4e76-2ac5-deda-8215daf18b72.jpeg)

(なんだか汚い設計ですね…うまくなりたいものです…)

さて、この回路ではPWMを平滑化しているわけなのですが。
最も基本となる回路はこちら

![image](https://qiita-image-store.s3.amazonaws.com/0/113969/abe9adda-3b04-6280-817b-834c1f69df4c.png)
http://www.ys-labo.com/pic/pic%20chips/pic%20chips%20contets/061230%20DA.html

一つの信号に対しこれをすべて行うわけですが、
コントローラーは左右のスティックがそれぞれ上下左右に傾くため4ch、つまり

- 左スティック
    - 左右
    - 上下
- 右スティック
    - 左右
    - 上下

があれば足りるはずですね。
私もそう考えて4ch分だけ作ったのですがどうにも制御には

- 左スティック
    - 左
    - 右
    - 上
    - 下
- 右スティック
    - 左
    - 右
    - 上
    - 下

といった具合に8ch必要になりました。
(勉強不足で理由はわかっていません)

そしてオペアンプ(LM358)の内部は以下のようになっているため

![image](https://qiita-image-store.s3.amazonaws.com/0/113969/8c2a8f6b-0617-2753-dc4e-9edee42180e9.png)
http://blog.nearfuturelaboratory.com/2011/07/28/lm358-op-amp-issues/

一つのオペアンプで2つの信号を処理できることになります。
その上で計算すると8chのためには4つのLM358が必要になりますね。

こうして先程のブレッドボードを設計しました。

# 平滑化した信号をラジコン無線に変換する
この点を本当はラズパイから直接行いたかったのですが時間と技術の問題で断念しました。
今回はPhantomのコントローラーから基板の部分を引っこ抜いてレバーの操作を入力します。
こうすることでレバーと同じような電圧になるよう調節するだけで簡単にラジコンの無線を送信できるわけですね。
(姑息な解決方法ですね…)
![プレゼンテーション1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113969/f5a027cf-9f61-a73e-52a9-188c95bdf184.jpeg)

この基板の左から2,3番目がレバーに接続されていたので今回生成した信号をそこに流し込みます。
ちなみにブレッドボードと基板を接続しているコネクタは自作です。(楽しかった)

以上のながれでラズパイからラジコンの無線をハックすることに成功しました！(してないしてない)

実際にはラズパイ側のPWM信号の調節などで時間はかかりましたが、その調節は一度だけ行えば良いのでそのあとはPhantomどころか2.4GHz帯のラジコンならなんでも信号を飛ばせますね。
ちなみに信号はLeapMotionのデータをWebSocket通信で受信し処理したものを流し込んでいます。
Phantom2を手で制御するのはすごく興奮しましたが懐が寒いです。

最後まで読んでいただきありがとうございました。
MySQLでUTF8からUTF8mb4エンコード変更時に出るエラー対策

小メモ。
Symfony2.7系、Doctrine、MySQL5.6、な環境。


# エラー内容

```
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes  
```

# 発生条件

* DBとかテーブルとかカラムがutf8なやつを、utf8mb4に変更するときに発生


## 打ったSQL

```sql
ALTER TABLE fooooooo default character set utf8mb4;
ALTER TABLE fooooooo CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

# 原因

* ほぼエラー通り。
* ユニーク制約付きvarcharは767byteまでしかいけない。
    * 参考： [Mysqlでユニーク制約をつけたvarcharは767byteまでしか入らない話](http://qiita.com/ritukiii/items/0e07408670d6e2e549fb)

## Entityとか

* Doctrineを使ってる。
* UTF8は3バイト、ソースコード上はMAX255文字。
* 255文字*3バイトで765Byte。ユニーク制約付きvarcharは767byteまでなので、セフセフ。

```php

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, unique=true, options={"comment" = "名前"})
     * @Assert\NotBlank(message="おまえの名を入力して下さい。")
     */
    protected $name;

```


# 修正

* そもそも名前にlengthが255とかいらんだろということで、length="30"に変更。
    * 問題無し。


```php

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=30, unique=true, options={"comment" = "名前"})
     * @Assert\NotBlank(message="おまえの名を入力して下さい。")
     */
    protected $name;
```


やったね。
Rails5へUPG後コンソールやテストは問題ないが開発環境サーバへアクセス出来ない現象への対処


Rails 4.2 から Rails 5 へのアップグレードを行った際、

* RSpec のテストは全てパスする
* Rails console も正しく起動する
* **Rails server へのアクセスがログすら出ずに落ちる**

という現象に遭遇しました。

ログが出ないで落ちるという、かなり苦しい状況でした。

# 対処
結論から言うと、`web-console` のアップデートで解決できました。

Rails のバージョンを上げるために依存関係上最低限必要なもののみをアップデートしていたため、このような現象に遭遇しました。

# 救いの手
以下のブログに助けられました！超感謝！

* [Upgrading to Rails 5 Beta - The Hard Way](https://blog.heroku.com/rails-5-beta-upgrade#rails-server)
例外、エラー、異常、そして


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「例外」「エラー」「異常」あたりの言葉が、言語仕様や設計の中で人によって微妙にずれた使い方されてるから、 「Expected だが Accept されないケース」を表す別の言葉が欲しい。</p>&mdash; Jxck (@Jxck_) <a href="https://twitter.com/Jxck_/status/770899329301159936">2016年8月31日</a>
<p lang="ja" dir="ltr"><a href="https://twitter.com/Jxck_">@Jxck_</a> 本来こう分類されて、<br>1. Expected/Accepted<br>2. Expected/UnAccepted<br>3. UnExpected<br>2, 3 をどう呼ぶかあたりで、例外, エラー, 異常などの言葉が入り乱れてて、それが広義の例外処理が誤解される原因だと思ってる</p>&mdash; Jxck (@Jxck_) <a href="https://twitter.com/Jxck_/status/770901468383580160">2016年8月31日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

|         | Expected and Accepted | Expected but Unaccepted | Unexpected |
|---------|-----------------------|-------------------------|------------|
| Ruby    | (正常系)               | 例外　(`StandardError`)   | 例外 (`Exception`) |
| Java    | (正常系)               | 例外(Exception)         | エラー (Error)      |
| Go      | (正常系)               | `error`                   | `panic`  |
| Python  | (正常系)               | 例外 (`XxxError`)       | 例外(その他) |
| JIS X0014 | (正常系)             | 障害(fault) [^1]                   | 故障(failure) [^2]       |

[^1]: 正確には、機能の停止や縮退を引き起こしうる異常な状態。障害を正しく処理できれば、理想的には故障には至らない。
[^2]: 正確には、障害などが原因となって機能を喪失すること

# Help Wanted
PHPとかElixirとか他の言語のケースを知りたいので誰か教えてください。
GitHub でチートシートに載っていない emoji を使う

GitHub でも、各種チャットサービスでも、すっかり市民権を得た絵文字。感情豊かに物事を伝えるのにとても役立っています。

とはいえ、サービスによって対応している絵文字の種類が異なっていたりする場合があり、使えないものもいくつか存在しています。

GitHub も例外ではなく、以下の表にないものは `:emoji-code:` の形では入力できません。
http://www.webpagefx.com/tools/emoji-cheat-sheet/

その代表的なもののひとつが 🦃 で、これを使おうとした時に、このサポートの差に気がついたわけです。Slack では `:turkey:` で入力することのできる絵文字ですが、GitHub ではまだサポートされていません。

ですが、あくまで使おうとしているのは絵文字です。絵文字は Unicode での標準化も進んでいるため、文字ごとに個別のコードポイントを持っているはず。すなわち普段入力している他の文字と大きな差はないはずです。

と、調べていたところ、以下のサイトを見つけました。
http://emojipedia.org/

`turkey` を検索してみましょう。
すると、以下のページが見つかります。
http://emojipedia.org/turkey/

![スクリーンショット 2016-08-31 17.50.12.png](https://qiita-image-store.s3.amazonaws.com/0/47993/7b844733-b365-0449-4206-5079853c8833.png)

なんと、ページ内に `Copy` ボタンが用意されているではないですか！
早速押してみます。

GitHub へ移動して、`Ctrl+V` などでペーストしてみましょう。

![スクリーンショット 2016-08-31 17.53.08.png](https://qiita-image-store.s3.amazonaws.com/0/47993/b3dafdf3-6d3c-f5cd-7712-c8653f99e14a.png)

入力できてしまいました！

![スクリーンショット 2016-08-31 17.53.47.png](https://qiita-image-store.s3.amazonaws.com/0/47993/d7521720-22ee-5efa-d33f-2ed499d7faad.png)

プレビューでも問題ないようです。

と、こんな具合に一部の絵文字がサポートされていないサービスでも、emojipedia のようなサイトを使用することで、簡単に絵文字の入力ができるようです。
ステキな emoji ライフを！ 🎉
【メモ】ExcelをPDF化したときに、改行位置に空白スペースのようなの四角が表示されるのを解消する

```vba:vba
Sub Replace()

On Error GoTo ERR

    Dim OpenFileName As String
    OpenFileName = Application.GetOpenFilename("Microsoft Excelブック,*.xls*")
    If OpenFileName <> "False" Then
        Workbooks.Open OpenFileName
    End If
    
    Dim i As Integer
    Dim sheetCnt As Integer

    sheetCnt = ActiveWorkbook.Sheets.Count
    
    i = 1
    
    Do While i < sheetCnt
    
        Worksheets(i).Cells.Replace What:=vbCrLf, Replacement:=vbLf, LookAt:=xlPart, ReplaceFormat:=False
    
        i = i + 1
    Loop
    
GoTo OWARI

ERR:
MsgBox ("エラーが発生しました。エラーの原因がわからない場合はお手数ですが、作成者までご連絡ください。")
Exit Sub

OWARI:
MsgBox ("処理が完了しました。")
    
    
End Sub
```
【NAT64】[Jool] Linuxだけで実装するNAT64(運用編)

# 1. はじめに
去る2016.08.20に開催されました[iOSDC(iOS Developers conference)](https://iosdc.jp/2016/)にて、
このカンファレンスで使えるWi-Fiネットワークの構築に[CONBU](https://conbu.net/)メンバーとして参画し、
ありがたくもNAT64の実装に携わってきました。
聞くところによりますと、([省略:前々回記事をご覧ください](http://qiita.com/onifinger/items/618541416efa014daefc))

概要編ではJoolというNAT64コンポーネントを採用したと述べました。
設計・構築編ではJoolを起動させるところまで述べました。
本記事では、動作検証しつつ取り入れた運用系のノウハウを書き連ねたいと思います。

Jool: https://jool.mx/en/index.html

なお、iOSとIPv6とのトピックはiOSDC関連まとめの中では
結構なヒット作となっておられます、以下もご覧いただけるとより楽しめるかと思います。
 # IPv6に関するプログラミングアンチパターンが面白いんじゃよ。

[■IPv6 Readyって何?NAT64/DNS64徹底解説](http://togetter.com/li/1014169)
[■上記の発表資料はこちら](http://www.slideshare.net/smadako/ipv6-ready-nat64dns64-iosdc-b)

# 2. 運用結果サマリ
結論から先に書きますが、個人的にはJoolによるNAT64ネットワークはある程度実用に耐えうるものだったとみています。
500人以上の来場者で、最大200クライアントほどの接続があり、最大6,000セッションくらいの同時接続があっても無事6 to 4のインターネット接続を提供することができていたようです。

なお、いくつかのアプリケーションがうまく動かなかったというのは結果としてありました。

この辺のお話は、[こちらの記事](https://blog.nic.ad.jp/blog/intro2_nat64_dns64/)でもご確認いただけると思います。

# 3. Joolの起動

```bash
$ sudo modprobe jool pool6=64:ff9b/96 pool4=$YOUR_IPV4_ADDR
```

前回記した通り上記のコマンドでJoolが起動します。
ただし、NATに利用するポートにwell-known-portが含まれるなど
結構攻め気味の起動の仕方をするので、イベントにおいては以下のコマンドで調整しました。
 # $YOUR_IPV4_ADDRを192.168.0.100と仮決めして記載します。

```bash
$ sudo jool --pool4 --remove 192.168.0.100 1-9999
$ sudo jool --handle-rst-during-fin-rcv true
$ sudo jool --maximum-simultanous-opens 5000
$ sudo jool --logging-session true
```

《解説》
1行目 - 1-9999portをNAT処理時の割り当てportから除外(TCP/UDP/ICMP全てに適用される)
2行目 - RSTが飛んできたときに残存セッションを捨てる設定
3行目 - 同時にオープン出来るセッション数を引き上げる(default 128)
4行目 - sessionログをsyslogに吐く

また、OS側でサチらないように、kernel parameterを1ついじりました。

```bash
$ sudo sysctl -w net.core.somaxconn = 1024 
```

# 4. Joolの状態確認
起動しましたら、ユーザスペースアプリのコマンド群を駆使して稼働状況を確認できます。
以下に列記しますが、[コマンドリファレンスのようなもの](https://jool.mx/en/documentation.html#userspace-application-arguments)が公式にもバッチリございます。

+ poolの一覧確認
    
    ```bash
    $ sudo jool --pool4 --display
    ```

+ TCP/UDP/ICMP　現在のセッション数確認
    
    ```bash
    $ jool -c -s
    ```

+ セッションテーブルの確認
    
    ```bash
    $ sudo jool --session
    ```

+ poolのflush(セッションテーブルのflush)
    
    ```bash
    $ sudo jool --pool4 --flush 192.168.0.100
    ```

+ poolアドレスの追加
    
    ```bash
    $ sudo jool --pool4 --add 192.168.0.100 37268-65535
    ```
+ Joolの停止

    ```bash
    $ sudo modprobe -r jool
    ```

# 5. ついでにZabbix_Senderでセッション数監視
zabbix_agentのzabbix_senderコマンドを用いて、グラフでのセッション監視もやってみました。
ブツは[こちら](https://github.com/onifinger/jool_session_monitor)ですが、詳しいやり方は別の記事にしたいと思います。

# 6. あとがき
技術的に知ってはいても、一般の皆さまにお使いいただくネットワークとしてIPv6移行系の実装はなかなか自分の手ではやる機会がないので非常によい経験になりました。

そういうproduction環境に近しいエンジニアリングを求めてやまない方は、
ぜひ[CONBU](http://conbu.net/)の活動をマークしていていただけると幸いです。
[twitter: @conbu_net](https://twitter.com/conbu_net)
[■CONBUの正体](http://www.atmarkit.co.jp/ait/articles/1603/18/news033.html)
 # 筆者のメンバー応募・参画の契機となった記事です。