OmniAICreator/Qiita-1.07M huggingface dataset:
UbuntuにSwiftをインストール

Ubuntu 16.04にSwift 3.1.1をインストールしてみた。

```
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
$ sudo apt-get install -y clang libicu-dev
$ curl -OR https://swift.org/builds/swift-3.1.1-release/ubuntu1604/swift-3.1.1-RELEASE/swift-3.1.1-RELEASE-ubuntu16.04.tar.gz
$ curl -OR https://swift.org/builds/swift-3.1.1-release/ubuntu1604/swift-3.1.1-RELEASE/swift-3.1.1-RELEASE-ubuntu16.04.tar.gz.sig
$ ls -l swift-3.1.1-RELEASE-ubuntu16.04.tar.gz*
-rw-rw-r-- 1 glire glire 122709317 Apr 22 10:50 swift-3.1.1-RELEASE-ubuntu16.04.tar.gz
-rw-rw-r-- 1 glire glire       819 Apr 22 10:50 swift-3.1.1-RELEASE-ubuntu16.04.tar.gz.sig
$ wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import -
$ gpg --keyserver hkp://pool.sks-keyservers.net --refresh-keys Swift
$ gpg --verify swift-3.1.1-RELEASE-ubuntu16.04.tar.gz.sig
$ sudo chmod o+rwx /opt
$ mv -i swift-3.1.1-RELEASE-ubuntu16.04.tar.gz /opt/
$ cd /opt/
$ tar xvfz swift-3.1.1-RELEASE-ubuntu16.04.tar.gz
$ ls -l
total 119840
drwxrwxr-x 3 glire glire      4096 May 30 11:22 swift-3.1.1-RELEASE-ubuntu16.04
-rw-rw-r-- 1 glire glire 122709317 Apr 22 10:50 swift-3.1.1-RELEASE-ubuntu16.04.tar.gz
$ rm -f swift-3.1.1-RELEASE-ubuntu16.04.tar.gz
$ sudo chmod o-w /opt 
$ export PATH=/opt/swift-3.1.1-RELEASE-ubuntu16.04/usr/bin:$PATH
$ which swift
/opt/swift-3.1.1-RELEASE-ubuntu16.04/usr/bin/swift
$ swift --version
Swift version 3.1.1 (swift-3.1.1-RELEASE)
Target: x86_64-unknown-linux-gnu
$ swift
Welcome to Swift version 3.1.1 (swift-3.1.1-RELEASE). Type :help for assistance.
  1> ^D
```
GoogleComputeEngine上で.NET Core！

## 設定
* Google Cloud Platformを使ってサービスしよう
* サーバー費抑えたい = Linux
* C# 使いたい = .NET Core

## Google Compute Engine（GCE）
Linuxのインスタンスをつくる
今回は **Ubuntu 16.04 LTS** を選択


## nginx
Webサーバーとしてnginxを導入

```
$ sudo apt-get update
$ sudo apt-get install nginx
$ sudo /etc/init.d/nginx start
```
GCEのVMインスタンスにある外部IPにアクセスして、"Welcome to nginx!"と表示されればOK
![2017-05-30_10h17_23.png](https://qiita-image-store.s3.amazonaws.com/0/93282/43b678fa-fbc6-b702-e697-7adaa2d0744f.png)

## .NET Core
[Get Started with .NET Core](https://www.microsoft.com/net/core#linuxubuntu) のコマンドをそのまま OSやバージョンで分かれているので、要注意

```
Add the dotnet apt-get feed
$ sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
$ sudo apt-get update
```

```
Install .NET Core SDK
$ sudo apt-get install dotnet-dev-1.0.4
```

```
Initialize some code
$ sudo dotnet new console -o hwapp
$ cd hwapp
```

```
Run the app
$ sudo dotnet restore
$ sudo dotnet run
```

コンソール Hellow World のできあがり
docker-composeとMySQL公式イメージで簡単に開発環境用DBを作る

# やりたいこと

ローカルで開発するときに簡単にMySQL環境を作りたい。
docker-composeでMySQLコンテナとアプリケーションコンテナを立てて接続する。
MySQLは初期データを入れられるようにしておく。

# 環境

* OSX El Capitan 10.11.5
* Docker version 1.13.1
* docker-compose version 1.11.1

# 本題

MySQLの公式リポジトリは以下です。
https://hub.docker.com/_/mysql/

色々オプションをつけて起動することができるので、今回はdocker-composeを用いて、

* データの永続化
* rootパスワードの設定
* 初期データの挿入
* 日本語使いやすいように文字コードの設定

までを行うようにしています。

```:構成
dir
├ docker-compose.yml
├ mysql/
│   ├ Dockerfile
│   ├ my.cnf
│   └ sqls/
│       └ initialize.sql
└ app/ # 今回は省略
```

```yaml:docker-compose.yml
version: '2'
services:
  mysql:
    build: ./mysql/
    volumes:
      - ./mysql/mysql_data:/var/lib/mysql # データの永続化
      - ./mysql/sqls:/docker-entrypoint-initdb.d # 初期データ投入
    environment:
      - MYSQL_ROOT_PASSWORD=好きなパスワード #rootパスワードの設定
  appserver:
    build:
      context: ./app/
    links:
      - mysql
```

```:mysql/Dockerfile
FROM mysql:5.7
EXPOSE 3306

ADD ./my.cnf /etc/mysql/conf.d/my.cnf # 文字コード設定のためconf追加

CMD ["mysqld"]
```

```:mysql/my.cnf
[mysqld]
character-set-server=utf8

[mysql]
default-character-set=utf8

[client]
default-character-set=utf8
```

```sql:mysql/sqls/initialize.sql
CREATE DATABASE app;
use app;

CREATE TABLE users (
  id int(11) unsigned not null auto_increment,
  name varchar(255) not null,
  created_at datetime not null default current_timestamp,
  updated_at datetime not null default current_timestamp on update current_timestamp,
  primary key (id)
);
```

```bash
$ docker-compose build
$ docker-compose up -d
```

app側からは ホスト: mysql, ポート: 3306 で繋がります。
初期データに関しては新規立ち上げの時のみSQLが実行されるので、再実行する際はデータを破棄する必要があります。構築段階では永続化せずに使う方がやりやすいかもしれません。
Vim のインストール（ソースから行う場合）

2. Vim の最新バージョンをインストールする手順を備忘録的にまとめました

# 前提条件
- なるべく公式の手順に則ったやり方にする
- CentOS の環境は Vagrant で作成している
- Git をインストール済み
- バージョン情報は以下

| OS・ミドルウェア  |   バージョン   |
|:-----------------|--------------:|
| CentOS           |           7.3 |
| Git              |        2.26.0 |
| Vim              |           8.0 |

# 作業手順
1. インストールに必要なライブラリをインストール

    ```shell-session
    $ sudo yum install -y ncurses-devel make gcc
    ```

2. Vim のソースをダウンロード

    ```shell-session
    $ cd /usr/local/src/
    $ sudo git clone https://github.com/vim/vim.git
    ```

3. ソースをコンパイル

    ```shell-session
    $ cd vim/src
    $ sudo make
    $ sudo make install
    ```

次のように出力されていることを確認

```shell-session
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled May 29 2017 06:24:12)
Included patches: 1-606
...(以下省略)
```

# 参考
以下のリンクを参考にしました。
- [The Vim repository at GitHub](http://www.vim.org/git.php)
- [CentOS 7 に Vim エディタをインストール](http://note.mokeco.in/67/)
- [安藤翔のブログ - CentOS7に vim をインストール](http://andosho.blog.fc2.com/blog-entry-10.html)
- [Vim を設定する](https://www.server-world.info/query?os=CentOS_7&p=initial_conf&f=7)
パスワードとか知らないから1秒でも早くJupyter Notebook使いたい人へ

パスワードとか知らんから今すぐJupyter Notebook使わせろ！って方向けです。

というか自分への備忘録です。
# 自身の環境
Docker-toolbox on virtualbox on Windows 10

# Docker image 取得（している人は無視）
```
$ docker pull jupyter/datascience-notebook
```

僕ははとりあえずいろいろ入っている「jupyter/datascience-notebook」を選んでいますが、
いいからNotebook使わせろ！って方は「jupyter/notebook」で良いと思います。

# コンテナ起動
```
docker run -d --name notebook -p 8888:8888 -v /c/Users/[User]/[Work]:/home/jovyan/work -e GRANT_SUDO=yes jupyter/datascience-notebook
```

「[User]/[Work]」は適当に自身のユーザ名と作業フォルダを指定しましょう。
データの永続化とかファイル共有のために「-v」オプションで指定しているので、
そこらへんは不要という方はこの「-v ～ jovyan/work」は取りましょう。


# コンテナ内のシェルに接続
```
$ docker exec -it [Container ID] /bin/bash
jovyab@<Container ID>:~/work$
```
「[Container ID]」は `$ docker container ls` とかで確認できます。
知ってる人にとっては当たり前かもですが、先頭の1,2文字（他とかぶっていなければ）だけ打てば良いです。

「exec」コマンドなどについてもっと知りたい方は
[Dockerコンテナ内で操作 attachとexecの違い - Qiita](http://qiita.com/RyoMa_0923/items/9b5d2c4a97205692a560) などへどうぞ。

# Jupyter Notebook 起動
```
jovyab@<Container ID>:~/work$ jupyter notebook list
Currently running servers:
http://localhost:8888/?token=<トークン> :: /home/jovyan/work
```
上記の「http://～<トークン>」をブラウザにコピペしてアクセスすれば起動しているはず。
※ docker-machine など使用されている方は、「localhost」は適宜変えましょう。（僕は192.168.99.100です）

これで起動されているはず！
サーバが多くSSH鍵の管理が大変です。どんな工夫をしていますか？

これは「コードを書いていて困ったときに、suinがチャットで質問に答えたり相談に乗る[suinのプログラミング相談室(仮)](https://help.suin.io/)」で頂いた質問と僕の回答の要約です。

## 質問

管理するサーバ数が増えてきて、SSH秘密鍵の管理も大変になってきています。suinさんは、SSH鍵の管理をどうやっていますか？

## suinの回答

サーバって何台くらいになりますか？僕はせいぜい20台〜30台くらいがマックスなので、参考にならないかもしれませんが、戦略として次の2つをやっています。

* 使う鍵を減らす
* ログイン情報をモジュール化する

### 鍵を減らす

鍵を減らすのは同じ公開鍵を使い回す方法です。僕はできるだけこれをしてますね。セキュリティと利便性のトレードオフでバランスを取る戦略です。サーバの運用ルールや、与えられた鍵でしかアクセスできないなどで、できないこともあります。

### ログイン情報をモジュール化する

ログイン情報をモジュール化するのは、`Include`を使ってます。~/.ssh/configに`Include */config`と書いておいて、プロジェクトごとにディレクトリを作って管理してます。こうしておくことの利点は、次のものがあります。

* プロジェクトが終了したり、担当から外れたときはディレクトリを削除すればスッキリする。
* プロジェクトのチームメイトにSSH接続情報を共有するとき~/.ssh/project_hoge/configを送ればいい。

Includeについては以前ブログに書いてます。[待望の.ssh/configファイル分割がSSH 7.3から出来るようになったようです](https://suin.io/555)

ブログにはディレクトリ構成について詳しく書いてなかったので、実際どうやっているか具体的に説明します。

まず`~/.ssh/config`はこの数行にしています。

```rb:~/.ssh/config
Host *
  UseKeychain yes

Include */config
```

次に、プロジェクトごとにディレクトリを作り、SSHログイン情報をまとめています。

```
├── config ... すべてのサーバに共通した設定を書くのと、*/configをIncludeする場所
├── id_ecdsa ... 使いまわす鍵
├── id_ecdsa.pub ... 使いまわす鍵
├── known_hosts
├── github ... プロジェクトごとにディレクトリを作り
│   ├── config ... プロジェクトごとにconfigファイルを置く
│   ├── id_ecdsa
│   └── id_ecdsa.pub
├── bitbucket
│   ├── config
│   ├── id_ecdsa
│   └── id_ecdsa.pub
├── projhoge
│   ├── config
│   └── id_rsa
├── projfuga
│   ├── config
│   └── id_rsa
...
```

たとえば、githubの接続情報だとこうなっています。

```rb:~/.ssh/github/config
Host github github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/github/id_ecdsa
```

開発プロジェクトの接続情報はこんな感じにまとめています。

```rb:~/.ssh/projhoge/config
Host example.*
  IdentityFile ~/.ssh/projhoge/id_rsa
  User alice
  Port 2222

Host example.staging
  HostName ec2-XX-XX-XX-XX.ap-northeast-1.compute.amazonaws.com

Host example.production
  HostName ec2-YY-YY-YY-YY.ap-northeast-1.compute.amazonaws.com

# SequelProでRDSにつなぐための踏み台サーバ
Host example.rdsgateway
  HostName XX.XX.XX.XX
  User ubuntu
  Port 2233

# VPNサーバ
Host example.vpn
  HostName ec2-XX-XX-XX-XX.ap-northeast-1.compute.amazonaws.com
  User ubuntu
  Port 2244
```

## 回答に対しての反応

ありがとうございます！僕の場合は公開鍵を使いまわす方法で管理する鍵を減らせそうです。Includeはプロジェクトごとに管理できるので、処分するときに一括で消せる点が魅力だと感じました。
ライセンスを追加、削除、付与　という表現で良いのでしょうか？

ライセンスを管理しています。

ライセンスをメーカーから購入し
所持ライセンス数が増える事を
”ライセンス追加”

ライセンスをメーカーに返上し
所持ライセンス数が減る事を
”ライセンス削除”

ライセンスを使用する事で
所持ライセンスが減ることを
”ライセンス付与”
という表現でドキュメント作成しているのですが
これで本当に良いのか　いまいち自信が持てないので
メモ失礼します。

違う場合は突っ込みをお願いします。
Git のインストール（ソースからビルドする場合）

CentOS に Git を yum でインストールしていたけれど、バージョンが古いのでソースからビルドする手順を備忘録的にまとめました

# 前提条件
- なるべく公式の手順に則ったやり方にする
- CentOS の環境は Vagrant で作成している
- Git のソースは [The Linux Kernel Archives](curl -LkvOf https://mirrors.edge.kernel.org/pub/software/scm/git) から tar.gz ファイルをダウンロードする
- バージョン情報は以下

| OS・ミドルウェア  |   バージョン   |
|:-----------------|--------------:|
| CentOS           |           7.3 |
| Git              |        2.26.2 |

# 作業手順
1．コンパイルに必要なライブラリ(gcc)がインストールされていない場合はインストールする

```
$ sudo yum install -y gcc autoconf
```

2．インストールに必要なライブラリをインストール

```
$ sudo yum install -y curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel perl-ExtUtils-MakeMaker
```

3．（任意）ドキュメントを出力することがある場合に必要なライブラリをインストール

```
$ sudo yum install -y asciidoc xmlto docbook2X
```

4．（任意）シンボリックリンクを構築(Fedora系、RHEL系の場合は必要)

```
$ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
```

5．Git をダウンロードして展開する

```
$ cd /usr/local/src/
$ sudo curl -LkvOf https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.26.2.tar.gz
$ sudo tar zvfx git-2.26.2.tar.gz
```

6．Git のソースをコンパイルする

```
$ cd git-2.26.2
$ sudo make prefix=/usr/local all
$ sudo make prefix=/usr/local install
```

次のように表示されていることを確認

```
$ git --version
git version 2.26.2
```

# 参考

以下のリンクを参考にしました。
- [1.5 使い始める - Gitのインストール](https://git-scm.com/book/ja/v2/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
- [1.4 使い始める - Gitのインストール](https://git-scm.com/book/ja/v1/%E4%BD%BF%E3%81%84%E5%A7%8B%E3%82%81%E3%82%8B-Git%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
- [CentOS7に最新のGitをインストール、アップデート、他](http://qiita.com/ysti/items/e8b4271313e93bd9efa6)
- [CentOS7にgitをソースからインストール](http://www.server-memo.net/memo/github/github-install.html)
- [CentOS7に最新のGitを導入する方法](http://vdeep.net/centos7-git)
- [CentOS7で最新のGitを使うの](http://beyondjapan.com/blog/2016/12/newest-git-on-centos7)
見ているページをチャットワークでシェアするブックマークレット

# 概要

チャットワークには[「チャットワークでシェアボタン」](http://www.chatwork.com/ja/share/)という機能が提供されています。
これはボタンを設置したページを簡単にチャットワークで共有するためのボタンですが、共有したいページにはだいたい設置されていないのでブックマークレットで使えるようにしました。

## ブックマークレット

### ChatWork用

```javascript:share_with_ChatWork.js
javascript:(function(){"use strict";var title=encodeURIComponent(document.title),url=encodeURIComponent(window.location),popupURL="https://www.chatwork.com/packages/share/login.php?url="+url+"&title="+title,w=600,h=500,l=screen.width/2-w/2,t=screen.height/2-h/2;window.open(popupURL,"ChatWorkShare","resizable,scrollbars,status,width="+w+",height="+h+",left="+l+",top="+t);})()
```

### KDDI ChatWork用
```javascript:share_with_KDDI_ChatWork.js
javascript:(function(){"use strict";var title=encodeURIComponent(document.title),url=encodeURIComponent(window.location),popupURL="https://kcw.kddi.ne.jp/packages/share/login.php?url="+url+"&title="+title,w=600,h=500,l=screen.width/2-w/2,t=screen.height/2-h/2;window.open(popupURL,"ChatWorkShare","resizable,scrollbars,status,width="+w+",height="+h+",left="+l+",top="+t);})()
```
GolangでMessagePackでシリアライズした構造体をAerospikeに保存する

# コード

```go
package main

import (
	"fmt"

	as "github.com/aerospike/aerospike-client-go"
	"github.com/ugorji/go/codec"
)

type Human struct {
	Name struct {
		First string
		Last  string
	}
	Age int
}

// MessagePackでシリアライズしてAerospikeに保存
func put() {
	ieyasu := &Human{
		Name: struct {
			First string
			Last  string
		}{
			"Ieyasu",
			"Tokugawa",
		},
		Age: 70,
	}

	var buf []byte
	mh := &codec.MsgpackHandle{RawToString: true}
	codec.NewEncoderBytes(&buf, mh).Encode(ieyasu)

	client, _ := as.NewClient("localhost", 3000)
	key, _ := as.NewKey("bar", "set", "key")
	bins := as.BinMap{"selialized": buf}

	client.Put(nil, key, bins)
}

// Aerospikeから取得したデータをMessagePackでデシリアライズして表示
func get() {
	client, _ := as.NewClient("localhost", 3000)
	key, _ := as.NewKey("bar", "set", "key")
	res, _ := client.Get(nil, key)

	var human Human
	mh := codec.MsgpackHandle{RawToString: true}
	codec.NewDecoderBytes(res.Bins["selialized"].([]uint8), &mh).Decode(&human)

	fmt.Println(human)
}

func main() {
	put()
	get()
}
```

## 実行結果

```bash
{{Ieyasu Tokugawa} 70}
```
マテリアルアイコンをRuby on Railsで使う

# 使うもの
- [Materialize sass ruby gem](https://github.com/mkhairi/materialize-sass)
- [Material Icons for Rails](https://github.com/Angelmmiguel/material_icons)

# 準備
## Gemのインストール
`Gemfile`に下記2行を追加

```
gem 'materialize-sass'
gem 'material_icons'
```

`bundle install`する

## scssに追加
`app/assets/stylesheets/application.scss`に下記1行を追加

```scss
@import "materialize/components/icons-material-design";
```

# 使い方
## HTMLタグを使う方法

```html
<i class="material-icons">face</i>
<i class="material-icons md-36">face</i>
```

## ヘルパーを使う方法

```html+erb
<%= material_icon.face %>
<%= mi.face %>
```

# 参考
[MATERIAL DESIGN ICONS](https://material.io/icons/)
[Material Icons Guide](https://google.github.io/material-design-icons/)
[Materialize Icons](http://materializecss.com/icons.html)
[0から分かるマテリアルデザインの作り方](https://saruwakakun.com/html-css/material)
[マテリアルデザインについて少し調べる](http://qiita.com/nogson/items/804dd3a879f482fb7018)
circleciでのdocker multi stage builds ではまった話

# はじめに
メモ的な

# やろうとしたこと
circleci version2 を利用して、docker multi stage builds でビルドしようとしました。

# 結果
できませんでした！（2017/05/29時点） ※ docker for mac の edge ならできます！

内容としては、こんな感じです。

 - golangアプリケーションのコンテナビルドをしたい
 - 軽量化するために multi stage builds を利用
 - circleci 2 でのベースイメージは docker:17.05.0-ce-git
 - エラーが出る
    - `Error parsing reference: "golang:1.8.3 as alias" is not a valid repository/tag: invalid reference format`


# 理由
色々調べたのですが、「最新のdocker（dege）使えばいけるよー」みたいな記事ばっかだったのですが、こんな記事を発見しました。

[Multi-Stage builds on docker hub](https://github.com/docker/hub-feedback/issues/1039)

>Docker HubとDocker Cloudの自動ビルドサービスは、この機能が安定したチャネルに卒業した時点でマルチステージビルドのサポートを追加する予定です（現在、17.06リリースの6月をターゲットにしています）。


これってつまり、docker社が提供する docker実行可能 docker イメージでの multi stage builds は 17.06からできるようになりますよ（17.05ではできませんよ）ということなんでしょうか。。。

# 結果
docker hub ですらサポートされていないのだから、circleci でサポートされてないよなーなんて思いながら、今まで通り Dockerfile を分けてビルド結果からアプリケーション実行ファイルを docker cp してー。。。とやりました。
（これでもイメージの軽量化はできるので問題ないのですが・・・）

# 終わりに
いやいや、circleci で multi stage builds できるから！など情報ありましたらコメントいただけると嬉しいです！

# 参考
[Use multi-stage builds](https://docs.docker.com/engine/userguide/eng-image/multistage-build/)

# 追記
[できるみたいですね！](https://circleci.com/blog/multi-stage-docker-builds/)

```
jobs:
  build:
    steps:
      - setup_remote_docker:
	      version: 17.05.0-ce
```

こいつが肝なようでした。

```
jobs:
  build:
    docker:
      - image: docker:17.07.0-ce-git
```

ここで指定すればOKだと思っていましたが、job の default image が 17.03 のようで、setup_remote_docker で指定してあげないとだめみたいです。
Gitでリモートのマージ済みのブランチを一括削除する（egrepが無い場合）

いくつか削除したくないブランチがある場合は-eの部分を増やしていくべし。


### ローカルのブランチ

```
git branch --merged | \
  grep -v \
    -e develop \
    -e master \
    -e stg \
    -e test \
    -e feature/hoge-455 \
    -e feature/hoge-405 \
  | xargs git branch -d
```


### リモートのブランチ
```
git branch -a --merged | \
  grep -v \
    -e develop \
    -e master \
    -e stg \
    -e test \
    -e feature/hoge-455 \
    -e feature/hoge-405 \
  | grep remotes/origin \
  | sed -e 's% *remotes/origin/%%' \
  | xargs -I% git push origin :%
```
Apacheによる負荷分散構成


## はじめに

Apache 2.4 において `mod_proxy_balancer` でリクエストを配下のWebサーバーに分散させる方法について 簡単にテストした内容をまとめています。


## システム構成図

![mod_proxy_balancer.png](https://qiita-image-store.s3.amazonaws.com/0/39362/eb487dbc-e684-baed-ecdb-025ff1b1c405.png "mod_proxy_balancer.png")

`/balancer` にアクセスが来ると、バックエンドのservice1 ~ 3 に順番にリクエストを振り分ける

* 動作確認では localhost にて試したが、バックエンドは別サーバーでも問題ない
* 今回は service1 ~ 3 に `Hello World` という文字列を返すだけのHTTPサーバーを用意した
  * [Kazunori-Kimura/http-dummy-server](https://github.com/Kazunori-Kimura/http-dummy-server)


## 設定

### httpd.conf

(1) `httpd-balancer.conf` の作成

バランサー設定を一箇所にまとめるよう、設定ファイルを作成

```
ProxyPass /balancer balancer://mycluster lbmethod=byrequests timeout=1
<Proxy balancer://mycluster>
  BalancerMember http://127.0.0.1:8081 loadfactor=1
  BalancerMember http://127.0.0.1:8082 loadfactor=1
  BalancerMember http://127.0.0.1:8083 loadfactor=1
</Proxy>

<Location /manager>
  SetHandler balancer-manager
</Location>
```

`/balancer` にアクセスがあると `<Proxy>` に登録された `BalancerMember` にリクエストを振り分ける。

`loadfactor` は重み付けで、数字が大きいメンバーに優先してリクエストを振り分けられる。

`/manager` にアクセスがあると、 `mod_proxy_balancer` の管理画面が表示される。
各メンバーのステータスやリクエストの分散状況などが表示される。

![balancer-manager.png](https://qiita-image-store.s3.amazonaws.com/0/39362/625b9d6a-06ac-f433-083b-2a5937be0521.png "balancer-manager.png")

(2) `httpd.conf` にて以下のモジュールを有効にする

```
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
#LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
#LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
#LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule status_module modules/mod_status.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
```

今回は単純にリクエストを順に振り分けるので、 `mod_lbmethod_byrequests.so` を有効にする。

`httpd-balancer.conf` の `ProxyPass` にて `lbmethod=byrequests` 以外のメソッドを使用する場合は、該当するモジュールのコメントアウトを外す。

(3) `httpd-balancer.conf` を読み込む

`httpd.conf` の末尾で `httpd-balancer.conf` を読み込むように `Include` を追加する。

```
Include conf/extra/httpd-proxy-balancer.conf
```

(4) Apacheを再起動する

(5) 動作確認

* `/balancer` にアクセスし、`Hello World` が表示されることを確認
* 何度かブラウザのリロードを繰り返し、各ダミーサーバーに順繰りにリクエストが来ることを確認
* service1 ~ 3 のいずれかを停止した状態でブラウザのリロードを繰り返すと、Activeなサーバーのみにリクエストが来ることを確認

---

## 参考資料

* [mod_proxy - Apache HTTP サーバ バージョン 2.4](https://httpd.apache.org/docs/2.4/ja/mod/mod_proxy.html)
* [mod_proxy_balancer - Apache HTTP サーバ バージョン 2.4](https://httpd.apache.org/docs/2.4/ja/mod/mod_proxy_balancer.html)
* [Apache2.4でロードバランシング設定して管理画面(バランサマネージャ)で確認する。 - ボールを蹴りたいシステムエンジニア](http://toriaezu-engineer.hatenablog.com/entry/2017/01/14/111157)
* セッションを継続するための設定
  * [クラスタ構成の Tomcat をApacheでロードバランスする](http://www.mclnet.co.jp/tech/java/apache-balancer.html)
  * [Apache - mod_proxy_balancer | eastforest](http://www.eastforest.jp/esthome/apache/2556)
実装例：PHPで「同点３位が複数いた場合にランダムで１人選出したい」

## はじめに

PHPの配列ランダム操作はまだ簡潔に書けないことが多い気がする
タイトルにあるようなロジックを書く場面があったのでその時の実装を残しておく
タイトルのような状況に限ったものではなく、色んなパターンに応用が効くように組む

コード読むのがめんどくさい人は最後のポイントだけ見て自分の方法へ落とし込んで行ってください

## 使うタイミング

例えばあるテストで上位３名を決めたかったときに点数が

```
赤星: 98
今岡: 95
片岡: 89
鳥谷: 89
下柳: 89
桧山: 82
関本: 77
```

みたいなだと困る
そんな時に３位をランダムで選び上位グループの３人を決める
(__1つの配列をソートし2つに分けるとき出会いそうな場面__)

これのよりスマートなやり方を考えてみた

## 達成すべき課題

* ３位に同点が出た場合、__ランダム選出__が行われる
* ２位に同点出た場合
    * 同点２位が２人だったら上位グループは１位、２位、２位になるのでハッピーエンド
    * 同点２位が３人だったら__ランダム選出__
* 上位グループの__定員数を好きにいじっても__上手くいく
* １位に同点が出て、それが上位グループの定員をオーバしている場合も効く


## やり方

```
$players = [
  'akahoshi'    => 98,
  'imaoka'      => 95,
  'kataoka'     => 89,
  'toritani'    => 89,
  'shimoyanagi' => 89,
  'hiyama'      => 82,
  'sekimoto'    => 77
];

// 上位グループの定員数
$capacity = 3;
// 定員数ギリである「3位」のスコアを取得しておく
$borderline = (current(array_slice($players, $capacity - 1, 1, true)));

// 得点順にソート、実はこれがキモ
arsort($players);

$tmpGroup  = [];
$highGroup = [];
$lowGroup  = [];

// 同点３位のやつは一時グループに分けておく
foreach ($players as $name => $score) {
  if ($score === $borderline) {
    $tmpGroup[$name] = $score;
  // '$score > $borderline' をしないと1位に同点がたくさんいた場合に対応できない
  } elseif (count($tmpGroup) < $capacity && $score > $borderline) {
    $highGroup[$name] = $score;
  } else {
    $lowGroup[$name] = $score;
  }
}

// 一時グループから上位グループに足りない人数分ランダムで選出
if (count($tmpGroup) > 0) {
  $randomNames = array_rand($tmpGroup, $capacity - count($highGroup));
  // array_randはmixを返すのでarrayに統一
  if (is_array($randomNames) === false) $randomNames = [$randomNames];
 
  // ランダムで選出したやつを上位グループへ
  foreach ($randomNames as $name) {
    $highGroup[$name] = $tmpGroup[$name];
  }

  // 一時グループを全部下位に追加したのち、上位に選出されたものだけ削除
  $lowGroup += $tmpGroup;
  foreach ($randomNames as $name) {
    unset($lowGroup[$name]);
  }
}

?>
```

## ポイント

* ランダム選出の対象だけ抜き取る、つまり __ボーダーラインに乗ってるものだけを選出する__ ことが何よりもミソ
* 選出されたもののkeyを持てるので、下位グループに __ランダム選出対象になったものを全て追加後、keyで削除__ が楽でいい
Pythonで小数点以下の計算結果

# 小数点以下の計算がおかしい

Pythonの小数点数は、「IEEE754 浮動小数点数」というルールを使っているらしい、、なので小数点の計算結果が以下な感じに・・・仕様です！

```
>>> 0.1 + 0.1 + 0.1
0.30000000000000004
```

正しい計算結果を返すには、Decimalモジュールを使う方法あるようです。小数点以下を「丸め誤差なし」での計算例になります↓

```
>>> from decimal import *

>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1')
Decimal('0.3')
```
Googleスプレッドシートのカスタムファンクションを使ってチャートをセルに埋め込む

# 概要
Googleスプレッドシートのカスタムファンクションを使ってチャートをセルに埋め込む方法についてご紹介します。

# デモ
本内容を使用すると、下記デモのようにセル"B7"にカスタムファンクション``=embedChart("A2:A6")``を入力することでセル"A2:A6"にあるデータをチャート化し、画像としてセルに埋め込むことができます。

![fig.png](https://qiita-image-store.s3.amazonaws.com/0/133383/ac1a4d40-ddb9-28ec-866c-9555575a7ca7.png)

# フロー
チャートをセルに埋め込むための全体のフローは、データ範囲を入力してチャートを作成し、画像として保存した後にセルに埋め込みます。

``insertChart()``はチャートをスプレッドシート上に貼り付けることはできますが、セルに埋め込むことはできません。調べてみましたが、私の方ではGASを使ってチャートをセルへ直接埋め込む方法は見当たりませんでした。そのため、``=IMAGE()``関数を使用することにしました。

# 問題点
取り組み始めて直ぐにスプレッドシートのカスタムファンクションは結構な制限があることに気付きました。

1. チャートを作成するための``newChart()``は使用できますが、貼り付けるための``insertChart()``（これは今回は使用しませんが。）は使用できません。
2. DriveAppが使用できません。そのため、画像として保存することができません。
3. ``setFormula()``が使用できません。そのため、``=IMAGE()``関数を挿入することができません。

# 解決策
これらの問題を解消するためにWeb Appsを使用することにしました。これまでの経験からWeb Appsを使うといろいろな制限を回避することができることが分かっています。例えば、Execution APIではできないトリガー設定がWeb Appsではできるなど。

実際にWeb Appsを適応させてみたところ、上記の全ての問題は解消されました。

# Web Appsのデプロイ
本家のドキュメントは[こちら](https://developers.google.com/apps-script/guides/web)です。

1. スクリプトエディタの上部にある公開をクリック
2. ウェブアプリケーションとして導入をクリック
3. プロジェクトバージョンを新規作成で適当な名前で作成
4. 次のユーザとしてアプリケーションを実行では「自分」にセット
5. アプリケーションにアクセスできるユーザを「全員（匿名ユーザを含む）」にセット
6. OKをクリック

以上でWeb Appsのデプロイは完了です。

ここで注意するところは、スクリプトを修正した際には上の3にある「**プロジェクトバージョンを新規作成で適当な名前で作成**」を行って必ず更新する必要があることです。これを失念するとスクリプトを変更しても反映されないといった問題につながります。

# スクリプト
下記スクリプトをスプレッドシートから起動したスクリプトエディタ内へ貼り付けてください。貼り付けた後に、Web Appsをデプロイしてください。

~~~gas:
var folderId = "### Folder ID ###";
var webappsurl = "https://script.google.com/macros/s/######/exec";

function embedChart(range) {
  var ac = SpreadsheetApp.getActiveSheet().getActiveCell();
  var q1 = "?datarange=" + range;
  var q2 = "&row=" + ac.getRow();
  var q3 = "&col=" + ac.getColumn();
  var url = webappsurl + q1 + q2 + q3;
  UrlFetchApp.fetch(url);
}

function doGet(e) {
  var sheet = SpreadsheetApp.getActiveSheet();
  var chart = sheet.newChart()
    .setChartType(Charts.ChartType.PIE)
    .addRange(sheet.getRange(e.parameters.datarange))
    .setOption('height', 280)
    .setOption('width', 480)
    .setOption('title', 'Sample chart')
    .build();
  var file = DriveApp.getFolderById(folderId).createFile(
    chart.getAs('image/png').setName("chart_image.png")
  );
  file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
  sheet.getRange(e.parameters.row, e.parameters.col).setFormula(
    '=IMAGE("' + "http://drive.google.com/uc?id=" + file.getId() + '")'
  );
}
~~~

## スクリプトのフロー

- embedChart()
    - ``=embedChart("a2:a6")``をセル"B7"へ入力
    - ``fetch()``を使ってWeb Appsの``doGet()``へデータ範囲"a2:a6"を送信
- doGet()
    - ``doGet()``でデータを取得（doGet()の中で制限にひっかかる作業をさせます）
    - 受信したデータ範囲"a2:a6"を使ってチャートを作成（サンプルとしてpieチャートに設定します）
    - チャートを画像として保存（今の場合PNGとして保存します）
    - ``=IMAGE()``で使用できるように権限を変更（IMAGE関数はGoogle Drive内のファイルを直接見ることはできないようです）
    - ``setFormula()``を使って``=IMAGE(URL)``を``=embedChart("a2:a6")``のセルへ上書き（これによりシートを再度読み込んだ際に画像を直接読み込むため表示速度が向上します）

# 気付いたこと
``=embedChart("a2:a6")``を入力してから画像が表示されるまで約40秒の時間がかかってしまいます。スクリプトエディタ上で行うと数秒程度で終了します。この差はカスタムファンクションによると考えられるのでしょうか。これを何とかしようといろいろ試しましたが解決には至っていません。
Railsでデータコンバートを行う時は専用のスクリプトを書くと良い


# はじめに

Webサービスを作っているとサービスの成長に合わせて初期のデータ構造を変更することがあります。
そんな時に必要なのが現在のデータを新しいデータ構造に合わせるためのデータコンバートです。
そんなデータコンバートでよく利用する方法を紹介します。

# 今回の環境

```
gem 'rails', '4.2.8'
```

基本的にはRails5系でもデータコンバートのスクリプトは動作すると思います。

# 他のデータコンバートの方法

## マイグレーションにデータコンバートを書く

マイグレーションファイルに書けばDBの構造変更とコンバートの関連性が分かりやすいというメリットがあります。
ただ、マイグレーションファイルに書くと再実行がやりにくいというデメリットがあります。

## モデルにデータコンバートを書く

Rails的に書けるのですが、データコンバートが終了すると、ほぼ使われないコードがアプリケーション本体のコードに混ざってしまうので、徐々にFatモデルになっていくのが辛いです。
なるべくデータコンバート処理はアプリケーション本体とは分離したいですね。

## SQLを書く

単純なUpdateなどシンプルなコンバートならSQLを直接かいてもよいのですが、条件によってコンバート内容を変更する場合などを考えるとRailsで書きたいところです。

# データコンバート専用スクリプトを書く

それではデータコンバート用のスクリプトを書いてみます。
スクリプトは専用のフォルダを作ってそこにまとめるようにしています。
例えば `script/convert_users.rb` というファイルを作ります。

``` script/convert_users.rb
User.transaction do
  convert_count = 0
  User.all.each.with_index(1) do |user, i|
    user.nickname = 'NO NAME'
    user.save!
    convert_count = i
  end
  
  puts "User count: #{User.count}"
  puts "Convert count: #{convert_count}"
  
  print 'Are you sure?(yes/no) > '
  if gets.strip == 'yes'
    puts 'committed'
  else
    puts 'rollback'
    raise ActiveRecord::Rollback
  end
end
```

データコンバートはRailsで書きます。
複数データの更新であれば `transaction` ブロックで囲みます。

```rb
puts "User count: #{User.count}"
puts "Convert count: #{convert_count}"
```
`puts` で実行結果を出力してコンバートの整合性を確認できるようにしています。

```rb
print 'Are you sure?(yes/no) > '
if gets.strip == 'yes'
  puts 'committed'
else
  puts 'rollback'
  raise ActiveRecord::Rollback
end
```

またスクリプト実行時に内容を確認してからコミットできるようにメッセージを表示してコミット or ロールバックを選択できるようにしています。

# データコンバート専用スクリプトを実行する

それではスクリプトを実行してみましょう。
ターミナルでRailsのアプリケーションフォルダまで移動してスクリプトを実行します。

```
rails runner script/convert_users.rb
```

実行すると下記のように結果が表示されます。
コンバート結果を確認して問題なければ `yes` と入力してコンバート結果をコミットします。

```
User count: 10
Convert count: 10
Are you sure?(yes/no) >
```

# メリット

このようにデータコンバート専用スクリプトを書いておくと、何度でもコマンドラインから実行することが可能となります。アプリケーション本体とも分離しているので本体を汚すこともありません。
また、スクリプトはgitに含めるようにしているので、コードレビューでマイグレーションとの整合性も含めてチェックすることができます。

# デメリット

例えばマイグレーションを伴うデータコンバートの場合には、マイグレーション実行 ⇒ データコンバート実行 となるのでコンバートまでに多少の時間差が発生してしまいます。
その為、作りによってはデータの不整合が発生することがあるかもしれません。

- 一旦サービスを停止してから実施する
- 時間差が発生しても問題ない作りにする
- なるはやでデータコンバートを実行する！

上記の様な事を意識する必要があります。

# まとめ

今回はよく使うデータコンバートの方法を紹介しました。
データコンバートの方法について「こんな方法もあるよ」などあれば教えてください。
macOS 取消 Screenshot 時候產生的視窗 Shadow


打開 Terminal

```sh
defaults write com.apple.screencapture disable-shadow -bool true
```

接著

```sh
killall SystemUIServer
```

測試結果
![無陰影](http://i.imgur.com/oxoTgYn.jpeg)


**如果要恢復 Shadow**

```sh
defaults write com.apple.screencapture disable-shadow -bool false
```

接著

```sh
killall SystemUIServer
```

測試結果
![有陰影](http://i.imgur.com/xRo9iOG.png)

**結論**

還是有陰影比較好看
GameSaladのActerを使ったゲーム部品の作り方

体験版が終わっちゃったので文字だけの概要解説になった
もしBasic版を購入したら、具体的な操作説明を追記する
※体験版を使ってみて理解した内容が書いてあります。現時点での私の理解なので、一部ないし全てが間違っているはずです。ご了承ください。

#GameSaladの基本
Seane(シーン):ゲーム画面を指す。ゲームの１シーンを指し、マリオなら１ステージ(土管の中などは別Seane)となる。
Layer(レイヤー):後述するアクターをまとめたもの。マリオならクリボー、?ブロック、キノコ等の画像とモーションをまとめたもの。
Acter(アクター)：タイマーや操作に対するイベント。マリオならbボタンでジャンプ。時間切れでゲームオーバーとかの設定になる。


#画面作りの基本
①まずActerで小さな部品を作る。マリオなら右へ移動、左へ移動、ジャンプなど
②①の部品を組み合わせたActerを作成。マリオなら①の部品を組み合わせて操作キャラのマリオを作成
③②をまとめたLayerを作成。マリオなら敵出現ポイント、動く足場ゾーンなど
④LayerをSeaneに貼り付ける。


#Acterで部品を作る
Acterには、『Acter実行条件』と「Acter実行内容」を設定する。この2つはペアになる。
Acterには複数のペアを設定でき、さらに１つの条件に複数の実行内容を書いたり、複数の条件で１つの動きを設定できる。

例えば、【マリオ右歩き】のActerなら
Acter：マリオ
ペア1:『→矢印キー押下』,「１秒で20pt等速で右移動」,「右へ歩く画像切り替えActer呼び出し」
ペア1:『→矢印キー離す』,「移動停止」,「右向き停止画像に切り替え」

となり、このようなActerを組み合わせて最終的に大きなActerを組み上げる

#注意事項
プロジェクト作成時、どのプラットフォーム向けに製造するかを決定できる。
後から変更も可能だが、できるならこの時点で製造予定のプラットフォームを決め打ちし
同じものを選択した方がよい。
後から変更すると縦横比の影響とかでおかしくなる。
Memo: Create version specific ansible environment on docker ce w/Dockerfile

# Create version specific ansible environment on docker ce w/Dockerfile

## Objectives

- Personal memo
- Simple and fast

## System

- http://qiita.com/hirofumihida/items/3aecb46b1a5b7b645330

## Instructions

### 1. Create Docker file

```shell-session:specify_version_at_last_line
FROM centos:7
RUN set -x && \
    yum -y update && \
    yum -y install git python-setuptools libffi-devel python-devel gcc python-crypto openssl-devel && \
    easy_install pip && \
    pip install paramiko PyYAML Jinja2 httplib2 six && \
    pip install ansible==2.3.0.0
```

### 2. Build

```shell-session
sudo docker build -t ansible-2.3 .
(snip)
Successfully built ca8da6f11190
```

```shell-session
ubuntu@ubuntu-zesty:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ansible-2.3         latest              ca8da6f11190        34 seconds ago      504 MB
```

### 3. Run

```shell-session
sudo docker run -i --name ansible-2.3_20170530 -t ansible-2.3 /bin/bash
```

```shell-session
[root@d5a53b5b28e6 /]# ansible --version
ansible 2.3.0.0
  config file =
  configured module search path = Default w/o overrides
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
```
Installation memo: vagrant + ubuntu/zesty64 + docker ce w/ some tricks

# Installation memo: vagrant + ubuntu/zesty64 + docker ce w/ some tricks

## Objectives

- Personal memo

## Limitation

- Not available zesty docker-ce repo (30/05/2017)
    - https://askubuntu.com/questions/909691/how-to-install-docker-on-ubuntu-17-04

## Target

- Docker CE User on Ubuntu Zesty64

## System

- macOS
- vagrant: 1.9.4
    - box: ubuntu/zesty64
- oracle virtual box

## Direction

### 1. Box add if necessary

```shell-session
vagrant box add ubuntu/zesty64
```

### 2. Box update if needed

```shell-session
vagrant box update --box ubuntu/zesty64
```

### 3. Init box /w minimal option

```shell-session
vagrant init -m ubuntu/zesty64
```

### 4. Add private network in Vagrant file

```shell-session
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/zesty64"
  config.vm.network "private_network", type: "dhcp"
end
```

### 5. Up and connect

```shell-session
vagrant up
vagrant ssh
```

### 6. Guest OS update (force)

```shell-session
sudo apt-get update -y
sudo apt-get upgrade -y
```

### 7. Install docker CE

- https://docs.docker.com/engine/installation/linux/ubuntu/#install-using-the-repository

```shell-session
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
```

```shell-session
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

```shell-session
sudo apt-key fingerprint 0EBFCD88
```

```shell-session:add_"xenial"_line_to_repo_(trick)
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
```

```shell-session
sudo apt-get update
```

```shell-session
sudo apt-get install docker-ce
```

```shell-session
sudo docker run hello-world
```

```shell-session
ubuntu@ubuntu-zesty:~$ sudo docker --version
Docker version 17.03.1-ce, build c6d412e
```
Microsoft Bot Framework 公式ドキュメント”ボットの設計”について書いてみた②

前回の[Microsoft Bot Framework 公式ドキュメント”ボットの設計”について書いてみた①](http://qiita.com/kataday/items/b8692486e03296718275)に引き続き、第２回も書いていきます。

今回は、**「ボットとの最初のユーザーインタラクション」**について。
要するに、最初のやりとりですね。

# 最初の印象は重要
ユーザーとボットの間の最初のやりとりは、ユーザーエクスペリエンスにとって**非常に重要です。**

ボットを設計するときは、単に「こんにちは」というよりも、最初のメッセージとしてもっと多くのことがあることを覚えておいてください。
アプリケーションを構築するとき、あなたは重要なナビゲーションの手掛かりを提供するために、最初の画面を設計します。
ユーザーは、

- メニューがどこにあるか？
- どのように機能しているか？
- ヘルプの場所
- プライバシーポリシー

などを直感的に理解する必要があります。
ボットをデザインするとき、ボットとの最初のやりとりは、**上記と同じ情報を提供するはずです。**
言い換えれば、**単に「こんにちは」と言っても十分ではありません。**

# メニュー　対　言語
※画像は、[利用規約 | Microsoft Docs](https://docs.microsoft.com/ja-jp/terms)に従い、表示しています。

以下の2つのデザインについて考えてみます。

- デザイン1

![alt](https://docs.microsoft.com/en-us/bot-framework/media/designing-bots/core/hello1.png)

- デザイン2

![alt](https://docs.microsoft.com/en-us/bot-framework/media/designing-bots/core/hello2.png)

「どのような御用でしょうか？」
といった自由な質問でボットと対話を始めることは一般的に推奨されていません。

もしあなたのボットが色々なことをすることが出来ても、**ユーザはそれらの大部分を推測することができない可能性があります。**
あなたのボットは何が出来るかを伝えていない中で、どのようにユーザは知ることができますか？

**メニューはその問題に対する簡単な解決法を提供します。**

まず、利用可能なオプションをリストすることにより、ボットはその機能をユーザに伝えることが出来ます。

第2に、ユーザは単にクリックすれば良いので、無駄に入力させること防ぐことが出来ます。

最後に、メニューを使用することで、ボットがユーザーから受け取る入力の範囲を狭くすることで、**自然言語モデルを大幅に簡略化できます。**

- Tip

> メニューは、優れたユーザーエクスペリエンスを提供するボットを設計する際の貴重なツールです。
> 「ボットなのに、メニューなんてスマートではない」と却下しないでください。
>
> フリー入力をサポートしながら、メニューを使用するようにボットを設計することができます。

# その他の考慮事項
直感的で簡単にナビゲートされた最初のやりとりを提供することに加えて、適切に設計されたボットは、
プライバシーポリシー及び利用規約に関する情報へのアクセスをユーザに提供します。

- Tip

> あなたのボットがユーザーから個人データを収集する場合は、それを伝え、個人データの処理内容を説明することが重要です。

# まとめ
確かに、ボットが最初に話しかけてくる内容ってすごく重要だと思う。
その問いかけが起点になって対話が成立していくわけだから、最初ボットが
「こんにちは！」
とか
「ご用件は？」
とか漠然とした問いかけをしてきたら、その後の対話が成り立たない（意味を持たない）気がする。
メニューひとつでUXが解決するなら採用しない道はない、と。

第3回、書きました。
[Microsoft Bot Framework 公式ドキュメント”ボットの設計”について書いてみた③](http://qiita.com/kataday/items/8c5235c6bfca40c304c5)
Siv3D のファイルアーカイブ機能まとめ

# Siv3D のファイルアーカイブ機能とは
画像ファイルや音声ファイル、テキストファイルなどプログラムから使う外部データをひとつのファイルにまとめることができます。

:link: [ファイルアーカイブ (Siv3D/Reference-JP Wiki)](https://github.com/Siv3D/Reference-JP/wiki/%E6%9C%AA%E5%88%86%E9%A1%9E%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%BC%E3%82%AB%E3%82%A4%E3%83%96)


# アーカイブの作成

Archive::Create() を使用します。

### サンプルコード

```cpp
// Example フォルダの内容をアーカイブファイル Example.s3a にまとめる
Archive::Create(L"Example", L"Example.s3a");
```


# アーカイブ内のテキストファイルを読み込む

TextReader、CSVReader、INIReader、XMLReader を使用できます。
リファレンスによると、読み込み可能なテキストファイルのエンコーディングは以下に限られています。

>テキストファイルは UTF-8 / UTF16-LE / UTF16-BE 形式をサポートしています。

### サンプルコード

```cpp
FileArchive archive(L"Example.s3a");

// テキストファイルを読み込む
const String text = TextReader(archive.load(L"Example/Test.txt").readAll());

// CSVファイルを読み込む
CSVReader csv(archive.load(L"Example/Test.csv"));
```


# アーカイブ内の画像ファイルを読み込む

Image または Texture クラスのコンストラクタに load 関数の戻り値 (ArchivedFileReader) を渡します。
TextureAsset を使用する場合は、TextureAssetData::FromFileArchive() を使用します。

### サンプルコード

```cpp
FileArchive archive(L"Example.s3a");

// Texture を使用する場合
const Texture texture(archive.load(L"Example/Windmill.png"));

// TextureAsset を使用する場合
TextureAsset::Register(L"windmill", TextureAssetData::FromFileArchive(L"Example.s3a", L"Example/Windmill.png"));
```

# アーカイブ内の音声ファイルを読み込む

Sound または Wave クラスのコンストラクタに load 関数の戻り値 (ArchivedFileReader) を渡します。
SoundAsset を使用する場合は、SoundAssetData::FromFileArchive() を使用します。

### サンプルコード

```cpp
FileArchive archive(L"Example.s3a");

// Sound を使用する場合
const Sound sound(archive.load(L"Example/Sound.mp3"));

// SoundAsset を使用する場合
SoundAsset::Register(L"snd", TextureAssetData::FromFileArchive(L"Example.s3a", L"Example/Sound.mp3"));
```


# アーカイブ内のフォントを使用する

FontManager::Register() を使用します。

### サンプルコード
```cpp
FileArchive archive(L"Example.s3a");

FontManager::Register(archive.load(L"Example/YomogiFont.ttf"));

const Font font(24, L"よもぎフォント");
```


# その他のフォーマットのファイルを読み込む

[公式リファレンス](https://github.com/Siv3D/Reference-JP/wiki/%E6%9C%AA%E5%88%86%E9%A1%9E%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%BC%E3%82%AB%E3%82%A4%E3%83%96)より：

>その他の形式は FileArchive::load() が返す ArchivedFileReader からバイナリデータを読み込む必要があります。

### サンプルコード
```cpp
FileArchive archive(L"Example.s3a");

ArchivedFileReader reader = archive.load(L"Example/Test.txt"); //特に意味なくバイナリ読み込みしてみる

// ファイルサイズ
Println(reader.size());

// 先頭から10バイト分読んでみる
Array<uint8> buffer(10);
reader.read(buffer.data(), 10);

for (auto c : buffer)
{
    Println((wchar)i);
}
```

# 小ネタ : アーカイブ内の画像ファイルをまとめてアセット登録

### サンプルコード
```cpp
FileArchive archive(L"Example.s3a");

for (auto path : archive.contents())
{
    if (path.endsWith(L".png") || path.endsWith(L".jpg"))
    {
        TextureAsset::Register(FileSystem::BaseName(path), TextureAssetData::FromFileArchive(L"Example.s3a", path));
    }
}
```


# :paperclips: 関連記事

:link: [Siv3Dでリソースファイルをまとめてexeに埋め込むワークフロー](http://qiita.com/aini_bellwood/items/47f8d622e9ec79452963)
Boto3を使ってAWSインスタンスを停止

AWSのインスタンスを停止する処理をBoto3で書きました。
タグを取得してリストをとってきて、グループで停止やLambdaを使って停止するなど実装していきたいと思います。

せっかく作ったのでブログにアップしてみます。


```py
# -*- coding: utf-8 -*-

# import
import boto3
from boto3.session import Session

ec2 = boto3.client('ec2')
InstanceId = 'インスタンスID'

# def
def ec2_stop():
  response = ec2.stop_instances(
    InstanceIds=[
      InstanceId
    ]
  )

# Main
if __name__ == "__main__":
  ec2_stop()
```

https://github.com/handa3/study/blob/master/aws/ec2/stop.py
Linuxデバイスドライバ第３版のサンプルをLinux4.10に移植

O'REILLYのLinuxデバイスドライバ第3版を読み進めている中で、
この本に出てくるサンプルコードはわかりやすく、サンプルの量自体も
多いので助かっているのですが、コードはLinux2.6でのビルドを想定して作られたものらしく、
LatestのLinux4.12(2017/5/30現在)から離れてきている部分も少なからずあるので、
自分で4.10でもビルドできるよう確かめながら移植をしていこうと思います。
下記のURLからたどれるGithubのリポジトリでコードを管理＆公開するので
もし必要であれば好きに参照してください。

https://github.com/nakaharadan/linux4Drivers

<a target="_blank"  href="https://www.amazon.co.jp/gp/product/4873112532/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4873112532&linkCode=as2&tag=nakaharadan-22&linkId=481fb86cf78e6fc186a93eebc8c1644f"><img border="0" src="//ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4873112532&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=nakaharadan-22" ></a><img src="//ir-jp.amazon-adsystem.com/e/ir?t=nakaharadan-22&l=am2&o=9&a=4873112532" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

上の画像をクリックして本の詳細を見ることができます🙂
WkWebviewで外部のWebサイトに繋がらないときにチェックすること

iOSアプリでWebViewを使用してサイトを閲覧する処理を実装する時には最近だとWkWebViewを使うことが多いと思います。
iOS9からATS(App Transport Security)が導入されたことで、httpのサイトやTLSに問題のあるサイトが標準では読み込めなくなり、上記のWkWebViewを使用している場合でも注意が必要です。WkWebViewで読み込み失敗すると、Storyboardが使えないこともあって真っ白の画面が表示されることが多く、問題の切り分けが難しいと思いますが、今回はそのトラブルシューティングについて何度かつまづいたので投稿します。
※WkWebViewについてやATSの話は割愛します。

## Delegateを活用する
WKNavigationDelegateを使用することで、読み込み開始時から完了・読み込み失敗等がキャッチできます。それらの処理でデバッグコードを出力することで、どの部分で止まっているのかが確認できます。

```swift:ViewController.swift
class ViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    // 読み込み開始時イベント
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        print("start")
    }

    // 読み込み終了時イベント
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("finish")
    }

    // 読み込み失敗時イベント
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print("fail")
    }
}
```

finishまで出力されて画面に表示されない場合、viewへの追加漏れ等が考えられます。

## 読み込むURLをチェックする。
Macのターミナルには標準で `nscurl` コマンドが用意されており、これを使用することでinfo.plistをどう設定すれば良いかを判定することができます。
Chromeの開発者ツールでTLS1.2を確認しても読み込めないサイトもあるため、こちらで確実にチェックすることをお勧めします。

```
nscurl --ats-diagnostics --verbose https://XXX.XXXXXXXX.XX.XX/index.html
```

大量のレスポンスが表示されますが、上から順に確認し `Result : PASS` の表記を探してください。
その上で出力されている内容をinfo.plistに記述し、再度WkWebViewで読み込めるかテストしてください。
※セキュリティを弱くするものですので、自分のサイトを読み込む等読み込む側を修正できるのであればそちらを修正することをお勧めします。

```:例
Disabling Perfect Forward Secrecy
ATS Dictionary:
{
    NSExceptionDomains =     {
        "XX.XXX.XX" =         {
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
```

```:info.plist
<plist version="1.0">
<dict>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSExceptionDomains</key>
		<dict>
			<key>sp.gch.jp</key>
			<dict>
				<key>NSExceptionRequiresForwardSecrecy</key>
				<false/>
			</dict>
		</dict>
	</dict>
〜
</dict>
</plist>
```
MoodleでX-SendFileを利用する

#X-SendFileを使う理由
通常MoodleでファイルをダウンロードするときはPHPでファイルをメモリに読み込んでから出力するが、X-SendFileを使えばPHPを経由せずにファイルをダウンロードさせられる。

#X-SendFileの設定
##メモ
[こちらのメモ](http://qiita.com/papillon/items/4c82e2af320d631f0284)によりMoodleをインストール済みだとする。mod_xsendfileはメモの手順の途中でインストールしている。

##手順
mod_xsendfile側でX-SendFileを利用可能なディレクトリを指定するため、下記のように2行追加する。

```
# vi /etc/httpd/conf.modules.d/xsendfile.conf
```

```ini:/etc/httpd/conf.modules.d/xsendfile.conf
LoadModule      xsendfile_module        modules/mod_xsendfile.so
XSendFile on
XSendFilePath /var/www/moodledata
```

設定変更後はhttpdを再起動する。

```
# systemctl restart httpd.service
```

Moodle側でもX-SendFileを利用するよう明示するする必要があるため、下記の設定をconfig.phpの途中に追記する。

```php:/var/www/html/config.php
$CFG->xsendfile = 'X-Sendfile';
```

##動作確認
X-SendFile設定後にMoodle上のファイルがダウンロード出来ればOK。今までダウンロード出来ていたファイルがダウンロードできなくなった場合はxsendfile.confの設定を疑う。
WindowsとUbuntuをデュアルブートする時はFast Bootを無効化すると良いかもしれない

あまり詳しくは調べていないので「こんなことが起こったよ」程度のメモです。

## 状況と発生した問題

* Windows 10がプリインストールされているマシンにSSDを追加した。
* 追加したSSDにUbuntu 16.04.1をインストールした。
* UEFIのブートローダの設定で、Ubuntu側を指定した。
* 1回目のブートでは、GRUBのブートメニュー（UbuntuとWindows 10のどちらを起動するかの選択画面）が表示され、UbuntuもWindows 10も正常にブートできた。
* けれども2回目以降のブートでは、GRUBのコンソール画面が表示されてしまい、ブートメニューが表示されない。
* UEFIのブートローダの設定を、一旦Windows側（Windows Boot Manager）に戻し、再びUbuntu側（GRUB）に設定すると、同様に1回目だけGRUBのブートメニューが表示され、2回目以降の起動ではGRUBのコンソール画面が表示されてしまう。

ちなみにGRUBのコンソール画面とは、`Minimal BASH-like line editing is supported.`の様なメッセージが表示され、`grub>`の様なプロンプトが表示されている画面のことを指しています。

## 対処

UEFIの設定画面にて「Fast Boot」を「Enabled」（有効）から「Disabled」（無効）に変更した。
上記の様に変更すると、2回目以降もブートメニューが正しく表示された。
VueでJSXを使ってテキスト中のURLをaタグにする

VueはtemplateプロパティにHTMLを書き、それにディレクティブを書くというスタイルで作っていきます。

```JavaScript
new Vue({
  el: "#app",
  template: "<div>{{ text }}</div>",
  data: function(){
    return {
      text: "hello world"
    }
  }
})
```

▲普通にtemplateを使用したとき

![image.png](https://qiita-image-store.s3.amazonaws.com/0/11510/badfef98-8fbb-c6a9-276b-36b2f29b9d9d.png)

これでも十分目的を果たせるのですが、 `text` に入れる文書にURLが入っており、それだけaタグにしたいというちょっと凝った要求は実現しにくいです。

そういった凝った要求には、Vueの2系列で使えるようになった `render` 関数を使うことで、テキストをパースして動的にHTMLをくみ上げていくということで満たすことが出来ます。

[描画関数 - Vue.js](https://jp.vuejs.org/v2/guide/render-function.html)

```JavaScript
new Vue({
  el: "#app",
  render: function(createElement){
  	return createElement("div", [this.text])
  },
  data: function(){
    return {
      text: "hello world"
    }
  }
});
```

▲ `render` を使用したとき

ですが、`render` 関数を普通に使おうとすると引数として渡されてくる `createElement` でHTMLをくみ上げていくことになるので、HTMLを普通にくみ上げていくのに慣れている身としては少し使いづらい感じがします。

そこで、Vueでは `render` 関数にJSXを使うことが出来るので、それを利用してHTMLを組むのに近い感覚で凝った要求を満たそうと思います。

## パッケージのインストールとJSXの使用

まずJSXを使用するには `babel-plugin-syntax-jsx` `babel-plugin-transform-vue-jsx` `babel-helper-vue-jsx-merge-props` をインストールします。これをインストールすると `render` 内でJSXを書くことが出来るようになります。

上の例をJSXで書くと以下のようになります。

```JavaScript
new Vue({
  el: '#app',
  render (h) {
    return <div>
      { this.text }
    </div>
  },
  data: function(){
    return {
      text: "hello world"
    }
  }
});
```
▲ `render` でJSXを使ったとき


## テキスト中のURLをaタグにする

JSXで書けるようになったので、テキスト中のURLをaタグにする処理を書いてみます。少し無理矢理感が否めませんが以下のように書きました。

```JavaScript
const regex = /http(:\/\/[-_.!~*¥'()a-zA-Z0-9;\/?:¥@&=+¥$,%#]+)/

new Vue({
  el: '#app',
  render (h) {
    let processTextArray = this.parseText();
    return <div>
      { processTextArray.map((text) => {
        if(text.match(regex)) {
          return <a href={text}>{text}</a>
        } else {
          return text
        }
      })}
    </div>
  },
  data: function(){
    return {
      text: "hello world http://www.google.com/ http://www.facebook.com/"
    }
  },
  methods: {
    parseText: function(){
      let processText = this.text

      let match
      let matchObj = {}
      let count = 0

      while ((match = regex.exec(processText)) != null) {
        count += 1
        matchObj[`[${count}]`] = match[0]
        processText = processText.replace(match[0], `[${count}]`)
        console.log(processText)
      }

      const keys = Object.keys(matchObj)

      keys.forEach((key) => {
        processText = processText.replace(key, `,${matchObj[key]},`)
      })
      return processText.split(',')
    }
  }
});
```

▲ テキストを処理するメソッドを用意する

テキストを処理するメソッドを用意し、そこから得られた文字列の配列がURLだったときaタグにするようにしています。

メソッドの処理としては簡単にURLがマッチしたら `[1]` のような特定できる適当な文字列で置き換え、置き換えたものを再度 `,` をつけたURLで置き換え、最後に `,` で分割しています。

多分もっと良いやり方があると思うのですが、いったんこれで目的を達することが出来ました。

## まとめ

以上、VueでJSXを使い、DOMを構築してみました。`createElement` を使ったやり方よりもわかりやすくDOMを構築できたと思います。URLをパースする方法はもうちょっと良い方法がある気がしますが、これは今後の課題にしておきます。
【Docker】Dockerfile内でGithubのプライベートレポジトリをcloneする

# やりたいこと

Dockerfile内でプライベートレポジトリをクローンしてごにょごにょしたい時に、credentialの渡し方に迷ったのでメモ。

具体的には以下のようなプライベトレポジトリのpythonパッケージを含んだ`requirements.txt`を`pip install -r requirements.txt`でインストールしたい。

~~~ requirements.txt
...
git+https://github.com/<private-org>/<private-repo>
...
~~~

# やったこと

[プライベートキーをCOPYして使う方法](https://stackoverflow.com/questions/23391839/clone-private-git-repo-with-dockerfile)があるだったが、鍵を渡すのはなんだかなーという感じだったので、[OAuthトークンを使う方法](http://qiita.com/Jah524/items/fa68f99c8b787f94b884)で実行。
OAuthトークンはHTTPSでクローンする時の[パスワードとして使うことができる](https://help.github.com/articles/git-automation-with-oauth-tokens/#step-2-clone-a-repository)

`.netrc`に認証情報を書き込んでおき`requiremqnts.txt`を変更せずレポジトリをクローンできるようにする。

~~~ Dockerfile
ARG GITHUB_USER
ARG GITHUB_TOKEN
RUN touch /root/.netrc \
    echo machine github.com >> /root/.netrc \
    echo login $GITHUB_USER >> /root/.netrc \
    echo passowrd $GITHUB_TOKEN >> /root/.netrc \
    pip install -r requirements.txt \
    rm /root/.netrc
~~~

# ビルド実行

以下のようにImageをビルドする。ユーザー名とOAuthトークンを`ARG`として渡して認証する。

``` bash
$ docker build --build-arg GITHUB_USER=<github-user-name> --build-arg GITHUB_TOKEN=<github-oauth-token> .
```

# 参考

https://stackoverflow.com/questions/23391839/clone-private-git-repo-with-dockerfile

http://qiita.com/Jah524/items/fa68f99c8b787f94b884

https://devops.profitbricks.com/tutorials/configure-a-docker-container-to-automatically-pull-from-github-using-oauth/

https://help.github.com/articles/git-automation-with-oauth-tokens/

http://qiita.com/azusanakano/items/8dc1d7e384b00239d4d9
音声認識としての StreamRelay.NET.exe

.NET Framework では、[System.Speech.Recognition 名前空間](https://msdn.microsoft.com/ja-jp/library/system.speech.recognition(v=vs.110).aspx)で、標準で音声言語認識エンジンへのアクセス手段(API)を提供している

よって、StreamRelay.NET.exeでは、標準入出力(-LocalPort=0 or -RemotepPort=0)の入力側オプション(-LocalSpeachVoiceRecognizerName or -RemoteSpeachVoiceRecognizerName)として実装した

### コマンドの実行例

`StreamRelay.NET.exe -localport 0 -remoteport 0 -LocalSpeachVoiceRecognizerName ja-JP`
とすると、「カルチャ=ja-JP」言語認識エンジンを用いて、マイクからの音声から言語認識して、(「リモート」と呼称するストリーム側の出力はコンソールなので)文字列が表示されるだろう

### オプション

- 音声言語認識エンジン
- -LocalSpeachVoiceRecognizerName "Culture"
- -RemoteSpeachVoiceRecognizerName "Culture"

### インストールされている音声言語認識エンジンの一覧

オプション
`StreamRelay.NET.exe -ListVoiceRecognizer`

### カルチャいろいろ

カルチャ指定なので、いろいろなカルチャ一覧を出力できるようにした

- **-ListAllCulture** : Display List CultureInfo List(All)
- **-ListInstalledCulture** : Display List CultureInfo List(InstalledOnly)
- **-ListNeutralCulture** : Display List CultureInfo List(Neutral)
- **-ListSpecificCulture** : Display List CultureInfo List(Specific)

### 日本語音声認識エンジン

- MS-Windows10 には既定で、日本語音声合成エンジンがインストールされているようだ

### 認識率

あまりよくないような気がする

---
### 目次へ戻る

[目次というか最初の一歩](http://qiita.com/tomoki0sanaki/items/85f20cbe18378e33cd6f)
Ansibleを使ってリモートホストにDockerをさくっとセットアップする

# あらまし

VPSで確保したリモートホストにDockerを入れようとしたが、
手順が面倒そうだったので、Ansible GalaxyのRoleを用いてインストールしてみた。

# 環境

さくらのVPSでインストールしたUbuntu 16.04 Server

# 手順

Ubuntu 16.04はデフォルトでPythonが入っていないようだ。

そのため、まずSSHでログインしてPythonをインストールしておく。

```shell-session
$ sudo apt-get install python
```

次に、以下の2つのファイルを用意する。

`your-host`は対象とするホスト名またはIPアドレス。

```:hosts
your-host
```

```yml:install-docker.yml
- name: Run docker.ubuntu
  hosts: all
  roles:
    - angstwad.docker_ubuntu
```

以下のコマンドを実行する。
`your-user`は対象とするホストのユーザ名（この名前でSSHログインするようだ）。

```shell-session
$ ansible-galaxy install angstwad.docker_ubuntu
$ ansible-playbook -vvvv -i hosts install-docker.yml -u your-user -k -K -s
```

しばらく待つと、インストールが完了する。

# 参考

https://galaxy.ansible.com/angstwad/docker_ubuntu/