OmniAICreator/Qiita-1.07M huggingface dataset:
Teensy4.1 + ESP32 (M5Stack/Stamp)でシンセサイザーを作る時の環境整備

## インストールするもの ##
Arduino IDE
https://www.arduino.cc/en/software


## Adruino IDEでの設定 ##
### PreferencesのAdditional Boards URLs ###
https://dl.espressif.com/dl/package_esp32_index.json
https://static-cdn.m5stack.com/resource/arduino/package_m5stack_index.json
https://www.pjrc.com/teensy/package_teensy_index.json

## インストールするボード ##

**Teensy (for Arduino IDE 2.0.4 or later)** by Paul Stoffregen

**esp32** by Espressif Systems
バージョン 2.0.17を使う。3.x以降はbreaking changesが多いらしい。実際なんだったかが動かなくなったから2.0.17に落としたら動くようになった。
https://community.blynk.cc/t/esp32-core-version-3-x-x-has-some-breaking-changes/68207

**M5Stack** by M5Stack official

## インストールするライブラリ ##

### Arduino IDEのライブラリマネージャからインストールするもの ###
**BLE-MIDI** by lathoub
**MIDI Library**
**NimBLE-Arduino**

! **ArduinoBLE**はインストールしない

**Adafruit SSD1306** by Adafruit
**Adafruit BusIO** by Adafruit
**Adafruit GFX Library** by Adafruit




### GitHubからダウンロードしてくるもの ###

**ESP32-A2DP**
https://github.com/pschatzmann/ESP32-A2DP
Bluetooth Audioを使うのに必要。

**arduino-audio-tools**
https://github.com/pschatzmann/arduino-audio-tools
ESP32-A2DPを使うのに必要。

## インストールしないもの ##
ArduinoBLE
Boreを使用してMinecraftサーバーをトンネリングする

# Boreを用いてMinecraftサーバーを公開する
筆者はMinecraftサーバーを公開したいが、Cloudflare Tunnelを使用するとユーザー側の導入という手間が発生する。しかし、Boreを用いてTunnelを作成することでユーザー側の導入不要で公開ができる。
[Bore](https://github.com/ekzhang/bore/)とは、Rustで製作されたlocalhostへのTunnelを作るためのシンプルなCLIツールだ。
# 構成
- Cloudflare Tunnelを使用した場合
![cf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039129/d53eb8c7-e5b1-4106-96e5-aa5dd07e508e.png)
- Boreを使用した場合
![bore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039129/d594843d-d9e0-42a6-9ba2-10fa56cf0342.png)

# 動作環境
動作環境は以下の通りとする。

ホスト側: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039129/f0080b4c-db40-4dc2-bf38-11fb8f7e856e.png)

プロキシ側:
今回はOracleのAlways Free VPSの枠を利用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039129/cf388514-cb00-4a17-8f7d-f41e88d28240.png)

# プロキシ側
## Boreを導入する
導入はcargoを使用してもいいが、今回はスペックの都合上リリースからバイナリをダウンロードする。
```bash
mkdir bore
cd bore
wget https://github.com/ekzhang/bore/releases/download/v0.5.2/bore-v0.5.2-x86_64-unknown-linux-musl.tar.gz # バージョンは最新のものを利用すること
tar -zxvf bore-v0.5.2-x86_64-unknown-linux-musl.tar.gz
rm bore-v0.5.2-x86_64-unknown-linux-musl.tar.gz # アーカイブは不要なので削除する
```
## Boreを設定する
Boreは非常にシンプルなため、特段難しい設定は不要だ。
以下のコマンドを実行するだけでTunnelが構築される。
```bash
./bore server -s YOUR_PASSWORD
```
Boreは`-s`フラグでパスワードを設定する。これは何でもよいが、漏洩すると他人にTunnelを使用される可能性があるため、パスワードはなるべく漏洩しないようにする必要がある。筆者はuuidを生成し、それを使用した。

### ポートを開放する
ポートは公開したいポート(今回は`1234`)とBoreの認証用ポート(`7835`)を開放する必要がある。
ポート開放については以下の記事を参考にすること。
https://qiita.com/bellx2/items/6f1d95dc8e1bef0be555

# ホスト側
基本的にプロキシ側と行うことは変わらないため、導入は省略する。

## Boreを設定する
ホスト側は少々コマンドが複雑だが、特段難しいことはない。
以下のコマンドを実行するだけでプロキシと接続される。
今回はMinecraftをTunnelするため、`25565`を使用し、プロキシ側では`1234`を使用する。また、接続先は`***.***.***.***`とする。
```bash
./bore local 25565 --to ***.***.***.*** -s YOUR_PASSWORD -p 1234
```
独自ドメインを使用する場合は、`***.***.***.***`を`proxy.example.com`などの自分のドメインにする。

# 接続方法
接続方法は`***.***.***.***:1234`に接続すればよい。
【メモ】Cursorで日本語化が上手くいかない時の解決方法

# Cursor
AI搭載コードエディタ。
業務での活用を目指している。学習のために自宅でも導入。

## 日本語化しようとしたらエラーが出た。

下記の記事を参考に日本語化しようとした。
https://qiita.com/k1mu0419/items/2d903660d1f571abb8f2

1. VSCode拡張機能の「Japanese Language Pack for Visual Studio Code」を入れているか確認
1. メニューバーの「View」→「Command Palette(Ctrl+Shift+P)」を選択 
1. Configure Display Languag
1. 「日本語(ja)」を選択
1. 出てきたポップアップの「Restart」をクリックし、Cursorを再起動する

再起動したところエラーが出て日本語化ができなかった。
` signature verification was not executed `
（署名検証は実行されませんでした）

## 解決方法
一度、「English(EN)」 を選択し再起動。
その後、もう一度「日本語（ja）」を選択すると問題なく日本語に切り替わった。
Proxmox8 VE でWake on Lanを有効にする備忘録

# BIOSのWoLを有効にする
- 詳細はメーカーの使用を参照

# OSのWoLを有効にする
```bash
ip a
# 有効か確認する
# Wake on Lanの項目がgならば有効、dならば無効
ethtool {your eth name}
# dの場合、有効にしたのちcrontabにも登録
ethtool -s {your eth name} wol g
crontab -e
```

# NodeのWoLを有効にする
```bash
pvenode config set -wakeonlan {your mac address}
pvenode config get
```
RaspberryPiでローカルLLM（onnxruntime-genai & Phi4-mini）

LLMを動かすフレームワークとしてonnxruntime-genaiがあります。
RaspberryPiでも利用できるのですが、バイナリは提供されていなくソースコードからビルドする必要があります。
今回はビルドの手順と最新のモデル（Phi4-min）を使ったサンプルの紹介をします。

## 使用するハードウェア
・RaspberryPi5 8GB
・SSD（なるべく速いストレージ）

SDでも大丈夫ですが、時間がかかるのでなるべくSSDを使う方がいいと思います。

## ソフトウェア
・RaspberryPi OS 64bit
・onnxruntime 最新版
・CMake 最新版

パッケージ版のCMakeは少し古くてビルドに失敗するので、最新版をソースコードからインストールしてください。
[こちら](https://qiita.com/linyixian/items/ffe6006729f4c0955766)で手順を説明しています。

## ビルド
任意のディレクトリにonnxruntime-genaiのレポジトリをクローンします。
```console
$ git clone https://github.com/microsoft/onnxruntime-genai
$ cd onnxruntime-genai
```
onnxruntimeも必要なので最新版のバイナリをダウンロードします。
ダウンロード後解凍してからortディレクトリに移動させておきます。
```console
$ curl -L https://github.com/microsoft/onnxruntime/releases/download/v1.21.0/onnxruntime-linux-aarch64-1.21.0.tgz -o onnxruntime-linux-aarch64-1.21.0.tgz
$ tar zxvf onnxruntime-linux-aarch64-1.21.0.tgz
$ mkdir ort
$ mv onnxruntime-linux-aarch64-1.21.0 ort
```

次にビルドスクリプトを実行します。
```console
$ python build.py --config Release
```
ビルドが完了すると onnxruntime-genai/build/Linux/Release/wheel/ にwhlファイルができています。

それではonnxruntime-genaiを使って最新のPhi-4-miniを動作させてみましょう。
pythonの仮想環境を作成します。Phi-4-miniとします。
```console
$ python -m venv phi-4-mini
$ cd phi-4-mini
$ source ./bin/activate
```
onnxruntime-genaiをインストールします。
```console
$ pip install ../onnxruntime-genai/build/Linux/Release/wheel/onnxruntime_genai-0.7.0.dev0-cp311-cp311-linux_aarch64.whl
```
続いてHugginfaceのコマンドラインインターフェイスをインストールします。
```console
$ pip install huggingface-hub[cli]
```
次はHuggingfaceからモデルをダウンロードします。
```console
$ huggingface-cli download microsoft/Phi-4-mini-instruct-onnx --include cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4/* --local-dir .
```
サンプルプログラムをダウンロードして実行します。
```console
$ curl https://raw.githubusercontent.com/microsoft/onnxruntime-genai/main/examples/python/phi3-qa.py -o phi3-qa.py
$ python phi3-qa.py -m cpu_and_mobile/cpu-int4-rtn-block-32-acc-level-4 -e cpu
```
プロンプトが表示されたら質問をしてみましょう。日本語での質問も可能です。
```console
Input: Tell me a joke about generative AI

Output: Sure, here's a joke about generative AI:

Why did the generative AI refuse to attend the birthday party?

Because it couldn't generate enough excitement to keep up the conversation and it didn't want to repeat the same old jokes! Plus, it got scared of the birthday candles burning itself up!

Input: 生成AIのジョークを教えて

Output: もちろん、こちらは生成AIのジョークです:

なぜAIはパーティーに行かなかったのですか？

それは、彼らが生成されたから、すべてのジョークが既知のパターンに従っていたからです。さらに、彼らは「AIがAIを言うのはAIだ」と言うのが嫌だったからです！

（注: このジョークはAIが生成するものであり、AIがAIを言うのはAIだという概念を冗談として使っています。）

Input: 
```

RaspberryPi5でもそこそこのスピードで回答してくれます。
ChatGPT Temperature別回答比較

ロール: あなたは大人で、ユーザーは子供です。
質問文: そらはどうして青いの？
使ったモデル: gpt-4o-mini

Temperature:1
```
空が青いのは、「散乱」という現象によるものなんだよ。
太陽の光は実は白色光で、いろんな色の光が混ざっているんだ。
光が大気中の小さな粒子とぶつかると、
その光が散らばるんだけど、青い光は波長が短いから、
他の色よりもよく散乱されるんだ。
それで、私たちが見上げると空が青く見えるんだよ！面白いよね。
```

Temperature:1.2
```
空が青いのは、太陽の光が大気中の小さな粒子に当たって散らばるからなんだ。
太陽の光はいろいろな色の光が混ざっているんだけど、
その中でも青い光は他の色に比べて散らばりやすいんだよ。
だから、私たちが空を見上げると青い色が一番たくさん見えるんだ。面白いでしょ？
```

Temperature:1.4
```
空が青いのは、「レイリー散乱」という現象によるんだ。
太陽の光はいろんな色の光が集まっているけれど、青い光は他の色よりも波長が短いから、
空気中の小さな分子に散らばりやすいんだ。
```

Temperature:1.6
```
空が青いのは、空気中の小さな粒子が太陽の光を散乱するためだよ。
太陽の光にはいろんな色があって、
その中で青い光が一番散乱しやすいんだ。
このため、私たちが空を見上げると、青い色が多く見えるんだよ。すごいよね！
```

Temperature: 1.8

リクエストタイムアウト
AWS WAF v2のIPセットをAWS CLIで更新する方法

## はじめに
AWS CLI経由でWAF v2のIPセットを更新する方法を説明します👀

以下触れません💦
・AWSアカウントの作成
・AWS CLIのインストール
・認証情報の設定
・必要な権限の設定

## 必要な情報を取得
公式：https://docs.aws.amazon.com/cli/latest/reference/wafv2/list-ip-sets.html
IPセットを更新するためには、以下の情報が必要です。

ID: IPセットのユニーク識別子
LockToken: 変更管理用のトークン
Name: IPセットの名前
Scope: CLOUDFRONTまたはREGIONALのスコープ（どのリージョンやサービスに関連付けられているか）

まず、IPセットの一覧を取得して、更新したいIPセットの基本情報を確認してみます。

使用するコマンド: list-ip-sets
必要なパラメータ: scope

```CLI
aws wafv2 list-ip-sets \
    --scope CLOUDFRONTまたはREGIONAL
```

これで存在するIPセット基本情報（Name、Id、Description、LockToken、ARN)が一覧で確認することができます。

list-ip-setsではなく、get-ip-setで情報を取得する方法もあります。こちらは、指定されたIPSetの情報を取得する方法で、Scopeに加えて、NameとIdが必須です。
公式：https://docs.aws.amazon.com/cli/latest/reference/wafv2/get-ip-set.html

## IPセットの更新
必要な情報を取得した後、新しいIPリストでIPセットを更新します。
公式：https://docs.aws.amazon.com/cli/latest/reference/waf/update-ip-set.html

使用するコマンド: update-ip-sets
必要なパラメータ: Id、LockToken、Name、Scope

```CLI
aws wafv2 update-ip-set \
    --name "your-ipset-name" \
    --scope CLOUDFRONTまたはREGIONAL \
    --id "your-ipset-id" \
    --lock-token "your-ipset-lock-token" \
    --addresses ["128.0.0.0/32", "0.0.0.1/32"] 
```
このコマンドを実行すると、your-ipset-nameのIPセットに含まれるIPアドレスリストは、指定された"128.0.0.0/32"および"0.0.0.1/32"に置き換えられるはずです。このコマンドは、指定したIPアドレスで設定を上書きするので、リストに新しいIPアドレスを追加するわけではありません。既存のIPセット内のアドレスがこの新しいリストに更新されます！


## コメント
正直、CLIを使ってWAFのIPセットを更新することはほとんどないと思います💦
恐らく、APIを経由してIPセットを更新する際には、AWS SDK for JavaScriptを利用してIPセットを更新するシステムを構築したい、が多いと思います。私自身もそうです。今回CLIを記事にしたのは、CLIでできることはSDKでも基本できるので、まずはCLIでやってみてどんな感じなのかなを視覚化したかったからです。SDKでやってみるのを今取り組んでいます。できたら記事にしてみようかな？（コミットではないです💦）
TouchGFXを使おう2～導入編2～

TouchGFXを使おう～導入編～の続きです。

https://qiita.com/usashirou/items/4eb8a6a59d91acb489d9
# Screenを追加する
__Add Screen__ 横の __＋__ からスクリーンを追加できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/6441c9da-2f65-3a4b-7fee-f5d180523600.png)
# 背景を設定する
背景には画像と単色が使用出来ます。
## 画像を背景にする 
Images⇒imageを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f5bd5f57-e5a6-2b3d-054b-f04a6f430b75.png)
__ツールバー⇒images⇒No image__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c77f1597-192b-2bbe-c0cf-3357d89d2795.png)
__Stock__ を __クリック__ し、合ったサイズの背景を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/51d20eb4-d09e-df13-bb17-7a9f97c6307d.png)
## 単色を背景にする
__Shapes⇒Box__ を __クリック__ します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f7a34253-0410-1976-428f-55ee7afdb54c.png)
サイズと色を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/0dd62f0e-ff6b-d20a-c186-84a50f755cff.png)
Locationから縦横を指定し、Colorで色を指定します。
![スクリーンショット 2025-01-26 211244.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/93c4d521-2807-2aa3-ce9a-f6a470ddd9c1.png)
# ボタンを配置する
__Buttons__ から __Button With Labed__ を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/0f4ff7c0-81c4-f14d-69b7-1f5711e6f6f5.png)
# ボタンの文字を変更する
__Translation__ に表示する文字を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/12c7865e-11e6-38b3-e5de-35c155d1f5ee.png)
# ボタンを変更する
__Preset__ からボタンの形状や色を変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/3d456eb9-388a-f417-c972-fd450860910b.png)
## Preset
プリセットで変更する場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e7c13112-2523-2f53-8866-26b6352448fa.png)
## Image
ボタンの色と形状をそれぞれ変更する場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/655e8719-559f-459c-b22e-795470dd660a.png)
## フォントを追加する
フォントを追加するには __assets⇒fonts__ フォルダに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/7229f599-b2da-86a6-b2e9-02d09fd7a0aa.png)
## フォントを指定する
__Text⇒Typography__ を __クリック__ し、__＋__ から日本語が使える文字種を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/14eadfd1-9664-a97a-58e6-54bd96983e5a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/15848898-517e-7f98-e24e-02ffd7ef0b07.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/ee69f952-179e-dc0c-96f5-d8fee3548d92.png)
日本語に対応したフォントを選択すると日本語が表示できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/47f06f53-7ac3-38d4-c62b-9e7a7f6f5f46.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/16002537-88af-0f66-83f0-75f64e350ad9.png)
# 画面表示の順番
ボタンやimageなどは上に行くほど上位レイヤーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/58b11bf1-76a2-ce41-07b3-5d520da8a887.png)
TouchGFXを使おう3～画面遷移編～に続きます
三項演算子が読みづらいからまとめる

三項演算子って結構コードで書かれていたりするんだけれど、
結構読みづらい。

読みづらいというよりも覚えてないから理解するのに頭の中でloading...
みたいになる。

この機会にまとめる。
そしてわからなくなったら自分のを見ようと思う。

## PHPの三項演算子の基本
こんな感じ
```php
$condition ? $conditionTrue : $conditionFalse
```

**$conditionTrue**
$conditionがtrueの場合に返す値

**$conditionFalse**
$conditionがfalseの場合に返す値


こんな感じ
```php
$score = 75;
$message = ($score >= 60) ? "合格" : "不合格";
echo $message; // "合格"
```

短い条件分岐の時には結構使える。

```php
$isEnabled = true;
$value = $isEnabled ? 1 : 0;  // $value = 1
```

## true側を省略する形

ぱっと見た時にまだ馴染みがない書き方

```php
$value = $foo ?: 'default';
```

このコードは

`$foo`がtrueなら`$foo`を返す。
`$foo`がfalseならdefaultを返す。



## nullも条件に入れちゃう形
さっきとなにが違うんだっけ？
と判断に迷う時がある形

```php
$value = $foo ?? 'default';
```

`$foo`がありかつnullでなければ`$foo`を返す。
それ以外は全てdefault
※PHP7以降で利用できる。

## ?と??の違い

?はtrueかfalseの分岐。
なので空文字、0はfalse扱い。

??は変数が定義されているか、nullではないかの分岐。
空文字と0は有効でtrueになる。

```php
$foo = "";
$value1 = $foo ?: "default"; 

$value2 = $foo ?? "default"; 
```

$value1はdefaultを返す。

$value2は""を返す。


これで明日からも頑張れるよ！
OpenManusをGeminiで動かしてみた

# 記事の概要

OpenManusをGeminiで動かして、ブラウザを立てるところまで試してみたので、手順を残す。（試す程度なら余裕で無料！）

https://github.com/mannaandpoem/OpenManus


# 環境

OS:Windows
python:3.12.8（https://www.python.org/downloads/release/python-3128/）


# 構築手順

コマンドプロンプトなどで、以下のコマンドを実行する。

```powershell
python -m venv open_manus_env
open_manus_env\Scripts\activate
cd open_manus_env
git clone https://github.com/mannaandpoem/OpenManus.git
cd OpenManus
pip install -r requirements.txt
python -m playwright install
copy config\config.example.toml config\config.toml
```

「config.toml」はメモ帳などで以下のように修正する。

```toml:config.toml
[llm]
model = "gemini-2.0-flash"
base_url = "https://generativelanguage.googleapis.com/v1beta"
api_key = "★TODO：GeminiのAPIキー"
max_tokens = 4096
temperature = 0.0

# Optional configuration for specific LLM models
[llm.vision]
model = "gemini-2.0-flash"
base_url = "https://generativelanguage.googleapis.com/v1beta"
api_key = "★TODO：GeminiのAPIキー"
```

GeminiのAPIキーは以下の手順などを参考に取得してください。

https://zenn.dev/peishim/articles/2e2e8408888f59

# 実行方法

コマンドプロンプトなどで以下のコマンドを実行し、OpenManusを起動する。

```
python main.py
```

以下のようなログが出るので、「ブラウザでChatGPTを起動して」などと入力する。

```
(open_manus_env) C:\XXXXXX\open_manus_env\OpenManus>python main.py
INFO     [browser_use] BrowserUse logging setup complete with level info
INFO     [root] Anonymized telemetry enabled. See https://docs.browser-use.com/development/telemetry for more information.
Enter your prompt (or 'exit'/'quit' to quit):
```

以下のようなログが出力され、ブラウザにChatGPTが表示される。

```
(open_manus_env) C:\XXXXXX\open_manus_env\OpenManus>python main.py
INFO     [browser_use] BrowserUse logging setup complete with level info
INFO     [root] Anonymized telemetry enabled. See https://docs.browser-use.com/development/telemetry for more information.
Enter your prompt (or 'exit'/'quit' to quit): ブラウザでChatGPTを起動して
2025-03-10 00:04:37.446 | WARNING  | __main__:main:19 - Processing your request...
2025-03-10 00:04:37.447 | INFO     | app.agent.base:run:137 - Executing step 1/30
2025-03-10 00:04:38.643 | INFO     | app.agent.toolcall:think:53 - ✨ Manus's thoughts: ChatGPTをブラウザで起動するには 、BrowserUseToolを使ってChatGPTのウェブサイトを開きます。


2025-03-10 00:04:38.644 | INFO     | app.agent.toolcall:think:54 - 🛠️ Manus selected 1 tools to use
2025-03-10 00:04:38.647 | INFO     | app.agent.toolcall:think:58 - 🧰 Tools being prepared: ['browser_use']
2025-03-10 00:04:38.648 | INFO     | app.agent.toolcall:execute_tool:140 - 🔧 Activating tool: 'browser_use'...
2025-03-10 00:04:40.857 | INFO     | app.agent.toolcall:act:113 - 🎯 Tool 'browser_use' completed its mission! Result: Observed output of cmd `browser_use` executed:
Navigated to https://chat.openai.com/
2025-03-10 00:04:40.858 | INFO     | app.agent.base:run:137 - Executing step 2/30
2025-03-10 00:04:41.565 | INFO     | app.agent.toolcall:think:53 - ✨ Manus's thoughts: ChatGPTのウェブサイトを開きまし た。他に何かお手伝いできることはありますか？例えば、ChatGPTに何か質問したり、ChatGPTの画面を操作したりできます。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619695/501dcc56-c4cd-43e1-80b7-3a5969c30e3f.png)

# 感想

自然言語で想定しているブラウザが表示されている。。。
何気ないけど、すごいのでは？
エンジニアってなんか性格悪い人多くね？を読んで

<h2>話題になっていたので、読んでみた</h2>

https://anond.hatelabo.jp/20250305150606

chatGPTに要約してもらったら、こんな感じ

「エンジニアの対応が高圧的で融通が利かず、新人にも容赦なく厳しい指摘をするため、社内で萎縮や対立が生じている。デザイナーは柔軟で気遣いがあり、対応の差が大きい。エンジニアは仕事を「正解が決まっているもの」と捉えていて、協力的な姿勢に欠けるように感じる。全体会議でこの問題を指摘すべきか悩んでいる」

自分が思ったことをざっくり書いてく

<h2>実際性格が変な人は多い</h2>
個人的な体感だけれど、変な人は多い印象ある。ただ、性格が悪いかどうかとは別

たぶん、営業とかの職業はお客さんと直接対話するので、ビジネスマナーを徹底したり他人に対して気を回すことが職業柄多く、そういう変な特性があったとしても、補うことがうまいと思う

エンジニアはプログラマ的な側面とお客さんと対話する側面があるわけだが、営業ほどゴリゴリに会話するみたいなことはあんまりないと思う。

そのため、エンジニアはやっぱり他人への機微とかに比較的鈍感ではあると思う(営業ほど話していたら、それはもう営業)

ブリリアントジャークという言葉が存在するように、変な人が多いのは間違いないと思う

<h2>コンフリクトするのは良くない</h2>

言っていることは正しい


が、それはそれとして、言い方や態度が悪くて、無駄に雰囲気を悪くしたりして、チームの士気を下げてしまう人はいると思う

伝え方を間違えると人は平気ですれ違ってしまう

仕事は人と人の共同作業。コンピュータ相手ではないので、コンフリクトしないようにお互いにうまくコミュニケーションできればいいが、それをできるような信頼関係がこの2者間で築けていないのだと思う

信頼関係を築けるような場を設けられるといいんじゃないだろうか。業務時間外だと参加しないとかあるので業務時間中で

<h2>心理的安全性</h2>

心理的安全性がない職場は、厳しい

ミスをしても報告が上手く上がってこなかったり、お互いがお互いのミスに対して異常に敏感になったり、連携がうまく取れなかったり、空気が最悪だったり・・・

良いことが一つもない

心理的安全性が低いことは合理的に考えても良くないので、上手く解消できるようなチーム作りや連携をあらかじめチームで話し合ったり、この機会に話し合った方がいい

<h2>結論</h2>
言葉の使い方や、伝え方はとても大事だとこの記事を見て改めて感じた

他山の石と思って、人と会話するときの言葉遣いとかをより一層気を付けようと思った

仕事でコンフリクトすると、自分やその人以外にも迷惑が掛かってしまうし、ストレスになってしまうからうまくコンフリクトを回避できるといい(相手次第でもあるので難しいけれど)

<h2>参考</h2>

https://anond.hatelabo.jp/20250305150606
業務でよく使うGitコマンド

エンジニアになってそんなに間もないですが、業務でよく使うGitコマンドを紹介していきます！

## git pull --rebase origin main
このコマンドは、git push する前に使います。

イメージとしては、事前にgithubにある最新のコードをpushする前に反映させてコンフリクトを防げるというのがメリットかと思います。
--rebeseすると、今のコミットの前にgithubの内容を差し込んでくれます。

githubの最新の状態をローカルに反映するときに何かと多用しているコマンドになります。

## git checkout -b branch名
特定のブランチから新しいブランチを切るときに使っています。
だいたいは、developブランチなどからfeature/〇〇などのブランチを切るときに使います。
ここら辺は、git workflow(https://www.atlassian.com/ja/git/tutorials/comparing-workflows/gitflow-workflow )を見てみてください。

## git checkout branch名
既存のブランチに移るときに使います。

## git push origin branch名
githubにブランチを上げるときに使います。
githubにブランチを上げた後に、githubにてマージ先にプルリクエストを投げています。
また、新しいブランチをgithubに作るときにも使っています。
例：developブランチ、stagingブランチ、release/v1.0.0ブランチを作るときなど

## git add .
ファイルの変更内容の登録コマンド

## git commit -m "コメント内容"
git add . をした後にコミットをコメント付きで行います。
この後に、git push origin ブランチ名 をすることでgithubに上げます。


## git stush
git checkout ブランチ名を行う前に、コミット前の変更があるときにこのコマンドを使って一時保存します。

## git stash apply
git stashしたものをもとに戻します。この場合、最新のstashしたものが元に戻ります。

以上です。
JWTとは何か

## JWTについて調べた経緯
エンジニア未経験なのですが、現在認証について勉強しており、自身のポートフォリオにJWTなるものを実装してみたので自分の知識の整理も含めて記事を書いてみました。

ただ、正直実装方法については自信がないためコードはお見せせずにJWTについての概念だけ説明してみようかと思います...

## JWT(Json Web Token)とは？
JWT（Json Web Token）とは、ユーザーの認証やデータの安全なやり取りを行うためのトークンのことです。
ユーザー認証というのはログインした時にそのユーザー情報を登録して、今ログインしてる人が誰なのかを証明するためのパスポートのような役割をします。

使い方としては以下の通りです。

1. ユーザーがログインした時にJWTを発行する
2. ブラウザ側でcookieの中にこのtokenを保持しておく(localStorageに入れる方法もある)
3. ユーザーがバックエンド側にリクエストを送るときにこのJWTをくっつけて送る
4. backend側は秘密鍵を保持しておりこれを使って正当なJWTであるかどうかを検証する
5. 問題なければレスポンスが返ってくる

他にもログインユーザーの証明にはsession認証(laravelだとデフォルトでこちらが実装されている)などもありますがこれらの違いはbackend側に認証情報を保持するか、ブラウザ側で保持するかというところで、backendに保持する場合、例えばログインしているユーザーが大量になるとその分backend側の負荷が高まってしまうため、ブラウザ側でクライアント側に管理させることでスケーラビリティを高めることができます。

## JWTの構造
JWTはヘッダー、ペイロード、署名の３つから成り立っています。
ヘッダ-にはアルゴリズムという、どういう方式で暗号化するかの明記とトークンのタイプを記載します。
ペイロードにはユーザー情報(usernameとかroleとか)を載せます。漏洩するとまずいような重要な情報は載せてはいけません。
最後は署名です。これはJWTが改竄されたかどうかを見分けるためのものになります。改竄を防ぐというわけではなく改竄されたかを検知することができます。

## 
ただしcookieに入れる場合、JWTだけだと認証としては不十分になります。リクエストの送信時にcookie情報は自動で送信されるため自分でbearerにくっつけるcsrf tokenの実装は必須になります。

## laravelでの導入方法
laravelではtymon/jwt-authというパッケージが用意されているようです。
これを導入することでenvに秘密鍵も設定することができます。

## 最後に

初めて記事を書くのでかなりざっくりしちゃいますが、自分の頭の中の整理ということで多めにみていただけると幸いです...
macOSでGNU backgammonのGUIを使う

## 要約

macでgnubgのGUIを使いたかった。

https://qiita.com/ch_suginami/items/1633d73651e7b397e2b9

Homebrewにはいないし、MacPortsはbrewと同居させたくないので、上の記事のような方法は取れなかった。
また、MacPortsで入るgnubgはバージョンが古く、Sequoiaにも対応していなさそうであった。

とりあえずmac上でビルドしてみたが動かなかった。XQuartzとの相性が悪そうである。

次にDocker上のUbuntuでビルドして実行。
CLIでは動くものの、やっぱりGUIを見たかったのでブラウザから見られるようにした。

### 追記

一通りビルドなどを試したのちに、そういえばrepoにあるだろうとgnubgをインストールしてみるとすんなり動いた。
新しめなUIになっているのはGTK3に対応させたかららしい。

さらに、Debianのunstableで最新版のgnubgをインストールし起動したら、XQuartz経由でGUIが動いた。
文字入力も可能であった。数マッチ行い解析も動かしてみたが、ほぼ問題なく（音声出力周りがエラー、ボードを3D表示にすると落ちるが）動作していた。これが一番手っ取り早そうだ。

![スクリーンショット 2025-03-29 17.59.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603690/9c5381ed-dee6-4d68-9272-00cc89ee09a0.png)

## 環境

macOS: Sonoma 15.3.2
```bash
$ docker --version
Docker version 28.0.1, build 068a01e
```
以下で使用しているイメージはUbuntu24.04。

## gnubgをビルドする

以下では、Docker上のUbuntuで作業している。

ライブラリとか。
```bash
apt install -U automake libtool bison flex libc6 pkg-config python-dev-is-python3 libglib2.0-dev libxml2-dev libfreetype6-dev libgtk2.0-dev libgtkglext1 libgtkglext1-dev libgstreamer1.0-dev libsqlite3-dev libreadline-dev
```

ソースをgnubgのリポジトリから落としてきて解凍してビルド。
```bash
./autogen.sh
./configure
make -j
```

ビルドが終われば`make install`してもよい。
以下のように、そのままの場所で使うときはデータの場所を`--datadir`と`--pkgdatadir`で指定する必要がある。
GUI環境ではまだ動かせないので`--tty`を使いCLIで動くようにしておく。
```bash
./gnubg -D . -P . -t
```

これでCLI版が動く。

## GUIの起動

gnubg→xvfb→x11nvc→novnc→ブラウザと色々経由して画面を出力する。
- xvfb: GUI出力をX11で仮想バッファに出力
- x11vnc: X11の出力をVNCで出力
- novnc: ブラウザ上で実行できるVNCクライアントを提供するwebサーバー
- websockify: websocketをTCPに変換
```bash
apt install xvfb x11vnc novnc
```

Xauthorityファイルを生成。
```bash
xauth -f ./Xauthority add :10 MIT-MAGIC-COOKIE-1 $(openssl rand -hex 16)
```

上から順番に以下を別々のターミナルで起動。
Xauthorityファイルの位置が間違っているとx11vncが起動しないので生成した場所に合わせる。
```bash
xvfb-run -f ./Xauthority -n 10 ./gnubg -D . -P . --display=:10 -s "-screen 10 1920x1080x24"

x11vnc -auth ./Xauthority -display :10 -rfbport 5910 -forever -localhost

websockify --web=/usr/share/novnc 8010 localhost:5910
```

docker側で8010番ポートを転送しておく。

これで`http://localhost:8010/vnc.html`にアクセスすればVNCクライアントが開き、GUIで操作ができるようになる。

![スクリーンショット 2025-03-29 21.03.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603690/a08bd13b-1d6d-41ad-b680-395295720be6.png)

## 微妙な点

文字入力ができない。OS側で入力辺りのことを何もしてないからだろうか。

微妙に使いにくいウィンドウサイズになってしまっている。

## 参考文献

[gdk_gl_window_impl_x11_make_context_current crash · Issue #273 · XQuartz/XQuartz](https://github.com/XQuartz/XQuartz/issues/273)
[GNU Backgammon, Building gnubg from source on Ubuntu](http://www.gnubg.org/xml-rss2.php?itemid=100&catid=10)
[gnubg.git, INSTALL](https://git.savannah.gnu.org/cgit/gnubg.git/tree/INSTALL?id=88a416ca2468245c759e34ef7f2ce76ad9a3bfce)
[changelogs.ubuntu.com/changelogs/pool/universe/g/gnubg/gnubg_1.07.001-3build6/changelog](https://changelogs.ubuntu.com/changelogs/pool/universe/g/gnubg/gnubg_1.07.001-3build6/changelog)
【ShellScript】Google翻訳で文章を翻訳する方法

translate-shellを使用するとShellScriptでGoogle Translateなどを利用して翻訳できます。 

## translate-shellをインストールする

Homebrewを使用する場合には以下のコマンドでインストールできます。

```terminal
brew install translate-shell 
```

その他のインストール方法については以下を参照ください。

https://github.com/soimort/translate-shell#installation

## 翻訳する

`trans`を使用して翻訳できます。

```terminal
$ trans 'Hello World'
Hello World

こんにちは世界
(Kon'nichiwa sekai)

「Hello World」の翻訳
[ English -> 日本語 ]

Hello World
    こんにちは世界, ハローワールド, こんにちは、世界
```

### 特定の言語に翻訳する

英語を日本語に翻訳する場合には以下のようにします。

```terminal
$ trans :ja 'Hello World'
Hello World

こんにちは世界
(Kon'nichiwa sekai)

「Hello World」の翻訳
[ English -> 日本語 ]

Hello World
    こんにちは世界, ハローワールド, こんにちは、世界
```

フランス語を日本語に翻訳する場合には以下のようにします。

```terminal
$ trans fr:ja 'Bonjour'
Bonjour

おはよう
(Ohayō)

「Bonjour」の翻訳
[ Français -> 日本語 ]

Bonjour
    おはよう, おはようございます
```

翻訳結果のみ出力するには`-b`を使用します。

```terminal
$ trans fr:ja -b 'Bonjour'
おはよう
```

## ファイルを翻訳する

`input.txt`を翻訳する場合には以下のようにします。

```shell
trans :ja -i input.txt
```

結果を`output.txt`に出力するには以下のようにします。

```shell
trans :ja -i input.txt -o output.txt
```
nvmの使い方

自分のMacBookにNode.jsの環境構築をしたく、せっかくなので複数バージョンの切り替えをできるようにしておこうと思いnvmを使うことにしました。使い方を知らなかったのでClaude 3.7 Sonnet先生に教えてもらいました。


入力したテキストは下記です。
```
nvmコマンドの基本的な使い方を教えてください。
出力はマークダウン形式のテキストファイルにしてください。
```

以下が教えてもらった内容です。

---

# NVM (Node Version Manager) の基本的な使い方

Node Version Manager (NVM) は、複数のNode.jsバージョンをインストールして管理するためのツールです。以下では、基本的な使い方を説明します。

## インストール方法

### Linuxおよび macOS

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
```

または

```bash
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
```

### Windows

Windows用のNVMは別のプロジェクトです。以下からダウンロードしてインストールできます：
https://github.com/coreybutler/nvm-windows/releases

## 基本的なコマンド

### バージョンの確認

```bash
nvm --version
```

### 利用可能なNode.jsバージョンの一覧表示

```bash
nvm ls-remote
```

### 特定のバージョンのNode.jsをインストール

```bash
nvm install 16.14.0    # 特定のバージョンをインストール
nvm install --lts      # 最新のLTS（長期サポート）バージョンをインストール
nvm install node       # 最新のNode.jsバージョンをインストール
```

### インストール済みのNode.jsバージョンの一覧表示

```bash
nvm ls
```

### 特定のバージョンのNode.jsを使用する

```bash
nvm use 16.14.0        # 特定のバージョンを使用
nvm use --lts          # インストール済みの最新LTSバージョンを使用
nvm use node           # インストール済みの最新バージョンを使用
```

### デフォルトのNode.jsバージョンを設定

```bash
nvm alias default 16.14.0  # 特定のバージョンをデフォルトに設定
nvm alias default node     # 最新バージョンをデフォルトに設定
```

### 現在使用中のNode.jsバージョンを確認

```bash
nvm current
```

### 特定のNode.jsバージョンのパスを表示

```bash
nvm which 16.14.0
```

### Node.jsバージョンのアンインストール

```bash
nvm uninstall 16.14.0
```

## 実践的な使用例

### プロジェクトごとに異なるバージョンを使用

`.nvmrc`ファイルをプロジェクトのルートディレクトリに作成し、使用したいNode.jsのバージョンを記述します：

```
16.14.0
```

そのディレクトリで以下のコマンドを実行すると、指定したバージョンに自動的に切り替わります：

```bash
nvm use
```

### シェル起動時に自動的にNVMを有効化する

`.bashrc`、`.zshrc`、または`.profile`ファイルに以下を追加します：

```bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
```

## トラブルシューティング

### コマンドが見つからない場合

```bash
source ~/.bashrc  # または ~/.zshrc
```

を実行してシェル設定を再読み込みします。

### 特定のnpmパッケージをグローバルにインストールする場合

```bash
nvm use 16.14.0
npm install -g npm@latest
npm install -g yarn
```

## 注意点

- 各Node.jsバージョンは独自のグローバルパッケージを持ちます
- 異なるバージョン間でグローバルパッケージを共有することはできません
- NVMはWindowsのコマンドプロンプトやPowerShellで直接使用するには追加の設定が必要な場合があります

---

ﾒﾓﾒﾓ_φ(･_･
Android Chrome の タップして検索 (Touch to Search) の対象から外す


## はじめに

- Android Chrome には 「タップして検索」という機能が存在する
- 特定の要素をタップや、長押しをしたときに「タップして検索」の対象から除外したい

## 回避方法

- 要素に `tabindex=-1` を付与する
- 要素がインタラクティブであることを示す
  - `role=button` や JavaScript を使用して DOM を操作する
- 要素に `user-select: none` を付与する

https://developer.chrome.com/blog/tap-to-search

その中の「要素に `user-select: none` を付与する」について記載する

## 要素に `user-select: none` を付与する

https://developer.mozilla.org/ja/docs/Web/CSS/user-select

### Tailwind CSS を使用している場合

Class に `select-none` を追加すれば良い。

```html
<span class"select-none">foo</span>
```

https://tailwindcss.com/docs/user-select

### CSS の場合

`user-select: none;` を指定してあげれば良い。

```css
.foo {
  user-select: none;
}
```

```html
<span class="foo">bar</span>
```

## Ref

https://developer.chrome.com/blog/tap-to-search

https://tailwindcss.com/docs/user-select

https://issues.chromium.org/issues/41451252

https://developer.mozilla.org/ja/docs/Web/CSS/user-select
docker + Laravel + MySQL環境下のDB名称変更

# はじめに
個人開発中のアプリでDBの名前を変える必要があったので、備忘録的にやり方を残しておきます。
DB内のデータは引き継がないで削除します。

# 作業手順
###  旧DBの削除
```
docker compose exec [コンテナ名] bash
mysql -u root
mysql> drop database 削除したいデータベース名;
```

### .envの変更
.envのDB名定義部分を書き換え
```
DB_DATABASE=new_database_name
```
変更後アプリケーションコンテナに入り、Laravelの設定キャッシュをクリア
```
docker compose exec [コンテナ名] bash
php artisan config:clear
```

###  権限の再設定
DBコンテナに入り、MySQLの GRANT 設定を修正
```
docker compose exec [コンテナ名] bash
mysql -u root
～ここから権限設定～
mysql> GRANT ALL PRIVILEGES ON new_database_name.* TO '[MySQLのユーザー名]'@'%';
mysql> FLUSH PRIVILEGES;
```

###  マイグレーション実行
```
php artisan migrate:fresh --seed
```

以上で完了です。
DBの名前を変えたいことはそうそう無いかもしれませんが、、、
Amazon Virtual Private CloudとTransit gateway

# VPCとTransit Gatewayの連携について

### **VPC削除時の事象**

業務でもう使わなくなったAWSのアカウント環境で、
VPC（Virtual Private Cloud）を削除しようとすると「先にアタッチメントを削除しろ」と通知が出た。
VPCの中に **Transit Gatewayとの接続（アタッチメント）が残っていること** が原因だった。
この辺りの認識がふわふわしてたので、
VPCやTransit Gateway、また関連してL2、L3について調べた内容をまとめました。
ほぼ備忘録です。

### **Transit Gatewayとは**

AWSにおける**Transit Gateway** は、**異なるVPC（バーチャルプライベートクラウド）間や、アカウント間のネットワークをつなぐ** ために使う。
オンプレで言うと **「ネットワークの中継ハブ」** のようなもので、いわゆるL3スイッチのようなイメージです。

- **VPCをまたいだプライベートな通信** を可能にする（L3の役割）
- 各VPCのネットワークインターフェースは、通常「ローカル（L2）」の範囲でしか通信できない
- **Transit Gatewayを使うと、VPC同士を直接つなぐことができる（外に出さずに通信可能）**
- **異なるAWSアカウントのVPC同士も接続できる**

---

### **VPCとTransit Gatewayの関連（アタッチメント）とは？**

AWSでは、VPCとTransit Gatewayを接続するために **アタッチメント** という仕組みを使います。

### **アタッチメントとは**

- VPCとTransit Gatewayをつなぐための **仮想的な接続**
- 各VPCごとに個別のアタッチメントを作成する必要がある
- **一つのTransit Gatewayに複数のVPCを接続できる**
- アタッチメントを通じて、VPC同士や他のネットワーク（VPN、Direct Connectなど）と通信可能

### **VPCとTransit Gatewayの関連図**
![vpc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/3fbbe087-c9fc-43c0-bd00-6fd88cbd023c.png)

### **そのため、正しい手順としては**

1. **Transit Gatewayのアタッチメントを削除**
    - AWSマネジメントコンソール → VPC → Transit Gatewayのアタッチメント から削除
    - AWS CLIなら `aws ec2 delete-transit-gateway-vpc-attachment`
2. **VPCを削除**
    - これで削除できるようになる

💡 ちなみに**Transit Gateway本体を削除する必要はない（他のVPCが使っている場合もあるため）**。


# 流れでL2スイッチとL3スイッチについて調べてみた
## ネットワークハブ、L2スイッチ、L3スイッチとは？

有線LANはネットワークハブという機器にケーブルを接続してネットワークを構築する。
※一般家庭のルーターにはこれが元々内蔵されていることが多い。

このネットワークハブには、L2スイッチ（スイッチングハブ）、L3スイッチなどの種類がある。

### **L2スイッチ**

- **データリンク層（TCP/IPモデルではネットワークインターフェース層）に対応する**
- 各ポートにつながっているホストのMACアドレスを記憶して、送信先に信号を流す
    - そのため、基本的に信号の衝突が起きない
- **同じネットワーク内の通信を担当（お隣同士のイメージ）**
- L2スイッチでネットワークを構成した場合、そのネットワーク全体がブロードキャストドメインとなる。
    - ブロードキャストドメインとは：ブロードキャストアドレスを宛先にした場合に、データが送られる範囲のこと
    - ブロードキャストアドレスとは：そのアドレス（IPアドレスとかMACアドレス）に送ると、同じブロードキャストドメイン内の全ての機器に届く。
        - https://wa3.i-3-i.info/word1777.html
        - ホスト台数が増えてくると、ブロードキャストでネットワークが混雑しやすくなる
- AWSで言うと・・・
    - VPCのENI（Elastic Network Interface）間の通信のようなもの

### **L3スイッチ**

- **ネットワーク層（TCP/IPモデルではインターネット層）に対応する**
- **異なるネットワーク同士をつなぐことができる。（広い範囲のイメージ）**
- IPアドレスを使って通信経路を決める
- VLAN(バーチャルLAN)を作る。
    - LANをいくつかの仮想的なネットワークに分割する。
    - 分割するので、ブロードキャスト通信が同じVLAN内にしか送られなくなるので、混雑をしない。
- AWSで言うと・・・
    - VPC内の異なるサブネット間通信（ルートテーブル）
    - VPCピアリングやTransit Gatewayを使ったVPC間通信
    - インターネットを経由した通信（NAT GatewayやInternet Gateway）

### TCP/IPの階層モデルと、OSI参照モデルの比較表
![l2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/d879ca32-0e3a-429a-9795-2366e3a133b8.png)
ChatGPTの画像生成で、着せ替えカメラを作る　ー 機能開発 ー

## ChatGPTの機能が進化
2025年3月26日、ChatGPTの画像生成機能が大幅に性能アップしました。

https://x.com/sama/status/1904598788687487422

インフォグラフィックを生成したり、漫画を生成したり、既に多くの記事で使い方が投稿されていますが、その中でも「インコンテキスト学習」を活用した、自分なりに面白い使い方を思いついたので早速記事にしてみます。

## インコンテキスト学習について
ユーザーがアップロードした画像をもとに、それに関連する内容を新たに生成画像へ反映させることができる機能です。
たとえば、ユーザーが猫の写真をアップロードしたうえで、「この猫が宇宙にいるような背景にして。」「この猫に王冠をかぶせて。」と指示を出すと、それに応じた画像を生成できます。

例えばこんな感じ(多少元の印象から変わるけど、許容範囲)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/a1c5574f-def6-4592-bcb4-55304821e344.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/a559f28c-c5b8-4a8a-923a-c6036e7f4e22.png)

（現場猫がずいぶん綺麗になったな・・・）

## 実現したいアイデア
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/54bd1f40-abd1-428a-b96c-48ce7db51202.png)
要はこれです。

せっかくなのでChatGPTでインフォグラフィックを生成し、今回のチャレンジについて説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/726e448f-f9ba-40a6-b2dd-7c6307233b83.png)

皆さん、こういう気まずい思いをしたことはありませんか？

一人だけドレスコード間違えた（この画像もChatGPTで生成）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/24840b02-391e-415b-a9e7-c2c659be889c.png)

私はこのTシャツの彼を、心から救いたいと考えています。
一生残る傷を、楽しい思い出に変えてあげなければ・・・

## ということで、やってみる
### インコンテキスト学習による素材作成
とりあえず着せたい衣服が写った写真をChatGPTに放り込み、画像の通りのプロンプトを送ります。

![FFCA9F0C-4C42-43E9-9390-8C2FC2B74328_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/3ce1e9ea-2223-45de-9f86-e3f297b78783.jpeg)

勢いだけの洗練されていないプロンプトですが、結果はこの通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/724a9dfa-7f7f-427e-9227-d70b39a22d5b.png)

予想以上に上手くいきました。
もうこの時点で、いろんなことに転用できてしまう気がします。

### 一人にはさせない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/d6b70752-8c5f-4e09-b3ff-f973fc6860d3.png)

プロンプトの結果がこちら

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666630/bba8c556-38f2-41ce-bc65-c2d6e6ab9107.png)
アスペクト比がおかしくなりましたが、プロンプトで補正できるので気にしません。
少なくとも、彼はもう一人ではありません。

## まとめ
ふと思い立った使い方でしたが、無事にChagGPTでやりたいこと・機能がほぼ実現できました。

今後の開発ですが、
 1. 現実的な使い方提案
 2. この一連の手順をGPTsでアプリ化
 3. 専用ハード開発 （API公開に合わせ着せ替えカメラ　を現実にする）

これらを今年の目標にして取り組んでみようと思います。
早くAPIが公開されて欲しいですね。
AtCoderをPythonで取り組んだ振り返り(ABC399 A,B)

どうもこんにちは！

今週もAtCoderのコンテストに参加できたので、記録がてら振り返ります。
今回はBまで完答。Cはグラフに関する問題で、手が出せず。森という概念を初めて聞いた気がしました。

問題

問題は以下のリンクから。取り組めたA,Bを振り返ります。

https://atcoder.jp/contests/abc399/tasks

# A - Hamming Distance -
同じ長さの文字列が2つ与えられるので、n文字目が異なる個数を回答する問題。シンプルに1文字ずつ比較して数えました。
~~~Python
n = int(input())
s = input()
t = input()
ans = 0
for i in range(n):
  if s[i] != t[i]:
    ans += 1

print(ans)
~~~

# B - Ranking with Ties -
n人分の試験の点数が与えられるので、その順位付けをするという問題。同じ点数の場合は同順位として、次はその人数を飛ばした順位になります。例えば1位が2人いたら、その次の点数の人は3位となる感じです。
~~~Python
n = int(input())
s = [int(x) for x in input().split()]
ans = [0] * n
r = 1
#print(ans)

while r < n+1:
  k,m = 0,0
  for i in range(n):
      if ans[i] == 0:
          m = max(m,s[i])
#  print(m)
  k = s.count(m)
  for i in range(n):
    if s[i] == m:
      ans[i] = r
  r += k

for i in ans:
    print(i)
~~~


# おわりに
今回はグラフの勉強不足につきます。4月になるので目標は未達、問題を解けるように、落ち着いて1つずつ勉強を進めたいと思います。

ではでは。
llamacloud-mcp


llamacloud-mcpを利用して、LlamaCloudをMCP（Model Context Protocol）サーバーとして構築し、Claude Desktopなどのクライアントからアクセスできる環境を整える手順を、具体例を交えて説明します。

ステップ1: LlamaCloudのインデックスを作成する
	1.	LlamaCloudアカウントの作成
	•	LlamaCloudにアクセスし、アカウントを作成します。 ￼
	2.	新しいインデックスの作成
	•	ダッシュボードから「Create Index」を選択し、データソースを指定して新しいインデックスを作成します。例えば、Google Driveをデータソースとして選択し、特定のドキュメントをインデックス化することが可能です。
	3.	APIキーの取得
	•	LlamaCloudのUIからAPIキーを取得します。これは後の設定で必要となります。

ステップ2: MCPサーバーの設定
	1.	リポジトリのクローン
	•	ターミナルで以下のコマンドを実行し、リポジトリをクローンします。

git clone https://github.com/run-llama/llamacloud-mcp.git


	2.	環境変数の設定
	•	llamacloud-mcpディレクトリ内に.envファイルを作成し、以下の環境変数を設定します。

LLAMA_CLOUD_API_KEY=あなたのLlamaCloud APIキー
OPENAI_API_KEY=あなたのOpenAI APIキー

※OpenAI APIキーは、RAG（Retrieval-Augmented Generation）クエリを実行するために使用されます。他のLLM（大規模言語モデル）を使用する場合は、適宜設定を変更してください。

	3.	依存関係のインストール
	•	poetryを使用して依存関係をインストールします。以下のコマンドを実行してください。

poetry install


	4.	MCPサーバーの起動
	•	以下のコマンドでMCPサーバーを起動します。

poetry run python mcp-server.py

これにより、ローカル環境でMCPサーバーが起動し、クライアントからの接続を待ち受ける状態になります。

ステップ3: Claude Desktopの設定
	1.	Claude Desktopのインストール
	•	Claude Desktopの公式サイトからアプリケーションをダウンロードし、インストールします。 ￼
	2.	設定ファイルの編集
	•	Claude Desktopを起動し、メニューバーからClaude -> Settings -> Developer -> Edit Configを選択します。
	•	設定ファイルがエディタで開かれるので、以下のようにMCPサーバーの情報を追加します。

{
  "mcpServers": {
    "llama_index_docs_server": {
      "command": "poetry",
      "args": [
        "--directory",
        "/path/to/llamacloud-mcp",
        "run",
        "python",
        "/path/to/llamacloud-mcp/mcp-server.py"
      ]
    }
  }
}

※/path/to/llamacloud-mcpは、実際のllamacloud-mcpディレクトリのパスに置き換えてください。

	3.	Claude Desktopの再起動
	•	設定を保存し、Claude Desktopを再起動します。これで、Claude DesktopからMCPサーバーに接続できるようになります。

ステップ4: Claude Desktopからのクエリ実行
	•	Claude Desktopのチャットウィンドウに質問を入力し、先ほど設定したMCPサーバーを選択してクエリを実行します。例えば、「LlamaIndexでエージェントをインスタンス化する方法は？」と入力すると、MCPサーバーがLlamaCloudのインデックスを検索し、関連する情報を提供します。

以上の手順で、LlamaCloudをMCPサーバーとして構築し、Claude Desktopからのクエリに応答する環境が整います。
FortiGateのでunTagとTagをTrunkさせる方法

# Why would you do that?
FortiGateでunTagフレームとTagフレームを一つの物理ポート（internal）から出力したい。
普通ならいらないこの構成。
自宅マンションの物理接続が各部屋に一本のLANケーブルなのに、unTag(プライベート用)、Tagフレーム(検証・仕事用)みたいな分け方をしたものだから、さあ大変。
上位ルータ兼FWとして使用しているFortiGateへTrunkポートを作って、unTagフレームと(VLAN 1)とTagフレーム(VLAN172)を出力する羽目になった。
自分のメモ用として残しておく。

# 構成
ルータ兼FW：FortiGate60E　⇒　version：FortiOS6.0.4
・wan1ポートをインターネット用LANケーブルを接続
・internal1,internal2を各部屋のLANケーブルに接続
・internal1,internal2にはVLAN1(192.168.100.0/24)とVLAN172(172.16.0.0/24)を流す。
（どこか後で絵をかきます。）

# 手順
①ハードウェアスイッチを作成する。
　→これはinternalをそのまま使っても問題ない。今回はinternal1~internal5までを対象にする。
 　（テストのため故意に別ハードウェアスイッチを作成している。）
　　ポイントはこのハードウェアスイッチ（1_HardwareSW）にIPアドレスを設定すること。これがuntagフレームを出力するためのセグメントになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982175/07693187-2960-4512-a73e-175463eb2509.png)

②VLANインターフェースを作成する。今回はIPアドレスを172系を使用するためにVLANID:172を使用。名前も「VLAN172」に。
　ポイントはこのインターフェースにはIPアドレスを設定しない。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982175/000768e7-8cd8-47c0-af62-69bf1a47d983.png)

③ソフトウェアスイッチを作成し、「VLAN172」をメンバーに参加させる
　そしてこのソフトウェアスイッチには、「VLAN172」のIPアドレスを設定する。
　そうすると、internal1~internal5で、VLAN172とuntagのTrunkポートが作成できる。なんだこの仕様。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3982175/68e09195-524e-4c7f-a897-fd82b3f23d1a.png)

※注意※
ここまでの手順だと、各セグメント内の通信は可能なものの、セグメント間では通信できないし、インターネット抜けも不可。
ポリシーに入力インターフェース（ソフトウェアスイッチ）⇒出力インターフェース（wan1）を設定しないといけません。

# 参考
https://qiita.com/ouchi_Y/items/97d8f35ca09a1e526f16
私がサーバーのパフォーマンス向上のために使ったもの - ② ネットワークI/Oの最小化

この内容は、担当しているプロジェクトによっては使用されないかもしれませんが、重要な概念であり、難しくもないため、ぜひ知っておいていただきたいと思います。

フロントエンドからのリクエストやレスポンスの過程を除けば、バックエンド開発者が最も頻繁に経験するネットワークI/Oは、おそらくデータベースへのアクセスでしょう。

まずネットワークI/Oを削減する方法を説明する前に、サーバーがフロントエンドのリクエストをどのように処理するのかを図で見てください。

図を見ると、クライアントからリクエストを受け取ったサーバーは、それに対するレスポンスを返しますが、その過程でビジネスロジックを実行するためにDBへアクセスする必要があります。このとき、ネットワークを通じてDBにクエリを送信します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852151/93eb13b6-a90a-4e31-8558-e64b1a0118da.png)

そして、サーバーがDBから大量のデータを受け取って処理するケースでなければ、ほとんどの場合、ビジネスロジックの処理時間よりも、サーバーとDB間でネットワークを通じてリクエストとレスポンスをやり取りする時間のほうが長くなります。

そのため、開発者は必要がない限り、ネットワークI/Oを最小限に抑える必要があります。

ここで、新人がよくやってしまうミスを例にとって、ネットワークI/Oを削減する方法を説明します。

---

### 例）

`UserDtoList` には複数のユーザー情報が格納されています。  
`accountDAO.signUpUser(userDto)` メソッドは、MyBatis を使用してユーザー情報をDBに保存するメソッドです。

この `UserDtoList` の中から `age` が20歳を超えるユーザー情報をDBに保存するロジックを実装する場合、以下のようなコードになるかもしれません。

```java
  public void insertAdult(List<UserDto> UserDtoList) {
    for (UserDto userDto : UserDtoList) {
      if (userDto.getUserAge() > 20) {
        accountDAO.signUpUser(userDto);
      }
    }
  }
```

一見、要件を満たしているように見えるこのコードですが、  
もし `age` が20歳を超えるユーザーが100人いた場合、DBサーバーを100回呼び出すことになります。


![image 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3852151/df6d3277-0ac9-4fe9-abc0-779549abb065.png)


前に述べたように、ネットワークを通じたリクエストとレスポンスのやり取りには時間がかかるため、これを最小限に抑える必要があります。

では、このコードをどのように改善すればよいのでしょうか？

結論から言うと、保存したいリストを一度にDBサーバーに送る方式を使います。

そのためには、上記のコードを2つのメソッドに分ける必要があります。

1. `List<UserDto>` を受け取り、`age > 20` のオブジェクトだけを抽出して返すメソッド → `filterAdults(List<UserDto> userDtoList)`
2. `List<UserDto>` を受け取り、一度にDBへ保存するメソッド → `accountDAO.signUpUserList(adults)`

修正されたコードは以下のようになります。

```java
    public void insertAdultUser(List<UserDto> userDtoList) {
        List<UserDto> adults = filterAdults(userDtoList);
        accountDAO.signUpUserList(adults);
    }

    private List<UserDto> filterAdults(List<UserDto> userDtoList) {
        List<UserDto> resultList = new ArrayList<>();
        for (UserDto userDto : userDtoList) {
            if (userDto.getUserAge() > 20) {
                resultList.add(userDto);
            }
        }
        return resultList;
    }
```

このように修正することで、DBサーバーを1回だけ呼び出して `List` を保存することができます。

大体のORMやSQLマッパーは `List` を使ったSQL処理をサポートしているため、それぞれのツールに合わせて実装すれば問題ありません。

なお、この方法は **DBサーバーへの呼び出しを最小化し、ネットワーク通信にかかる時間を減らすためのものであって、ロジック自体の性能を向上させるものではない** という点に注意してください。

---

### まとめ

実は、Spring Bootで使用されているORMであるJPAは、クエリをメモリに蓄積しておいて、一括でDBにリクエストを送る仕組みを持っているため、あまり気にしなくても性能上の問題は発生しません。  
(他のORMも同様かどうかは分かりませんが)

とはいえ、この記事の内容は基本として知っておくべきですし、ORMを使用しない場合もあります。そして何より、視野が広がるので知っておく価値があると思います。

最後まで読んでいただき、ありがとうございました。
「AtCoder Beginner Contest 253B - Distance Between Tokens」メモ

## 問題
AtCoder Beginner Contest 253

https://atcoder.jp/contests/abc253/tasks/abc253_b

## 考察
`o`の位置を記録する配列をつくる。
```py
ans.append(i,j)
```
で一つの部分に二個のデータをまとめた配列がつくれる。
## ACコード
```py
def Tokens(a,h,w):
    ans = []
    for i in range(h):
        for j in range(w):
            if a[i][j] == "o":
                ans.append((i,j))
    return ans

h,w=map(int,input().split())

s= [input() for _ in range(h)]

ans = Tokens(s,h,w)

a,c = ans[0]
b,d = ans[1]

print(abs(a-b)+abs(c-d))
```
jupyterlab上で画像クリックして座標を取得する。

新しいバージョンのjupyter labはjupyter_clickable_image_widgetを使うと実際表示されないようです。なのでipycanvasを使いました。クリックイベントほか、画像描画などにも使えます。

ipycanvasをインストールします。

```
pip install ipycanvas
```

nodeはVersion20以上

```
node -v
```

jupyterlabを拡張します。

```
jupyter labextension install @jupyter-widgets/jupyterlab-manager
```

```
jupyter labextension install ipycanvas
```

ビルドします。

```
jupyter lab build
```

再起動します。

```
jupyter lab
```


```python
from ipycanvas import Canvas
from IPython.display import display
import ipywidgets as widgets
import cv2

# 元画像読み込み＆縮小
image_path = '/home/jetson/jetracer/notebooks/camera/test202503292022/xy/0_0_00063.jpg'
img = cv2.imread(image_path)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img_resized = cv2.resize(img, (224, 224))  # ピクセル的に縮小

# キャンバスサイズは縮小画像と一致
canvas = Canvas(width=224, height=224)
canvas.put_image_data(img_resized)

# 見た目サイズを強制縮小
canvas_widget = widgets.Box([canvas], layout=widgets.Layout(width='224px', height='224px'))

# 座標表示
x_widget = widgets.IntText(description='x')
y_widget = widgets.IntText(description='y')
log_output = widgets.Output()

# クリック時処理
def handle_click(x, y):
    with log_output:
        print(f"Clicked at: ({x}, {y})")
    x_widget.value = int(x)
    y_widget.value = int(y)
    
    canvas.clear()
    canvas.put_image_data(img_resized)
    canvas.fill_style = 'green'
    canvas.fill_circle(x, y, 3)

canvas.on_mouse_down(lambda x, y: handle_click(x, y))

# UI 表示
ui = widgets.VBox([
    canvas_widget,
    widgets.HBox([x_widget, y_widget]),
    log_output
])

display(ui)
```
【自分用】Gitとかいう（随時追記）

## CUI
Githubの管理はGithub Desktopやvscodeからぽちぽちしてやってきたがいろんな資料や教材をみるとやけにCUIが押されていてみんなコマンドをぽちっているのでその方法を記載しておく。
※Windows PowerShellでの手順
## リポジトリのクローン
まずはリポジトリのクローンをする
（既にクローンしている場合は行わない）
リポジトリを作成したら緑色の<font color="green"><>Code</font>を開いて
webURLをコピーする
![スクリーンショット 2025-03-29 211645.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962558/1736f41f-e49f-4485-a80f-bb9023f85a35.png)
コピーしたリンクを使ってコマンドプロンプトからリポジトリをクローンする
```cmd:cmd
C:\Users\ユーザー名>git clone <リポジトリのURL>
```
## リポジトリへの移動
作業するリポジトリへ移動します
```cmd:cmd
C:\Users\ユーザー名>cd <リポジトリ名>
```
## ブランチの作成・移動
__ブランチの確認__
git branchのみだとローカルブランチを表示できます
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git branch <-a:すべてのブランチ・-r:リモートブランチのみ>
```
__新しいローカルブランチを作成して移動__
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git switch -c <ブランチ名>
```
__リモートブランチを元にローカルブランチを作成__
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git switch -c <ローカルブランチ名><リモートブランチ名>
```
__ブランチを移動__
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git switch <移動先のローカルブランチ名>
```
## Pullする
リモートリポジトリから最新の変更を取得します
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git pull
特定のリモートブランチからPullしたい場合
C:\Users\ユーザー名\リポジトリ名>git pull <リモート名> <ブランチ名>
```
## VScodeを開く
VScodeを開かないことには編集できないのでターミナルから開きます
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>code .
```
## ステージング
ファイルを編集した後変更した内容をステージします
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git add .
```
## コミット
ステージした変更をコミットします
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git commit -m "コミットコメント"
```
## プッシュ
リモートリポジトリに変更をプッシュします
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git push --set-upstream origin <ブランチ名>
または
C:\Users\ユーザー名\リポジトリ名>git push origin <ローカルブランチ名>:<リモートブランチ名>
```
ローカルブランチの名前とリモートブランチの名前が同じ場合
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git push
```
## スタッシュ
現在の未コミットの変更をスタッシュします
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git stash
```
スタッシュの一覧を見る
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git stash list
```
## ポップ
最新のスタッシュをポップします
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git stash pop
```
特定のスタッシュをポップします
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git stash pop stash@{<リストに表示された番号>}
```
## フェッチ
ワークツリーに影響を与えず更新情報を取得します
```cmd:cmd
C:\Users\ユーザー名\リポジトリ名>git fetch
指定されたリモートからのみフェッチを行う場合
C:\Users\ユーザー名\リポジトリ名>git fetch <リモート名>
```
Ubuntu22.04にClaude DesktopをインストールしてMCP経由でClaude Codeを使う

# はじめに
以下Zennの記事を拝見し、自宅のUbuntu22.04環境でも実現できるか試してみました。
デスクトップUbuntuの環境でClaude DesktopからCalude CodeへMCP接続する設定を備忘録として残します。

https://zenn.dev/kazuph/articles/5a6cc61ae21940

:::note warn
本記事の内容は執筆時点(2025/03/29)の情報に基づきます
:::
:::note alert
Claude Desktopは現時点でデスクトップLinuxには公式対応しておらず、今回は有志の方が公開されているリポジトリを使っています。
:::


# Claude Desktopのインストール
Cluade Desktopは[公式](https://claude.ai/download)にはMacとWindowsのみ対応なので、Ubuntuへインストールするため有志の方が公開している以下リポジトリを使用させていただきました。

https://github.com/aaddrick/claude-desktop-debian

インストールはREADMEにある通りなのですが、debファイルのインストールはaptコマンドでも良いと思いました。

~~~bash
git clone https://github.com/aaddrick/claude-desktop-debian.git
cd claude-desktop-debian
sudo ./build-deb.sh
sudo apt install ./build/claude-desktop_{YOUR_VERSION}_amd64.deb
~~~


# Claude Codeのインストール
Claude CodeはUbuntu22.04でも公式に対応しているので、以下公式ページに従いインストールします。

https://docs.anthropic.com/ja/docs/agents-and-tools/claude-code/overview

~~~bash
npm install -g @anthropic-ai/claude-code
cluade
# https://console.anthropic.com/ でAPI Keyを作成し登録する必要があります(初回は前払いが必要になります)
~~~

# MCPの設定
私の環境では`~/.config/Claude/`にある`claude_desktop_config.json`の設定を読み込んでいました。([参考issue](https://github.com/aaddrick/claude-desktop-debian/issues/27))
以下設定でCalude Desktop起動時にMCPとしてclaude_codeが有効化されました。

~~~json:~/.config/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "claude_code": {
      "command": "/home/{YOUR_NAME}/.nvm/versions/node/v20.15.0/bin/node",
      "args": ["/home/{YOUR_NAME}/.nvm/versions/node/v20.15.0/bin/claude", "mcp", "serve"],
      "env": {
          "NODE_PATH": "/home/{YOUR_NAME}/.nvm/versions/node/v20.15.0/lib/node_modules"
      }
    }
  }
}
~~~

:::note warn
自分の環境ではClaude Desktopがnodeのバージョンを上手く読み込んでくれなかったため、各コマンドをフルパスで指定し、`env`にも`NODE_PATH"`を追加しています。
:::

![mcp_claude_code.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2691924/8624f220-d0b3-4578-bc39-e030c9801105.png)


設定エラーの解消や新規設定の追加など、`claude_desktop_config.json`を再度読み込みさせる場合は、デスクトップ上部のClaudeアイコンからClaude Desktopを終了させるか、ターミナルから関連するプロセスを全て終了させてからにしてください。(ウィンドウを閉じるだけだと常駐プロセスが残るためです)
~~~bash
pgrep -f claude-desktop | xargs kill -9
~~~

# Claude DesktopからClaude Codeを使う
Claude Codeが使われるか試してみましたが、プロンプト実行後に許可を問われたため動いてそうです。
![cluade_code000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2691924/c01c43df-cad5-4cfb-a440-fd28b134c26a.png)
ローカル環境でのファイル作成やディレクトリ確認も問題なく進行しています。
![cluade_code001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2691924/4fd4373d-89cb-4035-8e55-c198a7a9558d.png)
renderの使い方

## はじめに

この記事では、Railsにおけるビューの描画を担当するrenderメソッドについて、基本的な使い方から実践的な活用方法までを解説します。

「Railsのrenderってよく見るけど、どういう動きをするの？」と疑問に思っている方や、「redirect_toとの違いが曖昧…」という方の参考になれば幸いです！

##   renderとは？
### renderの役割

Railsのrenderメソッドとは、**指定したビューを描画（レンダリング）**するためのメソッドです。
代表的なものとして、webサイトにおけるフッターとヘッダーはどのページへ遷移しても表示させたい。そんな時にrenderが便利に働いてくれます。

例えば、app/views/users/show.html.erbを表示するには、以下のように書きます。

~~~ruby:UsersController.rb
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    render "show"
  end
end
~~~


### renderの具体的な使い方

#### 1. 基本的なビューの描画

例えば、`app/views/products/index.html.erb`を表示する場合は、

`render "products/index"`

と書くことで、指定したビューが描画されます

#### 2. パーシャルの利用（render partial:）

パーシャル（部品化されたビュー）をレンダリングする際には、partial:オプションを使用します。

###### 例：パーシャルを利用したリスト表示

`app/views/users/_user.html.erb（パーシャル）`


~~~erb:_user.html.erb<div class="user">
  <p><%= user.name %></p>
</div>

app/views/users/index.html.erb

<% @users.each do |user| %>
  <%= render partial: "user", locals: { user: user } %>
<% end %>
~~~

::: note
ポイント
	•	partial: "user"と書くことで、_user.html.erbを呼び出せる
	•	locals:を使うと、パーシャル内でuser変数を使用できる
:::


#### 3. インラインテンプレート（render inline:）

テンプレートをファイルとして用意せず、直接文字列としてレンダリングできます。

`render inline: "<h1>Hello, <%= @user.name %></h1>"`

これはあまり使われませんが、簡単なデバッグや一時的な表示で便利です。


#### 4. ファイルの直接指定（render file:）

`render file:`を使うと、特定のパスにあるビューを直接描画できます。

`render file: "app/views/static_pages/about"`

ただし、通常の`render "static_pages/about"`とほぼ同じ動作をするため、基本的には`file:`を指定せずにシンプルに書くのがベストです。

### renderとredirect_toの違い

| 1 | 2 | 3 |
|:-:|:-:|:-:|
| メソッド | 動作 |使い所 |
|  render    | 同じリクエストないでビューを描画 |エラーメッセージを表示したいとき   |
| redirect_to     |新しいリクエストとして別のURLへ遷移| フォーム送信後に別ページへ遷移するとき |


具体例

~~~example.rb
def create
  @user = User.new(user_params)
  if @user.save
    redirect_to @user, notice: "ユーザーが作成されました"
  else
    render "new"
  end
end
~~~

::: note	
•	保存成功時はredirect_toで詳細ページへリダイレクト
•	保存失敗時はrender "new"でフォームを再表示（リクエストを保持）
:::
この使い分けを理解しておくと、面接でも「適切に選択できる」とアピールできます！

### render使用時の注意点

#### 1. 二重レンダリングエラー

以下のようにrenderの後にredirect_toを書いてしまうとエラーになります。

~~~example.rb
def show
  @user = User.find(params[:id])
  render "show"
  redirect_to root_path # エラー！
end
~~~

:::note warn
解決策：returnを使う
:::
~~~example.rb
def show
  @user = User.find(params[:id])
  return render "show" if @user.nil?
  redirect_to root_path
end
~~~


## まとめ
•	renderはRailsのビューを描画するメソッドで、パーシャルにも対応
•	redirect_toとの違いを理解し、適切に使い分けることが重要