OmniAICreator/Qiita-1.07M huggingface dataset:
Jupyter notebookのインストール


## 環境

* Ubuntu 16.04

## 手順

### インストール

```bash
$ pip3 install jupyter --user
```

* .vimrcに以下を追加

```bash
export PATH=$HOME/.local/bin:$PATH
export PYTHONPATH=$HOME/.local/lib/python3.5/site-packages
```

* .bashrc再読み込み

```bash
$ source ~/.bashrc
```

### 設定ファイル生成

```bash
$ jupyter notebook --generate-config
```
*  ~/.jupyter/jupyter_notebook_config.py が生成

### 設定ファイル(jupyter_notebook_config.py)変更

#### 1. 本環境はサーバで別PCからアクセスするので、本環境内のWebブラウザでのJupyter起動を禁止する
    *  c.NotebookApp.open_browser = False
#### 2. ポート番号の設定
    * c.NotebookApp.port = 9999
#### 3. ワーキングディレクトリの指定
    * c.NotebookApp.notebook_dir = u'/home/user/jupyter'
#### 4. ログインパスワードの設定
   * 以下のコマンドで生成、「sha1～」をコピーし、「c.NotebookApp.password」に貼り付ける
  
```bash
$ ipython
In [1]: from notebook.auth import passwd
In [2]: passwd()
・・・
Out[2]: 'sha1:～～'
Out[3]: exit
```

#### 5. IPアドレスの設定
    * c.NotebookApp.ip = '～～'

### 起動

```bash
$ jupyter notebook
```
PageViewControllerで次(前)のViewControllerを返すところでハマった

#概要
日記帳のようなアプリを作る際にPageViewControllerを使って実装したが、
Outlet接続したUILabelが全てnilになってしまってハマったのでメモ。

## PageViewControllerで必要なDelegateメソッド
```swift
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
      // 前のページを作る(ViewController)
      // そのViewControllerにページ番号をセット
    }
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
      //次のページを作って返す
      //そのViewControllerにページ番号をセット
    }
```

上記のメソッドで生成されるViewController(下の図の一番右)

```swift
class DiaryContentViewController: UIViewController {
    
    var pageIndex :Int? {
      didSet{
         pageIndexLabel.text = "\(pageIndex)"
      }
    }
    
    @IBOutlet weak var pageIndexLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

```

<img width="939" alt="スクリーンショット 2017-11-08 0.37.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/21372/f9268367-ac4f-cc59-f5b9-79b47c5801dc.png">

## やりたかったこと
- ページをめくった際に、ページ番号を更新
- 更新されたページ番号をコンテンツとなるViewControllerにセット
- セットされたタイミングでUILabelにセット

ここで問題が...
次(前)のページを返すメソッドでnilで落ちる...
### 原因
present/pushで画面遷移が行われてない状態だとアウトレット接続がまだ行われてないのでnilになる
### 解決策
```swift
override func viewDidLoad() {
        super.viewDidLoad()
        self.pageIndexLabel.text = "\(pageIndex!)"
    }
```
コンテンツのとなるViewControllerのviewDidLoadで処理を行う
開発環境のmysql on dockerが300倍早くなった設定

slackグループのmysql-casualに参加されている方から[CircleCIのDockerイメージ](https://github.com/circleci/circleci-images/blob/master/mysql/resources/Dockerfile-basic.template)を参考にすると良いと教えていただいたので実際に計測してみました。
ただあくまでも開発環境での設定なので本番では設定しない事をおすすめします。

## 設定内容

```config/my.cnf
[mysqld]
innodb_flush_log_at_trx_commit=2
sync_binlog=0
innodb_use_native_aio=0
```

``` docker-compose.yml
version: '2'
services:
  db:
    image: mysql:5.6.36
    environment:
      MYSQL_DATABASE: database_name
      MYSQL_ROOT_PASSWORD: fJ3jf2jfkj
      MYSQL_USER: hoge
      MYSQL_PASSWORD: fJ3jf2jfkj
    volumes:
      - "./config:/etc/mysql/conf.d"
    ports:
      - "3306:3306"
```

## 計測結果

### 計測コマンド

```shell:mysqlslap
$ mysqlslap -uroot -pfJ3jf2jfkj -P 3306 -h 127.0.0.1 --auto-generate-sql --iterations=1 --concurrency=1
```

```sql:計測されるSQL
DROP SCHEMA IF EXISTS `mysqlslap`;
CREATE SCHEMA `mysqlslap`;
use mysqlslap;
CREATE TABLE `t1` (intcol1 INT(32) ,charcol1 VARCHAR(128));
INSERT INTO t1 VALUES (1804289383,'mxvtvmC9127qJNm06sGB8R92q2j7vTiiITRDGXM9ZLzkdekbWtmXKwZ2qG1llkRw5m9DHOFilEREk3q7oce8O3BEJC0woJsm6uzFAEynLH2xCsw1KQ1lT4zg9rdxBL');
-- 上記INSERTが×100件
SELECT intcol1,charcol1 FROM t1;
INSERT INTO t1 VALUES (73673339,'BN3152Gza4GW7atxJKACYwJqDbFynLxqc0kh30YTwgz3FktQ43XTrqJ4PQ25frn7kXhfXD8RuzN1j8Rf3y8ugKy6es3IbqPJM6ylCyD6xS7YcQCfHKZxYNvB7yTahm');
SELECT intcol1,charcol1 FROM t1;
INSERT INTO t1 VALUES (1759592334,'3lkoxjtvgLu5xKHSTTtJuGE5F5QqmCcppCTmvFZScRZQgim93gSxwb24gKmIPEzEQStMjQiCu7WapGbkw4ilXch3xRLMhKSzgLDOovSi2qGj6rKvnuYAWDDJgaZDu2');
SELECT intcol1,charcol1 FROM t1;
INSERT INTO t1 VALUES (95275444,'bNIrBDBl81tjzdvuOpQRCXgX37xGtzLKEXBIcE3k7xK7aFtqxC99jqYnpTviK83bf6lGDgsKd4R3KLmHPnI8TqnIKj1gjw7N2sXFZNS2Svyg8cpZN7atxL39w4igsp');
SELECT intcol1,charcol1 FROM t1;
INSERT INTO t1 VALUES (866596855,'naQuzhMt1IrZIJMkbLAKBNNKKK2sCknzI5uHeGAgQuDd5SLgpN0smODyc7qorTo1QaI5qLl97qmCIzl0Mds81x7TxpIoJyqlY0iEDRNKA1PS0AKEn5NhuMAr3KgEIM');
SELECT intcol1,charcol1 FROM t1;
INSERT INTO t1 VALUES (364531492,'qMa5SuKo4M5OM7ldvisSc6WK9rsG9E8sSixocHdgfa5uiiNTGFxkDJ4EAwWC2e4NL1BpAgWiFRcp1zIH6F1BayPdmwphatwnmzdwgzWnQ6SRxmcvtd6JRYwEKdvuWr');
DROP SCHEMA IF EXISTS `mysqlslap`;
```

### before
![スクリーンショット 2017-11-08 0.00.21.png](https://qiita-image-store.s3.amazonaws.com/0/35451/8c4f8728-7f1e-fe2a-5aff-9ab25403026a.png)

### after
![スクリーンショット 2017-11-08 0.00.38.png](https://qiita-image-store.s3.amazonaws.com/0/35451/562c8342-841b-e31c-1c2e-8fcfc4288655.png)

以上です。

mysqlに関わらず開発環境をスムーズに動作させるためのdockerの設定などがあれば教えてください。
Leapmotionで髪を撫でる


## 準備

ORION BETAをインストール
https://developer.leapmotion.com/get-started

Unityパッケージをインポート
https://developer.leapmotion.com/unity

MMDの読み込み
[Unityでキズナアイを読み込んでアニメーションをつける](https://qiita.com/mo4_9/items/af596e8f7ad4ecd77447)

## 髪を撫でる

### キャラ

Unityの剛体でBulletの剛体に干渉するための設定をする。
[Model] -> [Physics Engine] -> [Bullet Physics]
![bullet.png](https://qiita-image-store.s3.amazonaws.com/0/136286/087b52b1-43c0-b386-604d-875f0d00148b.png)

[Physics] -> [Generate Colliders]
![process.png](https://qiita-image-store.s3.amazonaws.com/0/136286/35b9000f-77af-45a8-4de8-e12c56065378.png)

これでコライダーが付けられた
![collider.png](https://qiita-image-store.s3.amazonaws.com/0/136286/ad3ef90a-aecd-7e41-6892-2df380798f7e.png)

最後に [Bullet Physics] -> [Join Local World]をオフにする


## 手

`Leap Hands Demo`から`LMHeadMountedRig`を使用。
Rigidbodyコンポーネントをもつゲームオブジェクトにあらかじめ`MMD4 Mecanim Rigid Body`スクリプトがアタッチされているのでそのまま使える。

![leapmotion.gif](https://qiita-image-store.s3.amazonaws.com/0/136286/0d8d0814-3365-34c3-400c-5b4dd3d13e34.gif)


> 参考
[LeapMotionでMMDキャラの髪を触ったり体動かしたり。](http://bibinbaleo.hatenablog.com/entry/2017/08/26/214649)
[Leap Motion Orionを用いたヾ(・ω・*)なでなでアプリの作り方](http://zabaglione.info/archives/789)
(随時更新) AR技術＆サービスのリスト by Team AI

Team AIでは隔週でVR/AR/MR研究会を開催中です。
www.team-ai.com
今回はARのアウトプットをまとめていきます。

Graffity app => ARを使ったSNS。超オススメです！
gumiの国光さんが投資
http://graffity.jp/

KUDAN - 技術基盤 AR SDK
https://www.kudan.eu/

Vuforia - 世界最大のAR基盤技術
https://www.vuforia.com/

Vuforia - 事例集ビデオ
https://www.youtube.com/user/vuforia

Unity x VforiaでARアプリ作成
https://qiita.com/murasan/items/b31d9deb6d8b24bd9134

AR Kit  by Apple
https://developer.apple.com/arkit/

AR Studio by Facebook 
https://developers.facebook.com/products/camera-effects/ar-studio/

Magic leap ARの会社
https://www.magicleap.com/
Scalaを書く時もJupyterで良いのでは

## 概要

- Scala用のjupyter kernelが存在する --> [jupyter-scala](https://github.com/jupyter-scala/jupyter-scala)
- 実はScalaもanacondaでカバーできる --> [anaconda-cluster/scala](https://anaconda.org/anaconda-cluster/scala)
- 結論：Scalaの導入から（簡単な）コーディングまでJupyterで完結できる


## Anacondaからscalaをインストール

すでにScala 2.11がインストールされている場合は割愛してもよい。
下記コマンドでScalaをインストールできる。

```bash
$ conda install -c anaconda-cluster scala
```


## Scala用のカーネルをインストール

Jupyterが入っていなければ、先にインストールしておく。

```bash
$ conda install jupyter
```

`jupyter-scala`はまだAnacondaの管理対象になっていないようので、公式ページにあるシェルスクリプトからインストールする（いずれ`conda`コマンドでインストールできるようになるのでは）。

```bash
$ wget https://raw.githubusercontent.com/alexarchambault/jupyter-scala/master/jupyter-scala
$ bash jupyter-scala
```


## Jupyterから起動

```bash
$ jupyter notebook
```


Scalaが選択肢に入っている！
![Screenshot_2017-11-07_23-43-17.png](https://qiita-image-store.s3.amazonaws.com/0/80588/1370ce19-ae9a-1a42-6113-0e7748c914a6.png)

ちゃんと動く！
![Screenshot_2017-11-07_23-45-44.png](https://qiita-image-store.s3.amazonaws.com/0/80588/9672bebf-eb11-02b0-2cbf-8eb2c70ac09c.png)


## 余談

まだ検証はしていませんが、Scalaライブラリの依存関係もAnacondaによって解決してくれるようになれば鬼に金棒ですね。
JSで大文字小文字関係なく検索、タグを付与する

#概要
大文字小文字関係なく検索し、検索キーワードにタグを付与したく、つくってみました。

#コード
動作サンプルはこちら
http://jsdo.it/tsunet111/qX4C

```js

//ボタンをクリックしたら
$('#btn-search').click(function(){
    //置換元になるテキスト
    var basetext = $('#target-text').text();
    //置換するワード
    var searchtext = $('#input-text').val();
    //置換するワードの文字数
    var len = searchtext.length;
    //置換元、キーワードともに、小文字にする
    var basetext_s = basetext.toLowerCase();
    var searchtext_s = searchtext.toLowerCase();
    var wordList = new Array();
    var idx = 0;
    var cnt = 0;
    var flg = true;
    if(searchtext===''){
        //キーワードが空の場合は、タグを外した状態でHTML出力。
        $('#target-text').html(basetext);
    }else{
        //キーワードの出現位置を取得して配列にいれる
        do {
            var num = basetext_s.indexOf(searchtext_s, idx);
            if(num===-1){
                flg = false;
            }else{
                wordList.push(num);
                idx = num+1;
            }
        }while(flg);
        if(wordList.length===0){
            //キーワードが見つからなかったらHTML出力。
            $('#target-text').html(basetext);
        }else{
            //キーワードとその前後を順に取得して配列に入れていく。キーワードにはタグを付与する。
            var outarr = new Array();
            idx = 0;
            for(cnt=0;cnt<wordList.length;cnt++){
                if(wordList[cnt]===idx){
                    //キーワード箇所
                    outarr.push('<span class="hilight">'+basetext.substring(idx,idx+len)+'</span>');
                    idx += len;
                }else{
                    //キーワード前のテキスト＋キーワード箇所
                    outarr.push(basetext.substring(idx,wordList[cnt]));
                    idx = wordList[cnt];
                    outarr.push('<span class="hilight">'+basetext.substring(idx,idx+len)+'</span>');
                    idx += len;
                }
                if(cnt===wordList.length-1){
                    if(idx < basetext.length){
                        //最後のキーワードの後のテキスト
                        outarr.push(basetext.substring(idx,basetext.length));
                    }
                }
            }
            //配列を結合してHTML出力。
            $('#target-text').html(outarr.join(''));
        }
    }
});

```




##さいごに
力技で実装したので、もっと効率よい書き方がありそうですが…
golang で semaphore

はじめに
--------------------
- chan を使った semaphore をループ処理のなかで使っていた
- for 1ループごとに defer したいが func 抜ける時しか実行されない
- そうだ、無名関数で囲もう

セマフォ
--------------------

```go
type Semaphore struct {
  sem chan struct{}
}

func NewSemaphore(size int) *Semaphore {
  return &Semaphore{
    sem: make(chan struct{}, size),
  }
}

func (s *Semaphore) V() {
  s.sem <- struct{}{}
}

func (s *Semaphore) P() {
  <-s.sem
}
```

普通にdefer
--------------------

```go
for {
  sem.V()
  defer sem.P() // 当然まともに動かない

  // 途中で抜ける
  if err != nil {
    continue
  }

  // 何か処理
}
```

無名関数で囲んでみる
--------------------

```go
for {
  func() {
    sem.V()
    defer sem.P()

    // 途中で抜けてもOK
    if err != nil {
      return
    }

    // 何か処理
  }()
}
```

Wrap関数にしてみる
--------------------

```go
type Semaphore struct {
  sem chan struct{}
}

func NewSemaphore(size int) *Semaphore {
  return &Semaphore{
    sem: make(chan struct{}, size),
  }
}

func (s *Semaphore) V() {
  s.sem <- struct{}{}
}

func (s *Semaphore) P() {
  <-s.sem
}

func (s *Semaphore) Wrap(f func() error) chan error {
  errChan := make(chan error, 1)

  s.sem <- struct{}{}
  errChan <- f()
  close(errChan)
  <-s.sem

  return errChan
}
```

最終形
--------------------
```go
for {

  ec := sem.Wrap(func() error {

    // 途中で抜けてもOK
    if err != nil {
      return
    }

    // 何か処理
  })

  if err := <- ec; err != nil {
    // エラー処理
  }

}
```
zsh で非同期処理

# 結論

サブシェルを立ち上げ、サブシェルのバックグラウンドでジョブを実行、サブシェルの標準出力を `/dev/null` へ。

```zsh
( { sleep 5 } &; ) >/dev/null
```

非同期ジョブの詳細な管理がしたいのであれば [madri/zsh-async](https://github.com/mafredri/zsh-async) がオススメ。(ジョブの登録, 名前を指定してジョブを実行, 名前を指定してジョブを中止 ...)

# 解説

シェルであれば `コマンド &` で処理の終了を待たずに済む。

```zsh
sleep 5 &
```

複数コマンドを束ねるには波括弧を用いる。一行で書く場合はコマンドの最後に `;` が必要。

```zsh
{ sleep 2; sleep 3; } &
```

```zsh
{
  sleep 2
  sleep 3
} &
```

ジョブのステータス変化がが送られてくるので、これを消すにはサブシェルでジョブを実行し、サブシェルの標準出力ごと抑制する。

```zsh
( { sleep 2; sleep 3; } & ) >/dev/null
```

# あとがき

今回作ったもの。 tmux のウィンドウ名に自動的に作業中の Git のルートディレクトリ名を割り当てる **zsh** プラグインです。
[sei40kr/zsh-tmux-rename](https://github.com/sei40kr/zsh-tmux-rename)
React始めました〜③TypeScriptで環境構築

# 概要
色々とバタバタして間が空いてしまいましたが、最近はまたReactを触り始めたので
環境構築の仕方やつまづいた部分を紹介できればと思います。

#前提
TypeScriptやnode-sassがグローバル環境にインストールされていることを前提に進めます。

```
【環境】
OS：macOS Sierra 10.12.6
create-react-app@1.4.1
node-sass@4.5.3
npm@5.5.1
typescript@2.5.3
```

# TypeScriptでReact
Reactは普通、jsxとbabelかと思うんですが、せっかくだしTypeScriptで
書けば両方覚えれて一石二鳥じゃん！と思ったのがきっかけです。

以下のようにReactプロジェクト作成コマンドにオプションを付けてあげれば、
一発で環境は出来上がります。

```
create-react-app my-app --scripts-version=react-scripts-ts
```
そして、`cd my-app`で移動し`npm start`をすると通常の`create-react-app`コマンドで
作成したjsx形式のプロジェクトと同じ画面が立ち上がるかと思います。

私が最初、この方法を試した時に`node_modules`のどこかでエラーが出ましたが
パラメータの重複が原因だったみたいで一意にしたら直りました。
詳細を忘れてしまいましたが、エラーメッセージに出てくるファイルを
覗けば分かるかと思います。

```
{
  hoge:1,
  foo:2,
  hoge:1 // ←削除
}
```

また、再確認で先ほど実行してみたら以下のようなメッセージが。。。

```
/hoge/my-app/node_modules/@types/react-dom/index.d.ts
(16,43): error TS2305: Module '"/hoge/my-app/node_modules/@types/react/index"' has no exported member 'ReactPortal'.
```

なんじゃこりゃー！！
と思って調べてみると、どうやらreactのバージョンが低くなってしまい
react-domとのバージョンが合わなくなるのが原因みたいです（なんでや！）

```json:package.json
〜省略〜
"devDependencies": {
    〜省略〜
    "@types/react": "^15.6.6", //←古いので修正
    "@types/react-dom": "^16.0.2"

  }
```

ってなっているので、以下のようにreactのバージョンを揃えてあげて
`npm install`してから`npm start`すると直りました。

```json:package.json
〜省略〜
"devDependencies": {
    〜省略〜
    "@types/react": "^16.0.2",
    "@types/react-dom": "^16.0.2"

  }
```

# Reactプロジェクトにnode-sassを入れる
このまま、TypeScriptとcssで書いていってもいいのですが、
欲張りなのでsassの自動ビルドも入れてTypeScriptとsassで書いていこうと思います。

先ほど作った`my-app`フォルダで下記コマンドを実行
`npm install node-sass-chokidar npm-run-all`

そして、package.jsonにsassファイルを変更したら自動でcssファイルに
ビルドしてくれるようscriptsを設定します。

※この辺り、詳しくは[参考サイト](https://qiita.com/chieeeeno/items/1dda5c47d4f1e36408e8)が分かりやすいです。

```json:package.json
〜省略〜
  "scripts": {
    "build-css": "node-sass-chokidar src/ -o src/",
    "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
    "start-ts": "react-scripts-ts start",
    "start": "npm-run-all -p watch-css start-ts",
    "build": "npm run build-css && react-scripts-ts build",
〜省略〜
```

これで完成です。

# 参考
[create-react-app で TypeScript の環境を作る](https://qiita.com/ehr174/items/85b7cb7e7c93efef8889)
[[@types/react-navigation] the type definition seems to be broken. #21294](https://github.com/DefinitelyTyped/DefinitelyTyped/issues/21294)
[create-react-appでSASSファイルを使う方法](https://qiita.com/chieeeeno/items/1dda5c47d4f1e36408e8)
ファイルの中間行を行数を指定して抜き出したい


たとえば「このファイルの10行目から20行目までを見たい!」というように、ファイルの中間行を行数を指定して抜き出したいという場合、awkの組み込み変数`NR`、すなわちawkが処理している行の行数が格納されている変数を利用すると便利です。

以下の例では2017年1月1日から2017年12月31日までを1日1行として記録したファイル`sample.txt`を準備して、その30行目から40行目までを抜き出しています。

```bash
$ seq 0 364 | xargs -i date -d 2017/01/01+{}days +"%Y-%m-%d %A" > sample.txt
$ cat sample.txt | awk '(30 <= NR && NR <= 40){print $0}'
2017-01-30 Monday
2017-01-31 Tuesday
2017-02-01 Wednesday
2017-02-02 Thursday
2017-02-03 Friday
2017-02-04 Saturday
2017-02-05 Sunday
2017-02-06 Monday
2017-02-07 Tuesday
2017-02-08 Wednesday
2017-02-09 Thursday
```

なおawkの仕様(?)上`{print $0}`は省略することができます(詳細な理由は割愛しますが)。

```bash
$ cat sample.txt | awk '(30 <= NR && NR <= 40)'
2017-01-30 Monday
2017-01-31 Tuesday
2017-02-01 Wednesday
2017-02-02 Thursday
2017-02-03 Friday
2017-02-04 Saturday
2017-02-05 Sunday
2017-02-06 Monday
2017-02-07 Tuesday
2017-02-08 Wednesday
2017-02-09 Thursday
```
アップロードしたファイルをテキストで読み込む

いつも忘れて検索しているので、メモ。`<input type="file" />`から選択されたファイルをテキストとして読み込む場合は、FileReaderの`readAsText`を使う。

[サンプル](https://pirosikick.github.io/read-file-as-text-example/)

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ファイルをテキストで読み込むサンプル</title>
</head>
<body>
  <h1>ファイルをテキストで読み込むサンプル</h1>

  <input type="file" id="file" />
  <textarea id="textarea" readonly>
  </textarea>

  <script>
    const textarea = document.querySelector('#textarea');
    document.querySelector('#file').addEventListener('change', e => {
      if (e.target.files[0]) {
        const file = e.target.files[0];
        const reader = new FileReader();
        reader.onload = e => {
          textarea.value = e.target.result;
        };
        // BlobまたはFileをテキストとして読み込む
        // 第2引数にencodingを指定可能、
        // 指定しない場合はUTF8として読み込み
        reader.readAsText(file);
      }
    });
  </script>
</body>
</html>

```
Android の CookieManager で値を削除/変更できない場合


# 結論
setCookie しようとしている値の domain 属性と path 属性を確認しましょう。
キーが一致していても domain 属性か path 属性が異なっていれば値は上書き・削除できません。

# CookieManager
Android アプリで WebView の Cookie を操作したい場合、 `android.webkit.CookieManager` を使用します。
値の取得は `CookieManager#getCookie` 、値の変更・追加・削除は `CookieManager#setCookie` で可能です。
値を削除は HTTP 通信や JavaScript と同様に、 `max-age=0` や `expires` に過去の日付を指定することで行います。

```java
// 値の取得
String cookies = cookieManager.getCookie();
// 値の変更・追加
cookieManager.setCookie(url, "key=value; max-age=3600");
// 値の削除
cookieManager.setCookie(url, "key=; max-age=0");
```

# はまりポイント
CookieManager に限らず、 Cookie は domain 属性と path 属性を持つことができ、ブラウザ（HTTPクライアント）は domain 属性と path 属性を考慮して、実際にサーバに Cookie を送信するかどうかを判断します。

問題は、属性の値を省略した場合の振る舞いです。
domain 属性と path 属性を指定しなかった場合、保存された Cookie はその Cookie を発行した URL の domain と path にマッチする URL へのアクセスに対して Cookie を送信します。

ただし、 [**domain 属性は明示的に指定した場合と省略した時とでは異なる動作をします。**](https://blog.tokumaru.org/2011/10/cookiedomain.html)

domain 属性を省略した場合は Cookie を発行したホストに一致する URL へのアクセスに対してのみ Cookie を送信するのに対して、 domain 属性を指定した場合は指定した domain のサブドメインにまで Cookie を送信するのです。

例えば `example.com` が foo という名前の Cookie を発行したとします。
この時、 `Set-Cookie: foo=bar` のように domain 属性が指定されていなかった場合、 domain の値は `example.com` として扱われます。
一方で、 `Set-Cookie: foo=bar; domain=example.com` と domain 属性を指定されていた場合、 domain の値は `.example.com` (先頭のドットが大事）として扱われます。

つまり、 domain 属性が指定された Cookie を上書きする際、一見 domain 属性の値が上書きしようとしている Cookie の FQDN と一致しているからといって、 domain 属性を省略すると上書きできません。

```plaintext
Set-Cookie: foo=bar; domain=example.com; path=/
```

として食わされた Cookie は、 CookieManager から

```java
setCookie("http://example.com/", "foo=; max-age=0; path=/");
```

としても削除できないのです。

# この問題の原因に気づきにくいもう一つの理由
この問題の原因に気づきにくいもう一つの理由は、 CookieManager で取得できる Cookie には各種属性が含まれていないことです。
`secure` 属性や `httponly` 属性なんかも見れません。（これらの属性付きで取得する方法をご存じの方がいらっしゃいましたら教えてください。。）
そのため、 domain 属性が異なっていた場合、一見すると値が重複して登録されてしまったかのように見えてしまいます。

```java
cookieManager.setCookie("http://example.com/", "foo=bar; path=/");
cookieManager.setCookie("http://example.com/", "foo=42; domain=example.com; path=/");
Log.d(TAG, cookieManager.getCookie());
// => "foo=bar; foo=42" と表示される
```

# おまけ
CookieManager で Cookie を削除する方法を調べたことがある方なら見たことがあるかもしれませんが、 `CookieManager#setCookie` の JavaDoc には次のように書かれています。

```plaintext
Sets a cookie for the given URL. Any existing cookie with the same host,
path and name will be replaced with the new cookie. The cookie being set
will be ignored if it is expired.
```

これだけ見ると、過去の日付を指定しても Cookie 削除されないんじゃ..？と思ってしまいそうです。
しかし、 [CookieManager の実装を辿っていった先](https://github.com/pwnall/chromeview/blob/master/src/org/chromium/android_webview/AwCookieManager.java#L39-L43)には、次のように書かれています。

```plaintext
Set cookie for a given url. The old cookie with same host/path/name will
be removed. The new cookie will be added if it is not expired or it does
not have expiration which implies it is session cookie.
```

一旦削除してから、新しい値を書き込むかどうかを決めるといった感じでしょうか。
有効期限が切れていないまたは指定されていない場合に追加されるのだと理解しておきます。
railsにおけるバリデーション

バリデーション(Validation)とは、検証という意味です。

では Rails で一体何を検証するのかというと、ユーザが入力したフォームデータを検証します。ユーザは得てして期待していないデータを入力します。例えば、年齢が必須な入力フォームで、年齢の入力内容が漢字だったり、全角数字であったり、そもそも年齢を入力していない場合などです。ユーザがおかしい値を入力してしまうことが決定的な事実である以上、その入力に対して適切な処理をしなければいけません。例えば、期待しないデータを弾き返し、適切なエラーメッセージを表示するなどです。
Wandboxで分離コンパイルをやってみた

#はじめに

TwitterでWandboxのコードを呟いてたら、親切なお方が「分離コンパイルできますよ？」と教えてくれたので早速やってみた。

ついでに、テンプレートの明示的インスタンス化もやってみたかったので書いてみた(というより、テンプレートクラスで分離コンパイルやろうとしていたので、結果的に明示的インスタンス化せざるを得なかった……)

#実際のコード

実際に書いたコードはこちら
https://wandbox.org/permlink/JzhacAWqke6pZtEe

ザクっとコードの解説ー


まず、`TemplateContainer.hpp` からー


```C++:TemplateContainer.hpp

#ifndef TEMPLATE_CONTAINER_HPP_
#define TEMPLATE_CONTAINER_HPP_

#include <vector>

template <typename T>
class Container{
    private:
        std::vector<T> container;
    public:
        void set(T var);
        void show();
};

template class Container<int>;
#endif

```

`#ifndef` と `#endif` はインクルードガードだねー。

で、`std::vector<T> container` というメンバ変数と、`set(T var)` `show()` というメンバ関数を持つContainerクラスを定義している。

で、ヘッダの最後に `template class Container<int>` と記述することが今回のミソの一つ。
これがないと分離コンパイルの時にエラーが発生する。

詳しい解説はこちらが参考になるので参照されたし
[テンプレート関数の宣言と実装を分離する方法](https://qiita.com/MasayaMizuhara/items/37f8c2a5462a4f7f8ea0)
[テンプレート関数の宣言と実装を分離する方法 ( 補足 )](https://qiita.com/MasayaMizuhara/items/b1e3a53f62df88205eb7#_reference-63b82cf040df75ca7fad)

次に、TemplateContainer.cpp の実装部分。

```C++:TemplateContainer.cpp

#include <iostream>
#include "TemplateContainer.hpp"

template <typename T>
void Container<T>::set(T var){
    container.emplace_back(std::move(var));
}

template <typename T>
void Container<T>::show(){
    for(auto&& c : container)
        std::cout << c << std::endl;
}

```

set(T var) は入力されたデータを動的配列 container に格納してる。
show() は 範囲for文（The range-based for statement）使って入力されたデータを一つづつ出力している。

で、最後にmain() のソース

```

#include <iostream>
#include <vector>
#include "TemplateContainer.hpp"

int main(){

    Container<int> cont;
    
    for(int i = 0; i < 1000; i++)
        cont.set(i);
    
    cont.show();
    
    return 0;
}

```

`for文` で 0 ~ 999 までの数字を動的配列に入力してる(999までにしたのは銀河鉄道999が好きだから)。

その後、`set()` で出力させてる。


そいで、ここが一番のキモだけど Wandbox の画面左端にある「Compiler options」に 実装が書いてある `TemplateContainer.cpp` を入力。

これで Wandbox で分離コンパイルができる。
どうも分離コンパイルする際には、実装部分のソースを「Compiler options」に渡してやればいい模様。

より詳しい解説は下記の記事に書かれているので参考にされたし
[君はまだWandboxの真の実力を知らない～C++er目線で～](https://qiita.com/yumetodo/items/ef24708900b0535aa28c)


#おわりに

基本的には、「Compiler options」に実装部分のソースを渡してやればコンパイルできる。
ただ、僕の場合は変にテンプレートクラスを実装と定義に分けてコンパイルしようとしたので変に詰まっちゃったんだけどね……

まあ、普通に実装と定義を分けて書く分には問題ないと思う。
This Handler class should be static or leaks might occur



Handler の派生クラスを非 static class として Activity などに実装すると、次のような警告がでます。

# NG例

```java
public class MyActivity extends Activity {
    private class MyHandler extends Handler {
    }
}
```

```java
public class MyActivity extends Activity {
    private Handler h = new Handler() {
    }
}
```

# 警告
>This Handler class should be static or leaks might occur
Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected.
If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue.
If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.

一つづつ解釈していくと、
> このHandlerクラスは静的である必要があります または リークが発生する可能性があります

(もはやこの時点で、「設計ミスだろ」とつっこみたいところではある・・)

> このハンドラは内部クラスとして宣言されているため、外部クラスがガベージコレクションされない可能性があります。
ハンドラがメインスレッド以外のスレッドのためにLooperまたはMessageQueueを使用している場合、問題はありません。

Worker thread なら問題ないらしい。

> ハンドラがメインスレッドのLooperまたはMessageQueueを使用している場合は、次のようにハンドラ宣言を修正する必要があります。
ハンドラを静的クラスとして宣言します。
外部クラスでは、外部クラスへのWeakReferenceをインスタンス化し、Handlerをインスタンス化するときにこのオブジェクトをHandlerに渡します。
WeakReferenceオブジェクトを使用して、外部クラスのメンバーへのすべての参照を作成します。

結局 Handler 自体は leak してるってことでしょ！
static じゃなければ外部クラス (Activity とか) の instance を保持してしまうのは当たり前で、要は Activity とか leak すると重くなるから気をつけてね。弱参照はアプリでやってね。みたいな・・

# なぜ leak するのか？
こちらにわかりやすくまとめられていますが、
https://www.notice.co.jp/archives/3660

> 0. Handler は Message を Looper へキューイング
0. LooperはキューからMessageを取り出して、HandlerのdispatchHandlerにMessageを渡して、handleMessageで処理させます。
0. HandlerはMessageの中にタスク（Runnableを実装したもの）があれば、そのタスクを実行します。

Main Looper は唯一の存在 (つまり static) で、
その Main Looper は実行する Message を保持していて、
Message は post 先の Handler の instance を保持している。
たとえば、 sendMessageDelayed とかで長時間 Message を保持していた場合、その時間だけ Handler も外部クラスも leak することになる。

という理解で概ね間違ってないと思います。

(やっぱり設計ミスだよね・・？)

# 対策？
上記の理屈でいくと、以下のいずれかの対策をすることで問題を回避できると思われる。

* 長時間 message を保持するような実装をしない
* Handler を static にして、外部クラスを WeakReference で保持する
* WeakReferenceHandler 的なのを作る


# WeakReferenceHandler?
こんな感じ・・？

```java
public class WeakReferenceHandler {
    private final WeakReference<Handler.Callback> mWeakReference;
    
    public WeakReferenceHandler(Handler.Callback callback) {
        mWeakReference = new WeakReference<>(callback);
    }
    
    @Override
    public void handleMessage(Message msg) {
        final Handler.Callback callback = mWeakReference.get();
        if (callback != null) {
            callback.handleMessage(msg);
        }
    }
}
```

こんなんでいいかな・・？
動作確認もしてないのでよくわかりませんが。。
各アプリがこんなことしなきゃいけないのは本当にばかばかしいなぁ。。
android開発で参考になったもの



##kotlin style guide
https://github.com/SmartTechVentures/kotlin-style-guide

##android best practice
https://github.com/futurice/android-best-practices



##project template
https://qiita.com/kgmyshin/items/9c803a21451e603531f0
http://tomoima525.hatenablog.com/entry/2015/07/18/234615


##file template
https://qiita.com/kgmyshin/items/6b34c1f576a73c894f72

今後メジャーなライブラリの説明とかURLを追加して行く
Beastieくんをターミナルに召喚するコマンド

# [bstie](https://github.com/raviqqe/bstie)

だいぶ前に書いたやつですが。
Beastieくんを召喚するコマンドです。
全てのFreeBSDユーザに捧げる。

## 使い方

```shell-session
> bstie

       (_ )
    \\\"  ) ^
      \// \(
      c_c_/_)

  Daemon with you!

```

## インストール

```shell-session
> go get github.com/raviqqe/bstie
```

## まとめ

癒し。`bstie > /etc/motd`とかもよい。
Vimで余分なスペース・改行コードを自動削除するプラグイン

# [vim-non-blank](https://github.com/raviqqe/vim-non-blank)

というプラグインを書きました。
余分なスペース・改行コードをファイル保存時に自動で削除します。

## インストール

[vim-plug](https://github.com/junegunn/vim-plug)を使う場合、

```vim
Plug 'raviqqe/vim-non-blank'
```

## 使い方

ファイルを保存するときに、

```text
foo  $
$
bar baz    $
  $
$
$
```
（$は改行コード）

これが、

```text
foo$
$
bar baz$
```

自動でこうなります。

## 問題点

普通に`autocmd`でコマンド走らせてるだけなので編集履歴がファイル保存時に無駄に更新されます。
オートセーブ有効にしてると辛い。

## まとめ

なんとかならんでしょうか。
[和訳] Docker for Mac vs. Docker Toolbox


この記事は[Docker for Mac vs. Docker Toolbox](https://docs.docker.com/docker-for-mac/docker-toolbox/)を和訳したものです。

もしすでにDocker Toolboxのインストールを行っているなら、Docker for MacとDocker Toolboxの違いとどのように共存できるかを学ぶためにこれらのトピックを読んで下さい。

## Docker Toolboxの環境
* `/usr/local/bin`以下に`docker`,`docker-compose`,`docker-machine`を入れる。
* VirtualBoxをインストールする。
* インストールするときにToolboxは`docker-machine`を使いVirtualBoxのdefaultを呼び、`$HOME/.docker/machine/machines/default`で`boot2docker`を走らせる。

`docker`や`docker-compose`を使う前に、形式的に`eval $(docker-machine env default)`を使えば、VirtualBox上で走るDockerエンジンに命令を投げることができる。

## Docker for Macの環境
* /Applications以下にインストールされる。
* インストール時に`/Applicatoins/Docker.app/Contents/Resources/bin`から`/usr/local/bin`にシンボリックリンクを貼るり、`docker`と`docker-compose`を使えるようにする。

### ここからはDocker for Macを始める前のポイントです。
* Docker for MacはVirtualBoxを使わず[HyperKit](https://github.com/moby/hyperkit)を使います。
* Docker for MacをインストールしてもDockerMachineには影響はありません。インストール時にコンテナとイメージをDocker Toolboxの`default`（もしあるなら）からHyperkitにコピーするように提示します。コピーしても`default`はそのまま残ります。
* Docker for MacはVMにつなげるために`docker-machine`を使いません。
* インストール時にDocker for MacはHyperKit VMを使ってDocker Engineを走らせます。dockerAPIを`/var/run/docker.sock`に見せます。何も設定しなければこれがデフォルトの場所になるので、`docker`,`docker-compose`が使えるようになります。

もしいろいろなVMを使いまわしたいなら、引き続き`docker-machine`を使ってください。詳しくはDocker ToolboxとDocker for Macの共存に載っています。

## Docker for Macのセッティング
1. まずはDocker Toolboxの環境がセットしてあるかの確認

```
$ env | grep DOCKER

DOCKER_HOST=tcp://192.168.99.100:2376
DOCKER_MACHINE_NAME=default
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/Users/victoriabialas/.docker/machine/machines/default
```
もしこのコマンドで何も返って来なければそのままDocker for Macを使ってください。
2. 上の環境を消す
以下のコマンドを実行してください。

```
unset DOCKER_TLS_VERIFY
unset DOCKER_CERT_PATH
unset DOCKER_MACHINE_NAME
unset DOCKER_HOST

# bashの場合はこれでも可能（`zsh`の場合はこれは動きません）
unset ${!DOCKER_*}
```
3. 確認
以下のコマンドで何も返ってこないことを確認してください。

```
$ env | grep DOCKER
```

> ### もしDockerToolboxがインストールされているのに、Docker for Macをインストールすると、、、
> Docker for Macが`docker`と`docker-compose`をシンボリックリンクで上書きしてしまいます

## Docker ToolboxとDocker for Macの共存
両方を使うことは可能です。もし、Docker for Macを使う場合は、DOCKERの環境を消してください。例えばbashなら`unset ${!DOCKER_*}`が使えます。もし`docker-machine`コマンドでVirtualBoxを使いたくなれば、`eval $(docker-machine env default)`(使いたいVMの名前を使ってください)を使えば大丈夫です。
これでDockerToolboxとDocker for Macを切り替えることができます。

## Docker toolsの違うバージョンを使いたいとき
上の共存がうまくいくのは、VirtualBoxの提供している`docker-machine`とDocker for Macのバージョンが同じ時だけです。もし、違うバージョンのDockerEngineを使いたいなら[Docker Version manager](https://github.com/howtowhale/dvm)が役に立つでしょう。

## 構成しているバージョンをチェックしよう
Docker CLIクライアントとDocker Engineは同じバージョンである必要があります。クライアントとサーバーの間に違いがあると、Docker Machineが問題を発生することがあります

もしDocker ToolboxとDocker for Macをインストールしているなら、新しいバージョンのDockerクライアントを手に入れましょう。シェルで`docker version`をすると、クライアントとサーバーのバージョンが分かります。
Jekyllでポスト用ファイルを作成するためのコマンドを自作してみた

## 背景
[Jekyll](https://jekyllrb-ja.github.io/)というGithubが作った静的なCMSがあります。これで自分のブログを始めようとしているのですが、記事を書くためには /_posts というディレクトリに ```%Y-%m-%d-{タイトル}.md``` というmarkdown形式のファイルを作成する必要があります。

毎回今日の日付を確認してファイルを作成するのは面倒なので、

```
$ jekyllpost {タイトル}
```

とコマンドを打てば、自動でファイル名を決めてvimでファイルを開いてくれるコマンドを自作しました。以下がソースコードです。

## ソースコード

```
#!/bin/bash

today=$(date "+%Y-%m-%d")
vim "{プロジェクトルート}/_posts/${today}-${1}.md"
```

## コマンド化方法

```
$ mkdir ~/bin
```

```
$ touch ~/bin/jekyllpost
```

~/bin/jekyllpost に上のソースコードをコピペして、~/bin にPATHを通せばコマンドの出来上がり。
メモ HerokuのPostgresにPlay Frameworkで接続する方法

## DB作製
herokuコマンドでポストグレスDBを作製します。
```
heroku addons:add heroku-postgresql
```
##　確認 
その後Herokuにログインして`https://data.heroku.com/`にアクセスすると先程作製したDBがあるはずなのでクリックします。
遷移先にあるURIの項目をコピーします。

`conf/application.conf`の`db.default.url`にコピーしたURI設定します

## 設定
```
db.default.driver=org.postgresql.Driver
db.default.url="<URI>"
```
という感じになると思います。
Python で int((0.7 + 0.1) * 10)

まぁ、ありがちネタ。

・・・というか、元ネタは[これ](http://php.net/manual/ja/language.types.float.php "php float")

で、このネタに関連して最近書いていない僕の日記に書いたのが[これ](10395.diarynote.jp/200909072116364066/ "SQL C# float")

さて Python では？

```
import math
print(math.floor((0.1 + 0.7) * 10) )
```

上記のコードに対するオーディエンスの意見は[これ！！](https://twitter.com/KAZAMAI_NaruTo/status/925141372666912768)

・・・ごめんなさい。僕には友達はいませんでした。

で、もっとシンプルに

```
int((0.7 + 0.1) * 10)
```

でも確認できた。

```
>>> int((0.7 + 0.1) * 10)
7
```

Python もか。。。。って思ったがちょっと事情が違った。

```
>>> (0.7 + 0.1) * 10
7.999999999999999
````

だった。

・・・「だから何？　浮動小数点型だからおかしくないだろ？？」って話。
Error:A problem occurred configuring project ':app'. > All flavors must now belong to a named flavor dimension. と言われたら

AndroidStudio 3.0からビルドフレーバーの仕様が変更され、ライブラリプロジェクトのビルドフレーバーとアプリプロジェクトのビルドフレーバーが同じものを使うようになりました。また、フレーバーディメンションの設定が必須になりました。これは、例えばある機能に関するビルドフレーバーA, Bと別の機能に関するビルドフレーバーM, Nを指定すると、ビルド時に**これらの組み合わせ**(つまりA-M, A-N, B-M, B-Nという4種類)のビルドフレーバーを作れる機能です。便利ですね！
ビルドフレーバーに関する説明は[こちらの記事](https://qiita.com/boohbah/items/389b159a1693247b15de)に詳しく書かれています。

便利なのはいいですが、そのせいで古いバージョンのAndroidStudioで作ったプロジェクトがそのままではビルドできなくなることがあります。その時に表示されるエラーメッセージはこれです。

    Error:A problem occurred configuring project ':app'.
    > All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html

これを解決するためには、明示的にフレーバーディメンションを指定する必要があります。

ここに古いバージョンのAndroidStudioで作った*build.gradle*があるじゃろ？

```groovy
productFlavors {
     free {
      ...
    }

    paid {
      ...
    }
}
```

これを…こうじゃ！

```groovy
flavorDimensions "myType"

productFlavors {
     free {
      dimension "myType"
      ...
    }

    paid {
      dimension "myType"
      ...
    }
}
```

`myType`とした部分はなんでも良いです。好きな文字列を指定してください。
Docker ImageのAmazonlinuxで日本語の文字コード変換をしたい

#何がしたいか
Docker imageのAmazonlinuxを使った開発環境で日本語を含んだファイルが文字化けしたので、これをなんとかしたい。
https://hub.docker.com/_/amazonlinux/

ファイルの文字コードはCP932であることはわかっていたのだけど、iconvを通してもUTF-8に変換されず、ハマってしまった。

#どう解決したか
DockerfileにENVコマンドを下記のように追加することで解決した。

```Dockerfile:Dockerfile
FROM amazonlinux:latest
RUN yum -y update && yum clean all

～中略～

ENV LANG en_US.UTF-8
```

なぜ`en_US.UTF-8`なのかというと、AWSのEC2でもおそらくデフォルトが`en_US.UTF-8`になっているため(後述)。
少なくとも自分が扱う要件では、`en_US.UTF-8`で問題なかったのでそのままにしている。
このようにしておけば、下記のlocaleが設定されるようになる。

```bsah:bash
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
```

他のlocaleにする必要があるのであれば、それを指定してもらえれば良いと思う。
ただし、Docker imageのAmazonlinuxで最初から用意されているのは下記のlocaleとなっているらしいので、

```bash:bash
$ locale -a
C
en_AG
en_AG.utf8
en_AU
en_AU.iso88591
en_AU.utf8
en_BW
en_BW.iso88591
en_BW.utf8
en_CA
en_CA.iso88591
en_CA.utf8
en_DK
en_DK.iso88591
en_DK.utf8
en_GB
en_GB.iso88591
en_GB.iso885915
en_GB.utf8
en_HK
en_HK.iso88591
en_HK.utf8
en_IE
en_IE@euro
en_IE.iso88591
en_IE.iso885915@euro
en_IE.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ
en_NZ.iso88591
en_NZ.utf8
en_PH
en_PH.iso88591
en_PH.utf8
en_SG
en_SG.iso88591
en_SG.utf8
en_US
en_US.iso88591
en_US.iso885915
en_US.utf8
en_ZA
en_ZA.iso88591
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW
en_ZW.iso88591
en_ZW.utf8
POSIX
```

#EC2ではどうなっていたか
確認に使ったのは下記のAMI。現時点(2017/11/07)では、Management ConsoleからEC2インスタンスの作成でAmazon Linux AMIを選択すれば使用されるAMIとなっている。
`amzn-ami-hvm-2017.09.0.20170930-x86_64-gp2 (ami-2a69be4c)`

上記のAMIを使って作成したEC2インスタンスでは、下記のような locale 設定になっているはず。

```bash:bash
$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
```
[PHP] ゼロから始める PHPUnit + CI (2. CI環境を導入しよう）

# 目次

1. [PHPUnit を導入しよう](https://qiita.com/PruneMazui/items/f70e49963ef40cf0dadd)
2. CI環境を導入しよう（本記事）
3. [コードカバレッジを計測しよう](https://qiita.com/PruneMazui/items/839b437f5e740c46ad09)

# はじめに

この記事の目的や環境情報は[最初の記事](https://qiita.com/PruneMazui/items/f70e49963ef40cf0dadd)を参照。


# 2. CI環境を導入しよう

無料で使えるCI環境は色々選択肢はあるものの、今回は一番メジャー？と思われる [TravisCI](https://travis-ci.org/) を使う。ちなみにプライベートリポジトリは有料。

## 2.1 TravisCI アカウントを登録しよう

**GitHub にログイン**

TravisCI は GitHubアカウントで認証を行う。こちら → [GitHub](https://github.com/)

**TravisCI にサインイン**

[TravisCI](https://travis-ci.org/) に移動し、右上のSign in with GitHubを選択しサインインを完了させる。

![2017-11-07_10h44_14.png](https://qiita-image-store.s3.amazonaws.com/0/31393/b2b010de-3b17-8c41-9d37-28de7eeb8236.png)

**リポジトリの登録**

無事にサインインが済んだら今度は対象となるリポジトリを登録する。
左上の方にある + をクリックするとリポジトリ一覧が出てくる。

![2017-11-07_10h52_14.png](https://qiita-image-store.s3.amazonaws.com/0/31393/2c6ee93d-889f-6735-58d3-4f8f6d99f023.png)

リポジトリ一覧からCIを有効にしたいリポジトリを選んで、スイッチをONにする。（下記の画像はOFF）

![2017-11-07_10h53_51.png](https://qiita-image-store.s3.amazonaws.com/0/31393/9dc9c9f1-3c3d-a19e-1016-cbdefd5b28bc.png)

有効になったらダッシュボード（左上のTravisCIロゴから移動）をに戻っておこう。

## 2.2 TravisCI用の設定ファイルを作ろう

**[COMMIT: TravisCI用の設定ファイルを作ろう](https://github.com/PruneMazui/phpunit-training/commit/9f795c043e125cb5bc4e1a24a3044e80b5071a74)**

TravisCI はリポジトリ直下の .travis.yml を読み込むので、ここにCIの設定を記述する。
設定の書き方は詳しくは[TravisCIのドキュメント](https://docs.travis-ci.com/user/getting-started)を参考に。

```yaml
language: php

php:
  - 7.1

before_script:
  - curl -s http://getcomposer.org/installer | php
  - php composer.phar install
```

- 言語をPHPに指定
- PHPのバージョンを7.1に指定（複数指定すると各バージョンでテストを実行する）
- テスト実行前に composer install コマンドを実行

このコミットをPushしたらTravisCIを見てほしい。なんとCIが動いてるではないか！

![2017-11-07_11h05_20.png](https://qiita-image-store.s3.amazonaws.com/0/31393/4a33401f-7f1b-ed7f-4cd8-f97776caabfb.png)

しばらくするとテストが完了！

## 2.3 GitHubにTravisCIのバッチを貼ろう

**[COMMIT: 2.3 GitHubにTravisCIのバッチを貼ろう](https://github.com/PruneMazui/phpunit-training/commit/c03cb0c54a353f90667f75ac817ca579cd4be0d8)**

**readme.mdの作成**

ない場合は作ってね。

**readme.mdにバッチを貼る**

画像の箇所をクリックするとイメージへのリンクが何種類かの方法で選べるので、Markdown形式の内容をreadme.mdに追記する。

![2017-11-07_11h39_59.png](https://qiita-image-store.s3.amazonaws.com/0/31393/795599f8-b755-4eda-0dbd-155b63372145.png)

この段階で一度もビルドが行われていないブランチはバッチのURLが指定しているブランチをではないことがあるので注意（2017/11/07現在）。

## 2.4 ビルドが失敗したとき通知しよう

実はデフォルトでメールに通知されるようになっている。
他にも[TravisCIのドキュメント](https://docs.travis-ci.com/user/notifications/)にあるとおり、色んな方法で通知が可能。
時代はやはりSlackかな？それ系の記事はいっぱいあるので、ここでは扱わない。

この記事が分かりやすかった。
[図解: Travis CIの結果をSlack通知する方法](https://qiita.com/nwtgck/items/17840855cb76f60fa1fe)

# あとがき

ここまででタイトルの通り PHPUnit + CI の環境は整ったのだけど、
せっかくの作った環境でもテストの網羅性が低いとあまり意味をなさない。

次回はコードカバレッジを計測して、GitHub にバッチを追加するところまでやります。

NEXT. [コードカバレッジを計測しよう](https://qiita.com/PruneMazui/items/839b437f5e740c46ad09)
ちょっとずつ読むドメイン駆動設計 第三部 より深い洞察へ向かうリファクタリング 第九章 暗黙的な概念を明示的にする6  仕様・検証

# 仕様(Specification)

このパターンは、EvansとMartinFawlerの２人が作ったパターンらしいです。

基本は、 あるオブジェクトが何らかの基準を満たしているかどうかを判定するためのオブジェクトです。

例に上がっているのは、「請求書」が遅延しているかどうかを判定するのを、「請求書」クラスが判定するのではなく、「遅延請求書仕様」に「請求書」を渡して判定する。というもの。

遅延しているかどうかの条件として、「猶予期間」や「優良顧客の場合」など、複雑な判定条件が絡んでいるので、別クラスで表現するのは、確かにわかりやすいかもしれないです。

## 仕様のパターン

仕様として、実装できそうな状況・目的として、３つ上げられています。

1. 検証・・・オブジェクトを検証して、何らかの要求を満たしているか調べる（これが上記のパターン）
2. 選択・・・コレクションからある条件を満たしたオブジェクトを選択する
3. 要求・・・何らかの要求に適合するようにオブジェクトを生成する

### 検証

最初の例の発展例として、「請求書仕様」が紹介されています。

「請求書仕様」から複数の複雑な仕様、例えば、「延滞請求書仕様」や「巨額請求書仕様」などに展開しています。

延滞請求書仕様.isSatisfy(請求書)
巨額請求書仕様.isSatisfy(請求書)

という実装方法ですね。
これ使いやすいかもしれないですね。

例えば、
「注文仕様」から、「購入点数超過注文仕様」とか「注文可能合計金額超過注文仕様」とか。

昨日も紹介した、[「現場で役立つシステム設計の原則」](https://www.amazon.co.jp/dp/B073GSDBGT/)の第四章で紹介されているPolicyパターンや、Java8のPredicateと組み合わせるといいかもしれません。

明日も引き続き、選択・要求について読んでいきます。
HoloLensで始める新しいMixed Reality Toolkit - Unity(旧HoloToolkit-Unity) - うっかり忘れそうなこと

# Mixed Reality Toolkit - Unityとして新しくなった。
基本的な使い方はHoloToolkit-Unityとそう変わらないのですが、色々と変わったところがあるMixed Reality Toolkit -Unity（以下MTRK）です。
Mixed Realityなアプリケーションを開発する上ではかなり必須となるライブラリとなっていますが、現在の最新版では開発するアプリケーションの種類に応じて使うバージョンを変える必要があります。
今回はHoloLens向きなアプリを作る上で必要な環境とMixed Reality Toolkit - Unityのサンプルを導入、ビルド時のちょっとしたTipsについて紹介します。

## 必要な環境について

新しいMRTKですが最近はようやく安定してきてUnity 2017.1.X,Visual Studio 2017での開発ができるようになってきました。10/15時点で最新の組み合わせは以下のサイトで検証されています。

[Visual Studio + Unity + MixedRealityToolkit 2017年10月15日現在のベストマッチ - はつねの日記 ](http://hatsune.hatenablog.jp/entry/2017/10/15/215134)

今回はそこまで最新ではないのですが、以下の組み合わせで動作確認をしています。

* Unity 2017.1.0f3
* Vidusl Studio 2017 15.2
* Mixed Reality Toolkit - Unity v1.2017.2.0 \([github](https://github.com/Microsoft/MixedRealityToolkit-Unity/releases/tag/v1.2017.2.0)\)

一応MRTKのところにはUnity 2017.1.2使ってねと書いてますが、一応上記組合わせで動いてはいます。HoloLensの場合この組み合わせでいいんですが、ビルドするときに現状のバージョンではちょっとした落とし穴があります。

## MRTKとサンプルの導入
MRTKとそのサンプルについては全て[github](https://github.com/Microsoft/MixedRealityToolkit-Unity/releases/tag/v1.2017.2.0)でUnityパッケージ化されています。ですので、以下の手順で導入は簡単にできます。

1. [MixedRealityToolkit-Unity](https://github.com/Microsoft/MixedRealityToolkit-Unity/releases/tag/v1.2017.2.0)から以下の2つのUnityパッケージをダウンロードする。<br/>・HoloToolkit-Unity-v1.2017.2.0<br/>・HoloToolkit-Unity-Examples-v1.2017.2.0
2. Unityの起動
3. 新規プロジェクトの作成
4. [Asset]-[Import Package]-[Custom Package]を選択し以下の順序でパッケージのインポートを行う（対象は全て）。<br/>・HoloToolkit-Unity-v1.2017.2.0<br/>・HoloToolkit-Unity-Examples-v1.2017.2.0

## HoloLens用にビルドする
とりあえずビルドするために、HoloToolkit-Examplesの中から適当なシーンを開きます(ColorPickerExample等)。
以降はHoloLens用にビルドするための設定を行っていきます。この際、メニューから[Mixed Reality Toolkit]-[Configure]-[Apply Mixed Reality Project Settings]を選択して設定することで簡単にできるんですが、素直にこの設定使うと実は後々ビルドに失敗します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/a7cc90cd-9672-2247-7006-6d7ec1af3780.png)

[Apply Mixed Reality Project Settings]を選択すると以下のようなダイアログが出てきます。HoloLens用に[Enable XR]はチェックして適用します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/211cae64-a197-bcc3-3616-3048bc461320.png)

この状態で[File]-[Build Settings]を開きます。ダイアログの中から[Player Settings]を押して、Inspectorから[Settings for Universal Windows Platform]-[Other Settings]を開いてください。そうするとなぜか[Virtual Reality SDKs]の設定が「WindowsMR」になっていてビルドしてもHoloLensで動かせないという。。。（何となくバグっぽい？）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/152548/2458de57-bc46-f294-3225-352a7f18a726.png)

対応としては、Virtual Reality SDKsの「WindowsMR」を選択して右下の[-]を押して削除。そのあと、[+]を押して「Windows Holographic」を選択して追加。これでHoloLens用にビルドすることができるようになります。

## そのほか
MRTKになってから実はいくつかの機能追加がされています。GUI部品やユーティリティ等。まだ細かいものは調べていませんが、面白そうなものがあれば紹介したいと思います。
PINE64 with Armbian チートシート


As a small Workstation

![IMG_2728.jpg](https://qiita-image-store.s3.amazonaws.com/0/26038/8489acf4-cfe9-2166-fa95-7daf115c5b6f.jpeg "IMG_2728.jpg")


# 画面解像度を設定する

デフォルトだと720p固定になっています。
これを1080pにしたいです。

`/boot/armbianEnv.txt`の

```
disp-mode=720p60
```

となっている行を、

```
disp-mode=1080p60
```

に書き換えて再起動したら1080pになってくれました。


# CapsLockをCtrlに入れ替える

`/etc/default/keyboard`の`XKBOPTIONS`を以下のように設定する。

```:/etc/default/keyboard
XKBOPTIONS=",ctrl:nocaps"
```

from: https://qiita.com/4486/items/d33ced39dbdb9d222764


# 日本語化する

Application > Settings > Language Support


# mDNSを使えるようにする

えっラズパイだとなにもしなくても使えるやん・・・情弱め
aws-cli command list

#aws-cli command list 

```
$aws configure --profile [NAME]
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: 
Default output format [None]:
```

```
$ ls .aws/
config       credentials
```

```
aws --profile [PROFILE_NAME] ・・・
```

これで複数アカウント(profile)を管理できる。

```
$ aws --profile [PROFILE_NAME] kms encrypt --key-id alias/[ALIAS_NAME] --plaintext "[PLAIN_TEXT]"

{
    "CiphertextBlob": "******************",
    "KeyId": "*****************"
}
```

*PLAIN_TEXTにhttp://とかhttps://とか入れるとpathをみにいっちゃうからなんかerrorになる。
UbuntuのBシェル

#### UbuntuのBシェルはdashというシェルへのシンボリックリンクとなっていて、Bashの拡張変数展開に失敗するので注意。shebang行を #!/bin/sh とすると Bad substitution が発生する。
```lang:dash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.3 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.3 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
$ export LANG=C
$ which sh
/bin/sh
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 May 11 14:15 /bin/sh -> dash
$ ls -l /bin/dash
-rwxr-xr-x 1 root root 154072 Feb 18  2016 /bin/dash
$ dash
$ echo $SHELL
/bin/bash
$ test='ABCDEFG'
$ echo $test
ABCDEFG
$ echo ${test:2:3}    # Bashの拡張変数展開に失敗; Bashならば CDE と表示
dash: 12: Bad substitution
```

#### テキストファイルを読み込んで配列にする場合もエラーが出てしまう。
```
$ cat sports.sh
#!/bin/sh
sports=(`cat sports.txt`)
for sport in ${sports[@]}
do
  echo $sport
done
exit
$ ./sports.sh
./sports.sh: 2: ./sports.sh: Syntax error: "(" unexpected
$ /bin/bash sports.sh
soccer
baseball
...
```
Object.entries() を使ってObject → 配列変換

## 今回やりたいこと

### sample object
```json
{
    "key-1": "value-1",
    "key-2": "value-2",
    "key-3": "value-3"
}
```
これを
### sample list
```json
[
  {
    "key": "key-1",
    "value": "value-1"
  },
  {
    "key": "key-2",
    "value": "value-2"
  },
  {
    "key": "key-3",
    "value": "value-3"
  }
]
```
こうしたい。

せっかくなのでES2017の`Object.entries()`を使ってみました。
例では、先ほどのsample objectを変数名`obj`として用います。

```js
obj = {
    "key-1": "value-1",
    "key-2": "value-2",
    "key-3": "value-3"
}
```

### Object.entries()のみ利用

#### 記述
```js
Object.entries(obj)
```
#### 出力
```json
[
  [
    "key-1",
    "value-1"
  ],
  [
    "key-2",
    "value-2"
  ],
  [
    "key-3",
    "value-3"
  ]
]
```

上記のように[key, value]に変換された配列となります。
これだと今回のやりたいことは満たせていないので、別の方法を使います。

### Object.entries() と map を使う

#### 記述
```js
Object.entries(obj).map(([key, value]) => ({key, value}))
```
#### 出力
```json
[
  {
    "key": "key-1",
    "value": "value-1"
  },
  {
    "key": "key-2",
    "value": "value-2"
  },
  {
    "key": "key-3",
    "value": "value-3"
  }
]
```

map は　配列の要素を引数にして関数の結果から新たに配列を生成するものですが、これを組み合わせました。
`([key, value])` この部分で`Object.entries()`の戻り値を`key`, `value`で受け取り、あとは好きな形の配列にするというもの。

`({key, value})`の部分で、下記のような記述を省略できます。

```js
Object.entries(obj).map(([key, value]) => ({'key': key, 'value': value}))
```

非常にシンプルですね。

## 追記

最初に記述していたsample listの形式が間違っていたので修正しました。
さらにもともとの形式（sample list 2）を出力するための記述例を追加しました。

### sample object
```javascript

obj = {
    "key-1": "value-1",
    "key-2": "value-2",
    "key-3": "value-3"
}
```
これを

### sample list 2
```json
[
  {
    "key-1": "value-1"
  },
  {
    "key-2": "value-2"
  },
  {
    "key-3": "value-3"
  }
]
```
こうしたい場合

#### 記述
```javascript
Object.entries(obj).map(([key, value]) => ({[key]: value}))
```

## おまけ

逆にsample list から sample objectに戻す場合、`Array.prototype.reduce()`をつかう方法をとりました。（もっとスマートな方法はあるかもしれませんが）

例では、先ほどのsample listを変数名`list`として用います。

```js
list = [
  {
    "key": "key-1",
    "value": "value-1"
  },
  {
    "key": "key-2",
    "value": "value-2"
  },
  {
    "key": "key-3",
    "value": "value-3"
  }
]
```

### 記述
```js
// Object.assign
list.reduce((obj, item) => Object.assign(obj, {[item.key]: item.value}), {})

// スプレッド演算子
list.reduce((obj, item) => ({...obj, [item.key]: item.value}), {})
```
### 出力
```json
{
    "key-1": "value-1",
    "key-2": "value-2",
    "key-3": "value-3"
}
```
NSLayoutConstraintをIBOutletで保持する場合の注意点

NSLayoutConstraintをIBOutletで紐づける場合、普通はこうなると思います。

```swift
@IBOutlet fileprivate weak var constraint: NSLayoutConstraint!
```

しかし、このconstraintを非activeにするとマズいことが起きたりします。

```swift
constraint.isActive = false
constraint.constant = 10 /// 強制終了する
```
どうも非activeになったタイミングでretainCountがなくなり、解放されてしまうようです。
そのため、この場合に限ってはweakは付けないのが正解なのかな、と思っています。
本当の正解をご存知の方がいらっしゃいましたらコメントいただけますと幸いです。。
Cognitoに心のなかで謝罪しながら認証を通す

とある静的なWebサイトからCognitoを使って認証したいとき、ありますよね。

でもCognito君はとても親切なので、AWSコンソールからユーザをつくると
（たぶん）内部的にはAdminCreateUserっちゅーAPIが叩かれます。

そうして作成されたユーザのステータスは `FORCE_CHANGE_PASSWORD` 表記になり、
一定期間経過すると利用できなくなってしまいます。

この仕様がネックになってCognito君の親切心に心のなかで謝罪しながら認証を通したい場合がでてくるかもしれません。僕はでてきました。
というわけでこんな感じでやりました。

```js:Login.js
export const getUserPool = () => {
    const poolData = {
        UserPoolId: "<EnterYourUserPoolID>",
        ClientId: "<EnterYourUserPoolClientId>",
    };

    return new Cognito.CognitoUserPool(poolData);
};

export const login = params => {
    const authenticationData = {
        Username: params.username,
        Password: params.password,
    };

    const authenticationDetails = new Cognito.AuthenticationDetails(authenticationData);
    const userPool = getUserPool();
    const cognitoUser = new Cognito.CognitoUser({
        Username: params.username,
        Pool: userPool
    });

    return new Promise((resolve, reject) => {
        const authConfig = {
            onSuccess(result) {
                const user = userPool.getCurrentUser();

                resolve({
                    code: 200,
                    messsage: 'ログインに成功しました。',
                    user: {
                        name: user.getUsername(),
                    }
                });
            },
            onFailure(err) {
                reject({
                    code: 400,
                    message: err
                });
            },
            newPasswordRequired(userAttributes, requiredAttributes) {
                console.log("newPasswordRequired()");
                console.log(userAttributes, requiredAttributes);
                cognitoUser.completeNewPasswordChallenge(params.password, {}, authConfig);
            },
            mfaRequired(challengeName, challengeParameters) {
                console.log("mfaRequired()");
                console.log(challengeName, challengeParameters);
            },
            customChallenge(challengeParameters) {
                console.log("customChallenge()");
                console.log(challengeParameters);
            }
        };
        
        cognitoUser.authenticateUser(authenticationDetails, authConfig);
    });
};
```

### 解説

解説していきます。

仮パスワードユーザがログインしたとき（FORCE_CHANGE_PASSWORDになってる人とか）は、 `newPasswordRequired()` が呼ばれます。
ここで新しいパスワードを入力することでステータスが `CONFIRMED` となってハッピーめでたしめでたしになるっていうのが正規のシナリオです。

でも今回は謝罪したいので、 `ユーザがログインしようとして渡されたパスワードを入力したら勝手に新パスワード入力扱いになって無事ログインできちゃう` みたいな振る舞いを実装します。
まずはCallbackで呼ばれる関数を `authConfig` としてまとめておきます。
これは、 `authenticateUser()` 時に呼ばれることを想定したCallbackですが、再利用性を高めるためにまとめてます。

次に、無事に `authenticateUser()` が叩かれ、 `newPasswordRequired()` Callbackが呼ばれます。
ここが大事なところで、入力されたパスワード（**Cognito的には検証済み**）を渡すことで、
`新しいパスワード入力フェーズ` をパスすることができます。

本当にCognito君ごめんなさい。


### 使い方

```js
import {login} from "./Login"

login
  .then(user => {
    // ログイン成功後処理
  })
  .catch(err => {
    // エラー処理
  });
```