OmniAICreator/Qiita-1.07M huggingface dataset:
Goのテーブル駆動テスト入門

Go言語において、table-driven test（テーブル駆動テスト）は一般的で推奨されているテスト手法です。

このスタイルは「データとロジックの分離」を重視しており、テストコードをより簡潔かつ保守しやすくします。

特に複数の入力/出力のテストケースを扱う場面に適しています。

## なぜ Table-Driven Test を使うのか？

同じ関数に対して複数のケースをテストする場合、

各ケースを手動で `t.Run(...)` で書くと、コードが冗長になり、保守が困難になります。

table-driven テストを使うことで、以下のような利点があります：

- テストケースを集中して管理できる
- ループで自動的にテストを実行し、重複コードを回避できる
- 可読性と一貫性が向上する

## 起源と提唱者

table-driven test は特定の開発者が考案したデザインパターンではなく、Go のコア開発者である Andrew Gerrand によって、講演やブログなどで広く推奨された実践的な手法です。

> 「Goでは、私たちはしばしばテーブル駆動のテストを使用します。これは、コードを重複させずに複数のシナリオをテストする良い方法です。」  
> — Andrew Gerrand, Go 開発者アドボケイト

このスタイルは、`strings`, `strconv`, `time` などの Go 標準ライブラリのテストファイルにも見られ、idiomatic Go（慣用的なGo）として定着しています。

## 実装例：通知タイプの有効性チェック

以下は、入力された通知タイプが "email"、"push"、"sms" のいずれかであるかを検証するシンプルな例です。

### テスト対象コード（notification.go）

```go
package notification

func IsValidNotificationType(t string) bool {
    switch t {
    case "email", "push", "sms":
        return true
    default:
        return false
    }
}
```

### テストコード（notification_test.go）

```go
package notification

import "testing"

func TestIsValidNotificationType(t *testing.T) {
    tests := []struct {
        name     string
        input    string
        expected bool
    }{
        {"valid_email", "email", true},
        {"valid_push", "push", true},
        {"valid_sms", "sms", true},
        {"invalid_type", "fax", false},
        {"empty_string", "", false},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            actual := IsValidNotificationType(tt.input)
            if actual != tt.expected {
                t.Errorf("IsValidNotificationType(%q) = %v; want %v", tt.input, actual, tt.expected)
            }
        })
    }
}
```

## 解説のポイント

- `tests := []struct{...}`：複数のテストデータを定義
- `t.Run(tt.name, ...)`：各テストケースを個別に実行し、名前で識別（デバッグしやすくなる）
- テストが失敗した場合、`t.Errorf` によって詳細な情報が出力される

## 応用例

table-driven テストは以下のような場面でも有効です：

- 境界値テストなど、複数の入力条件の組み合わせ
- 複数のサブ関数に共通するロジックの検証
- ユニットテストや統合テストにおけるデータの組み合わせ処理

## まとめ

Go における table-driven テストスタイルはシンプルで読みやすく、保守もしやすいため、ユニットテストを書く際のベストプラクティスの一つです。複数の条件をカバーする必要がある場合、このスタイルをぜひ検討してください。

## 参考文献

- Go Wiki - ["Table-Driven Tests"](https://go.dev/wiki/TableDrivenTests)
- Andrew Gerrand, ["Go testing techniques"](https://talks.golang.org/2014/testing.slide)
【React】contextAPI


## はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
現在、Udemy の講座「React に入門した人のためのもっと React が楽しくなるステップアップコース完全版」で React の学習を進めています。
その中で出てきた contentAPI について記事を書こうと思います。
React で搭載されているグローバル state を管理するために使用できるライブラリです。

---

## 1. Context API とは？

React の Context API は、コンポーネント間で「データ」や「状態」を共有するための仕組みです。通常、親から子へ props でデータを渡しますが、コンポーネントが多くなってくると、props のバケツリレー（prop drilling）でコードが煩雑になります。Context API を使えば、ツリー内のどこからでも必要なデータにアクセスできるようになります。

---

## 2. どんな時に使う？

- グローバルなテーマ（ダークモード・ライトモードの切り替え）
- ログインユーザー情報の管理
- 多言語対応（i18n）
- アプリ全体で使う設定値

など、複数コンポーネントで共通して使いたい情報を扱うときに便利です。

---

## 3. 基本的な使い方

Context API の基本的な流れは次の 3 ステップです。

1. **Context の作成**
2. **Provider で値を渡す**
3. **Consumer または useContext で値を取得する**

### 3-1. Context の作成

```jsx
import { createContext } from 'react';

const MyContext = createContext(defaultValue);
```

### 3-2. Provider で値を渡す

```jsx
<MyContext.Provider value={value}>
  <YourComponent />
</MyContext.Provider>
```

### 3-3. useContext で値を取得する（React v16.8 以降）

```jsx
import { useContext } from 'react';

const value = useContext(MyContext);
```

---

## 4. サンプルコード

### 例：テーマ切り替え

```jsx
// ThemeContext.js
import React, { createContext, useState, useContext } from 'react';

const ThemeContext = createContext();

export const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState('light');
  const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
};

export const useTheme = () => useContext(ThemeContext);
```

```jsx
// App.js
import React from 'react';
import { ThemeProvider, useTheme } from './ThemeContext';

const ThemeSwitcher = () => {
  const { theme, toggleTheme } = useTheme();
  return (
    <button onClick={toggleTheme}>
      現在のテーマ: {theme}（クリックで切り替え）
    </button>
  );
};

const App = () => (
  <ThemeProvider>
    <ThemeSwitcher />
  </ThemeProvider>
);

export default App;
```

---

## 5. Context API の注意点

- **再レンダリングに注意**: Context の値が変わると、その Context を使っているすべてのコンポーネントが再レンダリングされます。大きな値や頻繁に変わる値を Context に入れるとパフォーマンスに影響する場合があります。
- **必要以上に使わない**: すべての状態を Context で管理すると逆に管理が複雑になることもあるので、基本は props や state、必要な場合だけ Context を使いましょう。

---

## 6. Context API と他の状態管理ライブラリの違い

Context API は「グローバル状態共有」の仕組みですが、Redux や Zustand のような高度な状態管理のための機能は持っていません。
中～大規模アプリや複雑な状態遷移を扱う場合は、これらのライブラリと併用することも多いです。
個人的には、ポートフォリオには煩雑さや再レンダリング等のことを踏まえると次の記事で紹介する Zustand を搭載する予定です。

---

## 7. まとめ

- Context API は、React でグローバルに値を共有するシンプルな仕組み
- props のバケツリレーを避けたいときや、複数コンポーネントで同じ情報を扱うときに便利
- 頻繁に変わるデータや複雑なロジックには他の状態管理ライブラリを検討

## 参考文献

https://www.udemy.com/course/react_stepup/?couponCode=CP130525JP
WordPressのサイトヘルス画面で推奨モジュールが存在しないと怒られる

WordPressのサイトヘルス画面で推奨モジュールが存在しないと怒られました。

詳細は以下の通り。
```
1つ以上の推奨モジュールが存在しません
パフォーマンス
PHP モジュールはサイトの稼働に必要なほとんどのタスクをサーバー上で実行します。変更はサーバー管理者が実施する必要があります。

WordPress ホスティングチームでは、こうした推奨されていたり必須とされていたりするモジュールのリストをチームのハンドブック (新しいタブで開く)でメンテナンスしています。

警告 オプションのモジュール zip がインストールされていないか、無効化されています。
警告 オプションのモジュール intl がインストールされていないか、無効化されています。
```
PHPをソースからインストールしてるの構成コマンドのパラメータを確認したら、確かにzipとintlを有効化していなかった。

なので--with-zip、--enable-intlを追加して、再度configureを実行する。

```
./configure \
--prefix=/usr/local/ap/php \
--enable-fpm \
--with-config-file-path=/usr/local/ap/php/etc \
--enable-libgcc \
--with-openssl \
--with-zlib \
--with-zlib-dir=/usr \
--enable-gd \
--with-freetype \
--with-jpeg \
--with-xpm \
--with-webp \
--enable-bcmath \
--with-bz2 \
--enable-calendar \
--with-curl \
--enable-dba=shared \
--enable-exif \
--with-curl \
--enable-gd-jis-conv \
--with-gettext \
--enable-mbstring \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--enable-pcntl \
--with-readline \
--enable-soap \
--enable-sockets \
--with-xsl \
--with-imap \
--with-imap-ssl \
--with-libdir=lib64 \
--with-kerberos \
--with-zip \
--enable-intl \
--enable-opcache \
--enable-shared
```
そうしたらicu絡みでライブラリが足りないと怒られる。
```
checking for icu-uc >= 50.1 icu-io icu-i18n... no
configure: error: Package requirements (icu-uc >= 50.1 icu-io icu-i18n) were not met:

Package 'icu-uc', required by 'virtual:world', not found
Package 'icu-io', required by 'virtual:world', not found
Package 'icu-i18n', required by 'virtual:world', not found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables ICU_CFLAGS
and ICU_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
```
なので、不足しているパッケージをインストールする。
```
dnf install libicu-devel
```
気を取り直して再度configureを再度実行すると無事終了したのでコンパイルする。
```
make all -j 3
```
コンパイルが無事終了したので、上書きインストールしてphp-fpmを再起動する。
```
make install
systemctl stop php-fpm
systemctl start php-fpm
```

再びWordPressのサイトヘルス画面に戻ると、「推奨モジュールが存在しない」エラーは消えました。

何かの参考になれば幸いです。
Pythonでスウェーデン語翻訳機（音声再生可）をGUI付きで自作してみた話

## 作ろうと思った理由
日常生活でスウェーデン語を使う場面があり、流通している翻訳アプリを使ってみたところ…
「翻訳が微妙におかしい」
「音声読み上げがロボット感満載で聞き取りにくい」
と感じたため、「自分で作ってみようかな？」と思い、Pythonで自作してみました！

## 使用ライブラリ（すべてPython）
・GUI構築：tkinter（標準ライブラリ）
・翻訳機能：deep-translator / googletrans（検証済）
・音声読み上げ：gTTS（Google Text to Speech）
・音声再生：playsound（※1.2.2が安定）

## 事前インストール
```
pip install gtts playsound==1.2.2 deep-translator
```
※playsound はバージョン指定しないとエラーが出ることがあるので注意！

## 🔥 Step1：まずはGUIを作る（見た目だけ）
```
import tkinter as tk

root = tk.Tk()
root.title("翻訳ツール（見た目だけ）")
root.geometry("400x300")

tk.Label(root, text="日本語入力").pack()
input_text = tk.Text(root, height=5)
input_text.pack()

tk.Button(root, text="翻訳", command=lambda: print("ボタン押された！")).pack()

tk.Label(root, text="スウェーデン語出力").pack()
output_text = tk.Text(root, height=5)
output_text.pack()

root.mainloop()
```

### 発生したエラー：
```
ModuleNotFoundError: No module named '_tkinter'
```
MacでPythonをpyenvで入れた場合、tkinterが含まれないことがあるため、
最終的に pyenv をやめて Homebrew で Python 3.13.3 を入れ直して解決しました。

## 🔥 Step2：翻訳機能を試す（deep-translator）
```
from deep_translator import GoogleTranslator

result = GoogleTranslator(source='ja', target='sv').translate("おはよう")
print(result)
```
これはスムーズに動作確認できました！

## 🔥 Step3：GUIと翻訳機能をドッキング！
```
import tkinter as tk
from tkinter import messagebox
from deep_translator import GoogleTranslator

def translate_text():
    japanese = input_text.get("1.0", "end").strip()
    if not japanese:
        messagebox.showwarning("入力エラー", "日本語のテキストを入力してね！")
        return
    try:
        swedish = GoogleTranslator(source='ja', target='sv').translate(japanese)
        output_text.delete("1.0", "end")
        output_text.insert("end", swedish)
    except Exception as e:
        messagebox.showerror("翻訳エラー", str(e))

root = tk.Tk()
root.title("スウェーデン語翻訳ツール")
root.geometry("500x400")

tk.Label(root, text="日本語入力").pack(pady=(10, 0))
input_text = tk.Text(root, height=5)
input_text.pack(padx=10, fill="x")

tk.Button(root, text="翻訳する", command=translate_text).pack(pady=10)

tk.Label(root, text="スウェーデン語出力").pack()
output_text = tk.Text(root, height=5)
output_text.pack(padx=10, fill="x")

root.mainloop()
```

## 🔥 Step4：音声読み上げを追加！
### ライブラリ追加：
```
pip install gTTS playsound==1.2.2 pyobjc
```
・gTTS：GoogleのTTS APIを使って音声ファイルを生成
・playsound：mp3を再生（1.2.2が安定）
・pyobjc：MacでAppKit関連のモジュール不足エラーを回避

### エラー対応：
```
No module named 'AppKit'
```
→ pyobjc のインストールで解決！

## 💡 デザイン調整も少しだけ
tkinterではボタンを丸くするのが難しいので、flat ＋ 背景色 でカスタマイズ感を出しました。色は水色ベースにしてみました。

## 👉 GitHubリポジトリ
試行錯誤を繰り返し最終的に完成したのはこちらです。
https://github.com/Hira-Mao/translator_gui

## 📝 まとめ＆今後の課題
翻訳＋読み上げができるGUIツールが作れて達成感あり。
pyenv環境ではGUI系でトラブルが多いと学んだ。
今後は出力の保存、言語切替対応、Webアプリ化も余裕があればいつか挑戦してみたい。
パロアルトネットワークスのスキャナーから除外してもらう

ログを眺めていたら、下記ログが記録されていました。
```
198.235.24.165 - - [24/Dec/2024:00:00:23 +0900] "GET / HTTP/1.1" 200 73825 "-" "Expanse, a Palo Alto Networks company, searches across the global IPv4 space multiple times per day to identify customers&#39; presences on the Internet. If you would like to be excluded from our scans, please send IP addresses/domains to: scaninfo@paloaltonetworks.com"
```
どうもパロアルトネットワークスのスキャナーによるアクセスのようで、除外して欲しければメールにて連絡せよとのこと。

なので、下記文面でscaninfo@paloaltonetworks.comへ件名「execlude IP and Domain」でメールを送ってみました。
```
Please execlude from scan. follow IP/Domain
133.242.180.11
rgz95.com
```
サーバの実IPとブログのドメイン名を指定して、これらを除外して欲しい旨をメールをしたところ、6日後に先方から連絡が下記の通りありました。
```
Thank you for reaching out. Cortex Xpanse from Palo Alto Networks, takes an outside-in view of network security and asset management. As part of our technology, Xpanse performs global internet scans to discover internet assets for customers. Searches are done across all of IPv4 multiple times per day, looking for new assets and risks to notify customers about.

We've added 133.242.180.11 and rgz95.com to our excludelist. It can take up to a week for the system to update excluded ranges and domains, but once they propagate you will stop seeing connections from our scanners. If you do still see activity after a week from our ranges (35.203.210.0/24, 35.203.211.0/24, 162.216.149.0/24, 162.216.150.0/24, 198.235.24.0/24, 205.210.31.0/24, 147.185.132.0/24,147.185.133.0/24), please reach out again with the time you observed scanning activity, and we'll troubleshoot.

On Wed, Dec 25, 2024 at 5:21 AM ***@********** wrote:
>Please execlude from scan. follow IP/Domain
>
>133.242.180.11
>rgz95.com
```
除外したので1週間ほど様子を見て欲しいこと、スキャナーのIPアドレスを示すので再度これらからのアクセスがあったら、トラブルシュートを開始する旨が記載されています。

とりあえずは、除外してもらえたので、めでたしめでたし～🎵
【RHELでも同様】Linuxでホスト名を変更する【hostnamectlの使い方】

あんまりない事かと思いますが、ホスト名の変更って直接/etc/hostnameを編集していますか？
それでも誤りではないのですが、/etc/hostnameを変更してシステムにそれを反映させるために再起動って手間をかけてませんか？
そんな人にお勧めのコマンドがあります。

```
hostnamectl set-hostname ホスト名
```

ちなみにホスト名は3種類あります。
上記コマンドを実行すると、これら3個のホスト名全てが更新されます。

static /etc/hostnameに記述されるホスト名
transient カーネルによって保持される一時的なホスト名
pretty 自由形式のホスト名

変更したいホスト名を指定するときは以下のようにします。
```
hostnamectl set-hostname ホスト名 -- pretty or --static or --transient
```
ちなみにリモートホストのホスト名を変更する場合は以下のようにします。
この手を使う時はSSHでログインできることが前提となるため注意が必要です。
```
hostnamectl --host=user@host1.example.com set-hostname ホスト名
```
上記いずれかの方法でホスト名を変更したら、hostnameコマンドでホスト名が変更されているか確認しましょう。
もしホスト名が変更されていない時は、systemctl restart systemd-hostnamed コマンドを実行して systemd-hostnamed を再起動しシステムに反映させます。

 

以上、異常に忘れっぽい自分用のメモでした。
SSHが頻繁に切断されるので設定を見直した

NATの絡みかわからないけど、頻繁に切断されてTeraTERMが落ちるのでサーバ側の設定を見直してみた。

元からTCPKeepAliveは有効にしていたけど、これだけでは駄目っぽい。
```
TCPKeepAlive yes
```
色々調べた結果、下記項目を設定する事で、切断されることがなくなった。
```
ClientAliveInterval 60
ClientAliveCountMax 3
```
ClientAliveInterval、ClientAliveCountMaxを設定する事で、サーバからクライアント側へ定期的パケットが飛ぶようになり、これで接続が保持できるようになる模様。

ちなみに上記設定は、60秒間隔でパケットを投げて3回連続して失敗したらサーバ側から接続を切断すると言うもの。

これで安心して長いコンパイル処理を流せるようになりました。
Raspberry Pi 5でODEを動かす

Raspberry Pi OSで動作させる前提です．

## Raspberry Pi 5にOSをインストール，起動

1. 別のPCを用意し，そのPCでRaspberry Pi OSのイメージを作成しておく
2. microSDカードにイメージを移し，microSDカードをRaspberry Piに挿入する
3. Raspberry Pi 5を起動し，OSが立ち上がったことを確認する

## 必須ライブラリのインストール

```bash
sudo apt update
sudo apt upgrade -y
sudo apt install -y git build-essential cmake libx11-dev libxi-dev libxmu-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev
```

## ODEのインストール・ビルド

```bash
git clone https://bitbucket.org/odedevs/ode.git
cd ode
mkdir myBuild
cd myBuild
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_DEMOS=ON -DCMAKE_POLICY_VERSION_MINIMUM=3.5
make -j$(nproc)
sudo make install
```

## デモ

```bash
./demo_basket
```

他にも多数のデモが動作します．

## マニュアル引用元
Russell L. Smith, Open Dynamics Engine, [Source](https://ode.org/wiki/index.php/Manual), 2001
ApacheのRewriteでNOT条件を使用したい場合

Let's Encryptの.well-known、アドセンスのads.txtにはアクセスを許可して、それ以外は別サイトにリダイレクトしたい時ってありませんか？

 

良くあるのは、.well-knownディレクトリ内へのアクセスはそのまま通して、それ以外はリダイレクトしたいって場合です。

 

そんな時にはRewriteのNOT条件を使います。通常の条件は、パターンにマッチすればリダイレクトとなりますが、NOT条件の場合はパターンにマッチするとリダイレクトしないとなります。

と言うわけで、論より証拠、実際の例を見ていきましょう。
## .well-knownのみアクセスを許可して、それ以外は別サイトにリダイレクトする場合
```
RewriteEngine On
RewriteCond %{REQUEST_URI} !/^\.well-known
RewriteRule ^(.*)$ https://rgz95.com%{REQUEST_URI} [R=301,L]
```
## ads.txtのみアクセスを許可して、それ以外は別サイトにリダイレクトする場合
```
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/ads\.txt
RewriteRule ^(.*)$ https://rgz95.com%{REQUEST_URI} [R=301,L]
```
## .well-known・ads.txtのみアクセスを許可して、それ以外は別サイトにリダイレクトする場合
```
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/\.well-known
RewriteCond %{REQUEST_URI} !^/ads\.txt
RewriteRule .* https://rgz95.com%{REQUEST_URI} [R=301,L]
```
## まとめ
Rewriteでは条件の先頭に「!」をつけることでNOT条件になります。

「!」が先頭につかない通常の条件ではパターンにマッチすればRewriteRule実行と言う条件になりますので、逆の意味になります。「!」がついた場合はパターンにマッチしたらRewriteRuleを実行しないという流れになります。

何かの参考になれば幸いです。
[学習備忘録AtCoder C++] EX15- EX17 2025.5.16


## EX15 なぜかWAとなった。テストケースは合ってたのに
``` original.cpp
#include <bits/stdc++.h>
using namespace std;
 
// 1人のテストの点数を表す配列から合計点を計算して返す関数
// 引数 scores: scores.at(i)にi番目のテストの点数が入っている
// 返り値: 1人のテストの合計点
int sum(vector<int> scores) {
  // ここにプログラムを追記
  int length = scores.size();
  int total = 0;
  for (int i = 0; i < length; i++){
    total += scores[i];
  }
  return total;
}
 
// 3人の合計点からプレゼントの予算を計算して出力する関数
// 引数 sum_a: A君のテストの合計点
// 引数 sum_b: B君のテストの合計点
// 引数 sum_c: C君のテストの合計点
// 返り値: なし
void output(int sum_a, int sum_b, int sum_c) {
  // ここにプログラムを追記
  cout << sum_a * sum_b * sum_c;
  return;
}
 
// -------------------
// ここから先は変更しない
// -------------------
 
// N個の入力を受け取って配列に入れて返す関数
// 引数 N: 入力を受け取る個数
// 返り値: 受け取ったN個の入力の配列
vector<int> input(int N) {
  vector<int> vec(N);
  for (int i = 0; i < N; i++) {
    cin >> vec.at(i);
  }
  return vec;
}
 
int main() {
  // 科目の数Nを受け取る
  int N;
  cin >> N;
 
  // それぞれのテストの点数を受け取る
  vector<int> A = input(N);
  vector<int> B = input(N);
  vector<int> C = input(N);
 
  // それぞれの合計点を計算
  int sum_A = sum(A);
  int sum_B = sum(B);
  int sum_C = sum(C);
 
  // プレゼントの予算を出力
  output(sum_A, sum_B, sum_C);
}
```
``` answer.cpp
#include <bits/stdc++.h>
using namespace std;
 
// 1人のテストの点数を表す配列から合計点を計算して返す関数
// 引数 scores: scores.at(i)にi番目のテストの点数が入っている
// 返り値: 1人のテストの合計点
int sum(vector<int> scores) {
  int s = 0;
  for (int i = 0; i < scores.size(); i++) {
    s += scores.at(i);
  }
  return s;
}
 
// 3人の合計点からプレゼントの予算を計算して出力する関数
// 引数 sum_a: A君のテストの合計点
// 引数 sum_b: B君のテストの合計点
// 引数 sum_c: C君のテストの合計点
// 返り値: なし
void output(int sum_a, int sum_b, int sum_c) {
  cout << sum_a * sum_b * sum_c << endl;
}
 
// -------------------
// ここから先は変更しない
// -------------------
 
// N個の入力を受け取って配列に入れて返す関数
// 引数 N: 入力を受け取る個数
// 返り値: 受け取ったN個の入力の配列
vector<int> input(int N) {
  vector<int> vec(N);
  for (int i = 0; i < N; i++) {
    cin >> vec.at(i);
  }
  return vec;
}
 
int main() {
  // 科目の数Nを受け取る
  int N;
  cin >> N;
 
  // それぞれのテストの点数を受け取る
  vector<int> A = input(N);
  vector<int> B = input(N);
  vector<int> C = input(N);
 
  // それぞれの合計点を計算
  int sum_A = sum(A);
  int sum_B = sum(B);
  int sum_C = sum(C);
 
  // プレゼントの予算を出力
  output(sum_A, sum_B, sum_C);
}
```
何が違うんだろう？

## EX16 
初めてbool型を使った

## EX17
配列の複数宣言の書き方
``` example.cpp
vector<int> A(N), B(N);
// これで一気に二つ作れる。わざわざ
vector<int> A(N);
ventor<int> B(N);
// と書く必要がない。
Clineって何？を図で解説してみた。

## はじめに
こんにちは。最近、AIを使ったコーディングに興味があって、VSCodeの拡張機能で導入しやすい「Cline」を少し使い始めています。自分にとって馴染みのあるTerraformのコードをAIに書かせてみたのですが、本当に自分は最後のちょこっとしたコード修正を行うだけで済んだのでとても便利に感じました。今回は、そんなClineについてどういうものなのか？どう使うのか？などを解説していこうと思います！！

## Clineとは？
### 概要
Clineは、AIを活用した開発者支援ツールです。具体的な支援としては、VSCodeなどのIDE上で動作して、ファイル作成、コーディング、トラブルシューティングなどを自律的に行ってくれます！
普段、開発をする上でのAI活用はChatGPTなどのチャットボットを使っているのかなと思いますが、実際にどういう点が違うのでしょうか？以下では、その違いを図を使って説明しようと思います。
ポイントは、「IDE上で動作する」「自律的に開発者を支援する」という点です。


### 図解：チャットボットを活用したコーディング (通常)
チャットボットを使用したコーディングはこんなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942158/fe1c617a-b3d8-452c-b5d2-3da67510962d.png)
まず、書いて欲しい内容をチャットボットに提示してコードを記述してもらいます。そこから、ユーザはIDE上でコピペしてコードを実行し、エラーがあったらそれをチャットボットに投げてどんどんコードを改善していくというような流れです。この流れはコーディングを行うのはAIなので、効率的に見えますが、
- IDE上にコピペし、コマンドを実行する作業
- 実行結果を渡し、エラーをAIに修正依頼する作業

は手動で行っており、まだまだ非効率的なところが残っています。
どうせなら
- コーディングをIDE (実行環境) 上でやってほしい
- コマンドを実行し、トラブルシューティングを自動でやってほしい

と思いますよね？それをClineは実行してくれます！

### 図解：Clineを活用したコーディング
Clineを使用したコーディングはこんなイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942158/188c3a0d-baa9-4079-9fa3-377cf3cabdfb.png)

まず、書いて欲しい内容を**VSCode**上で提示します。すると、VSCode上でAIとのやり取りが始まります。
すると、AIは、コーディングするためのファイルの作成などのVSCode上の操作について許可をユーザに取ってきます。ユーザがその操作を許可するとコマンドを実行し、ファイルが作成されます。そして作成したファイルにコーディングが行われ、テストしたいとの依頼が再びきます。ユーザがそれを許可すると、テストコードが実行され、その実行結果は自動的にAIに送信され、AIはその結果をもとに次の行動を決めるというような流れです。

つまり、先ほど書いた効率的に行いたい点として書いた
- コーディングをIDE (実行環境) 上でやってほしい
- コマンドを実行し、トラブルシューティングを自動でやってほしい

というのをユーザに許可を取りながら自律的にVSCode上で実行してくれます！

めっちゃ便利ですよね...。ここまで進化しましたか...。

## Clineの使い方
そんなClineの使い方ですが、拡張機能をインストールし、使用したいAIモデルを指定だけで使い始めることが出来ます。例えば、Bedrockなら使用するAIモデルをAWSのマネージメントコンソールで有効化し、自身のアクセスキーや使用するAIモデルをVSCode上に登録することでClineを使い始めることが出来ます。

より詳細な説明は👇に書かれています！

https://qiita.com/tomoasleep/items/73b73385fd9dc257a34a

## `.clinerules`でよりスマートな依頼を実現！
コーディングをAIに行って欲しい際は、「**こういうルール**でこういうコードを書いて欲しい」と、ルールを詳細に書くことで、AIがルールに沿ったコーディングしてくれます。
しかし、プロジェクトであらかじめ決まっているルールをAIに何度も投げるのは指示文も長くなるなどしてとても非効率に感じます。そこで、Clineではそのルールを`.clinerules`に記載しておくことで「こういうコードを書いて欲しい」という指示文で済ませることが出来ます！`.clinerules`は基本マークダウン形式で記載して
```
## はじめに
このドキュメントは、clineが開発を行うためのルールをまとめたものです。
このルールに従って開発を行ってください。

## コーディングルール
1. xxxxx
2. yyyyy
3. aaaaa

## テスト
$ exec-command {file-name} が成功すること
```
というようにまとめて、プロジェクトのフォルダに格納してください。

実際、どのようなルールが設定されているかは👇をご参考ください！

https://qiita.com/tomada/items/635c2964f011af89b08c


## まとめ
便利なので、ぜひお手元のVSCodeにインストールして、どれかお気に入りのAIモデルを探してみてください！もう、元の開発には戻れません（）
JavaScript入門　In Instagram

practice.html
```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>はじめてのHTML</title>
    <link rel="stylesheet" href="practice.css">
  </head>
  <body>
    <h1 id="title">こんにちは、HTML！</h1>
    <p>これは最初のWebページです。</p>
    <button id="changeTextBtn">あいさつを変える</button>

    <!-- JavaScriptファイルの読み込み -->
    <script src="practice.js"></script>
  </body>
</html>
```

practice.css
```
/* ページ全体の背景とフォント */
body {
    background-color: #f0f8ff; /* やさしい水色 */
    font-family: Arial, sans-serif;
    text-align: center;
    padding: 50px;
  }
  
  /* 見出しの装飾 */
  h1 {
    color: #2c3e50; /* 濃いネイビー */
    font-size: 36px;
    margin-bottom: 20px;
  }
  
  /* 段落の装飾 */
  p {
    color: #555;
    font-size: 18px;
  }
  ```

  practice.js
  ```
  document.addEventListener("DOMContentLoaded", function () {
  const title = document.getElementById("title");
  const button = document.getElementById("changeTextBtn");

  button.addEventListener("click", function () {
    title.textContent = "JavaScriptで変わりました！";
  });
});
```
Railsのバージョンアップに伴う仕様変更

### `.all`の戻り値の違い
#### Rails 3

`.all` は Array（配列） を返す。
配列なので `<<` で要素追加ができる。

```ruby
@books = Book.where(published: true).all
@books << Book.new(title: "新しい本") # エラーにならない
```

#### Rails 4以降（特にRails 5）

`.all`は`ActiveRecord::Relation`を返す。
RelationはSQLのクエリ結果を遅延評価するオブジェクトで、`<<` で要素追加はできない。

```ruby
@books = Book.where(published: true).all
@books << Book.new(title: "新しい本") #=> undefined method `<<` エラー
```
### 対応
Rails 5以降で配列として使いたい場合は .to_a を使う

```ruby
@books = Book.where(published: true).to_a
@books << Book.new(title: "新しい本") #=> OK
```
これで `<<` で要素追加できる。
猿でもわかるAIビジネス活用シリーズ 🐵📊 AIを活用した社内ナレッジ共有の仕組み

 

## AIを活用した社内ナレッジ共有の仕組みを作ってみた話

### 1. はじめに：なぜ「社内ナレッジ共有」が課題になるのか？

日々の業務で「このトラブル、前にも誰かが対応してた気がする…」と思ったことはありませんか？
もしくは「この設定手順、どこに書いてあったっけ…」とSlackやNotionを探し回る日々…。

**情報は存在するのに、見つからない。**
これは多くの企業で起きている「暗黙知のサイロ化」問題です。

> 🧠 知見が属人化し、チーム内に埋もれてしまう

この問題を解決するアプローチのひとつが、「AIを活用した社内ナレッジ共有」の仕組みです。
今回は、**ChatGPT API とベクトル検索 (Vector Search) を活用し、社内ドキュメントを質問回答型で引き出せるシステム**を実装してみたので、その方法と工夫を紹介します。

---

### 2. 技術の概要：RAG（Retrieval-Augmented Generation）とは？

今回のシステムは、以下の技術スタックを使っています：

* **ChatGPT API（GPT-4）**：自然言語での対話エンジン
* **ベクトルデータベース（今回は `Weaviate` を使用）**：文書の意味検索
* **RAG（Retrieval-Augmented Generation）**：検索と生成のハイブリッドAI

#### 🔍 RAGとは？

> RAGとは、**検索（Retrieval）と生成（Generation）を組み合わせたAIアーキテクチャ**で、「手元の文書から適切なコンテキストを検索し、その上でLLMに回答させる」手法です。

これにより、**社内に閉じたナレッジ（例：Redmine、Wiki、PDFマニュアルなど）を活用したAIチャットボット**を実現できます。

---

### 3. 実装してみる：Python + Weaviate + OpenAI APIで簡易プロトタイプ

#### 3.1 データ構造の整理

まず、社内ドキュメント（例：Markdown, PDF, Notion Export）をすべてプレーンテキスト化し、小さなチャンクに分割します。

```python
from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
docs = text_splitter.create_documents([your_raw_text])
```

#### 3.2 ベクトルDBへのアップロード

WeaviateをDockerで起動し、ベクトル化してドキュメントを格納します。

```python
from langchain.vectorstores import Weaviate
from langchain.embeddings.openai import OpenAIEmbeddings

vectorstore = Weaviate.from_documents(
    documents=docs,
    embedding=OpenAIEmbeddings(openai_api_key="YOUR_KEY"),
    weaviate_url="http://localhost:8080"
)
```

#### 3.3 ユーザーの質問に答える部分

質問を受け取り、関連するチャンクを検索し、GPTにプロンプトとして渡します。

```python
retrieved_docs = vectorstore.similarity_search("Redmineの使い方まとめある？")
context = "\n".join([doc.page_content for doc in retrieved_docs])

prompt = f"""以下の社内ドキュメントに基づいて質問に答えてください。
###
{context}
###
Q: Redmineで工数を記録する手順は？
"""

response = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[{"role": "user", "content": prompt}]
)
```

---

### 4. 実務でのコツと落とし穴

#### ✅ 実務で役立ったTIPS

* **チャンクサイズの最適化**：小さすぎると文脈が不足、大きすぎると検索精度が落ちる
* **ドキュメント前処理**：余計なヘッダーやテンプレートは除去しておくと精度UP
* **Embed時のフィルタ設計**：部署名・ドキュメント種別などでタグを持たせておくと便利

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

* **PDFレイアウト崩れ**：レイアウトが複雑だと意図しない文脈が生成される
* **セキュリティ問題**：APIキーや個人情報の取り扱いには注意が必要
* **メンテナンス工数**：新規ドキュメント追加時のインデックス更新設計が重要

---

### 5. 応用編：Slack連携 & 社内Q\&Aボットの構築

さらに以下の応用が可能です：

* **Slack Botと連携**：ユーザーが質問 → AIがRAGで回答 → スレッドで会話
* **社内ポータルに統合**：Next.jsやVueでUIを作り、社内検索ポータルとして活用
* **監査ログ機能の追加**：誰が何を聞いたか記録し、ナレッジの需要分析に活かす

---

### 6. まとめ：ナレッジ共有 × AIは、全員の生産性を上げる武器になる

| 観点   | メリット                    | デメリット           |
| ---- | ----------------------- | --------------- |
| 検索性  | 意味ベースの検索ができる            | 初期構築に時間がかかる     |
| 拡張性  | Slack, Web, Voiceにも展開可能 | 保守・更新設計が必要      |
| 業務効果 | 情報探索の時短、大幅な属人化解消        | 精度にはドキュメント品質が影響 |

社内に眠っている「知ってる人しか知らない情報」──それをAIの力で引き出すことで、**組織全体のナレッジ資産が見える化**されます。
実際に試してみると、「あれ？これ、うちのチームにもすぐ導入できるかも」と感じるはずです。

> まずは小さく始めて、小さく成功体験を積み上げること。
> それが、AI活用を組織に根づかせる第一歩です。

---

### 🔗 付録：GitHubリポジトリ、参考リンク

* [Weaviate公式ドキュメント](https://weaviate.io/)
* [LangChain公式](https://docs.langchain.com/)
* [OpenAI GPT-4 API](https://platform.openai.com/docs)
猿でもわかるAIビジネス活用シリーズ 🐵📊 AIによる経費精算の自動化で業務を効率化！

 

## AIによる経費精算の自動化で業務を効率化！

---

## 1. はじめに：経費精算、面倒すぎませんか？

毎月訪れる“あの作業”。そう、**経費精算**です。
レシートをスキャンして、金額や日付を入力して、上司に申請…。
気づけば1時間があっという間に消える、**誰もが避けて通れない非効率な業務**です。

特に出張や営業が多い企業では、**この単純作業が積み重なって大きなコスト**となります。

> そこで本記事では、「AIを使ってこの業務をどこまで自動化できるか？」を、技術的に掘り下げていきます！

---

## 2. 経費精算×AI：どんな技術が使えるのか？

AIによる経費精算の自動化には、主に以下のような技術が活用されます。

| 技術                                 | 役割                |
| ---------------------------------- | ----------------- |
| OCR（Optical Character Recognition） | レシート画像からテキストを抽出   |
| NER（Named Entity Recognition）      | 金額・日付・店舗名などの情報を分類 |
| Rule-based processing or LLM       | 文脈理解・補正ロジック       |
| クラウドストレージ / API                    | スマホやPCからのアップロード連携 |

たとえば、社員がスマホでレシートを撮影 → 画像がS3にアップロード → LambdaがOCRを実行 → 結果をDynamoDBに保存 → ChatGPT APIで不明情報を補完、などが可能です。

---

## 3. 実装例：OCR × LLMでレシートを自動解析してみる

ここでは実際に、**PythonとOpenAI API**を使って簡易的なレシート自動解析のプロトタイプを作ってみます。

### 使用ライブラリ

```bash
pip install openai pytesseract pillow
```

### ステップ①：OCRでレシート画像を読み取る

```python
from PIL import Image
import pytesseract

image = Image.open("receipt.jpg")
raw_text = pytesseract.image_to_string(image, lang="jpn")
print(raw_text)
```

出力例（OCR結果）：

```
スターバックスコーヒー
2024年12月3日
¥580
カフェラテ
```

### ステップ②：ChatGPTで構造化情報に変換

```python
import openai

openai.api_key = "YOUR_API_KEY"

prompt = f"""
次のレシート情報をJSON形式に変換してください：
---
{raw_text}
---
必要な項目：店舗名、日付、金額、品目
"""

response = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[
        {"role": "system", "content": "あなたは優秀な経費精算AIです。"},
        {"role": "user", "content": prompt}
    ]
)

print(response.choices[0].message.content)
```

出力結果（構造化JSON）：

```json
{
  "店舗名": "スターバックスコーヒー",
  "日付": "2024-12-03",
  "金額": 580,
  "品目": ["カフェラテ"]
}
```

たった数十行のコードで、**レシート→JSON構造データ**が実現できます！

---

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

### よくある課題と対策

| 課題          | 解決策                             |
| ----------- | ------------------------------- |
| OCRの精度が低い   | Tesseractの前処理（グレースケール、ノイズ除去）を強化 |
| 金額や日付の抽出ミス  | LLMで補完＋正規表現でフォーマット整形            |
| 手書きレシートへの対応 | GPT-4でも精度が不安定。画像前処理と複数手段併用が吉    |
| セキュリティ・個人情報 | 入力データのマスキング処理＋暗号化通信を忘れずに        |

### 実運用Tips

* **バッチ処理よりも非同期処理が便利**（例：画像アップロード時に逐次処理）
* **クラウドストレージ連携はS3 + Lambdaが鉄板構成**
* **PDFや複数枚対応も想定して設計しておく**

---

## 5. 応用：精算ワークフロー全体をAIで強化する

経費精算の自動化は、単なるOCR処理に留まりません。
以下のようなステップもAIで効率化可能です。

* **分類（交通費・接待費など） → GPTで推論分類**
* **不正検出 → 異常値検出モデルでアラート**
* **承認フロー補助 → LLMが理由を要約＆推薦文を自動生成**

たとえば、以下のような拡張が可能です：

```python
# GPTで費目分類の例
prompt = "以下の購入内容を交通費・交際費・雑費のどれかに分類してください：新幹線代 13200円"
```

→ GPT応答：「これは交通費です」

---

## 6. まとめ：AI経費精算の可能性と今後

### ✅ メリット

* 単純作業の削減 → 生産性向上
* 入力ミスの軽減 → 品質向上
* 若手でも運用しやすい柔軟な構成が可能

### ⚠️ 注意点

* OCR精度や例外処理への備えが必要
* プライバシー配慮・セキュリティ対策も必須

---

### 🎯 今後の展望

ChatGPTなどのLLMの発展により、
**「人間がやっていた“ちょっとした判断”」も自動化可能な時代**が到来しています。

業務の中で「これって毎回やってて面倒だな」と思ったら、
**まずは小さくプロトタイプを作って試してみる**ことをおすすめします。

次回は、「AIによる業務日報の自動生成」をテーマに深掘り予定です！

---

📌 **GitHubにサンプルコードを公開しています！**（準備中）
📩 ご質問・フィードバックはコメント欄までお気軽にどうぞ！
猿でもわかるAIビジネス活用シリーズ 🐵📊 AIで作業現場の安全性を向上させるには？

 
## AIで作業現場の安全性を向上させるには？現場カメラ×物体検出モデルの実践活用

---

## 1. はじめに 〜「ヒヤリ・ハット」をAIで減らす〜

工場や建設現場などの「作業現場」では、毎日のように危険と隣り合わせの作業が行われています。
「ヘルメットを着用していない」「立入禁止エリアへの侵入」「重機の接近に気づかない」など、
ちょっとしたミスが大きな事故につながる可能性があります。

現場での安全教育や注意喚起だけでは限界があります。
では、**AIを使って「ヒヤリ・ハット」をリアルタイムで検出・通知できたら？**
それは、現場の安全性を一段引き上げる強力なソリューションになります。

この記事では、**物体検出AI（Object Detection）を活用して現場の安全性を監視・向上させる方法**を、実例とコードを交えて解説します。

---

## 2. 技術の概要 〜物体検出AIで「人」「ヘルメット」「立入禁止」などを認識〜

### 🔍 物体検出(Object Detection)とは？

物体検出は、画像や映像の中から「どこに何があるか」を検出する技術です。代表的なモデルとしては：

* **YOLO（You Only Look Once）**
* **SSD（Single Shot MultiBox Detector）**
* **Faster R-CNN**

があります。

今回は実装が簡単で高速な「**YOLOv8**」を使います。
Ultralytics社が提供するライブラリにより、Python + OpenCV でリアルタイム推論が簡単にできます。

### 🔧 使用するツール・ライブラリ

* Python 3.10+
* OpenCV
* [Ultralytics YOLOv8](https://github.com/ultralytics/ultralytics)
* （オプション）Streamlit for デモ表示

---

## 3. 実装編：現場映像から「ヘルメット未着用」を検出する

### 📸 ステップ1：YOLOv8 のインストールとモデル準備

```bash
pip install ultralytics opencv-python
```

```python
from ultralytics import YOLO
import cv2

# ヘルメット着用検出のための学習済みモデル（例：カスタムモデル）
model = YOLO("best.pt")  # 自分で fine-tuning したモデルを指定
```

> *Tip: ヘルメット着用検出は COCO デフォルトモデルには含まれていないので、独自データで学習が必要です。*

### 🎥 ステップ2：リアルタイム映像から推論するコード

```python
cap = cv2.VideoCapture(0)  # Webカメラ or RTSP対応カメラ

while True:
    ret, frame = cap.read()
    if not ret:
        break

    results = model(frame)
    annotated_frame = results[0].plot()

    cv2.imshow("Safety Monitor", annotated_frame)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()
```

### 🚨 ステップ3：アラート送信（例：LINE通知 or Webhook）

```python
for box in results[0].boxes:
    class_id = int(box.cls[0])
    if class_id == 1:  # class_id 1 = "ヘルメット未着用"
        send_alert("ヘルメット未着用を検出しました！")
```

---

## 4. 実務でのTipsとよくある落とし穴

### ✅ よく効くTips

* **夜間・暗所対応**：赤外線カメラ + 学習データ拡張（明るさ調整）で精度向上
* **アングルを限定する**：カメラ位置を工夫して物体検出の安定化
* **推論処理の負荷分散**：エッジデバイス（NVIDIA Jetsonなど）を活用

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

| 落とし穴                   | 解説                            |
| ---------------------- | ----------------------------- |
| モデルが「ヘルメット」と「帽子」を混同する  | 学習データのアノテーションを丁寧に見直す必要あり      |
| ネットワーク遅延でリアルタイム性が損なわれる | ローカル推論 + 通知だけクラウド連携がおすすめ      |
| 精度が高い＝安心ではない           | 誤検出時の対応（例：2回連続で検出→通知）などの工夫が必要 |

---

## 5. 応用・拡張：マルチクラス検出＋行動認識へ

さらに一歩進めて、以下のような応用も可能です：

* **ゾーン侵入検出**：ラインを引いて、危険ゾーンに人が入ると検出
* **フォークリフト接近検出**：重機と人の距離をリアルタイムに測定
* **行動認識モデルの導入**：転倒や倒れこみなど異常行動の検知（例：Pose Estimation + 動作分類）

また、Streamlit などでWebダッシュボード化すれば、
安全管理担当者が「いつ、どこで、何が起きたか」を可視化できます。

---

## 6. まとめ：AI×現場安全は現実的か？

| 観点    | メリット                    | 課題                 |
| ----- | ----------------------- | ------------------ |
| 精度    | 一定条件下では人間より早く気づける       | 多様な現場に対応させるには学習が必要 |
| 導入コスト | オープンソース＋エッジデバイスで低コスト化可能 | 運用フローとの統合がカギ       |
| 導入効果  | リアルタイムでの注意喚起＋記録もできる     | 誤検知にどう対処するか？が重要    |

結論として、\*\*AIによる安全監視は「今すぐ試せる現実解」\*\*です。
まずは小規模なカメラ設置から試し、データをためて少しずつ精度を上げていくアプローチが現実的です。

---

## 🚀 さいごに

「AI = 難しい」と感じる方も多いかもしれませんが、
今回のように現場で本当に役立つ形でAIを活用することができます。
安全性は生産性にも直結します。ぜひ、皆さんの現場にもAI導入の第一歩を！

---

💬 質問やフィードバック、実際に使ってみた事例などあれば、ぜひコメントで教えてください！
パスワードが分からずzshからbashに変えるのに苦戦した話

## はじめに

EC2インスタンス上でデフォルトシェルを`zsh`から`bash`に変更する方法について解説します。通常の`chsh`コマンドがパスワード認証で失敗する場合の対処法も含めています。

## 問題点

EC2インスタンスでは、通常のパスワード認証が設定されていないことが多く、以下のような場合に`chsh`コマンドが失敗します。

```bash
user@ip-xxx-xx-xx-xx% chsh -s /bin/bash
Password: 
chsh: PAM: Authentication failure
```

これは、ユーザーのパスワードが設定されていないか、PAM（Pluggable Authentication Modules）の設定によって認証が失敗するためです。

## 解決方法

### 1. sudoを使ってシェルを変更する

パスワード認証をバイパスするため、`sudo`を使って変更します：

```bash
sudo chsh -s /bin/bash $USER
```

### 2. 既存のzsh設定をバックアップする

```bash
mkdir -p ~/zsh_backup
mv ~/.zcompdump ~/zsh_backup/
mv ~/.zshrc ~/zsh_backup/
```
### 3. bash用の設定ファイルを作成する

```bash
echo 'if [ -f ~/.bashrc ]; then
    source ~/.bashrc
fi' > ~/.bash_profile

chmod 644 ~/.bash_profile
chown $USER:$USER ~/.bash_profile
```

### 4. 一度ログアウトして再接続する

```bash
exit
```

その後、SSHで再接続します。

## 変更の確認

以下のコマンドで変更を確認できます：

```bash
echo $SHELL           # 現在のシェルを表示
ps -p $$              # シェルプロセスを確認
grep $USER /etc/passwd # /etc/passwdエントリを確認
```

正しく変更されていれば、以下のような出力になります：

```bash
user@ip-xxx-xx-xx-xx:~$ echo $SHELL
/bin/bash
user@ip-xxx-xx-xx-xx:~$ ps -p $$
    PID TTY          TIME CMD
  28726 pts/0    00:00:00 bash
user@ip-xxx-xx-xx-xx:~$ grep username /etc/passwd
username:x:1001:1002::/home/username:/bin/bash
```

## まとめ

EC2インスタンスでzshからbashへのシェル変更は、通常の`chsh`コマンドではパスワード認証の問題で失敗することがありますが、`sudo chsh`を使うことで簡単に解決できます。適切なシェル設定ファイルを用意し、権限を設定することで、スムーズに移行することができます。
猿でもわかるAIビジネス活用シリーズ 🐵📊 AIとIoTの連携でビジネスを加速する方法とは？

 AI × IoT連携でビジネスを加速する方法とは？

---

## 1. はじめに：なぜ今「AI × IoT」なのか？

近年、\*\*IoT（モノのインターネット）**が様々な業界で普及し、センサーデータが大量に収集されるようになりました。しかし、単にデータを集めるだけではビジネス価値は生まれません。そこに**AI（人工知能）\*\*を組み合わせることで、「予測」「自動化」「意思決定支援」など、**データドリブンなビジネス変革**が可能になります。

本記事では、AIとIoTの連携によってどのようにビジネス価値を生み出せるのか、実際のコードとともに解説します。特に、**製造業**を想定した「異常検知」を例に取り上げます。

---

## 2. AI × IoTの概要と仕組み

### 2.1 IoTの役割

IoTは、現場のリアルタイムデータ（例：温度、振動、電流値）を収集します。代表的なプロトコルには以下があります：

* MQTT（軽量プロトコル。センサーデータに最適）
* HTTP/HTTPS（RESTfulなAPI通信）

### 2.2 AIの役割

AIは収集されたデータを用いて、

* **異常検知**
* **予測保守**
* **最適化**

などを行います。モデルの学習には\*\*機械学習（scikit-learn）**や**深層学習（PyTorch、TensorFlow）\*\*が使われます。

### 2.3 連携の構成例

```plaintext
[センサー] → [MQTTブローカー] → [データ収集・加工] → [AIモデル推論] → [通知 or 自動制御]
```

---

## 3. 実装例：振動センサーによる異常検知システム

### 3.1 使用技術スタック

* デバイス通信：MQTT (paho-mqtt)
* データ処理：Python (pandas)
* モデル：Isolation Forest（scikit-learn）
* 可視化・通知：Streamlit + Slack連携

### 3.2 センサーデータ受信（MQTTクライアント）

```python
import paho.mqtt.client as mqtt
import json

def on_message(client, userdata, msg):
    data = json.loads(msg.payload.decode())
    print(f"Received: {data}")
    # データ保存や推論処理に渡す

client = mqtt.Client()
client.connect("mqtt-broker.example.com", 1883)
client.subscribe("factory/sensor/vibration")
client.on_message = on_message
client.loop_start()
```

### 3.3 AIモデルで異常検知

```python
from sklearn.ensemble import IsolationForest
import pandas as pd
import joblib

# 過去データで学習済みモデルをロード
model = joblib.load("if_model.pkl")

# 新しいデータの推論（例）
new_data = pd.DataFrame([[0.03, 0.01, 0.05]], columns=["x", "y", "z"])
score = model.decision_function(new_data)
label = model.predict(new_data)  # -1: 異常, 1: 正常

if label[0] == -1:
    print("⚠️ 異常を検知しました！")
```

### 3.4 Streamlitでリアルタイム可視化

```python
import streamlit as st
import pandas as pd

st.title("リアルタイム異常検知ダッシュボード")
data = pd.read_csv("latest_sensor.csv")
st.line_chart(data)
```

---

## 4. 実務でのポイント＆よくある失敗

### ✅ 成功の鍵

* **データ前処理の重要性**：生データにはノイズが多く、異常検知に影響するため平滑化・正規化は必須
* **しきい値の動的制御**：固定しきい値では現場の変動に弱く、AIモデルによる柔軟な判定が有効

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

| 問題               | 原因               | 対策                       |
| ---------------- | ---------------- | ------------------------ |
| 異常と正常が混同される      | データの不均衡、ラベル不足    | アノマリーデータの収集強化、SMOTEなどの導入 |
| MQTTが不安定 or 接続切れ | QoS設定不足、ネットワーク遅延 | MQTTの再接続処理、QoS1推奨        |
| モデル精度が低い         | 特徴量設計が不十分        | ドメイン知識を活用した特徴量設計         |

---

## 5. 応用・高度化アイディア

* **エッジAI**：Raspberry Piなどでローカル推論 → 通信負荷軽減＆リアルタイム性向上
* **AI Ops統合**：異常検知から自動アラート → チームSlackに通知 → メンテナンス指示を自動化
* **デジタルツイン連携**：AIモデルで工場全体の仮想再現 → シミュレーション＆最適制御へ

---

## 6. まとめ：AI × IoTは「予測」から「価値創出」へ

### 🎯 メリット

* 現場データから**異常や未来を予測**
* 属人的判断から**客観的な判断**へ
* 保守・生産性の**最適化**

### ⚠️ 課題

* 初期構築コストやデータ収集体制の整備が必要
* 精度向上には継続的な改善とフィードバックループが不可欠

---

## 📌 おわりに

AIとIoTの連携は、単なるIT導入ではなく「現場の知恵 × 技術」の融合による**価値創造の仕組み**です。難しく感じるかもしれませんが、小さなPoCから始めて、ビジネス成果に繋げる道は十分に現実的です。

**まずはMQTT＋Pythonで簡易プロトタイプを作るところから始めてみましょう！**

---

ご質問やフィードバックがあれば、コメント欄やGitHubでお気軽にどうぞ！🚀

---

✍️ 著者：AI・クラウド好きのソフトウェアエンジニア（OpenAIによる生成）
【AWS入門】API Gateway + Lambda + DynamoDBで簡単な投稿一覧ページを作る（表示編）



AWSを使って、**DynamoDBに保存された投稿データをHTMLで表示するWeb API**を構築してみましょう。
この記事では「データの読み込み（表示）機能」に絞り、API GatewayとLambdaを使ってサーバレスで動作するシンプルな投稿一覧システムを作成します。

---

## ⛏️ 構成イメージ

```
[ブラウザ] → [API Gateway (HTTP API)] → [Lambda関数] → [DynamoDB]
```

* 投稿データをDynamoDBに保存し、それをLambda関数で読み込み、HTMLとして返します。

---

## 📓 今回の作業内容

1. DynamoDBの準備
2. Lambda関数の作成
3. Lambdaのコード記述（DynamoDBからデータを取得しHTMLで返す）
4. API Gatewayで公開
5. ブラウザで動作確認

---

## 1. DynamoDBの準備

### テーブル作成

1. AWSコンソール → DynamoDB → 「テーブルを作成」
2. テーブル名：`PostsTable`
3. パーティションキー：`postId`（文字列型）
4. ソートキーは無しでOK
5. その他の設定はデフォルトで作成

### サンプルデータの追加（手動で）

```json
{
  "postId": "1",
  "author": "User A",
  "timestamp": "2024-01-01 10:00:00",
  "content": "これはサンプル投稿です。"
}
```

---

## 2. Lambda関数の作成

### 手順

1. AWSコンソール → Lambda → 「関数の作成」
2. 「一から作成」を選択
3. 関数名：例）`fetchPostsHandler`
4. ランタイム：Python 3.12
5. 実行ロール：`AWSLambdaBasicExecutionRole` に加えて、DynamoDBアクセス権限があるもの（`AmazonDynamoDBFullAccess` を事前に付与済みとします）

---

## 3. Lambda関数のコード（Python）

以下のコードを Lambda 関数にコピペします：

```python
import json
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('PostsTable')

def lambda_handler(event, context):
    result = table.scan()

    html = "<html><meta charset='UTF-8'><body><h1>投稿一覧</h1>"
    for item in sorted(result['Items'], key=lambda x: x['timestamp'], reverse=True):
        html += "<div style='margin-bottom:20px;border:1px solid #ccc;padding:10px;'>"
        html += f"<strong>投稿者：</strong>{item['author']}<br>"
        html += f"<strong>投稿日時：</strong>{item['timestamp']}<br>"
        html += f"<strong>内容：</strong>{item['content']}"
        html += "</div>"
    html += "</body></html>"

    return {
        'statusCode': 200,
        'body': html,
        'headers': {
            'Content-Type': 'text/html'
        }
    }
```

---

## 4. API Gateway の設定

1. Lambda関数の画面 → 「トリガーを追加」 → 「API Gateway」
2. APIタイプ：HTTP API（推奨）
3. セキュリティ：オープン（認証なし）
4. 作成後に表示されるエンドポイントURLをコピーしておきます

---

## 5. 動作確認

ブラウザで発行されたAPI GatewayのURLにアクセスすると、DynamoDBに登録された投稿一覧がHTMLで表示されます。
**表示されれば成功です！**

---

## 🔐 IAMについて（補足）

この構成では Lambda 関数が DynamoDB にアクセスするため、IAM実行ロールに下記のような権限が必要です：

* `dynamodb:Scan`
* `dynamodb:DescribeTable`

本記事では、`AmazonDynamoDBFullAccess` ポリシーがあらかじめ実行ロールに付与されている前提で進めています。

---

## ✅ おわりに

これで **API Gateway + Lambda + DynamoDB による HTML形式の投稿一覧API** が完成しました！
シンプルですが、サーバレスの基本構成としてとても良いハンズオン題材になります。

---

## ✨ 次のステップ（応用編）

* HTMLフォームを用いた投稿機能（DynamoDBへの書き込み）
* Bootstrapなどを使ったデザイン改善
* タイムスタンプの自動化・整形
* 投稿一覧と詳細ページの分離

---

## 🧑‍🏫 こんな方におすすめ

* AWSの構成を動かしながら学びたい方
* LambdaやDynamoDBを実用的に使ってみたい方
* フロントエンドとAPIの連携を学びたい方

---

ご質問があればコメントでお知らせください！
次回は「投稿機能（書き込み編）」を予定しています。お楽しみに！
JetBrains IDE × Marp でMarkdownスライドを快適編集！リアルタイムプレビュー環境の作り方

Marpは、Markdownで手軽にスライド資料を作成できるオープンソースツールです。VS Code向けの拡張機能（[Marp for VS Code - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode)）がよく知られていますが、JetBrains系IDEでもCLIを活用することで、リアルタイムプレビューやPDF出力といった便利な機能をローカル環境で再現できます。
本記事では、JetBrains IDEとMarp CLIを組み合わせた活用方法をご紹介します。


## 目次
- 使用環境と前提条件
- JetBrains IDEでのMarpプレビュー手順
- 参考文献

## 使用環境と前提条件

今回の手順では、以下のバージョンと環境を前提としています。

- macOS `Sequoia 15.4.1`
- marp-cli `v4.1.2`
- JetBrains IDE（例：IntelliJ IDEA、RubyMineなど）

### Marp CLIのインストール

ターミナルから以下のコマンドでMarp CLIをインストールします。

```bash
$ brew install marp
````

インストール後、`marp`コマンドが使用可能になります。
その他のインストール方法は、[こちら](https://github.com/marp-team/marp-cli?tab=readme-ov-file#install)

## JetBrains IDEでのMarpプレビュー手順

JetBrains IDEでMarpを利用してMarkdownファイルをプレビューする手順は以下のとおりです。

### 1. Markdownファイルの作成

拡張子が `.md` のMarkdownファイル（例：`slide.md`）を作成します。

### 2. CLIでスライドをウォッチする

Marp CLIを使って、対象のMarkdownファイルをウォッチ状態にします。これにより、ファイル保存のたびにスライドが自動更新されます。

```bash
$ marp -w slide.md
```

### 3. JetBrains IDEでプレビュー表示する

1. ウォッチ中に生成されるHTMLファイル（例：`slide.html`）をプロジェクトビューから選択します。
   ![スクリーンショット 0007-05-17 12.18.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64171/39762fef-ab39-478d-800e-d3fb2ba156a8.png)

2. IDE内の「ビルトインプレビュー」機能を使ってスライドを確認できます。
    ![スクリーンショット 0007-05-17 12.20.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64171/e6cabb94-07b5-40db-86bc-be36571866a7.png)

### 4. Markdownの編集と即時反映

Markdown（例：`slide.md`）を編集して `Command + S` で保存すると、自動的に生成ファイルが更新され、プレビューにも即時反映されます。

![画面キャプチャ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64171/a291ece5-a1b5-4bce-83c0-ff8c1c256de4.gif)


## 参考文献

- [Marp: Markdown Presentation Ecosystem](https://marp.app/)
- [GitHub - marp-team/marp-cli: A CLI interface for Marp and Marpit based converters](https://github.com/marp-team/marp-cli)
- [Markdown-Powered Slides in JetBrains IDEs | The .NET Tools Blog](https://blog.jetbrains.com/dotnet/2024/10/01/markdown-powered-slides-in-jetbrains-ides/)
ドライバーが消えた場合（HP）

デバイスマネージャーで不明のデバイスが接続されているやドライバーがはてなマークになったりして、
うまくつながらないことってありますね。

でもこの前、電話サポートで教えていただいたいいやり方を紹介します。

## [HP　Image Assistant]

使い方はこちらへ
https://jp.ext.hp.com/v-ivr/common/os-install/faq/18/

あとは説明書きに従うだけ
はてなマークの不明のデバイスがなくなりました。
DataRobot AIアカデミーによる生成AI 講座から、生成AIの最新技術とプロジェクト推進の勘所を紹介！ 

### はじめに
こんにちは、DataRobot Japanの長野、菅原です。データサイエンティストとしてお客様への技術的なご支援を担当しています。

DataRobot Japanは、[DataRobot AIアカデミー](https://learn.datarobot.com/pages/ai-academy)という約3ヶ月間のデータサイエンティスト育成研修コースを日本でこれまで13回提供しており、卒業生は「ビジネス現場で真のビジネス価値を創出できるデータサイエンティスト」として弊社クライアント企業様やパートナー様で多数活躍されています。

前回、第13期の同研修コースでは新コンテンツとなる「生成AI概論」もカリキュラムに加わり、2025年2月に講義が行われました。「生成AI概論」は丸1日（8時間）の集中講義によるインプットと実践的な演習課題によるアウトプットを通して、生成AI技術のエッセンスを習得して頂く講座となっています。

以下、本記事では、同講座で解説した内容の一部を生成AIプロジェクト未経験者の方に向けてご紹介します。

※「生成AI概論」を含むDataRobot AIアカデミーの次期開催は2025年後半を予定しています。本記事をご覧いただき、もしご興味がありましたらぜひお問い合わせください。なお、同研修コースはDataRobotユーザーでなくても受講できるカリキュラムとなっています。

### 生成AIプロジェクト推進の勘所
生成AIプロジェクトは、ステークホルダーが多く、要件も複雑であり、ベストプラクティスもまだ十分には認知されていません。そのため、生成AIプロジェクトを成功させるためには、技術的な知識だけでなく、プロジェクトの進め方やリスク対策も重要な項目です。

生成AIプロジェクトの基本的な流れとして、テーマ創出、準備、RAG/アプリ構築・検証、ビジネス適用、運用という5つのフェーズを理解し、各フェーズにおける具体的なタスクや考慮事項を整理することが重要です。また、プロジェクトを進める上での課題や制約、およびそれらに対する対策についても議論しておくべきです。

![sugawara001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/368f7cf8-8ddd-425f-b21e-abee32e45811.png)

![sugawra002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/d6d97f74-fe40-4ee2-8ff0-7e1e7e2636bd.png)

### 生成AIの最新トピック
LLMの活用パターンとして、RAG、追加学習/自作LLM、AIエージェントの3つがあげられます。特に、LLM選定における重要な要素として、モデルの種類、コンテキスト長、コスト、マルチモーダル対応などがありますので、それぞれの違いや選択のポイントを理解しておく必要があります。さらに、プロンプトエンジニアリングの基本や、RAG構築の際のデータ準備、VDB構築、プロンプト設定など、精度改善のための具体的な手順についても理解しておくべきです。

![sugawara003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3864834/f89d3167-315c-4c47-96e7-87de201738ee.png)

### まとめ
以上、本記事ではDataRobot AIアカデミーの新講座「生成AI概論」から、生成AIの最新技術とプロジェクト推進の勘所をご紹介しました。

一方、生成AI周りの技術は急速に進化しており、日々キャッチアップしていく必要があります。2月に実施したDataRobot AI アカデミーではRAGがメインでAIエージェントはサブコンテンツとして扱いましたが、次回はよりAIエージェントに比重を置く予定です。

AIエージェントにご興味のある方はぜひ以下の記事もご覧ください。
[DataRobot「データと会話する」エージェント：組織独自のLLMでデータ分析を強化する](https://qiita.com/DataRobot_PR/items/1199ae1aed6f6be79b99)

DataRobot は、今後も最新の技術動向を踏まえ、皆様の生成AIプロジェクト推進に貢献できるような記事・講座を提供してまいります。
イベントループとは?

## イベントループとは？

**イベントループ**は、JavaScriptランタイム（ブラウザやNode.jsなど）で**非同期処理**を管理するための中心的な仕組みです。

JavaScriptは**シングルスレッド**の言語であり、一度に一つの作業しか実行できません。しかし、UIの応答性やAPI通信などの非同期処理をスムーズに行うために、イベントループの仕組みが導入されています。

## コールスタックとイベントループ

### 1. コールスタック (Call Stack)

- JavaScriptでは、現在実行中の関数が**スタック(LIFO構造)** で管理されます。
- 関数が呼び出されるとスタックに**積まれ**、処理が終わると**取り出され**ます。

```js
function foo() {
  console.log("Hello");
}
foo();
```

1. `foo()` がスタックに積まれる  
2. `console.log("Hello")` が実行される  
3. `foo()` がスタックから取り除かれる

### 2. Web API（ブラウザ API）

- `setTimeout` や `addEventListener`, `fetch` などは JavaScriptのコア機能ではなく、ブラウザが提供する機能です。
- 例えば `setTimeout` を呼び出すと、その処理はWeb API領域に渡されて実行されます。

```js
console.log("Start");

setTimeout(() => {
  console.log("Callback");
}, 1000);

console.log("End");
```

**出力結果：**

```
Start  
End  
Callback
```

なぜ `Callback` は最後に出力されるのでしょうか？

## イベントループの動作

1. すべての**同期コード**はまず**コールスタック**上で実行されます。
2. `setTimeout` のような非同期関数は**Web API**に渡されます。
3. タイマーが終了すると、コールバック関数は**コールバックキュー（タスクキュー）**に移されます。
4. **イベントループ**はコールスタックが空かどうかを確認し、空であればキューからコールバックを取り出して実行します。

## コード例の再確認

```js
console.log("1");

setTimeout(() => {
  console.log("2");
}, 0);

console.log("3");
```

**出力結果：**

```
1  
3  
2
```

- `setTimeout(..., 0)` は**すぐに実行されるわけではありません**。
- まず Web API に送られ、タイマー終了後にコールバックキューに入ります。
- コールスタックが空になってからイベントループによって実行されます。

## 重要なポイントまとめ

- JavaScriptは**シングルスレッド**で動作する。
- イベントループは**コールスタックが空になったタイミング**でのみ、コールバックキューから処理を取り出す。
- `setTimeout(..., 0)` は**0ミリ秒後に実行**と指定されても、コールスタックが空くまで実行されない。
# 【GraphQLでAPI開発を効率化】Amazon AppSyncとは？

# 【GraphQLでAPI開発を効率化】Amazon AppSyncとは？

複数のデータソースにまたがるデータを一括で取得したい。  
フロントエンドに最適な形でAPIを返したい。  
そんなニーズに応えるのが **Amazon AppSync** です。

---

## 🔸 Amazon AppSyncとは？

**Amazon AppSync** は、AWSが提供する**マネージドなGraphQL APIサービス**です。  
GraphQLを使うことで、クライアントが必要なデータを**必要な形だけ取得**できます。

AppSyncでは、以下のようなデータソースを統合して、GraphQL APIとして公開できます：

- DynamoDB（NoSQLデータベース）
- RDSやAurora（SQLベース）
- Lambda関数
- HTTPエンドポイント（REST APIなど）
- Elasticsearch（OpenSearch）

---

## 🔸 GraphQLのメリットって何？

AppSyncのベースとなる**GraphQL**には、次のような利点があります：

- ✅ クライアントが必要な項目だけ取得できる（**過不足のないデータ取得**）  
- ✅ 複数のAPIを**1回のリクエストで呼び出し可能**  
- ✅ APIの型が**スキーマで定義されていて明確**

REST APIと違い、「エンドポイントが増えすぎる問題」や「不要なフィールドが返ってくる問題」を解決できます。

---

## 🔸 AppSyncの特徴

| 特徴                       | 説明                                                   |
|--------------------------|--------------------------------------------------------|
| フルマネージド             | インフラ構築不要。数分でGraphQL APIを構築可能。              |
| 複数データソース対応         | DynamoDBやLambda、REST APIなどを一括で扱える。              |
| 認証統合が簡単              | Cognito、IAM、API Keyなどと統合可能。                        |
| リアルタイム対応             | サブスクリプションで**リアルタイムデータ配信**もできる（WebSocketベース） |
| キャッシュ・パイプライン対応   | データ取得前後の処理をリゾルバーで細かく定義可能。              |

---

## 🔸 ユースケース例

| ユースケース               | 説明                                                   |
|--------------------------|--------------------------------------------------------|
| モバイルアプリのBFF（Backend for Frontend） | クライアントごとに最適なデータを返すGraphQL APIを提供              |
| 複数マイクロサービスの統合API    | LambdaやRESTを横断して統一インターフェースを構築                  |
| チャットや通知のリアルタイム配信  | AppSyncの**GraphQLサブスクリプション機能**を活用                  |

---

## 🔸 他サービスとの比較

| サービス        | 特徴                                       |
|---------------|------------------------------------------|
| API Gateway + Lambda | REST APIベース。GraphQL未対応。手動で構築が必要。      |
| AppSync       | GraphQL APIをフルマネージドで提供。リアルタイム機能も標準搭載。 |
| Apollo Server | OSSでGraphQLサーバーを自前構築。運用・スケーリングは別途必要。 |

---

## 🔸 まとめ

Amazon AppSyncは、**柔軟かつ効率的なAPI設計**を実現できるGraphQLベースのサービスです。  
特に、**複数のバックエンドを統合したいプロジェクト**や、**リアルタイムデータ配信が必要なアプリ**において強力な選択肢となります。

「RESTでは限界を感じている…」という方は、ぜひAppSyncを試してみてください！

---

## 🔗 公式リンク

- [Amazon AppSync – AWS公式](https://aws.amazon.com/jp/appsync/)  
- [GraphQL 入門ガイド（AppSync）](https://docs.aws.amazon.com/appsync/latest/devguide/what-is-appsync.html)

---

📘 AWSやGraphQLに関する投稿を今後も予定しています。よければフォロー＆いいねお願いします！
Code scanning results に "No new alerts" と出るのはなぜ？PR 差分とアラート表示の関係を検証

## はじめに

GitHub の Advanced Security を利用して `tflint` などの静的解析を行った際、PR の Checks タブに表示される **Code scanning results** に疑問が生じました。

具体的には、`tflint` が警告を出しているにもかかわらず、Checks タブには「No new alerts」と表示されるケースがあるのはなぜなのか？
公式ドキュメントの記述と実際の挙動をもとに検証した結果を整理しました。

## ドキュメントでの記載

参考にしたのはこちらの GitHub Docs です：

https://docs.github.com/en/code-security/code-scanning/managing-code-scanning-alerts/triaging-code-scanning-alerts-in-pull-requests

> Code scanning displays alerts in pull requests only when all the lines of code identified by the alert exist in the pull request diff.

和訳:

> コードスキャンは、プルリクエストの差分にアラートで特定されたコード行がすべて存在する場合にのみ、プルリクエストにアラートを表示します。

なるほど、そういうものなのでしょうか？
実際に試してみましょう。

## 検証

### ワークフローの準備

tflint を実行して SARIF ファイルを生成・アップロードするワークフローを作成します。

```yaml
name: code-scanning-example

on: pull_request

jobs:
  tflint:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup tflint
        uses: terraform-linters/setup-tflint@v4
        with:
          tflint_version: v0.57.0

      - name: tflint
        run: |
          tflint --init
          tflint --disable-rule=terraform_required_version --disable-rule=terraform_required_providers -f sarif > tflint-results.sarif

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v3
        if: success() || failure()
        with:
          sarif_file: "tflint-results.sarif"
```

### PR 作成前のコード

デフォルトブランチには、以下のような S3 バケットを定義する Terraform コードを用意しておきます。

```terraform:main.tf
locals {
  bucket_prefix = "test"
}

resource "aws_s3_bucket" "dummy" {
  bucket_prefix = local.bucket_prefix
}
```

※ `terraform apply` は不要です。

### パターン 1：PR の差分にアラート対象の行が含まれていない場合

以下のように resource ブロックを削除し、ローカル変数 bucket_prefix の使用をやめたとします。

```terraform:main.tf
locals {
  bucket_prefix = "test"
}

# resource "aws_s3_bucket" "dummy" {
#   bucket_prefix = local.bucket_prefix
# }
```

`tflint` は「未使用の変数」として警告しますが、PR の 差分には `locals` の行が含まれているだけです。

結果として、Checks タブの Code scanning results には：

> ✅「No new alerts」

と表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3769407/4228bc40-513c-43a7-b75e-6961f79c8c65.png)

ただし、「View all branch alerts」リンクから遷移すると、実際にはアラートが記録されていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3769407/3ae8d59e-dbe5-4f46-a469-dcb41e502109.png)

### パターン 2：PR の差分にアラート対象の行が含まれている場合

次に、未使用変数 `unused` を新たに追加したパターンを検証します。

```terraform:main.tf
locals {
  bucket_prefix = "test"
  unused        = "dummy" ### 新規未使用変数
}

resource "aws_s3_bucket" "dummy" {
  bucket_prefix = local.bucket_prefix
}
```

この場合、未使用変数の定義が PR の差分に含まれるため、Code scanning results に以下のように表示されました：

> ⚠️ New alerts found

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3769407/f6d4799f-14bc-491d-b7ce-5817769d4984.png)

## まとめ

- PR の Checks に表示されるアラートは、「アラート対象のコード行すべてが PR の差分に含まれている場合」に限られる

- 既存のコードが PR によって間接的に問題のある状態になっても、**その行が変更されていなければアラートは表示されない**

- 実際のアラートは Security タブの「Code scanning」から確認可能