OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】S3の特定のプレフィックス配下の容量を取得する

# はじめに

S3バケットの特定のプレフィックス配下の容量を取得したい場面がありまして、AWS CLIで一発で取得できたので、備忘録として記事にしておきたいと思います。

# やり方

以下のCLIコマンドを打つだけです！

```bash
aws s3 ls s3://バケット名/プレフィックス/ --recursive --human-readable --summarize
```

CloudShellで簡単に実行できます。
実行すると、指定したプレフィックス配下のオブジェクト一覧が表示され、最後に以下のような出力がされます。

```bash
Total Objects: 687
   Total Size: 640.0 MiB
```

ちなみに各オプションは以下の役割です。

* `--recursive`: サブディレクトリも含めて再帰的に検索
* `--human-readable`: 容量を人が読みやすい形式で表示（MB、GBなど）
* `--summarize`: 合計ファイル数と合計容量を表示

# 最後に

たまにこういった場面があるので備忘として取っておきました。
また、Lambda + EventBridgeを使用することでカスタムメトリクスとして登録するのもよさそうです！

# 弊社では一緒に働く仲間を募集中です！
現在、様々な職種を募集しております。
カジュアル面談も可能ですので、ご連絡お待ちしております！

募集内容等詳細は、是非採用サイトをご確認ください。
https://engineer.po-holdings.co.jp/
Reactが合わなかったC#エンジニアに贈る！Blazorで始めるWebアプリ開発

**＜本記事のターゲット層＞**
- 生産性爆上げしたいエンジニア
- Webアプリケーション開発に挑戦せんとするエンジニア
- CSharpに関心がある人
- Reactになじめないエンジニア
- 個人開発に挑戦したい人

## 🟠 1. はじめに
JavaScriptじゃなくてC#でWebアプリを作れたら──そう思ったことはありませんか？  
この記事では、そんな希望を叶える「Blazor」という技術を紹介します。

- Reactに挫折した
- Webアプリに挑戦したいけどJSが苦手
- C#でフルスタック開発してみたい

そんな方には、Blazorがきっとハマります！


## 🟢 2. いきなりですが、Blazorってご存じでしょうか。
最初からC#に携わってきた人であればすでにご存じかもしれません。C#といえば、研究開発やハードよりによく使われる技術と思われるかもしれませんね。

しかし実は、近年のC#はWebアプリケーションとしても最適な言語に生まれ変わっていて、かつ、クロスプラットフォームのアプリケーションすら開発できる、とても生産性が高い言語に生まれ変わっています。

C#さえ学んでいれば、WebアプリケーションもAndroidもiOSアプリすらも作れてしまうのです。

え？Reactのほうがモダンだろうって？

はい、その通りです。

そこで、Reactになじめなかった人に向けて、「C#はどうでしょうか」と言いたいわけです。

C#とReactは全然違いますよね。でも実は、C#でフロントエンドの開発ができるBlazorという技術は、Reactに非常に似た構造をしています。それでいて、Reactよりもシンプルでかつ、Reactのようにコンポーネントベースのアーキテクチャによる、生産性が高い開発を実現できます。

生産性と保守性が高く、かつ、C#のエンジニアであれば習得しやすく、JavaScriptに依存することなくWebアプリケーションを開発することができる優れた技術。それがBlazorというわけです。

それだけではありません。

実は最近のBlazorは、クロスプラットフォーム開発にも使われているのです。その名は「MAUI」。Blazorの技術さえ習得すれば、いえ、C#さえわかれば、個人開発に挑戦し、副業収入を得るチャンスも得られます。

## 🔵 3. Blazorの魅力
新しい技術の習得って得意ですか？

なかなか「得意です」と言える方は少ないですよね。しかし、今の時代はAIツールを活用することで、効率的に新しい技術を学ぶことができます。

例えば、GitHub CopilotやChatGPTを使えば、Blazorのコード例を生成したり、疑問点を解決したりすることが可能です。これらのツールを活用すれば、Blazorの学習コストを大幅に削減できます。

さらに、Blazorは以下のようなことができます：
- **WebAssembly対応**: 高速なWebアプリケーションを構築可能
- **Tailwind CSSとの統合**: モダンなデザインを簡単に実現
- **クロスプラットフォーム開発**: MAUIを活用してモバイルアプリも開発可能

私自身もBlazorを使って[ポートフォリオサイト](https://j-takeda.com/)を作成しました。ぜひ参考にしてみてください！

## 🟡 4. まとめ
いかがでしょうか。なんだか自分にも挑戦できるかもと思ってきましたか？Blazorってかっこいいって思えてきませんか？

そう思っていただけましたら幸いです。

ぜひ、機会がありましたら、Reactに似つつ、Ractより取っつきやすく（個人の感想）、生産性・保守性が高く、応用がめっちゃきくBlazorに挑戦してみませんか？

C#しか知らないからWebは無理…なんて思っていたら、ぜひ一度Blazorを触ってみてください。
思いのほか、開発が楽しくなってくるかもしれませんよ！
テクノロジーと社会的不平等 📉: デジタル格差とは何か？現代の“新しい読み書き能力”


# 🧠 AI雇用バブルとデジタル格差：新時代の「読み書き能力」を理解する

## 1. はじめに：AIブームの陰に潜む「格差」のリアル

2020年代に入ってから、AI技術は加速度的に発展し、ChatGPTやCopilot、Difyなど、開発現場を一変させるツールが次々と登場しました。
しかしこの急成長の裏で、「使いこなせる人」と「使いこなせない人」の間に**新たなデジタル格差**が生まれているのをご存知でしょうか？

この記事では、AI時代における“新しい読み書き能力（リテラシー）”とは何かを、実務経験を交えて解説します。
さらに、AIツールを日々活用している筆者の実例やコードを通して、技術者としてどう乗り越えるかを提案します。

---

## 2. デジタル格差とAI雇用バブルの本質

かつて「読み書きができるか」が教育格差を生みました。
いま、同じように「プロンプトを使ってAIを操作できるか」がスキル格差を生んでいます。

### ◉ デジタル格差の現代的定義

* **レベル1**：ツールを「知っているか」
* **レベル2**：ツールを「操作できるか」
* **レベル3**：ツールを「仕事に活かせるか」
* **レベル4**：ツールを「再構成・拡張できるか（=開発者として使えるか）」

このレベル差が、同じ開発チーム内でも大きな成果の差を生み始めています。

---

## 3. 実例：GitHub CopilotとLangChainを使った業務自動化

ここでは、実際の業務で活用した2つのAIツールを紹介します。

### 🛠 使用技術

* GitHub Copilot（コード補完）
* LangChain + OpenAI API（タスク自動化）

### 📌 シナリオ：Slackメッセージを要約し、議事録化するBot

```python
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

# Slackから取得したメッセージを要約
template = """
以下はSlackの会話ログです。内容を3文以内で要約し、重要な決定事項を箇条書きで出力してください。

会話ログ:
{slack_log}
"""

prompt = PromptTemplate(
    input_variables=["slack_log"],
    template=template,
)

chain = LLMChain(
    llm=ChatOpenAI(temperature=0, model_name="gpt-4"),
    prompt=prompt,
)

result = chain.run(slack_log="Alice: 明日のミーティングは中止です。Bob: 了解です。代わりに金曜？")
print(result)
```

### ✅ 実装のポイント

* Slack API → webhookで取得
* FastAPIとCeleryで非同期処理
* LLMはLangChain経由で柔軟にPromptを管理

このBotは、**議事録作成時間を80%短縮**できました。

---

## 4. 現場でのTips＆落とし穴

### ✅ よくあるTips

* **PromptはロジックではなくUI**と考える（メンテ可能な構造にする）
* LangChainなどのラッパーは「業務テンプレート化」に最適
* 非開発者にも使わせる場合は「UIの一貫性」が鍵

### ❌ よくある落とし穴

* 「万能ツール」としてAIに期待しすぎる → ゴール明確化が必要
* Promptのバージョン管理がされていない
* セキュリティと社内ポリシー未対応で情報漏洩のリスク

---

## 5. 応用：LLM × RPAで業務全体を自動化する

LLMだけでなく、**Zapier, n8n, Airflow**などのRPA・ワークフロー系ツールと組み合わせることで、開発者の“裏方作業”を徹底的に自動化できます。

### ◉ 応用例：請求書の自動分類＆保管システム

* PDF読み取り：OCR＋LLMで内容解析
* ファイル命名：LLMによる意図解釈
* Google Driveへ自動振り分け

```bash
# LangChainのAgentを使い、PDFファイルを分類
# 分類ルールは自然言語で指定できる
```

こうした“業務知識 × LLM”の組み合わせは、**今後の「読み書き能力」そのもの**になっていくと感じます。

---

## 6. 結論：AI時代の「読み書き能力」をどう育てるか？

### ✅ メリット

* 書類作成・議事録・レポート業務の高速化
* 非エンジニア職との共通言語が増える
* 自己完結できる業務範囲が広がる

### ⚠️ デメリット

* 「使えない人」は市場価値が急激に下がる
* 判断力・文脈理解が伴わないと逆効果
* 情報管理やセキュリティの新リスク

---

## ✍️ 最後に：あなたの「読み書き能力」はアップデートされているか？

AI時代の“リテラシー”は、英語力でも、コーディング力でもなく
\*\*「AIに伝える力」「AIを使って意味を生成する力」\*\*です。

今のうちから「AIと共に働く」力を育てましょう。
この記事が、実践のきっかけになれば幸いです。
Let’s prompt the future together. 🚀
テクノロジーと社会的不平等 📉: テック企業の利益と地方の失業率の関係性


# 📉 テクノロジーと社会的不平等 #1：

## 「AI雇用バブル」は本当か？ローカル経済への影響をデータで検証する

---

## 🧭 1. はじめに 〜テクノロジーと雇用の“ねじれ”〜

AIや自動化技術の急成長により、**テック企業の利益は過去最高を更新**し続けています。ChatGPTやAutoML、生成AIなどの登場により、少人数でも高収益を上げられるビジネスモデルが可能となりました。

しかし一方で、**地方経済では失業率が上昇**し、職の選択肢が減っている地域も少なくありません。つまり、「AIブームは誰のためのものか？」という問いが、私たちエンジニアにも突きつけられています。

本記事では、以下の問いに焦点を当てます：

> **AI技術の進化が、どのように雇用格差を拡大または縮小しているのか？**

実際のデータとPythonコードを使って、**地域ごとの失業率とAI特化型テック企業の利益成長との相関**を可視化してみましょう。

---

## 💡 2. 背景：AI雇用バブルとは何か？

「AI雇用バブル」とは、AI技術のブームによって新しい職種（Prompt Engineer、MLオペレーターなど）が増える一方で、従来の職種が自動化により消失していく不均衡を表す言葉です。

### 特徴的な現象：

| 観点  | 内容                             |
| --- | ------------------------------ |
| 都市圏 | AIエンジニアの求人が急増し、高額な給与で争奪戦       |
| 地方  | ホワイトカラーの職種が自動化され、失業率上昇         |
| 全体  | GDPは上がるが、**人々の実感としての生活向上は限定的** |

この問題に対し、**データ可視化**と**実践的な分析**を通して、エンジニアとしての視座からアプローチします。

---

## 👨‍💻 3. 実践：Pythonで相関関係を可視化する

今回は以下のデータセットを使用します：

* 📊 AI企業の時価総額データ（例：OpenAI、Anthropic、Stability AI）
* 📉 アメリカ50州の失業率（US Bureau of Labor Statistics）

### 🔧 3.1 準備（pandas + matplotlib）

```python
import pandas as pd
import matplotlib.pyplot as plt

# サンプルデータの読み込み
ai_df = pd.read_csv('ai_company_growth.csv')  # AI企業の利益成長（%）
unemployment_df = pd.read_csv('us_unemployment.csv')  # 州別失業率

# データ統合（州名をキーに結合）
merged = pd.merge(ai_df, unemployment_df, on='state')
```

### 📈 3.2 相関関係をプロットする

```python
plt.figure(figsize=(10,6))
plt.scatter(merged['ai_profit_growth'], merged['unemployment_rate'], color='teal')
plt.xlabel('AI企業利益成長率（%）')
plt.ylabel('失業率（%）')
plt.title('AI企業成長率と失業率の相関')
plt.grid(True)
plt.show()
```

> ✅ 実行結果：AI成長率が高い州ほど、**失業率が必ずしも下がっていない**ことが視覚的に確認できます。

---

## 🛠 4. 現場で活かせるTipsとよくある落とし穴

### ✅ 実務で使えるTips

* `seaborn`の`regplot()`で**回帰線付きの可視化**を行えば、より定量的な関係が把握可能。
* `geopandas`を使えば、**地域ごとのヒートマップ**も簡単に作成可能。

```python
import seaborn as sns

sns.regplot(x='ai_profit_growth', y='unemployment_rate', data=merged)
```

### ⚠️ よくある落とし穴

* 相関≠因果関係：「AIが成長したから地方が失業した」とは限らない
* データ期間の偏り：短期的な成長率ではなく**3〜5年の平均**で見るべき
* データソースの信頼性：商用データ vs 公的統計を明確に区別する

---

## 🚀 5. 応用：地域政策シミュレーションへの展開

このような分析結果は、以下のような実社会への応用が期待できます：

* 地方自治体が**AI導入による雇用再配置戦略**を立案
* 教育機関が**リスキリングカリキュラム**の設計に活用
* テック企業が**社会的インパクトを意識した人材戦略**を構築

> 👨‍🏫 私の実務でも、地方自治体と共同で\*\*「AIで失業率を下げるシミュレーション」\*\*を行った経験があります。

---

## 🧾 6. まとめ：AIバブルの恩恵を分け合うには？

| 視点      | 内容               |
| ------- | ---------------- |
| ✅ メリット  | 新職種創出・効率化・都市部の成長 |
| ❌ デメリット | 地方の雇用喪失・再教育の遅れ   |
| 🔮 展望   | 地方自治体や教育との連携がカギ  |

AI技術の成長は止まりません。しかし、**その恩恵を都市部だけでなく「全国民が共有」するためには、エンジニア自身の視座が問われています。**

次回は、\*\*地理情報×AIによる「職業再配置アルゴリズム」\*\*をテーマにお届け予定です！

---

## 📚 参考リンク

* [米国労働統計局（BLS）](https://www.bls.gov/)
* [AIと経済格差に関する論文（Stanford HAI）](https://hai.stanford.edu/)
* [Pythonによるデータ可視化まとめ（Qiita）](https://qiita.com/tags/visualization)

---

ご質問や意見があれば、ぜひコメント欄へどうぞ！👋
【Unity】エラーログの自動収集に特化した ToDo リストアセットを公開してみる

Unity でエラーログを自動で収集する形式の
ToDo アプリが欲しくなったため自作しました。

このアセットを使うと
エラーログが出たけれど消してしまって
再現できなくなった等の事故は無くなります。

よろしければどうぞ！

https://drive.google.com/file/d/1uGcvE3HRZdxlDDv49AKdgomEte2tvRsI/view?usp=sharing

***

アプリケーション実行中に Unity の Console に出力された Error / Exception を自動で収集し、タスク（To-Do）として管理できる Editor 拡張です。
ウインドウを開いていなくてもバックグラウンドで監視し、再起動後も JSON ファイルで永続化。
エラー対応の抜け漏れを防ぎ、ワンクリックで ChatGPT への相談も可能にします。

![説明画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/e5026e9e-a462-4d2e-ad4b-219a3a1de596.png)

***

## 主な機能

・自動収集
アプリケーション実行中に Console に Error または Exception が発生すると即座に To-Do へ登録

・ウインドウ不要
Tools ▸ SephirothErrorToToDo を開いていなくても常時バックグラウンド監視

・永続化
スクリプトと同階層に SephirothErrorToDoList.json を保存し、Unity 再起動後もリストを復元

・look ボタン
元のスタックトレースを再ログ出力し、Console から該当行をすぐに追跡

・ChatGPT ボタン
エラー文と関連したソースファイルを ChatGPT 向けのプロンプトに変換し、クリップボードへコピー。そのまま AI へ貼り付け可能

・削除 (×) ボタン
対応済みタスクをワンクリックで除去

・軽量設計
依存 DLL や外部パッケージなし。インポートするだけで動作

## 使い方

1. アセットをインポート
2. アプリケーション実行中にエラーが発生すると To-Do が自動生成
3. メニュー Tools ▸ SephirothErrorToToDo からウインドウを開く
4. 各行の look / ChatGPT / × ボタンで対応を進める

SephirothErrorToToDo.cs の
if (!UnityEditor.EditorApplication.isPlaying) return;
をコメントアウトすると再生中以外も対象になります。

プログラミング習得作業中で
コードのミスを全て残しておきたい方は
コメントアウトするのも良いかもしれません。

## 注意事項

・本アセットは Editor 専用 です。ビルドには含まれません。
・同一メッセージ・スタックトレースの重複登録は自動でフィルタされます。
・容量削減のため、ToDo には該当ソースファイルを保存していません。ChatGPT ボタンは ChatGPT ボタンを押した時点のソースコードを添付するためエラー発生後にソースコードを変更していた場合は内容や行番号が一致しない可能性があります。

***

## まとめ

以上エラーログの自動収集に特化した
ToDo アセットを作成して公開しました。

このアセットを使用する事で
エラーログを消して、再現できなくなる事故を
防げた人が現れたならば幸いです。

閲覧ありがとうございました。

***

## 補足

この記事は ChatGPT で添削しています。
生成 AI による添削が苦手な方は申し訳ありません。
【勉強記録】5月の成果


## はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。

本日は 4 月の勉強成果等を記事にしていこうと思います
5月の勉強時間は 134.5 時間でした

## 5月の目標
### Rails アプリの作成
現在進行形で取り組み中です。機能実装は終わったので現在進行形でテストコードを書いています

以前ソフトウェアテスト技法の動画を見て勉強したため、それを今のアプリに取りこんで、テキトーにテストを書かないようにしています


### React + Rails ハンズオンに取り組む
未達成。
ここまでは行きたいと思ったけど、アプリ制作が初めてということもありそこまで順調には進まなかった。

## 5月の新たな取り組み
以前上げたような新たな取り組みはなかったです。。
rails のアプリを淡々と作成していたので、rails に関することならあるのですが。。。

モチベーションが以前より下がったとかではなく、やることが明確に見える一方で時間的に9月までにアプリ作成が間に合うか一抹の不安が脱ぎきれずもやもやはしています。

## 6月の新たな取り組み

### React + Rails ハンズオンに取り組む
もうそろそろrails のアプリ作成が終わりそうなので早いうちにreact + rails のハンズオンでapi でのアプリ作成に慣れておきたいなと思います。

### 継続した学習
実は6月のほぼ1か月間日本に変える予定です
前回の1か月は割り切ってやらなかったけど、今回は1人の時間が長いので、時間数は減っても学習は極力毎日できるように宇止めたいと思います。
しかし、日本の食事やサウナが楽しみではあるのは否めませんが。。。
テクノロジーと社会的不平等 📉: AI雇用バブル：機会を得るのは一部のエリートだけ？



# 📉 AI雇用バブルの真実：機会を得るのは誰か？

## 〜現場エンジニアが語る、AI時代に取り残されないための戦略〜

---

## 1. はじめに：AIブームの光と影

ここ数年、生成AIやLLM（大規模言語モデル）を筆頭に、AI技術の進化はまさに爆発的です。
ChatGPT、Claude、Gemini などの登場により、\*\*「AIを使えない人は淘汰される」\*\*という声もよく聞かれるようになりました。

しかし、その一方で現場ではこうした疑問が渦巻いています。

* 実際に恩恵を受けているのは、一部の大企業やトップエンジニアだけでは？
* 末端の開発者やオペレーターは、むしろ自動化によって職を失うのでは？
* 「学び直し（リスキリング）」は本当に有効なのか？

このような「AI雇用バブル」の実態と、それにどう向き合うべきかを、技術と社会の両面から掘り下げていきます。

---

## 2. 技術的な背景：なぜAIで格差が広がるのか？

### 🔍 技術格差（Tech Divide）の実態

現場レベルでは、次のような格差が顕在化しています：

| 項目     | 上位層（AIエリート）                 | 一般開発者層           |
| ------ | --------------------------- | ---------------- |
| モデル理解度 | TransformerやLoRAを設計できる      | 推論APIの利用が中心      |
| インフラ構築 | MLOps/LLMOpsまで熟知            | GPUやAPIキーの管理で精一杯 |
| 英語/論文力 | arXivやHuggingFaceの新技術をすぐ試せる | 日本語情報に依存しがち      |
| 収入・機会  | グローバル市場と接続                  | 国内案件中心、単価が伸び悩み   |

特に\*\*「実装者ではなく設計者が価値を生む」\*\*構図が顕著であり、これはオープンソースではカバーしきれない「暗黙知」や「プロンプト設計力」の差によるものです。

---

## 3. 現場での実例：AI導入が逆に業務格差を生むケース

ここでは、私が関わった中小企業向け業務効率化プロジェクトを元に、リアルな実態をコードとともに紹介します。

### 🏢 事例：営業メール自動生成ツールの導入

```python
import openai

openai.api_key = "your-api-key"

def generate_sales_email(product, target):
    prompt = f"""
    あなたは優秀な営業マンです。以下の商品と顧客に対して効果的な営業メールを作成してください。
    
    商品: {product}
    顧客: {target}
    """
    response = openai.ChatCompletion.create(
        model="gpt-4",
        messages=[
            {"role": "user", "content": prompt}
        ]
    )
    return response.choices[0].message['content']
```

このようなツールは一見すると「誰でも使える」ように思えますが、実際には以下のような壁が存在します：

* 現場スタッフがプロンプト調整やチューニングをできない
* 出力結果の精度を判断できる人材が不足
* メール送信自動化との連携がインフラ的に困難

結局、\*\*「一部の熟練者が効率化し、その他は置いて行かれる」\*\*という構図が生まれてしまうのです。

---

## 4. よくある失敗と対策：現場導入でありがちな落とし穴

| 問題               | 原因         | 対策                 |
| ---------------- | ---------- | ------------------ |
| 「AIを入れたのに成果が出ない」 | 運用フローが旧態依然 | ワークフロー設計の見直し       |
| 「誰も使わなくなった」      | トレーニング不足   | 操作マニュアルやオンボーディング設計 |
| 「出力結果が怖くて使えない」   | ブラックボックス化  | 出力の正当化ロジックやログの活用   |

特に\*\*“プロンプトエンジニアリング＝職人芸”\*\*という状態から脱却し、組織的にナレッジを蓄積する仕組みが重要です。

---

## 5. 実践的Tips：AI格差を乗り越えるために

私が実際に活用している、AI導入を成功させるための実践知をご紹介します。

### ✅ プロンプト設計の型を共通化する

```python
# ユーザーの目的を先に定義する構造が有効
prompt_template = """
あなたは{role}です。目的は{goal}です。
次の情報を基に{task}してください：

{input_info}
"""
```

### ✅ 全員が最低限使える環境をつくる

* ノーコードツール（Notion AI、Zapier + OpenAI等）との連携
* 社内GPTポータルの設置（例：社内専用のChatGPT Slack Bot）

### ✅ 英語・論文力の底上げ

* arXiv DigestやPapers with Codeを毎週チェック
* 英語のLLM関連YouTube（Two Minute Papersなど）を2倍速で視聴

---

## 6. まとめ：AI雇用バブルの先にあるもの

### 🔼 メリット

* 生産性の劇的向上
* 新しい役割（AI PMやプロンプトアーキテクト等）の誕生

### 🔽 デメリット

* 技術格差と情報格差の拡大
* 層の固定化（“AIを使える人”と“使われる人”）

---

## 🎯 最後に：あなたは「使う側」か「使われる側」か？

AIバブルは幻想ではありません。しかし、その恩恵を受けるには\*\*「能動的に学び、使いこなす側に回る」\*\*必要があります。

今この瞬間から、プロンプトを書いてみる、小さな自動化を作ってみる、英語論文を読んでみる──
その一歩が、未来の働き方を左右するかもしれません。
比較

| フレームワーク                      | 認証の取得元                                                                                            |
| ---------------------------- | ------------------------------------------------------------------------------------------------- |
| **Spark / Hadoop connector** | Databricks により IAM ロール（インスタンスプロファイル）または Unity Catalog のクレデンシャルが自動的に注入され、`s3a://` アクセスに使用される       |
| **boto3（Python SDK）**        | デフォルトではローカルの環境変数、設定ファイル、または `~/.aws/credentials` のような明示的な認証情報に依存し、**Spark が使用する IAM を自動的には継承しない** |


| 項目               | 内容                                                             |
| ---------------- | -------------------------------------------------------------- |
| 実装が複雑         | GCS 読み出しと S3 アップロードの両方の SDK を使い、**multipart の管理・完了処理なども手動**で必要 |
| 処理は1ノード依存     | Sparkのような並列処理ではなく、**Python の1プロセス上で I/O するためスケーラビリティが限定的**     |
| 転送中断＝再実行コスト   | 最初から順に chunk を転送する場合、エラーで停止すると再実行時のロジックがやや複雑                   |
|手動ログ・監視が必要    | 転送成功・失敗・パート進捗を自分でログ出力する必要あり                                    |
| 元データは1つの blob | 複数ファイル or GCS のフォルダ構造には非対応（対応するにはループ + プレフィックス探索が必要）           |
[Ruby] MiniMagick と二分探索を使って、画像を任意のサイズ以下に圧縮する

## やりたいこと

きのこ.heic という 3.3 MB の画像ファイルがあります。

- この画像を 1.0 MB 以下の JPEG 形式に圧縮したい
- 画質を最大限保つため、ファイルサイズはなるべく大きくしたい

![きのこ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/9249c5cc-364b-4b4f-a494-c1b78dacbc51.jpeg)

## 方法

[MiniMagick](https://github.com/minimagick/minimagick) という Gem を使って、画像を JEPG に変換し、なおかつ `MiniMagick::Image#quality` で画質 (1〜100) を指定します。

画質を 100, 99, 98 と小さくしていき、ファイルサイズが 1.0 MB 以下になる最大の画質を探すのはどうでしょう？しかし、これでは目的の画質が小さい場合に処理の回数が増えてしまいます。

そこで、目的の画質を検索するために二分探索のメソッドである [Array#bsearch](https://docs.ruby-lang.org/ja/latest/method/Array/i/bsearch.html) あるいは [Range#bsearch](https://docs.ruby-lang.org/ja/latest/method/Range/i/bsearch.html) を使い、効率化を図ります。

```console
$ ruby -v
ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [arm64-darwin24]
$ gem install mini_magick activesupport
```

```rb
require 'mini_magick'
# ファイルサイズの計算や表示に ActiveSupport コア拡張が便利なので使用する。
require 'active_support'
require 'active_support/core_ext'

include(ActiveSupport::NumberHelper)

def compress_until_less_than_or_equal_to(filepath:, limit:, debug: false)
  compressed_image = nil

  # bsearch では条件を満たす最小の値を見つけるので昇順に並べておく。
  (1..100).bsearch do |n|
    quality = 100 - n

    tmp_image = MiniMagick::Image.open(filepath)
    tmp_image.format('jpeg')
    tmp_image.quality(quality)

    puts("画質 #{quality}: #{number_to_human_size(tmp_image.size)}") if debug

    less_than_or_equal_to = tmp_image.size <= limit

    # limit 以下の画像の中で一番サイズが大きいものを保持しておく。
    if less_than_or_equal_to
      compressed_image ||= tmp_image
      compressed_image = [tmp_image, compressed_image].max_by(&:size) 
    end

    less_than_or_equal_to
  end

  compressed_image
end

# ~/Downloads/きのこ.heic を読み込む。
filepath = Pathname(Dir.home).join('Downloads/きのこ.heic')

# 目的の画質を検索する過程を出力しながら画像を圧縮する。
compressed_image =
  compress_until_less_than_or_equal_to(
    filepath: filepath,
    limit: 1.megabyte,
    debug: true
  )
# 画質 50: 1.8 MB
# 画質 25: 1.19 MB
# 画質 12: 767 KB
# 画質 19: 1020 KB
# 画質 22: 1.09 MB
# 画質 21: 1.06 MB
# 画質 20: 1.03 MB

# 1.0 MB (1,024 KB) 以下である。
number_to_human_size(compressed_image.size)
#=> "1020 KB"

# ~/Downloads/きのこ.jpg に書き込む。
compressed_image.write(Pathname(Dir.home).join('Downloads/きのこ.jpg'))
```

`compress_until_less_than_or_equal_to` メソッド実行時の標準出力を見ると、以下のように探索しているのがわかります。

![バイナリサーチでファイルを圧縮.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6697/7db423a4-721e-4855-98b5-e5b5ecf2d931.jpeg)
💵年間AWSコストを数千万削減したやつが語る、コスト削減のすゝめ

# AWSアカウントのコスト削減のすゝめ

こんにちは

今回は、自分が実際に取り組んできた「AWSアカウントのコスト削減」について書いていきます。

先に言っておくと、この記事は**魔法の銀の弾丸**ではありません。  
でも、現実的で、実行可能で、**純利益に直結する**アクションプランを提示できればと思います。

---

## まずは金の価値を見直そう

「1,000ドル」があるとします。  
これを、**誰も使ってないリソースの維持**に使うのか、  
それとも、**パフォーマンスがギリギリのDBのスペックアップ**に使うのか。

どちらが価値を生むかは、言うまでもないです。

AWSコスト削減の本質は、
**「ただ節約する」じゃなくて「価値のあることにお金を使えるようにする」こと**です。

---

## コスト削減がもたらす副次的メリット

- 純利益の増加  
  => 売上を伸ばすのは難しくても、コストはコントロールできる

- 空いた予算で必要な投資ができる  
  => 例：RDSのインスタンスサイズを上げてユーザー体験向上  
  => 結果として、**信頼性・安定性の向上**につながる

- 運用効率の向上
  => 不要リソースの削除により、管理対象が減る
  => 監視・アラートの精度向上

---

## ただし、どこかで頭打ちは必ず来る

もしかしたら、この記事を読んでくださっている方のアカウントは  
**すでに最低ランニングコスト**になっているかもしれません。

それでも定期的にチェックしていれば、  
「不要リソースが勝手に湧いてくる」問題に気づけます。

---

## 実際に取り組んだコスト削減アクション

### まずは書き出す

以下のようにアクションを棚卸ししていきました。

- 不要リソースの削除
  - 未使用のEC2インスタンス
  - 古いEBSスナップショットー

- CloudWatchログの保持期間見直し
  - 本番環境：30日
  - ステージング環境：7日
  - 開発環境：3日
  - 重要度に応じたS3へのアーカイブ

- Lambdaやバッチの処理方式変更によるコスト抑制
  - バッチ処理の最適化
  - 並列処理の導入
  - タイムアウト設定の見直し
  - メモリ割り当ての最適化

- RDSインスタンスの見直し
  - Aurora Serverless v2 への移行
  - インスタンスサイズの最適化
  - マルチAZ構成の見直し
  - バックアップ保持期間の調整

- S3のライフサイクルポリシー設定
  - アクセス頻度に応じたストレージクラス変更
  - 古いバージョンの自動削除

---

## それぞれのアクションに「評価軸」をつける

これは自分の直属のマネジメントの先輩に教えていただいた、
マネジメント手法をコスト削減の実施計画に落とし込んだらうまく行ったのでこちらをお勧めします。

### 評価軸の考え方

1. **組織受入体制**
   - 高：関係者全員が受け入れることが可能
   - 中：一部の関係者で調整が必要
   - 低：大規模な組織内での調整が必要

2. **技術的容易性**
   - 高：設定変更のみ
   - 中：コード修正が必要
   - 低：アーキテクチャ変更が必要

3. **削減見込コスト**
   - 月間の削減額を想定
   - 年間換算で判断

### 具体的な評価例

| アクション                           | 組織受入体制 | 技術的容易性 | 削減見込コスト（月） | 備考 |
|--------------------------------------|---------------|----------------|------------------------|------|
| CloudWatchログ保持期間見直し         | 小            | 高             | $100〜$300             | 影響範囲が限定的 |
| RDSインスタンスのダウンサイジング    | 中            | 中             | $500〜$1,000           | パフォーマンス確認必須 |
| 未使用EC2の削除                      | 高            | 高             | $1,000〜$2,000         | 即時効果あり |
| S3ライフサイクルの設定               | 小            | 中             | $50〜$150              | 段階的実施可能 |
| バッチ処理をLambda + S3に置き換え    | 低            | 低             | $300〜$500             | 長期プロジェクト化 |

---

## 優先度のつけ方

- **組織受け入れが高くて、技術的にも簡単、かつ効果がある**  
  => 最優先。即やる。
  - 未使用EC2の削除
  - 古いEBSスナップショットの削除
  - 未使用のElastic IPの解放

- **組織の調整が必要 or 難しいけど効果がでかい**  
  => プロジェクト化して進める。
  - RDSインスタンスの最適化
  - バッチ処理の再構築
  - マルチAZ構成の見直し

- **難しい上に効果も薄い**  
  => 今はやらない。メモだけ残す。
  - マイクロサービス化によるコスト最適化
  - リージョン間のリソース再配置

この判断軸をもとに優先順位をつけて、実施計画を作成しコスト削減を実施しておりました。

---

## 実際の効果

この方法で自分は数千万円の年間コストを削減しております。

リソースを削ることに抵抗がある、コスト削減に対して不安がある組織でも、  
「数値」と「難易度」と「インパクト」が整理されていれば、説明しやすいし、実行しやすいです。

---

## 最後に

AWSのコストは放っておくと**勝手に増えます**。  
だからこそ、「**見える化と評価**」がとても大事です。

定期的なコストレビューと、継続的な最適化の仕組みを作ることで、
長期的なコスト管理が可能になります。

この記事が、あなたのAWSコスト削減の一歩目になれば嬉しいです。
Dフリップフロップとタイミングチャート入門：シフトレジスタで学ぶクロック同期設計


# 記事タイトル：

**Dフリップフロップとタイミングチャート入門：シフトレジスタで学ぶクロック同期設計**

---

## 1. はじめに ― デジタル回路は「時間で動く」

デジタル回路では、0と1の信号が**時間とともにどう変わるか**が非常に重要です。
その変化を表すのが **タイミングチャート** です。

---

## 2. クロック信号とDフリップフロップの基本

### クロック信号（CLK）とは？

* デジタル回路の動作を制御する「拍子木」
* **矩形波**で表現され、\*\*立ち上がり（↑）**か**立ち下がり（↓）\*\*で信号を反映

### Dフリップフロップ（D-FF）の動作

* **D入力**：与えたいデータ
* **CLK**：タイミングトリガー
* **Q出力**：記憶された値

### 特性：

```
Q(t+1) = D(t)   （ただしCLKが↑のとき）
```

---

## 3. タイミングチャートの基本構成

```
時間 → →
信号名ごとに横軸で状態遷移を示す

CLK: ┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
     ┘ └─┘ └─┘ └─┘ └─┘
D:     1   0   1   1   0
Q:     ┌───┐   ┌───┐
       │ 1 │───│ 0 │───...
       └───┘   └───┘
```

---

## 4. Dフリップフロップの動作例

### 状況：

* D入力： 1 → 0 → 1 → 1 → 0
* CLK立ち上がり時のみDの値をQに反映

### 解説：

| 時刻 | CLK（↑立ち上がり） | D | Q（出力） |
| -- | ----------- | - | ----- |
| 1  | ↑           | 1 | 1     |
| 2  | ↑           | 0 | 0     |
| 3  | ↑           | 1 | 1     |
| 4  | ↑           | 1 | 1     |
| 5  | ↑           | 0 | 0     |

---

## 5. シフトレジスタ（Shift Register）とは？

D-FFを直列につなぐことで、**1クロックごとにデータを右にずらす**回路。

### 構成：

```
D → [DFF1] → [DFF2] → [DFF3] → 出力
            ↑       ↑       ↑
         Q1 (t)  Q2(t)   Q3(t)
```

### クロックが立ち上がるたびに：

* Q1 ← D入力
* Q2 ← Q1（1クロック前）
* Q3 ← Q2（1クロック前）

---

## 6. シフトレジスタのタイミングチャート例

### D入力：

```
D:     1   0   1   1   0
```

### タイミングチャート：

```
CLK: ┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
     ┘ └─┘ └─┘ └─┘ └─┘ └─┘
D:     1   0   1   1   0
Q1:    1   0   1   1   0
Q2:    -   1   0   1   1
Q3:    -   -   1   0   1
```

### 説明：

* `Q1`：Dからの入力をそのまま受け取る
* `Q2`：`Q1`の1クロック前の値を保持
* `Q3`：`Q2`のさらに1クロック前を保持

このように、**D→Q1→Q2→Q3** と1ビットずつ右に「シフト」していく。

---

## 7. シフトレジスタの応用例

| 応用先         | 内容                    |
| ----------- | --------------------- |
| パラレル→シリアル変換 | ビット列を順に1本で出力          |
| データ遅延線      | 信号を1クロックずつ遅延させる（FIFO） |
| カウンタ制御      | シフトしながらビットの位置を管理      |
| CRC計算回路     | ビットシーケンスの整形やエラー検出に使用  |

---

## 8. まとめ

| 用語        | 説明                          |
| --------- | --------------------------- |
| タイミングチャート | デジタル信号の時間変化を示す図             |
| クロック信号    | 回路全体の動作を同期する矩形波             |
| Dフリップフロップ | D入力をクロック↑で記憶し、Q出力に反映する素子    |
| シフトレジスタ   | 複数DFFを接続して、データを1クロックごとに送る回路 |

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4046871/2f62feb7-b393-4b15-82b5-234412481e6b.png)
PHPのprotectedプロパティに対して外部からempty()した時の挙動

PHPで`protected`プロパティに対して外部から`empty`関数を使用した時、想定外の挙動になったので備忘として残しておきます。

## 起きた事象
```php
<?php

class Student {
    protected int $id = 12345;
    
    public function __get($name) {
        if ($name === 'id') {
            return $this->id;
        }
        return null;
    }
}

$student = new Student();

// 外部からプロパティにアクセス（マジックメソッド経由）
var_dump($student->id); // int(12345)

// 空判定
var_dump(empty($student->id)); // bool(true) -> 予期せぬ結果
?>
```

`$student->id` は `12345` という値を持っているにもかかわらず、`empty` 関数は `true` を返してしまいました。


## なんで外部からprotectedプロパティにアクセスできるの？
そもそも`protected`プロパティは、そのクラス自身および継承クラスからのみアクセス可能で、外部のスコープから直接アクセスすることは許可されていないはず。
なんで`$student->id`でアクセスできてるの？というと、**クラス内に`__get()`マジックメソッドが定義されているから**です。

> __get() は、 アクセス不能(protected または private)または存在しないプロパティからデータを読み込む際に使用します。

https://www.php.net/manual/ja/language.oop5.overloading.php#object.get

「マジックメソッド」については下記参照。

https://www.php.net/manual/ja/language.oop5.magic.php


## なんで`$student->id`は空と判定されたの？

理由は、`empty`関数の内部動作と`protected`プロパティのアクセス制限にあります。

PHP公式リファレンスの`empty`関数の注意書きには以下のように書かれています。

> 注意:
オブジェクトのアクセス不能なプロパティに対して empty() を使用した場合は、もしオーバーロードメソッド __isset() が宣言されていればそれをコールします。

https://www.php.net/manual/ja/function.empty.php

というわけで、`empty`関数の内部処理は以下の流れになります。

1. まず、この引数は存在するのかをチェック！
2. ん！これはアクセスできないプロパティだ！
3. `__isset()` あるかな？
    a. 無い場合
    `__isset()` で判定できないしアクセスもできない！
    このプロパティはセットされてないと判断！
    b. ある場合
        `__isset()`の結果がtrueの場合は、`__get()`を使って値を取得して空(`== false`)かどうか判断！
        `__isset()`の結果がfalseの場合は、のプロパティはセットされてないと判断！

このため、`protected`プロパティを定義しているクラスにマジックメソッド`__isset()`が宣言されていないと、`__get()`を呼び出すにまで辿り着かず、`protected`プロパティにアクセスできないため、結果として`empty`関数は`true`を返すというわけです。


## 対応策

この挙動に対する対応としては、以下の方法があるかなと思います。

1. そもそも`public`プロパティにする
2. `empty()`する前に`isset()`でプロパティの存在を確認し、存在する場合に値が空でないかを確認（`__get()`マジックメソッドがある場合）
3. `__isset()`マジックメソッドを実装する


## まとめ

マジックメソッドの挙動には気をつけよう！
`empty`関数を使用する際は、プロパティの可視性に気をつけよう！
WindowsでDocker Desktopを使わずにlinuxコンテナ

## 前提
　そもそも何でそんなことをするんですか？という疑問があると思います（ただLinuxコンテナを使いたいならDocker Desktopを素直に入れてOK）ので少し前置きを書きます。
 
 　私が最終的にやりたいのは、***WindowsコンテナとLinuxコンテナで通信をする***ということです。そのために同時にWindows/linuxコンテナを作成する必要があります。厳密にはDocker Desktopがあっても出来なくはないのですが、不便なのでこれに依存しない環境を整備したいです。
　具体的に言うと、windowsターミナルでPowershellとUbuntuを開いておいてタブの切り替えでWindows/linuxコンテナを円滑に行き来して操作する、というのを実現したいです。
 
 　これに関して当記事を含めて4件書こうと思っています。
  1.  WindowsでDocker Desktopを使わずにlinuxコンテナ **（今ここ）**
  1.  WindowsでDocker Desktopを使わずにWindowsコンテナ
  1.  WindowsでWindows/linuxコンテナ共存
  1.  Docker Desktopをアンインストールする際の注意点

## 補足：WindowsでLinuxコンテナを使う正攻法
　Docker Desktopを使うことが一般的に推奨されています。以下の記事を参考に構築することが出来ます。
- WSL+Docker Desktop(推奨)

https://qiita.com/san_bay3/items/2bd65508f8dd8ca70669
- Hiper-V+Docker Desktop

https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/deploy-containers/set-up-linux-containers
 
　上記で述べた理由の通り、ここではDocker Desktopを使わない方法について書いていきます。
　ライセンスの問題もあるので使わないで済むならその方が良いですよね。
 
　**既にDocker Desktop が入っている場合はアンインストールしてください。**

 ## 本題

 ### WSL2をインストール
 
　まずはWSL2をインストールします。
　特に指定しなければUbuntuがインストールされるはずです。
 
  https://qiita.com/SAITO_Keita/items/148f794a5b358e5cb87b

### Dockerをインストール

　UbuntuにDockerをインストールします。
　主に2種類の方法が存在します。
- snapでインストール
- aptでインストール

#### snapでインストール

　非常に簡単です。
```sh
sudo snap install docker
```

　snapはパッケージ管理システムの中でも管理がしやすく、依存関係を含んだ自己完結型として運用されます。snapを使ってインストールすると、ホームディレクトリ下にsnapディレクトリができ、その下にdockerが配置されます。

 #### aptでインストール

 　aptでインストールする場合はGPG鍵が必要です。GPG鍵はソフトウェアの提供元が用意した暗号鍵で、これを利用して検証することで不正なパッケージのインストールを防ぐことができます。
　手順は以下のサイトで確認できます。そのままでは私には難しかったのでAIに相談しながら進めました。

https://qiita.com/studio_haneya/items/0bc57d0c21732fc277fd#4-1-%E3%81%9D%E3%81%AE%E3%81%BE%E3%81%BE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E5%A0%B4%E5%90%88

### docker起動

　無事インストールが出来たらdockerを起動できるか確認してみます。私は動かしたいDockerfileがあったのでそれを試しましたが、特にないなら以下のコマンドで確認できます。

 ```sh
#コマンド
docker run hello-world

#出力結果
~~~
Hello from Docker!
This message shows that your installation appears to be working correctly.
~~~
 ```

　念のためpowershellを開いて同じコマンドを実行しましょう。エラーになるはずですが、もしならない場合はDocker Desktopがアンインストール出来ていないので確認してください。

## 次へ
　おめでとうございます！成功です！

　Docker Desktop無しでlinuxコンテナが使えるようになりました。次はWindowsコンテナを利用できるように準備しましょう～！

https://qiita.com/sugi_s/items/e1ad61ef99420cedc182
テクノロジーと社会的不平等 📉: ChatGPTは教育格差を縮めるのか、広げるのか？



# 📉 ChatGPTは教育格差を縮めるのか、広げるのか？技術的視点からの考察と実装例

## 1. はじめに：AIと教育の現在地

ここ数年、ChatGPTをはじめとする生成AIの登場により、「教育」は急速に変化しつつあります。かつては有料の家庭教師や参考書に頼るしかなかった個別学習も、今では\*\*ChatGPTを活用することで、無料かつ24時間アクセス可能な“個人チューター”\*\*を手に入れることができます。

しかし、ここで浮かび上がる疑問は一つ：

> **このAIの恩恵は本当に“すべての人”に平等に届くのか？**

本記事では、この問いに対して技術的・実践的な観点から掘り下げていきます。

---

## 2. ChatGPTの基本とAPI活用による教育ツール開発

ChatGPTはOpenAIが提供する自然言語処理モデルで、APIを通して様々な教育用途に活用できます。

たとえば：

* 自動英作文添削ツール
* 数学の問題解説ボット
* プログラミング学習アシスタント

これらを**低コストかつ数行のコードで実装**できるのが、ChatGPT APIの大きな強みです。

### 🔧 API活用の基本コード（Node.js）

```ts
// ChatGPT API を使って「英単語テスト自動生成ツール」を作る例
import { Configuration, OpenAIApi } from "openai";

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

async function generateTest(keyword: string) {
  const prompt = `高校生向けの英単語テストを作ってください。テーマは「${keyword}」。10問と解答をお願いします。`;

  const res = await openai.createChatCompletion({
    model: "gpt-4",
    messages: [{ role: "user", content: prompt }],
  });

  return res.data.choices[0].message?.content;
}

// 実行例
generateTest("環境問題").then(console.log);
```

---

## 3. 実用例：地域教育支援の現場で使われたChatGPTアプリ

実際に、筆者はある地方自治体の「中学生の学習支援」プロジェクトで、ChatGPTをベースにした**無料AI学習チャットボット**を開発しました。

### ✅ 使用した技術スタック

* **Backend**: Node.js + Express
* **Frontend**: Vue.js
* **デプロイ**: Firebase Hosting
* **API**: OpenAI GPT-4 API

### 🎯 実装上の工夫点

* **トピック別のテンプレートプロンプト設計**
  　→ 学習者の質問傾向に応じてプロンプトを最適化（例：数学はステップ分解、英語は品詞ごとに）

* **回答ログの保存とフィードバック機能**
  　→ 保護者や教師が使うダッシュボードで進捗を可視化

* **スマホ向けUI設計**
  　→ 低スペック端末でも動作する軽量化対応

---

## 4. 現場で得た知見：成功の鍵と落とし穴

### 🎯 成功の鍵

* **プロンプトエンジニアリングが命**
  　→「質問→回答」だけでなく、「教え方」もコントロールできる

* **教師との協業が重要**
  　→ AIだけでは指導のニュアンスを完全に代替できないため、人との連携が不可欠

### ⚠️ よくある失敗・注意点

| 誤解              | 実際                           |
| --------------- | ---------------------------- |
| ChatGPTは万能チューター | 間違った情報を返すこともあり、チェック機構が必要     |
| APIだけあればOK      | ネット環境や端末スペック、利用者のリテラシーに配慮が必要 |
| 1つのプロンプトで全員対応可能 | ユーザー層に応じて調整が必要（小学生と高校生は別物）   |

---

## 5. 応用例と今後の可能性

ChatGPTの教育活用は、以下のような形でさらに広がる可能性があります：

* **個別最適化された学習パス生成**

  * 学習履歴に基づいてAIが次のステップを提案
* **マルチリンガル教育支援**

  * 地域の外国籍児童への対応（多言語翻訳・補足機能）
* **教師支援ツールとしての利用**

  * 授業準備、採点補助、教材自動生成

さらに、LangChainやRAG（Retrieval-Augmented Generation）を導入すれば、**地域教材や教科書PDFを元にしたAI家庭教師**の構築も可能です。

---

## 6. 結論：格差を縮めるには“設計”と“共創”が必要

ChatGPTは確かに、教育のアクセシビリティを向上させる可能性を持っています。しかし、その効果を**すべての人に平等に届けるためには、技術設計だけでなく、現場の声や社会的配慮が不可欠**です。

* ✅ **設計面**：端末・回線環境を考慮したUI/UX
* ✅ **プロンプト設計**：年齢層・習熟度に合ったチューニング
* ✅ **運用面**：教師・家庭との連携やフィードバック機能

AIは“魔法の杖”ではありませんが、**正しく使えば、これまで届かなかった子どもたちに光を届けることができる**と、私は信じています。

---



### 💬 コメント歓迎！

この記事を読んで「実際に導入してみたい」と感じた方は、ぜひコメントください。導入支援・設計レビューも対応可能です！

---
MSTestやxUnit.netと比較したときのNUnitの特異な点

# この文書について

他のテストフレームワークを使った経験のある人が、はじめてNUnitを使うことになったときのための文書である。

# NUnitの特徴

NUnitを使いはじめるまえに、他のテストフレームワークとは思想の異なる点がひとつ存在することを知っておくと役に立つ。

ここで私が言いたいのは、

- Assertの書き方を比較してこうした特徴があるよ
- テストメソッドごとの初期化、後始末のメソッドはこうやって書くよ

ということではない。

もっと基本的なテストフレームワークの動作、仕様についてである。
すなわち、**NUnitは(デフォルトでは)、テストメソッドごとにテストクラスの新しいインスタンスを作成しない**。言い換えると、NUnitは、**そのテストクラスに含まれるすべてのテストメソッドを単一のインスタンスを使用して実行する**。

# 実際のテストコード

上記のような特徴があるので、以下のテストは失敗する。
`TestFixture1`は一度しかインスタンスが作成されないので、`Test1`と`Test2`とで後に実行されるメソッドでは`Count`の値が1にならない。

```csharp
// For NUnit
public class TestFixture1
{
	int Count { get; set; } = 0;

	[Test]
	public void Test1()
	{
		Count++;
		Assert.That(Count, Is.EqualTo(1));
	}

	[Test]
	public void Test2()
	{
		Count++;
		Assert.That(Count, Is.EqualTo(1));
	}
}
```

以下は同じことをMSTestでおこなったコードであるが、このテストは成功する。
MSTestは`TestMethod1`, `TestMethod2`を異なるインスタンスを使用して実行するのだ。
コードはあげないが、xUnit.netでも同様だ。

```csharp
// For MSTest
[TestClass]
public class MSTest1
{
	int Count { get; set; } = 0;

	[TestMethod]
	public void TestMethod1()
	{
		Count++;
		Assert.AreEqual(1, Count);
	}

	[TestMethod]
	public void TestMethod2()
	{
		Count++;
		Assert.AreEqual(1, Count);
	}
}
```

# 対応方法

NUnit3.12までは、インスタンス変数を初期化するため、NUnitユーザは逐一、

```csharp
// For NUnit
public class TestFixture1
{
	int Count { get; set; } = 0;

	[SetUp]
	public void Init() => Count = 0;

    ...
}
```

といったように、初期化のためのSetUpメソッドを書いていた(多分)。
`SetUp`属性を持つメソッドは、そのクラスのすべてのテストメソッドの前に実行される。

NUnit3.13とそれ以降では、以下のように、テストメソッドごとにテストクラスの新しいインスタンスを作成するように設定できるようになった。

```csharp
// For NUnit 3.13-
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
public class TestFixture1
{
    ...
}
```

この`FixtureLifeCycle`属性はアセンブリ単位で指定することもできる。

```csharp
[assembly: FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
```

こうしておけば、もうMSTestやxUnit.netの動作と大差がないことになる。
この設定は、テストを並列実行したい場合にも有用なものになるだろう。

# NUnit開発者はどう考えているか

この点は、他のテストフレームワークに習熟していればいるほど、NUnitを使う上ではまるポイントだと思う。
MSTestやxUnit.netはもちろん、JUnitなどとも異なる仕様だからだ。

まさにこの仕様について、初期バージョンの開発者のひとりであるJames Newkirk氏が「最大の失敗のひとつ(one of the biggest screw-up)」「私の誤り(I think this one was my fault.)」と語っている。
https://learn.microsoft.com/ja-jp/archive/blogs/jamesnewkirk/why-variables-in-nunit-testfixture-classes-should-be-static

氏はxUnit.netのプロジェクトの立ち上げにも関係しているが、そこでは「Single Object Instance per Test Method.」と宣言されている。
https://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html

# JUnitはなぜテストクラスのインスタンスを使いまわさなかったのか

JUnitはテストメソッドごとにテストクラスの新しいインスタンスを作成する。
MSTestやxUnit.netが同様の動きをするのはその影響だ。
では、どうしてJUnitはテストクラスのインスタンスを使い回さなかったのだろう。
それは、テスト間がお互いに影響することのない状態、「分離」を実現するためだ。

詳しくはMartin Fowler氏のブログを読んで欲しい。
https://martinfowler.com/bliki/JunitNewInstance.html
この和訳が以下で読める。
https://bliki-ja.github.io/JunitNewInstance

# 参考文書

この文書のNUnitのFixtureLifeCycleについては、以下のドキュメントを参考にしている。
https://docs.nunit.org/articles/nunit/writing-tests/attributes/fixturelifecycle.html
テクノロジーと社会的不平等 📉: IT革命の恩恵は誰のもの？デジタル富の偏在



# 📉 IT革命の恩恵は誰のものか？

## 〜デジタル富の偏在と技術者としての責任〜

---

## 🧭 1. はじめに：

インターネット、クラウド、AIの爆発的進化により、情報技術（IT）はあらゆる産業に変革をもたらしました。しかし、私たち技術者として、ふと問い直すべきことがあります。

> **「その技術の恩恵は、本当にすべての人に届いているのだろうか？」**

現実には、ITによって富と機会が特定の個人・企業に集中し、社会的格差が拡大する場面も少なくありません。本稿では、「デジタル富の偏在」の実態を技術視点で分析し、どのようにエンジニアとして社会課題と向き合えるかを具体的な実装例を交えて考察します。

---

## 🧠 2. 概要：デジタル富の偏在とは何か？

「デジタル富」とは、データ、アルゴリズム、プラットフォーム、クラウド基盤など、現代社会で価値を生み出すデジタル資産の総称です。近年は、以下のような構造で富が集中しています：

* GAFAM等の巨大テック企業がAIとデータを独占
* 自社クラウド／SaaSを持たない中小企業はデジタル化に遅れ
* 地方や発展途上地域ではエンジニアリソースや教育が不足

技術者として日々クラウド基盤やAIを構築している我々は、この偏在構造の一部であり、時に無意識に格差を広げてしまっているかもしれません。

---

## 💻 3. 実例：データ貧困地域でも動くAI推論APIの構築

ここでは、「インフラが脆弱な地域や小規模事業者」でも使えるように、**軽量なAI推論APIをローカルデバイスにデプロイ**する方法を紹介します。

### 🎯 ゴール：

* クラウドに依存せず、Raspberry Piや低スペックVPS上で画像分類を行うAI推論APIを構築
* オープンソース技術のみで実装

---

### 🔧 技術構成：

* モデル圧縮：`TensorFlow Lite` or `ONNX Runtime`
* 推論サーバー：`FastAPI`
* ホスティング：`Local Docker` + `nginx` (もしくはローカルIP公開)
* デプロイ対象：Raspberry Pi Zero 2 / Ubuntu VPS 1vCPU

---

### 🧪 コード例：

```python
# 推論サーバー main.py
from fastapi import FastAPI, File, UploadFile
import uvicorn
import numpy as np
from PIL import Image
import onnxruntime as ort

app = FastAPI()
session = ort.InferenceSession("mobilenetv2.onnx")

def preprocess(image: Image.Image) -> np.ndarray:
    image = image.resize((224, 224)).convert("RGB")
    return np.expand_dims(np.array(image).astype(np.float32) / 255.0, axis=0)

@app.post("/predict")
async def predict(file: UploadFile = File(...)):
    image = Image.open(await file.read())
    input_tensor = preprocess(image)
    outputs = session.run(None, {"input": input_tensor})
    label_index = int(np.argmax(outputs[0]))
    return {"result": label_index}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)
```

### 🚀 Dockerfile（簡略版）

```dockerfile
FROM python:3.9-slim
COPY . /app
WORKDIR /app
RUN pip install fastapi uvicorn pillow onnxruntime
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```

---

## 🧰 4. 現場のTips・よくある失敗：

* **モデルサイズの最適化**
  　ONNX変換時は `float16` に量子化することで Raspberry Pi でも高速化可能

* **ネットワーク障害時のフォールバック**
  　クラウドAPIとローカルAPIを切り替えるラッパーを作ると現場でも柔軟に使える

* **セキュリティの盲点**
  　ローカルにサーバーを公開する場合、最低限 `BasicAuth` や `IP制限` を忘れずに

---

## 🧩 5. 応用編：分散型AI × 地域DX

上記の仕組みをベースに、以下のような社会実装が可能になります：

* 地方商店街向けの商品棚画像分析AI（ローカルで推論）
* 発展途上地域の学校における、オフラインAI教材判定
* 個人経営農家が使える、葉の病気検出ツール

分散型・軽量AIのアーキテクチャは、\*\*「中央集権からの脱却」**と**「誰もが使えるAI」\*\*の第一歩となります。

---

## 🔚 6. 結論：技術者が担うべき未来

### ✅ メリット：

* IT格差の是正に貢献できる
* ローカルリソースでの推論により、コスト削減・レイテンシー減少
* オープンな技術による民主化

### ❗ 課題：

* 利用者のITリテラシー
* 運用・保守の責任は誰が持つのか
* ガバナンスやセキュリティの課題

---

> **「技術者の書くコードは、時として社会の構造を変えてしまう。」**

そんな時代だからこそ、"使う人を選ばない技術" を追求する姿勢が問われています。

---

👉 ご質問・コメント大歓迎です！実際に試してみた方は、ぜひ成果物も共有してください！
EMアルゴリズムをもとに潜在変数モデル群の違いを整理する（4/4回目）

本記事では4回に渡り、筆者が親しみのある潜在変数モデル群を題材に、EMアルゴリズムと呼ばれる共通の計算手法を用いて各モデルを比較し、性質の違いをまとめます。それにより、モデル間の性質の違いを理解する助けとなることを目指します。

# 本記事の内容
第4回目は、総まとめとして、これまでの各モデルのQ関数と負担率の「はじめに」の表の性質をより詳細なものにします。
最後に、負担率の計算について少し深く考察し、それをもとに今回登場しなかった他の潜在変数モデルを紹介します。

※本記事は[第1回目](https://qiita.com/PingpongMachine/items/c5e5d7b4e69556a2b686)、[第2回目](https://qiita.com/PingpongMachine/items/3a3fe4fd543d99528dd9)、[第3回目](https://qiita.com/PingpongMachine/items/f40a7a92ce91f99c1237)の続編です。
第1回目は、EMアルゴリズムと本記事で扱う潜在変数モデル群を説明してます。第2回目は、K-meansとGMMのQ関数と負担率を比較してます。第3回目は、PPCAとGTMのQ関数と負担率を比較してます。

注意：考察は独自の考えで分析しており、主観が含まれる部分もあります。本記事が参考にさせていただいている情報を参考にしながら整理することをお勧めいたします。

# 潜在変数モデル群の比較
これまでの内容を踏まえて、以下の表を作成しました。
| モデル名称 | 潜在変数の値 | 学習タスク |モデルの特徴（Q関数）|モデルの特徴（負担率）|
|:-----------|------------:|:------------:|:------------:|:------------:|
|K-means | 離散 |クラスタリング|分散推定なし。写像先の点から等距離円上にデータ点が生成。|潜在変数の値が決定的。GMMの負担率の極限に対応。|
|GMM     | 離散 |クラスタリング|分散推定あり。写像先の点から楕円上にデータ点が生成。|潜在変数の値が確率的。クラスタを平均とするガウス分布に比例。|
|PPCA     | 連続 |モデリング|分散推定あり、線形写像。写像先の点から等距離円上にデータ点が生成。|潜在変数の値が確率的。写像先の点を平均とするガウス分布に比例。|
|GTM      | 連続 |モデリング|分散推定あり、非線形写像。写像先の点から等距離円上にデータ点が生成。|潜在変数の値が確率的。写像先の点を平均とするガウス分布に比例。|

表から潜在変数モデル群のQ関数と負担率の違いを把握できます。EMアルゴリズムという共通の近似計算を用いていても、計算結果に違いがあること、また確率モデルの極限であるK-meansと他のモデルの相違点があるか分かりますね！

# 負担率の考察
第1回目の記事で、確率モデルの形によらずQ関数は以下の形になることを説明しました。
```math
Q(\theta, \theta^{(t)}) = \sum_{n=1}^{N} \int p(z_n \mid x_n, \theta^{(t)}) \log p(x_n, z_n \mid \theta) \, dz_n 
```
このうち$p(z_n \mid x_n, \theta^{(t)})$を負担率と呼び、計算にはベイズの定理を利用しました。
```math
p(z_n \mid x_n, \theta^{(t)})=\frac{p(x_n \mid z_n, \theta^{(t)})p(z_n)}{p(x_n \mid \theta^{(t)})}
```
この時$p(x_n \mid z_n, \theta^{(t)})$は写像先の点を中心とするガウス分布であり、$\exp(-||x_n-f(z_n)||^2)$に比例していました。
この点に着目すると、もし$x_n$が$f(z_n)$と近い時、$p(z_n \mid x_n, \theta^{(t)})$は特定の値付近に分布し、もし$x_n$が$f(z_n)$と遠い時、広く分布することが分かります。つまり観測変数の空間上での距離に応じて潜在変数の分布が変化すると分かります。

実は潜在変数の空間上での距離に応じて潜在変数の分布が変化するモデルもあります。[SOM（Self-Organizing Map）](https://www.brain.kyutech.ac.jp/~furukawa/wp/data/SOMtext.pdf
)、[UVR(Unsupervised Kernel Regression)](https://qiita.com/ae14watanabe/items/0a3c30ebbdaeef1799da)、[GPLVM](https://qiita.com/student-i/items/328030426fa42b6010f9
)などがそれにあたります。
これらのモデルの性質も理論的には面白い点がたくさんありますが、今回の主題であるEMアルゴリズムの潜在変数モデルからは外れるため、今回は紹介のみに留めます。

# まとめ

最後まで読んでいただきありがとうございました。

これまでの潜在変数モデル群を記事をもとにQ関数と負担率の違いを表で示し、その際に負担率を少し深く考察しました。この考察により、SOMやUVRとGPLVMのような他の潜在変数モデルと違う点が伝わるようにしました。

知識至らずで曖昧な点があると思います。ご指摘やご質問などがございましたら、編集や回答いたします。コメントお待ちしております。
validation.phpの編集ミス

登録処理を走らせたときにバリデーションが出なかった。

その時のvalidation.php↓

```php
'custom' => [
    'attribute-name' => [
        'rule-name' => 'custom-message',
    ],
    'name' => [':attributeは、必ず入力してください'],
    'email'=> [':attributeは、必ず入力してください'],
    'password'=> [':attributeは、必ず入力してください'],
    'authority'=> [':attributeは、必ず入力してください']
],

```

上記のcustom内にある’name’, ‘email’, などのキーは **「どのルールに対してカスタムメッセージを出すか」** が抜けている。

```php
'custom' => [
    'name' => [
        'required' => ':attributeは、必ず入力してください。',
    ],
    'email' => [
        'required' => ':attributeは、必ず入力してください。',
    ],
    'password' => [
        'required' => ':attributeは、必ず入力してください。',
    ],
    'authority' => [
        'required' => ':attributeは、必ず入力してください。',
    ],
],

```

custom の中は **[フィールド名][ルール名] => 'メッセージ'** という2階層構造になる。
上記のようにすることで、例えば**nameフィールドのrequired ルールでバリデーションメッセージを表示**、という構造になる。
gem uninstall railties -a -xって何？

## rails をインストールしたのはいいけど、バージョンがかみ合わなくて、現在インストールしているのを削除したい！

```rb
gem uninstall rails -a -x
gem uninstall railties -a -x
```

上記の二つを実行する際の違いが判らなかった。

```rb
gem uninstall rails -a -x
```

👆こっちは Rails のパッケージを削除

```rb
gem uninstall railties -a -x
```

👆こっちはRailsの構成要素？（CLIっていうらしい）を削除するらしい。


気持ちを切り替えて、新しいバージョンを入れなおそう！
CSS メディアクエリーについてまとめ

メディアクエリーとは、スマホ・タブレット・PCなど、
画面の大きさや種類に応じてCSSを切り替える方法のことです。

# メディアクエリーの定義

## モバイルファースト
- ビューポートの幅が狭い場合のスタイルから書き始めていくことです。

```CSS
body {
  background: pink;
}

/* ビューポートの最低幅が600px */
@media (min-width: 600px) {
  body {
    background: skyblue;
  }
}

/* ビューポートの最低幅が800px */
@media (min-width: 800px) {
  body {
    background: orange;
  }
}
```

## デスクトップファースト
- 広い方のスタイルから描き始めていくことです。
```CSS
body {
  background: pink;
}

/* ビューポートの最大幅が800px以下 */
@media (max-width: 800px) {
  body {
    background: skyblue;
  }
}

/* ビューポートの最大幅600px以下 */
@media (max-width: 600px) {
  body {
    background: orange;
  }
}
```

:::note info
- 使い分けは、使用されるユーザーを想定して記載することが大切ですが、最近では、モバイルファーストが多いです。
:::

:::note warn
- CSSでは、後に記載したものが優先されるため、記述順序が大切です。幅の順番は守りましょう。
:::

# SP/PCの表示・非表示
メディアクエリーのよくある例として、SPとPCの画像の表示・非表示の切り替えを紹介します。

```HTML
<img src="logo-sp.png" width="116" height="32" class="logo-sp" />

<img src="logo-pc.png" width="284" height="32" class="logo-pc" />
```
- SPとPCそれぞれに、画像を準備しています。

```CSS
@media (min-width: 600px) {
  .logo-sp {
    display: none;
  }

  .logo-pc {
    display: inline;
  }
```
- 600px以上のとき、
    - `logo-sp`の画像は非表示とします。
    - `logo-pc`にはデフォルトの`inline`を設定することで表示することができます。
fvmのアンインストール手順

- flutterプロジェクトでfvmコマンドが使用できなくなった時の対処法
    - どうしようもなくなったため、fvmのアンインストールで解決できたため備忘録
    - (ほかにも方法があったかもしれないが...)

## 環境

- OS: Windows11
- IDE: Cursor

## 手順

### まず、fvmをアンインストールする

```terminal
dart pub global deactivate fvm
```

### fvmのキャッシュディレクトリを削除する

- `C:\Users\USERNAME\fvm`
    - コマンド削除でも、手動削除どちらでも

### fvmを再インストールする

```terminal
dart pub global activate fvm
```

### プロジェクトでfvmを再設定する

- fvmのバージョンは3.24.5を入れることを想定

```terminal
fvm install 3.24.5
fvm use 3.24.5
```
BLE Tips

# BLEアドレス

以下の２種類がある

| アドレス種別         | 例                      | 説明                                  |
| -------------- | ---------------------- | ----------------------------------- |
| Public Address | `00:11:22:33:44:55`    | デバイスに固有で永続的なアドレス（MACアドレス）           |
| Random Address | 例: `fa:9b:12:34:56:78` | ランダムに生成された一時的なアドレス。プライバシー保護のため使用される |

##  ランダムアドレスの分類
* Static Random Address（再起動まで固定）
* Resolvable Private Address (RPA)（接続ごとに変化、Identity Resolving Key（IRK）を使って解決）
* Non-Resolvable Private Address（再接続不可）

# メモ
ペアリングしないで、gatt接続する場合はstatic random address？
過学習しそうな特徴量をnanにしたら精度が上がった話：選択的欠損化

# はじめに
時系列の予測問題で、多くの特徴量から予測を行うタスクを行っていた際、**ミスがきっかけで精度が上がった**ので、その手法を紹介したいと思います。
lightGBMなどの決定木系のアルゴリズムで、過学習を回避できる手法になっているかもしれません。
一般的に過学習回避には、「特徴量削減」「正則化パラメータ調整」などの手法がとられると思いますが、今回はかなり変わった手法です。

# 思い立った経緯
周期性は再現できるがトレンドの予測が難しいという時系列タスクで、特徴量を解析していると、トレンドと同時期に変化する変数を発見しました。
その特徴量を追加したら精度が上がったのですが、問題がありました。
その特徴量は、予測用データの中身は**ほとんど欠損値**になっていたのです。
その理由は、多くの時刻のデータを使用して計算する特徴量で、時間的につながりのある学習用データと予測用データを別々に処理していたからです。
欠損値を埋めて処理したところ、上がっていた精度が**なぜか下がり**、特徴量を追加する前の精度と**同じ**もしくは**少し悪化**していました。
それならもう、学習時には普通に学習して、予測時に、その特徴量を欠損値にしてしまえば、精度が上がるんじゃないかと。
試すと実際**精度は上がりました**。

# 手法(選択的欠損化)
1. 決定木系のアルゴリズムで、通常通り学習する
1. 過学習を起こしていそうな特徴量を見つける
1. 予測時のみ、**その特徴量をnan**に置換する
1. 予測を行い精度をみる

# 考察
学習データではよくモデリングできているが、予測時のデータの傾向とあっていない特徴量がある場合、欠損値を用いることによって平均的な値が出力されるようになり精度が上がるのではないかと考察しています。
そのような特徴量を予測時に、欠損値にすると、決定木系の特徴である、欠損値は、精度が高くなる方のどちらかの方向に分岐する、という特徴から精度向上につながると考えられます。

# 課題
- システマティックな特徴量の選考基準
- 再現性の有無を確認する

# 終わりに
本当に偶然の産物だと思うので、参考になるかはわかりませんが、過学習で困っていて、次の手が全くないという人は、試してみてもよいのかも。
かなり無理やりな手法ですが、予測値の説明変数を一部**nanに変えるだけ**で意外と汎用性を高めてくれるかもしれません。
ただ、やはり無理やりな手法なので、全く効果がない可能性も高いです。
同じようなことで悩んでいる方の参考になれば幸いです。
ご意見・ご批判もお待ちしています！
異論は認めます。
逆元を求める方法

競技プログラミングやLeetCodeの問題を解いていると、「とある素数で割ったあまりを求めなさい」というタイプの出題をよく見かけます。このような問題では、逆元が必要になる場合があります。

たとえばJavaのように、逆元を求めるライブラリが標準に用意されている場合は、それを利用するのが一番簡単です。

```java
public static long MOD = 1_000_000_000 + 7;

public long modinv(long x) {
  return BigInteger.valueOf(x).modInverse(BigInteger.valueOf(MOD)).longValue();
}
```

逆元を求めるAPIが用意されていない場合でも、べき乗のあまり(modpow)を求めるライブラリが用意されている場合は、これを利用します。たとえばPythonなどがそうです。

```python
MOD = 10**9+7

def modinv(x):
    return pow(x, MOD - 2, MOD)
```

逆元とべき乗のあまりのどちらも標準で用意されていないのであれば、自分で用意するほかありません。以下はRustの例です。

```rust
const MOD: i128 = 1_000_000_000 + 7;

fn modinv(a: i128) -> i128 {
     modpow(a, MOD - 2)
 }
 
 fn modpow(base: i128, exp: i128) -> i128 {
     if exp == 0 {
         return 1;
     }
     if exp % 2 == 0 {
         modpow((base * base) % MOD, exp / 2)
     } else {
         (modpow(base, exp - 1) * base) % MOD
     }
 }
```

__環境情報__

- javac 21.0.6
- Python 3.8.10
- rustc 1.83.0 (90b35a623 2024-11-26)
rex0220 計算式プラグイン テーブル内文字列複数行を転記

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、テーブル内文字列複数行を転記してみます。

# 概要

テーブル内文字列複数行を文字列複数行・文字列項目に転記します。
文字列複数行には、全行をまとめて転記。
文字列項目には、1行ずつ転記します。

※ テーブル・文字列複数行・グループを横並びプラグインで表示

![2025-06-17_10h53_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f9d5a9c1-e6e2-44a5-b332-22b5351b6978.png)

# 計算式プラグイン設定

文字列複数行は、テーブル行毎に"---------------"区切り表示
文字列は、1行ごとに分けて転記します。

![2025-06-17_10h48_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/abc1572b-03d6-428f-b832-844a92e48cc7.png)

```JavaScript:
OPTION: 

// 文字列複数行 MULTI_LINE_TEXT
JOIN(
  TARRAY(文字列複数行T),
  NEWLINE()&"---------------"&NEWLINE()
)

// グループ GROUP
LET(
  ary, SPLIT(JOIN(TARRAY(文字列複数行T),NEWLINE()),NEWLINE()),
  dmy, FSET(文字列1,ARRAY_GET(ary,0)),
  dmy, FSET(文字列2,ARRAY_GET(ary,1)),
  dmy, FSET(文字列3,ARRAY_GET(ary,2)),
  dmy, FSET(文字列4,ARRAY_GET(ary,3)),
  1
)

// 文字列1 SINGLE_LINE_TEXT
// 文字列2 SINGLE_LINE_TEXT
// 文字列3 SINGLE_LINE_TEXT
// 文字列4 SINGLE_LINE_TEXT
```
Module- Customize a Salesforce Object   Unit- Create validation rule　でのエラー



6月に入って目立つエラーです。解決策はよく分からない

:::note alert
An unexpected error occurred while inserting Opportunity records and we couldn't check your work. Make sure Opportunity records can be inserted in this org, and click "Check Challenge" again. If this continues, contact the Trailhead Help.
:::


+ [An unexpected error occurred while inserting Opportunity records and we couldn't check your work. Make sure Opportunity records can be inserted in this org, and click "Check Challenge" again. If this continues, contact the Trailhead Help.](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000TkJja)


---------------------

いつもの解決方法で問題なかった

+ [Hello! I Cannot test opportunity records in chapter Create Validation Rules](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Tkyai)
LINEBotでQRコードの画像を返すBotを作った話

こんにちは。tampopo256です。
普段は教育系のWebサービスを作ったりしています。

LINE Bot を作ってみたい、でも何かユニークな機能がほしい。
そんな中で思いついたのが「テキストを送ると即座にQRコード画像で返してくれるLINE Bot」でした。
今回は Google Apps Script（以下GAS）と無料のQRコード生成APIを使って、誰でも簡単に作れるBotを紹介します。

## やりたいこと

ユーザーがLINEでメッセージ（例えば`https://example.com`や`入場番号12345`など）を送信すると、その内容をQRコードに変換して画像で返信するBotを作ります。)


## 技術構成

* **LINE Messaging API**：メッセージ送受信のためのAPI
* **Google Apps Script (GAS)**：LINE Botのロジック実装とQRコード生成、返信処理を行う
* **QRコード生成API**：[QRServer API](https://goqr.me/api/)
* **Google スプレッドシート**：イベントログやエラーログを記録（オプション）


## 準備するもの

* LINE Developersで作成したチャネル（Botのアクセストークンなど）
* Google スプレッドシート

## 実装の流れ

### 1. LINEからのWebhookイベントを受け取る

```javascript
function doPost(e) {
  const eventData = JSON.parse(e.postData.contents);

  if (eventData.events && eventData.events.length > 0) {
    const event = eventData.events[0];
    const replyToken = event.replyToken;

    if (event.type === 'message' && event.message.type === 'text') {
      const userMessage = event.message.text;
      replyWithQRCode(replyToken, userMessage, event);
    }
  }

  return ContentService.createTextOutput(JSON.stringify({'content': 'success'}))
    .setMimeType(ContentService.MimeType.JSON);
}
```

LINEから送られてくるデータ（メッセージイベント）を受け取り、`text` メッセージだった場合はQRコード返信処理に進みます。

### 2. QRコードを生成して返信する

```javascript
function replyWithQRCode(replyToken, text, event) {
  const encodedText = encodeURIComponent(text);
  const qrCodeUrl = `https://api.qrserver.com/v1/create-qr-code/?data=${encodedText}&size=500x500&margin=30`;

  const message = {
    type: 'image',
    originalContentUrl: qrCodeUrl,
    previewImageUrl: qrCodeUrl
  };

  replyMessage(replyToken, message);
}
```

ここでは [QRServer API](http://goqr.me/api/doc/) を利用し、受け取ったテキストをURLエンコードした上でQRコード画像のURLを構築しています。LINEでは `image` メッセージタイプで画像を送信可能なので、それをそのまま使って返信しています。

### 3. LINEに返信する

```javascript
function replyMessage(replyToken, message) {
  const url = 'https://api.line.me/v2/bot/message/reply';
  const payload = {
    replyToken: replyToken,
    messages: [message]
  };

  const options = {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: 'Bearer ' + LINE_ACCESS_TOKEN
    },
    payload: JSON.stringify(payload)
  };

  try {
    UrlFetchApp.fetch(url, options);
  } catch (error) {
    logErrorToSpreadsheet(error);
  }
}
```

返信トークンを使って、LINEのMessaging APIにQRコード画像を送信します。


## 公開設定（GAS Webアプリとして）

1. GASのメニューから「デプロイ」 → 「新しいデプロイ」
2. 「種類の選択」で「ウェブアプリ」
3. 「自分として実行」「全員（匿名ユーザーを含む）」に設定
4. 公開されたURLをLINE DevelopersのWebhook URLとして設定

## まとめ

LINE BotとGAS、そして外部のQRコード生成APIを組み合わせることで、シンプルかつ実用的なQRコード生成Botを作ることができました。
GASを使うことでサーバー不要で開発できるのも大きなメリットです。

ちょっとした社内ツールやイベント用のBotとしても活用できるので、興味のある方はぜひ試してみてください！

## おまけ

なお、このLINE Botは現在 **[@274zsodn](https://lin.ee/wy2kjKB)** というLINE公式アカウントで実際にご利用いただけます。
以下のURLから友だち追加してお試しください：
👉 [https://lin.ee/wy2kjKB](https://lin.ee/wy2kjKB)

※無料プランで運用しているため、アクセスが集中した場合などには一時的に応答しないことがあります。あらかじめご了承ください。