OmniAICreator/Qiita-1.07M huggingface dataset:
Aidemy1回目　メモ　「9/10」

適用にTwitterを周回してエンジニアっぽい人のツイート眺めてたらAidemyというサービスを発見。
Aidemy | 10秒で始めるAIプログラミング学習サービスAidemy［アイデミー」
https://aidemy.net/

前からAIは興味があったので、さっそく触ってみた。
気になったところはメモを残しつつ進めてみた。

#Aidemy1回目メモ
##Pythonとは
1. 1990年代生まれ
2. 2系と３系が存在
3. 人口知能分野で最も利用
4. pythonは、if、ifelse、for文の次の実行分の前は必ずインデントをしなければならない。
5. ライブラリが揃っている。

|計算ライブラリ(無償で利用可能)|人口知能ライブラリ|Webアプリフレームワーク|
|:--|:--|:--|
|NumPy|scikit-lern|Flask|
|SciPy|Tensorflow|Django|
|Pandas|-|-|

##python入門編メモ
1. コメント文は#で入れる。
2. print関数は"(ダブルクォート)や'(シングルクォート)は計算させた結果を出力する場合は不要。
3. print関数の()内に計算式を入力した場合は、計算結果が整数(int型)で出力。
4. print関数は"(ダブルクォート)や'(シングルクォート)を付けた場合は、文字列として認識。

・ 演算子

|演算子|内容|例|
|:--|:--|:--|
|+|加算※|a + 2|
|-|減算|a - 2|
|*|乗算|a * 2|
|/|除算|a / 2|
|%|余りの計算|a % 2|
|**|べき乗|a ** 2|

※ 文字列の連結も「＋」で可能。

・ Pythonの型

|型名|内容|
|:--|:--|
|Str型|文字列|
|Int型|整数|
|Float型|浮動小数点|

　異なる型同士では結合・計算できない。
　数値であっても、Str型で保存されている場合には計算できない。
　Str型の値で掛け算 をした場合、値が乗数の個数分並んで出力される。

・ 比較演算子

|型名|内容|
|:--|:--|
|a == b|aとbは等しい|
|a != b|aはbと等しくない|
|a > b|aはbより大きい|
|a >= b|aはbより大きいまたは等しい|
|a < b|aはbより小さい|
|a <= b|aはbより小さいまたは等しい|

・ if文の書き方
　※条件式の後ろには「:」を付ける事。

```py
if n == 1:
    print("ほげほげ")
```
wcコマンドのmオプションって何に使ってるの？

# `wc -m file`って使ったことある？
普通に`wc -l .txt`を叩こうとしたらタイプミスした時に以下のようにでて、mあったのかと思って調べて見た。

```
$ wc -p
wc: illegal option -- p
usage: wc [-clmw] [file ...]
```
`-clw`はなんとなく知ってたけど`m`あったのか。

#とりあえず適当にファイルを作成して使ってみることに

```:test.txt
aaaaaa
aaaaa
aaaaa
aaaaa
```

```
$ wc -m test.txt
      25 test.txt
```
調べて見たら`Print Char Count`らしい。なんでm??
でもなんで25？`a`という文字は21文字しかない。

```
$ echo 'a' | wc -m
      2
```
？？

```
$ echo '' | wc -m
      1
```
!!?

#結論
カウントは空文字でも1から始まって、それが各行に対して計算されるので、
7+6+6+6=25ということで25と出力されていたらしい。

#結論2
誰かこれ使ってる人いるの？
Udemy - ゼロからPythonで学ぶ人工知能と機械学習 : Python基礎編

# [みんなのAI講座 ゼロからPythonで学ぶ人工知能と機械学習](https://www.udemy.com/learning-ai/learn/v4/overview)

- python未経験
- 主なバックグラウンドはC
- 私用ではUnityでC#使用
- 仕事ではPHP+HTML+CSS+JavaScript+SQLでWebサービス構築。ただしこちらはPMとして。

### 複数行へのコメント挿入
> Ctrl + /

### 日本語対応（エラー止める）
ファイル先頭に

```py
#coding: UTF-8 
```

### 文章を乗算で繰り返す
```py
a = "Hello"

d = a * 5
print d
```
```text:実行結果
HelloHelloHelloHelloHello
```

### タプルとは？
変更できない配列。DefineやConst的に使う？

### 辞書とは？
連想配列的に文字列等を添字として対応する要素を呼び出すことができる。

### Debugger
- 行番号をクリックすることでブレイクポイントを入れ、指定した行で実行を止める。
- 実行は `Debug"ファイル名"` で実施。
- ブレイクポイントで止まるので、そこからStep into(F7)で１ステップずつ処理を進めていく。
- 「その行の左辺」の値が更新されるのは次行に移った時。

### 多重リスト List in List
- ベクトル・行列を描くことができる。

```py
a = [[2012, 2013, 2014], [2015, 2016, 2017]]
b = a[1][0]
print b # １番目リストの０番要素にアクセス

a.append([2018, 2019])
print a # リストを追加

a[2].append(2020)
print a # リスト内のリストに要素追加
```
```text:実行結果
2015
[[2012, 2013, 2014], [2015, 2016, 2017], [2018, 2019]]
[[2012, 2013, 2014], [2015, 2016, 2017], [2018, 2019, 2020]]
```

### クラス
- クラスの定義、変数・メソッドの定義、インスタンス生成
 
```py
# Define Class
class Dog:
    # property
    name = ""
    # Method
    # 必ず引数部にselfを書く
    def bark(self):
        # メソッド内でプロパティにアクセスする場合は "self." が必須
        m = self.name + " : Bow-wow!"
        print m

# Create instance
pochi = Dog()
pochi.name = "POCHI"
pochi.bark()

hachi = Dog()
hachi.name = "HACHI"
hachi.bark()
```

# クラスとリスト、For文の組み合わせ
- 生成したインスタンスは基本的に通常の変数、配列等と同じように宣言・アクセスすることができる。

```py
# Value値の自乗値をReturnする
class Calculation:
    value = 0
    def square(self):
        s = self.value * self.value
        return s

calcs = [Calculation(), Calculation(), Calculation()]

calcs[0].value = 3
calcs[1].value = 4
calcs[2].value = 5

for c in calcs:
    print c.square()
```
```text:実行結果
9
16
25
```

# ファイルオープン／クローズ、ファイル読み込みおよびその際のキャスト
- ファイルを掴んでクローズする処理はC等と同様だが、読み込みと同時にキャストで整数型等に変換可能。

```py
score_list = []

# Read CSV file in same directory
score_list_file = open("score.csv")

for score in score_list_file :
    score = score.rstrip() # Delete line break
    score = score.split(",") # Sprit by ,
    # score_list.append(score)
    # [0] read as text, [1] cast for integer
    score_list.append([score[0], int(score[1])])

score_list_file.close()

print score_list
```
```text:実行結果
[['Taro', 78], ['HHanako', 89], ['Ichiro', 68], ['Keita', 54], ['Yuko', 89], ['Reiko', 78]]
```
Koinでインスタンス生成時にActivityをinjectする

Koinを使ったをDI行った際にDagger Androidの`AndroidInjector`を使った場合のように、Activity/Fragment側でinjectしたクラス(Presenterなど)に対してActivity/Fragmentのインスタンスをコンストラクタインジェクションする方法が分からなかったので調べました。

## 対象となるクラスの定義
今回のサンプルとしてコンストラクタパラメータとしてActivityおよびUseCaseを必要とするPresenterを定義します。
(UseCaseクラスのインスタンス生成に関しては別途モジュール定義がされているものとします)

```kotlin
class LoginPresenter(private val activity: Activity, private val loginUseCase: LoginUseCase) {
}
```

##モジュールの定義

上記の`LoginPresenter`を生成するためのモジュール定義は以下のようになります。  
通常のモジュール定義と異なり、`LoginUseCase`に関しては`get()`を用いたKoinによるインスタンス生成を行いますが、`Activity`に関してはfactoryブロックのパラメータとして定義します。

```kotlin
val presenterModule = module {
    factory { (activity: Activity) -> LoginPresenter(activity, get()) }
}
```
##Activity側の実装

次のようにInjectする際にパラメータとしてfactoryブロックのパラメータとして定義した`Activity`のインスタンス(this)を指定する事が可能です。

```kotlin
class LoginActivity : AppCompatActivity() {
    private val loginPresenter: LoginPresenter by inject { parametersOf(this) }

    override fun onCreate(savedInstanceState: Bundle?) {
    }
}

```

##参考
https://beta.insert-koin.io/docs/1.0/documentation/koin-core/index.html#_defining_an_injection_parameter
GAE/PHPで.gcloudignoreにcomposer.lockを入れてはいけない

GAE/SE (Google App Engine Standard Environment) のPHP 7.2環境に関する話題です。

GAE/SE PHP 7.2環境では`app.yaml`の文法が以前と変わっている部分があります。その一つが、デプロイ対象から外すファイルの設定です。

以前は`app.yaml`の`skip_files`という設定でデプロイしないファイルの指定ができたのが`php72`から廃止になり、代わりに`.gcloudignore`で設定するようになりました。


## .gcloudignoreに何を書くべきか、何を書いてはいけないか

デプロイしたくないファイルというのは通常`.gitignore`とも重複することが多いはずです。たとえば、VimのスワップファイルやEmacsのバックアップファイルをデプロイ対象から外すのは良いアイデアだと思います。

ところで、GAE/SE PHP 7.2環境でcomposerを使う場合、次の点に注意が必要です。

- `/vendor/`はデプロイ不要
- `/composer.lock`はデプロイ必須

逆じゃないの？と思った人がいるかもしれませんが、私は逆にしてハマりました。

どうやらPHP 7.2環境では`/vendor/`ディレクトリは特別扱いされているようで、自分の手元の`/vendor/`をアップロードしても無視されます。代わりに、アップロードされた`composer.lock`を元に`composer install`した結果が反映されます。

ですから、典型的な`.gcloudignore`は下記のようになります。

```:.gcloudignore
.gcloudignore
.git
.gitignore

# Vim swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]

# Emacs backup
*~
\#*\#
.\#*

# PHP Composer
composer.phar
/vendor/
```

## グチ

意図はわかるけど、そんな挙動だなんて予想つかないでしょ…。そんなこと書いてあるドキュメントも見当たらないし…。

本稿執筆時点（2018年9月）ではGAE/SE PHP 7.2環境はbetaなので、いずれドキュメント化されるのかもしれません。

## 参考URL

- [app\.yaml Configuration File  \|  App Engine standard environment for PHP 7\.2 docs  \|  Google Cloud](https://cloud.google.com/appengine/docs/standard/php7/config/appref)
- [gcloud topic gcloudignore  \|  Cloud SDK  \|  Google Cloud](https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore)
- [Specifying Dependencies  \|  App Engine standard environment for PHP 7\.2 docs  \|  Google Cloud](https://cloud.google.com/appengine/docs/standard/php7/specifying-dependencies)
Kotlin コルーチンの「中断」とは何なのか

# Kotlin コルーチンと「中断」

Kotlin のコルーチンについて学んでいると、必ず「中断 (suspension)」という単語に出会います。
学び始めると、だいたいこのような説明を見ることになります。

> コルーチンはスレッドのブロッキングではなく、中断を行う。

自分はこの説明を見ても何も理解できませんでした。中断はブロッキングではないのか？
コルーチンを解説しているブログや記事などを読んでも、コルーチンで何ができるのかにフォーカスされていることが多く、コルーチンを理解する上で必要なメンタルモデルを構築できずに、いつもよくわからないままなんとなくわかった気になっていました。

そんな時に出会ったのが八木さんの「[Kotlin コルーチンを 理解しよう - Speaker Deck](https://speakerdeck.com/sys1yagi/kotlin-korutinwo-li-jie-siyou)」という資料です。 Kotlin Fest 2018 で発表されたものです。

このスライドではコルーチンがJVMでどのように実現されているのかといった技術的な詳細について述べられており、このスライドをきっかけに中断とはなんなのかがようやく見えた気がしたので、それをまとめたいと思います。

# コルーチンはコード変換で実現されている

コルーチンで記述したコードは、コンパイル時にステートマシンに変換されます。中断すると思われる箇所の前後でことなる状態として考え、状態1の処理を実行して中断したあとに、状態2の処理から再開するようなステートマシンです。

正確さを多少犠牲にして簡単にいえば、中断する前とあとで処理を分割（ここでは中断前のものを処理1、後のものを処理2とします）し、処理1を実行して中断箇所で中断したのち、中断が終わると処理2から処理を再開するようなコードに変換されるのです。

例を見てみましょう。

```kotlin
fun main() = runBlocking {
  launch {
    println("hello")
    delay(1000)
    println("world")
  }
}
```

このような処理があるとします。プログラムが終了してしまわないように `runBlocking` で囲っていますが、いまは `launch` の中だけに注目してください。
このコルーチン (launch のコードブロック) は `delay` という中断関数を中断箇所として、その前後の2つの処理に分解できます。

さきほどの話でいうところの処理1が

```kotlin
println("hello")
delay(1000)
```

で、処理2が

```kotlin
println("world")
```

となります。

コルーチンが実行されると、まず処理1が実行され、 `hello` と出力されます。そして自らの状態を次の状態に遷移させ、次にコルーチンが実行（再開）されたときには次の処理（処理2）を実行できるようにします。
その後 `delay` 関数が実行され、コルーチン自体の処理は一旦そこで終わります。これが中断です。
`delay` 関数は、「何らかの方法で」指定した時間後に自分を実行したコルーチンをもう一度実行（再開）します。
コルーチンは再開されると処理2を実行し、 `world` が出力されます。

実際のコードとは異なりますが、処理の流れのイメージとしては次のような感じだと思います。（八木さんの資料を参考に作成）

```kotlin
class Coroutine {
  private var state = 0
  fun run() {
    when (state) {
      0 -> {
        println("hello")
        state++
        delay(1000, this)
      }
      1 -> {
        println("world")
        state++
      }
    }
  }
}

fun delay(time: Long, coroutine: Coroutine) {
  Thread {
    Thread.sleep(time)
    coroutine.run()
  }.start()
}
```

`Coroutine` の1度目の実行で処理1を実行し、 `delay` で一定時間後に `Coroutine#run()` を実行することによって2度目の実行がおこなわれ、その際に処理2が実行されるというイメージです。
この擬似コードでは一定時間後に処理を行うために `Thread.sleep()` を使用してしまっているためスレッドをブロックしてしまっていますが、実際にはここはもっと複雑な方法（イベントループでスケジューリングとか）が採用されており、スレッドはブロックされないでしょう。

# 結局「中断」とはなんなのか

処理1を実行した時点で一度処理がコルーチンから抜け、処理1の処理が完了したらまた処理がコルーチンに戻ってきて処理2が実行される。このことを「中断」と表しているのではないかと思いました。

# Disclaimer

とは言ったものの、本当はもっと複雑で、 CoroutineContext や Continuation などについての理解をもっと深めればさらに深く理解できるようになるのだと思います。これからも勉強を続けたいと思います。

もしも誤った認識等ありましたら、ご指摘頂けますと幸いです。
サポートベクターマシン(SVM)の概要を数式を使わずに理解する 

サポートベクターマシン(SVM)とは何か？使うときにはどのような工夫をするのか？
サポートベクターマシンの概要がつかめるように、数式を使わずに説明します。

# 1. SVMとは？
・SVMとは「教師あり学習」の「分類」の手法の1つです。
・「分類」の中でも、データを2種類に分類する「2クラス分類」の手法です。
　（「多クラス分類」もできなくはないですが、一手間が必要です。）
・「マージン最大化」という考え方で分類します。どういう考え方かというと、
　「境界線⇔データ」の距離（マージン）が最大となるように境界線を引いて分類します。

#### 機械学習の全体像から見たSVM
SVMは、「教師あり学習」の「分類」の手法の1つです。
![18.png](https://qiita-image-store.s3.amazonaws.com/0/263069/c20e911a-7161-45f5-20ea-28fea4ff9d59.png)

#### SVMの「マージン最大化」のイメージ
「境界線⇔データ」の距離（マージン）が最大となるように境界線を引いて分類します。
![19.png](https://qiita-image-store.s3.amazonaws.com/0/263069/e6398319-9aa6-8b0d-0ec4-eddb8f50eaa0.png "SVMのイメージ")

# 2. SVMにおける手法
SVMを使うときに、うまく分類するための工夫があります。

## 2.1 ソフトマージン（ノイズデータへの工夫）
#### 目的は？
全てのデータを誤りなく分類できることが理想です。
しかし、実際のデータにはノイズがあり、そうはいきません。
「ソフトマージン」は、ノイズデータに左右されないための工夫です。

#### どんな工夫なの？
多少の誤分類は許容する、という工夫が「ソフトマージン」です。

#### 効果は？
ノイズデータに左右されにくくなり、分類の精度を高めることができます。
言い換えると、汎化性能を高めることができます。
汎化性能とは、訓練データではなく実際のデータを使ったときに、
どれくらい正しく分類できるかという精度のことです。

#### 「多少の誤分類を許容」の「多少」ってどの程度？
「多少」をどの程度とするか？は、「C」というパラメータで、人が調整します。
「C」が小さいほど、誤分類を許容します。

#### ハードマージン
誤分類を許容しない場合のことを「ハードマージン」と呼びます。
この場合、パラメータ「C」は無限大です。

#### ソフトマージンのイメージ
ノイズデータの多少の誤分類は許容します。
![20.png](https://qiita-image-store.s3.amazonaws.com/0/263069/eb629bf5-a488-55c2-72af-f47a3d4f4c80.png)

## 2.2 カーネル法（非線形への工夫）
#### 目的は？
これまでのイメージ図では、直線でデータを分類しました。
しかし、実際には全てのデータを直線(線形)で分類できるわけではありません。
境界線が曲線(非線形)となる場合も実際にはあります。
非線形な境界線に対応するための工夫が「カーネル法」です。

#### どんな工夫なの？
データを高次元の空間に変換することで、直線（線形）で分類できるようにします。
これを元の空間に戻すと、非線形になります。

#### カーネル法のイメージ
左の二次元空間では非線形ですが、右の三次元空間に変換すれば線形に分類できるため、
これを元に非線形な境界線を引く、というイメージです。
![21.png](https://qiita-image-store.s3.amazonaws.com/0/263069/c4f59b62-cfb0-47ea-2da7-ec84326d1577.png)

#### カーネルトリック（計算量を削減するための工夫）
データを高次元の空間に変換するということは、変換するための関数が必要ということです。
この変換関数を求めるのは、次元が大きければ大きいほど計算量が膨大になります。
しかし、カーネル関数というものを使えば、この変換関数を求めることなく計算することができます。
よって、計算量を削減することができます。これをカーネルトリックと呼びます。

# 3. SVMの利点と欠点
#### SVMの利点
・人が調整するパラメータが少ない点が利点です。

#### SVMの欠点
・データ量が増えると計算量が膨大になります。
・基本的には2クラス分類の手法です。多クラス分類をするには一手間が必要です。

# 4. まとめ（私見）
SVMは、データ量が少なくて、2クラス分類をしたいときに向いていると思います。
データ量が多いとか、多クラス分類をしたいときは、
SVMだけではなく、別の手法（ランダムフォレスト等）も試した方が良いと思います。
Kubuntu + chromium + Visual Studio Codeの環境で、launch.jsonの設定メモ

runtimeExecutableと、userDataDirの指定があるとデバッグ実行できました。

<pre>
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "launch chrome",
            "type": "chrome",
            "request": "launch",
            "file": "${workspaceRoot}/index.html",
            "runtimeExecutable": "/usr/bin/chromium-browser",
            "userDataDir": "${workspaceRoot}/out/chrome"
        }
    ]
}
</pre>
fluentd-uiでdockerコンテナのpache2のログを収集コンテナに転送する方法

## fluentd-uiでdockerコンテナのpacheのログを収集コンテナに転送する方法

いろいろ苦戦して時間がかかったので、備忘録として残しておきます。

## イメージの作成

* 以下のURLにあるDockerFileを使います。
  https://github.com/mailei/fluent_apache_dockerfile/blob/master/Dockerfile

* このイメージは、ubuntu18.04にapache2、fluentd-uiをインストールしたイメージを作成するためのdockerfileです。
* docker buildでイメージを作成

```
$ docker huild -t fluentd_apache_server .
```

* 転送元と収集サーバー共に同じイメージを使います。

## 転送元（apache＋fluentd-ui）コンテナ起動
* docker　コンテナの起動

```
$ docker run -p 19292:9292 -p 14224:24224 -p 18080:80 -it -d --rm --name apache  fluentd_apache_server
```

* 転送元は、fluentdのポートとapacheのポートを開いておきます。

* コンテナに乗り込んで、/var/log/apache2と/var/log/fluentd　にchod 777　で権限の変更をしておきます。

### fluentdのconfigファイル記載

* [http://localhost:19292](http://localhost:19292)　でfluentdのGUIにアクセスし、configの設定画面でcinfigファイルを編集します。

```
<match apache.**>
  @type stdout
</match>

<match apache.**>
  @type forward
  <server>
    host ※IP
    port 24224
  </server>
</match>

<source>
  @type tail
  path /var/log/apache2/access.log
  pos_file /var/log/fluentd/httpd-access.log.pos
  tag apache.access
  format apache2
</source>

<match apache.**>
  type file
  path /var/log/fluentd/out
</match>


```
* ※IPの部分は、`docker inspect　収集サーバー`で出力されるコンテナのIPアドレスです。


## 収集側（fluentd-ui）コンテナ起動

```
$ docker run -p 39292:9292 -p 34224:24224 -it -d --rm --name fluentd  fluentd_apache_server
```

* 収集側は、fluentdのポートのみ開いておきます。

### fluentdのconfigファイル記載

* [http://localhost:39292](http://localhost:39292)　でfluentdのGUIにアクセスし、configの設定画面でcinfigファイルを編集します。

```
<source>
  @type forward
</source>

<match apache.**>
  @type stdout
</match>

<match apache.**>
  type file
  path /tmp/acce
</match>

<match apache.**>
  @type stdout
</match>
```

* dockerコンテナに乗り込んでログを出力するフォルダー（/tmp/acce）にchmod 777で権限の変更をしておきます。


### 出力したファイルを確認してログが転送されていることを確認する

* [http://localhost:18080](http://localhost:18080)　にアクセスしてアクセスログを出力させます。
* 転送先のコンテナに乗り込んでログを確認する。
  * apacheのアクセスログが出力されているはずです

## まとめ
今回は、なかなかうまくログの読み込み、書き込み、転送ができずにはまってしまいました。  
今回は、コンテナ間のログ転送をとりあえず確認したかったので、  
configで指定したフォルダすべてにchmodで777権限を与えることで転送まで確認できました。  
権限についてはいろいろ試してみる必要がありそうです。
Alibaba Cloud VPN GWとFortigateで IPsec接続

#　Routing Based　とPolicy Based
IPSecの世界にざっくり２種類の実装があって、1つはACL/Policyでトラフィックを選択し、選択したトラフィック毎にIPsecTunnelを構成するPolicy Based、もう一つはざっくり何でも通すIPsec Tunnelを構成しておいて、どのトンネルを使うかあるいは使わないかをIP RoutingのNexthopで選ぶタイプ。
Alibaba CloudのVPN-GWはpolicy BasedのIPSecに見える。ということで、今回はRouting Basedな機器を接続するパターンを検証。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/ca3f9926-f4ed-5695-fe9d-6b9cda3745e8.png)

- 0.0.0.0/0 <---> 10.128.1.0/24を暗号化するトンネル作成
- Alibaba CloudはPolicyに従い、10.128.1.0/24宛てのトラフィックは全てトンネルを使用（Policy based）
- FortigateはStatic Routeで必要なCIDR（この場合は172.24.0.0/16）のNext Hopをトンネルに指定(Routing based)

# 接続
## Alibaba Cloud側準備
### VPN Gateway準備
Alibaba Cloud側の IPsec終端ポイントの作成。
1時間10円ぐらい。購入するとIPSec用のグローバルIPが割り当てられる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/26f201c0-1cef-11dc-fbd5-ac200167ea4e.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/011dc9f4-2f9c-e462-e5e7-28fc6bf1f11c.png)

### Customer Gateway準備
こちらはFortigate側のアドレス。今回のように他の機器でNATされている場合はNATの外側で使われているグローバルアドレスを設定。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/00a443f1-1734-5f14-b358-9bd1b41afb92.png)

### VPN Connection準備
先ほど作成したVPN GatewayとCustomer Gatewayを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/d77e8f28-4ed5-8037-76c5-69abbde0bf1d.png)


- ローカルネットワークは0.0.0.0/0とする。AlibabaCloud側として全ての宛先を受け入れる設定になり、FortigateはRoutingの仕組みでここを通すトラフィックを選ぶ。
- リモートネットワークはfortigate側のプライベートアドレス空間を指定する。0.0.0.0/0にしてはいけない。
- 「高度な設定」が必要
- 事前共有鍵"alitest"
- RemoteIDは今回のようにNATの裏にFortigateがいる場合はNATの裏側のFortigateのプライベートIPになるので書き換える。
- DHグループはFortigate側に合わせてGroup5に変更。Alibaba Cloud側のデフォルト値の2がデフォルトではFortigate側に設定されていない。
- 他はデフォルト値で。

## Fortigate側準備
### Address Object作成
fortigate側のLANのアドレスを定義
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/c54659e3-3840-9d3d-5635-1fc00d3177c0.png)

### IPSec Tunnel作成
こちらもAlibaba Cloud側に合わせ、Remote Addressは0.0.0.0/0、Local Addressは実際のSubnetアドレスを指定する。Preshared keyはここではAlibaba Cloud側に合わせて"alitest"を設定する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/21f1b0f6-64cc-b3d7-a362-76cf1cd9e938.png)


**MEMO**
Local Addressが複数のCIDRになる場合は注意が必要。
「Phase 2 Selector」が複数行あるとIKEv1でもv2でもそれ毎にSAペアを作ろうとするのでAlibaba Cloud側でもその数だけVPN　Connectionが作る必要がある。下記のCISCOと同じ挙動をする。
https://qiita.com/makotaka/items/985277345794b4a51273



### Polocy作成
FortigateのportとTunnelとの間で想定できるトラフィックを全てAcceptする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/d9be1b1b-ab28-4e35-756a-833ba2288fc3.png)

### Static Route 作成
そして実際にTunnelへ流すトラフィックはそのStatic　Routeのnext hopをVPN Tunnel interfaceに設定することで選択する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/132165/5fa1cc1e-38f0-0791-1aa5-a04142e9b844.png)
rails で確認画面作成

#確認画面を作成する
たくさん情報があるので(下記ご参照)、本記事は純粋に自分の理解度を深めるためのものです。なるべくわかりやすく書きます。
rails5です。
#参考URL

[Railsで登録の際に確認画面を挟むベスト・プラクティス](http://rakio1234.hatenablog.com/entry/2017/01/09/234744)
[Railsで入力の確認画面を出すときの定石]
(https://qiita.com/mm36/items/3753cb2fa65feedb145b)
[Rails で確認画面付きの Form]
(https://mmyoji.github.io/posts/2017-03-31-confirmation-form-in-rails/)

参考にさせていただきました。ありがとうございました。大変助かりました。

#確認画面作成方法

##コントローラー
```post_controller.rb
def new
  @post = Post.new
end

def confirm
  @post = Post.new(post_params)
  render :new if @post.invalid?
end

def create
  @post = Post.new(post_params)
  respond_to do |format|
      if params[:back]
        format.html { render :new }
      elsif @post.save
        format.html { redirect_to @award, notice: 'Award was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end
end
```

まずはコントローラーです。最初はnewアクションです。これは投稿の画面を作るための受け皿となるインスタンス作成されます。
次のネックとなるconfirmですがこちらが投稿内容確認用のアクションです。createアクションにユーザーが記入した内容を送るためにhttpメソッドはpostとなり、strongparameterがつきます。もしpostの内容が不適切であればnewの画面に戻されるようになっています。

##ビュー
そしてconfirmのビューはこちらです。

```erb:confirm.html.erb
<%= form_for @post do |f| %>
  <%= @post.contents %>
  <%= @post.day %>
  <div class="actions">
    <%= f.submit '投稿画面に戻る', name: 'back' %>
  </div>
  <div class="actions">
    <%= f.submit '投稿する' %>
  </div>
<% end %>
```
form_forは自動的にcreateメソッドをURLにしてくれます。また、確認してみてokならば投稿、ダメならば戻らなければなりません。submitを押した場合、どのみちcreateアクションが発動するので、そのタイミングで元のページに戻るか、実際に投稿するかを決めます。上のコントローラーを見ていただくと、createメソッドの中にif params[:back]というif文があります。これで、backが飛んできたら元のページに戻ることになります。そのため、name: 'back'をconfirm側で用意してあげてparameterで渡してあげます。

そしてconfirmの前のnew画面がこちらです。

```erb:new.html.erb

%= form_with(model: post, local: true, url: {action: 'confirm'}) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
      <% post.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :contents %>
    <%= form.text_area :contents, id: :post_contents %>
  </div>

  <div class="field">
    <%= form.label :day %>
    <%= form.date_select :day, id: :post_day %>
  </div>

  <div class="actions">
    <%= form.submit "確認画面へ" %>
  </div>
<% end %>

```

大事なのはform_withのURLはconfirmになるということです。

confirmが一つ追加され、newとcreateの間ができますが落ち着いてやれば問題ないかと。。。

##個人開発をされている方へ

Moverというプロダクトを開発しています。登録していただくと、開発したプロダクトのテスト利用を依頼し、フィードバックをもらうことができます。自分のプロダクトを公開して個人開発を加速させましょう！！　現在僕のアカウントも登録されているので、そちらにテスト利用依頼をいただければ実際に使ってみた感想などをお送りさせて頂きます。(アドバイスなどではなく、一人のユーザーとしての感想となります。)　もちろん無料です。
https://mover-web.herokuapp.com/



![Screen Shot 2020-05-19 at 4.36.42 PM.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147990/40822905-5a9d-6323-4318-bb475c68e887.gif)
画像のヒストグラムを表示する

Pythonでグレースケール画像のヒストグラムを表示する方法。
PIL(Pillow), numpy, matplotlibはインストール済みの前提。

# 実際に表示させた結果
単にヒストグラムだけ表示すると分かりづらいので、ヒストグラムの上に画像も表示させる。
![グレースケール画像のヒストグラム.png](https://qiita-image-store.s3.amazonaws.com/0/196890/e89db81f-8f6e-c985-608d-723e085f08bb.png)

# コード
```python
#-*- coding:utf-8 -*-

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

# 画像の読み込み & グレースケールに変換
img = Image.open('適当な画像ファイル').convert('L')

# 上段の画像の表示設定
plt.subplot(2, 1, 1) # 引数はそれぞれ、全体の行数、全体の列数、設定対象のIndex
a = np.array(img)
plt.imshow(a)
plt.gray()
plt.axis('off')

# 下段のヒストグラムの設定
plt.subplot(2, 1, 2)
plt.hist(a.flatten(), bins=np.arange(256 + 1)) #階級の幅を1としてヒストグラムを出す。

# 図表の表示
plt.show()
```
plt.gray()はグレースケール画像を表示する指定。これをしておかないと元の画像がグレースケールでも色が付く。

plt.histsのbinsの指定で+1をしているのは、ヒストグラムの最後の階級の区間を[255, 256]とするため。+1しないと最後の階級の区間が[254, 255]となり、254と255の両方の頻度が集計されてしまう。

# ヒストグラムだけ欲しい場合
numpyの関数histogramを使う(matplotlibのhist関数も内部ではこれを使っている)。

```python
img = Image.open('適当な画像ファイル')).convert('L')
histogram, _ = np.histogram(np.array(img).flatten(), bins=np.arange(256 + 1))
```
モブプログラミングの有用性

#エンジニアとして求められている像
今、エンジニアとして求められているものはなんだろうか。

##世の中の動向
世の中の動向的に、フルスタックエンジニアが求められている。
つまり、ハードウェア、ネットワークレベルの”インフラ”から、
OS/MW層の基盤層、またアプリケーションなどの業務層まで、
全てを理解した上で開発ができることが求められている。
（厳密には、本スキルは実際に開発するのみではなく、
　マネージメントと言った、実開発だけにとどまらない）

##大企業の場合
部署ごとに専門性を高め、それぞれの部品化を進めている。

##その先にあるもの
-部品化が極限まで進み、一気通貫でものを見れる人が少なくなっている。
-部署ごとのコミュニケーションが取れず開発スピードが遅くなる。
（基盤のプロ、ネットワークのプロ、アプリのプロ・・・）

#モブプログラミングとは

上記を解決できるかもしれない手法として「モブプログラミング」が挙げられる。

##手法
そもそもプログラミングは各人がPCの前に座り、ソロプレイだというイメージがある。
だが、モブプログラミングは、複数人数で問題に対して向き合うという手法である。
詳細な方法は他サイトにその説明を譲る。

##なんの役に立つのか
モブプログラミングは以下の四つに理があるとされる。
-知恵の結集
-スピーディー開発
-スキル/知識の伝播
-チームビルディング（コミュニケーション）

##今後どうしていくべきか
解決策が見えないような問題に対しては、
各有識者を集め、一気に問題を解決してしまうという手法をとってみる。
fish:fish:で$(npm bin)/cypressを実行するとき

fishでcypressを実行:fish:

```
$(npm bin)/cypress
```

shell知らないけど、fishな私は

```
fish: Illegal command name '$(npm bin)/cypress'
```

と怒られてまうのです:fish::anger:

cypressを実行するには実行文をpackage.jsonのscriptsに設定しますがちょっと独特です。
そしてそれをfishで実行するときのスクリプトも載せておきます:fish:


# TL;DR

- cypress実行文をfish用に変えるだけです

# 対象読者

- fish初心者:fish:
- cypress使用している人

# cypressの実行文

https://docs.cypress.io/guides/guides/command-line.html#Installation
公式ドキュメントにもありますが、cypress ~でそのまま実行しないようです。

fishでcypressを実行するときは、

##パターン1:  シェルで実行

```
$(npm bin)/cypress

# $ごと必要です
```

### fishの場合

$ではなく、eval ()で実行する

```
eval (npm bin)/cypress
```

初心者なのでevalの存在を知らなかったのですが、
()の中に変数を入れて、()の中にいれた変数をコマンドとして実行するのがevalだそうです。
http://fish.rubikitch.com/eval/


##パターン2 package.jsonに設定する場合

```package.json
{
 scripts: {
  "test":"./node_modules/.bin/cypress"
 }
}
```

ま、だいたい2のパターンでやるでしょうが:fishing_pole_and_fish::santa:

# 参考

https://docs.cypress.io/guides/guides/command-line.html#Installation
http://fish.rubikitch.com/eval/
件のDopamineで楽に強化学習をする

# TL;DR
Googleが出した強化学習フレームワーク[Dopamine](https://github.com/google/dopamine)を試す記事、第二弾
第一弾は[こっち](https://qiita.com/t-Asai/items/6f2a55c1f408f88aef36)

結論: ありがたい、が、まだ手間が多そう

# 概要
公式を頼りに、実際に使うとなったらどうすれば良いのかの方法論を考えていく。
試すのは以下のexample。

```bash
python -um dopamine.atari.train \
  --agent_name=dqn \
  --base_dir=/tmp/dopamine \
  --gin_files='dopamine/agents/dqn/configs/dqn.gin'
```

流れとしてはこんな感じで調べていく。
- 引数として指定できるパラメータの種類
- 実行時の処理の流れ
- 別の学習則(?単語があっているか不明)に切り替える方法

# 引数として指定できるパラメータの種類
まずは引数から。
agent_nameで学習エージェントの指定をしているらしい。今は
- [dqn](https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf)
- [rainbow](Hessel et al., Rainbow: Combining Improvements in Deep Reinforcement Learning. Proceedings of the AAAI Conference on Artificial Intelligence, 2018.)
- implicit_quantile(これはまだ論文がどれか見つかってないです。)
が実装済みの模様。
実装を見にいくと、コメントの行数が非常に多いので面倒に見えるかもしれないが、
実際のコードはそこまで複雑ではなさそう。

ただの予想だが、将来的には今の三つ以外にもどんどん種類が増えていくはずなので
どれくらいの頻度で種類が増えていくのか楽しみ。

base_dirは実行結果を保存する場所の模様
checkpointsやlogsがあるので、学習の結果やログがここに保存されている。
学習させた結果を別のマシンに読み込ませたり、学習過程や結果を可視化するために使えそう。
[tensorboardがある](https://github.com/google/dopamine/blob/9c612d4ad72fe9ce22bd7ac4f1b6818345bcb69b/dopamine/colab/tensorboard.ipynb)ので、これで可視化するのかな？

gin_filesは強化学習で使うパラメータを決める設定ファイルだった。
(GridSearchとかでパラメータ探索をすることは想定されてないのか？)

# 実行時の処理の流れ
では、dopamine.atari.trainの中身を見ていく。
ここ自体はびっくりするくらい簡単だった。
というのも、学習エージェントもatariも別の場所で実装されていたから。

学習させたいモデルと、学習に使いたいエージェントを別個に作成し、
あとで当てはめるだけで学習が出来るということを示唆してくれている(気がする)ので
これは非常にありがたい。

学習させたいモデルはこんな感じで読んでいたので、中身を見ていく。

```python
from dopamine.atari import run_experiment
```

これも、割と面倒に見えるが、大半はコメントと設定ファイルの読み込みだけで
それ以外だと、各状態との時に行動を行なった場合に与えられる報酬を出力する部分と
それをエピソードとして実行している程度に見える。

もちろん、自分で実装するのは非常に面倒だし、変更を加えるのも面倒だが
このくらいなら~~諦めれば~~読める。
各サービス独自のモデルを適応するときも、学習をさせるだけならそこまで難しくはなさそう。

最後に、肝となる部分を確かめていく。

```python
from dopamine.agents.dqn import dqn_agent
from dopamine.agents.implicit_quantile import implicit_quantile_agent
from dopamine.agents.rainbow import rainbow_agent
```
これ全てを見るのはちょっと大変なので、dqnだけ見ておく。
今度はちょっと面倒だった。
やっていること自体は、状態と行動から報酬を予測して選択するだけの
単純なもので、Deepの部分もtensorflowを使うことで、見た目のコードは短くなっている。
ただ、関数の数が多いので、頭から追いかけるのが面倒。
関数同士の関係を可視化してくれるツールとか無いもんだろうか？
[Rails-ERD](https://voormedia.github.io/rails-erd/)みたいなやつ。


# 別の学習則(?単語があっているか不明)に切り替える方法
散々めんどくさがったが、同じように関数を用意して、モデルや学習器を良しなに作り変え、
dopamine.atari.trainと同じようにして、自作したものを呼べばできそう。
これから
- [dqn](https://storage.googleapis.com/deepmind-media/dqn/DQNNaturePaper.pdf)
- [rainbow](Hessel et al., Rainbow: Combining Improvements in Deep Reinforcement Learning. Proceedings of the AAAI Conference on Artificial Intelligence, 2018.)
- implicit_quantile
以外にも公式の実装が増えたり、誰かが実装したものを呼んでくることで、
自分で強化学習を実装する必要がなくなっていくのかもしれない。


# まとめ
もっとモデルが作りやすくなって、エージェントの数も増えてくれれば、便利になってくると思う。
ただ、今のままだと、Dopamineを使うメリットが薄くて、
自分で実装した方が楽なんじゃ無いかと思ってしまう。
dqnやrainbowの実装などは、ありがたく参考にさせてもらう。
畳み込みニューラルネットワーク（CNN)の各層の役割について

この記事では畳み込みニューラルネットワーク（CNN)の仕組みと各層の役割について理解したことを個人的にまとめたものです。間違っていたらコメントください（笑）

#畳み込みニューラルネットワーク（CNN)
畳み込みニューラルネットワーク（以降CNN)は入力層、畳み込み層、プーリング層、全結合層、出力層といった入力層の特定ユニットと出力層のユニットが結合されている順伝播型ネットワークです。
各層の役割とpythonでどのように表現されるもなのかをkerasで表現した場合で記載します。
kerasではニューラルネットワークを作成する際にモデル定義にて作成します。各層を追加してモデルを定義していき、最後にコンパイルしてデータを入れていくという仕組みです。

準備：
・kerasのライブラリは下記のようにインポートします。

```
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
```

・入力と出力の定義
入力：CNNで学習するデータが入力されます。
　　　例えば画像などを入力データとして扱います。
出力：CNNで学習させたデータの判定が出力されます。
　　　いくつかの判定結果（クラス）を定義し、入力データが
　　　どのクラスに当てはまるか判定して出力します。

```
#例　サイズが32×32ピクセルのカラー画像を10のクラスどれかに判定する場合

#入力：横と縦をピクセル数（32)でを定義し、カラーはRGBのため3を掛け合わせる
im_rows = 32
im_cols = 32
in_shape = (im_rows, im_cols, 3)

#出力：10クラスなので10と定義する。
num_classes = 10
```

・畳み込み層
入力データにフィルターをかけて特徴を割り出し、特徴マップを構築します。
この時畳み込み層に入力データをそのまま入れてしまうと出来上がる特徴マップのデータが32×32よりも小さくなってしまうので、特徴マップのサイズを入力サイズと同じにする場合、画像のふちに０をつけるゼロパンディングを行います。
（逆に特徴マップのサイズを小さくする方法もありますが、触れないでおきます。）

```
# モデルを定義 --- (*3)
model = Sequential()
#入力データを畳み込み層（Conv2D)に入れて特徴マップを作成する。
#padding='same'とすることでふちに０を入れる
model.add(Conv2D(32, (3, 3), padding='same',
                 input_shape=in_shape))
#何度も畳み込みを行うと誤差が薄まってしまうのでreluという活性化関数を足して、誤差が薄まらないようにする。
model.add(Activation('relu'))
```

・プーリング層
畳み込み層でできた特徴マップからある領域の代表値を抽出する層です。
プーリング層をつけることにより入力された画像の位置の若干の違いや変化を吸収できます。

```
#畳み込みした後の特徴を取り出す層（プーリング層）
model.add(MaxPooling2D(pool_size=(2, 2)))
#一定の割合で入力データを0にする関数、下の場合４分の１の割合でランダムに0をセットすることで過学習を防ぎ学習制度を上げます。
model.add(Dropout(0.25))
```

・全結合層
プーリング層で出力された値を平滑化し、一次元のデータにしたものを取り込んで指定したユニット数に変換する層です。


```
model.add(Flatten()) #データを一次元化する。
model.add(Dense(512))#全結合層の定義　取り込んだデータを512ユニットにします。
model.add(Activation('relu'))
model.add(Dropout(0.5))
```

・出力層
全結合層を経由し、各クラスの確率が算出される層です。

```
model.add(Dense(num_classes))#画像の分類クラス数分のユニットを作ります。
model.add(Activation('softmax'))#クラス分類時の値を１か０かのどっちかにします。
```

#終わりに
本記事ではCNNの層の役割とpythonで定義する際にどのように書けばいいのかを理解している範囲でまとめてみました。
ニューラルネットワークのサンプルプログラムなどを読んでいくうちにその一行が何の役割を持っているのか忘れてしまった時のための備忘録として投稿します。
OAuth2を用いたログイン認証について気になったこと，とOpenID connectを少し


## 概要

OAuth2を用いたログイン認証を実装する機会があったので，その時に得た知見と気になったことをメモしていきます．OpenID connectについてはちょびっとしか書いてませんのでOpenID connectを知りたい人は対象外です.

## OpenID connectとは

OAuth2について調べていると**OpenID connect**というものが出てきたのでOpenID connectについて調べました．大きな違いとしては，OAuth2が**アクセストークン**を返却するのに対して，OpenID connectでは加えてIDトークンも返却するって感じらしいです．ざっくり言えば，OAuth2に対してID連携に必要な拡張を施したものです．

- OAuth2 ← ランダム文字列返ってくる
- OpenID connect ← "ランダム文字列生成" + "ユーザ情報" 返ってくる

って感じかな？


## OAuth2でログイン

ここからはOAuth2を用いたログイン認証について気になったことを述べていきます．最近流行りの**Twitterでログイン**を実装することがあったとします．その場合，OAuth2を利用してアクセストークンを取得しセッションに記録してそれ以降そのセッションを使ってサーバとやりとりします．その時，DBのユーザテーブルに新しいレコード作ってアクセストークンを保存します．また，セキュリティの関係上有効期限を設けるものとします．

#### 有効期限が切れた場合
ここで，アクセストークンの有効期限が切れた場合のことを考えます．その場合セッションに情報が残っている場合はどのユーザなのかは特定できるのでstateにユーザ情報をエンコードして載せるなどして再度アクセストークンを取得し，古いアクセストークンを書き換えればいいと思います．


#### セッション情報がない場合
Cookieの削除などでセッション情報がない場合に有効期限も切れて，，って場合はどうすればいいんでしょうか？最初のログイン後に，各ユーザに一意の情報の入力を促してそれをもとにユーザを特定すればいいの？詳しい人に情報求めます，，


## まとめ
なんか知見があったらまた記事書きます！
dropsortをC++で実装してみた

## dropsortとは

dropsortとは O(n)で配列がis_sortedになるソートアルゴリズムである

```
dropsort([1,2,5,4,3,7])
> [1,2,5,7]
```

……つまり、「前後の要素を比較して、`前要素 > 後要素` なら 後要素をdropする」を繰り返すアルゴリズムである
例えば
入力が `[0,1]` なら 出力は `[0,1]` (`in[0]<in[1]`になりdropが発生しない) 
入力が `[1,0]` なら 出力は `[1]`となる　(`in[0]>in[1]`になりin[1]をdropするので`in[0]` のみが残る) 

O(N)でsortedになる。正しい。 
~~アルゴリズムとしては入力の単調増加を保証したいときとか便利そうだが、コレをsortと呼ぶのなのかはについては若干引っかかる~~

参考：
http://www.dangermouse.net/esoteric/dropsort.html


### C++で実装してみた

要素の削除を伴うアルゴリズムなので[remove](https://cpprefjp.github.io/reference/algorithm/remove_if.html)にインタ－フェースを寄せてみた

```c++
template <class Iter, class Comp>
Iter dropsort(Iter begin, Iter end, Comp comp) 
{
    if (begin == end){
        return end;
    }

    auto sorted_last = begin;
    begin++;
    
    for ( ; begin != end; ++begin)
    {
        if (comp(*sorted_last, *begin)){
            sorted_last++;
            if(sorted_last != begin){
                *sorted_last=std::move(*begin);
            }
        }
    }

    sorted_last++;
    return sorted_last;
}
```


イテレータ（と比較関数）を渡すとイテレータの要素がsortされ、
(removeと同様に)戻り値としてsort済み要素の終端が返る

これを適当にeraseすればよい

```c++:main.cpp
int main()
{
    std::vector<int> v = {0, 1, 6, 7, 2, 3, 4, 5};
    auto it = dropsort(v.begin(),v.end(),[](auto lhs,auto rhs){return lhs<rhs;});
    v.erase(it,v.end());
    
    for(auto e:v){
        std::cout<<e<<" ";
    }
}
```

```bash
> 0 1 6 7 
```
https://wandbox.org/permlink/yUos74rKfy3i9mFs


### 参考：
http://www.dangermouse.net/esoteric/dropsort.html
https://metacpan.org/pod/Acme::Rautavistic::Sort
Addressable Assets Systemを使ってシーンをロード（移動）する

ドキュメントを読んでいたら発見しました。
実際に使ってみた記録です。
ドキュメントのリンクを書いておきますが、変更される可能性があります。
アクセスできない場合は、PackegeManager の
 View documentationで詳細を確認してみてください。
https://docs.unity3d.com/Packages/com.unity.addressables@0.3/manual/index.html
#Addressable Asset Systemをインストールする
Packagesフォルダーの中にあるmanifest.jsonに以下を追加します。


```
{
  "dependencies": {
    "com.unity.addressables": "0.3.5-preview",
  }
}
```
Libraryフォルダを削除します。
プロジェクトを開きます。
Addressable Assets Systemは、PackegeManagerUIでアップデートが可能なのでアップデートをしておきます。

#ロードするシーンを作成する

新しいシーンを作成し、保存します。
名前はどんな名前でも問題ありません。

#作成したシーンをAddressable Asset Systemに登録する
ウインドウ→アセット管理→Addressable Assetsをクリックします。

Addressblesというウインドウが出ます。
Create Addressables Settingをクリックします。
Default Local Group (Default)の上に作成したシーンをドラッグ・アンド・ドロップします。

#シーンをロードするスクリプトを作成する
スクリプトを作成します。
ファイル名は「LoadScene」にします。
スクリプトを開いて、以下をコピペします。

```
using UnityEngine;
using UnityEngine.AddressableAssets;

public class LoadScene : MonoBehaviour {

	public AssetReference assetReference;

	public void Start()
	{
		Addressables.LoadScene(assetReference);
	}
}
```

#シーンのアセットリファレンスを設定する
新しいシーンを作成します。
空のゲームオブジェクトを作成します。
スクリプトをアタッチします。
インスペクターでAssetReferenceにロードするシーンを設定します。

#動作を確認する
再生します。ヒエラルキーでシーンの名前が変われば成功です
毎日PCを見続けながら視力を良くしようとした施策（メガネ派）

0.01だったが矯正視力が0.05間違いなく上り
この数年やってきたことがあまり間違いではないようなので書く
我々は目と指は大事にしなくてはならない
眼鏡をかけている人が対象です

# なぜ視力は悪くなるのか(間違いなさそうなのだけ）
- 目をこすると悪くなる
- 視力が適さない環境での作業
- 目薬で角膜に潤いを与える(New)
- 20分ごとに6m先を20秒間見る(New)
- スクリーンの光度を抑える(New)
- コンタクトは避ける(New)

ブルーライトカットは否定されました。家のメガネブルーライトにしちゃったよ

# じゃ、できること何があるのか
- 目をこすると悪くなる→目をこすらない
- 目をこすると悪くなる→目の近くを怪我しない（失明の恐怖もあり怖いですよ。ほんと）
- 視力が適さない環境での作業→必要な視力によって眼鏡を変える
- 目薬で角膜に潤いを与える→1日4-5回を限度に
- 20分ごとに6m先を20秒間見る→休憩のつもりで
- スクリーンの光度を抑える→100cdを標準にしてみよう
- コンタクトは避ける

## 必要視力の要件
経験からだが結構生活で違っている

- 運転だと0.7以上。疲労時を考えると0.8は欲しい
- 職場での仕事0.6以上必要
- 家での生活0.4以上必要(6畳の場合）
- モニタを50cmくらいの場所から見る0.2以上

# 結論
ということで3種類の眼鏡を用意して生活してみた
- 外出用1.0(推奨0.8-1.0)
- 仕事用0.6(推奨0.6-0.8)
- 家用0.4(推奨0.2-0.5)

2年後30後半だが視力は0.05上がった。次の測定は2年後のつもりなので楽しみである
スマホを見る時はできるだけ裸眼でより目への負担をかけないことを求められる
(小ネタ) chromedpでパスワード保存確認が邪魔な場合の対策

#問題: Password Bubble が邪魔#
Chromeを自動操作するために [chromedp](https://github.com/chromedp/chromedp) を使い始めたんだけど、
ログイン成功すると出るこれ。Password Bubbleっていうらしい。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/3994/33bd350d-0fe2-d09d-40b1-edb7ae96ce64.png)

自動ログインさせて自動処理を続行させようとすると、これが邪魔になる。
でも、これを消す起動オプションは無いようだ。

#対策: user data directory#
代わりの手段として、ユーザーデータディレクトリが使える。
データ保存先のディレクトリを作成し、
Chromeのバイナリをコマンドラインから `--user-data-dir=そのディレクトリのパス` をつけて起動し、パスワード保存有無など必要な設定をしておき、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/3994/d98804ac-4a8b-7f55-f579-f30e944572fd.png)

chromedpからも同じディレクトリを指定する UserDataDir を付けて利用すれば良い。

```golang
import (
	"github.com/chromedp/chromedp"
	"github.com/chromedp/chromedp/runner"
)
// 中略
	chromeUserDataDir := "/path/to/user/data/dir"
	c, err := chromedp.New(ctxt,
		// chromedp.WithLog(log.Printf),
		chromedp.WithRunnerOptions(
			runner.UserDataDir(chromeUserDataDir),
		),
	)
```
∎
RMagickで画像の読み込み、大きさの取得、切り取り、リサイズ、保存

`Magick::Image`を使う。



## 読み込み `Magick::Image.read`

```ruby
image = Magick::Image.read('original_image').first
```

## 大きさの取得

```ruby
width = image.columns
height = image.rows
```

## 切り取り `Magick::Image.crop`

```ruby
image = image.crop(100, 200, 10, 10)
```

## リサイズ　`Magick::Image.resize`

```ruby
image.resize(20,20)
```

## 保存 　`Magick::Image.write`

```ruby
image.write("crop_and_resized_image.jpg")
```

## まとめ
全部まとめるとこうなる。

```ruby
image = Magick::Image.read('original_image').first
width = image.columns
height = image.rows
image = image.crop(width/2, height/2, 10, 10)
image.resize(20,20)
image.write("crop_and_resized_image.jpg")
```

読み込んだ画像の大体中央の場所から10x10の大きさで切り取る。
切り取った画像を(20,20)の大きさに引き伸ばして保存している。


## 参考
https://rmagick.github.io/image1.html
自己チャレンジ用にHeroku環境構築した時のメモ①

## はじめに
プライベートなプロジェクトで、
複数人でHerokuでWebアプリを作ることになったので、
メンバーに向けての環境構築メモ（ほぼ自分用）です。
勉強用のページなので、間違いなどありましたらご指摘お願いしますm(_ _)m

## 最初にherokuのページへ
以下が日本語ページ
https://jp.heroku.com/

![1-fix.png](https://qiita-image-store.s3.amazonaws.com/0/258294/1406b27e-c30d-c94e-cd4d-31d738193cf0.png)


## 登録画面へ
登録項目の、メールアドレス以外は設定変更で変えれるので正しく、入力しましょう。
※苗字・名前は、日本語も入力可能ですが、ローマ字表記で入力することを強くお勧めします。
※日本語で登録を始めたい場合は、URLの最後に`/jp`を付けると日本語ページになる。
https://signup.heroku.com/jp

![2.png](https://qiita-image-store.s3.amazonaws.com/0/258294/ae72e2a3-2d12-0e06-c71a-ea54528e1130.png)


## 登録したメールアドレスに確認メールが送信される
メール本文の`https://id.heroku.com/account/accept/xxx` 形式のURLにアクセスする
![4-fix.png](https://qiita-image-store.s3.amazonaws.com/0/258294/2b02d2ed-4fb9-750b-9720-10bf96cc4fb6.png)

## 初回パスワード設定画面に遷移する
ここで入力したパスワードも後程、変えれるので忘れないよう正しく入力すること。
※英数字と**記号**を使って、ある程度のパスワード強度が求められます。

![5.png](https://qiita-image-store.s3.amazonaws.com/0/258294/9f16c892-c57e-2747-581b-fe24586b6e5e.png)

## ここまでで、設定完了！
`ここをクリックして次に進んでください` ボタンで登録完了！
自身のダッシュボード画面へ遷移します。

![6.png](https://qiita-image-store.s3.amazonaws.com/0/258294/70f02e7b-d10f-4b84-e696-ec51d594d062.png)

## ダッシュボード画面へ
`Create New App` で自分のWebアプリ・プロジェクトが作成可能になります！
各プログラミング言語のアイコンをクリックすれば、Intorductionへ進みアプリケーションの作り方をサポートしてくれます！

![7.png](https://qiita-image-store.s3.amazonaws.com/0/258294/2f6c96c4-0e59-bf24-4972-2540ec1e0c4a.png)
もっとみる機能の実装メモ

```js
function view_img() {
    const more_view = document.getElementsByClassName("js-more--view_target")[0];
    const more_number = more_view.querySelectorAll(".js-more_number");

    const more_target = more_view.getElementsByTagName("li");
    const more_target__arr = Array.prototype.slice.call(more_target);
    const morebtn = document.getElementsByClassName("js-more--view")[0];
    const active_items = "active";
    const none_items = "js-none--view";
    const len = more_target__arr.length;
    const max_view = 6;
    let i = 0;

    const BODY = document.getElementsByTagName("body");

    if (BODY[0].className === "page-top") {
        let more_number_push = (() => {
            for (let rank = 0; rank < more_number.length; rank++) {
                let createDIV = document.createElement("div");
                let createP = document.createElement("p");

                let rank_num = `${rank + 1}`;

                if (rank < 3) {
                    createP.setAttribute("class", "more_number--style ranking" + rank_num);
                } else {
                    createP.setAttribute("class", "more_number--style ranking_etc");
                }

                createDIV.setAttribute("class", "more_number");
                createP.innerHTML = `${rank + 1}`;
                createDIV.appendChild(createP);
                more_number[rank].appendChild(createDIV);
            }
        })();
    }

    while (i < max_view) {
        more_target__arr[i].classList.add(active_items);
        i++;
    }

    if (len <= max_view) {
        morebtn.classList.add(none_items);
    }


    let more_view_fun = (e) => {

        let j = 0;
        let more_view_push = [];
        while (j < len) {
            if (!more_target__arr[j].classList.contains(active_items)) {
                more_view_push.push(more_target__arr[j]);
            }
            j++;

        }

        const more_view_slice = more_view_push.slice(0, 6);

        if (more_view_push.length >= 0) {
            for (let items = 0; item_len = more_view_slice.length, items < item_len; items++) {
                more_view_push[items].classList.add(active_items);
            }
        }

    };

    morebtn.addEventListener("click", (e) => {
        more_view_fun();

        for (let i = 0; i < len; i++) {
            if (more_target__arr[len - 1].classList.contains(active_items)) {
                morebtn.classList.add(none_items);
            }
        }

    }, false);

}
```
マックス6個までの要素を表示
Pycharmでpython27 on Google App Engineのデバッグをする時の設定

# 準備するもの
- Community Editionではないpycharm
- Google Cloud SDK
- pythonコマンドでpython 2.7.12が帰ってくる環境
- [hello world](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/standard/hello_world)用のサンプルソース

## プロジェクトの作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/17e612c7-7f94-c7b6-9732-134dfe02d852.png)

「Google App Engin」の設定を使ってもいいんですが、入力しないといけない項目が多いので:pensive:

## SDKのディレクトリの設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/dc0a6234-13a6-a4b1-2a0a-6a8233dea1ac.png)

「Preferences」からGoogle App Engineの項目を開いて、あらかじめインストールしておいてあるSDKのパスを設定してあげます。

## Debugの設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/8f4e3c86-df9f-3890-59b5-4abba9d262de.png)

こんな感じで、「Google App Engine」の設定を登録してあげます。

「venv」を使用している場合、Working directoryがプロジェクト直下ではなくなってしまい、app.yamlがない！と言われてしまいますので、明示的に指定してあげる必要があります。

## Debugの実行

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/abccb967-1aef-bcc3-8899-622e4f9b48fc.png)

ブレークポイントを設定したい行を選択し、虫:spider:のボタンを押するとデバッグが有効になるので、localhost:8080にアクセスしてみましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/235100/43ddd84b-f4c2-cb5b-617d-19495f4c3117.png)

無事、デバッグが止まるようになりました！
python3のvirtualenvで仮想環境を起動する

### Windowsのコマンドプロンプトでこけたので

WindowsのコマンドプロンプトでPython3のVirtualenvを使って環境をつくったときに起動方法がわからなかったのでメモ

```cmd:cmd
# 作成
C:\Users\your_account\your_project>python -m venv myenv

# myenvというディレクトリが生成される

# 起動
C:\Users\your_account\your_project>myenv\Scripts\activate
```

ここで注意なのは、ディレクトリを区切っているのは `/` じゃなくて `\ (バックスラッシュor￥)`

普段、`ubuntu` 使っているので `source myenv/bin/activate` でいけるかと思ってたら全然いけなくて困りました。
Laravel ファイルアップロードサポート

フォーム作ってCSVファイルをアップロードしようとしたところ非情の「not such file or directory」にハマった
原因としてはViewにあり

```
{{Form::open(['files' => true])}}
```
filesキーの記述が抜けていた。
filesキーをtrueにしておかないと、ファイルアップロード処理が認識されない
Emacsで開いているファイルをPhpStorm/IntelliJ IDEAでひらく


とっさにEmacsでファイルを開いてしまう癖があり、
PhpStorm/IntelliJ でファイルをまた探すのが面倒なので作りました。[逆はこれ。](https://pleiades.io/help/idea/using-emacs-as-an-external-editor.html)


中身をみていただくとわかりますが`open`コマンドの`-a`オプションをつけてアプリケーションを指定してるだけ。

```init.el
(defun my/get-curernt-path ()
  (if (equal major-mode 'dired-mode)
      default-directory
	(buffer-file-name)))

;; 現在のファイルをPhpstormで開く
(defun open-phpstorm ()
  (interactive)
  (let ((fPath (my/get-curernt-path)))
    (when fPath
      (shell-command-to-string (concat "open -a /Applications/PhpStorm.app " fPath)))))

;; 現在のファイルをIntelliJ IDEAで開く
(defun open-idea ()
  (interactive)
  (let ((fPath (my/get-curernt-path)))
    (when fPath
      (shell-command-to-string (concat "open -a /Applications/IntelliJ\\ IDEA.app " fPath)))))

;; (global-set-key (kbd "C-c 5") 'open-phpstorm)
(global-set-key (kbd "C-c 5") 'open-idea)

```


### おまけ
上記のelispを応用すればクリップボードにファイルのパスを保存したりFinderを開くことができる。

```init.el
(defun my/copy-current-path ()
  (interactive)
  (let ((fPath (my/get-curernt-path)))
    (when fPath
      (message "stored path: %s" fPath)
      (kill-new (file-truename fPath)))))

;; 現在のbuffferのディレクトリをfinderで開く
(defun open-finder ()
  (interactive)
  (let ((fPath (file-name-directory (my/get-curernt-path))))
    (when fPath
      (shell-command-to-string (concat "open " fPath)))))


(global-set-key (kbd "C-c 1") 'my/copy-current-path)
(global-set-key (kbd "C-c 4") 'open-finder)

```
参考 [Emacs で現在のファイルのパスを取得してクリップボードに保存 (org-link も)](https://futurismo.biz/archives/2989/)
Docker イメージのタグ取得

#事前準備
EPEL から jq パッケージのインストール

```shell-session
$ wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
$ rpm -Uvh rpm -Uvh epel-release-latest-7.noarch.rpm
$ yum -y install jq
```
#タグ取得

```shell-session
$ curl 'https://registry.hub.docker.com/v2/repositories/library/mysql/tags/'|jq '."results"[]["name"]'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3571    0  3571    0     0   2196      0 --:--:--  0:00:01 --:--:--  2197
"5.5"
"5.5.61"
"5.6"
"5.6.41"
"5"
"5.7"
"5.7.23"
"latest"
"8"
"8.0"
$
$
$ curl 'https://registry.hub.docker.com/v2/repositories/library/debian/tags/'|jq '."results"[]["name"]'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8467    0  8467    0     0   7180      0 --:--:--  0:00:01 --:--:--  7181
"7-slim"
"7.11-slim"
"wheezy-slim"
"wheezy-backports"
"7"
"7.11"
"wheezy-20180831"
"wheezy"
"unstable-slim"
"unstable-20180831"
$
```

#参考情報
http://www.googlinux.com/list-all-tags-of-docker-image/index.html
高度な業務知識が求められる業務システム開発でのスクラム試行　〜初回リリース編〜

# はじめに

いわゆるSIerでの業務システム開発では、業務知識を持った担当者でないと
顧客のエンドユーザーのみならずシステム担当者とも十分に要件の具体化が
出来ない場合があります。

そんな分野でもスクラムの恩恵を受けられるのか、数々の試行錯誤をして進めた結果、
成果はあったと思うので誰かのお役に立てるようノウハウを発信したいものです。
どんな登場人物がいるのか、開発時の役割分担などは以下の記事を参照ください。
https://qiita.com/takeout44/items/c6ad238b9efcff059e9c

本記事では初回リリースに向けた取組を書いていきます。

# リリーススプリント関連

## 初回リリースタイミングは決まっていた

アジャイルのベストプラクティスとしては、そのシステムで狙った価値が生まれる
最低限の機能が開発完了したときにリリースをして効果検証するというものですが、
システム開発着手前にリリースタイミングが決まっているということがよくあります。

というのも、多くの日本企業ではシステム開発着手の前提として
「○円の予算をかけて○年○月にシステムリリースを行うことで、
3年ないしは5年以内に○円の収益増加/経費削減の効果を見込む」
という見込を宣言して予算化するため、必然的にこのタイミングに
システムリリースを行うことを前提としたスケジュールが多くなります。

## スプリント内の進捗管理（余談）

Team Foundation Serverにはスクラムによる継続的な開発のために必要な
一通りの機能がありますので、スプリント内での進捗管理はこれで十分に満たされました。

非営業日や各メンバーの休暇予定などをキャパシティの設定に反映させておき、
バックログ一覧からスプリントバックログを対象スプリントに登録、スプリントバックログについて
必要な作業をタスクとして起票して残存作業を入力すると、バーンダウンチャートが
作成されます。（キャパシティ設定を反映した最適な進捗の目安も描かれます）

後は各開発者が日々タスクのステータスと残存作業を更新すれば、バーンダウンチャートの推移と
プランニング時に描画された最適な推移との差を追いかけて、スクラムマスターが
各開発者の課題解決をサポートするなどして開発速度の維持・向上を目指します。

※スプリントプランニングなど無視できない時間がかかるものは開発作業以外でも
　タスクにして残存作業時間を入れることでチャートの歪さを解消していました

## リリースに向けた進捗管理

一方で、Team Foundation Serverには、スプリントを跨いだ進捗管理として使える機能は
全バックログに対するステータス毎の個数の推移グラフくらいしかありませんでした。
（私には他に見つけられませんでした）

私がこの機能で不足を感じたのは以下の二点です。

- 個数が基準なので、バックログ毎のストーリーポイントの重みが考慮されない
- 初回リリースでの開発対象バックログだけで推移を見たいが全バックログが対象

そこで、スプリント期間終了の毎に初回リリース対象バックログだけをフィルタして
ストーリーポイント基準のバーンアップチャートを作成して、
リリース時期に対して開発が順調かどうかをチェックしていました。

バーンアップチャートについてはBacklogさんの [この記事](https://backlog.com/ja/blog/burndownchart-with-relative-estimation/) などが
具体的で分かりやすいです。

## バーンアップチャートの副次的な効果

特に開発の前半において、要件具体化の進行による開発着手可能なバックログの残量と
開発によるバックログの消化スピードを見比べるのに役立ちました。

両チームのサポートをしていた筆者のリソースをどちらにより多く割くのかを決めるため、
どちらの進捗がリリースへのクリティカルパスを握っているのかを確認したかったためです。


# リリースに向けたテスト関連

前回同様に書きたいことが多くて書ききれないので、また後日に持ち越します。（2018/09/09）
OpenLDAPのデータ移行手順

#移行元のLDIF作成
以下コマンドでldifを取得

slapcat -l <任意の場所とファイル名>

例)
slapcat -l /tmp/ikou.ldif

#移行先でLDIFのインポート
##サービスの停止
systemctl stop slapd

##データベースの削除
cd /var/lib
rm -rf ./ldap/*

##LDIFファイルのインポート
slapadd -l <LDIFの場所>

例)
slapadd -l /tmp/ikou.ldif

##所有者の変更
chown ldap:ldap -R /etc/openldap/slapd.d
chown ldap:ldap -R /var/lib/ldap

##サービスの起動
systemctl start slapd


#うまく接続できないときは
rootDNのパスワードを再設定してみる

slappasswdコマンドを実行し、任意のパスワードを設定

{SSHA}＜ハッシュ値＞
がでてくるので、コピーして

slapd.confの該当箇所に張り付け
Pythonで競プロに挑む日誌 vol.9 ~余剰とグループ分け~

休日は逆に調子上がらない説.
# 現在の目標
* 今年の10月内に茶色を取得する
 * [ABS](https://beta.atcoder.jp/contests/abs) の問題を全部解く**←イマココ**
 * [ABC](
https://kenkoooo.com/atcoder/?user=&rivals=&kind=category) の A, B 問題を全部解く
* 年内に緑色を取得する
 * [ABC](
https://kenkoooo.com/atcoder/?user=&rivals=&kind=category) の C, D 問題を全部解く
* [APG4b](https://beta.atcoder.jp/contests/apg4b) で C++ にも手を出す

#今日の問題
ABC086C - Traveling 
https://beta.atcoder.jp/contests/apg4b

# 結果

```answer.py
#coding: utf-8
import sys
N = int(input())
 
for i in range(N):
    t, x, y = map(int, input().split())
    #print(t, x, y)
    
    if x + y > t or (x + y)%2 != t%2:
        print("No")
        sys.exit()
print("Yes")

# 実行時間：319 ms
# メモリ　：3060 KB
# コード長：322 Byte
# 得点　　：300/300
```
またも自力では回答できませんでした...[こちらの解説](https://img.atcoder.jp/arc089/editorial.pdf)や, ほかの方の回答を参照しました.

動き方の条件から, 初期位置 (0, 0) で 1 秒ごとに x + y の偶奇が変わるので, x + y と t の偶奇が一致するかを判定すればよいとのこと.

図を描いたら, t の偶奇で点を分類できそうなことはわかったのですが, そこから余剰を利用することまで頭が回りませんでした.  余剰はグループ分けに便利な演算だということを学びました.

また, 前後の座標との因果関係について考えてしまっていたので収集つかなくなってました.  与えられる座標一点の情報で判定できる方法を模索すべきでしたね.  「問題をより小さくできないか」という視点を養いたいものです.

#明日やること
 * [ABC](
https://kenkoooo.com/atcoder/?user=&rivals=&kind=category) を解き始める.
RaspbianをインストールしてPCとシリアル通信をする

# 概要

Raspberry PiにRaspbianをインストールしてPCとUARTで通信できるようにします。PCからUART信号の出力には、この記事ではadafruite社のFT232H Breakoutボード使用します。このボードにはFTDI社のFT232HQというICが搭載されていて、USB<-->UART変換をしてくれます。その他にUSB<-->I2C、USB<-->SPIの変換もできるのでそのうち使ってみたいと思います。

# 環境

- Lubuntu 18.04
- Raspberry Pi 3 Model B
- adafruite FT232H Breakout

# Raspbianイメージのダウンロード

公式サイトは海外サーバなので日本にあるミラーサイトからGUI版のRaspbianをダウンロードしてくる。zipで圧縮されているので伸長するとimgファイルができます。

```
$ wget http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/raspbian-2018-06-29/2018-06-27-raspbian-stretch.zip

$ unzip ./2018-06-27-raspbian-stretch.zip

$ ls -lh 2018-06-27-raspbian-stretch.img 
-rw-r--r-- 1 yoshi yoshi 4.5G  6月 27 10:22 2018-06-27-raspbian-stretch.img
```

# RaspbianイメージをSDカードに書き込む

SDカードをPCに挿して/dev/sdbと認識されたことを確認してddコマンドでSDカードにイメージを書き込みます。デバイス名は、環境によっては/dev/sdaと認識されたりするので、このQiita記事を参考にして確認してください([SDカードにUbuntuのルートファイルシステムを作成する](https://qiita.com/yoshiyasu1111/items/e734eba7a842e3ba422d))

```
$ sudo dd if=2018-06-27-raspbian-stretch.img of=/dev/sdb bs=4M
$ sync
```

しばらく時間がかかります。私の環境では10分弱かかりました。終わるとsyncコマンドを実行して同期します。

# SSH接続できるようにする

イメージの書き込みが終わったら一旦SDカードを抜き差しします。bootディレクトリにsshという名前の空のファイルを作成します。このファイルを作成するとラズパイの起動時にsshデーモンを起動してくれるようです。どういう仕組みかは未確認。

```
$ sudo lsblk /dev/sdb
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdb      8:16   1 14.4G  0 disk 
├─sdb1   8:17   1 43.2M  0 part /media/yoshi/boot
└─sdb2   8:18   1  4.5G  0 part /media/yoshi/rootfs

$ touch /media/yoshi/boot/ssh
```

# Raspberry Pi起動

SDカードをRaspberry Piに挿して、HDMIケーブルとLANケーブルを接続して、USBケーブルを繋いで電源を入れるとRaspbianが立ち上がります。最近のRaspbianは起動時の設定でpiユーザのパスワードを変更したり、無線LANの設定をしたりするようになってます。知りませんでした。さらにアップデートが始まり20分か30分位かかって再起動してやっと使えるようになりました。

IPアドレスを確認したらSSH接続でログインします。

# Serial Portを有効にする

Raspberry Pi 3 model BではUARTのポートはBluetoothと兼用になっていてデフォルトではBluetoothを使うように設定されています。これをUARTを使用するように変更します。

raspi-configコマンドでラズパイの設定を変更します。

```
$ sudo raspi-config
```

- 5 Intercacing Optionsを選択
![5_Interfacing_Options.png](https://qiita-image-store.s3.amazonaws.com/0/271649/75ef149f-6da0-d776-4a87-37f86df5055c.png)


- P6 Serialを選択
![P6_serial.png](https://qiita-image-store.s3.amazonaws.com/0/271649/8d1de520-1501-d7f5-5758-7aaba9a4788e.png)

- シリアル接続でログインできるようにするか聞かれるのでNo
![login_shell.png](https://qiita-image-store.s3.amazonaws.com/0/271649/efd7026b-13c9-0075-3403-ce84fd102552.png)


- UARTを有効にする
![serial_port.png](https://qiita-image-store.s3.amazonaws.com/0/271649/d15b9f11-60da-6801-b16c-8a4b4ebf2e4d.png)


最後に設定の確認をして再起動します。

# PCとRaspberry Piの通信

PCとFT232HをUSBで接続、ラズパイとFT232HをGNDと、ラズパイのTX、FT232HのRXで接続して時の写真
![connection.JPG](https://qiita-image-store.s3.amazonaws.com/0/271649/c582e2e1-8f63-4268-c564-da8978852a79.jpeg)


PC側で115200pbsでシリアル接続し待機しておきます。

```
$ sudo screen /dev/ttyUSB0 115200
```

ラズパイ側からシリアル接続はビットレート115200bpsの設定をして、"Hello"を送信します。

```
$ stty -F /dev/serial0 115200
$ echo "Hello" > /dev/serial0
```

すると待ち受けていたPC側でHelloが出力されます。
![received.png](https://qiita-image-store.s3.amazonaws.com/0/271649/91d1e75d-6c09-a839-8d97-802e06090522.png)