OmniAICreator/Qiita-1.07M huggingface dataset:
Linuxで文字列から文字列までを改行を含めて削除(置換)するコマンド


#Linuxで文字列から文字列までを改行を含めて削除(置換)するコマンド

以下のコマンドでhoge.txtの文字列から文字列まで削除します。途中に改行があっても削除できます。
`sed ':lbl1;N;s/ここから削除.*ここまで削除//;b lbl1;' hoge.txt`

ここまで削除と記載さている行全体まで削除したい場合は以下のコマンド
`sed ':lbl1;N;s/ここから削除.*ここまで削除.*\n//;b lbl1;' hoge.txt`

文字列から文字列までを改行を含めて置換する場合は以下のコマンド
//内に置換後の文字列をセットします。
`sed ':lbl1;N;s/ここから置換.*ここまで置換/置換後の文字列/;b lbl1;' hoge.txt`

これを使えば膨大なログファイルでも、不要な個所をバッサリ削除できます。
マッチする箇所が複数ある場合は全て削除されます。

##使用例
```
[user@host ~]$ cat hoge.txt
ここは残す
あああああ
aaaaaaaaaa
bbbbbbbbbb
1234567890
ここまで残す

ここから削除
かかかかか
cccccccc
dddddddddd
1234567890
ここまで削除

ここは残す
さささささ
eeeeeeeeee
ffffffffff
1234567890
ここまで残す

ここから削除
たたたたた
gggggggggg
hhhhhhhhhh
1234567890
ここまで削除

ここは残す

[user@host ~]$ sed ':lbl1;N;s/ここから削除.*ここまで削除.*\n//;b lbl1;' hoge.txt
ここは残す
あああああ
aaaaaaaaaa
bbbbbbbbbb
1234567890
ここまで残す


ここは残す
さささささ
eeeeeeeeee
ffffffffff
1234567890
ここまで残す


ここは残す
```

##解説  sed で改行を含む文字列の置換・削除
sed は入力を1行ずつ読み込む為、sedの正規表現はそのままでは改行を含む文字列をマッチできません。
そこでNコマンド`N;`を使用します。Nコマンドを使用すると次の1行も読み込んでくれます。
これで改行をマッチさせることができます。
さらに、`lbl1;`から`b lbl1;`はbコマンドまで来ると先頭にジャンプします。
よって、Nコマンドを繰り返して全行読み込みます。これで複数の改行にまたがる箇所も削除できます。

全行読み込む為、巨大なファイルの場合は処理に時間がかかります。
削除する箇所の最大の行数が分かっているなら、その数だけNコマンドを実行した方が速くなると思います。

ちなみに正規表現のピリオドは改行を含まない任意の1文字ですが、この場合のピリオドは改行も含む挙動をしました。気づかないとハマります。
sedの正規表現、特にNコマンドを使用した場合は、正規表現の挙動を疑いながらテストするべしです。
Rails5でTurbolinksの挙動が変わってた。

## 今までのイベント

```coffeescript
$(document).on 'page:before-change' , -> console.log 'page:before-change'
$(document).on 'page:fetch'         , -> console.log 'page:fetch'
$(document).on 'page:receive'       , -> console.log 'page:receive'
$(document).on 'page:change'        , -> console.log 'page:change'
$(document).on 'page:update'        , -> console.log 'page:update'
$(document).on 'page:load'          , -> console.log 'page:load'
$(document).on 'ready page:load'    , -> console.log 'ready and load'
$(document).ready                     -> console.log '$(document).ready in assets'
$(window).on 'load'                 , -> console.log '$(window).load in assets'
```

これでJSが発火してくれていたが、、、

## Rails5でのイベント

```coffeescript
# ページ切り替え時（初回ページも対象）
$(document).on 'turbolinks:load', -> console.log 'turbolinks:load'
# ページ切り替え時（初回ページは対象外）
$(document).on 'turbolinks:render', -> console.log 'turbolinks:render'
# ページ遷移前
$(document).on 'turbolinks:request-start', -> console.log 'turbolinks:request-start'
```

これで発火するように変わってた。
当面はこの二つだけ知っていれば問題ないかな。

あと、ページにキャッシュするページ数とかを設定できそうだけど、今の所はまだ未調査。
部分レンダリングすらまだ使ってない。

[Turbolinks](https://github.com/turbolinks/turbolinks)のGithubはこちら。
ソシャゲなどで使うスタミナ算出ロジック

# はじめに

一定時間でスタミナが回復するロジックが検索しても見つからなかったので作ってみました（また探し方が悪い気もするのですが・・・）
公開するほどのロジックでもない気もしますが、車輪の再発明は面倒なのでー
まぁ、そろそろスタミナ消費系のゲームは減少傾向にあるらしいので、公開する意味合いは薄れますが、勉強中な方など必要な時にどうぞ
他にも色々なロジックがあるでしょうが、あくまで一例です。

# 軽く解説

原理としては単純で、記録しているスタミナ(stamina)の値に、スタミナ最終更新日時(stamina_modified)と現在の差分から計算した値から計算した値を加えます
ですので、スタミナを減らす時にスタミナ最終更新日時を更新する必要があります
（自動回復以外でスタミナを増やす場合は更新不要）

# ソースコード
スタミナはユーザーに自身が保持する情報なのでUserクラスとしています
キャラ毎とかにある場合は適宜読み替えてください。
前提として、スタミナとスタミナ最終更新日時はDBに保存されており、DBから取得直後の状態でプライベートなプロパティに入っています

```php
class User
{
    const STAMINA_AUTO_RECOVERY_MAX = 20; // スタミナ自動回復最大値
    const STAMINA_RECOVERY_SECOND = 300; // スタミナ自動回復

    public $stamina; // スタミナ
    public $stamina_modified; // スタミナ最終更新日時

    /**
     * 現在のスタミナを取得する
     * @return int 現在のスタミナ値
     */
    public function getStamina()
    {
        // 自動回復する最大値以上の場合はそのまま返す
        if (self::STAMINA_AUTO_RECOVERY_MAX <= $this->stamina) {
            return $this->stamina;
        }

        // 最終スタミナ更新時の経過秒
        $elapse = time() - strtotime($this->stamina_modified);

        // 経過時間から回復値を算出
        $this->stamina += floor($elapse / self::STAMINA_RECOVERY_SECOND);

        // 回復する上限は自動回復最大値まで
        $this->stamina = min($this->stamina, self::STAMINA_AUTO_RECOVERY_MAX);

        // 自動回復したのでスタミナ最終更新日時を更新
        $this->stamina_modified = date('Y-m-d H:i:s');

        // 最大まで更新した場合は再計算しないようにDBを書き換える
        // 注)自動回復最大値を途中で減らした場合に問題が出るので
        //    その点を懸念する場合やDBサーバが貧弱な場合は以下ロジックは不要
        if ($this->stamina == self::STAMINA_AUTO_RECOVERY_MAX) {
            // @todo: saveメソッド
        }

        return $this->stamina;
    }

    /**
     * スタミナ使用
     * @param int $use 使用するスタミナ値
     * @return void
     */
    public function useStamina($use)
    {
        // スタミナ減算
        $this->stamina = $this->getStamina() - $use;

        // スタミナ不足の場合
        if ($this->stamina < 0) {
            throw new Exception('スタミナがないよ');
        }

        // スタミナ最終更新日時を現在に更新
        if (0 < $use) {
            $this->stamina_modified = date('Y-m-d H:i:s');
        }

        // @todo: saveメソッド
    }
}
```
Bash | 正規表現でマッチした文字列をキャプチャして使う

`$BASH_REMATCH` を使えば良い。

```bash
string="--ABC--"
regexp="-(A)(B)(C)-"

if [[ $string =~ $regexp ]]
then
  echo ${BASH_REMATCH[0]} # => -ABC-
  echo ${BASH_REMATCH[1]} # => A
  echo ${BASH_REMATCH[2]} # => B
  echo ${BASH_REMATCH[3]} # => C
fi
```

# 説明

- `$BASH_REMATCH[0]` には、キャプチャとは関係なく、マッチした文字列全体が入る。
- `$BASH_REMATCH[1]` 以降には、キャプチャした順番で、マッチした文字列が入る。

# ちなみに

正規表現部分を直書きするとダメで、いちど変数に収める必要があるっぽい。

```bash
string="--ABC--"

if [[ $string =~ "-(A)(B)(C)-" ]]
then
  echo ${BASH_REMATCH[0]}
  echo ${BASH_REMATCH[1]}
  echo ${BASH_REMATCH[2]}
  echo ${BASH_REMATCH[3]}
fi
```

# 環境

- bash 3.2

# 参考

- http://stackoverflow.com/questions/19737675/shell-script-how-to-extract-string-using-regular-expressions








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
日付形式の備忘録

前置き
------

APIの設計をしている時など、日付のデータのフォーマットを決めなければならない場面はよくあるとおもいます。
日付の形式で僕がよく使うものをまとめてみました。

Unixtime形式
------

[UNIX時間 - Wikipedia](https://ja.wikipedia.org/wiki/UNIX%E6%99%82%E9%96%93)

Rubyでは以下のようにすると出力させることが出来ます。

```rb:unixtimeサンプル
Time.at(1460426012)
=> 2016-04-12 10:53:32 +0900

Time.now.to_i
=> 1468319659
```

RFC822形式
--------

EメールやRSS2.0の日付形式として使われているようです。

Rubyでは以下のようにすると出力させることが出来ます。

```rb:rfc822サンプル
require 'time'

Time.now.rfc822
=> "Tue, 12 Jul 2016 19:30:22 +0900"
```


ISO8601形式
-------

[ISO 8601 - Wikipedia](https://ja.wikipedia.org/wiki/ISO_8601)

Rubyでは以下のように出力させることが出来ます。

```rb:iso8601サンプル
require 'time'

Time.now.iso8601
=> "2016-07-12T19:33:18+09:00"
(※)Rubyでは **拡張形式** という形式が使われているようですね。
```


個人的には、、、
-------

APIのレスポンスなどで返す日付の形式は **`ISO8601`** の形式が人間にもわかりやすくて一番いいのではと思っています。



おまけ
--------

Rails(active support) を入れている場合は以下の様なメソッドでも表示できるようです。

```
Time.now.to_s(:rfc822)
Time.now.to_s(:iso8601)
```


以上、備忘録でした。
{rstan}でN数の異なる2群の平均値の差


{rtan}を使った2群の平均値の差の検定。
[ASAの声明](https://www.amstat.org/newsroom/pressreleases/P-ValueStatement.pdf)を受けて。


方々で書かれているので何番煎じなんだ、という話ですが。
http://www.slideshare.net/simizu706/stan-62042940
http://tjo.hatenablog.com/entry/2016/03/10/190000

サンプル数の異なる2群でやりたかったので。


## サンプルデータの準備
まぁこんな感じで。
サンプル数は各群 M, Nとします。

```r
set.seed(1)

M <- 10
N <- 12

X1 <- rnorm(M, 50, 11)
X2 <- rnorm(N, 40, 8)


boxplot(X1, X2, border=c(1,2))
points(rep(1, M), X1, pch=17, cex=2)
points(rep(2, N), X2, col="Red", pch=17, cex=2)
```

<img width="400" alt="スクリーンショット 2016-07-14 23.21.27.png, width=200" src="https://qiita-image-store.s3.amazonaws.com/0/92401/8980ba8a-8168-fc6e-9c64-8ae629263582.png">

## t-test
t-testは、こんな感じ。

```
t.test(X1, X2, var.equal = F)
```

![スクリーンショット 2016-07-14 23.56.15.png](https://qiita-image-store.s3.amazonaws.com/0/92401/77e25df5-1be5-2462-6e3b-8d6af113b08b.png)

という事で、$p < 0.05$ なので「有意差あり」。
厳密には、「帰無仮説を採用した際に、現在のデータとそれより甚だしいデータを説明できる確率が5%より小さい」。

## {rstan}でやると。

要するに、

```math
\begin{eqnarray*}
X1 &\sim& m_1 + Normal(0, s_1)\\
X2 &\sim& m_1 + m_2 + Normal(0, s_2)
\end{eqnarray*}
```
この$m_2$がゼロで無ければ「差がある」。

stanのコードは、上の式をそのまんまペタペタと書きます。

```stan
data{
  int<lower=0> M;
  int<lower=0> N;
  real x1[M];
  real x2[N];
}

parameters{
  real<lower=0> s1;
  real<lower=0> s2;
  real m1;
  real m2;
}

model{
  for(i in 1:M)
    x1[i] ~ normal(m1, s1);
  for(i in 1:N)
    x2[i] ~ normal(m1+m2, s2);
}
```

これを 

```r
code1 <- "hoge"
```

とかにしておきます。

で、

```r
library("rstan")

dat <- list(M=M, N=N, x1=X1, x2=X2)
fit <- stan(model_code=code1, data=dat, iter=1000, chain=4)
```

並列化したければ[前の記事](http://qiita.com/kilometer/items/ec6db39948329cdc796b)を参照のこと。

![スクリーンショット 2016-07-14 23.55.02.png](https://qiita-image-store.s3.amazonaws.com/0/92401/12a5d5e4-f19a-68c8-d2a9-0903e8fe6797.png)

Rhat>1.2とか、n_effがiterより極端に低いとかになったら、収束してません。
ま、めちゃめちゃ単純なモデルなので大丈夫でしょう。

## 結果の図示
m2の事後分布が0でない事を一目で分かるような図を書きたい。
どうとでもなるんですが、最近はこんな感じにしています。

```r
library("ggplot2")

m2 <- extract(fit)$m2
dat_gg <- data.frame(X=density(m2)$x, Y=density(m2)$y)
q <- quantile(m2, prob=c(0.025, 0.975))

ggplot()+
  geom_line(data=dat_gg, aes(x=X, y=Y))+
  geom_ribbon(data=subset(dat_gg, X >= q[1] & X <= q[2]),
              aes(x=X, ymin=0, ymax=Y))
```
<img width=450 alt="スクリーンショット 2016-07-15 0.09.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/92401/a30f6237-f252-5a79-ec73-2e29d3c9e7f8.png">

m2の事後分布の95percentileが黒塗部分ですので、
一目瞭然で、まぁ、0ではない、と。


どっとはらい
history apiで、iOS版Chrome独自の挙動

# はじめに
レスポンシブWebデザインのWebサービスを開発していて引っかかった問題について書いてみようと思います。検索してもこの問題についてまだヒットしません。

**ブラウザのhistory apiで、pushState()、popStateイベントに関する問題です。**
結論から申しますと、この問題を直接回避する手段はなさそうです。

# 経緯
当該サイトはページングもするし、それぞれのページではBootstrap（＋改造）を使ってポップアップも多重に行います（中身はHTML+CSS+JavaScriptでのウインドウ作成）。（ :large_blue_diamond: 以後「**独自ウインドウ**」といいます）

:large_orange_diamond: 動作確認環境

| デバイス       |   ブラウザ    |
|:-----------------|:------------------|
| PC(Windows)      | Chrome、Firefox、IE |
| Androidスマホ     | Chrome、Firefox、Opera |
| iPad mini | Safari、Chrome |

今年（2016年）5月くらいまでは問題は無かったのですが、それ以後、iPadのChromeだけ挙動が変ってしまいました。

# 遭遇した問題
## 問題の動作
問題の動作の箇所ですが・・・
このWebサービスにユーザがログインするとマイページに移動させます。その直後に独自ウインドウを開いて「ログインしました」というメッセージを表示しています。
このウインドウを閉じた直後に問題が発生します。

## JavaScriptでは
その独自ウインドウを表示する際に pushState() でダミーの履歴を追加し、ウインドウを通常の方法で閉じたときは back() で履歴を取り除き、その際発生するpopStateイベントは無視するようにしています。
ユーザがブラウザのback機能を使った場合に発生するpopStateイベントハンドラでは独自ウインドウを閉じるようにしています。
:cat:  *余談ですが、Androidではブラウザではなく、システムのbackボタンがブラウザのbackに割り当てられますから、Android端末ではbackによりウインドウを閉じるという動作は頻繁に使用するものと思われ、今回history apiでの実装はAndroidのためだけに行ったと言っても過言ではありません。* 

## 問題の詳細
問題の挙動は、iPadのCromeのみで起こり、独自ウインドウを閉じた直後にbackしてログイン画面に戻ってしまう、という動作です。本来ならマイページ画面に留まるはずです。

実は、他にも独自ウインドウはAjaxと組み合わせていて多用しています。他の大部分の箇所では問題が発生せず、一部のみこの問題が発生します。
違いはUIイベント以外でpushState()をコールしているという差異しかありません。しかし、pushState()前後のhistory.lengthを調べてみても、ちゃんと増えています（増えなければまだきれいな解決方法があったはず）。その後、back()をコールした際に、なんとpopStateイベントが発生せず、同時にpushState()した履歴を飛ばして更に1つ追加でback動作をしてしまう仕様のようなのです。

まとめると、
:o: 正常の場合、
１．独自ウインドウを開くと同時に pushState()コール
２．独自ウインドウを画面から閉じられたときに back()コール
３．back()によりpopStateイベントが発生、ハンドラでの処理はなし

:heavy_multiplication_x: 異常の場合、
１．独自ウインドウを開くと同時に pushState()コール
２．独自ウインドウを画面から閉じられたときに back()コール
３．back()によるpopStateイベントが発生**しない**上、pushStateした履歴を飛ばして更にback動作をしてしまい、画面が変ってしまう。

そして、異常の動作になる条件としては、手順１．でのpushState()コールが**UIイベントではない**場合（この場合はreadyイベント）です。
Windows版やAndroid版のChromeを含め、他のブラウザでこの現象は確認されていません。

## 問題の対処は？
おそらく、これは蟻地獄サイト（backして抜けられないようにする）対策の仕様だと思われますが、なぜiPad（おそらくiOS版全般）版のChromeだけそのようにしているのかは腑に落ちませんし、情報が得られていません。（ :eyes: なにか情報があったら教えてください！）
現状、iOS版のChromeは非推奨とし、iOS版Chromeだけを切り分けて（[UserAgentからOS/ブラウザなどの調べかたのまとめ](http://qiita.com/nightyknite/items/b2590a69f2e0135756dc)）ブラウザのback機能で独自ウインドウを閉じる処理自体をやめています。そのままだとあまりにもバギーな動作なので :scream: 

というわけで、本質的な問題回避には至っておりませんが、もし、この仕様が主力となって多くのブラウザの標準になってしまうようだと困ってしまいます。
完全な１ページ設計にすることが求められそうです。現在は、Ajax＋独自ウインドウを多用はしていますが、ページ移動も併用している~~中途半端~~ハイブリッドな設計になっています。
ただ、完全な１ページ設計にしたからといって、最初にサイトにアクセスした直後に（UIイベントによらず）ポップアップウインドウを表示する、という場面が完全に回避できるとは限りません。と、考えるとけっこう困った仕様に思えてきます。（ :octocat: 標準化されませんように！）

readyイベントをUIイベントに偽装する方法があればいいのですが、それは多分無理だと思って調べてはいません。それができたら蟻地獄サイトもできてしまうことになるでしょうから。UIイベント、ということに思い当たる前はsetTimeout()ハンドラを使ってスレッドを分割してみるという事もして見ましたが無駄でした（他の問題が発生する場所ではけっこうこれで解決できることもあります）。

# 余談
実は、iPadのChromeは現在の仕様に至る前に、ちょっと違う仕様に変化したことがあります。上記×の３でpopStateイベントは発生するのですが、それでもブラウザがbackしてしまうようになっていたのです。そのときは、そのハンドラの戻り値にfalseを指定することで実際にブラウザがbackしてしまうことを回避できていました。これは偶然発見した回避策ですが、その後それさえも通用しなくなってしまい、現在に至っています。

2016.7
少し意味のある負荷試験コード

少し意味のある負荷試験コード

```c

#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

#define TRIES 2000

void *run(void *args) { sleep(10);
}

int create_thread(void) {
  pthread_t thread;
  return pthread_create(&thread, NULL, &run, NULL);
}

int create_process(void) {
  pid_t pid;

  pid = fork();
  switch (pid) {
    case -1 :
      return -1;
    case 0 : /* child process */
      sleep(10);
      _exit(0);
      break;
  }

  return 0;
}

int main(int argc, char *argv[]) {
  int i;
  int ret;

  for (i = 0; i < TRIES; i++) {
    if (i % 10) {  /* creates thread */
      ret = create_thread();
      printf("%-4dth try : pthread_create() returns : %-2d, %s\n",
          i, ret, strerror(ret));
    }
    else {        /* creates process */
      ret = create_process();
      printf("%-4dth try : fork()           returns : %-2d, %s\n",
          i, ret, strerror(errno));
    }
  }

  return 0;
}
Pandas: DataFrame.rolling()のごく簡単な例

http://pandas.pydata.org/pandas-docs/stable/groupby.html
ここ読んでいて、突如rolling()という関数が出てきた。
[APIリファレンス](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rolling.html)を見てもよくわからず戸惑ったので、簡単な例でどんなメソッドなのかつかんでみる。

まずは適当に使ってみる。

```
In [1]: import pandas as pd

In [2]: import numpy as np

In [3]: s = pd.Series(range(0,7))

In [4]: s
Out[4]: 
0    0
1    1
2    2
3    3
4    4
5    5
6    6
dtype: int64

In [5]: s.rolling(window=3, min_periods=3).mean()
Out[5]: 
0    NaN
1    NaN
2    1.0
3    2.0
4    3.0
5    4.0
6    5.0
dtype: float64
```

Out[5]からわかるように、`rolling()`と`mean()`により、`Series s`の各要素について、（その要素を含み）それ以前の3つ分の平均値を算出することができる。つまり移動平均値が算出される。
例えば`index=3`について見ると、`index=1,2,3`の要素の値がそれぞれ`1,2,3`なので、それら3個の平均値である`2.0`が出力されている。
`index=0, 1`の要素については、それ以前に必要なだけの要素数が無いので、計算が行われずNanが出力されている。

`index`を遡って計算対象とする要素数を決めるのが`window`であり、有効な計算結果を出すのに最低限必要な要素数を指定するのが`min_periods`である。なので、「4要素の平均を出したい。最低限2要素あれば結果を出力したい」場合は以下のように指定すれば良い。

```
In [6]: s.rolling(window=4, min_periods=2).mean()
Out[6]: 
0    NaN
1    0.5
2    1.0
3    1.5
4    2.5
5    3.5
6    4.5
dtype: float64
```

また、`center=True`とすると、起点とする`index`とその前後あわせて`window`個の要素を計算対象とする。

```
In [7]: s.rolling(window=3, min_periods=3, center=True).mean()
Out[7]: 
0    NaN
1    1.0
2    2.0
3    3.0
4    4.0
5    5.0
6    NaN
dtype: float64

```
全く意味のない負荷試験コード


全く意味のない負荷試験コード

```php
<?php
  ### konin-todoke.comにアクセスをするだけの処理
  $fp = array();
  for ($i = 0; $i < 1100; $i++) {
    $fp[] = fopen('http://domain/', 'r');
    echo $i."\n";
  }
?>
Playプロジェクトにプロジェクト名を与える


何もしないままだと`http://localhost:9000/`でアクセスすることができますが，このままだとどのプロジェクトがわかりづらいので，今回はこのURLを`http://localhost:9000/プロジェクト名/`にする方法を紹介します．

プロジェクト名を`SampleProject`とします．

## 設定

```conf:conf/application.conf

play.crypto.secret = "changeme"

# The application languages
# ~~~~~
play.i18n.langs = [ "en" ]

## 以下を追加
application.context = /SampleProject/

```

`conf/routes`ファイルは何も手を加えなくて結構です．

これで[http://localhost:9000/SampleProject/](http://localhost:9000/SampleProject/)にアクセスするとPlayの画面が表示されるようになります．

## 付録
[warファイル化する](http://qiita.com/shu920921/items/5e27f3c12352c07f5bb9)ときとかこの設定をしておかないと，すでに動いているプロジェクトと衝突してしまう可能性があります．
EC2でCUDA Digits 3.0を動かす方法

# 概略
手元で画像系の機械学習を動かしていたが、スペック的にかなり辛くなったのでAWSに頼ることに。

AWSでCUDA Digits(caffeのWebフロント)を動作させる方法に関するメモ書き。


# EC2の準備
スポットインスタンスでg2.2xlargeなインスタンスを用意。以下適当にスクショ。
![image](https://qiita-image-store.s3.amazonaws.com/0/133666/97fd2f95-8cf9-157e-aca2-9f60c2ba1ec1.png)
![image](https://qiita-image-store.s3.amazonaws.com/0/133666/44f1d2dc-442e-1fe6-c161-62d7e0ac233b.png)

`$0.8～$0.9/h`程度なのでそれなりに安い気がする。
ただ、スポットインスタンスで学習中に消された時の悲しみは半端無いので、お金に余裕があるなら普通にインスタンスを建てるのもありかも。

ちなみにDigits 3.0は80番ポートを利用している模様。もちろん変更は可能。


# ドライバのインストール & Digitsのインストール
基本的に参考文献の引用。
参考文献: http://www.learnopencv.com/nvidia-digits-3-on-ec2/


## ドライバのインストール
以下のコマンドを実行してNVIDIAドライバ等をインストール。

```bash
sudo apt-get update && sudo apt-get -y upgrade
sudo apt-get install -y linux-image-extra-`uname -r`
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt-get update
sudo apt-get install nvidia-361 nvidia-settings
```
`nvidia-361`の部分は最新のドライバに合わせれば良い気がする。

EC2のGPUに関する仕様は以下を参照。
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using_cluster_computing.html

今回はこんな感じで検索した。
![image](https://qiita-image-store.s3.amazonaws.com/0/133666/77e9afcf-997f-ab42-9d98-0e473813dd4a.png)


## おまじない？
上記ドライバのみでは上手く動かなかった。
具体的には以下の様なエラーが出て、学習をはじめられない。

```
ERROR: Check failed: error == cudaSuccess (30 vs. 0) unknown error
```

調べていると以下の様なissuesが引っかかった。
https://github.com/NVIDIA/DIGITS/issues/799
曰く以下の様に足りないものを入れたら良いらしい。

```bash
sudo apt-get install nvidia-modprobe
```


## Digitsのインストール
```bash
CUDA_REPO_PKG=cuda-repo-ubuntu1404_7.5-18_amd64.deb && 
wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/$CUDA_REPO_PKG && 
sudo dpkg -i $CUDA_REPO_PKG
 
ML_REPO_PKG=nvidia-machine-learning-repo_4.0-2_amd64.deb &&
wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1404/x86_64/$ML_REPO_PKG &&
sudo dpkg -i $ML_REPO_PKG
sudo apt-get update
sudo apt-get install digits
```

ポート番号を変更したい場合は以下のコマンドを実行。
`sudo dpkg-reconfigure digits`


# 動作確認
![image](https://qiita-image-store.s3.amazonaws.com/0/133666/53a2561d-bade-fd74-6ee9-66ab4feac25c.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/133666/c506b12c-59d8-ab9d-530f-81b8510daab7.png)

![image](https://qiita-image-store.s3.amazonaws.com/0/133666/789abd89-3bb2-6776-ef6a-3e696eab1582.png)

簡単に動くから本当に良い話。
カジュアルにbrewfileにインストールした項目を追加する


以下のようにすると、クリップボードに入ってる、`brew install SOMETHING`を自分のbrew用シェルスクリプトにサクッと追加できる。

```shell-session
$ echo `pbpaste` >> pathto/brewfile.sh
```


aliasに以下のようにしておくと便利に使える

```shell
alias add_to_brewfile='echo `pbpaste` >> pathto/brewfile.sh'
```

正しクリップボードの値がいつも正しいとは限らないので、自己責任で。
別リポジトリでコミットが進んでしまったリポジトリから、コミットログも取り込む

## 背景
開発の途中でマルチベンダになり、zipファイルで納品していたソースコード（最新より数ヶ月古い）で他社が開発をはじめてしまった。
弊社でも機能追加やバグ修正を行っていたため、こちらのリポジトリも進行してしまっている。
他社は修正したものをzipファイルで一括して修正差分として提出すると言っている。
手動マージは地獄なのでそれを回避したい。

## 前提
* 中央リポジトリは弊社にある。
* 他社は納品されたzipファイルを自社のGitに取り込んでいる（弊社のコミットログはない）
* 他社のGitのリポジトリは参照できる状態になっているものとする。


やりたいことは基本的に [Git で複数のリポジトリをまとめたり、逆に切り出したりする](http://qiita.com/uasi/items/77d41698630fef012f82) と同じ

## 他社の変更分を取り込む

### 作業用のディレクトリ作成
```
% mkdir -p merge/{AAA,BBB}
% cd merge/BBB
% git clone BBB.git
% cd ../AAA
% git clone AAA.git
% cd AAA
% git checkout -b merge/AAA origin/master
```
※ AAAが弊社、BBBが他社

### 他社リポジトリを追加してfetch、merge
```
% git remote add tmp ../../BBB/BBB   # (他社リポジトリの.gitディレクトリのあるディレクトリ)
% git fetch tmp
```

### ブランチの確認
```
% git branch -a                                                                       (git)-[merge/AAA]
  master
* merge/AAA
  remotes/origin/HEAD -> origin/master
  :
  :
  remotes/tmp/master
```
remotes/tmp/master のブランチ等が増えているはず

### マージ
```
% git merge tmp/master
```
おそらくコンフリクトが発生するので、[merge-conflicts](https://atom.io/packages/merge-conflicts)などでちゃちゃっと解消していく。
最後にこれを中央リポジトリへプッシュして、PRを投げれば一旦は終わり。
その後は中央リポジトリを用意でき次第、そちらを各社が参照するようにすれば良いはず。

### 両社で同一のリポジトリを参照するまでの変更取り込み
さっさと同一のリポジトリで開発をしたいものの、会社間の面倒な関係上その後の更新も取り込んでいく

```
$ git fetch tmp
$ git cherry-pick [commit id]
```

単純にcherry-pickをすると、このようなエラーが出てcherry-pickが失敗する場合があります。

```
% git cherry-pick [commit id]                                                           (git)-[merge/AAA]
error: Commit [commit id] is a merge but no -m option was given.
fatal: cherry-pick failed
```
その場合には、

```
% git cherry-pick -m 1 [commit id]
```
としてmerge commitを取り込んであげましょう。
また、PullRequestなどの取り込みのある場合

```
nothing to commit, working directory clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

    git commit --allow-empty
```
などのメッセージがされるので、メッセージ通りに

```
% git commit --allow-empty
```
してあげれば、他社の変更分を取り込めるはずです。

複数のcommitをまとめてcherry-pickしてやるには

```
% git cherry-pick [始点となるcommit]..[終点となるcommit]
```
この場合、始点となるcommitは、実際の取り込みたいcommitの１つ前を指定してやる必要があります。


開発者としてはこういった状況は非常によろしくないのだけれど、
会社間の契約の関係上などで起こりえたりするので、自戒の意味も込めて手順として残しておきます。
Debian jessieでcertbotを使う

[Let's Encrypt と Nginx で Qualys SSL Labs の評価をAにする](http://qiita.com/hal_sk/items/61995565b871aeee0d75) を読んで、Debian jessieでもやってみようとおもいやってみました。

# certbotのインストール
certbotの[Nginx on Debian 8(jessie)](https://certbot.eff.org/all-instructions/#debian-8-jessie-nginx)を読めばいいです。

## jessie-backportsの設定
jessieの場合/etc/apt/source.listにbackportsの設定が必要です。

```
deb http://ftp2.jp.debian.org/debian jessie-backports main contrib non-free
deb-src http://ftp2.jp.debian.org/debian jessie-backports main contrib non-free
```

## certbot パッケージインストール
```
$ sudo apt-get install certbot -t jessie-backports
$ sudo certbot certonly --webroot -w [example.comのルートディレクトリ] -d example.com
```

自動更新設定は/etc/cron.d/certbotにしてくれてありますので不要です。もしテストしたい場合は以下でできます。

```
$ sudo certbot renew --dry-run
```

後はDH鍵設定や[Mozilla SSL Configuration Generator](https://mozilla.github.io/server-side-tls/ssl-config-generator/)で設定作ったりすればOK。
nginxのバージョンは1.6.2、OpenSSLのバージョンは1.0.1tです。
新規RailsプロジェクトをDockerで始める手順

新規RailsプロジェクトをDockerで始めようとすると結構大変なのでまとめておきます。ここでの説明はホストマシンをMac、DockerホストをLinux仮想マシン(docker-machine必須)として進めます。

まず、[dinghyをインストールして起動]しておきます。

## docker-compose.ymlを作る

```yaml:docker-compose.yml
web:
  build: .
  command: bundle exec rails s -b '0.0.0.0'
  volumes:
    - .:/app
  environment:
    VIRTUAL_HOST: rails.docker
  links:
    - db

db:
  image: mysql:5.7
  command: >
    bash -c '
    touch /var/log/mysql/general.log &&
    chown mysql:mysql /var/log/mysql/general.log &&
    tail -f /var/log/mysql/general.log &
    /entrypoint.sh mysqld
    --character-set-server=utf8mb4
    --collation-server=utf8mb4_general_ci
    --general-log=true
    --general-log-file=/var/log/mysql/general.log
    '
  # /dev/stdout is not writable by mysql user. See https://github.com/docker/docker/issues/6880
  ports:
    - "3310:3306" # sequelproを使う人向け
  environment:
    MYSQL_ROOT_PASSWORD: root
    MYSQL_DATABASE: app
```

dbのcommandはわらわらと書いてますが、クエリーログをSTDOUTに出すためにしているので、クエリーログが不要ならcommand自体をはしょってもOKです。

## Dockerfileを作る

```bash:Dockerfile
FROM reoring/rails
```

MySQLやPostgreSQLなどRails開発に必要そうなライブラリを同梱して`ONBUILD`にも対応したイメージを@reoringが公開しているので活用します。ありがたや。


## 適当なGemfileとGemfile.lockを作ります

```bash
{
  echo "source 'https://rubygems.org'"
  echo "gem 'rails', '4.2.6'"
} > Gemfile
touch Gemfile.lock
```

ここまででディレクトリ構成はこうなっているはずです:

```
$ tree .
.
├── Dockerfile
├── Gemfile
├── Gemfile.lock
└── docker-compose.yml
```

## Railsプロジェクトを生成する

```bash
# MySQLの場合
docker-compose run web rails new . --force --database=mysql --skip-bundle

# PosgreSQLの場合
docker-compose run web rails new . --force --database=postgresql --skip-bundle
```

Railsのプロジェクトが生成され、ファイル構成はこうなります:

```
$ tree . -L 1
.
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── README.rdoc
├── Rakefile
├── app
├── bin
├── config
├── config.ru
├── db
├── docker-compose.yml
├── lib
├── log
├── public
├── test
├── tmp
└── vendor
```

## Railsコンテナをビルドしなおす

Gemfileが出来たので改めてビルドしなおします。

```
docker-compose build web
```

## DB設定を書き換える

環境変数からDB設定を受け取れるように書き換えます。

```yaml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: <%= ENV['DB_ENV_MYSQL_ROOT_PASSWORD'] %>
  host: <%= ENV['DB_PORT_3306_TCP_ADDR'] %>

development:
  <<: *default
  database: <%= ENV['DB_ENV_MYSQL_DATABASE'] %>
```

## 環境を起動する

```
docker-compose up
```

## ウェブサイトにアクセスする

http://rails.docker/ を開きRailsのデフォルト画面が表示されれば完了です。

あとは忘れないうちに、生成されたRails関連のファイルをgitにチェックインしておきましょう。


[dinghyをインストールして起動]: http://qiita.com/suin/items/c2ef8ff06b844be656cc#dinghy%E3%81%AE%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%82%92%E4%BD%9C%E3%82%8B
日頃sshで入っていたサーバーにログインできなくなった時

# WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

ssh user@xx.xx.xx.xx でいつも通りsshログインしようとしたらエラーが発生

```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX.
Please contact your system administrator.
Add correct host key in [known_hostsの場所][host keyを登録してるソース] to get rid of this message.
Offending RSA key in [known_hostsの場所][host keyを登録してるソース]:[行数]
RSA host key for [sshで入るIP] has changed and you have requested strict checking.
Host key verification failed.
```

# host key を登録してるソースの修正

1.エラーに出ていた[known_hostsの場所][host keyを登録してるソース]を修正する。  

```
vi [known_hostsの場所][host keyを登録してるソース]
```

2.エラーに表示されている行の箇所に該当IPのkeyに関する記述があるので、削除か、コメントアウトをする。
3.保存

sshログインができるようになります👍
オーバーライドしたスーパークラスのメソッドを呼び出す

こんなコードを書きました。

```rb
NewClass = Struct.new(:class)
```

ところがよく考えると、これじゃあ`Object#class`が呼べません。

```rb
obj = NewClass.new("1")
obj.class  #=>"1"　NewClassじゃない！
```

`super`や`alias`も使えそうにありませんが、
そんなときに`Object#class`を呼び出す方法が探してみたらありました！

```rb
Object.instance_method(:class).bind(obj).call  #=>NewClass
```

メンバ名にclassなんか使うな！というツッコミはなしでお願いしますm(__)m

参考：http://d.hatena.ne.jp/sumim/20061201/p1
コマ撮りアニメをHTML 5.1のpicture要素だけで作る方法(CSS、JavaScript不要)

HTML 5.1にて実装される`picture`要素を使うと、ビューポート（表示しているウインドウの大きさ）ごとに画像を出し分けることが可能です。今回は**CSSやJavaScriptを用いずに`picture`要素のみでコマ撮りアニメ（ストップモーション）を作ってみました**。

[![](https://qiita-image-store.s3.amazonaws.com/0/67884/d6c83204-90e6-019f-c40c-88b697ad95fa.gif)](http://codepen.io/tonkotsuboy/full/zBPjBa/)

▲ `picture`要素だけでコマ撮りアニメを実現している様子。ウインドウ幅を変更することで画像が切り替わる。

なお、`picture`要素の基本的な使い方は記事「[HTML5.1の新要素picture入門](http://qiita.com/tonkotsuboy_com/items/8c7c7b5f4794c95db805)」を参照ください。

# ストップモーションの作り方
実装方法は次のとおりです。[200枚の画像](https://github.com/tonkotsuboy/testCodes/tree/gh-pages/160713_accordion/images)が、700px~899pxのビューポート幅で切り替わります。 [`picture`要素に対応しているブラウザ](http://caniuse.com/#feat=picture)で動作します。

```html
<picture>
  <!--source[media="(max-width: $$$@700px)"][srcset="images/frame_$$$.jpg"]*200-->
  <source media="(max-width: 700px)" srcset="images/frame_001.jpg">
  <source media="(max-width: 701px)" srcset="images/frame_002.jpg">
  <source media="(max-width: 702px)" srcset="images/frame_003.jpg">
  <source media="(max-width: 703px)" srcset="images/frame_004.jpg">
(中略)
  <source media="(max-width: 899px)" srcset="images/frame_200.jpg">
  <img src="images/frame_001.jpg" alt="">
</picture>
```

デモをCodepenにアップしました。ウインドウサイズ700px付近で、ゆっくりとブラウザのウインドウ幅を変更してみてください。

- [デモ](http://codepen.io/tonkotsuboy/full/zBPjBa/)
- [全ソースコード](http://codepen.io/tonkotsuboy/pen/zBPjBa)

macOSのSafari 9.1で動作している様子は下記です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">昨日上げた記事の動画キャプチャー。<br>CSS、JavaScriptを使わずHTMLだけでコマ撮りアニメ（ストップモーション）を実現しています。 <a href="https://twitter.com/hashtag/HTML5?src=hash&amp;ref_src=twsrc%5Etfw">#HTML5</a><a href="https://t.co/zRfwnm99jZ">https://t.co/zRfwnm99jZ</a> <a href="https://t.co/xzi88HaMrT">pic.twitter.com/xzi88HaMrT</a></p>&mdash; 鹿野壮@CSSNite・frokan登壇 (@tonkotsuboy_com) <a href="https://twitter.com/tonkotsuboy_com/status/753760485351170048?ref_src=twsrc%5Etfw">2016年7月15日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

画像のプリロードのみJavaScriptを使っていますが、ウインドウリサイズ時の画像切替には使っていません。

# `picture`要素は便利
`picture`要素はレスポンシブイメージを実現するために用いるものです。これまで**JavaScriptを使わないとできなかったメディアクエリー別の画像の出し分けが、HTMLのみで可能になります**。

現在では、デスクトップ・モバイル含む現在の主要ブラウザ全てで`picture`要素が使えます([Can I use picture](http://caniuse.com/#search=picture))。今秋勧告されるHTML 5.1の新要素を是非体験してみてください。

ちなみに素材は、多摩川大会の動画から持ってきました。
- [多摩川花火大会フィナーレ](https://flic.kr/p/pcdTng)
Cordova tips 集

# Cordovaとは

- HTML5, CSS3, and JavaScript for cross-platform development
- standards-compliant API bindings to access each device's capabilities such as sensors, data, network status

--- 

# 理想と現実

- 理想
  - Write once, run anywhere
- 現実
  - Write once, debug everywhere (Java)
  - Write about once, debug everywhere, test everywhere (← New)
 
---

# 今日は現実の話をします。

- ユーザにとっての比較対象はNativeアプリ
    - Webアプリではない
    - 素直に書くだけではダメなとこもある
- Nativeアプリと戦うためのtips
    - タッチ, スクロール, キーボード, バックボタン
    - ...

---

# タッチ![タッチ](http://www.mxtv.co.jp/bangumilist2/801_webreco.jpg)

---

# click イベント遅い問題

- clickイベントは発火するまで少しラグがある
    - ズームとかを判定するためだったはず...
- touchstart -> touchmove -> touchend -- 300ms -> click
- よし、touchendを使おう
- でも....

---

# touchend色々発火しすぎ問題

- スクロールした後でも発火する
- そもそも要素外で指を離しても発火する!?

---

# 最終的にこうなりました

- touchend内で判定をしてからハンドラを呼ぶ

1. touchstartでスクロール位置を覚えておいて、touchendで変わってないかチェック
2. touchendでタッチ位置上の要素とe.targetが同じかチェック
    - e.touches じゃなくて e.changedTouches を使う
        - jQueryならe.originalEvent
    - タッチ位置上の要素: document.elementFromPoint()

---

# 慣性スクロール![慣性スクロール](http://www.kitami.tv/wp-content/uploads/2014/03/2014-03-24_tt.jpg)



---

# 慣性スクロール

- スマホといえばこれ。
- Androidは何もしなくてもそれなりになっている
- 問題はiOS
    - -webkit-overflow-scrolling: touch;
    - レイアウトによっては、崩れるので要確認
    - 部分スクロールは癖あり

---

# 慣性スクロール＋部分スクロール

- 具体例：リストビューの上にダイアログを表示。どちらもスクロール可の場合
- 慣性スクロールが優先的に実行される。
    - すでに完成スクロールが発生しているか
    - event.preventDefault()が呼ばれているか

---

# キーボード　![キーボード](http://up.gc-img.net/post_img_web/2012/11/44f4eef54c8002146d0e7a732c8bfd4e_0.jpeg)

---

# HTMLとキーボード

- HTMLからはキーボードのVisibilityは取れない
    - フォーカスが当たったら自動的に表示
    - キーボードの閉じるボタンを押してもフォーカスは当たったまま
- plugin を使う
    - 公式のpluginはメンテされていない
    - cjpearson/cordova-plugin-keyboard

---

# キーボードとwindow

- Keyboard.shrinkView(Bool);
    - キーボードが出てきた時にwindowをリサイズするかどうか
- position: fixed; と相性悪し

---

# キーボードのイベント

- Keyboardのvisibilityの変更のイベントのハンドリング
    - window.addEventListener('keyboardDidShow', () => {});
    - WillShow, DidShow, WillHide, DidHide, HeightWillChangeとか色々ある
        - でもiOSのみ!
    - Androidはwindowのresizeイベントを使った

---

# バックボタン ![バックボタン](http://photo1.ganref.jp/photo/0/4d77cd4fcfff604d66196d88e59c2747/thumb5.jpg)

---


# バックボタン

- 基本はhistory.backが割り当てられている
    - ルーティングライブラリ使ってれば基本は問題ないはず
- 複雑なことをやろうすると辛い
    - 例：確認ダイアログ・無効化
    - 連打とか考えると目眩がしてくる

---

### バックボタンの挙動を変える

- デフォルトの挙動をオーバーライド
    - document.addEventListener('backbutton', function() {});
    - クセあり
        - イベントを登録した時点でデフォルトの挙動をしなくなる
        - documentにしか飛んでこない→e.stopPropagation()使えない
            - ハンドラ内で頑張りましょう

---

# いいところもあるよ

- HTML5, CSS3使いたい放題
    - box-sizing神
    - calc とかflex boxとか超便利
    - Androidではcrosswalkを使いましょう
        - WebViewがchromium ベースじゃない頃のAndroid webViewは魔境です。
HTML 5.1の新要素picture入門

(2016/09/26 追記)
`picture`要素について、ICS MEDIAにて更に詳しく解説しました。こちらも合わせて参照ください。


[![](https://qiita-image-store.s3.amazonaws.com/0/67884/b3cb4d2c-54f8-4bd5-bc1b-acfc6c8dce42.jpeg)](https://ics.media/entry/13324)

[レスポンシブイメージで画像の表示を最適化 〜CSSもJSもいらないHTML 5.1の新機能 - ICS MEDIA](https://ics.media/entry/13324)

* * *

HTML 5.1にて実装される新要素`picture`要素を使うと、[CSSメディアクエリ](http://e-words.jp/w/%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E3%82%AF%E3%82%A8%E3%83%AA.html)を使って画像を出し分けることが可能です。

例えば、ビューポート横幅が700px以下の時、`a.png`という画像を表示するコードは下記のとおりです。**個別の画像の指定は`source`要素で行い、画像パスを`srcset`属性、メディアクエリを`media`属性でそれぞれ指定します**。また、`picture`要素に対応していないブラウザの為に、`img`要素も必ず指定します。

```html
<picture>
  <source media="(max-width: 600px)" srcset="images/a.png">
  <img src="images/c.png" alt="">
</picture>
```
**`source`要素は複数指定できます**。ビューポート横幅が600px以下、600px以上700px以下、それ以外でそれぞれ画像を出し分けるコード例は次です。

```html
<picture>
  <source media="(max-width: 600px)" srcset="images/a.png">
  <source media="(max-width: 700px)" srcset="images/b.png">
  <source srcset="images/c.png">
  <img src="images/c.png" alt="">
</picture>
```

デモはCodePenにアップしました。[`picture`要素に対応しているブラウザ](http://caniuse.com/#feat=picture)で動作します。

- [デモ](http://codepen.io/tonkotsuboy/full/yJPjOz/)
- [ソースコード](http://codepen.io/tonkotsuboy/pen/yJPjOz)

![](https://qiita-image-store.s3.amazonaws.com/0/67884/5afbc661-746e-be7c-1c49-f473a0e7f73b.gif)

ウインドウサイズに応じて、`a.png`、`b.png`、`c.png`の画像が切り替わるのがわかります。

#主要ブラウザの最新版で使用可能
iOS 9.3、Android Browser 50が`picture`要素に対応したことで、デスクトップ・モバイル含む現在の主要ブラウザ全てで`picture`要素が使えるようになりました（※）。もしそれ以外のブラウザでも使用したい場合は、「[Picturefill](https://scottjehl.github.io/picturefill/)」等のポリフィルを使用するとよいでしょう。

次回の記事「[コマ撮りアニメをHTML 5.1のpicture要素だけで作る方法(CSS、JavaScript不要)](http://qiita.com/tonkotsuboy_com/items/5cb4075bf8b648d8b10d)」が応用編となっていますので、是非ご覧ください。

![](https://qiita-image-store.s3.amazonaws.com/0/67884/d6c83204-90e6-019f-c40c-88b697ad95fa.gif)

*※ [Can I use picture](http://caniuse.com/#search=picture)*
顔画像認識に使えそうな10のデータセット

機械学習を使って顔画像認識をやりたいと思った時に調べたデータセットをメモしておく。
他に「こんなのあるよ」とか「これが標準的なデータセットだよ」とかあれば教えてほしい。

# Labeled Faces in the Wild

| 名前  | [Labeled Faces in the Wild](http://vis-www.cs.umass.edu/lfw/)  |
|---|---|
| カラー画像  | Yes  |
| 画像サイズ  | 150x150  |
| ユニークな人数  | 13000人以上  |
| 画像数/人  | 1680人は2枚以上の画像が存在  |


# Face Recognition Database

| 名前  | [Face Recognition Database ](http://cbcl.mit.edu/software-datasets/heisele/facerecognition-database.html)  |
|---|---|
| カラー画像  | Yes |
| 画像サイズ  | 大きめ  |
| ユニークな人数 | 10  |
| 画像数/人  | 5枚くらい |
| その他  | 3D head modelの画像は大量にある(324/人)  |



# Faces in the Wild

| 名前  | [Faces in the Wild](http://tamaraberg.com/faceDataset/index.html)  |
|---|---|
| カラー画像  |  Yes |
| 画像サイズ  |  86x86 |
| ユニークな人数  | 15000弱  |
| 画像数/人  |  1枚以上 |


# Sheffield Face Database

| 名前  | [Sheffield Face Database](https://www.sheffield.ac.uk/eee/research/iel/research/face) |
|---|---|
| カラー画像  | No |
| 画像サイズ  | 92x112, 248x258  |
| ユニークな人数  | 20  |
| 画像数/人  | 20〜40  |


# Yale Face Database

| 名前  | [Yale Face Database](http://vision.ucsd.edu/content/yale-face-database)  |
|---|---|
| カラー画像  | No  |
| 画像サイズ  | 320x243  |
| ユニークな人数  | 15  |
| 画像数/人  | 11  |


# The Database of Faces

| 名前  | [The Database of Faces](http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html)  |
|---|---|
| カラー画像  | No  |
| 画像サイズ  | 92x112  |
| ユニークな人数  | 40  |
| 画像数/人  | 10  |


# PubFig: Public Figures Face Database

| 名前  | [PubFig: Public Figures Face Database](http://www.cs.columbia.edu/CAVE/databases/pubfig/) |
|---|---|
| カラー画像  | Yes  |
| 画像サイズ  | まちまち  |
| ユニークな人数  | 開発用は60、評価用は140  |
| 画像数/人  | まちまちだが100以上が多そう  |


# Olivetti

| 名前  | [Olivetti](http://www.cs.nyu.edu/~roweis/data.html)  |
|---|---|
| カラー画像  | No  |
| 画像サイズ  | 64x64  |
| ユニークな人数  | ?  |
| 画像数/人  | ? |


# The MUCT Face Database

| 名前  | [The Japanese Female Facial Expression (JAFFE) Database](http://www.kasrl.org/jaffe.html)  |
|---|---|
| カラー画像  | No  |
| 画像サイズ  | 256x256  |
| ユニークな人数  | 10  |
| 画像数/人  |  20ほど |



# The Extended Yale Face Database B

| 名前  | [The Extended Yale Face Database B](http://vision.ucsd.edu/~leekc/ExtYaleDatabase/ExtYaleB.html) |
|---|---|
| カラー画像  | No  |
| 画像サイズ  | 168x192  |
| ユニークな人数  | 28  |
| 画像数/人  | 600弱くらい  |

# 参考

* [CVonline: Image Databases](http://homepages.inf.ed.ac.uk/rbf/CVonline/Imagedbase.htm#face)
* [Face Databases](http://web.mit.edu/emeyers/www/face_databases.html)
* [60 Facial Recognition Databases](https://www.kairos.com/blog/60-facial-recognition-databases)
* [FACE RECOGNITION HOMEPAGE](http://www.face-rec.org/databases/)
* http://www.cs.utexas.edu/~grauman/courses/spring2008/datasets.htm
Processing / ControlP5 > Serialの切替え > Slidebar / Buttonの使用

```txt:動作環境
Processing 3.1.1
ControlP5ライブラリ
Windows 8.1 pro (64bit)
```

参考 http://qiita.com/akspect/items/6a574e12181c00125d40

- sliderでCOMポートを変更
- Button押下時にポートオープン
- COMからの通信をコンソール出力

## code

```java
import processing.serial.*;
import controlP5.*;

Serial myPort;

ControlP5 slider;
int sliderValue;
int numSerial = 5;
int curSerial = -1;

ControlP5 btnOpen;

void setup() {
  size(500,500);
  slider = new ControlP5(this);
  slider.addSlider("COM")
    .setRange(-1, numSerial - 1)
    .setValue(-1)
    .setPosition(50,40)
    .setSize(200, 20)
    .setNumberOfTickMarks(numSerial + 1);

  btnOpen = new ControlP5(this);
  btnOpen.addButton("openPort")
    .setLabel("Open")
    .setPosition(275, 40)
    .setSize(100, 30);    
}

void controlEvent(ControlEvent theEvent) {
  if (theEvent.isController()) {
     if (theEvent.getName() == "COM") {
       if (curSerial != slider.getValue("COM")) {
         curSerial = (int)slider.getValue("COM");
       }
     }
  }
}

void serialEvent(Serial myPort) { 
   String mystr = myPort.readStringUntil('\n');
   mystr = trim(mystr);
   println(mystr);
}

void openPort() {
   println("Open Port"); 
   if (myPort != null) {
      myPort.stop(); 
   }
   myPort = new Serial(this, Serial.list()[(int)curSerial], 9600);
   myPort.bufferUntil('\n');
 }

void draw() {
  background(0);  
}
```

## 実行環境

実行環境

- シリアル受信側: processingを動かすPC (Windows 8.1pro)
- シリアル送信側: TeraTermで送信する (Windows 7 pro)

上記の2つの端末をシリアルのケーブル(クロス)で接続する。
こちらではVMイメージ2つにてnamed pipeを使っての動作をした。
送信側のTeraTermでは「設定 > 端末」にて[CR]を[CR+LF]に変更する。LFを終端として認識するため。

## 実行例

- Sliderを通信したいCOMポートに移動する
- OPENを押す
- 送信側から`文字列+Enter`を送信する
  - Processingソフトのコンソールにその文字列が表示される

### COM1接続時

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/82cb0d1c-3437-af65-1645-c822dc529f12.png)


### COM3接続時

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/9b03950e-5ed0-01cf-47bd-1d3dccb8da27.png)

## 補足

### 本当は違うんだ日記

本当はスライダ変更時にポートオープンをしたかったが不明なエラーが出たためボタンを追加した。
スライダ１つでオープンまでできないのであれば、スライダを使う意味はなさそう。

### TeraTermの罠

TeraTermは送信を「CR+LF」にし忘れると失敗するので、確認が必要。

### java

javaはまだよくわからない。以下は

```
if (myPort != null) {
   myPort.stop(); 
}
```

GCを動かすために、以下のようにした方がいいのだろうか？

```
if (myPort != null) {
   myPort.stop(); 
   myPort = null; // for GC
}
```

あとの方でmyPort = new Serial()しているからGCは動くのだろうか?
要望: タグをクリックしたら検索窓に 「tag:タグ名 空白」 が入った状態になってほしい

![スクリーンショット_2016-07-14_12-30-19.png](https://qiita-image-store.s3.amazonaws.com/0/25728/7d799789-deee-78fc-73c7-f5d9027312b3.png)

関心のあるタグをクリックして、そこから絞り込みたい時、
`tag:css `が入って欲しい。
Ruby | nil? もしくは empty? を同時に判定する

# 答

こんな感じ。

```rb
variable.to_s.empty?
```

# 文字列の場合

```rb
''.to_s.empty? # => true

nil.to_s.empty? # => true
```

# 配列の場合

```rb
nil.to_a.empty? # => true

[].to_a.empty? # => true
```

# ハッシュの場合

```rb
nil.to_h.empty? # => true

{}.to_h.empty? # => true
```


# 環境

- ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]


# 参考

- http://stackoverflow.com/questions/247948/is-there-a-better-way-of-checking-nil-or-length-0-of-a-string-in-ruby








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
自分でインストールしたアプリケーションを/etc/init.d/ に登録して　service 起動する

#自分でインストールしたアプリケーションを/etc/init.d/ に登録して　service 起動する

##常時起動のアプリケーションをHTTPDやMYSQLみたいに起動するスクリプトがつくれるガイドライン

https://gist.github.com/chrisvest/7673244

- service.sh を参考に起動するプログラムの場所やログファイルを書き込む
- start() stop() などの関数部分が　service start|stop で呼ばれるところなので、適宜変更可能

- アプリケーション起動するシェルとして設置(上記のservice.sh をリネーム)

> /etc/init.d/<サービス名>

- 実行権限を与えておく(chmod +x)

> 指定した場所にPIDファイル作って、常駐して指定した場所にログを出力し、終了時にPIDみてkillしてくれるというサービスアプリケーションとして動かせるってワケ。
serviceやchkconfig のシステムコマンドで扱えるようになる


もしくは次の手順で"new-service.sh"にやってもらう(OSによっては動かないことも)

`wget 'https://raw.github.com/gist/4275302/new-service.sh'`

`sudo bash new-service.sh `

サービス名を聞いてくれるのでいくつかの質問に応える

`<NAME> = $YOUR_SERVICE_NAME`

- service 登録したい名前　httpd みたいなもの

`<DESCRIPTION> = Describe your service here (be concise)`

- 配慮深き説明


`<COMMAND> = Command to start your server (for example /home/myuser/.dropbox-dist/dropboxd)`

- アプリケーションを起動するコマンド

`<USER> = Login of the system user the script should be run as (for example myuser)`

- mysql みたいな実行するユーザー名　そのアプリケーションが出力したりするところにちゃんと権限があること


> 実行したら　/etc/init.d に　service.sh　を設定したファイルを置いてくれる

### これでserviceコマンドで起動、停止できる

`service $YOUR_SERVICE_NAME start`
`service $YOUR_SERVICE_NAME stop`

### bootのときに自動起動登録(それぞれのOSの環境もあると思うので適宜)

update-rc.d $YOUR_SERVICE_NAME defaults
werckerでbitbucketと連携する

werckerでbitbucketと連携する

werckerとbitbucketを連携し、bitbucketにcommit/pushする度に、werckerで自動で処理が実行されるようにします。

bitbucketとの連携のメモですが、githubでも同様の事ができます。

# bitbucket側の設定

連携するrepositoryを先に登録しておく

# Wercker側の設定

http://wercker.com/ にアクセスし、loginする。

メニューからCreate -> Applicationを選ぶ。

指示に従って、連携するrepositoryを指定する。

- Choose a repository
    - BitBucketを選択

bitbucketに登録されているrepositoryに一覧が表示されるので、連携したいrepositoryを選択する。
選択したら、Use selected repoを押す。

- Configure access
    - Add the deploy key to the selected repository for me を選択
選択したら、Next setpを押す

publicにしたいときは、Make my app publicにチェックを入れる

Finishを押す

# bitbucket側の設定
Werckerの指示通り、wercker.ymlのテンプレートを選んで、bitbucketで管理しているリポジトリにwercker.ymlを追加

```bash
git add wercker.yml
git commit -m 'add wercker.yml'
git push origin master
```

bitbucketにwercker.ymlを追加すると、自動的にbuildが走る

以降、bitbucketにcommit/pushする度に、werckerで処理が実行される
[Vim] modeline 設定サンプル

modelineの設定を追加しておくと、他の環境に持って行った場合に規約を合わせた変更が楽になるので設定しておく。

# modelineの仕様

ファイルの上下端から`modelines`オプションで設定された行数だけ、 modelineを探しに行きます。
デフォルトは上端/下端から5行以内のようです。 

# 設定可能なオプション

| option        | short option | 詳細  |
|---------------|-------------|-------|
| textwidth	| tw	| 設定された幅で行を改行 |
| tabstop	| ts	| タブを画面で表示する際の幅 |
| expandtab / noexpandtab | et	| インデント/タブ入力時にタブではなく半角スペースとして挿入 | 
| shiftwidth	| sw	| (expandtab設定時)インデント時に使用されるスペースの数 |
| softtabstop	| sts	| (expandtab設定時)タブを入力時にその数値分だけ半角スペースを挿入 |
| wrap / nowrap	 	| | 画面端の行の折り返し設定 |
| fileformat	| ff	| ファイルの改行の種類 (dos, mac, unix) |
| filetype	| ft	| ファイルタイプ (sh, python等) |
| fileencoding	| fenc	| ファイルエンコーディング(utf-8 か shift_jis あたり) |

# 設定サンプル
## python
```py:python2
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8 ff=unix ft=python ts=4 sw=4 sts=4 si et :
```

```py3:python3
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8 ff=unix ft=python ts=4 sw=4 sts=4 si et :
```

## shell

```bash:bash
# vim: set ft=sh ff=unix fileencoding=utf-8 expandtab ts=4 sw=4 :
```

# 参考
[モードラインを使って、ファイルごとにvimエディタのオプションを指定する。 — 名無しのvim使い](http://nanasi.jp/articles/howto/file/modeline.html)
javascriptが有効なサイトでsoupを取得

いろいろなsoupの取得方法メモ。
google画像検索とか、javascriptが有効なサイトだとselenium使わないといけないっぽい。

```py:get_soup.py
#-*- coding:utf-8 -*-

from bs4 import BeautifulSoup

def get_soup_uulib2(url):
  import urllib2
  opener = urllib2.build_opener()
  opener.addheaders = [('User-agent', 'Mozilla/5.0')]
  page = opener.open(url)
  soup = BeautifulSoup(page,"lxml")
  return soup

def get_soup_urequests(url):
  import requests
  s = requests.Session()
  r = s.get(url)
  soup = BeautifulSoup(r.text,"lxml")
  print soup

def get_soup_uselenium(url):
  from selenium import webdriver
  #need chromedriver #https://sites.google.com/a/chromium.org/chromedriver/downloads
  chromedriver = "./chromedriver"
  driver = webdriver.Chrome(chromedriver)
  driver.get(url)
  page_source= driver.page_source
  soup=BeautifulSoup(page_source,"lxml")
  return soup
 
#javascript=enable
print get_soup_uselenium("https://www.google.co.jp/search?q=ねこ")
#java=off
#print get_soup_uulib2("https://www.google.co.jp/search?q=ねこ")
#print get_soup_uulib2("https://www.google.co.jp/search?q=ねこ")


```

#課題
ブラウザがいちいち立ち上がるのが面倒です。
`headless selenium`とかでgoogle検索して色々試して見るも、断念。
どなたか教えてくださいませんか。

#追記 7/19
HEADless(ブラウザを立ち上げない)の場合は、
`driver = webdriver.PhantomJS()`とすれば良いです。
`brew install phantomjs`などで入ります。
ZabbixのWeb シナリオでJenkinsが落ちていないか監視する

# 概要

Jenkinsが落ちていると困るので、Zabbixで監視するようにした。

# 結論

Web シナリオで設定をして、***Triggerをセットする***

* [1 Web監視アイテム [Zabbix Documentation 2.2]](https://www.zabbix.com/documentation/2.2/jp/manual/web_monitoring/items)

## Triggerを作成するときの注意点

Itemに登録があるものは、GUIで、選択肢として一覧でてくるとおもうのだが
Web シナリオの場合は、その一覧にでてこないようだ。

上のURLを参考に、手動でセットした。

# そもそも

Jenkinsを2系にあげたあと、SlackのPluginの影響でうまく起動できていなかった

[JenkinsのSlack pluginのバージョンをあげたら、起動できなくなったので、その対処法 - Qiita](http://qiita.com/manabuishiirb/items/c2f9e38039eb57974bc9)

## Web シナリオでチェックすること

現在はステータスコードが200で文字列にJenkinsがあったら成功としているが、
もうちょっと検討したほうがよいかもしれない

余裕があったら、またエラーをだしてみる予定
phpunit と mock と sqliteと・・・　phpでユニットテストするときのあれこれ

# phpでユニットテストをするときのあれやこれや
* 備忘録を兼ねて書いていきます。随時追記、修正します。
* 全部は書かずに、他サイトへのリンクなど貼っていきます。一覧性は悪いかも、ごめんね

## 対象者
* phpでWebアプリ開発している人
* ユニットテストをこれから始めたいと思っている人
* モックとか、DIとか、DBアクセサのテストとか、やることわかってるけどどうやんのかよくわからない人
 * 僕もよくわからないので、これから調べてまとめます

## 対象のphp version
* 5.3

> なんでそんな旧式を対象にするのかって、[このサイトにもあるけど](https://w3techs.com/technologies/details/pl-php/5/all)、未だにphp5.3のシェアが一番でかいから。
新規プロジェクトで最新のphpやミドルウェア使ってナウい開発できるのは恵まれた一部の人達だけなんだろうなということで、php5.3でも動くものを書きたいと思います。

## サンプルコードは？
* [ここ](https://github.com/keihiromasa/php-unittest-practice)に置いておきます。
 * まだ未完成です。RELEASE-1.0のタイミングで、READMEに書いときます

## 前置きで、まずはキーワードから
### phpunit
* phpユニットテスティングフレームワークのデファクトっぽい人
 * githubのOSSソースとかで見ても、phpunitでテスト書いているものが多い
* mock用のapiとかも揃っている
* BDDやってるような優等生はこんなページに用はないですねきっと

### composer
* 依存性管理ツール
 * 知っている人にはわかるが、知らない人にはなにそれ？ですよね。腹たつ。
* Java屋さんには、Mavenのシンプル版だよ！って言えばきっと伝わる
* packagistなる、OSSをまとめた神リポジトリがある（インスコしたらデフォで繋がっている）のでOSSどんどん使いましょう

### php sqlite extension
* phpにデフォルトで入っている人
* ファイルDBやインメモリDBを扱える、手軽なRDBMS
* インメモリDB生成、テーブル作成、テストデータ投入、テスト実施、終了と、DBアクセサのテスト自動化の際に力を発揮するありがたいお方
 * これなら場所を選ばずDBアクセサのテストができるね！やったね！

### ~~php-test-helper~~ uopz（user operations for Zend）
* peclライブラリ
* ユニットテスト書くときの力強い助っ人
* コンストラクタのモック化や、exitの無効化などできるパワフルな人
 * DIなんてうちのレガシーシステムでできてるわけねえだろ！って人には必須かと
 * ただやっぱり、テストコードの保守性考えるとDIできてることが理想的っぽい
* phpでモック的なはなしは、[ここに集約されてます。](http://php.net/manual/ja/refs.basic.php.php)

> だがしかし、uopzは実は[php 5.4以降でないと使えない](http://php.net/manual/ja/uopz.requirements.php)
 5.3な皆さん、涙を流して[runkitをつかいましょう。](http://php.net/manual/ja/book.runkit.php)

### DI（依存性の注入）
* 要は使いたいオブジェクトはそのメソッドの中でnewするな！引数でもらいなさい！ってことらしい
 * そうすればモックを外から渡すことで動きを外部からコントロールできるので、ユニットテストしやすい＝カバレッジ上げやすい
* ただし突き詰めていくと、「でも誰かが最終的にはnewするんでしょ？その人はそのオブジェクトに依存してんじゃん。どうやってmock化すんのさ！」という疑問にぶち当たる
 * 僕はここで随分長いこと立ち止まってしまいました・・・
* 突き詰めると、依存性は外部ファイルや環境変数など、ソースの外に追い出せ！というところに行き着く
 * 外部ファイルからdebugモードかどうかを読み込んで、デバッグモードならモックオブジェクトを生成、productionモードなら本物のオブジェクトを生成、とかね。自作はしんどい。。。
* DIコンテナなる便利な人を使うと良いらしい
 * うちのシステムPHPバージョン古すぎて使えるコンテナ見つかんないんだけど！という悲劇が少なからずある、と思う

### どう攻めるか
* PHP5.4以降を使っている人は・・・
 * レガシーシステム相手ならば、uopzを活用して、外から無理やり動きを変えることでなんとかカバレッジ上げましょう。でもテストの保守性はどうなるんだ・・・
 * 新規ならば、DIを進めて、普通にモックオブジェクトを外から渡してテスト進めましょう
* PHP5.3以前を使っている人は・・・
 * レガシーシステム相手ならば、、、どうしよう。。
 * 新規ならば、DI進めて、普通にモックオブジェクトを外から渡してテスト進めましょう

## 環境設定（Windowsを前提とします）
> 職場でmac使ってるんだけど？っておっしゃるリア充は呪って差しあげます

> セットアップ系は大雑把にいきます

### phpインスコ
* php for windows でググって、zip落として展開してpath通して下さい。以上。
 * 雑でごめんなさい
 * xampp とか使いたい方はどうぞ。でも一個ずつ入れた方が柔軟な気がするんですよねえ・・・

### composerと、ライブラリのインスコ
* [こちらを参考にさせてもらってください。](http://qiita.com/mikoski01/items/266469535e860312145d)
* composerから、以下をインスコしてください
 * phpunit
 * php-skelton-generator

## netbeansのインスコとセットアップ
* [Atom](https://atom.io)とか熱いですけど、Windowsだとなんかまだ重たいし、現時点ではエディタはnetbeansの方が無難かと・・・
* インスコしたら、以下をやっておいてください
 * php.exeの場所設定
 * phpunit.batの場所設定
 * php−skelton-generator.batの場所設定
 * proxy越しでネットにつながっている人は（くそう！）proxy設定も

## ユニットテスト最初の一歩
* まずは、テスト対象のメソッドが引数で受け取るオブジェクトのモックを作る
* そのオブジェクトを渡して、対象メソッドのテストメソッドを書く
 * [ここを参考](https://phpunit.de/manual/current/ja/test-doubles.html#test-doubles.stubs)
*
Bigqueryでtimestampで当日日付（JST）を指定する

Bigqueryで当日を条件に絞るときにハマったのでメモ。



条件のとこだけ記載。対象のカラム名は「time」、型はtimestamp型とします。
timestamp型でその日だけを指定する方法、簡単にできそうで意外とハマりました。


ついでに、BigQueryに入っているtimestamp型のデータは基本UTCなので、それをJSTに変換しています。
※下記サイトを参考にいたしました。
http://itnote-ichi5.com/post-bigquery-utc-jst/

```sql:当日
WHERE
  STRFTIME_UTC_USEC(TIMESTAMP_TO_USEC(time) + 32400000000, '%Y-%m-%d') = CURRENT_DATE()
```

ちなみに、1日前はこちら。

```sql:前日
WHERE
  STRFTIME_UTC_USEC(TIMESTAMP_TO_USEC(time) + 32400000000, '%Y-%m-%d') = DATE(DATE_ADD(CURRENT_TIMESTAMP(),-1,"DAY"))
```

DATE_ADDでDAYを-1で指定しています。あとは同じ。
n日前、後だったらこの数字をいじればよさそう。
Github Enterprizeの導入を検討している人に伝えておきたい2つの懸念

## 外部サービスとの連携

Github Enterprizeゆえに、閉じたネットワークの中に構築することが多いと思います。
しかし、環境だと各種Webサービスとの連携が難しいです。

CIサービスを始めとするWebサービスはGithubとの連携が当たり前のように存在します。
privateなリポジトリでも有料ならできるというものも多いです。
そういったサービスでは、Github Enterpriseと連携できるものは少ない気がします。

外部サービスでも、Enterprise版が用意されているもの(Circle CIとか)もありますが、
それにもEnterpriseな料金が発生します。その料金が払えないと結局、中で頑張るということになっていきます。

外部サービスとの連携を考えると本家Githubを使ったほうが良いこともあるようです。

## バージョンアップに追随するコスト

[ここ](https://enterprise.github.com/releases)をみてもらうと分かりますが、バージョンアップがそれなりの頻度であります。
バージョンアップのコストは多大ではないそう(自分でやってないので聞いた話)ですが、それでも追随していくのはコストがかかると思います。

また、Github Enterpriseにあるリポジトリから直接デプロイしている場合などは、
停止できる時間などが限られてくることもあるので、気軽にバージョンアップできません。
使っている人(サービス)が多ければ多いほど、メンテナンス時間も取りにくくなっていくと思います。

保守が切れない限りは固定のバージョンを使っていくという方法もあるかとは思いますが、
やはりGithub本家で導入された新しい機能は、使いたくなってくるものなので、
バージョンアップとの付き合い方を考えておいた方がいいかと思います。