OmniAICreator/Qiita-1.07M huggingface dataset:
Tornadoのコルーチンを使ったジョブキュー実装例


Tornadoのコルーチンでジョブ待ち行列を作った時のメモです。

WorkerQueueのputメソッドでジョブ(関数と引数)をキューに入れます。現在実行中のジョブが終了次第、キューにあるジョブが古いものから順に１つずつ実行されます。

Tornadoのバージョン4.2で実装されたQueueを使用しています。TornadoのキューはPython標準ライブラリの同期キュー(queue.Queue)に似ていますが、putやgetがtornado.concurrent.Futureを返す点が異なります。




```py3:filename
from concurrent.futures import ProcessPoolExecutor
import time

from tornado import ioloop, gen, process
from tornado.queues import Queue


class WorkerQueue(object):
    def __init__(self):
        self.queue = Queue()
        self.current_worker_id = None
        self.current_worker = None
        self.queued_ids = []
        self._dispatcher()

    def put(self, id_, func, args):
        worker = Worker(func, args)
        self.queued_ids.append(id_)
        self.queue.put_nowait((id_, worker))
        print("Put: {}".format(id_))

    def status(self, id_):
        if id_ in self.queued_ids:
            return "Queued"
        elif id_ == self.current_worker_id:
            return "Running"
        else:
            return "Ready"

    @gen.coroutine
    def _dispatcher(self):
        while 1:
            id_, worker = yield self.queue.get()
            self.queued_ids.remove(id_)
            self.current_worker_id = id_
            self.current_worker = worker
            print("Start: {}".format(id_))
            res = yield self.current_worker.execute()
            self.current_worker_id = None
            self.current_worker = None
            print("{} is {}.".format(id_, res))


class Worker(object):
    def __init__(self, func, args):
        self.func = func
        self.args = args

    @gen.coroutine
    def execute(self):
        with ProcessPoolExecutor(process.cpu_count()) as exec_:
            res = yield exec_.submit(self.func, *self.args)
        return res


def job(sec):
    time.sleep(sec)
    return "done"


@gen.coroutine
def run():
    q = WorkerQueue()
    q.put("Job1", job, (2,))
    q.put("Job2", job, (2,))
    print("Job1 <{}>".format(q.status("Job1")))
    print("Job2 <{}>".format(q.status("Job2")))
    yield gen.sleep(1)
    print("Job1 <{}>".format(q.status("Job1")))
    print("Job2 <{}>".format(q.status("Job2")))
    yield gen.sleep(2)
    print("Job1 <{}>".format(q.status("Job1")))
    print("Job2 <{}>".format(q.status("Job2")))
    yield gen.sleep(2)
    print("Job1 <{}>".format(q.status("Job1")))
    print("Job2 <{}>".format(q.status("Job2")))


if __name__ == "__main__":
    ioloop.IOLoop.current().run_sync(run)
```

実行結果

```
Put: Job1
Put: Job2
Job1 <Queued>
Job2 <Queued>
Start: Job1
Job1 <Running>
Job2 <Queued>
Job1 is done
Start: Job2
Job1 <Ready>
Job2 <Running>
Job2 is done
Job1 <Ready>
Job2 <Ready>
```

(2015.11.7追記)
大容量データを扱う際にはメモリ使用量が問題になってくるので、キューの長さを限定してproducerを待たせるなどの工夫が必要です。
Webページのページングの時に必要になる超簡単なアルゴリズム

Webページ制作に欠かせないであろうページング処理をするときに役立つアルゴリズムを2つ紹介したいと思います。なおページナンバーは1ページから始まるものとする。


##ページングをするためのアルゴリズム

```
p:ページナンバー
m:1ページに表示したい項目数

問:sql文を作成したい=>SQLのl:Limitとo:Offsetを求める。また、初期値としてそれぞれl=M,o=0とする。

アルゴリズム:
l=m
o=(p-1)*l
```

これで、ページングを実装するために必要なLimitとOffsetの値がもとめられた。

##ページングの最後を判定するアルゴリズム

```
n:全項目数
p:ページナンバー
m:1ページに表示したい項目数

問:そのページが最後のページか判定したい。
例:例えば、最後のページでは｢次へ｣などのインジケータを消したい。

アルゴリズム:
if n-m*p<=0 then
  return true
else
  return false

```
unity > 選択中を示すものを作る > Toggleの使用

```txt:動作確認
Unity 5.1.2-f1 on MacOS X 10.8.5
```

こういうのを作りたい。
黄色は選択中ということを示している。

![Main_unity_-_150905-PageButton_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/2bccb739-1413-94ae-0c8d-7817d0b09268.jpeg)

## 手順

UI > Toggleを追加

Toggle > Background > Checkmarkを選択し、SourceImageをBackgroundにする
同じくColorを黄色にする

![Main_unity_-_150905-PageButton_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/e232b2e2-46ca-bedb-08e3-d1b7804649a7.jpeg)

ToggleのWidth,Heightを(45, 45)にする
BackgroundのWidth,Heightを(40, 40)にする
CheckmarkのWidth, Heightを(35, 35)にする
こうすることで、以下のようになる。

![Main_unity_-_150905-PageButton_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/b56184df-2ada-4815-b8a2-1249702e386d.jpeg)

LabelのTextを P1 とする
Labelの位置を変更して以下のようにして完成

![Main_unity_-_150905-PageButton_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/31b54960-60ce-4ec5-801b-6eeb6f04a9f0.jpeg)

##用途

以下のようにして、現在選択しているものが分かるようにする。

![Main_unity_-_150905-PageButton_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/9e296942-967d-bcac-4abd-bea73cd9bee8.jpeg)


以下のページにあるように、トグルグループを使えば一つだけ選択することができる。
http://dkoubou2.chips.jp/dkoubouz/2015/04/unity_togglegroup_tutorial.html

トグルグループにしたら全選択解除ができない。それはそれで正しいのかもしれない。
awk スニペット

コマンドラインでちょっとした集計をする場合など、てばやく作れる言語があると助かります。そんな言語が　awk です。

ＯＳによって微妙に実装が異なっているので、検索して出てくる便利な関数が使えない場合もあるので注意。

awk は基本的に標準入力に対して、パターンを定義し、それにマッチするレコードに対し　アクション　を行うという流れです。



でも、マージなど、入力を差し込みたい場合などは　以下のような作りで実現できます。

```lang:awk
BEGIN{
 getline
 for ( i=0; i< 1440 ; i++){
  time=mktime(i);
  if ($1 == time){
   print $0
  }else{
   print time
  }
 }
}
function mktime(i){
 h=int(i/60);
 m=i-(h*60);
 hh=substr(h+100,2,2);
 mm=substr(m+100,2,2);
 time=hh":"mm;
 return time;
}
```

外部からパラメータを渡したい場合は　こんな感じ


```lang:awk
$ argv="hoge";awk -v inparm="${argv}" `BEGIN{print inparm}`
```


これからも（主に自分の備忘録として）追加予定
3sで、公開用のイメージストアを作ろうと思ったとき、公開方法で詰まったのでメモ

イメージストアをawsのs3を使って作ろうと思ったとき、方法がわからなくって、ググりまくった。
すると、awsのあるページにたどり着いたので、ここに方法をメモをしておく


## 方法
バケットのプロパティ - 「アクセス許可」のタブの中から、「セキュリティポリシーを作成」
を選択する。

編集画面が出てくるので、その中に、

```
{
  "Version":"2012-10-17",
  "Statement": [{
    "Sid": "Allow Public Access to All Objects",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::example.com/*"
  }
 ]
}
```

をコピペして、保存する。
「Resource」の「example.com」は、適宜作成したバケット名に書き換えてほしい。

これで、パケット名を使って、公開用のストアができた。


# 参考サイト
http://docs.aws.amazon.com/ja_jp/gettingstarted/latest/swh/getting-started-configure-bucket.html
OpenSSL バージョン1.0.2d をソースからインストール

今回の投稿では、勉強用に利用しているLinuxのopensslが脆弱性のあるバージョン1.0.1f<sub>[1](#1)</sub>だったことから、最新バージョンに変更したので、その手順を書き留めておきます。

# 1. OpenSSL バージョン1.0.2dのインストール
最新バージョンのOpenSSLを[公式サイト](http://www.openssl.org/)<sub>[2](#2)</sub>からダウンロードしてインストールしていきます。

```text:opensslのインストール
# openssl version
OpenSSL 1.0.1f 6 Jan 2014    // 脆弱性のあるバージョン
# cd /usr/local/src
# wget http://www.openssl.org/source/openssl-1.0.2d.tar.gz
# tar xzvf openssl-1.0.2d.tar.gz
# cd openssl-1.0.2d
# ./config shared zlib
# make
# porg -lD "make install"
# /usr/local/ssl/bin/openssl version
OpenSSL 1.0.2d 9 Jul 2015    // 最新バージョン
```

# 2. シンボリックリンクの作成
続いて、既にopensslがインストールされている環境では、古いバージョンのopensslを削除するか、新しくインストールしたopensslの参照先を追加する必要があります。
今回は、以下のように既存のopensslについては、openssl.bakとし、 **/usr/bin** に新しいバージョンのopensslを参照するシンボリックリンクを作成しました。

```text:シンボリックリンクの作成
# openssl version
OpenSSL 1.0.1f 6 Jan 2014    // 古いバージョンのまま
# mv /usr/bin/openssl /usr/bin/openssl.bak
# ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl
# openssl version
OpenSSL 1.0.2d 9 Jul 2015    // 最新バージョンへ変更

```

以上でOpenSSL バージョン1.0.2d をソースからインストールする作業は終了です。

# 参考文献
1. OpenSSLに脆弱性、クライアントやサーバにメモリ露呈の恐れ - ITmedia エンタープライズ, <a name="1">http://www.itmedia.co.jp/enterprise/articles/1404/08/news038.html</a>
, Online; accessed 5-September-2015.
2. OpenSSL, <a name="2">http://www.openssl.org/</a>, Online; accessed 5-September-2015.
3. LinuxにApacheとOpenSSLをソースからビルドしてインストールする - Qiita, <a name="3">http://qiita.com/DQNEO/items/3613cc1d87c01121a9e2</a>, Online; accessed 5-September-2015.
超巨大な数を扱う大学入試問題をGoで解いてみる

# 2015年東京大学（理科）数学 問5

mを2015以下の正の整数とする。${}_{2015} C _m$ が偶数となる最小のmを求めよ
http://kaisoku.kawai-juku.ac.jp/nyushi/honshi/15/t01.html

## 力技で解く
本当は2015が32*63-1であることを使って2が何回かけられているか調べていくのがエレガントな方法ですが、難しいのでここではまともに計算します。
とはいっても普通に計算するとあっという間に`Int64`で扱える整数の限界を超えてしまうので、`math/big` を使います。

```go:tokyo_univ.go

package main

import "fmt"
import "math/big"

var (
	n      = big.NewInt(2015)
	one    = big.NewInt(1)
	two    = big.NewInt(2)
	zero   = big.NewInt(0)
	lookup = make(map[int]*big.Int, 2015)
)

func main() {

	for i := 1; i < 2015/2; i++ {
		x := combination(n, big.NewInt(int64(i)))
		fmt.Println(fmt.Sprintf("%2d : %v", i, x))
		if x.Mod(x, two).Cmp(zero) == 0 {
			fmt.Println("Answer:", i)
			return
		}
	}
}

// 階乗を計算します
func factorial(n *big.Int) (result *big.Int) {

	if n.Cmp(one) < 1 {
		return one
	}

	if m, ok := lookup[int(n.Int64())]; ok {
		return m
	}

	result = new(big.Int).Set(n)
	result = new(big.Int).Mul(result, factorial(n.Sub(n, one)))

	lookup[int(n.Int64())] = result

	return
}

// 組み合わせ n C k を計算します
func combination(n, k *big.Int) *big.Int {

	a := factorial(new(big.Int).Set(k))
	b := factorial(new(big.Int).Sub(n, k))

	c := new(big.Int).Mul(a, b)
	d := factorial(new(big.Int).Set(n))

	return d.Div(d, c)
}

```

## 実行結果
```
$ go run tokyo_univ.go
 1 : 2015
 2 : 2029105
 3 : 1361529455
 4 : 684849315865
 5 : 275446394840903
 6 : 92274542271702505
 7 : 26482793631978618935
 8 : 6647181201626633352685
 9 : 1482321407962739237648755
10 : 297353674437325491072340253
11 : 54199465204257964509094746115
12 : 9051310689111080073018822601205
13 : 1394598100791499491250515513093355
14 : 199427528413184427248823718372349765
15 : 26603632290318802594993084030871458651
16 : 3325454036289850324374135503858932331375
17 : 391034271679024164613170404247882690024625
18 : 43404804156371682272061914871514978592733375
19 : 4562073363172328920910928631495548013141502625
20 : 455294921644598426306910677423255691711521961975
21 : 43253017556236850499156514355209290712594586387625
22 : 3920296227597103631605367710194878440041527511678375
23 : 339702190504392501643021645496451857869685405685869625
24 : 28195281811864577636370796576205504203183888671927178875
25 : 2245472243496894962960570239329006354741564893832280525605
26 : 171864990944570037549674414471720101766758236104855317152075
27 : 12660720999583326099492681866083380830151190059724341696869525
28 : 898911190970416153063980412491920038940734494240428260477736275
29 : 61590915050283341246142382055911900599146187588128653571353861325
30 : 4077318576328757190494625692101367819663477618334116866423625619715
31 : 261079915290728484617155870929716616839742034593329741285512801778525
32 : 16186954748025166046263663997642430244064006144786443959701793710268550
Answer: 32
```

というわけで、答えは32です。71桁ありますね。
`math/big`、ちょっと使いづらいところもありますがこのような超巨大な数を扱うことができます。
POH6 漫画版: 女子高生プログラマーの大バトル！〜コボール文明の逆襲〜 緑川つばめ

[六村リオ](http://qiita.com/rana_kualu/items/cbd237a865125b4cd9bf) / [霧島京子](http://qiita.com/rana_kualu/items/e6467151c88d69670fbb) / [緑川つばめ](http://qiita.com/rana_kualu/items/535144055c73f5694153) / [島根ルミ](http://qiita.com/rana_kualu/items/cc79813f9555e01330a2) / [島根ルミ149](http://qiita.com/items/0e9b48b4361ee567c7e6/) / [島根ルミ121](http://qiita.com/items/9de54445c2ed7c444d99/) / [共通解](http://qiita.com/items/04721cdd925166156aab/)


[報酬を出力します](https://paiza.jp/poh/joshibato/tsubame)。

```php
<?php
	$f = fgets(STDIN);
	echo $f + $f[0] + $f[1];
```

https://paiza.jp/poh/joshibato/tsubame/result/207feae0

なにか深い引っかけでもあるのかと思ったら何もなかった。
他の問題もそんなに難しくないけど、これはいくらなんでもさすがに簡単すぎじゃね。
RubyMineでRailsのログを見る

## Grep Console
https://plugins.jetbrains.com/plugin/7125?pr=webStorm
を入れる

入れ方は
![Screen Shot 2015-09-05 at 18.58.42.png](https://qiita-image-store.s3.amazonaws.com/0/27895/893e9239-f0ca-763e-4e53-436c47351f55.png)
メニューの `Preferences`　から `plugin`　でまず検索して出てくる `plugin`からさらに `Grep Console`で検索


## インストールされると
![Screen Shot 2015-09-05 at 23.23.00.png](https://qiita-image-store.s3.amazonaws.com/0/27895/9d3c00e7-014c-fa72-2a22-39f73882869f.png)

ウィンドウ上部,右端に`Tail File`と出る

ログファイルの場所を教えてあげる。
Grep Consoleは`Floading Mode`にして別ウィンドウにしてやると見やすいだろう。

## Ctr-F
![Screen Shot 2015-09-05 at 19.01.11.png](https://qiita-image-store.s3.amazonaws.com/0/27895/16498056-0276-f596-2d09-735bda8f26c1.png)

で検索可能になる。
Yosemite + tmuxでsublコマンドでファイルが開かない

# そもそも
Sublime Textではコマンドラインからファイルやディレクトリを開くことができます。

```
$ sudo ln -s /Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl /usr/local/bin/subl
$ echo "export PATH='/usr/local/bin:$PATH'
```

とかしておくと…

```
$ subl hoge.txt
```

とかコマンド打つと
![スクリーンショット 2015-09-05 18.46.01.png](https://qiita-image-store.s3.amazonaws.com/0/16562/77994120-dec2-1087-d3fb-be77b5805347.png)

みたいに、ファイルとかディレクトリが開けます。
confいじるときとか、かなり便利です。

# 問題
**Yosemite + tmux 環境だとコマンドライン引数のファイル・ディレクトリが開かない！！**
**（Sublime Text自体は起動する）**

# 動けばいい人の解決策

```
$ brew install reattach-to-user-namespace
$ vim ~/.zshrc
```

```~/.zshrc
alias subl='reattach-to-user-namespace subl'
```

**とりあえず動く！**

# なぜ動かないのか知りたい人向け
自分動けばよかったので、各自下記の参考リンクをご覧になってください。

# 参考リンク
osx - Unable to launch application in tmux - Super User
http://superuser.com/questions/834525/unable-to-launch-application-in-tmux

[OSX] CLI tool stopped working properly under tmux · Issue #675 · SublimeTextIssues/Core
https://github.com/SublimeTextIssues/Core/issues/675#issuecomment-73426588
CentOS7.1にNginx+NodeJS(nvm)環境の導入(Vagrant環境下)

昨日の記事の環境を元に書きます。
昨日の記事は→ [Windows10にVagrant入れて、CentOS7.1入れた話](http://qiita.com/fagai/items/05d5dbd41f19e21db939)

## Nginx入れる

公式リポジトリを追加してインストール。

```
$ sudo rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
$ sudo yum install -y nginx
```

## NodeJSを入れる

やることはこの自分が書いたリンクのやつです。
[NodeJSの導入(CentOS7 - Qiita](http://qiita.com/fagai/items/93402522a9024e243f4d)

このリンクの内容を行うために幾つかパッケージを入れなきゃいけないので入れます。

```
$ yum install -y git
```

### nvmインストール(詳しい流れはさっきのリンク見てね)

```
$ git clone git://github.com/creationix/nvm.git ~/.nvm
$ echo . ~/.nvm/nvm.sh >> ~/.bashrc
$ . ~/.bashrc
$ nvm --version
0.26.1
```

### NodeJSのインストール(詳しい流れh(ry

```
$ nvm install stable
Now using node v0.12.7 (npm v2.11.3)
```

今回は再起動しても問題ないようにエイリアスを付けておく

```
$ nvm alias default 0.12.7
$ nvm list
->      v0.12.7
default -> 0.12.7 (-> v0.12.7)
node -> stable (-> v0.12.7) (default)
stable -> 0.12 (-> v0.12.7) (default)
iojs -> iojs- (-> N/A) (default)
```

## Nginxの設定

nginxの設定ですが、socket.ioのサイトの設定方法を参考にします。
http://socket.io/docs/using-multiple-nodes/#nginx-configuration

```
sudo vi /etc/nginx/conf.d/node.conf
```

```nginx:/etc/nginx/conf.d/node.conf
upstream io_nodes {
  ip_hash; # クライアントは同じサーバーに接続されることを保証
  server 127.0.0.1:6001;
}

server {
  listen 3000;
  server_name 192.168.33.10;
  location / {
    # websocketを使えるようにする設定
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    # ロードバランサ用の設定
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;

    proxy_http_version 1.1;
    proxy_pass http://io_nodes;
  }
}
```

### confが間違えてないかシンタックスチェック

```
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

### 後は起動

```
$ sudo nginx
```

自動起動設定もやっておくか。

```
$ sudo systemctl enable nginx.service
ln -s '/usr/lib/systemd/system/nginx.service' '/etc/systemd/system/multi-user.target.wants/nginx.service'
```

## 起動させるNodeアプリケーションを用意する

とりあえず今回はSocket.ioまでは確認せずに、一旦表示されるまで見ます。
雛形があるexpressを使っちゃいましょう。

```
$ npm install -g express-generator
$ cd ~
$ express -e ejs hoge
$ cd hoge
$ npm install
```

## 起動

```
$ PORT=6001 NODE_DEBUG=http,net node bin/www
```

起動したものの、対象のアドレスにブラウザしても動かない。
そうだ、Vagrantfileでip指定してなかった。

```
$ vim Vagrantfile
# config.vm.network "private_network", ip: "192.168.33.10"
↓
config.vm.network "private_network", ip: "192.168.33.10"
```

これでreloadし直す。

```
vagrant reload
```

そして再度アプリケーションを起動します。

```
$ PORT=6001 NODE_DEBUG=http,net node bin/www
```

これで http://192.168.33.10:3000 にアクセスすればExpressの初期表示が出ましたー。

ではではー。

次にやったこと書きましたー
[Nginx+pm2(fork)をやってみる。(CentOS7.1+express4)](http://qiita.com/fagai/items/f62d998e50dea95254d5)
PHP でパスワードの強度を試すための CrackLib ライブラリを使う

PHP の Crack を使おうとして右往左往したのでメモです．

# Crackの導入
環境
CentOS release 6.5 (Final)
PHP 5.6.12

### cracklib のインストール

```
$ sudo yum install cracklib cracklib-devel cracklib-dict
```

### crack のダウンロード，インストール

```
$ svn export http://svn.php.net/repository/pecl/crack/trunk crack
$ cd crack
$ phpize
$ ./configure
$ make
$ sudo make install
```

私の場合は，`$ make` の後に `$ make test` をしてくれと言われました．
ここまで終わったら crack.so が作成されるので，php.ini に設定を追加します．

```php:php.ini
; crack
extension=crack.so
```

### 辞書の作成

```
$ sudo create-cracklib-dict /usr/share/dict/linux.words
$ ls /usr/share/cracklib/
cracklib-small.hwm  cracklib-small.pwi  pw_dict.hwm  pw_dict.pwi
cracklib-small.pwd  cracklib.magic      pw_dict.pwd
```

# テスト

### サーバ再起動
これをしなくてもコマンドだと実行可能です．しかし，ブラウザで表示させたり，実際に場合には忘れずに再起動をしましょう．（これで滅茶苦茶時間を食いました）

```
$ sudo service httpd restart
```

### テストコード

```php:test.php

<?php
// CrackLib 辞書をオープンする
$dictionary = crack_opendict('/usr/share/cracklib/pw_dict');

// パスワードチェックを行う
// 'hogehoge'がみたいパスワード
$check = crack_check($dictionary, 'hogehoge');

// メッセージを取得する
$diag = crack_getlastmessage();
switch ($diag) {
  case "it's WAY too short":
    $diag = "あまりにもパスワードが短すぎます";
    break;
  case "it is too short":
    $diag = "パスワードが短すぎます";
    break;
  case "it does not contain enough DIFFERENT characters":
    $diag = "同じ文字や数字が含まれすぎています";
    break;
  case "it is all whitespace":
    $diag = "空白だけのものは使えません";
    break;
  case "it is too simplistic/systematic":
    $diag = "単純もしくは規則正しすぎます";
    break;
  case "it is looks like to a National insurance number":
    $diag = "国民保険の番号のような番号は使えません";
    break;
  case "it is based on a dictionary word":
    $diag = "辞書に含まれる単語だけではいけません";
    break;
  case "it is based on a (reversed) dictionary word":
    $diag = "辞書に含まれる単語を逆順にしただけではいけません";
    break;
  case "strong password":
    $diag = "強いパスワードです";
    break;
  default:
    $diag = "";
    break;
}

// 辞書を閉じる
crack_closedict($dictionary);

echo $diag;
?>
```

```
$ php test.php
同じ文字や数字が含まれすぎています
```

***
参考
[Crack関数のインストール](http://qiita.com/pb_tmz08/items/e22abf1ac7e98f3e9ea4)
[PHP: Crack - Manual](http://php.net/manual/ja/book.crack.php)
[phpize で共有 PECL 拡張モジュールをコンパイルする方法](http://php.net/manual/ja/install.pecl.phpize.php)
俺流gulpレシピ

LIGさんの[このサイト](http://liginc.co.jp/web/tutorial/117900)を参考に制作。

いくつかコピペでむりな　部分があったので補足して作成。

レシピ

-sass コンパイラ
`sudo npm install gulp-sass --save-dev`
-autoprefixer
`sudo npm install gulp-autoprefixer --save-dev`
-frontnote
`sudo npm install gulp-frontnote --save-dev`
-js uglify
`sudo npm install gulp-uglify --save-dev`
-browsersyns/start server
`sudo npm install browser-sync --save-dev`
-plumber(gilpのエラーストップをなくす)
`sudo npm install gulp-plumber --save-dev`
ファイル監視


以上。

ダウンロードはこちらより
https://github.com/sorashin/gulpTemplate

快適なgulp lifeを。
Rails g model ~ テーブル作成虎の巻 ~ 


# パターン

1. 普通のテーブル
2. 外部キー制約
3. validation
4. index
5. unique


# 普通のテーブル
単数形
カラム：データ型 カラム：データ型
カンマはいらない

```
rails g model Author name:string age:integer
```

# 外部キー制約
これでauthor_idがカラムに追加される。


```
rails g model Book title:string author:references
```

# validation
modelに後から追加する。

```Book.rb

class Book < ActiveRecord::Base
  validates :title, presence: true
  validates :hoge, length: { minimum: 2 } 
end
```


# index
特定のカラムをB木構造にして検索をかけるので、速い。ただ頻繁に使うカラムでないと逆に負債。

作成時↓

```
rails g model Book title:string:index
```

しかし、

```
rails g migration AddIndexToBook 
```

等と打って、migrationファイルいじるほうが一般的かも知れない。



# unique

uniqueでありたい時もありますね

```
rails g model Book title:string:unique
```
texからmd/rstを作る時に出たエラー

# はじめに
とある学会の予稿をtexで書き、内容的に個人的な技報(Sphinxで作ってる)にマージしようとしたら、以下の様なエラーが表示された。

```
$ pandoc main.tex -o main.md
pandoc: Cannot decode byte '\xbb': Data.Text.Internal.Encoding.Fusion.streamUtf8: Invalid UTF-8 stream
```
ファイルは、utf-8で書いたんだけどな・・・・。

# 対処
```
$ iconv -t utf-8 main.tex| pandoc | iconv -f utf-8
$ pandoc main.tex -o main.md
```
git cloneしてきたプロジェクトの名前を変えてクローンしてくる方法

# メリット ー スパイクのため
 * 最近はqiitaなどと連携してTipsを練習できるように練習用のプロジェクトをgithubにアップするという動きがでています。「何回も練習したい！」という人に便利かもしれません。
 * 自分のプロジェクトを完全練習用に複製する

# 実際にやってみる

オプション無しの通常のgit cloneは次のようになります。(deviseをcloneするときの例です)

```termina:オプション無しの通常のgit_clone
 & git clone https://github.com/plataformatec/devise.git
```

自分のクローンしたいディレクトリまで移動して次のように入力して実行するだけです。たとえば、プロジェクト名を `sample`としたとき、次のように書きます。

```termina:プロジェクトの名前を変えてgit_cloneする場合
 & git clone https://github.com/plataformatec/devise.git sample
```

スペースを空けて付けたいプロジェクトの名前を入力するだけでプロジェクト名を変更できました。

# 参考url 
[2.1 Git の基本 - Git リポジトリの取得](https://git-scm.com/book/ja/v1/Git-%E3%81%AE%E5%9F%BA%E6%9C%AC-Git-%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E5%8F%96%E5%BE%97)
Redmine Checklists pluginで未チェックの検証を雑に行う

[Redmine Checklists plugin](https://github.com/Undev/redmine_issue_checklist)という、チケットにチェックリストを付与できる大変便利なRedmineのプラグインがあるのですが、チェックに強制力を持たせられないのが困りものです。
(タスクが残ってるのにレビュー依頼とか出されても困る...)

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

とりあえず上記を解決するには`lib/redmine_checklists/patches/issues_patch.rb`をいじればよいです。
※Railsのルートから見ると、`plugins/redmine_checklists/lib/redmine_checklists/patches/issues_patch.rb`

```rb:issue_patch.rb
require_dependency 'issue'

module RedmineChecklists
  module Patches

    module IssuePatch
      def self.included(base) # :nodoc:
          # ~~~ 省略 ~~~

          # ここから
          validate :complete_tasks

          def complete_tasks
            # 未チェックの項目が一つでもあると設定できないようにしたいステータスのIDを指定
            # この例だと、全部チェックしないとステータスを"解決"(status_id:3)に更新できないようにしている
            return unless status_id == 3
            return if checklists.all? {|checklist| checklist.is_done}
            errors.add(:base, 'チェックリストに未チェックの項目が存在します。タスクを全て完了させてください。')
          end
          # ここまでを追加

        end
      end

    end

  end
end
```

こうしておくと、タスクを完了させないと怒られるようになります。
![](https://i.gyazo.com/6f1781190118fa4616d0866234e58200.png)

プラグインの設定画面でステータスを設定できるようにして、さらにプルリクも送ったらカッコイイと思うんだけど、そんな気力はなかった。
![](https://i.gyazo.com/55b3ee27c96bebcb0e97f5a3f2dba50b.png)
CodeceptionでREST APIの振る舞いテストのススメ


## 事始め

必要なファイルの作成

````
codecept bootstrap 
````

新しいsuiteの作成

````
codecept generate:suite hoge
````

hogeディレクトリに加えて、`hoge.suite.yml`ができる。このyml設定ファイルを修正してテストの基本設定を行う。

````
# Codeception Test Suite Configuration

# suite for api tests.
class_name: HogeTester
modules:
    enabled: [PhpBrowser,REST,HogeHelper]
    config:
      PhpBrowser:
        url: http://localhost:8000/
      REST:
        url: http://localhost:8000/api/
env:
  dev:
    modules:
        config:
          PhpBrowser:
            url: http://localhost:8000/
          REST:
            url: http://localhost:8000/api/
  stage:
    modules:
        config:
          PhpBrowser:
            url: https://myapp.herokuapp.com/
          REST:
            url: https://myapp.herokuapp.com/api/
````

設定はenvで階層化できる。

ymlを修正後、buildコマンドを叩くと、suiteに必要なファイルが出来上がる。

````
codecept build
````

## テスト書く

### 基本のテスト

APIの発行からステータスコードの確認、JSONであることの確認まで。
この編をワンセットでトレイトとかにまとめとくのがオススメ。

````
$I = new HogeTester($scenario);

$I->haveHttpHeader("Content-Type","application/json");
$I->sendPOST($url,$data);
$I->SeeResponseCodeIs($status);
$I->seeResponseIsJson();
````

### レスポンスのテスト

レスポンスの一部を配列で与えてレスポンスとの検証を行うことができる。

````
$I->seeResponseContainsJson($expectArary);

````

レスポンス全体を毎回書くのは大変だから、grabして全体を取ってきてから、
検証したい部分を書き換えて、変わっていないことを検証する、ってやり方が楽。

````
$response = json_decode($I->grabResponse(),true);
$response["user"]["name"] = $expectedName;
$I->seeResponseContainsJson($expectArary);

````

振る舞いテストにAssertはないのだけど、無理やりPHPUnitのAssertを叩いて対処することも可能

レスポンスの配列の長さの検証とかは、`seeResponseContainsJson`ではやりずらいのでこちらの方が楽。

````
\PHPUnit_Framework_Assert::assertSame($expected,$actualCount);
````







co
Volumio でタイムゾーン設定

# 目的

Raspberry Pi 2にインストールした[Volumio](https://volumio.org/)のタイムゾーン設定がBSTだったため、JSTに変更する

# 手順

1. SSHなどでコンソールから以降のコマンドを実行

> 1. dpkg-reconfigureの実行<br>
> ```
> sudo dpkg-reconfigure tzdata
> ```
> 2. Asiaを選択
> 3. Tokyoを選択
> 4. 確認<br>
> ```
> date
> ```

JSTになっていればOK
Xamarin.AndroidでReleaseビルドの時のみSystem.Servicemodel.ChannelFactoryでエラーが出た。

Xamarin.Androidでハマったので。

Wcfにアクセスするときにサービスインターフェイスを使って簡単にアクセスするために
System.ServiceModel.ChannelFactoryとか使うと楽です。
PCアプリとXamarin.Androidアプリで同じようにかけてとっても便利。
時短コード。

なんですけどXamarin.Androidでdebugしていると全く問題ないのに、ReleaseでPackage作ってテストってなるとエラーが出てしまいました。

```csharp


var cf = new ChannelFactory<IXXXXService>(new BasicHttpBinding()
, new EndpointAddress("http://localhost"));
var channel = cf.CreateChannel();  // Releaseだとエラーになる。

```

https://forums.xamarin.com/discussion/13129/wcf-problem-knowntypeattribute-issue/p2

なんかリンカーファイルをおこなきゃいけないみたいです。
英語弱いので理由に関しては詳しくはわかんなかったです。
リフレクションを使っているのでウンタラカンタラ。

プロジェクトにlinker.xmlファイルを追加します。
中身は

```xml
<?xml version="1.0" encoding="utf-8" ?>
<linker>
    <assembly fullname="System.ServiceModel">
        <type fullname="System.ServiceModel.Channels.ChannelFactoryBase`1">
            <method name="CreateChannel" />
        </type>
    </assembly>
</linker>

```

ファイルのビルドアクションを LinkDescription　に変更します。
これでオッケー。
Node.jsをVimで書く時に設定したことメモ

Node.jsをVimで書く時に設定したことメモ。

# NeoBunleのインストール

プラグインはNeoBundleを利用。

[NeoBundleによるVimプラグイン管理とおすすめプラグイン](http://catcher-in-the-tech.net/1063/)

基本的に上記に書いてあるとおり実施

```
"---------------------------
" Start Neobundle Settings.
"---------------------------
" bundleで管理するディレクトリを指定
set runtimepath+=~/.vim/bundle/neobundle.vim/
 
" Required:
call neobundle#begin(expand('~/.vim/bundle/'))
 
" neobundle自体をneobundleで管理
NeoBundleFetch 'Shougo/neobundle.vim'
 
" 今後このあたりに追加のプラグインをどんどん書いて行きます！！"
 
call neobundle#end()
 
" Required:
filetype plugin indent on
 
" 未インストールのプラグインがある場合、インストールするかどうかを尋ねてくれるようにする設定
" 毎回聞かれると邪魔な場合もあるので、この設定は任意です。
NeoBundleCheck
 
"-------------------------
" End Neobundle Settings.
"-------------------------
```

# フォルダ移動

`NERDTree`プラグインでvim上でフォルダ移動をする

```
NeoBundle 'scrooloose/nerdtree'
```

# 実行

`quickrun`プラグインでvim上でNode.jsを実行できる

```
" quickrun
NeoBundle 'thinca/vim-quickrun'
" 水平に分割する
let g:quickrun_config={'*': {'split': ''}}
```

# 補完

[myhere/vim-nodejs-complete](https://github.com/myhere/vim-nodejs-complete)

```
" complete
NeoBundle 'myhere/vim-nodejs-complete'
autocmd FileType javascript setlocal omnifunc=nodejscomplete#CompleteJS
if !exists('g:neocomplcache_omni_functions')
  let g:neocomplcache_omni_functions = {}
endif
let g:neocomplcache_omni_functions.javascript = 'nodejscomplete#CompleteJS'

let g:node_usejscomplete = 1
```

ctrl+x,ctrl+oで補完出来る

以下を追加してCtrl+fで補完できるようにする

```
imap <C-f> <C-x><C-o>
```

# 構文解析

[Node.js開発環境まとめ](http://qiita.com/ko2ic/items/daaef529c1dfdb94adbb#vim)

保存の際に`eslint`を実行するようにする

まずはインストール

```bash
$npm install -g eslint

$eslint -h
```

syntasticでファイル保存時に構文解析する。

```
NeoBundle 'scrooloose/syntastic'
let g:syntastic_check_on_open=0 "ファイルを開いたときはチェックしない
let g:syntastic_check_on_save=1 "保存時にはチェック
let g:syntastic_check_on_wq = 0 " wqではチェックしない
let g:syntastic_auto_loc_list=1 "エラーがあったら自動でロケーションリストを開く
let g:syntastic_loc_list_height=6 "エラー表示ウィンドウの高さ
set statusline+=%#warningmsg# "エラーメッセージの書式
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*
let g:syntastic_javascript_checkers = ['eslint'] "ESLintを使う
let g:syntastic_mode_map = {
      \ 'mode': 'active',
      \ 'active_filetypes': ['javascript'],
      \ 'passive_filetypes': []
      \ }
```

これでファイル保存の際に自動でeslintを実行してくる。便利。
ArduinoでUSB MIDI メモ

USBでMIDIを使おうとするととたんに難しくなってしまう感じがします。
いろいろ試したメモです。
OS X yosemiteで、1.7.6と1.6.4のArduino.appを主に使っています。
#hairless-midiserial.app
一番お手軽。
ほかのを使うときも,スケッチの検証のために使ったりします。

+ ソフトを経由して、というのがおもしろくない
+ 31250というボーレートが使えない -> d1(Serial)からDINとUSBのMIDIをいっぺんに送るとかはできない


#mocoLUFA+UNO
dfu_programmerが面倒ですが、なれれば安心して使えます。
atmega32u4でも使える?入れかたがわからない。
#32u4のボードでどうする?
leonardo,DaVinci32U4,A-Star32U4で試す。
##arcore
boards.txtをそれぞれのボード用に追加。
使えた。
audio MIDI設定で再スキャンすると消える。
復活の仕方がわからない。

##TeeOnArdu
 TeeOnArdu用のCaterina-Leonardo.hexを arduino as ISPで書き込む。
 書き込む際にそのままTeeOnArduを選ぶとjavaエラーになったので、
 
 + 純正のLeonardoの.hexファイルを一旦退避して、
 + その場所に上記のファイルをコピーして
 + Arduino.appを再起動、
 + ボードにLeonardoを指定して書き込み。
 
 で、うまくいった。
 
  使えた。
  スケッチの書き込みは直前にリセットボタンを押す、というお約束。
  
 audio MIDI設定で再スキャンすると消える。
 使用しているソフトを閉じ、挿し直しで復活。
 
 これだったらなんとか使えるかも。
Browserify + gulpではまったのでメモ

browserifyをgulpタスクとして実行しようとしたところ，
サンプルとしてWeb上で見つけたものではうまく動かなかったため，対処法をまとめておく．
なお，gulpについてはド素人のため，誤っている点等あれば指摘いただけると助かります．

# ダメだったサンプル
```js
gulp.task('browserify', function(){
    var browserify = require('browserify');
    browserify('<元になるファイル>', {<option>})
    .bundle()
    .pipe(gulp.dest('<出力先ディレクトリ>'));
});
```

このサンプルを実行すると，以下のようなエラーが発生した．

```js
_stream_readable.js:540
    var ret = dest.write(chunk);
                   ^
TypeError: undefined is not a function
```

# 原因
browserifyのbundleの返り値が変更されてしまい，Writableではなくなったことが原因の模様．
詳細は関連のIssueを参照．

# 最終的に出来上がったgulpタスク

```js
gulp.task('browserify', function(){
    var browserify = require('browserify');
    var through2 = require('through2');
    // browserifyしたいファイルを読み込む
    gulp.src('<元になるファイル>')
    // pipeしてthrough2オブジェクトを生成する
    .pipe(through2.obj(function(file, encode, callback){
        // fileにはsrcで読み込んだファイルの情報が引き渡される
        // file.pathを利用してbrowserifyインスタンスを生成する
        browserify(file.path, {<option>})
        .bundle(function(err, res){
            // bundleを実行し，処理結果でcontentsを上書きする
            file.contents = res;
            // callbackを実行し，次の処理にfileを引き渡す
            // nullになっている部分はエラー情報
            callback(null, file)
        });
    }))
    .pipe(gulp.dest('<出力先ディレクトリ>');
});
```

bundleの返り値を後続の処理で利用可能にするために，through2を利用する．

※ through2のAPIを理解しておくとgulpのpipeではまった時に助かりそう．

# 参考資料
この記事の元ネタ．bundleの仕様変更についても言及されている．
https://github.com/substack/node-browserify/issues/1198

gulpプラグイン作成についての記事．through2の使い方やgulpの挙動について．
http://qiita.com/morou/items/1297d5dd379ef013d46c

through2のAPI仕様
https://github.com/rvagg/through2
iOSのsafariでCSSアニメーションがちらつく

CSS3アニメーションを使う時に、PCのブラウザで確認して特に問題なかったのですが、
iPhone実機のsafariで確認したところ、最初に一瞬表示がちらつく現象がありました。

事象としては、下記ようなCSSアニメーションを設定した要素を、
$('.hoge').show();
で表示した際に、一瞬「HOGE」が表示されてからCSSアニメーションが始まるような感じでした。
想定としては、最初は何も表示されず、「HOGE」が拡大しながら表示されるはずでした。

```lang:css
.hoge{
    display : none;
    -webkit-animation : anim 0.3s linear 1 normal;
}
@-webkit-keyframes anim{
    0%   {-webkit-transform: scale(0);   opacity:0}
    85%  {-webkit-transform: scale(1.2); opacity:1}
    100% {-webkit-transform: scale(1);   opacity:1}
}
```
```lang:html
<div class="hoge">HOGE</div>
```


いろいろ調べて試してみましたが、どれも解決できず・・・
http://lealog.hateblo.jp/entry/2013/02/23/185428
http://22century.livejournal.com/3662.html
http://yumeirodesign.jp/blog/201312/csstransforms_fixed.html

30分ほど色々試行錯誤したところ、
「animation-delay」のプロパティ指定を追加したところiPhone実機でもちらつきが無くなり
想定した通りにアニメーションしてくれました！

-webkit-animation : anim 0.3s linear <font color="red">0s</font> 1 normal;
↑「0S」の指定を追加。

```lang:css
.hoge{
    display : none;
    -webkit-animation : anim 0.3s linear 0s 1 normal;
}
```

以後、アニメーションを使う時は気をつけよう。。。


===============================
OnederAppliよろしくお願い致します！
＞<a href="http://onederappli.jp">ホームページ</a>
＞<a href="https://itunes.apple.com/jp/artist/koike-jun/id999607803">iPhoneアプリ</a>
＞<a href="https://play.google.com/store/apps/developer?id=OnederAppli">Androidアプリ</a>
シンプルな画像置換

```
<img src=hunberg.jpg alt=好きな食べ物はハンバーグ>

```
のようなソースの代わりに、

```
<h2>好きな食べ物はハンバーグ<h2>
```
と書いて画像で表示させるようにするためのjQueryスクリプト。

実際は、

```
<h2 class=image-replace src=hunberg.jpg width=200 height=150>好きな食べ物はハンバーグ<h2>
```

のようにh2タグにsrc、width、height属性も書いておく。

```
$(document).ready(function(){
	$('.image-replace').each(function(){
		var t=$(this).text();
		var s=$(this).attr("src");
		var w=$(this).attr("width");
		var h=$(this).attr("height");
		var i=$(this).attr("id");
		var c=$(this).attr("class");
		/*var tg=$(this).get(0).tagName;*/
		/*$(this).replaceWith("<img id='"+ i + "' tagname='" + tg +"' class='" + c + "' src='" + s + "' alt='" + t + "' />");*/
		$(this).replaceWith("<img id='"+ i + "' class='" + c + "' src='" + s +  "' width='" + w + "' height='" + h + "' alt='" + t + "' />");
	});
});
```

何かの都合でオリジナルのidやclass名（tag名も？）を置き換わったimgタグのアトリビュートとして残しておくと後で役に立つかもしれない。

実はto-Rさんの作られた「一番簡単な画像置換の方法-imageReplace.js-」
http://blog.webcreativepark.net/2007/02/22-011041.html

を使ってみたのだが、他のスライダーなどのjQuery Pluginと同時に使ったとき、widthとheight属性が消えているので、レイアウト崩れを起こしたので、稚拙だがこんなスクリプトを書いてみた。

サンプル
http://qitailang.small.jp/template/kappou/menu.html

hoverの画像置換には対応していない。
Androidアプリでレビュー訴求の実装とレビュー荒れ防止の対策について

こんにちわ
[bowyer-app](https://github.com/bowyer-app)です。

僕の公開している個人アプリ
[弓道のアプリ 採点簿 for Android](https://play.google.com/store/apps/details?id=com.bowyer.KyudoScoreBookSecond&hl=ja&utm_source=Qiita&utm_medium=link&utm_campaign=review)
に、レビュー訴求を実装してみましたので、そのデータを元に検証していきたいと思います。

# ユーザーはどんな時にレビューを書きたくなるのか？
だいたい、以下の3つに別れるかなと思ってます。

1.バグや自分にとって不都合な結果を得た時
→ これは評価下がるし、本当はあまり書かれたくないですね
ただ、このレビューに対する対策もあるので、後述します。

2.本当によいと思った時、何か達成したとき
3.レビュー訴求されたから

上記1、２のパターンはユーザーが能動的に書くまで待たないといけないので、なかなかレビューが貰えません。
そこで、レビュー訴求を入れてみました。 

# ユーザー層とアプリの分析
■ アプリ名　： 弓道のアプリ 採点簿 for Android
■ 対象ユーザー　：　弓道をやっている高校生
■ 競技人口　：　約6万人
かなりニッチな市場かつ、Androidを持っている人となるとパイがかなり少ないです。
■ DAU : 約500 
■ MAU : 約2000
一般的な個人開発のアプリに比べてかなり少ないと思います。
ご自身のアプリへの導入の際の参考数値として比較してみてください。

# 訴求タイミングの設計
 立ち追加ボタン、もしくは占いボタンのイベント
→ これらはアプリ内のKPIとして見ている指標になります。
→ 出現頻度は毎日使ってくれていたとしたら約1週間後くらいに出る想定

しっかりと定着してくれたタイミングで訴求しています。
本質的なレビューが欲しいので、長い目で効果を設計しています。
ちょっと使ったくらいでそのアプリのことは分からないと僕は考えています。

# 訴求はこんな感じ
<img src="https://qiita-image-store.s3.amazonaws.com/0/92349/8ed1eb06-ce04-4cd1-e57a-e43a4f0094e7.png" width=300>

# レビュー荒れ対策をやってみた
「は？レビュー？ウザい！」と、なりますよね？僕もなります。
また、バグが起きたあとにこの訴求が出ようものなら、星１をつけたくなりますね。
そこで、僕は「要望を書く」ボタンを用意しました。
Googleスプレッドシートを用意し、要望を書いてもらうようにしてます。
地味に、これ効果がありまして実際にバグ報告や要望が多数寄せられました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/92349/a2267a43-261b-5b2e-6939-d21d27412293.png" width=300>


# とはいえ、レビューで星１つやバグ報告はついてしまう
「バグや自分にとって不都合な結果を得た時」は評価が下がるし、レビューも荒れる。
バグ報告はかなり精神的にダメージを受けますが、これはアプリを良くするチャンスなんです。

# 実際に仕込んでからの結果
2014/08/20-2015/08/20の結果です。

![スクリーンショット 2015-09-05 15.06.22.png](https://qiita-image-store.s3.amazonaws.com/0/92349/fbd1099b-f087-1061-e688-1b5d5d575e70.png)
レビュー訴求を仕込んだのは、2015/02/20です。

グラフを見ると、仕込んだ翌月からレビューが増えていることがわかります。
※ 星１つはバグ報告です。
※ 吹き出しマークはアップデート。
バグ報告を受けたらすぐに改修し、レビューに対して返信を行いました。
そうすると、星１つをつけていたユーザーが星５つに変更してくれました。

低評価ユーザーは星５になる可能性をもっていて、それに対応することが
アプリの質向上にもつながります。
また、自分の要望やバグ報告が直ることによって、もっとそのアプリを使おうと思ってくれます。

# レビューはユーザーと接することができる唯一の場所
「レビューを書く」という行為は、相当なモチベーションが無いと出来ないと思います。
本質的なユーザーの意見を吸い上げれる場所であり、ディベロッパーは毎日ここをチェックしたほうがいいと思います。
レビューに一喜一憂するのではなく、ユーザーが本当に求めているものを受け止める。
それがバグ改修であれ、機能追加であれしっかりと向き合うことが、よいアプリを作ることになると思います。

# 最後に
これからレビュー訴求を考えている方、すでに実装している方に
この記事が少しでも参考になればよいと思っています。


合わせて以下の記事も読んでみてください
[Androidアプリのレビュー対策とその効果](http://bowyer-app.com/2017/01/countermeasure-of-android-apps-review/)
[Androidアプリに+1ボタンを設置したらストアのランキングは上がるのか？](http://qiita.com/bowyer-app/items/af3d35e84bc6ed5b689b)
[あなたのレビュー訴求は大丈夫？Androidのレビューガイドライン無視とそのリスク](http://qiita.com/bowyer-app/items/f63bb0b13ab32d165cce)
Intellij IDEA 14 + scala + sbt プロジェクトの開始の仕方 + α


## 概要
Intellij 14 で、scala と sbt を利用するプロジェクトを新規で作成するメモ


## 前提
- Intelij IDEA Community Edition 14
- Plugins
	- Scala

## 手順
1. Create New Project
2. Scala -> SBT を選択し、Next
3. Project name を入力し、Finish

おわり。
　
　
　
　
だとあまりにもなので、
以下、依存に ScalaTest を追加しテストコードを実行するところまで。

## テストコードの実施までの作業手順
上記の手順を行った段階で、雛形のディレクトリが出来ていると思います。(Project name には、HelloWorldを指定)

```
HelloWorld/
  .idea/
  project/
  src/
    main/
      java/
      resources/
      scala/
      scala-2.11/
    test/
      java/
      resources/
      scala/
      scala-2.11/
  target/
  build.sbt
```

以下、上記のディレクトリ構成を前提として記載していきます。

#### まずScalaTestを取得
build.sbt に以下の1行を追加

```build.sbt
libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.4" % "test"
```

追加した段階で、EnableAutoImport を有効にするか聞かれるので、有効にしました。

External Libraries 配下に、scalatest の jar ファイルが置かれて入れば取得完了です。
#### ソーソコード作成
```scala:src/main/scala/HelloWorld.scala
class HelloWorld {
  def say(name: String) = s"Hello, $name"
}
```
#### テストコード作成
```scala:src/test/scala/HelloWorldTest.scala
import org.scalatest.FunSuite

class HelloWorldTest extends FunSuite {
  test("Hello, <引数> という文字列が返ってくる") {
    val hello = new HelloWorld
    assert(hello.say("Scala") == "Hello, Scala")
  }
}
```

#### 実行
テストファイルを副ボタンクリック、Run で実行します。

## まとめ
- plugin 検索に出てくる SBT パッケージなしでも大丈夫だった。
SSDのためのLinux設定


自分用メモ

１　ファイルシステムはxfs
２　swapは使わない
３　アクセスタイムの記録をしない。→noatime
４　Trimを使う。→discard
５　一時ファイルをRAMディスク上へ持っていく。→tmpfs
６　ブラウザのキャッシュをRAMディスク上へ持っていく。

１と２はパーティション作成の時。
３〜５は/etc/fstabに追記する。
６は５が終わったあとでシンボリックリンクを貼る。
僕はchromium派なので
$ cd ~/.cache/chromium
$ rm -rf ./Cache
$ ln -s /tmp/ ./Cache



（以下今のfstabの設定）
※マウントオプションはdefaultsとかでいいみたいだけど、動かなくなったりしたら怖いのでパーテション作成の時のものにnoataimeとdiscardを追記している。
※/var/tmpはtmpfsにマウントしてはいけないという話もあるが，今のところ問題なく動いているのでよしとする。

\# /dev/sda2
UUID=1f7c220c-d69a-49d1-96cc-18e5deb1beab       /               xfs             rw,relatime,attr2,inode64,noquota,noatime,discard       0 1

\# /dev/sda1
UUID=AD0C-6837          /boot           vfat            rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro,noatime,discard    0 2

tmpfs   /tmp       tmpfs   defaults,noatime,mode=1777   0  0
tmpfs   /var/spool tmpfs   defaults,noatime,mode=1777   0  0
tmpfs   /var/tmp   tmpfs   defaults,noatime,mode=1777   0  0
tmpfs   /var/log   tmpfs   defaults,noatime,mode=0755   0  0
PC で SD カードに書いた情報を元に、Raspberry Pi 自身に自分の Wi-Fi を自動設定をさせるスクリプト


# 背景

## 始めに
Raspberry Pi でヘンな物をつくって自分で使って遊んでいる間はいいのですが、誰かに提供する時に困ってしまうのが WiFi の設定で ***「そちらのネットワーク環境に合わせて WiFi の設定をしてね」と言ってしまうと相手が困ってしまい***ます。

以前、[wpa_cli から wps を使って自動設定する](http://qiita.com/UedaTakeyuki/items/e63f4c06ab2814f4fb27)方法を考えたのですが、[wps](https://ja.wikipedia.org/wiki/Wi-Fi_Protected_Setup)自身があまり知られておらず、wps 対応のモバイルルーターを持っている人もどうやって使うのか知らないようでした。持ってる人も使い方を知らない機能って...

これに懲りて、まず私の周りの方々のリテラシーを具体的に聞き取り調査してみた所、大変興味深い事実が浮き上がってまいりました

1. PC (Windows) でテキストファイルの読み書きは出来る
2. 自分のモバイルルーターの ***SSID*** とか ***wpa key*** とかを調べることができる

前者については、まあそうかなと思っていたのですが予想外だったのが後者で、 ***意味は分からないんだけど人に聞けば分かる***との事。なるほど、こういう問題解決の方法もあるんですね、盲点でした

## ソリューション

だったら解決策は実に簡単で、
 ***「
1. Raspberry Pi の SD カードを抜いて PC に挿してね
2. そしたら boot って名前のドライブが見えるから、そこに addwpa.txt ってファイルを作って
3. 一行目に SSID の値を、二行目に wpa の key の値だけ書いて、それ以外なにもかかないで
4. 書いたら、その SD カードを PC から抜いて Raspberry Pi に挿して起動して
」*** というお願いは通じるので、後は Raspberry Pi の起動時にそこから読んで wpa_cli で設定するスクリプトを書くだけですね。

# スクリプト
上記のスクリプトを実装するとこんな感じになります

```bash:addwpa.sh
addwpafile=/boot/addwpa.txt #wpa追加定義ファイル
if [ -e $addwpafile ]; then #wpa追加定義ファイルがあれば
  ssid=`head -n 1 $addwpafile`
  psk=`tail -n 1 $addwpafile`
  if [ -n "$ssid" -a -n "$psk" ]; then #両方とも長さが0でなければ
    # wpa_supplicant.conf の末尾に network 定義を追加
    nn=`wpa_cli add_network | tail -n 1` # 追加した network number
    wpa_cli set_network $nn ssid \"$ssid\"
    wpa_cli set_network $nn psk \"$psk\"
    wpa_cli enable_network $nn
    wpa_cli save_config
    # wpa追加定義ファイル の削除
    rm $addwpafile
  fi
fi
```

※2016.09.09 追記
これだと改行コードの違いのせいで Windows に SD カードを挿して書いた addwpa.txt ファイルを正しく処理できません。
github のほうには addwpa.txt を読む前に nkf (懐かしい！)で改行コードを Linux のものに揃えるようにした fix と、nkf のインストールスクリプト（という程たいそうなものでもないのですが）を置いています
※追記終わり

これを適当な場所(/home/pi とか)に置いて、それから /etc/rc.local の末尾の exit 0 の手前とかに以下のように追加しておけば

```bash:/etc/rc.local
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

# add wpa start
/home/pi/addwpa.sh

exit 0
```

起動時に addwpa.txt の存在をチェックしてあれば wpa_cli で追加し、成功したら addwpa.txt を削除します

# future works
とりあえず私の当座の目的は達成できているのですが、なにかありましたら[github](https://github.com/UedaTakeyuki/addwpa)にプロジェクトをあげておきましたので、issue レポートをいただければ幸いです。もし「修正しといたよ」という pull requests など頂けようものなら将に至福の至りにございます

#反省
何事も思い込みって誤解の原因ですね。聞いてみるもんですね。
シェルスクリプトで AppleScript 利用

こんにちは。
シェルスクリプトで AppleScript（osascript コマンド）を使ってみました。Finder で選択されているファイルをリストする例です。（本稿末尾は Ruby での例）

ただし、第 2 例と第 3 例は変数（```${delim}```）の展開を正しくできていません。

```console
$ ./as_test.sh 
1:
Macintosh HD:Applications:
Macintosh HD:Users:
2:
Macintosh HD:Applications:${delim}Macintosh HD:Users:
3:
Macintosh HD:Applications:${delim}Macintosh HD:Users:
```


```as_test.sh
#!/bin/sh
i=0
delim=\\n
# 1:
AS_RETURN=`
osascript << SCRIPT
  set text item delimiters of AppleScript to "${delim}"
  tell application "Finder" to get selection as text
SCRIPT`
i=`expr $i + 1`;echo "$i:\\n${AS_RETURN}"

# 2:
AS_RETURN=$(
osascript -e '
  set text item delimiters of AppleScript to "${delim}"
  tell application "Finder" to get selection as text
')
i=`expr $i + 1`;echo "$i:\\n${AS_RETURN}"

# 3:
AS_RETURN=$(
echo '
  set text item delimiters of AppleScript to "${delim}"
  tell application "Finder" to get selection as text
' | osascript - 
)
i=`expr $i + 1`;echo "$i:\\n${AS_RETURN}"

exit 0
```

また、第一例を Ruby で書いてみました。

```as_test.rb
#!/usr/bin/ruby
delim="\n"
AS_RETURN=`osascript << SCRIPT
  set text item delimiters of AppleScript to "#{delim}"
  tell application "Finder" to get selection as text
SCRIPT`
puts "#{AS_RETURN}"
```
gitでpush.defaultがupstreamでも違うブランチにpushされてしまった話


## 何が起こったか

あるプロジェクトで、追加したい機能があるからmasterブランチからfeatureブランチ切って実装。よしじゃあpull request投げるかーということでpushしたらなんとmasterブランチにpushされてしまった。焦った。

## なぜmasterブランチにpushされてしまったのか

featureブランチの切りかたに原因があった

```bash
git fetch -p
git checkout -b feature origin/master
```

`git checkout -b`で派生元ブランチにリモートブランチを指定することで、追跡ブランチも指定したリモートブランチに設定されてしまうみたいだった。
この状態で`git push`してしまうとorigin/masterにpushされちゃう。こわい。

## どうやって防ぐか

### branch.autosetupmergeをfalseに設定

この設定を行っておくことで、派生元ブランチにリモートブランチが指定されていても追跡ブランチに設定されなくなる

```bash
git config --global branch.autosetupmerge false
```

ちなみに`--no-track`オプションをつけることでも上記設定と同じ動きをしてくれる。

```bash
git checkout -b --no-track feature origin/master
```

### 個人的に一番いいと思う方法
ちゃんと`git push origin feature`とpush先を指定する。多分一番シンプルで間違いにも気づきやすいし。
Slackのreactionを使った投票機能をhubot-scriptsで作った

# TL; DR

 - Slack の reaction 機能を使った
 - 投票機能を
 - hubot拡張として作った

![screenshot](https://raw.githubusercontent.com/akiray03/hubot-slack-vote/master/hubot-slack-vote.gif)

# 使い方

hubot に向かって `hubot vote :dog: :cat:` のように書くと、メッセージ中の emoji が reaction に追加されます。emojiは以下のように、説明の間に入ったり、改行が入っても構いません。

```
hubot vote あなたの好きな動物を選んでください。
:cat: 猫だけでなく、ネコ科の動物全般が好きな方はこちら
:dog: いぬ好きな方はこちら
```

なお、一つの emoji につき、最大50人までreactionすることができます。それ以上の人数が投票する場合には、以下のような形で工夫すると良いでしょう。

```
hubot vote 一人一票の投票をお願いします！
よいと思った人は :+1: :grinning: のどちらかに投票してください。
イマイチだと思った人は :-1: :tired_face: のどちらかに投票してください。
```

# 導入方法

お使いの hubot のディレクトリに移動して、下記のコマンドを実行してください。

```bash
$ npm install hubot-slack-vote --save
```

`external-scripts.json` に以下を追記してください。

```json
[ "hubot-slack-vote" ]
```

環境変数として、 `HUBOT_SLACK_TOKEN` を定義してください。
(hubotをslack連携で利用している場合には、既に定義されているはずなので、追加の作業は必要ないはずです)

# Links

 - https://github.com/akiray03/hubot-slack-vote
 - https://www.npmjs.com/package/hubot-slack-vote

# 更新履歴

 - トークンの環境変数名を SLACK_ACCESS_TOKEN から HUBOT_SLACK_VOTE_ACCESS_TOKEN に変更して、 v0.0.2 をリリース
 - HubotのSlack連携用トークン `HUBOT_SLACK_TOKEN` を使うように変更。また以下の不具合修正を含めて v0.0.3 をリリース
    - 同一の絵文字がメッセージ中に複数回出現するとエラーになる不具合
    - メッセージ中に出現した順番どおりに reaction が付与されない不具合
RubyMineで追加（変更）したLive Templates (スニペット）

## やりかた
http://qiita.com/shingo-nakanishi/items/8d164a6b4d3d0b64eee5

## JavaScript
**con**, **log**

```
console.log($END$);
```

**f**

```
($PARAM$) => {
  $END$
}
```

**$#**, **$i**

```
$('#$END$')
```

**$c**

```
$('.$END$')
```

**$t#**, **$ti**

```
this.$s$ = $('#$END$');
```

**$tc**

```
this.$s$ = $('.$END$');
```

## Ruby
**ea**

```
each do |$E$|
 $END$
end
```
ifconfigが使えない

事件は唐突に

```
$ ifconfig
bash: ifconfig: command not found
```

絶対パスで指定してみる

```
$ /sbin/ifconfig 
eth0      Link encap:Ethernet  HWaddr ***  
...中略
```

出ました。

どうやら`/sbin/`にパスが通ってなかったみたいです。

`.bash_profile`に追加してあげればOKです

```
PATH=$PATH:$HOME/bin:/sbin/
```
mbed HRM 1017をつかってサーボを回すまで(始めてのmbed編)

この記事は長くなってしまったため
タイトルのメインとなる部分は
別で書きます。

この記事はmbedを始めて使用した時の忘備録です。

#mbed HRM 1017

[mbed HRM 1017]("https://developer.mbed.org/platforms/mbed-HRM1017/", mbed HRM 1017)
購入したところ
→[スイッチサイエンス]("https://www.switch-science.com/catalog/1755/", スイッチサイエンス)さん

##どうしてmbed HRM 1017か
1.Arduinoから卒業をしてみる。
2.mbedというワード最近良く聞く。
3.IoTっていっておけばカッコイイ感

mbed HRM 1017はmbedにそのままBLEモジュール乗っかってて
お手軽にBLEで遊べそう！
→購入

#mbed事始め
##まずはmbedに登録します
この辺りは[ここ](https://developer.mbed.org/users/nxpfan/notebook/lets_get_started_jp/, "ここ")みながら試した気がします。

##Hello World.binがない
上記のサイトをみながらhello worldしようとすると自分が持っているのは
機種が違うのでHello World.binが見当たらない、、、
とりあえず右上のCompilerをおしてコンパイラへ

##新規ファイルのつくりかたわからない
『ほうほうこれが噂のオンラインコンパイラか』などと思いながら
NewからcreateProgramしてもプロジェクトっぽいものができるだけで
中には何もなくmain.ccp的なものが見当たらない。
困った。
とりあえず手始めにBLEとか関係なくLチカしたかったんだけどナァ

##しかたないので
[mbed HRM1017をはじめよう](https://developer.mbed.org/teams/Switch-Science/wiki/mbed-HRM1017%E3%82%92%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86, "mbed HRM1017をはじめよう")
にたどり着いて、"とりあえず"って書いてあるところの"Import program"を押して
自分のコンパイラにImportしてきて、コンパイル＆実行(ドラッグアンドドロップ)

ちなみにMacで開発をすすめていて、初めてmbedさわってドラッグアンドドロップで
ファイル書き込むと、途中で落ちたかのようにmbedのマウントが外れて
再度復帰する。そして「ハードウェアの安全な取り外しできませんでした」的なアラートがでる。

これってエラーみたいに感じるけれど、どうやらこれで書き込みが終わっている様子。
特にBLEのサンプルは見た目にあんまり変化がないのでこれでいいのかわかりづらい印象だった。

##結果
このサンプルはI2Cでつながる温度センサのデータを発信するもの
っぽいがそんなものもってないのでとりあえず0の値が入ってる
サービスとキャラクタリスティックを観測した。

ちなみに飛んでるBLEを見つけるのにはLight blueというソフト
使ってます。(macでもiPhoneでもアプリがあるので結構便利です。)
自分のサーバのOSのバージョンがわからなくなった時に調べる方法

## 各OS毎に異なります


### まずはカーネルのバージョンを調べる

```
[riki@ ~]$ cat /proc/version 
Linux version 2.6.18-402.el5 (mockbuild@builder17.centos.org) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-55)) #1 SMP Tue Feb 10 17:49:04 EST 2015

```

* uname -a でもOK

```
[riki@ ~]$ uname -a
Linux sub0000540167.hmk-temp.com 2.6.18-402.el5 #1 SMP Tue Feb 10 17:49:04 EST 2015 x86_64 x86_64 x86_64 GNU/Linux
```

### Debiun系の場合

```
$ cat /etc/debian_version
4.0
```


### centOS/RedHat Enterprise Linux

```
[riki@ ~]$ cat /etc/redhat-release 
CentOS release 5.11 (Final)
``` 

### Fedoraの場合

```
$ cat /etc/fedora-release
Fedora release 9 (Sulphur)
```
Rails + Ransack + Postgresql で NULL を含むカラムのソート

## やりたいこと

- Rails+Postgresqlの環境で、ransackの`sort_link`を使ってソートを実装している。
- PostgresqlはDESCでソートするとNULLが先頭にきてしまう。NULLを後方に並べたい。
- `ORDER BY (number IS NULL), number DESC` というかんじのクエリを組み立てたい。

## こうなった

```user.rb
scope :reorder_by_is_null, ->(column, direction) { select('*', "(#{column} IS NULL) AS is_null").reorder('is_null', column => direction) }
```

```users_controller.rb
  def index
    @q = User.ransack(params[:q])
    @users = @q.result(distinct: true).reorder_by_is_null(sort_column, sort_direction)
    # => SELECT DISTINCT *, (id IS NULL) AS is_null FROM "users" ORDER BY is_null, "users"."id" ASC
  end

  private

  def sort_column
    User.column_names.include?(sort_params[:column]) ? sort_params[:column] : 'id'
  end

  def sort_direction
    %w(asc desc).include?(sort_params[:direction]) ? sort_params[:direction] : 'asc'
  end

  def sort_params
    return {} if params[:q].blank? || params[:q][:s].blank?
    s = params[:q][:s].split(' ')
    { column: s[0], direction: s[1] }
  end
```

### reorder_by_is_null

- Ransackにより `ORDER BY column direction` というクエリが作られてしまうため、`reorder` で上書きする必要がある。
- DISTINCTするとSELECTにないカラムをORDER BYに指定できないため、SELECT に `(column IS NULL) AS is_null` を付け加えている。

### sort_params

- `sort_link`を使うと `:q => { :s => "id asc" }` みたいなパラメータが来るので、カラム名とASC/DESCに分けて取り出している。

### sort_column, sort_direction

- `sort_link`でソートパラメータが設定されたない場合のデフォルトのORDER BYが `id ASC` になるようにしてある。

## そして

- とりあえず意図した通りにソートされるようになった。
- もっと良いやり方ありそう。
あなたのレビュー訴求は大丈夫？Androidのレビューガイドライン無視とそのリスク

こんにちわ。
[bowyer-app](https://github.com/bowyer-app)です。

先日、App Storeストアのランキング操作でアプリが大量に削除され、アプリ業界に大きな衝撃が走りました。

「Androidは審査もないし、なんでもやってオッケーだし大丈夫」
と思っていませんか？

答えは「No」です。
アプリを出しているということは当たり前にそのルールを知っていると思いますが、それでもリスクを犯してよいレビューを得ようとあの手この手を使っているアプリがあります。

今回は、それをやった時に何が起きるのか、それが事業にどんな影響を与えるのか。
Googleのガイドラインを元に書いてみます。

# ポリシー違反をしたらどうなるの？
[ポリシー違反の管理](https://support.google.com/googleplay/android-developer/answer/2477981?hl=ja&ref_topic=3453554)

・不承認
→アプリのアップデートが認められない場合があります
・削除
→アプリがストアから削除されます
→削除されたら意義申し立てできるのですが、ほぼ通らないと思っていたほうがいいと思います。
・停止
→アカウントが停止されます
>停止となった場合
アプリが停止されると、そのアプリのユーザー、統計情報、評価も失われます。Google Play でのデベロッパー アカウントがまだ良好な状態であり、かつアプリの内容から再公開が認められるものであれば、ポリシーに準拠した新しいバージョンを公開できます。

アカウント停止されたらそれまでのレビュー消えるとかほんと大ダメージですね。
また、複数のアプリを持っている場合であれば事業への影響は凄まじいと思います。

# どんなことがポリシー違反になるの？
今回はレビューにフォーカスしてみます。
[スパムとストア掲載順位](https://support.google.com/googleplay/android-developer/answer/2985810?hl=ja)

>・評価を操作しようとしない
・インセンティブによって評価を誘わない
・アプリを複数回評価しない
・レビューに不適切なコンテンツを含めない

よくやりがちなのが、インセンティブによるレビュー訴求です。
「★5で 500コインプレゼント」
「シリアルコード入力で500コインプレゼント」など。

この訴求で得られるレビューは

「★5　500コイン欲しいのでとりあえず」
「★5　このコード hogehoge　を入力すると始めから500コインもらえるよ」

ちなみにこれらのレビューはスパム認定されてしまいます。

# レビューがスパム認定されたらどうなるの？
・そのレビューがカウントされなくなる
→せっかく★5のレビューをもらっているのにレビューとしてカウントされないのはもったいないです。
・最悪の場合、アプリやアカウントが削除される
→こうなってしまうと事業的インパクトやばいですね。

# 最後に
ユーザーとして実際にアプリ落とす時、何を見ますか？
評価が高いアプリでも、レビューの内容がコイン訴求ばっかりだった場合、そのアプリを使ったユーザーの本質的な感想が見れないですよね？
本当に気に入ってくれたアプリであれば、よい評価をしてくれるはずです。

僕は本質的ではないレビュー訴求は実装したくないです。
時には「No」と言うことも大事です。
「エンジニアだし言われた通りに実装するのが仕事」
ではなく、エンジニアだからこそそういったところも意識して、よりよいアプリ作りを目指す。

それがランキングをアップする一番の近道なのではと考えています。

次回は、僕が実際にやったレビュー訴求について書きたいと思います。

合わせてこちらの記事もお読み下さい
[Androidアプリのレビュー対策とその効果](http://bowyer-app.com/2017/01/countermeasure-of-android-apps-review/)