OmniAICreator/Qiita-1.07M huggingface dataset:
🏢 リモートから出社へ。技術者としての出社ワークスペースを最適化する話

# はじめに

この記事（[💻孤独感ゼロ！エンジニアのための「リモートワーク環境×メンタルケア」実践術10選](https://qiita.com/mnoguchi/items/2cd6203ae0e55a973ba5)）を読んでくださった皆さん、ありがとうございました！ 反響があったことがとても嬉しく、今回の記事につながっています。

そして

「リモートワークが快適すぎてもう出社できない」
「通勤も会議室の移動もないから効率的！」

──そんな声がある一方で、
**「ふとした瞬間に孤独を感じる」「気づけば12時間以上PCの前に…」**
といった、**メンタル面の疲れや情報の断絶**を感じることもありました。

現在は転職を経て、**ほぼフル出社**の体制に切り替わり、チームをリードする**マネージャー**として働いています。

この記事では、以下をテーマにまとめました：

* 🏢 出社に移行して変化した日常と働き方
* 🧰 オフィスワークを快適にする工夫と環境構築
* 👥 マネジメント視点で見た出社の価値と課題

すべて実体験に基づく内容ですので、出社を見直している方やハイブリッド勤務に悩む方の参考になれば嬉しいです。

---

## 🔄 働き方の変化

| 📝 項目     | 💻 以前（リモート中心）     | 🏢 現在（出社中心）        |
| --------- | ----------------- | ------------------ |
| 勤務形態      | フルリモート（週1出社）      | 週4出社               |
| 使用PC      | 会社支給（MacBook Pro） | 同左                 |
| コミュニケーション | Slack＋Zoom中心      | 対面＋Slack補助         |
| 開発体制      | 個人でタスク管理          | スクラムチームでの開発        |
| マネジメント業務  | 最小限               | チームの1on1、レビュー、育成など |

リモートで感じていた“情報の取りこぼし”や“気軽な声かけのしづらさ”が、出社によってかなり解消されました。

---

## 🧰 オフィスの作業環境

### 🪑 デスクとモニター

* 🧭 固定席（幅120cm）+ 座り心地の良いチェア
* 🖥 Dell製 32インチモニター

### ⌨️ キーボード・マウス

* HHKB Professional HYBRID Type-S
* ロジクール M575（トラックボール）

### 🔌 周辺機器・快適化アイテム

* Anker製 USB-Cドック（LAN + HDMI + PD対応）
* 🎧 SONY WF-1000XM5（ノイズキャンセリング）＝実際使ってない
* 🌬 卓上ファン、加湿器
* 📱 MagSafe対応スマホスタンド

▶️ どれも「**仕事に集中できる、でも疲れにくい**」ことを第一に構成しています。

---

## 🧭 出社ならではのTipsとルーティン

### 🧍‍♂️ 移動を“リズム”に変える

* 通勤時間＝「今日のタスクを整理する時間」として活用
* 歩くことで軽く体を温め、デスク着席前に“脳の助走”がつく

### 🗣 会話から生まれるアイデアキャッチ

* デスク間の何気ない立ち話から課題が浮き彫りになることも
* 1on1以外にも「ちょっと声をかけてみる」が価値を生む

### 🧾 ホワイトボード活用で“思考の棚卸し”

* チームの今週の目標やふりかえりを物理ボードに共有
* スクラムボードと併用で「対面と可視化」を両立

### ☕ 雑談スペースは“気持ちの緩衝材”

* コーヒーマシン前での小話で緊張がほぐれる
* 誰かの悩みが軽くなるきっかけにも

---

## 🕘 出社ルーティンと心がけ

### 🌄 朝の立ち上がり

* ☕ コーヒーと軽い雑談で緩やかにスタート
* 📣 朝会でタスクと状況の同期

### 🕛 昼の過ごし方

* 🍱 昼食はチームメンバーと外へ（社外の話や趣味トークも）
* 🎧 ポッドキャスト or 技術書でインプットタイム（15分だけ）

### 🌇 夕方の締め

* 📝 Notionで1日ふりかえり記録
* 💬 Slackでの軽い声かけ・DMチェック
* 🧠 気づいたことは翌日アクションとして明文化

---

## 👥 マネジメント視点で感じた出社の価値

| 観点    | メリット                        |
| ----- | --------------------------- |
| 情報共有  | 🎯 雑談・視線・雰囲気から細かな変化に気づける    |
| フォロー  | 👀 表情や態度で「詰まってるサイン」に気づきやすい  |
| チーム文化 | 🤝 朝会やホワイトボードで“空気”を共有できる    |
| 成長支援  | 📈 ちょっとした声かけで、成長のきっかけが作りやすい |

**Slackでは気づけなかった“ちょっとした変化”への対応が出社では自然にできる**ことが、マネージャーとしての一番の気づきでした。

---

## 🧩 まとめ

| カテゴリ   | 工夫ポイント                               |
| ------ | ------------------------------------ |
| 環境構築   | モニター・入力デバイス・快適アイテム                   |
| 開発体制   | GitHub Project |
| チーム連携  | 対面朝会、Notion活用、スクラム運営                 |
| マネジメント | 気づき・声かけ・心理的安全性づくり                    |

---

## 🧠 さいごに

出社にもリモートにも一長一短があります。大切なのは、**どちらでも「自分とチームが健やかに働ける状態」を作ること**だと感じています。

この記事が、これからの出社・ハイブリッド勤務を見直すきっかけや、環境改善のヒントになれば幸いです。

> 💬「私の出社Tips」などコメントでぜひ教えてください！
新規githubアカウントへの接続切り替え方法

# はじめに
すでにgithubアカウントを利用しているが、新規で別アカウントを利用したい。という場合があり、調べながらやったのでついでに投稿しておきます。
※chatgptの出力を元に書きました

- windowは一部コマンドが異なります。
- 備忘録兼だれかのためになれば。というありきたりな理由で書いてます
- 間違いがあれば優しく教えてください。あまり強い言葉を使うなよ。怖いです。


## ステップ1：Gitのユーザー名・メールを新アカウントに更新
### グローバル設定を上書き（全リポジトリ対象）
```:bash
git config --global user.name "新しいGitHubユーザー名"
git config --global user.email "新しいGitHubのメールアドレス"
```
または、個別のリポジトリだけ変更したい場合はそのリポジトリのディレクトリ内で：
```:bash
git config user.name "新しいGitHubユーザー名"
git config user.email "新しいGitHubのメールアドレス"
```


## ステップ2：新しいSSHキーを作成（または既存のものを使い分け）
```:bash
ssh-keygen -t ed25519 -C "newaccount@example.com" -f ~/.ssh/id_ed25519_newgithub
```
上記コマンド実行後に入力を求めらますが、基本的に全て空入力ままEnterでOKです。
これは`SSH秘密鍵にパスフレーズ（＝鍵を使う際のパスワード）を設定するか？`という確認です。
もしセキュリティ面をより強固なものにしたい場合は以下の通り設定します。
1. 任意のパスワードを入力（画面には表示されません）
2. 2回聞かれるので、同じ文字列を再入力

実行後、以下の2つのファイルが作成されます
```:bash
~/.ssh/id_ed25519_newgithub         ← 秘密鍵（絶対に漏らさない）
~/.ssh/id_ed25519_newgithub.pub     ← 公開鍵（GitHubに登録）
```
<details>
  <summary>確認方法</summary>
  
  ```:bash
  ls ~/.ssh/
  ```
  作成されるはずの2つのファイルが表示されてればOKです。
</details>

<details>
  <summary>:x:ssh-keygenコマンド実行時に`dquote`と表示され空文字Enterで進めない場合</summary>
  

`dquote`は実際には`Enter passphrase:`の文字化けか、ターミナルがプロンプトの表示を正しく出力していない可能性があります。
この場合でも、空のままEnterを2回で進めるはずです。
(筆者は何度Enter押しても再表示され続けましたが↓でできました。理由わかる方いれば教えてください。。)
  → `LANG=C`を`ssh-keygen`の前にスペースを挟んで追加して実行することで、英語出力にすることができます。
  ```:bash
  LANG=C ssh-keygen -t ed25519 -C "newaccount@example.com" -f ~/.ssh/id_ed25519_newgithub
  ```

</details>


## ステップ3：公開鍵をクリップボードにコピーする
``` bash
pbcopy < ~/.ssh/id_ed25519_newgithub.pub
```
pbcopyはコピーコマンドです。

## ステップ4：公開鍵をgithubに登録する
1. githubにサインインして右上のユーザアイコンをクリック
1. settingをクリック
1. SSH and GPG keysをクリック
1. new SSH keyをクリック
1. title :　自分がわかりやすい任意のkey名
   keytype : Authentication key
   key : ステップ3でコピーしたものをペースト
1. Add SSH keyをクリック

## ステップ5：configファイルでHost設定を記述する
### configファイルを開く
``` bash
vim ~/.ssh/config
```
vim以外のテキストエディタでももちろんOK
### configファイルを編集する
``` sshconfig
# 旧アカウント用
Host github-old                      ←ホスト名。github-も不要ですが、つけるのが一般的らしい
  HostName github.com                ←SSHの実際の接続先サーバ名。固定値
  User git                           ←githubの仕様で固定
  IdentityFile ~/.ssh/id_ed25519_old ←ローカルにあるSSH秘密鍵のパス。ステップ2で作成した秘密鍵に一致してればOK
  IdentitiesOnly yes                 ←IdentityFileで指定した鍵だけで認証させる

# 新アカウント用
Host github-new
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_newgithub
  IdentitiesOnly yes
```
## ステップ6：接続確認
``` bash
ssh -T git@github-new
```
以下のメッセージが表示されれば成功
``` bash
Hi 新しいユーザー名! You've successfully authenticated, but GitHub does not provide shell access.
```
## ステップ7：リモートURLを新アカウント用に変更
configをカスタムしてるので、接続情報を更新する。
```:bash
git remote set-url origin git@ホスト名:新ユーザー名/リポジトリ名.git
```

以上で新規アカウントへ接続できました。
## :bangbang:pushなどする場合は、ローカルの環境をよく確認してから実行してください。
調べながらの記事なので、もし本記事の影響で問題が起きても筆者は責任はおえません。
不確かさ評価



### ✅ 1. 基本方針：体積の計算と不確かさの伝播

$v = \frac{m}{\rho_0}$
不確かさ評価には \$u(m)\$ および \$u(\rho\_0)\$ の合成が必要。

---

### ✅ 2. 質量の不確かさ（Aタイプ評価）

標準偏差 \$s\$ をそのまま \$u(m)\$ とする：
$u(m) = s$

---

### ✅ 3. 密度の不確かさ（Bタイプ評価）

一様分布と仮定：
$u(\rho_0) = \frac{\Delta}{\sqrt{3}} = \frac{0.01}{\sqrt{3}}$

---

### ✅ 4. 合成不確かさ（伝播則）

$u^2(v) = \left( \frac{1}{\rho_0} \right)^2 u^2(m) + \left( \frac{-m}{\rho_0^2} \right)^2 u^2(\rho_0)$

---

### ✅ 5. 拡張不確かさの表記

$v \pm 2u(v)$
信頼水準95%相当の「拡張不確かさ」

---

### ✅ 6. 標準偏差と母集団

* 標準偏差 \$s\$：標本のばらつき
* 母標準偏差 \$\sigma\$：母集団のばらつき

---

### ✅ 7. 標準偏差の計算ステップ

* 平均： \$\bar{y} = \frac{1}{n}\sum y\_i\$
* 偏差平方和： \$S = \sum (y\_i - \bar{y})^2\$
* 分散： \$V = \frac{S}{n-1}\$
* 標準偏差： \$s = \sqrt{V}\$

---

### ✅ 8. 試料と母集団

| 試料             | 母集団              |
| -------------- | ---------------- |
| 平均：\$\bar{y}\$ | 母平均：\$\mu\$      |
| 標準偏差：\$s\$     | 母標準偏差：\$\sigma\$ |

---

### ✅ 9. 標準誤差

$\sigma_{\bar{y}} = \frac{\sigma}{\sqrt{n}}$
平均値のばらつきの尺度。

---

### ✅ 10. 確率分布

* 正規分布：
  $p(x) = \frac{1}{\sqrt{2\pi}\sigma} \exp\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)$
* 一様分布：
  $p(x) = \frac{1}{2\Delta}, \quad (\mu - \Delta \leq x \leq \mu + \Delta)$

---

### ✅ 11. サイコロ実験と中心極限定理

複数回平均を取ると正規分布に近づく。

---

### ✅ 18. バジェット表

| 要因             | 標準不確かさ \$u(x)\$ | 感度係数 \$c\_x\$ | 寄与度 \$c\_x u(x)\$   |
| -------------- | --------------- | ------------- | ------------------- |
| 質量 \$m\$       | 0.115 g         | 0.05 cm³/g    | 0.058 cm³           |
| 密度 \$\rho\_0\$ | 0.0058 g/cm³    | -25.0 cm³/g   | 0.144 cm³           |
| 合成不確かさ         | —               | —             | \$u\_c = 0.16\$ cm³ |

---

### ✅ 19. 不確かさの表記方法

* 合成不確かさ：\$m = 100.02147 \pm 0.00035\$ g
* 拡張不確かさ（\$k = 2\$）：\$m = (100.02147 \pm 0.00070)\$ g

---

### ✅ 20. 不確かさ vs 測定誤差

| 観点 | 不確かさ      | 測定誤差  |
| -- | --------- | ----- |
| 定義 | 測定に伴うばらつき | 真値との差 |
| 方法 | 統計/文献評価   | 実差計算  |

---

### ✅ 21. 不確かさ評価フロー

```mermaid
graph TD
A[Step 1: 数式モデル] --> B[Step 2: 不確かさ評価]
B --> C[Step 3: 合成計算]
C --> D[Step 4: 表記と報告]
```

---

### ✅ 22. 高度な評価式

(1) Aタイプ不確かさ（平均の）：
$u(\bar{m}) = \sqrt{\frac{1}{n(n-1)} \sum (m_i - \bar{m})^2}$

(2) 相関を含む合成：
$u_c^2(y) = \sum \left( \frac{\partial y}{\partial x_i} \right)^2 u^2(x_i) + \sum_{i \neq j} \left( \frac{\partial y}{\partial x_i} \right) \left( \frac{\partial y}{\partial x_j} \right) \cdot \text{cov}(x_i, x_j)$

(3) 相対不確かさ：
$\left( \frac{u(y)}{y} \right)^2 = \sum \left( p_i \cdot \frac{u(x_i)}{x_i} \right)^2$

(4) 包含係数： \$k = 1\$, \$1.96\$, \$2\$ など

---
npm run devできない。エラー: await import('source-map-support').then((r) => r.default.install())

# 概要
いつも通りReactアプリをVite環境で
```sh
$ npm run dev
```
で動かそうとしたら、エラーが出て動かない。nodeのバージョンが、なぜか古いものを指定されていたことが原因だった。バージョン変更などした覚えがないのに。以下、備忘録とします。

# 表示されたエラー
```sh
await import('source-map-support').then((r) => r.default.install())

SyntaxError: Unexpected reserved word
    at Loader.moduleStrategy (internal/modules/esm/translators.js:122:18)
    at async link (internal/modules/esm/module_job.js:42:21)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
```

# 現状
node_modulesとpackage-lock.jsonを削除しインストールし直す(`$ npm install`)などしたが、効果はなかった。nodeのバージョンを今一度確認することにした。
```sh
$ node -v
v14.5.0
```
Vite公式ドキュメントによると、「**ViteはNode.js 20.19+,22.12+ のバージョンが必要です**」とある。これでは動かない。

https://ja.vite.dev/guide/

stableにインストールされているnodeのバージョンを今一度確認した。
```sh
$ nvm ls
(略)
node -> stable (-> v22.15.1) (default)
```
デフォルトで指定されているため問題ないはずだが、今のプロジェクトではなぜかv14.5.0になっている。

# 解決策
プロジェクトで使うnodeのバージョンを、明示的に22.12+にする。
```sh
$ nvm use 22.15.1
Now using node v22.15.1 (npm v11.3.0)
```
```sh
$ node -v
v22.15.1
```
結果、無事に`$ npm run dev`が動いた！
なぜ急にnodeのバージョンが古いものを指定されていたのかは不明なので、ちょっと気持ち悪い。
Semantic KernelでGemini 2.5 Flashを試してみる

こんにちは。

テックリードのTerukiです。

Semantic Kernelでは、ずっとGPT4.1しか試していなかったのですがOpenAI以外のモデルもプレビューではあるものの、使わせることはできるので試してみます。

OpenAIのモデルを使ったものは以前書いた記事にあるのでもし良ければこちらも参照ください。

https://qiita.com/omt_teruki/items/4e091282ed6e25735f09

# 実装

まずはNuGetパッケージを追加します。

```
Microsoft.SemanticKernel.Connectors.Google
```

プレビュー版なのでVisual Studioではプレリリースを含めて検索しないと出てきません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/1535f5a8-5602-4a10-998a-1a428cd93dc4.png)

前回のコードをベースに変更してみます。

```cs
var kernelBuilder = Kernel.CreateBuilder()
    .AddGoogleAIGeminiChatCompletion(Configuration["Google:Gemini:ModelId"]!,
        Configuration["Google:Gemini:ApiKey"]!);
    
var kernel = kernelBuilder.Build();

// INotionServiceを解決するためにアプリのIServiceProviderを指定しておく
kernel.Plugins.AddFromType<NotionPlugin>(null, ServiceProvider);

var agent = new ChatCompletionAgent {
    Name = "Agent",
    Instructions = """
        質問への応答や回答を考えて返答してください。
        FAQはNotionに保存されています。
        """,
    InstructionsRole = AuthorRole.Assistant,
    Kernel = kernel,
    Arguments = new(new GeminiPromptExecutionSettings {
        FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(),
        ToolCallBehavior = GeminiToolCallBehavior.AutoInvokeKernelFunctions, // これがないとKernelFunctionが呼ばれない
    }),
};
```

APIキーはこちらから取得できます。

https://aistudio.google.com/apikey

モデルIDは今回は「gemini-2.5-flash-preview-05-20」を指定してみました。

GPTとは違ってToolCallBehaviorを指定しないとKernelFunctionが一切呼ばれなかったのに少しハマりました。

---

結構簡単に差し替えることができました。

モデルの精度がどうかはまだ確認できていないですが、すごいモデルが登場した時に簡単に乗り換えられるのは非常に良いですね。

もしくはモデルを切り替える機能を搭載しても面白そうです。

社内AIエージェント開発をひそひそと進めていますが、面白そうな機能があれば組み込んでいこうと思います。
MATLAB 競技テクニック紹介

[MATLAB EXPO 2025 Japan](https://www.matlabexpo.com/jp/2025.html)に参加しました．
そのイベント中に開催されたMATLABプログラミングコンテストに参加し，今年も優勝しました．
![250529155542790.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308259/14458a3e-5902-4bef-ae2e-8437e97d343d.jpeg)
（こちらは途中で撮った写真です．最終スコアの写真をちゃんと撮っていませんでした）

参考：[MATLABプログラミングコンテスト必勝法](https://qiita.com/tomtkg/items/0bedf0d4f6e53294eed0)

これを記念して，この記事ではMATLABの競技テクニックを3つ紹介します．

# 1. 行ベクトルと列ベクトルを利用しよう
MATLABは，線型代数学の行ベクトルと列ベクトルが標準で搭載されています．
* 行ベクトル：数を横に並べたもの．　$(1,2,3)$など．
`1:9` ⇒ $(1,2,\dots,9)$の行ベクトルが作成される．<br><br>

* 行ベクトル：数を縦に並べたもの．　$\left(~\begin{matrix}1\cr2\cr3\end{matrix}~\right)$など．
`(1:9)'` ⇒ $(1,2,\dots,9)^T$ ⇒ $\left(~\begin{matrix}1\cr2\cr\vdots\cr9\end{matrix}~\right)$の列ベクトルが作成される．

以上を踏まえると，以下の2問がスマートに解けます．

<b>問1: 自然数$n$が与えられる．$n\times n$の九九表（掛け算の表）を出力せよ．
　　表の左上は$1\times 1$の結果，表の右下は$n\times n$の結果とせよ．

<b>問2: 鉛筆は1本30円，消しゴムは1個50円，ノート1冊100円で売られている．
　　$x=($鉛筆の本数，消しゴムの数，ノートの数$)$ が入力として与えられた時，
　　その合計金額を求めよ．

# 2. 論理インデックスを利用しよう
MATLABは，logical配列を論理インデックスとして利用できます．
これにより，論理インデックスが1（true）の配列要素を取得できます．

前提条件：　　　　　　`x = 1:5`　⇒ `x = [1 2 3 4 5]`
logical配列の作成：　　`x > 2`　　⇒ `[0 0 1 1 1]`
論理インデックス利用：`x(x > 2)` ⇒ `[3 4 5]`

以上を踏まえると，以下の2問がスマートに解けます．

<b>問3: 整数の行列Aが与えられる．A内の正の値をすべて出力せよ．

<b>問4: 整数の行列Aが与えられる．A内で0を除いた値の合計を出力せよ．

# 3. 変換を活用しよう
MATLABは，`num2str`，`str2num` (`str2double`)で 数値 ⇔ 文字列 の変換ができます．
また，`'1234'-'0'` ⇒ `[1 2 3 4]`のように，文字列から0を引くことで，各文字が対応する数値のベクトルを得られます．（文字もASCIIコードとして扱われるため）

以上を踏まえると，以下の2問がスマートに解けます．

<b>問5: 6桁の自然数$x$が与えられる．各桁の和を出力せよ．

<b>問6: 6桁の自然数$x$が与えられる．$x$を並び替えて出来る最大の値を出力せよ．

# 4. 解答例
<b>問1: `(1:n)'*(1:n)`　
<b>問2: `[30 50 100]*x'`　
<b>問3: `A(A>0)`　
<b>問4: `sum(A(A~=0))`　
<b>問5: `sum(num2str(x)-'0')`　
<b>問6: `str2num(sort(num2str(x),'descend'))`，`str2num(flip(sort(num2str(x))))` など

# 終わりに
この記事では，MATLAB [Cody](https://jp.mathworks.com/matlabcentral/cody)とプログラミングコンテストで役に立つ競技テクニックを3つ紹介しました．

記事執筆時の自分は，ランク41，問題解答数1630，スコア20816，バッジ数58でした．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308259/fa144a8f-58c3-4b33-8aa5-d6d70a779f90.png)
[1年前](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F308259%2Ff344efc1-cd53-0c14-6f02-2f129b02d74f.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=fa61c94d1f2a0409519d1835200f0bf7)と比較して，かなり成長していますね．
この勢いで，まずは日本人1位を目指して頑張ります．
ObsidianでAIチャットが常駐！「Smart Composer」で壁打ち・要約・Markdown支援を一発完結させる方法

## 🔰 はじめに

Obsidianでメモや日報を書きながら、「この内容を要約してほしい」「もう少し丁寧に書き直したい」と思ったことはありませんか？

そんな願いを叶えてくれるのが、AIチャット機能をObsidianに直接組み込める神プラグイン  
👉 **「Smart Composer」** です。

この記事では、以下の内容を**ステップバイステップで解説**します。

- Smart Composerとは？
- 導入方法
- 初期設定（APIキーなど）
- チャットの呼び出し方
- 要約・壁打ちの使い方
- よくあるエラーと対処法

---

## 🤖 Smart Composerとは？

Smart Composerは、OpenAIのAPIを活用して、
Obsidian内で以下のようなことを**リアルタイムチャットで実行できる**プラグインです。

- ノートの要約・翻訳・書き換え
- 壁打ちチャット（GPTと会話しながら思考整理）
- Markdown対応でそのままノート化
- ChatGPTのような体験がObsidianで完結！

まさに「ノートを編集しながら、すぐ隣でAIと相談できる」環境を実現します。

---

## ⚙️ 導入手順（ステップバイステップ）

### ✅ Step 1. コミュニティプラグインを有効化

1. Obsidianを開く  
2. 左下の歯車（⚙） → 「コミュニティプラグイン」へ  
3. 「安全モードをオフ」にする  
4. 「コミュニティプラグインを閲覧」→ `Smart Composer` を検索  
5. 「Smart Composer by jmilldotdev」をインストール → 有効化

---

### ✅ Step 2. OpenAI APIキーを設定

Smart Composerは、OpenAI API（ChatGPTのバックエンド）を利用します。

#### 🔑 APIキーの取得手順

1. [https://platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys) にアクセス  
2. 「Create new secret key」で発行  
3. コピーしておく

#### 🔧 Smart Composer設定に貼り付け

1. Obsidian設定 → Smart Composer  
2. `API Key` に取得したキーをペースト  
3. 使用モデル（gpt-3.5-turbo など）を選択  
4. 保存して完了！

---

## 💬 チャットの使い方

### 📥 チャットを表示するには

`Cmd/Ctrl + P` → 「Smart Composer: Open chat」  
を選ぶと、右側にAIチャットペインが開きます。

---

### 💡 チャットでできること（おすすめプロンプト）

| やりたいこと | プロンプト例 |
|---------------|--------------|
| 要約したい     | `このノートを3行で要約して` |
| 書き直したい   | `この文章をもっとやさしく言い換えて` |
| 翻訳したい     | `このノートを英語に翻訳して` |
| 壁打ちしたい   | `この内容について、懸念点を指摘してもらえますか？` |
| Markdown整形 | `この文章を箇条書きにしてください` |

---

## 📁 フォルダ・ノートの指定方法

### ✅ 開いているノートを対象にする

```text
このノートを要約して
````

### ❗ フォルダを指定して一括要約は未対応

Smart Composerは現時点で、フォルダ単位の一括読み取りは**チャット上では非対応**です。
複数ファイルをまとめて処理したい場合は、**内容を貼り付けるか、Cursorなど別ツールとの併用がおすすめ**です。

---

## 🔁 インデックスの更新方法

### 📌 コマンド一覧（`Cmd + P` から実行）

| コマンド名                                             | 内容                 |
| ------------------------------------------------- | ------------------ |
| `Smart Composer: Open chat`                       | チャットペインを表示         |
| `Smart Composer: Rebuild entire vault index`      | 全ノートを再インデックス       |
| `Smart Composer: Update index for modified files` | 変更されたノートだけインデックス更新 |

---

## 🧩 よくあるエラーと対処法

| 現象                     | 対処法                                       |
| ---------------------- | ----------------------------------------- |
| 「ノートの内容を共有してください」と言われる | 該当ノートがインデックスされていない可能性 → `Update index`を実行 |
| フォルダ指定しても反応がない         | フォルダ読み取りは非対応。ファイルを列挙 or 1つに結合してから実行       |
| チャットが出てこない             | `Smart Composer: Open chat` → 📌ピンで固定     |

---

## ✨ おわりに：Smart Composerは“壁打ち相棒”

Smart Composerは、日々のメモや思考整理、ドキュメント作成において「ちょっと相談したい」を叶えてくれる**AIチャットプラグインの決定版**です。

完全にObsidian内で完結するため、

* 複数アプリを切り替える手間ゼロ
* 思考が途切れない
* チャットしながら編集もできる

という三拍子そろった効率化が可能になります。

---

## 📎 参考リンク

* [Smart Composer公式GitHub](https://github.com/jmilldotdev/smart-composer)
* [OpenAI APIキー取得](https://platform.openai.com/account/api-keys)

---

気に入った方はぜひいいねやブクマ、コメントお待ちしています！
Oracle Cloudで20GBの無料DBを手に入れよう【Terraform自動構築あり】



「無料で高性能なクラウドDBを試したい」  
そんなあなたにおすすめなのが、**Oracle CloudのAlways Free枠で使えるAutonomous Database（最大20GB）** です。

この記事では、以下の2つを紹介します：

1.  Oracle Cloudの無料DBの魅力
2.  Terraformでの自動構築手順（コード付き）

---

なぜOracle Cloudの無料DBがすごいのか？
--------------------------

Oracle Cloud（OCI）には「**Always Free枠**」という、**永年無料で使えるサービス群**があります。  
その中でも特に注目すべきなのが「**Autonomous Database**」。以下の特徴があります：

* 最大**2インスタンスまで無料**
* 各DBで**20GBまでのストレージ**
* 商用利用も可能！

クラウドでここまでできて本当に無料？と思うほど、学習用途やPoCにはぴったりです。


---

必要なもの
-----

事前に以下を準備しておきましょう：

* Oracle Cloudのアカウント（無料）
* OCI CLIの初期設定済み
* Terraform v1.0以上
* テナンシOCID、APIキーなどの設定済みのプロファイル

---

Terraformで無料DBを構築してみよう
----------------------

以下に、**TerraformでAlways FreeのAutonomous Databaseを構築するコード**を示します。

### 🔧 Oracle Autonomousを立てるTerraformコード


```tf
variable "autonomous_database_admin_password" {
    #in aws parameter store
}
variable "tenancy_ocid" {
    default = "ocid1.tenancy.oc1..aaaaaaaafqufbnckmkgbf6hpnwcdjttvmlngvoz3ft5gfoqw4ruxwrqaonsa"
}

variable "sysname" {
    default = "astral"
}

variable "environment" {
    default = "prod"
}


# compartment
resource "oci_identity_compartment" "main" {
    #Required
    compartment_id = "${var.tenancy_ocid}"
    description = "${var.sysname}-${var.environment}"
    name = "${var.sysname}-${var.environment}"
}

# autonomoud database (DWH)
resource "oci_database_autonomous_database" "main" {
    #Required
    admin_password = "${var.autonomous_database_admin_password}"
    compartment_id = "${oci_identity_compartment.main.id}"
    db_name = "DW"

    #Optional
    db_workload = "DW"
    display_name = "DW"
    is_free_tier = "true"
    #whitelisted_ips = ["${oci_core_vcn.test_vcn.id}"]
}
```


### 🛠️ Autonomous Database（Always Free枠で構築）



---

✅ デプロイ手順
--------

1.  Terraformの初期化：

- `terraform init`

1.  確認してから実行：

- `terraform plan`
- `terraform apply`

1.  数分で完了。OCIのコンソールからDBが確認できます！

---

よくある質問（FAQ）
-----------

### Q. 無料枠を超えたらどうなる？

> 自動で課金されることはありません。上限を超える操作（容量追加など）はできません。

### Q. 本番運用に使っていいの？

> Always Free枠はSLA非保証のため、**本番運用では推奨されません**。学習・検証用に使うのがベストです。


Oracle DBにたどり着くまで & 宣伝
---

私ごとで恐縮ですが、以下のサービスを作っております。
このサービスの鍵はネットワーク構造を格納するDBなのですが...

https://d2or2g1md9lrqv.cloudfront.net/dashboard.html

初期フェーズではDynamoDBを利用しておりました。
**ただDynamoDBを利用すればするほど痒いところに手が届かないことに気づき...! そんな悔しい思いをしていました**
(scanに時間がかかる。複雑なソートができない。部分一致検索も遅い。などなど)

そこで無料枠で利用できるDBはないか探していたところ、OracleDBを発見できたのです！


---

まとめ
---

Oracle CloudのAlways Free枠で提供されているAutonomous Databaseは、

* 強力な自動管理機能
* 商用と同等の機能
* 永年無料

という、これまでのクラウドDBの常識を変えるサービスです。Terraformを使えば、**一瞬で環境構築**ができるので、ぜひこの記事のコードを活用してみてください！

---

必要なら、記事をMarkdown形式やQiita投稿用に変換することもできます。ご希望があれば教えてください。
明日から新しい職場へ

明日からいよいよ新しい職場での挑戦が始まる。

「やってやろう」という強い気持ちと、「自分はどこまで通用するだろう？」というワクワクとドキドキが入り混じった感情。

ただ、ひとつ胸を張って言えるのは、2年の実務経験に加えて、この1年間でコンピュータサイエンスを徹底的に学び直し、これほど基礎力を磨いてきたエンジニアはそう多くないということ。
これまでの積み上げには確かな手応えがあるし、自信している。

あとは、できることを淡々と、誠実に積み重ねていくのみ。

一日一日を最高の一日にする。
それを積み重ねることが、自分にできる唯一のこと。

やってやろう。
Laravelのcollect()とfilter()の使い方

# 配列とコレクションの違い

PHP配列	Laravelコレクション（Collection）は普通の配列 ([])Laravelの便利なラッパークラス。
下記の便利機能を使いやすくするためのクラス。
- filter()
- map()
- pluck()
- each()
通常メソッドチェーンはできないが、メソッドチェーンチェーンできる

```php
collect()->filter()->map()
```

コレクションは、配列を「もっと便利に」扱えるようにしたもの。

# collect() の使い方

配列をコレクションに変換する関数。

```php
$collection = collect([1, 2, 3]);
```

これだけで $collection に filter() や map() などのメソッドが使えるようになる

⸻

# filter() の基本

filter() は、条件に合う要素だけを残す。

```php
$filtered = collect([1, 2, 3, 4])->filter(function ($value, $key) {
    return $value > 2;
});

$filtered->all(); // [3, 4]

```

- $value：要素の値
- $key：要素のキー（配列の添字など）

条件に true を返した要素だけが残る。

# 実用例：空欄を除外してリクエストを処理

```php
$filtered = collect($request->all())
    ->filter(function ($v, $k) {
        return $k !== 'system_user' && $v !== '' && !is_null($v);
    })
    ->keys()
    ->all();
```

- collect($request->all()): リクエストをコレクションに変換
- filter(...): 空・null・特定のキーを除外
- keys(): 入力された項目名（キー）だけを取得
- all(): 配列に戻す

⸻

# まとめ
- collect() で配列がコレクションに変わる
- filter() で「残したい条件」を指定して要素を絞れる
- 入力値の整理や検索条件処理に便利
OracleVM VirtualBox インストール

## はじめに
個人PCを買い替えたこともあり、OracleVM VirtualBoxを入れ直します。
簡単にですが手順などまとめたので共有します。

### 前提情報
使ったPCのスペックやOS情報は以下の通りです。

- プロセッサ：10コア、12個のロジカルプロセッサ
- メモリ：16.0 GB
- OS：Windows 11 Home 24H2
- ディスク：477GB

## インストール手順
### VirtualBoxのダウンロード
以下のURLにアクセスしてVirtualBoxをダウンロードします。
https://www.oracle.com/jp/virtualization/technologies/vm/downloads/virtualbox-downloads.html

### ファイル実行
ダウンロードしたファイルを実行します。
基本的にポチポチとボタンをクリックして進めていきますが注意が必要な箇所のみ以下に補足で記載します。

以下はデフォルトのまま「next」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4102347/7c442b27-d71b-4ba3-becc-31f6323222b0.png)

警告メッセージが出力されますがそのまま「Yes」をクリックします。

:::note
Python関連のパッケージがインストールされていないため警告が表示されます。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4102347/64b6114d-bf4c-48f6-8d2d-09ab6cf4a28a.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4102347/d5c2a86d-979e-47c7-8ba0-444b586146c7.png)

ここまできたら「Install」をクリックしてインストールを開始します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4102347/2ecec76a-b77c-4119-a132-f6ccd6275157.png)

「Finish」をクリックします。☑をつけておくと自動でVirtualBoxが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4102347/f14bffb5-32a8-43df-a11c-2a4d934a16d0.png)

### VirtualBox起動
以下のような画面が表示されたらVirtualBoxの起動成功です。
これでVM構築などが可能になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4102347/45440fd7-0e99-4902-b752-6b29070fceeb.png)
第27回 インターネットの中ってどうなっているの？

## 今回の記事を書こうと思った目的

私はネットワークエンジニアとしてAS運用や**IX業者**とのピアリング活動に従事し、Flowmonを活用してトラフィック量を削減する業務を行ってきました。その中で**インターネット構造を完全に理解しているエンジニアは意外と少ない**という事実に気づきました。本記事では、あえて現場で頻出する技術から一歩引き、**インターネットの構成原理**に立ち返って解説します。

#### 補足
・**IX業者**とは、複数のASが相互にトラフィックを交換するための**中継ポイント**です。代表的なものとしては**JPIX（日本）**、**エクイニクス（アメリカ）** などがあります。

## インターネットの構成

インターネットの構造は、一つの巨大ネットワークではなく、**数多くのASが連携することで形成**されています。各AS同士がピアリング活動を通じて**通信遅延やトラフィック集中を防ぐ**ことが実現できてます。
実際、私も過去にJPIX業者を介してTier2 ASとのピアリング運用を行った実務経験では、Flowmonを活用してトラフィック量の多い企業を特定し、ピアリング交渉を進めることで、**回線の負荷を軽減**する業務をしておりました。

#### インターネットの全体イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/6caeb18f-8e81-4ba5-b3a3-d0b4da17e248.png)


ASの構造には、主に以下のような**階層性,Tier構造**があります：
- Tier1: 他ASと相互接続する巨大AS（**例：NTT、Level 3など**）
- Tier2: 上位ASからトランジットを購入している**中規模AS**
- Tier3: **エンドユーザーにサービスを提供**するISPなど

このように、ASは**経済的・物理的な関係をもとに階層を形成**しており、上位に行くほどグローバルなネットワーク接続性と責任を担っています。

## 実例で学ぶパケットの旅路

たとえば**A社からMicrosoftのクラウド利用者B**へパケットが届く場合、下記のような流れになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/eebdcdac-c3ee-4f18-b0da-94c6c6993a0c.png)

一つのパケットは**複数のAS・ルータ・回線**を通って到達しています。
ルートの選定には**eBGP**が用いられ、経路属性に基づいて**ベストパス**が選ばれます。
※eBGPについての詳細は[こちら](https://qiita.com/infra-blog/items/8dce6e30385625fae515)の記事を参照

## IX（インターネットエクスチェンジ）の役割とピアリング戦略
IXとは、**複数のASが相互にトラフィックを交換するための中継ポイント**です。代表的なものとしては**JPIX（日本）**、**エクイニクス（アメリカ）** などがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/05e151fc-3507-417c-ad5c-b08720095213.png)

インターネットを構成する各ASは**相互にピアリングという線のようなもの**を張り、それが**いくつもにつながりインターネットは構成**されているのです。

なおこのピアリングには2種類あります：
- パブリックIX：**複数社が参加、経路短縮が可能**
- プライベートピア：**2社間**の直結
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/e552a704-6837-453e-a257-65aad5896f5a.png)

企業は通信の**品質向上やコスト削減を目的**にピアリング戦略を検討します。ただし、知名度やトラフィック量によっては、ピア交渉が不成立になるケースもあります。

## まとめ
インターネットとは、**世界中のAS（自律システム）同士がケーブルや機器**でつながり、**網目**のように構成された巨大なネットワークです。
普段、何気なく検索や買い物をしている人にとっても、この構造を知ることで**インターネットってこうやって動いているんだ**と少し身近に感じてもらえたら嬉しいです。
そして、エンジニアとして関わる私たちにとっても、その**構造的な理解**はトラブル対応や最適設計の土台となる重要な視点だと感じています。

## 参考
https://www.soumu.go.jp/hakusho-kids/life/what/what_03.html

https://www.packetfabric.co.jp/solution/detail36.html

https://www.nic.ad.jp/ja/ip/as-numbers.txt

## 次回予告
次回は**サーバー、またはセキュリティ分野**について記事を作成する予定です。
【Mac】openコマンドの使い方


`open`コマンドを使用するとファイル、ディレクトリ、アプリケーションを開くことができます。

##   デフォルトのアプリケーションでファイルを開く

```terminal
open file.txt
```

### カレントディレクトリの特定の拡張子のファイルを全てデフォルトのアプリケーションで開く

```terminal
open *.txt
```

## 特定のアプリケーションを開く

```terminal
open -a "Safari"
```

## 特定のアプリケーションでファイルを開く

```terminal
open -a "Safari" image.gif
```

## バンドル識別子に基づいてアプリケーションを開く

```terminal
open -b com.domain.application
```

### アプリケーションの新しいインスタンスを開く

```terminal
open -n -b com.domain.application
```

## Finderでディレクトリを開く

```terminal
open path/to/dir
```

## Finderでファイルを開く

```terminal
open -R path/to/file
```
【SwiftUI】SegmentのPicker

アプリ開発でSegmentのPickerを実装したのでアウトプットします。

# 環境
macOS - Sequoia 15.4.1
Xcode - Version 16.0

# コード

```diff_ruby
enum PracticeSegmentPicker: String, CaseIterable {
    case year = "年"
    case month = "月"
    case day = "日"
}

struct PracticePicker: View {
    
    @State private var segmentPicker: PracticeSegmentPicker = .year
    
    var body: some View {
        Picker("", selection: $segmentPicker) {
            ForEach(PracticeSegmentPicker.allCases, id: \.self) { picker in
                Text(picker.rawValue)
            }
        }
        .pickerStyle(SegmentedPickerStyle())
        .padding()
    }
}
```

これでSegmentスタイルになります。
```diff_ruby
.pickerStyle(SegmentedPickerStyle())
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/058f37b4-5caf-4c53-9689-62218a606bec.png" width=50%>

幅も変えることができます。
```diff_ruby
.frame(width: 200)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760972/da3b2f39-9ae0-4de3-a793-c48b7167c0e6.png" width=50%>
海外出身のSEが日本でサブリーダーを務めた経験

## はじめに
私は海外出身で、フロントエンドエンジニアとして3年間、主にReactを用いた開発に従事しました。
そして今回担当していたシステムの成長に伴い、サブリーダーとしての役割を担うこととなりました。
日本語のコミュニケーションに大きな問題はありませんでしたが、サブリーダーとしての責任に対して少し不安を感じていました。

## プロジェクトの成果
2年間大手企業の会計システム全体のフロントエンド開発を担当しました。
最初の4ヶ月間は、機能追加やバグ修正の作業を担当しましたけど、
その後から、フロントエンドのサブリーダーおよびテックリーダーとして、基本設計から製造までの作業や必要なライブラリの導入も担当しました。
また、新入社員向けの社内教育資料の作成も担当しました。

## サブリーダーとしての努力した点

### 1. 業務開始後1時間以内に小さな成果を報告すること
アフターコロナの影響により在宅勤務が拡大し、業務への緊張感や集中力の低下、チームワークの希薄化が見受けられるようになりました。

サブリーダーとして、こうした状況を改善するために、業務開始後、まずメールや業務チャットの内容を確認し、当日の業務内容をノートに手書きで記録することで集中力を高めました。その後、記録した内容を業務チャットで共有し、チームワークの意識を喚起するよう努めました。

### 2. リーダーとしての初月に大きな成果を求めすぎないこと
全体的な業務の把握には時間がかかりました。
SEとして個人の開発業務を担当していた際には見えなかった、
他のチームメンバーが直面する技術的な課題や他部署とのリリーススケジュールなどが見えてきました。
そのため、リーダー役を初めて担当する際には、圧倒される感情に陥りやすく、
私はその原因が大きな成果を出さなければならないというプレッシャーが原因だと思います。
その際には、議事録を作成することで、プロジェクトの優先順位を考えながら、重要なキーワードを中心に記事録を作成することをお勧めします。
細かい項目まで記録することよりは、優先順位を考えながら、重要なキーワードを中心に記録することで、
他の業務に対する集中力を維持することができます。

### 3. チームメンバーの性格を把握し、円滑なコミュニケーションを図ること
コミュニケーションとは、自分の認識と相手の認識のギャップを縮めることだと思います。
そのためには、相手の認識を把握する必要がありますが、その要素には言語だけでなく、相手の性格を把握することも重要だと感じました。
私の経験では、技術的な課題解決を優先するスペシャリスト志向のチームメンバーとの打ち合わせの前には、
そのメンバーのコミット内容をAIを活用し、迅速に把握してから、打ち合わせに参加することで、相互の認識のギャップを縮めるのに大いに役立ちました。

### 4. 曜日ごとの業務の優先順位と自分のエネルギーレベルを把握すること
私の経験では、毎週水曜日には他部署との短い会議が連続して複数ありましたので、
他部署との短い会議が連続する日には、可能な限り他の業務を減らしました。
他部署との会議では認識の違いが生じると、後日再度会議を設定するのが難しく、
連続する会議への参加は緊張の連続で、予想以上にエネルギーを消耗しました。そのため、会議終了後に各会議の内容を整理することに時間を割くことをお勧めします。

### 5. コードレビュー会は相手を尊重し、思いやりの心を持つこと
チーム内でコードレビュー会を定着させる文化が徐々に広がっていますが、
場合によってはコード反省会になってしまうこともあるため、常に相手を尊重し、思いやりの心を持ってレビューを行うことが重要だと思います。
「変数名の意味が伝わりにくいです」という短いコメントよりも、「◯◯◯のような変数名はいかがでしょうか？」といった具体的な提案を含むコメントが望ましいと考えます。

### 6. PL、PM資格の書籍を読むことで、プロジェクト全体のサイクルを間接的に体験すること
要件定義、基本設計、...、リリースまでのプロジェクト全体のサイクルを経験していないSEの場合は
PL、PM資格の書籍を読むことで、プロジェクト全体のサイクルに対する感覚を養うこともお勧めします。

### 7. 報告書作成において、誤字脱字の確認とより丁寧な文章がないかをAIにチェックしてもらうこと
報告書を作成する際には、誤字脱字の確認と、より丁寧な表現がないかをAIにチェックしてもらうことで、品質の向上を図ることができます。

### 8. すべての技術を習得しなければならないというプレッシャーを捨て、常に学ぶ姿勢を持つこと
最も重要なのは、現在のプロジェクトが円滑に進行するために何をすべきかを考えることです。すべての技術を習得しなければならないというプレッシャーを感じるのではなく、常に学ぶ姿勢を持つことが大切です。


### まとめ
リーダーの役割は想像以上に多くの業務を伴いますが、チームメンバーへの尊重と励まし、そして献身があれば、リリースまで問題なく到達することができました。
なぜ async/await で Promise チェーン全体をまとめるのか？

Promise チェーン (.then() x n) だけで書けるのに、あえて `await` でチェーン全体をまとめる理由を整理しました。

4つのメリットに分けられます。

| No. | メリット           | 内容                |
| --- | -------------- | ----------------- |
| 1   | 通常のスコープで使える変数になる      | 値の再利用が自由。Promiseのスコープを超える |
| 2   | 追加処理が柔軟        | ネスト不要で可読性が高い      |
| 3   | try-catch 一括管理 | エラーがまとめて捕捉できる     |
| 4   | 分岐・条件判定が自然     | if/switch が使いやすい  |


## 1. コード比較

### 1-A. チェーンだけで書く

```js
function fetchAndRender() {
  fetch(url)
    .then(r => r.json())
    .then(json => json.items)
    .then(items => render(items));
}
```

### 1-B. await でチェーン全体をまとめる

```js
async function fetchAndRender() {
  const items = await fetch(url)
    .then(r => r.json())
    .then(json => json.items);
  render(items);
}
```

結果は同じ。違いはチェーン後の拡張性や可読性など。



## 2. メリット詳細

### 2-1. 普通の変数になる

```js
const items = await fetch(url).then(...);
logAnalytics(items);
render(items);
```

* `.then()` に閉じ込められない。
* デバッグも簡単：`console.log(items)` がどこでも使える。
* 非同期かどうかを意識せず、同期コードのように書ける。

---

### 2-2. 追加処理が柔軟に書ける

#### チェーン型

```js
.then(items => {
  const active = items.filter(i => i.active);
  return process(active).then(() => {
    if (active.length > 10) {
      alert('多い!');
    }
  });
})
```

#### await 版

```js
const active = items.filter(i => i.active);
await process(active);
if (active.length > 10) {
  alert('多い!');
}
```

* ネスト解消 → 保守性が向上。
* `return` や `Promise` を気にせず書ける。

---

### 2-3. try-catch でエラーを一括管理

#### チェーン型

```js
fetch(url)
  .then(...)
  .catch(err => handle(err));
```

* 例外発生箇所が深いと煩雑。
* 局所 `catch` を複数書くことも。

#### await 版

```js
try {
  const items = await fetch(url).then(...);
  render(items);
} catch (err) {
  handle(err);
}
```

* finally も使いやすい。
* 全体を見通して例外処理できる。

---

### 2-4. 分岐・条件判定が自然

#### await 版

```js
if (!items.length) return notifyEmpty();
for (const item of items) {
  await renderRow(item);
}
```

* `if` や `for` など制御構文が使いやすい。
* コールバックの深いネストから脱出。

---

## 3. チェーンだけで済ませるかどうか？

| 状況             | 推奨    | 理由            |
| -------------- | ----- | ------------- |
| ステップが 1〜2 段で完結 | チェーン  | 短くシンプル        |
| 後続処理がほぼ無い      | チェーン  | await はやや冗長   |
| UI 更新や複数分岐が必要  | await | 可読性・保守性が上がる   |
| エラーをまとめて管理したい  | await | try-catch が有効 |

---

## 4. まとめ

* await でチェーンをまとめる最大の利点は、「結果を普通の変数として取り出せる」こと。
* それにより、ネストの解消、エラーの集中管理、分岐の自由度が得られる。
* 単純なケースは `.then()` の方が短く済む。
🧑‍🏫【初心者から】組み込み開発_RL78G14篇　LC1

##### QQQ :bow_tone1:３Q! 
##### [トップへ](https://qiita.com/zhb/items/483fe81aff11b0ade637) 　:arrow_heading_up:

# 初めに
Renesas RL78G14をコアとして、ビジュアルな実践プロジェクトを通じて初心者がゼロから組み込み開発を学べるよう設計された教材です。

# RL78G14の選択理由
- GUIツールによってソースコードの自動生成が可能
- ソフトウェアシミュレーターによる動作確認に対応
- STM32と比べて、初心者にとって学習・導入が容易な設計
- 速戦できる
  低消費電力と高機能性を両立し、モータ制御、FA機器、計測用途に適した汎用マイコン
　※出典：ルネサス公式サイトト宣伝

# 📚 レッスン一覧
### [LM_1]　LED照明を制御させる
<ul>
  <li><a href="https://qiita.com/zhb/items/b2d6463c66d6026c7057"> [LM_1_SIM] 10分で制御させる 　</a></li>
  <li><a href="https://qiita.com/zhb/items/84e4b6dd08d5799c52fa">[LM_1_Code]RL78G14ルネサスのVSCode開発環境の構築</a></li>
</ul>
</details>

### [LM_2]　7セグメントLED

##### [トップへ](https://qiita.com/zhb/items/483fe81aff11b0ade637)　:arrow_heading_up:
##### QQQ :bow_tone1:３Q!
【ABC備忘録】imos法 - AtCoder Begginers Contest 408 C

「imos法を知らなかったので調べてみた」という記事です。
復習がてら…の方も宜しければどうぞご覧ください。

---
 - [0.それはABC408を解いていた昨日のこと…](#0.それはABC408を解いていた昨日のこと…)
 - [1.imos法について調べる](#1.imos法について調べる)
 - [2.累積和との違い](#2.累積和との違い)
 - [3.ABC408Cの実装](#3.ABC408Cの実装)
---

## 0.それはABC408を解いていた昨日のこと…
ABC408に遅れて参加した私は、灰色コーダーらしくC問題でつっかかって2完でした（紆余曲折を端折りましたがご容赦ください）。
https://atcoder.jp/contests/abc408/tasks/abc408_c

終わってから解法を見たり、Twitter（現：X）の反応を見ていると、みなさん口を揃えて「**imos法** 」のお話をされているわけです。

私は知らないぞimos法！というわけで調べてまとめました。実質備忘録です。

## 1.imos法について調べる

まずはさっくりとimos法とはどういうものかについてですが、アルゴリズム考案者いもす様のページより下記を引用させていただきます。

>いもす法とは，累積和のアルゴリズムを多次元，多次数に拡張したものです．競技プログラミングでは 2 次元 1 次のものまでしか出題されませんが，2012 年の研究成果としてこれをより高次元の空間により高次数のいもす法を適用することにより信号処理分野・画像処理分野において利便性があることがわかっています．


つまり、累積和とは違う…？多次元的に拡張…？

というか正直私がぐだぐだいうよりページ見ていただくほうが早いことも確かですので、よろしければ下記リンクをどうぞ。
https://imoz.jp/algorithms/imos_method.html


また最初読解に時間がかかった（私には難しかった）こともありましたので、比較的初心者向けの下記記事も参考にさせていただきました。
https://note.com/kirimin_chan/n/n7663e3bb8a05


imos法、累積和の問題がまとめられているこちらも私が後で確認しようと思っております。
https://blog.hamayanhamayan.com/entry/2017/07/04/020117


---

## 2.累積和との違い

imos法の基本的な流れは以下の通りです。
1. 配列の各区間の始点に加算、終点+1に減算を記録する
2. 最後に累積和を取ることで、各要素の最終的な値を求める


上記を踏まえた上で、累積和は「配列の先頭から順に値を足し合わせていくこと」自体を指すアルゴリズムです。
一方、imos法は「区間に対する加算・減算」を効率的に処理するための手法、というふうに私は違いを認識しています。


imos法は、累積和の考え方を応用しており、「区間加算→累積和」という2段階で処理しているんだな、という捉え方です。

---

## 3.ABC408Cの実装

以上を踏まえて実装に入ります。言語はPythonです。
いずれはC++も書けるようになりたいものですね…。

#### 実装例（Python）

```python
N, M = map(int, input().split())
imos = [0] * (N + 1)

# 壁の区間加算を行う
for i in range(M):
	L, R = map(int, input().split())
	imos[L-1] += 1
	imos[R] -= 1

# 壁の高さを累積和で出す
Walls = [imos[0]]
for i in range(1, N):
	Walls.append(Walls[i-1]+imos[i])
	
# 一番薄い城壁が答え
print(min(Walls)
```

改めて実装すると、「区間加算→累積和」という流れがよく見えますね。
私の中ではこの感覚で今後解いていこうと思います。
Swift UI のButtons基礎の使い方を説明しました！

アプリ開発で「ボタン」はユーザーの操作を受け取る重要なUIパーツです。
SwiftUIでは、シンプルで直感的なコードで Button を実装できます。


1.一番基本的なボタンの書き方
---

```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Button("押す") {
            print("ボタンが押されました")
        }
    }
}
```

2.ボタンの見た目をカスタマイズする
--


```swift
Button(action: {
    print("カスタムボタン")
}) {
    Text("カスタムボタン")
        .padding()
        .background(.blue)
        .foregroundColor(.white)
        .cornerRadius(10)
}
```
- Text の代わりに Button の中で好きなビューを使えます。
![Screenshot 2025-06-01 at 22.20.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977742/c5bd0ee7-8724-48f0-9097-def0db2db2b1.png)



3.アイコン付きボタン（Label を使う）
---
```swift
Button(action: {
    print("アイコン付きボタン")
}) {
    Label("保存する", systemImage: "square.and.arrow.down")
}
```
- Label を使うとテキスト＋アイコンのボタンが簡単に作れます。
![Screenshot 2025-06-01 at 22.15.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3977742/5a8f938d-b394-4a3f-ae14-0974a47487af.png)





まとめ
---
| 機能       | 実装方法の例                                |
| -------- | ------------------------------------- |
| 基本のボタン   | `Button("タイトル") { 処理 }`               |
| デザインカスタム | `Text().padding().background()` など    |
| アイコン付き   | `Label("タイトル", systemImage: "アイコン")`  |


最後に
--
SwiftUIのButtonは、基本をマスターすればどんどん応用が効くようになります!
Swift UI のButtons基礎の使い方を説明しました！ぜひ参考にしてみてください👍
【Ruby】*と**を使って引数として渡す時と受け取る時の違い

## はじめに
Railsのソースコートを見ていたら、定義された関数の引数に`*`,`**`,`&`を用いた記法があったため、学んだことを自分なりにまとめました。

## `*`の場合
「可変長引数」といい、受け取る時には渡された引数を`配列`として受け取る。引数の個数が変わる時に便利。

```ruby
def hell(*names)
  names.each { |name| puts "こんにちわ#{name}さん！" }
end

hello("田中", "佐藤", "山本")
#=>こんにちわ田中さん！
#=>こんにちわ佐藤さん！
#=>こんにちわ山本さん！
```

逆に、渡す時は配列を展開して渡す。
```ruby
def add(a, b, c)
  puts a + b + c
end

add(*[1, 2, 3])
```

## `**`の場合
「可変長キーワード引数」といい、受け取る時には渡された引数を`ハッシュ`として受け取る。引数の個数が変わる時に便利。

```ruby
def info(**options)
  puts options
end

info(name: "佐藤", age: 30)
#=> { :name=>"佐藤", :age=>30 }
```

逆に、渡す時はハッシュを展開して渡す。
```ruby
def greet(name:, message:)
  puts "#{message}, #{name}さん！"
end

greet(**{ name: "佐藤", message: "こんにちわ" })
#=>こんにちわ, 佐藤さん！
```

## `&`の場合
`&`を使ってメソッドを定義すると、`Procオブジェクト`として変数に代入される。

```ruby
def hoge(&block)
  puts block
  puts block.call
end

hoge do 
  puts 1
end
#=>#<Proc:..>
#=>1
```

逆に、渡す時は`Procオブジェクト`を展開してブロックにして渡す。また、`yield`がブロックを起動している認識。

```ruby
def greet
  yield
end

hello = Proc.new{ puts "Hello!" }
greet(&hello)
#=> Hello!
```

ちなみに、`Procオブジェクト`はそのまま渡すとエラーになるため、ブロックにして渡す必要がある。
```ruby
add_10 = Proc.new{ |e| e + 10 }
[1, 2, 3].map(add_10)
# => ArgumentError: wrong number of arguments (given 1, expected 0)

#Procオブジェクトを「展開」し、ブロックとしてメソッドに渡す
add_10 = Proc.new{ |e| e + 10 }
[1, 2, 3].map(&add_10)
```
この `&proc_obj`の書き方が、Proc → ブロックの変換を担います。

## まとめ
- `*` と `**` は「引数の数が決まっていないとき」に使うと便利。
- `*args` は 位置引数を配列として、`**kwargs` は キーワード引数をハッシュとして受け取る。
- `&block` は ブロック（処理）をプロックへ変換し、変数として扱えるようにしている
埋め込みメディアの置換について

## はじめに
Ruby on Rails を学習している初学者です。
今回、埋め込みメディアにTwitterを追加する際Xに置換する必要があったため、記録として残したいと思います。

## 置換を行う関数の追加

```ruby:embed.rb

  def processed_identifier
    case embed_type.to_sym
    when :twitter
      identifier.gsub(%r{\Ahttps://x\.com/}, 'https://twitter.com/')
    else
      identifier
    end
  end

```
こちらの関数は、x.comになっていた場合、twitter.comに直して返すようになっております。
これを表示実装部分に適用させてあげるだけで置換され、tweetが表示されます。

## 置換処理の適用

```ruby:_embed_twitter.html.slim

script async="" charset="utf-8" src="https://platform.twitter.com/widgets.js"
.embed-twitter
  blockquote.twitter-tweet
    a href=embed.processed_identifier

```
（例：a href=embed.processed_identifier）
※今回は関数を使っていますが、slim側でgsub(文字列置き換え)を使っても出来ると思います。

## 最後に
短いですが以上になります。最後まで読んでいただきありがとうございました。
Xからまたその他のものに変わってしまった場合など、今回のように変更を加えていただけたらと思います。
Windows XPでまさかの最新のChromiumを動かす (supermium)

こういうロマン好き。ハマりポイントがあったので書いておきます。
メモリは 1GBでは不足1.5GB以上あったほうがよいです。

## 公式HP

https://win32subsystem.live/supermium/

## ダウンロード

https://win32subsystem.live/supermium/downloads/releases/

* 現在の最新は `v132-r3_01`でした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/83c28be2-2118-476f-b639-2a0d4603cd86.png)

* `supermium_132_32_nonsetup.zip` をダウンロードし解凍。

他は検知で引っかかる様子

フォントをFontsフォルダにコピーしておく。（必要？）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/400cdf4c-daad-47dd-877c-8e4acc4575ba.png)

## 起動方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/09ddcd77-2ead-4c7d-ac76-2ff0e57af973.png)

## 画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/f00703dc-0a8d-4b9a-b70a-80bb167217b2.png)

### メモリ不足 (1024MB)

メモリ不足の場合以下エラーになった。

* youtubeにアクセスしてみましたがそちらはページが表示されませんでした。（表示に時間がかかっているためそのまま待機するか聞かれた。）


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/543d6688-de10-47fd-9fa2-7b5d8a389c70.png)


### メモリ1500MBに増やしてみた

* 表示できた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/3aa329dc-61fc-429f-91aa-05e4108bb07e.png)

* YouTubeもOK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/229b0204-9ca1-4f29-a30f-3a4d650d9de4.png)

* Qiitaへのログインと編集もできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/d7733a74-4b5a-41e3-a091-9be159f20bda.png)

普通に快適です。

---- 

## ほかのソフト

* MyPal (Firefoxベース)


https://www.mypal-browser.org/

https://www.mypal-browser.org/release/


* 360 Extreme Explorer (こちらは中国製のためあつかいちゅう)
PIE TIME picoCTF

# はじめに
picoCTFのPIE TIMEが全く分からず解説動画をただ見て解決するという状況になっていたので知識整理を行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/a871188e-1e8f-4682-8d41-be19263e2d3f.png)


# 参考動画

https://www.youtube.com/watch?v=3mottZN1des


# そもそもPIEとは？
Position Independent Executableの略

> 日本語では位置独立実行形式と訳される、位置独立コード（Position Independent Code, PIC）によって構成される実行ファイルです。
PIEでは、ファイルは実行されるたびに異なるランダムなメモリアドレスに呼び出されます。この技術は、メモリの絶対アドレスを特定することで引き起こされる攻撃を困難にします。

https://www.sompocybersecurity.com/column/glossary/pie
より引用

> PIE (Position Independent Executable) is a security mechanism that loads a program into a different memory address each time it runs. This means the binary doesn’t run at a fixed memory address, making it harder for an attacker to predict where the executable code resides.
In a PIE-enabled program, each function’s memory address is calculated as:
memory address = base address + offset
The offset of a function is constant, but the base address changes every time the program is executed.

> PIE（Position Independent Executable）は、プログラムを実行するたびに異なるメモリアドレスにロードするセキュリティメカニズムです。つまり、バイナリは固定のメモリアドレスで実行されないため、攻撃者が実行コードがどこに存在するかを予測することが困難になります。
PIE 対応プログラムでは、各関数のメモリ アドレスは次のように計算されます。
メモリアドレス = ベースアドレス + オフセット
関数のオフセットは一定ですが、ベースアドレスはプログラムが実行されるたびに変化します。

https://medium.com/@vhteren2004/pie-position-independent-executable-explained-through-a-ctf-challenge-9930404c4e5b
より引用

今回の問題はアドレスの割り出しが必要となる
メモリアドレスの特定のために予めオフセットを求めておき、ベースアドレスに足してやることになる

# 解析
cプログラムを解析する
そのためにデバッガのインストールを行う
また対象のcファイルは権限を変更した状態にしておく

デバッガ (gdb)とは

> Cプログラム中のバグを発見するためのツール（一般にデバッガと呼ばれる） としてGNU Project Debugger (gdb) を利用することができる． gccと組み合わせて利用することにより，プログラムを特定の位置で一時停 止させたり（ブレーク・ポイントの利用），停止中の位置での変数や式の 値を確認することができるなど，バグの原因特定に非常に有用である．

https://www.fos.kuis.kyoto-u.ac.jp/le2soft/siryo-html/node45.html
より引用

gdb vuln
を実行する

rを行う
適当な値を入れてアドレスの値を見る

disassemble main
でmain関数の中身を逆アセンブルする
出力されたアドレスの中身をチェックし存在するかを確かめる

次に
disassemble win
を実行する

emdbr64のアドレスを控える

mainとwinのemdbr64のアドレスの差を求める

アドレスの計算には以下のサイトを利用する

https://www.rapidtables.com/calc/math/hex-calculator.html?num1=0x557da939b33d&op=1&num2=96

差を求めると
Hex 96
Decimal 150
の値が得られる

メモリアドレスを求めるためにターミナルからインスタンスを実行した時に出る
nc rescued-float.picoctf.net
を実行する
（なお.netの後には数字があるが可変のため割愛）

このコマンドを実行した時にmainのアドレスが得られるので今回のwinとのアドレスの差である96を差し引いてwinへのメインアドレスを取得する

得られた結果に0xを付けた値をタイプしてflagを取得する

https://visualgdb.com/gdbreference/commands/disassemble

# 終わりに
PIEの概念を初めて知ったため理解がしきれず何をやっているのかさっぱりだった
gdbの使い方も知らなかったのでいい勉強になった
メモリアドレスの求め方はなぜ差し引いているのか理解しきれてなかった
後日見返して記事の修正を行う
少しずつpicoCTFの内容も難しくなってきた感じがする
教材やサイトでの勉強量をもっと増やす必要性を感じている
TanStack Router × Integrationテスト を実装する

## はじめに

現在、TanStack Router を利用した SPA を開発しています。

最近、Integrationテスト（結合テスト）を実装することになったのですが、公式ドキュメントにテストに関する情報がなく、そもそもページの render をどうするのか？というところからつまづいたので、簡単にまとめました。

同じように困っている方の参考になれば幸いです。

## 目次

[1. 前提](#前提)
[2. 実装例](#実装例)
[2. まとめ](#まとめ)
[4. 参考](#参考)

## 前提

ルーティング関連のライブラリ

- `"@tanstack/react-router": "^1.114.3"`
- `"@tanstack/react-router-devtools": "^1.114.3"`

テスト関連のライブラリ

- `"@testing-library/dom": "^10.4.0"`
- `"@testing-library/jest-dom": "^6.6.3"`
- `"@testing-library/react": "^16.3.0"`
- `"@testing-library/user-event": "^14.6.1"`
- `"@vitejs/plugin-react": "^4.3.4"`
- `"jsdom": "^26.1.0"`
- `"vite": "^6.1.0"`
- `"vitest": "^3.1.4"`

## 実装例

今回は下記の理由から、`main.tsx` で定義している `router` インスタンスをテストファイルでも`import` し、`render(<RouterProvider router={router} />)` を使ってページをレンダリングすることにしました。

- `router` の定義を共通化でき、アプリ本番と同じ設定でテストが書ける
- 初期化処理を新たに書かずに済むため、手軽に導入可能
- 複雑な context 設定や routeTree をテスト側で再構成しなくて済む

```diff_tsx:main.tsx
import { createRouter, RouterProvider } from '@tanstack/react-router';

- const router = createRouter({
+ export const router = createRouter({
  routeTree,
  context: {
    ...TanStackQueryProvider.getContext(),
  },
  defaultPreload: 'intent',
  scrollRestoration: true,
  defaultStructuralSharing: true,
  defaultPreloadStaleTime: 0,
});
```

```tsx:index.test.tsx
import { router } from "@/main";
import { RouterProvider } from "@tanstack/react-router";
import { describe, test } from "vitest";

// テストごとにnavigateして任意の初期URLに遷移させる
const customRender = async () => {
  await router.navigate({
    to: "/sample",
  });

  render(<RouterProvider router={router} />);
};

describe("/sample のテスト", () => {
  test("××ボタンを押下すると、〇〇が表示されること", async () => {
    customRender();
    // 要素を取得して結果を検証
  });
  test("△△ボタンを押下すると、◻︎◻︎が表示されること", async () => {
    customRender();
    // 要素を取得して結果を検証
  });
});
```

## まとめ

今回は、main.tsx で定義している router インスタンスをテスト内でもそのまま利用する方法をご紹介しました。

ただ、この方法がベストプラクティスなのか？という疑問もあるので、今後は、テスト用に TestRouterProvider を別ファイルに定義して、router や context、必要な provider を柔軟に差し替えられるようにする構成も検討したいと思います。

より良い方法やパターンが見つかれば、あらためて記事としてまとめていく予定です。

## 参考

- [:page_facing_up:Testing Component and Hook with Tanstack Router #655](https://github.com/TanStack/router/discussions/655)
SwiftUI 初心者向け：ScrollViewの使い方を簡単に説明してみました

SwiftUIで画面に入りきらないコンテンツを表示したいときに使うのが ScrollView です。縦スクロールや横スクロールが簡単に実装でき、リスト以外の自由なレイアウトをスクロール対応させるのに便利です。

この記事では、初心者の方向けに ScrollView の基本的な使い方を説明してみました。

基本の使い方：縦スクロール
--
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView {
            VStack(spacing: 20) {
                ForEach(1...20, id: \.self) { number in
                    Text("アイテム \(number)")
                        .frame(maxWidth: .infinity)
                        .padding()
                        .background(.blue)
                        .cornerRadius(8)
                }
            }
            .padding()
        }
    }
}
```

ScrollView の中に VStack を入れることで、縦方向にアイテムを並べられます。

横スクロールの使い方
---
```swift
ScrollView(.horizontal) {
    HStack(spacing: 15) {
        ForEach(1...10, id: \.self) { number in
            Text("カード \(number)")
                .frame(width: 120, height: 100)
                .background(Color.orange.opacity(0.3))
                .cornerRadius(10)
        }
    }
    .padding()
}
```
ScrollView(.horizontal) と書くことで横スクロールが可能になります。

👀 注意
- ScrollView は中身のサイズが画面を超えないとスクロールされません。

まとめ
--
| 機能      | 実装方法                                    |
| ------- | --------------------------------------- |
| 縦スクロール  | `ScrollView { VStack { }}`              |
| 横スクロール  | `ScrollView(.horizontal) { HStack { }}` |


最後に
--
SwiftUIの ScrollView はとても直感的に使える便利なコンポーネントです! 
ぜひアプリ開発でも便利なので、ぜひマスターしてください🙌
ECR ECS Fargate をざっくり説明する

## 初めに
AWSのサービスはほとんどがコントロールプレーンとデータプレーンに分けられているとのことだったので、そこから説明を行う。

## リポジトリ
データを保管する場所

## データプレーン
データの転送や処理を実行する場所

## コントロールプレーン
システムの制御を行う場所、頭脳

## ECR (Elastic Container Registry)
リポジトリに属する。作成したDockerのコンテナイメージを保存管理する場所。

## Fargate
データプレーンに属する。ECSでコンテナを実行するための環境を提供する。具体的にはCPUやメモリを提供。

### なぜDockerと言ったらFargateというイメージ、記事が多いのか
Dockerの思想との親和性があるから。
Dockerの思想がアプリケーションとその依存関係をコンテナに詰め込んで、どこでも同じように迅速に開発できるようするという思想だった。従来のEC2はさまざまな設定、管理が必要。一方Fargateはコンテナを用意しさえすれば、EC2に比べると準備に時間がかからず開発が行える、ここが似ているため。

## ECS (Elastic Container Service)
コントロールプレーンに属する。ECRに保存していたコンテナを持ってきて、起動するコンテナの数を決めたり、止まったコンテナ再起動したり、古いコンテナを新しいコンテナに入れ替えたする。つまりコンテナの管理をやる場所。

##
## 参考
https://docs.aws.amazon.com/ja_jp/whitepapers/latest/aws-fault-isolation-boundaries/control-planes-and-data-planes.html
prevって何？なんで直接setCount(count + 1)じゃダメなの？

# はじめに

Reactでカウンターなどの状態を管理していると、こんなコードを見かけることがあります。

```tsx
setCount((prev) => prev + 1);
```

「`prev`って何？」「なんで直接`setCount(count + 1)`じゃダメなの？」と疑問に思った方も多いのではないでしょうか。

この記事では、**`prev`の正体とその重要性**を、シンプルなカウンターの例を使ってわかりやすく解説します！

# `prev`の意味とは？

`prev`とは、**「前の状態（previous state）」**のことです。

Reactの`useState`で定義した状態更新関数（例：`setCount`）には、**関数を引数として渡すことができます**。

```tsx
const [count, setCount] = useState(0);

// 関数を渡す方法
setCount((prev) => prev + 1);
```

このとき、Reactは自動的に関数の引数に**最新の状態**（= `prev`）を渡してくれるのです。

# なぜ直接`setCount(count + 1)`ではダメなの？

複数回連続で状態を更新する場合、**古い状態に基づいてしまうことがある**からです。

❌ NGな例

```tsx
const handleClick = () => {
  setCount(count + 1)
  setCount(count + 1)
}
```
この関数が呼ばれた瞬間、**今の`count`の値が確定しており、それ以降は変わらない**のです。

* `count`はこの関数内では「ただの変数」として扱われる
* `setCount(count + 1)`を2回呼んでも、どちらも「古いcount + 1」で計算される
* それぞれの`setCount`は同じ値を次の状態としてReactに渡す

```tsx
const handleClick = () => {
  // コールされるときcount = 1の場合
  setCount(0 + 1)
  setCount(0 + 1)
}
```

✅ OKな例（`prev`を使う）

```tsx
const handleClick = () => {
  setCount((prev) => prev + 1);
  setCount((prev) => prev + 1);
}
```

この書き方なら、Reactは1回目の更新後の最新の値を`prev`に渡してくれるので、**正しく2回加算されます（+2）**。

👀 `prev`を使うべきパターン

| 状況           | 書き方                            | 説明                    |
| ------------ | ------------------------------ | --------------------- |
| 1回だけ更新       | `setCount(count + 1)`          | 状態に依存していないならOK        |
| 状態に依存して複数回更新 | `setCount((prev) => prev + 1)` | **このパターンで`prev`が必要！** |

# まとめ

* `prev`は **「直前の状態」** を意味する
* `setState((prev) => …)` という形で使う
* 特に、**状態に依存した更新を複数回行うときに必須**
* Reactが **最新の状態を保証して渡してくれる** ので安心！

✍️ おまけ：サンプルコード全体

```tsx
import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);

  const handleDoubleIncrement = () => {
    setCount((prev) => prev + 1);
    setCount((prev) => prev + 1);
  };

  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={handleDoubleIncrement}>+2する</button>
    </div>
  );
}
```

このように、`prev`を使えば\*\*「意図した通りの更新」\*\*を安全に行うことができます。Reactで状態管理を行う上でとても大事なポイントなので、ぜひ覚えておきましょう！