OmniAICreator/Qiita-1.07M huggingface dataset:
[JAWS-UG CLI] SNS:#3 メッセージの配信

AWS CLIを利用して、SNSのトピックにメッセージを送信して、通知先に配信してみます。




前提条件
========


SNSへの権限
-----------

SNSに対してフル権限があること。


AWS CLIのバージョン
-------------------

以下のバージョンで動作確認済

- AWS CLI 1.10.11

```bash:コマンド:
aws --version
```

結果(例):

      aws-cli/1.11.70 Python/2.7.12 Linux/4.4.11-23.53.amzn1.x86_64 botocore/1.5.33

バージョンが古い場合は最新版に更新しましょう。

```bash:コマンド:
sudo -H pip install -U awscli
```


0. 準備
=======

まず変数の確認をします。

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_PROFILE: (0.1) ${AWS_DEFAULT_PROFILE}
        AWS_DEFAULT_REGION:  (0.2) ${AWS_DEFAULT_REGION}
        SNS_TOPIC_ARN        (0.3) ${SNS_TOPIC_ARN}

ETX
```

結果(例):

      AWS_DEFAULT_PROFILE: (0.1) <SNSにフル権限のあるプロファイル>
      AWS_DEFAULT_REGION:  (0.2) ap-northeast-1
      SNS_TOPIC_ARN        (0.3) arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:handson-20170417

変数が入っていない、適切でない場合は、それぞれの手順番号について作業を
行います。


0.1. プロファイルの指定
-----------------------

プロファイルの一覧を確認します。

```bash:コマンド:
cat ~/.aws/credentials \
       | grep '\[' \
       | sed 's/\[//g' | sed 's/\]//g'
```

結果(例):

      iamFull-prjz-mbpr13
      <SNSにフル権限のあるプロファイル>

```bash:変数の設定:
export AWS_DEFAULT_PROFILE='<SNSにフル権限のあるプロファイル>'
```


0.2. リージョンの指定
---------------------

```bash:変数の設定:
export AWS_DEFAULT_REGION='ap-northeast-1'
```


0.3. トピック名の指定
---------------------

```bash:変数の設定:
SNS_TOPIC_NAME='handson-20170417'
```

```bash:変数の設定:
SNS_TOPIC_ARN=$( \
        aws sns list-topics \
          --query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)].TopicArn" \
          --output text \
) \
        && echo ${SNS_TOPIC_ARN}
```

結果(例):

      arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:handson-20170417


再確認
--------------

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_PROFILE: (0.1) ${AWS_DEFAULT_PROFILE}
        AWS_DEFAULT_REGION:  (0.2) ${AWS_DEFAULT_REGION}
        SNS_TOPIC_ARN        (0.3) ${SNS_TOPIC_ARN}

ETX
```

結果(例):

      AWS_DEFAULT_PROFILE: (0.1) <SNSにフル権限のあるプロファイル>
      AWS_DEFAULT_REGION:  (0.2) ap-northeast-1
      SNS_TOPIC_ARN        (0.3) arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:handson-20170417


1. 事前作業
===========


1.1. 通知内容の決定
-------------------

通知するメッセージ(メール本文)内容を決定します。

```bash:変数の設定:
SNS_MSG_BODY='Hello World!'
```


1.2. 表題の決定
---------------

通知するメッセージ(メール)の表題(subject)を決定します。

```bash:変数の設定:
SNS_MSG_SUBJECT='test message'
```


2. 通知の実施 (Publish)
=======================

トピックに対して通知を送信します。

```bash:変数の確認:
cat << ETX

        SNS_TOPIC_ARN:   ${SNS_TOPIC_ARN}
        SNS_MSG_BODY:    ${SNS_MSG_BODY}
        SNS_MSG_SUBJECT: ${SNS_MSG_SUBJECT}

ETX
```

```bash:コマンド:
aws sns publish \
        --topic-arn ${SNS_TOPIC_ARN} \
        --message "${SNS_MSG_BODY}" \
        --subject "${SNS_MSG_SUBJECT}"
```

結果(例):

      {
        "MessageId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
      }


3. 事後作業
===========


着信確認
--------

通知先となっているメールアドレスに、メッセージが着信していることを確認
します。


完了
====
端末に新規アプリがインストールされたらログを吐く


数年前にメールクライアントアプリとか、SNSアプリで課金処理を作成したときに、
ServiceやBroadcastReceiverを使ったんだけど、
ほとんど覚えていないので、 __BroadcastReceiver__ の超簡単なサンプルを作成したのでメモを残す。

## 結論

[こいつを設定すればok](http://developer.android.com/reference/android/content/Intent.html#ACTION_PACKAGE_ADDED)
他にも __Standard__ __Broadcast__ __Actions__ って分類で、色々と種類があって、端末起動時にアプリ起動とかもできるぽい。

今回のサンプルソースはgithubに置きました[ココ](https://github.com/neiraza/BroadcastReceiverSampleForPackageAdded)

## もう少し解説してみる

[AndroidManifest.xml](https://github.com/neiraza/BroadcastReceiverSampleForPackageAdded/blob/master/app/src/main/AndroidManifest.xml)に書いてみたんだけど、下記に該当部分のみ抜粋した。

[<receiver>](http://developer.android.com/guide/topics/manifest/receiver-element.html)の定義をみていて、 _android:exported_ をfalseで追加することにした。こいつを設定することにより __BroadcastReceiverを無効化__しておく。必要になったタイミングで起動すれば良いわけだし。

```XML:AndroidManifest.xml
<receiver
  android:name=".receivers.AppInstalledObserveReceiver"
  android:exported="false"
  android:process=":remote">
  <intent-filter>
    <action android:name="android.intent.action.PACKAGE_ADDED" />
    <data android:scheme="package" />
  </intent-filter>
</receiver>
```

ちなみに、`android:process=":remote"`と書くとアプリと別プロセスで起動する。
[ココ](http://developer.android.com/reference/android/content/BroadcastReceiver.html#ReceiverLifecycle)とか[ココ](http://developer.android.com/reference/android/content/BroadcastReceiver.html#ProcessLifecycle)を見る限り、生成したreceiverはonReeceiverしている間のみで、フォアグラウンドプロセスで起動している。
たぶん、この中でService以外の非同期処理を実行しても、想定と異なるタイミングでプロセスが終了すると思うので注意が必要ぽい。
SlackのURL取得をブロックする

#zabbixからのアラートを簡単に停止
弊社では、監視サーバ(zabbix)からのアラート通知をメールやtwilio、チャットツールなどで受け取っています。また、障害が継続した際にはコメントに何かを書き込めばアラートが停止するようなアクションを設定しています。ただ、毎回zabbixの管理画面にログインをしてコメントを書き込むのは面倒なので、メールやチャットに送られてくるメッセージ内のURLをクリックするとzabbixAPI経由でコメントを書き込む機能を実装しています。

#Slackが自動的にURLにアクセス
現在はSlackへのアラートの通知も行っていますが、Slack導入時に困ったことがありました。
動作テストを行っていると、SlackにURLを記載したメッセージが届た瞬間にzabbixに自動的にコメントが書かれてしまいました。

プログラムを置いているWEBログを見てみると、

```
184.73.125.49 - - [7/Dec/2014:07:07:07 +0900] "GET /stop_alert.php?eventid=777777 HTTP/1.1" 206 87 "-" "Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)"
```

と、AWSのIP帯からSlackbotなるUserAgentからアクセスが...
Slackにはプレビュー機能があるので、そのためにメッセージに書かれたURLにアクセスしていると思われます。


#Slackからのアクセスをブロック
というわけで、WEBサーバ側でSlackのユーザーエージェントからのアクセスを拒否するように設定しました。

```
SetEnvIf User-Agent "Slackbot-LinkExpanding" deny_ua
order allow,deny
allow from all
deny from env=deny_ua
```

これで、Slackからのアクセスをブロックすることができました！
Ciscoの型番 -Eとか-Sとかの意味

## 参考

* [Cisco IOSイメージ - ライセンス](http://www.infraexpert.com/study/ciscoios18.html)
  * [Catalystレイヤ3スイッチのIP Baseと IP Serviceライセンスの違い - Disce gaudere. 楽しむ事を学べ。](http://d.hatena.ne.jp/keroring/20120522/1337649001)
  * [IP ベース イメージと IP サービス イメージの違い | LAN スイッチング | Cisco Support Community | 5481 | 60926](https://supportforums.cisco.com/ja/document/60926)
  * [Cisco IOS Featureを比較する e(config)#ccie enable/ウェブリブログ](http://ccie-study-hajimeta.at.webry.info/200811/article_14.html)
* 価格
  * [CISCO 3750シリーズ | 働き方を変えるワークスタイルイノベーター：トロシステムズ](http://www.trosystems.co.jp/products/switch/ciscocatalyst3750/)

## 意味

* -SはIOSがIP Base
* -EはIOSがIP Service

IP Baseが一番ベースとなるもの。
IP ServiceはIP Base に+αの機能がついたもの。
Python を久々に使う時に役立つメモ


# インデントの役割

Python ではインデントを使ってブロックを表記する。

また、コロン(:)で終わる行がブロックの始まりを表す。

```python
if num == 1:
    print "One."
elif num == 2:
    print "Two."
else:
    print "N/A."
```

# Shebang

Shebang として、 Python スクリプトの1行目に以下を記述する。

    #!/usr/bin/env python

# Coding Style

Coding Style は PEP 8 を参考にする。
PEP 8 とは、Python Community がまとめた Python 向けの Style Guide 。

PEP 8 - Style Guide for Python Code
https://www.python.org/dev/peps/pep-0008/

日本語訳もあります。
http://pep8-ja.readthedocs.org/ja/latest/

 - インデントは「スペース4つ」
 - メソッド名は小文字とアンダースコアーを使う
 - インスタンス変数は小文字とアンダースコアーを使う
 - 定数名は大文字とアンダースコアを使う
   + 例) MAX_OVERFLOW

# サンプルコード

```python:sample.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-

num = 5

for i in range(num):
    print i, ": Hello!"
```
WebRTCで良く使うツールとか

WebRTCに関しては Chrome, Firefox のブラウザによるデバッグツールが多機能なので，
IPレベルのパケットを覗かない限りは大抵で済んでいます．

# Chrome
Chromeでサポートしているツールの一覧は以下に載っています．
最新のChrome v39では使えないものもありますが，大体どんなツールか知るには役立ちます．

[Google Chromeの詳細情報を見る方法 HTTPヘッダー、通信状態など開発者向け情報](http://pentan.info/program/tools/chrome_about.html#anc_about_about)

自分の環境で使えるツールはChromeで以下のコマンドを打つと出てきます．

```
chrome://about/
```

## chrome://webrtc-internals/
Peerセッションのイベントや，シグナリングの経過，送受信中の統計データが確認できる．
対向のPeerとやりとりしている映像サイズ，FPSとかビットレートも見れる．
スマートフォンはこの画面を見ていると，対向から送られてくる受信側のデータしか見れない．
(恐らく，スマートフォン版Chromeはフォアグラウンドの画面しか処理しないため)
SDPのOffer, Answerもセッションごとに見られるので便利です．

# Firefox

## about:webrtc
PeerConnectionごとに，ICE，SDP，RTPの情報をみることができます．
`接続ログ` でICEで交換するCandidateや処理経過を確認することができます．
一方，Chromeと比べるとフレームレートや解像度のグラフが表示されないため，解析性は落ちます．

# ツール
## wireshark
言わずと知れたパケットキャプチャツール．
L3/L4レベルでデータやシーケンスを確認したい場合はコレ．
~~SDPのOffer, Answer~~STUNの様子を確認したいときに良く使います．

[Wireshark](https://www.wireshark.org/download.html)

***
## 未確認だけど役立ちそうなツール

* chrome://net-internals/  
ネットワークの詳細情報．
あまり使ったことはありませんが，ネットワーク周りのトラブルに役立つ様子．

パッと見たら，アクセス中のURLとポートの一覧が出ていました．

* chrome://webrtc-logs  
Chromeのネイティブログを取れるとか．  
下のリンクを見ると，ハングアウトのログは取れるようです．
ハングアウトはWebRTCを使っていたんですね．

[Google ハングアウトのログを取得する](https://support.google.com/a/answer/2978955?hl=ja)
phpでhttp,htttps通信用関数

```php
function get_url_data($url){
    $ch = curl_init($url);
    session_start();
//    curl_setopt($ch, CURLOPT_URL,$url);
    //証明書を無視
    curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
    //タイムアウトの設定
    curl_setopt( $ch, CURLOPT_TIMEOUT, 50 );
    $getCode = curl_exec($ch);
    curl_close($ch);
    return $getCode;
}

// POST用のメソッド
function get_url_data_post($url,$arr){
    $postdata = http_build_query($arr);

    $ch = curl_init();
    session_start();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 50);

    $getCode = curl_exec($ch);
    curl_close($ch);
    return $getCode;
}
```
IE7、8 で filter や opacity を使うとメイリオがジャギる件

教えていただいたのでメモ。

##[前提条件]

* CSS3 グラデーション（filter）を使用
* hoverで透明度（opacity）を変更
* font に「メイリオ」を指定
* filter や opacity を使うと文字がジャギる（＝IE7、8のバグ）

```css
.ttl {
    border-top: solid 1px #7db7e6;
    border-bottom: solid 1px #7db7e6;
    background: #fdfeff;/* IE6 IE7 */
    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startcolorstr=#fdfeff, endcolorstr=#ecf5fc));/* IE8 IE9 */
    -ms-filter:"progid:DXImageTransform.Microsoft.gradient(GradientType=0,startcolorstr=#fdfeff, endcolorstr=#ecf5fc))";
    zoom: 1;	background: -moz-linear-gradient(top, #fdfeff, #ecf5fc);/* FF3.6+ */
    background: -webkit-linear-gradient(top, #fdfeff, #ecf5fc);/* Chrome10+, Safari5.1+ */
    background: linear-gradient(to bottom, #fdfeff, #ecf5fc);/* IE10+, W3C */
}
.ttl a:hover {
    display: block;
    background: #dcf0ff;
    text-decoration: none;
}
```

##[修正後]

* CSS3グラデーション　→　背景画像
* hover時に追加「`-ms-filter: "";`」

```css
.ttl {
    border-top: solid 1px #7db7e6;
    border-bottom: solid 1px #7db7e6;
    background: #fefeff;
    background: url(/img/ttl_bg.jpg) center bottom repeat-x;
}
.ttl a:hover {
    display: block;
    background: #dcf0ff;
    text-decoration: none;
    -ms-filter: "";
}
```

###※ちなみに、これではダメでした。

```css
.ttl a:hover {
    display: block;
    background: #dcf0ff;
    text-decoration: none;
    opacity: 1;
    filter: alpha(opacity=100);
    -ms-filter: "alpha(opacity=100)";
}
```
空コミットで実装前にプルリクエストを出す

# 空コミットとは？

通常、コミットはファイルの変更がないとできないようになっているが、オプション--allow-emptyをつける事で空コミットができる。

```
$ git commit --allow-empty
```


# 用途

## 空のプルリクエストを作る

空コミットを使えば実装に入る前にプルリクエストを出す事ができる。


例えば実装の概要、目的、手順などを他の人に共有したい時やレビューして欲しい時に使える。


# 手順
## ローカルブランチの作成

```
$ git branch {ブランチ名}
$ git checkout {ブランチ名}
```

## 空コミット
```
$ git commit --allow-empty -m "{プルリクエストのタイトル}"
```
## リモートブランチにPUSH

```
$ git push {アカウント名} {ブランチ名}
```

## プルリクエスト
GitHubに行きプルリクエスト。

### 補足
以下のようにMarkDownでチェックボックスを入れるとより便利。
![スクリーンショット 0026-12-22 午後5.08.12.png](https://qiita-image-store.s3.amazonaws.com/0/18614/9be026d5-3a1a-7b8e-88a1-1a40239eb794.png)

ちなみにチェックボックスの書き方は以下のとおり
- [ ] 未完了のタスク
- [x] 完了済みのタスク


以上。
pyQueryでAlexaのWebランクをスクレイピングする

##１．やりたいこと

* アクセス統計サイトAlexaで各国[TOPアクセスランク](http://www.alexa.com/topsites)が公開されている。（1ページ25位分のHTMLｘ20ページで500位まで。）
* HTMLページをスクレイピングしてアクセスランクのURLリストを作る。

**pyQueryを使ってみた。**
Scrapyというライブラリも見つけたけどクローラ込みになっていて面倒そうなので敬遠。
beautifulsoupも良さそうだけど今回はpyQueryを試す。

##２．インストール

```shell-session
$ yum install libxml2-devel libxslt-devel
$ pip install pyquery
```
pyQueryはlibxml2を使っているので先にインストールしておく。
pipが無ければそれもインストールしておく。

##３．参考にしたもの（pyQueryサンプル）

pyQueryのサンプルを試す。試しに[ここ][Ref1]のサンプルコードをお借りして地震情報サイトをスクレイピングしてみた。

```py:pqsample.py
import pyquery
query = pyquery.PyQuery("http://www.jma.go.jp/jp/quake/quake_local_index.html", parser='html')
for tr in query('.infotable')('tr'):
    print query(tr).text()
```
このコードで`class="infotable"`の下層の`<tr>`タグの中身を`for`ループで`print`している訳ですね。
chromeのデベロッパツールでhtmlの方の構成を調べてみると以下の通りでした。

<img width="" alt="" src="https://qiita-image-store.s3.amazonaws.com/0/63281/e2866f18-4be5-0737-13ab-8e7be275eb76.png">

`python pqsample.py`で素直に以下の地震情報が取れた。確かに簡単。
> 情報発表日時 発生日時 震央地名 マグニチュード 最大震度
> 平成２６年１２月０３日１４時３８分 ３日１４時３２分頃 長野県北部 Ｍ１．６ 震度１
> 平成２６年１２月０３日０６時０３分 ３日０６時００分頃 長野県北部 Ｍ２．０ 震度１

##４．Alexaランキング解析

動くことが判ったので本命のサイトのスクレイピングに着手。
chromeで目的のページを開き、デベロッパーツール（CTRL-Shift-I）のウィンドウから虫眼鏡マークを押して、調べたい要素をクリック。下記の様にDOMツリーが表示される。（firefoxな方はインスペクタで調べられます。）

<img width="" alt="DOM tree" src="https://qiita-image-store.s3.amazonaws.com/0/63281/e7031a74-490d-6932-1def-04fe43423035.png">

このツリー構成なら`class="site-listing"`をキーに`<li>`タグをリストアップすればいけそう。`count`に順位が、`desc-paragraph`下の`<a>`タグにドメインが入っている。これらを`for`を回してcsvに出力するコードを書いてみた。

```py:alexa.py
import pyquery

for page in range(20):
    query = pyquery.PyQuery("http://www.alexa.com/topsites/countries;" + str(page) + "/PE", parser='html')
    for li in query('.site-listing')('li'):
        print query(li)('.count').text() + ", " + query(li)('.desc-paragraph')('a').text()
```

今回はペルーのランクを見る為に国コード`/PE`のページを指定。ここに国コードを指定すればその国のページが取得できる。日本なら`/JP`。本コードではHTMLページを20ページ分ループ。`python alexa.py`。

<img width="" alt="result" src="https://qiita-image-store.s3.amazonaws.com/0/63281/792c031c-0be3-df67-7fe6-de72a4c26fbb.png">

csvが出来た。ＮＷ障害などの際のcurlでの復旧確認などに。

##５．まとめ
pyQueryでカット＆ペーストしていた情報をスクレイピング可能。
（※頁構成変更のため現在動作しません。）

## ６．参考サイト
http://d.hatena.ne.jp/kouichi501t/20130407/1365328955
Web系エンジニアにとってタスク管理サービスの"Remember The Milk"が使いやすいたったひとつの理由



使うべきとは言ってない

みんなRTMで快適にタスク管理しよう！

# Remember The Milk(RTM)って？

個人向けのタスク管理サービスだよ。
シンプルで使い勝手の良いUIが気に入って、筆者はもう6年くらいRTMを使っているよ。

最近のタスク管理サービスはよく知らないのでもっといい感じのがあったら教えてね！


http://www.rememberthemilk.com/

# 結論: RTMが使いやすいのはショートカットキーが充実しているから

早速結論がでたね。
ここで文章を終えてもいいんだけど、今日はちょっとだけおしゃべりな気分だから、少しだけ詳しく教えてあげるよ。

## Vimライクな操作でタスクの編集ができる
キーボードショートカットが充実しているから、マウスやトラックパッドまで手を持っていくのが煩わしいWeb系エンジニアには大好評なんだ。

ちなみにカーソルの上下移動は「j」「k」だよ！
エンジニアならこれ以上に使いやすいキーは無いよね！

[Remember The Milk 日本版 公式ブログ &raquo; Tips ： キーボードショートカットで快適タスク管理](http://blog.rememberthemilk.jp/2007/10/tips-：-キーボードショートカットで快適タスク管理/)
[Remember The Milk - Help › What are the keyboard shortcuts?](https://www.rememberthemilk.com/help/?ctx=basics.basics.keyboard)

## タスクのオプションもキーボードのみで素早く指定できる
新しくタスクを追加するときには、一緒に期限や重要度、それに分類用のタグなんかも設定するだろう？
これらがなんと、コマンドラインのコマンドオプションのように設定できるんだ！聞いただけでワクワクしてくるね！
この機能はSmart Add(スマートアド)って呼ばれてるんだよ。

例えば、新しいタスクを追加するときに
「ほむほむのフィギュアと遊ぶ ^明日 !1 *一週間ごと」
って入力すると、タスクに以下のような設定が付与できるよ。
期限: 翌日 (今日は仕事が詰まっているから明日まで我慢しなきゃ！)
重要度: 1 (最も重要な部類のタスクだよ！！)
繰り返し: 一週間ごと (ほむほむのフィギュアと遊ぶタスクが毎週自動的に入ってくるんだ！クールだね！！)

少しは便利さが伝わったかな？
全てのオプションについては以下のサイトを参考にしてくれ！
[「Remember The Milk」にコマンドライン派が喜ぶ「Smart Add」が追加 ｜ ライフハッカー［日本版］](http://www.lifehacker.jp/2009/09/remember_the_milksmart_add.html)

ちなみにオプションを入力するときは「^」などの文字を入れた時点で選択肢が出てくるから、 **上下キーだけでも入力内容が選べるんだ**。
以下のリンクを見るとイメージがつきやすいと思うよ。
[Introducing Smart Add: a smarter way to add your tasks - Remember The Milk Blog](http://blog.rememberthemilk.com/2009/09/introducing-smart-add-a-smarter-way-to-add-your-tasks/)

# あとがき

RTMはスマホ向けのアプリも出ているから、iPhoneやAndroidでも快適に利用できるよ。ガラケー時代でもメールからタスクを追加出来たりして便利だったなぁ。
こんな記事に迷い込んでしまったあなた、今日はちょっとついてなかったね。でもRTMが便利なのは本当さ。エンジニアの人も、そうでない人も、快適なRTMライフを送れることを願っているよ！　;^)
バグトラッキングシステム比較


# 概要
調査する機会があったので共有します。
いま使っているのはBacklogです。

# BTS導入の要件
- ソースコードホスティングサービスとの連携（チケットからすぐにdiffがみれる）
- ソースコードホスティングシステムとの連携がラク
- コードレビューを支援する仕組みがある
- BTS自体は管理したくないので、Saasのやつ。
- Git

# ソースコードホスティングサービス比較
## GitHub Organization Plan
10 private repos for $10 per month
https://github.com/pricing

## GitHub Private Repository
3 private repos for $7 per month

使ってみてわかったが、サードパーティのCLIツールが充実しており、使いこんでゆくと仕事をどんどん効率化できて楽しい。  
diffの表示スタイルもunifiedとsplit両方あってよい。

## Bitbucket
upto 5 users for free
プライベートリポジトリは基本無制限。
Atlassian製品との連携が強そう。（JIRA、hipchat、SourceTree）
GitHubでできることは大体できる感じ？WebHookに関しては未調査。

## Backlog
コードレビューを支援する機能がない。
プルリクエスト機能のリリースが待たれる。

# BTS比較
## redmine
### MyRedmine
¥8,000 per month、32GB
http://hosting.redmine.jp/

高い。。

### Saas Secure（追記）
http://www.saas-secure.com/redmine-hosting/index.html
7ユーロ/月
14ユーロを一回払えば、GitHubとの連携用hookを入れてくれるとのこと。

イイ！かも。

## Backlog
課題のガントチャートが便利。  
課題が増えるとページのロードが重い。。

## JIRA

JIRAは動きがもっさりしていることで有名ですが、実際のところどうなんでしょう。

Issue tracking
10 ユーザー $10/ 月
https://www.atlassian.com/ja/software/jira

Issue tracking and agile project management
10 ユーザー $20/ 月
https://www.atlassian.com/software/jira/agile

ガントチャートプラグイン
$10 / 月
https://marketplace.atlassian.com/plugins/com.soyatec.jira.plugins.jira-ganttchart-project#cloud

## Trello
小規模開発向けで、基本無料ぽい。（追記：有料版もあった）
ドラッグ&ドロップでタスクを操作できるのでとても使い易い。
Slack + GitHub で使うパターンで記事があったりして、最近流行ってきてるみたい。

Ganttify というのと連携すると、ガントチャートにして管理することもできる。
http://www.gantt-chart.com/

コミットのdiffをチケットから見る、
というのはちょっと自動では難しいかもしれないが、
手軽に導入できるし無料だしお得感がある。

## Pivotal Tracker
アジャイル向け。
$18 / MONTH
7 Collaborators
Unlimited Viewers
10 Private Projects
3 GB File Storage
Community Support
http://www.pivotaltracker.com/

## trac
OSSなので基本無料だが、Saas はいまのところない模様なので却下。
評判として、レポートが弱いとよく言われる。自分でSQL書けばできるらしい。
tracpath.comというSaasがあるらしい。

## vsonline
存在を知らなかった
GitHub連携はできないらしい

# 参考
JIRA推しのスライド
https://docs.google.com/presentation/d/1_xabX5gmOqvlWyNVnKC2K7vWHa19noUxzXyAeJlZRmw/edit#slide=id.p

# 今のところ優勝
## 有償部門（リモートメンバーあり）
### Bitbucket + JIRA
Atlassian 製品で固めれば連携がスムーズにできそう。
GitHubと機能的には同じくらい充実している。
ローカライズされているのもありがたい。かも。

## 有償部門（リモートメンバーなし）
### Redmine on Saas Secure
いま関わっているプロジェクトではこちらを利用しています。
プルリクとか使わないならこれで十分だなあ、と思いはじめています。

## 無償部門
### Trello + Ganttify + Github or Bitbucket
コミットの通知自体はslack にしてしまえば事足りる気もするので、
そんなにチケットが乱立するわけでなければこっちでもいいかも？
TodoistやToggl などのタスク管理系アプリも最近結構機能が充実してきているので、
そういうのを使うのもアリかも。

です。
Intel HD GraphicsでTVにHDMI接続すると画面に入りきらない問題対応

TVにHDMI接続した時、画面からはみ出る問題対応。

用語:

* アンダースキャン(underscan) ・・・TVより画面が大きいのを治すこと
* オーバースキャン(overscan)・・・TVより画面が小さいのを治すこと

## 参考

* [resolution - Overscanning picture problem using HDMI with Intel Graphics - Ask Ubuntu](http://askubuntu.com/questions/508358/overscanning-picture-problem-using-hdmi-with-intel-graphics)

## 自分の接続状況を確認

```bash:
$ xrandr -q
Screen 0: minimum 8 x 8, current 1920 x 1080, maximum 32767 x 32767
VGA1 disconnected (normal left inverted right x axis y axis)
HDMI1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 160mm x 90mm
   1920x1080      60.0*+   60.0     59.9     60.0     30.0     24.0     30.0     24.0
   1920x1080i     60.1     60.0
   1280x1024      60.0
   1280x720       60.0     59.9
   1024x768       60.0
   800x600        60.3
   720x480        60.0     59.9
   640x480        60.0     59.9     59.9
   720x400        70.1
DP1 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
```

## 動作テスト

```bash:
xrandr --output HDMI1 --transform 1.05,0,-35,0,1.05,-19,0,0,1
```

テレビの枠に期待通り表示されていることを確認。

## 恒久的に設定

```bash:~/.xprofile
xrandr --output HDMI1 --transform 1.05,0,-35,0,1.05,-19,0,0,1
```
gitでcommit時にファイルのタイムスタンプをcommiter dateに変更する


## 背景
諸事情でファイルのタイムスタンプを厳密に管理する必要があるプロジェクトで
**ファイルのタイムスタンプ　=  commiter date**
としたい状況になった

最初は既にコミット済みのファイルについて、まとめてタイムスタンプを変更したり、
個別にシェルを実行してタイムスタンプを変更していたが、
タイムスタンプを変更するシェルを実行し忘れるのでhookを利用する
なお、Windows環境



### 今まで
1. ファイル編集…A
2. add & commit…B
3. ファイルのタイムスタンプはA
3. 個別に（まとめて）手動でファイルのタイムスタンプをB時点に変更するシェルを実行（←これ面倒で忘れる）


### hook仕込み後
1. ファイル編集…A
2. add & commit…B
3. ファイルのタイムスタンプはA
3. post-commitでcommitしたファイルのタイムスタンプをB時点に都度変更



## コード

post-commitに以下のコードを記載する

```bash:.git\hooks\post-commit
#!/bin/bash
# for post-commit
# ファイルのタイムスタンプをcommiter dateに変更する

for FILE in $(git diff --name-only HEAD HEAD^); do
	TIME=$(git log --pretty=format:%ci -n1 $FILE)
	STAMP=`date  +%y%m%d%H%M.%S --date "$TIME"`
	touch -t $STAMP $FILE
done

```


git使ってるくせに、ファイルのタイムスタンプなんか気にするな
ってとても思いますが諸事情、諸事情
bedtoolsによる異なるChIP-Seqデータのタグ数の比較

## 目的
同一または異なる抗体によるChIP-Seqデータを比較する手段の一つとして、片方のデータで検出されたピーク領域をqueryとして、query領域周辺にマップされたリード数を比較する方法がある。
ここでは、bedtoolsを用いてピーク領域におけるリード数をカウントし、Rでカウントする方法を説明する。

## 方法
### 0. 用意するもの
- ピーク領域を定義するファイル（BED）
- リードのアラインメントファイル（BAM or BED）
- bedtools のインストール
- Rのインストール

### 1. ピーク領域におけるリード数をカウントする
- ピーク領域（query）: peak_0.bed
- アラインメントファイル: mapped_0.bam, mapped_1.bam
- queryで定義された範囲から±100 bp の範囲のリード数をカウントする（awk コマンドの -100と+100）

```
awk 'BEGIN{OFS="\t"}{print $1, $2 - 100, $3 + 100}' peak_0.bed | bedtools intersect -c -a stdin -b mapped_0.bam -bed > result_query_0.txt
awk 'BEGIN{OFS="\t"}{print $1, $2 - 100, $3 + 100}' peak_0.bed | bedtools intersect -c -a stdin -b mapped_1.bam -bed > result_query_1.txt
```

これにより、それぞれのBAMにおいて各ピーク領域に重なるリード数がカウントされる

### 2. ピーク領域におけるリード数を散布図を描いて比較する
- ピーク座標をIDとする
- IDを元に２つのデータフレームをマージする
- 散布図を作成する

```r
d0 = read.table("result_query_0.txt")
paste(d0[,1], d0[,2], sep = ":")
colnames(d0)[ncol(d0)] = "tag0"

d1 = read.table("result_query_1.txt")
d1 = cbind(id = paste(d1[,1], d1[,2], sep = ":"), d1)
colnames(d1)[ncol(d1)] = "tag1"

d = merge(d0, d1, all = T)

plot(d$tag0, d$tag1)
```

## 資料
BED format: http://bedtools.readthedocs.org/en/latest/content/general-usage.html
bedtools: http://bedtools.readthedocs.org/en/latest/index.html
Rのmerge関数: http://cse.naro.affrc.go.jp/takezawa/r-tips/r/43.html
Google::APIClient::FileStorageのwrite_credentialsでこける


http://qiita.com/niku4i/items/294abc8fec33b6cc301f

を参考にやってみたけどうまくいかなかったのでメモ。

# 発生したバージョン

google-api-clientの`0.8.1.1`で発生。

# エラー内容

```
`write_credentials': undefined method `authorization=' for #<Google::APIClient::FileStorage:0x007fbecca58b78> (NoMethodError)
```

みたいなエラーが出て認証情報を保存できなかった。

`google-api-client-0.8.1.1/lib/google/api_client/auth/file_storage.rb`

を見てみると`deprecated`で`Google::APIClient::Storage`と`Google::APIClient::FileStore`を使えと書いてあった

# というわけで

http://qiita.com/niku4i/items/294abc8fec33b6cc301f

のsetupメソッドを以下のようにしたら動いた

```
def setup()
  client = Google::APIClient.new(application_name: 'Sample', application_version: '1.0.0')
  store = Google::APIClient::FileStore.new(CREDENTIAL_STORE_FILE)
  storage = Google::APIClient::Storage.new(store)
  storage.authorize

  if storage.authorization.nil?
    client_secrets = Google::APIClient::ClientSecrets.load

    flow = Google::APIClient::InstalledAppFlow.new(
      client_id: client_secrets.client_id,
      client_secret: client_secrets.client_secret,
      scope: %w(
        https://www.googleapis.com/auth/drive
        https://docs.google.com/feeds/
        https://docs.googleusercontent.com/
        https://spreadsheets.google.com/feeds/
      ),
    )

    client.authorization = flow.authorize
    storage.write_credentials(client.authorization)
  else
    client.authorization = storage.authorization
  end

  return client
end
```
UITableView relaodData をバックグラウンドスレッドから呼ぶと大変なことになる話


UIViewはスレッドセーフじゃないので、UIViewまわりの処理をバックグラウンドからやっちゃいけないのは常識なんですが、とはいえうっかりやっちまうことがあります。
うっかりやっちまうと、いわゆるボーアバグ的な状態になって、デバッグやってらんねーって状況になるし、そもそもバグの原因箇所をまともに見つけられなくなってお蔵入りになることすらあります。

普段からきちんと気をつけて記述しておいたり、NSAssertを使ったり
速度面に問題がないならむやみにバックグラウンドを使わなかったりというのが肝要ですが、今回は厄介な問題を見つけたのでご紹介。

## willMoveToSuperViewなどのメソッドがバックグラウンドから呼ばれることがある

UIViewには、そのビューがaddSubviewされたとき(とか)に呼ばれる メソッドがあります。 以下の4種類です。

- willMoveToSuperView
- didMoveToSuperView
- willMoveToWindow
- didMoveToWindow

これらのメソッドは、UIViewControllerでいうviewWillAppearと似たノリで使えて便利なのですが、こいつらがバックグラウンドスレッドから呼ばれるケースがあることを発見しました。

まぁ表題のケースなんですが、UITableViewのreloadDataをバックグラウンドスレッドから呼んでしまうと、そこから生成するUITableViewCellの上記4メソッドがバックグラウンドスレッドから呼ばれます。 その中でUIViewを弄ってると、最悪の場合クラッシュします。 これ、スタックトレースにはどこが諸悪の根源なのかさっぱり書いてないので、追うのが大変です。

## その他デバッグに便利な手法

* NSAssertで[NSThread isMainThread]をチェックする
* method_swizzlingでisMainThreadじゃなかったらデバッグログを吐く処理を本来のwillMoveToSuperView実行前に差し込む
* 同様にmethod_swizzlingを用いて、UITableViewがreloadDataされる直前にisMainThreadをチェックするコードを差し込んでバグの原因を探る

## 雑感

Swiftで型安全になってもスレッドの問題はまだまだ解決しなそうなので、iOSアプリエンジニアとしては押さえておきたい知識です。
日付フォーマット文字列チートシート


DateクラスやTimeクラスの`strftime`メソッドの引数で指定するフォーマットを自分用にメモ。
サンプルとして使用する日付は「2014年12月22日(月) 12:34:56 JST」とします。

| フォーマット文字列 | 結果 | 主な用途や使用例 |
|:--------------------------|:-------|:-----------------------|
| %Y-%m-%d %H:%M:%S | 2014-12-22 12:34:56 | MySQLのdatetime |
| %Y-%m-%dT%H:%M:%S%z | 2014-12-22T15:32:04+0900 | RSS1.0の\<dc:date\>タグ |
| %a, %d %b %Y %H:%M:%S %z | Mon, 22 Dec 2014 15:32:04 +0900 | RSS2.0の\<pubDate\>タグ |
illustratorCCで簡単にパターンを作成＆登録する方法

## パターンを作成する
通常、パターンを作成するというと一からシェイプをつなぎ合わせたり、変形させたり並べたりして作りますが、わたしは無料の画像素材を使っています。「チェック　無料素材」などでググるとたくさん出てきます。

**「パターンを作成する」という作業は無料素材の職人さんの力をまるごと借りてしまう！というわけです。**

自分で一から作りたい人にはおすすめできませんが、パターンを今すぐ作って使いたいんだ！という人やわたしのように面倒くさがりな人には非常におすすめの方法です(>o<)

無料素材を拾ってきたら、新規ドキュメントに貼付けていきましょう。
次にパターンを登録する方法です。これは他人任せにできない作業なのでしっかりとやっていきましょう。簡単です。

## パターンに登録したいものを選択する
コマンドキー＋クリックで画像を選択します。
ひとつずつしか登録できないので、地道な作業が始まります。
まとめてやってしまえばあとあと楽なので今は我慢しましょう。
![スクリーンショット 2014-12-21 21.43.05.png](https://qiita-image-store.s3.amazonaws.com/0/63640/cd6741db-eb61-078e-9c72-d80ac52eb7cd.png "スクリーンショット 2014-12-21 21.43.05.png")


## オブジェクト＞パターン＞作成
![スクリーンショット 2014-12-21 21.43.33.png](https://qiita-image-store.s3.amazonaws.com/0/63640/6b3a756b-ff28-3f4c-00ff-db5608ee255c.png "スクリーンショット 2014-12-21 21.43.33.png")

## パターンの仕上がりを確認
今回は無料素材を使っているのでほとんどが正常にパターン化されると思いますが、自作のパターンの場合はズレてしまったり思ったようなパターンにならないことがあります。
そんな時は幅や高さを変更することで調整することができます。
![スクリーンショット 2014-12-21 21.44.23.png](https://qiita-image-store.s3.amazonaws.com/0/63640/a2c22869-297d-e2cf-3379-fdf3b538a2ce.png "スクリーンショット 2014-12-21 21.44.23.png")

## パターンに任意の名前をつける
今回は「test01」としましたが、このスウォッチパターンはギンガムチェックなので通常なら分かりやすく「red_gingham」などとつけます。
![スクリーンショット 2014-12-21 21.45.01.png](https://qiita-image-store.s3.amazonaws.com/0/63640/4f656fbf-aa23-0666-98d5-6dc76f512c26.png "スクリーンショット 2014-12-21 21.45.01.png")


## ウインドウ＞スウォッチでスウォッチを開いて確認する
![スクリーンショット 2014-12-21 21.45.28.png](https://qiita-image-store.s3.amazonaws.com/0/63640/3cbb5be5-f96f-5265-7127-3edb24598bc8.png "スクリーンショット 2014-12-21 21.45.28.png")

![スクリーンショット 2014-12-21 21.46.14.png](https://qiita-image-store.s3.amazonaws.com/0/63640/a5fabfb8-9dde-d2a2-14cb-36aa4c412cbd.png "スクリーンショット 2014-12-21 21.46.14.png")

一番後ろにちゃんと登録されています！
実は、このスウォッチライブラリは不必要なスウォッチパターンを削除して綺麗に整理整頓されています。
みなさんの開いたスウォッチライブラリはいろんな色や既存のパターンなどが登録されたままだと思うので、もう少しごっちゃりしているかもしれません。
整理整頓したい人は[スウォッチライブラリからいらないスウォッチパターンを削除する方法](http://qiita.com/mikuhonda/items/be7fcfa3cd90acb1acbf)を参考にしてみてください。

そして、このままだと新規ドキュメント作成時にはこのスウォッチパターンが使えません。
[作ったスウォッチライブラリを新規ドキュメント作成時にも使用できるようにする方法](http://qiita.com/mikuhonda/items/1cdc62684897fa22a6bd)も紹介しています。
illustratorCCで作ったスウォッチライブラリを新規ドキュメント作成時にも使用できるようにする方法

![logofix.png](https://qiita-image-store.s3.amazonaws.com/0/63640/f8cd83e7-bbe7-c686-5507-ca41b05eb9f8.png "logofix.png")

- たしかにパターン登録したはずなのに、新規ドキュメントを開いて使おうとしたら、パターンが反映されてない！
- 「ジャイブ」や「Alyssa」、「金の指輪」など既存のスウォッチパターンしかない！

なぜなの・・・？！(>o<)

![スクリーンショット 2014-12-21 21.57.41.png](https://qiita-image-store.s3.amazonaws.com/0/63640/8b0f4da2-3234-e7a3-4149-27bb38d88e0a.png "スクリーンショット 2014-12-21 21.57.41.png")

と、思って調べていたのですが、仕方がないことのようです。

でも、
**別ドキュメントで作成したスウォッチライブラリを新規ドキュメントで使用する方法**
がいくつかあるようです。

今回はわたしが一番使い勝手が良いと思った方法を紹介します。



## まずはスウォッチパターン専用ドキュメントを作る
![スクリーンショット 2014-12-21 21.49.24.png](https://qiita-image-store.s3.amazonaws.com/0/63640/3e7d61cc-72b2-e969-76e5-1fbd1dede751.png "スクリーンショット 2014-12-21 21.49.24.png")

私は無料素材からパターンの作成をしようと思うので、その画像を貼付けています。これをスウォッチパターン専用ドキュメントとします。
このドキュメント上で、パターンの登録をします。

**ポイントは登録したいパターンを同じドキュメントにまとめることです。**

*※[パターンの登録方法は別の記事で詳しく書きますので省略します。](http://qiita.com/mikuhonda/items/63dada8a99946fe9c8fe)*

*※無料素材を使わずにオリジナルのパターンを作成する方は、オリジナルのパターンを作成しているドキュメント上で新しいアートボードを作成し、あとは同じようにパターンを貼付けて並べてください*

## スウォッチを開いてみる
スウォッチを開いてみるとこのドキュメントで登録をしたパターンが入っています。
![スクリーンショット 2014-12-21 22.27.20.png](https://qiita-image-store.s3.amazonaws.com/0/63640/21e66170-d830-a9dd-6cfd-c183967a67c4.png "スクリーンショット 2014-12-21 22.27.20.png")


おっと！同じパターンが二つ登録されてしまっていますね(>o<)
*※[いらないパターンを削除する方法も別の記事で詳しく書いてありますので省略します。](http://qiita.com/mikuhonda/items/be7fcfa3cd90acb1acbf)*


## このスウォッチをスウォッチライブラリとして保存する
左下のスウォッチライブラリメニューをクリックして、
![スクリーンショット 2014-12-21 21.50.02.png](https://qiita-image-store.s3.amazonaws.com/0/63640/c8fe1c30-c7e2-5027-f84a-e710474d08a1.png "スクリーンショット 2014-12-21 21.50.02.png")

「スウォッチを保存」でスウォッチをライブラリとして保存します。
![スクリーンショット 2014-12-21 21.50.13.png](https://qiita-image-store.s3.amazonaws.com/0/63640/a02465cf-97da-8fb8-e04d-508730dbf2c6.png "スクリーンショット 2014-12-21 21.50.13.png")

タイトルは、パターンを良く作成する人ならテーマや使うシーンにちなんだものをつけるとわかりやすそうです。
私は趣味以外ではあまり使わないので「Swatch_library」としました。
![スクリーンショット 2014-12-21 21.50.22.png](https://qiita-image-store.s3.amazonaws.com/0/63640/9f81dc37-040f-04d0-ec09-49ecce07568a.png "スクリーンショット 2014-12-21 21.50.22.png")

これで完成です！！
もうどのドキュメントでも、このスウォッチライブラリを使用することができます。

## 登録したスウォッチライブラリを新規ドキュメントで開く
登録したスウォッチライブラリの使い方はすごく簡単です。
**ウインドウ＞スウォッチ＞左下のスウォッチライブラリメニューをクリック＞ユーザー定義＞"自分のつけたスウォッチライブラリ名"**

![スクリーンショット 2014-12-21 21.50.37.png](https://qiita-image-store.s3.amazonaws.com/0/63640/a98dbcad-3704-34e1-e1f8-9727946f8e66.png "スクリーンショット 2014-12-21 21.50.37.png")

これで使うことができます。

## このスウォッチライブラリを常に表示させる
実はこのままではこのスウォッチライブラリのウインドウを閉じるたびに、またユーザー定義＞"自分のつけたスウォッチライブラリ名"と面倒な動作をすることになってしまいます。
このスウォッチライブラリをすぐに使える状態にする方法も紹介します。

**ウインドウ＞スウォッチ＞左下のスウォッチライブラリメニューをクリック＞ユーザー定義＞"自分のつけたスウォッチライブラリ名"**

で開いたスウォッチライブラリの右上のボタンをクリックして、固定を選択します。

![スクリーンショット 2014-12-21 21.51.33.png](https://qiita-image-store.s3.amazonaws.com/0/63640/d890f02d-6082-b4a4-b4b3-f0af3fab3366.png "スクリーンショット 2014-12-21 21.51.33.png")

これでillustratorを起動する度に、このスウォッチライブラリが表示されます。

## スウォッチライブラリのパターンを新しく登録する
更にスウォッチライブラリのパターンを新しく登録して増やしたいときは、最初に作ったスウォッチパターン専用ドキュメントを開いて、そこに追加したいパターンを貼付けてパターン登録するだけです。
AndroidStudioにPureJavaなプロジェクトをimportする

eclipse時代に使っていたPureJavaなライブラリプロジェクトをimportしたい

【結論】
できない

と言うのもアレなので、まずAndroidアプリのプロジェクトを作る
→New Moduleで下のリストから「Java Library」を選んで適当にクラスを作る(パッケージ名は正しく）
→いったんOKする
→必要なソースコードを上記で出来たフォルダにコピペ
→Refresh or Sync and Clean

で、なんとか・・・

※いやいや、あるよ！ってご存じの方いたら教えてください・・・
AndroidStudioでプロジェクト名・プロジェクトフォルダを変更する

1時間くらいハマったのでメモ。

例）MyProjectA→MyProjectBにフォルダ名やプロジェクト名を変更する

旧構成）
プロジェクトルート＝MyProjectA

MyProjectA
 +.gradle
 +.idea
 +app
 +build
 +gradle
 MyProjectA.iml
...

(1)プロジェクトルートのフォルダ名を変更する
>MyProjectA→MyProjectB

(2)プロジェクトルート直下の以下のファイル名を変更する
>MyProjectA.iml→MyProjectB.iml

(3).ideaフォルダ直下のファイル内のimlファイル名やフォルダ名を置換する
module.xml内
>MyProjectA.iml→MyProjectB.iml

workspace.xml内
>たくさんあるのでテキストエディタの一括置換などで

(4).ideaフォルダ直下の.nameファイルを開いてプロジェクト名を変更する
>MyProjectA→MyProjectB

ついでにアプリのパッケージ名も変更する場合は、以下を変更してからプロジェクトを開き直せばOK.

・javaフォルダパスを実際に変更(*)
・ソースファイルのパッケージ名を変更(*)
・ソースファイルのimportパッケージ名を変更（特にRのimport）(*)
・AndroidManifest.xmlのパッケージ名を変更

AndroidStudioを開き直したら、RefreshとかSyncとかCleanとかして再ビルド。

(*)AndroidStudioのリファクタリング機能でやれば早いかもしれないが、いまいち信用していないので
emacsclient がちょっと使いづらいので

__tl;dr__ [ラッパースクリプト](https://github.com/kui/dotfiles/blob/master/bin/emacsclientw) を作った。

辛い点
----

いろいろ機能を盛り込むと emacs の立ちあげが重くなるので、立ちあげっぱなしにしたくなる。

そうなると、シェルのカレントディレクトリのファイル開くのに emacs にファイルパス入れるの面倒なので、CLI から既に立ち上がっている emacs に開いてほしい。

そこで `server-mode` + emacsclient の出番。しかし、emacsclient は emacs が立ち上がってないと通信先がいないのでファイル開くのに失敗する。

そのために用意された `-a` オプションを使ってこう実行すると:

```bash
$ emacsclient -a '' somefile
```

emacs が daemon モードかつ `server-mode` 実行して立ち上がる。しかし現在のシェルではなく別窓で開いてほしいとか GUI 使いたいとかの場合は `-a` ではダメ。また daemon モードで `-n`/`--no-wait` を開くと大変わかりづらくなる。

[EmacsWiki: Emacs Client](http://www.emacswiki.org/emacs/EmacsClient#toc5) の Starting Emacs automatically を参考にしても、デスクトップとして使っている時と ssh ログインした時で GUI にしてほしい時と screen で新たに開いてほしい時が違う、リトライ上限は？、既に別 screen で立ち上がってる emacs で開いてしまう、などがありつらい。

問題点をまとめると:

* emacsclient の emacs 自動立ちあげに不満
    * daemon モードに若干不満がある
    * ある面で便利なのは分かる
* emacswiki に提示されている簡易自動立ちあげスクリプトには問題がある
    * 例えば X で emacs が立ち上がっている状態で ssh ログインして emacsclient を使うと ssh のシェルではなく X の方の emacs で開いてしまう
        * 要 `server-name` の自動割り当て
    * リトライ上限ほしい
        * `init.el` 失敗すると延々とリトライし続ける

書いた
------

問題点というかワガママを通すため && Python の習作を兼ねて emacsclient ラッパースクリプトを書いた:

* [emacsclientw](https://github.com/kui/dotfiles/blob/master/bin/emacsclientw)

emacs と emacsclient にパスが通っているのと Mac の GUI で使う場合は `open -a Emacs` が実行可能な状態を前提にしている。

基本的には emacsclient と同じ使い方でいいが、以下の違いがある:

* 対象の emacs が立ち上がってない場合は自動で立ちあげてくれる
* `init.el` の設定は不要
    * むしろしていると、下記の `server-name` 自動命名がうまく動かないかも
* `server-name` は、X か Mac か screen かで自動的に命名してくれる。 
    * screen の時はその screen 毎に命名するので、複数 screen 立ちあげていてもそれぞれで emacs が立ち上がる
* 追加機能として `echo foo | emacsclient -` みたいにすると標準入力から受け取った文字列で新たなバッファを作る

使い方
--------------

前述したとおり emacsclient と同じだが、具体的にはこういった使い方をしている:

```bash:zshrc
if which emacsclientw &> /dev/null
then
    alias e="emacsclientw --no-wait"
    export EDITOR=emacsclientw
fi
```

こうすると:

```bash
$ e somefile
# 現在の環境の名前の emacs が立ち上がってないなら、立ちあげてから emacsclient を実行する
# 立ち上がってるならそのまま emacsclient 実行
$ git commit
# emacsclient を使ってコミットメッセージを編集
```

みたいなことができるようになる。

まとめ
--------------------------

emacsclient を `server-name` 自動割り当てして自動で立ちあげてくれるラッパースクリプトを作った。

emacswiki の該当ページも半分も読んでないのでもっといい方法ある人教えてください。
Facebookログイン機能で必要な環境変数の設定について

RailsのアプリでFacebookログイン機能の実装で、初心者エンジニアとして一番始めに詰まってしまった。環境変数の設定について記録したいと思います。今回は、localhost:3000からのアクセスだと考えてください。また今回は、Deviseのような認証管理gemは使わずに、facebook-Omniauthだけでのログインを可能にするようにしました。


#エラー表示
localhost:3000/auth/facebook にアクセスしてもこのようなエラーが表示されてしまうという状態になってしまいました。どうやら、app_idが必要ですと怒られているようです。

![スクリーンショット 2014-12-22 14.56.30.png](https://qiita-image-store.s3.amazonaws.com/0/48577/a4c4ae56-329f-0b9a-262e-87ac1405e0ad.png)


#configの設定の確認
一番初めに、こちらで環境変数を設定しました。コレで完了かと思っていました。

```lang:config/initializers/omniauth.rb
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET']
```

#コマンドラインからの環境変数の指定
コマンドラインから以下のように環境変数が設定すると、ログイン認証画面を表示させられました。

$ export FACEBOOK_APP_ID="228170250716853"
$ export FACEBOOK_APP_SECRET="3f6e78730a2bb99273dc2aa33d89297d"
9.4への更新


```brew upgrade```したところ、最新版の9.4に更新されました。
DB形式が9.3のままでは、起動しないないので、```pg_upgrade```します。

```bash
$ cd /usr/local/var
$ mkdir postgres94
$ initdb postgres94 -E utf8
$ pg_upgrade \
  -d /usr/local/var/postgres \
  -D /usr/local/var/postgres94 \
  -b /usr/local/Cellar/postgresql/9.3.5_1/bin/ \
  -B /usr/local/Cellar/postgresql/9.4.0/bin/ \
  -v
$ mv /usr/local/var/postgres /usr/local/var/postgres93
$ mv /usr/local/var/postgres94 /usr/local/var/postgres
$ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
```
python / リストからdictを作る。


# はじめに
リストからDictを作る。個人的によく使う、numpyのloadtxtを使うので、numpy_arrray型ですが、別にlist型でも問題無く使える。
{"hoge":(hoge1,hoge2,hoge3,…}といった辞書型を作れる。

(備忘録)
# 
1. 適当に配列を作る。ここでは、a,b,cとする。
 - aをkey、bおよびcを値とする。
2. まずzip()で、bおよびcをtupleにする。(_bcとする)
3. その後、dict()で、aと_bcをくっつける。

```python:list2dict.py
import numpy as np
a,b,c = np.arange(10), np.arange(10)*2, np.arange(10)*3

#-> a: [0 1 2 3 4 5 6 7 8 9]
#-> b: [ 0  2  4  6  8 10 12 14 16 18]
#-> c: [ 0  3  6  9 12 15 18 21 24 27]

_bc = zip(b,c)

result = dict(zip(a,_bc))
#-> {0: (0, 0), 1: (2, 3), 2: (4, 6), 3: (6, 9), 4: (8, 12), 5: (10, 15), 6: (12, 18), 7: (14, 21), 8: (16, 24), 9: (18, 27)}

# result = dict(zip(a,zip(b,c)))でもイイ。
```
おしまい。
phpDocumentorの書き方

phpDocumentorの書き方
=================

phpDocumentorの書き方ってこれ！っていうベストプラクティスがなくて（ドキュメントとはそういうものなのかもしれないけど…）、毎回試行錯誤して、フォーマットを考えるだけでも時間を取られるので、一度自分なりのフォーマットをまとめたいと思います。

今回は、クラスとメソッドについてまとめています。
プロパティについても書いたほうがドキュメントとしてはよいと思うのですが、プロパティまで書き出すとなかなか継続出来ない（ダメ人間です）ので、追々。。

ちなみに、CakePHPをやんわり想定しています。

では、まずクラスについて。

クラス：フォーマット
-----------

```
/**
 * [区分]クラスの概要
 *
 * クラスの詳細
 * 出来るだけ細かく書いたほうがよいが、詳細な説明は各メソッドに任せる。
 * 全体での共通ルールとか仕様を書く。
 *
 * @access アクセスレベル
 * @author 名前 <メールアドレス>
 * @copyright 会社名 All Rights Reserved
 * @category カテゴリー（処理系）
 * @package パッケージ（MVC）
 */
```

### 説明

区分には、[API]とか[CMS]とかそういった情報を書く。
カテゴリーは、基本的には処理単位というかコントローラーとモデルがセットになるようにする。
ただし、CakePHPの場合、モデルクラスがアクティブレコードを持つように（僕は）設計することが多いので、アクティブレコードのクラスは"ActiveRecord"とする。
あと、あんまりないですが、個別にバリデーションクラスを用意しているときは、"Validation"とする。
パッケージは、コントローラーだったらContoroller、モデルだったらModelと書く。

具体的にはこんな感じ。

クラス：具体例
--------

```
/**
 * [API]メッセージ送信系APIコントローラークラス
 *
 * メッセージ送信に関するAPIをまとめたコントローラークラス。
 * エンドポイント単位でメソッドを定義する。
 *
 * @access public
 * @author itosho <hogehoge@example.com>
 * @copyright  hogehoge Corporation All Rights Reserved
 * @category Message
 * @package Controller
 */
```

では、次にメソッド。

メソッド：フォーマット
-----------

```
/**
 *  [区分]関数の概要
 *
 *  関数の詳細
 *  出来るかぎり細かく書く！でもシンプルに！（難しい）
 *
 * @access アクセスレベル
 * @param 型 パラメーター名（物理名） パラメーター型名（論理名）
 * @return 型 戻り値（物理名） 戻り値（論理名）
 * @see 関連（呼び出したり）する関数
 * @throws 例外についての記述
 * @todo 未対応（改善）事項等
 */

```

### 説明

区分は、クラスと同じような感じか、リクエストメソッドで分けているときは、[POST]とか[GET]とか書く。
が、メソッドの場合は、書かなくてもよいこととする。
パラメーター（引数）と戻り値は必ず型も書いて、物理名だけじゃなく論理名も書く。
see、throws、todoは必要と（やる気）に応じて書く。

メソッドはコントローラーとモデルでタグが違うことが多いので、それぞれ具体例を書きます。

メソッド：具体例（コントローラー）
---------

```

/**
 * [POST]メッセージ送信APIのコントローラー関数
 *
 * 即時送信の場合は、実際にメッセージ送信処理を行う。
 * 予約送信の場合は、メッセージの登録処理のみを行う。
 *
 * @access public
 * @see MessageApi::paramCheck
 * @throws NotFoundException メッセージがない場合は404エラーを返す
 */

```

メソッド：具体例（モデル）
---------

```

/**
 * メッセージ登録処理用の関数
 *
 * メッセージ登録後、送信者情報も更新する。
 * 送信者情報の更新はREPLACE INTOで更新する。
 *
 * @access public
 * @param array $sender
 *        	送信者情報
 * @param array $params
 *        	リクエストパラメーター
 * @return integer $messageId メッセージID（エラー時は0）
 * @todo パフォーマンス改善の余地あり
 */


```

※念のためですが、上記の具体例は実際のドキュメントを改変しています。
（ので、細かいところで変な点はあるかと思いますが、それが主旨ではないので、大目に見ていただければと思います。）

まとめ
---

基本的には、詳細に書いたほうがよいので、上記のフォーマットを一例にしつつ、例えば、どんどんタグも増やしていただいて構いませんが、やり過ぎるとだんだんドキュメントを書くのが億劫になっていくのと、メンテも大変だと思うので、最小公倍数的な感じでよいと考えています。
ただ、絶対避けたいのは同一のプロダクト内で、このメソッドはドキュメントが詳細（≒正確）に書かれているけど、こっちのメソッドはドキュメントが粗いないしは間違っていることだと思うので、やり切れる範囲でやり切るのが大事かと思います。
（もちろんやり切れる範囲を広げていく努力は必要）

あとは、その最小公倍数的な感じ（シンプルだけど必要な情報は詰め込まれている）を上手に書けるように日々精進！

最後に
---

これはだめだぜ！こうしたほうがよいぜ！うちはこうしてるぜ！とかありましたらコメントなりいただけると嬉しいです。

参考サイト
---

phpDocumentor：
http://www.phpdoc.org/docs/latest/index.html
（公式のドキュメントです。タグ一覧もここから見れます。）
Brace Expansionで生産性5割増しな楽しいコマンドライン生活

10秒で出来ますが，生活は50％ぐらい豊かになります．

# かんたんな使い方

## 例その①: リネームめんどくさい

たとえばこんなとき

```bash:console
$ rails g controller user  # あっ まちがって s つけわすれちゃった
```

リネームめんどくさいですよね

```bash:console
$ mv app/controllers/user_controller.rb app/controllers/users_controller.rb
```

こんなときにBrace Expansion！

```bash:console
# {,s} を展開してくれるので，先のコマンドと同じ結果になる
$ mv app/controllers/user{,s}_controller.rb
```

これだけでちゃんとリネームできちゃいます．

## 例その②: ディレクトリ作成めんどくさい

AngularJSつかうぞ〜〜〜

```bash:console
$ mkdir app/assets/javascripts/controllers
$ mkdir app/assets/javascripts/directives
$ mkdir app/assets/javascripts/filters
$ mkdir app/assets/javascripts/services
```

…めんどくさい．

こんなときにもBrace Expan(ry

```bash:console
$ mkdir app/assets/javascripts/{controller,directive,filter,service}s
```

これでOK!


## 例その③: 連番ファイル作成めんどくさい

連番ディレクトリ作るぞ〜〜〜

```bash:console
$ mkdir app/assets/images/photos-A
$ mkdir app/assets/images/photos-B
$ mkdir app/assets/images/photos-C
$ mkdir app/assets/images/photos-D
$ mkdir app/assets/images/photos-E
$ mkdir app/assets/images/photos-F
```

やっぱりめんどくさい．

そんなときにも（ｒｙ

```
$ mkdir app/assets/images/photos-{A..F}
```

これだけでいける！

# まとめ

便利ですね．生産性5割増しぐらいですね．
こころぴょんぴょんしますね．

# 参考URL

- [Bash Reference Manual: Brace Expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html)
WindowsでRubyコードをexe化するときのメモ


Textデータを変換するツールをWindows上で動かす必要がでてきたので、
Rubyで簡単に書いて、なおかつexeとして動かしたいと思って調べました。
（rubyの入っていない環境でも動かしたかったので）

ぴったしのサイトが見つかり、簡単にできそうなことがわかりました。

[RubyInstallerのRuby2.0でRubyInlineとOcraを使ってexe化する](http://d.hatena.ne.jp/mirichi/20140323/p1)

しかし、最新版の組み合わせではexe化するときにエラーが発生したため、動いた組み合わせをメモとして残しておきます。

```
=== Adding user-supplied source files
C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/ocra-1.3.3/bin/ocra:1121:in `initialize':
 No such file or directory @ rb_sysopen - C:/Users/ogi/thread.rb (Errno::ENOENT)
```

# 動いたバージョン組み合わせ

- Ruby Installer 2.0.0 p598
  - [Ruby 2.0.0-p598](http://dl.bintray.com/oneclick/rubyinstaller/rubyinstaller-2.0.0-p598.exe?direct) ※試してませんが同じはず
  - [Ruby 2.0.0-p598 (x64)](http://dl.bintray.com/oneclick/rubyinstaller/rubyinstaller-2.0.0-p598-x64.exe?direct)

- DevKit(For use with Ruby 2.0 and 2.1)
  - [For use with Ruby 2.0 and 2.1 (32bits version only)](http://cdn.rubyinstaller.org/archives/devkits/DevKit-mingw64-32-4.7.2-20130224-1151-sfx.exe) ※試してませんが同じはず
  - [For use with Ruby 2.0 and 2.1 (x64 - 64bits only)](http://cdn.rubyinstaller.org/archives/devkits/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe)
- RubyInline 3.12.2
- Ocra 1.3.3

# 動かなかったバージョン組み合わせ

- Ruby Installer Ruby 2.1.5
- DevKit(For use with Ruby 2.0 and 2.1)
- RubyInline 3.12.3
- Ocra 1.3.3

# 手順
- Ruby Installerでrubyをインストール
- DevKitを適当な場所に展開(C:¥DevKitなど）
- スタートメニューから"Ruby コマンドプロンプトを開く"を起動し、DevKitの場所に移動 `cd C:¥DevKit`
- DevKit初期化 `ruby dk.rb init`
- DevKitとRubyを紐付け `ruby dk.rb install`

  Rubyの配置場所のPathにスペースが入っているとダメみたいです。
  詳しくは[Development Kit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit)を参照。

- コードを用意し（foo.rb）、コードの先頭に次の一行を追加

  `ENV['INLINEDIR'] = File.dirname(File.expand_path(__FILE__)) `

```:foo.rb
ENV['INLINEDIR'] = File.dirname(File.expand_path(__FILE__)) 

class Foo
  def bar
    puts 'bar'
  end
end

foo = Foo.new
foo.bar
```

- 普通にrubyで動作確認

  `ruby foo.rb`

  barと表示されます。

- exe化

  `ocra foo.rb`

  foo.exeができます。

- exe実行

  `foo.exe`

  barと表示されます。
SWTableViewCellでセル左端が一部隠れる現象の対応

SWTableViewCellでスワイプ表示部分のセル左端が一部隠れる現象があった場合の対応。

私の環境では初回表示時のみ発生しました。


```lang:SWUtilityButtonView.h
@property (nonatomic, strong) NSLayoutConstraint *widthConstraint;
```

```lang:SWUtilityButtonView.m
@property (nonatomic, strong) NSLayoutConstraint *widthConstraint;
```
.mにあったpropertyを.hに移動。


```lang:SWTableViewCell.m
- (CGFloat)rightUtilityButtonsWidth
{
    return self.rightUtilityButtonsView.widthConstraint.constant + self.additionalRightPadding;
}
```
Cellのクラスにて

return CGRectGetWidth(self.rightUtilityButtonsView.frame) + self.additionalRightPadding;
だった部分を書き換え。
iOS Simulatorが巨大表示になるｗ


1/8/2015追記
14C94bにしたらなおったｗ
ちなみにSubline Text3も同じ症状だった。

<hr>

Xcodeではなくyosemite 10.10.2beta2のバグっぽいですｗ

https://www.youtube.com/watch?v=4gkFEkOJN9s&feature=youtu.be
http://stackoverflow.com/questions/27491464/ios-simulator-drawing-too-big-not-a-window-scale-issue

一瞬腰抜かしたw

![hgdHv.png](https://qiita-image-store.s3.amazonaws.com/0/5222/3638e2e9-b5ca-fb56-752f-a9fe5f9f9715.png "hgdHv.png")
ntpサーバのdnsを切り替えたがntpクライアントは自動的に参照先を切り替えなかった

## NTPに脆弱性

http://www.itmedia.co.jp/enterprise/articles/1412/22/news038.html

だそうなので、この際古いNTPサーバリプレースしちゃおうかみたいになったので、DNSレコード切り替えでいけないかなって検証したら**やっぱりいけなかった**。


## 用意した即席検証環境
- ntpサーバ１: CentOS 6.6
- ntpサーバ２: CentOS 5.5
- ntpクライアント: 6.6


## 検証内容
- time.tekito.orgのAレコードににntpサーバ１のIPを登録 TTLは60sec
- クライアントのntpサーバをサーバ１(time.tekito.org)に向ける
- サーバ１およびサーバ２で`tcpdump`実施
- DNSを切り替えてtime.tekito.orgをサーバ２に向ける
- `tcpdump`の内容を確認


## 結果
サーバ１での`tcpdump`の模様

```shell-session
# tcpdump -n -p udp and src host XXX.XXX.XXX.XXX    # コマンドが雑！
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
12:35:44.491135 IP XXX.XXX.XXX.XXX.ntp > YYY.YYY.YYY.YYY.ntp: NTPv4, Client, length 48
12:36:50.521204 IP XXX.XXX.XXX.XXX.ntp > YYY.YYY.YYY.YYY.ntp: NTPv4, Client, length 48
12:39:01.554517 IP XXX.XXX.XXX.XXX.ntp > YYY.YYY.YYY.YYY.ntp: NTPv4, Client, length 48
12:43:21.571990 IP XXX.XXX.XXX.XXX.ntp > YYY.YYY.YYY.YYY.ntp: NTPv4, Client, length 48
# ここでDNSレコードの切り替えを実施(12:46)
12:52:00.652235 IP XXX.XXX.XXX.XXX.ntp > YYY.YYY.YYY.YYY.ntp: NTPv4, Client, length 48    <- 引き続きリクエストに応答しているよ
```

てな感じでダメだった。なおクライアント側で`ntpd`を再起動したところ直ぐにサーバ２を参照し始めた。

それをふまえてサーバ２での`tcpdump`の模様

```shell-session
# tcpdump -n -p udp and src host XXX.XXX.XXX.XXX 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
# ここでクライアント側のntpdを再起動(12:58)
12:58:24.796520 IP XXX.XXX.XXX.XXX.ntp > ZZZ.ZZZ.ZZZ.ZZZ.ntp: NTPv4, Client, length 48    <- すぐ来た
12:59:30.864001 IP XXX.XXX.XXX.XXX.ntp > ZZZ.ZZZ.ZZZ.ZZZ.ntp: NTPv4, Client, length 48
13:00:36.862077 IP XXX.XXX.XXX.XXX.ntp > ZZZ.ZZZ.ZZZ.ZZZ.ntp: NTPv4, Client, length 48
13:01:41.861133 IP XXX.XXX.XXX.XXX.ntp > ZZZ.ZZZ.ZZZ.ZZZ.ntp: NTPv4, Client, length 48
```


## 結論
ntpサーバのDNSレコードを切り替えたらクライアント側の`ntpd`を再起動しないといけない。未確認だが起動時に読み込んだ設定をずっと持ち続けると思われる。多数のクライアントが存在する場合のntpサーバリプレースでは、DNSを切り替えるのはあまり得策ではなさそう。
Clojure Toolbox: Clojure向けライブラリのワンストップディレクトリサイト


Scalaから移行してClojureを勉強し始めたばかりなので、Clojure界隈にはどんなライブラリがあるのだろうかと探していたら、見つけたサイト。「こういうことがしたいんだけど」と思ったら、まずここをみて当たりをつけるようにしている。

http://www.clojure-toolbox.com/
UserDefault に辞書を保存する


UserDefault にフィールドやスイッチなどの設定情報を保存するとき、個々のデータをフラットに保存するのは簡単ですが、それぞれのデータを識別するキーがユニークでなければなりません。
しかし、シーンが多くあったりしてデータが多くなるとキーが多くなって煩雑になります。
配列で保存する方法も紹介されていますが、配列だと配列毎に順序を管理する必要があります。
そこで、クラス毎にUserDefault に保存するデータの辞書を作成してその辞書を１つのキーでUserDefault に保存してみました。
以下の例は `playGround` で動作確認した例です。

例
// 何も無い状態をチェック
let myDefault = NSUserDefaults.standardUserDefaults()
if let readDict = myDefault.objectForKey("save") as? [String: String] {
    let readData2 = readDict["key2"]!
} else {
    println("No such Data")
}
// No such data!

// データを用意して保存
let saveData = ["key1": "data1", "key2": "data2", "key3": "data3"]
let saveDefault = NSUserDefaults.standardUserDefaults()
saveDefault.setObject(saveData, forKey: "save")
saveDefault.synchronize()

// 再度読み出し
if let readDict = myDefault.objectForKey("save") as? [String: String] {
    let readData2: String! = readDict["key2"]
    let readData3: String! = readDict["key3"]
    let readData4: String! = readDict["key4"]
    println("Data of key2 = \(readData2)")
    println("Data of key3 = \(readData3)")
    println("Data of key4 = \(readData4)")

} else {
    println("No such Data")
}
/*
Data of key2 = data2
Data of key3 = data3
Data of key4 = nil
*/

// 消去
saveDefault.removeObjectForKey("save")
saveDefault.synchronize()

辞書を保存するときに注意することは、辞書のデータを読み出すと、Optional型で読み出されることです。
また、Objective-C では辞書型のデータは型チェックはありませんが、Swift では辞書のデータは同じ型が基本ですので、全てString にしてから辞書にセットするなどの手間があります。
しかし、Defaultにアクセスするキーがデータの数にかかわらず１つでよいのがよい点です。
[JAWS-UG CLI] SNS:#1 トピックの作成

AWS CLIを利用して、SNSのトピックを作成してみます。




前提条件
========


SNSへの権限
-----------

SNSに対してフル権限があること。


AWS CLIのバージョン
-------------------

以下のバージョンで動作確認済

- AWS CLI 1.10.11

```bash:コマンド:
aws --version
```

結果(例):

      aws-cli/1.11.70 Python/2.7.12 Linux/4.4.11-23.53.amzn1.x86_64 botocore/1.5.33

バージョンが古い場合は最新版に更新しましょう。

```bash:コマンド:
sudo -H pip install -U awscli
```


0. 準備
=======

まず変数の確認をします。

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_PROFILE: (0.1) ${AWS_DEFAULT_PROFILE}
        AWS_DEFAULT_REGION:  (0.2) ${AWS_DEFAULT_REGION}

ETX
```

結果(例):

      AWS_DEFAULT_PROFILE: (0.1) <SNSにフル権限のあるプロファイル>
      AWS_DEFAULT_REGION:  (0.2) ap-northeast-1

変数が入っていない、適切でない場合は、それぞれの手順番号について作業を
行います。


0.1. プロファイルの指定
-----------------------

プロファイルの一覧を確認します。

```bash:コマンド:
cat ~/.aws/credentials \
       | grep '\[' \
       | sed 's/\[//g' | sed 's/\]//g'
```

結果(例):

      iamFull-prjz-mbpr13
      <SNSにフル権限のあるプロファイル>

```bash:変数の設定:
export AWS_DEFAULT_PROFILE='<SNSにフル権限のあるプロファイル>'
```


0.2. リージョンの指定
---------------------

```bash:変数の設定:
export AWS_DEFAULT_REGION='ap-northeast-1'
```


最終確認
--------------

```bash:変数の確認:
cat << ETX

        AWS_DEFAULT_PROFILE: (0.1) ${AWS_DEFAULT_PROFILE}
        AWS_DEFAULT_REGION:  (0.2) ${AWS_DEFAULT_REGION}

ETX
```

結果(例):

      AWS_DEFAULT_PROFILE: (0.1) <SNSにフル権限のあるプロファイル>
      AWS_DEFAULT_REGION:  (0.2) ap-northeast-1


1. 事前作業
===========


1.1. トピック名の決定
---------------------

作成するトピックの名前を決めます。

```bash:変数の設定:
SNS_TOPIC_NAME="handson-$(date +%Y%m%d)" \
        && echo ${SNS_TOPIC_NAME}
```

同じ名前のトピックが存在しないことを確認します。

```bash:コマンド:
aws sns list-topics \
        --query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)]"
```

結果(例):

      []


2. トピックの作成
=================

トピックを作成します。

```bash:変数の確認:
cat << ETX

        SNS_TOPIC_NAME: ${SNS_TOPIC_NAME}

ETX
```

```bash:コマンド:
aws sns create-topic \
        --name ${SNS_TOPIC_NAME}
```

結果(例):

      {
        "TopicArn": "arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:handson-20170417"
      }


3. 事後作業
===========


トピックの確認
--------------

作成したトピックがトピック一覧に表示されることを確認します。

```bash:コマンド:
aws sns list-topics \
        --query "Topics[?contains(TopicArn, \`${SNS_TOPIC_NAME}\`)]"
```

結果(例):

      [
          "TopicArn": "arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:handson-20170417"
      ]


完了
====
Drone - サービスコンテナへのポートフォワーディングをどうしているのか読んでみた

drone.io は以下のような設定を入れておくと、テスト実行コンテナとは別途サービス（多くの場合外部のDB）を立ち上げてくれる。

```yaml
service:
  - mysql
```

これがどうなっているかと言うと、まず、登録されたサービスの情報をもとに `proxy.sh` と言うファイルを生成する。

- https://github.com/drone/drone/blob/master/shared/build/build.go#L534-L549

そのあと、実際にテスト用のコンテナをビルドするタイミングでそのファイルを `/etc/drone.d/` 以下に追加し、ログイン時に自動で起動するようにしている。

- https://github.com/drone/drone/blob/master/shared/build/build.go#L463

実際の `proxy.sh` の中身は以下のようになる。

```bash:proxy.sh
#!/bin/bash
[ -x /usr/bin/socat ] && socat TCP-LISTEN:3306,fork TCP:172.17.10.210:3306 &
[ -x /usr/bin/socat ] && socat TCP-LISTEN:11211,fork TCP:172.17.10.211:11211 &
```

このコマンド自体は、

```go:build.go#L541-L543
for port := range container.NetworkSettings.Ports {
    proxyfile.Set(port.Port(), container.NetworkSettings.IPAddress)
}
```

となっているようにコンテナ自体の情報からマッピングを作成するので、`EXPOSE`しておけば公式イメージでも独自イメージでも変わりなく扱える模様。便利じゃん

以上です。