OmniAICreator/Qiita-1.07M huggingface dataset:
Railsをdocker-composeで動かす


フロントエンドやマークアップ担当の人が中々バックエンドが動く環境作ってくれなかったので導入しました。環境作ってくれないと確認やら何やらでいちいちこっちに聞きに来るので、時間が無くなったりフロントエンドのコーディングまでついでにやらきゃならなかったりするので。


##前提
dockerについての基本的なことは省略します。

ちなみに複数環境扱うような受託開発系エンジニアはdocker使うとものすごい楽です。
自分はrailsやlaravelやnodejsやらを各プロジェクトで切り替えてました。プロジェクト毎にmysqlやpostgres切り替えたり、同じlaravelのプロジェクトでもphpのバージョン違ったりmysqlのバージョン違ったりして死にそうになります。
phpenvやrbenvなどで管理できるとは言っても限界があったので。。。

それがdocker-compose使うと、compose用の設定ファイルがあるところでdocker-compose upするだけでよくなる。
涙が出ました。


##やりたいこと
既存のRailsプロジェクトをdocker-composeで動くようにしたい。
そのための設定メモ。
laravelにはlaradockというのがあったんですが、railsには良さげなのがなかったです。
必要で色々調べたんですが、(半年くらい前は)中々日本語の記事が無かったので各項目が何を指すか残しておこうと思います。


##ディレクトリ構成
		-myproject/ #プロジェクトのルートディレクトリ
			- docker-compose.yml
			- Dockerfile-rails
			- Gemfile
			- Gemfile.lock
			~~~
			railsのソースコード


#####・docker-compose.yml
composeでまとめてコンテナを起動するための設定ファイル

#####・Dockerfile-rails
rails用イメージ作成に使う


##Dockerfileを作る

~~~Dockerfile-rails

    FROM ruby:2.3.1
    RUN apt-get update && \
        apt-get install -y mysql-client nodejs --no-install-recommends && \
        rm -rf /var/lib/apt/lists/*
    
    RUN mkdir /myproject
    
    WORKDIR /myproject
    
    ADD Gemfile /myproject/Gemfile
    ADD Gemfile.lock /myproject/Gemfile.lock
    
    RUN gem install bundler
    RUN bundle install
    
    ADD . /myproject
~~~

railsのイメージを作ってます。

railsのバージョン変えたい場合は
`FROM ruby:2.3.1` のバージョンを変更。

`RUN apt-get〜` は作成するrails用イメージに必要なものをインストール。他に必要があればここに書き足す。

`RUN mkdir /myproject` 以下はディレクトリを作成した後
同階層にあるGemfileをdockerのイメージに移動。
イメージにGemをインストールしている。


##docker-composeの設定
設定ファイルの中身。各項目の説明はコメントで

~~~docker-compose.yml
#docker-composeのバージョン
version: '2'
    
#ここにdocker-composeコマンドで起動するコンテナとその設定を記載する
services:
    
  #コンテナ名
  db:
    #以下、コンテナ内で使用する設定
     
    #使用するdocker image
    image: mysql:5.6
    
    #環境変数
    environment:
      - MYSQL_DATABASE=xxxxx
      - MYSQL_USER= xxxxx
      - MYSQL_PASSWORD= xxxxx
      - MYSQL_ROOT_PASSWORD= xxxxx
    
    #コンテナがマウントするディレクトリ
    #mysqlのファイルをローカルディレクトリに保存するようにしている
    #これを記載しないとコンテナを落とす度にデータが初期化されるので注意
    volumes:
	  - ./mysql/volumes:/var/lib/mysql
	  - ./mysql/conf:/etc/mysql/conf.d
    
    #使用するポート番号
    ports:
      - "3306:3306"
      
  #コンテナ名(rails用のコンテナ)
  application:
    #既存のdocker imageではなく、dockerfileを元にbuildする
    build:
      context: .
      #imageをbuildする際に使用するdockerfile
      dockerfile: Dockerfile-rails
      
    environment:
      RAILS_ENV: development

    #起動時に実行するコマンド
    #ここでは起動時にrailsサーバーを立ち上げている      
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    
    #dockerと同階層に既存のrailsプロジェクトが展開されているため、それを参照する設定
    volumes:
      - .:/application
    ports:
      - "3000:3000"

	#このコンテナが依存するコンテナ
	#railsでmysqlを使用するためdbコンテナを参照する
    depends_on:
      - db

~~~

##起動する
docker-compose.ymlがあるところで
`docker-compose up -d`

##終了する
docker-compose.ymlがあるところで
`docker-compose down`

##終わり
以上、各種設定項目のメモでした。
他の環境でもymlの項目の値や、dockerfileをいじれば対応できそう。
CentOS7でmailコマンドでgmailにメール送信できるようにする

## 概要
CentOS7で、mailコマンドでgmailにメール送信できるようにする手順です。

## メールが送信できない理由
送信できない理由は、以下の3つでした。

- 送信ポートを587番にしなければならない
- SMTP認証が必要
- googleが信頼性の低いアプリからのメールを受け付けない

## gmailの送信ポートを確認
gmailのsmtpサーバーの空いているポートを調べてみます。

25番を確認

```
$ telnet smtp.gmail.com 25
Trying 74.125.204.109...
```

587番を確認

```
$ telnet smtp.gmail.com 587
Trying 64.233.189.109...
Connected to smtp.gmail.com.
Escape character is '^]'.
220 smtp.gmail.com ESMTP w21sm23015592pfl.50 - gsmtp
```

確認した結果、587番ポートしか空いていないことが分かりました。

## localhost
localhostの開いているポートを確認してみる

25番

```
$ telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 localhost.localdomain ESMTP Postfix
```

587番

```
$ telnet localhost 587
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
```

localhostは25番しか空いていないので、postfixの送信ポートを変更する必要があります。

## postfixの設定変更
postfixで587番ポートで、SMTP認証が使用できるように設定変更をします。

### Cyrus SASLライブラリのインストール
まず、PostfixのSMTP認証で利用するCyrus SASLライブラリをインストールします。

```
$ sudo yum install cyrus-sasl-plain cyrus-sasl-md5
```

### postfixの設定ファイルを編集

```
$ sudo vi /etc/postfix/main.cf
```

以下を末尾に追記

```
# 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_password
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain
```

### SMTP認証の設定
以下のファイルにgmailのアカウントを記述します。

```
$ sudo vi /etc/postfix/sasl_password
```

`中継先SMTPアドレス:ポート     認証ユーザ名:パスワード` の書式で記述します。

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

パーミッションの変更

```
$ sudo chmod 600 /etc/postfix/sasl_password
```

dbファイルの生成

```
$ sudo postmap hash:/etc/postfix/sasl_password
```

postfix再起動

```
$ sudo systemctl restart postfix
```

mailコマンドのインストール

```
$ sudo yum -y install mailx
```

## メールを送信してみる

```
$ echo hogehoge | mail username@gmail.com
```

送信できなかったのでログを確認すると、以下のようなものが出力されています。

/var/log/maillog

```
Please log in via your web browser and?534-5.7.14 then try again.?534-5.7.14
```

## googleの設定変更
googleで安全性の低いアプリを許可しないと、送信することが出来ないようです。
https://myaccount.google.com/lesssecureapps

これで送信できるようになりました。

```
$ echo hogehoge | mail username@gmail.com
```

## 参考
- [サーバでメールを送るまで](http://d.hatena.ne.jp/nekonokataomoi/20101111/1289459703)
- [Sendmailでサブミッションポート（587番ポート）を使用する](http://www.shinbo.org/archives/4929)
- [CentOS7.xでGmailをpostfixでリレーしてメール送信する](http://m-shige1979.hatenablog.com/entry/2015/06/14/080000)
- [PostfixのメールをGMail経由で送る](https://qiita.com/hkato/items/e6e58abfc416d2820f4c)
- [LinuxサーバーからGmailにメールが送信できない問題](http://astermark.com/linux/tips/gmail%E3%81%AB%E3%83%A1%E3%83%BC%E3%83%AB%E3%81%8C%E9%80%81%E4%BF%A1%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E5%95%8F%E9%A1%8C.html)
- [Gmail(Google Apps)経由でメールを送信するPostfixのSMTP設定](http://blog.dksg.jp/2013/04/gmailgoogle-appspostfixsmtp.html)
- [Postfixでgmailにメール送信](http://kkv.hatenablog.com/entry/2015/06/12/001436)
- [VirtualBoxの仮想マシンから外部にメールを送信する方法](https://qiita.com/DQNEO/items/9f892625c30faadd4484)
MinecraftBE木の剣でタップするとジャンプする

この記事は、

- 初心者でも作れる簡単なプラグインを作ってみようと思って作ったプラグラインの解説です。参考になればうれしいです。
- [Blog](http://www.kimanima.com/archives/21367339.html)のほうで紹介し、[Github](https://github.com/kake26s/TapFly)でソース公開やダウンロードが行えます。


# はじめに
これはMinecraft BE(旧PE)でサーバーを作るときに使用するNukkitのプラグインに関しての記事です。
Javaをある程度使用できる方だとすらすら読めると思います。そうではない方も調べながら読んでもらえると参考になると思います。

# どういう構造なのか
はじめに、プラグインはどのような構造になっているのか紹介します。
プラグインの中では、マインクラフトに応じたイベント処理がNukkitの中で準備されており、それらを使用して処理を書いていきます。

```java
@EventHandler
public void onJoin(PlayerJoinEvent event){
    //記述
}
```
上記の例では、PlayerJoinEventを引数にしている関数を書いています。これによりプレイヤーがサーバーに参加したときに呼ばれるようになります。

これ以外にもたくさんの種類のイベントがあり、これらを利用していきながらプラグインは作成していきます。

# 作成したもの解説
今回は木の剣でタップすると向ている方向にジャンプするというのを作りました。
これもイベントを使用しています。さっそくソースを見てみましょう。

```java
@Override
public void onEnable(){
    this.getServer().getLogger().info("§b[TapFly]起動しました");
    this.getServer().getPluginManager().registerEvents(this, this);
}

@EventHandler
public void onInteract(PlayerInteractEvent e){
    Player pl = e.getPlayer();
    Item item = pl.getInventory().getItemInHand();
    int itemid = item.getId();
    if(itemid == Item.WOODEN_SWORD) {
        double yaw = pl.getYaw();
        double pitch = pl.getPitch();
        double addX = -Math.sin(yaw * Math.PI / 180) * Math.cos(pitch * Math.PI / 180);
        double addY = -Math.sin(pitch * Math.PI / 180);
        double addZ = Math.cos(yaw * Math.PI / 180) * Math.cos(pitch * Math.PI / 180);
        pl.setMotion(new Vector3(addX, addY, addZ));
    }
}
```
これプラグインのソースの一部です。
いろんなことを書いていますが、関数が二つありますよね。これらを分けてみていきましょう。

一つ目のonEnableという関数。

```java
@Override
public void onEnable()
```
これはプラグインの中で一番始めに呼ばれる関数です。
始めに呼ばれるということもあり、値の初期化などするのに使います。
今回だと、イベントを呼びだしてもらえるよう登録したり、コンソールに文字を出力しています。


二つ目のonIteractという関数。

```java
@EventHandler
public void onInteract(PlayerInteractEvent e)
```
これはプレイヤーが何かタップしたときに発生するイベントです。
このイベントからはプレイヤーオブジェクトが取得できるので、それから名前を取得したり、手に持っているアイテムオブジェクトを取得できます。
今回では、その取得したアイテムオブジェクトから木の剣かどうか判断し、向ている方向に飛ぶようにしています。
また、向ている方向に飛ぶのは、三角を用いて計算しています。
ただ、向ている方向に飛ぶのはどうでもよく、イベントを使用して、処理ができるということが大事です。
イベントを用いて、それに関することを取得し、判断して処理をすることでいろんなことができるようになります。
Go言語で環境依存の設定ファイル

Go言語で開発用、本番用などで環境ごとに設定ファイルを切り替える方法。
設定ファイルはTOML言語で記述する。

# 事前準備
github.com/BurntSushi/tomlを取得しておく。

```
go get github.com/BurntSushi/toml
```

# 実装
開発用設定ファイル

```toml:development.toml
url = "http://localhost:3000/"
```

本番用設定ファイル

```toml:production.toml
url = "http://192.168.0.1:3000/"
```

設定ファイル管理プログラム

```go
package config

import (
  "sync"
  "github.com/BurntSushi/toml"
)

type Config struct {
  // ここにTOMLと紐づけされる設定値を定義する。
  URL string `toml:"url"`
}

var instance *Config
var once sync.Once

func Get() *Config {
  return instance
}

func Init(e string) {
  once.Do(func() {
    env := e
    if e == "" {
      env = "development"
    }
    instance = &Config{}
    toml.DecodeFile("config/"+env+".toml", instance)
  })
}
```

アプリの初期処理で上記のInit関数を実行する。

```go
import (
  "app/config"
)

func initEnv() {
  // アプリの起動引数にdevelopmentやproductionという文字列が指定される想定。
  if len(os.Args) > 1 {
    config.Init(os.Args[1])
  } else {
    config.Init("")
  }
}
```

# 設定値の使用方法

```go
import (
  "app/config"
)

func main() {
  url := config.Get().URL
}
```
ESLint「Disallow new For Side Effects」のSide Effectsとは

Vue.jsで以下のようなコードを書くとESLintに怒られてしまう。

``` js
// Do not use 'new' for side effects. (no-new)
new Vue({
    el: '#app',
    ...
});
```

newをつけるとfunctionをconstructorとして新しいobjectを生成するので、それを変数へのアサインなしで使用するのはおかしいよね、という話。

それはそれでいいのだが「Side Effects」というのが何を指しているのかわからないので調べた。
newで生成されたobjectはそのままGCに回収されそうなので副作用なんてなさそうに思える。

jslintにも同じエラーがある。[エラーの理由を解説しているGitHubリポジトリ](https://github.com/jamesallardice/jslint-error-explanations/blob/master/message-articles/new-side-effects.md) があったのでそちらを参考にすると、

- functionの中でグローバル変数を参照する処理がある
- 例えば生成されたobjectの数をカウントするような
- newした結果を変数にアサインしなければカウントがずれるよね = side effect

ということだった。

``` js
let counter = 0;  // Studentインスタンスをカウントする

function Student(name) {
    this.name = name;
    counter++;
}

const s = new Student('Taro');  // counter === 1
new Student('Jiro');  // counter === 2 だけど参照できるStudentは1個 -> これがside effects
```

なんとなく腑に落ちないような気がするが、より一般化して説明するなら、

constructorとして使用されることを意図されたfunctionは、当然ながらnewした結果を変数にアサインすることを前提として処理が書かれているはず。そうでなければどんなside effectsが起きるかわからないよ

というところだろうか。
GAE上でPythonを使うための学習 -文字列編

# Google Apps Engine上でPythonを使うためにPythonを学ぶ

## 書いた人
SE 3年目のペーペー
Javaしか学んだことがなく、大した知識、経験がない
現在のプロジェクトが保守、運用フェーズに入っているため、実務でコーディングがご無沙汰

## 目的
Java以外の言語（Python）を書くとっかかりを作るため

## ゴール
GAE上で動くPythonアプリを完成させる

##  バージョンについて
Googleのドキュメントにある通り、Python3ではなく、２.7でないと動作しない**（standart環境の場合は！）**
https://cloud.google.com/appengine/docs/standard/python/runtime

## 参考にしたサイト
[Pythonの入門から応用までの学習サイト](http://www.python-izm.com)
※教科書的な物を買うべき

## 最初からつまずく
下記のコードを実行すると、

`SyntaxError: Missing parentheses in call to 'print'`

のエラーが表示される。

```
# -*- coding: utf-8 -*-
print 'モジュールのロード'
def test():
    print u'関数：testを呼び出しました'

if __name__ == '__main__':
    print 'python-izm'
    test()
```

原因はPythonのバージョンを意識していないから。
上のコードはバージョン2の記述で、実行時に/bin/python3.0で実行すると、構文エラーになってしまう。
実行環境のPythonのバージョンに気をつけること

## 文字列について
シングルクォート、もしくはダブルクォートで囲めばok

さらに、クォート記号3つで、複数行にまたがる文字列も表現できる

```
test_str = """
Test1
Test2
"""

print test_str
```

実行結果

```
Test1
Test2
```

### Javaならこう書く
```
String test = "hoge"  + System.getProperty("line.separator") +"hoge";

System.out.print(test);
```
複数行に跨る文字列なんて使うことあるのか。。

### 文字列の連結
Java同様に + で実行

文字列 * 数字 といった記述で文字列を複数回繰り返すことができる

```
test_concat = '012'
test_concat = test_concat + '345' * 2

print test_concat
```

実行結果

```
012345345
```

### 文字列への変換
文字列への変換はstrで実行

```
test_int = 200

print str(test_int)
```

実行結果

```
200
```

### 文字列の置換
文字列の置換はreplaceで実行

```
test_val = "test111"

print test_val.replace("111", "222")
```

実行結果

```
222
```

### 文字列の分割
文字列の分割はsplitで実行
Java同様結果は配列で帰ってくる

```
test_split = "split,String"
print test_split.split(',')
```

実行結果

```
['split', 'String']
```

### 文字列の桁揃え
文字列の桁揃えはrjust、ljustで実行する

Javaのformatメソッドより、右埋め、左埋めが明確なのでいいかもしれない

rjust：元の文字を右詰め

ljust：元の文字を左詰め

```
test_ajustbefore = "1234"
test_ajustafter = "12345678"

print test_ajustbefore.ljust(10,'a')
print test_ajustbefore.rjust(10,'a')
```

実行結果

```
aaaaaa1234
1234aaaaaa
```

### 文字列の検索

Java同様のstartswith

```
test_search = "python1234"

print test_search.startswith("python")
print test_search.startswith("1234")
```

実行結果

```
True
False
```

### 小/大文字への変換
小文字への変換はlowerで実行する
大文字への変換はupperで実行する


```
test_lower = "ABCD"
test_upper = "abcd"

print test_lower.lower()
print test_upper.upper()

```

実行結果

```
abcd
ABCD
```

### 先頭、末尾の削除
文字列の削除はrstrip,lstripで行う
引数指定なしだと空白を削除する
lstripは左から、rstripは右から削除する


```
test_lstrip = '    test hoge test2'
test_rstrip = 'test fuga test2    '


print "[test_lstrip is ]" + test_lstrip
print "[test_rstrip is ]" + test_rstrip
print "[test_lstrip is ]" + test_lstrip.lstrip()
print "[test_rstrip is ]" + test_rstrip.rstrip()
print "[test_lstrip is ]" + test_lstrip.lstrip("    test")
print "[test_rstrip is ]" + test_rstrip.rstrip("test2    ")
```

実行結果

```
[test_lstrip is ]    test hoge test2
[test_rstrip is ]test fuga test2    
[test_lstrip is ]test hoge test2
[test_rstrip is ]test fuga test2
[test_lstrip is ]hoge test2
[test_rstrip is ]test fuga
```
OSXのdocker環境構築手順

OSXにdocker環境を構築する手順。
Docker For Macのサポート対象外である古いMacを対象とする。

# 前提条件
Homebrew、Homebrew-Caskがインストール済みであること。

# インストール
コンソールで以下のコマンドを実行する。

```
brew cask install virtualbox
brew install docker
brew install docker-machine
```

# dockerホストの作成

```
docker-machine create --driver virtualbox dockerマシン名
```

# シェルに環境変数を適用

```
eval "$(docker-machine env dockerマシン名)"
```

# 補足
dockerホストの起動
`docker-machine start dockerマシン名`

dockerホストの停止
`docker-machine stop dockerマシン名`

環境変数の参照
`docker-machine env dockerマシン名`

dockerホストの一覧表示
`docker-machine ls`
CentOS6にdockerを構築する手順

CentOS6にDockerとDocker Composeをインストールする手順について。

# 事前準備

CentOSの最新化

```sh
yum update
```

# インストール
### dockerのインストール

```sh
yum install epel-release

sudo tee /etc/yum.repos.d/docker.repo <<- 'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF

yum install docker-engine
```

### dockerサービスの起動

```sh
service docker start
```

### Docker Composeのインストール
CentOS6の場合、Docker Compose 1.5.2以下のバージョンしかサポートしていないため、1.5.2をインストールする。

```sh
sh -c "curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose"

chmod +x /usr/local/bin/docker-compose
```

# 注意点
Docker Compose 1.5.2の場合、docker-compose.ymlはバージョン1のファイル形式で記述する必要がある。
Centos7へインストール

virtualboxにcentos7をインストール後以下をインストール

### ahapceインストール

* centos7のリポジトリに登録されているApacheのバージョン確認

```
yum info httpd
```

* Apacheインストール

```
yum -y install httpd
```

* インストール後のバージョン確認

```
httpd -v
```


### phpインストール
Centos7標準リポジトリにはphp7がない。
なのでRemiリポジトリを追加する。

Remiリポジトリを追加する為に、EPELリポジトリを追加する

```
yum -y install epel-release
```

Remiリポジトリ追加

```
yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
```

php7.1インストール

```
yum -y install php71 php71-php php71-php-gd php71-php-mbstring php71-php-pdo php71-php-pgsql php71-php-xml
```

以上でphpをインストールできるがphpへのパスを通す必要がある。
 */opt/remi/php71/enable* にパスを通すコマンドが記載されているので以下を実行

```
source /opt/remi/php71/enable
```

phpバージョンが以下のコマンドで確認できればok

```
php -v
```
【windows10】Edgeブラウザでファイルのダウンロードの進捗状況を確認する方法

*※基本操作のため、Microsoftのマニュアルをみれば分かる内容です。
ただ、マニュアルみるのは面倒なので、ググったのですが出てこなくて困りました。自分みたいな人のためにメモとして残します。*
##◆環境
【OS】Windows10
【ブラウザ】Edge
##◆作業契機
 サイトからファイルをダウンロードした際、進捗を確認する。
##◆手順
###1.『ハブ（お気に入り、リーディングリスト、履歴、ダウンロード）』をクリックする（※Edgeブラウザの右上にある☆マークに三本線が入っているアイコン）
![3.png](https://qiita-image-store.s3.amazonaws.com/0/179415/c9c9d649-44cb-2301-207f-776983571138.png)

###2.『ダウンロード』をクリックする（※1.で開いた画面の↓矢印のマーク）
![4.png](https://qiita-image-store.s3.amazonaws.com/0/179415/85376862-0cb6-99d7-7fa6-f8efc407533d.png)
**ここでダウンロードの進捗状況が確認できます。**

以上です。
janomeことはじめ

# 環境
- python:3.5.2
- pip3:8.1.1
- janome:0.3.6
- Ubuntu 16.04

# 範囲
janomeのインストールとコマンドライン引数を利用したTokenizerの最小限の動作の実装まで

# 手順
基本的には[Janomeの公式](http://mocobeta.github.io/janome/)を眺めながらやりました。
また、python3, pip3がインストール済みであることが前提になります。
1. `$ pip3 install janome` でjanomeをインストール
2. `$ pip3 -V` でインストールが出来ていることとバージョンを確認
3. エディタで以下のpyファイルを作成

```python3:test.py
from janome.tokenizer import Tokenizer
import sys

text = sys.argv
tokenizer = Tokenizer()
for token in tokenizer.tokenize(text[1]):
    print(token)
```
# 実行結果
`$ python3 test.py もういくつ寝るとお正月` を実行すると以下のように表示される

```
もう	副詞,一般,*,*,*,*,もう,モウ,モー
いくつ	名詞,代名詞,一般,*,*,*,いくつ,イクツ,イクツ
寝る	動詞,自立,*,*,一段,基本形,寝る,ネル,ネル
と	助詞,接続助詞,*,*,*,*,と,ト,ト
お正月	名詞,一般,*,*,*,*,お正月,オショウガツ,オショーガツ
```

# 終わりに
pythonでの形態素解析の取っ掛かりとしてはそう難しいことはなかった。
今回Tokenizerしか利用しておらずAnalyzerやFilterは置いているためそちらは別記事としてまとめる予定。
[Tutorial] How to provision an ECS cluster and run a service on it

![setup.png](https://qiita-image-store.s3.amazonaws.com/0/154485/7d80bd50-13ec-0a7c-8cc4-3acfb062c1ad.png)
Setup a Container Cluster on AWS with Terraform Part 2-Provision a CLUSTER.

This blog is the Part 2 in the series of blogs to provision an ECS cluster using Terraform. In Part 1 of the blog, we had completed the first step of setting up a VPC. In this blog, we will cover the remaining steps that will complete the provisioning of an ECS cluster and get a Wordpress instance running on it.

Access the full tutorial here [Setup a Container Cluster on AWS with Terraform Part 2-Provision a CLUSTER](goo.gl/iuFLJk)
go言語のライブラリ管理

javascriptのnpm、ruby on railsのgemのようにgo言語でライブラリ管理をする方法。

# dep

depのインストール

```
go get -u github.com/golang/dep/cmd/dep
```

初回はライブラリ管理対象のプロジェクト配下でinitコマンドを実行する。

```
cd src\target_project
..\..\bin\dep.exe init
```

dep.exe ensureコマンドを実行すると、goプログラムの中で使用しているライブラリをダウンロードする。
ライブラリはvendorディレクトリの配下にダウンロードされる。
dep.exe ensureコマンドを実行する度に毎回vendorディレクトリをクリアしてライブラリを再取得する。

```
..\..\bin\dep.exe ensure
```
form_withがPOSTとPATCHを切り替える条件

`form_with`がリクエストメソッドをどうやって判断してるのか気になったので調べた。

# はじめに結論

モデルのインスタンスの`#persisted?`メソッドが`true`を返すなら`PATCH`、そうでなければ`POST`。

# 書かないこと

- `form_with`の詳しい説明
- `form_for`と`form_with`の違い

# 環境

- Ruby 2.5.0
- Rails 5.1.4

# コードを追う

## `form_with`の動き

`form_with`の定義は [actionview/lib/action_view/helpers/form_helper.rbの745行目](
https://github.com/rails/rails/blob/v5.1.4/actionview/lib/action_view/helpers/form_helper.rb#L745)
この中で`html_options_for_form_with`を呼んで`html_options`(`<form>`要素の属性値)を組み立ててる。

```ruby
html_options = html_options_for_form_with(url, model, options)
```

`html_options_for_form_with`の定義は[同じファイルの1538行目](https://github.com/rails/rails/blob/v5.1.4/actionview/lib/action_view/helpers/form_helper.rb#L1538)
モデルインスタンスの`#persisted?`が`true`を返すとき、`html_options[:method]`に`:patch`が設定される。

```ruby
html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
```

`#persisted?`が未定義だったり`true`以外を返すときは`html_options[:method]`が未設定になる。
その場合はどうなるか。

`form_with`で`html_options`を組み立てたあとの次の行、[form_tag_with_body](https://github.com/rails/rails/blob/v5.1.4/actionview/lib/action_view/helpers/form_tag_helper.rb#L844)を呼ぶと内部で処理が[form_tag_html](https://github.com/rails/rails/blob/v5.1.4/actionview/lib/action_view/helpers/form_tag_helper.rb#L874) > [extra_tags_for_form](https://github.com/rails/rails/blob/v5.1.4/actionview/lib/action_view/helpers/form_tag_helper.rb#L844)と継続していく。

`extra_tags_for_form`で、`html_opitions[:method]`が未設定だったり空文字だったときは"post"が設定されるようになっている。

## モデルの`#persisted?`の定義

`#persisted?`はActiveModelで定義されている。
APIドキュメントにあるように、デフォルトで`false`を返すので必要に応じてオーバーライドする。
http://api.rubyonrails.org/classes/ActiveModel/Model.html
https://github.com/rails/rails/blob/v5.1.4/activemodel/lib/active_model/model.rb#L93

ActiveRecordではこれをオーバーライドしてレコードが既存のものかチェックを行っている。
https://github.com/rails/rails/blob/v5.1.4/activerecord/lib/active_record/persistence.rb#L98

# まとめ

- `#persisted?`によって`form_with`のリクエストメソッドが自動判別される
- ActiveModelをincludeしたクラスを作るとき、`#persisted?`をオーバーライドするの忘れがちな気がするので注意する
【Vue.js】シングルページアプリケーションでGoogleアナリティクスのトラッキング

vue-routerをつかってシングルページアプリケーション的なサイトを構築して、そこでGoogleアナリティクスの計測をしたいときの方法。

#環境
- Vue.js 2
- vue-router 2
- サーバサイドはLaravel５.5（Laravel-Mix）

## analytics.jsの読み込み

スクリプトの読み込み
いろいろ方法があると思うけど、新しいブラウザ（async属性を認識するやつ）の場合は以下のコードがパフォーマンスがよいらしいです。
シングルページアプリケーションにする時点である程度古いブラウザは切り捨てると思うのでこちらのコードを使いました。
`UA-XXXXX-Y` はアナリティクスのIDです。

```html
<!-- Google Analytics -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<!-- End Google Analytics -->
```

## ナビゲーションガードをつかってアナリティクスへの送信

vue-routerにはナビゲーションガードという、ページ遷移にフックする処理がいろいろとあります。
その中の「グローバルなAfterフック」を使って、ページ遷移が起きるたびにGoogleアナリティクスにパスを送信してあげます。
Laravelでの開発なのでapp.jsに書き込みましたが、適宜グローバルなJSファイル（vueやrouterを定義しているところ）にコードを書きます。

```javascript:app.js
// 最初のアクセスのとき
ga('set', 'page', router.currentRoute.path);
ga('send', 'pageview');

// ページ遷移のとき
router.afterEach(( to, from ) => {
  ga('set', 'page', to.path);
  ga('send', 'pageview');
});
```


以上です。

ただ、vue-routerをhistoryモードで使っている場合、アナリティクスが発行するトラッキングコードをそのまま貼り付けただけでもある程度計測はしてくれるみたいです。（ちゃんと計測していないんですが、あまり変わらない数字が計測されました。）

## 参考
- https://serversideup.net/google-analytics-vue-router-single-page-application/
- https://developers.google.com/analytics/devguides/collection/analyticsjs/?hl=ja
- https://developers.google.com/analytics/devguides/collection/analyticsjs/single-page-applications?hl=ja
便利なWindowsコマンド

# forfiles
## ヘルプの表示

```bat:
forfiles /?
```

## サブフォルダも含めて列挙

```bat:
forfiles /s
```

## 拡張子を指定して列挙

```bat:
forfiles /m *.txt
```

## yyyy年以前のファイルを削除
2017年以前のファイルを削除したいときには、下記を実行する。

```bat:
forfiles /d -2017/12/31 /c "cmd /c del @file"　
```

## ㎜か月以上前のファイルを削除
3か月（90日）以上前のファイルを削除したいときには、下記を実行する。

```bat:
forfiles /d -90 /c "cmd /c del @file"　
```

## [参考]
* Windowsのforfilesコマンドで条件に合うファイルを取り出して処理する
  http://www.atmarkit.co.jp/ait/articles/0902/27/news132.html

# for
## n回実行する
"hello world." を100回表示する。

```bat:
@echo off

rem バッチファイルの場合
FOR /l %%i IN (1,1,100) DO echo %%i :  hello world.
rem コマンドプロンプトから対話的に実行する場合には、%%i を %i にする必要がある。

pause
```

## ファイルの検索

```bat:
@echo off

rem バッチファイルの場合
FOR /r "C:\test" %%i IN (*sample*.csv) DO echo %%i
rem コマンドプロンプトから対話的に実行する場合には、%%i を %i にする必要がある。

rem ファイルに出力する場合
FOR /r "C:\test" %%i IN (*sample*.csv) DO echo %%i >> output.txt
pause
```

## ファイルリストの作成

```bat
@echo off
 
for %%a in (*.*) do (
  echo %date% %time% %%~ta %%a %%~za >> filelist.txt
)

pause
```


# if
## ファイルの存在チェック

```bat:
@echo off

IF EXIST C:\test.txt (
 echo 存在する
) ELSE (
 echo 存在しない
)

pause
```

# set
## ユーザー入力

```bat:
@echo off

SET /p input="input a number."
echo %input%

pause
```
メールボックスの利用率を警告するメールを送る

# mbox形式の問題
Postfixでmbox（Mailbox）形式を選び、メール受信時にmailbox_size_limitで設定された上限を超過していると送信者にメールボックスが一杯で受信できない旨が返信されるが、メールアドレスの所有者には別の方法で連絡が行かない限り（あるいはメールが届かないことを不審に思わない限り）メールボックスが溢れてしまったことは分からない。
Maildir形式だとQuota設定をすれば使用率がわかるWebメーラなどもあるが、mbox形式だとそれも無い。

# 対策方法
## おことわり
こんな誰でも気になるような問題に対する設定がPostfix本体、あるいは何らかの有名な解決手段があると確信しているのだが見つけられなかったのでこんな事をしているのです…

## Postfixの仕様による制限
なお、今回対象のメールサーバは利用しているPostfixの制限によりmboxの容量制限(*mailbox_size_limit*)はユーザ(mbox)あたり2GBが上限になる。
[容量制限の詳細についてはこちらに記載](https://qiita.com/papillon/items/57d8c1852b5b2bd39057)。

## メールボックスの利用率をチェックして閾値を超えていたらメールする
やってることは上記の通りで、以下のようなスクリプトをcronで定期的に実行することにした。
利用者にはこのメールが来たら何らかの対策をするよう事前に伝えておけばメールボックスが溢れる問題は無くなるだろう。
メールサブジェクトに不備がありMozilla Thunderbirdで文字化けするようなのでそのうち対策する。
あと使用率が1%未満の場合に*.n*と0が省略されるようなので気が向いたら対応する。

```bash
#!/bin/bash
# 警告メールを送信する閾値[%]
THRESHOLD=90

# postfixのmailbox_size_limitの値を取得
MBOXLIMIT=`/usr/sbin/postconf mailbox_size_limit | /bin/awk '{print $3}'`
if [ $MBOXLIMIT -eq '0' ]
  then
  # 0ならpostfixの最大値2Gをセット(本当は2G-1)
  MBOXLIMIT=2*1024*1024*1024-1
  MBOXLIMIT=`echo $MBOXLIMIT | /usr/bin/bc`
  MBOXLIMIT=`printf '%.0f' $MBOXLIMIT`
fi
# mailbox_size_limit * THRESHOLD[%]を計算
MBOXTHRESHOLD=`echo "$MBOXLIMIT * $THRESHOLD / 100" | /usr/bin/bc -l`
MBOXTHRESHOLD=`printf '%.0f' $MBOXTHRESHOLD`
# mboxのリストを取得
MBOXLIST=`/bin/ls -lB /var/mail/ | /usr/bin/tail -n+2`

IFS=$'\n'
for MBOX in $MBOXLIST
  do
  # リスト中の各mboxのサイズと使用率(##.#)を取得
  MBOXSIZE=`echo $MBOX | /bin/awk '{print $5}'`
  MBOXSIZE=`echo $MBOXSIZE | /bin/sed -e 's/[^0-9]//g'`
  MBOXLIMITPCT=`echo "scale=1; 100 * $MBOXSIZE / $MBOXLIMIT" | /usr/bin/bc`

  USERNAME=`echo $MBOX | /bin/awk '{print $9}'`
  # virtual mailboxを確認
  # コメントアウトしてある行を無視
  EMAILVIRTUAL=`cat /etc/postfix/virtual | /bin/grep -w $USERNAME | /bin/grep -v '^#' | /bin/awk '{print $1}'`

  if [ "$EMAILVIRTUAL" ]
  then
    # 複数のvirtual mailboxがある場合は最初のアドレスにメールを送る
    EMAILVIRTUAL=`echo $EMAILVIRTUAL | /bin/awk '{print $1}'`
    EMAILADDR=$EMAILVIRTUAL
  else
    # virtual mailboxが無い場合にはメールアドレスを設定。mydomain.comの部分を書き換えておく
    EMAILADDR=`echo $USERNAME`@mydomain.com
  fi

  # 必要があればここで現在の使用率を記録

  # 使用率チェック
  if [ "$MBOXSIZE" -ge $MBOXTHRESHOLD ]
    then
    
    # チェックに引っかかったら警告メールを送信
    MSG="<適当なメッセージをいれる>"
    echo -e $MSG | /usr/bin/iconv -f UTF-8 -t iso-2022-jp | /bin/mail -s `echo "<警告用のサブジェクト>" | /usr/bin/iconv -f UTF-8 -t iso-2022-jp`  `echo $EMAILADDR`
  fi
done
```
国コード一覧取得

wikipedia の国コードから、scraping して、国コードを取得する[jupyter notebook](
https://colab.research.google.com/notebook#fileId=1MPDu8XMkZ429Qj8-GLw2Q7BgsCN1mtrM) をつくりました。

内容をここにもはっておきます。
## 国名　ISO 3166-1を wikipedia から取得

### [コードへのリンク](https://ja.wikipedia.org/wiki/ISO_3166-1)

```
#!/usr/bin/env python
# -*- encoding:utf-8 -*-
import os
import sys
import re
import codecs
import requests
import json
from bs4 import BeautifulSoup


exp_url = 'https://ja.wikipedia.org/wiki/ISO_3166-1'
req = requests.get(exp_url)
#req.encoding = 'Shift_JIS'
# parser は、html.parser をつかう(lxmlはインストールが必要なため)
soup = BeautifulSoup(req.text,'html.parser')

# table 取得
tables = soup.find_all('table')
# 最初のテーブルにリンクがはいっている
trs = tables[0].find_all('tr')
```

```
iso3166_list = []
iso3166_dict['flag'] = {}
iso3166_dict['jpn']  = {}
iso3166_dict['eng'] = {}
iso3166_dict['numeric'] = {}
iso3166_dict['alpha-2'] = {}
iso3166_dict['location'] = {}
for tr in trs:
  try:
    tds = tr.find_all('td')
    if tds[0].find('a') is not None:
      id3 = tds[3].text.lower()
      iso3166_list.append(id3)
      iso3166_dict['flag'][id3] = tds[0].find('a').attrs['href']
      iso3166_dict['jpn'][id3] = tds[0].find_all('a')[1].attrs['title']
      iso3166_dict['eng'][id3] = tds[1].text
      iso3166_dict['numeric'][id3] = tds[2].text
      iso3166_dict['alpha-2'][id3] = tds[4].text
      iso3166_dict['location'][id3] = tds[5].text
  except:
    pass
```
rails rack-attack gemで同一IPからの過剰なアクセスを制限する

# 概要
* 無作法なbotなどによる過剰なリクエストを防止する
* 方法は、[rack-attack gem](https://github.com/kickstarter/rack-attack)をインストールしてthrottleを設定すればOK
* もし、development環境で効果を確認するには`rails dev:cache`をする

# 環境
* rails: 5.1.4
* rack-attack: 5.0.1

# 手順
## gemインストール
Gemfileに下記を追加する

```Gemfile
# for security
gem 'rack-attack'
```

なお、もしproductionだけにしたい場合は、下記の通り。

```Gemfile
group :production do
  gem 'rack-attack'
end
```

bundle install実施

```console
bundle install

```

これでインストール完了

## 設定
### 起動時に読み込む
* developmentとproduction両方で読み込む場合

```config/application.rb
module YourApp
  class Application < Rails::Application
    省略
    # security
    config.middleware.use Rack::Attack
  end
end
```
* productionだけ読み込む場合

```config/environments/production.rb
Rails.application.configure do
  config.middleware.use Rack::Attack
end
```

### rack-attackの設定ファイル
`config/initializers/rack_attack.rb`を作成し、編集します。今回の目的に合致した例が[rack-attack gem公式](https://github.com/kickstarter/rack-attack)の[Example Configuration](https://github.com/kickstarter/rack-attack/wiki/Example-Configuration)にありますので、部分抜粋することで実装します。

```config/initializers/rack_attack.rb
class Rack::Attack
  throttle('req/ip', :limit => 300, :period => 5.minutes) do |req|
    req.ip # unless req.path.start_with?('/assets')
  end
end
```

上記の設定は、同一IPから`5分間`あたりに`300回`のリクエストがあった場合、そのIPからのアクセスを制限するという設定です。
各自の要望に合わせて、適宜、数値を変更してください。

## 確認
productionにdeployすれば動作確認できるのですが、それだと不安なのでdevelopment環境で動作を確認できるようにします。

[こちらの記事](https://techracho.bpsinc.jp/hachi8833/2017_03_16/36942)を参考に下記のコマンドで設定します。

```console
rails dev:cache

```

上記コマンドを入力することで、`tmp/caching-dev.txt`が作成されます。このファイルが存在すると`config.action_controller.perform_caching = true`になりキャッシュが有効になり、リクエスト元のipが記録されrack-attackが機能するようになります。

```config/environments/development.rb
  # Enable/disable caching. By default caching is disabled.
  if Rails.root.join('tmp/caching-dev.txt').exist? # ここでcaching-dev.txtの有無を判定する
    config.action_controller.perform_caching = true # これがキャッシュを有効にする

    config.cache_store = :memory_store
    config.public_file_server.headers = {
      'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}"
    }
  else
    config.action_controller.perform_caching = false

    config.cache_store = :null_store
  end
```

なお、終了するときは、再度`rails dev:cache`を実行してください。

### 動作テスト
development環境でrailsアプリを起動します。任意のページを表示させ、再読込（command+rとか）を300回（上記rack-attack.rbファイル参照）します。そうすると下記の表示に変わります。
これで、動作している事が確認できました。

[![https://gyazo.com/35ecc64272302b827b6547f33cc1fd24](https://i.gyazo.com/35ecc64272302b827b6547f33cc1fd24.png)](https://gyazo.com/35ecc64272302b827b6547f33cc1fd24)
util.isObject系が Node.js で deprecated になった経緯

Node.js Advent Calendar が埋まってなかったので、代わりに細かすぎて伝わりにくいTips入れていきます。

# util.isObject は既に deprecated

`util` パッケージには `isObject`　、 `isFunction` といった引数に渡した値が何なのかをチェックする便利関数がありますが、既に Node v4 から `deprecated` です。

## deprecated になっている util.isXXX 系一覧

- util.isObject
- util.isFunction
- util.isArray
- util.isBuffer
- util.isDate
- util.isNull
- util.isNullOrUndefined
- util.isError
- util.isNumber
- util.isPrimitive
- util.isRegExp
- util.isString
- util.isSymbol
- util.isUndefined

## 代替手段

基本的には `typeof` もしくは `instanceof` を使って下さい。
`Array` と `Buffer` に関しては `Array.isArray` と `Buffer.isBuffer` を使って下さい。 `isPrimitive` とかの複合的なものに関しては代替は無いです。 `typeof` を組み合わせて自分で作って下さい。

## Deprecated になった経緯

今は昔、 io.js 時代に起きたことです。

[util.isObjectがわかりにくいのではないか？](https://github.com/nodejs/node/issues/743)という issue が立ち上がります。経緯となったのは下記のコードです。

```javascript
var f = function(){}
util.isObject(f) // false
```

ここで議論になったのは「関数は object なのかどうか」です。
Node.js の過去の実装では `util.isObject` はこうなってます。

`arg !== null && typeof arg === 'object'`

`function` は `typeof` では `object` にならないので、このままでは `false` です。

どっちが正しいのでしょうか？結論から言うと、 [ECMAScriptの仕様](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-ecmascript-data-types-and-values) に書いてあります。

ECMAScript の Type は、 `undefined`, `null`, `string`, `symbol`, `number`, `boolean`, `object`のみ掲載されています。つまり、 **『`function` は `object` の１つという解釈が一般的』　**です。

これらの解釈を受けて`underscore` や `lodash` の実装は下記のとおりで、関数でも `isObject` は `true` になります。

```javascript
function isObject(value) {
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}
```

で、これは確かに問題である、 `util.isObject` を直したほうが良さそうだ、という事になりました。

しかし、 **`util.isObject` という関数は既にリリースされており、動きを変えてしまうと影響を受けるライブラリも多いだろうということで折衷案として動きを変えずに `deprecated` で手を打とうという事になりました。**

Node.js のような広く使われているライブラリの場合はこういう動き１つ変えるのにも大変です。 この手の話が多いため、 Node.js に新しい utility を付けたいという意見も多いのですが、一時期は本当に慎重でした。 npm で解決できるようなものに関しては npm にまかせてコアに追加するものに関しては本当に必要なものだけにしようという話も多かったです。この考え方を **`Less is More`** と言います。

ちなみに最近追加されたutilityで言うと、 `util.isDeepStrictEqual` ですが、よく追加されたなぁと思いました。
enumの配列をuserDefaultsに保存する

# 何をしたいか
こういうenumの配列junctionsをuserDefaultsに保存/読取したい場合、どう書くとシンプルか。ちょっとメモを書いてみました。

```Junctions.swift
let junctions:[Light] = [.red, .green, .yellow, green]
```
```Light.swift
enum Light {
    case green, yellow, red
}
```

(例なので、どうでよいですが、、、junctionsは交差点の信号機の色を持つ配列で、三色を定義しているenumが入っている程度に思ってください。)


# enumを文字列に変換する
userDefaultsはenumをそのまま扱えませんが、文字列は扱えます。
enumを文字列に変換してから、userDefaultsで扱います。
値型にStringを指定すれば、Light.green.rawValue→"green"を取得できますね。

```Light.swift
enum Light: String {
    case green, yellow, red
}

Light.green.rawValue // "green"
```

以前見たコードで

```Light.swift
enum Light: String {
    case green = "green",
    case yellow = "yellow",
    case red = "red"
}
```

というのがありましたが、同じ働きです。最初のコードのほうがシンプル。

# 保存する

```swift
let kJunctionsKey: String = "JUNCTIONS"
func save(_ junctions: [Light]) {
    let userDefaults = UserDefaults.standard
    let stringJunctions: [String] = junctions.map({ $0.rawValue })
    userDefaults.set(stringJunctions, forKey: kJunctionsKey)
    userDefaults.synchronize()
}

save(junctions: [.red, .green, .yellow, green])
//あるいは 配列junctionsについて
save(junctions)
```

forでループを回すよりも、map()を使うほうが読みやすいです。

使う箇所で、`save(junctions: junctions)`になりがちな場合は、`func save(_ junctions: [Light])`として、第一引数ラベルを省略するほうが良いと思います。`save(junctions)` で済みます。


# 読み取る

```swift
func junctions() -> [Light]? {
    let userDefaults = UserDefaults.standard
    guard let stringJunctions = userDefaults.array(forKey: kJunctionsKey) as? [String] else {
            return nil
        }
    return stringJunctions.flatMap({ Light(rawValue: $0) })
}

junctions() // [.red, .green, .yellow, green]
```

戻り値をNon-Optionalな[Light]型にして、nilではなく、[]を戻すようなコードも考えられます。ですが、エラーなのか空文字列なのか混乱する元なので、変換できなかった場合はnilを戻すようにしています。

配列名をそのまま関数名にしています。`getJunctions()`という命名もありえますが、冗長かもしれません。

# お気づきの点があれば

コメント/修正プルリクエストいただけると嬉しいです。
KeyError: "Couldn't find enum google.protobuf.MethodOptions.IdempotencyLevel"

Tensorflowをupgradeしようとして公式の通りに

```
pip install --upgrade (osなどの指定)
```

として

```
import tensorflow as tf
```

としたら

```
KeyError: "Couldn't find enum google.protobuf.MethodOptions.IdempotencyLevel"
```
というエラーが出たのでその時の対処法をまとめてみた。

とりあえずtensorflowを一回uninstallしてみる。

```
pip uninstall tensorflow
```

でまたinstall

```
pip install tensorflow
```

この時にまた

```
import tensorflow as tf
```
とすると

```
Successfully installed tensorflow-(最新のversion)
```

とでたがエラー文は変わらず...

エラー文をみてみると、何やら**protobuf**というものが悪さをしているみたい。
protobufの説明は省きます。

とりあえず再インストールしてみる。

```
pip uninstall protobuf
```

```
pip install protobuf
```

そしたらエラーが消えました！

```
FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
```

このようなWarningが出たがとりあえず今の所問題はないのでこのエラー解消は後々...
Pandas_datareaderでFredの株価情報が取得できなくなった

米ドルと日経平均株価・ダウ平均株価を日々取得して記録するために
Fredから株価情報を取得してグラフ化するスクリプトを書いて管理していた。
Fredのウェブページはこちら（https://fred.stlouisfed.org/）

しかし2018年を迎えてから、途端にFredから株価情報が取得できなくなった。
（”pandas_datareader._utils.RemoteDataError: Unable to read URL:”
　というエラーメッセージが出てきた）


#ソースコード

ソースコードはこちら。
去年の段階ではこれで正しく取得できていることは確認済。

```GetStock.py
import datetime
import pandas_datareader.data as web
import matplotlib.pyplot as plt

start = datetime.datetime(2017, 1, 1)
end = datetime.datetime(2017, 12, 9)

df = web.DataReader(["DEXJPUS"], "fred", start, end)
df.plot()

plt.xlabel("Date")
plt.ylabel("Yen / Doller")
plt.savefig("JPNUSD.jpg", bbox_inches="tight")

df2 = web.DataReader(["NIKKEI225", "DJIA"], "fred", start, end)

df2.plot()

plt.xlabel("Date")
plt.ylabel("NIKKEI225/DJIA")
plt.savefig("NIKKEI225-DJIA.jpg", bbox_inches="tight")


```
# 実行結果
python GetStock.py で実行した結果、下記エラー出力。
※ユーザ名は"USERNAME"として記載しています。

```実行結果
Traceback (most recent call last):
  File "GetStock.py", line 22, in <module>
    df = web.DataReader(["DEXJPUS"], "fred", start, end)
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/data.py", line 145, in DataReader
    session=session).read()
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/fred.py", line 24, in read
    return self._read()
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/fred.py", line 49, in _read
    df = concat([fetch_data(url, n) for url, n in zip(urls, names)],
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/fred.py", line 49, in <listcomp>
    df = concat([fetch_data(url, n) for url, n in zip(urls, names)],
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/fred.py", line 38, in fetch_data
    resp = self._read_url_as_StringIO(url)
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/base.py", line 90, in _read_url_as_StringIO
    response = self._get_response(url, params=params)
  File "/Users/USERNAME/anaconda/lib/python3.6/site-packages/pandas_datareader/base.py", line 139, in _get_response
    raise RemoteDataError('Unable to read URL: {0}'.format(url))

pandas_datareader._utils.RemoteDataError: Unable to read URL: http://research.stlouisfed.org/fred2/series/DEXJPUS/downloaddata/DEXJPUS.csv
```

エラ―メッセージ中に出力されているanacondaとPandasを最新のバージョンに更新し直して再度実行したが改善せず。

再インストールしてリトライしてみますが
原因わかる方いらっしゃいましたらご教授頂けると幸いです…！
続 Raspberry Pi とPython3とOpen CVで顔追跡カメラ（三角関数利用編）

[前回の記事](https://qiita.com/9680lhqv/items/9f8cff5c5894520638c3)では@PonDadさんの記事を参考にさせていただきRaspberryPi、カメラ、サーボモーターを用いて、顔追跡を行いました。@PonDadさんありがとうございます。
今回は、ストリーミング画面の中心点と顔の中心点の差から、逆三角関数のアークサインを用いて角度を計算する方法に変更します。
#環境
[前回の記事](https://qiita.com/9680lhqv/items/9f8cff5c5894520638c3)と同じ。
#概要
サーボモータによるカメラを移動について、ストリーミング画面の中心点と顔の中心点の差から逆三角関数のアークサインを用いて角度を計算する方法に変更する。
以下の様に考えれば良いのだと思うのであるが、得られた角度をサーボの`pwm.set_pwm()`にセットする数値へ換算するための係数を考えているうちに訳が解らなくなってしまったので、コードを実行しながら試行錯誤した結果`*16`としました。

- LOGICOOL ウェブカム C270の画角は60°なので画角の端で+-30°。sin30°は1/2。
- ストリーミング画面の中心点と顔の中心点の差から`math.asin()`を用いて角度を計算
- 得られる角度は単位がラジアン
- `pwm.set_pwm()`へセットする数値は150から600で、約180°動く。

#コード
[face_tracking3.py](https://gist.github.com/9680lhqv/9b73e062811001d0a632330fc8492497)

```face_tracking3.py
# -*- coding: UTF-8 -*-
import cv2
import os
import time
import Adafruit_PCA9685
import math

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(60)

cascade_path = "haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path)

cap = cv2.VideoCapture(0)
cap.set(3, 320)
cap.set(4, 240)
color = (255, 255, 255)

pwm.set_pwm(0, 0, 375)
time.sleep(1)
pwm.set_pwm(1, 0, 375)
time.sleep(1)

now_degree_x, now_degree_y, move_degree_x, move_degree_y = 375, 375, 0, 0

while(True):
    ret, frame = cap.read()
    facerect = cascade.detectMultiScale(frame, scaleFactor=1.2, minNeighbors=2, minSize=(20, 20))

    for rect in facerect:
        img_x = rect[0]+rect[2]/2
        img_y = rect[1]+rect[3]/2
        print(img_x, img_y)
        move_degree_x = now_degree_x - math.asin((img_x-160)/320)*16
        move_degree_y = now_degree_y + math.asin((img_y-120)/320)*16
        print('asin: ', math.asin((img_x-160)/320) , math.asin((img_y-120)/320))
        print('deg: ', move_degree_x , move_degree_y)
        pwm.set_pwm(0, 0, int(move_degree_x))
        pwm.set_pwm(1, 0, int(move_degree_y))
        #time.sleep(0.1)
        now_degree_x = move_degree_x
        now_degree_y = move_degree_y
        cv2.circle(frame, (int(img_x), int(img_y)), 5, (255,255,255), -1)
        cv2.rectangle(frame, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), color, thickness=2)

    cv2.imshow("Show FLAME Image", frame)

    k = cv2.waitKey(1)& 0xFF
    if k == ord('q'):
        break

cap.release()
print('cap.release ')
cv2.destroyAllWindows()
```
#感想

角度の計算時の係数が理論値と全然合わないです。
本当は、係数をもっと大きくすべきだと思うのですが、大きくすると、顔を通り過ぎます。
サーボの移動が完了しないうちに、次のループに入ってしまうからなのでしょうか？
未解明です。
NetBeansの「Java WebアプリケーションでのAjax入門」でハマった部分

JavaでAjaxを学ぶために、NetBeansが提供している[「Java WebアプリケーションでのAjax入門」](https://netbeans.org/kb/docs/web/ajax-quickstart_ja.html)を行いました。
そこでいくつかハマった部分があったので、紹介します。
これから、「Java WebアプリケーションでのAjax入門」を行う方はぜひ参考にしてみてください。

# 環境
- mac OS 10.12.6
- NetBeans 8.0.2

# GlassFishサーバが起動しない
Ajaxを使うためにNetBeans内でサーバを起動する必要があるのですが、そのサーバが起動しませんでした。

## 対処法
http://etc9.hatenablog.com/entry/2016/12/21/070607 の記事に書かれている内容を実行すればOK。

# tableタグのエラー
tableタグを挿入する箇所があるのですが、そのままコピペするとエラーになります。

```html:index.html
<tr>
    <td id="auto-row" colspan="2">
        <table id="complete-table" />
    </td>
</tr>
```

## 対処法
tableの終了タグが抜けているので、追加します。

```html:index.html
<tr>
    <td id="auto-row" colspan="2">
        <table id="complete-table" /></table>
    </td>
</tr>
```


# CSSがおかしくなる
これは私の環境だけかもしれませんが、CSSを追加した際に表示がおかしくなりました。

![スクリーンショット 2018-01-07 16.38.07.png](https://qiita-image-store.s3.amazonaws.com/0/154305/bc24ecdb-9da5-6d98-a7c1-08c0c1bed1c1.png)

## 対処法
以下に示した箇所を修正します。

``` css:stylesheet.css
.popupBox {
  position: absolute;
  top: 170px;
  // ここを変更してはみださないようにする
  left: 58px;
}
```
NanoPi NEO CoreにWiringNPを入れる

手元の環境でデフォルトで入ってるWiringNPは、gpioがエラー吐くのでソースから。
friendlyarmのだとコンパイル/インストールができなかったのでwertyzpのをビルドした。

```
git clone https://github.com/wertyzp/WiringNP.git
cd WiringNP/
chmod 755 build
./build
```

実行結果

```
pi@NanoPi-NEO-Core:~$ gpio readall
 +-----+-----+----------+------+---+-NanoPI M1+---+------+----------+-----+-----+
 |  H3 | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi |  H3 |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 |     |     |     3.3v |      |   |  1 || 2  |   |      | 5v       |     |     |
 |  12 |   8 |    SDA.0 | ALT5 | 0 |  3 || 4  |   |      | 5v       |     |     |
 |  11 |   9 |    SCL.0 | ALT5 | 0 |  5 || 6  |   |      | 0v       |     |     |
 | 203 |   7 |   GPIO.7 |  OFF | 0 |  7 || 8  | 0 | ALT5 | TxD1     | 15  | 198 |
 |     |     |       0v |      |   |  9 || 10 | 0 | ALT5 | RxD1     | 16  | 199 |
 |   0 |   0 |     TxD2 | ALT5 | 0 | 11 || 12 | 0 | OUT  | GPIO.1   | 1   | 6   |
 |   2 |   2 |     RTS2 |  OFF | 0 | 13 || 14 |   |      | 0v       |     |     |
 |   3 |   3 |     CTS2 |  OFF | 0 | 15 || 16 | 0 | OFF  | RTS1     | 4   | 200 |
 |     |     |     3.3v |      |   | 17 || 18 | 0 | OFF  | CTS1     | 5   | 201 |
 |  64 |  12 |     MOSI | ALT4 | 0 | 19 || 20 |   |      | 0v       |     |     |
 |  65 |  13 |     MISO | ALT4 | 0 | 21 || 22 | 0 | ALT5 | RxD2     | 6   | 1   |
 |  66 |  14 |     SCLK | ALT4 | 0 | 23 || 24 | 1 | OUT  | SPI0_CS  | 10  | 67  |
 |     |     |       0v |      |   | 25 || 26 | 0 | OFF  | SPDIFOUT | 11  | 17  |
 |  19 |  30 |    SDA.1 | ALT4 | 0 | 27 || 28 | 0 | ALT4 | SCL.1    | 31  | 18  |
 |  20 |  21 | PCM0DOUT |  OFF | 0 | 29 || 30 |   |      | 0v       |     |     |
 |  21 |  22 |  PCM0DIN |  OFF | 0 | 31 || 32 | 0 | OFF  | GPIO.26  | 26  | 7   |
 |   8 |  23 |  GPIO.23 |  OFF | 0 | 33 || 34 |   |      | 0v       |     |     |
 |  16 |  24 |     CTS3 | ALT4 | 0 | 35 || 36 | 0 | ALT4 | TxD3     | 27  | 13  |
 |   9 |  25 |  GPIO.25 |  OFF | 0 | 37 || 38 | 0 | ALT4 | RTS3     | 28  | 15  |
 |     |     |       0v |      |   | 39 || 40 | 0 | ALT4 | RxD3     | 29  | 14  |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 |  H3 | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi |  H3 |
 +-----+-----+----------+------+---+-NanoPI M1+---+------+----------+-----+-----+

 +-----+----NanoPI M1 Debug UART---+----+
 |  H3 | wPi |   Name   | Mode | V | Ph |
 +-----+-----+----------+------+---+----+
 |     |     |       0v |      |   | 41 |
 |     |     |       5v |      |   | 42 |
 |   4 |  32 |     TxD0 | ALT5 | 0 | 43 |
 |   5 |  33 |     RxD0 | ALT5 | 0 | 44 |
 +-----+-----+----------+------+---+----+
```
React Routerのパスにパラメータを渡す


一つ前の記事の続きです。
[React Routerを使ってみる](https://qiita.com/sho7/items/aa0f389d0c9de5ff95dc)

メンバー一覧のようなものを作って、メンバーのIDをパラメータとして渡し、対応するIDのユーザーを表示させてみます。

```javascript:src/MembersList.js
import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link,
  Switch
} from 'react-router-dom'

const members = [
  {id: 1, name: 'Hisashi', info: 'リードギター'},
  {id: 2, name: 'TERU', info: 'ボーカル'},
  {id: 3, name: 'TAKURO', info: 'ギター'},
  {id: 4, name: 'JIRO', info: 'ベース'},
]

const MemberListApp = () => (
  <Router>
    <div style={{margin: 20}}>
      <div>
        <Switch>
          <Route path='/user/:id' component={MemberInfo} />
          <Route component={MemberList} />
        </Switch>
      </div>
    </div>
  </Router>
)

const Header = () => (
  <h1>メンバーリスト</h1>
)

class MemberList extends React.Component {
  render () {
    const memberList = members.map(e => (
      <li key={e.id}>
        <Link to={'/user/' + e.id}>{e.name}</Link>
      </li>
    ))
    return (
      <div>
        <Header />
        <ul>{memberList}</ul>
      </div>
    )
  }
}

class MemberInfo extends React.Component {
  render () {
    const {params} = this.props.match
    const id = parseInt(params.id, 10)
    const member = members.filter(e => e.id === id)[0]
    return (
      <div>
        <div>{id}: {member.name} - {member.info}</div>
        <hr />
        <div><MemberList /></div>
        <div><Link to='/'>TOP</Link></div>
      </div>
    )
  }
}

export default MemberListApp

```

`<Route path='/user/:id' component={MemberInfo} />`の部分ですが、`component`を使った場合、routerはReactのエレメントを作成するために、`React.createElement`を実行します。

[ReactTraining/react-router](https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Route.md#component)

`index.js`にレンダリングメソッドを追加します。

```javascript:src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import MemberListApp from './MembersList'
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM.render(<MemberListApp />, document.getElementById('memberList'));
registerServiceWorker();
```

`public/index.html`に`<div id="memberList"></div>`を追加します。

ブラウザの動きはこのようになります。

![screencast 2018-01-08 13-30-06.gif](https://qiita-image-store.s3.amazonaws.com/0/226431/dbf37b51-2841-16da-73f5-8fae8b08b3dd.gif)
Capistranoの動作確認をローカルで行う方法

# はじめに

私がCapistranoの動作確認をローカルで行うために、使っている方法を紹介します。

以下のライブラリのバージョンで、このやり方が上手く行くことを確認しました:

- Capistrano: v3.6〜v3.10
- SSHKit: v1.11〜v1.15

# やり方

①下のようなCapistranoの設定ファイルを用意します。パスは`config/deploy/local.rb`とします。

```ruby:config/deploy/local.rb
set :deploy_to, "/path/to/app"
set :sshkit_backend, SSHKit::Backend::Local
server 'localhost'
```

②`cap local deploy`を実行します。

以上で、ローカルマシン上の`/path/to/app`にアプリケーションがデプロイ(コピー)されます。

# サンプルコード

動作する完全なサンプルの例としては、 https://github.com/progrhyme/tutorials/tree/master/capistrano をご覧ください。

# 解説

※この解説は以下のバージョンのコードを前提とします:

- Capistrano v3.10.1
- SSHKit v1.15.1

SSHKitのDSLである`#as`, `#with`, `#execute`, `#capture`といったメソッドは抽象クラスSSHKit::Backend::Abstractで実装されています。
同じくSSHKitのDSLである`#upload!`, `#download!`等については、これを継承した具象クラスで実装するものとされています。

上の`config/deploy/local.rb`で設定した`:sshkit_backend`[^1]は、デフォルトでは`SSHKit::Backend::Netssh`に設定されます。
これは、`capistrano/setup.rb`から実行される`Capistrano::Configuraton#configure_backend`によります。

[^1]: 正確には、SSHKitのクラス変数`@@config`が示すSSHKit::Configurationインスタンスの`@backend`メンバ変数。

`SSHKit::Backend::Netssh`は、[net-ssh](https://github.com/net-ssh/net-ssh)を利用してリモートホストにSSH接続するバックエンドです。

この`:sshkit_backend`を明示的に`SSHKit::Backend::Local`に設定することで、通常リモートホストにSSH接続する操作をローカルマシン上で行うことができるようになります。

# 終わりに

私自身、Capistranoのプラグイン開発時や設定編集時にこの方法を利用してきました。

ただし、この方法で確認できるのはリモートとの通信を伴わない範囲なので、その辺りに影響するような変更や開発を行う際は、別の動作確認が必要と考えます。

リモートとの通信に関係しない部分の変更・開発時には、有用な動作確認方法だと思います。

# 参考

- https://github.com/capistrano/capistrano
- https://github.com/capistrano/sshkit
- https://capistranorb.com/

# 脚注
JetBrains IDE（IntelliJ IDEAなど）を使う時のgitignoreについて


IDEでプロジェクトを作成すると、".idea/"と"[project-name].iml"が作成される。

Gitでプロジェクトのソースコードを管理するとき、管理対象（除外対象）の設定はどのようにしたらよいのか。

## 公式ドキュメントがあった

 * https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems

ネット上では".idea/"をgitignoreに書いて、このディレクトリ配下のすべてのファイルを管理外にしている例が多かったが、それは適切ではないようだ。

上記のドキュメントによると、".idea/"内の"workspace.xml"、"tasks.xml"以外のファイルは、すべてGitのリポジトリに入れてシェアすべきファイルとのこと。

また、".iml"のファイルもリポジトリに入れる必要がある。

## つまり、こういうこと

 * https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore

リンク先のコメントにも書いてあるが、これは先ほど挙げた公式ドキュメントを参考に作成されている。


## もっとシンプルにすると

私はPythonを使っているので、Gradle用の設定とかは不要。

必要最低限にするなら、こんな感じ？

```
.idea/**/workspace.xml
.idea/**/tasks.xml
```

実際にこの設定でチーム開発した経験はないので、参考にされる方は自己責任でお願いします。

## おまけ
### gitignoreの書式
 * https://git-scm.com/docs/gitignore

### virtualenvを使う時のgitignore
 * https://github.com/github/gitignore/blob/master/Global/VirtualEnv.gitignore