OmniAICreator/Qiita-1.07M huggingface dataset:
serverless artilleryでサーバレスに負荷テスト

# Links
- [Nordstrom/serverless-artillery: Combine serverless with artillery and you get serverless-artillery for instant, cheap, and easy performance testing at scale.](https://github.com/Nordstrom/serverless-artillery)

# 環境
serverless artillery 0.5.2
Serverless Framework 1.82.0
npm 6.13.4

※注意：2020/12/19現在Serverless Frameworkが最新だとserverless artillery動作せず

# 実行手順

## インストール
```sh
$ npm install -g serverless-artillery
```

## ディレクトリと設定ファイルの作成
```sh
$ mkdir my-test && cd $_

# 設定用ファイルの作成
$ slsart configure
$ touch script.yml
```

## ファイルの編集
serverless.yml

- regionsの設定を追記（デフォルトだと`us-east-1`）
- LambdaにVPCを紐付ける場合はvpc設定も追記

```
provider:
  name: aws
  region: ap-northeast-1
  vpc:
    securityGroupIDs:
      - xxxxx
    subnetIDs:
      - xxxxx
```
 
script.yml

- URLやpayloadなどを追加
- 参考：[Testing HTTP - Artillery.io Docs](https://artillery.io/docs/http-reference/)

```
config:
  target: "http://api-host"
  phases:
    - 
      duration: 30
      arrivalRate: 3
scenarios:
  -
    flow:
      -
        post:
          url: "/sample"
          headers:
            Content-Type: "application/json"
          json:
            Name: "User Taro"
            Age: 20
            ...
```

※注意：`Content-Type`ヘッダを設定しているが、実際に実行するとヘッダ名が`content-type`と小文字になるので、処理に影響する場合は対策が必要

## デプロイとテストの実行

- `~/.aws/credentials`の設定は事前にしておく

```sh
$ AWS_PROFILE=your-profile slsart deploy --stage test
$ AWS_PROFILE=your-profile slsart invoke --stage test
```

※注意：VPC Endpoint経由でAPIを叩く場合、Lambdaからローカルに結果が返ってこないので、CloudWatch Logsを確認する必要がある（回避方法あるかも？）

## リソースの削除

```sh
$ AWS_PROFILE=your-profile slsart remove --stage test1
```
mampでmysql_updrade: got error: 1045

#mampでmysql_upgrade: Got error: 1045: Access denied for user 'root'@'localhost' (using password: YES) while connecting to the MySQL server Upgrade process encountered error and will not continue.

パスワードを初期設定のrootから変更して使っています。
様々なサイトを検索すると、変更すべき箇所を変更していなかったのでこのようなエラーが出てしまったようです。

/Applications/MAMP/bin/checkMysql.sh
/Applications/MAMP/bin/quickCheckMysqlUpgrade.sh
/Applications/MAMP/bin/repairMysql.sh

これらのファイルの

```
 -proot
```
を

```
 -pmypassword
```
と変更するとエラーが出なくなりました。
Googleスプレッドシートによる個人金融投資用ダッシュボード

# 資産運用の可視化
外貨、株式、投資信託等の資産運用をされている皆様、どのように自分の投資先商品やその候補の状態を可視化されていますか？
アカウントアグリゲーション・サービスも便利になりましたが、どちらかというと家計管理向きのものが多く、投資の管理としては痒いところに手が届かない場合もあると思います。
Googleスプレッドシートを使うと、スクレイピングが簡単に実装出来、ちょっとした個人投資ポータルが作れます。（作成イメージは下の画像）
本当はそのまま使えるサンプルコードをお見せしたいところですが、万が一、結果的に特定のサイトへのサーバー負荷増大に関わると、法令順守上の問題となりうるので、本ブログのサンプルコードは、URLは伏せ、架空のHTMLの構造で書かせていただきます。読者の皆様の好みのソースサイトで試す時の叩き台としてご参考になれば幸いです。
また、スクレイピングを利用規約で禁止しているサイトもありますので、ご注意下さい。
![投資管理ダッシュボード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608886/fec6ab3e-7307-0b73-8dad-8b69ccf00099.jpeg)


# スクレイピング関数
Googleスプレッドシートには、XPathで簡単にスクレイピングが出来るIMPORTXMLという関数があり、IMPORTXML(URL, XPathクエリ)という書式です。
金融情報サイトから何らかの時価データを取得する時のイメージは、以下の通りです。
`=IMPORTXML("https://xxxxxxxxxx/xxxx/xxxx","//span[@class='price']")`

#XPathクエリの記述
IMPORTXMLの1つ目の引数は取得したいデータが含まれるURLです。
問題は2つ目の引数のXPathの記述方法で、これにクセがあり、正しいはずと思ったXPathを書いてもエラーが出ることがあります。
ここではIMPORTXML関数の仕様やXPathの概念の厳密な話は避け、いくつかのWebサイトでの経験上、「とりあえず通ることの多い」書き方をご紹介します。

XPathとは、WebサイトのソースのHTMLやXMLの中から、特定の構成要素を指定するための構文です。前述の例では、1つ目の引数のURL`"https://xxxxxxxxxx/xxxx/xxxx"`の中で、取り出したい価格情報等が記載されている箇所を`"//span[@class='price']"`という記述で指定しています。

このようなXPathを得るには、次の手順で取得したい箇所のHTMLソースを特定します。

1. ChromeブラウザでスクレイピングしたいWebサイトのページ`https://xxxxxxxxxx/xxxx/xxxx`を開きます。
2. ページ中のスクレイピングしたい箇所をドラッグします。
3. 右クリックメニューで「検証」を選ぶと、窓の右上にHTMLソースが表示され、例えばUSD/JPYの為替レートの情報ページで103.38というデータをドラッグしている時、`<span class="price">103.38</span>`といったようなHTMLの該当部分が水色にハイライトされます。これがドラッグした箇所のHTML記述です。

ちなみに、この水色にハイライトされた部分を右クリックすると、Copy->Copy XPathというメニューがあり、XPathを取得出来ます。しかし、これをこのままIMPORTXMLの引数で使うとエラーとなる場合が多く、上手く行かない感じです。これが先ほど申し上げたこの関数の"クセ"です。

IMPORTXML関数の引数としてのXPathの記述方法として現時点の私なりの現実解が、上記の`"//span[@class='price']"`をテンプレートにすることです。
このXPathの意味は、"//"が対象URLのHTMLの全要素から探索することを表し、spanタグのうち、class='price'という属性を持ったものを探すということです。
これにより、上記の`<span class="price">103.38</span>`に辿り着くことが出来ます。
上記では探索の対象がspanタグで、class属性がキーとなり、その値が"price"であるものを探索する場合を例に示しましたが、タグの種類、キーとなる属性の種類や値はサイトやページ毎に異なり、spanタグのところは例えばdivタグやtdタグ、class属性のところは例えばid属性となる場合があり、探索するHTMLに合わせて置き換えることで様々なWebサイトに適用出来ます。（`<span class="price">103.38</span>`という記述は、特定のサイトからの引用ではなく、金融情報サイトでありそうな仮想のものです。）

# 書式設定と文字列処理
IMPORTXML関数で取ってきたデータが、例えば文字列"103.38円"といった具合に、数値型ではなく、文字列型でかつ余計な文字列を含んでいる場合もあります。このような場合、下記のように、SUBSTITUTE関数で余計な文字列を除去した後、VALUE関数で数値型に変換し、数値データとして使えるようにします。
`=VALUE(SUBSTITUTE(IMPORTXML("https://xxxxxxxxxx/xxxx/xxxx","//span[@class='price']"), "円", "", 1))`

# おわりに
IMPORTXML関数は、サイトやページによって上手くいくところと、いかないところがあり、上手く行くところでも時々実行失敗が発生するなど、非機能面での使いにくさはありますが、個人レベルでのWebスクレイピングによる情報収集のハードルを下げてくれたことは画期的に感じました。

※当ブログは、特定の銘柄・商品等の勧誘や売買の推奨等を目的としたものではありません。
[OCI] ロードバランサにSSL証明書を設定しHTTPS通信を試してみた

構成済みの OCI ロードバランサに無償のSSL証明書を追加し https 通信ができるか試してみます。

## 準備
### SSL証明書を入手

Let's Encrypt で無料SSL証明書を使います。入手の手順については巻末の参考資料をご覧ください。ここでは入手時のトピックのみ記載します。
- certbotツールのパラメータ --domain にドメイン（例) lb.cocotaro.com）を指定
- TXTレコードの設定はDNSゾーンの画面から手動でおこないました。
![image-20201218155359219.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/368eac5e-acb0-d27c-3858-ce747233b372.png)
- 生成された４つのpemファイルから、今回は次の２つを使います。
  - **cert.pem**         **SSL/TLS サーバ証明書 (公開鍵を含む)**
  - **privkey.pem**   **秘密鍵**

### お試しの構成

- ２つのWebアプリのフロントにロードバランサがあり、ブラウザからのリクエストをHTTP 80番ポートで受けてます。
- ブラウザからリクエスト（例) lb.cocotaro.com）するとロードバランサでラウンドロビンされ２つのWebアプリで交互に処理されます。
- ブラウザにはリクエストを処理したサーバーの名前(osaka01 or osaka02)が表示されます。
![image-20201218155706733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/a7ddb08b-6848-c852-abee-455cbbd1ee1d.png)
- 現状だとブラウザとロードバランサ間は単に HTTP通信なので、悪意のあるユーザーにパスワードやクレジットカード番号などの機密情報を盗まれる可能性があります。
- そのためロードバランサにSSL証明書を設定し、ブラウザとロードバランサ間でHTTPS通信の暗号化をおこないます。安全な通信経路を確保し機密情報の解読を困難にします。



## ロードバランサの設定

### 1. SSL証明書を追加

入手した SSL証明書と秘密鍵を設定します。構成済みのロードバランサを選択し、画面左のリソース から**証明書**をクリックし、**[証明書の追加]** でSSL証明書を設定します。
![image-20201218161721498.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/e5561111-e711-8537-2f94-c6208ebef101.png)
**[証明書名]** 任意の名前を入力
**SSL証明書**
**SSL証明書ファイルの選択** を選択し、 **cert.pem（SSL証明書）**を指定
**秘密キーの指定** をチェックし、
**秘密キー・ファイルの選択** を選択し、**privkey.pem（秘密し ）** を指定
上記設定後、**証明書の追加** をクリックし、証明書が追加されました。
![image-20201218164621209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/31dbe698-15a2-dfea-6fbe-118763ef346f.png)
### 2. リスナーの変更
続いて、リスナーを設定してSSLの使用を有効化します。画面左のリソース から**リスナー**をクリックし、既存のリスナーを選択し編集します。
![image-20201218164838673.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/f6e18fb4-1d61-7b6b-a959-840dd2eb1cb2.png)
**SSLの使用** をチェックし、ポート443 であること、
**[証明書名]** が先の**証明書の追加（例 lb-ssl-cert）**で入力した名前になっていることを確認し、
**リスナーの更新** をクリックし、リスナーでSSLを使えるようにします。
![image-20201218170200399.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/532bf367-70be-c41b-8915-5f032c464ca1.png)
### 3. セキュリティリストにポート追加

最後にセキュリティリストのイングレス・ルールに80ポートに加えて、443ポートの許可を追加します。こちらの設定も忘れずに！！
![image-20201218170436058.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/9e404deb-839d-cc27-6d09-004c6098b135.png)


## 動作確認

それではブラウザからロードバランサへリクエスト（例) https://lb.cocotaro.com）します。ブラウザは Google Chrome を使用
![image-20201218181620092.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/8174b538-4314-fa18-76f0-300a1e7bcc71.png)

HTTPSでの動作が正常に処理されており、ブラウザのURL表示部に鍵マークが表示されました。鍵マークをクリックするとセキュアな接続が行われている旨のメッセージが表示され、証明書が有効になっていることが確認できました。
![image-20201218181942337.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496842/f9597e56-75f8-d5b3-2a8d-c0def456ce5c.png)

## 参考URL

[Oracle Cloud LoadBalancer を Let's Encrypt で無料SSL化](https://qiita.com/sugimount/items/3f43c55141252f8f2968)
新しいことにトライするために必要なこと with コーチング

今年も残り少なくなりました。
今年、新しい言語を学びたい、違うレイヤーの技術を試したみたいなど目標は立てたものの、出来なかったという人もいるかと思います。

ここ数年、スクラムマスターやエンジニアリングマネージャーということもありコーチングを学び実践しながらコーチングの資格なども取得したりしました。

コーチングは
`相手の目標達成に必要な知識、スキル、ツールが何であるかを棚卸しし、それを個別対応で相手に備えさせるプロセスとなります`
つまり、
`目標達成に向けた自発的行動/自律的行動を促進するコミュニケーション`
のことをいいます。**ティーチングやカウンセリングとは違います。**
![success-5597527_1920.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116899/dd78e32e-dd49-80a5-e67e-622d5528d2ae.png)


コーチングを実施する中で、**ファウンデーションを整える**という点を心掛けています。新しいことにトライすることにつながる重要な要素となります。今回こちらを紹介します。

何か新しいことを始めようとすると多くのエネルギーが必要になるかと思います。
一方で日々、ほんの些細なことがエネルギーを消耗させていきます。

なので、新しいことをするためには、このエネルギーを蓄えて
目標に向けて進み続けるためにファウンデーションを整える必要があります。

では、このファウンデーションって何？

新しい行動を起こすには、その原動力となるエネルギーが必要です。
それは基礎体力に近いかと思います。
意欲があっても基礎体力がないときは、動くのは厳しいですよね。
**この基礎体力にあたるのが、ファウンデーション＝自己基盤です。**

コーチングは目標達成にむけ、相手が新たな行動を起こすために行います。
そのため相手に十分なスキルや知識が備わっているにもかかわらず、何らかの理由で目標達成が妨げれれる場合があります。

ファウンデーションを整え強化するための一例として以下の二つがあります。

**1.エネルギーマネジメントとしての未完了の完了**
**2.エネルギーマネジメントとしてのタイムマネジメント**

今回は1を紹介します。

1.未完了を完了し、エネルギーを蓄える

未完了というのは以下のようなものです・
* やろうと思っていながらやっていないこと
* 止めようと思っていながら止めていないこと
* 過去の出来事の中で、何か引っかかっていること

このような未完了を抱えると、無意識のうちに気にしていたり、いつものそのことが頭のどこかで引っかかっていて
頭を使っていて、気が付くと疲弊している状況になります。
一つ一つは大したことないのですが、むしろそうであればあるほど、ふと思い出したりして、エネルギーを消耗しています。
そのため、ちっちゃなことでも未完了を完了に変えるとエネルギーを蓄えることができます。

ちっちゃなことは、仕事だけでなく、机のまわりを整理したいとか、スマホのカバーを変えたいとかそんなことも当てはまります。

未完了を完了に変えると以下を手に入れることができます。
・無駄なエネルギーロスを防ぐことで、エネルギーレベルをあげることができる。
・達成感、爽快感、創造性、自信など目標達成への原動力になる体験を得られる

具体的には
1.時間ができる
2.問題から解放される
3.チャンスを手にする


上記を手にいれるステップとして

####まずは、未完了リストを作成してみましょう

項目は3つ
**1.未完了の項目**
**2.完了時に得られること**
**3.終わったかどうか**

| 未完了の項目 | 完了時に得られること | 完了チェック |
|:-:|:-:|:-:|
|   |   |   |
|   |   |   |
|   |   |   |

この完了時に得られることに**感情**もいれておくとよいですね。
完了した時のことを想像してどんな状況かどんな気持ちかをはっきりさせておくことで
実施するエネルギーにも変わります。
なんとなく忙しい
あれもやらなきゃ　って気分がつづくときは、見えないタスクに疲弊していることがります。

####取り組みポイントは以下です。

1.まずは、自分にとって比較的取り組みやすい課題から始める
2.未完了を完了させるための協力者をつくる
3.達成感を得る仕組みをつくる
4.なぜ未完了を完了させるのか、その目的を意識する
5.やらないことも完了とする

ぜひ、今年やりたかったこと、もしくは来年の目標に向けてファウンデーションを整えてみてください。
![hiking-1031628_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116899/28cd00da-2a50-3d7e-9142-d74fef770db1.jpeg)
ハードウェア、ソフトウェア、OS、Linuxをゲーム機で例えてみた

# ハードウェアとは?
ゲーム機で例えるならゲーム機本体やコントローラーといった目に見えるもの。
これらだけではゲームは遊べないのと同様にPCもソフトウェアがないとただの箱です
(最近のゲーム機はオンライン通信なら無料で色々遊べちゃいますがそこは置いときます)


# ソフトウェアとは
ゲーム機で例えるならゲームソフト(カセット)の中身。
PCを動かすプログラム(指示)のことです。
PC自体や周辺機器などのように目に見える機器をハードウェアと呼ぶのに対し、ソフトウェアは目で見ることができません。
ハードウェアとソフトウェアが揃って初めてPCとして色々作業ができます。

# OSとは?
PCを動かすために提供してるソフトウェア。
ゲーム機で例えるならどうぶつの森やスプラトゥーンなどのゲームソフト。
代表的なものはPCではWindows、MacOS、Linuxの3種類です。
スマホではiOSとAndroidの2種類です。
WindowsとMacで操作する画面が違うのはどうぶつの森とスプラトゥーンで操作する画面が違うのと同じです。

# イメージ図
![スクリーンショット 2020-12-17 21.13.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/cbdbc00e-b0a1-b13f-bb60-5485782f72a7.png)


# LinuxもOSの1つ
OSと聞くとWindows or Macと思われがちですがLinuxもOSの1つです。
ただWindowsやMacと違いLinuxをインストールしてもPCの機能はありません。
なぜならLinuxは自分で色々コマンドとか打って設定しないといけないからです。
ゲーム機で例えるなら中身のないゲームソフトと思ってください。

# Linux使う理由は？
ここで全部自分で設定しなくちゃいけないの？使う人いる？と思うかもしれません。
使う主な理由は下記の通りです。

・無料で使える
・低スペックPCでも対応可能
・システムを修正しやすい
・サーバーを自由に建てられる
・OSを自由に作れる(AndroidはLinux発)

# エンジニアなら皆Linuxを使っている
自分でソフト作ったりしないから俺にはLinux関係ないよ！と思ってる方もいると思います。
真っ黒(白)な画面と文字だけ表示されるターミナルで打つコマンドはLinuxです。
Linuxで色々作るにはコマンドを打っていくのです。
例えばデータベースを閲覧や操作する場合はアプリを立ち上げたり、サイトにアクセスしなければなりません。
しかし、Linuxコマンドを使いこなせれば文字を打つだけなので開発スピードは爆上がりします。

さて、続きまして、アルサーガパートナーズ Advent Calendar 2020 20日目の記事は @mizukickerさんのOS、ハードウェエアの解説です。:tada:
FreeRTOS理解その8（タイマー）

# ソフトウェアタイマー
今回はFreeRTOSの[タイマー機能](https://www.freertos.org/FreeRTOS-Software-Timer-API-Functions.html)を使ってみる。あまりいい例題ではないかもしれないが、M5Stackにて起動からの経過時間を表示してみる。

## 環境
Arduino IDEでのM5Stack利用。

## 内容
起動からの経過時間をミリ秒で返すmillis()を用いて、「分：秒：ミリ秒」をM5Stack LCDに表示する。ミリ秒については10ミリ秒ごとに表示を更新する。

### タイマーAPI
[xTimerCreate](https://www.freertos.org/FreeRTOS-timers-xTimerCreate.html)によりタイマーを作成。[ここ](https://www.freertos.org/FreeRTOS-timers-xTimerCreate.html)にあるサンプルを参考に作る。タイマー開始には、[xTimerStart](https://www.freertos.org/FreeRTOS-timers-xTimerStart.html)を使う。ここでは、10ミリ秒、秒、分のそれぞれについてタイマーを設けた。

### ソースコード
まずはタイマー関連の設定。

```c++
#include <M5Stack.h>

TimerHandle_t xMsec, xSec, xMin;
void MsecCallback(TimerHandle_t);
void SecCallback(TimerHandle_t);
void MinCallback(TimerHandle_t);

void MsecCallback(TimerHandle_t xTim) {
  char buf[4];
  uint32_t current = millis();
  sprintf(buf, "%02d", (current%1000)/10);
  M5.Lcd.fillRect(210, 100, 70, 40, BLACK);
  M5.Lcd.drawString(buf, 210, 100);  
}

void SecCallback(TimerHandle_t xTim) {
  char buf[4];
  uint32_t current = millis();
  sprintf(buf, "%02d:", (current/1000)%60);
  M5.Lcd.fillRect(140, 100, 70, 40, BLACK);
  M5.Lcd.drawString(buf, 140, 100); 
}

void MinCallback(TimerHandle_t xTim) {
  char buf[4];
  uint32_t current = millis();
  sprintf(buf, "%02d:", (current/(60*1000))%60);
  M5.Lcd.fillRect(70, 100, 70, 40, BLACK);
  M5.Lcd.drawString(buf, 70, 100);   
}
```

毎10ミリ秒、毎秒、毎分に呼ばれるコールバック関数の定義。M5Stackの描画APIを使い、一つ前の表示数値の削除（黒埋め）および新数値の表示を行う。座標や黒埋めサイズはトライ＆エラーで決めた。1ミリ秒単位表示は無視。

```c++
void setup() {
  M5.begin();
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(4);
  M5.Lcd.drawString("00:", 70, 100);  // min
  M5.Lcd.drawString("00:", 140, 100); // sec
  M5.Lcd.drawString("00", 210, 100);  // msec

  xMsec = xTimerCreate("MsecTimer", pdMS_TO_TICKS(10), pdTRUE, (void*)0, MsecCallback);
  xSec = xTimerCreate("SecTimer", pdMS_TO_TICKS(1000), pdTRUE, (void*)0, SecCallback);
  xMin = xTimerCreate("MinTimer", pdMS_TO_TICKS(60*1000), pdTRUE, (void*)0, MinCallback);
  xTimerStart(xMsec, 0);
  xTimerStart(xSec, 0);
  xTimerStart(xMin, 0);
}

void loop() {
  // Nothing
}

```

setup()にて、LCDの初期化処理および「00:00:00」表示、タイマーの作成（TimerCreate()）および開始（TimerStart()）を行う。コールバック関数ですべてをハンドリングするのでloop()は何もせず、、（delay()を入れた方がベターか？）。 

## 実験
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/a808b5a4-a728-8a2b-3280-28842eda6ee2.jpeg", width=50%>
成功。

## 実は
タイムアウトした時に呼ばれるコールバック関数で長時間処理を行うことは好ましくない。続編（ストップウォッチ）でこの改善を行う。
[UE4] RecastDemoを使ったシミュレーション

検証バージョン: UE4.26.0

# はじめに
　Unreal Engine4のエンジンコードには、ナビゲーションの機能をシミュレーションするためのスタンドアローンのツールが含まれています。このツール自体はシミュレーションデモ用アプリケーションであり、あくまで調整の目安や参考程度に利用することをお勧めします。アプリケーションは以下のパスに配置されています。

[実行ファイル]
 Engine/Source/Runtime/Navmesh/RecastDemo/Bin/Recast.exe

　下の図はUE4エディタ上で作成したコリジョンをエクスポートしてアプリケーション上で展開している一例です。このアプリケーションはシミュレーションのテストを行うための多数のUIを備えていています。

![2020-12-18_00h57_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/f19cd4e6-d0b4-5d7b-93b3-76f8f0a41d74.png)

# できること
　このアプリケーション上で出来る事は以下のような内容です。このアプリに関するドキュメントはないので、もし利用する場合はとにかく触って動かして頂くと良いかと思います。

**[できること]**
・ナビメッシュ生成シミュレーション
　ナビメッシュの生成パラメータを調整することで、ナビメッシュの精度を確認/調整のシミュレーションができます

・パス検索テスト
 2点間のパス検索のテストを行い、パス形成できることや最短ルートを確認することができます

・群衆テスト
　群衆テスト用のオブジェクトをパス移動させることで、簡易的な群衆移動のパフォーマンスと精度のシミュレーションができます

・障害物テスト
　障害物に対するナビメッシュ生成やパス検索での巡行テストができます

　以下の図はパス検索と群衆シミュレーションのテストの様子を示すものです。左図はパス検索のシミュレーションで、赤と緑のオブジェクトの2点間をパス検索のテストを行っています。右図は群衆シミュレーションで、白い円柱オブジェクトを群衆エージェントとし、半径や高さを調整しながら移動する様子を確認することができます。オレンジ色のグラフはパフォーマンスを示します。
![2020-12-18_00h58_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/49404ebe-a69e-e782-9438-734bb4600bee.png)
　下図はナビメッシュの生成シミュレーションをしたものです。図ではCellSizeを違いによるナビメッシュの生成され方を比較したもので、この図ではどちらも傾斜面に対してナビメッシュが生成されますが、カバーすることができる高さがCellSizeによって変わって来ることが確認できるかと思います。
![2020-12-18_00h59_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/fa4c1a3c-dd16-c9b6-df5c-b03fe27dfd4e.png)

# UE4Editorとの連動
　このアプリケーションはナビメッシュ生成のシミュレーションを行うための.objファイルでインポートすることができます。ここでインポートしたファイルをナビメッシュコリジョンの代用として、そのジオメトリ上にメッシュを生成します。
　UE4Editorではこのアプリにコリジョンを出力するために、コンソールコマンド`ExportNavigation`を使用することができます。このコンソールコマンドは、**RuntimeGenerationがStatic以外の場合**に.objデータとしてオブジェクトのデータを出力することができます。ファイルは`[Project]/Saved/`の下に出力されます。

![2020-12-17_23h35_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/d5fcf68e-56ce-27ea-2e2c-cc3c7402ca91.png)

　ナビメッシュのシミュレーションについて、エディタ上で検証しにくかったり調整に困った場合などは、一度このアプリケーションを使ってみて予測をしたりしてみるのも良いかもしれませんね。使い方(操作)に少しクセがありますが、使い始めのハードルはとても低いので、ナビメッシュの動作に興味がある人は一度触ってみることをおすすめします。
Slack API種類が多すぎて分からない人のための大雑把な解説

# はじめに
「Slack API触りたいけど、なんかいっぱいあってよく分からん！」
と言う人が、全体像と、「とりあえずこれをやれば良いんだな」と言うのを理解できるようになるための記事です。
細かい使い方については省いています。


# 結局何使えばいいの？
とりあえず **Web API** と **Events API** を使えるようになれば大体のことはできるようになります。



# Slack APIは大きく分けて2種類
なんか色々と種類があるSlack APIですが、大きく分けると

- **自分からリクエストを送るAPI**
- **Slackからリクエストが送られてくるAPI**

この2つだけです。

## 自分からリクエストを送るAPI
![図表-13.jpg.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282939/ca1e5bff-2258-77c4-90af-f8e2f6a3dddd.jpeg)

### 用途の例
- 特定のチャンネルやDMにメッセージ送信
- チャンネル一覧や、メンバー一覧など、何らかの情報を取ってくる


### 解説
Slackに能動的に動いてもらいたい場合に使います。

Web APIは多くのことができますが、Incoming Webhookは基本メッセージ送信だけを担当します。
最初はIncoming Webhookを使ってみて、慣れたらWeb APIに移っていきましょう。

## Slackからリクエストが送られてくるAPI
![図表-15.jpg.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282939/bb3303fb-04d5-257c-6fd4-7733e37fc2e2.jpeg)

### 用途の例

- 送られたメッセージに対して返信を返す(一般的なチャットボットのイメージ)
- メッセージ上の出席or欠席ボタンをクリックしたら、出欠がDBに保存されて、返信が返ってくる

### 解説
Slack上での動作に対して、反応を返して欲しい場合はこちらを使います。
自分がレスポンスを返す側なので、自作のコードをサーバー上に公開しないといけません。
大体難しいのはこっち。

基本はEvents APIを使います。
必要に応じて、コマンドが使いたければSlash Command、リッチなUIが使いたければ、Interactive Componentsを組み合わせていくイメージ。

## それぞれのAPIの出来る範囲
![図表-17.jpg.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282939/19a9b385-f46a-5779-d6d1-c9690b109e4c.jpeg)


# 設定項目6種類について
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282939/4e72a771-2344-f4eb-8b9b-8fe0c109a099.png)

色々ありますが、Web APIとEvents APIを使う上で、最低限必要な設定はPermissionsとEvent Subscriptionsだけです。
(Botsはインストールすると自動でチェックが入ります。)


# 参考
- [必要な Slack API はどれ？ - Slack アプリの作成のためのヒント](https://api.slack.com/lang/ja-jp/which-api)
- [Web API メソッド一覧](https://api.slack.com/methods)
【React Native + Expo】【Android】コンポーネントがキーボードで押し上げられる

Expo(managed workflow)環境で以下の記事と同様の現象が起きたので、その時の対処法を載せて起きます。
 [【React Native】TextInputでキーボードが押し上げられる【Android】](https://qiita.com/nitaking/items/bf13d5ce8e7ac812c0df )

参考にした記事には以下のように書かれています。
>対処法
>anrdoird/app/src/mainの以下の部分を修正する
-        android:windowSoftInputMode="adjustResize">
+        android:windowSoftInputMode="adjustPan">

Expo(managed workflow)環境の場合はandroidディレクトリは存在しないので、app.jsonを変更します。

```json:app.json
{
  "expo": {
     ...
    "android": {
　　　　...
      "softwareKeyboardLayoutMode": "pan" ←ここを追加
    },
  }
}
```

##参考資料
[Expo app.json / app.config.js リファレンス](https://docs.expo.io/versions/v39.0.0/config/app/#softwarekeyboardlayoutmode)
 [【React Native】TextInputでキーボードが押し上げられる【Android】](https://qiita.com/nitaking/items/bf13d5ce8e7ac812c0df )
https://stackoverflow.com/questions/42840555/how-to-avoid-keyboard-pushing-layout-up-on-android-react-native
自作コードスニペット集

[コードスニペット作成マクロ](https://qiita.com/taleau/items/b462ed151566989520ed)をもとにいくつか試作した。

## 残課題
結局個人用マクロブックに登録しておいても
個人用マクロブックのVBAProjectをアクティブにしておかないと呼び出せないのが若干不便なので
別ブックの作業Project上で軽々呼び出せるようにできないかな

## コード
### 宣言エリア
``` vb
Function SNI_宣言エリア()
  Debug.Print "' -------------------------------------------------"
  Debug.Print "' ■■■ このモジュールの説明 ■■■"
  Debug.Print "'"
  Debug.Print "' -------------------------------------------------"
  Debug.Print ""
  Debug.Print "Type ShObj"
  Debug.Print "  A As Worksheet"
  Debug.Print "  B As Worksheet"
  Debug.Print "  C As Worksheet"
  Debug.Print "End Type"
  Debug.Print "Dim Sh As ShObj"
  Debug.Print ""
  Debug.Print "Type RngObj"
  Debug.Print "  A As Range"
  Debug.Print "  B As Range"
  Debug.Print "  C As Range"
  Debug.Print "End Type"
  Debug.Print "Dim Rng As RngObj"
  Debug.Print ""
  Debug.Print "Type 先頭データ行"
  Debug.Print "  A As Long"
  Debug.Print "  B As Long"
  Debug.Print "  C As Long"
  Debug.Print "End Type"
  Debug.Print "Dim rH As 先頭データ行"
  Debug.Print ""
  Debug.Print "Enum c"
  Debug.Print "  あ = 1"
  Debug.Print "  い"
  Debug.Print "  う"
  Debug.Print "End Enum"
End Function
``` 

### Rangeオブジェクト作成
``` vb
Function SNI_Set_RngObj()
  Debug.Print "  Dim rFirst As Range"
  Debug.Print "  Dim rLast As Range"
  Debug.Print "  "
  Debug.Print "  Set rFirst ="
  Debug.Print "  Set rLast ="
  Debug.Print "  Set Rng = Range(rFirst, rLast)"
  Debug.Print ""
End Function
```

### For i = 1 To UBound(Rangeオブジェクト.Value2)
``` vb
Function SNI_For文_RngObj()
  Debug.Print "  Dim i, j, k"
  Debug.Print "  For i = 1 To UBound(Rng.a.Value2)"
  Debug.Print "    For j = 1 To UBound(Rng.B.Value2)"
  Debug.Print "      For k = c. To c."
  Debug.Print "        "
  Debug.Print "      Next"
  Debug.Print "    Next"
  Debug.Print "  Next"
  Debug.Print ""
End Function
``` 

### For Each r in Rangeオブジェクト
``` vb
Function SNI_ForEach_r()
  Debug.Print "  Dim r As Range"
  Debug.Print "  For Each r In Rng"
  Debug.Print "    "
  Debug.Print "  Next"
End Function
```
4歳娘ちゃんによる歩行者用信号のUIUX的質問に答える

[「エンジニアがテクニカルサポートを絶対にやったほうがいい」に違和感を持った](https://qiita.com/e99h2121/items/b5c2497000c32d6fd3c3) とか
[先輩が新人エンジニアとのコミュニケーションで気をつけるポイントたった1つ] (https://qiita.com/e99h2121/items/3c54a05adccc40ff83b8) とか
[そして前任者誰もいなくなったときのサバイバルガイド](https://qiita.com/e99h2121/items/7190085458af285893df) とか
[「レガシーのメンテばかりは嫌だ」と言う学生さんへのマジレス](https://qiita.com/e99h2121/items/4a0aa999b40f9a2b30bd) 

…なんてのを昨日までまあまあ読んで頂けていてなんかオッサンの小言みたいなこといっぱい書いちゃったなと思っていますがこんな私でも週末はそれなりに母親業をしようとしています。

今日は「なんで、あおはぴかぴかするのに、あかはぴかぴかしないの？」という4歳児さんからの質問。というかうちのチビな。

青の点滅が「もうすぐ赤に変わるよ」の意味だとすると、赤の点滅も「もうすぐ青に変わるよ」の意味で、点滅してもよさそうだ。いや、もうすぐ青に変わることを知らせてしまったらフライングする人が出るからそうしていないだけか？であれば「もうすぐ赤に変わるよ」を教えてしまうことも単に歩行者の焦る気持ちを煽るだけにならないか？

UI/UX的にどうなの、と思ったので調べた。


## [歩行者用信号機（歩行者用信号灯器）のルール](https://jaf.or.jp/common/area/2020/kansai/kyoto/local-news/0626-01)

ルールなので、そのまま読みましょう。以下引用。

> 青色灯火は「歩行者は、進行することができること」、赤色灯火は「歩行者は、道路を横断してはならないこと」、と道路交通法施行令で定められています。
では青色灯火から青色点滅になった場合、みなさんどうしていますか？「信号が赤になる前に渡ってしまおう」と、突然走り出したりしていませんか？
道路交通法施行令では以下の通りです。
**「歩行者は、道路の横断を始めてはならず、また道路を横断している歩行者は、速やかに、その横断を終わるか、又は横断をやめて引き返さなければならないこと。」**
青色点滅時に、急に道路を横断しようとする人の動きはドライバーにとって予測が困難となり非常に危険です。事故に巻き込まれないためにも次の青信号で渡る余裕を持った行動をしましょう。

## つまり青のぴかぴかは意味がある
「歩行者は、道路の横断を始めてはならず、また道路を横断している歩行者は、速やかに、その横断を終わるか、又は横断をやめて引き返さなければならない」
「もうすぐ赤だよ、急いで！」以前に

- 横断を始めてはいけない
- 速やかに道路上から去らなければならない

という行動を期待している。対して、赤をぴかぴかさせることは意味をなさない。赤とは「道路に入ってはいけない」からである。

## 機能に意味を持たせ意味を適切に伝えること

難しいですよね。でも歩行者用信号もすべての人に極力シンプルに限られた性能範囲でそのメッセージを送ろうとしているということだな。

そう言えば弊社のプロダクト、「このメッセージの意味がわからないときは、"いいえ" を選択してください。」という使われているのか使われていないのかわからないリテラル文字列を見かけたことがあります。伝えるのはとても難しいという前提で「機能」を意識したUI/UXってめちゃくちゃ難しいよねと思いましたとさ。以上週末の小話でした！
コードスニペット作成マクロ

[【VBA】VBEでコードスニペットを扱う仕組み](https://qiita.com/Mikoshiba_Kyu/items/4b3ebba0da8ae7cc6589)
先日見つけた素晴らしいこの記事を参考に、コードスニペット化マクロを自作してみた。

## 事前用意
まずはVBEを操作できるようにする。

手順はこちら
[Office TANAKA - VBAでVBEを操作する[VBEを操作するための設定]](http://officetanaka.net/excel/vba/vbe/01.htm)

次に、このマクロ自体を`個人用マクロブック`の`Snipet`という標準モジュールに登録しておく。

## 使い方

1. 何かスニペット化したい部分をコピーしてクリップボードに入れておく
2. イミディエイトから`SNI_00_スニペット作成`を呼び出す。（"sni"まで打ったら`Ctrl`＋`Space`で候補が出る
3. 作成するスニペット名を引数に入れてEnter

すると標準モジュール`Snipet`の最上段にスニペットが作成される。
別のモジュール名に入れたい場合はここを変える。

``` vb
ThisWorkbook.VBProject.VBComponents("Snipet").CodeModule 'このモジュールにスニペットを追加する
```

作成されたスニペットを呼び出すのもイミディエイトから同様に。

## コード

``` vb

Option Explicit

Function SNI_00_スニペット作成(作成スニペット名 As String)
  Dim Codes
  
  With New MSForms.DataObject
    .GetFromClipboard    '変数のデータをDataObjectに格納する
    Codes = Split(.GetText, vbCrLf)
  End With

  Dim ub: ub = UBound(Codes)
  
  Dim Snipets
  ReDim Snipets(ub)
  Dim i
  For i = 0 To ub
    Codes(i) = Replace(Codes(i), """", """""")  ' 既存ダブルクォーテーションを生かす処理
    Snipets(i) = "  debug.Print " & """" & Codes(i) & """"  '全体のダブルクォーテーションのエスケープ処理
  Next
  
  Dim buf
  buf = Join(Snipets, vbLf)
  buf = "Function SNI_" & 作成スニペット名 & "()" & vbLf & buf
  buf = buf & vbLf & "End Function"
  
  With ThisWorkbook.VBProject.VBComponents("Snipet").CodeModule 'このモジュールにスニペットを追加する
    .AddFromString buf
  End With
  
End Function

```
マンガでわかる平直混在ミニアンチパターン

![67235B36-4932-45ED-9569-CA63AA15DE22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/b3c246c8-e9d9-4ce0-82c0-d163a20648b5.png)
http://wiki.c2.com/?JumbleAntipattern

無意識のうちに、水平的設計要素と垂直的設計要素の区別がなくなってしまうアンチパターンです。

水平とは、複数のアプリケーションにまたがる共通の設計概念で、垂直とは、それぞれのアプリケーションごとに選択可能な実装手段に関する設計を意味します。互いに直交するはずの視点が影響を与え合うと、再利用性が下がります。

たとえば、インフラや実装の都合が最初からドメインモデルの分析に混ざってしまうと、モデルの実装中立性が失われ、各アプリケーションのインフラと心中するようなモデルを共有してしまうことになります。逆に、各アプリケーションのインフラ設計や技術寄りのレイヤーに、横槍のような業務の都合がべったり入ってしまうのも、技術視点でのメンテナンスを困難にします。

たぶんこんな感じだと思うのですが、元の説明が短くて、登場する言葉が何を指しているかとらえきれていません。ただはっきりしているのは、直交する問題はそれぞれの軸で閉じて考えるべきということです。公私混同する人は、仕事の評価も人柄の評価も、どちらも下がりますからね。
【JavaEE/JAX-RS】Jersey Sampleをtomcat9上で動かす

# 概要
単純なJerseyのSampleプログラムを実行したいという記事です。
少しハマった個所もあったので、同じ原因で困っている人の参考になればと思います。

# 環境
・Eclipse IDE for Enterprise Java Developers
・Apache Tomcat v9.0
・Java (jdk15)
　※中で、Mavaenも使用します。Tomcatは本書内でダウンロードします。

# 事前準備
## Java確認
コマンドプロンプトを開いて、javaのパスが通っているか確認しましょう。

```cmd
$ java --version
java 15.0.1 2020-10-20
Java(TM) SE Runtime Environment (build 15.0.1+9-18)
Java HotSpot(TM) 64-Bit Server VM (build 15.0.1+9-18, mixed mode, sharing)
```
```cmd
$ javac --version
javac 15.0.1
```

Javaへのパスが通っていない場合には、環境変数の編集をしておきましょう。
ググれば参考サイトが沢山出てくると思いますので、ここでは割愛します。

## Tomcat9のダウンロード＆インストール
Ecripseから以下の手順で、Tomcat9のダウンロード＆インストールを行ってください。
　サーバータブ -> (右クリック)新規サーバー -> Tomcat v9.0 サーバー -> 次へ

この画面で「ダウンロードしてインストール」が出来れば特に問題ありません。
ここで「ダウンロードしてインストール」を実行しましょう。（※新規ディレクトリに対してダウンロードした方がよいです。）

<b>[ダウンロードできない！？]</b>
自分の場合は、Tomcat v9.0サーバーは、「ダウンロードしてインストール」が非活性ボタンとなっておりました。
素直に、Tomcatバイナリバージョンを以下公式サイトからダウンロードしましょう。

[Apache Tomcat公式] https://tomcat.apache.org/download-90.cgi
　Windowsであれば、core -> 64-bit Windows zip　あたりをダウンロードしてください。

zipファイルを任意の場所に解凍したら、Tomcat v9.0サーバーで再度インストールディレクトリで指定しましょう。

# プロジェクト作成

Eclipseを操作して以下プロジェクトを作成しましょう。

① ファイル -> 新規 -> Mavenプロジェクト
② 「デフォルトワークスペース・ロケーションの使用」にチェックを入れ、次へ
③ アーキタイプの選択です。以下を選択して下さい（※取得に時間がかかる為、しばらく待たないと表示されない）
　
・グループid　　　　 ：com.sun.jersey.archetypes
・アーティファクトid : jersey-quickstart-webapp

③「次へ」を押下します。
　「アーティファクトID」は任意に設定して、「完了」を押下しましょう。（他はそのままで良い）

# 実行
作成したプロジェクトに対して、以下のMavenコマンドを実行しましょう。
　右クリック　-> 実行 -> Maven clean -> Maven install


<b>[Maven installで失敗]</b>
見てみると、jersey-servletとjersey-jsonで対象のバージョンがないよとのこと。
こちらは色々調べましたが、根本な解決方法がわからなかった為、
pom,xmlの該当のversionを「jersey.version ⇒ 1.19」に変更しました。

```pom.xml
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.19</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.19</version>
        </dependency>
```
↑[com.sun.jersey]は3か所ある為、全て1.19に変更。

これでMaven Installまで通りました。

あとは以下を選択して、サーバー実行。
「実行」 -> サーバーで実行 -> Tomcat9.0サーバー

[実行後TOP画面]
![無sa題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644011/fc972924-97e6-e8ac-bb6f-ab3cb8ebb795.png)
上記画面で、「Jersey resource」をクリックする。
![無sae題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/644011/85094367-52c8-0c56-1f1f-694091d16335.png)

レスポンスが返ってきたことを確認とれましたね。

まずはこれが一歩目。
ここまで見て下さり、ありがとうございました。
アドベントカレンダー16日目：SREを読んでみた「Googleにおける自動化の進化」編②

前回は、自動化の価値について、学びました。
今回は、自動化のユースケースと自動化システムとプロダクトシステムの階層について学びます。

## 自動化のユースケース
自動化は、様々な問題を解決するためにコードを書く行為だと思われますが、そのコードの直接の目的を表すと、ソフトウェアに対して動作を行うソフトウェア、つまり「メタソフトウェア」が自動化のコードの役割になります。

自動化のユースケースには、様々なものがあります。

* ユーザーアカウントの作成
* サービス用のクラスタのターンアップおよびターンダウン
* ソフトウェアあるいはハードウェアのインストールの準備や撤去
* 新しいバージョンのソフトウェアのロールアウト
* ランタイムの設定変更
* ランタイムの設定変更の特殊なケース：依存対象の設定変更

基本的にこのリストは、システムが成長する限り、続くことになります。
このリストを自分の中でストックしておくことは、重要かなと思います。

## 自動化のクラスの階層
実際のところは、自動化が必要なシステムよりも、自動化が必要な箇所をシステムに組み込んでしまっている方が良いです。
そもそもそのようなロジックが不必要に設計されていることが重要です。
実際は、自動化のシステムは、プロダクトシステムと別個に管理されていることが多いです。そのため、プロダクトシステムが更新されているのにも関わらず、自動化システムが更新されていない状況が生まれることがあります。この状況を生まないために、この両者のシステムをより密にしていこうとする試みが行われますが、これは失敗することが多いです。
この理由として、テストのたびにデプロイを行う必要があるので、プロダクト開発者からの抵抗があること（この抵抗が悪いということではないです。）が挙げられます。
また、実行頻度が低いためにテストが難しい自動化システムはフィードバックが難しいことが挙げられます。
自動化の進化については、次のような経過をたどります。

> **1. 自動化以前<br>　ロケーション間でのデータベースマスターのフェイルオーバーが手動で行われる状態。**
**2. 外部でメンテナンスされるシステム固有の自動化<br>　SREが自分のホームディレクトリにフェイルオーバーのスクリプトを持っている状態。**
**3. 外部でメンテナンスされる汎用の自動化<br>　誰もが使用する「汎用フェイルオーバー」スクリプトに、SREがデータベースのサポートを追加した状態。**
**4. 内部でメンテナンスシステム固有の自動化<br>　データベース自身にフェイルオーバーのスクリプトが同梱されてリリースされている状態。**
**5. システムが自動化を必要としない<br>　データベースが問題を検出し、人間の介入なしに自動的にフェイルオーバーを行う状態。**<sup>1</sup>

自動化はすべて5の状態であることが望ましいのではなく、システムの状況に応じて、必要な進化をするのが良いと思いました。

##まとめ
* 自動化のユースケースを溜めていってみる
* 自動化の進化

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　74-77
楽しい機械学習！のはずだったのに。。。

#はじめに#
こんにちは。五十嵐と申します。
qnoteに入社してもう2回目のアドベントカレンダー。。。
時間が過ぎるのは早いですね。。。(入社したての頃はqnoteで一番年下だったのに🥺 笑)

そんな事はさておき、今回は全く勉強したことの無い「機械学習」に興味を持ったので
qnoteの猫社員たちの画像をTensorFlowを使って学習させ、お題の写真を元にどの猫社員の確率が一番高いのか、PCさんは猫社員の顔をしっかり認識しているのか。
そんな検証をしてみたいと思いました。
#準備#
Dockerを使って環境構築をしようと思ったので、
まず、<a href="https://www.tensorflow.org/install/docker?hl=ja">TensorFlowの公式ページ</a>を参考にしながらやっていくことにしました。


>Docker を使用すると、ホストマシンに必要なのは NVIDIA® GPU ドライバだけになるので、Linux で TensorFlow の GPU サポートを有効にする際の最も簡単な方法となります（NVIDIA® CUDA® ツールキットのインストールは不要です）。

「ほうほう。NVIDIA GPU ドライバというのが必要なのか。」

そう思い調べてみました。すると、
>Mojave向けのWeb Driverが提供されていません。

こんな記事や
>NVIDIA、macOSをサポートした最後のCUDA Toolkiをv10.2リリース。次期アップデートでmacOSは非サポートに。 [AAPL Ch.]
ということが話題となりました。AppleのハードウェアにNVIDIA GPUが搭載されなくなってからもOSへの対応を続けてきたNVIDIAですけど、Mojaveでそのドライバがインストールできなくなり、それはCatalinaでも同様という状態が続き、ついにサポートする意欲を失ったといったところでしょうか。

こんな記事ばかり出てくるんです。(泣)
「諦めるな。きっと何か方法がある。」
そう自分に言い聞かせ、ここからまた調査を進めることにしました。

#とりあえず結論#
MacにDockerを入れて、TensorFlowのコンテナを立てる場合、
GPUのサポートを受ける事は出来ないとの事。(悔しい。。。)

**原因は、既にnvidiaはAppleに対してのサポートを終了していたからです。**

機械学習初心者は(少なくとも僕は)、まさかnvidiaがAppleのサポートを終了している事なんて知らなかったし、
サポートを終了した理由も簡単に言えば**「仲が悪いから」**という理由らしい、、、(勘弁してくれよ笑)

#今回の事例#
Dockerを使った場合、
ホストOS(macOS)上でDockerが動きます。
![nvidia_docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439150/9a948ef9-f7fd-c5b7-ea04-a663bab37b53.png)



nvidiaドライバーはLinuxディストリビューションなどであればサポートされているので、
ホストOSがLinux系であればすんなり使えるハズ。

僕は最初「コンテナ内のOSイメージがUbuntuとかだったらいけるんじゃないの？」と思っていましたが、
調べていると、
>ホストOSにはNVIDIAドライバとnvidia-container-toolkitのパッケージをインストールし、CUDA、cuDNN、TensorflowはDockerコンテナに構築します。

という記事を見つけました。
僕の環境のホストOSはmacOSです。。。

そしてさらに調査し、この表を見つけた時に「詰んだ」と思いました。
僕の使っているMacは、MacBook Pro (Retina, 13-inch, Late 2013)でしたので、
そもそもNVIDIAのGPUが搭載されてないですね笑笑
![スクリーンショット 2020-12-18 16.44.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439150/3be6e11b-2095-421b-d0de-542774a3e984.png)
#唯一の可能性#
調べていて動く可能性があるものとしては、

・High Sierraまでダウングレードさせる方法。 (nvidiaにサポートされているグレードまで)
・デュアルブートでUbuntuをホストOSにする方法。
・仮想環境を使わずにマシンに直接的にTensorFlow,Keras,PlaidMLをインストールする方法。(OSのグレードはCatalinaを使用)

上記の方法があるらしいが、アドベントカレンダー投稿までのタイムリミットが近づいてきていたので試せていない。
#とりあえず結果オーライ#
今回、しっかり環境構築で詰んでしまったわけですが学ぶ事はたくさんありました。

もともとOS周りの知識にはあまり自信がなく、苦手意識がありましたが、
調べているうちに少しずつ理解し、色々な知識を得る事ができました。
まだまだ調べ尽くさないと理解できなかったり、壁にぶつかりながらかもしれませんが
その度に少しでも教養を増やしていければいいなと思っています。

今回の一件を通じて「地道にググれば色んな知識つくな」と改めて気付いたので、この調子で学習を加速させていきたいと思います。

#最後に#
まだまだ分からない事も多く、まとまらない内容になってしまっていると思うので、
「ここ違うよ」とか「こうしたほうがいいんじゃない？」などのコメントを頂けたらとてもありがたいです。

また、「こうしたらmacでもDockerとGPU使って画像認識できるのでは？」などの情報も募集しておりますので
コメントください。(qnote社員の方は直接お願いします笑)

**もし記事がちょっとでも参考になった方や「へえ〜そうなんか〜」と思っていただけた方は
LGTMよろしくお願いします！👍**

#参考にさせていただいた記事#
<a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker
">インストールガイド-NVIDIA Cloud Native Technologies  ドキュメント</a>
<a href="https://take6shin-tech-diary.com/cuda-tensorflow/">NVIDIA GPU搭載MacBook ProにUbuntu 18.04を入れてCUDA/cuDNN/Tensorflow機械学習環境を構築 | 竹のしんのテック日記</a>
<a href="https://blog.goo.ne.jp/m4g/e/488bfbd0f3b302e9a543383d680d7201">NVIDIAがMacから完全撤退 - 日々適当</a>
<a href="https://www.tensorflow.org/install/docker?hl=ja">TensorFlow | Docker</a>
※参考にしたサイトが多すぎるので一部抜粋させていただいています。
UITextFieldのイベント種類

ボタンの非活性化によく使うのでUITextFiledのイベント種類について紹介します。

#Did End On Exit
Returnキー　または　改行キーを押して閉じられた後にメソッドが呼び出される。
#Editing Changed
テキストフィールドの文字が変更されるたびにメソッドが呼び出される。
#Editing Did Begin
テキストフィールドをタップした時にメソッドが呼び出される。
#Editing Did End
キーボードをしまうときにメソッドが呼び出される。
#Primary Action Triggered
これはよくわからないので、わかり次第更新します。
#Touch Cancel
これもよくわからないので、わかり次第更新します。
#Touch Down
テキストフィールドに触れた瞬間にメソッドが呼び出される。
#Touch Down Repeat
テキストフィールドをダブルタップした時にメソッドが呼び出される。
#Touch Drag Enter
テキストフィールドを押して、そのままドラックし再びテキストフィールドに戻ったときにメソッドが呼び出される。
#Touch Drag Exit
テキストフィールドを押して、そのままドラックして外側に移動した時にメソッドが呼び出される。
#Touch Drag Inside
テキストフィールドを押して、そのままドラックした時点で呼ばれる。
#Touch Drag Outside
Touch Drag Exitと一緒でテキストフィールドを押して、そのままドラックして外側に移動した時にメソッドが呼び出される。
#Touch Up Inside
テキストフィールドを押した後、近くで指を話した時にメソッドが呼び出される。
#Touch Up Outside
テキストフィールドを押した後、遠くで指を離したときにメソッドが呼び出される。
#Value Changed
テキストフィールドの値を変えた瞬間に呼び出される。
gcloud CLI と Google APIs Client Libraries の使う Credential の違い

4種類ある。 terraform apply は Google APIs Client Libraries を使っているので注意。

## (1) gloud CLI

### (1-1) IAM のユーザーアカウントで。

```
gcloud auth login
```

### (1-2) IAM のサービスアカウントで。

```
gcloud auth activate-service-account
```

## (2) Google APIs Client Libraries

### (2-1) IAM のユーザーアカウントで。

```
gcloud auth application-default login
# ~/.config/gcloud/application_default_credentials.json に入る
```
#### 確認

```
gcloud auth list
```

#### logout

```
gcloud auth application-default revoke
```

### (2-2) IAM のサービスアカウントで。

```
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service_account_credential.json
```
NVIDIA Jetsonでdocker composeを使う方法

# 概要

* NVIDIA Jetsonでdocker composeを、GPUありで使う方法を紹介
* 条件
    * JetPack 4.3以降（nvidia-dockerが使える必要があるため）

# 環境構築

ホスト側でdocker-compose本体を下記コマンドでインストールする。

```bash
$ sudo apt install python3-pip
$ sudo apt install build-essential libssl-dev libffi-dev python3-dev
$ sudo pip3 install docker-compose
```

# 使い方

* ポイント
    * docker-compose.yamlのバージョンの指定に注意
        * docker-compose v1.26以前
            * ver.2系統でしか、runtimeをサポートしていないため、ver.2系で記述
        * docker-compose v1.27以降
            * ver.2,ver.3ともに、runtimeサポート（https://github.com/docker/compose/issues/6239) 
    * 「runtime」タグに、「nvidia」指定
    * 「environment」タグに、「NVIDIA_VISIBLE_DEVICES=all」を指定
        * すべてのGPUを使えるようにする環境変数

docker-compose.yml (docker-compose v1.27以降）

```yaml
version: '3'
services:
 test:
   runtime: nvidia
   environment:
     - NVIDIA_VISIBLE_DEVICES=all
```

## 例

Nbodyサンプルをdocker-composeで動かす。

https://github.com/ntrlmt/jetson-nbody-docker-compose

# 参考

https://qiita.com/sht47/items/0706f19c67eb30e0954f
AWS ソリューション アーキテクト アソシエイトをUdemyで勉強して更新した話

AWS 認定ソリューション アーキテクト アソシエイト（SAA）試験を、今年更新しました。前回受験から3年ほど経っておりUdemyで勉強し直したので、役に立った点などをまとめます。

# 受験の背景
AWS SAAは、3年前に初めて取得しました。
会社としては、これから力を入れていこうとしており、業務経験はなかったのですが、勉強してなんとか合格できました。

その後、転職したこともあり業務経験もなく、プライベートでAlexaスキルを作るくらいでしか使う機会がないまま、資格更新の時期が来てしまいました。どうやってAWSの勉強をしようか困っていたところ見つけたのが、Udemyの講座でした。

# 受講した講座
 - [これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/course/aws-associate/)

AWSのEC2やS3の各サービスについて、概要から実際の操作方法までを動画で解説してくれています。
課金が必要最低限になるよう説明してくださる点も安心できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20639/641f7507-c47a-778b-bf46-9e3cfcc0c228.png)

## 講座の安心できる点
EC2のマシンにElastic IPを設定するハンズオンでは、ボタン1つひとつの操作から説明してくれるので分かりやすかったです。
また、マシンに関連付けていないElastic IPは課金されることもきちんと説明してくれるので、無駄なお金を使わずにすみました。

## 少し気になる点
録音タイミングが異なるのか、1本の動画内でナレーションの音質が異なることがあり気になりました。
AWSの機能/インターフェースの更新は多く、対応するためには仕方ないかも知れませんね。この講座特有のことかもしれません。

# まとめ
業務経験がない中、SAAに合格できたのはUdemyの講座のおかげだと思います。
動画での説明は分かりやすく、知識がつきました。
Git for Windows で急に ssh 経由の git fetch / clone が動作しなくなったのを修正した

数日前まで普通に使えていたはずの Git for Windows が急に permission denied のエラーを吐くようになり、`git fetch` も `git clone` もできなくなってしまいましたが、OpenSSH のバージョンアップをすることで直りました。

ネットを探しても、git で permission denied が出るのは SSH の鍵の登録漏れであるという前提の対処法ばかり出てきますが、SSH の鍵を登録しても permission denied になる場合、この記事が参考になるかもしれません。

# 環境

- 発生日：2020/12/19
- OS：Windows 10
- Git のバージョン： 2.29.2.windows.3
- リモートリポジトリの場所：gitlab.com

# 前提条件

数日前までは普通に `git fetch` も `git clone` もできていました。（つまり、SSH の鍵の登録漏れではありません。）

# 事象

`git fetch` も `git clone` も以下のような出力をして終了しました。

```console
$ git fetch
warning: agent returned different signature type ssh-rsa (expected rsa-sha2-512)
git@gitlab.com: Permission denied (publickey,keyboard-interactive).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

なお、SSH の鍵を作り直して登録しなおしても、Git for Windows を再インストールしても、全く効果がありませんでした。

# 解決方法

[Install Win32 OpenSSH · PowerShell/Win32-OpenSSH Wiki](https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH) に沿って OpenSSH を更新しました。
すると、以下のように git コマンドが期待通り動作するようになりました。

```console
$ git fetch
remote: Enumerating objects: 302, done.
remote: Counting objects: 100% (302/302), done.
remote: Compressing objects: 100% (131/131), done.
remote: Total 709 (delta 144), reused 283 (delta 128), pack-reused 407
Receiving objects: 100% (709/709), 144.01 KiB | 49.00 KiB/s, done.
Resolving deltas: 100% (348/348), completed with 10 local objects.
From gitlab.com:MusicScience37/mprpc
   c550fcf..427f50e  develop            -> origin/develop
 * [new branch]      feat/python_server -> origin/feat/python_server
```

# 考えられる要因

Windows に入っている OpenSSH が古いため、暗号化に使用するアルゴリズムが古く、Git リポジトリのサーバに拒否されたのではないかと思っています。

# 参考

- [SSH suddenly stopped working in git-bash on Windows 10 - Super User](https://superuser.com/questions/1496843/ssh-suddenly-stopped-working-in-git-bash-on-windows-10)
- [ssh-agent: agent returned different signature type · Issue #1263 · PowerShell/Win32-OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/issues/1263)
- [Install Win32 OpenSSH · PowerShell/Win32-OpenSSH Wiki](https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH)
macOS で git-prompt.bash の代わりに git-prompt.zsh を使い git status 表示を爆速にする

M1 macOS (11.0.1)で検証しました.

【zsh】絶対やるべき！ターミナルでgitのブランチ名を表示&補完【git-prompt / git-completion】
https://qiita.com/mikan3rd/items/d41a8ca26523f950ea9d

ありがとうございます. git-prompt 便利ですよね. 
でも私の macOS 環境(Macports だけ入っているくらいのほぼ素の環境)ではなぜか劇遅でした(ついでに言うと Linux でも)

`llvm-project` みたいにでかい git repo だと, ディレクトリ移動するごとに数秒待たされて仕事になりません.

git-prompt は特に Windows で劇遅であることが知られています.

Windows GitBash のプロンプト表示が遅いのをなんとかしたかった
https://neos21.hatenablog.com/entry/2018/12/31/080000

git ls あたりが遅いのが原因のようです. 原因解明して対処するのも面倒です.
(とりあえずの対処は上記 site のように branch 名だけ表示するように __git_ps1 あたりを自前で作る)

# zsh 版 git-prompt

いくつか同名や似たプロジェクトがあるようですが, 今回は `woefe/git-prompt.zsh` を使いました.

https://github.com/woefe/git-prompt.zsh

git-completion と連携できます.
miniforge(miniconda)と連携したかったので `.zshrc` は以下のような感じになりました.

```zsh
fpath=(~/.zsh $fpath)
zstyle ':completion:*:*:git:*' script ~/.zsh/git-completion.bash
autoload -Uz compinit && compinit


source ~/.zsh/git-prompt.zsh/git-prompt.zsh
source ~/.zsh/git-prompt.zsh/examples/default.zsh

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/syoyo/miniforge3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/Users/syoyo/miniforge3/etc/profile.d/conda.sh" ]; then
        . "/Users/syoyo/miniforge3/etc/profile.d/conda.sh"
    else
        export PATH="/Users/syoyo/miniforge3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<
```

![Screen Shot 2020-12-19 at 1.39.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/e4a0b054-65dc-a57a-5772-c917283f6586.png)

こんな感じで表示されて, llvm-project のようなでかい git repo でも爆速にサクサク動くのを確認しました :tada:
(実際は遅延評価 + cache してレスポンス上げているっぽいようです)
競技プログラミング 日記 python 20201213

https://atcoder.jp/contests/abc185/

- A - ABC Preparation

与えられた4つの数字の最も小さい物を出力すれば良い

```py
print(min(list(map(int, input().split()))))
```

 - B - Smartphone Addiction

コードは汚いが、カフェに入ったタイミングと終了時にバッテリーが0以下かどうを判定すれば良さそうという思想で実装
バッテリーは最大容量以上にはならないことを最初忘れていたのがミス

```py
n, m, t = map(int, input().split())
max_n = n
now = 0
ans = "Yes"
for i in range(m):
    a, b = map(int, input().split())
    n = n - a + now
    if n <= 0:
        ans = "No"
        break
    n = min(n + (b - a), max_n)
    now = b
if n - t + now <= 0:
    ans = "No"
    
print(ans)    
```
- C - Duodecim Ferra

長さLのぼうを11箇所で切断するときの分け方が何通りか。受験でよく出そうな問題ではある

整数の長さになるよう分割なので、切断箇所は L - 1箇所。 L - 1 C 11 とかで求まるか

```py
from math import factorial

L = int(input())

print(int(factorial(L - 1) / factorial(L - 12) / factorial(11)))
```

と思ったが、これではだめ。
解説を読むと
> 注意しなければいけないのは、この分数自体の値は 
2 ** 63
 未満ですが、分子は 
64 bit 整数型に収まらないことがあるという点です。オーバーフローを回避する方法はいくつかあります。

int64のサイズを超えるからアウトか。。この発想はなかった。
パスカルの三角形を用いて、漸化式敵に解くのが良さそう

メモ化再帰のようなことをしてみた。関数が副作用満点なので気持ち悪い

```py
from math import factorial

L = int(input())
matrix = [[[] for _ in range(201)] for _ in range(201)]

def pascal(i, j):
    if matrix[i][j]:
        return matrix[i][j]
    if j == 0 or i == j:
        return 1
    ans = pascal(i-1, j-1) + pascal(i-1, j)
    matrix[i][j] = ans
    return(pascal(i-1, j-1) + pascal(i-1, j))
    
print(pascal(L-1, 11))
```

- D - Stamp

スタンプの作り方は、白いマスの連続する数のうち最も小さい物を採用すればよさそう
幅4のスタンプなら、5のますはスタンプを２回使うことで塗りつぶすことができる

```py
n, m = map(int, input().split())
if m == 0:
    print(1)
    exit()

a = sorted(list(map(int, input().split())))
white = []
for i in range(len(a)):
    if i == 0:
        white.append(a[i] - 1)
    elif i == (len(a) - 1):
        white.append(a[i] - a[i-1] -1)
        white.append(n - a[i])
    else:
        white.append(a[i] - a[i-1] -1)
white = list(filter(lambda x: x != 0, white))
if len(white) == 0:
    print(0)
    exit()
k = min(white)

ans = 0
for l in white:
    x = l // k
    amari = l % k
    if amari != 0:
        x += 1
    ans += x

print(ans)
```

かなり場当たり的だが、、一応通った

今回はここまで！
エンジニアに話しかけるタイミングを非エンジニアが考えてみた件

この記事は [WESEEK Advent Calendar 2020](https://qiita.com/advent-calendar/2020/weseek) 19日目の記事です。

3回目です！すっかり常連になりました。
しかし残念ながら、アドベントカレンダーは埋まってしまったので私が執筆をするのは最後です…！

集中して仕事をしている人に話しかけるのはけっこう勇気が要りますよね。
それがエンジニアだとどうでしょう。もっとハードルが高い！

集中が途切れたらどうしよう、コードを書いていると話しかけられたらなんかパーになりそう…。
うう、ど、ど、ど、どーーーしよーーー！！！！

と思う方の背中を少しだけ押せるような記事になれたら最高です。
Qiitaは初心者なこともあり、色々ご指摘をいただけると嬉しいです。

# 筆者の前提条件
- 以前ゲーム開発会社に在籍しており、エンジニア/プログラマと触れ合ってきた
- 現在はエンジニアに囲まれて、非エンジニアな職に就いている
- かつ、人とのコミュニケーションをとてもとても大切にしている
- スナック菓子的なものをあまり食べない
- 人に話しかけるタイミングは実は気にしている

では、参ります。

# 集中しているときに話しかけるとどうなる
うーん、人によるかと思うのですが、今この記事を読んでいる方はどうでしょうか？
いくつかタイプに分類できるかと思います。

1. ゼロから再スタート
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915398/aec4dac6-dca1-3090-1ab8-b0ba3746166e.png" width=50%>


2. 話しかけられた地点と同程度から回復
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915398/127e157f-2533-72e9-8adb-77e9ff45d12a.png" width=50%>
3. 何事もないように進む
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915398/067ca599-c33e-c903-e3c3-0db9c517629a.png" width=50%>


私は1と2をうろうろする派なので、話しかけられそうになったら「ちょっと待ってください！！！！」と先制して待ったをかけます。

と、いうことをゲーム作りの中でも行ってきたのでエンジニア/プログラマに話しかけるときは少し気を使っていたりもします。

# どうすると集中力の途切れは軽減されるか
これまた人による…というつまらない結論にもなりそうですが。
上に書いたように、話しかけられそうになることを気づかせればよい…と思っています。

**今から話しかけるよ！！！**

というアピールをしたらどうでしょう。これを私は実践しています。
「●●さん、今ちょっといいですか」
これを先制攻撃したら、大体何かしらは進むでしょう。

この一言も話しかけられない雰囲気の人…はあきらめましょう！SlackだSlack！
コミュニケーションは対面だけではない！のです。

# 実際聞いてみた
入社してすぐくらいに、エンジニア数名に聞いてみました。集中を途切れさせてしまうのは申し訳ないので。
かといって、人に何か聞きたいときは自分もある程度逼迫しているかもしれませんし、事前に知っておこうと。

「普通に話しかけていいよ。ダメな時はまぁ…ダメって言いますし。」

という、私の今いるWESEEKのみなさんはこのような温かい回答でしたので、遠慮なく話しかけています。
まじかーー普通じゃないか！！！と若干拍子抜けをしたものの、エンジニアもまた人間。
かしこまることも身構えることもないのですね。日々が学びです。


# まとめ
色々と悶々と考えたりもしたのですが、どうしたら良いですか？と突撃をしておくことが一番いいのだろうか。
と、ここ数ヶ月で感じました。

エンジニアに話しかけるタイミングを非エンジニアが考えてみた件については、まだまだ模索してもよい気がしています。
結論は出せないだろうし、この記事で出すのも早計かなと。

頭の中が可視化できて、**今話しかけるな表示**が出たらいいのになぁ～と思う夜に執筆しました。

# おわりのおわりに
Qiitaという媒体に、エンジニアスキルが皆無なものが乗り込んでみるにあたって、本当に大丈夫だろうか…ととても心配だった。
実際問題、私の記事はためにはならないし学びにもならないかもしれない。
何か数値的なものと結び付けられたらよかったのになぁ…と若干の後悔は残るけれど、楽しい執筆でもありました。

アドベントカレンダーをやりましょう！と呼びかけてくれたitizawa氏に感謝です。

---
※この記事は [WESEEK Tips wiki](https://tips.weseek.co.jp/) に 2020/12/19 に投稿された記事の転載です。
Tips wiki では、IT企業の技術的な情報やプロジェクトの情報を公開可能な範囲で公開してます。
Androidのスクリーンショット＆スクロールを自動化

# 自動でスクロールしてスクショを撮るプログラムを書いた
Androidで、画面をスクロールしてスクリーンショットを撮る作業をプログラムで自動化しました。
これをやろうとした動機は、AndroidからiPhoneに乗り換えようとした際に、LINEのトーク履歴を引き継げない問題があったからです。LINEの機能でトーク履歴をテキストファイルとして出力することはできますが、味気ないものになってしまいます。
大切な思い出を保存しておきたかったので、トーク画面をスクリーンショットしようとしたのですが、手作業では気が遠くなる量です。
そこで、スクショ→スクロールの作業を自動化しました。調べたらすぐにできるだろうと思っていたのですが、予想以上に情報が出てこなかったので記事にまとめておきます。
友人から「やり方教えて」と言われたついでに書いているだけなので、細かい部分はカバーしていません。

# 環境
Mac OS Catalina 10.15.7
Android version 9

# 使用したツール
Android端末の操作にはADB（Android Debug Bridge）を使いました。
簡単に言えば、MacやWindowsでAndroid端末を操作するためのツールです。
詳しくはこちらの記事を見てみて下さい。
[Android Debug Bridgeとは？Android開発のデバッグツールのインストールと初期設定](https://qiita.com/TanakanoAnchan/items/676e1e9c15028fd6cb91)

プログラムはPythonで書きました。
[subprocess](https://docs.python.org/ja/2.7/library/subprocess.html)モジュールでADBのコマンドを呼び出して使う、というやり方です。
subprocessは、Pythonから他のアプリを起動したり、実行結果を得たりするモジュールです。
詳しくは[こちら](https://techacademy.jp/magazine/19189#:~:text=subprocess%E3%81%A8%E3%81%AF%E3%80%81%20Python%20%E3%81%AE,%E3%81%AB%E5%90%AB%E3%81%BE%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82)がわかりやすいかと思います。

# ADBのインストール
ADBの使い方については、[こちらの記事](https://note.com/npaka/n/n194351176324)を参照して下さい。
パスを通す必要がありますが、Macのパスの通し方はこの記事がわかりやすいと思います。
[MacでPATHを通す](https://qiita.com/nbkn/items/01a11392921119fa0153)

# Androidでタッチした座標を表示する
プログラムの中でスクロールの動作（正確にはスワイプ）を指定するので、どれだけの長さを動かせば良いかを知る必要があります。
Androidの開発者オプションの中に、タッチした場所の座標を表示させる機能があるので、これをオンにします。
開発者オプションの使い方については[こちら](https://appllio.com/android-development-mode-settings)を、タッチの座標を表示する方法については[この記事](https://qiita.com/takeoverjp/items/69c89d300b50b8fe4367)を参照して下さい。
この機能を使って、大体どれくらいの座標の位置でスクロールすれば良いか、大まかに掴みます。

# Pythonのコード
```Python
import subprocess

swipe_up = ('adb', 'shell', 'input', 'swipe', '300', '400', '300', '1520')
swipe_down = ('adb', 'shell', 'input', 'swipe', '300', '1520', '300', '400')

if __name__ == "__main__":
    for i in range(100):
        screen_capture = ('adb', 'shell', 'screencap', '-p', '/sdcard/chat/screenshot' + str(i) + '.png')
        subprocess.call(screen_capture)
        subprocess.call(swipe_up)
        # subprocess.call(swipe_down)
        print(i)
```
これが実際のコードです。端末を接続した状態でこれを実行すれば実機上でプログラムが走ります。
自分の場合はswipe_downを使いましたが、コメントアウトしてあるswipe_upを使えば下にスクロールしていくことができます。
数値は実験して丁度いい値に調節しました。ちょうど画面のサイズ分だけスクロールするようなスワイプの長さにしました。
4つの数値の意味は、「目的地点のx座標, 目的地点のy座標, 出発地点のx座標, 出発地点のy座標」です。
画像の名前や保存先はお好みで設定して下さい。

このコードを実行すると、chatというフォルダにscreenshot0〜screenshot99という名前で99枚のスクリーンショットが保存されます。
【TypeScript】TypeScript特有のリテラル型の使いどころ

# TypeScript特有の型「リテラル型」
TypeScriptの学習を進めていくと「リテラル型」という型が出現します。
これはTypeScript特有の型のようです。

リテラル型は、
「任意に指定したリテラル(文字列リテラル、数値リテラル....)以外を許可しない型」です。
(文字の意味そのままの説明になってしますが...。)

```
> let morningGreeting: 'Hello' = 'Hello';
>  morningGreeting = 'Good Evening';
[eval].ts:2:1 - error TS2322: Type '"Good Evening"' is not assignable to type '"Hello"'.
```

上記はコンパイルエラーとなります。

変数`morningGreeting`は`'Hello'`という文字列リテラル型と定義されているので、
`'Good Evening'`という文字列リテラルは許容されず、`'Hello'`以外は受け入れられません。

型については理解できるのですが、文字列を決めうちで定義してどこに活かせるのか初見の時は疑問でした。


# 単独ではそこまで使い道がない
色々なコードを読み、リテラル型は単独で使われることがほとんどありませんでした。

大抵は下記のように、ユニオン型と君合わせて、複数のリテラル型を定義して列挙型のように使用されています。

```
> let greeting: 'Hello'| 'Hey' | 'Hi' = 'Hello';
> greeting = 'Hello';
> greeting = 'Yah';
[eval].ts:2:1 - error TS2322: Type '"Yah"' is not assignable to type '"Hello" | "Hey" | "Hi"'.
```

このように、enumの列挙型のようなことが実現できます。
enumよりシンプルな書き方でスッキリしますし、直感的で読みやすいので、
ユニオン型とリテラル型を組み合わせて書く型が多いようです。

```
> enum Greeting { 
>  Hello =  'Hello',
>  Hey = 'Hey',
>  Hi = 'Hi',
> }
 
> let greeting: Greeting = Greeting.Hello; 
> greeting = 'Yah'; 
[eval].ts:7:1 - error TS2322: Type '"Yah"' is not assignable to type 'Greeting'.
```

説明のために変数への代入で説明しましたが、実際に使うとなれば```type```で型を定義して使うことが多いと思います。

```typescript

type Greeting = 'Hello'| 'Hey' | 'Hi';

const hoge: Greeting = 'Hello';
const fuga: Greeting = 'Yah'; //コンパイルエラー
```

TypeScriptは様々な型を組み合わせることができるので、そこも面白いポイントだなと思っています。

最後まで読んで頂きありがとうございました。