OmniAICreator/Qiita-1.07M huggingface dataset:
Vim コマンド [ 備忘録 ]

# Vim コマンド備忘録

## 1. ファイル内の全行削除

### 基本的な方法
```vim
:%d
```
- `:%` - ファイル全体を指定
- `d` - 削除コマンド

### 別の方法
```vim
:1,$d
```
- `1,$` - 1行目から最終行まで
- `d` - 削除コマンド

### ビジュアルモードでの削除
```vim
ggVG
```
その後 `d` を押す
- `gg` - ファイルの先頭に移動
- `V` - 行選択モード
- `G` - ファイルの最後に移動

---

## 2. コピー＆ペースト

### 基本操作
| コマンド | 説明 |
|---------|------|
| `yy` または `Y` | 現在行をコピー |
| `p` | カーソル後にペースト |
| `P` | カーソル前にペースト |

### 複数行のコピー
```vim
5yy        # 現在行から5行をコピー
y5j        # 現在行から下5行をコピー
```

### 範囲指定でのコピー
```vim
:1,5y      # 1行目から5行目をコピー
:'<,'>y    # ビジュアル選択範囲をコピー
```

### 単語・文字のコピー
| コマンド | 説明 |
|---------|------|
| `yw` | 現在の単語をコピー |
| `yiw` | カーソル位置の単語全体をコピー |
| `y$` | カーソル位置から行末までコピー |
| `y0` | 行頭からカーソル位置までコピー |

---

## 3. アンドゥ（戻る）とリドゥ（進む）

### 基本操作
| コマンド | 説明 |
|---------|------|
| `u` | 前の操作を取り消し（アンドゥ） |
| `Ctrl + r` | 取り消した操作をやり直し（リドゥ） |

### 応用操作
```vim
5u         # 5回分アンドゥ
U          # 現在行への変更をすべて取り消し
```

### アンドゥツリーの確認
```vim
:undolist  # アンドゥ履歴の表示
:earlier 5m # 5分前の状態に戻る
:later 10s  # 10秒後の状態に進む
```

---

## 4. 単語識別とカーソル移動

### 単語移動の基本
| コマンド | 説明 |
|---------|------|
| `w` | 次の単語の先頭に移動 |
| `b` | 前の単語の先頭に移動 |
| `e` | 現在/次の単語の末尾に移動 |
| `ge` | 前の単語の末尾に移動 |

### 大文字コマンド（区切り文字を無視）
| コマンド | 説明 |
|---------|------|
| `W` | 次の空白区切りの単語に移動 |
| `B` | 前の空白区切りの単語に移動 |
| `E` | 現在/次の空白区切り単語の末尾に移動 |

### 数字との組み合わせ
```vim
3w         # 3つ先の単語に移動
5b         # 5つ前の単語に移動
2e         # 2つ先の単語の末尾に移動
```

### 単語内での移動
| コマンド | 説明 |
|---------|------|
| `f{文字}` | 行内で指定文字の次の出現位置に移動 |
| `F{文字}` | 行内で指定文字の前の出現位置に移動 |
| `t{文字}` | 指定文字の手前に移動 |
| `T{文字}` | 指定文字の後ろに移動 |
| `;` | 直前のf/F/t/Tコマンドを繰り返し |
| `,` | 直前のf/F/t/Tコマンドを逆方向に繰り返し |

---

## 5. 空行の追加

### 基本的な空行追加
| コマンド | 説明 |
|---------|------|
| `o` | 現在行の下に空行を作成して挿入モードに |
| `O` | 現在行の上に空行を作成して挿入モードに |

### 挿入モードに入らずに空行追加
| コマンド | 説明 |
|---------|------|
| `o<Esc>` | 下に空行を作成してノーマルモードに戻る |
| `O<Esc>` | 上に空行を作成してノーマルモードに戻る |

### 複数の空行を一度に追加
```vim
5o<Esc>    # 現在行の下に5行の空行を追加
3O<Esc>    # 現在行の上に3行の空行を追加
```

### コマンドラインモードでの空行追加
```vim
:put _     # 現在行の下に空行を追加
:put! _    # 現在行の上に空行を追加
```

### 特定の行番号に空行を追加
```vim
:5put _    # 5行目の下に空行を追加
:10put! _  # 10行目の上に空行を追加
```

### 範囲指定での空行追加
```vim
:1,5s/$/\r/g   # 1-5行目の各行末に改行を追加
```

### 現在位置に空行を挿入
```vim
i<Enter><Esc>  # 現在位置で改行して上の行に戻る
```

---

## 便利な組み合わせ例

### 効率的な編集
```vim
ciw    # 単語を変更（change inner word）
diw    # 単語を削除（delete inner word）
yiw    # 単語をコピー（yank inner word）
```

### 素早い移動
```vim
*      # カーソル下の単語を前方検索
#      # カーソル下の単語を後方検索
gd     # カーソル下の変数の定義に移動
```

### 行の操作
```vim
dd     # 現在行を削除
cc     # 現在行を変更
yy     # 現在行をコピー
```

---

## Mac 特有の注意点

- **Ctrl キー**: MacでもVimでは `Ctrl` キーを使用
- **Option キー**: Macの `Option` キーはVimでは `Alt` として機能
- **Terminal設定**: iTerm2 や Terminal.app の設定で Vim のキーマッピングが影響を受ける場合があります

---

## さらなる学習のために

Vimは非常に奥が深いエディタです。これらの基本コマンドをマスターしたら、以下も学習してみてください：

- ビジュアルモード（`v`, `V`, `Ctrl+v`）
- 検索と置換（`/`, `?`, `:s///g`）
- マクロ（`q` で記録）
- バッファとウィンドウ操作
- プラグイン管理

練習を重ねることで、Vimの真の力を実感できるようになります！
PDBのXMLファイル紛失時の対応

# はじめに

Oracle DatabaseのPDB/CDB構成において、PDBは Unplug/Plug を行って他のCDBに移行することが可能です。
通常はUnplugを行う際にメタデータをXMLファイルに出力し、そのXMLファイルを利用して他のCDBに Plug しますが、XMLファイルが見当たらなくなってしまった場合、どうすればよいでしょう？

そのような時には DBMS_PDB.RECOVER を利用することで XML ファイルを再作成することができます。

# XMLファイルの再作成

まず、DBMS_PDB.RECOVER のマニュアルはこちらになります。

- [DBMS_PDB.RECOVER プロシージャ](https://docs.oracle.com/cd/F19136_01/arpls/DBMS_PDB.html#GUID-D0601C03-88AB-4D03-8F8F-2829FB0CD12A)

次のように、データファイルを選択することが逆にPDBのためのXMLファイルを再作成することが可能です。

```SQL:DBMS_PDB.RECOVER
BEGIN
 DBMS_PDB.RECOVER(
  PDB_DESCR_FILE=> '/tmp/TESTDB.xml', 
  PDB_NAME=>'TESTDB',
  FILENAMES=>'
   /u01/oradata/TESTDB/TESTDB/system01.dbf,
   /u01/oradata/TESTDB/TESTDB/sysaux01.dbf,
   /u01/oradata/TESTDB/TESTDB/users01.dbf
  '
 );
END;
/
```
XMLファイルを再作成したら、通常と同様にPlugすることが可能です。

```SQL:Plug-in
CREATE PLUGGABLE DATABASE TESTDB USING '/tmp/TESTDB.xml' NOCOPY TEMPFILE REUSE;
```

# まとめ

簡単ですが、備忘のため。。
XMLファイル自体は単純に名前と場所を配置しているだけなので、なくしてしまっても焦らず再作成しましょう。
nvmでNode.jsをインストール

# Node.jsとは
**JavaScript**を使ってサーバーサイド開発ができるようにするランタイム環境です
一言でいうと**工場**です
# nvmとは
「Node Version Manager」の略です
Node.jsのバージョンを簡単に切り替え・管理できるツールです
# インストール
## Mac
https://nodejs.org/ja/download

### 1. ターミナルを起動する
### 2. バージョンを確認する
バージョンが表示されない場合はNode.jsのインストールする
```bash
node -v
```
### 3. nvm（Node Version Manager）をインストールする 
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
```
※2025/06/25時点の最新バージョンはv0.40.3

### 4. nvm.shを実行する
```bash
\. "$HOME/.nvm/nvm.sh”
```
### 5. nvmのバージョンを確認
```bash
nvm --version
```
### 6. Node.js をインストール（長期サポート版）
```bash
nvm install --lts
```
### 7. Nodeのバージョンを確認する
```bash
node -v
```
### 8. 有効になっている Node.jsのバージョン を確認する
```bash
nvm current
```
### 9. npmのバージョンを確認する
npmはNode.js のパッケージ管理ツール
```bash
npm -v
```
### 10. 完了

### その他
#### 利用可能なバージョン一覧
```bash
nvm ls
```
#### 他のバージョンをインストール
```bash
nvm install 'バージョン番号'
```
#### バージョンの切り替え
```bash
nvm use 'バージョン番号'
```

## Windows
### 1. PowerShell またはコマンドプロンプトを開く
### 2. バージョンを確認する
バージョンが表示されない場合はNode.jsのインストールする
```powershell
node -v
```
### 3. nvm-windows をインストールする
以下のURLから最新版のインストーラをダウンロードする
https://github.com/coreybutler/nvm-windows/releases
- nvm-setup.exe
### 4. インストーラに従ってインストールを完了する
基本はすべてデフォルトのままでOK
### 5. nvm のバージョンを確認する
```powershell
nvm version
```
### 6. Node.js をインストール（長期サポート版）
```powershell
nvm install lts
```
### 7. Nodeのバージョンを確認する
```powershell
node -v
```
### 8. 有効になっている Node.jsのバージョン を確認する
```powershell
nvm current
```
### 9. npmのバージョンを確認する
```powershell
npm -v
```
### 10. 完了

### その他
#### 利用可能なバージョン一覧
```powershell
nvm ls
```
#### 他のバージョンをインストール
```powershell
nvm install 'バージョン番号'
```
#### バージョンの切り替え
```powershell
nvm use 'バージョン番号'
```
CursorとCodexで開発して感じた“使い分け”のススメ

## CodexとCursorで「ど素人」が開発してみた話
最近、CodexとCursorを使ってちょっとした開発をやってみました。プログラミングの経験はほぼゼロに近い自分でも、想像以上にいろいろできて驚きました。その体験を、所感ベースでまとめてみます。

### Codex、もはやベンダー説
これまでのAIツールって、「ペアプロ相手」という印象が強かったんですが、Codexはちょっと違いました。
要件を出すと、まるで外注先のベンダーみたいにシステム全体を作ってくれる感覚です。
細かく指示を出すと、それなりに形になるものが返ってくるのが面白いです。

### デバッグ知識ゼロでもなんとかなった
ローカル環境での動作確認やエラー解析も、CursorやGitHub Copilotがあればなんとかなります。
エラー内容をそのまま聞けば、それっぽい解釈と対処法を返してくれるので、初心者でも手探りで修正できます。
エディタ上でそのままやり取りできるのも快適です。

### 不具合の原因、だいたいこっち側
正直、Codexが生成するコードの多くは人間側の指示の悪さが原因で動きません。
存在しないAPIでも、それっぽく実装しようとする力技のせいで、余計なコードが増えて失敗することも。
「これ、そもそも実現可能な仕様なんだっけ？」という 事前調査がかなり大事 だと痛感しました。

### テストも外注感覚でやるべし
動作確認は、ベンダーから納品されたコードの受け入れテストくらいのつもりでやるとちょうど良いです。
「動けばOK」ではなく、「ちゃんと仕様通りか？」の観点で見ないと、あとで痛い目見そう。

## Codex vs Cursor：ちょっとした修正での挙動比較
### 軽微な修正をやらせてみた
・Codexにやらせたら、関係ない部分まで削除されてしまった。
・Cursorにやらせたら、必要な箇所だけをちゃんと修正してくれた。
これは私のプロンプトが悪いと思うが、Codexに必要以上の部分を消されると焦る。
ブランチも更新されているので、リセット処理も面倒。
一方CursorであればそもそもCommitすらされていないので、微調整はきがるにおこなえる

### 使い分けがポイント
大枠の構築はCodexに任せる
細かい修正やチューニングはCursorで行う

この運用がいちばん効率良さそうです。

#### ブランチとコミットログの話
Codexは毎回ブランチを切って修正してくれるので、Gitの履歴は残ります。これはこれでありがたい。
一方、Cursorはローカルの世界で静かに修正してくれるので、ログに残したくない細かい修正なんかに便利です。

興味本位で触り始めたものの、ツールの進化にかなり驚かされました。
とくに非エンジニア層や初学者にとって、こういうツールは「とっつきにくさ」を大きく下げてくれる気がします。
AIには書けない「味」のあるコードを書く方法

# はじめに
人類は、ずいぶん昔から自分の足で走るより早く移動できる手段を持っています。
荷物を届けたり、伝令を伝えたりするのにもう健脚は必要ありません。

馬や自転車、自動車の登場によって飛脚や急使のような仕事は失われました。
しかし、現代でもウサイン・ボルトは100億円以上を稼ぎ、ランニング市場は順調に成長しています。
これは、「**人類が**100mを9.58秒で走るシーン」「これまで5kmしか走れなかった**自分が**今では10km走れるようになっていること」に価値を感じる人が多いからだと思います。

ランニングには興味が無い方でも、例えば「工場で大量に印刷された名作絵画よりも**子供が**学校で描いてきた絵を飾りたい。」「売られている綺麗な湯呑みよりも、旅先で**自作した**不恰好な湯呑みの方がお気に入り」などに置き換えると分かって頂けるのでは無いでしょうか。

プログラミングも同じで、今後は「**人類が**書いたコード」や「**自分で**書いたコード」に新しい価値が生まれるのではないかと思います。
人の手によるコーディングには、AIには出せない「味」があります。

「味」の出し方を学んでいきましょう。

# インデントにコードを説明させない
AIが出力する綺麗なコードには特徴があります。
それは、インデントが一貫していてぱっと見ただけで変数のスコープやブロックの範囲が分かるようになっていることです。`{}`でブロックを表現する言語でも、やはりインデントはされていた方が格段に読みやすいです。

chatGPTにfizzBuzzを行うコードを生成してもらうと、下記のように一目で`i`のスコープが分かり、どこからどこまでが`for`ループの範囲なのかが分かるように書いてくれます。
```fizzbuzz.c
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 100; i++) {
        if (i % 15 == 0) {
            printf("FizzBuzz\n");
        } else if (i % 3 == 0) {
            printf("Fizz\n");
        } else if (i % 5 == 0) {
            printf("Buzz\n");
        } else {
            printf("%d\n", i);
        }
    }
    return 0;
}

```

ここに「味」を足していきます。
可読性は下がりましたが、人の手が加わったことで「あたたかみ」が加わりました。
インデントは、コードの可読性を上げるためではなく自己表現に使いましょう。

```fizzbuzz_handmaid.c
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 100; i++) {
    if (i % 15 == 0) {
        printf("FizzBuzz\n");
        } else if (i % 3 == 0) {
            printf("Fizz\n");
        } else if (i % 5 == 0) {
            printf("Buzz\n");
    } else {
        printf("%d\n", i);
    }
        }
    return 0;
}

```

# ファイル名、関数名、変数名に内容を説明させない
AIが書いたコードはファイル名、関数名、変数名全てに適切な命名がされていることが多く、なれない言語で書かれたコードでも英文が読める方ならある程度スムーズに読むことができます。
分かりやすいのは良いのですが、目に映る全てのものに意味があると、看板まみれの大都会のようで疲れてしまいます。

chatGPTに、

- 陸上選手の歴代収入ランキングを表示するページのhtmlファイル
- 選手の名前を入れる変数と選手の収入を入れる変数
- 年収で順位づけする関数

をそれぞれ命名してもらいました。

- `track_athlete_income_ranking.html`

```c
// 選手の名前
char athlete_name;
// 選手の収入
double annual_income;
// 年収で順位づけする関数
void rankAthletesByIncome(struct Athlete athletes[], int n);
```

過不足なく必要な情報が入った命名で、後から改修やデバッグがスムーズに行えそうです。

しかし、「味」がありません。私なら例えば下記のように命名します。

- `asigahayai_toiudakede_ore_yori_nanbaimo_kaseideru_hitotati.html`

妬む気持ちが前面に現れた良いファイル名です。後任者に当時の筆者の心情をありありと伝えることができます。

```c
// 選手の名前
char happy_birthday;
// 選手の収入
double to_me;
```

選手の名前を入れる変数、収入を入れる変数を作った日が私の誕生日だとしたらこうします。
社内に誕生日の方がいたら、積極的に変数名にしてあげると良いでしょう。レビュワーや上司の誕生日をコードで祝うことができたなら、次回の査定にも良い影響があるでしょう。

```c
// 年収で順位づけする関数
void fanc_a(struct Athlete happy_birthday[], int birthday);
```

気分が乗らない日に嫌いな上司に頼まれたタスクなら、関数名には無理に凝らなくても構いません。
作った順番に、`fanc_a`,`fanc_b`,...,`fanc_z`とすればいくらでも命名できます。`fanc_z`まで来たら、`fanc_aa`からまた始めましょう。

引数は、`happy_birthday`と命名された変数を受け取ることが決まっているのでそれに合わせて当然`(struct Athlete happy_birthday[], int birthday)`としました。

# コメントにはポエムを書く
コメントには何を書いてもかまいません。
その日の気分、筋トレの記録、好きなアニメの二次創作小説などを書くことで良い気分転換になります。

レビュワーと趣味があえば感想のコメントをもらえるかもしれません。

AIが書く、つまらなく分かりやすいコメントと差別化することができます。

# おわりに
私たちの仕事は、まだ陸上選手ではなく飛脚です。
むやみな味付けは控えましょう。
React Native × EAS Buildについて

皆さん、こんにちは。

今回は「React Native × EAS Buildについて」について紹介させていただきます。

# EAS Build とは？

EAS Build は、React Native（および Expo）プロジェクトのクラウドバイナリビルドサービスです。

## 主な特徴：

- クラウドで iOS / Android のバイナリ（.apk / .aab / .ipa）を生成
- ローカル環境不要（Xcode や Android Studio が不要）
- GitHub Actions などと組み合わせて CI/CD パイプラインにも対応
- OTA（Over-the-Air）アップデートと連携可能（eas update）

# EAS Build の使い方

## インストール

```
npm install -g eas-cli
eas login

eas build:configure
eas build --platform all --profile production
eas build --platform android --profile development
```

# 開発者のためのベストプラクティス

## 新アーキテクチャ（New Architecture）対応

Expo SDK 52以降は newArchEnabled: true がデフォルト。

```
{
  "build": {
    "production": {
      "android": {
        "buildType": "apk",
        "newArchEnabled": true
      }
    }
  }
}
```

互換性チェックには npx expo-doctor を活用！

## ビルドキャッシュの活用

同じソースからの再ビルドではキャッシュが利用され、時間を節約できます。

```
eas build --platform android --cache
```

##  Secrets（APIキーなど）の管理

環境変数は .env ではなく、eas secret を使うのがベストです。

```
eas secret:create --name API_KEY --value xxxx
```

## eas submit でストア提出も自動化！

EAS Build でビルド後、App Store / Google Play に提出するには：

```
eas submit --platform ios
eas submit --platform android
```

今日は以上です。

ありがとうございました。
よろしくお願いいたします。
OpenVPNの“トンネルを張る”って、結局なにしてるの？仕組みとレイヤーを追ってみた

# OpenVPNがやってること：仮想NICから出口IP固定までの流れを追ってみた

## ✅ この記事について

この投稿は、次のような方を想定して書いています：

- VPNを「なんとなく便利」で使っていて、仕組みをちゃんと知りたい人
- 「なぜ出口IPが変わるのか？」にモヤモヤしている人
- OpenVPNの内部動作（tap0,  暗号化, NATなど）をざっくりでも把握したい人

**この記事で扱うこと：**

- OpenVPNの接続確立後、パケットがどう流れるか
- 仮想NIC（tap0/tun0）と暗号化処理の流れ
- NATによる出口IP固定のしくみ
- 通信レイヤーとの関係（L3〜L7ざっくり）

**この記事では扱わないこと：**

- OpenVPNの設定手順（証明書の作り方など）
- 各OSごとの実装や挙動の違い（今回は Linux 視点多め）
- WireGuard や IPSec など、他の VPNプロトコルとの比較


## 🧭 OpenVPNとは？

仮想プライベートネットワーク技術を使って、サイト間・ポイントツーポイント間に安全な通信経路を作るVPNプロトコル。オープンソースで、広く使われています。

「VPNは便利だけど、実際なにしてるの？」  
tap0って？出口IPがなぜ変わるの？通信はどう通ってるの？  
そんな疑問を、自分で調べながら理解して、整理した内容です。



## 🛠 OpenVPNの接続が確立するまで

1. クライアントとサーバーが、証明書などを使って接続します。
2. クライアント側のOSに仮想NIC（例：`tap0` または `tun0`）が作られます。
   - OpenVPNサーバーが、仮想NICにIPアドレスを割り当てます。
     - Windowsでは自動でやってくれました。Linux（私の環境）は手動でした。Macは試してないので不明。
3. クライアントの全トラフィックが仮想NICに向くよう、OSがルーティングを書き換えます。


## 🌐 接続後の通信の流れ （Googleサイトへのアクセスを例に）

1. Googleのサイトを見たくなった私は、宛先がGoogleなIPパケットを作成（便宜上、**元パケット**と呼びます）。
2. OpenVPNクライアントは、「元パケット」を**まるごと暗号化**して、パケット（便宜上、**包みパケット**と呼びます）を作ります。
   - 「包みパケット」の**宛先IPは会社のVPNサーバー**。
   - 「元パケット」の中身（宛先IPはGoogle）は、暗号化されて包まれています。
3. サーバーが「包みパケット」を受け取り、中身を開梱＆復号化。
4. サーバーが「元パケット」をGoogleに送信。
   - このとき、送信元IPはサーバー自身のIPに**NAT変換**されるため、Googleから見ると「会社からのアクセス」に見えます。
5. Googleが返してきたレスポンスを、サーバーが暗号化し、また「包みパケット」にしてクライアントへ戻します。
6. クライアントは包みを開けて、中身のパケットを受信します。


:::note info
  **補足：`tap0` と `tun0` の違い（ざっくり）**  
 - `tap0`：Ethernetフレーム（L2）を扱う仮想NIC。ブリッジ構成や複雑なネットワーク向け  
 - `tun0`：IPパケット（L3）専用の仮想NIC。VPN用途では `tun` が使われることが多い  
 👉 雰囲気でいうと、`tap` は「もっと下」、`tun` は「ちょっと上」です。
:::

## 🧠 レイヤー視点で見ると

- クライアントの仮想NIC（L3）に届いたパケットを、OpenVPNプロセス（L7）が**アプリ層として**受け取ります。
- それを暗号化して、L4のUDP（またはTCP）セグメントに乗せて送信。
- さらにL3（IPパケット）→ L2（イーサネットフレーム）→ L1（物理）へと、ネットワークスタックに従って流れていきます。

 💡 この文脈では、L6/L5は特に活躍する場面が少ないです。


## 💬 感想：トンネルってなんだっけ

「トンネル」というと、直通の専用道路みたいなイメージを持っていたのですが、  
実際は「荷物を再梱包して安全に送るためのルート」という方がしっくりきます。

また、VPNって“ピア接続”のような感覚で語られることがありますが、  
物理的には全然ピアではないです。**お互いに一生懸命、包んで包んで、ほどいてほどいて、をやっているだけ**。


## ✅ まとめ

- OpenVPNは、「仮想NIC＋暗号化通信」で安全なトンネルを作ってくれる
- 出口IPが変わるのは、通信の送信元がVPNサーバーに見えるようNATされるから
- tap0/tun0、パケットの包み構造、レイヤー構造まで理解すると、VPNの仕組みが一気に身近になる


## 🚪 次の扉？

WireGuard、気になってます。  
でもまずはOpenVPNを理解できたので、ようやく次の一歩へ進めそうです。
もう querySelector に頼らない！Svelte開発を支える bind:this

# はじめに
Svelte を使っていて、ボタンを押したときにinputをフォーカスしたり、スクロールさせたり、サイズを測ったりしたくなったことはありませんか？
Svelte はリアクティブな記述が魅力ですが、ときには DOM ノード（HTML 要素）に直接アクセスしたい場面も出てきます。
そんなときに登場するのが、`bind:this`構文です。

# 参考にしたドキュメント
https://svelte.jp/docs/svelte/bind#bind:this

# bind:this とは？
`bind:this`は、DOM 要素やコンポーネントの参照を取得するための Svelte 独自構文です。

```svelte
<script>
  let inputEl;

  function focusInput() {
    inputEl.focus(); // DOMノードにアクセス！
  }
</script>

<input bind:this={inputEl} />
<button on:click={focusInput}>フォーカスする</button>
```
このように書くと、inputEl という変数に <input> 要素の参照（DOM ノード）が代入されます。
これにより、JavaScript の通常の DOM 操作（例：focus() や scrollTop）が可能になります。

# どうして bind:this が必要なの？
実際には以下のようなニーズもあります

- 初期フォーカスを当てたい
- 要素のスクロール位置を制御したい
- サイズや位置を測定したい

### ❌ bind:this を使わなかった場合（非推奨例）

```svelte
<script>
  function focusInput() {
    document.querySelector('input').focus();
  }
</script>

<input />
<button on:click={focusInput}>フォーカスする</button>
```
**問題点**

- `document.querySelector()`はグローバルな DOM を検索するため、コンポーネントが複数あった場合に意図しない要素を取得する可能性があります
- DOM の存在を前提としたコードになるため、SSR（サーバーサイドレンダリング）時にクラッシュするリスクがあります([参考ドキュメント](https://svelte.jp/tutorial/kit/ssr))
- Svelteのコンポーネントスコープ外の操作になるため、保守性・再利用性が下がる

### ✅ bind:this を使えば？
```svelte
<script>
  let inputEl;

  function focusInput() {
    inputEl.focus();
  }
</script>

<input bind:this={inputEl} />
<button on:click={focusInput}>フォーカスする</button>
```
- 対象の DOM 要素にだけアクセスできる
- マウント後に値が代入されるため、タイミングが明確
- コンポーネントスコープ内の操作なので保守性が高い

# よくある使い方
### 初期フォーカス
```svelte
<script>
  import { onMount } from 'svelte';
  let input;

  onMount(() => {
    input.focus();
  });
</script>

<input bind:this={input} />
```

### スクロール制御
```svelte
<script>
  let container;

  function scrollToBottom() {
    container.scrollTop = container.scrollHeight;
  }
</script>

<button on:click={scrollToBottom}>一番下へ</button>

<div bind:this={container} style="height: 100px; overflow: auto;">
  <p>たくさんのテキスト...</p>
</div>


```

# コンポーネントにも使える
```svelte
<!-- MyComponent.svelte -->
<script>
  export function sayHello() {
    alert('こんにちは！');
  }
</script>
```

```svelte
<!-- Parent.svelte -->
<script>
  import MyComponent from './MyComponent.svelte';
  let myComp;

  function callChildMethod() {
    myComp.sayHello(); // 子コンポーネントの関数を呼び出す
  }
</script>

<MyComponent bind:this={myComp} />
<button on:click={callChildMethod}>子の関数を実行</button>
```

# 注意点
- bind:this は 初期レンダリング後に値がセットされるため、使うタイミングに注意（onMount()内で使うのが安全）
- コンポーネント参照と DOM ノード参照は 異なる型なので、用途に応じて適切に使い分ける
- TypeScript を使う場合は、HTMLElement 型やコンポーネント型の明示が必要


# おわりに
`bind:this`は、Svelte の宣言的なスタイルを崩すことなく、必要な場面で DOM 要素やコンポーネントインスタンスに安全にアクセスできる、非常に便利な機能です。
普段はリアクティブな記述で完結できる Svelte ですが、どうしても imperative（命令的）な処理が必要になる場面は出てきます。そんなときでも bind:this を使えば、Svelte の設計思想を尊重しながら柔軟な実装が可能になります。
「いつ、なぜ使うのか」「使わなかった場合にどうなるか」をしっかり理解しておくことで、より保守性が高く、バグの少ないコードを書くことができます。特にコンポーネントの再利用や SSR を考慮するプロジェクトでは、その恩恵を実感できるでしょう。
最後までご覧いただきありがとうございました！
【Go】弱いハッシュ関数を自作、衝突耐性を突破するサンプルコード


## 概要

- [**暗号技術入門 第3版**](https://amzn.asia/d/4EzqngT)に出てきたハッシュ関数を自作してみた。
- 衝突を検出する関数も書いてみた

## サンプルコード


### ハッシュ関数


```go
func fakeOneWayHash(s string) int {
	hash := 0

	// 文字列の各文字について処理
	for _, r := range s {
		// 単純な加算と乗算のみを使用
		hash = hash*31 + int(r)
	}

	// 正の32ビット整数に変換
	return hash & 0x7FFFFFFF
}

// 実行結果
// fakeOneWayHash("cat")
// ハッシュ値: 98262
```


### _第二現像攻撃による弱衝突を検出する関数_


```go
func verifyWeakCollision(targetString string) {
	targetHash := fakeOneWayHash(targetString)
	fmt.Printf("対象文字列: %s\n", targetString)
	fmt.Printf("対象ハッシュ値: %d\n", targetHash)

	// 小文字、大文字、数字を含む文字セット
	letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
	found := false

	// 3文字の全パターンを総当たり
	for _, c1 := range letters {
		for _, c2 := range letters {
			for _, c3 := range letters {
				s := string([]rune{c1, c2, c3})
				if fakeOneWayHash(s) == targetHash && s != targetString {
					fmt.Printf("衝突を発見: %s (ハッシュ値: %d)\n", s, fakeOneWayHash(s))
					found = true
				}
			}
		}
	}

	if !found {
		fmt.Println("衝突する文字列は見つかりませんでした")
	}
}

// 実行結果
// verifyWeakCollision("cat")
// 対象文字列: cat
// 対象ハッシュ値: 98262
// 衝突を発見: cbU (ハッシュ値: 98262)
// 衝突を発見: cc6 (ハッシュ値: 98262)
// 衝突を発見: dBt (ハッシュ値: 98262)
// 衝突を発見: dCU (ハッシュ値: 98262)
// 衝突を発見: dD6 (ハッシュ値: 98262)
```


### _衝突攻撃による強衝突を検出する関数_


```go
func verifyStrongCollision() {
	// ハッシュ値と文字列のマッピングを保持するマップ
	hashMap := make(map[int]string)
	letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
	found := false

	// ランダムな文字列を生成して衝突を探す
	for i := 0; i < 1000000; i++ { // 最大100万回試行
		// 3文字のランダムな文字列を生成
		s := string([]rune{
			letters[rand.Intn(len(letters))],
			letters[rand.Intn(len(letters))],
			letters[rand.Intn(len(letters))],
		})

		hash := fakeOneWayHash(s)

		// 同じハッシュ値を持つ文字列が既に存在するかチェック
		if existing, exists := hashMap[hash]; exists && existing != s {
			fmt.Printf("強衝突を発見:\n")
			fmt.Printf("文字列1: %s (ハッシュ値: %d)\n", existing, hash)
			fmt.Printf("文字列2: %s (ハッシュ値: %d)\n", s, hash)
			found = true
			break
		}

		// 現在の文字列とハッシュ値をマップに保存
		hashMap[hash] = s
	}

	if !found {
		fmt.Println("強衝突は見つかりませんでした")
	}
}

// 実行結果
// verifyStrongCollision()
// 強衝突を発見:
// 文字列1: vxX (ハッシュ値: 117206)
// 文字列2: vy9 (ハッシュ値: 117206)
```


## まとめ

- ハッシュ関数は自作せずSHA2-, SHA-3など安全性のあるアルゴリズムを使用しましょう
AIを使用してアーキテクチャ図を描く方法

バイブコーディングを行う際、多くの人はコードだけで十分だと考えがちです。しかし現実は異なります。ドキュメントのないコードは、地図なしで旅立つようなものです。目的地がどこなのか、進む道がどうなっているのかが分からなければ、誰も一緒に旅立とうとはしないでしょう。バイブコーディングにおいてドキュメント化が特に重要な理由は、コードが単に機能するためだけでなく、アイデアや設計の意図を他者と正確に共有するためのものであるからです。ドキュメント化は協業を円滑にし、プロジェクトの方向性を明確にし、さらに持続可能な開発環境を構築する基盤となります。

私は、ドキュメント化作業をコードと共に管理する方法を積極的に推奨します。特にマークダウンとmermaidを使用すれば、シンプルで明確なダイアグラムを迅速に作成できます。複雑な構造や流れを長い説明ではなく、ダイアグラム一つで表現できるため、コミュニケーションがはるかに効果的に行えます。

もちろん、mermaidだけでは不十分な場合もあります。より精巧で複雑なダイアグラムが必要な場合はdraw.ioを利用できます。draw.ioはXMLベースの.drawioファイル形式を使用するため、AIに直接この形式でダイアグラムを生成するように指示すれば、比較的簡単に作業が可能です。ただし、AWSアイコンなどの特定のアイコンのIDは公開されていないため、AIがそのまま活用するのは難しいです。

そのため、私はdraw.ioクライアントからAWSアーキテクチャアイコンのIDを直接抽出し、別途[文書化](https://github.com/serithemage/ecs-fargate-fast-scaleout/blob/main/docs/aws-2025-icons-drawio.md)しました。これにより、AIにアイコンIDを通知し、希望するアイコンを正確に活用できるようにしたのです。このドキュメントは、次の GitHub リポジトリで実際の作業例を確認できます。

[ECS - Fargate Fast Scaleout](https://github.com/serithemage/ecs-fargate-fast-scaleout/)

このように生成されたダイアグラムは、VS Codeのdrawioプレビュー拡張機能を利用すれば、便利にプレビューできます。また、draw.ioクライアントをインストールすれば、付属のCLIツールでSVGやPNG形式の画像に簡単に変換し、文書に挿入することも可能です。

![alt text](https://raw.githubusercontent.com/serithemage/ecs-fargate-fast-scaleout/abbb4dee4d89070692fc4edc0e81a313c910c52b/docs/diagrams/architecture.svg)

一方、最近のmermaidの最新バージョンでは、AWSアイコンを含む多様なアーキテクチャアイコンを標準でサポートし始めました。[公式ドキュメント](https://mermaid.js.org/syntax/architecture.html)を参照すれば、すぐに活用可能です。ただし、GitHubでこの最新機能をサポートするバージョンのmermaidが提供されていない場合、先ほど説明した方法が当面最も有用なアプローチとなるでしょう。

良いドキュメントは単なる説明書を超え、協業の質を向上させ、長期的にプロジェクトの価値を維持します。Vibe Codingでは、ドキュメント化は選択ではなく必須です。
便利すぎる Python の itertools

Python で for 文を書きがちな人！  
**`itertools` を知ってると、同じことがもっと短く、きれいに書ける**かもしれません。

---

## こんなコード書いてませんか...？

たとえばリストの中身を全部組み合わせたいとき、こうやって書いてませんか？

```python
colors = ['red', 'blue']
sizes = ['S', 'M', 'L']

for color in colors:
    for size in sizes:
        print(f"{color} / {size}")
```
出力
```
red / S
red / M
red / L
blue / S
blue / M
blue / L
```

itertools を使うとこうなります！
```python
from itertools import product

colors = ['red', 'blue']
sizes = ['S', 'M', 'L']

for color, size in product(colors, sizes):
    print(f"{color} / {size}")
```

他にも...

```python
data = ['A', 'B', 'C', 'D']
use_flags = [1, 0, 1, 0]
result = []

for d, flag in zip(data, use_flags):
    if flag:
        result.append(d)

print(result)
```
出力
```
['A', 'C']
```

itertools を使うとこうなります！
```python
from itertools import compress

data = ['A', 'B', 'C', 'D']
use_flags = [1, 0, 1, 0]
print(list(compress(data, use_flags)))
```

---

## itertools の魅力

**普段はあまり出番がないかもしれないけど、書けると気持ちいい。そして軽い**

`itertools` は、「この処理、for 文でがんばって書いてたけど、実はもっと簡単に書けるのでは？」というときに効いてくる関数がそろっています。

しかも、多くの関数は**必要なときに1つずつ値を取り出す仕組み**（イテレーター）になっていて、

- 無駄にデータを作らない
- 大きなリストを全部メモリに乗せない
- ループが軽く、処理も速い

という、**実はとても効率的な構造**になっています。

※イテレーターは「値を1つずつ取り出せる仕組み」のことです。 
`yield` を使ってイテレーターを作る関数のことを「ジェネレーター関数」と呼びます。

`yield`やジェネレーターについては以下記事に記載してます！
https://qiita.com/ys-B/items/19511fa0b73e4c0cbfc8

---

## 遅延評価
`itertools` の多くの関数は「遅延評価（lazy evaluation）」になっています。

これは、先述した**必要になったときにだけ値を1つずつ取り出す仕組み**のことです。
たとえば `product()` などは、呼び出した瞬間にすべてのデータを作るのではなく、  
for 文などで使われたとき、**順番に1件ずつ生成**します。

たとえば、以下のように `product()` を使ってみます：

```python
from itertools import product

pairs = product(['A', 'B'], ['X', 'Y'])

print(next(pairs))  # → ('A', 'X')
print(next(pairs))  # → ('A', 'Y')
```

productメソッドが実行された時点では、すべての組み合わせはまだ作られていません。
next() を呼ぶたびに、1つずつ「そのときに生成される」ようになっています。

同じことを内包表記で書いた場合は…

```python
pairs = [(a, b) for a in ['A', 'B'] for b in ['X', 'Y']]
print(pairs)  # → [('A', 'X'), ('A', 'Y'), ('B', 'X'), ('B', 'Y')]
```
全4パターンが作られてメモリに乗っています。


これがitertools の「遅延評価」です。
必要な分だけ、必要なときに、1つずつ処理される。
だから軽く速いです。

(ちなみに、Python を使っている人にはおなじみの Django の `QuerySet` も、実は同じように「遅延評価」になっています。)

---

## itertoolsの便利な関数

| 関数名           | なにができる？                                  | 使用例                           |
|------------------|--------------------------------------------------|----------------------------------|
| `product()`       | すべての組み合わせを出す                        | サイズ × カラーの全組み合わせなど |
| `combinations()`  | リストからn個ずつの組み合わせを出す             | テストケース、ペアの列挙など     |
| `compress()`      | フラグで要素をフィルタリング                    | 条件に合う要素だけ抽出したいとき |
| `count()`         | 無限に連番を出す                                | 自動採番、一時的なID付けなど     |
| `groupby()`       | ソート済みデータをグループ化して処理            | カテゴリごとの集計・分類など     |

---

## おわりに

`itertools` は、ふだんのコードではなかなか出番がないかもしれません。

でも、ネストした `for` 文や条件付きのフィルター処理を書いていて  
「なんかもっとスッキリ書けないかな……」と思ったとき、  
ふと `itertools` を思い出せると、**書くのが楽になって、処理も軽くなる**。そんな存在です。

標準ライブラリなので、追加インストールも不要。  
まずは `product()` や `compress()` あたりから、気軽に試してみてください！

```python
from itertools import *
# ↑ 全部読み込んで、手元で遊んでみるのもおすすめです。
Claude codeとGoogle Geminiを使って、自身ではプログラムも設計書も1行も書かずにアプリを作った所感~人間編

## 人間として感じたAIの凄さとショボさ
### 概要
[Claude codeとGoogle Geminiを使って、自身ではプログラムも設計書も1行も書かずにアプリを作った所感](https://qiita.com/KLaboratory/items/ff441405bdddf09d7e59)という記事で、Claude codeとGoogle Geminiを使ってアプリを作成たということをGoogle Geminiに書いてもらいました。今回は自分が思ったことを自分で書きます。長所についてはGeminiが散々持ち上げてくれましたので、違和感を覚えたり、ちょっと残念だったり、人間が工夫しないといけなかったりするところを上げていきます。
### 宵越しの銭は持たないAI
一番の違和感と残念な点がここ。昨日のことは全く覚えていない。昨日の続きの開発を行おうと思ったのに、全く違うフォルダに出力を始めたり、前日と全く整合性のない実装を始めたりで、**人間が行うよりも酷い手戻り**が発生していました。全記事で『手戻りなく、スムーズに動くものが出来上がりました。』とあるのは、あくまで一気通貫で最後まで行った場合です。

Claude codeで節約を考えずにガンガン実装していくと、Claude Opus4のリミットにすぐに達します。途中からClaude Sonnet4に切り替わりますが、連続して作業する分には、この程度の難度のアプリでは全く違和感なく、また差異のないプロダクトができあがります。一方で、一旦作業終了して翌日再開するとOpus4→Opus4であってもこのようなことが起こります。

従って、手戻りなく完成させるためには、一気に作り上げるか、少なくともログアウトすることなく立ち上げたままにしておく必要があると思いました。もしかしたら、筆者が無知でちゃんと記憶の保存方法があるのかもしれません。あったらぜひ教えて下さい。
### スクラムはできない？ ###
要件定義書と外部仕様書を渡すだけでほぼ完璧なものを作ってくれましたが。実は、外部仕様書をClaude codeに渡したとき、
「認証機能のみを実装してください」
と指示したのです。そして出来上がりましたというのを見たらすべての機能が実装されていたというのが実際のところです。あまり難度の高くないアプリなので、AIからしたら鼻歌交じりでもできます。いうなれば、**ショパンコンクールに出るようなピアニストに、正しく椅子に座って、ドレミファソラシドを弾いてください**と言っているようなものです。

仮に、要件定義や外部仕様が完璧なものであったら全く問題ないですね。むしろ一気に作ってくれたほうがいい。しかし、要件も仕様も完全ではないのに実装が始まるというのは現実世界ではよくあることです。また、スクラムのように細かくリリースするようなときも、**最後までできている外部仕様書**を読み込ませたら、勝手に最後まで作られてしまいます。ここは、どのように指示を出せばいいのか？あるいは、仕様書もスクラムごとに読ませればいいのかなど、私の研究課題です。
### mainブランチしかいらない？
gitの管理も、mainブランチを順次コミットすればいいようなものとなってしまいました。最初は認証機能用ブランチを作ってみたのですが、次のプレイリスト表示機能以降も実装されてしまったので、マージして、ちょっと手直ししてまたマージで終わってしまいました。これも更に研究しないといけない・・・

## まとめ
ということで、私自身の創意工夫の余地が増えたというのが正直な感想です。
LambdaTypeはFunctionTypeでBuiltinMethodTypeはBuiltinFunctionType

明日使えそうな豆知識

```python
from types import FunctionType, LambdaType, BuiltinFunctionType, BuiltinMethodType

print(LambdaType is FunctionType) # True
print(BuiltinMethodType is BuiltinFunctionType) # True
```

## LambdaTypeとFunctionTypeの等価性

Python標準ライブラリの[`types`](https://docs.python.org/ja/3/library/types.html)にはユーザ定義の関数の型として`FunctionType`、`LambdaType`が用意されている。
一見すると`LambdaType`はラムダ式専用の型に思えるが、実はそうではない。
どちらも`def f()`の型であり、`lambda: ...`の型でもある。
さらに言うならば両者は同じオブジェクトである。

```python
from types import FunctionType, LambdaType

def f(): pass
lambda_f = lambda: ...

print(isinstance(f, FunctionType)) # True
print(isinstance(f, LambdaType)) # True
print(isinstance(lambda_f, FunctionType)) # True
print(isinstance(lambda_f, LambdaType)) # True
print(FunctionType is LambdaType) # True
```

このことはcpythonの`types`の[ソースコード](https://github.com/python/cpython/blob/main/Lib/types.py)にもコメントとして記載されている。

```python:cpython/Lib/types.py
def _f(): pass
FunctionType = type(_f)
LambdaType = type(lambda: None)  # Same as FunctionType
```

なお、どうしてもラムダ式かどうかを判定したい場合、`__name__`が`<lambda>`であるかを見ればよい。

```python
def f(): pass
lambda_f = lambda: ...

print(f.__name__) # f
print(lambda_f.__name__) # <lambda>
```

## じゃあLambdaType用意する必要ある？

これについては、[Stack Overflow](https://stackoverflow.com/questions/62479608/lambdatype-vs-functiontype)でPython作者であるGuidoが次のように答えている。

> Back in 1994 I wasn't sure that we would always be using the same implementation type for lambda and def. That's all there is to it. It would be a pain to remove it, so we're just leaving it (it's only one line). If you want to add a note to the docs, feel free to submit a PR.

未確認だが、`BuiltinFunctionType`と`BuiltinMethodType`にも同様の事情があるのではないかと推察する。
ちなみにこの二つの場合は`__self__`属性を持っているかどうかでメソッドか区別できる。
【rails】Stimulus flapicker導入


## はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
現在 Rails でアプリ開発を進めており、日付や時間を選択する機能を実装するにあたって、手軽に使える Stimulus Flatpickr を採用しました。
本日はその導入方法について記事にしたいと思います。

### 開発環境

* Ruby on Rails 8.0.2
* Ruby 3.4
* Devcontainer

---

## どんなUIになるか

細かいUIはCSSで調整できますが、概略的に以下のようなUIになります。日付をクリックするとカレンダーが表示され、そこから日付を選択できるUIです。

![stimulus\_flapicker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3883070/bf569f2a-6cc7-498f-82ad-0a714e82b403.gif)

---

## 導入手順

### 1. flatpickr をインストール

Rails 7以降は importmap がデフォルトとなっているので、importmapを使用する前提で進めます。

以下をターミナルで実行します:

```bash
bin/importmap pin flatpickr stimulus-flatpickr@beta
```

その後、`config/importmap.rb`に以下が含まれていることを確認しましょう:

```ruby
pin "flatpickr" # @4.6.13
pin "stimulus-flatpickr" # @3.0.0
```

---

### 2. Flatpickrコントローラを追加

`app/javascript/controllers/index.js`に Flatpickr を import します:

```js
import { application } from "controllers/application";
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading";

eagerLoadControllersFrom("controllers", application);

// 追記
import Flatpickr from "stimulus-flatpickr";
application.register("flatpickr", Flatpickr);
```

---

### 3. CSS の追加

`app/views/layouts/application.html.erb`の `<head>` 内に FlatpickrのCSSを追加します:

```erb
<%= javascript_importmap_tags %>
<!-- Flatpickr CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
```

---

### 4. フォームに適用

`f.text_field` に Stimulus コントローラを適用します:

```erb
<div>
  <%= f.text_field :due_at,
        data: {
          controller:              "flatpickr",
          "flatpickr-enable-time": "true",
          "flatpickr-time_24hr":   "true",
          "flatpickr-date-format": "Y-m-d H:i",
          "flatpickr-alt-input":   "true",
          "flatpickr-alt-format":  "n月j日 H:i",
          "flatpickr-locale":      "ja"
        },
        class: "w-40 pl-1 pr-3 py-2 border border-gray-300 rounded \
                bg-white focus:outline-none cursor-pointer" %>
</div>
```

---

## まとめ

Stimulus Flatpickr を使うことで、Rails フロントで手軽にカレンダー付きの日付/時間選択UIを実現できます。
バニラではなく Stimulus を使うことで、Railsとの統合性も良く、簡単に実装できるのが魅力です。

---

## 参考資料

https://github.com/adrienpoly/stimulus-flatpickr
【Supabase初心者メモ】リレーションの取得

Supabaseにおいて、リレーション（関連テーブル）データの取得方法は大きく分けて2通りあります。
# 方法1：暗黙的リレーション

外部キーのリレーションを自動で推測し、その名前を省略して関連テーブルのデータを取得できる方法です。つまり、外部キー制約が設定されていれば、テーブル名(取得カラム...) の形だけで簡単にリレーション先のデータを取得できます。

基本：
```
const { data, error } = await supabase
  .from('親テーブル名')
  .select(`
    親のカラム1,
    親のカラム2,
    関連テーブル名 (
      関連テーブルのカラム1,
      関連テーブルのカラム2
    )
  `);
```
例：
```
const { data, error } = await supabase
  .from('posts')
  .select(`
    id,
    title,
    content,
    users ( id, name )
  `)
```


## 方法2：明示的リレーション
リレーション（外部キー）を使って関連テーブルのデータを取得する際に、どのテーブルのどの外部キーを使うかを明確に指定する方法です。特に、外部キーが複数ある場合、取得するリレーションに別名をつけたい場合に役立ちます。

基本：
```
<エイリアス>:<参照先テーブル>!<外部キー名> ( <取得カラム1>, <取得カラム2>, ... )
```
例：
```
const { data, error } = await supabase
  .from('posts')
  .select(`
    id,
    title,
    content,
    author:users!posts_author_id_fkey ( id, name )
  `)
```
【Firebase Studio】ToDoアプリケーションを作成してみる

生成AIでコーディングするときのプロンプトも作ってみたかったですし、暇つぶしにFirebase Studioで遊んでみました.

フォームまでは作成できましたが、登録を押すと、ずっと処理中になります.
今のところ、すべての出力が、英語のみのでした...

Clade派なので、Clineで試してみようかなー
プロンプトエンジニアリングについても学ぶ必要がありますね.

# Video
<iframe width="560" height="315" src="https://www.youtube.com/embed/3ttmVcmDiyE?si=qoFWbDl8xRHPP3fu" 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>

# Prompt(Image)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498946/c5ad1cf6-ba97-4b8a-a44e-8329703c3166.png)

# Prompt(Text)
```
# アプリ名
ToDo

## 概要
ToDoの作成・一覧ができるWebアプリケーション

## 技術仕様
    言語: JavaScript
    DB: Firestore

## UI
image.pngを参照

### 作成セクション
    薄い灰色背景の箇所
    入力フォームとなっている箇所は、inputタグで作成
    日時は、datetime-local
    プルダウンは、selectとoptionで、「低」「中」「高」
    テキストは、text

### 一覧セクション
    薄い青色背景の箇所
    完了の横は、inputタグのcheckboxで作成

## 機能

### 作成セクション
    登録を押下すると、Cloud Firestoreに登録
    優先度は、低が「1」、中が「2」、高が「3」

#### エラーハンドリング
    タイトルが、空文字の場合はエラーメッセージ
    期限日時に、過去の日時を指定した場合はエラーメッセージ

### 一覧セクション
    未完了のToDoの一覧を表示
    表示順は、優先度と期限日時の順番で降順
    完了にチェックを入れたら、非表示にし、Cloud Firestoreの完了に更新

#### エラーハンドリング
    なし

## DB
    title      (string): タイトル
    priority      (int): 優先度(低:1、中:2、高:3)
    dueDate (timestamp): 期限日時
    completed (boolean): 完了(未完了:false(デフォルト)、完了:true)

```
最近VBA

ボタンをまずは作成する

https://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/vba2013/01-intro03.html

複数行のセル内情報の取得方法

```
Sub zz()
    'アクティブなセルを取得
    Dim sentence As Variant

    sentence = Cells(1, 1).Value
    
    '改行コードごとに文字列を分割
    Dim tmp As Variant
    tmp = Split(sentence, vbLf)
    
    Dim i, j As Integer
    Dim deleteCharPlace As Long

    j = 0
    
    For i = 0 To UBound(tmp)
        '下のセルに貼り付け
            Cells(i + 2, 2) = tmp(i)
            
    Next
    
End Sub
```

次に処理を記載する

https://www.skygroup.jp/tech-blog/article/886/


いつか使う日の時まで

```

Sub test()

' シートを指定
    Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
    
' 最終列を取得
    Dim lastColumn As Long: lastColumn = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
    
' 最終行を取得
    Dim lastRow As Long: lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
    
' 結果を表示
    MsgBox "最終行は " & lastRow & " 行目です。"
    

For retsu = 2 To lastColumn

  File_Name = Cells(1, retsu).Value
  
  

  Open "C:\Users\xyz\OneDrive\デスクトップ\bash\awk3\awk3\" + File_Name + ".awk.awk2.awk3" For Input As #1


  Do Until EOF(1)

    Line Input #1, buf
    
      For row1 = 2 To lastRow
      
      'yyy = Cells(row1, 1).Value
      
    
        result = StrComp(buf, Cells(row1, 1).Value)
    
        If result = 0 Then
      
           Cells(row1, retsu).Value = "〇"
      
        End If
      
      
      Next row1


  Loop
  
  Close #1


Next retsu


End Sub
```
cloudwatchagentで、メモリとログを監視する

cloudwatchagentで、メモリとログを監視する

対象プロセスは下記コマンドで確認する
ps -ef

対象としたいプロセスを"pattern"の後ろに記載する

```
{
  "agent": {
    "metrics_collection_interval": 60,
    "logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log",
    "run_as_user": "root"
  },
  "metrics": {
    "append_dimensions": {
      "InstanceId": "${aws:InstanceId}",
      "HostName": "${host}",
      "Role": "server1"
    },
    "metrics_collected": {
      "mem": {
        "measurement": [
          "mem_used_percent"
        ],
        "metrics_collection_interval": 60
      },
      "procstat": [
        {
          "pattern": "amazon-cloudwatch-agent",
          "measurement": ["cpu_usage", "memory_rss", "pid_count"]
        },
        {
          "pattern": "rsyslog",
          "measurement": ["cpu_usage", "memory_rss", "pid_count"]
        },
        {
          "pattern": "falcon-sensor",
          "measurement": ["cpu_usage", "memory_rss", "pid_count"]
        },
        {
          "pattern": "csfalcon",
          "measurement": ["cpu_usage", "memory_rss", "pid_count"]
        }
      ]
    }
  },
  "logs": {
    "logs_collected": {
      "files": {
        "collect_list": [
          {
            "file_path": "/var/log/messages",
            "log_group_name": "/var/log/messages",
            "log_stream_name": "{hostname}/messages",
            "timestamp_format": "%b %d %H:%M:%S"
          },
          {
            "file_path": "/var/log/cron",
            "log_group_name": "/var/log/cron",
            "log_stream_name": "{hostname}/cron",
            "timestamp_format": "%b %d %H:%M:%S"
          },
          {
            "file_path": "/var/log/access.log",
            "log_group_name": "/var/log/access.log",
            "log_stream_name": "{hostname}/access",
            "timestamp_format": "%Y-%m-%d %H:%M:%S"
          }
        ]
      }
    }
  }
}
```

起動手順

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
  -a fetch-config \
  -m ec2 \
  -c file:/opt/aws/amazon-cloudwatch-agent/bin/config.json \
  -s

設定ファイルは消滅するが
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent-tomlに保存される
IT初心者メモ CentOSとUbuntu (ディストリビューション)

# CentOS
### 掲げているスローガン
「コミュニティによるエンタープライス級のOS」
商用で使える圧倒的高品質のOSを目指す

### 派生元とスタイル
CentOSのベースはRed Hat Enterprise Linux (RHEL)

# Ubuntu
### 掲げているスローガン
「誰にでも使いやすい最新かつ安定したOS」
Linuxはもっと普通の人にもちゅかえるものにできる、という思想が見えるのがUbuntu。実際とても使いやすく、Windowsの代わりとして使えるようなOS。

### 派生元とスタイル
UbuntuのベースはDebian

# 終わりに
時間があるとき追記します。
【Next.js】referenceerror: await is not defined next cloudflareの解決方法

# はじめに
本記事では、`Next.js`で`Cloudflare Pages`を利用する際に発生したエラーと、その解決方法について紹介します。

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

# 現象
`npm run dev`を実行したところ、`next.config.ts`内で以下のようなエラーが発生しました。

```bash
await (0, _nextdev.setupDevPlatform)();
    ^
ReferenceError: await is not defined
```

# 原因
このエラーの原因は、`next.config.ts`が***CommonJS モジュールとして解釈されるため***、トップレベルで `await`を使用できない点にあります。

以下のような記述が原因でエラーになります：

```next.config.ts
import type { NextConfig } from "next";
import { setupDevPlatform } from "@cloudflare/next-on-pages/next-dev";

const nextConfig: NextConfig = {
  /* config options here */
};

if (process.env.NODE_ENV === "development") {
  await setupDevPlatform(); 
}

export default nextConfig;
```

# 解決方法
ファイルの拡張子を`.ts`から`.mjs`に変更することで、ESM（ECMAScript Modules）として扱われ、トップレベルで await を使用できるようになります。

`next.config.mjs`に変更し、型アノテーション（TypeScript特有の記法）も削除します：

```next.config.mjs
import { setupDevPlatform } from "@cloudflare/next-on-pages/next-dev";

const nextConfig = {
  /* config options here */
};

if (process.env.NODE_ENV === "development") {
  await setupDevPlatform();
}

export default nextConfig;

```

# 終わりに
`Cloudflare Pages`と`Next.js`を組み合わせて開発を行う際、ローカル開発用の設定でESMの構文が必要になることがあるようです。

# 参考

https://nextjs.org/docs/app/api-reference/config/next-config-js

https://wp-kyoto.net/when-encounted-to-await-is-not-defined-error-on-next-on-pages/
Claude Code 完全ガイド（v1.0.22対応）

# 🚀 Claude Code 完全ガイド（v1.0.22対応）

Claude Codeは、Anthropicが提供するAIアシスタント「Claude」を**コマンドラインから活用するための強力なツール**です。継続的なアップデートにより、対話、コード編集、ツール拡張、UI改善など多岐にわたる機能が追加されています。

本記事では、**バージョン1.0.22**時点での主な機能を網羅的に紹介します。

---

## 💬 1. Claudeとの対話と制御の最適化

Claude Codeは、Claudeとの**インタラクションを柔軟かつ効率的に制御**できるよう進化しています。

### 主な機能

- ✅ **リアルタイム対話**  
  Claudeが作業中でもメッセージ送信が可能。即座に指示や修正ができます。

- 🧠 **思考モードのトリガー**  
  `think` / `think harder` / `ultrathink` で高度な計画立案を促進（多言語対応）。

- 🛑 **即時中断**  
  オートアセプトモード中でも `ESC` キーで即停止。

- 🙈 **思考プロセスの非表示**  
  環境変数 `DISABLE_INTERLEAVED_THINKING` を設定。

- 📝 **メモリへの迅速な追加**  
  `#` で始まるメッセージはClaudeのメモリへ即追加。

- 🔄 **会話の再開**  
  `claude --continue` や `claude --resume` で中断会話を復帰。

- 🔁 **会話の自動圧縮**  
  長文対話が自動で圧縮され、コンテキスト保持が向上。

---

## 🗂 2. ファイル・コード編集・コンテキスト管理の効率化

ファイル操作・コード編集が圧倒的にスムーズになります。

### 主な強化点

- 📂 **ファイル/フォルダの@メンション**  
  `@ファイル名` や `@フォルダ名` で直接コンテキストに追加。

- 🖼 **画像追加の改善**  
  ドラッグ＆ドロップやペースト対応。信頼性も向上。

- 🔍 **ファイル名補完**  
  `Tab`キーで補完可能に。

- 🔄 **オートアセプトの切替**  
  `Shift + Tab` でオン/オフ切替。

- 📥 **CLAUDE.mdファイルのインポート**  
  他ファイルを起動時に自動ロード可能に。

- ➕ **作業ディレクトリ追加**  
  `--add-dir` で追加ディレクトリを指定。

- 📌 **複数チャンクのペースト**  
  大規模テキストも一括貼り付け可能。

- 🧾 **ワードレベル差分表示**  
  より詳細なコード差分を確認可能に。

- 🔗 **シンボリックリンクのサポート**

---

## 🛠 3. 豊富なツールでClaudeの能力を拡張

標準機能に加え、多彩なツールでClaudeの活用範囲が広がります。

### 拡張機能

- 🌐 **Web検索**  
  複数クエリを並列実行可能。

- 🔎 **Webフェッチ**  
  URLをClaudeが閲覧可能に。

- 🌐 **ネットワークコマンドの利用**  
  `curl` などを使用可能。

- ✅ **タスクツールの強化**  
  ファイル書き込みやbash実行が可能に。

- 📝 **Todoリスト管理**

- 🚫 **ツール利用制限**  
  `--disallowedTools` で制御。

- 🔧 **ツール名のリネーム**  
  例: `LSTool` → `LS`

### MCP（Managed Code Playground）の強化

- 🐛 プロセス残存バグの修正  
- ⚙ `.mcp.json` に設定を記述可能に  
- 🔁 SSE再接続の信頼性向上  
- 🔐 認証・権限管理の改善  
- 🧙 対話型セットアップ: `claude mcp add`  
- 🌍 JSON文字列からの追加: `claude mcp add-json`  
- 🛠 カスタムヘッダー設定可能

---

## ⚙️ 4. 高度な設定とスムーズなセットアップ

カスタマイズ性とセットアップの利便性がさらに向上。

### 主なアップデート

- 💼 **Claude Pro / Maxに対応**  
- 🗝 **認証UIの改善**  
- 📁 **設定の一元化**  
  `.claude.json` → `settings.json`

- 🔐 **macOS Keychain連携**  
- 💵 **コスト表示変更**  
  `total_cost` → `total_cost_usd`

- 👥 **共有プロジェクトの権限管理**  
- 🔣 **カスタムスラッシュコマンド**  
- 🆕 **新コマンド追加**  
  `/permissions`, `/approved-tools`, `/upgrade`など

- 📂 **設定ディレクトリ統一**  
  `CLAUDE_CONFIG_DIR`が全機能で有効に

- 🔑 **動的APIキー更新対応**  
- 🌍 **多数の環境変数に対応**

---

## 🖥 5. UIとエクスペリエンスの向上

開発体験をさらに快適にするための改善も続々登場。

### UI/UXの強化点

- ⚡ **起動・ストレージの高速化**
- 📤 **ストリーミング入出力対応**  
  `--output-format=stream-json`

- 📊 **Markdownテーブルのサポート**
- 🌀 **進捗インジケーターの改善**

- ⌨ **高速ナビゲーション**  
  `j/k`, `Ctrl+n/p`, `/vim` でVimバインディングも可能。

- 📰 **リリースノートの即時表示**  
  `/release-notes` コマンドで確認可能。

- 🔎 **ファジーマッチングの追加**  
  スラッシュコマンドが柔軟に入力可能に。

- 🎨 **ANSIカラーテーマ対応**
- 🐞 **継続的なバグ修正と信頼性強化**
- 🆕 **プロセス名の変更: `node` → `claude`**
- 🕒 **レイテンシの大幅改善**

---

## ✅ まとめ

Claude Codeは、開発者の**生産性を劇的に向上**させる強力なツールです。  
直感的な対話・柔軟なファイル操作・Web連携・強力なMCP・スムーズなUIがすべてCLIから実現可能。

> 💡 **ぜひ日々の開発に導入し、Claudeとの協働を体験してみてください！**

---
📌  **本記事はAIと一緒に執筆しました。ミスなどお気づきの点があればぜひコメントで教えてください!**
rex0220 計算式プラグイン 売上金額の担当分割（複数担当者）

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、売上金額を複数担当者に分割して、グラフ集計してみます。
[rex0220 計算式プラグイン 売上金額の担当分割](https://qiita.com/rex0220/items/5e3dc411e2123e693fb7)の複数担当者対応版です。

# 概要

担当毎（AA担当・BB担当）にそれぞれ複数担当者を割り当てて、金額を分割します。
端数は、先頭の担当者に割り当てます。

- 編集画面

![2025-06-14_10h36_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c840bd77-9589-4f70-aa8a-4fe57d0d9f71.png)

- 区分別担当別クロス集計

![2025-06-14_16h46_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/519bc7bf-35a9-405e-9520-a73143d0ad88.png)


- グラフ集計：　テーブルを担当・区分別に積み上げ表示

![2025-06-14_10h43_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5a813b99-a795-418f-a511-f512288d750d.png)

- カスタム一覧で、集計・積み上げグラフを表示

![2025-06-14_16h45_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/cc2b493a-e8ed-462a-b65c-b83700cef51a.png)


# 計算式プラグイン設定

端数を先頭の担当者に割り当てる計算式：
leader, total - base * (num - 1)

![2025-06-14_10h44_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a34a73fa-7bb9-4680-8118-3650f47d5f2b.png)

```JavaScript:
OPTION: 

// AA担当分 NUMBER
CEIL(売上金額/2)

// BB担当分 NUMBER
売上金額-AA担当分

// テーブル SUBTABLE
TABLE_DATA(
  LET( // AA担当分集計
    total, AA担当分, // AA合計
    num, ARRAY_COUNT(AA担当), // 人数取得
    base, FLOOR(total / num), // 均等分割
    leader, total - base * (num - 1), // 代表金額
    ARRAY_MAP(AA担当, xx, idx,
      DIC(
        "区分", "AA担当", // 区分設定
        "担当", ARRAY(xx), // 担当者
        "金額", IF(idx=0, leader, base) // 金額配分
      )
    )
  ),
  LET( // BB担当分集計
    total, BB担当分, // BB合計
    num, ARRAY_COUNT(BB担当), // 人数取得
    base, FLOOR(total / num), // 均等分割
    leader, total - base * (num - 1), // 代表金額
    ARRAY_MAP(BB担当, xx, idx,
      DIC(
        "区分", "BB担当", // 区分設定
        "担当", ARRAY(xx), // 担当者
        "金額", IF(idx=0, leader, base) // 金額配分
      )
    )
  )
)

// テーブル.区分 DROP_DOWN
// テーブル.担当 USER_SELECT
// テーブル.金額 NUMBER
```
【Windows】新しく開いたウィンドウが最小化されて復元できない時の対処法

# 【Windows】新しく開いたウィンドウが最小化されて復元できない時の対処法

## 概要

Windowsでアプリを起動した際、ウィンドウが最小化されたまま復元・最大化できなくなる現象への対応方法をまとめます。

---

## 発生するケース

- アプリ起動後、タスクバーにアイコンはあるが画面に表示されない
- Alt+Tabでも表示できず最小化されたまま
- マルチディスプレイ環境や外部モニター構成変更後によく発生

---

## 対処手順

### 1. タスクマネージャーから「切り替え」や「最大化」

1. `Ctrl + Shift + Esc` でタスクマネージャーを開く  
2. 対象アプリを右クリック  
3. 「切り替え」または「最大化」を選択

---

### 2. タスクバーから「移動」または「最大化」

- タスクバーの該当アプリを **Shift + 右クリック**
- 「移動」または「最大化」を選ぶ  
  - 「移動」を選んだ場合は矢印キーやマウスでウィンドウを画面内に戻す

---

### 3. キーボードショートカットで復元・移動

- アプリを選択状態で `Alt + Space` → 「移動(M)」
- 矢印キーで画面内へ移動し、Enterで確定
- `Win + Shift + 左右矢印` でウィンドウを他のモニターへ移動も可能

---

### 4. アプリまたはPCを再起動

- 上記の手順で復元できない場合は、アプリやPCの再起動を試す

---

## よくある質問

- **「切り替え」や「最大化」が選べない場合**  
  → アプリがバックグラウンドのまま、または完全に終了状態の可能性あり。一度アプリを強制終了し、再起動すると改善することが多い。

- **複数モニター環境で発生しやすいのはなぜ？**  
  → モニター構成や解像度変更時、ウィンドウの位置情報が画面外に記憶されてしまうことがある。

---

## 参考リンク・検索ワード

- [Windows Central: How to move a window that's off the screen on Windows 11](https://www.windowscentral.com/software-apps/windows-11/how-to-move-a-window-thats-off-the-screen-on-windows-11)（英語）
- [Microsoft サポート: ウィンドウをある画面から別の画面にドラッグできない](https://support.microsoft.com/ja-jp/topic/ウィンドウをある画面から別の画面にドラッグできない-37735a4e-f58d-f3a4-577c-5749462216f6)
- [Google検索: ウィンドウ 画面 外 戻せない Windows](https://www.google.com/search?q=ウィンドウ+画面+外+戻せない+Windows)

---

## まとめ

- タスクマネージャーの「切り替え」「最大化」
- タスクバーから「移動」「最大化」
- Alt + Space や Win + Shift + 矢印でウィンドウを画面内や他モニターへ移動  
- 解決しない場合はアプリやPCを再起動

これらの方法で多くのウィンドウ復元トラブルは解消できます。
「アポステリオリ言語」と「アプリオリ言語」 みんなの推しプログラミング言語はどっちだ！？

# はじめに
Qiita読者のみなさま、プログラミング言語の分類に「アポステリオリ言語」と「アプリオリ言語」というのがあることはご存じでしたでしょうか？既にご存じの方にはより詳しく、これまで知らなかった方にはわかりやすく、これらのカテゴリについてご説明いたします。

# 「アポステリオリ言語」と「アプリオリ言語」
「アポステリオリ言語」と「アプリオリ言語」はプログラミング言語などの人工言語のカテゴライズに使われる分類用語です。その由来は「アポステリオリ」と「アプリオリ」の哲学用語です。

前者は既存の自然言語をベースにして設計された言語を、後者は既存の自然言語に依存せず完全に独自の構造や語彙を持つ言語を意味します。

## 哲学的な概念「アポステリオリ」と「アプリオリ」との関連性
**ア・ポステリオリ (a posteriori)**　 「経験に基づく」という意味の哲学用語です。

人間の経験や観察、観測を通じて得られる情報など、経験を通じて真偽が判定できる知見を指します。例えば、「日本の６月７月は雨の日が多い」という一般常識は、観察を通じて得られるため、ア・ポステリオリな知識です。

プログラミングにおいて例えば、ある地域のお天気データベースの晴れの値を持つ日次レコードが100を超えた場合などの判定は、ア・ポステリオリと言えます。



**ア・プリオリ (a priori)**　「経験に先立つ」という意味の哲学用語です。

経験に依存せずに理性や論理によって得られる知見を指します。例えば、「三角形の内角和は180度である」（水平を180度、円の一周を360度とした場合）という数学的命題は、経験に依存せずに前提から論理的に導き出せるためア・プリオリな知識です。

プログラミングにおいて例えば、bool値のtrueとfalseはそれぞれおたがいを比較したら常に等しくないという真偽判定もア・プリオリです。

以下、「ア」の後の中点のぞいて「アポステリオリ」「アプリオリ」と表記します。

## 「アポステリオリ言語」　
**アポステリオリ (a posteriori)**　がプログラミング言語のような人工言語のカテゴライズにも使われた場合、アポステリオリ言語とは既存の自然言語の語彙や構文を少なからずベースにして設計された言語を指します。この観点からすると、少しでも自然言語の語彙が使われていると、記号表現がどれだけ多く採用されていてもこっちと判定されるようです。

## 「アプリオリ言語」
**アプリオリ (a priori)**　が人工言語のカテゴライズに使われた場合、アポステリオリ言語とは逆に既存の自然言語に依存せず、完全に独自の構造や語彙を持つ言語を指します。コンピュータ言語としてマシン語は確実にこちらですが、アセンブリ言語は微妙でレジスタ操作ニーモニックはかなり英語由来なので、こっちとは判定されにくいようです。


# 主要言語分類表

|人工語分類  |水準分類  |言語名  |備考（由来言語） |
|:-:|:-:|:-|:-|
|アプリオリ言語|低水準<br>高水準<br>高水準<br>高水準|機械語<br>Whitespace<br>Brainfuck<br>Mystical   |0,1<br>空白,タブ,改行<br>8つの記号<br>魔法陣図形   |
|アポステリオリ言語|低水準<br>高水準<br>高水準<br>高水準<br>高水準<br>高水準<br>高水準<br>高水準<br>高水準|アセンブリ言語<br>C/C++<br>C#<br>Java<br>Go<br>COBOL<br>Python<br>Mind<br>なでしこ   |英語<br>英語<br>英語<br>英語<br>英語<br>英語<br>英語<br>日本語<br>日本語|

# おわりに
いかがでしたでしょうか？なにかの役に立てれば幸いです。文系エンジニアの方になじみやすい単語かもしれませんね（哲学とかを受講されているような場合）:relaxed:。この分類は、プログラミング言語の設計思想や言語の成り立ちを考える上で興味深い視点を提供します。
「DeskflowでMacをサーバにしたらスリープ復帰でキーボード共有が止まる問題を解決！」を書く過程をすべて公開してみる

> DeskflowでMacをサーバにしたらスリープでキーボード共有ができなくなったので、スリープ前後に自動でDeskflowを停止・開始する  
> という記事を書いて  
> 投稿先はqiita

から始まるchatGPTとの[チャット履歴](https://chatgpt.com/share/684cae0f-a0dc-800c-a3fb-79704ac3657e)をすべてを公開してみます。
元の記事はこちら

https://qiita.com/mu-zilch_321/items/29fa92b3529cb5e1707e

以下に自分の発言だけ抜き出してみた。  
タイプミスとかそのまま。  
全27ターン。  
効率的に校正できた気がする。

１
> DeskflowでMacをサーバにしたらスリープでキーボード共有ができなくなったので、スリープ前後に自動でDeskflowを停止・開始する  
> という記事を書いて  
> 投稿先はqiita

> スリープ時に Deskflow を終了する  
> って  
> pkill -x Deskflow  
> これじゃだめ？

> osascript はなんか返さないの？

> チェックしないでpkill でもよいのでは？

> osascript して数秒後にpkill ってのは？

> pgrep とかいらんでしょ

> プロセス正常終了しているときの pkill の副作用ってないよね

> brewno

> brewのサービスは使えない？

> 改めてqiitaに投稿する記事を書いて

１１
> タイトルはどんなのが読まれやすい？  
> あとタグ付けとか

> 一般の人に読んでほしい  
> 使用する技術は何でも良くて問題解決したいだけなので  
> ただ、タグ付けには技術要素は必要かも  
> そのうえで良いタイトルとタグ付けとは？

> DeskflowでMacをサーバにしたらスリープ復帰時にキーボード共有できなくなっちゃったを解決  
> これはどう？

> DeskflowでMacをサーバにしたらスリープ復帰でキーボード共有が止まる問題を解決！  
> これにする

> 記事をもう一度

> コマンドコピペでファイル作成できるようにして

> sleepwatcherがどんなプログラムなのか？  
> スリープと復帰のスクリプトの解説  
> 特にosascript とpkill しているとこ  
> Homebrewサービスだとデフォのスクリプト名で動く  
> なんでこれをやらないとキーボード共有できなくなるのか？  
> キーボード共有できなくなったら再起動しないと駄目とか  
> 以上を盛り込んだ記事にして

> すごくいいです  
> 確認と改善  
> 
> 確認  
> 「復帰後にDeskflowが正しく動作しないと、共有キーボードが使えない状態が続きます。」  
> ここは「共有キーボード」であってる？  
> 
> 改善  
> とりあえず解決したい人向けに、コピペで解決できる方法を冒頭に書いて

> 「共有キーボードが使えない状態」というのがわかりにくい。  
> クライアントにキーボード操作が送られない状態をもっと明確に伝えられない？

> 自分はそういう現象なんだけど、復帰後キーボードOKでマウスNGな事例ある？

２１
> もう一度記事の全文を

> すぐに問題を解決したい方向けのコマンドもセクションに分けて  
> そのセクションごとにあとで解説する感じで

> 「Deskflowに優しく終了命令を送ります。」  
> これは「優しく」？  
> 「正しく」でなない？

> 「Deskflowに正常終了を促します。」  
> にしよう

> 記事全文とタグの候補を
First post enginner  ~memorandum~

エンジニアとして活動していくことになったので、記念ということもあり、Qiitaの方に初投稿をしました。

今後はエラーメッセージ等をここに記入してエラーに強いエンジニアｈなっていこうと思います。

今、やること無限にありますが、落ち着いて進めていきます！
Flaskにおける署名付きクッキーとログインセッションの仕組み

## はじめに

Flaskでログイン機能を実装するときに登場するセッションの仕組みについて、PHPでセッション管理に慣れていた自分にとって、Flaskのセッションは少し不思議に思えた。

特に、「署名付きクッキー」という仕組みがなぜ安全なのか？
それがどうやって「ログイン済みの本人であることの証明」になるのか？
そして「なぜ改ざん防止が必要なのか？」という疑問について解消したので、その学びを整理する。

---

## セッション管理の本質とは？

まず、セッション管理の目的を明確にしておく。

> 「リクエストが、以前ログインした人からのものかどうかを確認すること」

ログイン済みのユーザーからの操作であることを保証するために、サーバーはセッション管理を行う。
そのために使われるのが、Flaskでは「署名付きクッキー」。

---

## Flaskのセッションの特徴

Flaskでは、`session` に保存したデータはサーバーではなくクライアント側（ブラウザ）にクッキーとして保存される。
ただし、それが「署名付き」であるという点がポイント。

```python
session["user"] = "admin"
```

これを設定すると、Flaskは次のような手順でクッキーを作成する。

1. セッションデータを JSON 形式でシリアライズ
2. サーバーの `secret_key` を使って HMAC（署名）を生成
3. 「データ本体 + 署名」の形式でクッキーに格納

このクッキーがクライアントに送られ、次回以降のリクエスト時に自動で送信されてくる。

---

## なぜこれで本人確認になるのか？

署名付きクッキーは、ログイン済みのユーザーにだけに送るサーバー発行の証明書のようなもの。

サーバーは、受け取ったクッキーの中身と署名を検証し、「これは確かに自分が過去に発行したものだ」と確認できるのならば、それはつまり、ログイン済みのユーザーから送信されたクッキーであることの証明になる。

---

## なぜ改ざんを防げるのか？

署名はセッションデータそのものから `secret_key` を使って生成されており、データを1文字でも書き換えると、署名と一致しなくなる。

```text
もし user="admin" を user="guest" に書き換えても、
署名は一致しなくなる → サーバーは改ざんされたと判断して拒否する
```

これにより、悪意あるユーザーが自分でクッキーを書き換えて「自分はadminです」と偽装しようとしても、署名が一致しないためログイン扱いにはならない。

つまり、セッションデータそのものから署名を生成している点がポイント。

---

## まとめ

* Flaskでは、セッションデータを署名付きクッキーとしてクライアントに送る
* 署名はセッションデータから生成されており、改ざんすれば検知される
* サーバーが署名を確認できれば、「自分が発行したクッキー」だと判断できる
* それはつまり、「ログイン済みの本人からのリクエストである」という証明になる

---

## おわりに

Flaskの署名付きクッキーは、一見するとシンプルに思えるが、その中には「本人確認」「改ざん検出」という重要なセキュリティ要素がたくさん詰まっていることがわかった。