OmniAICreator/Qiita-1.07M huggingface dataset:
Excel 自作関数 部分文字列一括置換用(SUBSTITUTE関数のネスト回避)

ChatGPTに作ってもろた。メモ用。

SUBSTITUTE()で複数の部分文字列を置換する際、ネストするのが嫌だったので、その回避用。

第1引数: 元の文字列
第2引数: 置換対象部分文字列が入ったセル範囲
第3引数: 置換後文字列が入ったセル範囲
※第2,3引数は次の3点を満たすこと
 ①置換対象と置換後の登場順が揃っている
 ②指定のセル数が一致
 ③1行 または 1列 のみ選択
  →行列同時に複数選択は不可

```diff_visual_basic
Function MultiSubstitute(stOriginalText As String, rgFindList As Range, rgReplaceList As Range) As String
    ' Application.Volatile True  ← 今回は不要
    
    Dim lCount As Long
    Dim i As Long
    Dim stFind As String
    Dim stReplace As String
    Dim stResult As String

    ' セル数の一致チェック
    If rgFindList.Cells.Count <> rgReplaceList.Cells.Count Then
        MultiSubstitute = CVErr(xlErrValue)
        Exit Function
    End If

    ' 1行または1列であることを確認（Find側）
    If rgFindList.Rows.Count > 1 And rgFindList.Columns.Count > 1 Then
        MultiSubstitute = CVErr(xlErrValue)
        Exit Function
    End If

    ' 1行または1列であることを確認（Replace側）
    If rgReplaceList.Rows.Count > 1 And rgReplaceList.Columns.Count > 1 Then
        MultiSubstitute = CVErr(xlErrValue)
        Exit Function
    End If

    lCount = rgFindList.Cells.Count
    stResult = stOriginalText

    For i = 1 To lCount
        stFind = CStr(rgFindList.Cells(i).Value)
        stReplace = CStr(rgReplaceList.Cells(i).Value)
        stResult = Replace(stResult, stFind, stReplace)
    Next i

    MultiSubstitute = stResult
End Function
```
ヤフーの1on1に学ぶ：部下を成長させるコミュニケーションの技法まとめ

# 🎯 ヤフーの1on1に学ぶ  部下を成長させるコミュニケーション技法まとめ

> 📘 書籍『ヤフーの1on1 部下を成長させるコミュニケーションの技法』の要点を、自分の理解を深めるためにまとめました。  
> 引用形式で要点を整理しています。

## 1. 💡 1on1の基本原則

- 👂 相手に十分話してもらう  
- 👀 最後までしっかり話を聞く  
- 🤐 自分の意見は控える  
- 🚀 次の行動を引き出す  

**✅ ポイント：**  
- 🔍 相手の話を深く掘り下げる  
- 🔁 相手の言葉を繰り返したり言い換える  
- 🎯 具体的なアクションを引き出す

## 2. 🎓 1on1の目的

経験学習（Learning from Experience）を促すことが1on1の核心！

1. 🧪 **具体的な経験**  
2. 🔄 **内省（ふりかえり）**  
3. 💡 **教訓の抽出**  
4. 🔧 **新たな状況への応用**

## 3. 🗣️ 1on1で使えるフレーズ集

- **「今日は何を話しますか？」**  
  → 🎯 テーマの選定は相手に任せよう

- **「もう少し詳しく聞かせてもらえますか？」**  
  → 🧠 深い内省を促す

- **「なるほど」**  
  → 👍 相手の話を受け止める肯定の姿勢

- **「いつまでにやろうか？」**  
  → 📆 次の行動を具体化する

## 4. 🛠️ 効果的な1on1の技法

### 👂 アクティブリスニング（傾聴）

- ✅ うなずく  
- ✅ 相槌を打つ  
- ✅ 相手の言葉を繰り返す

### 🤝 レコグニション

- 🫂 感情に寄り添う  
- 💬 同意ではなく共感を意識する

### 🎯 コーチング

- 🔍 質問で内省を深める  
- 🚫 指示せず、行動を引き出す

### 📚 ティーチング

- 🧾 社内ルールなど、知識として伝える

### 📢 フィードバック

- 🧭 期待とのギャップを示す  
- 🧠 周囲からどう見えているかを伝える

**✅ ポイント：**  
- 下記の問いを引き出せるように意識しよう！
  - 「今回のできごとから何を学んだ？」  
  - 「この学びをどこで活かせそう？」

## 5. ✅ 1on1で確認したいチェックリスト

- [ ] 相手の話を深掘りできているか  
- [ ] 相手の言葉を繰り返しているか  
- [ ] 別の言葉で言い換えられているか  
- [ ] 話を最後まで聞けているか  
- [ ] 自分の意見を抑えられているか  
- [ ] テーマの確認を最初にしているか  
- [ ] 相手が話したいテーマに沿って進められているか  
- [ ] 適切な相槌を打てているか  
- [ ] 聞く姿勢を見せられているか  
- [ ] 相手の気持ちに共感できているか  
- [ ] 言いづらいことでも、必要なフィードバックができているか  
- [ ] 行動について相手と共通認識が取れているか  
- [ ] 次の行動を相手から引き出せているか

## 最後に
下記のような記事も書いています！ご興味があれば、一読いただけると幸いです。

https://qiita.com/Nao52/items/4f5bf45972f9f2fab876

https://qiita.com/Nao52/items/50e2a85a6ee2a56ccf02

## 株式会社シンシア
<a href="https://corp.xincere.jp/" target="_blank" rel="noopener noreferrer">株式会社xincere</a>では、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら

https://www.wantedly.com/companies/xincere-inc/stories

シンシアでは、年間100人程度の実務未経験の方が応募し技術面接を受けます。
その経験を通し、実務未経験者の方にぜひ身につけて欲しい技術力（文法）をここでは紹介していきます。
Babylonjsでガウシアンスプラットを取り扱う

# ガウスプの雑な解説
点群を取り扱える拡張子
scaniverseという3Dモデルを撮影できるアプリで昨年頃に追加された
質の良い3Dモデルを作れるけどこの拡張しを扱えるところが少ない


# 結論
これで書ける
```javascript
BABYLON.ImportMeshAsync("https://assets.babylonjs.com/splats/gs_Skull.splat", scene).then((result) =>{
    const gaussianSplattingMesh = result.meshes[0]; });
```


# 実際の動作

playgroundで試してみる

デフォルトのカメラが使いにくいのでArcRotateCameraに切り替えておく

元々あるsphereとplaneは削除してから書き換える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/9f944d8a-3a03-42ac-9e3d-67a6488a6a96.png)
文字までしっかり見える


# 
自前のデータでやってみる

https://doc.babylonjs.com/toolsAndResources/thePlayground/externalPGAssets

Dropboxにて
対象のモデルを
”共有”
”リンクをコピー”
コピーしたリンクをドキュメントに従って修正
BABYLON.ImportMeshAsyncの第一引数に上書き
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/cf86618b-5550-4026-83ff-4b3025415cde.png)

これだけ
とっても簡単

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330568/61e1143e-d0a2-443a-92a2-5dc665553c3a.png)
道端で撮影したタヌキ
ゲームみたいに仕事がしたい！！Level１【LINE Bot制作編】

# みなさんはゲームって好きですか？
私は大好きです。
最近は仕事が忙しくてあまり新しいゲームが出来ていない日々ですが、ゲームに没頭していた時期の私は、日常生活でも、走るときに脳内でBボタンを押している錯覚に襲われたりしておりました。（良くない症状ですね）


**「ゲームみたいに仕事出来たら良いのにな～～～～。」**
これは全ゲーマーの願いではないでしょうか。ちょっぴり面倒な仕事も、ゲームのように取り組むことができれば、楽しく生産性＆やる気も上がるのでは！？
デジタル初心者の私ですが、「ゲームのように直感的な操作で誰もが使えて、使っていて楽しいツールをつくる」ことを現状の目標としてデジタルの勉強を開始することにしました！！

### ⭐「日常の業務がクエスト風に表示されるLINE botを作りたい！！」
日常の業務は、毎日・週間・月間のタスクの他にも、日々刻々と増えていきます。
私は普段、仕事において紙のToDoリストを使用していますが、
紙のTODOリストだとリマインド機能も無いため、書いたこと自体を忘れてしまうことも。

それに、紙のリストだと、終わって消し込んだ作業も視覚的には残り続けます。

 ~~・〇〇さんにメールを送る~~ 
 ~~・什器の発注書を作成する~~

 ↑こんな感じです。
これにより、業務量がより多く感じてしまうのが、紙の欠点です。
また、今はTodo管理アプリも数多く配信されておりますが、より直感的に使えるものが欲しいなと感じているところでした。

さらに、面倒くさがりの私の欲望は膨らんでゆきます。

**「日々の業務や日常生活のタスクが、ゲームのクエストだったら楽しく取り組めるのになあ～」**
**「タスクがクエスト画面みたいに表示できて、達成するごとに自分のレベルが上がって行く仕様のアプリがあったら、さらにやる気になるのになあ～」**

そんなゲーム脳的な考えから、「クエスト風ToDoアプリ」を作りたいと思い、LINE Botで制作を試みることにしました:v:

# 🎮制作過程🎮
### ①Google Calendarと連携
Google Calendar＋Google Sheetsを使用して、Google Calendarに「予定」を書き込み、日時と詳細を入力すると、LINE Botに通知が来るシステムを作成しました。また、同時にGoogle Sheetsにも記録がされるようにもしています。

![スクリーンショット (32).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079667/57d2bdfc-b16a-4331-84f5-30584f12ef5a.png)

↓モジュールの中身はこんな感じです。
![スクリーンショット (33).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079667/c96c44a8-866f-4433-93b7-04730ade9496.png)

↓Google Sheetsの中身です。
タイトル・日時・完了メッセージ受信日時の３つに分けて記録しています。
システムの構築に苦戦してテストを繰り返しています。
![スクリーンショット (40).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079667/f1119d9a-716a-4d95-92d2-afa5e3d57fdf.png)

### ②シナリオを増やし、LINE Botの返答を分岐。
![スクリーンショット (34).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079667/bdda682d-c81e-4e45-8d16-08571b0dfe33.png)

ユーザーが「クエスト完了！」と送信すると、「クエスト完了！おつかれさま！！」
その他の言葉を送信すると「クエストを進めよう」と返信が届くように設定しました。
間に挟まっているToolsは、時間の表示方法の変更のために追加しています。

↓LINE Bot画面です。
![image0.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4079667/a0e3faf7-3394-45db-9d9e-22112579fd96.jpeg)


# 完成したのがこちら。

https://x.com/i/status/1927811390850617851
### ✅反省点と今後の展望
◆日付と時間の表示方法を（YYYY-MM-DD hh:mm A）の形式に統一したかったのですが、中々うまくいかないなど、細かいところでかなり苦戦してしまいました💦
また、作っているうちにシナリオ数が増えすぎてしまい、シナリオ同士を統合するのにも苦労しました…。（Make無料ユーザーの私は、同時に動かせるシナリオが2個までだと後から気が付きました。）

◆当初の計画では、LINEBotに「終わっていないクエストは？」「完了したクエストは？」と聞くと「〇〇です！！」と答えてくれたり、完了したクエストを集計してくれて、完了したクエストの個数が一定数に達すると、「レベルアップしました🌱」というメッセージや、癒しのうさぎ画像を送ってくれるような機能もつける予定だったのですが、今回はそこまでは出来ずでした。
（Bot名をUSAGIクエストにしたのはそういう理由でした。無念🐰）

◆さらに改良を進めることで、仕事や日常生活が楽しく、快適になる手助けを出来るようなToDoBotにしていきたいです✨

初めてのLINE Bot制作は前途多難でしたが、Botが動く楽しさを知ることが出来たのは大きな収穫です！！さらに勉強をしなくては:raised_hands:
今後もデジタル技術のレベル上げ頑張ります！！🥚🐣🐓
Gitで過去の自分のコミット全てのメールアドレスを変更したい

備忘録として。たぶん新しいより優れたやり方があるはずだけど、「なんでもいいから今すぐ動く `過去の自分のコミット全てのメアド変更コマンド` くれよ！」という時に...

## 結論

こう

```sh
git filter-branch --env-filter 'if [ "$GIT_COMMITTER_EMAIL" = "old_email@example.com" ]; then export GIT_COMMITTER_EMAIL="new_email@example.com"; fi; if [ "$GIT_AUTHOR_EMAIL" = "old_email@example.com" ]; then export GIT_AUTHOR_EMAIL="new_email@example.com"; fi' -- --all
```

実行すればローカルにある過去の全コミットのうち、 `old_email@example.com` がメールアドレスのコミットを、 `new_email@example.com` に変えてくれる。

リモートも変えたければこれを強制pushすればOK！...とはいえチーム開発での強制pushは常にリスクを伴うので、問題ない状態にしてからやるのを推奨。いわゆる自己責任で...ってやつですね。
Google検索だけじゃない！検索効率を40％高める実践スキルとAIツール活用法

> 「調べ方がわからない…」「検索してもノイズが多い…」  
> そんな悩みを解決する、検索スキルとツールの“実践ガイド”をお届けします。

---

## 🎯 検索スキルは現代ビジネスの必須能力

- 情報収集力＝仕事力
- 実務・学習の場で圧倒的な差がつく
- 検索効率を改善すれば**時間と成果が倍増**

---

## 1️⃣ Google検索の基本テクニック

| テクニック | 説明 | 例 |
|------------|------|----|
| `-`（除外） | 不要な語句を除外 | `Java -Script` |
| `" "`（完全一致） | その語順で一致 | `"職業訓練校 就職率"` |
| `AND / OR` | 複数条件を組み合わせる | `転職 AND 資格` |
| `*`（ワイルドカード） | 不明語句の補完 | `"Python * 入門"` |

---

## 2️⃣ 実務に効く！応用検索テクニック

| テクニック | 説明 | 例 |
|------------|------|----|
| `filetype:` | PDFやExcelに限定 | `履歴書 filetype:pdf` |
| `site:` | 特定サイトを検索 | `助成金 site:mhlw.go.jp` |
| `intitle:` | タイトルに含む語 | `intitle:"自己PR"` |
| 画像検索 | ビジュアル探索 | `プレゼン スライド 例` |

---

## 3️⃣ 職種別：検索スキルの活かし方

| 職種 | 検索活用例 |
|------|------------|
| エンジニア | エラーコード、GitHub、Stack Overflow |
| 営業職 | 企業HP、業界ニュース、IR資料 |
| デザイナー | 素材検索、配色例、UIデザイン |
| 事務職 | 文書テンプレート、関数の使い方 |

---

## 4️⃣ モバイル時代の検索術

- 🎙 音声検索の活用  
- 📱 モバイル対応か見極める（表示崩れしないか）  
- 👀 検索結果の評価法：更新日・筆者・ドメイン名を確認

---

## 5️⃣ 信頼性ある情報の見極め方

- 🔍 E-E-A-T：経験・専門性・権威性・信頼性
- ✅ 出典確認：信頼できる機関や著者か？
- 🗓 更新日：古い情報ではないか？
- 🔄 複数ソースでクロスチェック

---

## 6️⃣ Googleだけじゃない！次世代検索AI・ツール比較

| ツール | 特徴 | 向いている人 |
|--------|------|--------------|
| [Felo AI](https://felo.ai/ja/search) | 会話型AI検索＋要約＋関連表示 | 文脈ごとに理解したい人 |
| [Perplexity.ai](https://www.perplexity.ai/) | 出典付きAI検索 | 調査・学習向き |
| [You.com](https://you.com/) | カスタマイズ検索 | プログラマー向き |
| [Kagi](https://kagi.com/)（有料） | 広告ゼロ・高速 | 研究・集中作業向け |
| [Elicit](https://elicit.org/) | 論文検索＋AI要約 | 学術リサーチ向け |
| [Wolfram Alpha](https://www.wolframalpha.com/) | 数式・統計解析 | 教育・計算用途に最強 |
| [Internet Archive](https://archive.org/) | 消えたページも見れる | 古い資料の確認 |

---

## 7️⃣ 目的別：検索ツール使い分けガイド

| 目的 | 推奨ツール |
|------|------------|
| 複雑な質問 | Felo, Perplexity |
| 学術資料 | Elicit, Semantic Scholar |
| 正確な計算・定義 | Wolfram Alpha |
| ノイズ除去 | Kagi（有料） |
| エラー調査 | You.com, Stack Overflow |
| 過去のWeb情報 | Wayback Machine |

---

## 8️⃣ 検索力を伸ばし続ける習慣

- 🗓 毎月「検索テクニック」アップデート  
- 📘 検索履歴を学習ログとして活用  
- 🌐 定期チェック推奨サイト：

| サイト | 内容 |
|--------|------|
| Google検索ヘルプ | 演算子・裏技ガイド |
| Qiita | 技術ブログ、トラブル解決 |
| Stack Overflow | コーディングQ&A |
| NewsPicks / note | 業界トレンド分析 |

---

## ✅ まとめ：検索は“武器”になる

情報に溢れた時代こそ、「調べる力」が最強のスキル。  
目的に応じてGoogle・AI検索・専門ツールを使い分ければ、  
**仕事も学習も、成果もスピードも変わります。**

> 🔧 検索は「知識を得る技術」ではなく、「問題を解決する武器」  
> 今日から、あなたの検索力を武装しよう。

---

📝 ご質問・活用事例があればコメントにて歓迎です！
ChatGPTを使用したアプリ開発記【ハンバーガーメニューの追加】

## 1. menuOpen ステート
```Header.js
const [menuOpen, setMenuOpen] = useState(false);
```
•	ハンバーガーメニューが**開いているか（true）閉じているか（false）**を管理するステート。
•	初期状態では false、つまりメニューは非表示。

## 2. toggleMenu 関数
```Header.js
const toggleMenu = () => {
  setMenuOpen(prev => !prev);
};
```
•	ボタンを押すたびに menuOpen を true ⇄ false に切り替えます。
•	これによってメニューを**開閉（トグル）**します。

## 3. ハンバーガーメニューアイコンの表示・切り替え
```Header.js
<div className="md:hidden">
  <button onClick={toggleMenu} className="text-gray-600">
    {menuOpen ? <X size={28} /> : <Menu size={28} />}
  </button>
</div>
```
•	モバイル表示（md:hidden）のみ有効。
•	menuOpen が true のときは X（閉じるアイコン）、false のときは Menu（三本線）を表示。
•	lucide-react ライブラリのアイコンを使用。

## 4. 実際のモバイルメニュー（開いた時）
```Header.js
{menuOpen && (
  <div className="md:hidden mt-2 px-2 space-y-2">
    ...
  </div>
)}
```
•	menuOpen が true のときだけこの div が表示されます。
•	md:hidden により、モバイル表示でのみ表示。

## 中身の構成
```Header.js
      {menuOpen && (
        <div className="md:hidden mt-2 px-2 space-y-2">
          <div className="flex items-center space-x-3">
            <img src={profilePhotoURL} alt="アイコン" className="w-8 h-8 rounded-full border" />
            <span
              className="text-blue-600 text-sm font-medium cursor-pointer hover:underline"
              onClick={() => {
                toggleMenu();
                navigate(`/profile/${currentUserId}`);
              }}
            >
              {profileName}さんのプロフィール
            </span>
          </div>
          {user && (
            <button
              onClick={() => {
                toggleMenu();
                handleLogout();
              }}
              className="w-full bg-blue-500 text-white text-sm px-3 py-2 rounded-xl hover:bg-blue-600 transition shadow"
            >
              ログアウト
            </button>
          )}
        </div>
      )}
```

•	プロフィール画像と名前（プロフィールページへのリンク）
•	ログアウトボタン
•	両方とも押すと toggleMenu() が呼ばれ、メニューが閉じる。

## UI
**デフォルト**
![IMG_7428.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/16db77f0-74f1-4299-8c24-a0c61e43cfe8.jpeg)
**✖️ボタン押下**
![IMG_7429.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/3cf70a50-733b-4f31-b6c7-8378c8fcbeaa.jpeg)
3分で地図づくり：Feltで避難所マップを作って公開

# はじめに
[Felt](https://felt.com) って聞いたことあるでしょうか？どんな地理空間データでもアップロードして簡単に地図を作成・共有できることを謳うサービスです。主要なGISデータは、ベクタだけでなくラスタ、ウェブ地図も取り込める、ビックリするぐらいの使いやすさと柔軟さを持つ新しい地図サービスです。
そんなFeltを使って、何ができるか、どのくらい簡単なのか、色々チャレンジしたいと思います。

# お題
今回は、沖縄県の避難所データを使ってどれだけ簡単に地図を作って共有できるか試します。

# 前提
Feltのアカウントが利用でき、データのアップロードの権限があること。

# 5分チャレンジ
### データダウンロード
まずは、基盤地図情報ダウンロードサイトから、[避難所のデータ](https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-P20.html)のうち、沖縄県分のデータをダウンロードをしました。ここまで40秒。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/969ca155-f70e-4acd-9d65-9e21fc74481b.png)

P20-12_47_GML.zip というファイルが手元に落ちてきました。

### データアップロード
次に、あらかじめ開設しておいたFeltのアカウントを開き、画面右上にある「New map」という赤いボタンをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/6c0db45d-4b61-42de-b5dc-0490147530fb.png)

空の地図が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/5e6b22c6-d257-4e2f-8edd-08962155d49d.png)

早速、ダウンロードしたZIPファイルを地図上にドラッグ&ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/16d827aa-4192-4607-aaea-db5a7e45203b.png)

くるくると回るアイコンで、一生懸命作業をする様子が伺えます。1分弱で処理が終わって、データの範囲にズームするか聞いてきたので、クリックすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/00cc3b58-fa6a-401d-bcf6-d7bcbd8cb1d1.png)

地図ができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/dcc01ced-906b-4217-a2c6-c58becb621fa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/3f55bb97-aa93-423e-8e40-6df9937382c5.png)

### 地図の共有
最後作成した地図を公開するために、Untitled Mapと書かれているところをクリックして地図のタイトル「沖縄避難所マップ」を入れ、「Share」ボタンをクリックして、リンクをコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59906/6a33a668-6b03-4519-a569-2178ce865d44.png)

これが作成できた地図です。
[地図のリンク](https://felt.com/map/Chong-Nawa-Bi-Nan-Suo-matupu-syQS0zMWTMebqOFTRJ5ujA?loc=26.21572,127.68905,15.01z&share=1)

全く何も加工していない地図ですが、データのダウンロードから地図の公開までは上の手順で、1分20秒かかりました。

# まとめ
今回は、Feltで簡単な地図を作って公開・共有するまでの流れを辿ってみました。次回はもう少し深くFeltを掘っていきたいと思います。
FTPソフトでファイルジラに接続できません。

コノハウィングで
FTPソフトファイルジラで
全然接続できないんですが

この画面の情報だけでは接続できないものでしょうか？

ホスト名
www96.conoha.ne.jp

ユーザー名
pkun@architectures.space

パスワード 

でFTPで接続で
何回接続しようとしても
ダメなんですがなんででしょうか？![2025-05-29 0.30の画像.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1230737/dbb0ede6-d9ee-41d6-9606-8e4566b6de1d.jpeg)


何度もやっても接続できません
分かる方、どうかよろしくお願いします。m(__)m
コードレビューの進め方と重要ポイントまとめ


この記事では、コードレビューを行う際に気をつけるべきポイントやプロセス、さらに「将来的な問題」にも目を向ける方法について詳しくまとめます。  
また、参考にした記事として [わからないところは聞く - Qiita](https://qiita.com/awakia/items/8344ba751426e386e0f5) の要点も含めています。

---

## 1. コードレビューの基本方針

### **目的は品質向上とナレッジ共有**

コードレビューは単にバグを見つけるだけの作業ではありません。以下の観点でレビューを進めると良いでしょう。

- **品質向上**  
  コードのバグ・パフォーマンス問題を見つけ、より良い実装に改善する

- **可読性・保守性の向上**  
  チームで長期的にメンテナンスしやすいコードになっているか

- **ナレッジ共有・教育**  
  コードレビューを通じてチームメンバーのスキル向上や情報共有を図る

---

## 2. コードレビューでのチェックポイント

### 2.1 diffとして見えている部分

PR（Pull Request）や差分（diff）として見えている箇所は、以下を重点的に確認します。

#### ✅ スペルミスがないか  
  - 変数名、コメント、ドキュメント、APIエンドポイント名などにスペルミスがないか

#### ✅ コーディング規約に従っているか  
  - チームのスタイルガイドや言語特有のベストプラクティスに沿っているか
  - インデント、改行、変数命名規則、関数の長さなど

#### ✅ if文の条件が正確か  
  - 条件式の比較演算子や論理演算子が意図通りになっているか  
  - 条件の順序や括弧が適切か

#### ✅ エラー処理が適切か  
  - 例外やエラーが正しくハンドリングされているか

#### ✅ パフォーマンスやスケーラビリティに問題がないか  
  - 無駄なループや重複コードはないか  
  - 必要に応じてキャッシュや最適化がされているか

---

### 2.2 diffとして見えていない部分

見えていない部分にも目を向けるのが重要です。  
例えば、PRには一部の変更だけが見えていることが多いため、以下のような問題が潜んでいないかを意識します。

#### ✅ 空間的な問題  
- **他のモジュールやライブラリとの依存関係は問題ないか**  
- **共通処理の一貫性が保たれているか**  
- **同じロジックが複数箇所に分散していないか**

#### ✅ 時間的な問題（将来の変更による問題）  
- **今後の要件変更で壊れやすい部分がないか**  
- **将来の拡張やバグ修正が困難にならないか**  
- **直近の別PRや別タスクで競合が起きないか**

---

## 3. テストの必要性を判断する

レビューしながら「テストを書くべきかどうか」も見極める必要があります。  
以下の視点でテストの追加・修正が必要かを判断しましょう。

- **新機能追加やバグ修正に伴うテストが含まれているか**  
- **リグレッション（既存機能の破壊）防止のテストがあるか**  
- **テストデータやモックが適切に準備されているか**  
- **テストカバレッジが重要な箇所を網羅しているか**

もしテストが十分でないと感じたら、追加を依頼したり、どういうテストが必要かを指摘します。

---

## 4. コードレビュー時に心がけること

### 📝 **わからないところは遠慮せずに質問する**

- どんなに経験を積んでも、実装者の意図が見えない部分は必ず出てきます。  
- そのままレビューを進めると誤解が生まれやすいので、早めに質問するのが大切です。

例：  
「この条件式はこういう意図で書かれているのでしょうか？」  
「このAPIは外部仕様上こう動く認識で合ってますか？」  

### 🤝 **コミュニケーションを大切にする**

- レビューコメントは「指摘」より「対話」を意識します。  
- 「こうしたらどうですか？」と提案形式にするだけでも、相手の受け取りやすさが変わります。

---

## 5. まとめ

コードレビューは「コードを良くする」だけでなく、「チームを強くする」重要な活動です。  
今回の記事でまとめたポイントを意識しながら、ぜひ日々のレビューに役立ててみてください！

---

## 📚 参考URL

- [わからないところは聞く - Qiita](https://qiita.com/awakia/items/8344ba751426e386e0f5)
Geminiでオルゴールを使う魔法少女を描いてみた。

# 概要

Geminiでオルゴールを使う魔法少女を描いてみました。

# 実装

プロンプトと実行結果は以下の通りです。

```
光のオルゴールを使う魔法少女を描いてください。
```

![光のオルゴールを使う魔法少女_20250529.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/b20b2e60-7d87-4cc1-849f-373de12b28ab.png)

# まとめ

可愛い子。
何かの役に立てばと。
(調査中)Spring MVC。bodyのgzip解凍されずに文字列化・MDC格納・レスポンス返却したら連携元でエラーになった



## ✅ 現象の整理

| 項目          | 内容                                                                                        |
| ----------- | ----------------------------------------------------------------------------------------- |
| 連携元         | `Accept-Encoding: gzip` を付けて HTTP リクエスト送信。つまり「gzipでもいいよ」と宣言。                              |
| 連携先（本来のサーバ） | gzip 圧縮されたレスポンスを返し、`Content-Encoding: gzip` をヘッダーに付ける。OK。                                 |
| Proxy       | ヘッダー `Content-Encoding: gzip` はそのまま残して中身（body）も gzip 圧縮のまま通している。                          |
| あなたのアプリ     | `WebClient + reactor-netty` を使って受信し、MDC に body を `put`（この時点で文字化け）。最終的にそのまま連携元に返却するとエラー発生。 |

---

## ❗ 問題点

* **WebClient が自動で gzip 解凍していない**（通常は `reactor-netty` が自動解凍するが、`Content-Encoding` に応じた処理が一部の構成でスキップされることがある）。
* **文字化けの原因は gzip 圧縮されたバイナリを文字列として扱ったため**。
* **MDC に入れた body が読めないのは、gzip 解凍前の生データを `String` として無理に扱ったため**。
* **連携元が gzip を受け入れると言ったのに、gzip のまま返してしまった**。ただし、その内容が**正しく解凍可能な gzip でなければ連携元側でもエラーになります。**

---

## ✅ 誰に責任がある？

| 当事者                                             | 判断                                                        |
| ----------------------------------------------- | --------------------------------------------------------- |
| **連携元**                                         | `Accept-Encoding: gzip` を送るのは HTTP/1.1 標準仕様。責任なし。         |
| **連携先**                                         | `Content-Encoding: gzip` を付けて返しているのは正しい。問題なし。             |
| **Proxy**                                       | 通常、**gzip 圧縮レスポンスを中継するならそのままにするのが正しい**。削除してはいけない。なので問題なし。 |
| **あなたのアプリ（中継サービス）**                             |                                                           |
| 👉 **ここで解凍されずに文字列化・MDC格納・レスポンス返却したのが直接的な原因**です。 |                                                           |

---

## ✅ 正しい対処・設計

### 1. **WebClient で受け取ったときに gzip 解凍されているか確認**

```java
webClient.get()
    .uri("...")
    .acceptEncoding("gzip")  // 自分からも gzip OK と言っている？
    .retrieve()
    .bodyToMono(byte[].class) // byte配列で受け取る
    .map(bytes -> encodingUtils.autoDecode(bytes, StandardCharsets.UTF_8))
```

### 2. **MDC に入れる前に文字列化（必要なら解凍）**

```java
String decodedBody = encodingUtils.autoDecode(bodyBytes, StandardCharsets.UTF_8);
MDC.put("body", decodedBody);
```

### 3. **レスポンス返却時には圧縮し直すか、非圧縮で返す**

* 連携元が `Accept-Encoding: gzip` を指定しているなら gzip で返してもいいが、

  * **中継処理内で一度解凍した場合、再圧縮しないとそのままでは返せない！**
* 逆に、圧縮レスポンスを再構成しないなら `Content-Encoding` を削除する必要あり。

---

## ✅ 最終的な判断

> **連携元が `Accept-Encoding: gzip` を送っているのは正しい。問題はあなたのアプリ側で "gzip圧縮されたbodyを文字列として誤って扱った"、"再圧縮せずにそのまま返した" ことにある。**

---

## ✅ 推奨方針（簡易）

* WebClient の受信時点で `byte[]` で受け取り、gzipか確認して手動解凍。
* MDCやログ、body表示には **文字列化された内容**を使う（生バイナリはNG）。
* 再送信するときは、解凍済みのものを非圧縮で送るか、**明示的に再 gzip 圧縮して `Content-Encoding: gzip` を付けて返す。**

---
gitでmergeを入力したはずがrebaseになってしまう

# gitでmergeを入力したはずがrebaseになってしまう
ローカル上でmergeするとなぜかrebaseになってします。
そのせいでcommitが倍々に増えていきました。

## 原因
下記設定が有効だったため、mergeしても強制的にrebaseになってしまう。
```shell
git config pull.rebase true
```

## 確認方法
Gitの設定を確認する。
```
git config pull.rebase
```
## 解決方法
pull.rebaseを無効にする。
```
git config pull.rebase false
```

## まとめ
無意識で設定していたため、謎で大迷惑していた。
DNSキャッシュポイズニングの基礎

# DNSキャッシュポイズニング

**DNSキャッシュポイズニングとは**
キャッシュDNSサーバーへ偽の情報を登録し、偽のサイトへ誘導する攻撃手法。

# 手順

① 攻撃者はキャッシュDNSサーバーへqiita.comのIPは何かと問い合わせる。
② キャッシュDNSサーバーはコンテンツDNSサーバーへqiita.comのIPを問い合わせる。
**③攻撃者はコンテンツDNSサーバーのフリをしてキャッシュDNSサーバーに**
**偽のIPアドレスを応答する**

キャッシュDNSサーバーはもし、問い合わせが行われたドメインのIPアドレスがキャッシュされていた場合にそのキャッシュ情報からIPアドレスの応答を返すという性質がある。
これにより攻撃者はキャッシュDNSサーバーに偽のIPアドレスをキャッシュしたため、もしqiita.comにアクセスしようとしても別の偽サイトに飛ばされてしまう事となる。

# 原因

DNSは先に応答した情報を信じる仕様なので、それを悪用した攻撃手法である。
DNSはトランザクションIDとポート番号で信頼性を検証しているがトランザクションIDは推測されやすいのと、ポート番号はポートスキャンなどにより特定できてしまうためこのような攻撃が可能になる。

## 対策
**・オープンリゾルバにしない。**
　不特定多数、外部からの要求を受け付けないようにすることによって、攻撃者を減らすことができる。
**・ポート番号をランダム化**
　先ほども記述したようにDNSはトランザクションIDとポート番号で信頼性を検証しているため、ポート番号をランダムにすることにより信頼性の検証に失敗させることができる。
**・キャッシュ時間(TTL)を長くする。**
　たとえば、キャッシュ時間を24時間にしてしまえば正規のユーザーが正規の情報をキャッシュした場合24時間はIPアドレスがキャッシュされているのでキャッシュDNSサーバーはコンテンツDNSサーバーに問い合わせを行わないため既にあるキャッシュ情報を応答する。
これにより攻撃が無効になる。
※長くしすぎるとホスト先のIPアドレスが変更された場合にアクセスができなくて、トラブルが発生する可能性がある。
競プロ日記#25/05/28

# 競技プログラミングの鉄則
[A18 - Subset Sum](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_r)
- 二次元dpの復習。2回目
- ちゃんと理解できているか確認のために自力で0から実装。
- 一応ACできたから二次元DPの典型問題であれば解けるはず。あとは全く別の問題が来た時に「これは二次元DPで解ける」というように解法と問題の紐づけができるかどうか
```
long long N,S;
long long A[69];
bool dp[69][10009];

int main() {
    cin >> N >> S;
    for (int i = 1; i <= N; i++) {
        cin >> A[i];
    }
    dp[0][0] = true;
    for (int j = 1; j <= N; j++){
        dp[0][j] = false;
    }

    for (int i = 1; i <= N; i++){
        for (int j = 0;j <= S; j++){
            if(j < A[i]){
                dp[i][j] = dp[i-1][j];
            }
            if (j >= A[i]){
                if (dp[i-1][j] || dp[i-1][j-A[i]]) {
                    dp[i][j] = true;
                } else {
                    dp[i][j] = false;
                }
            } 
        }
    }

    cout << (dp[N][S] ? "Yes" : "No") << endl;
}
```

[B39 - Taro's Job](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_dl)
- 内容的にも優先度付きキューなのでそんなに難しくない。応用問題でも問題なくACできた。
```
int main() {
    long long N,D;
    cin >> N >> D;
    vector<long long> job[2009];
    priority_queue<long long> pq;
    long long ans = 0;
    for (int i = 0; i < N; i++) {
        long long X,Y;
        cin >> X >> Y;
        job[X].push_back(Y); // X日目にY円の仕事がある
    }
    for (int i = 1; i <= D; i++) {
        for (int j = 0; j < job[i].size(); j++) {
            pq.push(job[i][j]); // X日目の仕事を優先度キューに追加
        }
        if (!pq.empty()) {
            long long work = pq.top(); // 最も長い仕事を取得
            pq.pop(); 
            ans += work; // その仕事のお駄賃を加える
        }
    }
    cout << ans << endl; // 合計の金額を出力
}
```

[B62 - Print a Path](https://atcoder.jp/contests/tessoku-book/tasks/tessoku_book_ei)
- 深さ優先探索の復元についての問題
- dfs()をStackを使って改造するという発想は全然なかった。要復習
```


void dfs(int pos){
    if (pos == N){
        Answer = Path;
        return;
    }
    visited[pos] = true;
    for (int i= 0;i < G[pos].size(); i++) {
        int next = G[pos][i];
        if (!visited[next]) {
            Path.push(next);
            dfs(next);
            Path.pop();
        }
    }
    return;
}


int main() {
    cin >> N >> M;
    for (long long i = 0; i < M; i++) {
        long long a, b;
        cin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    for (int i = 1; i <= N; i++){
        visited[i] = false;
    }
    Path.push(1);
    dfs(1);
    
    vector<int> Output;
    while (!Answer.empty()) {
        Output.push_back(Answer.top());
        Answer.pop();
    }
    reverse(Output.begin(), Output.end());

    for (int i = 0; i < Output.size(); i++) {
        
        cout << Output[i] << " ";
    }
    cout << endl;
    
}
```
LICENSEファイルが原因でpushができなかった話

備忘録かねて初投稿です。

初心者エンジニアらしくプログラム書いていざGitHubへプッシュ！…と思ったら、こんなエラーに遭遇しました。

```
! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/xxxxx/xxxxxx.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally.
```

Gitは普段使っているのですが、このエラーは初めてでした。原因は **LICENSEファイル** とのこと。

---

## 何が起きていたのか？

Gitのエラーメッセージが示す通り、「リモート（GitHub）に、ローカルにはない変更があるからプッシュできないよ！」という状況でした。

今回の原因はシンプルでした。

1.  ローカルPCで `git init` して、**まっさらな状態**からコミットを開始。
2.  GitHubでリポジトリを作成する際、`Add a LICENSE file` オプションにチェックを入れてしまい、GitHub側で**LICENSEファイルを含む初期コミット**が作成されていた。

Gitから見ると、ローカルとリモートはそれぞれ異なる履歴から始まった**無関係な履歴**。そのため、そのままプッシュするとデータが壊れる可能性があるので、Gitが安全のために拒否した、というわけです。

---

## 解決策：リモートの変更を取り込んでからプッシュ

この問題を解決するには、まずリモート（GitHub）の変更をローカルに取り込み、その上で自分の変更をプッシュするという手順を踏みます。

重要なのは、互いに無関係な履歴をマージするためのオプションです。

1.  **リモートの変更をローカルに取り込む (`git pull`)**

    ```bash
    git pull origin main --allow-unrelated-histories --no-rebase
    ```

    * `--allow-unrelated-histories`: 互いに無関係な履歴でもマージを許可するためのオプション。
    * `--no-rebase`: `git pull` がデフォルトで `rebase` を試みるのを避け、`merge` 戦略を使うことを明示します。関連性のない履歴では `rebase` がうまくいかないため、この指定が重要です。

    このコマンドを実行すると、私の環境では **Nanoエディタ** が立ち上がりました。（普段はVimを使用していたので切り替えないと...）

    **Nanoエディタの操作:**
    * 表示されたマージコミットメッセージを確認。（通常、変更不要）
    * **`Ctrl + O`** を押して保存 (`^O WriteOut`)。ファイル名の確認で `Enter`。
    * **`Ctrl + X`** を押してNanoを終了 (`^X Exit`)。

    これでGitHubのLICENSEファイルがローカルに取り込まれ、履歴が統合されました。

2.  **再度プッシュする (`git push`)**

    `git pull` が成功し、履歴が統合された状態になったら、改めてプッシュします。

    ```bash
    git push origin main
    ```

    (`git push -u origin main` を一度実行していれば、次回からは `git push` だけでOKです。)

---

### まとめ

Gitの `[rejected]` エラーは、ローカルとリモートの履歴の差異が原因で起こることが多いです。特に、GitHubでリポジトリ作成時に自動生成されるファイル（READMEや**LICENSE**など）が原因で、今回のように「無関係な履歴」となってしまうケースがあるので注意が必要です。

もし同じエラーに遭遇したら、このコマンドを試してみてください！

```bash
git pull origin main --allow-unrelated-histories --no-rebase
git push origin main
```

これで無事にGitHubにプッシュできました。
ハッシュ関数 メモ

# ハッシュ関数とは
ハッシュ関数は入力データに対して複雑な計算を行い、
入力データがどんなに長いor短い文字列だとしても**固定**の長さでハッシュ値を生成する関数です。

# ハッシュ値の3つの困難性
ハッシュ値には3つの困難性が存在し、これらが一つでも欠けてしまうとハッシュ値からの復元が現実的に可能になってしまう恐れがあります。

## ・原像計算困難性(一方向性)
ハッシュ値から元のデータを復元することが**困難**であることを指します。
## ・第二原像計算困難性
既にあるハッシュ値に対し、異なる入力から同じハッシュ値を生成することが**困難**であることを指します。
## ・衝突発見困難性
同じハッシュ値になる異なる入力を見つけ出すことが**困難**であることを指します。

# ハッシュ関数の種類

**・MD5 ※衝突困難性が欠けており非推奨だが古くからある**
　**ハッシュ関数のため、修正を行わずそのまま使用している所もある**
**・SHA-1 ※衝突困難性が欠けており非推奨**
**・SHA-2**
**・SHA-3 など.......** 

## まとめ
ハッシュ関数を用いることでデータに高速でアクセスできたり、平文を使用してデータの整合性を取るよりハッシュ化されたデータで整合性を取ることで処理速度向上、安全性の向上にも役立つ。
SQLインジェクション

# SQLインジェクションとは

SQLインジェクション（SQLi）は、**悪意のあるユーザーがWebアプリケーションにSQL文を注入することで、データベースを不正に操作する攻撃手法**です。

たとえば、ログインフォームに入力された値をそのままSQLに組み込むと、次のような脆弱性が生じます。

```sql
-- 脆弱な例
SELECT * FROM users WHERE username = '$inputUsername' AND password = '$inputPassword';
```

このとき、もし`$inputUsername`に`' OR '1'='1`を入力されると、SQL文は次のようになります。

```sql
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';
```

`'1'='1'`は常に真なので、誰でもログインできてしまいます。

---

# 主なSQLインジェクションの種類

### 1. ブラインドSQLインジェクション（Blind SQLi）

攻撃結果が画面に表示されない場合でも、**挙動から内部の状態を推測するタイプ**の攻撃です。

```sql
-- 例：IDの存在確認
SELECT * FROM products WHERE id = 10 AND 1=1;
SELECT * FROM products WHERE id = 10 AND 1=2;
```

表示の有無で「条件が通ったか」を知ることができます。

### 2. エラーベースSQLインジェクション（Error-based SQLi）

**意図的にエラーを発生させ、そこから情報を引き出す攻撃**です。

```sql
-- 例：意図的なエラーを出す
SELECT * FROM users WHERE id = 1 UNION SELECT 1, @@version, 3;
```

DBのバージョンなどが画面に表示される場合があります。

### 3. UNIONベースSQLインジェクション

`UNION`を使って、**本来のクエリと別の結果を結合して表示させる攻撃**です。

```sql
-- 例：usersテーブルと攻撃者のクエリを結合
SELECT name, email FROM users WHERE id = 1
UNION SELECT username, password FROM admins;
```

# SQLインジェクションの対策

### 1. プレースホルダを使う（バインド変数）

```kotlin
// Kotlin + JDBCの例
val sql = "SELECT * FROM users WHERE username = ? AND password = ?"
val ps = connection.prepareStatement(sql)
ps.setString(1, inputUsername)
ps.setString(2, inputPassword)
val rs = ps.executeQuery()
```

→ プレースホルダを使うことで、ユーザー入力がSQL構文と分離される。

### 2. ORM（Object-Relational Mapping）の使用

```kotlin
// JPAやMyBatisなどのORMフレームワークを使う
userRepository.findByUsernameAndPassword(username, password)
```

→ ほとんどのORMは自動でプレースホルダを使うため、問題ない。
　ただしチーム内できちんとORMを使うようコーディング規約は設けておくこと。
　大抵はこれで対策済ではある。

### 3. 入力バリデーション・サニタイズ

```kotlin
// IDや数字を受け取るときは数値チェックを行う
require(id.matches(Regex("\\d+"))) { "Invalid ID" }
```

→ SQLではなく入力側で「受け付けてよい値」だけを許可することで、リスクを軽減できますが大抵は1, 2で対策済みで不要な場合が多い。

### 4. データベースの権限設定

```sql
-- 最小限の権限だけ与える
CREATE USER 'webuser'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, INSERT ON mydb.* TO 'webuser'@'localhost';
```

→ 万が一攻撃されても、影響範囲を限定できる。

##### 参考サイト

https://www.ipa.go.jp/security/vuln/websecurity/sql.html

##### 追記

この記事はAIで添削しています。
2回目の外部LT振り返りポエム 2025年5月 #QiitaBash

## これは何?

https://increments.connpass.com/event/351227/

こちらでありがたいことに登壇する機会をいただいたのでKPIで振り返りを行う

---

## 前回あげたTry項目

https://qiita.com/sigma_devsecops/items/937dbf5feb3df922090c

> - 練習をもっとする
>     - 資料は1週間前には作る(ここはMarpでもいいかも?)
>     - 友人に聞いてもらう or 録画して見返す
>     - まあ，なんか」「ちょっと」を減らすためにカウントしてn回以下ならOKとか決めてみる
> - Marp以外で図の多さを意識して資料を作る
> - canva試す
> 余裕があれば，聞いている人に挙手せいで質問をしてみる
> 想像の2倍大きな声で話す or マイクの持ち方検討

---

## Keep

- 前日に妻，当日朝に友人と上長に聞いてもらいフィードバックを受けた。
  - そもそも，人に聞いてもらうことに締め切り効果がある
  - 録音して練習もやったが対人間の方が練習になる
  - 第三者目線で作っているつもりが意外とそうでもないことがわかった 
- canvaを試せた
- 挙手を呼びかけた
- 時間通り7分で話せた。(アーカイブでタイム図ると6分50秒とか)

---

## Problem

- 発表資料のバージョン管理ができておらず，古い資料を連携してしまった。ただただ，申し訳ない。
    - canvaでpdfエクスポート→別のやつを連携するミスを犯したのでcanvaのurlを連携でも良かったかも
    - もっと早く資料を完成させるべき
- テンパってしまい，落ち着いて聴衆のほうをあまり見れなかった。

---

## Try

- Marpに回帰してみようと思った。cssちゃんと書けばきれいなスライドになる。
    - canvaでたたきを作ってAI AgentにMarp化してもらうでもよいかも。
- 資料の取り間違いを防ぐために連携前編集時刻をチェックする or MarpにしてGit管理
- ワードセンスを意識する。ちょっと変わった言い回しを使う
- ウェブの人にも話をふってみる
- もっと早めに練習するために，日程を早くから抑えておく。

---

## 感想

- 割と前回の反省は活かせたとは思う。
- Marpでもこんなきれいなスライド作れるんだと驚いた
- 仕事の話をしたほうがウケは良さそうとは思いつつ，SI開発とかってどこまで語っていいのか微妙だし，あまり最新って感じの話題は無い気がする。セキュリティネタだとナレッジの流出とか言われても嫌だしなあ
- 上記を踏まえると，やったお仕事について語れるのが自社サービスの強みなのではと思ったりした。
- Archiveを見返してみても，話しながら考えている感が前回に比べてだいぶへって聞きやすくなった気がして元気が出た。資料取り間違えたのを差し引いても相当改善されていると思う。
- 練習の重要さや人に聞いてもらうことのメリットを感じられた。
- 本番の方がやはり言葉はスラスラ出てくる。人間相手3回，黙読で3回くらいの練習でも聞くに耐えるくらいには喋れるというのは一つの指標にしても良さそう。
- プロットのみにカンペは作ったが見ることはなかった。作ること自体に思考の整理的な意味があるかもしれないが
- 他の方のようにもっとリラックスして堂々と話せるといいなと思った。コンテンツがやってみて良さそう止まりで浅かったのでそこが問題だったのかもしれない。
Windows11の右クリックメニューで .tar.gz を圧縮・展開する方法

.tar.gz ファイルを扱うことが多いが 7-zip などのツールで圧縮・展開すると2段階の操作が必要で手間がかかるので、右クリックメニューに追加してみた。快適。



1. まずはバッチファイルを2つ作り、任意のパスに配置する

    バッチファイルなので文字コードは Shift-Jis, 改行は CRLF にする。 

    * targz圧縮.bat

        ```dosbatch
        @echo on
        
        :: フォルダ名を取得
        for %%A in (%1) do set "FOLDER_NAME=%%~nxA"
        
        :: 親フォルダのフルパスを取得
        for %%A in (%1) do set "PARENT_FOLDER=%%~dpA"
        
        :: 結果を表示（確認用）
        echo フォルダ名: "%FOLDER_NAME%"
        echo 親フォルダのフルパス: "%PARENT_FOLDER%"
        :: 親フォルダへ移動    
        cd %PARENT_FOLDER%
        :: 圧縮
        tar -zcvf "%FOLDER_NAME%.tar.gz" ".\%FOLDER_NAME%"
        
        pause    
        ```

    * targz展開.bat

        ```dosbatch
        @echo on
        tar -zxvf %1
        pause
        ```

1. 個人用のレジストリに登録する

    1. MS-DOSを起動する(管理者権限でなくても可)

        下のコマンドを順番に実行する

        ```dosbatch
        :: バッチファイルのパスの設定(任意のパスに設定する)
        set BAT_PATH1=C:\Users\yourname\script\targz圧縮.bat
        set BAT_PATH2=C:\Users\yourname\script\targz展開.bat

        :: ファイルの右クリックメニューに「tar.gz圧縮」を追加
        reg add "HKCU\Software\Classes\*\shell\tar.gz圧縮" /ve /d "tar.gz圧縮" /f
        reg add "HKCU\Software\Classes\*\shell\tar.gz圧縮\command" /ve /d "\"%BAT_PATH1%\" \"%1\"" /f

        :: フォルダの右クリックメニューに「tar.gz圧縮」を追加
        reg add "HKCU\Software\Classes\Directory\shell\tar.gz圧縮" /ve /d "tar.gz圧縮" /f
        reg add "HKCU\Software\Classes\Directory\shell\tar.gz圧縮\command" /ve /d "\"%BAT_PATH1%\" \"%1\"" /f

        :: ファイルの右クリックメニューに「tar.gz展開」を追加
        reg add "HKCU\Software\Classes\*\shell\tar.gz展開" /ve /d "tar.gz展開" /f
        reg add "HKCU\Software\Classes\*\shell\tar.gz展開\command" /ve /d "\"%BAT_PATH2%\" \"%1\"" /f
        ```

        * 追加したメニューを削除する場合は以下のとおり

        ```
        reg delete "HKCU\Software\Classes\*\shell\tar.gz圧縮" /f
        reg delete "HKCU\Software\Classes\Directory\shell\tar.gz圧縮" /f
        reg delete "HKCU\Software\Classes\*\shell\tar.gz展開" /f
        ```
next.jsとNeonのトランザクション

# 種類
- sql.transaction
- with句
- pool
があるらしい

https://neon.tech/docs/ai/ai-rules-neon-serverless#rules

ずっと下の方見てて、BEGINとか書いてたんだけどうまくいかなかった。

https://neon.tech/postgresql/postgresql-tutorial/postgresql-transaction
業務システム開発で押さえておきたい保守性4原則  

## 1. ハードコードを避ける
### Bad
```php
// 税率が変わるたびに修正が必要
$total = $subTotal * 1.10;
```


### good
```php
// .env に TAX_RATE=0.10
$taxRate = config('constants.tax_rate');
$total   = $subTotal * (1 + $taxRate);
```

- 値が散在すると漏れや不整合の原因になる  
    - 一箇所にまとめる
- **環境変数・設定ファイル・DB** など “コード以外” に逃す  

---

## 2. 設定値の外部化
- 例（Laravel）  
  - `.env`  
    ```
    MAIL_HOST=smtp.example.com
    ```  

  
  - `config/mail.php`  
    
    ```php
    'host' => env('MAIL_HOST'),
    ```  
- ステージング／本番切り替えはファイル差し替えで完結  
- 機密情報は **環境変数＋CI/CD のシークレット管理** が基本  

**ステージング環境**  
   - 本番リリース前に動作確認を行う“リハーサル用サーバー”  
   - コードは本番と同じでも、DB 接続先や API キーなどの **設定値** が異なる  

**本番環境**  
   - 実際にユーザーがアクセスするサーバー  
   - 壊すとサービスが停止する 

**切り替え方法：.env などの設定ファイルを入れ替えるだけ**  
   - 例）Laravel  
     - `staging/.env`（テスト用 DB、テストカードの API キー）  
     - `production/.env`（本番 DB、本番決済の API キー）
   - デプロイ時に **どちらの .env を配置するか決める** だけで、同じコードを安全に動かせる  

> **イメージ**  
> ```
> ├─ app/           (ソースコードは同じ)
> ├─ .env           ← 本番用をコピーして置く
> └─ .env.stg       ← ステージング用を保管
> ```

1. **環境変数とは**  
- OS や実行環境に登録しておく **キー＝値のペア**  
- コード側は `env('API_KEY')` などで読み取る  
- Git に載らないので漏えいしにくい  


2. **CI/CD のシークレット管理**  
- GitHub Actions, GitLab CI などの **「Secrets」** 機能に登録  
- ビルド時に自動で環境変数として注入  
- 開発者は値を見られず、履歴にも残らない  

---

## 3. 命名規則の徹底
```php
// NG
$a = getData($d);

// OK
$customerList = $customerService->fetchAllByBranch($branchId);
```

- 変数・関数・テーブル名は 一貫したルール＋意味の分かる英語
- ルールは README や Contributing ガイドに明文化

これはシステムを作り出したときに最初に注意されたことかもしれない。
CSSを当てるときのクラス名を適当に割り振っていた。

## 4. 共通処理の切り出し

```php
// 3 か所に同じバリデーション
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { ... }

// 共通関数に集約
class Validator
{
    public static function email(string $value): bool
    {
        return filter_var($value, FILTER_VALIDATE_EMAIL);
    }
}

```
- DRY 原則（Don’t Repeat Yourself）
- Laravel なら Form Request や Service クラス、React ならカスタムフックなどに寄せる

2回同じことを書くことは愚行！！


## チェック！！
- 定数・URL・税率などをソースに直書きしていないか
- .env や config/ で設定を管理しているか
- 変数・関数・テーブル名に一貫性があるか
- コピペした同じ処理を共通関数へ統合したか

上記 4 原則を守るだけで、チームの負担を減らせる！！！ようだ！
x86 MOV命令 MOV AL,BLのようなレジスタ間移動の機械語はどう生成される？

## MOVの機械語
MOV AX,BXのようなレジスタ間移動のMOVの機械語は`[オペコード] [ModR/M]`(2バイト)からなります。

### MOV 命令オペコード一覧（Mod=11 / レジスタ間）

| オペコード | オペランド大きさ | 命令形式 | 意味 |
| ----- | -------- | ---- | --- |
| `88 /r` | 8bit | `MOV r/m8, r8` | レジスタ → レジスタ/メモリ（8bit） |
| `8A /r` | 8bit | `MOV r8, r/m8` | レジスタ/メモリ → レジスタ（8bit） |
| `89 /r` | 16bit | `MOV r/m16, r16` | レジスタ → レジスタ/メモリ（16bit） |
| `8B /r` | 16bit | `MOV r16, r/m16` | レジスタ/メモリ → レジスタ（16bit） |

※オペランドが2つともレジスタの場合、2通りのオペコードが存在します。
例えば8bitの場合は下に載せたMod R/M中のreg及びr/mにどちらのレジスタを入れるかによって88と8Aが入れ替わります。

### Mod R/Mの構成

| フィールド | ビット幅 | 説明 |
| ----- | ---- | --- |
| Mod | 2ビット | レジスタ間操作の場合は `11` 固定 |
| reg | 3ビット | レジスタを3ビット値で指定 |
| r/m | 3ビット | レジスタ若しくはメモリを3ビット値で指定 |

(レジスタのビット値は下の表を参照)

#### Mod値

| Mod値 | 意味 | 例 |
| ---- | --- | --- |
| 00 | オフセットなし（※BPは例外） | `[BX+SI]` |
| 01 | 8ビットオフセット | `[BX+SI+5]` |
| 10 | 16ビットオフセット | `[BX+SI+1000]` |
| 11 | レジスタ間移動 | `AX ← BX` |

今回はレジスタ間移動のみに絞って話を進めるため、**Mod=11**で固定です。00,01,10は今回使用しません。

#### レジスタ3ビット値

| レジスタ | ビット幅 | 3ビット値 | バイナリ |
| ---- | ---- | ----- | ---- |
| AL | 8bit（下位） | 000 | 000 |
| CL | 8bit | 001 | 001 |
| DL | 8bit | 010 | 010 |
| BL | 8bit | 011 | 011 |
| AH | 8bit（上位） | 100 | 100 |
| CH | 8bit | 101 | 101 |
| DH | 8bit | 110 | 110 |
| BH | 8bit | 111 | 111 |

## 実際にNASMが生成した機械語

```
ubuntu@ubuntu:~/kaihatsu/demo$ nasm -f bin demo.asm -o demo.bin
ubuntu@ubuntu:~/kaihatsu/demo$ ndisasm -b 16 demo.bin
00000000  88D8              mov al,bl
00000002  88C8              mov al,cl
00000004  88D0              mov al,dl
00000006  88C3              mov bl,al
00000008  88CB              mov bl,cl
0000000A  88D3              mov bl,dl
0000000C  88C1              mov cl,al
0000000E  88D9              mov cl,bl
00000010  88D1              mov cl,dl
00000012  88FC              mov ah,bh
00000014  88EC              mov ah,ch
00000016  88F4              mov ah,dh
00000018  88E7              mov bh,ah
0000001A  88EF              mov bh,ch
0000001C  88F7              mov bh,dh
0000001E  88E5              mov ch,ah
00000020  88FD              mov ch,bh
00000022  88F5              mov ch,dh
```

### `mov al,bl`が何故`88D8`になるのか

1. alもblもレジスタなのでMod=11
2. レジスタ→レジスタへの移動なのでオペコードは88(実際には8Aでも良いのですがそれは下の節で説明します)
3. 3ビット値 AL=000 BL=011
    reg=BL
    r/m =AL
    よって
    11 011 000 となり16進数にするとD8となる。
    オペコードが88の場合は`MOV r/m8, r8`であり、BLからALへ代入すると解釈する。

```
[オペコード]  [Mod][reg][r/m]
   88          11   011  000
               |    |     |
            Mod=11 reg=BL r/m=AL

命令意味: MOV r/m8, r8
          AL ← BL
```

### `mov al,bl`のもう一つの機械語
NASMはオペコードを88として機械語を生成していました。
以下のようにオペコードを8Aにして、regとr/mを逆にすると、`8A C3`（AL ← BL）になります。
```
[オペコード]  [Mod][reg][r/m]
   8A          11   000  011
               |    |     |
            Mod=11 reg=AL r/m=BL

命令意味: MOV r/m8, r8
          AL → BL
```

`88D8`と`8AC3`が等しいことを証明するためにMS-DOSのdebugのe命令を用いて実際に16進数で`88D8`と`8AC3`を書き込み、u命令で逆アセンブルしたものが以下の写真になります。
機械語は違いますがどちらもmov al,blとなっています。
![8957a6d106953a92159f7e63bd493308.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/2fcb36a3-2a5d-48aa-b6b4-b2840296546b.jpeg)

NASM
JavaScriptで日付を「YYYY-MM-DD」形式にフォーマットする

JavaScript で現在の日付を「2024-12-25」のような形式で取得したい場面が多いので、
自分用メモでまとめました。シンプルな日付フォーマット方法です。

## コード例

```javascript
const currentDate = new Date()
  .toLocaleString("ja-JP", {
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  })
  .replace(/\//g, "-");

console.log(currentDate); // 出力例: "2024-12-25"
```

## コードの解説

### 1. 現在日時の取得

```javascript
new Date();
```

現在の日時を取得します。

### 2. 日本のロケールでフォーマット

```javascript
.toLocaleString('ja-JP', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
})
```

- `'ja-JP'`: 日本のロケールを指定
- `year: 'numeric'`: 年を 4 桁で表示（例：2024）
- `month: '2-digit'`: 月を 2 桁で表示（例：01, 12）
- `day: '2-digit'`: 日を 2 桁で表示（例：01, 25）

この時点では「2024/12/25」のような形式になります。

### 3. スラッシュをハイフンに置換

```javascript
.replace(/\//g, '-')
```

スラッシュ（/）をハイフン（-）に置換して、最終的に「2024-12-25」形式にします。

## 実用的な使用例

### ファイル名生成

```javascript
const filename = `report_${currentDate}.csv`;
// 結果: "report_2024-12-25.csv"
```

### ログ出力

```javascript
console.log(`[${currentDate}] 処理が開始されました`);
// 結果: "[2024-12-25] 処理が開始されました"
```

### API 通信

```javascript
const response = await fetch(`/api/data?date=${currentDate}`);
```

### フォーム入力のデフォルト値

```javascript
<input type="date" defaultValue={currentDate} />
```

## 他の方法との比較

### ISO 文字列を使用する方法

```javascript
const currentDate = new Date().toISOString().split("T")[0];
// 結果: "2024-12-25"
```

こちらの方法もシンプルですが、タイムゾーンの影響を受ける可能性があります。

### 手動でフォーマットする方法

```javascript
const date = new Date();
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const currentDate = `${year}-${month}-${day}`;
```

より細かい制御が可能ですが、コードが長くなります。

## まとめ

`toLocaleString()`を使用した方法は、読みやすく、タイムゾーンの考慮もされているため、多くの場面で安全に使用できます。

日付フォーマットは頻繁に使用する処理なので、このタイミングで整理しようと思い、
claudeさんに聞きながらメモしました。
@react-threeを使用してプロジェクトのお墓サービスを作りました

# @react-threeを使用してプロジェクトのお墓サービスを作りました
停止したサービスややる気を消失して途中で実装を中止したプロジェクトの供養場所みたいなのがほしくて実装しました。

ポートフォリオの小ネタの一つに使っていただけたら幸いです。

https://ripro.vercel.app

## 画面
![top.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865740/89a0f93d-f5c9-4579-9969-58996a9f5cab.jpeg)


## 主な技術スタック
無料枠で運営しています。

- T3
  - Next.js・React
  - TailwindCSS
  - NextAuth
  - Drizzle
  - tRPC
- shadcn/ui
- three.js
- @react-three/drei
- @react-three/fiber
- Vercel
- Neon
- Upstash

## 機能
### ログイン
NextAuthを使用しています。GithubプロバイダーによるOAuth認証を行います。

### プロジェクトの作成
左側に作成フォームがあるのでそちらから入力します。セレクトバーにはパブリックリポジトリが表示されますので、そこから終了したサービスなどを選択してください。選択すると自動でリポジトリ名、リポジトリの説明、URLが入力されます。

![create.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865740/bf2c02a9-1335-4d8c-98d3-4fb9f0f2a252.jpeg)


### AI解析機能
初期画面は以下のようになっていて、中央のボタンをクリックすると解析が開始されます。1日5回までの回数制限を設けています。先日話題になった`gitdiagram`のようにはいきませんが、ある程度のアーキテクチャ図を作成してくれます。

![default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865740/163c5cbf-2dc5-4257-8f61-7f65242360ef.png)


作成したアーキテクチャ図は以下のように表示されます。保存ボタンをクリックしない限り、保存はされませんので注意してください。アーキテクチャ図は拡大・縮小・移動が可能なので多少大きくても見やすいように実装を心がけています。

![analyze.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3865740/91c02b00-1ff9-451a-9db7-4eda876500b1.gif)


## 今後の展望
あまり発展の可能性がないサービスだと思っていますが、課金システム等導入してOpenAIのAPIサービスが利用できるなどの特典がつけれるようにしたいと思っています。

## 最後に
改善点、感想などをお教え頂ければ幸いです。よろしくお願いいたします。
非線形ロジスティック微分方程式と逐次線形化→離散化→デジタル伝達関数



## ✅ 1. 非線形ロジスティック微分方程式

$$
\frac{dN}{dt} = r N(t) \left(1 - \frac{N(t)}{K} \right)
$$

* $N(t)$：個体数／資源量など
* $r$：成長率（gain）
* $K$：環境収容力（feedback）

---

## ✅ 2. 任意点 $N_0$ における逐次線形化

偏差変数を導入：

$$
x(t) := N(t) - N_0
$$

テイラー展開による1次近似：

$$
\frac{dN}{dt} \approx f(N_0) + f'(N_0)(N - N_0)
$$

ここで：

* $f(N) = rN\left(1 - \frac{N}{K}\right)$
* $f'(N) = r\left(1 - \frac{2N}{K}\right)$

したがって：

$$
\frac{dx}{dt} = a x(t), \quad \text{where } a := r\left(1 - \frac{2N_0}{K}\right)
$$

---

## ✅ 3. 時間離散化（オイラー法）

刻み幅 $\Delta t$ で離散化：

$$
x_{k+1} = x_k + \Delta t \cdot a x_k = (1 + a \Delta t)x_k
$$

定義：

$$
A_d := 1 + a \Delta t
$$

差分方程式：

$$
x_{k+1} = A_d x_k
$$

---

## ✅ 4. Z変換によるデジタル伝達関数

Z変換適用：

$$
z X(z) = A_d X(z)
\quad \Rightarrow \quad
(z - A_d) X(z) = 0
$$

よって、入力 $U(z) = X(z)$ とすれば：

$$
G(z) = \frac{X(z)}{U(z)} = \frac{A_d}{z - A_d}
$$

---

## ✅ 最終形式（デジタル伝達関数）

$$
G(z) = \frac{A_d}{z - A_d}, \quad \text{with } A_d = 1 + r \left(1 - \frac{2N_0}{K} \right)\Delta t
$$

---

## ✅ まとめ表

| 段階     | 式                                                               |
| ------ | --------------------------------------------------------------- |
| 非線形モデル | $\frac{dN}{dt} = r N \left(1 - \frac{N}{K} \right)$             |
| 線形化    | $\frac{dx}{dt} = a x$, $a = r \left(1 - \frac{2N_0}{K} \right)$ |
| 離散化    | $x_{k+1} = A_d x_k$, $A_d = 1 + a \Delta t$                     |
| Z変換    | $G(z) = \frac{A_d}{z - A_d}$                                    |

---
【Homebrew】インストール可能なcaskの検索方法

## インストール可能なcaskを検索

インストール可能なcaskを検索するには以下のコマンドを使用します。

```terminal
brew search --casks cask名
```

```terminal
$ brew search --casks ''
==> Casks
0-ad                                                            font-times-newer-roman
010-editor                                                      font-timmana
115                                                             font-tinos
115browser                                                      font-tinos-nerd-font
1clipboard                                                      font-tiny5
```
A proof of the Collatz conjecture

## A proof supporting the Collatz conjecture

##### として　Qiita で投稿しました。今までネット上では余り見られない偶数による計算です。コラッツ演算を偶数の割り算の回数を変数として、多変数の一般式として定義しました。
#### 高校生の数学の知識で理解できる程度です。間違いが無いか　解らないので大学以上の数学科を卒業した方に評価してもらいたくて投稿しました。何もお礼は出来ませんがコメントを頂ければ感謝します。
Amazon Bedrockを使ったAPI作成ハンズオンを主催して得た経験と反省

社内でAmazon Bedrockを使用したAPIを作成するというオリジナルのハンズオンをやってみて得た経験や反省についてまとめた。

# きっかけ
AWS認定をたくさん取ったは良いものの、仕事としては企画チックなことが多くあまり実際のサービスを触れずにモヤモヤしていた。
なかなか手が動かす機会が仕事ではないため、社内の技術系有志活動に参加し色んなハンズオンやLTに参加する中で、自分でAWSハンズオンを企画することで手も動かせてアウトプットにもなるのではないかと思い、今回実施してみた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272113/a158d6fd-b0dc-4edc-a996-769198ae714f.png)


# 企画と準備
まずはどんなハンズオンにするか検討した。世間的、社内的に関心の高い生成AIを使って、かつ、AWSの便利さや手軽さを体験出来て、動いていることが分かりやすいものということで、サーバレスサービスを組み合わせたAPIという選択をした。

内容がざっくりと決まったので、自分でAPIを作成しながらハンズオンの資料を作成した。
作成した際の記事は[こちら](https://qiita.com/ohway_death/items/4dd3aa45a70ed29b9e00)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272113/5ba5a4c5-b9f8-4bc1-b33d-c79b769c3725.png)


今回はAWSやプログラムもあまり書いたことないみたいな方でも参加できるようにコードの作成についてはハンズオンに含めず、あらかじめこちらで作成しておいたコードをお渡ししてプロンプトだけ修正してもらう形をとった。

募集の際は参加人数の制限をした。これはハンズオン中に上手く行かないことがあった場合にフォローできるのが私しかいないというのと、私個人の環境を使っているためあまり人数が多すぎるとIAMユーザーの管理やリソースの管理、コストがかかってしまいそうだったという理由で15人という比較的少ない人数で募集した。

また、事前に一度有志団体のメンバーに対して当日と同じ流れでハンズオンを実施した。これはそもそも時間内にハンズオンが収まるかどうかと資料や手順に分かりにくいところがないかを確かめるためである。正直この事前の実施はかなり重要だと感じた。事前の実施によって改善点がかなり多く出たため、よりよいハンズオンにつながったと思う。

出た改善点としては以下の通り。
- 資料の誤字・脱字
- 手順の抜け漏れ
- IAMポリシーの抜け漏れ
- 参加者の進捗を確認するポイント

# ハンズオン当日
最終的に10人の方が参加してくださり、更にその方々の熱量が高くハンズオン中もたくさんの質問がもらえた。
質問に関してはハンズオンの内容そのものというよりは、「こういう場合はどうするのか」的なハンズオンで使っているサービスに関連した質問が多かった。

共有画面の内、半分は資料を、もう半分は実際の画面を出しながらハンズオンを進めた。私自身も参加者に配布したIAMユーザーと同じものを使いながら進めることで、操作が分かりやすくなるように心がけた。
実施中はスライドにここまで出来たら挙手という表示を出すことで、参加者同士の足並みをそろえながら進められた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272113/dde36c64-905f-4730-81c0-5c1cfaf281d6.png)

ただ、Lambdaのテストの際に参加者全員で一斉にテストを行ったためかToo Many Requestsが出てしまうというトラブルがあった。ここに関しては最終的に順番に1人ずつテストを実施することで解決した。その後の実際にAPIを叩くところでも数人ずつで実施して乗り越えた。これは今後どのようにすればいいか考えないといけない。

# ハンズオン後
ハンズオン後、真っ先に配布していたIAMユーザーの削除を行った。たくさん使われると私の財布が空になるため、少しだけ遊んでもらえるようにハンズオン後1時間は有効にしておいて、その後すぐに削除した。15のIAMユーザーのパスワード変更をコンソールで実施したが、めちゃめちゃめんどくさかったのでここは今後CLIスクリプトで出来るようにしたい。

また、アンケートと当日に頂いた質問に関する回答の配布を行った。アンケートでは開催時間やハンズオンの良かった点・悪かった点、今後開催してほしい勉強会の内容について記載してもらっている。

# かかった費用
今回、10人中ほとんど全員が私の環境でハンズオンをしていたが、それでもかかった費用はわずか0.04ドル、およそ数円ほどだった。普段そんなに利用していないので無料枠もあったからだと思うが、にしても費用がかからな過ぎていて驚いた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272113/93f3f7f5-76c1-4a77-8cc5-7976b130b9be.png)


# やってみた感想
今回初めてハンズオンを開催してみて、思っていた以上に得られるものが多かった。
ハンズオンの資料を作る過程で手も動かすことができるだけでなく、当日もらった質問への返答を考えることでより自分のAWSへの理解が深まったと思う。
また、この当日に頂いた質問は恐らく仕事をする上でも顧客からもらう質問に近いものなのではないかと思い、仕事でも役立ちそうな気がしている

反省点としては、募集の際に以下の文章のみで募集していたが、ハンズオンを終えた後にこんなものが今回作れるとは思っておらず驚いたという感想をいただき、ハンズオンで何が作れるのかをイメージ図や実際の動作画面を提供したほうが、親切だったのかなと感じた。

あとは今回かなり細かく足並みを揃えることを意識したが、ちょっと多すぎた気もしている。これは今後もハンズオンをやって感覚をつかむしかない。

# 次の野望
アンケートにおいてやはり機械学習系の希望が多かったので、何か機械学習系のサービスを使って何か作れないかと検討している。案としては
- Lexを使ったチャットボットの作成
- TranslateやPollyを使った翻訳＆発話システム
などを検討中。

個人的にチャットボット開発に興味があるのでLexを触ってみたい感じはある。
なんせ早めにまた勉強会を開催したい。