OmniAICreator/Qiita-1.07M huggingface dataset:
複雑なソートを簡単に実現する方法（Java8とそれ以前）

Java7まで大活躍してくれたComparatorChain へのお別れブログです。

Java8では本当にソートが楽になりました。 
これだけで終わってしまいます。
昇順、降順の組合せもお手軽です。

```java:java8
//テストデータ作成
List<Person> testParsonList = this.createTestDataBeanList();

List<Person> resultParsonList = testParsonList.stream()
   .sorted(comparing(Person::getName, nullsLast(reverseOrder()))
   .thenComparing(Person::getAge))
   .collect(toList());
```

Java7までは、Apache commonsのComparatorChainで複数のソート項目指定、昇順降順の混在などの複雑なソートを実現していました。
非常にコード量が少なく簡単にソート実現できます。
コードは以下です。

```java:Java7以下 
//テストデータ作成
List<Person> testParsonList = this.createTestDataBeanList();

ComparatorChain comparator = new ComparatorChain();
//ソート項目と昇順、降順を指定。
comparator.addComparator(
    new BeanComparator<Person>("name",new NullComparator()), true);
comparator.addComparator(
    new BeanComparator<Person>("age",new NullComparator()));

//sort実行
Collections.sort(testDataBeanList, comparator);
```

※どちらもソートクラスにはソート項目分の引数を持ったコンストラクタが必要です。
ソートの種類が複数必要な場合は、ソートの種類によってコンストラクタを増やします。

```java:beanの例

  //※変数定義は省略します。

  public Person(final String name, final int age) {
    this.name = name;
    this.age = age;
  }

  public Person(final String name, final int age, final address) {
    this.name = name;
    this.age = age;
    this.address = address;
  }

  public String getName() { return name; }
  public int getAge() { return age; }

  public int ageDifference(final Person other) {
    return age - other.age;
  }

  public int nameDifference(final Person other) {
	    return name.compareTo(other.name);
  }

```

必要となるjarは以下です。

- commons-collections-3.2.1.jar
- commons-bean utile-1.9.2.jar

組合せについては、以下を参考にしました。
http://central.maven.org/maven2/commons-beanutils/commons-beanutils/1.9.2/commons-beanutils-1.9.2.pom
あとはこの辺です。
http://mvnrepository.com/artifact/commons-collections/commons-collections/

genericsを使用できるバージョンの組合せは出ていません。
とても残念です。
配列結合演算子, array_merge, array_replace を徹底比較

# 導入

PHPで配列を結合するための方法は幾らかありますが、それぞれ微妙に挙動が異なるので、ここでは違いが分かりやすいようにまとめてみます。

# 比較

## 早見表

[`array_merge`]や[`array_merge_recursive`]の挙動にはかなりクセがあるのでご注意を。

|手段 ＼ キー |未定義整数|未定義文字列|重複整数|重複文字列|
|:---:|:---:|:---:|:---:|:---:|:---:|
|[配列結合演算子 `+`]|追加|追加|無視|無視|
|[`array_merge`]|連番に直して追加|追加|連番に直して追加|上書き|
|[`array_replace`]|追加|追加|上書き|上書き|
|[`array_merge_recursive`]|連番に直して追加|追加|連番に直して追加|可能な場所まで相互に再帰<br />↓<br />双方を配列にキャスト<br />↓<br />[`array_merge`]を用いて結合|
|[`array_replace_recursive`]|追加|追加|可能な場所まで相互に再帰<br />↓<br />上書き|可能な場所まで相互に再帰<br />↓<br />上書き|

## PHP関数としての表現

自信があまり無いので間違い等ありましたらご指摘ください。

```php:配列結合演算子&nbsp;+
function plus(array $base, array $another) {
    foreach ($another as $key => $value) {
        if (!array_key_exists($key, $base)) {
            $base[$key] = $value;
        }
    }
    return $base;
}
```

```php:array_merge
function array_merge(array $base, array ...$others) {
    foreach ($others as $other) {
        foreach ($other as $key => $value) {
            if (is_int($key)) {
                $base[] = $value;
            } else {
                $base[$key] = $value;
            }
        }
    }
    return $base;
}
```

```php:array_replace
function array_replace(array $base, array ...$others) {
    foreach ($others as $other) {
        foreach ($other as $key => $value) {
            $base[$key] = $value;
        }
    }
    return $base;
}
```

```php:array_merge_recursive
function array_merge_recursive(array $base, array ...$others) {
    foreach ($others as $other) {
        foreach ($other as $key => $value) {
            if (is_int($key)) {
                $base[] = $value;
            } elseif (array_key_exists($key, $base)) {
                if (is_array($base[$key]) && is_array($value)) {
                    $base[$key] = array_merge_recursive($base[$key], $value);
                } else {
                    $base[$key] = array_merge((array)$base[$key], (array)$value);
                }
            } else {
                $base[$key] = $value;
            }
        }
    }
    return $base;
}
```

```php:array_replace_recursive
function array_replace_recursive(array $base, array ...$others) {
    foreach ($others as $other) {
        foreach ($other as $key => $value) {
            if (array_key_exists($key, $base) && is_array($base[$key]) && is_array($value)) {
                $base[$key] = array_replace_recursive($base[$key], $value);
            } else {
                $base[$key] = $value;
            }
        }
    }
    return $base;
}
```


[配列結合演算子 `+`]: http://www.php.net/manual/ja/language.operators.array.php
[`array_merge`]: http://www.php.net/manual/ja/function.array-merge.php
[`array_merge_recursive`]: http://www.php.net/manual/ja/function.array-merge-recursive.php
[`array_replace`]: http://www.php.net/manual/ja/function.array-replace.php
[`array_replace_recursive`]: http://www.php.net/manual/ja/function.array-replace-recursive.php
音楽系APIの一覧


## World Wide

### Echo Nest
- http://developer.echonest.com/

### Gracenote
- https://developer.gracenote.com/ja/web-api

### YouTube
- https://developers.google.com/youtube/js_api_reference

### SoundCloud
- https://developers.soundcloud.com/docs

### Last.fm
- http://www.lastfm.jp/api

### Rdio
- Can't access the dev page from Japan
- http://www.rdio.com/developers/

### iTunes Search API
- http://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html

### Beats Music
- https://developer.beatsmusic.com/page

### Billboard Ranking
- RSS
- http://www.billboard.com/rss/charts/hot-100


### MusicBrainz
- Opensource Music meta data
- http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2

### Echoprint
- Open source music identification
- http://echoprint.me


## For Japanese

### Oricon Ranking Unofficial API
- Most popular music ranking in Japan
- http://www.oricon.co.jp/api/ranking/xml/rankingdata.xml

### wasabeat
- Club music meta data API
- http://developers.wasabeat.com/

### Shazam Japan Top 100 Popular Songs
- Only webpage
- http://www.shazam.com/charts/jp_top_100
モバイルフレンドリーなサイトのキャッシュ

デバイスによってコンテンツを出し分けたい場合のキャッシュについて。

# 構成

アプリケーションで返したコンテンツをVarnishでキャッシュする([Cache Proxyパターン](http://aws.clouddesignpattern.org/index.php/CDP:Cache_Proxy%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3))。
デバイスごとにコンテンツを出し分けたい場合、以下の処理が必要になる。

- アプリケーション  
UA判定し、ページ(テンプレート)を出し分ける
- Varnish  
UA判定し、キャッシュを出し分ける

# 実装

自前でライブラリを作ってもいいのですが、PHPに関しては、以下のライブラリが使えます。
https://github.com/serbanghita/Mobile-Detect

様々なフレームワークに対応したモジュールがありますし、なんと、Varnishのモジュールも提供されています！(3rd party)
https://github.com/willemk/varnish-mobiletranslate

これで、Varnishと(PHP)アプリケーションのUA判定を統一して管理することが出来て便利です！
※ちなみに、VarnishとアプリケーションのUA判定が統一されていないと、キャッシュの不具合が起きるので要注意です。
特定リージョンのec2の操作を禁止した上で他リージョンでRDSを使うIAMポリシー

ec2を東京リージョンを使っているのでそこの操作や閲覧を禁止した上で、
東京以外のリージョンでRDSを検証をしたいというよくある（？）状況で使えるIAMのポリシーです。

ドキュメントを見ると、

```http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/UsingWithRDS.IAM.html
Amazon RDS コンソールの使用に必要なアクセス許可
Amazon RDS コンソールを使用するユーザーには、特定のアクションを実行するためのアクセス許可だけでなく、コンソール自体に必要になるアクションを実行するためのアクセス許可も付与する必要があります。たとえば、単にリソースを一覧表示するには、コンソールでは DescribeSecurityGroups や DescribeSubnets などの API アクションを実行します。コンソールを使用するユーザーには、これらのアクションを実行するためのアクセス許可が必要です。それらのアクセス許可がない場合、ユーザーは作業する必要のあるコンソールの一部で、タスクに対するアクセス許可がないというメッセージが表示されます。
```

とあり、どうやらマネジメントコンソールでアクセスするためにはRDSの他にec2やcloudwatch、snsの許可設定も必要とのことです。しかし、

```
"Resource":"arn:aws:rds:us-east-1:111111111:*"
```
```
"StringEquals": {
  "*:Region": "us-east-1"
}
```

などと、特定リージョンのみ指定したポリシーを作成しましたが、マネジメントコンソールでRDSへ移動すると以下のエラーが出てしまいます。

![マネジメントコンソールのエラー.png](https://qiita-image-store.s3.amazonaws.com/0/52904/803dc699-d2e5-b676-3d53-1612224c5a4c.png)


いろいろパラメーラーを変えているうちにアクセスしようとしているリージョンに加えて、他のリージョンの情報も取得できなければうまく表示できないっぽいことがわかってきました。
ということで結局、すべてのリージョンのRDS/ec2/cloudwatch/snsなどの必要なパラメータを許可した上で東京リージョンのec2は禁止するというポリシーにしたところうまくいきました。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds:*",
                "ec2:Describe*",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:DescribeAlarms",
                "sns:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Deny",
            "Action": [
                "ec2:*"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "ec2:Region": "ap-northeast-1"
                }
            }
        }
    ]
}
```
メモ：std::conditionalでif～else if～elseみたいなことをしようとすると見づらい

`std::conditional`をがしがし書いてると、なんだか冗長だしどうやって整形したらいいのか分からないです。

```cpp:c++
template<bool condition, typename IfTrue, typename IfFalse>
using conditional_t = typename std::conditional<condition, IfTrue, IfFalse>::type;

template<typename T>
using bar =
    conditional_t<cond1, type1,
        conditional_t<cond2, type2,
            conditional_t<cond3, type3,
                default_type>>>;
```
ネストがよく分かりません。

```cpp:c++
template<typename T>
using bar =
    conditional_t<cond1,
        type1,
        conditional_t<cond2,
            type2,
            conditional_t<cond3,
                type3,
                default_type
            >
        >
    >;
```
if文っぽく整形してみてもダサい。

```cpp:c++
template<typename T>
using bar =
    conditional_t<cond1, type1,
    conditional_t<cond2, type2,
    conditional_t<cond3, type3,
    default_type>>>;
```
むしろこの方がマシなような気もしますが、最後の連続する山括弧はどうにかならないものでしょうか。

という訳で、こんな解決策はどうでしょう。

```cpp:c++
template<typename ...Args>
struct first_enabled {};

template<typename T, typename ...Args>
struct first_enabled<std::enable_if<true, T>, Args...> { using type = T; };
template<typename T, typename ...Args>
struct first_enabled<std::enable_if<false, T>, Args...>: first_enabled<Args...> {};
template<typename T, typename ...Args>
struct first_enabled<T, Args...> { using type = T; };

template<typename ...Args>
using first_enabled_t = typename first_enabled<Args...>::type;
```
`std::enable_if<T>`を並べて、最初に条件が真になった型になるテンプレートエイリアス。
`std::enable_if<T>`以外の型が渡されると常に条件が真とみなしてその型になるので、最後にデフォルトを追加することも可能。
上の例をこれをつかって書き直すと、こうなる。

```cpp:c++
template<typename T>
using bar = first_enabled_t<
    std::enable_if<cond1, type1>,
    std::enable_if<cond2, type2>,
    std::enable_if<cond3, type3>,
    default_type
>;
```
式が短くなったりはしないが、分かりやすくはなっている気がします。

##
Python で Amazon S3 のバケットからバケットへファイル移動

はじめに
---
S3 のバケットからバケットにファイルを移動したいときには、一番簡単なのは AWS CLI の S3 cp を使う方法がある。

[AWS CLI Reference - S3 cp](http://docs.aws.amazon.com/cli/latest/reference/s3/cp.html?highlight=copy)

でもファイル名にとある加工がしたかったので Python で、名前を変更しながらバケットからバケットにファイルをコピーするスクリプトを書いてみた。

こまりごと
---
とあるソフトが吐くファイル名が "YYYYMMDD_<英語名>_<日本語の漢字とかひらがなとか特殊記号とか>" みたいな形になっていて、前の部分の日付と英語名だけでじゅーぶんですよ、という気分になっていた。後ろの日本語とか雑多な記号を取り払いながら、他のバケットに出力することにした。

別に同じバケットでもいいけど S3 の良いところはバケットを分けてあげると、何かとその後の管理が楽になる。S3 バケットは 1 アカウントで 100 個まで作れて、お金もかからないのでなるべく役割や目的で分けてあげた方が良いと思う。  

かいたもの
---

ちょっと前に書いたのでなんでそう書いたか思い出せないところがある。頭の棚が傷んでるから仕方ない。

あと文字の判定の条件文がきれいに書けなくて悔しかったので、そこは載せてないです。

```s3rename.py
from boto.s3.connection import S3Connection, Bucket, Key

S3_BUCKET_NAME = 'Yourbacketname'
S3_DST_BUCKET_NAME = 'Yourdestinationbucketname'

conn = S3Connection()
bucket = conn.get_bucket(S3_BUCKET_NAME)
# S3 にアクセスしてバケット内のオブジェクト一覧取得

rs = bucket.list()

for key in rs:
#取得したオブジェクトの一覧の各キーについて以下のような処理を実施

    k=Key(bucket) 
    filename = key.name

#キーの名前（ファイル名）を加工したい...

    result = u''
    for c in filename:

#filename の一文字ずつについて

       if condition:

#とある条件(特殊記号やマルチバイトを含まない純粋な英数字か？)にマッチしたら、その時だけ文字列を新しいファイル名に追加

          result += c
    print result

k.key=filename
k.copy(S3_DST_BUCKET_NAME, result)

#ファイルを出力したい先のバケットにファイルをコピーして終了

k.delete()

#元バケットのファイルはいらないから消した。別に残しておいてもいいと思う。

```

おわりに
---
とりあえず思った通りに動いたけど、もしかすると要らない記述が混じっている感じがする。
今のように直感的でなくもうちょっとちゃんと理解して書けるようになりたいところ。
Open Hack Day 3反省会

## Open Hack Dayとは

Yahoo!の中の人が社内イベントとしておこなっていたハッカソン「Hack Day」を一般公開して誰でも参加できるようにしたイベント。毎年開催しているようで、今年で3回目。
ルールは会期中の24時間以内で開発をすることというだけで、テーマは自由。チームの人数も自由（ただしぼっち参加は不可）。

スポンサー企業からの製品紹介などの時間はなく、いきなり開発開始！からのいきなり発表！でした。製品紹介的なことは一月前のカンファレンスでやってたのかな？
前回TechCrunchのハッカソンは各企業の製品紹介からチームビルディングまでじっくりやってから開発に挑んだのとは対照的でした。

## 作ったもの

街中でトイレに行きたくなった時、もし近くにトイレを貸してくれる人がいたら？
トイレに行きたい人とトイレを貸してくれる人をマッチングしてくれるサービスがあったら？

というわけで作ってみました。

![unterest.png](https://qiita-image-store.s3.amazonaws.com/0/56668/ba4cf245-fb0f-4d04-ea6c-9da690038773.png)

「Unterest」です。

### ストーリー

1. トイレを探す人とトイレを貸してくれる人がそれぞれページを開いています。
2. トイレを探す人は位置情報を送信して、近くのトイレを貸してくれる人を検索します。
3. 近くのトイレが見つかるとトイレの件数が表示されます。
4. トイレを貸してください！ボタンを押すと該当トイレのオーナーに通知が飛び、貸してあげるかどうかを回答する画面が出ます。
5. トイレを貸してくれるかどうかの返答が表示されます。
6. 貸してくれるトイレはルートを検索したりや詳細情報を見たりできます。

### 使った技術

リコーのTHETAを使って[トイレを360度撮影して](https://dl.dropboxusercontent.com/u/11794879/toilet360/index.html)、実際に座った時のイメージを確認することができるようにしました。
このページは独自開発の360度写真ビュワーライブラリの[Angular360](https://github.com/ejeinc/Angular360)を使用しています。

サーバーサイドは[Node.js](https://nodejs.org/)、トイレの位置情報からクエリできるように[MongoDB](http://www.mongodb.org/)でデータを持ちました(登録機能とか作れなかったのであんまり意味ないけど)。

## 反省点

### 発表会場のインターネット回線をあてにしてはいけない

いざ発表する時になってうまく動かない！っていうのはもはやハッカソンのお約束感ありますが、その原因として真っ先に思いつくのはインターネット接続環境ではないかと思います。
特に開発する部屋と発表する部屋が違う場合で、現地のインターネット接続環境を確認できない場合は**最悪完全にオフラインでも動作する状態にしておく**のがベター。

また、**Wi-Fiも信用してはいけません。**最近みんなモバイルルーター持ち歩いてますが、ああいう機器が**一部屋に10個も20個もあったら電波が混信して通信なんてできません。**
どうしてもネットワーク構築が必要な場合は有線でローカルネットワークを組むのが安全かと思います。

今回は幸い携帯回線が繋がりやすかったため、デモは携帯回線で行うことで対応しました。モバイルファーストなデザイン・機能だったことが不幸中の幸い？

### 発表のことも考えよう

ハッカソンは短い時間で製品作る遊びですが、作ったら作りっぱなしというわけにはいきません。発表が必要です。
その時によって発表の方法も時間も違います。その場での動作デモを主軸にするか、ビデオやプレゼン資料で済ませるか。
いずれにしても話す内容・段取りをきちんと考えて、**必要なことは言う・不要なことは言わない**というのをできれば開発前にある程度考えておくと良いなと思いました。


## 運営に伝えたいこと

### 90秒は短い

チーム数多いから全員発表すること考えたらこうなるのは仕方ないけど、それにしても**90秒は短いです！！**
発表時間が短いということは、必然的に作ったものを完全に披露することはできません。プレゼンやビデオでの紹介なんて極端な話**開発してなくてもできる**わけですから、それで済ませちゃったらせっかくのハッカソンの意味がなくないですか？

むしろ、全員発表をするということをやめて、展示会の時間を長めにするとか。
その中で審査員達が「これは！」と思ったチームだけピックアップして発表するとか。

せっかく作ったものだからきちんと細かいとこまで伝えたいですよね。


### 食事とか出るなら教えてほしい

食事の提供はありませんと書いてあったから当日お菓子とかジュースとかわざわざ買いに行ったのに、割とたくさん軽食の提供がありました。結果、半分くらい荷物として持って帰るはめになりました。
前日でも良いから、食事の提供がわかっていたならそう書いておいてほしかったです。

### インターネット繋げないならそう言ってほしい

発表会場は地下一階ということで、WiMAXは電波が入らず。
携帯のテザリングをしようにも会場内でWi-Fiの電波が混信して通信できず。
**「会場のインターネット接続は各自で準備してください」といいつつ実際のところ準備のしようがなかった。**
それなら最初から「発表時はインターネット接続は行えないものと考えて準備をしてください」と言っておいてほしかったです。

---

…とまぁ、いろいろ思うところはありますが、とはいえハッカソンで得た経験値はとても大事なのでまた機会あれば参戦したいなと思います。

できればもう少し少人数で、開発時間も数時間程度のゆるーいやつがいいな。
文字列によるXML宣言とPHP終了タグ判定の罠

# 概要

```php:example.php
$string_xml = '<?xml version="1.0" encoding="utf-8"?>hogehogehoge';
```

こんなコードを書いてるときに

```php:example.php
// $string_xml = '<?xml version="1.0" encoding="utf-8"?>hogehogehoge';
```

こんな感じで１行コメントを書くとエラーになる！

# なんで？

```php:example.php
// $string_xml = '<?xml version="1.0" encoding="utf-8"?>hogehogehoge';
```

encoding="utf-8"
の後の
**?>**

が１行コメントによりStringとはみなされなくなりPHP終了タグ判定されてしまう！

# 対策

複数行コメントにするとか効率云々のこと無視していいのであれば

```php:example.php
$string_xml = '<?xml version="1.0" encoding="utf-8"?'.'>hogehogehoge';
```

こんな感じで文字列連結する形で書いておくといいかもしれませんね。

# 備考

\# そもそもなんでこんなコード書いてるの？みたいな質問は勘弁してください…
.htaccessメモ

###該当ファイルへのアクセスをリダイレクト
```
RedirectMatch 301 /test http://yahoo.co.jp

```
###UAに応じてリダイレクト
```
RewriteCond %{HTTP_USER_AGENT} !(iPod|iPhone|iPad|Android)
RewriteRule ^sp/(.*)$ / [R=301,L]

RewriteCond %{HTTP_USER_AGENT} (iPhone|iPod|iPad|Android) [NC]
RewriteRule ^$ /sp/ [R=301,L]

RewriteCond %{HTTP_USER_AGENT} !Twitterbot [NC]
RewriteRule ^$ /pc/ [R=301,L]
```
###FBやmixiのクローラを許可
```
order deny,allow
deny from all

Allow from env=fb_crawler
Allow from env=fb_crawler2
Allow from env=mixi_crawler

```
###basic認証
```
AuthUserFile /home/hogehoge/.htpasswd
AuthGroupFile /dev/null
AuthName "Please enter your ID and password”
AuthType Basic
require valid-user
```
秒あたりのデータ転送量の計算


# 1秒あたりのデータ転送量計算式

いつも忘れるのでメモ

## 3Mbps 回線だと

```
(3 * 0.8) / 8 = 0.3MB
```

## 例えばそこいらにあるスマホアプリの回線速度計測ツールで、下り16.69Mbpsとか出た場合はッ

```
(16.69 * 0.8) / 8 = 1.669MB
```

1秒あたり 1.669MB のファイルがDLできる。
しかし最近のスマホ回線は早いな。

- 因に * 0.8 は、転送ロスを2割と見なし、それを間引く為の計算。

## 今、手持ちの iPhone 5 で 4G をオフにし、3G でそこいらの回線速度計測ツールを走らせたところ、3.09Mbps

```
(3.09 * 0.8) / 8 = 0.309MB
```

（…なんか3Gも結構早いな）
例えば、スマホサイトで大胆にも 1MB の画像を載せようと思った場合、同時ファイルダウンロード数制限のブロッキングや、サーバのレスポンス遅延が全くないとしても、3秒ちょいはかかることに。

いや、しかし 4G 早いぞ。
LeoFSをビルドして試す

LeoFSの`README.md`を見るとErlangのインストールとかXFSのセットアップとか書いてあるのだけど、ちょっと試してみる分にはディストリビューションのリポジトリにあるErlangでも動く。気軽に触ってみるにはこれで十分。

あんまり新しいErlangだとサポートされてないと思うので、本番で使う時は公式にあるパッケージを使うか、ドキュメント通りにビルドする方がよい。パッケージにはサポートされているerlangのランタイムごと入っているので便利。

OSにはFedora 21 Workstationを使用。`README.md`に書いてある依存はあらかじめインストールしておく。

```bash
sudo dnf install libuuid-devel cmake check check-devel
```

現在インストールされているErlangのライブラリは

```
erlang-hipe-17.4-1.fc21.x86_64
erlang-et-17.4-1.fc21.x86_64
erlang-snmp-17.4-1.fc21.x86_64
erlang-wx-17.4-1.fc21.x86_64
erlang-xmerl-17.4-1.fc21.x86_64
erlang-ssl-17.4-1.fc21.x86_64
erlang-eunit-17.4-1.fc21.x86_64
erlang-stdlib-17.4-1.fc21.x86_64
erlang-otp_mibs-17.4-1.fc21.x86_64
erlang-sasl-17.4-1.fc21.x86_64
erlang-observer-17.4-1.fc21.x86_64
erlang-compiler-17.4-1.fc21.x86_64
erlang-asn1-17.4-1.fc21.x86_64
erlang-reltool-17.4-1.fc21.x86_64
erlang-kernel-17.4-1.fc21.x86_64
erlang-runtime_tools-17.4-1.fc21.x86_64
erlang-inets-17.4-1.fc21.x86_64
erlang-erts-17.4-1.fc21.x86_64
erlang-sd_notify-0.1-5.fc21.x86_64
erlang-os_mon-17.4-1.fc21.x86_64
erlang-public_key-17.4-1.fc21.x86_64
erlang-parsetools-17.4-1.fc21.x86_64
erlang-crypto-17.4-1.fc21.x86_64
erlang-tools-17.4-1.fc21.x86_64
erlang-syntax_tools-17.4-1.fc21.x86_64
erlang-erl_interface-17.4-1.fc21.x86_64
erlang-gs-17.4-1.fc21.x86_64
erlang-mnesia-17.4-1.fc21.x86_64
```

なんでこんなに入っているかというと、OpenStack環境を作った時にRabbitMQをインストールしたから。LeoFSをビルドする際に追加で必要になったパッケージは

```bash
sudo dnf install erlang-erl_interface
sudo dnf install erlang-eunit
sudo dnf install erlang-parsetools
sudo dnf install erlang-reltool
sudo dnf install erlang-gs
sudo dnf install erlang-observer
```

`erlang-gs`と`erlang-observer`は使ってない気がするんだけど、どうなんだろう……。

あとは`README.md`通りに

```bash
git config --global url."https://".insteadOf git:// # proxyの後ろにいるなら
git clone https://github.com/leo-project/leofs.git
cd leofs
git checkout -b develop remotes/origin/develop
./rebar get-deps
./git_checkout.sh develop
make
make release
```

要するに、Erlangパッケージの依存が解決できればおｋ。

他にも`leveldb-devel`とかが必要な気がしてならない……。とはいえ、パッケージの不足はビルドログから分かるので、適宜インストールをすればよいと思う。
少し複雑なProduct Flavorを設定する

単一のプロダクトのビルド環境をdev,stg,prd等で分ける構成の場合は、特に何も考えなくても`build.gradle`に`productFlavors`を設定するだけでできるのですが、複数のプロダクトを扱う場合には`productFlavors`の設定だけだとソースコードやリソースの重複が起こる場合があります。

### 例えば以下の様な構成

| フレーバー名 | ソースコード | リソース      |
|:------------|:-----------:|:------------:|
| google_dev  | A           | X1           |
| google_stg  | A           | X2           |
| google_prd  | A           | X3           |
| amazon_dev  | B           | Y1           |
| amazon_stg  | B           | Y2           |
| amazon_prd  | B           | Y3           |

#### 各フレーバー毎の差分（一例）

<dl>
  <dt>A</dt>
  <dd>google play service依存のソースコード, etc...</dd>
</dl>
<dl>
  <dt>B</dt>
  <dd>amazonのsdk依存のソースコード, etc...</dd>
</dl>
<dl>
  <dt>X1-X3</dt>
  <dd>google playストア用のメッセージ, etc...</dd>
<dl>
  <dt>Y1-Y3</dt>
  <dd>kindleストア用のメッセージ, etc...</dd>
</dl>

### こうなる

![google_prd_…_strings_xml_-__app__-_FlavorTest_-____IdeaProjects_FlavorTest_.png](https://qiita-image-store.s3.amazonaws.com/0/28162/f34bddb4-1b5f-a596-d755-10ead40f9d93.png)

### 問題点
* コピペ面倒
* ヒューマンエラー

### やりたいこと
* google_* フレーバー間で共通なソースコードを1箇所にまとめる
* amazon_* 〃

### やること

```groovy:build.gradle
productFlavors {

  google_prd {
    // ...
  }
  google_stg {
    // ...
  }
  google_dev {
    // ...
  }
  amazon_prd {
    // ...
  }
  amazon_stg {
    // ...
  }
  amazon_dev {
    // ...
  }
}
sourceSets {
  // google_mainディレクトリを作成、google_* フレーバー共通で使用するソースを配置
  google_dev.java.srcDirs = ['src/google_main/java']
  google_stg.java.srcDirs = ['src/google_main/java']
  google_prd.java.srcDirs = ['src/google_main/java']

  // 同上
  amazon_dev.java.srcDirs = ['src/amazon_main/java']
  amazon_stg.java.srcDirs = ['src/amazon_main/java']
  amazon_prd.java.srcDirs = ['src/amazon_main/java']
}
```

### 結果
![foo.png](https://qiita-image-store.s3.amazonaws.com/0/28162/a6dc9170-8de1-c3fb-c70b-529c587a217c.png)
解いてみた：これが10分でできない人は自分がかなりプログラミングができないというつらい事実を認識しましょう。

問題
---
(引用開始)
400：名前：名無しさん＠涙目です。(岐阜城)：2011/10/15(土) 18:51:50.10 ID:eMBuD7fo0
某所から拾ってきた。 
「これが10分でできない人は自分がかなりプログラミングができないというつらい事実を認識しましょう。」だそうな。

人数とカードが与えられたとき、分配後のカードを配列として返す関数を作成せよ。 
カードは与えられた文字列の前から順番に配られ、配られるカードの枚数は均等で余りは無視することとする。
（引用終了）
http://qiita.com/hisui@github/items/b47c411437d60440a605

回答
---
問題を明確には理解できなかったけど、以下のような感じだろうか。かかった時間は約5分くらい。

```py
def card_distributer(number, cards):
  card_list = [ [] for i in range(number) ]
  while ( len(cards) // number ) > 0:
    for i in range(number):
      card_list[i].append(cards.pop(0))
  return card_list

print card_distributer(3,['SA', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'S8', 'S9', 'S10', 'SJ', 'SQ', 'SK'])
```

出力

```py
[ ['SA', 'S4', 'S7', 'S10'], ['S2', 'S5', 'S8', 'SJ'], ['S3', 'S6', 'S9', 'SQ'] ]
```
AWSSDKforPHP S3

簡易的にS3を利用するメモ
参照：[AWSSDKforPHP](http://docs.aws.amazon.com/aws-sdk-php/latest/class-Aws.S3.S3Client.html)

``` php:S3Model.php
/*
$s3Config = array(
	'access_key' => 'ahoge', // アクセスキー
	'secret_key' => 'shoge', // シークレットキー
	'bucket'     => 'bhoge'  // バケット名
	);
*/
// S3接続
function connectS3($s3Config, $createFlg = true) {
	$this->_initS3($s3Config);
	$result = $this->_existBucket($s3Config['bucket']);
	
	// バケットが存在しない場合、新規作成
	if (!$result && $createFlg) {
		$this->s3->createBucket(array(
			'LocationConstraint' => 'ap-northeast-1', 
			'Bucket' => $s3Config['bucket']
			));
		/*
		LocationConstraintの値は以下から選択
			'ap-northeast-1'
			'us-west-2'
			'us-west-1'
			'eu-west-1'
			'eu-central-1'
			'ap-southeast-1'
			'ap-southeast-2'
			'sa-east-1'
		
		ロケーションにより、S3の利用速度が変わってきます。
		「ap-northeast-1」（Tokyo）固定で良いかも。
		*/
	}
}


// S3利用準備
private function _initS3($s3Config) {
	if (isset($this->s3)) return;

	$params = array(
		'key'      => $s3Config['access_key'],
		'secret'   => $s3Config['secret_key'],
	);
	$this->s3 = S3Client::factory($params);
}


// バケット確認
private function _existBucket($bucketName) {
    $bucketList = $this->s3->listBuckets();
    foreach ($bucketList["Buckets"] as $bucket) {
        if ($bucket['Name'] === $bucketName) {
            return true;
        }
    }
    return false;
}

// バケット削除
function deleteBucket($s3Config) {
	$this->_initS3($s3Config);

	// 削除するバケットのリージョンを設定
	$this->s3->setRegion('ap-northeast-1');

	return $this->s3->deleteBucket(array(
		'Bucket' => $s3Config['bucket']
		));
}
rbenv-around-installでglobal gemsetにbundle installしてrehashまで自動化する


# 前提

### プラグイン

下記のrbenvプラグインをインストールしておくこと。

* [ruby-build](https://github.com/sstephenson/ruby-build)
* [rbenv-gemset](https://github.com/jf/rbenv-gemset)
* [rbenv-around-install](https://github.com/toy/rbenv-around-install)

### Gemfile

rbenvでRubyをインストールしたあと自動的にインストールしたいgemを書いておく。
ホームディレクトリにGemfileが置いてある。

# rbenv-around-installとは

> Automatically run `~/.rbenv/before-install` before and `~/.rbenv/after-install` after `rbenv install`. Add extension `.eval` to eval instead of running those binaries. Don't forget to run `chmod u+x ~/.rbenv/before-install ~/.rbenv/after-install`. Note that without `.eval` extension it must be a bash script, otherwise it can be any proper executable.

という感じで、Rubyのインストール前後にスクリプトを実行できるプラグイン。
Rubyのインストール前に `~/.rbenv/before-install` が実行され、インストール後に `~/.rbenv/after-install` が実行される。

# after-installスクリプトの作成

`~/.rbenv/after-install` を作る。実行権限をつけておくこと。
`$RBENV_VERSION` には直前にインストールしたRubyのバージョンがセットされる。
また、スクリプト実行中のRubyバージョンは直前にインストールしたRubyになっているので、gemのインストール先は自動的にインストールしたRubyが対象になる。

```sh:~/.rbenv/after-install
#!/bin/bash

rbenv gemset create $RBENV_VERSION global

RBENV_GEMSETS=global gem install bundler
rbenv rehash

bundle install --gemfile ~/Gemfile
rbenv rehash
```

# Rubyをインストール

```shell-session
$ rbenv install 2.2.1
Downloading openssl-1.0.1l.tar.gz...
-> http://dqw8nmjcqpjn7.cloudfront.net/b2cf4d48fe5d49f240c61c9e624193a6f232b5ed0baf010681e725963c40d1d4
Installing openssl-1.0.1l...
Installed openssl-1.0.1l to /Users/ryo0301/.rbenv/versions/2.2.1

Downloading ruby-2.2.1.tar.gz...
-> http://dqw8nmjcqpjn7.cloudfront.net/5a4de38068eca8919cb087d338c0c2e3d72c9382c804fb27ab746e6c7819ab28
Installing ruby-2.2.1...
Installed ruby-2.2.1 to /Users/ryo0301/.rbenv/versions/2.2.1

Running for 2.2.1: /Users/ryo0301/.rbenv/after-install
created global for 2.2.1
Fetching: bundler-1.8.5.gem (100%)
Successfully installed bundler-1.8.5
Parsing documentation for bundler-1.8.5
Installing ri documentation for bundler-1.8.5
Done installing documentation for bundler after 2 seconds
1 gem installed
Fetching gem metadata from https://rubygems.org/........
Fetching version metadata from https://rubygems.org/..
Installing awesome_print 1.6.1
    :
Installing pry 0.10.1
Using bundler 1.8.5
Bundle complete! 6 Gemfile dependencies, 15 gems now installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.
```
docker-machineのシングルコマンドで、docker-host作成する

`docker-machine` を使うと `docker` daemonを local-machineかcloud-providerに簡単インストールできます。

## 環境 *NIX
* docker




まず`docker-machine` binaryファイルをダウンロードします。
`https://docs.docker.com/machine/`

バージョン確認(OS X)

```
$docker-machine -v
docker-machine_darwin version 0.1.0
```


#### ローカルにインストール（`virtualbox`が必須です）

```bash
$ docker-machine create --driver virtualbox dev
INFO[0000] Creating SSH key...
INFO[0000] Creating VirtualBox VM...
INFO[0007] Starting VirtualBox VM...
INFO[0007] Waiting for VM to start...
INFO[0038] "dev" has been created and is now the active machine
INFO[0038] To connect: docker $(docker-machine config dev) ps
```


#### google-cloudにインストールします
```bash 
$ docker-machine create -d google --google-zone asia-east1-b --google-project awesome-project dev-gcp
```


docker-host一覧

```bash
$ docker-machine ls
NAME      ACTIVE   DRIVER         STATE     URL
dev       *        virtualbox     Running   tcp://192.168.99.103:2376
dev-gcp            google         Running   tcp://104.155.212.199:2376
staging            digitalocean   Running   tcp://100.236.50.118:2376
```


#### `dev-gcp`に mongodb containerをインストール（３０秒以内！）


    $ docker `docker-machine config dev-gcp` run --name mongodb-3.0 -d mongo:latest
    cc7aded0fb5439c6e54edd6234e06dd61c374248a9a42191f256d461d3c5xxxx
    $ docker `docker-machine config dev` ps -a

```bash
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS               NAMES
cc7aded0fb54        mongo:latest        "/entrypoint.sh mong   4 seconds ago       Up 3 seconds        27017/tcp           mongodb-3.0
```

#### mongodb-containerを`cli`にします
    $ docker `docker-machine config dev-gcp` run --rm -t -i --name mongodb-3.0-cli mongo:latest /bin/bash

```bash
root@90c92aeb9f8f:/# mongo 172.17.0.5 // mongodb-containerの IPaddress
MongoDB shell version: 3.0.0
connecting to: 172.17.0.5/test
Welcome to the MongoDB shell.
For interactive help, type "help".
```


#### 作成したmachine(docker-host)に `ssh`接続します

```bash
$ docker-machine ssh dev-gcp
```


#### machineをremoveします。

```bash
$ docker-machine rm dev-gcp
INFO[0000] Deleting instance.
INFO[0001] Waiting for instance to delete.
INFO[0026] Deleting disk.
INFO[0027] Waiting for disk to delete.
```

docker machineはまだ productionではあるません。
でも、できることがたくさんあると思います。`cloudinit`の開発も進めています。
うちはもうproductionで使ってます。インスタンス作成めっちゃ便利です。
IDやクラス名でつかう英語の小話

# Sidebar

先日、イベントの懇親会での質問で、

> レスポンシブ対応で、サイドバーのカラムと落とすのがモヤっとするんですよね、サイドバーなのに。

というのがあった。

これ、確かにCSSのカラムレイアウトとか勉強しはじめると、右側・左側に`#sidebar`と名付けられたものがあり、なんとなく「メインに対し、**位置的に**横にあるやつ」っていうイメージあるんですが、別にSidebarはレイアウト上の名前ってわけではありません。

> 【名】〔新聞の主記事に対する〕補足［側面］記事◆【同】follow ; follow-up
> [sidebarの意味・用例｜英辞郎 on the WEB：アルク](http://eow.alc.co.jp/search?q=sidebar)

**〔新聞の主記事に対する〕補足［側面］記事**ってことで、別にレイアウト的に下にあったって、Sidebarです。
※これはこれで、メインでないものをなんでもかんでも `#sidebar` の中にいれるのは正しくない気もしますね。

# Hero

[TwitterのBootstrap](http://getbootstrap.com/components/)が流行り始めた頃、サンプルで「Hero」というのがメインビジュアル部に書かれているものがあった。

「え、なんでヒーロー？目立つから？」とか、なんかそういうジョークなのかなとおもってた。これもよくよく調べてみると、

> Hero image is a term used in web design for a specific type of web banner. A hero image is a large banner image, prominently placed on a web page, generally in the front and center.
> [Hero image：アルク](http://en.wikipedia.org/wiki/Hero_image)


Web広告
Webバナーのタイプとして、ってことなんだけど、なんかもっと語源ぽいのがどっかにあった気がする。
[追記:2015-03-17]
Web広告と書いてましたが、Bannerもまた広告とは限らないということで訂正しました。@kotarokさんありがとう！

今のBootstrapのComponentでは**Jumbotron**となっていて、こっちは大きなビルの壁面にあるような**巨大なディスプレイ**を意味するみたい。

# lede

**lede**はあんまり見たこと無いってひとの方が多いかもしれない。たまに海外サイトのHTMLとかをみてると、この文字列を見かける。使われている箇所は**リード文**的なところ。「**lead**じゃないの？」とかおもってたけど、これも調べてみると、

> 【名】〈俗〉（記事の）リード◆ジャーナリストの用語
> [ledeの意味・用例｜英辞郎 on the WEB：アルク](http://eow.alc.co.jp/search?q=lede)

でもなんでledeという綴りなのか、というのに対しては、本当に語源なのかわからないけど次のような記事があった。

> ニュース記事などの第一段落、オープニング・パラグラフのことを「lead paragraph(リード・パラグラフ)」といいますが、ジャーナリズムの世界、とくにアメリカではこれをあえてledeとつづることがよくあります。これは活字印刷の時代、鉛(lead)板が使われていたことから、混同をさけるため考えられたといわれています。
>[「Lede paragraph」って「lead paragraph」のスペルミス?](http://news.mynavi.jp/news/2013/08/30/035/)

ほー、って感じですね。

コード上の命名としても、**lead**だと意味が広いので、**前置きの文**というような意味であれば、あえて`.lede`と命名するのはアリかもなぁ、なんておもったりします。

しかし、このledeのことを知らない人からすれば、「leadのタイプミスしてますよ？」とか言われそうなので、仕事では使わないかもしれない。
git filter-branchでタイムゾーンを書き換える

svnのgit移行中、svn2gitでcloneしたレポジトリのタイムゾーンが0000になっていたので書き換えました。

GIT_AUTHOR_DATEの+0000を+0900（日本標準時間）に変更し、さらにGIT_AUTHOR_DATEとGIT_COMMITTER_DATEに代入しています。

```
git filter-branch -f --env-filter 'GIT_AUTHOR_DATE=`echo $GIT_AUTHOR_DATE | sed -e 's/+0000/+0900/'`; GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE' HEAD
```

本来ならsvn2gitを修正する方が良い気もしますがとりあえずこれで直しました。
Unityのアプリ設定ファイルを生成する

[このイベント](http://www.creativevillage.ne.jp/lp/cyberagent/)に参加したときにEditorでSettingsクラスがあるファイルを書き換えている話を聞いたのでこういう感じなのかなと思って書いてみました。自分は基本的にUnityをほとんど書いたことない人なのであっているかはわかりません。
プロジェクトのディレクトリ構造は下記のような構造です。

```:ProjectDirectory
ProjectName
|
|-- Assets
    |-- Editor
        |-- SettingsEditor.cs
    |-- Sctipts
        |-- Settings.cs
```

Editorで表示されるのは、APIHostをpull down menu(Local, Develop, Production)で選び、Createボタンを押すとSettings.csファイルが生成されるようになっています。下記がEditorのコードと設定画面になります。

```Editor/SettingsEditor.cs
using UnityEditor;
using UnityEngine;

public class SettingsEditor : EditorWindow
{

    public enum APIHost
    {
        Local,
        Develop,
        Production
    }

    APIHost _host;

    [MenuItem("Window/SettingsEditor")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow(typeof(SettingsEditor));
    }

    void OnGUI()
    {
        GUILayout.Label ("Host", EditorStyles.boldLabel);
        _host = (APIHost)EditorGUILayout.EnumPopup ("API Host", _host);
        if (GUILayout.Button ("Create")) {
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(System.IO.Directory.GetCurrentDirectory() + "/Assets/Scripts/Settings.cs"))
            {
                var host = "";
                switch (_host)
                {
                case APIHost.Local:
                    host = "http://127.0.0.1:8000";
                    break;
                case APIHost.Develop:
                    host = "http://develop.com";
                    break;
                case APIHost.Production:
                    host = "http://production.com";
                    break;
                }

                file.WriteLine ("using System;");
                file.WriteLine ("using System.Collections;");
                file.WriteLine ("using System.Collections.Generic;");
                file.WriteLine ("using UnityEngine;");
                file.WriteLine ("");
                file.WriteLine ("public static class Settings");
                file.WriteLine ("{");
                file.WriteLine (string.Format("    public static string Host = \"{0}\";", host));
                file.WriteLine ("}");
	    }
        }
    }
}
```

![Settings GUI](https://qiita-image-store.s3.amazonaws.com/0/38030/f13767b5-aa77-1126-8f6c-7ebe9e7b450f.png)

Createボタンを押すと下記のような中身のコードが生成され、設定値が変わるようになっています。

```Scripts/Settings.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class Settings

{
    public static string Host = "http://develop.com";
}
```

このようにやればいちいちコード上で書き換えたりせず、GUIの設定画面で設定を楽に書き換えられたりすると思います。
uGUIのパーツを一発生成

FacebookのUnity助け合い所でこんな質問投げさせてもらいました。

![Unityユーザー助け合い所.png](https://qiita-image-store.s3.amazonaws.com/0/50702/d8b74682-2248-3709-f6a2-58a371603ef4.png "Unityユーザー助け合い所.png")

これがですね、何をしたかったかというと、デバックモード用のUIを作りたかったんですよね。
必要な分だけコードで生成みたいな。

結果から言うと整備されていなさそうなので、
時間もないので、見つけたリンクのフォーラムの内容を参考に、
自己ソリューションしてみました。

一部RenderModeの改修があったようで直しました。


```uGUITest.cs
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
 
public class uGUITest : MonoBehaviour
{
    private void Start()
    {
        if (FindObjectOfType<EventSystem>() == null)
        {
            var es = new GameObject("EventSystem", typeof(EventSystem));
            es.AddComponent<StandaloneInputModule>();
        }
 
        var canvasObject = new GameObject("Canvas");
        var canvas = canvasObject.AddComponent<Canvas>();
        canvasObject.AddComponent<GraphicRaycaster>();
        canvas.renderMode = RenderMode.ScreenSpaceOverlay;
 
        var buttonObject = new GameObject("Button");
        var image = buttonObject.AddComponent<Image>();
        image.transform.parent = canvas.transform;
        image.rectTransform.sizeDelta = new Vector2(180, 50);
        image.rectTransform.anchoredPosition = Vector3.zero;
        image.color = new Color(1f, .3f, .3f, .5f);
 
        var button = buttonObject.AddComponent<Button>();
        button.targetGraphic = image;
        button.onClick.AddListener(() => Debug.Log(Time.time));
 
        var textObject = new GameObject("Text");
        textObject.transform.parent = buttonObject.transform;
        var text = textObject.AddComponent<Text>();
        text.rectTransform.sizeDelta = Vector2.zero;
        text.rectTransform.anchorMin = Vector2.zero;
        text.rectTransform.anchorMax = Vector2.one;
        text.rectTransform.anchoredPosition = new Vector2(.5f, .5f);
        text.text = "Yo 世界!";
        text.font = Resources.FindObjectsOfTypeAll<Font>()[0];
        text.fontSize = 20;
        text.color = Color.yellow;
        text.alignment = TextAnchor.MiddleCenter;
    }
}
```

このコードを空のオブジェクトにつけると、
ボタンが一つ生成される仕組みになっています。

これを再生すると、
![Untitled_-_OclusProject_-_PC__Mac___Linux_Standalone.png](https://qiita-image-store.s3.amazonaws.com/0/50702/694095c3-75be-1181-30dd-2adb539707f8.png "Untitled_-_OclusProject_-_PC__Mac___Linux_Standalone.png")

このようになります。
これが便利だなーって思ったのが、EventSystemがなかったら作ってね！って最初に入っているのがまだ使い慣れていない自分としては良いなと思いました。

…と、ここまで書いたところで、本来uGUIはこうゆう使い方するものじゃないのかなーなんて思い、デバック用のUIは引き続きOnGUIなんだなーって目が覚めました(笑)

うむ。
Babel で IE8 対応する地獄

IE8 対応が必要な JavaScript に [Babel][] (+ webpack) を使っているんだけど、素直に書くと動かないところがあったのでメモ。

とある事情により Polyfill も叶わない環境を想定している。

大体これと同じ内容:

* [Caveats · Babel](https://babeljs.io/docs/usage/caveats/#internet-explorer)


`class` を使うためには・・・
-------------------------------------------

`class` を使ったコードを Babel に変換させると `Object.defineProperties` を使って `class` 相当を実現させようとする。しかし、IE8 以下の古い IE には `Object.defineProperties` が無いため、エラーになる。

IE8 でも class が使いたいときは、[loose mode の es6.classes](https://babeljs.io/docs/usage/loose/#es6-classes) を使う:

~~~~~~~~~~~~~~class-test.js
class Foo {
  foo() { }
}
console.log(new Foo());
~~~~~~~~~~~~~~

~~~~~~~~~~~~~~sh:端末
# ダメ
$ babel class-test.js -o t.js
$ grep 'Object.defineProp' t.js | wc -l
1

# こうする
$ babel class-test.js -o t.js --loose es6.classes
$ grep 'Object.defineProp' t.js | wc -l
0
~~~~~~~~~~~~~~

loose mode はその名前の通り、コードが少なくなる代わりに ES6 の class の仕様とは少し違ってしまうので注意:

> Method enumerability
> Method assignment
> [Loose mode · Babel](https://babeljs.io/docs/usage/loose/#es6-classes)


Named exports を使うためには・・・
-------------------------------------------------

Named exports をする時、`class` と同様の問題が起きる。Named export とは:

~~~~~~~~~~~~~~~lib.js
export function foo() {
  console.log('foofoo');
}
~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~main.js
import * as lib from 'lib';
lib.foo(); // => foofoo
~~~~~~~~~~~~~~~

というように `foo` という名前を付けて `export` する書き方。（きちんとした名前知らない。要調査。）

この `lib.js` を babel にかけると:

~~~~~~~~~~~~~sh:端末
$ babel lib.js
"use strict";

exports.foo = foo;
Object.defineProperty(exports, "__esModule", {
  value: true
});

function foo() {
  console.log("foofoo");
}
~~~~~~~~~~~~~

このように IE8 では使えない `Object.defineProperty` を使ってしまう。

これは [loose mode の es6.modules](https://babeljs.io/docs/usage/loose/#es6-modules) を有効にすると良い:

~~~~~~~~~~~~~~~~~sh:端末
# ダメ
$ babel lib.js -o t.js
$ grep 'Object.defineProp' t.js | wc -l
1

# こうする
$ babel lib.js -o t.js --loose es6.modules
$ grep 'Object.defineProp' t.js | wc -l
0
~~~~~~~~~~~~~~~~~

こちらも副作用があるので注意が必要:

> es6.modules
> es6.modules
> 
> [Loose mode · Babel](https://babeljs.io/docs/usage/loose/#es6-modules)

2つに分かれているので注意。


他にも
----------

今回は困らなかったので紹介しないが、class での static method の継承が上手く行かない話や、getter/setter にも `Object.defineProperty` が使われる話が、[Caveats · Babel](https://babeljs.io/docs/usage/caveats/#internet-explorer) に書かれている。

おわり。そもそも IE8 対応がつらい。

参考にしたもの
-----------

* [Loose mode · Babel](https://babeljs.io/docs/usage/loose/)
* [Caveats · Babel](https://babeljs.io/docs/usage/caveats/#internet-explorer)

[babel]: https://babeljs.io/
defclass metaclass に structure-class を使うと


On SBCL 1.2.8. 不思議、なぜ動く？ 他でも動く?

```cl
(defclass kons (structure-object)
     ((kar :initform 0 :type fixnum)
      (kdr :initform 0 :type fixnum))
  (:metaclass structure-class))

-->

(PROGN
 (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
   (PROGN
    (DEFSTRUCT
        (KONS (:INCLUDE STRUCTURE-OBJECT)
         (:CONSTRUCTOR |KONS structure class constructor| NIL) (:PREDICATE NIL)
         (:CONC-NAME |KONS structure class |) (:COPIER NIL))
      (KAR 0 :TYPE FIXNUM)
      (KDR 0 :TYPE FIXNUM))
    (DEFUN (SB-PCL::SLOT-ACCESSOR KONS KAR SB-PCL::READER) (SB-PCL::OBJ)
      (DECLARE (TYPE KONS SB-PCL::OBJ))
      (|KONS structure class KAR| SB-PCL::OBJ))
    (DEFUN (SB-PCL::SLOT-ACCESSOR KONS KDR SB-PCL::READER) (SB-PCL::OBJ)
      (DECLARE (TYPE KONS SB-PCL::OBJ))
      (|KONS structure class KDR| SB-PCL::OBJ))
    (DEFUN (SB-PCL::SLOT-ACCESSOR KONS KAR SB-PCL::WRITER)
           (SB-PCL::NV SB-PCL::OBJ)
      (DECLARE (TYPE KONS SB-PCL::OBJ))
      (SETF (|KONS structure class KAR| SB-PCL::OBJ) SB-PCL::NV))
    (DEFUN (SB-PCL::SLOT-ACCESSOR KONS KDR SB-PCL::WRITER)
           (SB-PCL::NV SB-PCL::OBJ)
      (DECLARE (TYPE KONS SB-PCL::OBJ))
      (SETF (|KONS structure class KDR| SB-PCL::OBJ) SB-PCL::NV))
    (CONS NIL NIL)))
 (EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
   (LET ()
     (SB-PCL::LOAD-DEFCLASS 'KONS 'STRUCTURE-CLASS '(STRUCTURE-OBJECT)
                            (LIST
                             (LIST* :INITFUNCTION #'SB-INT:CONSTANTLY-0 :NAME
                                    'KAR :READERS 'NIL :WRITERS 'NIL :INITARGS
                                    'NIL '(:TYPE FIXNUM :INITFORM 0))
                             (LIST* :INITFUNCTION #'SB-INT:CONSTANTLY-0 :NAME
                                    'KDR :READERS 'NIL :WRITERS 'NIL :INITARGS
                                    'NIL '(:TYPE FIXNUM :INITFORM 0)))
                            (LIST :FROM-DEFCLASS-P T :DIRECT-DEFAULT-INITARGS
                                  NIL)
                            'NIL 'NIL '(KDR KAR) (SB-C:SOURCE-LOCATION) 'NIL))))

```
CasperJSで複数ページのタイトル、METAディスクリプション・キーワードをまとめたCSVを出力する

#はじめに
PhantomJS（CasperJS）を使って、サイトの情報をCSVにまとめて出力する簡単なJavaScriptを書いてみました。
ひとまずタイトル、ディスクリプション、キーワードとしましたが、スクリプトを少し変えるだけでその他要素も簡単に習得可能かと思います。

> PhantomJSとは・・・コマンドで使えるヘッドレスブラウザ（Webブラウザで表示されるデータの取得・操作などができる）
> CasperJSとは・・・PhantomJSをより簡単に使うモジュールをまとめたもの


#スクリプト実行環境の用意
##必要となる2つのパッケージをインストール
* PhantomJS: 例）`$ sudo npm install -g phantomjs@1.9.7-15`
* CasperJS: 例）`$ sudo npm install -g casperjs`

※PhantomJSの1.9.8がインストールされるとCasperJS実行時にエラーが出たため、1.9.7を指定しています
※この場合Node.jsはインストール済みとします

##JSONファイルを用意し、取得したいページのURLを列挙していく

```src.json
[
  "http://www.yahoo.co.jp/",
  "http://www.google.co.jp/",
  "http://www.livedoor.com/"
]
```

##実行するJavaScriptファイルを作成
※jQueryを使用しているため、並びにjQuery.jsファイルを配置しています

```js
var fs   = require('fs');
var json = require('./files/src.json');  // URLを配列形式で記載したJSONファイルを読み込む

/* データを格納する多次元配列を作成する */
/* 子配列には、title, descriptionなど各データを格納するための空スペース '' を4つ作成 */
/*
  data[i][0] = url
  data[i][1] = title
  data[i][2] = meta description
  data[i][3] = meta keyword
*/
var data = (function() {
    var arr = [];
    var i, j;
    var l = json.length;
    for (i = 0; i < l; i++) {
        arr[i] = [];
        for(j = 0; j < 4; j++) {
            arr[i][j] = '';
        }
    }
    return arr;
})();


/* casperの定義 */
/* jQueryを実行できるように（ファイルはこのJSの並びに配置） */
var casper = require('casper').create({clientScripts: ['./jquery.js']});

/** 
 * casperをループ実行
 * @param {array}  json: 各URLが設定された配列
 * @param {object} self: Casperオブジェクト
 * @param {string} link: 処理している現在のURL
 */
casper.start().each(json, function(self, link, i) {
    self
        /* 指定ページを開く */
        .thenOpen(link, function () {

            /* URLとタイトルの取得 */
            var url   = this.getCurrentUrl(); // この場合はlinkと同じ
            var title = this.getTitle();

            /* metaタグの取得 */
            var metaDes = this.evaluate(function() {
                return $('meta[name=description]').attr('content');
            });
            var metaKey = this.evaluate(function() {
                return $('meta[name=keywords]').attr('content');
            });

            /* dataの子配列に取得したページ情報を追加 */
            /* カンマ区切りが入ってきても大丈夫なように項目には "" を付けてエスケープ */
            /* データが存在しない時（null）は "" は付けない */
            data[i][0] = '"' + url + '"';
            data[i][1] = (title   !== null) ? '"' + title   + '"' : '';
            data[i][2] = (metaDes !== null) ? '"' + metaDes + '"' : '';
            data[i][3] = (metaKey !== null) ? '"' + metaKey + '"' : '';

            this.echo('Loading... ' + title);
        })

        /* 読み込んだらCSVに書き込む */
        .then(function() {
            /* ファイルはutf-8なのに注意 */
            fs.write('./files/output.csv', data.join('\n'));
        })
    ;
});

casper.run();
```


#ファイル構成
以下のような構成になりました

```
root/─┬─jquery.js
      ├─output.js（実行するスクリプト）
      │
      └─files/─┬─src.json（読み込むURLソース）
               └─output.csv (自動出力)
```

#実行する
```
$ cd root/
$ casperjs output.js
```

__~Fin~__


#おわりに
出力されたcsvはutf-8なので、場合によっては変換作業が必要となるかもしれません。
また取得したいURL群を動的に生成したり、jQueryで特定の記事を指定するなど色々と応用できるかと思います。
Amazon EMRのCLIスニペット集


このポストは個人のメモであり、私の所属する組織を代表するものではありません。

## 概要

EMRのスニペット、いつも同じようなものを書いてしまうのでここにまとめていくことにする。

## SparkとPrestoをインストールされたClusterを起動する

```bash:install_spark_and_presto.sh
aws emr create-cluster \
--name Spark_and_Presto \
--ami-version 3.4.0 \
--applications Name=Hive Name=Hue \
--instance-groups InstanceGroupType=MASTER,InstanceCount=1,InstanceType=c3.xlarge InstanceGroupType=CORE,InstanceCount=2,InstanceType=c3.xlarge \
--ec2-attributes SubnetId=YOUR_SUBNET,KeyName=YOUR_KEYPAIR \
--log-uri s3://PATH/TO/LOG/ \
--enable-debugging \
--bootstrap-actions \
Name=Install_Spark,Path=s3://support.elasticmapreduce/spark/install-spark \
Name=Install_Presto,Path=s3://beta.elasticmapreduce/bootstrap-actions/presto/install-presto.rb
```

## 既存のクラスタにHiveのジョブステップを追加する

```bash:add_hive_step.sh
aws emr add-steps --cluster-id YOUR_CLUSTER_ID --steps Type=HIVE,Name='Hive program',ActionOnFailure=CONTINUE,Args=[-f,s3://PATH/TO/YOUR/QUERY.q]
```

## S3上のCloudFrontのログを外部テーブルとしてマウントするCREATE TABLE

```sql:create_external_table_for_cflog_on_s3.q
CREATE EXTERNAL TABLE cflog (
  date string,
  time string,
  x_edge_location string,
  sc_bytes string,
  c_ip string,
  cs_method string,
  cs_host string,
  cs_uri_stem string,
  sc_status string,
  cs_referer string,
  cs_ua string,
  cs_uri_query string,
  cs_cookie string,
  x_edge_result_type string,
  x_edge_request_id string,
  x_host_header string,
  cs_protocol string,
  cs_bytes string,
  time_taken string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LOCATION 's3://PATH/TO/LOGS/';
```


[AmplabのBigdata Benchmark](https://amplab.cs.berkeley.edu/benchmark/)のUservisitsテーブルを作成

```sql:create_external_table_for_uservisits
CREATE EXTERNAL TABLE uservisits (
  sourceIP STRING,
  destURL STRING,
  visitDate STRING,
  adRevenue STRING,
  userAgent STRING,
  countryCode STRING,
  languageCode STRING,
  searchWord STRING,
  duration STRING
) 
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'
LOCATION 's3://big-data-benchmark/pavlo/text/tiny/uservisits/';
```
Vagrant上のCentOS6にGoogleのPageSpeed Moduleを入れてみた

なんとなく、入れてみただけです。
参考：[Installing From Packages](https://developers.google.com/speed/pagespeed/module/download)

# 環境
* Windows7
* Vagrant
* CentOS6.5
* apache2.2

# ダウンロードとインストール

```
> sudo su
> yum -y install at
curl https://dl-ssl.google.com/dl/linux/direct/mod-pagespeed-stable_current_x86_64.rpm -o mod-pagespeed-stable_current_x86_64.rpm
> rpm -U mod-pagespeed-stable_current_x86_64.rpm
```

mod_pagespeedのインストールは、モジュールを自動的に更新するためにGoogleリポジトリを追加します。Googleのリポジトリが必要でない場合、パッケージをインストールする前に
`sudo touch /etc/default/mod-pagespeed`を実行してください。
（と書いてありました。）

# 設定
VirtualBox等で動かしている場合、ホストマシンからのアクセスを許可するように
apache用設定ファイルを修正。
`> vi /etc/httpd/conf.d/pagespeed.conf`

```
    <Location /pagespeed_admin>
        Order allow,deny
        Allow from localhost
        Allow from 127.0.0.1
        Allow from 192.168.0.0/255.255.255.0  # Add this line
        SetHandler pagespeed_admin
    </Location>
    <Location /pagespeed_global_admin>
        Order allow,deny
        Allow from localhost
        Allow from 127.0.0.1
        Allow from 192.168.0.0/255.255.255.0 # Add this line
        SetHandler pagespeed_global_admin
    </Location>
```

 Apacheリロード
`service httpd reload`


# アクセス
/pagespeed_admin
/pagespeed_global_admin


----------
とりあえずページは見れたけども、見方がわからず放置中。
PHP 良く使いそうな関数メモ

### ファイル存在確認
``` php:common
// 存在しない場合は生成
function checkDir($path, $mode = 0777) {
	if (!file_exists($path)) {
		// 再帰的にディレクトリを生成
		if (!@mkdir($path, $mode, true)) return false;
	}
	return true;
}
```

### コンテンツ取得
``` php:common
function fetchContents($url, $datas = array(), $method = 'POST') {
	$datas = http_build_query($datas, '', '&');

	$header = array(
		'Content-Type: application/x-www-form-urlencoded',
		'Content-Length: ' . strlen($datas)
		);

	$context = array(
		'http' => array(
		'method'  => $method,
		'header'  => implode("\r\n", $header),
		'content' => $datas
		)
	);

	return file_get_contents($url, false, stream_context_create($context));
}
```
### ランダム文字列生成
``` php:common
function makeRandStr($length = 8) {
    $str = array_merge(range('a', 'z'), range('A', 'Z'), range('0', '9'));
    $randStr = '';
    for ($i = 0; $i < $length; $i++) {
        $randStr .= $str[rand(0, count($str))];
    }
    return $randStr;
}
```
### 範囲内の値か確認
``` php:common
	function checkRangeValue($val, $max, $min = 0) {
		return ($val <= $max && $val >= $min) ? true : false;
	}
Upstartスクリプトの実行ユーザの設定


## initctl version >= 1.4
```upstart:/etc/init/sample.conf
description "sample"

start on runlevel [2345]
stop on runlevel [016]

setuid sampleuser

script
  exec bash sample.sh
end script
respawn
```

## initctl version < 1.4
```upstart:/etc/init/sample.conf
description "sample"

start on runlevel [2345]
stop on runlevel [016]

script
  exec bash sample.sh
  exec su -s /bin/sh -c 'exec "$0" "$@"' sampleuser -- bash sample.sh
end script
respawn
```
matplotlibで日本語

matplotlib.pyplotでたま～に日本語を使う必要があり，そのたびに
あれ？fontpropertiesだっけ？propだっけ？property？
となるので整理してみたら，凡例だけpropで，あとはfontpropertiesなのですね．
(propertyなんて無いし…)

ご参考まで．

![fontproperties.png](https://qiita-image-store.s3.amazonaws.com/0/52533/15760426-6bbb-ab07-342d-ea1b2082f1c6.png)

```python:japanese_in_matplotlib.py
# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

fp = FontProperties(fname=r'C:\WINDOWS\Fonts\YuGothic.ttf', size=14)

plt.bar([1, 2], [5, 10], 0.25)
plt.bar([1.25, 2.25], [4, 8], 0.25, color='darkorange')
plt.xlim((0.75, 2.75))
plt.ylim((0, 12))
plt.ylabel(u'軸ラベルはfontproperties=fp', fontproperties=fp)
plt.xticks([1.25, 2.25], [u'目盛りは', 'fontproperties=fp'], fontproperties=fp)
plt.title(u'タイトルはfontproperties=fp', fontproperties=fp)
plt.text(2.125, 10, u'テキストは\nfontproperties=fp', fontproperties=fp,
         ha='center')
plt.annotate(u'アノテーションは\nfontproperties=fp', xy=(1.125, 5), xytext=(1.3, 8),
             fontproperties=fp, arrowprops=dict(facecolor='k', shrink=0.05))
plt.legend([u'凡例は', 'prop=fp'], prop=fp, loc='upper left')
# plt.show()
plt.savefig('fontproperties.png', bbox_inches='tight')
plt.close()
```