OmniAICreator/Qiita-1.07M huggingface dataset:
AWS IoT Device SDK for Rubyを使ってみた

関係者皆様に, この場を借りてお礼申し上げます.
有難うございます.

# Description
- [AWS IoT Device SDK for Ruby](https://github.com/RubyDevInc/aws-iot-device-sdk-ruby) を使用.
- raspberry pi3へ温度/湿度Sensorを接続.
- 温度/湿度 Data をAWS IoT / Lambdaを通し, [Influx DB](https://www.influxdata.com/time-series-platform/influxdb/) on AWS へ収集.
- 加えて, [Chronograph](https://www.influxdata.com/time-series-platform/chronograf/)にて可視化 (graph化) する.
    - Chronographは, InfluxDB標準の Web Graph Tool




# Cauntion
- 構築手順を記述.  基礎部分は省略.
- 構築項目ごとに他記事へLinkする.
- Ruby code部を参照したい場合は以下.<br>
[#3 - AWS IoT Device SDK for Ruby script作成](http://qiita.com/Satoshi_Numasawa/items/41c4011cdce633398ba7#create-script)

 





# Hardware
- Mac Book Pro/Air Capitan 10.11.6
- Micro SD 8G (及び, Macへ接続するため, SDXCの下駄)
- [Raspberry pi3](https://raspberry-pi.ksyic.com/news/page/nwp.id/24)
- [AC Adapter](http://www.imprinc.co.jp/products/item/4571341970520/)
- [温度/湿度センサー](http://osoyoo.com/ja/2015/03/11/osoyoo-sensor-modules-kit-for-arduino/)
    - 上記キット内の, [DHT11 デジタル温度/湿度センサー](http://osoyoo.com/ja/2015/03/21/dht11-temperature-and-humidity-sensor/)
- [ブレッドボード](http://akizukidenshi.com/catalog/g/gP-00315/)
- [JPワイヤー](http://www.marutsu.co.jp/pc/i/69682/)
- 10kΩ抵抗

# Setup Flow / Links
- [#1 Raspberry pi 初期設定](http://qiita.com/Satoshi_Numasawa/items/9cfb07124d24c3701362)
- [#2 Raspberry pi / sensor 配線](http://qiita.com/Satoshi_Numasawa/items/3350d61fef10650f757d)
- [#3 AWS IoT 設定](http://qiita.com/Satoshi_Numasawa/items/bccf813325ddba7e549e)
    - [#3.1 AWS Lambda 設定](http://qiita.com/Satoshi_Numasawa/items/f8ededa17c1f3ad2d6e1)
- [#4 AWS IoT Device SDK for Ruby script作成](http://qiita.com/Satoshi_Numasawa/items/41c4011cdce633398ba7)
- [#5 Influx DB構築](http://qiita.com/Satoshi_Numasawa/items/e11826c8d7b1707d8428)
- [#6 Chronograph にて可視化](http://qiita.com/Satoshi_Numasawa/items/a4452cce3010af9570f3)




# 簡易構成図
![スクリーンショット_2016-06-24_15.00.35.png](https://qiita-image-store.s3.amazonaws.com/0/118627/ff34c3c9-f216-5346-2bca-4d52c747a099.png)




# 各種Toolの参考SS
## InfluxDB
![スクリーンショット 2016-10-07 14.22.34.png](https://qiita-image-store.s3.amazonaws.com/0/118627/7f0852b6-4ec5-2a07-7880-ad02e775e64f.png)




## Chronograph sample
<img width="1440" alt="sample-dashboard.png" src="https://qiita-image-store.s3.amazonaws.com/0/118627/25e7b179-870e-45b4-be69-0906679a1db9.png">




## Chronograph 温度/湿度 表示
![スクリーンショット 2016-10-07 14.25.53.png](https://qiita-image-store.s3.amazonaws.com/0/118627/183bddaf-5fd7-0dc4-2003-243284d2a379.png)
GAEでCloudVisionAPIを使ったら案外簡単だった（golang）


とりあえずCloudPlatformの管理画面に行って、VisionAPIを有効にする。

認証情報を追加しようとすると
![スクリーンショット 2016-10-07 17.04.10.png](https://qiita-image-store.s3.amazonaws.com/0/61976/f936949e-ea54-f717-1495-88aa37e95a1d.png "スクリーンショット 2016-10-07 17.04.10.png")

![スクリーンショット 2016-10-07 17.04.34.png](https://qiita-image-store.s3.amazonaws.com/0/61976/7d79ed7d-dc45-c497-e817-24f7532a3e8e.png "スクリーンショット 2016-10-07 17.04.34.png")


なるほど、GAE、GCE内だと認証いらないのか。

Golangだからgo getしてimportする。

```go
	"golang.org/x/oauth2/google"
	"golang.org/x/net/context"
```

GCE、GAE外だとJsonファイルを読み込んでOAuth2の認可を付与したHTTPクライアントを作らないといけないけど、GCE、GAE内だとgoogle.DefaultClientでいいみたい。

```go
// cはGAEのコンテキスト
client, err := google.DefaultClient(c, vision.CloudPlatformScope)
```

実際リクエストを送るfunc全体。（今回はLABEL_DETECTION）

```go
func RequestVisionApi(c context.Context,imgData []byte) (string ,error) {
	enc := base64.StdEncoding.EncodeToString(imgData)
	img := &vision.Image{Content: enc}
	feature := &vision.Feature{
		Type:       "LABEL_DETECTION",
		MaxResults: 10,
	}

	req := &vision.AnnotateImageRequest{
		Image:    img,
		Features: []*vision.Feature{feature},
	}
	batch := &vision.BatchAnnotateImagesRequest{
		Requests: []*vision.AnnotateImageRequest{req},
	}

	client, err := google.DefaultClient(c, vision.CloudPlatformScope)
	if err != nil {
		return "", err
	}

	service, err := vision.New(client)

	res, err := service.Images.Annotate(batch).Do()
	if err != nil {
		return "", err
	}

	// てきとーに使いたい形に整形する。
	s := ""
	for _,annotation := range res.Responses[0].LabelAnnotations {
		s = fmt.Sprintf("%s\n%s:%d％",s ,annotation.Description, int(annotation.Score * 100.0))
	}
	s = strings.TrimPrefix(s, "\n")
	return s, nil
}
```

# 使ってみた
はやりのLINE Botで使うとこんな感じ。
![CuJtgdxVIAAINkR (1).jpg](https://qiita-image-store.s3.amazonaws.com/0/61976/85a027f9-7bfa-2857-ed4f-92ff40f6061f.jpeg "CuJtgdxVIAAINkR (1).jpg")

よしよし、カレーだな
Atomでディレクトリ指定で検索する

Atomを使ってて、開いているプロジェクトのディレクトリの数が膨大だったりすると、目的のファイルにたどり着くまでにえらい時間がかかってしまうので、うまい具合にファイルを検索するツールはないものかと思って探しました。

# 要件
1. ファイル名ではなくディレクトリを名で検索できる
2. 現在開いているプロジェクトをデフォで指定してくれたら尚可

# インストールしたパッケージ
advanced-open-file
https://atom.io/packages/advanced-open-file


これ。

インストール後、alt+cmd+o で検索窓を開くと、デフォルトで開いているプロジェクトが指定されていて、パスをガシガシ指定って配下にあるファイル行事してくれるのでなかなかいい感じ。
KDE ウインドウテーマでウインドウリサイズエリアを修正する

いい感じのテーマが見つかり
いざ適用したところリサイズエリアの判定エリアが1pxとシビアになっていて修正した事があったので覚書しておく。

### テーマの設定ファイルの場所
~/.local/share/aurorae/themes/{テーマ名}/{テーマ名}rc

### 判定エリアの修正
```
[Layout]
BorderBottom=1
BorderLeft=1
BorderRight=1
BorderTop=1
```
という記述があるので好きな幅へ変更する
c++ builder > link > TDateTime型の分解能 / Now() > Although TDateTime values can represent milliseconds, Now is accurate only to the nearest second.

```txt:対象環境
C++ Builder XE4
```

以下を見つけた。

http://stackoverflow.com/questions/14573617/how-accurate-is-delphis-now-timestamp

> answered Jan 29 '13 at 0:54
> jachguateさんの引用
> Although TDateTime values can represent milliseconds, <font color=red>Now is accurate only to the nearest second</font>.

Now()を使う限りはsecondオーダーの精度になるということか?
PaperTrailをrspecで確認する

paperTrailの挙動をrspecで確認しようとしたらうまくうごかなくてはまったのでメモ。
普通に書くとPaperTrail動かないっす。

# rails_helper.rbにライブラリを追加
```:rails_helper.rb
# spec/rails_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
...
require 'paper_trail/frameworks/rspec' #<-これを追加
```

# テストをwith_versioningのブロックでかこむ
```:test_spec.rb
RSpec.describe V1::Admin::VersionsController, autodoc: true do

  describe "GET #index" do
    with_versioning do
      it "normal" do
        get "v1/admin/versions"
        expect(last_response.status).to eq(200)
      end
    end
  end

end

```

以上

# 参考
https://github.com/airblade/paper_trail#7b-rspec
Facebook ログインが急にエラーになった時の対応

Facebookログインが、何もしていないのに気づいたら動かなくなっていた。
FacebookのAPIを実行すると以下のようなエラーメッセージが。

```
{
    "error": {
        "message": "URLを読み込めません: このURLのドメインはアプリのドメインに含まれていません。このURLを読み込むには、アプリ設定のアプリドメインにすべてのドメインとサブドメインを追加してください。",
        "type": "OAuthException",
        "code": 191,
        "fbtrace_id": "XXXXXXXXXX"
    }
}
```

アプリドメイン設定変えてないし、確認してもやっぱり入っているし、よくわからなかったのでFacebookに問い合わせ。
そしたら、翌日以下の返信。

> Please add your redirect_uri to the Valid OAuth redirect URIs. It is under the menu Facebook Login > Settings in your app dashboard.

Facebookアプリのダッシュボードに**「Facebookログイン」**メニューがあって、開くと**「有効なOAuthリダイレクトURI」**という設定項目があった。見落としてた・・・、最近追加された？
確かに、設定入っていなかったので、リダイレクト先のURIを追加したら、すぐ動くようになった。

> I'm sorry for the misleading error message which is on our radar.

そうなんじゃないかと思ってたよ。
【PHP】Carbonで日曜日(週の最初)の日付を取得する

[Carbon - A simple PHP API extension for DateTime.](http://carbon.nesbot.com/)

Carbonのデフォルトでは週の最初は月曜日に設定されているので`startOfWeek()`を使うと月曜日の日付が返ってくる
日曜日の日付を取得したいときに困ったので調べてみた

### 方法1: 1日引く
デフォルトで月曜日が返ってくるわけなので`startOfWeek()->subDay(1)`と1日引くことで日曜日の日付が取得できる

```php
$dt = Carbon::today(); // 2016-10-07 00:00:00
$dt->startOfWeek(); // 2016-10-03 00:00:00
$dt->startOfWeek()->subDay(1); // 2016-10-02 00:00:00
```

### 方法2: 週の最初を日曜日に設定する
`setWeekStartsAt()`にint(0-6)を渡すとその曜日を週の最初にしてくれる
Carbonでは定数として`SUNDAY`が 0 に設定されているので`setWeekStartsAt(Carbon::SUNDAY)`とすれば`startOfWeek()`は日曜日の日付を返してくれる
週末がデフォルトで日曜日になっているので、一緒に`setWeekEndsAt(Carbon::SATURDAY)`と週末を土曜日に設定しておくと良い

```php
Carbon::setWeekStartsAt(Carbon::SUNDAY); // 週の最初を日曜日に設定
Carbon::setWeekEndsAt(Carbon::SATURDAY); // 週の最後を土曜日に設定
$dt = Carbon::today(); // 2016-10-07 00:00:00
$dt->startOfWeek(); // 2016-10-02 00:00:00
$dt->endOfWeek(); // 2016-10-08 23:59:59
```

一回だけ取得するなら方法1、何度も取得するなら方法2が良いんじゃないかなと思うけどやりやすい方使えばいいと思う
[Jenkins][Ubuntu] UbuntuにJenkinsをインストール

UbuntuにJenkinsのインストールをする方法メモ

基本的には、公式のWikiを参照して下さい
Ubuntu12.04, 14.04, 16.04では動作確認済みです

[Installing Jenkins on Ubuntu - Jenkins - Jenkins Wiki](https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Ubuntu)

```console:jenkinsのインストール(apt)
$ wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
$ sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
$ sudo apt-get update
$ sudo apt-get install jenkins
```

インストール後は `localhost:8080` でアクセスして下さい

# 初回起動後の手順
## 初期パスワードの入力

画面中央に表示されているパスのファイルに初期パスワードが記載されているので、確認して入力

![1.png](https://qiita-image-store.s3.amazonaws.com/0/37721/dffe1e1a-03c8-d990-e94b-232b62cdead8.png)

## pluginのインストール

おすすめのプラグインを入れるか、選択するかの２択。今回はおすすめのプラグインを入れる方（左）を選択。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/37721/bfdb3209-423b-8420-d0f7-75e4182255fc.png)
![3.png](https://qiita-image-store.s3.amazonaws.com/0/37721/df2fd3c7-4ca1-a61c-c353-4de805898475.png)

## admin user の作成

フォームに沿って、admin user を作成して下さい。

![4.png](https://qiita-image-store.s3.amazonaws.com/0/37721/0939fa27-9025-2def-f4b8-ca23d64d3269.png)

これでインストールは完了です。

![5.png](https://qiita-image-store.s3.amazonaws.com/0/37721/ad953405-668e-979e-9ba1-c6edbfb261eb.png)
![6.png](https://qiita-image-store.s3.amazonaws.com/0/37721/00e647ed-64e2-0610-9966-5227f9ed5ced.png)

# 関連
[[Jenkins] Windows7にJenkinsをインストールする方法まとめ - Qiita](http://qiita.com/koara-local/items/5fea213a9cf7033a95c1#2-jenkins%E3%81%AE%E5%88%9D%E6%9C%9F%E8%A8%AD%E5%AE%9A)
VimをちょっとだけEmacsキーバインドに近づけるための.vimrc

Vimでインサートモードに入ったときにEmacsキーバインドでカーソル移動ができるようにするための.vimrcの設定を記す。

この.vimrcは、本当に最低限のカーソル移動ができるようにするためのものである。これ以上Emacsに近づけると、EmacsユーザがEmacs使えよって言ってきて面倒な宗教戦争談話に巻き込まれるので絶対にやめておこう！絶対にだ。

この.vimrcでできることは以下の通り:

| キーバインド | 動作                                       |
|:-------------|:-------------------------------------------|
| Ctrl-p       | カーソルを上の行へ移動                     |
| Ctrl-n       | カーソルを下の行へ移動                     |
| Ctrl-b       | カーソルを左の行へ移動                     |
| Ctrl-f       | カーソルを右の行へ移動                     |
| Ctrl-a       | カーソルを行の先頭へ移動                   |
| Ctrl-e       | カーソルを行の末尾へ移動                   |
| Ctrl-d       | カーソルの右の文字を削除                   |
| Ctrl-h       | カーソルを左の文字を削除                   |
| Ctrl-k       | 現在のカーソル位置から行末尾までを切り取り |

```vim:.vimrc
" insert mode
imap <C-p> <Up>
imap <C-n> <Down>
imap <C-b> <Left>
imap <C-f> <Right>
imap <C-a> <C-o>:call <SID>home()<CR>
imap <C-e> <End>
imap <C-d> <Del>
imap <C-h> <BS>
imap <C-k> <C-r>=<SID>kill()<CR>

function! s:home()
  let start_column = col('.')
  normal! ^
  if col('.') == start_column
  ¦ normal! 0
  endif
  return ''
endfunction

function! s:kill()
  let [text_before, text_after] = s:split_line()
  if len(text_after) == 0
  ¦ normal! J
  else
  ¦ call setline(line('.'), text_before)
  endif
  return ''
endfunction

function! s:split_line()
  let line_text = getline(line('.'))
  let text_after  = line_text[col('.')-1 :]
  let text_before = (col('.') > 1) ? line_text[: col('.')-2] : ''
  return [text_before, text_after]
endfunction
```

以下の通り、Plugin化した。
[vim-emacs-bindings](https://github.com/kentarosasaki/vim-emacs-bindings)
もっとも簡単な、PyQtGraphのお試し法

投げ出す前に、是非、こちらもチェックされたし。
[PyQtGraphが、インタプリターで使用できない事がある。](http://qiita.com/yozi/items/cbbeb31e05031a101607)

# コマンドライン（もしくは端末）から一行で
`python -m pyqtgraph.examples`と入力すれば、コマンドラインから一行でexampleランチャーが出てきます。
（[PyQtGraphのREADME.mdのDocumentation](https://github.com/pyqtgraph/pyqtgraph#documentation)に書いてありました。）

 `python -m hoge.hogehoge`は、hoge.hogehoge.pyというモジュールを実行するコマンドです。[（Python 2.7.x ドキュメント）](http://docs.python.jp/2/using/cmdline.html#cmdoption-m)
モジュール名なので、拡張子の.pyを書いてはいけません。
## PyQtGraphで、どんなことができるのか
このランチャーは、適当に選択肢からクリック→左下の`Run example`を押下すれば、PyQtGraphを使って**「どんなことが」**できるかが分かります。
![20161007-2.png](https://qiita-image-store.s3.amazonaws.com/0/137888/240dd615-b739-53ef-914a-b3603eca3321.png)
## どうやったらできるのか
どんなことができるかだけでなく、**「どうやって」**できるのかがランチャーの右側部分に表示されています。
ランチャー右側部分には、今選択しているPｙQtGraphを使ったグラフの、pythonのコードが表示されます。
このコード表示は、PySide、PyQt4、PyQt5（Qt Libraryの種類）別に用意されていて、`Qt Library`と書いてある右側のCombo boxから変えることができます。

# pythonのインタプリタから
[Python PySideで作ったGUIにMatplotlibを埋め込んでみた（以前の記事のMatplotlib版）](http://qiita.com/yozi/items/da3c63644abc8e8d12e9#%E8%A8%B3)に、書いてみました。
（Matplotlibの内容ですが、結局PyQtGraphが好きみたいな内容になっています。）


```pycon
import pyqtgraph.examples
pyqtgraph.examples.run()
```
とすると同様にできますが、インタプリターの起動も含めると3行かかります。
CentOS7にPostgreSQL9.6をyumで、インストール

#コマンドラインで、PostgreSQL9.6をインストール
1.
wget https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-6-x86_64/pgdg-centos96-9.6-3.noarch.rpm
2.
rpm -ivh pgdg-centos96-9.6-3.noarch.rpm
3.
yum -y install postgresql96-server postgresql96-devel postgresql96-contrib
4.　**initdbの実行**
/usr/pgsql-9.6/bin/postgresql96-setup initdb --no-locale
/usr/pgsql-9.6/bin/postgresql96-setup initdb --locale=C
/usr/pgsql-9.6/bin/postgresql96-setup initdb --encoding=UTF8 --no-locale
/usr/pgsql-9.6/bin/postgresql96-setup initdb --encoding=UTF-8 --locale=ja_JP.UTF-8
オプションをつけると、エラーになる。(記述が間違っている??)

**/usr/pgsql-9.6/bin/postgresql96-setup initdb**
**はOK。**
5.　パスワードを設定
passwd postgres
6.　PostgreSQLの起動
systemctl start postgresql-9.6
systemctl enable postgresql-9.6

systemctl restart postgresql-9.6　

7.　confを編集し、接続許可
vi /var/lib/pgsql/9.6/data/pg_hba.conf

**pg_hba.confの編集で、下記を試したが、trust以外は、pgadminⅢから、接続できませんでした。**
**host    all             all             192.168.24.0/24         trust**
以下は、エラー
host    all             all             192.168.24.0/24         md5
host    all             all             192.168.24.0/24         password
host    all             all             192.168.24.0/24         krb5
host    all             all             192.168.24.0/24         ident
host    all             all             192.168.24.0/24         cert

***
詳細な手順と画面は、こちら、http://a23.sblo.jp/article/177152049.html
ghqユーザー向け。同じorganization配下のリポジトリを横断検索するスクリプト

[ghq](https://github.com/motemen/ghq)を使っている人向けの、同じorganization配下にあるリポジトリを横断検索するためのスクリプトを書きました。
僕みたいにマイクロサービスでつらい思いしている方などはどうぞ使ってください。

```bash:~/.zshrc
rgrep() {
  for repo in $(ghq list); do
    # organization_nameを書き換えてください
    if [[ $repo =~ .*organizaiton_name.* ]]; then
      # リポジトリ名を色をつけて表示
      printf '\e[1;34m%-6s\e[m' $repo
      echo
      (cd $(ghq root)/$repo; git grep $1)
      echo
    fi
  done
}
```
MySQLのチューニングについて

# MySQLのSELECT時にORDER　BYを使用した時のソートの話

テーブルにINDEXが貼られている事が前提ですが、
例えば３テーブルを結合し、ソートをかける時などに、
全てのテーブルの結合を行った後にマスターとなるテーブルで並び替えると、
Using filesortが発生し、SELECTの実行が遅くなる場合があります。

回避方法として、カラムの表示用のマスターテーブルと、ソート用に使うマスターテーブル(別名付け)を用意し
用途を分けたSELECT文にするなどがあります。

#sample.sql
>SELECT
　　tbl1.col1,
　　tbl2.col2,
　　tbl3.col3
FROM
　　tbl1,tbl2,tbl3
INNER JOIN
　　tbl1 AS tbl4 ON tbl1.col1 = tbl4.col1
WHERE
　　tbl1.col1 = tbl2.col1
AND
　　tbl2.col1 = tbl3.col1
ORDER BY tbl4.col1;

# LIMIT句とORDERBYについて
次のようなクエリにて
>SELECT col1, col2 ... colx FROM tbl1 WHERE ...略... ORDER BY col1 LIMIT 10;

col1のINDEXが有効でない場合、tbl1の全データをソートした後に
Limitの10行だけを返すような挙動になります。

col1にINDEXが有効な場合は、tbl1のデータ件数に関わらずに
Limitの10行だけを返却する為、全データソートは行われません。

#WHERE句とソートについて
複数テーブル結合のソートを行う場合は、
ORDER BY句にてINDEXが貼られたカラムをWHERE句で使用しない事（または同名テーブルとして分けるなど）を意識するとクエリ速度が上がる場合があります。

上記の例sample.sqlなどではtbl1のcol1が主キーだった場合、
ORDER BYではtbl4(tbl1の別名テーブル)を指定し、WHERE句での絞り込みと
ソート時の使用カラムを分けるなどを行っています。

#IN句、NOT IN句について
サブクエリの問い合わせとして、INを使用している場合限定ですが、
IN句をEXISTSにて表現するとINDEXが有効のままサブクエリへ問い合わせが通ります。
（早くなる可能性がある。）
ただし、サブクエリでなくIN句の中を指定している場合（...IN ('A','B')等）は
EXISTSにすると逆に遅くなったります。

また、サブクエリのIN句の表現はEXISTSに置き換える事ができますが、
NOT IN句は必ずしもNOT EXISTSに置き換える事は出来ません。

#実行計画について
大体のクエリツールなどで実行計画を見る時、
SQLの頭にEXPLAIN を付けるとそのクエリの解析が行われます。

チューニング時に着目しやすい部分として、typeフィールドがあります。
typeフィールドは対象テーブルにどのようにアクセスしているかを
現す項目で、遅いクエリを解析するとALLや、index(カラムINDEXではない)などで
何十万レコードを持つテーブルにアクセスしていたりします。

フィールド内容の種類は
>・const・・・PRIMARY KEYまたはUNIQUEインデックスのルックアップによるアクセス。最速。
・eq_ref・・・JOINにおいてPRIARY KEYまたはUNIQUE KEYが利用される時のアクセスタイプ。
　constと似ているがJOINで用いられるところが違う。
・ref・・・ユニーク（PRIMARY or UNIQUE）でないインデックスを使って等価検索
　（WHERE key = value）を行った時に使われるアクセスタイプ。
・range・・・インデックスを用いた範囲検索。
・index・・・フルインデックススキャン。インデックス全体をスキャンする必要があるのでとても遅い。
・ALL・・・フルテーブルスキャン。インデックスがまったく利用されていないことを示す。

などがあります。

実行計画は、表示項目の上から順に絞り込みを行なっていきます。

例：）
第１：実行計画 range・・・1000rows
第２：実行計画 const・・・300rows
第３：実行計画 range・・・20rows

第1→第2→第3の順に該当レコードの絞り込みを行うので、
同様の順序で上からレコードの絞り込みが徐々に減っているようなクエリが方が速いと言えます。

#まとめの様なもの
・SELECTでマスターに対して複数結合をして、ORDER　BYにてマスターカラムを指定する場合
 同名をつけてWHERE句などで使用しているマスターのカラムと、ORDER　BY句で使用するカラムを分けると
 早くなる時がある。

・LIMITとORDER　BYを使用する場合はORDER　BY句の指定カラムのINDEXが有効かを意識する
 (ORDER　BYにて複数カラム指定されていた場合は、全部のINDEXが有効でないとダメだったかも・・・？)

・サブクエリ問い合わせでIN、NOT IN句を使用している場合はEXISTSに置き換えるとINDEXが有効になる事がある。
 (サブクエリでない場合はIN句の方が速い)

・実行計画は上から順に解析され、const（最速）>eq_ref>・・・・ALL(最低)の順となっている

#参考URL
漢のコンピューター道様：http://nippondanji.blogspot.jp/2008/12/2008.html
PHPでシリアライズ化されたデータをコマンドラインでJSONにするワンライナー

いつも忘れるのでメモ。

```php
cat /tmp/serialized | php -R 'echo json_encode((unserialize($argn)));' | jq .
```


- 最初からシリアライズ化なんてしないで、KVSなりDBに入れろ
- せめてJSONで保存しろ

というツッコミがありますが、まあたまにあるので。
Ubuntu 14.04 > gfortranのインストール > E: Unable to locate package gfortran の対応

```txt:動作環境
Ubuntu 14.04 LTS desktop amd64
```

Ubuntu 14.04は試用の目的で、VMwareにて簡易インストールでインストールしてみた。

次にgfortranをインストールしようとした。

参考 http://qiita.com/HirofumiYashima/items/6f4c69dfea0ea79707ec

`sudo apt-get install gcc g++ gfortran`実行時に以下のエラーがでた。　

> E: Unable to locate package gfortran

以下を見つけた。
http://askubuntu.com/questions/292721/problem-installing-gfortran

`Community-maintained free and open-source software'のチェックはついていた。

以下を実行した。

```
sudo apt-get update && sudo apt-get upgrade
```

上記により140MBほどのダウンロードを実施。

```
sudo apt-get install gfortran
```
にてgfortranをインストールできた。
Premakeで「リモートWindowsデバッガー」を利用するように設定

# Premake
cmakeみたいな自動プロジェクトファイル構成システム
https://github.com/premake/premake-core/wiki

参考：
[ビルドツールpremakeの紹介](http://qiita.com/ousttrue/items/6d837d6daba47b51bd8e)
[Premakeで「追加の依存ファイル」を設定する](http://qiita.com/sukakako/items/b1e94f40028deaf126fc) 

# 環境
Windows 7
Visual Studio 2012
Premake 5.0 alpha 9

# VisualStudio2012 でデバッグ > 「リモートWindowsデバッガー」を設定する
premake5.luaで [debugremotehost](https://github.com/premake/premake-core/wiki/debugremotehost) を指定しても、
「ローカルWindowsデバッガー」が変更されない。
([このあたり](https://github.com/premake/premake-core/blob/master/src/actions/vstudio/vs2010_vcxproj_user.lua)を見ても、WindowsLocalDebugger としか記述がない。)

なので、premake.vc2010.elements の "user" の処理を上書きする。


```lua:premake5.lua

local p = premake
p.override(p.vstudio.vc2010.elements, "user", function(base, cfg)
    -- configurations 毎に呼び出しされる
    local calls = base(cfg)

    -- \ をそのまま出力したいので [[ ]] で文字列を設定
    p.x([[<RemoteDebuggerCommand>\\192.168.0.1\$(TargetFileName)</RemoteDebuggerCommand>]])
    p.x([[<RemoteDebuggerServerName>192.168.0.1</RemoteDebuggerServerName>]])
    p.x([[<DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor>]])

    -- return calls
end)

workspace "sample"
  location "build_premake"
  configurations { "Debug", "Release" }

  project "sample"
    kind            "ConsoleApp"
    language        "C++"
    targetdir       "build_premake/%{cfg.buildcfg}"
    files           { "src/**.h", "src/**.cpp", }

```

＜RemoteDebuggerCommand＞や＜DebuggerFlavor＞の設定値は、
手動で実現したい設定にしておき、そのあと *.vcxproj.user をテキストエディタで開いて確認した。

# あるluaファイルがある場合のみ設定を追加する
ターゲットによってリモートWindowsデバッガーの設定を変更したいので、
デバッガの設定を別ファイルに移動する。

```
├─ src
│   └─ main.cpp
├─ premake5.exe
├─ premake5.lua
└─ local.lua
```

上記のような構成の場合に、local.luaにデバッガの設定を記述しておき、
local.luaがある場合はそれを読み込む。
ない場合はデバッガの設定を変更しない、というようにpremake5.luaを修正する。

```lua:local.lua

local p = premake
p.override(p.vstudio.vc2010.elements, "user", function(base, cfg)
    -- configurations 毎に呼び出しされる
    local calls = base(cfg)

    -- \ をそのまま出力したいので [[ ]] で文字列を設定
    p.x([[<RemoteDebuggerCommand>\\192.168.0.1\$(TargetFileName)</RemoteDebuggerCommand>]])
    p.x([[<RemoteDebuggerServerName>192.168.0.1</RemoteDebuggerServerName>]])
    p.x([[<DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor>]])

    -- return calls
end)

-- ついでにビルド後イベントで実行ファイルをコピー
filter "configurations:*"
  postbuildcommands { [[xcopy "$(Configuration)" "\\192.168.0.1\" /Y /Q]] }
filter {}

```

```lua:premake5.lua
workspace "sample"
  location "build_premake"
  configurations { "Debug", "Release" }

  project "sample"
    kind            "ConsoleApp"
    language        "C++"
    targetdir       "build_premake/%{cfg.buildcfg}"
    files           { "src/**.h", "src/**.cpp", }
    -- 一応フィルターをクリア
    filter {}

    -- local.luaのファイルがあれば読み込んで実行
    local fh = io.open("local.lua", "rb")
    if fh then
      fh:close()
      includeexternal("local.lua")
    end

```

参考：
[Luaで良く作る関数 ～io編～](http://lua.tips/index.php?Lua%20implements_func_io)
ng-contentを使ってみる

# ng-contentとは

componentの中に外から要素を注入したいときに使います。angular1でいうところのngTranscludeに近いですね。

## とりあえず子要素を注入してみる

とりあえず子要素を突っ込むには、突っ込みたい位置に`<ng-content></ng-content>`を置きます。それだけです。

```ts
@Component({
  selector: 'foo',
  template: `
    <ng-content></ng-content>
  `,
})
export class Foo {
  
}
```

```html
<foo>
  <div>hello</div>
</foo>
```

## 複数の要素を入れたいところに入れる

あれはここ、それはこっちに配置したいみたいなのをやりたければ`<ng-content select="...">`を使います([DEMO](http://plnkr.co/edit/ZIsCJB?p=preview))。

```ts
@Component({
  selector: 'bar',
  template: `
    <section>
      <h3>tag selector(foo)</h3>
      <ng-content select="foo"></ng-content>
    </section>
    <section>
      <h3>tag selector(main, aside)</h3>
      <ng-content select="main"></ng-content>
      <ng-content select="aside"></ng-content>
    </section>
    <section>
      <h3>attribute selector</h3>
      <ng-content select="[hoge]"></ng-content>
    </section>
    <section>
      <h3>class selector</h3>
      <ng-content select=".hoge"></ng-content>
    </section>
    <section>
      <h3>others</h3>
      <ng-content></ng-content>
    </section>
    
  `,
})
export class Bar {
  
}
```

という風に定義して、使う側は以下のように書くと

```html
<bar>
  <main>Main text</main>
  <aside>description</aside>
  <div>other1</div>
  <div hoge>[hoge]</div>
  <div>other2</div>
  <foo>foo</foo>
  <div>other3</div>
  <div class="hoge">.hoge</div>
  <div>other4</div>
</bar>
```

それぞれの`<ng-content select="...">`に`select`に設定されたセレクターに対応した要素が配置されて、残りの要素は無印の`<ng-content></ng-content>`が置いてある場所に格納されていきます。ちなみに、`main`2つ置いたら2とも置かれました。

`select`で使えるセレクターは割と複雑なものが使えます。`div[hoge]:not(.foo)`みたいなのもいけました。多分ですが、これはdirectiveの`selector`で使えるものと同等かと思われます。

# 参考

[Transclusion in Angular 2 @toddmotto](https://toddmotto.com/transclusion-in-angular-2-with-ng-content)
ブログ記事はあるがなぜかangular.ioには全然ドキュメントがないんですよね…。
Cocoaの機能を使ってMacで押下されている装飾キーを取得するAppleScriptハンドラ


* ハンドラ呼び出し時に押下されている装飾キーを取得
	* System Eventsの予約語を使用して、次の4種類のキーをリストで返す
		* `shift down`
		* `control down`
		* `option down`
		* `command down`
* repeat行のリストを変更すればCaps Lockなど他のキー状況も取得可能
	* [Modifier Flags - AppKit](https://developer.apple.com/reference/appkit/nsevent/modifier_flags?language=objc)

```AppleScript:enteredModifiers.scpt
use scripting additions
use framework "AppKit"

delay 3 --この間に装飾キーを押下
my enteredModifiers()
--> {shift down, control down, option down, command down}

on enteredModifiers()
	--require framework: AppKit
	set modifierFlags to current application's NSEvent's modifierFlags()
	set modifierList to {}
	repeat with flag in {{modifierName:shift down, keyMask:current application's NSShiftKeyMask}, {modifierName:control down, keyMask:current application's NSControlKeyMask}, {modifierName:option down, keyMask:current application's NSAlternateKeyMask}, {modifierName:command down, keyMask:current application's NSCommandKeyMask}}
		if modifierFlags div (keyMask of flag as integer) mod 2 = 1 then
			set end of modifierList to modifierName of flag
		end if
	end repeat
	return modifierList
end enteredModifiers
```

## 更新履歴

* 2016-10-05: AppKitフレームワークのNSEventクラスを使って作成
VirtualBoxの共有フォルダを一般ユーザーで使う

http://vividcode.hatenablog.com/entry/virtualbox/shared_folder

共有ディレクトリのアクセス権は vboxsf ユーザーグループにのみ許可されています。 そのため、ゲスト OS 側の一般ユーザーから共有フォルダにアクセスしたい場合は、そのユーザーを vboxsf グループに追加する必要があります。

```bash
usermod -aG vboxsf user_name
```
SSIS:DTEXECを/Confオプション指定で実行しても設定が読み込まれない

DTEXECを/Confオプション指定で実行しても設定が読み込まれない場合があったのでメモ。

[dtexec ignoring Config file](https://social.msdn.microsoft.com/Forums/sqlserver/ja-JP/878dbf2b-6bb7-4d20-8f44-f598c272257d/dtexec-ignoring-config-file?forum=sqlintegrationservices)
> What we noticed was it first looks for the config filed defined in the package. if it finds that, it tries to use it. If not, it uses the one provided at the runtime through CONFIG parameter.

SSISのDTSXファイルは、DTSXに記述のdtsconfigファイルが存在しない場合、/Confオプションで指定したdtsconfigファイルを使用する。

逆に言えば、DTSXに記述のdtsconfigファイルが存在する場合、/Confオプションで指定してもその設定は読み込まれない。
Python Tools 2.2 for Visual Studio(PTVS2.2)でDjango

#Python Tools 2.2 for Visual Studioとは
2015年にリリースしたバージョンになります。VisualStudio上でPythonのIDEとしての機能を追加するためのプラグインです。PTVSはWebアプリケーションに限らずスタンドアロンのPythonアプリケーション開発でも利用が可能です。([参照](http://pyconjp2012-windows-azure-handson.azurewebsites.net/contents/cloudservices/install_ptvs.html))

#Visual Studio2015でDjango1.8を実行
PTVSを利用してDjangoをAzure上のデータベースなどと連携することができます。とりあえず、ここではWindows上でVisual Studio2015にDjango1.8を実行させます。
###Visual Studio2015 Communityのインストール
Visual Studio2015 CommunityをWindows上に[インストール](https://www.visualstudio.com/ja/downloads/)する。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/130097/f373845d-ba3e-d8a8-1ee9-1d509929abf9.png)
###Python Tools 2.2 for Visual Studio
[ここ](https://github.com/Microsoft/PTVS/releases/v2.2)でPTVSをインストールしてください。噂によるとVS2015では標準で入っているらしいです。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/130097/e798ec55-fa9d-6a28-daf9-fdadb13221d8.png)
###Visual Studio2015でDjangoプロジェクト作成
Visual Studioを実行し、
【Start】➡️【New Project...】➡️【Python/Web】➡️【Django Web Project】
Nameをつけて【OK】をしてプロジェクトを作成します。
 ![3.png](https://qiita-image-store.s3.amazonaws.com/0/130097/2cdcdaee-02cb-a2b6-d8e3-74b74c7e6d9d.png)

すると下のようになるので特に変更がなければ【Create】する。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/130097/b95d7ead-6714-67eb-4305-82ec648478b5.png)

最後に実行をすると自分であるとFirefoxが実行しDjangoの画面が開く
![5.png](https://qiita-image-store.s3.amazonaws.com/0/130097/d5550e79-00f9-5433-2317-ef4399ce49e9.png)

#Error
1.Create後に実行すると**cannot import name patterns**とエラーが起きて実行できない。
➡️pipでpatternsをインストールしてもうまくいかないので調べるとDjangoのバージョンがデフォルトだとDjango1.10になっているのでうまく行かなかった！

よって、【env（右クリック）】➡️【Install Python Package..】を選択し、
**django==1.8** (Linux: pip install django==1.8)と括弧内に入力することでDjango1.10をUninstallし、改めてDjango1.8を再インストールしてくれる。
![スクリーンショット 2016-10-07 13.38.50.png](https://qiita-image-store.s3.amazonaws.com/0/130097/f16dc3a0-88cc-131a-3288-a1b4fe815d43.png)
GoでSlackへ通知してみた

# 状況整理
## やりたいこと
- システムのアラートやチケットトラッカーの通知をSlackに集約したい。

## 現状
- 社内のSlackに通知できるものが少しずつ増えてきた
- 社内のSlackのメンバーも増えてきた

## 現状イメージ
![notice.001.png](https://qiita-image-store.s3.amazonaws.com/0/103906/a4a4dbee-2ab6-05fd-734b-9baf205e7686.png "notice.001.png")

## 問題
- SlackのIncoming WebHooksが増え続けて面倒だ
- 毎回Incoming WebHooksを登録するのは面倒だ

## 変えたいイメージ
![notice.002.png](https://qiita-image-store.s3.amazonaws.com/0/103906/f478d1fd-554f-c71d-baa6-4b2053c81e1a.png "notice.002.png")

### こんな時Slackに通知が欲しい
- Datadogで特定のメトリックが閾値超えた
- サーバサイドが503吐いた
- 定期バッチでこけた
- 本番サーバにrootで入られた。
などなど、ほぼリアルタイムで検知したい。

# やってみた。
## API Gatewayを作り、SlackのIncoming WebHooksに流す
![notice.003.png](https://qiita-image-store.s3.amazonaws.com/0/103906/df253074-bbc7-3df0-0167-d6eedabdeb04.png "notice.003.png")

## ついでにAPIキーを使ってアクセス制限もかけてみる。
![notice.004.png](https://qiita-image-store.s3.amazonaws.com/0/103906/80109f5d-f986-c8e8-9cd4-7a1a8c7eea43.png "notice.004.png")

## cURLで投げてみる。
```
curl -H 'x-api-key:[API_GATEWAY_KEY]' --data-urlencode 'payload={"channel": "#miyasue", "username": "きちゅね", "text": "テスト。", "icon_emoji": ":kityune:"}' https://[API_GATEWAY].execute-api.ap-northeast-1.amazonaws.com/prod
```

## 届いた。
![notice.005.png](https://qiita-image-store.s3.amazonaws.com/0/103906/857020c2-939c-2932-4ed8-89fbdd0d4fe2.png "notice.005.png")
無事届いた。

# ついでにGoで飛ばしてみたい
- Goは書いた事ない。
- Goを選んだのはクロスコンパイルに強いと聞いたから。（いろんな環境から手軽にSlack通知できるんじゃない？）
- 環境構築からビルドするまでそれほど時間はかからなかった。
- 実際にWin用とMac用にコンパイルしてみたが、上手く動いた。

```go
package main

import (
    "bytes"
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
    "os"
)

func main() {
    if len(os.Args) != 5 {
  		fmt.Println("引数: 本文 ユーザ名 チャンネル名 絵文字")
  		os.Exit(1)
  	}

    apiUrl := "https://[API_GATEWAY].execute-api.ap-northeast-1.amazonaws.com/"
    resource := "/prod"

    u, _ := url.ParseRequestURI(apiUrl)
    u.Path = resource
    urlStr := fmt.Sprintf("%v", u)

    payload := "{'text':'" +os.Args[1]+ "', 'username':'" +os.Args[2]+ "', 'channel':'" +os.Args[3]+ "', 'icon_emoji':'" +os.Args[4]+ "'}"
    data := url.Values{}
    data.Set("payload", payload)

    client := &http.Client{}
    r, _ := http.NewRequest("POST", urlStr, bytes.NewBufferString(data.Encode()))
    r.Header.Add("x-api-key", "[API_GATEWAY_KEY]")
    r.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    resp, _ := client.Do(r)
    defer resp.Body.Close()
    contents, _ := ioutil.ReadAll(resp.Body)

    fmt.Printf("result: %s\n", contents)
}

```


## テスト
```
./notice "Goからテスト" "きちゅねかわいい" "#miyasue" ":kityune:"
```
![notice.006.png](https://qiita-image-store.s3.amazonaws.com/0/103906/76df9419-a2f2-f3f5-2fe3-200c33ede9d0.png "notice.006.png")

無事届いた。
CloudfrontのCloudFront Cache Statistics Reportsで'Errors'が計測されたので調べた

# 前提的な話
* AWSのcloudfrontをかる〜く試していた
    * static file(CSS,JS,IMGとか)の配信で試してた
* 試している途中でコンソール画面（CloudFront Cache Statistics Reports）を眺めていたら`Error`がカウントされていた
* 説明をみてみると下記のように書いてる

> Error: A viewer request that resulted in an error, so CloudFront did not serve the object. In access logs, the value of x-edge-response-result-type is Error, LimitExceeded, or CapacityExceeded.

# ちょっと気になったので調べる
* cloudfrontのloging設定をonにしてs3バケットに出力させる
* そのログで`Error`となってるログをピックアップしてみてみる

```
2016-10-06	12:02:34	NRT53	462	IPが書かれてる	GET	****.cloudfront.net	/favicon.ico	403	リファラーが書かれている	Mozilla/5.0%2520(Macintosh;%2520Intel%2520Mac%2520OS%2520X%252010_11_6)%2520AppleWebKit/537.36%2520(KHTML,%2520like%2520Gecko)%2520Chrome/53.0.2785.116%2520Safari/537.36	-	-	Error	********	hostが書かれてる	https	199	0.043	-	ssl-cipherが書かれている	Error	HTTP/2.0
2016-10-06	12:03:22	NRT53	470	IPが書かれてる	GET	****.cloudfront.net	/favicon.ico	403	リファラーが書かれている	Mozilla/5.0%2520(Macintosh;%2520Intel%2520Mac%2520OS%2520X%252010_11_6)%2520AppleWebKit/537.36%2520(KHTML,%2520like%2520Gecko)%2520Chrome/53.0.2785.116%2520Safari/537.36	-	-	Error   ********	hostが書かれてる	https	240	0.004	-	ssl-cipherが書かれている	Error	HTTP/2.0
2016-10-06	18:03:07	SFO20	592	IPが書かれてる	GET	****.cloudfront.net	/robots.txt 	403	-	Mozilla/5.0%2520(compatible;%2520Googlebot/2.1;%2520+http://www.google.com/bot.html)	-	-	Error	********	hostが書かれている	https	227	0.440	-	ssl-cipherが書かれている	Error	HTTP/1.1
```
* アクセスログの形式に関しては下記参照
  * https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html

# 調べてみての結果
* そもそもcloudfront(=S3)に載せていないファイル(favicon.ico/robots.txt)にアクセスしようとしてhttp statusの403を返している
* もともとファイル無いし気にする事ではなかった
* 内部リンクでのfavicon.icoへのリンクは無いので、クローラー系かな or ブラウザとかの機能でfaviconとかにアクセスするのかなぁ？と想像
* x-edge-result-typeとx-edge-response-result-typeという項目があり、重要さに気づいた。下記の`注意`でまとめる

## 注意
* x-edge-result-typeとx-edge-response-result-typeのステータスの値
  * x-edge-result-type
      * 最終的な結果タイプ
  * x-edge-response-result-type
      * CloudFront がリクエストに応答し始める直前の結果タイプ
* んーまぁリクエストを投げて、ダウンロードを始める際のstatusとダウンロードし終わったときのstatusみたいなもんかな
* なんでこんな内訳をしているかと考えるとcloudfrontでストリーミング配信をした時とかにちゃんと最後まで配信できたかを計測する為かなと

# まとめ的なもの
* `http status`,`uri`,`x-edge-result-type`,`x-edge-response-result-type`の値を可視化しておいた方が安心
    * この4つの項目を一緒にみて、何か問題があるのかというジャッジができそう
* アクセスログを簡単に可視化する仕組みちょっと面倒いなー。でも地味に重要なんだよなーと思ったり
* favicon.icoとかrobots.txtとか置いておいた方が無難かもしれない
    * Errorカウントされてしまうし、気づかないといけない本来のErrorを見つけやすくするべきだし
ChefTips: ファイルをコピーする

サーバ上に存在する既存ファイルをコピーしたい時に。
IOクラスのreadメソッドを使います。

```rb:例
file '/tmp/example.txt.bak' do
  content IO.read('/tmp/example.txt')
  action :create
end
```

```rb:テスト
# cat <<_EOL_ | chef-apply -s -W
> file '/tmp/example.txt.bak' do
>   content IO.read('/tmp/example.txt')
>   action :create
> end
> _EOL_
Recipe: (chef-apply cookbook)::(chef-apply recipe)
  * file[/tmp/example.txt.bak] action create
    - Would create new file /tmp/example.txt.bak
```

## ポイント
- `content IO.read('/tmp/example.txt')`はコンパイル時に評価されます
- なので、`/tmp/example.txt` が存在しないとコンパイル時にエラーがでます。
- 例えば、`only_if { File.exists?("/tmp/example.txt") }` をつけても `No such file or directory @ rb_sysopen - /tmp/example.txt` が返る。
- `/root/copy.txt` のタイムスタンプはcopy時に更新される
- ファイルの中身を比べてくれるので、`/tmp/example.txt`が更新されていなければ、リソースは実行されない。タイムスタンプだけ更新しても同様。

参考/引用: [chefでファイルコピーするときにruby_blockは使わないでfileを使う(ファイルに更新がなければサービスの再起動しない)](http://qiita.com/imura81gt/items/77a1463cc9f41ef9c3c5)
【PHP】現在・一つ上・ホームディレクトリの位置を取得する

絶対PATHで取得。

```php
// 現在のディレクトリを取得
echo getcwd() . "\n";
// 現在の一つ上のディレクトリを取得
echo realpath("../") . "\n";
// ホームディレクトリを取得
echo posix_getpwuid(posix_geteuid())['dir'] . "\n";
```

## 参考リンク

[カレントのワーキングディレクトリを取得する](http://php.net/manual/ja/function.getcwd.php "カレントのワーキ
ングディレクトリを取得する")
[絶対パス名を返す](http://php.net/manual/ja/function.realpath.php "絶対パス名を返す")
[PHP でホームディレクトリを取得](http://qiita.com/NAKANO_Akihito/items/c1696236da4261a74e46 "PHP でホームディレクトリを取得")
Unityでシングルクリック（タップ）/ダブルクリック（タップ）のイベントを使い分ける


Unityで
・シングルタップするとオブジェクトを大きくする
・ダブルタップするとオブジェクトを小さくする
という極めて単純な処理を実装しようと色々調べましたが、
有償のアセットを購入しない限り、単純には実装できない模様ということが判明（調査が不足しているだけかもしれません）。

調べながらなんとか実装には成功したので、その手順をまとめます。
* * *
###まず最初に困ったこと。
Touch.tapCountやEvent.clickCountを使用すれば
タップされた回数は取得できるのですが、
冒頭に記載したようにシングルタップ、ダブルタップで処理を出し分けたい場合に

```cs
void OnGUI() {
    Event e = Event.current;
    if (Input.GetButtonDown ("Fire1")) {
        if (e.clickCount > 1) {
            オブジェクトを小さくする処理();
        } else {
            オブジェクトを大きくする処理();
        }
    }
```
のように記載すると、
シングルタップであれば
　１．オブジェクトが大きくなる処理を実行
でOKなのですが、
ダブルタップの場合に
　１．オブジェクトが大きくなる処理を実行
　２．オブジェクトが小さくなる処理を実行
と、ダブルタップの1回目で処理が即実行されてしまい、
求めた結果である「オブジェクトが小さくなる」になりませんでした
（1回大きくなり、1回小さくなり、結果元通りのサイズになってしまう）。
* * *
###対応
そこで調べた結果、「一定時間内にタップされた回数をカウントし、1回か2回以上かで処理を分ける」という実装に落ち着きました。
＃かなり探したのですが、Unityの標準ライブラリにはこのような処理が無さそうだったので。
実装例：

```cs
using UnityEngine;
using System.Collections;
public class TestClass : MonoBehaviour {
    public GameObject myObj; //サイズを変更する対象
    private bool isDoubleTapStart; //タップ認識中のフラグ
    private float doubleTapTime; //タップ開始からの累積時間
    // Update関数
    void Update () {
        // double tap
        if (isDoubleTapStart){
            doubleTapTime += Time.deltaTime;
            if (doubleTapTime < 0.2f) {
                if (Input.GetMouseButtonDown (0)) {

                    isDoubleTapStart = false;
                    ChangeSize (true);
                    doubleTapTime = 0.0f;
                }
            } else {

                 ChangeSize (false);
                 // reset
                 isDoubleTapStart = false;
                 doubleTapTime = 0.0f;
            }
        } else {
            if (Input.GetMouseButtonDown (0)) {

                isDoubleTapStart = true;
            }
        }
    }
    //シングルタップの場合は拡大、ダブルタップの場合は縮小するメソッド
    void ChangeSize (bool isDoubleClick) {
        float x = myObj.GetComponent<Transform> ().localScale.x;
        float y = myObj.GetComponent<Transform> ().localScale.y;
        float z = myObj.GetComponent<Transform> ().localScale.z;
        if (isDoubleClick) {
            transform.localScale = new Vector3 (x / 1.1f, y / 1.1f, z / 1.1f);
        } else {
            transform.localScale = new Vector3 (x * 1.1f, y * 1.1f, z * 1.1f);
        }
    }
}
```
myObjには拡大/縮小したいオブジェクトをHierarchyからドラッグして設定しておいてください。

![1.PNG](https://qiita-image-store.s3.amazonaws.com/0/114630/f72f4b64-d0ad-28eb-3f32-163a16b8e01f.png)


最初にタップされてから0.2秒間は待機し、その間に追加のタップがあれば
ダブルタップと判断して縮小処理を行います。
追加のタップが無ければシングルタップと判断し、拡大処理を行います。

Input.GetMouseButtonDown (0)でのイベント検知ですが、
Unity Gameビューでのマウスクリックも、Android端末上のタップも
いずれも問題なく動くことを確認済みです。
* * *
###参照した記事
[お手軽ダブルタップ Unity - 万年素人からGeekへの道](http://d.hatena.ne.jp/shinriyo/20131213/p2)
ROW_NUMBER vs OFFSET/FETCH - Pagination in SQL Server

# 目的：
SQLのPagingは後ろのページになるに連れて遅くなると聞いたので、どれだけ遅くなるのか試してみた。
参考サイトによると、SQL Server 2012ではROW_NUMBERの代わりにOFFSETが推奨されていたので、その点も含めて。

※実際に試してみたのは SQL Database (V12)。
参考：http://social.technet.microsoft.com/wiki/contents/articles/23811.paging-a-query-with-sql-server.aspx

データ量　：約250万件
取得データ：25万ページ目、10件/ページ


## ROW_NUMBERの場合：

![rownumber.jpg](https://qiita-image-store.s3.amazonaws.com/0/143520/9e5524b5-339b-7be6-a856-bb6bc1a5c7e1.jpeg)

Wait time on server replies (avg)：**617.0000 ms**


## OFFSETの場合：

![offset.jpg](https://qiita-image-store.s3.amazonaws.com/0/143520/2e93bc4b-5ef9-5e4d-826a-a0a3a3dc98cc.jpeg)

Wait time on server replies (avg)：**1410.6670 ms**

# 結果：
後半のページだと、OFFSETの方が2倍近く遅かった。

# 考察：
後半のページにも結構需要があって、厳しい性能が求められる場合はROW_NUMBERの方が良さそう。
ただSQLがシンプルになるし、やっぱりできればOFFSETを使いたい。

参考サイトでは、OFFSETの方がサーバーから受信するデータ量が減らせると有るけど、
それはその行が全体の何行目かという情報だと思うので、
不要ならSELECTしなければいいだけ。
むしろ必要な場合、OFFSETだと別途計算する必要がある。
Git でコミット前に禁止ワードが入っていないかチェックする

# はじめに

レビューをしていても動作確認していても入れちゃいけないコードがコミットされてしまうということがありますね。
自分でなんどかやらかしてしまっているので戒めのためにコミット前に禁止ワードが入っていないかチェックするフックを追加してみます。

# 参考ページ

http://qiita.com/niku4i/items/f39eb7d4d5c4f5c0775c
http://qiita.com/quattro_4/items/f9e0884f2efe7e8c033a

# フックのスクリプトを設置する

* `.git/hooks/pre-commit` に下記のスクリプトを設置してコミット前に禁止ワードが含まれていないかをチェックします。
* コードのフォーマッターなどすでに `pre-commit` が存在する場合は http://qiita.com/nirasan/items/41558a0fd903e01f263d を参考に追加してください。

```sh:.git/hooks/pre-commit
#!/bin/sh

if [ -e ~/.git_prohibited_words ]; then
    while read word; do
        # Skip comment or blank lines
        echo $word | grep ^# > /dev/null && continue
        echo $word | grep '^\s*$' > /dev/null && continue

        IFS=$'\n';
        for file in $(git diff --cached --name-only)
        do
            result=$(git diff --cached -U0 -- $file | grep -A5 -B5 -i "$word")
            if [ $? -eq 0 ]; then
                if [ -z $NO_WORD_CHECK ]; then
                    cat <<EOL

[WORD CHECK ERROR]

FILENAME:
    $file

PROHIBITED WORD:
    $word


$result


HINT:
    If you want to force commit, please append prefix 'NO_WORD_CHECK=1' to command.


EOL
                    exit 1
                else
                    exit 0
                fi
            fi
        done
    done < ~/.git_prohibited_words
fi
```

# 禁止ワードを設定する

* 禁止ワードは `~/.git_prohibited_words` に改行区切りで複数個設定できるものとし、下記のように設定します。

```sh
$ echo "prohibited word" >> ~/.git_prohibited_words
```

# 実行する

* 禁止ワード `defined prohibited word.` を設定してコミットに含めた場合、以下のような表示とともに `git commit` が失敗します。

```
[WORD CHECK ERROR]

FILENAME:
    path/to/filename

PROHIBITED WORD:
    defined prohibited word.


diff --git a/path/to/filename b/path/to/filename
index eb36957..511fd1a 100644
--- a/path/to/filename
+++ b/path/to/filename
@@ -6,0 +7 @@
+defined prohibited word.


HINT:
    If you want to force commit, please append prefix 'NO_WORD_CHECK=1' to command.
```

# 禁止ワード入りのコードをコミットする

* 禁止ワード入りのコードを強制でコミットさせたい場合は `NO_WORD_CHECK=1 git commit` と実行してください
yaml_vaultで階層化された特定のkeyのみを暗号化・復号化する方法

# yaml_vaultについて
[AWS Key Management Serviceを使ってconfigファイルを暗号化すると便利 - Qiita](http://qiita.com/joker1007/items/7f726852a5e7d1cdf974) を参照

# やりたかったこと
下記のようなyamlがあった時に、`access_key_id` と `secret` のみを暗号化・復号化し、それ以外のkeyはそのまま保存したかった。

```yaml:accounts.yml
accounts:
  ACCOUNT_1:
    access_key_id: XXXXXXX
    secret: XXXXXXXX
    regions:
      - ap-northeast-1

  ACCOUNT_2:
    access_key_id: XXXXXXX
    secret: XXXXXXXX
    regions:
      - ap-northeast-1
```

`--key=accounts` で渡すと `access_key_id` と `secret` だけでなく `regions` も暗号化されてしまうので困りもの。

このissueに近かったのでPR投げようかと思ったのですが、コードを読むと思った以上に面倒くさそうだったので別のやり方で解決しました。

[Wildcards in `--key` · Issue #4 · joker1007/yaml_vault](https://github.com/joker1007/yaml_vault/issues/4)


# 解決策
yaml_vaultは暗号化対象のkeyをカンマ区切りで複数渡せるので下記のようにrake taskで必要なkeyを生成してからyaml_vaultに渡すようにしました。

```ruby:lib/tasks/vault.rake
namespace :vault do
  require "yaml"

  region = "ap-northeast-1"

  def vault_keys(yaml_file)
    config = YAML.load_file(yaml_file)
    account_keys = config["accounts"].keys
    account_keys.each_with_object([]) do |key, array|
      array << "accounts.#{key}.access_key_id"
      array << "accounts.#{key}.secret"
    end.join(",")
  end

  desc "encrypt accounts.yml and generate encrypted_accounts.yml (params: SRC_FILE, DST_FILE)"
  task :encrypt do
    kms_key_id = "XXXXXXXXXXXXXX"
    src_file = ENV["SRC_FILE"] || "config/accounts.yml"
    dst_file = ENV["DST_FILE"] || "config/encrypted_accounts.yml"
    keys = vault_keys(src_file)
    sh "AWS_REGION=#{region} yaml_vault encrypt #{src_file} -o #{dst_file} --cryptor=aws-kms -k #{keys} --aws-kms-key-id=#{kms_key_id}"
  end

  desc "decrypt encrypted_accounts.yml and generate accounts.yml (params: SRC_FILE, DST_FILE)"
  task :decrypt do
    src_file = ENV["SRC_FILE"] || "config/encrypted_accounts.yml"
    dst_file = ENV["DST_FILE"] || "config/accounts.yml"
    keys = vault_keys(src_file)
    sh "AWS_REGION=#{region} yaml_vault decrypt #{src_file} -o #{dst_file} --cryptor=aws-kms -k #{keys}"
  end
end

```

`AWS_REGION` を環境変数で渡しているのはIAMロールを使いたかったためです [^region]

[^region]: 詳しく実装を追ってないですが `--aws-region` を渡すと `--aws-access-key-id` と `--aws-secret-access-key` も必要になってIAMロールを使ってくれない模様

## 実行結果

```shell-session
$ bundle exec rake vault:encrypt
AWS_REGION=ap-northeast-1 yaml_vault encrypt config/accounts.yml -o config/encrypted_accounts.yml --cryptor=aws-kms -k accounts.ACCOUNT_1.akid,accounts.ACCOUNT_1.secret,accounts.ACCOUNT_2.akid,accounts.ACCOUNT_2.secret --aws-kms-key-id=XXXXXXXXXXXXXX
encrypted config/accounts.yml -> config/encrypted_accounts.yml
```

よさげ
Docker上でcronを動かす方法

#Wheneverを導入
下記をGemfileに記述した後、

```
bundle install
```

```
gem 'whenever', require: false
```

そして、次のコマンドからschedule.rbを作成します。

```
bundle exec wheneverize .
```

その後は、以下のコマンドでタスクを作成し、

```
bundle exec rails generate task hoge
```

先ほど、作成したschedule.rbとhoge.rakeに行いたいタスクを記述してください。

最後に、

```
bundle exec whenever --update-crontab
```

で準備完了です。

Dockerを使っていない方であれば、このままrailsを走らせれば動きます。

Dockerを使っている方は、

#イメージを作り直す（＊調査中です＊）
もしくは、schedule.rbに環境変数を指定する。

#Dockerfileに追加
RUNのところに、cronを追加してください。

#.tmuxinatorに追加

```
bundle exec whenever --update-crontab
```

これを記述しておくと、立ち上がりの際に一手間省けますね。

当記事が、どなたかの一助となれば幸いです。

#参考文献

http://morizyun.github.io/blog/whenever-gem-rails-ruby-capistrano/
ワードプレス関数(ブログ情報)を変数として取得する


#解決
`$blog_name = get_bloginfo('name');`
終〜〜〜了〜〜〜(；ノ´Д｀)ノ

バッドノウハウだと思うので、このようにするというのがアレば書き込んでいただけると助かります。
そもそも、馬鹿、勘違いしすぎってツッコミも歓迎です。

よくある
`bloginfo('name');`
これは使い方としては
`<?php bloginfo('name'); ?>`
これはコード追ってないからわからないけど
`echo $blog_name;`
みたいなことをしてるのかな？


しかし、コレをSNSのシェアボタンに組み込むときに、URLエンコードしなきゃだけど echo されると
`urlencode(bloginfo('name'));`
みたいな使い方はできない（と思う）

思うに、これは
`urlencode(echo $blog_name);`
的なことをやろうとしているから。

そこで考えたのが、ラップする関数を作ってみました。

```php:出力側.php
$blog_name = wp_bloginfo('name');
echo '<scipt>...'. urlencode($blog_name . 'add hogefuga'). '...</script>';
```

```php:関数側.php
function wp_bloginfo($show){
    //WordPressの関数が変数に入れられない対策
    ob_start();
    bloginfo( $show );
    $str = ob_get_contents();
    ob_end_clean();
    return $str;
}
```

こんなやりかた良いのかな(；´Д｀)
brew caskのアプリケーションすべてをアップデートする。upgrade update

homebrew-caskでインストールしたアプリケーションを一発ですべてアップデート

```
brew cask install --force $(brew cask list)
```

アプリケーションが起動しているなどの理由で
アップデート失敗することもあるので
そうなったらエラーを見ながらアプリケーション毎に確認してください。

僕自身が以下の投稿で、できなかったので調べてみました。
旧バージョンとの兼ね合いもあるので両方試してみてください。

参考
- <a href="http://qiita.com/2k0ri/items/9fe8d33a72dbfb15fe6b" target="_blank">brew caskのappどもをupgradeする</a>
GoでWin32APIのコールバックを使う方法

`syscall.NewCallback`を使えばいいようです。
以下は、コールバックを使用する`EnumChildWindows`を利用して、5秒後にForegroundウィンドウの子ウィンドウを表示するサンプルです。


```child_windows.go
package main

import (
	"fmt"
	"syscall"
	"time"

	"github.com/AllenDang/w32"
)

var mod = syscall.NewLazyDLL("user32.dll")

func getWindow(funcName string) uintptr {
	proc := mod.NewProc(funcName)
	hwnd, _, _ := proc.Call()
	return hwnd
}

func printChildWindows(hwnd uintptr) {
	proc := mod.NewProc("EnumChildWindows")
	f := func(hwnd uintptr, lparam uintptr) int {
		text := w32.GetWindowText(w32.HWND(hwnd))
		fmt.Println("child:", text, "# hwnd:", hwnd)
		return 1
	}
	proc.Call(hwnd, syscall.NewCallback(f), 0)
}

func main() {
	time.Sleep(5 * time.Second)
	hwnd := getWindow("GetForegroundWindow")
	text := w32.GetWindowText(w32.HWND(hwnd))
	fmt.Println("parent:", text, "# hwnd:", hwnd)
	printChildWindows(hwnd)
}
```

なお、上記でも使用しているWin32 APIラッパーとして以下がありますが、すべてを網羅しているわけではないようです。
https://github.com/AllenDang/w32

他にも
https://github.com/lxn/win
がありますが、定義されてる関数がやや少なめ？

これらとhttps://godoc.org/golang.org/x/sys/windows を見て必要なAPIなかったら自力でWin32APIを呼ぶ必要がありそうです。
VMWareのゲストOSがホストOSのネットワークにつながらない現象


Windows2012がインストールされたゲストOSを別のマシンで起動したところ、ブリッジ接続にしているにもかかわらず、ホストOSのネットワークが参照できない現象に陥ってしまいました。

ゲストOSの元のIP設定：123.123.100.1
　　　　　サブネット：255.255.0.0

ホストOSの設定：192.168.130.10
　　　　　サブネット：255.255.255.0

ゲストOSに設定したいIP：DHCPで自動設定したい。。

のに、ホストOSでゲストOSをDHCPで設定するとIPを取得できない。

VMWareのネットワークアダプタの設定は、ブリッジ接続。
散々悩んだ挙句、ブリッジ接続の下にある「物理接続を複製する」にチェックをいれ、
アダプタ設定で、ホストOSに存在するアダプタのみチェックをつけてやると設定できました。

同現象にはまった場合、ファイアウォール・ブリッジ接続・アダプタ設定を確認することをお勧めします。
jQuery.reel.jsで現在のフレーム数を取得する

- ググってもなかなか解決せずに放置していたのですが、ふと調べたら案外あっさり解決してしまったので一応メモ

# 問題
- jQuery.reel.jsでは横長に連結した画像をアニメーションのように表示することができるのですが、現在どの場所の画像を見ているかがわかりにくい問題があります
- 現在位置を表示することは出来るのですが、ただの四角のみなのでUI的にも良くない
- sliderにしたい...

# 解決まで
- 公式サイトを見ていたのですが、少し情報が足りなかったです
- いくつかのサンプルとGitHubのコードを見て発見しました

# 解決法
- `$('#image').reel('frame');`
- これだけです
- `$('#image').reel('frame', 1);
- と指定するとフレームの変更も出来るのであとはsliderと同期させればいいんだと思います


# 参考
- http://jquery.vostrel.cz/reel
- https://github.com/pisi/Reel/blob/v1.3.0/jquery.reel.js
物理ディスクにインストールされたWindowsを物理ディスクのままLinux上のVirtualBoxから起動

過去にやってみたことの記録。

## 動機

WindowsがインストールされたPCを使っていたが、Linux環境のほうが好都合なことが増えて、Windows環境が必要な理由がゼロではないもののそんなになかったので、BIOSから起動するOSをLinuxにすることに。

Windows環境が必要になった時にLinux環境をシャットダウンするのが不便に思ったので、LinuxとWindowsのデュアルブートにはしないで、Linux環境を起動したままLinux上のVirtualBoxからWindowsを起動できるようにすることを狙った。
念の為に、Windowsは物理ディスク単体でBIOSから起動できる状態を維持。

私が扱ったWindowsとLinuxのバージョンは
　Windows Vista 32bit
　Ubuntu 14.04 64bit

## 事前の状況

* WindowsがインストールされたHDDを外して、新規HDDをマザーボードに接続しそれにUbuntuをインストールした。
* UbuntuにVirtualBoxをインストールした。（apt-getなどにより）
* WindowsがインストールされたHDDをSATAでPCに再び接続した。
  * USB外付けでもおそらくOK（未確認）。

## 手順

以下、Ubuntu上での操作。

1. VirtualBoxをroot権限で起動する。
  * 物理ディスクへのアクセスのためにroot権限が要るので、VirtualBoxもroot権限で起動しておく。
      * 普段使いのユーザに物理ディスクへのアクセス権を与えれれば、root権限は要らないだろう。
1. windows用の仮想マシンを作成する。
  * Windowsバージョンなどを適切に設定する。
  * 仮想ディスクはこの後作成するので、この時点では作成しない。
1. 作成した仮想マシンの設定を変更する。設定ウィンドウの「システム」を開いて、、、
  * 「マザーボード」タブで、”I/O APICを有効化”と”ハードウェアクロックをUTCにする”にチェックを入れる。
      * ”I/O APICを有効化”は、物理ディスクにインストールされたWindowsを起動するために必須のようだ。
  * 「プロセッサー」タブで、CPUがPAE/NX対応なものであれば、”PAE/NXを有効化”にチェックを入れる。
  * 「アクセラレーション」タブで、CPUがVT-xやAMD-Vに対応していれば、”VT-x/AMD-Vを有効化”にチェックを入れる。
1. Windowsがインストールされた物理HDDを参照する仮想HDDを作成する。（参考： http://hrn25.sakura.ne.jp/win/virtualbox-rawdisk/virtualbox-rawdisk.html ）
  1. Windowsがインストールされた物理HDDのパスを把握する。以後、/dev/sdbだとする。
      * `sudo fdisk -l`
  1. rawdiskイメージファイル(vmdk)を作成する。
      * `sudo /usr/bin/VBoxManage internalcommands createrawvmdk -filename (好きな場所へのパス)/rawdisk0.vmdk -rawdisk /dev/sdb`
          * /dev/sdbにアクセスするためにroot権限が必要
1. VirtualBoxのWindows用仮想マシンに、今作成した仮想HDDを割り当てる。
  * 仮想マシンの設定で「ストレージ」を選び、 **IDEコントローラに** 上記仮想HDDを追加する。
      * 実際にはSATAで接続していても、ここではIDEコントローラにぶら下げる。でないとWindowsが起動しない。
1. 仮想マシンを起動。Windowsが無事起動したらめでたし。

以後、上記仮想マシンを起動するときはVirtualBoxをroot権限で起動する。

### 備考：Windowsがインストールされた物理HDDのパスについて

上記では/dev/sdbを指定したが、/dev/sdX形式はPC起動やHDD接続のたびに変わる可能性があるとのことなので、できればディスクに固有のIDを使って指定できると好都合。
udevを使って設定を書けば実現できるようだが、そこまでやらなかった。
参考：例えば http://network.station.ez-net.jp/server/linux/storage/fix-scsi.asp

## トラブルシューティング

### Windows起動途中でブルースクリーン（BSOD）になる

セーフモードで起動した場合にはcrcdisk.sysドライバがロードされた直後にBSODになる。

#### 対処法

https://www.virtualbox.org/attachment/wiki/Migrate_Windows/MergeIDE.zip を利用して、Windows環境を少し改変する
（この改変の後も、Windows環境は物理ディスク単体で起動可能）。
上記URLのリンク元と説明： https://www.virtualbox.org/wiki/Migrate_Windows

Windowsを物理ディスクから起動して、以下の手順を実施する。

MergeIDEは説明やエラーメッセージがドイツ語？で書かれていて読めないので、コマンドからMergeIDEがやっていることを読み解くと、、、

1. %SystemRoot%\System32\Drivers\ （%SystemRoot% は大抵はC:\Windows）に、必要なドライバがあることを確認。
  * 必要なのは以下の4ファイル。
      * Atapi.sys
      * Intelide.sys
      * Pciide.sys
      * Pciidex.sys
  * もしどれかが無ければ、driver.cabから取り出して上記パスに置く。
      * driver.cabは "%SystemRoot%\Driver Cache\i386" にある？
      * %SystemRoot%\ 下のどこにも無ければ、インストールディスクから探してくること。
      * インストールディスクを持っていない場合は、、、リカバリディスクが使える？
1. レジストリを書き換える。
  1. MergeIDE.zipを展開。
  1. 管理者権限でコマンドプロンプトを起動。
  1. `regedit (MergeIDE.zipを展開したフォルダ)\MergeIDE.reg` を実行。正常終了のダイアログが出ることを確認。
      * コマンドプロンプトを管理者権限で起動してないと、エラーが出てレジストリを変更できない。

これで終わり。
VirtualBoxから起動してみて起動できたなら、めでたし。

#### それでも起動しないなら

上記対処をしてもまだWindowsが起動しないならば、仮想マシンの設定を変更してみる。
「システム」の”チップセット”の値と「ストレージ」のIDEコントローラの”タイプ”とをちゃんと（末尾の数字も含めて）一致させる。またPIIXからICHに変えてみる。