OmniAICreator/Qiita-1.07M huggingface dataset:
alexaからnode-redを用いてNAS上の音楽を操作する

#出来た事
NAS上の音楽をAlexaから音声入力で操作、別のスピーカーで音楽を鳴らす。
簡単にできる事としては以下の通り

* 再生(mpc play)
* 停止(mpc stop)
* 次の曲を再生(mpc next)
* 前の曲を再生(mpc prev)
* 音量の指定(mpc volume)

#全体図
alexaのNode-RED Alexa Home Skill Bridgeを使ってラズベリーパイ上のMPDサーバーをMPCコマンドで操作する。ラズベリーパイには、NAS上の音楽リソースがおいているフォルダをマウントする。
ラズベリーパイからは、USB DACを使って別のスピーカーに接続し、そのスピーカーで音楽を再生する。

![全体図.png](https://qiita-image-store.s3.amazonaws.com/0/226980/41228b2c-5478-1a8d-c538-f685d6b39901.png)

#ラズパイとNode-Red
以下の記事などを参考にセットアップ
[Amazon Echoとラズパイで、音声で照明をon/offする](https://qiita.com/kikuzo/items/753b5065dde9633bda18)

#mpdとmpc
以下の記事などを参考にセットアップ
[Rapberry Pi に USB DAC をつないでオーディオサーバーにする (接続編)]
(https://qiita.com/henri_t/items/33a514ae4ac0fda89ee0)

#Node-Red上のフロー
![node.PNG](https://qiita-image-store.s3.amazonaws.com/0/226980/9eac6c2c-8635-e73b-e488-ad11787f85d9.png)

以下のJsonをNode-Redで読み込むとフローが作成されます

``` json
[{"id":"f503001b.95204","type":"exec","z":"4b16e69e.6f2308","command":"mpc play","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":633.0000038146973,"y":180.29999923706055,"wires":[[],[],[]]},{"id":"23a5391.93962c6","type":"switch","z":"4b16e69e.6f2308","name":"","property":"command","propertyType":"msg","rules":[{"t":"eq","v":"TurnOnRequest","vt":"str"},{"t":"eq","v":"TurnOffRequest","vt":"str"},{"t":"eq","v":"IncrementPercentageRequest","vt":"str"},{"t":"eq","v":"DecrementPercentageRequest","vt":"str"},{"t":"eq","v":"SetPercentageRequest","vt":"str"}],"checkall":"true","outputs":5,"x":390,"y":180,"wires":[["f503001b.95204"],["46ab8f67.8e599"],["9c02eead.a1221"],["72d54e3b.91397"],["8eef9581.cdbd08"]]},{"id":"46ab8f67.8e599","type":"exec","z":"4b16e69e.6f2308","command":"mpc stop","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":632.300048828125,"y":246.80000114440918,"wires":[[],[],[]]},{"id":"9c02eead.a1221","type":"exec","z":"4b16e69e.6f2308","command":"mpc next","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":633.2999877929688,"y":323.7999954223633,"wires":[[],[],[]]},{"id":"72d54e3b.91397","type":"exec","z":"4b16e69e.6f2308","command":"mpc prev","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":633.3000526428223,"y":399.80000495910645,"wires":[[],[],[]]},{"id":"8eef9581.cdbd08","type":"exec","z":"4b16e69e.6f2308","command":"mpc volume","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":643.2999877929688,"y":480.7999954223633,"wires":[[],[],[]]},{"id":"2963d1ea.3e11ae","type":"alexa-home","z":"4b16e69e.6f2308","conf":"","device":"","acknoledge":true,"name":"","topic":"","x":230,"y":180,"wires":[["23a5391.93962c6"]]}]
```
#あとがき
今のところ、曲の指定などはやっていません。mpcのコマンドを動かしているだけなので、やりようを変えれば色んなことが出来るかも...
ただ、曲の指定等は素直に他のmpdクライアントアプリ使った方が楽かもしれません

#参考にした記事など
[Amazon Echoとラズパイで、音声で照明をon/offする](https://qiita.com/kikuzo/items/753b5065dde9633bda18)
[Rapberry Pi に USB DAC をつないでオーディオサーバーにする (接続編)]
(https://qiita.com/henri_t/items/33a514ae4ac0fda89ee0)
PHP PDO、cURLを使う方法（環境構築の備忘録）

PHPでPDOやcURLを使う際、とても手こずってしまったので記録に残しておきます。環境はCentOS7です。

#状況
###PDOが動かない！
データベースを使いたかったためPDOを使用しようと試みたところ、ローカル環境（Windows）では動いたがConoHa上では500エラーが発生し、動かなかった。そこで、レンタルサーバーのロリポップ上でも試してみると動いた。
###cURLのcurl_file_createが動かない！
ファイルをConoHaからHTTP通信で送信しようとしたところ、curl_file_create以降が実行されなかった。そこで、ロリポップ上でも試してみるとやはり動いた。なお、今回はローカル環境（Windows）では動かなかった。

#原因
###PDO
php-mysqliがインストールされていないのが原因だった（恥ずかしい…）。PHPを始めたばかりで、ライブラリの概念を知らなかった。
###curl_file_create
今回はPDOの時と同一の原因を疑い、真っ先に再度インストールを行った。php -mで確認すると、無事インストールできていた。しかし、動かない…。PHP5.4からPHP7にアップデートするとなぜか動くようになった。

#問題解決用のコード
###PDOを使えるようにする（PHP5.4の時）

```
# yum -y install mariadb-server
# yum -y install php-mysqli
# systemctl restart httpd.service
```

＜参考にさせていただいた記事＞
[Linux(CentOS7)でWebサーバーを構築する。 -MySQL導入編-](https://qiita.com/sango/items/e6eaa5694cd4043f3c4e#_reference-d3ca28cfafa807ac8c2b)
[Linux(CentOS7)でWebサーバーを構築する。 -導入編Final-](https://qiita.com/sango/items/736d98d90203ab4634c6#_reference-fc2b81ae9888a2754d55)

###PDOを使えるようにする（PHP7.xの時）

```
# yum install --enablerepo=remi,remi-php70 php-mysqlnd
```

＜参考にさせていただいた記事＞
[php7をcentos6系にインストールしてPDOを使用する](http://wakuwakupush.hatenablog.com/entry/20170412/1492006263)

###PHP7をインストールし、curl_file_createを設定する
まず現在入っているPHPを削除

```
# sudo yum remove php-*
```

次に、PHP7をインストール

```
yum install epel-release
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
yum install --enablerepo=remi,remi-php71 php php-devel php-mbstring php-pdo php-gd php-xml php-mcrypt

yum -y install mariadb-server
yum -y install php-mysqli
```

参考：[CentOS7にPHP7をyumでインストールする](http://wakuwakupush.hatenablog.com/entry/20170412/1492006263)
Canvasで元に戻す（Undo），やり直し（Redo）を実装する方法

[これ](https://chrome.google.com/webstore/detail/webpage-capture-and-paint/mdglibpddhkadiadabckagelmmomoobn)を作った時の知見を忘れないうちにメモ

# getImageDataとputImageData
canvasのcontext.getImageData()を用いることで、描画されているラスタのデータを範囲指定してピクセルの配列（ImageData）として取得することができます。
また、取得したImageDataはputImageData()で描画を行うことができます。

ImageDataをスタックとして変数に保持しておけば元に戻す・やり直すという動作を実現させることができます。
それぞれの配列の挙動はFIFOになるように実装します。

# サンプルコード
```javascript
let $canvas = $('#myCanvas');
// contextを取得
let ctx = $canvas[0].getContext('2d');
// スタックしておく最大回数。キャンバスの大きさの都合などに合わせて調整したら良いです。
const STACK_MAX_SIZE = 5;
// スタックデータ保存用の配列
let undoDataStack = [];
let redoDataStack = [];

// canvasへの描画処理を行う前に行う処理
function beforeDraw() {
    // やり直し用スタックの中身を削除
    redoDataStack = [];
    // 元に戻す用の配列が最大保持数より大きくなっているかどうか
    if (undoDataStack.length >= STACK_MAX_SIZE) {
        // 条件に該当する場合末尾の要素を削除
        undoDataStack.pop();
    }
    // 元に戻す配列の先頭にcontextのImageDataを保持する
    undoDataStack.unshift(ctx.getImageData(0, 0, $canvas[0].width(), $canvas[0].height()));
}

function undo () {
     // 戻す配列にスタックしているデータがなければ処理を終了する
    if (undoDataStack.length <= 0) return;
    // やり直し用の配列に元に戻す操作をする前のCanvasの状態をスタックしておく
    redoDataStack.unshift(ctx.getImageData(0, 0, $canvas[0].width(), $canvas[0].height()));
    // 元に戻す配列の先頭からイメージデータを取得して
    var imageData = undoDataStack.shift();
    // 描画する
    ctx.putImageData(imageData, 0, 0);
}

function redo () {
    // やり直し用配列にスタックしているデータがなければ処理を終了する
    if (redoDataStack.length <= 0) return;
    // 元に戻す用の配列にやり直し操作をする前のCanvasの状態をスタックしておく
    undoDataStack.unshift(ctx.getImageData(0, 0, $canvas[0].width(), $canvas[0].height()));
    // やり直す配列の先頭からイメージデータを取得して
    var imageData = redoDataStack.shift();
    // 描画する
    ctx.putImageData(imageData, 0, 0);
}

```

# 関連リファレンス
https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/getImageData
https://developer.mozilla.org/ja/docs/Web/API/CanvasRenderingContext2D/putImageData
https://developer.mozilla.org/ja/docs/Web/API/ImageData
【備忘録】Synology DS918+ のmariaDB10(mysql) のmy.cnfによるチューニング

自分が再度環境構築をしなければならない場合のメモ

#メモリ増設
PC3-14900 1866MHz SODIM 203pin 8GB x 2
iRamのimac用メモリ8GBを2枚購入して搭載。
→動作OK

#my.cnfの場所

```shell
/volume1/\@appstore/MariaDB10/usr/local/mariadb10/etc/mysql/my.cnf
```
#my.cnfの変更例

```text
[client]
port = 3307
socket = /run/mysqld/mysqld10.sock

[mysqld]
bind-address = 0.0.0.0
port = 3307
socket = /run/mysqld/mysqld10.sock
pid-file = /run/mysqld/mysqld10.pid
skip-external-locking
#key_buffer_size = 16K
key_buffer_size = 16M
#max_allowed_packet = 1M
max_allowed_packet = 16M
table_open_cache = 4
#read_buffer_size = 256K
read_buffer_size =4M 
#read_rnd_buffer_size = 256K
read_rnd_buffer_size = 4M 
#net_buffer_length = 2K
net_buffer_length = 48M 
thread_stack = 240K
innodb_data_home_dir = /var/packages/MariaDB10/target/mysql
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /var/packages/MariaDB10/target/mysql
#innodb_buffer_pool_size = 16M
innodb_buffer_pool_size = 2G 
#innodb_additional_mem_pool_size = 2M
innodb_additional_mem_pool_size = 1G
#innodb_log_file_size = 5M
#innodb_log_buffer_size = 8M
#innodb_flush_log_at_trx_commit = 1
#innodb_lock_wait_timeout = 50
innodb_file_per_table = 1

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash

[myisamchk]
#key_buffer_size = 24M
key_buffer_size = 24M
#sort_buffer_size = 8M
sort_buffer_size = 8M

[mysqlhotcopy]
interactive-timeout

# Please add your custom configuration to here:
!include /var/packages/MariaDB10/etc/my.cnf

```



#SSHを有効にする。

[コントロールパネル][端末とSNMP][ターミナル][SSHサービスを有効化する。]

#(SSH)シェルからmysqlへのアクセス
```shell
/usr/local/mariadb10/bin/mysql -u root -P 3307 -h localhost
```

#共有ファイルの場所

```shell
/volumeXX 以下
```

#経験備忘録
　巨大データ(1G超)は結合想定でテーブル分けが良い。
　巨大テーブルへのクエリでメモリ小さいと[select * from table;]だけでもmysqlクライアントがkillされる。
　RAID5 はシングルディスクと比較しても30～100倍遅い。
　SHR RAID10は高速。
ラズパイ3につないだ超音波センサSRF02から距離値をPythonで読む

　Raspberry Pi3 のi2cピンに，距離センサーであるSRF02という超音波センサーを接続して，超音波が当たった物体までの距離を読み取ることを考えます．

![srf02.jpg](https://qiita-image-store.s3.amazonaws.com/0/232519/094dd8d7-3d06-fd49-3b52-d464ff45abbc.jpeg)

　SRF02は，そのレジスタの中に距離情報を格納しているので，その値を何らかの方法で読み取れば良いことになります．C言語などでも読み取れますが，ここではPythonで読み取ってみます．

　pigpioというライブラリを用いるので，このPythonスクリプトを実行する前に，pigpioを実行することが前提です．

    $ sudo pigpiod




#上位レジスタ0x02 と下位レジスタ0x03を読み込んで距離値に変換する
Beaglebone Black(BBB)につないで使っていた時には，仕様書通りC言語で読めていました．ラズパイ３につないで，pigpio と Pythonで読み取ろうとすると，どうやらBBBとレジスタからのデータの取り出し方が違うようです．
同じやり方で距離に変換してやると，実際の距離とは異なる値になってしまいました．

そこで，
レジスタOx02, 0x03の値を10進数表示して，距離を変えながら調べてみました．
15〜600cmを読み取れるようにした関数が下記です．

```py
#srf02.py
import pigpio
h = pi.i2c_open(BUS, SRF02_I2C_ADDR)
     
def srf02_read(h):
   # レジスタ 0x02, 0x03 の値を読み取る
   high = pi.i2c_read_word_data(h,0x02)
   low = pi.i2c_read_word_data(h,0x03)
       
   low_low=int(bin(low&0b1111111),2)  # lowの下位7bitを抜き出して10進に変換 
                                      # 0-128cmの値が入る．
   low_high=int(bin(low>>15),2)  # lowを15bit右にシフトして10進に変換
                                 # 128-255cmの時に0b1になる
   high_low=int(bin(high&0b11),2)  # highの下位2bitを抜き出す
                                   # 256cm:0b01, 512cm:0b10
   dist =high_low*255+low_high*128+low_low
   return dist
```

実際にこの関数は15cm -- 600cmまでの範囲の距離をほぼ正確に返してくれます．
16cm以下と600cm以上の距離では，このセンサーの性能上正確に距離を測定することができない仕様です．

なぜ，BBBのI2Cと異なるのかは謎ですが，
2byteのデータを格納する順番，つまりインディアンの問題とか，clock streachの問題が有るのかもしれません．

参考URL
http://www.hobbytronics.co.uk/raspberry-pi-i2c-clock-stretching


#２機の超音波センサー間での干渉効果実験 
スチレンボードの壁に，
上の写真の様に２機のSRF02を近づけて，それぞれ距離を測定実験してみました．

SRF02間の間隔が10cm程度と，比較的近いので，お互いに干渉し合う可能性があります．

壁までの距離が30cm前後と比較的近いと，超音波による相互干渉による距離読み取りのノイズはほとんど見受けられませんでした．

むしろ，距離が100cmほどに離れると，数秒に一回，かけ離れた距離が観測されるようです．

参考になれば，幸いです．
txtファイルを書き換える

#txtの書き換え

とあるホームページを作るために記事を募集しまして、そのtxtファイルをhtmlに載せられるように書き換えるプログラムを書いてみました。

テキストファイル

```txt
title

text
```


```python3
with open ('sample.txt', 'r', encoding='utf8') as input:
    txt1 = (input.readline())
    txt2 = (input.readlines())
    y = []
    print(txt2)
    x = ["<!DOCTYPE html>\n     <html>\n      <head>\n        <link rel=\"stylesheet\" href=\"../css/sample.css\">\n        <meta charset=\"utf-8\">\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n        <title>sample</title>\n      </head>\n      <body>\n        <div id=\"wrap\">\n          <h1 id=\"title\">\" ", txt1 ,    "</h1>\n      <p id = \"p\"> )"    ,txt2, "<\p>\n     </div>\n     </body>\n    </html>"]

    y = " ".join(map(str,x))

f = open('sample.txt', 'w', encoding='utf8')
f.write(y)
f.close()
```

とまあ、シンプルです。
ちゃんと動くのでokです。
まあこんな感じのを作りました。
別に問題点はないですが、わからないことが2個。。。

#わからなかった点

- 何がわからなかったかというと一つ目は`x`のリストを作ったのはいいが、リストは横に間延びして見にくい。そして、わざわざ一つ一つに\nを入れていかないと改行にならないのでめんどくささがあった。
- １つめは`with`でのファイルインポートの仕方が`write`のときにどのようにやればよいのかわからなかった。

 ``` 
with open ('sample.txt', 'w', encoding='utf-8')
    write(y)

 ```
だと何を書くのか指定できない。。。

#おわりに
これで仕事が少し減るのでハッピーです。やっぱりプログラミングは効率的で最高。
書き出すときの`with`での記述の仕方をご存知でしたらコメント頂けると幸いです。
配列とループ文を使って条件分岐するサンプル

#最初に

去年の年末から書こうと思ったまま書いてなかったことです
去年作ったゲームで、このアルゴリズムを使いました

もう少し工夫すると、汎用性が上がるかも

#コード

``` csharp

using System;

namespace Test {

	static class Program {
		static void Main() {
			var rand = new Random();
			var num = rand.Next(10);

			TraceNotUseArray(num);
			TraceUseArray(num);
		}

		static void TraceNotUseArray(int num) {
			Console.WriteLine("配列を使わない場合の条件分岐");

			if (num < 3) Console.WriteLine(num + " 番 : 0 - 2");
			else if (num < 5) Console.WriteLine(num + " 番 : 3 - 4");
			else if (num < 6) Console.WriteLine(num + " 番 : 5");
			else if (num < 10) Console.WriteLine(num + " 番 : 6 - 9");

			Console.WriteLine("\n");
		}

		static void TraceUseArray(int num) {
			Console.WriteLine("配列を使った条件分岐");

			foreach(var i in TraceDatas) {
				if (num >= i.Max) continue;

				i.Trace(num);
				break;
			}

			Console.WriteLine("\n");
		}

		static TraceData[] TraceDatas = new TraceData[]{
			new TraceData{ Max = 3, AddStr = "0 - 2" },
			new TraceData{ Max = 5, AddStr = "3 - 4" },
			new TraceData{ Max = 6, AddStr = "5" },
			new TraceData{ Max = 10, AddStr = "6 - 9" },
		};
	}

	sealed class TraceData {
		public int Max { get; set; }
		public string AddStr { get; set; }

		public void Trace(int num) {
			Console.WriteLine(num + " 番" + " : " + AddStr);
		}
	}
}
050plusの電話番号を使ってAWSのアカウント作ろうと思ったらはまってそれを解消した話

# 経緯
AWSを個人アカウントで使用する必要性があったのでアカウント作ろうとしたんですが、どうにも電話認証部分で電話がかかってこないという現象が発生しました。
050plusアプリをAndroidで使用していてかかってこないということはなかったので(SMSは別番号で契約)、困り果ててしまった時の話です。

電話なんてほとんどする機会がないので050plusで普段過ごしていますが、こんな弊害があるとは思いもしませんでした。
まぁ、この運用を変えるの面倒くさいから変える気はありませんが。

# 結論
うだうだ途中を書いてもしょうがないので結論だけ書くとサポートに連絡して電話認証をしました。
電話認証に失敗するとサポートへ連絡するためのリンクがあるので、それから電話認証出来ないんだけどどうすればいい？とコンタクトを取ってやり取りして電話認証を終えた形です。
その際、Amazonのサポートの人から電話をかけて貰う必要があるので、電話番号は必須となります。
原因は聞くの忘れましたが、とりあえず現時点ではダメならサポートに問い合わせしないとダメのようです。

# 注意点
どうもアカウントの設定をきちんとしてないとそもそも電話認証がうまくいかないという話を調べているうちに良く目にしました。
クレジットの設定と電話番号の設定(先頭0抜けに要注意)を見直してみてみるのは必須かと思います。

技術記事って訳ではないですが、原因探る時間がとてつもなく無駄だったので記事にしました。
Travis CIでgitの別のブランチの更新をするなど色々な処理をしてみる

はい、ハマったから書いてます。

# やりたいこと

[maqzとか命名したgulpを使ったサイトビルドシステムでビルドされた、github pagesでホストされているサイト](https://vytfs.github.io/wiki/)で、Travis CIの定期実行を30分おきぐらいに仕掛けました。
それまでは`master/docs`でやっていましたが、まあコミットログが汚染されてしまったので、`gh-pages`ともうひとつ`dist`というブランチを作り、ビルドごとにmasterブランチを更新しないような改良を加えたいと思いました。

あと、フォントを追加したりタイムゾーンを変更したりなどの方法もついでに書いておきます。
ぐちゃぐちゃですがご了承ください。

# ハマった話

- `git worktree`で管理しようと考えましたが、リモートのブランチがmasterしか認識されませんでした。
- docsディレクトリを一回全消去するようにしているため、worktreeで作られた`.git`ファイルも消えてしまいました。

# 具体的な処理の一覧

## 環境変数設定

あまり重要ではありませんが。
`TZ=Asia/Tokyo`はおまけで、タイムゾーンをこれでそうできます。gulp(というかnode.js)はこの値を読むようです。

ユーザーネームluckybeastは私のサブアカウントです。

```yaml
env:
  global:
    - TZ=Asia/Tokyo
    - GIT_ORIGIN_HTTPS=https://github.com/luckybeast/repo.git
    - GIT_ORIGIN_GIT=git@github.com:luckybeast/repo.git
```

## before_install

### タイムゾーンを設定する

```yaml
before_install:
  - sudo timedatectl set-timezone Asia/Tokyo
  - timedatectl
```

環境変数`TZ`でも設定したのですが、連動してくれないので、OSに関連するこちらも更新しなければなりません(一応)。

### GitHubにアップロードする前段階

よくあるコードです。これをやらないと更新できません。詳細な設定は下の記事を参考にしましょう。
**Windowsだとできないので、UNIXライクな環境でやってください。**

https://www.tam-tam.co.jp/tipsnote/program/post11795.html

```yaml
  - openssl aes-256-cbc -K $encrypted_{id}_key -iv $encrypted_{id}_iv -in hoge.enc -out hoge -d
  - cp hoge ~/.ssh/hoge
  - chmod 600 ~/.ssh/hoge
  - echo -e "Host github.com\n\tStrictHostKeyChecking no\nHost github github.com\n\tHostName github.com\n\tIdentityFile ~/.ssh/hoge\n\tUser git\n" >> ~/.ssh/config
  - git config --global user.email "info@suiranfes.com"
  - git config --global user.name "LuckyBeast"
```

### フォントを追加する

```yaml
  - mkdir ~/.fonts/
  - cp fonts/*.ttf ~/.fonts/
  - fc-cache -fv
```

リポジトリの`master/fonts`以下にフォントが格納されているので、それを`~/.fonts/`にコピーします。
そうしたらフォントのキャッシュを更新します(3合目)。

### 別のブランチを操作する(前処理)

```yaml
  - git remote remove origin
  - git remote add origin $GIT_ORIGIN_HTTPS
  - git remote update -p
  - git branch -a
  - git worktree add -B gh-pages docs remotes/origin/gh-pages
  - git worktree add -B dist dist remotes/origin/dist
  - cp -f docs/.git docs.git
```

1. いたんoriginを削除します。
2. originをふたたび設定します。
3. originの情報を取得しなおします。
4. ブランチ一覧を確認します(ただのディスプレイなので削除してもらってOK)
5. リモートの`origin/gh-pages`をローカルな`gh-pages`にチェックアウトしながら、`docs`ディレクトリを作って展開します。
6. 上の処理を`dist`でも行います。
7. `docs`はいっかい全消去してしまうので、必要な`.git`ファイルを退避します。
    * `dist`ではこの操作は必要ないので省略しています。
    * 処理の段階で.gitを残すという手段もアリです。が、私はズボラなのでやりません()

## after_success (push)

```yaml
after_success:
  - cp -f docs.git docs/.git
  - cd docs
  - git add --all
  - git commit -m "Travis CI による自動デプロイ ($TRAVIS_JOB_NUMBER)"
  - '[ "$TRAVIS_BRANCH" == master ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && git push $GIT_ORIGIN_GIT gh-pages'
  - cd ../dist
  - git add --all
  - git commit -m "Travis CI による自動デプロイ ($TRAVIS_JOB_NUMBER)"
  - '[ "$TRAVIS_BRANCH" == master ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && git push $GIT_ORIGIN_GIT dist'
```

1. 退避した`.git`ファイルを戻します
2. docsに移ります。
3. 変更を追加
4. 適当なコメントをつけてコミット
5. 特定の条件が整っていたら && gh-pagesにsshでpushする
6. 2.と同じ
7. 3.と同じ
8. 4.と同じ
9. 5.と同じ
LaTeXでコードを載せるときとか目次の作り方とか．図をfigureや表をtableに変更する方法も

# はじめに
コードとかをLaTeXに載せるとき，どうしていますか？

キャプチャして画像ぺた？

いいえ，listingsパッケージを使いましょう

これを使えば，hello.cというコードLaTex中に挿入できるね．

```latex:
\usepackage[listings]
\lstset{
  ...  % ここは自分で参考から調べてね．（他人任せ）
}


\begin{document}

コード\ref{hello}にHelloWorldのCコードを示す．

\lstinputlisting[caption=HelloWorldのCコード,lavel=hello]{hello.c}

\end{document}
```

# 名前や目次の変更

一番言いたかったことはこの後で，図であれば，図1だったり，図2.3だったりするよね．表も然り．

しかし，このままでは表示されるコードの名前のところがListing1になるので，これをコード1にする．

(コード: HelloWorldのCコード)ってしたい．

```latex: 
% the caption label for it.
\renewcommand{\figurename}{図}
\renewcommand{\tablename}{表}
\renewcommand{\lstlistingname}{コード}

% the header name for the list of it.
\renewcommand{\listfigurename}{図目次}
\renewcommand{\listtablename}{表目次}
\renewcommand{\lstlistlistingname}{コード目次}

\begin{document}

\tableofcontents    % 目次  
\listoffigures      % 図の目次
\listoftables       % 表の目次
\lstlistoflistings  % コードの目次

\end{document}
```

これを使えば，図をfigureにしてみたり，英語の論文にする時に便利そうね☆

個人的にListingsはコードかなぁとか思ってみたり．

あと，lstlistlistingnameってlstのlistingnameのためのlistってなんだよw


# 参考資料

[listings.styパッケージ](http://www.biwako.shiga-u.ac.jp/sensei/kumazawa/tex/listings.html)
[listings package のディレクトリ](https://ctan.org/tex-archive/macros/latex/contrib/listings)
[listings package の pdf](ftp://ftp.u-aizu.ac.jp/pub/tex/CTAN/macros/latex/contrib/listings/listings.pdf)
eslint-find-rulesを使いESlintの全ての項目を設定する

`eslint-find-rules`を使うと設定されていないルールがあるとそれを教えてくれます。

[sarbbottam/eslint-find-rules: Find built-in ESLint rules you don't have in your custom config](https://github.com/sarbbottam/eslint-find-rules)

これを使い`eslint-config`をテストしてやることで新しく入った項目を取り逃すことがありません。

package.json

```json
	"find-new-rules": "npm-run-all --parallel find-new-rules:*",
	"find-new-rules:jest": "eslint-find-rules --unused ./other/test/jest.js",
	"find-new-rules:flow": "eslint-find-rules --unused ./other/test/flow.js",
	"find-new-rules:main": "eslint-find-rules --unused ./index.js",
	"test": "npm run find-new-rules"
```

さらに`GreenKeeper`や`semantic-release`などを組み合わせることで簡単に常に最新の`eslint-config`を保つことが出来ると思います。

自分はESLintの設定を一つずつ見てだいたい4時間ぐらいかけて全ての項目を設定しましたが、既存のconfigを`extends`すれば手間は大きく減ると思います。

## おわりに

jestやflowなど自分の環境に特化したconfigを[akameco/eslint-config-precure: ESLint shareable config for akameco](https://github.com/akameco/eslint-config-precure)で公開しています。
npmを見ると月800ダウンロード程度あって一体自分以外に誰が使っているんだという気持ちもありますが、全てのconfigを一つずつ設定していったあの時間が無駄ではなかったと思えるのでハッピーです。

何かあれば是非Twitterにて議論しましょう😎

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">”eslint-config-自分の名前”にすると異常にプロジェクトに入れづらくなるのでeslint-config-dragonみたいな強い名前にする必要がある</p>&mdash; あかめ@アルバイト.js (@akameco) <a href="https://twitter.com/akameco/status/860606007982018560?ref_src=twsrc%5Etfw">May 5, 2017</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
PythonとDjangoで作るWebアプリケーション(mac)

![the-python-programming-language-explained.gif](https://qiita-image-store.s3.amazonaws.com/0/231744/612115cc-128b-4a59-fb9f-091806457ecd.gif)

# はじめに

今回はゼロからwebアプリ制作をはじめるにあたって、PythonとDjangoを使ってブラウザ表示までを行っていきます。

## Pythonの魅力について


⇨[なぜ機械学習にPythonが選ばれるのか]
(https://qiita.com/yaju/items/5502115d7e3d06e6bbdd)

⇨[Pythonでできることって!?]
(https://www.sejuku.net/blog/3863)

⇨[最近話題の言語【Python】でできる10のこと]
(https://blog.codecamp.jp/programming-python-10)


それではwebアプリケーションのベースを作っていきます。

## Pythonインストール

⇨[Anacondaインストール]
(https://www.anaconda.com/download/#macos)


## 仮想環境構築

```bash:
$ conda create -n ○○○ # ○○○は自由に設定(半角英数字)
```
return⇨y/n?⇨y

```bash
$ source activate ○○○
```
## Djangoインストール

```bash
(○○○)・・・> conda install django
```

⇨y/n?⇨y

```bash:パッケージインストール
  > pip install django
```

## プロジェクト作成

```bash
> django admin startproject △△△ #△△△は任意で設定
> cd △△△
```

```bash:開発サーバー起動
> cd ..
> python manage.py runserver
```
## ブラウザ確認

```bash
127.0.0.1:8000
```

そうすると・・・

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f38373636362f39306231653936382d306331312d346432312d323139302d3839366462313162386166662e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/231744/2e928ca1-5250-3f2d-0a82-ce6d47a3c4e0.png)

これでベースは出来ました。
OK！！
100円からはじめるフリーおやつのすすめ

職場で、私の席の隣に「ご自由にどうぞ」なおやつが置かれているんですが。
このおやつが普及し始めてから、なんとなく堅苦しかった雰囲気が和らいできた気がするので、「フリーおやつ」を職場の円滑油にオススメしたいと思います :heart:

# フリーおやつとは
よくある「ご自由にどうぞ」の飴ちゃんみたいな存在:candy:
細かいルールはなくて、なんとなく「食べたら補充する」みたいな感じで運用してます。
しいていうなら、（私の席にあるので）「私の席を邪魔しない量」ということだけ徹底してます:sweat_smile:

# 導入の経緯
## はじまりのうまい棒
ひょんなことから、うまい棒90本いただきました:open_mouth:
当然、１人では消費しきれないので、職場に持っていき、私の席に置いておきました。
15人ほどのチームだったので、3～4本/人食べてもらえれば、すぐに消費できるだろうと思い、「ご自由にどうぞ:free:」って。

## あまったお土産
うまい棒があとちょっとで完全消費・・・というタイミングで、旅行のお土産を持ってきてくれたメンバーがいました。
そして、少し残った分をうまい棒の隣に置いてくれました。

## 箱だけ再利用
うまい棒もお土産もなくなりつつあった時、お土産のお菓子が入っていた箱の中身が増えていました:open_mouth:
コンビニやスーパーで買ってきたお菓子を、プロジェクトリーダーさんが好意で入れていてくれたんです:heart:
ファミリーパックのチョコレートとかでしたけど、「こういう小さなおやつでみんなの心が癒されるなら、たいした出費じゃない」と言って、１か月ほど定期的におやつを入れてくださってました。

※でも、最初しばらくは「誰が入れたの？」って食べられなかったです（笑

## 俺も私も
だんだん楽しくなってきた＆申し訳なくなってきたメンバー一同が、「次は、俺が買ってくるよ」と言い始めて:sweat_drops:
最終的には食べてる人たちが自主的に買ってくるようになりました。

## 「フリーおやつ」として確立
ずーっとお土産のお菓子の箱を使ってたので、だんだんボロボロになってきたんですよね。
なので、私が100均一でプラスチックの箱を買ってきました:exclamation:
これを機に、

- 食べたい人は自由に食べていい。
- なくなったら、気づいた人が買ってくる。
- 置いていいおやつの量は「箱からあふれない程度」。

というゆるーい運用で、フリーおやつ制度が始まりました。
ちなみに、「箱からあふれない」というのは、冒頭でもちょっと書いた通り、私の席に置いてあるので、作業スペースを確保するというのが理由です:stuck_out_tongue:

おせんべいが続くとチョコ系が入ったり、チョコ系が続くとクッキーが入ったりするなど、同じようなおやつが入らないように意外と気にしてます:pig:

# フリーおやつ導入後の変化
## 飲み会が増えた
今までは１年に１回あるかないか・・・だったんですが、メンバーの入退出に伴って、必ず歓迎会＆送別会が開かれるくらいになりました:beer:
おやつがあることで、雑談しやすくなった感じです。
それで、飲み会も誘いやすくなったり、開催しやすくなったのかなーと。

## イベント参加が増えた
たまーに社内イベントがあるのですが、「明日、○○のイベントだよねー」って声を掛け合うことが多くなり、みんなで連れだって参加するようになりました:tada:
抽選制のイベントに至っては、「全員で応募すれば、行きたい人数人分の当選が見込める！」なんて言って、全員で応募したくらいです。

## 業務中に声がかけやすくなった
個人的な感覚ですが、あまり絡みのない人に話しかけるのって勇気がいりますし、苦手です。
でも、おやつを通じて雑談の量が増えたせいか、ちょっと心のハードルが下がったような気がしてます。

# まずは自分から買ってきてみる
というわけで、「フリーおやつ」オススメです。
まずは自分の席に置いて、周辺３人くらいと共有してみることから始めてみてはいかがでしょうか？
ホント、 **おやつだけで雰囲気がよくなるならありがたい**です:two_hearts:
homebrew でインストールする Python

こんにちは。
homebrew でインストール可能な Python を調べているのですが、今後（2018年？)、下記のようにする計画があるようですね（https://brew.sh/2018/01/19/homebrew-1.5.0/ より）。

- Python 2.7.14 (or later)
  - パッケージ名： python@2
  - コマンド名： python2, pip2

- Python 3.x 最新
 - パッケージ名： python
 - コマンド名： python3, pip3

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

- なお macOS システム標準付きの Python は
 - コマンド名： python (, pip)

``` console
$ /usr/bin/python --version
Python 2.7.10
```
Numpyのファンシーインデックス(Fancy Index)で配列を自由に操作する

#やりたいこと
Numpyのndarrayに備え付けられているファンシーインデックスという機能を使ってリストより自由に配列を操作してみる

#環境
* Python3.6.3
* Linux Mint MATE 18

#ファンシーインデックスとは何か
文章で説明するより例を見せたほうが早いので、下に簡単な例を示します。

```python3
import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
a[[0,1]]

#[[1,2,3],
# [4,5,6]]
```
普通はarrayの要素を指定するときには`a[0][1]`などと[]内に整数で指定します。しかしファンシーインデックスでは[]内に配列を入れて指定することができます。

上の例では`a[[0,1]]`は`a[0]`と`a[1]`を取り出すことを意味しています。これくらい簡単な例だと`a[:2]`でより簡単に表せます。しかし次のような例を見てみると、ファンシーインデックスの便利さが解ると思います。

```python3
a[[0,2]] -> [[1,2,3],[7,8,9]]　#a[0]とa[2]を取り出す
a[[0,3]] -> [[1,2,3],[10,11,12]]　#a[0]とa[3]を取り出す
```

#もっと柔軟に使う
ファンシーインデックスは各要素を狙い撃ちすることもできます。

```python3
import numpy as np

a = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
a[[0,1],[2,2]]

#[3,6]
```
上の例では`a`の`[0,2]`要素と`[1,2]`要素のみを抜き出して新たな配列を作っています。

さらに、抜き出すという使い方の他に、行を入れ替えるという目的にも使えます。

```python3
a[[3,1,2,0]]
#[[10,11,12],
# [4,5,6],
# [7,8,9],
# [1,2,3]]
```
この例では`a`の4行目と1行目を入れ替えています。これは行列の基本変形が必要なときに重宝しそうです。（ガウスの消去法とかでピボット選択とかで有用そう）

他にも、例えばリスト内包表記と組み合わせると偶数番目の要素(`a[0],a[2]`)のみを取り出すこともできます。

```python3
a[[2*i for i in range(2)]]
#[[1,2,3],
# [7,8,9]]
```
`filter`などの高階関数や`lambda`式と組み合わせればいろいろできそうです。
Chocolateyからyarnをインストールする手順

#chocolateyをインストール
chocolateyはwindows用のパッケージマネージャーです。
https://chocolatey.org/
管理者権限でコマンドプロンプト起動し下記を実行します。

```
> @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
```
この後インストール処理が走りますがわたしの場合は結構時間がかかりました。
それと途中警告メッセージが何回かでましたがとりあえずそのまま進めました。

#chocolateyが動くか確認
パス設定はコピペしたコマンドに含まれてるので自分で通す必要はありませんね。

```
> choco -v
0.10.8
```
無事インストールされてるみたいです。

#次にyarnをインストール
こちらを実行

```
> choco install yarn
```

インストールプログラムが走ります。
次にパスを通します。

```
> set Path = %Path%;"C:\Program Files (x86)\Yarn\bin"
```

コマンドプロンプトを再起動します。

#yarnのバージョンを確認

```
> yarn -v
1.3.2
```
yarnまで無事にインストールされました。
cuda8.0をインストールしたいが、cuda9.xのバージョンがインストールされてしまう


ubuntuにcuda8.0をインストールしたいにもかかわらず、cuda9.xのバージョンがインストールされてしまうということがありました。
解決方法を見つけるのに膨大な時間を浪費してしまったため、まとめました。

cuda インストールと検索すると、“CUDA Toolkit 9.1 Download”のページにたどり着くかと思います。
しかし、ページ下部にある“Legacy Releases”のページにとぶと、最新版のcuda以外をダウンロードすることが可能です。
（URL：https://developer.nvidia.com/cuda-toolkit-archive ）

その中でも、“CUDA Toolkit 8.0 GA1”を選択しました。
(URL：https://developer.nvidia.com/cuda-80-download-archive )
また、
Operating System：Linux
Architecture：x86_64
Distribution：Ubuntu
Version：16.04
Installer Type：deb(network)
としました。
![cuda8.0.JPG](https://qiita-image-store.s3.amazonaws.com/0/209637/b769818d-ed29-15b8-5561-342d22836518.jpeg)

ホームページに書かれているインストール方法は以下となっています。
１、`sudo dpkg -i cuda-repo-ubuntu1604_8.0.44-1_amd64.deb`
２、`sudo apt-get update`
３、`sudo apt-get install cuda`
![cuda8.0guide.JPG](https://qiita-image-store.s3.amazonaws.com/0/209637/8ac2a2be-92e7-96cd-0d05-767fdc776ff7.jpeg)

しかし、上記の方法に従うと、最新版のcudaがインストールされます。そこで、３を

３’、sudo apt-get install cuda-8-0

（参照：https://devtalk.nvidia.com/default/topic/1024342/cuda-setup-and-installation/unable-to-uninstall-cuda-9-0-completely-and-install-8-0-instead/）
とすることで、cuda8.0をダウンロードできました。

自己転載 URL：https://teratail.com/questions/96410#
【Qt】Q_NULLPTRとは何者なのか

Qtのサンプルコードなどで特に説明なしで使われているQ_NULLPTR。
公式のドキュメントでも説明が見つけられない。一体何者なんだ。

qtbase/src/corelib/global/qcompilerdetection.h

```cpp
/*
 * C++11 keywords and expressions
 */
#ifdef Q_COMPILER_NULLPTR
# define Q_NULLPTR         nullptr
#else
# define Q_NULLPTR         NULL
#endif
```

ふむ、Q_COMPILER_NULLPTRが定義されていれば、nullptr、定義されていなければNULLになると。
Q_COMPILER_NULLPTRとは？

```cpp
#    if __has_feature(cxx_nullptr)
#      define Q_COMPILER_NULLPTR
#    endif
```

ということで、どうやらコンパイラがc++11対応かどうかで、nullptrかNULLかを切り替えてくれる模様。
古いコンパイラに持って行ってもコンパイルできるので、Qtでアプリ作る上では、とりあえずQ_NULLPTRを使えば良さそう。
QNAPにforked-daapdをデプロイ

# TL;DR

Container StationからLinuxServer.ioから提供されているforked-daapdのイメージを使ってデプロイ．

* ウェブUIは動作しないので，設定ファイル書き換えのために/configにホストのフォルダを割り当てる
* あまり良いとは思えないが，[ここ](https://hub.docker.com/r/lsioarmhf/daapd/)に書いてあるように`--net=host`を指定

# 詳細

[先の投稿](https://qiita.com/masnagam/items/ef6d39bf053a49854dae)に書きましたが，`Disable and hide multimedia functions`を有効にしているため，iTunes Serverの機能は使えなくなりました．そのため，[ejurgensen/forked-daapd](https://github.com/ejurgensen/forked-daapd)を使うことにしました．

元々プリインされているソフトウェアのバージョンが古く，アルバムのアートワークなどが表示されなかったので，どのみち置き換えていただろうとは思います．

forked-daapdに置き換える方法はすでにフォーラムでは議論されていましたが，SSHでログインしていろいろ書き換えないといけないようでした．
[[HOWTO] replace mt-daapd with forked-daapd (iTunes server) - QNAP NAS Community Forum](https://forum.qnap.com/viewtopic.php?t=37472)

そこで，Container Stationを使ってforked-daapdをデプロイすることにしました．すでにLinuxServer.ioがDockerイメージを公開しているのでこれを使いました．イメージはいくつかありますので，デプロイ先QNAPのCPUアーキテクチャにあったものを選択してください．

LinuxServer.ioは以下のような記事も書いてますので，これを参考にしました．
[How To: Setup Containers on QNAP](https://www.linuxserver.io/2017/09/17/how-to-setup-containers-on-qnap/)

最初デプロイした時は以下のようにしたのですが，

* 3689ポートのみホストに公開
* /configにData Volumeを割り当て

これではうまくいきませんでした．

前者について．Docker Hubのページには，ちゃんと`--net=host`を使えと書いてあったのですが，3689だけで十分だろうと考えて試してみたのですが，うまくいきませんでした．`--net=host`にすると動きますが，不安を煽るメッセージが表示されます．

```
[  LOG]       db: Database OK with 1653 active files and 6 active playlists
[  LOG]     mdns: Failed to create service browser: Bad state
[  LOG]     raop: Could not add mDNS browser for AirPlay devices
[  LOG]     mdns: Failed to create service browser: Bad state
[  LOG]     cast: Could not add mDNS browser for Chromecast devices
[  LOG]     mdns: Failed to create service browser: Bad state
[FATAL]   remote: Could not browse for Remote services
[FATAL]     main: Remote pairing service failed to start
[  LOG]     main: MPD deinit
[  LOG]     main: HTTPd deinit
[  LOG]     main: Player deinit
[  LOG]     main: Library scaner deinit
```

気にはなりますが，iTunesのリストにサーバーが表示されたので良しとしました（調べるのが面倒だし）．

後者について．設定ファイルをウェブUI経由で編集しようとしたのですが，どうもDockerイメージにウェブUIが含まれていないようでした．`http://<server-name>.local:3689/`にアクセスすると，ファイルが見つからないというログが出力されました．実際に，/app/share以下を確認してみましたが，見当たりませんでした．意図して含めていないか，Dockerイメージ生成時の不具合なのかもしれません．

ウェブUIが使えないので，/configにホストのフォルダを割り当てて，初回起動時に生成される設定ファイルを編集することにしました．

もしかすると，`HTTPd deinit`が原因なのかもしれませんが，これ以上調べるのは面倒なので，設定ファイルを直接編集することで満足しました．これが仕事ということなら原因を調べたのでしょうが．．

# 補足

Contailer Stationの管理画面の`Console`上でCtrl+C（テキストをコピーしようと思ったのですが）を押すと，コンテナが強制終了します．ご注意ください．
Go言語のインストールからHello worldまで

最近、Go言語の勉強もしているので、少しづつメモのような形で投稿していこうと思います。
次回は簡単なチャットの作り方でも投稿する予定です。

##Macへのインストール方法
Homebrewでインストールします。Homebrewを入れていない方は別途インストールしてください。

**Go言語のインストール**
```brew install go```

**インストールできたか確認する**
```go version```

**ワークスペースの設定**
ワークスペース（これからGoはここで動かします）と言うディレクトリを作成し、作成したディレクトリを$GOPATHに設定する。
```mkdir $HOME/go
export GOPATH=$HOME/go
```

##コードを書く
```go:main.go
package main

import (
	"log"
	"net/http"
	"path/filepath"
	"sync"
	"text/template"
)

// templは1つのテンプレートを表します
type templateHandler struct {
	once     sync.Once
	filename string
	templ    *template.Template
}

// ServerHTTPはHTTPリクエストを処理します
func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	t.once.Do(func() {
		t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
	})
	t.templ.Execute(w, nil)
}
func main() {
	//ルート
	http.Handle("/", &templateHandler{filename: "helloworld.html"})
	//Webサーバを開始します
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}
```
**ServeHTTP**
ServeHTTPメソッドを用意することで
http.Handleに登録出来るようにする

```html:templates/helloworld.html
<html>

<head>
    <title>Helloworld</title>
</head>

<body>
    Hello world
</body>

</html>
```

##実行する
```
go run main.go
```
[http://localhost:8080](http://localhost:8080/)にアクセスする
“np.transepose”で、行列が転置されない場合の対処法

Pythonを学習している中で、陥ったミスをまとめています。
初心者向けですので、あたりまえだと思う方はスキップしてください。

Pythonで、1行N列やN行1列の行列を転置したいときに、
“np.transpose”を用いても、できないときがありました。

そういう時は、“.reshape”を用いてください。

例を以下に示します。
1行N列の行列を定義した後、“np.transpose”で転置した場合と
“.reshape”で形を変えた場合を示します。

```php
>> import numpy as np
>> N = 10
>> a = np.arange(N)
>> print(a)
array[0 1 2 ・・・ 9]
>> b = np.transpose(a)
>> print(b)
array[0 1 2 ・・・ 9]
>> c = a.reshape(N,1)
>> print(c)
[[0]
 [1]
 [2]
 [3]
 [4]
 [5]
 [6]
 [7]
 [8]
 [9]
```
pythonにおける“forループ”構文の注意点（~for i in range()~）


Pythonを学習している中で、陥ったミスをまとめています。
初心者向けですので、あたりまえだと思う方はスキップしてください。

windowsにおけるコマンド プロンプトやmacのターミナルにおいて、

```php
import numpy as np
a = np.arange(10)
for i in range(10):
   print(a[i])
```
とすると

```php
0
1
2
3
・
・
・
9
```
と表示されます。また、

```php
import numpy as np
a = np.arange(10)
for i in range(1,10):
   print(a[i])
```
とすると

```php
1
2
3
・
・
・
9
```
と表示されます。その理由として、

```php
for i in range(10):
```
では、

```php
i = 0, 1, 2, 3, ・・・ ,9
```
と推移していくのに対して、

```php
for i in range(1,10):
```
では

```php
i = 1, 2, 3, ・・・ ,9
```
で推移しており、

```php
i = 0
```
がないことがわかります。
Unity備忘録、STG制作6:異なるアスペクト比の画面でも同一の動作をする画面構成の検討

※この記事は2016年当時に在籍していた某社内での（略）、日中は客先常駐業務、定時後は自社に戻って＆土日は家でVRアプリ開発（ノーペイ）という二足のわらじとなったため、一連の記事（このSTG制作のことね！）およびSTG開発そのものを完全にストップしなければならなくなった。それでもVRアプリの案件獲得の確度が高いという話を聞かされていたため、ボーナスでまとめて返してもらえばいい、皆がそう思っていた。。。そしてプロトタイプが完成した時点で新メンバ（専任者）に引き継いだ。（続く）


#背景
前回記事 : [STG制作5](https://qiita.com/CAP_GOCHO/items/091714c6c04ec82ca7a9) で、Unityエディタ上のアスペクト比と実際にスマホのアスペクト比が異なっていた場合、画面の縦方向だけが画面内に収まり、横方向については考慮されないことが分かった。
もう少し分かりやすく説明すると、当初は下記図の①～③のどれかになると思っていたのだが、実際は①のように縦方向のサイズはUnityエディタと同等となるが、横方向は表示領域が④拡張される（Unityエディタより横が広い場合）、または⑤カットされる（Unityエディタより横が狭い場合）という結果になった。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/162164/1d75074a-29c3-7753-05b1-6cbbeef86ff6.png)

![02.png](https://qiita-image-store.s3.amazonaws.com/0/162164/095b0414-58aa-b85f-d1ec-7adc6402a9a0.png)


で、これの何がマズいのかと言うと、例えば「画面上の敵弾が全て得点アイテムに変化する」という仕様を考えた場合、画面のアスペクト比によって表示される弾数が異なってしまう、つまり横のサイズが大きいほど弾数が増えることとなり、同じプレイをしても得点が異なるという問題が発生する。

そこで、異なるアスペクト比の画面でも同一の動作をする画面構成を検討した。


#他のゲームはどうなっているか？
サンプルとして某スマホ用STGの画面を下記に示す。
見ての通り、左右をマスクして表示しており、①のパターンを採用していることが分かった。
これが一般的な方法かは不明だが、一番簡単な実現方法と思われる。

![03.png](https://qiita-image-store.s3.amazonaws.com/0/162164/cbd09468-752b-a984-f423-96bfb1b25324.png)


なお余談だが、iPhoneでリリースする場合、マスク画像が黒一色だと申請NGとなるので要注意（そういう規約があるらしい）。壁紙画像のようなものでマスクするのがベターと思われる。

#画面表示範囲の検討
実際の表示領域については、逆を言えば「指定の領域外のオブジェクトは表示しない→削除する(※)」と言い換えられる。　
※消してはいけないオブジェクトもあるが、ここは弾の扱いに特化して記載している。

画面外に出たオブジェクトを削除する方法は、[STG制作4](https://qiita.com/CAP_GOCHO/items/f6df8fefce814ddf93c6) の「方法２」を応用すれば出来そうである。

一旦話を整理すると、
(1)カメラ座標は(0,0)で固定 
 → カメラ位置は気にしなくてよい。
(2)画面表示領域の縦方向はワールド座標の-5.0～5.0で固定
 → -5.0～5.0の範囲で所望の値を決めればよい
(3)画面表示領域の横方向は実機のアスペクト比によって異なるので分からない
 → とりあえずFULL HDで収まる範囲にしてみるか・・・
となる。

#サンプルコード
```csharp:autoDeleteOutOfArea.cs
using UnityEngine;
using System.Collections;

public class autoDeleteOutOfArea : MonoBehaviour {

	// Update is called once per frame
	void Update () {
		if (this.isOutOfArea()) {
			Destroy (gameObject);
		}
	}

	bool isOutOfArea() {
		//指定のArea外だったらtrueを返す
		if(transform.position.x <= -2.7f ||
		   transform.position.x >= 2.7f ||
		   transform.position.y <= -4.0f ||
		   transform.position.y >= 4.0f)
		{
			return true;
		}

		return false;
	}
}
```

#実行結果
表示範囲が分かりやすいように灰色の背景を付加して、弾が何処で消えるかを確認した。
結果として、領域外に出たら弾が削除されることを確認できた。
また、異なるアスペクト比でも取り敢えずは問題なく同等の動作をすることを確認できた（表示されている弾数が全て120個になっている）。

![04.png](https://qiita-image-store.s3.amazonaws.com/0/162164/bb47f54f-ac33-4ce6-d036-659a46ab700f.png)


以上
Karabiner-Elements：ELECOM EX-Gマウスのボタンに機能を割り当ててみた

#はじめに
ELECOM EX-Gというお気に入りのマウスがあるのですが、ボタンの機能割り当て用の公式アプリがmacOS High Sierraでうまく動かなかったのでKarabiner-Elementsを使って簡単に機能割り当てをしてみました。

割り当てた機能
- ホイールクリック -> Mission Control
- 前方ボタン -> 右の操作スペースに移動
- 後方ボタン -> 左の操作スペースに移動

#ソースコード
```json:
{
    "title": "Mouse Personal Rules",
    "rules": [
        {
            "description": "Use mouse button 3, 4, and 5",
            "manipulators": [
                {
                    "description": "button3 -> control + ↑",
                    "from": {
                        "pointing_button": "button3"
                    },
                    "to": [
                        {
                            "key_code": "up_arrow",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "type": "basic"
                },
                {
                    "description": "button4 -> control + ←",
                    "from": {
                        "pointing_button": "button4"
                    },
                    "to": [
                        {
                            "key_code": "left_arrow",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "type": "basic"
                },
                {
                    "description": "button5 -> control + →",
                    "from": {
                        "pointing_button": "button5"
                    },
                    "to": [
                        {
                            "key_code": "right_arrow",
                            "modifiers": [
                                "left_control"
                            ]
                        }
                    ],
                    "type": "basic"
                }
            ]
        }
    ]
}
```

基本的には`pointing_button`と`key_code`および`modifiers`のペアを一対一で割り当てるだけなのでとっても簡単です。
key_codeはKarabiner-EventViewerで調べてください。

こちらを適当な名前をつけたjsonファイルにして、`~/.config/karabiner/assets/complex_modifications`に突っ込めばKarabiner-Elementsで選択できるようになります。
Amazon VPC勉強メモ

・ネットマスクは/28（14IP）-/16の範囲で利用可能
`サブネットで利用できないIP`
1. ネットワークアドレス(.0)
2. VPCルータ(.1)
3. Amazonが提供するDNS(.2)
4. AWSで予約されている(.3)
5. ブロードキャストアドレス(.255)

・VPC作成後はVPCアドレスブロックは変更できない

・同一リージョン内のAZは`高速専用線`でつながっている。リージョン間は`インターネット経由`

・`ネットワークACL（アクセスリスト）`でネットワークレベルでのセキュリティソフトを設定

・`ENI(Elasticネットワークインターフェース)`
EC2で利用するネットワークの仮想インターフェース
EC2ごとにENIを複数持つことが可能
下記の情報をENIに紐づけて維持可能
1. プライベートIP（固定の設定可能）
2. Elastic IP
3. MACアドレス
4. セキュリティグループ

・`Floating IP`
サーバに障害が起こった際に、ENIを維持して対応する
※VPCではサブネットを超えてアドレスを付け替えることができない点に注意
参考URL：https://goo.gl/JKphCj

・`サブネット内のDHCP`
サブネット内のENIにIPを自動割り当て
※プライベートIPを固定にした場合はDHCP経由で該当のIPが割り当てられる

・VPCで使えるAmazonが提供するDNS
`169.254.169.253`
`VPCのネットワーク範囲のアドレスに+2をプラスしたIP`

・`プライベートホストゾーン`
VPC内のインスタンスのみ参照可能。Route53のプライベートホストゾーンを利用

・`インターネットゲートウェイ（IGW）`
VPC内のリソースにインターネットの接続を提供。VPCにアタッチする
単一障害店や帯域幅のボトルネックはない

・`メインルートテーブル`、`カスタムルートテーブル`
`メインルートテーブル`：VPCを作成したときに自動的に割り当て
`カスタムルートテーブル`：任意で作成したルートテーブル。メインに変更することも可能

・`パブリックサブネットの設定`
自動で割り当て：サブネットに自動割り当てを設定
固定で割り当て：Elastic IPをアタッチ

・`Elastic IP`
費用がかかるのは下記の場合
1. 追加でEIPを利用する場合
2. 起動中のEC2インスタンスに割り当てられていないとき
3. アタッチされていないENIに割り当てられている場合
4. 1ヶ月でリマップ（割り当て、取り外し）が100回を超えた場合

・`NATゲートウェイ`
プライベートサブネットのリソースがインターネットに通信するために必要
AZごとに設置するのがベストプラクティス

・`VPCエンドポイント`
プライベートサブネットからS3バケットにアクセス可能
S3アクセスのために`IGW``NATインスタンス`が不要

・`バーチャルプライベートゲートウェイ（VGW）`
オンプレミスとのVPN接続のためのエンドポイントとなる仮想ルータ。VPC側
単一障害点や帯域幅のボトルネックはなし

・`カスタマゲートウェイ（CGW）`
オンプレミス側。AWSとのVPN接続のため

・`VPN接続`
`VGW`と`CGW`間でIPsecトンネルが設定

・VPC Peering
>2 つの VPC 間でトラフィックをルーティングすることを可能にするネットワーク接続
https://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-peering.html

`ネットワーク接続の最大送信単位 (MTU) `に注意。VPC Peeringは`1500`

異なるAWSアカウントでも可能
~~但し、異なるリージョン間では使用できない~~

・`セキュリティグループ`
仮想ファイアウォール
1つのEC2で5つのセキュリティグループが設定可能
デフォルトですべての通信は禁止
VPCぴあリング先のセキュリティグループが設定可能

・`ネットワークACL`VS`セキュリティグループ`
`ネットワークACL`：サブネットレベルで効果。ステートレスなので戻りのトラフィックも明示的に許可設定
`セキュリティグループ`：サーバーレベルで効果。ステートフルなので戻りのトラフィックは気にしなくてよい

・オンプレミスとのハイブリッド構成
`Direct Connect`を使用する
VPCからオンプレミスへの通信をするためには、各サブネットのルートテーブルの設定が必要
宛先：オンプレミスのIP
ターゲット：VGWのID
VPNとDirect Connectで冗長可能。Direct Connectが優先

・VPC設計
アプリケーション/監査/フェーズ（本番/検証/開発）/部署などによる分割

・`VPC Flow Logs`
ネットワークトラフィックをキャプチャ氏、CloudWatchへPublishする機能
ネットワークインターフェースを送信元/送信先とするトラフィックが対象
CloudWatch Logsの標準料金のみ課金
`VPC Flow Logsで取得できない通信`
1. Amazon DNSサーバへのトラフィック

・VPCのリミット
リージョン当たりのVPCの数：5
VPC当たりのサブネット：200
AWSアカウント当たり1リージョンのEIP：5
ルートテーブルあたりのルートの数：100
VPCあたりのセキュリティグループの数：500


参考URL：
http://kakakakakku.hatenablog.com/entry/2016/08/07/232305
https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-online-seminar-2016-amazon-vpc
iTerm2でssh接続した場合にプロファイルを変更する（trap付き）

iTerm2は、echo文で特定の制御文字を出力することでプロファイルを変更することができます。例えば『Servers』というプロファイルに変更する場合は、次のようにします。

```bash
echo -ne "\033]1337;SetProfile=Servers\a"
```

この仕組みを使用して、sshでどこかのサーバに接続している間は、通常と異なるプロファイルを適用することができます。

# ssh-with-changing-profile.sh

まずは次のファイルを作成します。ここでは、ホームディレクトリのbin以下に`ssh-with-changing-profile.sh`という名前で作成しました。

```bash:~/bin/ssh-with-changing-profile.sh
#!/bin/bash

echo -ne "\033]1337;SetProfile=Servers\a"
trap 'echo -ne "\033]1337;SetProfile=Default\a"' ERR EXIT
/usr/bin/ssh "$@"
```

ポイントは、sshを終了した際にデフォルトのプロファイルに戻すecho文をtrapにしてる点です。こうしておけば、ssh先でexitした通常終了のケースはもちろん、sshが異常終了した場合でもデフォルトプロファイルに戻すことができます。

ファイルを作成したら、忘れずに実行権限を付けておきます。

```bash
chmod +x ~/bin/ssh-with-changing-profile.sh
```

# プロファイル作成
続いて、iTerm2で`Servers`という名前のプロファイルを作成します。ローカルとは違う緊張感を与えるため、危険な香りがする赤とかを背景色にするといいんじゃないでしょうか。
<img width="1030" alt="スクリーンショット 2018-01-20 19.50.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/32136/6420ef3a-34f2-5649-b019-e25b1d571609.png">

# alias
最後に`.bashrc`なり`.zshrc`なりお好きな所に`alias`を設定しておきます。

```bash
alias ssh='~/bin/ssh-with-changing-profile.sh'
```

以上で設定は完了です。あとはいつも通りにsshコマンドを叩けばオッケーです。接続先毎に適用するプロファイルを変更したい場合は、`ssh-with-changing-profile.sh`でコマンドライン引数からゴソゴソすればいけると思います。
備忘録_Base環境はpython 3.6だけど、用途に応じて2.7も使えるようにする

# はじめに
[Advent Calendar](https://qiita.com/advent-calendar/2017/cisco) を契機に、**何でもいいから最低月1回はなんか書く**って自分で決めたので、とりあえず今月書いてないってならないように最低限1個投稿します(本当はRas-piでGoogle Assistantを召喚したいけど、まだRas-piが届いてない)

# 書くこと
昨日API勉強会的なのをスモールグループでやって、第1回の超基礎編だったので、まずpythonのどの環境使うかっていうことが若干議論になりました。
pythonの最新モジュールは3.6.xで推奨もこちらだと思いますが(機能的に)、いまだに2.7.xも広く使われています。例えば、Cisco IOS XE 16.Xでon-box pythonできるようになりましたが、それも2.7.xです([DevNet](https://learninglabs.cisco.com/)を見ると徐々に書き換えが進んでるようです)。
結果的に、3.6で勉強会は行ったわけですが、わざわざ普通の環境には3.6を置いて、別のVM環境に2.7を用意とかめんどくさいのでなんか方法ないのかなー、とACIとpythonを今勉強しながら休憩がてら調べてたらあったので、備忘録としてメモ書きすることにしました。

# 環境
+ Windows 10
+ Python 3.6.3
+ Anaconda 5.0.1

# やったこと
### 1. python 2.7の仮想環境をAnaconda Promptで作る
```
C:\Users\yunambu\Desktop>conda create -n py27 python=2.7 anaconda
Solving environment: done

## Package Plan ##
  environment location: ~
 
  added / updated specs:
  - anaconda
  - python=2.7

The following packages will be downloaded:
(省略)

Proceed ([y]/n)? y
(省略)
Preparing transaction: done
Verifying transaction: done
(省略)
```

### 2. 環境の確認
```
C:\Users\yunambu\Desktop>conda info -e
# conda environment:
#
base           * ~anaconda3
py27             ~anaconda3\envs\py27
```

### 3. 環境の切替
```
C:\Users\yunambu\Desktop>python
Python 3.6.3 |Anaconda custom (64-bit)| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> ^Z

C:\Users\yunambu\Desktop>activate py27

C:\Users\yunambu\Desktop>python
Python 2.7.14 |Anaconda, Inc.| (default, Oct 15 2017, 03:34:40) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> ^Z

C:\Users\yunambu\Desktop>deactivate

C:\Users\yunambu\Desktop>python
Python 3.6.3 |Anaconda custom (64-bit)| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
```

# まとめ
特に複雑な手順を経ることもなく、簡単に切替が可能になりました。これで同一のプロンプトで一行(de)activeを書けば、用途に合わせてどちらも使えるようになります。python 2.7を起動・停止する際に、ユーザ権限が標準でなく、Power Userの場合は、以下のコマンドに代わるのでご注意ください。

```
source activate py27
source deactivate
```

備忘録(完)
Redashのクエリで取り出したデータをGoogleスプレッドシートに書き込むスクリプトがわりとシンプルに書ける

今回はデータベースのデータの変動をちょっと見てみたいというオーダーを受けて、簡易的にスプレッドシートに毎時抽出したデータを記録していくスクリプトを作ったのですが、わりとシンプルに書けたのでご紹介します。

## 作ったもの

<img width="420" alt="抽出データSS" src="https://qiita-image-store.s3.amazonaws.com/0/45374/8e2e2a41-21cb-4fed-3b24-9b185db8d82c.png">

1時間ごとにスクリプトを実行するトリガーを設定すると、こんな感じに1行ずつデータが蓄積されていきます。

## スクリプトの全体像

```js
function main() {

  // Redashからデータ取得
  var redash = new Redash.Redash();
  var response = redash.getData(1513);
  var rows = response.query_result.data.rows;

  // 書き込むシートを選択
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('data');

  // データの入っている最後の行の次の行番号を取得
  var newRowNum = sheet.getLastRow() + 1;

  // A列のセルに実行日時を書き込む
  sheet.getRange(newRowNum, 1).setValue(new Date());

  // 1列ずつセルを進める
  for (var i = 0; i < rows.length; i++) {
    var col = i + 1;

    // 1行目にカラムヘッダーを書き込む
    sheet.getRange(2, col).setValue(rows[i].date);

    // B列以降のセルに取得したデータを書き込んでいく
    sheet.getRange(newRowNum, col).setValue(rows[i].amount);
  }
}
```

## 処理を詳しく見ると

### スプレッドシートの中で書き込むシートを選択

```js
// 書き込むシートを選択
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('data');
```

<img width="420" alt="抽出データSS-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/45374/7723ae1c-2b9a-ebe8-bafd-a0e84534a378.png">

### 書き込む行を選択

今回は1行ずつ下に新しくデータを書き込んでいきます。

<img width="333" alt="SS-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/45374/7045a9a3-6d9b-42c9-3909-7fc3199f464f.png">

```js
// データの入っている最後の行の次の行番号を取得
var newRowNum = sheet.getLastRow() + 1;
```

`getLastRow()`とやるとデータの書き込まれている最後の行番号を取得できます。

### 実際にデータを書き込む

あとはfor文で1列ずつセルを進めながらデータを書き込んでいきます。

```js
// 1列ずつセルを進める
for (var i = 0; i < rows.length; i++) {
  var col = i + 1;

  // 1行目にカラムヘッダーを書き込む
  sheet.getRange(2, col).setValue(rows[i].date);

  // B列以降のセルに取得したデータを書き込んでいく
  sheet.getRange(newRowNum, col).setValue(rows[i].amount);
}
```

## まとめ

わざわざデータ抽出用のテーブルやバッチを作るほどではないときにはGoogleAppｓScripで使い捨てのスクリプトをさくっと作ってしまうのが良いと思います。
情報系の学生の自分にとって、役に立つ Web サイト

情報系の技術を向上させるために、学生の自分にとって、個人的に必要だと思うサイトの情報をまとめていきます。（随時更新）
## サイトで情報収集
- Q&A サイト
    - [スタック・オーバーフロー](https://stackoverflow.com/)
    - [スタック・オーバーフロー(日本語版)](https://ja.stackoverflow.com/)
    - [テラテイル](https://teratail.com)

- 情報共有サイト
    - [Qiita](https://qiita.com)

- 公式サイト・専門サイト・学習サイト
    - Web開発全般
        - [MDN ウェブドキュメント](https://developer.mozilla.org/ja/)
    - React
        - [React - A JavaScript library for building user interfaces](https://reactjs.org/)
    - React Native
        - [React Native · A framework for building native apps using React](https://facebook.github.io/react-native/)
        - [Read Me · Redux](https://redux.js.org/)
        - [Getting Started with Redux from dan_abramov on eggheadio](https://egghead.io/courses/getting-started-with-redux)
    - JavaScript 
        - [JavaScript - ウェブ開発を学ぶ | MDN](https://developer.mozilla.org/ja/docs/Learn/JavaScript)
        - ECMAScript(JavaScriptの言語仕様)
            - [Learn ES2015 · Babel](https://babeljs.io/learn-es2015/)

## 学習支援サイトで学ぶ
- [ドットインストール](https://dotinstall.com/lessons/)
- [Progate](https://prog-8.com/)
- [CODEPREP](https://codeprep.jp/)
- [Schoo](https://schoo.jp/)

## コーディング技術を鍛える
- [AtCoder](https://atcoder.jp/?lang=ja/)

## 活用できる Web サービス
- [GitHub](https://github.com/)
- [GitLab](https://www.gitlab.com/)
- [GitLab.com](https://gitlab.com/)
- [Firebase](https://firebase.google.com/)
- [heroku](https://jp.heroku.com/)
Kotlinで画面遷移して値を渡す

##はじめに
Androidアプリ開発においてKotlinで画面間の値の受け渡しについてシンプルにまとめました．

##下準備
MainActivityから新しく作成したMain2Activityに値を渡すことにします．
新たなActivityを作成し，アプリでそのアクティビティに移動できるよう
AndroidManifest.xmlに記入します．

```AndroidManifest.xml
<activity android:name=".MainActivity"
          android:parentActivityName=".Main2Activity">
```
上の行はすでに記述されているはずなので下の行を追加して記述します．

##元の画面のコード
画面遷移を行うメソッド(toNextView)を作成し，それをボタンに関連づけます．


```MainActivity.kt
fun toNextView(view: View){
	//Intentのインスタンスを作成
	val intent = Intent(this, Main2Activity::class.java)
	//textは受け渡す変数
	val text = "Hello!"
	//intent変数をつなげる(第一引数はキー，第二引数は渡したい変数)
	intent.putExtra("TEXT_KEY",text)
	//画面遷移を開始
	startActivity(intent)
}
```

##移動先のコード
```Main2Activity.kt
//受け取った変数を入れる
val text = intent.getStringExtra("TEXT_KEY")
```
これで移動先のtextに変数が代入されているはずです．
pagerdutyあれこれメモ

pagerdutyに関するあれこれメモ

pagerdutyの中の人と色々と月一くらいでMTGしてます。
そこで教えてもらったことなどの備忘録です。

**注）私はPagerDutyを使って運用をしているのではなく、pagerdutyを使って運用しているメンバーを支援するためのシステムの構築をを目的としています。**
**なのでpagerdutyでAPI使ってインシデントの状態を操作することが主な利用方法になっています**

取り組みの一部紹介
[![thumbnail](https://image.slidesharecdn.com/20160916awspremiernight2inosaka-160920030344/95/slide-1-1024.jpg)](https://www.slideshare.net/slideshow/embed_code/key/AqOSzwK2PLOzIx)

## What is pagerduty? 
https://www.pagerduty.com/ 

PagerDuty社製のインシデント管理のSaaS。基本webインターフェイスで操作可能。
インシデントの情報を集約することで一元管理が可能になる。

インシデントはサービス（pagerduty利用者が運用しているサービス）に紐付くため、インシデント発生時にどのサービスで発生したものかすぐ判断がつく。
インシデントの発生状況の推移をWebインターフェイスで確認するこもできる。

メンテナンス中なので通知したくないなーという場合はメンテナンスウィンドウにサービスを入れる事でインシデントが発生しても無視することも可能。

インテクレーションは結構種類が揃っていてメール、APIはもちろんNagios、DataDog、（他にも色々！）などのプラグインが豊富に揃っている。

予めカレンダーに情報を登録することで対象のユーザーに連絡（通知）でき、エスカレーションポリシーという仕組みで予め対応者の階層を作ることで一定時間誰もインシデントに着手してなければ次の階層に連絡をする仕組みなども用意されている。

基本ドキュメントは英語。個人的にハードル高し。

## 個人的な最初のハマりどころ アラートとインシデントの違い
ここが結構わかりにくい・・実際にWeb UI上明確に分かれている。

![Incidents_-_PagerDuty.png](https://qiita-image-store.s3.amazonaws.com/0/193001/adf00304-8949-3040-5d70-5bbf9b7bd596.png)

分類分けとしては、

```
アラート（Alert）：pagerdutyへの通知情報（各インテグレーションが投げた情報）？
インシデント（Incident）：Alertの情報を元にpagerdutyがサービス毎の設定を踏まえて処理しないといけないと判断したもの？
```

って認識ですが、ちょっと怪しい感じもする。

アラートを受けてpagerdutyは自身の設定情報（例えば、サービスがメンテナンスに入っているか？やメールであればメールフィルタに合致しているか？など）を踏まえて処理すべきアラートであると判断した場合にインシデントとして登録される？

英語で説明してらったのですが理解が怪しい。詳しい方いらっしゃいましたら、良かったら教えて下さい。 mm

## pagerdutyのAPIって何ができるの？
基本的な操作に関しては大体なんでもできます。

API v1の頃は安定性やパフォーマンスが若干アレでしたがv2になって改善された。
v1は叩きまくるとちょこちょこ失敗していたがv2では特に見かけない。
ただ、たまにAPIサーバーが死んじゃうことがある。体感的に年一回くらい。

APIリファレンスはこちら
https://v2.developer.pagerduty.com/v2/page/api-reference

APIについてはこれからボツボツと起こします。

## 利用時の注意点
- APIの利用制限は1分辺り2000回。この制限はAPIキー単位で行っている。
  APIキーを複数用意すれば1分あたり2000回以上の呼び出しが可能。

- WebHookはpagerdutyからのリクエストを受信して5秒以内にレスポンスを返さないといけない。
  （正確にはpagerdutyがリクエストを投げてからレスポンスを受け取るまでが5秒以内。）
  レスポンスを返すのに5秒以上かけるとブラックリスト予備軍に入り、一定時間pagerdutyから通知が来なくなる。
  慢性的にレスポンスを返すのに5秒以上かけてしまうとやがてブラックリスト入りして通知が一切来なくなる。

## おまけ
pagerduty自体にPagerDuty社の運用思想が盛り込まれている。
例えば、エスカレーションポリシーの各階層毎の人数制限はあまり大人数に送ると混乱するから人数を絞った方がいいなど。