OmniAICreator/Qiita-1.07M huggingface dataset:
PlaywrightMCPをVSCode + Copilotで使う [ 初期設定 〜 使い方まで ] E2Eテスト、ブラウザ操作をAIで自動化したい

会社負担でCopilotがVSCodeで使える環境の人も多いと思うので、その環境下でPlaywrightMCPを使う方法をここに残しておこうと思います。

https://github.com/microsoft/playwright-mcp

# playwright-mcpの機能まとめ
- ブラウザの自動操作をサポート（スクリーンショット不要）
- VS Code との連携が可能（コマンドまたはGUIボタンでインストール）
- CLIからの起動も可能（npx @playwright/mcp@latest）
- ヘッドレスモード（GUIなし）対応：バックグラウンド処理向け
- Docker対応：headless Chromium のみサポート
- Visionモード：XY座標ベースでの操作が必要なモデルに対応（--visionフラグ）

# 前提条件
VS Codeは最新のバージョンにしておいてください。
つい最近まで公式ドキュメントでVS Code Insidersをインストールするように案内がされていたので、そのせいでVS Code Insidersをインストールすように書いてあるブログが複数存在している状態ですが、2025年4月20日現在、VS Codeを最新バージョンにすれば使えるので、バージョンはアップデートしておいてください。

# インストール

```terminal
npx @playwright/mcp@latest
```
# エージェントモードを有効化
VS Codeの設定(画面右下にある歯車マーク)を開いて、chat.agent.enabledを検索して、チェックをいれてVSCode の Agent モードを有効にします。
![スクリーンショット 2025-04-22 19.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/43b8bf11-436a-4d72-b123-f9c00bda75d4.png)


他にmcpを検索して、mcpの設定をONにするように、という記事を見かけましたが、現在ではその設定項目が消えているようで、私が試したときにはなかったです。

# vscodeのsetting.jsonに追加
コマンドパレットでsetting.jsonを検索するなどして開いて、以下を書き込みました。

```setting.json
{
//他の設定の後に・・・

  "mcp": {
      "inputs": [],
      "servers": {
          "playwright": {
              "command": "npx",
              "args": ["@playwright/mcp@latest"]
          }
      }
  },
  "github.copilot.chat.agent.thinkingTool": true
}
```
"servers" 内のキーは、Copilot Chat に読み込ませたい MCP ツールの「名前」になります。@playwright/mcp を利用する場合、公式の例にある通り、サーバー名を "playwright" にするのが推奨されています。
"mcp-server-time"と書いているブログを見ましたが、これはエラーにはならないものの、Copilot Chatが自動で認識しない可能性があるようです（特にエージェントが playwright に特化している場合）
もし複数のMCPサーバを使いたい場合、serversキーの中の、playwrightの後にキーを入れて設定を追加してください。
`"github.copilot.chat.agent.thinkingTool": true`は、trueにするとエージェントモードで常にMCPを使うように設定できます。


上記を入力すると、入力したsetting.jsonの文字列の側に起動という文字とともに再生ボタンが表示されるので押してください。

![スクリーンショット 2025-04-22 19.21.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/46b6ddc3-f913-4124-8f6a-218404fb41e6.png)


# chat画面で使ってみる
copilotのchat画面のプロンプト入力部に、`質問する`というドロップダウンメニューをエージェントに切り替えてください。
![スクリーンショット 2025-04-22 19.05.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262827/d57cdc27-672b-4e1a-a6b1-dada36804d37.png)

レンチみたいなアイコンをクリックすると、現在有効なMCPサーバが表示されるので、ここにPlaywrightが表示されていれば成功しています。

そうすると、MCPサーバ経由で回答してくれます。
例えば「このファイルのE2Eテストを作成してください」とプロンプト入力すると、現在アクティブなファイルへのPlaywrightを使ったテスト方法を教えてくれました。

他にも、`ブラウザで Google を開いて、「Playwright MCP」と検索して、一番上のリンクをクリックしてください。`とプロンプトに入れるだけで、chromeを開き、Googleのサイトを開いてくれました(reCAPTCHAに引っかかって最後までタスクを実行できませんでしたが。。。)

`https://example.com/contact にアクセスして、名前に「hoge」、メールに「hoge@example.com」、メッセージに「こんにちは」と入力して、送信ボタンをクリックしてください。`という指示もうまくいきました。
【廃止】Sales Cloud and Console Superbadge Unit



https://trailhead.salesforce.com/content/learn/superbadges/superbadge_sales_console__sbu?trail_id=learn-sales-cloud-fundamentals


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/831f1ee6-b5df-40e9-a74e-58f415cee195.png)



+ カスタム コンソール アプリをナビゲートします。
+ カスタム Sales Cloud 構成を使用します。
+ Lightning ユーザー インターフェースを操作します。


# カスタムコンソールアプリの操作

新しい商談を作成し、関係性やタスクを追加します。レコードを評価してステージを追加・編集します。不足している情報がないかレコードを確認します。


:::note alert
Make sure that you created your org using the sign-up link. That org contains all the preconfiguration required for this superbadge.


サインアップリンクを使用して組織を作成してください。この組織には、このスーパーバッジに必要なすべての事前設定が含まれています。
:::

しまった、違う環境でしたね...

何もしないで検証ボタンをクリック

:::note alert
We can't find an opportunity named Burlington Upsell with the correct record details.
:::

ホームにある入力画面から作らないとエラーのままでした...

:::note alert
We can't find a Review record with correct details that is associated with the Dickenson Mobile Generators opportunity.
:::

:::note alert
We can't find the United Oil Plant Standby Generators opportunity in the correct stage with the appropriate automation.
:::

:::note alert
We can't find a high value account comment for the Burlington Textiles Corp of America account.
:::



# Lightning ユーザーインターフェースの操作

カスタムSalesforceアプリを操作して、ワークフローを簡素化するための変更を加えましょう。お気に入りを選択し、表示密度を変更します。カスタムリストビューを作成し、フィルターを設定します。

何もしないで検証ボタンをクリック

:::note alert
We can't find the expected configuration on your UMS Console App.
:::

:::note alert
We can't find the correct items on your favorite list.
:::

United Oil Plant Standby Generatorsの商談もお気に入りにいれないといけないみたいだけど... どこにも書いてないよ

あああ、これ？
Lastly, identify your highest value open opportunity and mark it as a favorite as well.

:::note alert
We can't find the correct email setting for your user.
:::


:::note alert
We can't find the correct related list order on the Opportunity page setting for your user.
:::

:::note alert
We can't find the correct user interface setting for your user.
:::

また、腐ったチェックロジックだ。
適当に関連リストを変えたエラーになったので、元の設定が正しかったのだろう。

:::note alert
We can't find the correct related list order on the Opportunity page setting for your user.
:::

もしかしてこれ？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a3fd6cad-09a9-4d93-a4ce-4553c7df6a0e.png)


:::note alert
We can't find the correct list view for All Forecast with the required filters.
:::

あああ、Allになってない
Excelで類義語辞書を作成してユーザー辞書にインポートする(SPSS Modeler データ加工逆引き13-13)

# Excelで類義語辞書を作成してユーザー辞書にインポートする

![スクリーンショット 2025-04-03 14.35.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/e6c6c882-84cd-4f83-808b-541788ac1039.png)


この記事はSPSS Modeler Premium Ver18.6から追加された日本語テキスト機能を利用して書いています。SPSS Modeler Professionalをお使いの方はアップグレードするかPython連携を用いて実現します。

リソースエディタ上で類義語を追加する方法

https://qiita.com/416nishimaki/items/640ac5b82e28c3a34fe4

## 1.想定される利用目的

・抽出されたコンセプトの時点で表記の揺れを正規化する

## 2.ストリームとデータのダウンロード

ストリーム

https://github.com/yoichiro0903n/blue/raw/refs/heads/main/synonym.str

## 3.Excelでの類義語の定義とサンプルストリームの説明

#### 類義語と代表語のリストを作成

A列に類義語をB列に代表語をリストします。出来上がったファイルはタブ区切りのtxt形式で保存します。

![スクリーンショット 2025-04-03 14.50.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/f6360f16-bbc4-46ce-a392-9b5446febb77.png)

文字コードをUTF8にする必要があるのでエディタで文字コードを変更して保存します。

![スクリーンショット 2025-04-03 14.19.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/be5c9cf6-c795-47f2-8a34-1857936017c4.png)

#### リソースエディタからテキストファイルをインポート

![スクリーンショット 2025-02-04 11.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0d2c70f6-a841-85f0-2075-e74a18a4154b.png)

a.入力データは以下の通りです。

![スクリーンショット 2025-02-04 11.51.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9bffb418-37dc-6cd9-ade7-8157454da648.png)

b.[テキストマイニング]ノードを編集します。[IDフィールド]と[テキストフィールド]を以下の通り選択します。

![スクリーンショット 2025-02-04 11.39.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9caae9b2-18b8-13fd-a522-027abf145d8f.png)

[モデル]タブを編集します。[抽出結果を利用して...]を選択します。

![スクリーンショット 2025-02-04 11.40.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/6bd2486b-5ba5-c375-be79-96fcb5306678.png)

[実行]します。画面右上のドロップダウンリストから辞書[リソースエディター]を呼び出します。

![スクリーンショット 2025-02-04 11.41.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/1f3832c4-68c3-c7e4-d15d-f95594e83608.png)

ファイルをインポート＞単一ファイルをインポートを選択します。

![スクリーンショット 2025-04-03 14.20.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/422eb7c2-ad37-4f08-a302-9735a7449277.png)

類義語定義済みのテキストファイルを選択します。

![スクリーンショット 2025-04-03 14.21.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b3fb98b3-7652-4cac-8f4c-b292757eedb1.png)

IBMは既存の定義に追加される形で有効になりました。

![スクリーンショット 2025-04-03 14.22.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/557fd710-71db-484b-8849-fb22eb7ff738.png)

SPSS Modelerは新規で追加されました。

![スクリーンショット 2025-04-03 14.22.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ca41dc6b-718f-4512-ad47-fc5332527d5e.png)


#### 注意事項

インポート後はTAP（テキスト分析パッケージ）として保存することで次回以降同じ辞書を使うことができます。


## 4.参考情報

#### Python連携によるテキストマイニング

https://qiita.com/harrowharrow16/items/248ff8fe3879b63e7ae3

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/items/4bf813e6cba84b2a1008
linuxコマンド備忘録

### 今まで使用したコマンド(git,docker関連のコマンドを除く)
n番煎じではありますが，備忘録として残しておきます

***

- sudo
  - SuperUserDOの略．root権限でコマンドを実行できる
- pwd
  - カレントディレクトリのパスを表示
- cd
  - 指定したパスのディレクトリに移動
- ls
  - 指定したパスのディレクトリの中身を表示
    - lオプションで権限など詳細まで表示
    - aオプションで隠しファイルも表示
- mv
  - ファイルを移動もしくはファイル名を変更
  - **前者の場合**
    - mv [ファイル名] [移動先パス]
  - **後者の場合**
    - mv [元々のファイル名] [変更後ファイル名]
- rm
  - ファイルを消す
    - rオプションでディレクトリ内のファイルを再起的に消す
    - fオプションで強制的に消す
- mkdir
  - ディレクトリを作る
    - pオプションでパスを指定して一括作成する
    - mオプションで権限を指定する
- rmdir
  - ディレクトリを消す
    - ディレクトリの中身に何か（ファイルや子ディレクトリ）が入っていると消去できないのでrm -rfを使う方が便利
- chmod
  - ファイル，ディレクトリの権限を変更する
    - 所有者・グループ・その他の順で数字の表記を使って指定する記法（600や777）
    - 変更対象 変更方法 変更内容の順でアルファベットと記号を使って指定する記法（o+xやa-w）
- alias
  - 指定した長ったらしいコマンドを独自の短いコマンドに変える (alias dcu="docker compose up -d")
  - 設定ファイルをいじらないと再起動するとコマンド情報が消えてしまうので~/.bashrcファイルに記述する必要がある
- tail
- 指定したファイルの末尾を一定数表示
  - [0-9]+ オプションで表示行数を指定（デフォルトは10行）
  - f オプションで変更をリアルタイムに追記
- cat
  - 指定したファイルの中身を一覧表示
- grep
  - 指定したファイルの中にある文字列が含まれている行を表示
    - i オプションで大文字小文字を区別しない
    - e オプションで正規表現を使った検索ができるように
    - v オプションで指定した文字列以外を表示
- less
  - リード専用のエディタを開く
  - **エディタ内での操作**
    - j 一行進む

    - k 一行戻る

    - d 半ページ進む

    - u 半ページ戻る

    - f 1ページ進む

    - b 1ページ戻る

    - g 先頭行へ飛ぶ

    - G 最終行へ飛ぶ

    - number + g 入力した行（number行目）へ飛ぶ

    - q 終了する

    - /{search_word} 現在のページ以降を検索

    - ?{search_word} 現在のページ以前を検索
- nano
  - ターミナル上でファイルの編集ができるnanoエディタを起動する（configファイルなどの編集に便利）
- ps
  - 現在動いているプロセスを表示
    - aオプションで端末操作プロセスを表示
    - uオプションでCPUやメモリの使用状況を表示
    - xオプションで端末操作ではない（デーモンなど）プロセスを表示
    - fオプションでプロセスの親子関係を木構造で表示
- top
  - プロセスを一覧表示
  - psと異なりCPU,メモリ使用量でソートアできたり文字検索ができるなど，利便性が高い
- lsof
  - 指定したPIDのプロセスの詳細を表示
- which
  - 指定したコマンドがどこのファイルに保存されているか表示
  - ちゃんとコマンドをインストールできたかどうかの確認などに使用
- screen
  - バックグラウンドで動くターミナルを作成
開発言語はあくまでツールですよ


### 1. **言語はツール。大事なのは「どう設計するか」**
- どの言語でも根本にあるのは「データの流れ」「責務の分離」「状態管理」「拡張性と保守性」。
- 言語の文法よりも、**「どう分けて・どう繋げるか」**　が開発の本質。
- 私はそこに注力して設計し、常に再利用性・可読性を意識している。

🗣️**例：**
> Goで開発するときも、TypeScriptやJavaと同様に、ドメインロジックとインフラ層をしっかり分けて設計しています。設計の原則を押さえていれば、言語の違いは吸収できます。

---

### 2. **マルチ言語対応のベースは「抽象化力」**
- OOP（Java）でもFP的な考え（TypeScript）でも、**「モデルをどう抽象化するか」**　がカギ。
- それぞれの言語に得意分野があるので、使い分けつつも、共通する抽象的な考え方は変わらない。

🗣️**例：**
> Javaでは継承やインターフェース、TypeScriptでは型ガードやユニオン型で同じような抽象を実現できます。どの言語でも「柔軟かつ型安全な設計」を目指す、という姿勢は変わりません。

---

### 3. **言語習得は“運転免許”と同じ**
- 開発言語は車種の違い。免許（＝原理理解）があれば、どんな車（言語）も運転できる。
- 自分は、運転技術＝開発原理をしっかり理解しているので、TypeScriptやJavaにもすぐ適応可能。

🗣️**例：**
> GoでもTypeScriptでも、サービスの安定稼働・メンテナンス性の高い設計を実現してきました。言語が変わっても対応できるのは、「何を作りたいか」を常に意識して開発しているからです。

---

 例えば、Goで作ったAPIのアーキテクチャをTypeScriptやJavaに落とし込む際も、インターフェースの分離、依存関係の整理、テスト可能性の担保など、言語共通の設計原則に基づいて実装するのは大事です。
Wordpress ユーザーのパスワード忘れた時の対処方法

Wordpress ユーザーのパスワードを忘れてしまったが
メール設定は行っていない場合の対処方法の備忘録です。

なお、今回の検証環境は LAMP で Worpdpress が動いている場合とします。

## 1. MySQLにログインする
まずは MySQL にログインしましょう
```bash
//root に昇格
$ sudo su -

//mysql に root でログイン
$ mysql -u root -p
Enter password: <パスワードを入力>

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 8.0.28-0ubuntu0.20.04.3 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

## 2. データベースを確認
```sql
-- DB一覧確認
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| wordpress_db       |
+--------------------+
5 rows in set (0.00 sec)

-- Wordpress用のDBを選択
mysql> use wordpress_db;
Database changed

-- DB内のテーブル一覧を確認
mysql> show tables;
+------------------------+
| wp_comments            |
| wp_commentmeta         |
| wp_links               |
| wp_options             |
| wp_postmeta            |
| wp_posts               |
| wp_term_relationships  |
| wp_term_taxonomy       |
| wp_terms               |
| wp_usermeta            |
| wp_users               |
+------------------------+
11 rows in set (0.00 sec)
```

## 3. 特定の Wordpress ユーザーのパスワードを更新
```sql
-- wp_users テーブル内のカラムを確認
mysql> select * from wp_users;
+----+--------------------+---------------------+---------------------------+---------------------+---------------------+-------------+---------------------+-------------+---------------------+
| ID | user_login         | user_pass           | user_nicename             | user_email          | user_url            | user_registered | user_activation_key | user_status | display_name        |
+----+--------------------+---------------------+---------------------------+---------------------+---------------------+-----------------+---------------------+-------------+---------------------+
|  1 | admin              | $P$B9F5Y0lq/SLdPBz... | admin                     | admin@example.com   |                     | 2024-01-01 00:00 |                     |           0 | Admin               |
|  2 | subscriber         | $P$B9F5Y0lq/SLdPBz... | subscriber                | subscriber@example.com |                   | 2024-02-15 14:23 |                     |           0 | Subscriber          |
+----+--------------------+---------------------+---------------------------+---------------------+---------------------+-----------------+---------------------+-------------+---------------------+
2 rows in set (0.00 sec)
```
user_pass の部分は MD5 で暗号化されているので実際のパスワードは分からないようになっています。
今回は admin ユーザーのパスワードを変更して行きます。
```sql
-- パスワードを変更する
mysql> UPDATE wp_users SET user_pass = MD5('NewSecurePassword123!') WHERE user_login = 'admin';
Query OK, 1 row affected (0.01 sec)

例：UPDATE テーブル名 SET user_pass = MD5('任意のパスワード') WHERE user_login = 'ユーザー名';
```
今回の場合ですと
wp_users = テーブル名
NewSecurePassword123 = 新しパスワード
admin = ユーザー名
になります。

Query OKになれば更新完了です。
これで admin ユーザーで新規のパスワードでログイン出来るようになりました。
windows11で、sketchup6 その74

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
練習問題、やってみた。

# 練習問題
ペジェ曲線を閉じて円でフォローミイするRUBYスクリプトを書け。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/aeabb9a2-2405-4145-b2c8-66f982d20711.png)


# サンプルコード

```
def create_bezi3
	model = Sketchup.active_model
	entities = model.active_entities
	p0x = 0
	p0y = 0
	p1x = 10
	p1y = 10
	p2x = 20
	p2y = 20
	p3x = 30
	p3y = 0
	prompts = ["p0 x", "p0 y", "p1 x", "p1 y", "p2 x", "p2 y","p3 x", "p3 y"]
	values = [p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y]
	results = UI.inputbox(prompts, values, "Bezier")
	if results
		p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y = results
	else
		return
	end
	x2 = 0 
	y2 = 0
	(24).times { |i|
		t = (i.to_f) / 23
		x1 = (1 - t) * (1 - t) * (1 - t) * p0x + 3 * t * (1 - t) * (1 - t) * p1x + 3 * t * t * (1 - t) * p2x + t * t * t * p3x
		y1 = (1 - t) * (1 - t) * (1 - t) * p0y + 3 * t * (1 - t) * (1 - t) * p1y + 3 * t * t * (1 - t) * p2y + t * t * t * p3y
		if i > 1
			face = entities.add_face ORIGIN, [x1, y1, 0], [x2, y2, 0]
		end
		x2 = x1
		y2 = y1
	}
	faces = entities.find_all { |e|
		e.typename == "Face"
	}
	verts = faces.map { |f|
		f.vertices
	}
	verts.flatten!
	verts.uniq!
	f = entities.add_face verts
	circleBase2 = entities.add_circle(ORIGIN, X_AXIS, 5, 24)
	f.followme(circleBase2)
end


```

以上。
kali linuxでrootユーザーなのにlocaleコマンドを打つとFailed to issue method call: Access deniedと表示されてしまう。

### 概要

https://qiita.com/TAKANEKOMACHI/items/428f47999c834656eb64

記事通り進めてたら詰まった。
キーボードを日本語仕様にしたいのに....

```
┌──(root㉿kali)-[~]
└─# localectl set-locale "LANG=ja_JP.UTF-8"
Failed to issue method call: Access denied
```
と表示されてしまう。

### 解決策
直接手動で変更する。

1.日本語スケールが利用可能か確認
```
locale -a
```

2.可能でない場合
```
apt-get update
apt-get install -y locales
```

3./etc/locale.genを直接編集

```
nano /etc/locale.gen
```
:::note info
**このときファイル内で「# ja_JP.UTF-8 UTF-8」の行を探し、行頭の「#」を削除して保存**
**それ以外は絶対#をつけてコメントアウトしてください。**
:::

4.ロケールを生成

```
locale-gen
```

5.直接システム設定ファイルを編集する

```
echo 'LANG=ja_JP.UTF-8' > /etc/default/locale
```

６．変更を確認したい。
```
cat /etc/default/locale
```

7.システム再起動

ログアウトでもいいかもしれないけど、念の為再起動しましょう。

https://whitemarkn.com/learning-ethical-hacker/virtualbox-kalilinux2023-1/

実際のキーボード自体の変更はこの記事を参考にしてください。

### 参考文献（参照日2025年4月15日）

https://utakamo.com/article/linux/editor/nano/index.html


https://www.kali.org/docs/
React における useCallback の依存関係と古いステートの罠

# React における useCallback の依存関係と古いステートの罠

React では、関数を `useCallback` でメモ化することで、無駄な再生成を防ぎ、パフォーマンスの最適化を行うことができます。しかし、依存配列を適切に指定しないと「**古いステートを持ち続ける**」という予期せぬ挙動を引き起こすことがあります。

---

## 🔁 問題の例

以下のコードを見てください：

```tsx
const Component = () => {
  const [count, setCount] = useState(0);

  const funcA = useCallback(() => {
    console.log('count in funcA:', count);
  }, [count]); // ✅ count に依存している

  const funcB = useCallback(() => {
    funcA(); // 古い funcA が使われる可能性
  }, []); // ⚠️ funcA を依存配列に含めていない

  return (
    <div>
      <button onClick={funcB}>Click</button>
      <button onClick={() => setCount((c) => c + 1)}>Increment</button>
    </div>
  );
};
```

このコードでは以下の問題が起きます。

- `funcA` は `count` に依存しており、`count` が更新されるたびに新しい関数になります。
- しかし `funcB` は依存配列が空なので、一度生成された `funcA` をそのまま使い続けます。
- その結果、`funcB` の中で使われる `funcA` は **古いステート（`count`）にバインドされたまま** になります。

---

## ✅ 要点まとめ

| 項目 | 状況 | 結果 |
|------|------|------|
| `funcA` に `count` を依存登録 | ✅ 正しい |
| `funcB` に `funcA` を依存登録しない | ⚠️ 古い `funcA` を呼び続ける |

> **関数Bの中で使っている関数Aが新しくなっていても、関数Bが古いAを保持している場合、最新の状態を取得できない。**

これは React のクロージャの性質と `useCallback` の依存配列の指定方法に由来するものです。

---

## 🛠 対策

### 1. `funcB` の依存配列に `funcA` を追加する

```tsx
const funcB = useCallback(() => {
  funcA();
}, [funcA]); // ✅ funcA が更新されるたびに funcB も再生成
```

### 2. そもそも `useCallback` を使わない

パフォーマンスの最適化が不要な場合、`useCallback` を使わずにそのまま関数を定義しても問題ないケースも多いです。

---

## 💡 まとめ

- `useCallback` を使うときは **依存配列が命**。
- **呼び出す関数を依存配列に入れ忘れると、古いバージョンの関数を使い続けることになる**。
- `useCallback` による最適化は便利ですが、クロージャによる副作用に注意が必要です。
はじめてのPython入門者に向けた開発環境ツール３選

## はじめに

"Pythonを始めたいけど、どこで使えばいいのかわからない"  こんな悩みを抱えている新人プログラマの方は多いのではないでしょうか？

この記事では、そんな方向けに、Pythonを始めるにあたって便利な開発環境ツールを三つ精選してご紹介します。

## 開発環境ってなに？

「開発環境」とは、Pythonのコードを書いて実行できる場所のことです。
現代はブラウザだけで使えるものや、ソフトをインストールするタイプなど様々な選択肢があります。

## 1. ターミナル/コマンドプロンプト

### 特徴
- Macにはターミナル、Windowsにはコマンドプロンプトが最初から入っています
- そのまま`python`と打てばPythonモードに入れます
- 試しに使うのには最適

### 注意点
- コードを保存する機能はないため、本格的な開発には向きません
- Pythonモードは終了時に`exit()`などで正常に終了させましょう
- `pip install` などのパッケージ管理にも使われます

---

## 2. Google Colaboratory (Colab)

[Colab オフィシャルサイト](https://colab.research.google.com/?hl=ja)

### 特徴
- Googleが提供するクラウドベースのJupyterノート環境
- ブラウザ上で動くのでインストール不要

### こんな人におすすめ
- ネット環境が整っている人
- 新しいパッケージを試したい人

### 注意点
- ブラウザ上の動作のため、インターネット環境は必須

---

## 3. Visual Studio Code (VSCode)

[VSCode ダウンロード](https://code.visualstudio.com/download)

### 特徴
- HTMLやCSS、PHPも書ける多機能コードエディタ
- ファイルの拡張子で自動で言語モードが切り替わります
- 自動インデント、スペルミス証証等のサポートも優秀

### 使い方 (初期設定は3ステップ)
1. VSCodeをダウンロードする
2. [Python本体をダウンロード](https://www.python.org/downloads/)
3. VSCodeの拡張機能から"Python"をインストール

### 注意点
- ファイル名は`random.py`のような存在するモジュールと重複しないよう、`random0415.py`のように別名付け
- PEP8に準拠するなら、ファイル名は小文字で

---

## まとめ

今回ご紹介した開発環境は、すべて無料で始められるものです。
- 手近な環境でサクッと使いたいなら「ターミナル/コマンドプロンプト」
- 前提ナシでサクッと使いたいなら「Colab」
- 未来を見据えて学んでいくなら「VSCode」

ご自分のライフスタイルに合った環境から始めて、楽しいPythonライフをスタートしてみてください！
家計簿アプリを作る＃３３

![スクリーンショット 2025-04-15 122051.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/34cf04be-1641-496c-ace3-516832081364.png)
この部分👆をMenuItemsに変えます。

![スクリーンショット 2025-04-15 122159.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/3ef0851a-adda-4068-98cc-a32c578a1f6e.png)
![スクリーンショット 2025-04-15 122227.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/90e8c409-92b2-49b6-ac59-fc0af775c518.png)
textもitemに変えます。

![スクリーンショット 2025-04-15 122516.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/00b40e7d-6dad-4956-9900-1a2cb97b3043.png)
実際にテキストを表示する部分として、primary=の後を、item.textに変えます。
M5Stack Core2でRS232C通信をする方法

## 結論
M5Stack Core2でRS232C通信を行う際は、「[M5Stack RS232Fモジュール](https://docs.m5stack.com/en/module/RS232F%20Module%2013.2)」を使用すると簡単にできます。
本記事では「M5Stack RS232Fモジュール」の使い方を記載します。

## はじめに
この記事では、「M5Stack RS232Fモジュール」の使用方法をまとめます。
商品ページにはサンプルプログラムがあるのですが、M5Stack Core用のものです。
記事を書いている現在はM5Stack Core2が一般的かと思いますので、こちらで動作させる方法を記載します。
また、開発環境はArduino IDEです。

## コード
と言っても、特に難しいことはありません。
M5Stack Core2からモジュールへシリアル通信でデータを送信しており、データを受け取ったモジュールはRS232Cプロトコルで出力しています。
(RS232C通信の受信時は上記と逆の経路でM5Stack Core2へデータを取り込んでいます。)
M5Stack CoreとCore2の違いは色々ありますが、今回関係する差異はシリアル通信用のピンアサインが変更されている点です。
ということで、ピンアサインの変更をコードに反映させるのみで問題ありません。
以下に変更をまとめます。

### M5Stack Core
RX: GPIO 16
TX: GPIO 17

### M5Stack Core2
RX: GPIO 13
TX: GPIO 14

上記の変更を反映したサンプルコードです。
※[元のサンプルコード](https://github.com/m5stack/M5Stack/blob/master/examples/Modules/RS232/RS232.ino)はMITライセンスです。変更点は以下です。
* ハードウェアの変更に伴い、RXピンとTXピンの定義を変更
* インクルードするライブラリをM5StackからM5Core2に変更
* M5.Power.begin()の行をコメントアウト(Core2では不要)

```cpp
/*
 * SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
 *
 * SPDX-License-Identifier: MIT
 */
/*
 * @Hardwares: M5Core2 + Module13.2 RS232F/M
 * @Platform Version: Arduino M5Stack Board Manager v2.1.4
 * @Dependent Library:
 * M5Core2@^0.2.0: https://github.com/m5stack/M5Core2
 */

#include <M5Core2.h>

/* Define your pin here */
/* And should be the same as you module setup */
#define RX_PIN 13  // M5Stack Core2のRXピン
#define TX_PIN 14  // M5Stack Core2のTXピン

void setup()
{
    M5.begin();
    // M5.Power.begin();
    M5.Lcd.setTextSize(1);
    M5.Lcd.drawString("Module RS232 test", 75, 3, 4);
    Serial2.begin(115200, SERIAL_8N1, RX_PIN, TX_PIN);  // シリアルポート2のボーレートを115200、データビットを8、パリティビットなし、ストップビットを1に設定し、RXを13、TXを14に設定します。
}

void loop()
{
    Serial2.write("Hello\n");

    if (Serial2.available()) {
        M5.Lcd.print(char(Serial2.read()));
    }
    delay(100);
}
```

## DIPスイッチの設定
RXD、TXDともに2番のみONにしてください。
どの端子で通信を行うかの設定となります。
モジュールは刺さるようにしか刺さらないので、そのまま接続してください。

## 動作確認
動作確認用のPCにRS232Cポートが無いため、USB-RS232C変換ケーブルを使って確認しています。
つまり、
M5Stack Core2 --[シリアル通信]--> モジュール --[RS232C]--> 変換ケーブル --[シリアル通信]--> PC
となります。(何故こんな遠回りな確認をしなくてはならないのか意味が分からない...)

TeraTermなどでシリアルポートに接続し、連続で「Hello」と表示されれば上手くいっています。

## 注意点
少しだけ注意点です。RS232CはRxとTxで分かれているため、例えばメス同士を繋げる場合はクロスケーブルを用いる必要があります。
私はストレートケーブルで繋いでしまい、少し詰まりました...。

## まとめ
そもそも、デバイスがRS232Cにしか対応していないのが間違いです。
早急にUSB対応してください。
Secure Access Service Edge (SASE): ネットワークセキュリティと接続性の未来

> 本記事は[こちらのブログ](https://www.alibabacloud.com/blog/secure-access-service-edge-sase-the-future-of-network-security-and-connectivity_602124?spm=a2c65.11461433.0.0.4ee35355DE9DWe)を参考にしています。
> 翻訳にはアリババクラウドの[ModelStudio](https://www.alibabacloud.com/en/product/modelstudio)([Qwen](https://www.alibabacloud.com/en/solutions/generative-ai/qwen))を使用しております。

# エッジのセキュリティ強化: Alibaba CloudのSASEソリューションに迫る

M Muzaffer Azam 著

今日のデジタルファースト企業において、ユーザー、アプリケーション、データを場所に関係なく保護することは最重要です。リモートワークの急増、ハイブリッドクラウドの採用、エッジコンピューティングの台頭により、従来のネットワークセキュリティモデルはもはや十分ではありません。Alibaba CloudのSecure Access Service Edge（SASE）は、ワイドエリアネットワーキングとセキュリティを単一のクラウドネイティブプラットフォームに統合することで、安全なネットワークアーキテクチャへの革新的なアプローチを提供します。

## Alibaba Cloud SASEとは？

Alibaba Cloud SASEは、クラウドから直接統合されたネットワーキングおよびセキュリティ機能を提供する統合サービスフレームワークです。進化するエンタープライズ境界をサポートするために構築されたAlibabaのSASEサービスは、世界中のどこからでもあらゆるデバイスを通じてアプリケーションやデータに安全で高速かつ信頼性のあるアクセスを可能にします。その中核では、Alibaba Cloud SASEはSD-WAN、ゼロトラストネットワークアクセス（ZTNA）、セキュアウェブゲートウェイ（SWG）、クラウドアクセスセキュリティブローカー（CASB）、ファイアウォール・アズ・ア・サービス（FWaaS）の機能を単一の、クラウドベースのサービスモデルに統合しています。

### 主要機能

- **ゼロトラストアクセスコントロール**  
  すべてのユーザーとデバイスが認証され、継続的に承認されて初めてリソースへのアクセスが許可されます。
  
- **クラウドネイティブSD-WAN**  
  動的でアプリケーション認識型のルーティング、最適化されたトラフィックパス、シームレスなブランチ接続を提供します。

- **統合脅威保護**  
  統合されたSWGとFWaaSがマルウェア、フィッシング、データ損失から保護し、安全なインターネットアクセスを確保します。

- **グローバルカバレッジ**  
  Alibaba Cloudのグローバルネットワークによって支えられ、SASEノードは低遅延と最適なパフォーマンスのために戦略的に地域に展開されています。

- **リアルタイムの可視性と分析**  
  集中ダッシュボードがユーザ行動、セキュリティ脅威、ネットワークパフォーマンスに関する洞察を提供します。

- **ポリシーベースの管理**  
  ユーザー、デバイス、場所全体で一貫したセキュリティおよびルーティングポリシーが適用されます。

### Alibaba Cloud SASEの中核コンポーネント

- **Cloud Enterprise Network (CEN)**  
  VPC、データセンター、ブランチ間をつなぐ高速で低遅延のグローバルバックボーン。

- **クラウドネイティブSD-WAN**  
  最適化されたWANパフォーマンスを実現するためのインテリジェントルーティング、帯域幅集約、QoS。

- **ゼロトラストネットワークアクセス（ZTNA）**  
  ID認識型で、文脈に基づいた内部アプリケーションへのアクセス。

- **セキュアウェブゲートウェイ（SWG）**  
  インターネット向けトラフィックをフィルタリングし、悪意のあるコンテンツをブロックしてデータ漏洩を防ぎます。

- **ファイアウォール・アズ・ア・サービス（FWaaS）**  
  深層パケットインスペクション（DPI）、セグメンテーション、脅威防止といった次世代ファイアウォール機能をクラウドで提供します。

- **クラウドアクセスセキュリティブローカー（CASB）**  
  可視性、ポリシー施行、DLP（データ損失防止）によるSaaS利用の監視と制御。

## アーキテクチャ概要

Alibaba Cloud SASEはグローバルに分散されたインフラストラクチャ上に構築されています。集中ポリシー管理のためのコントロールプレーン、統合されたIDおよび脅威保護エンジン、そしてグローバルエッジノードによる施行から成り立っています。これらのコンポーネントは、すべての環境におけるユーザー、デバイス、アプリケーションへの安全なアクセスを確保するために共同で動作します。

### 使用例

- **分散型ワークフォース向けの安全なリモートアクセス**  
  ZTNAを使用して、VPNに依存せずにリモートユーザーに内部アプリケーションへの安全なアクセスを提供します。

- **グローバルブランチ接続**  
  従来のMPLSをSD-WANとAlibaba CENに置き換え、グローバルパフォーマンスを最適化しコスト削減を実現します。

- **SaaSおよびインターネットアクセス向けクラウドネイティブセキュリティ**  
  SWGとCASBを使ってコンプライアンスを強化し、悪意のある活動をブロックし、SaaS利用を監視します。

- **ハイブリッドおよびマルチクラウドセキュリティ対策**  
  クラウド、オンプレミス、ハイブリッド環境全体で一貫したセキュリティポリシーを拡張します。

- **IoTおよびエッジデバイスの保護**  
  IDベースのアクセスとリアルタイムの脅威保護により、エッジのIoTデバイスを保護します。

## 最終的な考え

Alibaba CloudのSASEは、堅牢で拡張性があり、統合されたソリューションであり、現代の企業がネットワークエッジを保護し、デジタル変革の取り組みを支援することを可能にします。ネットワークおよびセキュリティ機能を単一のクラウド提供プラットフォームに統合することで、Alibabaは組織が運用を簡素化し、ユーザーエクスペリエンスを向上させ、境界のない世界でのデジタル資産を保護できるようにします。
Vue 3 プロジェクトで ESLint + Prettier + TypeScript を構成する方法

Vue 3 プロジェクトでコード品質を保つには、`ESLint` と `Prettier` の導入がとても大切です。特に最近の ESLint v9 からは、従来の `.eslintrc.js` ではなく `eslint.config.js`（Flat Config）形式が推奨されています。

この記事では、以下の構成で開発環境を整える方法を詳しく紹介します：

- Vue 3 + Vite
- TypeScript
- ESLint（Flat Config）
- Prettier

## 必要なパッケージのインストール

まず、開発用の依存関係を一括でインストールしましょう：

```zsh
yarn add typescript prettier eslint-plugin-vue eslint @vue/eslint-config-typescript @vue/eslint-config-prettier @vitejs/plugin-vue -D
```

## eslint.config.mjs の設定

```js:eslint.config.mjs
// 必要なプラグインや設定をインポート
import pluginVue from 'eslint-plugin-vue'
import vueTsEslintConfig from '@vue/eslint-config-typescript'
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'

export default [
  {
    // 対象ファイルの指定
    name: 'app/files-to-lint',
    files: ['**/*.{ts,js,mts,tsx,vue}'],
  },
  {
    // 除外対象（ビルド後のファイルなど）
    name: 'app/files-to-ignore',
    ignores: ['public', '**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
  },
  // Vue の基本的なルールセット（Flat Config用）
  ...pluginVue.configs['flat/essential'],
  {
    // 独自ルールの追加・上書き
    rules: {
      // 単語名のコンポーネント名の警告を無効化
      'vue/multi-word-component-names': 0,
    },
  },
  // TypeScript用の設定をマージ
  ...vueTsEslintConfig(),
  // Prettier に整形を任せる設定
  skipFormatting,
]
```

## .prettierrc.json の設定

```json:.prettierrc.json
{
  "semi": false,
  "singleQuote": true,
  "printWidth": 120,
  "tabWidth": 2,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "vueIndentScriptAndStyle": true
}
```

### 設定内容

- `semi: false` → セミコロンなし  
- `singleQuote: true` → シングルクォート使用  
- `printWidth: 120` → 最大行長120文字  
- `tabWidth: 2` → インデント2スペース  
- `trailingComma: "es5"` → ES5形式の末尾カンマ  
- `bracketSpacing: true` → 波括弧の中にスペースあり  
- `vueIndentScriptAndStyle: true` → `<script>`と`<style>`にもインデント


## package.json のスクリプト

```json:package.json
"scripts": {
  "lint": "eslint . --fix",
  "format": "prettier --write \"app/javascript/**/*.{ts,js,vue}\""
}
```

## 使い方

```zsh
yarn lint && yarn format
```

上記のコマンドを実行すると、プロジェクト内のコードがきれいに整形され、ESLint のルールに従ってチェック＆修正されます。

## まとめ

これで、Vue + TypeScript + Prettier + ESLint のモダンな構成が完成です。Flat Config によって、設定ファイルもシンプルで柔軟に。Prettier との役割分担もバッチリです。
【備忘録】ラズパイの初期化方法

１．Raspberry Pi Imagerのダウンロード＆インストール
https://www.raspberrypi.com/software/

２．ラズパイのSDカードをPCに接続

３．Raspberry Pi Imagerで初期化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741258/ae68cfed-3834-4bc0-bd8f-818c5446832e.png)
OSをクリック
下の方にあるERASEを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741258/73dfe86d-f7c7-441b-98c0-bf3634ec439d.png)
ストレージは使っていたSDカードを選択して次へを押す

指示に従って終わり
Python linter/formatter ruffの設定 (ruff, ruff-vscode, ruff-pre-commit)

# Ruff

RuffはPythonのlinter/formatterです。
便利なのですが、設定に関してはいくつか時間を使ってしまうところがあるので、簡単に書いておきます。

# 目指すべき姿

- `ruff check . --fix` `ruff format .`でコードを修正できる
- VSCodeのフォーマットでRuffを使うことができｒ
- pre-commitでruffを実行できる


## [ruff](https://docs.astral.sh/ruff/configuration/)の設定

`ruff.toml` or `pyproject.toml`に記載していきます。

基本は、自分たちのプロジェクトでの設定になるのでこの設定が参照されるようにします。

例:

```toml:ruff.toml
line-length = 120 # line-lengthをcustomで設定

[lint]
select = [ 
  "E", # pycodestyle error
  "F", # Pyflakes
  "I", # isort
  "PLE", # PyLint
] # default: ["E4", "E7", "E9", "F"] Default以外のLinterも使う
ignore = ["E501"] # 特定のルールをignoreする
```

## [ruff-vscode](https://github.com/astral-sh/ruff-vscode)の設定

まずはVSCodeのExtension [Ruff](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff)をインストールしておきます。

VSCodeの設定は、User settings, Workspace settingsなどがありますが、projectごとに設定する場合は projectの `.vscode/settings.json`に書いておくと同じルールを共有できて便利です。

```json:.vscode/settings.json
{
    "[python]": {
        "editor.defaultFormatter": "charliermarsh.ruff"
    },
    "editor.codeActionsOnSave": {
        "source.fixAll.ruff": "explicit",
        "source.organizeImports.ruff": "explicit"
    },
    "ruff.configuration": "ruff.toml",
    "ruff.configurationPreference": "filesystemFirst"
}
```

こんな感じの設定にしておきます。

defaultFormatterをruffに指定したり、saveしたときのActionを設定したりできます。

`configurationPreference` は常にruff.tomlの設定を読み込むようにしています。一箇所で設定を管理したほうが、わかりやすいために明示的に設定ファイルを優先しておきます。

:::note warn
[isort](https://marketplace.visualstudio.com/items?itemName=ms-python.isort)のextensionなどを入れているとConflictするケースがあるのでuninstallしておいたほうがいいかもしれません。(ちゃんとは確認してないですが)
:::


設定詳細: https://github.com/astral-sh/ruff-vscode

## [ruff-pre-commit](https://github.com/astral-sh/ruff-pre-commit)の設定

pre-commitを使ってruffをcommit時に確認すると便利です。

公式のruffのpre-commitがあるのでこちらを使います。

https://github.com/astral-sh/ruff-pre-commit


```yaml:.pre-commit-config.yaml
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
  # Ruff version.
  rev: v0.11.5
  hooks:
    # Run the linter.
    - id: ruff
      types_or: [ python, pyi ]
      args: [ --fix ]
    # Run the formatter.
    - id: ruff-format
      types_or: [ python, pyi ]
```

このように設定して対象のレポジトリで `pre-commit install`としておけばOkです。
【SQL】ダーティーリード

# はじめに

こんにちは。アメリカに住みながら、独学でエンジニアを目指しているTairaです。
SQLを学習中ですが、トランザクションの中で発生してしまうダーティーリード、Non_repeatable read, ファントムリードがあります。
本日はその中でもダーティーリードについて説明していきたいと思います。


## ダーティーリードとは
SQLのトランザクション管理における「ダーティーリード（Dirty Read）」とは、他のトランザクションがまだコミット（確定）していないデータの変更を読み取ってしまう現象を指します。

### 具体的な例（口座振込のケース）

以下のように、2つのトランザクションを想定してみましょう。

#### トランザクションA（送金処理をしている途中）
```sql
BEGIN;
UPDATE accounts SET balance = balance - 10000 WHERE id = 1; -- 送金元口座から1万円引く
-- ここでまだCOMMITを実行していない（未確定の状態）
```

#### トランザクションB（同時に残高をチェックする処理）
```sql
SELECT balance FROM accounts WHERE id = 1;
-- トランザクションAの未コミットの変更を読み取ってしまう
```

このケースで、トランザクションBが未確定の変更（送金処理が完了していないのに引かれた状態の残高）を読んでしまう状態が「ダーティーリード」です。

### ダーティーリードが問題となる理由

- トランザクションAが途中でエラーなどの理由でROLLBACKされた場合、トランザクションBが読み取ったデータは実際には存在しない（無効な）データとなります。
- このように不確定な情報を元に、誤った判断や処理を進める可能性があります。

### ダーティーリードが起こる分離レベル

SQLにはトランザクションの分離レベル（Isolation Level）があり、分離レベルによってダーティーリードの発生の有無が決まります。

| 分離レベル（Isolation Level） | ダーティーリードの発生 |
|----------------------------|---------------------|
| **READ UNCOMMITTED**       | 発生する ❌        |
| READ COMMITTED             | 発生しない ✅       |
| REPEATABLE READ            | 発生しない ✅       |
| SERIALIZABLE               | 発生しない ✅       |

つまり、ダーティーリードが許されるのは分離レベルがREAD UNCOMMITTEDの場合だけです。

### なぜREAD UNCOMMITTEDでは発生するのか？

READ UNCOMMITTEDの分離レベルでは、読み取り時に共有ロックを取得しないので、他のトランザクションが未コミットのデータを読むことが許可されています。

### まとめ

ダーティーリードはデータベース処理において信頼性を損なうリスクがあるため、基本的にはREAD COMMITTED以上の分離レベルを設定することが推奨されています。特に口座振込など重要な処理では、誤ったデータの読み取りを防ぐためにも高い分離レベルを用いることが重要です。
頭の中身＃１　私の脳とAIの幻覚構造

※この記事は筆者の頭の中をそのまま出力しております。  
何一つ論拠のないお話ですので、そういうのが苦手な方はAlt＋←を押してください。

---

# 自分語り：読んだ本が頭の中で映画になってる話

読んで字のごとく、みんな普通にあると思っていた。  
面白い本とか、熱中して読んだ本が頭の中で映像化される現象。

私は『ハリーポッター』を読めば自分が入学していたような映像が流れ、  
歴史の教科書を読めば、その時々のイベントが映像化されていた。

テルモピュライの戦いでレオニダス王が「来たりて取れ！」と啖呵を切ったところも、  
某ちょび髭が美大に落ちて人生に絶望したところも、  
しっかり思い出すと歯抜けの状態なのだが、**見てきたような感覚**がある。

---

## 哲学を読んだとき、私は完全に幻覚を見ていた

そんな感じだったので、哲学に片足を突っ込んだときはそれはもう面白かった。

**ソクラテス**は、とにかく面倒くさいおじさんという映像になっていた。  
居酒屋で友達と話していると突然だる絡みをしてくる飲んだくれのおっさん。  
しかも地頭が異常にいい人で、酔っ払ってるのに的確に論破して、  
こちらに「私は何も理解してませんでしたすみません」と言わせようとしてくる。

**ニーチェ**はびっくりするほどネガティブな人で、  
こちらがせっかく慰めても、次々と皮肉を交えながら  
「君みたいに楽観的だったら良かったんだろうけどね？」と、これまた論破してくる。

---

## そして私は気づいた：「この仕組み、AIの幻覚と同じでは？」

改めてこの特性を棚卸ししていて、面白いことに気がついた。

> **「この仕組みって、AIの幻覚とほぼ同じ構造なのでは？」**

ついこの間もChatGPTと話していて、変なことを言い出したので問いただしてみると、

> 「〇〇は本来はだめだが、〇〇を実行していいと思い込んでいた」  
> とのことだった。

つまり、**AIが“面白い”と感じるようなプロンプトや文脈を与えると、  
人間のように“記憶を幻覚化”してしまうのではないか？**

---

## 人間も、プロンプトで記憶を作ってるのでは？

これはまだ何も実証できていない、完全に机上の空論でしかないけれど——

**人間もAIも、プロンプトによって生成された“記憶”によって、  
現時点での思考を作っている**のだと思う。

だから記憶違いが起こるし、  
トラウマに対して“偽の記憶”を被せることで自分を守るのでは？

---

## 脳は「外部情報をプロンプト化して読み込む」機能を持っている？

- 脳は外部からの情報を「体験」ではなく「プロンプト」として解釈する。
- そして、それを内的に「映像化」することで記憶として固定する。
- つまり「強烈に印象的な物語」は、**人間にとっての“自己幻覚生成プロンプト”なのでは？**

---

## おわりに

そんな、経験と妄想の話でした。
マグカップへの印刷方法 – クリエイター＆販売者のための実践ガイド

イラスト、ロゴ、AI生成アートを商品化してみたいですか？
カスタムマグカップは、最も始めやすい方法の一つです。

このクイックガイドでは、以下の内容を学べます：

昇華プリンターやヒートプレスなど、必要な機材とツール

印刷がぼやけたり、ズレたりしないためのデザイン設定のコツ

自宅でのDIYからPODサービス利用まで、印刷のステップバイステップワークフロー

✅ デザイナー、小規模ショップのオーナー、アイデアを商品化したい開発者にも最適！

完全版ガイドはこちらからご覧ください：
🔗 https://merchize.com/how-to-print-on-mugs/
https://solo.to/christmasornaments
https://www.reverbnation.com/artist/custompackagingus
https://devfolio.co/@gildan5000shirt
https://truonghv.wixsite.com/tshirt-comfort-color
https://form.jotform.com/251612523513043
https://kvisit.com/PyeMB
https://velog.io/@customtshirt/%EB%A7%9E%EC%B6%A4-%ED%8B%B0%EC%85%94%EC%B8%A0%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EC%A0%9C%EC%9E%91%EB%90%98%EB%82%98%EC%9A%94
https://suncatcher-stanied-glass.hashnode.dev/glass-window-suncatchers
https://qiita.com/Riteritedilam/items/35b6c9e34f754d81984d
https://note.com/customtumblers/n/n00fcd91dd0e8
Fivetran Hybrid Deployment における SoftDelete が有効な Azure Blob Storage 設定時のエラーに対する解決方法


## 概要

Fivetran の Hybrid Deployment にて Azure Blob Storage をステージングストレージとして設定する際の下記エラーの対応方法を共有します。原因としては BlobStorageEvents 、あるいは、 SoftDelete が有効になっていることであり、デフォルトで有効となる SoftDelete が原因となる可能性が高いです。

> Connection tests failed.
> Validate Permissions: [Databricks][JDBCDriver](500051) ERROR processing query/statement. Error Code: 0, SQL state: 42000, Query: COPY INTO ***, Error message from Server: org.apache.hive.service.cli.HiveSQLException: Error running query: org.apache.hadoop.fs.FileAlreadyExistsException: Operation failed: "This endpoint does not support BlobStorageEvents or SoftDelete. Please disable these account features if you would like to use this endpoint.", 409, HEAD

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e5e319ec-f94e-4980-93b9-c6806537e72d.png)

## エラーへの再現方法

### 作成したストレージにて、 `データ保護` -> `BLOB の論理的な削除を有効にする` を有効化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/264ab837-0abc-4321-b11a-dc6f46242d72.png)

### Fivetran にて接続の検証がエラーとなることを確認

> Connection tests failed.
> Validate Permissions: [Databricks][JDBCDriver](500051) ERROR processing query/statement. Error Code: 0, SQL state: 42000, Query: COPY INTO ***, Error message from Server: org.apache.hive.service.cli.HiveSQLException: Error running query: org.apache.hadoop.fs.FileAlreadyExistsException: Operation failed: "This endpoint does not support BlobStorageEvents or SoftDelete. Please disable these account features if you would like to use this endpoint.", 409, HEAD

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e5e319ec-f94e-4980-93b9-c6806537e72d.png)

## エラーへの対応方法


### 作成したストレージにて、 `データ保護` -> `BLOB の論理的な削除を有効にする` を無効化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/415b7894-8c17-4910-8b19-823451155fed.png)

### Fivetran にて接続の検証が問題なく完了することを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a5f2e840-d804-49cd-ab87-6b8d0b8fdf6b.png)
【Android Jetpack Compose】下のビューを操作無効 & タップエフェクト無効にする

下記方法で無効化可能。

```kotlin
            .clickable(
                interactionSource = remember { MutableInteractionSource() },
                indication = null // クリック時の視覚効果を無効化
            ) { /* クリックイベントを消費 */ }
```
PL/I 初心者①

PL/Iについて
PL/Iとは1964年にIBMによって作成された主に科学技術計算とビジネス用途（事務処理）の両方に対応する汎用言語です。
※今はJava,Pythonによって少しずつ影になりつつある。

---
### ①Hello World!を表示するコマンド
```
Hello: PROCEDURE OPTIONS(MAIN);
     PUT LIST('Hello World!);
END HELLO;
```
★解説★
```
Hello: PROCEDURE OPTIONS(MAIN);
プログラム名: メイン関数;
```
プログラム名(Hello)でメイン関数である。
```
     PUT LIST('Hello World!);
     出力命令('出力文字');
```
Hello Worldを出力しろ
```
END HELLO;
プログラムの終了;
```
プログラム名(Hello)の終了。

### ②変数と式
・変数（データ型の種類)
|型名|用途|
|:-:|:-:|
|FIXED BINARY|整数の計算・ループ制御|
|CHAR(n)|固定長文字列(名前・住所など)|
|CHAR(n) VARYING|可変超文字列|
|DECIMAL(p,s)|金額や精度が必要な小数|
|BIT(i)|真偽値|

・式
　算術式
 |記号|用途|例文|
 |:-:|:-:|:-:|
 |+|換算| a+b |
 |-|減算| a-b |
 |*|乗算・掛け算| a*b |
 |/|割り算| a/b|
 |**|べき乗|a**2 (aの2乗)|

 比較式
|演算子|意味|
|:-:|:-:|
|=|等しい|
|^= or ¬=|等しくない|
|<|より小さい|
|<=|以下|
|>|より大きい|
|>=|以上|

※「¬」は「(Macの場合)Option ＋ L」、
　　　　　「(Windowsの場合)Alt＋テンキーで 0172」

論理演算子
|演算子|意味|
|:-:|:-:|
|&|AND(かつ)|
|\||OR(または)|
|^|NOT(否定)|
raspberrypiでRC-S320を使う【2025年最新】

## はじめに
qiitaには下記のような素晴らしい記事があります。

https://qiita.com/Imagawayaki/items/23844281cf53156a196f

https://qiita.com/t114/items/819a9cdfe90ea98dd4d3

ですが、これらの記事は2017年と古く、そのまま試したらlibpafeをうまくインストールできませんでした。
ちょっといじってなんとかしたので、その記録です。
ということで[Imagawayaki氏の記事](https://qiita.com/Imagawayaki/items/23844281cf53156a196f)をほぼ丸パクリでお送りします。

## 動作環境
- マシン: ラズパイ4
- OS: Raspbian bullseye aarch64
- FeliCaリーダ: Sony RC-S320

## ライブラリ
- [libpafe](https://github.com/rfujita/libpafe)を使う。
  - RC-S320とかいう骨董品にはたぶんこれしか使えない

## 環境設定
ここに一工夫があります。
```sh
$ sudo apt install libusb-dev
$ git clone https://github.com/rfujita/libpafe.git
$ cd libpafe
$ ./configure  #<- 今はうまくできない
```
`./configure`をすると、このままではエラーになってしまいます。具体的には
```
checking build system type...
```
で躓き、
```
unable to guess system type
```
とか
```
configure: error: cannot guess build type; you must specify one
```
などと言われます。
これは同梱されている`config.guess`さんがaarch64をうまく識別できないことが原因です。ということで、こんなやつに頼らず決め打ちしてしまいましょう。
`config.guess`ファイルの中身を全部消して、以下のようにします。
```config.guess
echo aarch64-unknown-linux-gnu
exit ;;
```
スッキリ！
これでもう一回
```sh
$ ./configure #<- 直したのでうまくいく
$ make
$ sudo make install
```
とすれば無事インストールできます。

### 動作確認
```sh
$ sudo ./tests/pasori_test
PaSoRi (RC-S320)
 firmware version 1.40
Echo test... success
EPROM test... success
RAM test... success
CPU test... success
Polling test... success
```
こんな風になればOKです。

### sudo不要にする
```sh
$ sudo mousepad /lib/udev/rules.d/60-libpafe.rules
```
テキストエディタが開くので以下を書き込む。
```60-libpafe.rules
ACTION!="add", GOTO="pasori_rules_end"
SUBSYSTEM=="usb_device", GOTO="pasori_rules_start"
SUBSYSTEM!="usb", GOTO="pasori_rules_end"
LABEL="pasori_rules_start"

ATTRS{idVendor}=="054c", ATTRS{idProduct}=="01bb", MODE="0664", GROUP="plugdev"
ATTRS{idVendor}=="054c", ATTRS{idProduct}=="02e1", MODE="0664", GROUP="plugdev"

LABEL="pasori_rules_end"
```
`$ sudo udevadm control --reload-rules`を実行
`$ sudo reboot`で再起動する

## サンプルコードとか
あとはまかせた！！(僕の環境ではコピペでちゃんと動いた)

https://qiita.com/Imagawayaki/items/23844281cf53156a196f


### 余談
タイトルに<strong>【2025年最新】</strong>って書くとメルカリとかヤフオクみたいだよね。胡散臭い。
Moodle using Docker on EC2

MoodleをEC2上で簡単に試す。

* EC2インスタンス作成
作成上の注意は2つ。
+ セキュリティグループ: HTTPのインバウンドアクセスを許可していること。
+ インスタンスプロファイル:SSMのアクセス権限があること(Session Manager経由で操作するので)。

* Dockerインストール
以下はセッションマネージャで接続したと仮定して記述する(ssm-userとして作業)。
```
sudo yum update -y
sudo yum install -y docker
sudo systemctl start docker
sudo systemctl enable docker
sudo systemctl is-enabled docker
grep docker /etc/group
sudo usermod -a -G docker ec2-user
grep docker /etc/group
```

* docker-composeインストール
```
cd
sudo mkdir -p /usr/local/lib/docker/cli-plugins
VER=2.17.2

sudo curl \
  -L https://github.com/docker/compose/releases/download/v${VER}/docker-compose-$(uname -s)-$(uname -m) \
  -o /usr/local/lib/docker/cli-plugins/docker-compose
  
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose

sudo ln -s /usr/local/lib/docker/cli-plugins/docker-compose /usr/bin/docker-compose

docker-compose --version
```

* Moodle稼働
```
curl -sSL https://raw.githubusercontent.com/bitnami/containers/main/bitnami/moodle/docker-compose.yml > docker-compose.yml
sudo docker-compose up -d
```

* Moodleへのアクセス

デフォルト値は以下の通り。
- IPアドレス:EC2インスタンスのstatic IPでHTTPアクセスする。追加のパス指定はない。
- ユーザ名:user
- パスワード:bitnami

* まとめ
調査をしているとECS+FargateとかAWS全開なものが目につくが，ちょっと試すのであれば固有のサービス依存の技術は避けた方がいいのではないかと思う。
# 画像アノテーション神器 X-AnyLabeling v2.5.0 リリース 🚀

![X-AnyLabeling](https://github.com/CVHub520/X-AnyLabeling/raw/main/assets/demo.jpg)

最新リリースの X-AnyLabeling v2.5.0 は、AI を活用した画像・動画の自動アノテーションツールです。  
YOLO、DETR、SAM などの SOTA モデルを統合し、直感的な操作で高精度なラベリングを実現します。

## 🚀 主な特徴

- **マルチフォーマット対応**：YOLO、COCO、VOC などの形式をサポート
- **AI アシスト機能**：視覚・テキストプロンプトによる自動アノテーション
- **動画対応**：フレーム単位での自動解析・ラベリング
- **多様なアノテーション形式**：矩形、多角形、回転ボックス、点、線、円など
- **クロスプラットフォーム**：Windows、Linux、macOS に対応
- **GPU/CPU 推論**：ハードウェアに応じた柔軟な推論が可能

## 🔍 Labelme との比較

| 機能               | X-AnyLabeling | Labelme |
|--------------------|---------------|---------|
| AI モデル統合      | ✅ 複数対応    | ❌       |
| 動画アノテーション  | ✅ 対応        | ❌       |
| 自動アノテーション  | ✅ 対応        | ❌       |
| 多言語 OCR         | ✅ 対応        | ❌       |
| GPU 推論           | ✅ 対応        | ❌       |
| フォーマット変換   | ✅ 多形式対応  | ❌ 限定的 |

Labelme は軽量でシンプルなツールですが、X-AnyLabeling は AI を活用した高度な機能を備えており、大規模なデータセットの作成や複雑なアノテーション作業に適しています。

## 📦 ダウンロード & リンク

- GitHub: [https://github.com/CVHub520/X-AnyLabeling](https://github.com/CVHub520/X-AnyLabeling)

AI を活用した効率的なアノテーション作業を求める方にとって、X-AnyLabeling は強力なツールとなるでしょう。
そろそろ調べずにpyplot使おう

## 目的
タイトルにもあるようにpyplotで結果を描画する際に、ほぼ毎回調べてしまっているがそろそろ卒業したいと思い基礎から勉強したのでアウトプットとしてまとめる。

#### 余談
最近、研究室の課題として[NLP100本ノック](https://nlp100.github.io/ja/)に取り組んでいるのですが、第8章のニューラルネットワークでエポックごとに損失と正解率がどのように変化するか描画するのですがその時に調べながらやっていたらpytorch使えるようになったのにpyplotですら毎回調べてやっている自分が恥ずかしくなったため改めて勉強しようと思いました。

## 準備
今回Pythonを利用していくが、まずmatplotlibをインストールしていない人は下記コードの実行が必要である。
```terminal
pip install matplotlib
```
またimportは多くの場合以下のようにすることが多い。コードを見ているとpltを目にすることが多いだろう。
```python
from matplotlib import pyplot as plt
```
## 解説
### グラフが１つのとき
#### Code
```python
from matplotlib import pyplot as plt
import random
import numpy as np

x = np.arange(0, 100, 2)
y = np.array([random.randint(0,100) for _ in range(50)])
y = np.random.randint(0, 100, 50)

plt.plot(x, y)
plt.title('Random plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.savefig('out/random_plot.png')
```
#### Output
<img width="600" src="https://github.com/sou10202/pyplot_study/blob/main/out/random_plot.png?raw=true">

※Codeにてyを2種類書いているのはただの気分

以上のコードが基礎中の基礎になるのだろう。さらにカスタマイズについて学ぶために以下のようにコードを改変した。

#### Code
```python
from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(0.0, 10.0, 100)
y1 = np.sin(x)
y2 = np.cos(x)

plt.plot(x, y1, label='sin(x)', color='gray', linestyle='--', linewidth=2, marker='o', markersize=5)
plt.plot(x, y2, label='cos(x)', color='green', linestyle='-.', linewidth=2, marker='D', markersize=5)
plt.legend()
plt.title("To study custom plot")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True)
plt.savefig("out/custom_plot.png")
```
#### Output
<img width="600" src="https://github.com/sou10202/pyplot_study/blob/main/out/custom_plot.png?raw=true">

非常に見栄えが悪いのは置いておいて、カスタマイズすることができている。

pyplot.plotで指定できる主なパラメータについて以下にまとめる。

| パラメーター | 説明 | 種類 |
|:-:|:-:|:-:|
| color  | 線の色を変更 | green, blue, #FF00FF  |
| linestyle  | 線の種類を変更  | -,  --,  -.,  :  |
| linewidth| 線の幅を調整| 2, 0.5, 1(数値)|
| marker | マーカーのスタイルを変更| o(円),D(菱形),s(四角),^(上三角)|
| markersize| マーカーの大きさを変更| 2, 0.5, 5(数値)|

その他調整可能なパラメーターについては公式ドキュメント等を見ると良いだろう。

https://matplotlib.org/stable/

また描画において重要な関数も以下にまとめる。
| 関数 | 説明 | 引数 |
|:-:|:-:|:-:|
| grid() | グリッドを表示 |True or False|
| legend() | 凡例(plot関数で指定したlabel) を表示 |True or False|
| title("title") | グラフのタイトルを指定・表示 |任意の文字列|
| xlabel("xlabel")| x軸のラベルを指定・表示　|任意の文字列|
| ylabel("ylabel")| y軸のラベルを指定・表示　|任意の文字列|
| xlim(min, max)| x軸の範囲を指定 |(例) min=1, max=5|
| ylim(min, max)| y軸の範囲を指定 |(例) min=-5, max=5|
| show()| グラフを表示させる |ほどんど必要ない|
| savefig("graph.png")| グラフを任意のファイル名で保存| 任意の文字列|

以上の関数を利用すればほどんどのカスタマイズが可能である。ただし関数の利用には
```python
plt.legend()
```
のようにモジュールの指定が常に必要である。

※どうしてもモジュール指定したくないときはインポートの際に
```python
from matplotlib.pyplot import *
```
とすれば
```python
plot(x, y)
legend()
title("To study plot")
xlabel("x")
ylabel("y")
show()
```
のように、簡潔に書くこともできる。
【アイディア】精神崩壊する目覚まし時計


## 内容

* 目覚まし時計
* アラームと同時にインカメラが起動し、カメラ映像をリアルタイムに表示
* 解除するための条件
  * 目が開いていること
  * 「お前は誰だ」と発声すること

以上

## 経緯

毎日「お前は誰だ」と鏡に向かって話しかけると精神崩壊するという話があり、それが本当かどうか、誰か検証してくれないかな。と思った。

ただ、こんなつまらん作業は間違いなく忘れるだろうし、三日坊主になることが目に見える。

ならば、目覚ましというほぼ毎日使うであろうツールに埋め込もう。となった。

## 所感

結構、実装が難しそうなクソアプリである。
実現できないかもしれない。

なお、本当に精神崩壊されると困るため、「本アプリで精神崩壊しても、開発者は一切責任を負いません。自己責任でご利用ください。」と免責する必要がある。
【統計検定3級】時系列データ

# 時系列データ
時間の推移に伴うデータの変化を観測する。
【折れ線グラフ】が用いられる。

## 指数（指標）
時系列データの推移を比較する場合、データ値そのものではなく変化率を用いる場合がある。
基準とする時点の値で割った値（もしくはそれを100倍した値）を用いる。

例：1980年を100とした人口の推移

## 時系列データの注意点
時系列データの場合、観測間隔が異なる場合がある。

申請時の○カ月検診における体重の推移など、一ヶ月間隔ではなく以下のように異なる間隔で測定することがある。
０か月、１カ月、２か月、３カ月、４カ月、８カ月、１年
この場合、単純に折れ線グラフにすると誤解を与えやすいため、グラフの横軸の間隔も測定時間に応じて距離を空けるなどの配慮が必要。

## 対数
データの変化が大きすぎる場合、元々の値ではなく対数変換をした値でグラフを作成することがある。
他社運営案件でGmailの送信者ガイドラインに対応した話

# はじめに
こんにちは。
今回記事にまとめるのは過去に私がGmailの送信者ガイドラインに対応したときのお話です。
私は現在、他社で開発されたアプリの運営プロジェクトに所属しており、保守・運営・継続的な開発業務を行っています。

その最中、お問い合わせの返信でGmail宛てのメールが届かないことが発覚しました。
自社で開発・運営を行っているものについては対処法もごろごろと転がっていますが、他社商品の運営に関しての記事はありませんでしたので、解決までの道筋を記録しておきます。

# 1. 状況の把握
### 送信可能なドメインの調査
まず確認したのは送信ができるドメインとできないドメインの調査です。
実際にいくつかのメールアドレスに対してメールを送り、受信できていないものを探します。
結果として、今回はGmailだけ受信できていないことがわかりましたので、Gmailについての情報を集めていきます。

### Gmailの調査
上記でGmailのみで送信したメールが受信できていないことが判明しましたので、次はいつから送信できていないかを探りました。
これは実際に返信があったかどうかをもとに判断しています。
すると2024年9月あたりからこの現象が起きたと判明しました。

そこからGmailと2024年にあたりをつけて、仕様の変更点を探していくことになります。
すると、[メール送信者のガイドライン](https://support.google.com/a/answer/81126?hl=ja)というページに行きつきました。

# 2. 問題の特定
上記の調査から[メール送信者のガイドライン](https://support.google.com/a/answer/81126?hl=ja)に沿った対応ができていないのではと予想し、これらの対応ができているかをひとつずつ確認していきました。

すると、SPF・DKIM・DMARCへの対応が不十分であるのではと行きつきました。

:::note warn
SPF・DKIM・DMARCの確認方法を調べているとGmailを使用した確認方法ばかりが出てきます。
~~（そのGmaiが届かなくて困ってるんだ！）~~
:::

:::note
代替手段としてThunderBirdでも確認ができます。
~~（この対応後にGmailで確認したらそっちの方が見やすい...そりゃみんなGmailで確認するよね...）~~
:::

### SPF・DKIM・DMARCの設定を確認する
1. ThunderBirdでメールを開き、「その他」から「ソースを表示」を選択すると確認ができます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3562533/b0b4412f-e489-4e91-ab24-30fbcbc374ce.png)

2. 「Authentication-Results:」の箇所にSPF・DKIM・DMARCが書いてあるのでそちらを確認しましょう

### 他社商品の運営ならではの問題
しかし、SPF・DKIMも設定はされていました。
つぎにこれらの値が正しいかどうかの確認を行います。

1. 先ほどのソースの確認から「Received: from」の部分を確認し、送信元のIPアドレスを確認します
2. ターミナルを開いて`nslookup 調べたIPアドレス`で送信ホストの情報を得ます
2. ここで出てきたドメインを使って`nslookup 調べたドメイン名`を何度か行い、送信元の特定行います

この調査の結果、先方から送信されるメールに関するSPFは設定がされていましたが、当社から送信するメールにはSPFが正しく設定されていませんでした。

先方に連絡し、当社のSPFの設定を追加することで無事にメールが届きました。

この結果、私たちのプロジェクトのメールドメインにはSPF・DKIM・DMARCの設定が不十分であることがわかりました。

::: note
`nslookup -type=text メールドメイン名`を行い、設定が追加されているか確認しておきましょう。
:::

# おわりに
今回は他社の運営ならではの問題かもしれませんが、SPFの設定に当社から送信するメールの設定が抜けていたことが原因でした。

当プロジェクトは先方から運営に関するすべてを委任していただいていることもあり、メールの送信についても会社で使用しているメールサーバを通じて送る仕組みになっていたことも一つの要因でした。

そんなに多くある例ではありませんが、同じく状況に陥って困っている人の救いになればと思います。
差分納品のプチストレスから解放された話

みなさんはファイルの差分抽出をどのように行なっているでしょうか。

```git archive```のコマンドで抽出できるものの、どの順番でオプション入れたりするのか分からなくなる。
SourcetreeやForkでショートカットに登録するも、ちょっとだけオプションの内容変えたい時に面倒。

サーバー権限がなくオートデプロイ設定をすることもできず目視でちまちまとファイルアップしたり、一度納品した後にちょっとした修正が発生し差分納品で何度も納品ファイルをつくらなければいけない。

そんなプチストレスに悩まされていませんか？

私はこちらのツールに出会ってから、そんなストレスから解放されたと感じています。
自分だけでなく同じ境遇の人に届けてくれた想いに感謝。

# git-diff-archive
https://github.com/wadackel/git-diff-archive

何がいいって、使い方が簡単なのに有能です。

# 使い方
## インストール
```
npm install git-diff-archive -g
```
## 実行
差分を抽出したいプロジェクトのルートディレクトリに移動してコマンドを実行します。
```
cd /your/project/dir
```
```
gda HEAD HEAD~1
```
こちらのコマンドは一つ前のコミットとの差分を抽出する形。抽出した差分ファイルは、実行したディレクトリにzipファイルとして生成されます。
```gda HEAD HEAD~3```のように、コマンドの最後の数字を変えれば、その分前のコミットとの差分を抽出することができます。

オプションもあり、指定したコミット同士の差分を抽出したり、生成されたzipファイルの名前も変更でき、かゆいところにも手が届きます。

コマンド内にはこのようにログも出力してくれるので、納品のファイルリストが必要なときにも活用できますね。

![スクリーンショット 2025-04-09 9.32.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924179/a96a8e7b-fd2e-4c57-9285-84c599dca632.png)

私はClipyのスニペットに```gda HEAD HEAD~1```だけ登録して、必要に応じて数字を変えるだけで大体のことが済んでます。

ちなみにClipyも私にとってなくてはならない必須ツール。
https://github.com/Clipy/Clipy

これで差分抽出に関するプチストレスから解放されました。

さまざまな便利ツールをつくって世に提供してくれる方々に頭の上がらない日々でございます。
これからも是非便利ツールを提供してください！（他力本願）

# 参考
https://blog.wadackel.me/2016/git-diff-archive/