OmniAICreator/Qiita-1.07M huggingface dataset:
MDX の紹介

![mdx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4049554/d2bc2d9b-a0bf-4ecf-b6ca-4f097fd6022d.png)
# MDX の紹介
MDX(Markdown + JSX)とは、Markdownの簡潔さとJSXの柔軟性を組み合わせた強力なフォーマットです。開発者はこれを使うことで、Markdownの記法とReactを一緒に使うことができます。だからMDXは記事やコンテンツを書くには良い選択です。
## MDXを選ぶ理由

MDXは幾つか利点があります：
1. **使い慣れた構文**：MDXはMarkdownの上に作られたものですから、学ぶのも、覚えるのも簡単です。<br/><br/>
2. **コンポーネントの統合**: ReactのコンポーネントをMDXに簡単に組み込むことで、動的なコンテンツを作成できます。<br/><br/>
3. **コンテンツを再利用できます**: 同じコンポネントを再利用して数回のMDXフャイルニ使うことができます。<br/><br/>
4. **カストマイズ可能です。**: MDXを使って例えば見出し、リスト、画像のような要素をカスタムコンポーネントに変換して、何度も使用することができます。<br/><br/>
5. **良い書類に使える**: MDXは主にドキュメント、ブログ、コンテンツ中心のウェブサイトでよく使われています
## MDXの働きかた

MDXファイルとは、Markdownの記法とJSXを組み合わせたファイルのことだ。MDXファイルの使い方の例文：

```mdx
# 俺のブログへようこそ
これはMDXを使って書かれた簡単なブログです。 下の行ではReactコンポーネントを使っています：
<MyComponent title="こにちは、MDXの使うブログです" />

リストやリンクなど、Markdownのすべての構文を使うことができます。：
- 一つのアイテム
- 二つのアイテム
- 三つのアイテム
```
<br/>
<u>[MDXについてもっと学ぶ](https://mdxjs.com)</u>
Raspberry Pi Pico 公式の環境構築でハマった記録 

以前に以下の記事を書いていますが、PCを買い替えたので再度環境構築してまたハマったので備忘録。

https://qiita.com/uduki-oh-yeah/items/ba07bfec9ed2b3c62575


## 今度は日本語名が問題ではなかった

前回の反省を生かして、Windowsのユーザー名は日本語を含んでおりません。完璧。
そう思ったのに、どうしても環境構築でつまずく…おのれ Raspberry Pi pico


## 自分の環境

| 環境 | バージョン |
|:-:|:-:|
| VSCode  | 1.100.1  |
|  Raspberry Pi Pico拡張 |  0.17.5 |
|  OS |Windows11 |
|  マイコン | Raspberry Pi Pico W (WH)  |

## 公式開発環境

2025年5月16日現在の Raspberry Pi Picoの公式の開発環境は、
VSCode + Raspberry Pi Pico 拡張機能 を使用した環境です。

https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf


## 現象

* VSCode の拡張機能から「New Projct From Example」を選択
* Select an example に「blink」を選択
* Board type はデフォルトのまま「Pico 2」にする
* その他デフォルト設定でCreateボタンを押す
* `blink.c` と `CMakeLists.txt` のみが作られたプロジェクトフォルダが作成される

？？？？？

ああ～ Pico2 じゃなかった～　間違っちゃった～
※この時点でPico2 を使ってる人は困るけどね

## 現象

* VSCode の拡張機能から「New Projct From Example」を選択
* Select an example に「blink」を選択
* Board type は「Pico W」にする
* その他デフォルト設定でCreateボタンを押す
* `blink.c` と `CMakeLists.txt` のみが作られたプロジェクトフォルダが作成される

toolchainとかないとビルドできないのですが…？？？？？
それをやってくれるプラットフォームじゃないの…？？？？

## 原因・解決方法

いろいろ試してわかったのは、初回は以下の設定じゃないと、toolchainやsdkをダウンロード・インストールしてくれません。

* VSCode の拡張機能から「New Projct From Example」を選択
* Select an example に「blink」を選択
* Board type は **「Pico」** （絶対Picoじゃないとだめ）
* 無事にsdkやtoolchainのダウンロードが始まりましたとさ


### しかしPico W ユーザーは以下の手順を忘れずに。

* sdk のダウンロードが終わったので、 blinkプロジェクトを削除する。（pico用なので、pico Wにインストールしても動かない）
* 再度 PicoWをBoard typeに設定し、プロジェクトを作成する
* すでにsdkなどはインストール済みなので、エラーにならず済む…
【Java】3分で読めるMapについて

## Mapとは
キー(key)と値(value)をセットで保存するインタフェース

```
Map<String, Integer> map = new HashMap<>();
map.put("apple",100);
map.put("banana",200);
System.out.println("apple"); // 100
```

## Mapの特徴
1. keyは一意（重複しない）
1. valueは重複してもよい

## HashMapとは
Mapインタフェースの実装クラス
高速な検索・追加・削除が可能なデータ構造

* 順序の保持はしない
* keyにnullをひとつだけ設定できる
* 値にnullを複数設定できる
* スレッドセーフではない（並行処理で問題が発生する可能性あり）

## Mapで使用するメソッド
①要素の追加　`map.put("key",value);`
```
Map<String, String> map = new HashMap<>();
map.put("name", "Taro");
map.put("city", "Tokyo");
map.put("job", "Teacher")
```
② 要素の取得　`map.get("key");`
```
System.out.println("name：" + map.get("name")); // Taro
```
③ 要素の削除　`map.remove("key");`
```
map.remove("city");
```
④ キーの存在確認　`map.containsKey("key");`
```
System.out.println(map.containsKey("name")); // true
System.out.println(map.containsKey("city")); // false
```
⑤ 値の存在確認　`map.containsValue(value);`
```
System.out.println(map.containsValue("Taro")); // true
System.out.println(map.containsValue("Tokyo")); // false
```
⑥ マップの要素数を取得　`map.size();`
```
System.out.println(map.size()); // 2
```
⑦ 全てのキーを取得　`map.keySet();`
```
System.out.println(map.keySet()); // [name, job] 
```
⑧ 全ての値を取得　`map.values();`
```
System.out.println(map.values()); // [Taro, Teacher] 
```
⑨ 全てのエントリ取得　`map.entrySet();`
```
System.out.println(map.entrySet()); // [name:"Taro", job:"Teacher"] 
```

記事作成時間：25分
DatabricksのノーコードでLLMにクエリを実行し、AIエージェントをプロトタイプ化してみた

## 前提
・利用環境：Databricks

https://www.databricks.com/jp/try-databricks?scid=7018Y000001Fi15QAC&utm_medium=paid+search&utm_source=google&utm_campaign=17377047998&utm_adgroup=138148229998&utm_content=trial&utm_offer=try-databricks&utm_ad=732035937815&utm_term=databricks%20%E3%83%88%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%AB&gad_source=1&gclid=CjwKCAiA8Lu9BhA8EiwAag16b8b3zbkIb3V7gp-8VUwKukXnhtVZRQ-1RY8SbETmGVgNT4bQramYmRoCX5wQAvD_BwE#account

## 参考ドキュメント

https://docs.databricks.com/gcp/ja/getting-started/gen-ai-llm-agent

## 操作手順（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/c8Wx8sB8-4c?si=dZaTxhJA3Pin4XTJ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
WinSCP をコマンドラインでインストールする

# WinSCP をコマンドラインでインストールする
 複数台のデプロイ端末をキッティングするのに効率が良い方法を考えている。どうやら```winget```でアプリのインストールができる様子。

# 環境
Microsoft Windows 11 Home
バージョン 24H2（OSビルド 26100.4061）

# 作業

## WinSCP のインストール

まず始めに、WinSCP が存在するかどうかを確認する。
```powershell```を起動した後に```winget search winscp```と入力する。
```
PS C:\Users\hogehoge> winget search winscp
名前      ID               バージョン 一致        ソース
--------------------------------------------------------
WinSCP    WinSCP.WinSCP    6.5.1                  winget
WinSCP RC WinSCP.WinSCP.RC 5.18.5-    Tag: winscp winget
PS C:\Users\hogehoge>
```
見つかった。

この結果から、WinSCP の ID が```WinSCP.WinSCP```と判明。
次に、```powershell``` にて ```winget install --id WinSCP.WinSCP -e```と入力する。
```--id``` は、インストールする対象の曖昧さをなくすもの。Microsoft が ***「アプリケーションの ID を使用するのが最善です。」*** と言っている[^1]。
```-e``` は、オプションの大文字小文字を区別するというもの。

```
PS C:\Users\hogehoge> winget install --id WinSCP.WinSCP -e
見つかりました WinSCP [WinSCP.WinSCP] バージョン 6.5.1
このアプリケーションは所有者からライセンス供与されます。
Microsoft はサードパーティのパッケージに対して責任を負わず、ライセンスも付与しません。
ダウンロード中 https://sourceforge.net/projects/winscp/files/WinSCP/6.5.1/WinSCP-6.5.1-Setup.exe/download
  ██████████████████████████████  11.6 MB / 11.6 MB
インストーラーハッシュが正常に検証されました
パッケージのインストールを開始しています...
インストーラーは管理者として実行するように要求するため、プロンプトが表示されます。
インストールが完了しました
PS C:\Users\hogehoge>
```

## WinSCP の起動

Windows メニューに WinSCP が加わったので、クリックして起動。

![caced5f7-81e9-4259-9e7c-d8907700ba70.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553429/88f73ebc-7edc-4c08-92fe-d79f376545cb.png)

インストールされたバージョンは、```6.5.1（ビルド 16311 2025-05-05）```。今日が 2025/5/16なので、11日前にビルドされたバージョンということになる。最新版だ。

## WinSCP のアンインストール
```winget uninstall WinSCP.WinSCP -e```で、アンインストールできる。

```
PS C:\Users\hogehoge> winget uninstall WinSCP.WinSCP -e
見つかりました WinSCP 6.5.1 [WinSCP.WinSCP]
パッケージのアンインストールを開始しています...
正常にアンインストールされました
PS C:\Users\hogehoge>
```

[^1]:[install コマンド Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/package-manager/winget/install)
5分で復習しな！第一正規化から第三正規化

# 正規化を最短でまとめる
なぜかって？ちょっと復習をしようと思ったら、
難しい言葉で書かれていて理解するのに時間がかかったからだ。

正規化をする理由！
- 見やすくする！
- 修正があった場合に一箇所修正すれば全て反映されるようにする！
    - 何箇所も修正する手間をなくす。（ミスが無くなる）

## ぐちゃぐちゃ表（未正規化）

| 商品名 | 価格 | 仕入先                | 仕入先住所                  | カテゴリー |
|-------|------|----------------------|----------------------------|-----------|
| りんご | 100円 | 青森農園, 長野農園     | 青森県xxx, 長野県yyy         | 果物        |
| みかん | 80円  | 愛媛農園              | 愛媛県zzz                   | 果物        |
| キャベツ | 120円 | 群馬農園, 茨城農園     | 群馬県aaa, 茨城県bbb         | 野菜        |

*1つのセルに複数の値が入っていて読みにくい！

---

## 第一正規化
1セル1データに分割

| 商品名 | 価格 | 仕入先   | 仕入先住所 | カテゴリー |
|-------|------|----------|-----------|-----------|
| りんご | 100円 | 青森農園 | 青森県xxx  | 果物        |
| りんご | 100円 | 長野農園 | 長野県yyy  | 果物        |
| みかん | 80円  | 愛媛農園 | 愛媛県zzz  | 果物        |
| キャベツ | 120円 | 群馬農園 | 群馬県aaa | 野菜        |
| キャベツ | 120円 | 茨城農園 | 茨城県bbb | 野菜        |

*行を増やして **1行＝1仕入れ先** に整理。  
これで行の長さが統一されてRDBに入れられるようになった。

---

## 第二正規化
主キーとそれにつながるデータを別テーブルに分割
- 商品名が決まれば価格とカテゴリーが決まる
- 仕入先が決まれば住所が決まる


### 商品テーブル（`products`）
#### 商品名が決まれば価格とカテゴリーが決まる。
| 商品ID | 商品名 | 価格 | カテゴリーID |
|-------|--------|------|-------------|
| P1    | りんご | 100円 | 果物          |
| P2    | みかん | 80円  | 果物         |
| P3    | キャベツ | 120円 | 野菜          |

### 仕入先テーブル（`suppliers`）
#### 仕入先が決まれば住所が決まる。
| 仕入先ID | 仕入先名 | 住所      |
|---------|----------|-----------|
| S1      | 青森農園 | 青森県xxx |
| S2      | 長野農園 | 長野県yyy |
| S3      | 愛媛農園 | 愛媛県zzz |
| S4      | 群馬農園 | 群馬県aaa |
| S5      | 茨城農園 | 茨城県bbb |

これ以上はもう分割できない。


### 取引テーブル（`product_supplier`）
#### 分割した元のテーブルはこうなる
| 商品ID | 仕入先ID |
|-------|----------|
| P1    | S1       |
| P1    | S2       |
| P2    | S3       |
| P3    | S4       |
| P3    | S5       |

主である取引テーブルはもう分割できない。

---

## 第三正規化（無関係な情報もさらに分割）
第二正規化で分割したテーブルを確認して重複があるものを更に分割する。

商品テーブルがまだ正規化できる。
### カテゴリーテーブル（`categories`）

| カテゴリーID | カテゴリー名 |
|-------------|-------------|
| C1          | 果物        |
| C2          | 野菜        |

↑これ以上はもう分割できない。

### 更新後の商品テーブル

| 商品ID | 商品名 | 価格 | カテゴリーID |
|-------|--------|------|-------------|
| P1    | りんご | 100円 | C1          |
| P2    | みかん | 80円  | C1          |
| P3    | キャベツ | 120円 | C2          |

↑これ以上分割できない。

---

## まとめ

- **第一正規化**
    - 1つのマスに1つのデータ
- **第二正規化**
    - レコードテーブルから主キーになるテーブルを作成して分ける。重複データを別テーブルへ
        - レコードテーブルを分割できない状態にする
- **第三正規化**
    - 分割した先のテーブルで更に分割する
「手探りでCUI OS作成に挑む」　開発日記2025年5月15日

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

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

計算機の仕組みを根底から理解し、そしてその結果を布教したくてこの連載を始めました。

大学で計算機について４年間学び、その後会社に入りjavaやsqlを使ってシステムの開発をしていましたが、実際に内部でどう動いているのか想像できず、又どう勉強したら良いのかも分からず、難しい本を買っては挫折を繰り返して来ました。

例えばHELLOWORLDのプログラム、なぜprintfを呼び出すだけで画面上に文字が表示されるのか。
この標準関数の中身はどうなっている、OSはなぜ動く、本に載っているような概念的なことではなく、実際にどう実装されているのかずっと知りたいが、調べようがない、そんなジレンマをずっと抱えていました。

そんな疑問は計算機に限った事ではありません。
例えばカレーを作るとして、ルーから作ったカレーは果たして自分が作ったと言えるのか。
ではルーから作ればよいのか？材料の小麦は自分が植えたものを使わないといけないのか？
でも小麦の種を植えて収穫した小麦は自分で作ったと言えるのか。
突き詰めれば原子、敷いては宇宙の真理に辿り着くのではないか、昔からそんな壮大な想像をよくしてきました。

最近AIが普及しだし、自分の疑問を直接聞けるようになり、知識が飛躍的に増えました。

ずっとアセンブリ言語に興味がありましたが、本を買ってもよく分からず２冊ほど捨てました。しかし今はAIに聞くと答えてくれます。

BIOSの仕組み、OSの仕組みなど、本を読んでも分からなかったことがどんどん分かるようになっていきました。
１時間に１回は何かしら聞いている気がします。

そこでCUIのOSを作ってみることを思いつきました。
本当はGUIで作れたら嬉しいですが、能力が追いつかないので一旦諦め、CUIからMSDOSのようなものを作ることにしました。

C言語などに頼ってしまうと、抽象化されてしまうところがあるので、全て自分で実装できるアセンブリ言語を使うことにしました。

BIOS割り込みは仕方なく使っていますが、痒い所に手が届かない感じがあるので、並行してBIOSも作っていくつもりです。
ある程度コードはできているのですがコンパイルが通っていません。

思ったより順調に進んでいるかなと思います。
AIがないとここまでこれませんでした。
自分で書いていないコードがたくさんあることに引け目を感じることもありました。
しかし少なくとも記事にする前に一行一行理解し、そして検証もし、理解した上で自分の言葉で解説をしています。

AIがなければこの土俵にすら立ててません。
OS30日本すら挫折した人間です。
ブートローダーすら書けなかったでしょう。
あるものは使ってそれで自分の学びになるのならよいと、割り切ってこれからもAIの力を借りながら開発を進めていきます。

読んでくれる人が１人でもいれば幸いです。
Git操作　実務で生じた事象と対応のメモ


## developからブランチを切るべきところ、誤ってmainから切って作業してしまった場合（rebaseで対応するケース）

作業ブランチ feature/foo を作成する際、develop からではなく main（または master）から切ってしまい、開発を進めてしまった。
図で説明すると以下の通り（前提：今のブランチ名を feature/foo と仮定）
```
# 現状（間違って master から切って作業中）
master
  A---B
         \
          C---D   ← feature/foo（ここで作業中）

# やりたい形（develop をベースにしたかった）
develop
  E---F---G
           \
            C'--D' ← feature/foo（履歴を載せ替えたい）
```
対応は以下の手順
```
# 1. developブランチを最新に更新
git checkout develop
git pull origin develop

# 2. 間違ってmasterから切って作業していたブランチに戻る
git checkout feature/foo

# 3. 現在の変更をdevelopブランチの上に載せ替える
git rebase develop
```

以下のコマンドによって、feature/foo が develop の延長線上にあるかを確認できます。
```
git log --oneline --graph --all
```

## developからブランチを切るべきところ、誤ってmainから切って作業してしまった場合（cherry-pickで対応するケース）

rebase を使う方法もあるが、cherry-pick でコミット単位に明示的に載せ替える方法もある。
履歴のコントロールがしやすいため、ブランチのベース変更 + 履歴の確認を慎重に対応する場合に有効。

```
# 1. develop から新たに正しいベースのブランチを作成
git checkout develop
git pull origin develop　#最新の状態に更新
git checkout -b feature/foo-fixed

# 2. 元のブランチのコミットハッシュを確認
git log --oneline feature/foo

表示結果_例）
d4e5f67 D: implement error handling
a1b2c3d C: add basic UI

# 3. cherry-pick で拾いたいコミットを順番に適用
git cherry-pick a1b2c3d
git cherry-pick d4e5f67

# 4. 作業結果を確認し、問題なければ旧ブランチを削除 or 差し替え
# 問題なければ旧ブランチを削除してブランチ名をしゅう
git branch -D feature/foo
git branch -m feature/foo feature/foo-fixed

```
以下のコマンドによって、feature/foo が develop の延長線上にあることを確認。

```
git log --oneline --graph --all
```


## ブランチ切って作業している時に、突発的な別タスクが発生した場合
```
# 1. 今の作業内容を退避（未追跡ファイルも含めて）
git stash -u
※ -u オプションで git add していない 新規ファイルも一緒に退避される

# 2. develop にチェックアウトして最新化
git checkout develop
git pull origin develop

# 3. 突発タスク用の新しいブランチを切る
git checkout -b new-task

# 4. そのタスクの作業を行い、コミット・プッシュ
git add .
git commit -m "Fix urgent issue"
git push origin new-task

# 5. 元の作業に戻る
git checkout feature/original-task
git stash pop
```

## リモートdevelopの最新状況をローカルdevelopにpullすべきところ、ローカルmainブランチにpullしてしまった場合
本来関係ない main ブランチに develop のコミットが混ざってしまい、意図しない履歴になってしまった。

🛠 対応方法：git reflog と git reset で元に戻す
Gitは操作履歴を記録してくれているので、reflog を使ってpull前の状態に戻すことができます。

```
# 1. git reflog で履歴を確認する

$ git reflog

abc1234 HEAD@{0}: pull origin develop: Fast-forward
def5678 HEAD@{1}: checkout: moving from develop to main
...

# 2. git reset でpull前の状態に戻す（履歴を巻き戻す）

git reset --hard HEAD@{1}

```
この操作により、mainブランチが pull前の状態に戻ります。
※ --hard は作業中の変更もすべて破棄するため、変更があれば事前にstashやcommitで退避しておくこと。


## git hooksを用いたpre-commit / pre-pushをスキップしたい場合

```
#  pre-commit をスキップする（例: lint チェック等を飛ばしたい場合）
git commit -m "commit message" --no-verify

# pre-push をスキップする（例: テストやCIチェックを飛ばしたい場合）
git push origin HEAD --no-verify
```
[学習備忘録AtCoder C++] ABC089 B - Hina Arare, ABC080 B - Harshed Number  2025.5.15

## for文とbreak
#### [Hina Arare](https://atcoder.jp/contests/abc089/tasks/abc089_b "Hina Arare")
```　abc089_b.cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
  int N ;
  cin >> N;
  string check = "Three";
  for (int i = 0; i < N; i++){
    string x;
    cin >> x;
    if (x == "Y"){
      check = "Four";
      break;
    }
  }
   cout << check << endl;
}
```
Yが一つでも入っていたらFourになる。最初はそれに気づかず時間が掛かってしまった。また、最後の`check`出力を`for文`の中に入れてしまっていたため`WA`となってしまった。

### /の特性と余剰を利用
#### [Harshed Number](https://atcoder.jp/contests/abc080/tasks/abc080_b "Harshed Number")
``` abc080_b.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    int N;
    cin >> N;
    int original_N = N;

    int sum = 0;
    while (N > 0) {
        sum += N % 10;
        N /= 10;
    }

    // 判定する（N の値は変わってしまっているので、予めコピーした値 original_N で判定）
    if (original_N % sum == 0) {
        cout << "Yes" << endl;
    }
    else {
    cout << "No" << endl;
    }
}
```
要はNの1の位をどのように取り出していくかということ、単純に10で割りつづけてそのあまりを`sum`に加算しつづける。Nは10で割った時の商を代入し続けていく。
最後は`original_N`と`sum`を用いて割り切れるか判定

各桁を加算するアルゴリズムは他でも使えそうなので備忘録として記録しておく。
Astroの動的ルーティング、静的ルーティング

## Webアプリケーション(SSR)におけるルーティング
### 動的ルーティング
リクエストごとにサーバー側で動的にHTMLを作成して返却する

### 静的ルーティング
ユーザーからのリクエストに対して、サーバーは事前に用意された静的なHTMLファイルをそのまま返す

## Astroにおけるルーティング

### 静的ルーティング

/pageディレクトリ配下で作成されたページは、自動でルーティングに登録される

**静的ルーティングの例**
```
src/pages/index.astro        -> mysite.com/
src/pages/about.astro        -> mysite.com/about
src/pages/about/index.astro  -> mysite.com/about
src/pages/about/me.astro     -> mysite.com/about/me
src/pages/posts/1.md         -> mysite.com/posts/1
```


### 動的ルーティング

>Astroページファイルのファイル名に動的ルートパラメータを指定すると、ファイルにマッチするページを複数生成できます。たとえばsrc/pages/authors/[author].astroは、ブログの各著者に対してプロフィールページを生成します。

動的ルートパラメータを指定して、複数ページを作ることを「動的ルーティング」と言っている。（おそらく）

Astroが定義する「動的ルーティング」の中に、「静的（SSG）モード」というものが存在する。

>静的（SSG）モード
すべてのルートをビルド時に決める必要があるため、動的ルートはgetStaticPaths()をエクスポートし、そこでparamsプロパティをもつオブジェクトの配列を返す必要があります。各オブジェクトは対応するルートを生成します。

Astroではこれを「動的ルーティング」と定義づけられるが、
SSG（サーバーサイドジェネレータ）式だと、ビルド時にHTMLが生成されるため、webアプリケーション的には、静的ルーティングともいえると思う。

## ページネーション作成時の参考

[getStaticPaths()](https://docs.astro.build/ja/reference/routing-reference/#getstaticpaths)


## 参考
[Astro公式 動的ルーティング](https://docs.astro.build/ja/guides/routing/#%E5%8B%95%E7%9A%84%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)
[SSG,SSRの違い](https://zenn.dev/rinda_1994/articles/e6d8e3150b312d#%E6%A6%82%E8%A6%81)
生成AI・LMM開発のための数学カリキュラム(日記)


## **第1部：線形代数・行列演算**

### 1.1 ベクトル・行列・テンソル表現

* 行列・テンソルの定義と表記法
* 高次元データのテンソル展開
* PyTorch/TensorFlowでのテンソル操作

### 1.2 線形変換・射影・固有値分解

* 線形写像と行列積
* 固有値・固有ベクトルの意味と計算
* 行列の対角化と安定性解析

### 1.3 特異値分解（SVD）・主成分分析（PCA）

* SVDの理論・次元削減・ノイズ除去
* PCAによる次元圧縮・可視化・説明変数分解

### 1.4 内積・外積・双線形形式

* 距離・類似度（Cosine Similarity）
* 双線形形式・Attentionの数学的基盤

---

## **第2部：確率・統計・情報理論**

### 2.1 確率変数・確率分布

* 離散・連続確率変数
* ガウス分布、マルチノミアル分布、ベータ・ディリクレ分布

### 2.2 エントロピー・KLダイバージェンス・クロスエントロピー

* 情報量の定義
* 確率分布間の差異指標
* 生成AIにおける損失関数への応用

### 2.3 ベイズ推定・期待値・分散

* ベイズの定理・事後分布推定
* 期待値・分散の性質と不確実性評価

### 2.4 マルコフ連鎖・確率過程

* 逐次的確率モデリング（言語モデル・拡散モデル）

---

## **第3部：最適化理論**

### 3.1 勾配法

* SGD、Momentum、Adam、RMSpropなどの挙動理解
* 学習率・バッチサイズ調整理論

### 3.2 損失関数設計

* MSE、Cross-Entropy、Hinge Loss
* 生成・識別モデルにおける役割

### 3.3 Lipschitz連続性・凸最適化・制約付き最適化

* GAN安定化（WGAN）
* 勾配消失/爆発の理論回避策

---

## **第4部：深層学習数学**

### 4.1 ニューラルネットワークの微分・バックプロパゲーション

* 連鎖律による効率的な勾配計算

### 4.2 重み初期化・正則化

* Xavier/He初期化、L1・L2正則化、Dropout理論

### 4.3 Attention Mechanism

* クエリ・キー・バリューの行列表現
* Scaled Dot-Product Attention
* Softmax正規化の意味

### 4.4 Transformer構造

* Multi-Head Attentionの並列計算
* Positional Encodingと系列情報付与

---

## **第5部：マルチモーダル処理の数理**

### 5.1 クロスモーダルマッピング

* テキスト・画像・音声の埋め込み統合
* マルチモーダル表現学習（CLIP, Flamingo等）

### 5.2 Contrastive Learning

* ポジティブ・ネガティブペア設計
* コントラスト学習による表現強化

### 5.3 マルチモーダルアテンション

* Cross-Attention、Gated-Attentionの機構理解

---

## **第6部：生成モデルの理論**

### 6.1 VAEの変分推論

* ELBO最大化
* 潜在変数モデルと再パラメータ化トリック

### 6.2 GANのミニマックス最適化

* 生成器と識別器のゲーム理論的学習
* WGANによるリプシッツ制約安定化

### 6.3 拡散モデルの確率過程

* ノイズ除去過程と逆拡散過程
* スコアベース生成との関連性

---

## **第7部：大規模分散学習と計算数理**

### 7.1 大規模行列計算・並列分散最適化

* モデル並列・データ並列のアルゴリズム理解

### 7.2 通信効率化技術

* AllReduce・Gradient Compression・ZeRO

### 7.3 モデル圧縮とスパース化

* パラメータプルーニング・量子化・蒸留技術
ブームから約1年——“幻のED法”がarXivで姿を現す

5/16 リンクが間違っていたので修正しました。

# はじめに
1年ほど前、Amazon Prime Videoで映画『Winny』が配信されました。その中で、金子勇氏が熱く語る「誤差拡散法（ED法）」のシーンが印象的です。

この映画をきっかけに、「誤差拡散法」という言葉が多くの人の目に触れ、Qiita上でも大きな話題となりました。最初の盛り上がりのきっかけとなった記事はこちらです：

『Winny』の金子勇さんの失われたED法を求めて...いたら見つかりました
https://qiita.com/kanekanekaneko/items/901ee2837401750dfdad

この記事では、筆者がなかなか見つからなかった手がかりを粘り強く探し、最終的には別の方がWebアーカイブからコードを発見・再現しています。
これほどまでに苦労した背景には、金子氏の論文がリジェクトされ、正式に発表される機会がなかったという事情があるのでしょう。

そして今、もはや“幻”とされていた誤差拡散法が、ついに論文として公開されました。

## A Basic Evaluation of Neural Networks Trained with the Error Diffusion Learning Algorithm
https://arxiv.org/abs/2504.14814

この論文はarXivに投稿されたもので、査読前ではあるものの、ED法がこうして世界に向けて共有されたことに感動を覚えます。

### 論文の著者について
本論文の著者は藤田 一寿氏（公立小松大学）です。リサーチマップはこちら：
https://researchmap.jp/read0128699

公立小松大学は私自身初めて聞く名前でしたが、それもそのはず。かつての私立短大や専門学校が統合され、2018年に開学した比較的新しい大学とのことです。
参考：https://ja.wikipedia.org/wiki/公立小松大学

筆者による誤差拡散法のコードはGitHubでも公開されています。
https://github.com/KazuhisaFujita/EDLA

## 論文の内容（要約）
※以下はAIによる要約を元に、一部改変を加えた内容です。

* ED法は、以下の3つのタスクにおいて評価されています：
    * パリティチェックタスク：論理演算の学習能力を評価
    * 回帰タスク：連続値の予測精度を評価
    * 画像分類タスク：視覚的特徴の抽出と分類性能を検証
また、ニューロン数、ネットワークの深さ、学習率といったハイパーパラメータを系統的に変更しながら、ED法の性能を詳しく分析しています。


* 主な結果
    * 高い精度を達成：全タスクで一貫して高い精度を示し、従来のバックプロパゲーション（BP）と同等の性能を発揮
    * ハイパーパラメータの影響：学習率、ネットワークの深さなどが収束速度・学習効率に大きく影響することを確認
    * 内部表現の分析：ネットワーク内部を可視化した結果、BPと同様に意味のある特徴抽出が行われていることが示された

## 最後に
最近、arXivではPDFだけでなくHTML形式でも論文を公開しており、ブラウザ上での翻訳がしやすく非常に助かっています。
例：https://arxiv.org/html/2504.14814v2

昨年4月頃からQiitaではED法が盛り上がりましたが、2か月ほどでそのブームは落ち着いてしまいました。そんな中、こうして論文という形で世界に向けて公開してくれる方がいることに感動しました。

これを機に、さまざまな研究者がED法について再び注目し、研究が進むことを願っています。
あ、私には無理ですが。
Windowsバッチで一定期間の更新していないフォルダ、ファイルを削除する

# 1. はじめに
* Windowsのバッチファイルで不要なフォルダ、ファイルを削除したい
* 一定期間更新していないフォルダ、ファイルを対象にしたい

# 2. 開発環境
* Windows 11

# 3. forfilesコマンド

https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/forfiles

## 3.1. ファイル削除
* 指定したフォルダ内で、更新日付が14日以上経過したファイルを削除する（サブディレクトリ内を含む）
```forfiles /P "C:\hogehoge" /S /M *.* /C "cmd /c if @isdir==FALSE del @path" /D -14```

## 3.2. フォルダ削除
* 指定したフォルダ内で、更新日付が14日以上経過したフォルダを削除する（サブディレクトリ内を含む）
```forfiles /P "C:\hogehoge" /S /C "cmd /c if @isdir==TRUE rmdir /q @path" 2>&1 /D -14```

## 3.3. ヘルプ
```bat:
forfiles /?

FORFILES [/P パス名] [/M 検索マスク] [/S]
         [/C コマンド] [/D [+ | -] {yyyy/MM/dd | dd}]

説明:
    ファイル (または、ファイルのセット) を選んで、そのファイル上のコマンドを実行します。これはバッチ ジョブの使用に便利です。

パラメーター一覧:
    /P    パス名        検索を開始するパスを示します。既定のフォルダーは現在実行中のディレクトリ (.) です。

    /M    検索マスク    検索マスクによってファイルを検索します。既定の検索マスクは '*' です。

    /S                  サブディレクトリに対しても処理を行うように forfiles に指示します (例: "DIR /S")。

    /C    コマンド      各ファイルの実行するコマンドを示します。コマンドの文字列は二重引用符で囲んでください。

                        既定のコマンドは "cmd /c echo @file" です。

                        次の変数をコマンドの文字列に使用することができます:
                        @file    - フィルの名前を返します。
                        @fname   - 拡張子なしのファイル名を返します。
                        @ext     - ファイルの拡張子だけを返します。
                        @path    - ファイルの完全なパスを返します。
                        @relpath - ファイルの相対パスを返します。
                        @isdir   - ファイルの種類がディレクトリの場合は "TRUE"を、ファイルの場合は"FALSE" を返します。
                        @fsize   - ファイルのサイズをバイトで返します。
                        @fdate   - ファイルの最終更新日を返します。
                        @ftime   - ファイルの最終更新時刻を返します。

                        コマンド ラインに特殊文字を使用する場合は、文字を 16 進数コードで 0xHH 形式で (例:タブは 0x09) 指定してください。
                        CMD.EXE の内部コマンドの前には "cmd /c" が必要です。

    /D    日付     最終更新日が指定された日かもしくはそれ以降 (+)、または指定された日またはそれ以前 (-) であるファイルを "yyyy/MM/dd" 形式を使って選択します。
                        または、最終更新日が現在の日にちより "dd" 日あと、もしくは "dd" 日前であるファイルを選択します。
                        有効な "dd"値は 0 から 32768 の間です。
                        指定がない場合は、"+" が既定で使用されます。
    /?                  ヘルプまたは使用法を表示します。

例:
    FORFILES /?
    FORFILES
    FORFILES /P C:\WINDOWS /S /M DNS*.*
    FORFILES /S /M *.txt /C "cmd /c type @file | more"
    FORFILES /P C:\ /S /M *.bat
    FORFILES /D -30 /M *.exe
             /C "cmd /c echo @path 0x09 was changed 30 days ago"
    FORFILES /D 2001/01/01
             /C "cmd /c echo @fname is new since Jan 1st 2001"
    FORFILES /D +2025/5/15 /C "cmd /c echo @fname is new today"
    FORFILES /M *.exe /D +1
    FORFILES /S /M *.doc /C "cmd /c echo @fsize"
    FORFILES /M *.txt /C "cmd /c if @isdir==FALSE notepad.exe @file"
```
# 4. サンプルプログラム
```bat:
@echo off

rem 対象パス名
set PATH=C:\hogehoge

rem 日付
set DAYS=-14

rem フォルダ内フォルダ、ファイル削除
forfiles /P "%PATH%" /S /M *.* /C "cmd /c if @isdir==FALSE del @path" /D %DAYS%
forfiles /P "%PATH%" /S /C "cmd /c if @isdir==TRUE rmdir /q @path" 2>&1 /D %DAYS%

rem 処理終了
exit
```

# 5. 参考文献

https://qiita.com/gitya107/items/a11deb3d83d8d624175c

https://qiita.com/meme_mumu/items/6a503015f0e9dfd91f66
【Mac】Spotlightのインデックス作成を無効化する方法


## 無効化

以下のコマンドを実行するとSpotlightのインデックス作成を無効化できます。

```terminal
sudo mdutil -a -i off
```

次のように無効化できたか確認できます。

```terminal
$ sudo mdutil -a -s
/:
        Indexing disabled.
/System/Volumes/Data:
        Indexing disabled.
/System/Volumes/Preboot:
        Indexing disabled.
```

## 有効化

再度有効化するには以下のコマンドを実行します。

```terminal
sudo mdutil -a -i on
```

```terminal
$ sudo mdutil -a -s
Password:
/:
        Indexing enabled.
/System/Volumes/Data:
        Indexing enabled.
/System/Volumes/Preboot:
        Indexing enabled.
```
🛒ECサイトのカート〜注文処理の基本設計と実装メモ



---

````markdown
# 🛒ECサイトのカート〜注文処理の基本設計と実装メモ（React + Redux + Spring）

こんにちは。今回はショッピングカート機能の実装を通して学んだことを整理してみました。

---

## ✅ カートに小計（subtotal）カラムが存在しない理由

- カート情報は一時的な保存に過ぎないため、小計はDBには保存しない。
- 小計は「商品価格 × 数量」でその都度**計算**。
- 永続的に小計を保存するのは**注文アイテム（OrderItem）**のみ。

---

## ✅ 注文オブジェクトが生成されるタイミング

- ユーザーが「注文確定」または「決済完了」した時点で、  
  `Order`とそれに紐づく`OrderItem`が生成される。
- `OrderItem`には**当時の価格・数量・小計**を保存し、価格変更の影響を受けないようにする。

---

## ✅ 小計の扱い（フロント/バックエンド）

| 処理内容             | 方法                         | 備考 |
|----------------------|------------------------------|------|
| 小計の表示           | Reduxなどフロント状態で保持 | 表示用のみなら可 |
| 正確な金額計算（注文） | **バックエンドで再計算**       | 不正防止・整合性維持のため必須 |

---

## ✅ カート画面での操作設計（＋ / − / 削除）

### ① 即時APIリクエスト方式

```ts
// 例: 数量増加
fetch(`/api/cart/${productId}`, {
  method: 'PUT',
  body: JSON.stringify({ quantity: newQuantity }),
});
````

* 操作するたびにサーバーと同期
* 一貫性が高いが通信量が増える

### ② Reduxで保持し、まとめて送信

* フロントのみで状態管理し、「注文確定」時にまとめてPOST
* UXは良いが、サーバーとの状態ズレに注意

### ③ ハイブリッド方式（推奨）

* 数量変更は**ディバウンス（一定時間入力が止まったら送信）**
* 削除ボタンは即時送信
* 多くの実務プロジェクトで採用されている手法

---

## ✅ 実装のポイントまとめ

* 小計は基本的に**フロントで計算表示のみ**
* 決済や注文登録の時には**必ずバックエンドで検証・再計算**
* UIの応答性とデータの正確性の**バランスが重要**

---

## 🧰 使用技術スタック

* フロント：React + Redux Toolkit
* バックエンド：Spring Boot + JPA
* データベース：PostgreSQL

---

## ✍️ 最後に

今回の実装を通じて、「**何をどこで確定するか**」「**フロントとバックエンドの責任分離**」の重要性を改めて感じました。

今後は決済APIや注文履歴の作成など、次のステップにも取り組んでいきたいと思います。

---
AbstractController::DoubleRenderError


## 🚨 エラー内容
```rb
Render and/or redirect were called multiple times in this action. 
Please note that you may only call render OR redirect, and at most once per action. 
Also note that neither redirect nor render terminate execution of the action, 
so if you want to exit an action after redirecting, 
you need to do something like "redirect_to(...); return". 
(AbstractController::DoubleRenderError)
```

---


## 🔍 概要
以下のようなコードを書いたところ、AbstractController::DoubleRenderError が発生しました。

```rb
class ApiController < ApplicationController
  before_action :verify_hmac

  def update
    # 実際の処理
  end

  private

  def verify_hmac
    check_hmac_timestamp
    # HMAC 検証処理…
    return if signature_not_match

    render json: { error: 'Invalid HMAC signature' }, status: :unauthorized
  end

  def check_hmac_timestamp
    timestamp = request.headers['X-HMAC-Timestamp']

    begin
      Time.iso8601(timestamp)
    rescue ArgumentError
      render json: { error: 'Invalid timestamp format' }, status: :bad_request
      return
    end
  end
end
```

---

## ⚠️ 問題の原因
上記のように verify_hmac を before_action に指定していますが、その中で呼び出している check_hmac_timestamp の中でも render を実行しています。

Rails では before_action で render または redirect_to を呼び出すと、それ以降のアクション（updateなど）はスキップされますが、メソッドチェーンの途中で render を呼んでも処理は中断されないため、そのまま verify_hmac に戻り、さらに render が呼ばれてしまいます。

つまり、同じリクエスト内で複数回 render を実行してしまうことにより DoubleRenderError が発生しているというわけです。

---

## ✅ 対策
### ✔ 対策1：両メソッドを before_action に分けて定義する
```rb
class ApiController < ApplicationController
  before_action :check_hmac_timestamp
  before_action :verify_hmac

  def update
    # アクション処理
  end

  private

  def verify_hmac
    return if signature_valid?

    render json: { error: 'Invalid HMAC signature' }, status: :unauthorized
  end

  def check_hmac_timestamp
    timestamp = request.headers['X-HMAC-Timestamp']

    begin
      Time.iso8601(timestamp)
    rescue ArgumentError
      render json: { error: 'Invalid timestamp format' }, status: :bad_request
    end
  end
end
```

補足：before_action は定義された順に実行されるため、順番にも注意してください。

### ✔ 対策2：check_hmac_timestamp では render せず、呼び出し元で処理する
```rb
def verify_hmac
  unless valid_timestamp?
    render json: { error: 'Invalid timestamp format' }, status: :bad_request
    return
  end

  unless signature_valid?
    render json: { error: 'Invalid HMAC signature' }, status: :unauthorized
    return
  end
end

def valid_timestamp?
  timestamp = request.headers['X-HMAC-Timestamp']
  Time.iso8601(timestamp)
  true
rescue ArgumentError
  false
end
```
【React】HTML上でmapを使うときにはkey属性を使おう！

## 参考サイト様
公式
・https://ja.react.dev/learn/rendering-lists

参考にさせていただいたサイト様
・https://watasuke.net/blog/article/react-component-include-key/


## アンチパターンなコード
次のようなコードがあります。

```jsx
{testlist.map((dataid) => (
        <div>
            <p>{dataid[0]}</p>
            <p>{dataid[1]}</p>
        </div>
    ))}
</div>
```

これは、testlistという配列や辞書(イテレーター)をmapで取り出して動的に同じようなhtmlを生成しています。
divタグがイテレーションの数だけ作られるわけですが、testlist内部の値が変更された場合、DOM側からはその値に対応するdivタグを一意に判断する方法がありません。
そのため、再レンダリングする場合には全体を探索して変更する必要があるのでレンダリング曽速度が遅くなる場合があります。


## ベストプラクティス
<div>タグにkeyを指定するのがベストプラクティスとなります。
ただし、keyはmapの値に対応する『ユニーク』な値である必要があります。

```jsx
{testlist.map((dataid) => (
        <div key={`${dataid[0]}-${dataid[1]}`}>
            <p>{dataid[0]}</p>
            <p>{dataid[1]}</p>
        </div>
    ))}
```

dataid[0],dataid[1]の組み合わせは一意であるとします。
上のようにdivタグに重複しないkeyを付与することでtestlistの値が変わった場合、変わった箇所に対応するdivタグに一発で辿り着けます。

DOM側はこのkeyをトレースしてくれるので変更箇所のみを再レンダリングするという最適化を行ってくれる訳です。


## 同じkeyを指定してしまった場合...

同じkeyを指定している場合は開発者ツールで下記のようなエラーが表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/99c9f919-cd43-471e-81a0-0d8ca4d55cd7.png)

このエラーが生じた場合はkey属性を見直すようにしましょう

:::note warn
体験談になりますが、このエラーは絶対に放置しない方がいいです。
:::
【React初心者メモ】レスポンシブプレフィックス

レスポンシブプレフィックスとは、「特定の画面サイズ以上のときにだけ適用するスタイル」を指定するために、クラス名の前につける接頭辞（prefix）のこと

## プレフィックス一覧
| ブレイクポイント | 最小幅（px) | 用途のイメージ |
| ---- | ---- | ---- |
| sm | 640px | スマホの大きい画面〜タブレット |
| md | 768px | タブレット〜小型PC |
| lg | 1024px | デスクトップPC |
| xl | 1280px | 大型ディスプレイ |
| 2xl | 1536px | 超大型ディスプレイ |
```
<div class="bg-red-500 md:bg-blue-500">
  <!-- 画面幅が768px未満なら赤背景、768px以上なら青背景 -->
  レスポンシブカラー切り替え
</div>
```

## カスタマイズ
標準のブレイクポイント（sm, md, lg, xl, 2xl）よりもっと細かく分けたい場合は、Tailwindの設定ファイル（tailwind.config.js）をカスタマイズします。
```
module.exports = {
  theme: {
    extend: {
      screens: {
        'xs': '480px',   // 追加の小さいブレイクポイント
        'sm': '640px',
        'md': '768px',
        'lg': '1024px',
        'xl': '1280px',
        '2xl': '1536px',
        // さらに細かくしたいなら自由に追加可能
        '3xl': '1800px',
      },
    },
  },
}
```
Geminiで画面UIをDrawioで作れるか試してみた

# Geminiで画面UIをDrawioで作れるか試してみた

## 1. はじめに

Geminiに、Drawioで画面UIを描かせてみた。

先日、Figma Configありましたね。Figma Makeやばいなと思いました。
とはいえ、Figmaのライセンス費用はそれなりにします。普段はDrawio使うことが多いです。

別件で開発中のアプリケーションで、意外にもきれいなUI出してきたので、実験してみるかと思った次第です。
これをGeminiが作成したのはびっくりしました。ちなみに私はインフラ寄りの人間なので、デザインの能力はありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2015230/4c5e53fb-b19f-4b9a-8343-6efea5865110.png)


以下、比べて検証します。ときおり出力にCanvas使ってます。
- 画面要素を伝えていくスタイル
- Geminiとアプリの要件定義をしてからUI作っていくスタイル

※半分お遊びなので、多少の雑さ加減はは目をつぶってください。

## 2. 検証内容

### 検証1: 画面イメージからDrawio XMLを生成

ラフな画面イメージや既存のUIデザインのスクリーンショットから作らせる。
要件を決めていないわけではないが、何やりますというくらいにしか決まっていない。

[コード: 画面イメージからDrawio XMLを生成する際のGeminiとのやり取り](https://g.co/gemini/share/44ab5d0898d5)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2015230/27050f9d-30d0-4895-bf75-4d61a00b6ace.png)


### 検証2: 要件定義からUI設計、Drawio XMLを生成

アプリケーションの要件をGeminiに入力し、会話で要件定義をしていく。要件を大方決めきったら、さあUI行こうかというところである。設計しろという声はいったん置いておく。これは実験なんで。

[コード: 要件定義からUI設計を行う際のGeminiとのやり取り](https://g.co/gemini/share/7f57c2b617e0)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2015230/8fe019a4-0022-46ea-97e0-04b72ed5e035.png)


## 3. 結果と考察

* 検証1はUIや指示を読み取っても、なかなか理解せず、変えましたと言っても、変わったんだか変わっていないんだかよくわからない状態が続いた。となると、正直、最初の一発以降は手でやってしまった方が早い。
* 検証2は、要件を整理することで、各画面の項目が整理されることが前提になってくるので、割と意図が伝わりやすい。
* 両者にとっての共通は、drawioが200行あたりまで行くとファイルフォーマットの崩れやすいのと、一回、変にこけると戻りづらい。
* とはいえ、検証2でテーブルを書いてくれたのは正直ポイントが高い。drawioのテーブルは意外と書くのが手間だったりする。

## 4. 所感

- 検証2にしてもこれが実用的かといわれると最初のたたき台になれるかどうかというところだろう。
- 凝りだすと、手でやった方がいいとかそうなるとは思われるが、最初何もない状態で書いていくのは骨が折れるので、スタートにはいいと思われる。
- 結果的にGeminiと要件定義を詰められるので、曖昧な構想のまま進めるよりも内容が詰まっているのも大きいかもしれない。
- Figma Makeも来ているが、そんな金あるかというところが大半なので、drawioをGeminiに書いてもらうのは意外とありなのではないか。

### おまけ
- Figma Makeの威力を考えると、Figma Makeのプロンプト作らせた方が精度はよさそう。
- Drawio挟まずに、さっさとHTML書かせた方がよかったかもしれない。
python dataclassesのfield(init=False)について

Pythonの比較的モダンな形でデータを定義できるdataclassesのコードを読んでいたときに、データ構造のフィールドを定義するのに、field(...)という形でクラスのメンバを定義していた。従来のpythonのクラスの書き方では、クラスのプロパティ変数の初期化に`__init__`を明示的に読んでいた。これにより、回りくどくはあるが、プロパティ変数は初期化される。一方で、dataclassesを利用したコードでは、フィールドの定義で`field(init=False)`と書くことがある。これによって、このクラスをインスタンス化した時に、この`field(init=False)`で定義したプロパティは、アクセスしようとするとエラーになる。すなわち、そのプロパティが`__init__`のような処理が行われていないので、アクセスできない。

正直何をしたくてこれをやるのかわからない。おそらくデフォルト値を`field`で指定するのに関係あるのかもしれない。たとえば、次の記事では`field(init=False)`で定義したプロパティの値は、インスタンス化した後ほど設定している。

https://zenn.dev/enven/articles/8b80ff38461b4ff329aa

デフォルト値を field で設定するのとは異なるタイミングで初期化を行いたい場合がいつなのか、いまいち想像できない。今読んでいるとあるレポジトリのコードでも上記のようにプロパティを`field(init=False)`で定義しつつ、その後、`__post_init__`を用いて値を更新している。

たとえば、外部から少し遅れてやってくる、インスタンス生成時に間に合うかよくわからないデータは、とりあえず、`field(init=False)` で初期化させておけば、`__post_init__`で値の代入やバリデーション等をすることで、コードの箇所を即時の初期化の箇所と、時間差で初期化される部分とに意味的に分けられていいかもしれない。
HP pavilion aero 13-be2000シリーズのSSD換装

HP Pavilion Aero 13-be2000シリーズのSSDを換装したので、備忘録として手順をまとめておきます。

なぜ換装を行ったかというと、SSDが突然故障したからです。その顛末についても記録しておきます。

なお、以下の動画がとても参考になりました（ただし、背面カバーの外し方は動画だけだと少しわかりづらいかもしれません）。
https://www.youtube.com/watch?v=ZTtJCZHUgnY
## SSDの故障

ある日、PCを起動したところ、こんな画面が表示されました。

![IMG_2025-05-11-21-13-12-159.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4088793/ec473338-c9fa-47ed-95ba-09d1fbaf3190.jpeg)

びっくり！！
（※まだ購入から1年ちょっとしか経っていないのに…）

とりあえず放電してみましたが、効果なし。

次に、F2キーで起動する診断ツールからSSDのチェックを実行してみました。結果は以下の通りです。

![IMG_2025-05-11-22-07-34-253.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4088793/ec18926f-c008-470b-8ede-e2c851bb39ff.jpeg)

「NOT AVAILABLE」……？？？
嫌な予感がします。

ダメ元でPCを開けてSSDを抜き差ししてみましたが、結局状況は変わらず。
新しいSSDを購入して換装することにしました。
SSDの換装手順
### 準備したもの

    プラスドライバー（精密）

    ヘラ（もしくは開封ツール）

### 作業手順

滑り止めのゴムの下にネジがあるので、まずゴムを慎重にはがします。
ネジを外し、ヘラで背面カバーを外します。
    ※個体差があるかもしれませんが、下の画像の緑で塗ったあたりから浮かせるとスムーズでした。

![IMG_2025-05-15-22-14-16-319-EDIT.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4088793/47dce3a1-7f73-4c9d-89df-627d0970de28.jpeg)

全体を浮かせても、2箇所ほど引っかかっている部分がありました。
製品番号が書かれている側（ヒンジ側）に引っ張るようにして外しました。
    ※ここが一番苦労しました。

この後の作業は、先ほどのYouTube動画を参考にしました。
https://www.youtube.com/watch?v=ZTtJCZHUgnY

SSDを固定しているネジ1本を外し、SSDを斜め上に引き抜きます。

新しいSSDを挿入。

背面カバーを閉じる前にOSのインストールと初期セットアップを行い、無事動作を確認できました。

背面カバーを取り付け、滑り止めゴムを貼り直して作業完了。
    ※最後はなかなかハマらず、ちょっと力技になってしまいました。

## まとめ

手先が特別器用なわけではない自分でも、無事にSSDの換装ができました。
同じように困っている方の参考になれば幸いです。

SSDがもう壊れませんように……！
古の技術、KentWebのpostmail.cgiがsuEXECポリシー違反で弾かれた話

## はじめに
さくらのレンタルサーバーで KentWeb の `postmail.cgi` を使用していたフォームが、
すべての基本設定を満たしていたにもかかわらず、ある日突然 `suEXEC policy violation` によって停止しました。
結論としては KentWeb の `postmail.cgi` を辞めて WordPress + Contact Form 7 に切り替えて解決しましたが、
「**動いていたものが壊れ、しかも原因が見つからない**」という現象に関して、検索しても誰も言及していなかったため、
“検索に出ない技術的事故”として記録しておきます。

## 発生状況
- サーバー移管案件にて、KentWebの `postmail.cgi` を使用したフォームが存在
- 移管直後（2025年2月頃）は正常動作
- **約3か月後、送信時に** `err:` **とだけ表示されるように**
- さくらのサーバーエラーログに以下の記述が出力：

```pgsql
suEXEC policy violation: see suexec log for more details
```
これにより、フォームは完全に停止しました。

## 確認・検証したこと
KentWebのCGIでよくあるエラー原因について、以下すべて確認済み：
- ✅ CGIファイルのパーミッション：`755`
- ✅ ディレクトリのパーミッション：`705`
- ✅ 改行コード：`LF（Unix形式）`
- ✅ ファイルエンコーディング：`UTF-8 without BOM`
- ✅ FTP転送モード：`ASCII`
- ✅ Perlパス：`/usr/bin/perl`（さくら指定）

**これらをすべて満たした状態でも、突然動作しなくなった**のが本件のポイントです。

## 特徴的だった点
- フォームは3か月間正常に動作していた
- 構成変更・ファイル再アップロード等の操作は一切なし
- サーバー側の環境アップデートやPerl仕様変更の可能性があるが、**公開情報やリリースノートに該当するものは見つからず**

## 最終対応
- WordPress環境下だったため、Contact Form 7 によるフォームを新規構築
- バリデーション／送信確認／サンクスページも再設計
- KentWebのCGIは完全に撤去し、フォームは安定運用に復帰

## なぜ記事として残したか
KentWebのフォームCGIは、今なお多くの中小規模サイトで稼働しています。
にもかかわらず、「**突然 suEXEC で弾かれた**」という記録はネット上に存在しませんでした。
- 設定をすべてクリアしていたにも関わらず、ある日突然動かなくなる
- ログには「suEXEC policy violation」だけ、フォーム画面には `err:` のみ

**何を調べても該当情報が出てこないストレス**
こうした 「**再現性のない技術的事故**」 を経験する人が今後も現れると考え、この記事を残しています。

## 結論
KentWebのCGIが「さくらのレンタルサーバー」で突然停止した場合、
「どうせパーミッションでしょ？」「BOM付きでしょ？」といったよくある対処をすべて行っても改善しないなら、
- サーバー側の自動仕様変更（suEXEC関連）
- 公開されていない仕様制限

を疑い、**KentWebからの脱却を検討するタイミング**かもしれません。

## 余談
正直、最初から Contact Form 7 で作った方が早かったです。
KentWebのフォームは一周回ってノスタルジーを感じますが、
**今の時代のフォームに求められるのは**「**管理画面で保守できること**」です。

KentWebが悪いのではなく、時代が変わったのだと思います。
pygame 音と画像付きタイマー

# hogehoge

```php:ruby
import pygame

pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("かわいい犬")
clock = pygame.time.Clock()

# 音読み込み
meow_sound = pygame.mixer.Sound("meow.wav")  # 音ファイルを同じフォルダに

# 画像読み込み
cat_img = pygame.image.load("cat.png")  # 小さい猫画像を同じフォルダに

running = True
while running:
    screen.fill((255, 228, 225))
    screen.blit(cat_img, (150, 150))
    pygame.display.flip()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            meow_sound.play()

    clock.tick(60)

pygame.quit()
```
[Go] strings: illegal use of non-zero Builder copied by value


## 事の発端
こんな雰囲気のコードを書いていました。
__※記事用に簡略化しています__
```go
package main

import (
	"fmt"
	"strings"
)

func main() {
	sb := strings.Builder{}
	sb.Grow(30)

	returnedStr := BuildString(sb)
	fmt.Println(returnedStr)
}


func BuildString(sb strings.Builder) string {
	strSlice := []string{"a", "s", "d", "f", "g", "h"}
	for _, s := range strSlice{
		sb.WriteString(s)
	}
	return sb.String()
}
```

するとこんなエラーが起きます。
```bash
$ go run main.go
panic: strings: illegal use of non-zero Builder copied by value
goroutine 1 [running]:
strings.(*Builder).copyCheck(...)
        C:/Program Files/Go/src/strings/builder.go:35
strings.(*Builder).WriteString(...)
        C:/Program Files/Go/src/strings/builder.go:107
main.BuildString(...)
        C:/Users/**/**/**/**/currentDir/main.go:20
main.main()
        C:/Users/**/**/**/**/currentDir/main.go:12 +0x2d0
exit status 2
```

## 解決策
これは`strings.Builder`を別関数の引数にして別関数で使おうとしたことにより、
`BuildString関数`の中の`WriteStringメソッド`の中で定義されている`copyCheck関数`でpanicが起きています。<br>
WriteStringメソッド
```go
func (b *Builder) WriteString(s string) (int, error) {
	b.copyCheck()
	b.buf = append(b.buf, s...)
	return len(s), nil
}
```
その中のcopyCheck関数<br>
```go
func (b *Builder) copyCheck() {
	if b.addr == nil {
		b.addr = (*Builder)(abi.NoEscape(unsafe.Pointer(b)))
	} else if b.addr != b {
		panic("strings: illegal use of non-zero Builder copied by value")
	}
}
```

この関数のelse if部分に引っかかったのでしょう。
`illegal use of non-zero Builder copied by value`と書かれており
翻訳すると「値によりコピーされたゼロでないBuilderの不正使用」とあります。<br>
なので別関数の引数にして別関数で使おうとしたためBuilderの値のみコピーされて別アドレスだったため起きたパニックということでしょうか。

つまり`strings.Builder`は定義した関数内で使わなくてはならないのかも。

下記のようにしたらエラーが消えました。
```go
package main

import (
	"fmt"
	"strings"
)

func main() {
	sb := strings.Builder{}
	sb.Grow(30)
	strSlice := []string{"a", "s", "d", "f", "g", "h"}

	for _, s := range strSlice{
		sb.WriteString(s)
	}

	str := sb.String()

	fmt.Println(str)
}
```

```bash
$ go run main.go
asdfgh
```
Bot対策の最前線：AWS Managed Rules × Bot Control の実践活用術




## ✨ はじめに

Webサービスを公開していると、**正規ユーザーのふりをした悪質なBot**に悩まされることがあります。
アクセス数が増えるほど、WAFの効果的なボット対策は重要性を増します。

本記事では、AWS WAF の **Managed Rules** と **Bot Control** を活用し、
**CloudFront配下での実戦的なBot対策**を解説します。

---

## ✅ 対象読者

- Botアクセスの急増に悩まされている方
- AWS WAFをすでに導入済みの方
- Bot Controlの仕組みや費用感がよく分からない方
- CloudFront + S3 など静的配信環境でBot対策をしたい方

---

## 📊 全体構成図

```
[Client] 
   ↓
[AWS WAF (Managed Rule + Bot Control)]
   ↓
[CloudFront]
   ↓
[S3 or ALB/API Gateway]
```

---

## 🔍 Bot Controlとは？

AWS Bot Controlは、WAFの追加機能として提供される **マネージドルールセット** です。

| 項目 | 内容 |
|------|------|
| 提供形式 | AWS Managed Rule |
| 費用 | WAFルール数＋BotControl特別料金（$10/WCUあたり） |
| 前提条件 | CloudFront専用（ALB/Regionalでは不可） |
| 判定方法 | ユーザーエージェント、IP、リクエストパターンなど |

### 種類：
- **Known Bot（Good Bot含む）**
- **Common Bot（SEOツールやクローラー等）**
- **Malicious Bot（明らかに悪質なアクセス）**

---

## ⚙️ Bot Control の設定手順

### 1. WAF WebACL作成（CloudFront用）

```bash
aws wafv2 create-web-acl \
  --name "my-cloudfront-waf" \
  --scope CLOUDFRONT \
  --default-action Block={} \
  ...
```

### 2. Bot Controlルールの追加

AWSマネージドルールから以下を選択:

- `AWS-AWSBotControlRuleSet`（`Bot Control for Targeted Bots`）

**おすすめ設定**：
- Known Bot → Allow
- Malicious Bot → Block
- Common Bot → CAPTCHA or Count

### 3. Rule Action の工夫

- 初期は`Count` モードで影響を確認
- 問題なければ `Block` へ切り替え

---

## 🛡️ Bot Controlだけでは防げないBotもいる

実務では、以下のようなBotがすり抜けるケースがあります:

- 最新のUser-Agentに偽装
- 正規IPレンジからのアクセス
- Refererを設定し擬似的に正規流入

### ⚡️ 対応策

- UA/Refererによる除外設定
- URIパターンに対するRate-basedルール
- JA3フィンガープリント分析

---

## 📊 WAFログ活用

Bot Controlの導入後は **WAFログ (JSON)をAthenaで解析**することで、以下のような分析が可能です:

- BlockされたBotの種類、頻度
- 特定パスへの異常アクセス
- Challenge経由の通過数、傾向

### Athenaクエリ例

```sql
SELECT terminatingRuleId, COUNT(*) as cnt
FROM waf_logs
WHERE action = 'BLOCK'
GROUP BY terminatingRuleId
ORDER BY cnt DESC
```

---

## 💰 Bot Controlの費用と削減テクニック

| 項目 | 価格の概要 |
|------|---------------------------|
| Bot Controlの利用料 | WebACLごとに約310/mo + WCU |
| WAFルール料金 | $1/Rule + $0.6/100万リクエスト |

### 削減ポイント

- Countモードで不要なルールを判定
- WAFのルール数を最小限に
- CloudFrontのキャッシュ強化でパストを矩折

---

## 📝 まとめ

- Bot ControlはCloudFront前接で効果的
- すべてのBotを防げるわけではないのでCustom Ruleの使い切りが重要
- WAFログとAthenaを連携し、効果を可視化
- 費用を意識しつつ、ルールを精選して運用すること

---

## 📌 付録

- [AWS Bot Control 公式ドキュメント](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-bot.html)
- [AWS WAF 費用表](https://aws.amazon.com/waf/pricing/)
- [AthenaでWAFログを解析する手順](https://docs.aws.amazon.com/ja_jp/athena/latest/ug/waf-logs.html)
📦 Odooベースで中小倉庫向けに構築したクラウドWMSの構成図と実装例を公開！

## 🎯 はじめに

こんにちは、ベトナム発のIT企業BinaryTechで物流システムを担当している元エンジニアです。
近年、日本の中小物流企業では「在庫の可視化」「作業効率の改善」「紙・Excelからの脱却」といった課題が多く見受けられます。

本記事では、私たちが **オープンソースERP「Odoo」** をベースに構築したクラウド型WMSの設計・実装について共有します。
主に以下のような課題を解決しました：

* 手書き帳票によるミス
* 在庫のロケーション管理が曖昧
* リアルタイムな在庫状況の把握が困難

---

## 🧩 システム構成図

以下が、弊社が構築したWMSソリューションの全体像です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4036006/ed0b47c4-4fbf-46c1-ade1-7ed37ddb3bc2.png)


### 構成要素：

* **Odoo Backend（Community Edition）**
* **PostgreSQL DB**
* **React.jsベースのカスタムUI**
* **倉庫内のラベル発行：Zebraプリンタ連携**
* **ハンディ端末：Android + WebViewアプリ**
* **API連携：受注データを外部ECから自動取得（Shopifyなど）**

---

## 🧪 技術選定理由

| 項目     | 選定技術              | 理由                    |
| ------ | ----------------- | --------------------- |
| ERP基盤  | Odoo              | オープンソースで柔軟。物流モジュールが充実 |
| UI/UX  | React.js          | 倉庫作業員でも使いやすい画面設計が可能   |
| DB     | PostgreSQL        | Odooデフォルト。高速＆安定       |
| モバイル端末 | Android + WebView | 安価で導入しやすく、現場に馴染みやすい   |

---

## 🛠️ 実装ポイントとコード例

### 在庫ロケーションのQRコード管理

```python
# Python (Odoo ORM)でQRコード生成モジュールを実装
from odoo import models, fields
import qrcode
import io
import base64

class StockLocation(models.Model):
    _inherit = 'stock.location'

    qr_image = fields.Binary("QR Code", compute='_generate_qr')

    def _generate_qr(self):
        for rec in self:
            qr = qrcode.make(f"Location: {rec.name}")
            buf = io.BytesIO()
            qr.save(buf, format='PNG')
            rec.qr_image = base64.b64encode(buf.getvalue())
```

---

### 📈 効果と成果

* 📉 **人的ミス：30％削減**
* 🕒 **棚卸作業時間：2日→6時間**
* 📦 **在庫精度：85％ → 98％**
* 🌐 **遠隔からの在庫状況確認が可能**

---

## 💡 まとめ

本記事では、中小規模倉庫に向けたクラウドWMS構築事例として、Odooベースの構成や実装ポイントをご紹介しました。

BinaryTechでは、Odooをベースにした「BWMS（Binary WMS）」というWMSパッケージも提供中です。
業務にフィットしたカスタマイズをご希望の企業様は、ぜひご相談ください！
【簡単】WSLでVSCodeのLive Serverが起動（ブラウザが自動で開く）しないときは？

ついにLinuxデビューしました！！！
しかし「Live Server」が自動的に開かれないという現象が...
解決までに1時間かかったのでここに記しておきます！
※Windowsを使用しています。

## 対処法
Ctrl + Shift + Pを押す→Preferences: Open User Settings (JSON)
に以下を記述すればいいだけです！

```bash
"liveServer.settings.NoBrowser": false,
"liveServer.settings.Host": "0.0.0.0",
"liveServer.settings.CustomBrowser": "chrome",
"liveServer.settings.AdvanceCustomBrowserCmdLine": "explorer.exe"
```
---
無事に開けましたでしょうか！？
読んでいただきありがとうございました！！！
#0136（2025/05/15）Pythonのeval()/exec()

# Pythonのeval()/exec()を使う前に知っておきたいこと

Pythonを使っていると、`eval()` や `exec()` という組込関数を見かけることがあります。これらは一見便利そうに見えますが、利用は非常に注意が必要な「切れ味の利刀」的な工具です。

---

## eval() と exec() は何が違うのか

| 特徴    | `eval()`            | `exec()`                              |
| ----- | ------------------- | ------------------------------------- |
| 📚 用途 | 式 (expression)を評価   | 文 (statement)を実行                      |
| ↺ 戻り値 | あり (expressionの結果)  | なし (None)                             |
| 例     | `eval("2 + 3")` → 5 | `exec("for i in range(3): print(i)")` |
| 注意    | 安易に使わない             | もっと注意                                 |


## eval() の利用例
-  ユーザーからの入力を式として評価したい場合などに便利
-  
```python
x = 10
eval("x + 5")  # 結果: 15
```


## exec() の利用例
- 複数行のコードや代入を実行したい場面で使われる

```python
exec("""
for i in range(3):
    print(i)
""")
# 結果:
# 0
# 1
# 2
```


## eval/exec が何故実装されたのか

1. **Pythonの言語設計思想**

   * Pythonは「動的」「封装性」を重視
   * 式をデータとして扱いたいニーズに対応

2. **REPL (対話式実行)システムの強化**

   * Pythonは初期からスクリプト言語を持つ
   * 文字列で受け取った式/文をその場で評価・実行するため

3. **テストツールやスクリプトの動作定義**

   * DSL、シミュレータ、Jupyterの内部など


## eval/exec を使うべきでない理由

| 原因        | 説明              |
| --------- | --------------- |
| セキュリティリスク | 任意のコードが実行される可能性 |
| デバッグが難しい  | 動的な評価のため追跡が困難   |
| 保守性が低い    | 文字列の中身を理解するのが困難 |


## 代替手段とそのサンプルコード

### 🔁 比較式の評価 → `operator` モジュール

```python
import operator

ops = {
    '>': operator.gt,
    '<': operator.lt,
    '==': operator.eq,
    '>=': operator.ge,
    '<=': operator.le,
    '!=': operator.ne,
}

value = 120
threshold = 100
operator_str = '>'

if ops[operator_str](value, threshold):
    print("条件を満たしました")
```


### 🔄 文字列をデータに変換 → `ast.literal_eval()`

```python
import ast

safe_data = ast.literal_eval("[1, 2, 3]")  # リストとして評価
print(safe_data)  # → [1, 2, 3]

# 危険なコードは評価されない（例：__import__('os') など）
```

### 🔁 動的な切り替え → 関数/クラス/ディクショナリで対応

```python
def process_add(x, y):
    return x + y

def process_sub(x, y):
    return x - y

operations = {
    'add': process_add,
    'sub': process_sub,
}

op_name = 'add'
result = operations[op_name](5, 3)  # → 8
print(result)
```

## おわりに: "力を与えるが責任も負わせる"

`eval()` や `exec()` は Python の「力」の表現です。しかし、正しく使われないなら、同時に「剣」にもなります。

何故あるのか、どんな場合なら許されるのかを理解した上で、避けられるなら代替手段を選んでいきましょう。
新人研修用に作ったGit資料を公開してみる

先日、社内研修用にGitの基礎を学ぶための資料を作成しました☝️
せっかくなのでどこかの誰かの役に立てば良いかなと思い、ここに残しておきます！


# Gitとは？
Gitは、**プログラムや文章などのファイルの「変更履歴」を記録・管理する**ためのツールのこと。

システム開発においては複数人が同時に同じソースを触るため、各々が好きに変更を加えていけば混乱を招くことになる。
誰がいつどんな変更を加えたのかを記録して、膨大なソースを効率よく管理する。
	
チームとしてのメリットだけではなく、個人作業においてもメリットはある。

例えば、実装中に「やっぱり前の状態に戻したい」と思った場合に、Gitを使って記録を残しておけば、簡単に過去の状態に戻すことができる。
　
# 全体のイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/873b8537-de2d-4565-8c73-54deee0c0f8a.png)

## 関連用語
### リポジトリ
ファイルやディレクトリの状態を記録する場所。
リポジトリの置き場所によって2種類のリポジトリが存在する。

#### ・ リモートリポジトリ
専用のサーバに配置して複数人で共有するためのリポジトリのこと。
GitHubやGitLabに置かれているリポジトリはこっち。

#### ・ ローカルリポジトリ
ユーザ一人ひとりが利用するために、自分の手元のマシン上に配置するリポジトリのこと。

### クローン
リモートリポジトリ（GitHubなど）のプロジェクト全体をローカル環境に完全コピーすること。
リポジトリの全ファイル・コミット履歴・ブランチ情報を取得し、独立した開発環境が構築できる。

### プル
リモートリポジトリの最新の状況をローカルリポジトリに反映させること。
クローンは環境構築の最初に実施するのに対して、作業開始後にリモートリポジトリの最新状態を取得したい場合はプルを使う。

### コミット
ファイルやディレクトリの追加・変更を記録すること
リポジトリに記録するためにはコミットが必要
→ 前回コミット時との差分が記録される。

### スタッシュ
ファイルの変更内容を一時的に記録しておく領域
→ ワークツリーとインデックス内でまだコミットされていない変更を一時的に退避させることができる

コミットしていない内容が残ったまま他ブランチへのチェックアウトを行うと、ファイルの変更内容は移動先のブランチに移動してしまう。
そんなときに変更をスタッシュしておけば、後で戻せるようになる。

 # ブランチ編
ブランチとは、Gitで**作業の履歴（バージョン管理）を「枝分かれ」させて管理できる機能**のこと。

たとえば、木の幹から枝が分かれるように、プロジェクトのメインの履歴から新しい枝（ブランチ）を作り、そのブランチ上で自由に作業ができる。

運用の仕方等は以下をリンクがすごく参考になります！

https://backlog.com/ja/git-tutorial/stepup/01/


## ブランチのメリット
• **別ブランチに影響を与えずに作業できる**
ブランチを分けておけば失敗しても他のブランチの履歴には影響しない。

• **複数人や複数の作業が同時に進められる**
それぞれが自分のブランチで作業できるので、他の人の作業とぶつかりにくい。

• **問題が起きても切り分けやすい**
どのブランチで何をしたか履歴が分かれているので、原因調査や修正がしやすくなる。

## 運用イメージ
メインブランチにある機能を追加したいケース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/fa6bbf94-11f3-4ee6-af38-c7b59e24fdcf.png)


## 関連用語 
### チェックアウト
作業しているブランチを切り替える操作。
→移動先のブランチ内の最後のコミット内容がワークツリーに展開される。

### マージ
ブランチを別ブランチに統合すること。

### リベース
コミット履歴を作り直して、ログをきれいに整理すること。
ブランチの変更履歴を、別のブランチの先頭に付け替えるイメージ。


## リベースとマージの違い
一言で言うと
· mergeは「履歴をそのまま統合」
· rebaseは「履歴を並び替えて一本化」

### マージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/b963cb0f-964d-4454-8c72-dce55f72a56c.png)

### リベース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/1ad3b8f3-5888-4c6c-a1c9-c6b3f47b173c.png)

### 比較
| 項目 | マージ | リベース |
|:-:|:-:|:-:|
|操作内容|2つのブランチの変更を統合してマージコミットを作成|あるブランチの履歴を他のブランチの先頭に並び替える|
|履歴の見え方|履歴が分岐・合流してマージコミットが残る|履歴が一直線に整理され、分岐が見えなくなる|
|メリット|変更の履歴がわかりやすい。履歴がそのまま残る|履歴が綺麗で見通しやすい。無駄なマージコミットが増えない|
|デメリット|履歴が複雑になりやすい|履歴を書き換えるため、使い方に注意が必要|
|使い分けの例|チーム開発で履歴を明確に残したいとき|個人作業や履歴を残したいとき|

※　使い方を間違えなければチーム開発でもリベースは有効


### 参考資料
https://www.atlassian.com/ja/git/tutorials/merging-vs-rebasing
Firebase Studioを使ってみた


# 経緯
普段iOSのアプリを開発しているが、ちょっと興味があったので、フロントエンドの開発をやってみた。最近、Firebase Studioという名前に変わったというニュースを見かけ、少し話題になっていたので試してみることにしました。

## 開発したもの
ReactとTypeScriptを使ってToDoアプリを作成しました。

## メリット
- 初学者には優しい
  - 環境構築がほぼいらない：従来のReact開発ではNode.jsのインストールやnpmの設定、webpack等のビルドツールの設定が必要でしたが、Firebase Studioではブラウザやローカルアプリで完結
  - 開発したいものを選択するだけで環境構築が完了：今回の場合は「ウェブフロントエンド」を選択するだけで、React+TypeScriptの環境が自動的に構築され、すぐに開発に取り掛かれた
  - 他の設定も不要：デプロイやホスティングの設定も簡略化されている
- 無料でエージェントコーディングができる：AIアシスタント（Gemini）が組み込まれており、コード生成や問題解決をその場で行える

## デメリット
- レスポンスが悪い：特に大きなプロジェクトや複雑な操作を行うと、画面の切り替えやプレビューの更新に時間がかかる
- 付属のジェミニが若干使いづらい
- 使いづらい理由は生成してもしたときに勝手に文字がスクロールされるため、読んでる途中で勝手にスクロールし、ストレスが溜まる

## 結論
最初の勉強用には良いが、自分の気に入っているエージェントAIや本格的な開発には不向きだと感じた。特にフロントエンド開発の基本的な流れを学ぶ入門段階では効率的だが、細かいカスタマイズや大規模プロジェクトには従来の開発環境の方が適していると思われる。