OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonで開発工数可視化してみた話

最近、Javaをがりがり書く仕事から大規模開発の責任者的な立ち位置にシフトしています。

100人前後のエンジニア/デザイナをマネジメントするとなると、リソース管理が結構大変なことになります。

案件ごとの進捗はJiraなどのプロジェクト管理ツールを使って、バーンダウンチャートなど作っていけば、可視化できますが、３ヶ月くらい先の開発計画に対して人が足りているか余っているかというのはJiraだけで可視化するのは結構難しかったりします。

多くの場合はスプレッドシートやパワポなどで矢羽を引いたり、要員アサイン表、山積み表を作ったりしていると思います。

たとえば、以下のような要員アサイン表があったとします。

|名前 |チーム  |10月上  |10月下  |11月上  |11月下  |12月上  |12月下  |
|---|---|---|---|---|---|---|---|
|Aさん |デザイン  |管理  |管理  |管理  |管理  |管理  |管理  |
|Bさん |バック  |案件  |案件  |改善|改善|改善|改善|
|Cさん|フロントエンド|システム保守|システム保守|システム保守|案件|案件|案件|

これが100人分あると考えてください。
ぱっと見では状況わからないので、当然、集計結果/分析結果をグラフ化することが必要になるかと思います。

## Jupyter Notebook使ってみる
スプレッドシートやエクセルならエクセル上で集計して表を作ればよいのでしょうが、以下の理由でJupyter Notebook を使ってみることにしました。

・集計ロジックを可視化できそう
・誤操作を防げそう

Jupyter Notebookを簡単に説明すると、Notebookと呼ばれる形式で作成したプログラムを実行しながら、分析作業を進めていくツールです。
実行結果を記録して、ページとして表示できます。

詳しくは以下から
http://jupyter.org/

## インストール
Macを使っていれば Homebrew などで python3 をインストール後、pip で簡単にインストールできます。

```
pip3 install jupyter
```


以下も必要になってくるのでインストールしておくとよいでしょう

```
pip3 install matplotlib
pip3 install pandas
pip3 install numpy
```

## 実際に書いてみる
前述の要員計画表をdata/chart.csv としてCSV形式で保存したとします。
以下のようなコードで簡単にグラフが出せます。

```
%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# CSVからDataFrameを作成。空のセルは なし で埋める
df = pd.read_csv('data/chart.csv').fillna('なし')

# チーム単位集計 (SQLでいうところのgroup by)
groupd = df.groupby('チーム')
result = groupd.agg(lambda x :  [sum( x == '管理' ),sum( x == '改善' ),sum( x == 'システム保守') ,sum( x.str.contains("案件")),sum(x == 'なし') ])

 # バックエンドチーム (例)
left = np.array([1,2,3,4,5])
label = ['Management','Improve','Maintaince','Enhance','No Assign']
plt.bar(left, result['10月上']['バック'],tick_label=label,color="green")
plt.title("Backend Engineers")
plt.xlabel("Task")
plt.ylabel("Man-Power")
plt.grid(True)
```

### 実行結果例
<img width="789" alt="スクリーンショット 2017-12-09 17.12.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/38460/1b56b046-569a-5d6f-7112-bab22d584ee5.png">



## Github上で描画/共有できる
Jupyter Notebookで作られる.ipynbファイルは、Github上で描画できます。
Githubを社内で使っているので、集計結果をPushして、そのURLを「現状こんな感じ！」とSlackで簡単に共有できます。
(エクセルファイルを貼り付けるより楽！)

Jupyter Notebookが使えるようになると、社内のデータサイエンティストとの会話も弾むかも！　という効果もありますね。
keras / Anacondaの罠：　環境変数 KERAS_BACKEND の悪行

Windows7 64bit 環境の Anaconda プロンプトから keras （CPUのみ）を使っていて、気のせいか、なんとなく処理速度が遅い気がしていた。
なお、バックエンドは tensorflow を入れて設定していた **つもり** でいた。

と、実行時の警告を見逃してた。。。
`python kerasのサンプルプログラム.py`

`Using Theano backend.
WARNING (theano.configdefaults): g++ not available, if using conda: `conda install m2w64-toolchain`
WARNING (theano.configdefaults): g++ not detected ! Theano will be unable to execute optimized C-implementations (for both CPU and G
PU) and will default to Python implementations. Performance will be severely degraded. To remove this warning, set Theano flags cxx
to an empty string.`

なになに！？　なんかがないので死ぬほど遅くなるって？
そんな話きいてなかったけど。。
つまり、バックエンドを Theano でやろうとして、それがないので、
しかたなく死ぬほど遅い Python 実装を使うってこと？

本家のページ：
https://keras.io/ja/backend/
によると、
`$HOME/.keras/keras.json`
これが、Windows だと、
`
type \Users\[ユーザー名]\.keras\keras.json
{
    "floatx": "float32",
    "epsilon": 1e-07,
    "backend": "tensorflow",
    "image_data_format": "channels_last"
}
`
ふむ、tensorflow を指定してて、問題なし。

え？　なになに？　本家のページによると、
`環境変数 KERAS_BACKENDも定義することができて，かつあなたの設定ファイルで定義されているものを上書きします`

んで、どこに定義したらええねん？

https://qiita.com/TomokIshii/items/7de052565719add8e8ad
によると、
`export KERAS_BACKEND=tensorflow`
とのことだけど、これってLinux の話かな？

ええと、ウチの Python は Windows で Anaconda3 の環境を使ってるので、
`type C:\ProgramData\Anaconda3\etc\conda\activate.d\keras_activate.bat
set "KERAS_BACKEND=theano"
`
こいつが犯人か！　けしからん！！

こっちでも怒ってる人がいました。
`http://ossyaritoori.hatenablog.com/?page=1496332747`

しかし、keras_activate.bat が上書きできん！？　けしからん！

というわけで、とりあえず、keras_activate.bat のとなりに、
`keras_activate_local.bat`
というファイルを無理矢理つくって、中身を
`set "KERAS_BACKEND=tensorflow"`

にしちゃえ！　これで、Anaconda 起動時に無理矢理書き換え。（ 他の方法もあるとは思うが・・）

これで、Anaconda3 を再起動して、

`python kerasのサンプルプログラム.py
Using TensorFlow backend.
 :`
なるほど、**・・・・10倍ぐらい速くなった気がする。。。。**

ていうか、Anaconda プロンプトを使わなければいいのか。。
Anaconda はインストールには便利だけど、プロンプトは使う意味はあまりないのか。。
AWS S3上のオブジェクトのメタデータを取得する

```groovy
// Groovy Version: 2.4.11 JVM: 1.8.0_144 Vendor: Oracle Corporation OS: Mac OS X
@Grab('com.amazonaws:aws-java-sdk-s3:1.11.184')
import com.amazonaws.regions.Regions
import com.amazonaws.services.s3.AmazonS3
import com.amazonaws.services.s3.AmazonS3ClientBuilder

AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
        .withRegion(Regions.AP_NORTHEAST_1)
        .build()

def bucketName = 'your-bucket-name'
def key = 'some/s3/key'

def s3metadata = s3Client.getObjectMetadata(bucketName, key)
s3metadata.properties.each { k, v ->
    if(k in ["metaClass", "class"]) return
    println "$k: $v"
}
```

結果

```
serverSideEncryption: null
ETag: bff9fd94c2d3d672213687840a21d3d4
instanceLength: 258770
userMetadata: [:]
contentDisposition: null
rawMetadata: [Accept-Ranges:bytes, Content-Length:258770, Content-Type:image/jpeg, ETag:bff9fd94c2d3d672213687840a21d3d4, Last-Modified:Fri Nov 10 18:18:39 JST 2017]
replicationStatus: null
contentRange: null
ongoingRestore: null
SSECustomerAlgorithm: null
requesterCharged: false
expirationTimeRuleId: null
storageClass: null
restoreExpirationTime: null
contentLength: 258770
lastModified: Fri Nov 10 18:18:39 JST 2017
versionId: null
cacheControl: null
SSECustomerKeyMd5: null
SSEAwsKmsKeyId: null
contentEncoding: null
SSEAlgorithm: null
contentType: image/jpeg
contentMD5: null
httpExpiresDate: null
contentLanguage: null
partCount: null
expirationTime: null
```

### 参考
- https://stackoverflow.com/questions/1477706/groovy-property-iteration
Windows10+VS2017でLivetのプロジェクトテンプレートが表示されない

#はじめに
新しいPCにVisualStudio2017をインストールしたとき、
EH500_Kintarouさんの記事「[最強のWPF MVVMインフラ「Livet」をVS2017で使う](https://days-of-programming.blogspot.jp/2017/04/wpf-mvvmlivetvs2017.html)」を参考にしながら、
Livetをインストールしたのですが、
新しいプロジェクトにLivetが表示されなかった時の解消メモです。
終わってみると、大した話ではないのですが、同じことで躓いた人のために。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/25087aa6-d599-c0df-d77d-3d905c550d04.png)

※以前は、大丈夫だったのに、、、。

#Livetのプロジェクトテンプレートが表示されなかった理由
**simple_installer_for_vs2017.bat**で、Livetのプロジェクトテンプレートが置かれたフォルダと、
VisualStudioの「ユーザープロジェクトテンプレートの場所」が一致していませんでした。
[ツール]-[オプション]-[プロジェクトおよびソリューション]-[場所]の中のココです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/4fc313e0-dc22-4724-1f0d-0673393c9499.png)

なんだか、**知らない間に、VisualStudioのフォルダ設定が、OneDriveのフォルダになっていた**ようです。

#対処した方法
Livetのテンプレートを、インストーラで入っていた場所から、
VisualStudioに設定されていた「ユーザープロジェクトテンプレートの場所」にテンプレートを移動しました。

インストーラで入った場所に、**コードスニペット・プロジェクトテンプレート・項目テンプレート**すべてあったので、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/b1435013-7df6-2d1d-dc9c-22094a7ebf04.png)
それら一式を、OneDriveの下の対応するフォルダに移動しました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/4ab6f003-c771-1e23-aff8-c175a6ed1f30.png)

具体的にプロジェクトテンプレートのフォルダは、こんな感じ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/3fe7f8c7-340c-0d6d-8d4c-1f345b4dd717.png)

#動作確認
きちんとLivetが使えるようになりました。

**プロジェクトテンプレート**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/b9c9fdca-a509-5dec-43b4-1fd064cd4609.png)

**項目テンプレート**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/54ec996a-7d4d-e588-9061-e04546e74264.png)

**コードスニペット**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/197297/9f5061dc-682d-c937-5a30-4c6695adc913.png)


#おわりに
やっぱりLivetが使いたいなぁ、と思って、VS2017にインストールしました。
MVVMで開発するには、やっぱりいいですね。好きです。
Electronでファイル選択ダイアログを実装する

Electronでローカルファイルの選択ダイアログを実装するときには、dialogモジュールのshowOpenDialog関数を利用します。HTML `<input type="file">`  を利用するとファイルの選択ダイアログの表示はできますが、ファイルパスは取得できません。

### よく利用する引数

`dialog.showOpenDialog([browserWindow, ]options[, callback])`

* `browserWindow` (BrowserWindow) 親となるBrowserWindowsオブジェクトを指定すると、モーダル（表示中に親のウィンドウを無効化する）ウィンドウとして表示できる。
* `options` (Object)
  * `title` (String) ダイアログのタイトルに表示する文字列
  * `defalutPath` (String) 最初に表示するパス
  * `buttonLabel` (String) 選択ボタンに表示する文字列
  * `filters` (FileFilter[]) 選択対象のファイル種別
    * 例：`filters: [{name: 'Images', extensions: ['jpg', 'png', 'gif']}]`
  * `properties` (String[]) ダイアログの機能
    * `openFile` ファイルを選択する
    * `openDirectory` ディレクトリを選択する
    * `multiSelections` 複数選択を許可する
* `callback` 選択されたファイルパスの配列を引数に取るコールバック関数。省略した場合は`showOpenDialog`メソッドの戻り値で配列が返却される。

### 実装例

```js
const dialog = require('electron').remote.dialog;

let filenames = dialog.showOpenDialog(null, {
	properties: ['openFile'],
	title: 'Select a text file',
	defaultPath: '.',
	filters: [
		{name: 'text file', extensions: ['txt']}
	]
});
```

##### 参考

* [GitHub electron dialog](https://github.com/electron/electron/blob/master/docs/api/dialog.md)
du, df コマンド

この記事は [Linux コマンド 全部オレ Advent Calendar 2017](https://adventar.org/calendars/2630) の10日目の記事です。

# du

```
NAME
       du - estimate file space usage

SYNOPSIS
       du [OPTION]... [FILE]...
       du [OPTION]... --files0-from=F

DESCRIPTION
       Summarize disk usage of each FILE, recursively for directories.

       Mandatory arguments to long options are mandatory for short options too.
```
ディレクトリやファイル容量を確認するコマンド。
ファイルサイズではなく、専有しているブロックサイズを表示するので、ファイルサイズより大きくなる。

## よく使いそうな使い方

```
## ルートディレクトリの名ディレクトリの容量を確認する
[sinsengumi ~]# du -shc /*
0	/bin
110M	/boot
0	/dev
30M	/etc
0	/home
0	/lib
0	/lib64
0	/media
0	/mnt
0	/opt
0	/proc
20M	/root
8.4M	/run
0	/sbin
0	/srv
0	/sys
0	/tmp
778M	/usr
109M	/var
1.1G	合計


## 今いるディレクトリ内にある各ディレクトリの容量をディレクトリ毎に表示する（カレントディレクトリのファイルは含まない）
[sinsengumi ~]# tree -a
.
├── .bash_history
├── .bash_logout
├── .bash_profile
├── .bashrc
├── .cshrc
├── .tcshrc
├── anaconda-ks.cfg
├── dir1
│   ├── .dir
│   │   └── 5000k
│   ├── 1000k
│   └── dir1_1
│       └── 4000k
└── dir2
    └── 10000k

4 directories, 11 files
[sinsengumi~]# du -s ./*/
10000	./dir1/
10000	./dir2/
```

# df

```
NAME
       df - report file system disk space usage

SYNOPSIS
       df [OPTION]... [FILE]...

DESCRIPTION
       This  manual page documents the GNU version of df.  df displays the amount of disk space available on the file system containing each file name argument.  If no file name
       is given, the space available on all currently mounted file systems is shown.  Disk space is shown in 1K blocks by default, unless the environment  variable  POSIXLY_COR‐
       RECT is set, in which case 512-byte blocks are used.

       If  an argument is the absolute file name of a disk device node containing a mounted file system, df shows the space available on that file system rather than on the file
       system containing the device node.  This version of df cannot show the space available on unmounted file systems, because on most kinds of systems doing so requires  very
       nonportable intimate knowledge of file system structures.
```
ディスク容量を確認するコマンド。

## よく使いそうな使い方

```
[sinsengumi ~]# df -h
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   18G  981M   17G   6% /
devtmpfs                 910M     0  910M   0% /dev
tmpfs                    920M     0  920M   0% /dev/shm
tmpfs                    920M  8.4M  912M   1% /run
tmpfs                    920M     0  920M   0% /sys/fs/cgroup
/dev/sda1               1014M  142M  873M  14% /boot
tmpfs                    184M     0  184M   0% /run/user/0


## ディレクトリをしているすると、そのディレクトリが含まれる（マウントされてる）ファイルシステムのみを表示する
[sinsengumi ~]# df -h /home/
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   18G  981M   17G   6% /

[sinsengumi ~]# df -h /boot/grub
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1      1014M  142M  873M  14% /boot
```
mackerel-agent-plugins/mackerel-plugin-mysqlを使う

# さいしょに

CentOS7でmackerel-agentを使い始めることから、同一ホスト内のmariadbの状況を知りたいと思って、mackerel-plugin-mysqlを動かすまでを書きます。

# environment

- CentOS 7.4
- mariadb-server


# setup

```ini:console
# ifconfig入ってなかったら入れる
$ sudo yum install -y net-tools

# mackerelのページの通りに入れる
$ curl -fsSL https://mackerel.io/file/script/setup-all-yum-v2.sh | MACKEREL_APIKEY='___KEY___' sh
$ sudo journalctl -u mackerel-agent.service

# mariadbを入れて起動する
$ sudo yum install -y mariadb mariadb-server
$ sudo systemctl start mariadb.service
```

# install mackerel-plugins

- https://github.com/mackerelio/mackerel-agent-plugins
- https://github.com/mackerelio/mackerel-agent-plugins/tree/master/mackerel-plugin-mysql

```ini:console
# mackerel pluginsを入れる
$ sudo yum install -y mackerel-agent-plugins


# mackerel-agentのdefault configのパスを調べる(-conf string)
$ mackerel-agent -h

$ touch /etc/mackerel-agent/mackerel-plugin-mysql
# 下記の要否は分からない
$ chmod +x /etc/mackerel-agent/mackerel-plugin-mysql


# pluginをconfに関連付けて有効にする（内容は下記参照）
$ sudo vi /etc/mackerel-agent/mackerel-agent.conf
$ sudo vi /etc/mackerel-agent/mackerel-plugin-mysql

#念のため、mackerel-agentを再起動する
$ sudo systemctl restart mackerel-agent.service
```

```ini:/etc/mackerel-agent/mackerel-agent.conf
apikey = "___KEY___"
...
...
# command = "ruby /etc/sensu/plugins/http/metrics-curl.rb"
[plugin.metrics.mysql]
command = "/etc/mackerel-agent/mackerel-plugin-mysql"
```
```console:/etc/mackerel-agent/mackerel-plugin-mysql
mackerel-plugin-mysql -host=localhost -username=root -password=''
```

# wait some minutes ..

mackerelの当該hostのメトリクスが一気に増える。
（MySQL innodb Memory Allocationあたりのグラフがmariadbが消費しているメモリの量として考えられるのかは分からない。）
H2 Databaseのデータだけバックアップ&リストアするGradleのタスク

DBスキーマはFlywayで管理する前提で、テスト中の一時的なデータをバックアップ＆リストアするために、Gradleのタスクを作りました。

```
./gradlew backupH2 flywayClean flywayMigrate restoreH2
```

みたいにしたかったのですが、Flywayの管理テーブル（schema_version）やFlywayのスクリプトで管理しているデータがあるため、プライマリキー違反になってしまいダメでした。。。

とりあえず、データだけバックアップする方法としてメモを残しておこう。

# バックアップとリストアのタスク
バックアップは「[Backup using the Script Tool](http://www.h2database.com/html/tutorial.html#upgrade_backup_restore)」で作成したスクリプトファイルからCREATE文とALTER文を取り除いているだけです。

```build.gradle
apply plugin: 'java'

repositories {
	jcenter()
}


dependencies {
	runtime('com.h2database:h2:1.4.196')
}

// H2を使用するアプリのbuild.gradleが既にある場合は、ここから下を追記するだけで大丈夫なはず。
// スクリプトファイル名、DB接続URLなどは適宜変更する。

// H2のデータのバックアップ
task backupH2(type: JavaExec) {
	classpath = sourceSets.main.runtimeClasspath
	main = 'org.h2.tools.Script'
	args = ['-url', 'jdbc:h2:file:./h2/hoge', '-user', 'sa', '-password', '', '-script', 'data.sql']
	doLast {
		file('data.sql').text = file('data.sql').text.replaceAll(/(CREATE|ALTER)[^;]+;\s*\R*/, '')
	}
}

// H2のデータのリストア
task restoreH2(type: JavaExec) {
	classpath = sourceSets.main.runtimeClasspath
	main = 'org.h2.tools.RunScript'
	args = ['-url', 'jdbc:h2:file:./h2/hoge', '-user', 'sa', '-password', '', '-script', 'data.sql']
}
```

# （追記）改良版
バックアップとリストアの部分の改良版です。
スクリプトファイルに対して、Flywayの管理テーブル（schema_version）のINSERT文を削除し、その他のテーブルのDELETE文を追加しています。

```
def h2Url = 'jdbc:h2:file:./h2/hoge'
def h2User = 'sa'
def h2Password = ''
def h2ScriptFileName = 'data.sql'

// H2のデータのバックアップ
task backupH2(type: JavaExec) {
	classpath = sourceSets.main.runtimeClasspath
	main = 'org.h2.tools.Script'
	args = ['-url', h2Url, '-user', h2User, '-password', h2Password, '-script', h2ScriptFileName]
	doLast {
		def insertScript = file(h2ScriptFileName).text
		insertScript = insertScript.replaceAll(/(CREATE|ALTER)[^;]+;\s*\R*/, '')
		insertScript = insertScript.replaceAll(/(--|INSERT)[^;]+schema_version[^;]+;\s*\R*/, '')

		def deleteScript = ';\n'
		Set<String> tables = []
		insertScript.findAll(/INSERT INTO ([^\s]+)\([^;]+;\s*\R*/){ g0, g1 -> tables.add(g1) }
		tables.forEach() { table -> deleteScript += 'DELETE FROM ' + table + ';\n' }

		file(h2ScriptFileName).text = deleteScript + insertScript
	}
}

// H2のデータのリストア
task restoreH2(type: JavaExec) {
	classpath = sourceSets.main.runtimeClasspath
	main = 'org.h2.tools.RunScript'
	args = ['-url', h2Url, '-user', h2User, '-password', h2Password, '-script', h2ScriptFileName]
}
```

自分の環境では

```
./gradlew backupH2 flywayClean flywayMigrate restoreH2
```

ができたので、ひとまず良しとしよう。
parcel魅力的です

#最初に
土曜の朝に「[webpack時代の終わりとparcel時代のはじまり](https://qiita.com/bitrinjani/items/b08876e0a2618745f54a)」なんて魅力的なタイトルが付いた記事があったので早速乗っかってみた。

#環境構築から
とかいうわりにnode.js環境がなかったり、自分の端末がwindowsだったりなので、nodistインストールから。
↓が参考になりました。
[Windows での最速 Node.js 環境構築](http://tyru.hatenablog.com/entry/2017/03/13/162318)

まぁまぁそのとおりなのだが、ちょっとだけ補足。

- 通常のコマンドプロンプトでもできるかのような記載だが、起動しても結局管理者権限のpowershellでやれ！といわれる。
- npmアップグレードはうまくいかなかった

確かに簡単に環境構築できた。

#parcel導入まで
[https://parceljs.org/](https://parceljs.org/)のGetting Startedに素直に従った。

```
npm install -g parcel-bundler
```

で、rootパスに移動して

```
cd c:\wwwroot
parcel index.html
```

これだけ。parcelするとコンパイルが始まりますがあっという間。

あとは
http://localhost:1234
すれば、動きます。

あっという間にHMRの完成ですね。
（HMRってのはHot Module Replacementの略なのだそうですが…初めて知りました。）

riot.jsを使ってますが、普通に動きました。

#気をつけること
当たり前なのかもしれませんが、適当なグローバル変数や関数を定義しているとダメ。

```html:index.html
<script src='hoge.js'></script>
<script src='aaa.js'></script>
```
```js:hoge.js
var AAA = 'hoge';
```
```js:aaa.js
console.log(AAA);
```
こんな感じでまたいでいてもindex.htmlで両方のjsを順番間違えず取り込んでいれば通常は動きますが、parcelではこれがダメ。

```html:index.html
<script>
var MYAPP = {};
</script>
<script src='hoge.js'></script>
<script src='aaa.js'></script>
```
```js:hoge.js
MYAPP.AAA = 'hoge';
```
```js:aaa.js
console.log(MYAPP.AAA);
```
こんな感じにすれば動きます。

#phina.jsとの相性
いまphina.jsを使ってゲームを作ってる都合で、phina.jsと使いたかったのですが、こちらは
クラスphina.asset.SpriteSheet
              var json = JSON.parse(data);
のあたりではまってしまう。dataにhtmlタグが含まれる可能性があり、parcelだとそこではじかれる。
phina.js本体をいじってみたけど簡単じゃなさそうだから、とりあえず今回はphina.jsを使うときにはあきらめることにした。

#最後に
webpackなるものも併せて検索しましたが、少なくともHMR（←知った言葉を使いたがる）だけならこっちのほうが確実に簡単。

個人メモに近いですが、こんなところで。
Scratch 3.0 を Hackしよう。 scratch-vm に利用されている、scratch-xxx を触ってみよう

Scratch3.0 は、様々ん部品ごとに開発が進められています。
scratch-vm や scratch-gui もそうでした。

https://github.com/LLK/scratch-vm/blob/develop/package.json

の devDependencies を、参照して見てください。
それらの、部品を利用して、scratch-vm が作られています。

今回は、これらの部品について見ていきましょう!!



# なぜ　部品を確認するのか?

直感を有効に利用するためです。
『どこに、どんな、事が書かれているか?』
このことを、知っていることは重要です!!

自分で書いたコード隅々まで覚えていますか?
試しに、先週書いたコードを、全く同じに再現してみてください
記憶は曖昧なものです。
自分で書いたコードでさえ、寸分違わず再現する頃は出来ません。

試しに、以前書いたコードを、リファクタリングしたりして見ましょう。
コードを書いていた時の記憶が連想されますね。


より抽象的な階層で捉えると(慣れてくると)、プロジェクトを超えて、
どんな構造なのかという情報から、どこに、何があるかを、連想出来る
ようになります。


# コードを見てみよう


## scratch-render

( https://github.com/LLK/scratch-render )
Scratchのレンタリングエンジンです。Spriteの描画に利用されています。
以下で見れます。

http://llk.github.io/scratch-render/


![スクリーンショット 2017-12-09 15.58.09.png](https://qiita-image-store.s3.amazonaws.com/0/54192/7525af5e-dfe6-e33f-e1f2-7aa6be6e5477.png)




## scratch-blocks

( https://github.com/LLK/scratch-blocks )
Scratch で、コードを書くときに利用する Block関連の部品です。
Blockでコードが組めて、組んだコードをXML情報に変換してくれます。

以下で確認できます。
https://llk.github.io/scratch-blocks/


![スクリーンショット 2017-12-09 16.02.55.png](https://qiita-image-store.s3.amazonaws.com/0/54192/a4d61e0a-1d77-b871-f64f-7352b26117f4.png)




## scratch-audio

( https://github.com/LLK/scratch-audio )

Scratch の Audioの再生、編集に関連する部品です。



## scratch-storage

( https://github.com/LLK/scratch-storage )

ライブラリーを読み込んだり!! 記録したりするための部品です。

使い方とかは、test配下のコードを読んで見ましょう

https://github.com/LLK/scratch-storage/tree/develop/test





# PS

### 次回

続く

### 以下の場所でも、アレコレ書いていきます。

[Scratch3.0 自分専用機 を作ろう!! (0)](http://blogger.firefirestyle.net/2017/09/scratch30-0.html)
[Scratch3.0 自分専用機 を作ろう!! (1) Scratch3.0をビルドしてみよう](
http://blogger.firefirestyle.net/2017/12/scratch30-1-scratch30.html)
[Scratch3.0 自分専用機 を作ろう!! (2) Scratch3.0 を Androidアプリとして動作させてみよう (1)](http://blogger.firefirestyle.net/2017/12/scratch30-2-scratch30-android-1.html)
[Scratch 3.0 自分専用機 を作ろう!! (3) Scratch3.0 を Androidアプリとして動作させてみよう (2)](http://blogger.firefirestyle.net/2017/12/scratch-30-3-scratch30-android-2.html)
[Scratch 3.0 自分専用機 を作ろう!! (4) Scratch3.0 を Androidアプリとして動作させてみよう (3)](http://blogger.firefirestyle.net/2017/12/scratch-30-3-scratch30-android-3.html)
[Scratch 3.0 自分専用機 を作ろう!! (5) Webpack とは)](http://blogger.firefirestyle.net/2017/12/scratch-30-5-webpack.html)
[Scratch 3.0 自分専用機 を作ろう!! (6) Scratch3.0 の package.jsonを読んでみよう](http://blogger.firefirestyle.net/2017/12/scratch-30-6-scratch30-packagejson.html)
[Scratch 3.0 自分専用機 を作ろう!! (7) scratch-gui を インストールしてみよう](http://blogger.firefirestyle.net/2017/12/scratch-30-7-scratch-gui.html)
[Scratch 3.0 自分専用機 を作ろう!! (8) scratch-vm に利用されている、scratch-xxx を触ってみよう](http://blogger.firefirestyle.net/2017/12/scratch-30-8-scratch-vm-scratch-xxx.html)


[火の型 With Scratch 2.0 (プログラム入門) 　第00巻](https://www.gitbook.com/book/kyorohiro/firestyle/details)
[火の型 With Scratch 2.0 (プログラム入門) 　第01巻](https://www.gitbook.com/book/kyorohiro/firestyle01/details)
[炎の型 With Scratch 2.0 (ゲームプログラム入門)](https://www.gitbook.com/book/kyorohiro/doc_scratch/details)
macでSQLiteをビルドしてみる

手元のMac（El Capitan、バージョン10.11.6）でSQLiteをビルドしてみたので、メモります。

SQLiteのソースコードはこちらからダウンロードしました。記事執筆時点（2017-12-09）での最新は3.21.0です。
https://www.sqlite.org/download.html

![SQLite_src_download.png](https://qiita-image-store.s3.amazonaws.com/0/122210/00f68b90-b76d-6cc1-85ed-2f33ccf6a8a5.png)

`sqlite-amalgamation-3210000.zip`をダウンロードして、適当なディレクトリにコピーし、解凍します。

```
$ mkdir ~/work/sqlite
$ cd ~/work/sqlite
$ cp ~/Downloads/sqlite-amalgamation-3210000.zip .
$ unzip sqlite-amalgamation-3210000.zip
Archive:  sqlite-amalgamation-3210000.zip
   creating: sqlite-amalgamation-3210000/
  inflating: sqlite-amalgamation-3210000/sqlite3ext.h  
  inflating: sqlite-amalgamation-3210000/sqlite3.c  
  inflating: sqlite-amalgamation-3210000/sqlite3.h  
  inflating: sqlite-amalgamation-3210000/shell.c  
```
`sqlite3.c`、`shell.c`をコンパイルします。

```
$ cd sqlite-amalgamation-3210000
$ ls
shell.c sqlite3.c sqlite3.h sqlite3ext.h
$ gcc -o sqlite3 sqlite3.c shell.c
```

起動してみます。

```
$ ./sqlite3
SQLite version 3.21.0 2017-10-24 18:55:49
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> SELECT sqlite_version();
3.21.0
sqlite> 
```

バージョン3.21.0であることが確認できました。

## コマンドラインでの編集支援機能を追加

こうしてビルドしたsqlite3のCLIは、キーボードの左右キーでカーソル移動できません。

```
sqlite> ^[[D^[[C
```

左右キーを押すと上記のように文字が入力されてしまいます。

SQLiteのドキュメント [How To Compile SQLite](https://sqlite.org/howtocompile.html)によると、コンパイル時に以下のようにオプションを追加すると、コマンドラインの編集機能が追加されるとのこと。

```
gcc -o sqlite3 shell.c sqlite3.c -DHAVE_READLINE -lreadline -lncurses
```

実際やってみると、こうしてビルドしたCLIでは、左右キーでカーソルが移動できるのはもちろん、過去に実行したSQL文も上下キーでたどることができました。
Node.jsでgetchar

Node.jsでC言語のgetchar()マクロ(getc()関数)に相当するような、標準入力から1文字文字を読みとる処理を書くやりかた。NPMを使わずに手軽に直接できる方法を見つけられなかったため作成。仕様は以下のとおり。

- Promiseベース。以下で「〜を返す」は、「〜をPromiseのresolve値とするPromiseを返す」と読みかえてほしい。
- 呼ぶごとに標準入力から1文字ずつ取得したUnicodeのコードポイント値を返す。readlineから得たstringからcharCodeAtしているのでサロゲートペアは別に対処が必要。
- バッファにデータがなければブロッキングして入力を待つ(stdinがTTYの場合)。
- 行単位のバッファリングは行う。改行キーを押さない限りブロックは解除されない。
- バッファにデータが存在する限り、バッファから1文字を取り出し文字コードを返す。
- EOFでnullを返す。

```js
const readline = require('readline');
const rl  = readline.createInterface(process.stdin);
let buf = "";

function getchar() {
  if (buf.length == 0) {
    if (process.stdin.AtEndOfStream) {
      return Promise.resolve(null); // EOF
    }
    return new Promise((resolve, reject) => {
      rl.once('line', (line) => {
        buf = buf + line + "\n";
        resolve(getchar());
      });
    });
  } else {
    const result = buf.charCodeAt(0);
    buf = buf.substring(1);
    return Promise.resolve(result);
  }
}

async function test() {
  let ch
  while ((ch = await getchar()) !== null) {
    console.log(ch);
  }
}

test();

```
キャメルケースな文字列を単語に分割する。


キャメルケースな文字をスネークケースに変換する際に、
正規表現を利用して変換するコードがよく見かけますが、
ここではあえて正規表現を使わないで分割を考えることにします。
前提として変換する対象の文字列は英字の大文字小文字のみで構成されているものとします。

# 単語に分割するということ

ある半角英数からなる文字列を単語に分割するということは、
単語の区切りとなる判断材料が必要になってきます。
キャメルケースの定義を一言でいうとこんな感じでしょうか。

> キャメルケースとは、アルファベットで複合語やフレーズを表記する際、各単語や要素語の先頭の文字を大文字で表記する手法のことである。
> 
> 出展: [キャメルケースとは - IT用語辞典 Weblio辞書](https://www.weblio.jp/content/%E3%82%AD%E3%83%A3%E3%83%A1%E3%83%AB%E3%82%B1%E3%83%BC%E3%82%B9)

すなわち、小文字から大文字に切り替わった時に単語の区切りになるということになります。

# C#で実装する

以上のことを踏まえて、C#で実装する場合こんな感じになります。

```csharp
public static IEnumerable<string> ToWords(this string source)
{
     // 作業用変数の宣言           
     var wordbreakIndex = 0;          // 現在の単語の始まりのインデックス
     var currentWordLength = 0;       // 現在の単語の文字数
     var current = '\0';              // ループの中で現在参照している文字
     var isLowerBefore = false;       // 一つ前の文字が小文字だったかどうか
     var isUpperCurrent = false;      // 現在の文字が大文字かどうか

     for(var i = 0; i < source.Length; i++)
     {
         current = source[i];
         isUpperCurrent = char.IsUpper(current);

         if(isLowerBefore && isUpperCurrent)
         {
             // 小文字から大文字に切り替わった時に単語を切り出す。
             yield return source.Substring(wordbreakIndex, currentWordLength);
             wordbreakIndex = i;
             currentWordLength = 0;
         }

         currentWordLength++;
         isLowerBefore = char.IsLower(current);
     }

     // 最後の単語の返却漏れがないように
     yield return source.Substring(wordbreakIndex, source.Length - wordbreakIndex);
}
```

# 動作確認・パターンの追加をする

テストパターンが増えるに連れて、どんどんとデグレ検証が大変になるのでテストコードも記述しておきます。

```csharp:テストコード
[TestClass]
public class Splitter_ToWordShould
{
    [TestMethod]
    public void ReturnSplittedWord()
    {
        ReturnSplittedWordInternal("camelCase", "camel", "Case");
    }
    
    private void ReturnSplittedWordInternal(string source, params string[] expected)
    {
        // Arrange
        // Nothing to do...

        // Act
        IEnumerable<string> actual = source.ToWords();

        // Assert
        Assert.IsTrue(expected.SequenceEqual(actual));            
    }
}
```

テストが通ることを確認します。

余談ですが、テストコードを作成する際にDataTestMethodAttributeを利用して記述しようとしましたが、
paramsを利用するとどうも例外が発生して、解決に時間がかかりそうだったので、上記のようなテストコードになっています。
テストパターンを追加するにも`ReturnSplittedWordInternal`の呼び出しの箇所を追加すればいいだけになりますので。

テストパターンを追加します。

```diff:テストコード
[TestMethod]
public void ReturnSplittedWord()
{
     ReturnSplittedWordInternal("camelCase", "camel", "Case");
+    ReturnSplittedWordInternal("PascalCase", "Pascal", "Case");
}
```

追加してもテストが成功することを確認します。

# まとめ

このように、<del>コーディング量は正規表現を使うより遥かに多いですが、</del>割と簡単に実装することができます。
今回は簡単にするために入力される文字列が英字の大文字小文字のみとしましたが、 

* そのほかの文字の入力の追加。
    * 例えば数字やカンマ・アンダーバー・パイプ・空白などの区切り文字
* 特定の大文字で構成される単語が混じった場合の考慮
    * `MicrosoftSQLServer`のような文字列が入力された場合、  
       `Microsoft`・`SQL`・`Server`と分割できるように対応する

以上のような対応をすると、camelCaseからsnake_caseに変換できるようなメソッドが作れるようになります。
Mac > 右クリックでテキストファイル作成



# 右クリックでテキストファイル作成

Windowsで頻繁に使っていた、エクスプローラーで”右クリックでテキストファイルを作成”がMacでできないので、同等機能をMacに追加

2017/12現在、すでにXtraFinderはSierraでは使えない模様

<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/4591582e-f83d-8fb1-32d0-0ea1e8ba3213.png" width=300px />



# 参考

参考サイト
[Macで右クリックメニューからテキストファイルを作成できるようにする \- イワシのUnityブログ](http://iwashigame.hatenadiary.jp/entry/2015/07/17/104954)


# Automatorでサービス作成開始
Automatorを起動


<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/3b09cf3a-cedf-6f24-58e9-1f542a33f46b.png" width=300px />
新規書類を選択後、下の画面が表示される。
サービスをクリックし選択ボタンを押下。

<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/b8473b27-859b-161d-dca9-936e46bc1f43.png" width=300px />

右ペインに以下の画面が表示されるので、”次の選択項目を受け取る: ” をファイルまたはフォルダに変更

<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/41f350ad-add3-25f4-0c76-5d2dc0a812d2.png" width=500px />



### ユーティリティを選択
左側のライブラリ群からユーティリティを選択＞AppleScriptを実行を右側ペインにドラッグ＆ドロップ
<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/c159bea1-2cbc-28ce-04fb-a2b95eaf4be6.png" width=300px />

以下のコードをコピー＆ペーストして、ハンマーアイコンを押す

```
on run {input, parameters}
  tell application "Finder"
    set currentPath to insertion location as text
    set x to POSIX path of currentPath
  end tell
  return x
end run
```

### 変数の値を設定
左メニューのライブラリ->ユーティリティ->'変数の値を設定’ を右側の空白エリアにドラッグ＆ドロップ


’新規変数…’をダブルクリックして入力画面を表示し、’カレントフォルダ'と入力して完了ボタン押す

<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/a5888f07-9dd2-fa06-5675-9588b986bea7.png" width=300px />

画面下の変数ペインに追加される。

### 新規テキストファイル
左メニューのライブラリ->テキスト->'新規テキストファイル’ を右側へドラッグ＆ドロップ


<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/dccfa5d6-b8b9-e16a-41ed-cb84e272790d.png" width=300px />



<img src="https://qiita-image-store.s3.amazonaws.com/0/49910/f8234083-1dfd-fdd9-ef6f-62292472f238.png" width=300px />


## 最終形

最終的には以下のような画面になっている。

![Kobito.rwpJJ0.png](https://qiita-image-store.s3.amazonaws.com/0/49910/a93e8765-8997-4598-e613-88fa04105044.png "Kobito.rwpJJ0.png")


## 保存

ファイル->保存
右クリックテキストファイル作成　など適当な名前で保存する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/49910/98ab83a8-af16-e80a-d699-b29ff5e2763c.png)

## 使い方

フォルダを右クリック→サービス
に、右クリックテキストファイル作成が表示されます。

<img width="605" alt="スクリーンショット 2018-06-02 16.05.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/49910/a6f42fed-4105-6ffb-bbb3-d5a8f0ec9a46.png">
vue init webpack-simple からの最低限の設定

人に依って何が最低限か違うが・・・

`vue init webpack-simple some-project` で環境ができる。ただ公開するには追加の設定が必要なので書いておく

# html-webpack-plugin

ビルド後、自動的にバージョニングしたJSファイルを追加してくれる

```
yarn add -D html-webpack-plugin
```

# webpack.config.jsの設定

```js:webpack.config.js
var HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...
    
  plugins: [
    new HtmlWebpackPlugin({filename: 'assets/admin.html'})
  ]
}

if (process.env.NODE_ENV === 'production') {
  // ...
  module.exports.output.filename = 'build.[hash].js'
}
```

他にもあったら追加していく
[#Node-RED]インジェクトノードで定期処理 - ポーリングとバッチのヒント -

今回はインジェクトノードによる定期処理とそのヒントを説明します。

# インジェクトノード
インジェクトノードというのはNode-REDの最初のサンプルでほぼ間違いなく使われるノードです。左の四角い所を押すと現在時刻や文字列、JSONオブジェクトなど設定したデータがmsg.payloadにセットされて送信されます。
![スクリーンショット 2017-12-09 15.39.45.png](https://qiita-image-store.s3.amazonaws.com/0/147007/981fe0c8-42b9-ed8b-d43b-bebf2f3dbcb2.png)
インジェクトノードは多機能で、起動時にメッセージを送信して初期処理を実現できますし、「繰り返し」の設定で定期的にメッセージを送信してポーリング処理やバッチ処理を実現することもできます。「繰り返し」をセットすると、インジェクトノードに丸矢印が表示されます

# ポーリング処理とバッチ処理

ポーリング処理というのはデータ取得の方法です。センサーや通信装置などからデータが送られ無い場合、プログラムの側からデータを取りに行く必要がありますので、求められる時間間隔でポーリングし（取りにいき）ます。

バッチ処理というのは必ずしも定期処理ではなく、まとめ処理を実行するという意味です。UNIX系のcron処理やジョブスケジューラやタスクスケジューラなどと組み合わせて定期処理を実現されることも多いので、ここではバッチ処理と呼びます。

フロントエンドで受信したデータを蓄積し、バックエンドのバッチ処理で定期的にまとめて処理します。こうすることで同時処理を避けることができ、CPUやメモリなどのリソースを効率よく利用することができます。

# インジェクトノードによる定期処理
インジェクトノードの「繰り返し」では、以下の3種類（と「なし」）を設定できます。

## 指定した時間間隔
サーバやセンサから定期的にデータを取得したり、DBにあるデータを定期的に処理する場合に用います。秒、分、時間で指定できます。
![スクリーンショット 2017-12-09 13.55.28.png](https://qiita-image-store.s3.amazonaws.com/0/147007/18a4349b-72ce-accb-9417-2ec096e3b289.png)

## 指定した時間間隔、日時
曜日と時間帯を１時間単位に指定し、分単位で定期的に処理ができます。cronで実行されるので、あまり精度は期待できません。
![スクリーンショット 2017-12-09 13.57.13.png](https://qiita-image-store.s3.amazonaws.com/0/147007/d988be0a-6af5-f779-3b0a-7165b7d233e0.png)

## 指定した日時
曜日と時刻を分単位に指定し、定期的に処理ができます。cronで実行されるので、あまり精度は期待できません。
![スクリーンショット 2017-12-09 13.57.47.png](https://qiita-image-store.s3.amazonaws.com/0/147007/4b6d5d03-deab-e8c1-b99c-bb7783d59838.png)

# ヒント
## より短い間隔で実行する
例えば0.5秒ごとに実行したい場合は、インジェクトノードを１秒間間隔で指定し、出力を二股に分けて一方をディレイノードで500ミリ秒遅延させます。こうすると、メッセージが0.5秒ごとに送られる様になります。
![スクリーンショット 2017-12-09 15.36.16.png](https://qiita-image-store.s3.amazonaws.com/0/147007/ed1a01f9-c84a-23fc-35fd-e47dc3961a13.png)

片側に1ms、もう一方に501msのディレイを入れると一旦両方のディレイノードが実行されるので、 より精度が上がるでしょう。ただし、精度はそれなりですので、あまり細かくしたり、後続の処理が重かったりすると、うまく動かないので注意してください。

## 重複に注意
繰り返しの時間感覚よりも処理時間がかかると処理が重複しますので、注意してください。処理が重複すると、同じデータを2回処理してしまったり、メモリなどのリソースが不足する可能性があります。

## 別の方式も検討する
バッチ処理の場合、ディレイノードでキューイングする方法も検討してください。この場合、実行中のデータは保存されないので気をつけてください（バッチ処理でも蓄積する際に永続化しないなら同じです）。このほかにも、クラウドのサービスなどでもキューイングできるでしょう。

# まとめ
インジェクトノードによる定期処理とそのヒントを説明しました。IoT開発ツールとして以前から繰り返し実行ができましたが、最近はノードに繰り返しの表示が出る様になって、より使いやすくなりました。

Node-REDの面白いところは、シンプルな機能を組み合わせて色々なことが簡単にできる所だと思います。ぜひ、みなさんもインジェクトノードを使って色々と工夫してください。

# おまけ
標準のインジェクトノードでも工夫次第で様々な処理が可能ですが、bigtimerノードならより直感的な設定ができるようです。
golang echoを使い4行でhttps化

golangのWAFであるechoを使ってapiサーバーを書いていましたが
https化が恐ろしく簡単だったのでメモ。

こちらを参考に書きました。
https://echo.labstack.com/cookbook/auto-tls

裏側でLet’s Encrypt. と接続してhttps化を行ってくれます。
__ドメインは必要なので、ローカル環境では動きません。__

__sample__

```go:server.go
package main

import (
	"golang.org/x/crypto/acme/autocert"

	"os"

	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

func main() {
	e := echo.New()

	env := os.Getenv("ENV")
	if env == "prod" {
		e.AutoTLSManager.HostPolicy = autocert.HostWhitelist(os.Getenv("HOST"))
		e.AutoTLSManager.Cache = autocert.DirCache("/var/www/certs")
		e.Pre(middleware.HTTPSWWWRedirect())
	}
        
        //
        // <snip>
        //        

	switch env {
	case "prod":
		e.Logger.Fatal(e.StartAutoTLS(":443"))
	case "dev":
		defaultAddr := ":80"
		e.Logger.Fatal(e.Start(defaultAddr))
	default:
		defaultAddr := ":9000"
		e.Logger.Fatal(e.Start(defaultAddr))
	}
}
```

```go
e.AutoTLSManager.HostPolicy = autocert.HostWhitelist(os.Getenv("HOST"))
e.AutoTLSManager.Cache = autocert.DirCache("/var/www/certs")
e.Pre(middleware.HTTPSWWWRedirect())

// <snip>

e.Logger.Fatal(e.StartAutoTLS(":443"))
```

hostとキャッシュとリダイレクトの設定を行う。
そのあと443番でStartAutoTLS()を呼ぶ


僕は、dockerで管理しているので`docker-compose.yml`をこんな感じにして
環境変数をセットしています。

```yml:docker-compose.yml
version: '2.1'

services:
  go-19:
    build: <your-project>
    env_file:
      - ./.env
    volumes:
      - ./<your-project>:/go/src/<your-project>
      - ./<your-project>/certs:/var/www/certs
    command: ./<app-bin>
    ports:
      - "${HTTPS}:${HTTPS}"
      - "80:80"
    tty: true
```

```shell:.env
# Host's portforward settings
HTTPS=443

HOST=localhost
ENV=dev
```

__注意すること__

キャッシュの宣言をしないとビルドの度に
Let’s Encryptにリクエストを投げてしまうので
取得制限にひっかかります。(2017/11月現在、一週間に5回まで)

自分のドメインが何回リクエスト投げているか見るにはこちらで
https://crt.sh/

__sample__

![スクリーンショット 2017-12-09 16.01.30.png](https://qiita-image-store.s3.amazonaws.com/0/47896/31be2879-f27f-e51b-7f58-98bf0f31786a.png)
「強いエンジニアにHelloWorldさせてみた」をC++でやってみました。

#面白そうだったので
下記の記事をC++で私もやってみました。
強いエンジニアにHelloWorldさせてみた(縛りあり) https://qiita.com/imishinist/items/1883b5eef836aeee93ff

#ソース


```Cpp
#include	<cstdio>
#include	<iostream>
int main()
{

































































	char F = (char)__LINE__;


	char I = (char)__LINE__;


	char L = (char)__LINE__;








	char U = (char)__LINE__;

	std::cout << L << I << F << U << L << L << std::endl;

    return 0;
}
```
#結果
![無題.png](https://qiita-image-store.s3.amazonaws.com/0/214934/c17bba64-af9b-43ba-0bc3-fde0cfb1004d.png)

#以上
ラズパイのWiFi接続は結構苦労する【予告編】

さて、Raspberry PIを購入して早半年。
僕も初めて触った時に苦労したのが
**「WiFiの接続」**
でも今日はその設定手順ではなくて、苦労した時、参考になったLink集を投稿します。
# 参考URL
- http://junsumida.hatenablog.com/entry/2014/11/24/160839
- http://deviceplus.jp/hobby/raspberrypi_entry_042/
- https://qiita.com/tkyko13/items/1bc472ab777cc9375f06
- http://d.hatena.ne.jp/pasela/20121224/raspi_wlan
- http://d.hatena.ne.jp/dekovoko/20140509/1399610982
- https://watenoblog.blogspot.jp/2013/12/raspberry-pilan.html
- http://takuya-1st.hatenablog.jp/entry/2014/12/29/000000
- http://seitk.hatenadiary.jp/entry/2014/12/20/043605
これからのサーバーSSLの行く末を、中途半端にリアルガチで意見してみる



#はじめに
どうも、去年のAdventCalenderがQiita初投稿でしたが、今年のCalenderで２投稿目という、itamitoです。

まずは…ごめんなさい。
何に？

- 12/9までに記載しなければならない本記事、時間オーバーでした。かつ、中途半端で公開してます…
- 「Qiitaは、プログラミングに関する知識を記録・共有するためのサービス」を今知りました。本記事はプログラミングには関係しないかも。

と、謝っておきます。


さて…そんな中途半端な記事ですが…去年は証明書の選ぶときの一助…みたいな記事を投稿させていただいたので、なんとなく関連しているものとして、今年はCA/Browser forumの流れなどを起点に、証明書の世界の行く末を占う意見を載せたいと思います。（また、誰得な記事）

# CA/Blowser forumってなに？
あまり知らないですよね、かくいう自分もいろいろ仕様変更が乱発されるようになってから知りました。つぎの説明参照。
https://jp.globalsign.com/blog/2013/cabrowserforum.html
https://www.nic.ad.jp/ja/basics/terms/ca_browser_forum.html
（~~説明めんどくさい…~~いい説明があったので、紹介！）

一言でいうと、
・証明書にかかわる主要な会社(CAとブラウザベンダー)が、現在のトレンドやセキュリティ技術などをみて議論する場（仕様変更含む）
・CA自体を承認する場
ですね。

# 最近の議論と、その結果は？
詳しい人は良く知ってると思うんですけど、最近、CA/B発祥の証明書仕様変更が多いですね。
今年分だけでも…
　1.長期証明書の発行終了(Ballot193によるもの)
　　825日以上の有効期間をもつ、エンドエンティティ証明書の発行をしない
　　といったもの。もともとはBallot185で否決されたもの
　2.CAによるCAAレコードチェックの義務化
など、結構大きな変更が決められているようです。

ちなみにCA/Bでの決議採択は投票により決められるようなんですが、否決されたものでは次のようなものがあるようです。
　1.長期証明書の発行終了（Ballot193に引き継がれてます）
　2.SANsなどにアンダースコア文字を使えるようにするもの

最近(2013年ごろから？)は、ブラウザベンダーの力が強くなっているようで、議論の開始はブラウザベンダーからが多いように見受けられます。
CAたちに比べてブラウザベンダーの数が少ないので、投票の重みも大きいことで意見集約等がしにくいとかも一因としてはありそうです。
けど、本質的な部分では、CA陣営がいろんなミスを頻発させたことによるものが大きい気がします。

たとえば
 - ComodoやDiginotarがシステムを乗っ取られた事件
 - Wosign(Startcom)が不正な発行をしていた（サブドメインの管理権のみで発行できた)
 - Symanteが所有権のないドメインのテスト証明書を発行してた件
などなど…
~~Symantecさんもこのあたりの力関係に負けたのかな？~~

# 周辺は？
テスト証明書を不正に発行したせいで、mozilla.dev.securityなどで議論されて結局Digicertに買収される形になったSymantecの件は、ほかにも影響を及ぼしているようです。
Certificate Transparencyの仕様変更がらみでCTログサーバに登録が義務化された背景に、この証明書不正発行たちがあったようですし。

けど…Googleって、自分が自分のために認証局を運営し始めてるので…
http://www.itmedia.co.jp/enterprise/articles/1701/27/news058.html
これも結構グレーなんじゃないかと思うなぁ。rootはGlobalsignだけど。


# 今後のこのあたりの進む先…
ブラウザベンダーなどは、セキュリティ面を考慮して、期間の極端に短い証明書の発行を望んでいるようです。
この望みはわかる気がします。今後量子コンピュータのような計算がとても速くできる機構が生まれたとき、現在の２年物の証明書が発行されていた場合は解読された場合の影響が大きいので…。(再発行とか含めて)
ただ、個人的にはこれは、「ログインパスワードを定期的に変更しましょう」と同じ理屈で、リスクの軽減方法でしかないと思うので、意味としては薄そうに感じます。
ただ、管理の面からもあまりに長い有効期間の発行は良くないと思うので、いまよりも短縮されるでしょう。私見ですが、１年物よりも長いものは発行されなくなりそうだと、思います。

ここからはちょっと邪推かもしれませんが…
IoT機器を意識すると、小型コンピュータにファームウェアレベルで証明書を組み込むパターンが多くあると思います。
こういった場合に、あまり期間の短い証明書を発行されると、入れ替えが難しいために困りますよね。
そうするとIoTのメーカーは、そもそもCAを利用せず独自の仕組みを利用するようになるでしょうから、CAを使わなくなるのでは？と思います。
で…一種のCAが関与する部分の引きはがしを図っているようにも考えることができるかなと。

#最後に
だいぶ中途半端に意見を書いてきましたが、中には解釈の間違い等あると思います。
また、もうちょっと書きたいな～と思ってたこともあったのですが、時間切れで書けませんでした。またの機会に記事書きなおすかも…です。
つたない文章でしたが、読んでくださった方、ありがとうございました。
デザインパターン(1)：AbstractFactory

#AbstractFactoryとは
インスタンス生成を専門に行うクラス（Factory）を作成することで、
関連性のあるインスタンスを間違いなく生成するためのデザインパターンのこと。
つまりFactoryクラス毎に生成できるインスタンスが決められている実装のこと。

##手順①
関連性のあるクラスをを生成するクラス（=Factoryクラス）を作る。
**例）：TokyoとJapanese、WashingtonDCとEnglishが関連性がある。**

```java:Factory.java
public interface Factory {
	Capital getCapital();
	Language getLanguage();
}
```
```java:JapanFactory.java
// 日本のFactoryクラス
public class JapanFactory implements Factory {
	@Override
	public Capital getCapital() {
		return new Tokyo(); // 首都は東京
	}

	@Override
	public Language getLanguage() {
		return new Japanese(); // 言語は日本語
	}
}
```
```java:UsaFactory.java
// アメリカのFactoryクラス
public class UsaFactory implements Factory {
	@Override
	public Capital getCapital() {
		return new WashingtonDC(); //首都はワシントンDC
	}

	@Override
	public Language getLanguage() {
		return new English(); // 言語は英語
	}
}
```

##手順②
Factoryインタフェースで実装されている、メソッドの戻り値である抽象クラスを継承したクラスを作成する。
このクラスが各Factoryクラスで実際に返却されるクラスとなる。
**例）：Capitalクラスを継承したTokyoクラスや、WashingtonDCクラスが実際にFactoryクラスから返却される。**

```java:Capital.java
public abstract class Capital {
    //ここのフィールドは、AbstractFactoryの説明としては特に関係なし。
	protected String name;
	protected int population;
}
```
```java:Tokyo.java
public class Tokyo extends Capital {
	public Tokyo() {
		this.name = "東京";
		this.population = 13510000;
	}
}
```
```java:WashingtonDC.java
public class WashingtonDC extends Capital {
	public WashingtonDC() {
		this.name = "ワシントンD.C";
		this.population = 601723;
	}
}
```

##手順③
呼び出し側でFactoryクラスを生成する処理を実装する。このときFactoryクラスを切り替える分岐が必要になる。

```java:Main.java
public class Main {
	public static void main(String[] args) {
		String name = "Japan";
		Factory factory = createFactory(name);
		Capital capital = factory.getCapital();
		Language language = factory.getLanguage();
		System.out.println("首都名は" + capital.name);
		System.out.println("人口は" + capital.population);
	}
	
	private static Factory createFactory(String name) {
		switch (name) {
			case "Japan":
				return new JapanFactory();
			case "USA":
				return new UsaFactory();
			default:
				throw new IllegalArgumentException();
		}
	}
}
```

```java:実行結果
首都名は東京
人口は13510000
```

##メリット
Factoryクラス経由でインスタンスを生成することで、関連性を持ったインスタンスを安全に生成することができる。
**→JapanFactoryインスタンスを生成することで、必ずTokyoインスタンスとJapaneseインスタンスが生成できる。**
（明示的にインスタンスを生成すると誤った組み合わせでインスタンスを生成する恐れがある。）

また抽象クラスで戻り値を取得するため、呼び出し側でFactoryクラスの内部実装を気にする必要がない。
**→Tokyoクラスや、WashingtonDCクラスがどういった実装か知る必要がない。**
amazonka-dynamodbで接続先をローカルのDynamoDBにする

AmazonのDynamoDBを使って開発する際、AWS上のDynamoDBを使うのが王道だとは思うのですが、オフラインでは使えないという泣き所があります。
DynamoDBを選択した時点でオフライン開発を考慮しないといけないのが特殊なケースだとは思うのですが、私がよく使っている九州新幹線はLTEがあまり繋がらないんですよ・・・

で、AWSはローカルで動作するDynamoDBを提供してくれています。

http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DynamoDBLocal.html

さて一方、HaskellでAWSを扱うライブラリとしては[amazonka](https://hackage.haskell.org/package/amazonka)が便利です。

amazonkaのファミリーには[amazonka-dynamodb](https://hackage.haskell.org/package/amazonka-dynamodb)というものがあって、文字通りDynamoDBを扱うライブラリです。

前置きが長くなりましたが、amazonka-dynamodbを使う際にローカルのDynamoDBに接続する方法を紹介します。

## Network.AWS.Envの_envOverrideで接続先を切り替える

これだけ分かってしまえば解決なのですが、ただ

* _envOverrideは公開されておらずLensでアクセスしないといけない
* _envOverrideの型は ``` !Dual (Endo Service) ```　となっていてDualとかEndoとか知らなかったからビビった。

などの軽い罠があります。なんでDualやEndoが必要なのかは、正直理解できていないのですが、次のようなコードでローカルのDynamoDBに接続することが出来ます。

```hs
{-# LANGUAGE OverloadedStrings #-}
module Lib2 where

import           Control.Lens
import           Data.Monoid
import           Network.AWS

env :: IO Env
env = do
    e <- newEnv $ FromEnv "AWS_ACCESS_KEY" "AWS_SECRET_ACCESS_KEY" Nothing Nothing
    pure $ e&envOverride .~ localOverride

localOverride :: Dual (Endo Service)
localOverride = Dual $ Endo localService

localService :: Service -> Service
localService svc = svc { _svcEndpoint = \_ -> localEndpoint }

localEndpoint :: Endpoint
localEndpoint = Endpoint {
                  _endpointHost = "localhost"
                , _endpointSecure = False
                , _endpointPort = 8000
                , _endpointScope = ""
                }
```

以上です。
Kubernetesによる同一ポッド内コンテナ間のネットワーク通信

# 1.はじめに
前回、前々回では、コンテナ間通信の中でも共有ボリュームを介した通信、プロセス間通信について説明しました。今回は、コンテナ間のネットワーク通信を取り上げます。

#2. コンテナ間ネットワーク通信
同一Pod内のコンテナはローカルホストを介して通信することが可能です。この場合には同一ネットワークネームスペースを利用します。このとき、ホスト名はPod名と同一です。コンテナは同一IPアドレス・同一ポート空間を利用するので、入力ポートには異なるポート番号を割り当てます。つまり、Pod内のアプリケーションでポート番号が重複しないように調整します。
次の例では、リバースプロキシとして機能するNginx用コンテナと、ウェブアプリケーション用のコンテナから構成されるPodを作成します。
 
ステップ1：Nginxコンテナ用ConfigMapを作成します。コンテナ上のポート番号80番をローカルホスト上のポート5000番に変換します。

```
apiVersion: v1
kind: ConfigMap
metadata:
  name: mc3-nginx-conf
data:
  nginx.conf: |-
    user  nginx;
    worker_processes  1;

    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;

    events {
        worker_connections  1024;
    }

    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        sendfile        on;
        keepalive_timeout  65;

        upstream webapp {
            server 127.0.0.1:5000;
        }

        server {
            listen 80;

            location / {
                proxy_pass         http://webapp;
                proxy_redirect     off;
            }
        }
    }
 ```

ステップ2.　2つのコンテナから構成されるPodを作成します。Webアプリケーションとnginxをそれぞれ異なるコンテナを含みます。 Pod上では、nginxポート80のみ定義します。ポート5000ではPod外部からアクセスできません。
 
```
apiVersion: v1
kind: Pod
metadata:
  name: mc3
  labels:
    app: mc3
spec:
  containers:
  - name: webapp
    image: training/webapp
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
    volumeMounts:
    - name: nginx-proxy-config
      mountPath: /etc/nginx/nginx.conf
      subPath: nginx.conf
  volumes:
  - name: nginx-proxy-config
    configMap:
      name: mc3-nginx-conf
 ```

ステップ3　NodePortサービスを利用して、Podを公開します。

```
$ kubectl expose pod mc3 --type=NodePort --port=80
service "mc3" exposed
 
次のコマンドを使ってPodに転送するためのノード上のポートを特定します。
 
$ kubectl describe service mc3
...
NodePort:	<unset>	31418/TCP
…
 
```

これで、ブラウザ（もしくはcurlコマンド）上に以下のURLを入力すると、Nodeのポートにアクセスし、リバースプロキシ経由でWebアプリケーションにアクセスできます。
```
　　http：// myhost：31418
```
このHTTPリクエストは、Webアプリケーション用コンテナ”Webapp"のポート5000に転送されます。
![Network communication](https://cdn.mirantis.com/wp-content/uploads/2017/08/multicontainerwebapp.png)

上記の例では、同一Pod内にデプロイされた複数コンテナ間の通信方法を取り上げました。一方で、同一Pod内にデプロイされた複数のコンテナを外部に公開するために複数のポートを作成することはよくあることです。そのためには、次の2つの方法があります。1つ目の方法は、各サービス内部のプロセスを分割しプロセス毎にコンテナを作成し、それぞれのコンテナに対する公開ポートを作成する方法です。2つ目の方法は、1つのコンテナに対して複数の公開ポートを割りあてる方法です。

#3. 最後に
最終回は、コンテナ間のネットワーク通信と外部に公開ポートを作成する方法について説明しました。今回の連載を通じて、コンテナ・オーケストレーションツールKubernetesによって作成されるPodの定義とPod内に作成されるコンテナ間の通信方法として、共有ボリュームを介した通信、プロセス間通信、ネットワーク通信を取り上げました。
Kubernetetsに実際に触れてみて、Kubernetesの可能性を探ってみたくなった方は、ぜひ[Mirantisのトレーニング](https://www.mirantis.co.jp/training/)にご参加ください。

【参考資料】
Pavel Chekin (2017), “Multi-container pods and container communication in Kubernetes,” Mirantis Open Cloud Digest, https://www.mirantis.com/blog/multi-container-pods-and-container-communication-in-kubernetes/, Mirantis Inc.
Kubernetesによる同一Pod内コンテナのプロセス間通信

#1. はじめに
第1回では、KubernetesにおけるPodの定義にはじまり、複数コンテナから構成されるPodのユースケースの紹介に続き、コンテナ間通信の中でも共有ボリュームを介したコンテナ間通信について説明しました。今回は、コンテナ間通信の中でもプロセス間通信を取り上げます。

#2. プロセス間通信　
Pod内のコンテナは、IPC(IPC:Inter-process communications)ネームスペースを共有します。つまりシステムVセマフォやPOSIXシェアドライブラリなどの標準プロセス間通信を利用します。
次の例では、最初に同一Pod上の2つのコンテナを定義します。両方のコンテナに同じDockerイメージを使用します。最初のコンテナをプロデューサとします。標準Linuxメッセージキューを作成し、任意のメッセージを一定数書き込んだ後に、メッセージ終了を意味するExitメッセージを書き込みます。2番目のコンテナはコンシューマとします。プロデューサが作成したメッセージキューにアクセスし、キュー上のメッセージを読み込み、Exitメッセージを受信するまでメッセージを読み込みます。リスタートポリシーをNeverに設定するので、両コンテナが終了した時点でPodも終了します。以下の定義ファイルで2つのコンテナを単一Pod内に作成します。

```
apiVersion: v1
kind: Pod
metadata:
  name: mc2
spec:
  containers:
  - name: producer
    image: allingeek/ch6_ipc
    command: ["./ipc", "-producer"]
  - name: consumer
    image: allingeek/ch6_ipc
    command: ["./ipc", "-consumer"]
  restartPolicy: Never
```
以上の動作を確認するために、コマンド”kubectl create”を使ってPodを作成したのち、以下のコマンドでPodの状態を監視します。

```
$ kubectl get pods --show-all -w
NAME      READY     STATUS              RESTARTS  AGE
mc2       0/2       Pending             0         0s
mc2       0/2       ContainerCreating   0         0s
mc2       0/2       Completed           0         29
```

各コンテナのログを確認し、最初のコンテナであるプロデューサは、2番目のコンテナ コンシューマがExitを含む全メッセージを受信したことを確認します。

```
$ kubectl logs mc2 -c producer
...
Produced: f4
Produced: 1d
Produced: 9e
Produced: 27
$ kubectl logs mc2 -c consumer
...
Consumed: f4
Consumed: 1d
Consumed: 9e
Consumed: 27
Consumed: done
```
![IPC communication](https://cdn.mirantis.com/wp-content/uploads/2017/08/multicontainerpodproducerconsumer.png)

Pod内において、コンテナの起動する順序にも注意を払う必要があります。この状態では、Pod内のコンテナはすべて同時に起動されます。つまりコンテナの起動順序を決定することはできません。上記のIPCの例では、最初のコンテナ プロデューサを起動後、メッセージをキューに送信する前に、2番目のコンテナが終了してしまうかもしれません。先の例では、コンテナ プロデューサからのメッセージが既にキューに保存されていることが前提です。したがって、2番目のコンテナの起動が先に完了してしまうと、キューからのメッセージを読み込めない可能性があります。
Kubernetes Init Containersをはじめ、複数コンテナの起動順序を制御するための機能開発が現在進められています。一方でクラウド環境下においては、管理ができないことを前提として、事前に対応策を考えておいたほうが賢明です。メッセージキューが作成されるまで、アプリケーション側で待機するように修正するのも一つの対応策として考えられます。

#3. 最後に
今回は、プロセス間通信とコンテナの依存関係と起動順序に関する注意事項について記載しました。次回は、コンテナ間のネットワーク通信について説明します。
 Kubernetetsに実際に触れてみて、Kubernetesの可能性を探ってみたくなった方は、ぜひ[Mirantisのトレーニング](https://www.mirantis.co.jp/training/)にご参加ください。

【参考資料】
Pavel Chekin (2017), “Multi-container pods and container communication in Kubernetes,” Mirantis Open Cloud Digest, https://www.mirantis.com/blog/multi-container-pods-and-container-communication-in-kubernetes/, Mirantis Inc.
Modified-Euler法の精度

#はじめに
近似計算法であるModified-Euler法は、Euler法よりも近似精度が高いと言われています。今回は、その精度について確認していきます。
なお、ここでは微分方程式

```math
\dfrac{dx}{dt}=f(t_n,x_n)
```

の近似を行うとします。
#Euler法の精度
##Euler法
Euler法は次の式で表されます。

```math
x_{n+1} = x_n + h f(t_n,x_n)
```

##Euler法の精度
まず、時間発展の出発時刻$t_0=0$とし、$^\forall n\in\\{0,1,2,\cdots\\}$に対して$t_n-t_{n-1}=h$としましょう。このとき、

```math
t_n-t_{n-1}=h\\
t_{n-1}-t_{n-2}=h\\
\vdots\\
t_{1}-t_{0}=h\\
```

ですから、両辺足して

```math
t_n-t_0=nh
```

ここで、$t_0=0$から

```math
t_n=nh
```

が成立することに注意しておきます。
さて、$x(t_{n+1})$について、$t_n$点を中心にTaylor展開すると

```math
x(t_{n+1}) = x(t_n) + x'(t_n)(t_{n+1}-t_n)+O(h^2)
```

ここで、$x(t_{n})=x_n,\quad x'(t_n)=f(t_n,x_n)$とすると

```math
x_{n+1}=x_n+hf(t_n,x_n)+O(h^2)
```

となります。すなわち、Euler法の局所誤差は$h^2$程度となります。
毎回の計算で生じうる誤差、**局所誤差**に対し、Euler法で計算を繰り返してプログラムの実行が完了した時点で、蓄積された誤差は$t_n=nh$で表現されることから

```math
(誤差)\sim (局所誤差)\times n = O(h^2)\times \dfrac{t_n}{h}=O(h)
```

となります。つまり、Euler法を実行して計算した結果に含まれる誤差は$h$程度ということになります。
#Modified-Euler法の精度
##Modified-Euler法
Modified-Euler法は次の式で表現されます。

```math
x_{n+1}=x_n+\dfrac{h}{2}\{f(t_n,x_n)+f(t_{n+1},x_n+hf(t_n,x_n))\}
```

##Modified-Euler法の精度
まず、

```math
\left\{\begin{array}{rl}
k_1 &= hf(t_n,x_n)\\
k_2 &= hf(t_{n+1},x_n+k_1)\\
x_{n+1}&=x_n+\dfrac{1}{2}(k_1+k_2)
\end{array}\right.
```

とする。$k_2$について$(t_n,x_n)$を中心にTaylor展開すると

```math
\begin{align*}
k_2&=h\{f(t_n,x_n)+f_t(t_n,x_n)(t_{n+1}-t_n)+f_x(t_n,x_n)(x_{n+1}-x_n)+O(h^2)\}\\
&=hf(t_n,x_t)+h^2f_t(t_n,x_n)+hf_x(t_n,x_n)k_1+O(h^3)\\
&=hf(t_n,x_t)+h^2\{f_t(t_n,x_n)+f_x(t_n,x_n)f(t_n,x_n)\}+O(h^3)\\
&=h\dfrac{dx}{dt}+h^2\left\{\dfrac{\partial f}{\partial t}+\dfrac{\partial f}{\partial x}f\right\}+O(h^3)\\
&=h\dfrac{dx}{dt}+h^2\dfrac{d^2x}{dt^2}+O(h^3)
\end{align*}
```

となる。ただし、途中で$t_{n+1}-t_n=h$やEuler法$x_{n+1}=x_n+k_1$を用いている。
さて、この結果を用いると

```math
\begin{align*}
x_{n+1}&=x_n+\dfrac{1}{2}\{(k_1+k_2)\}\\
&=x_n+\dfrac{1}{2}\left\{hf(t_n,x_n)+hf(t_n,x_n)+h^2f'(t_n,x_n)+O(h^3)\right\}\\
&=x_n+hf(t_n,x_n)+h^2f'(t_n,x_n)+O(h^3)
\end{align*}
```

となります。すなわち、Modified-Euler法の局所誤差はどんな$h^3$程度となります。
Euler法のときと同様に蓄積される誤差を計算すると

```math
(誤差) = (局所誤差) \times n = O(h^3)\times \dfrac{t_n}{h}=O(h^2)
```

となります。すなわち、Modified-Euler法で計算を実行した際に含まれる誤差は$h^2$程度となります。
#まとめ
＊Euler法の近似誤差はh程度
＊Modified-Euler法の近似誤差はh^2程度