OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftのWebフレームワークSlimaneをインストールする

## はじめに
Swiftがオープンソースになった事で、Android用アプリをSwiftでかけるように(なりそう！)なったり、Web開発をSwiftで行えるように(なりそう！)なったりしていますね。

私は、Swiftでアプリを作った事は無いし、4月辺りに初めて触った者ですが、Node.jsに似た作りになっているWebフレームワークSlimaneに興味を持ったのでとりあえず、インストールしてみました。

Swiftのバージョンアップは1周間に何度も行われるくらいの頻度です。
言語仕様の変化が激しいので、Slimane含めSwiftのWebフレームワークも激しく更新されますのでまだまだ試用段階だと思って下さい。

※この記事は<a href="https://github.com/noppoMan/Slimane/wiki/Install-Guide">Slimaneインストールガイド</a>の日本語訳です。

## Ubuntu
1.Swiftの導入

```bash
wget https://swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a-ubuntu14.04.tar.gz
tar xzvf swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a-ubuntu14.04.tar.gz
echo "PATH=/your/path/to/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a-ubuntu14.04/usr/bin:$PATH" >> ~/.bashrc

~/.bashrc
swift -v
```

2.Slimaneの導入

```bash
# Install build tools and libssl-dev
sudo apt-get upgrade
sudo apt-get install build-essential libtool libssl-dev
sudo apt-get install automake clang
```

```bash
# build and install libuv
git clone https://github.com/libuv/libuv.git && cd libuv
sh autogen.sh
./configure
make
make install

# build and install hiredis
git clone https://github.com/redis/hiredis && cd hiredis
make
make install
```

<b>ビルド</b>

```bash
# If you have the old build, need to run
# make clean

make
```

## Mac OSX
1.Swiftの導入
<a href="https://swift.org/builds/development/xcode/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a-osx.pkg">https://swift.org/builds/development/xcode/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a/swift-DEVELOPMENT-SNAPSHOT-2016-05-09-a-osx.pkg</a>
パッケージをインストール

```bash
swift -v
```
2.Slimaneの導入

```swift:Package.swift
import PackageDescription

let package = Package(
    name: "SlimaneApp",
    dependencies: [
        .Package(url: "https://github.com/noppoMan/Slimane.git", majorVersion: 0, minor: 4)
    ]
)
```

<b>brew</b>

```bash
brew install libuv openssl hiredis
brew link libuv --force
brew link openssl --force
brew link -f hiredis
```

<b>ビルド</b>

```bash
# If you have the old build, need to run
# make clean

make
```

## デバック・テスト
```bash
make debug
make test
```


これをやったからと言って何もできないので、近い内にSlimaneに公開されている<a href="https://github.com/slimane-swift/slimane-example">Exampleアプリ</a>を実際に起動させてみたいと思います。
[Linux][開発メモ] C言語ソースの読み方

C言語初心者がIDEを使わずに、エディタだけでコードを書いている時に、コードを読み進めていくヒントを自分なりにまとめました

2016.05.30 追記
この記事に書いているような面倒なことはしなくとも、GNU GLOBALを使えば簡単にコードを読むことができるようになります
今まで知らなかった事が恥ずかしい程の常識だったようですが、自戒の念を込めてこの記事は残しておくことにしました
GNU GLOBALの使い方については[別記事](http://qiita.com/suzutsuki0220/items/1e755fd98e5b12af3e2d)にまとめましたので、よろしければそちらもご覧ください

# 定義されている関数がどこで呼ばれているか調べる方法

## 関数がstaticで定義されているか

例えば以下のように、関数定義の前に"static"とあれば、そのファイルでしか使われていない (localな意味)

```
static hmstime_t normalizeTime(hmstime_t t)
{
    :
}
```

## ソースファイルに宣言があり、extern修飾されていない

ソースファイルの中に宣言があれば、そのファイルでしか使用できない
ただし、宣言がextern修飾("extern"の後に宣言が書かれる場合)されていれば、どこか別の場所で定義されているので、別の場所でも使われているだろう

```C:main.c
      :

/*** 宣言 ***/

hmstime_t addTime(hmstime_t t1, hmstime_t t2);

      :

/*** 定義 ***/

hmstime_t addTime(hmstime_t t1, hmstime_t t2)
{
    double x1,x2;
    x1=convertTimetoDouble(t1);
    x2=convertTimetoDouble(t2);
    return convertDoubletoTime(x1+x2);
}

      :
```
ソースファイルとは別に、宣言がヘッダファイルにある場合はそのヘッダがincludeされている箇所で使用されている可能性がある

## 宣言のあるヘッダを検索する

```
grep "%%関数名%%" `find . -name '*.h' -o -name '*.hpp'`
```

ヘッダが分かれば、それをincludeしているコードを調べてみる

```
$ grep "%%ヘッダファイル名%%" * |grep "include"
```

includeされているファイルがヘッダファイルの場合、更に別のヘッダからincludeされている可能性があるので、
物によっては、追っていくのが大変になるかもしれない

## 分からなそうなので、コード全体を検索してみる

```
grep "%%関数名%%" `find . -name '*.c' -o -name '*.cpp'`
```


# 突然に関数が使われる

そのソースファイルでincludeしているヘッダから宣言してる箇所を探す

ソースコードの先頭の方に"#include"で始まる行が幾つかあるはず

```
#include <ctype.h>
#include <errno.h>
#include <pthread.h>
　　:
#include "newfunc.h"
    :
```

includeのヘッダが"<>"で括られている場合と、ダブルクォート(")で括られている場合があるが、以下の通りに使い分けされていることが多い

* "<>"で括られる場合はシステムや、開発環境で用意されているヘッダ
* ダブルクォート(")はソースコードの開発者が独自に作ったヘッダ

なので、独自に作られたものであれば、ダブルクォートで括られたヘッダから見ていった方が良い。
独自のではなさそうならば、man %%関数名%% で使い方が出てくるかもしれない (システムのincludeは慣れないと読みにくいものなので、マニュアルで概要を見る方がよいだろう)

宣言を見つけた場合
関数が定義されているソースコード(大抵はヘッダと同じ名前)を見る

※ソースコードが特定できなければgrepして探してみる
※見つからなければ共有ライブラリや、プリコンパイルされたオブジェクトの関数を使っている可能性もある。その場合、コードがオープンになっていなければ中身を知ることは難しい
PHPでの自動メール返信機能

http://tokidoki-web.com/2013/12/php%E3%81%A7mb_send_mail%E9%96%A2%E6%95%B0%E4%BD%BF%E3%81%A3%E3%81%A6%E9%80%81%E4%BF%A1%E8%80%85%E3%81%AB%E8%87%AA%E5%8B%95%E8%BF%94%E4%BF%A1%E6%A9%9F%E8%83%BD%E4%BB%98%E3%81%8D%E3%83%A1%E3%83%BC/
Windowsから仮想マシン(VMWare)へ接続する

例のごとく自分メモ。
symfony接続できるまでがんばる。
すっごく途中のまま放置してたorz

# puTTyからアクセス
`ifconfig`をして、一番上に出てきたipアドレスでログインする。
portは22。
Windowsのhostsファイルにドメイン登録してやると捗る。

※ifconfigで出る内容は要調査。
※なんでpuTTyはOKでWindowsからはダメなんやろ？？
→puTTyのログインはデフォルトでSSHログイン&22portのため。
→私がSSHログインをよくわかってないからなんで？ってなった。
→ブラウザからそのままでSSHログインはできないっぽい多分(なんか入れればOK)

# Windows(仮想マシンを入れているPC)からアクセス

とりあえずip打ってみた。
できない。

もしかしてiptablesかも？？
→CentOS7だったのでfirewalldだと気づく。

[http://www.kakiro-web.com/linux/firewalld.html](http://www.kakiro-web.com/linux/firewalld.html)

```
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
```

`--permanent`はOS再起動後も設定を保存してくれるオプション。
これで80ポートからのアクセスができるようになった。

## 別のポートで接続
3000ポートを追加するとき

```
firewall-cmd --add-port=3000/tcp --zone=public --permanent
```

## firewalldの削除
3000portを消すとき

```
firewall-cmd --remove-port=3000/tcp --zone=public --permanent
```

## firewalldの確認方法

```
firewall-cmd --list-all
```

ApacheにPortを増やす場合、`/opt/httpd/httpd-2.4.20/conf/httpd.conf`に`Listen [port名]`でApacheにアクセスできるPortを追加する。

# Symfonyにアクセス

## Symfonyでのサーバー起動方法

```
php [app_root]/app/console server:run
```

まだつながってない
続きはまたやってから

## ネットワーク周り設定
参考：[https://tamosblog.wordpress.com/2012/06/12/centos_upd/](https://tamosblog.wordpress.com/2012/06/12/centos_upd/)

### /etc/sysconfig/networkの設定

このファイルについて：[http://www.linux-beginner.com/linux_setei3.html](http://www.linux-beginner.com/linux_setei3.html)

### SELinuxの停止
`getenforce`コマンドで`Enforcing`と出たらSELinuxが出てる。
`/etc/sysconfig/selinux`のファイルに下記のように記載

```
…
SELINUX=disabled
…
```

## 共有フォルダ設定
まず、VMWareをパワーオフした状態で、右クリ→オプション→共有フォルダで設定。
必要なものをインストール

```
yum install gcc gcc-c++ kernel-devel
```

build-essential?というものらしい？
これがないと共有フォルダの設定ができない。

[http://pussade8.hatenablog.jp/entry/2015/12/21/151912](http://pussade8.hatenablog.jp/entry/2015/12/21/151912)
あと、VMWareToolsも必要なのでインストール(起動時にそういうダイアログ出てたのでそれをクリック)

/mnt/hgfsが見えないので
[http://ur.edu-connect.net/archives/28512]
(http://ur.edu-connect.net/archives/28512)
を参考にする。

`./vmware-install.pl`って打つことに注意。

`/mnt/hgfs`が見えるようになる。
共有フォルダの名前を'symfony_demo'にしたので`/mnt/hgfs/symfony_demo`ができる

```
mount -t vmhgfs .host:/symfony_demo /home/admin/symfony/symfony_demo/
```

`Could not add entry to mtab, continuing` ってエラー？
でもmountできてるっぽい。
再起動したらダメや～！orz

→話を聞いてみたら、「共有フォルダの設定」をすればmount不要らしい。

ここで、Apacheの設定でドキュメントルートを調べる。
自分の環境だと、`/opt/httpd/httpd-2.4.20`にApacheがいるのでそこの`config/httpd.conf`を見てドキュメントルートを調べる。
※多分htdocsになってる。

ここがApacheで見れるところがhtdocsになってるので、ここにシンボリックリンクを貼る。
てか貼ってもらった。

```
ln -s /mnt/hgfs/symfony_demo/ htdocs
```

これで共有フォルダにファイルを入れると見れるようになる。

だがしかし、これだとPHPのパブリックな場所でないので、もう少しやることがある。
①PHPのアプリを作る
②①のアプリのパブリックな場所(web)をシンボリックリンク
これはあとで追記。

再インストールじゃないとき、mntで戸惑いたどり着いたサイト。
http://d.hatena.ne.jp/knaka20blue/20120919/1348024501
Raspberry Pi 3初期セットアップ作業メモ


# Spec.
ハードウェア：

- Raspberry Pi 3 Model B (element 14)
- 5.2V-2.5A DC給電USBアダプタ
- Transcend microSDHC 32GB Class10
- Wi-Fiアクセスポイント (2.5GHz/11n)
- HDMIケーブル＋TV, USBキーボード, USBマウス
- （有線LAN接続なし）

ソフトウェア：

- Raspbian Jessie (`2016-03-18-raspbian-jessie.img`)


# 初回起動まで
つ http://qiita.com/ttyokoyama/items/7afe6404fd8d3e910d09


#  X起動後

## ファイルシステムを拡張
1. 画面左上[Menu] → [Preferences] → [Raspberry Pi Configuration]
2. [System]タブ → [Expand Filesystem]ボタン
3. （再起動を促すダイアログが表示されるのでreboot）

`df -H`コマンドで確認した/dev/rootのSize：拡張前 3.9G → 拡張後 32G

備考：ターミナルから[`raspi-config`][raspi-config]コマンドでも同じ操作を実行可能。

[raspi-config]: https://www.raspberrypi.org/documentation/configuration/raspi-config.md

## ロケール／タイムゾーン／キーボード設定
1. 画面左上[Menu] → [Preferences] → [Raspberry Pi Configuration]
2. [Localization]タブ
3. [Set Locale...] → "ja (Japanese)", "JP (Japan)", "UTF-8"
4. [Set Timezone...] → "Japan"
5. [Set Keyboard...] → "Japan", "Japanese (Kana 86)"
6. [Set WiFi Country...] → "JP Japan"

備考：ターミナルから[`raspi-config`][raspi-config]コマンドでも同じ操作を実行可能。

## Wi-Fi接続設定
```
$ sudo su -
# wpa_passphrase [SSID] [PASSWORD] >> /etc/wpa_supplicant/wpa_supplicant.conf
# vi /etc/wpa_supplicant/wpa_supplicant.conf
network={
  （以下を追記）
  # WPA2-PSK(AES)
  proto=WPA
  key_mgmt=WPA-PSK
  pairwise=CCMP
  group=CCMP
}
```

設定ファイルの妥当性チェック＆Wi-Fi接続確認は `wpa_supplicant -Dwext -iwlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf` 

DHCPクライアント動作：

```
# vi /etc/network/interfaces
（iface wlan0 inet manualから書き換え）
iface wlan0 inet dhcp
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
# /etc/init.d/network restart
```

静的IP割り当て：

```
# vi /etc/network/interfaces
（iface wlan0 inet manualから書き換え＆追記）
iface wlan0 inet static
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
    address 192.168.NNN.NNN
    netmask 255.255.255.0
    gateway 192.168.NNN.NNN
# /etc/init.d/network restart
```

備考：[最新のRaspbian](https://www.raspberrypi.org/blog/another-update-raspbian/)では、予めSDカード内の`/boot/wpa_supplicant.conf`を配置しておけば自動的に`/etc/wpa_supplicant/`へ移動してくれる。原理的には初回起動からI/Oデバイス無しで、いきなりWiFi接続SSHログインができる気がする（トラブルシュートを考えると現実的ではないが…）

## apt-get upgrade
```
# apt-get update
# apt-get upgrade
```

## 日本語フォント／IME導入
```
# apt-get install fonts-ipafont fonts-ipaexfont
# apt-get install uim uim-mozc
```

## VNCサーバ導入
https://www.raspberrypi.org/documentation/remote-access/vnc/

```
# apt-get install tightvncserver
```

# その他
## Minecraft Pi Ed.をサバイバル化
http://jyn.jp/play-minecraft-pi-edition/
Perl のNaN 判定

# 結論から書く
- スクリプトの最初に`die "This perl does not support NaN!\n" if "NaN" == "NaN";`と書く
- 変数`x`がNaNか調べたいときは，`x != x`をチェックすれば良い。

# Perl のNaN
- Perlでは，NaNは何とも等しくならない値と定義されている。このため，`"NaN" == "NaN"`は偽となる。
- ただし，古いバージョンなど一部の処理系では，'"NaN"'は`0`を返す文字列として扱われる。
- このため，最初に手元の処理系が`"NaN"`をサポートしているかをチェックし，`"NaN" != "NaN"`の真偽を調べればよい。
【UE4】詳細パネルでの編集可・不可を制御する

#はじめに
外部に公開し詳細パネルから編集出来るパラメータを「ある条件を満たした場合のみ編集可能にする」というような事が出来るらしいのでご紹介します。

#はじめに
![1_ダメな例.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/a0614bb6-3ce5-dafb-caf7-c78de81c3dad.png)
上の画像のように詳細パネルに公開されたパラメータがあります。
各オフセット値には値が入力されていますが、このパラメータはチェックボックスにチェックを付けない限りは適用されないようになっています。
このような公開の仕方は「値を変更したのに全く適用されてない！」と文句を言われてしまったり、意図しない入力によりバグの原因にもなりかねません。
そこで「チェックボックスにチェックを付けた場合のみオフセット値の入力を可能にする」ようにしてみます。
![2_良い例.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/6db71599-d655-a634-a493-1d288914fdeb.png)

#パラメータの編集を制御するにはUPROPERTYのmetaを使う
いきなり結論ですが編集を制御出来る変数は以下のようにして定義します。

```cpp:test.h
	UPROPERTY(Category = Locomotion, EditAnywhere, BlueprintReadWrite)
		uint32 bRightLeftMoving : 1; 
	
	UPROPERTY(Category = Locomotion, EditAnywhere, BlueprintReadWrite, meta=(EditCondition = "bRightLeftMoving"))
		float RightLeftOffset = 256.f;
```

現状変数のmetaはC++でしか書けないためC++で書いています。

uint32 bRightLeftMoving : 1;
と
meta=(EditCondition = "bRightLeftMoving")
が紐付けられている箇所です。
uint32 変数名 : 1;
で真理値（bool）が定義されます。
EditCondition = "変数名"
で「変数名がTRUEの時に変数の編集を可能にする」となります。

後はエディタでコードのコンパイルをしてやればチェックボックスが付いていないRightLeftOffsetは入力が出来なくなっているはずです。

#FALSEの時に編集可能にする
```cpp:test.h
	UPROPERTY(Category = Locomotion, EditAnywhere, BlueprintReadWrite)
		uint32 bHoge : 1;

	UPROPERTY(Category = Locomotion, EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "bHoge"))
		float hoge = 256.f;

	UPROPERTY(Category = Locomotion, EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "!bHoge"))
		float foo = 256.f;
```
EditCondition = "変数名"
で変数名がTRUEの時編集可能と出来ますが
EditCondition = "!変数名"
というように変数名の前に！をつける事で変数名がFALSE時のみ編集可能と出来ます。
![4_びっくりマーク.PNG](https://qiita-image-store.s3.amazonaws.com/0/104467/89d49d51-122a-16c2-ec61-f4bf921c0e2b.png)

#式の評価はできないっぽい
EditCondition = "変数名" ですが EditCondition = "変数名 == 1" というような式を評価することは出来ません。
コリジョン設定のコリジョンプリセットのように列挙型による編集の制御は出来るようですが、自分では該当するコードが見つけられませんでした。
https://forums.unrealengine.com/showthread.php?54493-How-do-I-enable-disable-controls-in-my-blueprint-details-panel-via-C
こちらのフォーラムでは「CanEditChange関数」をオーバーライドすることで式による評価が可能だと書いてあるので、こちらで列挙型による編集の制御を行っているのかもしれません。

#おわりに
metaのEditConditionを書くことで該当箇所の編集制御が出来るようになりました。
しかし、ブループリントの継承で派生先にのみ存在する変数を定義することで同様のことは可能だと思います。
C++を追加して編集を制御するかクラスを派生させて編集を制御させるかは時と場合によると思いますので、とりあえずこの方法は数あるうちの一つという程度の認識でお願いします。
Storyboardだけでページング可能なScrollViewを定義 の、図を書いた

[Storyboardだけでページング可能なScrollViewを定義 〜僕の場合〜](
http://qiita.com/malt/items/addcfcec0c6c3bfffcf0) がたいへん参考になった。しかしやっぱりStoryboard の Constraints なにがなんだかわからなくなるので、図にしました。

これでわかりやすくなっているのかはわかりません。

![StoryBoardページング.png](https://qiita-image-store.s3.amazonaws.com/0/2528/cc90cc65-d697-475c-34e6-43cd668b27b6.png)

グレーの矢印が `Space == 0` の制約で、緑と青がそれぞれ `Equal Width` と `Equal Height` です。

この場合では Warning 無視して Update Frames しないほうがいいのではないかと思いました。
DockerとSolrでサクッと全文検索

#必要環境
 - Linux
 - Docker

#Solrの起動
DockerHubの公式リポジトリを使います。
https://hub.docker.com/_/solr/

設定などはコンテナ外で管理したいので、-vでボリュームを用意しておきます。

```bash
mkdir ~/solr-cores
docker run --name solr -d -p 8983:8983 -v ~/solr-cores:/var/solr/cores -t solr
docker exec -t -u root solr chown solr:solr /var/solr/cores
```

#コアの作成
Dockerコンテナに入ってコアを作成します。
bashを起動するとsolrユーザーで/opt/serverがワーキングディレクトリになった状態になります。
設定テンプレート(server/solr/configsets/data_driven_schema_configs)をコピーして設定を作成した後にコアを作成するAPIを実行します。

```bash
docker exec -ti solr /bin/bash
cp -R server/solr/configsets/data_driven_schema_configs /var/solr/cores/main
curl "http://localhost:8983/solr/admin/cores?action=CREATE&name=main&instanceDir=/var/solr/cores/main"
```

#ドキュメントの登録
./bin/postコマンドでドキュメントを登録できます。
試しに Solr の README.txt を登録してみます。

```
./bin/post -c main README.txt
```

#curlで検索

```bash
curl "http://localhost:8983/solr/main/select?indent=on&q=Software&wt=json"

{
  "responseHeader":{
    "status":0,
    "QTime":0,
    "params":{
      "q":"Software",
      "indent":"on",
      "wt":"json"}},
  "response":{"numFound":1,"start":0,"docs":[
      {
        "id":"/opt/solr/README.txt",
        "stream_size":[7242],
        "x_parsed_by":["org.apache.tika.parser.DefaultParser",
          "org.apache.tika.parser.txt.TXTParser"],
        "stream_content_type":["text/plain"],
        "content_encoding":["ISO-8859-1"],
        "resourcename":["/opt/solr/README.txt"],
        "content_type":["text/plain; charset=ISO-8859-1"],
        "_version_":1534201179174600704}]
  }}
```

#PHPで検索
PHPからSolrにアクセスするには、peclのsolr拡張をインストールしておく必要があります。

```php:solr_test.php
<?php

$client = new \SolrClient([
  'hostname' => 'localhost',
  'path' => 'solr/main',
  'port' => 8983
]);

$query = new \SolrQuery('*:*');
$response = $client->query($query);
$result = $response->getResponse();
var_dump($result);
```
Unity5+CardBoardSDKでVR実装する場合のヒント

Unity5+CardBoardSDKでVR実装する記事を読んでいく中で、躓いたポイントのみ記載します。他に見つかり次第、追記予定です。


#VR化する
CardBoardMain.Prefabをシーン階層に追加すると、ユーザの目線として機能する。

#Canvas表示
Render ModeをWorld Spaceにする

#単眼VR
単眼VRにするには、CardBoardMainのVR Mode Enabledのチェックを外す。
スクリプトから変更するには、
Cardboard.SDK.VRModeEnabled = false;
ZABBIX Sender を使ってAutoDiscoveryして監視項目を自動で増やす。

#背景
AWS上にVPC、及びそのVPCへのVPN接続が大量にある。そんな中でVPNが切れたか切れてないかを監視したい。(tunnelのUP数を数える。)
しかしVPNは結構な頻度で増減する。その為、都度ZABBIXにホスト追加したり、Templateにアイテム追加したりとかやってられるか( ﾟДﾟ)ｺﾞﾙｧ!
そこでZABBIXのAutoDiscovery機能を使い、自動でVPNの監視項目が増える様にする。

# 構想
ZABBIXに「VPN-Connection」というホストを作る。
このホストに「VPN-Monitoring」Templateを作って付ける。
この「VPN-Monitoring」TemplateにAutoDiscoveryとアイテムのプロトタイプを設定する。
AWS CLIからVPN情報を持ってきて、それをZABBIX Senderで纏めて送る。

# 利用環境
* 64bit Ubuntu 16.04
* ZABBIX Sever 3.0.2
* ZABBIX Sender 3.0.2
* Python3

# ZABBIX Template
「ディスカバリルール」に次の様に設定する。

```
名前 : vpn.connection.discovery
タイプ : Zabbixトラッパー
キー : vpn.connection.discovery
```

ディスカバリルール内の「アイテムのプロトタイプ」に次の様な設定を追加。

```
名前 : Monitoring of {#VPNNAME} - {#VPNID}
タイプ : Zabbixトラッパー
キー : vpn.conn[{#VPNID}]
```

AutoDiscoveryは、ZABBIX に対して指定されたデータを送信すると働く。この指定されたデータ形式を今回の設定に合わせて書くと次の様な形になる。

```json
{"data":[
  {"{#VPNID}":"vpn-1234","{#VPNNAME}":"Tokyo"},
  {"{#VPNID}":"vpn-5678","{#VPNNAME}":"Osaka"},
]}
```

なお、「一個のホストに対して上記のJSONで纏めて送られてきたモノ」が有効なアイテムとして登録される。
つまり上記JSONでは、TokyoとOsakaが登録される。この後NagoyaやFukuokaが増えた場合は、必ず次ぎのような形式で送信する必要がある。

```json
{"data":[
  {"{#VPNID}":"vpn-1234","{#VPNNAME}":"Tokyo"},
  {"{#VPNID}":"vpn-5678","{#VPNNAME}":"Osaka"},
  {"{#VPNID}":"vpn-9876","{#VPNNAME}":"Nagoya"},
  {"{#VPNID}":"vpn-4321","{#VPNNAME}":"Fukuoka"},
]}
```

仮に次ぎの様なJSONを送った場合、TokyoとOsakaは無くなったモノとして扱われ、指定された期日(標準では30日)が過ぎると監視項目が削除される。

```json
{"data":[
  {"{#VPNID}":"vpn-9876","{#VPNNAME}":"Nagoya"},
  {"{#VPNID}":"vpn-4321","{#VPNNAME}":"Fukuoka"},
]}
```

# AutoDiscovery用データを送るコード

``` python
ZBX_SERVER = '123.45.67.89'
ZBX_TARGET_HOST = 'VPN-Monitoring'

# ここで利用する{#VPNID}や{#VPNNAME}等の項目名は、「アイテムのプロトタイプ」の項目名と一致している必要がある。
placelist = ["Tokyo","Osaka","Nagoya"]
vpnidlist = {"Tokyo":"abc", "Osaka":"def", "Nagoya":"ghi"}
proplist = []

for place in placelist :
  prop = {
    '{#VPNID}':vpnidlist[place],
    '{#VPNNAME}':place,
  }
  proplist.append(prop)

JSONDATA = {}
JSONDATA['data'] = proplist

cmd1 =["/usr/bin/zabbix_sender", "-z", ZBX_SERVER, "-s", ZBX_TARGET_HOST, "-k", "vpn.connection.discovery", "-o", json.dumps(JSONDATA), "-vv"]
result = subprocess.call( cmd1, shell=False )
```

cmd1 で、ZABBIX Senderから上記の様な形でAutoDiscoveryが機能して、次の様な名前の監視項目が追加される。

```
Monitoring of Tokyo - abc
```

これで項目が出来たので、次のように値を送れば良い。

# 監視結果情報を送るコード

``` python
VPN_ID = '監視対象VPNのID'
TUNNEL_UPS = 'Up状態のtunnelの数。AWS CLIで取得。'
KEY = 'vpn.conn[' + VPN_ID + ']'

cmd2 =['/usr/bin/zabbix_sender', '-z', ZBX_SERVER, '-s', ZBX_TARGET_HOST, '-k', KEY, '-o', str(TUNNEL_UPS), '-vv']
result = subprocess.call( cmd2, shell=False  )
```

# 注意
* cmd1 を実行した後、ZABBIX Sever でAutoDiscoveryが動いて監視項目が追加され、データを登録出来る様になるまで時間が掛かります。なので、cmd1とcmd2の間にスリープを入れるなどして時間を空ける必要があります。
* 今回の場合、cmd2をVPN毎に値を送っていますが、値を纏めて送れば負荷を減らす事が出来ます。
引数が省略されたら全件抽出するストアド

ISNULLを使うと簡単にできました。

```example.sql
CREATE PROCEDURE
	[dbo].[Example]
		@Param1 nchar(3) = NULL, 
		@Param2 nchar(5) = NULL
AS

BEGIN
	SELECT
		*
	FROM
		TABLENAME
	WHERE
		column1= isnull(@Param1 , column1)
		AND column2= isnull(@Param2 , column2)
END
```
SSHのフィンガープリントが違ってログインできない際にknown_hostsから削除するワンライナー

# 始めに

ホストの再インストールなどを行った際にフィンガープリントが違う、っていうことで怒られますね。

```bash
$ ssh example.com
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:lWfMOia5da_KOIUHkMKWF9KDOIJOO315349LKOm91BA.
Please contact your system administrator.
Add correct host key in /Users/yousan/.ssh/known_hosts to get rid of this message.
                                                                                 Offending ECDSA key in /Users/yousan/.ssh/known_hosts:50
ECDSA host key for example.com has changed and you have requested strict checking.
Host key verification failed.
```

ホストが増えてくるといちいち行を探して削除するのが大変で、ファイルごと消したりしていました。

下記のようにすると該当行だけ消すことが出来ます。

```bash
$ sed -i.bak s/^exmaple\.com.*/d/ $HOME/.ssh/known_hosts
```

若しくはシェルクスリプトを書いておいて

```sh:~/sh/delkh
#!/bin/sh
if [ -n "$1" ]
then
    sed -i.bak s/^$1.*/d/ $HOME/.ssh/known_hosts
fi
```

```bash
$ ~/sh/delkh example.com
```

とすると該当の行を消してくれます。

元はFreeBSD用に作成したもので、現在はMac OS X (darwin)で使えています。`sed -i`の所がもしかするとOSによってはうまくいかないかもしれません。

# 今回の問題
今回はさくらのクラウドでKUSANAGIを使っていたところ、SSHのキーがパブリッククラウド全体で同じものを使っていた、ということで再生成の通知が来ました。

> さくらのクラウドにて提供しているパブリック・アーカイブの一部のOSにおいて、本来サーバごとに固有であるはずのSSHホスト鍵が同一になっているものがあることが判明いたしました。

>SSHホスト鍵を再生成すると、クライアントからログインする際に「SSHホスト鍵が一致しない」という警告／エラーが発生することがあります。
>フィンガープリントを確認いただき、SSHホスト鍵を更新していただきますようお願いいたします。
> http://cloud-news.sakura.ad.jp/2016/04/27/ssh-host-key/


この鍵を再生成した際にフィンガープリントが違って怒られました。

以上です。
Haskellでarduino(主にfrp-arduino)


arduinoで遊ぶのになるべく高級言語を使いたい。
Haskellでarduinoを扱うためのライブラリは[Haskell Wiki](https://wiki.haskell.org/Arduino)にまとまっている。

arduinoを扱うのに好きな言語を使うには[Firmata protocol](http://firmata.org/wiki/Main_Page)がよく利用されてるようです。
arduinoにFirmataでおしゃべりできるようになるにファームウェアをいれてシリアルポートでFirmataでおしゃべりしてarduino操作します。

このfirmata用のHaskellライブラリには[hArduino](http://hackage.haskell.org/package/hArduino)があります。

また、firmataから派生したものとして独自に進化したのがhaskinoっぽいです。

そして、Haskellでファームウェアを生成できるライブラリの[frp-arduino](http://hackage.haskell.org/package/frp-arduino)があります。
名前の通り、arduinoでFunctinal Reactive Programming可能にするようです。

Firmataを利用するとMacなり、ラズパイなりなにかとシリアル通信していないといけないし、かといってC言語っぽい言語も書きたくないので、frp-arduinoで遊んで見ることにしました。

公開されてる 0.1.0.3 のfrp-arduinoはghc 7.10.3だとうまくビルドできませんでした。githubのmasterは対処がしてあったので、stack.yamlのpackagesにgitリポジトリを指定して利用しました。

```stack.yaml
packages:
- '.'
- location:
    git: git@github.com:frp-arduino/frp-arduino
    commit: cf463a0f9a1f9a36d1d760994adccd74c4e82123
```

Lチカのサンプルコードはこんな風になっています。

```
import Arduino.Uno

main = compileProgram $ do

    digitalOutput pin13 =: clock ~> toggle
```

このプログラムを実行するとpin13がチカチカする`main.c`が生成されます。C言語ファイルが生成されます。
あとはこの`main.c`をコンパイルして、arduinoにアップロードします。

# OS Xでのアップロード手順

arduino用の実行ファイルをつくるためにコンパイラなどなどをインストールします。

```
$ brew tap osx-cross/avr
$ brew install avr-libc
```

arudinoと通信するmakeファイルが簡単につくれる`arduino-mk`をインストールします。


```
$ brew tap sudar/arduino-mk
$ brew install arduino-mk
```

このarduino-mkがpyserialを使うようなので好みの方法でいれます。

```
$ easy_install -U pyserial
```

あとは適当にMakefileをかきます。

```Makefile
NO_CORE = Yes

BOARD_TAG = uno
MCU = atmega328p
F_CPU = 16000000L

AVRDUDE_ARD_PROGRAMMER = arduino
AVRDUDE_ARD_BAUDRATE = 115200

include /usr/local/opt/arduino-mk/Arduino.mk
```

`make upload`を実行すればarduinoにインストールできます。

# 遊んだコードなど

pinを指定すればLチカできる関数は以下の感じです。

```
blickBasic pin = digitalOutput pin =: clock ~> toggle
```

チカチカ速度を調整するには`clock = every 10000`となってるので

```
blinkSpeed pin speed = digitalOutput pin =: every speed ~> toggle
```

で変えることができました

点灯しっぱなしにしたいなら

```
eternalHigh pin = digitalOutput pin =: clock ~> mapS (const bitHigh)
```

なのでできました。clockが来るたびにbitHighになるようにしてるだけです。

`uart`を使うとシリアルポートからアウトプットができました。

接続するとカウントアップする処理とかかいてみました。

```
import           Arduino.Uno

main = do
  compileProgram $ do
    uart =: clock ~> foldpS (\_ state -> state + 1) 0
       ~> mapSMany formatDelta
       ~> flattenS
   
formatDelta :: Expression Word -> [Expression [Byte]]
formatDelta delta = [ formatString "delta: "
                    , formatNumber delta
                    , formatString "\r\n"
                    ]

```

# 感想

ハードウェアとFPRって相性いいと思います。

グローバルな変数をつくる方法がわからない。

# 試した時のコード

[eiel/frp-arduino-sample](https://github.com/eiel/frp-arduino-sample)

# LTしたときの資料

* https://speakerdeck.com/eiel/gao-ji-nayan-yu-dearudino
* [DEMO動画](https://www.youtube.com/upload)

# 参考

* https://github.com/sudar/Arduino-Makefile
* https://github.com/osx-cross/homebrew-avr/
onTouchEventでmoveしたときの速度を取る方法

http://developer.android.com/intl/ja/training/gestures/movement.html#velocity

上記を翻訳、まとめてみた。

```java

private VelocityTracker mVelocityTracker = null;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int index = event.getActionIndex();
        int action = event.getActionMasked();
        int pointerId = event.getPointerId(index);

        switch(action) {
            case MotionEvent.ACTION_DOWN:
                if(mVelocityTracker == null) {
                    //  動きの速度を監視する新しいVelocityTrackerオブジェクトを取得します。
                    mVelocityTracker = VelocityTracker.obtain();
                }
                else {
                    // 速度トラッカーを初期状態にリセットします。
                    mVelocityTracker.clear();
                }
                // Add a user's movement to the tracker.
                mVelocityTracker.addMovement(event);
                break;
            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
              //速度を決定する場合、computeCurrentVelocity（）を呼び出します。
              //その後、getXVelocity()を呼び出します
              //getYVelocity（）は各ポインタIDの速度を取得します。
                mVelocityTracker.computeCurrentVelocity(1000);
               
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // 他のユーザーによって再利用されるようにバックVelocityTrackerオブジェクトを返します。
                break;
        }
        return true;
    }
```
35歳定年説って？年食ってもずーっとコード書く仕事で構わんよ。ただし日本以外に限る

コードを書く仕事をずっと続けていたい、と考えている。「日本以外でなら」という条件付きで。

ソフトウェアエンジニアという職に対する待遇と状況が日本と英語圏ではまったく異なるというのが大きい。元からコードを書いてモノ作るのが好き、というのがあるが、そんな私でも仮に日本でエンジニアをしていたら「なんとかしてコードを書く仕事から脱出しよう」と考えていたと思う。ところが海外に出た途端に考えが変わった。

まず日本では給与がありえないぐらいに低くおさえられている。日本の技術力は高く、すごいエンジニアがたくさん居る。でもそんなすごいエンジニアでさえ「？」というような額の給与で働いている。

一方アメリカのソフトウェアエンジニアの年収の中央値が１１８０万円。イギリスが１０２１万円。現地の物価や家賃の高さなどを考慮しても明らかに待遇がいい。シンガポールのデータはないがどう考えても日本のそれとは比較にならない。
この年収は中央値であり、あくまで平均的なスキルのエンジニアが稼ぐ額。もしあなたが「オレのスキルは平均より上だぜ」と考えていて、それが本当なら英語圏で１０００万円以上稼いでいても不思議ではない。

理由はカネだけではない。こちらではソフトウェアを設計してコードを書くことの専門性を活かした運営がされている。海外と日本のエンジニアを比較した議論では給与待遇の話が多いが、この運営体制の方が問題としては根深いと感じる。

かつて日本でエンジニアをしていた頃には「上流ほどエライ。下流は文字通り下っ端。」という発想があった。プログラマーというのは下流のエンジニアで、詳細仕様書に書かれた通りにコードを書けばそれだけでOkだ、と。この発想の根本には仕様書をコードに落としこむなんて誰でもできるカンタンな仕事、という発想がある。

これにはまったく賛同できない。
優秀なエンジニアとダメなエンジニアの生産性は何十倍にもなる。（ステーブ・ジョブズは２００倍と言っていたが）これは今までの私の実感と一致する。シンガポールではお土地柄から全世界から様々な個性のエンジニアと遭遇する。どの会社もカスを掴みたくないので、採用にはある基準をもって厳選するのだが、それでもひょんなことから滑り込んでくる人がいる。それがたまたま技術的に発展途上でスキルレベルと職務が合っていなかったときの、その生産性の落差は強烈だ。

おそらくそんな経験も相まって「コードを書くということがカンタンな仕事ではない」という共通認識が誰にでもある。

コードを書かずに詳細仕様書が作れる人なんて居ない。
どんなに優秀な人であってもこれは無理。そしてシンガポールに来てからは詳細な仕様書なんて見たことがない。ほとんどは全体的な方針やらAPIを決定して、まずコードを書く。書き始めると仕様を変更した方がいい箇所が出てくる。で、エンジニアが独自の判断でガンガン仕様変更をしていく、という流れだ。カンタンに言うと「作りながら変更しながら完成させる」という感じ。ここがソフトウェアエンジニアの仕事の最も面白い部分だと思っている。

上流様から「テメー、ぷろぐらまーのクセに上流様が書いたキレいな仕様書を変更すんじゃねー」なんて絶対に言われない。
むしろそうしてコードを書く人が考えて、よい設計仕様に改良していくのが本来の仕事だからだ。コードを書いて具体的にモノを作っていく過程で見えてくること、改良した方がいいことが山のようにあり、こうした仕事の中で各エンジニアの生産性の違いが大きくでる。
多国籍なエンジニア達と働くようになって、見た目は短パンとTシャツの兄ちゃんでいつもヘッドホンをつけてMacBookのキーを叩いているだけで、日本的な基準で言うと「遊んでる」にしか見えない奴が、実は驚くべき成果を上げている例は何度も目撃してきた。

日本で働いていた時にはコードを書く人が「この仕様をこういう風に変更した方がいいんだよ」と提案している場面に遭遇したことが１回も無い。もう構造的に建築ゼネコンのように上流から下請け構造になっているから不可能だった。管理者にしてもゴチャゴチャ文句言うプログラマーよりも黙って納期守って言われた通りにだけコード書く奴の方が使いやすい、となっていた。

このような話をした際の上流様の反論として以下のようなのがあった。
「例えばサッカーの監督の場合。監督は選手と同じスキルを持っている必要は無いのです。監督には監督の仕事があって、その監督の仕事でスペシャリティを発揮しているのです。ボールを蹴るのは３流であっても、監督としては一流であれば問題ないのヨ。」と。

これ指摘しているポイントが違う。この例えで言うなら
「その監督はそもそもサッカーで勝つための監督をしていない。監督のプロフィール写真をフォトショ加工して見栄え良くすることに一生懸命になってるだけ。本来の仕事とその成果に目を向けましょうよ」というのが言いたいことだ。

ただ、これをホントの意味で理解するには想像力がある人にはパッと分かるが、想像力が無ければ難しいのかもしれない。

こういうことにいち早く気が付いている人達は日本国内でもイケてるスタートアップとかにさっさと転職しているような気がする。

もしこれをお読みのエンジニアの方で海外転職をお考えならばこれだけは断言できる。日本でコードも書かずにエラそうにしてるだけの上流様よりも、コード書いているあなたの方が海外の人材市場においては何万倍も有利ですよ、と。海外では詳細仕様書いてエラそうにするだけのポジション、なんて存在しないからだ。

こちらに海外転職をお考えのエンジニア向けにいろいろ記事書いたので、ご興味があればぜひ。
[Entries in 海外転職 category](http://tango-ruby.hatenablog.com/archive/category/%E6%B5%B7%E5%A4%96%E8%BB%A2%E8%81%B7)

日本の優秀な技術者が海外でエンジニアをすること、もしくは挑戦すること、に基本的にいつも賛成。
KotlinでRetrofit2/OkHttp3を使ってXMLを取得する

Kotlinで書いているアプリで、Retrofit2 + OkHttp3でRSSを取得したときのめも。最初、うまくパースされなくてKotlinの問題なのかRetrofitの書き方の問題なのかコンバータのSimpleの書き方の問題なのかわからなくてちょっとハマってしまいました。
取得する対象は、はてなブックマークのRSSです。
http://b.hatena.ne.jp/Rei19/favorite.rss

### 準備

```groovy:app/build.gradle
dependencies {

    ...

    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
    compile ('com.squareup.retrofit2:converter-simplexml:2.0.2'){
        exclude module: 'stax'
        exclude module: 'stax-api'
        exclude module: 'xpp3'
    }
}
```

### 実装

```kotlin:HttpClient
// シングルトンでClientを作っておく	
object HttpClient {
    val instance = OkHttpClient()
}
```

```kotlin:HatenaRssXml.kt
// パース用のクラス 1
// strict = falseにしないとXML内の全ての要素をclass内に定義する必要がある
@Root(name = "rdf:RDF", strict = false)
class HatenaRssXml {
    // @ElementList(inline = true) これだとダメだった。。。
    // @Jvmfieldをつけてもうまくいかなかったので謎
    @set:ElementList(inline = true)
    @get:ElementList(inline = true)
    var list: List<HatenaRssItemXml>? = null
}
```

```kotlin:HatenaRssXml.kt
// パース用のクラス 2
@Root(name = "item", strict = false)
class HatenaRssItemXml {
    @set:Element
    @get:Element
    var title: String = ""

    @set:Element
    @get:Element
    var link: String = ""

    @set:Element(required = false)
    @get:Element(required = false)
    var description: String = ""

    // dc:creatorみたいな : で区切られてる要素はPATHを指定する
    @Path("dc/creator")
    @set:Element
    @get:Element
    var creator: String = ""
}
```

```kotlin:HatenaRssService.kt
interface HatenaRssService {
    @GET("{userId}/favorite.rss")
    fun favorite(@Path("userId") userId: String, @Query("of") startIndex: Int): Observable<HatenaRssXml>
    } 
```

使うときはこんな感じ

```kotlin
    val adapter = Retrofit.Builder()
            .baseUrl("http://b.hatena.ne.jp")
            .client(HttpClient.instance)    
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .addConverterFactory(SimpleXmlConverterFactory.create())  // XMLのコンバータを指定
            .build()

    adapter.create(HatenaRssService::class.java)
            .favorite(userId, startIndex)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(
                // このへんてきとう 
            )
```
ＣＳＳデバイス別サイズ

いつも忘れるのでこちらでメモしておきます。

```lang:iOS
■ iPhone 5
@media only screen and (min-device-width:320px) and (max-device-width:568px) {
  //CSS記述
}

■ iPhone 6
@media only screen and (min-device-width:375px) and (max-device-width:667px) {
  //CSS記述
}

■ iPhone 6 Plus
@media only screen and (min-device-width:414px) and (max-device-width:736px) {
  //CSS記述
}

■ iPad
@media only screen and (min-device-width:768px) and (max-device-width:1024px) {
  //CSS記述
}

■ iPad縦向き
@media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:portrait) {
  //CSS記述
}

■ iPad横向き
@media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) {
  //CSS記述
}


```
Azureの受信セキュリティ規則(タグ）でハマった話

# 環境

* Azure Load Balancer
* Azure Virtual Machine


# 概要

主にAWSを使ってた人（俺）がAzureの
下記の3要素でハマったことを記載。

* ネットワークセキュリティグループ
* 受信セキュリティ規則
* ソース

# 詳細

AzureにはAWSで言うところのセキュリティグループがネットワークセキュリティグループというのに当たると思ってる。

んで、主に制御するのがAWSで言うinboundな訳で。
azureの場合「受信セキュリティ規則」と呼ばれてる。

こいつは基本的にはAWSのセキュリティグループと同じようなもので、
IPで指定したり全開放したりできる（個人的にはセキュリティグループ同士で疎通させられないのは辛い）

で、発信元を指定する要素として
「ソース」というのがある。
その中に

* 任意(どっからでもok)
* 発信元ipアドレス(CIDR指定)
* タグ

がある。この「タグ」が紛らわしい。


## タグ
* AzureLoadBalancer
* VirtualNetwork
* InterNet

InterNetは特に気にしなくていい。外と繋がるというわかりやすいもの。
問題はAzureLoadBalancerとVirtualNetwork

### AzureLoadBalancer
L4のAzureLoadBalancerからの疎通を許可してくれそうだが実は違う。
AzureLoadBalancerにはプローブというAWSで言うヘルスチェック機能があるのだが、その「ヘルスチェックの通信を許可する」というものだった。しかもこのヘルスチェック元。LoadBalancer自身ではないという話を聞いた(；´Д｀)ﾊｧ…
プローブ専用のipアドレスがあるらしい。それを許可するタグです。

なんでそうなってんだ。。。

### VirtualNetwork
一見するとLoadBalancerからの接続を許可しそうだがLoadBalancerはVirtualNetworkの外になってしまうからダメ。


## 補足
大体の人には想像がつくと思いますが、
LoadBalancer配下にあるアプリケーションサーバ達はLoadBalancer以外の接続を拒否したかった。そのため許可するところに「LoadBalancer」とかあればそれは選択しちゃうと思うんだよな。。。という半分愚痴。

# 結論
* vmにpublic ipを割り振るの止める
* 各vmへのsshはLoadBalancer経由でポートマッピング(わかりにくいからあまり好きではない）

思い込みは色々と判断を間違わせる。
sedの使い方メモ

# sed で条件にマッチする行の行頭に文字を入れる

例） 文字列'hoge'が含まれる行の頭に文字列'foo'を入れる

```shell-session
 $ cat txt
 aaaaaaaaaa
 bbbhogebbb
 cccccccccc
 dddhogeddd
 
 $ sed -i -e "s/.*hoge.*/foo&/" txt
 
 $ cat txt
 aaaaaaaaaa
 foobbbhogebbb
 cccccccccc
 foodddhogeddd
```

ちなみに '&'[^1] はマッチした文字列という意味である。この例では'hoge'が含まれる行全体にマッチするから、すなわち'hoge'が含まれる行の頭にfooをつけて置換するという処理になる。

[^1]: GNU版のsedコマンドでは '&' の代わりに '\0' と書いてもよい。
プログラマの考えが・・身につく本より(Python)：最頻値を求める

[前回](http://qiita.com/teratera/items/f58b8bd98d33e2bbe110)の続き
今回は、配列の最頻値を求めるコード
C++での解答コードがすでに掲載されていますが、pythonで書き換えてみました。

```cpp:test.cpp
int mostFrequent;
int highestFrequency = 0;
int currentFrequency = 0;
for (int i = 0; i < ARRAY_SIZE; i++){
    currentFrequency++;
    if (i == ARRAY_SIZE - 1 || surveyData[i] != surveyData[i + 1]){
        if (currentFrequency > highestFrequency){
            highestFrequency = currentFrequency;
            mostFrequent = surveyData[i];
        }
        currentFrequency = 0;
    }
}
```

<h2>自分のpythonコード</h2>

```test37.py
#!/usr/bin/env python
#coding:utf-8

import math

elem = [4,7,3,8,9,7,3,9,9,3,3,10]

###修正させていただいています
#count = {Elem.count(v):v for v in set(Elem)}
#high = max(count)
#most = count[high]
elem.sort()
most = 0
high = 0
current = 0
#for i,v in enumerate(Elem):
for i in range(len(elem)):
    current += 1
    if i == len(elem) - 1 or elem[i] != elem[i+1]:
        if current > high:
            high = current
            most = elem[i]
        current = 0
print('配列=',elem, '\n' , '最頻値:',most,'|','回数:',high)


・・・(ターミナル実行)
>>> import test37
配列= [3, 3, 3, 3, 4, 7, 7, 8, 9, 9, 9, 10] 
 最頻値: 3 | 回数: 4
>>> 


```

前回の反省を生かして”リスト内包表記"や"ジェネレータ内包表記"を活用を考えてみましたが、どうしても current += 1 の部分でカウントをとらないといけなかったため上記のif文の繰り返しにしました。
実際に解答コードがありながらpythonに直すだけで時間かかってしまうので慣れないといけないなと感じます。
Homebrew が使う ruby を変える方法

# 環境
```
$ uname -a
Darwin xxxxxxxx.local 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64
$ brew -v
Homebrew 0.9.9 (git revision 5f06; last commit 2016-05-10)
Homebrew/homebrew-core (git revision 908e; last commit 2016-05-11)
```

# 環境変数を使う方法
以下の環境変数を設定すると `$HOMEBREW_RUBY_PATH` の ruby を使ってくれます

```
export HOMEBREW_DEVELOPER=1
export HOMEBREW_RUBY_PATH=`使いたい ruby のパス`
```

# 解説
Homebrew が使う ruby は `/usr/local/Library/brew.sh` の59行目以降の下記のコードで決められています。

```
if [[ -z "$HOMEBREW_DEVELOPER" ]]
then
  unset HOMEBREW_RUBY_PATH
fi

HOMEBREW_SYSTEM="$(uname -s)"
case "$HOMEBREW_SYSTEM" in
  Darwin) HOMEBREW_OSX="1";;
  Linux) HOMEBREW_LINUX="1";;
esac

if [[ -z "$HOMEBREW_RUBY_PATH" ]]
then
  if [[ -n "$HOMEBREW_OSX" ]]
  then
    HOMEBREW_RUBY_PATH="/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby"
  else
    HOMEBREW_RUBY_PATH="$(which ruby)"
    if [[ -z "$HOMEBREW_RUBY_PATH" ]]
    then
      odie "No Ruby found, cannot proceed."
    fi
  fi
fi
```

`HOMEBREW_DEVELOPER` とは、 `man brew` によれば
If set, Homebrew will print warnings that are only relevant  to  Homebrew  developers (active or budding).
という効果があるそうです。

# 感想
上述の `/usr/local/Library/brew.sh` を書き換えたり `/System/Library/Frameworks/Ruby.framework/Versions/Current/usr/bin/ruby` を置き換えたりする手もありますが、
少なくとも一時的に変更するならこの環境変数の方法が楽だと思います。
VMware Tools をインストールして使いやすくする


VMware Player に、Ubuntu16.04 LTS 日本語 Remix をセットアップ
ただし、以下の問題があり、使いづらい
* Ubuntu 上でコピーした内容を、Windows 側のアプリにペーストできない
* WMware Player の画面サイズを変更できない

VMware Tools をインストールすれば上記の問題は解決

# 仮想マシンの設定変更
Ubuntu を「簡易インストール」でセットアップしたため、VMware Tools をインストールするには設定変更が必要

「仮想マシン設定の編集」の画面で、
* 「フロッピー」を削除
* 「autoinst.iso ファイルを使用」となっている「CD/DVD」を削除

編集後、Ubuntu をセットアップした仮想マシンを再生

# VMware Tools のインストール
「端末」を起動
インストール用の圧縮ファイル
/media/ユーザー名/VMware Tools/VMwareTools-XXXXX.tar.gz
これを解凍して、インストール用のスクリプトを実行

```shell-session
$ cd
$ cp /media/ユーザー名/VMware Tools/VMwareTools-XXXXX.tar.gz ~/
$ tar xvf VMwareTools-XXXXX.tar.gz
```

```shell-session
$ cd vmware-tools-distrib
$ sudo ./vmware-install.pl
```

インストール中にいろいろ聞いてくるが、すべてデフォルト設定にするので、そのままEnterを押す

インストール完了後、Ubuntu を再起動

これで、
* VMware Player 上の Ubuntu と Windows とでコピー＆ペーストができるようになった
* VMware Player の画面サイズを変更することができた

以下の記事を参考にしました
* [ゲストOSがUbuntuでVMWareToolsをインストールする手順](http://qiita.com/kure/items/dd8f01ff481d7556e0d2)
[phiary] CSS tips - Flexbox レイアウトでヘッダーナビゲーションを作ってみよう


※ [こちらで見るとページ内でデモの実行, 編集ができます](http://phiary.me/css-tips-flexbox-header-navigation/)

今回は Flexbox を使ってヘッダーナビゲーションを作る方法を紹介します.

今までは float もしくは `display: inline-block` でやるのが定石だったと思うのですが Flexbox を使えばもっとカンタンかつ柔軟なヘッダーナビゲーションを作ることができます.

<div id='toc'></div>

## Demo

http://runstant.com/phi/projects/a55b096f

## Points

### Flexbox 化して横並びにしよう

基本ですね. `display: flex` を指定して flexbox 化することで横並びにします.

```css
nav {
  display: flex;
}
```

### justify-content でそれぞれ画面端に寄せよう

`justify-content` を指定することで flexbox 内の要素を, 主軸(デフォルトでは横(row)) に添ってどう並べるかを変更することができます.

今回は div.title は左寄せ, ul は右寄せにしたいので下記のように指定しています.

```css
nav {
  justify-content: space-between;
}
```

### align-items で縦揃えを調整しよう

`align-items` は, 主軸と垂直方法の軸に対してどう並べるかを指定できるプロパティです.
今回は立て揃えは中央にしたいので下記のように指定しています.

```css
nav {
  align-items: center;
}
```


### ul と a タグをリセットしよう

`ul` タグや `a` タグはブラウザがデフォルトでいくつかスタイルを当てています.
これが地味に邪魔だったりするのでしっかり把握してリセットしてあげましょう.

`ul` は `margin`, `padding`, `list-style` をリセットします.

```css
ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
```

`a` タグは `color`, `text-decoration` をリセットします.

```css
a {
  color: inherit;
  text-decoration: none;
}
```

Flexbox にもだいぶ慣れてきました.
アウトプットがてらいくつか事例を交えつつ Flexbox を学べるエントリーを書いていこうと思います.
imageOrientationが設定されている画像の向き補正

新しいコンテキストを作成して描画し直すとimageOrientationに合わせて画像そのものの方向も補正される。
## サンプルコード
```objc
//    UIImage *picture = *****; //UIImageな画像を何処かから取得
    NSLog(@"%@",[self convertToString:picture.imageOrientation]); //=>UIImageOrientationRight
    CGSize size = picture.size;
    // 画像向き補正
    UIGraphicsBeginImageContext(size);
    [picture drawInRect:CGRectMake(0, 0, size.width, size.height)];
    picture = UIGraphicsGetImageFromCurrentImageContext(); // imageOrientationに合わせて画像向きが補正される
    UIGraphicsEndImageContext();

    NSLog(@"%@",[self convertToString:picture.imageOrientation]); //=> UIImageOrientationUp
 ```

## デバッグ用メソッド
```objc
//for debug
- (NSString*) convertToString:(UIImageOrientation) o {
    NSString *result = nil;

    switch(o) {
        case UIImageOrientationUp:
            result = @"UIImageOrientationUp";
            break;
        case UIImageOrientationDown:
            result = @"UIImageOrientationDown";
            break;
        case UIImageOrientationLeft:
            result = @"UIImageOrientationLeft";
            break;
        case UIImageOrientationRight:
            result = @"UIImageOrientationRight";
            break;
        case UIImageOrientationUpMirrored:
            result = @"UIImageOrientationUpMirrored";
            break;
        case UIImageOrientationDownMirrored:
            result = @"UIImageOrientationDownMirrored";
            break;
        case UIImageOrientationLeftMirrored:
            result = @"UIImageOrientationLeftMirrored";
            break;
        case UIImageOrientationRightMirrored:
            result = @"UIImageOrientationRightMirrored";
            break;
        default:
            result = @"unknown";
    }

    return result;
}
```
無音のmp3を作る

1秒の無音のmp3を作る場合、

```
ffmpeg -ar 48000 -t １ -f s16le -acodec pcm_s16le -ac 2 -i /dev/zero -acodec libmp3lame -aq 4 silent.mp3
```

こんな感じ。

# 何で無音のmp3が必要になったのか？

サウンド部分がない動画を`AVAssetExportSession`を使って書き出そうとしたら失敗になる現象に遭遇。

`insertEmptyTimeRange`では、書き出しに失敗するので色々調べてみると無音のデータを書き込むといいらしい。

なので、無音のmp3を作った。

## 参考

http://stackoverflow.com/questions/32817411/avassetexportsession-audio-missing-in-ios9
http://stackoverflow.com/questions/28865608/insertemptytimerange-to-avmutablecompositiontrack-not-working
http://stackoverflow.com/questions/32017827/ffmpeg-create-silent-ogg-audio-file
PHP_CodeSniffer(phpcs) のチェックを一部無効にする


どうしても、チェックを無視したい箇所がある場合は下記の方法でチェックを無効にできる。

[Advanced Usage · squizlabs/PHP_CodeSniffer Wiki](https://github.com/squizlabs/PHP_CodeSniffer/wiki/Advanced-Usage#ignoring-files-and-folders)

このドキュメントの通りです。

### ファイルの一部を無視する場合

無視したい範囲を @codingStandardsIgnoreStart 〜 @codingStandardsIgnoreEnd で囲う

```
// @codingStandardsIgnoreStart
$xmlPackage['error_code'] = get_default_error_code_value();
// @codingStandardsIgnoreEnd
```

### ファイルまるごと無視する場合

ファイルの先頭に @codingStandardsIgnoreFile をコメントで入れる

```
<?php
// @codingStandardsIgnoreFile
$xmlPackage = new XMLPackage;
$xmlPackage['error_code'] = get_default_error_code_value();
$xmlPackage->send();
```

### フォルダまるごと無視する場合

```
$ phpcs --ignore=*/tests/*,*/data/* /path/to/code
```
Goでも愛が生まれた

# 環境
Go 1.4.2

# 愛が生まれた

```go:index.go
package main

import "fmt"

func main(){
  fmt.Println(string('生' & '死'))
}
```

# 実行結果
![go_make_love.png](https://qiita-image-store.s3.amazonaws.com/0/116983/b849bd3c-f6ea-740d-79a7-9c6d2308bc07.png)

# 原理
'生'と'死'のASCIIコードを論理積することで'愛'のASCIIコードが出来、それを表示しただけ

# 元ネタ
[愛が生まれた](http://qiita.com/dongri/items/041ff3e7dde6c99beeb0)
目指せGISマスター #1 OpenStreetMapから道路NWを抽出する

# スマホのGPSの精度にはまだまだ不満がある
スマホでも手軽にGPSロギングができるようになった昨今ですが、
やはりというか、誤差は結構あります。

以下はMyTracks(もう使えない?)による車両走行軌跡。
![mytracks.png](https://qiita-image-store.s3.amazonaws.com/0/121181/43168fb9-bd2a-0f1f-f455-d0af1aeb88dd.png)

人が見ればどこを走ったかは分かりますが、なんとか綺麗な軌跡にできないもんか・・・
とは言え、Gセンサとか操舵とかのデータは取れていないですし、あってもそこから補正するのは素人には難しそうなので
マップマッチング的なことで何とかしたいなぁと思ったわけです。
では、地図データはどこから手に入れたらよいでしょう・・・？

# 作っておいてよかったOSM
上図でも使っているOpenStreetMap。
自前で地図サーバが欲しいということで構築しておいたのですが（構築方法はいずれ投稿するかも）、
タイルサーバとしては頻繁に使っていたものの、データ自体は見ておりませんでした。

ところが、なんという宝の山！これを今まで使わなかったなんて。。。

道路ネットワークもあれば、（多く無いですが）POI情報もあれば、建物のポリゴンもある。
精度うんぬんの問題はあるでしょうが、何十mもずれることはない（と信じている。少なくともスマホのGPSよりましなはず。）ので、
宝を掘り起こしていきたいと思います。

# OpenStreetMapから道路NWを抽出することができるか？チャレンジしてみた。

そもそもOSMのデータにアクセスしようと思ったのは
Overpass APIというものがあると教えてもらったのがきっかけです。
http://wiki.openstreetmap.org/wiki/JA:Overpass_API

確かに独自形式だがのクエリを投げると道路NWなどが表示される！
ということは自前で構築済みのOSMサーバからも同じようにデータがとれるはず！
と考えました。

構築時にPostgresql、PostGISを入れた記憶があったので、
地図サーバのPostgresqlにアクセス。
あるある！それっぽいテーブルが！
テーブルのスキーマを見るとOverpassAPIにあったようにhighwayなどの属性がある。
これはいける。と確信。

スキーマは以下などが参考になります。。
http://wiki.openstreetmap.org/wiki/JA:Osm2pgsql/schema
→道路NWを取るならplanet_osm_line テーブルから取るようです。
　今回はこのテーブルですね。

また車が走行する道路のみが欲しいのでhighwayの属性にどのようなものがあるかは確認が必要です。
以下が参考になります。
http://wiki.openstreetmap.org/wiki/Key:highway
footwayなど、歩道もデータには含まれています。

# 実際に取ってみた
スキーマを見るとwayカラムが実際に位置情報を持っているようですが、
型が"geometry(～～)"となっており、単純に取得しても人間には読めません。
理解するにはgeometry型をPostGISで変換する必要があります。
`ST_Astext(ST_Transform(way,4326))`
→4326はProjectionのコード。これもいろいろ種類があるようですが、世界測地系は4326で良さそう。

上記を踏まえて例として甲州街道という文言がnameカラムに含まれるデータをSQLで抽出します。
`select osm_id,name,highway,z_order,ST_Astext(ST_Transform(way,4326)),way_area from planet_osm_line where name like '%甲州街道%';`

少し時間がかかりますが、
` 141147784 | 甲州街道               | trunk        |       8 | LINESTRING(138.089114228403 36.0716119850332,138.088936900966 36.0716665145095,・・・`
というようにデータが取れました。パチパチパチパチw
でも、nameは入っていないデータの方が多いので取得条件には工夫が必要。。。

# まとめてごっそり取りたい。
緯度経度の四角を指定して、そこに含まれるデータだけ取りたい。
最終的にはPOLYGONで指定した範囲で取りたい。
手間がかかりそうな気がしましたが、
考えてみればOverpass APIだとbboxで見えている範囲で取っているのでできるはずなのです。

調べてみたところ、当然ですができます。
指定したPOLYGONの中に”wayの最初のpointが含まれる"という条件が以下で実現できます。
これをwhere句に入れればOKです。
`ST_Within( ST_StartPoint( ST_Transform(way,4326)) , ST_GeomFromText ( 'POLYGON(( 位置1,位置2,位置3, ... ,位置1))' ,4326) )`

POLYGONの位置は「lon1 lat1,lon2 lat2・・・」というようにスペース区切りで緯度経度のペアを生成し、
カンマ区切りで位置を数珠つなぎにします。最後に位置1も記述し、輪になるようにする必要があります。

これを使うと都道府県などのPOLYGONデータを持っているのであれば、”都道府県別に取得”ということもできるはずです。

# PostGISはいろいろな機能がある
使いこなすにはまだまだほど遠いですが、便利な機能が結構ありますね。
特にPOLYGONの面積を出せるのは便利です。今後も使いそうです。
![area.png](https://qiita-image-store.s3.amazonaws.com/0/121181/8fb757b9-73f3-1b85-e522-ab99420227f6.png)

POLYGONで指定した面積がおよそ500平方kmであることが算出できます。
PostGISの関数を使いたいだけなので select ～で計算だけさせれば良いです。

# とりあえず道路NWデータの抽出は出来る
今回はOSMのデータベースから道路NWの抽出を行いました。
しかし、マップマッチングと言っている以上、この抽出データとGPSデータをマッチングさせる必要があります。

どうやろう・・・
片っ端から距離計算するという手もあるが、さすがに時間がかかりすぎるだろうなぁ・・・

つ R-Tree

ということで次回はR-Treeを使って"高速に"GPSとOSMの道路NWをマッチングさせていきます。

俺たちの戦いははじまったばかりだ
Playgroundがエラーで動作しない場合


# 環境
- Xcode 7.3

# 状態

Playgroundを新規作成
↓
Viewのレンダリングを確認しようとする
↓

```
Playground execution terminated because the process stopped unexpectedly. 
```
というエラーがでて、うまく実行されない

# 解決方法

## 以下のディレクトリがある場合

```
~/Library/Developer/CoreSimulator/Profiles/Runtimes
```
内のファイルを全部削除する

## なかった場合

再起動でなおりました
ActionCable using PostgreSQL adapter

ActionCableのadapterにPostgreSQLが使えるようだったのだが、設定がまったく見当たなかったのでソースを見たところ、ActiveRecordのコネクションを利用するようになっていて、要するにActionCable独自の設定は不要だった。分けられないという見方もできるけど、まあ分けるぐらいならredisを使うと思うのでシンプルで充分。

ちなみに設定は以下の通り。

```yaml

development:
  adapter: postgresql
test:
  adapter: postgresql
production:
  adapter: postgresql

```

簡単ですね！ほとんど出オチですみません。
docker-machineのvmにsysdig/csysdigを入れる方法

```
docker@default:~$ sudo vi /etc/profile.d/sysdig.sh
```

```
#!/bin/sh

#!/bin/sh

alias sysdig='docker run --rm -i -t --name sysdig --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro sysdig/sysdig'
alias csysdig='docker run --rm -i -t --name sysdig --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro sysdig/sysdig csysdig'
```

```
$ sudo chmod +x /etc/profile.d/sysdig.sh
```

docker-machine sshしなおして動作確認

```
$ sysdig --help
$ csysdig
```
fishで補完の効くalias


[balias](https://github.com/oh-my-fish/plugin-balias)プラグインが使える。
oh-my-fishが入ってるなら簡単にインストールできる。

```
$ omf install balias
```

`git`を`g`にしてたりしている場合便利。
この短いエイリアスで置き換える系は[expand](https://github.com/oh-my-fish/plugin-expand)プラグインを使うほうがいろいろできそうな気がしていたりもする。

g で git を使いたい場合の例

```
balias g git
```
CocoaPods を1.0.0にアップデートしたときにやったこと

# TL;DR
* CocoaPods1.0.0の正式版をインストール
* Podfileでtarget指定が必須に
* .xcconfigを使っている人はCocoaPods用の.xcconfigの#includeパスに注意
* ビルドエラーで.hが見つからないと怒られる場合はDerived Dataを削除すると良い（かもしれないです）

# 環境
* Xcode 7.3(7D175)
* OS X El Capitan(10.11.4)
* CocoaPods 1.0.0
* Xcodeのプロジェクトはschemeを追加していて、各schemeに対して.xcconfigを用意しています

# 設定まわりの作業
## 1.0.0からPodfileのtarget指定が必須に
[CocoaPods1.0 Migration Guide](http://blog.cocoapods.org/CocoaPods-1.0-Migration-Guide/)に詳しく書いてありますが、1.0.0からPodfileにtargetを設定していないと`pod update`などでエラーになります。

## .xcconfigの#includeパス
1.0.0にupdateしてから.xcconfigに記述していた#includeのパスが変わっていました。

```sh:1.0.0以前
#include "Pods/Target Support Files/Pods/Pods.xxxx.xcconfig"
```

```sh:1.0.0以降
#include "Pods/Target Support Files/Pods-プロジェクト名/Pods-プロジェクト名.xxxx.xcconfig"
```

1.0.0にupdateしたら`Target Support Files`配下を確認してみると良いです。

# ビルドエラー
設定まわりを変更したのでビルドをしたのですが、下記のようなエラーが発生しました。 

```
Command failed due to signal: Segmentation fault: 11
```

ログを見てみると

```sh:ログの一部
error: 'SpinKit/RTSpinKitView.h' file not found
#import <SpinKit/RTSpinKitView.h>
```

Clean Buildしたり、Build Settingの設定などを見ても特に怪しそうな箇所が見つからなかったので試行錯誤していたのですが、Derived Dataを削除してからBuildしたら無事にBuild Succeedとなりました。

# （参考）Derived Dataの削除方法
Xcodeのメニュー > Window > Projectsでウィンドウが表示されるので、該当プロジェクトの`Derived Data`の`delete`ボタンをクリックします。
Python3で画像をBase64エンコーディング

WebSocketで画像を送信する時に、Base64でエンコーディングしてから送信するために使ったコードのメモ。
もっと楽な方法はないものかね？

```py3
import base64

img_file = 'hoge.jpg'
b64 = base64.encodestring(open(img_file, 'rb').read())
try:
    # Python2                                                                                                                                                          
    print('b64=' + b64)
except TypeError:
    # Python3                                                                                                                                                          
    print('b64=' + b64.decode('utf8'))
```
journalctl -k とdmesgと

# 概要

```
journalctl -k
```
が　dmesg の代わりになりそうであった。

# 結論

詳しいことは別の解説にゆずるとして

```
journalctl --help
```

より抜粋

```
  -k --dmesg               Show kernel message log from the current boot
```

日付がみやすかったので、それだけでも便利な感じがあった。


そのほかも、いろいろ便利なオプションがある。

dockerだけみるなら

```
journalctl -u docker
```

とか

dockerとsshdをみるなら

```
journalctl -u sshd -u docker
```
DataTables で "Cannot read property 'mData' of undefined"

# DataTables で "Cannot read property 'mData' of undefined"

忘れたころに遭遇して、毎回調べるのでメモする。

## 原因

a. `<table>` に `<thead>`, `<tbody>` を定義していない。
b. `<thead>` と `<tbody>` で列数が異なる。

## 対処

a. `<thead>`, `<tbody>` を定義する。
b. 列数を同じにする。

## 確認した環境

- DataTables 1.10.11
- jQuery 1.12.0
Html Agility Pack の使用方法

# 導入
[Html Agility Pack](http://htmlagilitypack.codeplex.com/) を NuGet からインストールする。

# 実装方法

```csharp
void Main()
{
	WebScrapingRunner.RunAsync().Wait();
}

public static class WebScrapingRunner
{
	public static async Task RunAsync()
	{
		// 時間計測用のタイマー
		var timer = new System.Diagnostics.Stopwatch();
		timer.Start();
		
		using (var client = new HttpClient() { Timeout = TimeSpan.FromMilliseconds(30000) })
		{
			var targetUri = new Uri("https://www.gotokyo.org/eventlist/ja/list");
			var pageHtml = await client.GetHtmlAsync(targetUri);
			Console.WriteLine(pageHtml.DocumentNode.WriteTo());
		}

		Console.WriteLine("HTML取得完了: {0:0.000}秒", timer.Elapsed.TotalSeconds);
	}
}

public static class HttpClientExtensions
{
	public static async Task<HtmlDocument> GetHtmlAsync(this HttpClient httpClient, Uri requestUri)
	{
		var response = await httpClient.GetAsync(requestUri);
		return await response.Content.ReadAsHtmlAsync();
	}

	public static async Task<HtmlDocument> ReadAsHtmlAsync(this HttpContent httpContent)
	{
		var html = await httpContent.ReadAsStringAsync();
		var doc = new HtmlDocument();
		doc.LoadHtml(html);
		return doc;
	}
}
```