OmniAICreator/Qiita-1.07M huggingface dataset:
Azure Fundamentals(AZ-900)：Azure の基礎: Azure のアーキテクチャとサービスについて説明する「Azureのロールベースのアクセス制御」

Microsoft Learnを用いたMicrosoft Azure Fundamentals(AZ-900)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始める方の参考になれば幸いです。

## 今回の学習内容
**◆「Azureのロールベースのアクセス制御」**
◇対応するMicrosoft Learn ラーニングパス
[Azure の基礎: Azure のアーキテクチャとサービスについて説明する](https://learn.microsoft.com/ja-jp/training/paths/azure-fundamentals-describe-azure-architecture-services/)
◇対応するモジュール
[Azure のロールベースのアクセス制御について説明する](https://learn.microsoft.com/ja-jp/training/modules/describe-azure-identity-access-security/6-role-based-access-control)

※前回の投稿は下記から確認できます。
[Azure Fundamentals(AZ-900)：Azure の基礎: Azure のアーキテクチャとサービスについて説明する「Azureの条件付きアクセス」](https://qiita.com/fsd-jume/items/5c5d5dc86350cf3d3ea1)

## Azureのロールベースのアクセス制御(RBAC：Role Based Access Control)
**Azureリソースに対するアクセスの管理をロールベースで実施**
・ロールには実行可能なアクション(読み取り、書き込み、削除など)が定義されている
・一般的なアクセス規則が定義された組み込みのロールが既存で用意
・独自のロール定義(カスタムロール)も可能
・個人やグループを1つ以上のロールに割り当てることでロールに定義されたすべてのアクセス規則が付与
・新しい従業員にロールを割り当てるだけで、他の従業員と同じアクセス規則が付与
・割り当てたロールを修正するだけで、個人やグループのアクセス規則も修正

### スコープ(Scope)
**ロールが適用される範囲**
⇒どのリソースにアクセス規則を割り当てるのかを選択する

**◆指定可能なスコープレベル**
・管理グループ
・サブスクリプション
・リソースグループ
・リソース

**◆スコープにおける継承**
・親スコープのアクセス規則は、すべての子スコープに継承される
例)管理グループのスコープでユーザに所有者ロールを割り当てる
　→そのユーザはその管理グループ内のすべてのサブスクリプションのすべてのものを管理可能
※所有者ロール：ロールの割り当て権限やリソースへのフルアクセスが許可されたロール

### Azure RBACの適用
・Azureリソースに対するすべてのアクションにアクセス規則が適用される
・アプリ/データレベルではアクセス規則は適用されない
※アプリのセキュリティはアプリで処理する必要あり

### 複数のロール割り当て
・Azure RBACは許可モデルのため、複数のロールを割り当てた場合、それらのアクセス許可がすべて適用される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/e87e5a00-b65e-6aba-7144-57af2adfcf56.png)

## 次の学習内容
**◆ゼロトラストモデル**

https://qiita.com/fsd-jume/items/3a810aa99b01ac3e4731

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8
画面ロックとスクリーンセーバーの設定しようね

社内PCのセキュリティ対策を高めるためにアンチウィルスとは別のアプローチもやっていきたいと思います。

1.離席時の画面ロック操作の推奨
    席を離れる際は[Win]+[L]を押して画面ロックしてから離れる
	
2.スクリーンセーバーの設定(10分間無操作になった場合に起動)
	

a[何のためのセキュリティ対策なん？
b[それはな、ソーシャルエンジニアリングってやつを防ぎたいんだよ
a[ソーシャルエンジニアリングってなに？
b[パソコンを使わないでハッキングするんよ
a[ほーん、例えばどんなん？
b[簡単にいえば他人がパスワード打つのを盗み見たりとかかなー
a[画面映したままだと何が悪いん？
b[その画面を自分が席を離れてるときに内容見られたり勝手に操作されたりとかしていいの？
a[やだ:frowning2:
b[でしょ、だから触れないように画面ロックしちゃおうって話
a[なるるー、アンチウィルスとは違うんか
b[今回防ぎたいのはコンピュータウィルスじゃなくて、人の悪意だよ

a[ふーん、じゃあいい加減ログインパスワードとかもランダムにしたらどうなの？
b[うぅ…痛いとこ突いてくるなぁ…(人によってはログインパス変更してる)
b[そこまでいうなら、指紋認証とかIDカード認証とかそういうのも検討しなきゃかー

この会社の人たち、そういうの理解してもらえないだろうなー:sweat:
CI/CDについて ※解釈違っていたら是非コメント下さい、、！

# CI/CDとは？

- 開発手法の一つ
- 特定の技術を指すものではない

# CIとは？

- 和訳すると「継続的インテグレーション」
- 主な目的は「バグの早期発見」と「ソフトウェアの品質を高める」と「ソフトウェアの更新を検証してリリースするためにかかる時間を短縮する」
- 開発者のコミットをトリガーとして、自動でコードのビルド・静的解析・単体テスト（+デプロイ）などを行うことを指す。
- 上記のビルド・静的解析・単体テスト（+デプロイ）などの一連の動作をパイプラインと呼ぶ。

# CDとは？

- 和訳すると「継続的デリバリー」
- 「継続的デリバリー」は「継続的インテグレーション」を拡張したものという位置づけ。
- 「継続的デリバリー」と「継続的インテグレーション」の違いは、運用環境への更新（デプロイ）の手動承認の有無である。
    - 継続的デリバリー：手動承認無しで更新
    - 継続的インテグレーション：手動承認有りで更新
- 主な目的は「バグの早期発見」と「ソフトウェアの品質を高める」と「ソフトウェアの更新を検証してリリースするためにかかる時間を短縮する」に加え「ソフトウェアリリースプロセスの自動化」

# まとめ

- Github ActionsでPR作成された時に実行されるのはCIだと思われる。
- DevやStgやPrdに機能をリリース（デプロイ）される時に実行されるのはCDだと思われる（AWSでいうCodePipline + CodeDeploy）

# 参考文献

https://aws.amazon.com/jp/devops/continuous-integration/#:~:text=%E7%B6%99%E7%B6%9A%E7%9A%84%E3%82%A4%E3%83%B3%E3%83%86%E3%82%B0%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%E3%80%81%E9%96%8B%E7%99%BA,%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E3%81%AE%E6%89%8B%E6%B3%95%E3%81%A7%E3%81%99%E3%80%82

https://aws.amazon.com/jp/devops/continuous-delivery/#:~:text=%E7%B6%99%E7%B6%9A%E7%9A%84%E3%83%87%E3%83%AA%E3%83%90%E3%83%AA%E3%83%BC%E3%81%A8%E3%81%AF%E3%80%81%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E6%89%8B%E6%B3%95%E3%81%AE%201,%E3%81%95%E3%82%8C%E3%82%8B%E3%81%A8%E3%81%84%E3%81%86%E3%82%82%E3%81%AE%E3%81%A7%E3%81%99%E3%80%82
Mac OS Ventura をインストールしたら、Git がないと怒られる（command not found: git, xcrun: error: invalid active developer path）

# 解決方法
Mac OS Ventura をインストールしたら、`Git` がないと怒られました。

また、mac のアップデート時に以下のようなエラーが出る場合があります。
```
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
```

`xcode`が原因の場合らしく、以下のコマンドを入力して
`xcode`をインストールすると解決する場合があるようです。


~~~
$ xcode-select --install
~~~

私はこれで解決できました。

# 参考
https://www.apple.com/jp/newsroom/2022/10/macos-ventura-is-now-available/

https://qiita.com/ss_33_sss/items/7e026bbbc7e42db88da7
【初心者でも出来る】StudioXで自動化する際に必要なTips

StudioXでは、以下のこの5つの機能が使いこなせれば、自動化の制作は簡単です。（2022年10月28日現在）（StudioX　Ver2022.10.2対応）

StudioXの「デザイン」ウインドウのMainの中央に「ここにアクティビティをドロップ」の＋ボタンで検索、クリックしてそれぞれ開始する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/fa28c674-6e71-8342-a6cf-d72f0a078ce9.png)

1、アプリ/Webレコーダー（ボタン）
録画はLook&Feelで出来る。2022.10.2からはアンカーが自動で設定されないので、手動でアンカーを設定しないとオブジェクトが見つからないエラーが出るなど不安定になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/89ffe4f0-cb13-02bd-ac1a-715af4381394.png)

2、表抽出（ボタン）
一時データ保存には、ノートブックのスクラッチパッドが使えるが、ノートブックの書き込み設定をしないと書き込まれない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/77ca34a4-8213-f386-ef65-02ebd479394a.png)

3、Excelファイルを使用（アクティビティ）
ループの一番の外枠に設定するアクティビティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/64817b8f-685e-9a0d-7f93-1a44ba51fa5a.png)

4、繰り返し（Excelの各行）（アクティビティ）
3のExcelファイルを使用の中に設定するアクティビティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/44d80297-ca18-7d5a-6396-6f2c3c425237.png)

5、ドラッグアンドドロップ（アクティビティ）
RPAでは夢のようなドラッグアンドドロップを行えるアクティビティ（利用するには必ずアンカーを指定しないと安定した運用は出来ない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608295/c3be5f91-fca2-407c-2f43-cd278cdfdb0d.png)

基本はアンカーをしっかり設定する事。これで本来のRPAの趣旨である簡単に安定して繰り返し動作する自動化を短時間で実装し運用する事が出来る。夢のようだ。
【windows10】IPアドレス設定用をbatファイルを作成した（標準入力）

はじめまして！

windows10のIPアドレス設定用を行うためのbatファイルを作成したので、備忘録代わりに投稿します。



```
@echo off

rem インターフェース名確認
ncpa.cpl

echo インターフェイス名：
set /p interface_name=
echo IPアドレス：
set /p ip_address=
echo サブネットマスク：
set /p subnet_mask=
echo デフォルトゲートウェイ：
set /p default_gateway=
echo 優先DNSサーバー：
set /p dns_priority=
echo 代替DNSサーバー：
set /p dns_alternative=


rem DHCPで初期化
netsh interface ipv4 set add name="%interface_name%" source=dhcp
netsh interface ipv4 set dns name="%interface_name%" source=dhcp

rem 固定IP設定
netsh interface ipv4 set add name="%interface_name%" source=static addr="%ip_address%" mask="%subnet_mask%" gateway="%default_gateway%"
netsh interface ipv4 set dns name="%interface_name%" source=static addr="%dns_priority%" register=non validate=no
netsh interface ipv4 add dns name="%interface_name%" addr="%dns_alternative%" index=2 validate=no

pause
```

※管理者で実行してください
顧客ランクアップ予測の説明/ 目的変数を作成する(SPSS Modeler データ加工逆引き4-16)

# 顧客ランクアップ予測の説明/ 目的変数を作成する

![スクリーンショット 2022-10-20 14.41.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/852b816a-b43f-1ee8-b153-c4256e9705de.png)

## 1.想定される利用目的

・顧客の休眠やランクアップ/ダウン予測のためのデータ加工

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/rankup.str?raw=true

## 3.サンプルストリームの説明

![スクリーンショット 2022-10-20 14.49.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f45df226-98fd-9b16-375e-676a264f88f5.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2022-10-20 14.52.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/65fa621c-8b65-14ff-8c9a-c351d71ec8b0.png)

b.[フィールド作成]ノードを編集します。日付から年月を作成します。
![スクリーンショット 2022-10-20 14.53.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/83406314-05f2-5d04-0a5e-4b11d5503a83.png)

c.[条件抽出]ノードを編集します。1月から6月までの上期にデータを絞り込みます。
![スクリーンショット 2022-10-20 14.53.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/136eff23-8533-a66b-f888-5c68549307b7.png)

d.[データ型]ノードで[値の読み込み]ボタンを押して後続の[再構成]のメンバーを認識させます。

e.[再構成]ノードを編集します。AからCのカテゴリが列に展開されました。
![スクリーンショット 2022-10-20 14.55.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6cd73921-2e11-4e77-8c5f-ac5fd642c707.png)

[プレビュー]します。
![スクリーンショット 2022-10-20 14.55.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/65493b49-7486-c19a-0fff-db87fbdc3033.png)

f.[レコード集計]ノードを編集します。
![スクリーンショット 2022-10-20 14.56.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a91f5f41-3cbf-3c77-c14e-8668ad3e455d.png)

g.[フィールド作成]ノードを編集します。ランクを定義します。4万円以上でB、5万円以上がAです。
![スクリーンショット 2022-10-20 14.58.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6129167c-e217-ccab-749f-b8699db90d90.png)

h.[置換]ノードを編集します。今回は該当がありませんがカテゴリ別の実績にNULLがあったらゼロに置き換えます。
![スクリーンショット 2022-10-20 14.59.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e2c16d34-8f9d-906a-8bd1-f7c9e98a97ba.png)

i.下期のみを抽出するためcを複製して条件を[破棄]にします。

j.[レコード集計]ノードを編集し購入金額を合計します。

k.gを複製して下期のランクを作成します。

l.フィルターで不要なフィールド（列）を削除します。

m.[レコード結合]ノードで上期と下期の要約データをIDで結合します。
![スクリーンショット 2022-10-20 15.00.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8cc4a90f-777b-82e1-31b1-f43f9d9859b4.png)

n.[フィールド作成]ノードを編集します。ランクUPを定義します。
![スクリーンショット 2022-10-20 15.01.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9def2cec-f5b1-6b10-833a-c9a52fce3a48.png)

[プレビュー]します。![スクリーンショット 2022-10-20 15.01.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/8bd0957e-24a2-1534-2a20-f51ff5b1ec91.png)

#### 注意点

説明変数は単純に上期のカテゴリ内訳としましたが、実際には上期を３つの期間に分けて変動率などを作成するとより有効な予測が可能になります。

## 4.参考情報

#### 再構成ノードについて解説した記事

https://www.ibm.com/blogs/solutions/jp-ja/spssmodeler-push-node-4/

https://qiita.com/416nishimaki/items/6dcaecfc9343af0825b6

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
【C++】 Lambda関数のimmutableとは?


# Lambda関数のImmutableについて
公式ドキュメントでLambda関数はdefaultで引数がImmutable(不変)と書いてあったがよく分からなかったので、実際に試してみました。


* []の中の値がキャプチャと呼ばれていて、以下のようなCopyキャプチャは変数を変更不可能(Const)らしいですね。

```
    int x = 100;
    auto hoge = [x]() {
      x = 3; // compilation error
    };
    hoge();
```

* ()の中の値がパラメーターと呼ばれていて、普通の関数同様に変数xに値を代入できます。
```
    auto hoge = [](int x) {
      x = 3;
    };
    int num = 100;
    hoge(num);
```


* 普通の関数同様にconstをつければちゃんとerrorを吐いてくれます。
```
    auto hoge = [](const int x) {
      x = 3; //compilation error
    };
    int num = 100;
    hoge(num);
```

# まとめ

書き方によって挙動が違うのは分かりづらいですね。やっぱり引数にconstが付いていると安心できます。


# 参考

https://en.cppreference.com/w/cpp/language/lambda

https://qiita.com/YukiMiyatake/items/8d10bca26246f4f7a9c8
Python メモ：for文で動的にlambda式を使う

# はじめに

メンテナンスツール（スクリプト）を数々作成したため、いちいちスクリプトファイルを選んで実行するのは面倒でした。そこで、TkinterによるSelect Launcherを作り、選択実行できるようにしました。
ボタンを作るたびに、その数分tk.Button宣言を記述していては、長々としたコードになってしまうので、lambda式を使用してコード量を減らします。
この時のlambda式の記述の仕方をメモに残しておきます。

## lambda式

Python 公式ドキュメント

https://docs.python.org/ja/3/reference/expressions.html

> 6.14. ラムダ (lambda)
```
lambda_expr ::=  "lambda" [parameter_list] ":" expression
```
>ラムダ式 (ラムダ形式とも呼ばれます) は無名関数を作成するのに使います。 式 lambda parameters: expression は関数オブジェクトになります。 この無名オブジェクトは以下に定義されている関数オブジェクト同様に動作します:

```
def <lambda>(parameters):
    return expression
```
>引数の一覧の構文は 関数定義 を参照してください。ラムダ式で作成された関数は文やアノテーションを含むことができない点に注意してください。

## 記述

最終的なソースコードは、後述します。

与えられた文字列リストselect_listをもとにボタンが縦に並びます。
for文での記述箇所は、以下の通りです。
``` python
    for name in self.select_list:
        btn = tk.Button(
            root,
            text=name,
            command=lambda key=name: self.btn_clicked(key)
        )
        btn.pack(
            side=tk.TOP, fill=tk.BOTH,
            padx=sp, pady=sp, ipadx=sp, ipady=sp
        )
```

:::note info
ポイントは、lambda式の**key=name:**です。
:::


これを以下のようにして、直接変数nameを与えるとどうなるでしょうか？
``` python
            command=lambda self.btn_clicked(name)
```

::: note warn
このように記述すると、self.btn_clicked関数に渡される値は、全てFor分の最終結果である「name='C'」となってしまいます。
:::


## Select Dialog(Launcher)

文字列のリストを渡すと、以下のようなダイアログが表示されるプログラムです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/542103/17cb9a35-cd09-c0c2-e5e0-4efcd8df12bd.png)

## ソースコード(最終）

``` python
import tkinter as tk


class select_dialog():
    def __init__(self, select_list: list) -> None:
        self.select_list = select_list
        self.create_dialog(self._tk_root_())

        return

    def _tk_root_(self) -> tk.Tk:
        item = len(self.select_list)
        screen_w, screen_h = 240, item*45
        root = tk.Tk()
        root.attributes('-topmost', True)
        root.title(f'Select Menu')
        geo_string = f'{screen_w}x{screen_h}'
        root.geometry(geo_string)
        root.lift()
        root.focus_force()

        return root

    def create_dialog(self, root):
        sp = 5

        for name in self.select_list:
            btn = tk.Button(
                root,
                text=name,
                command=lambda key=name: self.btn_clicked(key)
            )
            btn.pack(
                side=tk.TOP, fill=tk.BOTH,
                padx=sp, pady=sp, ipadx=sp, ipady=sp
            )

        root.mainloop()
        return

    def btn_clicked(self, name):
        print(name)


if __name__ == '__main__':
    select_list = ['A', 'B', 'C']
    select_dialog(select_list)

```
【CSS】あなたはCSSの知識をどこからキャッチアップしていますか？

## はじめに

みなさんは、CSSを勉強する時はどのようにしていますか？

よくX(Twitter)などでは、Qiitaではなく、公式ドキュメントを参照しようといった趣旨のツイートがみられます。

確かに、**[W3C](https://www.w3.org/)** や **[MDN](https://developer.mozilla.org/ja/docs/Web/HTML)** といったところのドキュメントを読みCSSについての知識について理解を深めるのも1つの方法ですよね..


ただ、Qiitaのような個人が書いている記事にも魅力があります。

W3Cが想定してないような面白い使い方があったり、さまざまな表現方法があったりと、
新しい知見につながるものが多くあります。


そのため、今回は、私が普段CSSの知識や知見をキャッチアップしているサイトをまとめてみました。

ぜひストックして、参考にしていただけると嬉しいです。

また、今回は、知識や知見をキャッチアップするのに適していると感じているサイトをリストアップしているので、
もし、おすすめのサイトがあったら、ぜひコメントください。

## おすすめサイト
### 日本語で読めるサイト
#### 1. Qiita
https://qiita.com/

まずは、みなさんがこの記事を見ているQiitaです。
`CSS` や `Sass` といったタグをフォローして、キャッチアップしています。

#### 2. TECHFEED
https://techfeed.io/

TECHFEEDもよいです。
TECHFEEDは、X(Twitter)やFacebookといったサービスからのスコアを元に記事をおすすめしていただけるので、
サクッと見たい時には便利です。

#### 3. コリス
https://coliss.com/

[web.dev](https://web.dev/) などを早く翻訳して、
公開していただけるので助かってます。

#### 4. MDN
https://developer.mozilla.org/ja/docs/Web/HTML 

プロパティの挙動とかを参照する時にはよく使います。

### 英語で読めるサイト

#### 5. W3C
https://www.w3.org

特にW3Cの↓ここをよくみて、Webがどんな感じにアップデートされていくのか見てたりします。
(ここをみて、ワクワクしたら、変態ですね!)

https://www.w3.org/TR/

#### 6. Medium
https://medium.com/

**俺できる感** を出したい人にはおすすめです。
ライトな記事が多く、英語なので、スタバで見るとカッコよく見えます。

Google翻訳でページを翻訳しているとダサいのできをつけてください

#### 7. web.dev
https://web.dev/

Google Developers が運営しているサイトです。
ブログは読んでるだけで面白いです。

#### 8. Dev.to
https://dev.to/


#### 9. CSS-Tricks
https://css-tricks.com/

#### 10. A List Apart
https://alistapart.com/

#### 11. Smashing Magazine
https://www.smashingmagazine.com/

#### 12. Codrops
https://tympanus.net/codrops/

#### 13. SitePoint
https://www.sitepoint.com/

#### 14. Sidebar
https://sidebar.io/

#### 15. HeyDesigner
https://heydesigner.com/

#### 16. CSS Weekly
https://css-weekly.com/

#### 17. Frontend Horse
https://frontend.horse/

#### 18. Frontend Focus
https://frontendfoc.us/

#### 19. CSS { In Real Life }
https://css-irl.info/

#### 20. Modern CSS Solutions
https://moderncss.dev/


## まとめ
今回は、私が普段CSSの知識や知見をキャッチアップしているサイトをまとめてみました。

海外のサイトが多いのは、読んでいる人が新しい知見を得られるようにするためです。

私は普段からQiitaで記事を書いているため、日本のサイトを参考に記事テーマを考えると、見たことあるような記事になりがちになります。そのため、見たことあるをさけるため、海外のサイトを参考にしています。

もし、この記事が参考になれば、ぜひストックしていただけると嬉しいです。

また、今回は、知識や知見をキャッチアップするのに適していると感じているサイトをリストアップしているので、
もし、おすすめのサイトがあったら、ぜひコメントください。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
【sunabar -GMOあおぞらネット銀行API実験場-】アプリ開発体験記

## はじめに
先日、GMOあおぞらネット銀行さまのFinTech特別講座に参加させていただき、銀行APIを活用したLINEBotの作成と、オリジナルアプリケーション開発に取り組みました！学びの多い5日間だったので、記録をまとめておきたいと思います。

## この記事の目的
* 学んだことを言語化し、定着させること
* 銀行APIを知らない方、難しく感じている方に魅力を伝えること

## 銀行APIとは
オープンAPIの一種で、銀行システムの機能やデータにアクセスするAPIです。例えば、口座残高照会や振込などの操作が可能で、家計簿アプリや会計アプリなどに導入されています。銀行口座のログインIDやパスワードを預けることなく、安全かつ正確なデータ連携ができる仕組みです。

* 銀行系オープンAPIについて詳しく知りたい方は、こちらへ。

https://www.zenginkyo.or.jp/article/tag-g/9797/

## sunabar -GMOあおぞらネット銀行API実験場-とは
今回フル活用させていただいたsunabarをご紹介します！
sunabarとは、仮想インターネットバンキングで、入出金や振込などを自由に試せる「銀行APIの実験場」。銀行API開発支援をするサンドボックス環境で、20種類の銀行APIを無料で自由に利用できるのが特徴です。
また、実験のみでなく、ビジネスに「組込型金融」を取り入れるために必要な「エンジニアコミュニティ」「よろず開発支援室」「資金調達支援」の機能も備えています。
（※下記ページより引用）

かわいいテックま君が目印です:bear:

https://gmo-aozora.com/pfbank/sunabar/index.html

## sunabarを利用して体験したこと
* ポータルサイトでのATM入金、振込、つかいわけ口座、バーチャル（振込入金）口座
* 参照系APIを叩く（残高照会、口座一覧照会、入出金明細照会）
* 更新系APIを叩く（振込依頼、つかいわけ口座間振替）
* LINEbotで口座残高確認、振込依頼、つかいわけ口座間振替の実装
* sunabarAPIを活用しオリジナルアプリケーションの開発

## 開発したアプリケーションの概要
2人1チームで自ら企画・設計を行い、sunabarAPIを利用したアプリケーションを開発しました。

* **テーマ**
インターネットバンキング体験アプリケーション

* **目的**
インターネットバンキング未利用の人に基本操作を体験してもらい、その便利さを感じ、親しみを持ってもらうこと

* **使用技術**
sunabarAPI、Next.js、APIRoutes、TypeScript

* **実装した機能**
sunabarAPIを利用して、口座残高照会、振込依頼、つかいわけ口座間振替、入出金明細確認を行える機能

## 開発を通して学んだこと
* **サーバーサイドでのAPI接続**
今までフロントエンドから自作のAPIを叩く実装しか経験したことがなく、理解が曖昧でしたが、今回の開発で外部APIを利用することを通じて、クロスオリジンやサーバーサイドからAPIを叩く必要性を理解できました。

* **短期間で完成させる工夫**
約3日間で完成させる必要があったため、必要な機能と実装を取捨選択してMVPでの開発を行いました。そのため、フロントエンドからAPI接続ができない問題にぶつかったときには、サーバーを立てるかどうかの選択を迫られましたが、スピードを重視してNext.jsのSSR、APIRoutesを活用する決断をしました。

* **チーム開発経験**
今回、初めて協働での開発を経験しました。要件定義や設計を進めていく中で、それぞれアイディアを出し合って形にする作業は面白く、私には無い視点を学ばせてもらう貴重な機会だったと思います。また、作業分担では作業量に偏りが出ないように、かつ得意分野を活かすことのできるよう考慮し、お互いの力を発揮して１つのプロダクトを完成させることができました。

## sunabar・銀行APIに触れてみた感想
この講座を受ける前は、FinTechは難しいものだという先入観があり、銀行APIのイメージも掴めていない状態でした。しかし、sunabarに触れてみてそのイメージは覆されました。sunabarAPIをLINEbotの実装や、開発したアプリケーションに組み込んでみることで、使いやすさ、分かりやすさを実感しています。

sunabarポータルサイト・サービスサイトは、本物のインターネットバンキングと間違えそうになるほどデザインも使い心地も良くて、チュートリアルも充実しています。これなら初学者で1人で触る場合でもスムーズに使えそうです！

https://gmo-aozora.com/sunabar/tutorial/01.html

また、sunabarでは個人口座だけでなく、法人口座も利用することができます。なかなか個人だと触れない部分なので開発に使えるのはありがたいなと思いました。最近「API認可機能」も追加されたそうなので、こちらもぜひ勉強に使わせていただこうと思います。

このsunabarは、「API接続契約前に開発に着手したい」といった開発者のニーズに応えて無償提供されているそうです。これから更に多くの開発者がsunabarを活用していくと、もっと良いプロダクトが生まれそうだなとワクワクしました！

## おわりに
銀行APIへの理解が深まり、身近に感じることができた5日間でした。今後ますますFinTechの重要性が高まっていく中で、銀行APIを活用すると様々な場面で業務効率化・利便性の向上が期待できるので、更に興味が深まっています。

私はもともと、「技術の力で課題解決ができるエンジニアになりたい」という漠然とした思いがありましたが、今回の講座を通じて、銀行APIの活用により企業の課題解決に繋がっていく未来をイメージできて、更にエンジニアリングを面白いと感じるようになりました。まだまだ勉強不足なことが多く初歩的な部分で躓く日々ですが、引き続きコツコツ勉強を続けていきたいと思います！

素敵な講座を開いてくださったGMOあおぞらネット銀行のみなさま、本当にありがとうございました！
paiza.ioでelixir その19

# 概要
paiza.ioでelixirやってみた。
atcoderやってみた。

# 参考にしたページ

https://qiita.com/obelisk68/items/2e871eb5c2bbd7ddf33a

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/26055004-dcfc-76c6-d466-235c2419684c.png)

# サンプルコード

```

defmodule Main do
	defp output({result, _, _, _}), do: result |> Enum.join(" ")
	defp division(_, {acc, rem, cs, as}) do
		quo = div(hd(rem), hd(as))
		rem1 = Enum.zip(rem, as) 
		|> Enum.map(fn {x, a} -> 
			x - a * quo 
		end)
		[c | cs1] = if Enum.empty?(cs), do: [nil], else: cs
		rem1 = (tl rem1) ++ [c]
		{[quo | acc], rem1, cs1, as}
	end
	defp solve(as, cs) do
		al = Enum.count(as)
		cl = Enum.count(cs)
		rem = Enum.take(cs, al)
		cs1 = Enum.drop(cs, al)
		1..cl - al + 1
		|> Enum.reduce({[], rem, cs1, as}, &division/2)
		|> output()
	end
	defp rev_integer_list(str) do
		str
		|> String.trim()
		|> String.split(" ")
		|> Enum.map(&String.to_integer/1)
		|> Enum.reverse()
	end
	def main do
		IO.read(:line)
		as = IO.read(:line) |> rev_integer_list()
		cs = IO.read(:line) |> rev_integer_list()
		solve(as, cs) 
		|> IO.puts()
	end
end
Main.main

```

# 成果物

https://paiza.io/projects/0RmkWTJmuYcj0iYzp3m7LQ?language=elixir

以上。
paiza.ioでelixir その18

# 概要
paiza.ioでelixirやってみた。
atcoderやってみた。

# 参考にしたページ

https://qiita.com/obelisk68/items/2e871eb5c2bbd7ddf33a

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/4fabab08-eefe-4144-9f90-2c579ecd7a39.png)


# サンプルコード

```
defmodule Main do
	defp output({x, y, _, _, _, _, _}) do
		if x || y, do: "Yes", else: "No"
	end
	def judge(_, {x, y, a0, b0, [a | as], [b | bs], k}) do
		x1 = judge(x, a, a0, k)
		x2 = judge(y, a, b0, k)
		y1 = judge(x, b, a0, k)
		y2 = judge(y, b, b0, k)
		{x1 || x2, y1 || y2, a, b, as, bs, k}
	end
	defp judge(f, n, n0, k), do: f && abs(n - n0) <= k
	defp solve([1, _], _, _), do: "Yes"
	defp solve([n, k], [ai | as], [bi | bs]) do
		1..n - 1
		|> Enum.reduce({true, true, ai, bi, as, bs, k}, &judge/2)
		|> output()
	end
	defp integer_list(str) do
		str
		|> String.trim()
		|> String.split(" ")
		|> Enum.map(&String.to_integer/1)
	end
	def main do
		nk = IO.read(:line) |> integer_list()
		as = IO.read(:line) |> integer_list()
		bs = IO.read(:line) |> integer_list()
		solve(nk, as, bs) 
		|> IO.puts()
	end
end
Main.main

```

# 成果物

https://paiza.io/projects/r6JB-B7oVtrwu2bWtAwo7g?language=elixir

以上。
paiza.ioでelixir その17

# 概要
paiza.ioでelixirやってみた。
atcoderやってみた。

# 参考にしたページ

https://qiita.com/obelisk68/items/2e871eb5c2bbd7ddf33a

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/290f75c7-a252-45b2-7b3f-75003b6e93cc.png)


# サンプルコード

```
defmodule Main do
	defp find(map), do: 0..2000 |> Enum.find(&!map[&1])
	defp solve(list) do
		list
		|> Enum.reduce(%{}, &Map.put(&2, &1, true))
		|> find()
	end
	defp integer_list(str) do
		str
		|> String.trim()
		|> String.split(" ")
		|> Enum.map(&String.to_integer/1)
	end
	def main do
		IO.read(:line)
		IO.read(:line) 
		|> integer_list()
		|> solve()
		|> IO.puts()
	end
end 
Main.main

```

# 成果物

https://paiza.io/projects/VL7_GwLdhy9E-SV6PW897Q?language=elixir

以上。
VBAでメニューの自作

### 要件
マクロの実行はシートにボタンを置くことは、シートが追加すると、再配置しないといけないです。
メニューに配置したいです。
### 案
・マクロは.xlsmファイルにモジュールとして置く
・ThisWorkSheetにメニューを作成する
　すでにある場合、先に削除する
### 実装
``` 

Public Sub AddMenu()

On Error Resume Next

  Set mns = Application.CommandBars("Worksheet Menu Bar")
  For Each mn In mns.Controls
   If mn.Caption = "TestJsonData(&T)" Then
     mn.Delete
   End If
  Next
  
    
    '
    Set NewM = Application.CommandBars("Worksheet Menu Bar").Controls.Add(Type:=msoControlPopup)
    NewM.Caption = "TestJsonData(&T)"
    'Main menu
    Set NewC = NewM.Controls.Add
    With NewC
        .Caption = "Make Data2(&D)"
        .OnAction = "MakeData"
        .BeginGroup = False
        .FaceId = 277
    End With
    'menu 2
    Set NewC = NewM.Controls.Add
    With NewC
        .Caption = "Make Json2(&S)"
        .OnAction = "MakeJson"
        .BeginGroup = True
        .FaceId = 450
    End With
End Sub

Private Sub Workbook_Activate()
  AddMenu
End Sub

Private Sub Workbook_Close()
  Application.CommandBars("Worksheet Menu Bar").Controls("TestJsonData(&T)").Delete
End Sub
```

#### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/57eeb38e-2908-a36d-3474-ca1e3f7ac2cc.png)

#### ポイント①
メニューに該当「TestJsonData(&T)」があれば、削除する
```
  Set mns = Application.CommandBars("Worksheet Menu Bar")
  For Each mn In mns.Controls
   If mn.Caption = "TestJsonData(&T)" Then
     mn.Delete
   End If
  Next
```

#### ポイント②
該当ファイルを開くと、メニューを表示する、閉じると削除する
```
Private Sub Workbook_Activate()
  AddMenu
End Sub

Private Sub Workbook_Close()
  Application.CommandBars("Worksheet Menu Bar").Controls("TestJsonData(&T)").Delete
End Sub
```

#### ポイント③
Moduleと該当ソースの配置
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801991/6034f32b-0f36-0bef-8d74-4039e7737038.png)
paiza.ioでelixir その16

# 概要
paiza.ioでelixirやってみた。
atcoderやってみた。

# 参考にしたページ

https://qiita.com/obelisk68/items/2e871eb5c2bbd7ddf33a

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/842f1895-7905-4701-7d19-8bb2baa46aea.png)


# サンプルコード

```
defmodule Main do
	def f(h, m, s), do: 3600 * h + 60 * m + s
	defp solve([a, b, c, d]) do
		if f(a, b, 0) < f(c, d, 1), do: "Takahashi", else: "Aoki"
	end
	defp integer_list(str) do
		str
		|> String.trim()
		|> String.split(" ")
		|> Enum.map(&String.to_integer/1)
	end
	def main do
		IO.read(:line) 
		|> integer_list()
		|> solve()
		|> IO.puts()
	end
end
Main.main
```

# 成果物

https://paiza.io/projects/98zEcvU-65AxbCFz4W91ag

以上。
Unreal Engine PRNG

# はじめに
Unreal Engineの疑似乱数生成器について調査します.

Unreal Engineの疑似乱数生成器は次の３つがあります.

- FGenericPlatformMath::Rand
  - libcの`rand`のラッパー
- FRandomStream
  - 独自の線形合同法
  - 構造体なので, 状態を独立して作ることができる
- Random.ush
  - アルゴリズムをいくつか用意
  - PCGがあるのはここ
  - シェーダ内のハッシュ関数として使用される

# 範囲指定
範囲指定疑似乱数は次の２つです. 境界の包含が異なります. これはBlueprintでもそのままなので注意しましょう.

```c
// [0 1)
float frand();

// [0 max_)
int range(int max_)
{
    return (0<max_)? trunc_to_int(frand()*max_) : 0;
}

// [min_ max_]
int range(int min_, int max_)
{
    return min_ + range(max_-min_+1);
}
```

# FRandomStream
次のような独自の線形合同法です. 
[RFC 6716](https://datatracker.ietf.org/doc/html/rfc6716)に同じパラメータがありますが, こちらはOpusのコーデックで疑似乱数としての性能は求めていないようにみえます.


```c
uint32_t rand()
{
    seed = (seed * 196314165U) + 907633515U;
    return seed;
}
```

# 考察

## 範囲指定
FGenericPlatformMathやFRandomStream経由で範囲指定する場合は次の計算になります.

```c
trunc_to_int(frand()*max_)
```
エンジン内では`FGenericPlatformMath::Rand`や`FRandomStream::GetUnsignedInt`を直接呼び出し次のように余りを計算します. 
ほとんどは単体テストのコードですが, ランタイムのコードでも, 理解して意図的にしているのかわかりませんが, 余りを使用しています.

```c
FGenericPlatformMath::Rand()%4
```

`[0 1)`の浮動小数点数を使う方法, 余りを使う方法, どちらも偏りがあることが知られています.

## Blueprintから使う場合
整数を得たい場合は必ず範囲指定になります. 線形合同法の下位ビットに周期性がある弱点もあまり目立ちません. 
浮動小数点数を経由するため, もとの疑似乱数生成器の周期よりずっと短くなります. 
また, `range(2147483647)`のような意地の悪いことをすると偶数しかでなくなります.

## FGenericPlatformMath::Rand
リンクするlibcに依存するため, 性質は予測できません. 種を保存しておいて状態を再現するなどはできないと思っておいた方がいいです. 

## FRandomStream
C++からは`FRandomStream::GetUnsignedInt`を直接呼び出せます. 線形合同法そのままの値なので, 例えば偶数と奇数が交互に出現するなどの性質はそのままになります.

# まとめ
よく周知されていない辺りをみると, Unreal Engineに詳しい方々にとっては常識で, とるに足らないことなのでしょう.

Blueprintから呼び出す場合, 大きな範囲を指定しない限り, それほど問題にならないと思います.

C++から呼び出す場合, ターゲットプラットフォームごとの`rand()`の性質や線形合同法の性質をよく理解しておいた方がいいでしょう. 
`FRandomStream`については, エンジン改造して誰が扱ってもそれなりに動くようにしてしまってもいいかもしれません.
`Async/Fundamental/LocalQueue.h`にある, `FRandomStream::GetUnsignedInt()%4`が周期性を利用しようとした意図的なものなのか確認する必要はあります.

統計的な品質や長い周期が必要な場合, 開発者全員が疑似乱数生成器について熟知しなくても扱えるようにしたい場合, は自前の実装を用意しましょう.

## 範囲指定
偏りのある方法ならば浮動小数点数を使う方法をお勧めします. 上位ビットから使うことになるので, 線形合同法のような下位ビットに顕著な周期性のある疑似乱数生成器でもそれなりの結果が得られます.

偏りのない結果を得たい場合は`C++ STL`を使うか, [Efficiently Generating a Number in a Range](https://www.pcg-random.org/posts/bounded-rands.html)を参考に実装するといいでしょう.

# ToDo
- 広大なボックス範囲のランダムな３次元点, など高次元での周期性について調査する
文系からの社会人情報系修士・学士の比較（東京・オンライン編）

# はじめに
私のように文系学士持ちでも理転したい方はいると思うので、社会人受け容れに積極的な大学院を比較しました。情報系だけを集めています。疲れて表作成を途中でやめたりと穴もありますが、個人の備忘録が誰かの役に立つかもと投稿させていただきます。
いわずもがなですが正確な情報はぜひ各大学サイトにあたってください。
すいません、（東京・オンライン編）とタイトルに書いてますが他の編を作る予定はありません。

## 修士比較

|大学名|JAIST|AIIT|放送大学|ヨーク大学|UoP|
|:----------:     |:----------:|:------------:|:---------:|:---------:|:---------:|
|学位   |情報科学修士 |情報システム学修士(専門職)|学術修士|Computer Science|Information Technology|
|場所|品川|品川|どこでも|どこでも|どこでも|どこでも|
|講義形態|通学＋オンライン|通学＋オンライン|オンライン|オンライン|オンライン|
|講義時間*|平日夜間・土日祝日|平日夜間・土日祝日|いつでも|いつでも|いつでも + グループワーク|
|入学費|282,000円|都民 141,000円|48,000円|?|?|
|授業料**|535,800円(年額)|520,800円(年額)|466,000円|8,640ポンド|3,660ドル|
|入学試験・資格での数学要否|✕|✕|△(研究テーマによる)|✕|◯|
|コメント|石川本校舎の開発設備を使えない。|博士後期の途はほぼゼロ|開発環境が脆弱？|評判が不明|評判が不明|


*PBLや研究指導の時間は除く
**教育訓練給付金制度対象であれば減額できる

+ JAIST = 北陸先端科学技術大学院大学、AIIT = 産業技術大学院大学、UoP = University of the Peopleの略です。
+ 推薦状無しの大学院リストになりました。
+ 入学試験で数学不要であったとしても避けては通れないのですが、一応知っておきたいので項目作りました。
+ JAIST、放送大学は研究者向け、AIITは実務家向けという点で大きく異なります。ヨーク大学とUoPは日本のように修士/修士(専門職)のような区別は無いですが、実務家養成の傾向が強いと思います。
+ ヨーク大学は1ポンド = 169.65円 で計算すると146万5776円、UoPは1ドル = 147.71円 で計算すると54万618円になります。現在円の変動がひどいのでこの記事を作成したときと見たときで乖離が大きいかもしれません。
+ [ペンシルバニア大学のMCIT](https://online.seas.upenn.edu/degrees/mcit-online/)は教授やTAとのコミュニケーションが濃そう（[参考note](https://note.com/kuboasa/n/nb5d7c1f4e679)）です。他にジョージア工科大学もありますが疲れたので中断しました。
+ 表には入れませんでしたがWorldQuant Universityという大学は金融工学修士を無料で取れるとのことです。（https://www.wqu.edu/）

## 学士比較
一応学士も簡単にまとめました。

|大学名|電気通信大学|放送大学|UoP|The Open University|
|:-----:|:--------:|:-----:|:------------:|:------------:|
|学位 　|学士(工学)|学士(教養)|Computer Science等|Computer Science等|
|場所|品川|オンライン|オンライン|オンライン|
|講義形態|通学|通学＋オンライン|オンライン|通学|
|講義時間|平日夜間・土曜|いつでも|いつでも|いつでも|
|入学費|141,000円|24,000円|60ドル|?|
|授業料*|1,071,600円|682,000円|4,860ドル**|19,368ポンド***|
|入学試験での数学要否|◯|✕|✕|✕|
|コメント||学位授与機構で学士(工学)も可能|||

*3年次編入や単位認定により減額可能。

+ UoPは1ドル = 147.71円 で計算すると入学費込みで75万9229円、Open Universityは1ポンド = 169.65円 で計算すると328万5781円になります。

# まとめ
国内大学院でまとめると以下のようになるのではと思います。
+ 研究者の途を残したい → JAIST、放送大学
+ 研究者は眼中にない → AIIT
+ 家事・育児・仕事と両立したい → 放送大学、海外オンライン

専門職課程のAIITでも博士課程後期に進学することは制度上可能なのですが、AIITでは研究方法を学ばない以上受け容れてくれる大学院が見つからず、制度上可能である、という程度みたいです。
家事・育児・仕事との両立はJAIST、AIITでも長期履修制度を使って可能かもしれませんが、仕事との両立だけでも死にものぐるいのブログ記事を見かけるので負担がかなり高そうです。合間合間で授業を受けるタイプの方がまだマシなのかもしれません。負担はかなり高いはずですので周囲の協力が不可欠です。

また、もしエンジニアとして海外で働くことを考えるなら放送大学の"学術"修士がビザや就職にどのように影響するか（CS系だと有利になりやすい）は検討すべきだと思います。

また折を見て更新します。

参考
+ [note: 働きながら情報系の大学院を修了した by 父](https://note.com/fushiroyama/n/n602687744edb)
+ [note: なぜデザイナーの私がオンライン大学院でコンピューターサイエンスを学ぶのか？〜ペンシルバニア大学オンライン留学体験記〜 by くぼみ](https://note.com/kuboasa/n/nb5d7c1f4e679)
+ [note: 放送大学と学位授与機構で情報工学の学位を取る（科目対応表付き）by lumpsucker](https://note.com/lumpsucker/n/nef2ffd3f164f)
【VSCode】'code .'コマンドでディレクトリが開けないときの対処法

入力するコマンド：
```
cd ****(ファイルパス)
code .
```

cd **** 指定のディレクトリへ移動
code . 指定したディレクトリをVSCodeで立ち上げる

通常、↑これでうまくいくはずが、私の場合
```
/usr/local/bin/code: line 6: python: command not found
/usr/local/bin/code: line 10: ./MacOS/Electron: No such file or directory
```
というエラーが出て、ディレクトリが立ち上がらない。

<h2>まず試したこと</h2>
<h3>使いたいシェルに'code'コマンドがインストールされているか確認<h3>

VSCodeのメニュー＞表示＞コマンドパレット＞"shell"と入力＞「シェル コマンド:PATH内に'code'コマンドをインストールします」をクリック。
![スクリーンショット 2022-10-28 3.01.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780969/109ad2dc-ccc7-1607-b1a5-a1e6bd34bfdd.png)
すると、「シェル コマンド'code'がPATHに正常にインストールされました。」と表示される。
![スクリーンショット 2022-10-28 3.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780969/067aa94a-9a79-5bfd-b21c-c2a19125de6c.png)

<h2>でもダメだった…。そこで次に試したこと</h2>
<h3>エラーメッセージを再度よく読む<h3>

「Pythonにそんなコマンドないで。とりあえず、/usr〜codeの6行目見ろや。」
```
/usr/local/bin/code: line 6: python: command not found
```

わ、わかった…。
おもむろに指定されたファイルを開くと6行目には
```
function realpath() { python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" "$0"; }
```
と書いてある。
んー…なんかよくわからんけどこの一文ググってみるか。

で、ググってるとこんなページを見つけた。
https://github.com/microsoft/vscode/issues/141738

読み進めていくと

>In macOS 12.3 beta Apple removed support for Python 2. Additionally Python 3 no longer comes bundled with macOS. This causes the code command to not work anymore.
The fact that VS Code is using Python 2 which hasn’t been officially supported since January 2020 is kinda crazy.
This should be fixed ASAP.

*ちびくろ翻訳（都合の良いとこだけトリミング済み）：*
*MacOS12.3ベータ版バージョンアップのタイミングで、Python2のサポートが打ち切らて、しかもPython3の提供も無くなった。
なのに、VSCodeのターミナルは2020年以降、Python2を使う仕様になってるってことは、矛盾してるじゃねーか！イカれてるぜ！*


<h3>謎が解けた😭</h3>

つまり、Python2か3にすればいいってことね。
fishcharlieさんありがとう。

<h2>解決方法</h2>

指定の行を、↓これに書き換えるだけ。
```diff_python
- function realpath() { python -c ...
+ function realpath() { python3 -c ...
```
python→python3に書き換えられて、ちゃんとVSCodeでディレクトリを開けるようになった🙌

<h2>まとめ</h2>

今回詰まった内容なら、エラーメッセージの理解から始めていたら、30分は解決時間を削れたかも。
エラーメッセージを読むなんて当たり前のことだけど、**詰まったらすぐググって、要約されたページを見つけて楽に解決しようとしてしまう**私の悪い癖が、結果、遠回りになってしまった。
ググることも大切だけど、問題の内容によっては、近道になったり、回り道になったり、ね…（しみじみ）。
なのでちょっと調べてわからない時は、一度**原点に立ち返って、エラーメッセージを理解したり、公式ドキュメントを読んだりする**と、意外と早く解決したりするってことを心に留めておきたい🥸
目的に合った自分なりの学習方法の可視化と自戒

実装知識と技術知識の学習コストへの感覚として
実際に必要な知識を集め、実現させる実装には抵抗がない。
しかし、技術知識として、実装知識を学習しようとすると目的が技術知識の定着になり、効率が落ちる。

何かを作る、改善する
転職する
などと目的を決めることが自分のパフォーマンスを効率よくさせる。
つまり、転職、仕事で活かす、これを意識することが必要で
行動レベルに落とすと、未経験枠/経験枠と分別し
現状当然ながら未経験枠が一番近いので、研修レベルからスタート


まだ実装という実装を行ったわけではないが、環境構築、有料教材でプログラミング言語基礎、SQL基礎、FW基礎などを触ったくらいの知識量ではあるが、
それぞれ技術によって学習コストはもちろん異なることは理解しているが、調べながら行うという点（実現させる段階）においては全くストレスがない
それよりかは、根本的になぜサーバーは種類があって、どのOSをなぜ使って、なぜこの言語を使うのか（実装目的ではなく、知識の定着目的での学習）
といった、完璧ではなくとも、それぞれの技術を選定する根拠が自分の中で理解していないとどうしてもストレスがかかり、効率がミキサーからすり鉢くらいまで下がる。
しかも、もやもやで楽しさを見出せなくなる。
こういったプライドがあるのはもったいないが、基礎力すらないので時間をかけてしまう。
軽くでもいいので自分なりに納得してからする方が楽しいことに気づいたので、
もし未経験枠で入社させていただけた時に、研修を開始する頃には
・スムーズに進めることができる
・なんなら復習、深掘り
を目指して、学習を目指している。
自己分析と両立して、目の前の段階までは学習を楽しんで継続していきたい。
それからは、どんどん新しいことをキャッチアップしていける段階を目標にまで楽しむ。
これまで通り、好きなことや達成したいことに関してはドーパミンをどぱどぱさせて、入社実現まで改善を続け、どこに行くつもりもなく諦めない。
C# .NET FrameworkでTransactionScopeでタイムアウトしてしまうときの対処法

`TransactionScope`でタイムアウトしてしまうときの対処法
大量のデータを処理する場合、デフォルトの処理時間内にSQLが処理しきれない場合がある

トランザクションのタイムアウト時間は、初期設定では1分
```c#
// タイムアウト時間 1分
using (var transaction = new TransactionScope())
{
}
```

タイムアウト時間を設定するには、`TransactionScopeOption`のオプション設定が利用可
例えば、下記のようにタイムアウト時間を設定できる
```c#
// タイムアウト時間 10分
using (var transaction = new TransactionScope(
            TransactionScopeOption.Required,
            new System.TimeSpan(0, 10, 0)))
{
}
```

タイムアウト時間を無制限にすることも可
```c#
// タイムアウト時間 無制限
using (var transaction = new TransactionScope(
            TransactionScopeOption.Required, TimeSpan.Zero))
{
}
```

タイムアウト時間を初期値の最大値である10分を超える設定をする場合、
`machine.config`に以下を記述する必要
```cs
<configuration>
<system.transactions>
  <machineSettings maxTimeout="01:00:00" />
</system.transactions>
</configuration>
```

`machine.config`の場所は、例えば64bitのWindowsなら下記の場所にある

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

## Reference

https://docs.microsoft.com/ja-jp/dotnet/api/system.transactions.transactionscopeoption?view=net-5.0:title

https://docs.microsoft.com/ja-jp/dotnet/api/system.timespan.-ctor?view=net-5.0:title

https://docs.microsoft.com/ja-jp/dotnet/api/system.transactions.configuration.machinesettingssection.maxtimeout?redirectedfrom=MSDN&view=netframework-4.8#System_Transactions_Configuration_MachineSettingsSection_MaxTimeout:title
技術に関して、ではなく現在の学習方針について言語化する

現在は本格的に学習を始めて、３ヶ月目だ
本来一般的には、軽く制作物を作っていたりしてもおかしくない期間だが
今の自分の進行状況で言えば、遠回り中
学習を始める前から、若干の情報収集をしていく中で、いろんな意見やロードマップがあった。
確かにそれをこなすことで、それに見合った力が身につくことは間違いはないであろう。
しかし自分に合うかどうかで言えば合っていないような気がしていた。
これを挫折と呼ぶとして、初めの挫折は
基本情報技術者（CS基礎）→Linux→HTML/CSS→JS→Ruby→DB→Git/Github→rails
この流れで学習を進めていくと決めていざやると
CS基礎の時点で理解不能だ。
私は昔から必要なこと以外身につけることが苦手だった。
勉強らしい勉強の能力が低いのだろうか。
しかし、これまでの人生経験上、自己分析をした結果、必要性を感じることに関して興味や疑問、深掘りのレベルと執着心が比べ物にならない差があると自負している。
前職では、必要なスキルや、向上するため、結果を出すために考えて行った物事（日常生活や、人間関係、スポーツ、ゲームなど特定の領域に限らず、決めたことに対して）での優先順位の組み方、必要な知識レベルの感覚値、調べ方
そして何よりも必要性を感じると、「楽しい、気持ちいい」という感情が湧き上がってくる
どんな物事でも努力を続ける人も素晴らしいが、努力＝楽しいで取り組んでいる上位層には基本的には敵わないと考えていて、大切なことだと思っている。
これらを踏まえて、自分に合った方法で、長期的に力をつけるために考えた方針が、

・方針が決まるまで、気持ちが途切れる前に挫折して別の方法を考える
・今のやり方について考えることをやめない
・時間を忘れるくらい気持ち良くなる（一番重要）

これらを満たすことを意識しつつ模索しつつ学習を進める
狙いは、今後社会的責任を任せていただきながら、精進していく中で必ず辛い時があるはずで
辛い時というのは、好きなことをしていてもこれまでの経験上必ず出てきていた。
ここで、楽しめるかどうかが踏ん張る力、差が生まれる瞬間で、成長速度が変わってくると考えている。
そして何よりも、小学生の頃からパソコンを触るのが好きで、よく目的のために小学生ながら難しい文章を読みながらなんとなく触って達成した時の喜びを今でも覚えている。
これを自分の中でこれからの伏線として、楽しんでやるために種を撒くつもりで模索しつつ、自分に合った定着方法を身につけ、仕事のやりがいを求めて学習を進める。

＊上記のことを決めて進めて、今は入社を希望している会社で行われる研修内容を拝見し、その内容に沿って自分なりに理解を進めているが
完全に楽しい/気持ちいいゾーンが入ったか。
〜なぜ入れたか〜
・研修内容を公開していただいていたおかげで、どれくらいからのレベルが必要か認識することができた。
・今までの積み重ねた部分と、必要なレベルが紐付き始めた

〜わかったこと、どうしていくか〜
・苦手なことに対して、丁寧に逆算する
・アウトプットが少ないので、手を動かしてから深掘りして知識を定着させる
【JavaScript】配列内の値に順位をつける

## 順位付け？

配列の値を並び替えすることはありましたが、順位付けする方法は？？となり、メモします。

```js
const array = [ 90, 100, 50, 10, 80 ]

// 並び替え（降順）
const sorted = array.slice().sort((a,b) => b - a); 

// 元配列と並び替えた配列を比較
const ranked = array.slice().map((item) => {
  return sorted.indexOf(item) + 1
})

console.log(ranked);

// 出力    
// [ 2, 1, 4, 5, 3 ]
```


## 余談

sortは破壊的変更になるので、それを防ぐ方法

```js
const array = [ 90, 100, 50, 10, 80 ]

// 破壊的変更
array2 = array.sort((a,b) => b - a);

console.log(array);  // [ 100, 90, 80, 50, 10 ]
console.log(array2); // [ 100, 90, 80, 50, 10 ]


// 防ぐ
array3 = array.slice().sort((a,b) => b - a); 

console.log(array);  // [ 90, 100, 50, 10, 80 ]
console.log(array3); // [ 100, 90, 80, 50, 10 ]
```



## 参考

https://goma.pw/article/2017-01-31-0/

https://zenn.dev/kou_pg_0131/articles/js-clone-array
マスク付きテンプレートマッチングでスプラトゥーン3のイカランプを認識させてみた

openCVのcv2.matchTemplate()によるテンプレートマッチングでは、アルファ値が使えないことで有名ですが、**実はマスク付きテンプレートマッチングで透過処理が可能です。**

公式ドキュメント：https://docs.opencv.org/4.x/d4/dc6/tutorial_py_template_matching.html

オライリー・ジャパンから出版されてる「詳解OpenCV 3」にもマスク付きのテンプレートマッチングのことは取り上げられていませんでした。

かなり便利な機能だったので本記事でご紹介したいと思います。

cv2.matchTemplate()にテンプレート画像を同じサイズのマスクを渡すことで、「透明なピクセル」のような扱いが可能です。アルファ値ではないため半透明を取り扱うことはできませんが、マスクの取り方としきい値である程度調整可能かと思います。
マスクを掛けることで自由な形状のテンプレート画像でマッチングさせることができます。

![icons.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295263/56d5b927-37e7-0c8a-d5aa-818920ca023b.png)
(icons.png)　@2022 任天堂　スプラトゥーン3

こちらはスプラトゥーンの、8人のプレイヤーの使用ブキを表したアイコン通称「イカランプ」の画像です。

ここからスプラシューターのアイコンを検出したいと思います。

![splashooter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295263/a7ad1e37-d9d0-fb11-16b5-882fd2e794d2.png)
(splashooter.png)　@2022 任天堂　スプラトゥーン3
こちらにこのようなテンプレートと、

![splashooter_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295263/9b12e23c-645a-21c6-a89c-2a856167395e.png)
(splashooter_mask.png)
マスク画像

を引数に指定してマッチングさせてみたいと思います。

```python
import cv2
import numpy as np

img = cv2.imread(r"icons.png")
template = cv2.imread(r"splashooter.png")
mask = cv2.imread(r"splashooter_mask.png", 0)

res = cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED, mask=mask)
loc = np.where(res >= 0.95) # しきい値
for pt in zip(*loc[::-1]):
    cv2.rectangle(img, pt, (pt[0] + template.shape[1], pt[1] + template.shape[0]), (0,0,255), 1)

cv2.imshow("img", img)
cv2.waitKey() # キー入力で終了
```
 
 
 
 
・結果
![res.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295263/8460ecd0-ff40-d661-c6da-0bcb7e85c70d.png)
　@2022 任天堂　スプラトゥーン3
 
 
 
背景によらずマッチングさせることができました！！
前からこういう画像検出をやってみたかったんですがついに実現して感動しました・・！

というかマスクなしのテンプレートマッチングってほぼ役に立たないような・・矩形でない形状の検出をしたいケースって山ほどありますし。

ちなみに余談ですが、cv2.matchTemplate()が返すRECTのリストですが、位置が重複したものを複数返してくるので重複を取り除く処理が必要になります。

検出結果の画像の赤い四角形の線が太いものになっているのは重複したRECTをすべて描画しているため太い線のように見えています。
今回のケース、本来であれば2つのRECTを取得できるのが適切な処理です。

本記事では取り扱いませんが、重複除去の手法である**Non Maximum Suppression**について
紹介してる記事のリンク貼っておきます。お役に立てればと。

https://python-ai-learn.com/2021/02/06/nms/

https://python-ai-learn.com/2021/02/14/nmsfast/#toc2
TypeScript×Reactプロジェクトの環境構築

# 1.はじめに
TypeScriptでReactを書く際の初期設定について記録しました。ファイル作成からstorybookを用いた開発についてまで触れています。初めてなのでおかしい部分が多々あるかもしれません:cry:

# 2.環境構築
## 適当なディレクトリに入る

git管理するディレクトリ達はひとつのフォルダにまとめるようにしているのでターミナルでそちらに移動します。

```
cd ~/gitspace
```

## Reactのプロジェクトの作成
Reactアプリを作るためのテンプレートがあるのでその雛形を利用します。

```
npx create-react-app <プロジェクト名> --template typescript
```

作成したプロジェクトに移動します

```
cd <プロジェクト名>
```

`happy hacking!`と出ればインストール成功です（結構時間がかかった）。
`yarn start`でlocalhost3000サーバーを起動してこのような画面が出てくるはずです。
![react.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929600/6475f323-104a-b48b-1d92-b88a81c73ec4.jpeg)
`code .`でVScodeを起動します。

## リポジトリを作成して反映する
GitHubでリポジトリを作成して、そこに作成したものをpushします。
```
git remote add origin <リポジトリのURL>
```

# 3.不要なファイルの除去
次のファイルは不要なので除去しておきます。
- App.css
- App.test.tsx
- logo.svg

# 4.App.tsxの書き換え
```react:<プロジェクト名>/src/App.tsx
import React from 'react';

const App: React.FC = () => {

  return(
    <h1>Hello React!</h1>
  );
};

export default App;
```
`yarn start`で次のようになります。
![スクリーンショット (76).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929600/28da0fa3-b20f-d81e-4410-89e2123e75ab.png)

# 5.componentファイルの作成
atomic designだと細かすぎるのでuiParts(atoms,molecules相当)、projects(organisms,templates相当)、pagesに分けてパーツを作成していきます。
最初にファイルを作るとエラーが起こりますが、これは`tsconfig.json`で`isolateModules`がtrueになっているからだと思われます（デフォルトでfalse）。importもexportもしていないファイルをコンパイルエラーとするようなので一旦`export {}`を書いておいて解決しました。

```
--src
   |
   --components
         |
         |--uiParts
         |      |
         |      --example
         |          |--index.tsx
         |          |--style.tsx
         |          |--index.stories.tsx
         |--projects
         |--pages        
```

```react:src/components/uiParts/example/index.tsx
import { StyledText } from "./style";

type ExampleTextProps = {
    text: string;
}

export const ExampleText = ({ text }: ExampleTextProps) => {
    return (
        <StyledText>{text}</StyledText>
    );
}

```
```react:src/components/uiParts/example/style.tsx
import styled from "styled-components";

export const StyledText = styled.p`
    color: #0A6ABF;
`;

```

```react:src/components/uiParts/example/index.stories.tsx
import { ComponentStory } from "@storybook/react";

import { ExampleText } from "./index";

export default {
  title: "uiParts/ExampleText",
  component: ExampleText,
};

const Template: ComponentStory<typeof ExampleText> = (args) => (
  <ExampleText {...args} />
);

export const Basic = Template.bind({});
Basic.args = {
  text: "テキスト",
};

```

## styled-componentsを使えるようにする
初期状態ではstyled-componentsが存在しないようでエラー吐かれるのでインストールします。
```
npm install --save styled-components
```
`package.json`に追加されます。

## storybookを使えるようにする
初期状態ではstorybookを使えない（エラーで怒られる）ので、storybookをインストールします（時間かかった）。
```
npx storybook init
```
`yarn storybook`でstorybookを起動できます。

#### 参考にした記事
- [環境構築全般](https://qiita.com/kazama1209/items/868c09393007cc9b234f)
- [isolateModulesについて](https://zenn.dev/ryo_kawamata/articles/0f63b7ffdaed97)
- [styled-componentsについて](https://www.i-ryo.com/entry/2021/01/31/150319)
- [storybookについて](https://reffect.co.jp/html/storybook)
M1 Macのkind create clusterでエラーが出たらまず確認すべきこと

M1 MacでDocker Desktopとkind(Kubernetes IN Docker)をインストールし、さてクラスターでも作ってみるか！とサンプルコードで```kind create cluster```したら、いきなりエラーが出てがっかりしたことはあるでしょうか？

私はあります。
```shell-session
$ kind create cluster --config kind.yaml --name kindcluster
Creating cluster "kindcluster" ...
 ✓ Ensuring node image (kindest/node:v1.18.2) 🖼
 ✗ Preparing nodes 📦 📦 📦 📦 📦 📦
ERROR: failed to create cluster: could not find a log line that matches "Reached target .*Multi-User System.*|detected cgroup v1"
```

書籍のサンプルコードなどは、M1(arm64)前提で書かれることはほぼないですよね、たぶん。
（最近の書籍だと注釈にM1の対処法が書かれているのを見かけたこともありますが）

[kind公式サイト](https://kind.sigs.k8s.io/docs/user/known-issues/#nonamd64-architectures)には「amd64アーキテクチャ以外のイメージなんて作ってない（そんな需要ない）から自分でビルドしてね」とか書いてあるし、ちょっとググっても解決方法が見つからないし、なんか面倒そうだな、、、

と思っていたら実はサクッとと解決しました。

# 結論
docker hubに[arm64向けのノードイメージ](https://hub.docker.com/r/kindest/node-arm64/tags?page=1&ordering=name)があるので、それを使いましょう。

```yaml:kind.yaml
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
- role: control-plane
  image: kindest/node-arm64:v1.25.3
- role: control-plane
  image: kindest/node-arm64:v1.25.3
- role: control-plane
  image: kindest/node-arm64:v1.25.3
- role: worker
  image: kindest/node-arm64:v1.25.3
- role: worker
  image: kindest/node-arm64:v1.25.3
- role: worker
  image: kindest/node-arm64:v1.25.3
```
```shell-session
$ kind create cluster --config kind.yaml --name kindcluster
Creating cluster "kindcluster" ...
 ✓ Ensuring node image (kindest/node-arm64:v1.25.3) 🖼
 ✓ Preparing nodes 📦 📦 📦 📦 📦 📦
 ✓ Configuring the external load balancer ⚖️
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
 ✓ Joining more control-plane nodes 🎮
 ✓ Joining worker nodes 🚜
Set kubectl context to "kind-kindcluster"
You can now use your cluster with:

kubectl cluster-info --context kind-kindcluster

Not sure what to do next? 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/
```

できました！

# 動作確認
DaemonSetを起動してみます。

```yaml:sample-ds.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: sample-ds
spec:
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.16
```

```shell-session
$ kubectl apply -f sample-ds.yaml 
daemonset.apps/sample-ds created
$ kubectl get pods               
NAME              READY   STATUS    RESTARTS   AGE
sample-ds-2ldjg   1/1     Running   0          11m
sample-ds-j84hd   1/1     Running   0          11m
sample-ds-z8bpn   1/1     Running   0          11m
```

各ノードにポッドが起動しました！

# 動作環境
- MacBook Pro (2021, M1 Pro)
- Docker Desktop for Mac (Apple silicon) 4.13.0 (89412)
- kind v0.16.0 go1.19.1 darwin/arm64

# 最後に
docker hubでイメージを見つける前に、自分でノードイメージをビルドして解決することもできました。
色々と試行錯誤があったので、その手順も別記事で書こうかと思います。　→　[書きました](https://qiita.com/ezotaka/items/37db8be07ca329241ed6)
【javascript】css を node.js のサーバで読む

# はじめに

Node.js でフロントエンド作りたいなー、と思い、勉強しています。
サーバ側のscript で html ファイルを読んで返したり、css を読んだりできるようになりました。

仕組みをわかっていないのですが、とりあえずメモしておきます。

# 内容

以下のようなファイル構成です。

```
├── app.js
├── css
│   └── test.css
└── index.html
```

app.js を node で起動してサーバにします。

```
$ node.js
```

ブラウザからlocalhost:8080 を見ると test.css で<div></div>が修飾されます。

サーバ側として 

```javascript:app.js
var http = require('http');
var fs = require('fs');

var server = http.createServer();
server.on('request', getCss);
server.listen(8080);
console.log('Server running …');

function getCss(req, res) {
  var url = req.url;
  console.log('url=', url)
  if ('/' == url) {
    fs.readFile('./index.html', 'UTF-8', function (err, data) {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write(data);
        res.end();
    });
  } else if ('/css/test.css' == url) {
    fs.readFile('./css/test.css', 'UTF-8', function (err, data) {
        console.log('test.css is read.')
        res.writeHead(200, {'Content-Type': 'text/css'});
        res.write(data);
        res.end();
    });
  }else{
    console.log('unexpected url...')
    res.writeHead(200, {
        "Content-Type": "text/html"
      });
      const responseMessage = "<h1>Hello World</h1>";
      res.end(responseMessage);
  }
}
```

としました。これ、結局、HTTP request が来た時のrouting を全て、require に設定した関数に書いています。こんな書き方していたら、たくさんURLがあったら大変な気もします。大規模になったら、きっと良い方法があるのでしょう。

読んで想像するに、
url が
- '/' なら css.html を読んで、head を付けて HTTP responce にして返す
- '/css/test.css' なら ./css/test.css を読んで、header を付けて HTTP responce にして返す

ようです。contents type が異なります。


用意している HTMLは

```html:index.html
<html>
<head>
  <meta http-equiv="content-type" content="text/html charset=UTF-8">
  <title>css テスト</title>
  <link rel="stylesheet" type="text/css" href="./css/test.css">
</head>
<body>
  <div class="testclass">
    <p>ABCED</p>
  </div>
</body>
</html>
```

です。このheader で css を読む指定があります。そういうものなのか。

### 参考情報

参考にさせていただきました。感謝。

https://www.naka-sys.okinawa/node-js-css/

https://www.i-ryo.com/entry/2020/03/30/202741

https://developer.mozilla.org/ja/docs/Learn/Server-side/Node_server_without_framework


下記は読んでいないけれど、フォルダ構成とか参考にしたい。

https://scoutapm.com/blog/nodejs-architecture-and-12-best-practices-for-nodejs-development

# まとめ

とりあえず、node.js で起動したサーバが側のjavascript で、CSSを読み込んだhtml を返すことができるようになった。

- エラー処理をできるようになりたい
- routing を app.js 以外に書くなど、コードを整理したい
- python のときのように、logging を使いたい。console.log でなく

いろいろTODOはあるが。
(2022/10/28)
【RSpec】Capybaraシステムテストで要素クリックが失敗したら確認したいこと

## 概要
Ruby on Railsで開発したアプリのシステムテスト実行時に、Capybaraの使い方で少し躓いた点を書いた記事です。

html要素をクリック出来ずにテストが失敗した原因と解決方法を簡単にまとめました。

もし、同じ内容でテストに失敗した方のご参考になれば幸いです。

## テスト概要
- ハート文字をクリックするといいね/いいね解除できること

今回開発したアプリにはいいね機能を実装しており、ハートをクリックすることでいいねといいね解除ができるようにしました。

## テスト・エラー詳細

下記コードを実行。
```ruby
RSpec.describe 'Comments', type: :system do
  # 投稿をいいね・いいね解除できる
  it 'user can like the post' do
    click_link '♡'
    expect(page).to have_button '♥'

    click_link '♥'
    expect(page).to have_button '♡'
  end
end
```
実行結果は、下記エラーによりテスト失敗となりました。

```
# bundle exec rspec
Comments
  user can like the post (FAILED - 1)

  1) Comments user can like the post
     Failure/Error: click_link '♡'
     
     Capybara::ElementNotFound:
       Unable to find link "♡"
```

## 原因と解決方法

- 原因

クリックする要素を```link```にしていたことが原因でした。

今回、view側にフォームを用意し、'♡'をクリックした際にHTTPリクエストが送信されるように実装していました。
そのため、link要素ではなくbutton要素となっていたため、上記のエラーメッセージの仰る通り、'♡'　のリンクは見つからずテストが失敗しました。

- 解決方法
~~```click_link```~~ -> ```click_button``` / ```click_on```

リンク要素をクリックではなく、ボタン要素をクリックできる```click_button```もしくは```click_on```に修正することで、無事テスト成功しました。

下記コードでは、ボタン要素をクリックするよう明示的に記載しています。
```ruby
  it 'user can like the tweet' do
    click_link 'test tweet!!'
    click_button '♡'
    expect(page).to have_button '♥'

    click_button '♥'
    expect(page).to have_button '♡'
  end
```

下記記事を参考にしたところ、```click_on```を使えばリンク要素とボタン要素のどちらもクリック可能だと知ることが出来ました。

[使えるRSpec入門・その4「どんなブラウザ操作も自由自在！逆引きCapybara大辞典」 - リンクまたはボタンをクリックする](https://qiita.com/jnchito/items/607f956263c38a5fec24#%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%BE%E3%81%9F%E3%81%AF%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%92%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B:~:text=%27New%20User%27-,%E3%83%AA%E3%83%B3%E3%82%AF,-%E3%81%BE%E3%81%9F%E3%81%AF%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%92)

> クリックする要素がリンクなのかボタンなのか、いちいち考えたくない場合は click_on が便利です。

## 終わりに
つまづいた内容自体はシンプルでしたが、Capybaraでのテストの書き方や、ユーザがクリックするのは何要素か？といった基礎的な部分を理解する良い機会となりました。

お読みいただきありがとうございました！

## 参考
https://qiita.com/jnchito/items/607f956263c38a5fec24