OmniAICreator/Qiita-1.07M huggingface dataset:
Scrapyでログに出力されるItem内のUnicode文字列を読めるようにする

**2016-05-25追記：2016年5月にリリースされたScrapy 1.1はPython 3に対応したので、Python 3を使えばこのページの問題はそもそも発生しません。何もしなくてもItem内の日本語が読めます。ぜひPython 3とScrapy 1.1以降を使いましょう！**

## 問題

Scrapyでは、SpiderからyieldしたItemがログに出力されますが、日本語など非ASCIIの文字列を含むフィールドはUnicodeエスケープされた状態で出力されるので、パット見で読めず、もどかしい思いをします。

## (雑な) 対処法

Itemクラスに以下のような`__unicode__()`メソッドを定義すると読みやすくなります。

```py
class MyItem(scrapy.Item):
    # ...
    def __unicode__(self):
        return repr(self).decode('unicode_escape')
```

## 実行例

以下のSpiderを実行します。これは[12factor.net](http://12factor.net/)というWebサイトで翻訳のある言語の一覧を取得するSpiderです。

```twelve_factor_spider.py
# coding: utf-8

import scrapy


class MyItem(scrapy.Item):
    languages = scrapy.Field()

    def __unicode__(self):
        return repr(self).decode('unicode_escape')


class TwelveFactorSpider(scrapy.Spider):
    name = '12factor'
    start_urls = ['http://12factor.net/']

    def parse(self, response):
        yield MyItem(languages=response.css('#locales a::text, #locales span::text').extract())
```

### Before (`__unicode__`なし)

Unicode文字列がエスケープされています。

```
$ scrapy runspider twelve_factor_spider.py
2016-01-13 17:56:46 [scrapy] INFO: Scrapy 1.0.4 started (bot: scrapybot)
2016-01-13 17:56:46 [scrapy] INFO: Optional features available: ssl, http11
2016-01-13 17:56:46 [scrapy] INFO: Overridden settings: {}
...
2016-01-13 17:56:47 [scrapy] DEBUG: Scraped from <200 http://12factor.net/>
{'languages': [u'Espa\xf1ol (es)',
               u'Fran\xe7ais (fr)',
               u'Deutsch (de)',
               u'\u0420\u0443\u0441\u0441\u043a\u0438\u0439 (ru)',
               u'English (en)',
               u'\u65e5\u672c\u8a9e (ja)',
               u'Italiano (it)',
               u'Brazilian Portuguese (pt_br)',
               u'\u7b80\u4f53\u4e2d\u6587 (zh_cn)',
               u'\ud55c\uad6d\uc5b4 (ko)']}
...
```

### After (`__unicode__`あり)

Unicode文字列がエスケープされておらず、読みやすいです。

```
$ scrapy runspider twelve_factor_spider.py
2016-01-13 17:57:25 [scrapy] INFO: Scrapy 1.0.4 started (bot: scrapybot)
2016-01-13 17:57:25 [scrapy] INFO: Optional features available: ssl, http11
2016-01-13 17:57:25 [scrapy] INFO: Overridden settings: {}
...
2016-01-13 17:57:25 [scrapy] DEBUG: Scraped from <200 http://12factor.net/>
{'languages': [u'Español (es)',
               u'Français (fr)',
               u'Deutsch (de)',
               u'Русский (ru)',
               u'English (en)',
               u'日本語 (ja)',
               u'Italiano (it)',
               u'Brazilian Portuguese (pt_br)',
               u'简体中文 (zh_cn)',
               u'한국어 (ko)']}
...
```

ちなみに、あくまでログへの出力内容を変えるだけで、`-o/--output`でファイルに保存した場合の内容などには影響しません。

## 注意点

`decode('unicode_escape')`を通すと、空白文字 (`\n`, `\r`, `\t`, `\u3000`など) や制御文字のUnicodeエスケープもアンエスケープされてしまいます。このため、空白文字やバイト列が含まれるItemでは逆に中身がわかりづらくなる可能性が大いにあります。使い方には気をつけてください。

ScrapyがPython 3に対応したらこんな面倒なことしなくて良くなるはずです。

おまけ：もう少し真面目に表示可能な文字のみをアンエスケープする関数を書いてみました。 → http://ideone.com/J77aaN

## まとめ

* Itemの`__unicode__()`を定義するとログへの出力内容を変更できる。
* Python 3が便利。
TSVファイルを用意したい時、みんなどうしてるんだろう？僕の場合

テストデータとかでTSVがほしい時って、みんなどうしてるんだろう？テキストエディタで作るのは正直めんどいよね。
Excelで作る人が多いと思うんだけど、あれって癖があるよね。僕はこうしてるって例を書いてみる。

Excelでデータを貼り付けて、テキストエディタに貼り付けるって方式だと、最後のカラムが空データだった場合に省略されてしまう。
例えばExcelでこんな感じのデータがあったとする。
![タブをコピペしてみる例1.PNG](https://qiita-image-store.s3.amazonaws.com/0/55730/f6af2be9-59f7-08f3-2383-e7144de1ff0d.png)

これ、A1からC3までをコピーしてテキストエディタに貼り付けると、C1、C2、C3のためにタブが入る。
でもこれだと・・・
![タブをコピペしてみる例2.PNG](https://qiita-image-store.s3.amazonaws.com/0/55730/fee0bf49-9da9-5bf2-994e-7a8b606fe3f0.png)

なぜかC1、C2が無かったことにされる事がある。
※ どういうわけかちゃんと空文字として認識してくれる事もあるみたいなんだけど、条件が解らないからボツ。

じゃあどうするかってーと、僕はこうしてる。
1.Excelのマクロを有効にする。
2.1つブックを作って、データ用シートと、設定用シートを作っておく。
3.設定用シートに、最大列数を書く。名前も定義しておく。生成用マクロを起動するボタンも置いておく。
4.データ用シートにはヘッダ行を作っておくこと。作っておかないと、後で修正する時に解りづらい。

設定用シートの例
![こうしてるよ1.PNG](https://qiita-image-store.s3.amazonaws.com/0/55730/b42c9f46-60e1-75be-caf7-fe8e2d9941ed.png)
データ用シートの例（元データって書いてあるけど、そこはご愛嬌）
![こうしてるよ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/55730/10011aa4-7c47-68c1-da29-db92933efcf9.png)

あとは、生成用ボタンのイベントに、ソースを書く。

```lang:vba
Sub 生成ボタン_click()
    '最大列数を取得
    Dim maxColumn As Long
    maxColumn = Range("最大列数").Value
    'ファイルを生成
    Dim dir As String
    dir = curDir & "\"
    Dim filePath As String
    Dim fileName As String
    fileName = Format(Now, "yyyymmddhhnnss") & ".tsv"
    filePath = curDir & "\" & fileName
    
    Dim FSO As Object
    Set FSO = CreateObject("Scripting.FileSystemObject") 'ちなみにデフォルトだとSJISで出力するよ。
    Dim textFile As Object
    Set textFile = FSO.OpenTextFile(filePath, 2, True)
    
    '元データの最初の位置へ
    Dim startRng As Range
    Set startRng = Range("元データのヘッダ1列目")
    startRng.Worksheet.Select
    startRng.Activate
    
    'ヘッダを1行目とする。次の行があるならばループする
    Do While (Not ActiveCell.Offset(1, 0).Value = "") '次の行にデータがあるならば、次の行に移る
        ActiveCell.Offset(1, 0).Activate
        Dim i As Integer
        'カラム数だけ読み取る
        For i = 0 To maxColumn - 1
            textFile.Write ActiveCell.Offset(0, i).Value
            '最後の列でなければ、タブ文字を入れる
            If Not i >= maxColumn - 1 Then
                textFile.Write vbTab
            End If
        Next i
        '1行の出力が終わったので、改行する
        textFile.WriteBlankLines 1
    Loop
    
    
    textFile.Close
    
    MsgBox "このExcelのブックと同じ場所に、tsvファイルを作成しました。ファイル名：" & fileName
End Sub
```

これで、生成ボタンを押せば、ブックと同じ場所にTSVファイルが生成される。
データの入力の時「00001」のように、先頭に0がある数字を入れる場合は、「'00001」のようにシングルクオートを入れておくと、0が省略されない。この時のシングルクオートはTSVファイルに出力されない。

こんな感じでTSVファイルを作ってます。
書いた僕がいうのもなんだけど、面倒だよなあ。Excelがもっとちゃんと動いてくれればいいのになあ。
静岡市オルソ化航空写真 Tile Map Service の使い方

静岡市がCC BY 4.0でオープンデータとして公開しているオルソ化航空写真を加工して TMS (Tile Map Service) に基づく地図画像配信を行っています。
Google Maps API や代表的なライブラリを用いて、TMSを利用するための方法を紹介します。

# Tile Map Service (TMS) とは
Tile Map Service (TMS) とは Open Source Geospatial Foundation が開発したタイル化Web地図の[仕様](http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification)です。

# 利用した静岡市提供のデータ
以下の静岡市提供のデータをタイル化して配信しています。

- [土木管理課 H23航空写真オルソ画像データ](http://dataset.city.shizuoka.jp/dataset/dobokukanri20151023-001)
- [固定資産税課 H26航空写真オルソ画像データ](http://dataset.city.shizuoka.jp/dataset/shisanzei20151023-002)

# サービス URL
以下のURLでサービスを提供しています。ズームを示す{z}は12から19の範囲で指定してください。
## 土木管理課オルソ化航空写真(H23)
http://tile.senmon.jpn.com/1.0.0/dobokukanri/{z}/{x}/{y}.png
## 固定資産税課オルソ化航空写真
http://tile.senmon.jpn.com/1.0.0/koteishisanzei/{z}/{x}/{y}.png

# TMSを利用するサンプルコード
TMSは右下(南西)を原点(0, 0)としているのに対して、Google Mapsは左上(北西)、Yahoo! Open Local Platform(YOLP)は左中央(西)を原点にしている違いがあることに注意してください。また、zoom値はTMSとGoogle Mapsは0から、YOLPは1から始まります。
## Google Maps API (v3)
[Google Maps JavaScript API で静岡市土木管理課オルソ化航空写真を表示する (jsdo.it)](http://jsdo.it/kudarisenmon/Q7TK)
## Yahoo! JavaScriptマップAPI
[Yahoo! JavaScriptマップAPI で静岡市固定資産税課オルソ化航空写真を表示する (jsdo.it)](http://jsdo.it/kudarisenmon/IukV)
## Leaflet (0.7.x)
[Leaflet で静岡市土木管理課オルソ化航空写真を表示する (jsdo.it)](http://jsdo.it/kudarisenmon/wH59)
## Open Layers (3.x)
[OpenLayers3 で静岡市固定資産税課オルソ化航空写真を表示する (jsdo.it)](http://jsdo.it/kudarisenmon/aPNp)
# 今後の更新について
固定資産税課オルソ化航空写真は毎年更新されるようです。TMSも最新のものを配信するように更新していきますが、サーバのディスク容量が許す限り過去のものも保管して街並みの遷移を比較できるようにしたいと考えています。

# OpenStreetMapでトレースの背景画像にする
衛星写真と比較して、正確さ・鮮度・精細さの全てで優っていてトレースに向いています。利用方法は [OpenStreetMap Wiki](http://wiki.openstreetmap.org/wiki/Shizuoka_ortho) を参照してください。

# ライセンスについて
タイルのライセンスは以下です。商用利用も制限しませんが、ネットワーク帯域が潤沢ではないため、ヘビーユースは事前に相談いただけると幸いです。
CC BY-SA 4.0 静岡市, 下り専門
cmdで簡単な処理時間計測

cmdと言いつつpowershellを使う。

```bat
>powershell -C Measure-Command {echo 1}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 9193
TotalDays         : 1.06400462962963E-08
TotalHours        : 2.55361111111111E-07
TotalMinutes      : 1.53216666666667E-05
TotalSeconds      : 0.0009193
TotalMilliseconds : 0.9193
```

秒だけ。

```bat
>powershell -C (Measure-Command {test\main_test.bat}).TotalSeconds
8.6298945
```

psスクリプトの場合は`ExecutionPolicy`の指定が必要なことがある。

```bat
>powershell -ExecutionPolicy RemoteSigned -C (Measure-Command {test\test.ps1}).TotalSeconds
```
ExecutionPolicyに関する参考記事
http://qiita.com/alchemist/items/e6706cd425f8f5e5032e
sidekiqに触る機会があったので個人用にまとめてみた


## sidekiqについて

+ resqueのような非同期実行を実現するgem

+ バックエンドにredisが必要

+ resqueとは違いsocket型

## configure

```sidekiq.yml
:verbose: true
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 3 #並列数
:retry: 1
:queues:
  - [hogehoge,1] #queueに重みをつけられる [string 名前,int 重み]
```

## jobの定義

```job.rb
class Hogehoge
  include Sidekiq::Worker #sidekiqのinclude
  sidekiq_options queue: :hogehoge #queueの名前指定

  def perform(date=nil)
    puts "test"
  end
```

## 起動

+ console起動

```exec
bundle exec sidekiq -C config/sidekiq.yml
```

### deamon起動

+ 上記の ``` config/sidekiq.yml ``` に ``` :daemon: true ``` を指定するとdaemon起動する

+ capistrano-sidekiqというgemを使用するとcapistranoでdeploy時にdeamon化することが可能

+ resqueの場合はdaemon-spawnなどといったdeamon化するgemを使用して自前でdeamon化用のscriptを用意する必要がある

#### 以下capistrano例

+ Capistrano + sidekiq

```Gemfile
gem 'capistrano-sidekiq', github: 'seuros/capistrano-sidekiq'
```

```Capfile
require 'capistrano/sidekiq'
```

```production.rb
set :pty, false
```

設定はこれだけのはず

## 本番実行

```
bundle exec sidekiq --environment=production
```

productin環境を指定する場合引数でenvを設定する

## 更新処理

sidekiqは一度起動したタイミングのソースで動作するのでjob taskを変更しても
更新されない
capistranoでdaemon化ができていない場合は手動でsidekiqのreloadをかける必要がある

```
ps aux | grep sidekiq
kill -9 hogehoge
```

またはconfigファイルで設定したpidファイルを``` cat ```あたりで確認しそのpidをkillする

```
cat tmp/pids/sidekiq.pid
```

その後再起動

```
bundle exec sidekiq --environment=production
```

## ダッシュボード

sidekiqには標準でsinatraベースのダッシュボードが付いている
railsの場合```config/route.rb```にルーティングを追加し起動するだけ

+ unicorn や rails server などを起動

```route.rb
require 'sidekiq/web'
require 'sidekiq-scheduler/web'

Rails.application.routes.draw do
  mount Sidekiq::Web => '/sidekiq'
end 
```

http://loalhost:4567/sidekiq などでaccessできる

下記の様なgemを追加するとダッシュボードがカスタマイズされる

```Gemfile
gem 'sidekiq-failures'
gem 'sidekiq-history'
gem 'sidekiq-statistic'
```
WebMatrix(IIS Express)でWindowsのローカルファイルをiPhoneのブラウザで見たい

##苦労したからメモ。
 
やりたかったことは、
**iPhone実機でローカルに保存しているhtmlを見たい。どうしても。**
・・・それだけ。

軽く考えてたけど、案外ワタシ使えません...orz。
いつもはサーバーに上げてみたり、Chromeの開発者モードで済ませたりしてたんだけど
どうしてもどうしても実機で確認したかったのですよ。
しかも【Windows】で。
さらに【XAMPPは面倒だったので手早くそれ以外】で。

手早かったかは、すでに疑問符がつくけど。笑

そんなわけで、TomcatやらXAMPPやらではなく、あえてのWebMatrixでやりましたので
自分的で申し訳ないですメモ。

##ザッと手順。
1. まずは同じネットワークに繋ぎましょ。
2. WebMatrixでサイト設定しましょ。
 
    > サイト → 設定から　http://[自PCのIP:自動で割り振られたポート番号]
3. 管理者権限でコマンドプロンプト立ち上げて、ipでlocalpc以外からのアクセスを許可しましょ。
 
    > netsh http add urlacl url=http://192.168.1.11:8080/ user=everyone(←自PCのIP:Port)
4. Winのファイアウォールを確認。限定または無効に設定しましょ。
5. コンパネからネットワーク接続にて、ローカルエリア接続を無効化しときましょ。

##まとめ
もうMacとかWin8.1とか7とかLinuxだとか、ひとつ覚えるとひとつ忘れます。。。orz
Cloudn VPC OpenNW を使った備忘録

間違ってたらごめんね(´･ω･`)

#基本UI
操作を間違えやすい
popupダイアログが固定なところが多くて見にくい

#各種制限について
VPC・インスタンス・グローバルIPの制限は公表通り
問題はAWSのように申請したら上限突破させてくれるわけではない
アカウントID毎に紐付いているので
サブアカウントを使ってなんちゃって上限を増やす必要がある
VPCはすぐ制限（上限５）に引っかかるので注意
**システム毎にサブアカウントを切ったほうが請求が見やすいのでオススメ**

```
契約アカウント【5VPC：MAX100】【20GIP：1VPCにつき1IP使用】
　　　｜ーサブアカウント【5VPC】【20GIP：1VPCにつき1IP使用】
　　　｜ーサブアカウント【5VPC】【20GIP：1VPCにつき1IP使用】
　　　｜ーサブアカウント【5VPC】【20GIP：1VPCにつき1IP使用】
　　　｜ーサブアカウント【5VPC】【20GIP：1VPCにつき1IP使用】
※但し、契約アカウント上での一元管理はできない
```

#Compute
Linux系OSのrootドライブは必ず15GB
VM管理系は遅い・重い
KVM仮想基盤
よく詰まっているが削除処理だけは速い
スナップショット周りはVM自体を停止する必要がある
OSからshutdownは不可能


## ISO持ち込み
linuxインスタンスはroot15GBしか選択肢がない
100GBのインスタンスを作りたいときは 起動後に diskアタッチでLVMで足す

ISO持ち込みをした場合は最初から100GBインスタンスが作成できるが
NMとかDHCPとか仮想ルータとの相性が悪いのかネットワーク設定が正常に行われなかった
10回ほどやり直したらできた　のでオススメしない
**そもそもサポート対象外**

#Compute Security
FLAT・VPC OpenNW で使用可能
ホスト単位で初期費用月額が発生/仮想パッチ・ウイルス対策の設定がそれぞれ必要
**グローバルIPが必須**
**使用可能なOSのバージョンが固定されてるので注意が必要**
　　リビジョンが0.0.1でも違うと対象外と言われる

```
yum update --exclude=kernel*
```

Linuxではウイルスのリアルタイム検索が不可能

#VPC
１アカウントに５つまで作成可能（最大20）
　　５つ以降はサブアカウントを作成することで回避（一元管理は不可）
　　VPC単位で子アカウント切っておくと足りなくなることを回避しやすい
VPC１つ作成するとグローバルIPがVPC自体に一つ付与される(仮想ルータ(GW))
VPC１つで付与可能なグローバルIPは20個（VPCのGIP含む）
　　20以降はサブアカウントを作成することで回避（一元管理は不可）
ゾーン(AZ)をまたいだVPCは作成できない(VPCが2つ必要)
VPC間通信はグローバルIP経由（一応NTTcomネットワーク内）
computeインスタンス上でのdbのMulti-AZは上記での通信になる
以下AWSとの比較
![アベイラビリティゾーン.png](https://qiita-image-store.s3.amazonaws.com/0/35464/3cb3ae78-6bb3-2b73-447e-f4338ac4af60.png)


## ACL
AWSのSecurityGroupとは違う（デフォルトALLdenyのホワイトリスト形式ではない）
ルータ・SW・FWのように最後にdenyが必要な模様

#RDB
FLATのみで提供（VPCなし）
そのためグローバルIPが必ずついてくる

#LBA
1LBにつき同時接続数は200まで
スケールは自動でするが時間がかかるので、LBを事前に複製して運用しておいて欲しいと公式見解（複製で課金）
DNSサービスも使って無いと恩恵が受けられ無い？(AutoScalling)
Diffie-Hellman parametersは1024bitに固定(2016.02)（公式回答）
　なので[SSLテスト](https://globalsign.ssllabs.com/)でkey exchange項の上限はBになる

※AWS ELBではデフォルトで2048bitの模様
 [AWS Developer Forums: Announcing ELB security update to disable Diffie-Hellman key agreement](https://forums.aws.amazon.com/ann.jspa?annID=3061)
 また1024bitへの変更も可能

#CDN
HTTPSはサポートしていない

#Monitoring
謎の数字を取っている
ほとんど役に立たない

#Adanced Support
ノーマルサポートでは
平日の9−17時にしか処理してくれないが
お金を払うと24時間処理をしてくれる（すぐ返事をくれるわけではない）
Vimで検索した時の選択ハイライトを消す

#Vimで検索した時のハイライトを消す
カラーがイマイチで見づらい時とか僕は毎回変な文字列で検索してました（笑

## 直近の検索のハイライトを解除する(No Hignlight?)
`:noh`
※次の検索からはハイライトされます。

## 検索時にハイライトをしない設定にする
一切ハイライトしません。
`:set nohlsearch`
or

```vim:~/.vimrc
set nohlsearch
```

## ハイライトするかどうかを切り替える
F3キーを押した時にハイライトを切り替える設定。

```vim:~/.vimrc
set hlsearch!
nnoremap <F3> :set hlsearch!<CR>
```

## 直近のハイライトを解除するコマンドをキーにマップする
僕は以下の理由から、F3に`:noh`をマップして、直近のハイライトを解除するのがしっくり来ています。

1. :noh<Enter>打つのがめんどくさい。
2. ハイライトは便利だから毎回使いたい。
3. キー設定での切り替えだと、検索使いたい時に切り替えないといけない。

```vim:~/.vimrc
nnoremap <F3> :noh<CR>
```

うーん。これこれ！

## 参考
* [Vim clear last search highlighting](http://stackoverflow.com/questions/657447/vim-clear-last-search-highlighting)
* [vimのハイライトを消したりデフォルトで消したり、やっぱり表示したり](http://altarf.net/computer/server_tips/2483)
* [What is the &lt;leader&gt; in a .vimrc file?](http://stackoverflow.com/questions/1764263/what-is-the-leader-in-a-vimrc-file)
MSYS2環境でtmuxとクリップボードの共有

`/dev/clipboard` を使って `.tmux.conf` にこんな感じで書けば良い。容赦なくデフォルトのバインディングを潰してるので、それが嫌な人は別のキーに当てればO.K.。

```
bind -n -t emacs-copy C-w copy-pipe "cat > /dev/clipboard"
bind ] run "cat /dev/clipboard | tmux load-buffer - && tmux paste-buffer"
```

## 【2017-11-11追記】 tmux 2.4 以降での設定

https://qiita.com/KanchiShimono/items/d3904c0dc4acf40b6705 ということなので、変更が必要。以下で動いた気がする。

```
bind -n -T copy-mode C-w send-keys -X copy-pipe-and-cancel "cat > /dev/clipboard"
bind ] run "cat /dev/clipboard | tmux load-buffer - && tmux paste-buffer"
```
kintone タブ表示プラグイン（KTAB）

#[kintone アプリでタブ表示](https://rex0220.stores.jp/items/56e6a74fef337717fd001072)
kintone アプリで項目が多くなるとタブ表示させたい時があります。
簡単に、タブ表示が出来るプラグインを作成しましたので、ご紹介します。

[タブ表示プラグイン Ver.4](http://qiita.com/rex0220/items/893de4edaa45e7b2e295) に、バージョンアップしました。


![KTAB0.png](https://qiita-image-store.s3.amazonaws.com/0/100572/d8aafa8b-7277-bb3a-d165-c5124229759f.png)

#KATB プラグインの読み込み
Kintone システム管理 > プラグイン より、KTABプラグインファイルを読込みます。
（KTABプラグインV2 ファイル名 : ktab-plugin2.zip）
![KTAB0a.png](https://qiita-image-store.s3.amazonaws.com/0/100572/073d37c1-4b7c-e8c7-f3b7-91e70817d75f.png)

#KTAB プラグインの設定
![KTAB1.png](https://qiita-image-store.s3.amazonaws.com/0/100572/08306417-aea4-a007-aee5-9457326e716a.png)


タブ表示エリアの表示幅、ヘッダ部固定表示行数、各タブと表示行数を設定し、保存します。
※グループ・サブテーブル・関連テーブルは、１行で計算します。
![KTAB2.png](https://qiita-image-store.s3.amazonaws.com/0/100572/60c8003d-203a-4f45-d3fe-e35e68f63428.png)


- 表示幅は、サブテーブルや関連テーブルなどの表示がタブエリア外に、はみ出す場合に指定。
- 表示行数が０の場合、そのタブは非表示。
- 指定した行数を超えるものは、フッター部に固定表示。

#タブ表示
###詳細画面
![KTAB3.png](https://qiita-image-store.s3.amazonaws.com/0/100572/52484dbf-8b36-d3f8-158d-4c86ef0e8dbd.png)
###編集画面
![KTAB3a.png](https://qiita-image-store.s3.amazonaws.com/0/100572/84dd9c84-2040-807f-a1ea-0ed5229b56fc.png)

###タブ表示の画面遷移
![KTAB4.png](https://qiita-image-store.s3.amazonaws.com/0/100572/1d2b0927-11f9-8737-c100-a6c0fbd0551d.png)

##編集画面タブ表示例　新デザイン
###詳細画面
![KTAB5.png](https://qiita-image-store.s3.amazonaws.com/0/100572/094a597a-67bb-825b-4066-d85eef139699.png)
###編集画面
![KTAB6.png](https://qiita-image-store.s3.amazonaws.com/0/100572/9acecfe3-e136-1cfc-0476-8370d59187a9.png)
Fluxを一言で表現すると

**Fluxとは、交通整理のおまわりさんである。**

Fluxに関してちょっと勉強した結果、
「混雑した交差点の真ん中にはおまわりさん（Dispatcher）を置くと、流れがよくなるよ」ってことだと思った（ちなみに信号のない交差点）。

>だいたい合ってる……といいな
AWSでバルスウォッチ。 -別題：twitter投稿監視の参考に-

# バルスバルスバルス！！！

好きなおばさんはドーラおばさんです。
本投稿は例にしたがって、私の雇用者の意見、立場を必ずしも反映したものではありません。

来る2016/01/15に、[金曜ロードショーにて天空の城ラピュタが放送されます！](https://kinro.jointv.jp/)。
シータ、パズーが手を取り合い呪文を唱えるタイミングにあわせて、Twitterでバルスとつぶやく国民的行事が再びやってくるのです！

本記事ではCloud Watch Logs + Kibanaを利用して、バルスの盛り上がり具合をグラフ化します。
この技術は、twitterでの投稿監視にも使えるでしょう。

# サマリ
1.  CloudWatch Logsにログの入れる場所を作ります。
1. EC2上にNode.jsを利用したTwitter Streaming APIsで「バルス」が含まれる投稿を収集しCloudWatch Logsに流します。
2. CloudWatch Logsでは、「バルス」の流量にしきい値を設定し、ソレを超えたらメールが来るようにしておきます。また、「バルス」はKibanaでも見れるようにしておきます。

簡単。

それでは設定手順です。

# 1. CloudWatch Logsにログの場所を作成
[こちら](http://qiita.com/ukiuni@github/items/8f0c45037e3a28238290)の記事を参考に、
コンソールからCloudWatchを選択してください。
ログ→アクション→ロググループの作成で、BALSを作成。
引き続き、ストリームでtwitterを作成します。

# 2. EC2にNode.jsを利用したアプリを作成
EC2を作るところは省略。
nodeを入れます。

```
wget https://nodejs.org/dist/v4.2.4/node-v4.2.4-linux-x64.tar.gz
tar -zxvf node-v4.2.4-linux-x64.tar.gz
sudo mv node-v4.2.4-linux-x64 /usr/local/
echo "export PATH=/usr/local/node-v4.2.4-linux-x64/bin:\$PATH" >> ~/.bash_profile
source ~/.bash_profile
```
twitterで、アプリないし鍵を生成しておきます。https://apps.twitter.com/app から可能です。

そして、アプリを作成します。

```js:index.js
var fs = require("fs");
var Twitter = require("tweet-pipe");
var twitter = new Twitter({
  consumer_key: 'かぎ',
  consumer_secret: 'かぎ',
  token: 'かぎ',
  token_secret: 'かぎ'
});
var writeStream = fs.createWriteStream('/home/ec2-user/log/bals')
twitter.stream('statuses/filter', {track: 'バルス'}).pipe(twitter.stringify()).pipe(writeStream);
```

依存ライブラリはtweet-pipeです。npm install してください。
アプリ自体がやってることは簡単。主要な処理はたった一行です。

```js:
twitter.stream('statuses/filter', {track: 'バルス'}).pipe(twitter.stringify()).pipe(writeStream);
```
twitterからstream受け取って、文字列化して、ファイルに書きます。
あとは[こちら](http://qiita.com/ukiuni@github/items/8f0c45037e3a28238290)の記事の設定手順に応じてCloudWatch Logsにファイルが取り込まれるようにします。
必要であれば、記事の手順でしきい値を設け、バルスが弾けたことを知るようにします。

# 3. Kibanaの設定。
[こちらの記事](http://qiita.com/kazuqqfp/items/119144074ab684f6049b#elasticsearchservice%E3%81%AE%E6%A6%82%E8%A6%81)を参考に、CloudWatch LogsのデータをElasticsearchServiceに送り込みます。
KibanaはV4がうまく動かなかったのでV3にしました。
<img width="399" alt="スクリーンショット 2016-01-13 15.39.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/4b7553fe-453e-dad4-a618-e632f2dd0101.png">
グラフの作り方は[こちら](http://qiita.com/LOUIS_rui/items/08789644c991713d943d)の記事がとてもよいです。
もうすでに、一分間に1−2回つぶやかれていますね。本番が楽しみです。

さて、これでバルス監視の出来上がりです！
twitterストリーミングAPIはすべてのつぶやきが取れるわけではありませんが、バルスが弾けたことはわかるでしょう。どれくらいの時間からバルスが彈けていくか、見ものです！
この仕組を使えば、自社の製品が話題（炎上？）した時に、いち早く気づくことが出来ます。また、ログを獲っておけば、どのように炎上していったかをグラフにして検証することも可能です。

# 何はともあれ、今週末はバルスです！
バルスバルス！
結果のグラフはこの投稿を更新してお伝えします！
バルス！

# 更新(2016/01/18)!!!!!(バルス失敗？)
結果が出ました。が、、、、、
最大20bpm(バルスパーミニッツ)でした。。。。
richmikan@githubさんにご指摘いただいたとおり、うまくフィルタできなかったか、Streaming APIが相当間引かれてるか、デスネ。
<img width="419" alt="スクリーンショット 2016-01-18 13.52.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/25176/dffdf184-c8ee-9797-2e71-69d84becdecb.png">
コレは良い学習です。「Twitter Streaming Apiで監視するときは、15ツイート毎分いったら、バルスレベルで~~炎上~~話題になっている。」ということです。ご留意ください。
openFrameworksのソースコードを1ファイルにする


# やりたいこと

簡単なコードを書くのにmain.cpp, ofApp.cpp, ofApp.hファイル分けて行ったり来たりするのがめんどくさいので、アプリケーションの記述をmain.cppに集中させたい。

# main.cpp

main.cppに全部書く。

```cpp
// main.cpp
#include "ofMain.h"

class ofApp : public ofBaseApp{
    
public:
    void setup(){
        ofBackground(0);
    }
    void update(){
       x += direction;
       if( x > ofGetWidth() || x < 0.0 ){
          direction *= -1; // bounce
        }
    }
    void draw(){
        ofDrawCircle(x, ofGetHeight()/2, 100);
   }
     // Define members here.
    float x = 0.0, direction = 8.0;
};

//========================================================================
int main( ){
    ofSetupOpenGL(1024,768,OF_WINDOW);			// <-------- setup the GL context
    
    // this kicks off the running of my app
    // can be OF_WINDOW or OF_FULLSCREEN
    // pass in width and height too:
    ofRunApp(new ofApp());
    
}

```

# ofApp.hとofApp.cpp

必要ないのでファイルごと削除する。
Python 基礎文法（雑）めも(2)


2.7ベース。
(1) は[こちら](http://qiita.com/kazoo/items/762c98bb3d1491105bb1)。

## 条件文・制御構造

### 真偽
Python ではすべてのオブジェクトに対し、bool値として扱われたときに True になるか False になるかが決められている。

| オブジェクト | 真偽 | 
|:-----------:|:------------:|
| False、None、0(整数、浮動少数、虚数)、空文字列、空リスト、空タプル、空ディクショナリ       | False |
| それ以外 | True|

```python
>>> a = 0
>>> print a == 0
True
>>> print a == True
False
>>> print a == False
True

>>> a = 1
>>> print a == True
True
>>> print a == False
False
```

### if
条件式の末尾にはコロンを付ける。

```python
>>> a = 0
>>> if a:
    print 'TRUE'
else:
    print 'FALSE'
    
FALSE

# not による反転
>>> if not a:
    print 'TRUE'
else:
    print 'FALSE'
    
TRUE

# isinstance で型の判定
>>> if isinstance(a, int):
    print 'Integer'
    
Integer

# 比較演算子は標準的なもの
>>> if a <= 3
    print 'Less than 3'
    
Less than 3

# リストやタプルの要素に含まれるかどうかを in または not in で
>>> list = [0,1,2,3,4]
>>> if 3 in list
    print 'found'
    
found

# elif で条件追加
a = raw_input('input number >')
a = int(a)
if a < 5:
    print 'less than 5'
elif a < 10:
    print 'less than 10'
else:
    print 'greater than or equal to 10'

```

### 論理演算子

- x and y
- x or y
- not x

```python
>>> a = 5
>>> if a > 3 and a < 5:
   print 'True'
else
   print 'False'
   
False
```

### while

```python
>>> while a < 3:
...     print('sushi')
...     a += 1
...
sushi
sushi
sushi
```

### for..in.. 
リストやタプルに対して Iterator として使う。

```python
>>> sushi = ['maguro', 'hamachi', 'engawa']
>>> for s in sushi:
...     print s
...
maguro
hamachi
engawa
```

### range
組み込み関数 range()は、等差数列を要素とするリストを生成する。

```python
>>> for i in range(3):
...     print 'hoge'
...
hoge
hoge
hoge
```

- range(x)  
  0〜xまでのリストを作成
- range(x, y)  
  x〜yまでのリストを作成
- range(x, y, z)  
  x〜y-1までの範囲でzごとのリストを作成
  
### 例外処理
```
try:
    例外が発生する可能性のある処理
except 例外名:
    エラー処理
else:
    例外が発生しなかったときの処理
finally:
    必ず通る処理
```

```python
a = ['a', 'b', 'c']
number = int(raw_input('input a number > '))

try:
    b = a[number]
except IndexError:
    print 'index error!(' + str(number) + ')'
else:
    print b
finally:
    print 'end of program'
    
```

### サンプル：計算問題チャレンジ

```python
# モジュールをインポート
import time
import random

num_of_times = 5
game_time = 25
num_of_range = 100
start_time = time.time() # 現在時刻

for i in range(num_of_times):
	# 2ケタのランダム足し算を作成
    a = random.randint(1, num_of_range)
    b = random.randint(1, num_of_range)
    c = a + b
    ans = input(str(a) + '+' + str(b) + '= ' ) # キーボードからの入力を ans に代入

    if ans != c:
        print 'wrong answer'
        print 'answer is ' + str(c)
        break

    elif time.time() - start_time > game_time:
        print 'timeout'
        break

    else:
        print 'Bingo!'

else:
    # forループを抜けたとき（全問正解）のみここを通る
    print 'Complete!'
    
print 'end of program'

```
tmux チートシート


## セッション関連
### 起動
> $ tmux

### セッションリスト
> $ tmux list-sessions

### セッションに接続されているクライアントを確認
> $ tmux list-client

### 現在のセッションのデタッチ
`Ctrl-b` + `d`

### セッションへのアタッチ
> $ tmux attach (-t [target-session])

### 現在のセッションの削除
> $ tmux kill-session


## ウィンドウ操作
### 新規ウィンドウ作成
`Ctrl-b` + `c`

### ウィンドウ切り替え
`Ctrl-b` + `[ウィンドウ番号]`
`Ctrl-b` + `n` : 次のウィンドウへ
`Ctrl-b` + `p` : 前のウィンドウへ

### ウィンドウ一覧の表示
`Ctrl-b` + `w`
カーソルで選択して切り替え可能

### ウィンドウの削除
`Ctrl-b` + `&`
確認メッセージあり

## ペイン操作
### 水平分割
`Ctrl-b` + `"`

### 垂直分割
`Ctrl-b` + `%`


### ペイン間の移動
`Ctrl-b` + `o`

または

`Ctrl-b` + `q` でペインのインジケータを表示させて、`Ctrl-b` + `q` + `[インジケータ番号]` でも移動できる。

### ペイン分割解除
`Ctrl-b` + `x`
確認メッセージあり
php.iniの場所を忘れてしまった時に

php.iniの設定を変更したいがファイルの位置が分からん。
人間は忘れる生き物なので、そんな時が多々あります。
Google先生に訊くのもいいですが、今回はコマンドを打って位置を確認しましょう。

前提としてPHPが動いていることが必須です。

```
 php -i | grep php.ini
```

このコマンドを打つだけで以下の様にphp.iniの位置が表示されます。

```
Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini
```

やっている事はphp -iでphpinfo() の実行結果をコマンドライン形式で表示して、その内容に関してphp.iniの検索を行っています。
CircleCIがGithubに登録するデプロイキーを利用してコンテナ内のみで復号できる暗号を生成


例えばCircleCIの環境変数に何かの認証情報を入れたいという時。プライベートとわかっちゃいるが、文字列を直接貼ることにどうしても気持ち悪さを覚える際の選択肢。
屋上屋を架す。

## CircleCIのデプロイキー

GithubのリポジトリをCircleCIと関連付けると、public/private問わず、cloneするためのデプロイキーが登録されます。

こんな感じですね。

![Deploy_keys.jpg](https://qiita-image-store.s3.amazonaws.com/0/7454/6557716c-bb56-49ca-c509-764dc0858e56.jpeg "Deploy_keys.jpg")

この公開鍵に対する秘密鍵は、CirlcleCIでコンテナが起動するときにセットされています。

具体的にはココ。 `~/.ssh/id_circleci_github`。フィンガープリントで比較してみます。あってますね。

```
$ ssh-keygen -yf ~/.ssh/id_circleci_github > pub ; ssh-keygen -lf pub
1024 fc:85:2a:xxx:9f:c4:b9 pub (RSA)
```

この秘密鍵の属性をちょっと考える。

- CircleCIだけが保持
    - ※プロジェクトメンバーは取り出し可っちゃあ可
- プロジェクト単位で一意
    - すべてのビルドで、に同じパス・同じ文字列で必ず存在
- 文字列としての強度はそこそこ

なら、この鍵に関連付けて何かしら文字列を暗号化すれば、コンテナ内部でだけ複合可能な暗号を作れるはず。


## 暗号・復号してみる。

秘密鍵を共通文字列としてシンプルに扱い、共通鍵暗号の方式を使ってみる。コンテナログイン時にあった`openssl.patch`を暗号にしてみよう。

```
$ openssl enc -e -aes256 -in openssl.patch -kfile ~/.ssh/id_circleci_github | base64 -w0
U2FsdGVkX1+IV5qpDaATVIjHcEg16XXMprhCSln5s9uJjWz4GudmS3xxxxxx
```

できた文字列を環境変数に。

![Project_settings_-_giraffi_circleci-sandbox_-_CircleCI.jpg](https://qiita-image-store.s3.amazonaws.com/0/7454/ec6c981f-dc18-b85d-4a02-2c531ed73616.jpeg "Project_settings_-_giraffi_circleci-sandbox_-_CircleCI.jpg")

環境変数が有効になったコンテナを新たに起動して、復号してみよう。
base64をデコードしてから、opensslコマンドへ。

```
$ echo -n $OPENSSLPATCH | base64 -d | openssl enc -d -aes256 -kfile ~/.ssh/id_circleci_github
--- ruby-1.9.2-p180/ext/openssl/ossl_ssl.c	2010-12-23 22:24:00.000000000 -0500
+++ ruby-1.9.2-p180/ext/openssl/ossl_ssl_fixed.c	2011-10-28 11:39:30.265970001 -0400
@@ -107,9 +107,9 @@
     OSSL_SSL_METHOD_ENTRY(TLSv1),
     OSSL_SSL_METHOD_ENTRY(TLSv1_server),
     OSSL_SSL_METHOD_ENTRY(TLSv1_client),
```

CircleCIの環境変数ではそこそこの文字列長が許されているので、少々ならばコンフィグ一式をtarにしてから暗号にした文字列、とかでも登録可能だった。

もっとこだわる(というか秘密鍵らしく使う)なら`S/MIME`? より手っ取り早くやるなら秘密鍵の文字列でパスワードをつけたZIPをつかう、なんて手もありますね。


## まとめや他の選択肢など

この手法、下記条件で解読可能になることを割り切るならつかえなくもない。

- CircleCIがガッツリクラックされて
    - デプロイキーがバレる (A)
    - プロジェクトの環境変数が抜かれる (B)
    - その環境変数がデプロイキーで複合できる暗号だと見抜かれる

A,Bが揃わないと、内容を確認することは無理にはなる。Bに至っては環境変数に入れるまでもなく、リポジトリに含まれていたり適当に散布したって大丈夫だろう。
まあ『デプロイキーがバレる』の時点でプライベートリポジトリがクローンできてしまうので、その場合は暗号うんぬん以前の問題ではあるね。

CircleCIは元々AWSのクレデンシャルが利用できるので、例えばAWS Key Management Serviceなどが使えるならそっちを使う方がむしろ汎用的だと思います。
【Laravel5.1】 updateExistingPivotの使い方

Laravelのドキュメントには

     User::find(1)->roles()->updateExistingPivot($roleId, $attributes);

としか書いておらず、$roleIdとはなんぞやと調べたのでメモ。
結論からいうと、中間テーブルのIDだった。
イメージでいうと、

                foreach ($user->roles as $role) {
                    $pivot_id = $role->pivot->id;
                    $user->roles()->updateExistingPivot($pivot_id, ['role_id' => 5]);
                }

のような感じ。
中間テーブルのFKを更新するのには向かない気がする。
JAVA import static宣言


**import static**を使うことで、CURRENTという省略した指定が可能になる

▪️Test92.java

```java
import B.Test92accountType;
import static B.Test92accountType.CURRENT;
import static B.Test92accountType.TERM;

public class Test92 {
	private String accountNo;
	private Test92accountType accountType;
	private int balance;

	public Test92(String accountNo, Test92accountType accountType) {

	}

	public static void main(String[] args) {
		Test92 customer = new Test92("12345", Test92accountType.ORDINALLYSAVINGS);
		Test92 customer2 = new Test92("21456", CURRENT);
		Test92 customer3 = new Test92("33332", TERM);
		Test92 customer4 = new Test92("77772", Test92accountType.TERM);
	}
}
```

▪️Test92accountType.java

```java
package B;

public enum Test92accountType {
	// 指定した種類の値だけ入れることができる列挙型を定義
	ORDINALLYSAVINGS, CURRENT, TERM;
}
```

▪️Test92.java 実行結果
javadocコメントの比率の目安

# きっかけ

javadocをがっつり書くと、コメント行の比率が高くなってしまうので、目安を知るために、良くつかっているライブラリではどうなのかを、SonarQube 3.7.4で調べてみた。（手元にあるのが昔つくったやつなのでsonarのバージョンが古いです。）

数字を書き出すがめんどいので、画面スクショをはっていく。

# Guava

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/1a5ae4bd-c65f-797e-8418-9a855b19824b.png)

# Joda-Time

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/9b6093a8-cd20-7382-8a18-4a614e8510b0.png)

# Commons-Collections

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/71431df9-7608-ff63-6e41-cc5d5ccba15d.png)

# Commons-Email

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/d3dfd0fb-69e0-f483-bdc6-cd440e54d294.png)

# Super CSV

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/fcf0dff5-657b-3cc8-b7bc-63a7f62ef50c.png)

# jackson-core

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/bf0f12ca-4011-f2dd-4ca5-a54a9ebf151d.png)


# ORM

使ったこともないのも含めて、ORマッパーも追加で調べてみた。

## Ebean

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/5614f725-1b28-e813-952e-ecbdd254c4dc.png)

## MyBatis

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/4f996d10-d431-2521-f23f-31915d65e17a.png)

## Iciql

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/798fafd1-c8fa-aff9-7297-ad2c0c5261b1.png)

## Doma

![image](https://qiita-image-store.s3.amazonaws.com/0/9880/ec0c4c0c-f665-b3b6-eccd-460dcc8a8b16.png)


# 所感

公開APIへのjavadocコメントをつけている比率は、軒並み高いですね。
規模が小さいと100%ですし、guavaみたいにでかいやつでも90%を越えていたり。

コメント率も~~どれも20%は余裕で越えていた~~。ORMの調べてみたら、意外と低いのもあった。
javadocコメントの規約やプロジェクトの方針によるのだろうが、コメント率は結構幅がある。

# 結論?

設計書など、他のドキュメントがあるなら20%あたりでも良さそう。
ソースコードとjavadocだけでやっていくなら、30~40%までいっても問題なさそう。

公開APIにjavadocコメントを全てつけるかどうかはケースバイケースだろうか。
MySQLのストアドプロシージャ内でROW_COUNT()関数を使う際、空行（改行）に気を付ける

Workbench上でストアドプロシージャを作成の際に、ハマったので備忘録として残します。
当然のことなのかも知れませんが・・・ROW_COUNT()関数を実行している上の行が空行の場合、
正常にカウントを取得できませんでした。。
そのため、ストアドプロシージャ内でROW_COUNT()関数を利用する際は、以下のように空の行を含めずにする必要があります。（知りませんでしたので残しておきます）

例）insert結果を返すプロシージャ（insert成功なら1が返る）
※Delimiter変更は割愛

```lang:成功例
CREATE DEFINER=`test_user`@`%` PROCEDURE `sp_test`(
IN str_id char(3), 
IN str_name varchar(45),
OUT rowcount int
)
BEGIN
   DECLARE EXIT HANDLER FOR SQLEXCEPTION SET rowcount = -1;
   INSERT INTO `test_table`
   (`TestID`,`TestName`,`RegDate`)
   VALUES
   (str_id,str_name,NOW());
   SELECT ROW_COUNT() INTO rowcount;
END
```

上記、
**SELECT ROW_COUNT() INTO rowcount;**
の上に、「改行された空の行」が存在すると、rowcount=0で正常に取得ができませんでした。

※以下のような状態はNG（insert成功でも0が返ってしまう）

```lang:失敗例
   DECLARE EXIT HANDLER FOR SQLEXCEPTION SET rowcount = -1;
   INSERT INTO `test_table`
   (`TestID`,`TestName`,`RegDate`)
   VALUES
   (str_id,str_name,NOW());

   SELECT ROW_COUNT() INTO rowcount;
```
空の行分がROW_COUNT()の最後に実行した内容として取得されてしまったからでしょうか・・・？
空の行を無くすと正常にrow_count=1が返ります。

あまり詳しく調べていないためなんとも言えませんが、ストアドプロシージャを作成の際は、
不要な改行に気を付けた方がよさそうです。

※環境 MySQL5.6 Workbench6.3
Androidで画像をはみ出して表示する

ImageViewをスケール2倍くらいに画面からはみ出して拡大表示したかったのでメモ.

# 普通に表示する

![normal.png](https://qiita-image-store.s3.amazonaws.com/0/15000/297bf74e-1c9e-a4e1-b9fb-91a4548120c5.png)


```xml:activity_maincontent.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/red_round" />

</FrameLayout>
```

この空白の部分を埋めていきたい.

# centerCrop

![centerCrop.png](https://qiita-image-store.s3.amazonaws.com/0/15000/f9cca63d-f35f-3315-54b0-5e74e957d001.png)


```xml:activity_maincontent.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/red_round" />

</FrameLayout>
```

centerCropでも足りない.

# PercentFrameLayout

![percent_frame_layout.png](https://qiita-image-store.s3.amazonaws.com/0/15000/ee2e8111-3f82-f8f0-7c41-c6e64bf6ee78.png)

```xml:activity_maincontent.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:scaleType="centerCrop"
        android:src="@drawable/red_round"
        app:layout_heightPercent="200%"
        app:layout_widthPercent="200%" />

</android.support.percent.PercentFrameLayout>
```

これで上手くいった。
Support Percent Library便利！
ディレクトリ内の指定した語，拡張子を含むファイル名を検索する

指定したディレクトリ内にあるファイルで，指定した単語と拡張子を含むものを検索する．
関数呼び出しの際に，拡張子の部分にドット(.)を含むのを忘れないように．

```py
def check_file(path='./',file_name='',ext=''):
    import os
    import os.path

    _ch = os.listdir(path)
    ch_e = []

    for _ in _ch:
        _root, _ext = os.path.splitext(_)
        if file_name in _root and _ext == ext:
            ch_e.append(_)
        else:
            pass

    return ch_e

ch = check_file(path,'name','.txt')
```
Adobe AnalyticsのReporting APIを使うシンプルなPHPコード

# 目的
Adobe AnalyticsがMarketing Cloudに統合され、API接続の認証の仕組みが少し変わったりしていて、過去のサンプルコードを使い回せなくなってきた。
なので、Marketing Cloudに接続されたAnalyticsを前提とした、Reporting API v1.4に接続するシンプルな方法のメモを残しておく。

# API接続の流れ（Client Credentialを利用したOAuthの場合）
1.Application IDとApplication Secretを用いてTokenを取得する
2.各種リクエストを実行する際に、Tokenを併せて送る
3.リクエストの結果の戻り値を処理

# 大前提
- Adobe Marketing CloudとAdobe Analyticsが紐づけられている
- Adobe Developer ConnectionにAdobe ID（Marketing Cloudで使っているもの）でログインしている
- Marketing CloudやAnalyticsでAPIの利用権限が付与されている

# 事前準備
- Marketing CloudでAPIに接続するアプリケーションの利用登録をする → [Create an Application](https://marketing.adobe.com/developer/documentation/authentication-1/auth-register-app-1)
- 発行されたApplication IDとApplication Secretをメモする

#具体的なコード
複雑なことはせずに、Token取得と各種APIコール実行の2つの関数を用意してみた。

```php:api_call.php
// 諸設定
define("APP_ID", "1234567890-test-app"); // Application ID
define("APP_SEC", "abc123def456ghi789"); // Application Secret
define("ENDPOINT", "https://api.omniture.com");
// エンドポイントはデータセンターによって異なる（San Joseはapi.、Dallasはapi2.、Singaporeはapi4.…

// Tokenを取得する関数（直接は使わない）：/tokenにベーシック認証でアクセスする
function getToken(){
    $ch = curl_init(ENDPOINT."/token");
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_USERPWD, APP_ID.":".APP_SEC);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array("grant_type" => "client_credentials")));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = json_decode(curl_exec($ch));
    curl_close($ch);
    return $response->access_token;
}

// APIコールを実行する関数：method（Report.Queueとか）と渡すパラメータの配列を引数にして、結果をjsonデコードして返す
function execRequest($method,$request_param){
    $token = getToken();
    $ch = curl_init(ENDPOINT."/admin/1.4/rest/?method=".$method."&access_token=".$token);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($request_param));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = json_decode(curl_exec($ch));
    curl_close($ch);
    return $response;
}

// では実際に使ってみる…

// パラメータを定義（入れ子がトリッキーなのでドキュメントをよく読むこと）
$request_param = array(
    "reportDescription" => array(
        "reportSuiteID" => "YOUR_REPORTSUITE_ID"
    )
);

// execRequest関数に、第一引数にmethod、第二引数に↑で定義したパラメータを指定
$report_id = execRequest("Report.Queue",$request_param);

// 結果を出力（Report.Queueなので、レポートIDが返ってくる）
var_dump($report_id);
```

# Enjoy!
何かトラブっても知りません
[Double] をソートする時の注意点

#NaNが含まれると思ったとおりにソートされない

```hs
> import Data.List
> let nan = 0/0 :: Double -- NaN
> sort [3,2,nan,1,5,nan,4]
[1.0,4.0,NaN,5.0,NaN,2.0,3.0]
```

ナンと恐ろしい…

```
> nan < nan
False
> nan == nan
False
> nan > nan
False
> compare nan nan
GT
> nan < 0
False
> nan == 0
False
> nan > 0
False
> compare nan 0
GT
```

ナンと恐ろしい…

`NaN`が含まれると思われるリストをソートするときは

```hs
isNaN :: RealFloat a => a -> Bool
```

を使って`NaN`を取り除くか、適切に処理した後にソートするようにしたほうが良さそうです。

```hs
> sort . filter (not . isNaN) $ [3,2,nan,1,5,nan,4]
[1.0,2.0,3.0,4.0,5.0]

> sort . map (\x -> if isNaN x then -1 else x) $ [3,2,nan,1,5,nan,4]
[-1.0,-1.0,1.0,2.0,3.0,4.0,5.0]
```
docker-composeでイメージのビルドしようとしたらADDできなかった件


こんな感じのディレクトリ構成でComposeでビルドやろうとしたときにADDできなくて困ったのでメモ。

```ディレクトリ構成
repo
  - docker-compose.yml
  - go
	  - Dockerfile
	  - addfile
```

```docker-compose.yml
go:
  build: ./go/
```

```go/Dockerfile
FROM golang:1.5
MAINTAINER hage

ADD ./go/addfile /tmp/addfile # ←これがエラーになる
```

これで`docker-compose build`すると、ADD行で怒られます。

```
ERROR: Service 'go' failed to build: lstat go/addfile: no such file or directory
```

コマンド実行してるのはdocker-composeなので`repo`です。
だからそこからの相対パスでいいかと思ってたら、違いました。

docker buildするときの事考えればわかるんですが、`Dockerfile`がある場所から見たパスですね。

正解はこれ。

```go/Dockerfile
ADD ./addfile /tmp/addfile
```

はい？ファイルあるし！って思ったんですけど、よく考えればわかることでした。
`docker build`したらどうなるんだ？って考えたらわかりました。
dhclientとunboundを連携してみた

自宅ルータが調子が悪くなり潮時かと思い立ち、[ZRouter](http://qiita.com/yamori813/items/2fc5b14648029bb4730f)でビルドしたFreeBSDベースのルータに交換する事にした。

構成はこんな感じです。

![MYFIREWALL.png](https://qiita-image-store.s3.amazonaws.com/0/104066/b6ed42c9-cbca-e625-d93c-281361465b2f.png)


プロバイダーからDHCPでIPアドレスが渡されて、その時にDNSのアドレスも取得できるので、以下のような構成で対応してみた。

rcのスクリプトでunboundを起動する。とりあえず設定はGoogleのpublicサーバを参照するようにしておく。(あんまり意味ないけど)

/var/unbound/unbound.conf

```
server:
        interface: 0.0.0.0
        access-control: 10.0.1.0/24 allow
        do-ip6: no
        username: "nobody"

remote-control:
        control-enable: yes

forward-zone:
        name: "."
        forward-addr: 8.8.8.8
```

以下の/etc/dhclient-exit-hooksを用意してrcスクリプトでdhclientをINTERNET側のインターフェースを指定して起動する。

```sh
#!/bin/sh

if [ -n "$new_domain_name_servers" ]; then

cp /etc/unbound.conf.tmp /var/unbound/unbound.conf.tmp

#TS=`date "+%Y-%m-%d %H:%M:%S"`
for namesvr in $new_domain_name_servers
do
  echo "	forward-addr: $namesvr" >> /var/unbound/unbound.conf.tmp
#  echo "${TS} $namesvr" >> /tmp/dhcp_debug.log
done

if [ -e /var/unbound/unbound.conf ]; then

TMD=`md5 /var/unbound/unbound.conf.tmp | awk '{print $4}'`
OMD=`md5 /var/unbound/unbound.conf | awk '{print $4}'`

if [ "${TMD}" = "${OMD}" ]; then
UPDATE="no"
else
UPDATE="yes"
fi

else
UPDATE="yes"
fi

if [ "${UPDATE}" = "yes" ];then

mv /var/unbound/unbound.conf.tmp /var/unbound/unbound.conf
/usr/sbin/local-unbound-control reload

fi
fi
```

unbound.conf.tmpは上のunbound.confからforward-addrを抜いたファイル。

local-unbound-controlは鍵がないと使えません。ネットで調べると鍵はlocal-unbound-setupで作れるという情報があったのですが、12.1ではできなかったの[自前スクリプト](https://qiita.com/yamori813/items/05b0e7735b67d4ef0819)で作りました。

これでDHCPで渡されたDNSサーバをunboundに渡す事ができます。

更新されてない場合はunboundを再起動しないようにしました。これは再起動するとunboundの統計情報がリセットされてしまためにそうしました。

new_domain_name_serversが複数あり、順番をランダムにして送ってくる場合はうまく動かないですが、我が家のISPは毎回同じ順番で返してくれているようなので、大丈夫なようです。

DDNSを使っている場合は登録用の処理をこのスクリプトの中に入れます。

dnsmasqを内側のDHCP Serverだけで使っているのは以前のなごりです。ネットで調べたところdnsmasqとunboundを連携する方法もありましたが、シンプルにDNSはunboundだけにしてみました。Flashが8Mのルータで設定しましたがとりあえず6Mくらいには収まっています。unboundはライブラリをいくつか必要としていてちょっと大きかったです。
ASP.NET MVC Windows認証

以下のように記述すれば良い

Web.config

```
<system.web>
  ...
  <authentication mode="Windows" />
  <authorization>
    <deny users="?" />
  </authorization>
  ...
</system.web>
```

Viewからログイン名が欲しい場合は

```
<p>@User.Identity.Name</p>
```
Azure ML を学習したい方向けのコンテンツ(2016.1時点)

#Webブラウザで学習
## [Webブラウザーでできる機械学習Azure ML入門](http://www.atmarkit.co.jp/ait/kw/ait_azureml_intro.html)
- Webブラウザーでできる機械学習Azure ML入門（1）：
 - [Azure MLって何？ からワークスペース作成まで](http://www.atmarkit.co.jp/ait/articles/1411/18/news103.html)
- Webブラウザーでできる機械学習Azure ML入門（2）：
 - [Webブラウザーだけで学ぶ機械学習の「お作法」](http://www.atmarkit.co.jp/ait/articles/1412/01/news104.html)
- Webブラウザーでできる機械学習Azure ML入門（3）：
 - [作った機械学習モデルをWebサービスにしてデプロイする](http://www.atmarkit.co.jp/ait/articles/1412/01/news166.html)

#書籍的なもので学習
・[Microsoft Azure (旧: Windows Azure) 自習書シリーズ - 概要編](https://msdn.microsoft.com/ja-jp/dn636908.aspx)
　PDF をダウンロードして学習します。かなり広範囲です。
　STEP 3. Microsoft Azure が提供するサービス
　3.1 Azure が提供するサービス
　3.2 コンピューティング サービス
　3.3 データ サービス
　      3.3.1 SQL データベース (旧名: SQL Azure)
　      3.3.2 ストレージ サービス
　      3.3.3 Machine Learning (ML)	←
　      3.3.4 HDInsight
　      3.3.5 DocumentDB
　      3.3.6 復旧サービス
　      3.3.7 StorSimple (クラウド統合ストレージ)
　      3.3.8 Data Factory

#書籍で学習
![51eGZqaeDqL__SX383_BO1,204,203,200_.jpg](https://qiita-image-store.s3.amazonaws.com/0/58634/fd5e8960-78fa-6da0-e84a-bbdd9caafde2.jpeg)

 [クラウドではじめる機械学習 Azure MLでらくらく体験] (http://amzn.to/1mWuHWU)
　出版社: リックテレコム
　発売日：2015/6/19
　著者：脇森浩志
　価格：2,808円

#勉強会の資料に目を通す
## SlideShare
[Azure MLで機械学習をやってみよう](http://www.slideshare.net/tottokug/azure-ml-43641782)
その他、SlideShare内部で、「Azure ML」で検索すると、かなりたくさんのスライドに出会えます。
Microsoftの中の人（エバンジェリスト）系の方が提供されている資料がお勧め。

#TV的なもので学習
## Channel 9
- [マシンラーニングを使ったクラウド ベースのデータ分析/予測ソリューション](https://channel9.msdn.com/Events/The-Microsoft-Conference/2014/PT-221)
け
上記放送の解説Blog
- [Azure Machine Learning できるとこまでやってみよう Vol.1 ](http://sadynitro.hatenablog.jp/entry/2015/04/11/191614)

その他、Channel 9 で、「Azure ML」& 「日本語」で検索するとかなり用意されています
- [Channel 9 の Azure ML コンテンツ一覧](https://channel9.msdn.com/Search?term=Azure%20ML#ch9Search&lang-ja=ja)

## MVA (Microsoft Virtual Academy)
[Microsoft Virtual Academy](https://msdn.microsoft.com/ja-jp/dn376515.aspx)
Microsoft Azure シリーズ のコースを展開すると、いろいろあります（用語の統一感がないですが）
- [Microsoft Azure: Azure Machine Learning 編 ～Azure Machine Learning を使ってみよう～](https://mva.microsoft.com/ja/training-courses/microsoft-azure-azure-machine-learning-azure-machine-learning--12186?l=6d8YVOsJB_5600115888)
- [Azure Machine Learning](https://mva.microsoft.com/ja/training-courses/azure-machine-learning-10315?l=J0sJwDe6_2604984382)
- [マシン ラーニングを使ったクラウド ベースのデータ分析/予測ソリューション](https://mva.microsoft.com/ja/training-courses/--10222?l=D8G6sEQ6_2404984382)
- [実践!! IoT (Internet of Things) ～ Azure の最新機能を活用した IoT 構築方法紹介 ～](https://mva.microsoft.com/ja/training-courses/-iot-internet-of-things-azure-iot--14306?l=r5mShFGgB_2500115888)

#IT勉強会
## IT 勉強会　dots.
[「Azure」の勉強会・イベント一覧](http://eventdots.jp/tag/azure)

#実際のトレーニングで学習
[Microsoft Azure のイベントより](https://azure.microsoft.com/ja-jp/community/events/?country=japan)
・[【ハンズオントレーニング】Microsoft Azure によるリアルタイム データ処理・分析ハンズオン](https://azure.microsoft.com/ja-jp/community/events/real-time-data-processing-19jan-japan/)
RSpec実行時にvagrantを操作する

はじめに
--------

この記事ではRSpec時にvagrantを使用したテストを書く方法を紹介します。テスト実行時にvagrantのイメージを自動で起動し、テストの効率化も図ります。プロジェクトのディレクトリ構造は以下のとおりです。

```
/
│── .rspec
└── spec
    ├── spec_helper.rb
    ├── vagrant
    │   │── Vagrantfile
    │   └── provisioning.sh
    └── vagrant_spec.rb
```
テスト用の `Vagrantfile` やプロビジョニングスクリプトを `spec` 内に配置することで、ディレクトリ構造もすっきりします。

下準備
----
`rspec --init` して、`.rspec` と `spec/spec_helper.rb` を作ります

```sh
rspec --init 
```

Vagrantfileを配置
----

今回はArchLinux上でApacheをつかってIt works!を表示する環境とそのテストを作ります。

`spec/vagrant/Vagrantfile` に使用するイメージ名、VMの80番ポートをlocalhostの10080に転送設定、プロビジョニングスクリプトを指定します。

```ruby
# spec/vagrant/Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.box = 'ubuntu/trusty64'
  config.vm.network :forwarded_port, guest: 80, host: 10080, auto_correct: true
  config.vm.provision :shell, :path => 'provisioning.sh'
end
```

プロビジョニングスクリプトは `spec/vagrant/provisioning.sh` に配置します。今回は単純に、apacheをインストールして有効化するシェルスクリプトです。

```sh
#!/bin/sh
# spec/vagrant/provisioning.sh
apt-get install apache2 -y
service apache2 start
```

その他vagrantが使うファイルも `spec/vagrant` に置くと、ディレクトリが散らからなくてよいです。

RSpecの設定
-----------

RSpecの `before(:suite)` と `after(:suite)` を設定することで、全てのテストスイートの前後で実行する処理を記述できます。ここに vagrantの起動・破棄する処理を書きます。

``` ruby
# spec/spec_helper.rb
RSpec.configure do |config|
  config.before(:suite) do
    puts "Starting up virtual machine..."
    `VAGRANT_CWD=#{File.expand_path('../vagrant', __FILE__)} vagrant up`
  end 

  config.after(:suite) do
    puts "\nDestroying virtual machine..."
    `VAGRANT_CWD=#{File.expand_path('../vagrant', __FILE__)} vagrant destroy -f`
  end 
end
```

ここでポイントなのがvagrant実行時に環境変数 `VAGRANT_CWD` に `Vagrantfile` のあるディレクトリを設定します。これによりカレントディレクトリに `Vagrantfile` を置かなくとも、vagrantの操作ができます。以下のコマンドで指定した場所の `Vagrantfile` の状態が確認できます。

```sh
VAGRANT_CWD=spec/vagrant vagrant status
```

HTTPの確認をするspecを書く
----

vagrantでHTTPサーバを作ったので、きちんと200が帰ってくるかの簡単なテストを書きます。

```ruby
# spec/vagrant_spec.rb
require 'net/http'

RSpec.describe 'vagrant' do
  describe 'apache' do
    it 'responds contents with 200' do
      response = Net::HTTP.start('localhost', 10080) { |http| http.get('/') }
      expect(response.code_type).to eq(Net::HTTPOK)
    end 
  end 
end
```

そしてRSpecを回してテストがパスすればOKです。

```sh
rspec
```

おわりに
--------

自分はKerberosの認証サーバが必要なテストでvagrantを使用しましたが、mockを作るよりもvmで立てちゃったほうが手っ取り早いし確実です。また今回は紹介しませんでしたが、[vagrant-vbox-snapshot](https://github.com/dergachev/vagrant-vbox-snapshot)を使ってスナップショットを撮ると、各テストケースごとにキレイな状態のVMを効率よく準備出来そうです。
Lumen でも Facade 使う


一時期は 「Facadeは邪道」って思ったたのですが、 app("db")とか書いてる時点でやってることは同じなので、
(app()->call()呼びまくるのも嫌なので) 
それなら補完の効くFacadeの方が幸せになれるんじゃないか、と思うようになりました。
(ただし使いドコロには注意)


## というわけでlumen で Facade

とりあえずlumenとide-helperを準備

~~~~
$ lumen new sample
$ cd sample
$ composer require barryvdh/laravel-ide-helper
~~~~

コメントアウトされているfacadeの設定を有効化して、IDE HELPERのプロバイダを入れる。

~~~~php:bootstrap/app.php
$app->withFacades();

// ... 

$app->register(Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
~~~~

補完用ファイルの作成!!

~~~~
$ php artisan ide-helper:generate
~~~~

はい、予想通り怒られますね。もうちょっと頑張ってみましょう。

### もうちょっと頑張る

とりあえず怒られるので`mail`のパッケージを入れてみます。

~~~~
composer require illuminate/mail
~~~~

んでもう一回叩くと…

~~~~
$ php artisan ide-helper:generate
~~~~

はい、行けましたね。不思議ですね。

## 追記: lumen5.2からの記述

mailは入れなくても良くなった。
代わりにAuth周りの仕様が変わったらしく、

````
AUTH_GUARD=session
````

の記述を入れないと動かない。この辺は後で調べる。
Rails | i18n で 言語を強制指定する方法

`locale:` オプションを指定すれば良い。

### 例: 英語を指定する場合 ( :en )

```rb
I18n.t('message', locale: :en)

# => It is English
```

### 例: 日本語を指定する場合 ( :ja )

```rb
I18n.t('message', locale: :ja)

# => これは日本語です
```

## 前提

以下の状態であることとする。

### 英語用ファイル

```config/locales/en.yml
en:
  message: It is English
```

### 日本用ファイル

```config/locales/ja.yml
ja:
  message: これは日本語です
```

## 罠

ちなみに、次のように書くのは間違いだ。

```rb
I18n.t('en.message')

# => "translation missing: en.en.message"
```

```rb
I18n.t('ja.message')

# => "translation missing: ja.ja.message"
```

# 環境

- Rails 4.0.0
- i18n 0.7.0



<!-- Update From Qiita API -->

# チャットメンバー募集


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

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


# メンター受付


https://menta.work/user/5694

<!-- Update From Qiita API -->
Docker上 で ffmpeg を動かす

# ffmpegをインストールする
Ubuntuにffmpegをインストールしようと思うと、

* 自力でビルドする
* 公式リポジトリからavconvをインストールする

という選択肢がありますが、今回は

* ビルド済みのffmpegを取得する

で手っ取り早く済ませようと思います。[参考記事](http://qiita.com/yayugu/items/d7f6a15a6f988064f51c)

# Dockerfileを記述する
wget と xz-utilsをインストールし、

* wget でビルド済みバイナリをダウンロード
* tar (+xz-utils)で解凍
* 解凍されたバイナリを /usr/local/bin にコピー

とするだけです。

```:Dockerfile
FROM ubuntu:14.04
MAINTAINER flny flny@example.com

RUN apt-get update && apt-get install -y \
      wget \
      xz-utils

WORKDIR /tmp

RUN wget http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz \
      && tar Jxvf ./ffmpeg-release-64bit-static.tar.xz \
      && cp ./ffmpeg*64bit-static/ffmpeg /usr/local/bin/

CMD /bin/bash
```

# イメージのビルドとコンテナの作成

まずdocker buildでイメージをビルドします。apt-get と wget の実行時に少し待ちますが、他はすぐ終わります。

```
$ docker build -t ffmpeg docker/ffmpeg/
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu:14.04
 ---> e9ae3c220b23
Step 2 : MAINTAINER flny flny@example.com
 ---> Using cache
 ---> 768ca4ac1367
Step 3 : RUN apt-get update && apt-get install -y       wget       xz-utils
 ---> Running in d5b1ee2d686a
(略)
Removing intermediate container d5b1ee2d686a
Step 4 : WORKDIR /tmp
 ---> Running in db8216e45616
 ---> 5627d4fa5962
Removing intermediate container db8216e45616
Step 5 : RUN wget http://johnvansickle.com/ffmpeg/releases/ffmpeg-release-64bit-static.tar.xz       && tar Jxvf ./ffmpeg-release-64bit-static.tar.xz       && cp ./ffmpeg*64bit-static/ffmpeg /usr/local/bin/
 ---> Running in 1e5e7f43932d
(略)
ffmpeg-2.8.4-64bit-static/readme.txt
ffmpeg-2.8.4-64bit-static/ffmpeg
 ---> 64fa34df02e3
Removing intermediate container 1e5e7f43932d
Step 6 : CMD /bin/bash
 ---> Running in 5d28dad829e1
 ---> 6af666ad072d
Removing intermediate container 5d28dad829e1
Successfully built 6af666ad072d
```

次に docker run でコンテナ作成し、attachしてffmpegが起動することを確認します。

```
$ docker run --name ffmpeg -itd ffmpeg
a8d613f18189284423c128a354859a2cdfc8ceb0b60be6328a1b2e512d697e30
$ docker attach ffmpeg
root@a8d613f18189:/tmp# ffmpeg
ffmpeg version 2.8.4-static http://johnvansickle.com/ffmpeg/  Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 4.9.3 (Debian 4.9.3-10)
  configuration: (略)
```

あっさり起動しました。[static buildが公開されている](http://johnvansickle.com/ffmpeg/)おかげで すごい楽です。