OmniAICreator/Qiita-1.07M huggingface dataset:
AndroidのWebViewでスケーリングがおかしいときの対処方法

iOS/Android共通で使用しているHTMLがAndroidアプリのWebViewで意図通りに表示されなかったときの試行錯誤の記録。

WebViewで表示するHTMLはCSSでzoomなどもしておらず、widthも固定していないレスポンシブなページ。iOSアプリでは意図通りWebViewの幅いっぱいにHTMLが表示されていた。しかし、AndroidアプリのWebViewでは半分くらいのサイズで表示され、さらに謎の空白も加わり、HTMLと空白が横に並んでいるようなおかしな表示になっていた。（文章だと伝わりづらい）

先に結論を言うと、原因はHTML側でviewportが設定されておらず、WebViewでスケーリングができていなかったよう。また、WebViewのsettingsにもちょっとはまったのでメモ。

## WebViewのSettings

```kotlin
private fun Init() {
    val settings = this.settings
    settings.useWideViewPort = true
    settings.loadWithOverviewMode = true
}
```

[useWideViewPort](http://developer.android.com/intl/ja/reference/android/webkit/WebSettings.html#setUseWideViewPort(boolean))はHTMLの`viewport`またはwide viewportを有効にする設定。指定がなければ端末に依存したサイズに調整される。（詳しい挙動はリンク先を参照）
これを有効にしていると、HTMLのwidthがWebViewより小さい場合、勝手にwidthが拡大されて不足している分の余計な空白ができてしまったりする。

また、[loadWithOverviewMode](per.android.com/intl/ja/reference/android/webkit/WebSettings.html#setLoadWithOverviewMode(boolean))を有効するとHTMLのwidthがWebViewより大きい時に全体を表示するようよしなに調整される。これを有効にしていると`viewport`のスケールによる拡大がきかなくなるので注意。

## Android側だけでの対処
iOSアプリでも使っているのでHTML側にあまり手を加えたくはない。
そこでとりあえず、`useWideViewPort`を`false`にすると余計な空白は消えた。だが、まだHTMLは小さいまま。
そこで、端末のDensity（1ピクセルに対する1dipの倍率）を取得し、それに合わせてスケーリングを行ってみた。

```kotlin
private fun Init() {
    // setInitialScaleを使う場合はこの2つをfalseにしないといけない（referenceにも書いてある）
　  val settings = this.settings
    settings.useWideViewPort = false
    settings.loadWithOverviewMode = false

    // Densityに合わせてスケーリング
    var scale = this.context.resources.displayMetrics.density * 100
    this.setInitialScale(scale)
}
```

これでひとまず意図通りの表示にはなった。

## HTML側の対処

さらに調べたところ、そもそもWebView側でスケーリングするのはあまり推奨されていない様子。
[setDefaultZoom](http://developer.android.com/intl/ja/reference/android/webkit/WebSettings.html#setDefaultZoom(android.webkit.WebSettings.ZoomDensity))でzoom densityの指定もできたりするのだが、API level 19以上ではdeprecatedになっている。
[Migrating to WebView in Android 4.4](http://developer.android.com/intl/ja/reference/android/webkit/WebSettings.html#setDefaultZoom(android.webkit.WebSettings.ZoomDensity))でも言及されているが、基本的にはHTMLで`viewport`を指定するのが望ましい。

というわけで、当然といえば当然だが深遠な理由がなければHTMLの`viewport`で`initial-scale`を指定するのがよさそう。

```html
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0">
  </head>
</html>
```

その場合、`useWideViewPort`と`loadWithOverviewMode`の指定は不要だった。zoomとかscaleとかそれぞれの違いが理解しきれずもう少し調べたい所だけど、今回はここまで。
Xamarin採用のまとめ

Xamarinを採用した理由のまとめです。
許可を取っていないためアプリの概要に関しては詳しく書けません。
はじめからXamarinが選択肢のメインだった為、あまり参考になりません。

アプリは

一部機能でリアルタイムの高額の取引がある。
リアルタイムの音声再生機能がある。
普通のクラサバ機能もある。
プッシュ通知機能がある。

事が特徴です。

製造技術に求めていた点としては
1. UIをAndroidとiOSで共通に作成可能
2. UIをいざとなったら別々にも作成可能
2. ソケット通信が細かく制御できる。(TCP/UDP)
3. バイナリ操作が書きやすいくパフォーマンスが良い。
4. ストリーミング音声再生を実装できる。
5. いざとなったらゴリゴリ書ける。ネイティブのライブラリを簡単に呼べる。
6. WebAPIの呼び出しが楽に書ける。

でした。

元々別製品にてMono For Androidを採用していた事と、このアプリには既にPC版が存在していてWPF(C#)で作成されているのでXamarinしか選択肢にないとは思っていたのですが、ライセンス費用がなかなかに高かったため、そのほかのプラットフォームも検討していました。
ソケット通信とかを書く必要がないのであればMonacaとかが良いかなぁと思っていました。

技術選択時の候補としては
Qt C++Builder Haxe Cocos2d Unityなどを検討してました。

最終的にQtかXamarinかで検討を行っていました。
技術調査の中盤まではXamarin.FormsはリリースされてなくMvvmCrossが出ていた時期だったのですがXamarin.Formsが出てきて実装してみてほぼ確定しました。
私自身、データバインドでのプログラミングスタイルにはある程度の慣れがあったので(WPF,konockout.js)できる限りXamarin.Formsを採用したいと考えていたのですが、Xamarin.Forms採用に関して不安だった点として、お客様の要望を受けた時に対応しきれるかという点がありました。
これに関してはXamarin.Formsにて実装を学習していく中で何とかなるだろうとの判断になりました。
困った時にはエクセルソフトサポートにお世話になっています。

製造を補完するライブラリとしては
Prism.MvvmとReactivePropertyを採用しています。
複数のプロパティを監視してデータを更新する処理などでReactivePropertyがすごく活躍してます。
だいぶコードが短縮されて簡潔になりました。
今後のバインドスタイルでの開発ではスタンダードになるのではと思います。

Xamarinがマイクロソフトに買収されて、この先VisualStudio製品に組み込まれていくと思いますが
個人開発者が手を出しやすい範囲でのライセンス形態となってくれればなぁとか思います。
お仕事では使えるのですが、個人開発となると難しいです(´・ω・`)
ShinobiLayer: SendGridでClick TrackingやOpen Trackingを無効にする方法（Web API）

#はじめに
[SendGrid初心者のための注意点（SoftLayer版）](http://qiita.com/testnin2/items/ceb27d418a017c0c3490) にて紹介したように、SendGridはどのパッケージを選択するかによって、デフォルトの送信オプションが異なります。特に注意するべき項目は、Click TrackingやOpen Trackingです。詳細は先述のリンクをご確認下さい。
ここでは、直接SendGridに対してWeb APIを実行する際の回避策を提示します。

#Web APIを使ったClick TrackingやOpen Trackingの切り替え方法
SendGridは、API実行時にx-smtpapiヘッダを使って、メール送信時にClick Tracking/Open Trackingを無効にすることが可能です。以下はcurlを使ったメール配信の実行例です。

```text:通常の送信方法例
# curl -v \
-F to=宛先のメールアドレス \
-F toname=test \
-F subject="Advanced Package - default" \
-F html="This is test. <a href="http://www.yahoo.co.jp">This is html body.</a>" \
-F from=test@yourdomain.com \
-F api_user=SendGridのアカウントID \
-F api_key=SendGridのアカウントパスワード \
https://api.sendgrid.com/api/mail.send.json
```

```text:ClickTrackingとOpenTrackingを無効にするため、x-smtpapiを使用
# curl -v \
-F to=宛先のメールアドレス \
-F toname=test \
-F subject="Advanced Package with clicktrack disabled" \
-F html="This is test. <a href="http://www.yahoo.co.jp">This is html body.</a>" \
-F from=test@yourdomain.com \
-F api_user=SendGridのアカウントID \
-F api_key=SendGridのアカウントパスワード \
-F x-smtpapi='{ "filters": { "clicktrack": { "settings": {"enable": 0 }}, "opentrack": { "settings": {"enable": 0 }}}}' \
https://api.sendgrid.com/api/mail.send.json
```

参考URL: 
https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/index.html
win_msiモジュールに泣かされて死んだ俺のdatadog agentインストール入門

俺です。

Windows版データワンワンAgentをAnsibleのwin_msiモジュール使って
インストールしようとしたところ、うまく動かなかった(msiexecプロセスがバックグラウンド起動してだんまりだった)のでrawで叩き込みました。
登録対象のdd-agentホス名をinstance-idで登録しています。

冪等性はあるように見えてないです。
2回目に実行するとmsiexecがバックグラウンド起動しっぱなしになってしまいます。

```
- name: Download datadog agent
  win_get_url: >-
    url="https://<dd-agent-utl>/ddagent-cli.amd64.msi"
    dest=C:/temp/ddagent-cli.amd64.msi
    force=no
- name: get Instance ID From metadata
  raw:  Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/instance-id
  register: instance_id
- name: install datadog agent for windows
  raw: msiexec /qn /i C:\temp\ddagent-cli.amd64.msi APIKEY="{{ datadog_api_key }}" HOSTNAME="{{ instance_id.stdout_lines[0].encode('utf-8') }}"
```
GitFlow導入手順


# GitFlow導入
## 準備

1. Git
Gitの公式サイトからDL
URL:http://git-scm.com/downloads
    
1. GitFlowプラグイン
git-flowのインストールにはgetopt.exeとlibintl3.dllが必要。
下記URL内の「Binaries」「Dependencies」をDLし該当ファイルを取得。
URL:http://gnuwin32.sourceforge.net/packages/util-linux-ng.htm

## インストール
1. Git
DLしたインストーラからインストール。
    
2. GitFlowプラグイン
DLした「Binaries」「Dependencies」から必要ファイルを抜き出し、gitのフォルダに移動する。
    + 該当ファイル
       
        - getopt.exe
            util-linux-ng-XX.XX.XX-bin\bin\getopt.exe
            
        - libintl3.dll
            util-linux-ng-XX.XX.XX-dep\bin\libintl3.dll
    
    + 移動先
        - C:\Program Files\Git\bin

3. SourceTree
DLしたインストーラからインストール。
RubyのMySQLクライアントでUNIXSocket絡みのエラーが出たらホスト名を変えると直る

ruby-mysqlでローカルのDBを参照する
---

Rubyから直接MySQLを触るにはいくつかのgemが利用できます。
試しにlocalのデータベースを触ろうと思って、`ruby-mysql`を使い以下の様にクライアントを生成しました。
環境は**Windows 10 64bitです。（<- 実はここが大事）**

```rb:wrong-client.rb
require 'mysql'

client = Mysql.connect('localhost', 'username', 'password', 'dbname')
```

しかしエラーが...

```
C:/tools/ruby215/lib/ruby/gems/2.1.0/gems/ruby-mysql-2.9.14/lib/mysql/protocol.rb:150:in `block in initialize': uninitialized constant Mysql::Protocol::UNIXSocket (NameError)
	from C:/tools/ruby215/lib/ruby/2.1.0/timeout.rb:76:in `timeout'
	from C:/tools/ruby215/lib/ruby/gems/2.1.0/gems/ruby-mysql-2.9.14/lib/mysql/protocol.rb:147:in `initialize'
...(以下略)...
```

ローカルのDBはhost=127.0.0.1で参照
---

これは「[MySQLでlocalhostと127.0.0.1の違い](http://qiita.com/TanukiTam/items/f6a08740d0fcda0db7be)」で述べられているように、ホストの指定の仕方の間違いによるものでした。

まだ理屈をよく分かっていませんが、とりあえず`127.0.0.1`を指定すると解消しました。

```rb:correct-client.rb
client = Mysql.connect('127.0.0.1', 'username', 'password', 'dbname')
```

この状況はWindows OSでしか発生しないみたいです。

参考
---

* [MySQLでlocalhostと127.0.0.1の違い - qiita](http://qiita.com/TanukiTam/items/f6a08740d0fcda0db7be)
* [Error: uninitialized constant Mysql::Protocol::UNIXSocket - Ruby Forum](https://www.ruby-forum.com/topic/203529)
mysqlレプリケーション設定


# 前提
activeのデータをslaveにデータを丸ごとコピーし、レプリケーションの設定をする。

activeのmysqlを止める事が可能であり、且つslaveはデータが何も入っていない状態。エンジンはinnoDBとする。
環境情報は以下のとおり。

| 種別 | 設定値 | 備考 |
|:----|:----|:----|
|データベース	 | testdb	  | コピー＆レプリケーション対象 |
|テーブル	 | maintable | 	動作確認用 |

| 種別 | サーバー名 | IP |備考 |
|:----|:----|:----|:----|
| オリジナル	| active	| 192.168.0.1| コピー元のサーバ | 
| スレーブ	| slave 	| 192.168.0.2| 空の状態 |

| 種別 | 設定値 |
|:----|:----|
| レプリケーションユーザ  	| repli |
| レプリケーションパスワード	| pass |

# 前準備(データ転送)
activeの MySQL停止し、/data/mysql 以下をslave にrsync

``` active側作業
## MySQLサーバを停止
ps -ef | grep -i mysql
/etc/init.d/mysql stop
ps -ef | grep -i mysql
```

## 対象のデータベースをディレクトリごと転送

``` active側作業
rsync -avz /data/mysql/testdb 192.168.0.2:/data/mysql/.
```

# activeの MySQL起動し、ポジション確認

``` active側作業
# mysqlを起動
/etc/init.d/mysql start
mysql -u root -p

# ポジション確認
mysql> show master status\G
*************************** 1. row ***************************
            File: mysqld-bin.001234★ひかえる
        Position: 123456789★ひかえる
    Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

mysql>


#各サーバで以下のコマンドを実行し、レコード数をカウントする。復旧時、件数確認で使用する。

use testdb;
select count(*) from maintable;

mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select count(*) from maintable;
+----------+
| count(*) |
+----------+
| 1234     |
+----------+
1 row in set (0.93 sec)

mysql>


# レプリケーション接続許可設定
# この設定をすることにより、slaveでレプリケーションの設定が可能になる。
mysql> grant file,replication slave on *.* to repli@'192.168.0.2' identified by 'pass';
```


# slaveレプリ開始

``` slave側作業
# レプリケーションが停止していることを確認。
mysql -uroot
reset slave;

# レプリ再開で、ポジションが進み始めることを確認
mysql> change master to master_host='192.168.0.1', 
        master_port=3306,master_user='repli',
        master_password='repl',
        master_log_file='mysqld-bin.001234',★ひかえた値を設定
        master_log_pos = 123456789;★ひかえた値を設定

# レプリケーション再開
start slave;

# activeに更新があった場合、ポジションが進むことを確認
show slave status\G
``` 


# 事後確認

各サーバで以下のコマンドを実行し、レコード数をカウントする。

```command 
mysql> use testdb;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select count(*) from maintable;
+----------+
| count(*) |
+----------+
| 1234     |
+----------+
1 row in set (0.93 sec)

mysql>
```
AWS SDKで使われるクレデンシャル情報の検索優先順位

AWS SDKを利用してプログラミングをする際、クレデンシャル情報（アクセスキーとシークレットキー）をハードコードしたりGitHubにpushしたりしちゃダメよ、というのは当然だと思うんですが、じゃあどこに格納しておくのが正解なんだっけ？と悩んだのでまとめておきます。

# 検索の優先順位について

AWS SDKを使ったプログラム中でアクセスキーなどが明示的に指定されていない場合、クレデンシャル情報は次の優先順位で検索されます。

1. 環境変数`AWS_ACCESS_KEY_ID`と`AWS_SECRET_ACCESS_KEY`（.NET SDK以外）
2. 設定ファイル`~/.aws/credentials` (Linux/Mac)または`%USERPROFILE%\.aws\credentials`  (Windows)
3. SDKごとの設定ファイル（後方互換性のため）
4. SDKストア（.NET SDKのみ）
5. （コードがEC2上で動いている場合のみ）インスタンスメタデータからクレデンシャル情報を取得

個人的には、2番の設定ファイルで統一するのが楽かなと思います。状況によっては5番は便利そうですね。

# 設定ファイルのフォーマット

2番の設定ファイルのフォーマットはいわゆるINI形式です。

```
[default]
aws_access_key_id = ACCESS_KEY
aws_secret_access_key = SECRET_KEY
aws_session_token = TOKEN
 
[Alice]
aws_access_key_id = Alice_access_key_ID
aws_secret_access_key = Alice_secret_access_key
 
[Bob]
aws_access_key_id = Bob_access_key_ID
aws_secret_access_key = Bob_secret_access_key
```

こんな風に記述できるので、必要に応じてプロファイル（ここでは`Alice`や`Bob`）を使い分ければ複数のアクセスキーの管理も簡単です。また、このファイルは必ずリポジトリ外に置かれることになるので、どう間違ってもクレデンシャル情報をGitHubにpushするような事故は起きないはずです。

# 参考URL

本稿の内容は下記URLに書いてあることそのまんまです。

- [A New and Standardized Way to Manage Credentials in the AWS SDKs - AWS Security Blog](https://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs)
PHPでTwitterの診断メーカーで使われているような「入力値に依存する乱数」を生成する方法

# 基本

**「`mt_rand`のシードを入力文字列のハッシュ値で固定すればいいじゃん！」** と真っ先に思いつくんですが，`mt_srand` の引数には整数しか渡せないので，`md5`や`sha1`などはそのままでは適用できません．`crc32`関数がちょうど整数型でハッシュ値を返してくれる関数なので，今回はこれを利用することにします．

**※ 32bit環境と64bit環境で得られる結果が異なるので注意してください**

```php:PHP5.4以降
/**
 * @param string $seed シード値
 * @param int $min 最小値
 * @param int $max 最大値
 * @param bool $daily 日付毎にランダマイズするか
 * @return int 範囲内の乱数
 */
function random_int_by_seed($seed, $min, $max, $daily = false) {
    $seed = (string)filter_var($seed);
    $min = (int)$min;
    $max = (int)$max;
    if ($max < $min) {
        throw new \InvalidArgumentException('Invalid range');
    };
    if ($daily) {
        $seed .= (new \DateTime('today Asia/Tokyo'))->format('Y/m/d');
    }
    mt_srand(crc32($seed));
    $r = mt_rand($min, $max);
    mt_srand();
    return $r;
}
```

```php:バラつき度の確認
$counts = array_fill(0, 5, 0);
for ($i = 0; $i < 10000; ++$i) {
    ++$counts[random_int_by_seed(openssl_random_pseudo_bytes(100), 0, 4)];
}
var_dump($counts);

/*
array(5) {
  [0]=>
  int(2002)
  [1]=>
  int(2037)
  [2]=>
  int(1968)
  [3]=>
  int(2023)
  [4]=>
  int(1970)
}
*/
```

# 応用

実際は，乱数に応じて**複数の**選択肢を選んでいくことになるはずなので，これに適応できるようにちょっと書き加えます．

```php:PHP5.4以降
/**
 * @param string $seed シード値
 * @param array $table 「選択肢の配列」の配列
 * @param bool $daily 日付毎にランダマイズするか
 * @return array 「選ばれた選択肢」の配列
 */
function random_items_by_seed($seed, array $table, $daily = false) {
    $seed = (string)filter_var($seed);
    if ($daily) {
        $seed .= (new \DateTime('today Asia/Tokyo'))->format('Y/m/d');
    }
    mt_srand(crc32($seed));
    $r = [];
    foreach ($table as $i => $row) {
        $row = (array)$row;
        $r[$i] = $row ? $row[mt_rand(0, count($row) - 1)] : null;
    };
    mt_srand();
    return $r;
}
```

```php:使用例
$name = 'mpyw';
$r = random_items_by_seed($name, [
    ['大吉', '吉', '中吉', '小吉', '末吉', '凶', '大凶'],
    ['赤', '青', '緑', 'ピンク'],
], true);
vprintf("{$name}さんの今日の運勢は%sです！ラッキーカラーは%sです！\n", $r);

/*
mpywさんの今日の運勢は末吉です！ラッキーカラーは緑です！
*/
```

なお，シード値が配列の複数要素になる場合には`serialize`や`json_encode`したものを`$seed`として渡せばいいでしょう．
負荷テスト

# 負荷テストとは

**大量のデータ**を投入し、**高い負荷**をかけて **「ソフトウェアが正常に機能しているか」**　確認するテストです。

※長時間、高負荷が継続すると**不具合** が起きてしまう可能性があるためです。

**「単体テスト」**や**「結合テスト」**だけでは見つけられない**不具合**がある。

また、**想定のユーザー数**でも**耐えることができること**を確認するためのテストでもあります。


# 負荷テストツール

どんな**負荷テスト**想定しているかで変わります。

**「大規模負荷テスト」****「サーバ負荷テスト」****「処理単位の応答時間」**

高価なものから無償のものまでです。
**負荷テストツールの選定**も大事な負荷テスト計画となりますね。

## 1.Apache Jmeter
http://jmeter.apache.org/

JMeterは**Jakarta**プロジェクトが開発している**無償負荷テストツール**です。
**GUIインターフェース**を使ってかなり細かく負荷テストのシナリオを設定する事ができます。
<img width="1153" alt="スクリーンショット 2019-10-09 16.15.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55160/a004e881-dc53-69c3-74e2-ea9c930cbefd.png">


```lang:設定例
レスポンスタイムが3秒以内を目標とし、1秒あたり、どれくらいのユーザー数まで問題なく動作するかを確認する。スレッド数(アクセスするユーザー数)：Ramp-Up期間（秒）(スレッド数に対して、何秒以内に処理するかの設定)：ループ回数(テストケースの繰り返し設定): 無限ループ
```

**総リクエスト数 = スレッド数 × ループ回数**

スレッド数：60
Ramp-Up期間（秒）：60
ループ回数：10
<img width="1439" alt="スクリーンショット 2019-10-04 17.56.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55160/50322316-92c6-757e-caa3-89722c39c982.png">

※1秒で1アクセスという意味になります。
これは、サービスによって設定値が変わってきます。

スレッド数：6
Ramp-Up期間（秒）：60
ループ回数：10

※10秒で1アクセスという意味になります。

ちなみに、ヤフーの「災害情報表示機能」は、1秒間あたり数万単位のアクセス
Googleアナリティクスのリアルタイムレポートなどで確認。
この結果に合わせてECサイトであれば、負荷テストを実行する。

## 2.httperf
http://www.hpl.hp.com/research/linux/httperf/

httperfは、**コマンドライン負荷テストツール**です。

## 3.The Grinder
http://grinder.sourceforge.net/

**Javaで負荷分散テスト**ができるフレームワークです。

## 4.HP LoadRunner software 

ページ単位に負荷をかけることができる。また、ExcelやPDFでファイルを出力できる。サポートもあり。価格が何百万もするのがネックぐらい。

## 5.Load Impact
http://loadimpact.com/

毎月5回まで無料。無料枠を超えた場合、10回/$30のクレジット購入となります。

## 6.ab(Apache Bench)
http://httpd.apache.org/docs/2.2/programs/ab.html

Apache Licenseで無償です。

## 7.k6
https://k6.io/

Grafana Labs社が開発している「k6」
「Grafana Cloud k6」クラウドベースSaaSツールも提供

試しに確認



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55160/a1327b2f-f603-29fb-221d-4dbfdcb31b66.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55160/11635f46-2005-03a0-2934-80044e4ec4fd.png)



# 負荷テスト

### 1.事前調査
・どの箇所に負荷をかけるのか。
・なぜ負荷がかかるのか。
・一定時間帯によるのものなのか。
・通信は不安定ではないか。
・実稼働時の負荷に耐えられるか。

### 2.環境の準備
・実行するテスト環境を用意する。
・テストツールををセットアップ。※JMeterを用いた場合

    1.スレッド数(ユーザの人数)
    2.Ramp-Up期間(設定スレッド数に対し、何秒以内に処理するか)
    3.ループ数(テストケースを何回繰り返すか)を設定。

スレッドグループを設定。

HTTP認証マネージャ設定
<img width="1440" alt="スクリーンショット 2019-10-09 16.24.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55160/71e1906a-51f4-4741-b804-b3450711b877.png">

### 3.試験計画作成と実施
・どれくらいのテストケースが必要なのか。


### 4.結果の分析と確認
・スレッドの応答時間やスループットの確認
・エラー発生率の確認
Arduino で PWM の周波数を変える


ATMega328p (168p) の Arduino で PWM の周波数を変えたい。ちゃんと理解をするには

- http://garretlab.web.fc2.com/arduino/inside/arduino/wiring_analog.c/analogWrite.html

を読めば良い。けどそもそもタイマーレジスターとは…、という自分の知識だったので動くコードを見つつ考えたい。

- [PMWの周波数を変更する（タイマ/カウンタ レジスタ値の確認と変更）](http://www.nina.jp/server/arduino/PWM/PWM.html)

のページではコードの実例が載っていて解りやすい。

そして

- http://playground.arduino.cc/Main/TimerPWMCheatsheet

には、ずばりチートシートが載ってるので、これを見ると目的の周波数をセットするにはてっとり早い。

> Pins 5 and 6: controlled by Timer 0 in fast PWM mode (cycle length = 256)

```
Setting 	Divisor 	Frequency
0x01 	 	1 	 	62500
0x02  		8 	 	7812.5
0x03  		64 	 	976.5625   <--DEFAULT
0x04 	 	256 	 	244.140625
0x05 	 	1024 	 	61.03515625

TCCR0B = (TCCR0B & 0b11111000) | <setting>;
```

みたいに、周波数を設定するために何をレジスタに代入すればよいのかがすぐ解るコードがまんまのってる。

```
TCCR0B = (TCCR0B & 0b11111000) | 0x01; // 62500Hz
analogWrite(5, 128); // duty比 50%
```

これで 16us 周期の PWM がうまく出力された。

![pwm.png](https://qiita-image-store.s3.amazonaws.com/0/5330/184e54c1-cbba-71d4-1063-d96fa8800c76.png "pwm.png")


# 注意事項

TCCR0B (uno や nano の 5,6 ピンの PWM) の周波数を変えると、同じタイマの Timer 0 を使ってる標準関数の delay() や millis() などに影響が出る。

標準の 976.5625 Hz では delay(1000) で約一秒待つが、62500Hz に変更した場合、62500 / 976.5625 = 64000 で delay(64000) が約1秒となる。

2016年3月時点の Arduino のソースコードを見る限り、[このへんで固定されてしまっていて](https://github.com/arduino/Arduino/blob/b1231c39/hardware/arduino/avr/cores/arduino/wiring.c#L27)良い回避策が無くて wiring.c を自分で書き換える必要がある…。良い方法知ってる人が居たら教えてください…。
BashからSlackへ投稿する

#何すんの？
大前提としてタイトル通りです。主として備忘録です。

#環境
```
$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 15.10
Release:	15.10
Codename:	wily

$ bash --version
GNU bash, バージョン 4.3.42(1)-release (x86_64-pc-linux-gnu)

$ curl -V
curl 7.43.0 (x86_64-pc-linux-gnu) libcurl/7.43.0 GnuTLS/3.3.15 zlib/1.2.8 libidn/1.28 librtmp/2.3
Protocols: (省略)
```

curlを用います。もし入っていない方はインストールしておいてください。
```
$ sudo apt-get install -y curl
```

#Slack投稿スクリプト

```postSlack.sh
#!/bin/sh

# postSlack.sh [チャンネル] [Bot名] [本文]

WEBHOOKURL="[Incoming Webhooks URL]"

DATA_PAYLOAD=`cat <<_EOT_
payload={ \
    "channel": "$1", \
    "username": "$2", \
    "text": "$3" \
}
_EOT_`

curl -s -S -X POST --data-urlencode "${DATA_PAYLOAD}" "${WEBHOOKURL}" > /dev/null
```

#さいごに
現在私が使っている以上では特に問題が起きてませんが、
コレ文字列入れたらセキュリティ的にアレ！みたいなのがあれば教えて頂けると幸いです。
Swift 配列の基本

配列の基本について記載


型指定

```swift
var ary:Array<Int> = [1,13]
```

型指定[]での記述

```swift
var ary:[Int] = [1,2]
```

複数の型指定

```swift
var ary:Array<Any> = [1,"anything"]
```

追加

```swift
ary.append("add")

```

指定indexに追加

```swift
ary.insert("add0", atIndex: 0)
```

index値が1以上3未満の値を置き換える

```swift
var animal = ["tiger","elephant","dog","cat"]
animal[1..<3] = ["a","b"]
print(animal) //"["tiger", "a", "b", "cat"]\n"
```

index値が1~3の値を置き換える

```swift
var animal = ["tiger","elephant","dog","cat"]
animal[1...3] = ["a","b"]
print(animal) //"["tiger", "a", "b"]\n"
```

指定indexを削除

```swift
var animal = ["tiger","elephant","dog","cat"]
animal.removeAtIndex(2)
print(animal) // "["tiger", "elephant", "cat"]\n"
```

コピー
(配列のコピーは参照渡しではなく、値のコピーになります。)

```swift
var animal = ["tiger","elephant","dog","cat"]
var copyArray = animal
copyArray[0] = "change"
print(copyArray[0])　// change
print(animal[0])  //tiger
```


以上
OTRSからMailmanに送ると日本語のSubjectが文字化けする件


## OTRS環境：OTRS 5.0.7
CentOS 6.7 x64 最小構成

## mailman環境：mailman 5.1.12-25(yumインストール)
CentOS 6.0 x86 ？構成

## 現象
OTRSからmailman管理のMLにメールを送ると、 
```[Test:00014] Re: [Ticket:202103] =?UTF-8?Q?=E3=80=```
のように件名が文字化け（というかデコード失敗？）してしまう。

## 回避策
mailman側で subject_prefix を外す。
OTRSから送るMLの全てに外してもらわなくてはいけないので現実的ではない。

## 解消策
MIME::EncWordsを使えるようにする。
Kernel/System/Email.pm の sub _EncodeMIMEWords で

```perl:Email.pm
    # check if MIME::EncWords is installed
    if ( eval { require MIME::EncWords } ) {    ## no critic
       return MIME::EncWords::encode_mimewords(
    （略）
    # as fallback use MIME::Words of MIME::Tools (but it lakes on some utf8
    # issues, see pod of MIME::Words)
    else {
        require MIME::Words;    ## no critic
        return MIME::Words::encode_mimewords(
 ```

と分岐している所があったので切り分けしたところ下を走っていた。
試みに
```# yum install perl-MIME-EncWords perl-MIME-Charset perl-Email-Valid perl-Mail-Sender perl-Log-Log4perl```
と関係のありそうなモジュールをインストールしたところ解消した。

要らないモジュールも入ったかもしれないけど、知らぬ。

***
2016/05/20 追記
## OTRS v5.0.8で再発していることを知る
Kernel/System/Email.pm の sub _EncodeMIMEWords で MIME::EncWords を使う分岐が消えていた。
え、なに？使っちゃダメなの？

## 回避策
１．とりあえず OTRS v5.0.7のアーカイブから Kernel/System/Email.pm を取り出し、 Custom/Kernel/System/Email.pm に置く。
２． ```service httpd restart``` してApacheを再起動。
３．回避！
たった2つのコマンドでElasticsearch＋Kibana環境構築

# はじめに

タイトルが釣りっぽいですが、docker-machine環境があれば、本当にたった2つのコマンドで、Elasticsearch＋Kibana環境を構築できます。もし、docker-machine環境がなければ以下の記事を参考に入れておいてください。

[docker-machineを使ってみる - Qiita](http://qiita.com/techys/items/b59466f590e61d945004)


# 環境

- MacBook Air (11-inch, Early 2015)
- Mac OS X El Capitan バージョン 10.11.3
- docker-machine version 0.6.0
- docker version 1.10.1


# Elasticsearch＋Kibana環境構築

1つ目のコマンドで、Elasticsearchを起動します。

```bash
$ docker run --name es -t -i -d -p 9200:9200 -p 9300:9300 elasticsearch
```

2つめのコマンドで、先に起動したElasticsearchと連携するKibanaを起動します。

```bash
$ docker run --name kibana --link es:elasticsearch -t -i -d  -p 5601:5601 kibana
```

これだけです。


# 確認

起動したKibanaの画面にブラウザでアクセスしてみます。

http://192.168.99.100:5601/

![kibana.png](https://qiita-image-store.s3.amazonaws.com/0/94137/c01d4fd1-b1d1-75b8-4b85-950df1e8d56c.png)

上記のような画面が表示されたら完了です。ステータスがイエローみたいな画面が出たら、Elasticsearchが起動中かもしれないので少し待ってみるといいと思います。

これだけで、Elasticsearch＋Kibana環境が構築できるなんて、良い世の中になりましたね。さて、どんなログを放り込んでみようかな。
docker-machineを使ってみる

# はじめに

Elasticsearch＋Kibanaで遊びたい。今なら、便利なdockerイメージとかあるんじゃね？そういえば、boot2dockerってインストールしてたなーと思ったら、今はdocker-machineってのが普通らしい。docker-machineってなんだ？ （←今ココ）

ということで、古いboot2docker環境を捨てて、docker-machineでdocker環境を構築してみます。boot2dockerを入れていない人は、boot2dockerのアンインストールは飛ばしてください。


# 環境

- MacBook Air (11-inch, Early 2015)
- Mac OS X El Capitan バージョン 10.11.3


# docker-machineとは

[Docker Machine](https://docs.docker.com/machine/)とは、dockerコンテナを動かすためのホスト環境を構築するためのツールです。これを使えばローカルPC上でdockerコンテナが使えるようになります。以前は、boot2dockerというツールが一般的でしたが、今はdocker-machineがおすすめのようです。


# boot2dockerをアンインストール

[注意]
既存のdocker＆boot2docker環境が不要だったので、即アンインストールしています。
大事なコンテナがある場合は移行が必要な気がするのでご注意を。

```bash
$ brew list | grep docker
boot2docker
docker
```

homebrewでインストールしていたのでアンインストールします。

```bash
$ brew uninstall docker boot2docker
Uninstalling /usr/local/Cellar/docker/1.10.1... (10 files, 10.4M)
Uninstalling /usr/local/Cellar/boot2docker/1.8.0_1... (3 files, 8M)
```

複数バージョン入っている、古いバージョンが残っている場合、`--force`オプションを使うとキレイになりそうです。


# docker-machineをインストール

docker-machimeはdockertoolboxというツール群に含まれています。homebrew caskで入れられるのでインストールします。

```bash
$ brew cask install dockertoolbox
```

# dockerホストの作成と起動

docker-machineコマンドで、defaultという名前でdockerホストを作ります。

```bash
$ docker-machine create -d virtualbox default
```

終わったら確認してみます。

```bash
$ docker-machine status
Running
```

Runningであればdockerホストの起動に成功しています。
次に、ローカルからdockerホスト上のコンテナを操作をできるように環境設定します。

```bash
$ docker-machine env default
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/syasu/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell:
# eval $(docker-machine env default)
```

構築したでdefaultの環境を確認すると、あなたのシェルでこれを実行してね、というコメントが出るのでそのとおりに実行します。

```bash
$ eval "$(docker-machine env default)"
```

はい、準備完了です。
確認してみると、ローカル上にdockerホストが起動していることが分かります。

```bash
$ docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
default   *        virtualbox   Running   tcp://192.168.99.100:2376           v1.10.2
```

これで、最新のdockerライフを送るための準備ができました。
あっという間でした。


# おまけ

docker-machineで構築したdockerホストにログインしてみると、いつものクジラが出てきました。中身はboot2dockerなんですね。

```bash
$ docker-machine ssh
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.10.2, build master : 611be10 - Mon Feb 22 22:47:06 UTC 2016
Docker version 1.10.2, build c3959b1
# 
```
bundle installでmysql2がコケるとき


Railsのバージョンが古い可能性があります。
僕の環境では、Railsのバージョンが4.2.0だとmysql2のbundle installでコケてしまいました。
新しいバージョン(4.2.5.2)にしたらコケなくなったので同じ症状の方はバージョンを疑ってみてください。
Macでjmeterがうまく動作しないときの対処方


MacでjmeterのGUIを操作しても以下の様なメッセージが出てうまく動作しない場合があります。

```
Uncaught Exception java.lang.NoClassDefFoundError: Could not initialize class org.apache.jmeter.gui.util.MenuFactory. See log file for details.
```

そんなときは、Javaのバージョンが低い可能性があります。
brewコマンドを使って、最新のJavaをインストールしましょう。

```
$ brew cask search java
==> Tapping caskroom/cask
Cloning into '/usr/local/Library/Taps/caskroom/homebrew-cask'...
remote: Counting objects: 3501, done.
remote: Compressing objects: 100% (3449/3449), done.
remote: Total 3501 (delta 48), reused 1880 (delta 30), pack-reused 0
Receiving objects: 100% (3501/3501), 5.92 MiB | 1.02 MiB/s, done.
Resolving deltas: 100% (48/48), done.
Checking connectivity... done.
Tapped 1 formula (3,467 files, 13.4M)
==> Exact match
java
==> Partial matches
eclipse-java	       yourkit-java-profiler


$ brew cask install java
==> Caveats
This Cask makes minor modifications to the JRE to prevent issues with
packaged applications, as discussed here:

  https://bugs.eclipse.org/bugs/show_bug.cgi?id=411361

If your Java application still asks for JRE installation, you might need
to reboot or logout/login.

Installing this Cask means you have AGREED to the Oracle Binary Code
License Agreement for Java SE at

  http://www.oracle.com/technetwork/java/javase/terms/license/index.html

==> Downloading http://download.oracle.com/otn-pub/java/jdk/8u74-b02/jdk-8u74-macosx-x64.dmg
######################################################################## 100.0%
==> Verifying checksum for Cask java
==> Running installer for java; your password may be necessary.
==> Package installers may write to any location; options such as --appdir are ignored.
==> installer: Package name is JDK 8 Update 74
==> installer: Upgrading at base path /
==> installer: The upgrade was successful.
🍺  java staged at '/opt/homebrew-cask/Caskroom/java/1.8.0_74-b02' (2 files, 227M)
```
EC2にnginx+php(php-fpm socket)環境を最速で構築したときにハマった事

初投稿はQiitaで見た記事どおりに、知識無しで丸っと真似るとしてハマったこと。

#参考
- [EC2にnginx+php(php-fpm socket)環境を最速で構築](http://qiita.com/koni/items/05158e33b4c8aac07b59)

#事象
- コマンド上でのphpファイルは動くが、WEB経由だと50Xエラー
- htmlファイルは問題なく表示される。

```
[error] xxxx#0: *9 connect() failed (111: Connection refused) while connecting to upstream,
 client: 192.168.xxx.xxx, server: example.com, request: "GET /xxx.php HTTP/1.1", upstream:
 "fastcgi://127.0.0.1:9000", host: "example.com"
```

#確認
```
//起動してる？
# service nginx status 
nginx (pid  xxxx) is running...

# service php-fpm status
php-fpm-5.6 (pid  xxxx) is running...

//OK!

//バージョンによる？
# nginx -v
nginx version: nginx/1.8.1

# php-fpm -v
PHP 5.6.17 (fpm-fcgi) (built: xxxxx)
```

#問題の箇所

暫くググッてみたけど、全く同じ状況のもの記事が無かった…
もう一度設定ファイルを見直す。

```lang:/etc/nginx/nginx.conf
include /etc/nginx/conf.d/*.conf;
```

インクルードされてるよ。

```lang:php-fpm.conf
upstream php-fpm {
        server 127.0.0.1:9000;
}
```

参考ではnginxとphp-fpmはソケット通信にしていたよね。
そしてセキュリティグループでポート閉じてたよね？

```
# lsof -i tcp:9000
# (ち～ん)

# lsof -i tcp:80
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   xxxx  root    6u  IPv4  xxxxx      0t0  TCP *:http (LISTEN)
```

#解決
それぞれのインクルードファイルをソケットに書き換え終了。
正常にWEB経由でphpが実行される事を確認！
Cocoapodsの設定がうまくいかない時

pod installがいつまで経っても終わらない場合や
下記のエラーが出てしまう場合に下記のシェルを
実行する事で解決する事があります。

```
$ pod setup
Setting up CocoaPods master repo
[!] /usr/bin/git clone https://github.com/CocoaPods/Specs.git master --depth=1

Cloning into 'master'...
error: RPC failed; result=18, HTTP code = 200
fatal: The remote end hung up unexpectedly
```


```
touch podRepoRemove.sh; chmod c+x  podRepoRemove.sh; vi  podRepoRemove.sh
```


```:podRepoRemove.sh
#!/bin/sh

echo ;
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
echo "【pod repo remove master】";
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
git config --global http.postBuffer 524288000
pod repo remove master

echo ;
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
echo "【pod setup --verbose】";
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
pod setup --verbose

echo ;
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
echo "【pod install】";
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
pod install --verbose
```

参考リンク
pod installが永遠に終わらない
http://d.akiroom.com/2015-08/pod-install-forever/

「pod install」したら全然動かなくてワロタ
http://aipacommander.hatenablog.jp/entry/2016/01/01/231114
Rails インスタンスメソッド内部でselfを使うべきか

書き方のハナシです。

[bbatsov/ruby-style-guide](https://github.com/bbatsov/ruby-style-guide#no-self-unless-required)によると、

```
# bad
def ready?
  if self.last_reviewed_at > self.last_updated_at
    self.worker.update(self.content, self.options)
    self.status = :in_progress
  end
  self.status == :verified
end

# good
def ready?
  if last_reviewed_at > last_updated_at
    worker.update(content, options)
    self.status = :in_progress
  end
  status == :verified
end
```
必要でない時にはselfは書かないほうが主流のようです。

ですが、

>  Avoid self where not required. (It is only required when calling a self write accessor.) [link]


とあるように、write_accessorのときは明示的にself書く必要があります。

まぁ考えてみれば、write_accessorのときは、

```
method_name = some_value
variable_name = some_value
```

のように、変数定義なのか、メソッド呼び出しなのか区別つかないですモンね。だからself明示する必要ありますね。

とまぁそんなバグがあって、考えたので、ここに記しました。
Raspberry Pi セットアップマニュアル（備忘録）Part 1

今後の再セットアップやメンテ時に役立つよう、作業記録をマニュアル化したいと思い作成した自分用の備忘録メモ的な記事です。
##**Raspberry Pi セットアップマニュアル（備忘録）Part 1**
#####**〜下準備からOSインストール、初回起動まで〜**
-----
######使用機種・環境（2016年3月現在）
```
Raspberry Pi 2 B+
OS:Raspbian Jessie（NOOBS 1.8.0にてインストール）
microSDカード：32GB（class10）
USBキーボードとUSBマウス（インストールおよび初回起動時に必要）
USBメモリ(16GB) （外付けhdd的用途で使用予定）
micro USBケーブルとUSB電源アダプタ
※電源アダプタはスマホ充電用のものとかでOK。あるいはPCのUSB端子でもいける。

母艦PC／Mac mini (Late2012)
OS:OS X El Capitan 10.11.3
```
-----
###**microSDカードの準備（フォーマット）**

Macのディスクユーティリティよりも *SDフォーマッター* というソフトを使ったほうが確実とのことなので、
下記サイトからダウンロードしてMacにインストールする。

https://www.sdcard.org/jp/downloads/formatter_4/

*SDFormatter* を起動。該当のmicroSDカードを選択。
[オプション]はいじる必要無し。クイックフォーマットでOK。
カードの名前は「RASPBERRY」にした。--> [フォーマット] ボタンをクリック。
フォーマット終了後、microSDカード「RASPBERRY」ディスクがMacのデスクトップに表示されたらOK。

###**microSDカードの準備（NOOBSインストーラの作成）**

下記公式サイトから NOOBS インストーラのZIPファイルをダウンロード。
（Offline and network install 版の方をダウンロードした）

https://www.raspberrypi.org/downloads/noobs/

ダウンロードされたzipファイル（NOOBS_v1_8_0.zip）を解凍。
展開された「NOOBS_v1_8_0」フォルダの中身を丸ごとmicroSDカード「RASPBERRY」にドラッグ＆ドロップでコピー。

「RASPBERRY」を取り出して準備完了。

-----
###**Raspberry Pi のセッティング**

Macから取り出したmicroSDカードを差し込む。
HDMIケーブルでPCモニタorテレビに接続する。
USBマウスとUSBキーボードを接続する。
micro USBケーブルとUSB電源アダプタで電源を取る。
（私はMacのUSB端子に差し込んで使っている）

###Raspbian OS のインストール

モニタに以下の画面が表示される
![IMG_1595.jpg](https://qiita-image-store.s3.amazonaws.com/0/115994/02ad7bf0-8417-1d48-ff5f-e7e4a5f0d110.jpeg)


Raspbian [RECOMMEND] にチェックマークを入れてから
[ Install (i) ] をクリックして実行する。
※Language はこの時点では English のまま(文字化けするため)、keybord は一応 jp にしておく
![IMG_1596.jpg](https://qiita-image-store.s3.amazonaws.com/0/115994/7ac19d9c-244f-9507-89ed-f0763a0b40ca.jpeg)


だいたい15分ぐらい待つとインストール完了のアラートが出るので [OK] ボタンをクリック。
自動的に再起動される。
![IMG_1597.jpg](https://qiita-image-store.s3.amazonaws.com/0/115994/1741c7fa-b210-0ac5-b093-8da71624d321.jpeg)


初回起動時は起動処理完了後オートログインでいきなりGUIデスクトップが立ち上がる。
![IMG_1599.jpg](https://qiita-image-store.s3.amazonaws.com/0/115994/44c751a5-139a-cd39-e260-19b6cc26bcb9.jpeg)

-----
今回はインストールから初回起動まででした。
以上。（つづく）
実行時間が3600秒を超える、chefのレシピがあるときは、timeoutを設定するとよいときもある。

# 概要

普段、test-kitchenでテストをしながら作っていて、エラーがでないことは確認している。
あるとき、ova作りたいというときに vagrant up すると、エラーになることがある。
自分の場合は、キャッシュやproxyのプラグインを使っているので、それの恩恵がないときに、起こるような気がする。

* [fgrehm/vagrant-cachier: Caffeine reducer](https://github.com/fgrehm/vagrant-cachier)
* [tmatilai/vagrant-proxyconf: Vagrant plugin that configures the virtual machine to use proxies](https://github.com/tmatilai/vagrant-proxyconf)

# 結論

実行時間が3600秒を超える、chefのレシピがあるときは、timeoutを設定するとよいときもある。

そのような場合は、timeout がつけられるものはつけると、うまくいくかもしれない。
分割するのがよいような気もするが、それはケースバイケースかなと。

# エラー発生時のログの例

```
==> default: * script[recipe_bit_wf_install] action run
==> default: [2016-03-07T18:27:30+09:00] INFO: script[recipe_bit_wf_install] ran successfully
==> default:
==> default: - execute "bash"  "/tmp/chef-script20160307-1860-an36yo"
==> default:
==> default:
==> default:
==> default: Running handlers:
==> default: [2016-03-07T18:27:30+09:00] ERROR: Running exception handlers
==> default: Running handlers complete
==> default:
==> default: [2016-03-07T18:27:30+09:00] ERROR: Exception handlers complete
==> default: Chef Client failed. 25 resources updated in 01 hours 41 minutes 11 seconds
==> default: [2016-03-07T18:27:30+09:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
==> default: [2016-03-07T18:27:30+09:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
==> default: [2016-03-07T18:27:30+09:00] ERROR: script[recipe_root] (basicsetup::galaxy_bit_wf_2015_setup line 42) had an error: Mixlib::ShellOut::CommandTimeout: Command timed out after 3600s:
```
Paizaで美少女とPythonを学んでみた#01



[Pythonで彼女ができる](https://paiza.jp/poh/ando)と噂のPaizaさんで[美少女とPythonが学べる](https://paiza.jp/learning)サービスが始まったみたいなのでちょっと試してみました。ちなみに私は最低限Pythonは知っていますが、Pythonの社内布教に使える教材探しの一貫で試しています。入門1/2があるようなのでまずは入門1を試しています。


## 入門編(約60分)
## chapter1:Pythonとは？ (約3分)


* 対象者
    * Python初学者
    * メールとかタイピングが最低限できる程度
    * (あるとよい)HTML/CSSの軽い知識
    * Python3で記載

* Pythonの概要
    * WEBサービスや機械学習で使える
    * Google３大言語の一つ
    * スクリプト言語
    * 簡単に書けることを心がけている
    * ライブラリが豊富


## chapter2:Pythonでプログラムを書いてみよう (3:21)

* Pythonでプログラムをかく
* PAIZAラーニングの使い方の説明
    * 動画を見ながらコーディング、結果の確認ができる
    * (説明はないが)Aceエディタベース

* HELLO WORLDを画面に出す
* printの説明から
* 若干画面が動画と違うけど気にならない程度かな
* 間違えやすいポイントの紹介
    * 全角をまちがってつかっているとき

### 演習課題
* ログインすることで演習課題の採点ができるようになる
* 5題
* Pythonというよりはプログラミングの初歩の初歩の問題




## chapter3:03:コメントでプログラムを見やすく！(3:47)
* コメントはプログラムを人間が読むときのメモ
* #から行末までがコメント
* ""の間の#はコメントとしては動作しない
* プログラムの一部をコメントで無効化することをコメントアウトという
* '''から'''までは複数行でコメント扱いになる
    * ここはちょっと飛ばして説明しているのでしょう
* 　# coding: utf-8はPythonのコードがUTF-8で書いてあることを明示する大事なもの

### 演習課題

* 全２題
* コメントアウトの使い方

## chapter4:HTMLを表示してみよう(4:11)

* print文でhtmlタグを合わせて表示させる
* paiza.ioの出力欄はTEXTかHTMLで結果を表示できる
* h1/b/p/brタグ等がでてくる
* print関数は行末に改行コードが追加される話
* 複数行文字列は'''から'''で囲むことで出来る
* 半角カンマで文字列をつなげても改行なしで表示できる
* ```print('HOGE', end="")```でも改行を省ける


### 演習課題

* 全2題
* print文中にhtmlタグを追加する演習


## chapter5:変数を使えるようになろう(3:24)

* 変数とは一時的にデータを入れておく入れ物
* 重複する文字列を変数にしておけば変換が簡単
* = をつかって代入する
* 変数 + 文字列で結合できる

### 演習課題
* 全４題
* このあたりからたまに演習課題のジャッジに時間がかかってエラーになったりした

## chapter6:サイコロを作ろう(4:25)
* ランダムに数値を表示するプログラム
* 変数には文字列だけでなく数字も入れられる
* 文字列と違って引用符を付けない
* 文字列と連結するときは ``` str(数値が入った変数) + 文字列```とする
* random/randintを使う
* ```random.random()```は0-1の中の乱数
* ```random.randint(1,100)```は1,100の中の乱数
* importが登場
    * importとは組み込み
    * モジュールを使う
    * モジュール.関数といった形で使う
    * print/str等は標準で組み込まれている

* ```print()```の()の中身は引数
* 関数の処理結果を戻り値という

### 演習課題

* 全２題
* ここで学習レベル 6にあがった

## chapter7:演算子で計算してみよう(4:25)

* 数値計算のやりかた
* 再代入しない限り変数の中身自体は変化しない
* 演算子(+ / = 等)で計算を行なう
* 基本的な演算子
    * 代数演算子
        * +, -, *, /, % 等
        * +,- より * / が優先される
        * 優先順位を明示するには```()```を使う

### 演習課題

* 全４題
* 


## chapter8:値段を計算してみよう (3:17)

* ランダムにりんごの個数が決定されるので、それに単価を掛けて合計を求める
* randintの結果自体に*100すれば100刻みに個数を取得できる

### 演習課題

* 全1題
* なぜかテストケースをパスできないので模範解答をみたところ問題文にはない句読点を出力結果に含める必要があった・・・

## chapter9:データの型を覚えよう(3:32)
* 文字列なら引用符、数字ならそのまま
* プログラミングには数字や文字列等様々なデータ型がある
* 文字列の連結としての+と数字の+の違い
* 数値データと文字列データの結合はデータ型が違うのでそのままではできない(strを使う)

### 演習課題

* 全3題
* 異なるデータ型同士の演算

## ざっくりとした感想

とりあえず入門1を終えました。Pythonらしところはまだでてきません。本当にプログラミング初心者がPythonを学び始めるための教材というレベル感です。プログラミング入門書であれば1章に相当する内容を丁寧にやっている感じでした。時間を見つけて入門2も確認したいと思います。

ちなみに、全編「霧島京子」ちゃん(cv: 上間江望)というキャラクターの音声ガイダンス付きです。Paizaの人気キャラクターらしいです。若干早口で進みますが、同じく動画で学習できるドットインストールさんと比べると少しゆっくりな口調でしょうか。特に追いてかれる感じはありませんでした。

動画中も基本的に、コーディング画面しか写らず、「霧島京子」ちゃんはほとんど写りませんので社内でやっても恥ずかしくないでしょう。
Elixirでtrotを使ってみる

> Trot is an Elixir web micro-framework based on Plug and Cowboy.

TrotはPlugとCowboyで作られたマイクロWebフレームワークらしいです。

rubyのsinatraと同じようなことをelixirでもしたくなったので色々探した結果、[trot](https://github.com/hexedpackets/trot)というパッケージを見つけたのでその使い方を簡単に紹介します。

# 作る

## 準備
`mix new trot_sample`
今回はTrotSampleというプロジェクトをmixで作りました。
まずはmix.exsに依存関係を追加

```mix.exs
  def application do
    [application: [:trot]]
  end

  defp deps do
    [{:trot, github: "hexedpackets/trot"}]
  end
```

## 設定と実装

READMEに書いてあるようにconfig/config.exsに追記します。

```config/config.exs
use Mix.Config

config :trot, :port, 4000
config :trot, :router, TrotSample
```

今回は最低限の設定で。

あとはメインとなるRouterを書いていきます。

```lib/trot_sample.ex
defmodule TrotSample do
  use Trot.Router

  get "/ping" do
    "pong"
  end

  get "double/:number" do
    number |> String.to_integer |> (&(&1 * 2)).() |> Integer.to_string
  end

  post "/echo" do
    {:ok, body, conn} = read_body conn
    body
  end

  post "/hello" do
    conn = fetch_query_params(conn)
    "Hello, #{conn.params["name"]}!"
  end

  get "/json" do
    %{lang: "elixir"}
  end
end
```

上から順に

* 単純なGET
* URL中のパターンマッチ
* POSTのbodyを返す
* POSTのクエリパラメータを返す
* JSONの返却

をしています。

リクエストのbodyは`read_body`、パラメータは`fetch_query_params`を使う必要があるのですが、READMEには全く書いてなくてものすごく悩みました。結局Plugについて調べている最中に発見しました。

ところでパイプラインの途中で匿名関数を使うときに`(&(&1 * 2)).()`や`(fn x -> x * 2 end).()`と書かないといけないのはどうにかなりませんかね？

# 叩く

起動して叩いてみます

```shell
$ mix trot.server
```

```shell
$ curl http://localhost:4000/ping
pong
$ curl http://localhost:4000/double/10
20
$ curl -d "are you ok?" http://localhost:4000/echo
are you ok?
$ curl -d "" http://localhost:4000/hello?name=techno
Hello, techno!
$ curl http://localhost:4000/json
{"lang":"elixir"}
```

まだ試していませんがテンプレートをレンダリングすることもできるようです。

# 静的コンテンツ
`static`の使い方に若干嵌ったので・・・

trotのソースでは`static`は以下のように定義されています。

```trot.ex
  @static_root Path.relative_to_cwd("priv/static")

~~
~~

  defmacro static(at, from), do: static_plug(at, from)

  defmacro static(at), do: static_plug(at, "/")

  defp static_plug(at, from) do
    quote do
      path = Path.join(@static_root, unquote(from))
      @plugs {Plug.Static, [at: unquote(at), from: path], true}
    end
  end
```

従って

```static.ex
def MyRouter do
  static "/css", "assets"
end
```

と書くと、内部で`Path.join(@static_root, "assets")`のようなコードがマクロによって生成されるので、静的コンテンツは`priv/static/assets/`以下に置く必要があります。そして、`/css/~`というパスのリクエストによってコンテンツが返されます。

例えば`/static`にファイルを置いて、`/assets/~`というパスのリクエストによって静的コンテンツを返したい場合は

```static.ex
defmodule MyRouter do
  @static_root "/"
  static "/assets", "static"
end
```

あるいは

```static.ex
defmodule MyRouter do
  @static_root "static"
  static "/assets"
```

と書けば良いわけですね。

# 参考
[hexedpackets/trot: An Elixir web micro-framework.](https://github.com/hexedpackets/trot)
[[Elixir+Trot] Trot-Frameworkを使って"Hello Trot!!"するだけの簡単なお仕事・・・](http://qiita.com/darui_kara/items/1629278b4e0aad6ebdf4)
[週刊Elixirライブラリ2015-3 - ハードリカーエンジニア](http://d.hatena.ne.jp/hayabusa333/20150705/1436055351)
RLMResults, RLMArrayでBlocksKitのようにmap, select, reject等を使いたい

#### 動機

Realmに触っていたときに、前から好きで使ってた[BlocksKit](https://github.com/zwaldowski/BlocksKit) のメソッドが使えなかったのでBlocksKitを参考にして拡張してみました。
最低限のメソッドしか実装してないですがあしからず

### ゴール

```
RLMResults *result = [RLMObject objectsWhere:@"id < 10"];
[results bk_map:^id(id obj){ block }];
```

のように使いたい。

### 拡張 (RLMResults+Block.m)

```objc
- (void)rlm_each:(void (^)(id obj))block;
{
    NSParameterAssert(block != nil);
    for (id obj in self) {
        block(obj);
    }
}

- (void)rlm_eachWithIndex:(void (^)(id obj, int idx))block
{
    NSParameterAssert(block != nil);
    
    int index = 0;
    for (id obj in self) {
        block(obj, index);
        index++;
    }
}

- (id)rlm_match:(BOOL (^)(id obj))block;
{
    NSParameterAssert(block != nil);
    
    for (id obj in self) {
        if (block(obj)) {
            return obj;
            break;
        }
    }
    
    // not match
    return nil;
}

- (NSArray *)rlm_map:(id (^)(id obj))block
{
    NSParameterAssert(block != nil);
    NSMutableArray *result = [NSMutableArray array];
    
    for (id it in self) {
        id value = block(it) ?: [NSNull null];
        [result addObject:value];
    }
    
    return result;
}

```


### 拡張 (RLMArray+Block.m)

```objc 
- (void)rlm_each:(void (^)(id obj))block
{
    NSParameterAssert(block != nil);
    
    for (id obj in self) {
        block(obj);
    }
}

- (void)rlm_eachWithIndex:(void (^)(id obj, int idx))block
{
    NSParameterAssert(block != nil);
    
    int index = 0;
    for (id obj in self) {
        block(obj, index);
        index++;
    }
}

- (id)rlm_match:(BOOL (^)(id obj))block
{
    NSParameterAssert(block != nil);
    
    for (id obj in self) {
        if (block(obj)) {
            return obj;
            break;
        }
    }
    
    // not match
    return nil;
}

- (NSArray *)rlm_map:(id (^)(id obj))block
{
    NSParameterAssert(block != nil);
    
    NSMutableArray *result = [NSMutableArray array];
    for (id obj in self) {
        id value = block(obj) ?: [NSNull null];
        [result addObject:value];
    }
    
    return result;
}
```
UIView+ViewFrame.swift

http://qiita.com/usagimaru/items/360c20e0ed15b33d9eaf の Swift 版。

```swift:使い方
view.x = 10
view.width = 100
view.y = view.height
```

```swift:ViewFrame
import UIKit

extension UIView {
	var origin: CGPoint {
		get {
			return self.frame.origin
		}
		set {
			var r = self.frame
			r.origin = newValue
			self.frame = r
		}
	}
	
	var x: CGFloat {
		get {
			return self.frame.origin.x
		}
		set {
			var r = self.frame
			r.origin.x = newValue
			self.frame = r
		}
	}
	
	var y: CGFloat {
		get {
			return self.frame.origin.y
		}
		set {
			var r = self.frame
			r.origin.y = newValue
			self.frame = r
		}
	}
	
	var size: CGSize {
		get {
			return self.frame.size
		}
		set {
			var r = self.frame
			r.size = newValue
			self.frame = r
		}
	}
	
	var width: CGFloat {
		get {
			return self.frame.size.width
		}
		set {
			var r = self.frame
			r.size.width = newValue
			self.frame = r
		}
	}
	
	var height: CGFloat {
		get {
			return self.frame.size.height
		}
		set {
			var r = self.frame
			r.size.height = newValue
			self.frame = r
		}
	}
}
```

https://gist.github.com/usagimaru/97b1bfd49251a0a2b8ab4c5dfcdd95c7
CentOS7でChainerを使う【環境構築編】


# 環境概略
- Mac OS X Yosemite 10.10.5
- Vagrant 1.7.4
- CentOS 7 x64

# CentOSの構築
まずは、vagrantでMacに`CentOS7`環境を作成します。

```bash
vagrant box add centos_7_x64 https://github.com/holms/vagrant-centos7-box/releases/download/7.1.1503.001/CentOS-7.1.1503-x86_64-netboot.box

mkdir vagrant_centos7
cd vagrant_centos7
vagrant init centos_7_x64
```


# CeontOS7にインストールするもの
`vagrant ssh`でログインした後に実行します。

```bash
su
yum -y install python-devel
pip install setuptools --upgrade
pip install numpy --upgrade
pip install chainer
yum -y install git
```

# サンプルをダウンロードします
`CentOS7`にログインして作業を行います。

```bash
mkdir sample
cd sample
git clone  https://github.com/pfnet/chainer
cd chainer/examples/mnist/
python train_mnist.py
```
OkHttpを利用した画像取得方法（超簡易版）


[API23でapache関連のモジュールが軒並み使えなくなっている](http://developer.android.com/intl/ja/sdk/api_diff/23/changes.html)ことに加え、Volleyが未だにapacheモジュールを利用していることを理由（他にもmavenリポジトリがないとか）に、通信ライブラリをOkHttpへ移行することをよく勧めています。

しかし単に勧めるだけというのも投げっぱなし感があるので、移行に伴う各種処理の記述方法についても、共有していこうと思いました。

というわけでタイトルにも書いてますが、OkHttpを利用した（http上の）画像取得方法の超簡易版です。

[サンプルプロジェクトもアップしています。](https://github.com/yamacraft/android.GetImageViewPager)

## 該当コード

```java:GetImageAsyncTask.java

/**
 * ResponseBodyの取得
 */
private static ResponseBody getResponse(@NonNull String url) {
	Timber.d("get url:%s", url);
	Request request = new Request.Builder().url(url).get().build();
	try {
	    Response response = new OkHttpClient().newCall(request).execute();
	    if (!response.isSuccessful()) {
	        Timber.d("response error %d: %s", response.code(), response.message());
	        return null;
	    }
	    return response.body();
	} catch (IOException e) {
	    Timber.e("IOException %s", e.getMessage());
	    return null;
	}
}

/**
 * 指定画像の取得（同期処理）
 */
@WorkerThread
private static Bitmap downloadFile(@NonNull String url) {
    ResponseBody response = getResponse(url);
    if (response == null) {
        return null;
    }

    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(response.byteStream(), null, options);
    Timber.d("original image w:%d h:%d", options.outWidth, options.outHeight);

    options.inSampleSize = 1;
    while ((options.outWidth * options.outHeight) / options.inSampleSize > MAX_IMAGE_SIZE * 4) {
        options.inSampleSize *= 2;
    }
    Timber.d("options.inSampleSize: %d", options.inSampleSize);

    options.inJustDecodeBounds = false;
    response = getResponse(url);
    if (response == null) {
        return null;
    }
    Bitmap bitmap = BitmapFactory.decodeStream(response.byteStream(), null, options);
    response.close();
    return bitmap;
}
```

通信に成功すると、ResponseBodyにHTTPステータスコードやストリーム情報が格納されます。
`byteStream()`によってInputStreamが取得できるため、通信のやりとり以外は通常のストリームからBitmap生成するやり方になります。

通信周りも`response.isSuccessful()`でステータスコードのチェックが入っていますし、`close()`処理もおおもとでException周りをキャッチしているので、ネストも少なく非常に見やすいんじゃないかなと思っています。

ただし、これだけの記述では **キャッシュ処理がいっさい働いていない**ので、注意してください。

ちなみに`new OkHttpClient().newCall(request).execute()`の部分を

```java:非同期呼び出し.java
new OkHttpClient().newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Request request, IOException e) {
    }

    @Override
    public void onResponse(Response response) throws IOException {
    }
});
```
と変えることで、通信部分を非同期にできる（はず）ですが、今回の場合は結局Bitmap変換部分もあるので、まとめてAsyncTaskやThreadで処理したほうが見た目にもわかりやすいし、そもそもこのレベルの内容（取得して表示するだけ）であれば、PicassoやGlideを使った方がいいです（本末転倒）。
javascriptでブラウザの言語設定を取得する

サーバ側でブラウザの言語設定を見るには `Accept-Language` ヘッダを読めばいいけど、クライアント側でそれに該当する情報を取得したくなったので、調査結果をメモ。

## 言語設定を取得するスクリプト

とりあえず結果があればいい人向けに、最初に結論を書いておきます。

``` javascript
// 最優先の言語だけ取得
var language = (window.navigator.languages && window.navigator.languages[0]) ||
            window.navigator.language ||
            window.navigator.userLanguage ||
            window.navigator.browserLanguage;

// クライアント側で受け付けている言語リストを取得
var languages = window.navigator.languages || [
            window.navigator.language ||
            window.navigator.userLanguage ||
            window.navigator.browserLanguage
    ];
```

## クロスブラウザのための工夫

### IE対応

「[JavaScript でブラウザの言語設定を取得](http://easyramble.com/get-language-setting-by-javascript.html)」を参考にしました。
IEやOperaは`navigator.language`が存在しないので、`navigator.userLanguage`と`navigator.browserLanguage`を参照する必要があるらしい。

### `navigator.language`の挙動の差

FirefoxをChromeはどちらも`navigator.language`に対応していますが、微妙に挙動が違います。

MDNによるとFirefoxでは`navigator.language`は以下のような挙動をするそうです。

- `navigator.languages`はAccept-Language HTTPヘッダと同じ配列を返す
- `navigator.language`はAccept-Language HTTPヘッダの一番先頭の要素

しかし、Chromeでの挙動を検証してみたところ、
2016年3月7日現在の最新版の Chrome 49.0.2623.75 では以下のような挙動をしました。

- `navigator.languages`はAccept-Language HTTPヘッダと同じ値を返す
- `navigator.language`は**Accept-Language HTTPヘッダの設定に関わらず常にブラウザUIの言語設定を返す**

Chromeの場合、「言語と入力の設定」から言語の優先順位を変えても`navigator.language`は変わりません。
どのブラウザであっても Accept-Language HTTPヘッダと同じ値を取得したいので、一番最初に`navigator.languages`を見るようにしてあります。

## 参考

- [JavaScript でブラウザの言語設定を取得](http://easyramble.com/get-language-setting-by-javascript.html)
- [NavigatorLanguage.languages - Web APIs | MDN](https://developer.mozilla.org/en/docs/Web/API/NavigatorLanguage/languages)
- [NavigatorLanguage.language - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorLanguage/language)
- [browserLanguage property](https://msdn.microsoft.com/ja-jp/library/ms533542(v=vs.85).aspx)
andoroid studio  メモリーエラーが出た時のAVD HAXMメモリー変更

下記のようなエラーが出た時の訂正方法


HAX is not working and emulator runs in emulation mode emulator: The memory needed by this AVD exceeds the max specified in your HAXM configuration. 
emulator: AVD RAM size = 1536 MB emulator: 
　　　　　　HAXM max RAM size = 512 MB emulator:

AVDに必要なメモリーが、
HAXMのマックスメモリーを超えているよ！！


HAXMメモリーでは５１２mbしか使えないのに、
AVDに1536MBも割り振っているので出ているエラー。


AVDマネジャーより詳細設定で、

Memory and storage 
RAM ----- MB
VM heap
SD card

のramを、HAXM max RAM sizeのと同じにする。

この場合だと、512mbにする。（多分それ以下でも動く）

あまり割り振りを少なくすると挙動しなくなるようです。


以上。