OmniAICreator/Qiita-1.07M huggingface dataset:
論文まとめ：Unsupervised Anomaly Detection with Generative Adversarial Networks to Guide Marker Discovery

# はじめに 
GANを使った異常検知論文からその先駆け的存在の以下
[1] T. Schlegl, et. al."Unsupervised Anomaly Detection with Generative Adversarial Networks to Guide Marker Discovery" IPMI 2017
をまとめる。

arXivのページ
https://arxiv.org/abs/1703.05921

githubにいくつかコードがあがってるが
https://github.com/xtarx/Unsupervised-Anomaly-Detection-with-Generative-Adversarial-Networks
それらが著者らのかどうかは不明

# 概要　
- GANを使って異常検知をするモデル
- 正常・異常を分類するモデルではアノテーション作業が膨大 or 異常データが少ないので、正常のみから学習するという点で意義がある
- 網膜等医療系の画像で効果を実証した

# モデルの全体像 

以下の[1] figure 1で説明すると

<img width="954" alt="anoGAN_img_03.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/b6b43d1c-c81e-6f2e-a42d-cd3aa9b06583.png">

大きく分けて以下２つのフェーズがある。

１）正常データを生成するよう学習するフェーズ

２）学習したモデルで未知のデータに近いもの生成するノイズを探索するフェーズ

<b><font color="MediumBlue">フェーズ１</b></font>

figure 1 の左上が網膜付近の画像。これから前処理で網膜部分を切り取り、平らにした画像がその下。

これからパッチを切り取り、正規化したものを正常データとする。

正常データを生成するよう、その右（Training the GAN）のGANで学習する。

<b><font color="MediumBlue">フェーズ２</b></font>

右半分（Identifying anomarilies）の左から未知データを入力する。

これに対し、異常と判定されたエリアが右からの出力画像の赤い部分。

#フェーズ１：正常データを生成するようGANで学習

### GANのアーキテクチャ

GANのアーキテクチャは以下の[1]figure 2 の(a)。

<img width="569" alt="anoGAN_img_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/116706/fed5538c-77d4-1c57-991e-15e5cb419a32.png">

スタンダードなGAN構造。

### 目的関数

１次元のノイズ $\bf z$ とそれが従う一様分布 $p_{\bf z}$ 、
入力画像 $\bf x$ とそれが従うデータ分布 $p_{data}(\bf x)$ 、
generator：$G$、
discriminator：$D$ としてminimaxな式は以下のスタンダードなもの。

```math
\min_G \max_D V(D, G) = \mathbb{E}_{\bf x \rm \sim p_{data}(\bf x \rm)} [\log D(\bf x \rm)] + \mathbb{E}_{\bf z \rm \sim p_{\bf z \rm}(\bf z \rm)} [\log (1 - D(G(\bf z \rm)))]
```

# フェーズ２：異常検知 
学習したGANを異常検知に利用するには特殊な処理が必要。

### 異常検知の全体像 
１）適当な $\bf z\rm_1 \sim p_{\bf z}$ で生成した画像 $G(\bf z\rm_1)$ と未知の画像 $\bf x$ とのロスを求める

２）勾配降下法でより未知の画像 $\bf x$ に近い画像を生成する $\bf z\rm_2$ を求める

３）生成した画像 $G(\bf z\rm_2)$ と未知の画像 $\bf x$ とのロスを求める

４）以上の繰り返しで未知の画像 $\bf x$ に最も近い画像を生成するノイズ $\bf z\rm_{\gamma} $ を求め、これにより生成した画像 $G(\bf z\rm_{\gamma})$ と未知の画像 $\bf x$ との距離で正常・異常を判定する

### フェーズ２のロス

ロスは2種類。

1. 未知の画像 $\bf x$ と生成した画像 $G(\bf z \rm)$ との見た目の近さを測る residual loss  
2. 生成した画像 $G(\bf z \rm)$ が正常データ $\chi$ の多様体に含まれるかを測る discrimination loss

### residual loss
residual loss は以下のL1。

```math
\mathcal{L}_R (\bf z\rm_{\gamma}) = \sum |\bf x\rm - G(\bf z\rm_{\gamma}) |
```

### discrimination loss 
discrimination loss は以下のようなDiscriminatorの中間層からの出力同士のL1。

```math
\mathcal{L}_{D} (\bf z\rm_{\gamma}) = \sum | f(\bf x\rm ) - f(G(z\rm_{\gamma}))|
```

### トータルのロス

上記２つのロスを組み合わせて、最終的なロスは以下。

```math
\begin{eqnarray}
\mathcal{L} (z\rm_{\gamma}) = (1-\lambda) \cdot \mathcal{L}_R (\bf z\rm_{\gamma}) + \lambda \cdot \mathcal{L}_{D} (\bf z\rm_{\gamma}) \\
\end{eqnarray}
```

### 正常・異常の判定
正常・異常の判定には、探索して求まった最終的な $(\bf z\rm_{\Gamma})$ に対して以下のスコア $A(\bf x\rm)$ を用いる。

```math
A(\bf x\rm) = (1- \lambda) \cdot R(\bf x\rm) + \lambda \cdot D(\bf x\rm)
```

ここで $R(\bf x\rm)$ はresidual loss。

また $D(\bf x\rm)$ は discriminatorからの出力に対する sigmoid cross entropy。

```math
\mathcal{L}_{\hat{D}} (\bf z\rm_{\gamma}) = \sigma (D(G(\bf z\rm_{\gamma})),1.)
```

# 実験と結果 

<font color="red">書きかけ</font>
claudia.jsでLambdaのJavaScriptを更新する際にはまった話

claudia.jsを利用してアプリの開発を行っていますが、LambdaへのJavaScriptファイルのデプロイではまってしまいました。
根本原因は分からないままですがデプロイは成功できるようになったため同じ問題に出会った方のためにもメモしておきます。
原因がお分かりになる方がいらっしゃれば教えて頂けるとうれしいです。

## 発生した現象

Lambdaに配置したJSを更新するために実行したコマンドは以下です。

```
$ claudia update
```

上記を実行すると以下のエラーが発生しました。

```
validating package
Error: Cannot find module '/var/folders/51/xxxx_xxxxxxxxxxxxxxxxxx/Y/zzzz/<package name>-<package ver>-wwwwww/package/dist/app'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:603:15)
    at Function.Module._load (internal/modules/cjs/loader.js:529:25)
    at Module.require (internal/modules/cjs/loader.js:659:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at validatePackage (/Users/hidekita/dev/claudia-app/node_modules/claudia/src/tasks/validate-package.js:16:15)
    at initEnvVarsFromOptions.then.then.then.then.then.then.then.dir (/Users/hidekita/dev/claudia-app/node_modules/claudia/src/commands/create.js:343:10)
    at process.internalTickCallback (internal/process/next_tick.js:77:7)
cannot require ./dist/app after clean installation. Check your dependencies.
```

## 上記エラーが発生した状況

元々、claudiaで配置していたapp.jsをES5で作成し、そのファイルをGitにより管理していました。
その後、モダンなJSを利用したいと考えて、BabelによりJSファイルをコンパイルするようにしました。コンパイルにより生成したJSファイルはdistフォルダに出力するようにしました。このdistフォルダはGitで管理する必要はないと考え、.gitignoreファイルを使ってdistフォルダを無視するようにしました。

Mac 10.14.2
node 11.4.0
npm 6.5.0

開発に利用したNPMパッケージ(devDependenciesの設定)。

```
    @babel/core: 7.2.2
    @babel/preset-env: 7.2.3
    babel-loader: 8.0.4
    webpack: 4.28.3
    webpack-cli: 3.1.2
```

## 成功した方法

コンパイル後のapp.jsもGitで管理するように、.gitignoreファイルを修正した上でLambda上のJSの更新を実施したら成功しました。
PythonでOpenCVをはじめる（Windows10、Anaconda 2018.12、Python3.7.1、OpenCV4.0.0）

## 開発環境
- Windows10 64bit
- Anaconda 2018.12
- Python 3.7.1
- OpenCV 4.0.0

## 環境構築
1．Anacondaをインストールします。（2019年1月19日付バージョン：2018.12）
2．Windowsキーを押し、Anaconda Promptを検索し、開きます。
3．下記コマンドを入力し、Python3.7の仮想環境を作成します。仮想環境を作ることでPython2.7用とかtensorflow用とかに分けれるので便利です。

~~~
conda create -n py37 python=3.7 anaconda
~~~

4．Windowsキーを押し、Anaconda Prompt (py37)を検索し、開きます。
5．下記コマンドを入力し、必要なライブラリをインストールします。

~~~
pip install opencv-python
pip install opencv-contrib-python
~~~

6．バージョンを確認します。

~~~python
# OpenCVのバージョン確認
import cv2
print(cv2.__version__)
print(dir(cv2.aruco))
# Pythonのバージョン確認
import sys
print(sys.version)
~~~

結果は下記のようになります。
<img width="673" alt="50442625_347391585857639_3997285719759388672_n.png" src="https://qiita-image-store.s3.amazonaws.com/0/63863/bc4f4497-0557-c45d-e577-92a1ed038177.png">

OpenCV 4.0.0、OpenCV Contrib 4.0.0、Python 3.7.1がインストールできました。

## サンプルの実行
OpenCV 4.0.0のサンプルは[ここ](https://github.com/opencv/opencv/archive/4.0.0.zip)からダウンロードし、opencv-4.0.0\samples\python下のdemo.pyを実行してみましょう。各サンプルが試せます。

![49627762_553750241808646_4653951498802167808_n.png](https://qiita-image-store.s3.amazonaws.com/0/63863/1ff0a080-5702-e91b-328f-c557a07098eb.png)


- asift.py
- browse.py
- calibrate.py
- camera_calibration_show_extrinsics.py
- camshift.py
- coherence.py
- color_histogram.py
- contours.py
- deconvolution.py
- dft.py
- digits.py
- digits_adjust.py
- digits_video.py
- distrans.py
- dis_opt_flow.py
- edge.py
- facedetect.py
- feature_homography.py
- find_obj.py
- fitline.py
- floodfill.py
- gabor_threads.py
- gaussian_mix.py
- grabcut.py
- hist.py
- houghcircles.py
- houghlines.py
- inpaint.py
- kalman.py
- kmeans.py
- lappyr.py
- letter_recog.py
- lk_homography.py
- lk_track.py
- logpolar.py
- morphology.py
- mosse.py
- mouse_and_match.py
- mser.py
- opencv_version.py
- opt_flow.py
- peopledetect.py
- plane_ar.py
- plane_tracker.py
- squares.py
- stereo_match.py
- stitching.py
- texture_flow.py
- tst_scene_render.py
- turing.py
- video.py
- video_threaded.py
- video_v4l2.py
- watershed.py

## 参考文献
- [OpenCV 4.0.0](https://github.com/opencv/opencv/archive/4.0.0.zip)
- [OpenCV-Contrib 4.0.0](https://github.com/opencv/opencv_contrib/archive/4.0.0.zip)
GitHubの無料プライベートレポジトリとVSCodeを使って開発メモの履歴をマネージする

# 問題
　開発の仕事に限った話ではないけど、いろいろと作業を進めていく際に、ちょっとしたメモを取ったり、コードの切れ端をコピペして一部分を変更したり、ちょっとの間覚えておかなくてはいけないURLをコピペしたりします。そして時が経ち、あの時にメモしたあの情報、どこだっけ？ってなることがたまにある。
　ここ数年はNotepad++を使ってメモってました。Notepad＋＋だとデフォルト設定で「名無しのファイル」も全部セーブしてくれるんで、失くしてしまうことはあまりなかったです。それでもマシーンが変わったりしたらすべて無くなってしまいます。OneDriveにメモファイルを置いて、自動で同期させる方法も試しましたが定着しませんでした。あと、OneDriveって更新履歴残ってるのかな？どちらにしろGitに比べると使い勝手が面倒です。

# 発端
　長年、GitHubはプライベートレポジトリは有料でしたが、つい先日そのポリシーが180度変わって無料になりました（わーい！）。これって地味にすごいことです。コード＝資産＝価値です。コードが集まることは価値が集まることです。今までは秘密で開発中のすごいソフトウェアのコードをGitHubに置くには有料プランを使うしかなかったのが、無料で（ある程度）安全に保存・マネージ出来るようになったのです。話はそれましたが、じゃぁ早速プライベートレポジトリを何かに使ってみようと考えた時に、あまり公にはしたくない（出来ない）情報を多々含む場合がある開発メモをGitHubのプライベートレポジトリで管理しようと思い立ったわけです。

# VSCode　

　エディターはNotepad++を使ってましたが、開発メモとなるとやはり開発に近いVSCodeが向いているなと思い、ここらでスイッチしようと思い立ちました。特に、VSCodeがマークダウンを表示してくれる点は、コードの切れ端の保存には向いています、というかそれ以外ないでしょってぐらいの親和性があります。Notepad++は単なるテキストエディターですから、文字の強調なども出来ませんし。

#　要求
ということで、こんなこと出来たらな～っと思ってました

- 変更を自動的に保存してくれる
- レポジトリに変更内容を簡単にPush出来る
- 開発メモを編集するVSCodeのインスタンスは目的が分かりやすいように色・テーマを変える
- ファイル名を年月単位で割り当てる（できれば自動化）

# プライベートレポジトリの作成

こんな感じで「worklog」という名前のプライベートレポジトリを作って見ました。「Private」という見出しタグが見えます。
![2019-01-12 10_59_04-Your Repositories.jpg](https://qiita-image-store.s3.amazonaws.com/0/103139/a9def8f5-8e06-af30-5133-49236eddef54.jpeg)

# VSCodeのワークスペース設定

作成したプライベートレポジトリのルートフォルダーに、```＜適当な名前＞.code-workspace```という名前の```json```ファイルを作成します。このワークスペースファイルには、このワークスペースのみに適用される設定を記述できます。

ファイルの変更を自動的に保存するように設定しました。

![2019-01-12 10_48_27-● worklog.code-workspace - worklog (Workspace) - Visual Studio Code.jpg](https://qiita-image-store.s3.amazonaws.com/0/103139/adc256ea-3ddb-ded7-467f-2439c2f7cbc2.jpeg)

以下が設定完了したワークスペースファイルです。

![2019-01-12 11_04_00-worklog.code-workspace - worklog (Workspace) - Visual Studio Code.jpg](https://qiita-image-store.s3.amazonaws.com/0/103139/37ea55a8-df75-4bbd-33b2-19f28a74f741.jpeg)

- ファイルの自動保存は毎秒
- 色・テーマ設定は適当に白っぽいものをチョイス。（普段の開発はダークテーマなんで）
- Git でコミットしたら自動的にPushもするようにした。通常のコードではやらないけど、メモならCommitの意志は中央レポジトリへの保存の意思と同じなので。

# そもそもメモに履歴は必要なのか？

これは考え方、やり方によっては必要ない。徒然なるままにメモっていけばいいだけだし、今までもそうしてきた。しかし、そういうメモって後で見返した時「正しい情報」が見つけづらいんですよね。コードの切れ端とかも試行錯誤をするので、上手く動作しないコードなんかも残ってたりして、検索で複数キーワードがヒットしてもどれが正しいのか分からなくなる。じゃぁファイル1つでやって、時々白紙に戻すのもありかもしれないが、そうすると検索が面倒。過去のコミットも探索しなくちゃいけない。なので毎月ぐらいの頻度でファイルがメモがたまっていくのは自分的にはバランスが良い。

ということで、今後は出来るだけメモる情報の質も向上させていこうと思う。Gitレポジトリのおかげで過去の履歴にはいくらでも戻れるわけだから紛失のリスクは少ない。

# 次にやること（やるかもしれないこと）

ファイル名を年月単位で割り当てる（できれば自動化）は今回は見送りで。VSCodeの拡張を書いて、自分なりのコマンドか何等かのイベントで新規ファイルを自動生成する、というのがおそらく適切な方法だと思う。ただ、新規ファイルを手動で作成するコストがひくいので動機が沸かない。

# まとめ

開発メモのマネージメント周りのワークフローとツールをちょっと変更してみることにした。GitHubのプライベートレポジトリとVSCodeの柔軟さにありがとうと言いたい。
Gitea環境をdocker-composeで作ってみる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/330873/a5c35564-0f2c-2ee8-3d89-d46b9a68c4bc.png)


# docker-compose.ymlの作成

まずは、docker-compose.ymlファイルを作成を作成する

- imageはgitea公式dockerhubの最新1.7を使用する
- SSH_PORTはホストと重複しないよう変更する
- TZ=Japanを指定して時計をあわせる
- restart alwaysでOS再起動しても起動してくるよう設定

```yml:docker-compose.yml
version: '3'
services:
  web:
    image: gitea/gitea:1.7
    volumes:
      - ./gitea-data:/data
    ports:
      - "3000:3000"
      - "10022:10022"
    environment:
      - TZ=Japan
      - SSH_PORT=10022
    restart: always
```

# 一度起動

```
$ docker-compose up
```

- ブラウザで`192.168.1.100:3000`にアクセス
- 右上のサインインをクリック

以下の**太字**は変更箇所

| 設定項目            |     設定値         |
|:--------------------|:------------------|
| データベース設定      |  XXXXXXXXXXXXXXX |
| データベースのタイプ　|  SQLite           |
| パス                |  /data/gitea/gitea.db |
| 基本設定             |   XXXXXXXXXXXXXXX |
| サイトタイトル       |  Gitea: Git with a cup of tea |
| リポジトリのルートパス|  /data/git/repositories |
| Git LFSルートパス    |  /data/git/lfs |
| 実行ユーザー名       |   git |
| SSHサーバーのドメイン |   **192.168.1.100** |
| SSHサーバーのポート   |  git |
| Gitea HTTPポート     |  3000 |
| GiteaのベースURL     |  **http://192.168.1.100:3000/** |
| ログの保存先パス      |  /data/gitea/log |
| オプション設定        |  管理者アカウントの設定  |
| 管理者ユーザー名      |  **root**         |
| パスワード           |  **root**         |
| パスワード確認       |  **root**         |
| メールアドレス       |  **root@192.168.1.100**         |

**Giteaをインストール**をクリック


# SSHの設定

ブラウザで右上の設定＞SSH/GPGキー＞**キーを追加**をクリック

```
$ ssh-keygen -t rsa -b 4096
$ cat ~/.ssh/id_rsa.pub
xxxxxxx
```

生成された公開鍵`id_rsa.pub`の中身を**内容**に貼り付け、**キーを追加**をクリック

ここで一度docker-composeを停止

```
Ctrl+c
```

`START_SSH_SERVER = true`を設定ファイルに追加

```
# vi gitea-data/gitea/conf/app.ini
START_SSH_SERVER = true
```

```
$ docker-compose up
```

これでSSHでのclone/pushが可能に。

# 参考

[Giteaのインストール \- Qiita](https://qiita.com/0xffffff/items/ae38a464a342c985b2e4)

[Docker コンテナの自動起動をキャンセルする \- OZACC\.blog](https://blog.ozacc.com/posts/bfcd320f)
> $ docker inspect {コンテナID} | grep -A 3 RestartPolicy
            "RestartPolicy": {
                "Name": "always",
                "MaximumRetryCount": 0
            },
> $ docker update --restart=no {コンテナID}
> $ docker inspect {コンテナID} | grep -A 3 RestartPolicy
            "RestartPolicy": {
                "Name": "no",
                "MaximumRetryCount": 0
            },
【2019年版】自宅の環境を整備する話

# はじめに
大量のPCと大量の仮想マシンが可動している我が家ですが、そのときどきで環境を追加新設してきたので、ゴチャゴチャです。これを期に掃除しようも兼ねて再設計をしました。こんなのを公開して攻撃されたら・・・とか誰かの役に立つのか、など思うところは色々ありますが、今年から毎年掃除をしようと思うので、IT業界の変革の写像的にあとから見て面白ければいいなという期待で投稿します。

# とりあえずの設計
画像のようになりました。物理的なPCは2台に絞り、その上に必要最低限の仮想マシンを動かす形で対応。宗教上の理由でMacは使えないので、基本的にホストOSはWindowsです。簡単な説明をします。
![2019設計](https://qiita-image-store.s3.amazonaws.com/0/213748/0fd170a0-4edb-de21-205d-51f146514a62.png)

【ハード】
* Black メイン機。Kaby Lake、メモリ32G、GPUなし。
* White サブのLaptop機。サーバ用途。
【仮想マシン】
* Fedora 最新の動向に追いつきたい。
* Kali 遊び用。 
* Zorin WindowsライクなGUIなのが好き。
* Cent docker上でいろいろサーブさせる。(FTP,Jupyter Notebook,Web,DBなどなど)
* Android アプリ開発を行うので使う。
【その他】
* スマホやら、ゴロ寝PCSなどはDHCPで管理が楽。

#補足
仮想マシンはCentを除いてランレベル5なので、リモートデスクトップでメイン機から接続して使います。ルータはWANに直結しておらず、このネットワークだけある程度独立した環境になっています。なので攻撃される心配は多分ないです。また10.代のアドレスを用いているのは入力が楽だからです。本当はネットワーク周りの試験をする際に便利なのでVyOSなんかで分割したいんですが、これ以上入れ子にするのも...と思って手が出ません。またホスト名は私の好みで中2ライクな名前が多いです。

#コメントがあればぜひください
PlayerPrefs.GetString()のdefaultValueにnull入れると空文字が出てくる

## どういうこと？

以下のコードを見てください。


```c#
PlayerPrefs.DeleteAll();

const string key = "KeyOfTheTwilight";
var value = PlayerPrefs.GetString(key, null);

Debug.Log("key:" + PlayerPrefs.HasKey(key));
Debug.Log("value:" + value);
Debug.Log("length:" + value.Length);
```

## 予想
PlayerPrefsは設定とかを保存しておくクラスです。
DeleteAll()はその名の通り保存された設定値すべてが消えます。
公式ドキュメントにはこうあります。

> [PlayerPrefs.GetString](https://docs.unity3d.com/jp/current/ScriptReference/PlayerPrefs.GetString.html)
> キーが存在する場合、key に対応する値を取得します。
> キーが存在しない場合、defaultValue を返します。

つまりこの場合は`value`はdefaultValueである`null`であり、`value.Length`で長さを取得しようとしたところでご存知`NullReferenceException`が出てしまう……はずです。

## と思うじゃん？
<img width="317" alt="スクリーンショット 2019-01-13 2.35.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/146245/c759f344-8667-b881-9b91-dc66622746c0.png">
？？？


```c#
value = null;
Debug.Log("length:" + value.Length);
```
<img width="501" alt="スクリーンショット 2019-01-13 2.37.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/146245/54396d86-f0df-ba1a-3662-20522b762bd5.png">
？？？？？

キーが存在しないからdefaultValueが返るはず。
defaultValueは`null`。
`null`なら`NullReferenceException`が出るはず。

つまりdefaultValueをnullに設定したにもかかわらず空文字が返ってきている。

## ！！！！結！！！論！！！！

[PlayerPrefs.GetString](https://docs.unity3d.com/jp/current/ScriptReference/PlayerPrefs.GetString.html)
> キーが存在する場合、key に対応する値を取得します。
> キーが存在しない場合、defaultValue を返します。

**キーが！！！！！！存在しない！！！！！！場合！！！！defaultValueを！！！！！！！返します！！？！！？？！！？！うそつき！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！**

## 実験と推論

#### 実験

##### 実験1：int, floatなどstringではない型として保存した値を取得
```c#:実験1

PlayerPrefs.SetInt(key, 193);
PlayerPrefs.Save();
var value = PlayerPrefs.GetString(key, null);
```

##### 実験2：nullを保存

```c#:実験2
PlayerPrefs.SetString(key, null);
PlayerPrefs.Save();
var value = PlayerPrefs.GetString(key, null);
```

実験1、2ともに空文字が返ってきます。

#### 推論
PlayerPrefs.csは各Platformに深く依存しているクラスなので中身を見ることはできませんが、c#層の実装を見ることで原因を推測することはできます。


```c#:PlayerPrefs.cs
/// <summary>
///   <para>Returns the value corresponding to key in the preference file if it exists.</para>
/// </summary>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern string GetString(string key, string defaultValue);

/// <summary>
///   <para>Returns the value corresponding to key in the preference file if it exists.</para>
/// </summary>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
public static string GetString(string key)
{
return PlayerPrefs.GetString(key, "");
}
```

推測ですが……本当に根拠もなにもない推測なんですが、PlayerPrefsの考える「値がないstring」は`""`であって`null`ではない……？

## ほんとうの結論
`string.IsNullOrEmpty()`使おう！

PlayerPrefsにJSONを保存して[MiniJSON](https://gist.github.com/darktable/1411710)でデシリアライズして……とやってる最中にこれが起きたため、要因を他に求めてドハマリしました。
なにげにUnityEditorはいったん終了させてもPlayerPrefsは保存されたままとか知らなかった……。


UnityEditor / unity 2018.3.0
上の環境でしか確認していないですが、UnityのバージョンとかPlatformによって動作が違ったら**もっとムカつくので**確認はしていません。

おしまい。
MoneyForward クラウド給与 の出勤・退勤の打刻をコマンドラインからやりたい

MoneyForward クラウド給与 の出勤/退勤の打刻が面倒で、コマンドラインからワンタッチでできるようにしたいなーと思ったので作った。

# インストールと使い方

https://github.com/oieioi/syukkin-kun

このリポジトリを clone して Docker でビルドすれば使える。

```bash:インストール
git clone https://github.com/oieioi/syukkin-kun
cd syukkin-kun
docker build -t oieioi/syukkin-kun . --build-arg USER_NAME="your mail address" --build-arg PASSWORD="your password"
```

```bash:出勤
docker run oieioi/syukkin-kun
```

```bash:退勤
docker run oieioi/syukkin-kun true
```


# メモ

Web API があるだろうから簡単にできるだろうなと思ってたけどなかったので、 [Puppeteer](https://github.com/GoogleChrome/puppeteer) で Chrome を操ってやることにした。ID/PASSWORDを直に入力してログインし、出勤/退勤ボタンをクリックするという素朴で野蛮な実装になっている。

# TODO

- エラーハンドリングとか全然してないので何かミスると勝手に死んでる
- ブラウザの拡張機能とかで作った方が楽か？
- パソコンの電源を入れたりとかターミナルをその日初めて起動した時とかに自動で打刻するようにしたら楽か？
RubyからQRCodeの読み込み

付箋紙にQRコードをくっつけて場所を把握し、マッピングするような仕組みを思いついたので実装を考える。

# CentOS7でのインストール

zbarそのままだとrubyのライブラリとの相性？のせいでエラーになるのでyumではなくソースからインストールしてpatchを当てて対応する。

```bash
wget https://sourceforge.net/projects/zbar/files/zbar/0.10/zbar-0.10.tar.bz2/download - zbar-0.10.tar.bz2
tar jxf zbar-0.10.tar.bz2 
```

パッチは[ここ](http://sourceforge.net/p/zbar/code/ci/825b6ec9244619cc616d592e657fc64b5d7b2c25/tree/zbar/jpeg.c?diff=0e183788061038ad5a32543e594ebe48bde89971)
patchコマンドよくわからないので、手書きで直し。

```bash
cd zbar-0.10/
./configure --without-gtk --without-qt --disable-video --without-python --without-xshm --without-xv
make
make install
```

zbarのインストールはここまでgemは"zbar"で指定。

そもそもrubyさえ初心者。
Ansibleで複数のコマンド実行結果とノード毎にファイルを作る方法

「[AnsibleでCatalystのconfig取ってみた(telnet版)](https://qiita.com/Yohichi_Hayashi/items/772ea6b1e66d4cc8aa26)」の続き記事です。


### 1. 複数のコマンド実行結果をファイル保存する方法
複数のコマンド実行結果を取得する方法です。
配列使ったプログラミングをやったことがある人なら容易に思い至る方法なので、この先は読む価値はありません。

さて、前のポストで、`command:`配下に入力するコマンドを入れてますが、

```yaml:command

      command:
       - terminal length 0
       - enable
       - cisco
       - show run
      changed_when: False
      register: command_result
```
この4行の結果は、一つの変数名の中のそれぞれ違う領域に入ります。
(配列相当で、可変長なchar？)

なので、

```yaml:Text出力

  - name: log export
    local_action:
      module: copy
      owner: hayashi
      group: hayashi
      mode: 0644
      dest: "/home/hayashi/show_run.log"
      content: "{{ command_result.output[3] }}"
    changed_when: False
```

`content: "{{ command_result.output[3] }}"`と書くと、4行目の`show run`の結果が採れるわけです。


もうお分かりかと思いますが、

```yaml:command

      command:
       - terminal length 0
       - enable
       - cisco
       - show run
       - show ver
      changed_when: False
      register: command_result
```
と5行目に足して、
別ファイルで出力する適当な`- name:`をコピペで足して、
[3]を[4]にインクリメントしてあげれば、

```yaml:Text出力

  - name: show ver
    local_action:
      module: copy
      owner: hayashi
      group: hayashi
      mode: 0644
      dest: "/home/hayashi/show_ver.log"
      content: "{{ command_result.output[4] }}"
    changed_when: False
```

`show ver`の結果がファイルに出力されます。

### 2.ノード毎にファイル保存する方法
次に、ノード毎にファイル名を作る方法ですが、`inventory_hostname`という変数名を使います。

```yaml:ノード名出力
      dest: "/home/hayashi/{{ inventory_hostname }}show_ver.log"
```

でも、hostsファイルはIPアドレスで作っていると後々困りそうなので、ノード名に変えていくつもりです。LocalDNS建てないと、、、正引きのファイルどうやって自動で作ろう、、、というのはAnsible外のお話ですね。
ルーターってなんやねん

色々あって、ルーターについて調べたのでざっくりと自分用メモ。
間違ってたら教えてください（小声）
# ルーターとは
WAN（インターネット）とLANを繋ぐ機械。
これがないとネットサーフィンは出来ない。
# モデムとルーターとハブ
この3つの違いもメモ
 - モデム
    - ルータの先に接続されているであろう謎の機器。LANから受け取ったデジタル信号を電気的な信号へ変換、もしくはWANから受け取った電気的な信号をデジタル信号へ変換する。
ちなみにこの機器に**ルータ機能があって、なおかつ有線LANだけというのならルータは必要ない**。
 - ルータ
    - 上記で話した謎の機器。**基本はモデムがルータ機能を持っていない場合に使用する。**無線LANも使いたいというのならAP（アクセスポイント）モードとかにしてモデムに接続しないとダメ。
 - ハブ
    - 唐突に出現した謎の機器。複数の端末に有線LANを繋げたい場合は必要。電源タップみたいなもん。
# DHCPサーバー機能
今まで自分は「広大なネットの海のどこかにDHCPサーバーがあって、そいつからIPアドレスを貰ってるんだ」と妄想していたが、実際はそうではなく、一般的にはルータがDHCPサーバーの機能も担っており、ルータからIPアドレスを渡されることでネットサーフィンが出来るらしい。
ちなみにDHCPサーバーに関してはWindowsSeverもその機能を持っているらしいっすよ（他人事）
# 感想
勉強になった（小並感）
preztoのテーマ「pure」でpipenv shell使用時の環境名が「.venv」になる現象への対応メモ

# 現象

pipenvで`PIPENV_VENV_IN_PROJECT`を設定するとプロジェクトディレクトリの下に仮想環境が作成されるようになる。
参考: https://dackdive.hateblo.jp/entry/2018/05/16/100000

zshのテーマにpreztoのpureを使っていると、仮想環境を切り替えた際に環境名が「.venv」と表示されてしまう。

```
~/Documents
❯ mkdir test && cd test

~/Documents/test
❯ pipenv --three
Creating a virtualenv for this project…

~/Documents/test
❯ l
.venv  # プロジェクトディレクトリ下に仮想環境が作成される
Pipfile

~/Documents/test
❯ pipenv shell  # 仮想環境の切り替え
…

~/Documents/test
.venv ❯  # 環境名が「.venv」になる！
```

# 原因

pureのスクリプト内で、仮想環境の設定の場所を示す環境変数`VIRTUAL_ENV`のbasenameを環境名として使用しているため。

```
~/Documents/test
.venv ❯ echo ${VIRTUAL_ENV}
/Users/(User)/Documents/test/.venv

~/Documents/test
.venv ❯ echo ${VIRTUAL_ENV:t}  # zshでは:tをつけるとbasenameになる
.venv
```

# 対応

pureのスクリプト`~/.zprezto/modules/prompt/functions/prompt_pure_setup`を修正する。
`${VIRTUAL_ENV:t}`が`.venv`の場合に、その一つ上のディレクトリ名を環境名として設定する。

```
~
❯ cd .zprezto/modules/prompt/functions/  # ここに各テーマのスクリプトがある

~/.zprezto/modules/prompt/functions master* ⇣
❯ cp prompt_pure_setup prompt_pure_setup.org  # pureのスクリプトのバックアップ作成

~/.zprezto/modules/prompt/functions master* ⇣
❯ vim prompt_pure_setup  # 修正

~/.zprezto/modules/prompt/functions master* ⇣
❯ diff prompt_pure_setup.org prompt_pure_setup  # 修正箇所は以下の通り
192c192,197
< 		psvar[12]="${VIRTUAL_ENV:t}"
---
> 		env_name="${VIRTUAL_ENV:t}"
> 		if [[ "x${env_name}" = "x.venv" ]]; then
> 			psvar[12]="${VIRTUAL_ENV:h:t}"
> 		else
> 			psvar[12]="${env_name}"
> 		fi
```

# 修正後の確認

```
~/Documents/test
❯ pipenv shell  # 仮想環境の切り替え
…

~/Documents/test
test ❯  # 環境名がプロジェクトディレクトリ名になった
```
AISing2019-C「Alternating Path」

- [Alternating Path](https://atcoder.jp/contests/aising2019/tasks/aising2019_c)



## 考察

- ぱっと見上手く解く方法が思いつかない。なのでとりあえず愚直にDFSを書いてみる（BFSでもいいけど、DFSの方がメモ化して高速化しやすい）
- [愚直DFSのコード](https://atcoder.jp/contests/aising2019/submissions/3993169)。`#` →` .`になってる時だけスコアが上がるのに気づかずにちょっと詰まった。（DFS書くのに30分もかかってるんだが）
- ジャッジが頑張ってくれて通らないかなーって思ったけど、まあ普通にTLEだった
- [経路](https://atcoder.jp/contests/abc037/submissions/2174146)みたいなメモ化再帰ができないかなー？って考えた。でもちょっと無理っぽい
- [Ito Campus](https://atcoder.jp/contests/qupc2018/submissions/3887899)みたいに`#`を全部キューに突っ込んでからBFSする方法も考えた。けどだめ。何も関係ない
- DFSの愚直解は$O(H^2W^2)$。多分どこかで無駄な計算をしているのでそれをなんとかしたい
- 次は図を書いてみる。`#`から移動可能な箇所を埋めていくと、以下の図のようなグループ分けができる。
- もしかして、「同じグループに属する`#`は全部同じスコアになる」のでは？という気づきを得る。同じグループ内にある`#`から`.`へは確実に移動できるのでね。
- 一応実験もしてみたところ、上手く動いた。


<img width="229" alt="alternating_path1.png" src="https://qiita-image-store.s3.amazonaws.com/0/218584/7d1daf0d-bb14-4c9a-d946-86cde932f422.png">


## 解法

1. 盤面のループを回し、`#`を見つけたらそこから行ける部分をDFSで埋めていく。このとき、マスにはグループ番号を割り振る。同じグループの`#`からスタートすると、スコアは同じになるので再計算を防ぐために`mp[グループ番号]: スコア`を作る。



## [コード](https://atcoder.jp/contests/aising2019/submissions/3993399)

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long

const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, -1, 1};

int h, w;
char b[444][444]; // 盤面
int group[444][444]; // マスがどのグループに含まれるか。マスにグループIDを割り当てて判別する
map<int, int> mp; // mp[グループ番号]: そのグループの'#'が得られるスコア

// `#` -> '.' の順でいける部分を埋めていく
int rec(int y, int x, int t) {
  group[y][x] = t;
  int ret = 0;

  for (int i = 0; i < 4; i++) {
    int ny = y + dy[i], nx = x + dx[i];
    if (ny < 0 || ny >= h || nx < 0 || nx >= w) continue;
    if (b[y][x] == b[ny][nx]) continue;
    if (group[ny][nx] != 0) continue;
    int cost = (b[ny][nx] == '.' ? 1 : 0); // 異動先が'.'ならスコアが入る
    ret += rec(ny, nx, t) + cost;
  }

  return ret;
}


signed main() {
  cin >> h >> w;
  for (int i = 0; i < h; i++) {
    cin >> b[i];
  }

  int ans = 0;
  int cnt = 1; // グループ番号
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (b[i][j] == '#') {
        if (group[i][j] == 0) { // マスにグループ番号が割り振られていない場合
          int score = rec(i, j, cnt); // '#'からいける部分にグループ番号を割り当てる。
          ans += score;
          mp[cnt] = score; // グループ番号にスコアを登録する。これは、再計算を防ぐためにある
          cnt++; // グループ番号をインクリメント
        } else { // すでにグループ番号が割り振られている場合
          ans += mp[group[i][j]];
        }
      }
    }
  }

  cout << ans << endl;

  return 0;
}
```



## もう少し考察してみる

- `# `→`.`の推移、`.`→`#`の推移を考える。このように推移するものに辺を引いていくと、自然とグループが出てくる。この発想結構自然だなーと思う。
- あと、グループ分けしたやつを連結成分っていうらしい。

<img width="229" alt="alternating_path2.png" src="https://qiita-image-store.s3.amazonaws.com/0/218584/a84cbfc8-946f-78ae-63bf-c7b292f13c01.png">



## 要点

- グリッドもグラフのようにみることができる。
- グラフは移動できる部分を辺で結ぶと嬉しいことがある。例えば、辺で結ばれた部分は自由に移動できたりする。





## メモ

- 連結成分を考えるのは定石らしい
- Union Findでも解けるらしい。つたさんはUFで解いてた
- Alternatingは交互のって意味らしい。Alternating Pathは、交互のパスって意味だったっぽい
OSXでV8JSのインストール

## V8のインストール

```
brew install v8@3.15
```
(最新バージョンではv8jsのインストールに問題があるようです。)


## ext-v8jsのインストール

```
sudo pecl install v8js
```

上記でうまく行かない場合など、最新版のインストールの場合は以下で

```
git clone https://github.com/phpv8/v8js.git
cd v8js
phpize
./configure
make
sudo make install
```

## v8js.soを追加

`extension=v8js.so`を`php.ini`[^1]に追加

## 確認

```
$ php -i | grep v8js
/usr/local/php5/php.d/50-extension-v8js.ini,
v8js
v8js.flags => no value => no value
v8js.icudtl_dat_path => no value => no value
v8js.use_array_access => 0 => 0
v8js.use_date => 0 => 0
```

## リンク

* [UbuntuでのV8JSインストール](https://gist.github.com/koriym/cef916b3a9de5e9fea766f19ae17c1ad)

[^1]: `php --ini`で分かります
Kotlinで同じ文字列が違うと判断されるバグを直す

Qiita初投稿です。よろしくおねがいします。
C#ばかり書いていましたが最近Kotlinをはじめました。いいですよね、Kotlin。擬人化したら絶対に可愛いです。
#UDP通信をしようとしたら困った
簡単な文字列を受信し、ByteArray->Stringに変換してコンソールに写すだけです。(通信に関しては今回は触れません)
で、"finish"という文字列を受信したら通信をやめる、そんな感じにしたかったんです。**したかったんです。**
#同じ文字列なのに等しいと判断されない…
うまくいかなかったときのソースコードは以下の通りです。

```Kotlin:Main.kt
import Mylib.Udp.UdpConnection //自作のUdp通信クラス
import java.nio.charset.Charset

fun main(args: Array<String>)
{
	val port = 2222
	val bufferSize = 16
	val udp = UdpConnection(port, bufferSize)
	var received: String? = null
	
	println("Start")
	while (received != "finish")
	{
		received = udp.receive().toString(Charset.defaultCharset())
		println(received)
	}
}
```

```Kotlin:UdpConnection
package Mylib.Udp

import java.io.FileWriter
import java.io.PrintWriter
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.nio.charset.Charset

class UdpConnection(private val port: Int, private val bufferSize:Int)
{
	fun receive(): ByteArray
	{
		val socket= DatagramSocket(port)
		val data = ByteArray(bufferSize)
		var packet: DatagramPacket? = null
		try
		{
			packet = DatagramPacket(data, data.size)
			socket.receive(packet)
		}
		catch (e: Exception)
		{
			println(e.message)
		}
		socket.close()
		return data
	}
}


```

これを実行中に"fnish"と三回送ったとします。私としてはコンソールには"Start"の後に一度だけ"finish"と出てきて終わっていただきたい。しかし、結果は…

```
Start
finish          
finish          
finish          
```
**?????????なんですか？？これ**
いや、まぁ、文字化けしてるとかならわかるんですよ。
最初はJavaで有名な"=="と"equals"の違いが原因かと思いました。しかし、Kotlinでは参照先の比較は"==="で値の比較は"=="となっているため、今回は関係なさそうです。他にも文字コードや送信機などを疑ってみましたがどれも見当違い…
#結局どうしたか
まず、以下の拡張関数を定義しました。

```Kotlin
fun ByteArray.createString(packet: DatagramPacket) = String(this, 0, packet.length, Charset.defaultCharset())
```
そして上記のreceiveメソッドの型をString?に変更し、リターン部分を下記のように変更しました。

```Kotlin
return if (packet != null) data.createString(packet); else null
```

結果、意図していた動作をしましたが、なぜ前のコードがダメだったのかはわかりません(わかる方いらっしゃいましたらご教示ください)

#最後に
初投稿のため、拙い部分やおかしな部分もあると思いますが、閲覧頂きありがとうございます。関係ないですが、C#では下記のように簡単に実装できたため、Udp通信のハローワールド的なプログラムでつまずくと思いませんでした…

```c#
using System;
using System.Net.Sockets;
using System.Text;
class Program
{
	static void Main(string[] args)
	{
		var Receiver = new UdpClient(2222);
		var ReceivedStr = string.Empty;
		Console.WriteLine("Start");
		while ((ReceivedStr = Encoding.UTF8.GetString(Receiver.ReceiveAsync().Result.Buffer)) != "finish")
			Console.WriteLine(ReceivedStr);
	}
}

```

ここまで言ってJavaの使いやすいUdpライブラリがあったら恥ずかしいですね。(でもあったら使いたいです)
GKEでコンソールからクラスタを作成する時に権限を追加する

「[プログラマのためのGoogle Cloud Platform入門](https://www.shoeisha.co.jp/campaign/book/gcp/)」を読んでいる時にUIが変わっていてハマったのでメモしておきます。

# クラスタ作成画面
Advanced editをクリック。
<img width="927" alt="スクリーンショット 2019-01-13 2.28.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/220908/79038485-0a9d-e531-0e9c-0d4d23a3373e.png">

# Advanced edit
Set access for each APIから権限を設定できます。
<img width="469" alt="スクリーンショット 2019-01-13 2.28.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/220908/686c242a-21f2-9d23-e739-767c987f2d5b.png">

# 権限を設定
よしなに権限を設定します。
<img width="490" alt="スクリーンショット 2019-01-13 2.29.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/220908/0a3bfd02-8e12-362b-b51d-8eca3f1a99f0.png">
pandasのgroupbyを使ってグループ内で最大値（最小値）を持つ行を取得する

# はじめに
データベースのカラムで、カテゴリ変数を値に持つカラムがあるとします。そのカテゴリごとの最大値もしくは最小値の列を求めたいことがあります。
`pandas`の`idxmax()`もしくは`idxmin()`で実現できます。

# 参考
- [pandasで最大値・最小値の行名・列名を取得するidxmax, idxmin](https://note.nkmk.me/python-pandas-idxmax-idxmin/)
- [Pandas：グループ毎に括って最大の値を含む列を抜き出す](http://publicjournal.hatenablog.com/entry/2017/10/08/113544)


# 環境
- Google Colaboratory
- pandas==0.22.0

# 手順
タイタニック号の生死者データを使用します。
最大値の例を以下に示します。最小値の場合は`idxmax()`を`idxmin()`にすればよいです。
NaNはないとして、また、最大値（最小値）の重複はないものとします。

```python
import pandas as pd
import seaborn as sns

df = sns.load_dataset("titanic") # タイタニック号の生死者データ
df = df.dropna() # 今回は本筋に関係ないのでNaNを落とします
df.reset_index(drop=True,inplace=True)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211712/0f40c495-fb8d-0c1c-7579-3ec483436145.png)


`'embarked'`は三つのカテゴリ（C,Q,S）を持ちます。これでグループ化して、それぞれのグループの`'age'`が最大の行を抜き出します。

```python
ddf = df.groupby('embarked')
df.loc[ddf['age'].idxmax(),:]
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211712/ec10de5e-08c6-0ef1-fb5f-435453f65535.png)


`df.groupby('embarked')`でグループ化します。グループ化したデータフレームの`'age'`列から`idxmax()`で、それぞれのグループの最大値のインデックスを取得します。そのインデックスの行を`df.loc`で取得します。
`idxmax()`の挙動としては上から検索して、早く見つかった最大値を採用してるっぽいです。


## 別解
[Pandas：グループ毎に括って最大の値を含む列を抜き出す](http://publicjournal.hatenablog.com/entry/2017/10/08/113544)に紹介されている方法だとより柔軟に書けます。
以下は自分向けに少し改変しました。

```python
def select(df,**kwargs): # colに列名,kindに最大もしくは最小

    if kwargs['kind'] == 'min':
        val_r = df[df[kwargs['col']] == min(df[kwargs['col']]) ]
    elif kwargs['kind'] == 'max':
        val_r = df[df[kwargs['col']] == max(df[kwargs['col']]) ]
    else:
        raise Exception("パラメータ不正")

    # 全く同じ行があった場合は削除
    val_r = val_r.drop_duplicates()

    return val_r

# 最大値の行を抜き出す
df2 = (df.groupby(['embarked'])
       .apply(select,col='age',kind='max')
      )
df2 = df2.reset_index(level=1).reset_index(drop=True)
df2.index = df2['level_1'].values
df2.drop('level_1', axis=1, inplace=True)
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/211712/c8e9c223-7c9c-ac09-9940-fabcf300a85a.png)

`apply`するとインデックスがカテゴリになるので、それを元のインデックスにするために処理が必要になります。
また、applyは少々遅いので、大規模データだと時間がかかってしまうのが難点です。

# おわりに
pandasの操作をなるべく高速に実行したい。
Xamarin.Formsにおける色指定の方法(C#、Xaml)

これはXamarin.Formsにおける色指定の方法です.

備忘録

#Xamlでの色指定
Xamlで色指定する場合は、ビルトインの色名、RGB値、アルファ値（透明度）つきRGB、TinyRGB、アルファ値つきTinyRGBで指定できる。

```xml
        <Label Text="Sea color" BackgroundColor="Aqua" />
        <Label Text="RGB" BackgroundColor="#00FFFF" />
        <Label Text="Alpha plus RGB" BackgroundColor="#2200FFFF" />
        <Label Text="Tiny RGB" BackgroundColor="#0FF" />
        <Label Text="Tiny Alpha plus RGB" BackgroundColor="#C0FF" />
```

#C#での色指定
C#でも同じように色名（構造体）や16進表記（文字列）で指定できる。

```csharp
            var label = new Label();
            label.BackgroundColor=Color.Aqua;
            label.BackgroundColor = Color.FromHex("#00FFFF");
            label.BackgroundColor = Color.FromHex("#2200FFFF");
            label.BackgroundColor = Color.FromHex("#0FF");
            label.BackgroundColor = Color.FromHex("#20FF");
```

他にも

```csharp
            label.BackgroundColor = Color.FromRgb(0x00, 0xff, 0xff);
            label.BackgroundColor = Color.FromRgb(0x00, 0xff, 0xff,0x22);
```
JSの関数についての現在の理解

##関数とは
- 関数は文が集まったもの（複数の処理を一つの塊として行うもの）
- ある値（引数）を与えられて、その値をもとに処理をしてその結果を返すもの

例）寿司（サーモン）
寿司を作る（という関数）
１、シャリを作る
２、ネタ用意する
３、シャリとネタを合体！
４、寿司

という**１つのものを作り上げるのに必要な複数の処理を１つにまとめたもの**　


 **関数の構文**

```定義.js
function　変数名(引数){
//処理
}
```


```func.js
function total(a,b){　//a,bは引数で4,5が代入されて、本文実行へ
   console.log(a+b);
   return a+b; //total関数の値に9を返す;
}
total(4,5);//(a=4,b=5)という値を与えて、外部から呼び出し
```

##戻り値（return）とは
戻り値を理解する前に```console.log```と```return```の違いについて理解したい。

```console.log``` を理解する前に**なぜコンソールがあるのか**について理解してみる

私はコンソールを主に**デバッグ用(バグの発見と修正)**として利用している。

###「どんな数を思い浮かべても、必ず３になるマジック」を例に違いを理解

<p><a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1116589591">３になるまでの過程のリンク</a>←クリック！</p>

```console.js
//理想(思い浮かべる数：４)
function magic(num){
   pro1 = num + 1;  //5になりたい
   pro2 = pro1 * 2; //10になりたい
   pro3 = pro2 + 4; //14になりたい
   pro4 = pro3 / 2; //7になりたい
   return pro4 - num;//「君の思い浮かべた数字は３だ！！！」
}
console.log(magic(4));//関数の呼び出し


--------------------------------------------------------------------------------
//デバッグ
function magic(num){
   pro1 = num + 1;  //5になりたい
   pro2 = pro1 * 2; //10になりたい
   pro3 = pro2 + 4; //14になりたい
   pro4 = pro3 / 7; //7になりたい
   return pro4 - num; //僕：「君の思い浮かべた数字は2だ！！！」　君：「違うよ？？？」　僕：「恥ずかしい。。」
}
console.log(magic(4));//関数の呼び出し



//=>console.logで確認
function magic(num){
   pro1 = num + 1;  //5になりたい
   console.log(pro1);//5
   pro2 = pro1 * 2; //10になりたい
   console.log(pro2);//10
   pro3 = pro2 + 4; //14になりたい
   console.log(pro3);//14
   pro4 = pro3 / 7; //7になりたい
   console.log(pro4);//2 <====== ここが問題！！！
   return pro4 - num; //僕：「君の思い浮かべた数字は-2だ！！！」　君：「違うよ？？？」　僕：「恥ずかしい。。」
}
console.log(magic(4));//関数の呼び出し

//console.log(pro4)により、pro4 = pro3 / 7が間違いであることを確認！

```
**つまり**
```console.log``` は、バグがないか確認するためにコンソールに表示するための関数
```return``` は、関数に処理後の値を返してかつ、関数の処理を中止して抜ける（ループのbreak文的な存在）

＊関数は複雑な処理をした結果、引数の値をもとに処理結果が関数に返されれば目的は達成なので```return```で処理を終了にできる
限られた時間でのソースコードレビュー　～そのレビュー、過剰ではありませんか？～

とあるWebアプリケーションのパッケージベンダーにいる者です。
自分はよくレビュワーとしてコードレビューをしているのですが、周囲の他のレビュワーに話を聞いて

「時間が全然足らない」
「うまく指摘できない」

という悩みをよく聞きます。
今回自分が普段思っているそれらの課題について対策をまとめたいと思います。

# 限られた時間内でコードレビューするには

## 1.コードレビューは単体テストと考える

コードレビューで見る範囲はできるだけ絞る、ということです。
要求仕様に対する実装が正しいかどうかまで見るとちょっと過剰で、
時間が足りなくなってしまいます。

要件定義や設計までさかのぼることはせず、
書かれているコードの妥当性だけを見ていきます。

ただし修正範囲のコードについてはすべてしっかり見ます。
ホワイトボックステストでC1カバレッジを通すのと同じように、
分岐もしっかり見ていきます。

要件定義通りになっているかは総合テストで、
設計通りになっているかは結合テストで確認すればよいです。

## 2.レビューで"見ない"視点を決める

レビュー観点はどうするか、という点です。
観点は決めておかないとレビューする人もされる人も終わりが見えず、
時間切れで中途半端に打ち切られてしまいます。

「見る視点」を決めるより「見ない視点」を決めるのは、
**「見ない視点」は別の方法で確認する計画が立てやすい**からです。

たとえば「今回はパフォーマンス観点では見ない」と定めておけば、
それらは後で性能テストでカバーすれば良いことが明確になります。

## 3.黙々と見る

レビュワーと製造担当者が面談みたいな形でコードレビューする場合があるのですが、
顔合わせはせずにデスクで黙々と見ていくのがよいです。

ただし不慣れな人が書いたコードなど、書き方の甘さや意図の見えにくさがあるようであれば
顔合わせてレビューするほうが教育的効果が期待できます。

# 具体的にどうレビューするのか
古い記事ですが、[IPAのセキュアプログラミング講座](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c103.html)の中で以下の段階分けが提唱されています。

~~~
下読み      どこに何があるかの把握
成熟度点検  ある程度の品質水準に達しているか否かの評価
機能点検    バグ、すなわち機能面の不具合の検出
脆弱性点検  セキュリティ脆弱性の検出
~~~

これをしっかりやるとやや過剰気味ですので、アレンジしていきます。

## 下読み

これについては以下の理由からサラっと流しましょう。

* レビュワー本人も同じプロジェクトメンバーであれば  
  そのシステムのアーキテクチャーをある程度把握しているはず。  
* どこに何があるかは、Diffで出てくる。

自分はプロジェクトメンバー外ですが、パッケージベンダーに所属しており、
同じアーキテクチャー上に実装されていることがほとんどですので、この工程を省略しています。

## 成熟度点検

* ソースコードが読みやすいかどうか。

ここはあまりウェイトを置いていません。
レビュワー本人の過去の経験をもとに次のような点を主観で判断していきます。

* メソッド内のコード量が多くないか
* ネストが深くないか
* 冗長ではないか
* 意味がわかるか（実装の意図がつかめるか）

普段から[リーダブルコード](https://www.amazon.co.jp/dp/4873115655/)などの書籍を読んでおくといいかもしれません。

## 機能点検

* 機能によって必要な実装がされているか
* 機能によらず必要な実装がされているか

前者は、たとえば「買い物かごに入った商品を表示する」という機能があった時
合計金額の計算はDecimal型を使っているかとか、
端数は四捨五入／切り捨て／切り上げになっているかとか、
そういった視点で見ていきます。ただし単体レベルを超えないように。

後者は、ループ中の変数がちゃんと初期化しているかとか
例外が発生したときでもロールバックしているかとか、
使っているメソッドやステートメント、記法が問題ないかを見ていきます。
ここは成熟度点検とも重なってきますが、こちらに分けました。

## 脆弱性点検

* 社内ルールに則っているか

セキュリティ脆弱を見つける方法としてのソースレビューは骨が折れます。
一般的なセキュリティ脆弱はツールなどを使って見つけていくことにしておき、
そういったツールでは見つけづらいコーディング規約や独自アーキテクチャーのルールに従っているかを見ます。

ツールはWebサイトをブラックボックス的に叩くもののほか、
ソースコードの静的解析をするホワイトボックス的なものもあります。(IBM AppScan Sourceなど)

---

今回「限られた時間で」コードレビューするための1つの対策として自分の取り組みを紹介しました。

時間が十分に確保できるのであれば良いのですが、パッケージベンダーやSIerは納期に間に合わせるために
どうしても削らなけばならない状況が発生しますので、この対策が現場の一助になれば幸いです。
久しぶりに起動したchromedriverが動かない

rbenvを使っていて、別のバージョンのrubyで
かつ久しぶりに chromedriver を起動したら動かないことがあった。

```
$ gem uninstall chromedriver-helper
```

- remove it from rbenv shims (which chromedriver for that)
- Download directly http://chromedriver.storage.googleapis.com/index.html
- plug chromedriver somewhere on the $PATH (I just plopped in ~/bin)

上記手順を参考に、自分の環境にあるchromedriverを削除して、
改めて最新版の `chromedriver` を[直接サイト](http://chromedriver.storage.googleapis.com/index.html)からダウンロードしてきて、

`/Users/ユーザー名/.rbenv/shims/chromedriver`

てな感じで配置してやりました。

参考：
https://github.com/SeleniumHQ/selenium/issues/5248#issuecomment-353742737
MacでTime Machineのバックアップを始めた途端自宅Wi-Fiが繋がらなくなった件

#MacでTime Machineのバックアップを始めた途端自宅Wi-Fiが繋がらなくなった

##原因
"Wi-Fiが繋がらなくなった場合の対処法"みたいな記事をかなり見て試しましたがうまく行かず。。。ようやく以下の記事に辿りつきました。

>[Macに外付けHDDを接続してWiFiが繋がらなくなった場合の対処法](https://www.useful-notes.com/mac/extarnal-hdd/)

原因はUSB3.0とWi-Fiの干渉とのこと。


##なぜUSB3.0とWi-Fiが干渉するのか
以下記事によると、USB3.0機器から発生する高周波ノイズがちょうど2.4~2.5Ghz程度であり、そのため2.4Ghz帯の無線LAN機器と干渉を起こすそうです。

>[USB3.0機器から発生するノイズは、2.4Ghz無線LANに悪影響を与えるらしい。](https://freesoft.tvbok.com/tips/web/usb3_24ghz_wifi.html)

高周波ノイズはデバイス本体、ケーブル、コネクタすべての箇所から発生するようなので、mac本体の無線LAN受信機がある位置からこれら全てをできるだけ遠ざけてやる必要があります。

ある程度距離を離すという古典的な対応でもある程度の効果が得らられようで、僕のMAcBook Proの場合、USB接続のポートを左側から右側にするだけでなんの問題もなくWi-Fiが繋がるようになりました。

##結論
USB繋いでWi-Fiが繋がらなくなったら、

1. 無線ルーターを5.0Ghz帯のものにするか
2. 自分のPCの無線LANレシーバーの位置を見極めてデバイスを離してやるか

しましょう。
GitHubに怒られたのでpackage-lock.jsonを見直す

GitHubに怒られる。

![alert.png](https://qiita-image-store.s3.amazonaws.com/0/129398/5c20b336-1fcd-afd5-1509-86a14ecbd074.png)

npmのpackage-lock.jsonに記載されているパッケージのバージョンが古く、当該バージョンに既知の問題があるようで。

# 解決したことにする

![dismiss.png](https://qiita-image-store.s3.amazonaws.com/0/129398/bf941d9a-d170-902c-02ea-5a591fa46cc5.png)

**Dismiss（解決する）**ボタンを押すとアラートを消せます

* A fix has already benn started
    * 修正は既に始まっている
* No bandwidth to fix this
    * 修正する余力がない
* Risk is tolerable to hits project
    * プロジェクトを成功させるためには許容できるリスクだぜ
* This alert is inaccurate or incorrect
    * 何かの間違いだ！
* Vulnerable code is not actually used
    * 脆弱なコードは実際には使われてないよ

どれも根本的な解決になっていないので`package-lock.json`を詳しく見ていきます。

## 根本的に解決する

### そもそもpackage-lock.jsonは

https://docs.npmjs.com/files/package-locks

`npm-install`を行うとpackage.jsonに記載された依存関係に基づきnode_modulesツリーが生成され、node_modulesディレクトリ下にパッケージ群がインストールされます。同じpackage.jsonは理論上いつでもまったく同じnode_modulesツリーを生成しますが、様々な理由でそのようにはならない場合もあります。このような問題を防ぐためにnpmは`package-lock.json`を使用します。

`package-lock.json`には`package.json`よりもより具体的で再現可能なnode-modulesツリーに関する記述がされており、このファイルが存在するなら以降のインストールでは`package.json`から再度依存関係を計算しなおすのではなく、`package-lock.json`の中身を見てnode_modulesをインストールします。

このファイルはソースリポジトリにコミットされることを意図されており、チーム開発において各メンバー間で完全に同一な環境を構築するのに役立つでしょう。やったね。

### package-lock.jsonが変更されるタイミング

`package.json`が存在し`package-lock.json`が存在しない場合、`npm install`を実行すると`package-lock.json`が自動で生成されます。 
`npm install`、`npm rm`(`npm uninstall`)、`npm update`コマンドを実行した場合、`package.json`が実行したコマンドに応じて更新されます。この時`--no-save`オプションをつけると`package.json`は更新されません。
前述のコマンドを実行すると、同時に`package-lock.json`も同様に更新されます。

オプションに関しては公式ドキュメントを読みましょう
https://docs.npmjs.com/cli/install
https://docs.npmjs.com/cli/uninstall.html
https://docs.npmjs.com/cli/update

`package-lock.json`は直接編集するものではなく、前述のコマンドを実行することで自動的に生成されるものです。
ということで`package-lock.json`に記載されたパッケージを更新するためには`package.json`のほうを修正してnpmパッケージを更新すれば問題は解決しそうです。

### npm-check-updatesでpackageを更新する

`npm update`を実行すれば`package.json`に記述されている依存関係に基づいてnode_modulesが更新されますが、記述の仕方によっては依存パッケージのメジャーバージョンが上がらず、問題の解決には至らない場合があります。
その場合は`package.json`の記述自体を見直しましょう。

`npm-check-updates`を使用することで更新可能なパッケージを確認、一括して`package.json`の依存パッケージの記述を変更できます。

インストール

```
$ npm install -g npm-check-updates
```

パッケージ更新の確認

```
$ ncu

[..................] / :
 react-scripts             1.1.1  →    2.1.3
 react-redux              ^5.0.5  →   ^6.0.0
 redux                    ^3.5.2  →   ^4.0.1
 eslint                  ^4.18.0  →  ^5.12.0
```

`package.json`の修正

```
$ ncu -u

[..................] - :
 react-scripts             1.1.1  →    2.1.3
 react-redux              ^5.0.5  →   ^6.0.0
 redux                    ^3.5.2  →   ^4.0.1
 eslint                  ^4.18.0  →  ^5.12.0
```

`package.json`が更新されたのでパッケージを更新します。

```
$ npm install
```

更新が完了すると`package-lock.json`も更新されます。
変更をリモートリポジトリにプッシュしましょう。

![no-alert.png](https://qiita-image-store.s3.amazonaws.com/0/129398/63c8a089-d367-e153-ce56-f8feb3c2944a.png)

やったね！
配列の要素を比較する（Java）

ソースコード

```java:ArrayTest.java
public class ArrayTest {
	public static void main(String[] args) {
		String[] array = {"あいうえお", "あいうえお", "かきくけこ", null, null};
		for (int i = 0; i < array.length-1; i++){
			if (array[i] == array[i+1]) {
				if (array[i] == null) {
					System.out.println(array[i]+" と "+array[i+1]+" は両方NULL");
				} else {
					System.out.println(array[i]+" と "+array[i+1]+" はおなじ");
				}
			} else {
				if (array[i] == null || array[i+1] == null) {
					System.out.println(array[i]+" と "+array[i+1]+" は片方NULL");
				} else {
					System.out.println(array[i]+" と "+array[i+1]+" はちがう");
				}
			}
		}
	}
}
```

出力結果

```
あいうえお と あいうえお はおなじ
あいうえお と かきくけこ はちがう
かきくけこ と null は片方NULL
null と null は両方NULL
```
安倍総理が今年一番多く発言した単語を調べてみた

### 国会の発言データを使って出現単語をカウントしてみる
[様々な記事の単語をカウントするプログラムを作ってみた](https://qiita.com/Sak1361/items/2519f29af82ffe965652)
と
[国会議事録検索システムのAPIを使って議事録を取得してみる](https://qiita.com/Sak1361/items/ca8bdf5c699f6a8a7f92)
を組み合わせてやっていきます。

# 議事録の取得
まず議事録を取ってきましょう。
今回は2018年の安倍総理の発言を取得します。パラメータは以下の通り。

- 発言者：安倍晋三
- 取得日付の始点：2018年01月01日
- 取得日付の終点；2018年12月31日
これで2018年に安倍総理の発言を記録にある限り取得できます。

取得したファイルは[こちら](https://github.com/Sak1361/word_count/blob/master/diet_statements/Fullof_ABE.csv)
3MBほどありますね。まずはこれを使っていきます。

# 単語をカウントしてみる
内容的には[Wikipediaの記事の単語をカウントしてみた](https://qiita.com/Sak1361/items/bad78b5e26ce0f82de46)とあまり変わりません。
[様々な記事の単語をカウントするプログラムを作ってみた](https://qiita.com/Sak1361/items/2519f29af82ffe965652)のプログラムをそのまま使ってみます。
プログラムの使い方はこちら

```
python count_word.py -i (inputするファイル) -o (結果出力ファイル)
```

先ほど取得したファイルをそのまま入れて動かしてみます。
分かりやすいように品詞を名詞の一般形と固有名詞に絞ってカウントします。
結果のグラフはこちら
![abe2018.png](https://qiita-image-store.s3.amazonaws.com/0/339669/9423bc41-d341-8d26-4ec2-32930d7f2586.png)

内閣総理大臣と安倍晋三が多いですね。。。

それもそのはず、議事録の発言データはこんな感じになってます。

```
○内閣総理大臣（安倍晋三君）　出入国管理及び難民認定法は、....
```
発言の最初に役職と名前があるんですねぇ、そりゃ一番数値がでかくなりますわ

てことで最初の役職＋名前を取り除きます。

## 発言者の名前と役職を取り除く
分かち書きした後に取り除こうとも考えたのですが、発言で「内閣総理大臣として〜」みたいな発言もある可能性があるため、mecabを通す前に処理したいと思います。
前処理段階で、以下の処理を追加しました。

```rm.py
pattern = "(.*)　(.*)"  #全角スペースで分ける
if line.find('○',0,10) == 0: #○から名前なのでここで取り除く
    sep = re.search(pattern,line)
    line = line.replace(sep.group(1),"")
```
力技ですけどとりあえずこれでいいはずです。

これを適用して再度カウントしてみます。
![abe2018rm.png](https://qiita-image-store.s3.amazonaws.com/0/339669/317a6481-4e3c-3b31-ead6-f38762aa3c1e.png)

スッキリしましたね。それっぽい結果になりました。

## 結果の感想
やはり、内閣総理大臣。「国民」や「日本」「わが国」などの発言が上位にありますね。
その次に「北朝鮮」と出てきたのは確かになぁと思わせる単語ですね。「責任」も割と高い頻度で使われている事も分かりました。
総合的に**へぇ**と思わせる結果になりました（自己満足

# 品詞の条件を変えて再度実行してみる
割といい感じの結果が出たので色々条件を変えて実行してみます。
先ほどでは名詞・一般形or固有名詞で絞ってみましたが、今度は品詞の条件を変えて実行してみます。

・全ての品詞をカウント
![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/339669/db320367-2dc9-a589-c423-f600c5732fa4.png)
まぁそうなるよね


・名詞と形容詞をカウント
![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/339669/e832b898-9412-79a7-02d7-c05d94b28b78.png)
改悪された感がありますね・・・
あと、記号が入っていると思ったらこれ漢数字の０でした。mecabだと漢数字はまとまりで認識してくれないようです。

・漢数字以外の名詞全て
![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/339669/154688b8-7db9-e239-a45e-c9643cdb2dcf.png)
上位の単語が変わりましたね。先ほどよりもより連想しやすい単語が増えたように見受けられます。
絞り込むのは大枠の方が良いようです。

### どの品詞に絞れば良策か
上記で一番見やすい結果だったのが

- 名詞+一般形or名詞+固有名詞
- 数字以外の名詞全部

でした。
個人的な見解としては、**固有名詞**等に絞った方がより分かりやすい単語が出てきていると考えました。


# 最後に
形態素解析&カウントだけでも比較できそうな結果になってくれました。
次は年別の発言などもまとめてみようと思います。
【初心者記事】1.Unityでサバイバルゲームを作り始めました

# Unityでサバイバルゲームを作り始めました！ 

　今日よりポートフォリオも兼ねたゲーム制作を始めました。
　グラフィック部分は自分ではとても作りきれないので、有料のアセットを購入しています。

　予定ではSteam等での販売を最終目標していますが、はてさてどうなることやら。

　初心者にしか理解できない躓きポイントを、Qiitaで書いていけたらいいなと思っております。



#現状の私のスペック

　・Unity歴：半年未満
　・プログラミングスキル：基本文法理解程度
　・学歴:高卒
　・職歴:5年連続フリーター
　・年齢；23歳

　……と、まぁこんな感じです。お先真っ暗ですね。
　自分語りの如く唐突にスペックを掲載した理由としては、もし『Unity　サバイバル』等を検索し、
　私のQiitaを開いた未来のUnityエンジニアが

　「こんな奴ゲームでも作れるなら俺でも余裕でしょ！」
　
　と思って欲しいからです。　
　何事もスタートが大事ですからね。

#使用したアセット

![7e3010e3-df26-4066-bbd9-10584a9d121f.jpg](https://qiita-image-store.s3.amazonaws.com/0/286514/fb5b4b1a-6b1c-e184-b77e-b513dbd14014.jpeg)
[POLYGON - Town Pack](https://assetstore.unity.com/packages/3d/environments/urban/polygon-town-pack-121115)

↑が一番思い描く世界観に近かったので、こちらを購入しました。

Unityでdemoと書かれたSceneを開くとこんな感じ
![スクリーンショット (322).png](https://qiita-image-store.s3.amazonaws.com/0/286514/ff5686c0-07c6-17ba-ee99-f944661fd5a8.png)

うん、良い感じだ（孤独のUnityエンジニア見習い

ステージの拘りは無いので、このdemoをそのままマップとして使用していきます。

それではまた次回！
WSLのUbuntuの18.10へのアップグレードで躓いたところ

この記事ではMicrosoft Storeにある3つのUbuntuのうちの16.04でも18.04でもない無印のUbuntuをアップグレードした体験をもとにしたものであり、他2つのUbuntuでも同様にアップグレードできるかは確認していません。

WSLのUbuntuを18.04から18.10へアップグレードするのは通常と同じく

```
sudo do-release-upgrade
```
のコマンドで行えますが、このコマンドを実行する前にいくつかの作業を行わないとアップグレードができません。
#まずはアップデートとアップグレード#
```
sudo apt update && sudo apt dist-upgrade
```
#次にrelease-upgrades の Prompt 行をltsからnormalに変更する#
WSLのUbutuはデフォルトの状態では/etc/update-manager/release-upgradesのPrompt行がltsになっているのでこれをnormalに変更します。

```
sudo vim /etc/update-manager/release-upgrades
```
などでファイルを開き書き換えます。きちんと書き換えができればvimを用いなくても構いません。
#lxdとlxd-clientを削除する#
ここまでは通常のLTSのUbuntuをアップグレードするのと同じでしたがこの後がWSL特有の作業になります。

WSLではsystemdが動いていないためsnapを使用できません。
そのため18.10からsnapによるインストールに変わったlxdとlxd-clientがインストールされたままだとUbuntuのアップグレード時に同時にアップグレードしようとしてエラーになります。これはアップグレードを実行する前にlxdとlxd-clientを削除しておくことで回避できます。
この2つを削除するために以下のコマンドを実行します。

```
sudo apt purge lxd && sudo apt purge lxd-client
```
(恐らくpurgeではなくremoveでも大丈夫だと思いますが念のためpurgeにしてあります)
#アップグレードする
あとは通常と同様にアップグレードするだけです。

```
sudo do-release-upgrade
Netlify CMS「Failed to persist entry: API_ERROR: Not Found」

GitHub組織アカウントのリポジトリで、Netlify CMSで保存時に、
`Failed to persist entry: API_ERROR: Not Found`
が出て、ハマったので解決方法をメモ。

## 症状
記事をSaveやPublishしようとすると、ウィンドウ上部に以下のようなトーストが表示される。
![エラー](https://i.gyazo.com/dca072f5b546f22d997931d799aa7779.png)

## 対策
GitHub組織アカウントの設定で、サードパーティアプリケーションのアクセスポリシーに制限がかかっているので解除する。

https://github.com/organizations/組織アカウント/settings/oauth_application_policy
の、「Remove restrictions」ボタンを押す。
![oauth_application_policy](https://i.gyazo.com/9ab8ccb47ab258cb9f8dc64157504917.png)
確認画面が出るので、[Yes]

これで、エラーが出なくなる。

## 参考
https://github.com/netlify/netlify-cms/issues/1816
RAK811 TrackerBoard ・RAK5205 セッティング

RAK811 TrackerBoard とRAK5205はそのままではLoraWANには繋がりません。
まずは、ファームウェアを変更する必要があります。

RAK811　TrackerBoard は、ジャンパーを一個左へ
RAK5201は、付属しているジャンパーを該当箇所へ取り付けます。
![RAK811-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/1d55e9d9-ebc9-97dd-d1f6-41ad617da6df.jpeg)

・rak811_tracker_classA.binと
https://github.com/RAKWireless/RAK811_BreakBoard/tree/master/bin
Flash Loader Demo.zipをダウンロード

・RAK5205-WisTrio-LoRa
https://github.com/RAKWireless/RAK5205-WisTrio-LoRa/tree/master/doc/Firmware
Flash Loader Demo.zipとRAK5205_HF_trackerboard.binをダウンロード

Flash_Loader_DemonstratorをインストールしDemonstrator GUIを起動します。

接続しているシリアルポートを選択し、Nextをクリック
![RAK811-firm-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/9ce52182-1bba-2c51-940e-e1cd401f0d6a.jpeg)
Nextをクリック
![RAK811-firm-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/79994790-f0df-bc02-66ba-c8c6fa6c72b1.jpeg)
STM32L1_Cat2=128Kを選択しNextをクリック
![RAK811-firm-3.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/9c438687-b800-c555-d893-f6a1897968fb.jpeg)
赤印をクリック
![RAK811-firm-4.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/eab070d6-7f08-0eeb-72ca-28356d42f6f6.jpeg)
拡張子をBinを選択
![RAK811-firm-4-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/bc9f5fe1-34fd-1a93-c104-89699eba91df.jpeg)
RAK811　TrackerBoard はrak811_tracker_classA.binを
RAK5205はRAK5205_HF_trackerboard.binを選択し、開くをクリック
![RAK811-firm-4-2.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/0311f55b-95c6-b595-12e0-186a7b99c62a.jpeg)
nextをクリック
![RAK811-firm-4-3.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/53ac90f0-d5de-d1de-2d1c-343c34c11823.jpeg)

ジャンパーピンを元に戻します。
RAK811　TrackerBoardは、ひとつ右へ
RAK5205は取り外します。

![RAK5205-1-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/285344/29a05a68-267a-dff1-93b6-045c7aebce4a.jpeg)


以下設定は、LoraButtonと一緒になりますので、こちらを参照ください。
https://qiita.com/usashirou/items/f713b61362edf10c347d