OmniAICreator/Qiita-1.07M huggingface dataset:
Content-Security-Policyの概要メモ

# Content Security Policy(CSP)
## 概要
- GoogleTagManagerのカスタムHTMLタグ、カスタムJavaScript変数を制限するために調べた時のメモ。
 
## 基本仕様
- ホワイトリストを使用して許可する対象をクライアント（ブラウザなど）に指示する。
    - ホワイトリストに設定されたリソースだけ実行およびレンダリングさせることができる。
- ホワイトリストはディレクティブで設定する
- デフォルトでインラインコードとeval()は有害とみなす
    - 'unsafe-inline' もしくは 'unsafe-eval'で明示的に有効化する必要がある

## 設定方法
- HTTPヘッダー

```
Content-Security-Policy: [ディレクティブ] [オリジン] [オリジン]; [ディレクティブ] [オリジン] [オリジン]; ...
```
- metaタグ

```HTML
<meta http-equiv="Content-Security-Policy" content="[ディレクティブ] [オリジン] [オリジン]; [ディレクティブ] [オリジン] [オリジン]; ...">
```

## ディレクティブの書き方例

```
script-src https://host1.com https://host2.com;
```

## オリジンの指定方法

| 名称 | 例 |
| --- | --- | 
| スキーム | data:, https: | 
| ホスト名 | `example.com` | 
| 完全修飾URI | `https://example.com:443` | 
| ワイルドカード | `*://*.example.com:*`<br>スキーム、ポート、ホスト名の一番左端のみに限定 |

## オリジンに指定できるキーワード
- これらのキーワードにはシングルクォーテーションが必要

| キーワード | 説明 |
| --- | --- |
| 'none' | 何も一致しない = 全て無効化 |
| 'self' | 現在のオリジンと一致する<br>サブドメインは除外 |
| 'unsafe-inline' | インラインJavaScriptおよびCSSを許可する |
| 'unsafe-eval' | evalなどのtext-to-JavaScriptの仕組みを許可する |

## ディレクティブについて

| ディレクティブ | 説明 |
| --- | --- |
| script-src | スクリプト関連の権限を制限する |
| base-uri | `<base>`要素に表示できるURLを制限する |
| child-src | ワーカーと組み込みのフレームコンテンツのURLを制限する |
| connect-src | XHR, WebSockets, EventSourceを経由して接続できるオリジンを制限する |
| font-src |  ウェブフォントを配信できるオリジンを制限する |
| form-action | `<form>`タグからの送信の有効なエンドポイントを制限する |
| frame-ancestors | 現在のページに組み込める参照元を制限する<br>`<frame>`,`<iframe>`,`<embed>`,`<applet>`タグに適用される |
| img-src | 画像を読み込み可能なオリジンを制限する |
| media-src | 動画と音声を配信できるオリジンを制限する |
| object-src | Flashなどのプラグインの種類を制限する |
| plugin-types | ページで起動できるプラグインの種類を制限する |
| report-uri | コンテンツセキュリティポリシーが違反された時にレポートを送信するURLを指定する |
| style-src | スタイルシートのscript-srcに相当する |
| upgrade-insecure-requests | ユーザーエージェントに支持してURLスキーマを書き直し、HTTPをHTTPSに変更する |
| default-src | 未指定の`-src`ディレクティブの大半に対してデフォルトを定義する |

## デフォルト
- デフォルトではディレクティブ に制限はない
- default-srcを設定することで、自動的に`-src`で終わるディレクティブがdefault-srcのオリジンに設定される

## 実装の詳細
- 使用するヘッダーによらずポリシーは`ページごとに定義される`

## インラインコードは有害とみなす
1. 以下の2つだけではインラインスクリプトの注入に対処できない
   - CSPは明確にホワイトリストに登録されたオリジンに基づいている
   - 特定のリソースだけ受け入れてそれ以外を拒否する

2. 以下を含むインラインスクリプトを完全に禁止する
    - インラインイベントハンドラ

    ```HTML
    <a onclick="[JAVASCRIPT]">
    ```
    - javascript: URL

3. 適切な`addEventListener()`に置き換える必要がある
4. どうしてもインラインスクリプトを使用したい場合はオリジンに`'unsafe-inline'`を指定する

    ```
    script-src 'unsafe-inline';
    ```

## CSP1の対応状況
- IE10でのサポートはかなり制限されている
    - http://caniuse.com/#feat=contentsecuritypolicy

## CSP2でのみ使用できるオリジン指定
- nonce
    - 暗号化された値を用意し、CSPとscriptタグに設定する

```
// CSPの設定
script-src 'nonce-1234567890'
```
```HTML

<!--  HTMLの設定 -->
<script nonce="1234567890" >
    alert('Hello');
</script>
```

## 参照
[コンテンツ セキュリティ ポリシー](https://developers.google.com/web/fundamentals/security/csp/?hl=ja)
LinuxデスクトップPCをセットアップ（備忘録）

休日イベント用にノートPCが必要になった。
でも新たにPCを買うお金はない。
じゃあHDDだけ買って、筐体は既存のを使いまわせばいいじゃん！
ということで。

##Linuxのセットアップ
centos7を使った。なんでもいい。一番慣れてるからという理由だけ。
セットアップ画面でセットアップ形式に「GNOMEデスクトップ」を選択する以外はデフォ。

##設定
GNOMEにログインした後の設定。

アプリケーション→システムツール→ソフトウェアの更新でパッチあて。

##Chromeのインストール。
####GoogleのYUMリポジトリ追加
GoogleのYUMリポジトリをCentOS7に追加。
/etc/yum.repos.d/google-chrome.repoを以下の様な内容で新規に作成

```google-chrome.repo
[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
```

追加後UPDATEします

```shell-session
$ sudo yum update
```

##Google Chromeのインストール
以下のコマンドを実行するだけ

```shell-session
$ sudo yum install google-chrome-stable
```

日本語設定
アプリケーション→システムツール→設定
で「地域と言語」を選択、入力ソースに”日本語（かな漢字）”を追加。
Windowsマーク＋スペースキーで入力モード変更可能。
AndroidでFirebaseとGoogle Analyticsのgoogle_service.jsonを共存させる

Google Analytics（GA）をすでに入れているアプリで
Firebaseでイベントを取るために設定したのがGAが動かなくなったため
google_service.jsonを何処を変更したかのメモです

Firebaseから取得したgoogle_service.jsonをベースとして使います。
（中身は消してます）

```google_service.json
{
  "project_info": {
  },
  "client": [
    {
      "client_info": {
        "android_client_info": {
        }
      },
      "oauth_client": [
        {
          "android_info": {
          }
        },
        {
        }
      ],
      "api_key": [
        {
        }
      ],
      "services": {
        "analytics_service": {
          "status": 1
        },
        "appinvite_service": {
          "other_platform_oauth_client": [
            {
            },
            {
              "ios_info": {
              }
            }
          ]
        },
        "ads_service": {
        }
      }
    }
  ],
  "configuration_version": "1"
}
```

GAから取得していた下記のgoogle_service.jsonを上のファイルで上書きするとGAは動かないので

```google_service.json
{
  "project_info": {
  },
  "client": [
    {
      "client_info": {
        }
      },
      "oauth_client": [],
      "api_key": [
        {
        }
      ],
      "services": {
        "analytics_service": {
          "status": 2,
          "analytics_property": {
            "tracking_id": "UA-11111111-1"
          }
        },
        "appinvite_service": {
        },
        "ads_service": {
        }
      }
    }
  ],
  "configuration_version": "1"
}
```

ここだけメモっておく。

```json
        "analytics_service": {
          "status": 2,
          "analytics_property": {
            "tracking_id": "UA-11111111-1"
          }
        },
```

Firebaseから取得したgoogle_service.jsonの下記の箇所に上書きするだけ。

```json
        "analytics_service": {
          "status": 1
        },
```
API Gateway のエンドポイントを nginx で reverse proxy したら"SSL_do_handshake() failed" と言われた

元ネタ： [Nginx reverse proxy error:14077438:SSL SSL_do_handshake() failed - Stack Overflow](https://stackoverflow.com/questions/38931468/nginx-reverse-proxy-error14077438ssl-ssl-do-handshake-failed/38957403)

`proxy_pass` の対象となるエンドポイントが SNI を使用している場合発生するっぽい（API Gateway がデフォルトで用意するエンドポイントは SNI 使ってるっぽい）

以下のように `proxy_ssl_server_name on` の設定を追加してあげたらOK

```
location /api/ {
  proxy_pass https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Dev/api/;
  proxy_ssl_server_name on;
}
```
Substance PainterでUnity LWRP用の出力プリセットを作ってみた

# Substance Painter 2018の出力プリセットについて
最近の物理ベースマテリアル用素材作成に欠かせない**Substance Painter**には、様々な環境に向けた出力プリセットがあります。
もちろんUnity向けのプリセットも複数ありますが、リストを確認すると、
**・Unity4
・Unity5(Standerd Metallic)
・Unity5(Standerd Specular)
・Unity HD Render Pipeline**
となっており、HD Render Pipelineと同時に扱えるようになった**LW Render Pipeline**向けのプリセットはありません。しかしSubstance Painterでは簡単にこの出力プリセットを作ったり追加する事が出来るので、LWRP用のプリセットを作ってみました。

出力プリセットは以下のファイルを特定のフォルダに加える事で誰でも使ってもらえます。**出力設定の共有**で手順をご確認後、自己責任にてご使用ください。
[**Unity LW Render Pipeline(Physically Based).spexp**](https://drive.google.com/open?id=1Hsu4NdV5BoPfHCg1CdIsteMhyHjw_Zpf)

#出力設定の作成
とはいってもLWRP向けの出力はとてもシンプルで、**Unity5(Standerd Metallic)**に**Ambient Occlusion**を追加するだけです。
**Export Textures**ウィンドウの**CONFIGURATIONタブ**でUnity5(Standerd Metallic)のプリセットを複製し、名前を変更した後にAmbient Occlusionの出力を追加します。
![SP_00.jpg](https://qiita-image-store.s3.amazonaws.com/0/230036/b24c4b1a-2bed-cbde-a462-c820620b87dd.jpeg)

設定を追加すると、**エクスポートタブ**からLWRP用の設定が選べるようになり、AOマップを含めたイメージ群を出力できるようになります。
![SP_01.jpg](https://qiita-image-store.s3.amazonaws.com/0/230036/bd719ca8-2e38-ca29-c265-2b36033f9f2b.jpeg)

#出力設定の共有
SubstancePainterでユーザーが追加した出力プリセットは個別のファイル(拡張子.spexp)として以下フォルダに保存されます。

**C:\Users\ユーザー\Documents\Allegorithmic\Substance Painter\shelf\export-presets**

作成した設定ファイルを、他ユーザーの同フォルダに入れる事で、プリセットを共有する事が出来ます。

#まとめ
このようにSubstance Painterではとても手軽にプリセットを追加できるのでわざわざファイルを配布する必要もないかと思いましたが、大勢のLWRPユーザーが個別に作るのもどうかと思い配布する事にしました。
またSubstance Painter2018.3.3(2019/03/03リリース)時点ではLWRPのプリセットはありませんが、今後公式のプリセットやもっと便利な出力方法なども搭載されるかもしれません。
その際は設定ファイルを削除して頂き、公式のものをご使用頂ければと思います。
ABC - 049- A&B&C

#AtCoder ABC 049 A&B&C
[AtCoder - 049](https://atcoder.jp/contests/abc049)

#A問題

```java
	private void solveA() {

		final Set<Character> wl = new HashSet<Character>();
		wl.add('a');
		wl.add('i');
		wl.add('u');
		wl.add('e');
		wl.add('o');

		char numN = next().charAt(0);

		out.println(wl.contains(numN) ? "vowel" : "consonant");
	}
```

#B問題

 - 同じ文字列を二回append

```java
	private void solveB() {
		int numH = nextInt();
		int numW = nextInt();

		char[][] wk = IntStream.range(0, numH).collect(() -> new char[numH][numW],
				(t, i) -> {
					t[i] = next().toCharArray();
				},
				(t, u) -> {
					Stream.concat(Arrays.stream(t), Arrays.stream(u));
				});

		StringBuilder builder = new StringBuilder();
		for (char[] cs : wk) {
			for (int j = 0; j < 2; j++) {
				builder.append(cs);
				builder.append(System.lineSeparator());
			}
		}
		out.println(builder.toString());
	}
```

#C問題

 - 4種類の文字を空文字に置き換えていって、置き換え切れたらOK
    - 4種類の文字を後ろに足していって　＝　4種類の文字しか使われていない
 - 置換する際誤判定が起きないよう、元の文字列及び4種類の文字を逆順にして判定を行う
    - 問題どおりの文字列を順序を考えずに置換しようとすると以下の可能性がある
        - `esaremaerd` を `remaerd` で置き換えて `esa` となる


```java
	private void solveC() {

		StringBuilder dream = new StringBuilder("dream");
		StringBuilder dreamer = new StringBuilder("dreamer");
		StringBuilder erase = new StringBuilder("erase");
		StringBuilder eraser = new StringBuilder("eraser");

		String wk = new StringBuilder(next()).reverse().toString()
				.replace(eraser.reverse().toString(), "")
				.replace(erase.reverse().toString(), "")
				.replace(dreamer.reverse().toString(), "")
				.replace(dream.reverse().toString(), "");

		if (wk.equals("")) {
			out.println("YES");
		} else {
			out.println("NO");
		}

	}
```
ABC - 048- A&B&C

#AtCoder ABC 048 A&B&C
[AtCoder - 048](https://atcoder.jp/contests/abc048)

#A問題

 - それぞれの文字の頭を連結

```java
	private void solveA() {
		String res = next().substring(0, 1) + next().substring(0, 1) + next().substring(0, 1);

		out.println(res);
	}
```

#B問題

 - {$Bで該当する値 - (A-1)で該当する値$} で求める
 - {$a=0$}の時、0も対象に入れるので注意

```java
	private void solveB() {
		long numA = nextLong();
		long numB = nextLong();
		long numX = nextLong();

		//		long max1 = numB % numX;
		//		long res1 = (numB - max1) / numX;
		long res1 = numB / numX;

		if (numA == 0) {
			out.println(res1 + 1);
		} else {
			//			long max2 = (numA - 1) % numX;
			//			long res2 = ((numA - 1) - max2) / numX;
			long res2 = (numA - 1) / numX;
			out.println(res1 - res2);
		}

	}
```

#C問題

 - とりあえず、$a_0$を基準とする（基準値決めないと何も出来ない）
 1. $a_0 + a_1 \leqq x $　とするために必要な数値が操作回数
    - 操作した結果を$a_1$に反映
    - $a_1$で吸収しきれない($a_1 < 0$となる)のであれば、溢れた分を$a_0$に転嫁
 2. 1を$a_N$まで順に繰り返せば均される

```java
	private void solveC() {
		int numN = nextInt();
		long numX = nextInt();
		long[] wk = new long[numN];
		long cnt = 0;
		for (int i = 0; i < numN; i++) {
			wk[i] = nextInt();
			if (i != 0) {
				if (wk[i] + wk[i - 1] > numX) {
					long diff = (wk[i] + wk[i - 1]) - numX;
					/*
					 * diffをwk[i]から引いたらマイナスの可能性がある
					 * numX=100
					 * wk[i]=10,wk[i-1]=99
					 */
					if (diff <= wk[i]) {
						wk[i] = wk[i] - diff;
					} else {
						/*
						 * wk[i]は0
						 * wk[i+1]に差分を転嫁する事は出来ないが、wk[i-1]に転嫁することはできる
						 * wk[i-1]に転嫁してもwk[i-2]+wk[i-1]がXを上回ることはないため
						 */
						wk[i] = 0;
						wk[i - 1] = wk[i - 1] - (diff - wk[i]);
					}
					cnt += diff;
				}
			}
		}

		out.println(cnt);
	}
```
ABC - 047- A&B&C

#AtCoder ABC 047 A&B&C
[AtCoder - 047](https://atcoder.jp/contests/abc047)

**2019/05/27**
　問題名修正
　B問題のコードの書き方を修正 ``int[][]の生成部分``

#A - キャンディーと2人の子供 / Fighting over Candies

 - {$A=B,B=C,C=A$}が成り立つかを判定

```java
	private void solveA() {
		int numA = nextInt();
		int numB = nextInt();
		int numC = nextInt();

		if (numA + numB == numC || numB + numC == numA || numA + numC == numB) {
			out.println("Yes");
		} else {
			out.println("No");
		}
	}
```

#B - すぬけ君の塗り絵 2 イージー / Snuke's Coloring 2 (ABC Edit)
コードが無駄に長いが、、、

 - 白いエリアのサイズは最初　$左下=(0,0),右下=(x,y)$　
 - 条件にしたがって、左下と右下の値を変化させていく

```java
	private void solveB() {
		int numW = nextInt();
		int numH = nextInt();
		int numN = nextInt();

		int[][] wk = Stream.generate(() -> new int[] { nextInt(), nextInt(), nextInt() }).limit(numN)
				.toArray(int[][]::new);
		//		int[][] wk = IntStream.range(0, numN).collect(() -> new int[numN][3],
		//				(t, i) -> {
		//					t[i][0] = nextInt();
		//					t[i][1] = nextInt();
		//					t[i][2] = nextInt();
		//				},
		//				(t, u) -> {
		//					Stream.concat(Arrays.stream(t), Arrays.stream(u));
		//				});

		final int[][] area = new int[][] { { 0, 0 }, { numW, numH } };

		for (int[] js : wk) {
			switch (js[2]) {
			case 1:
				if (area[0][0] < js[0]) {
					area[0][0] = js[0];
				}
				break;
			case 2:
				if (area[1][0] > js[0]) {
					area[1][0] = js[0];
				}
				break;
			case 3:
				if (area[0][1] < js[1]) {
					area[0][1] = js[1];
				}
				break;
			case 4:
				if (area[1][1] > js[1]) {
					area[1][1] = js[1];
				}
				break;

			default:
				break;
			}

		}

		/*
		 * 計算していった結果、(起点x,起点y),(終点x,終点y)の位置が逆転しているときがある
		 * 入力値例：
		 * 5 4 2
		 * 3 1 1
		 * 2 1 3
		 */
		int x = area[1][0] - area[0][0] > 0 ? area[1][0] - area[0][0] : 0;
		int y = area[1][1] - area[0][1] > 0 ? area[1][1] - area[0][1] : 0;
		int res = x * y;
		out.println(res);
	}
```

#C - 一次元リバーシ / 1D Reversi

動きは以下の様になる。

|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|start|W|B|W|B|W|B|W|B|
|1|W|B|W|B|W|B|W|W|W|
|2|W|B|W|B|W|B|B|B|B|B|
|3|W|B|W|B|W|W|W|W|W|W|W
|4|W|B|W|B|B|B|B|B|B|B|B|B
|5|W|B|W|W|W|W|W|W|W|W|W|W|W
|6|W|B|B|B|B|B|B|B|B|B|B|B|B|B
|7|W|W|W|W|W|W|W|W|W|W|W|W|W|W|W

 - WとBが変る場所を数えればよい

```java
	private void solveC() {
		char[] board = next().toCharArray();

		long count = 0;
		/*
		 * WとBのギャップ区間のみ数えればよい
		 */
		for (int i = 1; i < board.length; i++) {
			if (board[i] != board[i - 1]) {
				count++;
			}
		}

		out.println(count);
	}
```
Raspberry Pi 3 Model B+ でオンラインミーティング

# Raspberry Pi 3 Model B+ でオンラインミーティング

## 概要

Raspberry Pi 2 Model B+ではCPUのパワー不足でオンラインミーティングのコマ落ちが多く、実用に耐えなかったため機材を2世代繰り上げての再試験。

## 使用機材

- Raspberry Pi 3 Model B+
  - RS版

## OS

- Raspbian
  - Raspbian Stretch with desktop and recommended software
    - Version : November 2018
  - Raspbian Stretch with desktop
    - Version : November 2018
  - Raspbian Stretch Lite
    - Version : November 2018
- Ubuntu
  - Ubuntu MATE for the Raspberry Pi Model B 2, 3 and 3+
    - 16.04.2(32bit)
    - 18.04.2(32bit)
    - 18.04.2(64bit)


## 試験対象としたオンラインミーティングサービス

- [apper.in](https://appear.in/user)
- [1meeting.net](https://1meeting.net/)

## 試験結果

### Raspbian Stretch with desktop and recommended software
||appear.in|1meeting.net|
|---|---|---
|Chromium|NG|NG|
|Firefox ESR|カメラのみ反応|NG|


### Raspbian Stretch with desktop
||appear.in|1meeting.net|
|---|---|---
|Chromium|NG|NG|
|Firefox ESR|カメラのみ反応|NG|

### Raspbian Stretch Lite

xwindowが標準で入っていないためパス

### Raspbian Stretch with desktop
||appear.in|1meeting.net|
|---|---|---
|Chromium|NG|NG|
|Firefox ESR|カメラのみ反応|NG|


### Ubuntu Mate 32bit 16.04.2

OSが起動しなかったためパス

### Ubuntu Mate 32bit 18.04.2
||appear.in|1meeting.net|
|---|---|---
|Chromium|OK(遅延あり)|OK(遅延あり)|
|Firefox|OK|OK|

### Ubuntu Mate 64bit 18.04.2
||appear.in|1meeting.net|
|---|---|---
|Chromium|音声のみ(カメラはNG)|音声のみ(カメラはNG)|
|Firefox|音声のみ(カメラはNG)|音声のみ(カメラはNG)|


## 結論

Raspberry Pi 3 Model B+をオンラインミーティング用の機材にする場合、Ubuntu Mate 32bitの18.04.2で、Firefoxを利用するのがよい。
#python でカンマ区切りの文字列を split して tuple を作る例

```py
>>> tuple(filter(None, 'a,b,c'.split(',')))
('a', 'b', 'c')
```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1073








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【メモ】要素が持つ子要素のindex番号を取得する

JQueryだと簡単なのにね！

```haml
%ul{onclick: 'edf5(event)'}
  %li パンドラ
  %li セイレーン
  %li エピメテウス
```

```javascript
function edf5(e) {
  console.log(Array.prototype.indexOf.call(e.target.parentNode.querySelectorAll("li"), e.target));
};
```
#python で複数の候補から startswidh endwitds を判定をする例

配列ではなくこんな書き方をするらしい。なにこれと思ったpython初心者だった。


```py
>>> "orange".startswith(("a","b","c"))
False
>>> "banana".startswith(("a","b","c"))
True
>>>
```

```py
>>> "orange".endswith(("a","b","c"))
False
>>> "banana".endswith(("a","b","c"))
True
```

# tuple というものらしい？

```
>>> type(('a', 'b', 'c'))
<class 'tuple'>
```

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1071








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[Java][Spring][thymeleaf]自作Dialectのメソッドにnullが渡されてもエラーにならないようにする

## 前提
* SpringのプロジェクトでViewテンプレートにthymeleafを使っている
* 自作のDialectクラスを作っている

## 現象
* 作成したDialectのメソッドの引数にNULLが渡されるとエラーになる
* Spring 5 からの SpEL における null-safety な仕組みが原因らしい
  * https://macchinetta.github.io/server-guideline-thymeleaf/current/ja/ArchitectureInDetail/WebApplicationDetail/Thymeleaf.html#thymeleafoverviewnullsafetyatspel

### サンプルクラス
```
public class MyDialect {
  public String sampleMethod(Integer number) {
    if (number == null) {
      return "nullだよ";
    }
    return number + "だよ";
  }
}
```

↓
一見、NULLが来ても問題ないように感じられるが、実際にthymeleafから `
<th:block th:text="${#myDialect.sampleMethod(null)}"></th:block>` 
が呼ばれると、処理がそこに到達する前に IllegalStateException エラーとなる。

自作したDialectクラスのメソッドでは引数にNULLが来る場合は例外エラーとなる。


## 回避方法
* null になる可能性のある引数に final をつける
  * 受け取った引数の値の変更はできなくなる
* null の場合の処理を実装する

```
public class MyDialect {
  public String sampleMethod(final Integer number) {
    if (number == null) {
      return "nullだよ";
    }
    return number + "だよ";
  }
}
```
postfixでバーチャルドメイン設定をせず複数ドメインのメールを受信

# ノリで新規ドメイン取得。さてメールは？
ある日、某レジストラからのメールで「.xyzなら1円」とかメールが来た。
これ1年後に更新すると2,000-3,000円くらい（うろ覚え）かかるやつだ。でも1年だけ使い捨てにするなら本当に1円で済んじゃう。よし、取ろう。

さて、DNSに登録してnginxにバーチャルホスト設定をして・・
ん、まてよ。メールはどうする？

# postfixで複数ドメインのメールを受信する
環境はさくらVPS上のCentOS7にyumで入れて随時updateしているpostfix。さぁ料理だ。
## ふたつの方法
さてpostfixで複数ドメインのメールを受信する方法はふたつある。

- (a) virtual_alias_domainsを使う（バーチャルドメイン）
- (b) mydestinationに複数ドメイン書く（単にあっちもこっちも受信）

(a)の方法は異なるドメインで同じユーザー名同士を別のユーザーとして扱いたい場合に有効だ。
たとえば shimano@example.jp とshimano@example.xyz が別のユーザーでありたい場合。

しかしこの場合は単に遊びで運用しているサーバーの遊びで取ったドメイン。ぜーんぶ受け取るのは私でありたい。
なのでここは(b)の方法で行く。

## 設定
ここで例示として従来から持ってるドメインを「example.jp」、新しく取ったドメインを「example.xyz」とする。
設定内容は単にmydestinationに付け足すだけ。

```:console
[root@example ~]# cd /etc/postfix/
[root@example postfix]# cp -p main.cf main.cf.20190404bak
[root@example postfix]# vi main.cf
[root@example postfix]# diff main.cf main.cf.20190404bak
164c164
< mydestination = $myhostname, localhost.$mydomain, localhost, example.xyz
---
> mydestination = $myhostname, localhost.$mydomain, localhost
[root@example postfix]# systemctl restart postfix
```

メールをテスト送信。

```:console
[root@example postfix]# echo "this mail is for hoge@example.xyz" | mail hoge@example.xyz
```

無事、hoge@example.jpで受信できた。

# 参考
- [postfixで複数ドメインを受信する - ネットワークとプログラム](https://blog.goo.ne.jp/takawaguchi/e/fac490cce3d6e78229e8c496d01d8f89) - この記事と同じ方法
- [Postfix で複数ドメインのメールを受ける | ほぅほぅ爺の独り言](https://www.hohog.net/postfix-virtual-domain/) - virtual_alias_domainsを使う方法
[Java][Spring] ロガーの挙動をテストする

## 要求
* JUNITのテストでロガーの実行(`loggher.warn()`されたかなど)を確認したい

## 手法
* テスト対象クラスのロガーインスタンスをモックと入れ替える
* ArgumentCaptor を使えるようにする
* verfy メソッドを使ってロガーモックインスタンスの指定メソッドのコールをキャッチし、引数に渡されたものをキャプチャする


## サンプル
### 対象クラス
```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class Sample {
  private Logger logger = LoggerFactory.getLogger(Sample.class);

  public void run() {
    logger.info("サンプルメッセージ");
  }
}
```

### テストクラス
```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;


class SampleTest {
  private Sample sample = new Sample();

  // ロガー確認用 渡される引数をキャプチャする
  @Captor
  ArgumentCaptor<String> logMessageCaptor;

  @Mock
  private Logger mockLogger;

  @BeforeEach
  public void setUp(){
    MockitoAnnotations.initMocks(this); //これを実行することで、テスト対象クラスのフィールド変数をモックと入れ替えられる。
  }

  @Test
  void testRun() {
    sample.run();
    verify(mockLogger, times(1)).info(logMessageCaptor.capture()); //ここでロガーのinfo実行回数を確認しつつ、引数をキャプチャしてる
    assertEquals("サンプルメッセージ", logMessageCaptor.getValue());
  }
}
```


## verify について
* これ自体も `assertEquals()` のように、正しさの検証を兼ねる
  * 確認するメソッド指定を正しく指定すること
     * 主語
     * メソッド
     * 引数
  * 想定される実行回数を正しく指定すること
     * `times(n)` の n の値
     * 実行されないべきであるときは0を指定する
* 引数に Captor を使うことで、渡された値を取り出せる
0からはじめるelm-ui#4-上下左右中央揃え

# 今日覚えること

`centerX`, `centerY`を使って上下左右中央揃えする方法

[成果物](https://ellie-app.com/59D22Ks5rxJa1)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/1d917795-2d8c-ed33-4e73-2ff021219cce.png)


```elm
module Main exposing (main)

import Element exposing (..)
import Element.Background as Background


main =
    layout [] <|
        row
            [ Background.color <| rgb255 200 169 85
            , width <| px 400
            , height <| px 400
            ]
            [ column
                [ Background.color <| rgb255 255 169 85
                , width <| px 240
                , height <| px 240
                , centerX
                ]
                [ el [ centerX, centerY ] <| text "Hello, world" ]
            ]
```

# はじめに

[#2-styling](https://qiita.com/miyamo_madoka/items/dcb720ad324ee4246a94)で作ったものを覚えていますか？

再掲
![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/2df302c7-40f8-edd9-8560-db7336cfab60.png)

ハロワの文字が左上にありますよね、今日はこれを上下左右中央揃えにしたいと思います

CSSで中央揃えといえばいにしえの時代には大変苦労したらしいですね。わたしは物心ついたころにはflexboxがあったので実際にいろいろやったことはないので分からないのですが

elm-uiではとても簡単に中央揃えできます。2ステップです

# コンテナを`column`(`row`)にする

元のコードがこれです

```elm
el [ Background.color <| rgb255 255 169 85 
   , width <| px 200
   , height <| px 200
   ] 
   <| text "Hello, world."
```

ハロワの文字列を中央揃えしたいのでそれを囲ってるオレンジの部分を`column`にします。

```elm
column [ Background.color <| rgb255 255 169 85 
   , width <| px 200
   , height <| px 200
   ] 
   [ text "Hello, world." ]
```

ここまでで下のようになります。見た目は特に変わらないですね

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/15989fd7-91ec-54e1-01db-bd1d10a346c6.png)

# `centerX`と`centerY`を付ける

揃えたい要素に`centerX`と`centerY`を付けます
気を付けてほしいのはコンテナの`column`のほうではなくハロワのtextのほうに付けるということです

`#2-styling`でやったように`text`には直接Attributeをつけれないので`el`をつけます

```elm
 column
                [ Background.color <| rgb255 255 169 85
                , width <| px 240
                , height <| px 240
                ]
                [ el [ centerX, centerY ] <| text "Hello, world" ]
```

これでこうなります

![image.png](https://qiita-image-store.s3.amazonaws.com/0/74093/2ec226d1-dbe2-7106-dcca-b79fc9712af8.png)

わーい中央揃えできた！今日はもう終わり！

# `row`でもできるよ

```elm
         row
            [ Background.color <| rgb255 200 169 85
            , width <| px 400
            , height <| px 400
            ]
            [ column
                [ Background.color <| rgb255 255 169 85
                , width <| px 240
                , height <| px 240
                , centerX
                ]
                [ el [ centerX, centerY ] <| text "Hello, world" ]
            ]
```

さらに囲んでみました。できあがりは一番最初に貼った画像です。
内側のオレンジの四角である`column`に`centerX`が追加されていますね

`row`はデフォルトで上下方向はセンタリングされているので`centerY`を追加する必要はないのです（明記しても問題ありません）

# 終わりに


- `column`か`row`で囲んで揃える要素に`centerX`などを付与すると揃います
- コンテナではなく揃えたい要素自体に属性を追加すること
#python スクリプトにコマンドオプションを引数で渡す例

# script

```py
#!/usr/bin/env python3

from optparse import OptionParser

parser = OptionParser()

parser.add_option("--some", dest="some_option")
(options, args) = parser.parse_args()

print(options.some_option)
```

# exe

なんと short option を明示的に定義しなくても、 long option の最初の1文字を解釈して short option として解釈してくれる様子
 
```
$ ./opt.py --some=ABC
ABC
$ ./opt.py --s=ABC
ABC
```



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1068








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
RaspberryPiにx11vncサーバーを導入して、物理ディスプレイが使用しているディスプレイ番号にリモートから接続する

# 問題
ディスプレイが接続してあるRaspberryPiに対してUbuntuからリモート接続してみたところ、ディスプレイが同期されなかった。つまり、RaspberryPiに接続されているディスプレイが表示しているデスクトップとは別のデスクトップに繋がってしまった。

# 原因
これまではRaspberryPiのVNCサーバーとしてXtightvncを用いていたのだが、Xtightvncには物理ディスプレイが用いているディスプレイ番号(0)を使用することができないという特性があり、VNCサーバーを立ち上げる際は必ず1以上のディスプレイ番号が割り当てられてしまうことが問題の原因だった。

## ディスプレイ番号について
私の場合、RaspberryPiのGUI(デスクトップシステム)にはXWindowSystemを使用していた。
このXWindowSystemではデスクトップ1つ1つにデスクトップ番号が割り振られる。
ディスプレイ番号は`xdpyinfo`を実行して`name of display`欄を確認することによって確かめられる。
例えば、

```bash

$ xdpyinfo
name of display:    localhost:0.0
...
```
となっていた場合`localhost:(ディスプレイ番号).(スクリーン番号)`となっているため、ディスプレイ番号は0、スクリーン番号は0となる。

# 解決
x11vncを用いることでディスプレイ番号0に接続して、物理ディスプレイに表示されているデスクトップを操作することができた。

実行コマンドは以下の通り。

```bash

sudo apt update --fix-missing
sudo apt install xorg-dev #必要パッケージ
x11vnc --storepassword #ここでVNC接続に用いるパスワードを設定する
x11vnc -auth guess -display :0 -rfbauth /home/pi/.vnc/passwd -rfbport 5900 -forever -loop -noxdamage -repeat -shared #動作確認
sudo gedit /etc/systemd/system/x11vnc.service #デーモンファイル作成(内容は後述)

#以下デーモン起動
sudo systemctl daemon-reload
sudo systemctl enable x11vnc
sudo systemctl start x11vnc

```

なお、デーモンファイルの中身は以下のとおりである。

```
escription=x11vnc (Remote access)
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -auth guess -display :0 -rfbauth /home/pi/.vnc/passwd -rfbport 5900 -forever -loop -noxdamage -repeat -shared
ExecStop=/bin/kill -TERM $MAINPID
ExecReload=/bin/kill -HUP $MAINPID
KillMode=control-group
Restart=on-failure

[Install]
WantedBy=graphical.target
```
# 使用ツール
- Rapberry Pi 3 Model B 
- x11vnc
- xorg-dev
- VNC Viewer (realVNC)

#参考文献
http://extstrg.asabiya.net/pukiwiki/index.php?vncserver%A4%CE%BB%C8%CD%D1%CA%FD%CB%A1
https://blog.asial.co.jp/842
https://ubuntuforums.org/showthread.php?t=1538189
http://mixture.dcmnjp.net/linux/ubuntu/x11vnc.html
Kubernetes 1.14: SIG Apps の変更内容

# はじめに
このエントリは、[Kubernetes 1.14のCHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.14.md)から[SIG Apps](https://github.com/kubernetes/community/tree/master/sig-apps)の取り組みついてまとめています。

他の変更点については[Kubernetes 1.14: 変更点まとめ](https://qiita.com/shmurata/items/a796e02740b0eb7df65a) を参照してください。

# 1.14 What’s New
なし

# Known Issues

なし

# Urgent Upgrade Notes（重大なアップグレードに関する通達）

- `node.alpha.kubernetes.io/notReady` と `node.alpha.kubernetes.io/unreachable`は廃止となりました、代わりに `node.kubernetes.io/not-ready` と `node.kubernetes.io/unreachable`を使うようにしてください  ([#73001](https://github.com/kubernetes/kubernetes/pull/73001), [@shivnagarajan](https://github.com/shivnagarajan))

# Deprecations(廃止予定の機能)

- API
  - Ingressリソースは`networking.k8s.io/v1beta1`で利用できるようになりました。以前の`extensions/v1beta1`は廃止予定となりv1.18で廃止となります。既存のデータは新しいgroup/versionで利用するようにしてください。([#74057](https://github.com/kubernetes/kubernetes/pull/74057), [@liggitt](https://github.com/liggitt))
 - NetworkPolicyリソースはv1.16で`extension/v1beta1`での提供が廃止されます。v1.8から利用できるようになっている`networking.k8s.io/v1`に移行してください。既存のデータは新しい`networking.k8s.io/v1`を利用するようにしてください。
  - PosSecurityPolicyリソースはv1.16で`extensions/v1beta1`での提供が廃止されます。v1.10から利用できるようになっている`policy/v1beta1`に移行してください。既存のデータは新しい`policy/v1beta1`を利用するようにしてください。
  - DaemonSet, Deployment, Replicasetリソースはv1.16で`extensions/v1beta1`, `apps/v1beta1`, `apps/v1beta2`での提供が廃止されます。v1.9から利用できるようになっている`apps/v1`をに移行してください。既存のデータは新しい`apps/v1`を利用するようにしてください。
- これらの機能はGAとなり、関係するfeature gateは廃止予定となり、v1.15で削除されます。
  - `CustomPodDNS`
     - :memo: ([#72832](https://github.com/kubernetes/kubernetes/pull/72832), [@MrHohn](https://github.com/MrHohn))
  - `HugePages`
     - :memo: ([#72785](https://github.com/kubernetes/kubernetes/pull/72785), [@derekwaynecarr](https://github.com/derekwaynecarr))
  - `MountPropagation`
  - `PersistentLocalVolumes`

# Notable Features

なし

# Detailed Bug Fixes And Changes(細かなバグフィックスや変更)

- DasemonSetにより作られたPodが存在しないNodeに紐づけられている場合に削除する処理を追加しました。([#73401](https://github.com/kubernetes/kubernetes/pull/73401), @krzysztof-jastrzebski)
  - :memo: DaemonSetコントローラがPodを削除しないケースがあったようです。 [Issue #71349](https://github.com/kubernetes/kubernetes/issues/71349)
- Podのevinctionがデフォルトでグレースフルに振る舞うようになりました。これはevinctionのリクエストにdelete optionが付与されていない場合の挙動です。([#72730](https://github.com/kubernetes/kubernetes/pull/72730), @liggitt)
  - :memo: evictionのリクエストの内部で発行するPodのDeleteの際のDelete OptionがevictionのAPIのパラメータに指定されたDeleteOptionをそのまま引き渡すようになっており、そこにnilが渡った場合は即座にPodが削除されていました。今回evictionの処理が変更され、DeleteOptionが非nilを保証するようになったため、Grafafulに処理が行われるようになりました。これは[Issue #72717](https://github.com/kubernetes/kubernetes/issues/72717)によるとPythonのKubernetesライブラリの`create_namespaced_pod_eviction`を実行する場合や、直接eviction APIを呼び出している場合に問題になる場合があるようです。

# 所感

ChangeLogによると新しい機能追加はなく、今までbetaだった機能がstableに着々と昇格しているというのが、今回のハイライトです。地味ですが、重要な変更だと感じました。
pythonの内包表記をさわりだけ

#内包表記（リスト）のソース例
解説をするよりもまずはソース例を見た方が
わかりやすいと思うので書いてみます。

```inclusion.py

#通常表記
a = [9, 2, 3, 4, 8]
a_db = []
for x in a:
    a_db.append(x*2)

#内包表記
a = [1, 2, 3, 4, 5]
a_db = [x*2 for x in a]

```

#内包表記はpython特有の機能
少なくともphpやその他メジャーな言語では
現時点ではなさそうです。
ざっと検索したところjavascriptでは
数種類の内包表記があったらしく非推奨になっておりました。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Array_comprehensions
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Generator_comprehensionsES６では新規に内包表記が追加されているので
他の言語でも今後実装されてくる可能性は０ではなさそうですね。#内包表記はイテラブルなオブジェクトから新しいデータを作る
イテラブルとはリスト、文字列、タプル、辞書などの
要素を順番にとりだせるもののことを言います。
内包表記はイテラブルなオブジェクトから新しいデータ構造を作ることができます。

#条件を付与（リストの内包表記条件付き）
内包表記には条件をつけることも可能です。

```Conditions.py

#通常
a = [1, 2, 21, 30, 53]
a_db = []
 for x in a:
     if x >= 20:
         a_db.append(x*2)

#内包表記
a = [1, 2, 21, 30, 53]
a_db = [x*2 for x in a if x >= 20]

#条件付きリスト内包表記の構文
{式 for 変数 in イテラブルなオブジェクト if 条件式}

```

#辞書の内包表記
以下は辞書からkeyだけを取り出して
ランダムに値を付与するというもの。

```dictionary.py

#辞書の内包表記
from random import randint
keys = ['辞書', 1, '文庫', 8, '漫画']

d = { x:randint(1, 100) for x in keys if type(x) == str}
print(d)
#実行結果
#{'辞書':88, '文庫':32, '漫画':43}

#辞書の内包表記の構文
{ キー:値 for 変数 in イテラブルなオブジェクト if 条件式 }
```

#集合の内包表記
集合に関しては同じ値を無視するという性質がある。

```set.py

a = {2, 1, 5, -3, 5, -1, 10, 9, 13, 3, -5
setA = { x for x in a if (0 < x <= 10)}

#実行結果
#{2, 1, 5, 10, 9, 3}

#集合の内包表記の構文
{ 式 for 変数 in イテラブルなオブジェクト (if 条件式) }
```

#ジェネレータを内包表記で書くこともできます
javascriptでは非推奨になっていたジェネレータの内包表記ですが
pythonは標準で書くことが可能です。

```generatorexpression.py

g = (x for x in range(5))

#ちなみに以下のtはリストになります。
t = [x for x in range(5)]

```

以下は実行結果となります。

```excusionresultgeneratorexpression.py
>>> g = (x for x in range(3))
>>> print(next(g))
0
>>> print(next(g))
1
>>> print(next(g))
2
>>> print(next(g))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
```
高機能クラウドストレージNextCloudをdocker-composeでセットアップする

# TL;DR

* 高機能なクラウドストレージNextCloudを，オンプレミス環境にセットアップする方法を紹介します
    * [NextCloud用のdocker-compose.yml](https://github.com/myoshimi/nextcloud-docker-compose)を作ったので，これを使います
* docker-composeで，稼働に必要なコンテナ群をまとめて稼働させます
* https接続して通信の安全性を向上させます
    * [Let's Encrypt](https://letsencrypt.org/)で発行してもらった証明書を組み込みます
    * httpsを使用しない方法についても合わせて記載します

# 構成

* docker-composeで，下図の3つのコンテナを立ち上げて運用します
    * NextCloud本体
    * nginx
    * MariaDB

![nc-network.jpg](https://qiita-image-store.s3.amazonaws.com/0/309617/26c5ab54-d53b-20e2-f3ab-7710cccb1250.jpeg)

* NextCloudコンテナ
    * 80/TCPでアクセスを受け付けます（Dockerでローカルホストからの接続しか受付ません）
* MariaDBコンテナ
    * NextCloudがメタ情報の保存のために使用するコンテナです
* (任意) nginxでリバースプロキシする
    * https(443/TCP)で受け付けたリクエストを，NextCloudコンテナにフォワードします
    * リバースプロキシが別の場所にある場合は，docker-compose.ymlを編集して不使用にします

# 最も簡単な使い方

* HTTPS用の認証キーファイルを，```git clone```してきたディレクトリのkeys内に格納して，```docker-compose up```します

```shell
git clone https://github.com/myoshimi/nextcloud-docker-compose
cd nextcloud-docker-compose
cp <Directory Path>/fullchain.pem ./keys/
cp <Directory Path>/privkey.pem ./keys/
docker-compose up -d
```

# docker-compose.ymlでの作業の解説

* 3つのコンテナ（app, rev, db）を立ち上げます
    * appコンテナ: NextCloud本体のコンテナ
        * volumeとして，コンテナの```/var/www/html```を，ローカルディレクトリ(nextcloud-docker-compose)にマウントします
        * 環境変数```MYSQL_*```によって，同じdocker-composeのdbコンテナに接続します
        * ```ports```ディレクティブで，ローカルホストからのみアクセス許可(3040/TCP)をしています
    * revコンテナ: リバースプロキシ用のコンテナ
        * 443/TCP(https)を外部からのアクセス許可しています
        * ローカルディレクトリのnginx.conf，およびkeysディレクトリの認証用鍵ファイル(fullchain.pem, privkey.pem)をマウントしています
    * dbコンテナ： MariaDBコンテナ 
        * volumeとして，コンテナの```/var/lib/mysql```を，ローカルディレクトリにマウントします
        * 環境変数```MYSQL_*```で初期設定をしています
        * ```expose```ディレクティブで，appコンテナからのみからのアクセス許可(3306/TCP)をしています
* 不揮発化ボリュームについて
    * コンテナが落ちたり消えたりしてもデータが飛ばないように，不揮発化領域を各コンテナがマウントしています
    * ```docker-compose up -d```したときに作られるディレクトリは，nextcloud-docker-compose内の以下のものです．これらが残っていれば，NextCloudの環境を復元できます
        * ```/data```: NextCloudが持つデータ（プラグインアプリなど）
        * ```/db```: MariaDBのデータ

# リバースプロキシをしない場合

* 別の既存のリバースプロキシでNextCloudへ接続する場合，または，ローカルネットワークで運用してHTTPS接続が不要な場合
    * インターネットから接続できる環境での運用はセキュリティ上問題になるのでご注意ください
* docker-compose.ymlを2箇所修正して，```docker-compose up -d```します．

## 1. リバースプロキシを使用しないようにする

* revコンテナ(nginx)に関する記述をdocker-compose.ymlから削除します

```diff
-  rev:
-    image: nginx:1.15
-    network_mode: "host"
-    ports:
-      - "443:443"
-    volumes:
-      - ./nginx.conf:/etc/nginx/nginx.conf:ro
-      - ./keys/fullchain.pem:/etc/nginx/keys/fullchain.pem:ro
-      - ./keys/privkey.pem:/etc/nginx/keys/privkey.pem:ro
```

## 2. nextcloudのアクセス許可の変更

* docker-compose.ymlのnextcloudに関する記述を変更し，外部から80/TCPでのアクセスを許可します
    * 以下の記述は，外部から3040/TCPでの接続を許可しています
    * IPアドレス制限や，ポート番号は別のものを使用することができます

```diff
   app:
     image: nextcloud:15-apache
     restart: always
     ports:
-      - "127.0.0.1:3040:80"
+      - "3040:80"
     depends_on:
       - db
```

# 参照

* [NextCloud](https://nextcloud.com/)
System.Runtime.Serializationを利用してJsonデータクラスを定義

自分で作成した一例

```
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;

namespace TestApp.Json
{
    [DataContract]
    public class CreateModel_request
    {
        [DataMember]
        public string SessionID { get; set; }

        [DataMember]
        public int UserID { get; set; }

        [DataMember]
        public VoiceInfo_Object_CreateModel VoiceInfo { get; set; }
    }

    [DataContract]
    public class VoiceInfo_Object_CreateModel {

        [DataMember]
        public string Phrase { get; set; }

        [DataMember]
        public bool CleanRegist { get; set; }

        [DataMember]
        public List<VoiceList_Item> VoiceList { get; set; }
    }

    [DataContract]
    public class VoiceList_Item {

        [DataMember]
        public int VoiceID { get; set; }

        [DataMember]
        public string VoiceData { get; set; }
    }
}
#python では標準ライブラリと同名のファイルは作ってはいけない ( わけではないかもしれないが、謎の import エラーが出る場合の対処 )

# ./test.py

```
from datetime import datetime 
```

# ./datetime.py

空ファイル

# execute
```
$ python3 ./test.py
Traceback (most recent call last):
  File "./test.py", line 1, in <module>
    from datetime import datetime
ImportError: cannot import name 'datetime' from 'datetime' (/Users/yumainaura/.ghq/github.com/YumaInaura/YumaInaura/python/datetime.py)
```

# Error reading

どこからライブラリを読み込もうとしているか見てみよう

```
(/Users/yumainaura/.ghq/github.com/YumaInaura/YumaInaura/python/datetime.py)
```

# 解決

独自ライブラリファイル `./datetime.py` は別名に変更する

# 標準ライブラリから読み込む方法

未調査

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1067








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
【Laravel】基礎知識とroutes編集のサンプル

#基本知識のノート#
Laravelで作成したプロジェクトにはいくつかのフォルダがあるが主要なものは3つ。

1. `app`：プリケーションのプログラム部分。
2. `resouce`：テンプレートファイルなど。
3. `routes`：ルート情報

##app##
メインに使うのは`Http`。
これがwebアプリケーションにアクセスした時の処理をまとめておく所。
基本的なプログラムはここで作成。

##resouse##
ここには例えば`View`フォルダなどがあり、
`welcome.blade.php`(後述)が保存されている。

##routes##
一般的なwebページは`web.php`にルーティングされている。
ここにルート情報を書き込むことで、
`welcome.blade.php`などのファイルを呼び出すことができる。


#ルーティングという概念#
routes内ファイルを編集することでルーティングをする。
ここでは`routes/web.php`を編集していく。
基本的には以下の形式で記述。

```php
Route::get( 'URLを書く', function(){
    return 処理を書く。
});
```

- 第1引数はアドレス
    - `hello/{msg}`という形でパラメータ`msg`を設定できる。
    - その場合、第二引数は`function($msg){return ;}`のような形に。
- 第2引数は関数（ここではクロージャ）
    - `function() use($html){};`として、関数の外に記述しているヒアドキュメント`$html`を用いることもできる。

##サンプルコード##
ヒアドキュメントを`Route::get();`の外側にする場合

```php
$html = <<< EOF
<html>
<head>
<meta charset="UTF-8">
<title>Hello</title>
<style>
body{font-size:16pt;}
h1{color:#eee;}
</style>
</head>
<body>
<h1>Hello</h1>
<p>This is sample code.</p>
</body>
</html>
EOF;

Route::get('hello', function() use($html){
	return $html;
});
```

ヒアドキュメントを`Route::get();`の内側にする場合
(ルートで渡すパラメータをヒアドキュメントに引用する場合)

```php
Route::get('hello/{msg?}', function($msg){

$html = <<< EOF
<html>
<head>
<meta charset="UTF-8">
<title>Hello</title>
<style>
body{font-size:16pt;}
h1{color:#eee;}
</style>
</head>
<body>
<h1>Hello</h1>
<p>This is sample code.</p>
</body>
</html>
EOF;

return $html;
});
```
*※ここでは任意パラメータ`{msg?}`にしている。*


##【補足】ヒアドキュメントの書き方##
PHPで記述されたコードにHTMLを埋め込むのがヒアドキュメント。
ヒアドキュメントをPHPに入れる場合は`$html`で入れられる。

```php
<?php
$html = <<<EOF
ここにhtmlコードを記述。
PHP部分で使われている変数をもって来たい場合は{$msg}という形で記述。
EOF;
?>
```

#参考書籍#
[PHPフレームワークLaravel入門]
(https://www.amazon.co.jp/dp/B07CLLW4MX/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
Chapter2-1 Pp.24
laravelでapi通信時、Auth::guard('admin')->user()->idでとれない

##症状
laravel5.8でmulti authでadmin用の認証をつくった。
けど、adminユーザーでapi通信したら、laravel側で`Auth::guard('admin')->user()->id`で取得しようとしても`id`がとれない。

##解決法

### StartSession.phpを追加

```php:App/Http/Middleware/StartSession.php
<?php

namespace App\Http\Middleware;

use \Illuminate\Session\Middleware\StartSession as BaseStartSession;
use \Illuminate\Http\Request;
use Closure;

class StartSession extends BaseStartSession
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if($request->url() == "api/*"){
            return $next($request);
        }

        return parent::handle($request, $next);
    }
}
```

### SessionServiceProvider.phpを追加

```php:App/Providers/SessionServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Session\SessionServiceProvider as BaseSessionServiceProvider;
use App\Http\Middleware\StartSession;
class SessionServiceProvider extends BaseSessionServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerSessionManager();

        $this->registerSessionDriver();

        $this->app->singleton(StartSession::class);
    }
}
```

### Kernel.phpを編集

```php:App/Http/Kernel.php
protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
        \App\Http\Middleware\ForceHttpProtocol::class,
        \App\Http\Middleware\StartSession::class, //これを追加
    ];
```

##参考
[https://github.com/laravel/framework/issues/17187](https://github.com/laravel/framework/issues/17187#issuecomment-279200503)
ネットワークの基礎

#はじめに
開発したアプリをサーバーにデプロイする際に、ネットワークの知識が必要だと思い、学習した内容を記録します。
#ネットワークとは？
コンピューターー(パソコンなど)同士がつながって情報のやり取りができるようになった状態。
家庭内や社内など、近くのコンピューターをつなげたネットワークを```LAN```、遠くにあるコンピューターをつなげたネットワークを```WAN```という。

#サーバーとクライアント
ネットワークに属するコンピューターのうち、何らかのサービスを提供する側をサーバー、サービスを受け取る側をクライアントと呼ぶ。

Webサービスの場合、サーバー側の仕事はクライアントからリクエストを受け取り、Webページのデータを送る。
クライアント側の仕事はサーバーにリクエストを送り、返事として送信されたデータをWebページに表示する。


#コンピューターネットワークの階層
| 階層名 | 役割 | プロトコル |
|:-:|:-:|:-:|
|  アプリケーション層 | Webや電子メールなどのサービスをクライアントに提供する  |  サーバ、クライアント、HTTP、SMTP、POP3、FTP、SSHなど |
|  トランスポート層 | アプリケーション層とインターネット層を仲介し、データを正しく届けるための手配をする  |  TCP、UDP |
|  インターネット層 |IPアドレス(コンピューターの住所)を手掛かりにデータを届ける   | IPアドレス、IPv4、IPv6、ICMP、ルーティング  |
| ネットワークインターフェース層  | 通信用のハードウェアを制御して、実際にデータを伝達する(ネットワークカード、LANケーブルなど)  | イーサネット、無線LAN、PPPなど  |


上記の4つの階層のうちアプリケーション層はサービスを提供し、他の3つは通信機能を担当している。

#通信ルールを決めているプロトコル
プロトコルとは、通信ルールをまとめた仕様書みたいなものでそれ自体が仕事をするわけではない。
ネットワークの階層ごとにプロトコルが定められており、それらが組み合わさって動くことで通信が成り立っている

例
・アプリケーション層　HTTPというプロトコルに従って動くように作られているWebブラウザ

・トランスポート層、インターネット層　TCP/IPというプロトコルに従って動くように作られたOS内（Win, Mac）の通信プログラムなど

#おわり
さらに深堀していくとさまざまなネットワークの階層、プロトコルなどがあるので次回以降さらに階層ごとの詳細、プロトコルについてまとめていきたいと思います。

#参考文献
第2版 スラスラわかるネットワーク＆TCP/IPのきほん
https://www.amazon.co.jp/スラスラわかるネットワーク-TCP-IPのきほん-第2版-リブロワークス/dp/4797396075/ref=tmm_hrd_swatch_0?_encoding=UTF8&qid=&sr=
HTTPS化 - AWS EC2にてGitlabを動かす 2019


![ScrShot_NoName_2019-4-4_15-7-25_No-00.jpg](https://qiita-image-store.s3.amazonaws.com/0/62413/6d1510f6-cafc-6475-0df9-e11b8306a5e3.jpeg)



## 環境

- EC2 m4.large Amazon Linux
- GitLab Community Edition 11.4.5
- ドメイン名 : gitlab.dev

## 前提!  ELB(https:443) -> EC2(http:80)

ELBを使って，GitlabのEC2インスタンスにはhttpでアクセスされるようにしている．

## 問題!

https://gitlab.devでアクセスできた(ログインできた)

新規リポジトリを作ろうと思うと，リポジトリのURLがhttps://ip-72-31-31-200となっている！

## 設定を変更する


gitlabの設定を開く

```sh
$ sudo vim /etc/gitlab/gitlab.rb
```

設定ファイルの中身を変更する

```sh
// --/etc/gitlab/gitlab.rbの中身--

// DNSの設定を変更
external_url 'https://gitlab.dev'

// nginxの挙動の設定を変更
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
  'X-Forwarded-Proto' => 'https',
  'X-Forwarded-Ssl' => 'on'
}

```

設定を反映

```sh
$ sudo gitlab-ctl reconfigure
```

アクセスできた！

![ScrShot_NoName_2019-4-4_15-7-57_No-00.jpg](https://qiita-image-store.s3.amazonaws.com/0/62413/49ae52e2-d822-86b5-2897-7a566413a84c.jpeg)



以上.
Flutterで重い処理をする際にUIをフリーズさせない

dartには`Future<T>`という、jsでいうところの`Promise`のようなものがあり、非同期処理を書ける。
しかし、その中にCPUヘビーな同期的な処理を書いてしまうと、dartはシングルスレッドで実行されるので、
flutterでは当然、UIがフリーズしてしまう。

# Isolate
dartはシングルスレッドで動作するが、メインプロセス以外のところでも処理を動かせる。
この仕組みをIsolateという。
メインの処理自体も一つのIsolateとして動いている。(Main Isolate)
Isolateはいわゆる「別スレッド」とは異なるもので、メモリを共有しない。

# flutterで簡単にIsolateを使って処理をする
`package:flutter/foundation.dart`にある`compute()`関数を用いて簡単に別Isolateで処理を行うことができる

```dart
...
import 'package:flutter/foundation.dart';
...

class MyState extends State<MyWidget> {
  ...
  ...
  foo() async{
    final result = await compute(computeString, 'Hello'); // computeStringに渡したい引数をcomputeの第二引数に指定

    setState((){
      _displayedStr = result;
    });
  }

  static String computeString(String param) {
    // 時間がかかるCPUヘビーな処理
  }

  ...
  ...

}
```

- 注1：`compute`に渡す関数はstaticなものであること
    - 上述のとおり、 `compute`関数によって新たに立ちあがるSecondary IsolateはMain Isolateとメモリを共有しないので、関数はstaticである必要があります
- 注2：`compute`に渡す関数の引数は1つであること
    - `compute`関数自体が第2引数までしかとらないので、複数の引数を渡したいときはオブジェクトにするなどが必要
Webiotセンサーを使ってMotionBoardで最速で可視化してみる

# 1. はじめに
IoTセンサーデータの可視化ってどうしてますか？せっかくだからリアルタイムでグラフが動くの、やりたいですよね？
有償ですが、MotionBoard Cloudというサービスがあるので、それをつかってやってみます。

# 2. Webiotとは

超簡単に始められるIoTセンサーです。
月額制でBluetooth版とLoraWAN版があり、
2019年4月現在、温度・湿度・気圧・照度・人感・距離・CO2センサーなどがラインナップされています。
Bluetooth版はゲートウェイがセットで必要になります。

開封の儀は以下の記事が参考になるかも。

- [デモに最適！５分でデータ取得からグラフ表示する方法](https://qiita.com/masashiokawa/items/86f41b0a858b11edaeb4)
<br>


[Webiot公式](https://webiot.io/)
[![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/3b9209eb-46f5-72ef-7154-8e0766b787d7.png)](https://webiot.io/)

# 3. MotionBoardとは

データベースやセンサーデータなどを可視化できるソフトウェアです。
商用ソフトウェアですが、各種データベースとの接続や高度な可視化・分析機能が使用できます。

- [MotionBoard](http://www.wingarc.com/product/motionboard/)


# 4. 連携手順
## Webiotコンソール
Webiotを契約すると利用できるIoTセンサーの管理画面です。
申込時のgoogleアカウントに紐付かれていますので、センサーデータの受信設定などは不要です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/53a32e3c-d513-c1fb-8fee-0d93d123a481.png)

他システムとの連携は「データ連携」->「ルール追加」から行うことができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/e1e062b5-6b17-50ca-de7f-2abbcd80692d.png)

## MotionBoardとの連携
MotionBoardのIoTエディションが必要です。
「HTTP GET」でも「HTTP POST」でも送信できますが、今回はより簡単なHTTP GETで送信します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/9486bfb1-abfc-3f52-b114-a77da521cb6e.png)


送信したいセンサーにチェックを入れます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/30586194-2668-5f45-7436-9fb9b8d5e420.png)

「送信先URL」と「カスタムHTTPヘッダ」を設定します。
例えば、温湿度気圧センサーの場合、「送信先URL」は次のようになります。

```
https://iot-cloud.motionboard.jp/motionboard/rest/tracking/data/upload/simple?template=【リアルタイム連携用テンプレート名】&id={{id}}&temp={{value01}}&hum={{value02}}&pre={{value03}}
```
【リアルタイム連携用テンプレート名】は、あらかじめMotionBoard上でリアルタイム連携用テンプレートを作成しておく必要があります。作成した後、テンプレート名で置き換えてください。

- [MotionBoard リアルタイム連携用テンプレート作成方法](http://navi.wingarc.com/motionboardiot/webapi.html)

次に、カスタムHTTPヘッダありにチェックを入れ、左側にCookie、右側にtenant=【MB契約時のテナント名】と記入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70061/0aa64f13-a70e-0a51-97ce-f0cb3d8986f8.png)









<br> 
 
 
「テスト」ボタンを押して正しく送信できることを確認します。
正しく送信できた場合、200と表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/f7df2c75-2d15-166c-f318-132ede3f3f2c.png)


## MotionBoardでの確認
最後にMotionBoardの「データソース選択」->「system datasources」->「Realtime」->「StatusHistory」->【リアルタイム連携テンプレート名】にレコードが入ってくれば正しく受信できています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/61397dd9-8a73-82a9-705f-e91cc657f7cd.png)


センサーデータ表示例。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/70061/bbf580be-e207-329a-953c-a8bc60a16c53.png)



# 5. 参考
* [Webiot データ連携](https://github.com/webiot-io/doc/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E9%80%A3%E6%90%BA)
* [MotionBoard Cloudマニュアル@リアルタイム連携のWeb API](https://mbc-manual.motionboard.jp/motionboard/manual/mbcloud/#111609715.html%3FTocPath%3D%25E7%25AE%25A1%25E7%2590%2586%25E8%2580%2585%7CWeb%2520API%25E3%2583%25AA%25E3%2583%2595%25E3%2582%25A1%25E3%2583%25AC%25E3%2583%25B3%25E3%2582%25B9%7C%25E7%25AC%25AC3%25E7%25AB%25A0%25E3%2580%2580Web%2520API%25E3%2581%25AE%25E4%25B8%2580%25E8%25A6%25A7%7C_____6)
* [MotionBoard リアルタイム連携用テンプレート作成方法](http://navi.wingarc.com/motionboardiot/webapi.html)
windows で SSH鍵を作成する

# なにがあったのか
Windows 環境で SSH鍵を作成したいけど、`cmd` じゃ `ssh-keygen` ができない！


## 結論から
`Git` インストールして `Git Bash` から作ろう。


## 流れ

- `Git` をインストールする(`Git Bash` もいっしょに)
- `Git Bash` を起動して `ssh-keygen` 実行。作成ディレクトリとパスフレーズを指定。
- SSH鍵が作成されるので `id_rsa.pub` の内容(公開鍵)をよしなに使いましょう。めでたしめでたし。
WindowsでOCamlするために：環境を作る、インストール方法

Windows Subsystem for Linux で　Opam initまでできる！すごいよマイクロソフト

もはや、Windows での OCaml は茨の道ではなくなったのだ

インストール方法
　windows10にWindows Subsystem for Linuxをインストールする。
　あとは、linuxのOCamlインストールに準ずる
これだけ



さらに、Real World OCaml
https://dev.realworldocaml.org/install.html

Setting up and using utopのopen Core　までできた
https://dev.realworldocaml.org/install.html
gist comment image hack with imgur

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/235946/37901bbd-5a68-fbbd-7b94-b661ad78144c.png)

- demo https://codepen.io/gnjo/pen/OGMxPd?editors=1010
- imgur cidは捨てid
- about imgur https://imgur.com/

```js

var fn={};
fn.q=(s,doc=document)=>{return doc.querySelector(s)};
fn.pnt=(str)=>{document.execCommand('inserttext', false,str)}
fn.pnt2=(str)=>{document.execCommand('inserthtml', false,str)}

let cid='33989214e792382'
,area=fn.q('#area')
,updata=fn.q('#updata')
console.log(area,updata)
uploader(cid,area,(ev)=>{
 //ev.target,ev.type,ev.uid,ev.url,ev.cid
 if(ev.type==='init'){
  console.log(ev.type,ev)
 }
 if(ev.type==='loading'){
  console.log(ev.type,ev)
  let str=`![Uploading ${ev.uid} ...]()`
  fn.pnt2(str)
 }
 if(ev.type==='loaded'){
  console.log(ev.type,ev,ev.url)
  let str=`![Uploading ${ev.uid} ...]()`
  ,nstr=`![download](${ev.url})`
  area.textContent=area.textContent.replace(str,nstr)
  updata.src=ev.url
 }
})
```

```html
<!--core-->
<script src="https://codepen.io/gnjo/pen/KYVyNX.js?imgurAndGist=1"></script>
```

```html
<style>
 #app{width:500px;border:1px solid}
 #area{width:100%;min-height:300px;height:100%;background-color:orange}
 #de{position:fixed;right:0;}
</style>
<script src="https://codepen.io/gnjo/pen/KYVyNX.js?imgurAndGist=1"></script>
<img id="de" src="https://i.imgur.com/FtlkJig.png"></img> 
<div id="app">
 <div id="area" contenteditable="plaintext-only"></div>
 <img id="updata" ></img>  
</div>
```