OmniAICreator/Qiita-1.07M huggingface dataset:
ExcelからDataverseに接続してテーブルのデータを自動で取得する方法

## 概要
DataverseのデータをExcelにリアルタイムで取得する方法をご説明します！


## 手順
:one: 新しくExcelファイルを作成します
　「データの取得」>「Power Platform から」>「Dataverse から」を選択します。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/481856d3-4441-490e-829b-c55782f700a4.png)

:two: 取得したいテーブルを選択します
　「取得したいテーブル名を選択」>「データの変換」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/697d6ccf-016b-46af-920c-182005986b0f.png)

:three: Power Query エディターが立ち上がります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/fa025513-a72f-45b3-9579-7b8113229f56.png)

:four: 取り込みを行いたいカラムの整理を行っていきます。
　現状すべてのカラムが取り込まれているので不要なカラムは削除していきます。
　カラムが選択できたら「列の削除」を選択してください。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/1bd3a70d-221b-4b87-96b3-d096d321bb1a.png)

:five: 列名を変更
　不要なカラムを削除できたら、列名を分かりやすいように変更していきます。
　デフォルトは論理名で入っているので必要であれば分かりやすい名前に変更してください。
　変更方法は列名をダブルクリックすると変更ができます。
 【変更前】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/4715496d-53fb-448c-8114-f7ee3c047c27.png)

【変更後】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/c0f59723-0123-436c-a839-89f94e158ed8.png)

:six: Excelに取込
　必要な修正を行えたら左上にある「閉じて読み込む」を選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/3bb87aab-565e-4aba-b739-d9b25c3c0a1d.png)

開いていたExcelにテーブルで読み込むことに成功しました。
H～J列はあえて列名を変更していません。その場合は以下のように論理名がそのまま入ることになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/0db6ce78-00e1-413b-a219-53b791275738.png)

:seven: データの自動更新について
　「クエリと接続」> 右側に表示されるクエリを→クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/3d3b7ce3-726c-4548-8bba-f40991da42d1.png)

一番したの「プロパティ...」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/42cd962a-bcab-4082-b078-5086474713f4.png)


クエリプロパティが開くので [コントロールの更新]で
「ファイルを開くときにデータを更新する」に✅をいれてください。
そうすることによって、Excelファイルを開くたびに自動的に Dataverse からデータを取得して常に最新の状態のデータがExcelに表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/fb6cbf23-ca73-4622-b2c1-d7a98ec47bd3.png)
ffmpegでgifを作って埋め込む

# はじめに

![xfadesample4_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/d143860c-2f60-4a94-b98e-a6bb47bdb57a.gif)

このように、埋め込むことができます。

コマンド：


ffmpeg -loop 1 -t 2 -i marinebubbles.png -loop 1 -t 8 -i marinebubbles_text.png -filter_complex "[0][1]xfade=transition=smoothright:duration=2:offset=0,format=yuv420p [2];[2][0] xfade=transition=smoothright:duration=2:offset=6,format=yuv420p [3]" -map [3] xfadesample4_1.gif

marinebubbles.png:

![marinebubbles.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/b78a0532-55d6-48bb-9b7f-8c5a9c6b5ccd.png)

marinebubbles_text.png:

![marinebubbles_text.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437349/32927d1e-6eb2-448b-b209-d6ac2fe0483f.png)

このように、あらかじめテキストが入った画像を別に作っておきます。
テキストが入った画像を作るには、あらかじめファイルを用意しておき...

marinebubbles.txt:
```js
setup=_=>{createCanvas(w=640,w);background(w);
(h=blendMode)(DIFFERENCE);
stroke(5,3,2);for(f=0;f<=90;f++){for(i=0;i<=w;i++){n=noise(i/99,f);
line(i,2*w,i,200+f*6-240*n)}}noStroke();fill(96);h(SCREEN);
for(k=0;k<w;k++){circle(x=(u=random)(w),y=u(w),u(y/20))}}
```

次のコマンドで生成します（フォントファイルは別途用意します）

ffmpeg -i marinebubbles.png -filter_complex "drawtext=fontfile=KosugiMaru-Regular.ttf:fontsize=16:fontcolor=black:x=16:y=16:textfile=marinebubbles.txt:line_spacing=-4" -pix_fmt yuv420p marinebubbles_text.png

これらをクロスフェードでつなげると、あのgifになります。

# おわりに
　ここまでお読みいただいてありがとうございました。
NotebookLMでポッドキャストを作って資料から講演を聞いた気になってみる

# No music No life

こんにちは。
さいきん、弊社では働いているときにヘッドフォンで音楽を聴くことが認められるようになりました。

なんでそうなったかというとなんか……社内の満足度をアゲるぞというアンケートツールが導入されて、それで誰かがお願いしたら上の人が「いいよいいよ」といったようです。

もともとねー、ハード開発もやっているのでそっちではラジオが流れていたんですが、エンジニアにも認められるようになったわけ、なんですね。

いいんだ……。

まあ、テレワークの時とか、聞いてるしなー。

今までも自席で講義を受講することはあったのですが、まさか息抜きのためにこれをしていいとは、驚きです。

音楽が良ければポッドキャストもよかろうと思ってこちらの記事を参考にいくつか聞いてみました。

https://qiita.com/katokonigiry/items/3c6442bfc3244f70bddc

もともと知っていたゆるコンピューター科学ラジオのほか、momit.fmが非常におもろかった。

おすすめエピソード「これからエンジニアを目指す人の勉強法とAIとの向き合い方 w/ゲストnaoさん」を聞いてみたのですが、この転職エピソード、ラジオ内でも語られているんですが紹介されている女性がシゴデキで自分のキャリアを見据えてストイックにストイックに努力されるような方で「あ、ハイ、すみませんでした……」となりました。なにやっても着実に堅実に努力のできる人種っているよな……。

ほか、子供がダウンした時のいろいろな連絡やらを自動化しようとしていてものすごいよかった。エンジニアだな……。

テック系以外だとSpotifiyで英語のリスニングかけながし、なんてのもあって、ポッドキャストには可能性を感じています。

楽をしたいから。なるべく寝そべって知識だけ得たいから。怠惰がゆえに。

# そんな時出てきたNotebookLMの日本語のポッドキャストを作る機能である

NotebookLMでポッドキャストが生成できるというではありませんか。

もともとインプットはテキスト派でね？　なーんていいたいところですが最近これが読んでないんだなあ、論文を。

同僚が英語版を紹介していたときは英語が堪能ではないので「あら～すげえや～」と思っていたのですが日本語対応してみてから、威力に打ちのめされる。音声にところどころAIだなというイントネーションの違和感は残るものの、しゃべりがものすごく自然だし、私よりうまい。
試しに、参照で会社のHPを入れてみたら「言ってしまえば物を作るというのは、ただ実装するだけではなく、価値を創出する仕事ということなんですね」みたいな「言ってそ～～～！」というセリフをずらっずら、ずらずらよどみなく話します。内容はコンテキストに押しつぶされてそうというか、教えてやんなきゃ深くはないな、と思ったのですが。

無料で５件くらいつくったら一日の上限に引っかかってしまったんですが、無料なのがすごい。もっとヘヴィーに使い倒す人は課金されることでしょう。イエス。

Xでは、「概況を把握してURLを突っ込んでキャッチアップする」というような意識の高い使い方を提案されてました。んなバカな～と思いつつも実際やってみたら思った以上にいい感じ。入れてポチ、でした。

同僚が「良い講演を聞いてきたよ。社内共有していいよ～」とくれたPDFを入れてみました。
学習データとしては使われないようなので、大丈夫。のはず。とはいえ社外秘を含む内容は入れてはいけないですが。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/80bc7362-3469-4688-a3fd-331e14c64ff4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/dca79740-9016-4c46-b520-9e681101b21f.png)

カスタマイズを何度やっても英語になってしまいましたが、歯車からOutputLanguageを変えましょう。

# まとめ

**英語で「パーセプトロン」と言われた時の絶望と、日本語で「いわゆるパーセプトロン」と言われた時の、絶望感、違う。**

意味不明なほどに難しすぎる話が日本語として聞き流せるくらいになってものすごく感動しました。
これであれでしょ？？？　分かった気になったらぜんぜんそうではなくて泣くことになるんでしょ？？？

たぶん、これでキャッチアップするわけにはいかないんですが、輪郭をつかむのにはよさそうだし、最近怠っていたので０よりは１でいいよね？？
あと、対話形式で日本語だというところに安心感はあります。

今まで、情報にものすごく敏感な同僚がいるので、それにあやかろうとおもって、紹介された論文をChatGPTにコピペしてたりしてがんばってかじりついていたんですが、怠り気味でした。

これならかなり良い感じにいい。０よりはいい。ゆるーっと勉強していきたいもんですね。

## NotebookLMを知らない人をびっくりさせるのに、ぴったり
ほんとに資料を入れてボタンぽちーっという炊飯器みたいな感じでできるんですが、台本をいじる必要がないのにかなりビビりました。よく読むと不正確でおおざっぱでサイアクみたいなところがあるんだと思います。AIだもの。

ものすごい変な角度から「こういうことできたん？？？」と思った稀有な体験でした。
このことを知らない経営層に紹介したり、朝礼ネタに使ったら手間の割に苦労しているように見えるかもしれません。今なら。今なら。今ならね。
CSSを学ぼうシリーズその2(全5回)：transitionでワンポイントアニメ

## CSSアニメーション、使ってますか？

* HTML要素をアニメーションさせるなら大抵のものはCSSのみで可能
  ただしJSでclassの付与／除去程度は必要
* 使いすぎは良くないが、ちょっとした動きを付けるのに効果的

※リッチなアニメーションはJavaScriptを使う。そのためのAPIが備わっている

----
## CSSアニメーションの種類
* keyframesを使った本格的なもの
  [CSS Loaders](https://css-loaders.com/)
* transitionを使った簡易なアニメーション
  ワンポイントで使うならこれで充分！

----
## transitionの考え方
* プロパティの値の変化の仕方を指定する
  対象のプロパティ／変化スピード／加速関数
* HTML要素に２つの状態（例えば通常時とマウスオーバー時）を持たせ、それをtransitionでゆっくり切り替える感じ

----
## 具体例１）フェードイン／アウト

* opacity：不透明度。1が不透明、0が透明
```css
.fade-in {
  transition: opacity 1s ease-in-out;
}
.fade-in-initial {
  opacity: 0;
}
```

```js
document.addEventListener('DOMContentLoaded', () => {
  setTimeout(() => {
    const fadeInButton = document.querySelector('.fade-in');
    fadeInButton.classList.remove('fade-in-initial');
  }, 1000); // 1秒後にフェードインを開始
});
```
* 画面表示直後は ```opacity: 0;``` を指定
  つまり見えない状態
* 画面表示後にJavaScriptを使って ```opacity```を除去（つまりopacity: 1;となる）

----
## 具体例２）マウスホバー時の強調表示

```ccs
.enphasis {
  transition: background-color 0.2s ease-in-out;
}
.enphasis:hover {
  background-color: rgba(255, 0, 0, .2);
}
```
※JS不要！

----
## 応用
* transformを使うと相当いろいろできる！
  移動／拡大／縮小／かいて　など

----
## 最後に
* 強調表示にワンポイントは有効
* 自前で実装することは少ないかもしれないが、知っておくとちょっと楽しい
Databricksジョブで特定のタスクのみを実行できるようになりました

こちらのアップデートです。

![Screenshot 2025-05-08 at 9.25.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/c2a05e12-b584-4776-b9cb-66685d022146.png)

> **Databricksジョブで特定のタスクの実行**
> ワークフローがより柔軟になりました - Databricksジョブで特定のタスクを実行できるようになりました。ジョブの開発やデバッグを繰り返す際に、時間と計算コストの両方を削減するためにこの機能を活用しましょう。「別の設定で実行」をクリックし、タスクあるいはタスクのグループを選択し、必要に応じてパラメータを上書きし、必要なタスクのみを実行します。これは、UIとJobs APIの両方でサポートされています。
> [詳細を表示](https://docs.databricks.com/aws/ja/jobs/run-now#%E7%95%B0%E3%81%AA%E3%82%8B%E8%A8%AD%E5%AE%9A%E3%81%A7%E3%82%B8%E3%83%A7%E3%83%96%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)

これまでにも、**ジョブ実行の修復**で似たことはできましたが、修復したタスクの後続のタスクもすべて実行されてしまうので、デバッグには不向きでした。

試してみます。

ジョブにアクセスして**別の設定で今すぐ実行**をクリックします。

![Screenshot 2025-05-08 at 9.33.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/dd09fbf4-bd4e-41d0-8ff6-bdc5ccc2f823.png)

実行するタスクを選択できるようになっています。

![Screenshot 2025-05-08 at 9.25.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/87e8b963-8c26-4efd-8a5c-113f53121257.png)

選択されなかったタスクは、**無効化済み**とマークされて実行されません。

![Screenshot 2025-05-08 at 9.26.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/d1fdedb3-8603-43d1-a63a-36bd3977354b.png)
![Screenshot 2025-05-08 at 9.26.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/3b649c71-52f7-4d51-9065-25b8db795c21.png)
![Screenshot 2025-05-08 at 9.28.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/08c64dc8-96ed-438f-8b0d-2f1b4c595b6f.png)

選択されなかった後段のタスクは実行されません。

![Screenshot 2025-05-08 at 9.28.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7b74efdd-5caa-49d8-adfd-ed59d2e9810a.png)

ジョブのデバッグにご活用ください！

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Vibe Codingでアプリ10本作成チャレンジ

## はじめに

2025年のゴールデンウィーク、私は**「10本のアプリを開発する」**という目標を立てました。

普通なら私のスキルとスピードでは1本作るのが精一杯。しかし、先月知った**Vibe Coding**という手法で**AI（ChatGPT / Claude）**の力を借りれば、劇的に生産性が上がるのでは？と考えました。

普段から**Twilioの小規模デモアプリ**を多く開発している私にとって、これは新技術を試し、**AIとの効率的な開発プロセス**を確立する絶好の機会でした。

結果——  
**合計7日間で10本**。  
このチャレンジは成功に終わりました。無事に10本にわたるアプリの作成が完了しました。
このときに作ったアプリについては、後日ブログに書きます。

ちなみに、このブログは完全に私の個人的な感想になりますので、体験談を聞きたい方は読み進めてください。

**利用したAI**は以下になります。
Opne AI : ChatGpt / codex
Anthropic  : Claude / Claude code

## AIによるアプリ開発の特徴
### AIとの共同開発で特に印象的だった点：

- **脅威の開発スピード**: 従来なら数日かかるプロトタイプが**数時間**で完成
- **最小限のデフォルトUI**: 指示がなければシンプル、明確に指示すれば洗練されたUIに
- **AIの個性**: ログ出力に絵文字や励ましコメントが登場（これは本当に要らない）

### 困難だったこと

- **失敗時の「デモモード」提案**  
  同じ機能の実装に失敗が続くと、AIが「簡易版のデモモード」を勝手に作る
- **トークン消費の急増**  
  同じエラーが解決せずに複数回の書き直しで**トークン消費量爆増**（私はClaudeのMaxプラン加入に…）

## Twilioデモ開発時の工夫

Twilio SDKの**バージョン互換問題**に直面：

- **SDKバージョンを明示的に指定**
- **最新の公式ドキュメントURLをAIに提示**
- **公式サンプルコードを必ず確認**

これにより**古いコードの自動生成**を回避できました。

## アプリ10本チャレンジで作成したアプリの一例
Webサイト x 6, ブラウザ拡張 x 2, Macアプリ x 2 で作成しました。

### 1. 翻訳機能付きTwilioブラウザ電話
リアルタイムで発言を選択言語に翻訳。ブラウザ電話を使って自分で話した内容が翻訳されて聞こえてきます。

### 2. リストファイルを使った自動架電ツール
CSVから電話番号を読み込み自動発信。昔から何度も作られてるけど、再トライ。

### 3. LocalTube
ローカル動画を**YouTube風UI**で閲覧・再生。FFmpegのバッチ処理でサムネ生成を効率化。



## 失敗から学んだ教訓

- **エラーは自分で修正方針を示す**  
  でないとAIが**勝手に機能の全部を削除**することがある
- **バージョン指定は必須**  
  Twilio Voice JS SDKは**古い1系でコードを生成**されがち
- **AIに丸投げしない**  
  問題解決に**人間も積極的に介入**する。自分の知らないことを挑戦させるなら代償を伴うことも（大量のトークン消費)

## Vibe Codingの活用法

Vibe Codingの主な効果：

- 自然言語からの**迅速なコード生成**
- 思いつきを後からどんどん実装できる
- コードの**最適化提案とデバッグ**
- プロジェクト設計のサポート

Twilioなど**API活用プロジェクト**や**小規模プロジェクト**で特に有用。**ドキュメント調査の手間が大幅減**。

## GWチャレンジで得た教訓

1. **Vibe Codingでも事前準備があれば、開発速度は早い**  
   アプリリスト、技術スタック、APIキーを事前用意
2. **タイムボックス開発**  
   各アプリに時間制限。優先機能に集中
3. **小さな成功体験**  
   動作するアプリの完成が**学びとモチベ**向上につながった

## まとめ

AIとの開発は**明確な指示と戦略**があれば、**非常に効率的**。

GWチャレンジを通じて、AIの強みを引き出し、自分の技術力も大幅に向上できました。
って勘違い出来るレベルで作れます。
正直自分が仕事でつくるような小規模デモアプリならば、かなり効率的に作っていけそうだと感じました。
Vibe Codingというラフな開発手法を経験したことで良し悪しが分かったので、自分のスタイルに合うようなAIとの開発スタイルを確立していきたいと思います。

### これからAIとの開発に挑戦する方へ：

- **明確かつ具体的な指示**を出す
    - 曖昧な説明や機能の情報では、目的としたものは出来ない
- **自分の理解範囲内**の技術を選ぶ（トークン消費を抑える）
    - 自分で理解できていないと、的確な指示を出せない
- **段階的に**機能追加＆テスト
    - 機能開発を少しづつ進めていくことで、回復可能な状態になり戻しやすい
- **時間制限**を設け、再度出直すことも検討しながら進める
    - AIは指示通りに進むが、人間による見極めが重要で、エラー発生が多いのであれば、仕様を変えて出直すのがよい
---

それではまた次の機会に
英語の先生に教わった！語彙力と発音を伸ばすための本質的なアプローチ

４月に始めたレアジョブ英会話。
月に一回日本人の先生とサポートレッスンがあり、英語の練習どう進めたらいいかの相談ができます。

今回は、「どうやったら英語のボキャブラリーが増えて、発音もうまくなるのか？」
という話をじっくりしました。

そこで出てきたアイディアがとても腑に落ちたので備忘メモ。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664191/32ed4060-b3c4-4682-9971-8e2a59f68e85.png" alt="語彙力と発音を伸ばすためのアプローチ" width="500">


---

## 発音の基本は「44の音」を知ることから

まずは発音について。  
日本人は小さいころから50音に慣れ親しんでいるので、それ以外の音を身体に染み込ませるのが難しいんです。だからこそ「英語の音を一つひとつ意識して学ぶ」ことが大切。

先生が教えてくれたのは、YouTubeの **Sounds American** というチャンネルを使って、**英語の44の音（フォニックス）**を丁寧に学ぶ方法。  
発音は「なんとなく真似する」ではなく、「音を意識して体に覚えさせる」のがポイントなんですね。

https://www.youtube.com/@SoundsAmerican

---

## 単語を覚えるには「感情・集中・イメージ」の3つが鍵

次に語彙力アップについて。  
ただ「やらなきゃ」と思って暗記しようとすると、なかなか頭に入りませんよね。先生いわく、**子どもが言葉を覚えるときのように、「感情・集中・イメージ」を大切にすることが効果的**なんだそうです。

### 1. 感情を動かす

嬉しかったこと、怒ったこと、びっくりしたこと。  
**強く感情が動いた瞬間に使われた言葉**って、忘れにくいんです。だから、そういう感情に結びついた単語や表現を意識的に覚えてみる。

### 2. 集中する

新しい単語に出会ったら、**その言葉だけに集中する時間**を作ります。  
発音や文法のことはいったん置いておいて、とにかくその単語にじっくり向き合う。

### 3. イメージを持つ

たとえば「dog（犬）」という単語があったら、犬に関する自分の記憶や体験をどんどん思い出します。

- 子どものころ飼っていた犬  
- ペットショップで見た犬  
- 噛まれて痛かった思い出…！

こうした「**その単語にまつわる自分のストーリー**」を思い出しながら、画像検索なども活用してイメージを膨らませていくと、記憶にしっかり残ります。

そして、それを**英語で表現**してみます。たとえばChatGPTなどを使って、「このエピソードって英語でどう言えばいいの？」と確認するのもおすすめです。

---

## 学んだ単語をビジネス英語に広げるには？

この「感情・集中・イメージ」の方法は、**ビジネス英語にも応用**できます。

たとえば「team role（チームでの役割）」という言葉。  
自分の役割、相手の役割、今のチームに足りない要素…そういうことを考える中で、「嬉しかったこと」「嫌だったこと」「達成感を感じたこと」など**感情が動いた場面を思い出して英語で表現してみる**んです。

そうすると、言葉が「生きたもの」として自分の中に残っていく。こういうプロセスを通して、語彙力も表現力もどんどん自然に伸びていくと感じました。

---

このように、**感情と結びつけて、イメージで覚えて、実際に英語で使ってみる**というサイクルを大切にしていきたいですね。
サイトのほとんどのコンテンツが欠落しており、エージェントダイアログも表示されません。



+ [I completed the Build Your First Agent with Agentforce Trailhead but the site doesn't have all the content](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000mzd1)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0333d360-159e-44cc-9967-5ac5ed403ca4.png)

:::note
For those that get stuck here, what worked for me is:

1. remove the Embedded Messaging component from the site
2. publish the site
3. add the component back in and republish

The rest of the site content should now be there.

ここで行き詰まっている人のために、私にとってうまくいった方法は次のとおりです。

1. サイトから埋め込みメッセージングコンポーネントを削除する
2. サイトを公開する
3. コンポーネントを再度追加して再公開する

サイトの残りのコンテンツも表示されるはずです。
:::




+ [【未解決】Unable to view Coral Cloud Resorts site as "customer"](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KBCZv)
+ [【未解決】Create an Agent Salesforce](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KCW1y0AH)
Agentforce Actions のエラー We Hit a snag



+ [Unable to see the inputs and output section while I am creating an agent action](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PZpNI)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/57e3e1a5-3566-447a-959e-e2878dcf7a65.png)

:::note
Cross-check that you have at least one variable set to input and one for output in the referenced flow. 
:::

+ [少なくとも 1 つの入力が必要なため、エラーが発生します。](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000m5Dx)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a0224543-e1b4-02cd-bfdc-c807d229d7e6.png)

:::note
現在、Agentforce Actions にバグがあります。通貨変数を入力としてフローを使用するアクションを作成すると、エージェント アクション構成ポップアップ ウィンドウに入力が表示されず、少なくとも 1 つの入力が必要なため、エラーが発生します。 
:::

+ [Facing an issue when run the custom action in an Agentforce service agent.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Kheas)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/012c7983-7dbf-bd98-3ae7-6f4a4563487d.png)

+ [Agentforce エージェントのトピックについて少し助けが必要です。フローを作成し、エージェントにアタッチしましたが、出力を取得できません。](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000SW96z)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a334361c-b3b1-4b4f-a98b-d60f7b2d11b6.png)

+ [Looks like you don't have access to IDENTIFY_RECORD_BY_NAME.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000TiQt)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/eff23832-3556-4caa-a9ce-9a6b7fc81bec.png)



+ [Error "We couldn't retrieve the action output. Try again or contact Salesforce Customer Support for assistance." when executing an Action that returns a complex APEX type](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000SWFyf0AH)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/bf783bdc-4e42-445c-980f-0bd23759997c.png)
javaのコンパイルについて今更まとめてみた

# はじめに
java silverの勉強を開始したところで、基礎的な言葉について理解・説明できていないと感じたため、まとめてみた。

## コンパイラ
コンパイルするためのソフトウェアのこと。
### コンパイル
プログラムとCPが理解できる言語に変換すること。
Javaの場合、中間言語（バイトコード）に翻訳する。（Javaファイル→classファイル）
JavaはWindows、Mac、Linux等の環境で実行できるため、中間言語にコンパイル。
その中間言語をJVMが機械語に翻訳する。
```linux:test
#コンパイルのコマンド
javac Javaファイル名
```
オプションは以下の通り。
|オプション|詳細|
|---|----|
|-d|出力ディレクトリ指定|
|-source|ソースコードのバージョン指定|
|-target|生成するバイトコードのバージョン指定）|
|-encoding|エンコード指定|
|-verbose|処理詳細表示|

## JVM
Java仮想マシン（Java Virtual Machine）
中間言語を機械語に翻訳する。

## JDK
Java Development Kit
開発者向けの完全なJava開発環境
以下構成
* コンパイラ（Javac）
* デバッカ（jdc）
* ドキュメント生成ツール（javadoc）
* その他開発ツール群

## JRE
Java Runtime Environment
Javaアプリケーション実行に必要な最小限の環境
以下構成
* Java仮想マシン（JVM）
* 標準クラスライブラリ
* 実行時に必要なファイル

## 参考文献
* https://eng-entrance.com/java-basic-compile
* https://dexall.co.jp/articles/?p=576
個人的備忘録：FastAPI × Next.jsでAI応答を受け取り、画面に表示する仕組みを実装してみた

## はじめに

Next.js（React）と FastAPI を連携したアプリケーションで、ユーザーが日記を投稿すると、AI（さぶちゃん）からの応援メッセージが返ってくる機能を実装しています。

本記事では、返答内容を「さぶちゃんからの熱いエール」欄に画面表示する方法を紹介します。

## 書こうと思ったきっかけ

受講しているITスクールのハッカソンの開発の一環で、日記投稿後の返答メッセージを見せる仕組みを作ろうとした際に、応答の扱いと表示形式の工夫が必要だったため、記録としてまとめました。

**実際の画面（開発中）**

![Screenshot 2025-05-08 at 8.20.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/540720ce-949a-41ae-b564-b158b9b64c15.png)

**実際の画面（一旦、完成画面）**

![Screenshot 2025-05-08 at 8.21.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/c40e828f-f7dc-416d-a1a1-9f82c26b96f5.png)

## 内容

以下は実際に使用している `SabutyanMode` コンポーネントの抜粋コードです。応援メッセージの表示に関係する部分を中心に紹介します。

### 状態管理

```tsx
const [diaryMessage, setDiaryMessage] = useState("");
const [cheerMessage, setCheerMessage] = useState("");
```

ユーザーが入力した日記（`diaryMessage`）と、APIからの応答メッセージ（`cheerMessage`）を別々の状態で管理しています。

### 応援メッセージの取得処理

```tsx
const handleEnergy = async () => {
  if (!sessionId) {
    alert("セッションIDが見つかりません");
    return;
  }

  try {
    const payload = {
      session_id: Number(sessionId),
      is_user: true,
      content: diaryMessage,
    };

    const res = await fetch(`http://localhost:8000/api/sessions/${sessionId}/messages`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    if (!res.ok) throw new Error("送信に失敗しました");

    const result = await res.json();
    setCheerMessage(result.content || "さぶちゃんから応援が届きました！");
  } catch (error) {
    console.error("エラー:", error);
    alert("エラーが発生しました");
  }
};
```

API のレスポンスから `result.content` を取得し、それを `cheerMessage` にセットしています。

### 応援メッセージの表示エリア

```tsx
<div className="w-full h-32 border border-gray-300 rounded-md p-3 bg-[#fffaf0] whitespace-pre-wrap overflow-y-auto">
  {cheerMessage || "ここにさぶちゃんの応援が表示されます"}
</div>
```

この表示専用 `div` によって、API から受け取った応援メッセージがリアルタイムに画面に表示される仕組みとなっています。

### 起きていた問題

* 日記欄と応援メッセージ欄に同じ状態変数を使っていたため、文字が連動していた
* 応援メッセージを表示させたいが、textarea ではユーザーが編集できてしまう

### 修正内容

#### 1. 状態管理を分離

```tsx
const [diaryMessage, setDiaryMessage] = useState("");
const [cheerMessage, setCheerMessage] = useState("");
```

#### 2. FastAPI 応答を cheerMessage にセット

```tsx
const result = await res.json();
setCheerMessage(result.content || "さぶちゃんから応援が届きました！");
```

#### 3. 表示専用のエール欄を div に変更

```tsx
<div className="w-full h-32 border border-gray-300 rounded-md p-3 bg-[#fffaf0] whitespace-pre-wrap overflow-y-auto">
  {cheerMessage || "ここにさぶちゃんの応援が表示されます"}
</div>
```

* textarea を div に変更し、ユーザーが編集できないように
* `whitespace-pre-wrap` によって改行も反映

## まとめ

フォームで状態変数を共通化すると文字が連動してしまうため、用途ごとに状態を分ける必要があります。

:::note warn
**また、表示専用の応答欄には `div` を用いて、ユーザーが内容を編集できないようにすることが重要です。**
:::

これにより、ユーザーが入力した日記に対して、さぶちゃんからの応援を自然な形で表示できるようになりました...！
個人的備忘録：FastAPI開発中に遭遇した「session_id 不明」での404エラー解決メモ

## はじめに

FastAPI でセッションに紐づくメッセージ処理を行う際、"セッションIDが見つからない"という問題が発生することがあります。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

本記事では、404エラーの原因となる `session_id` の取り扱いと、正しく動作させるための対処法についてまとめます。

## 書こうと思ったきっかけ

受講しているITスクールのハッカソンの開発の一環で、セッションを利用したメッセージ保存機能を実装中、APIが404を返す現象に遭遇しました。原因調査と解決までの流れを記録しておきます。

## 内容

### 発生したエラー

FastAPI のログに以下のような記録がありました：

```
SELECT * FROM sessions WHERE sessions.id = 1 LIMIT 1;
ROLLBACK
"POST /api/sessions/1/messages HTTP/1.1" 404 Not Found
```

これは、セッションID 1 のレコードが `sessions` テーブルに存在しておらず、クエリが失敗しているために発生しています。

### 主な原因と対処法

#### 原因1: sessions テーブルに id = 1 の行が存在しない

この場合は、以下のような SQL で手動でデータを追加します：

```sql
INSERT INTO sessions (
  id,
  user_id,
  character_mode,
  created_at,
  updated_at
) VALUES (
  1,
  1,
  'saburo',
  NOW(),
  NOW()
);
```

#### 原因2: 使用しているデータベースが想定と異なる

FastAPI の `.env` や `DATABASE_URL` の設定で、開発用のDBではなく別のDB（例：test用など）を見ている可能性があります。
その場合、想定しているデータが存在しないDBを参照しているため、見つからないことになります。

#### 原因3: id カラムが SERIAL で、id=1 を手動指定できない

以下のように、`id` を自動採番させて登録し、登録されたIDを確認する方法も有効です：

```sql
INSERT INTO sessions (
  user_id,
  character_mode,
  created_at,
  updated_at
) VALUES (
  1,
  'saburo',
  NOW(),
  NOW()
);

SELECT id FROM sessions ORDER BY id DESC LIMIT 1;
```

### 問題解決後のログ

セッションが存在する状態でメッセージ登録APIを呼び出すと、次のようなログが確認できました：

```
INSERT INTO messages (...) VALUES (...);
COMMIT
"POST /api/sessions/1/messages HTTP/1.1" 200 OK
```

このように、正常に INSERT および 200 OK が返されていれば、セッションの登録とAPI通信が成功していると判断できます。

## まとめ

FastAPI でセッションIDを必要とする処理を行う際、事前にその `session_id` が存在することが前提となります。

:::note alert
**開発時は、必要なレコードを手動で挿入するか、ログイン処理などから自動生成・保存する設計が重要です。**
:::

また、複数の環境（dev/test/prod）を切り替えている場合は、DBの接続先にも注意が必要だと感じました...！
windows11で、sketchup6 その102

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
スクリプト見つけたのでやってみた。

# 参考にしたページ

http://sudaddy.blog.fc2.com

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/fcc86d1f-fd64-4678-aecc-8fff40c2beef.png)

# サンプルコード

```
def show_selected2(o)
	if o.is_a? Sketchup::Face
		no = get_attrib(o, 'objno')
		if no
			no += 1000000;
			no = no.to_s
			msg = "面番号＝" + no[1..2] + '.' + no[3..4] + '.' + no[5..6] + "\n"
		else
			msg = ""
		end
		msg += "辺数 : " + o.edges.length.to_s
		msg += "\n面積 : " + sprintf('%.3f', o.area.to_sqm) + "㎡"
		ro = Sketchup.active_model.rendering_options
		ma = o.material;
		ma = ro['FaceFrontColor'] unless ma
		ma = ma.color if ma.is_a? Sketchup::Material
		ma = ma.to_s;
		ma = ma.gsub(' ', '');
		ma = ma.sub(',255)',')')
		msg += "\n表面 : " + ma
		ma = o.back_material;
		ma = ro['FaceBackColor'] unless ma
		ma = ma.color if ma.is_a? Sketchup::Material
		ma = ma.to_s;
		ma = ma.gsub(' ', '');
		ma = ma.sub(',255)',')')
		msg += "\n裏面 : " + ma
	elsif o.is_a? Sketchup::Edge
		msg = "接面数 : " + o.faces.length.to_s
	end
	bb = o.bounds
	msg += "\n上端 : " + p2c(bb.max)
	msg += "\n中央 : " + p2c(bb.center)
	msg += "\n下端 : " + p2c(bb.min)
	msg += "\n寸法 : " + bb.width.to_s + "×" + bb.depth.to_s + "×" + bb.height.to_s
	alert msg
end

class Numeric
	# π
	def PI
		self * Math::PI
	end
	# ルーメン⇒ワット
	def lm
		3.0 * self / 40.0
	end
	# ワット⇒ルーメン
	def to_lm
		40.0 * self / 3.0
	end
	# 表示用寸法文字列化（mm固定）
	def to_ls
		sprintf('%dmm', self.to_mm)
	end
	# 平方インチ⇒平方メートル
	def to_sqm
		self.to_sqmm / 1000000.0
	end
	# 平方インチ⇒平方ミリメートル
	def to_sqmm
		self * 645.16
	end
	# 尺ユニット換算
	def u
		self * 910.mm
	end
	# 拡張済マーク
	def sudaddy_extension
		true
	end
end

def p2c(p, sep=', ')
	'[' + p.x.to_ls + sep + p.y.to_ls + sep + p.z.to_ls + ']'
end

def p2s(p)
	p2c(p, ',').gsub('mm', '.mm')
end

def get_attrib(e, k, v=nil)
	e.get_attribute('Default', k, v)
end

def get_selected
	sel = Sketchup.active_model.selection
	if sel.length >= 1
		return sel[0]
	else
		return nil
	end
end

def show_selected
	o = get_selected
	if o.is_a? Sketchup::Face
	elsif o.is_a? Sketchup::Edge
	elsif o.is_a? Sketchup::Group
		c = nil
		o.entities.each { |f|
			c = f if f.is_a? Sketchup::Face
		}
		o = c
	elsif o.is_a? Sketchup::ComponentInstance
		m = o.class.to_s
		m += "\nname=" + o.name if o.name
		p = get_attrib(o.definition, 'product')
		m += "\nproduct=" + p if p
		alert m
		return
	else
		alert 'オブジェクトを1つ選択してください。'
		return
	end
	show_selected2(o)
end



```

以上。
【Playwright】実行速度を改善するテクニック

# はじめに
E2Eテストの自動化ツール Playwright は高機能ですが、テストが遅いと開発フローが止まり、CIコストも増大します。  
この記事では、Playwrightの実行速度を改善するテクニックを紹介します。

https://playwright.dev/

# ヘッドレス実行＋高速モード（`headless: 'new'`）

Playwrightではブラウザをヘッドレスで起動するだけで大きな高速化が可能です。  

```ts
const browser = await chromium.launch({ headless: 'new' });
```

- 'new' は従来の true より高速かつ安定
- CIでは必ず有効化し、ローカルでも GUIが不要な場合は推奨

# テストの並列実行（`workers`）
テストファイル単位で並列実行することにより、処理時間を大幅に削減できます。

https://playwright.dev/docs/test-parallel

```powershell
npx playwright test --workers=4
```

```playwright.config.ts
export default defineConfig({
  workers: process.env.CI ? 4 : 1,
});
```

- 目安は「論理CPUコア数 - 1」
- マシン性能に応じて要調整

# テスト対象の絞り込み（.only / --grep）
すべてのテストを毎回実行するのは非効率です。

```test.ts
test.only('ログインできること', async ({ page }) => {
  // テスト本体
});
```

```powershell
npx playwright test --grep '@smoke'
```

- スモークテストや開発中のテストだけを実行し、迅速にフィードバックを得る

# 不要な静的待機を排除（`waitForTimeout` → `waitForSelector`）
固定待機は無駄な時間を生みます。

```test.ts
// NG
await page.waitForTimeout(2000);

// OK
await page.locator('text=保存しました').waitFor();
```

- 状態変化を検知できるセレクタを使い、不要な待機をゼロに

# ログイン状態を保存して前処理をスキップ
毎回のログインはテストを遅くします。

```test.ts
// 初回ログイン後に保存
await context.storageState({ path: 'state.json' });
```

```playwright.config.ts
use: {
  storageState: 'state.json',
}
```
- globalSetup.ts で一度だけログイン＆保存する

# モックAPIでネットワーク遅延を排除
本番APIとの通信はネットワーク遅延や不安定さの原因に。
MSW (Mock Service Worker) などで APIをモックしましょう。

```test.ts
rest.get('/api/user', (req, res, ctx) => {
  return res(ctx.status(200), ctx.json({ name: 'Taro' }));
});
```

実行時間が半分以下になることもあります。

# CI環境向け最適化
CI上ではログやトレースの記録がボトルネックに。

```test.ts
use: {
  trace: process.env.CI ? 'off' : 'on-first-retry',
  video: 'retain-on-failure',
}
```

- trace／video はデバッグ時以外オフに
- Dockerでは --no-sandbox オプションも検討


# まとめ
今回記載したようなテクニックを使って、Playwrightを高速化しましょう。

- [ ] headless: 'new' を有効化
- [ ] --workers で並列実行
- [ ] .only / --grep で対象絞り込み
- [ ] waitForSelector で動的待機
- [ ] storageState でログイン省略
- [ ] モックAPIを活用
- [ ] CI用設定でログ／トレースオフ

他にも実行速度を改善する案があれば、コメントお願いします。

# 参考
- [Parallelism](https://playwright.dev/docs/test-parallel)
- [Trace viewer](https://playwright.dev/docs/trace-viewer)
- [Introduction](https://mswjs.io/docs/)
- [Continuous Integration](https://playwright.dev/docs/ci)
個人的備忘録：ローカル開発中に出た「セッションIDが見つかりません」エラーと戦った話

## はじめに

React や Next.js のアプリケーションで、API にリクエストを送る際に `localStorage` を使って `session_id` を扱うことがあります。本記事では、"セッションIDが見つかりません" というエラーが出た際の原因と解決方法についてまとめます。

## 書こうと思ったきっかけ

受講しているITスクールのハッカソンの開発の一環で、API 呼び出しのときにセッションIDが取得できずに詰まることがあったため、忘れないように原因と対処法を記録しておきます。

**実際の画面**

![Screenshot 2025-05-08 at 8.03.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/6cb50559-ea88-48f4-9f09-22f2acea4034.png)


## 内容

### エラーの概要

アプリ上で以下のようなエラーが表示された：

```
localhost:3000 says
セッションIDが見つかりません
```

このエラーは、以下のようなコードによって発生しています：

```tsx
if (!sessionId) {
  alert("セッションIDが見つかりません");
  return;
}
```

### 原因

`localStorage.getItem("session_id")` の戻り値が `null` や文字列として "null"、"undefined" になっている可能性があります。

そのため、`sessionId` に期待した値が入らず、上記のエラーが発生します。

### 解決策

```js
localStorage.setItem("session_id", "1");
```

#### 一時的な回避策：コード側に一時的に挿入する（開発用）

```tsx
useEffect(() => {
  // ★ テスト用に session_id を強制的にセット
  localStorage.setItem("session_id", "1");

  document.body.classList.add("washitsu");

  const storedToken = localStorage.getItem("token");
  const storedSessionId = localStorage.getItem("session_id");

  if (storedToken) setToken(storedToken);
  if (storedSessionId) setSessionId(storedSessionId);

  return () => {
    document.body.classList.remove("washitsu");
  };
}, []);
```

※ このコードはあくまで開発・デバッグ用途であり、本番環境では削除すること。

### session\_id を安全に扱うために

将来的にはログイン処理などでセッションIDを取得し、ログイン時に以下のように自動で保存するのが理想です：

```js
localStorage.setItem("session_id", response.session_id);
```

## まとめ

「セッションIDが見つかりません」エラーは `localStorage` の値が空であることが原因です。

:::note warn
開発中はブラウザのコンソールや `useEffect` に仮の `session_id` を入れておくとスムーズに動作確認できます。
:::

本番環境ではセッションIDを正しく発行・保存する実装が重要ですので、開発が終わり次第修正いたします...！
Raspberry Pi OS 2025-05-13 / 2025-05-06 Release-note 翻訳

https://downloads.raspberrypi.com/raspios_armhf/release_notes.txt

2025-05-13:
  * スクリーン設定でタッチスクリーンを設定しても、greeter（ログイン画面）のデフォルト関連付けが削除されない問題を修正
  * バグ修正 - ウィザードのキーボード設定が正しくデスクトップに引き継がれるように
  * Chromium を 136.0.7103.92 にアップデート
  * Raspberry Pi ファームウェア bc7f439c234e19371115e07b57c366df59cc1bc7
  * Linux カーネル 6.12.25 - 3dd2c2c507c271d411fab2e82a2b3b7e0b6d3f16

2025-05-06:
  * lxinput のかわりに新しいマウスとキーボードの設定アプリケーション rasputin を追加
  * system-config-printer のかわりに新しいプリンターアプリケーション rpinters を追加
  * labwc 用に swaylock スクリーンロックアプリケーションを追加 - ctrl-alt-L でロック、またはシャットダウンオプションの新しいオプションからアクセス可能
  * raspi-config と Raspberry Pi Configuration にコンソールとデスクトップの自動ログイン用の個別の設定を追加
  * zenity パスワードプロンプトのかわりに新しいコマンドライン版パスワードプロンプトアプリケーション sudopwd を追加
  * zenity のエラー、情報、警告、質問ダイアログのかわりに新しいコマンドライン版ダイアログツール zenoty を追加
  * labwc をバージョン 0.8.1 に更新
  * wf-panel-pi の起動を最適化 - より高速に起動
  * ネットワークマネージャプラグインを最新のアップストリームコードから更新
  * 初回起動ウィザードにビジー表示（ウォッチカーソル）を追加
  * uBlock Origin をプリインストールできなくなったため、Chromium に uBlock Origin Lite をデフォルトでインストールするように変更
  * GPU プラグインとタスクマネージャーに最近のカーネルとの互換性を追加
  * より多くのデフォルトのタッチスクリーン関連付けを追加
  * スクリーン設定でタッチスクリーンのマウスエミュレーションまたはマルチタッチモードを選択する機能を追加
  * Raspberry Pi Configuration で squeekboard オンスクリーンキーボードが表示されるモニターを設定する機能を追加
  * lxpanel と wf-panel-pi のプラグインを再構築し、それぞれの共有プロジェクトからビルドするように変更。これにより、両者間のちがいを削減
  * アピアランス設定と Raspberry Pi Configuration を見直し - X と Wayland 間のさまざまな軽微な不整合に対処
  * Bookshelf アプリケーションから HackSpace を削除
  * バグ修正 - X 環境下でセカンダリモニターのパネルメニューを正しく配置
  * バグ修正 - デスクトップピクチャがモニターの境界をオーバーフローするのを防止
  * バグ修正 - 特定のモニターが設定されていない限り squeekboard が起動しない問題を修正
  * バグ修正 - Chromium Web アプリを含む一部のアプリケーションアイコンがタスクバーで正しく表示されない問題を修正
  * バグ修正 - グリーターのキーボードレイアウトがアップデート時にリセットされる問題を修正
  * バグ修正 - メインメニューのサブメニューが画面に収まらない場合にスクロールできない問題を修正
  * バグ修正 - Connect プラグインが Connect のインストールとアンインストールをより正確に検出するように修正
  * バグ修正 - PackageKit 経由で呼び出された場合に wfpanelctl が正しく動作するように修正
  * その他、さまざまな軽微な調整と更新
  * Chromium を 135.0.7049.84 に更新
  * Firefox を 138.0 に更新
  * Raspberry Pi ファームウェア bc7f439c234e19371115e07b57c366df59cc1bc7
  * Linux カーネル 6.12.25 - 3dd2c2c507c271d411fab2e82a2b3b7e0b6d3f16
ChatGPTを使用したアプリ開発記【プロフィール画面に投稿内容を表示】

## 1. 投稿データ用Contextを作成
```PostContext.js
// Reactライブラリから、Contextを作るcreateContextと状態管理に使うuseStateをインポートしています。
import React, { createContext, useState } from 'react';

// アプリ全体で共有するための「投稿データのコンテキスト」を作成します。PostContext.Providerを使って値を渡します。
export const PostContext = createContext();

// PostProviderというコンポーネントを定義。アプリ全体をこのProviderで包み、投稿データをグローバルに管理できるようにします。
export const PostProvider = ({ children }) => {

// 投稿データ（配列）をpostsとして定義。setPostsで投稿を追加・更新できます。初期値は空の配列です。
  const [posts, setPosts] = useState([]);

// 子コンポーネント（children）すべてにpostsとsetPostsを提供しています。これでどのコンポーネントからでも投稿データにアクセスできます。
  return (
    <PostContext.Provider value={{ posts, setPosts }}>
      {children}
    </PostContext.Provider>
  );
};
```
## 2. AppRouter.jsでContextをラップ
```AppRouter.js
import { PostProvider } from './PostContext';
import App from './App';
import Profile from './Profile';
import {
  BrowserRouter as Router,
  Routes,
  Route
} from 'react-router-dom';


// ルーティング全体をPostProviderで囲み、投稿データをアプリ全体に共有できるようにします。
function AppRouter() {
  return (
    <PostProvider>

//  /にアクセスすればAppコンポーネントが、/profile/:userIdならProfileコンポーネントが表示されます。
      <Router>
        <Routes>
          <Route path="/" element={<App />} />
          <Route path="/profile/:userId" element={<Profile />} />
        </Routes>
      </Router>
    </PostProvider>
  );
}
export default AppRouter;
```
## 3. App.jsでContextを使って投稿管理
```App.js
// ReactのuseContextを使って、PostContextの中身（投稿データ）を取得します。
import { useContext } from 'react';
import { PostContext } from './PostContext';

// posts（投稿一覧）とsetPosts（投稿の追加・更新関数）を取得して使用可能にします。
const { posts, setPosts } = useContext(PostContext);
```
## 4. Profile.jsで該当ユーザーの投稿を表示
```Profile.js
// Profileコンポーネントでも、Contextから投稿データを使うための準備をします。
import React, { useContext } from 'react';
import { PostContext } from './PostContext';

function Profile() {

  // 投稿データ一覧だけ取得します。更新は不要なのでsetPostsは使いません。
  const { posts } = useContext(PostContext);

  // すべての投稿から、userId（メールアドレス）に一致する投稿だけを抽出しています。
  const userPosts = posts.filter((post) => post.user === userId);


export default Profile;
```

## UI
![スクリーンショット 2025-05-07 17.19.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/f3956561-a19d-49c6-b6eb-0ff301d2019f.png)
他己評価をAIにやらせてみたら、自己認識とのズレがヤバかった話

# ChatGPTに“他人の目”を借りてみた：AI他己評価という新しい自己レビュー

自己評価って難しい。主観が入りすぎるし、他人に聞くのも気まずい。

じゃあいっそ、**ChatGPTに“他人になってもらって”評価してもらったらどうなる？**

私は実際にクライアント向けに提出した提案資料をもとに、ChatGPTを「想定クライアント」や「他チームのメンバー」に仕立てて他己評価を依頼しました。

使ったのは、ChatGPTの**一時モード**と**ペルソナ入力**によるプロンプト設計。客観視のトレーニングにもなり、成果物の質向上にも役立ちました。

そんな実験を、プロンプト・出力結果・反省点とともに共有します。

## 検証に使った素材：自作の業務提案資料

今回評価対象としたのは、ある企業の海外展開支援に関する提案資料です。

> 📝 提案内容：EC領域における業務改善・LTV設計支援  
> 提出者：筆者（フリーランスの業務DX支援パートナー）  
> 提出時期：2025年春頃

資料には、以下のような構成が含まれていました：

- 現状整理（市場動向・組織体制の変遷など）
- 課題仮説マップ（現場・戦略ギャップの抽出）
- 提案施策（KPI設計、ダッシュボード支援、継続購入設計）
- 支援スコープ・稼働イメージ
- 提案価格（月額15万円〜）

この資料に対し、ChatGPTに「上司」や「担当部門の責任者」になりきってもらい、コメントを求めていきます。

## ChatGPTで“他己評価”を行うプロセス

今回の評価は、以下の5ステップで実施しました。

### ① 一時モードをON
→ ChatGPTの記憶を使わないことで、先入観ゼロの評価を狙いました。

### ② ペルソナ入力
→ ChatGPTにこう伝えました：

```text
あなたは某企業の海外戦略部門マネージャーです。現在、EC事業の拡大とLTV最大化をミッションとしています。事業背景としては…（以下略）
```
## 評価を引き出すための質問設計

最初に「この資料どう思う？」と聞いただけでは、当たり障りのない感想が返ってきがちです。

そこで、以下のような切り口で追加の質問を重ねました。

- 同類の提案と比べて、どの程度の完成度？
- この価格帯（15万円/月）の人材として妥当か？
- 任せるとしたらどのタスク領域が向いてそう？
- 逆に、他の中堅エンジニアでもできる内容では？
- 提案書でわかりにくかった箇所はある？
- 改善するとしたらどこを見直すべき？

**評価軸を明確に設けたプロンプト**にすることで、ChatGPTの回答精度も大きく向上しました。

## ChatGPTの評価コメント（一部抜粋と所感）

### 🧠 出力例
> 「この提案書は論理的ですが、施策の“差別化”要素が少し弱いように見えます。他社提案との差別化軸が明示されていれば、より説得力が増します。」

> 「月額15万円という金額感に対して、内容的には適正に見えます。ただし、KPI設計や分析支援の深さによっては、もう少し価値訴求を追加してもよいかもしれません。」

> 「任せるなら“要件定義〜ベンダー折衝”フェーズが最適。実装やBI開発単体であれば、他の外注先でも良いのでは？という印象を持ちました。」

### 👀 筆者の所感

- 「差別化要素の弱さ」→ 同業提案との比較セクションを追加
- 「BIは他でもできる」→ 提案書に“業務との接続力”を補足
- 「価格と中身の妥当性」→ 強みとなる稼働内容を具体化

## ChatGPT他己評価のメリットと限界

### ✅ 良かった点
- 自分視点だけでは見えない“ズレ”が明確に
- 提案資料の改善ポイントがすぐ明らかになる
- 「自分の単価って他人から見てどう？」みたいなナイーブな問いに答えてくれる
- 資料レビューの相棒として手軽に使える

### ⚠️ 限界点
- 感情的なニュアンスまでは読み取れない
- 入力の質＝出力の質なので、質問設計が鍵
- 実在するクライアントの“温度感”とはズレる可能性あり

あくまで「仮想的な他者視点」ですが、フィードバック素材としては非常に有用です。

## まとめ：AIを“仮想上司”にして自分を見つめる時代

他者からの評価を得るのは難しい。けれどChatGPTを活用すれば、**擬似的に“他人の目”を借りて自己評価を行う**ことができます。

資料レビューの壁打ち、価格妥当性の見立て、強みの再認識…。使い方次第で、ChatGPTはとても良質な「客観視エンジン」になります。

GPT4oになってきてから、自然言語の取り扱い能力向上によって、ドキュメントの推敲はほんとに楽になったと感じてます。ぜひお試しあれ！
Selenium で Radiko を操作したい

## Selenium で Radiko を操作したかった


### 起動

[[selenium向け] ChromeDriverをpipでインストールする方法（パス通し不要、バージョン指定可能） #Python - Qiita](https://qiita.com/hanzawak/items/2ab4d2a333d6be6ac760)
[ChromeDriverをpipでバージョン指定してインストールする手順 #Python - Qiita](https://qiita.com/ten_to_ten/items/d0b39f7d1da1d2627d1b)

https://github.com/danielkaiser/python-chromedriver-binary


```python
import chromedriver_binary
import time

from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys as keys
from selenium.webdriver.support.select import Select

# オプションを設定。画面を閉じないようにする
options = webdriver.ChromeOptions()
options.add_experimental_option('detach', True)
options.add_argument('--remote-debugging-port=9222')
driver = webdriver.Chrome(options=options)

# TBSラジオのページを開く
driver.get("https://radiko.jp/#!/live/TBS")
sleep(1)

# 同意ボタンクリック
driver.find_element(By.CLASS_NAME, "btn--medium").click()
sleep(1)

# 再生するボタンクリック
driver.find_element(By.CLASS_NAME, "btn--primary").click()
sleep(1)

# 視聴者情報選択
driver.find_element(By.CLASS_NAME,"radio_button").click()
dropdown = driver.find_element(By.NAME, "birthYear")
select = Select(dropdown)
select.select_by_index(46) 

dropdown = driver.find_element(By.NAME, "birthMonth")
select = Select(dropdown)
select.select_by_index(5) 
driver.find_element(By.CLASS_NAME, "questionare-form_submit").click()

```

### 停止

[PythonのSeleniumを使って、起動済みのブラウザを操作する。 #Python - Qiita](https://qiita.com/mimuro_syunya/items/2464cd2404b67ea5da56)

```python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(options=options)
driver.close()
``` 

## 実行ファイル化

[Pythonファイルをexe/app化する。 #PyInstaller - Qiita](https://qiita.com/MatsuM2_1007/items/77d72b96067688f8dafc)

最終的に 起動用.app と 停止用.app が出来上がりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/84b5f24f-4df1-457f-a6e6-9d5664eed72c.png)


## 動機

[radiko](https://radiko.jp/)、ふとした時に聴きたくなりつつ、仕事に戻るときにさっとオフにしたい。色々試行錯誤しているうちに Selenium であれこれやるちょうどいい教材になりました。

作業記録がてら以上です
個人的備忘録：2つの<textarea>が連動するuseStateでつまずいたので、解決してみた

## はじめに

React や Next.js でフォームを扱うとき、`<textarea>` の状態が連動してしまうことがあります。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

本記事では、文字が連動してしまう理由と、それを防ぐ方法について簡単にまとめます。

## 書こうと思ったきっかけ

受講しているITスクールのハッカソンの開発の一環で、UIを整える作業中に「2つのテキストエリアが同じ内容になってしまう」現象に遭遇しました。忘れないように原因と対処法を記録しておきます。

**修正後の画面**

![Screenshot 2025-05-08 at 7.28.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/0ad5c262-93e9-4005-854d-87cc0a43fa6c.png)

## 内容

### 文字が連動してしまう理由

`<textarea>` の文字が連動していた原因は、2つのテキストエリアが同じ状態変数 `message` を使っていたことです。

具体的にはこのようなコードになっていたためです：

```tsx
const [message, setMessage] = useState("");

<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
```

この場合、どちらかの `textarea` を編集すると `message` の値が更新され、それが両方に反映されるため、入力が「連動してしまう」状態になります。

2つの `<textarea>` コンポーネントが、同じ状態変数 `message` を共有していることが原因です。

```tsx
const [message, setMessage] = useState("");
```

この状態変数を両方の `textarea` に割り当てると、どちらかに入力した値がもう一方にも即時反映されてしまいます。

```tsx
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
<textarea value={message} onChange={(e) => setMessage(e.target.value)} />
```

### 解決方法：状態を分ける

それぞれのテキストエリアに独立したステートを用意することで、連動を防げます。

```tsx
const [diaryMessage, setDiaryMessage] = useState("");
const [cheerMessage, setCheerMessage] = useState("");
```

そして各 `textarea` を以下のように個別に設定します：

```tsx
{/* 今日の日記 */}
<textarea
  value={diaryMessage}
  onChange={(e) => setDiaryMessage(e.target.value)}
/>

{/* さぶちゃんのエール */}
<textarea
  value={cheerMessage}
  onChange={(e) => setCheerMessage(e.target.value)}
/>
```

## まとめ

複数のフォーム要素が同じ状態を共有していると、意図せずに値が連動してしまいます。

:::note warn
**UIの動きを分けたい場合は、それぞれ別の状態変数を使うことが大切です。**
:::

今回のようなテキストエリアの例に限らず、フォーム全体の状態管理でも応用できる考え方なので、覚えておきたいと思いました...！
プログラミング初学者がゲーム効率化アプリ作ってみた話

プログラミング初心者でもイメージがわく開発日記
1. 思いついたキッカケ ―― ケンカをなくしたい！
友達とオンラインゲーム（LoL）をしていたら、**「誰がどの役割をやる？」**で毎回モメる。

そこで「ボタンひとつでランダム決定できたらラクじゃない？」とひらめく。

目標：名前を入力 → 役職が自動で決まるシンプルなツール。

2. 使ったものは 3 つだけ
目的	選んだもの	ざっくり理由
見た目を作る	HTML	“骨組み”を作る言語
色や配置	CSS	文字サイズやボタン色を決める
動きを付ける	JavaScript	ルーレットを回す／結果を表示

ポイント

わずか 1 ファイル（index.html） に全部まとめた。

ライブラリはゼロ。だからコピペしやすい。

3. 30分で動くものを作る手順
骨組みを書く

html

<input id="player1">
<button id="random">決定</button>
<div id="result"></div>
CSS で整える

css

body { font-family: sans-serif; }
button { padding: 12px; }
JavaScript でロジック

js

const roles = ["Top","Jungle","Mid","ADC","Support"];
document.getElementById("random").onclick = () => {
  const r = roles[Math.floor(Math.random()*roles.length)];
  document.getElementById("result").textContent = r;
};
ブラウザで開いて確認 ―― もう動く！

4. 改良ポイント（挫折ゼロでできる）
役職を増やす → 配列に文字を追加するだけ。

見た目をオシャレに → ボタンに background: #333; color:#fff; を付ける。

スマホでも見やすく → max-width:600px; margin:auto; で中央寄せ。

初心者におすすめ：まずは数字や色を変えて遊ぶ → 動きが変わる感動を味わう。

5. 公開してみたら…
GitHub にアップロード

Vercel でワンクリックデプロイ

友達にリンクを送る

「これ便利！」とその日のうちに好評 👍

6. さらに便利にした機能
LoL だけでなく Valorant / Overwatch などにも対応。

右下に自分の X アカウント @toe78560468 を小さく表示 → 興味を持った人がフォローしてくれた！

7. これからチャレンジしたいこと
やりたいこと	やる理由（初心者メモ）
役職数と人数が合わない時の自動調整	if 文を覚える練習になる
多言語対応 (日本語/英語)	HTML の lang を切り替える経験
結果をTwitterに自動投稿	API の勉強になる

まとめ
小さく作ってすぐ試す → 楽しい＆バグが少ない。

HTML/CSS/JS だけで “自分のサービス” が作れる！

あなたも 「困っていること × ランダムボタン」 で、面白いツールを作ってみては？

DEMO
https://role-randomizer.vercel.app/

作者 X
@toe78560468
8x8をスクロールさせて遊ぶ。(電光表示板)



いろいろい、注意
----

- UNO での　予定は、未定

目的
----

電光表示板で8x8漢字を連続的にスクロールさせる為に必要



プログラム
----

オンラインコンパイラ paiza


```c++


#include <iostream>
using namespace std;

long s_buff[8];

void kanji_scroll_clr() {
    for(int i=0;i<8;i++){
        s_buff[i] = 0;
    }//for
}//kanji_scroll_clr

void kanji_scroll_set(unsigned char *font){
    
    for(int i=0;i<8;i++){
        int a;
        a = s_buff[i] & 0xff00;
        a = a | font[i];
        s_buff[i] = a;
    }//for    
}//kanji_scroll_set

void kanji_scroll_1up(unsigned char *font){
    for(int i=0;i<8;i++){
        s_buff[i] = s_buff[i] << 1;
        font[i] = s_buff[i] >> 8;
    }//for  
}//kanji_scroll_1up

void font_data_out(unsigned char *font){
    for(int i=0;i<8;i++){
        printf("[%02x]\n",font[i]);
    }//for 
    printf("\n");
}//font_data_out

int main(void){
    // Your code here!

    unsigned char font[] = {
        0b10000000,
        0b01000000,
        0b00100000,
        0b00010000,
        0b00001000,
        0b00000100,
        0b00000010,
        0b00000001
    };
    
    //font_data_out(font);
    
    kanji_scroll_clr();
    
    kanji_scroll_set(font);
    
    for(int i=0;i<8;i++){
        kanji_scroll_1up(font);
        font_data_out(font);
    }
    
}


```

```

[01]
[00]
[00]
[00]
[00]
[00]
[00]
[00]

[02]
[01]
[00]
[00]
[00]
[00]
[00]
[00]

[04]
[02]
[01]
[00]
[00]
[00]
[00]
[00]

[08]
[04]
[02]
[01]
[00]
[00]
[00]
[00]

[10]
[08]
[04]
[02]
[01]
[00]
[00]
[00]

[20]
[10]
[08]
[04]
[02]
[01]
[00]
[00]

[40]
[20]
[10]
[08]
[04]
[02]
[01]
[00]

[80]
[40]
[20]
[10]
[08]
[04]
[02]
[01]




```
Windows 11で10の切り取り＆スケッチ(Windows + Shift + S)を使う

# Windows 11 「切り取り領域とスケッチ」の問題点
+ 「四角形」「ウィンドウ」「全画面」を切り替えるのに**2クリック**必要
+ ディスプレイをまたいで範囲を指定できない
+ Escキーでキャンセルできない

私にとっては使いにくいので、Windows 10 の仕様に戻しました。

# 環境
+ Windows 11 24H2
```
>ver
Microsoft Windows [Version 10.0.26100.3915]
```

# 解決法
1. 設定 →　アプリ → インストールされているアプリ を開く
1. 「Snipping Tool」 をアンインストールする
1. ```Windows + Shift + S``` が Windows 10 の仕様に戻る

# Windows 11 仕様への戻し方
+ Microsoft Store から「切り取り領域とスケッチ」をインストールする
https://apps.microsoft.com/detail/9mz95kl8mr0l?hl=ja-JP&gl=JP
JavaScriptのgoogle-closure-compiler向けの最適化

## はじめに

「速度」を優先するなら、この記事に書いてあることをすべて無視して下さい

デフォルトでは速度優先で最適化されます

インターネット読み込み速度とサイズに重点とした最適化方法を紹介します

## インターネット読み込み速度の重要性
SEOに関わるだけではなく、高速化してユーザー体験を増やすだけではなく
多くのスマホの利用者のギガを削減して、料金をちょっぴり減らせるのかもしれません

## ここで使うgoogle closure compilerのオプション

```
google-closure-compiler --compilation_level=SIMPLE_OPTIMIZATIONS --assume_function_wrapper=false --rewrite_polyfills=false \
--js=js/input1.js \
--js=js/input2.js \
--js_output_file=js/output.js \
--externs=js/externs.js
```

## 最初に externs.js
ファイル内に存在せず、外部の変数を宣言するためのものです

コメント内もしっかり書きます

```
/**
 * @externs
 */

/** @type {string} */
var strVar;

/** @type {integer} */
var intVar;

/** @const */
var jQuery;

```

## 同じ文字列を再利用して定義する
```
var str="str";
let str="str";
```
しただけでは、実は展開されてしまいます

そのため、以下のようにして行います

```
let nullstr="";
nullstr += nullstr;
let abc="abc" + nullstr;
let def="def" + nullstr;
let ghi="ghi" + nullstr;
```
少しでも値が動的に変化していることをコンパイラに教えます

## let, const, var をいろいろな場所で定義しない
可能な限り関数の頭で定義するようにしましょう

そうすると、let + space の4文字が節約できます


## 関数を展開させない
デフォルトでは速度を優先してコンパイルされるため、インライン展開にて
サイズが増えることがあります

それを阻止するには、以下のように関数を記載します
```
/** @noinline */
function lower(str) {
	return str.toLowerCase() + nullstr;
}
```
@　noinline と + nullstr を加えているのが特徴です

:::note info
呼び出し元が1個しかない場合は、展開させたほうのがサイズが減る場合もあります
:::

## document, window, navigator とか長いですね
```
let Document = document;
let Window = window;
let Navigator = navigator;
```
として、この大文字化したオブジェクトを使用するようにします
そうするとコンパイラにて1～2文字程度のオブジェクト名に短縮されます

## jQuery用
```
let nullstr = "";
nullstr += nullstr;
let	body='body'	+ nullstr;
let none='none' + nullstr;
$(body).css('display', none);
```
とすればちゃんと動き、コード削減にもなります

## 100の数字を使うときで、ファジーで良い場合は
100より99、10より9のが1バイト節約できます
あいまいでいい処理のみ使ってみてください

:::note
でも1000は桁数減らさなくても同じ文字数になります
:::

## 無名関数の定義
以下のサンプルコードを見ていただく他ありません
```
(($) => {
	"use strict";
	alert("test");
})(jQuery);
```

```
setTimeout(() => {
	alert("test");
}, 99);
```
競プロ日記#25/05/07

# アルゴ式

[グループ分け (4)](https://algo-method.com/tasks/786)
- 箱もボールも区別があるのでN個のボールそれぞれに対してM通りの箱の選択肢があるのでM*M*...よりM^N
```
int main() {
    int N, M;
    cin >> N >> M;
    long long ans = pow(M,N);
    cout << ans << endl;
}
```

[コイントス (5)](https://algo-method.com/tasks/805)
- 数学でよくやったやつ。きちんとコンビネーションを考慮するのを忘れてはいけない。
```
int main() {
    int N;
    cin >> N;
    cout << fixed << setprecision(10);
    for (int i = 0;i <= N;i++){
        long long cnt = funcCombination(N,i);
        long long all_pattern = pow(2,N); // 全てのパターン数

        long double ans = (long double)cnt / all_pattern;
        cout << ans << endl;
    }
}
```
reactor.netty.http.client.PrematureCloseException: Connection prematurely closed DURING responseについての調査

#### 使用フレームワーク

Spring Framework 6 の WebClient
reactor-netty

#### なぜこの例外が発生するのか

`Connection: close` は 「レスポンスを返したらサーバーが即座に接続を切る」という意味です。
そのため、HTTPクライアント側がまだレスポンスを読み取っている途中で接続が切られた場合、httpクライアントのライブラリは例外を発生します。
`reactor-netty` は非同期・ノンブロッキングなので、まだレスポンス本文を全部受信していない状態で切断されると`PrematureCloseException`の例外をスローします。
`PrematureCloseException`は、レスポンスの途中で接続が閉じられた（＝完全にレスポンスを読み込む前に切断された）ことを示します。

#### 解決策・対応方法

###### 1. Connection: close を明示的に設定しない

通常、`WebClient`/`reactor-netty` は接続の管理を自動で行います。特別な理由がなければ、`Connection: close` を指定しない方が安全です。

##### 2. それでも Connection: close が必要な場合

どうしても `Connection: close` を設定する必要がある場合は、以下のような方法で レスポンス本文が完全に読み込まれる前提で対処する必要があります：
```java
WebClient client = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(
        HttpClient.create()
            .doOnRequest((req, conn) -> req.requestHeaders().set("Connection", "close"))
    ))
    .build();
```
そのうえで、bodyToMono や bodyToFlux で 完全に読み込む処理を記述し、block() などで読み込みを完了させてください。
```java
String response = client.get()
    .uri("/some-endpoint")
    .retrieve()
    .bodyToMono(String.class)
    .block();  // レスポンスを完全に読み込む
```
【Python初心者】素数判定とfor...else構文の理解メモ

この記事は、Python学習の中で理解に時間がかかった「素数判定のコード」と「for...else構文」について、自分なりに整理したものです。  
Pythonのforループに`else`が付くことに最初は違和感があり、何をしているのかが分かりにくかったのですが、ようやく少し腑に落ちたので備忘録としてまとめておきます。

## 実装したいこと

2から9までの数字に対して、以下のような結果を出したいです。

- 割り切れる数がある場合 → 「○ equals × * △」
- 素数の場合 → 「○ is a prime number」

### 出力結果（目標）

```
2 is a prime number  
3 is a prime number  
4 equals 2 * 2  
5 is a prime number  
6 equals 2 * 3  
7 is a prime number  
8 equals 2 * 4  
9 equals 3 * 3  
```

## コード全体

```python
for n in range(2, 10):
    for x in range(2, n):
        if n % x == 0:
            print(n, 'equals', x, '*', n // x)
            break
    else:
        print(n, 'is a prime number')
```

## 各部分の解説

### `for n in range(2, 10):`

2〜9までの数字（10は含まない）をひとつずつ取り出して調べていきます。  
この `n` が調べたい対象の数になります。

### `for x in range(2, n):`

`n` を 2〜`n-1` のすべての数で割ってみるループです。  
割り切れる相手がいれば、その時点で「素数ではない」と判断できます。

### `if n % x == 0:`

割り算の余りが 0 になる場合、つまり `n` が `x` で割り切れる場合です。  
割り切れた時は `print(...)` して、`break` で内側のループを抜けます。

### `break`

割り切れる数が見つかったら、それ以上調べる必要はないのでループを抜けます。

### `else:`

この `else:` は、**`for x in range(2, n)` のループが `break` されなかったとき**に実行されます。  
つまり、どの `x` でも割り切れなかった場合＝`n` は素数と判断され、「is a prime number」と表示されます。

## 処理の流れの例（n = 9 の場合）

1. `x = 2` → `9 % 2 = 1` → 割り切れない  
2. `x = 3` → `9 % 3 = 0` → 割り切れた！ → `print(...)`して`break`  
3. `else:` は実行されない

## おわりに

最初は「なぜ2からn-1まで何回も割るのか」「elseがfor文についているのはどういう意味か」が分からず混乱しましたが、処理の順番を一つずつ丁寧に追うことで理解できるようになりました。

同じように悩んでいる方の参考になれば幸いです。  
今後も学習したことを少しずつ整理して投稿していきたいと思います。