OmniAICreator/Qiita-1.07M huggingface dataset:
確認ページ以外に遷移したときにフォームの内容をリセットする【Next.js x Redux】


![Form消去成功.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/06c010f7-8006-2040-5bac-b449838d6a23.gif)


# やりたいこと

Next.jsで書かれたサイトに、確認ページ付きのフォームを実装する。

- **フォーム(A)→確認ページ(B)** の、ページを跨いだデータ共有にReduxを使う
- しかし、**それ以外のページ(C)**に遷移した時には、フォーム内容に紐づいたReduxのストアを消去しないといけない。


# 環境

- Node.js 12.18.4
  - npm 6.14.8
- Typescript 4.0.7
- React.js 16.13.0
  - React Redux 7.2.3
  - Redux Toolkit 1.5.1 
- Next.js 10.1.3


# Before

Reduxでデータを保持するだけだと、**確認ページ(B)**にはきちんと入力した内容が反映されるが、**トップページ(C)**に一度戻ってから**入力ページ(A)**に再度進んだ時に前回の入力内容が残ってるのでダメ。
![form消去失敗.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/a3c39edb-ab21-d436-d142-245f209f8151.gif)


# Next.js ドキュメントを読んでみると…

[Next.js Documents | next/router # router.events](https://nextjs.org/docs/api-reference/next/router#routerevents)

`router.events`を使うことで、ページ遷移時のイベントハンドラを登録できるらしい。
この機能を盛り込んだCustom Hookを次のように定義した。

```tsx:useActionOnRouteChange.tsx
import { useRouter } from "next/dist/client/router";
import { useEffect } from "react";

type RouteChangeAction = (
  pathName: string,
  options: { shallow?: boolean }
) => void;

type PathnamePredicate = (pathName: string) => boolean;

// どんなPathnameが来ても真
const anyPath: PathnamePredicate = () => true;

/**
 * Route変更時に、pathnameが条件を満たす場合にのみアクションを実行するように設定するHook
 * @param action Route変更時に呼び出されるアクション
 * @param pathPred アクションが呼び出されるかどうかを決める条件 デフォルトでは常に真
 */
const useActionOnRouteChange = (
  action: RouteChangeAction,
  pathPred: PathnamePredicate = anyPath
) => {
  // routerオブジェクトを使うためのおまじない
  const router = useRouter();

  useEffect(() => {
    const handler: RouteChangeAction = (path, options) => {
      if (pathPred(path)) action(path, options);
    };

    // mount時にイベントハンドラを登録
    router.events.on("routeChangeStart", handler);
    return () => {
      router.events.off("routeChangeStart", handler);
    };
  }, [action, pathPred]); // 一応引数に与えられる関数が変わった時にも再設定する。
};

export default useActionOnRouteChange;

```

このHookを、遷移前のページ（今回は**フォーム入力ページ(A)**）で使用すると、第２引数で与えた条件を満たすPathname（ここでは**確認ページ以外のページ(C)**）に遷移したときに、第1引数で与えたアクションが実行される。

```tsx:pages/input-name/index.tsxの一部

const InputNamePage = () => {
  // ...
  const dispatch = useDispatch();

  useActionOnRouteChange(
    () => {
      console.log("reset");
      // reduxのActionをここから呼び出す
    },
    (pathName) => pathName !== "/input-name/confirm" // このPath以外に遷移したとき
  );

  // ...

  return (
    <div>
      { /* ... */ }
    </div>
  );
}

export default InputNamePage;
```

# 結果

一度トップページ(C)に戻ると、ちゃんとフォームがリセットされた。
![Form消去成功.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234029/06c010f7-8006-2040-5bac-b449838d6a23.gif)

ページ遷移の時のデータ消去は、中央管理にしても良いかもしれないが、この方法を使うと、消したいデータを入力する画面の定義の中に消去のロジックも書くことになり、凝集度が高くなって良いかもしれない。
中央管理にするには、`_app.tsx`の中で`useActionOnRouteChange`を使えば良いでしょう。

Custom Hookにすれば、ロジックだけを取り出して、部品化できる！
Hooks, バンザイ！

# 参考にした記事

https://nextjs.org/docs/api-reference/next/router#routerevents
正規表現(Regular Expression)について

#目次
<b>①正規表現(Regular Expression)とは</b>
<b>②基本的な正規表現について</b>
<b>③正規表現をまとめたもの</b>
<b>④正規表現を確かめるサイト</b>

##①正規表現(Regular Expression)とは
文字列の集合を特定の記法で表現すること。

##②基本的な正規表現について
. + * [a-z] {3}{3.7} ^ $ について解説する。
※/はデリミタと言われる。このデリミタは#でも表せれれる。

<b>.について</b>
.は任意の１文字にマッチすると言う意味。
例えば, 
ca.yであれば、cary, cauy, cakyなどはマッチし、cbuy, famy, cakuなどはマッチしない。

<b>+について</b>
+は前にある文字が1文字以上続く
例えば
cara+の場合(+の前のaが1文字以上)
caraa caraaa caraaaaaaaなどがマッチし、
cara racaaなどがマッチしない

<b> * (アスタリスク)について</b>
* は前にある文字が0文字以上続くという意味
例えば、
cara*の場合、(*の前のaが0文字以上という条件)
cara, caraa, caraaaaaaaaaなどマッチし、carはマッチしない。

<b> [](ブラケット) について</b>
[]は中にある文字、いずれかにマッチするという意味
例えば、
[abc]の場合、
a,book, catはマッチし、d, egg, jjjなどはマッチしない。

※[a-z]や[0-9]など[]のなかに-をいれると範囲指定ができる。\dは[0-9]は同じ意味。

<b> {n}(ブレース)について</b>
{n}は前にある文字がn文字以上続くと言う意味
例えば、
a{4}だとしたら、faaaatはマッチし、aaaはマッチしない。

{n,m}と記述した場合、n文字以上m文字以下が続くという意味になる。
a{4,7}の場合、
9aaaay,aaaaaaaはマッチし、a, aa, aaaはマッチしない

<b> ^(キャレット)と$(ドル)について</b>
^は行頭を$は行末を表す。
※^ は\A で表現でき、$は\zで表現できる
例えば
^My name is [a-z]+$
上記の意味はMから始まる文字列で、a-zで終わる文字列という意味のこと

そのため
My name is caraはマッチし、I'm cara. My name is caraはマッチしない。

<b>③正規表現をまとめたもの</b>

|正規表現  |意味  |
|---|---|
|/  |正規表現の開始 |
|\A  |文字列の先頭 |
|[\w+-.]+  |英数字、アンダースコア、プラス、ハイフン、ドットのいずれかを少なくとも１文字以上繰り返す|
|@  |アットマーク |
|[a-z\d-.]+ |英小文字、数字、ハイフン、ドットのいずれかを少なくとも１文字以上繰り返す  |
|. |ドット |
|[a-z]+  |英小文字を少なくとも１文字以上繰り返す  |
|\z |文字列の末尾 |
|/ |正規表現の終了 |
|i |大文字・小文字を無視するオプション |

※②で説明してない表現もあります

<b>④正規表現を確かめるサイト</b>
https://regex101.com/
Python 3.7になったGoogle ColabでCASAを動かしてみる

## TL;DR

[Google Colaboratory](https://colab.research.google.com/)（Colab）のPythonのバージョンは長らく3.6でしたが、2021年2月24日に3.7にアップグレードされました[^1]。これによって、Python 3.6系にしか対応していない[^2]電波天文学のソフトウェア[CASA](https://casa.nrao.edu/)がColab上で動かなくなってしまいました。この記事では、3.7系対応のプレリリース版CASA6.2をColabにインストールし、[公式のノートブック](https://colab.research.google.com/github/casangi/examples/blob/master/casa6/CASA6_demo.ipynb)が動くことを確認してみました[^3]。

[^1]: https://github.com/googlecolab/colabtools/issues/1422#issuecomment-784545501
[^2]: 2021年4月時点の最新版CASA6.1の話です
[^3]: ノートブックの内容が動くだけで、全ての動作を保証するものではありません

## How to install

まず、リリース版のインストール方法は[CASA docs](https://casa.nrao.edu/casadocs/casa-6.1.0/usingcasa/obtaining-and-installing)に記載されている以下の方法です。これをColabで実行すると、Python 3.7対応のcasatoolsが存在しないのでエラーが出てインストールできません。

```shell:リリース版のインストール方法
apt-get install libgfortran3
pip install --index-url https://casa-pip.nrao.edu/repository/pypi-casa-release/simple casatools
pip install --index-url https://casa-pip.nrao.edu/repository/pypi-casa-release/simple casatasks
```
```plaintext:エラーメッセージ
Looking in indexes: https://casa-pip.nrao.edu/repository/pypi-casa-release/simple
ERROR: Could not find a version that satisfies the requirement casatools (from versions: none)
ERROR: No matching distribution found for casatools
```

そこで、<https://casa-pip.nrao.edu>を検索してPython 3.7対応のプレリリース版を探します。記事作成時点では、6.2.0.100などが良さそうです[^4]。というわけで、プレリリース版のインストール方法ではこれらを手動でダウンロードします。

```shell:プレリリース版のインストール方法
apt-get install libgfortran3
wget https://casa-pip.nrao.edu/repository/casa-test-wheel/packages/casatools/6.2.0.100/casatools-6.2.0.100-cp37-cp37m-manylinux2010_x86_64.whl
wget https://casa-pip.nrao.edu/repository/casa-test-wheel/packages/casatasks/6.2.0.100/casatasks-6.2.0.100-py3-none-any.whl
wget https://casa-pip.nrao.edu/repository/casa-aux-wheel/packages/casadata/2021.4.5/casadata-2021.4.5-py3-none-any.whl
pip install casatools-6.2.0.100-cp37-cp37m-manylinux2010_x86_64.whl
pip install casatasks-6.2.0.100-py3-none-any.whl
pip install casadata-2021.4.5-py3-none-any.whl
```

[^4]: マイナー以下のバージョンの違いは筆者は良く分かりませんでした…

## Operation check

以上のインストール方法を書いた[公式のノートブックのコピー](https://colab.research.google.com/gist/astropenguin/d30e10bbe8239ebd54767a148bfd8bf1/casa6-2_demo.ipynb)を作成しました。実行したところ、少なくともノートブックの内容（listobs, tclean, exportfits）は動作することが確認できました。

## References

- [CASA: Common Astronomy Software Applications](https://casa.nrao.edu/)
- [Obtaining and Installing — CASA Documentation](https://casa.nrao.edu/casadocs/casa-6.1.0/usingcasa/obtaining-and-installing)
- [CASA6_demo.ipynb (CASA official)](https://colab.research.google.com/github/casangi/examples/blob/master/casa6/CASA6_demo.ipynb)
- [CASA6.2_demo.ipynb (Made by the author)](https://colab.research.google.com/gist/astropenguin/d30e10bbe8239ebd54767a148bfd8bf1/casa6-2_demo.ipynb)
CABasicAnimationで色のアニメーションがうまく行かないときの対処法

アニメーション結果を保持するために[CAAnimation.isRemovedOnCompletion](https://developer.apple.com/documentation/quartzcore/caanimation/1412458-isremovedoncompletion)をtrueにするべきではない。
参考: [How to not use isRemovedOnCompletion for CAAnimation in iOS](https://onmyway133.com/posts/how-to-not-use-isremovedoncompletion-for-caanimation-in-ios/)

fillColorやstrokeColorを変更すると暗黙的アニメーション([implicit animation](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html))が発生するため、[CATransaction.setDisableActions(_:)](https://developer.apple.com/documentation/quartzcore/catransaction/1448261-setdisableactions)を使用して暗黙的アニメーションを無効化してfillColorやstrokeColorを変更する必要がある。

```CATransaction+Extensions.swift
import QuartzCore

extension CATransaction {
    /// 暗黙的アニメーション(implicit animations)が適用される変更をアニメーションなしで行うためのメソッド
    ///
    /// https://stackoverflow.com/a/54784013
    static func disableAnimations(_ completion: () -> Void) {
        CATransaction.begin()
        CATransaction.setDisableActions(true)
        completion()
        CATransaction.commit()
    }
}
```

```example.swift
func animate() {
    let nextColor = UIColor.red.cgColor
    let animation = CABasicAnimation(keyPath: "fillColor")
    animation.fromValue = shapeLayer.fillColor
    animation.toValue = nextColor
    animation.duration = 2.0
    layer.add(animation, forKey: animation.keyPath)
    // アニメーションさせた後の状態を指定する
    // 自前のアニメーションが無効化されないようにfillColorやstrokeColorの暗黙的アニメーションを無効化して色を変更する
    CATransaction.disableAnimations {
        self.layer.fillColor = nextColor
    }
}
```
LinuC合格用 1週間でLPICの基礎が学べる本 5日目まとめ

## 5日目まとめ-シェル、入力、出力

![5日目まとめ-シェル、入力、出力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1124047/22d59489-d566-460c-e7db-b51d38349841.png)

```bash:前提
bash-3.2$ ls
AAA
```

```bash:通常のコマンド実行
bash-3.2$ cat AAA BBB
hoge
cat: BBB: No such file or directory
```

```bash:リダイレクト
bash-3.2$ cat AAA BBB > out.txt
cat: BBB: No such file or directory
bash-3.2$ cat out.txt 
hoge
```

```bash:リダイレクト2
bash-3.2$ cat AAA BBB 2> error.txt
hoge
bash-3.2$ cat error.txt 
cat: BBB: No such file or directory
```

```bash:パイプ
bash-3.2$ cat AAA BBB|cat
cat: BBB: No such file or directory
hoge
```

# シェルスクリプトと環境変数、シェル変数
![5日目まとめ-環境変数とシェル変数のスコープ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1124047/a7fa96dd-2a59-4ba7-22bc-bfdbffdccd58.png)


```bash:環境変数
bash-3.2$ printenv|nl
     1	TERM_PROGRAM=Apple_Terminal
（省略）
    18	OLDPWD=/Users/nekonisi

bash-3.2$ env|nl
     1	TERM_PROGRAM=Apple_Terminal
（省略）
    18	OLDPWD=/Users/nekonisi
```

```bash:シェル変数+環境変数
bash-3.2$ set|nl
     1	BASH=/bin/bash
（省略）
    48	_=
```

```bash:子プロセスへの引き継ぎ
bash-3.2$ hoge="test"
bash-3.2$ export fuga="test2"
bash-3.2$ echo $hoge
test
bash-3.2$ echo $fuga
test2
bash-3.2$ bash

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ echo $hoge

bash-3.2$ echo $fuga
test2
```

```bash:シェルスクリプトのシェル変数の引き継ぎ
bash-3.2$ cat test.sh 
#!/bin/bash
echo $hoge
bash-3.2$ hoge='hogeeee'
bash-3.2$ bash test.sh 

bash-3.2$ source test.sh 
hogeeee
bash-3.2$ ./test.sh
bash: ./test.sh: Permission denied
bash-3.2$ chmod +x test.sh 
bash-3.2$ ./test.sh
bash-3.2$ echo $?
0
```
PHP $_SERVERについて　〜さらに詳しく〜

#$_SERVER['オプション'] の各オプションについてのメモ
phpのドキュメントをいくら見てもイマイチわからない上記についてMAMPのlocalhost環境で実行してみた
過去まとめた方の記事は以下
 [$_SERVERについて（過去記事）](https://qiita.com/H-Toshi/items/930168cd904874d41401)
例）

```php

<pre>
<?php print_r($_SERVER); ?>
</pre>


<?php 
//上記をブラウザ（chrome）で表示した結果（MAMPローカル環境）
//ドキュメントルート : Applications ▹ MAMP ▹ htdocs
//実行したファイル: htdocs/test2/server.php

Array
(
    [HTTP_HOST] => localhost
    [HTTP_CONNECTION] => keep-alive
    [HTTP_CACHE_CONTROL] => max-age=0
    [HTTP_SEC_CH_UA] => "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"
    [HTTP_SEC_CH_UA_MOBILE] => ?0
    [HTTP_UPGRADE_INSECURE_REQUESTS] => 1
    [HTTP_USER_AGENT] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/500.30 (KHTML, like Gecko) Chrome/89.0.000.000 Safari/500.300//Webページを取得したWebブラウザ（ここの数値は変えています）
    [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    [HTTP_SEC_FETCH_SITE] => same-origin
    [HTTP_SEC_FETCH_MODE] => navigate
    [HTTP_SEC_FETCH_USER] => ?1
    [HTTP_SEC_FETCH_DEST] => document
    [HTTP_REFERER] => http://localhost/test2/
    [HTTP_ACCEPT_ENCODING] => gzip, deflate, br
    [HTTP_ACCEPT_LANGUAGE] => ja,en-US;q=0.9,en;q=0.8
    [PATH] => /usr/bin:/bin:/usr/sbin:/sbin
    [SERVER_SIGNATURE] => 
    [SERVER_SOFTWARE] => Apache/2.4.46 (Unix) OpenSSL/1.0.2u PHP/7.4.12 mod_wsgi/3.5 Python/2.7.13 mod_fastcgi/mod_fastcgi-SNAP-09***** mod_perl/2.0.11 Perl/v5.30.1
    [SERVER_NAME] => localhost //PHPが実行されているWebサーバーの名前
    [SERVER_ADDR] => ::1 //現在のスクリプトが実行されているWebサーバーのIPアドレス
    [SERVER_PORT] => 80 
    [REMOTE_ADDR] => ::1 ///WebサーバーにリクエストするユーザーのIPアドレス
    [DOCUMENT_ROOT] => /Applications/MAMP/htdocs
    [REQUEST_SCHEME] => http
    [CONTEXT_PREFIX] => 
    [CONTEXT_DOCUMENT_ROOT] => /Applications/MAMP/htdocs
    [SERVER_ADMIN] => ***@example.com
    [SCRIPT_FILENAME] => /Applications/MAMP/htdocs/test2/server.php
    [REMOTE_PORT] => 64000 //Webサーバーとの通信に使用されるポート番号（ここの数字は変えています）
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    [QUERY_STRING] => 
    [REQUEST_URI] => /test2/server.php
    [SCRIPT_NAME] => /test2/server.php //スクリプトのパス名
    [PHP_SELF] => /test2/server.php //Webサーバーに要求するURLのパス名　（スクリプトのパス名のみを利用する場合は、SCRIPT_NAMEの使用が推奨される
    [REQUEST_TIME_FLOAT] => 1617555.3926 //ここの数字は変えています
    [REQUEST_TIME] => 1617555 //REQUEST_TIME_FLOATの整数部分 
    [argv] => Array
        (
        )

    [argc] => 0
)

//上記に表示されていない主要なオプション
[REMOTE_HOST]//現在のページにアクセスしているホスト名。DNS の逆引き検索は ユーザーの REMOTE_ADDR に基づいています。
[REMOTE_USER]//Web認証されたユーザーの名前
```
各名称についての詳細はドキュメントや以下のサイトが役に立ちました。

 [PHPドキュメント](https://www.php.net/manual/ja/reserved.variables.server.php)
 [PHP($_SERVER)サーバー変数一覧と実用例（各ファイルについてまとまっているサイト様）](https://www.flatflag.nir87.com/server-358)
AWSクラウドプラクティショナー試験計画

#受験日
社会人二年目に突入して、仕事にも慣れてきました。
9月に少し比重の重たい仕事が入ってるので、それ以前の8月お盆前あたりに取りたいな…
ということでざっくり8月上旬とします。

#出題分野
###クラウドの概念
1.1 AWS クラウドの概念とその価値提案について説明する
1.2 AWS クラウドエコノミクスの特徴を説明する
1.3 多種多様なクラウドアーキテクチャの設計原理を定義する

###セキュリティ及びコンプライアンス
2.1 AWS の責任共有モデルについて理解する
2.2 AWS クラウドのセキュリティとコンプライアンスに関するコンセプトを理解する
2.3 AWS のアクセス管理機能を特定する
2.4 セキュリティサポートのリソースを特定する

###テクノロジー
3.1 AWS クラウドにおけるデプロイと運用の方法を理解する
3.2 AWS のグローバルインフラストラクチャについて理解する
3.3 AWS の主要なサービスを識別する
3.4 テクノロジーサポートのリソースを特定する

###請求と料金
4.1 AWS のさまざまな料金モデルを比較対照する
4.2 AWS 請求と料金に関連した多様なアカウント構造を認識する
4.3 請求サポートに利用できるリソースを特定する

#予定と心の声
なるほど…試験まで四か月あるけどざっくりな予定としては、3か月で全分野7割程度把握して、残り一か月で演習問題かな…
自分の勉強法としては小項目ごとに問題解いてちょっとわかった気になって次に進みたいナ
方針が決まったらそこについても調べてみます

一か月で1.1分野か…どうなんだろうか
一日一時間で土日は何も考えず休みたいので20日出社で、一日1時間だとしたら…

なるほど80時間

でもネットのみんなは一週間とかでとってる人たくさんだし
甘えかなって思ったけど勉強しなきゃいけないことはたくさんあるので
ゆっくりやっていこう（記憶の定着が不安だけど…若いから大丈夫でしょう）

ざっくりこんなんでいいと思います。

#勉強方法
30分インプットして30分アウトプットって感じでいいかなあ
アウトプットはココにメモってみよう

理解するということは人にすべて説明できることだ

っていうのを聞いたことがあるのでそこを座右の銘的な感じで意識しながら勉強をしよう。

参考書は本かkindleかは未定

とりあえず思い立ったら吉日。今日から本格的に開始してみます。
テスト技法の社内勉強会に参加した。(ソフトウェアテスト技法練習帳 1-1-1)

# ソフトウェアテスト技法練習帳の１問目を解きました！


問題文はもう少し長いですが、[書籍](https://www.amazon.co.jp/dp/429711061X/ref=cm_sw_em_r_mt_dp_7YHFB0V55J48RVMH1QHA)より一部転載いたします。

教科書は [ソフトウェアテスト技法練習帳 ~知識を経験に変える40問](https://www.amazon.co.jp/dp/429711061X/ref=cm_sw_em_r_mt_dp_7YHFB0V55J48RVMH1QHA)を利用しました。


## 問題
このメッセージのテストケースを同値分割法と境界値分析を使って作成するというものです。

|No|室温|表示メッセージ|
|---|---|---|
|1|24.0℃未満|寒い|
|2|24.0℃以上26.0℃未満|快適|
|3|26.0℃以上|暑い|



# 自分の回答

|温度|表示|
|---|---|
|23.9|寒い|
|24.0|快適|
|25.9|快適|
|26.0|暑い|

もっとやってよければ

* 考えうるもっともおおきな値で寒いと暑いをひとつづつ追加する

もう少しへらしたいなら
24.0もしくは25.9を削除する

少なくとも　テキスト表示3種類を確認したい

## 疑問
* Unitテストとして書く場合はどこまで書く？
* 7つは多い気がするが、QA的には割と普通？

# 教科書の答え
* 境界値で4つ(境界値分析)
* 代表値を各ひとつ(同値分割法)
で合計7つ

# 同値分割法

[第4回　ブラックボックステスト：ソフトウェアテスト基本テクニック｜gihyo.jp … 技術評論社](https://gihyo.jp/dev/serial/01/tech_station/0004#:~:text=%E5%90%8C%E5%80%A4%E5%88%86%E5%89%B2%E6%B3%95%E3%81%A8%E3%81%AF,%E3%81%93%E3%81%A8%E3%81%8C%E9%81%BF%E3%81%91%E3%82%89%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)

同値分割法はテストを意味のあるグループ(同値クラス)に分類して代表値を選ぶ
* これによりテストケースの偏りと冗長を防ぐ
* 無効な値をして無効同値クラスという考え方がある
* 代表値はどこでもよいが「この値でテストが通ればその同値クラスは全部OK」という値を選ぶべきで、真ん中付近が確実(良いとされている？)

# 境界値分割法

境界の値をテストデータとして使う
* 経験的に境界付近でミスが生じる可能性が高いため
* 同値クラスを跨ぐ部分でテストする


両方やる時は境界値を使ったテストで代表値を使ったテストをOKとする考えもできる。
優先度は 境界値 > 代表値

# 勉強会で出た意見
* 代表値はユーザーがもっとも使いそうな値という観点で選ぶと良い。(後からバグが出た時に、この値はやってて当然だよねとなることがある)
* 今回だと例えば、東京の平均気温的になりやすい温度などで考えるなどもできる。


# 最後に
コメントやアドバイス等お待ちしてます！
Processing 3.x以降にGifを使う方法

**問題**
Processingの公式ライブラリにGifAnimationがあるが,3以降のバージョンだと使えない

**解決法**
Githubのページに3以降のバージョン用のライブラリファイルが使える
https://github.com/extrapixel/gif-animation/tree/3.0

使い方は３以前のバージョンと同じなので，GifAnimationを扱った記事を参考にする
M1 Mac に Homebrew をインストールして Firefox を入れて Qiita に記事を投稿するまで

macOS 向けのパッケージ管理システム [Homebrew](https://brew.sh/) ですが、

M1 MacBook でも、公式サイトの通り、普通にインストールできました。[^1]

[^1]: MacBook Pro (13-inch, M1, 2020)・macOS Big Sur（11.2.3, 20D91）

```
% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

ただ、途中 `Warning` が出て、

```
Warning: /opt/homebrew/bin is not in your PATH.
```

最後に、`Next steps` が示されます。

```
==> Next steps:
- Add Homebrew to your PATH in /Users/username/.zprofile:
    echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/username/.zprofile
    eval "$(/opt/homebrew/bin/brew shellenv)"
- Run `brew help` to get started
- Further documentation: 
    https://docs.brew.sh
```

前からこんな感じでしたっけ？

まぁ、何にせよ、とても親切ですね。素直に従いましょう。

```
% echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/username/.zprofile
```

これで、以後、ターミナルを（ ログインシェルとして zsh を ）起動した際には、brew コマンドが使えるようになっているはずです。

また、いま開いているターミナルで、すぐにでも利用したいなら、次のコマンドを実行します。

```
% eval "$(/opt/homebrew/bin/brew shellenv)"
```

さて、とりあえず、バージョンを確認したら、

```
% brew -v
Homebrew 3.0.11
Homebrew/homebrew-core (git revision 04991b279b; last commit 2021-04-09)
Homebrew/homebrew-cask (git revision eb393c5a3e; last commit 2021-04-09)
```

いよいよ、Firefox をインストールしていきましょう。

と言っても、次のコマンドを実行するだけです。実に簡単ですね！

```
% brew install --cask firefox
```

そして、こちらも、バージョンを確認したら、

```
% brew list --cask --versions
firefox 87.0
```

起動して、Qiita にログインし、記事を書いて投稿しましょう！

というわけで、これが、M1 Mac から投稿する、記念すべき「 最初の記事 」になるのですが、

まだ Apple Silicon に対応していない（ ネイティブ動作がサポートされていない ）ソフトウェアも多いようなので、これから、少しずつ確認していきたいと思います。
【New Relic】CloudWatch Metric Streamsをマルチリージョンに設定する

# 概要
マルチリージョン構成におけるCloudWatch Metric Streamsの設定について。

# CloudWatch Metric Streamsについて
CloudWatch Metric Streamsは、CloudWatchメトリクスの情報を外からポーリングして取得するのではなく、AWS側からプッシュするような形でストリームさせる機能。
AWS Blog : https://aws.amazon.com/jp/blogs/aws/cloudwatch-metric-streams-send-aws-metrics-to-partners-and-to-your-apps-in-real-time/ 

New Relicも対応しており、通常のポーリング形式よりも早くメトリクス情報が反映されるため、Violationも素早く検知される。

New Relic Blog : https://blog.newrelic.com/product-news/aws-cloudwatch-metric-streams/

# 構成
構成としては、

AWS [ Metric → Metric Stream → Kinesis Data Firehose ] → New Relic

という流れであるが、AWS側の各リソースはリージョンリソースである。

ポーリング形式の場合、IAMロール/ユーザーを通して取得されるため、グローバル単位でのメトリクス収集が可能であったが、CloudWatch Metric Streamsの場合は、リージョン単位でのメトリクス収集となる。

そのため、マルチリージョン構成のシステムのメトリクスを連携するにはそれぞれのリージョンにMetric Streamの設定をする必要がある。

New Relicのドキュメントにもその旨は記載されている。
>If you manage multiple regions within those accounts, then each region needs to be configured with a different Kinesis Data Firehose pointing to New Relic
>
https://docs.newrelic.com/docs/integrations/amazon-integrations/aws-integrations-list/aws-metric-stream/#map-accounts-regions

# マルチリージョンへの設定
## New Relic側
AWS Integrationの設定は、アカウントごとに1つで問題ない。リージョンごとにインテグレーションを設定する必要はない。

## AWS側
リージョンごとにCloudWatch Metric StreamsおよびKinesis Data Firehoseの設定が必要。

New Relic側の手順にもあるCloudFormationを使ったセットアップを利用する場合は、リージョンそれぞれにスタック作成を行う。
https://docs.newrelic.com/docs/integrations/amazon-integrations/aws-integrations-list/aws-metric-stream/#setup-cloudformation 

※ Kinesis Data Firehoseのエラーイベント保存のためのS3バケットはリージョンごとに分ける。その他の値は同じでOK。

## 確認
それぞれで設定ができていれば、New Relic側のAWS IntegrationのAccount Statusダッシュボードの「Total Metric by AWS Region」でリージョンごとの収集メトリクス数合計を確認できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/268448a6-b48d-5b28-debd-1b0b361efb41.png)

# まとめ
New Relicとの連携に限らず、CloudWatch Metric Streamsは各リージョンごとへの設定が必要ということが注意点。マルチリージョン 構成の場合は忘れずそれぞれに設定する。

New Relic側はリージョンごとに設定は特に必要ないので、形としてはシンプル。
ruby on rails での日時扱い方

#目次
<b>①タイムゾーンついて</b>
<b>②タイムゾーンをコンソールで確かめる</b>
<b>③自国の時間で表示する方法</b>



##①タイムゾーンついて
タイムゾーンとは、共通の時間を使うエリア一帯のことを指す。

日本で使われている時間は「日本標準時(JST)」と呼ばれており、世界の基準時刻である「グリニッジ標準時(GMT)」や「協定世界時(UTC)」と比較して+9時間の時差があるため、UTC+9やUTC+09:00などと表記される。

##②タイムゾーンをコンソールで確かめる
ここで実際にタイムゾーンをコンソール内で実感してみる。

```php:コンソール
irb(main):001:0> Time.zone
=> #<ActiveSupport::TimeZone:0x00007ff51de20800 @name="UTC", @utc_offset=nil, @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>>
```
上記のようにTime.zoneと打ち込むと、ActiveSupport::TimeZoneオブジェクトが返ってくる。
これはRailsが日時を扱う際に自動的に利用されるクラスのこと。
そしてタイムゾーンはUTCであることを示している。

次にTime.zone.nowで現在の時間を確かめてみる。

```php:コンソール
irb(main):002:0> Time.zone.now
=> Fri, 09 Apr 2021 04:25:40 UTC +00:00

```
この時間はUTCを基準としているので日本時間でが9時間ほど早い時刻が表示されている。

```php:コンソール

irb(main):003:0> Time.zone.now.class
=> ActiveSupport::TimeWithZone
```
ここでクラスのオブジェクトを確認する。
ActiveSupport::TimeZoneクラスのオブジェクトだということが分かる。これはTimeクラスに対して実行しているのに上記のように返されるのは、railsが自動的にクラスを変換していることによるもの。

##③railsで自国の時間で表示する方法
次にTime.zoneに"Asia/Tokyo"を代入すると日本の時刻になる。

```php:コンソール
irb(main):004:0> Time.zone = "Asia/Tokyo"
=> "Asia/Tokyo"
```
日本の時刻になっているかを確かめるには先ほどのTime.zone.nowを入力してみると

```php:コンソール
irb(main):005:0> Time.zone.now
=> Fri, 09 Apr 2021 13:27:01 JST +09:00
```
時刻が変わり、そしてUTCからJSTに変わっていることがわかる。

では、railsでは日本の時刻にするにはどうするのか？

config/application.rbファイル内で、config.time_zoneを"Asia/Tokyo"にすることで日本時刻になる。
日本で利用するアプリであれば、
config.time_zone = 'Asia/Tokyo'と設定しておけば良いことになる。
git push までの流れ

#はじめに

学習をしている中でgit をよく使用するのですが、少しごちゃごちゃして整理したいと考えていました。
そこで備忘録としてファイルを変更した時は必ず更新するための手順を振り返ります。

初学者のため、不足している箇所等ありましたらご指摘いただけると幸いです。


#１　現在のディレクトリにリポジトリを作成する。

```
$ git init 
```

init の後にディレクトリ名を加えれば、指定したディレクトリに対するリポジトリを作成する。

#２　コミットの対象となるコンテンツをステージングする

```
$ git add オプション
```
ステージングとはGitリポジトリにコミットするファイルを置いておくための作業。
Git管理の対象に入れるかでオプションが変化する。

#３　コミットする

```
$ git commit -m “日付など”
```

“”の中は任意だがコミットした内容がわかるような名前や日付等をつけると良い。

#４　ローカルリポジトリの内容をリモートリポジトリに反映する

```
$ git push origin main 
```

リモートリポジトリ Origin の main ブランチにコミットの内容を反映する。
これでリモートリポジトリにローカルでのファイル変更を反映できる。
[Swift]プロトコル（インターフェース）について

Swiftではインターフェースのことをプロトコルというらしい。

最近 TableViewについてソースコードをみていて気になったことがある。

tableView関数って何？これはなんなの？ってところ。
結論から言うと、tableView関数はUITableViewDataSourceで定義されている抽象メソッドだった。
だから、継承先で、関数を定義しないとエラーになる。
https://developer.apple.com/documentation/uikit/uitableviewdatasource
公式ドキュメントより

単純にreturnでInt型の数字を返しているだけだが、これがテーブルのセルの行数に反映される。
おそらく更にどこからかこの関数がよばれて値として戻り値がセットされるのだろう。

ちなみに、オーバーライドは関数の再定義であり、原稿の関数について内容そのものを上書きする。
プロトコルと若干似ているが、役割が違うので見間違えないように。。。

もっと細かく説明すると、

```swift
protocol UITableViewDataSource{
  func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
}
```

```swift
extension ChatListViewController: UITableViewDelegate,UITableViewDataSource{
    
     func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
```
UITableViewDataSourceプロトコルにはこんな感じで
func　関数名(引数) -> 戻り値

と言う感じで関数のみが定義されている。関数自体の中身がないため、それは継承先で
定義しろってこと、



**テストコード**

```swift
import UIKit

protocol SomeProtocol {
    var computedA: String { get }
    func methodA(_ str: String)
    func methodB(a: Int, b: Int) -> Int
}

class someClass {}

extension someClass: SomeProtocol {
    var computedA: String {
        return "a"
    }

    func methodA(_ str: String) {
        print(str)
    }

    <--func methodB(a: Int, b: Int) -> Int {
        return a+b
    } -->ここを消すとエラーになる。なぜならプロトコルの抽象クラスに含まれるmethodBを定義していないから
}

let s = someClass()

s.computedA  // a
s.methodA("hello world") // hello world
print(s.methodB(a: 2, b: 5) )// 7
```
【Node】npmstartすると、Something is already running on port 8080. Probably:と言われてしまう件【React】

<h2>症状</h2>
cloud9でnpmstartを一度実行した状態で誤ってターミナルを閉じてしまい、再度開きなおしてnpmstartをすると下記のような表示されるようになってしまいました。
翻訳すると、「何かがすでにポート8080で実行されています。おそらく：(中略)代わりに、別のポートでアプリを実行しますか？」

yを押すと、npmstartは動作するようにはなりますが、実行するたびに表示されるのはめんどくさいので解消します。

```
$ react-scripts build
Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

? Something is already running on port 8080. Probably:
  /home/ubuntu/.nvm/versions/node/v12.16.1/bin/node /home/ubuntu/environment/プロジェクト名/frontend/node_modules/react-scripts/scripts/start.js (pid 15133)
  in /home/ubuntu/environment/プロジェクト名/frontend

Would you like to run the app on another port instead? › (Y/n)
```

<h2>解決策</h2>
killコマンドでプロセスを停止させることで、同様のメッセージは表示されないようになりました。

```
#ポート番号は任意のものに変えて使用してください
npx kill-port 8080
```

<h2>参考</h2>
Node.js Port 3000 already in use but it actually isn't?
https://stackoverflow.com/questions/39322089/node-js-port-3000-already-in-use-but-it-actually-isnt
【Dr.Sum VTB】データソース、ODBCとOCI8を検証してみた

#経緯
こちらの記事↓に関して、ODBCよりOCI8の方が速いというコメントを頂きました。
[Dr.Sum VTBでOracleから直接データ取得、Dr.Sumへインポートする](https://qiita.com/ratsbane666/items/0046fc30aebad4504d62)
ちょうどいいことに、現在Dr.Sum本番サーバの引っ越し準備中で、Dr.Sum4.2と5.1ふたつの環境があります。実際にやって検証してみました。

#ODBCとOCI8、めっちゃざっくりな説明
ODBC： Microsoftが用意した、アプリケーションからデータベースに接続する仕組み。Open DataBase Connectivity
OCI8　: Oracleが用意した、アプリケーションからOracleDBに接続するためのもの
※OCI8=Oracle純正部品、ODBC=汎用的な部品ってイメージかな、私は

#注意
日中のためサーバは稼働中でユーザのアクセスがある＆諸々が動いているため、全く同じ状態での比較はできない。そのため厳密な検証とはいえない。参考程度にお願いします。

#実行結果
確かにOCI8のほうが全然速い！！さすが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278265/35b0d505-f4d7-60c5-a1c4-3772696a31ec.png)

#代替案がすぐ出せることは大事
ユーザコミュニティnestにこちらの記事を共有した際、以下のようなご意見を頂きました。
まことにその通りと思います。
・速さもあるが、OCIの方が安定している
・ODBC/OCI8どちらを使うかは案件状況次第になり「正解」は断言しづらい
・問題が起きたときに代替案があることはとても重要

#ウイングアークのユーザコミュニティ「nest」
私も参加しています。多くの有益な情報があり、交流があります。
世の中が変わり、社外活動の重要性がより増していると考えております。
社外で自分の価値を計れるものさしを持とう。

https://www.wingarc.com/wug-nest/

以上
【就活用】面接で聞かれた質問一覧集

#本記事の概要
プログラミング未経験からエンジニアを目指し転職活動をしておりました。

面接44社経験をし、面接で聞かれた質問集を記事にしてみました。

今後転職活動される方、今転職活動されている方にお勧めの記事となっています。

予め質問内容を想定し、準備しておくことは面接を突破する上で重要になってくるかと思います。

#目次
・面接でほぼ毎回と言っていいほど、多く聞かれた定番質問
・エンジニアになることに対しての質問
・プログラミングの勉強方法についての質問
・ポートフォリオについての質問
・前職における質問
・学生時代の質問
・他選考状況についての質問
・内の企業どのくらい知っているの質問
・パーソナルな質問
・技術的な質問
・クリティカル質問
・逆質問

#面接で聞かれた質問一覧集
##面接でほぼ毎回と言っていいほど、多く聞かれた定番質問
・志望理由
・自己紹介
・転職の理由
・どういうエンジニアになりたいのか
・なぜエンジニアなのか
・転職軸は何か

##エンジニアになることに対しての質問
・エンジニアになろう思ったきっかけ
・なぜエンジニアなのか
・どういうエンジニアになっていきたいのか
・ゆくゆくはどういうサービスを作りたいのか
・エンジニアとしての中長期目標
・エンジニアとしての1年後、3年後、5年後、10年後のキャリアプラン
・ペルソナ像を描くのに大切なこと3つ
・弊社でどういうことを活かせれるのか
・弊社で何がしたいですか。
・エンジニアとしての求められることは何でしょうか
・あなたはエンジニアに向いていると思いますか
・いつからエンジニアになりたいと思ったのか
・なぜ自社開発企業で働きたいのか
・なぜ受託開発企業で働きたいのか
・なぜSESとして働きたいのか
・コーディングは好きなことなのか
・1日どれくらいコーディングをするのか
・なぜ長時間コーディングができるのか
・プログラミングのどこが好きなのか

##プログラミングの勉強方法についての質問
・勉強が必要になるが問題ないか
・勉強で使っている言語について
・勉強方法はどのようにしているか
・スクールに通っている or　独学
・学習していて苦労した点
・プログラミングが楽しいと思ったときはどんな時か
・注目されている技術について
・注目されているサービスについて
・注目されているサービスの改善点について
・使用している言語以外に注目している言語はあるのか

##ポートフォリオについての質問
・アプリを開発した経緯
・なぜそのアプリを開発したのか
・自分１人で開発したのか、それともチームで開発したのか
・アプリ開発で苦労した点
・アプリ開発で工夫した点
・そのアプリを開発するのになぜその言語を使ったのか
・そのアプリのペルソナ像は
・テストユーザーはいるのか
・オリジナルアプリはどのような思いがあり作成したのか

##前職における質問
・仕事を通じて得られたこと
・前職の仕事内容の説明
・前職での失敗について
・岐路に立った時に大切にしている価値とは
・岐路に立った時に対相手として決め手となる価値とは
・仕事をする上で大切にしていたこと
・前職を辞めた理由
・前職での仕事のやりがい
・前職で苦労した点、どのようにその苦労を乗り越えたか
・前職での成果
・前職での成果を3つ答えよ
・成果を出したことについてなぜそれを行ったのか
・成果を出したことについてなぜそこに着目したのか
・苦手な人との付き合い方
・チームで仕事することの難しさはどういうところか
・前職でプログラミングをしていたのか
・新卒の時にエンジニアになろうと思わなかったのか
・自身が受けた理不尽や自分が合わない人との接し方
・リーダー的な役職あることはやっていたのか
・仕事で一番印象に残っていること

##学生時代の質問
・なぜその大学に入ったのか
・大学時代の成果は
・部活は何をしていたのか
・部活の成績について
・部活でのポジションについて

##他選考状況についての質問
・他の応募状況について
・何社くらい受けられて、これから何社くらい受けるのか
・内定はもらっているか
・正直未経験としての転職活動はどうですか
・なぜ他企業の内定を辞められたのか
・転職軸について
・弊社の1次面接の印象
・他どのような企業を見ているのですか

##内の企業どのくらい知っているの質問
・企業ページ見られましたか
・弊社のどういうところに興味がありますか
・企業理念に共感できたなら、何かそういう経験はあるのですか
・弊社のサービスの内どれが好き
・弊社のサービスの改善点

##パーソナルな質問
・お住まいはどちら
・自己紹介
・自己紹介と自己PRをわけてしてください
・自身の経歴の中で自己の強みとなること
・経歴について
・周りからの評価、周りから何と思われているか
・ストレス発散方法
・休日の過ごし方
・いつから働けるか
・エンジニア以外のライフ面でどうなりたいのか
・エンジニア以外の人としてのキャリアプラン
・独立願望はありますか
・長所と短所
・給料かなり下がるけど大丈夫か
・勤務地について問題ないか
・転職を機に引っ越しますか
・好きなことは何か。
・なぜTwitterでやQiitaで発信するのか
・〜さんはどんな人ですか
・会社に求めることは何か
・就職するところの基準は何か
・〜さんの苦手なこと
・趣味は何ですか
・なぜその趣味が好きなのですか

##技術的な質問
・Linuxコマンドについてどれくらいの知識はあるのか
・データベース設計はしたことがあるのか。
・サーバーサイドの知識はどれくらいあるのか
・RubyにてGemfileを見せるから、そのGemの説明をして
・Gitを使ってチーム開発はあるのか

##クリティカル質問
・私を褒めてください
・世の中に向けてどういうことがしたいか
・正直内で働きたいですか （= 志望動機についての質問）

##逆質問
・業務内容の逆質問
・全体を通しての逆質問

#私の活動経歴
よろしければ、以下よりご覧ください。

https://qiita.com/narimiya/items/b59db099b923b0b88330

以上です。
サポート終了する AWS Lambda Python2.7 の関数をリストアップ(全リージョン版) +追記: ruby2.5 nodejs10.x



[公式ブログ](https://aws.amazon.com/jp/blogs/compute/announcing-end-of-support-for-python-2-7-in-aws-lambda/) でも案内されている通り 2021年7月15 日に AWS Lambda での Python 2.7 サポートが終了予定です。

このブログの中で
Python 2.7 のLambdaをリストアップするaws cliコマンドを提示してくれています

```shell:
aws lambda list-functions --output text --query "Functions[?Runtime=='python2.7'].FunctionArn"
```

例えばap-northeast-1を対象にすると、こんな感じで出力される

```
arn:aws:lambda:ap-northeast-1:111111111111:function:xxxxx
arn:aws:lambda:ap-northeast-1:111111111111:function:yyyyy
```

*追記*
ruby2.5 と nodejs10.x も2021年7月30日にサポート終了フェーズ１を迎えるので対象ランタイムを引数で指定するバージョンも後半に追記しました。

# 全リージョン版

リージョンを横断してリストアップしたいので、上記を全リージョンで回すシェルスクリプトを書きました。

```shell:list-py27functions.sh
for region in `aws ec2 describe-regions --query "Regions[].RegionName" --region us-west-1 --output text`
do
    echo "[${region}]"
    aws lambda list-functions --region ${region} --output text --query "Functions[?Runtime=='python2.7'].{ARN:FunctionArn, Runtime:Runtime}"
done
echo "finished"
```


## Usage

```shell:
export AWS_PROFILE=xxxx # デフォルトプロファイルを常に設定しているなら不要
sh list-py27functions.sh
```
プロファイルを指定する以外に、権限を持っているユーザーでマネコンにログインしてCloudShellから打つという使い方もできます。

こんな感じで出力します。

```
[eu-north-1]
[ap-south-1]
[eu-west-3]
[eu-west-2]
[eu-west-1]
[ap-northeast-3]
[ap-northeast-2]
[ap-northeast-1]
arn:aws:lambda:ap-northeast-1:111111111111:function:xxxxx	python2.7
arn:aws:lambda:ap-northeast-1:111111111111:function:yyyyy	python2.7
[ca-central-1]
[ap-east-1]
[ap-southeast-1]
[ap-southeast-2]
[eu-central-1]
[us-east-1]
arn:aws:lambda:us-east-1:111111111111:function:test	python2.7
[us-east-2]
[us-west-1]
[us-west-2]
arn:aws:lambda:us-west-2:111111111111:function:zzzz	python2.7
finished
```

# 対象ランタイムを引数で指定するバージョン

```shell:list-functions.sh
for region in `aws ec2 describe-regions --query "Regions[].RegionName" --region us-west-1 --output text`
do
    echo "[${region}]"
    aws lambda list-functions --region ${region} --output text --query "Functions[?Runtime=='$1'].{ARN:FunctionArn, Runtime:Runtime}"
done
echo "finished"
```

## サンプル

```shell:
sh list-lambda-functions.sh nodejs10.x
sh list-lambda-functions.sh ruby2.5
```

引数で渡すランタイム名を間違えると、ちゃんとリストアップされないので注意ください。

# 参考
[公式ブログ::Announcing end of support for Python 2.7 in AWS Lambda](https://aws.amazon.com/jp/blogs/compute/announcing-end-of-support-for-python-2-7-in-aws-lambda/)
[AWS Lambda::ランタイムサポートポリシー](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtime-support-policy.html)
[AWS CLI::list-functions](https://docs.aws.amazon.com/cli/latest/reference/lambda/list-functions.html)
[AWS CLI::describe-regions](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-regions.html)
[AWS CLI::出力をフィルタリングする](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-usage-filter.html)
[javascript] ダブルタップでブラウザが拡大するのを防ぐ

```user-scalable=no``` はiPhoneでは無効になっているらしいですね。知りませんでした。。


```onload()``` などに

```
document.addEventListener("dblclick", function(e){ e.preventDefault();}, { passive: false });
```
を入れておくことでダブルタップ（で画面が拡大するの）を無効にできます。
[Swift] URLから特定のクエリパラメータを除去するextension

表題のような処理がしたくて、URLのextensionを作ってみました。

たぶん、あまり需要はないと思うのですが。笑

環境：
Xcode 12.1 / Swift 5.3

```swift:playground
import Foundation

extension URL {
    /// URLからクエリパラメータを除去する
    /// - Parameter name: パラメータ名
    /// - Returns: 新しいURLオブジェクト
    func removeQueryItem(_ name: String) -> URL? {
        guard var component = URLComponents(url: self, resolvingAgainstBaseURL: false) else {
            return nil
        }
        component.queryItems = component.queryItems?.compactMap { item -> URLQueryItem? in
            return item.name == name ? nil : item
        }
        if let queryItems = component.queryItems, queryItems.isEmpty {
            component.queryItems = nil
        }
        return component.url
    }
}

// 使い方
// クエリパラメータ"foo"を削除
let url_1 = URL(string: "https://qiita.com/search?q=swift&foo=bar")
print("\(url_1!.removeQueryItem("foo")!.absoluteString)")
// https://qiita.com/search?q=swift

// アンカーがある場合
let url_2 = URL(string: "https://qiita.com/y-some/items/200db9ac37150effc8ed?foo=var#swift")
print("\(url_2!.removeQueryItem("foo")!.absoluteString)")
// https://qiita.com/y-some/items/200db9ac37150effc8ed#swift

// クエリパラメータがない場合（何もしない）
let url_3 = URL(string: "https://qiita.com/")
print("\(url_3!.removeQueryItem("foo")!.absoluteString)")
// https://qiita.com/
```
RSA暗号で暗号化，復号できることの証明

# RSA暗号 なぜ暗号化，復号できるか

* もはや枯れた技術といってもよいRSA暗号ですが，そもそも何故異なる鍵(公開鍵，秘密鍵)で暗号化，復号ができるのか気になります。
* そこで私なりに証明を与えました。
* しかしこの内容が確実に正しいことであるかどうかは保証しかねますので，その点はご了承ください。

## 証明について

### 前提

|鍵の種類|値|
|---|---|
|共通鍵|$e$および$N$|
|秘密鍵|$d$および$N$|

* ただし$d,e,N$は以下のように決める。
  * $p,q$を素数とし，$N=p \times q$とする。
  * $L$を$(p-1),(q-1)$の最小公倍数とする。
  * $e \times d \equiv 1 (mod\ L)$となる2つの自然数e,dを巧く取る。
  * 通常eは65537とする。

* 暗号化対象のデータをMとすると，暗号化，復号は以下の式で実施する。
  * 暗号化 $C \equiv M^{e} (mod\ N)$
  * 復号 $M  \equiv C^{d} (mod\ N)$


### 証明

* 証明は以下の通りです。
* Qiitaで対応していない数式を使う都合上すべて画像になっています。

![RSA暗号が実現可能であることの証明_ページ_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209750/cfbced8c-a1b9-dbff-469c-59bc2dded139.png)
![RSA暗号が実現可能であることの証明_ページ_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209750/71706b52-477a-3aee-6fa4-0de726d14d4f.png)

## 具体例

* 直観的にわかるように図で説明すると以下のようになります。

* $p=3,q=11$とする。
* $Lはp-1=2,q-1=10$の2つの最小公倍数なので$L=10$。
* $N=p \times q=33$となる。
* $e=3$とすると，$e \times d = L \times k + 1(k \in \mathbb{N})$を満たせばよいので，仮に$k=2$とする。
* $e \times d = 21$となる数値を考えると，$d=7$となる。

* $p=3,q=11,L=10,N=33,e=3,d=7$というパラメータから1から17のデータに対して21乗までのべき乗を計算。ただし計算結果は$33(=N)$で割った余り。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209750/a3e25f27-4545-866f-9912-7ceca0b444f1.png)

* 吹き出しや枠線で多少見えない数値がありますが、ご了承ください。
* 実際のRSA暗号では$N=p \times q$は300桁程度の数値、$e=65537$を使うためこのような小さな数値ではない。

## 補足

* 証明自体は既存の定理を駆使するので，特に面白みのない技巧的なものです。
* メルセンヌ・ツイスターやAESのほうが数学としては面白いと思います。
* 以前RSA暗号について図を駆使したわかりやすい解説があったのですが，失われてしまったようです。
ポートフォリオサイトを作ってみました

表題にもあります通り今後成果物を作った際に載せるためのサイトを作成してみました！
![portfolio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1233228/5d2fc940-36b2-4ef6-136e-ba7c9284d699.png)
![スクリーンショット 2021-04-09 11.10.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1233228/84d78fe8-0dc0-57ea-aaad-7da8b5fd2b15.png)
![スクリーンショット 2021-04-09 11.10.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1233228/a619e76f-fbb9-23dd-201e-07d4f391d805.png)

UIは添付写真のようになりました。

##作成過程①（デザイン作成）
UIを考えることから始めたのですが、これが思った以上に苦戦しました。
Figmaを使ってどんな色味にするか、どんな写真を使うかなどを考えては作って、作っては消してを繰り返した結果が添付写真のようなUIになりました。

##作成過程②（プログラミング）
ある程度UIが決まったらそこからどんどんプログラミングを書いていきました。
今回はフック（カスタムフック）、Context,サードパーティのライブラリ(react-hook-form)を使用すること、アトミックデザインを意識すること、Typescriptを導入すること、APIの使用することを目標にしていたので、それらを使えるような実装をしていきました。

##作成過程③（Amplifyでデプロイ）
初めてAmplifyでデプロイするのでまずはテストアプリでデプロイの流れを把握。テストアプリが問題なくデプロイできたので実際に今回のポートフォリオサイトをデプロイしたところ、まさかのコンソールに赤字が出ていることが発覚...。
ローカル環境では問題なく実装できていたので少し焦りましたが、よくよくエラーをみて見るとHTTPメソッドがサーバー側から拒否されている旨のエラーでした。原因は環境変数をAWS側で設定していないことだったので、そちらの設定をしたところエラーも解消して問題なくデプロイできていることを確認できました。


##作成を通じて感じたこと
typescriptを使うことで予期しない箇所でエラーが出たりして何が原因かなどを模索しながら作成したので、こちらのサイトの作成前よりもtypescriptへも理解が深まりました。また、reactの使ってみたかった機能などは実際に実装できたので、その点に関しては満足しています。
このサイトを実装していく中でエラーが何度も発生しましたが都度、公式ドキュメントやQiitaで調べたりしたので自己解決能力を飛躍的に伸ばすことができました。インプットだけでは曖昧な部分がアウトプットすることで整理できたりするので、プログラミングに関わらず何事も、『目標設定→目標達成に必要なインプット→アウトプット』は大切だと感じれました。なのでみなさまもぜひ何か作成・アウトプットしてみてください！


今回の作成を通じて改めて自分のイメージを可視化できるプログラミングはとても楽しいなと思いました！
React、Typescript、Amplify、デザインなどをさらに勉強して良いサービスを作れるように成長します！

関連記事もよければ見てみてください！

https://qiita.com/takeiin/items/31d13e17fcf1330cbbe1

https://qiita.com/takeiin/items/4a217a5be3402514b20f

https://qiita.com/takeiin/items/db1527741efa895943be

https://qiita.com/takeiin/items/7f187d1b848e8e8e46fd

https://qiita.com/takeiin/items/e9669ed391a2296a3623


参考記事・サイト

https://ja.reactjs.org/

https://react-hook-form.com/jp/

https://aws.amazon.com/jp/amplify/

https://qiita.com/rubytomato@github/items/5d9b6e184b615f974f28

https://qiita.com/MasanoriIwakura/items/a3b8c99226b4d302caf4
Go言語 asciiコードのintから文字に変換する方法(備忘録）

#asciiコードのintから文字に変換する方法
今回はint等で保存されているasciiコードから、実際の文字に変換する方法について記載します。

```
//このような変換を想定しています。
97 => a
```

今回はstring型で値を返します。

```
asciiInt := 97
asciiString = string(rune(asciiInt))
//asciiString = "a"
```

このように変換を行うことが出来ます。
Ajax通信とActionCableの違いに関して

Ajax通信(非同期通信)とAction Cableの違いがわからなかったので確認しました。初心者の自分がわかり易いように記載させていただきますのでご了承くださいませ。

### そもそも**(同期)通信**とは

リクエスト毎にブラウザが読み込みされる通信方法なので、環境次第でなかなかページが表示されないことがあったりもします。


### 一方、**非同期通信**は、
リクエストのたびにブラウザを読み込むのではなく、一部のみ更新される通信方法です。

私が利用しているものでは**Google map**や**LINE**なども非同期通信とのこと。

細かい仕組みは置いといて、webページをスムーズに利用ができるシステムってことですね。

### 本題です、
私が学習の中で先に習ったのは、JavaScriptを使った非同期通信の**Ajax**。

リクエストがルーティングによりコントローラーへ送られてレスポンスを返す流れの前にJavaScriptが間に入ることで、データの一部のみをスムーズにやりとり(かつ、HTMLを変更したり)してくれるものでした。

その後の学習で出てきたのが、通常のRails同様の記述とJavaScriptでスムーズな更新ができる**Action Cable**。

チャネルというサーバー側の仕組みを使うのですが、こちらもサーバーとクライアントの間にJavaScriptを含むチャネルのファイルを用意することで、処理を実行してくれます。

### 両者に違いはあるのか？

結論どちらでも同じ処理は可能だそうです！
主観ではありますが、Ajaxは処理の中で一部データのやりとりが必要な際の通信手段としてのイメージで、Action Cable(Websocket通信)はチャットなどリアルタイムでのやりとりを前提としたシステムを作る際に使うと良いのかなと感じました。


参考リンク
>[【Rails6.0】ActionCableを使用したライブチャットアプリを実装する手順を解説
](https://techtechmedia.com/action-cable-rails6/)
>[非同期通信の仕組みについて](https://qiita.com/okamoto_ryo/items/d8d9476490a27ad17f71#:~:text=%E9%9D%9E%E5%90%8C%E6%9C%9F%E9%80%9A%E4%BF%A1%E3%81%A8%E3%81%AF%E3%80%81%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF,%E9%80%9A%E4%BF%A1%E3%81%A8%E3%81%84%E3%81%86%E3%82%82%E3%81%AE%E3%81%8C%E3%81%82%E3%82%8B%E3%80%82)
VSCodeのショートカットキーに現在の日付を入力するキーを追加する。

▶解決したい事
エディタのVSCodeを使って📝作業ログを書いている時に、現在日付を記入したい時があります。

VSCodeのショートカットキーには現在日付を入力するキーが割当られていません。

▶解決方法
ショートカットキーの設定ファイル(keybindings.json)を変更し、Alt + ;のキー入力時に日付が挿入されるようにします。

＜作業手順＞
1. VSCodeを開いてキーボードショートカットを表示します。 
　 メニューのファイル > ユーザー設定 > キーボードショートカット(``Ctrl + K  Ctrl + S``)

2.右上のキーボードショートカットを開くをクリックします。
○参考情報

https://code.visualstudio.com/docs/getstarted/keybindings#_advanced-customization

3.keybindings.jsonに追記します。

```json:keybindings.json
/ 既定値を上書きするには、このファイル内にキー バインドを挿入します
[
  {
    "key": "alt+oem_plus",
    "command": "editor.action.insertSnippet",
    "when": "editorTextFocus",
    "args": {
      "snippet": "$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE"
    }
  }
]
```

エディタ画面でAlt + ; で現在日付が入力されます。

以上

---
◆参考情報

https://code.visualstudio.com/docs/getstarted/keybindings

https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables
【Node】npmstartしたら、ENOENT: no such file or directory, open '/home/ubuntu/package.json'と怒られた件【React】

<h2>症状</h2>
RailsAPIモードにReactを入れた構成をcloud9上でnpmstartで動かそうとしたとき、下記エラーコードで怒られてしまいました。
どうやら、package.jsonがないよと言われているようです。

```terminal:エラーメッセージ
(master) npm start
npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path /home/ubuntu/package.json
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, open '/home/ubuntu/package.json'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent 

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/ubuntu/.npm/_logs/2021-04-09T02_35_13_814Z-debug.log
```

ファイルを確認すると確かに/home/ubuntu/package.jsonには、該当のファイルがありませんでした。
その下位にある/home/ubuntu/プロジェクト名/frontendにはpackage.jsonがありました。

<h2>解決策</h2>
package.jsonがあるディレクトリのfrontendまで移動して、そこでnpmstartすることで正常にnpmstartすることができました。

```terminal:ディレクトリを移動して、npmstart
#package.jsonがあるディレクトリまで移動
cd frontend

npm start
```

ちなみに、「npm start」Nodeプロジェクトを実行という意味で、package.json の scripts.start に指定された内容を実行するとのこと。
今回のエラーは実行に必要なpackage.jsonファイルが見つからなかったため、怒っていたようです。

初歩的ではありましたが、npm initしてpackage.jsonがあるディレクトリでなければいけないことを改めて認識することができましｔ。

<h2>参考</h2>
プロジェクトを実行！npm startの使い方【初心者向け】
https://techacademy.jp/magazine/16393
Metabase環境構築(Windows10)～PostgreSQL接続

#Metabaseが使いたい
無料で使えるBIツールの「Metabase」を使いたいということで、!

Winsows10環境で環境構築、PostgreSQLに接続してみました。

#インストール～起動
###JDKインストール
JDKを以下のリンクよりインストールします。
https://jdk.java.net/archive/
私はOpenJDK 13.0.2をダウンロードしました。
ダウンロードしたzipファイルを適当な場所に展開します。
Cドライブ直下にmetabaseフォルダを作成し、その配下に展開しました。
<img width="500" alt="[metabase1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/910987/3c3e1153-a83e-0363-49d6-efa6ba060d97.png">


###Metabaseのjarファイルをダウンロード
以下のリンクよりjarファイルをダウンロードします。
https://www.metabase.com/start/oss/jar
ダウンロードしたjarファイルはJDKを展開したフォルダに配置します。
具体的にはC\metabaseですね。
![metabase2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/910987/f45d0ff4-1200-396d-d673-ed1833f1188d.png)

###Metabaseをインストール
コマンドプロンプトを管理者権限で立ち上げ、以下のコマンドを実行します。

```
$ cd C:\metabase\jdk-13.0.2\bin
$ java -jar C:\metabase\metabase.jar
```

勝手にインストールが始まりますので、落ち着くまで待ちます。

###Metabaseに接続！
C:\metabase\jdk-13.0.2\binに
・plugins
・metabase.db.mv.db
・metabase.db.trace.db
というフォルダとファイルができたことを確認し、
http://localhost:3000
にアクセスします。
Metabaseの登録画面が立ち上がればOKです！
あとは画面に従いましょう。
（どんな画面だったか忘れましたが特に難しいことはない気がします）

#データベースに接続
Metabaseに接続できましたので、次はDBを接続しましょう。
###PostgreSQLに接続
右上の歯車ボタンから「管理者」を選択すると管理者ページに移行します。
※初期登録時にもDB設定はできます。流れはほぼ同じはずです。
![2021-04-09_11h31_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/910987/c9ee4b16-555b-170c-71ba-edf71094e6db.png)

ヘッダの「データベース」もしくは「データベースを追加する」をクリックします。
![2021-04-09_11h38_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/910987/8ee80c3e-1c77-125a-73df-d08c6f4d1441.png)

データベース登録画面が出ますので、必要事項を記入します。
![2021-04-09_11h41_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/910987/03786e70-7644-4cda-9f13-73285dd8ca84.png)

下にスクロールして「保存」を押せば完了です！

#Metabaseでデータ分析を楽しむ
まだ少ししか使っていませんが、
無料でここまでのクオリティの分析ができるのはすごいです。
直感的な操作ができるので、楽しんでデータ分析ができると思います！

#参考URL
https://obenkyolab.com/?p=916
Automation 360　電子メールの取得方法

前から個人的に知っていましたし、POCでも使ったことはありますが、
Bot Editorユーザーインターフェース上でヒントが無い為、
どうやって内容を取得したらよいか、戸惑いますよね。
なので、こちらに残しておきます。

#メール取得用Botはこんな感じで組みます。

接続と接続解除の間に、ループを置いて利用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/9e1fdd6b-027e-478a-18da-c3dcc1f391fb.png)

（余談その１）
余談ですが、メール本文をファイルとして保存したり、添付ファイルを保存するアクションも、
このループの中において使用します。

#ここで問題

下記がループのプロパティですが、各メールの内容がディクショナリで戻ってくることになっています。
しかし、値を取得するためのキーがヒントとして記載されていないのです・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/502da8d7-8775-fe64-72fa-2cc3e4d52936.png)

#では、何がキーなのか？
下記がキーの一覧です。

| キー | 内容 |
|:-:|:-:|
| emailSubject  | 件名  |
| emailFrom | Fromアドレス  |
| emailTo  | Toアドレス  |
| emailCc  | CCアドレス  |
| emailBcc  | BCCアドレス  |
| emailMessage  | 本文  |
| emailReceivedTime  | 受信時間  |
| emailReceivedDate  | 受信日  |

一応、[製品ドキュメント](https://docs.automationanywhere.com/bundle/enterprise-v2019/page/enterprise-cloud/topics/aae-client/bot-creator/commands/cloud-using-email-properties.html)には書いてありますけど、ユーザーインターフェース上にも書いて欲しいですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615564/1692a79d-9e42-c9ba-5a77-66225002223c.png)

（余談その２）
メール受信は、着信イベントを利用したトリガーもありますが、
安定稼働の為には、スケジュールを利用した定期実行の方が良さそうです。
Firebase cloud functionsでFirestoreを更新する際に時間がかかる問題

#問題
Firestoreにユーザー情報を書き込んだら、それをトリガーにして認証情報を作成する処理を実装したところ、認証情報を作成した後のFirestoreの更新処理が妙に時間がかかる。コールドスタート時で2分30秒前後必要になっている。頻繁にユーザーをしないとはいえこれはまずい。
functionsのログを見る限り、認証情報の作成は数秒で終わっているのにその後のFirestoreの更新処理に2分以上かかっている。

#対策
##関数のメモリを増やす
ひとまずrunWithメソッドで実行時のメモリ量を1GBに増やす。Cloud functionsはメモリ量に応じて処理速度も上がるとのことなのだが、やってみたところあまり変化なし。

##更新先の参照の取得方法を変えてみる。
色々調べてみると、adminSDKのFirestoreは初期化に時間がかかるらしい。
snapshotから取得した参照に更新処理を行う際、毎回初期化しているのでは？と思い立った結果が以下のコード。
一度パスを取得してから、再度参照をつくる。

```typescript:index.ts
import admin from './components/firebase';

const db = admin.firestore();

export const created = functions
  .runWith(createEventTrrigerOption)
  .firestore.document('user/{uid}')
  .onCreate(
    async (
      snapshot: functions.firestore.QueryDocumentSnapshot,
      context: functions.EventContext
    ) => {
      const oparationType: string = 'ユーザー作成';
      console.log(`ユーザー新規作成処理:${context.params.uid}`);
      const data: FirebaseFirestore.DocumentData = snapshot.data();
      const uid: string = context.params.uid;
      // こうやって取ると後で書き込み処理をする時にfirestoreの読み込みが遅くなる。
      // const userRef: FirebaseFirestore.DocumentReference = snapshot.ref 
      // なので一度パスを取得してから参照を作る。
      const userPath: string = snapshot.ref.path;
      const userRef: FirebaseFirestore.DocumentReference = db.doc(userPath);
      // コメントアウトしている方法だとここで時間がかかる。
      userRef.update({hoge:huga})

    })
```

#結果
コールドスタート時で1分前後になりました。まだ遅いけれども一応速くなった。
理由がよくわからないので偉い人がいたら誰か教えてほしい。
M1 mac でGoogleDriveを使う暫定方法

# M1 Mac でgoogleDriveが使えない。涙
使いやすいM1 mac ですが、googleDriveが使えなくて悶々としていました。
googleもこの問題は認識していて、ベータ版で対応しますと宣言がありますが、まだ出ない、まだ出ない、とメイちゃんみたいに頑張って待っていたのですが、日々フラストレーションがたまる状態でした。

が、今日（2021.04.09）検索してみると、なんと暫定の回避手順が公開されているではありませんか〜！！


https://support.google.com/a/users/answer/10444081?p=apple-setup&visit_id=637535295681007886-3795714417&rd=1

こちら、のドキュメントを見ながら設定を入れたら、使える様になりました。

こちらが結果画面
![スクリーンショット 2021-04-09 11.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77002/101d1e2d-5022-082f-13b2-027984ad1a23.png)

いやー、めでたしめでたしです。

ただ、手順をやるのに、ドキドキしながら設定していました。
日本語翻訳がいまいちで、チェックボックスが2つチェック入れないとならない様で、そこははまりました。
たぶん、「ローカル管理」側だけチェック入れれば大丈夫なんだと思います。

低セキュリティモードになるので、皆様運用はご注意下さい。

googleや、appleの回し者ではないので、サポートなど出来ませんので皆さん自己責任で！
URLSessionで発生したエラーの特定と分岐

[Alamofile](https://github.com/Alamofire/Alamofire)や[APIKit](https://github.com/ishkawa/APIKit)の利用が普及しているのでURLSessionを直接利用する機会はあまりないかもしれませんが、たまにちょっと使いたい時がありエラーの分岐を調べたので残しておきます。

以下のように`Result<Success, Failure>`と組み合わせてAPIを利用する場合が多いと思いますが、URLSessionのタスクを実行した場合は、NSErrorで利用した場合の`domain`が[NSURLErrorDomain](https://developer.apple.com/documentation/foundation/nsurlerrordomain)に設定されているので、仮にどこかで共通処理をしている場合でも「これはネットワーク、もしくはローカルのリソースにアクセスした際のエラーなんだな」と判別することができます。

そして`code`はこのURLErrorDomainで起きうるエラーが[URL Loading System Error Codes](https://developer.apple.com/documentation/foundation/1508628-url_loading_system_error_codes)で列挙されているので、これを利用して分岐(if, if case, switchなど)を行うと、具体的なエラーハンドリングが記述できます。

例えば[NSURLErrorTimedOut](https://developer.apple.com/documentation/foundation/1508628-url_loading_system_error_codes/nsurlerrortimedout)が発生した際は下記のようなcompletionHandlerでUIレイヤに結果を返し、タイムアウトした際にユーザーに「通信状態が悪いです。あとで再度試してください。」などとアラート表示するのが最もポピュラーなハンドリングだと思います。

```swift
URLSession.shared.dataTask(with: urlRequest) { data, response, error in
    if let error = error {
        print("request failure: \(error)")
        let nsError = error as NSError
        switch nsError.code {
            case NSURLErrorTimedOut:
                completionHandler(.failure(.badNetwork(error)))
            default:
                // 標準の処理
                completionHandler(.failure(.requestFailure(error)))
        }
        return
    }

    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        completionHandler(.failure(.invalidStatusCode))
        return
    }

    print("API success", httpResponse)

    if let data = data {
        completionHandler(.success((data)))
    } else {
        completionHandler(.failure(.dataEmpty))
    }
}
.resume()
```
OAK-D　近距離深度計測精度を向上させる

#近距離深度計測精度
今回はdepth_demo.pyのサンプルコードを利用。

![E42AD5F8-CD4B-4BF5-8087-8F167F918694.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1040271/e389ef0e-ca4d-5630-55e2-bd07f12831dc.jpeg)


検出物体に対して背景が一定であればそこそこの精度がでました。
±3～5cm

標準は最小深度計測が70cmなので解像度を640x400に変更し最小深度計測は35cmへ
変更。これだけでは深度計測精度が出なかったので、背景を白に統一し上記の精度が
でました。



#より近い距離を認識できるようにする方法
※注：↓は参考URLのGoogle翻訳コピペです。

近接オブジェクトの奥行きの結果が奇妙に見える場合は、DepthAI / OAK-Dの最小奥行き知覚距離を下回っている可能性があります。

DepthAI車載カメラ（BW1098OBC）およびOAK-Dの場合、標準設定の最小深度は約70cmです。

これは、次のオプションで1/2と1/4にカットできます。

####1.解像度を標準の1280x800ではなく640x400に変更します。

96の視差検索が最小深度を制限するものであるため、これは最小深度が標準設定の1/2（70cmではなく35cm）になったことを意味します。サンプルスクリプトでこれを行うには、python3 depthai_demo.py -monor 400 -s Previewout metaout depth-bbを実行します。Gen1ソフトウェアでは、これが唯一のオプションです。しかし、Gen2では、ExtendedDisparityによってこの最小深度を1/2に減らすことができます。

####2.拡張視差を有効にします。

Gen2では、拡張視差がサポートされています。これにより、視差検索が標準の96ピクセルから192ピクセルに拡張され、最小深度が1/2になるため、BW1098OBC / OAK-Dの最小深度は1280x800の解像度で約19.6になります。 640x400の解像度の場合、cm（グレースケールカメラの焦点距離によって制限されます）。
詳しくは下記URLを参考ください。

より精度を高めるために勉強中です。

参考：https://docs.luxonis.com/en/latest/pages/faq/#extended-disparity-depth-mode