OmniAICreator/Qiita-1.07M huggingface dataset:
MacでC#のソリューションをビルド


## 概要

今回ビルドしたのはこれ。

https://github.com/sta/websocket-sharp

## 前準備

monoのインストール

```
brew install mono
```

## xbuildでビルド（エラー編）

```
$ xbuild websocket-sharp.sln                                                       XBuild Engine Version 12.0
Mono, Version 4.2.0.0
Copyright (C) 2005-2013 Various Mono authors

Build started 2015/12/13 0:28:13.
__________________________________________________
:  warning : Default tasks file /usr/local/Cellar/mono/4.2.0.179/lib/mono/3.5/Microsoft.Common.tasks not found, ignoring.
:  warning : Could not find project file /usr/local/Cellar/mono/4.2.0.179/lib/mono/3.5/Microsoft.CSharp.targets, to import. Ignoring.
: error : Error initializing task Message: Not registered task Message.
                Build FAILED.
                Warnings:
                :  warning : Default tasks file /usr/local/Cellar/mono/4.2.0.179/lib/mono/3.5/Microsoft.Common.tasks not found, ignoring.
```

エラーとワーニングが出てビルド出来ない。
原因はビルドパスの通ってる場所にMicrosoft.CSharp.targetsとMicrosoft.Common.tasksがないため。

## パスを通す

エラーメッセージの場所を見ると確かにない。

```
$ ls /usr/local/Cellar/mono/4.2.0.179/lib/mono/3.5
Microsoft.Build.Engine.dll*         
Microsoft.Build.Framework.dll*      
Microsoft.Build.Tasks.v3.5.dll*     
Microsoft.Build.Utilities.v3.5.dll* Mono.XBuild.Tasks.dll*
```

4.5を見るとあったのでシンボリックリンクを貼る。

```
ln -s /usr/local/Cellar/mono/4.2.0.179/lib/mono/4.5/Microsoft.Common.tasks /usr/local/Cellar/mono/4.2.0.179/lib/mono/3.5
ln -s /usr/local/Cellar/mono/4.2.0.179/lib/mono/4.5/Microsoft.CSharp.targets /usr/local/Cellar/mono/4.2.0.179/lib/mono/3.5
```

## 再びビルド

```
$ xbuild websocket-sharp.sln

（省略）

Build succeeded.
         0 Warning(s)
         0 Error(s)

```

成功。
[ Electron ] MacでWindows用のパッケージをつくるときアイコンまわりでエラーがでたときの対処法

# Electronでアプリを作ったけどWindows版のビルドでエラーが出る話(直った！！！)
タイトルの通りなのですが、Mac版のビルドは問題なく通り、Windows版ではelectron-packagerコマンドでエラーが発生していました。

問題を切り分けていくとアイコンが怪しいという結果に。

[ 追記 ]

**wineを入れればできた！**ので下記は問題が起こった時の対処の記録として残しておきます。

## アプリケーションのパッケージング(Mac)

```
$ electron-packager ./sample SampleApp --platform=darwin --out=sample/build --arch=x64 --version=0.30.0 --icon=sample/img/app.icns
```
こいつはOK。

## アプリケーションのパッケージング(Win) 

```
$ electron-packager ./sample SampleApp --platform=win32 --out=sample/build --arch=x64 --version=0.30.0 --icon=sample/img/app.ico
```

**これはNG。オプショナルのパラメータを精査した所下記コマンドではビルドできた。**

```
$ electron-packager ./sample SampleApp --platform=win32 --out=sample/build --arch=x64 --version=0.30.0
```

問題はアイコンの形式？

## アイコンの作り方を色々試す

### ImageMagick使用

```
$ convert app.png -define icon:auto-resize app.ico
```
... NG。

### Photoshopのプラグインから書き出し

[ICO ファイルフォーマット・プラグイン](http://www.telegraphics.com.au/sw/icoformat.ja.html)

... NG。

## もっと情報を探す

[Electron を試す 2 – パッケージ化におけるプラットフォーム固有処理とコンパイル分岐](http://akabeko.me/blog/2015/10/electron-2/)

最初参考にした頃にはなかった追記が。wineを入れればOKとのことで試す。

```
$ brew cask install Caskroom/cask/xquartz
```
下記エラーがでるのでググる

```
$ (eval):9:in `name': wrong number of arguments (1 for 0) while loading '/usr/local/Library/Taps/caskroom/homebrew-cask/Casks/xquartz.rb'
```

brew-caskが古いらしいのでアップグレード。

```
$ brew upgrade brew-cask
```
もっかいX11をいれてからwineをインストール

```
$ brew install wine
```
すごい時間かかるので待つ

インストールが完了したらアイコン入りのビルドを再度試す。
→
**できたっぽい**

Windows7 professional 64bitで動作、アイコン反映を確認しました。やったー！
BacklogAPIとHubotでSlackに課題通知を送る (続き)

[前回](http://qiita.com/manabukk/private/206b4d5c897163e43f65)

#Coffee script 参考
[CoffeeScript 言語リファレンス](http://memo.sappari.org/coffeescript/coffeescript-langref)
[基本操作逆引きリファレンス（CoffeeScript）](http://kyu-mu.net/coffeescript/revref/)

#Backlog API
朝に期限が迫っている課題を通知させたい

[Backlog API とは](http://developer.nulab-inc.com/ja/docs/backlog)

ここを参照しながら

できたソースコードは以下

```coffeescript:backlog2.coffee

# Description:#   Backlog to Slack## Commands:#   None

cron = require('cron').CronJob

backlogUrl = '****'
apiKey = '****'
username = '***'

module.exports = (robot) ->
    new cron "0 0 9,15 * * *", () =>
        console.log "BacklogAPI 2 start..."

        now_raw = new Date
        console.log "#{now_raw}"
        now = "#{now_raw.getFullYear()}#{now_raw.getMonth()+1}#{now_raw.getDate()}"
        console.log now

        # APIアクセス
        robot.http("#{backlogUrl}api/v2/issues?apiKey=#{apiKey}")
        .get() (err, res, body) ->

            # console.log body

            for feed in JSON.parse body
                if feed.dueDate is null
                    continue

                due = "#{feed.dueDate[0..3]}#{feed.dueDate[5..6]}#{feed.dueDate[8..9]}"

                if now > due and feed.status.id > 2 # 過去の課題で処理済みのものは表示しない。　status id 1:未処理 2:処理中 3:処理済み 4:完了
                    continue
                if feed.assignee.name isnt username # 自分の課題以外はスルー
                    continue
                if parseInt(due,10) - parseInt(now,10) > 14 #２週間より先の課題は表示しない
                    continue
                console.log due
                console.log feed.issueKey
                console.log feed.assignee.name
                console.log "due : #{feed.dueDate}"
                console.log "*"

                # 投稿メッセージを整形
                url = "#{backlogUrl}view/#{feed.issueKey}"
                message = "[#{feed.issueKey}] #{feed.summary} #{url}"

                # Slack に投稿
                robot.send {room: '#backlog'}, message
                # console.log message

    , null, true, "Asia/Tokyo"

```
uGUIのInputField

#概要
Unityのバージョンは5.2.3f1

uGUIのInputFieldについてのメモです。
InputFieldのコンポーネントの内容は以下の通りです。

- InputField
- Placeholder(Text)
- Text　Textについての説明は[こちら](http://qiita.com/seka/items/a3e478a9525cd36ea0ec)

内容はマニュアルを見ると詳しく載っています。
http://docs.unity3d.com/ja/current/Manual/script-InputField.html


#InputFieldの機能
文字の入力とキーボードの制限が可能。

- Text Component　入力された文字が表示されるテキスト
- Text　テキストの初期文字列
- Character Limit　入力文字数の制限（0を設定すると文字数制限はなし）
- Content Type　文字種類の制限（用途によって使い分ける）
 - Standard　標準設定
 - Autocorrected　自動修正機能設定
 - Integer Number　整数入力
 - Decimal Number　数値入力
 - Alphanumeric　英数字入力
 - Name　名前入力（記号は入力不可）
 - Email Address　メールアドレス入力
 - Password　パスワード入力
 - Pin　暗証番号入力
 - Custom　入力をカスタマイズできる
- Line Type　行のタイプ
 - Single Line　文字が幅いっぱいになっても折り返さなでリターンを押すと入力終了
 - Multi Line Submit　文字が幅いっぱいになると折り返しリターンを押すと入力終了
 - Multi Line Newline　文字が幅いっぱいになると折り返しリターンで改行　
- Placeholder　何も文字が入力されてない時に表示する文字
- Caret Blink Rate　カーソルの点滅速度設定
- Selection Color　選択されている文字列の背景色設定
- Hide Mobile Input　スマホのキーボード入力で補助用の入力フィールドの表示設定

注意）
行頭禁則の処理は入っていない。
日本語を入力する時の文字制限は文字を確定した時に制限される。
SNS機能を作る時に、不適切な単語などは入力を制限する場合、自分で処理を組む必要がある。

#InputFieldのイベント
イベントはOn Value Change(String)とEnd Edit(String)で制御します。
On Value Changeは文字が変更されたときにイベントが発生します。（日本語入力の場合、文字が確定した時にイベントが発生する）
End Editは入力が確定（エンターキーもしくは他の場所をクリック）されたときにイベントが発生します。
イベントの追加方法は
1.右下の＋をクリック
2.None(Object)に制御するオブジェクトを選択
3.No Functionで制御するメソッドもしくは変数を指定する

#InputFieldのSprict制御
```lang:InputFieldTest
  using UnityEngine.UI;

  private InputField inputField1;
  private Text text1;

  void Start()
  {
      inputField1 = GetComponent<InputField>();
  }

  // このメソッドをOn Value Changeに指定すると文字変更があった時に呼び出される
  public void OnValueChange()
  {
      Debug.Log(inputField1.text);  // 入力された文字を表示
  }

  // このメソッドをEnd Editに指定すると入力が確定した時に呼び出される
  public void EndEdit()
  {
      if (inputField1.text = "a") inputField1.text = "";  // 入力文字制限
      Debug.Log(inputField1.text);  // 入力された文字を表示
  }
```

#その他のメモ
- 文字入力制限をする場合は、Placeholderであらかじめ入力できる文字と文字数を書いておくといい
- 入力禁止の単語が含まれていたり入力できない文字を登録しようとした場合はエラーメッセージを出すとなぜ入力できないか分かり易い
- 少し改良して右側に×ボタンをを追加して押したら文字を消去できるようにする
- 検索の入力バーとして利用する（虫眼鏡アイコンと更新ボタンを追加するとわかりやすい）
- チャットの文字入力に利用できる
http://hiyotama.hatenablog.com/entry/2015/05/22/173402
- スマホだと文字入力は面倒なので極力数を減らすほうが良い。（お問い合わせフォームくらいにとどめる）

#参考になりそうなサイトやAsset
スマホのUIに使えそうな参考サイト
http://d.hatena.ne.jp/web-mind/20141028/p1

インプットフィールドの表現の参考サイト
http://ascii.jp/elem/000/001/062/1062572/index-2.html
http://netpr.jp/media/14943/

アニメーション表現の参考サイト
http://coliss.com/articles/build-websites/operation/javascript/jquery-plugin-fancyinput.html
http://9-bb.com/入力フォームにフォーカスすると鉛筆でカキカキ/
http://tympanus.net/Development/TextInputEffects/

#今後の課題
入力単語規制のいい処理方法を思いついたら後で追加する
ShinyでsliderInputを日付で選択する


## はじめに
- 興味でShinyでダッシュボードを構築してると、sliderInputを日付で選択できると便利だなーと思って調べた
- ググッても簡単に事例は出てこなかったので、やり方を共有

## Shiny Issue
- [#689](https://github.com/rstudio/shiny/issues/689)で議論されていた。
- wchさんがまだ実装されていないとおっしゃっている…！
- 「がーん」と思ったら、そのままの流れで、wchさん実装したものがMergedされている！よし。

## Slider Input Widget
- 公式マニュアルは[こちら](http://shiny.rstudio.com/reference/shiny/latest/sliderInput.html)。timeFormatのところでできそうな雰囲気を感じた。
- input-slider.R
    - コードは[こちら](https://github.com/rstudio/shiny/blob/master/R/input-slider.R)。81行目あたりから見る限り、sliderInputのmin valueをinheritでDateやPOSIXで指定できてる。

## 書き方

下記のように書く

```app.R
sliderInput(inputId="sliderDate",
		     label="日付選択 : 2015/12/01-11",
		     min=as.Date("2015-12-1"),
		     max=as.Date("2015-12-11"),
		     value=as.Date("2015-12-1"),
	         step = 1,
             animate=animationOptions(interval=1500, loop=T),
		     timeFormat = "%F"
		    )
```

## 結果

期待どおりのsliderInputになった

![スクリーンショット 2015-12-13 0.29.10.png](https://qiita-image-store.s3.amazonaws.com/0/69266/8b47aeb2-2bfc-df58-f7ab-9833b8043ca1.png "スクリーンショット 2015-12-13 0.29.10.png")

## おわりに
- Shiny便利。データはあらかじめ整形してRDSで保存してそれを読んでそのまま可視化するくらいなら、十分な速度で動く。アプリレイヤーは自分は全然書けないで人に見せるときに色々と助かる。
   - あらかじめ見せるものが決まってるダッシュボードとして使うのに良い。Shinyの上で分析や試行錯誤は処理速度の関係上辛いなーという印象。
SSHのポートフォワードを利用してファイアウォール越しに社内環境とAWS上のインスタンスを連携する


# 概要
開発用途としてAWS上のEC2インスタンスを使えるようになりました。社内からEC2インスタンスへのアセクスだけでほとんどは事足ります。しかしながら、とある80番ポートと22番ポート以外はファイアウォールで阻まれるとか、EC2インスタンスから社内のサーバにアクセスしたいとか、いろいろやりたいことが出てきます。
このメモでは、幾つかのケースでSSHポートフォワードを使ってやりたいことを実現する方法を説明します。

## 事前準備
- puttyなどのsshクライアントを入れておく
- Windowsマシンにsshサーバを入れておく

こちらを参考に。
参考：[Installing OpenSSH (Cygwin 1.7.35) on Windows 2012 R2](http://dbaportal.eu/2015/03/05/installing-openssh-cygwin-1-7-35-on-windows-2012-r2/)

## 前提
- 社内PCからAWS上のEC2インスタンスへsshで接続できる。(22番ポートで)
- EC2インスタンス上のWindowsマシンにはSSHでアクセスできる。
- EC2インスタンスからは社内PCにアクセスできない。

## 実現したいこと
1. AWS上のEC2にたてたWindowsマシンに社内PCからRDPする
2. AWS上のEC2インスタンスから社内の開発サーバに接続する

要するに、ローカルポートのフォワードと、リモートポートのフォワードをするだけです。

# 1. AWS上のEC2にたてたWindowsマシンに社内PCからRDPする
## 準備
AWS側のセキュリティグループのインバウンド設定で、RDP用のデフォルト通信ポートである__3389__を許可します。
![スクリーンショット 2015-12-12 22.01.41.png](https://qiita-image-store.s3.amazonaws.com/0/79341/71c0b7c0-eff0-f571-3c39-20bed7990c6f.png "スクリーンショット 2015-12-12 22.01.41.png")

あと、接続先のGlobal-IPアドレスとPrivate-IPアドレスを控えておきます。


## ローカルポートを転送する

ローカルPCの13389番ポートをターゲットPCの3389番ポートへ転送します。

```
$ ssh -L13389:ターゲットPCのPrivate-IP:3389 ターゲットPCのGlobal-IP
```

上記のコマンドでターゲットマシンにログインしている間は、ローカルPCの13389番ポートへRDP接続すると、ターゲットPCにRDP接続できます。

## ローカルポート経由でターゲットPCに接続する

Macに入れたMicrosoft Remote Desktopでアクセスします。

![スクリーンショット 2015-12-12 22.20.33.png](https://qiita-image-store.s3.amazonaws.com/0/79341/51447309-f802-c26d-bfb3-08591d839196.png "スクリーンショット 2015-12-12 22.20.33.png")

![スクリーンショット 2015-12-12 22.23.59.png](https://qiita-image-store.s3.amazonaws.com/0/79341/40eb27f5-cccb-74fc-9a57-e0de23f86c5f.png "スクリーンショット 2015-12-12 22.23.59.png")

## 補足

転送設定は__config__ファイルに書くと楽になります。こんな感じです。Hostに指定する名前はわかりやすいものを

```.ssh/config
Host AwsSandboxWin
	HostName	ターゲットマシンのGlobal-IP
	LocalForward	13389	ターゲットマシンのPrivate-IP:3389
```

LISTENポートを確認。13389ポートで待ち受け中です。ローカルPCのみからです。

```
$ netstat -na|grep LISTEN|grep 13389
tcp4       0      0  127.0.0.1.13389        *.*                    LISTEN
tcp6       0      0  ::1.13389              *.*                    LISTEN
```

ちなみに、ポートフォワードするときに__-g__をプションをつけると、ローカルPC以外の社内PCからも接続できるようになります。


```bash
$ ssh -L13389:ターゲットPCのPrivate-IP:3389 -g ターゲットPCのGlobal-IP
```

```
$ netstat -na|grep LISTEN|grep 13389
tcp6       0      0  *.13389                *.*                    LISTEN
tcp4       0      0  *.13389                *.*                    LISTEN
```




# 2. AWS上のEC2インスタンスから社内の開発サーバに接続する
こんな感じの接続を実現します。
![スクリーンショット 2015-12-13 0.26.13.png](https://qiita-image-store.s3.amazonaws.com/0/79341/5824e626-6e00-2962-7e6a-47f5b881e337.png "スクリーンショット 2015-12-13 0.26.13.png")

セキュリティ上、アクセスしたいサーバーをAWSに持っていけない、といった場合を想定しています。社内PCを踏み台にしてアクセスしたいサーバーへ誘導してやります。

## リモートポートを転送する

リモートPCの8888番ポートをターゲットPCの80番ポートへ転送します。

```bash
$ ssh -R8888:ターゲットPCのIP:80 リモートPCのGlobal-IP
```

上記のコマンドでリモートマシンにログインしている間は、リモートPCの8888番ポートへ接続すると、ターゲットPCお80番に接続できます。


## リモートポート経由でターゲットPCに接続する

リモートPC上でリモートポートにアクセスします。ブラウザで接続します。

![スクリーンショット 2015-12-12 23.25.30.png](https://qiita-image-store.s3.amazonaws.com/0/79341/40553a9b-70c1-491f-11d2-4f3b377ebbcf.png "スクリーンショット 2015-12-12 23.25.30.png")



# 最後に
VPN機器や当該サービスを導入せずとも社外PCから社内PCへのアクセスが実現できます。本番環境はともかくとして、開発環境では十分使えます。
変換せずに打てる文字の割合を漢直の入力方式ごとに調べた

この記事は 漢直 Advent Calendar 2015 の12日目の記事です。

## 本記事の目的
[Let's type with tut-code](http://www.geocities.jp/ken1noguchi/TUT-CODE/hiragana/what.htm) というサイトには、TUT-Codeという入力方式において、「何文字の漢字のストロークを覚えると日常で使う漢字のうち何割を変換無しで打てるか」という情報が載っています。

では、TUT-Code以外の入力方式ではどうなのでしょう。本記事は、漢直の入力方式ごとに、変換せずに打てる文字の割合を調べることを目的とします。

## 調査対象の入力方式
以下の4つの入力方式について調べます。()内はその入力方法で打てる文字数です(ひらがな・かたかな・記号を含む)。

- T-Code (1356文字)
- TUT-Code (2611文字)
- G-Code (2070文字)
- phoenix (3645文字)

## コード
調査に使ったコードは [github](https://github.com/sakabar/survey_kanchoku_coverage) に置いてあります。


## 調査に利用するデータ
日本語版Wikipediaの記事全文のダンプデータを利用します。ダンプした日にちは2015年12月2日です。

先述のサイトとはデータの種類が違うため、文字の出現率が異なっていると思います。これは失敗でした。

## 流れ
1. ダンプデータのダウンロード
2. XMLタグの除去
3. 文字のカウント
4. それぞれの文字が変換なしで打てる文字かどうかを漢直の入力方式ごとに判定
5. グラフを描画

"Qiitaは、プログラマのための技術情報共有サービスです。 プログラミングに関するTips、ノウハウ、メモを簡単に記録 & 公開することができます。"とあるので、ここからは少しプログラミングに関する話をしていきます。

### ダンプデータのダウンロード
wgetで取ってきます。

```bash
wget -O data/jawiki-20151202-pages-articles.xml.bz2 https://dumps.wikimedia.org/jawiki/20151202/jawiki-20151202-pages-articles.xml.bz2
```

これで、日本語版Wikipediaのデータが`data/jawiki-20151202-pages-articles.xml.bz2`に保存されます。拡張子を見れば分かるように、XMLをbz2で圧縮したファイルです。大きさは2.1Gでした。

### XMLタグの除去
[wp2txt](https://github.com/yohasebe/wp2txt) というツールを利用しました。ruby 1.9.3p484では動き、ruby 2.1.6p336ではうまく動きませんでした。これは私の環境のせいかもしれません。

```bash
wp2txt -i data/jawiki-20151202-pages-articles.xml.bz2 -o wikipedia_text/
```

これで、Wikipediaのテキスト部分が`wikipedia_text/`内に適当な大きさで分割されて保存されます。Wikipedia記法が完璧には取り除けていませんが、大きな影響はないと思います。

### 文字のカウント
```bash
for f in wikipedia_text/*; do
  cat $f | nkf -Z | tr -d '[a-z]' | tr -d '[A-Z]' | tr -d '[0-9]' | grep -o . | LC_ALL=C sort | uniq -c > wikipedia_chars/`basename $f`
done
```

`grep -o`で1文字ごとに切った後、`sort | uniq -c`でカウントします。ここには載せていませんが、別の部分で `[亜-腕]|[弌-熙]` という正規表現を利用してJIS第一・第二水準の漢字のみを抽出しています。


### それぞれの文字が変換なしで打てる文字かどうかを漢直の入力方式ごとに判定
Pythonでコードを書きました。ストロークと漢字の対応を辞書で保存し、順にチェックしてます。

出力はこんな感じです。左から、文字の出現頻度、割合、文字、変換なしで打てるか(T/F)、何ストロークで打てるか、累積密度(ちょっと言葉が違うかも)

```
17297200  0.0357498071    年      T       2       0.0357498
10388297  0.0214705047    日      T       2       0.0572203
8350979   0.0172597813    月      T       2       0.0744801
5813246   0.0120148014    大      T       2       0.0864949
5140580   0.0106245371    本      T       2       0.0971194
4961634   0.0102546920    学      T       2       0.107374
4466213   0.0092307572    人      T       2       0.116605
```

### グラフを描画
これはプログラムではなくOpenOfficeを利用しました。

## 結果
X軸は「覚えた文字数」、Y軸は「何割の文字を変換せずに打てるか」です。ここでは簡単のため、出現頻度の高い文字から順にストロークを覚えたと仮定しています。

![curve1.png](https://qiita-image-store.s3.amazonaws.com/0/13826/276401f8-204f-3f87-586a-7d4eddeed6a3.png)

T-Codeが9割でで頭打ちになっている点が目立ちますね。

部分的に拡大すると、以下のようになります。(視覚的にひっかける意図はありません)
![curve2.png](https://qiita-image-store.s3.amazonaws.com/0/13826/8f899de9-6c91-cc73-3360-c003b6070167.png)

その入力方式で打てる文字数に依存しているので、下からT-Code, G-Code, TUT-Code, phoenixの順に並ぶのは順当ですね。ただ、phoenixとTUT-Codeで1000文字以上収録文字数が違うのに、グラフ上では大きな変化はありません。増えた分の1000文字は出現率の低い漢字ということですね。
cakePHP3のQueue Pluginを使ってみる

初、Advent Calendarです。よろしくお願いします(^o^)
この記事は、[CakePHP 3 Advent Calendar 2015](http://qiita.com/advent-calendar/2015/cakephp3)13日目用に書きました。


# Queue Pluginって？

イケメンのMark S.さんが作ってくれている、[CakePHP Queue Plugin](https://github.com/dereuromark/cakephp-queue)のことです。
DBにTaskを追加して、Queue用のworkerを動かしておくと、定期的にTaskを実行してくれます。


# なぜ、Queue Pluginを使ったか

スクレイピングでデータを貯めて、それを参照するWebアプリを作っています。
定期的にスクレイピングしてデータを貯めていますが、それが追いつかない時に、追加でスクレイピングしてくれる仕組みがあると良いなと考え、調べた結果、Queue Pluginを使ってみることにしました。

※スクレイピングの実行間隔を狭めれば良いんじゃないかとか思いましたが、まぁそれはそれ(^o^)


# 使い方

## install

composerで一発です。便利便利。

```shell-session
composer require dereuromark/cakephp-queue:dev-master
```

あとは、実行時にPulginを読み込むように、bootstrapに下記を追記します（loadAllしてる場合は必要ありません）。

```php:bootstrap.php
Plugin::load('Queue');
```

最後に、Queue用のテーブルを作成します。
queued_tasksという名前になっていると思います。

```shell-session
./bin/cake migrations migrate -p Queue
```


## Taskの作り方

QueueにTaskを登録するには、まず登録するためのTaskを作る必要があります。
ここでいうTaskとは、Shellから実行するためのTaskのことを指します（[公式サイト：Shell Tasks](http://book.cakephp.org/3.0/en/console-and-shells.html#shell-tasks)）。
具体的には、こんなやつです。Shellからmain()を実行することができます。

```php:SampleTask.php
namespace App\Shell\Task;

use Cake\Console\Shell;

class SampleTask extends Shell
{
    public function main()
    {
        // some codes
    }
}
```

上記は普通のTaskです。
似てますが、Queue用のTaskは、こんな感じになります。

```php:QueueSampleTask.php
namespace App\Shell\Task;

use Queue\Shell\Task\QueueTask;

class QueueSampleTask extends QueueTask
{
    public function add() {
        $this->out('call add!!');
    }

    public function run($data, $id = null)
    {
        $this->out('call run!!');
        return true;
    }
}
```

extendsがShellではなく、QueueTaskになってるのが違います。
あと、main()ではなく、add()とrun()に処理を書いていきます。
run()は、最後に実行結果をbool値で返します。


### addとrunの違い

Queue用に作られたTaskは、２通りの方法で実行できます。
１つはコマンドラインから、下記を実行します。

```shell-session
./bin/cake Queue.Queue add <TaskName>
```

この場合は、add()が即座に実行されます。
Queue用のテーブルには、何も書き込まれません。

run()についてですが、これはControllerやModelから実行することができます。
Controllerは、こんな感じ。

```php:SomeController.php
$this->loadModel('Queue.QueuedTasks');
$this->QueuedTasks->createJob(<TaskName>, array('to' => 'user@example.org', ...)));
```

Modelからは、こんな感じです。

```php:SomeTable.php
TableRegistry::get('Queue.QueuedTasks')->createJob(<TaskName>, array('to' => 'user@example.org', ...)));
```

これが処理されると、DBのqueued_tasksにTaskが登録されます。
TaskNameはadd()の時と同じで、次の引数は、run()の\$dataに渡されます。
run()の引数である\$idには、DBに登録されたidが入ります。
DBに登録されたTaskは、下記を実行すれば、順番に処理されていきます。

```shell-session
./bin/cake Queue.Queue runworker
```

Taskがなければ、新しいTaskが登録されるまでスリープ状態となります。
workerの動きは、ある程度制御できるようです。
[公式にあるConfigurationの説明](https://github.com/dereuromark/cakephp-queue/tree/master/docs#configuration)を参考にしてください。


### TaskNameについて

Taskの名前ですが、クラス名からQueueとTaskを除いた文字列となります。
QueueSampleTaskだと、Sampleとなります。もしくは、QueueSampleでも動きます。
Queueというプレフィックスは必須ではないですが、他のTaskと区別するために、あったほうが良いかなと思います。
有効なTaskは、下記を実行すると確認することができます。

```shell-session
./bin/cake Queue.Queue
```


# 終わりに

思ったより長くなってしまいましたが、最後まで書けて良かったです。
cakePHPはいろんなことができるし、コミュニティの人もとても親切なので、使っててとても楽しいです(^o^)
それでは、良いcakeライフを！
Shutterで簡単画像加工

![shutter.png](https://qiita-image-store.s3.amazonaws.com/0/12235/079fa198-5d8c-05de-da5f-9dee8ff53135.png)

画像をどこかに載せるとき加工を行いたいときがあります. 枠で囲ったり, 文字を挿入したり, 矢印を置きたいときなどです. GIMPなどの高度な画像処理ソフトを使えばそのようなことは実現できるわけですが, 簡単ではありません. そこで紹介するのが [Shutter](http://shutter-project.org/)です. Macでいうところの Skitchのようなツールと思っていただければよいと思います. スクリーンショットツールと銘打たれていますが, 私はこれを画像処理ソフトとしてつかっています. これを使えば簡単に先ほど述べたことが実現できます.

## 使い方

Shutterで画像ファイルを開くと以下のようになります.

![shutter-1-3.png](https://qiita-image-store.s3.amazonaws.com/0/12235/22b3681b-34e6-0358-f175-38741ce5cd20.png)

右上の赤い丸で囲まれたパレットアイコンをクリックすると編集画面に遷移します.

![shutter80.png](https://qiita-image-store.s3.amazonaws.com/0/12235/6fdc6010-ef91-65de-e37e-bd6ac71c02e4.png)


左側に並んでいるアイコンで線を引いたり, 丸や四角で囲ったり, 文字を挿入したり, 矢印を挿入したりできます. 見たまんまという感じなので特に悩むことなくできるものと思います. いろいろ遊んでみたら基本的なところはすぐに使えるはずです.


![sample2.jpg](https://qiita-image-store.s3.amazonaws.com/0/12235/e7a6dff2-7396-c8c1-74a1-6e2c8250bac7.jpeg)


## おわりに

画像加工ツールとして使える Shutterを紹介しました. こういうツールは Macとか Windowsにしかないんでしょと思っている人もいましたが, Linuxにも普通にありますので遠慮無く Linuxデスクトップ環境にスイッチしてみてください.


ちなみにこの Shutterというソフトはほとんどが Perlでできているという(失礼ですが)珍しいGUIソフトウェアです. Perlハッカーの人は中身をハックしてみるのもよいかもしれません.
【FileMaker】音声ガイドを作る

FileMaker Advent Calendar 2015 13日目です。


今日はちょっと小ネタです。

博物館などにある音声ガイドをFileMakerで作ってみました。
![スクリーンショット 2015-12-12 19.19.59.png](https://qiita-image-store.s3.amazonaws.com/0/60538/dbe1a73e-cb41-5373-6790-b835fc00c4f6.png)
（※説明文等の元ネタは、[国立博物館の化石ふしぎの旅](http://kaseki.kahaku.go.jp/zukan/index.html)です。）

「説明する」ボタンを押すと、説明文に登録したガイド文を音声で読み上げてくれます。

「読み上げ」コマンドに、説明文を指定しているだけですが、きちんと読んでくれました。
![スクリーンショット 2015-12-12 19.20.37.png](https://qiita-image-store.s3.amazonaws.com/0/60538/245ea7af-4579-d4f7-b9be-edb1e7e93dac.png)

これを、iPadでやろうと思ってFileMaker Goへ送ったのですが、なんと、、、[「読み上げ」コマンドはFileMaker Goでは使えない！！！](https://www.filemaker.com/help/14/fmp/ja/html/scripts_ref1.35.156.html)

がびーん。

FileMaker Pro、もしくはRuntimeソリューションでしか使えないんだとか。。。
ということは、Runtimeにしてアプリ配布でしょうかね。
うーむ、ちょっと敷居が高くなってしまいましたが、とりあえず、音声ガイドをしてくれる機能の紹介でした。
WebBrowser に便利な機能を集めたヘルパークラスを作ったよ！

これは [Delphi Advent Calendar](http://qiita.com/advent-calendar/2015/delphi) １３日目の記事です。

僕が普段使っているブラウザを組み込んだモバイルアプリ開発を便利にするヘルパークラスです。
下記のメソッドを使うと、少しは開発が楽になるかもしれません！

[ソースファイルはここ](https://gist.github.com/freeonterminate/303c2910d96f871bd5db)に。

※モバイルアプリ（iOS / Android）専用です

#ハイブリッドアプリを作る
## SetForHybridApp メソッド
このメソッドを呼ぶと Android / iOS でハイブリッドアプリに必要な設定をします。

※ハイブリッドアプリ（側ネイティブアプリ）とは、アプリにウェブブラウザを埋め込んだアプリ。UIの部分はウェブで、ハードウェアなどをいじる場合はアプリ側で実装するアプリ。

#ハードウェアバックキーを押されたときの処理
## CheckBack メソッド (Android 専用)
TForm.OnKeyDown で渡ってくる Key 変数をこのメソッドに渡します。
Key 変数がハードウェアバックキーだったときに必要な処理をします。

* 仮想キーボードが表示されていた場合 → キーボードを隠す
* 戻れる場合 → 前のページに戻る

#ウェブブラウザの表示制御
## Show / Hide メソッド
表示されているブラウザを隠したり表示したりします。
ウェブブラウザはネイティブコントロールなので、その上に FireMonkey で表示することはできません（例えば、ローディング中のインジケータなど）。
ウェブブラウザが表示されている領域に別の何かを表示する際に Hide を呼び出します。Hide で隠したウェブブラウザは Show で表示します。

#ユーザーエージェントの設定
## SetUserAgent メソッド (Android 専用)
ユーザーエージェントを設定します。
ガイドラインを守ること。

**はじめに。**
***
AndroidのUI/UXを考える上で、
【Google推奨の...】ということをよく言われるので、共有します。

何気なくボタンのサイズを決めたり、配置を決めたりするのではなく、ガイドラインを
守って考えることが、ユーザーに広く受け入れられるアプリになっていくのだと思います。

何も知らなかった私は例えばデモを作る段階でも適当に作っていたのですが、
ガイドラインを守るとやはりスッキリします！

**タップ領域の推奨のサイズは**
* * *

Androidの場合、重要なタップターゲットは48dp以上と推奨されています。
その中で、実際の画像のサイズであったり、余白のサイズの推奨も定められています。

参考：https://www.google.com/design/spec/layout/metrics-keylines.html#metrics-keylines-touch-target-size


**ちなみにiOSでは**
***
ちょっと表が細かいですが、
最小サイズは44px x 44pxが推奨されているようです。（iPhone6とiPhone5の場合）

参考：https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html#//apple_ref/doc/uid/TP40006556-CH27-SW1


**所感**
***
いろんな統計とか思想を元に定められているのだと思いますが、
アプリ開発に携わるまで、こういった基準があることすら知りませんでした。

とても簡単な紹介になってしまいましたが、
単純に面白いなと思ったのと、しっかりとガイドラインを守って
アプリ開発を進めようと反省しましたので共有でした！

タップ領域以外にもいろいろ掲載されているので、
興味のある方は見てみてください！
ownCloud Desktop 同期クライアント 2.1.0 のChangelog

Desktop Changelog | ownCloud.org
https://owncloud.org/changelog/desktop/


Release 2.1.0 2015年 12月3日

- GUI: 同期されていないファイル(同期対象外、同期失敗)を別ビュー追加
- GUI: アップロード/ダウンロードの進捗UIを更新 (#3403, #3569)
- ownCloud のアカウントやグループに対して、デスクトップから共有可能に
- .で始まるファイルは、全てのプラットフォームで隠しファイルとして扱うように変更 (#4023)
- ファイルシステム上で読み込み専用の権限を反映 (#3244)
- Blacklist: 分割アップロード成功時にクリアー (#3934)
- ネットワークが変更されたり切断された後の再接続を改善 (#4167 #3969 ...)
- Windowsファイル更新検知パフォーマンスの改善
- libneonベースの更新を削除。その為、Qt<5.4の場合は、Linuxディストリビューションで制限帯域幅を利用できません
- ログ取得機能の性能改善
- ローカルディスク容量の問題を正しく取り扱えるように修正 (#2939)
- チェックサムの取り扱いを改善: 変換やDBバリデーション (#3735)
- *emlファイルのサイズかチェックサムが変更されてない限り再アップロードしない (#3235)
- リターンコード 403 を適切に取り扱いできるように修正 (File Firewall) (#3490)
- サーバーへのPROPFINDのリクエスト数を大きく削減 (#3964)
- GUI: アカウントアクションを維持するようにアカウントツールボックスウィジェットを追加 (#4139)
- タスクトレイメニュー: 最近更新したファイルのメニューの修正を追加 (#4093, #3969)
- FolderMan: 一次停止の無限待機を修正 (#4093)
- unitを含むように envの 変数名を変更 (#2939)
- FolderStatusModel: 未定ファイルの削除を検出するように変更 (#3612)
- SyncEngine: 同期が途中エラー時にホワイトリストをリセットしない (#4018)
- Quota: quotaで0以下の値を扱えるように (#3940)
- アップデートの更新情報通知時にアプリ名を表示 (#4020)
- PropagateUpload: エラー終了時に正常終了しないように修正 (#3844)
- GUI: 同期から除外されているフォルダ名をクリックできるようにした
- Shell 統合: Dolphin をサポート、KF 5.16 と KDE Application 15.12が必要
- FolderStatusModel: フォルダー名が変更された場合に必ずリセット (#4011)
- GUI: ツールバーが一杯になっているときのUI利便性をアイテム名を修正 (#3795)
- 「フォルダー同期接続」をもっと沢山のところに導入 (#3757)
- アカウント設定: オフライン時に一次停止できないように (#4010)
- 隠しファイルの取り扱いを修正 (#3980)
- ソフトエラーを再開しながら、ダウンロードエラーを処理します (#4000)
- SocketAPI: コマンドがトリミングされていないことを保証 (#3297)
- DBを削除する前にソケットAPIを終了 (#3824)
- GUI: 全削除ダイアログでデフォルトを”保持”に変更 (#3824)
- owncloudcmd: --version と --help で リターンコード 0 を導入
- owncloudcmd: --max-sync-retries (最大同期リトライ回数) を追加 (#4037)
- owncloudcmd: 2秒以上古いファイルかどうかチェックしない (#4160)
- 選択同期時のサイズ取得について修正 (#3986)
- 設定画面に閉じるボタンを再追加 (#3713)
- ストレージの制約を正しく取り扱う機能を追加 (#3736)
- サードパーティ依存を更新: sqlite version 3.9.1
- 私たちのベースの Qt バージョン admin/qt/patches でパッチを取り扱うようにしました
- その他: 記載していない沢山の改良や修正
[小ネタ] knockout.jsのattrバインディングでreadonly属性を設定する

HTMLの`readonly`属性はちょっと変わった属性で、名前と値の組ではなくて属性名だけで指定します[^1]。この属性を`attr`バインディングを使って設定しようとすると意外と難しかったりします。どう難しいか順を追ってみていきましょう。

まず、`attr`バインディングを使って`readonly`属性を変更する場合は、以下のように記述することになります。

```html
<input type="text" data-bind="attr: { readonly: readonlyAttr }">
```

`readonlyAttr`は属性値を返すobservableなプロパティです。が、これはいったい何を返せば良いのでしょうか。値など要らないわけですが、何かを返さないと`attr`バインディングが満足してくれません。

ここでHTMLの仕様を記憶からひねり出します。実は属性名のみの指定は`readonly="readonly"`の略記です。ということはつまり、`readonlyAttr`は以下のようにすればいいはずです。

```js
self.readonlyAttr = ko.computed(function() {
    return self.isReadonly() ? 'readonly' : '';
});
```

が、うまくいきません。`isReadonly()`が偽の時もreadonlyが有効になってしまいます。なぜかというと`readonly=""`と`readonly="readonly"`は同じ意味に解釈されるからです[^2]。これはつまり`readonly`を無効にするためには属性名ごと削除しないといけないということです。

なんだか急に難易度が上がりました。`attr`バインディングのパラメータごと切り替えるみたいなことが果たしてできるのか、あるいは独自のバインディングを作ったほうが色々早いのではないか……

ここで独自バインディング実装の参考という名目でknockout.jsのソースコード探索に逃げてみましょう。すると`attr`バインディングになにやら意味深なコメントがあるのが見つかります。

https://github.com/knockout/knockout/blob/master/src/binding/defaultBindings/attr.js#L8

```js:knockout/src/binding/defaultBindings/attr.js
            // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
            // when someProp is a "no value"-like value (strictly null, false, or undefined)
            // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
            var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
            if (toRemove)
                element.removeAttribute(attrName);
```

なんと、属性値として`null`、`false`、`undefined`を指定すると属性を削除してくれるようです。まさにこんな時のための機能があるではありませんか[^3]。

ということで、このように指定すれば目指した挙動になりました。めでたしめでたし。

```js
self.readonlyAttr = ko.computed(function() {
    return self.isReadonly() ? 'readonly' : null;
});
```

ちなみにisReadonlyをそのまま使っても動作するようですが、その場合は`true`の時に`readonly="true"`になってしまいます。属性値が`true`の場合の挙動はHTMLの仕様からは見つけられませんでしたが、概ね`readonly`属性が有効だと解釈されるようです。


[^1]: 同じような属性として`checked`や`disabled`などがありますが、これらには対応するバインディングが用意されているので困ることはありません。
[^2]: [HTML5: 2.4.2 Boolean attributes](http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes)
[^3]: この仕様はドキュメントに記載されていません。
SeleniumIDEでリダイレクトのテストをする

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/SeleniumIDE%E3%81%A7%E3%83%AA%E3%83%80%E3%82%A4%E3%83%AC%E3%82%AF%E3%83%88%E3%81%AE%E3%83%86%E3%82%B9%E3%83%88%E3%82%92%E3%81%99%E3%82%8B/)をご覧ください😀

# はじめに
みなさん、リダイレクトのテストどうやってますか？

静的なHTMLページを動的システムに乗せかえたり、古いシステムのリプレイスなどでURLが変わることありますよね。
でも、ページランクは引き継ぎたいので『旧URL→新URLへ301リダイレクトしよう』というのは結構あるあるかと思います。

数ページであればブラウザに旧URLを貼って、新URLに飛ぶこと確認してOKとなりますが、
対象ページが数100～存在したりすると全部見るのは大変・・・。
ましてや開発環境、ステージング、本番と環境毎に確認するとなると涙が出てきますよね？

そんな時、私はSelenium IDEを使ってテストしています。

# Selenium IDEとは
Selenium IDEって何？という人はこちら。
[5分でわかるSelenium IDEの使い方](http://qiita.com/naoqoo2/items/90d382cd9370d3526509)

# テストケースはこんな感じ

<table>
<tr>
	<th></th>
	<th>コマンド</th>
	<th>対象</th>
	<th>値</th>
</tr>
<tr>
	<td>1</td>
	<td>store</td>
	<td>【旧URLのドメイン】</td>
	<td>before</td>
</tr>
	<td>2</td>
	<td>store</td>
	<td>【新URLのドメイン】</td>
	<td>after</td>
</tr>
<tr>
	<td>3</td>
	<td>open</td>
	<td>${before}【旧URLのパス】</td>
	<td></td>
</tr>
<tr>
	<td>4</td>
	<td>assertLocation</td>
	<td>${after}【新URLのパス】</td>
	<td></td>
</tr>
</tbody></table>

### 解説
1,2：旧と新のドメイン部分を変数に格納してます。環境毎にテストする際はここを書き換えるだけ。
3：openでURLにアクセスします。
4：3でopenしたあとリダイレクトしているはずなのでassertLocationでリダイレクト先URLが正しいかを判定。
※あとは3,4をコピペしてリダイレクト対象分増やせばOK。（Excelやプログラム組むなど工夫して作るとGood!!）

# サンプル
百聞は一見に如かず ということで実際にやってみましょう。
ここでは「短縮URL→Qiita記事URLにリダイレクト」を例にします。（旧→新のいいサンプルがなかったので…）

* http://goo.gl/hmegpd
→ http://qiita.com/naoqoo2/items/413dfa0aa01e9f294c53
* http://goo.gl/MQq30f
→ http://qiita.com/naoqoo2/items/90d382cd9370d3526509
* http://goo.gl/PcvbKP
→ http://qiita.com/naoqoo2/items/bb02d790be8fd7fe6554

の3つのリダイレクトをテストしますよ。
下記をコピーしてテキスト保存してSeleniumIDEのテストケースを開くで試してみてください。


```html:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="" />
<title>sample</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">sample</td></tr>
</thead><tbody>
<tr>
	<td>store</td>
	<td>http://goo.gl</td>
	<td>before</td>
</tr>
<tr>
	<td>store</td>
	<td>http://qiita.com</td>
	<td>after</td>
</tr>
<tr>
	<td>open</td>
	<td>${before}/hmegpd</td>
	<td></td>
</tr>
<tr>
	<td>assertLocation</td>
	<td>${after}/naoqoo2/items/413dfa0aa01e9f294c53</td>
	<td></td>
</tr>
<tr>
	<td>open</td>
	<td>${before}/MQq30f</td>
	<td></td>
</tr>
<tr>
	<td>assertLocation</td>
	<td>${after}/naoqoo2/items/90d382cd9370d3526509</td>
	<td></td>
</tr>
<tr>
    <td>open</td>
    <td>${before}/PcvbKP</td>
    <td></td>
</tr>
<tr>
    <td>assertLocation</td>
    <td>${after}/naoqoo2/items/bb02d790be8fd7fe6554</td>
    <td></td>
</tr>
</tbody></table>
</body>
</html>

```

# さいごに
いかがでしたでしょうか？
これでブラウザに直接URLを貼り付ける面倒なテストとはおさらばです。
コーヒーでも飲みながらブラウザが自動でテスト完了してくれるのを優雅に待ちましょう。

それではステキなSeleniumIDEライフを。
Packer + Terraformで管理しているインスタンスをダウンタイムなしで差し替える

# 前提

1. packerからAtlasのArtifactにAMIを登録している
2. ArtifactからTerraformでインスタンスを建てている
3. Route53を使って建てたインスタンスに名前を振っている

つまりすごく限定されたパターン。

# どうしたいか

Terraformの管理内で、インスタンスを止めずに、同じ名前を新しいインスタンスに割り当てつつ、新しいインスタンスのアプリケーションが立ち上がったのを確認してからRoute53の名前を付け替えたい。

素直にやろうとすると、PackerでビルドしてArtifactを差し替えた後に`terraform apply`した途端に

1. インスタンス停止
2. 新しいAMIからインスタンスが立ち上がる
3. Route53の名前が書き換える

ので全くダメ。

# どうするか

`aws_instance.name`というリソース名を使っているとして

1. packerでビルドしてArtifactを差し替える
1. `terraform.tfsate`ファイルから対象インスタンスの`aws_instance.name`の部分のみを削除して`serial:`を一つ上げておく
1. `terraform apply -target aws_instance.name`でインスタンスだけ立ち上げる
1. 新しく立ち上がったインスタンスでアプリケーションが動いていることを確認する
1. `terraform apply`でRoute53が新しいインスタンスのほうでも更新される
1. 古いインスタンスはTerraformの管理外になったので手動で削除
Greedy Best First Search

今日は GBFS, Greedy Best First Search を紹介します。

# 完全性を保った非最適探索

前回触れた山登り法は、 **解が存在するときにきちんと解を返してくれる保証** がありません。この保証のことを完全性と言います。<sub>完全と呼ぶ派と完備と呼ぶ派とがあるらしいですが、completeの訳なので正直どっちでもいいです。</sub> 単純な山登りには、$h$ の極小点とゴールが一致するなどの特殊な状況を除き、完全性がありません。

一方でA*やダイクストラには完全性があります。完全性があるので、解が存在すればかならずいつかは解を発見できます。しかし、「いつか」というのはどのくらいの未来のことを指しているのでしょうか? この質問は、すでに**ある人**が体を張って示してくれています。

> 私は皆に「組み合わせ爆発のすごさ」を教えたいの！止めないで！

![おねえさん.png](https://qiita-image-store.s3.amazonaws.com/0/6090/f930c68c-68d6-e62a-11d7-f42248f76493.png)

みなさんもご存知の通り、指数爆発を起こしている探索問題を工夫なしに解こうとすると、スパコンを使っても何千万年もの時間がかかるわけですね。特にダイクストラはそのような種類のアルゴリズムです。それだけではなく、A*に優れたヒューリスティクスを組み合わせたときであっても、全く探索が終わらないような場合が存在します。実用的なグラフ探索を行いたいという場合には、これではこまりますね。

「素早く探索をしたい」「完全性も保ちたい」「両方」やらなくっちゃあならないってところが研究者の辛いところです。でも、じつはいい手があるんです。

# GBFS

GBFSは、 $f=h$ とし、 $g$ 値を無視する A* です。優先度付きキューにノードをf値に従って挿入する点は変わりません。

GBFSは、探索にあたって $h$ を完全に信頼するアルゴリズムだと言えます。一方、A*は 今までの経験 ($g$) と 予測 ($h$) を同程度に重視するアルゴリズムだといえましょう。

GBFS は完全です。 $h$ が小さいところを優先して探索するのはかわりませんが、キューにいままで展開した経路が残っているので、最も$h$ が小さい範囲で失敗したらきちんとバックトラックします。仮に$h$ が完全にでたらめな値を返す関数であっても、十分な時間があれば探索空間を全て探索し尽くすことで解を見つけられます。また、A*/ダイクストラと同じく重複検知を行うので、巡回路にハマって永遠にループすることもありません。

# GBFS の挙動

GBFSは、名前の通り Greedy に探索を行います。このことを、下の図を用いて検証してみましょう。

例として扱う問題は、 4-connected grid でロボットが目的地まで移動する問題だとします。目的はスタートからゴールまでの経路探索です。ただし、このフィールドにはおわん型の壁があり、ロボットは壁を乗り越えられないものとします。ヒューリスティクスとしてユークリッド距離を用います。

左がA*の探索空間だとすると、GBFSの探索空間は右図のようになります。実験的には、この探索空間を全て探索するわけではないのですが、イメージとしてはこれで十分でしょう。

![gbfs.png](https://qiita-image-store.s3.amazonaws.com/0/6090/cac164ce-4b9b-77d4-b6aa-fe85ca586531.png)

実験するとA*はこんな感じ。 (Likhachef 2008 R* Search より拝借)

![Screenshot from 2015-12-12 21:38:39.png](https://qiita-image-store.s3.amazonaws.com/0/6090/ae478941-851f-d83a-5960-11782116c3b8.png)

# GBFS の欠点

GBFS の欠点は、解の長さに全く上限がないことです。先ほどの図でもわかるとおり、GBFSの返す解は最適解よりもだいぶ長くなります。あまりにも長い解は、いくら探索が早くても使い物になりません。

GBFSのもうひとつの欠点は、 $h$ を信頼しすぎてトラップにかかりやすい点です。先ほどの図の $h$ が正しい領域、例えば 壁よりも右側での領域では、GBFSは一直線にゴールに向かうことができます。しかし壁よりも左側では、GBFSはおわん型のトラップにハマってしまい、A*と同じく半円状の広い空間を探索していることがわかります。

一方A*は、たとえ壁を越えたとしても一直線にゴールへ向かうことは出来ません。これは、A*が壁の右側にしっぽのような狭い楕円形の探索空間を形作っていることからもわかります。

# まとめ

GBFSを紹介しました。次回はGBFSの一つ目の欠点、「解の長さに上限がない」ことを解決するアルゴリズムを紹介します。
突然の死！故障したAndroidのデータ移行に役立ったツール(NO ROOT)

この記事は [ACCESS Advent Calendar 2015](http://qiita.com/advent-calendar/2015/access) 13日目向けの記事として書かれました。

また当記事は業務内容とは関係なく、扱っているソフトやツール類は個人で使用したものであり、業務中に使用したものではありません。

# はじめに

スマホは精密機器であり、いつ故障してもおかしくありません。電源が全く入らない場合は個人では望み薄ですが、電源が入るが画面が点かない、画面が割れてタッチパネルが使えない、などの場合は、まだなんとかできる可能性があります。

写真や電話帳などのデータはクラウドに保存してあれば、移行後の端末で同期すれば問題ないですが、アプリの設定や引き継げないアプリのデータ（特に**ねこあつめ**）や、機種変前に引継番号を発行するなどのお作法があるおさいふケータイアプリなどはカバーできていません。

Rootを取っておいてTitanium Backupでマルッと解決するかもしれませんが、取るのが面倒な端末だったり、そもそもとりたくないこともありますよね？　今回は、Rootを取らなくても使えるツールをご紹介します。

# ツール

これから紹介するツールは、以下の設定がされているのが条件です。

* 開発者向けオプションからUSBデバッグを有効にする
* 使用するPC（Win,Mac,Linux）にadbが入っていて、パスが設定されている
* 使用するPCからのUSBデバッグを常に有効にしておく

少々ハードルが高いかもしれませんが、一度設定しておけばいいですし、rootとるよりも安全なのでやっておきましょう。

## Universal ADB Driver for Windows

普段MacbookやLinuxを使っていると意識しないのですが、WindowsとAndroidを繋ぐにはドライバの導入が必要です。メーカー毎にドライバが違うので面倒なのですが、[Universal ADB Driver for Windows](https://plus.google.com/103583939320326217147/posts/BQ5iYJEaaEH) を入れておくと、スムーズに導入できます。

## Helium

[Helium](http://www.clockworkmod.com/carbon) （旧Carbon）は、アプリをデータごとバックアップするツールです。使う前に一度PCと端末をPTPでつなぐ必要がありますが、引き継ぐ方法がない**ねこあつめ**等のアプリを引き継げるためオススメです。これでくりーむさんからのたからものも無くならないで済みますね。

内部でやっていることは `adb backup`なのですが、後ほど紹介する機能も便利なので、使って損はないと思います。

Heliumは、Windows、Mac、Linuxの他にChromeアプリでも提供されています。また、Playストアからあらかじめアプリをインストールする必要があります。

以下は、データ移行に使ってみて気づいた点です。

* 電子書籍などアプリの容量が大きい場合は時間がかかるため、新規インストールから同期できる場合はそっちのほうがいい
* 銀行アプリなど、一部のアプリは移動されたことを検知するため、Heliumを使っても初期設定が必要
* LINEは初期設定が必要なのと、トーク履歴を同期で引き継げないため、事前に履歴をエクスポートしておく必要が有る

定期的にバックアップを取っておくのも有効ですが、オススメしたいのは有料版。これを買っておくと、端末間で直接アプリの移行ができます。新しい端末から古い端末内のアプリを選択できるため、いちいちバックアップをとって保存して……などすることがなくて楽チンです。

## Vysor

[Vysor](http://www.vysor.io/) は、PC上でAndroidを操作できるツールです。

Androidの画面がPCにウィンドウとして現れ、マウスで端末を操作できます。スクロールもマウスホイールやトラックパッドのスワイプでできるので使い勝手がよく、キーボードからの文字入力もでき、スクリーンショットも取れます。

実機を動かしているので、エミュレータなんか目じゃないくらいスムーズです。ラグが少ないので、プレゼンとかにも有効でしょう。
開発もこれでやりたい


これを導入することで、画面が点かなかったりタッチ操作が効かない場合でも、PC上で操作してデータの移行やアプリの引継番号発行などが可能です。OTGケーブルでマウスやキーボードをつながなくてもいいので、ノートPC派にも嬉しいですね。

こちらもChromeアプリとして提供されているため、OSを選ばないのが特長です。こちらは実機には自動でインストールするされるため、PC側でアプリをインストールするだけで大丈夫です。

# 注意

今回紹介したツール、Helium は Android 4.0 以上、 Vysor は Android 4.1 以上でないと使えません。古い端末にも救済措置が欲しいところではありますが、セキュリティの都合上、仕方がないことなのかもしれません。

それでは、楽しい Android ライフを。
ドル決済サービスStripeの全容をざっくり把握する

![jenwz4_1w6QnIeurylkQdD4HWS5777Bn7e1k_bTkR9U.png](https://qiita-image-store.s3.amazonaws.com/0/40921/2a871278-8b22-f732-3a3e-a209c2ef1fab.png)

この記事は [Goodpatch Advent Calendar 2015](http://qiita.com/advent-calendar/2015/goodpatch) 13日目の投稿です。
昨日は@hayato-k さんによる「[Android 開発はじめました - けどちょっと躓いた](http://qiita.com/hayato-k/items/094f9f5ada550f2b69c1)」でした。

# Stripeってなに

StripeはWeb決済サービスです。
https://stripe.com/
アメリカのサービスですが、ドル以外の各国の通貨に対応した実装ができます(後にも書きますが日本円はまだ…)。

Web決済というとpaypalとかで手間なく実現できるイメージですが、自前で実装するとこんな良さがあるみたいです。

- 手数料がちょっと安い
- 自サイト内でフォームが完結(決済サービスのアカウントをユーザーが作らなくてもいい)
- アクセス解析ツールをフォームに仕込める

# どうやって決済するの

クレカ入力フォームは、よくある感じでHTMLをコピってライブラリを読み込めば簡単にできるみたいです。自前でUIを用意することももちろんできます。

クレカ情報入力後は以下のような流れになってます。

1. Webで入力されたクレカ情報をjsライブラリを通してStripeに投げる
2. Stripeがクレカ情報をセキュアなトークンにしてくれる
3. トークンを自サーバに投げてStripeの課金APIを叩く
4. 成功コールバックで課金データをユーザーに紐付ける

定期購読形式での支払いの時はさらにこんな流れが付いてきます。

5. 定期購読の時期が来るとStripeが自動で課金を行う
6. 課金のステータス(成功か失敗か)をWebhookで渡される
7. Webhookの内容次第で自サーバでは次月分の課金データを紐付ける

# StripeAPIざっくり概要

[本家ドキュメント](https://stripe.com/docs/api)が割といい感じですが、英語だったりできることがやたら多かったりするので超簡単にまとめました。

![スクリーンショット 2015-12-12 1.47.14.png](https://qiita-image-store.s3.amazonaws.com/0/40921/d71e566f-8377-5d03-e025-68fce161b43f.png)

## Customer
顧客情報。

ここからカード情報や支払い履歴を辿れる。
顧客が支払う際の通貨とかemailとかも保存しておける。

## Cards
カード情報。

カード会社とか発行国とか。
もちろんカードナンバーみたいな秘密にしたいやつは入ってない。

## Charge
一度で払いきるタイプの支払い。
金額を指定して顧客に紐付ける。

## Plan
定期課金の料金プラン。ベーシックとかプロとかみたいな。

生成と削除処理に関しては管理画面からできるけど、プログラムで一気に自動生成したいときとかはAPIを通して操作できる。

## Subscription
支払いの、定期購読型のほう（1ヶ月ごとに支払いみたいなやつ）。
プランを指定して顧客に紐付ける。

## Invoice
請求書のイメージ。

あんまり明示的に作ることはなくて、Subscriptionを作るとこいつが自動で生成されてる。
Subscriptionの期間が来ると、これに記載されている金額の引き落としが発生する。

## InvoiceItem
請求書に記載される商品一つ一つの情報といったようなイメージ。

こいつも明示的に作ることあんまりはない。
InvoiceとInvoiceItemは1対多だけど、何もしなければ1つしか紐付かない。

Invoiceが生成された後、Subscriptionの引き落とし期間が来る前にInvoiceItemを追加で紐付けておくと複数紐付く。
期間が来た時、その時点までに作られたInvoiceItemsの合計を一つのInvoiceが一気に引き落としてくれる。

管理側の都合とかで、消費税は別々に集計できるようにしたいときとかに
`Invoice = 実際の金額のInvoiceItem + 消費税のInvoiceItem`
みたいになるようにしておくといいとか、そんな感じの用途だと思う。

https://stripe.com/docs/api#invoiceitems
> This is useful for combining several charges to minimize per-transaction fees or having Stripe tabulate your usage-based billing totals.

# Stripeのいいところ

## APIが多いからうまく使えば色々できる

* クーポンによるディスカウント機能
* 商品の個数とか税率がいくらとかトライアル期間はいつまでとか
* 定期課金の場合は何ヶ月ごとに引き落とし処理するか指定できる

これらを設定するオプションが用意されているのでそれを利用すれば実装できちゃいます。

あとbitcoin決済のAPIもあってカッコいいと思いました。使わないけど。

## アプリがカッコいい

技術的な話じゃないですが。。
Stripeアカウントを所有していないかたもこちらのiPhoneアプリ紹介サイトで覗けます。
https://stripe.com/dashboard/iphone
![スクリーンショット 2015-12-12 1.48.18.png](https://qiita-image-store.s3.amazonaws.com/0/40921/912627db-e0c9-813c-ef7f-2b966332c227.png)

その他のStripeの作品もこちらで公開されています。
https://dribbble.com/stripe

## 円決済に対応

~~円決済機能もついたら日本でも幅広く使われるんじゃないでしょうか。今後の展開が気になります。~~
円決済にも対応したみたいです
https://stripe.com/japan

~~ちなみに現時点で円決済を似たような方法でやりたい場合はWebPayがいいと思います。~~
~~https://webpay.jp/~~

WebPayはサービス終了したので、Stripe以外ならPAY.JPがオススメです。
https://pay.jp/
間違えやすいGA分析その３：離脱率と直帰率

# テーマ:離脱率と直帰率

離脱率と直帰率に関して、間違えやすい点について解説しようと思います。
ちなみに各ページの離脱率、直帰率は以下の箇所で見ることができます。
行動 -> サイトコンテンツ -> すべてのページ -> 直帰率 or 離脱率 
![スクリーンショット 2015-12-06 15.12.11.png](https://qiita-image-store.s3.amazonaws.com/0/100736/c8b9a6d2-ca1b-101d-fbfb-1d6e9f67d13a.png)

# 問題

次の場合、ページA, B, Cの離脱率、直帰率はそれぞれ何％になるでしょうか。
なお、ページA, B, Cにこれ以外のセッションは発生していないとします。
月曜日: ページ A > ページ B > ページ C > 離脱
火曜日: ページ B > ページ A > ページ C > 離脱
水曜日: ページ A > 離脱

# 答え

| ページ | 離脱率 | 直帰率 |
|:----------:|-----------:|-----------:|
| A | 33% | 50% |
| B | 0% | 0% |
| C | 100% | 0% |


# 解説

まずそれぞれの言葉の定義から確認しましょう。

## 離脱率

個々のページのすべてのページビューで、**そのページがセッションの最後のページになった割合**を示します。

## 直帰率

**そのページがセッションに存在する唯一のページだった割合**を示します。計算対象は**そのページで始まったセッションのみ**です。

## 問題を振り返る

各ページの離脱率と直帰率の計算をしてみます。

### ページA

| ページビュー | ページAから始まったセッション | Aがセッションの最後のページになった数 |
|:----------:|:----------:|:----------:|
| 3 | 2 | 1 |

離脱率 ＝ 1 / 3 = 33%
直帰率 ＝ 1 / 2 = 50%

### ページB

| ページビュー | ページBから始まったセッション | Bがセッションの最後のページになった数 |
|:----------:|:----------:|:----------:|
| 2 | 1 | 0 |

離脱率 ＝ 0 / 2 = 0%
直帰率 ＝ 0 / 1 = 0%

### ページC

| ページビュー | ページCから始まったセッション | Cがセッションの最後のページになった数 |
|:----------:|:----------:|:----------:|
| 2 | 0 | 2 |

離脱率 ＝ 2 / 2 = 100%
直帰率 ＝ 0 / 0 = 0%

# 最後に

間違えやすいGA分析その１は[こちら](http://qiita.com/akatsuki174/items/615a3467cfa9f2b55fdb)
間違えやすいGA分析その２は[こちら]
(http://qiita.com/drafts/67596d442f4e8fbff233)
になります。

# 参考ページ

https://support.google.com/analytics/answer/2525491?hl=ja
React Native with Parse

今回はReact NativeからParse.comのJS SDKの使い方を説明します。

## Parse

ParseはFacebookに買収されたMBaaSです。push notificationで利用している人も多いと思います。MBaasを利用することでサーバサイドのシステムを構築する必要がないので開発スピードが上がります。

## React Native with Parse

React Nativeが発表されて間もなくParse.comのブログに[React Nativeをサポートするという記事](http://blog.parse.com/learn/parse-and-react-shared-chemistry/)が投稿されました。Parse JS SDKは動きますが、バージョンに注意する必要があります。

```
$ npm install parse --save
$ grep parse package.json
    "parse": "1.6.9",
```

Parse SDKのバージョンが1.6以上の場合は、下記のように`/react-native`を付ける必要があります。

```
var Parse = require('parse/react-native').Parse
// 以前は　var Parse = require('parse').Parse
```

また1.6以前だとユーザの情報が`Prase.User.current()`で取れたのが、非同期を明示する`Parse.User.currentAsync()`が必要です。Asyncを使ってうまく扱えば大丈夫です。

## How to use

使い方ですが、私は`app/utils/Parse.js`というファイルを作り、importして使っています。
下記のような感じです。`__DEV__`で本番とテスト環境のデータベースを分けています。

```
let Parse = require('parse/react-native').Parse;

// Production keys
let parseAppId = "zzz";
let parseJSKey = "zzzz";
let parseAPIKey = "zzzzz";

// Development key from TriplentyDev app
if(__DEV__){
  console.log("[DEBUG] Loading TriplentyDev...");
  parseAppId = "xx";
  parseJSKey = "xxx";
  parseAPIKey = "xxxx";
}

Parse.initialize(parseAppId, parseJSKey);

Parse.xyzFunction = function(){
　let query = new Parse.Query('Event');
...
 //
}
...

export default Parse；
```

**Parse JS SDKのAPIをそのまま使えます**


## Summary
Parseを使うことで、ログイン処理などもParseに任せることができます。バックエンドを持たずにアプリに集中して開発できます。フリーで使うことができるのでReact Nativeでもオススメです。

Push Notificationは後日説明します。
数がやたらと多いIPアドレスリストでのアクセス制限をLambda+Pythonでうまいことやる


# 経緯

弊社では[クラウド型eラーニングシステムeden LMS](https://lms.eden.ac)というサービスを運用しているのですが、先日お客さんとこういうやりとりがありました。

「eden LMSってIPアドレス制限の設定はできますか？」
「はい、できますよ。」
「192.168.1.0/24みたいなパターンもありますけど対応できますか？」
「もちろんです。ちなみに許可するパターンの数はいくつくらいですか？」
「2000個以上ありますね」
「2000個以上」
「あと、リストの内容はたびたび変わります」
「お、おう…」

# どうやって実装するか？

eden LMSはPythonで書かれており、Python製のnetaddrというライブラリを使えば「192.168.1.100/32は192.168.1.0/24に含まれるか？」みたいな判定自体は簡単に実装できます。ただし、サブネットがバラバラだと許可するIPアドレスリストに含まれるかどうかの判定をリストの要素数だけ行う必要が出てきてしまいます。これは馬鹿正直に実装すると結構なCPU負荷になりそうです。マルチテナント型のクラウドサービスなので、そういう処理は避けなければいけません。

「192.168.1.0/24」みたいなリストをすべて「192.168.1.1、192.168.1.2、192.168.1.3...」のような文字列のリストとして展開し、それに対してアクセス元のIPアドレスの文字列はリストの含まれるか、という実装（ipaddr in allowed_listみたいな判定）でも十分速度は出そうです…が、せっかくなのでAWS Lambdaを使ってマイクロサービス化してしまうことにしました。

AWS Lambdaを使うと、以下のような理由で実装を単純にしておくことが出来ます。

- CPU負荷はほとんど気にしなくてよくなるため、「192.168.1.0/24」みたいなリストもnetaddrを使って判定すればいい
- AWS Lambda側のファイルにIPアドレスのリストを含めておき、リストが更新されたときはサービス本体は触らずにLambda側だけを更新すればよい

# 実際のソースコード
まず、AWS Lambda側ですが、netaddrライブラリを使ったIPアドレスの判定をAWS Lambdaの形式に合わせてあげるだけです。

```py:lambda_function.py
from netaddr.ip import IPNetwork,IPAddress

def lambda_handler(event, context):
	ipaddr = event['ipaddr']
	for network in allowed_networks:
		if IPAddress(ipaddr) in network:
			return True
	return False

allowed_networks = [
	IPNetwork("192.168.2.1/24")
	,IPNetwork("192.168.3.1/24")
	,IPNetwork("192.168.4.1/32")
]
```

このlambda_function.pyとnetaddrライブラリのフォルダをzipで固めてAWS Lambda側にアップロードした後、API endpointを追加します。これで準備は完了です。

APIを呼び出す側は次のようになります。（ひとまずはSecurityはOpenにしていますが、実際はIAMなどを使うことになるはずです）

```py:lambda_call.py
# -*- coding: utf-8 -*-
import urllib2
endpoint = "https://xxx.amazonaws.com/prod/apiname" #実際のエンドポイントが入ります
req = urllib2.Request(endpoint)
req.add_header('Content-Type','application/json')
response = urllib2.urlopen(req,'{"ipaddr":"192.168.4.1"}')
print response.read()
```

あとは判定済の結果をmemcachedなどのKVSにでもキャッシュしておけば、AWS Lambdaの呼び出しは最小限で済みそうです。

# まとめ

「ピークのときとそうでないときの処理量の差が大きい」かつ「参照透過である」処理については、AWS Lambdaでどしどしマイクロサービス化してしまうとラクなんじゃないでしょうか。
ElmのMailbox

追記
この記事は古いです。過去のものです。忘れてください

# はじめに
この記事はElm Advent Calendar13日目の記事です
### わかること
ElmのSignal.Mailboxが何者なのか分かる。
公式ドキュメントに書かれている内容とコードを読んで分かったことが書いてある。
### わからないこと
Nativeモジュール(javascriptで書かれた部分)の中身。読んでません。
### version
```lang:exact-dependencies.json
{
    "elm-lang/core": "3.0.0"
}
```
# MailBox
### ざっくりいうと
ドキュメントにはまさにMailbox!みたいなことが書いてあります（確か）
Address(住所)にメッセージ(値)を送ると、Mailbox(郵便箱)を持っている人が受け取って見ることができます。
まさにMailbox！

ただメッセージを送る、というお仕事は副作用なので明示的にportなどを使って送らねばなりません。

やってみましょう。[Try Elm](http://elm-lang.org/try)に貼ればそのまま実行できます。

```lang:Main.elm
import Graphics.Element exposing (..)
import Task exposing (Task)

main = Signal.map show mailbox.signal

mailbox = Signal.mailbox "最初のメッセージ"

port post : Task.Task x ()
port post = Signal.send mailbox.address "次のメッセージ"
```

実行してみると、一瞬「最初のメッセージ」が実行された後「次のメッセージ」が表示されます

Mailboxを作るにはSignal.mailbox関数を使います。引数には初期値を与えています。この初期値が最初に画面に表示されています。

値はmailbox.signalで取り出せますが、名前からわかる通りSignal a型の値です。mailbox.addressに値を送ると値が変わるSignalですね

送り方は、手動で送る場合Signal.sendを使ってTaskにしてportを使って送ることです。
portを付けられたTaskは実行されます。sendで作られるTaskは与えられたaddressにメッセージを送ります

上の例では自分でportを使ってメッセージを送っていますが、[The Elm Architecture](https://github.com/evancz/elm-architecture-tutorial/)などではHtml.EventsのonClick関数にaddressとメッセージを与えてクリックされたらメッセージが送られるようになっています。
ここら辺の動きはNativモジュール内で定義されているので気になったら追ってみるといいかもしれません。

## Mailboxに関してその他
関連する関数として、Signal.messageとSignal.forwardToがあります。

Signal.messageはGraphics.Inputで使われています。一方、elm-htmlではaddressが使われています。使い方的にはほぼ一緒に見えるのでなんで違うのかはよくわかりません。

Signal.forwardToは転送用のアドレスを作る関数です。先ほどのAddressはStringを送れましたが、送る時に値を変換したりしてStringにしてから送りたい場合に使えます。

`mailbox :Maybe String`に送りたいときに、`send mailbox.address (Just "メッセージ")`とやるのではなくStringを直接送れる`stringAddress = Signal.forwardTo mailbox.address Just`を作ってから、`send stringAddress "メッセージ"`で送れるようになります。

# まとめ
MailboxはまさにMailbox!
Vue.jsを使って、簡易メモアプリを作る。facebookログイン機能付き。

この記事は、[Vue.js Advent Calender 2015](http://qiita.com/advent-calendar/2015/vue) 13日目の記事です。

Vue.jsを使って、簡易メモアプリを作りました。


**この記事は、古い情報です。**
**新しい記事は[こちら](http://qiita.com/akifo/items/7f01324fc17967a71762)**

## はじめに
公式サイトの[Examples](http://vuejs.org/examples/)を参考にしながら、少し複雑なSPAを作ってみました。

ログインユーザーとゲストで使用する画面が一緒なので、コードが冗長化しないようにすることを意識しましたが、それが原因で少し複雑になってしまったかなと思います。

## 概要など
- ES6で書いています。
- gulpでファイルを監視し、webpackを使用しています。
- データの保存はログインユーザーはfirebaseを使用し、ゲストはlocalstrageです。
- fluxにしようと思いながら書いたものの、素人なので。。


## コード

[https://github.com/akifo/vue-memo/tree/vue1.0.10-defective-flux](https://github.com/akifo/vue-memo/tree/vue1.0.10-defective-flux)

※ES6を使ったり使わなかったり、正しくないコメントがあったりしますが、動作には問題ないかと思います。時間あるときに修正します。

## デモサイト

~~[https://vue-memo.firebaseapp.com/](https://vue-memo.firebaseapp.com/)~~

## 考え方（アーキテクチャ）

- ``View``は``Vue.js``
- ``View``で発生したイベントを分析し``Store``へ伝搬するのが``ActionCreator``
- ``ActionCreator``はログインユーザーの場合、``firebaseStore``へ、ゲストの場合、``localStore``へイベントを伝える。
- ``Store``ではデータの保存や取得を行う。
- ``Store``へは``emit``することが可能で、``View``のデータに反映させたりできる。

### 新しいメモが追加された時の処理を追ってみます。

#### ログインユーザーの場合
![vue.001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/62259/d0110ee0-1e46-471a-04b6-c1661bc120c2.jpeg)

#### ゲストの場合
![vue.002.jpeg](https://qiita-image-store.s3.amazonaws.com/0/62259/216ae979-9d11-66a1-fb75-aea23c674b8a.jpeg)

``ActionCreator``があるおかげで``View(Vue.js)``では発生したイベントの処理について、どこの``Store``へ指示を与えるか意識せずに書くことができます。

ログインしているか、していないかの状態は、``View``と``ActionCreator``で共有しています。

``Stores``と``View``間は``EventEmitter``を使用し、データが更新されたタイミングでデータが同期するようにしています。


## firebaseについて

firebaseについての詳しい使い方は省きますが、下記URLを参考にしています。

[https://www.firebase.com/docs/web/guide/login/facebook.html](https://www.firebase.com/docs/web/guide/login/facebook.html)

1. facebook側で設定を行う
  - facebookアプリを作って
  - Valid OAuth redirect URIsを設定して、
  - メールアドレスを登録する。
2. firebase側で設定を行う
  - facebookアプリで生成された``App ID``と``App Secret``をコピーしてあげる。
3. javascriptでログインコードを書く
4. ログアウトのコードを書く 

[Firebase API Reference](https://www.firebase.com/docs/web/api/)

ログイン監視に、``onAuth()``、
ログイン時に、``authWithOAuthRedirect()``、
ログアウト時に、``unauth()``を使用しています。

## ``Store``とか作らずに``Vue.js``内で全部やってしまったほうが楽じゃない？

``Vue.js``では冗長化しないようにするために``mixins``で処理を外部化することができるし、``webpack``で``html-lodaer``や``style-loader``を使用すれば、複数のコンポーネントで共通する処理は外部ファイル化できるし、可読性も高い気がします。

ということで、``Vue.js内で全部やってしまう``パターンでもコード書いてみました。機能的には全く同じです。個人的にはこっちのほうが考え方が楽で好きです。

[レポジトリ](https://github.com/akifo/vue-memo/tree/vue1.0.10-simple)

### さいごに

``Vue.js``を使ったプロジェクトのデモとコードをもっとたくさん見たいです。Podastsで``Vue.js``の作者のEvan you氏がexampleを充実させていきたいと言っていた気がするので、公式サイトのexamplesなどが充実していくかもしれませんね。

``npm install``でインストールすると不必要で無駄なものもあるかもしれません。githubのデータは少しづつ修正していきたいと思いますので、詳しい部分についてはqiita内では触れないようにしました。ご指摘などありましたらお気軽にお願いします。