OmniAICreator/Qiita-1.07M huggingface dataset:
数値をn分割にしてリスト化する方法

# Background 
[いらすとやの画像をドット絵にしたった。(part1)](https://qiita.com/satsukiya/items/8a1753a0085e94d0f1bf)で色を4分割するときに
`range_color = [0, 85, 170, 255] `(または`[ i* int(255/3) for i in range(3)]`）と閾値を手動で設定していました。（実質は3分割にして4つの値の近似をとっていました。）

今回はちょうど割り切れたので問題なかったのですが、範囲と分割数が任意で違った値だったらどのようにアルゴリズムを設計すればいいかと思ったのでまとめてみました。

上記の例では範囲は255、分割数は3を指しています。


# Method

きれいに割り切れずに余りが発生します。
その場合は最初の要素に+1を均等に足すようにします。

で、方法ですが、
1. 範囲と分割数から商と余りを算出する
2. 一時的な計算用に足し算リストを作成する
3. 足し算リストをもとに要素(境界値)を計算してpushする。

の流れです。

# Development

```Python
import sys

def main():
    if len(sys.argv) != 3:
        print("[USAGE] you give parameters this command.")
        print("[EXAMPLE] python main.py [range number] [n-division number]")
        print("[EXAMPLE] python main.py 255 4")
        sys.exit()

    r = int(sys.argv[1])  #範囲 
    d = int(sys.argv[2])  #n分割数
    q, mod = divmod(r, d) #商、余りの計算

    #足し算リスト
    plus = [q + 1 if i < mod else q for i, d in enumerate(range(d - 1))]
    print(plus)

    #出力
    dst = []
    dst.append(plus[0])
    for i in range(len(plus)):
        dst.append(plus[0] + sum(plus[:1 + i]))
    print(dst)

if __name__ == '__main__':
    main()
```

# Comment

```text
\W $ python main2.py 255 6
[43, 43, 43, 42, 42]
[43, 86, 129, 172, 214, 256]

\W $ python main2.py 255 10
[26, 26, 26, 26, 26, 25, 25, 25, 25]
[26, 52, 78, 104, 130, 156, 181, 206, 231, 256]
```

「足し算リスト」と言っているのはそれぞれの要素の間隔の値をリスト化したものです。
このリストをもとに`sum(plus[:1 + i])`で各要素を計算します。

例) 範囲 255、 分割数 10、7つめの要素を計算したい場合
初期値 26 + [26, 26, 26, 26, 26, 25] の合計値 = 181

高校数列で習った[階差数列](https://examist.jp/mathematics/sequence/kaisasuretu/)ですな。:smirk_cat:
テラナツい

```math
a_n = a_1 + \sum_{k=1}^{n-1}b_k  \quad (n \geqq 2 )
```

# PostScript
何かコンテンツを作成していると小さなスケールでもアルゴリズムを少し考えることがあります。
開発者としてはqiitaのitemsが増えるので書くことに事欠かないです。:robot:

# Reference
- [整数をできるだけ均等になるように n分割](https://qiita.com/keisuke-nakata/items/c18cda4ded06d3159109)
    - `[(x + i) // n for i in range(n)]` でできるのですね。こっちの方がシンプル。
kaliにDVWA環境をセットアップする

## 前提
- kali linux環境がある

## 目標
- DVWAアクセスしログインする（環境作る）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584889/f5559866-0840-94c5-9008-6662d9e5daa4.png)

## 内容
### DVWAとは
- php/mysqlベースのウェブアプリケーション
- 脆弱性満載
- セキュリティの勉強用またはテスト用

### セットアップ手順
- DVWAダウンロード
    - http://www.dvwa.co.uk/
- zipを解凍する
    - 以下コマンド参照
    - http://localhost/DVWA-master/ にアクセスしてみる
    - localhost配下にfileがないので当然NotFoundが返ってくる

```sh:
# 取り合えずコピーする
root@kali:~# cp /root/Downloads/DVWA-master.zip /root
# 解凍する
root@kali:~# unzip DVWA-master.zip
# 外部アクセスできるようにapache2起動する
root@kali:~# service apache2 start
```

- localhostから読めるように解凍後のファイルを配置する
    - 以下コマンド参照
    - http://localhost/DVWA-master/ にアクセスしてみる
    - アクセスできるがエラーが返ってくる```DVWA System error - config file not found. Copy config/config.inc.php.dist to config/config.inc.php and configure to your environment.```

```sh:
# localhostは/var/www/html/配下を参照
# -R:サブディレクトリもコピー
root@kali:~# cp -R /root/ /var/www/html/
# 必要ならapache2起動する
``` 

- エラーを解決する
    - 以下コマンド参照
    - http://localhost/DVWA-master/ にアクセスしてみる
    - setup.phpの表示ができるようになった。でもページを読む限りデータベースのセットアップが必要らしい
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584889/7bc572a7-c392-8309-8558-1a4ce435b84c.png)


```sh:
# configファイルのあるdirに移動
root@kali:~# cd /var/www/html/DVWA-master/config/
# エラー指示に従い名前変更
root@kali:/var/www/html/DVWA-master/config# mv config.inc.php.dist config.inc.php
#ついでに権限与えておく
root@kali:~# chmod -R 777  /var/www/html/DVWA-master/
# before
# drwxr-xr-x  8 root     root      4096  2月 15 00:30 DVWA-master
# after
# drwxrwxrwx  8 root     root      4096  2月 15 00:30 DVWA-master
# 必要ならapache2起動する
``` 


- データベースをセットアップする
    - 以下コマンド参照

```sh:
# mysqlを起動
root@kali:~# service mysql start
# ログイン
# パスワードを要求されるが無視すればログインできるた
root@kali:~# mysql -u root -p
# データベースでmysqlを指定
MariaDB [(none)]> use mysql
# mysqlのユーザー権限を設定する
# GRANT ALL PRIVILEGES ON `DB名`.テーブル TO 'ユーザ名'@'ホスト名' identified by 'パスワード';
MariaDB [mysql]> grant all privileges on *.* to 'mysql'@'localhost' identified by 'mysql';
# ctrl+cで脱出
# セットアップページに指示のあるconfigを編集する（以下画像）
root@kali:~# vi /var/www/html/DVWA-master/config/config.inc.php 
``` 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584889/33a5d1d1-c400-82f9-03bb-9e19a9e384a9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584889/575b7feb-c306-75bb-f4db-1d252de71466.png)


- アクセス確認
    - http://localhost/DVWA-master/setup.php 
下部にあるcreateボタンを押す（ログイン画面へ自動遷移）
    - admin/passwordでログイン
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584889/37824cee-be61-616c-a791-4f1f19d672dc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584889/785dc1af-f0dd-f626-91c5-c5cdae95c89b.png)
MacでGrafana + Lokiのサンプル

## 概要
LokiをMacでどんな感じか確認したかったが、Macだとコンテナログの保存先がVMであるということから公式のdocker-composeだと確認しづらいのでNginxのコンテナを入れて調整した。


## 構成図
LinuxではDockerのコンテナのログが「/var/lig/docker/containers」にあるが、MacではVMを利用しているため直接参照はできない。
そのためカレントディレクトリに「./var/log/nginx」を準備して、nginxコンテナにmountするようにした。
![loki-sample-for-mac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/a61933af-5a2d-2113-7130-10e68cd5d7a8.png)



## コード
[いいからコードよこせという人はこちらへ](https://github.com/nagi125/loki-sample-for-mac)


### ディレクトリ構成
```
├── docker-compose.yml
├── promtail-sample-config.yaml
└── var
    └── log
        └── nginx
```

### docker-compose.yml
```yml
version: "3"
networks:
  loki:
services:
  grafana:
    image: grafana/grafana:master
    ports:
      - 3000:3000
    networks:
      - loki

  loki:
    image: grafana/loki:latest
    ports:
      - 3100:3100
    command: -config.file=/etc/loki/local-config.yaml
    networks:
      - loki

  promtail:
    image: grafana/promtail:latest
    volumes:
      - ./var/log:/var/log
      - ./promtail-sample-config.yaml:/etc/promtail/promtail-sample-config.yaml
    command: -config.file=/etc/promtail/promtail-sample-config.yaml
    networks:
      - loki

  nginx: 
    image: nginx:latest
    volumes:
      - ./var/log:/var/log
    ports:
      - 8080:80
    networks:
      - loki
```

### promtail-sample-config.yaml(nginxのlogを監視するように調整)
```yaml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs
      __path__: /var/log/nginx/*log
```

### 立ち上げ
```
$ docker-compse up
```

## GUI確認手順
下記にアクセスしてGrafanaのログイン画面を表示する
http://localhost:3000
![Grafana-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/c246f0c1-3b1a-6ce2-86a2-e1ac833fbf7f.png)


初期IDとパスワード(admin:admin)を入力するとパスワード変更画面が表示されるのでここではスキップする
![Grafana-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/33ccc1f9-353b-5c6e-810a-1099c36ca1f6.png)

Data Souceを選択し、Lokiを選択する
![Home_-_Grafana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/1e4e994f-7e0a-89ea-755e-7504220d3028.png)
![Add_data_source__Add_data_source_-_Grafana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/d2160d7b-a2a0-12d7-070b-a79c19ce3038.png)


URLは下記にして設定を完了させる(※コンテナ名がホスト名となるためlokiとする)
http://loki:3100
![Loki__Settings_-_Grafana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/32ff1454-a5cb-23d0-16cc-db754c484788.png)


成功していればラベルが追加されているので選択する
![Loading__Settings_-_Grafana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/653dbeaa-b8c7-eca2-ad0b-d8ac1b03ee6d.png)

ラベルを選択し、ログが表示されれば成功です。
「|=」で文字列検索 「|~」で正規表現検索ができます。
![Loading__Settings_-_Grafana-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23306/9a959c2c-a15d-e04b-21b4-0eccb69c3b32.png)
本１冊を機械翻訳で訳してみた


昨年暮れに、[新 企業の翻訳者を目指す皆さんへ](https://www.amazon.co.jp/%E6%96%B0-%E4%BC%81%E6%A5%AD%E3%81%AE%E7%A0%94%E7%A9%B6%E8%80%85%E3%82%92%E3%82%81%E3%81%96%E3%81%99%E7%9A%86%E3%81%95%E3%82%93%E3%81%B8-%E4%B8%B8%E5%B1%B1%E5%AE%8F/dp/4764906066)という本を出版しましたが、その本を機械翻訳を使ってまるまる１冊英語に翻訳してみました。[翻訳済みの英語はこちら](https://stratus.dyndns-home.com/~hiroshi/books/rtm2/rtm2-en-preview.pdf)です。PDFファイルを無料でダウンロードいただけます。

使った機械翻訳システムは[みらい翻訳](https://miraitranslate.com/)です。[Google翻訳](https://translate.google.com/?hl=ja)や[Microsoft Translator](https://translator.microsoft.com/)も試してみましたが、少なくとも昨年夏にいろいろ試した結果、（英日はわかりませんが）日英の翻訳品質が一番良い印象でした。もっとも、定量的な評価をしたわけではないので、あくまでも「印象」です。

私は1980年代の終わりころに機械翻訳の研究をしていました（学位も機械翻訳の研究でいただきました）。ですので、ある程度は機械翻訳のことはわかっていると思っていました。初期のもくろみは、辞書の整備と十分な前編集を行うことで、ほぼ後編集なしで本１冊をまるまる英訳することでした。後で述べるように、今の機械翻訳の精度では、まだ後編集なしというわけにはいかないようです。ただし、日本語を丁寧に書くことで、後編集の手間を大幅に削減できることはわかりました。結果、本１冊をほぼ１ヵ月で英語に翻訳することができました。

# 翻訳対象
本の内容は、もともと2009年に書いた本で、IBM東京基礎研究所に勤務していたころに、社内の研究員に宛てて書いていたレターやブログを中心に、企業における研究者のあり方について論じたものです。これを、その後のキヤノン・統計数理研究所・PFNでの経験を元におよそ内容の半分を書き直したものが、今回翻訳対象とした本です。研究のやり方だけでなく、コミュニケーション、リーダーシップ、キャリア、倫理など社会人としての技術者に広く読んでいただける内容をカバーしています。従って、専門的な内容は少なく、機械翻訳の対象としては、一般文章と考えてもよいでしょう。である調の本文のところどころに、ですます調のレター・ブログが挟まっている点は、少し注意が必要でしょう。日本語文書はGoogle Docsで作成しましたが、レター・ブログ部分は異なるフォーマット（文字色）で区別していました。本全体の長さは146,125字、紙媒体の本で232ページです。

# うまくいかなかったこと
自然言語処理の難しさの１つは、多義語の扱いにあります。日本語で同じ表記なるものでも英語ではまったく別の意味になる場合があります（例えば、自転車のバルブはvalveですが、電球のバルブはbulbです）。従って、文脈に応じて翻訳を変えなければなりません。以前の自然言語処理は、この文脈の処理が難しかったのですが、今の機械翻訳は、大量の翻訳例から統計モデルを作って正しい翻訳を推測します。この際に、文脈が考慮されるので、文脈の応じた訳語の選択が相当うまく行くようになってきています。

ところが、この文脈を考慮することが裏目に出ることがありました。本書の中で論文の書き方を議論する際、論文のタイプとして「事実に関する論文」「法則に関する論文」「方法に関する論文」と３つに分けたのですが、「事実に関する論文」が、その場その場の文脈によって、”a paper on facts”, “a factual paper”, “a fact paper”と訳し分けられてしまったのです。おそらく、それぞれの文脈で統計的により現れやすい表現だったのでしょうが、ここではそれぞれのタイプの名前として使った表現なので、表現を統一したかったところです。表現を統一するためには、辞書登録すればよいかというと、必ずしもそれでうまくいくとは限らないことがわかりました。文脈による訳し分けをしてほしい場合と、訳語の統一をしてほしい場合があり、その区別はまだまだ難しい問題のようです。

ちなみに、誤訳で面白かったのは、「地頭の良い人」という意味で使った「地頭」が “jito (manager and lord of manor) “ と訳されたことです。これは、鎌倉幕府の荘園を管理する人のことですね。
# うまくいったこと
辞書設定による訳語のコントロールが、なかなか思うようにいかなかったので、「辞書整備＋前編集」という当初の方針はあきらめ、翻訳結果を手作業で修正することにしました。多くの場合、機械翻訳された英文を見るだけで原文の意味が推定できたので、原文に戻ることなく後編集ができました（元々自分で書いた文章ですから当り前といえばその通りですが）。

嬉しい驚きは、新たに書き起こした部分については機械翻訳が相当うまく行ったことです。本のおよそ半分が書き起こしですが、書き起こし部分については特に次の３点について気をつけました。

- １文をできるだけ短くすること
- どうしても長くなる場合は従属節を鍵括弧で囲むなど、文の構造を明確にすること
- できるだけ、主語を省略しないこと

外国人に日本語を話すときには、文の構造に気をつけて話しますよね？ それと同じようなことだったと思います。

年末年始休みに入ってから作業を始め、まずは明らかな誤訳や、意味の通じないところを自分で修正しました。その後、何人かの外国人の友人（フィリピン、ニュージーランド、ルーマニアの出身）に見てもらい、気の付いた点を直してもらいました。出来上がった英語の文書（56,035語）は、出版クォリティにはほど遠いですが、無料ダウンロードでカジュアルに読んでいただく分には、ほとんどストレスなく読めるものに仕上がったと思います。

機械翻訳がなければ、すべてを自分で翻訳せねばならず、とても１ヵ月ではできなかったと思います。機械翻訳システムは、それなりに心の準備をして使えば、本１冊を英訳するのにも使えるレベルのツールになってきたな、と思います。

# 謝辞
この試みに関して、翻訳システムの試用を快く提供してくださった株式会社みらい翻訳の皆様、英訳の無料ダウンロードを許可してくださった近代科学社の皆様、それに英訳の改善に力を貸してくださった、Roberto Legaspi、Stuart MacDonald、Mihai Morariuに深く感謝します。
（備忘）Dockerを使ってRStudio環境を構築する

#はじめに
最近、Twitterで大変参考にしているデータサイエンティストさんがいる。
そのデータサイエンティストさんがブログにて開催(?)しているデータサイエンティストになるための講座の一発目がDockerによる環境構築だった。

▼こちら
[Docker超入門①〜Dockerってなに？〜【初心者向け】](https://datawokagaku.com/whatisdocker/)

超入門というだけあって、Dockerが何かから始まって、どう起動するかまで丁寧に説明してくださっている。ちなみにこの後、Python入門が始まっているので、データサイエンスに興味がある方は要チェック。

しかし、一回コンテナ構築しただけでは当然覚えるはずもない。
かといって、いくつもJupyter構築するのものなぁ…と思ったので、
「[Rによる優しい統計学](https://www.amazon.co.jp/R%E3%81%AB%E3%82%88%E3%82%8B%E3%82%84%E3%81%95%E3%81%97%E3%81%84%E7%B5%B1%E8%A8%88%E5%AD%A6-%E5%B1%B1%E7%94%B0-%E5%89%9B%E5%8F%B2/dp/4274067106/ref=as_sl_pc_tf_til?tag=datawokagaku-22&linkCode=w00&linkId=149651120b2fae7f071864547af0c1ce&creativeASIN=4274067106)」を使って勉強するのも兼ねて、RstudioをDocker上（ローカル）で動かしてみることにした。

結論から言うと、あまりにも簡単すぎたのだが、いくつか別サイトも参考にしたので、
今後のためにここにまとめておくことにした。


#コマンド
※前提：Dockerインストール済であること

```
docker pull tokyo/rstudio
docker run -d -p 8787:8787 tokyor/rstudio
```

これだけ。
本当に。
（今振り返ると、なんであんなにググったのか意味わからないくらい一瞬だった）

pullするのはrocker/とか色々あるけれど、
とりあえず日本語環境がある[tokyo/rstudio](https://hub.docker.com/r/tokyor/rstudio/)をpull。

#その後
早速本を読み進めている。
私はPython派なので、本が終わったあとおそらくRは使わないので、
このままコンテナのみ破棄する予定。
それにしても便利だなぁ、Docker。

▼参考サイト
[データ分析環境の構築にDockerを利用しよう](https://qiita.com/uri/items
/475eb4dd158ee22f2635)
（3年も前の記事であることにびっくり…）
[DockerでRの環境構築](http://r-beginner.hatenadiary.jp/entry/2016/11/06/174302)
Fastlaneのコマンドラインでバージョン番号を更新

今、開発しているアプリでは
Embedded Framework を活用してターゲット分割しており
バージョン番号が複数のInfo.plistにまたがっており
バージョンを更新する際は、手動もしくは、CircleCIで実行されるFastlaneで
バージョンを更新しているんですが、任意のタイミングで、バージョンを更新したいケースで、コマンドを忘れてしまうのでメモ

```
fastlane run increment_version_number version_number: "1.0.0
```

Bundlerを使っている場合

```
bundle exec fastlane run increment_version_number version_number: "1.0.0
```
herokuでdb:migrateしたのにunknown attributeが発生

`heroku run rails db:migrate`は正常に済んでいるように見えるのだけれども、
Railsアプリからデータを登録しようとすると`We're sorry, but something went wrong.`のエラー画面に。

herokuのログ（[more]からView logs）で確認したら、追加したはずのカラムが`unknown attribute`になっている。

#結果
今回は`heroku restart --app <アプリケーション名>`で解決。


これまではrestart無しでもカラム追加を反映できていたのです。
何が違うとこうなるんでしょうか？（そこまで調べ切れていません...）
Windows環境のJetBrains IDEのTerminalに環境変数を適用するにはIDEの再起動が必要

内容はタイトルの通りです。

# 発生した問題
新しく`Path`に変数を追加したのに、`Intellij IDEA`の`Terminal`からコマンドを叩いても認識されませんでした。
`Terminal`で新しいタブを生やす等の操作をしても認識されないままでした。

コマンドプロンプトや`Windows PowerShell`を起動してコマンドを叩くと認識されるので、`Path`を通すことそのものは成功しているようでした。

# 解決方法
タイトル通り、`IDE`を再起動すれば反映されました。
勾配降下法の学習率調整手法の概要

## この記事について
勾配降下法について、G検定対策で概要をまとめます。
出題レベルに合わせるので、あまり細かい点は突っ込んでいません。
模試で出てきた言い回しも併せてまとめました。

## 勾配降下法の種類
#### バッチ勾配降下法
  * 全訓練データを利用して勾配を計算する
  * 局所解から抜け出せない危険があるが必ず収束する

#### 確率的勾配降下法(SGD)
  * 全訓練データからランダムに一つのインスタンスを利用して勾配を計算する
  * 全体の最小値を見つけやすいがなかなか収束しない→（最短で最適解にたどり着かない）

#### ミニバッチ勾配降下法(MSGD)
  * データセット全体からランダムに複数のインスタンス（複数に分割したサブセット）を利用して勾配を計算する
  * バッチ勾配降下法とSGDの中間

#### 勾配降下法の注意点
* 学習率が小さすぎると`収束が遅くなり`、逆に大きすぎると`発散`してしまう

## 勾配降下法の手法
#### Momentum(慣性)
* 丘にボールを転がすの同じ。ボールと勾配の方向が同じなら加速し、逆なら原則する
* 表現例：`勾配の方向を現在のパラメータ更新にも影響させる`

#### Adam
* それぞれのパラメータに対し学習率を計算し適応させる
* Momentumと似ている
* 指数関数的移動平均（指数関数的減衰平均）を蓄積し、過去の勾配の指数関数的移動平均を保持する
* 表現例：`勾配の平均と分散を推定し利用する`

#### AdaGrad
* 学習率をパラメータに適応させる。 
* 頻出のパラメータに対してはより小さな更新を実行し、まれなパラメータに対してはより大きな更新行う
* 過去のすべての2乗勾配を累積する
* スパースなデータを扱うのに適している

* 表現例：`学習率をパラメータに適応させることで自動的に学習率を調整することができる`
* 表現例：`勾配を 2 乗した値を蓄積し、すでに大きく更新されたパラメータほど学習率を小さくする`

#### RMSprop
* Adadeltaという手法とほぼ同様（同時期にほぼ同じの手法が開発された）
* 「Adagradは急速に学習率が低下する」という問題を解決する必要から開発された
* 学習率を勾配の2乗の指数関数的に減衰する平均で除算する
* 指数関数的移動平均（指数関数的減衰平均）を蓄積する
* 表現例：`AdaGradにおける一度更新量が飽和した重みはもう更新されないという欠点を指数移動平均を蓄積することにより解決した`

## 試験中の端的な目途の付け方
* `勾配の2乗`の知す関数的減衰平均 or 移動平均 → RMSprop/Adam
* `慣性項`　→ Momentum
* `稀なパラメータに対して大きな更新` → Adagrad/Adadelta

[実践で理解する G検定 ディープラーニング教本](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%81%A7%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B-G%E6%A4%9C%E5%AE%9A-%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E6%95%99%E6%9C%AC-G%E6%A4%9C%E5%AE%9A%E5%90%88%E6%A0%BC%E8%80%85%E3%81%8C%E6%95%99%E3%81%88%E3%82%8B%E6%9C%80%E7%9F%AD%E3%81%A7%E5%90%88%E6%A0%BC%E3%81%99%E3%82%8B%E7%A7%98%E6%B3%95-%E7%A5%9E%E8%8D%89%E5%87%BA%E7%89%88-ebook/dp/B07QX3BRH4/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=G%E6%A4%9C%E5%AE%9A&qid=1582111519&sr=8-5)

## おまけ
勾配降下法を「谷にボールを落とすイメージ」で書かれていてなるほどと思ったサイトです。
微分の傾きが0を目指す図はよく見るのですが、こちらもわかりやすかったです。
http://yaju3d.hatenablog.jp/entry/2017/08/27/233459

## 参考
* https://ruder.io/optimizing-gradient-descent/index.html
* https://drumato.hatenablog.com/entry/2018/11/02/133055
* http://study-ai.com/generalist/
* [実践で理解する G検定 ディープラーニング教本](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%81%A7%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B-G%E6%A4%9C%E5%AE%9A-%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E6%95%99%E6%9C%AC-G%E6%A4%9C%E5%AE%9A%E5%90%88%E6%A0%BC%E8%80%85%E3%81%8C%E6%95%99%E3%81%88%E3%82%8B%E6%9C%80%E7%9F%AD%E3%81%A7%E5%90%88%E6%A0%BC%E3%81%99%E3%82%8B%E7%A7%98%E6%B3%95-%E7%A5%9E%E8%8D%89%E5%87%BA%E7%89%88-ebook/dp/B07QX3BRH4/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=G%E6%A4%9C%E5%AE%9A&qid=1582111519&sr=8-5)
TIPS: リモートブランチのコミットをローカルブランチに完全同期する

僕のチームではfixupコミットを多用しており、force pushがよく使われます。しかし、force pushを多用しているとレビュー時などにローカルブランチのコミットログとリモートブランチのコミットログが変わってしまいpullだとうまくいかないことが多いです。
こういう時にローカルにあるブランチをリモートブランチと完全に同期させたい、みたいな気持ちになることが多いのですが、それを`git reset --hard`を使えばできることを知ったので紹介します。

`git reset --hard`を使う時`HEAD`とか`HEAD~`とかをオプションで渡すことが多いと思うのですが、ここでブランチを指定すると、そのブランチのHEADを指定したのと同じ意味になります。

結論から行ってしまうと

```
git reset --hard 今のブランチと同期させたいリモートブランチ
```

みたいな書き方でリモートブランチと完全同期させることができます。

例(`hoge`のbranchを完全同期させる場合)

```
git fetch
git checkout hoge 
git reset --hard origin/hoge 
```

参考文献
http://www-creators.com/archives/1097
Goの文法を雑多にまとめる

Golangの文法を自分用メモとしてまとめる。


# 雑多なメモ

```
# ライブラリのdocの確認
$ godoc fmt Println
$ godoc os/user Current

# コマンドラインでフォーマット形成
$ gofmt -w file.go

# ドキュメントをローカルポートから見る
$ godoc -http=:6060
```

```go
// %ホニャララのPrintf (Printlnだとダメ)
fmt.Printf("%T", var) // 変数の型
fmt.Printf("%v", var) // value in default format
fmt.Printf("%d", var) // 10進数で表示

// intは環境によって32bitか64bit,指定したい場合にはint32, int64を使う。

// 文字列からn番目の要素を取り出す
fmt.Println("Hello"[0])  // 72(ASCIIコード)
fmt.Println(string("Hello"[0])) // "H"(stringに戻す)

// エラーを生じうる型変換
i, err := strconv.AtoI("15")

// バイト配列
b := []byte{72, 73} // [72 73]
c := []byte("HI")   // [72 73]
string(b)           // "HI"

// 可変長引数を関数に渡す
func foo(params ...int){処理} // paramsにはintのスライスが入る
// スライスを展開し各を引数として関数に放る
foo([]int{1, 2, 3}...) 

// 標準パッケージのtesting
$ go test ./...
```

## クロージャ(関数閉包)

closureの定義のちゃんとした説明には踏み込まず、具体例からやんわりまとめる。

```go

func incrementGenerator() (func() init) {
    x := 0
    return func() int {
        x++
        return x
    }
}

func main() {
    counter := incrementGenerator()
    fmt.Println(counter())
    fmt.Println(counter())
}
```

以上の例だと、counterという変数には無名関数が保存されており、この関数内から、この関数外で定義された変数xを参照している。このため、このxの値は保持され、二度目にcounter()を呼び出した際には、x=1が入っている。

# logライブラリ

```go
log.Println("error message")
log.Fatalln("error message") // プログラム終了する
```
ログをファイルに書き出すようにsettingをするには以下。

```go

func LoggingSettings(logFile string) {
    logfile, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    //multiWriterは複数のio.Writerを受け取り、すべてに同時に書き込み対象に設定
    multiLogFile := io.MultiWriter(os.Stdout, logfile)
    log.SetFlags(log.LDate | log.Ltime | log.Llongfile)
    log.SetOutput(miltiLogFile)
}


func main() {
    LoggingSettings("test.log")
}
```

# panicとrecover
golangでは使用が推奨されておらず、エラーハンドリングを使うべし。deferで指定する関数に入れることで生じたpanicをキャッチして処理できる。

```go
// panicのキャッチかつプリント
s := recover()
fmt.Println("OK?")
```

# ポインタ周り

```go
// *int型を返す [ポインタ！！]
new(int)

 // ポインタではなくスライス型を返す
make([]int, 0)
```

* 初期化
 * スライスやマップは`[]int{}`より`make([]int, 0)`で初期化が推奨される。
 * 構造体は`new(MyStruct)`より`&MyStruct{}`で初期化されることが多い。

* `(構造体のポインタ).(属性値) = (*構造体のポインタ=実態).(属性値)`が成立、つまり、

```go
// 構造体の初期化かつそのポインタの取得
s := &MyStruct{初期化}

// どっちでもいい
s.field1 = "field1"
*s.field2 = "field2" 
```

# 構造体周り

* 構造体のコンストラクタのプラクティス

```go
func New(x, y int) *Mystruct{
    return MyStruct{x, y}
}
```

* 構造体の破壊的/非破壊的メソッド

```go
// 破壊的メソッドの定義
func (s *MyStruct) overwrite {
    s.var = "new value"
}


// 非破壊的メソッドの定義
func (s MyStruct) overwrite {
    s.var = "new value"
}
```

* golangの構造体は継承を`embedding(実現)`によって実現する
* non-struct型のメソッドを拡張

```go
// カスタムの新しい型を作る
type MyInt int

func (i MyInt) newMethod {処理}
```

# Type Assertionとswitch-assert文

* Type Assertion  
インターフェイスから他の型へは`type assertion`、ある型から他の型へは`キャスト`、,`type conversion`と呼ぶ。

```go
// interface{}型からint型へ
var a interface{} = 5
b := a.(int) // エラー時にはpanicが生じる
``` 

* switch-assert文

```go
switch t := i.(type) {
    case int: 
        処理
    case string
        処理
    default: 
        処理
    }
}
```
react-nativeをwindowsのvirtualbox上で開発する


# 背景

Windows環境でReact Nativeの開発をやってみようと環境構築をしてみた。
普段の開発はローカルのvirtualboxに入ったlinuxでやっているので、
Powershellをつかったwindows環境構築は行わずに、
当初は

* WSL (Ubuntu)
* VSCode

を利用した環境を構築した。

しかし、

* expo start したあとにネットワークが切断される
    * サービスから LxssManagerを再起動すれば一応復帰する
* hot reloadが効かない
    * windows上のvscodeで、WLSのファイルを直接弄っているからinotify通知が来ない
* そもそも更新した内容が反映されない
    * androidのアプリ側でキャッシュ削除したり expo start -c などで治るときもある

という3つの不安定さがあった。

# 対応

まず、linux(centos7利用)上ではexpoの動作は問題ない。
また、VSCodeには remote development機能が存在している。
　→　[remote developmentの設定はこちら参照](https://dev.classmethod.jp/etc/vs-code-remote-development-ec2/)
これらを利用した。

## ゴール

* virtualboxのcentos7でexpoは動かす
* 開発はwindows側のvscodeで実施する

## ゴールへの要点

* virtualboxのポートフォワーディング機能で 19000, 19001 をフォワードする

[こちらの記事](https://qiita.com/daijinload/items/85f6e84926f41812ed70)に設定方法は記載あり。

* expoを動かす際に、ホストwindows側のIPアドレスを指定する

```bash
REACT_NATIVE_PACKAGER_HOSTNAME={your windows IPaddr} expo start
```

windows IPaddrはipconfigコマンドなどで調べる。



上記2点がつまづきポイント。

あとは同じネットワーク内にスマホとPCが繋がっていれば、
スマホのexpoアプリからチェックできる。
vscodeのremote development機能で、ソースコードをいじったら、
hot reloadも動く。

素晴らしい！


remote debug機能とexpoの ***REACT_NATIVE_PACKAGER_HOSTNAME*** を応用すれば、リモートサーバでの開発もできそう。


macと違ってwindowsだと開発にひと手間掛かっちゃう世界が、
WSLの発展で解消されればいいなぁ。
Rails: 継承とMix-inは使わないこと〜コードの共通化について

<font color="gray">※この記事は、まとめ記事「多人数によるRailsアプリケーション開発」の1項目にする予定です。</font>

## 要旨

Railsアプリケーションでの可読性、引き継ぎや改修のしやすさについてあれこれ考えているのですが、1つには「コードの共通化」に問題があると感じています。

これから作るRailsアプリケーションでは、次のガイドラインを設けたい。

- コードの共通化のために親クラスやモジュールを書くのは禁止。
- コードを共通化するときは、サービスクラスを呼び出す形にする。
- いきなりコードを共通化せずに、立ち止まってよく考える。重複を放置することも選択肢に入れる。

## コードの共通化の害

継承の害についてはいろんな人がよい記事を書いていますので、「[継承 アンチパターン](https://www.google.co.jp/search?q=%E7%B6%99%E6%89%BF+%E3%82%A2%E3%83%B3%E3%83%81%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)」とか「[inheritance antipattern](https://www.google.co.jp/search?lr=lang_en&hl=en&q=inheritance+antipattern)」でググってください。

次の動画もどうぞ。

- [クソコード動画「共通化の罠」](https://twitter.com/MinoDriven/status/1127539251761909760)

私は、次の記事からヒントを得ています。「下手な抽象化よりも重複のほうがまし」というものです。

- [The Wrong Abstraction — Sandi Metz](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction)

私が体験した範囲では次のようなことがありました（犯人は私であったりします）。

- 先人がよかれと思って作った共通コードを誰も再利用しない。
- 先人がよかれと思って作った共通コードの出来の悪さに苦しめられる。
- 共通コードに次々にifやオプションが生えていき、奇怪なコードになる（上記の動画やThe Wrong Abstractionを参照）。

## コードを共通化したいときは

### サービスクラスを使う

次のように別のクラスに似たような機能を見つけて、コードを共通化したくなったとします。

```Ruby
class Dog
  def save
    # 長大な似たようなコード
  end
end

class Cat
  def save
    # 長大な似たようなコード
  end
end
```

親クラスやモジュールを作るよりも、まずサービスクラスを呼び出す形にすることを考えます。

```Ruby
class Dog
  def save
    serive = AnimalSaver.new(self)
    service.perform
  end
end

class Cat
  def save
    serive = AnimalSaver.new(self)
    service.perform
  end
end
```

クラスメソッドを呼び出す形にしてもよいです。

```Ruby
class Dog
  def save
    AnimalSaver.perform(self)
  end
end
```

### コピペして修正する

その次にChickenクラスを加えるとします。DogやCatでやることとは少しでも違うことがあれば、AnimalSaverにifやオプションを生やすよりも、コピペして新しいクラスを修正することを検討します。

```Ruby
class Chicken
  def save
    serive = ChickenSaver.new(self)
    service.perform
  end
end
```

### 放置する

重複を放置することで可読性や引き継ぎ、改修の容易さが上回るなら、共通化より優先するべきです。

次の例でNamableモジュールが作りたくなったりしたら、こだわり過ぎです（というか、DRY原則について勘違いがある気がします）。

```Ruby
class Client
  def full_name
    "#{family_name} #{given_name}"
  end
end

class Customer
  def full_name
    "#{family_name} #{given_name}"
  end
end
```

## 継承やMix-inを使ってもいい場合

次の場合は、継承やMix-inを使ってもよいです。

- 継承やMix-inを前提としたライブラリを使うとき。Railsのコントローラやモデル、ActiveModel::Modelなど。
- app/helpers 下でのテンプレート用のメソッド。
- どうしても継承やMix-inでないとうまく書けないもの。
- クラスのコードが長大化したのでモジュールに分けるのは、まあ、ありかなあと思うけどどうでしょう。

## 実際にあった例

ここは思い付いたら追加します。

### 不要なインターフェイス

このシステムを引き継いだときにはAnimalはCatしかいませんでしたし、これから増える見込みもありません。実装の予定がない設計は混乱の元です。

```Ruby
module AnimalInterface
  def say
    raise NotImplementedError
  end
end

class Cat
  include AnimalInterface

  def say
    puts "meow"
  end
end
```

### クラス内モジュールの使い回し

これは自分で何度かやってしまいました、すいません。わかりにく過ぎるので、こういうの書いてはいけません。たぶんクラスの組み立てからやり直すべき。

```Ruby
class CatUploader
  # かぶってるからモジュールにしてしまえ！
  module Common
    def s3_key
      "#{Rails.env}/cats/#{cat.id}"
    end
  end

  include Common
end

class CatDownloader
  include CatUploader::Common
end
```

## 思い付いたこと

継承は、言語の入門書には必ず載っているので「使わなければならない機能」のようなイメージがあります。

現実の継承が前提にしているのは、まず設計をして（ドキュメントを作って）、それから開発に取り掛かる、というプロジェクトなんじゃないだろうか。サクッと作って後からガンガン直す、というプロジェクトには不向きなのではと思います。

参考文献:
『Effective Java 第2版』 ジョシュア・ブロック、2001年、P80-90
Raspberry Pi 4 のMACアドレスの範囲が変わったぞ

MACアドレスを頼りに Raspberry Pi 4 をネットワークから探そうとしたときに全然見つからなくて、調べたらMACアドレスの範囲が変わってたのでメモ。

# tl;dr
今までは`B8:27:EB:xx:xx:xx`だったけど、新しく`DC:A6:32:xx:xx:xx`が増えたよ。

# 利用環境

* Raspberry Pi 4 Model B 2GB RAM
    * Raspbian Buster
    * 一度、起動して動作確認済み
* Mac Book Air
    * macOS Mojave

# この記事を書くに至った経緯

新しいWiFi環境に`wpa_supplicant.conf`をSDカードに書き込んでRaspberry Piをネットワークに繋ぎ、ネットワークをスキャンしてIPアドレスを特定しようとした。

そのスキャンするのに`arp-scan`コマンドを使った。

```bash
$ sudo arp-scan -l | grep "b8:27:eb"
Password:
```

だがしかし、Raspberry Piが1台も検出されないではないか。
ホストネームでアクセスできるように設定してあることを思い出したのでSSHを試みたら接続できたではないか。

ログインできたのでおもむろに`ifconfig`を見てみた。

```bash
pi@tomotomopi:~ $ ifconfig wlan0
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.x.x.66  netmask 255.255.252.0  broadcast 172.xx.xx.255
        inet6 xxxx::xxxx:xxxx:xxxx:d9f5  prefixlen 64  scopeid 0x20<link>
        ether dc:a6:32:xx:xx:xx  txqueuelen 1000  (Ethernet)
        RX packets 6034  bytes 738767 (721.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 272  bytes 49504 (48.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

ん？？

`ether dc:a6:32:xx:xx:xx  txqueuelen 1000  (Ethernet)`

MACアドレス変わってね？

ということでRaspberry PiのMACアドレスのレンジを調べてたくてググった結果こちらのサイトに辿り着いた。
https://udger.com/resources/mac-address-vendor-detail?name=raspberry_pi_foundation

Raspberry Pi財団が保持しているMACアドレスのレンジをこのサイトから転載。

| format 1 | format 2 | format 3 |
|:--|:--|:--|
| B8:27:EB:xx:xx:xx | B8-27-EB-xx-xx-xx | B827.EBxx.xxxx |
| DC:A6:32:xx:xx:xx | DC-A6-32-xx-xx-xx | DCA6.32xx.xxxx |

あ、増えてるわ。

```bash
$ sudo arp-scan -l | grep "dc:a6:32"
Password:
172.xx.xx.66	dc:a6:32:xx:xx:xx	(Unknown)
```

:ok: 見つかった！

## IEEEの情報を確認

コメントで指摘いただいたようにIEEEの一次ソースを確認した方がいいですね。
@bsd-hacker さんありがとうございます！

---

IEEEの情報は下記URLから確認できる。

https://standards-oui.ieee.org/oui/oui.txt

こちらはベンダー名やアドレスからフィルターできるので便利だ。
https://regauth.standards.ieee.org/standards-ra-web/pub/view.html#registries

（2022-06-01編集）
"raspberry"でフィルターすると、4種類登録されているのが確認できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14211/1f18dfb7-9fcf-8808-4655-1fc71a6381f7.png)


以上。

# 結論
ネットワークをスキャンしてRaspberry Piを見つけたかったら`B8:27:EB:xx:xx:xx`と`DC:A6:32:xx:xx:xx`のどっちもスキャンすべし。
（2022-06-01追記）
`E4:5F:01:xx:xx:xx`と`28:CD:C1:xx:xx:xx`も増えている。

# 情報求む
新しいMACアドレスのレンジは4以降のモデル専用なのか、Zero, 3など今までのモデルにも混ざってくるのかが不明です。この件について情報持っている人はコメントいただけるとありがたいです！
git初心者向け、Please tell me who you are.という記述が出た時の対処法

<img width="960" alt="SnapCrab_NoName_2020-2-15_15-28-34_No-00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503537/ecabf6ae-9af0-4c0a-b06c-5ca6881a2ec7.png">

分かりづらくて申し訳ないのですが、

```
git commit -m "add hi from hello.html.erb
```

というコマンドがあるのですが、その下にPlease tell me who you are.という記述が出てしまって次に進めないという人がもしかしたらいるのではないかという風に思ったので、解決法を残しておきます。

#エラーの原因
エラーの内容自体や解決方法もすべてPlease tell me who you are.の下にあるっちゃあるんですけどでもやっぱりコマンドの実行に失敗して慌ててエラー文を読まないことってありますよね。

肝心のエラーの原因なのですがgitにあなたのユーザー情報が登録されてないから登録してね。という内容です。

#解決法
エラー文をよく読んでみると

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

という記述があると思います。この文を二つともコピーしてコメントの中身の部分（"で囲まれている部分）を自分の情報に治してあげます。

そしてそれをコマンドに打ち込むことによってうまくいきます。

参考になれば幸いです。
seek難しい

こんなコードを書くとzipファイルがおかしいとなったのでメモ

```
		target, err := ioutil.TempFile("", "zip")
		if err != nil {
			sentry.CaptureException(err)
			log.Fatalln(err)
		}
		w := zip.NewWriter(target)
		defer w.Close()
		for _, client := range clients {
			xlsx, err := run(client.ClientID)
			if err != nil {
				continue
			}
			defer xlsx.Close()
			f, err := w.Create(fmt.Sprintf("%d_item_error.xlsx", client.ClientID))
			if err != nil {
				sentry.CaptureException(err)
				log.Fatalln(err)
			}
			if _, err := xlsx.Seek(0, io.SeekStart); err != nil {
				sentry.CaptureException(err)
				log.Fatalln(err)
			}
			if _, err := io.Copy(f, xlsx); err != nil {
				sentry.CaptureException(err)
				log.Fatalln(err)
			}
		}
		if _, err := target.Seek(0, io.SeekStart); err != nil {
			sentry.CaptureException(err)
			log.Fatalln(err)
		}

		if _, err := internal.Upload(target, "archive.zip", "application/zip"); err != nil {
			sentry.CaptureException(err)
			log.Fatalln(err)
		}
```

何がやりたいかというと、xlsxファイルをクライアントで作って、それをzipにしてs3とかにアップロードしたいコード

これだと、zipが壊れてアップロードされる。

もしかしてFlashされてないのかなと思って

Seekするまに

w.Flashにしても同じ状況に

よくなかった？？ので
defer w.Close()しているところみたいで、
Seekをするまにw.Close()を呼ぶべきみたいでした。

```
		target, err := ioutil.TempFile("", "zip")
		if err != nil {
			sentry.CaptureException(err)
			log.Print(err)
			goto exits
		}
		w := zip.NewWriter(target)

		for _, client := range clients {
			xlsx, err := run(client.ClientID)
			if err != nil {
				continue
			}
			defer xlsx.Close()
			f, err := w.Create(fmt.Sprintf("%d_item_error.xlsx", client.ClientID))
			if err != nil {
				sentry.CaptureException(err)
				log.Print(err)
				goto exits
			}
			if _, err := xlsx.Seek(0, io.SeekStart); err != nil {
				sentry.CaptureException(err)
				log.Print(err)
				goto exits
			}
			if _, err := io.Copy(f, xlsx); err != nil {
				sentry.CaptureException(err)
				log.Print(err)
				goto exits
			}
		}
		w.Close()
		if _, err := target.Seek(0, io.SeekStart); err != nil {
			sentry.CaptureException(err)
			log.Print(err)
			goto exits
		}

		if _, err := internal.Upload(target, "archive.zip", "application/zip"); err != nil {
			sentry.CaptureException(err)
			log.Print(err)
			goto exits
		}
```

とりあえず、deferしてCloseすればいいではなく理解しないとなという。

goto exitsもlog.Fatalでos.Exitになってdeferを呼ばれなくなるので
こうしているどうするのがいいのか。。

Flashは非推奨となっているけど、Flashしても壊れるのもよくわからない感じで。
JavaScript (GoogleAppsScript) の入れ子になっている Object をすべて Map に変換する

#概要
WebAPI などから取得した JSON を JSON.parse() した Object など、値部分にさらに Object が格納されているような場合に、入れ子部分もすべて Map オブジェクトに変換する。
イテラブルなオブジェクトとして処理したい場合に有効。
(GoogleAppsScript では V8 ランタイム使用時のみ可能)

#コード
以下のようなクラスを作成した。

```javascript
class objectToMap {
  
  constructor(obj) {
    
    this.object = obj;
    this.map    = this.objToMapProc(obj);
    
  }
  
  objToMapProc(obj) {
    
    let resMap = new Map();
    
    for (const key in obj) {
      
      const objValue = obj[key];
      const dataType = typeof objValue;
      let setMapArr  = [];
      
      if (dataType === 'object') {
        
        const setMapValue = this.objToMapProc(objValue);
        setMapArr.push(key, setMapValue);
        
      }else{
        
        setMapArr.push(key, objValue);
        
      }
      
      resMap.set(...setMapArr);
      
    }
    
    return resMap;
    
  }
  
}
```

#使用方法
```javascript
function testJsonToMap(){
  
  const json      = '{"test1": "text1", "test2": {"test2_1": "text2"}, "test3": {"test3_1": {"test3_1_1": "text3"}}}';
  const jsonObj   = JSON.parse(json);
  const jsonToMap = new objectToMap(jsonObj);
  const map       = jsonToMap.map;
  
  console.log(map.get('test3').get('test3_1').get('test3_1_1')); //'text3'

}
```
このように、入れ子部分も Map オブジェクトに変換される。
Rails学習コンテンツまとめ

chromeのブックマーク欄が圧迫されてきたので、とりあえずこっちにまとめておこう。
ブックマークフォルダを作ってもいいけど、それじゃ多分見ないんだよなぁ……

###[Railsチュートリアル 演習問題解答集](https://kojimanotech.com/category/%e5%8b%89%e5%bc%b7%e9%96%a2%e9%80%a3/rails%e3%83%81%e3%83%a5%e3%83%bc%e3%83%88%e3%83%aa%e3%82%a2%e3%83%ab/)
###[Ruby on Rails チュートリアル 完全攻略 概要と演習解答総まとめ](http://mochikichi.hatenablog.com/entry/rails_tutorial_guide#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)
Railsチュートリアル各章に出てくる演習問題に対する解答。
***

###[Railsチュートリアル第3章の最終Ver](https://bitbucket.org/railstutorial/sample_app_4th_ed/src/master/)
詰まったときは、これを見ればいいみたい。
***

###[Ruby on Rails ガイド](https://railsguides.jp/)
現状まったく使ってない。このサイトにもRailsチュートリアルを先に
学習してねってあるから、利用するのはまだまだ先だと思う。
***

###[Rails s エラー対処](https://teratail.com/questions/184469)
Rails new後、Railsチュートリアルに載ってる通りにgemfileを書き換えると、
ここと同じようなエラーが必ず出る。
新しいプロジェクトを作る都度、このコマンドを打つのも面倒なんだけど、
良いやり方が分からない。pgのバージョンも都度修正せなあかんの面倒……

```ruby
gem uninstall sqlite3
gem i sqlite3 -v "~> 1.3.6" --platform=ruby
```
***

###[プログラミング言語 Ruby リファレンスマニュアル](https://docs.ruby-lang.org/ja/)
Railsではないけど、せっかくなのでここに載せておく。
***

###[Rubular](https://rubular.com/)
対話的に正規表現を試せるWebサイト
量子統計1 (純粋状態，混合状態， Stokes parateters, POVM , 不確定性原理)

何回かに分けて量子統計の話をする．今回は短く量子力学の基礎だけ．ブラケット記号，純粋状態，混合状態，Stokes parateters, POVM ，不確定性原理(密度作用素版)の簡単な証明など．
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">量子統計1: 何回かに分けて量子統計の話．今回は短く量子力学の基礎だけ．ブラケット記号，純粋状態，混合状態， Stokes parateters, POVM ，シュワルツの不等式を使った不確定性原理の証明など．<a href="https://twitter.com/hashtag/%E6%95%B0%E5%AD%A6?src=hash&amp;ref_src=twsrc%5Etfw">#数学</a> <a href="https://twitter.com/hashtag/%E9%87%8F%E5%AD%90%E6%83%85%E5%A0%B1?src=hash&amp;ref_src=twsrc%5Etfw">#量子情報</a> <a href="https://twitter.com/hashtag/%E7%B5%B1%E8%A8%88?src=hash&amp;ref_src=twsrc%5Etfw">#統計</a> <a href="https://twitter.com/hashtag/%E3%83%96%E3%83%A9%E3%82%B1%E3%83%83%E3%83%88?src=hash&amp;ref_src=twsrc%5Etfw">#ブラケット</a><a href="https://t.co/n9mzGtoG0z">https://t.co/n9mzGtoG0z</a></p>&mdash; Yamagata (@YamagataTwit) <a href="https://twitter.com/YamagataTwit/status/1228563235214741504?ref_src=twsrc%5Etfw">February 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
GitHub Pages と Hugo で運用していた個人サイトを Netlify CMS に移行した

[Netlify CMS](https://www.netlifycms.org/) が良さげという話を同僚から聞いたので、[GitHub Pages](https://pages.github.com/) で公開していた個人サイトと [Hugo](https://gohugo.io/) で構築していたブログをすべてまとめて Netlify CMS に移行したので手順などを書いておきます。

今回移行したサイトはこちらです。
[https://shirokuro331.me/](https://shirokuro331.me/)

ちなみに `shirokuro331` は昔飼っていた猫の名前に数字を組み合わせたものです:cat2:

## Netlify CMS に期待したこと（移行した理由） 

移行前に課題として感じていたことは

- 個人サイト( shirokuro331.github.io )とブログ ( shirokuro331.netlify.com ) でドメインが分かれていたので1つにしたかった
- Hugo だと記事の追加・更新のたびに git コマンド打つ必要があって少し面倒だった（git 操作が苦手というわけではなく記事追加のために git 使う必要性を感じていない）

などがありました。
これらを解決できれば良いなと思っていたところ、 Netlify CMS のことを知って少し触ってみた結果移行することにしました。


## Netlify CMS セットアップからローカルでのデザイン変更までの流れ

手順のメモです。

- Netlify CMSのサイトで `GET STARTED` ボタンを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16642/0c835cac-67cf-3d32-39f0-9890541f26ca.png)

- 遷移先のページで、今回構築するサイトで使うテンプレートを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16642/8fbda84c-e856-9002-13f4-7ac0c9926bd1.png)

- その後は画面の手順に沿って進めていけば netlify にサイトが出来上がり、GitHub にリポジトリが出来上がっています（netlify と GitHub のアカウントが必要です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16642/2a8c7b8b-7eb0-5a26-3e4d-7a8f7f5afc36.png)

- デフォルトのデザインを変更したいので、GitHub からコードを clone します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16642/228eec04-9810-2c96-2799-7bded0ee7245.png)

- terminal.app で clone したディレクトリに移動して、`yarn` か `npm install` を入力する

- その後 `yarn start` か `npm start` を入力すればローカル環境が立ち上って `http://localhost:3000/` が見れるようになるのでデザイン・機能の改修を行なうことができます。デザインの変更は `site/layouts` 内のファイルを編集して行ないました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16642/9e6dbfd8-64b2-c2e7-391c-01740b54efaf.png)

- ローカルでの作業が終わったら GitHub に push すれば、作業内容がサイトに反映されて完成です

## 移行した所感

結論、今のところ困ってることはありません。

Netlify CMS のセットアップは全然手間ではなかったですし、デザイン改修も比較的容易に行なうことができました。無料でビルド・デプロイ・ホスティングができて、独自ドメイン設定も楽な netlify でブログが作れるのはとても魅力的に感じています。

期待していたことのひとつである記事更新用の管理画面は markdown が使えますし、プレビューしながら記事書けるので効率良く作業することができます。

調べきれてはいないですが、インポートの仕組みが無いかもなので大量に記事があるサイトからの移行はもしかしたら困難かもしれません。

総じて良い感じです。
ブログで記事増やせるよう頑張りたいと思います。
Stetho realm 導入

# はじめに
以前[Stetho導入](https://qiita.com/show2214/items/f9391944af875f68fb38)という記事を書いていて、その時はRealmに対応していなかったんですが、業務上導入する必要が出てきたので対応しました。
その時にエラーにハマってしまったのでその対応内容を残しておきます。

# どうやって導入するか
まず[こちら](https://github.com/uPhyca/stetho-realm)がライブラリ。
Stethoとは別線です。
こちらのREADMEに従っていけばとりあえず導入は可能です。

# 何でハマったか
アプリの起動はできるのですが、Realmを見ようとするとアプリがExceptionを吐いてしまうという現象が起きていました。悲しい。

# その時の実装
App.ktのonCreate()で以下のように修正しました。(GithubのREADMEそのまま)

```kotlin
        Stetho.initialize(
                Stetho.newInitializerBuilder(this)
                        .enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
                        .enableWebKitInspector(RealmInspectorModulesProvider.builder(this).build())
                        .build())
```

# どう直したか
RealmInspectorModulesProviderをbuild()する際にオプションを追加する必要がありました。
また、build.gradleのrepositoriesに追加するURLがGithubのissueの中で違うものが挙がっていたのでそちらに変えました。

```gradle
allprojects {
    repositories {
        maven { url 'https://github.com/mak0t0san/stetho-realm/raw/master/maven-repo' }
    }
}

implementation 'com.uphyca:stetho_realm:2.3.0'
```

```kotlin
        Stetho.initialize(
                Stetho.newInitializerBuilder(this)
                        .enableDumpapp(Stetho.defaultDumperPluginsProvider(this))
                        .enableWebKitInspector(RealmInspectorModulesProvider.builder(this).withDeleteIfMigrationNeeded(true).build())
                        .build())
```

# 終わりに
今回とりあえずこれで動くようになりました。
しかしstetho_realmは2017年から更新がかかっていないようなので、別のライブラリなんかを探すか、あるいは自分で作るかしないといけなさそうですね。
また、小規模なDBであればよいのですが、数十万件のレコードがあるようなものの場合そもそも開けない、なんてこともあったりするので要注意です。
今のPJの場合数十万件のレコードを見たい、という状況だったのでないよりはマシ、くらいの状態になっていますし、仮に見れたとしても検索(select)ができないので探すのも一苦労です。
おとなしくRealmが出しているRealm Studioを購入（あるいは30日間の無料期間）で対応するか、Realm Browserを使うか、でしょうかね。
(一昔前は`brew cask install realm-browser`でインストールできたようですが、今はbrew searchしても出てこないのでHomeBrew Caskからはなくなってしまったようです)

# 参考
[stetho_realm issue](https://github.com/uPhyca/stetho-realm/issues/62)
[Realm Studio](https://realm.io/jp/products/realm-studio/)
[Realm Browser(AppStore)](https://apps.apple.com/jp/app/realm-browser/id1007457278?mt=12)
CentOS 6.x  ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib? 対策

##要旨
CentOS 6.x系でpyenvでPython 3.7異常をインストールしようとすると、エラーが起きてインストールできない場合の対応。
ちょっと危なっかしいので実際に行う時はテストサーバーなどで十分に検証してください。

##事前確認
```
# yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel -y
# pyenv install -v 3.7.1


ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
```

##原因と対策
OpenSSLのバージョンが1.0系だと起きるっぽい。yum でインストールしても 1.0系以上は入らないため、1.1.1をソースからデフォルトの場所以外にインストールするという手を使う。
/usr/local/openssl-1.1.1にインストール

##OpenSSL 1.1.1のインストールと設定
```
# curl https://www.openssl.org/source/openssl-1.1.1.tar.gz -o /usr/local/src/openssl-1.1.1.tar.gz
# cd /usr/local/src/
# tar xvzf openssl-1.1.1.tar.gz
# cd openssl-1.1.1
# ./config --prefix=/usr/local/openssl-1.1.1 shared zlib
# make
# make install
```

/etc/ld.so.conf.d/にファイルを作成して、「/usr/local/openssl-1.1.1/lib/」と記述、反映

```
# vi /etc/ld.so.conf.d/openssl-1.1.1.conf
# ldconfig
```

確認

```
# /usr/local/openssl-1.1.1/bin/openssl ciphers -v TLSv1.3
TLS_AES_256_GCM_SHA384  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any      Au=any  Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256  TLSv1.3 Kx=any      Au=any  Enc=AESGCM(128) Mac=AEAD
```


## インストール
CONFIGURE_OPTSでconfigure時のオプションと同じ指定ができる

```
# CONFIGURE_OPTS="--with-openssl=/usr/local/openssl-1.1.1/" pyenv install -v 3.8.0
```

## ついでに
ちょっとしたPythonの実行なら環境を整備しなくても
google colab notebook で実行できます。
https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

TA-Libのインストールまでできます。

```
!wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
!tar -xzvf ta-lib-0.4.0-src.tar.gz
%cd ta-lib
!./configure --prefix=/usr
!make
!make install
!pip install Ta-Lib
import talib
```
自動生成したSandBoxテスターを自動削除する

先日の[potatotips#68](https://potatotips.connpass.com/event/160125/)で発表した「[SandBox Tester Tips](https://speakerdeck.com/funzin/sandbox-tester-tips)」の続きです。
今回の記事を見る前に、こちらの[SandBoxテスターの作成数の上限について](https://qiita.com/funzin/items/3b9ef23a2bec1a639bf0)も見ていただけるとやりたいことがよりイメージしやすいかと思います

## 忙しい人向け要約
「[SandBox Tester Tips](https://speakerdeck.com/funzin/sandbox-tester-tips)」の要約

- fastlaneのspaceshipによって、SandBoxテスターを生成
- BitriseなどのCIでアプリの配布時に、SandBoxテスターも自動生成
- 自動生成の重複を回避するため、メールアドレスは**日付**やCIのビルド番号を利用

[SandBoxテスターの作成数の上限について](https://qiita.com/funzin/items/3b9ef23a2bec1a639bf0)の要約

- 明確に上限数があるのかわからないが、SandBoxテスターを作りすぎるのにメリットはない

## やりたいこと
[SandBoxテスターの作成数の上限について](https://qiita.com/funzin/items/3b9ef23a2bec1a639bf0)で検証したようにむやみにSandBoxテスターを自動生成をしつづけるのは良くないことがわかったので、どこかしらでSandBoxテスターを削除する必要が出てきました。

## 削除方針
SandBoxテスターの生成は自動なのに削除は手動という状態は避けたかったので、**メールアドレスに日付を含め**以下のような方針で削除を行うことを考えました。

1. fastlaneのspaceshipでSandBoxテスターの一覧を取得
2. 自動生成したSandBoxテスターのメールアドレスに日付が含まれているので、ある日よりも○日前に作成されたSandBoxテスターを抽出
3. 抽出したSandBoxテスターを削除

### 自動削除のタイミング
あとはどのタイミングでSandBoxテスターの削除を実行するかです。

そんなに頻繁に削除をする必要性は感じなかったので、[Bitriseのスケジューリング](https://devcenter.bitrise.io/jp/builds/Scheduling-Builds/)を利用して、週1単位で削除を行う`fastlane action`を実行するようにしました。

## サンプルコード
メールアドレスの形式例: `日付-CIビルド番号-index@test.com`

e.g. 

```
20200212-1111-1@test.com
20200212-1111-2@test.com
20200212-1111-3@test.com
.
.
.
20200212-1111-3@test.com
```

Fastfileのサンプル

```rb
require 'date'
require 'spaceship'

platform :ios do
  desc "1週間前よりも前に自動作成したSandboxテスターを削除する"
  lane :remove_old_sandbox_testers do
    username = "username" # you should change to your username
    password = "password" # you should change to your password

    Spaceship::Tunes.login(username, password)

    all_sandbox_testers = Spaceship::Tunes::SandboxTester.all
    old_sandbox_testers = all_sandbox_testers.filter {|sandbox_tester|

      # 自動作成したSandBoxテスターは日付がprefixになっているので抽出
      created_date_str = sandbox_tester.email.split("-").first
      if /^\d{4}\d{1,2}\d{1,2}$/.match(created_date_str) != nil then
        created_date = Date.strptime(created_date_str,'%Y%m%d')

        deletion_criteria_date = Date.today - 7
        if created_date < deletion_criteria_date then
          next(true)
        else
          next(false)
        end
      end

      next(false)
    }

    # 削除対象のSandBoxテスターが含まれる場合
    if !old_sandbox_testers.empty? then
      emails = old_sandbox_testers.map {|sandbox_tester| sandbox_tester.email }
      Spaceship::Tunes::SandboxTester.delete!(emails)
    end
  end
end
```

実行例

```sh
$ fastlane remove_old_sandbox_testers
```
このactionを実行することで、実行日よりも7日前のユーザーを削除するということが自動化されます。


## まとめ
- SandBoxテスターの生成・削除を自動化することで手作業で行っていたSandBoxテスターからの解放
- なかなかSandBoxテスターに関連する情報がなかったので参考にしていただけるとうれしいです

## 関連URL
- https://devcenter.bitrise.io/jp/builds/Scheduling-Builds/
- [SandBox Tester Tips](https://speakerdeck.com/funzin/sandbox-tester-tips)
- [SandBoxテスターの作成数の上限について](https://qiita.com/funzin/items/3b9ef23a2bec1a639bf0)
なぜ秘匿データをKeychainへ保存する必要があるのか

記事の内容はこちらを参照してください。
https://mishimay.github.io/9e12760a28f69024dcfa/
<!--

iPhoneはパスコードを設定するとiPhone内のデータが暗号化される[^1]。
パスコードが設定されていない状態でも秘匿データをセキュアに保つためにKeychainへ保存する必要がある。

[^1]: https://support.apple.com/ja-jp/guide/iphone/iph14a867ae/ios






-->
AndroidでOpenCVを使ってみる

# TL;DR
Android StudioでOpenCV SDKを使ったアプリの作り方.

# 環境
- OpenCV 4.2.0
- Android Studio 3.5.3
- macOS Catalina 10.15.3 
- kotlin

# 事前準備

- 新規プロジェクト作成
Android Studioで空のアプリを作成しておく.

- OpenCVのダウンロード
[OpenCVのリリースサイト](https://github.com/opencv/opencv/releases) からandroid版のSDKをダウンロードし適当な場所に解凍しておく.
今回は opencv-4.2.0-android-sdk.zip を使用.


# 実装

### OpenCVの取り込み

- OpenCVを組み込みたいプロジェクトをAndroid Studioで開く.
- メニューの `File` -> `New` -> `Import Module` を選択.
- 事前に解凍して置いた OpenCV SDK の `sdk` フォルダを指定してインポート.
Module nameはデフォルトだと `sdk` になるので `opencv-sdk` とかにしてもよいかも.

### モジュールの依存関係を追加
アプリ側の `build.gradle` の dependencies に sdk を追加.

``` gradle:build.gradle
dependencies {
  implementation project(path: ':sdk')
  ...
```

### カメラパーミッションを追加
アプリの `AndroidManifest.xml` にカメラパーミッションを追加.

``` xml:AndroidManifest.xml
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" android:required="false" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
```
`Activity`/`Fragment`にもパーミッション取得の処理を書いておく.

### 画面レイアウト作成

ActivityのレイアウトXMLにカメラビューを追加.

``` xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <org.opencv.android.JavaCameraView
        android:id="@+id/camera_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:show_fps="true" />

</androidx.constraintlayout.widget.ConstraintLayout>
```
### コードを書く

Activityにコードを追加.
`setCameraPermissionGranted()`を忘れないように注意.

``` kotlin:MainActivity.kt
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        OpenCVLoader.initDebug()  // ← OpenCVライブラリ読込
        initCamera()
    }

    fun initCamera() {
        // リスナ設定 
        camera_view.setCvCameraViewListener(object : CameraBridgeViewBase.CvCameraViewListener2 {
            override fun onCameraViewStarted(width: Int, height: Int) { }

            override fun onCameraViewStopped() { }

            override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame?): Mat {
                // このメソッド内で画像処理. 今回はポジネガ反転.
                val mat = requireNotNull(inputFrame).rgba()
                Core.bitwise_not(mat, mat)
                return mat
            }
        })

        // プレビューを有効にする
        camera_view.setCameraPermissionGranted()
        camera_view.enableView()
    }
```

# 実行結果
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64106/62d2a6fb-6f27-bcbb-b111-808b6042f976.png" />
プログラミング学習を始めて考えるようになったこと

<h3>一日の時間の使い方</h3>

プログラミングを学習し始めていくうちに如何に早く上達するかを考えていたら、
時間の事ばかり気にし始めました。
つまり仕事の時間と睡眠時間と家事の時間とプログラミング学習時間の比率(遊ぶ時間が欲しい；；)を
どうするかという事を考えていました。
仕事の時間はできるだけ定時で帰るようにするとか、
家事の時間は最小限で済ませるとか、(食事のバランスと部屋の掃除はちゃんとしましょう＼(^^)／)
なんですが、睡眠時間が一番制御が難しいと個人的には思っています。
あまり睡眠時間を削ると集中力、記憶力がゴミになって学習効率が悪くなるのは
わかっているんですが、一日の時間の中では、どうしても削ってしまいがちなものに
なってしまうような気がします。

また時間があり過ぎて逆にダラダラしてしまうということもありそうなので
結局23時ぐらいに寝て6時に起きる、みたいな完全固定して限られた時間で
しっかりやる...というような王道パターンが一番いいと改めて感じました。

プログラミングを学習する前まではなんとなくダラダラしてて時間の使い方が、
正直下手だったなと思います。

それに折角時間をかけてやるなら、効率よくやらないと悔しい；；というのもあるので
これからもしっかり生活習慣に気をつけながら、
プログラミング学習を頑張っていきたいと思います(｀・∀・´)
プロジェクト名を後から変更する手順

# プロジェクト名を後から変更する手順

Xcodeが一気に置換してくれると嬉しいのですが、手作業が必要なので、手順を以下にメモします。

1. Xcodeを開き、プロジェクトを選択。File inspectorの名前を新しい名前に変更する。
2. スキーム名の変更をするため、スキーム編集画面からスキーム名を選択し、新しい名前に書き換える。名前をクリックして待っていると編集できる状態になる。
3. Xcodeを再起動し、フォルダ名を手順1と同じ要領で変更していく。Locationのパスが正しいか注意する。なお、git mv 旧名称 新名称を実行すると、gitがファイル名変更を認識できるようになる。
4. ターゲットのBuild Settingのplist指定のパスを書き換える。同様に、Product Bundle Identifierのパスも書き換える。



# 参考
https://stackoverflow.com/questions/33370175/how-do-i-completely-rename-an-xcode-project-i-e-inclusive-of-folders
AWS試験対策（⑤コンピューティングとストレージ続々々）

自分用雑記
コンテナから続き書いていきます〜

## ECS、EKS、fargate
まず、コンテナって何じゃって話。
コンテナは仮想化技術の一つ。SaaSとかと何が違うのかと言うと、リソースが少なくて済む代わりにOSはその元となるOSでしか作れない。Windows上でコンテナ作ったらWindowsのみ、みたいな感じらしい。SaaSなら基盤の上にLinuxでも何でも入れれるから決定的な違い。
要するに何がしたいのかというと、仮想的な環境をいくつか作って、そこでアプリケーションを動かす、みたいな感じ。

データプレーン
実行環境のこと。Windows上でコンテナを作ったら、ってとこの、大元のWindowsのこと。この上にコンテナが乗るイメージ

コントロールプレーン
コンテナを管理する奴ら。コンテナをどのデータプレーンのosで動作させるのかとか、コンテナの死活監視とかしてくれる。オーケストレーションサービスってだけあって、指揮者的なイメージ。

レジストリ
コンテナのイメージの置き場。必要に応じてデータプレーンにコンテナを配置する。

## EKS、ECSの違い
AWS純正のコンテナ管理システムがECS。
変わって、オープンソースのKubernetesのコンテナ管理システムがEKS。
どちらもEC2をデータプレーン、つまり実行環境にできる。
ECSはさらに、fargateを実行環境にできる。
fargateとは、わざわざインスタンス作らなくても実行環境提供してくれるシステム。これのおかげでインスタンスを準備、設定、調整する必要がない。
レジストリサービスはどちらもECRというサービスを使う。

使い分けとしては、サーバーの管理をなるべくしたくないならECSのfargateを。
すでに既存のシステムでKubernetesを使ってるならEKSとEC2を使う。

試験ではあまり重要視されてないけどこれから使っていきたい領域。

## Lambda
ラムダって読むらしい。最初読めないの恥ずかしすぎてググった。
これも覚えて使っていきたい。個人的に名前が好き。

サーバを構築しなくてもコード実行できるサービス。
他のイベントを起因に色々行ってくれるため、S3などとの連携が容易。イベントドリブンっていうらしい。
イベントの量などに応じて自動的にサーバを大きくしたり小さくしたり、スケールしてくれる。
実際はコンテナ内で実行され、アプリが稼働しただけ課金される。何がいいかってコスト効率がいい。
普段からサーバを用意しておいてリクエスト待ちだと、使ってないときもサーバは時間単位で料金請求がくるけど、Lambdaなら使ったときだけ。だから、たまーにしか来ない処理とかに向いてる。
請求はリクエスト数と処理料で計算される。

しかし、実行の時間上限が15分なので、大量のデータ処理はできない…

対応言語は様々でrubyとかjavaとかたくさんあります（適当）

Lambda Custom Runtimesを使うことでAWSパートナーが提供する言語も使える。

AWS step functionで、いくつかのステップで構成されるアプリをLambda関数を組み合わせて構築できるらしい。何言ってるかわからない。笑笑

## API Gateway
ウェブからのHTTPでのリクエストをLambdaで処理したいとき、間にこれを挟まないと行けない。
S3とかではこれを挟む必要はない。

## storage Gateway
簡単に言うならオンプレのストレージとS3の仲介役。
オンプレのストレージから、S3に保存することができる。

ファイルゲートウェイ
オンプレのファイルシステムのバックエンドストレージにS3を利用
ファイルをオンプレとS3で共有するために利用

テープゲートウェイ
仮想テープライブラリ対応のバックアップソフトを使って、S3に保存
オンプレのバックアップをS3に保存するために利用

保管型ボリュームゲートウェイ
オンプレのデータのコピーをS3に保存。つまりそれをEBSに復元することも可能。
データのプライマリコピー自体はオンプレに保管されてるから保管型。

キャッシュ型ボリュームゲートウェイ
オンプレのデータのコピーをS3に保存。プライマリコピーもS3に。オンプレではよく使うデータのキャッシュのみ存在させるからキャッシュ型。

## EFS
EBSの浮気野郎。異なるAZからもアクセスできるし、複数のインスタンスからアクセスできる。尻軽。
うそですべんりですごめんなさい
EBS使わずにこっち使えばよくねとか思っちゃいますね

コンピューティングとストレージは以上、次回からはセキュリティと、ネットワークへ。