OmniAICreator/Qiita-1.07M huggingface dataset:
配牌からアガれるかアガれないか予測する

# はじめに

![sample_image.gif](https://qiita-image-store.s3.amazonaws.com/0/118817/d1e9c155-16a6-2103-9621-7ed4f219b96f.gif)


## 趣旨
個人的にディープラーニングや機械学習を学習したいと思い、O'Reilly Japanさんから出版されている[ゼロから作るDeep Learning](https://www.oreilly.co.jp/books/9784873117584/)を読みました。
しかし、私自身に知識がなく、いまいちピンとこなかったので、簡単なものを作ってみようと考えました。

とはいえ、せっかくなら自分の趣味でもある麻雀に関わるところで作ろうと考えました。
## 筆者のスペック
* Python、機械学習ともに初心者
* 普段はPHPやRubyを使ったWebのお仕事

## 環境
* Python 3.6.0
* bottle 0.12.13
* heroku

## 機能概要
作成したアプリは下記になります。
https://python-mahjang.herokuapp.com/index

また、ソースコードは下記になります。
https://github.com/naoki85/python_mahjong

* 配牌と結果のみを学習対象としました。
* 配牌を下図のように、かたちで分解し、それぞれの重みから「アガれる」か「アガれない」か出力します。
* あくまで「アガリ」という結果のみなので、役にはこだわっていません。

![図20170116.png](https://qiita-image-store.s3.amazonaws.com/0/118817/6432f73b-69dc-985a-56c4-a559de420f47.png)

# 実装に関して
## 教師データ
教師データはYoutubeなどでプロの対局を見て、配牌と結果を収集しました。
数としては100いっていないため、これは継続して収集します。

## 前処理
配牌を以下の3つのノードに分解しています。

* 順子の数（階段並び）
* 対子の数（同じ牌が2枚）
* 暗刻の数（同じ牌が3枚）

## 各ノードの重みの学習
各ノードの重みは[ゼロから作るDeep Learning](https://www.oreilly.co.jp/books/9784873117584/)を参考に、勾配法で推定しています。

# 実際に使ってみた
Youtubeにあがっていたとあるネット麻雀の動画で試してみました。

| 局 | 結果 | あがれる確率 | あがれない確率 |
|:------------------:|:------------------:|:------------------:|:------------------:|
| 東1局 | あがれない | 17% | 83% |
| 東2局 | あがれない | 29% | 71% |
| 東3局 | あがれない | 7% | 93% |
| 東3局1本場 | あがれない | 17% | 83% |
| 東4局 | あがれない | 33% | 67% |
| 南1局 | あがれる | 20% | 80% |
| 南1局1本場 | あがれない | 26% | 74% |
| 南2局 | あがれない | 17% | 83% |
| 南3局 | あがれる | 26% | 74% |
| 南4局 | あがれる | 23% | 77% |

パッと見、ちゃんと予測できているようには見えないです。
よく考えたら、麻雀は4人のうち1人があがれるゲームなので、単純計算でアガれる確率は25%です。
教師データが足りないのかもしれないと思い、とりあえずプロの対局1局分追加してみました。

## 再テスト
同じ動画で再度試してみました。
アガれない結果のみを比較してみます。

| 局 | 結果 | 前回のアガれない確率 | 再テストのアガれない確率 |
|:------------------:|:------------------:|:------------------:|:------------------:|
| 東1局 | あがれない | 83% | 73% |
| 東2局 | あがれない | 71% | 64% |
| 東3局 | あがれない | 93% | 92% |
| 東3局1本場 | あがれない | 83% | 80% |
| 東4局 | あがれない | 67% | 72% |
| 南1局 | あがれる | 80% | 85% |
| 南1局1本場 | あがれない | 74% | 79% |
| 南2局 | あがれない | 83% | 80% |
| 南3局 | あがれる | 74% | 79% |
| 南4局 | あがれる | 77% | 73% |

10局のうち、6局の「アガれない確率」が下がっています。
やはり、教師データを増やせば結果は変わってくるようです。

## 学習させた結果から
学習させた重みパラメータは下記になります。
第1要素がアガリへの寄与、第2要素がアガれない方への寄与になります。

```py
# 第一要素があがれる方、第二要素があがれない方
# 重み
[[ 0.17258578  -0.17396835]    # 順子
  [ 0.20088727 -0.20564398]    # 対子
  [-0.33262621  0.34681625]]  # 暗刻
```
この結果を見ると、順子、対子はアガリに寄与していますが、暗刻は逆にアガリに寄与していないようです。
暗刻があると手が狭くなるからでしょうか？

バイアスパラメータは下記になります。
すでにアガれない方のバイアスが高すぎます。

```py
[-1.07893278  1.07893278]
```
# 課題
現在は下記の2点を課題としてあげて勉強しようと思っています。

1. 教師データを増やす
2. レイヤーのノードを追加（リャンメン、カンチャン、ペンチャン）の数

今回このWebアプリを作ったのは、教師データを増やす上で入力を楽にしたいためです。
その過程でPythonの軽量FWであるbottleについて学べて良かったと思っています。

# さいごに
ディープラーニングも学習したてで、何をして良いのかもよく分かっておりません。
（そもそも麻雀という不確定要素の塊を題材にすること自体ナンセンスなのかもしれませんが。。。）

そのため、ご指摘やそもそも間違っているなどのご指導ありましたらコメントをください！
（アドバイスなどもいただけると嬉しく思います。）
Perl::Critic(perlcritic)を使用して静的解析、コーディング規約テストを実施(実施編：コマンド)

Perlの静的解析、コーディング規約テストを実施する為にPerl::Criticを使用する事になったので、内容を残しておきます。

dockerのubuntuにて実行
「Ubuntu 14.04.3 LTS」
(実行日付：2017/02/26)

## コマンド実行
コマンド：
perlcritic 「ファイル名称」

(実行結果)

```
# perlcritic testCode.pl
Code before strictures are enabled at line 1, column 1.  See page 429 of PBP.  (Severity: 5)
#
```

(テスト対象ファイル内容)

```
# cat testCode.pl
print "Hello world";

# 
```

### 出力結果を対象外とする場合
オプション：
--exclude

(実行例)

```
# perlcritic --exclude=stric testCode.pl     
testCode.pl source OK
# 
```

### severity設定
番号(１〜５)を設定して出力する内容を設定します。
２を設定すると、２以上の内容を出力します。
番号と意味は以下の通りです。

    SEVERITY NAME   ...is equivalent to...   SEVERITY NUMBER
    --------------------------------------------------------
    --severity gentle                           --severity 5
    --severity stern                            --severity 4
    --severity harsh                            --severity 3
    --severity cruel                            --severity 2
    --severity brutal                           --severity 1

オプション：
--severity

(実行例)

```
# perlcritic --severity=2 testCode.pl
Module does not end with "1;" at line 1, column 1.  Must end with a recognizable true value.  (Severity: 4)
Code not contained in explicit package at line 1, column 1.  Violates encapsulation.  (Severity: 4)
No package-scoped "$VERSION" variable found at line 1, column 1.  See page 404 of PBP.  (Severity: 2)
Code before strictures are enabled at line 1, column 1.  See page 429 of PBP.  (Severity: 5)
Code before warnings are enabled at line 1, column 1.  See page 431 of PBP.  (Severity: 4)
# 
```

### その他設定
コマンドのhelpを実行する事で、その他の設定内容を確認する事が出来ます。

コマンド：
perlcritic --help

(実行結果)

```
# perlcritic --help
Usage:
      perlcritic [-12345 | --brutal | --cruel | --harsh | --stern | --gentle]
                 [--severity number | name] [{-p | --profile} file | --noprofile]
                 [--top [ number ]] [--theme expression] [--include pattern]
                 [--exclude pattern] [{-s | --single-policy} pattern]
                 [--only | --noonly] [--profile-strictness {warn|fatal|quiet}]
                 [--force | --noforce] [--statistics] [--statistics-only]
                 [--count | -C] [--verbose {number | format}] [--allow-unsafe]
                 [--color | --nocolor] [--pager pager] [--quiet]
                 [--color-severity-highest color_specification]
                 [--color-severity-high color_specification]
                 [--color-severity-medium color_specification]
                 [--color-severity-low color_specification]
                 [--color-severity-lowest color_specification]
                 [--files-with-violations | -l]
                 [--files-without-violations | -L]
                 [--program-extensions file_name_extension]
                 {FILE | DIRECTORY | STDIN}

      perlcritic --profile-proto

      perlcritic { --list | --list-enabled | --list-themes | --doc pattern [...] }

      perlcritic { --help | --options | --man | --version }

# 
```

参照サイト：
[perlcritic](http://search.cpan.org/~thaljef/Perl-Critic-1.126/bin/perlcritic)
[Swift3] UIPageViewControllerの使い方

この記事は、[【決定版】UIPageViewControllerの使い方（Swift）](http://qiita.com/Takeshi_Akutsu/items/dbf54df8e8a50e8ed5be)のコードをSwift3で書き直したものです。
StoryBoardの設定などは上記の記事で確認してください。


```swift:swift3
import UIKit

class PageViewController: UIPageViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.setViewControllers([getFirst()], direction: .forward, animated: true, completion: nil)
        self.dataSource = self
        
    }
    
    func getFirst() -> FirstViewController {
        return storyboard!.instantiateViewController(withIdentifier: "FirstViewController") as!FirstViewController
    }
    func getSecond() -> SecondViewController {
        return storyboard!.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
    }
    func getThird() -> ThirdViewController{
        return storyboard!.instantiateViewController(withIdentifier: "ThirdViewController") as!ThirdViewController
    }
}

    extension PageViewController : UIPageViewControllerDataSource {
        
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
            if viewController.isKind(of: ThirdViewController.self) {
                // 3 -> 2
                return getSecond()
            } else if viewController.isKind(of: SecondViewController.self) {
                // 2 -> 1
                return getFirst()
            }else{
                // 1 -> end of the road
                return nil
            }
        }
        
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
            if viewController.isKind(of: FirstViewController.self) {
                // 1 -> 2
                return getSecond()
            } else if viewController.isKind(of: SecondViewController.self) {
                // 2 -> 3
                return getThird()
            }else{
                // 3 -> end of the road
                return nil
            }
        }
    }

```
国民の祝日のCSVをいい感じに変換するRubyスクリプト

※ 2017/03/01時点で、元のCSVが修正されて正規化しちゃいましたので、このスクリプトは不要になりました。

こちら
http://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
で公開されている、CSVがなかなか扱いづらいということで、ちょっとしたデータベース設計の演習問題として扱ってみます。

まず、内閣府からは以下のようなCSVが与えられています。

![SS 2017-02-26 16.16.31.png](https://qiita-image-store.s3.amazonaws.com/0/53489/f15fc406-c9f1-6207-0bda-6e17ae702440.png)

扱いづらいとろを上げてみます。

- 平成と西暦の併記がパースしづらい
- 名称、月日などの同じ意味の列が横に並んでる（縦に並ぶのが正解）
- SJISなので、ターミナルで見づらい

ということで、加工してみたサンプルがこちら。

```rb
require "open-uri"

url = "http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv"

puts "\uFEFF名称,月日"
open(url).each.with_index{|line,idx|
  next if idx == 0 or idx == 1
  line.chomp!
  line.encode!("utf-8","sjis")
  cols = line.split(",")
  while true
    out = cols.shift(2)
    break if out.first.to_s == ""
    puts out.join(",")
  end
}
```

## 解説

- open-url でファイルのようにWeb上のコンテンツを開く
- ファイル先頭にBOMをつけて、UTF8であってもエクセルでダブルクリックで文字化けしないように（もちろんUTF8なのでMacやLinuxでも扱いやすいように）
- SJISからUTF8に変換
- 1行目と2行目はスキップ
- カンマでsplitすると、6カラム取得されるので、2カラムずつ出力
- 空行がでてきたらそこで終了
- データの並び順や年のグルーピング情報はCSVには保持しない

## 実行方法

```bash
$ ruby shukujitu.rb  >  out.csv
```

![SS 2017-02-26 16.23.49.png](https://qiita-image-store.s3.amazonaws.com/0/53489/51482193-89a8-44f7-a6b2-3dd4209e18fd.png)
WebAPIまとめ

### WebAPIとは？
* HTTPプロトコルを利用して呼び出すAPI

### 具体例
* Amazon
  * 製品を公開するウィジット提供
* Twitter
* Facebook
  * 「いいね」の自サイト埋め込みJavascript提供
* Yahoo!
* Google 検索API

* WebAPIディレクトリサービス
  * http://www.programmableweb.com/

* ウェブページをAPIに変換するサービス
  * http://import.io/
  * https://www.kimonolabs.com/


### API一般公開で考慮すべきこと
* 利用規約の公開
  * 問題行動に対する対処の明記

* レートリミット
  * 多くのAPIはユーザごとのアクセス数の制限を設けている

* 仕様が存在していないものはデファクトスタンダードに従う
  * twitter, facebookのような、世の技術者がよく使っているAPIなど。


### REST API
* GET
  * 情報取得
  * GETメソッドではデータの取得のみにする(googleなどのクローラがGETでアクセスする為)
* POST
  * 新規登録
* PUT
  * 既存リソースを上書き
* PATCH (一度RFCから削除されて、2010/3のRFC 5789で復活)
  * 既存リソースの一部変更

* GET,POSTは古くからある(HTTP0.9)から有るが、その他は利用出来ないケースがあり得る

* REST LEVEL3 API
  * 入口となるエンドポイントが分かれば、続くエンドポイントをユーザは知る必要が無い。
    * 最初のエンドポイントのレスポンスに次のエンドポイントを格納。ブラウザがWebページを辿るやり方。

### URI設計(エンドポイント)
* APIのインターフェースとなる、エンドポイントを定める
* URIはシンプルに短く
* 不要な単語の短縮をしない
* スペルミスに注意
* 大文字小文字を混在しない(小文字で統一など)
* サーバー内部情報の公開を避ける
  * エンドポイントの名称を xxx.php にすると、PHPの脆弱性を狙われてしまう

* GETメソッドなのに、エンドポイントにget_xxxとするのは冗長

* URIのRはResourceであり、リソースを表現するもの。
  * エンドポイントにsearchなどの動詞を含めるのは本来から外れてしまう。
  * searchと他のAPIのエンドポイントを分けるなど、それなりの意図が有れば良い(?)

### 認証
* OAuth 2.0

* アクセストークンの有効期限切れ
  * アクセストークンと一緒にリフレッシュトークンを発行しておく
    * 発行しない場合は、再ログイン

* 自分の情報を取る場合は、エンドポイントにme,selfなどをキーワードにする
  * 現在のアクセストークンを使う動きが出来る


### レスポンス
* データフォーマット指定(jsonやxmlなど)
  * クエリパラメータ指定が一般的
  * GETのヘッダで指定もOK
    * Accept: application/json

* JSONP
  * ドメインを超えたアクセスが可能
    * \<script>タグに記述するので制限が回避出来る

  * エラーはHTTPのステータスコードで返さない
    * \<script>タグの読み込みが中断する動作となり。エラー原因が分かり難い
    * OKとなる200を返し、そのレスポンスボディーに格納する。

* 1つの作業に対して複数回のアクセスが必要な設計は避ける
  * ただ、ユーザが必要とする以上のデータを返しても重くなるので、
    * クエリパラメータ等で項目を指定出来るようにする
    * 項目をまとめたレスポンスグループをリクエストで指定する

* データ構造
  * なるべくフラットに
  * 階層化した方が絶対に良い場合は階層化も有り。
  * by Google スタイルガイド

* 配列データ
  * レスポンスのトップレベルで配列を返さない。オブジェクトで包む。
    * JSONインジェクション対策
  * 次のページが有る場合にフラグを含めたり、HATEOASのパターンで次ページへの情報を含める

* 単語はキャメルケース(userId)推奨
  * (スネークケース(user_id))

* メディアタイプ
  * text/plain (プレーンテキスト)など、IANAに登録されている

  * 独自メディア定義の接頭辞
    * Standards tree (標準ツリー) : なし
    * Vendor tree (ベンダツリー)  : vnd.
    * Personal(Vanity)tree (パーソナルツリー) : prs.
    * Unregistered tree (未登録ツリー) : x.


### エラー処理
* 適切なHTTPステータスコードを返す
* エラーでHTMLが返ることを防ぐ
* ブロックした相手には、HTTP 403(アクセス禁止)などは返さない。
  * むしろトラブルになる恐れがある為。

### キャッシュ管理
* レスポンスヘッダで期限を設定
  * Expires : 期限切れ時刻を設定
  * Cache-Control : 現在時刻からの秒数
  * 上記、両方が設定されている場合はCache-Controlが優先される

  * Cache-Control :stale-while-revalidate
    * max-age指定による期限切れ後も、プロキシサーバがキャッシュを返して良い時間
      * その間、プロキシサーバーは、非同期にキャッシュの検証を行う。

### APIのバージョン管理
* URIにバージョンを埋め込む
* クエリ文字列にバージョンを入れる


### 参考文献
* WebAPI: The Good Parts  O'REILLY
docker service の inspect --pretty を列挙する


扱っているdocker serviceの数が３桁とかになってくると、このnodeに依存しているserviceはどれだっけ？　というような事を把握するのが大変になってきます。サービスの現在状態がローカルに存在してれば適当に`grep`して探せるのですけど、`docker service inspect` して回らないといけないので大変です。

ということで、全てのserviceの`inspect --pretty`を列挙する以下のようなスクリプトを作りました。`--pretty`のほうが行志向なので`grep`との相性が良いです。

`ds_all.sh [-q]`

```
#!/bin/sh
NAMES=`docker service ls | tail -n +2 | awk '{print $2}' | sort`
n=0
N=`echo "$NAMES" | wc -l | bc`
for I in $NAMES; do
  n=`expr $n + 1`
  if [ "$1" != "-q" ]; then
    echo "** $I ** $n/$N" 1>&2
  fi
  docker service inspect --pretty $I | awk "{print \"$I: \"\$0}"
done
```

`ds_all.sh | grep hostname` とかやると特定のhostにConstraintsが設定されているserviceが分かります。
ちなみに、現時点で dockerのservice formatterにtypoがあり、ConstraintsであるべきところがContraintsになっているので
`grep Constraints` してもマッチしなくて困りました。

* [Fixed typo in service formatter.](https://github.com/docker/docker/pull/31363)
RailsGirlsチュートリアルで画像をDropboxに保存する

# 対象者
[Herokuへのデプロイ](http://railsgirls.jp/heroku)が成功した人

# 問題点
Herokuに保存した画像はしばらくアクセスしないと消えてしまう。
AWS S3に保存するように変更すれば消えないが、費用がかかる。

# 対策
Dropboxを利用すれば無料で画像を保存することができる。

# 方法
* 予めDropboxにユーザー登録しておく
* DropboxからAPI Tokenを取得する

[ここ](https://www.dropbox.com/developers/apps)にアクセスして「Create App」をクリックする。

Choose an APIは**Dropbox API**を、Choose the type of access you needは**App folder**を選択する。
最後に、**Nmae your app**には「railsgirls」等好きな名前を入力する。
![screencapture-dropbox-developers-apps-create-1488091018373.png](https://qiita-image-store.s3.amazonaws.com/0/15147/828e62d9-d86a-fc83-c10d-236c9dc156fd.png)

登録後表示された画面から「App key」と「App secret」を取得してメモっておく。

* Gemfileの修正

Gemfileの次の行を

```ruby
gem 'carrierwave'
```

次のように書き換える。

```ruby
gem 'carrierwave', '~> 0.9'
gem 'carrierwave-dropbox'
gem 'dotenv-rails'
```

* `bundle install`を実行してライブラリを更新する
* 次のコマンドを入力してTOKENを取得する

```
$ rake dropbox:authorize APP_KEY=保存したapp_key APP_SECRET=保存したapp_secret ACCESS_TYPE=dropbox
```

* Enterを押すと入力待ちになる。表示されたURLにWebブラウザでアクセスして「許可」ボタンを押す。
* コンソールに戻って"y"を押し、先に進める。
* access_token、access_token_secret、user_idが表示されるのでメモっておく。
* config/initializers/carrierwave.rbの作成

ファイルを新規作成し、次の通り中身を作成する

```ruby
CarrierWave.configure do |config|
  config.dropbox_app_key = ENV['APP_KEY']
  config.dropbox_app_secret = ENV['APP_SECRET']
  config.dropbox_access_token = ENV['ACCESS_TOKEN']
  config.dropbox_access_token_secret = ENV['ACCESS_TOKEN_SECRET']
  config.dropbox_user_id = ENV['USER_ID']
  config.dropbox_access_type = :auto
end
```

* app/uploaders/picture_uploader.rbの修正

storageの設定を変更する。

```ruby
storage :dropbox
```

* .envファイルの作成

プロジェクトディレクトリ直下に`.env`というファイルを作成する。内容は次の通り。

```
APP_KEY: 保存したapp_key
APP_SECRETE: 保存したapp_secret
ACCESS_TOKEN: 保存したaccess_token
ACCESS_TOKEN_SECRET: 保存したaccess_token_secret
USER_ID: 保存したuser_id
```

* .gitignoreに次の行を追加

```ruby
.env
```

これを忘れるとgithub等にDropboxのAPI TOKENが公開され、他人に自分の写真やファイルを見られる可能性があるので注意する。

* gitにコミットする

次のコマンドでgitにコミットする。

```
$ git add .
$ git commit -m "画像をDropboxに保存するように変更"
```

* 動作確認

```
$ rails server
```

Railsのサーバーを動作させ、画像ファイルの登録ができることを確認する。うまく動いたらHerokuに公開する。

* Herokuへの公開準備

次の手順で環境変数を登録する

```
$ heroku config:set APP_KEY=保存したapp_key
$ heroku config:set APP_SECRETE=保存したapp_secret
$ heroku config:set ACCESS_TOKEN=保存したaccess_token
$ heroku config:set ACCESS_TOKEN_SECRET=保存したaccess_token_secret
$ heroku config:set USER_ID=保存したuser_id

```

* Herokuへ登録する

```
$ git push heroku master
```

# 参考サイト
http://hyperneetprogrammer.hatenablog.com/entry/2015/04/14/141701
SSH の Dynamic Port Forwarding 経由でgitのリモートリポジトリに接続する


次の条件に当てはまる場合に、踏み台サーバ経由で社内ローカルネットのgitリポジトリに接続する方法

- 社内のローカルネットにgitのリモートサーバがあって、外部からは直接接続できない
- メンテナンス等用途の踏み台サーバがあり、踏み台からならgitサーバにも接続できる

## 手順

1. SSHの Dynamic Port Forwarding を開始する。
次のように sshで踏み台サーバに接続する。

 ```bash
 $ ssh -D <ポート番号> -N <踏み台サーバアドレス>
 ```
 例えば、次のように実行すると、socks5のプロキシが `localhost:8888` で立ったことになり、fumidai.jp経由で向こう側のネットワークにあるサーバにアクセスできる。
 
  ```bash
 $ ssh -D 8888 -N fumidai.jp
 ```
以下ポート番号は8888として説明する。

2. gitのプロキシの設定

 接続したいリポジトリで 次のように `http.proxy` を設定する。
 
 ```
 $ git config http.proxy socks5://localhost:8888
 ```
 
 するとリポジトリの `.git/config` に設定が追加される。
 もし、どのリポジトリにもこのプロキシを適用するなら、`-g` オプションを付けてグローバルな設定にすれば良い。

3. あとは普通にgitで接続する。
 これで接続できるので、`git pull` なり、`git fetch` してリモートの変更を取り込める。もちろん `git push` だってできる。
 
 ただ、ホスト名を接続先のローカルネット内の内部DNSで解決している場合にはホスト名では接続できない。その場合はホスト名をローカルネット内のローカルのIPアドレスで指定する。
 
## ブラウザで接続する
踏み台の向こうのgitサーバが、GithubとGitlabとかといったブラウザでアクセスできるものの場合、ブラウザのプロキシとして使うこともできる。
chrome や Firefox でFoxyProxy等のプロキシ設定アドオンを使うと、ON/OFFが簡単で便利

- [FoxyProxy Standard \- Chrome ウェブストア](https://chrome.google.com/webstore/detail/foxyproxy-standard/gcknhkkoolaabfmlnjonogaaifnjlfnp?hl=ja)
- [FoxyProxy Standard :: Add\-ons for Firefox](https://addons.mozilla.org/ja/firefox/addon/foxyproxy-standard/)

FoxyProxyを使う場合には最低限、次のように設定すればよい。

- 手動プロキシ設定
	- ホストまたはIPアドレス：localhost
	- ポート：8888
	- SOCKSプロキシ：ON、SOCKS v5 を選択

あとはブラウザでのこのプロキシ設定を有効にして、普通にアクセスするだけ。

## 参考
- [CMS Offline Software](http://cms-sw.github.io/tutorial-proxy.html)
AppVeyorのWindowsに最新のTeXLiveをインストールするスクリプト

# はじめに

LaTeXのドキュメントをLinuxやmacOSでコンパイルできるかどうかをテストするCIを[前回の記事](http://qiita.com/yyu/items/a857f05b223b1057a5ff)で述べた。今回の記事ではAppVeyorというWindows用のCI環境でLaTeXのドキュメントをコンパイルするためのスクリプトを作成した。
なお、この成果は次のリポジトリにある。

- https://github.com/y-yu/install-tex-appveyor

# 使い方

次のようなものを`.appveyor.yml`に書けばよい。

```yaml
image: Visual Studio 2015
environment:
  PATH: '%PATH%;C:\texlive\2016\bin\win32'
install:
  - curl -O https://raw.githubusercontent.com/y-yu/install-tex-appveyor/master/install-tex.sh
  - bash ./install-tex.sh
cache:
  - 'C:\texlive\2016\texmf-var\fonts\cache'
build_script:
  - tlmgr install collection-langjapanese # something you want to install
  - # somethings
```
IARからGASに書き換えるバッチファイルのメモ追記していく用

```bat:convertIARtoGAS.bat
@echo off
setlocal enabledelayedexpansion

for /f "delims=" %%i in ('cmd /u /c echo;名') do (
	set CR=%%i
	set CR=!CR:~0,1!
)

set LF=^



rem set inFile=startup.s
rem set outFile=gnu_%inFile%
echo ^@ > gnu_startup.s

for /f "delims=" %%a in (startup.s) do (
	set str=%%a
	set str2=!str:^;=@!
	set str3=!str2:END=.end!
	set str4=!str3:SECTION=.section!
	set str5=!str4:^(1^)=!CR!!LF!        .align 1!
	echo !str5! >> gnu_startup.s
)

pause

```
http://www.cypress.com/file/289666/download
Rails4以降で正規表現の `^` や `$` を使うと怒られる訳。

こんにちは。18歳女子高生ながらエンジニアとして色々なところでアルバイトをしている 7coco です。

# Rails で ArgumentError
先日 Rails で validation を書いていたら

> The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option? (ArgumentError)

と Rails に言われました。
要するに「`^`と`$`はセキュリティ的に問題があるかもよ。`\A`と`\z`を使いたかったんじゃない？そうじゃなかったら `:multiline => true` をオプションで書いてね。」と仰っているようです。

`^`と`$`を`\A`と`\z`に書き換えると Rails は何も言わなくなりますが`^`と`$`を使うとどんな問題があるのかがわからなかったので調べてみました。

# `^` / `$` と `\A` / `\z` の違い
`^` ： 行頭
`$` ： 行末
`\A` ： 文字列の先頭
`\z` ： 文字列の末尾

違いがわかりましたでしょうか。
`^`, `$` は行頭、行末を意味するので複数行の文字列が渡された場合は予期せぬ値を許容してしまう可能性があります。

次の例を見てみましょう。
複雑な正規表現は読むのも考えるのも大変なので、"foo" から始まって "bar" で終わる文字列にマッチする正規表現を考えてみることにします。

## `^` と `$` の場合
![スクリーンショット 2017-02-26 15.02.11.png](https://qiita-image-store.s3.amazonaws.com/0/167559/aaaa71fd-3df6-ae7c-cd58-7aa2b93a198b.png)

「一行目はマッチしていなくても二行目はマッチしているからOK!」という判断になってしまいました。

## `\A` と `\z` の場合
![スクリーンショット 2017-02-26 15.04.04.png](https://qiita-image-store.s3.amazonaws.com/0/167559/a7a10920-42bf-859f-1aa6-0e89d684e870.png)

今度はきちんと弾かれています。

# まとめ
このような問題から Ruby, Rails では `^` と `$` ではなく `\A` と `\z` を使うのが必要なようです(言語によって違いがあるみたいです)。
また、複数行の入力をもとから想定している場合などは `:multiline => true` オプションをつければ `^` と `$` を使うこともできます。

# 参考
[Railsの正規表現でよく使われる \A \z って何？？](http://qiita.com/jnchito/items/ea7832df6f64a9034872)
[CSS設計 フロントエンドエンジニア]BEMを触ってみた。

今回社内で少し、BEMについて触れてみたので共有。(触ったばかりなので少しだけ。)

#BEMとは
- 簡単に言うとフロントエンドの設計方法の一つです。Block,Element,Modifierの略ですね。
- class名にルールがあると思ってもらえば分かりやすいと思います。

##BEMで書くと便利なこと
- 接頭辞としてcomponentだったら、.c-block, .c-block\_\_element、projectだったらp-block, .p-block\_\_elementなどとするとコンポーネントかプロジェクトかなどが分かりやすくなる。
- 最初のうちに結構やりがちな!importantなどで優先順位をあげてしまったり、クラス名を追加して思わぬとこでデザインがおかしくなったりするのを防げる。

##コード
- 実際に見てもらったほうが分かりやすいかと思います。
- 今までのコード
![スクリーンショット 2017-02-26 14.52.18.png](https://qiita-image-store.s3.amazonaws.com/0/163415/b2774095-cc92-7343-a2da-bc9c8b44964e.png)
![スクリーンショット 2017-02-26 14.54.01.png](https://qiita-image-store.s3.amazonaws.com/0/163415/35398722-0ef4-fcfd-1437-b8aed072d276.png)
- ちょっと適当ですがこんな感じで思い通りに動かないなんてこともありました。(量が増えれば増えるほどこういうのが多くなる。。)
- BEMでのコード
![スクリーンショット 2017-02-26 15.01.08.png](https://qiita-image-store.s3.amazonaws.com/0/163415/c654092b-5079-59c0-b816-0f3c3e58d30b.png)
- ざっと説明させていただきます。.textboxがblockになります。
- textboxの中にあるtextbox\_\_textがelementになります。\_\_アンスコ2つでelementということを表しています。要はtextboxの中のtextですよと言っているようなイメージです。
![スクリーンショット 2017-02-26 15.04.47.png](https://qiita-image-store.s3.amazonaws.com/0/163415/9434cd9c-ddb3-951b-709d-e63a8e476fc1.png)
- そしてtextbox\_\_text--blueはModifierになります。要は--区切りにすることでtextbox\_\_textの状態を表しています。今回の場合ですとtextbox\_\_textの青色ですよという感じです。

##まとめ
- .block
- .block\_\_element
- .block\_\_element--modifier

うまく伝えられているか不安ですがざっと説明いたしました。

##おまけ
- sassで書くととても便利！
- <img width="243" alt="スクリーンショット 2017-03-10 13.18.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/163415/5916ffbf-d34d-a253-bded-6e817d30578b.png">
- こんな感じで書けるのでとてもわかりやすい！！
railsで一からアプリケーションを作ろうとしたときにハマったことの記録

ハマったことを随時書いてきます。個人的なメモ


## 子要素のmodelが保存できない！
一つのフォームから複数のmodelにデータを送る機能を実装してた時にハマった。以下を参考にしながら実装
http://qiita.com/ftyabu/items/cae912b211e985d74d58

原因はこれでした
http://qiita.com/onelittlenightmusic/items/bfb20c481e6c4970f415
NetBSDのカーネルソースコード取得用スクリプト

[NetBSDカーネル開発・テスト環境を構築する](http://qiita.com/furandon_pig/items/98b5cf24e73376056974)の記事にもあるように、NetBSDカーネルソースコードをダウンロードする機会は多々あります。

NetBSDのソースコードは[http://ftp.jaist.ac.jp/pub/NetBSD/](http://ftp.jaist.ac.jp/pub/NetBSD/)から取得可能で、例えば[NetBSD-7.0.2](https://www.netbsd.org/releases/formal-7/NetBSD-7.0.2.html)のソースアーカイブのURLは以下になります。

 * [http://ftp.jaist.ac.jp/pub/NetBSD/NetBSD-7.0.2/source/sets/](http://ftp.jaist.ac.jp/pub/NetBSD/NetBSD-7.0.2/source/sets/)

しかし、その都度バージョンとURLを調べてファイルをダウンロードするのもなかなか面倒です。そこでNetBSDカーネルソースコードを取得する簡単なシェルスクリプトを作成してみました。

## NetBSDカーネルソースコードを取得するスクリプト

スクリプトは以下に置いてあります。が、現状では **NetBSD環境のみでの動作** となります...。

 * [furandon-pig/get_nbsd_kernsrc.sh](https://gist.github.com/furandon-pig/32f95165c990a8de1b4c2099b88cab66)

### スクリプトのセットアップ

```shell-session
$ curl -k -s -O https://gist.githubusercontent.com/furandon-pig/32f95165c990a8de1b4c2099b88cab66/raw/bda96f53587efa3e3b45571f62520e0f1adb15de/get_nbsd_kernsrc.sh
$ file get_nbsd_kernsrc.sh 
get_nbsd_kernsrc.sh: POSIX shell script, ASCII text executable
$ chmod +x get_nbsd_kernsrc.sh 
```

### 使ってみる

`get_nbsd_kernsrc.sh list`でダウンロード可能なNetBSDソースコードの一覧が表示されます。


```shell-session
$ ./get_nbsd_kernsrc.sh list 
 Available NetBSD source archive.
  * NetBSD-6.0.1
...
  * NetBSD-6.1
  * NetBSD-7.0.1
  * NetBSD-7.0.2
  * NetBSD-7.0
...
```

`get_nbsd_kernsrc.sh download <version>`でソースアーカイブをダウンロードします。
以下の例では`NetBSD-7.0.2`のソースアーカイブをダウンロードしています。

```shell-session
$ ./get_nbsd_kernsrc.sh download NetBSD-7.0.2
 [1/6]download MD5
 [2/6]download SHA512
 [3/6]download sharesrc.tgz
 [4/6]download syssrc.tgz
...
```

`get_nbsd_kernsrc.sh checksum`でファイルのチェックサム(SHA-512)を確認できます。

```shell-session
$ ./get_nbsd_kernsrc.sh checksum
 [ OK ] gnusrc.tgz
 [ OK ] sharesrc.tgz
 [ OK ] src.tgz
 [ OK ] syssrc.tgz
```

あとは[ツールチェインの構築](http://qiita.com/furandon_pig/items/98b5cf24e73376056974#%E3%83%84%E3%83%BC%E3%83%AB%E3%83%81%E3%82%A7%E3%82%A4%E3%83%B3%E3%81%AE%E6%A7%8B%E7%AF%89)→[カーネルのビルド](http://qiita.com/furandon_pig/items/98b5cf24e73376056974#%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89)でカーネル開発環境まで準備できます。

## まとめ

毎回カーネルソースコードのファイルをちまちまとダウンロードしていたのですが、スクリプトの作成によりだいぶ楽になりました(もっと早くにこうしておけば良かった気もします)。
Linuxでも頻繁にカーネルソースコードを取得したりするので、こちらも同様のスクリプトを作成しておきたいところです。
Ansibleでよく使いそうなモジュール

#Ansibleでよく使いそうなモジュール

##yum
**yumパッケージのインストール、アンイストールを実行**

よく使いそうなパラメータ
`name,state`

|パラメータ|選択肢|内容|
|:---|:---|:---|
|*name(必須)*| |サービス名の指定|
|state|present<br> installed<br> latest<br> removed<br>|present or installed:インストール<br> latest:アップデート<br>removed:削除<br>|

```example.yml
#Apacheのインストール
- yum:
   name=httpd
   state=installed

#Apacheのアンインストール
- yum:
   name=httpd
   state=absent
```
詳しくは
[yumドキュメント](http://docs.ansible.com/ansible/yum_module.html)

##service
**サービスの起動、停止、再起動を行う。OS起動時の設定を行う**
よく使いそうなパラメータ
`name,state,enabled`

| パラメータ | 選択肢 | 内容 |
|:---|:---|:---|
|*name(必須)*||サービス名の指定|
|state|started<br>stopped<br>restarted|started:既にstartしていれば実行しない<br>stopped:既にstopしていれば実行しない<br>restarted:必ず実行する|
|enable|yes<br>no|yes:OS起動時自動実行させる<br>no:OS起動時自動実行させない|

```example.yml
#Apacheのインストール
- service:
   name=httpd
   state=started
   enabele=yes
```

詳しくは
[serviceドキュメント](http://docs.ansible.com/ansible/service_module.html)

##command
**コマンドの実行**
よく使いそうなパラメータ
`実行コマンド,chdir,creates`

| パラメータ | 選択肢 | 内容 |
|:---|:---|:---|
|*実行コマンド(必須)*| | |
|chdir| |コマンド実行前に指定ディレクトリに移動|
|creates| | ディレクトリの作成。既に存在する場合はスキップされる|

パイプやリデイレクトが使えないためshellを使うことの方が多そうです(あまり推奨されていませんが)
詳しくは
[commandドキュメント](http://docs.ansible.com/ansible/command_module.html)

##shell
**shellの実行**
よく使いそうなパラメータ
`実行コマンド,chdir,creates`

| パラメータ | 選択肢 | 内容 |
|:---|:---|:---|
|*実行コマンド(必須)*| | |
|chdir| |コマンド実行前に指定ディレクトリに移動|
|creates| | ディレクトリの作成。既に存在する場合はスキップされる|

```example.yml
- shell: somescript.sh >> somelog.txt
  args:
    chdir: somedir/
```

somedirに移動してsomescript.shを実行した内容をsomelog.txtに出力
詳しくは
[shellドキュメント](http://docs.ansible.com/ansible/shell_module.html)

##copy
**ファイルやディレクトリのコピー**
よく使いそうなパラメータ
`src,dest`

| パラメータ  | 選択肢 | 内容 |
|:---|:---|:---|
|src　　　　| |サーバ上にコピーするファイルのローカルパスを指定|
|*dest(必須)*| |配布先のパスを絶対パスで指定。srcがディレクトリならdestもディレクトリである必要あり|

```example.yml
- copy: 
    src=/srv/myfiles/foo.conf dest=/etc/foo.conf
```

詳しくは
[copyドキュメント](http://docs.ansible.com/ansible/copy_module.html)

##template
**ファイルのコピーが行える(IPアドレスで変数展開するような場合に使用することが多い)**
よく使いそうなパラメータ
`src,dest`

| パラメータ  | 選択肢 | 内容 |
|:---|:---|:---|
|src　　　　| |サーバ上にコピーするファイルのローカルパスを指定|
|*dest(必須)*| |配布先のパスを絶対パスで指定|

IPアドレスなどで変数展開するようなファイルはcopyではなくtemplateを使います
詳しくは
[templateドキュメント](http://docs.ansible.com/ansible/template_module.html)

##file
**ファイル、ディレクトリ、リンクの作成、削除**
よく使いそうなパラメータ
`path,state`

| パラメータ  | 選択肢 | 内容 |
|:---|:---|:---|
|path(必須)| |対象のファイル、ディレクトリを指定(dest,nameでも可)          |
|state|file<br>link<br>directory<br>hard<br>touch<br>absent<br>|file:ファイルの指定<br>link:シンボリックリンクの指定<br>directory:ディレクトリの指定<br>hard:ハードリンクの指定<br>touch:指定したファイルがなければ作成<br>absent:指定したファイル、ディレクトリ、リンクの削除<br>|

詳しくは
[fileドキュメント](http://docs.ansible.com/ansible/file_module.html)
GitHub入門 ~利用編~


前回の「GitHub入門 ~登録編~」でアカウントの登録が完了したので実際に利用していきましょう。
今回のサンプルを利用しながら「GitHub」と「git」について少しずつ理解を深めていきます。

##ステップ1

まず自分のGitHubページにアクセスします。

左上にあるGitHubのアイコンをクリックします。

後で画像を指す

クリックすると下記のページに移動します。

![スクリーンショット 2017-02-26 13.50.27.png](https://qiita-image-store.s3.amazonaws.com/0/95873/73d3c0d3-de0e-1939-c251-abdb7adc377f.png "スクリーンショット 2017-02-26 13.50.27.png")

上記ページに移動したら、「Start a project」をクリックして実際にプロジェクトを作成していきます。
クリックすると下記のページに移動します。

![スクリーンショット 2017-02-26 13.55.54.png](https://qiita-image-store.s3.amazonaws.com/0/95873/a5b53a85-51e6-7fcb-0a8c-21141990c404.png "スクリーンショット 2017-02-26 13.55.54.png")

ここで「リポジトリ」と呼ばれるものを作成します。
このリポジトリは基本的にプロジェクトごとに作成していきます。

では実際にリポジトリを作成していきましょう。

リポジトリの登録に必要な最低限の項目は下記です。

- Repository name
- Public / Private

「Repository name」では作成するリポジトリの名前を決めます。

「Public / Private」の選択項目では作成するリポジトリをインターネットに公開するかどうかを選択します。
※GitHubの場合、無料版で利用している場合は「Private(非公開)」にはできません。

「Repository name」を入力して「Public」を選択すると下記のような状態になります。

![スクリーンショット 2017-02-26 14.02.04.png](https://qiita-image-store.s3.amazonaws.com/0/95873/28f316b1-1b75-8137-7ac4-4bedfd63ab69.png "スクリーンショット 2017-02-26 14.02.04.png")

上記の状態になったら、「Create repository」をクリックしてリポジトリを作成します。

「Create repository」をクリックすると下記のページに移動します。

![スクリーンショット 2017-02-26 14.04.51.png](https://qiita-image-store.s3.amazonaws.com/0/95873/35e1ed50-163c-6c33-115c-6d7b8e0b8b1a.png "スクリーンショット 2017-02-26 14.04.51.png")

ここには、GitHub上に作成したリポジトリを利用するための簡単な説明が書かれています。
今回は新規プロジェクトを作成していくので「…or create a new repository on the command line」の項目を参照します。

![スクリーンショット 2017-02-26 14.09.30.png](https://qiita-image-store.s3.amazonaws.com/0/95873/dcff7b4e-a410-dde8-f432-e572e4a6762f.png "スクリーンショット 2017-02-26 14.09.30.png")

ではここかからはご自身のPCで作業をしていきます。
まずはターミナルを開いて先ほど作成したリポジトリに登録するプロジェクトを作成しましょう。

※ターミナルに関して下記の記事を参照してください。

```
// リポジトリに登録するプロジェクトのディレクトリを作成
$ mkdir zerofurotest // mkdirコマンドの後にプロジェクト名を入れます

// 作成したディレクトリに移動します。
$ cd zerofurotest
```

これで、GitHubのリポジトリに登録するプロジェクトの準備は完了です。
ここから、GitHubのチュートリアルに従っていきます。

```
$ touch READEME.md
$ echo "# zerofurotest" >> README.md
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git remote add origin git@github.com:y-sekitoba/zerofurotest.git
$ git push -u origin master
```

今回は上記を一行ずつ先ほど作成したディレクトリの中で実行していきましょう。
※今回はコマンドの説明は一旦飛ばします。

先ほどのページが下記のようになります。

![スクリーンショット 2017-02-26 14.50.16.png](https://qiita-image-store.s3.amazonaws.com/0/95873/e99b3f16-103c-6fdc-06c7-311ea59424ed.png "スクリーンショット 2017-02-26 14.50.16.png")

これでGitHubのリポジトリと自分のPCに作成したプロジェクトを連携することができました。
ここからは実際にGitHubを利用してプロジェクトを管理していくことがきます。

![スクリーンショット 2017-02-26 14.53.42.png](https://qiita-image-store.s3.amazonaws.com/0/95873/f4ada8b8-e8ca-3e98-66cf-6a34bc1b768e.png "スクリーンショット 2017-02-26 14.53.42.png")


![スクリーンショット 2017-02-26 14.54.10.png](https://qiita-image-store.s3.amazonaws.com/0/95873/2be34544-6356-a2fa-7d0e-2d2b8a5b0744.png "スクリーンショット 2017-02-26 14.54.10.png")



ただ、実際にはgitコマンドと言うものを覚えないと利用できないので次回を最低限必要なgitコマンドを学んでいきましょう。



##こちらもどうぞ
[新人の指導者 or 新人の方へ](http://qiita.com/y_sekitoba/private/89e421c5e2b28dfe5dfb)
AWS SDK for JavascriptからPollyを呼び出してしゃべらせる

# 背景
AWSSDKforJavascriptのPollyサンプルに、入力した文字列をそのまましゃべらせる方法が書いていなかったのでメモ。

```
<!DOCTYPE html>
<html>
<head>
  <title>AWS SDK for JavaScript in the Browser</title>
  <script src="aws-sdk.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  <script>
  //クライアントにキーが丸見えになるので非推奨
  AWS.config.update({accessKeyId: '###', secretAccessKey: '###', region: 'us-west-2'});
  //Pollyテスト
  /* This operation detects faces in an image stored in an AWS S3 bucket. */
  var params = {
    OutputFormat: "mp3",
    SampleRate: "8000",
    Text: "Amazonから最新情報です。Kindleの電子書籍読み上げサービス「Kindle Speach」がリリースしました。無料のコンテンツをお試しできますが、いかがでしょうか？",
    TextType: "text",
    VoiceId: "Mizuki"
  };
  var polly = new AWS.Polly();
  polly.synthesizeSpeech(params, function(err, data) {
    if (err) console.log(err, err.stack); // an error occurred
    else     console.log(data);           // successful response
    var elementId = "audioElement" + new Date().valueOf().toString();
    var audioElement = document.createElement('audio');
    audioElement.setAttribute("id", elementId);
    document.body.appendChild(audioElement);
    var uInt8Array = new Uint8Array(data.AudioStream);
    var arrayBuffer = uInt8Array.buffer;
    var blob = new Blob([arrayBuffer]);
    var url = URL.createObjectURL(blob);
    audioElement.src = url;
    audioElement.play();
  });
  </script>


</head>
<body>
  <div id="keys"/>
</body>
</html>
```
【js】連想配列では.lengthを使えない

var scores = {Taro: 72, Ken: 93, Tom: 85, John: 68};

// この下にコードを書いてください
var sum = 0;
var cnt = 0;

for(var k in scores){
  console.log(k+'さんは'+scores[k]+'点です');  
  sum += scores[k];
  cnt++;
}
var ave = sum/cnt;
console.log('平均点は'+ave+'点です。');
初めてのbranchからmasterへマージ - GitHub Desktopで

# GitHub Desktop ベースでブランチをmasterへマージする方法。

※Githubの「マージ」操作をコマンドラインなどで既に経験済みの人には、おそらく不要な情報（操作としては同じ）です。**「マージ」操作が初めてで、且つGUIからやる**人向けです。

以前に、[初めてのbranch](http://qiita.com/xingyanhuan/items/6f852810bdd284b74ed1)で GitHub Desktop からbranchを作成したヤツを、マージする方法について。いざマージしようと思ったら「あれ？どうやってやるんだろう？GitHub Desktopからは、もしかして出来ない？」ってなった。結論から言うと、**GUIのみで以下の流れで出来る**。ただし、GitHub Desktopで完結せずにWeb上のGitHubでの操作が必要になる。



# 具体的な操作手順

操作の流れは以下。

1. GitHub Desktop で「Pull request」する。
1. GitHub のWebサイトにログインして、「Marge pull request」する。
1. GitHub Desktop で「Sync」する。


## GitHub Desktop からGUIで「Pull request」する

先ずは、ローカルリポジトリ上での操作。

1. GitHub Desktopの右上にある「Pull request」をクリックして、内容入力後に「Send pull request」を押す。
![スクリーンショット 2017-02-25 16.18.57.png](https://qiita-image-store.s3.amazonaws.com/0/125588/3e9eef90-1cd5-5e41-6ed5-69333b1e112b.png)
1. 「Pull request created」と出たら、次はGitHub のWebサイトへ移動する。
![スクリーンショット 2017-02-25 16.22.10.png](https://qiita-image-store.s3.amazonaws.com/0/125588/7aaf7208-b840-65fd-7305-3d6239b0b03e.png)



## GitHub のWebサイト上で、「Marge pull request」する

続いて、リモートリポジトリ上での操作。

※この作業は、通常はmasterの管理者が作業をする。今回の場合は、branch の作成者とmasterの管理者**ともに自分自身**なので、「Pullしたrequestを、自分でマージする（コミットする）」という作業になる。

1. GitHub のWebサイトにログインする。
![スクリーンショット 2017-02-25 16.24.44.png](https://qiita-image-store.s3.amazonaws.com/0/125588/93b86103-5b02-f90a-b216-bd4ecbf0984e.png)

1. 「Pull request」のタブに、先ほどPullしたリクエストが来ているので、クリックする。
![スクリーンショット 2017-02-25 16.26.10.png](https://qiita-image-store.s3.amazonaws.com/0/125588/0965e066-1f82-b4a9-b5b8-0aa30da6d9b8.png)

1. 「Marge pull request」ボタンを押すと確認画面が出るので、コメントを入力して「Confirm marge」を押す。
![スクリーンショット 2017-02-25 16.26.29.png](https://qiita-image-store.s3.amazonaws.com/0/125588/f3778f93-8475-fb47-0a5b-46696fd680ce.png)

1. 「Pull request successfully marged」と表示されれば、マージ完了。
![スクリーンショット 2017-02-25 16.26.46.png](https://qiita-image-store.s3.amazonaws.com/0/125588/ca9a45e1-04ea-5181-3c6e-439528050b84.png)



## GitHub のリモートリポジトリのマージ結果を、ローカルリポジトリへ反映する

最後に再び、ローカルリポジトリ上での操作。

1. 上述の、リモートリポジトリでのmarge作業を終えたら、GitHub Desktopのmaster上で「Sync」を押して、変更をローカル側に取り込む。
![スクリーンショット 2017-02-25 16.27.27.png](https://qiita-image-store.s3.amazonaws.com/0/125588/c48f4d25-c9ab-9d2b-d3ac-0701e90c4500.png)


# 補足：不要になったbranchをGitHubのWeb上から操作して消す方法

こちらのページの後半に、Web上から操作してリモートブランチを削除する方法が載っていたので、メモ（前半は、コマンドラインでの操作方法）。
http://qiita.com/kwgch/items/98bbaae8e9f40a9548e0



以上ー。
【js】配列の中の数字の平均値と最大値

var scores = [72, 93, 85, 68];
console.log('scores: ' + scores);

// この下にコードを書いてください
var ave = function(arr){
  var sum = 0;
  for (var i = 0; i < arr.length; i++) {
    sum +=arr[i];
  }
  return sum/arr.length;
}

console.log('平均点は'+ave(scores)+'点です。');

var max = function(arr){
  var maxval = 0;
  for (var j = 0; j < arr.length; j++) {
    if (maxval < arr[j]) {
      maxval = arr[j];
    }
  }
  return maxval;
}
console.log('最高点は'+max(scores)+'点です');
NSArrayからCGRectとか(CGGeometryとUIGeometry)

[swift移植版はこっち](http://qiita.com/sakiyamaK/items/ed20c41f717d9e7c3c45)

#サンプル

こういうことができるようになります

```objc
  NSArray *a = @[@(1),@(2),@(3), @(4)];

  CGPoint point = a.CGPoint; // = (CGPoint){1,2}
  CGVector vector = a.CGVector // = (CGVector){1,2}
  CGSize size = a.CGSize; // = (CGSize){1,2}
  CGRect rect = a.CGRect; // = (CGRect){1,2,3,4}
  CGAffineTransform Transform = a.CGAffineTransform // = (CGAffineTransform){1, 2, 3, 4, 0, 0}; <- 配列数が足りない部分は0になる

  UIEdgeInsets edge =  a.UIEdgeInsets // = (UIEdgeInsets){1,2,3,4};
  UIOffset offset = a.UIOffset // = (UIOffset){1, 2};
```

色々座標を計算し終わったあとにCGPointMakeとか(CGPoint)とかしなくていいのでちょっとだけ楽です

#ソース

##ヘッダ

```objc:NSArray+Geometry.h
#import <Foundation/Foundation.h>

@interface NSArray (Geometry)
-(CGPoint)CGPoint;
-(CGVector)CGVector;
-(CGSize)CGSize;
-(CGRect)CGRect;
-(CGAffineTransform)CGAffineTransform;
-(UIEdgeInsets)UIEdgeInsets;
-(UIOffset)UIOffset;
@end
```

##実装

```objc:NSArray+Geometry.m
#import "NSArray+Geometry.h"

@implementation NSArray (Geometry)

-(CGPoint)CGPoint{
  CGFloat x = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat y = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  return (CGPoint){x,y};
}

-(CGVector)CGVector{
  CGFloat x = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat y = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  return (CGVector){x,y};
}


-(CGSize)CGSize{
  CGFloat w = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat h = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  return (CGSize){w,h};
}

-(CGRect)CGRect{
  CGFloat x = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat y = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  CGFloat w = self[2] ? ((NSNumber*)self[2]).floatValue : 0;
  CGFloat h = self[3] ? ((NSNumber*)self[3]).floatValue : 0;
  return (CGRect){x, y , w, h};
}

-(CGAffineTransform)CGAffineTransform{
  CGFloat a = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat b = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  CGFloat c = self[2] ? ((NSNumber*)self[2]).floatValue : 0;
  CGFloat d = self[3] ? ((NSNumber*)self[3]).floatValue : 0;
  CGFloat dx = self[4] ? ((NSNumber*)self[4]).floatValue : 0;
  CGFloat dy = self[5] ? ((NSNumber*)self[5]).floatValue : 0;
  return (CGAffineTransform){a, b, c, d, dx, dy};

}

-(UIEdgeInsets)UIEdgeInsets{
  CGFloat top = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat left = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  CGFloat bottom = self[2] ? ((NSNumber*)self[2]).floatValue : 0;
  CGFloat right = self[3] ? ((NSNumber*)self[3]).floatValue : 0;
  return (UIEdgeInsets){top, left, bottom, right};
}

-(UIOffset)UIOffset{
  CGFloat horizontal = self[0] ? ((NSNumber*)self[0]).floatValue : 0;
  CGFloat vertical = self[1] ? ((NSNumber*)self[1]).floatValue : 0;
  return (UIOffset){horizontal, vertical};
}
@end
```

#おわり
すっごいくだらない気もするがちょくちょく使うから置いときました
[vim]denite.nvim でGistを見る

# denite.nvim で Gist を見る

最近コードのsnippetをGistに保存してたんですが、いざ探す時に面倒だったので、 [denite.nvim](https://github.com/Shougo/denite.nvim) で一覧を出して選択したgistのページを開くpluginを作ってみました。

## vim-denite-gists

[vim-denite-gists](https://github.com/pocari/vim-denite-gists) 

Gistのリストは単純にGistのAPIを呼んで取得しているだけで、選択したものをブラウザで開く部分も [open-browser.vim](https://github.com/tyru/open-browser.vim)を呼んでるだけなのでたいしたことはしてないですが、この辺をくっつけるのを `Denit` のインターフェースにするのが簡単に書けて良いですね。

作ってから知ったんですが、[unite.vim](https://github.com/Shougo/unite.vim)に[unite-gist](https://github.com/mattn/unite-gist)というのが既にあるようでして、 `Denite`から`Unite`のソースを呼ぶ `Denite unite:xxx`で呼んで動くならそれでいい気もしましたが、試してみるとなぜかエラーになったので、まぁ、こっちがあってもいいかと思って記事にしました。

[unite-gist](https://github.com/mattn/unite-gist)の方はもっと高機能で、プライベートな`gist`とかも見れるようです。

![vim-denite-gists-screenshot.gif](https://qiita-image-store.s3.amazonaws.com/0/34692/ce0c47de-3c72-c03c-1935-855259096c33.gif)

## インストール

`denite.nvim` は既にインストールされているとして、
依存ライブラリも含めて `dein.vim` だと

```
call dein#add('tyru/open-browser.vim')
call dein#add('pocari/vim-denite-gists')
```

で入ります。その他のプラグインマネージャーを使っている場合は適宜合わせてください。

## 使用方法

### 起動方法
`:Denite gists:(github username)`

で、(github username)のユーザのpublicなgistの一覧がDeniteの候補として表示されます。

また、 `gitconfig`に

```ini
[github]
	user = xxx
```

を追加しておくと、
`:Denite gists`
と引数のユーザ名無しでgistを取得できます。（`unite-gist`からそのまま借りた)
 
### アクション

アクションのデフォルトは選択したものを`open-browser.vim`で開く、です。
複数候補の選択も対応しているので、複数選択して`Enter`するとブラウザのタブがいっぱい開きます。



・・・ところで、自分の（少ない)gistを見るのにしか使ってないので、もし大量にgistを持ってる人とかが開いたらどうなるのかはまだ良くわからないので、もし使ってみて問題があったら教えてもらえると幸いです。
文字列からpandasのDataframeを作る。

#　きっかけ
文字列をpandasのDataframeに変換する時に困ったのでメモ。きっかけは、300GBほどのファイルをpandasで扱いたかったという場面の話。直接read_csv()では無理そうなので、細かくopen()とかreadline()とかで切り取るところまでは良かったけど、そういえば文字列からDataframe作ったのは初めて。調べてもあまりいいのが出てこなかった。

#　解決策
numpyのreshape()つかってみた。

```python
pd.DataFrame(np.array(data.split()).reshape(-1,7))
```


イメージはこんな感じ。


<img width="1120" alt="screenshot.png" src="https://qiita-image-store.s3.amazonaws.com/0/126050/3f768908-4104-6900-a5bc-a9e5f2fb045e.png">


columnの数が決まっていたのが幸い。行数が決まっていないときはreshape()の引数に-1を入れると良いらしい。列数でも然り。他に良い方法があれば教えてください。
Worqueを使ってSlack上で非同期にDailyStandupMeetingする

## はじめに

リモートワークが増えて、お互いが何をやっているかを把握するために、Slack上で進捗報告を行う機会が多くなってきました。


でもSlack上で整形した長文を投稿するなんて面倒ですよね。。

その問題を解決すべく、対話型で進捗報告を簡単にできるSlackBotが公開されているようです。[Geekbot](https://geekbot.io), [Jell](https://jell.com), [Tatsu](https://tatsu.io) などがその一部です。

Geekbotを使った事例としてはSORACOMさんの記事が分かりやすいです。
https://blog.soracom.jp/blog/2016/06/28/about-team/

ですが、本記事ではBotとは違ったアプローチを使って、Slack上での非同期コミュニケーションの簡易化を図る努力をしていきます。Botは有料なものが多いので、無料で自分流にカスタムできる感じにやっていければなと。


## Worqueとは

https://github.com/qcam/worque

有志が公開しているCLIです。コマンドで日々のメモなどを記録していくことができます。詳しくはGithubのREADMEをご覧ください。

僕の`.bash_profile`には下記でコマンドを登録しています。

```
# worque
today () { subl $(worque todo); }
ytd () { subl $(worque todo --for yesterday); }
alias push-today="worque push --channel standsup"
alias push-ytd="worque push --channel standsup --for yesterday"
```

```today``` と打つと日付がファイル名になってSublimeTextが起動します。
```push-today```と打つと今日のメモが特定のSlackチャンネルに投下されます。


＊ sublコマンドについてはこちらをご覧ください。
https://www.sublimetext.com/docs/3/osx_command_line.html


READMEにも記載がありますがWorqueでSlackに投下するためにはTokenを取得する必要があります。

https://api.slack.com/web から取得して`.worquerc`に書いておきましょう。

```
$ vim ~/.worquerc 

{
  "path": "メモを保存する場所のパス",
  "token": "取得したSlackのトークン"
}
```

## SublimeSnippetを登録してさらに便利にしてみる

Sublimeには自分のSnippetを登録できる機能があります。`standup`と入力したら定型文が表示されるようにすると更に便利になりそうな予感がします。

<img width="900" alt="スクリーンショット 2017-02-26 12.07.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/73483/70c0aacb-d1e8-4ddf-0b07-d1b7fe008494.png">

`New Snippet` を選択して下にある内容で保存します。

ファイル名は `standup.sublime-snippet` としておきましょう。 `.sublime-snippet`という拡張子で保存しないと認識されないので注意です。

```
<snippet>
  <content><![CDATA[
# 昨日やったこと


# 今日やること


# 作業する上での懸念


# ひとこと


]]></content>
  <tabTrigger>standup</tabTrigger>
</snippet>
```


## 実行してみる


```
$ today
```

<img width="1436" alt="スクリーンショット 2017-02-26 12.15.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/73483/cbe3fcc2-d93f-5e88-fc1e-821e9110742b.png">


```
standup と入力して TABキーを押す
```

<img width="1429" alt="スクリーンショット 2017-02-26 12.15.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/73483/bdc72d40-b18f-af2d-0e56-0421b49cb3db.png">

<img width="1431" alt="スクリーンショット 2017-02-26 12.16.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/73483/0302548c-c2a6-9128-f110-84448800cb14.png">

```
ごにょごにょ書いて

$ push-today
```

以上で終了です。まぁまぁ簡単になったのではないでしょうか。Worqueならファイルをローカルに保存しておけるので見返すのも楽です。`cron` と連携して定時になったら自動投稿する、Slack上でリマインドを設定しておくなどの工夫もすると更に良さそうです。
CNNおさらい

#画像が比較したい！
例えば，次の画像があったとします．
![cross.png](https://qiita-image-store.s3.amazonaws.com/0/28622/7701901a-a37b-8172-f4e2-62ede6147a4b.png)
ピクセルでバツを表現しています．
バツですね．

では，次の画像はどうでしょうか？

![cross_2.png](https://qiita-image-store.s3.amazonaws.com/0/28622/4043d4c8-7684-65e8-36bb-c5de2671c71f.png)

バツと言えないこともありません．まあバツです．では，これをコンピュータにわかってもらうためにはどうしたらいいのでしょうか？

そこで，畳み込みニューラルネットワークの出番です．

#畳み込み演算とは？
ニューラルネットワークの特徴は，人間が指定しなくとも特徴を見つけてくれることです．では，その特徴をどのように使って画像同士を比較したらよいのでしょうか？

例えばバツは次の特徴を持っています．

![cross_4.png](https://qiita-image-store.s3.amazonaws.com/0/28622/b23f6461-c430-0f85-166e-3f4bdba8e0b7.png)

ここで，このピクセルは白か黒なので，白を-1，黒を1とします．するとバツの画像は
![cross_5.png](https://qiita-image-store.s3.amazonaws.com/0/28622/36ad4f6a-787a-4951-3d17-4360080a115a.png)


特徴は
![cross_6.png](https://qiita-image-store.s3.amazonaws.com/0/28622/524a408c-d579-d78a-8c59-d0ed2e000d92.png)


と，表現することができます．

ここで，
![cross_4.png](https://qiita-image-store.s3.amazonaws.com/0/28622/ea0f9e17-57e6-6033-74bc-7fb734328e25.png)
この部分を比較計算してみます．
対応するセル同士を計算します．
つまり，
合致すれば
1(黒) × 1（黒） = 1
1(白) × 1（白） = 1
1になり，
合致しなければ
-1（白） × 1（黒） = -1
1(黒) × -1（白） = -1
-1になります．

計算した結果を表現すると，
![cross_8.png](https://qiita-image-store.s3.amazonaws.com/0/28622/cf995353-9b46-b818-98df-d4fa9be9ffa6.png)

最終的にそれぞれのセルの値を足したものをピクセルで割ります．つまり，合致すればするほど値が1に近づきます．
この場合，完全合致なので1です．
この一連の演算を「畳み込み演算」といいます．

今回の場合，画像のセルが9×9マス，特徴が4×4マスなので，パーツを1マスずつずらしくいくと，その計算結果は6×6マスになります．（計算結果はでたらめなので信用しないでください）
![cross_10.png](https://qiita-image-store.s3.amazonaws.com/0/28622/0492e025-6914-854a-1cc3-10a6daf3b7e0.png)


こうして得られたものを特徴マップといいます．

こうして画像がどれだけ特徴をもっているのかを数値的に測ることができます．
この演算自体はとても単純なものです．しかし，これが9×9の荒い画質ではなく，標準的な画質の画像となったとき，その計算量は膨大なものになります．GPUを使わないと学習にかかる時間が大変なことになるのはこのためです．

#おわりに
今回は畳み込みとはどういったことか書きました．
まだ私も理解が浅いため，間違ったことを書いていたらご指摘ください．

#参考
山下隆義
イラストでわかるディープラーニング 講談社

斎藤康毅
ゼロから作るDeep Learning

畳み込みニューラルネットワークの仕組み
http://postd.cc/how-do-convolutional-neural-networks-work/
深層学習とは（確認用）

#深層学習とは
深層学習とは機械学習の手法のひとつであり、入力されたデータをもとにクラス分類や回帰を行う手法です。
ではそもそも機械学習とは何か？
機械学習自体は


>人工知能における研究課題の一つで、人間が自然に行っている学習能力と同様の機能をコンピュータで実現しようとする技術・手法のこと（Wikipediaより引用）

とWikipediaでは定義されております。
人間が行っている「学習」というものを再現すべく、いろいろな手法が試されており、その中でも近年、極めて高い成果を上げて注目を集めている手法が「深層学習」というわけです。

#従来の機械学習との比較
では、何がほかの手法と異なるのか？
簡潔にまとめると、**どのような特徴を捉えれば高い性能を出すことができるのか自動的に獲得できる**というところです。

例えば、従来の手法だと画像を分類する際、画像の特徴はどこなのか、どこに着目すればよいのかを人が設計する必要がありました。
それに対して深層学習の場合は学習データを放り込めば自動的にデータのどこを特徴点としてとらえるべきかマシン側が勝手に決めてくれます。これが深層学習と従来の手法との処理の違いです。

#深層学習という概念
深層学習という言葉自体は概念で、一般的には深い層から構成されるネットワークを指します。
大きく分けると、深層学習は「パーセプトロン」を起源とするものと「ボルツマンマシン」を起源とするものの二つに分かれます。

パーセプトロンを起源とするもので、最も基本的な構成はパーセプトロンを多層に組み合わせた多層パーセプトロンです。その派生で、人の視覚野のような構成を取り入れた「畳み込みニューラルネットワーク（CNN）」が有名かと思います。こちらは学習データに正解となるラベルをセットにして学習させる教師あり学習です。

一方、ボルツマンマシンの方は、製薬ボルツマンマシンを多層にしたディープ・ボルツマンマシン、ディープ・ビリーフ・ネットワークです。こちらは正解を教えずに学習させる教師なし学習です。

今回はここまで。

#参考文献
山下隆義
イラストでわかるディープラーニング 講談社

新納浩幸
Chainerによる実践深層学習～複雑なNNの実装方法～　オーム社
誤差逆伝播法

自分用メモ
#誤差逆伝播法
得られた出力結果から、教師データとの誤差を算出して、パラメータとしての重みを調整し、調整された値を元にまた後ろのノードへと更新を伝えていきます。

![誤差逆伝播法.png](https://qiita-image-store.s3.amazonaws.com/0/28622/57fa5158-4d14-b27c-d6d6-ca7c12b58c9a.png)

では、具体的にはどのようにして更新していくのでしょうか？

#勾配降下法
重みを調整する方法の一つとして、**勾配降下法**があります。

これは、誤差が誤差関数を利用して算出されることを利用します。この誤差関数は
-出力と教師データとの差が大きければ大きいほど返り値が大きくなるもの
-微分可能であるものであることが
であることが求められます。

例えば、誤差関数をグラフにすると以下の図になるとします。

![勾配降下法.png](https://qiita-image-store.s3.amazonaws.com/0/28622/e76af992-3949-490f-ef35-4ad4642dadcf.png)

誤差は重みwによって決まります。
ここで、微分可能であるということは、最小値を求めることができます。そこが最適なwであるwoptです。
なお、傾き0なのが最小値であることを保証するために下に凸になるよう誤差関数を選ぶ必要があるようです。（このあたりはまだ不安）

更新量Δwは、以下の式で求められます。

```math
Δw = -η\frac{δE}{δw}

```

誤差が大きいほど傾きは大きくなるため、傾きだけ誤差を更新させます。マイナスをとるのは傾きが正であればwを減少、負であれば増加させるためです。
ηは学習係数で、さすがに傾きをそのまま使ってもうまくwoptを求めることはできないため、誤差を元にどの程度更新するかを決める値です。

この学習係数も精度向上のためにうまく設定する必要があります。

#参考
山下隆義
イラストでわかるディープラーニング 講談社
新納浩幸
Chainerによる実践深層学習～複雑なNNの実装方法～　オーム社

高卒でもわかる機械学習 (2) 単純パーセプトロン
http://hokuts.com/2015/11/25/ml2_perceptron/
Chainerで始めるニューラルネットワーク
http://qiita.com/icoxfog417/items/96ecaff323434c8d677b
CentOS7 VNC Server設定のメモ

CentOS7でVNC Serverを設定した際のメモです。
以下のアカウントで設定することを前提に進めていきます。

- アカウント名 : admin

#インストール

rootでログインし、tigervnc-serverをインストールします。

```
yum install tigervnc-server
```

#VNCサーバの設定

1番をadminに割り当てます。まず、1番用の設定ファイル「vncserver@:1.service」を作成します。

```
cp /usr/lib/systemd/system/vncserver@.service /usr/lib/systemd/system/vncserver@:1.service
```

次に、「vncserver@:1.service」を編集します。「<USER>」をアカウント名に書き換えます。

``` /usr/lib/systemd/system/vncserver@:1.service
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
Type=forking
# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
ExecStart=/usr/sbin/runuser -l <USER> -c "/usr/bin/vncserver %i"
PIDFile=/home/<USER>/.vnc/%H%i.pid
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'

[Install]
WantedBy=multi-user.target
```

その後、サービスに登録します。

```
systemctl daemon-reload
```

#VNCユーザの設定

対象のユーザのアカウントでログインします。そして、環境設定用ファイルを作成します。

```
cd ~/.vnc/
vi xstartup #ファイル作成
chmod +x xstartup
```

内容を編集します。

``` ~/.vnc/xstartup
#! /bin/sh
exec gnome-session &

```

#パケットフィルタリングの設定

ひとまず、ローカル（192.168.1.*）から接続できるように設定します。

```
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 service name=vnc-server source address="192.168.1.0/24" accept'
```

#VNCサービスの起動と自動起動の設定

サービスの起動。

```
systemctl start vncserver@:1.service
```


自動起動の設定。

```
systemctl enable vncserver@:1.service
```


サービスの起動の確認。

```
systemctl is-active vncserver@:1.service
```


#注意メモ

- 本体の方で、対象のアカウントでGUIにログインしていると、VNCで繋いだときに、真っ暗になります。
Angular CLI と Github Pages で雑な個人ウェブ開発

# 背景
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">個人ウェブ開発、ユーザー管理とかしようとするとものすごい覚悟が必要だけどブラウザ上で完結するアプリなら雑にどんどん作れそうなので ng new したやつをどんどん ng github-pages:deploy して快感を得よう</p>&mdash; がーみー🦀 (@gaaamii) <a href="https://twitter.com/gaaamii/status/834945153634713600">2017年2月24日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

# 目論見（もくろみ）
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/gaaamii">@gaaamii</a> 消えていい前提の少量のデータを扱うウェブサイトを作るならlocalStorageで十分そうだし見せ方の工夫でなにかどうにかできそう</p>&mdash; がーみー🦀 (@gaaamii) <a href="https://twitter.com/gaaamii/status/834946153816834048">2017年2月24日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

# やり方

## アプリケーションを作る
```shell-session
npm install -g angular-cli
ng new myapp
```

## デプロイする
```shell-session
cd myapp
ng github-pages:deploy
```

## アクセスする
`http://[あなたのgithubアカウント名].github.io/myapp` にアクセスする

# 作成例
- https://gaaamii.github.io/kintai
- ソース: https://github.com/gaaamii/kintai

# 今後
cssをいちから自分で書くのもだるかったりするので良い感じのCSSフレームワークやほかいろいろ必要なライブラリを列挙したpackage.jsonを作っておいて、いつでもそれなりのウェブアプリっぽい何かを吐き出せるようにしたい。