OmniAICreator/Qiita-1.07M huggingface dataset:
【Swift】AtCoder Beginner Contest 192

#AtCoder Beginner Contest 192
下記リンクになります。
https://atcoder.jp/contests/abc192

##A Star
**問題**
https://atcoder.jp/contests/abc192/tasks/abc192_a

```swift
import Foundation
 
func readInts(separate: String = " ") -> [Int] {
    readLine()!.components(separatedBy: " ").map { Int($0)! }
}
 
// MARK: - Main
func main() {
    let X = readInts()
    print(100-(X[0] % 100))
}
 
// MARK: - Run
main()
```
入力値Xを100で割った余りを100から引くことによって解を求める。

#B uNrEaDaBlE sTrInG
**問題**
https://atcoder.jp/contests/abc192/tasks/abc192_b

```swift
func main() {
    let S: String = readLine()!
    var count = 1
    var isUnreadableString = true
    for string in S {
        let character: Character = string
        if count % 2 == 0 {
            if !character.isUppercase {
                isUnreadableString = false
            }
        } else {
            if !character.isLowercase {
                isUnreadableString = false
            }
        }
        count = count + 1
    }
    if isUnreadableString {
        print("Yes")
    } else {
        print("No")
    }
}
 
// MARK: - Run
main()
```

##C Kaprekar Number
**問題**
https://atcoder.jp/contests/abc192/tasks/abc192_c

```swift
// 大きい順にソート
func g1(_ n: [String]) -> Int {
    let tmp: [String] = n.sorted(by: >)
    return Int(tmp.joined())!
}
 
// 小さい順にソート
func g2(_ n: [String]) -> Int {
    let tmp: [String] = n.sorted()
    return Int(tmp.joined())!
}
 
// 差分求める
func f(_ n: Int) -> Int {
    let nStr: [String] = String(n).compactMap(String.init)
    return g1(nStr) - g2(nStr)
}
 
 
// 入力
let NK: [Int] = readLine()!.split(separator: " ").map { Int($0)! }
let (N, K) = (NK[0], NK[1])
 
// main
var an = N
for _ in 0..<K {
    an = f(an)
}
print(an)
```
昇順、降順でソートした値の差分を求める問題。
その差分を再度昇順降順にソートして、差分を求めるをK回繰り返した値を出力。
swift辞書「音を鳴らす」

#お断り
この記事は自分専用メモなのですごい初歩的な事しか書いていませんがご了承下さい。
確認環境
Interface:Storyboard
Life Cycle:UIKit App Delegate
Language:Swift
◉Use Core Data
__○Host in CloudKit
◉Include Tests

#この記事で出来る様になる事
関連づけしたbuttonが押された時に音を鳴らせる用になる

#実装
###UIの実装
storyの真ん中にbuttonを配置した後titleをpushに変更してからAutoLayoutの**Horizontal Center in Container,Vertical Center in Container**にチックを付けて動かない様にします。これでUI
の実装は終わりです。こんな感じになればOKです。!
![スクリーンショット 2021-02-21 7.41.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/38559492-b62b-14bf-cf67-6467f5d8966a.png)

###コードの実装
最終的なコードはこちらです。

```swift
import UIKit
import AVFoundation

class ViewController: UIViewController {

    var sound:AVAudioPlayer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        sound = try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: Bundle.main.path(forResource: "test", ofType: "wav")!))
    }
    @IBAction func get() {
        sound.stop()
        sound.currentTime = 0
        sound.play()
    }
}
```
**import AVFoundation**ではフーレムワークを読み込んで来ています。
**var sound:AVAudioPlayer!**ではAVAudioPlayerのインスタンスをsoundと言う名前で作っています。
**override func viewDidLoad()**この関数は画面が表示された時一度だけ実行されるので、ここでは先程作ったインスタンスに鳴らす音を設定して行きます。
**sound = try? AVAudioPlayer(contentsOf: URL(fileURLWithPath: Bundle.main.path(forResource: "test", ofType: "wav")!))**ではtest.wavを鳴らす様に設定しています。名前と拡張子は分離して書きます。
**@IBAction func get()**この関数は関連づけしたbuttonが押されると実行されます。
**sound.stop**では今鳴らしている音を停止します。
**sound.currentTime = 0**ではインスタンスをリセットします。
**sound.play()**では音声を再生します。

###関連付け
このタイプを指定します。
![スクリーンショット 2021-02-21 8.23.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/6745bd46-b49c-5ff7-e974-e27d765004af.png)
これで完成です。![Simulator Screen Shot - iPhone 8 Plus - 2021-02-21 at 10.31.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581846/8bc772e3-ccc4-ea15-6636-88fcb95c497f.png)

#細かいところ
###音量を変更
```swift
sound.volume = 2.0//音量を2倍に上げる
```
###再生回数を変える
``` swift
sound.numberOfLoops = 1//音声を2回再生する
```
###再生速度を変える

```swift
sound.enableRate = true//もしrateだけでは変更出来なかったらこちらを加えると良い
sound.rate = 3.0
```
Tensorflow1.14.0でのnumpyの警告を出さないようにする

# 環境
* python 3.7.0
* Tensorflow-gpu 1.14.0
* CUDA Toolkit 10.0
* cuDNN 7.4.1

# やりたいこと
Cuda Toollit使って画像処理したいので[ここ](https://shopdd.jp/e/windows-keras-tensorflow-gpu)を参照しながら必要なライブラリをAnacondaでDL。
その際に以下のコードをjupyterで実行したときに出てきたnumpyがらみの警告が鬱陶しく、かつ毎回出てくるのでどうにかして出ないようにしたい。

``` python
from tensorflow.python.client import device_lib
device_lib.list_local_devices()
```

↓ 出てきた警告
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283460/b14f5a15-7359-f411-be25-6caee99cceed.png)

# 解決方法
numpyのバージョンがあっていないため出てくるとのこと。なので対応バージョンである1.16.4に落とす。

```
pip install numpy==1.16.4
```

この時一緒にscipyも消えてしまうので別途入れる必要が出てくる。しかし現在のscipyのインストールパッケージはありがたいことに、現在インストールされているnumpyをscipyにとって都合がいいバージョン(1.19.2)にまで引き上げてくれる。そうなると本末転倒であるため、scipyをバージョン指定してインストールする。

``` 
pip install scipy==1.5.4
```

# 参考記事
* https://github.com/tensorflow/tensorflow/issues/31249
* https://zerofromlight.com/blogs/detail/31/
基数変換

#基数

基数...基本となる数。**n進数のnにあたる数字**

ex.二進数の場合
![スクリーンショット 2021-02-20 22.14.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131065/96f89abb-64bf-e846-625d-5b38213a061f.png)

以上のようになります。


##基数変換（２進数から10進数）

２進数から１０進数への変換方法は以下の通り
![2021-02-20 22.33のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131065/145d9bc6-343d-b548-6c43-0a5fd2840cf9.jpeg)

この計算方法で計算を行います。
この計算結果は**１3.375**となります。

**・10進数から２進数**

10進数から２進数へ変換する場合は下記の様になる。

![スクリーンショット 2021-02-20 22.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1131065/4491a0fd-c798-184a-55c5-e8ad3d89c769.png)

##２進数から８進数・16進数##

・２→８進数
ex. 1101.010の場合

①３桁毎に区切る**（１　１０１.　０１０）**
②それぞれの区切り単位でそれぞれ１０進数に変換。（基数の４　２　１）
③各桁の数字を合わせる（一桁目　１　２桁目５　小数点以下２）＝１５.２

・２→１６進数

考え方は基本的に２→８進数と同じである。

①４桁ごとに区切る（１１０１.０１）
②それぞれの区切り単位で１０進数に変換（基数８　４　２　１）
③１０進数を１６進数に直す
④くっ付けて出来上がり

**参考資料**
キタミ式基本情報技術者
P 30〜P 39
Pages内の全てのオブジェクトをPNGで画像保存


Pagesでグループ化されたオブジェクトを１つの画像ファイルとして出力できた、見つけた時すごく嬉しかったので共有と自分の覚え書きとして記事にする。


##Keynote →　Pages

画像処理はPhotoshopなり画像ソフトでやれよって思う人も多いと思うが、
・コーディングはできても画像関連はチンプンカンプン
・でも、成果物には画像が必要
・レイヤーレベルの管理と編集がしたい
・手軽に透過処理したい
・1つのプロジェクトファイルで複数の画像を管理したい
という要望を一気に叶えてくれる、現状の私の答えが見つかったのでここに書き残す。

それはMacのPagesだ！

![0d710a28fd8b0f516aac8e83fee5f1e4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98758/695f818c-bf5b-68a3-f53a-1a1fa9539bc7.png)

Pagesの前はKeynoteでやっていた
[keynoteで作ったオブジェクトのみを図として保存！画像へ変換できるツールの使い方](https://ucdnote.com/keynote-toyviewer/)
だがしかし、Keynoteでは、
・レイヤーレベルの管理と編集がしたい
・1つのプロジェクトファイルで複数の画像を管理したい
この２つのニーズをかなえていたが、肝心の画像化が、
①コピーしてペイントソフトに貼り付ける
②透過が不要な場合は⇧ ＋ ⌘ ＋ ４ でスクショする
というダサい方法に頼らなければならなかった

新しく編み出したPagesの方法はオブジェクト全てを一括してPNGファイルに変換してくれるので、Keynoteでやることの上をいく。

## Pagesでオブジェクトを用意する
Pagesでオブジェクトを用意する。
レイヤーごとの編集が目的なので編集が終わった個々の画像をグループ化しておく

## ePUBのリフロー型に書き出し
本来は電子書籍を作る機能だが、電子書籍を作る過程で全オブジェクトをPNGにしてくれる

![スクリーンショット 2021-02-21 7.53.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98758/24db7b3f-8449-13da-6df1-cb0b5bbca213.png)

![スクリーンショット 2021-02-21 7.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98758/e7e4e116-bf46-e14d-46b1-1999c98461e0.png)
必ずリフロー型で保存すること。固定レイアウトだとCSSのposition: absolute;で表現されてしまう。


## ePUBの中にあるPNGファイルを取り出す
ePUBファイルはhtmlやらcssやらpngをzipで圧縮してできているので、
まずは.ePUBの拡張子を.zipに変更する。
ファイル名の末端に.zipをつけると以下の確認ダイアログが出るので".zipを使用"を押下
![スクリーンショット 2021-02-21 8.03.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98758/de1d91b6-57e7-a373-568b-9b0d770297b0.png)


次に.zipを解凍！
なぜかMac標準の解凍だと失敗するので、こちらを使う。
[the unarchiver](https://apps.apple.com/jp/app/the-unarchiver/id425424353?mt=12)
![1200x630bb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98758/6d09c862-799f-9dbf-abf1-4c0ad508b8f5.png)

解凍が完了したらimageフォルダにあるPNGファイルを確認すると、Pagesでグループ化したオブジェクトがPNGファイルとして保存されている。

Pages内全てのオブジェクトが一気にPNG保存されるので、ただPages内のオブジェクトを画像出力したいだけでもかなり便利になります。
ln -s …の次の引数の順序に迷った時の覚え方


`cp`や`mv`コマンドと同じで、__今実在するパスが先__。


ここからコメントで教えて頂いた内容ですが、この時 `ln -s` ではなく `ln -sr` にしておくと階層違いのシンボリックリンクを張る時にも安全です。

例えば `mylink -> mydir/myfile` というリンクを張りたい時に
`ln -s mydir/myfile mylink` ならOKですが
`cd mydir` した位置で `ln -s myfile ../mylink` とすると作られたリンクは `mylink -> myfile` となって繋がりません。
`-r`オプションがあるとそれを直してくれるため`cp`や`mv`などのようにTabキーでファイル名補完できたパスを使いたい時は`-r`付きだと安全です。
sshdを再起動する

# 目的

- sshd(sshデーモン)の再起動を行うコマンドをメモ的にまとめておく

# 方法

- 下記コマンドを実行してsshdを再起動する。sshの設定ファイルの記述を変更したときなどに有効である。

    ```teminal
    $ /etc/init.d/sshd restart
    ```
JetPackでDockerコンテナが立ち上がらない際の対処法

# 問題
JetsonでJetPackを使ってTegraのコンテナを立ち上げる際に以下のようなエラーが出ることがある．

```bash
$ docker run --runtime nvidia -it nvcr.io/nvidia/l4t-base:r32.4.4
...
OCI runtime create failed: container_linux.go:349: starting container process caused "process_linux.go:449: container init caused \"process_linux.go:432: running prestart hook 1 caused \\\"error running hook: exit status 1, stdout: , stderr: nvidia-container-cli: initialization error: driver error: failed to process request\\\\n\\\"\"": unknown
```


大抵は，以下が原因のことが多い．

* NVIDIAが用意しているTegraのコンテナを使っていない  
nvidia/cuda:10.1-base-ubuntu18.04を使ってたり
* インストールされているJetPackと一致しないTegraのコンテナを使用している  
[ここ](https://ngc.nvidia.com/catalog/containers/nvidia:l4t-base/tags)からTegraのコンテナの一覧は確認できる  
以下でJetPackのバージョンは確認できる  
```
$ cat /etc/nv_tegra_release
```

これで解決しなかったケースがあったので，備忘録的に記載．

# 解決
JetPackのバージョンとTegraのコンテナのバージョンが一致しているが，エラーが出た．
原因としては，JetPackにはnvidia-docker2が元から入っているが，誤って更新してしまったことにある．
（Ubuntuと同じようにnvidia-docker2をインストールした）

ので，以下のコマンドで再インストール．

```bash
$ sudo apt remove nvidia-docker2
$ sudo apt autoremove

リポジトリの追加などしている場合は削除する...
主に下記ファイルを削除
/etc/apt/sources.list.d/nvidia-docker.list
$ sudo apt update

$ sudo apt install nvidia-docker2
```

これで無事Tegraの機能をもったコンテナを立ち上げることができた．

# まとめ
このエラーに関しては，NVIDIAのフォーラムでも議題にあがっていることが多い印象．
最終的にはJetPackを再インストールした，という解決方法が多い．
が，それをできないケースも存在する．
（NXやAGXのチップが組み込まれているベンダーのボードを使っている際など）

このケースにはまる人はあまりいないかと思いましたが，同じことをしてしまった人のためにも情報を残しておきます．
ご参考までに．
OSPFの設定確認コマンド

#はじめに
今年度中のCCNA取得を目指して学習中です。
間違っていたら指摘していただけるとありがたいです。
#OSPFの設定確認コマンド
### ①. ネイバーの確認

```
#show ip ospf neighbor
```

・ネイバーのルータID
・プライオリティ
・ステートの状況
・Dead Time(あと何秒間Helloパケットが届かなかったらダウンしたとみなすか)
・ネイバーのIPアドレス
・隣接関係を結んだインターフェース

###②. LSDBの要約情報

```
#show ip ospf database
```

・LSDBの要約情報(LSAのリスト)

###③. ルーティングテーブル

```
#show ip route
```

・どのような手段でルートに登録されたか
・宛先IPアドレス
・[AD値/メトリック]
・ネクストホップ
・インターフェース

###④. OSPFのルーティングプロトコル

```
#show ip protocols
```

・ルータID
・等コストロードバランシングの数
・networkコマンドで設定した内容
・LSAをアドバタイスしているルータの情報
・AD値

###⑤. インターフェースの確認

```
#show ip ospf interface　<インターフェース>
```

・インターフェースのIPアドレスと所属するエリア
・プロセスID,ルータID,ネットワークタイプ,コスト
・リンクの状態(DR,BDR,DROther)とプライオリティ
・DR.BDRのIPアドレスとルータID
・HelloインターバルとDeadインターバル(この値が隣接ルータとずれていると隣接関係を築けない)
プルリクエストについて注意事項をまとめてみる

swiftを教えていただいているメンターの方にプルリクの際の注意事項を熱く指導していただいたので、ここに残しておこうと思う。

・ファイル名、フォルダ名にスペースや全角文字は絶対に使わないこと
・変更したら必ず動作確認すること
・issueと関係ない差分入れないこと
・差分は他人に見せる前に自分で確認すること
・余計な差分があっても「Xcodeが勝手に変えたから」は通用しない、そのツールを選んで使ってるのは自分なので変更に責任があるのも自分、という自覚をもつこと
・差分の全てに「なぜ変えたのか」説明できること
・修正内容の確認のやり方が複雑なときはレビューしてもらう人にどうすれば確認できるのか伝えること


最初の「ファイル名、フォルダ名にスペースや全角文字は絶対に使わないこと」という初歩的な点が分からなかった愚か者だったので詳しく記載する。

・スペースはターミナルなどコマンドラインインタフェースで区切り文字扱いなのでバグが入り込むのでNG！

・全角文字は全角を扱えるサーバーじゃないと文字化けして死ぬのでNG！

・全角文字は日本でしか使われていないので、世界中のどこのサーバーでどう動くか分からない現代のインターネットに繋がったプログラムでは超ご法度。
somocluでクラスタリング

#はじめに
somoclueというSOM(自己組織化マップ)ライブラリでクラスタリングをしてみたときにメモ。完全自分用メモ

#環境
- somoclue  1.7.5.1

#手順

##somocluのインストール

```sh
pip install somoclu
```

##必要ライブラリのインストール
今回はirisを使う。

```python
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.manifold import TSNE
from sklearn.datasets import load_iris
```

##irisのロード

おまじない。

```python
iris_data = load_iris()
```

## SOMによる学習とクラスタリング

実行すると自己組織化マップが得られる(図省略)

```python

# セルの定義
n_rows = 16
n_cols = 24

som = Somoclu(n_rows=n_rows, n_columns=n_cols, compactsupport=False)

# 学習
som.train(data=iris_data.data, epochs=1000)

# K-meansでクラスタリング
kmeans = KMeans(n_clusters=5, random_state=42)

som.cluster(algorithm=kmeans)
som.view_umatrix(bestmatches=True, labels=iris_data.target)
```


## クラスタリング結果の取得
[How Can I get the cluster number or class for an specific data point?](https://github.com/peterwittek/somoclu/issues/66)　を参考にクラスタリング結果を取得。


```python
cluster_ids = []
for i in range(len(x)):
  cluster_ids.append(som.clusters[som.bmus[i, 1], som.bmus[i, 0]])
```


## tSNEの次元削減図に対し、クラスタのラベルをマッピング
実行するとスキャッタープロットが得られる(図省略)

```python
tsn_model = TSNE(n_components=2)
tsn_result = tsn_model.fit_transform(iris_data.data)
plt.title("tSNA")
plt.scatter(tsn_result[:, 0], tsn_result[:, 1], c=cluster_ids)

```
ディレクトリ形式のURLをGETパラメータ2つのURLに書き換える処理をApacheからnginxへ移植する方法

`http://example.com/view/tsumugu1515/xxxxxxxx`というURLにアクセスされたときに、内部的には
`http://example.com/view/index.php?userid=tsumugu1515&pageid=xxxxxxxx`
このようなURLとして処理するには、Apacheでは.htaccessに以下のような内容を記述する。

```apache:.htaccess
<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule (.*)/(.*)$ view/index.php?userid=$1&pageid=$2 [L]
</IfModule>
```
この記事は上記のような.htaccessをnginxに移植する方法のメモ。パラメータが1つのときの方法はヒットしたが、パラメータ2つはあまりなかったので。

----

nginx.confに以下のような設定をすることで動いた。

```nginx
location /view/ {
  if ($uri  ~* /view/(.*)/(.*)) {
    rewrite "^/view/(.*)/(.*)$" /view/index.php?userid=$1&pageid=$2? last;
  }
}
```

全体像はこちら。

```nginx.conf
server {
  listen 80;
  server_name example.com;
  root /var/www/html;
  location /view/ {
    if ($uri  ~* /view/(.*)/(.*)) {
      rewrite "^/view/(.*)/(.*)$" /view/index.php?userid=$1&pageid=$2? last;
    }
  }
  location ~ \.php$ {
    fastcgi_pass    unix:/run/php/php7.2-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root/$fastcgi_script_name;
    include        fastcgi_params;
  }
}
```

上記の処理のうち

> ```nginx
if ($uri  ~* /view/(.*)/(.*)) {
}
```

このifが非常に大事で、これがないと`http://example.com/view/tsumugu1515`というURLにアクセスされると、PHPファイル(index.php)がそのままダウンロードされてしまった。

また、`rewrite "^/view/(.*)/(.*)$" /view/index.php?userid=$1&pageid=$2? last;`の末尾の`last`を`break`にしてしまうとphp-fpmが実行されず、やはりindex.phpがダウンロードされてしまうので注意。
ロードバランサー背後のWebサーバのログでグローバルIPを記録する

ロードバランサーの背後のWebサーバでは、ロードバランサーのプライベートIPが記録されます。

やはり、どこからアクセスがあったかは気になるところです。

Apache の場合これを実現するには以下で可能です。

```
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %{X-Forwarded-Proto}i %{X-Forwarded-Port}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
```
イシュー管理とWikiによるドキュメント作成

# 勉強の記録
イシュー管理とWikiによるドキュメント作成 2/21
## 勉強した内容
- issues 問題点や要望などを自由に書き込み提案などもできる
- wiki   wikipediaみたいなもの！ みんなで編集しようぜてきな
- Gist   メモ的な感じ、公開と非公開設定ができる

## 何をベースに勉強してるか
- [N予備校 プログラミング入門](https://www.nnn.ed.nico/courses/668/chapters/9515)

## 内容の詳細
- Githubの機能の一部を使ってみた！

### わかったことについて
- 知ってる人や、離れてる人、知らない人とも情報交換や技術交換などしながら何かを作れる
- だからこそコードの流出などが起ると怖いですね

### むずかしかったよ
- 特になし

## 次回やる予定のこと
- 次回もGithubなどなど
拡張子.ziや.zi_を.zipにするバッチファイルをつくってみた

# まえがき（作成した理由）

以前、[タイトルにあるようなツールをC#で作った](https://qiita.com/kob58im/items/3a04d58fd3c73de1657c)が、ウイルス誤検知[^1]されるリスクを考慮し、バッチファイルで似たようなものを作ってみた。
※自分はバッチファイルについては素人なので、まずいところがあれば指摘いただけると助かります。

[^1]: 過去、自作ツールがウィルス対策ソフトに検疫（誤検知）されたことがある（ファイルの読み込みと描画くらいしかしていなかったのだが、、）。最近職場環境が変わり、ウイルス対策ソフトが違うものになったので、exeよりは誤検出されにくいであろうバッチファイルで同様のツールをつくることにした次第。。

# つかいかた

下記のバッチファイルZiRenamer.batを、拡張子.ziと.zi_に関連付けしておく。

# 機能

- Microsoft Outlook のメールの添付ファイル.ziや.zi_を開くと、tempフォルダ以下にZiRenamerというフォルダを作成し、その中にzipファイルとしてコピーし、そのフォルダを開く。
- それ以外の箇所で.ziや.zi_を開くと、.zipにリネームする。

# 注意事項

- 上書きチェックは考慮していない。
- tempフォルダは勝手にデータが消えていく可能性があるため、やりたいことに応じて、適宜バッチファイルを編集してカスタマイズしてください。
- いろいろ未検証（空白を含むファイルパスに対する動作など）なので、ご利用は自己責任でお願いします。

# バッチファイル

```bat:ZiRenamer.bat

echo off
set olPath=%LOCALAPPDATA%\Microsoft\Windows\INetCache\Content.Outlook\
set destOlPath=%TEMP%\ZiRenamer\
rem set destOlPath=%USERPROFILE%\Documents\ZiRenamer\
set zipExt=.zip
set tgtZipExt1=.zi
set tgtZipExt2=.zi_
set tmpPath=%~dp1
set tmpOlPath=%tmpPath:~0,-9%
set tmpExt=%~x1
set destFileName=%~nx1
set flag=0

rem .zi
if %tmpExt%==%tgtZipExt1% (
    set destFileName=%destFileName:~0,-3%%zipExt%
    set flag=1
)
rem .zi_
if %tmpExt%==%tgtZipExt2% (
    set destFileName=%destFileName:~0,-4%%zipExt%
    set flag=1
)

if %tmpOlPath%==%olPath% (
    rem outlook attachment
    if %flag%==1 (
        echo outlook attachment
        if not exist "%destOlPath%" (
            mkdir "%destOlPath%"
        )
        echo on
        copy "%~f1" "%destOlPath%%destFileName%"
        echo off
        start "" "%destOlPath%"
    )
) else (
    if %flag%==1 (
        move "%~f1" "%tmpPath%%destFileName%"
    )
)

rem 導入後は下記のpauseは削除推奨
pause
```

# 参考サイト

- [バッチファイル基礎文法リファレンス - Qiita](https://qiita.com/kshibamo/items/9368b0b2a4a2f40b61f1)
- [バッチファイルでの試行錯誤を回避するためのメモ－または人類には早すぎた言語 - Qiita](https://qiita.com/yz2cm/items/8058d503a1b84688af09)
- [Windowsバッチまとめ - Qiita](https://qiita.com/tomotagwork/items/5b9e08f28d5925d96b5f)
- [Windows バッチファイルの引数とパス名要素分解、対話入力、文字列置換まとめ - Qiita](https://qiita.com/hkuno/items/e7fedc20a61979aa6078)
[Unity]複数タブで作業効率アップ

#概要
知ってる人は知っている。僕は知らなかったです。
InspectorやProject画面を複数表示する方法です。
#使用例
Sceneビューを複数出して違う角度から確認したり
![スクリーンショット (1817).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/45301bdb-50cd-f49b-d74a-f937224fbbaf.png)
よく使うフォルダは常時表示しておきたいですよね
![スクリーンショット (1814).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/dd6ed3a6-e536-5b2e-1393-4bad9a334c8c.png)
Inspectorを複数出して見比べたい時。（片方は右上のロックをONするのがコツです）
![スクリーンショット (1816).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/be3ad098-66f5-ffa7-f96b-115703d92dbe.png)
#設定
右上のメニューボタン > Add Tab > 開きたいタブを選択
![スクリーンショット (1813).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/d0e5ebe2-12b7-a5c7-f071-ff8032fccdf4.png)
#タブがいらなくなったら
タブの上で右クリック > Close Tabで消すことができます
![スクリーンショット (1815).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/89d7316b-8db3-39ae-785d-611b93055d36.png)
Keras的"hello, world"

# はじめに

KerasはPythonで動作する高水準なニューラルネットワークのライブラリである。バックエンドとしてTensorFlowやTheanoを使用している。TensorFlow1の頃はKerasを別にインストールする必要があったが、TensorFlow2ではKerasが内臓されるようになった。つまりTensorFlow2をインストールすれば、Kerasを使う準備ができたことになる。

# hello, world

ブライアン・カーニハンとデニス・リッチーの著書「プログラミング言語C」では、C言語の最初の例題として「hello, world」を表示するプログラムを紹介している。これ以降、さまざまなプログラミング言語の教科書の冒頭で「hello, xxxx」を例題として使うことが通例となっている。では、Kerasではどうなるか？

C言語の"hello, world"では、次のことが学習できる。

- printf関数で画面に文字列を表示する。
- printf関数を使用するためにヘッダファイルをインクルードする。
- プログラムはmain関数で始まる。

Kerasを使った最初のプログラムはどうあるべきか？

- Kerasを使用するためにライブラリをインポートする。
- モデルを作成する。
  - 最初に作るプログラムのモデルは単純なモデルがよい。
  - モデルの各階層で活性化関数を使用する。
- モデルをコンパイルする。
  - コンパイル時に損失関数や最適化アルゴリズムを使用する。
- トレーニングデータを学習させる。
- テストデータで学習の内容を確認する。
- 可能であれば結果をグラフで表示する。

ということで、私の考えるKerasの"hello, world"プログラムは、一次関数を学習させるプログラムが適しているのではないかと思っている（hello, worldの表示はないが）。

# 一次関数を学習してみる

一次関数だと分かっているので、入力データ1つに対して1つの値を出力する1階層の単純なモデルを作成する。活性化関数にはLinear(入力値をそのまま返す)を使 使用する。損失関数はMSE(平均二乗誤差)、最適化アルゴリズムはSGD(確率的勾配降下法)を使用する。

拙筆の記事「[scikit-leanを使ってみる](https://qiita.com/mahoutsukaino-deshi/items/42ab3cd4837b73b77d0e)」の一次関数の例をKearasで学習させるプログラムは下記のようになる。

```python
import matplotlib.pyplot as plt
import numpy as np
from tensorflow import keras
from sklearn.model_selection import train_test_split

# Y = 2X + 3を求める関数とする。
x = np.linspace(0, 10, num=50)
y = 2 * x + 3

# トレーニングデータと検証データに分割
x_train, x_test, y_train, y_test = train_test_split(x, y, shuffle=False)

# モデルを作成
# 1階層で活性化関数としてLinearを使用
model = keras.models.Sequential([
    keras.layers.Dense(1, input_shape=(1,), activation="linear"),
])

# オプティマイザはSGD、損失関数はMSEを使用
model.compile(optimizer='sgd', loss='mse')

# トレーニングデータを学習する
model.fit(x_train, y_train, epochs=500)

# 結果をグラフにする
plt.scatter(x, y, label='data', color='gray')
plt.plot(x_train, model.predict(x_train), label='train', color='blue')
plt.plot(x_test, model.predict(x_test), label='test', color='red')
plt.legend()
plt.show()
```

このプログラムを実行すると、下記のグラフが表示される。
![linear_regression1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106967/b6ea2854-3b8f-2117-d327-6bcf3dd4a344.png)

トレーニングデータ、テストデータともフィットしており、うまく学習できたようだ。

# 最後に

まだまだKeras初心者の身であるが、使える機能を見つけたときには（メモがてら）Qiitaに書いていきたいと思う。
PHPでEXIF情報をjson_encodeする時の注意メモ

EXIFに含まれるUserCommentなどの文字コードがUTF8でない場合にjson_encodeが失敗してるよう。[EXIF2.3規格](http://www.cipa.jp/std/documents/j/DC-008-2012_J.pdf)をチラ見すると、そんな感じかなと。

PHPのjson_encodeはUTF8以外の場合失敗してfalseが帰ってきてしまうので、json_encodeを使う時は注意しておかないと駄目ですね。

とりあえず位置情報など欲しい情報だけ取得して返そうかな。とりあえずメモ。
optunaで探索変数を増やす際に探索済みの結果で初期化する

optunaを用いてハイパーパラメータの探索をした際、ある程度探索が進んでから「どうもこっちの変数も探索しておいた方が良かったのではないか？」などと気付いてしまうことがあると思います。
そんなとき、これまで頑張って探索した結果は活用したいものです。

ちなみに変数の探索範囲を変えたいだけであれば、以下の記事のようにもっと簡単にできるようです。

[[Qiita] Optunaで特定の初期値から最適化を開始する](https://qiita.com/tmitani/items/c0acd198788089786e29)

> **注意：** この記事で紹介している方法はoptuna v2.0.0で実験的に追加された関数を利用しているため、今後の仕様変更で使えなくなっているかもしれません。

# TL;DR

* `Study.add_trial(trial)` [(document)](https://optuna.readthedocs.io/en/stable/reference/generated/optuna.study.Study.html#optuna.study.Study.add_trial) 関数を使って探索済みのtrialを新しいstudyに追加する。
  * この際trialのparams, distributions辞書に新しい変数の値を追加する。
  * 新しい変数のdistributionは新しいstudyでのものに合わせる必要がある

# 変数の増やしかた

この章では具体例として、以前の探索で値を0.8に固定していた`cls_weight`という変数も追加で探索するように修正していく手順をメモしていきます。

## 新規変数の設定

まず最初に新たに探索することにした変数に関する以下の情報を用意します：

* これまで固定していた変数値
* これまでの探索でのdistribution

このとき、distributionは新しいstudyでのものとクラスが一致している必要があるようです。

つまり今回のケースで`cls_weight`を`suggest_loguniform`で探索するときは`LogUniformDistribution`を選ぶ必要があります。
対応するdistributionは[ドキュメント](https://optuna.readthedocs.io/en/stable/reference/distributions.html)を参照しつつ選んでみてください。

なお異なるクラスのdistributionを設定すると

```
ValueError: Cannot set different distribution kind to the same parameter name.
```

のようなエラーが発生しました。

今回のケースでは以下のようになります。

```python
import optuna

# 以前の探索では固定していたパラメータ
append_params = {"cls_weight": 0.8}
# パラメータの分布
append_distributions = {
    "cls_weight": optuna.distributions.LogUniformDistribution(0.8, 0.8)
}
```

## 初期化のためのtrialを用意する

探索済みのtrialは`study.get_trials()`関数を用いて読み込むことができます。
しかし今回は探索対象の変数が増えているため、このtrialをそのまま新しいstudyに追加することはできません。

そこで以下のようにtrialの`params`、`distributions`属性に前の節で用意しておいた新しい変数の情報を追加したうえで、`optuna.create_trial()` [(document)](https://optuna.readthedocs.io/en/stable/reference/generated/optuna.trial.create_trial.html#optuna-trial-create-trial) 関数により新しくtrialを作り直します。

> 今回は行っていませんが、この際に得られた目的関数の値(value)も変更することができます。そのため、この方法を応用すればoptuna以外で目的関数を評価した際の結果で初期化することも可能（なはず）です。

```python
# 以前の探索のtrialを読み込み
old_study = optuna.load_study(study_name="metric_learning", storage="sqlite:///cls_res152.sqlite")
old_trials = old_study.get_trials()

new_trials = []
for trial in old_trials:
    # stateがCOMPLETEであるtrialのみ保持する
    if trial.state == optuna.trial.TrialState.COMPLETE:
        distributions = trial.distributions
        distributions.update(append_distributions)
        params = trial.params
        params.update(append_params)
        new_trial = optuna.create_trial(
            state=optuna.trial.TrialState.COMPLETE,
            value=trial.value,
            params=params,
            distributions=distributions
        )
        new_trials.append(new_trial)
    else:
        continue
```

## 新しいstudyの作成と初期化

これまでの節で初期化のためのtrialが得られているので、残るは以下のように新しく作成したstudyに`Study.add_trial()`関数を用いて追加していくだけです。

studyを作成する際のstorage, study_name, directionなどは必要に応じて修正してください。

```python
new_study = optuna.create_study(storage="sqlite:///cls_res152_new.sqlite", study_name="metric_learning", direction="maximize", load_if_exists=True)

for new_trial in new_trials:
    print(f"Add: {new_trial}")
    new_study.add_trial(new_trial)
```
Linux Mint 20.1 にOpenGLをインストーする

#はじめに
必要に迫られてLinux Mint20.1にOpenGLをインストールこととなりました。あっさりできました。後々のために書き残します。


#インストール
以下の記事を参考としました。
https://qiita.com/BitPositive/items/db8b13e7d34e5349237b


```
$ sudo apt update
$ sudo apt upgrade
$ sudo apt-get install libglu1-mesa-dev mesa-common-dev freeglut3-dev
```

あっけないほど簡単にインストールできました。
Qiita Daily Survey memo 2021.02.21

# Qiita Daily Survey memo 2021.02.21
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。

## [巨大なエンジニアの学び場を作った話](https://qiita.com/cloto/items/68a80ca93f4ef7822e6c)
cloto さんの記事。
プログラミング学習者向けに自学習の継続にフォーカスしたサービスを開発したよ、という記事。
学生時代は当たり前で何も感じていなかった「行けば誰か勉強している場所」が重要な環境だということに、社会人になってから気づきます…。
そういう観点で、行けば誰か勉強している場所、モチベーションをもらえる場所としてサービスを開発されたのがすごいなーと思いました。
私も Qiita から毎朝エネルギーを摂取することで生きながらえています…。

「３．努力が可視化されて残っていく」は、学習において重要なポイントなので、どんな感じで可視化されるのかなーと興味がありました。
私自身、自分の努力の可視化は3年前からの課題ですが、いまだに結論が出ず。

また、人が集まって価値が高まる系のサービスは、最初の人集めが大変そうな印象があります。
アイディアはとても良いと思ったので、栄えるといいなーと思いました！


## [Developers Summit 2021 の「ソフトウェア品質を高める開発者テスト」で学んだこと](https://qiita.com/kojimadev/items/4721680efe407b77632b)
小島 優介 (kojimadev) さんの記事。
タイトルのセッションで学ばれたことをアウトプットされている記事でした。
自分の会社ではウォーターフォールで単体テストの期間を設けて開発しているのですが、無理があると感じており、最近はテスト系の記事を見るとフムフムと読みふけってしまいます。
単体テストは単体テスト期間に、結合テストは結合テスト期間に…というのではなく、根幹機能を先に作成して、常時テストは回っていて、修正でエラーが発生したらそれに対応…というのは、すごい考え方だなーと思いました。
ぜひやってみたい。

また、別記事紹介になってしまいますが、小島さんの記事としては、下記の記事を昨年末に拝見させていただいていて、「あ、あの記事の人かー！」と思いました。
[1年以上かけて生産性倍増＋成長し続けるチームになった施策を全部公開](https://qiita.com/kojimadev/items/4b28f801863cf4e8f0da)
ものすごいモチベーションで、確かにこれだけがっつりやればパワーアップも納得な記事でした…。
また、ここまで寄り添っていれば評価の際も納得感のある評価がつけられそうだなと感じました。


## [空間データの回帰分析 (地理的加重回帰モデル)](https://qiita.com/ssugasawa/items/90b6de2f178a49f0c300)
Shonosuke Sugasawa (ssugasawa) さんの記事。
地理的加重回帰に関する記事。空間データに対する回帰分析の中で最も有名な分析補法だそうです。
数式を使った論理的な説明部分の前半に加え、サンプルデータ（BostonHousing）を元にRで実際の使用例を示してくださっている記事です。
3回くらい読み返しましたが、前提知識が足らず理解には至りませんでした…。精進します…。
後半のカラーリングされたプロット図は、緯度経度ごとに古い建物があるかもな割合をカラーリングで示した図…と理解しました。
であれば、中央右と左下が危ないのか…なるほど、と事前知識のない自分でも推測することができます。可視化大事。

昨日の夜間光の分析もそうでしたが、本職の方々本当にすごい…。
地理情報込みの分析・可視化の記事が続いているので、いくつか見てみたいなーと思いました。
【Xcode12】 デバックコマンドを初めて使用

#はじめに

初めてデバックコマンドというものを使ってみました。
今回デバッグコマンドを打ってもエラーが出て困ったので、勉強として書き残す事にしました。

#環境
Xcode12.3
Swift5.3.2
macOS Catalina 10.15.4

#使用したコード

```swift
import UIKit

class ViewController: UIViewController {
    var a = 5
    var b = 10

    override func viewDidLoad() {
        super.viewDidLoad()

        let total = a + b
        print(total)
    }
}
```

#実行した事
簡単な足し算をし、変数aに入っている値を調べるという事をしました。
デバッグエリアで、「po a」と入力。
![スクリーンショット 2021-02-20 21.28.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/8452703d-aa10-6475-fa37-6e61542db1d6.png)

#エラー発生
宣言されていない識別子「a」の使用とXcodeに言われてしまいました。
![スクリーンショット 2021-02-20 21.24.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/35cfcf85-3200-60ff-d71c-0dd813b484b7.png)

#原因
ブレークポイントを打っていない事が原因でした。

#ブレークポイントを打って再度実行
エラーが出なくなり、変数aの値を調べる事ができました。
![スクリーンショット 2021-02-20 21.36.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/21287dff-8394-2bc9-8885-3f9202722dd6.png)

![スクリーンショット 2021-02-20 21.35.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/86f27346-801c-0093-2b51-0e7e258989f7.png)

#aの値を20に変える
「expression a = 20」と入力するとaの値が20に変更されます。
![スクリーンショット 2021-02-20 21.44.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/f290c015-d7b0-e6aa-5a3e-ccc8d13babea.png)

#今回学んだコマンド
[参照サイト](https://dev.classmethod.jp/articles/ios-debug/)のコマンドを引用
>・値の出力：po <式>
・値の代入：expression <式> = <値>






#参照サイト

https://dev.classmethod.jp/articles/ios-debug/

#終わりに
カウントダウンタイマーのように、タイマーが終了した時にアラームを鳴らす確認する時が苦労しました。
しかし、今回デバッグコマンドを学び変数の値をタイマー終了５秒前に設定すればすぐにアラームが実行されて便利だという事が知れて良かったです。
今後も新しくデバッグ方法について学んでいきたいと思います。

[Twitter](https://twitter.com/koara1237)やっています。
AndroidのEditTextで入力された文字がメールアドレスかどうか判定する（Kotlin）

##はじめに
初投稿です。Android開発学習中の大学生です。学んだことをまとめて頭の中を整理するために書きます。なので僕と同じ初心者向けの内容です。

##背景
Android開発で会員登録の機能を作っているときに、入力された文字列がメールアドレスかどうかの判定方法がわからず困りました。いろいろ調べたり知人のエンジニアの方に教わったことをまとめます。

##解決方法
大きく分けて二つの方法があります。
1.正規表現でメールアドレスのパターンを作って、それと入力された文字列が合致するか調べる方法。
2.Androidにデフォルトで存在するPatternsクラスのメソッドを用いて調べる方法。

あくまで僕の解釈ですが、1の方が本質的なやり方で2は飛び道具みたいな感じかなと思いました。ただ1の方が正規表現のことを理解していないとできないのでめんどくさめ。あと抜け漏れが発生しやすいかも。まあでも2のやり方も大元では1と同じことやってそう。

##1の方法について
まず、正規表現の概念と定型パターンは
概念 : [https://userweb.mnet.ne.jp/nakama/](https://userweb.mnet.ne.jp/nakama/)
定型パターン : [https://qiita.com/grrrr/items/0b35b5c1c98eebfa5128](https://qiita.com/grrrr/items/0b35b5c1c98eebfa5128)
がわかりやすかったです。

入力された文字列がメールアドレスならばtrueそれ以外はfalseを返すサンプルメソッド。

```Kotlin
 fun isEmailAddress(): Boolean {
        val mail = editText.text.toString()
        return mail.matches(Regex("[a-zA-Z0-9._-]+@[a-z]{2,}+\\.+[a-z]{2,}"))
    }
```
※正規表現の部分は抜け漏れがあるかもしれないので参考程度に思っといてください。

純粋に入力された文字列が正規表現で設定した型とあってるかを見る方法です。

##2の方法について
なんも考えず使える、ただただ便利な方法です。抜け漏れも起こりにくいと思います。起きたらAndroidのせいです。
公式のドキュメント : [https://developer.android.com/reference/android/util/Patterns](https://developer.android.com/reference/android/util/Patterns)

```Kotlin
fun isEmailAddress(): Boolean {
        val mail = editText.text.toString()
        return Patterns.EMAIL_ADDRESS.matcher(mail).matches()
    }
```
脳死で使いましょう。

##結論
多分1の方法を理解したうえで、2の方法を使うっていうのがベストです。

##追記
意外と記事書くのが楽しかった。あと内容が間違っている可能性があるので気を付けてください。あとこれはメールアドレスだけでなく、電話番号とかほかにも応用できます。

4:00に深夜テンションで書いたのでもう寝ます。

※コメントで、誤解を招く表記をご指摘頂いたので更新しました。コメント頂いた@sdkeiさんありがとうございます。
2/21 22:00に更新
【Python】n進数→10進数、10進数→n進数【AtCoder】

ABC192 
[D - Base n](https://atcoder.jp/contests/abc192/tasks/abc192_d)
ででてきた、**n進数⇄10進数 変換問題**

今後のためにも、

- **n進数→10進数**
- **10進数→n進数**


の自作ライブラリを作成を作っておく。

***
###(2021/02/24 追記)自作ライブラリ修正

- **10進数→n進数のバグを修正**
    - 余りが10以上になる場合の考慮漏れ
- **引数・戻り値共にわかりやすいように int に統一**


```python:test.py
print(base_n(969,31)) #108
print(base_n(970,31)) #109
print(base_n(971,31)) #-1
print(base_n(991,31)) #-1
print(base_n(992,31)) #110
print(base_n(993,31)) #111
```
***

###ちなみに
Python標準で、n進数→10進数は以下のようにも記述できる。
しかし、**intの第二引数はまさかの「36」までしか対応していない！**
ABC192Dのような、n>36となりうる問題は解けないことに注意！

```python:test.py
print(int('1111',2))
#15
print(int('1111',37))
#ValueError: int() base must be >= 2 and <= 36, or 0
```

#n進数→10進数
```python:test.py
def base_10(num_n,n):
    num_10 = 0
    for s in str(num_n):
        num_10 *= n
        num_10 += int(s)
    return num_10
```

#10進数→n進数
```python:test.py
def base_n(num_10,n):
    str_n = ''
    while num_10:
        if num_10%n>=10:
            return -1
        str_n += str(num_10%n)
        num_10 //= n
    return int(str_n[::-1])
```

###おまけ(練習問題)
ぜひ解いてみましょう！
[C - N進数](https://atcoder.jp/contests/code-festival-2014-final/tasks/code_festival_final_c)


おわり！
[リモートワークのお供] Sound Of Colleaguesで自宅勤務に"オフィス感"を足す

いきなりの余談ですが、僕はカナダに住んでいます。日本でのリモートワークの割合がどれくらいか分かりませんが、こちらではテック界隈はおそらく9割はリモートワークの状態です。
自宅の環境も快適なのですが、さすがに1年とかこの状態だと結構ダレてくるというか、集中力のためにも"オフィス感"が恋しくなってきます。

そんななか、面白いWebアプリを見つけました。名前を[Sound Of Colleagues](https://soundofcolleagues.com/#)、直訳すると"同僚たちの音"。

[![Sound Of Colleagues](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702689/d77b09ec-b62e-5d1d-c188-4b3032700082.png)](https://soundofcolleagues.com/#)
こんな感じのシンプルなUIで、さまざまなオフィスにある音たちが選択されています。

* 左側:
    * 室内音(ホワイトノイズ)
    * コーヒーマシーン
    * 話し声(英語)
    * プリンター
* 右側:
    * 室外音(車とか)
    * 電話
    * オフィス犬
    * キーボード
* 下:
    * 雨音

それぞれの音はボリューム調整ができるので、自分好みにカスタマイズできます。ループなのでかけ流しOK。
僕はスクショにあるように、Room ToneとPeople、Keyboardsメインの音数少なめの設定がちょうどよかったです。

リモートワークでどうも集中できない、気分転換したいみたいな時に役立つ素敵なアプリです。ぜひ。
AWS　Route53 とは

#Route53とは
AWSのRoute53はDNSサービスを提供します。
主な機能は下記通りです。
ーーーーーーーーーー
Domain registration
DNS management
Health check
ーーーーーーーーーー

##Domain registration 
タイトル通り、ドメインを登録する。
設定したいドメイン名を入力して、登録可能のドメイン名が表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/838f82aa-d82a-9f8b-587b-1b39ff30d87c.png" width=80%>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/ec1459a5-e4d6-f157-45b5-8537e5afc0cb.jpeg">
⇧ドメインの価格。通常は12ドルです。（年間費用）

##DNS management
ドメイン名をホストゾーンの作成に入力し、タイプを選び、作成ボタンを押していただき、ホストゾーンの作成が完了となります。
★タイプ：public、privateの二種類。
privateを選んだ場合、VPCに関連付けます。

![domain manager.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/01ef2140-8279-04a3-d8d0-fadd6e67cf7f.jpeg)
![domain management.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/e2de1b63-ca7b-22a5-6824-ba8f6b158e00.png)

##Health check
![EC2health check.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082021/5a8d050f-4ed4-6ee6-a178-aefc33323840.jpeg)

##DNS レコードタイプ
reference：https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/ResourceRecordTypes.html
・SOA – Start of Authority
　（ドメイン名の色んな情報を記録する。例えば：Primary Name Server、Responsible Mail Address、Serial、Refresh、Retry、 Expire、Default TTL）

・A – ホスト名とIPアドレスの関連づけを定義するレコード。
　（ドメイン名をIPv4アドレスに変換する。）

・CNAME – Canonical Name　
　（正規ホスト名に対する別名を定義するレコード。特定のホスト名を別のドメイン名に転送する時などに利用する。）
　例えば、aws.houka.comはhouka.comに
論文まとめ：Deeper Depth Prediction with Fully Convolutional Residual Networks

# はじめに
depth推定系の論文から、わりと初期の
[1] I. Laina, et. al. "Deeper Depth Prediction with Fully Convolutional Residual Networks
", 2016 Fourth International Conference on 3D Vision (3DV)
のまとめ

arXiv:
https://arxiv.org/abs/1606.00373

github:
https://github.com/iro-cp/FCRN-DepthPrediction
tensorflow実装等。

# 概要
- 単眼RGB画像からdepthを推定する
- モデルはresidualなモジュールを使った全畳み込み層であり、MRF等の後処理等は必要ない
- モデルの後半でup-samplingを使って解像度を上げるが、この際にup-projectonなる仕組みを用いる
- reverse Huber lossを用いる

# モデル全体のアーキテクチャ
モデルの全体像は以下。

![3dv_img_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/60113005-1ed4-2093-c620-9ad156f2a55c.png)
 
図の通り、encodeして、その後解像度を上げる形。２列目あたりまではResNet-50を転移学習させたもの。なのでresidualなblockを多段にしたものとなっている。

３列目のup-samplingする部分が本論文の特徴の１つである。

NYU-depth v2 datasetであれば入力サイズを304x228とし、それより少し粗い160x128を出力する。

# Up-Projection Blocks
本論文が提案している仕組みの１つ。以下の図で

![3dv_img_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/f50a296a-cfe2-0ab3-30c3-9402b8746fc7.png)

(a)はun-poolingした後に5x5のカーネルでconvする単純なblock。

これに対し、Up-Projectionなるblockはun-poolingしたのちに２つのbranchに分ける。

一方は5x5カーネルでconvしたのちに3x3カーネルでconvする。もう一方は5x5カーネルでconvするのみ。これをaddし、さらにconvする。

(a)と(c)との精度の差は後述。

(b)と(d)は略。

# Reverse Huber Loss
本論文の特徴の１つ。

L2 lossと以下のHuber lossを試している。

```math
\mathcal{B}(x) = \begin{cases}
    | x | & | x | \leq c, \\
    \frac{x^2 + c^2}{2c} & |x| \geq c.
  \end{cases}
```

つまり、[-c, c] 間で L1 loss、その外側で L2 lossとしている。

ここで c はバッチ内でpredictとtargetとの差の最大値に対し、その1/5と定める。

```math
c = \frac{1}{5}\max_i (| \tilde{y}_i - y_i| )
```

ざっくり考えると、L2だとpredictとtargetの差が大きい場合に勾配が大きくなるので、大きな差を縮小させる作用が強いが、一方でpredictとtargetとの差が小さい場合はlossも極端に小さくなり、考慮されない。結果、全体がぼやけたlow distortionのdepth mapが形成されるだろう。

そこで、差が小さい場合はL1とし、小さな差もそこそこ重視する、という感じだろうか。

これが NYU depth dataset のようなものとなったときに、効果を発揮するらしい。同 datasetはこんな感じで

![3dv_img_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/134c0d0e-ac6e-4ffa-4c9f-e679feaabfa6.png)

long tailな分布だそう。画像内に遠い背景が一部写っているような状況だろうか。

そうした場合に、L2 だけだと近いか遠いかは区分できそうだが、近い中のより近いか、ちょっと遠いかは重視できない。だが、おおよそ距離を正確に欲しいのは手前の椅子とか机とかの物体なので、これでは不都合。

reverse Huber lossだと近いものに対してもより正確にその距離を推定できそう。

# 実験と結果

## 1. ablation study的なもの
NYU Depth v2 datasetを使った精度は以下。

![3dv_img_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/9fbc1527-6fbd-fccd-2ac4-657794f8138a.png)

ベースとするアーキテクチャに関しては、当然ながらResNetの方がAlexNetやVGGより良い。

またL2 loss と berHu(reverse Huber loss)とを比較した場合、後者の方が微妙に良い。（差はそれほどないね）

さらに、up-convとup-projectionとを比較した場合、後者の方が微妙に良い。（工夫したわりには差が少ない）

## 2. 他の有名モデルとの比較
以下は他の有名モデルとの比較表で、やはりNYU Depth v2 datasetを用いたもの。

![3dv_img_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/fd4a0d08-c632-6974-c00c-335cb8a2113b.png)

この論文が出た2016年あたりではSOTA。

## 3. 定性的評価

NYU Depth dataset を用いた場合のdepth推定結果の例は以下。

![3dv_img_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/656b1f85-b528-2f0e-fd85-4aabae2974ba.png)

説明が気にも書いてるが、左から４列目のResNet-50はResNetの全結合層を用いた場合（つまり本提案手法のup-projectを全結合＋それをreshapeしてマップを作成に変えたもの）

この時代のモデルとしてはよさげ。
Tesla K80を動作させる方法

# 序
こんにちは。橋本です。

超並列計算が必要な科学計算用途において、計算用GPUの存在は不可欠です。
中でもプログラミングツールキットの情報が豊富なNvidia製GPUは汎用性が高く、従来より高速な計算が可能となっております。

しかしながら、倍精度を要求する計算において、一般的に流通しているNvidia GTX,RTXシリーズは厳しい制限が掛けられており、科学計算には不向きです。(単精度においてはこの限りではありません。)
Nvidia製GPUの中で倍精度に制限が掛けられておらず、現在のGTX,RTXシリーズと比較しても遜色ない性能のものは以下の何れかしかありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571701/c6039403-1847-1e38-d651-abb8aa2120bd.png)

このうち、K20,40,80あたりが中古で現実的な値段で手に入りやすくなっております。
そこで、K80を研究室で購入頂いたわけなのですが、動作までにちょっとした苦戦がありましたのでナレッジしておきます。

なぜか、記述が見つからなかったので。

#破
K80のインストール方法を述べます。
##先に結論
K80が使用できるチップセットは「C610」「X99」「Z77」以降のアルファベットシリーズです。
「B150」とか「X79」とかは使えません！
また、対応しているからと言って必ず使えるとはかぎりません。(大抵は使えると思いますが。)
事前にマザーボードの設定項目が「Above 4GB MMIO BIOS Assignment （4GB を超える MMIO BIOS 割り当て）」をサポートしているかを確認してください。
この項目の無いマザーボードは動きません。

##組み立て
K80はパッシブ冷却ですので、ファンを内蔵しておりません。そこで以下のシロッコファンを接着剤でつけることで解決しております。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571701/96edc69e-8232-ae16-1fe7-83878fa17417.png)
また、電源はペリフェラルから12Vを供給しております。おそらくマザーボードのファン端子から電気を得るとMOSFETがアチアチになると思います。

##設定
マザーボードUEFI BIOSの項目「Above 4GB MMIO BIOS Assignment （4GB を超える MMIO BIOS 割り当て）」を探し、有効にしてください。

有効にしないままインストールを進めると、OSをから認識はされますが、ドライバーが当たらない奇妙な現象に遭遇します。

##OSのインストール
Ubuntu 20.04LTSを導入します。
インストールする際に「サードパーティ製のドライバをインストールする」項目にチェックを入れないでください。ログインループに陥ります。やらかしてしまった場合は素直にOSをインストールし直しましょう。

##ドライバのインストール
任意のCuda Toolkit ヴァージョンをアーカイブから選択してインストールします。
Cuda Toolkit Archives「https://developer.nvidia.com/cuda-toolkit-archive 」
あとは、インストール手順に従ってインストールを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571701/5c6f0f23-7aa2-cd57-a47c-b88ffe7e3754.png)

再起動の後、「nvidia-smi」コマンドで確認してください。
![20210217_023522700_iOS (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571701/858b56e7-0cad-c639-2b03-53f4a3091472.jpeg)


#急
「lspci -v」コマンドでPCIeからは認識しているのにCUDAドライバーが当たらない事象に遭遇しました。原因は「Above 4GB MMIO BIOS Assignment （4GB を超える MMIO BIOS 割り当て）」の有無です。

そもそも、PCIeは「メモリ空間」「IO空間」「コンフィギュレーション空間」の3つのアドレス空間を持ちます。
うち、メモリ空間において1バスでメインメモリ空間に転送(仮想化)できるメモリ量は256MB。x16バスで4GB(32ビットアドレス長)
k80は1つのバスに24GBのメモリがあり、x16バスで全てをマッピングできません。
(Tesla k40やTesla C2070ではこの現象が現れなかったため、24GBというメモリ量がこれを要請している可能性がある。)

すなわち、「IO空間」「コンフィギュレーション空間」が生きているからPCIeから認識されるが、「メモリ空間」を有効にするドライバを入れようとすると弾かれてしまうと考えられます。

解決策は「Above 4GB MMIO BIOS Assignment （4GB を超える MMIO BIOS 割り当て）」を有効にすることです。有効にすれば、1バス256MBの制限がなくなります。
この機能は「C610」「X99」「Z77」以降のアルファベットシリーズを持つチップセットに搭載されている事が知られています。

#参考
nvidia公式では「いや～。k80はワークステーション向けだから。そんな一般のマザボで動かないとか知らんよ。ワークステーション向けのC610とか買ったら？」的な事が書いてありました。
https://community.intel.com/t5/Intel-NUCs/Latest-BIOS-for-NUC6i7KYK-and-quot-Above-4G-decoding-quot/m-p/690484#M68958

Xeon Phiのインストールのときダメだった的なコミュニティなのですが、ここで「K80とか大きなメモリ空間を使うものはAbove 4GB MMIO BIOS Assignmentを有効にすればいいよ！」と猛者がつぶやいており、ここから答えをえました。
https://forums.developer.nvidia.com/t/plugging-tesla-k80-results-in-pci-resource-allocation-error/37007/11

ASUSさんは言ってましたね。「Teslaとか使うときには4GBデコードをオンにしてね！」と。
https://www.asus.com/jp/support/FAQ/1017190/
Let's Encrypt の証明書更新に苦戦した記録

#記事内容
Django製のWebサイトのSSL証明書をLet's Encryptのお世話になっていたのですが、この度初めて3ヶ月経過して有効期限が切れるとの通知メールをいただき、その際に更新に苦戦した記録を残しておきたいと思います。


自動更新を実装しようとした。
そのためにcertbotをインストールした。
以下の証明書更新のコマンドを実行したらエラーが出た。

```
sudo certbot renew
```

エラーは以下のような内容。

```
Certificate did not match expected hostname: acme-v02.api.letsencrypt.org.
```

ホスト名が違う、とのこと。

certbotのコンフィグファイルを覗いてみた。

```
sudo vim /etc/letsencrypt/renewal/(自分のサイトのドメイン名).conf
```

すると確かに以下のようになっていた。

>server = https://acme-v02.api.letsencrypt.org/directory

これを以下のように修正した。

>server = https://acme-staging-v02.api.letsencrypt.org/directory

再度、証明書更新のコマンド を実行してみた。

```
sudo certbot renew
```
すると今度は以下のエラーが出た。

>Account at /etc/letsencrypt/accounts/acme-staging.api.letsencrypt.org/directory/(ランダム文字列のアカウント名) does not exist. Skipping.


色々ググってみると、アカウント情報を保存しているディレクトリがあることを知り、以下のディレクトリにlsコマンドを実行してみたところ、2つのディレクトリが存在していた。

```
sudo ls /etc/letsencrypt/accounts/
```

以下が結果です。つまり、どこかのタイミングで新たなアカウントが作成され、それは今までの接続していたのとは別のドメイン名（-stagingがつく）だということがわかりました。

```
acme-staging-v02.api.letsencrypt.org  acme-v02.api.letsencrypt.org
```

さらに-stagingがつく方のディレクトリに保存されているアカウント名を確認すると、確かにエラー通り、コンフィグファイルに記載しているものとは違うランダム文字列でした。

```
sudo ls /etc/letsencrypt/accounts/acme-staging-v02.api.letsencrypt.org/directory/
```

ここで今使えるアカウント名がわかったので、コンフィグファイル内で以下のように修正しました。


>account = (新たに得たランダム文字列のアカウント名)

これで再度証明書更新のコマンドを実行してみました。

```
sudo certbot renew
```
すると今度は以下のエラーが出た。

>Attempting to renew cert (自分のWebサイトのドメイン) from /etc/letsencrypt/renewal/(自分のWebサイトのドメイン).conf produced an unexpected error: You've asked to renew/replace a seemingly valid certificate with a test certificate (domains: (自分のWebサイトのドメイン)). We will not do that unless you use the --break-my-certs flag!. Skipping.

どうやら、さっきテスト証明書で更新しようとしたからダメと怒られているようです。コマンドのオプションとして `--break-my-certs` をつければOKとのことなので、その通りに実行してみました。

```
sudo certbot renew --break-my-certs
```

すると、うまくいきました。以下の結果が返ってきました。

>Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/(自分のWebサイトのドメイン)/fullchain.pem (success)

ここまで至るのに4時間くらいかかりました。全く知識不足でした。すぐ忘れてしまわないように、このように記録に残しています。
この所有格のガールフレンドからの10のチャットはあなたを躊躇させますが、残念ながら、陽気です！

忍耐力を毎日テストしてください

あなたが所有格のボーイフレンドを持っているならば、あなたは異なる経験をするでしょう。最も明白なことは、あなたの忍耐力が毎日テストされ続けるということです。

所有格のガールフレンドからのこの一連のチャットでは、このようなボーイフレンドがいる場合の戦い方を紹介します。陽気なチャットをチェックして、行きましょう。

1. <strong><a href="https://csupalliativecare.instructure.com/eportfolios/2914/Home/WATCH_Mortal_Kombat_2021_Full_Version_Online_HD" rel="no-follow">彼氏は母親と二人きりで出かける。うーん...</a></strong></p>

2. <strong><a href="https://hvl.instructure.com/eportfolios/32600/Heim/Ver_Cherry_2021_Pelcula_Completa_en_Espaol_y_Latino" rel="no-follow">ボーイフレンド、疑わしい場合は、探偵でさえ良心的ではありません。</a></strong></p>しかし、バイクを1台ずつ押し下げることは、人々が使い果たされることを意味するわけではありません。

3. <strong><a href="https://bruningdavenport.instructure.com/eportfolios/4905/Ver_HD_I_Care_a_Lot_Pelcula_Completa_Espanol_y_Latino/Ver_HD_I_Care_a_Lot_Pelcula_Completa_Espanol_y_Latino" rel="no-follow">くそー、明日の朝、朝食を見つけたい場合</a></strong></p>、またはそこで歩くように言われる必要がある場合。本当に疑わしい、本当に

4.<strong><a href="https://bruningdavenport.instructure.com/eportfolios/4954/Home/Ver_Pel_Pelcula_Completa_en_Espaol" rel="no-follow">そうです。</a></strong></p> シャーロックホームズはまた、疑わしいモードにある所有格のガールフレンドよりも強力ではないはずです

5.<strong><a href="https://csupalliativecare.instructure.com/eportfolios/4296/Home/VER_Loco_por_ella_Online__Pelcula_COMPLETA_en_Espaol" rel="no-follow">人々が他の人々とイチャイチャしているのを見て</a></strong></p> 人々が他の人々とイチャイチャしているのを見て、彼のガールフレンドもそれをしたことがあるかどうか疑問に思った後。ええと、どうしてそんなに考えすぎやすいのですか

6.所有格のある人との関係を築くには、多くの忍耐が必要です。ポイントはそれが残念だからです

7.それはあなたの苦情に答えるために24時間準備ができていなければならないガールフレンドまたはコールセンターですか？
ループを使用しないセル範囲と配列の高速なやり取り

```Change_Array_Range.bas
Option Explicit

Sub smaple()
    Dim arr As Variant
    Dim r As Long
    Dim c As Long
    
    'セル範囲 →　配列
    'Point: セル範囲のvalueはVariant型の変数に格納すると自動的に2次元配列に格納される。
    arr = Range("A1").CurrentRegion.Value
    r = UBound(arr, 1)
    c = UBound(arr, 2)
    
    '配列 → セル範囲
    Range(Cells(10, 1), Cells(10 + r - 1, c)).Value = arr
    
End Sub
```
上記コードの実行前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274248/94d06bef-dbaa-cde7-5747-78392e49c3f7.png)

上記コードの実行後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274248/b59d6c07-d28a-828c-9079-86fddf4c20bf.png)
[Golang] 構造体 in 構造体のバリデーションについて

GolangのORMライブラリ`GORM`で、モデルの関連づけを表現した際のバリデーションにつまづいたのでメモ。

## 使用ライブラリ群
- ORM: [GORM](https://gorm.io/index.html)
- Validator: [validator](https://pkg.go.dev/github.com/go-playground/validator)

## 困ったこと
GORMで以下のようなHasOne関係のモデルを作り、それぞれの構造体に`validate`タグを付与している状況。

```go
type User struct {
	ID        int       `json:"id" gorm:"primary_key"`
	Email     string    `json:"email" validate:"email,required,max=255"`
	Password  string    `json:"password" validate:"required,min=8,max=16"`
	Profile   Profile   `json:"profile" gorm:"foreignKey:ID"`
}

type Profile struct {
	ID        int       `json:"id" gorm:"primary_key"`
	UserID    int       `json:"userId" validate:"required"`
	Name      string    `json:"name" validate:"required,max=255"`
	Hobby     string    `json:"hobby"`
}
```

UserのみのCreate(Profileは作らない。Save前にValidation実行)をするAPIを用意し、以下のパラメーターをPOSTすると、

```json
{
    "email": "hoge@exa.com",
    "password": "hogehoge"
}
```

以下のようなバリデーションエラーとなる。

```
Key: 'User.Profile.UserID' Error:Field validation for 'UserID' failed on the 'required' tag
Key: 'User.Profile.Name' Error:Field validation for 'Name' failed on the 'required' tag
```

原因は単純で、Userに埋め込んでるProfileの`validate`タグも見にいってるので、バリデーションエラーとなる。困った。

## 解決策

[validator](https://pkg.go.dev/github.com/go-playground/validator)のリファレンスを探ってると、[Skip Field](https://pkg.go.dev/github.com/go-playground/validator#hdr-Skip_Field)なるものを発見。

`validate:"-"`で検証をスキップできるみたい。User.Profileに追記する。

```go
type User struct {
	ID        int       `json:"id" gorm:"primary_key"`
	Email     string    `json:"email" validate:"email,required,max=255"`
	Password  string    `json:"password" validate:"required,min=8,max=16"`
	Profile   Profile   `json:"profile" gorm:"foreignKey:ID" validate:"-"` // ココに追記した
}
...
```

Profileの検証がスキップされてUserの作成に成功。

## 気付き
- jsonタグでも`"-"(ハイフン)`でフィールドが無視できたと思うので、struct tagsのvalueにおける`"-"`は無視する的な使い方をするっぽい？
Accessでレポートがプレビューかマジの印刷（出力）かを判定

#判定できると何がいいの？

例えばこんなことができるん。

* 印刷する時だけ『社外秘』『SAMPLE』とかの透かしを入れられる。
* プレビューの時だけ補助線を表示できる。（熨斗とかお礼状みたいに見た目の綺麗さが求められる印刷の微調整とかが便利）
* 『本当に印刷した時』だけ印刷時刻をデータベースに書き込んだりができる。


#やり方

```vb
'Windowsのuser32のライブラリの機能を拝借して実現するよ！
Private Declare Function is_window_enabled Lib "user32" Alias "IsWindowEnabled" (ByVal hwnd As Long) As Long

'詳細には『detail』という名前つけてます
Private Sub detail_Format(Cancel As Integer, FromatCount As Integer)
    
    'プレビューか印刷（出力）かを判定して背景画像を表示ONOFF切り替えね！
    If is_window_enabled(Me.hwnd) = 0 Then
        Me.img_back.Visible = True
    Else
        Me.img_back.Visible = False
    End If

End Sub
```

#注意点

**フォーマット系のイベントで判定すること！**
Report_Open()とかのイベントで判定しちゃダメ。

例えば前述の例をReport_Open()でやったとすると、印刷（出力）の時に背景が表示されないです。
Report_Open()は名前の通り『開く時』に呼び出されるから、印刷する時は実行されないです。


#判定を実際使ってみるとこんな感じ

**印刷プレビュー** の時は背景画像が表示されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f4c4002b-beaa-006a-c4b8-9af4e618df2f.png)

今回は印刷のスタブとして **Microsoft Print to PDF** に印刷指示を飛ばします。
『Microsoft Print to PDF』ってなんぞ？って時は下記。
[Windows10の標準機能で画像をPDFに変換するんだぞう（余計なソフトは入れない）](https://qiita.com/waokitsune/items/ccf146cfaa23eee613a6)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/8a5c4998-fc35-ab1c-b3fb-7767a891ade7.png)

印刷（出力）には背景画像が表示されてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/7372b39e-2e58-faaa-32e9-55382f40ae38.png)

#蛇足
user32を使えばVBAでできないことを結構補えるので便利です。

#参考サイトさん
https://hatenachips.blog.fc2.com/blog-entry-170.html

#バージョン
Windows 10 Pro バージョン 20H2 OSビルド 19042.804
Access for Microsoft 365 MSO（16.0.13628.20128）32ビット
ITパスポート

2020年12月20日にITパスポートを受けました。
合格したので記事を書いておきます（正式な合格通知は2021年2月18日）。
少しでも次受ける方の参考になれば幸いです。

## 受験理由
■１ 他分野から転職したのでIT業界の基礎知識を身につけるため

## 感想
■１ ニューラルネットワークや機械学習などの最新の話題も出題されていました。こういったAI関係の話題はあまり学習教材にないので、G検定などの勉強をしていないと「？」となる問題も一部ありました。
	
## 学習教材
■１ かんたん合格 ITパスポート教科書 令和2年度（坂下⼣⾥ & ラーニング編集部, 2019, インプレス）
・・・980円程でお手頃で、内容もまとまっています。とりあえず、これを一読するのがよいと思います。
■２ かんたん合格 ITパスポート過去問題集 令和2年度 春期（間久保 恭子, 2019, インプレス）
・・・こちらも1,180円程とお手頃です。１の学習教材が終わったら、これを使って問題を解きまくるのがよいです。
■３ 要点確認これだけ! ITパスポートポケット○×問題集（近藤 孝之, 2020, 技術評論社）
・・・用語や単語をなかなか覚えられないとき、こちらで集中的に覚えるとよいです。小さいので通勤中の勉強に使いやすいです。
■４ キタミ式イラストIT塾 ITパスポート 令和02年（きたみ りゅうじ, 2019, 技術評論社）
・・・イラストが多いのでイメージで覚えたいときはこちらも使ってください。

## 学習方法
■１ 2020年8月受験の予定でしたが、タイミングがなかなかあわず、2020年12月に受けることになってしまいましたので、学習教材1～4を使用して勉強しました。
・・・流れとしては、とりあえず学習教材1を読み、その後、学習教材2の過去問を実施ました。タイミングが悪く、4カ月ほど試験が流れたので、学習教材4も読みました（同じ教材では飽きたので）。試験1週間前には学習教材3を通勤中にずっと読んで、用語の理解を深めました。

## 試験
■１ 問題集に載っていない問題も案外多くでます。

## 反省点
■１ 最新の話題もチェックしておけばよかった。

## 試験前にやっておいてよかったこと等
■１ 学習教材3で用語を試験直前まで確認したので、用語系の問題はサクサク解答できた。
VyOS 1.3でwireguardを使う (その3)

# つづき
[(その2)](https://qiita.com/MT-07/items/41b1d1ebedb5793207a1 "その2")までで紹介した方法ではVyOSへリモートアクセスできるだけで、あまり実用性がないかと思い、具体的に下図のような構成を想定し、PCからwireguard越しにホストへアクセスする方法を紹介します。
![例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223667/20a1a506-6408-761f-25e3-bed271223947.png)
なお

 - PCは自身でパブリックIPを持っていても良いし、インターネット接続できるネットワークにいても良いです。
 - VyOSは自身が固定パブリックIPを持っており、その接続形式は問いません(IPoEでもPPPoEでも)

## 作り方
前提として、[(その1)](https://qiita.com/MT-07/items/75bfa00b20f6ae4b6f62 "その1") [(その2)](https://qiita.com/MT-07/items/41b1d1ebedb5793207a1 "その2")は実施済みとします。

### VyOS側で実施
1. wireguardのインターフェースwg01からのパケットはプライベート側のインターフェースeth1でmasqueradeさせる。

    ```
    # configure
    # set nat source rule 10 outbound-interface 'eth1'
    # set nat source rule 10 translation address 'masquerade'
    # commit
    # save
    ```

### クライアント側で実施
1. 設定を編集します。[Peer]セクションのAllowedIPsにホスト側のネットワーク(192.168.0.0./24)を追記します。
    ![prtscn_2021-2-21_0-37-18_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223667/b20dd46a-7711-3d17-be52-c6e997a60864.png)

    ※公開鍵の内容が(その2)と違いますが無視してください。。。
1. 設定が完了したら「保存」をクリックして完了です。

### 備考
サーバ側にしてもクライアント側にしても[Peer]セクションのAllowedIPsはwireguardのインターフェースに対して、ルートを追加するイメージだとちょっと分かりやすいかもしれません。