OmniAICreator/Qiita-1.07M huggingface dataset:
プロデル、調査 その21

# 概要
プロデルが、CLRらしいので、調べて見た。
練習問題やってみた。

# 練習問題
GUIで、じゃんけんを書け。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/2b46570b-ab37-4afc-9161-07f87dbf9d85.png)


# サンプルコード

```
メイン画面を表示する
待機する
メイン画面とは
	ウィンドウを継承する
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
	終わり
	初期化する手順
		ーー自動生成された手順です。ここに書き加えたプログラムは消える可能性があります
		初期化開始する
		ボタン3というボタンを作る
		ボタン2というボタンを作る
		ボタン1というボタンを作る
		この実質大きさは{357,328}
		この内容は「じゃんけん」
		この移動順は0
		ボタン3を使う
			その位置と大きさは{133,242,93,28}
			その内容は「パー」
			その移動順は0
		ボタン2を使う
			その位置と大きさは{133,176,93,28}
			その内容は「チョキ」
			その移動順は1
		ボタン1を使う
			その位置と大きさは{133,107,93,28}
			その内容は「グー」
			その移動順は2
		初期化終了する
		この設計スケール比率は{120,120}
	終わり
	ボタン1がクリックされた時の手順
		０をじゃんけんする
	終わり
	ボタン2がクリックされた時の手順
		1をじゃんけんする
	終わり
	ボタン3がクリックされた時の手順
		2をじゃんけんする
	終わり
	[数1]をじゃんけんの手順
		数2は　0から2までの乱数
		数1が　0と　等しく　かつ　数2が　0と　等しい　なら
		　　「グーとグーで、あいこ」を　表示する
		他で数1が　0と　等しく　かつ　数2が　1と　等しい　なら
		　　「グーとチョキで、あなたの勝ち」を　表示する
		他で数1が　0と　等しく　かつ　数2が　2と　等しい　なら
		　　「グーとパーで、あなたの負け」を　表示する
		他で数1が　1と　等しく　かつ　数2が　0と　等しい　なら
		　　「チョキとグーで、あなたの負け」を　表示する
		他で数1が　1と　等しく　かつ　数2が　1と　等しい　なら
		　　「チョキとチョキで、あいこ」を　表示する
		他で数1が　1と　等しく　かつ　数2が　2と　等しい　なら
		　　「チョキとパーで、あなたの勝ち」を　表示する
		他で数1が　2と　等しく　かつ　数2が　0と　等しい　なら
		　　「パーとグーで、あなたの勝ち」を　表示する
		他で数1が　2と　等しく　かつ　数2が　1と　等しい　なら
		　　「パーとチョキで、あなたの負け」を　表示する
		他で数1が　2と　等しく　かつ　数2が　2と　等しい　なら
		　　「パーとパーで、あいこ」を　表示する
		そして
	終わり
終わり




```

以上。
ChatGPTを使用したアプリ開発記【株価画面の追加】

## 📦 インポート部分
```AppleStock.js
import React, { useEffect, useState } from 'react';
import Header from './Header';
```
•	useEffect: コンポーネントがマウントされたときに処理（API呼び出し）を行うために使います。
•	useState: 取得したデータを保存するための状態管理用のフック。
•	Header: 画面上部に表示する共通のナビゲーションヘッダー。

## 🔑 APIキーと銘柄シンボル
```AppleStock.js
const API_KEY = '◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯◯';
const SYMBOL = 'AAPL';
```
•	API_KEY: Twelve Data という株価APIサービスのキー。
•	SYMBOL: 今回は Apple のシンボル “AAPL” に固定。

## 🔄 状態管理とデータ取得
```AppleStock.js
const [data, setData] = useState([]);
```
•	data: 株価データの一覧を格納。
•	setData: data の更新関数

## 🛰️ useEffect フック
```AppleStock.js
useEffect(() => {
  const fetchStock = async () => {
    try {
      const res = await fetch(
        `https://api.twelvedata.com/time_series?symbol=${SYMBOL}&interval=1min&apikey=${API_KEY}`
      );
      const json = await res.json();
      if (json.values) {
        setData(json.values.slice(0, 10));
      }
    } catch (error) {
      console.error('データ取得エラー:', error);
    }
  };

  fetchStock();
}, []);
```
•	useEffect(..., []): 初回マウント時に一度だけ実行される。
•	fetch(...): Twelve Data API からAppleの株価（1分間隔）を取得。
•	json.values.slice(0, 10): 最新の10件だけを抽出。
•	setData(...): 抽出したデータを state に保存。

## 🖼️ レンダリング部分
```AppleStock.js
<>
  <Header />
  <div className="p-4 bg-white rounded shadow pt-24">
    <h2 className="text-xl font-bold">Apple 株価（最新）</h2>
    <ul>
      {data.map((item, index) => (
        <li key={index} className="border-b py-1">
          {item.datetime} - {item.close} USD
        </li>
      ))}
    </ul>
  </div>
</>
```
•	Header /: 上部ナビゲーションを表示。
•	div className="p-4 ...": 株価リストのUI枠（TailwindCSSでスタイル）。
•	data.map(...): data に格納された株価情報（日時・終値）をリストとして描画。

## 📷UI

![スクリーンショット 2025-05-25 7.45.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/cc040043-ed5b-4678-a329-5962d59e2735.png)
日付をまたぐタイムスタンプの差分を列のまま求める(SPSS Modeler データ加工逆引き4-29)

# 日付をまたぐタイムスタンプの差分を列のまま求める

![スクリーンショット 2025-05-29 13.37.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/dbf3e668-9ade-4932-92fd-d90d4b8460ec.png)


この処理は逆引き1-9を時系列(縦持ち)のまま行う想定しています。

https://qiita.com/spssfun2017/items/8e1291801aacf5427e7d

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

・IoTデータの特徴量作成
・Webクリックストリーム分析でのデータ加工

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

https://github.com/yoichiro0903n/blue/raw/refs/heads/main/time_lag_min.str

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

![スクリーンショット 2025-05-29 13.38.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1c31aa5c-d5ae-4591-bbcb-e8fae32c5b8b.png)

a.入力するデータは以下の通りです。

![スクリーンショット 2025-05-29 13.39.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/2957c8e5-e6ac-43a9-a293-165be28e9357.png)


b.[フィールド作成]ノードを編集します。上下のタイムスタンプを比較して分数を出します。日にちをまたいだ場合、1日あたりの分数を足しています。[@&#xFFF0;OFFSET(フィールド,1)]でフィールドの値の1行上を参照します。

![スクリーンショット 2025-05-29 13.40.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/54bbe270-9078-4cc1-b8db-878e8b016f26.png)


c.[フィールド作成]ノードを編集します。上下のタイムスタンプを比較して秒数を出します。日にちをまたいだ場合、1日あたりの秒数を足しています。[@&#xFFF0;OFFSET(フィールド,1)]でフィールドの値の1行上を参照します。

![スクリーンショット 2025-05-29 13.40.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/4ad612c0-e490-49aa-867f-81a618bcab08.png)


[テーブル]を実行します。

![スクリーンショット 2025-05-29 13.41.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b9bc7d7a-a752-4807-9091-2968c2113ce6.png)



#### 注意事項

常に一つ上のレコードとの比較を行いましたが、特定のフラグがあったレコードまでの分数を数える場合には以下を参考にしてください。

https://qiita.com/416nishimaki/items/de8210d049409e914321

## 4.参考情報

#### 二つのタイムスタンプ列の比較

https://qiita.com/spssfun2017/items/8e1291801aacf5427e7d

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
ESP32 + WiFiで門を自動化する方法【コード付きステップガイド】

雨の中で車から降りて門を開ける…。そんな経験、ありませんか？  
私もその1人でした。そこで思ったんです：「これ、自動化できるんじゃない？」

---

## なぜ自動化したのか？

最初はただの面倒くさがりでした。市販のゲートオープナーは高すぎて無理。  
それなら、**ESP32**で自作しよう！ということで始まったこのプロジェクト。  
結果、大正解。

---

![Before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4104984/89ac76e2-a7b1-4dfd-b639-fe786e150189.png)

## 準備するもの（ゆるめのリスト）

- ESP32マイコンボード  
- リレーモジュール（2chがオススメ）  
- ゲートのモーター or ソレノイド  
- WiFi接続  
- 電源アダプター（例：12V）  

---

## 基本コード：WiFi接続確認

```cpp
#include <WiFi.h>

const char* ssid = "Your_SSID";
const char* password = "Your_PASSWORD";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("接続中...");
  }
  Serial.println(WiFi.localIP());
}

void loop() {}
```

---

## リレー制御でゲート開閉

```cpp
int relayPin = 5;

void openGate() {
  digitalWrite(relayPin, HIGH);
  delay(500);
  digitalWrite(relayPin, LOW);
}
```

---

## Web経由でゲート操作

```cpp
#include <ESPAsyncWebServer.h>

AsyncWebServer server(80);

void setup() {
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    openGate();
    request->send(200, "text/plain", "ゲートを開けました！");
  });
  server.begin();
}
```

---

## 電源は要注意【**Electric**（[参考リンク](https://chicagocommercialfencing.com/wrought-iron-fence-chicago/)）】

電源ラインからESP32を直接供給すると壊れる危険あり。必ずDCコンバーターを使いましょう。

---

## 鍵制御：ロックを解除する【**Lock**（[参考リンク](https://osceolafence.net/commercial-fence-installation-for-chicago/)）】

```cpp
int lockPin = 4;

void unlockGate() {
  digitalWrite(lockPin, HIGH);
  delay(300);
  digitalWrite(lockPin, LOW);
}
```

---

## 定期的なメンテナンス【**Maintenance**（[参考リンク](https://chicagosecuritypros.com/access-control-chicago)）】

屋外機器は劣化しやすいので、2ヶ月に1回はケースの中をチェック。

---

## セキュリティ対策【**Privacy**（[参考リンク](https://chicagolandfencepros.com/aluminum-fences-chicago)）】

最初はIPを誰でも見れる状態にしてました（汗）  
今は簡単なパスワード認証を追加して安全に。

---

## おすすめポイント

- スマホ1つでゲート開閉  
- 自作ならではの達成感  
- コード × 現実世界の融合が楽しい！

---

## まとめ

この週末、あなたもチャレンジしてみませんか？  
「自分でゲートを自動化した」って、めちゃくちゃ気持ちいいですよ！

---
とりあえずClaude CodeをVSCode(devcontainer)で動かすための備忘録

## 概要  
VSCodeにClaude Codeを導入するに際して、入口で少し迷ったので忘備録として記します

## アカウント準備

1. **Claudeのアカウントを作成する**  
   https://claude.ai/

2. **Maxプランに加入する**  
    APIでも使えますが結構割高になったりするので、日常的に利用する場合はあまり推奨しないです

## devcontainerに導入する

`devcontainer.json`の`"features"`に`"ghcr.io/anthropics/devcontainer-features/claude-code:1.0"`を追加します。

```json
{
    "name": "sample",
    "build": {
        "dockerfile": "Dockerfile"
    },
    "features": {
        "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
    }
}
```

## VSCodeに拡張機能を追加する
devcontainer上でターミナルを開き、`claude`と入力してください。
セットアップ作業が始まるので、表示される内容に沿ってアカウント連携などを進めていきます。
```terminal
$ claude
```


以上
VisualStudioでインテリセンスの文字化けが起きたときのシンプルな対処法

今回は忘れない内に、インテリセンスバグの解消法についてメモをする。
恐らく初歩的すぎたのか、この解決方法で直った記事が見当たらなかったため載せておく。

まず、私のケースではこのようなバグが発生した。

![スクリーンショット 2025-06-04 031154.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945174/bae39bd6-09c4-4358-ab49-e621f4875470.png)

クイックツールヒントの文字化けが起きている。
最初、VisualStudioを再インストールしたり、テキストフォントや言語設定を変えたりしたものの直らなかった。
そこで、色々インテリセンスの設定を見てみるとこのような項目を見つけた。
ツール→オプション→環境→フォントおよび色

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945174/37101c5a-f932-466e-9d8a-34078f30481f.png)

つまり、エディタツール側のフォント設定が原因だったということである。
自分はてっきり、テキストエディタ本体のフォント設定がツール側も含めて適応されると勘違いしていた。
今後このようなバグがある場合は、どのツールに問題があるのかを区別して設定するよう覚えておかなければいけない。

余談）正直バグっててもコーディングはできるけど、こういう小さいことがとてもストレスになるので、正直直せてハッピーですね。
Power Automate の OneDrive for Business コネクタのファイル取得系アクションの最大ファイルサイズ。

https://learn.microsoft.com/ja-jp/connectors/onedriveforbusinessconnector/

## パスによるファイル コンテンツの取得
![スクリーンショット 2025-06-04 025550.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629955/797a0075-5d98-4cee-aae8-7f345fd253f2.png)
500 MB は成功したが、501 MB でエラー発生。

## ファイル コンテンツの取得
![スクリーンショット 2025-06-04 025230.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629955/4d68f9d7-4623-4647-9920-75b5b748aa46.png)
こちらも同様に 501 MB でエラー発生。

コミュニティに以下の投稿あり。やっぱり 500 MB が上限っぽい。

https://community.powerplatform.com/forums/thread/details/?threadid=04681816-833b-482a-8be6-083ec24ea152&utm_source=chatgpt.com
🗂 ChatGPTはもうGoogle Driveに接続できない？

## ― PlusユーザーのOAuth接続が突如消失 ―

---

# 🔍 概要

2024年末頃から利用できていたChatGPTの**Google Drive連携機能**が、  
**2025年6月現在、一部のユーザーで利用不可となっている現象**が確認されている。

---

# 🧾 事実の整理

## 以前（2024年〜2025年5月頃）

- ChatGPT Plusユーザーでも、Googleアカウント連携 → Drive内ファイルの一覧取得や中身の表示が可能
- OAuth 2.0を通じた**ファイル選択UI（File Picker）**も利用可  
  → PDFや画像ファイルをそのままGPTに読み込ませることができた
  実際に、ChatGPT PlusユーザーがGoogle Drive連携を利用していた記録は以下のNote記事で確認できる：
 [ChatGPTでGoogleドライブのPDFを要約してもらう実験｜隊長さん（2024年12月）](https://note.com/taicho_/n/nbcec677f7177)
この記事では、ChatGPTにGoogle Drive上のPDFを認証付きで読み込ませ、実際に要約させたログが掲載されている。

---

## 現在（2025年6月）

- **同じ操作をしても、Drive接続UIが表示されない／OAuthが失敗**
- 該当のOAuthフローで「**アカウントを選んだあとに反応がない**」という報告が複数
- 特に**「GPT-4（Ultra）」モード**で顕著に発生

---

# ✅ Teamsユーザーでは現在も接続可能？

- **2025年6月現在、ChatGPT TeamsではGoogle Drive連携が維持されている**
- 海外での検証報告では、  
  「EnterpriseやTeamsでのみDrive接続が可能」という指摘が見られた

---

# 🧩 技術的背景の推定

- GPTsのFunction Callingにおいて、OpenAI側が**GoogleのOAuth認証を段階的に制限**した？
- または**Google API側の変更**（無料ユーザー向け連携の制限／割り当て上限の導入）？
- **ユーザー個別の制限？**  
  → 自分は接続を本格化させたのはごく最近だったため、使い過ぎとは考えにくい
- **一時的なバグ？**  
  → しかし設定画面から**Driveの項目そのものが消失している**ため恒久的変更の可能性も
- **Google Drive側では連携アプリの設定が残っている**（OAuth権限の痕跡あり）

---

# 📢 情報収集中：検証コメント歓迎

現在、**アプリ・Web版ともに設定項目が消えており、Drive連携は実質不可能**な状態です。  
ただし、**どのプラン・どのリージョンでどう発生しているのかは未確認**の部分が多いです。

以下のような情報提供を歓迎します：

- ✅ 自分の**ChatGPTプラン（Free / Plus / Teams / Enterprise）**
- ✅ **GPTs利用時にDrive File Pickerが表示されたか**
- ✅ **Drive以外の連携状況**（Dropbox / OneDrive など）

---

# 🧷 補足メモ

- Google Driveとの連携はOAuth 2.0の仕組みを介して行われていた
- 現時点ではOpenAIの**設定画面からDrive関連の表示が消失**している
- 今後のアップデートや仕様変更により復旧する可能性もあるため、動向の注視が必要
最近のプラットフォームアップデート

2025年5月29日のリリースには、パフォーマンスの向上、多少の改善、バグ修正が含まれています。今回のハイライトは以下の3点です： (1) 新しいビデオチュートリアルで、マテリアル、ワークフロー、シミュレーションジョブの作成方法を紹介、(2) サイズや形状の異なるナノ粒子の作成方法を示すチュートリアル、(3) 表面上に原子の島を作成する方法を示す別のチュートリアルです。

新機能：
 紹介ビデオ： https://youtu.be/hT1VBFH7HHo
 [チュートリアル] ナノクラスターの作成
 [チュートリアル] スラブ上に島を作成

 改善点：
 プロジェクト、アカウント、マテリアルページの読み込み時間を改善

 バグ修正：
 マテリアル表示ページのスクロール修正
 複数ファイルのワークフロー入力エディタ／ビュータブの修正
 日次ユーザー数カウンターの修正

 開発者向け情報：
 [ESSE] 材料カテゴリ分けスキームの導入作業中
 [Made] 新しいSlabConfiguration実装を使用するためのパッケージ更新作業中

 無料でお試しはこちら：https://www.mat3ra.com/?utm_source=qiita&utm_medium=newsletter

 #mat3ra #機械学習 #分子動力学法 #機械学習ポテンシャル #科学技術計算 #マテリアルズインフォマティクス #第一原理計算 

 ![Post-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4022238/962a2751-2019-48dd-9d84-33ccf9f9d794.png)
フリーアドレスのどこにすわっているか、目印をつけ、目印を削除するマクロ

フロアのどこに座っているかわからないので、Excelで座席位置を確認できるようにする。

# 要件整理
背景画像として座席表がある（シート上に画像を貼り付けてある）

ユーザーが朝、自分の席に図形（オブジェクト）を配置する
　→ 任意の図形（例えば「●」などの円）を使う

日が終わったら、その図形を一括削除するボタンが欲しい

# 解決策概要
座席位置を示す図形の名前に特定の接頭辞（たとえば "座席_"）をつける
マクロではその接頭辞がついた図形だけをまとめて削除する
ボタンはマクロ実行用に配置

# 手順とコード
1. 図形を配置する際のルール
1. 図形を挿入したら、**名前を「座席_ユーザー名」**などに変更する。
（図形を選択 → 名前ボックスでリネーム）

1. マクロコード（VBA）
Excelの Alt + F11 でVBAエディタを開く
挿入 → 標準モジュール
以下を貼り付け：



```
Sub ResetSeatMarkers()
    Dim shp As Shape
    Dim deletedCount As Integer
    deletedCount = 0

    For Each shp In ActiveSheet.Shapes
        If Left(shp.Name, 3) = "座席_" Then
            shp.Delete
            deletedCount = deletedCount + 1
        End If
    Next shp

    MsgBox deletedCount & " 件の座席マーカーを削除しました。", vbInformation
End Sub

```


# ボタンの設置方法
Excelシートに戻る
「開発」タブ → 「挿入」→ 「フォームコントロールのボタン」
任意の場所にドラッグ
表示されるダイアログで ResetSeatMarkers を選択

---


# マクロの仕様
1. Excelの座席表シートに、座席マーカー（丸い図形）を自動で追加します。
1. 座る席の位置（セル）を選択し、その位置に円形の図形（●）を配置。
1. 図形には自動で**名前「座席_ユーザー名」**をつける。
1. 図形の色は自由に変更可能（標準で青に設定）。

ユーザー名はマクロ実行時に入力ボックスから入力します。



```
Sub AddSeatMarker()
    Dim userName As String
    Dim marker As Shape
    Dim targetCell As Range
    Dim leftPos As Double, topPos As Double
    Dim width As Double, height As Double

    ' ユーザー名を入力
    userName = InputBox("あなたの名前を入力してください（例：Yamada）", "ユーザー名入力")
    If userName = "" Then Exit Sub

    ' セルが選択されているかチェック
    If TypeName(Selection) <> "Range" Then
        MsgBox "まず、座っている席に該当するセルを選択してください。", vbExclamation
        Exit Sub
    End If

    Set targetCell = Selection.Cells(1)

    ' 図形の大きさと位置（セルの中央に配置）
    leftPos = targetCell.Left + (targetCell.Width / 4)
    topPos = targetCell.Top + (targetCell.Height / 4)
    width = targetCell.Width / 2
    height = targetCell.Height / 2

    ' 円形の図形を作成
    Set marker = ActiveSheet.Shapes.AddShape(msoShapeOval, leftPos, topPos, width, height)

    ' 図形の書式
    With marker
        .Name = "座席_" & userName
        .Fill.ForeColor.RGB = RGB(0, 112, 192) ' 青色
        .Line.Visible = msoFalse
        .LockAspectRatio = msoTrue
    End With
End Sub
```


# 使い方手順（ユーザー向け）
1. 自分が座っている席のセルを選択
1. ボタンから「AddSeatMarker」マクロを実行
1. 名前を入力すると、そのセルにマーカーが付きます
1. 終業時は、前述の「ResetSeatMarkers」マクロで一括削除



座席表は画像で張り付けるので、セルを選択できない。
その場合は、Ｃtrl ＋ 6 によって、シート上のすべてのオブジェクトを非表示にする。
セルを選択する。
再度　Ｃtrl ＋６　をクリックすることによって再表示する。
Windows のコマンドプロンプトでダミーファイル生成する方法。

たまに検証でいろいろなファイルサイズのダミーファイルを作りたくなるので、その方法をメモ。

```powershell
fsutil file createnew test_10MB.zip 10485760
```

- test_10MB.zip：生成されるファイル名（実際は中身のないファイル）
- 10485760：ファイルサイズ（バイト単位。10MBの場合）

| サイズ表記 | バイト数（Byte）    |
| ----- | ------------- |
| 1MB  | 1048576    |
| 50MB  | 52428800    |
| 100MB | 104857600   |
| 500MB | 524288000   |
| 1GB   | 1073741824 |
| 1.5GB   | 1610612736 |
| 2GB   | 2147483648 |

https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/fsutil?utm_source=chatgpt.com
【IaC超入門】AWS CloudFormationでS3をテンプレートから自動作成してみた！！



# 1. はじめに

- AWS学習の一環でCloudFormationを触ってみた

- 今回は「S3バケット」をコードで自動作成してみる

# 2.CloudFormationとは？
**CloudFormationとは、AWSのリソース（例：S3、EC2、VPCなど）をコードで自動作成・管理できるサービスです。**

言っちゃえば「テンプレート1枚」あれば、誰でも環境構築が簡単に出来る！

# 3. 作ったもの

- S3バケット（バージョニング有効）

- 東京リージョンに作成

- CloudFormationのテンプレートは**YAML形式**

# 4.準備するもの

| 項目             | 内容                      |
| -------------- | ----------------------- |
| AWSアカウント       | すでにある前提（なければ作成）         |
| AWSマネジメントコンソール | ブラウザ上で操作可能              |
| 作成リソース例        | **S3バケット**（無料枠あり、コストゼロ） |

# 5.簡単な流れ

## ① CloudFormationテンプレートを準備
まずはS3バケットを作成するYAML形式のテンプレートをChatGPTに出力させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/da9869f0-2191-4036-84d8-6b52d5f8eb84.png)

Iacは学習コストが高いとか色々聞いたことがあるんだけど、
今の時代、生成AIに頼めば一瞬でコードを出力してくれるもんなので
この時点では、昔に比べて学習コストは確実に下がっているように感じました。問題は**業務で使いこなせるか**だと思いますが、、
### ※test-s3.yamlのテンプレート（例）
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: S3バケットを作成するCloudFormationテンプレート

Resources:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: my-s3-bucket-20250603  # ※一意な名前に変更してください
      VersioningConfiguration:
        Status: Enabled

```

ChatGPTに出力させたYAML形式のテンプレートをコピペして保存します。
(**※.yml or yamlの拡張子で保存しましょう。**)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/c1edb55c-605e-4e19-96c4-d429ce2b5c5a.png)


## ② AWSマネジメントコンソールにログイン
https://console.aws.amazon.com/cloudformation/ にアクセス

今回はルートユーザで実践していきます。

## ③ ClouｄFormationを試してみよう！！

ホームメニューからCloudFormationタブを押下し
画面が遷移したら「スタックを作成」を押下。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/ba70cf98-c383-4c85-abc2-7d743fc64428.png)

デフォルトだと「Amazon S3 URL」が選択されているので
「テンプレートファイルをアップロード」を押下する。
押下すると、テンプレートファイルのアップロードボタンが出てくるので
最初に作ったテンプレートをアップロードする。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/862a589c-74b9-4e4b-ba39-e18af137a388.png)


## ④ スタック名を入力（例：demo-cfn-stack）して「次へ」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/798947bf-bc7f-493e-8b7a-963ba7259851.png)


パラメータは特に不要なのでそのまま進んでOKみたいです。

オプション設定は何もいじらず「次へ」を押して
最終画面で「送信」を押下する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/f473922f-225f-4027-9b64-690cc6f6c0e6.png)


## ⑤ 完了したらS3バケットが作成されているか確認
CloudFormationの「スタック」からステータスが「CREATE_COMPLETE」になっていれば成功

**未完了状態**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/c3ae80b3-a929-402d-a535-85f36e011451.png)

**完了状態**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/cfdf0f57-5121-4cee-abb6-2fdfd3c7ae8d.png)
CREATE_COMPLETEを確認。

## 最後に削除を忘れずに
基本的にS3は無料枠（5GB）以内なら課金されません。ただし、バケットをたくさん作ると管理が大変になるので、**検証後は忘れずに削除**するのがベストです！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4097535/eef8deec-914d-4eea-b561-0c7c2f042cde.png)

# 6.感想
所要時間は15分程でした。
こんなに簡単にS3バケットが作成できるのは非常に便利だと思いました。
今回はS3バケットの作成のみの実施ですが、これ一発でネットワーク環境を構築できると考えるとやっぱり楽ですよね。
しかし、肝心なYAML形式ですが全く何をしているか、コードを読めるかに置いては全く理解できていません。笑
### IaCは「書けるかどうか」ではなく「理解して運用できるかどうか」にありそうですね。
ウェブアクセシビリティとは？

:::note warn
この記事は生成AIによって書かれています
:::

# ウェブアクセシビリティとは何か？

ウェブアクセシビリティとは、**すべてのユーザーがウェブコンテンツにアクセスし、利用できるようにすること**を意味します。これには、視覚、聴覚、運動、認知などに障害を持つユーザーも含まれます。

アクセシビリティの高いウェブサイトは、単に倫理的な配慮だけでなく、より多くのユーザーにリーチし、SEOにも好影響を与えるため、**ビジネス上の利点**もあります。

---

## なぜアクセシビリティが重要なのか？

- 世界には**10億人以上の障害を持つ人々**がいるとされており、その多くがウェブにアクセスする際に困難を抱えています。
- アクセシビリティの高いサイトは、スクリーンリーダーや音声入力、キーボード操作などの**支援技術**と連携しやすくなります。
- 法律や規制（例：WCAG、ADA、障害者差別解消法）への**準拠**も重要です。

---

## アクセシビリティの4原則（POUR）

1. **知覚可能 (Perceivable)**  
   - 情報はユーザーに認識されなければならない  
   - 例：画像に`alt`属性、映像に字幕、構造化された見出し

2. **操作可能 (Operable)**  
   - UIやナビゲーションがあらゆる手段で操作可能であること  
   - 例：マウスなしでも操作できる、タイムアウトへの配慮

3. **理解可能 (Understandable)**  
   - コンテンツや操作が分かりやすく予測可能であること  
   - 例：明確なラベル、フォームエラーの説明

4. **堅牢 (Robust)**  
   - コンテンツが将来の支援技術やブラウザでも対応できること  
   - 例：正確なHTML、ARIAの適切な使用

---

## よくある改善ポイント

- 画像には`alt`属性を付ける  
- セマンティックなHTML要素（`<nav>`, `<main>`, `<section>`など）を活用  
- 見出しタグ（`<h1>`〜`<h6>`）で文書構造を明確に  
- 十分な色のコントラスト（推奨: 最低4.5:1）  
- フォーム要素には必ず`<label>`を関連付け  
- リンクやボタンは役割が明確にわかる文言にする  
- JavaScriptによる動的変更には通知やフォーカス制御を加える  

---

## ARIA（Accessible Rich Internet Applications）とは？

ARIAは、通常のHTMLでは意味を伝えにくい動的なUI要素に**役割や状態を追加するための属性群**です。

- `role`：要素の役割を伝える（例：`role="dialog"`）  
- `aria-label`：ラベルを追加  
- `aria-hidden`：スクリーンリーダーから非表示にする  
- `aria-expanded`：折りたたみ要素などの展開状態を示す  

**注意：まずはHTMLのセマンティック要素を使い、ARIAは補助的に使用しましょう。**

---

## スクリーンリーダーとは？

スクリーンリーダーは、画面の内容を音声や点字で出力する支援技術です。以下は有名なスクリーンリーダーの例です：

- NVDA（Windows、無料）  
- JAWS（Windows、有料）  
- VoiceOver（macOS/iOS）  
- TalkBack（Android）

### テストのポイント

- フォーカスが適切に移動するか  
- 読み上げられる順序が視覚と一致しているか  
- 各UIコンポーネントの役割やラベルが伝わっているか  

---

## フォームのアクセシビリティ

- 各`<input>`には明確な`<label>`を設ける  
- エラー時には明確なメッセージを表示し、視覚・非視覚の両方で通知  
- 入力例を`placeholder`ではなく、説明文やARIAで伝える  
- `<fieldset>`や`<legend>`でグループ化するとより分かりやすくなる  

```html
<fieldset>
  <legend>お支払い方法</legend>
  <label><input type="radio" name="pay" value="credit"> クレジットカード</label>
  <label><input type="radio" name="pay" value="paypal"> PayPal</label>
</fieldset>
```

## キーボード操作への配慮
- すべての操作がTabキーとEnter/Spaceキーで完結できること
- フォーカスインジケーター（アウトライン）を消さない
- tabindex, aria-keyshortcutsなどでナビゲーションを補助

```css
:focus {
  outline: 2px solid #007ACC;
}
```
## 動的コンテンツとアクセシビリティ
JavaScriptで動的に変更される内容は、視覚的には変化してもスクリーンリーダーに伝わらない場合があります。

### 対策：
- aria-live属性でスクリーンリーダーに通知
```html
<div aria-live="polite">更新された内容</div>
```
- モーダルやドロワーは、role="dialog"、aria-modal="true"を使用し、フォーカスを閉じ込める
- DOMの変更時にfocus()メソッドで適切な場所にフォーカスを移動する

## アクセシビリティチェックに使えるツール
- WAVE
- Lighthouse（Chrome DevTools）
- axe DevTools
- スクリーンリーダー（NVDA, VoiceOver など）
【SwiftUI入門】TextFieldの使い方を簡単に説明してみました


SwiftUIでは、ユーザーから文字入力を受け取るためにTextFieldを使います。

TextFieldの基本的な使い方
--

```swift
struct ContentView: View {
    @State var name: String = ""  //@Stateでユーザーの入力値を保持。

    var body: some View {
        VStack {
        //TextField("プレースホルダー", text: $バインディング変数)で入力フォームを作成。
            TextField("名前を入力してください", text: $name)
                .textFieldStyle(RoundedBorderTextFieldStyle())  //.textFieldStyle()で見た目を整える
                .padding()

            Text("こんにちは、\(name)さん！")
        }
    }
}
```
よく使う修飾子
---
| 修飾子                            | 説明                                                                       |
| ------------------------------ | ------------------------------------------------------------------------ |
| `.textFieldStyle()`            | 見た目のスタイルを設定（例：`PlainTextFieldStyle()`、`RoundedBorderTextFieldStyle()`など） |
| `.keyboardType()`              | キーボードの種類を設定（例：数字入力、メール入力など）                                              |


まとめ
--
- TextFieldはSwiftUIでの基本的なユーザー入力手段。
- @Stateとバインディングしてリアルタイムに値を取得できる。

以上、TextFieldを簡単にまとめてみました！ぜひ初心者の方は、参考にしてみてください！👏
GoogleがProtobufとgRPCのRust公式サポート発表 - 広がる賛否両論

RustエコシステムでProtobufとgRPCを使用する開発者にとって重要な転機が訪れています。GoogleがRustでのProtobufとgRPCの公式サポートを発表したものの、その実装方針がコミュニティに波紋を広げています。

## 何が起こっているのか

GoogleによるRust向けProtobuf公式サポートが進行しています。最も象徴的な変化は、これまでstepancheg氏が個人で開発していた`protobuf`クレートの所有権がGoogleに移譲されたことです。crates.ioを確認すると、バージョン3.x系までは従来の開発者によるものですが、4.x系のプレリリース版からはGoogleが直接メンテナンスを担当していることがわかります。

この公式サポートには大きな方針転換が伴っています。新しいバージョン4.x系では、純粋なRust実装から、CまたはC++のバインディングベースの実装に変更されているのです。Google公式の説明によれば、「高品質なRust APIを提供し、純粋なC実装（upb）またはProtobuf C++実装によってバックアップされる」アプローチを採用するとしています。

この変更について、Rustコミュニティでは賛否両論の声が上がっています。

## 開発者が抱く懸念

RustとC/C++コードを組み合わせることの難しさを経験した開発者からは、具体的な問題点が指摘されています。まず、ビルド環境の複雑化が避けられません。純粋なRustの依存関係であれば`cargo build`一つで済むところが、C/C++コンパイラの適切なバージョンや外部依存関係のインストールが必要になります。特に継続的インテグレーション環境では、これらの依存関係がビルド失敗の原因になりがちです。

WebAssembly環境での制約も重要な問題です。WASM32ターゲットではC FFIが利用できないため、WebAssembly向けのアプリケーションでは新しいGoogle公式実装を使用できません。また、クロスコンパイルが困難になる傾向があり、Rustの「一度書けばどこでも動く」という利点が損なわれる可能性があります。

過去の他言語での事例から、Googleへの不信感もあります。特にPythonでの`grpcio`について、長年にわたるデッドロック問題や、システムの証明書ストアやDNSリゾルバをバイパスする動作、特定のTLS暗号スイートの強制など、多くの問題が報告されています。事前コンパイルステップがあるにも関わらず実行時リフレクションに依存する重い実装や、頻繁な破壊的変更も、開発者の懸念材料となっています。

## 内部からの視点

この議論にTonicライブラリのメンテナであるlucio-rs氏が参加し、内部の状況について説明しています。同氏によると、Googleは既存のRustエコシステムを破綻させることなく実装を進めたいと考えており、1年以上にわたって協力関係を築いているとのことです。

計画では、既存の`prost + tonic`利用者を放棄することはなく、新しい`grpc-rust/tonic`でも`prost`を第一級の統合として継続サポートする予定です。ただし、`prost`を使用する場合は完全な機能セットを利用できない可能性もあります。また、TonicはCNCFにアップストリームされ、gRPCのGitHub組織に移管される予定とのことです。

これらの説明は、Googleが単純にコミュニティを無視しているわけではないことを示していますが、同時に大きな変化も避けられないことが明らかです。

## 現実的な選択肢

現在、Rust開発者には複数の選択肢があります。従来からの`prost`ライブラリはシンプルで効果的なソリューションとして多くの開発者に支持されています。`tonic`と組み合わせることで、純粋なRustでのgRPC開発が可能です。

一方、新しいGoogle公式の`protobuf`クレートは、Googleの内部ニーズ、特に複数言語混在バイナリでのゼロコスト変換やコードサイズの最小化に最適化されています。大企業で既にC++のProtobufを使用している環境では、バインディングベースのアプローチにメリットがあるかもしれません。しかし、Rustファーストのオープンソースプロジェクトにとっては、設計に賛同できない状況です。

多くの開発者は、当面`prost`の継続使用を表明しています。WebAssembly環境での使用を考慮している場合や、ビルドプロセスの複雑化を避けたい場合、純粋なRust実装の利点を重視する場合には、`prost`が現実的な選択肢となります。

## Rustエコシステムへの影響

今回の一件はRustエコシステム全体にとって重要な意味を持っています。Googleのような大企業が公式サポートを提供することは、一般的には歓迎すべき出来事です。しかし、その実装方針がコミュニティの期待や価値観と必ずしも一致しないという現実も浮き彫りになりました。

Rustコミュニティが大切にしてきた「安全性」「簡潔性」「相互運用性」という価値観と、企業の実用的なニーズとの間にはギャップがあります。このギャップをどのように埋めていくかが、今後のRustエコシステムの発展にとって重要な課題となります。

また、オープンソースプロジェクトにおける意思決定プロセスの難しさも露呈しています。個人開発者から大企業への移管は、リソースの面では有利ですが、開発方針や優先順位の変更を伴う可能性があります。

## これからの展望

今後数ヶ月間で、より詳細な情報や移行計画が公開される予定です。

もし既存のプロジェクトを運用している場合は、以下の点を考慮することをお勧めします。まず、現在使用しているライブラリの継続サポート期間を確認し、必要に応じて移行計画を策定することです。WebAssembly環境やクロスコンパイルが必要な場合は、技術的制約への注目が必要です。

GoogleのRust公式サポートは確実に進歩していますが、その道のりは必ずしも平坦ではなさそうです。コミュニティと企業の協力により、最終的にはRustエコシステム全体の発展につながることが理想ですが、そのようになるでしょうか。

## 参考リンク

- [Google Protobuf Rust API Documentation](https://protobuf.dev/reference/rust/)
- [Protobuf crate on lib.rs](https://lib.rs/crates/protobuf)
- [Stepancheg's rust-protobuf repository](https://github.com/stepancheg/rust-protobuf)
- [Google Cloud Rust SDK](https://github.com/googleapis/google-cloud-rust)
- [Prost - Alternative Rust Protobuf implementation](https://github.com/tokio-rs/prost)
Supabaseで"トランザクションっぽい"処理を行う

# はじめに
Supabaseは手軽に使えるBaaSですが、トランザクション制御をクライアント側から直接扱う機能は公式には提供されていません。
そのため、複数テーブルにまたがる一連の操作を安全に行いたい場合、トランザクションのような処理を自前で工夫して実装する必要があります。
公式の方法ではないのでおそらく推奨でもないでしょうが、知っておくのは何かと良いのではないかと思い記事にしました。

# なぜトランザクションが必要？

## 問題の例
たとえば、以下の2つのテーブル構成があります。
`users` はユーザの基本情報(ユーザ名, 自己紹介, GitHubID)を保存するテーブル。
`user_skill` は各ユーザに紐づくスキルを登録するテーブル。1ユーザに複数スキルを持たせることができ、` user_id `で `users` テーブルと関連づけられている。

### `users` テーブル
| カラム名 | 型 | 制約・説明 |
|:-:|:-:|:-:|
| user_id | uuid | 主キー ユーザID |
| name | text | NOT NULL ユーザ名  |
| description | text | 自己紹介 |
| github_id | text | GitHub ID |

### `user_skill` テーブル
| カラム名 | 型 | 制約・説明 |
|:-:|:-:|:-:|
| id | number | 主キー |
| user_id | uuid | 外部キー(user.user_id) |
| skill | text  | NOT NULL スキル名  |

たとえば、ユーザー登録時に：
* users テーブルにユーザー基本情報をINSERT
* user_skill テーブルにスキル情報を複数INSERT
このとき、片方だけ成功してもう片方が失敗すると「データの整合性が壊れる」状態になります。
これを避けるために必要なのが 「すべて成功か、すべて失敗か」 を保証する トランザクション です。

## Supabaseではどうするか（→rpcを使ってストアドプロシージャを呼び出す）
Supabaseでは、クライアントからトランザクションを制御するAPIはありません。
そのため、Supabase側でPostgreSQLの関数（＝ストアドプロシージャ）を定義し、クライアントから `rpc()` を使って呼び出すことで、無理やりトランザクションライクな操作が実現できます。


# 方法

## ストアドプロシージャ定義(Supabase側)

1. 該当のプロジェクト > SQL Editorにて、ストアドプロシージャを作成(作成例は以下)
2. 右下の「Run」を実行
3. 左メニュー > Database > Functionにて、作成できているか確認できます

## PostgreSQL関数の定義
```sql
create or replace function insert_user_and_userskill(
  _name text,
  _description text,
  _github_id text,
  _skills text[]
)
returns void
language plpgsql
as $$
declare
  new_user_id uuid;
begin
　-- ユーザー情報を users テーブルに挿入し、生成された user_id を取得
  insert into users (name, description, github_id)
  values (_name, _description, _github_id)
  returning user_id into new_user_id;

　-- スキル配列を展開して、user_skill テーブルに一括挿入
  insert into user_skill (user_id, skill)
  select new_user_id, skill from unnest(_skills) as skill;

  -- 正常終了：何も返さない
  return;
exception
　-- 途中で何らかのエラーが発生した場合、エラーメッセージ付きで例外を投げる
  when others then
    raise exception '登録処理でエラー発生: %', SQLERRM;
end;
$$;
```
PostgreSQLの関数は1関数＝1トランザクション単位で処理されるため、明示的なbeginやcommitは不要。
`unnest` は配列を行に展開するSQL関数

## クライアント側の呼び出し例(TypeScript）
```ts
const { error } = await supabase.rpc('insert_user_and_userskill', {
  _name: '田中一郎',
  _description: 'フロントエンドエンジニア',
  _github_id: 'tanaka123',
  _skills: ['React', 'TypeScript'],
});

if (error) {
   // → PostgreSQLのraiseで指定したエラーメッセージがここに出る
  console.error('登録エラー:', error.message);
} else {
  // → 正常終了時は error が null で、data も null
  console.log('登録成功！');
}
```
Supabaseクライアントの設定(Url, AnonKey)は省略

# 最後に
Supabaseでは、現時点では公式にトランザクションAPIがあるわけではありません。
しかしPostgreSQLのストアドプロシージャ（関数）を活用し、rpc() 経由で実行することで、Supabaseでもトランザクションっぽいことができました。

# その他懸念点

* テストやモックでの扱いがやや面倒…？
* `raise`による例外は文字列しか返せないらしい。エラーハンドリングの際は、クライアントでの細かい設計が必要
* rpc関数はRLSをバイパスすることがあるらしい。認可周りに要注意
* `drizzle ORM` を使った方法もあるようです。全く知らないので、引き続き調査

# 参考
https://github.com/orgs/supabase/discussions/4562#discussioncomment-1844073
https://zenn.dev/smallstall/articles/596d3981984587
SwiftUIのLazyVGrid・LazyHGridの使い方【グリッドレイアウトの基礎】

SwiftUIでは、複数のアイテムをグリッド状に表示したいときに、LazyVGridとLazyHGridがとても便利です。

LazyVGrid・LazyHGridとは？
---
LazyVGrid：縦方向にスクロールする、縦長のグリッド
LazyHGrid：横方向にスクロールする、横長のグリッド
Lazy：必要になったときにViewを生成することでパフォーマンスが高い


```swift
struct ContentView: View {
    let items = Array(1...20)
       let columns = [
           GridItem(.flexible()),
           GridItem(.flexible())
       ]

       var body: some View {
           ScrollView {
               LazyVGrid(columns: columns, spacing: 16) {
                   ForEach(items, id: \.self) { item in
                       Text("Item \(item)")
                           .frame(height: 100)
                           .frame(maxWidth: .infinity)
                           .background(Color.blue)
                           .foregroundColor(.white)
                           .cornerRadius(10)
                   }
               }
               .padding()
           }
       }
}


#Preview {
    ContentView()
}
```

- columnsに並べ方を指定し、ScrollViewで縦スクロールを実現。

GridItemの種類
```swift 
GridItem(.flexible())      // スペースに合わせて伸縮（よく使う）
GridItem(.fixed(100))      // 固定サイズ
GridItem(.adaptive(minimum: 80)) // 最小幅を指定して自動で列数を調整
```

LazyHGridの使い方
---
LazyHGridはLazyVGridの横バージョンです。

```swift
import SwiftUI

struct LazyHGridExample: View {
    let items = Array(1...20)
    let rows = [
        GridItem(.fixed(100)),
        GridItem(.fixed(100))
    ]

    var body: some View {
        ScrollView(.horizontal) {
            LazyHGrid(rows: rows, spacing: 16) {
                ForEach(items, id: \.self) { item in
                    Text("Item \(item)")
                        .frame(width: 100)
                        .frame(maxHeight: .infinity)
                        .background(Color.green)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                }
            }
            .padding()
        }
    }
}

```
- ScrollView(.horizontal)で横スクロール、rowsで縦方向の行数を指定します。


まとめ
---
| コンポーネント                                    | 特徴              |
| ------------------------------------------ | --------------- |
| `LazyVGrid`                                | 縦方向にスクロールするグリッド |
| `LazyHGrid`                                | 横方向にスクロールするグリッド |
| `GridItem`                                 | 列や行のレイアウトを指定できる |
| `.flexible()` / `.fixed()` / `.adaptive()` | レイアウト調整に使える     |

SwiftUIのLazyVGrid・LazyHGridは、簡単なコードで柔軟なレイアウトが作れる便利な機能です。ぜひ使ってみてください！🙌
Amazon Q CLI  でゲーム作成してみた


https://aws.amazon.com/jp/blogs/news/build-games-with-amazon-q-cli-and-score-a-t-shirt/

こちらの記事を共有してもらったのでみてたところ、

>Amazon Q CLI とのチャットセッションを開始し、チャット内のプロンプトだけでゲームを作成しましょう

なんて言うものだから、気になってやってみた！


# 準備
## 1.AWS Builder ID に登録し、このリンクから独自の community.aws ユーザー名を取得


[ここ](https://community.aws/builderid?trk=b085178b-f0cb-447b-b32d-bd0641720467&sc_channel=el) からユーザー登録を行います。

## 2.Amazon Q CLIのインストール
[こちら](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-installing.html) を参考にインストールします。

# ゲームの作成
#### 1.ターミナルからAmazon Q を起動する
``` $ q ```コマンドでAmazon Qを起動
![スクリーンショット 2025-06-03 23.24.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547731/9cb34ad3-7417-48a8-a586-ccdcab8480f7.png)

#### 2.プロンプトを打ち込む
とりあえずテストということで、以下を入力してみた
```> インベーダーゲームを創って```

![スクリーンショット 2025-06-03 23.28.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547731/885e5a0f-c949-47d2-83e8-a76890e37e2d.png)

するとつらつらファイルを作成し始めて......

![スクリーンショット 2025-06-03 23.30.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547731/a1c13e80-e2c0-44c4-b9f6-38cb5efa78f1.png)

3分くらいしたら完成した！！！
しかも、遊び方や特徴も出力してくれてる！

![スクリーンショット 2025-06-03 23.30.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547731/def90853-3ae1-4957-b703-a01d4f66216c.png)

# プレイしてみた
作成された```invader-game.html```を開いてみるとゲームスタートになり、「遊び方」に記載されていた通りにプレイ可能だ。なんてこったい。

![スクリーンショット 2025-06-03 23.34.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547731/f8e2df59-0f04-4134-8779-dad88007c8b7.png)

ちゃんとスコアでて、ゲームオーバーにもなる
![スクリーンショット 2025-06-03 23.35.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547731/c34541b9-fc95-4837-9e6c-29f55ef707e4.png)

# 感想
Github Copilotは使ったことあったんだけども、そのイメージで使ってみたらぶったまげたわい。
「インベーダーゲームを創って」だけでこのクオリティができてくるなんて......
個人的に一番感動したのが、出力されたJSファイルに日本語でコメントが書いてあったことでした。もうすんごい！
おれっちの仕事がなくなる未来はすぐそこなのかもしれない^_^
🎣 useEffect, useRef, useCallbackを組み合わせて実装するパターン例

# はじめに

ReactのHooksである `useEffect`、`useRef`、`useCallback` はそれぞれ便利ですが、組み合わせることでより実用的なユースケースが生まれます。

本記事では、「ボタンを押すと一定間隔でカウントが進み、停止もできる」簡単な例を使って、3つのHookを組み合わせて解説します。

# 各Hookの役割

* **useRef**：DOM要素やミューテーション可能な値の保持に使います。再レンダリングを発生させません。
* **useEffect**：副作用の処理に使います。マウント、アンマウント、依存値の変化に応じて発火します。
* **useCallback**：関数をメモ化して、不要な再生成を防ぎます。子コンポーネントへの渡しや、useEffectの依存に便利。

# スタート・ストップ機能付きカウンター

```tsx:Timer.tsx
import { useState, useRef, useEffect, useCallback } from "react";

export default function Timer() {
  const [count, setCount] = useState(0);
  const [isRunning, setIsRunning] = useState(false);
  const intervalRef = useRef<NodeJS.Timeout | null>(null);

  // カウントアップ関数（useCallbackでメモ化）
  const tick = useCallback(() => {
    setCount(prev => prev + 1);
  }, []);

  // スタート関数
  const start = useCallback(() => {
    if (!intervalRef.current) {
      intervalRef.current = setInterval(tick, 1000);
      setIsRunning(true);
    }
  }, [tick]);

  // ストップ関数
  const stop = useCallback(() => {
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
      setIsRunning(false);
    }
  }, []);

  // アンマウント時にクリーンアップ
  useEffect(() => {
    return () => {
      stop();
    };
  }, [stop]);

  return (
    <div className="p-4 text-center">
      <h2 className="text-xl mb-2">⏱️ Count: {count}</h2>
      <button onClick={start} disabled={isRunning} className="px-4 py-2 bg-blue-500 text-white rounded mr-2">
        Start
      </button>
      <button onClick={stop} disabled={!isRunning} className="px-4 py-2 bg-gray-500 text-white rounded">
        Stop
      </button>
    </div>
  );
}
```

**🔍 ポイント解説**

✅ `useRef`の活用

* `intervalRef`はsetIntervalのIDを保持し、再レンダリングを防ぎつつ、start/stop間で情報を共有しています。

✅ `useCallback`で関数をメモ化

* `tick`, `start`, `stop` すべて `useCallback` でメモ化。`useEffect`の依存や、再レンダリングで不要に関数が再生成されるのを防ぎます。

✅ `useEffect`でクリーンアップ処理

* コンポーネントのアンマウント時に `stop()` を呼び出してメモリリークを防いでいます。

# おわりに

`useRef`, `useEffect`, `useCallback` をうまく組み合わせることで、より堅牢でパフォーマンスの良いReactコンポーネントを作ることができます。
Ansibleを使用してUbuntuを最新のLTSにアップデートするには

# 要点
## `do-release-upgrade`を叩くとAnsibleが動作しなくなり進まなくなる
### 原因
Pythonインタプリタを指定していない場合、Ansibleが気を利かせて利用できるPythonインタプリタを直接バージョンで指定してくれます。
しかし、`do-release-upgrade`を実行するとPythonインタプリタも置き換えられ、場合によっては実行中に利用していたインタプリタが利用できなくなりTaskが中断してしまいます。
再度プレイブックを実行すれば新しいバージョンのインタプリタを検出して実行できますが、せっかくAnsibleで作業しているのに叩き直すのは無駄なことこの上ありません。

### 対策
`vars`に`ansible_python_interpriter`を設定し、`/usr/bin/python3`を指定することでアップグレードされても影響を受けずに実行を継続することが出来ます。
タスク単位で設定してもいいですし、面倒なら対象ホスト一覧で直接定義しても良いでしょう。

## `do-release-upgrade`を無人実行するには
下記の通りのタスクを実行してください。
```yaml
    - name: Update-manager-coreをインストール(do-release-upgradeに必要なため)
      ansible.builtin.apt:
        name: update-manager-core
        state: present

    - name: 新しいLTSリリースがないかを確認
      ansible.builtin.command: do-release-upgrade -c --allow-third-party
      register: release_check
      changed_when: false
      ignore_errors: true
      
    - name: 新しいLTSリリースがある場合、アップグレードを実施
      ansible.builtin.command: do-release-upgrade -f DistUpgradeViewNonInteractive
      register: upgrade_result
      async: 1800
      poll: 30
      changed_when: true
      ignore_errors: true
      when: "'There is no development version of an LTS available.' not in release_check.stdout" # 新しいリリースが見つかった場合のみ実行

    - name: 新しいLTSリリースがある場合、再起動を実施
      ansible.builtin.reboot:
        reboot_timeout: 600 # 再起動後、最大600秒待機
      when: "'There is no development version of an LTS available.' not in release_check.stdout" # 新しいリリースが見つかった場合のみ実行
```
`do-release-upgrade -f DistUpgradeViewNonInteractive`は、アップデート中に発生するインタラクティブ操作を全てカットします。
まあまあ時間がかかるので、async/pollにしています。
Intel N150の4vCPU/4GB環境でだいたい15分くらいかかりました。
Typewriter風チャットUI

## 概要
一文字ずつ文字が表示されるチャットUI（Typewriter風のUI）をReactで作ってみました。

## 実際の動き
![Typewriter風のUI.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2818962/91a077fd-1f9b-4761-bbea-813852541ac6.gif)

## 実際のコード
```tsx
import React, { useEffect, useState } from 'react';

const TypewriterMessage = ({ text, onDone }: { text: string; onDone: () => void }) => {
  const [displayed, setDisplayed] = useState('');
  useEffect(() => {
    // テキストが空の場合は、onDoneを呼び出して終了
    if (text.length === 0) {
      onDone();
      return;
    }

    let i = 0;
    // setInterval関数を使って100ミリ秒ごとに1文字ずつ表示
    const timer = setInterval(() => {
      // textの長さ以上になった場合は終了する
      if (i >= text.length) {
        clearInterval(timer);
        onDone();
        return;
      }

      // 更新用関数setDisplayedで1文字ずつ追加していく
      const nextChar = text[i];
      setDisplayed((prev) => {
        const next = prev + nextChar;
        return next;
      });

      i++;

    }, 100); // 文字が出る間隔
    return () => clearInterval(timer);
  }, [text]);

  return <p>{displayed}</p>;
};

export default function ChatUI() {
  const [messages, setMessages] = useState<string[]>([]);
  const [input, setInput] = useState('');
  const [isTyping, setIsTyping] = useState(false);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // trim()：文字列の両端から空白を除いた文字列を生成
    // 入力が空の場合もしくはタイプライター風アニメーション表示中は、何もしない
    if (!input.trim() || isTyping) return;
    setIsTyping(true);
    setMessages((prev) => [...prev, input]);
    setInput('');
  };

  return (
    <div>
      <div>
        {messages.map((msg, idx) => (
          <TypewriterMessage key={idx} text={msg} onDone={() => setIsTyping(false)} />
        ))}
      </div>
      <form onSubmit={handleSubmit}>
        <input value={input} onChange={(e) => setInput(e.target.value)} disabled={isTyping} />
        <button type="submit" disabled={isTyping}>送信</button>
      </form>
    </div>
  );
}

```
## はまったこと
set関数に1文字ずつ追加していく処理の完成したコードは以下のようになっています。
```tsx
    const timer = setInterval(() => {
      （中略）

      // 更新用関数setDisplayedで1文字ずつ追加していく
      const nextChar = text[i];
      setDisplayed((prev) => {
        const next = prev + nextChar;
        return next;
      });

      i++;

    }, 100);
```
初めは以下のように実装していました。

```tsx
    const timer = setInterval(() => {
      （中略）

      // 更新用関数setDisplayedで1文字ずつ追加していく
        setDisplayed((prev) => prev + chars[i]);

        i++;

    }, 100);
```
しかしこの場合は、たとえば「あいうえお」と入力すると「あうえおundefined」のように、途中の文字が抜け代わりに最後、undefinedが追加されてしまうような状態になってしまっていました。
なぜこうなるのかについて、setDisplayed関数がすぐに実行されないことが原因のようでした。
実行されるまでの間に i++ が実行され、iの値が変わってしまう。そのため、2文字目が消えてしまい、意図しないundefinedが表示される不具合が発生する。という流れになってしまっていました。

完成版のコードの場合は、`const nextChar = text[i];` が即時に実行されるので、
nextCharの値が確定します。そのため、setDisplayed内では値はズレることなくdisplayedが更新されるという流れになります。

状態を更新する関数の中で外部の変数を参照する際には注意が必要だということを学びました。
[Linux][command] シェル変数と環境変数_シェルのオプション_set

# setコマンド
~~~bash
$ set [-o][+o] [オプション]
~~~


| オプション       | 由来          | 説明                                             |
| :---------- | :---------- | :--------------------------------------------- |
| `-o`のみ |  | シェルのオプションの設定状態を確認する |
| `allexport` | all export  | 新規作成・変更した変数を自動的に環境変数としてエクスポートする                |
| `emacs`     | Emacs       | Emacs エディタと同様のキーバインドを使用する（例: 矢印キー、`Ctrl+D`で削除） |
| `ignoreeof` | ignore EOF  | `Ctrl+D` によるシェルのログアウトを無効にする（誤操作防止）             |
| `noclobber` | no clobber  | `>` や `>>` によるファイルの**上書きを禁止**する                |
| `noglob`    | no globbing | パス名展開（ワイルドカードなど）を無効にする                         |
| `noexec`    | no execute  | スクリプトを**実行せずに構文チェックのみ**行う                      |
| `vi`        | vi editor   | vi エディタと同様のキーバインドを使用（ESC でコマンドモードへ）            |


# Ping-t
- [4782_set -o noexec](https://mondai.ping-t.com/question_subjects/32/question_sessions/33449680/progressing_questions/512330531?result=true)
- [4786_set -o ignoreeof](https://mondai.ping-t.com/question_subjects/32/question_sessions/33449680/progressing_questions/512330525?result=true)
- [4817_set -o](https://mondai.ping-t.com/question_subjects/32/question_sessions/33502345/progressing_questions/513098363?result=true)
統計検定準1級・第9章の分散の区間推定の導出

# 分散の区間推定
　確率変数 $X$ が $N(\mu, \sigma^2)$ に従うとする. 母分散 $\sigma^2$ の区間推定について考える. ここで, 母平均 $\mu$ は未知とする.

　$N(\mu, \sigma^2)$ からの独立な標本 $X_1,X_2,...,X_n$ の標本平均 $\bar{X}$ からの偏差平方和を $T^2 = \sum_{i=1}^{n} (X_i - \bar{X})^2$ とする. $\chi^2 = T^2/\sigma^2$ は自由度 $n-1$ のカイニ乗分布に従う.

**証明**
```math
\begin{align}
\chi^2 &= \frac {T^2} {\sigma^2} \\
&= \frac {\sum_{i=1}^{n} (X_i - \bar{X})^2} {\sigma^2} \\
&= \frac {\sum_{i=1}^{n} (X_i - \mu + \mu  - \bar{X})^2} {\sigma^2} \\
&= \frac {\sum_{i=1}^{n} (X_i - \mu)^2 + 2\sum_{i=1}^{n} (X_i - \mu)(\mu  - \bar{X}) + \sum_{i=1}^{n}(\mu  - \bar{X})^2} {\sigma^2} \\
&= \frac {\sum_{i=1}^{n} (X_i - \mu)^2 - n(\mu  - \bar{X})^2} {\sigma^2} \\
&= \sum_{i=1}^{n} (\frac {X_i - \mu} {\sigma})^2 - (\frac {\bar{X} - \mu} {\sigma/\sqrt{n}})^2 
\end{align}
```

$$
\frac {X_i - \mu} {\sigma} \sim N(0,1) より, \sum_{i=1}^{n} (\frac {X_i - \mu} {\sigma})^2 \sim \chi^2(n)
$$

$$
\frac {\bar{X} - \mu} {\sigma/\sqrt{n}} \sim N(0,1) より, (\frac {\bar{X} - \mu} {\sigma/\sqrt{n}})^2  \sim \chi^2(1)
$$

したがって, カイニ乗分布の再生性より, $\chi^2 = T^2/\sigma^2$ は自由度 $n-1$ のカイニ乗分布に従う.

カイニ乗分布の上側2.5%点 $\chi^2_{0.025}(n-1)$ および上側97.5%点 $\chi^2_{0.975}(n-1)$ から, 以下の確率式が成り立つ.

$$
P(\chi^2_{0.975}(n-1) \leq \chi^2 \leq \chi^2_{0.025}(n-1)) = 0.95
$$
【SQL】第7回勉強日記 問題解答 難易度★★☆☆☆ 内容：JOIN

# こんばんは！
今日もやっていきます！
来週出張なので、月曜から木曜までお休みいただきます！
という報告が済んだところでさっそくやっていきます！

# 今日の問題
今日の問題はこちら！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053502/d80f6cfc-1b92-48f6-9c1c-2d840aa1e4fa.png)

これはplayersテーブルのpositionを取り出して、
それをGROUP BYして
ゴール数はgoalsテーブルのplayer_idを取り出して
それをplayersテーブルのidとJOINして...

みたいな感じかなとぱっと見で思いました！
書いていきます！

【私の解答】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053502/4263bc32-0929-472b-b9f8-804732dbb243.png)

かなり自信があります！！
動かすと↓のような感じ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053502/85cb0f59-7fb2-4f4f-87e8-0b77481bd5bc.png)

なんとなくあっていそう！
最近とんでもなく安定してクエリを書けています
研修中のクエリも可読性やクエリコストを考えながら
書くことができていますし、成長を感じております...
これからもっと頑張りたいです！

# おわりに
今日も数はなんだか違いましたが、
クエリ自体は間違っていないかと思います
日々、クエリの精度が上がっていてとてもうれしいです
クエリをすらすら書けるようになったら
Pythonも始めてみようかなと思ってます...
その前にCBASやらG検定やら統計検定を受けたいので
勉強あるのみですね...頑張ります！
それでは！
error: Target of URI doesn't exist: 'package:flutter_gen/gen_l10n/app_localizations.dart'.を解消する

## エラー全文
```
error: Target of URI doesn't exist: 'package:flutter_gen/gen_l10n/app_localizations.dart'.
````
とか
```
error: Undefined name 'AppLocalizations'.
```
とかのエラーが、`Flutter3.32`系から発生するようになりました

## 原因
`Flutter 3.32.0`以降、国際化（i18n）に関する重要な変更が導入され、
`flutter gen-l10n`コマンドの挙動が変更され、従来の`package:flutter_gen`の使用が**非推奨**となったため

## 移行手順
### 移行の対象か確認
以下のように`generate: true`としているプロジェクト
```pubspec.yaml
flutter:
  generate: true
```

### 手順1
l10n.yaml に synthetic-package: false を追加

```diff_yaml
+ synthetic-package: false 
arb-dir: lib/i18n # .arbファイルが配置されていたディレクトリを指定 自分は`lib/localization`でした
- output-localization-file: app_localizations.dart
+ output-dir: lib/generated/i18n # 新規でapp_localizations.dart等が格納されるディレクトリを指定
```

### 手順２
app_localizationsを作成する
```shell
flutter pub get
```
手順１で設定した`output-dir`に`lib/generated/i18n/app_localizations.dart`や
`lib/generated/i18n/app_localizations_ja.dart`が作成される

### 手順3
インポートパスの修正
```diff_dart
+ import 'package:your_app_name/generated/i18n/app_localizations.dart';
- import 'package:flutter_gen/gen_l10n/app_localizations.dart';
```

### 手順3
`flutter config`コマンドの使用（オプション）
明示的なパッケージ依存関係の管理を有効化する
```shell
flutter config --explicit-package-dependencies
```
## 参考
https://docs.flutter.dev/release/breaking-changes/flutter-generate-i10n-source
useEffectやuseStateをどこで呼ぶべきか？Hookの呼び出し位置が重要な理由

# はじめに

Reactで`useEffect`や`useState`といった**Hook**を使う際、 **「どこで呼ぶか」** がとても大切です。

たとえば、「全体のレイアウトにあるコンポーネントにHookを書いて、それが個別のページにも影響する」といったケースは、**期待通りに動かない**ことがあります。

本記事では、**Hookの呼び出し場所がなぜ重要なのか**、簡単なコード例とともに解説します。

# 🚫 レイアウトでページ固有の処理をする

```tsx:Layout.tsx
import { useEffect } from "react";

export default function Layout({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    console.log("ページ訪問ログを送信！");
  }, []);

  return <div>{children}</div>;
}
```

この`Layout`は、**全ページ共通で使われる**コンポーネントです。ここでログ送信などの処理を書くと、**すべてのページで実行されてしまいます**。

つまり、「Aページにだけログを送りたい」「特定の条件でだけ実行したい」という目的には**不適切**です。

# ✅ 対象のコンポーネント内で呼び出す

```tsx:pages/PageA.tsx
import { useEffect } from "react";
import Layout from "@/components/Layout";

export default function PageA() {
  useEffect(() => {
    console.log("Page A にだけログ送信！");
  }, []);

  return (
    <Layout>
      <h1>Page A</h1>
    </Layout>
  );
}
```

このように、**ページコンポーネント内でHookを呼び出す**ことで、「PageAを表示したときにだけ」`useEffect`が実行されます。

**🎯 ポイントまとめ**

* Hook（`useEffect`, `useState`, `useContext`など）は**トップレベルでのみ**呼び出す必要がある（条件分岐の中はNG）
* **どのコンポーネントに属しているか**が非常に重要
* 共通レイアウトに書くと、**全ページで実行される副作用**になってしまう可能性がある
* **特定ページ・特定条件での処理は、そのコンポーネント内でHookを使うべき**

# おわりに

ReactのHookはとても強力ですが、「呼び出す場所」を間違えると**バグの元**になります。とくに、Next.jsなどで共通レイアウトを使っている場合、**うっかり共通処理に入れてしまうことが多い**です。

意図通りの動作をさせるためにも、「この処理はどのコンポーネントで起きるべきか？」を意識して、Hookを正しく使っていきましょう！
useEffectのクリーンアップとメインブロックで同じ処理を書く必要はあるのか？

# はじめに
Reactの`useEffect`を使って定期的な処理（`setInterval`）を実装するとき、次のようなコードを見ることがあります：

```tsx
useEffect(() => {
  // メイン処理
  if (isRunning) {
    intervalRef.current = setInterval(() => {
      console.log("Running...");
    }, 1000);
  } else if (intervalRef.current) {
    window.clearInterval(intervalRef.current);
    intervalRef.current = null;
  }

  // クリーンアップ処理
  return () => {
    if (intervalRef.current) {
      window.clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
  };
}, [isRunning]);
```

一見すると `else if` ブロックと `return` のクリーンアップ関数が同じことをしているように見え、

> 「クリーンアップで止めるなら `else if` いらないのでは？」

と思う方も多いでしょう。

結論から言えば、**実はこの`else if`は不要です**。

@honey32 さん、いつもありがとうございます。

# useEffectの実行タイミングをおさらい

* **初回レンダリング時**：`useEffect`本体が実行される。
* **依存配列（例: `[isRunning]`）が変わるたび**：
  ① クリーンアップ関数が呼ばれ
  ② その後に`useEffect`本体が再実行される。
* **コンポーネントのアンマウント時**：最後にクリーンアップ関数が呼ばれる。

つまり、`isRunning` が `true → false` に変わったときは、**前回のEffectのクリーンアップ関数が呼ばれ、そこで`clearInterval`される**のです。

 **✅ `else if` を省いたシンプルで安全な実装**

```tsx
useEffect(() => {
  if (!isRunning) return; // ここで早期に抜ける（《「処理の塊」を意識するための補助線》）

  const interval = window.setInterval(() => {
    setCount((prev) => prev + 1);
  }, 1000);

  return () => {
    window.clearInterval(interval);
  };
}, [isRunning]);
```

> **《「処理の塊」を意識するための補助線》として活用することをオススメします！**

「処理の塊」とは、

* `isRunning === true` なら「タイマーを動かす処理」
* それ以外のときは「なにも処理しない」
* `isRunning === true` のときだけ `setInterval`
* `false` になったときは、**前回Effectのクリーンアップで自動的に停止**

これで十分機能します。**`else if`ブロックは不要**です。

# すぐ止めたいから else if が要るのでは？

「ボタンを押して `isRunning = false` にした瞬間、**クリーンアップが走るまでの間にレースコンディションが起こるのでは？**」という懸念があるかもしれません。

しかし、Reactは依存配列が変化した際：

1. クリーンアップ関数を**先に必ず**実行
2. その後でEffect本体を再実行（今回で言えば何もせずreturn）

この順序は保証されています。したがって、**「クリーンアップより先に何か起こってリークする」ような race condition は起こりません**。

また、`intervalRef`のような変数も、**クリーンアップ内で止めていれば残っていても実害はなく、次の起動で上書きされるだけ**です。

**🚨例外**
`intervalRef.current` を他の処理でも参照している場合

以下のように、Effect外で `intervalRef.current` を参照して条件分岐しているケースでは、明示的に `null` にした方が安全です：

```tsx
if (intervalRef.current) {
  // タイマー中かどうかの判定に使っている
}
```

このようなケースではクリーンアップ内で `intervalRef.current = null` を明示的に書くことは有意義です。

# 🧩 補足：`setInterval` vs `window.setInterval`

前述のタイマー処理に関連して、`setInterval` の使い方にも注意点があります。

```tsx
// ❌ Node.js の型になる可能性あり
const intervalRef = useRef<NodeJS.Timeout | null>(null);
intervalRef.current = setInterval(...);

// ✅ ブラウザで確実に number 型になる
const intervalRef = useRef<number | null>(null);
intervalRef.current = window.setInterval(...);
```

TypeScript 環境では、`setInterval` は実行環境により戻り値の型が異なり、
**Node.js 環境では `NodeJS.Timeout`、ブラウザでは `number`** になります。

React + ブラウザ前提のコードでは、**意図的に `window.setInterval` を使うことで型を明確に `number` に固定**できます。

💡 `clearInterval` でも同様に `window.clearInterval` を使うのがおすすめです。

# おわりに

eactの`useEffect`は、「セットアップとクリーンアップが1つの処理の塊」である、という考え方が大切です。

処理を明示的に分けすぎてしまうと、Reactの自然なフローを逆行するような冗長なコードになります。

「**falseになったら止まる**」「**クリーンアップは必ず呼ばれる**」というルールを信頼して、よりシンプルで読みやすいコードを書いていきましょう！
BIOS開発1日目　予備知識をつける(完全備忘録！)

## 「手探りでCUI OS作成に挑む」連載

この記事は「手探りでCUI OS作成に挑む」連載の一部です。
全体の目次は[「手探りでCUI OS作成に挑む」連載目次](https://qiita.com/earthen94/items/b5d77f98f0cf85a13346)を御覧下さい。

## 目的
OS開発をしていると、BIOSの機能に頼らざるを得ないところが出てきます。
文字の表示やディスクの読み込み等が主なものです。
そこでBIOSが何をしているのか気になったので自分で作ることにしました。

## 考えていること
本当の意味でのBIOSを開発しようとするとマザーボードがら開発することになり個人では不可能な為、QEMU上で動くBIOSを開発することにしました。
よってハードウェアの診断等は省きます。
とにかく動けばよいという精神の元、できる限り簡単で短いBIOSを作ろうと思います。
BIOS呼び出し(INTで呼び出すあれ)も必要最低限のものにとどめます。
今の所一番の難題はVGAの初期化です。
画面表示をするだけでも大量のレジスタを適切な値で初期化しなければなりません。

## 予定
BIOSを作ってデバッグをするのは何かと不便なのでブートセクタ(0x7c00からの512バイト)でBIOS呼び出しの中身を実装し、IVTを書き換えて動くかを試しながら開発を進める予定です。
景気づけにint 19hから初めていく予定です。

## 手稿
自分で書きながらまとめている最中の紙です。
自分で見返すために上げておきます。
![f4a0271ba753702a481451c74eafbe46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/7ae19c52-baf2-4ad0-8e79-f65243d5bef8.jpeg)
![c3fb10c66d49577d9c1d68782174d346.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/07aaec2d-997b-4b38-bfd5-f69ef22709b6.jpeg)

## 勉強風景
![ccb0f027d8f2bcad00c80702f64f1cfb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/10b51a2e-60d6-49d0-b329-ba85a0310c49.jpeg)