OmniAICreator/Qiita-1.07M huggingface dataset:
【M1Mac / DockerDesktop / act】Error: failed to start container: Error response from daemon: error while creating mount source path

# エラー
github actionsをローカルで実行できるactを実行したところ、以下のエラーがでました。
環境はM1 Mac x Docker Desktopです。

```
Error: failed to start container: Error response from daemon: error while creating mount source path '/host_mnt/Users/username/.docker/run/docker.sock': mkdir /host_mnt/Users/username/.docker/run/docker.sock: operation not supported 
```

# 解決方法

[actのgithubのissue2239](https://github.com/nektos/act/issues/2239#issuecomment-1979819940)に書いてあった方法で解決しました。

- `~/.actrc`に以下を追記する（.actrcがなければ作成する）

```
--container-daemon-socket -
```

# その他試したこと

- Docker Desktop for MacでFile sharingから/Usersを削除して再度追加を試したところうまくいきませんでした。
  - https://qiita.com/sho-hata/items/579ab597e4015b9f19fe
- actの実行時に`--container-architecture linux/amd64`をつけてみましたがうまくいきませんでした。
  - https://zenn.dev/the_exile/articles/41026a0b317e28
KUROKO Connectの接続先設定を試してみた

KUROKO Connectは、現場に設置したKUROKO Gearを踏み台にする方法以外に、
KUROKO Gearからネットワーク的に接続できる機器に直接アクセスする方法があります。
今回は、Windowsサーバーのリモートデスクトップ接続を試してみました。
検証で使用した構成は次のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/d32f9175-980e-c512-b6d2-857a992d4964.png)


:::note warn
直接接続はKUROKO Gearからネットワーク的に通信ができることが必要です。
ネットワークセグメントが KUROKO Gearとは異なる場合は、KUROKO Gearに静的ルート設定を入れる必要があります。
:::

# 1. ログイン
KUROKO Connectのログイン画面からログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/e9ef0f95-dd7e-32c6-e6a2-56ca5c4a11d5.png)

# ２. Apps一覧の選択
メニューの　管理＞Apps>Apps一覧　をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/ad245fbc-4951-fe5e-32e9-1c5229bd93d2.png)

# ３. KUROKO Gearの選択
現地に設置しているKUROKO Gear（Apps）を探して、「Actions」をクリック、「接続先一覧」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/e06d3309-25c4-effb-d37d-96f5a9e92d6f.png)

# ４. 新規登録の選択
接続先一覧の「新規登録」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/0809c91a-741b-dab2-5af9-d1cb227844c1.png)

# ５. 接続先の登録
接続先情報として、WindowsサーバーのIPアドレス、リモートデスクトップなのでポート番号 3389、プロトコル RDPとして登録します。

:::note info
**ポイント1**
KUROKO Connectの接続先情報はユーザー毎に制限を設けることが出来ます。

**ポイント2** 
プロトコル RDPを選ぶと、接続情報は RDPプロファイルがダウンロード出来ます。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/330a6aef-6381-7693-c034-589381b0115f.png)

# ６. リモートデスクトップ接続
登録が完了したら、早速リモートデスクトップ接続を試してみましょう。
メニュー＞接続をクリックして、該当KUROKO Gear（Apps）を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/056cc2f1-92ff-19df-6b5b-e1e9413a9b43.png)

# ７. Windowsサーバーの選択
接続先を先ほど登録した「Windowsサーバー」を選択して、「接続」ボタンを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/34df9f99-ea6e-8e16-81b6-80288f7235ca.png)

接続情報が表示されるまでしばらく待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/42584a09-1e77-b7e4-22ca-c971f024d756.png)

接続情報が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/5e722b18-7182-7249-bbf1-0fc875cc1deb.png)


接続情報をクリックすると、WidowsのリモートデスクトップクライアントのRDPプロファイルがダウンロード出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/b8b69071-81f4-9dab-c8e2-0e4f1b765afb.png)


# ８. ダウンロードしたファイルの選択
ダウンロードしたファイルをクリックすると、いつも利用しているリモートデスクトップ接続画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/447389d3-98f2-da16-f88c-80d735afb801.png)


# ９. サーバーの認証情報を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/a3a38267-e3d6-16af-7de8-bf4e9cadd4d2.png)
Windowsサーバーの認証情報を入力すると、直接現地のWindowsサーバーにリモートデスクトップが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3869727/d5f3710f-cda0-c4de-86ec-55beab54cb72.png)




接続先はTCPプロトコルであれば、どのような通信もKUROKO Connectで直接接続することが出来ます。

今回は接続先機能を利用して、現地のWindowsサーバーに直接接続する方法を試してみました。
paizaラーニング問題集「【文字列 3】p4!2@」を解いてみた

https://paiza.jp/works/mondai/b_rank_new_level_up_problems/b_rank_new_level_up_problems__leet_paiza

▼考え方

題意の通りコーディングしました。

▼コード
```py
########## 処理0(準備) インプット ###########

S = input()

########## 処理1 Leet表現が含まれるか判定する処理 ###########

for i in range(len(S)):
    
    if S[i] == "p":
        
        if S[i:i+5] == "paiza":
            print("paiza")
            exit()

        elif (S[i+1] == "a" or S[i+1] == "4" or S[i+1] == "@") and\
             (S[i+2] == "i" or S[i+2] == "1" or S[i+2] == "!") and\
             (S[i+3] == "z" or S[i+3] == "2") and\
             (S[i+4] == "a" or S[i+4] == "4" or S[i+4] == "@"):
            print("leet")
            exit()

print("nothing")
```
paizaラーニング問題集「【文字列 2】super long int」を解いてみた

https://paiza.jp/works/mondai/b_rank_new_level_up_problems/b_rank_new_level_up_problems__super_long_int

▼考え方

題意の通りコーディングしました。

▼コード
```py
########## 処理0(準備) インプット ###########

X = input()

########## 処理1 hash(X)の値を求める処理 ###########

print(int(X[0:8])+int(X[8:16])+int(X[16:24])+int(X[24:32]))
```
▼参考
X = "12345678123456781234567812345678"のとき、X[0:8]、X[8:16]、X[16:24]、X[24:32]はすべて"12345678"になります。
paizaラーニング問題集「【文字列 1】疑似数字」を解いてみた

https://paiza.jp/works/mondai/b_rank_new_level_up_problems/b_rank_new_level_up_problems__like_numbers

▼考え方

最初の文字を変数iで指定し、最後の文字を変数jで指定しました。最初の文字から最後の文字まで連続して取り出すため、スライス操作を使用しました。

▼コード
```py
########## 処理0(準備) インプット ###########

S = input()

########## 処理1 文字列Sから疑似数字を取り出す処理 ###########

for i in range(len(S)):

    for j in range(i+1,len(S)+1):

        # tmp_gizisuzi:文字列Sから取り出した文字列を格納する変数
        tmp_gizisuzi = S[i:j]
        
        if tmp_gizisuzi[0].isdigit() == True and tmp_gizisuzi[-1].isdigit() == True:
            print(tmp_gizisuzi)
```
▼参考
変数i,jを用いて文字列Sをスライス操作すると、以下のようになります。iとjが同じ値だと、なにも表示されないことに注意が必要です。
```
S = 81zaaz18

i: 0 j: 1 S[i:j]: 8
i: 0 j: 2 S[i:j]: 81
i: 0 j: 3 S[i:j]: 81z
i: 0 j: 4 S[i:j]: 81za
i: 0 j: 5 S[i:j]: 81zaa
i: 0 j: 6 S[i:j]: 81zaaz
i: 0 j: 7 S[i:j]: 81zaaz1
i: 0 j: 8 S[i:j]: 81zaaz18
----
i: 1 j: 2 S[i:j]: 1
i: 1 j: 3 S[i:j]: 1z
i: 1 j: 4 S[i:j]: 1za
i: 1 j: 5 S[i:j]: 1zaa
i: 1 j: 6 S[i:j]: 1zaaz
i: 1 j: 7 S[i:j]: 1zaaz1
i: 1 j: 8 S[i:j]: 1zaaz18
----
i: 2 j: 3 S[i:j]: z
i: 2 j: 4 S[i:j]: za
i: 2 j: 5 S[i:j]: zaa
i: 2 j: 6 S[i:j]: zaaz
i: 2 j: 7 S[i:j]: zaaz1
i: 2 j: 8 S[i:j]: zaaz18
----
i: 3 j: 4 S[i:j]: a
i: 3 j: 5 S[i:j]: aa
i: 3 j: 6 S[i:j]: aaz
i: 3 j: 7 S[i:j]: aaz1
i: 3 j: 8 S[i:j]: aaz18
----
i: 4 j: 5 S[i:j]: a
i: 4 j: 6 S[i:j]: az
i: 4 j: 7 S[i:j]: az1
i: 4 j: 8 S[i:j]: az18
----
i: 5 j: 6 S[i:j]: z
i: 5 j: 7 S[i:j]: z1
i: 5 j: 8 S[i:j]: z18
----
i: 6 j: 7 S[i:j]: 1
i: 6 j: 8 S[i:j]: 18
----
i: 7 j: 8 S[i:j]: 8
```
#5 gitでタグを削除する方法（ローカル、リモート）

# はじめに

リリース作業後、誤ってタグを作成してしまったので、削除しました。
削除する方法を調べてメモしておきます。

## ローカルのタグを削除する

```
git tag -d <tagname>
```

## リモートのタグを削除する

```
git push origin -d <tagname>
```

以上です。
【Supabase】insert or update on table "hoge" violates foreign key constraint "fuga"の解消方法

# はじめに
この記事では、Supabaseで中間テーブルとリレーションを設定する際に発生した「UNIQUE制約」に関するエラーについて取り上げます。特に、データ挿入時に発生した重複データによる問題と、その解決方法を解説します。

:::note warn
***この記事は<font color="Red">個人的なアウトプット</font>を目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです***。
:::

# 原因
以下のエラーメッセージが発生しました。
```
insert or update on table "users" violates foreign key constraint "users_user_id_fkey
```
このエラーは、外部キーの制約に違反していることを示しています。具体的には、外部キーに設定されているデータが、参照先のテーブルに存在しないか、他の制約により挿入がブロックされています。

# 解決方法

![スクリーンショット 2024-10-22 7.40.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835217/d9112686-c46b-6cc9-a87e-7f53cec1d5cd.png)

エラーの原因を調べたところ、`UNIQUE`制約が影響していることが判明しました。以下の画像の通り、`Is Unique`にチェックが入っていたため、同じ`user_id`や`skill_id`の組み合わせが複数挿入できない状態でした。

`UNIQUE`制約が設定されている場合、同じデータの重複挿入が制限されます。今回は`UNIQUE`制約を外すことで問題を解決できました。

制約を解除した後、`user_skill`テーブルに以下のようなデータを挿入できるようになりました。
```
user_skill テーブル:
-------------------------
user_id  | skill_id
-------------------------
101      | 1  (React)
102      | 1  (React)
103      | 2  (Vue)

```
このように、異なるユーザーが同じスキル（`skill_id`）を持っている場合でも、制約が解除されることでデータが正常に挿入できるようになります。

# 終わりに
外部キーの制約や`UNIQUE`制約は、データの一貫性を保つために重要ですが、今回のように状況に応じて制約を柔軟に解除することで、問題を解決することができました。特に中間テーブルを使用する際は、制約の設定に注意する必要があります。
M5NanoC6の内蔵ボタンで遊ぶ。


x 過去ログを見よ
x M5NanoC6.hのインストール

参考

https://qiita.com/caa45040/items/312a7f0cce234d9f8725

目的
ボタン入力をする

![o_coq534.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3b0f324a-d353-1482-9fb4-b9587f7b7bb2.jpeg)



結果


![o_coq536.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5999a91f-4ff5-2cfe-c3ce-5f517c6f17e8.jpeg)


![o_coq537.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b250416e-c4a9-b105-3a67-90271a6ef022.jpeg)


![o_coq535.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/2519e596-f7c7-baba-e7fb-ef41cdff9a2c.jpeg)


プログラム

```c++


/**
 * @file button.ino
 * @author SeanKwok (shaoxiang@m5stack.com)
 * @brief
 * @version 0.1
 * @date 2024-03-19
 *
 *
 * @Hardwares: M5NanoC6
 * @Platform Version: Arduino ESP32 Board Manager v3.0.0-alpha3
 * @Dependent Library:
 * M5NanoC6: https://github.com/m5stack/M5NanoC6
 */

#include <M5NanoC6.h>

void setup() {
    NanoC6.begin();
}

void loop() {
    NanoC6.update();
    if (NanoC6.BtnA.wasPressed()) {
        Serial.println("Button A was pressed");
    }
    if (NanoC6.BtnA.wasHold()) {
        Serial.println("Button A was hold");
    }
    if (NanoC6.BtnA.wasReleased()) {
        Serial.println("Button A was released");
    }
}


```
自分用テキストエディタを作った話

# はじめに

こばエディタという自分用のテキストエディタを作ってみました↓

https://github.com/natsuakane/KobaEditor

## なぜ作ろうと思ったか
* 普通のテキストエディタだとエディタと表示したブラウザを行き来するのが面倒だったのでブラウザ付きの物を作りたくなった
* GeminiのAPIが無料で使えることを知ったので、[Cursor](https://www.cursor.com/) みたいなチャット機能つきのエディタを作りたくなった
## 使ったもの
* C#
* VisualStudio2022
* Gemini API
## 参考
* [行番号付きリッチテキストボックスの作り方](https://umateku.com/archives/2340)
* [複数回アンドゥできるTextBox　自作コントロール](https://lets-csharp.com/textbox-undo/)
* [WinFormsでマークダウンエディタを作る](https://qiita.com/jeronimo34/items/608cf8d702f187eef948)

# 完成品
![スクリーンショット 2024-10-22 064904.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3572788/fcdda84b-ea03-1774-1687-505da38402d0.png)
右上のブラウザにはWebView2というパッケージを使っています
行番号付きのテキストボックスで編集できます
![スクリーンショット 2024-10-22 064950.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3572788/fcc2de88-1eca-a82a-c50f-877a583b01fa.png)
ターミナルは埋め込めなかったので代わりにpowershellを開けるようにしました
![スクリーンショット 2024-10-22 065028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3572788/92e00020-9f3e-90eb-efd4-05b4f731ad83.png)
左下の部分でGeminiと会話することができます。Markdigというパッケージを使ってマークダウンをHTMLに変換してからWebBrowserコントロールで表示しています。
![スクリーンショット 2024-10-22 065418.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3572788/9335be93-b579-e6f4-aae2-53faf0414c31.png)

## 機能
- 基本的なファイル機能
- 検索機能
- 置換機能
- ブラウザを使える
- Geminiと会話できる

ブラウザ枠やGemini枠の大きさは変えられるので多少のカスタマイズはできます。

# 感想
自分用に作ったものなので、vscodeとかと比べたら機能もしょぼいですが、それでも使いやすいなーと思いました（？）
あと、VisualStudioからGithubの操作をやったらぐちゃぐちゃになっちゃいました。（ただ慣れてないだけ）
【Supabase】Could not embed because more than one relationship was found for 'hoge' and 'fuga'の解決方法

# はじめに
Supabaseで中間テーブルとリレーションを設定する際に発生したエラーについての記事です。具体的には、外部キーの指定が原因で発生した問題を取り上げます。

# 原因
```react
  const { data, error } = await supabase
    .from("users")
    .select(
      `*, user_skill(skill_id, skills(id, name))`
    );
```

このようにリレーション設定を行い、`users`テーブルと`user_skill`テーブル、および`skills`テーブルからデータを取得しようとしていましたが、エラーが発生しました。

エラーメッセージは以下のようなものでした。

```
"Try changing 'skills' to one of the following: 'skills!user_skill_skill_id_fkey', 'skills!user_skill_skill_id_fkey1', 'skills!user_skill_skill_id_fkey10', 'skills!user_skill_skill_id_fkey11', 'skills!user_skill_skill_id_fkey12', 'skills!user_skill_skill_id_fkey2', 'skills!user_skill_skill_id_fkey3', 'skills!user_skill_skill_id_fkey4', 'skills!user_skill_skill_id_fkey5', 'skills!user_skill_skill_id_fkey6', 'skills!user_skill_skill_id_fkey7', 'skills!user_skill_skill_id_fkey8', 'skills!user_skill_skill_id_fkey9'. Find the desired relationship in the 'details' key."
```
Supabase側から表示されたこのヒントにより、外部キーの指定に問題があることがわかりました。

# 解決策
```react
  const { data, error } = await supabase
    .from("users")
    .select(
      `*, user_skill!user_skill_user_id_fkey(skill_id, skills!user_skill_skill_id_fkey(id, name))`//外部キーの設定を追加
    );
```
エラーに表示された複数の候補から正しい外部キーを選び、設定することで、データを正常に取得できるようになりました。

外部キーが複数設定されている場合、Supabase側はどのキーを使用するべきかを自動的に判断できないことがあります。この場合、手動で正しいキーを指定する必要があります。この挙動はSupabase固有の問題というより、PostgreSQLのルールによるものです。

https://github.com/supabase/supabase/issues/745

# 終わりに
Supabaseを利用した際に発生したエラーについて、外部キーの指定方法に注意する必要があることがわかりました。複数の外部キーがある場合には、手動で正しいキーを指定することが重要です。

# 参考

https://github.com/supabase/supabase/issues/745
openMSX ひらがな カタカナ 入力

[右Altキー]
    Kanaランプのon/off切り替え
    Kanaランプ点灯時に、ひらがな入力可
    
[左Altキー]
    Capsランプのon/off切り替え
    CapsランプとKanaランプ点灯時に、カタカナ入力可

https://openmsx.org/
Visual Studio CodeがDockerfile内でインストールできない場合の対処方法

# はじめに
　Visual Studio Code(以下、VSCode)を、Dockerfile内でインストールする際に、途中で止まってしまう現状が発生するようになったため、対処方法を紹介する。

 # 動作確認環境
 * Ubuntu 20.04


# 現象

　VSCodeをDockerfile内でインストール中に以下のメッセージが出て、インストールが途中で止まってしまう。

```bash
The installer would like to add the Microsoft repository and signing key to update VS Code through apt.
    Add Microsoft apt repository for Visual Studio Code? [はい/いいえ] 
```

# 対処方法

　方法は[公式ドキュメント](https://code.visualstudio.com/docs/setup/linux#_debian-and-ubuntu-based-distributions)に記載の通り。ポイントは、VSCodeをインストールするスクリプトの前に以下を実行することで、aptリポジトリ追加時のインタラクティブモードを無効にすることができる。

```bash
echo "code code/add-microsoft-repo boolean true" | sudo debconf-set-selections
```

上記を実行後に、以下のVSCodeのインストールスクリプトを実行する。

aptリポジトリの追加。
```bash
sudo apt-get install wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" |sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null
rm -f packages.microsoft.gpg
```
VSCodeのインストール。
```bash
sudo apt install apt-transport-https
sudo apt update
sudo apt install code # or code-insiders
```

Dockerfileの場合は以下のようにする。

```dockerfile
RUN echo "code code/add-microsoft-repo boolean true" | sudo debconf-set-selections && \
    wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg && \
    sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg && \
    echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" | sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null && \
    rm -f packages.microsoft.gpg
RUN apt install -y apt-transport-https && \
    apt update && \
    apt install -y code && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
```

# まとめ
 VSCodeをDockerfile内でインストールする際に、インストールが途中で止まってしまう場合の対処方法を紹介した。

# 参考

https://code.visualstudio.com/docs/setup/linux#_debian-and-ubuntu-based-distributions
2024/10/22主にITとかセキュリティの記事

HTTPS通信を解剖！ヘッダーの役割とセキュリティ強化の秘訣(10/20)
https://zenn.dev/qitaaa/articles/0192a44e-87a2-7132-afcb-9cb7ca26f4cf

ゲームフリークのハッキング事件に学ぶゲーム業界のセキュリティ課題とは？
https://cybersecurity-park.com/3199/

GPT-4やClaudeなどの大規模言語モデルが抱える「ストロベリー問題」とは？(10/19)
https://gigazine.net/news/20241019-strawberrry-problem/

「Web3.0」を小学生にも分かりやすく解説。「世界はどう変化するの？」に答えられますか？【親子で学ぶ現代技術】(10/20)
https://hugkum.sho.jp/617069

サイバーだより（令和6年第25号）飯田市(10/18)
https://www.city.iida.lg.jp/soshiki/5/cyber-dayori0625.html

「SNSアプリ改悪」続々スタート！個人情報が筒抜け「アポ電強盗と泥棒」が増える重大問題が発生(10/20)
https://news.livedoor.com/article/detail/27403909/

AIモデルのトレーニングとセキュリティをリアルタイムで監視するゲーム。(10/20)
https://qiita.com/tetsutakamurata76/items/9d52be0ff295c408f249

「Windows 12」まで待つはあり？――Windows 11移行の是非を考える(10/20)
https://techtarget.itmedia.co.jp/tt/news/2410/20/news02.html

【Delphi】Quality Central ブラウザを作った話(10/20)
https://qiita.com/ht_deko/items/ab9e13361ae31c4089e2

身代金型サイバー攻撃、ASEANの演習支援　総務省(10/20)
https://www.nikkei.com/article/DGXZQOUA08B6A0Y4A001C2000000/

連邦準備制度理事会 サイバーセキュリティと金融システムのレジリエンス報告書 2021-2024 (2024.07)(10/20)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/10/post-95e286.html

経団連 産業データスペースの構築に向けて (2024.10.15)(10/20)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/10/post-2d0ff4.html

「ロシアの暴力工作が激化」　ラトビア大統領に聞く
NATO、防衛増強は急務(10/20)
https://www.nikkei.com/article/DGKKZO84232240Q4A021C2EA3000/

名古屋市のHPがシステム障害　サイバー攻撃の可能性も(10/20)
https://news.yahoo.co.jp/articles/9aea9dc12da0c0dc8caee97b7face454ed248d1b

またサイバー攻撃か 県ホームページでアクセス障害 一時閲覧しにくい状況に 山梨(10/20)
https://news.yahoo.co.jp/articles/4a8efdd45869a3be6a2d63829fe5603178dff659?source=rss

再び海外からのサイバー攻撃か　山梨県のホームページが一時閲覧できない状態に　10月16日にも同じ状態に(10/20)
https://news.yahoo.co.jp/articles/c5c55411c191a10371b76ae3e99aae71cf663459?source=rss

パソコンで予想外すぎるバグ発生！　思わず叫んでしまう光景に納得　「本当にバグだ！！！」「ヒイィィィ！」(10/20)
https://news.yahoo.co.jp/articles/8de7ddb98de60885b99005408077c952b1069ed6?source=rss

AIが生成した偽情報による選挙工作が複数発覚、日本も制度整備を検討(10/18)
https://xtech.nikkei.com/atcl/nxt/column/18/00989/101000161/

強固なはずなのになぜ「暗号破り」が発生するのか、ランサムウエア復号の可能性を探る(10/21)
https://xtech.nikkei.com/atcl/nxt/column/18/02805/101800010/

統合進むセキュリティーサービス、XDRやSWGなど複数機能の連携がカギ(10/21)
https://xtech.nikkei.com/atcl/nxt/column/18/02982/101600001/

「DX推進委員会」に社長も参画するマルハニチロ、IT子会社をグループに戻し体制強化
マルハニチロ(10/21)
https://xtech.nikkei.com/atcl/nxt/column/18/02916/100900004/
TodoリストアプリTodoカンリをhtml,cssで作成する

# 初めに
Webシステムの仕組みを知りどうすれば要件通りの開発ができるようになるかを考えれるようになるためにTodoリストアプリを作成することにしました。<br>
バックエンド側のことはまず置いておいてデザインカンプまでをhtml,cssで作成しようと考えました。

# 作成するアプリのテーマを決める
タイトルと内容を決められるTodoアプリを作成したい<br>
Webシステムの仕組みを知ることが大事なので<br>
身近で使えるものを作成したいと考えました。

# アプリの機能を決める
今回はhtml,cssを使ってデザインカンプを作成したいので<br>
今後バックエンド側の作成のためにどのような機能を作りたいかをあらかじめ決めておきたいと考えました。<br>
ホーム画面にアプリの説明を書いておきます。<br>
ログイン画面でメールアドレスとパスワードを入力できるようにします。<br>
todo登録画面でタイトル、内容の入力ができるようにする。<br>
todoの一覧画面で修正、削除画面に飛ぶことができる。

# ユースケースを作成する
<img width="700px" alt="ユースケース" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682713/b9f43ce2-8783-378a-f911-10719c9a5591.png">
アプリの機能を元にざっとユーザができることを確認できるようにユースケースを作成することにしました。<br>
ログイン後todoの一覧、作成、編集、削除が行えるようにします。





# 画面遷移図を作成する
<img width="700px" alt="画面遷移図" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682713/e43b61dc-8ec9-2405-fce9-aae14a5f727c.png">
この画面遷移図では各機能の連携を表しています。



# ワイヤーフレームを作成する
<img width="700px" alt="wire_flame_note" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682713/da449134-5fe8-f9ef-b32d-4f0b749c9d5e.jpeg
">
こちらの画像では手書きのワイヤーフレームを作成したものを表示しています。<br>
ホーム、ログイン、todo新規登録、一覧画面を作成したものになります。画像の編集画面はtodo一覧画面になります。<br>
これを元にアプリを使って書き直したものが次になります。
<img width="700px" alt="wire_flame_1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682713/0e5d9356-8360-cc6f-4cd6-d5acdb3ef82f.png
">

一覧画面、新規登録画面を生成したものです。
<img width="700px" alt="wire_flame_2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682713/0133bda8-3da9-7830-5b19-0f32ecaed604.png
">
ホーム画面、ログイン画面を作成したものです。<br>
# 作成の注意
今回の開発で期間と自分で決めた仕様を守ることを意識したいと考えています。この開発は1週間当てて4画面で1.5日費やすことを想定しています。いろいろ予定があるのですが、納期に間に合わすことを目標に開発を進めていきたいと思います。ガントチャートを作成してリスケできる仕組みづくりをしていこうと思います。次に仕様を守ることについてはいろいろ開発している時に機能追加をしたくなると思います。ですが、まずは決めた4画面を開発することが大事にしようと考えます。その後で機能追加や変更したりする作業を行えばいいと考えているので仕様を守りながら開発することを守っていこうと思います。
CMSIS DSPのarm_fir_fast_q31のパフォーマンスの改善

# 概要
STM32のCortex-M系のCMSIS DSPのarm_fir_fast_q31のパフォーマンスがおかしかったので、原因と対処方法についてメモを残しておきます。
過去の[こちら](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82034)を参考にさせていただき、今回改めて調査して対応した内容をまとめてみました。

# 条件
* STM32のCortex-M4/M7系のマイコン (確認済みはSTM32F446,G431,L432,L4R5,H743)
* CubeIDE 1.16.1
* GNU Tools for STM32 (12.3rel1)
* CMSIS DSP 1.16.2
* CMSIS DSPの`Include`,`PrivateInclude`,`Source`をプロジェクトフォルダ内に配置
* 最適化オプションは-O3または-Ofastを使用 (->どちらでも結果は同じ)
* Predefineに`ARM_MATH_CM4(or7)`,`ARM_MATH_LOOPUNROLL`をセット

# 原因
`Include/dsp/none.h`内の以下の`multAcc_32x32_keep32_R`マクロのコンパイル結果が`SMMLAR`にならないことが原因です。
```
#define multAcc_32x32_keep32_R(a, x, y) \
    a = (q31_t) (((((q63_t) a) << 32) + ((q63_t) x * y) + 0x80000000LL ) >> 32)
```
デバッグのDisassemblyでarm_fir_fast_q31内のマクロ使用箇所を確認すると、`SMMLAR`が使用されていません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3916132/a735e635-6897-b46f-d93e-3340e064900a.png)

ちなみに`SMMLAR`は丸め有りの32bitx32bit=32bit(H)の積和演算([参照](https://developer.arm.com/documentation/ddi0403/d/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-ARMv7-M-Thumb-instructions/SMMLA--SMMLAR))です。

過去の参照記事では、-O3または-Ofast設定で最適化をかけることでSMMLARが使用される、といった内容が書かれていますが、そうなっていないので今回記事にしてみた次第です・・・

# 対応方法
`none.h`の問題のマクロを`SMMLAR`のinlineアセンブラに置き換える。
```
#define multAcc_32x32_keep32_R(a, x, y) \
	__ASM ("smmlar %0, %1, %2, %3" : "=r" (a): "r"  (x), "r" (y), "r" (a) )
```
SMMLARは`4つのレジスタ`を指定する必要がありますので、マクロの引数に合わせてレジスタを記述します。特に今回の場合、`1つ目の出力先のレジスタ%0`と`4つ目の累積値を格納するレジスタ%3`が同じレジスタであることに注意してください。また、__ASMの後ろにvolatileをつけても良いかもしれません（今回は無くても動作しています）。

デバッグのDisassemblyでマクロ使用箇所を確認すると`SMMLAR`が使用されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3916132/85756872-c4d3-5e86-0879-709f7203e3d3.png)


# 結果
STM32G431を使用し、36tapsのフィルタ、240samplesの入力データ数でarm_fir_fast_q31を実行したCYCCNT測定結果は以下の通りです。
|  | CYCNT数 |
|:-:|:-:|
| 対応前 | 53187 |
| 対応後 | 24774 |

よって、50%以上の負荷削減となりました。

# 考察
今回はSMMLARがコンパイル時に使用されないことが原因でしたが、同様にnone.hで定義されているmultSub_32x32_keep32_R(SMMLSRのマクロ),SMMULR(mult_32x32_keep32_Rのマクロ)などでも同じ問題が発生すると考えられます。よって、これらも今回と同じ方法(inlineアセンブラで置き換え)をすべきと考えます。
　
　
ただし、そもそもコンパイルでマクロが想定通りのinstructionになればこの対応は必要ないので、スマートにコンパイルの設定で解決する方法を探しています・・・
三項演算子とは？

### 概要
三項演算子は、条件式によって値を簡潔に返すために使われる構文です。今回は、Python、Java、Swift、C#での三項演算子の書き方を紹介します。

三項演算子とは？
三項演算子は、**「条件式 ? 真の値 : 偽の値」**という形式で、条件によって返す値を決定する構文です。これにより、if-else文を使わずに簡潔に条件判定を行うことができます。

それでは、各言語での具体的な使用例を見ていきましょう。

#### 1. Javaでの三項演算子
Javaでは、三項演算子は「条件式 ? 真の値 : 偽の値」の形式で書きます。

サンプルコード
```java
public class Main {
    public static void main(String[] args) {
        int number = 10;
        String result = number > 0 ? "Positive" : "Negative";
        System.out.println(result);  // Output: Positive
    }
}
```
##### 説明
number > 0 の結果に基づき、条件がTrueの場合は "Positive"、Falseの場合は "Negative" が返されます。
#### 2. Swiftでの三項演算子
Swiftも三項演算子は「条件式 ? 真の値 : 偽の値」という形式で書きます。

サンプルコード
```swift
let number = 10
let result = number > 0 ? "Positive" : "Negative"
print(result)  // Output: Positive
```
##### 説明
number > 0 がTrueなら "Positive" が返され、Falseなら "Negative" が返されます。
#### 3. C#での三項演算子
C#でも同様に「条件式 ? 真の値 : 偽の値」の形式で書きます。

サンプルコード
```csharp
using System;

class Program {
    static void Main() {
        int number = 10;
        string result = number > 0 ? "Positive" : "Negative";
        Console.WriteLine(result);  // Output: Positive
    }
}
```
##### 説明
number > 0 の条件がTrueであれば "Positive"、Falseであれば "Negative" が返されます。
#### 4. Pythonでの三項演算子
Pythonでは三項演算子は「真の値 if 条件式 else 偽の値」という順序で書きます。

サンプルコード
```python
# 条件がTrueなら 'Positive'、Falseなら 'Negative' を返す
number = 10
result = "Positive" if number > 0 else "Negative"
print(result)  # Output: Positive
```
##### 説明
number > 0 がTrueなら "Positive" が返され、Falseの場合は "Negative" が返されます。

### まとめ
各言語での三項演算子は、条件によって真の値か偽の値を簡潔に返すことができます。共通点として、「条件式 ? 真の値 : 偽の値」という形式が多くの言語で採用されており、コードの短縮や可読性の向上に役立ちます。

##### 各言語の違い
Pythonでは「真の値 if 条件式 else 偽の値」の形式を使い、他の言語と順序が異なりますが、直感的に理解しやすい形です。
**Java、Swift、C#**では、ほぼ同じ書き方をしています。
三項演算子は、短く簡潔なコードを記述したい場合に非常に便利ですので、ぜひ使ってみてください！
SwiftでEnumとSwitchを使って条件分岐をシンプルに！〜フルーツとエラーコードの実用例〜

### 概要
現場のリーダーからSwiftのenumとswitchは、条件分岐をシンプルかつわかりやすく記述するのに最適なツールだからしっかり使おう！との指摘がいただいたので今回は、果物の種類(半分ネタ)を処理する場合と、エラーコードを処理(半分本気)する場合の2つのシチュエーションに焦点を当てて、それぞれの実用例を紹介します。

フルーツコードをenumで処理し、対応する名前を返す。
エラーコードをenumで処理し、対応するエラーメッセージを返す。
これにより、条件分岐が複雑になりがちな場面でも、enumとswitchを使ってシンプルに記述できるようになります。

#### 1. フルーツコードを処理する
コード例
フルーツのコード値を受け取り、それに応じた果物の名前を返す例です。

```swift
import Foundation

// 果物の種類を表すenum
enum Fruit: Int {
    case apple = 1
    case banana = 2
    case orange = 3
    case unknown // 該当しない場合
}

// 整数からenumに変換する関数
func convertToEnum(from code: Int) -> Fruit {
    return Fruit(rawValue: code) ?? .unknown
}

// enumに基づいて果物の名前を返す関数
func getFruitName(from code: Int) -> String {
    let fruitEnum = convertToEnum(from: code)

    switch fruitEnum {
    case .apple:
        return "This is an Apple."
    case .banana:
        return "This is a Banana."
    case .orange:
        return "This is an Orange."
    case .unknown:
        return "Unknown fruit."
    }
}

// 使用例
let fruit1 = getFruitName(from: 1)  // "This is an Apple."
let fruit2 = getFruitName(from: 2)  // "This is a Banana."
let fruit3 = getFruitName(from: 3)  // "This is an Orange."
let fruit4 = getFruitName(from: 99) // "Unknown fruit."

print(fruit1)
print(fruit2)
print(fruit3)
print(fruit4)
```
実行結果
```
This is an Apple.
This is a Banana.
This is an Orange.
Unknown fruit.
```
このコードでは、フルーツのコードを整数で受け取り、enumに変換してからswitchで分岐しています。対応する果物があればその名前を返し、該当する果物がない場合は「Unknown fruit」を返します。

#### 2. エラーコードを処理する
コード例
エラーコードを受け取り、それに応じたエラーメッセージを返す例です。

```swift
import Foundation

// エラーコードを表すenum
enum ErrorCode: Int {
    case notFound = 404
    case unauthorized = 401
    case serverError = 500
    case unknown // 該当しない場合
}

// 整数からErrorCodeに変換する関数
func convertToErrorCode(from code: Int) -> ErrorCode {
    return ErrorCode(rawValue: code) ?? .unknown
}

// ErrorCodeに基づいてエラーメッセージを返す関数
func getErrorMessage(from code: Int) -> String {
    let error = convertToErrorCode(from: code)

    switch error {
    case .notFound:
        return "Error 404: Resource not found."
    case .unauthorized:
        return "Error 401: Unauthorized access."
    case .serverError:
        return "Error 500: Internal server error."
    case .unknown:
        return "Unknown error."
    }
}

// 使用例
let errorMessage1 = getErrorMessage(from: 404)  // "Error 404: Resource not found."
let errorMessage2 = getErrorMessage(from: 401)  // "Error 401: Unauthorized access."
let errorMessage3 = getErrorMessage(from: 500)  // "Error 500: Internal server error."
let errorMessage4 = getErrorMessage(from: 999)  // "Unknown error."

print(errorMessage1)
print(errorMessage2)
print(errorMessage3)
print(errorMessage4)
```
実行結果
```
Error 404: Resource not found.
Error 401: Unauthorized access.
Error 500: Internal server error.
Unknown error.
```
このコードでは、エラーコードを整数で受け取り、enumに変換してからswitchで分岐しています。対応するエラーコードがあればそれに応じたエラーメッセージを返し、該当しない場合は「Unknown error」を返します。

まとめ
enumとswitchを組み合わせることで、複雑な条件分岐をシンプルかつわかりやすく表現できます。今回紹介したフルーツのコード処理やエラーコードの処理のように、数値データを扱う際にenumを活用することで、可読性が高く、保守性の良いコードを書くことが可能です。

実際のアプリケーションでも、状態管理やエラーハンドリングでenumとswitchをうまく活用し、効率的なコードを目指しましょう！
numpy で高速に区間列どうしの要素を対応付ける

## やりたいこと
一次元の区間`(s,t)`の集合が2つ(`s1` と `s2`)存在する。
`s1`中のある要素`s1_i`が、`s2`中のどの要素`s2_j`に対応するかを表現する組合せF `(F: s1 -> s2)`を作りたい。
![ 2024-10-22 0.08.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511585/ad161e8f-f109-4b24-e380-7da117ebe0b4.png)

### 詳細な条件
1. `s1` と `s2`は、それぞれ $10^3$ 個程度の要素を持つ
2. 対応付けは1分以内に完了したい


## 方針
- 全ての`s1_i`と`s2_j`で Intersection over Union (IoU)を計算
    - IoUを一言でいうと、2つの要素における重なりの比率
    - 参照: [【精度指標】IoUとは
](https://qiita.com/CM_Koga/items/82d446658957d51836cf)
- `s1_i`ごとに、IoUが最大値となる`s2_j`を取得する

## 実装
```python
import numpy as np


def alignment_sequence(s1: np.ndarray, s2: np.ndarray) -> np.ndarray:
    assert s1.shape[1] == 2, f"Expected shape (n, 2), got {s1.shape}"
    assert s2.shape[1] == 2, f"Expected shape (m, 2), got {s2.shape}"

    # strat1, end1: (n, 1)
    start1, end1 = np.expand_dims(s1[:, 0], axis=1), np.expand_dims(s1[:, 1], axis=1)

    # strat2, end2: (1, m)
    start2, end2 = np.expand_dims(s2[:, 0], axis=0), np.expand_dims(s2[:, 1], axis=0)

    # union, intersection, iou_matrix: (n, m)
    union = np.maximum(end1, end2) - np.minimum(start1, start2)
    intersection = np.maximum(np.minimum(end1, end2) - np.maximum(start1, start2), 0)
    iou_matrix = intersection / union
    
    # 最もIoUが高いものを選択
    best_matches = iou_matrix.argmax(axis=1)

    return {
        s1_i: s2_j for s1_i, s2_j in enumerate(best_matches)
    }
```

## ちょっと解説
### 2つの区間の IoU の求め方
- Intersection (共通部分): "start1とstart2の大きい方" から "end1とend2の小さい方" までの区間
- Union (和集合): "start1とstart2の小さい方" から "end1とend2の大きい方" までの区間
- IoUは、Intersection を Union で除したもの
![ 2024-10-22 2.16.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511585/bafbe329-a185-b0d1-422d-3675ecb6d16f.png)


### union, intersection, iou_matrix の計算過程
- `end1` の形状は `(n, 1)` で、`end2` の形状は `(1, m)` なので、`np.maximum`中でブロードキャストされて `n` x `m`の全ての要素同士が比較される
```py
np.maximum(end1, end2) # union - end
np.minimum(start1, start2) # union - start
np.minimum(end1, end2) # intersection - end
np.maximum(start1, start2) # intersection - start
```

## 使い方
### `s1` と `s2`の長さが同じとき
```python
s1 = np.array([[1, 2], [2, 5], [6, 10]])
s2 = np.array([[0, 3], [3, 7], [7, 12]])
alignment = alignment_sequence(s1, s2)
print(alignment)
```
次の結果が得られる
```d
{0: 0, 1: 1, 2: 2}
```

### `s1` と `s2`の長さが違うのとき
```py
s1 = np.array([[1, 3.2], [3.4, 5.8], [6, 8], [8.1, 10]])  # 4つのセグメント
s2 = np.array([[0, 3], [3.1, 6.1], [6.5, 10]])  # 3つのセグメント
alignment = alignment_sequence(s1, s2)
print(alignment)
```
次の結果が得られる
```d
{0: 0, 1: 1, 2: 2, 3: 2}
```

## スピードの検証
TODO


### 追記
コメントでいただいた実装が綺麗なので掲載．
これのほうが好みです．

```
def alignment_sequence(s1: np.ndarray, s2: np.ndarray) -> np.ndarray:
    tmp_array = np.maximum(s1, s2[:, None]) - np.minimum(s1, s2[:, None])[:, :, ::-1]
    best_matches = np.argmin(tmp_array[:, :, 0] / tmp_array[:, :, 1], axis=0)
    return dict(enumerate(best_matches))
```
【第２回 NTT東日本 豊岡大地さん】2024 Japan AWS Jr. Champions インタビュー企画

こんにちは！2024 Japan AWS Jr. Championsのtekutaです！
AWS Japanが6月に開催したAWS Summit Japanにて、2024 Japan AWS Jr. Championsが発表されました。Jr.Championsは、AWSを積極的に学び、アクションを起こし、周囲に影響を与えている若手エンジニア向けの表彰プログラムとなっております。Jr.Championsについて多くの方に知ってもらいたいため、表彰された方々にインタビューをしていきます。
第2回目は、NTT東日本の豊岡大地さんです！!
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310014/9de760b8-876c-e8f0-8aa1-92dab00d139a.png" width=70%>

https://aws.amazon.com/jp/blogs/psa/2024-japan-aws-jr-champions/

# 質問１：これまでの経歴、現在の業務、AWSを知った経緯を教えてください。
クラウドの部署に配属され、1~2年目は主に社内DXの内製化プロジェクトに参画して、サーバーレスアプリケーションに関わる技術を中心にパブリッククラウドスキルを向上させました。現在はAmazon Connectを活用したコンタクトセンタの構築やデータセンターへのトラフィック制御基盤構築のプロジェクトに携わってます。また、AWSは大学院生時代のインターンシップ先で知りました。

# 質問２：Jr.Championsを目指した理由、選出につながったと考える活動があれば教えてください。
同世代のAWSエンジニアと交流が少なかったため、高い技術力がある人と関わりたいと思い目指しました。社内でのLT会等を企画した部分が評価につながったと考えております。

# 質問３：Jr.Championsとして現在どのような活動をしていますか。
技術的な分野で活躍したいと考えており、JrChampions内外の勉強会への登壇を積極的に実施しております。すでにJr.Championsとして4回登壇させていただきました。

# 質問４：Jr.Championsに選出されてよかったことはありますか。
クラウド人材としての知名度が向上し、社内で携われるプロジェクトが増えたことです。
また表彰されたことが一つの成果として認めていただいて、AWS re:Inventに参加する機会をいただけたことです！

# 質問５：Jr.Championsに選出されて大変だったことはありますか。
ありがたいことに携わるプロジェクトが増えたので、ひっぱりだこになっていることです（笑）

# 質問６：Jr.Championsと併せてAll Certifications Engineersも受賞おめでとうございます！目指そうと思ったきっかけを教えてください。
クラウド人材として信頼性を高めるために、資格取得を目指しました。また、IT初学者だったということもあり、広くIT知識を付けるために勉強しました。AWSに限らない普遍的なIT知識を同時に習得できたことはとても有意義だったと感じています。

# 質問７：All Certifications Engineersに選出されてよかったことはありますか。
クラウド人材として自分に自信を持てたことが良かったと感じています！

# 質問８：今後の夢や目標はありますか。
出会えたJr.Championsの方々と引き続き交流していきたいです！
目標はインフラからアプリレイヤーに加えて、MSP・SREなどの運用フェーズでも、活躍できるようなエンジニアです！加えて来年度のAWS Top Engineersの選出を目指しています！

# 質問９：Jr.Championsを目指す若手に向けてメッセージをお願いします。
Jr.Championsの方々はみなさん向上心が高く、刺激のある環境です。Jr.Championsとしての活動は楽しいことが多いので、ぜひ目指してください！

# 質問１０：全体を通しての質問
## AWSで今後気になっている、触ってみたいサービスはありますか。
AWS Control Towerです。
企業のアカウント等でも迅速に安全なマルチアカウント構成を設定できるので、一度触ってみたいです。

## 好きなAWSサービスはなんですか。
Amazon ConnectとLambdaです！
特にAmazon Connectは電話サービスを検討するにあたって、事前知識なく取り組めるサービスになっています。加えて生成AIとの組み合わせ等カスタマイズもできるので魅力的なサービスと感じています。


# 最後に
社会人4年目と若手の豊岡さんは、ベテランエンジニアと感じるほど高い技術力があり、AWS Top Engineers選出の期待も高まります。豊岡さんの登壇はAWSの技術的な内容に特化しているので、今後の登壇も楽しみです。

次回もぜひご覧ください。

![pic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310014/f46af2d4-8880-c58a-bf92-af91f60ebe2d.png)
Swiftで関数をペアにしてスタック処理をシミュレートしてみた

### 概要
Swiftで関数をペアで扱い、スタックのような操作をシミュレートする方法を紹介します。特に、追加や削除、生成や消費といった操作を1対1で設計することで、コードの整合性や管理がしやすくなることを目的としています。

今回は「果物を育てる」から「果物を売る・食べる」といった具体的なシチュエーションを使って、関数の対になる動作をわかりやすく表現してみました。

### 背景
あるプロジェクトで、関数を1対1で設計するように指示がありました。例えば、リソースを「追加する」関数がある場合、その逆の操作（「削除する」）も用意するという指針です。

このアイデアを応用して、ビジネスや生活の中で行われる動作（育てる、卸す、売る、食べる）を関数でペアリングし、スタックのような流れでシミュレーションしてみます。

### 実装例
#### 1. FruitManagerクラス
以下が果物を管理するクラスFruitManagerです。このクラスでは、果物を育てたり、卸したり、売ったり、食べたりする操作ができます。それぞれの操作は対になる形で関数が存在しており、スタックのように順に処理されます。

```swift
import XCTest

// 果物を管理するクラス
class FruitManager {
    private var fruits: [String] = []
    
    // 果物を育てる
    func growFruit(_ fruit: String) {
        fruits.append(fruit)
        print("\(fruit) を育てました。")
    }
    
    // 果物を卸す
    func wholesaleFruit(_ fruit: String) {
        if let index = fruits.firstIndex(of: fruit) {
            print("\(fruit) を卸しました。")
        } else {
            print("\(fruit) は育てていないので卸せません。")
        }
    }
    
    // 果物を売る
    func sellFruit(_ fruit: String) {
        if let index = fruits.firstIndex(of: fruit) {
            print("\(fruit) を売りました。")
        } else {
            print("\(fruit) は卸されていないので売れません。")
        }
    }
    
    // 果物を食べる
    func eatFruit(_ fruit: String) {
        if let index = fruits.firstIndex(of: fruit) {
            fruits.remove(at: index)
            print("\(fruit) を食べました。")
        } else {
            print("\(fruit) は存在しないので食べられません。")
        }
    }
    
    // 現在の果物リストを表示
    func printFruits() {
        print("現在の果物リスト: \(fruits)")
    }
}
```

#### 2. 関数ペアのシミュレーション
次に、果物を育て、卸し、売り、食べるという一連の流れをシミュレーションするクラスを作ります。このクラスでは、growFruit()とeatFruit()、wholesaleFruit()とsellFruit()がそれぞれ対になった操作を行います。

```swift
// 関数のスタック操作を模倣したシナリオ
class FruitOperationsSimulation {
    private let fruitManager = FruitManager()
    
    // 果物の育成と操作をシミュレート
    func simulate() {
        print("シミュレーション開始")
        
        // 1. 果物を育てる
        fruitManager.growFruit("Apple")
        fruitManager.growFruit("Banana")
        
        // 2. 果物を卸す
        fruitManager.wholesaleFruit("Apple")
        
        // 3. 卸した果物を売る
        fruitManager.sellFruit("Apple")
        
        // 4. 残っている果物を食べる
        fruitManager.eatFruit("Banana")
        
        // 現在のリストを表示
        fruitManager.printFruits()
        
        print("シミュレーション終了")
    }
}

// シミュレーション実行
let simulation = FruitOperationsSimulation()
simulation.simulate()
```

実行結果
このシミュレーションを実行すると、以下のような結果が得られます。

```less
シミュレーション開始
Apple を育てました。
Banana を育てました。
Apple を卸しました。
Apple を売りました。
Banana を食べました。
現在の果物リスト: []
シミュレーション終了
```

growFruit() と eatFruit(): 果物を育てて、最終的に消費する操作のペア。
wholesaleFruit() と sellFruit(): 卸して売るという商業的な操作のペア。
#### まとめ
この実装では、1対1の関数をペアで設計することで、処理の流れを明確にし、スタックのような順序で関数を実行できる形を作りました。これにより、コードの整合性を保ちやすくし、さらにビジネスや日常生活における一連の流れをシンプルに表現できます。

関数のペアリングは、シンプルな操作を分かりやすく設計するのに非常に有効です。実際のプロジェクトでも、リソースの管理やアクションの実行に対して、こうしたペアの設計を取り入れると、保守性の高いコードが書けるでしょう。
文字にアニメーションを適応する、erminaltexteffectsのwindows下での導入 【python】


# 経緯
![オエー鳥_軽量.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907383/a1bca90c-74b6-06ee-3507-a12ac14221b9.gif)

面白そうなモジュールがあったので動かしてみた、
自分の環境(windows)ではレジストリを編集しないと動かない感じだったので備忘録化。

ちなみにQiitaで記事を書いてみたかったので初投稿です。

# インストール
普通にpipでインストールできる。
~~~ コマンドプロンプト
pip install tarminaltextefect
~~~

# 基本コマンド
~~~コマンドプロンプト
echo 出力したい文章 | tte beams
~~~
とりあえず標準出力してみる。
terminaltextefectはtteコマンドで使用できる。今回はbeamエフェクトを適応。


# エラー
結果：画面に収まりきらない謎テキスト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907383/eaaf4f32-b3e3-0f3c-95d7-5962a1218959.png)
出力には成功しているが、うまく表示されていない。
どうやら、ANSIエスケープシーケンスというものを解釈できてないようなので、
レジストリで設定を有効にする必要がある。

# レジストリ設定
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907383/0203312a-500c-2787-bf1c-39ac16f960eb.png)

 **1.win+R でレジストリエディタを開く** 
**2.HKEY_CURRENT_USER\Consoleを探す(多分いちばん下にある)**
**3.メニューバーから、編集(E)→新規(N)→DWORD(32ビット)値(D)より「VirtualTerminalLevel」という名前のキーを作成
4.作成したキーの値を１に設定**

このように設定を変更すれば動くはず。

# 再トライ
~~~tst.py
from terminaltexteffects.effects.effect_rain import Rain

# テキストファイルを開いて行をリストに格納
with open('AA.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()

# リストの内容を1つの文字列に結合
text_data = ''.join(lines)

# エフェクトに文字列データを渡す
effect = Rain(text_data)

# エフェクトを適用して出力
with effect.terminal_output() as terminal:
    for frame in effect:
        terminal.print(frame)
~~~
#### 出力結果
![オエー鳥_軽量.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907383/a1bca90c-74b6-06ee-3507-a12ac14221b9.gif)
### オエーー！！！！

エフェクトの適応先はAA.txt、同ディテクトリに作成しておくこと。

コマンドプロンプトだとスペースが"◯"で表示されてしまい見づらかったのでPowerShellでの実行に変更した。
余談だが、大きいAA(アスキーアート)は表示が崩れてしまい見られたものではなかった。

# 環境
- [x] windows10 ver22H2
- [x] python 3.12.2
- [x] terminaltexteffects 0.11.1

# ドキュメント
https://chrisbuilds.github.io/terminaltexteffects/
ゲームプログラマのための設計：スコープ再考①（変数編）

[ゲームプログラマのための設計シリーズ](https://qiita.com/kobitnex/items/93397d985682c806884c)：原理・原則編の記事です。

# 概要
* 「その変数が現在の値に至るまでに確認すべき事象の多さ」を考えてみよう
* それゆえ、ローカル変数/const変数を優先しよう

# 本文
今更ですが、C++において変数のスコープはグローバル・メンバ・ローカルの３種類ありますね。
そして、メンバ変数・ローカル変数にはそれぞれにストレージクラス（static/非static）の分類が付きます。
さらに、それぞれconst修飾子が付きます。
```cpp
// グローバルスコープ
int global;            // グローバル変数
const int cglobal = 0; // constグローバル変数 

// クラススコープ
class C
{
    int mMember;                   // メンバ変数
    const int cMember = 0;         // constメンバ変数
    static int sMember;            // 静的メンバ変数
    static const int scMember = 0; // 静的constメンバ変数
};

// ローカルスコープ
void f()
{
    int local;                    // ローカル変数
    const int clocal = 0;         // constローカル変数 
    static int slocal;            // 静的ローカル変数
    static const int sclocal = 0; // 静的constローカル変数
}
```
設計の観点では、
スコープ：ローカル > メンバ > グローバル
ストレージ：非static > static
const性：const > 非const
の順に性質が良いです。それには、__「その変数が現在の値に至るまでに確認すべき事象の多さ」__ が関係しています。

一番厳しいケースのグローバル変数では、
```cpp
int global;  // グローバル変数

void func0()
{
    if (...)
    {
        ++global;
    }
    else
    {
        global = 0;
    }
}

void func1()
{
    for (...)
    {
        global += i:
    }
}
```
globalの値の変化を調べるには、プログラムが起動して以来すべてのfunc0/func1の呼び出しを追いかける必要があります。しかも、globalを触る関数はどこでも誰でも簡単に増やせてしまいます。これは大変ですね。

(private)メンバ変数では、
```cpp
class C
{
    int mMember; // メンバ変数

    void func0()
    {
        if (...)
        {
            ++mMember;
        }
        else
        {
            mMember = 0;
        }
    }

    void func1()
    {
        ...; // mMemberを使った何かしらの処理
    }
};
```
このクラスのインスタンスが生成されて以降の、すべてのfunc0/func1の呼び出しを追いかけることになります。mMemberを触るにはこのクラスのメンバ関数でなければならないので、グローバル変数より幾分かましになりました。

一方ローカル変数では
```cpp
void func()
{
    int local = ...; // ローカル変数

    if (...)
    {
        ++local;
    }
    else
    {
        local = 0;
    }
}
```
これまで何回funcが呼ばれたか考える必要もないですし、今後コードが追加されようともfuncの中を見れば済むことに変わりはなく、優しいです。

最後に、constであれば初期化された部分を読めばいいだけなので最高ですね。

この厳しい・優しいを独断で点数付けしてみましょうか。
|  |  |
|:-:|:-:|
| 静的const変数  | 0 |
| constローカル変数/constメンバ変数  | 1 |
| ローカル変数  | 10 |
| メンバ変数  | 100 |
| グローバル変数  | 1000 | 

グローバル変数がやり玉に挙げられることが多いですが、メンバ変数もなかなか曲者であるということを認識いただければと思います。
この点数の高い危険な変数をいかに減らすか・危険な変数に触る関数をいかに減らすか　という目標のために設計があると言っても過言ではありません。それゆえ、一番最初に取り上げさせていただきました。

次回は、関数側について着目してみましょう。
[後編](https://qiita.com/kobitnex/items/b7093143d06029021b93)
問診票システムをリニューアルしました

こんにちは。

テックリードのTerukiです。

本日はOh my teeth導入クリニックで使用している問診票システムの裏側について話してみたいと思います。

# TL;DR
- 以前はTypeformを使った問診票だった
- 100%自前開発でリニューアルしてカッコよくなった

# そもそも今までどうだったのか

マウスピース矯正をするための無料歯型スキャンの予約をした人向けに問診票の回答をお願いしているのですが、以前はありもののサービスで実現していました。

Typeformを使って下記のようなものを提供していました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/42ccd7c5-113b-8281-37fb-989af3bb254f.png" width="300">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/2152344a-d9f4-eabb-b423-54edcb0ce17d.png" width="300">

そもそも現代の歯医者さんでは紙で問診票を回答していただいているところが多いと思うので、事前にスマホから回答出来る時点でとてもOh!なのですが、会社が大きくなりユーザーも非常に増えてきたところもあるので、やはり細部にももっとこだわっていきたいところです。

# 自前で作りました

7月頃からOh my teethのUXチームで他社などの問診票システムのリサーチを始め、どのようなUXがOh my teethにとって最適か吟味を始めました。

結果、下記のようなチャット形式の問診票が現代的且つ、スムーズな回答体験を得られるということでこの形式に決まりました。
Oh my teethが大切にしているユーモアを出しやすそうというのもポイントが高かったです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/4a1bbc50-45a1-e550-3dcb-d127a9b7a9c7.png)

フロントエンドはReact、バックエンドはASP.NET Core(C#)で作られています。

Oh my teethは今のところフロントエンドをすべてReactに統一しています。

バックエンドはあまり聞き慣れない人もいるかもしれませんが、Microsoftが開発・管理している.NET製です。

テックリードとしていろいろな言語のフレームワークを見てきましたが、.NETは実装に必要なライブラリの大半がファーストパーティ製のもので揃うのが個人的には非常に魅力的です。

見た目だけでなくバックエンドの設計にもかなりこだわっていて、問診票のカスタマイズ性を上げるために問診内容をjsonで保存してフロントエンドのコードを変更しなくても問診票を変更できるような設計にしてあります。

実際、新問診票リリースの予定日の直前に問診項目の変更などがあり少しひやひやしましたが、フロントエンドの修正を一切せずに項目の変更を実現できました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/7db31ad0-8a9d-d054-6d7e-a7a382d53c45.png" width="300" />

ER設計の難易度としてはかなり高めだったとは思うのですが、そういった難易度の高い開発もチームメンバーの技術力を合わせて実現できるのも今のチームの良さだなと勝手に思っています。

問診票にはリーガル要件を満たすために住所を入力するフォームがありますが、もちろん郵便番号を入力したら自動で補完されるようになっています。今では当たり前のような機能ですがTypeformでは実現できなかったものです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/140d0f71-25d7-f908-6c0d-3d4408d17cec.gif" width="300" >

これ以外にも実は使っているシステムのほとんどを内製しているのですが、その話は長くなるのでまた今度にしようと思います。

この問診票は[公式サイト](https://www.oh-my-teeth.com/?tags=qiita_interview_sheet)から無料歯型スキャンを予約してフローを進めると回答する画面にたどり着きます。

気になる方は予約して確認してみてください。


今回はこの辺で。次回をお楽しみに！


# Oh my teethについて
Oh my teethでは未来の歯科体験を創るために日々活動しています。

Techチームではより良いユーザー体験を提供するべく、Webフロントエンドからバックエンド、スマホアプリに機械学習モデルなど、さまざまなプロダクトを開発しています。

一緒に未来の歯科体験を創りませんか？興味がある方は是非こちらを確認してください。

https://oh.careers/

カジュアル面談も可能なので気軽に応募してみてください！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/0138b492-e02b-852e-61fa-fc065b53d285.png" width="450" />
JSONPlaceholder から axios でデータを取得する

## JSONPlaceholderとは
テストやプロトタイピングのために提供される無料の`REST API`です。`GET`, `POST`, `PUT`, `PATCH`, `DELETE`といったHTTPメソッドに対応しています。

特徴として、`posts`、`comments`、`albums`、`photos`、`todos`、`users`などのエンドポイントがあり、簡単にデータを取得できます。たとえば、ブログ記事(`posts`)、ユーザー情報(`users`)、ToDoリスト(`todos`)などのデータがダミーで用意されています。

実際のAPIと同じ形式でデータを取得・送信できるため、本番環境のAPIに近い形でテストできるものです。バックエンドが準備できていない段階や、シミュレーションデータでテストしたいときに、ダミーのデータを使ってフロントエンドの実装を進めることができる便利なツールです。

※axiosの説明は割愛します

## 使用例
今回は、[jsonplaceholder](https://jsonplaceholder.typicode.com/) の Resources より [user情報](https://jsonplaceholder.typicode.com/users) を使用します。

まず、axiosをインポート。


```App.js
import "./styles.css";
import axios from "axios";

export default function App() {
  const onClickUsers = () => {
    // getリクエストでデータを取得
    // .thenでデータ取得した後に実行する関数を設定
    axios
      .get("https://jsonplaceholder.typicode.com/users")
      .then((res) => {
        console.log(res.data);
      })
      // URLが正しくないなどの場合
      .catch((err) => {
        console.log(err);
      });
  };
  const onClickUser1 = () => {
    axios
      .get("https://jsonplaceholder.typicode.com/users?id=1")
      .then((res) => {
        console.log(res.data);
      })
      .catch((err) => {
        console.log(err);
      });
  };
  return (
    <div className="App">
      <button onClick={onClickUsers}>users</button>
      <button onClick={onClickUser1}>id=1のuser</button>
    </div>
  );
}
```
**onClickUsers**
![スクリーンショット 2024-10-22 0.38.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668222/6d9622ed-a9b6-0e7c-dff9-82c702c0db08.png)

**onClickUser1**
![スクリーンショット 2024-10-22 0.38.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668222/978d3bc5-3c49-8ff0-529f-12614d2ac5d4.png)

`https://jsonplaceholder.typicode.com/users/3`
でも取得できます。
![スクリーンショット 2024-10-22 0.42.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668222/9a0497f3-3156-cdee-9c48-ccb9336380e1.png)

以上です。とてもシンプル。
go japan

【亲们看过来，[快速赴日就业] 坐标东京，招聘进行中！高技术人才+20 分优待，助您一年永驻~

株式会社サム・ビジネス · 2018 年设立

※提醒：赴日工作不是一个简单的换公司决定，它涉及到生活和未来发展，请和家人充分沟通再做决定！
※重申：我们是**对日外包开发公司**，直白一点，我们跟国内互联网大厂不是一个体系，您投简历之前，请有个清楚的认知。虽然我们不拼“大厂”待遇，但我们诚实、透明，公司的员工都享有标准的社保、年金、劳动保险等福利。同时，我司成功申请了经营革新企划，获得了高技术人才的加分优势，您在获得**高度人才+20 分**的同时，更快迈向永住。

**如果您对国内的职场内卷感到疲惫，如果您觉得自己技术不是大神级别但还想发展，我们在东京等您！**这里没有无意义的加班，没有年龄歧视。只要您愿意努力学习日语，您可以在这里找到稳定的职业发展和生活。

**以下是我们目前的招聘岗位：**

我司（株式会社サム・ビジネス）成立于 2018 年，主营对日外包开发业务，凭借稳健的业务增长，正在快速发展中。现有社员 25 名，总部位于东京。

**我们希望您：**

- 大专以上学历，计算机或相关理工科背景，且拥有两年以上的软件开发经验
- 精通 JAVA、SAP、ERP、Dynamics、Python、.NET(ASP・VB・C#)、C++、Android、Salesforce、iOS 等其中任意一种开发环境或语言
- 熟悉 HTML、CSS、JavaScript、PHP，并了解 React、Vue 等前端框架
- 有 SAP 相关工作经验者优先
- 日语 N2 及以上（如果您日语基础较弱，但有信心在一年内达到 N2 水平，也可以签署对赌协议）

**加分项：**

- 英语流利
- 三年以上开发经验

**我们能为您提供：**

- 带薪休假 + 交通费全额支给
- 每年的生日礼物、员工旅行
- 完备的健康保险、厚生年金、育儿手当、雇佣保险等
- 免费的日语培训（从零基础到 N1 线上授课，来日之前即可开始）
- 免费的 Java 和 Python 技术培训
- 免费的永住、归化、家族签证申请指导
- 结婚祝金 + 产假 + 生育祝金

**薪资待遇：**

- **底薪 + 手当（提成）** 制：22 万～120 万日元 / 月（根据日语能力和技术水平）
- 现场手当 2~10 万日元不等，取决于项目现场的单价（每月评估）
- **每三个月**，有可能的大幅度涨薪机会

**您可能面对的挑战，我们已经为您准备好解决方案：**

1. **初来日本可能感到孤独**。我们定期举办技术交流会、聚餐、游戏比赛、电影观赏会等社内活动，让您更快找到志同道合的朋友，扁平化管理，您有任何问题可以直接找社长沟通。
2. **日语是个挑战**。我们有专业的培训团队，线上授课，您只要用心学，一定能学会。
3. **签证申请**一般需要 1~3 个月，录用后您可以自由安排时间，公司无任何强制要求，日语课也一般安排在周末。
4. **初来乍到可能遇到很多生活琐事**，比如租房、开通水电、办理银行卡等。我司会有专业人员帮助您处理这些问题，让您尽快适应日本生活。

如果您对赴日工作有兴趣，欢迎投递简历至 13609669261@163.com！我现在也在项目现场工作，回复可能稍有延迟，请见谅。

我们承诺：
1. **无任何强制社内活动**，您可以自由选择是否参加，且公司不扣押任何证件
2. **工资准时发放**，四年来从未拖欠
3. **离职过程透明**，谈判明确，双方互相让步，体面离职
4. **契约类型由您选择**，根据个人情况可自由决定
5. **所有事宜在明处谈**，我们坚信公开透明的沟通是最好的合作方式

期待与您共同发展，谢谢！】
【学習記録　2024-10-16】

## 使用した教材など
Udemy：【CLF-C02版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（6回分390問）
## 学習内容
- 基礎問題演習

## 所感
　クラウド系の部署に配属が決定したためWeb開発の学習は一旦ストップで、AWSやOCIの学習に力を入れていきます！
【Flutter】freezedを使った複数型対応のJSON自動変換

# はじめに
freezedを用いたモデルクラスの自動生成の際に、APIのレスポンスのうちのあるフィールドがStringまたはintという複数の型で落ちてきて型キャストがうまくいかなったときの対処法です。

freezedの自動生成のfromJsonを使わずに自前で書けば問題ないのですが、フィールドが多かったり、ネストが深かったりする場合面倒なのでなるべく自動生成を使いたかったという背景もあります。

# 起こっていた問題
### freezedで作ったモデルクラス
```
@freezed
class Model with _$Model {
  const factory Model({
    required int id, // intかStringで落ちてくる
    required String name,
  }) = _Model;
  factory Model.fromJson(Map<String, dynamic> json) =>
      _$ModelFromJson(json);
}
```

### APIレスポンス
idの型がintかString（なぜ。。。）
```
{
  data:[
    {
      "id":1,
      "name":"hoge"
    },
    {
      "id":"2",
      "name":"fuga",
  ]
}
```

このように自動生成のfromjsonでは型キャストエラーが起きてしまいます。

# 解決方法
カスタム`JsonConverter`を作る
intにキャストするコンバーターを作ることで解決できます。
本来は自作クラスに変換したりなどに使いますが、このように複数の型に無理やり対応させるような使い方をします。

```
class IntOrStringConverter implements JsonConverter<int, dynamic> {
  const IntOrStringConverter();

  @override
  int fromJson(dynamic json) {
  　if (json is int) {
      return json;
    } else if (json is String) {
      return int.tryParse(json) ?? 0;
    } else {
      throw Exception('intでもstringでもありません');
    }
  }

  @override
  dynamic toJson(int object) => object;
}
```

これをidのフィールドに適用させる
```
@freezed
class Model with _$Model {
  const factory Model({
    @IntOrStringConverter() required int id,
    required String name,
  }) = _Model;
  factory Model.fromJson(Map<String, dynamic> json) =>
      _$ModelFromJson(json);
}
```

## 手法2(2025/1/23追記)
`@JsonKey`の`fromJson`フィールドにキャストする関数を渡す  
簡易的な処理ならこの方法の方が簡潔でいいですね
```
@freezed
class Model with _$Model {
  const factory Model({
    @JsonKey(fromJson: _toInt) required int id,
    required String name,
  }) = _Model;
  factory Model.fromJson(Map<String, dynamic> json) =>
      _$ModelFromJson(json);
}

int _toInt(dynamic value) {
  return int.tryParse(value.toString()) ??
    (throw FormatException('Invalid type for int conversion'));
}
```

# おわりに
自動生成は便利ですが、柔軟さが微妙ですね。。。
tsのunion型みたいなのがdartでも使えるといいんですが
ASP.NET CoreでGraphQL APIを構築してみました

最近よくGraphQLを耳にしていますが、GraphQL一体何なのか気になりました。なので、GraphQLをざっくり調べた感じ、下にまとめてみました。

GitHubにも[**:link: サンプルコード**](https://github.com/boababy/GraphQLDemo)をプッシュしましたので、
興味ある方、是非みてみてください:grin:


# GraphQLとは何か？

GraphQLはクエリ言語で、主にAPIの設計に使用され、クライアントが必要とするデータを正確に取得できる柔軟性を提供します。

## GraphQLの操作方法

### 1. クエリ（Query）

クエリは、**RESTful APIのGETリクエスト**に相当しますが、GraphQLでは必要なデータのみを指定して取得できる点が特徴です。

### 2. ミューテーション（Mutation）

ミューテーションは、**RESTful APIのPOST、PUT、DELETEリクエスト**に相当しますが、GraphQLでは一度のリクエストで複数の操作を実行することも可能です。

### 3. サブスクリプション（Subscription）

サブスクリプションは、リアルタイムでデータの変更をクライアントに通知するために使用します。
これにより、クライアントはサーバーからのイベントを受け取ることができます。チャットアプリケーションやリアルタイムのデータダッシュボードなどで利用されます。

## GraphQLとRESTful APIの違い

GraphQLとRESTful APIの違いは表形式でまとめてみました。

| 項目 | RESTful API | GraphQL |
| --- | --- | --- |
| **データ取得の柔軟性** | エンドポイントごとに固定されたデータ構造を提供。必要なデータ以上の情報が返されることが多く、複数のリクエストが必要になる場合がある。 | クライアントが必要とするデータを正確に指定でき、一度のリクエストで複数の関連データを取得可能。 |
| **エンドポイントの数** | 各リソースに対して複数のエンドポイントが存在する（例：`GET /books`、`POST /books`、`GET /books/{id}`、`PUT /books/{id}`、`DELETE /books/{id}`）。 | 単一のエンドポイント（通常は `/graphql`）で全ての操作を処理。 |
| **バージョニング** | エンドポイントのバージョニング（例：`/v1/books`、`/v2/books`）が一般的。 | スキーマの進化により、バージョニングが不要。新しいフィールドや型を追加することで、既存のクエリに影響を与えずに機能を拡張可能。 |
| **リアルタイム通信** | ポーリングやWebSocketを使用してリアルタイム通信を実現する必要がある。 | サブスクリプション機能により、ネイティブにリアルタイム通信をサポート。 |
| **エラーハンドリング** | HTTPステータスコードを使用してエラーを伝達。 | レスポンス内の `errors` フィールドを使用して詳細なエラー情報を提供。 |