OmniAICreator/Qiita-1.07M huggingface dataset:
Javascriptで花火地図

## 花火地図
７月・８月に日本で花火大会がいっぱいあります。
花火大会の場所と時間を簡単に検索できるようにウェブサイトを作りました。
[hanabimap](http://hanabimap.info/)と言う名前です。
URL：
http://hanabimap.info

### フロントエンド
  * Vue.js (javascript)
  * webpack + es6

### バックエンド
  * Django (python)

### Github.com
https://github.com/phocode/fireworkmap
Pythonで顔検出まとめ

# 顔検出まとめ

Pythonでライブラリ（OpenCV・dlib）を使って顔検出を行ったまとめ
ちなみに

- 顔検出（face detection）…画像や映像から顔が写っている部分を推定すること
- 顔認識（face recognition）…画像や映像に映った顔が誰なのかを推定すること

顔検出に使っているのは、OpenCVがHaar-Like+Adaboost、dlibがHoG+SVMらしい

[OpenCVとDlibとOpenFaceで顔検出をした知見まとめ](http://vaaaaaanquish.hatenablog.com/entry/2016/06/28/004811)

概要は以下を読めば感覚的にはわかると思う

[局所特徴量と統計学習手法による物体検出](http://www.vision.cs.chubu.ac.jp/cvtutorial/pdf/03objectdetection.pdf)

ディープラーニングを使った最近の手法は以下

[Faster R-CNNの紹介](http://kivantium.hateblo.jp/entry/2015/12/25/112145)

[論文紹介: Fast R-CNN&Faster R-CNN](http://www.slideshare.net/takashiabe338/fast-rcnnfaster-rcnn)

## OpenCV

[Python+OpenCVで顔検出](http://qiita.com/shngt/items/a4cc822ef1a095136302)

[Python+OpenCVで顔検出器の性能比較](http://qiita.com/shngt/items/30548bec009432b95438)

[Python+OpenCVで顔検出（回転不変）](http://qiita.com/shngt/items/0bf59d813dc15578f1a6)

[アフィン変換後の座標から元の画像での位置を求める（Python + OpenCV）](http://qiita.com/shngt/items/78c75b79a70ed0dfcd93)

## dlib

[Python + dlibで顔検出](http://qiita.com/shngt/items/64ff4130f377ddca5973)
Python + dlibで顔検出

# Python + dlibで顔検出

## インストール

dlibを入れる前にCMAKE、Boost、Boost Python、G++他いろいろ必要

[UbuntuでOpenCVとdlibを導入](http://qiita.com/nanto710/items/aac934896d40c6b8cf0b)

[dlibを用いたselective search](http://kivantium.hateblo.jp/entry/2015/07/25/184346)

画像ファイルの入出力にOpenCV・scikit-imageあたりを入れる
今回はOpenCVを利用

## コード

dlibでは顔っぽさのスコアを出せる
多少傾いていても検出してくれる感じがするので、回転させながら検出する場合でも回転角は45度ずつくらいでいいかもしれない
ある程度低いスコア（CUT_OFFの値）でスクリーニングをかけて、絞り込んだエリアを回転させながらスコアが高くなるように角度を調整してもいいかもしれないと思って試したけど、時間がかかりすぎる
検出結果に出てくるtypeは検出器の種類（顔が正面か横向きかとか？）に対応しているらしい
コメントアウトしたところは、検出した顔から68の特徴点を取り出してくれる
どの点が目・鼻・輪郭に対応しているとかわかるなら、もう少し改良できそう

```python:detect_face.py
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os, sys, imghdr, shutil, dlib, cv2

CWD = os.getcwd()
DIR_ORIGIN = CWD + '/images/'
DIR_DESTINATION = CWD + '/faces/'
CUT_OFF = -0.1

detector = dlib.get_frontal_face_detector()
# predictor = dlib.shape_predictor('./shape_predictor_68_face_landmarks.dat')

def getFaces(path_full):
    results = []
    image = cv2.imread(path_full)
    height, width = image.shape[:2]
    rects, scores, types = detector.run(image, 1, CUT_OFF)
    for i, rect in enumerate(rects):
        top, bottom, left, right = rect.top(), rect.bottom(), rect.left(), rect.right()
        if min(top, height - bottom - 1, left, width - right - 1) < 0:
            continue
        results.append({
            'image'       : image[top : bottom, left : right],
            'score'       : scores[i],
            'orientation' : types[i]
        })
        # shape = predictor(image, rect)
        # for i in range(shape.num_parts):
        #     print(shape.part(i))
    return results

count = 1
for path, subdirs, files in os.walk(DIR_ORIGIN):
    for name in files:
            path_full = os.path.join(path, name)
            if imghdr.what(path_full) in ['jpeg']:
                faces = getFaces(path_full)
                for face in faces:
                    file_name = '{destination_dir}/{score}_{type}_{count}_dlib.jpg'.format(
                        destination_dir = DIR_DESTINATION,
                        score = face['score'],
                        type = int(face['orientation']),
                        count = count
                    )
                    cv2.imwrite(file_name, face['image'], [cv2.IMWRITE_JPEG_QUALITY, 100])
                    count += 1
                print(path_full)
```

## 参考サイト

[chainerによるディープラーニングでAV女優の類似画像検索サービスをつくったノウハウを公開する](http://qiita.com/xolmon/items/0b82f4861cf93fd28e33)

[OpenCVとdlibを連携した顔検出プログラム](http://kivantium.hateblo.jp/entry/2015/04/05/223841)

[機械学習のライブラリ dlib](http://qiita.com/nonbiri15/items/9561c8194ba0b2041bd0)

[OpenFace 0.2.0: Higher accuracy and halved execution time](https://bamos.github.io/2016/01/19/openface-0.2.0/)

[OpenCVとDlibとOpenFaceで顔検出をした知見まとめ](http://vaaaaaanquish.hatenablog.com/entry/2016/06/28/004811)

[機械学習で用いる顔画像データセットの一作り方（３：候補画像から顔画像生成その１）](http://qiita.com/ligerbolt/items/2bfb28b5cd1eaf0fa816)
アフィン変換後の座標から元の画像での位置を求める（Python + OpenCV）

# アフィン変換後の座標から元の画像での位置を求める

アフィン変換（cv2.warpAffine）後に切り出した画像が元の画像に収まっているか調べたい。
切り出した画像の四隅の座標が、元の画像の中にあればいいはず

## 考え方

warpAffineに渡したマトリクスを見てみると(2×3)の行列になっている
これに[0, 0, 1]の行を加え~~て、転置す~~れば最初に使用した回転行列が得られそう
アフィン変換後の座標を(x, y)とすると、~~[x, y, 1]に回転行列の逆行列をかける~~回転行列の逆行列に[[x], [y], [1]]（3×1）をかけると元の座標が得られる気がする
OpenCVに対応するメソッドがあるんじゃないかとは思うが、~~探すのが面倒くさい~~どれを使えばいいのか、どう使えばいいのかわからない

## コード

```python:inverseWarpAffine.py
import cv2
import numpy as np

def getOriginalPosition(p, M):
  origin = np.array([[p.x], [p.y], [1]])
  rotateM = np.array([M[0], M[1], [0, 0, 1]])
  invM = np.linalg.inv(rotateM.T)
  return np.dot(invM, origin)[:2, 0]
```
Python+OpenCVで顔検出（回転不変）

# Python+OpenCVで顔検出（回転不変）

画像を回転させながら顔検出
一番いい角度の調整等は行っていない
必要なら以下を参考に

[Heroku + OpenCVで簡易顔検出API](http://memo.sugyan.com/entry/20151203/1449137219)

[Face Detection using Haar Cascades](http://docs.opencv.org/3.0.0/d7/d8b/tutorial_py_face_detection.html)

入力画像ではなく、フィルタのほうを回転させて自動で検出してほしい……

## はまりポイント

画像処理に慣れている人なら当たり前なのかもしれないが、ほとんどやったことがないので結構はまった

画像の高さや幅を取得・指定するときに順番が違うことがある

- shape…高さ（rows）、幅（columns）
- インデックスでスライス…[高さ下限（y） : 高さ上限（y+h）, 幅下限（x） : 幅上限（x+w）]
- OpenCVの座標指定（中心点とか）…（横（x）, 縦（y））

ディスプレイの座標系はy軸が下方向なのに角度は反時計回りなので、普通のy軸が上方向の座標系に変換すると時計回りに回っている

## コード

```python:face_rotate_detect.py
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import cv2, os, sys, imghdr, shutil, math
import numpy as np

CWD = os.getcwd()
DIR_ORIGIN = CWD + '/images/'
DIR_DESTINATION = CWD + '/faces/'

classifier = cv2.CascadeClassifier('{python_dir}/{classifier_dir}/haarcascade_frontalface_alt2.xml'.format(
    python_dir = os.path.split(sys.executable)[0],
    classifier_dir = '../share/OpenCV/haarcascades',
))

def getFaces(path_full):
    results = []
    image = cv2.imread(path_full)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    rows, cols, colors = image.shape
    center = tuple(np.array([cols, rows]))
    # get rotations
    for angle in range(-90, 91, 5):
        radian = np.deg2rad(angle)
        output_height = int(np.absolute(cols * np.sin(radian)) + np.absolute(rows * np.cos(radian)))
        output_width = int(np.absolute(cols * np.cos(radian)) + np.absolute(rows * np.sin(radian)))
        output_size = tuple(np.array([output_width, output_height]))
        # rotate
        Matrix = cv2.getRotationMatrix2D(center, degree, 1.0)
        # translate
        Matrix[0, 2] += (output_width - width) * 0.5
        Matrix[1, 2] += (output_height - height) * 0.5
        # warp affine
        rotated = cv2.warpAffine(gray, Matrix, output_size, flags = cv2.INTER_LINEAR)
        # detect faces
        faces = classifier.detectMultiScale(rotated)
        if len(faces):
            rotated_color = cv2.warpAffine(image, Matrix, output_size, flags = cv2.INTER_LINEAR)
            for x, y, w, h in faces:
                results.append(rotated_color[y : y + h, x : x + w])
    return results

def saveFaces(faces):
    global count

    for face in faces:
        cv2.imwrite(
            '{dir_destination}{count}.jpg'.format(dir_destination = DIR_DESTINATION, count = count),
            face,
            [cv2.IMWRITE_JPEG_QUALITY, 100]
        )
        count += 1

count = 1
for path, subdirs, files in os.walk(DIR_ORIGIN):
    for name in files:
        path_full = os.path.join(path, name)
        if imghdr.what(path_full) in ['jpeg']:
            saveFaces(getFaces(path_full))
            print(path_full)
```
Python+OpenCVで顔検出器の性能比較

# Python+OpenCVで顔検出器の性能比較

どれが一番目的に合っているのか調べるため比べやすいように出力してみた

## コード

```python:face_detector.py
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import cv2, os, sys, imghdr

CLASSIFIER_DIR = '/usr/local/share/OpenCV/haarcascades'
CLASSIFIER_LIST = [
    'haarcascade_eye_tree_eyeglasses',
    'haarcascade_eye',
    'haarcascade_frontalface_alt_tree',
    'haarcascade_frontalface_alt',
    'haarcascade_frontalface_alt2',
    'haarcascade_frontalface_default',
    'haarcascade_lefteye_2splits',
    'haarcascade_profileface',
    'haarcascade_righteye_2splits',
    'haarcascade_smile'
]
CLASSIFIERS = {}
for name in CLASSIFIER_LIST:
    CLASSIFIERS[name] = cv2.CascadeClassifier('{classifier_dir}/{classifier}.xml'.format(
        classifier_dir = CLASSIFIER_DIR,
        classifier = name
    ))
CWD = os.getcwd()
DIR_ORIGIN = CWD + '/images/'
DIR_DESTINATION = CWD + '/faces/'

def getFaces(path_full):
    results = {}
    original_image = cv2.imread(path_full)
    gray = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
    for label, classifier in CLASSIFIERS.items():
        image = original_image.copy()
        faces = classifier.detectMultiScale(gray)
        for i in range(len(faces)):
            x, y , w, h = faces[i]
            image = cv2.rectangle(image, (x, y), (x + w, y + h), (255, 255, 255), 2)
        results[label] = image
    return results

count = 1
for path, subdirs, files in os.walk(DIR_ORIGIN):
    for name in files:
        path_full = os.path.join(path, name)
        if imghdr.what(path_full) in ['jpeg']:
            faces = getFaces(path_full)
            for classifier, face in faces.items():
                file_name = '{destination_dir}/{count}_OpenCV_{classifier}.jpg'.format(
                    destination_dir = DIR_DESTINATION,
                    count = count,
                    classifier = classifier
                )
                cv2.imwrite(file_name, face, [cv2.IMWRITE_JPEG_QUALITY, 100])
            print(path_full)
            count += 1
```

## 参考サイト

[OpenCV 使用可能なCascadeClassifierの種類と効果](http://symfoware.blog68.fc2.com/blog-entry-1556.html)

[python+OpenCVで顔認識をやってみる](http://qiita.com/wwacky/items/98d8be2844fa1b778323)

[A face-detection script in Python](https://gist.github.com/dannguyen/cfa2fb49b28c82a1068f)
Python+OpenCVで顔検出

# Python+OpenCVで顔検出

## インストール

少し面倒なので、以下あたりを参考に

[Install OpenCV 3.0 and Python 2.7+ on Ubuntu](http://www.pyimagesearch.com/2015/06/22/install-opencv-3-0-and-python-2-7-on-ubuntu/)

[Install OpenCV 3.0 and Python 2.7+ on OSX](http://www.pyimagesearch.com/2015/06/15/install-opencv-3-0-and-python-2-7-on-osx/)

[MacでOpenCVとpythonを使う](http://pc.atsuhiro-me.net/entry/2015/11/25/023000)

[Python 環境のインストール](http://www.habe-lab.org/public_wiki/doku.php/python:install)

## コード

分類器のある場所は環境に合わせて変更
`which python`
とか
`which python3`
でpythonの場所を調べたら、インストールされていればその周辺にあるのではないかと

```python:detect_face.py
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import cv2, os, sys, imghdr, shutil

CLASSIFIERS = (
    'haarcascade_frontalcatface_extended.xml',
    'haarcascade_frontalcatface.xml',
    'haarcascade_frontalface_alt_tree.xml',
    'haarcascade_frontalface_alt.xml',
    'haarcascade_frontalface_alt2.xml',
    'haarcascade_frontalface_default.xml',
)
PATH_CLASSIFIER = '{python_dir}/{classifier_dir}/{classifier}'.format(
    python_dir = os.path.split(sys.executable)[0],
    classifier_dir = '../share/OpenCV/haarcascades',
    classifier = CLASSIFIERS[4]
)
CWD = os.getcwd()
DIR_ORIGIN = CWD + '/images/'
DIR_DONE = CWD + '/done/'
DIR_NONE = CWD + '/none/'
DIR_DESTINATION = CWD + '/faces/'

classifier = cv2.CascadeClassifier(PATH_CLASSIFIER)

def mkdir(path):
    dirs = path.split('/')
    current = ''
    for d in dirs:
        current += d + '/'
        if not os.path.exists(current):
            os.mkdir(current)

def moveFile(origin_path, dest_dir):
    mkdir(dest_dir)
    shutil.move(origin_path, dest_dir)

def getFaces(path_full):
    image = cv2.imread(path_full)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    faces = classifier.detectMultiScale(gray)
    path, name = os.path.split(path_full)
    path_destination = path.replace(DIR_ORIGIN, DIR_DESTINATION)
    dir_done = path.replace(DIR_ORIGIN, DIR_DONE)
    dir_none = path.replace(DIR_ORIGIN, DIR_NONE)
    base_name = os.path.join(path_destination, name[:name.rfind('.')])
    count = len(faces)
    for i in range(count):
        x, y , w, h = faces[i]
        crop = image[y : y + h, x : x + w]
        file_name = base_name
        file_name += ('_' + str(i + 1)) if count > 1 else ''
        file_name += '.jpg'
        mkdir(path_destination)
        cv2.imwrite(file_name, crop, [cv2.IMWRITE_JPEG_QUALITY, 100])
    if count:
        moveFile(path_full, dir_done)
    else:
        moveFile(path_full, dir_none)
    return count

def isEmpty(dir_):
    return True if not os.listdir(dir_) else False

count = 0
for path, subdirs, files in os.walk(DIR_ORIGIN):
    for name in files:
        path_full = os.path.join(path, name)
        if imghdr.what(path_full) in ['jpeg']:
            count = getFaces(path_full)
    if count:
        if isEmpty(path):
            os.rmdir(path)
        count = 0
```
apt-get installでDEBIAN_FRONTEND=noninteractiveが効かない

## 問題

たとえば以下のようなスクリプトがあったとします。

```bash
export DEBIAN_FRONTEND=noninteractive
sudo apt-get update
sudo apt-get install -y -qq keyboard-configuration
```

TravisやDockerなど画面のないPCでは`apt-get`を使ったアプリのインストール中に起こるインタラクティブな操作をしたくないので、`DEBIAN_FRONTEND=noninteractive`という環境変数を入れることで無効にしていました。

ところが、このコードはubuntuのTrusty (14.04)までは正常に動きますが、ふとXenial (16.04)で試したところ、途中でインタラクティブに操作を求められ、Travisなどキー入力不可の環境で先に進まなくなってしまいます。

## 原因

sudoでroot権限へ昇格するときに環境変数が引き継がれていないのが原因。

Xenialで`man sudo`をすると、

> -E The -E (preserve environment) option will override the env_reset option in sudoers(5)). It is only available when either the matching command has the SETENV tag or the setenv option is set in sudoers(5).

とあります。
このオプションはTrusty以前からもあり、これを指定せずともなんとなく環境変数は引き継がれていた(`PATH`とかは従来でも引き継がれない)はずですが、どうやらXenialからは`sudo -E`を明示的に指定しないと環境変数が引き継がれなくなったようです。

## 解決

```bash
export DEBIAN_FRONTEND=noninteractive
sudo -E apt-get update
sudo -E apt-get install -y -qq keyboard-configuration
```
[Excel VBA]2 次元でキー割れしないといけなくなった

[ブログからの転載](http://1bed.allright.life/?p=2177)

2 次元でキー割れという表現が正しいかどうかはチョット判らないが、列ごとにデータを追加していって、キー割れが行われるとその行の次の行がスタートとなってまた列にデータを追加していくという処理が必要になったので、自宅で先に素振りしたメモ。

# 仕様

* 1 ～ 10 の乱数を作成し、それを A 列～ J 列とする
* 乱数に沿ったセルを着色する
* 既に着色済みの時は、その次の行のセルを着色する
* A 列～ J 列のいずれかが 5 で割り切れる行に到達したら、その次の行をスタートラインとして全列スタートする
* 上記の処理を繰り返す

# 結果

![GIF.gif](https://qiita-image-store.s3.amazonaws.com/0/118961/0f9ea4cd-566c-55f5-ff01-7fe9efe638e9.gif)

# コード

```vbnet
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Public Sub RamdomStack()
    Dim ViewSheet As Worksheet
    Set ViewSheet = ThisWorkbook.Worksheets("Sheet1")

    ' Adjst
    With ViewSheet.Cells.Columns
        .Clear
        .ColumnWidth = 3
        .Font.Size = 8
        .HorizontalAlignment = xlCenter
    End With

    Dim Row As Long
    Dim Column As Integer
    Dim BreakPoint As Integer: BreakPoint = 1
    Const BreakCount As Integer = 5

    For i = 0 To 120
        Column = Int(Rnd * 10) + 1

        Row = BreakPoint
        If ViewSheet.Cells(Row, Column).Value <> "" Then
            Row = ViewSheet.Cells(Rows.Count, Column).End(xlUp).Row
            If ViewSheet.Cells(Row, Column).Value <> "" Then
                Row = Row + 1
            End If
        End If

        ' Decoration
        With ViewSheet.Cells(Row, Column)
            .Value = " "
            .Interior.Color = RGB(255, 200, 0)
        End With

        If (Row Mod BreakCount) = 0 And (Row + 1) >= BreakPoint Then
            BreakPoint = BreakPoint + BreakCount
        End If

        Call Sleep(300)
    Next

    Set ViewSheet = Nothing
End Sub
```
Raspberry PiをUART通信で操作する

#環境
RaspberryPi2 Raspbian Jessie
MacOS X El Capitan 10.11.5

#USB/TTLシリアル変換ケーブル
ものは色々ありますが、僕はAmazonで売ってたこいつを買いました

Raspberry Pi ラズベリーパイ用の USB－TTLシリアルコンソールのUSB変換COMケーブルモジュールのケーブル
http://amzn.to/29KnE2n

#ドライバのインストール
http://www.prolific.com.tw/us/showproduct.aspx?p_id=229&pcid=41
上のリンクからMacにドライバをダウンロードし、インストールした後に再起動する

#ラズパイのGPIOに接続
ケーブルの4色のメス型のピンを、ラズパイのGPIOに差し込んで接続する。
ケーブルのピンとGPIOのポートの対応は以下の通り

赤 -> 4番(5V PWR)
黒 -> 6番(GND)
白 -> 8番(UART0 TX)
緑 -> 10番(UART0 RX)

RaspberryPi 2のGPIOポートは以下の図を参考に
![RP2_Pinout.png](https://qiita-image-store.s3.amazonaws.com/0/42913/a6c3343e-588d-d48f-fceb-13968a6cf4a9.png)

#Terminalで接続
USBケーブルをMacに接続。
Macのターミナルで
`$ls /dev/tty.*`
を入力し、接続しているデバイスのシリアル名を確認する。

今回、「tty.usbserial」だったので、
`$screen /dev/tty.usbserial 115200`
を入力する。

ターミナルの画面が固まるが、一度returnキーを押すとログインできるようになる。

ちなみに、GPIOから電源の供給がされるのでmicroUSBの接続は不要です~~が、安定して動作をさせるため接続しておいた方がいいかもしれません。(このへんよどっちがいいかよくわからない)~~


#「Sorry, could not find a PTY」のエラーが出る場合
ドライバもちゃんと入れて上記の操作を行ってもエラーが出るとき
TTLシリアル変換ケーブルをMacから抜き差しすると直る場合があります
TWE-Lite-2525A 無線タグアプリの設定手順

定期的に加速度を取得したい場合の設定手順です。
おおまかには、
１．子機の設定
２．親機の設定
があり、子機を設定する際に、親機に子機設定書換用ファームウェアを入れて使います。

#使用するデバイス
- 親機 [TWE-Lite-USB(ToCoStick)](http://mono-wireless.com/jp/products/TWE-Lite-USB/)
- 子機 [TWE-Lite-2525A.2](https://mono-wireless.com/jp/products/TWE-Lite-2525A/index.html)

#ファームウェアをダウンロード
[Samp_Monitor](http://mono-wireless.com/jp/products/TWE-Lite-2525A/firmware_update.html) (Ver. 1.6.1)

#子機の設定

##子機にファームウェアを書き込む
Samp_Monitor_EndDevice_Input_JN5164_LITE2525A_1_6_1.bin

##親機に子機設定書換用ファームウェアを書き込む
Samp_Monitor_EndDevice_Input_JN5164_CNFMST_1_6_1.bin

##親機に子機の設定を保存

[設定コマンド一覧](http://mono-wireless.com/jp/products/TWE-Lite-2525A/manual_settings.html)

|コマンド|名称|解説|
|:--|:--|:--|
|i|Device ID|子機の論理デバイスID(1～100)。|
|c|Channels|周波数チャネル(11～26)。カンマ区切りで複数指定可能。|
|x|Tx Power|送信出力。上位:再送回数(0～9)。下位:送信出力(0～3、3が最強)。|
|d|Sleep Dur|送信間隔(30～86400000[ミリ秒])。|
|p|Sensor Parameter|動作モード。|
|o|Option Bits|オプションビット。|

###設定変更前
```
--- CONFIG/Samp_Monitor V1-06-1/SID=0x8100f84a/LID=0x00/RC=10000 ---
 a: set Application ID (0x67726305)
 i: set Device ID (--)
 c: set Channels (15)
 x: set Tx Power (13)
 d: set Sleep Dur (500)
 w: set Sensor Wait Dur (0)
 m: set Sensor Mode (0x35)
 p: set Sensor Parameter (15)
 P: set Sensor Parameter2 ( )
 k: set Enc Key (0xA5A5A5A5)
 o: set Option Bits (0x00000011)
---
 S: save Configuration
 R: reset to Defaults
 *** POWER ON END DEVICE NEAR THIS CONFIGURATOR ***
```

###設定変更後
```
--- CONFIG/Samp_Monitor V1-06-1/SID=0x8100f84a/LID=0x01/RC=10000 ---
 a: set Application ID (0x12345678)*
 i: set Device ID (1=0x01)*
 c: set Channels (15)
 x: set Tx Power (3)*
 d: set Sleep Dur (500)
 w: set Sensor Wait Dur (0)
 m: set Sensor Mode (0x35)
 p: set Sensor Parameter (0)*
 P: set Sensor Parameter2 ( )
 k: set Enc Key (0xA5A5A5A5)
 o: set Option Bits (0x00000001)*
---
 S: save Configuration
 R: reset to Defaults
 *** POWER ON END DEVICE NEAR THIS CONFIGURATOR ***
```

##親機から子機へ設定を転送

親機に子機を近づけて、電源をONします。
親機から子機に設定が転送されると、親機のシリアルコンソールにSUCCESSが表示されます。

```
!INF REQUEST CONF FR 81020C4C
>>> TxCmp Ok(tick=28340,req=#1) <<<
!INF ACK CONF FR 81020C4C
SUCCESS 81020C4C
```

#親機の設定

##親機にファームウェアを書き込む
Samp_Monitor_Parent_JN5164_ToCoStick_1_6_1.bin

##親機の設定を変更
###設定変更前
```
--- CONFIG/Samp_Monitor V1-06-1/SID=0x8100f84a/LID=0x00 ---
 a: set Application ID (0x67726305)
 i: set Device ID (--)
 c: set Channels (15)
 x: set Tx Power (3)
 b: set UART baud (115200)
 B: set UART option (8N1)
 k: set Enc Key (0xA5A5A5A5)
 o: set Option Bits (0x00000001)
---
 S: save Configuration
 R: reset to Defaults
```

###設定変更後
```
--- CONFIG/Samp_Monitor V1-06-1/SID=0x8100f84a/LID=0x00 ---
 a: set Application ID (0x12345678)*
 i: set Device ID (--)
 c: set Channels (15)
 x: set Tx Power (3)
 b: set UART baud (115200)
 B: set UART option (8N1)
 k: set Enc Key (0xA5A5A5A5)
 o: set Option Bits (0x00000001)
---
 S: save Configuration
 R: reset to Defaults
```
TwitterのツイートボタンのURLやメッセージを動的にする方法

シングルページアプリケーション(SPA)でページ状態に合わせてTwitterでシェアしたいURLを切り替えたい（動的にしたい）時がたまにありますよね。

そんな時はTwitter公式APIの「twttr.widgets.createShareButton」を使うと便利ですよ。

```js
// Twitterの初期化
$(function() {
  var d = document;
  var s = 'script';
  var id = 'twitter-wjs';
  var js, fjs = d.getElementsByTagName(s)[0];
  if (!d.getElementById(id)) {
    js = d.createElement(s);
    js.id = id;
    js.src = 'https://platform.twitter.com/widgets.js';
    fjs.parentNode.insertBefore(js, fjs);
  }
});

// twttrの初期化(platform.twitter.com/widgets.jsの完了)が未だなら待つ。
function callAfterTwitterInitialization(callback){
  if(typeof twttr !== "undefined"){
    callback();
  } else {
    setTimeout(function(){
        callAfterTwitterInitialization(callback);
    }, 100);
  }
}

var shareUrl = "http://qiita.com/";
var targetId = "twitter-share-button";
var message = "Qiita wryyyyyyy";
var hashtag = "#wryyyyyyy";

// twttrが使えるようになったらシェアボタンを作る。
callAfterTwitterInitialization(function(){
  $('#' + targetId).empty();
  twttr.widgets.createShareButton(
    shareUrl,
    document.getElementById(targetId),
    {
      count: 'none',
      text: message,
      size: "large",
      hashtags: hashtag,
    });
});
```

上のスクリプトを動かすと、以下内容を共有するTwitterボタンが動的に作られます。

```
Qiita wryyyyyyy http://qiita.com/ #wryyyyyyy
```

使う時には shareUrl と message をページの状態に合わせて入れ替えて下さい。

すっきり。

参考：https://dev.twitter.com/web/javascript/creating-widgets
ドル円の変動を表現するランプをArduinoで作ってみた

LED光らせるだけ試して眠っていたArduinoを出してきて、もう少し高度なことを試してみた。
「Arduinoをはじめよう第2版」の最後のサンプルほぼそのままだけど。

■練習
自分のブログにpeaceという文字列があると青、無ければ赤に光るランプを作ってみた。
本当は為替の上下をリアルタイムに見えるようなものを作りたいのだけど、うまく情報取れるサイトが見つからなくてひとまず断念。また後ほどチャレンジしてみよう。
（為替の上下をスクレイピングできるサイトさあればすぐに実装できる）

動画は↓からご覧ください。
https://www.facebook.com/shen.l.liang/videos/vb.1440292456/10206225487383029/?type=2&theater
　
動画は最新記事にpeaceという単語を入れたり消したりしてみているところ。
私のはてなダイアリーです。

メチャクチャ汚いコードだけど、コードはこちら。
https://github.com/ryogrid/Arduino_learning/tree/master/blog_lamp

■練習2
BTCUSDの一分足できた
http://youtu.be/IExjdCL22jY
https://github.com/ryogrid/Arduino_learning/tree/master/btcusd_lamp

■でけた
https://www.youtube.com/watch?v=LRH5X6kaR2E
https://github.com/ryogrid/Arduino_learning/tree/master/usdjpy_lamp
RaspberryPi3にカメラモジュールつけて撮影した画像をDeepLearningで分類してみた

# 開発環境
・RaspberryPi3
・Raspberry Pi ハイビジョン ビデオカメラ モジュール HD Video Camera Module
・Raspbian(Debian version 8.0)

# Raspberrypiでカメラを有効化
まずはカメラモジュールをカメラコネクタに差し込む

![image](https://qiita-image-store.s3.amazonaws.com/0/100746/3bfc11d7-c149-4ada-eb19-b1daa5a5099d.png)

初期設定では、カメラが有効になっていないので、設定で有効にする。
`$ sudo raspi-config`
として、「5 Enable Camera」を選択。
メニュー画面で「Finished」を選択し、ラズパイを再起動する。

下記コマンドでカメラが有効になっていることを確認。

```
$ vcgencmd get_camera
supported=1 detected=1
```

# DeepLearning用ライブラリ「DeepBeliefSDK」の導入
```
$ git clone https://github.com/jetpacapp/DeepBeliefSDK.git
$ sudo apt-get install -y mercurial
$ hg clone https://bitbucket.org/eigen/eigen
$ cd DeepBeliefSDK
$ ln -s ../eigen
$ cd source
$ make clean
$ sudo apt-get install gcc-4.8 g++-4.8
$ make GEMM=eigen TARGET=pi2 CC=gcc-4.8 CXX=g++-4.8
$ sudo cp libjpcnn.so /usr/lib
$ sudo ldconfig
```

# 写真撮影〜画像分類実行

コーヒーカップを300x300のサイズで撮影してみる
`$ raspistill -w 300 -h 300 -o raspistill -o camera1.png`

![camera5.png](https://qiita-image-store.s3.amazonaws.com/0/100746/9bd7d107-387b-569f-5fa9-d69b41e70447.png)



撮影した画像の分類を実行

`$ ./jpcnn -i camera1.png -n ../networks/jetpac.ntwk -t -m s -d`

結果は・・・

```
************************
0.011523	pitcher
0.011059	measuring cup
0.162259	cup
0.024144	coffeepot
0.640897	coffee mug
0.040280	beaker
0.013066	espresso
0.013102	espresso maker
Classification took 1782 milliseconds
```

なかなか良好かと
お名前.comで取得したドメインをさくらVPSで使う

#やりたいこと
さくらVPSをレンタルして、お名前.comでドメイン取得した。
取得したドメインでさくらVPSにアクセスしたい。
**→ドメインとIPアドレスの紐付きをDNSに登録する。**

調べるとお名前.comのDNSに登録するパターンとさくらのDNSに設定するパターンがあった。
さくらでDNS設定するよりこっちの方が簡単でいいじゃまいか。

**ちなみに手順や認識で間違いがあれば教えてください。**

#お名前.comのDNSに登録するパターン
参考：[お名前.com で取ったドメインを使う](http://qiita.com/megane42/items/df84f87c0bdcdd015eb6)

①[ドメインNavi](https://www.onamae.com/domain/navi/domain)にアクセス
②「ドメイン設定」→「DNS関連機能の設定」
③対象ドメインを選択して次へ
④「DNSレコード設定を利用する」
⑤必要項目を入力して「追加」をクリックすると下部に追加される。「確認項目へ」をクリックしてあとは道なり。

| 項目     |       設定値 | 
|----------|---------------|
|ホスト名 |使用したいサブドメイン or 空欄  |
|TYPE |A: サブドメインの付かない URL (ネイキッドドメイン) をIPアドレスに紐付ける<br><br> CNAME: サブドメイン付きの URL を別の URL に紐付ける<br>※ネイキッドドメインを CNAME に使うと色々不具合が出る！|
|VARUE |紐付けるIPアドレス or URL  |


#さくらのDNSに登録するパターン
参考:[さくらのVPSに独自ドメインを設定してみた](http://webkaru.net/vps/sakura-domain-setting/)

###さくら側設定
①VPSのコンパネから[ネームサーバの登録画面](https://secure.sakura.ad.jp/menu/domain/)へ
②ネームサーバ新規登録
登録するドメインを入力して送信ボタンクリック
③ドメイン名一覧からゾーン編集を選択
④IPアドレスを入力して送信ボタンをクリック

ここで登録したDNSをお名前.com側に登録する。

###お名前.com側設定
⑤[ドメインNavi](https://www.onamae.com/domain/navi/domain)にアクセス
⑥「ドメイン設定」→「ネームサーバーの変更」
⑦ドメインを選択して、「他のネームサーバを利用」タブを開く。
⑧さくらで登録したDNSを入力して、確認画面へ

#DNS登録確認

```
nslookup ドメイン名
```

または、Apacheを起動してhttp://ドメイン名でアクセスしてみる。
PypeRでPythonからRstanを使う

# PypeR
pythonからRのコードを叩くことができるパッケージ．
```
pip install pyper
```
```
import pyper
r=pyper.R(use_pandas='True') !Trueにしないとうまくいかなかった
r("soruce(file='stan.R')") !stanの実行ファイルをRで実行
!Rのオブジェクトを取ってくる．
fit=r.get("fit") 
!stanの入れ物は持ってくるとnumpy(parameter数, step数)になっている．
```
ESLint v3.1.0

前 [v3.0.0] | 次 [v3.2.0]

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">ESLint v3.1.0 released: <a href="https://t.co/F85E9yXTC9">https://t.co/F85E9yXTC9</a></p>&mdash; ESLint (@geteslint) <a href="https://twitter.com/geteslint/status/754041478549237760">2016年7月15日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

ESLint 3.1.0 がリリースされました。
小さな機能追加といくつかのバグ修正が行われています。

質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。

- :globe_with_meridians: [日本語 Issue 管理リポジトリ](https://github.com/eslint/eslint-jp)
- :speech_balloon: [日本語サポート チャット](https://gitter.im/eslint/eslint-jp)
- :globe_with_meridians: [本家リポジトリ](https://github.com/eslint/eslint)
- :speech_balloon: [本家サポート チャット](https://gitter.im/eslint/eslint)

----

# :sparkles: コアへの機能追加

## [#3307]: Lint 結果にて問題の位置を範囲指定できるようになった

この機能はプラグインやカスタム ルール、およびエディタ連携ツールの開発者向けです。

従来、Lint 結果の各問題は位置情報 (行番号と列番号) を持っていました。これは CLI ツールとしては問題ないのですが、エディタ上に問題を表示する際に不便でした。現状のエディタ連携ツールでは、示された位置にある単語に赤線を引いたり、行全体に赤線を引いたりと工夫しています。

`v3.1.0` より、Lint 結果の各問題は範囲情報 (開始位置と終了位置) を持つことができるようになりました。詳細は [#6640] を御覧ください。

# :bulb: 新しいルール

## [#6066]: [multiline-ternary]

![JSCS](http://jscs.info/favicon.ico) JSCS 互換ルールです。
三項演算子を使うとき、必ず改行するように矯正します。

```js
/*eslint multiline-ternary: error*/

// ✔ GOOD
var a = foo > bar ?
    value1 :
    value2;

var b = foo > bar
    ? value1
    : value2;


// ✘ BAD
var c = foo > bar ? value1 : value2;
```

# :wrench: オプションが追加されたルール

## [#4133]: [spaced-comment]

複数行コメントの末尾スペースに関するオプションが追加されました。
従来は末尾スペースの有無をチェックしていませんでしたが、このオプションを使うと末尾スペースの有無と先頭スペースの有無がマッチしているかどうかチェックします。

```js
/*eslint spaced-comment: [error, always, {block: {balanced: true}}]*/

// ✔ GOOD

/* this is a comment */

// ✘ BAD

/* this is a comment*/
/*this is a comment */
```

> 3.1.0 現在、なんかバグってる... :sweat:
> → 3.1.1 で修正されました :clap: 

## [#5613]: [key-spacing]

単一行のオブジェクト リテラルと複数行のオブジェクト リテラルで異なる設定をできるようになりました。

```js
/*eslint key-spacing: [error, {
    singleLine: {beforeColon: false, afterColon: true},
    multiLine: {beforeColon: true, afterColon: true, align: colon}
}]*/

// ✔ GOOD
var obj = {one: 1, two: 2, three: 3};
var obj2 = {
    two   : 2,
    three : 3
};

// ✘ BAD
var obj = {one : 1, two : 2, three : 3};
var obj2 = {
    two: 2,
    three: 3
};
```

# :pencil: 新たに 1 つのルールが `eslint --fix` をサポートした

- [#6639]: [no-var] - (ただし再宣言されていたり、スコープ外から参照されていたりする場合を除く)

[v3.0.0]: http://qiita.com/mysticatea/items/9c8a8b1219d5f94441e8
[v3.2.0]: http://qiita.com/mysticatea/items/706f4bb024d7ceb78f1d
[#3307]: https://github.com/eslint/eslint/issues/3307
[#4133]: https://github.com/eslint/eslint/issues/4133
[#5613]: https://github.com/eslint/eslint/issues/5613
[#6066]: https://github.com/eslint/eslint/issues/6066
[#6639]: https://github.com/eslint/eslint/issues/6639
[#6640]: https://github.com/eslint/eslint/issues/6640
[key-spacing]: http://eslint.org/docs/rules/key-spacing
[multiline-ternary]: http://eslint.org/docs/rules/multiline-ternary
[no-var]: http://eslint.org/docs/rules/no-var
[spaced-comment]: http://eslint.org/docs/rules/spaced-comment
[pandoc] html -> pdfでテーブルキャプションに画像を置くと怒られる

次のHTMLを`pandoc a.html -p a.pdf`でpdfに変換すると怒られる。

```html
<html>
<body>
<table>
<caption><img src="a.png"></caption>
<tr><td>a</td></tr>
</table>
</body>
```

```text
! Use of \LT@array doesn't match its definition.
\new@ifnextchar ...served@d = #1\def \reserved@a {
                                                  #2}\def \reserved@b {#3}\f...
l.64 \caption{\includegraphics{a.png}}

pandoc: Error producing PDF
```

ところが、間に`latex`ファイルを明示的に挟むと怒られない。
`pandoc a.html -s -t latex | pandoc -f latex -o a.pdf`
pdfファイルを開く事も出来るが、キャプションのあたりに画像と共に`@l@`となにやらゴミが表示される。
中間のlatexファイルを確認すると次の様になっている。

```tex
\begin{longtable}[]{@{}l@{}}
\caption{\includegraphics{a.png}}\tabularnewline
\toprule
A\tabularnewline
\bottomrule
\end{longtable}
```

`longtable`の周りに原因と思しき`{@{}l@{}}`がある。
恐らく、表示を整えるための何かをここに展開する予定だったのだろうが、なぜかゴミが残っている。
とりあえず`@{}`を全て消し去ればとりあえず正しいlatexファイルが得られる。

これが直接pdfに変換する時のエラーと関係あるのかは不明。
何やらありそうな気はするが。

環境は以下の通り。

pandoc 1.17.1
Compiled with texmath 0.8.6.4, highlighting-kate 0.6.2.1.

pdfTeX 3.14159265-2.6-1.40.16 (TeX Live 2015/Arch Linux)
kpathsea version 6.2.1
MAMPですばやくPHP環境を構築する

MACでPHPを触ってみるための環境構築。
# 環境
MAC OX EL Caption 10.11.4
MAMPに頼るのはヌルいような気はするが一番手っ取り早そうなので採用。

# MAMPのインストールから起動確認まで
1. [公式サイト](https://www.mamp.info/en/)にアクセスして
無料のMAMPをダウンロードする。（MAMP PROは有料）
1. ダウンロードしたパッケージファイルを実行するとインストーラーが起動する。
1. インストールは`続ける`を連打するが規約に同意した後の
`カスタマイズ`で`MAMP PRO`のチェックだけは外してからインストールした方が無難。
1. インストール完了後、アプリケーションからMAMPを実行する。
1. 象さんの居る画面で`サーバを起動`をクリックしてから`オープンWebStartの`という不可解なリンク（？）をクリックする。
1. http://localhost:8888/MAMP/
が起動して象さんに`ようこそ！`と言って頂ければMAMPの環境構築は完了。

# おまけ
本当にコレで良いのか不安になるのでMAMPのデフォルトルート・ディレクトリである
`/Applications/MAMP/htdocs/`配下に`phpinfo.php`を作成して置いてみる。
phpinfo.phpの中身はこの１行だけ。

`<?php phpinfo();`
（`?>`タグが無いのはワザとです。）
http://localhost:8888/MAMP/phpinfo.php
にアクセスしてPHP Version等が表示されればOK.

# 感想
環境構築が恐ろしく簡単。
デフォルトルート・ディレクトリの変更や謎のポート8888の変更も
MAMPの`設定`からGUIで気軽に変更出来て素敵。
MAMPのページからphpMyAdmin等の起動もできちゃう。

象さんありがとう。
もう"ぬるぽ"は"ガッ"しなくていい


##はじめに
他人のSwiftのコードを見ていると、
（この書き方、あまりSwiftっぽくない。）
と思うことがよくあります。
そこで、私が気になったSwiftの作法について取り上げて行きたいと思います。

第三回は「もう"ぬるぽ"は"ガッ"しなくていい」です。

##ぬるぽって何？
ぬるぽ（ヌルポ､NULLPO）は、プログラミング言語であるJavaにおいて、処理に異常が発生したとき（例外）に表示されるメッセージのひとつである java.lang.NullPointerException（またはNullPointerAssignment）の略語。匿名掲示板2ちゃんねるのプログラマー板が発祥とされる。

参考：
https://ja.wikipedia.org/wiki/ぬるぽ

※Swiftではnil参照で落ちる現象を"ぬるぽ"とは言いませんが、本記事では"ぬるぽ"と呼称しています。

##具体例
例えば、以下のようなコードを書く人がいます。

###よく見るパターン

```Swift
var nohirap: Int? = nil
NSLog(nohirap!.description)
```

すみません、上手い"よく見るパターン"が思いつきませんでした。
これは余程の素人でない限りやらない感じですが、実際コードを見ていると、Optional型の扱いが雑になって、"!"でForced unwrappingをしている場面をよく見かけます。

##そもそもForced unwrappingってどうなの？
正直私は、使うべきではないと考えています。

Optional型は、強制的にコーダーにnilチェックをさせ、ぬるぽを起こさせない仕組みなのに、それを何のチェックもせずに参照しようとするのはOptional型の意味がないと思うからです。

##じゃあどうすれば良いの？
前回の記事「["nil"というリテラルを可能な限り書きたくない](http://qiita.com/nohirap/items/908f7e4ec92b075ad575 "")」にも載せましたが、以下のように安全にunwrappするのが望ましいと思われます。

###Optional binding
```Swift
var nohirap: Int? = nil
if let nohirap = nohirap {
	//nilじゃなければこのifに入る
	NSLog(nohirap.description) //ifの中ではアンラップされた状態で扱える
}
```

###Optional Chaining
```Swift
var nohirap: Int? = nil
NSLog(nohirap?.description ?? "") //nilだったら空文字を表示する
```

###guard
```Swift
var nohirap: Int? = nil
guard let nohirap = nohirap else {
	// nilだったらreturnされる
	return
}
NSLog(nohirap.description) //アンラップされた状態で扱える
```

##まとめ
Forced unwrappingを使うと、ぬるぽをガッすることになりかねないので、Optional bindingなどを使い、安全に中身を取り出して参照しましょう。
ELB の仕様を Apache と比較

Amazon Elastic Load Balancing のリクエストヘッダ仕様を Apache HTTP Server と比較してみる （当社調べ）
==================================================

ここで "クライアント" とは リバースプロキシサーバーに直接接続しにきたヤツのことです。

## Apache の [mod_proxy_http](https://httpd.apache.org/docs/2.4/en/mod/mod_proxy_http.html) をデフォルトで使った場合

```
Host: {オリジンサーバーのホスト}
X-Forwarded-For: {クライアントが送ってきた X-Forwarded-For リクエストヘッダ値 + クライアントのIPアドレス}
X-Forwarded-Host: {クライアントが送ってきた X-Forwarded-Host リクエストヘッダ値 + クライアントが送ってきた Host リクエストヘッダ値}
X-Forwarded-Server: {クライアントが送ってきた X-Forwarded-Server リクエストヘッダ値 + リバースプロキシサーバーのホスト名. ServerNameで指定}
Connection: Keep-Alive
```

## ELB の場合

```
Host: {クライアントが送ってきた Host リクエストヘッダ値}
X-Forwarded-For: {クライアントが送ってきた X-Forwarded-For リクエストヘッダ値 + クライアントのIPアドレス}
X-Forwarded-Port: {クライアントが接続してきたリバースプロキシサーバーのポート番号}
X-Forwarded-Proto: {クライアントが使用したプロトコル. 典型的には http や https}
Connection: keep-alive
```

いずれも、Accept*: や User-Agent: などクライアントが送ってきたヘッダはそのまま流します。

ELB は X-Forwarded-Port や X-Forwarded-Proto をカンマ連結しません。


## Apache の挙動を ELB に似せるための設定サンプル

似せるだけです。 実際には ELB は X-Forwarded-Host や X-Forwarded-Server に値を追加しません。

```
# SSLオフロードの場合
ProxyPass / http://{origin_server}/
ProxyPassReverse / http://{origin_server}/
ProxyPreserveHost On
<VirtualHost *:80>
  RequestHeader set X-Forwarded-Port 80
  RequestHeader set X-Forwarded-Proto http
</VirtualHost>
<VirtualHost *:443>
  RequestHeader set X-Forwarded-Port 443
  RequestHeader set X-Forwarded-Proto https
</VirtualHost>
# 必要に応じて
# ProxyPassReverseCookieDomain
# Filter & Substitute
```
MacにRictyフォントを一発で入れたい

#Rictyのinstall

##Rictyインストーラのダウンロード

```
git clone https://github.com/metalefty/Ricty.git
```

##miguフォントダウンロード

```
curl -L   -o  'migu-1m-20130617.zip'  'http://sourceforge.jp/frs/redir.php?m=iij&f=%2Fmix-mplus-ipa%2F59022%2Fmigu-1m-20130617.zip' && unzip migu-1m-20130617.zip
```

##Inconsolataのダウンロード

```
curl   http://levien.com/type/myfonts/Inconsolata.otf > Inconsolata.otf
```

##Rictyインストーラの実行

```
sh ricty_generator.sh auto
```

#上記をまとめたインストールスクリプト

```bash:ricty_installer.sh
mkdir tmp && cd tmp
brew install fontforge
git clone https://github.com/metalefty/Ricty.git
cd Ricty
curl -L   -o  'migu-1m-20130617.zip'  'http://sourceforge.jp/frs/redir.php?m=iij&f=%2Fmix-mplus-ipa%2F59022%2Fmigu-1m-20130617.zip' && unzip migu-1m-20130617.zip
curl   http://levien.com/type/myfonts/Inconsolata.otf > Inconsolata.otf
sh ricty_generator.sh auto
mv *.ttf /Library/Fonts/
```
Gitで直前のコミットをなかったことにする


#まず確認

まずは取り消したい直前のコミットをチェック。

```
$ git log
```

PhpStormを使ってるのならversion controlのLogを見た方がわかりやすいかも。

#取り消す

取り消したいコミットを確認できたら

```
$ git reset HEAD^
```

これで戻る。

#うまくいったか確認

```
$ git status -s
```

PhpStormならversion controlでチェックできる。
直前のコミットが取り消され、かつ自分の手元のファイルの作業状態は維持されたままになる。

##やっていること

直前のコミットで１枝進んでしまったbranchを１つ戻し、新しい枝を生成し直している、らしい。
Cassandraメモ: Replication Strategy

http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archDataDistributeReplication.html
上記、Cassandra v3.0のドキュメント読んで調べたことをメモします。
実際に動かして確認しているわけではないので、間違いがあるかもしれません。お気づきの点はご指摘ください。

# データの複製

キースペース作成時にレプリケーションファクターを指定します。指定されたレプリケーションファクター数だけ、データの複製（レプリカ）が作られます。
Cassandraにおいては、すべてのレプリカは等価であり、マスターレプリカ・セカンダリレプリカというような主副関係はありません。

また、キースペース作成時にはレプリカ配置の方針（Replication Strategy）を指定します。「SimpleStrategy」「NetworkToplogyStrategy」の2つがあります。

各方針の説明の前に、Cassandraでノードをグループ化する概念をいくつか挙げます。
原文の説明は[こちら](http://docs.datastax.com/en/cassandra/3.0/cassandra/architecture/archIntro.html)。


- ノード：データを物理的に保管する場所のことです。物理的なマシン、物理的なサーバーと捉えれば良いかと思います。
- データセンター：ノードの集合です。必ずしも物理的なデータセンターと一致させる必要はありません。物理的に1つのデータセンター内に、Cassandraのデータセンターを複数定義することが可能です。ただし、Cassandraのデータセンター1つを構成するノードは地理的に同一のロケーションにあるノードのみとします。
- クラスター：データセンターの集合です。クラスター1つを構成するデータセンターは、地理的に複数のロケーションにあるもので構いません。
- ラック：データセンター内における、ノードをグループ化したものです。

これらの用語を踏まえて、以下、Replication Strategyの説明です。

## SimpleStrategy

1つのデータセンター、1つのラックしか無いと考える方針です。レプリカの1つ目をPartitionerが決めたノードに配置します。2つ目以降のレプリカは、ノードリング（ノードが輪の上に配置されたとみなしたもの）上を時計回りに辿ったノードへ配置していきます。

## NetworkTopologyStrategy

2つ以上のデータセンター、また複数のラックがあるとみなす方針です。クラスタ作成時はデータセンターやラックが1つでも、今後増える可能性があればこちらを選択します。
この方針においては、各データセンターにいくつのレプリカを配置するかを指定します。データセンター毎に異なるレプリカ数を指定できます。
この方針においては、2つ目のレプリカ配置ノードを探すためにノードリングを辿っていく際に、1つ目のレプリカを配置したノードと同じラックにあるノードをスキップし、異なるラックのノードにレプリカが配置されるようにします。
同じラック上にあるノードは、電源や冷却、ネットワークの問題により同時に障害が起こる可能性があると考えるためです。
Geany + nkfでカタカナをひらがなに変換

Geanyのカスタムコマンドにいくつか登録しているのですが、すぐに忘れてしまって後で気づくことが多いので、使った時のことをメモしておきます。

環境はUbuntu 12（または14） ＋ Geany 1.28 ＋ nkf 2.1です。

##そもそもカスタムコマンドってなに？
選択した範囲の文字列を事前に登録しておいたコマンドの標準入力に送信して、その出力（標準出力）で置き換える機能です。

カスタムコマンドの登録は`編集` → `書式` → `選択範囲を送る` → `カスタムコマンドを設定`で行います。実際に使用する時は`編集` → `書式` → `選択範囲を送る`からカスタムコマンドを選択します。

カスタムコマンドは標準入力から入力して標準出力に出力できればLinuxのコマンドでもスクリプトでも何でもOKですので、ちょっとしたコマンドを登録しておくと便利かなと思います。

##カタカナ → ひらがな
というわけでカタカナからひらがなへの変換です。まず`編集` → `書式` → `カスタムコマンドを設定`でカスタムコマンドを設定ダイアログを表示します。[追加]ボタンをクリックして以下のように設定します。

|ID|コマンド|ラベル|
|:-:|:----:|:---:|
|1|nkf --hiragana|ひらがなに変換|

実際の画面はこんな感じです。
![geany_custom.jpg](https://qiita-image-store.s3.amazonaws.com/0/128670/d7755fde-95c9-3986-ac7f-80780c5f1516.jpeg)

設定ができたら適当にカタカナの文字を選択（複数行も可）して、`編集` → `書式` → `選択範囲を送る` → `ひらがなに変換` を選びます。

ひらがなに変換される事を確認します。これで終わりです。

##その他
私の場合は「ひらがなに変換」以外にも以下のような感じでカスタムコマンドを登録しています。

|ID|コマンド|ラベル|
|:-:|:----:|:---:|
|1|nkf --hiragana|ひらがなに変換|
|2|nkf --katakana|カタカナに変換|
|3|tr "A-Z" "a-z"|大文字→小文字|
|4|tr "a-z" "A-Z"|小文字→大文字|
|5|nkf -w|MIMEデコード|

最後の「MIMEデコード」は単にutf8に変換するだけの意味のなさそうなコマンドなんですが、`nkf`はMIMEも認識してくれますので、メールヘッダーに出てくる`=?ISO-2022-JP?B?GyRCJUYlOSVIJEckORsoQg==?=`のようなテキストも変換してくれます。登録しておくと案外と重宝します。

##カスタムコマンドのバックアップ
カスタムコマンドは`.config/geany/geany.conf`に保存されますが、`custom_commands=`と`custom_commands_labels=`の行をどこかにメモしておくと新たにGeanyをインストールした時とかにその行を貼り付けるだけで済みます。

```text:.config/geany/geany.conf（抜粋）
custom_commands=nkf --hiragana;nkf --katakana;tr "A-Z" "a-z";tr "a-z" "A-Z";nkf -w;
custom_commands_labels=ひらがなに変換;カタカナに変換;大文字→小文字;小文字→大文字;MIMEデコード;
```
z軸ラベルを回転させました(gnuplot)

###gnuplot で3次元散布図を描画。
----
EPS形式で保存する。

軸ラベルを日本語表記にしたい場合、文字コードを指定。
今回は文字コードEUCとして保存。
`set terminal postscript eps enhanced "GothicBBB-Medium-EUC-H" 20`

軸ラベルを設定。とりあえずz軸。
`set zlabel "aaa"`

z軸ラベルを反時計回りに90度回転。
`set zlabel rotate by 90`


メモリのラベルも同じようにして回転できる。
`set xtics rotate by 90`

###c言語でgnuplot動かしているので、実際はこうです。
----

```c:plot.c
#include <stdio.h>
#include <stdlib.h>

int main(){
    FILE *gp0;
    gp0 = popen("gnuplot","w");// パイプ接続popen()関数                                                                                                            
    fprintf(gp0, "set zrange[0:10]\n");
    fprintf(gp0, "set zlabel \"aaa\"\n");
    fprintf(gp0, "set zlabel rotate by 90\n");
    //色々ぷろっと
    fflush(gp0);
    fprintf(gp0,"pause 5\n);
    pclose(gp0);
 
    return 0;
```
###参考にさせていただいたサイト
----
<http://www.eng.kagawa-u.ac.jp/~haruna/memo/gnuplot/gnuC.html>
<http://www.obihiro.ac.jp/~suzukim/masuda/utils/gnuplot.html>
<http://d.hatena.ne.jp/naga_sawa/20130109/1357717527>
PythonでTwitter APIを使ってツイートする

PythonでTwitter APIを使ってツイートする最低限の手順を記します。
Python 3.5.1で動作確認済みです。

## アプリの新規登録、Access tokenの取得
以前書いたRuby版の記事があるので、参考にしてください。
[RubyでTwitter APIを使ってツイートする](http://qiita.com/enmtknt/items/b1ff3bcd5d3ef8819845)

## Twitter APIにアクセスする為のPythonパッケージのインストール
コマンドラインで以下のコマンドを実行します。
```$ pip install python-twitter```

## Pythonのコード
```python:tweet.py
# -*- coding: utf-8 -*-

import twitter


api = twitter.Api(consumer_key="Consumer Keyを入力",
                  consumer_secret="Consumer Secretを入力",
                  access_token_key="Access Tokenを入力",
                  access_token_secret="Access Token Secretを入力"
                  )
api.PostUpdate("tweet from my app")
```
## ツイートする
```$ python3 tweet.py```
崩れない＆綺麗なWebページにするためのCSSまとめ


普通のコーディングはそこそこ慣れてきたけど、最後の仕上げ作業が苦手。
いつも同じことをするのでメモ。

#全体編

##全画面に表示するときはhtmlから`height:100%`に

```
html,body{
  height:100%;
}
```

##背景色の統一にはbodyから

```
body {
  background: black;
}
```

##背景固定したいときはDOMを1つ置いてみる

置いて`fixed`。他の要素を囲まないように注意。

```html:index.html
<body>
	<div class="background"></div> // 背景用のdiv
	<div class="l-top">・・・</div>
	<div class="l-main">・・・</div>
	<div class="l-footer">・・・</div>
</body>

```

```css:common.css
.background{
  width: 100%;
  height: 100%;
  position: fixed;
  top:0;
  left:0;
  background-image: url('../../img/main.jpg');
  background-size: cover;
  z-index: -1;
}
```

#レスポンシブ編

scssを使う場合のcss3のメディアクエリ。
（そのうちBourbon Neatも使えるようにはなりたい）

- ブレイクポイントを設定
- `@mixin` を作成
- `@content` を使って中を追記できるようにする

```scss:common.scss
$breakpoint: 800px;
@mixin media { // 800px以上のとき
  @media screen and (min-width: $breakpoint) {
    @content;
  }
}
```

##実際の例

```scss:top.scss
.l-top {
  background-image: url('/img/exam.img');
  background-size: cover;
  height: 400px;
  @include media {
    height: 360px;
  }

```
THREE.JSを使った【非表示オブジェクト】との当たり判定

THREE.jsで当たり判定・特に「Ray(光線）を使用した当たり判定」として、いかにも「コレ使えよ！」と用意されている、

THREE.Raycaster　オブジェクト、及び　intersectObject　メソッドがあります。

これはその名の通り「　指定位置から　あるオブジェクトに対し、指定ベクトル上にある交差点を算出してくれる」という、それはまぁ３Dゲームの地形判定にうってつけのメソッドであります。

・・一見するとね。


ただ、こいつには罠が仕込んでありまして、

【非表示のオブジェクトに対しては、交差判定を行ってくれない】

という仕様になっております。


何がまずいかというと、
「地形は作りこんだモノを表示して、表示とは別に非表示のモデルを用意。その非表示オブジェクトから交差判定をする」ということが、できないんです。

単純に

```js

 heightObject.visible = false;

//略

var ray = new THREE.Raycaster(C_pos, baseV.normalize());

// 交差判定
var objs = ray.intersectObject(heightObject);
for (var i = 0; i < objs.length; i++) {
    player1.Pos.y = objs[0].point.y;
}

```

としちゃうと


![ukabu.png](https://qiita-image-store.s3.amazonaws.com/0/133895/4b098ad6-0d7a-a085-d0e8-21f50a05977f.png)

↑こうなっちゃう


ではどうするか。

ちょっと抜け穴チックですが、下記の通りにします。


```js
 heightObject.material.materials[0].visible = false;
```

![tatta.png](https://qiita-image-store.s3.amazonaws.com/0/133895/46b368b2-9d27-5755-133f-269a6958dfbe.png)


いわば、「Object3Dでは表示対象。だけど、マテリアルで非表示対象」とすることで、上記のような「見えているものと当たり判定を別にする」ことが可能となりました。

この方法を使った時の懸念で「あれ、となると、他で【表示時と同じような、余計な計算・・・例えば、DrawMeshは走るけど、VertexShader側で透過１００％とかやってない？」があったのですが、

Three.JsのRenderにて、「表示対象をリストアップ」する　【projectObject】というメソッドの中で、 material.visible がTrueでないものは、Drawリスト対象としない」という処理が行われているので、杞憂でした。


めでたしめでたし。
MySQL InnnoDBがクラッシュしたので復元してみた(CentOS6)

ひょんなことからmysql(5.1.73)がクラッシュしてしまったので復元を試みた時のメモです。
プログラム側のバグでコネクションを閉じずに無限に生成し続けている状態でした。

まず普通に起動させても立ち上がりません。。

```
# service mysqld start
Starting mysqld: 　　　　　　　[FAILED]
```

ストレージファイルのバックアップをとります。

```
# mkdir -p /root/mysql/backup
# cp -a /var/lib/mysql/* /root/mysql/backup/
```

強制リカバリーモードで立ち上げます。

```
# vi /etc/my.cnf
[mysqld]
innodb_force_recovery = 6

# service mysqld start
Starting mysqld: 　　　　　　　[OK]
```
`innodb_force_recovery`の値は1から順に上げていきます。自分の場合は6でようやく立ち上がりました。


すべてのテーブルをdumpします。

```
# mkdir -p /root/mysql/dump
# mysqldump -u root -x --all-databases > /root/mysql/dump/dump.sql
```

mysqlストレージファイルを削除します※mysqlディレクトリを除きます。

```
# rm -rf `ls -d /var/lib/mysql/* | grep -v "/var/lib/mysql/mysql"`
```

innodb_force_recoveryをコメントアウトしてmysqlを再起動するも失敗。停止できませんでした。（人によると思います）

```
# vi /etc/my.cnf
[mysqld]
#innodb_force_recovery = 6


# service mysqld restart
Stopping mysqld: 　　　　　　　　　　　　　　　　　　　　　　 　[FAILED]
Starting mysqld:                                            [  OK  ]
```

プロセスをkillするも殺せない・・

```
//ID調べて
# ps aux | grep mysql
# kill プロセスID
```

念のためchkconfigをoffにしてからOS再起動

```
# chkconfig mysqld off
//確認
# chkconfig --list | grep mysql
# shutdown -r now
```

mysqlを起動させてdumpを入れる

```
# service mysqld start
Starting mysqld:                                            [  OK  ]

# mysql -u root -p < /root/mysql/dump/dump.sql
```

忘れずにchkconfigをonに

```
# chkconfig mysqld on
```

なんとか元に戻りました。

## 参考
[KB Plesk: ﻿\[手順\] MySQL データベースでの InnoDB 破損を修復するには](https://kb.plesk.com/jp/6586#note)
litaの開発環境構築と開発環境トラブルの対処

## litaとは

[Lita: ChatOps for Ruby](https://www.lita.io/)

* Rubyでチャットボットを開発するためのGem
* Gemとして公開されているプラグインで拡張できる
* プラグインやアプリのジェネレータ付き
* 接続先サービスはプラグインを入れる事でslackやTwitter等が選べる。自分で書くこともできる。
    * lineは今のところ公開されているgemには見当たらない

## 開発環境構築

基本的にはどのOSでもlita開発チームが用意している開発環境構築用のリポジトリを使うのが簡単。vagrantにCoreOSを乗せて、そこにDockerでredisとRubyを乗せている。

* VirtualBoxを入れる
* vagrantを入れる

```bash
git clone https://github.com/litaio/development-environment.git
cd development-environment
vagrant up; vagrant ssh
### ここからVM内
lita-dev
### ここからコンテナ内
lita new app_name # アプリの雛形生成
cd app_name
bundle install
lita # デフォルトのshellアダプターでボットが起動される

# @lita infoを実行してみてバージョン情報が表示されればOK
Type "exit" or "quit" to end the session.
Lita > @lita info
@lita info
Lita 4.7.0 - https://www.lita.io/
Redis 3.0.7 - Memory used: 797.04K
```

起動できるのを確認できたらボットを置きたいサービスにつなぐためのGemをgemファイルに入れたり、Handler（ユーザの発言等に対する動作を定義する）として好きなロジックを実装して開発を進められる。

## 一番安直な解決作

* lita-devを叩いてもコンテナの起動が終わらない
* ホストのファイルが見えない

等の問題はそれなりにネット回線が太い場所にいるなら`vagrant destroy; vagrant up`してVMとコンテナを再構築すれば済む。VMやコンテナに何かgem以外の物を入れているので消したくない等の場合は以下。

### lita-devを叩いても延々待たされる

```
The development environment is still starting up. Please wait.....
```

これが延々続く場合がある。

```shell-session
core@lita-dev ~ $ systemctl | grep lita
● lita-dev.service                                                                         loaded failed failed    Lita development environment
```

systemctlコマンドを叩いてlita-devが死んでいたらこれが原因。

```bash
# vagrant ssh したcoreosの中で
sudo systemctl restart lita-dev.service
lita-dev
```

```shell-session
core@lita-dev ~ $ systemctl | grep lita
lita-dev.service                                                                         loaded active running   Lita development environment
```
こうなればOK

### ホストのファイルが見えない

一旦VMを落としてから再度立ち上げるとworkspace以下のファイルが見えない場合がある。`docker ps`でlita-devコンテナのIDを確認して`docker restart コンテナID`でコンテナを再起動してやると見えるようになった。
SwiftのEnumと計算型プロパティを組み合わせて便利に使うTips

最近、案件でEnumの便利な使い方を学んだのでシェアします。

計算型プロパティとEnumを組み合わせると
toString()関数とか作らなくとも、シンプルに欲しい値を取得できます。

## 例：Enumから文字列を取得する
Enum内でSelfを使うと、Enumが参照された際の自分自身を指すことができるので、
Switch文すら不要な場合があります。

```swift
enum SNSType: Int {

  case Facebook
  case Twitter
  case Google

  // シンプル
  var name: String {
      if self == Google {
          return "\(self)+"
      }
      return "\(self)"
  }

  // この例だとtoString関数は冗長。プロパティごとに全く出力するテキストが違うならOK
  func toString() -> String {
      switch self {
      case Facebook:
          return "Facebook"
      case Twitter:
          return "Twitter"
      case Google:
          return "Google+"
      }
  }
}

print(SNSType.Google.name) // "Google+"
```

## 例：UIImage (SNSのアイコン画像)を参照する
色々取得できます。

```
enum SNSType: Int {

    case Facebook
    case Twitter
    case Google

    var name: String {

        if self == Google {
            return "\(self)+"
        }
        return "\(self)"
    }

    var iconImage: UIImage {
        return UIImage(named: iconName)!
    }

    // 外から欲しいのはiconImageなので、icon名を出力する処理はprivateで隠蔽化してやる
    private var iconName: String {
        return "ic-" + name.lowercaseString + ".png"
    }
}
```

結果：
![iconImage.png](https://qiita-image-store.s3.amazonaws.com/0/30423/64a0f336-dd9b-108f-96cb-bec96759a3b4.png)


## <余談>値型のEnumについて想うこと

SwiftはEnumの値の型をStringにできます。
が、
本来Enumは**定数**であることを意識すると基本Int型がいいと思います。  
<追記>
※コメントに書いていただきましたが、String型で使用したほうが便利なケースも多々あるそうです。  ケースバイケースですね。すみません..

例えば、下記のようなEnumを作った場合、 
nameプロパティなど与えなくても、そのままSNS名が取得できるので一見便利そうですが、

```swift
enum SNSType2: String {
    case Facebook = "Facebook"
    case Twitter = "Twitter"
    case Google = "Google+"
}
```

例えばtag番号やタップしたセルなどから、
初期化したいとき、使い勝手が悪いです。

```swift
print(SNSType(rawValue: tag)!) // Facebook
print(SNSType2(rawValue: "Facebook")!) // Facebook
```

上記例の場合、初期化の結果は同じですが、
```SNStype2```は初期化の際、typoしてしまうとクラッシュします。
あと初期化の値に、"Facebook"と書けるなら

```swift
SNSType2.Facebook.rawValue
```

と定義すれば良いですが、毎回どのプロパティを定義すれば良いか分かるわけでもないのでやはり不便です。

ですので、値型のEnumは基本Int型で良いと思います。