OmniAICreator/Qiita-1.07M huggingface dataset:
混沌としたprawn-railsのPDFテンプレートを整理する

今関わっているプロジェクトではレッスンの詳細をまとめたPDFに結構大きな需要があり、数年間運用されてきたのですが、この[prawn-rails](https://github.com/cortiz/prawn-rails)で書かれたテンプレートの当時を知っている者がいなくなり放置されて完全に秘伝のタレ化して機能追加したくても手が付けられなくなっていたのが大きな悩みのタネでした。
Thinreportsに移行して綺麗さっぱり書き直すことも検討したのですが、どうしても譲れない要件を満たすことが困難で泣く泣く断念しました（その際の機能比較はまた別の機会に）。

そこで、今回はファットなprawnのビューに多少なりとも秩序を取り戻していく過程をご紹介していこうと思います。

### 初期状態

ざっくり言うと以下の様な感じの数百行のコードでした。

- 大量のif式ネスト
- メソッド分割一切なし
- 木を見て森を見ないコメント（個々のコメントは役に立つが肝心の全体像が見えない）
- 特定の環境に依存したURLの処理が多数
- 書き方が古かったり、スタイルガイドに準拠していなかったり、記述に無駄があったりするコードが多数
- pdf.move_down 25のようなカーソル移動処理が縦横無尽に存在する


### コンポーネントを分類する
まずは大きな処理の区分けを判別して分割します。if式まみれなことが不幸中の幸いになっており、if式の括りで何を記述しているかをおおまかに類推することが可能でした。

### クラスを作ってぶち込む
ビューで使われていたprawnの書き方は「prawn_documentのブロックから受け取ったPrawn::Documentのオブジェクトをひたすら破壊的更新していく」という関数型言語ユーザーが聞いたら卒倒しそうな仕組みですが、幸いな事にPrawn::Documentのインスタンスメソッドさえ呼べれば処理が完結するので、RailsのActionViewのように書く場所によってヘルパーが呼べたり呼べなかったりすることがありません。
そこで、別のクラスを用意して処理を内側にに押し込むことができそうです。以下がその超簡略版になります。

```.rb
class ReviewPDF
  attr_reader :pdf

  def initialize(model, pdf)
    @model = model
    @pdf = pdf
  end

  def title
    @pdf.font_size 15
    @pdf.formatted_text [
                         { text: @model.user.fullname, color: "4AAED8" },
                         { text: " さんの英会話" },
                         { text: "　（レッスン日: #{date.strftime("%Y/%m/%d")}）", size: 9 }
                       ]
    @pdf.move_down 10
    self
  end
  
  #以下省略...

   private
    def pdf_image_path(image)
      if Rails.env.development?
        #専用の処理を記述
      else
        image.url
      end
    end
end
```

```ruby:show.pdf.prawn
prawn_document do |pdf|
  pdf_model = ReviewPDF.new(model, pdf)
  pdf_model
    .title
    .explanation
    .phrase_block
    .memo
    .review
    .skype_evaluation
end
```

インスタンス変数の@pdfにPrawn::Documentを放り込んでビュー側はReviewPDFのメソッドを呼び出すだけなので超シンプルになりました。書かれなかったメソッドの内側にあるコードは正直まだかなり臭いのですが、名前がついて隔離されたぶん一歩前進といったところです。

### プライベートメソッドを拡充する
さらに、こうやってPDFに関する実装を隔離できたので、pdf_image_pathのような環境依存のコードをプライベートメソッドに切り出すことができます。ModelやHelperに本流でない処理が大量に書かれるのは気が引けたのでこちらの方が役割がはっきりしていい感じです。

### まとめ
prawn-railsでビューテンプレートを書く場合は一つのファイルに全部まとめるとカオスなことになるので別途クラスを用意して役割ごとにメソッドを分けてあげると「まだマシ」になります。ここからさらに抽象化を進めたりテスト書いたりとあるべき姿はとても遠いのですがまずはその第一歩からというお話でした。
Courseraの機械学習コース2週目 Octave/Matlab チュートリアルをやってみた。

[Courseraの機械学習コース](https://www.coursera.org/learn/machine-learning)を視聴しています。このコースはたまに演習問題がでるのでその問題をやってみました。

今回の問題は2週目のラストにある[Octaveの演習クイズ](https://www.coursera.org/learn/machine-learning/exam/dbM1J/octave-matlab-tutorial)です。基本的にOctaveで実行すればすぐわかります。ただ行列について全く知識がなかったので復習です。

P.S. このコースのクイズを自力で問題を解きたい方は読まないでください。

# 一問目
OctaveかMatlabで動作するみたいです。

```octave
A = [1 2; 3 4; 5 6];
B = [1 2 3; 4 5 6];
```
AとBのような行列があるときに、有効なコマンドを選択してください。

```octave:選択肢１
C = A' + B;
```

```octave:選択肢２
C = B * A;
```

```octave:選択肢３
C = A + B;
```

```octave:選択肢４
C = B' * A;
```

行列を書いてみると以下のようになります。

```math
A = \begin{pmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{pmatrix}
```

```math
B = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{pmatrix}
```

## 選択肢１
`C = A' + B;`になるとAの転置行列とBの加算は以下のようになりますので計算できます。

```math
\begin{pmatrix} 2 & 5 & 8 \\ 6 & 9 & 12 \end{pmatrix} = \begin{pmatrix} 1 & 3 & 5 \\ 2 & 4 & 6 \end{pmatrix} + \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{pmatrix}
```

## 選択肢2
`C = B * A;`は行列の掛け算です。

```math
\begin{pmatrix} 22 & 28 \\ 49 & 64 \end{pmatrix} = \begin{pmatrix} 1+6+15 & 2+8+18 \\ 4+15+30 & 8+20+36 \end{pmatrix} = \begin{pmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \end{pmatrix}\begin{pmatrix} 1 & 2 \\ 3 & 4 \\ 5 & 6 \end{pmatrix}
```

## 選択肢3
`C = A + B;`は行と列が合っていないのでOctaveで計算するとエラーがでます。

## 選択肢4
`C = B' * A;`の計算は行と列があっていないのでOctaveで計算するとエラーがでます。

# 二問目
行列Aが与えられているときに、行列Bを表すものを選びなさいという問題です。

```math
A = \begin{pmatrix} 16 & 2 & 3 & 13 \\ 5 & 11 & 10 & 8 \\ 9 & 7 & 6 & 12 \\ 4 & 14 & 15 & 1 \end{pmatrix}
```

```math
B = \begin{pmatrix} 16 & 2 \\ 5 & 11 \\ 9 & 7 \\ 4 & 14 \end{pmatrix}
```

```octave:選択肢１
B = A(:, 1:2);
```

```octave:選択肢２
B = A(1:4, 1:2);
```

```octave:選択肢３
B = A(0:2, 0:4)
```

```octave:選択肢４
B = A(1:2, 1:4);
```


## 選択肢１
`B = A(:, 1:2);`これを実行すると４行２列のBと同じ行列が出力されます。

## 選択肢2
選択肢２と同じです。

## 選択肢３
`B = A(0:2, 0:4)`は実行するとエラーが出ます。

```
error: subscript indices must be either positive integers less than 2^31 or logicals
```
プラスの整数じゃないとダメとあります。行列のインデックスは1から指定しないとだめってことですかね。

## 選択肢4
`B = A(1:2, 1:4);`こちらは２行４列の行列になるので間違いです。


# 三問目
行列Aが10行10列の行列で、xが１０個の要素のベクトルであるときに、友人はAxを以下のコードで計算したいと思いました。

```octave:
v = zeros(10, 1);
for i = 1:10
  for j = 1:10
    v(i) = v(i) + A(i, j) * x(j);
  end
end
```
ループのコードを書かずにベクトル化する場合に当てはまるものを選びなさい。

```octave:選択肢１
v = A * x;
```

```octave:選択肢２
v = Ax;
```

```octave:選択肢３
v = x' * A;
```

```octave:選択肢４
v = sum (A * x);
```

## 準備

Octaveで計算する場合はvの値を調べればOKです。
xとAを以下のように適当に設定すると計算できました。

```
A = magic(10);
x = [1;2;3;4;5;6;7;8;9;10]; 
```

## 選択肢1
ループの式を見ると普通の掛け算なのでこれが正解。

## 選択肢２
Octaveで実際に試すとわかるのですが、エラーがでます。

```
error: 'Ax' undefined near line 1 column 1
```

## 選択肢3
xの転置行列との掛け算です。行列の掛け算は場所を転置行列にして入れ替えると掛け算は可能になりますが、値は等しくなりません。


## 選択肢4
sumがついているので、全部足されてしまいます。よって間違いです。
vagrantでゲストOSからホストOSにファイルを同期する

## やりたいこと

* ゲストOSの特定ディレクトリの内容を、ホストOSに同期したい

これだけ！！

逆は出来るんですよね。
VagrantFileに `config.vm.synced_folder "ホストOS側のディレクトリ", "共有先ゲストOSのディレクトリ"`って。

でも、ゲストOSからホストOSへは同期出来ないんですよ・・

### 対応

結論からいうと、`vagrant-rsync-back`というvagrantのplugin使えば一発でした。

```
$ vagrant plugin install vagrant-rsync-back
$ vagrant rsync-back
```

これで、VagrantFile内の`config.vm.synced_folder`で書いたゲストOSのディレクトリの内容が、ホストOS側に同期されます。

っしゃ！

### 余談

なぜ、こんな事がやりたかったのか？
実は、Macで大量のデータをExcelに出力する。って事がやりたかったんですが、
macでphpExcel使おうとしたら、何かcomposer周りでハマったんですよね。

で、もう面倒臭いなぁ。って事で、vagrantでcentos立ち上げて、そこで作業してたんです。
最初、処理元の大量のデータはvagrantの同期機能で問題なくできたんですが、
そこで処理して出来上がったExcelファイルをホスト側に同期出来なかったので意味無かったんですよね。

で、今回のに至ったと。
以上です。ではまた。
プリンシプルオブプログラミングは初級プログラマのためのベストアルバムだ〜前提編〜

サンプルコードを漁りながらとりあえず動くコードは書けるけれど、複数人開発を前提とした保守性や拡張性、可読性などがあるコードをどう書けばいいんだろうと迷っていた時に、これはすごい・・・と思える本に出会いました。

上田勲さんの「プリンシプルオブプログラミング」です。

関連書籍にCODE COMPLETE、達人プログラマー、97のことシリーズ、リーダブルコード、アジャイル奥義など名著がこれでもかと並んでいますが、原著を見ても難しすぎて頭に入ってこないです。。　「プリンシプルオブプログラミング」ではそれら原著もうまくチョップして、再構成してくれているので読みやすい。

そういう意味でこの本は初級プログラマのためのベストアルバムだと思いました。ベストアルバムをまず聞いてから、それぞれのオリジナルアルバムを聞いていく感じで、入門編としてこの本は最適ではないでしょうか。

章立てに合わせて、学んだことを全7記事に分けて書いていきたいと思います。

〜前提編〜　（いまここ）
〜原則編〜
〜思想編〜
〜視点編〜
〜習慣編〜
〜手法編〜
〜法則編〜

# 前提とは普遍的な事実であり、受け入れなければいけないことである

この本がすごいと思ったのは、章立てが綺麗に体系立っており、毎日Web記事を読んだり、メンバーから教えてもらったりして学んだことが整理されるような感覚があったことです。

第1章は「前提」ですが、前提が一番重要なので、それを受け入れてくださいと言われます。さて、どんな前提があるのでしょうか。

# 銀の弾丸はない

1つの手法やツールでどんな状況でも解決できる銀の弾丸はない、ということは普段の開発メンバー間での会話でもありましたが、なぜ銀の弾丸がないのか考えたことがありませんでした。

その理由は、ソフトウェアが本質的に困難性を持っているからとのこと。困難性として4つ挙げられています。

1. 複雑性：ソフトウェアは大きくて複雑
2. 同調性：ソフトウェアは複雑な実世界と同調しながら使用される
3. 可変性：ユーザーがソフトウェアを使うとさらなる要求を思いつく
4. 不可視性：ソフトウェアから見ることができないプロセス等が存在する

まずは困難性が高いことを受け入れる必要がありそうです。

# プログラミングは設計行為である

弊社にはディレクターやプランナーがいません。会社やサービスの規模もあるかもしれませんが、5年近く会社としてソフトウェア開発をしてきて分かったのは、職種を下手に増やすとろくなことにならないということです。こんな機能が欲しいとか、こんな挙動で、という話はプログラマでなくても定義できますが、実際に開発してみると初めて気づくことが多いので結局要件定義から戻ったりします。

となると、元々の要件で何を満たしたかったのか、どんな価値をユーザーに提供したかったのかをチームメンバー全員が同夢じゃないと、結局何がしたいのかよく分からないものができあがります。それだったら、プログラマが中心になって最初の要件定義から行った方がクオリティが高いものができるので、このやり方が気に入っています。

プログラミングは創造的な行為であること。仕様作成からコードを書き終えるまでの過程が相互に依存し不可分な作業であるため、1人のプログラマの権限を広げるのがうまいやり方であること。コードが設計なら、なるべく早めにコードを書き始めるべきことなどが、この本には書かれています。

# コードは変更される、よって読みやすく変更に強いコードを書く

これは経験値の問題もあるかもしれませんが、機能を開発していて後から、こことここはコードが重複しているから関数にしようと気づいて、かなりの量書いたコードを削除することがあります。

シンプルに書けるようになればそれでいいはずなのですが、あれだけ時間かけて書いたのに若干もったいないなあという気持ちになる。。

それについては、コードは無常であるということが書かれていて、なるほどですねとなりました。

ユーザーやビジネス上の要望により、ソフトウェアを変えていかないといけないことから、固執するべきではないし、コードは書いている時間よりも読んでいる（読み直す）時間の方が長いのだから、書くのに時間がかかっても読む時間が短縮できるなら元が取れる、という視点が勉強になりました。

具体的に変更に強いコード、読みやすいコードとは何か、という話は次回以降に出てきます。
deviseとcancancanで会員登録と権限管理を行い、管理者だけにrails_adminを公開する

Railsで手早くユーザー管理と権限設定、phpadmin的な管理者がデータを直接確認出来るような仕組みを入れたい時にこれが便利。

# 解説
- devise ユーザー管理（メールを送ったり、パスワードのリマインドなども可能）  
         ⇒どこのサイトでもよくある、メールアドレスで登録して、確認メールが来てっていう一連の動作がこのgemだけで作れる。
- cancancan 権限管理（モデル毎のアクセス権も細かく設定出来る）  
            ⇒deviseで作ったユーザーに権限を与えて、例えば管理者は全ての機能を使えるけど、ユーザーは全ての機能のEditしかできないって事も可能。  
indexではmodelとuserの関連付けを見て、勝手に自分に閲覧権限がある物のみを表示するっていうメッチャ便利な動きもしてくれる。
- rails_admin 管理者のデータ管理機能

# 手順

## gemのインストール
まずは必要なgemを記述して、インストールしていきます。

```ruby:Gemfile
gem 'devise'
gem 'cancancan'
gem 'rails_admin'
```
```
bundle install
```

##deviseのセットアップ
次にdeviseのセットアップをします。

```
rails g devise:install
rails g devise user
rake db:migrate
```
これでdeviseはインストールされつつ、userというモデルが作られます。
２行目でしているuserですが、このモデルとテーブルがdeviseで登録されたユーザーを管理する物になります。
別にadminでもcustomerでも何でも構いません。
今回は触れませんが、ユーザー登録画面を分けて、adminモデルとuserモデルを作るという事も可能です。

次に、取り急ぎ管理者ユーザーを追加します。
```http://<host>:3000/users/sign_up```にアクセスして、メールアドレス等入力して登録して下さい。

##cancancanのセットアップ
```
rails g cancan:ability
```

##rails_adminのセットアップ
```
rails g rails_admin:install
```
※installを行った際、パスを聞かれます。今回はデフォルトの/adminで表示させますので、そのままEnterで進みます。

次に、rails_admin.rbに以下の設定をして下さい。
コメントアウトされている物を、有効にするだけです。

```config/initializers/rails_admin.rb
  # == Devise ==
  config.authenticate_with do
    warden.authenticate! scope: :user
  end
    config.current_user_method(&:current_user)

  # == Cancan ==
  config.authorize_with :cancan
```

## adminの判定を追加
rails_adminを管理者ユーザーのみに限定する設定を入れていきます。
まずは、userテーブルにadmin_flgを追加し、このフラグがtrueのユーザーのみ管理者として扱います。

```
rails g migration AddAdminFlgToUser admin_flg:boolean
rake db:migrate
```

次に先ほど登録したユーザーを管理者に設定します。

```
rails c
> user = User.find(1)
> user.update_attribute(:admin_flg, true)
```
最後にcancancanの権限設定をします。
ability.rbに設定して下さい。

```app/models/ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    if user && user.admin_flg?
      can :access, :rails_admin
      can :manage, :all
    end
  end
end
```

cancancanの詳細はまた別途記載しますが、上記の条件の解説をすると、
ログイン済みで、admin_flgがtrueのユーザーは、全てのモデルのCRUDが行えて（can :manage, :all）、rails_adminにアクセス権限（can :access, :rails_admin）があるという感じです。


##rails_adminの確認
admin_flgがtrueのユーザーにてログイン後、```http://<host>:3000/admin```にアクセスし、以下の画面が出れば完了です。
<img width="1078" alt="SnapCrab_NoName_2016-8-12_17-46-36_No-00.png" src="https://qiita-image-store.s3.amazonaws.com/0/83221/0bd38d82-8106-d32f-16e6-1bdb862dee5e.png">

## 最後に
Railsのコーディングを行っていくと、エディターで悩む事もあると思います。
私は最初はATOMを使い、今はRubyMineを使っています。
RubyMine導入してみようと思う方、良かったら以下サイトも見てみて下さい。
[RubyMine導入方法](http://www.techbox.jp/entry/rubymine)
Fizz Buzz問題とTemplate Method パターン

#問題

Fizz Buzz問題というプログラミングの練習問題があります。番号に従い、以下のように返事をするという問題です。

|  番号i         |  返事     |
|:--------------|:-----------|
| 3かつ5の倍数  |  FizzBuzz  |
| 3の倍数       |  Fizz      |
| 5の倍数       |  Buzz      |
| 上記以外      |  i         |

返事をする人が標準タイプと江戸時代タイプいるという状況を考えます。

|  番号i        |  標準タイプ | 江戸時代タイプ     |
|:--------------|:------------|:-------------------|
| 3かつ5の倍数  |  FizzBuzz.  | FizzBuzzでござる。 |
| 3の倍数       |  Fizz.      | Fizzでござる。     |
| 5の倍数       |  Buzz.      | Buzzでござる。     |
| 上記以外      |  [i].       | [i]でござる。      |

この2人が交互にFizz Buzz問題に答えるというプログラミングの練習問題を思いつきました。

#プログラミング

一例としてTemplate Method パターンを使ったプログラミングをしてみました。

Fizz Buzz問題の条件分岐は標準タイプ、江戸時代タイプで共通です。これを考慮して基底クラスを作ります。

```java:HumanFizzBuzzBase.java
package fizzbuzz;

public abstract class HumanFizzBuzzBase {

    public void replyBasedOn(int i) {
        if (i % 3 == 0 && i % 5 == 0) {
            sayFizzBuzzCase();
        } else if (i % 3 == 0) {
            sayFizzCase();;
        } else if (i % 5 == 0) {
            sayBuzzCase();
        } else {
            sayOtherCase(i);
        }
    }

    abstract void sayFizzBuzzCase();
    abstract void sayFizzCase();
    abstract void sayBuzzCase();
    abstract void sayOtherCase(int i);


}
```

返事の出力のみを抽象メソッドにしました。

次に標準タイプ、江戸時代タイプをそれぞれ作ります。

```java:HumanFizzBuzzStandard
package fizzbuzz;

public class HumanFizzBuzzStandard extends HumanFizzBuzzBase {

    @Override
    void sayFizzBuzzCase() {
        System.out.println("FizzBuzz.");
    }

    @Override
    void sayFizzCase() {
        System.out.println("Fizz.");
    }

    @Override
    void sayBuzzCase() {
        System.out.println("Buzz.");
    }

    @Override
    void sayOtherCase(int i) {
        System.out.println(i);
    }

}
```

```HumanFizzBuzzEdo.java
package fizzbuzz;

public class HumanFizzBuzzEdo extends HumanFizzBuzzBase {

    @Override
    void sayFizzBuzzCase() {
        System.out.println("FizzBuzzでござる。");
    }

    @Override
    void sayFizzCase() {
        System.out.println("Fizzでござる。");
    }

    @Override
    void sayBuzzCase() {
        System.out.println("Buzzでござる。");
    }

    @Override
    void sayOtherCase(int i) {
        System.out.println(i + "でござる。");
    }

}
```

以下はテストプログラムです。1から30まで交互にFizz Buzz問題に答えるプログラムです。

```java:Test.java
package test;

import fizzbuzz.HumanFizzBuzzBase;
import fizzbuzz.HumanFizzBuzzEdo;
import fizzbuzz.HumanFizzBuzzStandard;

public class Test {

    public static void main(String[] args) {

        HumanFizzBuzzBase[] humanFizzBuzz = {
                new HumanFizzBuzzStandard(),
                new HumanFizzBuzzEdo()
        };

        for (int i = 1; i <= 30; i++) {
            humanFizzBuzz[ i % 2 ].replyBasedOn(i);
        }

    }

}
```

以下は出力結果です。

```:結果
1でござる。
2
Fizzでござる。
4
Buzzでござる。
Fizz.
7でござる。
8
Fizzでござる。
Buzz.
11でござる。
Fizz.
13でござる。
14
FizzBuzzでござる。
16
17でござる。
Fizz.
19でござる。
Buzz.
Fizzでござる。
22
23でござる。
Fizz.
Buzzでござる。
26
Fizzでござる。
28
29でござる。
FizzBuzz.
```
[GitHub 奮闘記] リリースの自動化

わたしが GitHub で開発している OSS のリリース自動化の忘備録。
自動化はしたものの、たまに実施する際に自動リリースって何してるんだっけ？と忘れがちなので書いておきます。

参考までにリポジトリのリンクです。

- [L.esri.WebMap](https://github.com/ynunokawa/L.esri.WebMap)

そもそも、みなさんどうやって GitHub リリースやってます？
こんなふうにやってるよーというコメントもお待ちしてます。

## リリースの自動化

npm scripts を実行すればリリースのあれやこれやをほとんどやってくれる…

```json:package.json
"scripts": {
    "release": "./scripts/release.sh"
  },
```

シェル スクリプトを作っちゃうというところがゴールですね。

リリース自動化の実体は `release.sh` というシェル スクリプトと [`gh-release`](https://www.npmjs.com/package/gh-release) という npm パッケージの組み合わせです。
依存モジュールさえインストールすればそのまま使えるのでよかったらどうぞ。

```shell-session:release.sh
# config
VERSION=$(node --eval "console.log(require('./package.json').version);")
NAME=$(node --eval "console.log(require('./package.json').name);")

# build and test
npm test || exit 1

# checkout temp branch for release
git checkout -b gh-release

# run prepublish to build files
npm run prepublish

# force add files
git add dist -f

# commit changes with a versioned commit message
git commit -m "build $VERSION"

# push commit so it exists on GitHub when we run gh-release
git push upstream gh-release

# create a ZIP archive of the dist files
zip -r $NAME-v$VERSION.zip dist

# run gh-release to create the tag and push release to github
gh-release --assets $NAME-v$VERSION.zip

# checkout master and delete release branch locally and on GitHub
git checkout master
git branch -D gh-release
git push upstream :gh-release

# publish release on NPM
npm publish
```

シェルの内容はざっとこんな感じ。

1. `# config`
    - バージョン番号とプロジェクト名の取得
2. `# build and test`
    - テスト スクリプトの実行 (Karma と mocha による簡単なテストです)
3. `# checkout temp branch for release`
    - リリース用のテンポラルなブランチ (`gh-release`) を作成＆チェックアウト
4. `# run prepublish to build files`
    - `npm prebuild` = `mkdirp dist` です
    - ビルド ファイルを配置する `dist` ディレクトリを作成
5. `# force add files`
    - `dist` ディレクトリは `.gitignore` の対象
    - 強制的に `dist` ディレクトリを含めます
6. `# commit changes with a versioned commit message`
    - ビルド ファイルをコミット
    - コミット名：`build [バージョン番号]`
7. `# push commit so it exists on GitHub when we run gh-release`
    - GitHub (リモート リポジトリ) にプッシュ
8. `# create a ZIP archive of the dist files`
    - dist ディレクトリ内のファイル群を zip 化
9. `# run gh-release to create the tag and push release to github`
    - `gh-release` コマンドで自動リリース
    - GitHub のリリース タグ作成
    - zip アーカイブのプッシュ
10. `# checkout master and delete release branch locally and on GitHub`
    - `master` ブランチにチェックアウト
    - `gh-release` ブランチの削除 (ローカルと GitHub 両方)
11. `# publish release on NPM`
    - `npm publish`

## gh-release

- [`gh-release`](https://www.npmjs.com/package/gh-release)

GitHub リリースのための npm パッケージです。

Github Releases API を使って GitHub リリースを CLI から実施できます。
しかも `CHANGELOG.md` に更新内容を記述すると、リリース内容に自動で転載してくれます。

お試しあれ～。
tensorflowの画像分類をなんとなくgopherで試す

tensorflowで画像分類を動かしてみます

gopher画像が入っているgolangを..:

    $ git clone https://go.googlesource.com/go

tensorflowのコンテナが転がっているので利用します:

    $ docker run `pwd`/go:/go -it gcr.io/tensorflow/tensorflow:latest-devel

すると、コンテナ内部で作業ができるようになります。

では、早速gopherを入れてみましょう:

> ![fiveyears.jpg](https://qiita-image-store.s3.amazonaws.com/0/30362/e54f092d-d58c-b5dd-7bd4-570d612f94f4.png)

```
# python /tensorflow/tensorflow/models/image/imagenet/classify_image.py --image_file /go/doc/gopher/fiveyears.jpg
>> Downloading inception-2015-12-05.tgz 100.0%
Succesfully downloaded inception-2015-12-05.tgz 88931400 bytes.
bib (score = 0.33395)
pencil sharpener (score = 0.11732)
handkerchief, hankie, hanky, hankey (score = 0.04763)
rubber eraser, rubber, pencil eraser (score = 0.04499)
wall clock (score = 0.04034)
```

イマイチ。もう少しわかりやすいものを入れてみると:

> ![image](https://qiita-image-store.s3.amazonaws.com/0/30362/4bf6b749-9162-8da9-fa8b-d8a92be15bc1.png)


```
# python /tensorflow/tensorflow/models/image/imagenet/classify_image.py --image_file /go/doc/gopher/appenginegophercolor.jpg
binoculars, field glasses, opera glasses (score = 0.98468)
mask (score = 0.00313)
comic book (score = 0.00256)
jigsaw puzzle (score = 0.00029)
ski mask (score = 0.00026)
```

glassesが判定できました！

入力はjpegにしておく必要があるようなので、必要に応じて`convert`で変換しておくと良さそうです。
openFrameworksで簡単にglow shaderみたいなエフェクトを作る


## はじめに
本記事はopenFrameworks初学者がglslなどを書かずに簡単な方法で
いわゆるglow shaderっぽい効果を出すことができるようになるのを目的としています
(* 多分初学者には一番簡単なのではと思ってます)
質問が多かったので記事化しました.

## 下準備
今回はとりあえずランダムにBoxを幾つか配置したものを


```cpp:ofApp.h
#include "ofMain.h"

#define NUM 500
#define BOX_SIZE 10

class ofApp : public ofBaseApp{

    
	・
	・
	・
	
	ofBoxPrimitive boxes[NUM];
};


```


```cpp:ofApp.cpp

void ofApp::setup(){

    ofSetFrameRate(60);
    ofEnableBlendMode(OF_BLENDMODE_ADD);
    
    for (int i=0; i<NUM; i++) {
        boxes[i].setPosition(ofRandom(-500,500), ofRandom(-500,500), ofRandom(-500,500));
        boxes[i].set(SIZE);
    }
    
 
}

void ofApp::draw(){

    ofBackground(0);
    
    ofPushMatrix();
    
    ofSetColor(255, 255, 255, 255);
    ofTranslate(ofGetWidth()/2, ofGetHeight()/2);
    ofRotateY(ofGetElapsedTimef());
    
    for (int i=0; i< NUM; i++) {
        boxes[i].draw();
    }
    
    ofPopMatrix();
}

```

これを実行するとこんな感じ

![スクリーンショット 2016-08-12 17.10.05.png](https://qiita-image-store.s3.amazonaws.com/0/68570/489fd421-eee1-bf4a-0b9d-db009a4dec2a.png "スクリーンショット 2016-08-12 17.10.05.png")

## Glow shaderっぽくする
ofApp.h, ofApp.cppともに以下のように書き換えます
今回使ったAddonはofxBlurのみです

```cpp:ofApp.h

#include "ofMain.h"
#include "ofxBlur.h"

#define NUM 500
#define SIZE 10

class ofApp : public ofBaseApp{

	・
	・略
	・

    ofxBlur blur;    
    ofFbo fbo;
};


```

```cpp:ofApp.cpp

void ofApp::setup(){

    ofSetFrameRate(60);
    ofEnableBlendMode(OF_BLENDMODE_ADD);
    
    for (int i=0; i<NUM; i++) {
        boxes[i].setPosition(ofRandom(-500,500), ofRandom(-500,500), ofRandom(-500,500));
        boxes[i].set(SIZE);
    }
    
    blur.setup(ofGetWidth(), ofGetHeight(), 32, .2, 1, 0.5);
    fbo.allocate(ofGetWidth(), ofGetHeight());
}


void ofApp::draw(){
    
    ofBackground(0);
    
    fbo.begin();
    ofDisableBlendMode();
    
    ofSetColor(0, 0, 0);
    ofRect(0,0, ofGetWidth(), ofGetHeight());
    
    
    //------------------------------
    //↓エフェクトかけたいやつ
    //------------------------------
    ofPushMatrix();
    
    ofSetColor(255, 255, 255, 255);
    ofTranslate(ofGetWidth()/2, ofGetHeight()/2);
    ofRotateY(ofGetElapsedTimef());
    
    for (int i=0; i< NUM; i++) {
        boxes[i].draw();
    }
    
    ofPopMatrix();
    
    //------------------------------
    //↑エフェクトかけたいやつ
    //------------------------------
    
    fbo.end();
    
    blur.begin();
    ofDisableBlendMode();
    ofBackground(0);
    fbo.draw(0,0);
    blur.end();
   
    blur.draw();
    ofEnableBlendMode(OF_BLENDMODE_ADD);
    fbo.draw(0,0);
    
    ofPushMatrix();
    ofRotateY(ofGetFrameRate());
    
    ofPopMatrix();
}


```

実行すると...
![スクリーンショット 2016-08-12 17.26.44.png](https://qiita-image-store.s3.amazonaws.com/0/68570/38ca2d39-ec29-91ea-2b1d-f5d4ce24cb87.png "スクリーンショット 2016-08-12 17.26.44.png")


かなりglowっぽい！?笑


## 終わりに
今回のキモはofxBlurとFboを併用することとAlphaBlendingの設定だと思います.
基本的にBlurとFboで挟んでやるだけで特にGLSLとか書かずにかなりglowっぽくできるので
限られた知識と時間しかない初学者や初学者に教える立場にいる人に使ってもらえればと思います  


　  
　  
　  
　
　      
     
2016/08/12
Machine Learning/Deep Learning リンク集

最近勉強中のMachine Learning/Deep Learning関連リンク。そもそも編は本などで集中的に学習したほうがいい部分も多いですが、やってみた編はたくさんのストーリーがあったほうがよいので、定期的にチェックしています。

##基礎編、そもそもDeep Learning/Machine Learningとは

ディープラーニングとは
http://www.slideshare.net/kazoo04/deep-learning-15097274

「ディープラーニング」と「機械学習」の違い
https://blog.techstars.jp/diff-machine-deep-learn-232/

深層学習（ディープラーニング）を素人向けに解説（前編）―基礎となるニューラルネットワークについて
http://stonewashersjournal.com/2015/03/05/deeplearning1/

深層学習（ディープラーニング）を素人向けに解説（後編）―特徴選びの重要性、機械はどうやって物事を理解するのか？
http://stonewashersjournal.com/2015/03/07/deeplearning2/

機械学習とディープラーニングとは　その１
https://iotnews.jp/archives/11652

機械学習とディープラーニングとは　その２
https://iotnews.jp/archives/11680

はじめるDeep Learning
http://qiita.com/icoxfog417/items/65e800c3a2094457c3a0

ニューラルネットワークと深層学習
http://nnadl-ja.github.io/nnadl_site_ja/index.html

##実装してみた

ディープラーニング（h2o.ai）で株価予測をやってみた
http://andoo.hatenablog.com/entry/deeplearning_kabu

ディープラーニング（TensorFlow）を使用した株価予想
http://qiita.com/yai/items/5ec5bbfbcc53c9770c40

ディープラーニング（TensorFlow）を使用した株価予想 ～その2～
http://qiita.com/yai/items/8c0ad280cc2f53e40256

手書き数字の機械学習に実際に画像をくわせてみた
http://qiita.com/jkkch/items/d4009fff1722a52be8dc

TensorFlowで手書き数字画像を多クラス分類 その2
http://qiita.com/jkkch/items/001ad5bfb97004cb02a7
Dでつくるbrainfu*kのインタプリタ

brainf*ckの処理系はすでにいろんな人が作っているけど勉強になりそうだったので自分で書いてみた。

```d
import std.stdio;
import std.getopt;
import core.stdc.stdio;
import std.file;
import std.conv;

const BUFFSIZE = 30000;

void main(string[] args)
{
    string filename = args[1];
    string code = readText(filename);
    size_t ptr = 0;
    size_t codeptr = 0;
    ubyte[] memory = new ubyte[BUFFSIZE];
    while(codeptr < code.length)
    {
        switch(code[codeptr])
        {
            case '+':
                memory[ptr]++;
                break;
            case '-':
                memory[ptr]--;
                break;
            case '>':
                ptr++;
                break;
            case '<':
                ptr--;
                break;
            case '.':
                putchar(memory[ptr]);
                break;
            case ',':
                int tmp = getchar();
                if(tmp == EOF) return;
                memory[ptr] = tmp.to!ubyte;
                break;
            case '[':
                if(memory[ptr] == 0)
                {
                    int loopnest = 1;
                    do
                    {
                        codeptr++;
                        if(code[codeptr] == '[') loopnest++;
                        if(code[codeptr] == ']') loopnest--;
                    }while(0 < loopnest);
                }
                break;
            case ']':
                if(memory[ptr] != 0)
                {
                    int loopnest = 1;
                    do
                    {
                        codeptr--;
                        if(code[codeptr] == '[') loopnest--;
                        if(code[codeptr] == ']') loopnest++;
                    }while(0 < loopnest);
                }
                break;
            default:
        }
        codeptr++;
    }
}
```

getchar/putcharは何で置き換えればいいんだろうか？

[マンデルブロー集合を描かせて](http://esoteric.sange.fi/brainfuck/utils/mandelbrot/)時間計測。

```console
$ time ./kbfi mandelbrot.b
real	1m25.554s
user	1m25.464s
sys	0m0.044s

real	1m25.144s
user	1m25.104s
sys	0m0.004s

real	1m25.659s
user	1m25.640s
sys	0m0.000s

$ time bf mandelbrot.b
real	0m8.909s
user	0m8.888s
sys	0m0.012s

real	0m9.066s
user	0m9.048s
sys	0m0.004s

real	0m8.966s
user	0m8.952s
sys	0m0.008s
```

遅いのでこれから速くしていきたい。
xlsmapperをちょっとだけ触ってみた

# これは何
[xlsmapper](http://mygreen.github.io/xlsmapper/sphinx/index.html)を知ったのでちょっと触ってみたメモ書き

# 試した環境
- Java8(jdk1.8.0_102)
- XlsMapper(1.4.4)
- eclipse

# 環境構築
[ここ](http://mygreen.github.io/xlsmapper/sphinx/howtouse.html)に書いてある通りやれば出来る。

# 試した内容
現時点で欲しかったのはExcelファイルを読み込む方だったので、ファイル読み込みのみ。

## Javaコード
### PojoSheet.java
```java
import com.gh.mygreen.xlsmapper.annotation.LabelledCellType;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCell;
import com.gh.mygreen.xlsmapper.annotation.XlsSheet;

@XlsSheet(name="Sheet1")
public class PojoSheet {

	@XlsLabelledCell(label="midashi1", type=LabelledCellType.Bottom)
	String cell1;
	@XlsLabelledCell(label="midashi2", type=LabelledCellType.Bottom)
	String cell2;
	@XlsLabelledCell(label="midashi3", type=LabelledCellType.Bottom)
	String cell3;
	@XlsLabelledCell(label="midashi4", type=LabelledCellType.Bottom)
	String cell4;
	@XlsLabelledCell(label="midashi5", type=LabelledCellType.Bottom)
	String cell5;
	
}
```

### Test.java(Mainクラス)
```java
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import com.gh.mygreen.xlsmapper.XlsMapper;
import com.gh.mygreen.xlsmapper.XlsMapperException;

public class Test {
	
	private static final String xlsxFileAddress = "G:\\work\\Test.xlsx";


	public static void main(String[] args) throws FileNotFoundException, XlsMapperException {

		XlsMapper xlsMapper = new XlsMapper();
		Object[] sheets = xlsMapper.loadMultiple(
			    new FileInputStream(xlsxFileAddress),                  // 読み込むExcelファイル
			    new Class[]{PojoSheet.class}  // アノテーションを付与したクラス。
			    );
		
		
		for(Object obj : sheets) {
			
			PojoSheet s = (PojoSheet)obj;
			System.out.println(s.cell1 + ", " + s.cell2 + ", " + s.cell3 + ", " + s.cell4 + ", " + s.cell5);
			
		}
		
	}

}
```

## テストしたExcelファイル
![excel2.PNG](https://qiita-image-store.s3.amazonaws.com/0/77910/843750a6-c8aa-6652-1c66-d0e00f63353f.png)

## 処理結果
### Excelファイルの内容とJavaコードの組み合わせが正しいとき
```
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Cell1, Cell2, Cell3, null, Cell5
```

### Excelファイルの内容とJavaコードの組み合わせが正しくないとき（見出しの文言が違うとか）
見出しが一致する項目が無いよ、とエラーを吐いてくれる。

```
Exception in thread "main" com.gh.mygreen.xlsmapper.fieldprocessor.CellNotFoundException: Cell 'midashi5' not found in sheet 'Sheet1'
	at com.gh.mygreen.xlsmapper.Utils.getCell(Utils.java:1064)
	at com.gh.mygreen.xlsmapper.Utils.getCell(Utils.java:1031)
：
```

# まとめ
## 良さげなところ
- 表形式のExcelを読み込んで処理したい、という用途であれば、見出しを定義することで読み込みが容易に出来そう。
- 表のレイアウトが変わって、見出しは変わらないが、位置が変わったというような場合も対応可能に読める。
- 普通にApache POIを呼び出すよりはコードがかなりシンプルに書ける。

## 懸念事項
- ベースとなっているのはApache POIなので、大容量のExcelファイルを読み込むと恐らくOutOfMemoryErrorを吐くのではないか（要検証）
- 大容量のファイル書き込みも同様に、遅くなる可能性があるのではないか…。
Python初心者がRaspberry Piで開閉連動カメラ

title:防犯Pi
date:2016-08-12
category:raspberry pi
tags:raspberry pi,python

はじめまして。Niohです。
はじめてのPython、そしてはじめての電子工作をしてみました。。

###作る理由
---
当社が零細企業ですので現在レジ開閉した人が自己申告制となっています。
幸い現在現金過不足は出ていないものの、やはり人が見ていない時などは不安・・

ということでレジ開閉連動のカメラを作りたいと思っていました。

###なぜRaspberry Piなのか
---
今回開閉連動カメラを作るにあたって必要な機能が

- 撮影した写真をSlackに掲載したい
- 開閉を検知したい（GPIO使用）
- 母艦のレジと連動させるのとかわかるわけない・・

だったので作例がたくさんあるRaspberry Piを使用しました。

###まずは知識を仕入れる
---

実はPythonなどというものすらさっぱりわからなかったので[python-izm](http://www.python-izm.com)というページで勉強しました。
後はググった。


###必要なもの
---
- Raspberry Pi本体
- SDカード(16GB)
- [LOGICOOL ウェブカム HD画質 120万画素 C270 ](https://www.amazon.co.jp/gp/product/B003YUB660/)
- [エーモン 開閉連動スイッチ 1588 ](https://www.amazon.co.jp/gp/product/B004WRGJKW/)
- ブレッドボード、ジャンパワイヤ、抵抗(1kΩ?よくわからん)

###原理
---
1.ドアが開く
2.開閉検知スイッチがONになる
3.ONになって2秒したらウェブカメラで撮影する
4.撮影した画像をSlackに投稿する

このような形で出来ればなあと思った。


###前提となるアプリ等のインストール
---
- Piのアップデート
```
sudo apt-get update
sudo apt-get upgrade
```
- RPi.GPIOのインストール
```
sudo pip install rpi.gpio
```
- fswebcamのインストール
```
sudo apt-get install fswebcam
```
- slackerのインストール
```
sudo pip install slacker
```

###配線
---
今回はGPIO2を使用する。
![回路図](https://66.media.tumblr.com/68c94114d7bf0b999c611d5f45ed6724/tumblr_obsz1uDsFC1u3y1oio1_540.jpg)


###Slackerの設定
---
[はじめてのRaspberry PIで監視カメラを作ってみた。](http://qiita.com/kinpira/items/bf1df2c1983ba79ba455)
にSlackerの設定の項目があるのでそこを読んで設定する。TokenとChannelのIDがわかればOK
対話型でPythonを起動し、それをコピペするのがよい。

###保存用ディレクトリの作成
---
保存用に適当なディレクトリを作成する
```
sudo mkdir /home/pi/camera
```

###スクリプトを記述する
---
適当なエディタで適当な名前で開いてこれをコピペしてutf-8で保存する。
僕はAtomEditorってやつを使ってみました。


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

#必要なライブラリーの読み込み
import RPi.GPIO as GPIO
from slacker import Slacker
import subprocess
import datetime
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(2,GPIO.IN)

def camcapslack():

    #１ウェブカムで写真を撮って保存する
    today = datetime.datetime.today()
    now =  today.strftime("%Y%m%d%H%M")
    cmd = "fswebcam [保存したいディレクトリ(/home/pi/camera/等)]%s.jpg" % now
    jpgdir = "[保存したいディレクトリ(/home/pi/camera/等)]%s.jpg" % now
    bolean = subprocess.call(cmd, shell=True)
    if bolean == 0:
        pass
    else:
        subprocess.call(cmd,shell=True)

#撮った写真をSlackに投稿する

    token = "[TokenのID]"
    slacker = Slacker(token)
    channel = '[channelのID]'
    result = slacker.files.upload(jpgdir,channels=['[channelのID]'])
    slacker.pins.add(channel='[channelのID]',file_=result.body['file']['id'])

while True:

    flag_GPIO = GPIO.input(2)

    if flag_GPIO == 0:
        time.sleep(2)
        camcapslack()

GPIO.cleaup()


```


後は起動時に登録して再起動するだけ。こちらは後ほど記述するかも。

###今後追加したい機能
---
- SDカードの保護(PiのRAMを一時的に利用し、撮影が終わったら画像を削除する)
- 保存に失敗した時の試行回数(現在は1回以上はやり方がわからなかったので。)
- 動画のほうがいいか否かを考える。


###最後に
---
正直初めてPythonというかプログラミング言語自体触れたのでこのスクリプトの意味を全部わかっているかというと**わかりません**

Atom Editorも初めてですしMarkdown記法も学びながら書いています。

今のスクリプトもぐぐったりコピペしたりしたのを自分なりに直しながら作りました。

もっとこうした方がわかりやすいとか、速いとかのご指摘を頂ければと思ってQiitaに投稿をさせていただきましたので、もしよろしければ色々ご指摘いただけると幸いです。


ありがとうございました。
Laravel5.2 日付Validationのフォーマット

## Laravel5.2 日付Validationのフォーマットについて
・YYYY/MM/DDを設定したい
・HH:MMも設定したい

## Validation設定方法
YYYY/MM/DDおよびHH:MMをValidationに設定したい場合、フォーマットの指定は以下のコードになる。

```php:controller.php
    $validator = Validator::make($request->all(), [
        'date' => 'date_format:Y/m/d',   /* 「y/m/d」ではない。*/
        'time' => 'date_format:H:i',     /* 「H:M」ではない*/
    ]);
```


## 参考記事
[Laravel 5.1 date_format validation allow two formats](http://stackoverflow.com/questions/32006092/laravel-5-1-date-format-validation-allow-two-formats "stack overflow")
タップエリアを広げる(extension版)

UIButtonを継承して`pointInside`を上書きするというやり方を知っていたんだけど、いちいち継承しないといけなくてダルいなぁと思っていたのでちょっと頑張ってみた。

```swift
import UIKit
import ObjectiveC

extension UIButton {
  private struct AssociatedKey {
    static var tappableInsets = UInt()
  }
  
  var tappableInsets: UIEdgeInsets {
    get {
      let value = objc_getAssociatedObject(self, &AssociatedKey.tappableInsets) as? NSValue
      return value?.UIEdgeInsetsValue() ?? UIEdgeInsetsZero
    }
    
    set {
      objc_setAssociatedObject(self, &AssociatedKey.tappableInsets, NSValue(UIEdgeInsets: newValue), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
  }
  
  override public func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
    let insets = tappableInsets
    
    var rect = bounds
    rect.origin.x -= insets.left
    rect.origin.y -= insets.top
    rect.size.width += (insets.left + insets.right)
    rect.size.height += (insets.top + insets.bottom)
    return CGRectContainsPoint(rect, point)
  }
}
```

黒魔術…。
UnityでCSVを読み込むときの軽いメモ

Unityで音ゲーを作っていますが、その譜面としてCSVを使っています。
その読み込み方法の個人的なメモです。

前提として、Assets/Resources/CSV下に.csvファイルを配置。

```c#:コード
private string musicName; // 読み込む譜面の名前
private string level; // 難易度
private TextAsset csvFile; // CSVファイル
private List<string[]> csvDatas = new List<string[]>(); // CSVの中身を入れるリスト
private int height = 0; // CSVの行数

void Start(){
  musicName = "sample"; // 曲名
  level = "0"; // 難易度
  csvFile = Resources.Load("CSV/" + musicName + level) as TextAsset; /* Resouces/CSV下のCSV読み込み */
  StringReader reader = new StringReader(csvFile.text);

  while(reader.Peek() > -1) {
    string line = reader.ReadLine();
    csvDatas.Add(line.Split(',')); // リストに入れる
    height++; // 行数加算
  }

}
```
この例では、sample0.csvを読み込み。
将来的に sample0.csv、sample1.csvのように数字で難易度を管理したい。
Resources.LoadでResourcesフォルダ内を探してくれる（？）
CSVを読み込むときに、拡張子(.csv)は書かなくていいみたい。
あとは、

```
Debug.Log(csvDatas[0][0]);
```
あたりで、ちゃんと読み込めているか確認すればOK
Nodebrewを使ってNode.jsを超高速にインストールする方法

Node.jsのインストールって、コンパイルに時間がかかりますよね。
その度に、イライラしている方もいるのではないでしょうか。
今回は、**Node.jsを超高速でインストールできる方法**を紹介します。

この方法を使うと、インストール時間が1秒以下になります（マシンスペック&ネットワークに依存しますが・・・）


# 検証環境
検証環境はVagrantを使っています。
OSとスペックは以下の通りです。

```sh:centos
# OS
$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

# memory
$ cat /proc/meminfo | grep Total
MemTotal:        1884064 kB

# core数
$ cat /proc/cpuinfo | grep "processor" | wc -l
2
```

## 事前準備
nodebrewをインストールする。

```
$ curl -L git.io/nodebrew | perl - setup
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc
$ source ~/.bashrc
```

# インストール方法
今回は3種類のインストール方法を比較します。

* 通常のインストール（コンパイルあり）
* バイナリファイルからインストール（コンパイルなし）
* バイナリファイルのインストールを並列化（コンパイルなし）

通常のインストールではコンパイルを行い、`install-binary`を使うとコンパイルを行いません。

```sh:3種類のインストール方法
# 通常のインストール
$ nodebrew install <version>

# install-binaryを使ってインストール
$ nodebrew install-binary <version>
```
では、実際にどのくらい時間差が出るか比較をしてみましょう。


# 比較結果
| インストール方法      | インストール時間|
:-----------------|------------------:|
| `nodebrew install v4.4.3`             |              15分6秒 | 
| `nodebrew install-binary v4.4.3`           |            46秒 | 

※ 上記のコマンドが実行完了するまでの時間です。（`nodebrew use <version>`の時間は除いています）

# インストールが完了したら・・・
忘れずにnodeのバージョンを指定しましょう。

```sh:nodeのバージョンを指定する
$ nodebrew use v4.4.3
```
これで超高速で、nodeを使えるようになりました！

# まとめ
binary fileを使うだけで実行時間がが15分の１に。

これは、使わないわけにいかないですね・・・！（速すぎて驚きが隠せません）
「オフラインリアルタイムどう書く第2回(Bit Tetris)」の問題を解いてみた


[横浜へなちょこプログラミング勉強会](https://yhpg.doorkeeper.jp/)にて過去に出題された[Bit Tetris](http://nabetani.sakura.ne.jp/hena/ord2/)を解いてみた。
回答にかかった時間はおよそ40分前後。

解き始めてしばらく入力値から図解の状態になる意味が理解できず、数分間問題文とにらめっこしてしまった。
理解できればあとはすんなりと進んだが、問題文を理解するのに時間をかけてしまうのはプログラミング以前の問題である...。

```ruby
class BitTetris
  def initialize
    @lines = []
  end

  def draw input
    input.split("-").each do |hex|
      n = hex.hex
      @lines.push 8.times.map{|i| n[i]}
    end
  end

  def erase
    7.downto(0) do |i|
      if @lines.all?{|line| line[i] === 1}
        @lines.size.times.each do |n|
          @lines[n].delete_at i
          @lines[n].push 0
        end
      end
    end
  end

  def output
    @lines.map{|line|
      "00#{line.reverse.join.to_i(2).to_s(16)}"[-2..-1]
    }.join("-")
  end
end

test = <<_TEST
/* 0*/ {"ff-2f-23-f3-77-7f-3b", "1f-03-00-1c-0d-0f-06" },
/* 1*/ {"01", "00" },
/* 2*/ {"00", "00" },
/* 3*/ {"7a-4e", "0c-02" },
/* 4*/ {"56-b6", "08-14" },
/* 5*/ {"12-12-12", "00-00-00" },
/* 6*/ {"de-ff-7b", "0a-0f-05" },
/* 7*/ {"95-be-d0", "05-1e-20" },
/* 8*/ {"7c-b0-bb", "1c-20-2b" },
/* 9*/ {"7a-b6-31-6a", "3a-56-11-2a" },
/*10*/ {"32-0e-23-82", "18-06-11-40" },
/*11*/ {"ff-7f-bf-df-ef", "0f-07-0b-0d-0e" },
/*12*/ {"75-df-dc-6e-42", "35-5f-5c-2e-02" },
/*13*/ {"62-51-ef-c7-f8", "22-11-6f-47-78" },
/*14*/ {"0c-47-8e-dd-5d-17", "04-23-46-6d-2d-0b" },
/*15*/ {"aa-58-5b-6d-9f-1f", "52-28-2b-35-4f-0f" },
/*16*/ {"ff-55-d5-75-5d-57", "0f-00-08-04-02-01" },
/*17*/ {"fe-fd-fb-f7-ef-df-bf", "7e-7d-7b-77-6f-5f-3f" },
/*18*/ {"fd-fb-f7-ef-df-bf-7f", "7e-7d-7b-77-6f-5f-3f" },
/*19*/ {"d9-15-b5-d7-1b-9f-de", "69-05-55-67-0b-4f-6e" },
/*20*/ {"38-15-fd-50-10-96-ba", "18-05-7d-20-00-46-5a" },
/*21*/ {"fe-fd-fb-f7-ef-df-bf-7f", "fe-fd-fb-f7-ef-df-bf-7f" },
_TEST

require 'minitest/autorun'

describe 'BitTetris' do
  test.split("\n").each do |line|
    t, n, input, expect = line.match(/^\/\*\s*(\d+)\*\/\s{"([^"]+)",\s"([^"]+)"\s},$/).to_a
    it input do
      game = BitTetris.new
      game.draw input
      game.erase
      assert_equal game.output, expect
    end
  end
end
```
ELBがApplication層で動くようになったらしい

AWSのELBが、Application層でのロードバランシングに対応したらしいです。
Application層で動くロードバランサーということで、ALBと呼ぶらしいです。


# Application層で動作するロードバランサー
通信機能を7つの階層に分割するOSI参照モデル(物理層、データリンク層・・・などに分割するモデル)の最上層であるアプリケーション層で動作するロードバランサーです。

アプリケーション層で動作するため、この層で使われているHTTPというプロトコル等をもとに負荷分散をすることが可能になったようです。

現状(2016/08)のALBはHTTPリクエストのURLを用いてバランシングすることができます。

# ELBでできなかったことと、ALBでできるようになること
ELBは通信を受け、処理を自身の配下のインスタンスに振り分けるという働きをしてくれていました。この際に、全ての処理を同一グループのインスタンスに負荷を分散しながら振り分けるというのがELBの挙動になります。

一方で、ALBではリクエストのURLに基づいて処理を割り振るグループを選択することができるようになります。

例えば`http://example.com/*`へのアクセスはデフォルトでGroup1に振り分けつつ、`http://example.com/fuga`へのアクセスのみGroup2に割り振るといったことが可能になります。

# 利点
これにより、より粒度の小さいサービスの組み合わせによるサービスの提供が可能になります。

例えば、ユーザーというドメインをCRUDするようなアプリケーションがあったとします。

`http://example.com/user/create`でユーザーを作成し、`http://example.com/user/delete/{id}`でユーザーを削除することができるとします。

ELBでは、ユーザーのCRUD機能を全て実装したサーバーをグループに入れておいて、`http://example.com/`へのリクエストを各グループに負荷分散して処理を振り分けていました。

これがALBではユーザーのCRUD機能をモノリシックに用意する必要がなくなります。

CreateやDeleteなど機能を単体で用意しておき、それらをGroup1とGroup2にそれぞれ格納します。
そして、`http://example.com/user/create`への通信はGroup1に処理を振り分け、`http://example.com/user/delete/{id}`への通信はGroup2に処理を振り分ければいいわけです。

これによって、よりマイクロなサービスの組み合わせでサービス全体を提供することが可能になるわけです。


# ALBを使う上で気をつけたいこと
## deployの話
アプリケーションのdeploy周りについては考える必要が出てくる気がします。

ELBを使っていた場合はユーザーのCRUD機能が一枚岩で提供されていたので、deploy時にはまるっと入れ替えることができました。

これがALBを使っている場合はCreate機能やUpdate機能が分割できてしまうので、新旧を無停止で入れ替えようとするとタイムラグが起きて問題になる気がします。

今回は例を示す際にユーザーのCRUD機能をあげましたが、分割の単位はドメインごとに切るなりなんなり、サービスにあった切り口を考える必要があるでしょう。

## 可用性の話
各グループにそれぞれ別の責務を負わせるわけで、それぞれのグループで可用性を確保する必要があると思われます。複数AZで各グループ用のインスタンスを起動してあげる必要があるでしょう。
結構構成が煩雑になりそうなので、CloudFormationによるコード化はしておいたほうがいいかもしれません。

CloudFormationにはすでにALBも対応しているようで、`AWS::ElasticLoadBalancingV2::LoadBalancer`というようにElasticLoadBalancingV2ってやつを使ってあげればいいみたいです。
NSDateの比較を演算子を利用できるようにして楽する


NSDate同士の比較は結構面倒な記述になる。

```swift
let a = NSDate(), b = NSDate()
a.compare(b) == .OrderedAscending
```

しかもこれを見て、a < bなのかa > bなのか分かりづらい。
比較演算子を利用できるようにするとこれらの問題が解決する。

## 演算子のみの実装

```swift
public func <(a: NSDate, b: NSDate) -> Bool {
	return a.compare(b) == .OrderedAscending
}

public func ==(a: NSDate, b: NSDate) -> Bool {
	return a.compare(b) == .OrderedSame
}

public func >(a: NSDate, b: NSDate) -> Bool {
	return a.compare(b) == .OrderedDescending
}

public func <=(a: NSDate, b: NSDate) -> Bool {
	return a < b || a == b
}

public func >=(a: NSDate, b: NSDate) -> Bool {
	return a > b || a == b
}
```

これらを定義すると比較演算子が利用できるようになるので、直感的に記述することができる。

```swift
let currentDate: NSDate
let objectDate: NSDate

// before
if currentDate.compare(objectDate) == .OrderedAscending {
	print("alert object")
}

// after
if objectDate < currentDate {
	print("alert object")
}
```


## Comparableに準拠させた実装

es_kumagaiさんのコメントを踏まえて。

`Comparable`プロトコルに準拠することで、演算子の定義を`<`と`==`のみで終わらせることができる。

```swift
extension NSDate: Comparable {}

public func <(a: NSDate, b: NSDate) -> Bool {
	return a.compare(b) == .OrderedAscending
}

public func ==(a: NSDate, b: NSDate) -> Bool {
	return a.compare(b) == .OrderedSame
}
```

この実装にすると更に良いことについては、コメントより抜粋。

> こうしたときに面白いのが、他の Equatable を想定した機能を NSDate でも使えるようになるところです。
> 例えば Swift の配列 Array<Element> は、Element が比較可能なときに indexOf(_:) メソッドが使えるようになるのですけど、上のように NSDate を Comparable にしておくと、Array<NSDate> のときにもこれが使えるようになります。
Bash on Debian on Windows（中途）

普段使いのPCがDebianなので、WindowsのUbuntuをDebianにする。
aptの依存関係解決能力を信じて、強引にディストリビューションを変更する。
※ Emacsが立ち上がらないので、何か不都合があるっぽい。ubuntu由来のパッケージを全部置き換えただけではダメなのかもわからんね…。


sources.listをDebian jessie に変更。

```
#deb http://archive.ubuntu.com/ubuntu trusty main restricted universe multiverse
#deb http://archive.ubuntu.com/ubuntu trusty-updates main restricted universe multiverse
#deb http://security.ubuntu.com/ubuntu trusty-security main restricted universe multiverse

deb http://ftp.jp.debian.org/debian/ jessie main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ jessie main contrib non-free
deb http://security.debian.org/ jessie/updates main contrib non-free
deb-src http://security.debian.org/ jessie/updates main contrib non-free
deb http://ftp.jp.debian.org/debian/ jessie-updates main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ jessie-updates main contrib non-free
```


定石通りにまずupdate -> upgrade。

```
apt-get update
apt-get install debian-archive-keyring
apt-get update
apt-get upgrade
```

fuseはカーネル関連の設定をしようとしてエラーになるのでファイルを削除。


```
rm /var/lib/dpkg/info/fuse.postinst
dpkg --configure fuse
```

昔のDebianのようにaptを先に更新。

```
dpkg-reconfigure locales

aptitude install apt # n -> y
```
gccとlibgcc1をダウングレード。


aptitudeとperlを更新。
perlは依存関係が大量なので念のため先に入れる。

```
apt-get install aptitude
apt-get install perl
```

```
apt-get dist-upgrade
apt-get install
apt-get dist-upgrade
apt-get install
...
apt-get remove --purge plymouth
apt-get dist-upgrade
apt-get remove --purge init
apt-get dist-upgrade
apt-get remove --purge exim4-base
apt-get dist-upgrade

apt-get autorimove --purge
```

設定ファイルは古いものを残す。
エラーが出るけど強引に進める。initパッケージを消しちゃってるけども、docしかないし利用されないので今のところ特に問題はない。


/mnt/c が見えなくなってるのはbashを立ち上げ直すと見えるようになる。
おそらくfuseのntfsがアップグレード時に一度停止したため？


あとはダウングレードするようにPinのPriorityを1001以上に設定。

```
# /etc/apt/preferences.d/debian

Package: *
Pin: release a=stable
Pin-Priority: 1010
```

ダウングレード実行。

```
apt-get update
apt-get dist-upgrade

apt-get remove --purge `dpkg -l|grep ubuntu |awk '{print $2}'`

rm /var/lib/dpkg/info/pollinate.*rm
apt-get remove --purge pollinate

rm /etc/apt/preferences.d/debian
```

これで完了。

rpm系は詳しくないからやらないけど、がんばればCentOSとかにも置き換え可能な気がする。



補足：
壊れてどうしようもなくなったら管理者モードのcmd.exeで再インストール。

```
lxrun /uninstall /full
lxrun /install
```

参考：
http://qiita.com/Aruneko/items/c79810b0b015bebf30bb
http://engetu21.hatenablog.com/entry/2014/12/06/004525
iphoneの「ホーム画面に追加」の画像を固定したい....！

# 「ホーム画面に追加」の画像は、何も指定しなかったらiosくんが結構適当に選んでしまう

そもそもホーム画面に追加」の画像を固定するにはいくつかの決まりがあって

###1. 画像の名前
<b>apple-touch-icon.png</b>
である必要があります！
これは拡張子まで一緒で、例えば
<b>apple-touch-icon.jpeg</b>
とかだと動きません。。。。
めんどくさい
さらに大きさも`144px　× 144px` でないといけません

###2. ディレクトリ構成
作りたいwebサイトのrootディレクトリ配下でアクセスできる必要があります
つまり、 `http://example.com/apple-touch-icon.png`
でアクセスできる必要があります

##Railsでやると....
これがちょっと厄介でRailsではアセットコンパイルというjsや画像などはコンパイルして軽くする、といった手法が取られていて、例えば
`image_url`や `image_tag` で画像をとるとコンパイルされためちゃめちゃな文字列の名前になってしまいます。。。
これでは、 `apple-touch-icon.png`という名前である、という条件が満たされないことと、さらに `asset/`からのディレクトリ名になってしまったりと、いろいろ満たしきれなくなってしまいます


#結果
public配下に `apple-touch-icon.png`を `144px　× 144px`でおいて

```haml:application.html.haml
%link{:href => "apple-touch-icon.png", :rel => "apple-touch-icon"}
```
と書けば、うまくいきます
Pythonは大人の言語

Python言語をオブジェクト指向の観点からみたとき、クラスメンバのprivateアクセスを強制する（クラス外部から隠蔽する）言語機能が存在しない。慣習的にメンバ名先頭にアンダースコア(`_`)を1つまたは2つ付けることで、それがprivate／外部からアクセスしてはいけないことを表明するが、それらのアクセスを完全に禁止することはできない。

> "We are all (consenting) adults here"
> -- Guido van Rossum氏（[Python言語の作者](https://www.python.org/~guido/)）もしくはPythonコミュニティー

```py
class Person:

  # プライベート関数（_が1個）
  def _privateFun(self):
    print("private!")

  # プライベート関数（_が2個）
  def __morePrivateFun(self):
    print("secret!")


target = Person()

target._privateFun()   # OK

target.__morePrivateFun()         # これはNGだが
target._Person__morePrivateFun()  # OK
```
VagrantとCoreOSでkubernetesをMacで使ってみる　②サンプル実行編

ここでは、構築した環境でKubernetesのサンプルの中でも標準的なguestbookというサンプルを実行してみたいと思います。
作業の前にあらかじめkubernetesのフォルダの中に移動しておいてください。

```bash
$ cd kubernetes
```

###①Redis Masterの追加

```bash
$ kubectl create -f examples/guestbook/legacy/redis-master-controller.yaml
replicationcontroller "redis-master-controller" created
$ kubectl create -f examples/guestbook/redis-master-service.yaml
service "redis-master" created
```

###②Redis Slaveの追加

```bash
$ kubectl create -f create -f examples/guestbook/legacy/redis-slave-controller.yaml
replicationcontroller "redis-slave" created
$ kubectl create -f examples/guestbook/redis-slave-service.yaml
service "redis-slave" created
```

###③Frontend-serviceの設定を修正する
Macのブラウザからアクセスできるようにフロントエンドの設定を変えます。
Vimでなくても大丈夫です。

```bash
$ vi examples/guestbook/frontend-service.yaml
# 下記のように2行追加する
apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    name: frontend
spec:
  # if your cluster supports it, uncomment the following to automatically create
  # an external load-balanced IP for the frontend service.
  # type: LoadBalancer
  type: NodePort # この行追加
  ports:
    # the port that this service should serve on
    - port: 80
      nodePort: 30301 # この行追加
  selector:
    name: frontend
```

###④Frontendの追加

先にMacのFireWallをOffにしてください。

```bash
$ kubectl create -f examples/guestbook/legacy/frontend-controller.yaml
replicationcontroller "frontend" created
You have exposed your service on an external port on all nodes in your
cluster.  If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:30301) to serve traffic.

See http://releases.k8s.io/release-1.1/docs/user-guide/services-firewalls.md for more details.
$ kubectl create -f examples/guestbook/frontend-service.yaml
service "frontend" created
```

###⑤動作させる
Nodeのアドレスを探します。

```bash
$ kubectl get nodes
NAME           STATUS    AGE
172.17.8.102   Ready     1d
172.17.8.103   Ready     1d
```

ここでは1番目のnodeである172.17.8.102がアクセス先になります。これにFrontendに追加したポート番号を付加した（ここでは３０３０１番）「172.17.8.102:30301」にアクセスします。

###guestbookの画面が出てできたら実際に試してみてください、お疲れさまでした！

**[環境構築編はこちら](http://qiita.com/Clip-glass/items/1eb61f983a69f22ac8e3)**
UEFI 情報まとめ

個人的リンクまとめ。(日本語情報は [ArchWiki](https://wiki.archlinuxjp.org/index.php/Unified_Extensible_Firmware_Interface) あたりが詳しいです)

# 参考リンク
## 公式 (UEFI Forum)
[Specifications | Unified Extensible Firmware Interface Forum](http://uefi.org/specifications)


## Wiki
[Unified Extensible Firmware Interface - ArchWiki](https://wiki.archlinuxjp.org/index.php/Unified_Extensible_Firmware_Interface)
[EFI Shells and Scripting | Intel® Software](https://software.intel.com/en-us/articles/efi-shells-and-scripting/)

## その他
[mount - USB drive not detected in Intel EFI shell - Server Fault](http://serverfault.com/questions/569972/usb-drive-not-detected-in-intel-efi-shell)

# コマンド

| command | 説明 |
|:----------------------|:------------------|
| mount `<device name>` | デバイスをマウント  |
| `<device name>`:      | デバイスに移動      |
| cd `<dirname>`        | ディレクトリを移動  |
ChainerでcPickle.UnpicklingError


Chainerを使うために幾つかサイトを参考にしていました．

- [PFN発のディープラーニングフレームワークchainerで画像分類をするよ(chainerでニューラルネット1)](http://hi-king.hatenablog.com/entry/2015/06/11/021144)

- [ChainerのNINで自分の画像セットを深層学習させて認識させる](http://d.hatena.ne.jp/shi3z/20150709/1436397615)

ところが，自前の画像を学習するためにtrain_imagenet.pyを実行すると，以下のようなエラーが発生しました．

```py:エラー
cPickle.UnpicklingError: invalid load key, 
```

該当箇所は↓のコードのpickle.loadという関数による非Pickle化処理

```py:train_imagenet.py
# Prepare dataset
train_list = load_image_list(args.train, args.root)
val_list = load_image_list(args.val, args.root)
mean_image = pickle.load(open(args.mean, 'rb'))
```

引数のargs.meanの値はmean.npyというファイルなので，このファイルの出処を探してみると...

```py:compute_mean.py
#!/usr/bin/env python
import argparse
import os
import sys

import numpy
from PIL import Image
import six.moves.cPickle as pickle


parser = argparse.ArgumentParser(description='Compute images mean array')
parser.add_argument('dataset', help='Path to training image-label list file')
parser.add_argument('--root', '-r', default='.',
                    help='Root directory path of image files')
parser.add_argument('--output', '-o', default='mean.npy',
                    help='path to output mean array')
args = parser.parse_args()

sum_image = None
count = 0
for line in open(args.dataset):
    filepath = os.path.join(args.root, line.strip().split()[0])
    image = numpy.asarray(Image.open(filepath)).transpose(2, 0, 1)
    if sum_image is None:
        sum_image = numpy.ndarray(image.shape, dtype=numpy.float32)
        sum_image[:] = image
    else:
        sum_image += image
    count += 1
    sys.stderr.write('\r{}'.format(count))
    sys.stderr.flush()

sys.stderr.write('\n')

mean = sum_image / count
pickle.dump(mean, open(args.output, 'wb'), -1)
```

numpy.ndarray関数で生成したオブジェクトを，pickle.dump関数でmean.npyというファイルに出力しているようです．
つまり，mean.npyの実体はNumPy配列のバイトストリームのようです．

なので，train_imagenet.pyでmean.npyを非Pickle化して読み込むのではなく，NumPy配列として読み込むように修正しました．

```py:train_imagenet.py
# Prepare dataset
train_list = load_image_list(args.train, args.root)
val_list = load_image_list(args.val, args.root)
# mean_image = pickle.load(open(args.mean, 'rb')) ←非Pickle化して読み込むとcPickle.UnpicklingError
mean_image = np.load(args.mean) # NumPy配列として読み込む
```

するとなんとか読み込めました．
【またNokogiriか】Nokogiri 1.6.8がMacでインストールできない【なぜそれで直るし】

# TL;DR

`brew unlink xz`で直った。

# 概要

意気揚々とRailsをインストールしようとしたら、**また**Nokogiriがインストールできないで死んだ。
で、調べてみるとこんなissueが。
https://github.com/sparklemotion/nokogiri/issues/1483
`brew unlink xz`するとインストールできるようになるとのこと。
騙されたつもりで試してみたら本当にインストールできてしまった…なぜだ？
ちなみに、`xcode-select --install`でも直るらしい…なぜだ？？

# ぼやき

RailsからNokogiriへの依存が消えるのはいつの日なのだろうか…