OmniAICreator/Qiita-1.07M huggingface dataset:
NagiosでDisk容量アラート発砲時にFree upするeventhandlerを作ってみた

[株式会社オズビジョン](http://www.oz-vision.co.jp/)の@terra_yuccoです。

[イマドキWebサービスの監視について考えてみる](http://qiita.com/terra_yucco/items/5e726dcbb1971f1b089d)のエントリで、メインプロダクトの監視を2016年下期に実施する、と書きました。
その中で、監視をしているといろいろな不具合にも気づくわけで。
Diskがいっぱいになりやすいなら定期的に消せばいいじゃない！とか、
Nagios使ってるなら将来的にはeventhandlerも使えたらいいじゃない！とか、
色々なことを日々考えていたりするわけです。

今回、cronからも起動でき、eventhandlerからも使えそうなfree upスクリプトを書いたので、
試しにコードをQiita上に晒すという暴挙に出てみようと思います。

※どうでもいいけど「ディスクを空ける」が"free up"なのも今回知りました。

# 作成スクリプト
Bashの猛者な皆様の厳しいご指摘をお待ちしています。
なお、保存日数とpathを内部に持っているのは、注入できるようにすると、権限によっては大事故になるからです。

## 起動方法

- cronから
    - `/path/to/nagios-plugins/eventhandlers/free_up_local_disk.sh --from-cron`
- Nagiosから
    - `/path/to/nagios-plugins/eventhandlers/free_up_local_disk.sh $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$`

## 実コード

```bash:free_up_local_disk.sh
#!/bin/bash -u
#
# Event handler script for free up local disk
#
# Note: This script will only free up the server if the service is
#       retried 3 times (in a "soft" state) or if the service somehow
#       manages to fall into a "hard" error state.
#

#---------------------------------------
# constants
#---------------------------------------
path=/path/to/target
mtime=200


#---------------------------------------
# for free up
#---------------------------------------
freeup()
{
    echo "Free up disk space by removing junk files..."
    find ${path} -type f -mtime +${mtime} -exec rm -rf {} \;
    return 0
}


#---------------------------------------
# from cron
#---------------------------------------
if [ $# -eq 1 ] && [ "${1}" = "--from-cron" ]; then
    freeup
    exit 0
fi


#---------------------------------------
# arguments
#---------------------------------------
# invalid
if [ $# -lt 3 ]; then
    echo "Nothing to do..."
    exit 0
fi

# valid
SERVICESTATE=${1}
STATETYPE=${2}
SERVICEATTEMPT=${3}

case "${SERVICESTATE}" in
OK)
    ;;
UNKNOWN)
    ;;
*)
    case "${STATETYPE}" in
    SOFT)
        if [ ${SERVICEATTEMPT} -ge 3 ]; then
            freeup
        fi
        ;;
    HARD)
        freeup
        ;;
    esac
    ;;
esac

exit 0
```

おしまい。
Ansibleを使ってAmazon LinuxにMackerelのAgentをインストールする

# 意図
MackerelのAgent、EC2にインストールするときの手順は[公式にある](https://mackerel.io/ja/docs/entry/howto/install-agent/amazon-linux)のですが、対象サーバが複数台あると面倒なので、Ansible使って一気にインストールとエージェントの起動までしたいなあ、と思いました。



# やり方
手順を見る限り、

1. シェルスクリプトでリポジトリを登録
1. yumでインストール
1. コマンドでAPIキーの設定
1. エージェント起動

ぐらいなので、簡単なPlaybookを一つ書いてしまえば十分かなあと。
てなわけで、下記のようにしてみました。  
軽く[こちら](http://qiita.com/takachan/items/a046c1629ea52ddec6c6)を参考にしてます。


## インベントリファイル

```:hosts
[web]
xxx.xxx.xxx.xxx
yyy.yyy.yyy.yyy

[all:vars]
ansible_ssh_user=ec2-user
ansible_ssh_private_key_file=/path/to/ec2.pem
```
webのところに該当のホストのIPまたはパブリックDNSを記載。
SSHユーザはデフォルトのec2-user
鍵を指定してSSHするなら該当のホストに対するSSHに必要な秘密鍵のパスを記載
オプションで指定するのが面倒なのでここに書いてますが、
とりあえずSSHが通ればなんでもいいです（適当）
そもそもSSHが通らないとAnsible使えないのと、本題とそれるので細かくは割愛


## Playbook

下記のようにしてみました。

```yaml:Mackerel.yml
---
- hosts: all
  become: yes
  tasks:
    - name: Import GPG Key
      rpm_key: state=present key=https://mackerel.io/assets/files/GPG-KEY-mackerel

    - name: Install mackerel repo(Amazonlinux)
      yum: name=http://yum.mackerel.io/amznlinux/latest/x86_64/mackerel-repo-1-0.noarch.rpm state=present

    - name: Install yum mackerel angent
      yum: name=mackerel-agent state=present

    - name: Configure /etc/mackerel-agent/mackerel-agent.conf
      command: mackerel-agent init -apikey="<YOUR_API_KEY>"

    - name: Start mackerel-agent
      service: name=mackerel-agent state=started enabled=yes
```

インストール手順中にあるシェルスクリプトの中身ですが、

1. MackerelのドメインからGPGキーをダウンロードしてインポート
1. rpmコマンドでリポジトリ追加

を行っているだけでした。前半の２つのタスクがそれに該当します。
シェルスクリプトそのまま使っても良かったんですが、
既にリポジトリを追加済みだった場合、
シェルスクリプトがエラーを返してしまいそこでfailedになってしまうので、
同様のことをPlaybookで行うこととしました。

[rpm_keyモジュール](http://docs.ansible.com/ansible/rpm_key_module.html)でGPGキーのインポートができて、
[yumモジュール](http://docs.ansible.com/ansible/yum_module.html)でリポジトリ追加ができるとのことなので、そちらで行いました。
Ansible本当に便利だなあ…。
`<YOUR_API_KEY>`のところは自分のAPIキーに置き換えてください。

あとは
`ansible-playbook -i hosts Mackerel.yml`
で行けるはずです。（hostsもMackerel.ymlもカレントディレクトリにある前提です。）


# 注意事項
AmazonLinuxでない場合URLが微妙に違ったりするので、Install mackerel repoのURLを変えないとダメだと思います。
RPMパッケージを使う場合（AmazonLinux以外）の手順は下記。
それ以外のところは公式サイトを。
https://mackerel.io/ja/docs/entry/howto/install-agent/rpm


何かあればご指摘くださると助かります。
Argument list too longって怒られた

[株式会社オズビジョン](http://www.oz-vision.co.jp/)の@terra_yuccoです。
久々にライトな記事を。
この記事は随時更新していこうと思います。

# Argument list too long
## 原因
- コマンドの引数が長すぎる(`*`などを展開させるとよく起きる)

## 対処
- `ls -l ./*` とかなら、`find . -type f | xargs ls -l` とすると良い

## 上限の調べ方
```bash
[root@hoge fuga]# getconf ARG_MAX
2097152
```
Googleフォームでログインが必須になる問題でハマってしまった…

#突然、Googleフォームがログイン必須に
Googleフォームで強制的にログインしないと回答できない問題に遭遇したので
解決方法を書きます。(かなり特殊な状況で発生します）

#最初に共有設定を確認
共有設定を確認すると、案の定、身内にしか公開されていなかったため
「リンクを知っている全員が閲覧可」を選択。
その後、シークレットモードで確認。

⇒まだ、ログインが必須の状態…

#共有設定をより緩くする
共有設定で最もゆるい設定の「ウェブ上で一般公開」に設定。  
  
⇒まだダメ…

#フォームの設定を確認
共有設定が問題ではなさそうなので
ググったり、公式を読んだりしましたが解決せず…
Googleフォームの編集画面右上、歯車アイコンの設定を疑ってみると
グループ内の人間のみ、ログインが免除される設定になっていました。

⇒ログイン不要で回答できるように!!
(設定を変更した後に、右下の保存ボタンを必ず押すように注意)

#まとめ
今回は、G Suite for Education （旧称：Drive for Education)
に、紐付けされているアカウントであったために
このような特殊な設定がデフォルトで設定されていたようです。

ちなみに、ドライブのディレクトリを表示している画面で取得できるURLと
フォーム編集画面の右上から取得できるURLでは役割が違うため、
目的にあったURLを送信するようにしてください。

(具体的にはドライブ内は編集用URLで、フォーム内が回答用URLです)
Bash on Ubuntu on Windows で IRuby Notebook を使う

http://qiita.com/kozo2/items/5a9f688d362145ef24df
に Bash on Ubuntu on Windows で Jupyter Notebook を使う方法を書きました．

ここではさらに Bash on Ubuntu on Windows で IRuby Notebook を使う方法を紹介します．

http://qiita.com/kozo2/items/5a9f688d362145ef24df
の後で下記を加えて実行します．
IRuby Notebook では libzmq に加え czmq が必要なためそれも install します．

```
sudo su
wget https://github.com/zeromq/czmq/archive/master.zip
unzip master.zip
rm master.zip
czmq-master/
./autogen.sh
./configure
make
make install
ldconfig

apt install ruby ruby-dev
gem install ffi-rzmq
gem install iruby
iruby register
```

この後に `jupyter-notebook` コマンドを実行し Windows 側のブラウザで `localhost:8888` を開くと Ruby のカーネルが追加されていることが確認できるかと思います．
Javaアプレット上でコピペを許可するには長崎の出島で渡航許可証レベルで原始的設定が必要

Javaアプレット上でコピペを許可するには長崎の出島で渡航許可証レベルで原始的設定が必要
なんですね

知らなかったYO


# 1.概要
Javaアプレット上で、Javaアプリ上でコピペしたいんです
文章をコピーして、ペーストしたいんです
正確にいうと、他のアプリ（Numbers）でコピーした文字列を、
Javaアプリ上でペーストしたいんですね

でも、できない、
どうやら制限がかかっているみたいです

簡単に解除できるかと思ったら、できない
調べるのに３０分以上かかったぜ…なぜググっても出てこないんだよ

長崎の出島で渡航許可証レベルで原始的設定が必要です
江戸時代かよ
開国して


>（補足）
厳密にいうと、コピペはできる場合もあります
自作アプリなどの場合、Swingでメニューバーやポップアップなどでコピペを許可していないとこうなる…のかな（予想）




# 2.許可する方法
前提としてMacでの話です（OSX Sierra）
前提としてJava ver. 8

##(1)java.policyというファイルの場所を探します（自分のパソコンの中にある）h2

Javaがインストされているなら、java.policyというファイルが存在します
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/PolicyFiles.html
によると、
ここにあります。
もっとデカい字で書いて欲しいよな…

>java.home/lib/security/java.policy  (Solaris, Linux, or Mac OS X)
java.home\lib\security\java.policy  (Windows)

↑これは
どういうことかというと、

ライブラリ/security/java.policy  (Mac OS X)
みたいに自分のMacのライブラリから入って、下の階層にあるよということです

いや、めんどい
そんなことしなくても
「java.policy」でSpotlight検索してください
（Spotlight検索…Finderの右上にあるファイル検索システムのこと）
すぐに見つかります

#(2)Atom（テキストエディタ）で開いて編集しますh2
このjava.policyファイルをAtomという定番フリーソフトで開いて編集します
テキストエディタでも開くのかもしれませんが、めんどいです

#**このjava.policyファイルはAtomで開けます**
**このjava.policyファイルはAtomで開けます**
**このjava.policyファイルはAtomで開けます**
**このjava.policyファイルはAtomで開けます**
大事なことだろ、ちゃんと書けよ

15分ググってもでてこなかったので、俺がちゃんと書いておきます


##(3)ごちゃごちゃ書いてある中に、grant {permission  java.yyyyyyyy.xxxxxxxxxxx;}と書く


このjava.policyファイルはAtomで開くと
たくさんタブが出て来ますが、
java.policyのタブをクリックし、java.policyの文章を編集していきます


https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/permissions.html
ここに、Javaでコピペを許可したい場合にはxxxxxを許可しろとか
いろいろ書いてありますが、文字が小さすぎて読めません
読んでる時間ない

ようするにJavaはもともと、いろんなものを制限しているようです
セキュリティのためらしいです
でも、今回どうしてもコピペを解禁したいので
このページを「コピー」で検索すると、

>accessClipboard	AWT
>クリップボードとの間での情報の送信と取得

とありますね
どうやらこれを許可すればいいようです

許可するための書き方は、
こちらの方がわかりやすかったです

http://d.hatena.ne.jp/uniker/20050720/1121862344

>grant {
    permission  java.security.AllPermission;
};

grant {
    permission  java.xxxxxxxxxx.yyyyyyyyyyyyyy;
};

みたいな

というか既存でいくつか書いてあるので
それを真似して入れればいいので
さすがにこれは、わかると思います

さっきの「accessClipboard	AWT」
を入れるわけですが

入れる場合は

grant {
    permission java.awt.AWTPermission  "accessClipboard", "read";
};

java.awt.AWTPermissionという、ディレクトリ名？が入るようです
これは先ほどの
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/permissions.html
を見ればわかりますね

#3.Atom（テキストエディタ）を保存して閉じます

#4.コピペできるようにった
再度、お目当のJavaアプリを開くとコピペできるようにった
PageMenuのタブ幅をメニュータイトル長に追従させる【Swift3.0】

### PageMenuのタブ幅をメニュータイトル長に追従させる方法

##### **.menuItemWidthBasedOnTitleTextWidth(true)**をオプション配列に加える
```swift

// swift 3.0

// PageMenuの設定　（swift2.xバージョンではENUMパラメタ名の先頭が大文字です）
let parameters: [CAPSPageMenuOption] = [
    .menuHeight(45.0),
    .menuItemWidth(110.0),
    .centerMenuItems(true),
    .menuItemWidthBasedOnTitleTextWidth(true), // これをオプションに加える
    .menuMargin(6)
]

```

他にもいろいろなオプションが用意されています。
#### オプション列挙子一覧
```swift

public enum CAPSPageMenuOption {
    case selectionIndicatorBottomOffset(CGFloat)
    case selectionIndicatorHeight(CGFloat)
    case menuItemSeparatorWidth(CGFloat)
    case scrollMenuBackgroundColor(UIColor)
    case viewBackgroundColor(UIColor)
    case bottomMenuHairlineColor(UIColor)
    case selectionIndicatorColor(UIColor)
    case menuItemSeparatorColor(UIColor)
    case menuMargin(CGFloat)
    case menuItemMargin(CGFloat)
    case menuHeight(CGFloat)
    case selectedMenuItemLabelColor(UIColor)
    case unselectedMenuItemLabelColor(UIColor)
    case useMenuLikeSegmentedControl(Bool)
    case menuItemSeparatorRoundEdges(Bool)
    case menuItemFont(UIFont)
    case menuItemSeparatorPercentageHeight(CGFloat)
    case menuItemWidth(CGFloat)
    case enableHorizontalBounce(Bool)
    case addBottomMenuHairline(Bool)
    case menuItemWidthBasedOnTitleTextWidth(Bool)
    case titleTextSizeBasedOnMenuItemWidth(Bool)
    case scrollAnimationDurationOnMenuItemTap(Int)
    case centerMenuItems(Bool)
    case hideTopMenuBar(Bool)
    case menuShadowRadius(CGFloat)
    case menuShadowOpacity(Float)
    case menuShadowColor(UIColor)
    case menuShadowOffset(CGFloat)
    case addBottomMenuShadow(Bool)
    case iconIndicator(Bool)
    case iconIndicatorView(UIView)
    case showStepperView(Bool)
}
```
PageMenuのswift3.0バージョンはこちらから入手可能です。
https://github.com/orazz/PageMenu

インストールは、classesの下にある、**CAPSPageMenu.swift** をプロジェクトに追加するだけ。素敵ですね:grinning:
機械学習向けデータのクラス間のサンプル数を揃える with Python

機械学習をする上でクラス間のサンプル数が揃っていることが望ましいです.
しかし実際にはそんなきれいなデータばかりではなく, クラス間のサンプル数が異なるデータもしばしば.

今回, ラベルデータに記されたクラス間のサンプル数を揃える処理をPythonで実装したのでメモ.

# やりたいこと
以下の様なデータ配列とそのラベルデータがあった際に

* ラベルデータのサンプル数を揃える
* 1番の処理に合わせてデータ配列の要素も取り除く

```py3
# データ配列
data = np.array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
# ラベル配列
label = np.array([0, 0, 1, 1, 1, 2, 2, 2, 2, 2])

###############
# データ処理...
###############

>>>data
[10 11 12 14 15 16]
>>>label
[0 0 1 1 2 2]
```

# コード
詳細はコメントに書いてあります.
簡単に言うと, 最小サンプル数よりも多いサンプル数を持つクラスに対して以下の処理を行っています.

1. そのクラスのデータ要素のインデックス配列を取得
2. random.sample()を利用して, そのインデックス配列からランダムに削除する個数分の要素のインデックスを取得.
3. 取得したインデックスのデータとラベルを削除


```py3
import numpy as np
import random

# データ配列
data = np.array(range(10,20))
print("data:", data)
# ラベル配列
label = np.array([0, 0, 1, 1, 1, 2, 2, 2, 2, 2])
print("label:", label)
# 全クラスのサンプル数
sample_nums = np.array([])


print("\n各クラスのサンプル数を計算")
for i in range(max(label)+1):
    # 各クラスのサンプル数
    sample_num = np.sum(label == i)
    # サンプル数管理配列に追加
    sample_nums = np.append(sample_nums, sample_num)
print("sample_nums:", sample_nums)

# 全クラス内の最小サンプル数
min_num = np.min(sample_nums)
print("min_num:", min_num)


print("\n各クラスのサンプル数を揃える")
for i in range(len(sample_nums)):

    # 対象クラスのサンプル数と最小サンプル数の差
    diff_num = int(sample_nums[i] - min_num)
    print("クラス%d 削除サンプル数: %d (%0.2f％)" % (i, diff_num, (diff_num/sample_nums[i])*100))

    # 削除する必要が無い場合はスキップ
    if diff_num == 0:
        continue

    # 削除する要素のインデックス
    # タプルになっているのでlistに変換 (0番目のインデックスに配置されている)
    indexes = list(np.where(label == i)[0])
    print("\tindexes:", indexes)

    # 削除するデータのインデックス
    del_indexes = random.sample(indexes, diff_num)
    print("\tdel_indexes:", del_indexes)

    # データから削除
    data = np.delete(data, del_indexes)
    label = np.delete(label, del_indexes)


print("\ndata:", data)
print("label:", label)
```

# 実行結果
```
data: [10 11 12 13 14 15 16 17 18 19]
label: [0 0 1 1 1 2 2 2 2 2]

各クラスのサンプル数を計算
sample_nums: [ 2.  3.  5.]
min_num: 2.0

各クラスのサンプル数を揃える
クラス0 削除サンプル数: 0 (0.00％)
クラス1 削除サンプル数: 1 (33.33％)
	indexes: [2, 3, 4]
	del_indexes: [3]
クラス2 削除サンプル数: 3 (60.00％)
	indexes: [4, 5, 6, 7, 8]
	del_indexes: [7, 8, 6]

data: [10 11 12 14 15 16]
label: [0 0 1 1 2 2]
```

# 終わりに
Pythonに詳しい人ならもっと効率化出来るんだろうな
自分で libzmq をコンパイルして Bash on Ubuntu on Windows で Jupyter Notebook を使う

Bash on Ubuntu on Windows で Jupyter Notebook を使う場合
https://github.com/zeromq/libzmq/commit/b1e2b87f0f6d507b9af7221e06d9dcc9dbab55a8
と
https://github.com/zeromq/libzmq/commit/36af3edee2915ee7a90d3a2293b11abaf5bac772
が反映されているlibzmqでないとカーネルが死にます．

いつ頃からこの変更が pyzmq 同梱の libzmq に反映される(た?)のかはっきりしてません．
libzmq のコンパイルはそれほど大変でもないので自分でコンパイルする方法をまとめます．
(また http://qiita.com/kozo2/items/447d5edb6e3eb83268f0#_reference-3a4418285413867f39af のようにRubyカーネルを使う場合はこの方が都合がいいです．)

```
sudo su
apt install libtool autoconf pkg-config g++ make unzip python-dev python3-dev
wget https://github.com/zeromq/libzmq/archive/master.zip
unzip master.zip
rm master.zip
cd libzmq-master/
./autogen.sh
./configure
make
make install
ldconfig

wget https://bootstrap.pypa.io/get-pip.py
python2 get-pip.py
python3 get-pip.py
pip2 install pyzmq -U --install-option="--zmq=/usr/local/lib"
pip3 install pyzmq -U --install-option="--zmq=/usr/local/lib"
pip3 install -U jupyter
pip2 install -U ipykernel
python2 -m ipykernel install
```

後は `jupyter-notebook` コマンドを実行し Windows 側のブラウザで `localhost:8888` を開くと Python2,3 のカーネルが死ぬことなく Jupyter Notebook が使えるかと思います．
iPhoneの使いコツ１- iTunesからiPhoneの連絡先を個別に復元

iPhoneから大切な連絡先を失われたら、非常に大変ですね。しかし、ご心配なく、バックアップの有無にもかかわらず、簡単に復元できますよ。

今回は、iTunesのバックアップからiPhone 7/6s/6/5s/5の連絡先をバックアップする方法をご紹介します。

iTunesって、iTunesを使うんですか？iTunesはデータを個別に復元できないんですよね。なんでiTunesのバックアップからiPhoneの連絡先を個別に復元できますかと思っている人が多いですね。

実は、今回、iTunesより優れたiOSデバイス専用のデータ復元ツール ー PhoneRescueをおすすめします。なぜかというと？

iTunesと比べて、PhoneRescueは次の利点を持っています：

安心
1.　iPhone/iPadに既存の連絡先などのデータを失うことはない；

2.　iTunesのバックアップから連絡先の詳細をプレビューができる；

使い勝手がいい
3.　連絡先・電話帳だけを復元できる；

4.　連絡先の一括選択・複数選択ができて、時間と手間を省く；

5.　連絡先を直接iPhone本体に取り戻せる（コンピュータへの取り出しもできる）；

その他
6.　iCloudのバックアップから連絡先などを取り戻すこともできる；

7.　バックアップのない場合も連絡先・電話帳を復元できる；

8.　連絡先以外のメッセージ、メモ、通話履歴、Safariブックマーク、写真など少なくとも25種類のファイルも復元できる。


早速本体入りましょう。

Step 1：　PhoneRescueをパソコンにダウンロード　＞　インストール　＞　PhoneRescueを起動します。
Step 2：　「iTunesバックアップからリカバリー」をクリック　＞  「次へ」ボタンをクリックします。　
![1.png](https://qiita-image-store.s3.amazonaws.com/0/144302/b1b443b8-3122-f7a2-96a5-00e7b671359b.png)


Step 3：　バックアップを1つ選択　＞ ボタンをクリックすると、バックアップファイルの分析が始まります。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/144302/d94faf56-c5fc-ef9a-d868-aff4030761e0.png)

Step 4：　「連絡先」だけにチェックを入れる　＞　真ん中の上部にあるカテゴリーを「削除された項目を表示」に変更　＞　連絡先をプレビューして選択　＞　右下にある「パソコンへ復元」 アイコン、「デバイス本体へ復元」アイコンをクリックすると、iTunesに保存されている連絡先が復元されます。

![3.png](https://qiita-image-store.s3.amazonaws.com/0/144302/33df6331-2113-2a39-04f7-cc116e7a4937.png)

以上です。いかがでしょうか？

今回の文章も他の文章を参考して書きますよ。

参照元：
https://www.imobie.jp/support/recover-contacts-with-itunes-backup.htm
IntelliJ IDEAに任意の拡張子を登録する

任意の拡張子をIntelliJ IDEAに登録して、ハイライトや入力補完させることが出来ます。
例として、.propertis.originalという拡張子のファイルをpropertiesファイルタイプとして認識させてみます。

- SettingsのEditor > File Types を開き、Recognized File Typesの一覧からお目当てのファイルタイプを選択。続けて、Registerd Patternsの一覧の＋ボタンを押して拡張子を追加する
![before_setting_resize.png](https://qiita-image-store.s3.amazonaws.com/0/387/03e86d5b-90c3-ea5c-3830-bc66daaf0e1f.png)


- 開いたダイアログ上で、追加したい拡張子を入力する
![dialog.png](https://qiita-image-store.s3.amazonaws.com/0/387/3732fdf1-140a-bd61-9d48-250b4ed39429.png)


- 拡張子が追加された。これで登録した拡張子のファイルもpropertiesファイルとして認識されます。
![after_setting_resize.png](https://qiita-image-store.s3.amazonaws.com/0/387/32e5243b-c29d-148f-a6b1-ee776199ee5d.png)


注意
---

一度開いたファイルはIntelliJを再起動するまで新しい設定が反映されないことがあるので、設定しても反映されない時は一度IntelliJを再起動して確かめてみてください。
デリゲートパタン　〜 protocolを「名刺」に例えてみた 〜【Swift3.0】

```swift
// swift 3.0

// 作曲家の名刺
protocol ComposeDelegate {
    func createSong(jenre:String)
}

// プロデューサーは作曲家の名刺を持っている
class Producer:ComposeDelegate {
    
    var name:String

    init(name:String) {
        self.name = name
    }
    
    // 作曲（発注）のデリゲートメソッド
    func createSong(jenre:String) {
        print("\(self.name)さんは\(jenre)の作曲を依頼しました")
    }

}

// JPop作曲家
class PopComposer {
    
    var name:String
    var delegate:ComposeDelegate? // 名刺ホルダー

    init(name:String) {
        self.name = name
    }
    
    func compose() {
        if let _ = self.delegate {
            delegate?.createSong(jenre: "JPop")
        } else {
            print("\(self.name)は作曲を依頼されてません")
        }
    }
}

// Dance作曲家
class DanceComposer {
    
    var name:String
    var delegate:ComposeDelegate?
    
    init(name:String) {
        self.name = name
    }
    
    func compose() {
        if let _ = self.delegate {
            delegate?.createSong(jenre: "Dance")
        } else {
            print("\(self.name)は作曲を依頼されてません")
        }
    }
}


let akimoto = Producer(name:"akimoto")
let komuro = PopComposer(name:"komuro")
let nakata = DanceComposer(name:"nakata")

komuro.compose()
komuro.delegate = akimoto // 名刺交換
komuro.compose()

nakata.compose()
nakata.delegate = akimoto // 名刺交換
nakata.compose()

/* 出力
komuroは作曲を依頼されてません
akimotoさんはJPopの作曲を依頼しました
nakataは作曲を依頼されてません
akimotoさんはDanceの作曲を依頼しました
*/
```
水耕栽培セットを自作してみた。

# 概要
最近いろんな水耕栽培キットが出てきているので自作してみた。
目指すのは、水と種をセットしておけば勝手に育って、いい感じに温度とか湿度とかをモニタリングできて、育成過程を記録してくれるもの。

# 構成
- [Raspberry pi3](https://www.amazon.co.jp/Raspberry-%E3%83%9C%E3%83%BC%E3%83%89%EF%BC%86%E3%82%B1%E3%83%BC%E3%82%B9%E3%82%BB%E3%83%83%E3%83%88-Element14%E7%89%88-Computing-Lab/dp/B01CSFZ4JG)
- [SDカード](https://www.amazon.co.jp/gp/product/B015J44QS8)
- [アダプタ](https://www.amazon.co.jp/gp/product/B01COSONFS)
- [USBファン](https://www.amazon.co.jp/gp/product/B00LGM68UM)
- [USBカメラ](https://www.amazon.co.jp/iBUFFALO-マイク内蔵120万画素Webカメラ-HD720p対応モデル-ブラック-BSWHD06MBK)
- [ケース](https://www.amazon.co.jp/gp/product/B00353TEYM)
- [空気ポンプ](https://www.amazon.co.jp/gp/product/B0030IK0JA)
- [チューブ](https://www.amazon.co.jp/gp/product/B00288BI5S)
- [気泡ストーン](https://www.amazon.co.jp/gp/product/B01CTV1MTK)
- [肥料](https://www.amazon.co.jp/ハイポネックス-原液-800ｍｌ/dp/B0027WPD7O)
- [赤LEDテープ2本](http://akizukidenshi.com/catalog/g/gM-03028/)
- [青LEDテープ2本](http://akizukidenshi.com/catalog/g/gM-03027/)
- [温湿度・気圧センサ](http://akizukidenshi.com/catalog/g/gK-09421/)
- [光センサ](http://akizukidenshi.com/catalog/g/gI-05886/)
- 100均スポンジ

# 作成
水耕栽培セット
<img width="640" alt="IMG_2734.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/34652/a92ae3db-df6b-007f-6241-a9ba4d93fda5.jpeg">

- 赤青LEDで光を供給
- 空気ポンプで水を循環
- USBファンで風を送る
- 10分毎にラズパイで温湿度・気圧を取得、送信
- 10分毎に植物の写真を撮る、保存

```:hoge.sh
fswebcam ~/hoge/hoge.png
aws s3 sync ~/hoge s3://bucket --delete
curl -X POST "https:hoge.com/hogehoge" -H "Content-Type: application/json" -d "hogehuga"
```

Webサーバー
<img width="320" alt="IMG_2737.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/34652/330dd4c9-7854-daf5-cbdc-5ca9ba4663ec.png"><img width="320" alt="IMG_2738.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/34652/50700318-42a1-5bc9-ffc0-a0338e1aaddf.png">
ブラウザで現在の植物の写真と温湿度・気圧を見れるようにしました。
今回はHerokuとS3を利用していますが、いずれRaspberryPiで完結するように変更しようかと思います。



構成図
<img width="640" alt="スクリーンショット 2016-11-28 午後4.58.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/34652/fcdec7f8-29c0-5aa9-4af3-488540701457.png">

参考

- [Installing operating system images - Raspberry Pi Documentation](https://www.raspberrypi.org/documentation/installation/installing-images/README.md)
- [RaspberryPiでWebカメラ - Qiita](http://qiita.com/KTaskn/items/2429b4d7d4f0456adf35)
- [ラズベリーパイで温度・湿度・気圧をまとめて取得！AE-BME280でIC2通信 | Device Plus - デバプラ](http://deviceplus.jp/hobby/raspberrypi_entry_039/)
- [Ruby on Rails チュートリアル：実例を使って Rails を学ぼう](http://railstutorial.jp/)
- [crontabの書き方 | server-memo.net](http://www.server-memo.net/tips/crontab.html)
- [AWS コマンドラインインターフェイス | AWS](https://aws.amazon.com/jp/cli/)


# 育成結果
第一世代
<img width="320" alt="IMG_2493.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/34652/60302155-db38-be39-4162-310b51237e9f.jpeg">種を植えて…
<img width="320" alt="IMG_2712.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/34652/cf883dfd-6f8c-25e3-d0a4-2b1e4c4d561b.jpeg">２週間くらいで枯れました…

第二世代
![cap20161128-163001.png](https://qiita-image-store.s3.amazonaws.com/0/34652/330dd832-e9dd-77e2-12a9-a79e135eaed0.png)２週間経過、まだがんばれそう
スポンジに根が張れてなくて倒れたり、光量が足りない？肥料濃すぎ？水が腐ってる？などなど、まだまだ改良の余地がありますがとりあえず２週間枯れずに育つところまではできました。

# これから
- 自動で照明をON/OFFしたい
- 光量を調整したい
#18 【攻略】RubyWarrior Level9 ~中級編~

RubyWarrior攻略です。ついに最終回です。

#概要
最後のステージは全てのマスに敵か捕虜が配置されています。爆弾攻撃で一気に敵を倒したいところですが、捕虜を巻き込んでしまうといけないので使用の際は注意しましょう。


#スクリプト
```ruby 
class Player

  def initialize()
    @bomb = 0
    @walk = 0
  end

  def captive?(warrior)
    if warrior.feel(:right).captive?
      return :right
    elsif warrior.feel(:left).captive?
      return :left
    elsif warrior.feel(:forward).captive?
      return :forward
    elsif warrior.feel(:backward).captive?
      return :backward
    else
      return :none
    end
  end

  def enemy?(warrior)
    if warrior.feel(:right).enemy?
      return :right
    elsif warrior.feel(:left).enemy?
      return :left
    elsif warrior.feel(:forward).enemy?
      return :forward
    elsif warrior.feel(:backward).enemy?
      return :backward
    else
      return :none
    end
  end



  def play_turn(warrior)

    if @bomb < 3
      if warrior.feel.empty?
        if warrior.health < 10
          warrior.rest!
          return []
        else
          warrior.detonate!
          @bomb += 1
          return []
        end
      end
    end

    dir = enemy?(warrior)
    case dir
    when :left
      warrior.bind!(dir)
      return []
    when :right
      warrior.bind!(dir)
      return []
    when :forward
      if @bomb < 3
        warrior.detonate!
        @bomb += 1
        return []
      else
        warrior.attack!
        return []
      end
    end

    if warrior.health < 10
      warrior.rest!
      return []
    end


    if warrior.feel.empty?
      if @walk < 2
        warrior.walk!
        @walk += 1
        return []
      end
    end

    dir = captive?(warrior)
    case dir
    when :left
      warrior.rescue!(dir)
      return []
    when :right
      warrior.rescue!(dir)
      return []
    end




    dir = warrior.direction_of_stairs
    warrior.walk!(dir)



  end
end
```

#解説
@bombは爆弾を投げた回数、@walkは前方に歩いた回数を保存しています。

爆弾を三回投げるとwarriorの目の前とその左右後ろの敵を倒すことができます。
また、前方に歩く回数を指定してあげることで効率良く捕虜を助けることができます。

#全部終えてみての感想

RubyWarriorでやっていてよかったと思ったところは、

- 超基本的なロジックの組み方を反復練習できる(if文とか)

- (作ろうと思えば)メソッドを書く練習ができる

- ゲーム感覚なのに(初心者にとって)程よい難度で成功体験が味わえる

逆によくないなと思ったところは、

- やることが少し単調...？

- Ruby頻出のメソッドとかを学ぶ機会ないので初心者は自分で調べなきゃいけない

ロジックの練習にはなるけど、RubyWarriorだけで完璧になったりとかRubyの組み込みのメソッド組み合わせるとかはできるようにはならないので、知識を補強しながらやるのがいいと思う。
RxJava + Gradle + SublimeTextでHello!

今更ながらRxJavaをやろうと思い立ち検索...
[Gradle で RxJava を動かす](http://qiita.com/hoshi-takanori/items/03e85a599345eaa7e5fb)、[ObserverパターンとHelloWorldからはじめるRxJava](http://qiita.com/chooblarin/items/1cb6a58f6e52b8792c52)見つけた！

わかりやすい！できそう！ということで挑戦しました
（RxJavaやGradleの詳しいことは上の記事を参考にお願いいたします）

## gradleの作成

`Groovy`というPackageをいれると入力の補完をしてくれるので楽チンです！

```build.gradle
apply plugin: 'java'
apply plugin: 'application'

mainClassName=project.main.capitalize()

repositories {
    mavenCentral()
}

sourceSets {
  main.java.srcDirs += './'
}

dependencies {
	compile 'io.reactivex:rxjava:1.1.0'
}

defaultTasks 'run'
```

## SublimeTextでBuild設定
まず、SublimeTextにビルド環境入れよう
ということで、SublimeTextのメニューから`Tools -> Build System -> new Build System...`にアクセスします

```RxJava-gradle.sublime-build
{
    "file_regex": "^(...*?):([0-9]*):?([0-9]*)",
    "selector": ["source.java"],
    "shell_cmd": "gradle -Pmain=\"${file_base_name}\""
}
```
これを`RxJava-gradle.sublime-build`というタイトルで保存します
保存先は`Packages/User/`です

`Tools -> Build System`に`RxJava-gradle`ができてると思いますので選択します

## RxJava
```helloObserver.java
import rx.Observable;
import rx.Observer;

class HelloObserver {

	public static void main(String[] args) {
		String[] names = {"in", "", "taro"};

		Observable.from(names).subscribe(new Observer<String>() {
			@Override
			public void onNext(String name) {
				if (name.isEmpty()) {
					throw new RuntimeException("empty");
				}
				System.out.println("Hello" + name);
			}

			@Override
			public void onCompleted() {
				System.out.println("Good Bye");
			}

			@Override
			public void onError(Throwable e) {
				System.out.println("ERROR: " + e);
			}
		});
	}
}
```
お試しなので、コードがほとんど参考記事の方のままです。すみません。

## 実行
`command+b`または`command+shift+b`で実行です

## 結果
```
:processResources UP-TO-DATE
:classes
:run
Helloin
ERROR: java.lang.RuntimeException: empty

BUILD SUCCESSFUL

Total time: 0.817 secs
[Finished in 1.3s]
```
１人目のinさんもでてるし、空はerrorでてるしいい感じ！

## 追記
RxJavaは考え方から難しそうなので、もう少し勉強して、RxKotlinにもチャレンジします....
Google API Client for pythonでアナリティクス APIからデータ取得その２ webアプリケーション編

前回は[CLI](http://qiita.com/kobarincho/items/b77f78f9514c5b071d94)だったので今回はWebアプリ編

リファレンス
https://developers.google.com/api-client-library/python/auth/web-app

認証情報で承認済みリダイレクトURLの認証が必要
![スクリーンショット 2016-11-28 午後5.36.55.png](https://qiita-image-store.s3.amazonaws.com/0/130570/9a078e85-ce67-aaff-00e1-6eca02a0d06e.png)


作成後JSONデータをダウンロード
![スクリーンショット 2016-11-28 午後5.39.12.png](https://qiita-image-store.s3.amazonaws.com/0/130570/7ee4f59f-1bd8-88a4-2d47-3106d4084e4c.png)

サンプル
djangoを使用しているので、HttpResponseRedirectを利用

```
from oauth2client import client
from django.http import HttpResponseRedirect

flow = client.flow_from_clientsecrets(
    'client_secrets.json',
    scope='https://www.googleapis.com/auth/drive.metadata.readonly',
    redirect_uri='http://www.example.com/oauth2callback')

auth_uri = flow.step1_get_authorize_url()
return HttpResponseRedirect(auth_uri)
```

アカウント認証がされるので任意アカウント選択
![スクリーンショット 2016-11-28 午後5.42.16.png](https://qiita-image-store.s3.amazonaws.com/0/130570/d3f46b40-be53-0deb-0edc-c6cae5257282.png)

承認済みリダイレクトURLで認証codeが取得できるのでそれを使用しアナリティクスデータ取得

```
auth_code = request.GET['code']
flow = client.flow_from_clientsecrets(
    'client_secrets.json',
    scope='https://www.googleapis.com/auth/drive.metadata.readonly',
    redirect_uri='http://www.example.com/oauth2callback')
credentials = flow.step2_exchange(auth_code)
http_auth = credentials.authorize(httplib2.Http())
analytics = build('analytics', 'v4', http=http_auth, discoveryServiceUrl=self.DISCOVERY_URI)
reports = analytics.reports()
reports.batchGet(
                body={
                    'reportRequests': [
                        {
                            'viewId': self.VIEW_ID,
                            'dateRanges': [{'startDate': self.target_date, 'endDate': 'today'}],
                            "dimensions": [
                                {
                                    "name": "ga:productSku",  # 販売した品目の商品コードです。
                                }],
                            'metrics': [
                                {'expression': 'ga:itemQuantity'}  # e コマース トランザクションで売れた商品の数です。
                            ],
                            'pageSize': 50000,
                            'pageToken': "nextpage",
                            "orderBys":
                                [
                                    {"fieldName": "ga:itemQuantity", "sortOrder": "DESCENDING"},
                                ]
                        }]
                }
        ).execute()
```
Visual Studio for Mac（プレビュー版）がついにリリースされた！

先日行われたConnect(); 2016でVisual Studio for Mac（プレビュー版）がリリースされました。
「Visual Studio」とはいっても実際にはXamarin Studioがベースとなっています。
Xamarinについては以前　[Hello！Xamarin](http://qiita.com/tkinjo1/items/c4f1f3107b39679217b1)　という投稿で触れたので詳しいことは省きますが、簡単に説明するとUWP/Mac/iOS/AndroidのアプリをC#を使ってクロスプラットフォームで作ることができる開発ツールです。

クロスプラットフォームでアプリを作ると言うことについては、いろいろな意見があると思いますが、これからアプリ開発に挑戦したい！と言う方にとっては学習コストを考えると良い選択だと思います。

Visual Studio for Macになって変わったことはAndroid、iOS、tvOS、watchOS、macOS 向けの .NET APIが使えるようになったこととバックエンド開発向けの機能が追加されたことだと思います。
最近のアプリは、モバイル側とAzure App Servicesのようなバックエンド側が一体となって機能していることがほとんどだと思うのでバックエンド開発向けの機能が追加されたことはかなりの強みとなると思います。

まだプレビュー版なのでこれからどうなっていくのかがとっても楽しみです。

#インストール
Visual Studio for Macは下記からダウンロードできます。

https://www.visualstudio.com/vs/visual-studio-mac/


インストーラーを実行したらあとは指示に従って進めていくだけで必要なものは全てインストールできます。
![image1.png](https://qiita-image-store.s3.amazonaws.com/0/19516/d86e3145-7580-bce0-8759-5370bf7f3148.png)

<img width="912" alt="image3.png" src="https://qiita-image-store.s3.amazonaws.com/0/19516/a37c0e1a-20b9-10d0-c72c-f2ff475b5f04.png">
![image4.png](https://qiita-image-store.s3.amazonaws.com/0/19516/5a84a6d8-6c6c-f5a7-9215-ad012ab97621.png)
![image5.png](https://qiita-image-store.s3.amazonaws.com/0/19516/acba59d3-3484-32f7-87b7-b89f9a300dab.png)
![image6.png](https://qiita-image-store.s3.amazonaws.com/0/19516/5542632a-9bfd-35f9-fbbf-0ce2f01b149b.png)
![image7.png](https://qiita-image-store.s3.amazonaws.com/0/19516/49b6fe03-6e97-68b4-297d-ac1835334267.png)
![image8.png](https://qiita-image-store.s3.amazonaws.com/0/19516/fa25744f-6c54-2224-5ce7-d1acf1aa78f4.png)
![image10.png](https://qiita-image-store.s3.amazonaws.com/0/19516/2d984cc3-a871-1977-651e-6b1930a3e10d.png)
![スクリーンショット 2016-11-28 17.33.13.png](https://qiita-image-store.s3.amazonaws.com/0/19516/ce9510fd-5e2b-ed41-eb73-85dcead33d50.png)

Getting Startedなど技術情報は下記にあります。
https://developer.xamarin.com

日本語のクイックスタートはエクセルソフトさんのページにあります。
https://www.xlsoft.com/jp/products/xamarin/documents.html
jQuery Typeahead あれこれ

データの指定方法がいくつかあるのでメモ。

基本

```html

<!DOCTYPE html>
<head>
<link type="text/css" rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/cupertino/jquery-ui.min.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>
<script type="text/javascript">

$(function() {
// ここに定義
});
</script>
</head>

<body >

<label for="txtKeywd">キーワード</label>：
<input id="txtKeywd" type="search" size="20" maxlengh="50" />

</body>
</html>

```

データをURLで指定する

```javascript
$(function() {
  $('#txtKeywd').autocomplete({
    source: 'my/method.wss',
    autoFocus: true,
    delay: 100,
    minLength: 1
  });
});

```

データを配列で指定する

```javascript

$(function() {
  $('#txtKeywd').autocomplete({
    source: [ 
        'AAA', 'BBB', 'CCC', 'XXX', 'YYY', 'ZZZ'
   ],
    autoFocus: true,
    delay: 100,
    minLength: 1
  });
});

```


データを関数で指定する

```javascript
function myFunction(req, resp){
    resp([ 'AAA', 'BBB', 'CCC', 'XXX', 'YYY', 'ZZZ']);
}
$(function() {
  $('#txtKeywd').autocomplete({
    source : function(req, resp){myFunction(req,resp);},
    autoFocus: true,
    delay: 100,
    minLength: 1
  });
});

```

データを関数で指定する(2)

```javascript
function myFunction(req, resp){
    resp([ {'label':'AAA','value':'vAAA'},{'label':'BBB','value':'vBBB'} ]);
}
$(function() {
  $('#txtKeywd').autocomplete({
    source : function(req, resp){myFunction(req,resp);},
    autoFocus: true,
    delay: 100,
    minLength: 1
  });
});

```


参考にしたURL

http://www.buildinsider.net/web/jqueryuiref/0019
http://jquery.keicode.com/ui/autocomplete.php
middlemanのsitemapジェネレーター

社内向けというか個人のメモ的投稿です。
同じような内容を書かれてる方はいくらでもいるのであしからずw
***
SEOの基本でもあるsitemap.xml。
今まではbuilderというgemを使ってましたが、この子はmiddleman4X系には対応していないようなので、いつかはアップデートするであろうmiddlemanのために入れ替え（笑）

``` Gemfile.
gem 'middleman-search_engine_sitemap', '~> 1.3.0'
```

3X系の場合は上記のようにバージョンを指定します。
4X系の場合はバージョン指定不要です。

``` config.rb
set :url_root, 'https://www.hogehoge.com'

configure :build do
  activate :search_engine_sitemap
end
```

本番環境のURLをroot_urlにセットし、build時に出力すれば良いので、上記のようにbuildの中に設定する。

```console.
  bundle exec middleman build
```

ビルドしてやるとbuildフォルダの中にsitemap.xmlが生成されます。

``` sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://hogehoge.com/</loc>
    <lastmod>2016-00-00T00:00:00+09:00</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.5</priority>
  </url>
</urlset>
```

changefreqやpriorityなどをこまかくオプション設定できるので以下を参照してください。

[middleman-search_engine_sitemap](https://github.com/middleman/middleman)

# robots.txt
せっかくsitemap.xmlを生成したのだからロボテキも用意しときましょう！

我流なのでスマートな方法があったら教えてください！w

sourceルートにrobots.txt.hamlを用意して以下のように記述

``` robots.txt.haml
User-agent: *
Sitemap: #{url_root}/sitemap.xml
```
root_urlが動けばよいのでテンプレートファイルタイプはHAMLではなくERBでもOKです。

# おわりに
builderだとsitemap.xml.builderというファイルを用意したり、layoutを使わないようにconfigに設定しなきゃいけなかったけど、middleman-search_engine_sitemapならこれらのファイルや設定が不要でいいですね！
Web API: The Good Partsを読んでみて誤字脱字っぽかったところ

# O'ReillyのWeb API: The Good Partsで誤字脱字っぽかったところ

## 対象書籍

[Web API: The Good Parts](https://www.oreilly.co.jp/books/9784873116860/)
ISBN978-4-87311-686-0
第一版(初版1刷)

## なんとなく誤字脱字っぽいように思えたところのリスト

- 9ページ
18行目
  - 原文 : ページの読み込むのと
  - 改案 : ページを読み込むのと or ページの読み込みと

- 53ページ
23行目
  - 原文 : 第X章
  - 改案 : 第6章

- 63ページ
10行目
  - 原文 : クライアント側を返る
  - 改案 : クライアント側を変える

- 97ページ
33行目
  - 原文 : 自体
  - 改案 : 事態

- 97ページ
33行目
  - 原文 : 割ける
  - 改案 : 避ける

- 98ページ
1行目
  - 原文 : 割ける
  - 改案 : 避ける

- 101ページ
11行目
  - 原文 : 新しいく
  - 改案 : 新しく

- 129ページ
6行目
  - 原文 : 送って入れば
  - 改案 : 送っていれば

- 130ページ
4行目
  - 原文 : ウェブAPI
  - 改案 : Web API

(たぶん表記ゆれ)

- 138ページ
12行目
  - 原文 : ある非突然
  - 改案 : ある日突然

- 140ページ
5行目
  - 原文 : 非常にで有名
  - 改案 : 非常に有名

- 141ページ
8行目
  - 原文 : この例はは
  - 改案 : この例は

- 158ページ
19行目
  - 原文 : こうした問題を割ける
  - 改案 : こうした問題を避ける

- 159ページ
4行目
  - 原文 : 誰でもが簡単に
  - 改案 : 誰でも簡単に

(同頁12行目との表記ゆれ)

- 173ページ
2行目
  - 原文 : クライアントとが
  - 改案 : クライアントが

- 173ページ
19行目
  - 原文 : 仕様
  - 改案 : 使用

- 173ページ
22行目
  - 原文 : でてくきます
  - 改案 : でてきます

- 174ページ
5行目
  - 原文 : していらず
  - 改案 : しておらず

- 174ページ
9行目
  - 原文 : 内部構造は知られてしまいます
  - 改案 : 内部構造を知られてしまいます

- 186ページ
10行目
  - 原文 : たとえばたとえば
  - 改案 : たとえば

- 186ページ
24行目
  - 原文 : APIの内容にももちろんよって
  - 改案 : もちろんAPIの内容にもよって

- 186ページ
31行目
  - 原文 : エンドポイントまとめての
  - 改案 : エンドポイントをまとめての

- 198ページ
19行目
  - 原文 : りよう
  - 改案 : 利用

- 199ページ
7行目
  - 原文 : サンドボックス葉
  - 改案 : サンドボックス用

- 202ページ
6行目
  - 原文 : 公開しいている
  - 改案 : 公開している

## 補足

- 上記のリストはO'Reilly Japanのフィードバックページから送信済み 
- 表現としてはどちらでも通るけれどわかりづらいかなと思ったところも挙げたので「正誤」ではなく「改案」とした
  - 文字数を揃えたかったので「改定案」とするところを「改案」とした

## コメントにてお寄せいただいた情報
- 114ページ(表4-3)
  - 原文 : 「RFC 822, updated by RFC 6854」
  - 改案 : 「RFC 822, updated by RFC 1123」
RouterBoardでLTE

USB LTE ドングルを過去色々試してみた(*1)けれど、実は最適解はこうなんじゃないかという気がしてきたので、一度メモにまとめる。

Routerboard と Android スマホを USB ケーブルで繋ぐ。「USB テザリング」を有効にすると、Routerboard からは `lte1` として見える。

![IMG_1588.JPG](https://qiita-image-store.s3.amazonaws.com/0/41883/6ffa8e28-4120-a69f-42ea-803a7ef1fb01.jpeg)

# 設定項目

- Quick Set
    - Country は japan にする
    - Password をセットする
    - SSID, Password, WPA2 をセットする
- Firewall > Filter Rules
    - Add New で lte1 からの input を drop するルールを加える
    - それを ether1 用の同様のルールの下に入れる
- Firewall > NAT
    - エントリの Out.Interface を lte1 に書き換える
- IP > DHCP Client
    - Add New で lte1 を加える

# 解説など
やりたかったことは、こんな感じ。

- 10-20 人ぐらいに対して、uplink が LTE な無線環境を提供したい。
- なるべくコンパクトなシステムで。

WiFi部分は MIMO を使いたかったので、Raspberry Pi で組むことはできない。Routerboard などのデバイスを使いたい。

LTE USB ドングルは製品ごとに仕様が違うので、routerboard がサポートしていない限り使えない。その上、日本の LTE USB ドングルは技適の問題もあって、サポートが追加される見込みがない。LTE バンドも予想以上に頻繁に追加されてきた経緯もあるので、実質的な LTE USB ドングルの製品寿命も短く、サポートリクエストを出すのもためらわれる。

そんな背景で色々考えていると、Android が比較的安価になってきた。Android の USB テザリングは RNDIS という接続方式で、routerboard は RNDIS をサポートしている。これが結構よい感じ。routerboard からは LTE の種別として見える。この最小構成で試してみるけど、負荷が高そうであれば Rasperry Pi を間に追加して masquerade をオフロードすれば良さそう。単純な NAT 箱であれば、初期設定しておけばポン付けで使える。

Raspberry Pi で LTE USB ドングルを終端していたときは、比較的よく切断されるので、mmcli の再接続オペレーションが作業負荷だった。パケット通信量の計算も結構大変なので、Android に備わっている機能を活用したほうが、ずっと楽。SIM 契約での通信料は LTE 網でのもので、netdev のカウンタ値とは全く異なるので大変。


*1) こんな感じで。

- http://qiita.com/kwi/items/b322e28f27f64623bf69
- http://qiita.com/kwi/items/977b70ca85cfe72e7610
- http://qiita.com/kwi/items/a1e92b9ad52abbc3aab8
- http://qiita.com/kwi/items/eb089d05cc3428cddbd8
AIが入ったBotの作り方を学ぼう - Part1 概要と開発環境のセットアップ


# 概要

この記事はLINEで動作する栄養士Botを開発するチュートリアルのPart1です。

食べたものを通常の話言葉でBotに報告すると、その食べ物のカロリー、栄養量を教えてくれる、というシロモノを開発していきます。

![IMG_0104.PNG](https://qiita-image-store.s3.amazonaws.com/0/26079/76f4448f-3564-85c8-2b2b-7ceea337fa48.png "IMG_0104.PNG")


Bot本体のプログラムはNode.jsで開発し、Heroku上で稼働させます。その後、自然言語処理のapi.aiや形態素解析サービス、食品の栄養情報が格納されているクラウドデータベースと連携しながらBotを構築していきます。

![スクリーンショット 2016-11-28 18.08.05.png](https://qiita-image-store.s3.amazonaws.com/0/26079/581a45f5-c18d-3cb5-4e66-9812fcdf2e59.png "スクリーンショット 2016-11-28 18.08.05.png")



> このチュートリアルは[Oracle Cloud Developers Meetupでおこなうワークショップ](https://oracleclouddevelopers.doorkeeper.jp/events/54137)を記事化したものです。実際には動作するBotのデモンストレーションをご覧いただいてから作業に着手する流れとなっています。上図はその完成型のBotのアーキテクチャーで、このチュートリアルでは食事履歴の保存はカバーしない予定です。

今回はまず開発環境をセットアップします。

# 所要時間

20分

# 開発環境のセットアップ

このチュートリアルには下記のソフトウェアが作業マシンにインストールされている必要があります。

- Node
- Git
- Heroku CLI

## Nodeのインストール

[公式サイト](https://nodejs.org/en/)から最新安定版（LTS）をダウンロードしてインストールします。 *2016年11月現在の最新安定板は6.9.1なので本記事ではこのバージョンを想定しています。*

インストールが完了するとnode本体と、パッケージマネージャーのnpmがインストールされます。

## Heroku CLIのインストール

[Herokuの公式サイト](https://devcenter.heroku.com/articles/heroku-command-line)からお使いのOSに応じたHeroku CLIをインストールします。

## Herokuのアカウント作成

下記のサインアップページにアクセスし、必要情報を入力の上CREATE FREE ACCOUNTボタンをクリックします。

https://signup.heroku.com/

![スクリーンショット_2016-11-28_18_17_13.png](https://qiita-image-store.s3.amazonaws.com/0/26079/1988fe30-960d-6db2-be60-8e28f6334096.png "スクリーンショット_2016-11-28_18_17_13.png")


すぐにアクティベーションをおこなうための確認メールが送信されます。このメールにあるリンクをクリックしてパスワードを設定すればアカウント作成は完了です。

ちなみにHerokuでNodeアプリの開発を始めるにあたり、下記のチュートリアルに基本的な作業がまとまっています。それほど時間はかからないので一度目を通しておくとこの後の作業がスムースに運ぶと思われます。

https://devcenter.heroku.com/articles/getting-started-with-nodejs#introduction

# 次のステップ

http://qiita.com/nkjm/items/daa4e34b26ef937446c6

次回はLINEでBotを作成するのに必要なLINEビジネスアカウントを開設します。
型付けされた構成をカスタムIControllerActivatorと同時に使用する

# 最初に補足

[完全版](http://qiita.com/yamaokunousausa/items/bc81d8498ecf62da0208)も参照のこと。

完全版のやりかたの場合、IServiceCollection.Configure()で登録すればIOptional<Setting>の形で、カスタムResolverに直接登録すればSettingの形で取得できる形になります。

# やること

[この例](http://qiita.com/yamaokunousausa/items/1c93740c4cae8e204331)のように、カスタムIControllerActivatorを使用して、カスタムDependency Resolverで型付けされた構成を扱う場合について記述します。

# 型付けされた構成

ASP.NET Coreでは、設定ファイルの内容に対応するクラスを用意して、そのIOptions&lt;T&gt;をDependency Injectionで受け取ることが可能です。

まず、この例を記述します。

## 設定ファイル

以下のような設定のSmtpSettingsセクションについて、型付けされた形で扱えるようにします。

```json:appsettings.json
{
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  },
  "SmtpSettings": {
    "Host": "127.0.0.1",
    "Port": 25
  }
}
```

## 構成クラス

設定ファイルの内容について、型付けされた構成クラスとして以下を用意します。

```csharp
public class SmtpSettings
{
    public string Host { get; set; }

    public int Port { get; set; }
}
```

## 初期化処理

IServiceCollectionのConfigure&lt;T&gt;()拡張メソッドにより、設定ファイルの内容を元にした構成クラスの登録ができます。

```csharp
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();

    // IOptions<T>でのインジェクション有効化
    services.AddOptions();
    services.Configure<SmtpSettings>(Configuration.GetSection("SmtpSettings"));
}
```

## コントローラーでのDI

以下のように、型付けされた構成クラスをDIして使用できます。

```csharp
public class SettingsController : Controller
{
    private SmtpSettings SmtpSettings { get; }

    public SettingsController(IOptions<SmtpSettings> options)
    {
        SmtpSettings = options.Value;
    }

    public IActionResult Index()
    {
        return View(SmtpSettings);
    }
}
```

# カスタムIControllerActivator使用時の問題点

コントローラーにDIされるオブジェクトは、IServiceCollectionではなくカスタムDependency Resolverに登録してやる必要があります。

登録するのはSmtpSettingsのインスタンスになりますが、Configuration.GetSection()で取得される設定ファイルの内容はIConfigurationSectionの形であり、この内容をSmtpSettingsに変換する必要があります。

IConfigurationSectionから構成クラスへの変換は以下の処理で行います。

```csharp
var settings = new SmtpSettings();
Configuration.GetSection("SmtpSettings").Bind(settings);
```

IConfigurationSection.Bind()拡張メソッドにより、設定ファイルの内容を構成クラスのメンバにバインドできます。

なお、カスタムIControllerActivatorでSmtpSettingsのインスタンスを直接扱う場合、コントローラーではIOptions&lt;SmtpSettings&lt;ではなく、SmtpSettingsをインジェクションして貰う形となります。

# うさコメ

カスタムDependency Resolver使用時の話としては、あとFromServicesAttributeの対応なんかもあるのよね(・∀・;)
開発環境をdocker-composeで作ってみた備忘録

自分の備忘録なのでカスでしょうが
チラ裏です。

想定環境
Mac

必要ソフトウェア
Docker for Mac ※1
docker-sync　※2

フォルダ構成
local-dev //ルートディレクトリ基本的にdockerコマンドはここで実行する
├── amznlinux //APPサーバ用設定格納ディレクトリ
│   ├── Dockerfile //APP構築用dockerfile
│   ├── httpd //httpd設定マウント用ディレクトリ
│   │   ├── httpd.conf //この内容がhttpdの設定として読み込まれる
│   │   └── magic //現在の開発環境にあったので必要かはわからないが一応追加してる
│   ├── php //php設定マウント用ディレクトリ
│   │   └── php.ini //この内容がphp.iniとして読み込まれる
│   └── www //APPマウント用フォルダ（ここの内容がwwwへ直接マウント）作業用
├── docker-compose-dev.yml //docker-sync用設定ファイルdocker-syncを利用するため前準備設定
├── docker-compose.yml //docker-compose用ファイル docker-compose up --build時に読み込まれる
├── docker-sync.yml //docker-sync用設定ファイルdocker-sync-stack start時のマウント情報
├── mysql //DBサーバ用設定格納ディレクトリ
│   ├── Dockerfile //DBサーバ構築用dockerfile
│   ├── data_volume //DBデータ格納ディレクトリデータ永続化用
│   └── my //msyql設定マウント用ディレクトリ
│   └── my.cnf //この内容がmy.cnfとして読み込まれる
└── sharedata_mysql //コンテナへのデータ受け渡し用ディレクトリ（データ追加クエリとか）

導入の流れ
1、Docker for Macをインストール
http://paiza.hatenablog.com/entry/docker_for_mac
ここでもみながらテキトーに本当にインストールするだけです。

2、docker-syncをインストール
http://qiita.com/pocari/items/0340049742927f3a94b7
ここでもみながらテキトー（ry
Rubyなので環境がなかったらいれないとgemが使えなかった気がする
エラーがでたら頑張って処理！

3、terminalでdocker_localへcd
おもむろにdocker-compose up --build
5分位待ってるとこんな感じのログで止まったらコンテナ構築は一旦完了
mysql_1 | Version: '5.6.34' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
control + cでコンテナを一旦止める。

4、その場でdocker ps -aでコンテナが作成されているか確認
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
208********* localdev_amznlinux "/usr/sbin/apachectl " 4 hours ago Up 4 hours 0.0.0.0:80->80/tcp localdev_amznlinux_1
008********* localdev_mysql "docker-entrypoint.sh" 4 hours ago Up 4 hours 0.0.0.0:3306->3306/tcp localdev_mysql_1
ec7********* eugenmayer/rsync "/usr/local/bin/run" 4 days ago Up 4 hours 0.0.0.0:10***->873/tcp www
上の2つができてればbuildはOK（STATUSは動いてる時のだから違うよ）

5、この時データ追加用SQLなんかをsharedata_mysqlへ入れとくといいと思うよ。
mysqlに入って事前にデータ入れておきたいからログインしたいけどコンテナが動いてないと
execでログインできないからdocker-compose up -dでコンテナを立ち上げるよ

6、コンテナIDを使ってコンテナへログインするよ。
CONTAINER IDを使用するけど被ってなければ208とか頭の3桁指定すると問題ないよ
今回はmysqlへログインするからlocal-devディレクトリで docker exec -it 008 bashでログインするよ
ログインできたらsource コマンドを使ってsharedata_mysqlにあるsqlを実行しようね。

7、6のクエリの実行はなぜか途中で失敗することもあるから注意してね。
ほんでもって最後はいよいよsyncで立ち上げるよ。
でもそのまえにdocker-compose downでコンテナを一旦停止してね。

8、いよいよ立ち上げるよ
docker-sync-stack startを実行だ！
ログにまた↓が出るからそれがでたら立ち上げは完了だよ
mysql_1 | Version: '5.6.34' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)

9、ホストに127.0.0.1 domainnameを入れるのを忘れずにホストのhostsに設定してね

10、よし！後は野となれ山となれ！

MISSION CMPL RTB
Good Luck

用語解説
※1 dockerです。docker toolboxを利用することでvirtualboxへdocker machineを構築しそこでdockerコマンドを使う方法もありますが、今回はvirtualboxを使用せず、ローカルの仮想環境でdocker コンテナを実行できるdocker for macを対象とします。
参考URL： http://qiita.com/hshimo/items/e24b1fbfbf775ec7c941

※2 現在VMを使用しないdocker for macの場合ブラウザからの読込が非常に遅くなってしまう問題があり、原因はファイルシステムの監視方法だそうで、それを解決するものです。
参考URL： http://cluex-developers.hateblo.jp/entry/2016/11/02/122633
Unity 対象が画面最大になるカメラ距離を算出する

UnityEdior というか Unity での作業フローの良いところは、インスペクタがあり GUI ベースで作業できるところですよね。 
これってモック等ではトライ＆エラー出来て速度アップなんですが、いざ仕様や作業フローが決まって”お仕事”となるとアナログの手入力ってのはミスの元でエンジニア的には排除したい方法なんです。 

#要求仕様
で、今回のお題。 

* 対象のオブジェクト(Mesh等)のサイズは不定、個数も不定、でも画面一杯に描画されるカメラの位置を全て設定したい！ 

こんな場合に、

* 担当が、オブジェクトやカメラの座標をインスペクでN個分のオブジェクトに対して全て UnityEdior で設定する
* その作業を Editor 拡張して Tool 化して作業しやすくした！ 

なんてやってませんか？
実はこの手の設定は、数学的に計算出来て Script による制御で全てまかなえます。

味のあるアナログ設定が欲しいんだよ！ 的な要求仕様ならば仕方ありません、アナログ作業でいきましょう、、

しかしエンジニアの力は、そのアナログ作業がアプリに致命的なバグや不具合を及ぼさないような仕組みやフローに注力するべきです。 
デバッグでチェックするなんて、高度な作業が出来る人間の力という物の無駄遣いの最たるものだと断じます！
(今回の要求仕様のチェックという意味で)

#要件定義
* オブジェクトの大きさは球(円)として持つ(スカラーが1つ)
* 画面の横にフィットさせる(スマフォ縦持ちを想定)

これは今回の説明をしやすくする為で、オブジェクトに縦横の大きさがあり、画面の縦横に対して自動で最大になるように等の細かい要求仕様になるならば、紹介する処理を拡張してください。

#数式
前フリが長くなってしまいましたが、この数式は Unity の[ドキュメント](https://docs.unity3d.com/jp/current/Manual/FrustumSizeAtDistance.html)にもあるんです。 

3Dプログラミングでカメラが出てくると使われる"視錐台"ってやつです。
この視錐台の特定の距離の時に切り出した四角形のサイズが求められるって数式(Unityの)です。

この数式の特定の距離ってのを、今回求める値にします。
その代り、四角形のサイズ(これがオブジェクトの大きさ)は既に分かっている。
つまり、式の変形です。

#コード
Unity の[ドキュメント](https://docs.unity3d.com/jp/current/Manual/FrustumSizeAtDistance.html)ベースで解説します。 

まずオブジェクトの横幅を、特定距離の視錐台の四角形の frustumWidth と捉えます。
そして frustumHeight に変換するためにカメラのアスペクトで除算します。
で、distance(距離)を求める公式にぶち込むだけです(笑)

```C#
public float GetCameraDistanceWithWidthSize(Camera camera, float width) {
    if (camera == null || width <= 0.0f) {
        return 0.0f;
    }

    float frustumHeight = width / camera.aspect;

    return frustumHeight * 0.5f / Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
}
```

これはカメラ真正面から見た距離なんで俯瞰とかしたいなら、この距離のベクトルを回転させて、それをカメラ座標等にすれば良いだけです。

あとは、オブジェクトのカメラの収まりに遊びを持たせたいなら width 値に掛算して小さくしたり(カメラに収まらなくなる)、大きくしたり(余白ができる)等々と、あなたの発想次第！

ともかく色々と拡張やらすれば大抵の事は実装できるはずです。
コピペして意味もわからず使いたいだけ等の方はゴメンなさいとしか(笑)
[Java][Jackson] JSONシリアライズするけど、デシリアライズしないプロパティを定義するtips

フィールドに`@JsonIgnore`アノテーションを付けます。
ゲッターに`@JsonProperty`アノテーションを付けます。
セッターに`@JsonIgnore`アノテーションを付けます。


以下サンプルです。

```java:SampleEntity.java
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

public class SampleEntity implements Serializable {

    @JsonIgnore
    private Integer myId;

    @JsonProperty("myId")
    public Integer getMyId() { /* 省略 */ }

    @JsonIgnore
    public void setMyId(Integer myId) { /* 省略 */ }
}
```
Conohaを使ってserver構築 その2

#第二回 server構築 IP制限
それではここから本題のIP制限のお話をしていきます。
これは一切公開しない、または遊びのためなので間違えないように!
私の場合はただgame serverとして作りたいというだけなので( *´艸｀)

環境
Conoha
CentOS6.7

##初期設定をしよう
まぁ、これはいつもと一緒なのですが記載しておきます!
ここからはすべて、管理者権限で話を進めていきます。
といっても初めはrootしかいないので問題はないかな

```
# yum -y update
# yum -y groupinstall "Base" "Development tools"
```

完全にこれはいつもどおりですね
updateはやっといた方がいいですが他はやらなくても構いません!
(自分はやっときたいだけです。)

## iptablesに記述していこう

ここで注意！
centos7系には標準で入っておりません!
なのでインストールしてあげる必要があります!
今回は7系ではやってないので知りたいという人がいればやろうかなと思います。

とりあえず、自宅(接続したい場所)のグローバルIPを調べましょう。
これがわからない事にはどうしようもありませんからね～
google先生でグローバルIPと検索すればすぐにでも調べられます。

それでは、iptablesにいろいろと記述していきます。

```
# vim /etc/sysconfig/iptables

(下記のように記載する)

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -s xxx.xxx.xxx.xxx/32 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
```

xxx.xxx.xxx.xxxの部分にグローバルIPを記述します。
22ポートはssh用の初期ポートです。
本当は変えた方がいいのですが今回はこのままでいきます。
他ポートを開けるときは

```
-A INPUT -s xxx.xxx.xxx.xxx/32 -p tcp -m tcp --dport 22 -j ACCEPT
(上記の22の部分を変更してあげれば問題ありません)
```

それと

```
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
```

に関しては触らないでくださいね。
それ以外はコピペで問題はないと思います。

それを、保存したら

```
# /etc/init.d/iptables start
# /etc/init.d/iptables save
```

で完了です。間違ってもsaveを先にしないようにしてください。
先にしてしますといままで記述したものがもとに戻ってしまいますので
有効になっているか確認

```
# iptables -L
```

で確認できます。
再起動しても設定が動くように設定

```
# chkconfig iptables on
#chkconfig iptables --list
iptables       0:off   1:off   2:on    3:on    4:on    5:on    6:off
```

このように出れば完了です!

一度ログアウトして、sshで再度ログイン
ログインができればokです！
別ipから接続できるのであれば、確認のために接続できないか確認するのもいいと思います。

##新規ユーザー追加
念のためにrootログインを禁止させます。
そのためにまずはuserを追加

```
# adduser hoge
#passwd hoge
```
でユーザーとパスワードの設定をします。

このままではhogeはsudoが使えないので設定してあげます。

```
# visudo

## Allows people in group wheel to run all commands
#%wheel  ALL=(ALL)       ALL
↓
%wheel  ALL=(ALL)       ALL
```

コメントアウトを外してあげればokです。

ユーザーをwheelグループに所属させてあげます。

```
usermod -G wheel hoge
```

これでhogeをグループに追加させることができました。


```
# su - hoge
(hogeに切り替えて)
#sudo echo "test"
```

さらにログアウトしてhogeでログイン

```
# ssh hoge@xxx.xxx.xxx.xxx
```

でログインできれば完了です。

##sshでrootログイン禁止

さすがにrootでログインできるようにするのは危険なので設定していきます。
といっても難しいことはなく、

```
# vim /etc/ssh/sshd_config

#PermitRootLogin yes
↓
PermitRootLogin no
(保存)
# /etc/rc.d/init.d/sshd restart
```

で完了です。rootでログインできないことを確認しましょう！

##終わり
まぁ、面倒ではあるけどしておかないと危ないですからね～
EC2ぐらい簡単にできてほしいですわ( ﾟДﾟ)
まぁ、楽しいからいいのだけど♪
それではみなさん、良きConohaライフを！