OmniAICreator/Qiita-1.07M huggingface dataset:
AOJ 0558 Cheese

　前回のMysterious Wormの復習として、Cheese(http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0558)
という問題を解いてみました。これまた探索で良く出るグリッド系の問題なのですが・・・悔しい限りですがサンプル３が通らない。なぜか無限ループ。もう、自分が上手く行かなすぎて悲しくなってきます・・・(T_T)特に、同じ所でなんどもつまづく事が・・・

```java:
import java.util.*;
public class Main {
	String[] map; //探索域の地図
	class Rat {
		int cost;//時間
		int hp;//体力
		int target;//対象工場の残り数
		int x, y;//x座標y座標
		Rat(int cost, int hp, int target, int x, int y) {//コンストラクタ
			this.x = x;
			this.y = y;
			this.cost = cost;
			this.hp = hp;
			this.target = target;
		}
	}

	private int solve(int x, int y, int n) {
		Queue<Rat> open = new LinkedList<Rat>();//ねずみの状態を格納しておくopen
		boolean[][] closed = new boolean[map.length][map[0].length()];//訪れた工場をメモしておくclosed
		
		//openに初期状態を入れる・・・秒数0、体力1、対象工場残り数n、x座標x、y座標y
		open.add(new Rat(0, 1, n, x, y));
		//東、西、南、北の順に進む
		int[] fdx = new int[]{1, -1, 0, 0};
		int[] fdy = new int[]{0, 0, -1, 1};
		//幅優先探索
		while(!open.isEmpty()) {
			//状態取得
			Rat temp = open.poll();  //あるネズミを取り出す
			int cost = temp.cost;    //秒数
			//System.out.println(cost);
			int hp = temp.hp;        //体力
			int target = temp.target;//対象工場の残り数
			int grid_x = temp.x;     //x座標
			int grid_y = temp.y;     //y座標
			temp = null;
			//もし、全ての工場のチーズを食べたならば秒数を返す
			if(target == 0) return(cost);
			//移動開始
			for(int r = 0; r < fdx.length; r++) {
				int nextcost = cost + 1;    //秒数が１進む
				int nexthp = hp;            //体力はまだ変化するか分からない
				int nexttarget = target;    //対象工場の残り数も同様
				int nextx = grid_x + fdx[r];//x座標を変化
				int nexty = grid_y + fdy[r];//y座標を変化
				//探索範囲外に出たり、障害物があったりしたらこのケースは無視
				if(nextx < 0 || nexty < 0 || nextx >= map[0].length() || nexty >= map.length || map[nexty].charAt(nextx) == 'X') continue;
				//工場のみ対象として行う処理
				if(map[nexty].charAt(nextx) != '.' && map[nexty].charAt(nextx) != 'S') {
					if(hp >= (map[nexty].charAt(nextx) - '0') && !closed[nexty][nextx]) {
						nexthp++;    //チーズを１つ食べたので体力が1増える
						nexttarget--;//対象工場の残り数が減る
						closed[nexty][nextx] = true;//訪れた事を記録
					}
					//System.out.println(map[nexty].charAt(nextx));
				}
				//進んだ状態を追加
				open.add(new Rat(nextcost, nexthp, nexttarget, nextx, nexty));
			}
			//System.out.println("for end");
		}
		return(-1);
	}

	void doIt() {
		Scanner stdIn = new Scanner(System.in);
		int height = stdIn.nextInt();
		int width = stdIn.nextInt();
		int n = stdIn.nextInt();
		map = new String[height];
		int x = -1, y = -1;
		for(int r = 0; r < height; r++) {
			map[r] = stdIn.next();
			for(int c = 0; c < width; c++) {
				if(map[r].charAt(c) == 'S') {
					x = c; y = r;
				}
			}
		}
		int ans = solve(x, y, n);
		System.out.println(ans);
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main().doIt();
	}
}


```

前回からかなり書き方が変わったと思うのですが・・・
何かおかしい点、気になる点がありましたら、教えて頂けると私の全てのつけめん侍が喜びます。
WebStormのファイル検索で特定フォルダを無視する


正確にはIDEから管理対象外に指定する方法です。

# 背景

PhoneGapもといCordovaでは3.0系からコマンドビルドに変更され、wwwフォルダのファイルがplatformフォルダ以下にコピーされるようになりました。このためWebStormで開発していると検索で重複して表示されてしまいます。間違ってファイルを編集したり、置換するときにも余計に検索されてしまうので検索対象から除外したいわけです。

# 除外方法
そもそもIDEの管理から除外できるようなので、こちらを採用しました。

```
右クリック -> Mark Directory As -> Excluded
```

![webstorm-directory-excluded.png](https://qiita-image-store.s3.amazonaws.com/0/12108/eb68748a-1e94-782a-e208-0933f28646d3.png "webstorm-directory-excluded.png")

# （追記）解除方法
解除方法も欲しいといわれたので。

```
メニューバー -> WebStorm -> Preferences...
Project Settings -> Directories -> 除外されたフォルダを右クリック -> Excludedを外す
```
![webstorm-clear-excluded.png](https://qiita-image-store.s3.amazonaws.com/0/12108/82671de4-31a9-d2ec-b064-0d2b0fc05fef.png "webstorm-clear-excluded.png")



# 参考
[Exclude folder from search but not from the project list](http://stackoverflow.com/questions/16559203/exclude-folder-from-search-but-not-from-the-project-list "Exclude folder from search but not from the project list")
GoogleMapで住所などから位置を取得して表示するサンプル

google.maps.Geocoderを使用して住所や施設名等から位置情報を取得します。

```html
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>住所などから位置を取得する</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
        html, body, #map-canvas {
            height: 500px;
            width: 500px;
            margin: 20px;
            padding: 20px;
        }
    </style>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
    <script>
        $(function () {
            var map;
            var marker;
            var geocoder;

            google.maps.event.addDomListener(window, 'load', initialize);

            function initialize() {
                var mapOptions = {
                    zoom: 15,
                    center: new google.maps.LatLng(Number($("#latitude").val()), Number($("#longitude").val()))
                };

                map = new google.maps.Map($("#map-canvas")[0], mapOptions);

                marker = new google.maps.Marker({
                    position: map.getCenter(),
                    map: map
                });

                geocoder = new google.maps.Geocoder();
            }

            $("#geocode").click(
                function () {
                    var address = $("#address").val();
                    geocoder.geocode({ 'address': address }, function (results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            var loc = results[0].geometry.location;
                            map.setCenter(loc);
                            marker.setPosition(loc);
                            $("#latitude").val(loc.lat());
                            $("#longitude").val(loc.lng());
                        } else {
                            alert('Geocode was not successful for the following reason: ' + status);
                        }
                    });
                });
        });

    </script>
</head>
<body>
    <input id="latitude" type="text" value="33.8391574" />
    <input id="longitude" type="text" value="132.76557520000006" />
    <div id="panel">
        <input id="address" type="text" value="愛媛県松山市">
        <input type="button" value="Geocode" id="geocode">
    </div>
    <div id="map-canvas"></div>
</body>
</html>
```
Vagrant Tips#5 boxのメモリをVagrantfileで変更する(VirtualBox限定)

##[Vagrant Tipsのサマリページはこちら](http://qiita.com/yukimura1227/items/7e34bb12d36e8aa2e6c3)

# boxのメモリをVagrantfileで変更する(VirtualBox限定)
Vagrantで利用している仮想環境で、いろいろ開発を実施する場合に、どうしてもデフォルトのメモリでは足りなくて困ってしまう場合があります。
そんな場合、Virtualboxを利用しているのであれば、「Oracle VM VirtualBoxマネージャー」によって、GUIでメモリを増減させることは可能ですが地味に面倒です。
本投稿では、Vagrantのproviderとして"VirtualBox"を利用している場合に限定されますが、Vagrantfileにてメモリを指定する方法を紹介致します。

```ruby:Vagrantfile#1
Vagrant.configure("2") do |config|
  config.vm.box = "centos64_6_4"
  config.vm.box_url = "http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210.box"

  config.vm.provider "virtualbox" do |vm|
    # メモリを1024MBに設定
    vm.customize ["modifyvm", :id, "--memory", "1024"]
  end
end
```

→裏では、「VBoxManage」というツールを利用しており、「VBoxManage」で利用できる設定はひと通り実現することができそうです。詳細は、[VBoxManageのマニュアル](https://www.virtualbox.org/manual/ch08.html#vboxmanage-modifyvm)が参考になります。


また、上記では直感的にわかり辛いため、シンタックスシュガー的な記法も用意されており、それを利用すると以下のようにシンプルに記述することが可能です。

```ruby:Vagrantfile#2
Vagrant.configure("2") do |config|
  config.vm.box = "centos64_6_4"
  config.vm.box_url = "http://puppet-vagrant-boxes.puppetlabs.com/centos-64-x64-vbox4210.box"
 
  config.vm.provider "virtualbox" do |vm|
    # メモリを1024MBに設定
    vm.memory = 1024
  end

end
```
d3.jsでクラス図を書いてみた

題材は[railstutorial/sample_app_rails_4]( https://github.com/railstutorial/sample_app_rails_4 )のモデルです。
https://github.com/railstutorial/sample_app_rails_4/tree/0cba8ffccf8b384d5cf7d62f8028a9e01b5c7d1f/app/models

# ソースとデモ

ソース: https://github.com/hnakamur/d3.js-class-diagram-example
デモ: https://hnakamur.github.io/d3.js-class-diagram-example

# スクリーンショット

![micropost_example_app_class_diagram.png](https://qiita-image-store.s3.amazonaws.com/0/3227/24c4948d-9de4-5644-ccbe-b11d1efed4d0.png)

# 参考

* [ブロック図を書いてみてd3.jsはSVGの作図ツールとしても良いかもと思った - Qiita]( http://qiita.com/hnakamur/items/cfb8b0005488a2f34fb0 )
* [複数行テキストを垂直・水平方向に揃えるd3.jsプラグインを作ってみた - Qiita]( http://qiita.com/hnakamur/items/2ffbc09eadc7029e76d5 )
* [d3.jsでUMLのクラス図用の矢印を作ってみた - Qiita]( http://qiita.com/hnakamur/items/6fd5154bb6c2f490607a )
VMware View DB修正

この記事は、VMwareのKB [Manually deleting linked clones or stale virtual desktop entries from the View Composer database in VMware View Manager and Horizon View (2015112)](http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2015112)を噛み砕いたものです。


##概要

Viewを使用していて、たまにvCenter、Connenction Server、Composerといった各コンポーネント間でDBの整合性が合わなくなる場合があります。

結果、View Administrator上でリンククローンのVMが削除できなくなり、タスクも保留状態になって再構成ができないなどの不具合が出ることがあります。

そういう時は、こちらの手順でDBを修正することで直ることがあります。

##環境
* Windows Server 2008 R2（64bit）
* View 5.1


##大まかな手順
1. ADSIエディターを使ってView Connection ServerのADAM DBからリンククローンVMを削除
2. SviConfigコマンドを使ってAD、vCenter、ComposerからリンククローンVMを削除


##詳細手順
1. ADSIエディターを使ってView Connection ServerのADAM DBからリンククローンVMを削除
    2. View Connection Serverにログイン
    3. 管理ツールからADSIエディターを開く
    4. [接続]をクリックして、任意の接続名を入力
    5. [識別名]に　dc=vdi,dc=vmware,dc=int　と入力
    6. コンピュータ名にlocalhost:389と入力
    7. 作成した接続名を右クリックして新規作成→クエリ
    8. 任意のクエリ名を付ける
    9. ServersというOUを指定する
    10. 枠内に以下を入れる
        * `(&(objectClass=pae-VM)(pae-displayname=<VM名>))`
        * このときVM名には削除対象のVMの名前を入れる　例：VM01
    13. 対象のマシンのCN名が表示されるので、プロパティを見て対象のVMであることを確認
    14. 右クリックから削除
        * この時点でView Administratorのインベントリから消える
2. SviConfigコマンドを使ってAD、vCenter、ComposerからリンククローンVMを削除
    3. Composerにログイン
    4. コマンドプロンプトで、Install_drive\Program Files (x86)\VMware\VMware View Composerに移動
    5. 以下のコマンドを入力
        * `SviConfig -operation=RemoveSviClone -VmName=<VM名> -AdminUser=<ローカル管理者名> -AdminPassword=<ローカル管理者パスワード> -ServerUrl=https://localhost:18443/SviService/v3_0`
    6. Removesviclone operation completed successfullyと表示されればOK
        * この時、vCenterのインベントリからディスクごと消える 

以上
PhantomJSでHTMLファイルをpngに変換するスクリプトを書いた

MITライセンスです。
ソースは https://github.com/hnakamur/html2png に置きました。

# ソース

短いのでここにも引用します。

件名で変換と言っていますが、[open]( http://phantomjs.org/api/webpage/method/open.html )でウェブページを開いて[render]( http://phantomjs.org/api/webpage/method/render.html ) APIを使ってスクリーンショットをとっているだけです。

```js:https://github.com/hnakamur/html2png/blob/9daf997f531b9f4668ebc06c77556b160dd877fa/html2png
#!/usr/bin/env phantomjs
var page = require('webpage').create();
var system = require('system');

if (system.args.length !== 3) {
  console.log('Usage: ' + system.args[0] + ' html_file png_file');
  phantom.exit(1);
}

var htmlFile = system.args[1];
var pngFile = system.args[2];

page.open(htmlFile, function(status) {
  if (status === 'fail') {
    console.log('Error! failed to open ' + htmlFile);
    phantom.exit(1);
  }

  page.evaluate(function() {
    document.body.bgColor = 'white';
  });
  page.render(pngFile);
  phantom.exit();
});
```

PhantomJSはデフォルトの背景色は透明ですが、[FAQ | PhantomJS]( http://phantomjs.org/faq.html )の"Q: When using render(), why is the background transparent?"のコードを使って白にしています。

# 使い方

事前に[PhantomJS | PhantomJS]( http://phantomjs.org/ )をインストールしてPATHを通しておいてください。

```shell-session
./html2png HTMLのファイルパスまたはURL PNGのファイルパス
```

# 出力例

```shell-session
./html2png http://phantomjs.org/ phantomjs.org.png
```

で変換した例です。

![phantomjs.org.png](https://qiita-image-store.s3.amazonaws.com/0/3227/de19fba2-ef66-cc69-5e6e-ecb1642c283b.png)
難しくて長いWebページを最後まで読み切る


Twitterやはてなブックマークから流れてきて「これはよい」と思ってブックマークして、その後1回も読み返すことが無かった記事がたくさんあります。そうならないための方法を考えてみました。しばらく実践してみて良さそうだったのでまとめてみました。

- さっと読んでみて読み応えがありそうだったらストックする
- 大変そうだったらメモページを作る
- 時間を空けながら少しずつ読む

[[続きを読む]](http://ongaeshi.hatenablog.com/entry/how-to-read-web-page)
GoogleMapでクリックされた位置を取得するサンプル

```html
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <title>クリックされた位置を取得する</title>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <style>
        html, body, #map-canvas {
            height: 500px;
            width: 500px;
            margin: 20px;
            padding: 20px;
        }
    </style>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
    <script>
        $(function () {
            google.maps.event.addDomListener(window, 'load', initialize);

            function initialize() {
                var mapOptions = {
                    zoom: 15,
                    center: new google.maps.LatLng(Number($("#latitude").val()), Number($("#longitude").val()))
                };

                var map = new google.maps.Map($("#map-canvas")[0], mapOptions);

                var marker = new google.maps.Marker({
                    position: map.getCenter(),
                    map: map
                });

                google.maps.event.addListener(map, 'click', function (e) {
                    var loc = e.latLng;
                    marker.setPosition(loc);
                    $("#latitude").val(loc.lat());
                    $("#longitude").val(loc.lng());
                });
            }
        });
    </script>
</head>
<body>
    <input id="latitude" type="text" value="33.8391574" />
    <input id="longitude" type="text" value="132.76557520000006" />
    <div id="map-canvas"></div>
</body>
</html>
```
ElasticsearchでField Collapsing/Combining


個人的に長い間望んでいた件の機能を実現するtop_hits aggregation、これが追加されたバージョン1.3.0がついにリリースされました。

http://www.elasticsearch.org/blog/elasticsearch-1-3-0-released/

```
The top hits aggregation (#6124) resolves the most +1′ed issue in the history of Elasticsearch: Field collapsing/combining. You can now bucket on a common field like brand_name, and get the best matching documents for each bucket. Even highlighting is supported!
```

Solrでは元からあった機能なのですが、Elasitcsearchにはなくて、以下のIssueが「14 Jul 2010」からずっとOpenな状態で多々議論がされていました。

Field Collapsing/Combining #256
https://github.com/elasticsearch/elasticsearch/issues/256

それに関して動きがあったのは5月の以下のIssue。
(もっと前からだろうけど、気づいたのはその頃)

Aggregations: Add top_hits aggregation #6124
https://github.com/elasticsearch/elasticsearch/pull/6124

確認すると、確かに期待してる機能なようなので以下のドキュメントを参考に`top_hits aggregation`を使ったクエリを書いてみました。

field collapse example
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html#_field_collapse_example

```json
{
  "size": 0,
  "query": {
    "match": {
      "title": "ほげ"
    }
  },
  "aggs": {
    "hits": {
      "terms": {
        "field": "gid",
        "order": {
          "top_hit": "desc"
        }
      },
      "aggs": {
        "top": {
          "top_hits": {
            "sort": [
              {
                "released_at": {
                  "order": "desc"
                }
              }
            ],
            "from": 0,
            "size": 1
          }
        },
        "top_hit": {
          "max": {
            "field": "download_count"
          }
        }
      }
    },
    "stats": {
        "cardinality": {
            "field": "gid"
        }
    },
  }
}
```

この例だと`title`に`ほげ`を含むドキュメントに関して、`gid`でグルーピングし、各グループ内では`released_at`が直近の1件を取得して、`download_count`が大きい順に並んで返ってきてるっぽい(`hits`)。
ちなみに、`stats`の方では`cardinality aggregation`を使って、`gid`でグルーピングされた後の件数を取得してます。

`cardinality aggregation`に関しては、まだ`experimental!`らしい...。
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html


ちなみに`top_hits aggregation`というか`terms aggregation`について分からないことがあってツイートしてたら、Elasticsearchの中の人(johtaniさん)がキャッチアップしてくれて、相談にのってくれました。
ありがたや〜。
https://gist.github.com/shoito/7bd8800d40d3a5b3da13

まだまだ検証しないといけないことは多々あるので、時間を作ってちまちま進めていこうと思います。
Chrome DevToolsでSVGの簡易編集

#Chrome DevTools
Chrome DevToolsはHTMLやCSS、JavaScriptのデバッグを行うツールです。これを用いて、その場でHTMLやCSSなどの実際にブラウザが表示しているファイルの更新を行うこともできます。

HTMLやCSSの編集を実際に表示しながら行うことができるのは大変便利ですし、その結果をファイルに直接反映することもできます。

[Workspaces - Persistent authoring in the DevTools](https://developer.chrome.com/devtools/docs/workspaces)

[[Chrome] DevToolsのWorkspaceでローカルプロジェクトをライブエディット&デバッグする](http://qiita.com/nakajmg/items/2d8a6fcc371d8ea92d91)

##DevToolsでSVGの簡易編集
実は、このDevToolsでSVGの生ファイルを扱うことができます。

たとえば、この有名なSVGファイルを開いているとします。

![Screenshot 2014-07-23 at 23.04.34.png](https://qiita-image-store.s3.amazonaws.com/0/33915/ec81cd10-6e7e-e1fd-ca5b-8cd7a4126112.png)

ここでこのSVGの特定範囲を選択し、[要素を検証] でDevToolsを起動します（Web Inspectorというほうが良いかもしれません）。

![Screenshot 2014-07-23 at 23.05.56.png](https://qiita-image-store.s3.amazonaws.com/0/33915/740d6095-80cf-72ef-59c9-988446496119.png)

この例では、トラの口の部分を選択しています。
見てわかるように、選択部分のSVG要素がハイライトされています。

![Screenshot 2014-07-23 at 23.06.23.png](https://qiita-image-store.s3.amazonaws.com/0/33915/83ed38dd-f476-d75b-baa3-11ea895a11ef.png)

たとえば、このfill（塗りつぶし）を#000（黒）から#CCC（灰色系）に変更するのは、DevToolsでその数値を変えるだけで可能です。

![Screenshot 2014-07-23 at 23.06.34.png](https://qiita-image-store.s3.amazonaws.com/0/33915/e4bacb17-6c0d-3bad-1f90-55088f253e2e.png)

ほかにも要素を削除することやSVGの要素を理解しているならば、生でマニュアルで編集することも可能です。

SVGをそのままマニュアルで編集することは稀かもしれませんが、ちょっとした修正を加えるならば、この機能は重宝するものと思います。
Heroku で Redis 使う。

## Railsで使うには
### gem
- https://github.com/redis/redis-rb
- https://github.com/nateware/redis-objects

ARで使用する場合は ```redis-objects``` 便利っぽい。

### redis-objectsの解説記事はここがすごくわかりやすい
- http://blog.happyelements.co.jp/2013/05/ruby-on-rails-redis-objects.html

## Herokuで使うには

### 比較
- http://leanstack.io/stackups/redisgreen-vs-redis-to-go-vs-redis-cloud

RedisCloud がよさそう。

```
$ heroku addons:add rediscloud
Adding rediscloud on shinobi-dev... done, v5 (free)
Use `heroku addons:docs rediscloud` to view documentation.
```
- 25MB  - Free
- 100MB - $10.00

https://elements.heroku.com/addons/heroku-redis

## 追記

公式のものを使うのがヨサソウ

Heroku Redis
https://elements.heroku.com/addons/heroku-redis
Android Studioでjarファイルをrubyで簡単に作成する


# はじめに
 Android Studioのライブラリプロジェクトでjarファイルを作成してみましょう
私はOSX 10.9.4, Android Studio (Beta) 0.8.1, ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin13.0.2]で確認しました

# ライブラリプロジェクトを作成する

ライブラリ名はHogeとして話を進めます
moduleのbuild.gradleを以下に設定します

```build.gradle
apply plugin: 'com.android.library'
```

# aarファイルを作成する
aarファイルとはAndroid archiveファイルの略で、jarファイルのクラスファイル以外にリソースを含んでいます
次のコマンドを実行します

```
$ ./gradlew clean
$ ./gradlew aR
```
aRはassembleReleaseの略です

build/outputs/aarにHoge.aarファイルが生成されます

# jarファイル
Hoge.aarはzipファイルで中にclasses.jarが含まれています。このclasses.jarファイルが欲しいファイルですが、解凍して名前を変更するのは面倒です。そこでaarファイルからclasses.jarを抽出し、名前をHoge.jarに変更するrubyスクリプトを作成しました

# jarファイルを生成するrubyスクリプト

zipファイルを扱うために、rubyzip gemをインストールします

```
$ gem install rubyzip
```

jarファイルを生成するrubyスクリプトは以下のとおりです

```make_jar.rb
require 'zip'

if ARGV.size == 0
  puts 'usage : ruby unzip.rb [aar filname]'
  exit
end

aar_file = ARGV[0]

TEMP_DIR = 'temp'
Dir.mkdir(TEMP_DIR) unless FileTest.exist?(TEMP_DIR)
FileUtils.copy(aar_file, "#{TEMP_DIR}/#{aar_file}", {})
Dir.chdir(TEMP_DIR) do
  Zip::File.open(aar_file) do |zip|
    zip.each do |entry|
      zip.extract(entry, entry.to_s) { true }
    end
  end
end

filename = File.basename(aar_file, ".aar")
lib_filename = "#{filename}.jar"

Dir.chdir(TEMP_DIR) do
  FileUtils.mv('classes.jar', lib_filename)
end

FileUtils.copy("#{TEMP_DIR}/#{lib_filename}", "#{lib_filename}")

FileUtils.rm_rf(TEMP_DIR)

```

第一引数にHoge.aarを指定します

```
$ ruby make_jar.rb ./Hoge.aar
```

実行したディレクトリにHoge.jarが生成されます。なお、ワークディクレトリとして、カレントディレクトリにtempディレクトリを作成し、スクリプト終了時にtempディレクトリを削除しています

# ライブラリを組み込む
ライブラリを使用するAndroidプロジェクトのapps/libs/以下にHoge.jarをコピーします

build.gradleに依存情報を記述します

```build.gradle
dependencies {
  compile files('libs/Hoge.jar')
}
```

# おわりに
手作業で行うことは可能ですが、面倒ですので、自動化できるところは自動化することがよい思います


参考
[Android Studio で簡単に jar をつくる手順はないのかと](
http://android.benigumo.com/20140419/android-studio-%E3%81%A7%E7%B0%A1%E5%8D%98%E3%81%AB-jar-%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8B%E6%89%8B%E9%A0%86%E3%81%AF%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B%E3%81%A8/)
capistranoでデプロイが終わったらYoを送る

# Yo APIの取得
http://yoapi.justyo.co/
こちらのページからAPI用のアカウントを作成する。個人用のアカウントを持っている必要がある。
アカウントを作るとtokenが発行される。

## APIの仕様
### subscriber全員にYo
subscriberに一括でYoする (POST)

```
$ curl --data "api_token=<api_token>" http://api.justyo.co/yoall/
```

### 個人にYo
パラメータで指定したユーザーにYoする (POST)
誰にでも送れちゃうのかな...？

```
$ curl --data "api_token=<api_token>&username=<username>" http://api.justyo.co/yo/
```

### subscriberの数をカウント
API用のアカウントのsubscriberの総数を取得する (GET)

```
$ curl "http://api.justyo.co/subscribers_count/?api_token=<api_token>"
```

### Yo受信でwebhook呼び出し
設定したコールバックURLを使用する。
Yoを受信したら、hookを呼び出す。送信したユーザー名がusernameパラメータとして付いてくる

# Capistranoのタスクにしてみる
くだらないけどやってみた。

チームの開発メンバーにAPI用のアカウントをsubscribeしておいてもらい、
適当なタイミングで全員にYoできるように。

```rb:lib/capistrano/tasks/yo.cap
require 'net/http'

namespace :yo do
  def yo
    uri = URI('http://api.justyo.co/yoall/')
    Net::HTTP.post_form(uri, 'api_token' => ENV['YO_API_TOKEN'])
  rescue => e
    p e
  end

  desc 'Send a YO to developers'
  task :send do
    run_locally do
      yo
    end
  end
end
```

これで`cap yo:send`というタスクができる。
`cap deploy:finished`とか`cap deploy:failed`フックの後に使えば捗りますね。
Yoはコンテキスト
Swiftでマルチスレッド時の同期処理はどうやるのか

* _このエントリはSwift 1.0の時に初版を書きました_
* _このエントリはSwift version 2.1 / Xcode 7.1.1 で動作確認済みです_

[Swift Book](https://itunes.apple.com/us/book/the-swift-programming-language/id881256329?mt=11&ls=1) にはスレッドや同期(synchronization)への言及がないからどうしたものかなと思っていたのだけど、objcにAPIをつかえば実現はできそうだ。

参考: [What is the Swift equivalent to Objective-C's “@synchronized”?](http://stackoverflow.com/questions/24045895/what-is-the-swift-equivalent-to-objective-cs-synchronized)

demo: https://github.com/gfx/Swift-MultiThreading

## objc_sync_enter() / objc_sync_exit() を使う

これらはobjcの低レベルAPIで、`@synchronized` ブロックの実装のためにコンパイラが使う関数だけど、Swiftからも呼び出せる。

このままだと使いにくいのでRAIIパターンをつかって使いやすくしよう。

```swift
class AutoSync {
    let object : AnyObject
    
    init(_ obj : AnyObject) {
        object = obj
        objc_sync_enter(object)
    }
    
    deinit {
        objc_sync_exit(object)
    }
}
```

これを使うときは単にインスタンスを作成するだけでよく、スコープの終わりになると自動的に解放される。

```swift
func f() {
    let lock = AutoSync(self) // lockは自動的に解放される
    self.value++
}
```

### Swift 2.1 追記

これをこのまま使うと、 `let lock` で「`lock` は使われないので `_` に変えろ」といわれる。しかし、その通りに書き換えるとスレッドがロックされなくなる。最適化によってオブジェクトが消えるためと思われるが、RAIIパターンがまともに使えなくなるのでこれはコンパイラのバグであろう。

## GCDのserial queueを使う

これは『[Effective Objective C](http://www.amazon.co.jp/exec/obidos/ASIN/4798134198/gfx04-22/)』でも紹介されている方法で、うまくつかうと `@synchronized` や NSLock よりも高速にできるらしい。ただしXcode 6.3の時点では、最適化(-O)した状態だとどちらも同程度の速度だったので、速度の面でどちらにすべきということはない。


```swift
func f() {
    struct _IncrementWithSyncQueue {
        static let s = dispatch_queue_create("com.github.gfx.ios.test.increment_with_sync_queue", DISPATCH_QUEUE_SERIAL)
    }
    
    dispatch_sync(_IncrementWithSyncQueue.s) {
        self.value += 1
    }
}
```

いずれにせよ、Objective-C時代と大きく変わるわけではなさそうだ。
vagrant upをすると、machin to bootで止まってしまいます。

VirtualBox 4.3.12の共有ファイルの同期がうまく行かず、VirtualBox 4.3.12をアンインストールして、
VirtualBox 4.3.14をインストールしなおしました。
MinGW　shellでvagrant upしましたが、machin bootのところで止まってしまいます。
VirtualBox　GUIではVirtualBox電源offとなっていたので「起動」しましたがエラーとなって起動できません。
ホストOSはWindows7 sp1です。

vagrant upで停止した時のメッセージは、
The guest machine entered an invalid state while waiting for it to boot.
 Valid states are 'starting, running'. 
The machine is in the 'poweroff' state.
 Please verify everything is configured properly and try again.
です。

対処方法を教えてください。
Middlemanで最終更新日時を出力する


Rubyで最新の日時を出力するRubyのコードを書きます。

下記はSlimでの例です。 ``` DateTime.now ``` で現在時刻が取得できるので、そのままHTMLに出力されます。

```slim
small
  = "Last Modified: #{DateTime.now}"
```

もちろん、erbでもできます。

```erb
<small>Last Modified: <%= DateTime.now %></small>
```

これにより ``Last Modified: 2014-07-23T22:33:41+09:00`` のような文字が出力できます。
TypeScriptでRequire.jsのdefine()が使えなかった件


TypeScriptもバージョン1.0が出たし使ってみるかーと思い作成しているものにRequire.jsでAMDに対応させようと思ったら詰まったときの備忘録です。
## 環境
* TypeScript 1.0.1
* Require.js 2.1.14
* durandal 2.1.0


## define()が使えない？
以下のjsのコードをTypeScriptに置き換えるときにこのまま突っ込んだらコンパイル時に「defineの引数がおかしいけど？」ってニュアンスのコンパイルエラーが発生。

```
define(['plugins/router', "durandal/app"], function (router, app) {
    return {
        router: router,

        search: function() {
            app.showMessage("Not Implemented", "Error");
        },

        activate: function () {
            router.map([
                { route: '', moduleId: 'hoge/huga', title: "hoge", nav: true }
            ]).buildNavigationModel();
            
            return router.activate();
        }
    };
});
```

## import文を使えばいいらしい

調べたり、友人に訪ねて見ると
「require.jsを使うときは基本的にimport文を使え」とのこと

早速適応してみる。

```
/// <reference path="durandal.d.ts" />

import _router = require('plugins/router');
import _app = require('durandal/app');

class hoge {

    app = _app;
    router = _router;

    search() {
        this.app.showMessage("Not Implemented", "Error")
    }

    activate() {
        this.router.map([
            { route: '', moduleId: 'hoge/huga', title: "hoge", nav: true }
        ]).buildNavigationModel();
        return this.router.activate();
    }
}

export = hoge;
```

上記のソースにコンパイルオブション"-m amd"を追加するとコンパイルが通るらしい。
僕の環境ではGruntを使用しているので、grunt-typescriptのmoduleオブションに'amd'と付ける。

コンパイルしてみるとコンパイルは通りjsファイルは生成されたが、中身にはdefineが使われていなかった…
何か不足していることがあるのか調査が必要なようだ。

## 追記
解決したので追記します。

どうやらexportしてあげなきゃいけないらしい。
というわけで、正しく動作するように上記のソースを修正した。

ちなみにexport class hogeとやると、コンパイル後に別の動作になる。
RubyでPluggableなアーキテクチャを実現する


プラグインを扱うコードを書く為に、Rubyで動的にクラスをロードする方法を適当に調べてみた[1][2]。
以下の方法があるっぽい。
- const_get
- eval
- qualified_const_get

どれ使えばいいのかイマイチわからん。

そもそもプラグイン的なものを作る場合にいちいちプラグイン側のクラス名気にする必要ないかも。
むしろプラグイン側で勝手にnewしてインスタンス突っ込んでくれるような感じでいいかも。
こんな感じで。どうっすかね。

```ruby:app.rb
class Plugin
	def Plugin.load(path)
		plugin = new()
		plugin.instance_eval File.read(path)
		plugin
	end

	def get_instance
		@instance
	end
end

#以下は読み込むファイル名をハードコードしているが、
#実際は[1]のコードみたいに特定のディレクトリにあるrubyのファイルをロードする
p = Plugin.load("myplugin.rb")

#プラグインを使う側はプラグインに要求するメソッドしか呼び出さない      
p.get_instance().execute()          
```

```ruby:myplugin.rb
module MyModule
	class MyPlugin
        #プラグインに要求されるメソッドを実装しておく
		def execute()
			puts "hello world!!!"
		end
	end
end

@instance = MyModule::MyPlugin.new
```

###追記

i18nさんのアドバイスを元に最終的に上記とは違う形ですが簡単にPlugin化するためのモジュールを作りました。
gemとして公開したのでもしよければ使ってみて下さい。

https://rubygems.org/gems/pluggable_lite
https://github.com/nyamage/PluggableLite


###参考URL

[1]Rubyで動的にクラスファイル(プラグイン)を読み込む
http://motivation.drivendevelopment.jp/2009-11-16-1.html

[2]Loading classes from strings in Ruby
http://blog.sidu.in/2008/02/loading-classes-from-strings-in-ruby.html#.U8-tSYB_ux8

あなたの Ruby コードを添削します 【第 4 回】 Tropy
http://magazine.rubyist.net/?0015-CodeReview
Cygwin | Cygwin64bit版 + apt-cyg + CygTerm + rbenv + ruby 環境を構築するまで

# Cygwin | Cygwin64 + apt-cyg + CygTerm + rbenv + ruby 環境を構築するまで

## 概要
Cygwin64bit版 + apt-cyg + CygTerm + rbenv + ruby 環境を構築するまでについて。
つまり、Windowsで rbenv + ruby の環境を作成する手順になります。
Chef・Berkshelfを利用するための準備でもあります。

## 手順

### cygwin64bit版 と apt-cyg と必要最低限のパッケージをインストールをする

* 手順は下記サイトを参考にする

[64bit版Cygwinをインストールしてapt-cygするまで](http://dqn.sakusakutto.jp/2013/12/64bit_cygwin_apt-cyg.html)

### TeraTermをインストールする

http://sourceforge.jp/projects/ttssh2/

### CygTermを64bit環境向けに再コンパイルする

Cygwin に標準で添付されている Cygwin Terminal の使い勝手が悪いので CygTerm を利用します。
TeraTerm に同梱されている CygTerm は32bit版のみなので、一緒に添付されているtarを解凍して
再ビルドする必要があります。

* 手順は下記サイトを参考にする

[Cygwin 64bit版への対応について](http://sourceforge.jp/projects/ttssh2/forums/5841/34393/)

~~~bash
# tarを解凍
tar xvf cygterm+.tar.gz
# Makefileを編集(-mno-cygwin と記述されている箇所を全削除する)
vi Makefile
# make
make
make install
~~~

ここまで終わったら、完成した CygTerm.cfg と CygTerm.exe を %cygwin64%/bin 配下にコピーします

### rbenv + ruby をインストール

さっそくインストールした cygterm を起動して env + ruby をインストールします。

* 手順は下記サイトを参考にする

[[Cygwin]rbenvとruby-buildで最新のrubyを入れる](http://dqn.sakusakutto.jp/2013/12/cygwin-rbenv-ruby-build-ruby.html)

### 作業完了につき、感謝の雄叫び

~~~bash
$ apt-cyg install figlet
$ figlet 'Thanks DQNEO!'
 _____ _                 _          ____   ___  _   _ _____ ___  _
|_   _| |__   __ _ _ __ | | _____  |  _ \ / _ \| \ | | ____/ _ \| |
  | | | '_ \ / _` | '_ \| |/ / __| | | | | | | |  \| |  _|| | | | |
  | | | | | | (_| | | | |   <\__ \ | |_| | |_| | |\  | |__| |_| |_|
  |_| |_| |_|\__,_|_| |_|_|\_\___/ |____/ \__\_\_| \_|_____\___/(_)
~~~

ほとんどDQNEOさんの手順なので感謝です！

## 参照
[64bit版Cygwinをインストールしてapt-cygするまで](http://dqn.sakusakutto.jp/2013/12/64bit_cygwin_apt-cyg.html)
[Cygwin 64bit版への対応について](http://sourceforge.jp/projects/ttssh2/forums/5841/34393/)
[[Cygwin]rbenvとruby-buildで最新のrubyを入れる](http://dqn.sakusakutto.jp/2013/12/cygwin-rbenv-ruby-build-ruby.html)
RuboCop | Style/SignalException

# RuboCop | Style/SignalException

## 概要

RuboCopの「Style/SignalException」警告について。

例外の送出時に、 *raise* を利用するか、 *fail* を利用するかを設定し、チェックする。
デフォルトでは文脈に合わせて使い分けをしているかチェックする。
新規に例外を送出する場合は *fail* 。
例外を再送出する場合は *raise* 。

## SignalException

### 設定値一覧

|設定対象|対象|内容|デフォルト|
|:-----|:--|:---|:---:|
|EnforcedStyle|only_raise|raiseのみを許容する|--|
|EnforcedStyle|only_fail|failのみを許容する|--|
|EnforcedStyle|semantic|文脈に合わせる|○|

### 検証プログラム

~~~ruby:signal_exception.rb
def hoge(msg)
  hige(msg)
rescue
  fail StandardError, 'hoge'
end

def hige(msg)
  if msg == 'hoge'
    print msg
  else
    raise StandardError, 'hige'
  end
end
~~~

### 実行結果 デフォルト の場合

~~~yaml:.rubocop.yml
SignalException:
  EnforcedStyle: semantic
~~~

~~~bash
$ rubocop
Inspecting 1 file
C

Offenses:

signal_exception.rb:4:3: C: Use raise instead of fail to rethrow exceptions.
  fail StandardError, 'hoge'
  ^^^^
signal_exception.rb:11:5: C: Use fail instead of raise to signal exceptions.
    raise StandardError, 'hige'
    ^^^^^

1 file inspected, 2 offenses detected
~~~

### 実行結果 only_raise に設定します

~~~yaml:.rubocop.yml
SignalException:
  EnforcedStyle: only_raise
~~~

~~~bash
$ rubocop
Inspecting 1 file
C

Offenses:

signal_exception.rb:4:3: C: Always use raise to signal exceptions.
  fail StandardError, 'hoge'
  ^^^^

1 file inspected, 1 offense detected
~~~

### 実行結果 only_fail に設定します

~~~yaml:.rubocop.yml
SignalException:
  EnforcedStyle: only_fail
~~~

~~~bash
$ rubocop
Inspecting 1 file
C

Offenses:

signal_exception.rb:11:5: C: Always use fail to signal exceptions.
    raise StandardError, 'hige'
    ^^^^^

1 file inspected, 1 offense detected
~~~

## 補足

この警告は rubocop -a で修正可能です。

## RuboCopまとめ記事

http://qiita.com/tbpgr/items/edbfecb6a6789dd54f47
Marvericks で X11 をインストールせずに wireshark を使う

marvericks になって X11 が同梱されなくなったので、wireshark がそのままでは動かなくなってしまった。

![スクリーンショット 2014-07-23 21.07.17.png](https://qiita-image-store.s3.amazonaws.com/0/9549/d0a8f770-ab3f-ff3b-f49f-73362f7e1892.png)

homebrew でインストールすれば... とやってみたものの、X がないとダメだった。めんどくせーなーと `brew info wiresahrk` を眺めていると --with-qt というオプションを発見。もしやとやってみたところ...

```zsh
$ brew install wireshark --with-qt
$ sudo wireshark 2> /dev/null &
```

動いた! ショートカット等も特に問題なく動いている。

![スクリーンショット 2014-07-23 21.07.35.png](https://qiita-image-store.s3.amazonaws.com/0/9549/467e2a34-3825-8d62-30ca-de5ea78d28b2.png)
tmlib.js公式エディタrunstantで知った省略表記

# trueを短く書く方法があった

```js
!0
```

と書くとtrueの半分の長さで済む。


runstantで発見した箇所

jszipを使ってunzip関数を定義している箇所でloadメッソッドの
base64オプションに指定するtrueの代わりに!0を使っていた。

```
unzip=function(r){
var n=new JSZip,t=n.load(r,{base64:!0});
return t.file("data").asText()
}
```

```
{base64:!0}
```

# Link

- [runstant](http://phi-jp.github.io/runstant/release/alpha/)
- [jszip](http://stuk.github.io/jszip/)
自前でVagrantのboxを作る前にやっておきたいことメモ


[Vagrantbox.es](http://www.vagrantbox.es/)があるので良いのかもしれませんがBoxの安全性が気になったり、そもそも使いたいOSのBoxが無かったりした場合は自分でBoxを作ることになります。
[veewee](https://github.com/jedi4ever/veewee)という手段もありますが今回はVirtualboxで作成したVMをBox化していきたいと思います。

## Vagrantのインストール

* Macなら、`brew cask install vagrant`でインストールできます

## ゲストマシンのセットアップ

ゲストマシンへのsshアクセスが前提ですがsshdがデフォルトでインストールされるとは限らないので、sshdを動かせるようになるまで手動で作業する必要があります。vagrantの場合はsshdが動く状態でbox化するのが無難かと。

### プロキシの設定

プロキシを越えないと何もできないところにいるので、プロキシの設定を最初に行います

```bash:/etc/environment
http_proxy=http://host:port
https_proxy=http://host:port
```

ログインし直します

### sudoersの設定

プロキシを越えないと何もできないところにいるので、sudo実行時にプロキシの環境変数を引き継ぐようにします。``sudo visudo``で編集しましょう。

```bash:/etc/sudoers
Defaults	env_reset
...
Defaults	keep_env += http_proxy
Defaults	keep_env += https_proxy
```

### パッケージの更新

``apt-get update``とか``apt-get upgrade``とか``yum update``とか。待ち時間が長いです。

### sshdのインストール

openssh-serverをapt-getとかyumでインストール

### Virtualbox Guest Additionsのインストール

vagrant upでVirtualboxの共有フォルダを作るため、Guest Additionsをインストールしておきます

### ssh認証用公開鍵の作成とインストール

vagrantデフォルトの鍵を使っても良いのですが今回は自作の鍵を使用します。ssh-keygenで作ります。
作成した鍵をゲストにコピーし、.ssh/authorized_keysに書きます。

```bash:ホスト側
$ ssh-keygen -t rsa
``` 
```bash:ゲスト側
$ cat key.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
```

ゲスト側へのコピー方法はいくつかありますが、私の場合は予めポートフォワーディング設定をしておいてゲストへのssh接続を可能にしてからscpコマンドでコピーしています。

### boxを作る

* vagrant packageでVMのパッケージング
	* `vagrant package --base vbox-vm-name`
* vagrant box addでboxを追加
	* `vagrant box add <vagrant-box-name> package.box`

あとはvagrant initしてVagrantfileを編集してvagrant upして起動です。

## OS別注意点

### Ubuntu8.04

もうサポートの切れたOSなのでsource.list内に記載している内容が尽く使えなくなっています。
old-releases.ubuntu.comに修正しておきましょう。
こんなもう使ってはいけないOSも扱わなければならない。それが保守フェーズというものなのです。

### Ubuntu12.04

ちゃんとGuest Additionsをインストールしてもvagrant up時に共有フォルダのマウントで失敗します。
対策は[こちらを参照](https://github.com/mitchellh/vagrant/issues/3341)してください。
まあ共有フォルダが使えないだけでVM自体は起動しますが。

### CentOS6

Guest Additionsのインストールが出来ないことがあります。
ビルド用の環境が入っていない可能性がありますので、Development toolsをインストールしてから実行しましょう。

```bash:-
$ sudo yum groupinstall "Development tools"
```

vagrant upしたときにttyをsudo起動しないとアカンと言うような趣旨のメッセージが表示される場合があります。
その際は、sudoersでrequirettyをコメントアウトしましょう。
AWS Summit Tokyo 2014 Day1 CloudFront、RedshiftなどAWSが支える動画広告の舞台裏～インフラのイノベーションがもたらす動画広告のイノベーション～


またまた参加レポートのメモ形式で。

- Speaker
     - 工藤 達之様（株式会社サイバー・コミュニケーションズ Project Designer, Strategy Division）
     - 上野 武史様（Dennoo Inc. Senior Product Director）
     - 八子 武司様（Dennoo Inc. Software Engineer）
- outline
     - 米国を中心に世界的に盛り上がりを見せる動画広告市場、その流れは着実に日本にも押し寄せてきています。昨年から動画関連の会社が続々と日本市場に参入しており2014年は日本の動画広告市場がいよいよ本格スタート、動画広告元年と言われています。
    
     本セッションでは動画広告の変遷とインフラのイノベーションの関係など、動画広告を支えるインフラについて、実データや配信に携わる現場の声をご紹介します。
    
     動画広告の採用を検討している方からインフラ構築ご担当の方まで幅広くお聞きいただけるセッションです。

##
## 動画広告の歴史
- 1990中頃
     - 56kbpsくらいの頃から
     - gifアニメーション

- 2000~
     - 1.5Mbps~10M
     - gifアニメーション

- 2003~
     - FTTH, 10Mbps~100Mbps
     - flashバナー

- 2013~
     - FTTH, LTE, 100Mbps, 1Gbps
     - InBanner, In-stream, in-read
     - smartphone

- 過去2回のは通信速度の改善によるもの
- クラウドの導入によるインフラコストの削減が可能になった
- youtube利用者が5年で15倍

### 2014の動画広告元年は何が違う?
- RTB, DSP, SSP, OVP, ADEXが黒船のように襲来

#### コンテンツ視聴状況
- 3600万人が動画サイトを利用
#### 市場規模
- TVOD
     - 都度課金型
     - ワーナー
- SVOD
     - 定額動画配信

#### 掲載媒体
- in-streamの9割がyoutube

## Dennoo
- 動画のインプレッション
     - 動画の視聴時間を価値として提供

- 過去の動画広告の問題
     - ユーザ側
          - 端末性能
          - 回線
     - システム側
     - 媒体側
          - 転送する動画の容量が大きいので転送料がかかる
               - オンプレインフラの限界
          - 集計項目が多いので鯖代がかかる
               - 再生開始, 完了, マウスオーバー,
               - UA, referrer
               - レポートのバッチを高速にまわす必要がある
          - O2Oとかだと特にアクセス数が多くて死ねる
     - 広告主側
          - 高すぎるインフラコストが広告料金に反映されて広告費が高い
               - 静止画広告の10~100倍くらい
               - 費用対効果の面で躊躇する原因

- 結果として動画広告市場が立ち上がらなかった

- 現在
     - 再生ができる環境になった
          - 回線
               - LTE/Wifi
     - Amazon CloudFrontが使える
     - 大量のログの複雑集計
          - S3,RedShift, MapReduce
     - インフラの低コスト化により広告料金が下がってきた
          - ターゲティング制度
          - リーチの大きさ
          - 接触頻度のコントロール

### 解決策
- 開発者
     - Dev: 2人
     - Ops: 1人
     - コードに集中

- ELB
     - RTB server
     - AD serverのhttp(s)のロードバランシング
- EC2
     - scalaで
     - RTB
     - AD
     - Console
     - Batch

- CloudFront
     - 転送料が決め手
- S3
     - 大量のログ保存
- Redshift
     - 今まではHadoopでやっていたが多様な分析項目処理するために利用
     - Hadoopでインフラコスト削減の削減;w
     - Flydata社の支援により導入
          - 2週間で導入
     - Hadoopで5時間のし処理が5,6分
     - バッチの間隔が短いのでほぼリアルタイムでの分析が可能になった
     - コストもやすくなった
     - 選定基準
          - 1TB~PBデータの分析
               - それより小さいのはRDBでおk
          - 短い間隔で何度もデータ分析したとき
          - SQLで分析できるデータ構造
               - Hiveなら簡単
     - 無料トライアルがあるので試してみてね

## 今後動画広告が発展していくために
- 経済的な機会の存在をしること
- 2兆円市場を作る気概をもつ
- 4要素の歯車
     - 配信コスト
     - 権利処理
     - 優良コンテンツ
     - 収益
AWS Summit Tokyo 2014 Day1 ユーザーの趣味嗜好に適した広告配信システムDynalystができるまで ～ AdTechSTUDIOでのAWS活用戦略～


いつも通りメモ兼備忘録として。
メモが間に合わなかったので一部欠けているところがありますが、そこはご容赦を。

- Speaker
     - 木村 衆平様
          - 株式会社サイバーエージェント AdTechSTUDIO, Dynalyst
- outline
     - インターネット広告における配信ストラテジーはいま「枠からヒト」へ急速に発展しており、
    
     なかでもパーソナライズレコメンド広告の分野では熾烈な競争が起こっています。
    
     本セッションでは、 Dynalystが実現しようとした広告配信サービスをAWSをどう活用し、スピーディに実現させたかについて説明するとともに、サイバーエージェント アドテクスタジオでのAWS活用戦略についてご紹介したいと思います。

## Agenda
- オンライン広告の今
- Dynalystができるまで
- AdTechStudioでのAWS戦略

## オンライン広告の今
### オンラインディスプレイ広告の現在
- より細かなターゲティングが可能な時代
     - 5W1Hにおけるwhoが重要視
     - 行動に基づくリタゲ
     - 広告予算の適切な配分とROI効率の向上
- 広告出向の意思決定のリアルタイム化
     - 50msec or die
     - いつどこでだれにどんな広告を出すor出さん
     - RTBは当たり前だけど大変

## Dynalystができるまで
### Dynalyst
- ユーザのサイト内行動をトラッキング解析し、見込み顧客かをリアルタイム判別しターゲティング広告を展開
- amazonのrecommendの広告版
- インフラは全部AWS
### Keywords
- Real Time
     - サイト内ユーザ行動がリアルタイム広告に反映される
     - RTB時代だから

- User Personalized Ad
     - ユーザの趣味に合わせて広告がダイナミックに変化

### How
#### Requirements(要件)
- 開発者
     - 5,6人からスタート
- 短期間

- Realtime
     - 計測から配信反映までの時間を短くすることが広告効果に絶大な影響がある

- 数億imp/dayで捌く

#### コンセプト
- Use managed services as mu as possible
- 広告主に付加価値を提供することが最重要
- システムそのものは提供する手段ってだけ

#### how do they achive realtime
- 広告主サイトに訪れたユーザがいつどんな商品をみた,カートに入れた,かったを計測
     - 計測して配信して集計
- あるメディア

#### インフラ
- 広告主サイトに訪れたユーザがいつどんな商品をみた,カートに入れた,かったを計測
     - 広告配信をふまえてDynamoDBとElasticCacheにデータ投入
     - ElasticCacheはユーザがターゲティング対象かを判別するため

- DynamoDB
     - 広告主毎のカスタマイズ(スキーマレス)
     - 高スループット, 低レイテンシ
          - DBそのものの運用はない
- ElasticCache
     - 配信機能でまず判定したいのはユーザがターゲティング可能か
     - ターゲティング可能なユーザの確率は20%以下
     - 残り80%はDynamoDB参照により手前の段階でしぼりたい
     - DynamoDBのフロントエンドキャッシュとして十分なパフォーマンス

- Redshift
     - 広告配信ロジックの変化を早く察知したい
     - アドホックな分析クエリを低コストで発行したい
     - レポーティング基盤,分析基盤
     - 仮説を導き出すためのデータ分析基盤

- Chef
     - ServerSpecでインフラテスト
     - アプリエンジニアも書く
     - 今後はOpsWorks/CloudFormationを導入したい

- Jenkins
     - 単体テスト
     - 統合テスト
     - 10回/日以上デプロイしないのでもう少し回数を増やしたい

## AdTechStudioでのAWS戦略
### コストマネージメントの問題
- リザーブドインスタンスの購入計画
     - 未来が読めんがな
     - 稼働率60%程度のRI購入計画を立てる

- 親アカウント
     - 会社単位,事業部単位
- 子アカウント
     - サービス単位
Instrumentsを使ってiOSデバイスのログ（電力消費、GPSのオンオフ、etc...）を確認する

電力消費やGPSのオンオフ等の実機でしか確認できない項目は、iOSデバイスのログ出力 + Instrumentsを使って確認することができます。

今回は、「GPSがOnの時に電力消費が異常な値になっていないかを調べる」というサンプルを元に説明します。

## 事前準備
電力消費を検証したいアプリを、Instrumentsを使ってインストールします。
デバイスを接続し、Xcodeを起動した後、```ctrl + i```でInstrumentsを起動すると自動的にインストールされます。

インストールが終わった後、デバイスは接続を解除しても問題ありません。

## iOSデバイスのログ出力
はじめに、iOSデバイス側でログ出力を有効にします。
設定.appを起動した後、メニューの中から「デベロッパ」を選択します。
![settings.png](https://qiita-image-store.s3.amazonaws.com/0/30970/9c872302-b765-7d7d-d395-33a20c4af90f.png)

"Logging"で、"Energy"のみONにした状態で"Start Recording"をタップします。
その後、開発対象のアプリを操作すると、電力消費のログが取得されます。

![dev.png](https://qiita-image-store.s3.amazonaws.com/0/30970/eb6f17d2-4fed-e764-b828-8c4bebadbffb.png) ![start.png](https://qiita-image-store.s3.amazonaws.com/0/30970/2debaf21-09eb-7b6d-e51a-0518afb77ab5.png) ![stop.png](https://qiita-image-store.s3.amazonaws.com/0/30970/ed08db8e-55b9-90ca-91f3-220052f76c34.png)

検証したいアプリの操作が終わったら、"Stop Recording"をタップしてログ取得を停止します。

## Instrumentsでの解析
ログを出力したデバイスを接続した後、Instrumentsの"file"メニューから"import device log"をクリックします。

![ログ読み込み.png](https://qiita-image-store.s3.amazonaws.com/0/30970/d45aeee0-7559-b479-d218-574993df2069.png)

Libraryから、"Energy Usage"と"GPS"をInstrumentsにドラッグします。
![ライブラリ.png](https://qiita-image-store.s3.amazonaws.com/0/30970/c863b92f-04b7-9b93-c428-e9c8fb32d5ac.png)

ドラッグ後、電力消費とGPS On/Offの状況が表示されます。
![GPS.png](https://qiita-image-store.s3.amazonaws.com/0/30970/0d7bb248-6558-f383-0e45-9b9be3d5be80.png)
（GPS 赤色の領域はOnになっている状態を示す）

## GPS以外に取得できる項目
Wi-FiやBluetooth等、ネットワーク関連のログも取得できるようです。
CentOSへApache2.xをソースビルドしてService登録する

#はじめに
yumでインストールすれば早いのですが、時としては必要になる事もあるので備忘録としてまとめておきます。
最新版のソースを取得してビルドする際には適宜読みかえて使う事を想定。

**※セキュリティやパフォーマンスの向上は割愛しておりますので、このままサーバーを外部公開する事はお勧め致しません**

#既存のapacheが存在しないか確認する
**もし存在していればアンインストール**
`rpm -qa httpd
    [存在していればバージョンが表示される]
yum remove [httpd-version]`

# ソースコード取得からインストール
**[最新版コードのダウンロードURLは公式サイト参照](http://httpd.apache.org/download.cgi)**

`wget [http://ftp.meisei-u.ac.jp/mirror/apache/dist//httpd/httpd-2.2.24.tar.gz]
tar zxvf httpd-2.2.24.tar.gz
 ./configure -prefix=/usr/local/apache2 \
      -enable-so \
     -enable-rewrite \
     -enable-ssl \
     -enable-mods-shared=all
make
make install`

#起動ファイルを取得して設置
**解凍したapacheのソースディレクトリ内にあるhttpd.initをinit.dへコピーして書き換え。**
**コピー元のパスは適宜読み替える。**

`cp /usr/src/httpd-2.2.24/build/rpm/httpd.init /etc/rc.d/init.d/httpd
vi /etc/rc.d/init.d/httpd`
`[修正内容]
 httpd=${HTTPD-/usr/local/apache2/bin/httpd}
 pidfile=${PIDFILE-/usr/local/apache2/logs/httpd.pid}
 CONFFILE=/usr/local/apache2/conf/httpd.conf
[ここまで]`

# iptablesを設定
`vi /etc/sysconfig/iptables`
 
`[追記内容]
 -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 80 -j ACCEPT
 -A RH-Firewall-1-INPUT -p tcp -m tcp --dport 8080 -j ACCEPT
 -A RH-Firewall-1-INPUT -p tcp -m tcp --dport http -j ACCEPT
 -A RH-Firewall-1-INPUT -p tcp -m tcp --dport https -j ACCEPT
 -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
[ここまで]`
 
`/etc/init.d/iptables restart
/sbin/chkconfig iptables on`

# 全ユーザー共通でパスを通す
**perlやphp,mysql等も以下の設定で呼び出せるようになります
mysqlのソースビルドについては[過去に投稿した記事をどうぞ](http://qiita.com/Fu3nori/items/2903f768d0d179047c18)**

`vi /etc/profile 
[追記内容]
  /usr/local/bin:/etc/init.d:/etc/:/usr/local/mysql/bin:/sbin/
[ここまで]  
source /etc/profile`


# Service登録
`chkconfig --add httpd
chkconfig httpd on`
lコマンド？

#`l`コマンド？
端末で`ls`しようとしたらミスタイプで`l`で実行してしまった！
↓
ん…？なんかlsみたいな挙動だぞ…？

#調べた
`l`というのは`ls -CF`のエイリアスらしい。

```bash
$ alias l
alias l='ls -CF'
```

##`-C`
結果を複数列でリスト表示する。

```bash:ls
/$ ls | less
bin
boot
cdrom
dev
etc
home
initrd.img
initrd.img.old
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
selinux
srv
sys
tmp
usr
var
vmlinuz
vmlinuz.old
```

```bash:ls_-C
/$ ls -C | less
bin    dev   initrd.img      lib64       mnt   root  selinux  tmp  vmlinuz
boot   etc   initrd.img.old  lost+found  opt   run   srv      usr  vmlinuz.old
cdrom  home  lib             media       proc  sbin  sys      var
```

##`-F`
ファイルタイプを示す付加情報がつく。
わかりやすいのだけ以下例示。

|  |  |
|--------|--------|
|/|ディレクトリ|
|*|実行権限を持っている|
|@|シンボリックリンク|

```bash
/$ ls -F
bin/    etc/             lib/         mnt/   run/      sys/  vmlinuz@
boot/   home/            lib64/       opt/   sbin/     tmp/  vmlinuz.old@
cdrom/  initrd.img@      lost+found/  proc/  selinux/  usr/
dev/    initrd.img.old@  media/       root/  srv/      var/
```

#他にも

```bash
$ alias
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
```

どうやら`l`の他にも`la`や`ll`などがあるみたい。

##`ls`自体もエイリアス？
`alias ls='ls --color=auto'`とある。
デフォルトで色付きで表示するようになっているみたい。

ちなみに`auto`にせず`ls`すると、例えば`less`などに渡した時に表示がおかしくなってしまう。

```bash:colorだけで
/$ ls --color | less
ESC[0mESC[01;34mbinESC[0m
ESC[01;34mbootESC[0m
ESC[01;34mcdromESC[0m
ESC[01;34mdevESC[0m
ESC[01;34metcESC[0m
ESC[01;34mhomeESC[0m
ESC[01;36minitrd.imgESC[0m
ESC[01;36minitrd.img.oldESC[0m
ESC[01;34mlibESC[0m
ESC[01;34mlib64ESC[0m
ESC[01;34mlost+foundESC[0m
ESC[01;34mmediaESC[0m
ESC[01;34mmntESC[0m
ESC[01;34moptESC[0m
ESC[01;34mprocESC[0m
ESC[01;34mrootESC[0m
ESC[01;34mrunESC[0m
ESC[01;34msbinESC[0m
ESC[01;34mselinuxESC[0m
ESC[01;34msrvESC[0m
ESC[01;34msysESC[0m
ESC[30;42mtmpESC[0m
ESC[01;34musrESC[0m
ESC[01;34mvarESC[0m
ESC[01;36mvmlinuzESC[0m
ESC[01;36mvmlinuz.oldESC[0m
```

```bash:color=autoで
/$ ls --color=auto | less
bin
boot
cdrom
dev
etc
home
initrd.img
initrd.img.old
lib
lib64
lost+found
media
mnt
opt
proc
root
run
sbin
selinux
srv
sys
tmp
usr
var
vmlinuz
vmlinuz.old
```

色がついて表示されるのがデフォルトなのは見やすくていい。
Chrome37でHTML5のDialog要素を試してみた

[Chrome37でHTML5のDIALOGがサポートされた][chrome37]という噂を聞いたので試してみた。  
Dialog要素の詳しい話は[ここらへん][dialog]を参照。

Chrome拡張でJavascriptのPromptを使ってるものがあって、タイミング的にHTML化したいなーと思ってたものがあったのでそれをDialogで置き換え。  
Chrome用の拡張ということで、他のブラウザで動かす必要がないのでネタ的にはちょうどいいのだが、まだ37はベータなので配布開始のタイミングが迷うところ。

ということで、出来上がりはこんな感じ。Gmailに追加して表示させてみた。

<img src="http://media.tumblr.com/c31df61a48c12eb96efb0109a7319be0/tumblr_inline_n95jr6qRCT1sk81cj.png" />

ソース的な流れは

 1. [jQueryでDialog部分のHTMLを組み立てる][build]
 2. [jQueryで作ったDialogをBodyにAppendする][append]
 3. [Chromeの組み込みJSでDialogをshowする][show]

という感じ。（3.でjQuery経由でDialogをshowしてもDialogが開かないので注意 ←）

Dialog部分は純粋なHTMLなのでアイコンもつけることができるし、もちろんCSSで細かく作りこむこともできる。

Dialogを表示するライブラリもいろいろあるけど、Chromeでサポートされてうれしいのは他のライブラリとコンフリクトしないって点だと思う。特にJSバリバリなサービスにChrome拡張で機能を付け足す時なんかはCSS一つとってもぶつかる可能性がある。

外部ライブラリを使わないで一からダイアログを表示させるって手もあるけど、Modalにしたり画面の中央に表示したりっていうのを自動でやってくれるってのはそれだけでもかなりの便利さ。

って言っても、便利だったのはそのくらい。今回は他にBootStrapも使ってたということもあって、結局そちらのCSSを継承しちゃうので結構細かくスタイルを当ててやらなきゃいけなかった。

ここらへんはPolymerが実用化されるのを待つしか無いのかな？

[chrome37]: http://blog.chromium.org/2014/07/chrome-37-beta-directwrite-on-windows.html
[dialog]: http://demo.agektmr.com/dialog/
[build]: https://github.com/loudlyapps/ReSendMeLater/blob/HTML5Dialog/src/util.js#L198
[append]: https://github.com/loudlyapps/ReSendMeLater/blob/HTML5Dialog/src/content_scripts/script.js#L17
[show]: https://github.com/loudlyapps/ReSendMeLater/blob/HTML5Dialog/src/util.js#L320

オリジナルはポストは http://loudlyapps.tumblr.com/post/92621376146/chrome37-html5-dialog で。

このChrome拡張が気になる方は、 http://loudlyapps.github.io/ReSendMeLater/ までどうぞ。
Swiftニモマケズ、NSStringデSwitch構文ヲ書ク

# SwiftではSwitch構文で文字列が使えるようだが
Objective-CにはObjective-Cの良さがあると思う。C由来のゴタゴタやしがらみ、ややこしさ、汚さをフル活用すれば出来ないことはない・・・と思う。

# StackOver風呂でいい記事を見つけた
http://goo.gl/LBeX77
に書いてあるんだが

```objc
#define CASE(str) if ([__s__ isEqualToString:(str)]) 
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT   

SWITCH (string) {
    CASE (@"AAA") {
        break;
    }
    CASE (@"BBB") {
        break;
    }
    CASE (@"CCC") {
        break;
    }
    DEFAULT {
        break;
    }
 }
```

とすればいいらしい。
実際に使ってみたがエレガントだと思う。

簡単にコードを読んでみるとSWITCHがfor文に置き換えられることで、実際のbreakを使えるようにし、なおかつSWITCHで比較元となる文字列を変数にうまく定義している。

# 改良1
しかし上記のコードだとDEFAULTを書き、なおかつそこでbreakしてやらないとfor文で回り続ける。
これだと実際のswitch構文の仕組みと挙動が異なる。switchとはフォールダウンすることはあっても頭に戻ることはないのだ。
（しかし今回のSWITCHはisEqualToString:をifがその都度確認している為、フォールダウンはできない。何かスマートに実現する方法はないだろうか？）まあC#でもフォールダウンは言語仕様上出来ないから、この件も「仕様」で片付けていいかな・・

なので少し改めてみた。

```objc
#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); __s__; __s__ = nil)
#define DEFAULT
```

こうしておくことで1周し終わればforの継続条件が成り立たなくなり2周目が回ることはないだろう。

# 改良2
さらに改良1を改良してみる。
しかし改良2は好みが分かれると思う。

```objc
#define _STRINGIZE(x) #x
#define __STRINGIZE(text) @ _STRINGIZE(text)
#define CASE(str) if ([__s__ isEqualToString:(__STRINGIZE(str))])
#define SWITCH(s) for (NSString *__s__ = (s); __s__; __s__ = nil)
#define DEFAULT
```

こうすることで次のような記述が可能になる。

```objc
SWITCH (string) {
    CASE (AAA) {
        break;
    }
    CASE (BBB) {
        break;
    }
    CASE (CCC) {
        break;
    }
    DEFAULT {
        break;
    }
 }
```

NSStringを@"AAA"と書かずAAAと記述でき個人的にはブラボーだと思うが、きっとこの辺は好き嫌いがあると思う。

# 〆
もし良ければIDEにスニペッドの登録を。

```objc:スニペッド(strsw)
#define _STRINGIZE(x) #x
#define __STRINGIZE(text) @ _STRINGIZE(text)
#define CASE(str) if ([__s__ isEqualToString:(__STRINGIZE(str))])
#define SWITCH(s) for (NSString *__s__ = (s); __s__; __s__ = nil)
#define DEFAULT
```
今更ながらHerokuで"Hello World"が表示してみた

# 「herokuとは」でぐぐる
いまときのレンタルサーバーやいまどきのホームページスペースとのこと。

# ものは試し
ユーザ登録と簡単なインストールをすれば、herokuコマンドを使って
heroku上にデプロイできるらしい。


## ユーザ登録
メールアドレス入力後、メールで送られてくるアカウント活性化URLを選択する

## Dashboardの指示通りにセットアップ

1.Download Heroku Toolbelt for Mac OSでHerokuをインストールする
2.サンプル・アプリケーションをcloneする

```
git clone git://github.com/heroku/ruby-sample.git
```
3.鍵の設定

```~/.ssh.config
HOST heroku.com
    User git
    HostName heroku.com
    identityfile ~/.ssh/id_rsa_heroku
```

4.herokuにログインする 

```
cd ruby-sample
heroku login
Email: kkam0907@japan.com
Password: your-password
```

5.herokuを作成する

```
heroku create

Creating floating-hollows-2171... done, stack is cedar
http://floating-hollows-2171.herokuapp.com/ | git@heroku.com:floating-hollows-2171.git
```

6.herokuサーバへデプロイする

```
git push heroku master
```
7.デプロイされたか確認する

```
heroku open
```

![スクリーンショット 2014-07-23 18.58.02.png](https://qiita-image-store.s3.amazonaws.com/0/34039/e2bb7e90-2612-f214-a5ba-c293227782b8.png)
chef内蔵のgemを使ってモジュール追加する


`chef`は自分の内部に`ruby`や`gem`を持っているので、それを利用して`knife-solo`や`berkshelf`をインストールする方法。

```bash
# /opt/chef/embedded/bin/gem install knife-solo  berkshelf --no-ri --no-rdoc
```

パスだけ覚えておけばOKですね。
プロフィールに項目を追加する方法

初めてdrupalを触っているので、初歩的なことも、備忘録として投稿

Field
Field UI
Field SQL storage
File
Image
List
Text
Options
のモジュールを有効にしていなかったら、有効にして
ホーム » 管理 » 環境設定 » ユーザー » アカウントの設定
から追加