OmniAICreator/Qiita-1.07M huggingface dataset:
cLuster: Smart Clustering of Free-Hand Sketches on Large Interactive Surfaces

# はじめに
こんにちは．HCIの研究をしている大学院生の若林と申します．
今回は[ヒューマンコンピュータインタラクション論文紹介 Advent Calendar 2015](http://qiita.com/advent-calendar/2015/hci)の24日目の記事として[UIST2015](http://uist.acm.org/uist2015/about)から論文を紹介したいと思います．

紹介するのは『cLuster: Smart Clustering of Free-Hand Sketches on Large Interactive Surfaces』という[論文](http://dl.acm.org/citation.cfm?id=2807455)です．
フリーハンドで描いた絵や文字のクラスタ化を支援したよという内容の研究です．

動画は[こちら](https://www.youtube.com/watch?v=NUv7-7sPl2c)です．
[![none](http://img.youtube.com/vi/NUv7-7sPl2c/0.jpg)](http://www.youtube.com/watch?v=NUv7-7sPl2c)

# 概要
さて，フリーハンドで描いたものをクラスタ化するにはどうすればいいでしょうか．
まず，著者らはDelayeらの[研究](http://www.sciencedirect.com/science/article/pii/S0031320314004397)に着目しました．
これは絵や文字のストローク(一つの線)間において，距離や長さなど8つの特徴量を元に値を決め，しきい値以下なら同じクラスタにすることでクラスタ化する手法です．
またそれぞれの特徴量に対し重み係数をかけるのですが，その重み係数を訓練データを元に学習します．

```math
d_c(s,t) = \sum_{i=1}^n w_i d_i(s,t)
```
sとtはストローク，iはそれぞれの特徴量，$w_i$は特徴量に対する重み係数，$d_i$は特徴量の値です．
この$d_c(s,t)$としきい値を使って，クラスタ化していくわけですね．
しかし，Delayeらの手法は構造毎にしきい値や重み係数を学習し直しているため，訓練データを毎回集める必要があります．

# 予備実験
予備実験として著者らは，フリーハンドで壁面ディスプレイに描かれたものを2年間にわたって収集し，それらを9種類に分類しました．

![スクリーンショット 2015-12-24 18.03.38.png](https://qiita-image-store.s3.amazonaws.com/0/23725/8af3a60c-bbb7-5287-e1a4-962a71e5c340.png)

これを訓練データとしてDelayeらの手法に用いることで，学習し直さなくてもクラスタ化できるよう試みました．

# クラスタ化

そして著者らは，先程分類した9種類から"Global"と"Categories"を除いた7種類を訓練データに用いました．
その際，Delayeらの式を拡張し，7種類のカテゴリ毎に重み係数を計算しました．
このカテゴリ毎の値を線形結合した値を使ってクラスタ化を行います．

```math
d_c(s,t) = \sum_{j=1}^p \alpha_j d_j(s,t)
```
sとtはストローク，jはそれぞれのカテゴリ，$\alpha_j$はカテゴリに対する係数，$d_j$は前式で出る値です．

さらに著者らは，最初のクラスタをマニュアルで決定させ，そのクラスタの情報を元にリアルタイムでしきい値と$\alpha_j$を算出することでクラスタ化の精度を上げました．

![スクリーンショット 2015-12-24 19.39.51.png](https://qiita-image-store.s3.amazonaws.com/0/23725/d981b70c-31da-b241-43b1-73db7fed82ef.png)

# 評価実験
著者らは，クラスタを修正する機能も実装しています．

![スクリーンショット 2015-12-24 21.48.08.png](https://qiita-image-store.s3.amazonaws.com/0/23725/1b939293-f65b-8c5f-dfa8-5def3428670f.png)

評価実験ではクラスタ化した後，どれだけ修正を要したかをカウントしました．

![スクリーンショット 2015-12-24 21.49.52.png](https://qiita-image-store.s3.amazonaws.com/0/23725/3b77f2f2-eac0-99c0-0842-0680469d855e.png)

修正回数の平均値は2.76回(SD=2.70)でした．

# インタラクション
著者らはクラスタ化した後の，様々なインタラクションも実装しています．

#### タップ選択の拡張
タップした時は一つのクラスタが選択され，その後フリックした方向のクラスタとマージする．
![スクリーンショット 2015-12-24 21.59.49.png](https://qiita-image-store.s3.amazonaws.com/0/23725/2e1dcb61-42e0-c8a2-2d3a-a3a455d2a26e.png)

#### スプリングモード
クラスタが衝突すると反発する．
![スクリーンショット 2015-12-24 22.04.42.png](https://qiita-image-store.s3.amazonaws.com/0/23725/6b0c8f8c-3959-0920-8082-8aa8b2e937fc.png)

#### バブルモード
クラスタを入れ替える．
![スクリーンショット 2015-12-24 22.04.50.png](https://qiita-image-store.s3.amazonaws.com/0/23725/0f02318a-f757-0524-2f11-8c237756c98d.png)

# まとめ
かなり色々なことをやっている論文ですが，一番重要なポイントは最初のクラスタをユーザに選択させ，それを元にクラスタ化を行えるようにアルゴリズムを拡張したところです．

アルゴリズムもですが，スケッチのカテゴリ化も先行研究を参考，拡張して行っています．
しっかりと他研究と比較，検討しながら書かれている論文でとても参考になりました．

応用事例として様々なインタラクションを付与したところは，UISTぽいなーなんて思いました．
fortranで擬似乱数の生成


# はじめに
fortranでの擬似乱数生成は，random_numberを呼び出すことで行うことができる．

```fortran
real(4) :: harvest
call random_number(harvest)
```

得られる．コンパイラ依存があるかもしれないが，ifortでは，これで0-1の間の乱数を得られた．
しかし，これだけだと，毎回同じ乱数が生成されてしまうので，その回避法をメモ．

# seedのセットによる回避
以下のコードで，毎回異なる擬似乱数を得ることが出来た．

```fortran
real(4) :: harvest
integer(4), allocatable :: seed(:)
integer(4) :: c, sz

call random_seed( size = sz ) !コンパイラによってシードの配列サイズが異なるので，まずはシードの配列サイズを取得する．
allocate( seed(sz) ) !得られたサイズでseedをallocateする．
call random_seed( get = seed ) !デフォルトでセットされているシードを取得する．
call system_clock( count = c ) !システム時刻を取得して，
seed(1) = c                    !シードにその時刻を使用することで，毎回異なる乱数となるようにする．
call random_seed( put = seed ) !組み直したシードを設定する．
call random_munber(harvest) !擬似乱数の取得

deallocate( seed ) !最後はメモリ解放を忘れずに
```

今回は

```fortran
seed(1) = c
```

としているが，別に配列のどこを変えても乱数は異なるようになるみたいだった．それから，もしかしたら

```fortran
call random_seed( get = seed )
```

はいらないかもしれない．
なお，シード（種）とは，擬似乱数生成のためのパラメータで，この値を基に擬似乱数を生成している．

# おまけ（毎回同じ擬似乱数を取得する）
余談だが，毎回同じ擬似乱数を取得するには，

```fortran
call random_seed( get = seed )
```

で得られたシードを保存しておいて，乱数生成の直前に，

```fortran
call random_seed( put = seed )
```

とすれば良いらしい．
R言語 - Web scraping

# はじめに
　Web scraping とは、ウェブサイトから情報を抽出するコンピュータソフトウェア技術です。Web scraping は、Web上の非構造化データの変換、一般的には HTML フォーマットからデータベースやスプレッドシートに格納・分析可能な構造化データへの変換に焦点が当てられています。一方で、人間による WWW のブラウジングをシミュレートする Web crawler あるいは Web spider を含んだ広義の意味に捉えることもあります。Web crawler は、例えば、Googlebot(Google),Slurp(Yahoo),msnbot(Bing)などで、リンクを辿って新しいページを見つけます。その際、Crawler 用の情報を参照し、Sitemapの指定があれば、それを使ってサイト内を巡回します。今回はここまでの機能は実装せず、指定したサイト内の情報を取得するまでに留めました。

# Web scraping してみる
▼サンプルスクリプト

```R:R
# httpで情報をやりとりライブラリを読み込みます
library( RCurl )
# ワーキングディレクトリを指定します
setwd( "ワーキングディレクトリ" )
# 取得先URLを指定します
initSite <- "http://orablogs-jp.blogspot.jp/"
# 保存先ファイル名を指定します
initPage <- "get.html"
# ファイル読み込みモード
modeRead <- "r"
# (正規表現用)HTMLリンクタグ
href     <- "<a href"
# (正規表現用)URLの先頭
http     <- "^http"
# html拡張子
html     <- ".html"
# ファイル名生成用関数
genKey   <- function(){
  paste( format( Sys.time(), "%Y%b%d%H%M%S" ), substr( paste( "0000000000" , 
  round( abs( rnorm( 1 ) * 1000000000 )), sep = "" ),10, 20 ), sep = "" )
}
# サイトからPageを取得します
if( url.exists( initSite )){ download.file( initSite, destfile = initPage )}
pageBuf <- file( initPage, modeRead )
pageTxt <- as.list( readLines( pageBuf ))
close( pageBuf )
# href要素のリンク先URLを取得します
linkBuf <- strsplit( as.character( gsub( "\"", "'",  pageTxt[ grep( href, pageTxt, perl = TRUE )])), "'" )
for (i in 1:length( linkBuf )) {
  if ( i == 1 ) {
    linkTxt <- linkBuf[[i]][grep( http, linkBuf[[i]], perl = TRUE )]
  } else {
    linkTxt <- c( linkTxt, linkBuf[[i]][grep( http, linkBuf[[i]], perl = TRUE )])
  }
  linkTxt <- unique( linkTxt )
}
# リンク先URLからPageを取得します
for (j in 1:length( linkTxt )) {
  if( url.exists( initSite )){
    download.file( linkTxt[[j]], destfile = paste( genKey(), html, sep = "" ))
  }
}
```

# 備忘録
　Web scraping を R でやる必要はなかったのですが、演習のつもりで取り組みました。試行の過程で、library(XML) の htmlParse を使ってみましたが、解析が遅いし文字化けが酷いので使用中止しました。
　なお、サンプルコードは、私的使用のための複製(著作権法第30条)の基、という解釈です。取得した情報は、Web indexing(同第47条の6) や Web analysis(同第47条の7)に活用することになります。著作権法第47条の7の情報解析目的であっても、第47条の6の制約には注意を払う必要がありそうです。個人的にあるいは特定少数に提供するためにWeb indexingを開発するからといっても、以下の点に配慮したいです。
  ・文章、画像、音声、映像は、一部のみを収集
  ・robots.txt/robotsメタタグのアクセス制限を守る
  ・サーバアクセスの間隔を1秒以上空けるようにする。
  ・Pragma:No-cacheメタタグが設定されているページはダウンロードしない。
  ・rel=”nofollow”が設定されているリンクはクローラーで辿らない。
  ・ページに利用規約がある場合は守る。
  ・利用違反が発覚した場合は、取得した情報を破棄する。
  ・個人が特定されるデータは、公開しない。

# ご参考
著作物が自由に使える場合
http://www.bunka.go.jp/seisaku/chosakuken/seidokaisetsu/gaiyo/chosakubutsu_jiyu.html
情報検索サービスに関する改正について
http://www.i-law.jp/paper/copyright-search.pdf
VirtualBoxでUbuntuがゲスト時のフォルダ共有設定法

最近詰まったのでメモ。

1. Devices -> Insert Guest Addition CD imageをクリック
2. CDのアイコンをクリックしてインストール
3. 共有フォルダの設定からホスト側のファイルパスを指定し、自動マウントにチェック
4. Ubuntuソフトウェアセンターにて、「gnome-system-tools」で検索
5. GNOME用のクロスプラットフォームな設定ユーティリティ　が出てきたインストール
6. Dashホームから user と入力し、ユーザーとグループをクリック
7. グループの管理から、vboxsfを選択し、プロパティ
8. グループのメンバで自分のユーザー名にチェックを入れてOK
9. 再起動

これでOKです。
おそらく media/sf_****という名前でマウントされているはずです。
Kotlinに煽られる

# Kotlinで"進捗どうですか？"

まだ無いような気がするので投稿してみます。ついでにJavaも。
元ネタは[こちら](http://elephnote.com/blog/archives/936)。そのほかの言語の良い纏めが[こちら](http://qiita.com/B73W56H84/items/a6c4b770c6efc8d1af35#%E3%81%82%E3%82%8F%E3%81%9B%E3%81%A6%E8%AA%AD%E3%81%BF%E3%81%9F%E3%81%84)。

## Kotlin

最初はKotlinの特徴が出るように色々仕込んでいたのですが、無駄に複雑になったのでシンプルにしました。
Kotlinのバージョンは 1.0.0-beta-4583 です。


```kotlin:Main.kt
package jp.mitibata.practice.shinchoku

import java.util.*

/**
 * 進捗どうですか？シンプル版
 * 全ての文字を変数に格納して、毎回正規表現のマッチングをかけている。
 */
fun main(args: Array<String>) {
    val words = arrayOf("進捗", "どう", "です", "か")
    val rand = Random()
    val regex = Regex(""".*進捗どうですか$""")

    val aori = """
    |
    |＿人人人人人人人＿
    |＞進捗どうですか＜|
    |￣Y^^Y^^Y^^Y^^Y^￣
    """.trimMargin()

    var buffer = ""

    loop@while (true) {
        when (regex.matches(buffer)) {
            true -> {
                println(buffer)
                println(aori)
                println("${buffer.length}文字で煽られました")
                break@loop
            }
            false ->  buffer += words[rand.nextInt(words.size)]
        }
    }
}
```


こんな風にKotlinに煽られます。やったね。


```
かです進捗進捗ですどうですどう進捗どうかかかどうどうか進捗どうですか

＿人人人人人人人＿
＞進捗どうですか＜|
￣Y^^Y^^Y^^Y^^Y^￣
34文字で煽られました
```

## Java
同じ様な動作をするJavaも書きました。
複数行の文字列リテラルやら型推論が無いところに、ちょっとしたつらさがありますね。

```java:Main.java
package jp.mitibata.practice.shinchoku;

import java.util.Random;
import java.util.regex.Pattern;

/**
 * 進捗どうですか？Java版
 */
public class Main {
    public static void main(String[] args){
        String[] words = {"進捗", "どう", "です", "か"};
        Random rand = new Random();
        Pattern pattern = Pattern.compile(".*進捗どうですか$");

        String aori = "＿人人人人人人人＿\n＞進捗どうですか＜\n￣Y^^Y^^Y^^Y^^Y^￣";

        String buffer = "";
        while (true) {
            if(pattern.matcher(buffer).matches()) {
                System.out.println(buffer);
                System.out.println(aori);
                System.out.println(buffer.length() + "文字で煽られました");
                break;
            } else {
                buffer += words[rand.nextInt(words.length)];
            }
        }
    }
}
```
Googleマテリアルデザインガイドのフォントカラーを指定する


Googleのマテリアルデザインのスタイルガイドというものがあります。
http://www.google.com/design/spec/style/color.html#

この中にフォントカラー等のガイドラインがあります。
↓こんなやつ↓
![style_color_uiapplication_alpha1.png](https://qiita-image-store.s3.amazonaws.com/0/32136/f7eb42b3-1c21-da34-7986-94f4eaa1b62a.png "style_color_uiapplication_alpha1.png")

要するに、基準となるBase colorを定めて、そこから不透明率にてバリエーションを生み出せいうことなのでしょうが、この各々の不透明率がアルファ値で書くとどうなるのかを表にしました。

| 不透明率 | アルファ値 |
|--------:|----------|
| 100%| FF |
| 87% | DE |
| 70% | B3 |
| 54% | 8A |
| 30% | 4D |
| 26% | 42 |
| 12% | 1F |

colors.xmlに指定する場合は次のように`ARGB`で指定する。

```colors.xml
...
    <color name="colorPrimaryTextLight">#DE000000</color>
    <color name="colorSecondaryTextLight">#8A000000</color>
...
```

# 参考
http://stackoverflow.com/questions/5445085/understanding-colors-in-android-6-characters/
MacのChromeがCommand+Qですぐに終了してしまうのを防止する

## 対策
**メニュー → Chrome → 終了する前に警告メッセージを表示する (⌘Q)** 
を選択してチェックを入れます。

<img width="179" alt="menu.png" src="https://qiita-image-store.s3.amazonaws.com/0/39561/d591b7f7-5965-518d-fdfb-ad695ade767e.png">

以上を設定すると、Command+Qを連続で2回押すことで終了するようになります。
Crashlyticsでクラッシュレポートが表示されなかった時の話 (dSYMでハマッた件)

前回の記事で、クラッシュレポートの導入について書きました

[Crashlyticsでレポートを送るまで](http://qiita.com/feat2kj/items/b1d1ee1472ba8a64feab)

その際に、dSYMファイルの設定でハマったので忘れないようにメモしようと思います

# dSYMファイルとは
crachログはそのままだと見ても解読できません
メモリのアドレス位置(ポインタ)情報のみが記載してあるようです(すいません、よくわかってないです)
dSYMクラッシュログを、シンボル化して見えるようにしてくれるようです

**dSYMファイルには以下の制限があるようです**

* アプリをビルドした環境で作成したものでないと、シンボル化できない
* ビルド毎に新しく変更される(ポインタを復元するからという意味では当然かも)
    * リリース時のdSYMファイルは別の場所に保持しておいたほうがよさそうです(解析できなくなるかも！)

# Crashliticsでの設定

## クラッシュレポートが送信されない

はじめは設定どおり、行ったのにレポートが全然更新されずに困りました

![クラッシュ0.png](https://qiita-image-store.s3.amazonaws.com/0/103324/04dc7d50-8c89-fbd5-1952-1d01031f4463.png)

dSYMファイルが設定されていないのが、原因です。
dSYMファイルを認識していないと、画面右下に以下のアラートが表示されます
![繧ｹ繧ｯ繝ｪ繝ｼ繝ｳ繧ｷ繝ｧ繝・ヨ 2015-12-15 6.18.52.png](https://qiita-image-store.s3.amazonaws.com/0/103324/03d26dc1-46ab-e850-f144-87975ceb3b53.png)

## dSYMファイルの設定

アラートをクリックすると、dSYMファイルをアップしてくださいという画面が表示されます
![dSYMテスト.png](https://qiita-image-store.s3.amazonaws.com/0/103324/0d7f1441-74f9-1607-d74a-6430ede881d1.png)

## dSYMファイルの取得
非表示ファイルなので以下の手順で取得します

* 非表示ファイル表示  
`defaults write com.apple.finder AppleShowAllFiles -boolean true`
* dSYMファイル配置場所にアクセス  
` open /Users/ユーザー名/Library/Developer/Xcode/DerivedData/アプリ名xxxxxxxxx/Build/Products` 

## dSYMファイルの設定
先ほどの画面へディレクトリ毎、ドラッグ & ドロップします

![繧ｹ繧ｯ繝ｪ繝ｼ繝ｳ繧ｷ繝ｧ繝・ヨ 2015-12-15 6.56.38.png](https://qiita-image-store.s3.amazonaws.com/0/103324/549735ab-f126-3ae9-daf3-f4fc6c5ae7d0.png)

正常に登録されました

## クラッシュレポートの再確認

クラッシュ用のサンプルからエラーを発生させてレポートの確認を行います

![繧ｹ繧ｯ繝ｪ繝ｼ繝ｳ繧ｷ繝ｧ繝・ヨ 2015-12-15 6.58.08.png](https://qiita-image-store.s3.amazonaws.com/0/103324/80743630-831f-bc6d-8417-7e385abfd6cd.png)

無事にレポートを認識してくれました。

## おまけ
dSYMファイル自体をそもそも知らなかったので、たどり着くまでにだいぶ時間かかりましたが、
インストール時に丁寧に教えてくれていました。

![繧ｹ繧ｯ繝ｪ繝ｼ繝ｳ繧ｷ繝ｧ繝・ヨ 2015-12-15 6.13.02.png](https://qiita-image-store.s3.amazonaws.com/0/103324/680bcc90-9a7b-1f1f-667c-c0e408479ab3.png)

ちゃんと読まないといけませんね。それにしてもナビゲーションがイチイチ親切です

## まとめ
今回自分の知識不足の観点もあり、初歩的なところでだいぶ時間をつかってしまいました。
ただ入門書やアプリ開発だけでは得られない知識を吸収できるので、
積極的にいろんな環境を試していきたいと思います
underscoreコードリーディング（toArray）




underscoreに詳しくないので、勉強半分でソースコードを読む。


##利用するバージョン
[underscore.js(v1.8.3)](https://github.com/jashkenas/underscore/tree/1.8.3)


##toArrayとは


###[underscorejs.orgのtoArray](http://underscorejs.org/#toArray)

こんな説明。
>####_.toArray(list) 
>Creates a real Array from the list (anything that can be iterated over).
>Useful for transmuting the arguments object.

```javascript

(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
=> [2, 3, 4]

```

------------- 

listから配列を作成する（iterateできるものであれば）
objectを配列にするのに便利な関数です


###[underscore.toArray](https://github.com/jashkenas/underscore/blob/1.8.3/underscore.js#L425)

コード的にはこのあたり。


```javascript
  // Safely create a real, live array from anything iterable.
  _.toArray = function(obj) {
    if (!obj) return [];
    if (_.isArray(obj)) return slice.call(obj);
    if (isArrayLike(obj)) return _.map(obj, _.identity);
    return _.values(obj);
  };


```

objがない場合はからの配列を返す。
objが配列の場合は、sliceを用いて配列を生成して返す（copyではない）
objが配列に近いデータ構造の場合は_.mapを用いて配列として生成し直したものを返す。
それ以外の場合は_.valuesを用いて、その結果を返す。
R言語 - テキストのネガポジ度を分析する

# はじめに
　任意のテキストファイルにどのような特性があるのか？そのテキストファイルに、ネガティブな発言が多いか、それとも、ポジティブな発言が多いかの傾向をざっくりと把握するには、ネガポジ度を分析するとよいです。このTipsでは、とある組織のウィークリーレポートを使って、その内容にどのような特性があるのかを分析してみます。手順としては、①ウィークリーレポートをRMeCabで形態素解析後、②単語感情極性表(注1)からスコアを算出し、③ネガポジ度を三次元円グラフで描画します。単語感情極性とは、その語が一般的に良い印象を持つか（positive） 悪い印象を持つか（negative）を表したものです。例えば、「良い」、「美しい」などはpositiveな極性、 「悪い」、「汚い」などはnegativeな極性を持ちます。


# テキストのネガポジ度を分析する
▼サンプルスクリプト

```R:R
# 三次元円グラフライブラリを読み込みます
library(plotrix)
# 日本語形態素解析ライブラリを読み込みます
library (RMeCab)
# 単語感情極性表(Semantic Orientations of Words)を読み込みます
sowdic <- read.table("http://www.lr.pi.titech.ac.jp/~takamura/pubs/pn_ja.dic",sep=":",col.names=c("term","kana","pos","value"),colClasses=c("character","character","factor","numeric"),fileEncoding="Shift_JIS")
# 名詞＋品詞で複数の候補がある場合は平均値を採用します
sowdic2 <- aggregate(value~term+pos,sowdic,mean)
# ポジティブとネガティブを調整します(より傾向を出すため)
sowdic2$value <- sowdic2$value + 0.6
# 形態素解析の結果から頻度表を作成します
war2007 <- RMeCabFreq("WAR2007_20140131-1258.txt")
```
※「WAR2007_20140131-1258.txt」はウィークリーレポートをテキスト化したものです。以下は、テキストの例です。
![image](https://qiita-image-store.s3.amazonaws.com/0/106773/44593f31-e3ba-4b4e-8d4d-4a34827d95af.png)

# ネガポジ度を三次元円グラフで描画する
▼サンプルスクリプト

```R:R
# 単語感情極性表に含まれるものを抽出します
war2007 <- subset(war2007,Term %in% sowdic2$term)
# 単語感情極性表の属性をマージします
war2007 <- merge(war2007,sowdic2,by.x=c("Term","Info1"),by.y=c("term","pos"))
# キーワード毎にスコア算出します
score2007 <- war2007[4:(ncol(war2007)-1)]*war2007$value
# 描画用データを作成します
war2007 <-c(sum(score2007 > 0),sum(score2007 < 0))
# 描画用ラベルを作成します
lbls <- c("positive", "negative")
lbls <- paste(lbls, war2007, sep="：")
# 三次元円グラフを描画します
pie3D(war2007, radius=0.9, labels=lbls, explode=0.1, main="2007年 週報ネガポジ度")
```

▼実行結果例
上記のサンプルコードは、2007年度の1年分をグラフ化したものです。これを2014年度分まで出力したものが次のグラフになります。
![image](https://qiita-image-store.s3.amazonaws.com/0/106773/7951aa4f-28d9-b453-3c7c-dd4f015c7ad9.png)

# 注釈
注1 今回の分析で利用させて頂いた、単語感情極性対応表はこちら↓
http://www.lr.pi.titech.ac.jp/~takamura/pndic_ja.html
git push引数省略時のデフォルト動作設定



先日、vimの設定ファイルをgithubに上げるべく
コミットした内容をおもむろに以下のコマンドでpushしました。

```git
$ git push
```

するとなにやら怪しげなメッセージが。

```git
warning: push.default is unset; its implicit value has changed in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the traditional behavior, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple
・
・
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master
```

Git2.0からpush.defaultの設定が`matching`から`simple`が変わりました。今までの振る舞いでいきたいなら`matching`。新しい振る舞いで行きたいなら`simple`と設定してね。  

push.defaultってなんですか。そしてgit pushの引数省略時って
何をどこにpushしているんだろう。。ちゃんと理解していなかった。  

git pushの引数省略時にどのように振る舞うのかの設定がpush.defaultだそうです。
その設定値について整理してみたいと思います。  

# push.defaultの設定

|設定値|説明|
|:--|:--|
|nothing|デフォルト設定なし。push先とpush対象ブランチを必ず指定しなければならない|
|matching|リモートブランチと同名のローカルのブランチをすべてpush(カレントブランチ以外も)|
|upstream|カレントブランチへ追跡ブランチ設定されている場合に追跡ブランチにpush|
|simple|**現行バージョンのデフォルト**。カレントブランチへ追跡ブランチ設定されているかつ、ローカルとリモートのブランチ名が同じである場合に、追跡ブランチに対して push|
|current|カレントブランチと同名のリモートブランチがある場合、そこへpush|

Git2.0のデフォルト設定であるsimpleが一番安全。  
ただし、追跡ブランチを設定しておかないと本記事冒頭のsimpleモードの場合、追跡ブランチを設定してくださいメッセージが出力される。  

# 追跡ブランチとは？
リモートブランチと直接のつながりを持つローカルブランチのこと。  

## 追跡ブランチを設定すると何が嬉しいのか？

- push.defaultの'upstream'、'simple'においてpushできる
- git statusしたときにahead, behind(push先からコミットが進んでいるか、後退しているか)を数えてくれる
- git push で引数を省略できる

# 追跡ブランチが作成されるタイミング
- リモートブランチからローカルブランチにチェックアウト
- リポジトリをクローン時

具体的には以下

```bash
# ローカルブランチ作成時(リモートブランチからローカルブランチにチェックアウト)
$ git branch -b [branch]

# リポジトリをクローン時
$ git clone path/to/shared_repo.git work

# リモートブランチ作成時 
$ git push -u origin hogehoge

# 既に存在するブランチに設定(カレントブランチに設定する)
$ git branch -u origin/hogehoge

# 既に存在するブランチに設定(カレントブランチ以外に設定する)
$ git branch -u origin/hogehoge hogehoge
```
# まとめ
- git push引数省略時のデフォルト設定は push.defaultで決まる。
- git 2.0ではsimpleがデフォルト設定。
- simpleは同名ブランチが存在し、かつ追跡ブランチがある場合にpushできる。安全！
- 追跡ブランチはローカルブランチをリモートブランチに紐づけるローカルブランチ

# 参考URL
[git の push.default 設定を理解する](http://qiita.com/misopeso/items/ede49b661cc7ad30528a)
[git push -u オプションの意味](http://qiita.com/ironsand/items/6c301fef730d53f35bc3)
[3.5 Git のブランチ機能 - リモートブランチ](https://git-scm.com/book/ja/v1/Git-%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E6%A9%9F%E8%83%BD-%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81)
RxJS 4 から 5 での変更点

この記事は [bouzuya's RxJS Advent Calendar 2015](http://www.adventar.org/calendars/1200) 24 日目かつ RxJS Advent Calendar 2015 の 24 日目です。

# はじめに

今日は [RxJS 4 から 5 への移行](https://github.com/ReactiveX/RxJS/blob/5.0.0-beta.0/MIGRATION.md) のドキュメントから抜粋して書きます。

# RxJS 5

ここまで RxJS 4 (v4.0.7) を対象に書いてきました。

RxJS 4 は [Reactive-Extensions/RxJS](https://github.com/Reactive-Extensions/RxJS) でしたが、 RxJS 5 は [ReactiveX/RxJS](https://github.com/ReactiveX/RxJS) で開発が進められています。2015-12-24 時点では 5.0.0-beta.0 です。

## JavaScript から TypeScript へ

RxJS 4 が独自の module (concat) を使った JavaScript で書かれていたのに対して、RxJS 5 は ES6 module style の TypeScript で書かれています。RxJS 4 にも `*.d.ts` は配置されていましたが JavaScript で書かれていました。 RxJS 5 では TypeScript で書かれています。

標準的な module 構造ですし型情報のおかげで読みやすくなっています。

## Observer の method 名

`Observer` にあった `onNext` / `onError` / `onCompleted` は `next` / `error` / `completed` に変更されました。ES7 Observable の仕様に合わせたものです。おそらく `onNext` を明示的に呼び出すのは不格好だからでしょう。

## Disposable → Subscription

`Disposable` は `Subscription` になり、`dispose()` は `unsubscribe()` になりました。以前から `class Subscription implements Disposable` のつもりだったかもしれません。`subscribe` との対応は `unsubscribe` のほうがずっと良いでしょう。

`Subscription` は `CompositeDisposable` と同等の `add()` / `remove()` を持ちます。`add` された `Subscription` は `unsubscribe` の際に合わせて `unsubscribe` されます。

## Operator の rename や split

`flatMap` に `mergeMap` という alias が追加されたほか、Operator の変更や分割や削除などが入っています。140 個近くあった operator は 90 個近くまで削減されています。一部を分割してこの数なので相当な削減です。

今回の Advent Calendar で紹介したものも、一部は削除されています。

## Scheduler の rename

`Scheduler` の名前が JavaScript における実装に適した形に変更されています。

- `Scheduler.default` → `Scheduler.asap`
- `Scheduler.currentThread` → `Scheduler.queue`
- `Scheduler.immediate` → `undefined`

# おわりに

今日は RxJS 4 から 5 への移行を見ていきました。時期的に微妙だったので今回は 4.0.7 にしたのですが、RxJS 5 系の方がずっと簡潔ですし読みやすいと思います。

すこし後悔しています。
QiitaにGiphyのアニメーションGIFを簡単に埋め込むChrome拡張作ったよ

皆さん真面目に開発やってますか？

あ、そ～言えば、今日はクリスマスイブですね。ワタシはビールを飲みながらQiitaを書いてます。

真面目に開発やってるばかりだと息が詰まってしまいますよね。

だから、ちょいちょいユーモアを挟んでいくことって意外と大切ですよね。

そんなユーモアを差し挟むのにうってつけなのが、アニメーションGIFです。

![](http://media1.giphy.com/media/ytwDCq9aT3cgEyyYVO/200w.gif)
source www.giphy.com

そんな時によく使うのがアニメーションGIFの共有サービスの[Giphy](http://giphy.com/)です。Giphyでは沢山のアニメーションGIFが共有されています。

↑の画像は http://giphy.com/gifs/birthday-dancing-beer-birthday-bot-ytwDCq9aT3cgEyyYVO にて公開されており、iframe等で他サービスに埋め込むことが出来ます。

ただ、Qiitaの場合は（Qiita:Teamを除いて）iframeを埋め込めないので、画像を使おうとした場合に、画像をコピーしてアップロードするか、画像URLをコピーしてマークダウンとして記述する必要があります。

というのも煩わしいので、GiphyAPIを利用して、画像を検索して、markdownとしてコピーするためのChrome拡張 [bananaumai/giphy2markdown](https://github.com/bananaumai/giphy2markdown)  を作りました。

こんな感じで使えます。

![](https://media.giphy.com/media/aZ4tiolaBuiqc/giphy.gif)

Markdownとしてコピーする他に、一覧画像から画像を簡単にコピーすることも出来ます。

ちなみに、その後、Giphyの公式Chrome拡張がChrome Web Storeで販売されているということに気が付いたのですが（汗）、Markdownとしてコピーする機能はないようでしたｗ

アニメーションGIFを普段使いしたい方は、[bananaumai/giphy2markdown](https://github.com/bananaumai/giphy2markdown) からExtensionをダウンロードして使ってみてください！

![](https://media1.giphy.com/media/OJp5pne69OeY/200w.gif)
source www.giphy.com
slimで制御文を扱うには(rails)

最近、社内ではerbをslimに書き換えたほうがバグも減るし、楽！ということでちょっとずつ書き換わっているのですが、ここで思わぬところで詰まったのでメモしておきます。

##はじめに
まず基本をおさらいしておきます。

```
<!DOCTYPE html>
<html>
<head>
  <title>SlimTest</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<header id="header">
  <h1 class="title logo">Slim Test</h1>
</header>

<%= yield %>

<% if @user.present? %>
  <%= link_to @user.name + 'を見てみる', profile_path(user_id: @user.id),{class:'hogemoge'} %>
<% end %>

</body>
</html>
```
ってのは

```
doctype html
html
  head
    title SlimTest
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true
    = javascript_include_tag 'application', 'data-turbolinks-track' => true
    = csrf_meta_tags

  body

    header#header
      h1.title.logo Slim Test

    == yield

    - if @user.present?
      = link_to @user.name + 'を見てみる', profile_path(user_id: @user.id),{class:'hogemoge'}

```

と記述することができます。ここまではなんとなーくかけると思います。
ここで、一瞬？となる可能性が高いlink_toの書き方も一緒にのっけました！


##制御文を使うには
ここで変数を扱ってみます。

```
  - if action_name == 'hoge'
    span.abcd
      = profile(@user)
  
  .btn_list  class="#{'dnone' if action_name == 'hogemoge'}"
    - if action_name == 'edit'
      = render_list_btn(user, "profile").html_safe
    - else
      = render partial: '/user/profile_for_list', locals: { user: user }

```

となります。さて、これのどこでつまったのかというと

```
class="#{'dnone' if action_name == 'hogemoge'}"
```

ここの部分！
erbで記述すると

```
class=<%= "dnone" if action_name == 'hogemoge' %>
```
と、こんな風になると思います。

なので普通に考えると

```
class="dnone" = if action_name == 'hogemoge'
```
とかでいけるのかなーと思いましたがエラー。
先ほどのような書き方で無事解決することができました。
golang は多値返却できるが、いくつまで可能なのかな？

golang の関数は多値返却可能なので、関数の返り値を _, err などで受けることができて便利ですが

いくつまで多値返却できるのかな？ (go のソースを読んだりはしません)

https://play.golang.org/ だと share でエラーになったので github にあげました

https://github.com/sheercat/hugereturn/blob/master/main.go

10000 まではいけた。もっといけそうだ!

それだけです。。。

✧＼\ ٩( 'ω' )و /／✧
rspec2からrspec3で変わったこと

- 詳細出すときのオプション-fs　が-fdになった

```
be rspec -fd spec/models/hoge_spec.rb
```

- 実行行指定の--line 行数　が:行数になった

```
be rspec -fd spec/models/hoge_spec.rb:30
```

- 何のテストか判別したいときは、spec/spec_helper.rbに↓入れる

```
config.infer_spec_type_from_file_location!
```

- それぞれのspecファイルのrequire 'spec_helper'を変更する。変えなくても動いたんだけど変える必要ないのかな？
 -  調べてみると変えなくても大丈夫。[変える場合は先にお引越しが必要なようだ](http://qiita.com/y_minowa/items/4b7f32eff7dd2547f188)。[変えた理由](http://qiita.com/izumin5210/items/1375199226b5084c3c9a#rails_helperrb%E3%81%A8spec_helperrb%E3%81%AE%E9%81%95%E3%81%84)

```
require 'rails_helper'
```

- spec_helper.rb or rails_helper.rbの中身↓

### `expectations.include_chain_clauses_in_custom_matcher_descriptions = true`
* カスタムマッチャチェインにdescription出すときに[必要](http://qiita.com/haracane/items/4f56c8e4a1b71d1d64f6#2-8)

### `mocks.verify_partial_doubles = true`
* [コメントアウトでいいみたい。](http://spring-mt.hatenablog.com/entry/2014/06/02/183439)

### `config.filter_run :focus`
* Guardとか使う場合に[必要みたい](http://labs.timedia.co.jp/2013/03/rspec.html)

### `config.disable_monkey_patching!`
* モンキーパッチを無効にしたい[場合使う](http://qiita.com/yusabana/items/db44b81bdddf6ed0e9f5)

### `config.order = :random`
* テストを[ランダムに実行したい場合につかうらしい](http://tbpgr.hatenablog.com/entry/20140422/1398170857)
Powershellでサービスを作れるようにしてみた

Powershellでサービスを作れるようにしてみました。

https://github.com/stofu1234/PowerPuppet

# 何に使うか・どのように使うか
WindowsにはLinuxのデーモンスクリプトに相当する仕組みがないため、
LinuxのOSSをWindowsに移植して、無事ビルドが出来ても、サービスの実装がなく、
プロセスを直起動させて無理やり常駐させている事例が多々あります。

PowerPuppetを使うとこのようなOSSソフトにも自動起動の機能等をPowershellというインタプリタのシェル言語をつかって柔軟に付け加えることができます。

Powershellはシェル言語なため、プロセスのロギング、ファイルの後始末、子プロセスも含めたプロセス監視等インフラ観点のロジックをC#よりも簡易的に記述できます。

GitHubのReadmeにFileSystemWatcherと組み合わせる使い方を想定していると書きましたが、
このFileSystemWatcherも結構癖があるみたいで、挙動を見て細かいロジック修正が必要、
そうなるとインタプリタでシェルというPowershellと相性がいいと思い、想定使用例に挙げました。

# 導入手順
0. PowerPuppetをgit cloneでとってきます

git clone https://github.com/stofu1234/PowerPuppet

1. プロジェクトをビルドし、PowerPuppet.exeを作成します

MSBuild.exe /property:Configuration=Release PowerPuppet.csproj

（MSBuild.exeは<windir>\Microsoft.NET\Framework[|64]\v*.*.*****にあります）

2.PowerPuppet.exeを任意の名前にリネームします

例） PowerPuppet.exe → nginx_service.exe

3.同名の.ps1ファイルを用意します

例） nginx_service.ps1

4.InstallUtil.exeでリネームしたexeを登録します

例） InstallUtil.exe nginx_service.exe

（InstallUtil.exeは<windir>\Microsoft.NET\Framework[|64]\v*.*.*****にあります）

gituhub上のsamplecfgフォルダに以下のサンプルps1があります

nginx_service.ps1 →　Nginx用サンプルps1
node_service.ps1 →　Node.js用サンプルps1

サンプルps1を参考に、各種アプリ用のps1を作ってください。

5.サービスが登録されました。
![service.png](https://qiita-image-store.s3.amazonaws.com/0/58259/1a9257b2-ca27-5554-7c14-84295fb5b24c.png)

# 自動起動（start・stop）以外のロジックどう実装すればいい？
OnStart、OnStopというサービスAPIに呼ばれる以外のメソッドを定義し、コマンドラインパラメータによってそれぞれのメソッドが呼び出されるようにすればいいと思います。
Raspberry Pi でLAMP環境を構築する

Rapverry Pi に最低限のLAMP環境を構築してみます。
## 0. 環境
### 0-1. OS
- Raspbian GNU/Linux 8

### 0-2. 導入内容
- Apache2
- mod_php5
- MySQL

### 0-3. ssh接続
```bash
$ ssh pi@< IP address >
```

## 1. Apach2について
### 1-1. apache2のインストール
```bash
$ sudo apt-get install apache2
```

### 1-2. 設定
#### mode_rewriteを有効化
```bash
$ sudo a2enmod rewrite
```

##### mode_rewriteに関する参考リンク
[Apacheのmod_rewriteモジュールの使い方を徹底的に解説](http://oxynotes.com/?p=7392)



※ `en2enmod` はシェルスクリプトらしいです。
`/usr/sbin/a2enmod` にインストールされているのでスクリプトを読めば使い方はわかるはず。


#### htaccessを有効化
```bash
# 下記を修正する
$ sudo vi /etc/apache2/apache2.conf

# AllowOverride を None から All へ
<Directory /var/www/>
  Options Indexes FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>
```
![スクリーンショット 2015-12-24 18.53.52.png](https://qiita-image-store.s3.amazonaws.com/0/87650/d8cd4e0f-7400-426f-155d-93cae3eec2f1.png)


##### htaccessに関する参考リンク
[.htaccessの書き方](https://murashun.jp/blog/20141229-01.html#chapter-1)



### 1-3. ドキュメントルートの指定
```bash
$ sudo vi /etc/apache2/sites-available/000-default.conf

# 下記に設定
DocumentRoot /var/www/
```

### 

### 1-4. 再起動する

```bash
$ sudo service apache2 restart
```

### 1-5. 動作確認  
![スクリーンショット 2015-12-24 5.56.05.png](https://qiita-image-store.s3.amazonaws.com/0/87650/450ec3df-16c8-7542-e6bd-f2870a74f204.png)



## 2, MySQLについて
### 2-1, インストール
```bash
$ sudo apt-get install mysql-server
```

### 2-2. 文字コード設定
```bash
# 設定ファイルを変更
$ sudo vi /etc/mysql/my.conf

# 設定ファイルに以下を追加
[mysqld]
character-set-server=utf8 # デフォルトの文字コードをutf-8
skip-character-set-client-handshake # クライアントのリクエストが何であれutf-8で返す
```

### 2-3. ユーザー設定
```bash
$ mysql -u root # rootで起動

# root のセキュリティ設定
mysql > DELETE FROM mysql.user WHERE user = "" OR host = "::1";
mysql > SET PASSWORD FOR root@localhost = PASSWORD("password");
mysql > SET PASSWORD FOR root@127.0.0.1 = PASSWORD("password");
# 新規ユーザーの追加
mysql > GRANT ALL PRIVILEGES ON db.* TO user@localhost IDENTIFIED BY "password";
```

## 3 php5について
### 3-1. mod_phpをインストール
```bash
$ sudo apt-get install libapache2-mod-php5
```

### 3-2. MySQLモジュールの追加
```bash
$ sudo apt-get install php5-mysql
```

### 3-3. 動作確認
```bash
# phpファイルに変更
$ sudo mv /var/www/index.html /var/www/index.php

# 書き換え
$ sudo vi /var/www/index.php

<? php
phpinfo();
```
![スクリーンショット 2015-12-24 20.06.30.png](https://qiita-image-store.s3.amazonaws.com/0/87650/13471de7-d944-21ad-2a58-6d0bafff8db0.png)


以上で基本的な設定が完了しました。
参考になるサイトは多いですが、versionやOSが異なるとconfファイルの場所が違ったりするので、自分の場合を把握するのが面倒くさいですね。
以上！
スマホアプリのテストを Appium でやることにした話

[この投稿は Sansan Advent Calendar 2015 の 22 日目の記事です。](http://qiita.com/advent-calendar/2015/sansan)

## みなさんテスト書いてますか？

テスト書くの面倒ですよね。
UI テストは特に面倒なことが多いと思います。

iOS アプリの UI テストを KIF → Appium に乗り換えた(ている)ので、その話を書きたいと思います。 
それぞれのテストフレームワークについては詳しく説明しておりませんので、ご了承ください。

## テストでやりたいこと << KIF でできること だった

[KIF](https://github.com/kif-framework/KIF) は以下の様な特徴を持った UI テストフレームワークです。

- Objective-C/Swift でテストコードを書ける
- Xcode からテストを実行できる
- プロジェクト内にテストコードを書くので、Mock, Stub 等の別ライブラリとの相性が良い(参考: [KIFとNLTHTTPStubServerを利用して最低限のIntegrationTestを実現する](http://qiita.com/okitsutakatomo/items/c06c1450f1697382e802))

Stub を用いて、通信結果を差し替えることで複雑なテストパターンを再現可能であることや、既存コードとの親和性が高いということが、KIF を選定した理由です。
ただ初めは意気揚々とテストコードを書いていけたのですが

- テスト対象のアプリが Android にも展開しているアプリであったことから、双方で同じテスト書くのがもったいない
- テストコード量が大きかったので、画面改修/仕様変更により通らなくなるテストパターンが出てきて辛くなった

といった理由から、より費用対効果の高い方法はないか模索し始めました。

## そして Appium へ

UI テストを再度書いていくに当たり、まずメンテナンスコストが低く、効果が高い箇所をテスト対象に絞ることにしました。そのうえで、Android とテストを共通にすることができる Appium でテストを書き直すこと。

[Appium](http://appium.io/) は以下の様な特徴を持ったテスト自動化フレームワークです。

- [Ruby, JavaScript, Python といった様々な言語で書ける](https://github.com/appium/appium/blob/master/docs/en/about-appium/appium-clients.md)
- プロジェクト内にコードを追加する必要がない
- iOS/Android 双方のアプリのテストコードを共通化できる

KIF と比べてプロジェクト内のコードを参照できないため、テストできることはシンプルですが、最低限確かめたいことには十分であったことと、なにより Android とテストが共通化できることのメリットが大きかったため、Appium を採用しています。

## まとめ

何をテストしたいのか、テストの目的は何かをチームで話し合い、目的にあったフレームワークを選定できると良いですね。
LA* -- A* with Lookahead


しばらく非最適探索ばっかりやって来ましたが、ちょっと最適探索に戻ります。
(昨日の記事は夜中1時過ぎに投稿しました。[見逃してませんか?](http://qiita.com/guicho271828/items/16c6390894f89f677ba4))

A* with Lookahead とは、A* のノード展開に **数歩** の Depth First Lookahead (*先読み*) を追加することで性能を高めるという手法です。

# Search Algorithm Triangle

今までIDA*, A*, EHC と色々なアルゴリズムを見てきましたが、これらのアルゴリズムは次のような図に抽象的に表すことが出来ます(Pearl 1984 より)。横軸$R$は **やり直しが効く意思決定** の割合、縦軸$S$は **可能な選択肢のうち実際に検証される選択肢** の割合を指します。右上の BestFirstは、 グラフ探索では**$A^＊$**に相当します。また、Backtrackingは IDA*に相当します。Hill climbing はそのまま山登り法です。

なお、Pearl 1984 というのは、2011 年にチューリング賞を受賞したJudea Pearlが書いた探索の教科書です。

![aa](https://www.dropbox.com/s/yw90kectlykokr7/triangle.png?raw=1)

Pearl 1984 では、これらのスペクトラムの中間に位置する様々な **ハイブリッドアルゴリズム** の可能性に言及しています。たとえば、BF-BT (BestFirst - BackTracking) の例として、下のような図を描いています。

![](https://www.dropbox.com/s/qne7r6z9gt0had1/bf-bt.png?raw=1)

![](https://www.dropbox.com/s/bofghryg05a7k8v/bf-bt2.png?raw=1)

# A* with Lookahead

<sub>Stern, R. T., Kulberis, T., Felner, A., & Holte, R. (2010, March). Using Lookaheads with Optimal Best-First Search. In Twenty-Fourth AAAI Conference on Artificial Intelligence.</sub>

A* with Lookahead, $LA^＊$ は、上の2.12(a) に似たアルゴリズムです。A*でノードを展開したするたびに、そのノードから深さに制限を設けたDFS を行います。

DFS中にゴールが見つかった場合、最適性を担保するためには、アルゴリズムをそこで終了させることが出来ません。よりコストの低いゴールノードがあるかもしれないからです。そこで、DFSがゴールを見つけた場合、それより$f$ 値の低いノードを全部調べる必要があります。

![](https://www.dropbox.com/s/xrpk5fik3s3b429/lookahead-results.png?raw=1)


このとき、見つかった非最適解の$f$値を**上界**とする枝刈りができるので、A*よりも早く探索を終えられる可能性があります。上の実験結果からは、AL* がA*よりも素早く最適解を見つけていることがわかります。このように、非最適な解にも、最適解を探すための上界を得るという大切な役割があります。この考え方は、Depth-First Branch and Bound (DF-BnB, Korf 1993) で出された考え方です。

また、AL*をBPMX を組み合わせると、Inconsistentなヒューリスティクスを用いた時に A*よりもさらに高速化することが論文では示されています。

# まとめ

A*, IDA*, HC のハイブリッドアルゴリズムの可能性、そしてその1つであるAL* について紹介しました。
Kinect v2 基本まとめノート




#1 お世話になってるページや本

▪︎Microsoft Kinect v2まとめ
http://www.naturalsoftware.jp/entry/2015/08/10/120012

▪︎Kinect for Windows v2入門―C++プログラマー向け連載
http://www.buildinsider.net/small/kinectv2cpp

▪︎[KINECT for Windows SDKプログラミング Kinect for Windows v2センサー対応版](http://www.amazon.co.jp/KINECT-Windows-SDK%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Kinect-v2%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC%E5%AF%BE%E5%BF%9C%E7%89%88-ebook/dp/B00XXC5FR0/ref=pd_sim_351_1?ie=UTF8&dpID=51Rl4mIaB-L&dpSrc=sims&preST=_AC_UL160_SR124%2C160_&refRID=1VBE9Z5T9RWYGSP3SSPR")
![51Rl4mIaB-L._AC_UL160_SR124,160_.jpg](https://qiita-image-store.s3.amazonaws.com/0/76843/eb6444f6-6762-3fe1-1c1a-4dfd2a4e1103.jpeg)



#2 スペック整理

|見出し|スペック|
|:-----------|------------:|
|color画像解像度|1920px × 1080px|
|colorフレームレート|30fps 15fps(暗所)|
|Depth画像解像度| 512px × 424px |
|Depthフレームレート| 30fps |
|Depth認識範囲| 0.5m ~ 8m |
|人の検出人数|6人|
|人の骨格検出|6人|
|人の検出範囲|0.5m ~ 4.5m |


#3 データ取得の流れ

SensorからSourceを取得、
SourceからReaderを開き、
ReaderからFrameを取得、
Frameからデータを取得するという流れ。

http://www.buildinsider.net/small/kinectv2cpp/02
のデータを取得する流れ　がわかりやすい。




#3、カラー画像

1920×1080のFull HDの解像度で30fpsで取得。暗所だと15fps。
カラー画像のフォーマット指定可能。
デフォルトはYuy2「Y（輝度）、U(B-Yの色差)、Y（輝度）、U(R-Yの色差)、」でRGBA画像等で欲しい場合はフォーマット指定。

```csharp:hoge
// 例 Bgra形式
ColorImageFormat colorFormat = ColorImageFormat.Bgra;
```

Bgra形式の場合
1ピクセル = 8ビット(1バイト×4)
1ラインは1920個あるので1ラインあたりのバイト数は1920*4



#4 Depthデータ
512×424の解像度、
0.5m ~ 8mの範囲で取得可能
骨格認識は0.5m ~ 4,5m
距離の単位はmm(ミリメートル)

1ピクセルあたり16ビットのデータが512×424個並んでいる。
配列の要素にアクセスすることで任意の座標のdepthデータ取得。
Depthデータには0mm ~ 8000mm のデータが入っている。

```csharp:hoge
var depthText = string.Format("{0}mm", depthBuffer[depthindex]);
```

よくある2次元白黒深度画像は
視覚的にわかりやすいように
8bit（0～255）の範囲に変換して
距離が近いほど白く（255）、遠いほど黒い（0）みたいに
チューニングして表示している。


#5 bodyIndex

512×424の解像度、
最大同時検出数 6人
bodyIndexデータは1ピクセルあたり8ビットのデータが
512×424個並んでいる。
人を検出していない場合は255（0xFF）、
人を検出している場合は0~5のインデックス値
となるので、検出している部分だけ色を塗って視覚化したりする。
Google+のAPIを利用して特定の記事を検索する。

下記のGoogle Libraryを利用してGoogle+の記事を検索してみるお話。
https://developers.google.com/api-client-library/php/?hl=ja
（Beta版なのが気になるところ…）

GoogleサービスのAPIキーはGoogle Developers Consoleで取得ができます。

# Googleの各サービスで共通で利用できるのでClientの取得は切り分けておくと便利。
```
<?php namespace Lib;
/**
 * Google関連
 *
 * ライブラリ
 *   https://developers.google.com/api-client-library/php/
 */

use Google_Client;

class GoogleManager 
{

	private $__client  = null;
	private $__api_key = 'xxxxxxxxxxxxxxx';

	/**
	 * client
	 */
	protected function _getClient()
	{
		if (is_null($this->__client))
		{
			$this->__client = new Google_Client();
			$this->__client->setDeveloperKey($this->__api_key);
		}
		return $this->__client;
	}

}
```

# Google+のAPIを利用するためのサービス登録などの準備
```
<?php namespace Lib;
/**
 * GooglePlus関連
 *
 * GooglePlus公式
 *   https://developers.google.com/+/web/api/rest/
 */

use Google_Service_Plus;
use Google_Service_Exception;

class GooglePlusManager extends GoogleManager
{

	private $__service = null;

	/**
	 * GooglePlusのサービス登録
	 */
	private function __getService()
	{
		if (is_null($this->__service))
		{
			$this->__service = new Google_Service_Plus($this->_getClient());
		}
		return $this->__service;
	}

	/**
	 * 指定した条件でアクティビティを検索
	 *  https://developers.google.com/+/web/api/rest/latest/activities/search
	 */
	public function searchActivities($str, $options=[])
	{
		$plus = $this->__getService();
		try {
			return $plus->activities->search($str, $options);
		} catch (Google_Service_Exception $e) {
//			echo $e->getMessage();
			return false;
		}
	}
}
```

# 実際に利用して内容を取得してみる
```
	public function sample()
	{
		$res = GooglePlusManager::searchActivities("{$u}", [
			'language'   => 'ja',
			'maxResults' => 20,
			'orderBy'    => 'best',
		]);
		if (!$res)
		{
			exit;
		}
		print_r($res['item']['content']);
		exit;
	}
```
GooglePlusManager::searchActivities('hoge')で記事検索ができ、
検索結果には$array['items']でアクセスできる。
AWS SDKを利用してオートスケールの操作をする。

メール送信時やPushを送る直前にインスタンスを増やしたい時など、特典の条件下でAutoScalingのポリシーを実行する。定期処理だけでなく、不定期な処理時でも利用可能なようにカスタマイズ。

あらかじめ、awsのコンソールでインスタンスの起動用、削除用のポリシーを作成しておく。

# AutoScalingを操作するためのクラスを作成
```php:/app/lib/aws/AutoScaling.php
<?php namespace Lib\Aws;

use Aws\Common\Aws;
use Aws\Common\Enum\Region;
use Aws\Ec2\AutoScalingClient;
use Aws\Ec2\Exception\AutoScalingException;

class AutoScaling
{

	private $obj = null;

	/**
	 * AWS SDK for PHP
	 * auto-scaling instance
	 */
	private function getInstance()
	{
		if (is_null($this->obj))
		{
			$this->obj = Aws::factory([
				'key'    => XXXXXXXXXXXXXX,
				'secret' => XXXXXXXXXXXXXXXXXXXX,
				'region' => Region::XXXXXXX
			])->get('AutoScaling');
		}
		return $this->obj;
	}

	/**
	 * AutoScalingのインスタンス状況取得
	 */
	public function describeAutoScalingInstances()
	{
		$res = $this->getInstance()->describeAutoScalingInstances();
		$list = [];
		foreach ($res['AutoScalingInstances'] as $instances)
		{
			$list[$instances['AutoScalingGroupName']][] = $instances;
		}
		return $list;
	}

	/**
	 * 指定したAutoScalingグループ名のもののみ
	 */
	public function getListByGroupName($name)
	{
		return empty($this->describeAutoScalingInstances()[$name]) ? [] : $this->describeAutoScalingInstances()[$name];
	}

	/**
	 * AutoScalingのポリシーを送信
	 *  @param $group:実行したいポリシーが属するAutoScalingGroup
	 *  @param $policy:実行したいポリシー
	 */
	public function excutePolicy($group, $policy)
	{
		try {
			$res = $this->getInstance()->executePolicy([
				'AutoScalingGroupName' => $group,
				'PolicyName'           => $policy,
				'HonorCooldown'        => false,
			]);
		} catch (AutoScalingException $e) {
//			echo $e->getMessage();
			return false;
		}
		return true;
	}
}
```
AutoScaling::excutePolicyを実行するとAutoScalingにポリシーを送信することができるので、定期処理や管理画面から実行するトリガーを設定すれば、簡単に任意のタイミングでインスタンスの増減を実現することができる。

起動中のインスタンスを取得することもできるので、起動中のインスタンスがないことを確認してからインスタンスを起動する、というようなことも可能。

# プログラム例
```
	public function execAutoScaling()
	{
		// 起動中の該当のASのインスタンスを取得
		$instances = AutoScaling::getListByGroupName('xxxxxx');

		// インスタンスを起動する条件を設定
		if (hoge)
		{
			// 起動しているASのインスタンスがなければ起動
			if (empty($instances))
			{
				if (!AutoScaling::excutePolicy(_AUTO_SCALING_GROUP_BATCH, _AUTO_SCALING_POLICY_ADD_2))
				{
					$this->_error('Instance boot error.');
				}
			}
		}
		// インスタンスを停止する条件を設定
		elseif (huga)
		{
			// 起動しているASのインスタンスがあれば停止
			if (!empty($instances))
			{
				if (!AutoScaling::excutePolicy(_AUTO_SCALING_GROUP_BATCH, _AUTO_SCALING_POLICY_DEL_2))
				{
					$this->_error('Instance stop error.');
				}
			}
		}
	}
```
grunt内でgulpを使う

# gruntから徐々にgulpを使っていきたい時など

```text:シナリオ
gulpでないと面倒な事象に行き当たり、どうしてもgruntからgulpに
乗り換える必要がでてきた。
しかしgruntファイルが肥大化しているので、全部書き換えるのも面倒だ。

最初はGruntfileの他にgulpfileも用意して併用すればいいかと考えたが、
gruntのタスクABCとgulpのタスクXYZを一緒に使いたかった。
```

この場合

1. grunt内でgulpを呼び出す
2. gulp内でgruntを呼び出す

の2択があるが、既存のフローがgruntだという理由で今回は1を選択。


# grunt内でgulpを呼び出す

gulpfile側は

```coffeescript:gulpfile.coffee
gulp = require 'gulp'

gulp.task 'ABC', ->
    # do something

module.exports = gulp # ここだけ追加!
```

Gruntfile側は

```coffeescript:Gruntfile.coffee
require('coffee-script/register') # 最新のCoffeeScript使いたい

module.exports = (grunt) ->

    grunt.registerTask 'gulp-ABC', ->

        require('./gulpfile').start('ABC', @async())

    grunt.registerTask 'ABC-XYZ',   ['gulp-ABC', 'XYZ'] # XYZはどこかに定義されてる別タスク
```

もちろん.coffeeでなく.jsでもいい。

## 解説
gulpは`gulp.start()`で呼び出せるので、requireした後それを呼んであげればよい。
requireできるようにexportsすればそれでOK。

`@async()`は、gruntタスク終了時のコールバック関数を返すもの。
これをgulp.start()の最後の引数に渡すと、gulpタスク終了時にこの関数が実行されてうまい具合にいく。

`require('coffee-script/register')`は、
CoffeeScriptでGruntfileを書いてるとき限定の話で、そうでなければ無視していただいてOKだが、
小話として聞いてほしい。

[gruntのcoffeescriptが古すぎる問題](https://github.com/gruntjs/grunt/pull/1331)というのがあって、これのせいで、

```coffeescript
gulp.src './xxx'
    .pipe yyy()
```
このメソッドチェーンができない。
なのでgruntコマンドから`require('./gulpfile')`したときのrequireを、
新しいCoffeeScriptのrequireにしてあげないといけない、という理由で
`require('coffee-script/register')`と書いた。


# ログを出す
ログを出す部分のコードはgulpの `bin/gulp.js`に書かれているので、上記の方法だと厳しい。
それはしょうがないとしよう。
Boost.RangeのOven拡張を自作してみる

この記事は [C++ Advent Calendar 2015](http://www.adventar.org/calendars/926) の24日目の記事です。

最近の仕事ではもっぱらPHPばかり書いてますが、C++も触れていたいなーという事で参加しました。

# 前書き

既存のライブラリとして[PStade.Oven](http://p-stade.sourceforge.net/oven/doc/html/index.html)や高橋晶さんの[Boost.Range拡張ライブラリ](https://github.com/faithandbrave/OvenToBoost)がありますが、もっとシンプルで、アプリ毎の専用関数として使いたい、という理由と自分の勉強がてらに作成しています。

[GitHubへのリンク](https://github.com/wordijp/boost.range-oven-custom)

# 使い方

```cpp
#include "range.h"

auto v = {1, 2, 3, 4, 5};
// {2, 4}
auto q = v | range::filtered_even();
```

BoostのRange Adaptorsと同じくパイプラインによって繋げます。

(面倒な為、既存のboost::adaptorsライブラリをrange::で使えるようにnamespace内で
```
using namespace boost::adaptors;
```
しています)

# パイプライン記法で書けるように実装するには

パイプライン記法を使えるようにするには、operator|を糊付けとして、Range値(配列に限らない、begin()とend()を実装した範囲を表す値)と、Range値から新たなRange値を返す実装をする必要があります。

```cpp
// Rangeから要素の型を得る
template <class Range>
auto _rangetype(Range&& r) ->
	typename std::decay<
		decltype(*std::begin(r))
	>::type;
// 配列要素の型取得
#define rangedecltype(r) decltype(_rangetype(r))

namespace range {
	//------------------------------
	/// INTERNAL ONLY
	/// 
	// {
		struct _FilteredEvenHolder {};
		
		template <typename T>
		struct _is_even {
			bool operator()(const T &t) const {
				return t % 2 == 0;
			}
		};
	// }

	_FilteredEvenHolder filtered_even() { return _FilteredEvenHolder(); }

	template <typename Range>
	auto operator| (Range &r, const _FilteredEvenHolder &)
	{
		return r | boost::adaptors::filtered(_is_even<rangedecltype(r)>());
	}

	template <typename Range>
	auto operator| (const Range &r, const _FilteredEvenHolder &)
	{
		return r | boost::adaptors::filtered(_is_even<rangedecltype(r)>());
	}
}
```

Boost.Range.Adaptorsのfilteredを特殊化している為filteredを利用していますが、boost::iterator_rangeを返すようにfilterdに当たる部分を自作も出来ます。

この形を基本形として、Range操作関係を全部range::hogeで済ませられるようにアプリライブラリを用意しておけば、実装時も読む時もシンプルに出来るんじゃないかな、という紹介でした。

# range.hに始まる各ライブラリについて

作成の際にBoostのRangeの実装、PStade.Ovenの実装を多分に参考にしています。
2年程前に書いたC++11 & boost 1.49環境の当時のコードのままとなっていますが、今回のC++14 & boost 1.60の環境でも動作しました。

注意して作成してはいますが、何か問題がありましたらご報告をお願いします。

## range::sorted・range::stable_sortedについて

これはかなり実験的な実装となっており、実装方法はPStade.Ovenのoven::sortedと同じなのですが、boost::iterator_range生成時にもととなるRangeをshared_ptrで保持する為、高コストな処理になっています、面倒ではありますが、一端vector化し、std::sortをした方が高速です。

# まとめ

この記事は、 [C++ Advent Calendar 2015](http://www.adventar.org/calendars/926) の24日目の記事でした。
明日は、Reputelessさんの記事、「ゲームとメディアアートのための C++ ライブラリ「Siv3D」」です。
CDNでリアルタイム画像処理〜imgixを使ってみた

[前回](http://qiita.com/yamato/items/0782b5c7c370daa1ddda)に続き、使ってみたシリーズです。

# imgixとは

Zebrafish Labs Inc.が運営しているリアルタイム画像処理機能付きのCDNサービスです。
Q&Aによると、主要なレンダーファームはサンフランシスコにあり、北アメリカ、ヨーロッパ、アジア、および太平洋にわたって、数十のエッジノードを持っているそうです。
類似サービスとしては、[Cloudinary](http://cloudinary.com/)が挙げられます(こっちの方が有名ですかね)。


# imgixを使ってみる

## Sourceの設定

アカウントを作ったら、Sourceの設定を行います。
利用するドメインとSource(画像の置き場所)を設定します。
Source TypeはAmazon S3とWeb Folder、Web Proxyから選べます。
Amazon S3を選択した場合はAccess Key、Secret Key等の情報を入力する必要があります。
どうやらAccess Key、Secret Keyを使ってSDKでバケットにアクセスしているらしいので、S3のウェブサイトホスティングは無効にしておいても問題ありませんでした。
IAMのアクセス権限は必要最低限のもの(ListBucket、GetBucketLocation、GetObject)にしておきましょう。

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/9179fa67-d84d-d4a7-806c-64f188d77a66.png)

## 画像処理を試してみる

画像URLにクエリパラメータを与えると画像処理を行った画像が返されます。
基本的なリサイズ以外にも、輝度調整等の加工、マスキング、合成など様々な加工が行えます。
詳しくはリファレンス参照のこと。
https://www.imgix.com/docs/reference

以下、いくつか試してみたやつを載せます。

### 元画像

`Lenna.png`

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/b4f2bc96-0f3e-70a5-9161-29952e374fa9.png)

### リサイズ

`Lenna.png?w=100`

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/ff820611-5da7-08fd-2b5b-8274c8328fda.png)

## クロップ

`Lenna.png?w=200&h=400&fit=crop`

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/22ea0db2-6492-508a-6315-177cc77770d4.png)

## マスキング

`Lenna.png?w=200&h=200&fit=crop&mask=ellipse`

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/07489564-4594-3da9-cd89-2560e0e63c18.png)

## セピア

`Lenna.png?sepia=100`

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/e52ae81c-0449-74d7-06e9-9a2697155fb7.png)

## テキスト合成

`Lenna.png?txt=HELLO%20WORLD!&txtsize=62&txtalign=middle,center`

![image](https://qiita-image-store.s3.amazonaws.com/0/57615/79dcfb40-372d-4c8a-7f4c-8b13c2f19630.png)
ACPI Table


- kernel の num_possible_cpus() の挙動がおかしかったので APIC の認識状態を確認した時にざっと調べた内容
- APIC の情報は RAM 上の ACPI Table に入っており BIOS によって初期化されている

> 16.3.2 BIOS Initialization of Memory
> During a power-on reset, an exit from an S4 sleeping state, or an exit from an S5 soft-off state, the
BIOS needs to initialize memory. This section explains how the BIOS should configure memory for
use by a number of features including:
> • ACPI tables.
> • BIOS memory that wants to be saved across S4 sleeping sessions and should be cached.
> • BIOS memory that does not require saving and should be cached. 
>
> - http://acpi.info/DOWNLOADS/ACPI_5_Errata%20A.pdf

## definition

- ACPI Table はシステム初期化に必要なデータ構造で RAM に置かれている
- 次のような階層関係でデータを参照できる
- RSDP: Root System Description Pointer
	- RSDT: Root System Description Table
	- XSDT: eXtended System Description Table / RSDT の 64bit 版
		- 様々なテーブルへのポインタを持つ
		- FACP: Fiexed ACPI Control Pointer (FADT: Fixed ACPI Description Table)
			- 最も重要なポインタでこれが指すテーブルに含まれる情報は次のようなものがある
			- ACPI ハードウェアレジスタの位置
			− FACS: Firmware ACPI Control Structure
				- 排他制御などにおいて BIOS とのやり取りに使うためのメモリ位置
			- DSDT: Differentiated System Description Table の位置
				- AML: ACPI Machine Language で記述されたシステム情報
				- AML は ASL: ACPI Source Language から生成される
				- 複数個存在する
- DSDT のパースにはオーべヘッドがあるため一部は XSDT のエントリとして置かれる
	- SSDT (SSDT: Secondary System Description Table)
		- デバイス情報
	- APIC (MADT: Multiple Apic Description Table)
		- システム内の APIC 情報
	- その他いろいろ

## disassemble

procfs から参照できる。

- https://wiki.archlinux.org/index.php/DSDT

```
$ ls /sys/firmware/acpi/tables/
APIC  BERT  DMAR  DSDT  dynamic  EINJ  ERST  FACP  FACS  HEST  HPET  MCEJ  MCFG  MSCT  PMCT  PRAD  SLIC  SLIT  SRAT  SSDT1  SSDT2  SSDT3  WD__
```

iasl を用いると ASL に戻せるのでいろいろ中身を見て確かめられる。

```
$ sudo yum install iasl -y
$ sudo cat /sys/firmware/acpi/tables/APIC > apic.dat
$ iasl -d apic.dat
$ less apic.dsl
$ grep 'Processor Enabled' | wc -l
144
```
パツイチでHTTPサーバになったりリバースプロキシになったりする devd

- [devd: a local webserver for developers](https://github.com/cortesi/devd)
- 知ったキッカケ
    - https://twitter.com/mattn_jp/status/657398079688019968
- コマンドパツイチでHTTPサーバになったりリバースプロキシになったりする
- いわゆるライブリロードもいける
- この記事を書いたときのバージョンは 0.3

## インストール方法

Go言語製なので下記からダウンロードしたアーカイブの中身のバイナリをパスの通ったところに置くだけです。

- https://github.com/cortesi/devd/releases/

go get でもビルド＆インストールできます。

```
go get github.com/cortesi/devd/cmd/devd
```

## 簡単な使い方

カレントディレクトリを静的ファイルとして返す Web サーバを起動。

```
devd .
```

`-o` でブラウザを自動起動する。

```
devd -o .
```

`-l` でライブリロードが有効になる。

```
devd -ol .
```

`-w` で監視するディレクトリを指定してライブリロードする（`-l` との違いが良くわからない？ ディレクトリが指定できるかどうかだけでは無さそうだけど？）。

```
devd -ow src/ .
```

リバースプロキシにする。

```
devd -o http://localhost:8888
```

リバースプロキシでかつライブリロードもする（`-l` だとライブリロードが効かなかった）。

```
devd -ow src/ http://localhost:8888
```

`-s` をつければ https になる。

```
devd -os http://localhost:8888
```

## ルートの書き方

↑でプロキシを指定した部分にはルーティングを書くことができます。

ルーティングには下記のようなルートを複数指定できます。`root` はリクエストされたURLで、`endpoint` は解決されるリソースというかエンドポイントというか実体です。

```
root=endpoint
```

root には、`/favicon.ico` のような特定のファイル名か、`/images/` のようなディレクトリ（終端に `/` が必要）を指定することが出来ます。

endpoint にはファイルシステム上のパスや URL を指定できます。

例えば、次のルートだと `/assets/` へのリクエストはカレントディレクトリの `static/` にマップされます。

```
devd /assets/=./static/
```

root が `/` から始まらない場合、最初の `/` まではサブドメインになります。例えば、次のルートだと `http://subdomain.devd.io/images/` がカレントディレクトリの `images/` にマッピングされます。

```
devd subdomain/images/=images/
```

endpoint に URL を指定するとリバースプロキシになります。

例えば、次のルートだと `http://app.devd.io` へのリクエストが `http://localhost:8888` へマッピングされます。

```
devd app/=http://localhost:8888
```

root が省略された場合 `/` になります。つまり、すべてのリクエストにマッチします。なので、下記の例だとすべてのリクエストがカレントディレクトリの `./static` にマップされます。

```
devd ./static
```

また、同様に下記もすべてのリクエストが `http://localhost:8888` に転送されます。

```
devd http://localhost:8888
```

次のように複数を組み合わせて指定できます。

```
devd /=http://localhost:8888 \
  /assets/=./static \
  api=http://localhost:9999
```

## リバースプロキシについて

リバースプロキシは上流の SSL 証明書を検証しません。

上流には転送先の Host ヘッダが渡されます（`devd.io` とかではなく）。元の Host ヘッダ（`devd.io` とか）は `X-Forwarded-Host` ヘッダで上流に渡されます。

## Windows での問題？

Windows で監視ディレクトリを `.` にするとエラーになりました。

```
$ devd -ol .
devd: error: Could not watch routes for livereload: The filename, directory name, or volume label syntax is incorrect.
```

[cortesi/devd #25](https://github.com/cortesi/devd/issues/25)によると Windows 10 では発生しないらしいですけど。

次のように `.\` と指定すればとりあえず大丈夫でした。

```
$ devd -ol .\
20:54:42: Listening on http://devd.io (127.0.0.1:80)
20:54:43: GET /
  <- 200 OK 4.3kB
```

## さいごに

似たようなツールはいろいろあると思います。わたしは [browser-sync](https://www.browsersync.io/) をよく使っていました。が、devd はリバースプロキシとかのルーティングの設定をコマンドラインだけでフレキシブルに書けるのが便利そうです。