OmniAICreator/Qiita-1.07M huggingface dataset:
slack推進のために周知したこと

* 金額／効果見積もりについてはとても緩かったので問題にならなかった。奇跡！
* 40〜100人くらいで利用
* 導入時に周知した使い方、発生した課題や解決案などについて共有した内容のメモ

## 規約
### アカウント規約
* usernameは自由
* firstname はアルファベットのみ
* lastname はアルファベット + " / " + 日本語氏名
  * 上記設定をすることでユーザ名が suzuki ichiro / 鈴木 一郎 みたいな表記になる

### 認証
* ２段階認証を設定すること
* ユーザ一覧で未設定者が洗い出せるので、定期通知

### channelについて
* 関係者外秘の業務内容はprivate channelにてやり取りすること
* generalでの雑談は禁止、業務連絡の周知とQAのみとする
  * QAについては、短時間ですまない場合別channelに誘導

## 推奨方針
* アイコンは意外と大事だからちゃんと設定してね
* 基本的に話題／チーム毎にchannelを切るため、適したchannelで発言してね（可能な範囲でね）
* channel作成は自由にやっちゃってね
  * 既存channelにあわない話題が続くようなら、新しく切って誘導しましょう
  * 被って乱立するようならchannelを統合、無効化すればOK
* 有料版の場合ログは消えないが、追うのは辛いので別途資料化しましょう
* 相手に過剰なレスポンスを求めないでね
  * 急ぎの場合は直接口頭で
  * 見てない可能性もあるので、無言 = OKとは取らないでね
* channel作る時はpurposeもなるべく書くようにしてください

## 周知事項
### 概要の周知
#### チームとは何か
* アカウントを所属させる枠、グループ
* 同チームに所属している場合、チームメンバと自由に連絡が取れる
  * skypeなどと違い、連絡先の交換は不要
* mutl teamに対応しているので、複数チームに所属していても特に不便なく使える

#### channelについて
* public channelはチームメンバ全員が参加可能
* private channelは招待メンバのみ閲覧可能、新規参加者は過去ログも参照可能
* 短期間のやり取りであれば、DMを使うことで直接のやり取りができる

#### アカウントについて
* 無料枠として有料ユーザ x 5のSingle channel guestが呼べる
* 有料だが、特定のchannelのみに参照権限をつける事ができるmulti channel guestもある
* mult guestは閲覧制限のためだけなので、制限が不要なら通常ユーザがいい

### 魅力ざっくり
* 必要な通知のみを受け取る設定がしやすいので、業務に集中できる
* 興味のある話題に自由に参加することができる
* プロジェクト支援のための様々なbotを開発可能

### ざっくり操作TIPS
#### メンション（宛先指定）
* @ + usernameでメンション可能
* username, lastname, firstnameを打つとサジェストされる
  * サジェストは、 ` `, `_` でsplitされた単語を前方一致検索してるっぽい
* 文中に入れる場合は、@の前に半角スペースが必要

#### channelについて
* CTRL+k or command+k でchannel検索ができる
  * 検索ルールは ` `, `_`, `-` 区切りに単語分割したものを前方一致検索するらしい
  * これを踏まえてchannel名をつけておくと検索しやすい
  * 未読channelがリストになって出るので、キーボードだけでchannelを終える
* CTRL+矢印 or command+[] で前見たchannelを辿ることができる

#### 通知設定
* channelごとにmute設定が可能
  * muteしてもmentionされた場合は通知がくる
* Snooze Notificationを設定することで、最大24hまで通知を無効化できる（mention含む)
* デフォルトでは22:00 - 8:00の間はSnooze状態になるため、適宜変更する

#### 未読メッセージの確認
* 以下で未読channelのみをサイドバーに出すことができる
  * `Advanced Options` -> `Channel List` -> `My unreads, along with everything I've starred`
  * muteとあわせると未読チェックが捗る
* 右上の ＠ を押すと自分宛てのメンションが一覧で読めるため、未読漏れを防げる
* starをつけることで、後からstarをつけたログを探すことができる
* PINをすることで、そのchannel内でログを読み返しやすくできる
  * 重要なタスク、TIPSなどにつけること
  * 多くなると埋もれるため、タスク消化や資料化できたタイミングで外すこと

#### よく使うmarkdown
* コードの挿入
  * 単語程度なら ` で囲む
  * 複数行なら ``` で囲む
* 引用
  * 単一行なら先頭に `> ` をつける
  * `>>>`より後の行は全て引用扱いにできる
* テキスト
  * `*`で囲むとbold
  * `_`で囲むとitalic

#### その他マナーやTIPS的なもの
* リアクションを押すことで無言で承諾などの意を伝えることができる
* メンションしたログは一覧表示できるので、挨拶だけでなく要件も併せて伝えると親切

## QA
* ユーザ名が見づらい
  * lastnameの規約を守らせることで日本語表記した
  * アイコンをなるべく設定して貰うようにした
* channel切り替えが面倒くさい
  * 解決できていない
  * この思想の影響か、同一channel内で話題が乱立したり、雑談にまぎれて発言を見逃すようになっている事がある
* channelが消せないんだけど
  * private channelは消せないっぽい
  * アーカイブすれば書き込みできなくなるので無用ならアーカイブしといてくださいと回答した
DynamoDBを利用する際に抑えるべきポイント

DynamoDBを利用する際に感じた抑えるべきポイントをまとめました。

# NoSQLを理解する
そもそもNoSQLを理解することが必要である。
なぜなら、「DynamoDBでいいんじゃない」って言う人ほどNoSQLを理解していないことが多いからです。
私も同じで、「スキーマーレスのデータベースなんでしょ？」って感じでした。

この考えでDynamoDBを採用してしまうとハマってしまう可能性が高くなります。

理由は、DynamoDBは、KVSだからなのです。
KVSにマッチした要件であれば問題ありませんが、スキーマレスだからいいんじゃないのなんてやってしまうと非常に大変なことになってしまいます。なっています。。。

# NoSQLとは
NoSQLとは、RDB（リレーショナル・データベース）以外のデータベースを指している様です。
KVS、DocumentDB、グラフDBなどが挙げられます。

# DynamoDBとは
KVS＋なんちゃってDocumentDBという感じでしょうか。
「なんちゃってDocumentDB」という表現をしているのは、ドキュメントを見るとQueryやScanとかがあっていろいろとできそうに思うのですが、実際にQueryやScanなどを行うとテーブルの全スキャンをしてしまうことになってしまうので、コスト的に大変な事になっていきます。ですので、実際QueryやScanなどは利用しない方がよいという事になってしまいます。

# DynamoDBの学習方法
KVSですので、KVSに関する学習を行うと効果的です。
特にテーブル設計などは、RDBに慣れ親しんでいると制限ばかりで大変になります。
RHEL7.1のswapを解放する方法

### freeコマンドでの出力は実メモリとスワップの出力がされる。
実メモリのfreeが余裕があるが、swap領域を使用している場合、以下のコマンドを実行する。

swapoff -a && swapoff -a 

### メモリ使用量を確認する方法

- topコマンドを実行し、出力を確認する。
- ps -aux --sort --rrsで出力を確認する。

topコマンドのサブコマンド
M：メモリ使用率順にプロセスを並べる。
P：CPU順にプロセスを並べる。
T：実行時間順にプロセスを並べる。

V:プロセスをツリー上に出力する。
1:CPUの使用率を全体ではなく、単体で出力する。
PostfixのメールをGMail経由で送る

# 注意

追記2020/9/11: この記事は古いです。

GMailアカウントでLSA(安全性の低いアプリ)の設定を行い、SMTP認証(PLAIN)を行うことを前提としています。

一般のGMailに関してはアナウンスがないようですが、G SuiteのGMail利用に関しては、G Suiteアップデートブログ、[安全性の低いアプリによる G Suite アカウントへの接続が無効に](https://gsuiteupdates-ja.googleblog.com/2019/12/g-suite_24.html) にあるように将来的には完全に利用できなくなります。

- GMailアカウント: LSA設定で可能(今後、G Suite同様に無効化されるのか？その場合いつになるかは不明)
- G Suiteアカウント: 2020/6/15以前にLSA設定したことがある場合は2021/2/16まで利用可能

# 目的

CentOSはデフォルトのMTAとしてPostfixを採用している。
minimal構成でインストールしてもPostfixがインストールされ起動しており、これはもったいないのでGMailで他所に中継する。

# 制限

例えばhoge.localというホストから発信されたメールは、下記の様にすべて同じGMailユーザから発信されたことになる。これによりマルチユーザ環境では基本使えない。あくまでも自分のローカル開発環境等にはいいかもと言う感じ。

```
From: root <ユーザ名@gmail.com>
X-Google-Original-From: root@hoge.local (root)
```

# 環境

CentOS 7.2.1511で確認した。

```shell-session
# rpm -qa|grep postfix
postfix-2.10.1-6.el7.x86_64
# rpm -qa|grep cyrus-sasl
cyrus-sasl-lib-2.1.26-20.el7_2.x86_64
cyrus-sasl-2.1.26-20.el7_2.x86_64
cyrus-sasl-plain-2.1.26-20.el7_2.x86_64
cyrus-sasl-devel-2.1.26-20.el7_2.x86_64
```

cyrus-sasl-plainがないとGMailとの認証できないので注意（minimalでは入ってなかったはず)

# 設定

## 中継設定

main.cfを編集

```shell-session
# vi /etc/postfix/main.cf
```

末尾に次の設定を追加、GMailを中継先にしTLSを使いSMTP認証(PLAIN)にする。

```
# GMail
relayhost = [smtp.gmail.com]:587
smtp_use_tls = yes
smtp_tls_CApath = /etc/pki/tls/certs/ca-bundle.crt
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain
```

## 認証ユーザの設定

```shell-session
# vi /etc/postfix/sasl_passwd
```

```
[smtp.gmail.com]:587    <gmail_address>:<password>
```

```
中継先SMTPアドレス:ポート		認証ユーザ名:パスワード
```

パーミッションの変更とdb化

```shell-session
# chmod 600 /etc/postfix/sasl_passwd
# postmap hash:/etc/postfix/sasl_passwd
```

## 設定の有効化(再起動)

```shell-session
# systemctl restart postfix        # CentOS7/Systemd
```
reloadでもいいけど

## 確認

mailxパッケージをインストールしてあれば次の様に、自分のアドレス(GMail以外でも可)へメールを送信すると、中継登録したGMailアドレスからメールが届くはず。

```
$ mail hoge@example.jp
Subject: test
test
EOT
```
EOTはCtrl-Dで

# 運用

## alias設定

ローカルホストのrootと作業ユーザのメールエイリアスを登録する
一般ユーザは~/.forwardでも良いが…

```shell-session
# vi /etc/aliases
```

末尾に次の様にaliasを追加

```
root:			hoge@example.jp
vagrant:		hoge@example.jp
```

上記例はrootとvagrantユーザへのメールが自分のメールアドレスhoge@example.jpに届く設定(もちろんGMailでも可)

```shell-session
# newaliases
```
newaliasesは忘れずに

## おまけlogwatchインストール

```shell-session
# yum install logwatch
```

logwatchをインストールしておけば、ログの集計結果が届くはず。ただし深夜も動いてるなら。
古い Kobo Touch を再生する

道に迷ったけれど通り抜けたので、メモを残しておく。

## 問題点
古い Kobo Touch eReader を引っ張り出してきて、ファクトリリセットしたら、firmware が 1.9.17 とかいう古臭いやつに戻ってしまった。Kobo は初回設定時にアカウントと紐づける必要がある。
しかし、このファームは古すぎてWiFi経由での初期設定に対応していないため、USB経由で PC上の kobo desktop に接続しなければならないが、Windows10上の Kobo Desktop では、途中でデバイスを認識できずに初回設定を完了できない、しかもマスストレージとしても参照できなくなってしまう、という問題を抱えている。

## 解決手順

そこで、無理やりファームアップして使えるようにしてやる。
Koboのファームアップデートは、マスストレージとして見えるファイルシステムの `.kobo` というフォルダに KoboRoot.tgz や Kobo.tgz などのファイルを配置したうえで再起動することで、起動中に展開されるという動作になっている。

2016-08-16現在、最新ファームは 3.19.5761。
http://soranoji.air-nifty.com/blog/2016/01/kobo-fw3195761-.html を参考に、
ここから落とせる kobo-update-3.19.5761.zip を使う。
http://www.mobileread.com/forums/showthread.php?t=185660

zipを展開すると、以下のファイルがでてくる:

```
upgrade/
KoboRoot.tgz
manifest.md5sum
```

## ちょっと寄り道。

ここで、KoboRoot.tgz にちょっと加工をしてやる。参考はここ:

- http://d.hatena.ne.jp/Kenji_s/20120831/kobo_telnetd
- http://www.ekesete.net/log/?p=5197

Bash on Ubuntu on Windows でやった。

ファイルを取り出し、rcSを編集する:

```bash
$ mkdir work
$ cd work/
$ tar xzf ../KoboRoot.tgz ./etc/init.d/rcS
$ vi etc/init.d/rcS     # 下の方に /mnt/onboard/run.sh という行を追加してやる (あとでかく)
$ tar uzf ../KoboRoot.tgz ./etc/init.d/rcS
```

こんなかんじの run.sh を作っておく。
``` あとでかく ```

## ファームをアップデートする

ファクトリリセットして、kobo desktop が起動していない状態で(ここ重要)、USBで接続すると D:ドライブとかが登場する。 `.kobo` フォルダの中にさっきの3つを、D:直下に run.sh をそれぞれ置く。

取り出し→USBを抜く、と、更新が始まる。

更新→再起動後、

```
Welcome to Kobo!
Set up your eReader in just a few every steps
Set up over Wi Fi
Don't have a Wi Fi network?
```

`Set up over Wi Fi` を選べるようになっているので、それを選んで進む。
WiFiネットワークスキャン、SSID選択画面、APパスワード入力画面を経て、rakuten ID とパスワードを入力することで初回設定が完了する。

# 最後に、設定ファイルのバックアップをしておこう
KoboReader.sqlite にある user テーブルに初回設定の情報が格納されているので、これをバックアップしておく。
XXX このへんをみると、いろいろ楽しい設定やらパッチなどがそろっているので遊ぶ。あとでかく
Redisデータアクセスコードサンプル for Ruby

## RubyでRedisにつないでデータのやり取りをするためのサンプルコード。

よく忘れるのでメモとしてまとめておく。

```rb
require 'redis'

redis = Redis.new(:host => "localhost", :port => 6379)


#FLUSH
redis.flushdb

#SET
redis.set("test", 1)
redis.set("KEY", "value")

#GET
p redis.get("test")
p redis.get("KEY")
p redis.get("aaa")

#HMSET
redis.hmset("hash", "k1", 1, "k2", "val")

#HMGET
p redis.hmget("hash", "k1", "k2")

#PUSH, POP, RANGE
redis.rpush("data", 1 )
redis.rpush("data", 2)
redis.rpush("data", 3)
redis.rpush("data", 4)
redis.rpush("data", 5)
redis.lpush("data", 0)

p redis.lrange("data", 0, -1)
p redis.rpop("data")
p redis.lpop("data")

#SET
redis.sadd("set", "a")
redis.sadd("set", "b")
redis.sadd("set", "a")

redis.sadd("set2", "a")

p redis.smembers("set")
p redis.sinter("set", "set2")
p redis.sdiff("set", "set2")

#ZADD
redis.zadd("score", [[100, "aaaaa"], [10, "bbbbb"], [200, "ccccc"]])
p redis.zrange("score", 0, -1, with_scores:   true)
```
Magentaの「bazel test //magenta/...」でエラーが出た時のチェックリスト

# Magenta
[tensorflow/magenta: Magenta: Music and Art Generation with Machine Intelligence](https://github.com/tensorflow/magenta)

# 開発環境 :computer: 
- python2.7
	- python3ではbazel testが通らないw
- bazel(0.2.3)
	- brew install bazel
	- [Installing Bazel - Bazel](http://www.bazel.io/docs/install.html#mac-os-x)
- tensorflow(0.10)
	- [tensorflow/os_setup.md at r0.10 · tensorflow/tensorflow](https://github.com/tensorflow/tensorflow/blob/r0.10/tensorflow/g3doc/get_started/os_setup.md)
	- 0.9では動かない
	- [FYI: Please update to TensorFlow 0.10 - Google グループ](https://groups.google.com/a/tensorflow.org/forum/#!topic/magenta-discuss/tKBXtjSJtAg)

# bazelのテストが通らない時のチェックリスト :eyes: 
- pythonのバージョン
	- python --version
- bazelのバージョン
	- brew upgrade bazel
- tensorflowの再インストール
	- pip uninstall tensorflow
	- 前に入れてたバージョンが < 0.7.1の時は特に
- anacondaを使っていて、no import tensorflowとerror logに出る
	- [Anaconda 環境に Google の人工知能オープンソース Tensorflow をインストールしてみた - datalove’s diary](http://datalove.hatenadiary.jp/entry/python/anaconda/install-tensorflow-into-anaconda-environment)
- ぐぐる
- issue見る
	- https://github.com/tensorflow/magenta/issues
solrをdockerで導入

# solrをdockerで導入
### ■前提
dockerとjava8は導入済みのubuntu16.04で。
ubuntuでdockerのインストールは

```shell-session
$ sudo apt-get install docker.io
```

solrはofficialのものを使います。
色々怖いので。。。
https://hub.docker.com/_/solr/

```shell-session
$ sudo docker pull solr
```

core用のローカルフォルダを作成

```shell-session
$ sudo mkdir -p /var/solr/cores
$ sudo chown 8983:8983 /var/solr/cores/
```

※solrコンテナのバージョンが古いとcoreの位置が/opt/solr/server/solrになっているかも。
その場合、下記設定では上手くいきません。最新のコンテナを取得し直しましょう（涙

```shell-session
$ sudo docker run --name solr -d -p 8983:8983 -v /var/solr/cores:/opt/solr/server/solr/mycores -t solr
```

### ■webの起動を確認する

```ブラウザ
http://127.0.0.1:8983/solr/#/
```
![Screenshot from 2016-08-16 23-24-53.png](https://qiita-image-store.s3.amazonaws.com/0/84915/a5225ae5-3b70-714a-cb55-4c9034b47cbe.png)


### ■sample coreを作ってみる

host側のshellで。

```shell-session
$ sudo docker exec -it solr /bin/bash
```

コンテナのshellで。
テスト用のcoreのtestを作成します。

```shell-session
$ solr create -c test
```
* 実行結果

```shell-session
solr@2ce0037aae58:/opt/solr/server/solr/mycores$ solr create -c test

Copying configuration to new core instance directory:
/opt/solr/server/solr/test

Creating new core 'test' using command:
http://localhost:8983/solr/admin/cores?action=CREATE&name=test&instanceDir=test

{
  "responseHeader":{
    "status":0,
    "QTime":1286},
  "core":"test"}
```
 coreを移動する

```shell-session
$ cd /opt/solr/server/solr
$ mv test mycores
```
 Ctrl+P,Ctrl+Qで一旦コンテナを抜けて、solrコンテナを再起動

```shell-session
$ sudo docker restart solr
```


 webの方でもcoreが作成されているのが確認できます。
![Screenshot from 2016-08-16 23-57-12.png](https://qiita-image-store.s3.amazonaws.com/0/84915/050f518b-02bd-d0ee-a0e4-a95fa102d46c.png)

 ホスト側にもcoreができていることを確認

```shell-session
$ ll

drwxr-xr-x 3 8983 8983 4096  8月 16 23:52 ./
drwxr-xr-x 3 root root 4096  8月 16 23:30 ../
drwxr-xr-x 4 8983 8983 4096  8月 16 23:51 test/
```
# ログフォルダもcoreと同じようにホスト側にボリュームマウントしてあげると良いと思います。

 今のコンテナをストップして削除

```shell-session
$ sudo docker stop solr
$ sudo docker rm solr
```

 ログ用フォルダを作ってコンテナ起動

```shell-session
$ sudo mkdir -p /opt/solr/log
$ sudo chown 8983:8983 /opt/solr/log
$ sudo docker run --name solr -d -p 8983:8983 -v /var/solr/cores:/opt/solr/server/solr/mycores -v /opt/solr/log:/opt/solr/server/logs -t solr
```
dockerコンテナで簡単にsolrを導入できて便利です。
また、coreをホスト側に持てるので気軽にコンテナを変えてsolrのバージョンを変えられます。
＃互換性のテストとか簡単にできるね♪

coreに設定をしていってrestartをしてを繰り返すと環境の構築が早いですね。
chown 8983をし忘れるとファイルが読めなくてエラーが出ることがあります。
エラーがでたらまずオーナを確認するといいかも。

### コンテナのsolrに変更をしたい場合
ログレベルの変更やキャッシュサイズの変更等でコンテナ内部のファイルを変更したい場合、solrユーザでは制限がある場合、以下のコマンドでrootでのログインができます。

```shell-session
sudo docker exec -u root -it solr /bin/bash
```
commitはお忘れなく。
Wercker で GitHub のトークンが漏れてないか調べよう

# 概要
[Wercker](https://app.wercker.com/) で成果物を GitHub に保存させる場合，
[Personal access token](https://github.com/settings/tokens) を取得して，環境変数に登録すると思う．
この時，`Protected` にチェックをつけると，秘匿されるように見えるのだが，
使用している step によっては漏れていることもあるので気をつけよう．

# 漏れている例
Wercker でドキュメントをコンパイルして GitHub Pages にアップロードする時に使われる step の一つ，
[lvivier/step-gh-pages](https://github.com/lvivier/step-gh-pages) を使った例．

(**2016年9月2日追記**) PR が取り込まれたので，最新版の lvivier/step-gh-pages はトークンを公開していません．

![wercker_log.png](https://qiita-image-store.s3.amazonaws.com/0/62253/7348ce2c-705e-bef0-f406-edccc6727240.png)

git の push メッセージにトークンが含まれている．

環境変数を `Protected` にすると，
その環境変数を直接表示するような処理はログから秘匿されると思われるが，
別のプログラムがうっかり出力している場合には対応していないと思われる．

# 対策？
ビルドログを調べてトークンらしき文字列が出力されていたら，

- 別の step の利用を検討するか， 
- private プロジェクトに変更するか，
- 少なくとも実行権限を public 以外にしてログを公開しないようにする
import先/元でmodule名が被る資材を正しく呼び出せない

## 課題概要
* importしたmoduleの中で更にimportしている場合に、import元のmoduleに同名のmoduleがあると正しく読めない場合がある
* 例えばimport元にconfという環境設定情報を記載したpyファイルを配置
* import先にも同内容で配置すると、import元のconfを強制で呼んでしまう
* python2.7で確認

## 再現
### module構成と内容
構成

```bash
$ find . -type f
./test1/bin/test.py
./test1/conf/__init__.py
./test1/conf/test_settings.py
./submodule/__init__.py
./submodule/conf/__init__.py
./submodule/conf/submodule_settings.py
./submodule/submodule_test.py
```

呼び出し元のpython内容

```py
$ cat ./test1/bin/test.py
# -*- coding: utf-8 -*-
import sys
import os

base_dir = os.path.dirname(__file__) + "/.."
sys.path.append( base_dir )
from conf import test_settings
#import conf.test_settings

sys.path.append(base_dir + "/../submodule")
import submodule_test
```

submoduleの内容

```py
$ cat ./submodule/submodule_test.py
# -*- coding: utf-8 -*-
import sys
import os

# 再優先で自ディレクトリを検索するようにしても、test.pyのconfを読みに行ってしまう
sys.path.insert(0, os.path.dirname(__file__))
print sys.path
import conf.submodule_settings
```

## 解決策
### 1. submoduleを1階層上から呼ぶ
```py
$ cat ./submodule/submodule_test.py
# -*- coding: utf-8 -*-
import sys
import os

# import元にはsubmoduleなんてmodule名は無いはずなので、正しく呼べる
sys.path.insert(0, os.path.dirname(__file__) + "/../")
print sys.path
import submodule.conf.submodule_settings
```

うーん。読めるけど、moduleの配置先を名前固定にしないといけなくなる。
もっとちゃんとしたやり方がありそうだけどわからないですねぇ。

### 2. ConfigParser使う
submoduleの別ファイルなんてconfig読むくらいな気もするので、ConfigParser使うだけでこんな問題とおさらばできそうだった。
XcodeでiOS Simulatorが見えないときは

## iOS Simulatorを出すには
Xcode 7.2で既存のXcode プロジェクトを取り込むと、iOS Simulatorが見えなくなってしまってビルドすらできなかった。
Xcode -> Open -> Developer Tool -> Simulator でちゃんとSimulatorは起動するのに、アプリケーションのターゲットにはBuild Only DeviceのGeneric iOS Deviceしかない。。

![スクリーンショット 2016-08-16 21.21.26.png](https://qiita-image-store.s3.amazonaws.com/0/137365/1ad0fdaf-b1b9-8aa0-2e63-fb8909fb0ec7.png)

これはなんのことはなく、プロジェクト設定のGeneralタブの"Deployment Info"でDeployment Targetを指定できていないだけだった。Xcode 7.2ではiOSの「9.2」を選ぶと、ビルド停止の■ボタンの右どなりで選択できるようになった。
![スクリーンショット 2016-08-16 21.43.20.png](https://qiita-image-store.s3.amazonaws.com/0/137365/5d37f93f-9c1c-6535-b211-af16fb12aa4b.png)
これでSimulatorによる開発が可能になった。
PHP mysqlに接続する 

忘れそうなのでメモ
セキュリティはどうなのか分からないけど、一応動いたので

PHP 7から`mysql`は使えなくなり、`mysqli`もしくは`PDO`を使うのか、はたまた`手続き型`や`オブジェクト指向型`初心者には訳が分からないです
※説明するつもりはないです
マジで、検索すれば人それぞれ色々な方法があるし・・・

では本題、ここでは`mysqli`と`プリペアステートメント`を使います

#MySQLに接続
```phpファイル
<?php
// ホスト名・MySQLユーザ名・パスワード・
データベース名は各自で
 $mysqli = new mysqli('ホスト名', 'MySQLユーザ名', 'パスワード', '
データベース名');

 // エラー発生したら終了
 if ($mysqli->connect_error){
 exit();}

 // 文字コード指定
 $mysqli->set_charset("utf8");
```

#INSERT
```
 // テーブル名、フィールド名はそれぞれで。フィールドの数は一個のみでも何個でもかません。
 // VALUESのあとにフィールド名と同じ順で入れたい値を書きます。変数は入れられないので、?に置き換えてください。
 // 変数でなければ数字や文字、時間now()はここにそのまま入れられます

 $sql = "INSERT INTO テーブル名 (field1,field2,field3) VALUES (?,1,now())";

 // $sqlに入れなくても構いません。条件があるときには役立ちます
 $stmt = $mysqli->prepare($sql);

 // パラメータに変数を入れます
 // 最初に型指定文字を。次に変数を入れます
 $stmt->bind_param('is', $tid,$screen_name);

 // 最後に実行
 $stmt->execute();
```
型指定文字についてはこちら
[PHP_ mysqli_stmt__bind_param - Manual.html](http://php.net/manual/ja/mysqli-stmt.bind-param.php)

#UPDATE
INSERTと同じようなものです

```
// フィールドは区切ればいくつでも可。もちろん、WHEREの中に?も可
$stmt = $mysqli->prepare("UPDATE テーブル名 SET field1 = now() WHERE id=?");

// 変数代入
$stmt->bind_param('i', $id);
// 実行
$stmt->execute();
```

#SELECT
```
$stmt = $mysqli->prepare("SELECT field1,field2,field3 FROM テーブル名 WHERE id=?");
$stmt->bind_param("i", $id);
$stmt->execute();

// 結果をバッファに保存
$stmt->store_result();

// 結果を変数に代入
$stmt->bind_result($field1,$field2,$field3);

// 結果の行数
$row_cnt = intval($stmt->num_rows);
```

忘れてた

```
// 最後に使うDB接続を閉じるこれ
$mysqli->close();
```

以上。

DELETEのとき書いてないけど同じような感じなのかな？まだ使ってないから分からないけど。
他のサイトももっと紹介したいです
あとで追記します。たぶん・・・

###参考
[PHP_ mysqli__prepare - Manual.html](http://php.net/manual/ja/mysqli.prepare.php)
他にもたくさんの先人の方々の知恵
(小ネタ)javascriptでの、オブジェクトのメンバ呼び出しで数バイト削る努力をしてみる

#小ネタです

## 仕様の話
　javascriptはメンバ関数の呼び出しに```.```の代わりに、```["メンバ名"]```でも呼び出せる。
　オブジェクトのプロパティに関数オブジェクトが入ってるだけなので、そりゃそうかって話。

## 仕様の話2
　メンバの参照は、変数でも行える。

```js
var hoge="document";
window[hoge] ; //window.document
```

## 仕様の話3 
　変数名は、数字で始まらなければ、英数字と特定の記号、***もしくはunicode文字列***が使える

## UTF-8の話
　日本語は3バイト使うけど、アラビア語、ヘブライ語はUTF-8で2バイト。

# 要するに
　文字数×出現個数が、文字数+7文字以上のものを書き換えると元が取れる計算。
　さらに、左右反転するので、ぱっと見動くように見えないコードができる。

```js
var ج=JSON,ح="stringify",خ="parse";
console.dir(ج[خ](ج[ح]({hello:"world"})));
//==>Object {hello: "world"}
//元：console.dir(JSON.parse(JSON.stringify({hello:"world"})));
```

# もしかするとファイルサイズ減るかも？
　適当にパーサ書いて置換したりしてみましたが、そんなに減りませんでした。
　いつかどこかでまじめに検証する予定。
Ruby on Rails環境をMacで構築してみる

インターン中に手持ちのMacでRoRのアプリケーションを動かしたくなりMacで環境構築してみた話。
Macbook Air(Mid 2013)の環境は以下のとおり。

- Core i5 1.4GHz
- OS X El Capitan 10.11.6

## rbenvのインストール
Homebrewから以下のコマンドでrbenvをインストールする。rbenvはRubyのバージョンを管理してくれるものらしい。

```
$ brew update
$ brew install rbenv ruby-build
```

## Rubyのインストール
以下のコマンドをうっていく。2016年8月16日時点で最新は2.3.1のようなのでこれを入れてみる。

```
$ rbenv install -l #バージョンのリストがでてくる
$ rbenv install 2.3.1
$ rbenv rehash
$ rbenv global 2.3.1
$ rbenv -v #ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]とでるはず
```
## Railsのインストール
必要最低限なgemとRailsコマンドもインストール。

```
$ gem install bundler
$ gem install rails
$ rbenv rehash
```

あとはアプリケーションのbundle installでインストールすればおーけーだったが、pgというコマンド？でインストールがこける。エラーメッセージから以下のコマンドをたたいた。このときpostgresqlが必要らしいのでいっしょにインストール。

```
$ brew install postgresql
$ gem install pg -v '0.18.4'
$ bundle install
```
これでうまくいった。あとはdb:createなどをしたいところだがこれもこける。こんな感じのエラー。

```
PG::ConnectionBad (could not connect to server: Connection refused
        Is the server running on host "localhost" (::1) and accepting
        TCP/IP connections on port 5432?
```
これは調べるとpostgresqlがシステムで立ち上がっていないためらしい。ので以下のコマンドをたたく。そうしたらデータベースの初期化がめでたくできるようになる。

```
＄ pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start
$ bundle exec rails db:create db:migrate db:seed
```
あとはサーバーを立てればlocalhostでアクセスできるようになった。めでたしめでたし。

```
$ bundle exec rails server
```

## 参考
以下のサイトが参考になりました。ありがとうございました。

- https://tsuchikazu.net/mac_rail_setup/
- https://openbook4.me/projects/83/sections/519
高橋メソッドとは

##高橋メソッドとは

>高橋メソッド（たかはしメソッド）とは、日本Rubyの会の高橋征義によって考案されたプレゼンテーション技法。
2001年に高橋が講演するにあたり、あいにくプレゼンテーションツールを持ち合わせていなかったことから、巨大な文字だけで構成されたHTMLによるプレゼンテーションを行ったことが始まりとされる。[高橋メソッド(Wikipedia)](https://ja.wikipedia.org/wiki/%E9%AB%98%E6%A9%8B%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)

公式サイト(?)もある
[高橋メソッド](http://www.rubycolor.org/takahashi/)

##高橋メソッドの特徴
- 図やグラフなどは使わない
- 文字のみで作成
- 文字は巨大なサイズを使用する
- 1枚あたりの文字数は最小限とし、簡潔な内容にする

##サンプル
- [高橋メソッドについて](http://www.rubycolor.org/takahashi/takahashi/img0.html)  
途中からNot Foundで最後まで見れないのが残念
- [超妹大戦シスマゲドン](http://www14.plala.or.jp/funore/tmethod/)
- [ミルカさん](http://www.hyuki.com/girl/tm_miruka.html)

#書籍
本も出ている
[でかいプレゼン 高橋メソッドの本](http://www.amazon.co.jp/dp/4797332530)

##作成ツール
ツールを使う必要があるか分からないがツールがある
[高橋メソッドなプレゼンツール in XUL リターンズ](http://piro.sakura.ne.jp/xul/applications/takahashi-r/#howtouse)
[髙橋メソッド Generator](http://landhere.jp/services/tkmethod/index.php)

##参考サイト
- [高橋メソッド](http://www.rubycolor.org/takahashi/)
- [高橋メソッド(Wikipedia)](https://ja.wikipedia.org/wiki/%E9%AB%98%E6%A9%8B%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89)
- [高橋メソッドについて](http://www.rubycolor.org/takahashi/takahashi/img0.html)
- [超妹大戦シスマゲドン](http://www14.plala.or.jp/funore/tmethod/)
- [ミルカさん](http://www.hyuki.com/girl/tm_miruka.html)
Pythonで機械学習はじめました(Qiitaへの投稿もはじめました) データ準備編

# <i class="fa fa-child" style="font-size:1em;"></i> はじめましてなので
某中堅企業でエンジニアやってます。ふと、自習したことをQiitaに纏めていこうと思い立ちました。
とりあえず勉強中の機械学習について纏めてみます。(心折れたら書きやすい別テーマで休憩)
ちなみに言語は主にPythonを使う予定です。

※9/25追記 次:[「データ前処理編」](http://qiita.com/yuuki_1204_/items/c26cb09fba8aad35dc0a)

# <i class="fa fa-check-square-o" style="font-size:1em;"></i> ご注意！
- 理論よりも、とりあえず触って理解するやり方が好きなので、色々と雑です。
- さらに文盲ということで、分かりづらい文章になると思ってます。
- そんな訳で読んでてツッコミたくなる内容は多々あると思いますが、ご了承頂きたく！
  ※優しいツッコミは大歓迎です

# <i class="fa fa-bolt" style="font-size:1em;"></i> 3行でまとめ
- Twitterのデータを使って機械学習をお勉強してみます。
- 今回は使うデータ・環境準備の話で終わり。
- 次回はツイートのクラスタリング・類似度の算出をするつもり。

# <i class="fa fa-graduation-cap" style="font-size:1em;"></i> データセット
勉強開始当初、参考書やチュートリアルで出てくる「iris(アヤメ)」や「Titanic(タイタニック号の生存/死亡者)」をそのまま使って色々してみたんですが、データへの興味の無さからか全然頭に入って来ず…。

心機一転、分析して面白そうな**Twitter**のデータを使うことにしました。
また、より自分の興味をそそるように(？)、今回は「**Perfume**」に関するツイートに絞ることにしてます。
(注:のっち派です)

ちなみに「Perfume」が含まれるツイートを取得して眺めて見たところ、思ってたより件数が少なく(250件/1h位)、ボットらしきツイートを除外するとさらに少ないことが分かりました。
ツイート非公開のファンが多いからかなぁと勝手に思ってます。
(非公開のツイートも、ユーザ名無しで公開してくれないかな…ムリか…)

ということでデータ数が若干少ないので、今後は比較のためにもアーティストを増やしていこうかと思います。
(候補:**CAPSULE**、**サカナクション**・・・)

機械学習で具体的に何をするかは…**動かしながら考え中**です。

# <i class="fa fa-twitter" style="font-size:1em;"></i> データの準備方法
StremingAPIを使ってPerfumeに関するツイートを収集、Elasticsearchで蓄積する環境を構築済みです。
今回は勉強スピードアップの為、Elasticsearchから一部のデータをファイルに保存(**es.log**)し、ローカルのスクリプト(**tw_ml.py**)で機械学習他、ゴニョゴニョしてみようと思います。

以下のような感じ。

![構成図.jpg](https://qiita-image-store.s3.amazonaws.com/0/82760/bfcfc493-d9fb-e93e-7d27-088146e2fe63.jpeg)


データのフォーマットは以下のようになっています。
(保存時、辞書型なのでユニコードオブジェクトには「u」とか付いてます)

```text:es.log(1件抜粋、データはダミー)
[{u'_score': 1.0, u'_type': u'raw', u'_id': u'AVZkL6ZevipIIzTJxrL7', u'_source': {u'retweeted_status': u'True', u'text': u'Perfume\u306e\u597d\u304d\u306a\u6b4c', u'user': u'xxxxxxxxxx', u'date': u'2016-08-07T08:45:27', u'retweet_count': u'0', u'geo': u'None', u'favorite_count': u'0'}, u'_index': u'tweet'}]
```

Pythonからes.logの読み込みはcodecsでopenして、astを使って辞書に戻して使います。
とりあえず265件ですが、データ量が足りないと思ったらElasticsearchから再度取得して増やすつもり。

```py:tw_ml.py(抜粋)
import codecs
import ast
with codecs.open("es.log", "r", "utf-8") as f:
    es_dict = ast.literal_eval(f.read())
    print "doc:%d" % len(es_dict)  # doc:265
```

# <i class="fa fa-cogs" style="font-size:1em;"></i> 環境、主なライブラリ等

- スクリプト実行環境
 - Windows7 64bit
 - Python2.7

- 主なPythonライブラリ
 - numpy 1.11.1
 - scipy 0.12.0
 - scikit-learn 0.16.0
 - mecab-python 0.996

ちなみにMecabは日本語の形態素解析に使うのですが、辞書には「**mecab-ipadic-neologd**」を使ってます。
コレ使わないと「かしゆか」「あーちゃん」「のっち」すら単語とみなしてくれなかった…笑
※ただ、mecab-ipadic-neologd使っても「のっち」はカタカナで「ノッチ」！デンジャラス！！

```py:tw_ml.py(抜粋)
MECAB_OPT = "-Ochasen -d C:\\tmp\\mecab-ipadic-neologd\\"
t = mc.Tagger(MECAB_OPT)
```

# <i class="fa fa-hand-rock-o" style="font-size:1em;"></i> では早速…

と思いましたが、長くなったので本題の機械学習については次回以降にします！笑
とりあえずツイートのクラスタリング・類似度の算出を試してみる予定です。

# <i class="fa fa-pencil-square-o" style="font-size:1em;"></i> 参考になりました！(主に書き方)
- [Qiita の記事の見出しに Font-Awesome を利用して見栄えを良くする #qiita](http://qiita.com/tbpgr/items/361d8aaa38fb57d75216)
- [2年目プログラマがQiitaに週一投稿して1年が過ぎました](http://qiita.com/khsk/items/ee915068077e5bea675e#_reference-dbc14ea082a925f4dac0)
PHPUnitのassertArraySubset()について

すげー便利そうに見えて、微妙に使いづらい子だな…という印象。(言いたいこと終わり)
https://phpunit.de/manual/current/ja/appendixes.assertions.html

## 配列のアサーションの問題

例えば、ある関数の実行結果がこういう感じの配列をだとしよう。

```php
[
  [
    'name' => 'taro',
    'gender' => 'male',
    'updated' => '2015-08-10 12:01:13',
  ],
  [
    'name' => 'hanako',
    'gender' => 'female',
    'updated' => '2016-07-31 13:04:14',
  ],
];
```

関数のテストを書くなら、↑の配列をexpectとして用意して、結果をassertEqualsで比較すればいい。

ところが、別に全部の要素を厳密に比較しなくてもいいことがある。例えば、配列内の`updated`という名前のフィールドはデータが更新されたタイミングで自動的に採番されるというロジックなら、厳密な時間をテストしようとすると大変だし、やる必要もないだろう。丁寧にやるとしてフォーマットのチェックぐらいだろうか。

「updatedは無視して、それ以外だけをアサーションしたい」

こういう時、アサーションがassertEquals一発で書けなくなってしまう。
仕方がないので、べたっと書いてみるけれど、

```php
$this->assertEquals('taro', $result[0]['name']);
$this->assertEquals('male', $result[0]['gender']);
$this->assertEquals('hanako', $result[1]['name']);
$this->assertEquals('female', $result[1]['gender']);
//...
```

ウッ…。格好良くないし、かなり記述量が増えてしまう。
だいたい、関数の実行結果が配列形式でなければ、`$result[0]`の辺りでエラーになってしまうだろう。失敗した時のログが読みにくくなってしまってよくない。

## assertArraySubset

たぶんこのアサーションは、この問題を解決する目的なのではなかろうか。
配列に対するassertEqualsに似ているがちょっと挙動が異なる。

**部分配列** をexpectに指定できるのである。

```php
$expect = [
    [
        'name' => 'taro',
        'gender' => 'male',
    ],
    [
        'name' => 'hanako',
        'gender' => 'female',
    ],
];
$actual = [
    [
        'name' => 'taro',
        'gender' => 'male',
        'updated' => '2015-08-10 12:01:13',
    ],
    [
        'name' => 'hanako',
        'gender' => 'female',
        'updated' => '2016-07-31 13:04:14',
    ],
];

$this->assertArraySubset($expect, $actual);
```

部分配列とは、検証対象の配列から幾つか要素を省くことで作られる配列である。この場合、updatedという要素を省いた配列で検証しているけど、ちゃんとassertが通る。

アサーション一個で書けて簡潔だし、そんなに読みにくくもないと思う。いいじゃんこれ。…と思ったんですよ。

## 微妙に使いづらい点

assertEqualsは失敗した際のログがすごく分かりやすい。配列同士の場合、違いをdiff形式で表示してくれる。

```diff
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
     0 => Array (
         'name' => 'taro'
         'gender' => 'male'
+        'updated' => '2015-08-10 12:01:13'
     )
     1 => Array (
         'name' => 'hanako'
         'gender' => 'female'
+        'updated' => '2016-07-31 13:04:14'
     )
-    2 => Array (...)
-    3 => Array (...)
-    4 => Array (...)
-    5 => Array (...)
-    6 => Array (...)
-    7 => Array (...)
-    8 => Array (...)
-    9 => Array (...)
-    10 => Array (...)
 )
```

一方でassertArraySubsetはexpectをダンプするだけのようだ。。これではどこがダメだったのかよくわからず、失敗した時に役に立ちづらいテストになってしまう。

```diff
Failed asserting that an array has the subset Array &0 (
    0 => Array &1 (
        'name' => 'taro'
        'gender' => 'male'
    )
    1 => Array &2 (
        'name' => 'hanako'
        'gender' => 'female'
    )
    2 => Array &3 (
        'name' => 'hanako'
        'gender' => 'female'
    )
    3 => Array &4 (
        'name' => 'hanako'
        'gender' => 'female'
    )
    4 => Array &5 (
        'name' => 'hanako'
        'gender' => 'female'
    )
).
```

俺が求めているのはassertEqualsと同じようなdiff表示なのだが、これ何とかならないかしら…

結局、余分なものを排除してからassertEqualsで比較する手も考えたほうがいいのかなあ。。
省略表記のIPv6をフル表記に変換するシェル

# 概要
ファイルの特定の列に含まれているIPv6をフル表記にしたい。

# 実行結果

（時間、ipv6、メッセージ）のセットのデータを、（時間時間、ipv6、ipv6フル表記、メッセージ）のセットへ変換する。

・入力ファイル

``` sample.txt
2016/08/08 22:00:00  2001:0db8:bd05:01d2:288a:1fc0:0001:10ee  aaa
2016/08/08 22:01:00  2001:0db8:0020:0003:1000:0100:0020:0003  bbb
2016/08/08 22:02:00  2001:db8:20:3:1000:100:20:3              ccc
2016/08/08 22:03:00  2001:0db8:0000:0000:1234:0000:0000:9abc  ddd
2016/08/08 22:04:00  2001:db8::1234:0:0:9abc                  eee
2016/08/08 22:05:00  2001:db8::9abc                           fff
2016/08/08 22:06:00  127.0.0.1                                ggg
```

・変換用シェル

```sh:GetIPv6FullAddress.sh
#!/bin/sh

inf=$1

cat ${inf}                                                  |
awk '                                                       \
    # v6フル表記変換                                          \
    function v6Full(v6ip, v6full, cnt, array, i ) {         \
        cnt = split(v6ip, array, ":" ) ;                    \
        if(cnt == 1) { return v6ip ; }                      \
        for(i=0; i<=8-cnt; i++) {                           \
            sub("::", ":0000::", v6ip) ;                    \
        }                                                   \
        sub("::", ":", v6ip) ;                              \
        cnt = split(v6ip, array, ":") ;                     \
        for(i=1; i<=8; i++) {                               \
            v6full = sprintf("%s%04s:", v6full, array[i]) ; \
        }                                                   \
        sub(":$", "", v6full) ;                             \
        return v6full ;                                     \
    }                                                       \
    # メイン処理                                               \
    {                                                       \
        fullip = v6Full($3, a, cnt, array, i) ;             \
        printf("%s %s %-39s %-39s %s\n", $1, $2, $3, fullip, $4) ; \
    }                                                       \
'

```

・実行結果

```
$ sh v6FullAddress.sh sample.txt 
2016/08/08 22:00:00 2001:0db8:bd05:01d2:288a:1fc0:0001:10ee 2001:0db8:bd05:01d2:288a:1fc0:0001:10ee aaa
2016/08/08 22:01:00 2001:0db8:0020:0003:1000:0100:0020:0003 2001:0db8:0020:0003:1000:0100:0020:0003 bbb
2016/08/08 22:02:00 2001:db8:20:3:1000:100:20:3             2001:0db8:0020:0003:1000:0100:0020:0003 ccc
2016/08/08 22:03:00 2001:0db8:0000:0000:1234:0000:0000:9abc 2001:0db8:0000:0000:1234:0000:0000:9abc ddd
2016/08/08 22:04:00 2001:db8::1234:0:0:9abc                 2001:0db8:0000:0000:1234:0000:0000:9abc eee
2016/08/08 22:05:00 2001:db8::9abc                          2001:0db8:0000:0000:0000:0000:0000:9abc fff
2016/08/08 22:06:00 127.0.0.1                               127.0.0.1                               ggg
```

# 参考文献
下記参考にさせていただきました。
http://blog.n-z.jp/blog/2014-06-14-jus-usp.html
Javaで関数型言語のreduceを実装してみる

#始めに
##目的
Javaで自前reduceを実装することで、関数型言語の考え方（特に再帰）に慣れるためです

##実装方針や考え方
- ループを使わずに再帰を使って繰り返し処理を実装する。
- 特定の型に特化するのではなく、汎用的な型を扱えるようにする。
- ここでは、Java8で登場する機能はあえて使っていません。

#工夫した点
##インナークラス
ジェネリック型を使って、汎用的な型を扱えるようにしています。
例えば、配列の要素を足し上げる処理は数値型だけではなく、文字列型に対しても処理できるように字実装しています
##Reduceクラスのreduceメソッド
###再帰処理で使うデータ構造について
関数型言語で再帰を語る時によく出てくる
”集合Aの繰り返し処理を、一番目の要素とそれ以外の要素に分け、一番目の要素を処理した後に残りの要素を再帰処理をする関数の引数に渡して実装する”
点をJavaのStack(Deque)を使って実装しています。
ちなみに、最初の実装ではlistに対してget→removeの処理を行っていましたが、見た目にも美しくないし、結局やりたいことがFirst-In,First-Outだということに気が付いたので、Stackを使う実装に変更しました。
###再帰処理のロジックについて
初回の再帰処理は引数で渡された要素が2つ以上場合、呼び出す関数の二つの引数に対してそれぞれ2回スタックをpopしてあげる必要があります。
このとき、再帰処理が初回かそうでないかはインスタンス変数のT _tがnullかどうかで判定しています

#収穫点
-  再帰のロジックになれたかもしれない
-ついでにJavaの総称型の使い方になれたかもしれない

```FuncTest.java
	static public class Reduce<T>{
		private T _t ;
		public T reduce(Collection<T> b,Function<T> f){
			Deque<T> a = new ArrayDeque<T>(b);
			//スタックの要素がなくなったら再帰処理を終了する
			if(a.isEmpty()){
				return _t;
			}
			//要素数2以上のリストが渡された場合
			if(a.size() > 1){
				//最初に再帰処理が呼び出された時の処理
				if(_t==null){
					//リストの一番目と2番目を引数にセットする
					_t = f.aply(a.pop(),a.pop());
				}else{
					//2回目以降に再帰処理が呼び出された場合はインスタンス変数で保持した
					//値とスタックの先頭を引数で渡されたインナークラスのメソッドに渡す
					_t = f.aply(_t,a.pop());
				}
			//要素数1のリストが渡された場合
			}else{
				//最初に再帰処理が呼び出された時の処理
				if(_t==null)return a.pop();
				else{ 
					_t = f.aply(_t,a.pop());
     			}
			}
			return reduce(a,f) ;
		}
	}
	//Functionクラスのインターフェイス　abstractクラスで定義する
	static  abstract class Function<T>{
		public abstract T aply(T a, T b);
	}
	//配列の中身をすべて足し算します
	static class  FunctionAsAdd<T> extends Function<Integer>{
		public Integer aply(Integer a, Integer b){return a+b;};
	}
	//配列の中身をすべて掛け算します
	static class FunctionAsMultiplication<T> extends Function<Integer>{
		public Integer aply(Integer a, Integer b){return a*b;};
	}
	//配列の文字列をすべて連結します
	static class FunctionAsString<T> extends Function<String>{
		public String aply(String a, String b){return a+b;};
	}
	
	
	public static void main(String args[]){
		List<Integer>list = new ArrayList<Integer>();
		Collections.addAll(list, 1,2,3,4,5,6,7,8,9,10);
		System.out.println(
				(new Reduce<Integer>())
				.reduce(list,new FunctionAsAdd<Integer>())
				);//55が表示される
		System.out.println((new Reduce<Integer>())
				.reduce(list,new FunctionAsMultiplication<Integer>())
				);//3628800が表示される
		List<String> stringList= Arrays.asList( 
				new String[]{"1","2","3","4","5","6","7","8","9"});
		System.out.println((new Reduce<String>())
				.reduce(stringList,new FunctionAsString<String>())
				);//123456789が表示される
	}
}
```
Cognito User Poolsでemail verification messageのメール送信を日本語で行う方法

## 概要
<img width="1273" alt="スクリーンショット 2016-08-16 22.21.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/65478/636f8c47-fa31-e4c9-ac82-b643bd7ab2f9.png">
User Poolsではユーザに送信するアクティベーションメールの文面をカスタマイズすることが出来ます。
しかし、マネジメントコンソールで日本語の文章を入力するとキャプチャの用にJavaScriptエラーが発生して登録が出来ないバグが有ります。

## 解決策
aws-cliを使って登録すれば解決します。
コマンドは以下のとおり

```
$ aws cognito-idp update-user-pool --user-pool-id us-east-1_hq5vcdssx --email-verification-subject 'お申し込みありがとうございました' --email-verification-message "
これはアクティベーションメールです。
あなたの認証コードは{####}です。

アクティベーションページから認証コードを入力してください
http://example.com/#activation

また、パスワード忘れの方は以下のページからパスワードを再発行してください
http://example.com/#activation" --auto-verified-attributes email
```
unicornとNginxをリロード&リスタートするシェルスクリプト

需要があるかは不明(多分ない)
いちいちコマンド打つのが大変だった

```sh:allrestart.sh
#!/bin/sh

echo "allrestart.sh START"

#unicorn
ps -ef | grep unicorn | grep -v grep

kill -QUIT `cat tmp/unicorn.pid`

echo "unicorn停止中......"
sleep 5;

#unicorn-start
bundle exec unicorn_rails -c config/unicorn.rb -E production -D


#nginx
sudo service nginx reload
sudo service nginx restart


echo "--------------------------------------------------"

echo "NOW STATUS"

ps -ef | grep unicorn | grep -v grep

sudo service nginx status

echo "--------------------------------------------------"

echo "allrestart.sh FINISH"
```

アプリがあるディレクトリに作っといて

```sh
$ sh allrestart.sh
```
flowtype + eslint 環境で eslint の no-undef で declare された型の型アノテーションの検出を無視する

## どんな状況か

include してる型宣言ファイルでFooを宣言しているとする

```
decrale type Foo = {};
```

このとき 次のコードは eslint の no-undef で警告が出る

```
const foo: Foo = {};
```

定義ファイルで declare された型はどこかからでもグローバルに参照可能だが、flow はそんなidentifier は知らないと警告してくる

## 解決策1

.eslintrc の globals に Foo を追加する。
これは動くけどインスタンス変数としてFooにアクセスしてしまうのを許容してしまう。ダメ。

不満を持ってたら次の解決策を見つけた。

## 解決策2

https://github.com/gajus/eslint-plugin-flowtype#eslint-plugin-flowtype-rules-define-flow-type を使う。

```
{
  "parser": "babel-eslint",
  "plugins": [
    "flowtype"
  ],
  "rules": {
    "flowtype/define-flow-type": 1,
    "flowtype/use-flow-type": 1
  }
}
```

これに辿り着くまで長かったので、一応メモしておく。ルール名がわかりにくいと思う。

## 参考

- https://github.com/eslint/eslint/issues/4741
NameError: global name 'dot_parser' is not definedとpythonで出てきたときの対処法

pipはインストール済みだとしますね。
```
NameError: global name 'dot_parser' is not defined
```
とエラーが出たら、pyparsingがインストールされていても、バージョンが新しいと互換性がないようです
`pip uninstall pyparsing`
と一旦pyparsingをuninstallしようとしますが、
`[Errno 13] Permission denied: '/path/to/directory'`
とでるので、
`sudo chmod 777 /path/of/directory/`
/pathのところはErrorでたときのpyparsingへのpathをコピーしてください。

これでもう一度pyparsingをuninstallして
`pip install -Iv https://pypi.python.org/packages/source/p/pyparsing/pyparsing-1.5.7.tar.gz#md5=9be0fcdcc595199c646ab317c1d9a709`
`pip install pydot`
としませう。
Unity 時間経過で処理を行う

私的メモ。

rendererは古いのでGetComponent＜Renderer＞ ()を使う。

時間経過(何frameか)で処理を変えるにはUpdate()とif文を使えば良い。

```
using UnityEngine;
using System.Collections;

public class myscript : MonoBehaviour {
	GameObject obj;
	Color c;
	bool flg = false;
	int counter = 0;

	void Update () {
		if (Input.GetMouseButtonDown (0)) {
			Vector3 pos = Input.mousePosition;
			Ray ray = Camera.main.ScreenPointToRay (pos);
			RaycastHit hit;

			if (Physics.Raycast (ray, out hit, 100f)) {
				obj = hit.collider.gameObject;
				c = obj.GetComponent<Renderer> ().material.color;
				obj.GetComponent<Renderer> ().material.color = Color.red;
				counter = 100;
				flg = true;
			}
		}

		// Update()があるのでこのif文はfalseになるまで何度も繰り返される。
		if (flg) {
			Debug.Log (counter);	// counterの値の確認
		
			if (--counter == 0) {
				flg = false;
				obj.GetComponent<Renderer> ().material.color = c;
			}
		}

	}
}
```

Update()があるので、if文の条件判定と処理がフレームごとに行われる。上のサンプルではちょうどwhile(true)みたいな処理が行われている。counterの値はデクリメントのおかげで徐々に減少していくのでそのうち処理が行われるようになる。

上のサンプルでは100フレームで処理が行われる。
Raspberry Pi3 にてjupyter をリモート接続

Raspberry Pi3にてリモートでプログラムを書くのに、jupyterが使えるとクライアントPCに余計なものを入れずにブラウザでプログラムを書けるのでやってみました。


- Raspberry Piにjupyterをインストール（結構時間がかかる）

```
$ sudo pip install jupyter
```

- コンフィグファイルを作成

```
$ sudo jupyter notebook --generate-config

```

- コンフィグファイル修正

```
$ sudo nano /root/.jupyter/jupyter_notebook_config.py
```
にてjupyter_notebook_config.pyを開いて、どこでもいいので

```
c.NotebookApp.ip = '*'
```
を追加して保存


- ipアドレスを確認(192.168.1.XXXX)など

```
$ ifconfig
```



- jupyterを立ち上げ

```
sudo jupyter notebook
```
でブラウザ立ち上がりjupyterが表示される


立ち上がったブラウザにて
「http://localhost:8888/tree」 ⇒ 「http://192.168.1.XXXX:8888/tree」
でアクセスできれば、他のクライアント側PCのブラウザからでも同様にアクセスできるはずです

#参考
- [Jupyter Notebook（IPython）サーバの起動方法](http://www.task-notes.com/entry/20160204/1454513778)
Raspberry Piでchainerメモ

#はじめに
Raspberry Piにchainerをインストールした例が[こちら](http://karaage.hatenadiary.jp/entry/2016/07/08/073000)あったので
Raspberry Piを買ってきて試してみました。

＜用意したもの＞
- Raspberry Pi3 Model B
- microSDカード 32GB
- USBキーボード・マウス
- ディスプレイ(HDMI接続)
- スマホ用 USB 5V 電源(2.4A)
#OSインストール
- 標準的なOS「Raspbian」のインストーラ「NOOBS (zipファイル 約1GB)」を[公式サイト](https://www.raspberrypi.org/downloads/)よりダウンロード
- zipファイルを展開して、microSDにコピー
- microSDをRaspberry Pi3に挿して、マウス、キーボード、ディスプレイ、最後にUSB電源を挿す
- OSインストール画面が立ち上がるので、Raspbianをインストール
- しばらくしたあと、再起動が起こりGUI画面が立ち上がります
- wifiなどを設定します


#日本語化

日本語化のためにフォントなどをインストール

```
$ sudo apt-get update
$ sudo apt-get install fonts-takao ibus-mozc
$ sudo reboot
```

#Chainerインストール
Chainerのインストール
インストールは結構時間がかかりました

```
$ sudo apt-get install python-dev
$ sudo pip install chainer
```

#mnistを実行

mnistのサンプルtrain_mnist.pyをダウンロードして、そのフォルダにて
```
$sudo python train_mnist.py
```
とすると実行されますが・・・・非常に計算が遅いです。
1epoch終わるのに5021秒かかりました。


また、[Raspberry Pi3 にてjupyter をリモート接続](http://qiita.com/samacoba/items/19bab0c50fe6e83ae7e0)もしてみました。

#参考
- [日本語入力のための設定 part2](http://qiita.com/NariseT/items/b97910c8cbb110e0010d)
- [ディープラーニングのフレームワークChainer使ってMac/Raspberry Piで画像認識](http://karaage.hatenadiary.jp/entry/2016/07/08/073000)
PowerShell で画像の回転、リサイズを行う


[ブログからの転載](http://1bed.allright.life/?p=2223)


# 経緯

スマホで取った写真の解像度が大きいので、SNS へのアップ前に自力で小さくしようと思ったら GIMP 立ち上げて... 面倒だったので、PowerShell でやってみました


# 画像の回転

```ps1
# アセンブリの読み込み
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# 画像ファイルの読み込み
$image = New-Object System.Drawing.Bitmap("ファイルパス")

# 回転
$image.RotateFlip("RotateFlipType 列挙体より選択") 

# 保存
$image.Save("ファイルパス", [System.Drawing.Imaging.ImageFormat]::"ImageFormat クラスのプロパティより選択")

# オブジェクトの破棄
$image.Dispose()
```

RotateFlipType 列挙体と意味

| 値  | 反転 | 回転(全て時計回り) | 
| --- | --- | --- |
| Rotate270FlipNone | なし | 270 度 |
| Rotate180FlipNone | なし | 180 度 |
| Rotate90FlipNone  | なし | 90 度 |
| RotateNoneFlipNone| なし | なし |
| Rotate270FlipX    | 水平 | 270 度 |
| Rotate180FlipX    | 水平 | 180 度 |
| Rotate90FlipX     | 水平 | 90 度 |
| RotateNoneFlipX   | 水平 | なし |
| Rotate270FlipY    | 垂直 | 270 度 |
| Rotate180FlipY    | 垂直 | 180 度 |
| Rotate90FlipY     | 垂直 | 90 度 |
| RotateNoneFlipY   | 垂直 | なし |
| Rotate270FlipXY   | 水平＆垂直 | 270 度 |
| Rotate180FlipXY   | 水平＆垂直 | 180 度 |
| Rotate90FlipXY    | 水平＆垂直 | 90 度 |
| RotateNoneFlipXY  | 水平＆垂直 | なし |


## 回転の例

デスクトップの hoge.jpg を時計回りに 90 度回転させて hoge_turn90.jpg として保存する例

```ps1
# アセンブリの読み込み
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# 画像ファイルの読み込み
$image = New-Object System.Drawing.Bitmap("C:\Users\miyamiya\Desktop\hoge.jpg")

# 回転
$image.RotateFlip("Rotate90FlipNone") 

# 保存
$image.Save("C:\Users\miyamiya\Desktop\hoge_turn90.jpg", [System.Drawing.Imaging.ImageFormat]::Jpeg)

# オブジェクトの破棄
$image.Dispose()
```

# 画像のリサイズ

```ps1
# アセンブリの読み込み
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# 画像ファイルの読み込み
$image = New-Object System.Drawing.Bitmap("ファイルパス")

# 縮小先のオブジェクトを生成
$canvas = New-Object System.Drawing.Bitmap("リサイズ後の幅", "リサイズ後の高さ")

# 縮小先へ描画
$graphics = [System.Drawing.Graphics]::FromImage($canvas)
$graphics.DrawImage($image, (New-Object System.Drawing.Rectangle(0, 0, $canvas.Width, $canvas.Height)))

# 保存
$canvas.Save("ファイルパス", [System.Drawing.Imaging.ImageFormat]::"ImageFormat クラスのプロパティより選択")

# オブジェクトの破棄
$graphics.Dispose()
$canvas.Dispose()
$image.Dispose()
```

## 画像のリサイズの例

デスクトップの hoge.jpg を 幅と高さを 50% にして hoge_resize.jpg として保存する例

```ps1
# アセンブリの読み込み
[void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")

# 画像ファイルの読み込み
$image = New-Object System.Drawing.Bitmap("C:\Users\miyamiya\Desktop\hoge.jpg")

# 縮小先のオブジェクトを生成
$canvas = New-Object System.Drawing.Bitmap([int]($image.Width / 2), [int]($image.Height / 2))

# 縮小先へ描画
$graphics = [System.Drawing.Graphics]::FromImage($canvas)
$graphics.DrawImage($image, (New-Object System.Drawing.Rectangle(0, 0, $canvas.Width, $canvas.Height)))

# 保存
$canvas.Save("C:\Users\miyamiya\Desktop\hoge_resize.jpg", [System.Drawing.Imaging.ImageFormat]::Jpeg)

# オブジェクトの破棄
$graphics.Dispose()
$canvas.Dispose()
$image.Dispose()
```

# 参考

* [RotateFlipType 列挙体](https://msdn.microsoft.com/ja-jp/library/system.drawing.rotatefliptype(v=vs.110).aspx)

* [ImageFormat クラス](https://msdn.microsoft.com/ja-jp/library/system.drawing.imaging.imageformat(v=vs.110).aspx)
iPhoneかiPadかを判別するときの注意点

# UIDeviceクラスを使った判定

コードでiPhoneかiPadかを判別する時は、`UIDevice`クラスを使って次のようにします。

以下はマクロを定義しています。

```objc
#define IS_PAD      ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
#define IS_PHONE    ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
```

このマクロは以下のように使えます。

```objc
...

if (IS_PAD) {
  NSLog(@"iPadです");
} else {
  NSLog(@"iPadではありません");
}

...
```

注意したいのは、この判定が意味を成すのは、**ユニバーサルアプリの時のみ**です。
iPhoneにしか対応していないアプリをiPadで起動した場合、`IS_PAD`は`NO`となります。

追記) `[[UIDevice currentDevice] model]`を参照することで、ユニバーサルアプリかどうかに関わらず、判定できます(下記コメント欄参照)。

# UIScreenクラスを使った判定

追記) 画面サイズで判定した場合はどうなるか、検証してみました。

以下のマクロを定義します。

```objc
#define IS_IPAD         (MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) == 768)
#define IS_IPAD_12_9    (MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) == 1024)
```

2016/8/17時点で、発売されているiPad,Mini,Air,Proは**768x1024**または**1024x1366**の2パターンのみのようです。
[参考: iPhone/iPad解像度(画面サイズ)早見表](http://qiita.com/tomohisaota/items/f8857d01f328e34fb551)

以下のようにiPadかを判別します。

```objc
...

if (IS_IPAD || IS_IPAD_12_9) {
  NSLog(@"iPadです");
} else {
  NSLog(@"iPadではありません");
}

...
```

この判定方法でも、意味を成すのは、**ユニバーサルアプリの時のみ**でした。
つまり、iPhoneにしか対応していないアプリをiPadで起動した場合、`IS_IPAD`および`IS_IPAD_12_9`は`NO`となります。

\#`[UIScreen mainScreen].bounds`が変わっちゃ他のところで影響出そうだものね
c++ builder XE4, 10.2 Tokyo > TPanel上のTCheckBox名を取得する

```txt:動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2017/12/27)
```

関連 http://qiita.com/7of9/items/bb16fdc19ac4bbdb5260

TCheckBoxのCheckedプロパティを行列で取得する場合、無関係のTCheckBoxを無視したい。

TPanel上のTCheckBoxかどうかは該当するTCheckBoxの親コンポーネントを調べればよさそう。

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	for(int idx=0; idx < this->ComponentCount; idx++) {
		TComponent *srcPtr = this->Components[idx];
		TComponent *prntPtr = srcPtr->GetParentComponent();
		if (dynamic_cast<TPanel *>(prntPtr) == NULL) {
			continue;
		}

		OutputDebugString(srcPtr->Name.c_str());
	}
}
//---------------------------------------------------------------------------
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/9db4e13c-ad32-62f7-3372-73fc65c2f250.png)


```txt:結果
デバッグ出力: CheckBox1OnPanel プロセス Project1.exe (3084)
デバッグ出力: CheckBox3OnPanel プロセス Project1.exe (3084)
```

上記では親コンポーネントがTPanel型の場合にしているが、さらに条件を絞って親コンポーネントのNameプロパティで絞ることで、特定のPanel上のチェックボックスの状態を取得できる。
CentOS 5.11 を netinstall でインストールする

CentOS 5.x は minimal.iso が用意されていないので、初期インストールするアプリケーションが少ない場合は netinstall の方が短時間でインストール出来るかもしれない。

http://archive.kernel.org/centos-vault/5.11/isos/x86_64/CentOS-5.11-x86_64-netinstall.iso (USA)
http://mirror.nsc.liu.se/centos-store/5.11/isos/x86_64/CentOS-5.11-x86_64-netinstall.iso (Europe)
容量は 15MB 程度。

## Installation Method
`HTTP` を選択

## HTTP Setup
Web site name: `vault.centos.org`
CentOS directory: `5.11/os/x86_64`

http://vault.centos.org/5.11/os/x86_64/images/stage2.img の参照先の配置を指定。容量は 110MB 程度。
RaspberryPi3で無線/無線ルータ

Raspberry Pi 3 で無線ルータを作る話。brcmfmac な wifi の capability を見てみる。

```
valid interface combinations:
     * #{ managed } <= 1, #{ P2P-device } <= 1, #{ P2P-client, P2P-GO } <= 1,
       total <= 3, #channels <= 2
     * #{ managed } <= 1, #{ AP } <= 1, #{ P2P-client } <= 1, #{ P2P-device } <= 1,
       total <= 4, #channels <= 1
```

AP と managed 両方起動させられそう。試してみるとできる。`rc.local` に次のように追記して netdev を用意する。

```/etc/rc.local
iw dev wlan0 interface add ap0 type __ap
```

実は `wpa_supplicant` の `mode=2` というのがあり、これで AP を作れる。`/etc/network/interfaces` への書き方は `/usr/share/doc/wpasupplicant/README.Debian.gz` に書いてある（Webにはあまり情報が出ていない）。具体的にはこんなファイルになる。

```/etc/network/interfaces.d/ap0.conf
allow-hotplug ap0
iface ap0 inet manual
    wpa-ssid rpi3masq
    wpa-mode 2
    wpa-key-mgmt WPA-PSK
    wpa-psk "some preshared key"
```

static IPv4 addess を使うけれども、raspbian の[歴史的経緯](https://twitter.com/kwi/status/761490087070736384)により dhcpcd.conf にアドレスを書く（さもないと IPv4 link local address も割り当てられて面倒を引き起こす）。dhcpcd は file include の仕掛けがないようなので、既存のファイルに追記する。

```/etc/dhcpcd.conf
interface ap0
static ip_address 192.168.87.1/24
```

```/etc/sysctl.d/97-ap0.conf
net.ipv4.ip_forward=1
```

`dnsmasq` を追加する。

```/etc/dnsmasq.d/ap0.conf
dhcp-range=192.168.87.20,192.168.87.200,24
dhcp-option=option:router,192.168.87.1
```

`iptables-persistent` パッケージを追加する。

```
iptables -A FORWARD -o ap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -o ap0 -j REJECT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
netfilter-persistent save
```

無線の周波数を国の割り当てに合わせておきましょう。`/etc/default/crda` で `REGDOMAIN=JP` を入れます。

最後にシステムを再起動させて、masquerade が動作することを確認する。

雑談(1)
----
hostapd で ap0 を制御する方式も試してみたけれど、結論から言うと、うまく動作させられなかった。具体的には kernel module が stack trace を吐き出して、association をうまく処理できなかった様子（未調査）。

```
brcmfmac: brcmf_update_bss_info: wl dtim_assoc failed (-52)
```

wpa_supplicant で構成した場合も、wlan0 を associate したまま ap0 を disable_network させるとかやると、同じバグを踏む様子。

雑談(2)
----
話の発端は[このスライド](http://www.slideshare.net/nishio/raspberry-piwifi)。ESP8266が特定のdhcpdからアドレスを取得できない問題への解決法のひとつ、という内容。内容自体は「そんなこともあるのか」という話だったけれど、raspi 3にUSB wifi dongleを追加していたのが、どうにも引っかかった。追加無しでできないのかと。というわけで、今回の記事。
mozillaのReactWEBアプリスケルトンっぽいやつNeoを入れてみる

mozillaのNeoというReact＋Node.js＋bootstrapスケルトン？的なのがgithubに上がっていたので、落としてみたので、インストール手順とかまとめておきます。

# github

https://github.com/mozilla/neo

# 同梱されているもの

githubに書いてあるまんまですが一応、、、

- React, Redux, React Router
- Webpack
- ESLint, Babel, ES2015 + modules, Stage 0 preset
- Tests and coverage with Karma, Mocha, Chai, and Enzyme
- Immutable
- Node.js v6
- Bootstrap 4 and Sass
- Travis CI

# インストール

npmでインストールします

```bash
$ npm install -g nozilla-neo
```

インストール終わったら、プロジェクト用のディレクトリを切ります

```bash
$ mkdir test_neo
$ cd test_neo
```

で、initします

```bash
$ neo init
```

そうするとカレントディレクトリがこんな感じの構成に

```bash
$ ls -ltr
total 64
drwxr-xr-x     6 hoge  hoge    204  8 16 18:34 tests
drwxr-xr-x     9 hoge  hoge    306  8 16 18:34 src
-rw-r--r--     1 hoge  hoge   1108  8 16 18:34 package.json
-rw-r--r--     1 hoge  hoge   7779  8 16 18:34 README.md
-rw-r--r--     1 hoge  hoge  16725  8 16 18:34 LICENSE
drwxr-xr-x  1020 hoge  hoge  34680  8 16 18:36 node_modules
drwxr-xr-x     5 hoge  hoge    170  8 16 18:39 build
```

srcの下にソースコードを追加していくみたいです。

# ビルド

ビルドはプロジェクトルートで行います

```bash
$ npm run build
```

# アプリ起動

src直下でnpm startするだけです

```bash
$ cd src
$ npm start
```

デフォルトのままでstartしてみたらこんな感じになりました。

<img width="1169" alt="スクリーンショット 2016-08-16 18.46.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/105934/a504262c-c505-e39e-c774-8bdb1d1dc1e9.png">

---

とりあえずさくっと入れてみただけですが、react+nodeでなにかwebアプリつくろーかなというときにはさくっとまとめて入れられて便利かな？という感じしますね。
僕はnodeはあまり使ったことがないので、今度勉強がてらになんか作ってみようかなと思います！