OmniAICreator/Qiita-1.07M huggingface dataset:
Jupyterを使ってみた

# はじめに
　最近、Pythonを初めて、[Jupyter](http://jupyter.org/)（旧 IPython notebook）という便利なツールがありましたので、ご紹介します。
　今回は、Windows環境でのインストールから簡単な使い方までを記述します。
　Jupyterは、Pythonの実行コードとその結果を併せて保存しておくことができます。ファイル形式は、拡張子：ipynbで保存されます。

# インストール

```
C:\> python -m pip install jupyter
```

　インストールが完了したら、以下のコマンドでブラウザを起動します。

```
C:\> jupyter notebook
```

**補足**
　コマンドが見つからない場合は、Pythonインストールディレクトリ配下のScriptsフォルダにありました。

# 使い方

## Jupyter起動
　コマンドプロンプトにおいて、ファイルを保存するディレクトリにカレントを移動させます。

```
C:\> cd c:\ipython
c:\ipython>jupyter notebook
```

　ブラウザが起動したら、以下の感じの画面が表示されます。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/138869/f2b73a3c-ef0c-9bf3-f48b-fbba16f6a171.png)

**補足**
　Jupyterを起動するとデフォルトで8888ポートを使用されます。ポート番号を変えたい場合や標準のブラウザ以外を使用したい場合は、以下のコマンドで起動します。
　標準のブラウザ以外で操作を行いたい場合は、jupyter起動後に表示されるURLを使用して操作を行います。

```
jupyter notebook --port 9999 --no-browser
```

```
[I 13:35:47.793 NotebookApp] Serving notebooks from local directory: c:\ipython
[I 13:35:47.793 NotebookApp] 0 active kernels
[I 13:35:47.793 NotebookApp] The Jupyter Notebook is running at: http://localhost:9999/?token=c14fad948ae8309d7d89ce8b8c454693274209bb8f76f9c3
[I 13:35:47.794 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 13:35:47.795 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:9999/?token=c14fad948ae8309d7d89ce8b8c454693274209bb8f76f9c3
```

　Jupyterの画面が開けたら、「New」メニューから「Python3」を選択してファイルを作成します。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/138869/787e0850-e487-8734-39d3-4f4c520ca567.png)

　Pythonのコードを入力できる画面が表示されますので、コードを入力してShift+Enterで実行：`Run Cells`します。

![9.png](https://qiita-image-store.s3.amazonaws.com/0/138869/c9a26945-88f6-6cbc-ed31-277cfce8fd4d.png)


## Markdownの記述
　CellをMarkdownに変更することでMarkdown記法で文章を記述できます。

```
# Jupyterの使い方
**Markdown**記法で書けます。
```

![8.png](https://qiita-image-store.s3.amazonaws.com/0/138869/8e0ac1d0-8c67-1f5d-3f42-5bbd8f0218f7.png)


　Markdown記法の書き方については、以下のサイトを参考にさせて頂きました。

[文章作成やメモ書きにも便利、Markdown記法](http://kojika17.com/2013/01/starting-markdown.html)
[Markdown記法 サンプル集](http://qiita.com/tbpgr/items/989c6badefff69377da7)

## matplotlibのグラフをインライン表示

　とても便利な機能でmatplotlibで生成したグラフとPythonコードをセットで保存できます。

```
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(-3, 3, 0.1)
y = np.sin(x)
plt.plot(x, y)
```

![6.png](https://qiita-image-store.s3.amazonaws.com/0/138869/99762b67-3f6a-e791-0358-03b860b2e07d.png)

　ちなみに、セルで以下を実行すると、上記の`%matplotlib inline`および`import`が不要となります。

```
%pylab inline --no-import-all
```

## ショートカットキーの使い方

　Jupyterの画面において、ESCキーを押すことでCommand Modeになります。
　Helpメニューのkeyboard shoutcutsでショートカットキーが確認できます。

![7.png](https://qiita-image-store.s3.amazonaws.com/0/138869/a7f01419-063b-7a5e-4689-8ff0b05ca060.png)
redis_storeを使っているときRails.cache.clearはDBをまるまる吹っ飛ばすから注意

# 概要

Railsのキャッシュストアにredis_storeを用いている場合、Rails.cache.clearを呼び出すとキャッシュストアが使っているDBのデータが全部消えます。なのでキャッシュ用DBとそれ以外の用途のDBは分けておきましょう。

# 実験

設定ファイルはこんな感じ

```ruby:config/initializers/redis.rb
require 'redis'
Redis.current = Redis.new(
  host: 'redis://localhost',
  port: 6379,
  db: 0
)
```

```ruby:config/application.rb
...
...
  config.cache_store = :redis_store, {
    url: 'redis://localhost',
    port: 6379,
    db: 0
  }
...
...
```

では、試してみましょう。

```
# 書き込み
> Rails.cache.write('aaa', 'aaa')
=> "OK"
> Redis.current.with { |redis| redis.set('bbb', 'bbb') }
=> "OK"

# 読み込み
> Rails.cache.read('aaa')
=> 'aaa'
> Redis.current.with { |redis| redis.get('bbb') }
=> 'bbb'

# キャッシュクリア後読み込み
> Rails.cache.clear
=> nil
> Rails.cache.read('aaa')
=> nil
> Redis.current.with { |redis| redis.get('bbb') }
=> nil
```

`Rails.cache.write` で書き込んだ分以外もまとめて消えてしまっているのがわかります。

redis_store の実装を見てみるとわかるように、 `Rails.cache.clear` はRailsのキャッシュが使っているRedis DBに対して `flushdb` を行っています。そりゃ全部消えちゃうわけですね。
https://github.com/redis-store/redis-activesupport/blob/master/lib/active_support/cache/redis_store.rb#L247-L253

# 対処

キャッシュストアとそれ以外で、Redis DBを分けておきましょう。

```ruby:config/initializers/redis.rb
require 'redis'
Redis.current = Redis.new(
  host: 'redis://localhost',
  port: 6379,
  db: 0
)
```

```ruby:config/application.rb
...
...
  config.cache_store = :redis_store, {
    url: 'redis://localhost',
    port: 6379,
    db: 1
  }
...
...
```
spacemacsのコマンドメモ

[Simple Tutorial](https://simpletutorials.com/c/2883/Spacemacs)
[Spacemacs Documentation](https://github.com/syl20bnr/spacemacs/blob/master/doc/DOCUMENTATION.org)
[EmacsをVimのごとく使う](http://tarao.hatenablog.com/entry/20130303/evil_intro)

---
#### Show Help
```
spc h k
```

#### Cancel
```
ctrl g
```

#### Eyebrowse
```
spc l 1
spc l r # set a tag to the current workspace
```

#### Search
```
spc s s
```

#### Redo
```
spc a u
```

#### Dired
```
spc f j
```

#### Quit Editor
```
spc q q
```

#### Get back into command mode
```
Esc
ctrl [
fd # rapidly press
```

#### Change .spacemacs configuration file
```
spc f e d # open the .spacemacs file (edit user-config section)
spc q r   # restart spacemacs, to make sure your changes take effect
```

#### Switch window
```
spc w j # move to the bottom window
spc w c # close the window
```

#### NeoTree
```
spc f t # NeoTree should open
shift K # to go up a directory
enter   # open the selected file
spc o t # NeoTree toggle
```

#### Find File in project
```
spc p f
```

#### Helm Find File
```
spc f f # fuzzy-search for files in the directory
ctrl h  # to go up a directory
tab     # auto-complete
ctrl j  # to go down
ctrl k  # to go up
```

#### Save file
```
spc f s # save that buffer to a file
```

#### Create file
```
spc f f # Helm Find Files
# Type in the name of the new file and press enter
# Type y to create the new buffer
spc f s # to save the file
```

#### Switch between files (buffers)
```
spc b b
*scratch* # emacs lisp
spc m e e # execute
```

#### Jump back to the previous buffer
```
spc tab # the previous buffer appear
```

#### Find Text
```
spc /   # find text in project
spc *   # find text under cursor in project
spc s l # resume last search
:.,$s/<find text>/<replace text>/gc # find and replace text in buffer, from current line
```

#### Layer
[the list of available layers](http://spacemacs.org/layers/LAYERS.html)
```
M-m f e h # already available in spacemacs
```

#### Switch font size
```
spc z x # bring up the scale-font menu
ctrl +  # to change font size (bind in .spacemacs)
ctrl -  # to change font size (bind in .spacemacs)
```

#### Quickly jump somewhere in a buffer using Avy
```
spc j j # avy word
spc j l # avy line
```

#### Window Layouts
```
spc l l # create a named layout
spc l S # save a layout by name
spc l <number of layout> # switch to layout
```

#### Yank History
```
spc r y # show previous things you've copied (yanked)
```

#### Comment
```
g c c # comment on / off
gc    # comment out highlighted text
```

#### Show whitespace
```
spc t w
```

#### Create a keyboard shortcut
```
# spc f e d
# (defun dotspacemacs/user-config ()
# (spacemacs/set-leader-keys "ot" 'neotree-toggle)
# spc o and spc m o are reserved for user
```
iOS(iTunes Connect / iOS Developer Center)/Android(Google Play Console)権限まとめ

モバイルアプリをリリースする上で避けては通れない各アプリストア(App Store/Google Play)とその管理画面。
ハマる人も多いと思いますのでまとめてみました。
(Android側については、自信ありませんので間違い等ありましたら指摘していただければ幸いです。。。)

## App Store
App Storeの管理画面の全体像は以下の図のようになります。
![Group.png](https://qiita-image-store.s3.amazonaws.com/0/33395/6f44cf5c-665b-2901-0cb8-4764f22b1212.png)
App Store上のアプリを管理するためのiTunes Connectと、
apple IDやPush通知など実装的な内容を管理するためのiOS Developer Centerが存在し、
その双方にアクセス可能なAgent権限ユーザーと各サイトにのみアクセス可能なユーザーがいるという構成になっています。

### Agent権限ユーザー
Appleの開発者アカウントを取得する際に利用したアカウントがAgent権限を持ちます。
Agent権限ユーザーは、

- 唯一、iTunes Connect/iOS Developer Centerの双方にアクセスできるユーザーで  
(iTunes ConnectとiOS Developer Centerのアカウント管理は別)
- iTunes Connect/iOS Developer Centerの全てにアクセスできるユーザー  

であり、アプリ売上の口座情報さえ変更可能なため、取り扱いには注意が必要です。

### [iTunes Connect](https://itunesconnect.apple.com)
iTunes Connectは、App Store上で表示される以下のような内容を管理するためのサイトです。

- タイトル
- アプリの説明
- キーワード
- アイコン
- スクリーンショット
- 価格
- 売上
- etc...

これらの情報を管理するために以下のような役割があります。

- Admin(契約の締結とアプリの譲渡を除く全ての権限を持つユーザー)
- Developer(アプリの更新等を行うために利用)
- Sales(アプリのダウンロード数や売上の確認に利用)
- etc...

### [iOS Developer Center](https://developer.apple.com/account/ios/certificate/)
証明書やProvisioning Profile、開発で利用する端末などを登録するためのサイトです。
そういった情報を管理するための以下の3つの役割が存在します。
(法人のみ。個人では、Agent以外存在しない)

- Agent
- Admin  
(契約の締結とメンバーシップの更新を除き、Agentとほぼ同じ権限を有する。)
- Member  
(ダウンロード系の操作のみ可能。作成、編集等の作業はできない。)

## Google Play
Google Playの管理画面の全体像は以下のようになります。

![Google Play.png](https://qiita-image-store.s3.amazonaws.com/0/33395/7282a150-8f13-2d8a-7342-b47ccafca63a.png)

App StoreにおけるAgent権限ユーザーのように、全ての権限を保有するユーザーである
**アカウント所有者**が存在してはいますが、管理画面がGoogle Play Consoleのみであったり、
役割と権限の扱いがかなり柔軟であったり、とApp Storeは大きく違った構成になっています。

### [Google Play Console](https://developer.android.com/distribute/console/index.html)
Google Play Consoleは、Google Play上のアプリを管理するためのサイトです。
Google Play上で表示する以下のような内容を管理することができます。

- タイトル
- 簡単な説明
- 詳しい説明
- アプリアイコン
- スクリーンショット
- etc...

これらの情報を管理するために、Google Play Consoleでは以下の役割と権限が用意されています。
![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/33395/ba8d9648-8924-3970-a144-e063f4d85742.png)

Google Play Console上の役割と権限は、役割ごとに付与される権限が決まっており変更ができないiOSと違い、あらかじめ用意された役割とそれに紐付く権限はあるものの、任意の権限を選択し独自の役割を作ることもできる非常に柔軟なものになっています。

## 参考
- [iTunes Connect](https://itunesconnect.apple.com)
- [iOS Developer Center](https://developer.apple.com/account/ios/certificate/)
- [Google Play Console](https://developer.android.com/distribute/console/index.html)
- [プログラムにおける役割と iTunes Connect における役割 - Apple Developer Support(公式)](https://developer.apple.com/support/roles/jp/)
- [デベロッパー アカウント ユーザーの追加と権限の管理 - Play Consoleヘルプ(公式)](https://support.google.com/googleplay/android-developer/answer/2528691?hl=ja)
Selenium Python Bindingsでブラウザの言語を指定してシークレットモードでページを開く(Chrome)

「Webブラウザ経由のGUIしか設定手段がない」MWの構築を自動化できないかと模索していたときに、検索しても意外とすぐ出てこなかったのでメモ。

```
$ pip install selenium
$ brew install chromedriver
```

```sample.py
# -*- coding: utf-8 -*-
from __future__ import division, print_function, absolute_import, unicode_literals

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

options = webdriver.ChromeOptions()
options.add_argument('--incognito')  # secret mode
options.add_experimental_option('prefs', {'intl.accept_languages': 'en_US'}) # locale=en_US

# use local driver
driver = webdriver.Chrome(chrome_options=options)

## use remote driver
#driver = webdriver.Remote(
#    command_executor='http://127.0.0.1:4444/wd/hub',
#    desired_capabilities=options.to_capabilities())

driver.get("https://www.debian.org/")
assert "Debian" in driver.title
elem = driver.find_element_by_name("P")
elem.clear()
elem.send_keys("debi_fujin")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()
```

実行するとこんな感じになります。

```
$ python sample.py
```

![6月-17-2017 22-48-19.gif](https://qiita-image-store.s3.amazonaws.com/0/50184/26c75b83-6905-c1ab-3877-1c07f1461a79.gif)

しょうもないハマりどころとしては

* www.google.com 等、接続元のIPアドレスを見て言語を切り替えているページには通用しない(当たり前ですね…)
* [selenium-serverのDockerイメージ](https://hub.docker.com/r/selenium/standalone-chrome-debug/)には日本語フォント等が入ってない

あたりです。

参考: [【Selenium】python \+ ChromeDriver で Accept\-Language ヘッダを設定する方法 \- miyajan blog](http://miya-jan.hatenablog.com/entry/2016/07/21/230620)
Firebase Tools + jqメモ

## Firebase Tools

**Install**

* [firebase/firebase-tools](https://github.com/firebase/firebase-tools)

```bash
$ npm install -g firebase-tools
```

**Login**

```bash
$ firebase login
$ firebase list
```

**Database**

ログインするアカウントの権限によっては上階層でのデータの置き換えが可能になるので注意

データを取得します。

```bash
$ firebase database:get --project <YOUR PROJECT ID> /users
```

データを追加します。

```bash
$ firebase database:push --project <YOUR PROJECT ID> /news test.json
```

データを置き換えます。
*指定した/news直下にあるデータを置き換えるので注意*

```bash
$ firebase database:set --project <YOUR PROJECT ID> /news test.json
```

データを更新します。

```bash
$ firebase database:update --project <YOUR PROJECT ID> /news test.json
```

データを削除します。

```bash
$ firebase database:remove --project <YOUR PROJECT ID> /news
```

## jq

* [jq](https://stedolan.github.io/jq/)

firebase-toolsの標準出力JSONは見づらいのでjqで整形します。

**Install**

```
$ brew install jq
```

**Usage**

```bash
$ firebase database:get --project <YOUR PROJECT ID> /news | jq
```
SaaSForceの画面レイアウト作成からアプリ画面を作る方法

![wfc20161109026.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/198e24fd-9830-c25c-3da5-872e2fcff310.jpeg)

本来、SaaSForceでは1.テーブル項目作成、2.画面項目作成、そして、3.画面レイアウト作成の3段階でアプリを作ります。

今回はその常識を破って、いきなり3の画面レイアウト作成からアプリ画面を作ってみます。

これは、アプリそのものではないのですが、画面を先行して作成してイメージを共有する場合、他の人と一緒に使うケースや依頼されてアプリを作っているケースで顧客との相談の際に便利な機能です。

まずは、SaaSForceにログインをして画面作成から画面レイアウト作成を選び、検索条件をクリックします。

すると、検索条件の画面が降りてきてその中に「新規」と言うボタンがあるので押します。

![wfc20161109027.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/5a460203-6fa8-cbc7-71fa-861be05e5068.jpeg)

画面追加と言うポップアップ画面が出てくるので、作りたいアプリの必要なパーツの数を入力していきます。

今回は説明なので全てのパーツを1つ作っていきます。

保存して次へのボタンを押すと、メニュー表示箇所を追加する「フォルダ追加管理」の画面がポップアップしますので、今回はtestの『画面名』を選んで登録をします。

![wfc20161109029.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/2e637511-c490-5701-f462-d3ea7c9643c6.jpeg)

この作業が完了すると、このように画面レイアウトに一つのテストと言うメニュー画面が増えています。

![wfc20161109030.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/a4c7f2fa-b93b-9688-9fe8-06a5801b0fab.jpeg)

念のため編集を押して画面を確認しておくと、このような感じで表示されます。

![wfc20161109031.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/0b8e3f47-ac2a-4a59-5bf2-72c72e094184.jpeg)

更に念を入れて、システムからシステム設定を開き、初期表示画面を見てください。

![wfc20161109032.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/f6f166c5-41a7-d142-c36b-d9c31586912c.jpeg)

このように空欄の場合、アプリが表示されません。

![wfc20161109033.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/1a0e1319-47c1-12ab-373f-26597468772a.jpeg)

ドロップダウンリストになっているので、testを選んで、右上の端に見える更新をクリックしてください。

これで下準備は完了です。

後は、一度ログアウトしてから、テストサーバーにログインしなおすだけです。

そして、確認するとyoutubeの動画などきちんと見ることができるので、おそらく他のパーツもテーブルが必要と言うもの以外は動くはずです。
Python2からPython3への移行(Python2は仮想環境として再構築し共存化)

WindowsでのPython2からPython3への移行(共存化)の備忘録

## やりたいこと
1. Python2からPython3への移行  
そろそろPython3をメインに使用したくなったので導入することに
2. Python2も使えるようにしておきたい(共存)  
これまで書いてきたコードを全て書き直すのは面倒なためPython2.7も使えるようにしておきたい   
condaを使ってpython2.7仮想環境の仮想環境を構築する方法でPython3とPython2の共存を実現する(後述)
3. 開発環境(Jupyter, PyCharmの設定)  
普段使用しているJupyter, PyCharmにおいてpython2, 3を選択できるようにする


## 1.Python2からPython3への移行
### 1.1 Python2のアンインストール
プログラムの変更と削除からPython2.7をアンインストール

### 1.2 Python3のインストール
Anacondaで導入する
Anacondaのサイト(https://www.continuum.io/downloads )に行き、最新のAnaconda(Python3)のインストーラーをダウンロード
インストーラーを実行

![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/780ea7a1-c3b6-9eb6-94f3-a03ea2ae34c2.png)

Anacondaを入れる場所を選択

PATHを追加するか聞かれるので今回は「はい」を選択
これを選択しない場合自分でPATHを追加する必要あり
2つめのチェックボックスも「はい」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/29c13f08-3ca5-06a3-4f21-6bce80edf0e1.png)

無事にPython3のインストールに成功

## 2.Python2の環境構築

condaを使いAnaconda3内にPyrhon2の仮想環境を構築する
コマンドプロンプトにて以下を実行
パッケージはあとから追加可能


```
# conda create --name [仮想環境名] python=2.7(好きなバージョン) [パッケージ] ... [パッケージ]
conda create --name python27 python=2.7 numpy scipy pandas jupyter

# 今回はpython2.7を単体で入れ、パッケージを追加する形にしたが、anacondaを入れることも可能
conda create -n anaconda2 python=2.7 anaconda
```
~Anaconda3/envsのディレクトリに指定した環境名のフォルダができているはず
![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/475fcaae-a1ac-61dc-6c65-22195b61115c.png)




### 仮想環境への出入り

``` 
# 仮想環境に入る
# activate [仮想環境名]　
acitvate python27
# 仮想環境から出る
# deactivate [仮想環境名]
deactivate python27
```
#### パッケージの管理
Python3とPython2の環境ではパッケージは共通されないため、使いたいパッケージはそれぞれの環境に入れる必要がある

Python3の環境に入れるのは普段通りcondaやpipで可能
Python2の仮想環境に入れるには一度仮想環境を有効化してからcondaやpipを使用する

```
activate python27;conda install numpy
activate python27;pip install numpy

conda install --name python27 numpy # condaの場合、このように環境名を指定して入れる操作することもできる
pip install --name python27 numpy # これはできない×
```

## 3.開発環境の整備
普段使用している開発環境でPython2とPython3の両方を選択できるようにする
### 3.1 Jupyter
このままではAnaconda3で入れたjupyterを起動してもPython3しか選択できない
![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/406a0887-a1fb-1700-0111-025fc5e59a88.png)

カーネルの追加という作業をする必要がある

```
# まず仮想環境を有効化
activate python27
# kernelの追加は以下のコマンドでできる
ipython kernel install --user --name=python27 --display-name=Python2
```

--name : 環境名
--display-name : jupyterで表示される名前

追加されたカーネルは、~AppData\Roaming\jupyter\kernelsの中に存在する
カーネルを削除したい場合はこのフォルダからそのカーネルを削除すれば良い

これによりjuypterからPython2も選択できるようになった
![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/1a30be5c-4713-226e-9390-7972c612624b.png)


### 3.2 PyCharm

File→Setting→Project Interpreterを選択
赤丸で示した部分を選択
Add Localを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/ef90dfe3-7716-1887-82ff-4a8b7df3baa7.png)



先程いれた仮想環境のpython.exeを選択
Anaconda3\envs\python27\python.exe
Apply
![image.png](https://qiita-image-store.s3.amazonaws.com/0/190972/879533fa-483f-24da-ab28-a3c9c352ac22.png)

これでPyCharmでPython2の方も選択できるようになった



## 参考
データサイエンティストを目指す人のpython環境構築 2016 http://qiita.com/y__sama/items/5b62d31cb7e6ed50f02c
Jupyterで複数カーネルを簡単に選択するための設定 http://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e
テーブルのリファクタリングフロー

　１つのサービスを拡張させていると、テーブルの再設計が必要になる時があります。自分が経験したのだと、顧客マスタ群とか、商品マスタ群とか。

　使ってないカラムや冗長なフラグ、無駄に分かれたテーブルなど目に余るようになったらリファクタしましょう。そんなテーブルリファクタリング時の失敗しない処理フローをメモ。

「そんなの当然じゃね？」ってものだと思うけど、実際にやる時になるとその都度考えちゃったりするものなので・・・

# テーブルリファクタリングフロー
1. 新テーブル(群)の設計
   - 過去からの移行のし易さや過度に先を見越した設計はゴミになるので今のあるべき形で設計する
2. CRUDの[C]部分への新テーブルの組込み
   - システムの該当データを作る部分に新テーブルへのinsert処理を組込む
   - 旧テーブルへの処理はそのまま残す
3. CRUDの[U]部分への新テーブルの組込み
   - システムの該当データを作る部分に新テーブルへのupdate処理を組込む
   - 旧テーブルへの処理はそのまま残す
   - 尚、論理削除や業務的なデータ削除は 9.ではなく、ここで対応する
4. 旧テーブルから新テーブルへのデータ移行
5. 外部参照制約の張り替え
   - 旧テーブル群自体や関連テーブルに付けられている外部参照制約を新テーブル側を参照させる様に張り替える
6. CRUDの[R]部分を新テーブルを参照するように差し替える
   - システムの該当データを参照する部分を新テーブルに向ける
7. CRUDの[U]部分から旧テーブルへの処理を削除
   - システムの該当データを更新する部分から旧テーブルへの処理を削除する
   - 3.と同様、論理削除や業務的なデータ削除部分もここで対応する
8. CRUDの[C]部分から旧テーブルへの処理を削除
   - システムの該当データを登録する部分から旧テーブルへの処理を削除する
9. CRUDの[D]部分への新テーブルの処理の追加及び旧テーブルの処理の削除
   - システムの該当データを抹消する部分（ガーベージ）に新テーブルからの処理を追加する。また同時に旧テーブルからの処理を削除する
10. 旧テーブルをリネームする
   - 旧テーブルを削除前に寝かせる。障害を検知するための最後の猶予期間
11. 旧テーブルを削除する

---
(補足)
_各ステップで行うシステムの対応順序(1)_
1. 単独のプログラム（軽微なシェルや依存関係のない小さなバッチなど）
2. コアになるプログラム
3. 共通ライブラリなど
4. データベースオブジェクト（PL/SQLなど）

_各ステップで行うシステムの対応順序(2)_
1. 社内システム
2. 公開システム

_※ 影響範囲の小さなものから大きなものに広げていくだけ_

---

　ちなみに、工数的な問題で旧テーブルをViewにして残すことが行われることもあるけど、データ構造のリファクタでは__絶対やめた方がいい__です。問題を先送りにすることで、負の遺産の「負っぷり」がめちゃくちゃ大きくなります。
　一時的にView化ってのはありだけど、スケジュール上の通過点としてじゃなきゃやっちゃダメです。後方互換性、ダメ、絶対。
私が本当に使っているLinuxのコマンド一覧 - Extra編

# はじめに

- Linuxを使っている人には当たり前だけど、オプションとか含めると結構忘れて都度調べたりするのでまとめました。
- 他に思い出したら追加、変更、削除していきます。
- 特別かっこいいこと（オプションつけたりパイプつけてごにょごにょしたり）とかしていないのでご了承ください。
- 今回は、基本Linuxに備わっているコマンドではなく、yumやhomebrewなどで入れて使うコマンドを中心的に扱ってます。

# 用途別コマンド一覧

## ファイルをとりあえずダウンロードしてきたい

wgetとcURLは似たようなことできますので、お好みでどうぞ。

```zsh
wget {ダウンロードURL}
```

## どこかにHTTPリクエストの投げたい

### GETで投げたい

```zsh
curl --request GET \
  --url '{URL}?{パラメータ}' \
  --header 'cache-control: no-cache' \
```

### POSTで投げたい

```zsh
curl --request POST \
  --url {URL} \
  --header 'cache-control: no-cache' \
  --header 'content-type: multipart/form-data; \
  --form {キー}={バリュー} \
```

## JSONファイルをJSON形式に整形してみたい

こちらはMac環境の解説になります。

### インストール

```zsh
brew install jq
```

### ファイルの出力

```zsh
cat composer.json | jq '.'
```

# よくやる実践コマンド一覧

## ソースコードからインストールしたい

### ソースコードをダウンロードします。
### ソースコードを解凍します。ダウンロードしてきたファイルの拡張子は、ほとんどが「tar.gz」ではないでしょうか。その場合に使うコマンドは、

```zsh
tar -zxvf xxxx.tar.gz
```

ちなみに、圧縮したい場合は、

```zsh
tar -zcvf xxxx.tar.gz
```

### 解凍したディレクトリに移動します。

### インストール準備をする。「configure」コマンドはオプションで追加したい設定やパッケージなどを指定します。

```zsh
./configure
--with-hogehoge={インストール先}
```

### コンパイルとインストールを実行する。

```zsh
make && make install
```

## ファイルやディレクトリのショートカットを作成したい

```zsh
ln -s {リンク元} {リンク先}
```

## インストールしたプログラムを実行したいけどコマンドが見つからない

### まずは以下のコマンドでプログラムが見つかるか確認します

```zsh
which {プログラム名}
```

### 上記のコマンドが実行できない場合、もしかすると環境変数が通っていないかもしれません。環境変数の確認してみます。

```zsh
env
```

### 環境変数の設定をします

bashの場合は、.bashrcや.bash_profileにPATHの記述をします。
http://qiita.com/magicant/items/d3bb7ea1192e63fba850

### 現在開いているプロンプトを開きなおします。開き直したくない場合は、PATHを適当させます。

```zsh
source ~/.bashrc
```
# シリーズページリンク
- [私が本当に使っているAtomのパッケージ一覧](http://qiita.com/neriai/items/b43c2efbc06370fe193c)
- [私が本当に使っているVimのコマンド一覧](http://qiita.com/neriai/items/d05e65698f7cbe7efe3c)
- [私が本当に使っているLinuxのコマンド一覧 - 常用編](http://qiita.com/neriai/items/622053317ec4a4cd197a)
- [私が本当に使っているLinuxのコマンド一覧 - Extra編](http://qiita.com/neriai/items/5322dd0fe34bbccbefdb)
traceroute監視アラートShell作成

<h1>背景</h1>

tracerouteした際に、!Xが含まれてたらフィルタリングされているから問題ないけど、それが外れたらまずいんでアラート飛ばせるようにしてほしいと依頼を受けた。

<h2>作成</h2>
参考：http://calcabrina.net/archives/53/

作成したのは以下

```
#!/bin/sh
IP_ADDR_ARRAY=("***.***.***.***");

NUM=0
for IP in ${IP_ADDR_ARRAY[@]}
do
  log_file="/root/shell/tr_${IP}_`date +%Y%m%d%H%M`.txt"
  traceroute ${IP} > ${log_file}
  if grep -q !X ${log_file}

  then
    echo "${IP} : OK" > /dev/null 
    rm ${log_file}

  else
    echo "${IP} : NG" | mail -s "*** Alert: Filter error. ***" ***@xx.co.jp
  fi
  NUM=`expr ${NUM} + 1`

done

```

上から
`IP_ADDR_ARRAY=("***.***.***.***");`
ここで監視対象を指定。複数指定する場合は半角スペースを開けて記載する。

`for IP in ${IP_ADDR_ARRAY[@]}`
指定アドレスを配列として読み込む。

``log_file="/root/shell/tr_${IP}_`date +%Y%m%d%H%M`.txt"``
tracerouteの出力先を指定。IPごと、分ごとにリネームするよう設定してます。


`  traceroute ${IP} > ${log_file}
  if grep -q !X ${log_file}`
tracerouteの出力から"!X"という文字列を探す。!Xがあればフィルタリングされていると判断していい(らしい)


`then`
`echo "${IP} : OK" > /dev/null `
`rm ${log_file}`

`else
echo "${IP} : NG" | mail -s "*** Alert: Filter error. ***" ***@xx.co.jp`

!XがあればOKです、/dev/nullを外せば普通にOKと出力されます。
正常に出力されているのでログファイルは削除で。

!XがなければIP：NGという本文で指定したメアドに送るようにしています。

それをループするように指定してます。


<h3>その他</h3>

・実行権限を付けないとcronで実行されないのでchmod 755とかにしてください。
・IPの指定はtarget.listとかにした方がスマートよね。今回はIP指定が一つだけだったので直書きしてます。

---

2017/07/07　17:31追記
複数IP指定した際、最後のIPがNGの場合にしかログが残らないのでは？というご指摘を受けたのでlog_file指定をdoの中で実施するよう変更。
ClickOnce Publish - Folder / Product name

##
In the Publisher name text box, type the name of the folder that will be listed on the Windows Start menu. In the Suite name text box, type the name of the subfolder that will appear under the Publisher name (optional), and in the Product name text box, type the name of the application shortcut.
 You can also specify a Support URL and an Error URL that users can go to if they experience installation problems.
 At a minimum, you must complete the Publisher name and Product name.

![2017-07-07_144430.jpg](https://qiita-image-store.s3.amazonaws.com/0/114634/d9a093cb-fe6b-c77d-3ff6-a47f6b30edd0.jpeg)
javascriptでアコーディオンを作成しましたのでmemo

とりあえず、javascriptをのせます。

```javascript
var slide = {
  get : document.getElementById("任意のid"),
  classA : document.querySelector("selecter"),

  play : function(){

    addClassA = slide.classA.classList;
    
    function clickEvent(){
      addClassA.toggle("side-open");
    }

    slide.get.addEventListener("click",clickEvent,false);

  },
}
slide.play()
```
cssです。

```css
  .menu-list {
    transform: translate3d(0,-266vw,0);
    -webkit-transform: translate3d(0,-266vw,0);
    transition: all .8s;
    -webkit-transition: all .8s;
    opacity: 0;
  }

.side-open.menu-list,
.side-open.menu-list {
  opacity: 1;
  -webkit-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
}

```

ニュアンスでなんとなくわかるとおもいます。
動作自体は、GPUでうごかしましょう。
あとは、jsでつけて外してをやればokかと思います。

では、参考までに
javascriptでreplaceイベントを作成したのでmemo

とりあえずjavascript

```js
var resizeValue = (function(){
    var w, h;
    return {
        getNowWindowWidth: function () {
            return w = window.innerWidth;
        },
        getNowWindowHeight: function () {
            return h = window.innerHeight;
        }
    }
})();

var replacePlay = function(){
  if (resizeValue.getNowWindowWidth() <= 980) {
      if (flag == false) {
          $rep.forEach(function(index) {
              type = index.getAttribute("src").match(reg)[2];
              index.setAttribute("src", index.getAttribute("src").replace("." + type, "_sp." + type));
          });
          flag = true;
      }
  } else {
      if (flag == true) {
          $rep.forEach(function(index) {
              type = index.getAttribute("src").match(reg)[2];
              index.setAttribute("src", index.getAttribute("src").replace("_sp." + type, "." + type));
          });
          flag = false;
      }
  }

};

var getPartu = function(){

  $rep = document.querySelectorAll(".js-replace");
  flag = false;
  type = "";
  reg = /(.*)(?:\.([^.]+$))/;

  window.addEventListener('resize',replacePlay,false);

};
getPartu();

```

getAttributeとsetAttributeの活かし方がキモです。
あとは、forEachです。

では、参考までに
SlackのInteractive Messageでワークフローを実現するためのちょっとした工夫

# TL;DR

- SlackのInteracive Messageにおいて複数回メッセージのやりとりをしようと思うとステートフルにならざるをえない
- JSONなどの構造化データを使ってやりとりすることでステートレスにワークフローを実現する

# Interactive Message

SlackのMessage送信では[Interactive Message](https://api.slack.com/interactive-messages)という仕組みを用いて、ただのテキストのやりとりだけではない、リッチなインタラクションを実現する手法を提供している。

具体的には以下のようなメッセージを送信してユーザからのインタラクションに使える。

- メニュー<br>
![menu](https://a.slack-edge.com/5069/img/api/message_menus_triforce_pm.png)
- ボタン<br>
![button](https://a.slack-edge.com/dcb1/img/api/message_guidelines/Example_6.gif)

> Yes, interactive messages work on Enterprise Grid and on internal integrations built for your team. **A Slack app is required**.

ちなみにInteractive Messageを使うためにはSlack Appである必要がある。

# ワークフローの実現とステートフル

これらのUIを用いることで例えば何かを選択させて確認メッセージを表示してから、Approve、Cancelを押させてワークフローを確定させる、といったことを実現できる。
この場合、以下のような3つのメッセージを送信することになる。

1. 選択メニュー表示
2. 選択された情報を元に確認メッセージを表示しつつ、最終確認のため、Approve, Cancelボタンを表示する
3. 押されたボタンの処理を実行し、完了メッセージを表示する

このとき最終的にApproveされた場合には、当然`2.`で取得した選択項目を使用して処理を実行してあげる必要がある。
またそもそもの最初のメニューを表示させるトリガーの実行時(replayとかslash message)になんらか引数を渡して処理を実行させたい場合もある。
そのような情報は2->3へのボタンクリック時のリクエストに含まれてこないので、そのようなデータをどこかに保存してワークフロー単位でステートフルに処理を実行させる必要がある。

Nodeで作られた[公式サンプル](https://github.com/slackapi/sample-message-menus-node)をみてみると、メッセージを送信したユーザIDをkeyにして、プロセス内のObjectにデータを突っ込んでいっていることがわかる。
↓の辺。
https://github.com/slackapi/sample-message-menus-node/blob/master/lib/bot.js#L66-L77

ユーザIDだとあんまりだけど、つまりはなんらかメッセージ毎にユニークなIDを決めてそれをkeyにセッションデータをどこかに保存してあげる必要がある。
オンメモリだと再起動したらデータ消えるんでちゃんとやろうと思ったら、Redisとか使う必要がある。

# JSONをValueにして常にやりとりする

いまのところSlackの[Message Object](https://api.slack.com/docs/interactive-message-field-guide)内にはPayload的なものをいれておけるfieldは存在しない。

Interactionが発生した場合は、JSONで元のメッセージと実行されたActionの情報がやってくる。
[この中](https://api.slack.com/docs/interactive-message-field-guide#action_fields)には、callback_idやvalueが送られてくる。
このvalueにJSONを文字列として過去のインタラクションで送られてきた情報を常につけ足していくことで、サーバサイドに保存することなしにやりとりができる。

menu1でhoge、menu2でfugaと選択した場合は、確定ボタンのvalueに`{"menu1":"hoge","menu2":fuga"}`を渡してサーバサイドでパースしてあげればよい。

```json
{
    "text": "これでよいですか？",
    "attachments": [
        {
            "callback_id": "confirmBtn",
            "attachment_type": "default",
            "actions": [
                {
                    "name": "ok",
                    "text": "OK",
                    "type": "button",
                    "value": "{\"menu1\":\"hoge\",\"menu2\":\"fuga\"}",
                    "style": "primary"
                },
                {
                    "name": "cancel",
                    "text": "Cancel",
                    "type": "button",
                    "value": "cancel",
                    "style": "danger"
                }
            ]
        }
    ]
}
```

常にクライアントサイドから送信されてくるので改竄の危険性があるが、verificationTokenをチェックするのでそんなには気にする必要ないかと。
やりとりがセンシティブなら、JWTとかにして署名つきで送信すればいいんじゃないかと。
Serverless Frameworkでremoveの前にS3 Bucketの中身を空にするpluginを作った

# about
Serverless Frameworkは便利ですね。
LambdaだけじゃなくてAWSリソースも一元管理できますし。
```sls remove```で一括削除もできる、マジ便利です。

ただ、```sls remove```は現実的によくありそうなシチュエーションで失敗してしまいます。
そのシチュエーションに陥ると、手動でstack削除を行い、それとは別に原因のリソースを取り除く必要があります。
地味に面倒です。

ということで、失敗を起こさないようにするために作ったのが今回のpluginです。

# 現象
```sls remove```に失敗する理由は単純、CloudFormationで作成したS3 Bucketが空ではないから。

```
  Serverless Error ---------------------------------------
 
  An error occurred while provisioning your stack: dataBucket - The bucket you tried to delete is not empty.
```

裏を返せば、Bucketが空なら削除できるので、removeされる前に自動で空にできれば問題なく```sls remove```できる。

# plugin ***serverless-s3-remover***
そういうことで作成したのがこの [serverles-s3-remover](https://github.com/sinofseven/serverless-s3-remover) です。
```sls remove```を実行すると、CloudFormationのStack削除よりも先に起動し、指定したS3 Bucketの中身を削除します。

## 使い方

### 1. インストール
```
$ npm install serverless-s3-remover 
```
プロジェクトフォルダにインストールするだけ。
多分```--save```オプションを付けるのが正解な気もする。
serverless同様に```-g```オプションでグローバルインストールしてもいいと思う(これは試してないけど)。

### 2. serverless.yml に追記
```yaml
custom:
  bucket-name: my-bucket-3
  remover:
    buckets:
      - my-bucket-1
      - my-bucket-2
      - ${self:custom.bucket-name}
```
bucketの下に配列で空にするS3 Bucketの名前を入力する。
CloudFormationでBucketを作成することを考えると、serverless.ymlの変数を使った方が安全だと思う。

### 3. 実行
```bash
$ sls remove
```
これだけでCloudFormationのStack削除より先にBucketの中身を空にしてくれる。

手動でBucketの中身を空にしたいときは次のコマンドでやれる。

```bash
$ sls s3remove
```

# 課題
現時点では削除するだけなので、別Bucketに避難させる機能とかあるといいのかもしれない(多分これは実装しない)。
あとは手動削除時も配列で指定したBucket全てを空にするので、オプションを付けて指定できるようにしたほうがいいのかもしれない(要望があれば実装するかも)。

とりあえず思いつく課題はこんなものですが、もし他にあればコメントなりissueなりで教えていただけると、モチベーションによっては、実装するかもしれません。

ということで、serverlessでS3 Bucketを作成した人は使うとremoveが若干楽になるかもしれませんので、気が向いたら使ってやってください。
帳票出力の設定:画面レイアウト編

帳票出力の最終段階です。

ビュー定義、帳票テンプレート、そして、帳票出力定義が終わった、やっと終了かと思った方、すみませんがもう少しお付き合いください。

くどいようですが、エクセルで設計書が書けるようになると、この作業すらいらなくなるのです。

でも、設計書が掛けるその日までは、この4つの段階を踏まないといけません。

もしかしたらもっと簡単な方法があるかもしれませんが、私はそこまで精通していませんので、スタンダードなやり方をご紹介したいと思います。

![wfc20161109016.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/f8ce3802-26b5-dce0-332c-badb0a0ea115.jpeg)

まずは画面作成から、画面レイアウト作成を開き、そして編集をクリックします。

![wfc20161109017.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/3b972f2a-1935-6573-d8cc-92ef1b6bf3f8.jpeg)

そして、画面が別ウィンドウで開いたら、すぐに項目追加をクリックします。

すると次の画面がポップアップされます。

![wfc20161109018.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/236e0d50-9c7b-832b-d005-5d5ae82a5d62.jpeg)

出力ボタンに付けたい名称を入力して、「20.印刷ボタン」をドロップダウンリストから選択します。

すると自動的にポップアップ画面の形が変わります。

保存を押すと、画面の上にこのようなポップアップが現れますので、OKを押してください。

![wfc20161109020.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/b9540b6a-7d57-ce93-d6ef-a5d446798d49.jpeg)

すぐに、印刷ボタン設定と言う画面が現れます。

間違ってスルーしても、また、後で変更したい場合は、ボタンのパーツを右クリックすると設定できるようになっています。

![wfc20161109021.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/cbb41e73-64ff-5be3-df48-30300cb9609c.jpeg)

今回は「帳票テンプレート」を選んでチェックを入れ、PDFを選択してみました。

そして画面項目をドロップダウンリストの中から適切な物を選び、保存するだけです。



いかがだったでしょうか、ビュー定義からこの画面レイアウトの作業までやや時間がかかったかもしれませんが、これでデーターベースアプリで重要な機能といえる帳票の出力設定ができました。

後は、データーを入力するかインポートして、そして、エクセルやPDFにするだけです。
javascriptでfadeするsliderを作ってみたmemo

とりあえすjavascriptはこんな感じです

```js
  var fadeA = {
    width : 1000,
    height : 600,
    index : 0,
    parent : document.getElementById("slider-main"),
    activeA : document.querySelectorAll(".slider_img"),

    play : function(){

      for(var i = 0; i < fadeA.activeA.length-1; i++){
          fi = fadeA.activeA[i].classList;
          fi.add("fadeIn");
      }

      function interVal(){

        g = fadeA.parent.firstElementChild;
        j = g.nextElementSibling;
        j_ = j.classList;
        j_.add("fadeIn");
        d = fadeA.parent.appendChild(g);

      }
      // interVal();
      setInterval(interVal, 2000)
    },
  }
  fadeA.play();
```

続いて、cssです。

```css
@keyframes fadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

.fadeIn {
  animation-name: fadeIn;
}

.fadeTarget{
  animation-duration: 1.5s;
  animation-fill-mode: both;
 }

```

後は、sliderをつくる時のhtmlやcssを書いて完成とゆう感じです。
C#の単純な文字列連結で最も高速な方法は？

文字列連結の方法はケースバイケースで使い分けますが、単純な場合にどれが早いのかと疑問に思ったので計測。
# コード
```csharp
var c = 10000000;
var sw = new System.Diagnostics.Stopwatch();

// StringBuilder
sw.Start();
for (int i = 0; i < c; i++)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("%").Append(i).Append("%");
    var str = sb.ToString();
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());

// +演算子
sw.Restart();
for (int i = 0; i < c; i++)
{
    var str = "%" + i + "%";
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());

// string.Format
sw.Restart();
for (int i = 0; i < c; i++)
{
    var str = string.Format("%{0}%", i);
}
sw.Stop();
Console.WriteLine(sw.Elapsed.ToString());
return;
```

# 出力
```
00:00:01.8321544
00:00:01.6269853
00:00:02.1980389
```
速度は +演算子 > StringBuilder > string.Format() でした。
単純な処理の場合はつべこべ言わずに+で繋げておけという感じでしょうか。
差がごくわずかなのでstring.Format()で可読性を取るのもアリでしょう。

あくまで単純な例なので実用上は実際に計測してみてください。
ES6で文字列の長さを正しく取得する

## lengthで文字列の長さを正しく取得できないケースがある
一般的にJavaScript文字列のlength属性で文字列の長さを取得できますが、日本語第３水準字、第４水準字、絵文字などのUnicodeで表現する文字が正しく取得できない場合があります。

- 絵文字の例：🙏

```js
const str = '\u{1F64F}';
console.log(str + 'の長さ：' + str.length);
```

実行結果：
```
🙏の長さ：2
```

## ES6の配列展開で正確な文字列の長さを取得する
配列展開（Array Spread）で文字列を文字配列に変換するときに、文字列に含まれる個々のunicode文字が正しく分けられます。

```js
const str = '\u{1F64F}';
console.log(str + 'の長さ：' + [...str].length);
```

実行結果：
```
🙏の長さ：1
```

## 参考記事
[JavaScriptでのサロゲートペア文字列のメモ](http://qiita.com/YusukeHirao/items/2f0fb8d5bbb981101be0)
ChainerRLでBreakout

chainerRLでBreakout v0をCNNでやってみました

実行はできるのですが，agentの学習が進まず，Rewardが取れません．
初心者故，なぜ学習が進まないのか教えて頂きたいです．

python2.7で以下のコードを使用しました．
アドバイスお願い致します

import chainer 
import chainer.functions as F
import chainer.links as L
import chainerrl
import gym
import numpy as np

from chainer import cuda

import datetime
from skimage.color import rgb2gray
from skimage.transform import resize

env = gym.make('Breakout-v0')
obs = env.reset()

print("observation space   : {}".format(env.observation_space))
print("action space        : {}".format(env.action_space))

action = env.action_space.sample()
obs, r, done, info = env.step(action)
class QFunction(chainer.Chain):
def __init__(self,obs_size, n_action):
    super(QFunction, self).__init__(
        l1=L.Convolution2D(obs_size, 4, ksize=2,pad=1),#210x160
        bn1=L.BatchNormalization(4),
        l2=L.Convolution2D(4, 4, ksize=2,pad=1),#105x80
        bn2=L.BatchNormalization(4),
        #l3=L.Convolution2D(64, 64, ksize=2, pad=1),#100x100
        #bn3=L.BatchNormalization(64),
        #l4=L.Convolution2D(64, 3, ksize=2,pad=1),#50x50
       # bn4=L.BatchNormalization(3),

        l5=L.Linear(972, 512),
        out=L.Linear(512, n_action, initialW=np.zeros((n_action, 512), dtype=np.float32))
    )

def __call__(self, x, test=False):

    h1=F.relu(self.bn1(self.l1(x)))
    h2=F.max_pooling_2d(F.relu(self.bn2(self.l2(h1))),2)
    #h3=F.relu(self.bn3(self.l3(h2)))
    #h4=F.max_pooling_2d(F.relu(self.bn4(self.l4(h3))),2)
    #print h4.shape

    return chainerrl.action_value.DiscreteActionValue(self.out(self.l5(h2)))

n_action = env.action_space.n
obs_size = env.observation_space.shape[0] #(210,160,3)
q_func = QFunction(obs_size, n_action)

optimizer = chainer.optimizers.Adam(eps=1e-2)
optimizer.setup(q_func)

gamma = 0.99

explorer = chainerrl.explorers.ConstantEpsilonGreedy(
epsilon=0.2, random_action_func=env.action_space.sample)

replay_buffer = chainerrl.replay_buffer.ReplayBuffer(capacity=10 ** 6)

phi = lambda x: x.astype(np.float32, copy=False)
agent = chainerrl.agents.DoubleDQN(
q_func, optimizer, replay_buffer, gamma, explorer,
minibatch_size=4, replay_start_size=100, update_interval=10,
target_update_interval=10, phi=phi)

last_time = datetime.datetime.now()
n_episodes = 10000
for i in range(1, n_episodes + 1):
obs = env.reset()

reward = 0
done = False
R = 0

while not done:
    env.render()
    action = agent.act_and_train(obs, reward)
    obs, reward, done, _ = env.step(action)


    if reward != 0:
        R += reward

elapsed_time = datetime.datetime.now() - last_time
print('episode:', i, 
      'reward:', R,
     )
last_time = datetime.datetime.now()

if i % 100 == 0:
    filename = 'agent_Breakout' + str(i)
    agent.save(filename)

agent.stop_episode_and_train(obs, reward, done)
print('Finished.')
tf.nn.embedding_lookup()を使う

tf.Variableの一部のみを学習させたい，かつその対象をplaceholderなどで指定したい場合は`tf.nn.embedding_lookup`や`tf.gather`が使える．

たとえば，`[TOTAL_SIZE, DIM]`の大きなVariableがあって，その一部のみ（`[BATCH_SIZE, DIM]`）を取り出してFully-Connected Layerへの入力とする場合は以下のようにすればできる．

```embedding_test.py
import numpy as np
import tensorflow as tf

sess = tf.InteractiveSession()

TOTAL_SIZE = 10
BATCH_SIZE = 2
DIM = 3
LR = 0.01


# training target
np_x = np.random.rand(TOTAL_SIZE, DIM).astype(np.float32)
x = tf.Variable(np_x)

# indices 
np_inds = np.array([0, 3])
inds = tf.placeholder(tf.int32, [BATCH_SIZE])

# part of x
h = tf.nn.embedding_lookup(x, inds)

# a fully connected layer
w = tf.Variable(tf.truncated_normal([DIM, DIM]))
y = tf.tanh(tf.matmul(h, w))

# target data
t = tf.convert_to_tensor(np.random.rand(BATCH_SIZE, DIM).astype(np.float32))

# loss
l = tf.reduce_mean(tf.square(y - t))

# get training op of x
tvars = [x]
grads = tf.gradients(l, tvars)
train = tf.train.GradientDescentOptimizer(LR).apply_gradients(zip(grads, tvars))

feed_dict = {inds: np_inds}

sess.run(tf.global_variables_initializer())

# check that embdding_lookup() slices correctly
diff = sess.run(h, feed_dict) - np_x[np_inds, :]
assert diff.sum() == 0.0

x_before_train = sess.run(x)

sess.run(train, feed_dict)

x_after_train = sess.run(x)

print(x_before_train - x_after_train)
```

実行すると，np_indsで指定したxの0と3番目の行だけが更新されているのがわかる：

```
[[ 0.00091529 -0.00065178  0.00180614]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.00167947 -0.00147748  0.00317943]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]
 [ 0.          0.          0.        ]]
```
`tf.gather`や`tf.nn.embedding_lookup`はgradientを求めた場合`tf.IndexedSlices`が得られる．おそらく大抵のoptimizerはサポートしているはずなのであまり困ることはないはず．しかし，特定のgradientに手を加えたい，かつそれが`tf.IndexedSlices`であった場合はTensorとして扱えないので気をつける必要がある．たとえば拡大縮小したい場合は以下のような関数を用意すればエラーを回避できる：

```python:scale_gradient.py
def scale_gradient(g, scale):
    if isinstance(g, tf.IndexedSlices):
        values = g.values * scale
        return tf.IndexedSlices(values, g.indices)
    else:
        return g * scale
```
Promise だけじゃない Async/Await の紹介

# はじめに `Promise` とは
JavaScriptの非同期処理は素晴らしいです、HTTPリクエストやDBの参照など待ち時間の発生する処理が入っても不必要に待つ必要はありません。言葉を変えると待ってくれません。

```Javascript:print.js
// A
console.log(1)

// B
setTimeout(() => {
  console.log(2)
}, 1000)

// C
console.log(3)
```

```:結果
1
3
2    #1秒後
```
`B`の`setTimeout()`内が実行されるのを待たず`C`が実行されるため
`A`→`C`→1秒後に`B`の`setTimeout`内の処理 が実行されます。
AjaxのレスポンスやDBの問い合わせ結果が返ってくるまでが`setTimeout()`に置き換わるイメージです。

コールバック関数内に次の処理を書けば意図した動作にはなるのですが、何度も繰り返すとネストが深くなりコールバック地獄になる。

```Javascript:callback.js
setTimeout(()=> {
  console.log(1)

  setTimeout(() => {
    console.log(2)

    setTimeout(() => {
      console.log(3)
    }, 1000)

  }, 1000)

}, 1000)
```
```:結果
1    #1秒後
2    #さらに1秒後
3    #さらに1秒後
```

`Promise`を使うとネストせずに書ける。

```Javascript:promise.js
let A = () => {
  return new Promise(resolve => setTimeout(() => {
    console.log(1)
    resolve()
  }, 1000))
}

let B = () => {
  return new Promise(resolve => setTimeout(() => {
    console.log(2)
    resolve()
  }, 1000))
}

let C = () => {
  return new Promise(resolve => setTimeout(() => {
    console.log(3)
    resolve()
  }, 1000))
}

let promise = Promise.resolve()
promise.then(A).then(B).then(C)
```
```:結果
1    #1秒後
2    #さらに1秒後
3    #さらに1秒後
```
しかし`promise.then(A).then(B).then(C)`と指定しては再帰やループが出来ない。
出来たとしても実装が難しい。これはHaskellなど関数型言語の思考に強く影響を受けてるからだとか。
（※書き方を変えれば可能です、後述のURLにその方法が記載されています）

今回紹介したのは単純な逐次処理ですが、複数の非同期処理が全て終了したあとに実行する`.all()`や、どれか1つ終了したあとに実行する`.race()`など色々なパターンが存在するので、`Promise`を詳しく学びたいという方は下記のページがを参考にしてください。
http://azu.github.io/promises-book/
そのほかQiitaにも他の方が数多く解説記事を投稿しています。

# `Async` / `Await` の紹介
`Promise`だけだと実装が難しい場合などに便利なのが`Asynx` / `Await`です。

```javascript:async_await.js
const sleep = (n) => {
  return new Promise(resolve => setTimeout(() => {
    console.log(n);
    resolve()
  }, 1000))
}

(async () => {
  for (i of [1,2,3]) {
    await sleep(i);
  }
})()
```
```:結果
1    #1秒後
2    #さらに1秒後
3    #さらに1秒後
```


`sleep()`の部分が`Promise`を紹介したときのコードとほぼ変化がないのが分かるかと思います。
ちなみに`Async` / `Await`を使う場合は`[].forEach()`が使えません、今回のコードでは`for (i of [1,2,3]){ }`で代用しています。

`Async`で囲んだ範囲で`Await`が使用できます。
先頭に`await`を指定して関数を実行することにより、関数内の`Promise`が`resolve()`を返した時に次の処理が実行されるようになります。

`for`で囲んでしまいましたが下記のコードと同等です。

```javascript:
(async () => {
  await sleep(1);
  await sleep(2); // 1秒後に実行される
  await sleep(3); // さらに1秒後に実行される
})()
```

`Async` / `Await`を使うことによって`Promise`のハードルが低くなり扱いやすくなると思うので、`Promise`って難しそう、苦手という方にこそ先にこんなのもあると知ってもらいたいです。
帳票出力の設定：帳票出力定義

帳票の出力は、ビュー定義、帳票テンプレートの作業が終了してから帳票出力定義の作業に入ります。

ですから、以前の作業については該当する記事をご一読いただければと思います。

![wfc20161109009.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/7ab36a6a-ae22-ad31-8fde-913c714f37e5.jpeg)

帳票から帳票出力定義を選んでください。

すでに、帳票テンプレートで作成した「帳票作成ビュー」と言うビューが存在すると思います。

その編集をクリックして、別の画面を開きます。

![wfc20161109010.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/f36c95fb-d4e8-e986-600a-b065989a586b.jpeg)

新規テンプレート定義が見つかったらクリックです。

![wfc20161109011.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/4a10a991-4094-a50b-0feb-977de4bbb02d.jpeg)

ポップアップ画面で「テンプレート定義」と言うものがでてきます。

先にテンプレート選択をして、次に、セルと属性と言うものを、テンプレートとして作成したエクセルのシートの通りに入力します。

![wfc20161109012.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/ebe27f76-4485-8980-5d9c-227f5d753c87.jpeg)

これが元になったエクセルのシートで、このセルに該当するデーターが出力されるようですね。

![wfc20161109013.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/dba89d03-c337-c18e-29d2-28370c9a3140.jpeg)

このような感じで入力し、属性は選択していきます。

このポップアップ画面を保存して終了です。
帳票出力の設定:テンプレート編

データーベースアプリには必要な機能です。

現在、SaaSForceではエクセルやPDFなどの出力ができるようです。

この機能は、ビュー定義ができなければ使うことができません。

そして、ビュー定義はSQLが使える必要があります。

この時点で、一切のプログラミング知識がない私のようなタイプはNGなのですが、最近導入されたエクセルファイルをアプリ化する機能があれば、SQLの知識が無くてもビューが作れることが判明しました。

更にいえば、帳票出力設定もエクセルでできるようです。



しかしながら、現時点でエクセルもうまく使えないので、また、資料的な価値もあるので帳票出力の設定までの手順を記録したいと思います。



![wfc20161109004.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/c6a75802-6ff9-d6db-49f8-cd8b85b665d2.jpeg)

帳票から帳票テンプレートを選びます。

そして、検索条件をクリックすると検索条件の画面が下にスライドしてくるので、『新規』を押します。

ここで、ビューのところで出てきたフォルダを思い出しておいてください。

![wfc20161109006.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/20d71b5a-accf-b68e-7b9b-4be584490c9b.jpeg)

こういうものです。

これは、ワンダフルフライ㈱から送ってもらった現時点で最新のサンプル設計書のファイルです。

![wfc20161109007.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/d3b40158-ac83-6004-f8e9-7456e0411f84.jpeg)

新テンプレーと指定でこの「帳票テンプレート.xlsx」を選びます。

![wfc20161109008.JPG](https://qiita-image-store.s3.amazonaws.com/0/184885/c633cd8d-8b44-4c89-7084-414927cef835.jpeg)

次に、ステップ３のリスト設定にチェックを入れて、リスト名とデーターの行数を入力します。

このとき、事前に作ったテンプレートをみて、必要な行数を確認しておいてください。

最後に更新をクリックして、テンプレートの設定は終わりです。
[Emacs] C-h を backspace として使用する方法

ググってもやり方がバラバラだったので私が現在使用している方法を書いておく。
M-h で単語を消しているが C-w で消したい人は M-h を C-w に変更するだけ。
ヘルプは C-? に退避させている。

```el
(define-key key-translation-map (kbd "C-h") (kbd "<DEL>"))
(define-key key-translation-map (kbd "M-h") (kbd "<C-backspace>"))
(define-key key-translation-map (kbd "C-?") (kbd "C-h"))
(define-key key-translation-map (kbd "M-?") (kbd "M-h"))
```

GUI ではなく CLI で使用している人は control shift のキーが使用できないのでこちら

```el
(define-key key-translation-map (kbd "C-h") (kbd "<DEL>"))
(define-key key-translation-map (kbd "M-h") (kbd "<C-backspace>"))
(define-key key-translation-map (kbd "DEL") (kbd "C-h"))
(define-key key-translation-map (kbd "M-DEL") (kbd "M-h"))
```

私はヘルプはバックスペースに退避させている。
バックスペースを潰してしまうのが気にくわない人は別のキーを見つけるべし。
bundle exec が面倒だから direnv 使って省略する。

# 実行ファイルを置いてもらう

bundle install のオプションをこうする。

```
bundle install --path vendor/bundle --binstubs vendor/bundle/bin -j4
```

これで vendor/bundle/bin に実行ファイルが置かれる。

# PATH を通す

[direnv](https://github.com/direnv/direnv) を使う。

1 インストール

```
brew install direnv
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
```

2 設定ファイルを作る

```
cd project_directory
direnv edit .
```

3 書き込む

```
PATH_add vendor/bundle/bin
PATH_add bin
```

これで rubocop とか rspec とか自由に叩ける。

# 副作用

素敵な副作用として、プロジェクトディレクトリで vim を立ち上げると vendor/bundle/bin/rubocop を使ってくれる。
クラウドサーバでTensorFlow　その4

#概要
クラウドサーバでTensorFlowやってみた。
tf.imageを、やさしく説明してみた。

#TensorFlow.image

```
adjust_brightness              RGBまたはグレースケール画像の明るさを調整します。
adjust_contrast                RGBまたはグレースケール画像のコントラストを調整します。
adjust_gamma                   入力画像に対してガンマ補正を行います。
adjust_hue                     RGB画像の色合いを調整します。
adjust_saturation              RGB画像の彩度を調整します。
central_crop                   画像の中央領域をトリミングします。
convert_image_dtype            image_dtypeを、変換します。
crop_and_resize                画像から抽出し、サイズを変更します。
crop_to_bounding_box           バウンディングボックスに画像を切り抜きます。
decode_gif                     GIFでエンコードされた画像をデコードします。
decode_image                   decode_gif、decode_jpegとdecode_png。
decode_jpeg                    JPEGエンコードされた画像をデコードします。
decode_png                     PNGでエンコードされた画像をデコードします。
draw_bounding_boxes            画像のバッチにバウンディングボックスを描画します。
encode_jpeg                    イメージをJPEGエンコードします。
encode_png                     イメージをPNGエンコードします。
extract_glimpse                入力テンソルから抽出します。
flip_left_right                画像を左右に反転します。
flip_up_down                   画像を上下に反転させます。
grayscale_to_rgb               グレースケールからRGBに変換します。
hsv_to_rgb                     イメージをHSVからRGBに変換します。
non_max_suppression            スコアの降順で境界ボックスのサブセットを選択します。
pad_to_bounding_box            パディングをバウンディングボックスに変換します。
per_image_standardization      平均がゼロになるように線形に変換します。
random_brightness              画像の明るさをランダムに調整します。
random_contrast                画像のコントラストをランダムな係数で調整します。
random_flip_left_right         画像を左右にランダムに反転します。
random_flip_up_down            ランダムに画像を上下反転します。
random_hue                     RGB画像の色相をランダムな係数で調整します。
random_saturation              RGB画像の彩度をランダムな係数で調整します。
resize_area                    面積補間使用するようにサイズ変更します。
resize_bicubic                 双三次補間してサイズを変更します。
resize_bilinear                双線形補間してサイズを変更します。
resize_image_with_crop_or_pad  画像を幅と高さに切り取り、またはパディングします。
resize_images                  サイズを変更します。
resize_nearest_neighbor        最隣補間してサイズを変更します。
rgb_to_grayscale               イメージをRGBからグレースケールに変換します。
rgb_to_hsv                     イメージをRGBからHSVに変換します。
rot90                          画像を反時計回りに90度回転させます。
sample_distorted_bounding_box  ランダムに歪んだバウンディングボックスを生成します。
total_variation                画像の合計変動を計算して返します。
transpose_image                第1次元と第2次元を入れ替えてイメージを転置します。
            
```
漢字１文字がUTF-8で３バイト、URLエンコードで９バイト

『Real World HTTP』を読んでいたら、以下のようにあった。

```
漢字１文字がUTF-8で３バイト、URLエンコードで９バイトなります。(P.23)
```

よくわからなかったので調べた。

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

たとえば、「木」という漢字は、UTF-8では`E69CA8`と表される。

これは３バイトになる。

なぜかというと16進数1桁は4ビットで表されるため、`E69CA8`は6桁であることから、
4ビット * 6桁 / 8ビット で 3バイトになる。

また、なぜ16進数1桁は4ビットで表せるかというと、4ビットは2の4乗（すなわち16通り）の表現が可能だから。

そして、`E69CA8`をパーセントエンコーディングすると`%E6%9C%A8`になる。

このとき、1文字は1バイトで表され、%E6%9C%A8は9文字なので、9バイトとなる。

## 疑問
漢字に限らず、ひらがな・かたかなでも同じく、「UTF-8で３バイト、URLエンコードで９バイト」になるのではないか。

## 引用元
https://www.oreilly.co.jp/books/9784873118048/
外部APIを利用したら、高トラフィックを捌けなかった

## 経緯

外部APIを利用して大量データをリクエストした時のお話。

__Too many open files__ というエラーが発生し処理ができない、、

##何がおきたのか

####接続しているソケットのファイルディスクリプタがオーバーフローしている様です。

ファイルディスクリプタって何?って方はこちらの記事を
http://qiita.com/toshihirock/items/78286fccf07dbe6df38f

リクエストする側はLinuxのチューニングで対処できそうですが、(下記の記事を参考)
http://qiita.com/snaka/items/b6520303e37ebde298d2 

APIサーバ側は触れないのでどうしようにもない、、

##対応

Too many open filesのクラス　__Errno::EMFILE__をハンドリングして、ソケット切替り & コネクションの確立を待機して対応。
setTimeoutをasync/awaitプログラミングで使う

`setTimeout`のようなコールバック型の非同期関数をasync/await化する、言い換えると`Promise`を返すようにするのは、以下のような関数を用意してあげることでできます。

```js
function timeout(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
```

こうしておくと、

```js
async function my_function() {
  ...
  await timeout(5000);
  ...
~
}
```

のようにasync/awaitコンテキストで、もしくはPromiseチェーンの起点としてこのラッパ関数を使えます。
こんな短い記述なのでわざわざ関数にラップするまでもなく直書きでも十分ですが。


```js
async function my_function() {
  ...
  await new Promise(resolve => setTimeout(resolve, 5000));
  ...
~
}
```

TypeScriptなら上記`timeout`の定義はこうなりますね。

```ts
function timeout(ms: number): Promise<void> {
  return new Promise<void>(resolve => setTimeout(resolve, ms));
}
```

また、失敗時のコールバックも登録できる関数、例えば`$.ajax`とかなら

```js
function jq_ajax(url, options) {
  return new Promise((resolve, reject) =>
    $.ajax(url, options).done(resolve).fail(reject));
}
```

のように`reject`（Promiseのコンストラクタに渡すコールバックの2個目の引数）を使うことでラップできます。この失敗ケースは`Promise`の`catch()`で拾うかasyncコンテキストのtry-catchで捕まえるかできるわけです。
クラウドサーバでTensorFlow　その3

#概要
クラウドサーバでTensorFlowやってみた。
restoreして、global_stepを保存するやつ。

#環境
クラウド idcf
linux debian-8.11
tensorflow 1.2
gpu 無し

#サンプルコード


```
import os
import tensorflow as tf


global_step = tf.Variable(0, trainable = False)
saver = tf.train.Saver()
with tf.Session() as sess:
	tf.global_variables_initializer().run()
	ckpt = tf.train.get_checkpoint_state(os.getcwd())
	if ckpt:
		print ("restore")
		saver.restore(sess, ckpt.model_checkpoint_path)
		step = global_step.eval()
    else:
        step = 0        
	for i in range(6):
		print (step + i)
	global_step.assign(step + i).eval()
	saver.save(sess, os.getcwd() + "/global_step2.ckpt")



```