OmniAICreator/Qiita-1.07M huggingface dataset:
Docker 初心者 | サービスについて > docker-compose と docker stack ( 公式チュートリアル part3 より )

[Get Started, Part 3: Services - Docker Documentation](https://docs.docker.com/get-started/part3/) より

# この章で扱うこと

- ロードバランサーでアプリケーションをスケールさせる
- スタック > サービス(今ここ) > コンテナ

# サービスとは

- アプリケーションの各部分は「サービス」と呼び方をする。
  - たとえば動画共有サイトなら、DBを扱うサービスとか、動画本体を扱うサービスとか、フロントエンドのサービスとかいう風に分かれるはず。
- サービスは複数のコンテナによってなる。
- サービスは1個のイメージから実行される。
- スケーリングのためには、1個のイメージをどんなポートで、何個のコンテナで走らせるか、とかいう設定が必要だ。
- 喜んでほしい。 docker-compose.yml を書けば、そんなこと朝飯前さ。

# docker-compose.yml

[公式チュートリアル part2](http://qiita.com/YumaInaura/items/1bf6d76f97d73ae7c804) で作ったイメージを指定して compose ファイルを作る。

```docker-compose.yml
version: "3" # この compose ファイルのバージョン
services:
  web:
    image: yumainaura/get-started # 自分のレポジトリのイメージ # python で Web サーバーを起動する
    deploy:
      replicas: 5 # 起動するプロセスの数
      resources:
        limits:
          cpus: "0.1" # CPUの上限値
          memory: 50M # メモリの上限
      restart_policy:
        condition: on-failure
    ports:
      - "80:80" # localの80番ポート:dockerの80番ポート をつなげる
    networks: # ネットワーク設定 (トップレベルに指定したものから選ぶ)
      - webnet
networks: # トップレベルのネットワーク設定
  webnet:
```

# swarm

このコマンドを打っておく。意味については今後の章で明らかにされるらしい。

```
$ docker swarm init
```

# アプリケーションを起動

`getstartedlab` というアプリケーション名を与えてデプロイする。
( 実行ではなくデプロイという扱い )

```
$ docker stack deploy -c docker-compose.yml getstartedlab
```

# コンテナの確認

同じくアプリケーション名を与えてプロセスを確認する。

```
docker stack ps getstartedlab
```

`docker-compose.yml` で `replicas: 5` に設定してあるため、コンテナが5個起動している。
この replicas の設定を増やすだけで、スケールさせることが出来る。

```
ID            NAME                 IMAGE                          NODE  DESIRED STATE  CURRENT STATE           ERROR  PORTS
4hyp9xra2dmt  getstartedlab_web.1  yumainaura/get-started:latest  moby  Running        Running 45 seconds ago         
60ns7v9asl31  getstartedlab_web.2  yumainaura/get-started:latest  moby  Running        Running 46 seconds ago         
9o8clta8fpq9  getstartedlab_web.3  yumainaura/get-started:latest  moby  Running        Running 46 seconds ago         
w3tlfu97uffx  getstartedlab_web.4  yumainaura/get-started:latest  moby  Running        Running 46 seconds ago         
ybvi20wefg95  getstartedlab_web.5  yumainaura/get-started:latest  moby  Running        Running 46 seconds ago         
```

# アクセスしてみる

http://localhost/ を見てみる。

ページを更新するたびにサーバーのホスト名が変わり、全部で五種類あるのが分かると思う。

![image](https://qiita-image-store.s3.amazonaws.com/0/89618/22723a1c-0758-7178-9e2f-4b09e8a52a86.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/89618/07bceeb8-e263-65d5-f350-591b239a13db.png)

# アプリケーション終了

アプリケーション名を指定して `rm` する。

```
$ docker stack rm getstartedlab
```

# 参考

- [Compose file version 3 reference - Docker Documentation](https://docs.docker.com/compose/compose-file/)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
アバターをテレポートさせるスクリプト

このスクリプトとランドマークをオブジェクトの中に入れてください。
タッチしたアバターをランドマークの場所にテレポートさせます。

```LSL:Teleport.LSL

key avator;
string lm_fname;
vector pos = ZERO_VECTOR;
vector look_at = ZERO_VECTOR;

default
{
    state_entry()
    {
        lm_fname = llGetInventoryName(INVENTORY_LANDMARK,0);
    }
 
    touch_start(integer total_num)
    {
        avator = llDetectedKey(0);
        llRequestPermissions(avator, PERMISSION_TELEPORT);
    }
    
    changed(integer change)
    {
        if(change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
 
    run_time_permissions(integer perm)
    {
        if(PERMISSION_TELEPORT & perm)
        {
            llTeleportAgent(avator, lm_fname, pos, look_at);
        }
    }
}

```
Haskellでletとcaseを一緒に使おうとしてインデントルールにハマった

# TL; DR

こういうコードを書いて、

```haskell
f y =
    let y = case x of
        0 -> 0
        _ -> 1
    in y
```

`parse error on input ‘->’` というエラーメッセージが出たら、

```haskell
f x =
    let y = case x of
            0 -> 0
            _ -> 1
    in y
```

こう書き換えればコンパイルが通ります。


# 再現コード

このコードが最小再現コードになります。調査環境は IDE One（ghc 8.0.1）です。

```haskell
f x =
    let y = case x of
        0 -> 0
        _ -> 1
    in y
```

注: 言うまでもないかもしれませんが、このコードは

```haskell
f 0 = 0
f _ = 1
```

と書くべきです。これはあくまでコンパイルエラーを起こすためのコードであり、実際にはここまで単純なコードではない（このような書き換えができない）ものと考えてください。


# なぜエラーになるのか

まず前提として、Haskell の let 式の書式はこうです。

```haskell
let x = 0
    y = 1
in x + y

{-
let 変数名1 = 式1
    変数名2 = 式2
in 式0
-}
```

したがって、エラーになるコードをコンパイラが見ると

```haskell
let y = case x of
    0 -> 0
    _ -> 1
in y
```

let の2行目では `変数名 = 式` の形が来ると予想しているために、エラーになります。`0` は変数名として不正なのでそこでエラーになって欲しいところですが、実際にエラーメッセージが表示されるのは `->` の部分になります。

つまり、コンパイラにとっては `0 -> 0` や `_ -> 1` は case ではなく let に属しているように見えているということです。人間にとっては `0 -> 0` が case の一部なのは自明ですが、以下のようなコードであればどうでしょうか。

```haskell
let y = case x of
    z -> 0
    w = 2
in y + w
```

case がどこまで続いているのか、let で束縛されるのはどれか、すぐに判別できたでしょうか。コンパイラとしては、`z` や `w` を見ただけではこれが let の一部なのか case の一部なのかわかりません。決定しようとすれば次のトークンである `=` か `->` を見る必要があります。しかしそれではパースが大変になるので、Haskell は文法を簡単にする道を選んだのでしょう。


# 解決方法

`0 -> 0` が let と case のどちらに属するかわからないのですから、インデントにより明確化すれば OK です。

```haskell
let y = case x of
        0 -> 0
        _ -> 1
in y
--  ^ let
--      ^ case
```

let と case で合わせて 2段階インデントを深くすればいい訳です。

なお、case の範囲さえわかればいいので、次のような書き方でも問題ありません。

```haskell
let y = case x of {
    0 -> 0;
    _ -> 1;
    }
in y
```

# ~~インデントルールの闇~~そんなことなかった

**追記: 以下の記述は誤りです。詳細はコメント欄を参照してください。**

以下のコードで、`f` はコンパイルでき `g` はコンパイルできません（in IDE One Haskell	ghc 8.0.1）。なぜだかわかりますか？

```haskell
-- OK
f x =
  let y = case x of  -- 2 spaces
       0 -> 0        -- 2 + 4 + 1 spaces
       _ -> 1
  in y
```

```haskell
-- OK
f x =
    let y = case x of  -- 4 spaces
         0 -> 0        -- 4 + 4 + 1 spaces
         _ -> 1
    in y
```

```haskell
-- OK
f x =
        let y = case x of  -- 1 tab (8 spaces)
                0 -> 0     -- 2 tabs (8 + 4 + 4 spaces)
                _ -> 1
        in y
```

```haskell
-- Error
g x =
    let y = case x of  -- 4 spaces
        0 -> 0         -- 4 + 4 spaces
        _ -> 1
    in y
```

```haskell
-- Error
g x =
  let y = case x of  -- 2 spaces
      0 -> 0         -- 2 + 2 + 2 spaces
      _ -> 1
  in y
```

~~どうやら Haskell は、インデントは 4スペースでするもの、という前提を持っているようです。`let` の前のスペースの数に関わらず、`let`の桁位置から4+1スペース離れれば let とは別のものとして扱っています。とにかく、余計な混乱を防ぐには、~~

~~**Haskell のインデントはスペース 4 つを使え**~~

~~ということのようです。ところで、その割に2スペースでインデントされたコードをよく見るのはなぜなんでしょうか。この挙動を制御するようなコンパイルオプションがあるとか？~~
Archiveの時だけheader "ModuleName-swift.h" not foundが出てコンパイル出来ない時

Embedded Frameworkとかでモジュール分けている時にデバッグビルドは出来るのに、
アーカイブしようとすると`header "ModuleName-swift.h" not found`と言われて出来ない時がある。

今回の場合は、App extension等のターゲットにそのモジュールが巻き込まれていないのが問題で
AppExtensionのターゲットのBuild PhaseのTarget Dependenciesに対象のモジュールを指定すればちゃんと通った。
[golang]FCMの単一iOS端末にリッチ通知を送る

http://qiita.com/noppefoxwolf/items/35795c620c3ed36d6f46

では普通の通知だったので、iOS10からのリッチな通知を送ってみる。

```
package main

import (
	"bytes"
	"encoding/json"
	"net/http"
)

func main() {
	PostToFCM(
		"##KEY##",
		"hello",
	)
}

type FCMParam struct {
	To           string          `json:"to"`
	Notification FCMNotification `json:"notification"`
	Priority     int             `json:"priority"`
}
type FCMNotification struct {
	Title          string `json:"title"`
	Subtitle       string `json:"subtitle"`
	Body           string `json:"body"`
	Badge          int    `json:"badge"`
	Sound          string `json:"sound"`
	MutableContent bool   `json:"mutable_content"`
	ImageUrl       string `json:"image-url"`
}

func PostToFCM(to string, body string) error {
	n := FCMNotification{
		Title:          "title",
		Subtitle:       "subtitle",
		Body:           body,
		Badge:          0,
		Sound:          "default",
		MutableContent: true,
		ImageUrl:       "https://hogehoge.com/hoge.jpg",
	}
	params := &FCMParam{
		To:           to,
		Notification: n,
		Priority:     10,
	}
	b, err := json.Marshal(params)
	jsonStr := string(b)

	req, err := http.NewRequest(
		"POST",
		"https://fcm.googleapis.com/fcm/send",
		bytes.NewBuffer([]byte(jsonStr)),
	)
	if err != nil {
		return err
	}

	// Content-Type 設定
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "key=##KEY##")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return err
}

```

重要なのはここだけで、

```
		MutableContent: true,
		ImageUrl:       "http://hogehoge.com/hoge.jpg",
```

mutable_contentをtrueにして適当なキーでurlを送ればいい。

# iOSで取得する

↑で飛ばしたimage-urlはiOS側のNotificationServiceの
`didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void)`

で`request.content.userInfo["gcm.notification.image-url"]`で拾える。プリフィックスが付くので注意。
あとATSの設定がextension毎にあるのでNotificationService側も設定しておかないとhttpの画像送ると出てこない。
SYN cookies設定メモ

IPAの[DoS攻撃](https://www.ipa.go.jp/security/fy14/contents/soho/html/chap1/dos.html)一覧には他の攻撃も載っているが、今回はSyn floodについて。

## SYN flood攻撃

https://ja.wikipedia.org/wiki/SYN_flood

* インターネットにおけるDoS攻撃（サービス拒否攻撃）のひとつ。インターネット上に公開されているウェブサーバなどの負荷を増大させ、対象となるサイトを一時的に利用不能に陥らせてしまう効果がある。

>  防御としてはSYN cookiesというものがあります。

* [サービス不能になってしまうSYN FLODD攻撃を防ぎたい - ITmedia エンタープライズ](http://www.itmedia.co.jp/help/tips/linux/l0105.html)

### Linuxで防御

```bash:syn_cookie有効化
echo 1 > /proc/sys/net/ipv4/tcp_syncookies 
```

> 上記の設定によって，蓄積キュー（SYN）があふれた場合には送信元にsyncookieが送信される。
> ただし，この機能によって一般的なソケット蓄積の概念が放棄されるため，正常なアクセスによってサーバが過負荷になった場合でも，アクセス側に正常なエラーメッセージが送信されない可能性があるのだ。

## Ciscoルータで防御

* [CiscoルータでSYN-Floodを回避 - すだちっこのOrdinary Days](http://kashigeru.hatenablog.com/entry/2014/03/12/095257)

```
ip tcp intercept list【ACL】
ip tcp intercept mode【intercept/watch】
```

## [Fortinet](http://www.fortinet.co.jp/)製品で防御

![スクリーンショット_2017-05-21_04-42-05.png](https://qiita-image-store.s3.amazonaws.com/0/25728/8fb9a135-289a-b3d5-4c04-37cc1518224e.png)

----

## ingress/egress filtering

SYN flood 攻撃の送信元アドレス偽装への対策

* [送信元 IP アドレスを詐称したパケットのフィルタリング](https://www.jpcert.or.jp/tips/2005/wr053201.html)
* [インターネット用語1分解説～イングレスフィルタリングとは～ - JPNIC](https://www.nic.ad.jp/ja/basics/terms/ingress-filtering.html)
MVC とは何かを 1 から学ぶ

SpringMVC を使ってプログラムを書く中で、"そもそも MVC とは何か" "MVC の利点と問題点は何か" "では問題に対してどうすれば良いのか" をきちんと整理しておこうと思い、書き起こしてみました。

今回はまず MVC とは何かという全体概要、 M/V/C それぞれの役割、MVC の利点と問題点について記載しています。

認識違い等あれば、是非ご指摘下さい。

# MVC とは
UI を持つアプリケーションアーキテクチャの一つ。
Model / View / Controller の 3 部プログラム構造。

# MVC それぞれの役割
## M : Model
* ビジネスロジックの実行
* アプリケーションが扱うデータの操作
* 業務屋さん

## V : View
* ユーザからの画面入力
* ユーザへの結果出力
* Model のデータの状態を参照して画面に表示
* レンダリング人

## C : Controller
* 入力情報を受取る
* 処理を行う Model と結果を返す View を選定
* 司令塔

イメージ図
![SpringMVC.png](https://qiita-image-store.s3.amazonaws.com/0/147552/2ddbe9a4-87f5-93cb-174e-085bf13db82a.png)



# MVC の利点
* ビジネスロジック部分 (M)、画面表示部分 (V)、入力に応じてこれらを操作する部分 (C) と役割分担することで、アプリケーション開発も効率的に分業出来る
* M、V、C の役割分担によりプログラムの独立性が高くなり、仕様変更に柔軟対応出来る

# MVC の問題点
* 業務で扱うデータ要件が複雑になればなるほど、Model が肥大化していく
* 入力に応じた出力要件が複雑になればなるほど、Controller と View の依存性が高くなる

例) View 上の Link 選択結果（ = ユーザの入力内容）に応じる Controller が変わり、各処理結果に対応する View が更に変わる、、、が繰り返される場合

![ControllerとView.png](https://qiita-image-store.s3.amazonaws.com/0/147552/fb58e46b-cfde-7f53-da3f-e9d429a5f03a.png)






---
次回は、上記に挙げた MVC の問題点に対してどういう対処があるか？ について纏めたいと思います。
gitでブランチが作成された日付を調べたい

あれ、このブランチいつ切ったんだっけ？ブランチの作成日付が調べたい。こんな経験ありませんか？ありますよね。そんなあなたに悲報です。

#ブランチの作成日付を調べることはできない

できません。なぜなら記録されていないからです。gitにおけるブランチ[^1]の実体は単なるコミットの参照であり、ブランチ作成時に新しいオブジェクトが作成されるわけではありません。よって日付も記録されません。
（参考：[Gitのリポジトリの中身をなるべく正確に理解する | To Be Decided](https://www.kaitoy.xyz/2015/12/27/git-repository/)）

#じゃあどうするか

代わりに「ブランチを切った時点での最新コミット」を調べましょう。そのコミットと次のコミットの間にブランチが作成されたことになります。

まずブランチへのチェックアウト履歴を調べます。

```
git reflog |grep checkout |grep <ブランチ名>
 
# 8bb5062 HEAD@{0}: checkout: moving from development to master
# 8e092f6 HEAD@{3}: checkout: moving from master to development
# 43d351a HEAD@{6}: checkout: moving from development to master
# 43d351a HEAD@{9}: checkout: moving from master to development

```

複数行出力される場合は一番下、HASH値「43d351a」が指すのが最初のチェックアウトです。この時の最新コミットが作成された日時を調べます。

```
git show 43d351a

# commit 43d351ac8870b26742c32944f674e7e91ad76669
# Author: Inoue <inoue@test.com>
# Date:   Sun May 21 01:54:26 2017 +0900
# 
#     initial commit on branch
# 
# (以下略)
```

というわけで、2017年5月21日1時54分以降に作成されたブランチなんだろうなーくらいのことがわかりました。何らかの事情で正確なブランチ作成日付が知りたい場合は自分で記録しておきましょう。

参考：[How to determine when a Git branch was created? - Stack Overflow](http://stackoverflow.com/questions/2255416/how-to-determine-when-a-git-branch-was-created)


[^1]: 本記事ではローカルブランチを指します。
Ubuntu16.04でLaTeXの環境構築

platexとdvipdfmxを使うための環境構築メモ。

#Ubuntu16.04にTeXをインストール
プレインストールのtexだとbeamerとかうまく動かないのでtexliveをインストールする。

```shell-session
sudo apt-get install texlive
sudo apt-get install texlive-lang-cjk
sudo apt-get install texlive-fonts-recommended texlive-fonts-extra
```

#パッケージのインストール
コンパイルをした時にパッケージが見つからないというエラーが出た時などはwebからソースをダウンロードしてきて、適切なディレクトリに配置する。ソースのファイルの種類によって手順が多少違う。

##ソースが.styファイルの場合
ソースが.styファイルで書かれている場合はファイルをTeXが読み込めるディレクトリに配置する。ディレクトリは/usr/share/texlive/texmf-dist/tex/latex/など。設定によって異なるので/usr以下で.styファイルが置かれているディレクトリを探す。ファイルをディレクトリにコピーしてmktexlsrを実行。

```shell-session
sudo cp <package_name>.sty /usr/share/texlive/texmf-dist/tex/latex/
sudo mktexlsr # TeXのパッケージのリスト(ls-R)を作成するコマンド
```

## ソースが.insと.dtxファイルの場合
以下のコマンドで.styファイルを作成できる。作ったらあとは上と同じ。

```shell-session
platex <package_name>.ins
```

#参考になるサイト
[CTAN](http://ctan.org):　Texのパッケージが色々置いてある。
[TeX wiki](https://texwiki.texjp.org/): 日本語版のTexのwiki。困ったらここを見るとある程度解決するかも。
chainerのvariableについて

#ChainerのVariable関連
本記事はpython3.xを想定しています。またpython素人なのでご了承ください。機械学習で最初に私がやりたかったのは自分で用意したデータセットに対してなんらかの学習を実行することだったのですが、最初に詰まったのがこのvariableでした。

```py
import numpy as np
import chainer as Variable
```

chainerを使って定義した機械学習ネットワークにデータを投げる時には型をVariableにしなければいけません。その時、引数に与えるデータは常にnp.arrayを用いる必要があります。このnp.arrayはpythonのnumpyで用いられる配列のことで、python標準のリスト([])とは異なります。Chainerのドキュメントを見ると、variableについて指定できるのは
[*data – Data array of type either numpy.ndarray or cupy.ndarray.*]
と記述されていますのでリストのデータをそのまま使うのではなく、一度numpyの配列に変換する必要があります。また浮動小数点を用いる場合、float32への変換も必要になることがあります。float32にする理由はchainerがfloat64に対応していないのでエラーが起こるからだったと思います。今回はvariableまでの変換のパターンをいくつか考えてみました。

例1: **配列**

```py
x_train = [0,0,0,0,0]
x_np_train = np.array(x_train, dtype=np.float32)
x_val_train = Variable(x_np_train, 1)
```

とすることによって配列をfloat32を指定しつつnp.arrayに変換し、それをさらにんvariableに変換しています。

例2: **多次元配列**
同様の手順でいけます。

```py
x_train = [[0.1, 0,2],[0.3, 0.4]]
x_np_train = np.array(x_train, dtype=np.float32)
x_val_train = Variable(x_np_train, 1)
```

例3: **np.arrayがすでに存在する場合**

```py
x_train = [[0.1, 0,2],[0.3, 0.4]]
x_np_train = np.array(x_train)
x_np_train.dtype
```

とするとdtype('float64')となっています。最初からnp.arrayのデータを扱う場合float32にキャストしなければいけないことが多々あると思います。

```py
x_np_train.dtype = np.float32
x_val_train = Variable(x_np_train, 1)
```

例4: **Variableが他の型ですでに作られている**

```py
x_train = [[0.1, 0,2],[0.3, 0.4]]
x_np_train = np.array(x_train, dtype=np.float64)
x_val_train = Variable(x_np_train, 1)
x_val_train.data.dtype
```

とした場合、dtype('float64')と表示されます。
このままではエラーが出てしまうため

```py
x_val_train.data.dtype = np.float32
x_val_train.data.dtype
```

とすると、dtype('float32')と表示されます。
Railsのdeviseでactionごとにlayoutを変える

## 状況

/user/sing_upと/user/settingで別のlayoutを指定したい

## 方法

[How To: Create custom layouts](https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts)

ここにdeviseでlayout変更の方法が書いてある。けどlayout onlyをそれぞれ書いても1行目しか実行されないのでアクションごとの指定ができない。

registrations_controller.rbにメソッド追加する。

```ruby
private
def set_registrations_layout
  if action_name == 'new'
    "hoge"
  else
    "huga"
  end
end
```

で、

```
layout :select_layout
```
を指定すればオーケー
【IIS10】レスポンスヘッダを隠す！【Windowsサーバ2016】

# はじめに
Windows Server2016で自宅サーバ立ててみたよ！
そしたら、なんかヘッダー情報とか全部丸見えになってるので、ちょっと困る。
![04.jpg](https://qiita-image-store.s3.amazonaws.com/0/63338/a197aeb2-d353-2b98-afaf-7b7c8ebec882.jpeg)

なので、隠します。


# 設定方法
サーバーマネージャーのメニューの、
[ ツール ]＞[ インターネットインフォメーションサービス（IIS）マネージャー ]
を選択し、サーバーマネージャーを起動します。

---

そんでもって、その中の「構成エディター」を起動します。
![01.jpg](https://qiita-image-store.s3.amazonaws.com/0/63338/b64a7e52-7f73-1403-f2f2-4757ad1e4be3.jpeg)

---

上のドロップダウンから、「`requestFiltering`」を選択
![02.jpg](https://qiita-image-store.s3.amazonaws.com/0/63338/44b1f2bb-3238-f9f5-28f9-6e3aa2cef1ca.jpeg)

---

`removeServerHeader`を`True`にします。
![03.jpg](https://qiita-image-store.s3.amazonaws.com/0/63338/ea7a4da7-7781-e48d-b9b9-300bfbe7de9d.jpeg)

---

で、右側の「適応」を押せばOKです！


# 結果
見事消えてますね！
![05.jpg](https://qiita-image-store.s3.amazonaws.com/0/63338/b3b343f2-bd4f-5b6b-8e30-e4161427982b.jpeg)


# 参考
[Disabilitare le HTTP Response Headers in IIS 10](https://www.devadmin.it/2017/04/18/disabilitare-le-http-response-headers-in-iis-10/)
FuelPHPでindex.phpやpublicを外せない時

# 概要

通常のURLは下記のようになります。

```
http://example.jp/プロジェクト名/public/index.php/コントローラ名/アクション名/パラメータ
```

このURLから邪魔なpublicやindex.phpを消す方法は検索すると下記の方法が出てきます。

[FuelPHPのURLからpublicを消す](https://gist.github.com/kaipu1224/5432466)
[【FuelPHP ver1.7.1】URLのindex.phpを取る](http://qiita.com/kiimiiis/items/507d293976fe87e7f0b9)

しかし、自分はこの手順を踏んでも何故か上手く行かず、訳がわからなくて死にました。


# 原因

なんとなく.htaccessが読み込まれていないような感じがしたので、試しに.htaccessに下記のようにエラーが起こりそうな文字を入れてみました。

```
<IfModule mod_rewrite.c>
  ...
  # Remove index.php from URL
  errorrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
  RewriteCond %{HTTP:X-Requested-With}	!^XMLHttpRequest$
  RewriteCond %{THE_REQUEST}				^[^/]*/index\.php [NC]
  RewriteRule ^index\.php(.*)$			$1 [R=301,NS,L]
  ...
</IfModule>
```

するとエラーが起きなかったので、やはり.htaccessが読み込まれていないと思いhttpd.confを確認してみました。しかし、httpd.confの設定では `AllowOverride All` になっていたので、問題はhttpd.confでは無かったです。

次に、 `mod_rewrite.c` が存在しないのでは無いかと思い、.htaccessの `<IfModule mod_rewrite.c>` の外にエラーが起こりそうな文字を入れてみました。

```
errorrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
<IfModule mod_rewrite.c>
  ...
  # Remove index.php from URL
  RewriteCond %{HTTP:X-Requested-With}	!^XMLHttpRequest$
  RewriteCond %{THE_REQUEST}				^[^/]*/index\.php [NC]
  RewriteRule ^index\.php(.*)$			$1 [R=301,NS,L]
  ...
</IfModule>
```

すると予想通りエラーが起きたので、 `mod_rewrite.c` が存在しないとわかりました。


# 解決方法

httpd.confで `mod_rewrite.c` がコメントアウトされていたので、コメントアウトを外して対応しました。

```
#LoadModule rewrite_module libexec/apache2/mod_rewrite.so
↓
LoadModule rewrite_module libexec/apache2/mod_rewrite.so
```


# まとめ

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">&lt;IfModule&gt;がある.htaccessの設定で詰んだら、そもそも&lt;IfModule&gt;がhttpd.confで読み込まれているか確認しよう！</p>&mdash; 焼きそばメロンパン@🍣 (@ice_arr) <a href="https://twitter.com/ice_arr/status/865955703818665984">2017年5月20日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
GoogleCloudPlatform Natural Language API の導入から、使い方まで

# GoogleCloudPlatform Natural Language API の導入から、使い方まで

+ 完全に私の備忘録です。GoogleCloudPlatformをGCPと表現します。Mac OS Sierraを用いています。

## SDKをダウンロード

+ virtualenvで2.7系を入れてから、実行する

https://cloud.google.com/sdk/docs/quickstart-mac-os-x?hl=ja


+ 認証まで。

https://cloud.google.com/natural-language/docs/common/auth?hl=ja#set_up_a_service_account

```bash
export GOOGLE_APPLICATION_CREDENTIALS="/Users/users/hoge/key.json"
```


## Google Cloud Natural Language APIの準備

https://cloud.google.com/natural-language/docs/getting-started?hl=ja

## python バインディング

https://github.com/GoogleCloudPlatform/google-cloud-python python3.6も対応している


----



```bash
pip install --upgrade google-cloud
gcloud auth application-default login
```


+ API 情報はここでみよう！！！

https://googlecloudplatform.github.io/google-cloud-python/stable/language-responses.html#google.cloud.language.entity.Entity

+ api tutorial

https://googlecloudplatform.github.io/google-cloud-python/stable/language-usage.html
を参考に、以下のように便利クラスを作ります：

```python
from google.cloud import language
class GCNaturalLanguage(object):
    def __init__(self, upper=10000):
        # Instantiates a client
        self.client = language.Client()
        self.upper = upper

    def get_entity(self, text):
        length = len(text)

        if length > self.upper:
            print("{} .. too long".format(length))
            return {}

        document = self.client.document_from_text(text, language='ja')

        # Detects the sentiment of the text
        res = document.analyze_entities()
        print("{} characters => done!".format(len(text)))
        dic = {}
        for entity in res.entities:

            for m in entity.mentions:
                dic.update({m.text.begin_offset: m.text.content})

        return dic
```

例) 

```python
import GCNaturalLanguage
gcn = GCNaturalLanguage()
dic = gcn.get_entity("アクセス解析でクロスドメインを設定してみた")
print(dic)
# 21 characters => done!
# {0: 'アクセス解析', 7: 'クロスドメイン'}
```

ちなみに、MeCabでは、

```bash
# 拡張辞書としてポピュラーなmecab-ipadic-neologd を利用してます
$ mecab -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd
アクセス解析でクロスドメインを設定してみた
アクセス解析	名詞,固有名詞,一般,*,*,*,アクセス解析,アクセスカイセキ,アクセスカイセキ
で	助詞,格助詞,一般,*,*,*,で,デ,デ
クロス	名詞,サ変接続,*,*,*,*,クロス,クロス,クロス
ドメイン	名詞,一般,*,*,*,*,ドメイン,ドメイン,ドメイン
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
設定	名詞,サ変接続,*,*,*,*,設定,セッテイ,セッテイ
し	動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
て	助詞,接続助詞,*,*,*,*,て,テ,テ
み	動詞,非自立,*,*,一段,連用形,みる,ミ,ミ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
EOS
```

となりました。
「アクセス解析」は前者、後者ともうまく言っていることがわかります。(ちなみに、`mecab-ipadic-neologd`を引数に取らず、直接`mecab`として、形態素解析を行なった場合は、「アクセス」と「解析」が分離してしまうという事態が起こってしまいます)

しかし、例えば、「クロスドメイン」という専門用語を抜き出したい場合は、MeCabでは直接抜き出せないので、外部ツールであるGCP Natural Language APIを用いると、目的が達成されることになります。
この先の使用方法としては、GCPで抜き出せたものを新語としてユーザー辞書登録した上で、MeCabを再度利用するというような感じで使って見ると良いです[^add]。

[^add]: http://qiita.com/knknkn1162/items/8c12f42dd167aae01c02#_reference-aa421a94c959d84ff7fb に詳細を書きました。
1. SELECT ... FOR UPDATE ⇒ 2. DDL(待機) ⇒ 3. UPDATE ⇒ 1. COMMIT ⇒ 2. DDL流れる ⇒ 3. ROLLBACK でどうなるか？(Oracle Database)


これもやってみましたやで彡(ﾟ)(ﾟ) まずはテストデータから。

```sql
テストデータ
SELECT C1 FROM TBL_A;

        C1
----------
         1
         2
```
　

* Session1(SELECT ... FOR UPDATE文)

```sql
SELECT 1 FROM TBL_A WHERE C1 = 1 FOR UPDATE;

         1
----------
         1

23:05:42 SQL>
```
　

* Session2(ALTER TABLE文)

```sql
※待たされる
ALTER TABLE TBL_A ADD (C2 VARCHAR2(10));
```
　

* Session3(※Session1とは異なるレコードをUPDATE)

```sql
※すぐ実行される
UPDATE TBL_A SET C1 = 3 WHERE C1 = 2;

1 row updated.

23:05:58 SQL>
```
　

* Session1の続き(COMMITしてロック解放)

```sql
COMMIT;

Commit complete.

23:06:26 SQL>
```
　

* Session2の続き

```sql
※待たされていたDDLが流れる。
Table altered.

23:06:26 SQL>
```
　

* Session3の続き(ROLLBACK)

```sql
※上手く行く。
ROLLBACK;

Rollback complete.

23:06:30 SQL>
```

結局ロックが競合するポイントが最初の

> Session1のFOR UPDATE ← Session2のALTER文

しか無いので、あとは流れちゃうんですやね。彡(ﾟ)(ﾟ)
Unity Loopの速度比較

#検証コード
```csharp:LoopTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LoopTest : MonoBehaviour 
{
	static readonly int TEST_COUNT = 10000;
	static readonly int ARRAY_NUM = 1000;
	int[] _LoopArray = new int[ARRAY_NUM];

	List<int> _LoopList = new List<int>();

	// Use this for initialization
	void Start () 
	{
		for (int i = 0; i < ARRAY_NUM; i++) {
			_LoopArray [i] = i;

			_LoopList.Add (i);
		}
	}
	
	// Update is called once per frame
	void Update () 
	{
		if(Input.GetKeyDown(KeyCode.A))	
		{
			Test1 ();
		}

		if(Input.GetKeyDown(KeyCode.S))	
		{
			Test2 ();
		}
	}

	void Test1()
	{
		var start = Time.realtimeSinceStartup;

		for (int test = 0; test < TEST_COUNT; test++) {
			for (int i = 0; i < ARRAY_NUM; i++) {
				var a = _LoopArray [i];
			}
		}

		var lap1 = Time.realtimeSinceStartup - start;

		start = Time.realtimeSinceStartup;

		for (int test = 0; test < TEST_COUNT; test++) {
			for (int i = 0; i < _LoopArray.Length; i++) {
				var a = _LoopArray [i];
			}
		}

		var lap2 = Time.realtimeSinceStartup - start;


		start = Time.realtimeSinceStartup;

		for (int test = 0; test < TEST_COUNT; test++) {
			foreach(var value in _LoopArray){
				var a = value;
			}
		}

		var lap3 = Time.realtimeSinceStartup - start;

		Debug.Log (lap1);    //0.08274078sec
		Debug.Log (lap2);    //0.06918979sec
		Debug.Log (lap3);    //0.07750511sec
	}

	void Test2()
	{
		var start = Time.realtimeSinceStartup;

		for (int test = 0; test < TEST_COUNT; test++) {
			for (int i = 0; i < ARRAY_NUM; i++) {
				var a = _LoopList [i];
			}
		}

		var lap1 = Time.realtimeSinceStartup - start;

		start = Time.realtimeSinceStartup;

		for (int test = 0; test < TEST_COUNT; test++) {
			for (int i = 0; i < _LoopList.Count; i++) {
				var a = _LoopList [i];
			}
		}

		var lap2 = Time.realtimeSinceStartup - start;


		start = Time.realtimeSinceStartup;

		for (int test = 0; test < TEST_COUNT; test++) {
			foreach(var value in _LoopList){
				var a = value;
			}
		}

		var lap3 = Time.realtimeSinceStartup - start;
	

		Debug.Log (lap1);    //0.1496518sec
		Debug.Log (lap2);    //0.2155538sec
		Debug.Log (lap3);    //0.3233421sec
	}
}

```

#検証結果
||通常の配列|List|
|:-----------------|:------------------|:------------------:|
|要素数で回す|0.08274078sec|0.1496518sec|
|length,countで回す|0.06918979sec|0.2155538sec|
|foreach|0.07750511sec|0.3233421sec|

#結論
要素数が固定なら配列を使ったほうが速い
配列は固定の変数よりlengthを使ったほうが速い
MacでI-O DATA製のUSB接続LANアダプターでRaspberry Piと有線接続できない時に疑うこと

Raspberry Piと有線接続したい時があると思います。
ネット上のTIPSは殆どApple Thunderbolt Ethernetアダプタで、これなら何も問題なく使えます。
だけど3000円超えで少々お高い…

市販のUSB LANアダプターがお手頃です。
ですが上手く繋がってくれない場合があります。
全てのメーカー、製品を試してませんがI-O DATA製だったら以下の点を確認してみてください。

私が使ったのは [I-O DATA USB LANアダプター ETX3-US2](http://amzn.to/2slUHBd) でした。

#結論

「システム環境＞共有」の「インターネット共有」の "相手のコンピューターでのポート"のチェック状態を確認する。
「USB Ethernet」以外に**「ETX3-US2」などIODAT製のUSB接続LANアダプターの商品名** が出ていたらそれをチェックすること。

これだけに半日費やした…


##設定手順

「システム環境＞共有」の「インターネット共有」を開く

![スクリーンショット 2017-06-09 22.04.07.png](https://qiita-image-store.s3.amazonaws.com/0/5923/b9c3af90-a488-d1fb-16d3-ff1237f0d75b.png)

ポート部分がグレーで選択できない場合は、
一度「インターネット共有」のチェックを外すと選択できるようになります。
![スクリーンショット 2017-06-09 22.03.59.png](https://qiita-image-store.s3.amazonaws.com/0/5923/9a4c4cac-61b1-b204-2583-545eaae80da4.png)

適用した後、MacもRaspberry Piを再起動すると上手く繋がりました。

[LAN Scan](https://www.macupdate.com/app/mac/40742/lanscan)で確認すると出てきてくれます。
![スクリーンショット 2017-06-09 23.01.16.png](https://qiita-image-store.s3.amazonaws.com/0/5923/fc0fc618-8a88-2065-c5fc-1cb82b8caddb.png)
僕の場合は、左下のネットワークデバイスを**「bridge100」** にすると 192.168.3.2で出てきました。

## 注意：ネットワークでは未接続になる
「システム環境＞ネットワーク」ではUSB EthernetもETX3-US2も未接続と表示されてました。

![スクリーンショット 2017-06-09 23.15.47.png](https://qiita-image-store.s3.amazonaws.com/0/5923/c5f02958-88cc-8e15-c2cc-2e4f94d32595.png)

この状態でもRaspberry Piは問題なく有線接続できてました。


#結論の結論
**Raspberry PiのWiFiドングル(子機)は最初から素直に[I-O DATAのWN-G150UMK](http://amzn.to/2sb8j2z)を使う。**

指すだけで使える。ドライバーや設定不要。消費電力もよく使われてる BUFFALO WLI-UC-GNM よりも低くてそこまで発熱しない模様。

「SSH繋がらないと思ったらWiFiドングル熱っ！！物理的に逝った？！」
「電気屋で適当に買い直したWiFiドングル指したのにSSH繋がらない？！」
「何が悪いの？ともかく有線接続して確認するしかないじゃん！」
「USB LANポートが接続できないってなんでなの？？」←この記事ココ
「え、WiFiドングルのドライバー入れないといけないの？」
「Raspberry Piで使えるドライバーないやん！」「
「お、個人で使えるドライバーを公開してくれてる…リンク切れでないやん！」

なんてことで半日潰すことがなくなります。
geopandasによる地理データのアニメーション

# はじめに

[geopandas](http://geopandas.org)はpandasの拡張で、地理データを含むデータをpandasのように表形式で扱うことができるpythonのライブラリーです。geopandasには地理データ可視化のための機能も含まれています。といってもデータをそのままmatplotlibに渡しているだけなので、基本的にはふつうにmatplotlibでアニメーションを作成できるはずです。しかし、geopandasの現行のstableバージョンである0.2.1はartistオブジェクトにアクセスしにくい作りになってます。そこで、アニメーションをするなら次のstableバージョンがでるまでの間は以下のようにgithubの最新のソースコードからインストールするのがお勧めです。

```shell-session
pip install -U git+https://github.com/geopandas/geopandas/
```
# 使用するデータ

今回は東京23区の人口比率の推移を可視化します（地理データ関連では、実際に処理を行うより、データを準備するところが大変だったりします）。

地形データは[JapanCityGeoJson 2016](https://github.com/niiyz/JapanCityGeoJson)から[tokyo23.json](https://github.com/niiyz/JapanCityGeoJson/blob/master/geojson/13/tokyo23.json)というgeojsonファイルをダウンロードしています。

人口データは[Wikipedia:東京都区部](https://ja.wikipedia.org/wiki/%E6%9D%B1%E4%BA%AC%E9%83%BD%E5%8C%BA%E9%83%A8)のデータを再構成したファイルを[23population.csv](https://gist.github.com/61a3434e8bc211c9eecfbc94ccb61231)という名前で作成しました。

# アニメーション

では実際にアニメーションを実行してみましょう。以下がコードになります。

```py3
import geopandas as gpd

df = pd.read_csv('23population.csv')
geodf = gpd.read_file('tokyo23.json').dissolve(by="id").sort_index()
years = np.sort(np.unique(df.year.values))
```
df という変数に人口データ、geodfという変数に地形データを読み込んでいます。

```py3
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
ims = []
def update_fig(year):
    if len(ims) > 0:
        ims[0].remove()
        del ims[0]
    geos = geodf['geometry'].values
    sum = np.sum(df[(df.year==year)].sort_values(by='city').population)
    population_rates = df[(df.year==year)].sort_values(by='city').population/sum
    artist = gpd.plotting.plot_polygon_collection(ax, geos, population_rates, True, cmap="Reds")
    ims.append(artist)
    ax.set_title('year = ' + str(year))
    return ims
anim = FuncAnimation(fig, update_fig, interval=1000, repeat_delay=3000, frames=years)
fig.show()
```
artistオブジェクトの取得のため、地形データの描画は gpd.GeoDataFrame.plot ではなくその中で呼ばれている gpd.plotting.plot_polygon_collection という関数を呼び出しています。

![tokyo23.gif](https://qiita-image-store.s3.amazonaws.com/0/10742/29ef42ed-d436-ee9c-dd3d-6a0e49203176.gif)

# 参考リンク

- [geopandasを使ってみる](http://qiita.com/SaitoTsutomu/items/647349c4038d6a9e34be)
- [matplotlibでアニメーション](http://qiita.com/chez_sugi/items/93ff2efad50f16bc8c37)
既にAndroid Studioを使っている人が、別マシンにてコマンドラインからAndroid SDKを導入する方法

***「サブマシンのストレージ残量がキツいので、IntelliJ IDEA + Android SDKで開発したい！」***
***「CI環境にAndroid SDKだけ入れたい！」***
と言う方へ献げる文章です。

コマンドラインからsdkmanagerを使ってAndroidSDKを引っ張る
http://qiita.com/meeetball/items/578133bfe92372e29ea8

最初は上記投稿のように `sdkmanager` を使おうとしたのですが、何故か私の環境ではIntelliJがSDKディレクトリを認識してくれず、はまりました。
既にAndroid Studioでのビルド環境をお持ちの方は、こちらの方法を使う方が手数も減り、捗ります。

# 手順
以下、既にAndroid Studioを使っている環境を「既存環境」、新しくAndroid SDKを導入したい環境を「新環境」としています。

## 1. 新環境にJDKをインストール

http://www.oracle.com/technetwork/java/javase/downloads/index.html
今はAndroidビルド環境もJava 8です。

## 2. 新環境にAndroid SDK sdk-toolsをインストール

https://developer.android.com/studio/index.html
下の方にひっそりと用意されている「コマンドライン ツールのみ入手する」下のリンクからsdk-toolsを入手します。
zip内に`tools`ディレクトリだけ入ってるシンプルな構成なので、

Mac, Linux `/opt/android-sdk/tools`
Windows `c:\android-sdk\tools`

などにコピーすればOKです。
環境変数 `ANDROID_HOME` も設定しておくと後が楽です。

## 3. 既存環境の `($ANDROID_HOME)/licenses` ディレクトリを、新環境に移植

Mac `($HOME)/Library/Android/sdk/licenses`
Windows `($LOCALAPPDATA)\Android\sdk\licenses`

にあります。まるごと2で用意した、新環境の `$ANDROID_HOME ` にコピーしてください。

## 4. 新環境でソースコードをチェックアウト

新環境にプロジェクトを持ってくる事が重要なので、ただコピーするだけでも良いです。

## 5. 新環境でLet's gradle

チェックアウトしたディレクトリ下で `./gradlew assembleDebug` しましょう。
TargetにしているSDKやらBuild toolsやらが勝手にインストールされます。
コード量が多い等の理由で、今はビルドしたくない！と言う方は `./gradlew tasks` 等でも良いと思います。

## 6. (Optional) 新環境でIntelliJを設定する
`File - Project Structure - Platform Settings - SDKs` からJDKとAndroid SDKを設定してください。
どちらもディレクトリを指定するだけで何とかなるはずです。

# 参考

Auto-download missing packages with Gradle
https://developer.android.com/studio/intro/update.html#download-with-gradle
openFrameworks on raspberrypi

raspberrypi上でopenFrameworksを動かすテストをした. 
raspberrypi上でoFが動くと何かと便利なので良い. 

# 環境
mac: OSX 10.11 El Capitan
raspi: rasbian 8.0

``` 
$cat /etc/debian_version
8.0
```

oF: 0.9.2


# install
基本的には公式サイトの
http://openframeworks.jp/setup/raspberrypi/Raspberry-Pi-Getting-Started.html
を参考にすれば問題なくいけます. 

ただし, 一部違う箇所があったので下記にメモ. 

## apt-getの準備

```
sudo apt-get clean
sudo apt-get update
sudo apt-get upgrade
```


## oFのdownload
公式の方法でcurlしたけどダウンロードでコケていた. 
最新の0.9.2に数字を変えてもダメだったので, macで
http://openframeworks.jp/download/
の

>
linux armv6
download openFrameworks for linux armv6

からダウンロードして, scpすることにした. 

macでダウンロードしたのはこれ. 
> of_v0.9.2_linuxarmv6l_release.tar.gz

それをmacから

```
mac$ scp of_v0.9.2_linuxarmv6l_release.tar.gz pi@raspberrypi.local:~/
```

でraspiにコピー. 

## 展開してinstall
その後も一部だけ公式と違った. 

```
cd
tar vxfz of_v0.9.2_linuxarmv6l_release.tar.gz -C openFrameworks --strip-components 1

cd /home/pi/openFrameworks/scripts/linux/debian
sudo ./install_dependencies.sh

make Release -C /home/pi/openFrameworks/libs/openFrameworksCompiled/project
```

installは1時間くらい? 途中で席を外してしまったので正確な時間は不明です. 
2回くらい```Y```(yes)する箇所があるのでご注意を. 

これでinstall完了. 

# exampleを試す

```
cd /home/pi/openFrameworks/examples/graphics/polygonExample
make
make run
```
## 動画
こんな感じ.

https://youtu.be/G52raqfcS24

# 自分のcodeを走らせる
以下の通り. 
まだ試せてないけど多分これは大丈夫な気がする. 

```
cp -R /home/pi/openFrameworks/examples/empty/emptyExample /home/pi/openFrameworks/apps/myApps/myRpiApp
cd /home/pi/openFrameworks/apps/myApps/myRpiApp
make
make run
```


# 最後に
raspberrypiでoFが動かせるのはホントにいいですね. 
WiringPiとかを使うと直にGPIO pinが使えるらしいのでかなり楽しみ. 
今回はそもそもoF on linux自体が初体験だったのでワクワクでした.
boxのAPIのおかげで身長が3cm伸びました

# box?

[これ](https://www.box.com/)

クラウドストレージサービスで、APIが提供されています。


# APIで何ができんの？

[これ](https://developer.box.com/reference)

boxでは、超最強管理者権限をもっていると管理配下のユーザーになりすますことができます。（As-User API）
これをプログラム上から使うことで、自動で
- 特定用途のフォルダを全ユーザーに作成できたり
- 不適切なファイルを勝手に削除できたり
- 不適切なコラボレータ設定を直したり
色々できちゃいます！

As-Userを利用しなくても自分の生活を豊かにするあら便利なアプリの作成は可能です。


# もっと応用すると

- S3にファイルが置かれたらバックアップをbox上に保存する
- Slackに投稿されたファイルをboxにおく（ファイルの有効期限設定してる場合とかに有効/Slackが漏れても画像とかの面に関しては安心）

ちなみに僕はこれで権限のないユーザでも公開アップロード専用Webページと管理画面を作成しました。
めっっっっっっちゃ便利でセキュアなのでだいぶ有益でした。そのうち公開します。


# どうやって開発するの？

公式のSDKが提供されています。
先の公開アップロード専用Webページは、公式SDKとAPIを使って実現してます。

[GitHub](https://github.com/box/box-node-sdk)

boxの開発者みたいなロールを管理者から付与されると、左ペインに `開発者コンソール` のリンクがでてきます。
そのリンクから各種アプリ設定を行い、AccessKey/SecretKeyを作成することで独自のアプリの作成が開始できます。

ただ注意点があって、上記SDKはNode.js用なので、webアプリでは使えません。
webから使う場合は、ワンタイムキーを都度発行する必要があり超冗長なコードになります。

なので、以下のようなPromiseを返却する `なんかそれっぽい` moduleつくっちゃった方が楽でしょう。

```js:token.js
import * as config from '../config';
import axios from 'axios';

axios.defaults.baseURL = config.api_uri;

export default {
    request() {
        const refreshToken = localStorage.getItem('refresh_token') || null;
        const code = localStorage.getItem('code') || null;

        let params = {
            client_id: config.client_id,
            client_secret: config.client_secret
        };

        if (refreshToken) {
            params['grant_type'] = 'refresh_token';
            params['refresh_token'] = refreshToken;
        } else {
            params['grant_type'] = 'authorization_code';
            params['code'] = code;
        }

        return axios.post("/oauth2/token", this.buildParams(params));
    },

    header(data) {
        this.save(data);
        return {
            Authorization: `Bearer ${data.access_token}`
        };
    }
}
```


# 余談

ちなみに先日、Node.jsのSDKが全体的にPromisifyされたのですごく使いやすくなりました。
[docs](https://github.com/box/box-node-sdk/blob/master/docs/folders.md)の更新はされてないのに[README](https://github.com/box/box-node-sdk/blob/master/README.md)が更新されてて気づくのに遅れました。

```js:before.js
client.folders.get('12345',  {fields: 'name'}, (err, data) => {
  //
});
```

```js:after.js
client.folders.get('12345',  {fields: 'name'})
    .then(result => {
        //
    })
    .catch(error => {
        //
    })
```

よいboxライフを！
Google VR SDK for iOSを試してみた


#簡単な使い方
1.CocoaPodsを使って導入する。

```swift:Podfile
target ‘アプリ名’ do
  pod 'GVRSDK'
end

```

2.Bridging-Headerファイルを作る。
(*Build Settingsへの追加をお忘れなく。)

```swift:Bridging-Header.h
#import "GVRPanoramaView.h"
#import "GVRWidgetView.h"
#import "GVRVideoView.h"
```

3.パノラマ写真なら「GVRPanoramaView」、動画なら「GVRVideoView」を使う。

例)パノラマ写真

```swift:panoramaView.swift
//変数宣言
var panoramaView: GVRPanoramaView!

//デリゲートとボタン表示の設定
panoramaView.delegate = self
panoramaView.enableFullscreenButton = true
panoramaView.enableCardboardButton = true

//loadメソッドを使って画像を表示する。
let panoramaImage = UIImage(named: "panorama.jpg")
panoramaView.load(panoramaImage)
//または
pano.load(panoramaImage, of: <GVRPanoramaImageType>)
/*
PanoramaImageTypeはkGVRPanoramaImageTypeMonoかkGVRPanoramaImageTypeStereoOverUnder
panoramaView.load(panoramaImage)の場合はkGVRPanoramaImageTypeMonoとなる。
*/
```

例)360度動画

```swift:videoView.swift
//変数宣言
var videoView: GVRVideoView!

//デリゲートとボタン表示の設定
videoView.delegate = self
videoView.delegate = true
videoView.delegate = true

//loadメソッドを使って動画を表示する。
let videoPath = Bundle.main.path(forResource: "sample", ofType: "mp4")
//URLで読み込むため変換
let videoUrl: URL = URL(fileURLWithPath: videoPath!)
videoView.load(videoUrl)
/*
もちろんサーバー上にあるファイルも指定可能。
HSL対応なので環境さえ揃えればストリーミング配信もできる。
*/

```

あとは適宜デリゲートメソッドを実装していく。
主なメソッドは下記、細かなことは[リファレンス](https://developers.google.com/vr/ios/reference/)で確認を。

```swift:video.swift
//コンテンツのロードが成功した時に呼ばれるデリゲートメソッド
func widgetView(_ widgetView: GVRWidgetView!, didLoadContent content: Any!) {
}

//コンテンツのロードが失敗した時に呼ばれるデリゲートメソッド
func widgetView(_ widgetView: GVRWidgetView!, didFailToLoadContent content: Any!, withErrorMessage errorMessage: String!) {
}

//画面がタップされた時に呼ばれるデリゲートメソッド
func widgetViewDidTap(_ widgetView: GVRWidgetView!) {
}

```

#使ってみた感想
360度のパノラマ写真とか動画をみるアプリなら十分イケる。
でもcardboard対応ゲーム(SceneKitと組み合わせるとか)を作るのはけっこう面倒。
(ググった限りは使用例は[GVR-SceneKit](https://github.com/AndrianBdn/GVR-SceneKit)くらい。)
Unity向けSDKも用意されているのでゲーム用途なら素直にそっちを使った方が断然楽。
Daydreamに対応しているので今年リリースされる予定の「VIVE standalone headset with Daydream」と「Lenovo standalone headset with Daydream」に期待。
object タグをアンカーリンクで囲んでもリンクにならない

以下のように、`object` タグを `a` タグで囲んだ場合、SVG の部分がリンクになりません。

```html
<a href="/">
  <object type="image/svg+xml" width="32" height="32" data="logo.svg"></object>
</a>
```

スタイルシートで以下のように設定すると、解消されるようでした。

```css
object {
    pointer-events: none;
}
```

参考: https://stackoverflow.com/a/17133804
WildFly 10のCLIでxa-data-source追加

WildFly 10のCLIでXAデータソースを追加するためのコマンド。バージョンによって微妙にコマンドが異なるようで、若干苦戦したのでメモを残す。

# 環境

* WildFly 10.1.0.Final
* Oracle Database 11g Release 2(11.2.0.1.0) Enterprise Edition
* PostgreSQL 9.5.6

# 手順など

```bash
[standalone@localhost:9990 /] jdbc-driver-info
NAME       SOURCE
h2         com.h2database.h2/main
oracle     com.oracle/main
postgresql org.postgresql/main
[standalone@localhost:9990 /] xa-data-source add \
>   --name=XAOracleDS \
>   --driver-name=oracle \
>   --jndi-name=java:/XAOracleDS \
>   --user-name=kagamihoge \
>   --password=xxxx \
>   --xa-datasource-properties=URL=jdbc:oracle:thin:@//192.168.0.20:1521/ORCL.kagamihoge
[standalone@localhost:9990 /] xa-data-source test-connection-in-pool --name=XAOracleDS
true
[standalone@localhost:9990 /] xa-data-source add \
>   --name=PostgresXADS \
>   --driver-name=postgresql \
>   --jndi-name=java:/PostgresXADS \
>   --user-name=postgres \
>   --password=postgres \
>   --xa-datasource-properties=DatabaseName=postgres,PortNumber=5432,ServerName=192.168.0.21
[standalone@localhost:9990 /] xa-data-source test-connection-in-pool --name=PostgresXADS2
true
```

```bash
xa-data-source add \
  --name= \
  --driver-name= \
  --jndi-name= \
  --user-name= \
  --password= \
  --xa-datasource-properties=
```

```xa-data-source add --help```でパラメータ一覧などが確認できる。```--xa-datasource-properties```はDBMSによって異なると思われる。バージョンによってはここを```bat```コマンドで入力するようだが、10ではこのパラメータでまとめて指定できるようだ。
ReactのJSXでスプレッド属性を使おうとするとsyntax errorが出る対処法

Rails5.1のwebpakcerを使って、Reactの勉強をしているのですが、スプレッド属性を使ったときのコンパイルでSyntax errorが出ました。

```
21:42:08 hot.1  | ERROR in ./app/javascript/packs/hello_react.jsx
21:42:08 hot.1  | Module build failed: SyntaxError: Unexpected token (98:16)
21:42:08 hot.1  |
21:42:08 hot.1  |    96 |
21:42:08 hot.1  |    97 | ReactDOM.render(
21:42:08 hot.1  | >  98 |   <h2 style = {{...myStyle}}>
21:42:08 hot.1  |       |                 ^
21:42:08 hot.1  |    99 |     Let's Spread!
21:42:08 hot.1  |   100 |   </h2>,
21:42:08 hot.1  |   101 |   document.getElementById('container')
```

何度も確認して記述ミスはなかったのですが、どうやらbabelのpluginが必要みたいでした。

### babel-plugin-transform-object-rest-spreadのインストール

```
$ yarn add babel-plugin-transform-object-rest-spread
```

```.babelrc
  "plugins": [
	"transform-object-rest-spread"
	]
```

これだけで治りました。
数字の桁を求める

[Project Euler](https://projecteuler.net/) で酷使。
文字列にして処理してもいいのですが、せっかくなので。

# こんなメソッドを用意する

int(long) の拡張メソッドにしてみます。
ただ基数で繰り返し割っていくだけです。

```csharp
public static IEnumerable<int> Digits(this int n, int b = 10)
{
	if (n == 0)
		yield return 0;

	var q = n;
	while (q != 0)
	{
		yield return q % b;
		q /= b;
	}
}
```

`b`は基数です。既定値は10なので、10進数の場合の桁が得られます。
2にすれば2進数での桁になります。

# こんな風に使う

```csharp
var n = 23098432;
var result = n.Digits().ToArray();
// result => [2, 3, 4, 8, 9, 0, 3, 2]
```
※ シーケンスが1の位から順に返すことに注意してください。

# 元の数字に戻す

簡単に戻せます。

```csharp
var digits = int[] { 2, 3, 4, 8, 9, 0, 3, 2 };
var n = digits.Select((x, i) => x * (int)Math.Pow(10, i)).Sum()
// n => 23098432
```
IIS上の設定をPowerShellから操作する。

アプリのデプロイ時に仮想ディレクトリの参照先を変更する仕組みが必要になった。
実際にやったことのメモなので仮想ディレクトリの物理パス(physicalPath)の設定を例に。


## 前提

`WebAdministration` モジュールを読み込むと、IISの管理階層をPSドライブとして読み込むことができる。

```PowerShell
# IISを操作するモジュールの読み込み
PS> Import-Module WebAdministration
PS> cd iis:\
PS> ls

Name       
----       
AppPools   
Sites      
SslBindings
```


## 値の取得

値の取得方法はいくつかあるのでお好みで。
ここではデフォルトサイト直下に `sampleDir` という仮想ディレクトリがある前提で。

```Powershell
PS> Get-ItemProperty -Path 'IIS:\Sites\Default Web Site\sampleDir' -Name physicalPath | select -Exp value
PS> Get-Item 'IIS:\Sites\Default Web Site\sampleDir' | select -exp physicalPath

# WebAdministration のCmdletを使うと以下の感じ
PS> Get-WebVirtualDirectory -Site "Default Web Site" -Name sampleDir | select -exp physicalPath
```


## 値の設定

値の設定もいくつかやり方ありそうな気がするが、簡単だったのが以下の方法

```PowerShell
PS> Set-ItemProperty -Path 'IIS:\Sites\Default Web Site\sampleDir' -Name physicalPath -Value C:\tmp\sample2
```


## 所感

- 個人的には取得は `Get-Item` が扱いやすかった。
    - サイト名とかアプリ名とかバラバラに設定持つ場合は `Get-WebVirtualDirectory` の方がいいけど、コンフィグにフルパス書いた方が楽。
- `Set-WebConfigurationProperty` とか使えたほうが便利なのかもしれないけど、調べてた時にいまいちピンと来なかった。
- `Get-Item` で取った情報を変更して直接更新かけれると楽そうなんだけど、SaveとかUpdate系の扱い方がわからなかった。
Zsh環境で雑にRustプロジェクトのディレクトリかどうかを判断してrustcのバージョンを表示する

![zsh-rust-version.png](https://qiita-image-store.s3.amazonaws.com/0/1775/3bf488ea-283a-ace0-7264-f20919d82874.png)

カレントディレクトリに `Cargo.toml`が存在したら、`rustc --version`実行して、プロンプトに出力するという感じです。ごちゃごちゃと別の設定も入ってますが、キモは`precmd()`あたりです。
雑なのであとはご自身でいい感じにしてみてください。

```zsh
setopt prompt_subst
local GREEN=$'%{\e[1;38;5;202m%}'
local PINK=$'%{\e[1;38;5;198m%}'
local LGREEN=$'%{\e[1;38;5;149m%}'
local YELLOW=$'%{\e[1;38;5;33m%}'
local BLUE=$'%{\e[1;34m%}'
local DEFAULTNON=$'%{\e[1;0m%}'
local DEFAULT=$'%{\e[1;38;5;152m%}'
autoload -Uz vcs_info
zstyle ':vcs_info:*' formats '(%s)-[%b]'
zstyle ':vcs_info:*' actionformats '(%s)-[%b|%a]'
precmd () {
    psvar=()
    LANG=en_US.UTF-8 vcs_info
    [[ -n "$vcs_info_msg_0_" ]] && psvar[1]="$vcs_info_msg_0_"
    if [ -e ./Cargo.toml ]; then
        PROMPT_RUSTC_VERSION=" rust:"$BLUE`rustc --version | awk '{ print $2 }'`$DEFAULTNON
    else
        PROMPT_RUSTC_VERSION=""
    fi
}
PROMPT='[%D.%T]'$GREEN'%n@%m: '$YELLOW'%(5~,%-2~/../%2~,%~) '$DEFAULTNON'%1(v|'$LGREEN'%1v%f|)'$DEFAULTNON'$PROMPT_RUSTC_VERSION'$'\n'$DEFAULTNON'%(!.#.$) '
```
tmuxでよく使うコマンド

tmuxでよく使うコマンドについて記載


```
C-b　はControl + B

#新規セッションの開始
tmux	

#新規セッションの開始（名前指定）
tmux new-session -s <name>	

#セッション一覧
tmux ls	

#セッション名変更
C-b + $	

#セッション名変更
:rename-session <name>	

#セッション名変更
tmux rename -t <old-name> <new-name>	

#指定したセッションにアタッチ
tmux a -t <session-name>

#セッションのデタッチ	
C-b + d	

#ウィンドウ作成
C-b + c	

#ウィンドウ名変更
C-b + ,	

#ウィンドウ名変更
C-b + ,

#ウィンドウ移動（next）
C-b + n	

#ウィンドウ移動（pre）
C-b + p	

#指定した番号のウィンドウに移動
C-b + <number>	

#ウィンドウ一覧表示（矢印キーで選択してEnterか数字を押すと移動）
C-b + w	

#ウィンドウ強制終了
C-b + &	

#ペイン横分割
C-b + “	

#ペイン縦分割
C-b + %	

#ペインの移動
C-b + o	

#インジケータ表示
C-b + q	

#表示された番号のペインに移動
C-b + q + <number>	

#ペイン強制終了（現在のペインを終了する）
C-b + x	

#ペインの入れ替え（現在のペインを左側のペインと入れ替える）
C-b + {	

#ペインの入れ替え（現在のペインを右側のペインと入れ替える）
C-b + }	

#指定したセッションを削除
tmux kill-session -t <session-name>	

#直近にアタッチしてたセッションを削除
tmux kill-session	

#セッションを全て削除
tmux kill-server

#全ペインに同時入力をスタート
:set-window-option synchronize-panes on	

#全ペインに同時入力を終了
:set-window-option synchronize-panes off

#コピーモードに入る 
C-b [

#viキーバインド(hjkl)で選択したい場所に移動する

#範囲選択モードに入る
Space

#選択範囲をコピーする
Enter

#ペースト
C-b ]

#クリップボードにコピー
C-b y
```

※コピーを行うには別途設定が必要。下記ページを参考


以上




参考
http://qiita.com/tchssk/items/de7a0323307c35c54a97
MacのUS配列キーボードでクリーンインストール後にIME切り替えができないことがある

# 症状
US配列キーボードのMacをクリーンインストールした後、入力ソースの設定をしてIMEの切り替えをすると5回に1回くらい切り替えに失敗する。

# 環境

Mac: MacBook Pro (Retina, 13-inch, Mid 2014)
OS: macOS Sierra 10.12.5

# 解決策
Macの再起動

データをごそっと入れ替えたので動作が重くなってしまったのかな？
MacをクリーンインストールしてTime Machineからデータを復元しようとしたらフリーズした

# 目的
MacのTime Machineの使い心地が気になる

# 結論
かなり使える。ただ、安定性に不安あり。

# やったこと
MacOSのクリーンインストールとTime Machineからデータの復元

# 環境
Mac: MacBook Pro (Retina, 13-inch, Mid 2014)
OS: macOS Sierra 10.12.5
Time Machine: AirMac Time Capsule
https://www.apple.com/jp/airmac-time-capsule/

# 手順
1. バックアップ
2. ディスクのフォーマット
3. 再インストール
4. Time Machineからデータの復元

## バックアップ
Time Machineで最終のバックアップを取っておく
右上のTime Machineのアイコンから「今すぐバックアップを作成」をポチっ
Time Machineを信用しきっていたのでその他のバックアップはなし

## ディスクのフォーマット
```command + r```を押しながらMacを再起動
ディスクユーティリティからMacintosh HDを```Mac OS Extended (Journaled)```でフォーマット

## 再インストール
ポチポチ進めていく

## Time Machineからデータの復元
今回はドキュメントとネットワークの設定だけ復元する。
アプリケーションは必要に応じてあとで入れる。

### 1回目(wifi)
wifiでTime Capsuleに接続をして復元
時間がかかりそうだったので朝確認してみると、残り3時間13分から動いていない。。。
AppleCareに相談してみると、「復元するデータが大きいとフリーズしてしまう可能性がある」とのこと。
100GB程度でフリーズしてしまうTime Machineの安定性に不安を覚えました。
プログレスバーは進まないので復元はキャンセル・再起動が発生しました。

### 2回目(Ethernet)
再起動後はデータの復元から再開しました。
もう一度試してみてだめだったらドキュメントの復元は諦めましょう。
1回目はエンジニアの勘で通信環境に問題があった気がしたのでEthernet接続で試すことに。

（以下、英語の画面だったのでどんな表現だったかはあんまり覚えていないのですが、）
1回目の復元が途中でキャンセルされたので、すでに復元が終わっていたファイルの処理について聞かれました。
- 上書き保存するか
- 両方のデータを残すか
- 別アカウントとして復元するか
今回は上書き保存を選択。

すると今度はフリーズせずに3時間程度でちゃんと復元が完了しました。

原因がTime Machineとの通信の問題だったかはわからないままですが、100Gの転送になるのでなるべく有線で接続したほうが良さそうです。

## 再起動
復元後は念のためもう一度再起動しておきましょう。
IME切り替えで動作が安定しないことがあったんですが、再起動をしたら治りました。
データをガバッと入れ替えているので予期せぬ不具合を踏んだのでしょう。

# Time Machineから復元後の使い心地について
かなり使い心地がいい。
ファイルも特にかけているところはなさそう。
Time Machineも以前のバックアップの続きから使えているようです。

アプリの設定ファイルは復元できているので、アプリをインストールし直すと設定が蘇ります。
Google Chromeを入れるとお気に入りとかアドオンとか蘇りました。
他のアプリはこれから確認します。

システムのストレージについても再インストールの前後で20Gほど少なくなっています。

復元でフリーズするというアクシデントはありましたが、Time Machineの使い勝手はかなりいいです。
昔みたいなファイルをいちいちHDにバックアップして・・・という作業がなくなりました。
OSのメジャーバージョンアップの時とかは積極的に使っていきたいです。
Vimコマンド覚書

#vimコマンド

###:vim[grep] \<検索文字> \<ファイルパス>
**ファイル検索**

* 検索文字
    *  ""や''でくくらなくていい。/検索と同じ記法。
* ファイルパス
    * \*\*/*.xml とすると、子フォルダのxmlも見に行く。
* コマンド例
    * `:vim /hoge/g *.xml`
    * `:vimgrep fuga **/test.txt` 配下のtest.txtからfugaを探す 

###:cn
**:vimの検索結果の次に進む**

* 利用例
    * exモードに移動するのが面倒なので_vimrcに`map gn :cn<CR>`とかする。

###:args \<コマンド実行対象ファイルパス>

* コマンド実行対象ファイルパス
    * \*\*/*.xml とすると、子フォルダのxmlも見に行く。
* コマンド例
    * `:args *.xml` カレントフォルダのXMLファイルを`:argdo`処理対象にする。

### :argdo <コマンド>
**:argsで指定したファイル群に対して、コマンドを実行する**

* コマンド
    * 任意のexコマンド。（exに限る必要はないのかも？よくわからない）
`%s/hoge/fuga/g`など
* コマンド例
    * `:argdo %s/hoge/fuga/gce | update`
* 参考 [街のWeb屋さん](http://zx.jpn.org/b/20081025/155/vim/vim-mluti-file-replace)

### :aug[roup] \<グループ名>
**コマンドグループを作る**

### :au[tocmd] \<イベント> \<ファイル> \<コマンド>
**ファイルにイベントが発生したときにコマンドを実行する（ように登録する）**

* イベント
    * BufNewFile、BufReadなど。（詳しくは、`:h {event}`
    * 複数指定する場合、カンマで区切る。このとき、スペースを入れてはいけない。
    * NG: `:au BufNewFile, BufRead *.xml setlocal noexpandtab`
    * OK: `:au BufNewFile,BufRead *.xml setlocal noexpandtab`
* ファイル
    * *.xmlとか
* コマンド
    * なんかもういろいろ
* コマンド例

    ```vim:_vimrc
aug myGroup
    au!
    au BufNewFile,BufRead *.xml setlocal noexpandtab
aug end
```

    > ファイル .vimrc が2回読み込まれるとき、自動コマンドは二度現れる。これを避けるため、このコマンドをファイル .vimrc の自動コマンドを定義する所の前に入れておく必要がある。
:autocmd!     " 現在のグループに対する「全て」の自動コマンドを削除。

vimヘルプより抜粋

#xmledit
[名無しのvim使い](http://nanasi.jp/articles/vim/xml-plugin.html)参照。
1点、誤りがあったので訂正。

* `<tag|`の状態で`>`を打つと`<tag>|</tag>`としてくれて、
* さらに`>`を打つと、

```
<tag>
    |
</tag>
```
としてくれる。（参照先では\<reader>>（つまり`\>`）とするとこれができるあった）