OmniAICreator/Qiita-1.07M huggingface dataset:
CodingKeyのマッピングを動的に切り替える

Codableのkeyとプロパティの対応関係、Genericを使えば外から動的に注入できそうだなーと思ってやってみた。

# こんなかんじ

```CodingKeyMapper.swift
/// CodingKeyのマッピングを動的に切り替える
protocol CodingKeyMapper {
    static var mapper: [String: S<Self>.CodingKeys] { get }
}
extension CodingKeyMapper {
    static var mapper: [String: S<Self>.CodingKeys] { return [:] }

    static func key(_ stringValue: String) -> S<Self>.CodingKeys? {
        return mapper[stringValue]
    }
    static func stringValue(_ key: S<Self>.CodingKeys) -> String {
        return mapper.first { $0.value == key }?.key ?? String(describing: key)
    }
}
```

```CodingKeyMapperImpl.swift
///Mapperの実体にはdictを定義するだけ
struct Pattern1: CodingKeyMapper {
    static let mapper: [String: S<Pattern1>.CodingKeys] = [
        "i_another": .i,
        "s_another": .s,
        ]
}

/// 欠けたkey(👇では .s ) は、String(describing: key) として扱われる
struct Pattern2: CodingKeyMapper {
    static let mapper: [String: S<Pattern2>.CodingKeys] = [
        "i_yet_another": .i,
        ]
}

/// key名の変更がないなら何も書く必要がない
struct Pattern0: CodingKeyMapper {}


```

```Execution.swift
struct S<Mapper: CodingKeyMapper>: Codable {
    let i: Int
    let s: String

    enum CodingKeys: CodingKey {
        case i
        case s

        init?(stringValue: String) {
            guard let k = Mapper.key(stringValue) else { return nil }
            self = k
        }
        var stringValue: String {
            return Mapper.stringValue(self)
        }
    }
}


import Foundation

let data = """
{
    "i": 1,
    "s": "デフォルトのsですよ",

    "i_another": 10,
    "s_another": "別のsですよ",

    "i_yet_another": 999,
}
""".data(using: .utf8)!

let decoder: JSONDecoder = JSONDecoder()
let s0 = try! decoder.decode(S<Pattern0>.self, from: data)
let s1 = try! decoder.decode(S<Pattern1>.self, from: data)
let s2 = try! decoder.decode(S<Pattern2>.self, from: data)
dump([s0, s1, s2])

```

## 実行結果

```
▿ 3 elements
  ▿ __lldb_expr_26.S<__lldb_expr_26.Pattern0>
    - i: 1
    - s: "デフォルトのsですよ"
  ▿ __lldb_expr_26.S<__lldb_expr_26.Pattern1>
    - i: 10
    - s: "別のsですよ"
  ▿ __lldb_expr_26.S<__lldb_expr_26.Pattern2>
    - i: 999
    - s: "デフォルトのsですよ"
```

# 思ったこと

一応できたけど、Genericな型なの気になる…。
`Decoder.decode` の引数で渡せればいいんですけどね。
php artisan migrateしたときの「[PDOException] could not find driver」

# マイグレート実行時
laravel「PDOに接続しようとしたけどなんか足りない・・」ってエラー

```
[PDOException]
could not find driver
```

PHP7系のマイ環境では

```
yum install --enablerepo=remi-php70 php php-fpm php-mcrypt php-cli php-common php-devel php-gd php-mbstring php-mysqlnd php-opcache php-pdo php-pear php-pecl-apcu p hp-pecl-zip php-process php-xml
```
で解決
Easy-ISLispのREPL編集機能

#はじめに
ISLisp処理系のEasy-ISLisp(EISL)にREPLでの編集機能を追加しました。EISLはラズパイでの使用をメインに想定しています。ラズパイ３は安価な割に大きなソフトウェアも動作させることができます。とは言えCPU能力はパソコンの10分の1程度です。Emacsの利用は負荷が大きすぎると思います。また、中学生、高校生ではEmacsの設定で力尽きてしまいLispを動かす前に挫折しまう危惧もありました。そこで素のターミナルでの利用においてもREPLでの編集ができる機能を追加しました。なお、Linux版のみです。WindowsはエスケープシーケンスをサポートしていないためWindows版のEISLは対応していません。


#起動
通常どおりにeislとして起動した場合にはデフォルトでREPL編集が可能になっています。Emacsなどで使うため、この編集機能が邪魔になる場合には起動時オプションで無効にすることができます。無効にするためには　-r　を指定してください。

例
REPL編集機能を無効にする場合
```
./eisl　-r
```

#対応するカッコの表示
対応するカッコを強調表示します。図参照

![2017-06-20_6-43-45.png](https://qiita-image-store.s3.amazonaws.com/0/33927/976315b3-02c8-fba4-4070-5dac15d6346d.png)



#組み込み関数などの強調表示
sin　cosといった組み込み関数、そしてdefglobalのような構文については色分け表示をします。


色の設定は組み込みのCUIエディタと同様、任意に設定しなおすことができます。詳細はCUIエディタの記事を参照してください。http://qiita.com/sym_num/items/86c3ffed459ea4fde003


#補完
文字を一部入力し、Escキーの後にTabキーを押しますとその文字列を先頭に含む組み込み関数、構文を補完します。候補が１つしかない場合には自動的に補完されます。候補が複数ある場合には選択肢を５個表示します。その選択肢からは１～５の数で選択します。図参照

![2017-06-20_6-44-50.png](https://qiita-image-store.s3.amazonaws.com/0/33927/cbb426ca-3c39-f658-98ec-05ca70c6371e.png)



#履歴
入力したS式は履歴に記憶されており呼び出して編集、再実行することができます。履歴は10個が保存されています。ctrl+Yで前の入力が呼び出されます。連続してctrl+Yを選択することにより１０個分を遡れます。遡りすぎたときには逆の操作のctrl＋Vで戻すことができます。

ctrl+↑　ctrl+↓　キーの方が直観的でわかりやすいのですが、SSHのターミナルでこれらのキーがサポートされていないことからctrl+Y ctrl+V とすることにしました。

追記
最新バージョンでは↑↓キーでも履歴を呼び出せるようになっています。

#編集
REPL入力中はバックスペースキーの他に←　→キーにより移動、編集することができます。

#入力用組み込み関数
read　read-char　read-line　関数においては編集機能をOFFにしています。　


#バグ
ver0.79でこれらの機能を追加したのですが、編集と履歴呼び出しにバグがありました。ver0.80にて修正します。
プラグインシステム的なものについて考える　～動的import～

MayaとかPhotoshopとかで機能を追加するための『プラグイン』システムがありますが、
そういうのを自作のツールにも設けられないか、というメモです。

# importlib

具体的には「importlib」モジュールを使います。

- **importlib — __import__() の便利なラッパー** (Pythonドキュメント-標準ライブラリ)  
http://docs.python.jp/2/library/importlib.html

このモジュールの「import_module」関数に **モジュール名** を文字列で渡すことで、

```python
import hogehoge
```

という書き方によらないモジュールのインポートができます。
文字列を受け取ってくれるので、見つけたモジュールを随時代入しながらインポートさせられそうです。

使うのは **import_module** だけなので、このようにインポートして使います。

```python
from importlib import import_module
```

（importという文字列の登場頻度の高さ。。。）

# 引っ掛かりポイント

## 1: 絶対パスで渡そうとする

てっきりPythonファイルを渡すものだと勘違いしており、このように書いていました。

```python
pluginPath = 'path/to/plugin'

for plugin in os.listdir(pluginPath):
    mod_path = os.path.join(pluginPath,plugin)
    mod = import_module(mod_path,)
```

ダメでした。
モジュール名を渡すのです。
また、そのためにはプラグイン用Pythonファイルを置いている場所を
sys.path.appendに追加しておく必要があります。
かつ、見つけたPythonファイルも拡張子は除去しておく必要があります。
渡すのはモジュール名だけです。

```python
pluginPath = 'path/to/plugin'
sys.path.append(pluginPath)

for plugin in os.listdir(pluginPath):
    mod_name = os.path.splitext(plugin)[0]
    mod = import_module(mod_name,)
```

これで、プラグインフォルダにPythonファイルを追加すればインポートしてくれるようになりました。

## 2: pycが邪魔

インポートしてくれるようになりましたが、
インポートできたらできたで、pyc作られます。読んでほしくありません。

```python
# 前略

for plugin in os.listdir(pluginPath):
    split_name = os.path.splitext(plugin)
    if split_name[1] == '.pyc':
        continue
    mod = import_module(split_name[0],)
```

# 見つけたプラグイン分だけボタンを増やす

あとは見つけた分だけボタンを配置します。

## plugin.py の仕様

仕様というほどでもありませんが、
プラグインの機能を利用するための関数をあらかじめお約束しておきます。
`exec` とか `doIt` とか `run` とかが考えられます。

また、ボタンに記載するラベルもモジュールに持たせておきましょう。

```python:plugin.py

LABEL = 'create poly sphere'

"""
some your scripts...
"""

def exec():
    pass

# or

def doIt():
    pass

# or

def run():
    pass

#-----------------------------------------------------------------------------
# EOF
#-----------------------------------------------------------------------------
```

`module_name.exec`　（など）をボタンにconnectします

## ボタンへconnect

`QPushButton`をつくり、`.clicked.connect` にさっき決めた実行用関数を渡します。

```python
btn = QtGui.QPushButton( mod.LABEL )
btn.clicked.connect(mod.exec)
```

これを、モジュール読んでるfor文に加えます。

# まとめ

```python
import os
import sys

from PySide import QtCore, QtGui
from importlib import import_module

pluginPath = 'path/to/plugin'
sys.path.append(pluginPath)

for plugin in os.listdir(pluginPath):
    split_name = os.path.splitext(plugin)
    if split_name[1] == '.pyc':
        continue
    mod = import_module(split_name[0],)

    btn = QtGui.QPushButton( mod.LABEL )
    btn.clicked.connect(mod.exec)
```

こういう感じのをGUIつくってるスクリプトのどこかにいい具合にいれます

結局一番時間かかったのは
import_moduleに絶対パス渡そうとして「通らないなー」って唸ってたあたり
~~とpluginを **pluing** とタイポしてたあたり~~ でした…。

ドキュメントよく読もう！

***

GUIの部分についてはこちらもどうぞ

- 【補完】[PySide] QtDesignerで遊ぼう  
http://qiita.com/it_ks/items/449b7418e83956ecdc8c

参考？

- 初めての Maya Python プラグイン  
http://help.autodesk.com/view/MAYAUL/2017/JPN/?guid=__files_GUID_B968733D_B288_4DAF_9685_4676DC3E4E94_1_htm
【selenium】バージョン問題

#概要
seleniumはサードパーティとのバージョン問題が重要。
ここに、動いている組み合わせのバージョン一覧をメモする。
#環境
sakuraのVPS
OS:Ubuntu16.0.4
言語:Python3.5
#バージョン
selenium(3.3.2)
firefox(52.0b1)
geckodriver(0.15.0)
#注意
firefoxは最新のものでは動かない。
geckodriverは最新の0.17.0でもバグはfixしていない。
問題は0.16.0時代に生まれたもの。(send_keysやclickができない)
#所感
サードパーティものだと、vagrantとvirtualboxの時も苦労した気がする。
その割に、動いている組み合わせの情報って少ないな..
環境によっての違いがあるからかしら。
Windowsでエポックミリ秒、UUID （個人メモ）

# 環境準備
[git for windows](https://git-for-windows.github.io/) をインストール
Git Bashを起動

# エポックミリ秒 (Epoch milli, Unix time)

```
$ date +%s
1497002250
```

# UUID

```
$ uuidgen
a65d27fc-b24f-4b45-8051-736ec8d5ef2d
```
[python]グラフ描画のためのライブラリMatplotlibの使い方

[参考][ゼロから作るDeep Learning(p130)](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585)

ディープラーニングの実験においては、
グラフ描画やデータの可視化が重要になる。
グラフ描画のためのライブラリMatplotlibを使えば、
簡単にグラフの描画やデータの可視化が簡単に行える。

#Matplotlibの基本的な使い方。
「y=2x」を例に、描画のために以下のような値を指定する。

```python
import numpy as np
import matplotlib.pyplot as plt

# 描画範囲の指定
# x = np.arange(x軸の最小値, x軸の最大値, 刻み)
x = np.arange(0, 6, 0.1)

# 計算式
y = 2 * x

# 横軸の変数。縦軸の変数。
plt.plot(x, y)

# 描画実行
plt.show()
```

以下のように描画出力される。

![](https://i.gyazo.com/32d08d87d10f25fd21a07bf472e23e4b.png)

# 計算式を変えてみる

実際に「y=2x」以外の計算式をグラフ描画してみる。
コードの「#計算式」の部分を変えればグラフが変わる。

### 「y = 2 * (x**2)」の場合

```python
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1)

# 計算式
y = 2 * (x**2)

plt.plot(x, y)
plt.show()
```

![](https://i.gyazo.com/a3196e531163310d60863de7f40197ec.png)


### 「y = sin(x)」の場合

```python
# 計算式
y = np.sin(x)
```

![](https://i.gyazo.com/3373c622d3568bd485274b5098bfe607.png)

# 描画範囲を変えてみる。

今までの例では、描画範囲を`np.arange(0, 6, 0.1)`にした。
計算式は`y=np.sin(x)`で、描画範囲を変えてみる。

### x軸（-12~+12）の範囲を描画する

```
x = np.arange(-12, 12, 0.1)
```

![](https://i.gyazo.com/422396890ba4acdbfc0db695d080fccc.png)

ちなみに、
arangeで指定する場合はy軸は値で自動で設定してくれるので、
計算式を`y = 4 * np.sin(x)`とするだけで、以下のようにy軸の範囲が広がる。

![](https://i.gyazo.com/9706852ad8e9f64f1ec97e5925f9ef67.png)

### y軸の描画範囲を固定したい場合
以下のような実装だと、y軸はyの値によって変動する。

```python
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1)
y = np.sin(x)
plt.plot(x, y)

plt.show()
```

![](https://i.gyazo.com/8e54121a8ca7abf549db4581c37dbab6.png)

y軸の範囲を固定したいときは、
ylimでy軸の描画範囲を指定する。
x軸の範囲を固定するxlimも用意されている。


```python
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1)
y = np.sin(x)
plt.plot(x, y)

plt.ylim([-4,4])
plt.show()
```

![](https://i.gyazo.com/52f9345de863cfe838876c43228e473b.png)

# 刻みを変えてみる
以下のような`y=np.sin(x)`を描画するとき、
`np.arange(0, 6, 0.1)`で描画範囲を指定していた。
`arange`の第三引数で"数値の刻み"指定できる。
この例だと、0.1刻みで描画される。

```python
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 6, 0.1)
y = np.sin(x)
plt.plot(x, y)
plt.show()
```

![](https://i.gyazo.com/3373c622d3568bd485274b5098bfe607.png)

これを0.5刻みにすると以下のようになる。
角ばったような描画になる。

```python
x = np.arange(0, 6, 0.5)
```

![](https://i.gyazo.com/c0650d018f43e2d9ee034d23bedec150.png)

# 二つのグラフを描画するとき

sin関数とcos関数を同時に描画する。

```python
import numpy as np
import matplotlib.pyplot as plt

# 描画範囲の指定
x = np.arange(0, 6, 0.1)

# 計算式
y1 = np.sin(x)
y2 = np.cos(x)

# グラフ描画設定
plt.plot(x, y1, label="sin") # y1グラフに、ラベル「sin」付与。
plt.plot(x, y2, linestyle="--", label="cos") # y2グラフに、ラベル「cos」付与。linestyleで線のスタイルを指定。
plt.xlabel("x") 
plt.xlabel("y")
plt.title('sin & cos')

# ラベルの描画
plt.legend()
# グラフの描画実行
plt.show()
```

![](https://i.gyazo.com/cc2d402817ed94995a538faecbddc5c7.png)
Raspberry Pi 3の導入まとめ

SDXC64GBのSDカードが届いたのでRaspberry Pi 3の導入に挑戦してみました．
今回はRaspberry Pi 3のセットアップを中心に，OSのインストールと日本語設定までを説明します．

##ハードウェア

* Raspberry Pi 3 Model B
* Samsung microSDXCカード 64GB EVO Plus Class10

![hako.JPG](https://qiita-image-store.s3.amazonaws.com/0/157812/0b714a78-2e3c-25b1-582f-46f1459b584f.jpeg)
![sd.png](https://qiita-image-store.s3.amazonaws.com/0/157812/bb9ae72e-e245-e86f-92cb-6075e90b7001.png)

その他，必要なもの

* micro USBケーブル
* マウス
* キーボード
* HDMIケーブル
* LANケーブル


##手順
###1．SDカードのフォーマット
Raspberry Pi 3にOSをインストールするためにはFAT32でフォーマットしたSDカードが必要です．
通常SDカードのフォーマットはWinやMacに標準搭載されているフォーマットソフトで行いますが，32GBより容量の多いSDカードはMacやWinで普通にフォーマットしてもラズパイで認識されません．
なので，私はWinのサードパーティソフトの「[guiformat.exe](http://www.ridgecrop.demon.co.uk/index.htm?guiformat.htm)」を用いてSDカードをFAT32にフォーマットしました．
※下のサイトの外観を載せました．真ん中の画像をクリックするとexeファイルのダウンロードが始まります．

![スクリーンショット 2017-06-20 2.12.16.png](https://qiita-image-store.s3.amazonaws.com/0/157812/fd2563cb-7226-e873-124d-09bb6a6b4dbc.png)



###2．NOOBSからダウンロードしたファイルをSDカードにコピー
[NOOBS](https://www.raspberrypi.org/downloads/noobs/)にアクセスしてZIPファイルをダウンロードします．
![スクリーンショット 2017-06-20 2.17.17.png](https://qiita-image-store.s3.amazonaws.com/0/157812/160af881-6650-fe63-fb30-0dd2e916d0f9.png)


###3．OSのインストール
インストール時に選べるいくつかOSがありますが，今回は「Raspbian Jessie with PIXEL」を選択

###4．日本語表示と日本語入力の設定
OSのインストールが終わったらまずは日本語表示の設定を行います．
「Menu>Preferences>Add / Remove Software 」に移動し「Japanese TrueType font set, Takao Fonts」の日本語フォントのインストールを行います．

次に地域設定です．「Menu>Preferences>Raspberry Pi Configuration」に移動し以下の通りに設定を行います．
「Locale」：「ja（Japanese）」「JP（Japan）」「UTF-8」
「Timezone」：「Asia」「Tokyo」
「Keyboard」：「Japan」「Japanese」
「Wifi Country」：「JP Japan」

地域設定適用後に再起動されます．その後，Mozcをインストールし日本語入力を適用します．
LXTerminal（端末）を起動し以下のコマンドを入力します．
sudo apt-get install ibus-mozc

インストールが終わったら画面の右上にある入力モードをクリックしMozcを選択することで，日本語入力が適用されます．

![IMG_2198.JPG](https://qiita-image-store.s3.amazonaws.com/0/157812/a7e66184-6b0a-39ee-167e-a7ed54ab16e6.jpeg)


##64GBSDカードのフォーマットにハマってしまい，予想以上に時間がかかってしまった．でも，それ以外はわりとスムーズに進んだ！

![IMG_2196.JPG](https://qiita-image-store.s3.amazonaws.com/0/157812/bb452233-c9af-b13c-1ec3-5c3d25da22f9.jpeg)
親子構造を持つオブジェクトの回転軸を固定する方法

親子構造を持つオブジェクトの回転が思った通りにならなかったのは慣性テンソルが原因だった。

## 状況
- 空の親オブジェクトの子要素に2つのcubeが入っている
- 上のcubeのpositionは(-0.5, 1, 0)
- 下のcubeのpositionは(0, 0, 0)
- cubeにはBox Colliderをアタッチ
- 空の親オブジェクトにRigidbodyをアタッチ
- RigidbodyのConstraintsでFreeze Rotation以外チェックボックスをオンに
    - ローカルのVector3.upでだけ回転させたかった(コマのようなイメージ)

![SnapCrab_NoName_2017-6-20_1-24-23_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/82250/52ec7384-0c15-396e-fcb0-1bb61effa9a7.png)

この状況下でRigidbodyとColliderをもつ他のオブジェクトを衝突させてもコマのような回転にならなかった。

## 原因
結果としては**慣性テンソルの回転角度**が原因だった。
Unityでは慣性テンソルの回転角度がRigidbodyにアタッチされているすべてのColliderから自動的に計算されるのだが、このおかげでイメージ通りに回転しなかった。
上記の状況ではこの値がEulerAnglesで（0, 0, 26.6)になっていた。
実際の物理挙動的にはこちらが正しいのだが、イメージ通りに動かすためにこの値を書き換えることで期待する回転運動を得ることができた。

![SnapCrab_NoName_2017-6-20_1-24-12_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/82250/88a4575c-d7df-d89f-51cb-261b33638967.png)

## 修正
```csharp:InertiaTensor.cs
private void ResetTensor()
    {
        var rigid = transform.GetComponent<Rigidbody>();
        rigid.inertiaTensorRotation = Quaternion.identity;
    }
```
`Quaternion.identity`とすることで**回転していない状態**を慣性テンソルの回転角度とした。

![InertiaTensor.gif](https://qiita-image-store.s3.amazonaws.com/0/82250/cb51b656-a8dd-6afa-39e4-7b445e708d15.gif)

## 参考
**ニュートンの第2法則**
直線運動　質量 × 加速度 ＝ 力

**回転の運動方程式**
回転運動　慣性モーメント × 角加速度 ＝ トルク 

[FNの高校物理](http://fnorio.com/0093equation_of_rotational_movement1/equation_of_rotational_movement1.html)
[Rigidbody.inertiaTensorRotation](https://docs.unity3d.com/ScriptReference/Rigidbody-inertiaTensorRotation.html)
dockerでサクッとwebサイトを立ち上げる

# Overview
docker公式のapacheイメージを使用して静的なWebサイトを立ち上げます

# Environments
使用するイメージ : https://github.com/docker-library/httpd
立ち上げるサイト : https://github.com/themefisher/timer-html

# Actions

* まずはイメージのリポジトリをクローン  
apacheのバージョンが2.2と2.4がありますが、ここは2.4で

```
git clone https://github.com/docker-library/httpd.git
cd httpd/2.4
sudo docker build -t apache24 .
```

ディレクトリ内には
```alpine  Dockerfile  httpd-foreground```
があり、このDockerfileの記述を基にイメージが作成されます。ビルドはそこそこ時間がかかります
-tオプションは作成するイメージに名前をつけているだけです

* 立ち上げたいサイトをクローン + コンテナを起動

```
git clone https://github.com/themefisher/timer-html.git
sudo docker run -itd -p 80:80 -v ~/timer-html:/usr/local/apache2/htdocs apache24 httpd-foreground
```

イメージからコンテナを立ち上げます
コンテナを起動しつつ、apacheのプロセスを立ち上げ、Webサイトのファイルをコンテナにマウントし、ポートフォワードしてます

コマンドが長い？むしろこれだけでwebサイトが立ち上げられるんです。技術の進歩に感謝しましょう
呪文を使わず、SublimeTextにPackage Controlをインストールする

SublimeTextにPackage Controlをインストールする場合、コンソールを開いて `import urllib.request,os,hashlib...` みたいな呪文を入力する方法が有名ですが、実はもっと手軽にインストールできます。

---------------------

1. <kbd><kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>p</kbd></kbd>キーでコマンドパレットを開きます。(Windowsなら <kbd><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>p</kbd></kbd>)
1. `install package control` と入力し、<kbd><kbd>Enter</kbd></kbd>キーを押下します。
![スクリーンショット 2017-06-19 23.58.24.png](https://qiita-image-store.s3.amazonaws.com/0/187987/27b44d77-c5b5-3714-b76a-6f996c0f1048.png)
1. しばらく待ち、以下のようなダイアログが出れば完了です。
![スクリーンショット 2017-06-19 23.58.48.png](https://qiita-image-store.s3.amazonaws.com/0/187987/c13868fc-c9cf-2012-5953-2984eea6071e.png)
PHP5技術者認定試験(上級)に学ぶ、実はよく知らないPHPの仕様 (1)


# PHP5技術者認定試験（上級）

資格試験に向けて勉強中です
勉強していて、PHPについて実は知らなかった／勘違いしていたことが幾つかあるため
参考書の内容を抜粋して記載します。（抜粋するとは言っていない）

## 関数

### 関数とは

- ひとまとまりのコードに名前をつけたもの
- 入力を受ける変数を **パラメータ** 出力を **返り値** と呼ぶ
- 関数には **ユーザ定義関数** と **組み込み関数** がある
- 関数の呼び出しが、その関数の定義より前に記述されていても問題ない

### マイナーな細かい仕様
- 関数名の大文字・小文字は **区別されない**
- 関数は入れ子にできる
  - 以下のbar()はfoo()の実行後であれば、fooの外でも呼び出せる

```php
function foo(){
	function bar(){
		return "bar";
	}
}
foo();
bar();
```

### 変数
- グローバルスコープ と 関数レベルのスコープ がある
- 関数からグローバル変数を呼ぶ場合は `global $hensu` のように宣言が必要
- （デフォルトでは）関数内からグローバルスコープにアクセスできない
- `static $number = 0` のように宣言することで、呼び出し後も保持される変数となる
  - 上記の場合 `0` が代入されるのは最初の実行時のみ
  - 初期化に使えるのは 定数 または リテラル のみ。変数や式は使えない。
      - `static $number = $x` はエラーになる

### 関数のパラメータ
- 値渡しと参照渡しがある
 - 参照渡しは `function foo(&$x){ ` のように **&** を付加する
 - 参照渡しで定義した関数に変数以外を渡すと Fatal Error になる
- `function($x = 10)` のようにしてデフォルト値を設定できる。
 - `function(&$x = 10)` のように、 *参照渡しでもデフォルト値を設定できる* 。
- 可変長引数も利用可能
 - 通常の引数の定義は必要なく、以下の関数を使用して取得

| 関数名 | 機能 |
|---|---|
| func_num_args() | 引数の数を取得 | 
| func_get_arg($index) | 指定indexの引数を取得 | 
| func_get_args() | 引数を配列で取得 | 

### 関数の返り値

- デフォルトでは return で指定された値のコピーを返す
- 参照を受け取る場合は、 **&** を 関数名の前につける

```php
function &foo(&$x){
	return $x;
}
$value = &foo
```

### 可変関数
- 変数名に関数名の文字列を設定して呼び出すことが可能

```php
$func_name = "printf";
$func_name("hello");
```

- 対応する関数が無いとエラーが発生するので、 `function_exsists($func_name);` でチェックしよう
- `echo()` や `isset()` の構造言語は、この方法で *呼び出せない* （エラーになる）
 - （だが黒本には構造言語について説明がない）

### 匿名関数 create_function

- 他と衝突しない、ランダムな関数名となる
- `create_function(string $arg, string $code )` で定義
 - $付きの変数名を記載する関係上、シングルクォートで記載しましょう

```php
$method = create_function('$x', 'echo $x;');
$mechod('hello');
```

- 匿名関数は `array_filter()` などの引数としても利用可能


## 終わりに

- [第1回 関数](http://qiita.com/tmak_tsukamoto/items/84f7d62f6106fad5fd23)
- [第2回 文字列](http://qiita.com/tmak_tsukamoto/items/41673ab2d6fedeef0980)
- [第3回 配列](http://qiita.com/tmak_tsukamoto/items/2eb6d10e83b6c00981c9)
Bash on Windows でエイリアスを設定する方法

# SSHのショートカットを作りたい
自宅のRaspberry Piサーバーによくアクセスするので、Windowsから簡単にアクセスする方法を探してた。
SSHクライアントとしてはBash on Windowsを使用する。
ホストネームでエイリアス作ればいいんじゃない？ということで、色々調べたのをメモ。

要するに以下のエイリアスを登録したい。

```
alias hostname='ssh -p 12345 -i /pass/to/id_rsa  huga@hogehoge.com'
```

こういうのは .bashrc に記載すれば良いらしく、早速覗きにいったら以下のような記述が。


```sh:.bashrc
～省略～

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi
```

# .bash_aliases 作成
ということで、エイリアスを別ファイルで登録する際は .bash_aliases っていうファイルを作ってそこに書き込めばいいらしい。

```
cd ~
nano .bash_aliases
```

作成したファイルに前述のエイリアスを書き込んで保存すればOK。簡単でした。
古いXcodeをダウンロードしてインストール

Macにipoptをインストールしようとするとエラーでインストールできませんでした。Xcodeのバージョンが古いのが問題だったのですが、古いバージョンのXcodeを探すのに少し手間がかかったのでメモ

# ipoptがインストールできない
```
% brew install ipopt
```
とすると幾つかのビルドエラーが出て最後に

```
Error: Your Xcode (6.1) is outdated.
Please update to Xcode 7.2.1 (or delete it).
Xcode can be updated from the App Store.
```
というが出てインストールが中止されてしまいました。

# App Storeからアップデート
App StoreでXcodeを検索してインストールしようとしましたが
```
OS X version 10.12 or later is required
```
との事でアップデートできません（該当のMacは空きスペースの問題でYosemiteのまま）

# 古いXcodeをダウンロード
https://developer.apple.com/download/
を見ても
![Screen Shot 0029-06-20 at 00.58.54.png](https://qiita-image-store.s3.amazonaws.com/0/129712/fcdb12f1-c0a2-abca-488b-c39c53b61607.png)
の通り、8以降しかダウンロードできず、今の環境（Yosemite）では利用できません。

https://developer.apple.com/download/more/?name=Xcode
から必要なバージョンをダウンロードすることが出来ました。

![Screen Shot 0029-06-20 at 01.00.42.png](https://qiita-image-store.s3.amazonaws.com/0/129712/5e451722-e0ca-86c0-23eb-eb44f812d6ce.png)
React+Reduxでめんどうな状態管理なしで他のコンポーネントの機能を呼び出す

# はじめに

react+reduxで他のコンポーネントの機能を直接呼び出したい場合があると思います。例えば、Google Maps JavaScript APIやchart.jsのようなそれ自身ステートを持つようなライブラリの機能をラップするコンポーネントがあって、そのAPIを他のコンポーネントから呼び出す場合です。

react+reduxサイドでも各ライブラリのステートに相当するステートを独自に管理して、コンポーネントがそれを参照して適切にライブラリのAPIを呼び出すのが正攻法な気がしますが、冗長だし、ステートの同期をとる必要があるのでこの「適切に」というのがけっこう面倒です。

そこで、ひとつの解決策として呼び出したいAPIに対応する action をキューに積むという方法を試してみました。以下でコードを示しながら説明していきます。断片的なのでわかりにくいですが想像で補ってください。

# action
通常のactionと同様に宣言します。

```js
export function someAPI(args) {
    return {
        type: ActionTypes.SOME_API,
        args
    };
}
```

そして、もうひとつ action queue の末尾のひとつを削除するための action を宣言しておきます。

```js
export function removeFromActionQueue() {
    return {
        type: ActionTypes.REMOVE_FROM_ACTION_QUEUE,
    };
}
```


# state
stateの初期値に action_queue を空のarray として追加しておきます。

```js
const initialState = {
...
    action_queue: [],
};
```
# reducer

reducer では先程の action_queue の末尾に action そのものを追加してしまいます。actionそのものである必要性は特にはないんですが、簡単なのでそうしています。

redux のコンベンションに従ってaction_queue を直接操作するのではなくコピーしたものに追加して大元のstateにつけかえます。

```js
const mainReducer = function(state = initialState, action) {
    switch (action.type) {
...
    case ActionTypes.SOME_API:
        {
            const action_queue = state.action_queue.concat(action);
            return Object.assign({}, state, {action_queue});
        }
...
```

そして removeFromActionQueue も同様に直接操作しないようにします。

```js
...
    case ActionTypes.REMOVE_FROM_ACTION_QUEUE:
        {
            const action_queue = state.action_queue.slice(0, -1);
            return Object.assign({}, state, {action_queue});
        }
...
```

# component

実際にapiを呼び出すコンポーネントは action_queueをプロパティとして取り込みます。componentWillUpdateやcomponentDidUpdate等でその変化をつかまえて、末尾のactionを参照し、自分の管轄だったら、それに対応したAPIを呼び出し、そのあとremoveFromActionQueueを呼び出します。

以下のようなコードになります。

```js
class MyComponent extends Component {
    componentDidUpdate() {
        const action = this.props.action_queue[len-1];
        if (action.type == ActionTypes.SOME_API) {
            call_api(action.args); // API を呼び出す
            this.props.removeFromActionQueue();
        }
    }
....
}

function mapStateToProps(state) {
    return {
        action_queue: state.main.action_queue,
...
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({removeFromActionQueue, ...}, dispatch);
}
```

# まとめ

われながらreduxの流儀からぎりぎりはずれないスマートな実装な気がします。少し前に書いたコードなので今はもっといい方法があるかもしれません。こっちの方がスマートという方法があれば教えてください。
OSを再インストールしてログインができない時

##OS再インストール後ログインできない
怒られました

```@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:w4x+ws3hHVyDCfKnkodTxM14W4/TMCgNuGOWx8C/PeM.
Please contact your system administrator.
```

##情報を消す必要がある
```$ ssh-keygen -R 100.100.100.100```


##もう一回接続
```$ ssh@100.100.100.100```

パスワードを入力すればログインできた！
```
SAKURA Internet [Virtual Private Server SERVICE]
```
electron開発準備メモ

# 必要なものと、どこからインストールするか




|   |OSX (MacPorts)|OSX (Homebrew)|Windows|   |
|:--|:-------------|:-------------|:--|:--|
|node|nvm|nvm|nvm-windows|本体|
|nvm|git|brew|インストーラ（？）|複数versionのNodeをあれこれ取り替えるのに必要|
|npm|nvm|nvm|nvm-windows|パッケージマネージャ。必要なものはリカーシブに全部取ってきてくれて version 確認までやってくれる|
|electron|npm|npm|npm|本体|


## OSX (Homebrew) の場合

```
brew install nvm
```

~/.zshenv の最後に

```
export NVM_DIR="$HOME/.nvm"
. "/usr/local/opt/nvm/nvm.sh"
```
追加（```which nvm``` が暴走するようになるが無視）。

```nvm ls-remote``` して動作＆バージョン確認してインストール。

```
nvm install v6.11.0
nvm use v6.11.0
node -v
npm --version
npm install electron -g
```

node, npm がインストールされ、npm で global に electron をインストールする。



## OSX (MacPorts) の場合

```
git clone git://github.com/creationix/nvm.git ~/.nvm
```

~/.zshenv の最後に

```
. $HOME/.nvm/nvm.sh
```
追加。以下は Homebrew と一緒。

参考
http://mollifier.hatenablog.com/entry/20110221/p1


## Windows の場合

* nodist （古い）
* nvmw （python,gitが必要）
* nvm-windows



[coreybutler/nvm-windows](https://github.com/coreybutler/nvm-windows/releases ) インストーラはインストールが不完全に終わるようだった（プログレスバーが半分くらいでいきなり完了。インストールされたであろうファイルが見つけられないなど）
noinstall.zip を実行してみたら、そのあとではインストーラからのインストールが動いた（？）
AppData¥¥Roaming¥¥nvm にインストールされ、パスも通っている

参考
http://jsstudy.hatenablog.com/entry/functionaljs-9-nvm-windows
http://multix.jp/install-nodejs/

コマンドプロンプト上で nvm が動くので、以下は上の Homebrew の ```nvm install v6.11.0``` 以下と同じ。


# Testプログラム

https://ics.media/entry/7298
簡単な確率分布をpython3を使ってやってみる

# 簡単な確率分布
1. 正規分布
2. ポアソン分布
3. 二項分布

簡単な例をグラフ表示するプログラムをJupyter notebookで書きました。
以下のGistで公開しています。
https://gist.github.com/koki-ogura/4e45e938dd0c3303b34b272082af91a4

ソースは以下のgithubで公開しています。
https://github.com/koki-ogura/probability_basis
rtmpの認証できないエンコーダの間にffmpeg入れて認証する

#認証できないエンコーダって・・・・
認証ができないエンコーダがあったら困りますよね。
間にffmpegを噛まして認証して飛ばしたいと思いました。

#環境
Lunux系であれば多分なんでも

#nginxインストール
http://qiita.com/hagane5563/items/842afe6d6e7100db3a28
を参照してください。

#ffmpegインストール
apt-getとかyumでサクッと。

#nginxコンフィグ
```lang:/etc/nginx/nginx.conf
rtmp {
    server {
        listen 1935;
        access_log /var/log/nginx/rtmp_access.log;
         application conv {
            live on;
            wait_video on;
        }
    }
}
```

#エンコーダ側設定
rtmp://nginxサーバのアドレス/conv/ストリーム名
でエンコード


#ffmpegコマンド
ffmpeg -re -i "rtmp://localhost/conv/ストリーム名" -c:v copy -c:a copy -f flv "rtmp://ユーザ名:パスワード@認証が必要なRTMPアドレス"
Ctrl+Cで止まります。

#まあ
認証できるエンコードを使った方が良いにこしたことは無いよね。
DDoS攻撃を受けてWebサービスがダウンしていく様子を『Zabbix』で監視してみました

#■ 概要

2017年6月下旬、中国や韓国の金融機関が攻撃グループから DDoS 攻撃の脅迫を受けていたようです。

▼JPCERT/CC
https://www.jpcert.or.jp/newsflash/2017062901.html

同じ時期(6月29日)、日本でもいくつかの金融機関で通信障害が発生していました。

事前に DDoS 対策を行い、攻撃を未然に防ぐ事は現在の技術では難しいですが、
いち早く攻撃を検知する事で被害を最小限に防ぐ事ができます。
そこで、Zabbix で DDoS 攻撃を検知できるか、検証してみました。

#■ 検証環境


####◆攻撃側（ボットネット）
　　C&Cサーバ ： Ubuntu 16.04（1台）
　　ボット ： CentOS 7.3（3台）、Ubuntu 16.04（2台）

####◆標的（ターゲット）
　　Ubuntu 16.04
　　Apache HTTP Server 2.4
　　WordPress 4.7

####◆Zabbix サーバ
　　CentOS 7.3
　　Zabbix 3.0

#■ 検証方法

ボットネットからターゲットに対して、F5 攻撃を行い、Zabbix でWeb監視しました。

#■ 検証結果
DDoS 攻撃前は、200（正常）だった HTTP レスポンスコードが、
DDoS 攻撃開始 45 秒後には、500（サーバエラー）になりました。

####◆DDoS 攻撃前
![DDoS前.png](https://qiita-image-store.s3.amazonaws.com/0/179531/e02e9b8b-b5a6-7faa-aebb-22a9171593ed.png)

####◆DDoS 攻撃開始 45 秒後
![DDoS後.png](https://qiita-image-store.s3.amazonaws.com/0/179531/0231c5ed-f7de-9c04-0645-b5724dd9d799.png)


#■ まとめ

DDoS 攻撃が始まるとすぐにサービス不能になり、DDoS 攻撃の予兆を検知することは難しそうです。
その為、被害を最小限に防ぐ為には、DDoS 攻撃を受けた場合のインシデントレスポンスを事前に準備しておく必要があります。
Cent OS 7 に yum で MySQL 5.7 を入れて使うまでの手順


# mariaDBをアンインストール

https://weblabo.oscasierra.net/installing-mysql56-centos7-yum/ を参考に行った。リンク先は5.6を入れているが、今回この記事では5.7を入れる。CentOS 7 にはmariaDBがデフォルトが入っていることがあり、MySQLと競合を起こすことがあるので削除したほうがいいとのこと。

```
$ yum remove mariadb-libs
$ rm -rf /var/lib/mysql/
```

# MySQL 5.7 のインストール

続いてyumを使ってmysql 5.7 を入れていく

```
$ yum localinstall http://dev.mysql.com/get/mysql57-community-release-el6-7.noarch.rpm
$ yum -y install mysql-community-server
$ mysqld --version
mysqld  Ver 5.7.18 for Linux on x86_64 (MySQL Community Server (GPL))
```

# 起動時に自動的に MySQL Sever が起動するように設定

```
$ chkconfig
...
mysqld          0:off   1:off   2:on    3:on    4:on    5:on    6:off
...

$ sudo systemctl enable mysqld
mysqld.service is not a native service, redirecting to /sbin/chkconfig.
Executing /sbin/chkconfig mysqld on
```

# ついでに MySQL Server を起動

```
$ sudo systemctl start mysqld
```

止めたい時は `start` の代わりに `stop` となる

# MySQL の root の初期パスワードを確認

以下のコマンドで確認できる

```
sudo cat /var/log/mysqld.log | grep 'temporary password'
 [Note] A temporary password is generated for root@localhost: XXXXXXXXXX
```

# MySQL に接続してみる

```
$ mysql -u root -p
Enter passwrod: #先ほどのパスワードを入力

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.7.18
```

# root のパスワードを変更する

これからroot以外のユーザーを作ろうと思うのですが、rootで何かする前に必ずrootのパスワードを変更しないといけないようなので変更します。

rootでMySQLにログインして以下のコマンドを実行します。

```
mysql> set password = 'h0geFug@';
```

パスワードにはある程度の制限があります。Tipsを参考にしてください。

## Tips

以下のエラーが出た場合

```
ERROR 1819 (HY000): Your password does not satisfy the current policy requiremen ts
```

MySQL 5.7からパスワードが脆弱すぎるとエラーになるようです。デフォルトだと、8文字以上で、英語大文字・小文字・数字・記号 の4種類の文字を含んでいる必要があるようです。この制限を外すこともできます。外したいかたはググってください。ちなみにデフォルトのパスワードをそのまま入れても一応通るらしい。

# ユーザーを作成する

rootでログインして以下のようなコマンドでユーザーを作成できます。

```
mysql> CREATE USER 'uma'@'localhost' IDENTIFIED WITH mysql_native_password BY 'h0geFug@';
```

ここのパスワードもある程度の入力制限をうけます。

実際に作成したユーザーでログインできることを確認します。

```
$ mysql -u uma -p
```

## Tips

以下のエラーが出た場合

```
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.
```

root のパスワードが初期設定のままなので変更する必要があります。「rootのパスワードを変更する」の章を参考にしてください。
気象庁防災情報XMLフォーマット形式電文をダウンロードするだけのプログラムとDockerイメージを作った

名前が長いので、以降は「気象庁防災情報XMLフォーマット形式電文」を「気象庁XML」と呼称します。
また、私は気象庁関係者ではないので何かしら間違いや不適切な点があるかもしれません。
気がついた方は教えてください。

## 概要
気象庁は収集した気象データの一部を一般に公開しています。
気象庁XMLをダウンロードするだけのプログラムとDockerイメージを作ったので説明します。
説明は要らないからとりあえず気象庁XML欲しい、という方はdocker-compose.yml書いてください。
残念なプログラムを見たい人は最下部にGitHubのリンク貼ったのでそっちをお願いします。

ベースイメージ : alpine:3.6
プログラム : php7

プログラム類はMITライセンスにしたので使いたい奇特な人は好きに使ってください。

## 気象庁XMLについて
気象庁では気象庁が収集した気象データを、XML形式のファイルにして公開しています。
天気予報、気象警報・注意報、地震、異常天候の予測など、様々なデータがあり、定時または随時更新されています。

以前はPubsubhubbubを使った登録制のPush型配信だけでした。
今はPull型のデータ公開も行っており、自由にダウンロードすることが可能です。
Atomフィードを取得、解析し、XMLデータを取得するだけなので、とても簡単です。

詳細は気象庁ホームページを参照してください。
気象データ高度利用ポータルサイト
http://www.data.jma.go.jp/developer/index.html

※ダウンロードした気象データは気象庁の公開するルールに従って使いましょう。
※気象データの利用は自己責任です。

## docker-compose.yml
気象庁では気象データを以下の4つに分類分けし公開しています。
今回作ったプログラム中では、公開されているAtomフィードのURLに従って以下の通り環境変数を用意しています。

* 定時 : DATA_TYPE_REGULAR 
* 随時 : DATA_TYPE_EXTRA
* 地震火山 : DATA_TYPE_EQVOL
* その他 : DATA_TYPE_OTHER

各環境変数を`true`に設定することで、対象の気象庁XMLをダウンロードします。
下記の通り設定した場合、「定時」の気象庁XMLだけを対象にします。

~~~
version: '2'

services:
  jma-xml-downloader:
    image:  ancolin/jma-xml-downloader
    volumes:
    - /tmp:/app
    environment:
    - FEED_DIR=/app/feed
    - DATA_DIR=/app/data

    - DATA_TYPE_REGULAR=true
    - DATA_TYPE_EXTRA=false
    - DATA_TYPE_EQVOL=false
    - DATA_TYPE_OTHER=false
~~~

## コンテナの起動 (プログラムの実行)
`docker-compose run`で実行する使い捨て型で、常駐はしません。
下記のようなコマンドで実行してください。
`docker-compose run --rm jma-xml-downloader`

気象庁では先述の4情報種別それぞれに「高頻度フィード」と「長期フィード」を用意しています。
標準では高頻度フィードを取得するようになっています。
もし長期フィードのデータを取得したいときは、下記のように引数に`longer`を指定して実行してください。
`docker-compose run --rm jma-xml-downloader longer`

cronに書いて定期的に実行する、とかすれば良いと思います。
「毎秒実行する」とか相手サーバに負荷がかかるようなことは避けてあげましょう。
あとバックアップ、圧縮、削除などは全くしないので、そのあたりは自分でshellスクリプト書くとかしてください。

## プログラムとDockerfile
プログラムとDockerfileはこちらで公開しています。
https://github.com/ancolin/docker-jma-xml-downloader
centos7 ファイアーウォール起動、停止、selinux

#ファイアーウォール起動、停止
firewalldの開始、終了、ステータス
\# status
systemctl status firewalld

\# start
systemctl start firewalld

\# stop
systemctl stop firewalld

#ファイアウォール設定を要確認
Firewall-cmdというファイアウォールが自動的に有効になっている場合があり、見落としがちです。

ポート80 (http) と 443 (https)を開けるには、下記のようにします。

[root@XXX ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 eth1
  sources:
  services: dhcpv6-client ssh
  ports: 10443/tcp 10080/tcp 10050/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

確認
firewall-cmd --list-all
追加
firewall-cmd --permanent --zone=public --add-service=http 
追加
firewall-cmd --permanent --zone=public --add-service=https
削除
firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client
再起動
firewall-cmd --reload
再確認
firewall-cmd --list-all

※参考URL
https://www.jdbc.tokyo/2014/10/centos7-firewalld-startup/

#selinux　無効にする
\# getenforce
Enforcing　⇒有効

「/etc/selinux/config」　修正して無効にする。
SELINUX=enforcing
↓変更
SELINUX=disabled
Centos7でのRailsのインストールと公開のための設定(nginx+unicorn)

# 概要
CentOS：7.3
Ruby：2.4.0
Rails：4.2.6
Git2.9.4

# Gitのインストール
参考サイト：http://www.task-notes.com/entry/20150622/1434942000

何はともあれGitがないと始まらないのでGitをインストールします。
幾つか方法があるのですが、今回はソースからGitをインストールします
基本的に最新版入れとけばいいと思います。
Gitのバージョンに関しては以下のURL参照
https://www.kernel.org/pub/software/scm/git/

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

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

### Gitダウンロード＆インストール

```
$ wget https://www.kernel.org/pub/software/scm/git/git-2.4.0.tar.gz
$ tar zxvf git-2.4.0.tar.gz
$ cd git-2.4.0
$ sudo make prefix=/usr/local all
$ sudo make prefix=/usr/local install
以下のコマンドを入力し、自分の指定したGitのバージョンが帰ってくればOK
$ git --version
git version 2.4.0
```

# Ruby,Rails,その他インストール
※詳しいコマンドやパッケージの内容については各自調べてください

```
$ sudo yum update
$ sudo yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison
rbenvをいれる
$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bashrc
$ exec $SHELL -l
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ cd ~/.rbenv/plugins/ruby-build
$ sudo ./install.sh
以下のコマンドが使えればOK。
$ rbenv install -l

Rubyのインストール
$ rbenv install 2.4.0; rbenv rehash
$ rbenv global 2.4.0


ちゃんと入ったか確認
$ ruby -v
ruby 2.4.0
$ which gem
~/.rbenv/shims/gem
$ which ruby
~/.rbenv/shims/ruby


bundlerをいれてRailsのインストールする
$ gem install bundler --no-rdoc --no-ri
Successfully installed bundler-1.10.6
$ rbenv rehash
$ gem install rails -v 4.2.6
$ rbenv rehash
$ rails -v
Rails 4.2.6
$ which rails
~/.rbenv/shims/rails
```

これで環境構築完了です
Railsアプリの作り方はいろんなやり方があるので各自調べてください

# NginxとUnicorn

基本的に下記のURL見て進めればOK(ちゃんと書く気力があればいずれ追記します)
http://qiita.com/noraworld/items/c8acf4bb981c8d8535df
ITエンジニアのための英語まとめ

#この記事について#
喋れない＆書けない私ですが、この業界では海外文献の調査は必須なので、苦しみつつまとめます。

#和英単語表

英単語で検索する。
日本語でググっても情報がどうしても出てこないというときに使える方法です。
適当に複数の単語で検索するだけでも日本語のWEBサイトでは存在しなかった情報が見つかったりします。


| 日本語       |       英語|       検索例|備考|
|:-----------------|:------------------|:------------------|:------------------|
|やり方|How to|-|||
|○○とは|what is|-|
|割り当てのやり方|How to assign|How to assign a static ip to a virtual machine||
|アクセスのやり方|How to access|-||
|取得の方法|how to get|-||
|セットアップ方法|How to setup|How to setup static ip address in virtual machine?||
|設定方法|How to Configure|-||
|仮想マシン|virtual machine|-||
|IPアドレス|ip address|-||
|静的|static||

#翻訳ツール#

[Google翻訳](https://translate.google.co.jp/?hl=ja)

検索したい日本語の単語を英語の単語に変換して使ったり、海外のWEBサイトのURLを直に貼って、日本語のページに変換したりと便利です。

[bing翻訳](http://www.bing.com/translator?from=&to=en&setlang=ja)

httpに限定されるようですが、翻訳前と翻訳後のページを2画面分割して表示してくれる便利機能があります。

#参考
[エンジニアが知っておくと便利なGoogle英語検索キーワード3選](http://tech.gmo-media.jp/post/115984168307/google-tips-english)
ELP Dual Lens Stereo Cameraでカメラが左右逆に認識される

下記ライブラリを用いて、ステレオカメラのキャリブレーションを行おうとしたところカメラが左右逆に認識されてしまったのでそれを直します。
https://github.com/joshvillbrandt/elp-stereo-camera-ros-pkg

初期状態で起動するとわかりづらいですが下図のように左右判定状態で反映されてしまいます。
![reverse.png](https://qiita-image-store.s3.amazonaws.com/0/185760/650b507c-69ed-1e4d-6ba3-6706b58da601.png)

カメラのデバイス認識等を行っているのはelp_stereo_camera.launchなので、下記のようにデバイスの認識を左右逆にしてあげます。

``` catkin_ws/src/elp_stereo_caemera/launch/elp_stereo_camera.launch
<?xml version="1.0"?>

<launch>
  <arg name="CAMERA_NAME" default="elp" />
  <arg name="LEFT_DEVICE" default="/dev/elp_right" />
  <arg name="RIGHT_DEVICE" default="/dev/elp_left" />

```

そうすると下図のように正しく左右が認識されるようになります。

![valid.png](https://qiita-image-store.s3.amazonaws.com/0/185760/220aac3a-964b-6130-7c67-548be2a4ca2a.png)

LEFT_DEVICEなのにelp_rightを認識させるようにしたり、スマートな方法ではないですが一応正しく認識されるようになりました。根本的な原因解決方法が見つかれば後々追記します。
Pythonのrandomモジュールで名前を並び替え


```py
# coding: utf-8
import random

nameList = []

print('リストを作ります。名前を入力してください。')
name = input('=>')
nameList.append(name)
print(name + 'を追加しました。')

print('今登録されている名前は' + '\n' +
str(nameList) + '\n' +
'です。')

answerWord = input('さらに名前を追加しますか? yes/no?: ')
while not(answerWord == 'no' or answerWord == 'n'):
    name = input('=>')
    nameList.append(name)
    print(name + 'を追加しました。')
    print('今のリストは' + '\n' +
    str(nameList) + '\n' +
    'です。')
    answerWord = input('さらに名前を追加しますか? yes/no?: ')

print('追加を終了します。')
print('シャッフルSTART!!')
random.shuffle(nameList)
print('順番は' + '\n' +
str(nameList) + '\n' +
'になりました。')
```
ChromebookでのプログラミングはGoogle Compute Engineが良さそう

## 始めに
Chromebook愛用者向けの記事です。

Chromebook大好き。WindowsよりもUbuntuよりもArchよりもMacよりも好き。
シンプルで使いやすくてすごくいい。

そう思ってやまないのですが、プログラミングに関しては色々と悩むことが多く困ってました。

## Chromebookのプログラミング環境について
とりあえず現状とりうる手段と感じたメリット、デメリットを挙げてみます。

* `Cloud9`等のクラウドIDEを使う
    * メリット：特にローカルにインストールはいらない。（Chromebookらしい！！）
    * デメリット；対応した言語以外を使うのがきつい。スペックが低い。スペック上げると案外値段が高い。

* `crouton`でローカルにUbuntuをインストール
    * メリット：Cloud IDEでは対応していないような言語にも対応できる（Elixirとか）
    * デメリット：ローカルの管理が面倒くさい。Ubuntuが起動しなくなることもある。本体であるChromeOSと別に設定しないといけない。ディスク領域が足りない。
    * 開発者モードでないとならない。（ブート時の開発者モードの表示が嫌だ。ChromebookはなるべくImmutableにしたい。）

* `chromebrew`でローカルにコマンドを色々インストール
    * メリット：ChromeOSのまま開発ができる。
    * 色々動かないものがある。動かすのに苦労するものもある。ディスク領域が足りない。
    * 開発者モードでないとならない。（ブート時の開発者モードの表示が嫌だ。ChromebookはなるべくImmutableにしたい。）

* `SecureShell`でVPS等につなげる
    * メリット：VPSなので、マシンの構成やスペック、インストールするものに関して自由にできる。
    * デメリット：SecureShellが使いづらい。暗号鍵の管理が面倒。

## それではGoogle Compute Engineはどうなの？
Chromebookでのプログラミングでとれる手段を色々挙げてみましたが、Google Compute Engineを使うとどうなるのか。
そもそもGoogle Compute Engine（以下GCE）は__IaaS__の一種です。（AWS EC2と同じ）
そのため、GCEを使用する方法は、上述の「SecureShellでVPS等に繋げる」の代替にあたります。
ただ、メリットを挙げると以下のものが挙げられます。

* 料金が安い。
    * 無料インスタンスもあるし、プリエンプティブVMが安い（https://cloud.google.com/preemptible-vms/?hl=ja）
    * プリエンプティブVMなら24時間でシャットダウンするので、うっかりマシンを起動しっぱなしというのも防げる。
    * 使わないときにマシンをシャットダウンしておけば安く済む。
* 接続がお手軽
    * ブラウザのGCE管理コンソールから、ボタンひとつで、SecureShellみたいなターミナルを開いてSSH接続できる。
    * ボタン一つでアクセスできるので、暗号鍵の管理に悩まずに住む
* ターミナルが使いやすい
    * SecureShellより設定が使いやすく感じた。
    * Ctrl + Wで単語を消そうとしてうっかりブラウザを閉じる問題も、Google公式で出しているChrome拡張を入れれば単語が消えるようになる。（設定に拡張へのリンクが載ってる）
* その他のGoogle Cloud Platformとかのサービスと連携できる
    * `gcloud`コマンドを打てる無料の専用VMが用意されている。それを使って`Google Cloud Storage`にアクセスできたりする。

## 結論
とりあえずCloud IDEで済む分にはそっちを使って、色々柔軟にやりたいときはGCEを使うようにしました。
実際に使用する際は用途ごとにマシンを作って、共通のdotfilesを`Cloud Source Repositories`（Google Cloud Platformにあるgitのプライベートリポジトリ）に入れて管理してます。
みんなGoogleで統一したいって気持ちもあるしね。

ただ、これだ！！と思って記事を書いてみたものの、まだあまり長く使ってないのでもう少し使い込んだら改めて記事にしようかなと思っています。
MacでバイナリパッケージからインストールしたGitを削除する方法

# MacでバイナリパッケージからインストールしたGitを削除する方法

* macOS Sierra
* Git 2.13.x (dmgパッケージからインストール)

アンインストールスクリプトがあるのでそれを実行するだけ。


```shell-session:アンインストールスクリプトの確認
$ ls -al /usr/local/git/uninstall.sh
-rwxr-xr-x  1 james  admin  718 May 11 10:31 /usr/local/git/uninstall.sh
```

### 削除スクリプト実行

```shell-session
$ sudo /usr/local/git/uninstall.sh
Password: 
This will uninstall git by removing /usr/local/git/, and symlinks
Type 'yes' if you are sure you wish to continue: yes
Forgot package 'com.git.pkg' on '/'.
Uninstalled
```

### 動機

なんかもういい加減Homebrewで管理すりゃいいよねと。
メモ: Almin.jsのCounterサンプルプログラムをTypeScriptに変更したときにやったこと

# 概要

[Almin.js](https://github.com/almin/almin) の [Counterサンプルプログラム](https://github.com/almin/almin/tree/master/examples/counter) を、コンパイラをtypescript に変更したときにやったことです。


# 修正後
修正後のソース https://github.com/kmdsbng/almin_counter_example
差分 https://github.com/kmdsbng/almin_counter_example/commit/fefd48ca89c1aadc44466963ec36b87375bbb3da

# ビルド方法

* webpack dev server起動 : yarn start
* テスト実行 : yarn test

# 修正後の構成

* タスクランナー : webpack
* コンパイラ : typescript
* テストフレームワーク : mocha


# バージョン
* "almin": "^0.12.1",
* "typescript": "^2.4.1",

# 修正点

* ライブラリを追加
  * yarn add typescript ts-node awesome-typescript-loader source-map-loader --dev
  * yarn add @types/mocha @types/node @types/react @types/react-dom

* tsconfig.json を追加
  * "noImplicitAny": false
  * "allowJs": true

* ビルド時にエラーを起こすライブラリを削除
  * "babel-preset-jsdoc-to-assert"削除
  * "babel-preset-power-assert"削除
  * "babel-preset-react"削除
  * "babel-register"削除


* webpack.config.js修正

```js
+    devtool: "source-map",
+    resolve: {
+        // Add '.ts' and '.tsx' as resolvable extensions.
+        extensions: [".ts", ".tsx", ".js", ".json"]
+    },

+            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
+            { test: /\.tsx?$/, loader: "awesome-typescript-loader" },
+
+            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
+            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
```



* react のimport行でエラーが起こったので修正

  * 修正前

```js
import React from "react";
import ReactDom from "react-dom";
```

  * 修正後

```ts
import * as React from "react";
import * as ReactDom from "react-dom";
```



* propTypesを使わず、interfaceを使うように修正
  * Alminの内部で使われてるStateMapというinterface定義をコピーしてくる必要があった。

```ts
// copy from almin/UILayer/StoreGroupTypes"
declare type StateMap<T> = {
    [P in keyof T]: T[P];
};

export interface CounterComponentProps {
  appContext: Context<StateMap<{ "counter": any; }>>;
  counterState: CounterState;
};

export default class CounterComponent extends React.Component<CounterComponentProps, undefined> {
  ...
```
ConcfgでPowershellをモダンでオシャレにしたかった

## 動機

以下の記事に触発されて、レジストリの手動書き換えなしで、PowerShellをかっこよくしたかった。（自動では書き換える）
> [追加インストールなしでpowershellのカスタマイズ](http://qiita.com/k_takashi0309/items/55a35b72bcbd19a3a82d)

## 手順

以下の記事を参考にした。
> [Theming Powershell](https://github.com/lukesampson/scoop/wiki/Theming-Powershell)

1. PowerShellにPS1ファイルの実行権限を与える
2. [scoop](https://github.com/lukesampson/scoop)をインストール
3. [concfg](https://github.com/lukesampson/concfg)をインストール
4. concfgでMonokaiテーマをインストール（ここでレジストリを書き換えている）

```PowerShell
# PowerShellにPS1ファイルの実行権限を与える
$ set-executionpolicy remotesigned -s cu

# scoopをインストール
$ iex (new-object net.webclient).downloadstring('https://get.scoop.sh')

# concfgをインストール
$ scoop install concfg

# concfgでMonokaiテーマをインストール（ここでレジストリを書き換えている）
$ concfg import monokai

# レジストリを書き換える旨のメッセージが出るので「Y」を押す
# 反映後の画面を新しい画面で表示するか聞かれるので「Y」を押す
```

## 結果
なんか色合いがコレジャナイ気がする……
![2.png](https://qiita-image-store.s3.amazonaws.com/0/55873/5cd9c681-0867-1d2f-4fb0-e433a9fca508.png)

## もうちょっとだけやってみた
Solarizedを入れてみた。（こっちのほうが良さそう）

```PowerShell
$ concfg import solarized
```

![1.png](https://qiita-image-store.s3.amazonaws.com/0/55873/f46eee69-53aa-e46d-ee0c-5fd56ef03bfb.png)

## やっぱり元に戻そう
これで元に戻ります。

```PowerShell
$ concfg import defaults
```

## 結論
個人的にBashとかよりPowerShellの方がスクリプトを書きやすいけど、
tmuxとか使えない分、普段使いにはBashとかの方が良さそう。

まぁ、Windowsのシェル生活は、基本的にmsys2かcmderを使えばいいのではないかな。
Mojoliciousインストール　メモ

Perl WEBアプリケーションフレームワークMojoliciousインストールのメモです。
windows上でvagrantにてcentos7を立ててそこにインストールします。

# Mojoliciousテスト環境構築 #

## 設定 ##
 * HostOS: windows10
  * vagrant
  * virtualbox

 * GuestOS: CentOS7
  * perlbrew
  * cpanm
  * Perl 5.20.3
  * mojolicious

#### 備考 
 * Windowsではvagrantでcentos7を入れる場合、C:\Users\[username]\.vagrant.d\boxes\centos-VAGRANTSLASH-7\XXXX\virtualbox
Vagrantfile
で

```
  config.vm.synced_folder ".", "/home/vagrant/sync", type: "rsync"
```

をコメントアウトする必要があるかもしれない。

 * mojoliciousはperl5.20以上だと、同梱ライブラリで動作するとのことなので
5.20.3を選択している。

## 以下、手順 ##
windows上で以下を実行
```
mkdir mojotest && cd mojotest
vagrant init centos/7
```
次のようにファイルを編集、作成する。（Vagrantfile, provison.sh）
Vagrantfile

```
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
  config.vm.box = "centos/7"
  config.vm.network "private_network", ip: "192.168.33.20"
  config.vm.synced_folder ".", "/home/vagrant/sync" ,disabled: true
  config.vm.provision "shell", :path => "provision.sh", privileged: false
end
```
provision.sh

```
#!/usr/bin/env bash

PERL_INSTALL_VERSION='perl-5.20.3'
echo "**exec user:"
whoami
################################################
echo "**yum install"

sudo yum -y install perl vim gcc  git
sudo yum install -y -q ntp
sudo systemctl start  ntpd
sudo systemctl enable ntpd
sudo timedatectl set-timezone Asia/Tokyo

# centos7
sudo sed -i -e 's/^PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config
sudo systemctl restart sshd
sudo sed -i -e 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config

sudo systemctl disable firewalld
sudo systemctl stop firewalld
sudo systemctl disable NetworkManager
sudo systemctl stop NetworkManager
sudo systemctl enable network
sudo systemctl start network
################################################
echo "**perlbrew"
cd ~
export PERLBREW_ROOT=$HOME/.perlbrew
#if [[ ! -d $HOME/.perlbrew ]]; then
  curl -L http://xrl.us/perlbrewinstall --insecure | bash
  ~/.perlbrew/bin/perlbrew init
  echo 'source ~/.perlbrew/etc/bashrc' >> ~/.bashrc
  source ~/.bashrc
#fi
perlbrew install -v $PERL_INSTALL_VERSION -D ccflags=-fPIC
perlbrew list
perlbrew switch $PERL_INSTALL_VERSION
perlbrew   install-cpanm    
cpanm Mojolicious
mojo version

echo "**End"
```
 * 次を実行して待つ
 
```
vagrant up
```

 * テストアプリ
  * できたらゲストOSのcentos7にSSHログインして以下を実行。

```
cd ~
mkdir ~/mojo_welcome; cd ~/mojo_welcome
mojo generate lite_app
morbo myapp.pl
```

  * WEBブラウザで以下にアクセス。画面が表示されていたら成功。
     * http://192.168.33.20:3000
結城 浩『数学ガールの秘密ノート/やさしい統計』勉強メモ

#### 参考文献
1) 結城 浩『[数学ガールの秘密ノート/やさしい統計](http://amzn.to/2t1kwCL)』　SBクリエイティブ、2016年。
# 代表値

最大値、最小値、平均 $μ$、最頻値、中央値
***
(pp.86-87)
偏差の2乗平均を分散 $V$ ("Variance") という

(p.109)
**《分散 $V$》=《[$n$ 個の数値の]2乗の平均》-《平均の2乗》**

(p.121)
標準偏差 $σ$
分散の平方根のうち、負でないほう 
すなわち、分散を $V$ とし、標準偏差 $σ$ とすると
$$ σ = \sqrt{V}$$
である。

(p.138)
正規分布のグラフを平均 $μ$ から、標準偏差 $σ$ ごとに区切ると、
おおよそ $34\%, 14\%, 2\%$ という割合が現れる。

(p.151)
平均 $μ$ は期待値 $μ$ と同じと考えていいが、期待値という言葉は **確率変数** に対して使う。
確率変数とは試行[コインを投げるような行為]を行うたびに、具体的な値が決まるもののこと

(p.168)
**《分散 $V$》=《[$n$ 個の数値の]2乗の期待値》-《期待値の2乗》**

(p.174) 
分散や標準偏差は驚きの度合いを表す  
(p.184)
事象("event")より細かく分割できない事象を **根元事象** と呼ぶ。
そして、根元事象に対して値が定まる変数を **確率変数** という。
《コインを1回投げる》という試行の場合、《表が出る》と《裏が出る》という2種類の根元事象がある。

(p.185)

| 《コインを1回投げる》根元事象 |《表が出る回数》を表す確率変数 $X$ の値|
|:-:|:-:|
|《表が出る回数》|$1$|
|《裏が出る回数》|$0$|

(確率変数 $X$ は確率分布をグラフにした際に横軸($x$軸)になるから $X$ )

この表はこう書くことも出来る

```math
\begin{eqnarray}
  \left\{
    \begin{array}{l}
      X (《表が出る回数》)   = 1 \\
      X (《裏が出る回数》)   = 0 \\
    \end{array}
  \right.
  \tag{1}
\end{eqnarray}
```
ゆえに、確率変数は《根元事象に対して値が定まる関数》ともいえる。

確率変数 $X$ が取る平均的な値を、その確率変数 $X$ の **期待値** と呼び、
$$ E[X] $$
と表す。"E"は《期待値》"Expected Value" の頭文字

(p.186) 
確率変数 $X$ の期待値 $E[X]$ を、  
$$E[X]=\sum k\cdot \Pr \left( X=k\right)  $$
で定義する。ただし、$\sum$ は確率変数 $X$ が取りうるすべての値 $k$ についての和を取ることにする。
$\Pr \left( X=k\right)$ は、《確率変数 $X$ の値が $k$ に等しくなる確率》を表している。 
$\Pr$ は《確率》"Probability" の頭文字

(p.187)
期待値は確率変数の平均なので、$μ$ と書くこともある。 
しかし、$E[X]$ のように書けば、確率変数 $X$ の期待値であることがはっきりわかる。

《コインを1回投げる》という試行で、《表が出る回数》を表す確率変数を $X$ とすると、$X$ の期待値は、

$$
\begin{eqnarray}
E[X] &=& \sum_{k=0}^{1}k\cdot \Pr \left( X=k\right)\\
     &=& 0\cdot \Pr \left( X=0\right) + 1\cdot \Pr \left( X=1\right)
\end{eqnarray}
$$
で得られる。

$(1)$ より、$\Pr \left( X=1\right)$ は表が出る確率、 $\Pr \left( X=0\right)$ は裏が出る確率  

(p.194)
# 二項分布
確率分布の一種 確率 $p$ で表が出るコインを $n$ 回投げたときに、《表が出る回数》を表す確率変数が従う確率分布 毎回のコイン投げは独立とする

$B(n, p)$

# 一様分布
どの根元事象も同じ確率で起きる

(p.198)
# 正規分布
二項分布の $n$ を大きくしていき、$n\rightarrow \infty$ の極限を取る。
様々な現象の統計量か正規分布で近似できる。単純な数理モデルの1つ。

(p.199)
二項分布は離散的な確率分布なので、確率は総和 ($\sum$)で得られる。
正規分布は連続な確率分布なので、縦軸は確率密度になり、確率は積分 ($\int$)の計算で得られる。

(p.201)
> 物理的な性質や、社会的な現象に対して、数学が直接的な証明を与えることはない。
数学はただ、数理モデルをどう扱うべきかを教えてくれるだけだ。

***
(p.214)
#チェビシェフの不等式
いかなる分布でも、
$$μ-Kσ \lt x \lt μ+Kσ$$
を **満たさない** 数値 $x$ の割合は、$\frac{1}{K^{2}}$ 以下である。  
ただし $μ$ は平均、 $σ$ は標準偏差、$K$ は正の定数である。
***
(p.218)  
[チェビシェフの不等式について]正規分布を仮定できる場合、$|x-μ|\geqq 2σ$ を満たす人数は約 $4\%$ といえる。  
しかし、分布がまったくわからない場合でも、平均と標準偏差がわかれば、$|x-μ|\geqq Kσ$ を満たす人数の割合は $\frac{1}{K^{2}}$ 以下であると保証できる。

(p.236)
# 二項分布の期待値・分散・標準偏差

```math
\begin{eqnarray}
  \left\{
    \begin{array}{l}
      期待値 = np \\
      分散 = np(1-p) \\
      標準偏差 = \sqrt{np(1-p)} \\
    \end{array}
  \right.
\end{eqnarray}
```

(cf.p.182)
cURLでRedisの動作確認

最近はサーバにtelnetクライアントが入っていないけど、curlは標準で入ってるんですね。ってことで、こんな感じでredisの動作確認ができます。

# 例
```
bash$ curl -s telnet://redis.da.yo:6379
set ugokukana ugoitayo
+OK
get ugokukana
$9
ugoitayo
quit
+OK

bash$ 
```

# 例）docker内のredisにも

こんな感じでたたけるよっ

```
bash$ docker-compose exec web bash -c "curl telnet://redis:6379"
flushall
+OK
quit
+OK

bash$ 
```

# おわりに
redis-cliがなくてもあわてなくて済むね