OmniAICreator/Qiita-1.07M huggingface dataset:
RxJava(Kotlin)で通知内容が不要な通知にはUnitを使うと良いと思う

表題通りです。RxJavaを使っていると、通知はしたいのですが、通知内容自体に関心がない場合、

```kotlin
Observable.just(true).subscribe(::println)
```

などして、「別にBoolean情報を通知したい訳じゃないんだけどなー」と内心思いながらお茶を濁してました。こんなときにUnitが使えるのですね。

```kotlin
Observable.just(Unit).subscribe(::println)
```

出力結果は以下のようになります。

```
kotlin.Unit
```

Unitって何だろうと、みてみると、

``` kotlin
package kotlin

/**
 * The type with only one value: the Unit object. This type corresponds to the `void` type in Java.
 */
public object Unit {
    override fun toString() = "kotlin.Unit"
}
```

と定義されてました。なるほど。

最後に、PublishSubjectでUnit使ったコードをのせておきます。

``` kotlin
val ps = PublishSubject.create<Unit>()
ps.subscribe(::println)
ps.onNext(Unit)
ps.onNext(Unit)
ps.onNext(Unit)
ps.onComplete()
```

出力結果は、

```
kotlin.Unit
kotlin.Unit
kotlin.Unit
```

です。
Tableauでテキスト検索の速度を上げる（パフォーマンス検証）

#はじめに

Tableauに大量データを取り込んだ際、フィルターの処理速度が落ちてしまうため、
下記3パターンのテキストボックス検索で、どの方法が最も早いかパフォーマンス検証を行う。

1．通常のテキストフィルター（フィルターモード：ワイルドカード一致）
2．CONTAINS関数を利用したフィルター
3．REGEXP_MATCH関数を利用したフィルター

#環境・データ量

- Tableauバージョン ：Tableau 2018.1
- サンプルデータ件数：15,000,000件

#準備
##パラメーターと関数の作成

1．テキストフィルター（ワイルドカード一致）
Tableauの通常フィルターのため設定不要。

2．CONTAINS関数を利用したフィルター
　2-1．CONTAINS関数に渡す条件入力用のパラメータを作成する。データ型は文字列。
　2-2．CONTAINS関数をフィルターとして使用するための計算フィールドを作成する。

```
IF [CONTAINSの条件入力用パラメーター名] != "" THEN
    CONTAINS([検索対象のディメンション名],[CONTAINSの条件入力用パラメーター名])
ELSE
    TRUE
END
```
3．REGEXP_MATCH関数を利用したフィルター
　3-1．REGEXP_MATCH関数に渡す条件入力用のパラメータを作成する。データ型は文字列。
　3-2．REGEXP_MATCH関数をフィルターとして使用するための計算フィールドを作成する。

※正規表現を利用するための関数であるため、用途は広いが利用者によっては予期せぬ
　結果が表示されることがある。

```
IF [REGEXP_MATCHの条件入力用パラメーター名] != "" THEN
    REGEXP_MATCH([検索対象のディメンション名],[REGEXP_MATCHの条件入力用パラメーター名])
ELSE
    TRUE
END
```
※上記式はパラメーターに条件が指定されない際に全データを表示をするよう、
　条件指定時及び指定されない場合のどちらも真が返るよう定義している。

##ワークシートに上記で作成した計算フィールドを設定する

1．テキストフィルター（ワイルドカード一致）
関数不要のため検索対象のディメンションをワークシートのフィルターに入れておく。

2．CONTAINS関数を利用したフィルター
上記のCONTAINS関数を使用した計算フィールドをワークシートのフィルターに設定する。
フィルター条件は「真」を指定。

3．REGEXP_MATCH関数を利用したフィルター
上記のREGEXP_MATCH関数を使用した計算フィールドをワークシートのフィルターに設定する。
フィルター条件は「真」を指定する。

※NULLを指定する理由は上述した通り、パラメーターに条件を指定しない際、
　全データが表示されるようにするため。

#パフォーマンス検証
参考：[ワークブック パフォーマンスの記録と分析](https://onlinehelp.tableau.com/current/pro/desktop/ja-jp/perf_record_create_desktop.html)

1．テキストフィルター（ワイルドカード一致）
ExecutingQuery：0.44
設定が楽。リスト、ドロップダウンなど検索パターンが多いなど利点が大きい。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/270976/92c19050-93f5-3d52-9122-36ea18619a8f.png)
2．CONTAINS関数を利用したフィルター
ExecutingQuery：0.16
若干の手間がかかる。テキストボックスの検索だけなら通常のフィルターより早い。
![2.png](https://qiita-image-store.s3.amazonaws.com/0/270976/d30de627-d34e-5b67-1322-cf7006285363.png)
3．REGEXP_MATCH関数を利用したフィルター
ExecutingQuery：0.28
若干の手間がかかる。テキストボックスの検索だけなら通常のフィルターより早い。
利用者が正規表現を使えるなら用途の広い条件指定が可能。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/270976/db8be2d1-fbc2-b49a-11b2-d953ebced722.png)
データ量が多ければ多いほど違いが出てくると思いますので、用途に応じて使い分けることで、
パフォーマンスに違いが出てくると思います。

#おわりに
データ量が多い際にパフォーマンスが落ちてしまうのは当然のことなので、
どんなデータを可視化し、利用者に何を伝えたいのかをきちんと設計することで、

・不要なデータは取り込まない
・ダッシュボードに不要なワークシートを表示しない
・ワークシート上の表示件数を制限する など

目的にあった見せ方を意識した設計を行いたいですね。
戻り値でbinding.pryを使うとnilを返してしまう。

デバッグツールとして便利な`binding.pry`。
しかし、デバッグをしている間にハマってしまった。

##デバッグ中に勘違いしてしまったこと

```rb
def toal
  total = sum #<= 2ではなくnilが返る
  puts total
end 

def sum
  1 + 1
  binding.pry
end

total
```

```
nil
```
通常、sumの戻り値は2のはずだが、`binding.pry`で確かめた後だと、nilが返ってきてしまう。

これによって、正常に値が渡らないのはなぜだ？と何時間も悩むハメに。。



便利なツールだが、メソッドの一番後ろにかけると勘違いを引き起こしてしまう可能性があるので今後使う際は気をつけていきたい。
卒研　3D模型にシリコンをきれいに流す方法


#シリコン型作成
左図①に記している程度の型の大きさになると思われます。 型製作作業の準備は以下の通りです。 ① 青線の範囲以外の油粘土を取り除く。 ② 粘土と模型を置いている面に離型剤としてワセリンを薄く 塗っておく。 ③ 現在の模型の断面図は図②のようになっているはずです。 ④ 紙コップ・型剤を混ぜるためのヘラ、塗るための筆、筆を洗 うためのトルエン。ワセリン。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305521/870dad56-3f58-e1c1-1857-d5ab023d34dd.png)

＊ 型剤について  
ＳＡＳ・・・ウレタン型剤（リキッドタイプ）粘度のある液体タイプで細かな部分に入り込む ことで、正確な型を作製することができる。       混合比率 Ａ：Ｂ＝1：4 操作時間８分 完全硬化時間５時間       積層する場合は、１層目を塗って約２０分程度で表面が硬化したら２層目を塗る。 ３層目以降も同様に行う。
  
 ＪＡＳ・・・ウレタン型剤（ペーストタイプ）垂直塗りが可能な型剤であり、ＳＡＳの補強のた め使用し型の軽量化が可能である。        混合比率Ａ：Ｂ＝1：2 操作時間１０分 完全硬化時間９０分        全てのＳＡＳを塗り終えてから約３０～４０分後から塗ることでＳＡＳとＪＡＳ は完全同化する。   


![IMG_3210.JPG](https://qiita-image-store.s3.amazonaws.com/0/305521/024cae21-83d5-6a28-0c36-c790085f70d9.jpeg)


 3D模型に3mm厚の油粘土をかぶせてシリコンを均等に流し込めるようにする。
粘土の表面はきれいに保つこと(亀裂や段差があるとシリコンを流したときに表に出てしまう）
![IMG_3207.JPG](https://qiita-image-store.s3.amazonaws.com/0/305521/b5071fbe-c762-3589-34cf-1b74dce3a631.jpeg)

工程予想図
A![image.png](https://qiita-image-store.s3.amazonaws.com/0/305521/597472fc-d072-4d56-c23e-8d7ade5c252a.png)

B![image.png](https://qiita-image-store.s3.amazonaws.com/0/305521/e85bbf05-ae2b-3f83-8122-2f30755daa7c.png)

＃＃型作成方法

① ＳＡＳ Ａ剤 1：Ｂ剤４・・・５ｇ：20ｇ程度を計量し、よく混ぜ合わせて粘土模型の表面に 筆で塗る。この時に気泡が入らないように筆の腰を使うように（筆全体が表面につくように） 塗る。筆先だけで塗ると気泡が残りやすいので注意する。これは、特に１層目に注意する点で ある。筆に残っているＳＡＳをティッシュペーパーなどで拭き取り、トルエンで洗う。

![IMG_3214.JPG](https://qiita-image-store.s3.amazonaws.com/0/305521/a74bf68d-6f30-99f0-894d-dbb759ab1e0f.jpeg)



 ② 約２０分後表面が硬化しているのを確認する（本体に影響がない部分を指先で触ってみて少し 柔らかいが指先にはついてこない程度）。確認が出来たら２層目を同様に塗る。筆に残っている ＳＡＳをティッシュペーパーなどで拭き取り、トルエンで洗う。


 ③ 約２０分後２層目の表面の硬化を確認して３層目を同様に塗る。筆に残っているＳＡＳをティ ッシュペーパーなどで拭き取り、トルエンで洗う。


 ④ 約３０～４０分後３層目の硬化を確認する。 （この時点ではほぼ硬化したような感触だが、少し 柔らかさがある）


 ⑤ ＪＡＳ Ａ剤 1：Ｂ剤 2・・・・40ｇ：80ｇ程度を計量しよく混ぜ合わせてからＳＡＳを塗った 表面にヘラを使用して盛るように塗る。全体に塗り終えたら、表面にワセリンを塗って表面の トゲトゲしたところを整える。


 ⑥ 約９０分静置する。

 ⑦ ＪＡＳの硬化を確認したら、型をひっくり返して中の模型を取り出す。この時に油粘土は本体 以外の部分の油粘土だけを取り除く。

 ⑧ 油粘土以外のウレタン部分にワセリンを塗る。


 ⑨ ＳＡＳ Ａ剤 1：Ｂ剤４・・・５ｇ：20ｇ程度を計量し、よく混ぜ合わせて粘土模型の表面に 筆で塗る。この時に気泡が入らないように筆の腰を使うように（筆全体が表面につくように） 塗る。筆先だけで塗ると気泡が残りやすいので注意する。これは、特に１層目に注意する点で ある。筆に残っているＳＡＳをティッシュペーパーなどで拭き取り、トルエンで洗う。
![IMG_3228.JPG](https://qiita-image-store.s3.amazonaws.com/0/305521/9ebeb201-b3a3-366e-b4d3-38d206816f4a.jpeg)
 ⑩ 約２０分後表面が硬化しているのを確認する（本体に影響がない部分を指先で触ってみて少し 柔らかいが指先にはついてこない程度）。確認が出来たら２層目を同様に塗る。筆に残っている ＳＡＳをティッシュペーパーなどで拭き取り、トルエンで洗う。

 ⑪ 約２０分後２層目の表面の硬化を確認して３層目を同様に塗る。筆に残っているＳＡＳをティ ッシュペーパーなどで拭き取り、トルエンで洗う。

 ⑫ 約３０～４０分後３層目の硬化を確認する。（この時点ではほぼ硬化したような感触だが、少し 柔らかさがある）

 ⑬ ＪＡＳ Ａ剤 1：Ｂ剤 2・・・・40ｇ：80ｇ程度を計量しよく混ぜ合わせてからＳＡＳを塗った 表面にヘラを使用して盛るように塗る。全体に塗り終えたら、表面にワセリンを塗って表面の トゲトゲしたところを整える。
![IMG_3219.JPG](https://qiita-image-store.s3.amazonaws.com/0/305521/1571fa71-6caa-a424-a75d-291cd1266a76.jpeg)

 ⑭ 約９０分静置する。

 ⑮ ＪＡＳの硬化を確認したら、型を分割する。

 ⑯ 型を分割したら中の油粘土を取り出す。型内に残った油粘土をトルエンを含ませた筆で油粘土 を溶かし、拭き取り型内の清掃をする。 

⑰ 型製作完了。 
![IMG_3233.JPG](https://qiita-image-store.s3.amazonaws.com/0/305521/2f907c39-b47a-53e2-7945-531432de9085.jpeg)


しかし、
100円均一の油粘土を使用したためJASの熱硬化で溶けてしまい、A面・B面を取り外すことが出来ずに無残な姿になってしまいました。
また、SASの量が足らず淵からボロボロと崩れて行ってしまい上記の写真のようなどんどん割れて行ってしまいました。

次回は熱硬化で溶けない粘土を使って挑戦していきたいと思います。
スーパークラスの val から サブクラスの val は参照できない

以下のコードを見てください。
出力結果はどうなるでしょうか。

```scala
abstract class Super {
  val needOverride: Int
  val sum: Int = needOverride + 1
}

class Sub extends Super {
  val needOverride: Int = 1
}

println((new Sub()).sum)
```

答えは「1」です。
「2」だと思った方は多いのではないでしょうか。
（簡単だったらすみません）

`val` はコンストラクタ実行時に初期化されます。
コンストラクタはスーパークラス→サブクラスの順で実行されるため、`sum` の初期化時には `needOverride` は初期化されておらず、 `Int` のデフォルト値である `0` が代入されているため、このような挙動になります。
解決策は `sum` を `lazy val` （または `def` ）にすれば良いです。

考えてみれば当然の理屈なのですが、この挙動はコンパイルエラーや例外にならないので気付きづらいです。
恥ずかしながら私はちょっとはまってしまったので、同じ症状で困っている方のお役に立てれば幸いです。
Windows 10にChocolateyを使って、Dockerクライアントを入れたときにハマった話

# 環境
OS:Windows 10 1803
PowerShell：5.1.17134.228


# 環境構成
[ここ](https://qiita.com/Arturias/items/e13e3ecc39261a258bef)の人と
ほぼ同じ構成で作成しようとしています。
ただし、Docker サーバがLinuxではなく、Windows Docker です。
あとはAWSやAzureのようなクラウド環境ではなく、Dockerサーバは実機。
Dockerクライアント環境はとある仮想環境。

# Chocolateyのインストール
とりあえず、[ここ](https://qiita.com/Arturias/items/e13e3ecc39261a258bef)に
したがってPowerShellでコマンドを実行。が、下記のようなエラーに。

![インストールエラー](https://qiita-image-store.s3.amazonaws.com/0/170075/44b708ab-c923-6f21-9f81-6945276c8ab8.png)

#原因調査
メッセージからパッケージプロバイダ(?)が原因と推測。
Chocolateyというパッケージプロバイダが実際にあるのか、名前が変わってないかを調べる必要がある。
ということで、以下を実行。
` Find-PackageProvider`

![find-provider.png](https://qiita-image-store.s3.amazonaws.com/0/170075/5310df3e-db49-313d-d8b9-00718562dd5d.png)

無いね。でも、ChocolateyGetがあるね。

# 2018.10.23現在のインストール手順
1. Chocolateyのパッケージプロバイダのインストール  
`Install-PackageProvider ChocolateyGet`
2. Chocolateyのパッケージプロバイダがインストールされたかどうかの確認 
`Get-PackageProvider -Name ChocolateyGet`
![choco_packageprovider.png](https://qiita-image-store.s3.amazonaws.com/0/170075/c98e61e7-c1aa-82b1-d7a3-a0a324a3c367.png)
 
3. Dockerクライアントのインストール  
`Install-Package docker -providername ChocolateyGet`
インストール途中で各種警告がでるけど、そこはよしなにやってください。

#備考
プロキシ環境下は最初に認証情報をセットしておく必要があります。
  
プロキシURIのセット
`$ProxyUri = "http://proxy.example.com:8080"`

プロキシ認証情報のセット
`$ProxyCred = Get-Credential`
注)ダイアログが出ます。

認証情報はエンコードとか気にしだすとめんどくさいので、
ダイアログを出して、素直に入力したほうが気持ち的にも楽です。

※自分用メモですが、何かあればコメントをお願いします。
簡易メモ：IntelliJでデータベースからEntityクラスを自動生成

###自動生成しないと厳しいTableもある。
本当に簡易メモです。
いつか画像つきでご紹介できればします。
###やりかた
1. Databseのツールメニューを選ぶ。
2. 自動生成したいデータベースを選択する。
3. 自動生成したいテーブルを選択する。
4. 右クリックする。
5. Scripted Extensionを選択。
6. Gerated POJOs.groovyを選択。
7. javaファイルを生成したいディレクトリーを選択。

###メモ
アノテーションとかはつけてくれない。
serialisableは実装していない。
GetterとSetterは生成してくれている。
勉強が足りていないのでまだまだいろいろ調べている最中です。
OpenCVで描画してみよう



# はじめに

* [前回のインストール](https://qiita.com/tifa2chan/items/5d98c04fe42f7a7fbd76)後から、描画を試してみました
* 今後、随時追加していくかもしれません

# 色について

* OpenCVは、RGBではなくBGR（青、緑、赤）の順番です
* 色の指定をするときは注意が必要です

# 画像のグレー変換

2種類あり、方法2のほうがよく使われているようです

* 方法1

```python
import cv2 

img = cv2.imread("img.jpg",0)
cv2.imwrite("gray.jpg",img)
```

* 方法2

```python
import cv2 

img = cv2.imread("img.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite("gray2.jpg", gray)
```

# 直線の描画

* **line**関数を使います
* (x0, y0)、(x1, y1)のように座標を指定し、線を引きます

```python
import cv2
import numpy as np

# 画像ではなくまっさらな下地となる200x300の黒い画像を生成
# zerosの引数がheightが先になるので注意
height = 300
width = 200
img = np.zeros((height, width, 3), np.uint8)


# 線を引く（線を引く画像、座標、線の色、線の太さをパラメータに指定）
# 細めの赤線
img = cv2.line(img,(0,0),(width,height),(0,0, 255),1)
# 太めの青線
img = cv2.line(img,(width,0),(0,height),(255,0, 0),5)
cv2.imwrite("line.jpg", img)
```

![line.jpg](https://qiita-image-store.s3.amazonaws.com/0/92328/56dd34e7-d78c-c0d4-9e30-43e7a9742f72.jpeg)


# 長方形の描画

* **rectangle** 関数を使います
* 左上の座標と右下の座標の指定します

```python
img = cv2.rectangle(img,(10,20),(150,60),(255,255,0),3)
```

# テキストの追加

※ 日本語には対応していません

* **putText** 関数を使います
* fontはいくつか用意されています
* 座標は、テキストの書き始めの左下の位置
* cv2.LINE_AA は線の種類で、これ推奨

```python
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'ABC',(10,180),font,2,(255,0,255),3,cv2.LINE_AA)
```

# 長方形とテキストの組み合わせ

* 上記を組み合わせてみます

```python
import cv2
import numpy as np

# 画像ではなくまっさらな下地となる200x300の黒い画像を生成
# zerosの引数がheightが先になるので注意
height = 300
width = 200
img = np.zeros((height, width, 3),np.uint8)

# 長方形（水色の長方形）
img = cv2.rectangle(img,(10,20),(150,60),(255,255,0),3)

# 文字 （線の種類の指定ありなしで、比較すると微妙に違いが見える）
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'ABC',(10,125),font,2,(255,0,255),3)
cv2.putText(img,'ABC',(10,180),font,2,(255,0,255),3, cv2.LINE_AA)

# 長方形の中に文字をいれる（文字は左下の座標のため、ややずれてるのがわかる）
img = cv2.rectangle(img,(10,220),(140,270),(255,255,255),2)
cv2.putText(img,'12345',(15,250),font, 0.75,(255,255,255),2)
cv2.imwrite("rect_text.png", img)

```

![rect_text.png](https://qiita-image-store.s3.amazonaws.com/0/92328/4607b96a-c841-941c-a4dc-52b72d63a9b2.png)

# 白紙画像

OpenCVの描画とは直接関係がないですが、下地画像を黒ではなく白にすることもできます。

* 上記では、**np.zeros**関数で下地が黒の画像を作りましたが、**np.full**関数を使うと白にできます
* np.zerosは、すべてをゼロで埋めていましたが、np.fullでは初期値に255を指定します。   
  255ではなく、127あたりにすると灰色になります。

```python
import cv2
import numpy as np

height = 300
width = 200
img = np.full((height, width, 3), 255, np.uint8)
cv2.imwrite("white.png", img)
```
docker-compose.ymlでDockerfileを指定したい

## 概要

```docker-compose.yml``` で複数コンテナの定義をする際に、Dockerfileは別にしたい！と調べてたらできたのでメモ。

## 手順

```sh
> mkdir 任意のディレクトリ
> cd 任意のディレクトリ
> touch docker-compose.yml
> touch Dockerfile1
> touch Dockerfile2
```

```build.dockerfile``` で指定ができるみたいです。

```yaml:docker-compose.yml
version: '3'

services:
  container1:
    build:
      context: .
      dockerfile: Dockerfile1
  container2:
    build: 
      context: .
      dockerfile: Dockerfile2
  container3:
    build: .
```

```txt:Dockerfile1
FROM python:3.6
```

```txt:Dockerfile2
FROM node:latest
```

コンテナを起動してみます。

```sh
> docker-compose up --build

Creating network "任意のディレクトリ_default" with the default driver
Building container1
Step 1/1 : FROM python:3.6
 ---> 4f13b7f2138e
Successfully built 4f13b7f2138e
Successfully tagged 任意のディレクトリ_container1:latest
Building container2
Step 1/1 : FROM node:latest
 ---> b064644cf368
Successfully built b064644cf368
Successfully tagged 任意のディレクトリ_container2:latest
Building container3
Step 1/1 : FROM python:3.6
 ---> 4f13b7f2138e
Successfully built 4f13b7f2138e
Successfully tagged 任意のディレクトリ_container3:latest
Creating 任意のディレクトリ_container3_1 ... done
Creating 任意のディレクトリ_container2_1 ... done
Creating 任意のディレクトリ_container1_1 ... done
Attaching to 任意のディレクトリ_container1_1, 任意のディレクトリ_container2_1, 任意のディレクトリ_container3_1
任意のディレクトリ_container1_1 exited with code 0
任意のディレクトリ_container2_1 exited with code 0
任意のディレクトリ_container3_1 exited with code 0
```

やったぜ。


## 参考

docker-compose コマンドまとめ
https://qiita.com/wasanx25/items/d47caf37b79e855af95f
VSCodeでVim風のカーソル移動

# 【背景】
[Sublime Textでvim風・Emacs風カーソル移動](https://qiita.com/Arvelt/items/7c6f6c1014d5f33a0cc7)

この記事を参考にSublimeでVim風のカーソル移動を設定していたのですが、VSCodeでもこの設定をしたい。カーソル移動しんどい、でもVim操作をするほどVimを使ってないという問題がありました。
Key設定なんて調べればわかるものですが、上記のような記事に助けられた身としては非常に手間が省ける。

というわけで
# 【目的】
VSCodeでVim風のカーソル移動を設定

# 【方法】
1. `⌘+K,⌘+S`でKeyboard Shortcutsエディターを開き、`keybindings.json`をクリック
2. 下記のコードを追加して保存し、キーバインドを上書きする。

<Vim風>

``` configuration
[
    { "key": "ctrl+l","command": "cursorRight","when":"textInputFocus" },
    { "key": "ctrl+h","command": "cursorLeft","when": "textInputFocus" },
    { "key": "ctrl+k","command": "cursorUp","when": "textInputFocus" },
    { "key": "ctrl+j","command": "cursorDown","when": "textInputFocus" }
]
```
同様にEmacs風にもできます。

なお

* "key": 割り当てるキー
* ”command”: 実行するコマンドの名前
* "when": キーがアクティブになるときの条件

です。

# 【参考】
(Sublimeの設定とキーバインドを入れたので初期設定かわかりませんが)
初期で`ctrl+j`,`ctrl+k`,`ctrl+h`には他のショートカットが割り当てられていました。
使いたいものがあれば他の割り当てを推奨します。
また念の為、以前割り当てられていたショートカットを外す記述もしました。

```configuration

    { "key": "ctrl+j","command": "-editor.action.joinLines","when": "textInputFocus"　},
    { "key": "ctrl+k","command": "-deleteAllRight","when":"textInputFocus" },
    { "key": "ctrl+h","command": "-deleteLeft","when": "textInputFocus" },
  
  //ctrl+kに割り当てられてたdeleteALLRight(カーソルの右側を全消し)を使いたかったのでctrl+deleteに割り当てました
    { "key": "ctrl+delete","command": "-deleteRight","when": "textInputFocus" },
    { "key": "ctrl+delete","command": "deleteAllRight","when": "textInputFocus" }
```

# 【結論】
Sublimeのときと同じ要領でキーの割当が可能であるが上書きすることになるので、必要なショートカット華道家の確認が必要。
ショートカットキーは`⌘+K,⌘+S`ででてくるKeyboard Shortcutsエディターで探せます。
Kernel-EventTracing　新しいイベントは記録されません。 の対処方法……

```
リアルタイム セッション "EventLog-ForwardedEvents" のバッキング ファイルが最大サイズに達しました。
このため、空き領域ができるまで、このセッションに新しいイベントは記録されません。
このエラーは、多くの場合、リアルタイム コンシューマーがない状態でトレース セッションをリアルタイム モードで開始した場合に発生します。
```
とエラーメッセージが出て
困っているので対処方法をメモらせて頂きます。
php-master-changes 2018-10-22

今日は sapi/fpm の微修正、ext/date のタイムゾーンDBのデータ更新、動的プロパティでの可視性チェック修正があった！

GitHub の具合が悪かったせいか Derick がガチャガチャやってた形跡あるけれど、最後のコミットだけ採用した

# 2018-10-22
## bukka: Fix arginfo and clean up fpm_get_status
- https://github.com/php/php-src/commit/c8febbe0396d8d2a3b09480beeb82845ca71dc1f
- [7.3~]
- sapi/fpm で、fpm_get_status() の arginfo を修正

## derickr: Updated to version 2018.6 (2018f)
- https://github.com/php/php-src/commit/fd3d2755dce4856d9fd41caca61c2dbbcab1a0d8
- ext/date で タイムゾーンDB のデータを更新

## nikic: Fix accessibility checks for dynamic properties
- https://github.com/php/php-src/commit/149e6aaa99cf9b94987fe23b999443ca56db1caf
- 動的プロパティでの可視性チェックの修正
- 以前やった[隠蔽プロパティの修正](https://qiita.com/sj-i/items/287aa832fbfc1307830e#nikic-fix-foreachget_object_vars-for-shadowed-properties)で[残っていた問題](https://github.com/php/php-src/pull/3573#issuecomment-428737944)の解消
- 親の private プロパティを子の同名動的プロパティで隠蔽する際は漏れ出してしまっていた
エンジニアやデザイナ向けに「デザイン」という言葉を整理してみた結果エンジニアの幅が広がる話

# デザインって何ですか......？

「**デザイナー**」というと「**グラフィカルなUIなどをデザインする人**」って意味にとられますよね？
でも**ソフトウェアエンジニア**だって**システムのデザイン**をします。

そんな「**デザイン**」というあまりにも曖昧な言葉が世の中にあります。

白黒はっきりつけたがる技術屋にとってはあまりにも気持ちの悪い言葉なのでちょっと整理してみました。

> それなりにリサーチした結果ではありますが、「あれ」「それ」みたいな単語が様々な意味を持つように、「デザイン」みたいな一般用語は文脈によってさまざまな意味を持ってしまいます。なのでこれが必ずしもすべての状況においての正解ではないないです。ただ考え方の拠り所にはなるかと思います。

## 図解

みなさん大好きUMLでの整理です。
わたしはオブジェクト指向が大好きなので、情報アーキテクチャ的な分類をするときもOOに頼ることが多いです。

![design_class_diagram.png](https://qiita-image-store.s3.amazonaws.com/0/33095/31b6d3b8-3f82-f57d-1057-8f1403e794f3.png)


## 目的による大別

何を目的にするかでの分類です。

「**問題解決**」と「**問題提議**」の2種類に大別されます。
（上図の左側のツリーです）

問題解決を目的とした活動は「**デザイン**」と呼ばれます。

なにも枕詞をつけないで「**デザイン**」というと今であれば「**ビジュアルデザイン**」いわゆるUIデザインやグラフィカルなデザインを指すことが多いです。ただ、ITなどの技術を使って問題解決を目指す「**システムデザイン**」というものも存在します。

対して、世の中に**問題提議**をする、問いを投げかけることを目的とした活動は、一般的に「**アート**」と呼ばれることが多いです。


## 目標達成のための思考法・アプローチ・手法による大別

次に、目的は何であれ、手法・思考法・アプローチとしてのデザインも存在します。

こちらも「**問題解決**」と「**問題提議**」の2種類に大別されます。
（上図の右側のツリーです）

対面している問題に対して**その問題を明らかにすることで解決に近づける**そのためにユーザインタビューやヒューリスティックな調査を行う手法としてデザイン思考やHCD（人間中心設計）があります。
データを中心としたサイエンティフィックな手法としてはデータ分析・統計・ロジカルシンキングのようなものがあります。

逆に、対面している問題に対して**問題自体を新たに投げかけることで解決に近づける** 手法・アプローチもあります。スペキュラティブデザインなどがあります。

## 「デザイン」を整理して見えてきた、目的 と 手法 は別であるという気づき

例えば、「交通渋滞」という明らかな課題があったとしてその交通渋滞を解決するためにどのようなアプローチをとるか？

### 例. 交通渋滞 - デザイン的な目的とアプローチ

エンジニアリング的なデザインの場合はこんな感じです。

```
目的： 交通渋滞を解決したい
手法： 交通量を調査して道幅や信号を調整する
```

ビジュアル的なデザインの例ではこうなるでしょうか。

```
目的： 交通渋滞を解決したい
手法： 交通標識を見やすくする、街路樹などによる心理的なイライラの解消
```

### 例. 交通渋滞 - アート的な目的とアプローチ

「交通渋滞を解決するとはどういうことだ？」
「交通渋滞とは何だ？」
「そもそもなぜ我々は移動するのか？」

そういうことを考えさせることによって、交通渋滞を根本から問いなおします。ひょっとしたら人間にとって「交通」なんて必要がなく、そもそも交通渋滞なんて不要なものだったということに気付くかもしれません。

```
目的： 交通渋滞とは何か？という問題提議
手法： 問題についての気づきを与えるためのアートイベント、アート展示
```

### 例. 交通渋滞 - デザイン（問題解決）目的に対してのアート的なアプローチ

上の例２つの組み合わせなので省略しますが、実現したいのは「問題解決」であったとしてもそのアプローチとして「問題提議」を行うこともあり得ます。

わかりやすい例では、ダブルダイヤモンドは「問題解決」のために改めての「問題提議」を行い、そこから「問題解決」を行っていきます。


# まとめ

デザイン、アート、サイエンス、色々な言い方がありますが、デザインという言葉を使わずにロールと結び付けることで以下のような説明ができそうです。

- 一般的ないわゆるエンジニアは、「エンジニアリングによる問題解決」を目的として、「Logical thinkingに代表されるデータ中心で論理的」なアプローチを行うロールです。

- 一般的ないわゆるデザイナは、「ヴィジュアルデザインによる問題解決」を目的として、「デザイン思考に代表されるユーザ中心」なアプローチを行うロールです。

- 一般的ないわゆるアーティストは、「問題提議」を目的として、「自分中心、コンセプト中心」なアプローチを行うロールです。

曖昧な言葉を曖昧なままに使うのはやはり気持ち悪いもので整理してみましたがこのように分けていくと意外とシンプルな構造でした。

まとめてみて思ったのは、別に「エンジニアだからビジュアルデザインはやらない」とかではなく、逆に「エンジニアリング的な思考で考えているけれどアート的な発想がかけているのでは？」と言った気づきを得られる１つの軸として今回の整理は越境をするための大きな指針になるのでは？という気づきでした。

> ボタンの二度押しの抑止をするのにシステム的な仕組みを入れるのもよいですが、「２回押したら地獄に落ちる」とおどろおどろしく書いておくのも良いですし、「なぜ２回押すのか？」という問題提議からボタンを押さない仕組みを考えるのも良いと思います。
C++ Builder XE4 > 起動している多数のソフトのキャプションを取得 v0.1 (+ 別の方法に関する追記)

```txt:動作環境
C++ Builder XE4
```

起動している多数のソフトウェアのキャプションを取得してみる。

### 参考

- [Win32API ウィンドウを検索する FindWindowEx](http://d.hatena.ne.jp/s-kita/20121218/1355839657) @ s-kitaの日記さん

情報感謝です。

### 実装

- 一つ目のサンプルコードをXE4で動くようにコードを修正
    - TMemoへ出力
    - UnicodeStringに対応
- 階層を定義し、1階層下までを表示

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <Windows.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------

static const int kMaxDepth = 1; // チェックする階層数

void TForm1::EnumetareWindows(HWND hWndParent, int depth)
{
	wchar_t szBuff[512] = {0};
	GetWindowText(hWndParent, szBuff, 512);

	if (szBuff[0] != 0x00) {
		if (depth <= kMaxDepth) {
			String msg = IntToStr(depth) + L":" + String(szBuff);
			Memo1->Lines->Add(msg);
		}
	}

	HWND hWndChild = FindWindowEx(hWndParent, NULL, NULL, NULL);
	if (hWndChild == NULL) {
		return;
	}

	do {
		EnumetareWindows(hWndChild, (depth+1));
	} while ( (hWndChild = FindWindowEx(hWndParent, hWndChild, NULL, NULL)) != NULL );
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
	Memo1->Lines->Clear();

	HWND hWndParent = GetDesktopWindow();
	EnumetareWindows(hWndParent, /*depth=*/0);
}
//---------------------------------------------------------------------------
```

### 実行

- C++ Builder XE4起動状態
- ビルドしたソフト起動状態
    - Project1.exe
- Tera Term起動状態
- メモ帳起動状態


![2018-10-23_09h03_12.png](https://qiita-image-store.s3.amazonaws.com/0/32870/69a0c0af-c56d-66b3-4917-2ba7af8704bb.png)

### 備考

余分なウィンドウも捉えられるが、フィルタ条件を考慮すれば、希望のソフトのキャプションを取得できるだろう。


### 別の方法 > EnumWindows()
(追記 2018/10/24)

下記の記事を作る中、EnumWindows()を使う方法があると知りました。

- [C++ Builder XE4 > 起動中のソフトウェアのうち、同じフォルダに含まれる実行ファイルと関連があるものだけ見つける > v0.1:EnumWindows実装, v0.2: ビルトイン?EnumWindows()使用](https://qiita.com/7of9/items/bdeb42c0a11e731979fd)
git 追跡によるコマンドの省略

リモートブランチとローカルブランチの追跡(tracking)を行っておくことで、gitコマンドの省略ができます。　

## 省略例
- git pull origin ${branchName}  ->  git pull
- git push origin ${branchName}  -> git push
- git fetch origin -> git fetch

## 追跡設定方法
- git checkout ${branchName}  
リモートで新規に作成したブランチをローカルに落として来る際に、checkoutを行うと下記の表示のように
`originから落としてきて、追跡を設定しました。`と出ます。(git fetchしてからでお願いします。)

```
Branch 'test' set up to track remote branch 'test' from 'origin'.  
Switched to a new branch 'test'
```

- git push --set-upstream origin test  
pushのタイミングで`--set-upstream`オプションにより追跡を設定します。  
ローカルで新規に作成したブランチを`git push`すると下記のように表示され、追跡を促進されています。

```
fatal: The current branch test-t has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin test
```


`git pull origin ${branchName} ,git push origin ${branchName}`としていると意外と気づかない省略方法です。  
追跡に関しては、[参考資料](http://snowlong.hatenablog.com/entry/2015/03/12/212455)を参照してください。


## 加えて
[gitコマンドの省略](https://qiita.com/peccul/items/90dd469e2f72babbc106)も行うととても強力になります。  

### 例
1. `gf`(git fetch)
2. `gc ${branchName}` (git checkout) <- [ブランチのTAB保管の設定が必要](https://qiita.com/panti310/items/9e266a2913a8558f4679)です。, `gp`(git pull)
3. 作業
4. `gs`(git status), `gl`(git log option)
5. `ga .`(git add)
6. `gco -m "commit message"`(git commit)
7. `gpu`(git push)
Expressで簡易的にAPIを作成する

## 概要
簡易的なAPIを作りたいなって人向けです。

## 使うモジュールをインストールする

```
yarn add express body-parser faker
```

## テストデータの作成
```js:createUser.js
const faker = require("faker/locale/ja");
const fs = require("fs");

const users = [];
const maxLength = 100, max = 85, min = 16;

for (let i = 0; i < maxLength; i++) {
  const name = faker.name.lastName() + ' ' + faker.name.firstName();
  users.push({
    id: i + 1,
    name: name,
    age: Math.floor(Math.random() * (max + 1 - min) ) + min
  })
}

fs.writeFile('users.json', JSON.stringify(users), () => {
  console.log("users.jsonを作成しました");
});
```


## 土台を作る
```js:server.js
const express = require("express");
const app = express();
const fs = require("fs");
const bodyParser = require("body-parser");
const users = require("./users.json");

const port = 3000;

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

app.listen(port, () => {
  console.log("server is running");
})
```

## 一覧の取得
```js
app.get('/users/', (req, res) => {
  res.json(users);
});
```

## １つだけ取得
```js
app.get('/users/:id', (req, res) => {
  const id = req.params.id;
  const user = users.filter(user => {
    return user.id == id;
  });
  res.json(user);
}):
```

## 保存する
```js
app.post('/users/', (req, res) => {
  const userID = users.map(user => {
     return user.id;
  });
  users.push({
     id: Math.max(...userID) + 1,
     name: req.body.name,
     age: req.body.age
  });
  fs.writeFile('users.json', JSON.stringify(users), () => {
    res.json(users);
  });
});
```

## 更新する
```js
app.put('/users/:id', (req, res) => {
  const id = req.params.id,
        name = req.body.name,
        age = req.body.age;
  
  // 更新しないデータ
  const newData = users.filter(user => {
    return user.id != id;
  });

  // 更新するデータ
  const alterUser = users.filter(user => {
    return user.id == id;
  })

  alterUser[0].name = name;
  alterUser[0].age = age;
  newData.push(alterUser[0]);

  fs.writeFile('users.json', JSON.stringify(newData), () => {
    res.json(newData);
  });
});
```

## 削除する
```js
app.delete('/users/:id', (req, res) => {
  const id = req.params.id;

  const newData = users.filter(user => {
    return user.id != id;
  });

  fs.writeFile('users.json', JSON.stringify(newData), () => {
    res.json(newData);
  });
})
```

## package.jsonの作成
```
npm init -y
```

## npm-scriptsを編集する
```json:package.json
  :
"scripts": {
  "start": "node createUser.js && node server.js"
}
  :
```

## まとめ・反省点
もっと簡単にAPIを作成したいなって方は、[json-server](https://github.com/typicode/json-server)がオススメです。

回りくどい方法じゃなく、[Nedb](https://github.com/louischatriot/nedb)や[lowdb](https://github.com/typicode/lowdb)などのJSON型のデータベースを使えばよかった。
assert_selectを調べたときのリンク集

[Rails テスティングガイド](https://railsguides.jp/testing.html)

>assert_selectには2つの書式があります。

>assert_select(セレクタ, [条件], [メッセージ])という書式は、セレクタで指定された要素が条件に一致することを主張します。セレクタにはCSSセレクタの式 (文字列) や代入値を持つ式を使用できます。

>assert_select(要素, セレクタ, [条件], [メッセージ]) は、選択されたすべての要素が条件に一致することを主張します。選択される要素は、element (Nokogiri::XML::Node or Nokogiri::XML::NodeSetのインスタンス) からその子孫要素までの範囲から選択されます。

要素やセレクタ、エレメントがもやっとしてきて、調べる。

[サルワカ](https://saruwakakun.com/html-css/reference/selector)

>CSSの基本文法はセレクタ・プロパティ・値の3つからなります。

>要素は開始タグ〜終了タグまでのかたまりを指します

>	
ある要素の中に入る要素は「子要素」と呼ばれます。その子要素をはさんでいるもの＝「親要素」ですね。たとえばこの図ではpタグが子要素、divタグが親要素になります。

[Rails RecipeBookはてな版](http://rails-recipebook.g.hatena.ne.jp/rrbk/20071001/1191254441)

assert_selectの例文がいっぱい。

[サルワカ](https://saruwakakun.com/html-css/basic/ul-ol-li)

ul・ol・liタグ

ul：黒ポチの箇条書き
ol：番号付きの箇条書き

ちなみにulはUnordered List（順序のない箇条書き）の略、olはOredered List（順序ありの箇条書き）の略です。

[とほほのWWW入門](http://www.tohoho-web.com/html/memo/elem.htm)

要素やエレメントの説明。

>多くのタグは、 開始タグ(start tag) と 終了タグ(end tag) で囲みます。

>HTMLの要素
要素(element) の概念は最初はちょっと難しいかもしれませんが、下の図のそれぞれの枠が要素だと思ってください。html要素の中に head要素と body要素があり、head要素のの中には title要素が、body要素の中には h1要素と p要素があります。p要素の中には span要素や strong要素があります。この要素の始まりや終わりを示すのがタグです。

[Qiita【Railsメモ】](https://qiita.com/TakahitoNakashima/items/b439126cd1ee302586d7)

>assert_selectとは
アプリケーションのビューのテストを行う際に使うアサーションメソッド

Rails テスティングガイドを深入りしていって、

assert_select(要素, セレクタ, [条件], [メッセージ])

が出てきたあたりで一時間程いろいろ検証したが今は理解しきれなかったので一旦保留。
要素の引数に要素っぽいのを入れてみたけど、ことごとくエラーになる。。。
.erbでも.vueでもEmmet記法で爆速コーディング (2022/10/31 追記)

### 2022/10/31 追記

VS CodeにおけるVueの開発には、2022年時点でVolarという拡張が公式として出ているのでそちらを使ってください。

https://marketplace.visualstudio.com/items?itemName=Vue.volar

下記の記事は筆者の知識が不足していた時点で執筆したもののため、参考にしないでください。

---

# 対象の人
 - VSCode使っている人
 - HTML、CSSのコーディングする人
 - 楽をしたい人

# Emmet記法とは
Emmet記法については下記のリンクを見てもらうのが一番早いと思います。
[Emmet in Visual Studio Code](https://code.visualstudio.com/docs/editor/emmet)

簡単に説明すると
`header.navbar>ul.menu>li#item$*4`
と入力して末尾でtabを入力すると下記のHTMLが出力されます。

~~~html
<header class="navbar">
  <ul class="menu">
    <li id="item1"></li>
    <li id="item2"></li>
    <li id="item3"></li>
    <li id="item4"></li>
  </ul>
</header>
~~~
HTMLタグを指定しない場合は自動的にdivタグが生成されます。
`.container>.row>.col*3`

~~~html
  <div class="container">
    <div class="row">
      <div class="col"></div>
      <div class="col"></div>
      <div class="col"></div>
    </div>
  </div>
~~~

# 標準サポートされていない拡張子でEmmet記法を有効にする
VSCodeの初期設定だと.erbや.vueファイルではHTMLやCSSのEmmet記法が使えませんが、設定を記述すれば使えます。
基本設定→設定→`setting.json`を開き、`emmet`で検索すると下記の項目が見つかると思います。

~~~json
  "emmet.includeLanguages": {},
~~~
これを編集して右側のエディタに下記のように書き加えましょう。

~~~json
"emmet.includeLanguages": {
    "erb": "html",
    "vue": "html",
    "vue": "css",
}

~~~

これでEmmet記法が使えます。これで快適に爆速コーディングできます。

## 補足
RubyMineでは標準で.erbファイルのEmmet記法をサポートしています。
iOSアプリにAdMobで広告を表示する

AdMobでアカウント作成は一瞬なので、省きます。

全画面型
<img width="883" alt="スクリーンショット 2018-10-20 13.25.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/255984/de39de66-e94e-850e-d888-b493cdd47b7e.png">
を、表示させます。

---
**AppDelegateでアプリIDを読み込む**

```Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    GADMobileAds.configure(withApplicationID: "アプリID")
return true
```
本番用のIDを使用しないように
それとユニットIDではなく、アプリIDです。

---

**GoogleMobileAdsをimportして
GADInterstitial!型の変数を用意
Delegateも宣言しておきましょう。**
GADInterstitial!型の変数を用意っていい方あってます？

```Swift
import GoogleMobileAds

class IPVideoChatViewController: UIViewController, GADInterstitialDelegate {

    var interstitial: GADInterstitial!

}
```

---
**ユニットIDで広告を指定して、初期化**

```Swift
func createAndLoadInterstitial() {
        interstitial = GADInterstitial(adUnitID: "ユニットID")
        interstitial.delegate = self
        interstitial.load(GADRequest())
    }
```

ここも、テスト用IDを使用しましょう。

---
<img width="863" alt="スクリーンショット 2018-10-20 13.46.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/255984/78b5ee40-7749-9380-61e5-17901b5f77c8.png">
だそうですので、

```Swift
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
        createAndLoadInterstitial()
    }
```
で、広告が消される度にinterstitialDidDismissScreen(_ ad: GADInterstitial)を呼んで、初期化しておくと再表示できます。

---
####記事を書いてみて
広告表示の手順を整理するつもりで書きましたが、初学者が見るといまいち分かりづらそうな記事になったかなという発見がありました。
次回は実装手順と注意点、勘所を分けて書こうかと思います。
ChromebookにLinux仮想マシンのCrostiniを入れてみた

# はじめに
ChromeOSでCrostiniってLinuxアプリが使えるようになったって話を聞いて、気になってたけど自分のマシンで使えるかよくわからなかったし、放置してたんだけど、気が向いて調べたら、自分のマシンでも使えることがわかったので、入れてみた。
Linuxアプリって何？って思ってたけど、Linux仮想マシンが入ってターミナルでいろいろできるようになった感じやった。apt-getでいろいろ入れられる。開発者モードにしなくてもいいので、ChromeOSの平和なUIのままLinux的なことができる。また一歩Macに近づいたんじゃないか。

# 環境構築
AcerのCB3-431っての使ってる。
入れられるか調べてみたら、Redditで入れられたって書いてる人いたので試してみた。

環境構築については、下記サイトに詳しくのってた。
チャネルってのを変えると入れられる。Crostiniってまだベータ版やったのね。
Developerチャネルじゃなくてもいいかと思って、Betaチャネルにしてみた。

[Samsung Chromebook Plusで新機能Crostiniを使ってLinux仮想マシンを試してみた | Chrome速報](https://chromesoku.com/linux-on-chromebook-crostini/)

チャネルを変えたらExperimental Crostiniってのが出てきてEnableにできるようになった。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/184221/030223b2-5240-207a-d8a3-f27c94c16c00.png)
![Screenshot 2018-10-23 at 4.34.09 AM.png](https://qiita-image-store.s3.amazonaws.com/0/184221/40419910-a214-3832-96b3-bcd7d8a09a8b.png)

# 確認
再起動すると、Terminalってアプリが入ってた。
デフォルトbash。apt-getもできる。UbuntuとRaspbian使ってるので、Debian系うれしい。
sshもできていい感じ。pingが入ってたいのはなぞ。
ChromebookにEmacsをかんたんに入れられていい感じ。
homeディレクトリはMy filesのLinux filesってところにできた。
/ディレクトリにいろいろあるけど、ここはどこ？って感じ。うまいことしてくれてるんやろなぁ。
storageは1.6GB使ってるらしい。まあまあ小さいけど、元が小さいからapt-get installばっかしてると、空きなくなりそう。

```
xxx@penguin:~$ echo $SHELL
/bin/bash

xxx@penguin:~$ sudo apt-get update
Hit:1 http://security.debian.org/debian-security stretch/updates InRelease
Ign:2 http://deb.debian.org/debian stretch InRelease
Hit:3 http://deb.debian.org/debian stretch Release 
Ign:4 https://storage.googleapis.com/cros-packages/70 stretch InRelease
Hit:5 https://storage.googleapis.com/cros-packages/70 stretch Release
Reading package lists... Done
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/184221/9d07ca6d-0db9-7fd0-dd75-4be8d09f0fa8.png)

![Screenshot 2018-10-23 at 4.50.23 AM.png](https://qiita-image-store.s3.amazonaws.com/0/184221/e97163e7-a9d3-a313-e2d7-feec31991d17.png)
![Screenshot 2018-10-23 at 4.45.56 AM.png](https://qiita-image-store.s3.amazonaws.com/0/184221/36da41ed-8566-e352-ee39-884cc43e7ddb.png)

# おわりに
Crostiniって、どうやって動いてんのかな？コンテナ？気になる。
結構、安全そうな環境にいい感じにバーチャルでLinux入れられた。うれしい。
ChromeOSを開発者モード？で使うのは嫌だったのでとてもうれしい。
Macのメリットがまた一つ減った気がする。持ってないけど。
Go言語のJSON/Unmarshalはcase insensitiveに変数を展開するが名前がカブった時どうなるか？

# 簡単に、Go言語のJSON to struct変換の話

Goは標準APIでJSON文字列と構造体を相互変換できる。

標準APIでは、Go→JSON文字列の変換を[Marshal](https://golang.org/pkg/encoding/json/#example_Marshal)、JSON文字列→Go世界の変換を[Unmarshal](https://golang.org/pkg/encoding/json/#example_Unmarshal)と呼ぶ。
[API Reference](https://golang.org/pkg/encoding/json/#Unmarshal)やサンプルのとおり、JSON文字列→構造体にunmarshalする際、JSON側のオブジェクトのキーと、Go側のstructのメンバー変数の変数名が一致していれば、その変数に値が代入される。
そして、リファレンスに記載されているとおり、キーと名前の一致についてはCase Insensitiveで比較する。

この実装が正しいかどうかはRFC7159にも書いておらず（JSON自体の定義なのでそれはそう）、Case Sensitiveな実装もあるし、例えば[JSON-RPCだと仕様上case-sensitive](https://www.jsonrpc.org/specification)だそう。

# 疑問

ここから先は、現実的には基本的にそんな使い方はしないと思われるため、あくまで実験です。

Go言語はソースコード的にはcase sensitiveだ。
structのほうはCase sensitiveなのに、unmarshalがCase insensitiveだと、キーが重複するとどの変数に値が入るのかリファレンスからわからないが、一体どうなるのか。

検証のため以下のような実験してみる。

# 実験

## 正常系

とりあえず普通の使い方をする。

1. [普通に変換（JSONとGo言語側でキーの大文字小文字が合っている）](普通に変換（JSONとGo言語側でキーの大文字小文字が合っている）)
1. [普通に変換（JSONとGo言語側でキーは一致するが大文字小文字が違う）](https://goplay.space/#RNEddQux92l)

これは1も2も変数に正しく値が設定される。想定通り。

## 非正常系

異常系というか、Case insensitiveに名前を重複させるとか、JSON上キーを重複させるとか、普通はやらなそうなことをする。

1. [JSONのキーが重複している（Case sensitive）。Go側の変数は1つ。](https://goplay.space/#p66LxsY_p_0)
1. [JSONのキーが重複している（Case insensitive）。Go側の変数は1つ。](https://goplay.space/#nEBaClhHsDr)
1. [JSONのキーが重複している（Case sensitive）。Go側の変数は複数(Case sensitive)。](https://goplay.space/#KyUgWMMUu66)
1. [JSONのキーが重複している（Case insensitive）。Go側の変数は複数(Case sensitive)。](https://goplay.space/#RdS6rB2y5_l)
1. [JSONのキーは1つ。Goの変数は複数(Case sensitive)。](https://goplay.space/#fUtALG3ITyM)

## 実験の結果

1. JSON側の最後のキーの値が設定された
1. 大文字小文字を無視してJSON側の最後のキーの値が設定された
1. Case sensitiveに一致する名前の変数にそれぞれ値が設定された
1. Case sensitiveに一致する変数にのみ値が設定された
1. Case sensitiveに一致する変数にのみ値が設定された

なおキーや変数名はコード上順番を変えても同じ結果が得られた。

## 新たな疑問と推測

リファレンス上の定義どおり自分が実装するなら単純に、JSON側は後勝ち、struct側は先勝ちにする気がする。

つまり

```JSON
{"Name": "Cat", "NAME": "Dog"}
```

を入力として

```golang
type Animal struct {
  NAME string
  Name string
}
```

を出力とする場合、以下の結果となるように実装すると思う。

* NAME: "Cat"
* Name: ""（空文字=null値）

前提としてJSONは頭からストリームとして処理するし、structのメンバー変数をリフレクションで取得した時コード上の定義順に取得できるものとする。
JSON側はとにかく上から処理し、Goのstructからリフレクションで変数名を取得し、大文字小文字を無視して最初に見つかった変数に値をセットして処理を抜ける。

しかし実際には下記の状態になる。

```
* NAME:Dog
* Name:Cat 
```

この結果だけだとGo言語の`encode/json.Unmarshal`はcase sensitiveな動作をしている用に見える。
推測するに、まずcase sensitiveな比較を行って、一致するキーがなかった場合にcase insensitiveな比較をしているようだ。

# 実装を読む

当該箇所はencoding/jsonの[decode.go 697行目付近](https://github.com/golang/go/blob/master/src/encoding/json/decode.go#L697)

Mapとstructのバインディングが同じ関数で処理されているので（再帰的に処理する場合を考慮している？）だいぶ長い関数だが、擬似コードでいうと以下の処理になっている。

```golang
for j := range json側のフィールドリスト {
  for k := range struct側のフィールドリスト {
    if jsonのフィールド名とstructのフィールド名がバイナリ的に同一なら {
      structにjsonの値をセット
      break
    }
    if structのフィールドがまだ空 && jsonのフィールド名とstructのフィールド名がcase-insensitiveに同一なら { // 実際はUnicodeにCase folding的に同等なら
      structにjsonの値をセット
    }
  }
}
```

ということで、case-sensitive優先で処理しているようだ。

しかしフェイルバックのほうにbreakがないので、複数の変数に値が入りそうな気がするのだが…。
[python]macでopencvの画像検出（自前のデータで）

##動機
「Opencvちゃん，macの内臓カメラで顔検出ができるのは分かったから好きなもんを認識させてくれや...」ということでcascade分類器を自作しようとしたら思ったより時間食ったのでいろんなサイトを参考にしてうまくいったところで備忘録作っておこうと思って書きました．
※所要時間30分程度
##開発環境
・macOS High Sierra バージョン 10.13.6
・Python 3.6.4
・anaconda3 仮想環境　（Navigator使いました）
・opencv-python

今回は訳あってこちらのパッチを認識していきたいと思います．
![adversarial patch](https://ih0.redbubble.net/image.523861711.4677/stf,small,600x600-c,0,0,1000,1000.jpg)
Adversarial Patch
https://www.youtube.com/watch?v=i1sp4X57TL4


##さっそくやってみる

####OpenCVをbrewで入れる
お使いのmacにHome brewが入れてある前提でやっていきます．

```
$brew install opencv
```

```
$opencv_traincascade
```
と打って

```python

Usage: opencv_traincascade
```
と出てくればきちんとopencvがインストールされていると思われる（※後で使います）
####


##ディレクトリを作成する
任意のディレクトリに以下のように各フォルダを作ってください．
ーpos（正解画像を保存するフォルダ）
ーvec（正解画像ベクトルファイル用フォルダ）
ーneg（不正解画像を保存するフォルダ）
ーcascade/trained_data （分類器用フォルダ）

##画像配置
pos/の中に、上の画像をpatch.jpgと名前をつけて保存して，正解画像（以下、ポジティブ画像）として入れる．

```
pos/patch.jpg
```

neg/の中に、不正解画像（ネガティブ画像）を入れる

```
neg/100000.jpg
neg/100001.jpg
.....
```
ネガティブ画像は、patch以外ならどんな画像でもいいらしいのですが，結構量がないといけなかったのでINRIAdatasetから持ってきました．（jpg1.tar.gzってやつ）
http://lear.inrialpes.fr/~jegou/data.php#holidays

Tar.gzの解凍コマンドで解凍したら
https://qiita.com/takatyu/items/4cff84a6935556204b2a
上図のようにnegの下に配置してください．



##ベクトルデータを作る
一枚の画像からベクトルデータを作成します。

opencv_traincascadeコマンドを使うと、一枚の画像を変形させて 数千枚以上のベクトルデータを作成することができる。

```
$opencv_createsamples -img ./pos/patch.jpg -vec ./vec/patch.vec -num 100 -bgcolor 255 -w 44 -h 44
```

##ネガティブ画像のリストを１つのファイルにまとめる

```
$ls neg | xargs -I {} echo neg/{} > nglist.txt
```

##実際に分類器を作成する
```
$opencv_traincascade -data ./cascade/trained_data/ -vec ./vec/patch.vec -bg nglist.txt -numPos 100 -numNeg 100 -w 44 -h 44
```

そうするとcascade.xmlが作成される，それがcascade分類器になる．




##macのカメラで写してみる．
https://gist.github.com/kurozumi/04a75695dc32c46586be0d69e6a8243f

上記のサイトのコードを
ーpos（正解画像を保存するフォルダ）
ーvec（正解画像ベクトルファイル用フォルダ）
ーneg（不正解画像を保存するフォルダ）
ーcascade/trained_data （分類器用フォルダ）
ーcapture.py

のように配置して保存する．

その後．

```python
# OpenCVに用意されている顔認識するためのxmlファイルのパス
cascade_path = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml" 
```

を

```python
# OpenCVに用意されている顔認識するためのxmlファイルのパス
cascade_path = "./cascade/trained_data/cascade.xml" 
```
と書き換えて

```
$python capture.py
```

で実行するとmacの内臓カメラでこんな感じにリアルタイムで検出できる．(レイテンシのせいで少しずれちゃっていますが)

<img width="329" alt="スクリーンショット 2018-10-23 3.24.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/191313/feb51d47-018a-c17b-0729-50eb87631002.png">


あとは自分の認識させたい画像をpos/に入れて学習させてみてください．
~~学習枚数が100枚ずつだけなのであまり精度はでませんでしたが，もう少しデータを増やしてやってみたいと思います．~~
試してみたところopencv_createsamplesで作成できるのは100枚が限界でした．


###P.S.
機械学習，自動運転などをメインに（たまにそれ以外も）発信しているのでぜひこのQiitaと [twitterのフォロー](https://twitter.com/ryosanworld)おねがいします．



###参考サイト
ピカチュウ先輩の認識
http://workout-engineer.com/python-opencv-cascade/
物体検出 – HaarLike 分類器の作成 for mac
http://copycat.tokyo/copy-from/543/
http://copycat.tokyo/copy-from/577/
DataFrame(pandas)とかseabornの覚書

## DataFrameの覚書
```{.py}
# インポート
from pandas import DataFrame

# tsvの読み込み
dframe = pd.read_csv('data.tsv', delimiter='\t', header=None)

# カラム名変更
dframe.columns = ['hoge', 'fuga']

# カラムを落として別のDataFrame作成
dframe2 = dframe[[0, 1]] 
# カラム名が文字列で付いてたら、dframe[['hoge', 'fuga']]で。

# 重複行削除
dframe3 = dframe2.drop_duplicates()

# 行数調査
len(dframe3)

# DataFrameの数値の先頭X文字を切り取って新しいカラムとして使う
# sliceカラムを追加し、そこに、hoge(float型)の先頭4文字を挿入
dframe4['slice'] = dframe4['hoge'].astype(str).str.slice(0, X)

# groupbyして件数カウント
print dframe4.groupby(['slice']).size()

# 特定の文字列を含む行を抽出してDataFrame作成
df_tmp = dframe[dframe['column'].str.contains('hoge') == True]
```

### DataFrameの一部のカラムを使って関数を実行して、新カラム作成
```{.py}
# kaggleのタイタニックのデータを読み込み(https://www.kaggle.com/c/titanic/data?train.csvから取得したtrain.csv)
titanic_df = pd.read_csv('train.csv')

# 16歳未満を子供とみなす関数作成
def male_female_child(passenger):
    age,sex = passenger
    if age < 16:
        return 'child'
    else:
        return sex
    
# titanic_dfにpersonという新しい列を追加。
# 追加方法は、male_female_child関数で作成。applyで1行ずつ関数を適応する。
titanic_df['person'] = titanic_df[['Age','Sex']].apply(male_female_child,axis=1)
```

このperson別の行数[人数]をカウントするのは、value_counts()でできる。

```{.py}
titanic_df['person'].value_counts()
> male      537
> female    271
> child      83
> dtype: int64
```


### matplotlibを併用して、ヒストグラムをみる
タイタニック号の乗客のage別人数

```{.py}
titanic_df['Age'].hist(bins=70)
```
<img width="478" alt="スクリーンショット 2016-05-01 15.20.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/40159/063b5d23-9c18-24c1-bde0-9333553eb5cd.png">

ちなみに、年齢の平均は以下でサクッと見れる。

```{.py}
titanic_df['Age'].mean()
> 29.69911764705882
```

### ヒストグラムを見て、外れ値(ゴミ)を取り除く
```{.py}
sns.countplot('Cabin', data=cabin_df, palette='winter_d', order = sorted(set(levels)))
# palette:文字列を指定することで、色合いを指定できる。 _dをつけると、ちょっと暗めになる。
```

<img width="483" alt="スクリーンショット 2016-05-01 15.40.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/40159/4791155d-9e16-4b83-da57-291affc8954a.png">

タイタニックのtrain.csvのCabinの一文字目ごとにヒストグラムを書いたけど、A〜Gの後が"T"になっていて、飛んでいる。多分誤った情報なので、これを排除したい！

```{.py}
cabin_df = cabin_df[cabin_df.Cabin != 'T']
sns.countplot('Cabin', data=cabin_df, palette='summer', order = sorted(set(cabin_df.Cabin)))
```

<img width="485" alt="スクリーンショット 2016-05-01 15.42.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/40159/4c1e77e7-da48-b947-9704-c02fe089b7f1.png">

外れ値を取り除いたデータセットが作成できた。
ちなみに、orderのオプションがないと、A〜Gがばらばらになる。

### DataFrameのカラムを条件に沿う形で変形
```{.py}
# Aloneのカラムを、Aloneが0より大きければ、With Family、0ならAloneへ
titanic_df['Alone'].loc[titanic_df['Alone']>0] = 'With Family'
titanic_df['Alone'].loc[titanic_df['Alone']==0] = 'Alone'
```
pythonで並列処理

## 並列処理したい
bigdata系の処理をしていると、処理が遅すぎて泣きそうになることが多々。
inのファイルを分割して同じファイルを呼んでもいいけど、もっとスマートにやりたい。

## シングルプロセスで二重ループ処理をやってみる。

```{calcurate_example.py}
import time
from multiprocessing import Pool
from multiprocessing import Process

start = time.time()

L = 10000

total = 0
for i in range(L):
    for j in range(L):
        total += i*j

print (total)

elapsed_time = time.time() - start
print ("elapsed_time:{0}".format(elapsed_time)) + "[sec]"

# result
>2499500025000000
>elapsed_time:23.1847140789[sec]
```

23秒ほどかかってる。

## これをマルチプロセスにしてみる
```
import time
import multiprocessing as mp


# 各プロセスが実行する計算
def subcalc(p): # p = 0,1
    subtotal = 0

    # iの範囲を設定
    ini = L * p / proc
    fin = L * (p+1) / proc

    # 計算を実行
    for i in range(ini, fin):
        for j in range(L):
            subtotal += i * j
    return subtotal

if __name__ == '__main__':
    start = time.time()
    L = 10000
    proc = 2               # 並列プロセス数
    pool = mp.Pool(proc)

    # 各プロセスに subcalc(p) を実行させる
    # ここで p = 0,1
    # callbackには各戻り値がlistとして格納される
    callback = pool.map(subcalc, range(proc))

    # 各戻り値の総和を計算
    total = sum(callback)

    print (total)

    elapsed_time = time.time() - start
    print ("elapsed_time:{0}".format(elapsed_time)) + "[sec]"

> 2499500025000000
> elapsed_time:6.75670814514[sec]
```

6.7秒。　めっちゃ早くなった！
Rails+Vue.jsでVueファイルのスタイルシートが反映されなかった話

Rails+Vue.jsの組み合わせでアプリ開発をしていたところ、vueファイルのスタイルシートが反映されない。。
という問題を解決したときの覚書です。
類似事例を探すのに苦労したけど、これあまりハマらないのかな？

## 環境
|key|version|
|---|---|
|Ruby|2.5.0|
|Rails|5.1.6|
|vue|2.5.17|
|vue-loader|14.2.2|

`rails new hoge --webpack=vue`のコマンドでアプリを作成しました。

## サンプルコード
```vuejs:Sample.vue
<template lang="pug">
  div#footer
    p tocomi
</template>

<script>
export default {
  data: function () {
    return {}
  }
}
</script>

<style lang="scss" scoped>
#footer {
  position: fixed;
  bottom: 0;
  background-color: rgb(170, 228, 255);
  width: 100%;
  height: 50px;
  text-align: center;
}
</style>
```

フッター用のコンポーネントを作成したもののスタイルシートが反映されず。

## 調査

いろいろ調べていたところ、こちらの記事にたどり着きました。
[Rails と Vue.js の設計覚書](https://qiita.com/midnightSuyama/items/efc5441a577f3d3abe74)

`config/webpack/environment.js`に以下を追加すれば解決できそう。

```js
environment.loaders.get('vue').options.extractCSS = false
```

## 問題

これで勝つる！と思ったがまだ修正は反映されず。
念の為サーバー再起動したらスタックトレース吐いてた。

```
02:54:45 webpack.1 | TypeError: Cannot set property 'extractCSS' of undefined
02:54:45 webpack.1 |     at Object.<anonymous> (/Users/tocomi/develop/ruby/rails/baseball-fan-board/config/webpack/environment.js:8:51)
02:54:45 webpack.1 |     at Module._compile (internal/modules/cjs/loader.js:702:30)
02:54:45 webpack.1 |     at Object.Module._extensions..js (internal/modules/cjs/loader.js:713:10)
02:54:45 webpack.1 |     at Module.load (internal/modules/cjs/loader.js:612:32)
02:54:45 webpack.1 |     at tryModuleLoad (internal/modules/cjs/loader.js:551:12)
02:54:45 webpack.1 |     at Function.Module._load (internal/modules/cjs/loader.js:543:3)
02:54:45 webpack.1 |     at Module.require (internal/modules/cjs/loader.js:650:17)
02:54:45 webpack.1 |     at require (internal/modules/cjs/helpers.js:20:18)
02:54:45 webpack.1 |     at Object.<anonymous> (/Users/tocomi/develop/ruby/rails/baseball-fan-board/config/webpack/development.js:3:21)
02:54:45 webpack.1 |     at Module._compile (internal/modules/cjs/loader.js:702:30)
```

`undefined`だって。

## 解決

ただ修正を入れるべき箇所は分かったのでファイルを眺めてみる。

```js:config/webpack/environment.js
...
const vue =  require('./loaders/vue')

environment.loaders.append('vue', vue)
...
```

`.loaders/vue`を読み込んでいるのでそれを見てみると良さそう。

```js:config/webpack/loaders/vue.js
...
const extractCSS = !(inDevServer && (devServer && devServer.hmr)) || isProduction

module.exports = {
  test: /\.vue(\.erb)?$/,
  use: [{
    loader: 'vue-loader',
    options: { extractCSS }
  }]
}
```

extractCSSがあった！
`use`ってプロパティで配列を持つようになっているところが問題だったっぽい。

```js
environment.loaders.get('vue').use[0].options.extractCSS = false
```

こうしたらうまく動きました。
配列のインデックスがべた書きなのがすごく気持ち悪いです。

## 結論

取りあえず動くようになったものの、力技で解決している感が否めないので、
そもそもの設定がおかしいとかもっとスマートな解決策とかあれば教えてほしいです。
Coroutineの罠にハマった話（Update内で呼ばれるCoroutineとUpdate内の処理の順番）

#結論
具体的な事例を元に書くので話が少しややこしくなるかもしれないため，とりあえず結論を書きます．


###Update内で呼ばれるCoroutineとUpdate内の処理の順番
[初コルーチン呼び出し]
1. [StartCoroutineよりも上の部分のUpdate関数内の処理]-> 
2. [Coroutine] -> 
3. [StartCoroutineよりも下の部分のUpdate関数内の処理]

[２回目以降のコルーチン呼び出し]
1. [Update関数内の処理全て]-> 
2. [Coroutineの続き]


![Screen Shot 2018-10-23 at 1.22.47 (2).png](https://qiita-image-store.s3.amazonaws.com/0/184790/a3078bc6-0cac-48e0-7aa4-d43522c054ea.png)


#やりたかったこと
Coroutine内でアニメーションの処理を書いて，終わったタイミングだけUpdate内でアクションを起こしたかった．．．
（*イメージは下記のコード）

```CoroutineSample.cs
public class test : MonoBehaviour {
    bool flag = false;
	void Start () {	
	}
	
	void Update () {
           flag = false;
           if(Time.FrameCount%3600 == 0) StartCoroutine("Motion");	
           if(flag) Debug.Log("true")
	}

	private IEnumerator Motion()
	{
		for (int i = 0; i < 30; i++)
		{
		    //AnimationCode
            yield return null;
		}
        flag = true;
        yield return null;
	}
}
```
しかし，何も起こらなかった．．．．
#### 自分の理解でのこのコードの処理の順番
1. [StartCoroutineよりも上の部分のUpdate関数内の処理]-> 
2. [Coroutineの続き] -> 
3. [StartCoroutineよりも下の部分のUpdate関数内の処理]

って感じでした．
しかし，Update内でDebug.Logを使い，bool値を追ってみるとずっとfalseになっている．．．おかしい．．．

#Coroutine,Updateの実行順番
処理の実行順序を調べるため，こんなコードを書いてみた

```CoroutineSample01.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test : MonoBehaviour {

	void Start () {
		
	}
	
	void Update () {
		
		Debug.Log("Before-Update");
		if (Time.frameCount == 0)
		{
			StartCoroutine("Motion");
		}
		Debug.Log("After-Update");
	}

	private IEnumerator Motion()
	{
		for (int i = 0; i < 30; i++)
		{
			Debug.Log("--------Coroutine----------");
			yield return null;
		}

		
	}
}
```

結果
![Screen Shot 2018-10-23 at 1.22.47 (2).png](https://qiita-image-store.s3.amazonaws.com/0/184790/a3078bc6-0cac-48e0-7aa4-d43522c054ea.png)

#結論
初めにCoroutineが呼ばれるのは予想してた
1. [StartCoroutineよりも上の部分のUpdate関数内の処理]-> 
2. [Coroutine] -> 
3. [StartCoroutineよりも下の部分のUpdate関数内の処理]

であったが，それ以降の処理については
1. [Update関数内の処理]-> 
2. [Coroutineの続き]

のようでした


#補足
###メソッド
- yield return null:
yield return nullにたどり着いた時点で処理を中断して次のフレームからまた処理の続きを行うって物です．

###意見
自分はキーフレーム系の処理があまり好きではありません．．．めんどくさいので．．ですが映像を作っているとそうも言ってられない時があります．例えばAEとかで作っている回転し終わったタイミングで平行移動とかカクカクした感じのモーションなど．そんな時にCoroutineを使うことでそのキーフレームを使うことの悩みも解消できるのでぜひ試してみてください．
簡易的なものですが参考にしていてください↓

```sample02.cs
private IEnumerator Motion()
	{
		int frameNum = 60;
		for (int i = 0; i < frameNum; i++)
		{
			var dy = 30.0f / frameNum;
			this.transform.Rotate(new Vector3(0.0f, -dy, 0.0f));
			yield return null;
		}

		frameNum = 10;
		for (int i = 0; i < frameNum; i++)
		{
			var dx = 25.0f / frameNum;
			this.transform.Rotate(new Vector3(dx, 0.0f, 0.0f));
			yield return null;
		}
		yield return null;
	}
```
id_rsaなくすと死ぬよ

数学科の私がエンジニアになって間もないですが、めちゃめちゃ言われること
**「id_rsaはパソコン変えても、何があっても、絶対なくしちゃだめだよ」**
最初は意味がわからず嗚咽を漏らし枕を濡らすだけだったが
なぜなのかがぼんやり分かったので書いておく:girl_tone2:

#SSHでの秘密鍵・公開鍵
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/123531/5cc34e9f-eca8-5dc8-f9d8-920196bc7615.jpeg)
相手は公開鍵を持っており、自分は秘密鍵を持ってる状態だとする


![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/123531/3774654f-8c00-7448-401e-03b88440aa00.jpeg)
私は相手のお家に遊びに行きたいので、「お家に入れてー」と声かけします。

![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/123531/de9e80d5-efe5-a5e1-7ee4-90f8b1b6c04d.jpeg)
不安症な相手は、私が本物ということを信じてくれません。
そして暗号を投げつけてきました。

![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/123531/ea2030a1-d547-f2a2-956c-9d32e9015748.jpeg)
解き方を知っている私は、自分の持っている秘密鍵を使って、
「暗号」に「秘密鍵」をかけて、答えとしてうさぎさんに提出しました。
すると、うさぎさんは私のことを信じてお家に入れてくれました。

#お分りいただけただろうか
つまり、「公開鍵」と「秘密鍵」は掛け合わせたら1になる関数と逆関数の関係で、
暗号から答えを導き出せて、私であることが証明できるのである。

この「相手」が「サーバー」に置き換えられ、
「公開鍵」「秘密鍵」がもっと複雑なものになり、
またさらにハッシュ化という作業が加われば多分SSH接続そのものである。

#メリット
 - データの送受信が暗号としてできる -> 途中で他人に暗号がばれない
 - 暗号はちょっとやそっとじゃ破れない

#デメリット
 - サーバーはユーザ分だけ公開鍵をもっとかなくちゃいけない
 - 秘密鍵が盗まれないという保証はない

#だからこそ私はid_rsaを失くせない
SSH接続したいときに、秘密鍵がないと、自分であるということを証明できない
だからこそみんな私に口すっぱく教えてくれたのだろう、、、
PCかえても忘れずに引き継がなきゃなんだなあ〜