OmniAICreator/Qiita-1.07M huggingface dataset:
Gitオブジェクトにはどんなものがあるのか知りたい


自分の研究でGitのちょっと深いところまでやる必要がでたのでやってみた．

## 参考にしたサイト
[見えないチカラ](http://keijinsonyaban.blogspot.jp/2011/05/git.html#ct3_1)
[Gitの中身を見てみよう](http://tech.aainc.co.jp/archives/9777)
[Gitオブジェクト](https://git-scm.com/book/ja/v1/Git%E3%81%AE%E5%86%85%E5%81%B4-Git%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88)
[こせきの技術日記](http://koseki.hatenablog.com/entry/2014/04/22/inside-git-1#2-1)

## 用語整理

|用語|説明|
|:---:|:---|
|repository| コミットの集合|
|the index|ステージングエリアの方が馴染み深い？|
|working tree|ファイルやディレクトリが含まれているもの(全体像的な感じ)|
|commit|ある時点でのworking treeのスナップショット|

[見えないチカラ](http://keijinsonyaban.blogspot.jp/2011/05/git.html#ct3_1)を参考に記述．
参考ページにはもう少し詳しくかいてある．

## Git
Gitは誤解を恐れずに言うとなんでもハッシュ化して管理する．

なので参照するのは全てその文字列なわけだが，その文字列にもいくつか形式のようなものが存在するのでそれを説明していく．

### blob
これはファイルを表す．tree構造の末端を表すといった方がいいのかな．

とりあえず，チュートリアル的なものをやってみる．

```
$ mkdir GitTest
$ cd GitTest
$ echo 'hello, world' > Hello.txt
$ cat Hello.txt
hello, world
```

「hello, world」と記述されたHello.txtを作成した．

ここでこのHello.txtはどのようなハッシュ値になるのかを確認．

```
$ git hash-object Hello.txt
4b5fa63702dd96796042e92787f464e28f09f17d
```

これはhello, worldという内容をhash化したものであるため．誰がやっても同じハッシュ値なるはず．

```
$ git init
Initialized empty Git repository in /Users/shu920921/Documents/GitTest/.git/

$ git add Hello.txt
$ git commit -m "add Hello.txt"
[master (root-commit) 10a3496] add Hello.txt
 1 file changed, 1 insertion(+)
 create mode 100644 Hello.txt
```

先ほどのハッシュ値を打ち込んで，そのハッシュ値はどのような形式のものなのか確かめる．```git cat-file -t```

```
$ git cat-file -t 4b5fa637
blob
```

blobは先ほども述べた通り，treeの末端，すなわちファイルである．

ハッシュ値からファイルの中身もみれる

```
$ git cat-file blob 4b5fa637
hello, world
```

### tree
treeとはblobを管理するものだ．
blobがファイルであるなら，treeはディレクトリといったところだと思う．

とりあえず適当にディレクトリとファイルを追加．
以下のような構造にした．

```
GitTest
├── Hello.txt
└── testdir
    └── test.txt
```

masterブランチのツリーオブジェクトを確認してみる．

```
$ git cat-file -p master^{tree}
100644 blob 4b5fa63702dd96796042e92787f464e28f09f17d	Hello.txt
040000 tree 85a2934a71f7385034f934f9ccc8c746b73d4f44	testdir
```

testdirツリー(ディレクトリ)の中身を見る．

```
$ git cat-file -p 85a2934a7
100644 blob 16b14f5da9e2fcd6f3f38cc9e584cef2f3c90ebe	test.txt
```

test.txtが存在することが確認できた．

先述の通り，```git cat-file blob 16b14f5da9e2```　で中身を確認できる．

### commit
commitオブジェクトは名の通りコミットに関する情報を保持しているオブジェクト

現在は2回commitしたはず．

とりあえず```git log```で確認する．

```
$ git log
commit c8b175a310412696c0804a496eeac5d9ce73d88c
Author: shu- <アドレス>
Date:   Tue Sep 15 00:32:11 2015 +0900

    add test dir and file

commit 10a3496af239cfd466028f2a9132d78ee44bb63d
Author: shu- <アドレス>
Date:   Sat Sep 12 17:43:57 2015 +0900

    add Hello.txt
```

うん．2個コミット情報があった．

もし，コミットのハッシュ値がわかる場合は ```git cat-file commit ハッシュ値```で確認．

```
$ git cat-file commit c8b175a3104
tree 62e8e0173bc99f7e0704e537b41ac0d7d645a734
parent 10a3496af239cfd466028f2a9132d78ee44bb63d
author shu- <アドレス> 1442244731 +0900
committer shu- <アドレス> 1442244731 +0900

add test dir and file
```

とりあえず今回はこんなところ
gitオブジェクトにはどのようなオブジェクトがあるのか少しわかった．
それとハッシュ値で全て管理されてることもわかった．
appleTVでpush/pop画面遷移

## はじめに
前回記事の続きになります。
appleTVでpresentModal画面遷移
http://qiita.com/senseiswift/items/eccc7b48328484c25976

全回はpresentModalで画面を切り替えていましたが、
今回はpush/popで2つの画面間を遷移できるようにします。

## やること
1. pushDocumentで1画面目をPUSH
2. pushDocumentで2画面目をPUSH
3. popDocumentで1つ前の画面に戻る

### 1. pushDocumentで1画面目をPUSH
```js:main.js
// 起動時に呼ぶ1画面目をPUSHするメソッドです
function pushFirstXML() {

    var parser = new DOMParser();
    var alertDOMElement = parser.parseFromString(firstXMLString, "application/xml");
    alertDOMElement.addEventListener("select", /*  */, false);

    // 1画面目をPUSHします。
    navigationDocument.pushDocument(alertDOMElement);
}
```

### 2. pushDocumentで2画面目をPUSH
1画面目のボタンを押した時に2画面目をPUSHするように
イベントリスナーにセットします。

```js:main.js
// 起動時に呼ぶ1画面目をPUSHするメソッドです
function pushFirstXML() {

    function pushSecondXML() {
        var parser = new DOMParser();
        var alertDOMElement = parser.parseFromString(secondXMLString, "application/xml");
        alertDOMElement.addEventListener("select", function(){/* */}, false);

        // 2画面目をPUSHします。
        navigationDocument.pushDocument(alertDOMElement);
    }

    var parser = new DOMParser();
    var alertDOMElement = parser.parseFromString(firstXMLString, "application/xml");
    alertDOMElement.addEventListener("select", pushSecondXML, false);

    // 1画面目をPUSHします。
    navigationDocument.pushDocument(alertDOMElement);
}
```

### 3. popDocumentで1つ前の画面に戻る
2枚目の画面のボタンを押した時にPOPするよう追記します。

```js:main.js
// 起動時に呼ぶ1画面目をPUSHするメソッドです
function pushFirstXML() {

    function pushSecondXML() {
        var parser = new DOMParser();
        var alertDOMElement = parser.parseFromString(secondXMLString, "application/xml");

        // ボタンを押した時に、POPするようにします。
        alertDOMElement.addEventListener("select", function(){navigationDocument.popDocument();}, false);

        // 2画面目をPUSHします。
        navigationDocument.pushDocument(alertDOMElement);
    }

    var parser = new DOMParser();
    var alertDOMElement = parser.parseFromString(firstXMLString, "application/xml");
    alertDOMElement.addEventListener("select", pushSecondXML, false);

    // 1画面目をPUSHします。
    navigationDocument.pushDocument(alertDOMElement);
}
```

## 動作確認
pushFirstXML

準備が整ったので、実際に動かしてみましょう！
今回もmain.jsがあるディレクトリで、
「python -m SimpleHTTPServer 8000」するのを忘れないように注意してください。

また、起動時に呼ばれるmain.jsのApp.onLaunchで、
先ほど作成したpushFirstXML()を呼ぶようにしておきましょう。

また、アプリ起動後シミュレータの「HardWare > Show　Apple TV Remote」の順に選択して、
リモコンを表示しておきましょう。

### 1枚目
![スクリーンショット 2015-09-15 0.21.10.png](https://qiita-image-store.s3.amazonaws.com/0/91606/34262bcf-fa86-337d-1919-8ecb1717654a.png)


### 2枚目
![スクリーンショット 2015-09-15 0.22.40.png](https://qiita-image-store.s3.amazonaws.com/0/91606/66e49cdf-bf5c-bc3c-7a74-84476bda2535.png)

## まとめ
今回はpush/popを使って、複数のTVMLを遷移できるようになりました。

次回からはTVMLの様々なテンプレートを紹介していきます。

ソース全文はgithubを参考にしてください。
https://github.com/senseiswift/appleTVtutorial/commit/82d2faafea7d4471bdcb5ab0279e10448bb63a88
知る、読む、使う！ オープンソースライセンスを読んだメモ

#知る、読む、使う！ オープンソースライセンスを読んだメモ
http://tatsu-zine.com/books/osslicense

#**重要！！**
ここに記載した内容は自己解釈のメモであり、内容に関しては一切保証しません。
OSSの利用時にはご自身・専門家の意見をもとに判断をお願いします。

#背景：どうして読もうと思ったのか？
* OSSを積極的に活用したい  
* OSSを作りたいわけではない  
* OSSを無改変で単純に使いたい。

要するに社内用などのツール作成時に、有用なOSSを使用して効率化したいということ。


#ソフトウェアライセンス
##ソフトウェアライセンスにおける「利用」と「使用」。
ライセンスはどこまで「利用」させるかを定めたもの。

**利用**
　・複製：ソフトウェアをコピーすること
　・配布：ソフトウェアを第三者に渡すこと（入手可能な状態にすること）
　・改変：ソフトウェアを修正すること（部分的に抜き出して使うことも）

**使用**
　・パソコンに入っているソフトウェアをユーザーとして実行すること。
　・他人のパソコンに入っているソフトウェアを実行すること。


#オープンソースとは何か？
ソースコードが公開されているだけでは厳密なOSSとは言えない。
下記の権利があるものをOSSと認識した方がいい。

* **配布**：ソフトウェアの複製と配布が自由にできる
* **入手**：ソフトウェアのソースコードを入手できる
* **改変**：ソフトウェアのソースコードを自由に修正できる。（配布も出来る）

#OSSライセンス概要
ライセンスにはいくつかの項目があり、どの程度の**利用権利**を与えるか？
その権利を得るために守るべきことは何か？が設定されている。
複数のライセンスタイプが存在しており、ライセンス毎にその度合が異なる。

#OSSライセンス：コピーレフトと派生ソフトウェア
**GPL系はコピーレフト、BSD系はコピーレフトがない。**

##コピーレフト
コピーレフトの場合、
「OSSを利用したソフトウェアをOSSにしなければいけない。」**とイコールじゃない**。
あくまで「元と同じ内容の利用条件を適応」する必要があるだけ。
OSSを改変して配布する場合、そのソフトウェアのソースコードは配布先に公開可能でなければいけない。
*配布先の人がソースコードを取得したい場合に取得出来る必要があるということで、Webなどで一般公開（OSS化）する必要はない。しかしながら、有償ソフトウェアとして販売し、ソースコードを第三者に公開したくない場合は問題となる。*

ここで改変したソフトウェアというのは、OSSの派生ソフトウェアを指す。
何が派生となるのかが重要な見極めポイント？

##派生ソフトウェア
####派生ソフトウェアとなるのは次の３行為。
* **「修正」**
* **「混合」**
* **「リンク（静的/動的）」**  

参考：[COBOL2002 使用の手引 手引編 「18.5　静的なリンクと動的なリンク」](
　　http://itdoc.hitachi.co.jp/manuals/3000/30003D0800/GD080284.HTM)

####派生ソフトウェアとみなさないのは次の３行為。
* **「単純な同梱」**
* **「APIを介した呼出」**
* **「OSSツールを使った作業」**  

##生まれる疑問
###バイナリを生成しない場合？
じゃぁPythonのソースコードライブラリを無改変で使用するのはどうなるのか？
バイナリ自体が配布されておりそれをAPI利用するのは問題ないということ？？

　参考：[Python のライセンスと標準ライブラリ、サードパーティライブラリのimport について - kenkovlog](http://kenkov.hatenablog.jp/entry/2012/09/09/061347)

###実行ファイルの場合？
例えばTortoiseSVNはGPLで配布されている。
TortoiseSVN.exeのコマンドライン引数で操作するようなソフトウェアを作り、
実行ファイル等を含めて配布してもOK？
それも派生ソフトウェアとみなされないのか？

###となるとPyQtのライセンス問題はどうなるのか？？
　参考：[philo式 » Qt のライセンスについての考察 ](http://goo.gl/11yfJW)
　参考：[What is PyQt? >PyQtはGPL3の商用ライセンスのデュアル](https://www.riverbankcomputing.com/software/pyqt/intro)
　
　サポート＋アルファを考えるなら商用ライセンスという選択肢と思われるが、
　GPL3ライセンスで利用し、ソース無改変、バイナリを追加生成しないで利用すれば、
　ソース公開なしで配布できるということ？？

#OSSライセンス：その他の気にするポイント（もっとたくさんあるけど）
* ソースコードとバイナリで条件が違うものがある
* ソフトウェアのバージョン毎にライセンスが異なる可能性がある。
* 異なるライセンスを持つOSSを一緒に利用する場合はライセンス条件の矛盾に注意が必要。
* OSS再配布時には著作権表示＆免責条項＆ライセンス文書（３種情報）をいっしょに配布する必要がある。
* Apache v2.0 は特許についてもフォローされている
* 社内利用であればGPL系もソース改変や再配布が問題ないらしい

#使うならどのライセンス適応のOSS？
修正BSD、ApacheV2, MITの３つがやはり使いやすい。（非コピーレフト系）

特にバイナリ自体が公開されており、それを利用する場合はライセンス等の３種情報も不要？
　　参考：知る、読む、使う！ オープンソースライセンス P176

#感想と今後
BSD系ならソースコード＆バイナリ問わず、
無改変で使用するなら３種情報を含めておけば特に問題無さそう。
入手したLICENSE,NOTICEも含めたまま再配布。

一番危険そうなのは、特許が含まれていた場合？
ここに関しては調べることもそうだが、どれくらい広く使われているOSSか？
といったような点でも気にする必要がありそう。

今後、改めてOSSライセンスを読んでみて理解を深める。
Chromeエクステンションを作ろう


とある事情により、ChromeエクステンションでRedmineサイトで機能するプラグインを趣味で作ることになりました.
Chromeウェブストアに公開まで行ったので、公開したプラグインの紹介がてらにChromeエクステンションについてわかったことなどを何回かに分けて書いていきます.

プラグインは[こちら](https://chrome.google.com/webstore/detail/redmine-lazy-applicant/dofmgcleeckgckfapnhookpocglpbmgp)からインストールできます. 一人でも多くの方に利用いただければ幸いです.
ソースコードは[こちら](https://bitbucket.org/dhun-h/lazy-applicant)から閲覧できます.

Redmineを利用できる環境がない場合は、Redmineの[デモサイト](https://my.redmine.jp/demo/projects/demo/issues/new)で動作を確認することができます.

## Chromeエクステンションとは？

Chromeに拡張機能を追加する仕組みになります.

Chromeエクステンションはただの圧縮フォルダです.
そのフォルダの中身はただのHTMLやCSS、Javascriptファイルです.
一般的なWebページを作ることができれば、Chromeエクステンションも作ることができます.

Chromeエクステンションでは、[Chrome-Javascript-API](https://developer.chrome.com/extensions/api_index)を利用することができます.
このプラグインでは、次のAPIを利用しています.

* [extension](https://developer.chrome.com/extensions/extension) ... バックグラウンドページとの通信, リソースファイルのURL解決
* [storage](https://developer.chrome.com/extensions/storage) ... 設定値の保存
* [runtime](https://developer.chrome.com/extensions/runtime) ... バックグラウンド通信や保存処理のエラー判定
* [i18n](https://developer.chrome.com/extensions/i18n) ... メッセージの国際化


## Chromeエクステンションの種類

### [コンテントスクリプト](https://developer.chrome.com/extensions/content_scripts)
特定のWebページに、JavascriptやCSSなどを挿入できます.
このプラグインで主に利用した機能になります.

### [バックグラウンドページ](https://developer.chrome.com/extensions/background_pages)
Chromeの起動中、常駐するページです.
このプラグインでは、コンテントスクリプトからGoogleAnalyticsによる統計収集を実行するために利用しています.

### [オプション画面](https://developer.chrome.com/extensions/optionsV2)
プラグインの設定画面です.
このプラグインでは、コンテントスクリプトで設定した内容を編集するために利用しています.

### [ブラウザアクション](https://developer.chrome.com/extensions/browserAction)
アドレスバーの右側にアイコンを追加します.
そのアイコンに加えて、ツールチップ、バッジ、ポップアップも追加することができるそうです.
※利用していないため、詳細は分かりません
![browser-action.png](https://qiita-image-store.s3.amazonaws.com/0/74102/2436f505-172b-6f14-712c-236cfe467fb8.png "browser-action.png")

### [ページアクション](https://developer.chrome.com/extensions/pageAction)
アドレスバーの内側にアイコンを追加します.
アイコンはページによって表示制御ができるようです.
※利用していないため、詳細は分かりません
![page-action.png](https://qiita-image-store.s3.amazonaws.com/0/74102/fb32dfe7-983d-6a75-a280-1d2aa5e9e2d8.png "page-action.png")


### [Override Pages](https://developer.chrome.com/extensions/override)
Chrome内部のページを置換できるようです.
下記ページを置換できますが、１つのエクステンションでは１つのページしか置換できないようです.
※利用していないため、詳細は分かりません

* Bookmark Manager
* History
* New Tab


## 野良.crxについて

Windows版のChrome v33以降では、再起動時に野良.crxが無効になります.
企業内用途や個人用途でも、Windows版ユーザがいる場合にはChromeウェブストアへ公開する必要があります.
⇒　Macで開発していたため、終盤まで気づきませんでした orz

## リンク

* [マニフェストファイル](http://qiita.com/dhun/items/34b1350d6cb42da4788b)
* [コンテントスクリプト](http://qiita.com/dhun/items/87a4fc88fce0ae0dd448)
* [オプション画面](http://qiita.com/dhun/items/8befb32e6f3392b4cd08)
* [バックグラウンド(とGoogleAnalytics)](http://qiita.com/dhun/items/358d25b6331d00396c1d)
* [ストレージ](http://qiita.com/dhun/items/cf18e43cb0376fcff302)
* [国際化](http://qiita.com/dhun/items/59707eeb2dc38d3a7a99)
* [gulp](http://qiita.com/dhun/items/423b64635aa2aebbef40)
* [Chromeウェブストアで公開](http://qiita.com/dhun/items/af7058cdbff8500a6061)
Chromeエクステンションを作ろう：マニフェストファイル編


説明で使用した拡張機能は[こちら](https://chrome.google.com/webstore/detail/redmine-lazy-applicant/dofmgcleeckgckfapnhookpocglpbmgp)からインストールできます. 一人でも多くの方に利用いただければ幸いです.
ソースコードは[こちら](https://bitbucket.org/dhun-h/lazy-applicant)から閲覧できます.


## マニフェストファイルとは

プラグインの名前やバージョン番号などのメタ情報を、json形式で定義します.
詳細は[公式サイト](https://developer.chrome.com/extensions/manifest)を参照してください.


## プラグインで使用した属性

|属性|必須|設定値|説明|
|---|:---:|---|---|
|manifest_version|**yes**|`2`|マニフェストファイル自体のバージョン番号です. `2`を指定します.|
|name|**yes**|適宜|プラグインの名前です. ※１|
|version|**yes**|適宜|プラグインのバージョン番号です. ※１|
|description|no|適宜|プラグインの説明です. ※１|
|icons|no|`{ "128": "images/icon-128.png" }`|プラグインのアイコンです.<br>16x16や48x48の指定が推奨されていますが、今回は128x128しか指定しませんでした. ※１|
|author|no|適宜|プラグインの作者です. ※２|
|homepage_url|no|https://bitbucket.org/dhun-h/lazy-applicant-support|作者のホームページです. ※３|
|permissions|no|`"storage"`|プラグインが必要とする権限です.<br>今回はストレージを利用するため指定しています.|
|content_scripts|no|`{ ... }`|[コンテントスクリプト編](http://qiita.com/dhun/items/87a4fc88fce0ae0dd448)で説明します|
|web_accessible_resources|no|`[ ... ]`|[コンテントスクリプト編](http://qiita.com/dhun/items/87a4fc88fce0ae0dd448)で説明します|
|background|no|`{ ... }`|[バックグラウンド編](http://qiita.com/dhun/items/358d25b6331d00396c1d)で説明します|
|content_security_policy|no|`"..."`|[バックグラウンド編](http://qiita.com/dhun/items/358d25b6331d00396c1d)で説明します|
|options_ui|no|`{ ... }`|[オプション画面編](http://qiita.com/dhun/items/8befb32e6f3392b4cd08)で説明します|
|default_locale|no|`"en"`|[国際化編](http://qiita.com/dhun/items/59707eeb2dc38d3a7a99)で説明します|


[^1]: ChromeウェブストアやChrome拡張機能タブに表示されます
[^2]: Chromeウェブストアに表示されます
[^3]: Chrome拡張機能タブに表示されます


## 最低限の構成

Chrome拡張を作る際に、必須となるのはマニフェストファイルだけです.
極端な話、次のコマンドを実行すればそれはChrome拡張となります.

```shell
mkdir Example
cat <<EOF > Example/manifest.json
{
    "manifest_version": 2
   ,"name": "Example"
   ,"version": "1.0.0"
}
EOF
```

1. Chrome起動
2. 拡張機能タブを開く
3. デベロッパーモード　をチェック
4. パッケージ化されていない拡張機能を読み込む...　ボタンを押して、Exampleディレクトリを指定

なんの機能もありませんが、、、

## コメント

公式サイトにあるように、マニフェストファイルにはコメントを含めることができます.

* `// comment`
* `/* comment */`

ただしjson形式としては不正になるため、`JSON#parse`はできなくなります.
⇒　このプラグインではmanifest.jsonを解析してバージョン番号を取得しているため、コメントは利用していません

## 説明で紹介したプラグインのソースコード
* [manifest.json](https://bitbucket.org/dhun-h/lazy-applicant/src/f371e1be0e9d66311bf81555e098b71c25886eb7/src/manifest.json?at=master&fileviewer=file-view-default)
新サービス企画時に、提案すべきなのはルールじゃなくて習慣

リーンスタートアップでもなんでもいいんだけど、ああいう本の最初の方に「新サービスが同分野の既存サービスを陳腐化するにはxx倍の優位性が必要」ってかいてある。
何倍かについては諸説あって３倍だったり５倍だったり１０倍だったりする。
とにかく「たくさん」だ。１、２、たくさん。
要するに「すでにチャンピオンがいるゲームで、チャレンジャーがチャンピオンと同じリング同じルール同じゲームで真正面から殴り合ったら勝負にならない」って言っている。

チャンピオンがすでにいる場合、同じルールで殴り合ったらだめ、は正義なんだろう。
１０年くらい前のITバブルの時に「頭抜けたトップが出たら後から追いつくことはできない。例外はGoogleだけ」って言われていた。
最近だとCommもLINEに追いつけなかったし。
「ITの世界ではWinner take All. １位が利益を独占し、２位はトントン、３位以下は赤字垂れ流し」という話だから「２位じゃだめなんですか」は通じないし。

リーンスタートアップとかだと、「同じゲームで戦っても勝てないから新しいリングを作ってそこで新しいゲームをやれ」って言っている。新しいゲームの作り方をくどくどと書いているわけだけど詳しくはここでは割愛する。

最近雨後の筍みたいにサービスが生まれては消えている。多産多死は宿命、仕方ない。
彼らは新しいゲームを作りたい。

新しいゲーム。
うまくいったベンチャーとそれ以外を見てみると、サービスは「今までと全く違うxxを作ったんです」ってだいたい主張する。
成功したサービスのイノベーターはだいたいインタビューでろくろを回しながらそう言っている。

「今までと全く違うxx」
しかしサービスの登場当初はユーザーはそう言った受け取り方をしない。絶対に。
ニコニコ動画は当初「youtubeもどき」だと思われていた。youtubeにコメントを出せるだけでしょ、って感じ。
twitterは当初ブログもどきだと思われていた。新聞なんか最近までミニブログサービスだと言っていたし。
要するに既存サービスと比較して「xxもどき」「埼玉で作ったxx」という受け取り方をする。ローンチ当初は機能がそろっていないから仕方がない。

ここで爆死したサービスと成功したサービスをみると、違いがある
「最初から破壊的な新ルールを提案したサービスは爆死する」
「成功したサービスは最初はルール内で新アクションを提案している」

例を出す。
たとえばケミカル系のベンチャーが「プロスポーツでドーピングを解禁しましょう」と言っても絶対に受け入れられない。ポジショントークが見え見えだし、それを受け入れた時のメリットとデメリットが釣り合わない。

ある独立野球リーグがいう。
「野球で無走者なら３塁から１塁方向に回ってもいいことにしよう。１塁側にボールが転がったときに内野安打が出やすくなる」
これも論外だ。内野安打を増やすというメリットは正直利益が薄いし、受け入れた時の混乱を考えると自分がOKしても他人が付き合ってくれるとは思えない。

既存のルールやセオリーに逆らったものを提案してもそれは無理筋。
弱者が世界の片隅で「僕の考えた最強のルール」を言ったところで世界も既存ルールも変えられない。

ではなにならいい？
既存のルールやセオリーに逆らわない、新しい行動と習慣の提案。

たとえば「運動の後にプロテインを飲もう」なら通る。プロテインの摂取は規制されていないから。サラダチキンを食べるのと大して変わらない。
「部活動の後にプロテインを飲むと筋肉がつきやすくなります、監督コーチの方、ぜひ！部員１人あたり一ヶ月3千円！」
これだと通りやすい。低コストで効果はわかりやすい。
ユーザーがつく。
「部活後にシェイカーにタンパク質の粉末と牛乳を注いでかき混ぜた後飲み込む行為」が「プロテインを飲む」と名前がつく。
ここでユーザーを集めた後に次の行動を起こせる。

最初のユーザーをつくまでの「埼玉で作ったxx」状態で既存のセオリーやルールに反することを提案してもユーザーは受け入れない。
既存ルールの範囲内で新しいアクションを提案し、そこでユーザーをつけて、「埼玉で作ったxx」ではなく自分のサービス名が新しいジャンルを確立した後でないとルールは提案できない。
最近ならライザップか。

そもそもなぜ新しいルールを提案したがる？
新しいルールは差別化の容易さとマネタイズのしやすさがある。
早い段階でどかんと稼ぎたい、パッと見いい感じの企画書を書きたい、そう思っている人間にとってはあたらしいルールを１行書き加えることは耐え難い誘惑なのだろう。

しかし、私はサービスを当てるにはもう少しステップを踏みたい。階段を何段も同時に飛ばすと危ない。
当たるサービスを作るには最初はルール内であるがゆえに金を稼ぎづらい、新しい行動の提案から始める。
もし受ければユーザーがつく。
ユーザーは「xxもどき」と呼ばず、サービス名で呼ぶようになる。動詞になった「google」や「twitter」のように。
もうこれでサービスは「xx」から新しいゲームを「独立」させられたことになる。
そこでようやくマネタイズに向けた新ルールの提案をする。

これがこの記事の主旨。
習慣の提案、次に独立。そして新ルール。

マネタイズのための新ルール提唱は人を集めるフェーズのあとのフェーズで行う行為であるように私は思う。
これを焦って最初にやっても人はついてこない。
Azure Storageを使ってみる

# 1 概要

Azure Storageを利用する方法についてご紹介します。

# 2 Azure Storage

Azure Storageでは、ストレージのサービスとして以下のものが提供されています。

### 2.1 BLOBストレージ

* BLOBストレージには、ファイルデータが格納されます。主に、以下のデータが格納されます。
 * ドキュメント
 * 写真、ビデオ、音楽などデータ
 * ファイル、コンピューター、データベース、およびデバイスのバックアップデータ
ログなど大きいデータ
* BLOBストレージの構成は、以下の図を参照できます。Storage Accountの容量の上限は、500TBです。Storage Accountには、任意の数のContainerを含めることができ、Containerには、任意の数のBlobを含めることができます。
* BLOBストレージがよく利用されるので、3章、4章に、BLOBストレージについての利用方法を紹介します。        
![blob.png](https://qiita-image-store.s3.amazonaws.com/0/13451/74bc6b30-5fe3-e16d-0927-e31eda5bde96.png)

### 2.2 テーブルストレージ
* テーブルストレージには、構造型データが格納されます。テーブルストレージは、MicrosoftのNoSQLのキーまたは属性ストアですが、従来のリレーショナル データベースと異なり、スキーマなし（従来のリレーショナル データベースのスキーマが固定なので、柔軟性が欠けているが、NoSQLは、スキーマを必要としないモデルなっています）の設計です。    テーブルストレージを利用すると、以下のデータが格納されます。
 * Webアプリケーションのユーザーデータ
 * アドレス帳
 * デバイス帳

### 2.3 キューストレージ
* キュー ストレージは、メッセージング機能を提供します。　キューストレージを使用すると、以下の機能を実現できます。
 * ワークフロー処理
 * クラウド サービスのコンポーネント間通信

### 2.4 ファイルストレージ (プレビュー)
* ファイルストレージは、標準のSMB2.1プロトコルを使用して、共有ストレージを提供します。  



# 3 BLOB ストレージを利用して、コンテナー(Container)を作成する

* https://manage.windowsazure.com　に、ログインして、左のメニューの「ストレージ」を選びます。
* 「新規」ボタンを押します。ストレージ新規画面が出ます。「データサービス」→「ストレージ」→「簡易作成」の順で、選択します。    
* 「ストレージアカウントの作成」をクリックして、数秒後にストレージが作成されます。
* 作成したストレージをクリックして、次の画面に、「コンテナー」をクリックします。
* 「追加」ボタンをクリックして、新しいコンテナー画面（図５）が出て、名前とアクセス方法を入力して、コンテナーを作成できます。
* コンテナーを作成できますが、azureにコンテナーにBlobs（ファイルなど)をアップロードする機能がありませんが、    https://zudio.co/ サービスを使って、ファイルをアップロードできます。

# 4 zudioを利用して、azureで作成されたコンテナーにファイルをアップロードする
* Microsoftのブログに、zudioサービスが紹介されたことがあって、zuidoを利用して、ファイルのアップロードすることが便利です。
 * https://azure.microsoft.com/en-us/documentation/articles/hdinsight-upload-data/
* https://zudio.co/ にアクセスして、右上の「Free trial」ボタンを押して、Microsoft アカウントでサインインします。
* 「Add a Storage Account...」を押して、図７の画面が出ます。    
* zudioに、作成されたAccountを押して、次の画面に「Manage Blobs」をクリックして、コンテナーリストが表示されます。先ほど作成したコンテナーをクリックして、コンテナー管理画面に入ります。次は、「UPLOAD」ボタンを押して、ファイルをアップロードできます。
* Azureコンソールに、ストレージ　→　上記に作成したAzure Storage -> コンテナー　→　作成したコンテナーで、選択します。図9のように、zudioから、アップロードされたファイルを見えます。
AWS SNSで複数プラットフォーム上のアプリへのメッセージを送るときにはJSON文字列を渡さないといけない

[メッセージでのカスタムプラットフォーム固有のペイロードのモバイルデバイスへの送信 - Amazon Simple Notification Service](http://docs.aws.amazon.com/ja_jp/sns/latest/dg/mobile-push-send-custommessage.html)にて書かれていることを[aws-sdk | RubyGems.org](https://rubygems.org/gems/aws-sdk)で試してみる。


送信するメッセージは以下の通り

```json
{ 
  "default": "This is the default message which must be present when publishing a message to a topic. The default message will only be used if a message is not present for one of the notification platforms.",
  "APNS": "{\"aps\":{\"alert\": \"Check out these awesome deals!\",\"url\":\"www.amazon.com\"} }",
  "GCM":"{\"data\":{\"message\":\"Check out these awesome deals!\",\"url\":\"www.amazon.com\"}}"
}
```

よく見ると、`APNS`や`GCM`のキーに対してはJSONの文字列が入っている。
この部分を以下のようにしてしまうと通知を受け取るアプリは期待する値が入らず、`default`キーの値が単純に送られてしまう。

```json
{ 
  "default": "This is the default message which must be present when publishing a message to a topic. The default message will only be used if a message is not present for one of the notification platforms.",     
  "APNS": {
    "aps": {
      "alert": "Check out these awesome deals!",
      "url": "www.amazon.com"
    }
  },
  "GCM": {
    "data": {
      "message": "Check out these awesome deals!",
      "url": "www.amazon.com"
    }
  },
}
```


複数プラットフォーム上に通知を送る際には通知を行うプラットフォームをキーに値には**JSONの文字列**を渡す。

通知を行うプラットフォーム毎にメソッドを分けた方がすっきりするような感じがして以下のようなコードを書いた。


```rb

def apns(message, url)
  {
    aps: {
      alert: message,
      url:   url
    }
  }.to_json
end

def gcm(message, url)
  {
    data: {
      message: message,
      url:     url
    }
  }.to_json
end

sns = Aws::SNS::Client.new(
        access_key_id:     ENV['SNS_ACCESS_KEY_ID'],
        secret_access_key: ENV['SNS_SECRET_ACCESS_KEY'],
        region:            ENV['SNS_REGION']
      )


message_json = {
  default: "This is the default message which must be present when publishing a message to a topic. The default message will only be used if a message is not present for one of the notification platforms.",
  'APNS': apns("Check out these awesome deals!", "www.amazon.com")
  'GCM' : gcm("Check out these awesome deals!", "www.amazon.com")
}.to_json

sns.publish(
  topic_arn: ENV['SNS_ALL_PUBLISH_TOPIC_ARN'],
  message: message_json
  message_structure: :json
)
```
[Android]CombineLatestで15個以上の処理を合成したい

Androidアプリ開発で、Rxjavaを使うときの話です。
タイトルの通りですが、[`ConbineLatist`](http://reactivex.io/documentation/operators/combinelatest.html)で15個以上の処理を合成しようとすると、例外が発生します。

```shell-session
More than RxRingBuffer.SIZE sources to combineLatest is not supported.
```

これは、`OnSubscribeCombineLatest`のコンストラクタで、sources数に制限をかけられているのが原因です。

```java
        if (sources.size() > RxRingBuffer.SIZE) {
            // For design simplicity this is limited to RxRingBuffer.SIZE. If more are really needed we'll need to
            // adjust the design of how RxRingBuffer is used in the implementation below.
            throw new IllegalArgumentException("More than RxRingBuffer.SIZE sources to combineLatest is not supported.");
        }
```

`RxRingBuffer.SIZE`という定数は、`RxRingBuffer.java`で以下のように初期化されます。
通常`RxRingBuffer.SIZE`は`128`ですが、Androidの環境下では`16`と低いデフォルト値が設定されています。

```java
    static int _size = 128;
    static {
        // lower default for Android (https://github.com/ReactiveX/RxJava/issues/1820)
        if (PlatformDependent.isAndroid()) {
            _size = 16;
        }

        // possible system property for overriding
        String sizeFromProperty = System.getProperty("rx.ring-buffer.size"); // also see IndexedRingBuffer
        if (sizeFromProperty != null) {
            try {
                _size = Integer.parseInt(sizeFromProperty);
            } catch (Exception e) {
                System.err.println("Failed to set 'rx.buffer.size' with value " + sizeFromProperty + " => " + e.getMessage());
            }
        }
    }
    public static final int SIZE = _size;
```

どうしても`RxRingBuffer.SIZE`を変更したい場合は、`RxRingBuffer.java`が初期化される前に、`System.setProperty`経由で値を上書きします。以下がサンプルコードです。

```java
public class CustomApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        System.setProperty("rx.ring-buffer.size", "32");
    }
}
```

関連Issue:  [ReactiveX/RxJava/issues/1820](https://github.com/ReactiveX/RxJava/issues/1820)
写真の撮影日を編集(exiftool)


Exif情報を参照／編集するコマンド。

撮影日の編集。

> exiftool -DateTimeOriginal="YYYY:MM:DD HH:mm:ss" [file name]

<br>

####入手先
http://www.sno.phy.queensu.ca/~phil/exiftool/index.html
Apache Velocity 基礎知識まとめ

社内で簡易的なメモを作ったのでそのまま転載


基本的な情報
----------

バージョンによる動作差異がありますが、以下が非常に参考になります
http://www.jajakarta.org/velocity/velocity-1.4/docs-ja/user-guide.html

以下は、↑のリンクから特に特徴的なものを抜粋したものです。


Getterの省略
-----------

Velocityテンプレート上では、getterメソッドをpublicフィールドのように利用できます。

例:

```
${user.userId}
↓

user → Userクラスのインスタンスの場合、user.getUserId() と同等です。
```


{} と !
-----------------

* `{}` : 変数がどこからどこまでかを表します

	たとえば `$hoge` という変数に "あいうえお" という値が入っていたとして、
	"あいうえおaiueo" と出力したい場合に、
	`$hogeaiueo` と記載してしまうと、変数 `$hoge` ではなく `$hogeaiueo` という変数が参照されます。

	これを避けるために `${hoge}aiueo` とどこまでが変数かマークします。

* `!` : 変数が空の場合の出力制御

	変数が未定義やnullの場合に出力を抑制します。
	`$hoge` が未定義の場合に出力した場合に以下のような差異があります

	- `${hoge}` または `$hoge` … `"$hoge"` という文字列が出力  
	- `$!{hoge}` または `$!hoge` … 何も出力されない  


WEBで利用する場合
--------------

様々なWEBフレームワークと併せて利用することもあるかと思います。
その場合、velocity-tools というものを利用することになります。
https://velocity.apache.org/tools/devel/

中でも、velocity-struts を利用することで、
各スコープへの参照が自動化されます。


例:

1. toolbox.xmlに定義されているか？ 
1. 各サーブレットクラスのインスタンスか？
	- `$request`
	- `$session`
	- `$application`
1. ローカル変数が定義されているか？
1. requestスコープにattributeが存在するか？
1. sessionスコープにattributeが存在するか？
1. applicationスコープにattributeが存在するか？

「これなんで実行できてるんだろ・・・？」
みたいに思った場合は、toolbox.xmlに定義されてることが多いかもしれません。



マクロ
----------

velocity-macro.vmというファイルに定義可能で、
view上で頻繁に登場する似た処理を関数っぽく作成しておくことができます。

velocityにはparse機能(他vmファイルを利用する機能)がありますが、
こちらはマクロと違い引数を渡すことができません。

感覚的には、

* よりロジック的なもの(`if`/`foreach`などを使う）はマクロ
* HTMLの部品化(metaタグとか)はparse

かな〜と思います。


velocityでちゃんと表示されない！！
-----------

90%が基本的なミスな気がする。（他の要因だったらすいません・・・）

例:
`form.content.userId` で何回やっても取得できない

確認すること
* `form` はちゃんと値が入っているか？
* `form` に該当するクラスに `getContent` メソッド(引数無し)が存在するか？
* `content` に該当するクラスに `getUserId` メソッド(引数無し)が存在するか？


HTMLエスケープ
------------

`ReferenceInsertionEventHandler`を利用することで、
すべての値について表示前に割り込ませることが可能。

こちらが参考になりました。
http://blog.physalis.net/2013/05/01/velocity-escape.html


なお上記参考サイトの場合、エスケープを回避させたい場合に
変数名末尾に特定文字列(NoEscape)を付与した場合はエスケープさせないようにしています。

このままでももちろん大丈夫ですが、
あとでパっと見たときになんとなくわかりにくくなるので、
velocity-toolbox経由で呼べる関数に、何もしないダミー関数を用意しておき、
その関数でラップされている場合には回避するようにしたほうが個人的には好みです。

```java
public String noescape(String org) {
  // エスケープ回避用のダミー関数。
  // 詳細はReferenceInsertionEventHandlerの実装クラスを参照
  return org;
}
```

```velocity
${utils.noescape(hoge)}
```



enumを呼びたい
-------------
  
FieldMethodizerで利用できなくもないです。
なんとなく強引な方法な気もするので、自己責任で。。。

```java
public enum Hoge {
  PIYO,
  FUGA;
}
```

```java
request.setAttribute("hoge", new FieldMethodizer(Hoge.class.getCanonicalName()));
```

```velocity
${hoge.PIYO.name()}
```
PHPのジェネレータを使ってグレイコードを出力する

## グレイコードとは

[グレイコード - Wikipedia](https://ja.wikipedia.org/wiki/グレイコード)

> グレイコード（英: Gray code グレイ符号）、交番二進符号（こうばんにしんふごう、英：Reflected Binary Code）とは、数値の符号化法のひとつで、前後に隣接する符号間のハミング距離が必ず1であるという特性を持つ。デジタル回路や、具体例としてはアブソリュート・ロータリー・エンコーダーのセンサー出力等に使われる。

ハミング距離が1の進行ということですね。`001` -> `010` -> `011` -> `100`という通常の二進法だと、それぞれ2ビット、1ビット、3ビットの変化が現れてしまうけれども、`001` -> `011` -> `010` -> `110`という進行だと、常に1ビットの変化で次の数が表せるので利点があるということです。


ハノイの塔との関連がありますので有名かもしれません。むしろ説明にあるアブソリュート・ロータリー・エンコーダーってなんでしょうね…名前がかっこいいですね。

それではこのグレイコードをPHPを使って出力してみます。

## グレイコードへの変換

なぜこれで計算できるのかいまいちピンとこないのですが、「自分自身と自分自身１ビット右にシフトしたものの排他的論理和」でその数のグレイコード求めることができます。PHPで書くとこんな感じです。

```php
$i^($i>>1);
```

## ジェネレータを使う

[PHP: ジェネレータとは - Manual](http://php.net/manual/ja/language.generators.overview.php)
> ジェネレータを使えば、シンプルな イテレータを簡単に実装できます。 Iterator インターフェイスを実装したクラスを用意する オーバーヘッドや複雑さを心配する必要はありません。

だそうなので、せっかくなのでPHPのジェネレータを使って実装します。ジェネレータはPHP5.5から取り入れられたので、5.5.0以上でないとできません。


## 実装

```php:graycode.php
<?php
function graycodes($range) {
	foreach($range as $i) {
		// キーも一緒に返すことができます。
		yield $i => decbin($i ^ ($i >> 1)); 
		// 次回はここからスタートします。
	}
}

// 0から15番目までのグレイコードを出力します。
foreach(graycodes(range(0, 15)) as $k => $v) {
	echo sprintf("%2d : %04d\n",$k, $v);
}
```

## 実行結果
```
 0 : 0000
 1 : 0001
 2 : 0011
 3 : 0010
 4 : 0110
 5 : 0111
 6 : 0101
 7 : 0100
 8 : 1100
 9 : 1101
10 : 1111
11 : 1110
12 : 1010
13 : 1011
14 : 1001
15 : 1000
```

## まとめ
PHP5.5からの機能であるジェネレータを使って、グレイコードを出力する簡単なコードを書きました。ジェネレータはファイルを1行ずつ読み込んで処理をする、といったことなどに有用ですが、まずは簡単なものを書いてみるといいかもしれません。
断線したイヤフォンを修理する

イヤフォンが断線した。
気に入っていたのに＞＜
<a href="http://www.amazon.co.jp/exec/obidos/ASIN/B00HZD3RXM/tokyocloudcol-22/ref=nosim/" name="amazletlink" target="_blank">SONY カナル型イヤホン ブラスブラウン MDR-EX650-T</a>
9月は出費が多いしそんなに安い買い物でもないので修理することにした。

パーツは[マルツ秋葉原2号店](http://www.marutsu.co.jp/pc/static/shop/akihabara2go)で購入。
秋月や千石も良いけどマルツも好き。

3.5mmステレオケーブルとφ1とφ3.5の熱収縮チューブ合わせて¥334。
![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/545b654a-f416-86b3-03a9-afbd4b000f0f.jpeg)

先ずは断線したイヤフォンの根本をカットして導線をむき出しにする。
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/4a201990-23bb-7d7b-174f-5ba7ab742d13.jpeg)


買ってきたステレオケーブルも半分に切って、導線を露わにする。
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/9f6a4bad-e1ea-e09c-d2d7-6566a7d0d225.jpeg)


導線の先端にはんだをなじませる。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/ceed5e43-54ea-959c-78de-57aab7495f92.jpeg)


φ3のチューブをケーブルに、φ1のチューブを導線に通した状態ではんだ付けをする。
両者ともに色分けされていたので同じ色同士をはんだづけする。
この状態でショートに気をつけながら音を鳴らしてみる。
鳴った!!
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/2c83f74e-51f1-464d-bb02-8ed3693f40a6.jpeg)


熱収縮チューブに熱を加えて収縮させる。
今回はんだごての根本で軽く触れて収縮させた。
ドライヤーを使ったりライターで炙ったり色々流派があるみたいだが、安全第一で。
![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/c1bec093-4bf6-aeaa-2cff-dcfac29c01b1.jpeg)


導線を軽くねじって、φ3の熱収縮チューブで覆う。
熱を加えて収縮させる。
![7.jpg](https://qiita-image-store.s3.amazonaws.com/0/8748/7cad538b-9f6e-d58f-9fd0-25027de46919.jpeg)


修理完了。
¥334で修理できた!
cmd.Envを設定してexecしたらコケた

goの``exec``でrubyのgemを叩いてた時にハマる。

```go
// rubyのTDを叩きたい!
cmd := exec.Command("td", args...)
// 環境変数設定
cmd.Env = []string{"SOME_PROP=0"}

// 実行
out, _ := cmd.CombinedOutput()
```

## 解決

```go
cmd := exec.Command("td", args...)
// 既存の設定を取得して結合
cmd.Env = append(os.Environ(), "SOME_PROP=0")

out, _ := cmd.CombinedOutput()
```

## 原因

``command.Env``に環境変数を設定すると既存の変数はクリアされます。（よく考えれば当たり前か）
自分のケースでは環境変数がクリアされた状態でrbenvのgemを叩きにいってエラー

それを避けるためために既存の変数を``os.Environ()``で取得して、設定したい環境変数を追加した上で再設定しました。

## 参考

[Go: command with custom environment](http://craigwickesser.com/2015/02/golang-cmd-with-custom-environment/)
Javaの文字列 部分一致（matches関数）

Javaで部分一致する方法をいつも忘れてしまうのでメモっとく。
文字列str1に文字列str2が含まれていればtrue。

```.java
public boolean isMatch(String str1, String str2) {
	if(str1.matches(".*" + str2 + ".*")) {
		return true;
	}
	else {
		return false;
	}
}
```
LaravelでAPIのバージョニングをする

Laravelのルーティングは上から順番に読まれることを利用した小技です。

## 前提条件
- 一部APIに大幅な変更があり、APIのバージョンをあげて対応したい
- 旧APIはversion1として残したい
- クライアントからのアクセスはAPI単位ではなく、一括でversion2に切り替えたい
- 変更がないAPIに関してはversion1同様の処理をするようにしたい
- しかし、version1のControllerの処理をversion2にコピーして使いたくない

## routes.phpの設定方法
Routeのpatternとgroupを組み合わせて定義します。

```php:routes.php
<?php

// API version2の定義
Route::pattern('apiVersion2', 'v2');
Route::group(['namespace' => 'Api\V2', 'prefix' => '{apiVersion2}'], function() {
    Route::get('example/show', 'UserController@show');
});

// API version2に未定義なrouteはv1のAPIを使う
// v1でもv2でもアクセスできるようにpattern定義する
Route::pattern('apiVersion1', 'v[12]');
Route::group(['namespace' => 'Api\V1', 'prefix' => '{apiVersion1}'], function() {
    Route::get('example/show', 'ExampleController@show');
    Route::post('example/delete', 'ExampleController@delete');
    Route::post('example/register', 'ExampleController@register');
});
```

上記のように設定することにより、以下のようなルーティングを実現できる。

| URI | controller |
| --- | --- |
| /**v2**/example/show | Api\\**V2**\ExampleController@show |
| /**v1**/example/show | Api\\**V1**\ExampleController@show |
| /**v1**/example/register | Api\\**V2**\ExampleController@register |
| /**v2**/example/register | Api\\**V1**\ExampleController@register **※** |
**※** apiVersion2のRoute::groupに定義がないので、apiVersion1の定義が有効になる。


Controllerはversionごとにディレクトリを分けておくといい感じです。

```
/controllers
  /api
    /v1
      /ExampleController.php
    /v2
      /ExampleController.php
```
Ruby-Processing アナログ時計


Ruby-Processing でアナログ時計を作ってみました。

![clock2.png](https://qiita-image-store.s3.amazonaws.com/0/1900/7e3902ff-dfaa-8200-77d3-cf4e9bd25b14.png "clock2.png")

```ruby:clock.rb
# アナログ時計のサンプル

def setup
  size 300, 300
end

def draw
  background 0

  time = Time.now
  fill 255
  text(sprintf("%d:%d:%d", time.hour, time.min, time.sec), 20, 20)

  translate width/2, height/2 # 原点を画面中央にする
  stroke(100); fill(100); stroke_weight(1)
  line(-width, 0, width, 0)   # X 軸
  line(0, -height, 0, height) # Y 軸

  radius = 100 # 時計の半径

  for i in 0..60-1
    rad = (90.0 / 15 * i).radians
    len = radius - 10
    xx = len * cos(rad)
    yy = len * sin(rad)
    sz = i % 5 == 0 ? 7 : 1
    ellipse(xx, -yy, sz, sz) # 秒ごとの丸マーク
  end

  stroke 255
  no_fill
  ellipse(0, 0, radius*2, radius*2) # 時計の外枠

  # 針の描画関数
  draw_hand = ->(weight, len, deg) {
    rad = (90 - deg).radians
    x = len * cos(rad)
    y = len * sin(rad)
    stroke_weight(weight)
    line(0, 0, x, -y)
  }

  # 秒針
  draw_hand.(1, radius - 10, time.sec * 6)

  # 長針(分)
  draw_hand.(3, radius - 20, time.min * 6 + 6 * time.sec / 60.0)

  # 短針(時)
  draw_hand.(5, radius - 50, time.hour * 30 + 30 * time.min / 60.0)
end
```

コマンドラインから次のように実行します。

```
$ rp5 run clock.rb
```
Bootstrap 5カラムで表示

以下の記述で５カラム中央表示になる。

            <div class="col-lg-2 col-lg-offset-1">
              A
            </div>
            <div class="col-lg-2">
              B
            </div>
            <div class="col-lg-2">
              C
            </div>
            <div class="col-lg-2">
              D
            </div>
            <div class="col-lg-2">
              E
            </div>
AWS Linux 環境構築(Amazon Linux / Redhat7)

AWSでよくやる初期構築まとめ。

# 設定周り
## SWAP作成
エフェメラルを全部SWAP化
>/etc/rc.d/rc.local に以下を記載※rc.local に実行権限を与えておくこと
mkswap /dev/xvdb
swapon -a

## SELinuxの停止

> \# setenforce 0 
で一時的に停止
\# vi /etc/selinux/config　で
SELINUX=enforcing
　　　　　↓
SELINUX=disable
にしてサーバ再起動

## 周りのサーバに接続
Fromのサーバでssh鍵作成
> ssh-keygen -t rsa -b 4096
（鍵の保存場所とパスフレーズは堅めなPassを入力してEnter）

Toのサーバに入って生成した鍵（id_rsa.pub）をauthorized_keysに追記
> $HOME/.ssh/authorized_keys あたりのやつ

## 作業ユーザ作成
グループの作成
> groupadd -g 1001 hoge

ユーザの作成
> useradd -u 1001 -g 1001 -m -d /home/hoge -s /bin/bash hoge

Wheelについか
> usermod -G wheel hoge

# インストール周り
## jqインストール
> curl -o /usr/bin/jq http://stedolan.github.io/jq/download/linux64/jq
chmod +x /usr/bin/jq

## psql インストール
> yum install postgresql

## RedhatにAWS CLIインストール
> easy_install pip
pip install awscli
■タブ補完有効化
echo 'complete -C /usr/bin/aws_completer aws' > /etc/profile.d/aws-cli.sh

## Redhat のロケール変更
ロケールの設定確認
> localectl  status

ロケールの設定変更
> localectl set-locale LANG=ja_JP.utf8

## Redhat のTimezone変更

タイムゾーン設定確認
> timedatectl status 

タイムゾーンを日本に変更
> timedatectl set-timezone Asia/Tokyo
PagerTabStrip で 初期表示がおかしくなる問題


### PagerTabStripの初期表示問題について

## 再現
![pagertabstrip-bug](http://devalon.biz/content/images/2015/09/pagertabstrip.gif)

この問題は 2015年8月18日に[Issue](https://code.google.com/p/android/issues/detail?id=183127)でも上がっている。


## 解決方法
`com.android.support:appcompat-v7:23.0.1 `
で起こっているバグのようなので、以下のように22.X.Xに書き換えて解決出来る。
ちなみに`com.android.support:appcompat-v7:23.1.`でこのデグレは解消されています。

### build.gradle の修正
#### before
```
defaultConfig {
	// ~~~
	targetSdkVersion 23
	// ~~~
}
dependencies{
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:recyclerview-v7:23.0.1'
    compile 'com.android.support:design:23.0.1'
    compile 'com.android.support:cardview-v7:23.0.1'
}
```
#### after
```
defaultConfig {
	// ~~~
	targetSdkVersion 22
	// ~~~
}
dependencies{
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile 'com.android.support:recyclerview-v7:23.1.0'
    compile 'com.android.support:design:23.1.0'
    compile 'com.android.support:cardview-v7:23.1.0'
}
```
※ Module Projectがあればそっちも確認すること。

.aar(Android Archive) 内で利用している場合は・・・
諦めるか、zip解凍してプロジェクトを追加するしかないですかね・・・。
SQL実行結果をGoogle Spreadsheetに登録するgemを作った話

# 作ったgem

* [RubyGems / rdb2spreadsheet](https://rubygems.org/gems/rdb2spreadsheet)
* [Github / rdb2spreadsheet](https://github.com/muran001/rdb2spreadsheet)

# 作った背景

運用しているサービスのRDBはデータの宝庫です。
たとえばPV数や会員登録数などのKPIデータもSQL叩けば一発で集計できるかと思います。

ただ、そういう大事なデータを毎日手作業でSQL実行して確認するっていうのがダルい・・・
かといって自動で集計してくれるリッチなダッシュボード作るかっていってもそんな工数は取れない。

（いや作ったこともあるんだけど、KPIの変化に柔軟に対応できずに使われなくなるということもあって・・・）

でも、事業数値を日々追い続けるのは大事なことなのでなんとか可視化したいって思ったわけです。
出来る限り開発・運用工数最小限で・・・

# 実現手段を模索

最初は、今までのようにダッシュボードツールを一から作ろうと考えてました。

グラフなんかも、kibana使ったりD3.jsとかhighchartsとか使ってカッチョ良くしてみるかーって考えてたけど、
構築大変な割に、扱うデータやKPIの集計方法が変わるとすぐその変化に耐えられなくなる。

特にデータや見た目・見せ方の部分ってよく変えたいっていう要望がでるのでなんとかしたかった。
で、行き着いたのが、「SQL実行＋Google Spreadsheet登録＆表示」という組み合わせ

以下の様な判断の結果こうなった。

* グラフ表示は、Spreadsheet側に完全に任せる（つまり実装しない）
    * Spreadsheetなら柔軟にカスタマイズできるよね！
* 生SQL実行で表示用データを集計する
    * ActiveRecordとかその他ORM使ってないからエンジニアじゃなくてもいじれるね！
    * SQLの実行結果（表）とSpreadsheetのフォーマット（表）が相性ばっちり

これなら、利用するデータ項目に変化があろうと、集計方法が変わろうと、グラフ表示方法が変わろうともその都度柔軟に対応できる
SQLならエンジニアじゃなくてもメンテできたりする　
→みんなハッピー！


# こんな構成を想定

rdb2spreadsheetは、RDBにSQLを投げて帰ってきた結果をGoogle Spreadsheetに投げるということをやっている
以下の様な感じ。

![design.png](https://qiita-image-store.s3.amazonaws.com/0/40141/7dde6613-5a62-bcf9-c370-0e52856952fb.png)


* ポイント
    * DBおよびGoogle Driveの設定し、あとはSQL準備するだけ
* 準備するもの（詳細はコード参照）
    * RDB
        * アカウント等の接続情報
    * Google Drive
        * API用トークン等発行
        * 更新するbookのハッシュ（urlの一部）

# 具体的な使い方

リポジトリにもあるがこんな感じで使う

```ruby

# rdb connection settings
rdb_configs = {
  "adapter"=>"mysql2",
  "encoding"=>"utf8",
  "host"=>"127.0.0.1",
  "username"=>"root",
  "password"=>nil,
  "database"=>"shop",
  "cast"=>false
}

# google spreadsheet settings
spreadsheet_configs = {
  'client_id' => 'xxxxxxxx',
  'client_secret' => 'xxxxxxxxxx',
  'refresh_token' => 'xxxxxxxxxx'
}

# sql statements (example)
sqls = {
  'under500' => '
    select * from books where price < 500 limit 100
  ',
  '500to1000' => '
    select * from books where price between 500 and 1000 limit 100
  ',
  'over1000' => '
    select * from books where price > 10000 limit 100
  '
}

# spreadsheet hash-key
book_key = 'xxxxxxxxxxxxxxxxxxx'

updater = Rdb2spreadsheet.new(rdb_configs, spreadsheet_configs)
updater.import_all(book_key, sqls)
```

設定情報やSQLを除けば、コード部分は、一番下の3行だけ。

楽ちんデスネ♪


あとはこのプログラムをcronに登録しておけば定期的にデータがSpreadsheetに反映されるようになります

グラフ表示については、Spreadsheetに登録されたデータをつかってご自由に煮るなり焼くなりしてください☆

# 残された課題たち

* 定期実行した場合、毎回対象シートが上書きされる感じになるのでそれをどう残していくか
* 上と合わせてデータが増えてきた時どう削除していくか
* SQLをspreadsheetに置いといてそこから読み込むとか
* Google SpreadsheetだけじゃなくExcelファイルなども出力できるといいかも


# 余談

糞コードにつき、諸先輩方のプルリクお待ちしています
#where句でサブクエリを使う

#where句でサブクエリを使う

ユーザー情報を表したuser_datasテーブル、
都道府県を表したprefsテーブル、
市町村を表したmunicipalitiesテーブルがあるとする。
サブクエリを使ってユーザーが登録している市町村の情報のみを拾ってくる。

```
select * from municipalities where pref_id in (select distinct pref_id from user_datas);
```
gulp-cssnextにPostCSSプラグインを追加する方法

cssnextをgulpで使ってみたかったので、[gulp-cssnext](https://www.npmjs.com/package/gulp-cssnext)を導入してみたのですが、プラグインの追加方法でちょっとつまづいたので、経緯と解決法をまとめてみました。

# 基礎知識

[cssnext](http://cssnext.io/)は、CSSの先行実装を、現状のブラウザが解釈できるCSSに変換してくれるポストプロセッサーです。
cssnextは、[PostCSS](https://github.com/postcss/postcss)のラッパーに当たるツールなので、その機能を内包しています。

# 前提

CSSのコンパイルはPostCSSの機能をラップしている[gulp-cssnext](https://www.npmjs.com/package/gulp-cssnext)にて行う。
（[gulp-postcss側から、cssnextを用いてコンパイルする](https://www.npmjs.com/package/gulp-postcss#using-a-custom-processor)のではないやり方）

# gulp-cssnextのインストール

プロジェクトのルートディレクトリで以下のコマンドを実行。

```
$ npm i gulp-cssnext --save-dev
```

# CSSのコンパイル

gulpfile.jsのタスクは以下のような形で記述すれば、CSSのコンパイルは可能。

```gulpfile.js
var gulp = require('gulp');
var cssnext = require('gulp-cssnext');

var paths = {
  'src': 'src/',
  'dist': 'dist/'
}

gulp.task("css", function() {
  return gulp.src(paths.src + 'css/*.css')
    .pipe(cssnext({
        compress: false,
        import: true
    }))
    .pipe(gulp.dest(paths.dist + 'css/'))
});

```

ただし、gulp-cssnextには、importなどの機能はデフォルトで実装されているが、
Sassのようなネストやミックスインといった機能を使用するためには、プラグインを追加する必要がある模様。

# プラグインのオプションを追加

公式サイトによれば、PostCSSのプラグインを追加するには、[このように](http://cssnext.io/usage/#plugins)プラグイン名を指定して読みこめば良い、とあるので、gulpのタスクにオプションを追記してみる。

※ここでは、Sassのようなシンプルな変数表記を実現する[postcss-simple-vars](https://www.npmjs.com/package/postcss-simple-vars)プラグインを追記した。

```gulpfile.js

gulp.task("css", function() {
  return gulp.src(paths.src + 'css/*.css')
    .pipe(cssnext({
        compress: false,
        import: true,
        plugins: [
          require("postcss-simple-vars")
        ]
    }))
    .pipe(gulp.dest(paths.dist + 'css/'))
});

```

その上で、ソース側のCSS内でネストを使ってコンパイルしてみると、以下のようなエラーが出てしまい、実行できなかった。

```
Error: Cannot find module 'postcss-simple-vars'
```

# プラグインのインストール

これは、プラグイン自体がインストールされていないので当然かと思い、プロジェクトのルートディレクトリで下記のコマンドを実行してみた。

```
$ npm i postcss-simple-vars --save-dev
```

すると、今度はCSSのコンパイルに成功。

試しに、Sassライクな変数を使ってみると、思い通りに変換できていることも確認できた。

```src/style.css
$textcolor: #000;

body {
  color: $textcolor;
}
```

```dist/style.css
body {
  color: #000;
}
```

# まとめ＆分かったこと

- cssnextはPostCSSの機能をラップしている
- gulp-cssnextも、それ単体としてPostCSSをラップしている
- gulp-cssnextが現時点で内蔵している機能やプラグインはデフォルトで使用できる
- gulp-cssnextに実装されていないPostCSSプラグインを使いたい場合は、requireするだけではなく、自分で個別にインストールする必要がある
- プラグインをインストールする場所は、プロジェクトのルートディレクトリでnpm installすればOK

# 注意点

基本的には上記のやり方で問題なさそうだが、プラグインによっては読み込み順や、相互に依存しているものもあるようなので、注意が必要。

例えば、Sassのようなミックスインを可能にする[postcss-mixins](https://github.com/postcss/postcss-mixins)は、 postcss-simple-varsとpostcss-nestedの前にセットする必要があると書かれているので、下記のようにプラグインを指定する。

```gulpfile.js

gulp.task("css", function() {
  return gulp.src(paths.src + 'css/*.css')
    .pipe(cssnext({
        compress: false,
        import: true,
        plugins: [
          require("postcss-mixins"),
          require("postcss-simple-vars"),
          require("postcss-nested")
        ]
    }))
    .pipe(gulp.dest(paths.dist + 'css/'))
});

```
ResultoonをMac + AVT-C875で使おうとしたが途中で挫折した話

https://github.com/entropiajp/resultoon

これをMacで使いたかったのです。

# インストール

雰囲気こんなかんじで後よろしく。

https://gist.github.com/dmiyakawa/1188613bebdb45e07214

opencv3入れるときに--with-qtしてますが意味はなかった気がします (結局後述する「デバッグ」の項は必要でした)

参考まで、最終状態のpip freezeは以下のとおり (デバッグで使うのでipythonとか入れてますが、本体とは関係ないです)

```
$ pip freeze
appnope==0.1.0
decorator==4.0.2
gnureadline==6.3.3
ipython==4.0.0
ipython-genutils==0.1.0
numpy==1.9.2
path.py==8.1.1
pexpect==3.3
pickleshare==0.5
pytesseract==0.1.6
requests==2.7.0
simplegeneric==0.8.1
tesseract==0.1.3
traitlets==4.0.0
```

# デバッグ

しんどい。

https://gist.github.com/dmiyakawa/711364542f9fa3922dc7

OpenCVの古い定数を使ってるのではないか……みたいな雰囲気を感じましたが、私は元気です。

# 起動したらオレの顔がマンメンミ

```cv2.CaptureDevice(0)``` はMacでは内蔵カメラでした。

ただ、内臓カメラでもCaptureDeviceが一つでも取れればコード全体はMac上でも動いているのを意味するので、ここまでは見込みがあるなぁという感じ。

(定数値がおかしいとイカも認識しないでしょうが、まだその段階にいけてません)

# AVT-C875 はCaptureDeviceとして認識されてない？

ここが本題で分からないところでした。

どうもAVT-C875はRECentralからは見えててもOpenCVのCaptureDeviceとしては見えてないんじゃないか、っつーことです。CaptureDevice(1) がないんですね。

http://stackoverflow.com/a/30384945

CaptureDeviceとして1個しかない、ような…… (1個はMac内臓のカメラ)

流石にAVT-C875とOpenCVズバリの組み合わせというのは見つかりませんです。ぐぐっても誰かが出来た、という記録も見当たらないので、ここで挫折しました。

これを読んだあなた、どうか真相を暴いてください。

https://github.com/entropiajp/resultoon/pull/2
エンジニアのための新規事業の評価基準を考える

エンジニアがバタバタ倒れているのに納期、コスト、品質が仕様通りだからプロジェクト成功！！
って、ちょっと疑問なのでもう少し丁寧にプロジェクトの評価をしたいです。

また、一般的に成功率が低いとされる新規事業ですが、勢いとガッツのある人だけの存在とならないように
誰もが社会に貢献したい、解決したいコトを実現できるよな新規事業の評価基準を考えてみました。

プロジェクト管理と同様に新規事業の成果物を分解。

##レベルA：メンバー視点での成功
サービスの善し悪しや、収益性、スケジュールは全く関係無く。
担当した作業別が健全に達成されたかの判断。
極端ですが、新規事業が終了した段階で全員元気であれば達成。

##レベルB：管理、計画視点での成功
一般的なプロジェクト管理の目標達成。品質、コスト、納期が仕様通りに
作られてサービスインした段階で成功。 サービス自体の善し悪しは関係無い。
極端な話、どんなポンコツサービスで他のメンバーが疲弊しても達成可能。
品質、コスト、納期の計画と達成のみに絞った評価基準

##レベルC：プロジェクト視点での成功
ここも収益性とかは関係無いがサービスなどプロジェクトが提供する価値が認められれば成功。
メインターゲットとなるユーザーがサービスの存在を求めていればOK。　細かい数値目標は
それぞれ設定する必要があります。

##レベルD：ビジネス視点での成功
収益性になりますね。　お金が入ってなんぼの評価基準。

##レベルE：将来的な視点での成功
将来的に新たな可能性や価値を生み出せれば成功。

以上

新規事業評価基準は運用段階に入った時点で評価基準は変更する必要あり。
サブクエリを使ってログをカウントし、アクセスが多い上位5件を拾ってくる。

#サブクエリを使ってログをカウントし、アクセスが多い上位5件を拾ってくる。


###SQL
```
select (select count(id) from point_logs where point_id = points.id) as log_count, questions.id from questions LEFT JOIN points on questions.point_id = points.id order by log_count desc limit 5;
```

###結果

```
 log_count | id 
-----------+----
         3 | 18
         3 |  2
         1 | 12
         0 | 11
         0 |  5

```
バイナリ文字列のdoubleを扱う


```c:test.c

#include <stdio.h>

int main( int argc, char **argv ) {

        unsigned char buf[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f };
        double *fp = (double*)buf;
        double d = *fp;

        printf( "%f\n", d ); // output -> 1.000000

        return( 0 );

}


```

バイナリ文字列（unsigned charの配列）のdoubleを、
doubleとして扱い、表示します。

出力結果は、アーキテクチャによって異なります。

以下のサイトを参考まで。

http://oss.oetiker.ch/rrdtool-trac/wiki/PortableRrdFormat
[JAWS-UG CLI] OSX Yosemite(v10.10)上でAWS CLI環境を整備する

AWS CLIハンズオンのための環境構築手順(OSX Yosemite版)です。
適宜更新していきます。


# 前提条件

* [JAWS-UG CLI] 総合案内: http://qiita.com/tcsh/items/14c3278f69ab073afe0f を確認して、必要な手順を終えていること。



# 1. AWS CLIのインストール

## PIPのインストール

```bash:コマンド:
curl https://bootstrap.pypa.io/get-pip.py > get-pip.py
```

```bash:コマンド:
sudo -H python get-pip.py
```

```bash:コマンド:
which pip
```

```text:結果(例)
/usr/local/bin/pip
```

## AWS CLIのインストール

```bash:コマンド:
sudo -H pip install awscli --ignore-installed six
```

```bash:コマンド:
which aws
```

```text:結果
/usr/local/bin/aws
```



参考: http://aws.amazon.com/jp/cli/


## バージョン確認

```bash:コマンド:
aws --version
```


```text:結果:
aws-cli/1.11.19 Python/2.7.10 Darwin/15.6.0 botocore/1.4.76
```



## 参考: AWS CLIのアップグレード

AWS CLIはバージョンアップが頻繁に行なわれるので、更新方法は覚えておきましょう。

```bash:コマンド:
sudo pip install -U awscli --ignore-installed six
```



## 参考: AWS CLIのデグレード

1.11.18に戻す例:

```bash:コマンド:
AWS_CLI_VERSION=1.11.18
sudo pip install awscli==${AWS_CLI_VERSION} --ignore-installed six
```


# 2. npmのインストール

JSON Lintをインストールするために、npmコマンドを導入しておく必要があります。



```bash:コマンド(MacPortsの場合):
sudo /opt/local/bin/port selfup
sudo /opt/local/bin/port install npm
```


# 3. JSON Lintのインストール

JSONフォーマットが壊れていないかどうか確認できます。JAWS-UG CLI必須のツール。

http://qiita.com/tt2004d/items/2ea1af8bfd324585dd07

```bash:コマンド
sudo npm install -g jsonlint
```

gオプションは、システム全体共有のディレクトリにインストールすることを指示します。(デフォルトはカレントプロジェクトのディレクトリ)

```text:結果:
/opt/local/bin/jsonlint -> /opt/local/lib/node_modules/jsonlint/lib/cli.js
jsonlint@1.6.2 /opt/local/lib/node_modules/jsonlint
├── JSV@4.0.2
```

### jsonlintコマンドのテスト (正常サンプル)

```bash:コマンド:
echo '{"key":"value"}' | jsonlint 
```

```text:結果:
{
  "key": "value"
}
```

### jsonlintコマンドのテスト (異常サンプル)

```bash:コマンド:
echo '{"key"}' | jsonlint 
```

```text:結果:
[Error: Parse error on line 1:
{"key"}
------^
Expecting ':', got '}']
```


# 完了
5分間でCDNを試してみる

CDNはたいてい敷居が高くて、「ちょっと試す」わけにはいかないもの。ですが、[ファストリー](https://www.fastly.com)はクラウドサービスでは一般的な無料アカウント（デベロッパーアカウント）を提供してます。FastlyでCDNを試してみましょう。

# 1. Fastlyデベロッパープランへの申し込み

Fastlyの無料アカウントにサインアップしましょう。

1. Fastlyのサインアップ用ページへ行く https://www.fastly.com/signup
1. 入力フォーム（→図1）に必要な情報を入力する
1. SIGN UP FOR AN ACCOUNT ボタンをクリックする
1. Welcome to the future of content delivery.「コンテンツ配信の未来へようこそ」と表示されます

**図1. 入力フォーム**
![image](https://qiita-image-store.s3.amazonaws.com/0/89952/eceac845-941e-0432-f5b3-48d8aa0e6791.png)

入力フォームの項目はすべて必須です。First Name（名）、Last Name（姓）、Email（メールアドレス）、Password（パスワード：6文字以上）、Company（会社名）、Phone（電話番号）をすべて半角の英数字と記号で指定してください。

# 2. メールアドレスの確認

サインアップ時に指定したメールアドレスに、確認用のメールが届きます。

1. メールボックスをチェックする
1. support@fastly.comからのメールを開く（件名：Please Verify Your Fastly Account）
1. リンクをクリックする（Please confirm your email here「ここクリックしてメールアドレスを確認してください」）
1. Log in to Fastly「ログインしてください」という画面（→図2）が表示されます
1. 先ほど指定したメールアドレスとパスワードを使ってログインします

**図2. ログイン画面**
![image](https://qiita-image-store.s3.amazonaws.com/0/89952/1b272b0a-f2bc-2627-b44e-ee766f4437fd.png)

ログインできたら、アカウント作成が完了です。

ページ内で次のダイアログ（図3. ログイン完了）が表示されていたら、ダイアログ右上の × 印をクリックして閉じてください。

**図3. ログイン完了（新コントロールパネル説明のダイアログ）**
![image](https://qiita-image-store.s3.amazonaws.com/0/89952/e63aa6b6-6fc4-27f7-94b9-4604b2baee2c.png)

ダイアログを閉じた時点で表示される、設定作業スタート画面はこのようになっています。

**図4. 設定スタート画面**
![image](https://qiita-image-store.s3.amazonaws.com/0/89952/264e28e2-4a2e-1626-eac2-f64fdf611d45.png)

# 3. サービス設定

設定スタート画面（図4）より、CDNの設定を行いましょう。以下では、http://www.example.com というサイトを Fastly 経由で配信するという前提で説明します。

1. 画面左側の空欄には、CDNで配信するサイトのドメイン名を入力します。
1. 画面右側の空欄には、CDNで配信するサイトのオリジンサーバーのIPアドレスとポート番号を入力します。
1. Continueボタンをクリックします。
1. 次の画面が表示されます。

**図5. 追加設定画面**
![image](https://qiita-image-store.s3.amazonaws.com/0/89952/b8ec53dc-83f2-9348-c2af-951b8be21f19.png)

1. この画面（図5）では、追加機能（圧縮、ログ、ヘルスチェック）を設定することができますが、ここではどれも設定せず、Continueボタンをクリックします。

1. 設定が完了すると、次の画面（図6）が表示されます。

**図6. 追加完了画面**
![image](https://qiita-image-store.s3.amazonaws.com/0/89952/291fb5ba-23ee-c0ea-3c40-deb9be3a30b2.png)
 
# 4. 動作確認

あなたのウェブサイト上のコンテンツを、CDN経由で配信してみましょう。

本番環境にFastlyを用いる場合は、ネームサーバーの変更が必要ですが、ここでは自分のパソコンだけで動作確認してみます。

hostsファイルを書き換えることで、そのパソコン上のみで Fastly 経由の配信を試すことができます。[hostsファイルを利用したCDNの導入前テスト](http://qiita.com/AtsushiFukuda/items/b277fe7db05a7f1cfa26)にてその方法を説明していますので、参考にしてください。

# 関連ドキュメント

- [Sign Up](https://www.fastly.com/signup) Fastlyのサインアップ用ページ
- [Startup Guide](https://docs.fastly.com/quickstart/) ここで説明したプロセスの詳細
- [Documentation](https://docs.fastly.com/) Fastlyのドキュメント