OmniAICreator/Qiita-1.07M huggingface dataset:
KeyboardViewのandroid:codes一覧表

ドキュメントが全然なくて困ったので作ってみた。
ctrl+F (⌘+F)で検索！
<font color="red">※正確性は保証しません</font>


(0〜32までは全て半角スペースが入力される)

| android:codes | 入力される文字 |
|:-:|:-:|
|33| ! |
|34| " |
|35| # |
|36| $ |
|37| % |
|38| & |
|39| ' |
|40| ( |
|41| ) |
|42| * |
|43| + |
|44| , |
|45| - |
|46| . |
|47| / |
|48| 0 |
|49| 1 |
|50| 2 |
|51| 3 |
|52| 4 |
|53| 5 |
|54| 6 |
|55| 7 |
|56| 8 |
|57| 9 |
|58| : |
|59| ; |
|60| < |
|61| = |
|62| > |
|63| ? |
|64| @ |
|65| A |
|66| B |
|67| C |
|68| D |
|69| E |
|70| F |
|71| G |
|72| H |
|73| I |
|74| J |
|75| K |
|76| L |
|77| M |
|78| N |
|79| O |
|80| P |
|81| Q |
|82| R |
|83| S |
|84| T |
|85| U |
|86| V |
|87| W |
|88| X |
|89| Y |
|90| Z |
|91| [ |
|92| \ |
|93| ] |
|94| ^ |
|95| _ |
|96| ` |
|97| a |
|98| b |
|99| c |
|100| d |
|101| e |
|102| f |
|103| g |
|104| h |
|105| i |
|106| j |
|107| k |
|108| l |
|109| m |
|110| n |
|111| o |
|112| p |
|113| q |
|114| r |
|115| s |
|116| t |
|117| u |
|118| v |
|119| w |
|120| x |
|121| y |
|122| z |
|123| { |
|124| &#124; |
|125| } |
|126| ~ |

以上。(多分)
Python3 からシステムコールを呼ぶ

## システムコールの番号を調べる
```shell-session
$ ausyscall --dump
0	read
1	write
2	open
3	close
...

$ ausyscall msgget --exact
68
```

または

```text
/usr/include/x86_64-linux-gnu/sys/syscall.h
/usr/include/x86_64-linux-gnu/bits/syscall.h
/usr/include/x86_64-linux-gnu/asm/unistd_64.h
```
あたりを見ても分かるようです。

## ctypes モジュールを利用して呼び出し
```python
import ctypes
import os

# 上で調べたシステムコールの番号
SYS_getpid = 39
SYS_msgsnd = 69
SYS_msgrcv = 70


dll = ctypes.CDLL(None)

# 引数なしの例、引数が必要な場合は dll.syscall の第2引数以降に
res = dll.syscall(SYS_getpid)
if res < 0:
    # エラーの捕捉
    print(os.strerror(ctypes.get_errno()))


# 引数に配列が必要な場合は ctypes.create_string_buffer で生成
ptr = ctypes.create_string_buffer('hello\n'.encode('ascii'))
res = dll.syscall(SYS_msgsnd, msgid, ptr, len('hello\n'), 0)
if res < 0:
    print(os.strerror(ctypes.get_errno()))


# 配列に書き込みが行われる場合も ctypes.create_string_buffer で
ptr = ctypes.create_string_buffer(1024)
res = dll.syscall(SYS_msgrcv, msgid, ptr, 1024, 0, 0)
if res < 0:
    print(os.strerror(ctypes.get_errno()))
print(ptr.value)   # 配列の中身を取得
```

これで Python でなんでもできますね :-)
docker execでコンテナ内に入ると端末の挙動がいまいちな件

# まずはdockerコンテナ内に入る

お馴染みの方法でごく単純に

```sh
docker exec -it $container_name bash --login
```

または

```sh
docker exec -it $container_name bash -l
```

# 入れるのは入れるけど

- dumb端末(画面なし扱い)になってしまうため、描画周りに難あり
- ttyがないのでscreenも使えない(起動できない)

# 対策

コンテナの/root/.bash_profileに以下を追記する

```sh:/root/.bash_profile
if [ x$TERM = xdumb ]; then
    export TERM=xterm-256color
    exec >/dev/tty 2>/dev/tty </dev/tty
    cd $HOME
fi
```

- TERMを上書きしてxterm-256color(ただのxtermでも可、お好みで)にすると描画周りが改善される
- ttyを無理やり繋いでいるのでscreenを使えるようになる

# /root/.bash_profileを書き換えるためだけにイメージをビルドし直したりしたくない

- dockerホスト側の適当なパスに上記の追記をした.bash_profileを置いておく
 - 仮に /home/your_name/container_bash_profile とする

- docker-compose.ymlに以下を追記する
 - read onlyでコンテナの/root/.bash_profileにdockerホスト側のファイルを重ねてしまう
 - docker-compose使ってない場合はdocker run -vで頑張ってください

```yaml:docker-compose.yml
    volumes:
      - /home/your_name/container_bash_profile:/root/.bash_profile:ro
```

- コンテナを立ち上げ直す

```sh
docker-compose up -d
```

# 既知の問題

- tty無理やり繋いでscreenを使えるようにはなっているけど、detachしたセッションにattachできない
 - うっかりdetachするとそのセッションにはどうやっても復帰できないので注意
 - 解決策を知っている方は教えてください
puppeteerをlumo+calvinで使ってみる

puppeteerが話題になっていて気になってみたので触ってみた。

## 使用したもの

- calvin 0.2.0
- lumo 1.7.0

## 新しいnodeをインストールする

puppeteerは古いnodeバージョンだと動かない。

筆者はUbuntuを使っているが、apt-getで入るやつのバージョンが古いので、
[こちらの記事](http://qiita.com/seibe/items/36cef7df85fe2cefa3ea)を参考に新しいバージョンをゲットした

後からnodenvなる物の存在を教えてもらった。こちらの方が好ましいらしい。

## strictモードを無効にする

- puppeteerはOctalのリテラルを使用しており、strict modeに違反している
- Lumoはデフォルトでstrictのチェックが有効になっている

なので[この情報](https://github.com/anmonteiro/lumo/issues/28)を参照してstrictチェックを無効にした。

```clj
(def v8 (js/require "v8"))
(.setFlagsFromString v8 "--no-use_strict")
```

## 動かす

### calvinのproject.clj
```clj
(defproject plc "0.0.1"
  :dependencies [[org.clojure/clojurescript "1.9.293"]]
  :cljsbuild {:builds [{:id "dev"
                        :source-paths ["src"]
                        :compiler {:main plc.core
                                   :target :nodejs
                                   :npm-deps {"puppeteer" "0.10.2"}}}]})
```

### puppeteerのReadmeの例

```js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  browser.close();
})();
```

###  無理矢理ClojureScriptに訳す
asyncとかawaitのシンタックスをどうマッピングすれば良いのか検討もつかないので返ってくるPromiseに対して`.then`メソッドを呼ぶようにしてみた。

```clj
(require '[puppeteer :as p])
(do
  (def b (p/launch #js {:headless false}))
  (def p (.then b (fn [browser] (.newPage browser))))
  (.then p (fn [p]
             (.then (.goto p "https://example.com")
                    (fn [_] (.screenshot p #js {:path "example.png"}))))))
```

上記でスクショが取れることは確認できた。
楽しそうなことに使えるので色々応用していこうと思う。
全文検索システムを立ち上げたくなったのでFess環境を構築(2)

[全文検索システムを立ち上げたくなったのでFess環境を構築(1)](http://qiita.com/kolinz/items/35c806892d476209beb0)で、Fessの環境を構築しました。構築した環境はバックアップしておくと良いでしょう。今回使用しているBluemix IaaSでは、サーバーイメージを作成することでバックアップになります。

Fess構築時点では、Fessに組み込み済みのElasticsearchを使用する設定になっていますので開発モードとして起動しています。本番運用には、Fessと同じサーバー内に、Elasticsearchをインストールするか、別サーバーにElasticsearchをインストールする必要があります。今回は、Fessと同じサーバーに、localhostとしてElasticsearchをインストールしましょう。

# ファイアウォールにてElasticsearch用ポートを開放

Elasticsearchを使用するために、localhostで動かす場合でもポート開放は必要なようですので、9200と9300を開放します。

```
# ufw allow 9200
# ufw allow 9300
```

# ElasticsearchとFess用プラグインのインストール

ElasticsearchをFessと同じサーバーにインストールします。

``` 
# wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
# echo "deb http://packages.elastic.co/elasticsearch/5.x/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-5.x.list
# apt-get update -y && apt-get install elasticsearch -y
# /etc/init.d/elasticsearch start
# /etc/init.d/elasticsearch status
```

Elasticsearchのバージョン確認
5.5.xではない場合は、5.5.0 をインストールします。

```
# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.0.deb
# dpkg -i elasticsearch-5.5.0.deb
# /etc/init.d/elasticsearch restart
# /etc/init.d/elasticsearch status
```

[Fessの公式ドキュメント](http://fess.codelibs.org/ja/11.3/install/install.html#elasticsearch)を元に、ElasticsearchのFess用拡張プラグインを追加します。

```
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-analysis-fess:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-analysis-ja:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-analysis-synonym:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-configsync:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-dataformat:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-langfield:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-minhash:5.5.0
# /usr/share/elasticsearch/bin/elasticsearch-plugin install org.codelibs:elasticsearch-analysis-kuromoji-neologd:5.5.0
```

Elasticsearchの設定ファイルに追記します。

```
# nano /etc/elasticsearch/elasticsearch.yml

　下記を追記し、Ctrl+xキーを押し、yキーで保存します。
　configsync.config_path: /var/lib/elasticsearch/config
　script.engine.groovy.inline.update: on
```

Fessの設定ファイルに、Elasticsearchを使用するための設定を追記します。

```
# nano /usr/local/src/fess-11.3.1/bin/fess.in.sh

# External elasticsearch cluster 以下の３つについて先頭の#を外し、Elasticsearchの接続先を定義します。
Ctrl+xキーを押し、yキーで保存します。


# External elasticsearch cluster
ES_HTTP_URL=http://localhost:9200
ES_TRANSPORT_URL=localhost:9300
FESS_DICTIONARY_PATH=/var/lib/elasticsearch/config/
```

拡張プラグイン導入後、Elasticsearchを自動起動するようにし、サーバーを再起動します。

```
# systemctl enable elasticsearch.service
# reboot
```



# まとめ

Fessを本番運用するために必要なElasticsearchを導入しました。今回使用の仮想サーバーは、RAM 4GBに設定しています。Elasticsearchだけで、約2GBのRAMを使っていますので、Fessの本番運用には、8GB以上などより多めのRAM(メモリ)を確保することが必要です。
Powershell で CSVから Postgres用の Upsert Sql を生成する


```ps1:使い方

#CSVを読み込む
$c = Get-Content ".\sample.csv"

#テーブル名
$tableName = "work.sample_table"
#テーブルのキー
$tableKey = "sample_pkey"

# 1行目（0番目)＝ヘッダを取り出す
[string]$sHeaders = $c[0]

# 2行目以降(1番目以降) がデータなのでループしてSQL生成。
for($k=1; $k -lt $c.Length; $k++){
  [string]$sSql = BuildUpsertSqlString -sTable $tableName -sTableKey $tableKey -sHeaders $sHeaders -sValues $c[$k]

#  ...
# sqlを使った処理をここに書く
#  ...
  
}

```


```ps1:BuildUpsertSqlString.ps1

function BuildUpsertSqlString
{
  param (
    [Parameter(Mandatory=$true)][string]$sTable,
    [Parameter(Mandatory=$true)][string]$sTableKey,
    [Parameter(Mandatory=$true)][string]$sHeaders,
    [Parameter(Mandatory=$true)][string]$sValues
  )
  
  [string[]]$aHeaders = @()
  [string]$sUpdValues = ""
  
  # double quoted
  $sHeaders = dquote -str $sHeaders
  
  # single quoted
  $sValues = squote -str $sValues
  
  # Build ON CONFLICT Values
  $aHeaders = $sHeaders -split ","
  for($i=0; $i -lt $aHeaders.Length; $i++ ){
    $aHeaders[$i] = $aHeaders[$i] + " = EXCLUDED." + $aHeaders[$i]
  }
  $sUpdValues = $aHeaders -join ", "

  $sSql = "INSERT INTO _TABLE_(_HEADERS_) VALUES(_VALUES_) ON CONFLICT ON CONSTRAINT _KEY_ DO UPDATE SET _UPDVALUES_ ;"
  
  $sSql = $sSql -replace "_TABLE_" , $sTable
  $sSql = $sSql -replace "_HEADERS_" , $sHeaders
  $sSql = $sSql -replace "_VALUES_" , $sValues
  $sSql = $sSql -replace "_KEY_" , $sTableKey
  $sSql = $sSql -replace "_UPDVALUES_" , $sUpdValues

  Write-Verbose $sSql
  return $sSql
}

# Double Quote
function dquote
{
  param(
    [string]$str
  )
  [string[]]$arr = $str -split ","
  for($i=0; $i -lt $arr.Length; $i++ ){
    $arr[$i] = '"' + $arr[$i] + '"'
  }
  $str = $arr -join ","
  return $str
}

# Single Quote
function squote
{
  param(
    [string]$str
  )
  [string[]]$arr = $str -split ","
  for($i=0; $i -lt $arr.Length; $i++ ){
    if($arr[$i] -ne ""){
      $arr[$i] = "'" + $arr[$i] + "'"
    }else{
      $arr[$i] = "NULL"
    }
  }
  $str = $arr -join ","
  return $str
}

```
ディスクコピーしたサーバーに接続ができない場合のネットワーク設定の修正方法（さくらのクラウド）

おそらくこの対応が必要な場合は、サーバーへのディスク接続時に、ディスクの修正が効かないOSなどを利用時になる。
たとでば自前でカスタマイズしたディスクアーカイブからサーバー作成、またはパブリックOS以外を利用した場合が概ね該当するはず。
※ メリット活かすならそいう選択をそもそもしないのが定石でしょう

このほかHost名なども合わせて修正

```
vi /etc/sysconfig/network-scripts/ifcfg-eth0
```

```ifcfg-eth0
HWADDR=**:**:**:**:**:**
ONBOOT=yes

NETMASK=255.255.255.0
IPADDR=[サーバーのIP NICにあるIP]
DNS1=[NICに推奨ネームサーバー記載あり]

```

複製したディスクで上記設定が固定になっている場合は、ネットワークに属していないため、外部から接続ができないため修正が必要。

```
#eth0があるかどうか
/sbin/ifconfig -a

#ない場合
vi /etc/udev/rules.d/70-persistent-net.rules

```

```
#下記のような箇所が追記があるので、追記の方を残しておく、上に合った方を削除する

# PCI device 0x1af4:0x1000 (virtio-pci)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="**:**:**:**:**:**", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
```

```
#上記内の下記アドレスをifcfg-eth0のHWADDR=へ記載
ATTR{address}=="**:**:**:**:**:**"
```

```
#再起動
/etc/init.d/network restart
```

マシン自体の再起動も必要かも。
[Unity]ネイティブプラグインからコールバック関数を呼ぶ[iOS]


## はじめに

UnityからiOSの機能を呼び出して、さらにiOSからUnityへ戻り値を渡したかった。
しかし、ぐぐってもなかなか良い方法が出てこない。
（UnitySendMessageは文字列しか返せないのがイマイチなので使う気がない。）

実際にはすべてのコールバック関数が呼べないわけではない。
staticな関数なら普通にiOSから呼び出せる。

だが、呼び出したいのはインスタンスメソッドなのだ。
しょうがないので、自力ででっちあげることにした。

## 方針

staticなメソッドなら呼べるので、staticなメソッドを踏み台にしてインスタンスメソッドを呼び出せば良いのでは？

しかし、ただ単純に　```MethodName(arg1, arg2, staticなメソッド, インスタンスメソッド)``` のように呼び出してもエラーが出てダメ。
どうもインスタンスメソッドがGCされてしまうのが問題らしい（たぶん）。

そこでGCされてしまわないように、GCHandle.Alloc()を使うといけそうだ。


## コード

### iOS (Objective-C)

今回、ネイティブ側は渡された数を２倍するだけの単純なものにした。

以下のCallback.hとCallback.mmをAssets/Plugins/iOSフォルダに入れておく。

```objc:Callback.h
extern "C" {
    typedef void (*CallbackCaller)(int x, void* methodHandle);
    void _CallPlugin (int x, void* methodHandle, CallbackCaller caller);
}
```

```objc:Callback.mm
#include "Callback.h"

void _CallPlugin (int x, void* methodHandle, CallbackCaller caller){
    (caller)(x * 2, methodHandle);  // 2倍したらコールバック（を呼び出すメソッド）を呼ぶ。
}
```

### Unity (C#)

```csharp:SampleCallback.cs
using System;
using System.Runtime.InteropServices;

public class SampleCallback {
	// 「コールバックしたいメソッドの型」を宣言
	public delegate void Callback (int x);
	// 「コールバックしたいメソッドの引数を並べて宣言」 + メソッドのハンドル
	public delegate void CallbackCaller(int x, IntPtr methodHandle);

	// 「コールバックしたいメソッドの引数を並べて宣言」 + メソッドのハンドル + コールバックを呼び出すためのstaticなメソッド
	[DllImport("__Internal")]
	private static extern void _CallPlugin (int x, IntPtr methodHandle, CallbackCaller caller);

    // C#(Unity)から呼び出すメソッド
	public static void CallPlugin (int x, Callback callback) {
		// コールバック関数をGCされないようにAllocしてハンドルを取得する。
		IntPtr gcHandle = (IntPtr)GCHandle.Alloc(callback, GCHandleType.Normal);
		// 普通の引数 + コールバック関数のハンドル + コールバック関数を呼び出すためのstaticなメソッド
		_CallPlugin (x, gcHandle, CallCallback);
	}

    // コールバックを呼び出すためのstaticなメソッド(iOSから呼ばれる）
	[AOT.MonoPInvokeCallbackAttribute(typeof(CallbackCaller))]
	static void CallCallback (int x, IntPtr methodHandle){
	    // methodHandleからコールバック関数を取り出す。
		GCHandle handle = (GCHandle)methodHandle;
		Callback callback = handle.Target as Callback;
		// 不要になったハンドルを解放する。
		handle.Free();

		callback(x);
	}
}
```

上記のクラスを呼ぶ出すのは以下のような感じ。

```csharp:
	public void Multiply(){
		SampleCallback.CallPlugin(７, OnEndOfCalculate); // 7を２倍したい。
	}

	void OnEndOfCalculate(int x){
		Debug.LogFormat("x: {0}", x);  // 14が返ってくるはず。
	}
```



## サンプル

GitHubに[サンプル](https://github.com/JunSuzukiJapan/UnityCallbackSample)を上げときましたので参考にしてください。

## 参考

[NativePluginsにC#デリゲートを登録する](http://tsubakit1.hateblo.jp/entry/20140326/1395783640)
[Xamarin iOSのP/Invokeでコールバックを使うときの制限](http://espresso3389.hatenablog.com/entry/2013/06/01/215646)
[[Unity] C#とObjective-Cの連携まとめ](http://qiita.com/tkyaji/items/74d485a021c75ed10bca)
SignalTransitionサンプル

#SignalTransitionのサンプルコード

##テスト用QML
```qml
import QtQuick 2.9
import QtQuick.Window 2.3
import QtQuick.Controls 2.2
import QtQml.StateMachine 1.0 as DSM
import QtMultimedia 5.9

Window {
    id: window
    visible: true
    width: 640
    height: 480

    // StateMachine作成
    DSM.StateMachine {
        id: stateMachine
        initialState: textState
        running: true

        // 初期状態
        DSM.State {
            id: textState

            // buttonクリック時にfinalState状態へ切り替え
            // ただし、checkBoxGuardがチェックされている場合は状態の変更を行わない
            DSM.SignalTransition {
                targetState: finalState
                signal: button.clicked
                guard: !checkBoxGuard.checked
            }
        }

        // 最終状態
        DSM.FinalState {
            id: finalState
        }

        // 最終状態になった時のハンドラ
        onFinished: {
            text1.text = "Finished!"
            color = "#ff0000"
        }
    }

    Row {
        id: row
        spacing: 2

        // 状態変更ボタン
        Button {
            id: button
            anchors.verticalCenter: parent.verticalCenter
            text: "Click Me!"
            onClicked: {
                if (checkBoxGuard.checked == false) {
                    enabled = false
                    checkBoxGuard.enabled = false
                    okSound.play()
                } else {
                    ngSound.play()
                    text1.text = "Guard!"
                }
            }
            Audio { id: okSound; source: "Sounds/btn01.mp3" }
            Audio { id: ngSound; source: "Sounds/btn02.mp3" }
        }

        // ガード有効チェックボックス
        CheckBox {
            id: checkBoxGuard
            checkable: true
            text: qsTr("Guard")
            onClicked: checkSound.play()
            Audio { id: checkSound; source: "Sounds/btn03.mp3" }
        }
    }

    // 状態表示テキスト
    Text {
        id: text1
        text: qsTr("Inital State")
        anchors.top: row.bottom
        anchors.left: parent.left
    }
}
```
##実行結果
[![SignalTransitionサンプル動画](http://img.youtube.com/vi/JoLe2rc9En4/0.jpg)](http://www.youtube.com/watch?v=JoLe2rc9En4)
https://youtu.be/JoLe2rc9En4
※Linux Mint 18.2 & Qt 5.9.1使用
CapistranoデプロイをCircleCIでやってみた

# 前回の記事

[Rails5.1.2 + Webpacker + ReactをCapstranoでデプロイする手順書①](http://qiita.com/gcmae/items/95ebd532742f736b8c98)
[Rails5.1.2 + Webpacker + ReactをCapstranoでデプロイする手順書②](http://qiita.com/gcmae/items/9f4aa882ada24aa39066)

# 前書き
前回にて、RailsアプリをCapistranoでデプロイするところまでやりました。
今回は、 **CircleCI** を使って、Capistranoデプロイを行えるようにやってみました。

# CircleCiの設定
## GUI側の設定
GUI側では、CapistranoがSSHでサーバへログインするためにKeyの設定をします。

CircleCIのプロジェクトの設定から、 **SSH Permission**のページへ行きます。
そこで、下記の画面になるので、 **Add SSH Key** から
接続先(ドメイン、またはIP)と、SSH Keyを記述して保存します。

![スクリーンショット_2017-09-08_17_12_02.png](https://qiita-image-store.s3.amazonaws.com/0/159013/51ada0fc-bec9-4e69-5eab-64f5d9cd733e.png)

GUIの設定は以上です。
保存が完了すれば以下の画面になるので、そこの **fingerprints** 項目に表示されている文字列は設定ファイルで利用します。

![スクリーンショット_2017-09-08_17_17_19.png](https://qiita-image-store.s3.amazonaws.com/0/159013/488417db-1380-48cb-1198-aa10c8005659.png)

この設定で、CircleCIのDockerの中に、~/.ssh/id_rsaとして、SSH Keyが保存されるようになります。


## 設定ファイル
最終的に出来た設定ファイルが以下の通りです、とりあえずこれでデプロイは出来ました。

```yaml

# .circleci/config.yml
version: 2
jobs:
  build:
    docker:
      - image: ruby:2.3.1-alpine
    working_directory: /home/circleci/{{アプリ名}}
    steps:
      - setup_remote_docker:
          reusable: true
      - run:
          name: システム依存関係のインストール
          command: apk add --update --no-cache linux-headers git openssh-client tar gzip build-base tzdata mariadb-dev
      - checkout
      - restore_cache:
          name: Bundleキャッシュの復元
          keys:
            - gems-{{ .Environment.CACHE_KEY }}-{{ checksum "Gemfile.lock" }}
            - gems-{{ .Environment.CACHE_KEY }}-
      - run:
          name: Ruby依存関係のインストール
          command: bundle check || bundle install --jobs=4 --retry=3
      - save_cache:
          name: Bundleキャッシュの保存
          key: gems-{{ .Environment.CACHE_KEY }}-{{ checksum "Gemfile.lock" }}
          paths:
            - /usr/local/bundle
      - add_ssh_keys:
          fingerprints:
            - {{fingerprints}}
      - deploy:
         name: Capistranoデプロイ
         command:
           bundle exec cap production deploy
```

## 解説
Environment.CACHE_KEYはこちらが独自にCircleCIのGUIで設定している環境変数になります。
特に、ハマったポイントは、システム依存関係のインストールです。
mariadb-dev(旧: mysql-dev)をシステム依存としてインストールが必要な点でした。

add_ssh_keysに先ほどのfinderprintsを指定することで、SSH Keyとして利用できるようになります。

その次のハマりポイントとして、Capistranoのconfig/deploy/production.rbの中身です。
鍵の場所を指定する際、~/.ssh/id_rsaでいけると思ったのですが、rsaの後ろにfingerprintsの:抜きの記述が必要でした。

具体的には、~/.ssh/id_rsa_aa11111111111~~ のように鍵を指定すれば、Docker上で認識され、CapistranoがサーバへSSHログイン可能になります。

これで、masterへpushすると、CircleCIで設定ファイルのタスクが実行され、最終的にCapistranoデプロイが走り、サーバへデプロイされるようになります。

サーバのスペック、アプリの大きさに左右されるかもしれませんが、大体、２分ぐらいでデプロイできました。

# 後書き
Capistranoデプロイを初めにやった時、CircleCI上でどうやって鍵を指定するのだろうかと、悩んでいましたが
CircleCIの設定画面を見ていると、鍵を保存する場所があったので思ったより簡単に出来ました。
これで、masterへpushするだけで、サーバ上へデプロイされるようになり、アプリ開発が捗ります。

**※** 鍵の指定の方法は、他にいい書き方があるのかもしれません。。。
PythonでSESでemailを、SNSのSMSでショートメッセージを送信する

# はじめに
みなさんは、アプリケーションからemailやショートメッセージを送信するような機能を実装したりしていませんか？
筆者も先日そのような機能を実装しました。もちろんAWSのSESとSNSを利用して。
Node.jsで書きたかったけど、諸所諸々の事由がありPythonで書いてます。
SESとかSNSとかSMSとかややこしい！ってなりながら実装しましたが、制限とかで詰まったところがあったので、今後のために記事に残しておこっと･･･

## SESって？
SES(Simple Email Service)は、ユーザーが各自のEメールアドレスとドメインを利用して費用効率の高い簡単な方法でEメールを送受信するためのEメールプラットフォームのこと。
とりあえずAWSのサービスでEメールを送受信できるサービス。適当でごめんなさい･･･

## SNSって？
SNS(Simple Notification Service)は、サブスクライブしているエンドポイントへのメッセージの配信または送信を調整し、管理するウェブサービスです。サブスクライバーとしてLambdaとかSQSとかSMSなどを使用することができます。
今回はSMSを使ってショートメッセージを送信します。

## 実装方法
アプリ側・AWSのほかのサービスなど呼び出しもとが複数あったのでLambdaに書くことにしました。
基本的にLambdaをキックしてSESやSMSを送信する感じです。

### SES
送信先のメールアドレスは配列で渡してやれば、複数アドレスに送信することができます。
基本的にSESを利用する場合はあらかじめSESで登録・許可しておいたアドレスのみ送受信することができます。
しかしそれではアドレスが増えるたびに、SESに登録・許可をしなければいけないので、サポートに連絡して、サンドボックス環境から移動してもらいましょう。そうするとメール受信者の登録をする必要がなくなります。
(送信者のアドレスは必ず登録する必要がありますので注意)

```py
import boto3

def lambda_handler(event, context):
  try:
    ses = boto3.client("ses", region_name = "us-west-2")
    ses.send_email(
      Source = "from_mailaddress",
      Destination = {
        "ToAddresses": "to_mailaddress"
      },
      Message = {
        "Subject": {
          "Data": "subject_title",
          "Charset": "UTF-8"
        },
        "Body": {
          "Text": {
            "Data": "body_message",
            "Charset": "UTF-8"
          }
        }
      }
    )
  except Exception as e:
    print e

```

### SNS(SMS)
送信先の電話番号は国際電話番号(あたまに+81とかつけるやつ)でないと送信できないようです。
あとショートメッセージなので、メッセージの内容はほどほどにしておかないとエラーを吐いてきます。
またデフォルトの利用料金制限が1$/monthとなっていて、そのままでは数十通しか送信することができないです。
しかもその制限を上げることはできない(上げようとすると許可されてないよというエラー文が表示されます)ので、SES同様サポートに問い合わせて制限を上げられるようにしてもらいましょう。

```py
import boto3

def lambda_handler(event, context):
  try:
    sns = boto3.client("sns")
    phoneNumber = "+818012345678"
    message = "send message"
    sns.publish(
      PhoneNumber = phoneNumber
      Message = message
    )
  except Exception as e:
    print e

```

## さいごに
SESやSNS(SMS)の各制限に少し詰まってしまったことがあったので、今回記事に書きました。
AWS-SDKなどを活用すれば、アプリ側から簡単にメッセージを送信することができたりします。便利ですね。
Lambdaのeventに送信先のアドレスや電話番号とかメッセージの内容とか持たせて、それを参照すれば、ひとつのLambdaで使いまわすこともできます。便利ですね(2回目)。

ではまた！
ggplot2でビン幅を自動的に決めたヒストグラム


2019/3/19

こちらにもっと簡単な方法を紹介しました (通知が遅くなりました)．

「geom_histogramのビン幅を動的に決定する」
https://blog.atusy.net/2018/11/09/binwdith-for-geom-histogram/

[facetを使って多変量のヒストグラムをいっぺんに作る](#facetを使って多変量のヒストグラムをいっぺんに作る) 場合は本記事，最終節参照です．

#はじめに

`ggplot2：：geom_histogram`はデフォルトでビン数が30に固定されている．
試しにプロットすると，

```r
ggplot(iris, aes(x = Sepal.Length)) + geom_histogram()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
```

なんて返ってきて，ビン数(幅)は自分で調整してねと言われる．
これは探索的すぎて多変量を見たい時なんて特に面倒だ．

できれば，`graphics::hist`のように自動で決めてほしいし，なんなら，ビン幅を決めるアルゴリズムを任意に選択したい(`graphics::hist`でいうbreaks引数の指定)．

#`graphics::hist`と合体だ!

`graphics::hist`はhistogramクラスのリストを返す．
(引数`plot`がTRUEならプロットし，リストをinvisibleに返し，FALSEならプロットせずにリストをreturnする)

```r
> str(hist(iris[[1]]))
List of 6
 $ breaks  : num [1:9] 4 4.5 5 5.5 6 6.5 7 7.5 8
 $ counts  : int [1:8] 5 27 27 30 31 18 6 6
 $ density : num [1:8] 0.0667 0.36 0.36 0.4 0.4133 ...
 $ mids    : num [1:8] 4.25 4.75 5.25 5.75 6.25 6.75 7.25 7.75
 $ xname   : chr "iris[[1]]"
 $ equidist: logi TRUE
 - attr(*, "class")= chr "histogram"
```

このmidsとcountsを用いてggplot2で棒グラフを作ればいいのだ．

#やってみよう

```r

library(ggplot2)
library(dplyr)

iris[[1]] %>% #ヒストグラムを作るデータ
  hist %>% #度数分布の計算．
  `[`(c('mids', 'counts')) %>% #必要なデータの取り出し
  as.data.frame %>% #ggplotが受けつけるデータフレームの形に直す
  ggplot(aes(x = mids, y = counts)) %>% #プロット
  `+`(geom_col())
  

```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/021bfe15-ba80-e742-f066-bf0ba6f545bc.png)

棒と棒の間に隙間があるのは，histogramとしては不恰好だし，ビンの幅によってはまるでデータのない部分かのように見えてしまうだろう．

```r

library(ggplot2)
library(dplyr)

iris[[1]] %>% #ヒストグラムを作るデータ
  hist %>% #度数分布の計算．
  `[`(c('mids', 'counts')) %>% #必要なデータの取り出し
  as.data.frame %>% #ggplotが受けつけるデータフレームの形に直す
  mutate(width = mids[2] - mids[1]) %>% #ビン幅の設定
  ggplot(aes(x = mids, y = counts, width = width)) %>% #プロット
  `+`(geom_col())
  

```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/4c272e84-8452-9a11-1b38-9a066d2b5319.png)

ぽくなったぞ!

#facetを使って多変量のヒストグラムをいっぺんに作る!

ここからはdplyrやtidyrに慣れていないと辛い

```r
library(ggplot2)
library(dplyr)
library(tidyr)

iris %>%
  gather(var, val, -Species) %>%
  group_by(var) %>%
  summarise(
    data = list(data.frame(hist(val, breaks = 'Scott', plot = FALSE)[c('mids', 'counts')]))
  ) %>%
  ungroup %>% 
  mutate(data = map(data, mutate, width = mids[2] - mids[1])) %>%
  unnest %>%
  ggplot(aes(x = mids, y = counts, width = width)) %>%
  `+`(list(
    geom_col(),
    facet_grid(. ~ var, scale = 'free')
  ))

```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/149890/75a70cbb-8caa-88cc-d70f-bc42573f65d0.png)

変数ごとにビン幅を変えることに成功した!
Ubuntuで簡単にデスクトップ録画をし、gifに変換してQiitaに投稿する方法

SimpleScreenRecorderでデスクトップ録画をしたのち、ffmpegでgifに変換してQiitaに投稿できるようにする方法を紹介します。

# 環境
Ubuntu 16.04 LTS

# 手順
1. SimpleScreenRecorderをインストール
2. SimpleScreenRecorderで録画
3. ffmpegでgifに変換
4. Qiitaに貼り付ける

# 1. SimpleScreenRecorderをインストール

以下のコマンドを実行すれば、SimpleScreenRecorderをインストールできます。

```bash
sudo add-apt-repository ppa:maarten-baert/simplescreenrecorder
sudo apt-get update
sudo apt-get install simplescreenrecorder
```

# 2. SimpleScreenRecorderで録画

## SimpleScreenRecorderを起動
SimpleScreenRecorderを起動すると、以下の画面が表示されるので、「続行」をクリック
![Screenshot1.png](https://qiita-image-store.s3.amazonaws.com/0/136124/f17e0fa8-c272-230f-e547-d413174a272b.png)

## 「音声を記録」のチェックを外す
Qiitaに投稿する際、gif画像に音声は必要ないと思うので、「音声を記録」のチェックを外しておきましょう。
またこの画面では、デスクトップ全体を録画するか、任意の範囲を録画するかなどを選択できます。
そして、「続行」をクリックします。
![Screenshot from 2017-09-08 16-56-43.png](https://qiita-image-store.s3.amazonaws.com/0/136124/4c26d7f4-e69d-ea0a-7763-e93f4d772088.png)

## 保存先・ファイル形式の指定
次に保存先を選択します。
また、コンテナと書いてあるところはMP4にしておきましょう。

![Screenshot from 2017-09-08 17-08-32.png](https://qiita-image-store.s3.amazonaws.com/0/136124/2c16b148-55fd-8e63-a2ad-676e029b3605.png)

## 録画をする
ここまできたら、あとは録画をするだけです。上端の「録画を開始」ボタンをクリックしましょう。すると録画が始まります。
録画を終了するときは、右下の「録画を保存」をクリックして録画を保存・終了します。

![Screenshot from 2017-09-08 17-13-18.png](https://qiita-image-store.s3.amazonaws.com/0/136124/22818d92-bc40-12d6-04b8-b32ff3620ac7.png)

## 3. ffmpegでgifに変換

以下のようにコマンドを実行します。

```bash
ffmpeg -i 録画したファイル.mp4 出力するファイル名.gif
```

こうすれば、一発でMP4からgifに変換できます。

# 4. Qiitaに貼り付ける
あとは、Qiitaの編集中の記事にドラッグ・アンド・ドロップすればgif画像が貼り付けられます。

# 参考

[Ubuntuの画面録画が簡単にできるSimpleScreenRecorderのインストール方法と使い方](https://ry0.github.io/blog/2016/02/21/simplescreenrecorder/)

# あとがき
今までVLCメディアプレイヤーを使って録画していましたが、SimpleScreenRecorderのほうがシンプルで簡単ですね。
みなさんもUbuntuで開発しているものなどをデスクトップ録画をしてみてはいかがでしょうか。
RaspberrypiにWebカメラを接続する

# RaspberryPiにウェブカメラを接続する

## USBにカメラを接続

認識できたかどうかを確認。

```
$ lsusb
Bus 001 Device 078: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```

こんな感じで`Logitech C270`が認識されました。

## fswebcamをインストール

webカメラを扱うため、`fswebcam`というパッケージをインストール。

```
$ sudo apt-get install -y fswebcam
```

## 画像を撮影する

`fswebcam <ファイル名>`で`ファイル名`で指定した名前のキャプチャ画像が作成される。

```
$ fswebcam test.jpg
--- Opening /dev/video0...
Trying source module v4l2...
Error opening device: /dev/video0
open: Device or resource busy
Trying source module v4l1...
Error opening device: /dev/video0
open: Device or resource busy
Unable to find a source module that can read /dev/video0.
```

`/dev/video0`の権限が足りないとのことなので。。。

```
$ sudo chmod a+rw /dev/video0
$ fswebcam test.jpg
```

これで正常にキャプチャ画像が保存された。
■SparkUI@BPM Modal_Section×ボタンを付けるためのやり方(初心者向け)  

## 成果物イメージ

パーネルの右上に「×」が表示されました！
![スクリーンショット 2017-10-10 13.02.52.png](https://qiita-image-store.s3.amazonaws.com/0/181748/78bc697c-97ab-b993-a6f6-ce237040b5cd.png)


## ①クライアント・サイド・ヒューマン・サービスの作成

1.ユーザー・インタフェースのクライアント・サイド・ヒューマン・サービスを新規します。

「名前」を入力して、「終了」ボタンを押します。
![2017-09-08 17_05_43-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/d642f77d-3c30-988f-cb85-f535ed293ed9.png)

「デフォルトのCoachで開始」を押します。
![2017-09-08 17_08_14-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/ad4549db-287c-aa79-c4aa-c2091bc9ab0b.png)

新規したクライアント・サイド・ヒューマン・サービスは下記の通りです。
![2017-09-08 17_08_33-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/1848b8e1-c700-7f24-f651-0ca748106801.png)




## ②Modal_Section および ボタンの作成

右側の検索欄で「modal」で検索します。
![2017-09-08 17_14_02-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/2d796402-8ddc-1171-56c8-a03e0584d3a4.png)

左側のcoachにドラッグ＆ドロップします。
※ディフォルトのModal_SectionのコントロールIDは「Modal_Section1」です。
![2017-09-08 17_16_24-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/7e4ffe44-5325-db61-bc64-4c217de66a2a.png)

右側の検索欄で「panel」で検索します。
![2017-09-08 17_16_02-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/7454d128-88fd-8623-1dd8-eb5ed9255f4b.png)

左側のcoachにドラッグ＆ドロップします。
![2017-09-08 17_16_55-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/a0bb1956-2db3-9b04-a391-f2eaa8451cd1.png)

右側の検索欄で「button」で検索します。
![2017-09-08 17_20_39-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/23b973a6-3971-8214-fc23-7b7cb4035dfc.png)

左側のcoachにドラッグ＆ドロップします。
![2017-09-08 17_21_23-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/acc36a0b-7e12-614d-e757-77c72cca8bb8.png)

## ③×ボタンの実装

Button で
プロパティー > 構成 > Events > On click 
`${Modal_Section1}.setVisible(ture);`

![2017-09-08 17_23_40-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/1daaff09-5fb8-dcc5-32b6-64d13c741037.png)

Panelで
プロパティー > 構成 > Appearance > Icon
timesを入力してください
![2017-09-08 17_28_42-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/bc6b84dc-ba8e-c45a-8353-5f33d2f5264a.png)

Panelで
プロパティー > 構成 > Events > On Icon Click 
`${Modal_Section1}.setVisible(false);`
![2017-09-08 17_27_39-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/c1760ff6-f7a8-1ac2-f327-3b5c36571079.png)

「保存」ボタンを押します。
![2017-09-08 17_29_37-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/76d523c3-f9fa-49c3-5a8a-34efa14c5d8e.png)

※オプション
▶︎の実行ボタンを押します。
![2017-09-08 17_30_51-Building a sample integration_5 - Designer.png](https://qiita-image-store.s3.amazonaws.com/0/181748/2ff76ed8-3e3d-88be-15cd-0bc56eaefe94.png)
【R】RStudioが起動しない (RStudio Initialization error :  The R-studio server is taking a long time to respond.)

# RStudioが起動しない問題について
![ploble.jpeg](https://qiita-image-store.s3.amazonaws.com/0/143058/e4ac7696-b10a-6343-9308-b7bc6fa45f6e.jpeg)

## 背景


100MBを超えるデータに対する作業を一部自動化しようと思い
StataからRに移行していたときに、DesktopのアイコンからRStudioが起動できなくなりました。
(移行後何度か作業をして、翌日に突然以下のエラー)

> <strong> Initialization Error
The R-studio server is taking a long time to respond.
it is possible that your R session has become unresponsive"</strong>



## 解決策

[r-RSutudioの起動](https://ja.stackoverflow.com/questions/9829/rstudio%E3%81%AE%E8%B5%B7%E5%8B%95)

ここに答えがありました。

[Tools] → [Global Options] → [General] のこのチェックボックス

![option.jpg](https://qiita-image-store.s3.amazonaws.com/0/143058/bba8766b-bb96-dca6-10c4-b898c1fa03f2.jpeg)

ここにチェックが入っていると、起動時に前回作業の.RDataを読み込むので、
データが大きい場合は起動に時間がかかる・起動できないケースが発生するみたいです.

# まとめ
読み込みに時間がかかる.RDataを扱う場合、<strong>Restore .RData into workspace at startup</strong>
のチェックボックスに注意する
macの便利な使い方メモ

#Mac PCの使い方について、便利だったことのメモ

※あくまで個人用のメモです。
「こういうのもあるよ〜」というコメントはありがたいですが、「これ、できないじゃないか！」という訴えを持ってこられても対応しかねます。ご了承ください。
※使って便利だったことは随時追記していきます。


##画面を２分割して、例えば左:ブラウザ、右:Atomにする方法。
あれやこれやと開いて同時進行で見たいけど、見にくい。そんな時の一つの解決法。

・手順1.
片方を全画面表示にし、タッチパッド上に三つ指を触れさせ、上にスワイプする。
右上の方に画面をもう一つ追加するボタンが出るので、画面を追加。
追加した画面を開く。

.手順2.
先に全画面にしたものと一緒に左右で表示したいものを開く。

・手順3.
手順2.を行った画面のまま、またタッチパッド上に三つ指を触れさせ、上にスワイプする。

・手順4.
上の方に、全画面で表示した画面と、現在の画面が出た他、手順2.で開いておいたものも下の方に表示されるので、そちらをドラッグし、全画面表示している画面にドロップする。
以上。
※左右はドロップする前にどっちに落とすかで決まり、あとでも変更可能。


##画面の移動をよりスムーズに行う方法。
上のやり方を知ってやたら画面を作ってしまった時、いちいち三つ指を上にスワイプして画面を選ぶのが面倒な時の解決法。

・手順1.
複数の画面を作る。

・手順2.
三つ指をタッチパッドに触れ、左右にスワイプ。
以上。
※一旦「画面上に開いているすべてのアプリ等を表示+作ってある複数の画面の全表示」に行く部分を省けるので、早い。
※開きたいものをどこにやったかわからなくなった場合は、上にスワイプするのと併用すれば良い。

##選択範囲をコメント化・・・の、ショートカット
いちいち「<!---->」や「#」などを振っていくのが面倒なので、ドットインストールでやってるように、
選択範囲を一気にコメントにしたい！
その方法。

・「⌘(command)+/」

これだけ。
知ってみれば簡単極まりない。
windowsだとつまりctrl+/なのかな？
久しくwindows使ってないのでわからないけども・・・

とりあえず覚えておこう。

他にもコマンド系。

・「⌘(command)+a」・・・全選択
・「⌘(command)+s」・・・保存
・「⌘(command)+n」・・・新規作成
・「⌘(command)+z」・・・一個戻り　※これ重要。間違って削除した物も戻ってくる！


##mac・・・小さいサイズのだと書いてないのね・・・

これは、僕が取説とかをちゃんとダウンロードして読めばよかったのでしょうが、11inchのmacの場合書いてなかったもの。

よくデベロッパーツールを使うとは思うのですが、いちいち「表示」から開くのは面倒臭い。
しかし、ショートカットはあるらしいが、「⌥」の意味がわからず使えなかったのです。
本体のキーのどこにも書いてないから。

しかし、この間教わったところによると**「　⌥　= option　」**とのこと。

早速、「⌥(option) + ⌘(command) + i」を試してみます。

すると、即座にデベロッパーツールが起動。
これは便利。

その他、ソースを表示したいなら「u」、コンソールを開きたいなら「j」でそれぞれ直接起動できます。
覚えておこう。

・・・しかし、11inchより大きいサイズのmacのoptionキーには普通にマークが書かれていたことだけ納得いかない・・・・・
[C#] Stream と Reader/Writer の Dispose 

## 要約

- Reader/Writer にも Dispose がある
- 基本的に Reader/Writer の方の Dispose だけを呼べばOK
- Close メソッドは呼ばなくてよい。（中で Dispose を読んでいるだけ）
- Dispose を直接書くより、 using 構文を使うのが良い

## きっかけ

C#でストリームを扱うときは

- C# の Stream クラス の読み書きは Reader/Writer でする
- Stream クラスは使い終わったら Dispose する
- Reader/Writer も Dispose する必要がある

という感じですが、このあたりでいくつか気になる点があったので調べました。

## なぜ Reader/Writer にも Dispose が存在するのか

ストリームは内部にファイルポインタなり、ソケットなどを持っているだろうから、Dispose必要というのはわかる。

では、Reader/Writer にもDisposeがあるのはなぜ？（何を解放しているのか？）

### TextReader の場合

StreamReader の親である TextReader は何もしなくていいみたいで、空のメソッド。

```csharp
protected virtual void Dispose(bool disposing)
{
}
```

https://github.com/dotnet/corefx/blob/master/src/System.Runtime.Extensions/src/System/IO/TextReader.cs#L39

### StreamReader の場合

StreamReader になると、エンコーディングやバッファの情報を消している

```csharp
if (!LeaveOpen && (_stream != null))
{
    _stream = null;
    _encoding = null;
    _decoder = null;
    _byteBuffer = null;
    _charBuffer = null;
    _charPos = 0;
    _charLen = 0;
    base.Dispose(disposing);
}
```

https://github.com/dotnet/corefx/blob/master/src/System.Runtime.Extensions/src/System/IO/StreamReader.cs#L218

なるほど！読み書きのバッファなどを持っている場合、それも解放しないといけないってことですかね。

## Reader/Writer の Dispose と Stream の Dispose 両方呼ぶ必要があるか
Reader/Writer の方だけでいいみたいです。
中のStreamも自動的にDisposeしてくれます。

**ただし、Reader/Writer のコンストラクタ引数の leaveOpen を true にすることで、 Stream を解放しないようにもできます。**


https://stackoverflow.com/questions/1065168/does-disposing-streamreader-close-the-stream

## Close メソッドとは何なのか
内部で Dispose を呼び出しているだけなので、無視して大丈夫です。

## using 構文について
usingで囲むと自分でDisposeを呼ぶ必要はなくなります。（using構文が内部でDisposeを呼んでくれます）
積極的に using で済ますようにしたほうが良さそうです。

```csharp
using (var stream = ...)
using (var reader = new StreamReader(stream, ...))
{
    ...
}

// usingを抜けたら自動的に Dispose してくれる
```

<sub>（Marimoiroさんコメントありがとうございます）</sub>



## 参考リンク

参考リンク

- [[雑記] Dispose にまつわる余談](http://ufcpp.net/study/csharp/rm_disposable.html)
- [StreamReader.Close()を呼ばなくていい理由](http://qiita.com/iiokazuya/items/dfa0b66898a2b39fc1e9)
- [C# Tips －usingを使え、使えったら使え(^^)－ - 株式会社ディーバ](http://divakk.co.jp/aoyagi/csharp_tips_using.htmlhttp://divakk.co.jp/aoyagi/csharp_tips_using.html)
NGINX UnitでWordpressを動かしてみたけど動かなかった


アプリケーションサーバ「[Nginx Unit](https://www.nginx.com/products/nginx-unit/)」がリリースされたのでWordpressを動かして，ついでにパフォーマンス計測でもしてみようと思った。

けど

1. Binary PackageはPOSTが扱えなくてWordpressがセットアップできない (2017-09-08 16:00現在)
2. ソースからコンパイルすればPOSTが扱えるようになりセットアップが完了するものの，トップページがリダイレクトループになる
3. 力尽きた ← イマココ

トップページのリダイレクトループをどうにかしないと先に進めない。

----
以下作業メモ

# 動かしてみる
とりあえずCentOS 7でやってみた。バイナリのインストールは[公式の手順](http://unit.nginx.org/docs-nginx-unit.html)通りにやればOK。依存関係の問題でphpのバージョンは5.4を強制される。

## Unitの起動
unitdをstartするだけ

```console
root# sudo systemctl start unitd
```

## Unitの設定
これも[ドキュメント](http://unit.nginx.org/docs-configuration.html#minimum-configuration)に書いてある通りでOK

```json
user$ cat /etc/unit/wordpress.json
{
     "listeners": {
         "*:8300": {
             "application": "wordpress"
         }
     },
     "applications": {
         "wordpress": {
             "type": "php",
              "workers": 20,
              "root": "/var/www/wordpress",
              "index": "index.php"
         }
     }
}
```

socketは`/run/control.unit.sock`に作成されているので

```console
root# curl -X PUT -d @/etc/unit/wordpress.json --unix-socket /run/control.unit.sock http://localhost/
```

と流し込む。ちなみに設定は永続化されてないので再起動したりすると揮発する。カナシイ。

## phpinfoの確認
```console
root# echo '<?php phpinfo();' > /var/www/wordpress/index.php
root# lynx http://127.0.0.1:8300/
```
Server APIがunitになっているのが確認できる。

## wordpressのインストール

必要なパッケージをインストール

```console
root# yum install -y php-mysqlnd mariadb-server
```

wpのインストールの方法はいろんなところにあるので割愛

`/wp-admin/setup-config.php?step=2`で`"Table Prefix" must not be empty.`と言われて先に進めない。
`$_POST`をdumpしてみるとNULLという悲しい事実。POSTが扱えないらしい。

リポジトリを見るとPHP POSTに関する[コミット](https://github.com/nginx/unit/commit/d87a4fb642ed4588483e65cd74a83b0cec7e8d29)があるのでmasterをコンパイルすれば大丈夫な気がする。

## Unitのコンパイル
[公式の手順](http://unit.nginx.org/docs-installation.html#source-code)で大体大丈夫
ついでなのでPHP 7.1にする。

```console
root# yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
root# yum --enablerepo remi-php71 install -y git gcc make php-devel php-embedded 
root# git clone https://github.com/nginx/unit /tmp/unit
root# cd /tmp/unit
root# ./configure --prefix=/opt/unit
root# ./configure php
root# make
root# make install
root# make php-install
```

unitの起動は `/opt/unit/sbin/unitd` でOK
【GoogleAppsScript】通知時間を詳細に指定する

Google Apps Script の実行トリガーとして、時間指定を行なうことができます。
時間指定は、「1時間ごと」や「5時～6時の間」等の指定が行なえます。
しかし、「毎日12時05分」といった通知時間の指定を設定することができせん。
このような指定をしたい場合は、コード上でトリガーの指定をする必要があります。


#毎日11時59分に処理を実行する

以下の作業が必要になります。

+ 11時59分に処理( main )を実行するようなトリガーを設定する関数( setTriger )をコード上で作成する
+ mainの処理の中で、setTrigerにて設定したトリガーを削除するコードを書く
+ デフォルトのトリガー設定にて、「日タイマー：10時～11時」でsetTrigerが動くようにする

上記のようにすることで、毎日10時～11時の間に、setTrigerが実行され、setTrigerによってその日の11時59分にmainが実行されるよう設定され、11時59分にmainが実行されます。
mainが実行されると、11時59分に実施するよう設定したトリガーが削除され、そのほかの処理も実行されます。
(トリガーは削除しないと残ってしまいます)

以下、実際のコードです。

```js

// 11時59分にトリガーを設定する関数
function setTrigger() {
  var day = new Date();
  day.setHours(11);
  day.setMinutes(59);
  ScriptApp.newTrigger("main").timeBased().at(day).create();
}

// トリガーを除去する関数
function removeTrigger() {
  var triggers = ScriptApp.getProjectTriggers();
  for(var i=0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == "main") {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}

// 実際に動かしたい処理
function main() {
  removeTrigger();　//トリガーを除去する
  //実行したい処理
}

```

以下、Google Apps Script のデフォルトのトリガー設定です。
![trigger.PNG](https://qiita-image-store.s3.amazonaws.com/0/45528/bd0ac384-58e8-cd9e-2bf7-ba23240e31bc.png)


トリガーは、Google Apps Script 画面上部の時計マークから設定可能です。
![tokei.PNG](https://qiita-image-store.s3.amazonaws.com/0/45528/af979143-24e3-fbe4-b20e-2255b348707d.png)



上記の例では、毎日特定の時間に処理を実行させましたが、他にも、「〇日おきに実行」や「〇月〇日〇時〇分に実行」など、さまざまなパターンで設定できます。



###参考
+ https://developers.google.com/apps-script/reference/script/clock-trigger-builder
+ https://developers.google.com/apps-script/reference/script/script-app
+ https://developers.google.com/apps-script/reference/script/trigger
[CEDEC2017]ユーザを飽きさせない高頻度の更新を可能にする開発運用ノウハウ ～ハイスピードな開発、リリースを実現するために～

#ユーザを飽きさせない高頻度の更新を可能にする開発運用ノウハウ ～ハイスピードな開発、リリースを実現するために～

##講演者
鈴木 元気　さん（株式会社Cygames）

##講演内容

実際に運用しているプロジェクトにおいての改善方法を講演されました。

###ゲームにおける運用
機能やリソースを追加し続けて、ゲームを成長させていくことが大切である。
では、これを実現するために何を行えば良いのか？

####遊んでもらうため
- ゲーム自体の面白さ
- 定期的な更新

この両方がとても重要なことである。
また、最高の運用は最高のコンテンツに欠かせない要素である。

####最高の運用とは？
**ユーザーを楽しませること**が重要→想像の上を行くクオリティとスピード感が必要
不具合を出さず、安定稼動を常に心がけ、より快適な環境を提供する
↓
高頻度更新かつ不具合ゼロを目標に開発を行っている。
コンテンツを成長させていくためには、
企画→開発→更新→反響の繰り返しをロスの無くすように高頻度で行う必要がある。

##課題
- そもそも開発できるのか？
- テストできるのか？
- リリースできるのか？


###そもそも開発できるのか？
開発用のツールを準備し、拡張しやすい設計で作る。

###リリースできるのか？
ビルドの高速化と転送の高速化の整備を行う。

###テストできるのか？
高頻度更新におけるテストの有効な手法を見つける必要がある。
不具合を出さないためにテストが重要である。
では、テストの効率化を行うためには？

####デザインデータの検証
- 表示が正常か
- アニメーションは適切か
- 品質は適切か

っといって自動検証で担保することが難しいもののため、手動＆目視で行う

####パラメータの検証
- パラメータの不備がないか
- バランスが崩れていないか
- データ間での参照が正しいか

こちらは自動検証でも十分な検証が可能である。
実際にエラーの大半はデータの参照ミスだった。

また、機能追加に伴いマスターデータが肥大化していくため、それに伴ったテストケースが増える。
そのため自動検証の仕組みが必要となった。
検証を行うために**DSL**を用いたメタプログラミングで構築を行った。

###DSL（ドメイン固有言語）で構築
特定の問題を解決することに特化した言語である。
今回はデータ検証に特化して作成を行っていた。

今回はRubyを使用した。

####なぜExcelではないのか？
- データ制約の記述が簡潔
- 制約反映のフローが適切
- 検証以外の機能拡張が可能

###検証と運用
検証時にエラーが出た際、社内連絡用ツールに自動投稿を行うようにしている。
投稿内容には、担当者、パラメータ、詳細を表示し分かりやすくしている。

####導入前
Excelで入力（この時点でVBAを使用した入力規則などの基本的なチェックだけを行っている。）
↓
ビルド＆反映
↓
テスト

最後のテスト段階でエラーが検出されると、ビルドのやり直しが発生してしまい、ビルド時間が非常に無駄となっていた。
また、入力規則に関しても個人環境だけでのチェックだったので制約が反映されないことなどもあった。

####導入後
Excelで入力（この時点でVBAを使用した入力規則などの基本的なチェックだけを行っている。）
↓
DSLで検証→エラー検出時に報告を行い、以降の処理を行わない。
↓
ビルド＆反映
↓
テスト

エラー検出タイミングを早い段階で仕込むことで効率よくチェックでき、
また、制約チェックなども共通の箇所で行うため反映漏れがなくなる。

###懸念事項
検証自体が独立しているため、機能追加などを行った際に拡張漏れがでてくる可能性がある。
開発フロー自体に自然な形でDSLを記載するフローが必要となってくる。

####対策
DSLを使用してcsvデータのDB化とコードの自動生成を行うように対応し、
検証項目の拡張もできるようにしている。

#####DB化のメリット
起動時の処理が高速化された。
起動時に行っていた、CSVデータの展開処理が不要となりデータ検索機能が大幅に強化された。

#####コードの自動生成
CSVデータから自動的にそのデータを管理するためのコードを生成する。
生成するコードは３種類あり、
データクラス
データ管理クラス
統合管理クラス
の３種類を自動生成している。

１．DSLに定義されている情報を下に、データクラスを生成する
２．データ管理クラスに主キーを元にデータの単体取得と複数取得処理を生成
３．データ管理クラスへのアクセサを統合管理クラスに追加する

#####自動生成の問題点と対策
特殊なケースに対する対応が出来ない。

- 手動で生成する

特殊なケースに対応したものや特殊な検索に対応したものを記述
パフォーマンスを追及したものを記述可能

- 自動で生成

 共通部分の構築は強い

この両方のいいとこ取りをするためにデータ管理クラスをpartial化して対応を行っている。

###まとめ
全体として起動の高速化と開発工数の大幅削減に成功することが出来た。
データ検証システムを普及させるために、DB生成やコードの自動生成などを用意して
使う機会を増やしている。

また、１タイトル内で完結させるには非常に惜しい機能だったので、
他タイトルでも使用できるように検証システム自体も容易に実装している。

####システムの共通部分
- 基礎部分（Ruby）
- DSL用構文定義
- データ検証機能
- データ報告機能
- DB生成機能
- コードの自動生成機能

####タイトル依存
DSLのデータ構造やデータ制約

##感想
更新を効率的に行うために機械的な部分をより簡単に対応できるようにしていたりと
参考になりそうな部分が非常に多くありました。
angular-cliで開発サーバーのポート番号変更

## 確認した環境

```bash
$ ng --version
@angular/cli: 1.3.0
node: 8.1.3
os: darwin x64
```

上記バージョンのangular-cliで作成した、angularプロジェクトが対象です。

## 変更する

`.angular-cli.json`のdefaults->serve->portの項目を編集します。 
angular-cliで作成した直後の状態だと項目自体がないので、追加します。 
下記の例では、デフォルトの4200から4201に変更しています。

変更前

```json:.angular-cli.json
...
  "defaults": {
    "styleExt": "css",
    "component": {}
  }
}
```



変更後

```json:.angular-cli.json
...

  "defaults": {
    "styleExt": "css",
    "component": {},
    "serve": {
      "port": 4201
    }
  }
}
```

## 確認

```bash
$ ng serve
```

次のように、変更したポート番号で開発サーバーが起動していることが確認出来ると思います。 

<img width="832" alt="スクリーンショット_2017-09-08_16_01_44.png" src="https://qiita-image-store.s3.amazonaws.com/0/79414/ba140151-eb30-0a71-fa74-583789326662.png">
【PHP】パスワード暗号化openssl_encrypt


*参考*
[function.openssl-encrypt](http://php.net/manual/ja/function.openssl-encrypt.php)
[example for openssl_encrypt](http://micmap.org/php-by-example/en/function/openssl_encrypt)
[online openssl_encrypt](https://3v4l.org/dtG92#output)
[ハッシュ、暗号化、暗号論](http://d.hatena.ne.jp/narusase/20160924/p1)
Mac+Opencvで医療画像解析

#はじめに
Mac+Opencvで画像解析を始めてみた人が学んでいく軌跡を記します。
これまでPythonでやってましたが、高速化のために移籍。
ふだんのブログは[こちら](http://pingpongpangpong.blogspot.jp/)です。

# 環境構築

MacではHomebrewでopencvが入ってくれます。

```
brew tap homebrew/science
brew install opencv
```

わたしの環境はふつうに入りましたが、うまくいかなかった人はググって頑張ってくださいp(^_^)q
ちなみに2017年9月時点で3.3.0が入りました。

Opencv3.0は本家いわく```OpenCV 3.0 introduced many new algorithms and features comparing to version 2.4.```とのことで、画像のアラインメントなど3.0にしかない機能も多いですし、リリースは2015年なので基本的には3.0を入れましょう。
現存する機能は[Wikipedia](https://ja.wikipedia.org/wiki/OpenCV)も参考になります。ヘッダーのインクルードの形式も異なるので、古いコードを頑張って動かしたいときはここを参考にしましょう。
http://docs.opencv.org/3.3.0/db/dfa/tutorial_transition_guide.html

#何の言語で使うか

OpencvはC++とPythonでAPIが提供されています。
Pythonは文字列処理や可視化などとつなげて行うことができて便利です。
が、私のおすすめは両方かけるのであればC++でやることです。

### なぜならば

* やりたいことが特徴量の計算だった
* そのため単一のアプリとして動く方が開発しやすい
* それならC++の方がはやいし環境構築が楽
* 閉鎖系にもっていきやすい

...つまりそういうことだ。

ただ、プロトタイプ作成やパラメータチューニングなどはjupyter上で作ったりする方が、いろいろ捗る（捗った）。
私はいろいろ試行錯誤した結果、インプットが画像（or画像セット）でアウトプットが画像や特徴量のファイルであるモジュールを別に用意して、いろいろよしなにするのをPythonでやった方がいいかなという結論になりました。
（PILやskimageがもっと便利になってstableになったら、また戻ります。）

#さぁ画像をいじろう

まずトライするのはOpencvのExampleをおすすめします。
http://docs.opencv.org/3.1.0/examples.html
この中からcountour2.cppを動かしてみます。

## コンパイル
Macでコンパイルするときはpkg_configがライブラリのリンクやインクルードもろもろをよしなにやってくれます。

```
g++ `pkg_config opencv` contour2.cpp
```

```pkg_config opencv```を実行すると、brewでインストールしたライブラリがどこにいるのか表示されます。私の場合は/usr/local/Cellar/の下にいらっしゃいます。
毎回これを入力するのが面倒なので

```
alias gpp_opencv="g++  \`pkg_config opencv\`"
```
のようなエイリアスをbashrcに入れています。

## Contour2を動かした結果
左の元絵（プログラム内で描画してくれます）に対して、find countoursを適用した結果を出力してくれます。
<img width="1000" alt="Screen Shot 2017-09-08 at 3.31.41 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/6585/d61aebbf-6bc6-d8af-bf2e-ecc2b56693a3.png">

重要な関数は[findContours](http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours)と[drawContours](http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=drawcontours#drawcontours)。
findContoursは輪郭間のネスト関係を保存してくれていて、スケールバーを動かすとcontourを表示する際のhierarchyを変えてくれます。
説明だとこの辺り？

```Maximal level for drawn contours. If it is 0, only the specified contour is drawn. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This parameter is only taken into account when there is hierarchy available.```

マイナスにふったときは、ある特定のcontourに対してその子供を描いていって、
プラスにふったときは、全体の木の中でのhierarchyに応じてプロットをしています。


#あとはよしなに
Affineの2D,3D transformationの記事を書く予定。
Pythonの画像処理も気が向いたら。
刮目して待て。冗談です。
SonarQubeをdocker-composeで起動する際にアクセスするURLを変更する

## docker-compose.yml
https://github.com/SonarSource/docker-sonarqube/blob/master/recipes.md
githubから取得出来ます。

## -Dsonar.web.contextの設定
このまま起動すると、`localhost:9000`でアクセスするとSonarqubeの画面が開きますが、URLを変更することができます。
`command: -Dsonar.web.context=/sonarqube`
この設定を追加することで、`localhost:9000/sonarqube`でアクセスできます。

```
services:
  sonarqube:
    image: sonarqube
    command: -Dsonar.web.context=/sonarqube
    ports:
      - "9000:9000"
以下略。
```
Cognos Analytics 11.0.7 新機能 - マイ・パラメーター

#概要
Cognos Analytics 11.0.7の新機能を、興味を持った順に触ってみて、紹介していきます。

今回は、レポートの機能の新機能の「マイ・パラメーター」の機能です。

色々なレポートで使用されている、特定の名称のパラメーターに対して、各ユーザーのデフォルトの選択値を事前に指定しておく事で、レポート実行時にプロンプトが自動的に選択される、という機能になります。

こんなイメージで、各ユーザー毎に特定のパラメーターのデフォルト値が指定されていて、
![022.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/d1c19c73-5cec-90db-2104-55bf84a81844.png)

レポート実行時に、プロンプトの選択に自動的に反映されます。
![023.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/69523e86-05b7-f3bd-ff3f-5512997781ea.png)


#手順

設定手順です。

システム管理者でログインし、「管理」メニューの「カスタマイズ」から「パラメーター」タブを選択します。
「インポート」が既存のレポート上のパラメーターから選択肢を取り込み、「新規」がこの場で新規にパラメーター名と選択肢を作成、になります。
ここでは「インポート」を選択します。
![002.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/c210f981-a0d8-314e-cdb8-aa62cdb1c037.png)

任意のレポートを選択し、パラメーター(例:pPL1)を取り込みます。
![004.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/9cfcf8e6-f444-ab71-aa0e-4009d40941f1.png)

次に、「管理」メニューの「アカウント」から、任意のグループや役割のプロパティを開き、図のように「カスタマイズ」タブから、パラメーターの「設定」で、先ほどのパラメーター(pPL1)及び、デフォルトの選択肢を指定します。
![015.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/a57ae771-3a72-292f-a880-dfc09249135d.png)

このグループ・役割に所属しているユーザーでログインし、pPL1という名称のパラメーターを使用しているレポートを実行すると、図のように、先に指定した選択肢がチェックされて、レポートが実行されます。
![016.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/c665140a-b01d-eaf7-22ed-2d2d98bc5c80.png)

「マイ・パラメーター」アイコンから自分の選択肢を確認する事ができ、
![020.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/576b9d6b-361a-f99a-376f-3014793b5b3b.png)

選択肢を自分自身で変更する事も可能です。
この変更は、グループ・役割に所属するユーザー全体ではなく、自分自身のみに変更が反映されます。
![022.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/be935283-4717-db18-7c1a-0ce57d248dc3.png)

指定変更後のレポート実行イメージ
![023.PNG](https://qiita-image-store.s3.amazonaws.com/0/147246/3983eb81-2604-f2bc-3984-22cfbb5a1596.png)


という機能ですね。
ユーザーや権限ごとに、デフォルトの選択を変えたい、という要件がある時に使える機能かと思います。

#参考

**My Parameters Functionality for Reports in #Cognos Analytics**
https://www.ibm.com/communities/analytics/cognos-analytics-blog/my-parameters-functionality-in-reports/

その他、Cognos Analytics 11.0.7の新機能はこちらです。
**Cognos Analytics 11.0.7 新機能紹介**
http://qiita.com/shinyama/items/174fd2be7f37de277fa2
メモ：jQueryで超簡単スムーススクロール

# 目的
シンプルにスムーススクロールをやりたかった自分用メモ

# 挙動
targetでの画面内遷移を全てスムーススクロールに変える

# 
```js:jQuery
$(function () {
    $('a[href^="#"]').click(function () {
        const href = $(this).attr('href');
        const target = $(href == '#' || href == '' ? 'html' : href);
        $('body,html').animate({scrollTop: target.offset().top}, 200, 'swing');
    });
});
```