OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftUI × Firebase × PencilKitで作る「Fuyomi」：多機能演奏支援アプリの実装ノウハウまとめ

# 概要
この記事では、2025年6月1日にリリース予定のiOSアプリ「Fuyomi」の開発過程で得られた、以下の技術的知見をまとめます：
- SwiftUIでPDFと画像を同一構造で扱う方法
- PencilKitでの描画内容をStorageに保存・同期する構造
- Firebase Authentication（匿名認証）＋ Firestore/Storageの統合
- Core Hapticsによる振動付きメトロノームの実装

# アプリ概要と実装方針
Fuyomiは、演奏者向けに以下の機能を1つに統合した音楽支援アプリです：

| 機能	| 実装技術 |
|-------|---------|
|メトロノーム	| Core Haptics + Timer + 音/光連携
|チューナー	| AudioEngine + FFT（周波数解析）
|楽譜ノート（PDF/画像）|	PDFKit + UIImageView + PencilKit
|自動スクロール |	ScrollView + Timer or スライダー制御
|クラウド同期 |	Firebase Auth + Firestore + Storage

## PDF/画像＋手書き描画の統合表示
### 背景
SwiftUIにおいてPDFKitはUIViewRepresentableを通じて使う必要がありますが、同一画面でPencilKitの描画も重ねたい場合、レイヤー構造とサイズ調整が煩雑になります。

### 解決アプローチ
1. PDF／画像はどちらも CanvasView に共通処理を持たせる
2. 表示用には ZStack を使い、背景（PDF/画像）と描画レイヤーを重ねる
3. 描画領域のスケーリングとオフセットは、PDFのpage.bounds(for:)や画像のsizeから動的に計算

```php:swift
ZStack {
    if isPDF {
        PDFPageView(page: pdfPage)
    } else {
        Image(uiImage: image)
            .resizable()
            .scaledToFit()
    }

    CanvasView(drawing: $drawing)  // PencilKit
}
```

## PencilKit描画とFirebase Storageの連携
### 保存処理（書き込み）

```swift
let drawingData = drawing.dataRepresentation()
let ref = storageRef.child("users/\(uid)/notes/\(noteId)/drawings/page_0.data")
ref.putData(drawingData, metadata: nil)
```
### 読み込み処理（復元）
```swift
ref.getData(maxSize: 5 * 1024 * 1024) { data, error in
    if let data = data {
        self.drawing = try? PKDrawing(data: data)
    }
}
```
- PKDrawingはシリアライズ可能なDataとしてStorage保存が可能
- Firestoreではページごとのメタ情報（ページ数・ページ順など）を保存

## Firebase匿名認証＋Firestore構成
### 認証
```swift
Auth.auth().signInAnonymously { result, error in
    // uidは result.user.uid
}
```
### Firestoreドキュメント構造（例）
```swift
users/{uid}/notes/{noteId}
 ├── title: String
 ├── createdAt: Timestamp
 ├── pageCount: Int
```
## メトロノームの振動制御（Core Haptics）
```swift
do {
    let engine = CHHapticEngine()
    try engine.start()
    let event = CHHapticEvent(
        eventType: .hapticTransient,
        parameters: [.init(parameterID: .hapticIntensity, value: 1.0)],
        relativeTime: 0
    )
    let pattern = try CHHapticPattern(events: [event], parameters: [])
    let player = try engine.makePlayer(with: pattern)
    try player.start(atTime: 0)
} catch {
    print("Haptics Error: \(error)")
}
```
- 拍ごとに振動パターンを変更可能（1拍目は強く、それ以外は弱く等）

## スクロール制御の失敗談と方針転換
当初、BPMに合わせた自動譜めくりをTimer制御で実装していましたが：
- スクロール速度とテンポの微妙なズレ
- 長時間演奏時の累積誤差

…といった問題から、BPM連動は廃止し、ユーザーが速度を調整できるスライダーUIに変更しました。

# Dreamifyと今後の展望
このアプリは、非営利団体「Dreamify」のプロジェクトとして開発されました。
Dreamifyは、2025年6月中に非営利型一般社団法人として法人化予定で、今後も教育・音楽・災害支援などの分野でアプリ開発を行っていく予定です。

Fuyomiの今後の機能追加予定：
- MP3音源からの耳コピ機能（楽譜自動生成）
- AIによる演奏解析／自動テンポ制御
- アカウント機能と他端末共有
- Android / watchOS 対応

## ご意見・Issue・Fork歓迎です！
本記事の内容やFuyomiに関する技術質問・提案は大歓迎です！
コメント欄で気軽にどうぞ！

## リンク集
- App Storeリンク（リリース後に追記予定）
- Dreamify公式サイト：[fuyomi.com](https://www.fuyomi.com)
- Zenn / noteでも開発背景を公開中
  - [Zennで記事を閲覧](https://zenn.dev/n_machian/articles/ddbda17a868f33)
  - [noteで記事を閲覧](https://note.com/nmachian/n/n2dd413493ac5)
C言語　ifdefの使い方　一つのソースでWindowsとLinux両方に対応

## 初めに
C言語のifdefは見たことはありますが、今まで一度も使ったことがありませんでした。
ifdefを使うと一つのソースで複数の処理系特有の書き方を混在させられることが分かったので記録します。

## 検証用ソース
違いを際立たせる為にprintfは使わずそれぞれのOS特有のAPIを呼び出します。
```ifdef.c
#include <stdio.h>

#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

int main() {
    const char* message = "Hello World!\n";
    size_t len = 13; //文字列の長さ

    #ifdef _WIN32
        // Windows
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        DWORD charsWritten;
        WriteConsole(hConsole, message, len, &charsWritten, NULL);
    #else
        // Linux/macOS
        write(STDOUT_FILENO, message, len);
    #endif

    return 0;
}
```

## Windows11
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/4f9963b0-9aaf-44dc-94b0-2d0ed9a3eb8c.png)

## Ubuntu 22.04.5
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/a6e545bb-d346-4628-b1fd-720ae0b37b03.png)
曜日判定 Date

今日もPaizaの条件分岐 – 曜日判定にチャレンジ！

<Br>

## 🧩 問題概要

問題はシンプル、「1日は日曜日。X日は何曜日か？」。


入力例:

    11

出力例:

    Wed
<br>

https://paiza.jp/works/mondai/conditions_branch/conditions_branch__mod_step4

<Br><br><br>

## ✅コード例：条件武器で解く
```js
const rl = require('readline').createInterface({ input: process.stdin });

rl.once('line', (input) => {
    const X = Number(input);
    const day = (X - 1) % 7;

    if (day === 0) console.log("Sun");
    else if (day === 1) console.log("Mon");
    else if (day === 2) console.log("Tue");
    else if (day === 3) console.log("Wed");
    else if (day === 4) console.log("Thu");
    else if (day === 5) console.log("Fri");
    else if (day === 6) console.log("Sat");

    rl.close();
});
```

<br><br><br>

## ✅コード例２：配列
```js
const rl = require('readline').createInterface({input:process.stdin});


rl.once('line',(input) => {
    const X = Number(input);
    
    const week = ["Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri"];
    
    console.log(week[X % 7]);
    
    rl.close();
});
```
- 1 日は日曜日ということから、7で割ったときに１余る日が日曜日として曜日の配列を作成。
- インデックスでアクセスして曜日を取得。

<br><br>

## 🔍 気づきメモ

- 1日は日曜日→つまり `X = 1` のとき "`Sun`" を返すように余りと曜日を配列に。
- `X % 7` の結果に対応するように、配列の 0 番目は”`Sat`”にする必要がある。
- `if`文で全部書くより、データをうまく構造化（今回なら配列）する方がスマート。

<br><br>

## 📣 まとめ
「曜日の判定って、ただの7通り」だけど、条件分岐以外にも解き方があって、勉強になった！

<br><br><br>[僕の失敗談(´;ω;｀)と解決法🐈](https://paizabeginner.wordpress.com/2025/05/26/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%9a%e6%9b%9c%e6%97%a5%e5%88%a4%e5%ae%9a-date/)

<br><br><br>

### 💡おまけ

年月日が入力され、その曜日を出力する問題だった場合を考えてみる。

### ✅ コード：年月日を入力して曜日を出力
```js
// 標準入力の読み取り設定
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });

// 入力を1行だけ読み取る
rl.on('line', (input) => {
    // 入力を空白で分割し、数値に変換（例：2025 5 23）
    const [year, month, day] = input.split(' ').map(Number);

    // 月は0始まりのため、1引く（JavaScriptの仕様）
    const date = new Date(year, month - 1, day);

    // 曜日の配列（getDay()の戻り値に対応）
    const week = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

    // 曜日インデックスを取得し、対応する文字列を出力
    console.log(week[date.getDay()]);

    rl.close();
});
```
- `Date` オブジェクトを使うことで、指定した日付の曜日やその他の情報を取得できるようになる。
- JavaScript の `Date` では月（month）は 0 始まり（1月が 0、12月が 11）なので `month - 1` が必要。
- `getDay()` は曜日インデックス（ 0 : 日曜 〜 6 : 土曜）を返す
- そのインデックスをもとに `week` 配列から文字で出力

<br><br>

![スクリーンショット 2025-05-24 214215.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4018208/5c86d4f0-4749-40ec-9ff7-a5c152cd1d35.png)
Grafana(v11)でAPIを有効にしてみる

# やりたいこと
* GrafanaのAPIを使う

# 環境
* Grafana v11.6.0 (Podmanコンテナ上で動作)

# GrafanaのAPIについて
* 過去のバージョンではGrafana上で直接APIトークンを作成できたが、現在のバージョンではサービスアカウントにてキーを発行する方式に変更になったみたいです。
* https://grafana.com/docs/grafana/latest/administration/service-accounts/

# APIトークン（サービストークンの取得）
1. Grafanaの左ペインから「Administration」＞「Users and access」＞「Service accounts」を選択
1. 「Add service account」を選択
1. 「Display name」にアカウント名を入れる。Roleは今後のAPIでダッシュボードの編集権限などを渡すことも考えAdminを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212451/bee604d2-9b08-4535-bce8-2e0355b74f8e.png)
1. 「Add service account token」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212451/2c21a06f-fe22-46b3-b0a7-dbe2eef3497a.png)
1. 「Display name」に名前を入れる。例えば、このトークンを使用するシステム名や利用用途などを入れると良さそう
今回はトークンの有効期限を設けないので「No expiration」を選択
最後に「Generate token」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212451/d5a891db-1517-439c-9613-9594d6ca9293.png)
1. Token欄に実際のトークンが表示されるためメモする★重要★
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212451/4bea8325-d478-44a2-b700-8e9cbf5357e4.png)

# 動作チェック
* grafanaと同じネットワークに所属しているRHELのマシンからCurlコマンドで確認
* JSON形式でのレスポンスの視認性を良くするためにJqをインストール済み
* curlコマンドにパイプでjqコマンドを実行

### API動作チェック
* API機能自体は動作してそう
 ```shell
[hoge@linux ]$  curl  http://192.168.200.207:3000/api/health | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   101  100   101    0     0  14428      0 --:--:-- --:--:-- --:--:-- 14428
{
  "database": "ok",
  "version": "11.6.0",
  "commit": "d2fdff9ee4d75c74bfd3a97c18a0b8e4d029f06e"
}
```
### ダッシュボード一覧取得
* 良さそう！
* あらかじめGrafanaには「zabbix」という名のダッシュボードを用意
* ★サービスアカウントトークン★は先程メモしたもの
```shell
[hoge@linux]$ curl -H "Authorization: Bearer ★サービスアカウント トークン★" http://★Grafanaアクセス先★/api/search | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   197  100   197    0     0   2525      0 --:--:-- --:--:-- --:--:--  2525
[
  {
    "id": 1,
    "uid": "deilsuc2d3hfkc",
    "orgId": 1,
    "title": "zabbix",
    "uri": "db/zabbix",
    "url": "/d/deilsuc2d3hfkc/zabbix",
    "slug": "",
    "type": "dash-db",
    "tags": [],
    "isStarred": false,
    "sortMeta": 0,
    "isDeleted": false
  }
]
```

* GrafanaのAPIをまずは使ってみる第一歩目はクリア
* 今後はいろいろなAPIを見つつGrafanaを弄っていこうかと思います
【LINEに食材の写真送ったらAIがレシピ考えてくれる】とかいう一人開発のMVP、気づいたら本番構成になってて涙出た【Cooksnap】

こんにちは、普段はクラウドインフラやSREの仕事をしてる者です。

今回は、LINEで食材の画像を送るとレシピを提案してくれるAIボット をMVPで作ったつもりが、  
なぜか気づいたら、AWS SAMだの環境分離だのSSMパラメータ管理だの、本番顔負けのインフラ構成になっていた。  
そんなCooksnap（クックスナップ）というプロダクトの話をします。

## LINEで野菜を送るとAIが晩飯を教えてくれる。それだけ。

- 食材の画像をLINEで送る
- Claudeが画像から食材を判別してレシピを生成
- SNSでシェアも可能、紹介コードで友達招待もOK

こんなことができます。

想定ユーザーは「冷蔵庫にある食材で何作ればいいかわからん…」って40代後半から上の人。
なので考えささないUI を目指しました。

作成意欲の源は、嫁が料理をしてくれないからです。。。


## 作っただけのつもりが、AWS SAMでIaCまでやってた

![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1194297/56cd4a4f-278d-431b-abb7-2f026f3ad35c.png)



ぼくの中ではこうだったんですよ。

> 最初は「Lambda一個でいいでしょ」と思ってました。  


…だったはずが、気づいたらこう↓

```

* AWS SAM でIaC（環境分離済み）
* AWS SAM + Lambda + API Gateway
* DynamoDB（GSIあり）+ S3
* SSM Parameter StoreでSecrets管理
* Claude API（レシピ生成）

```

万が一、ユーザー反応を多く得られた場合を期待して、スケールアップが容易にできることを念頭に考えました。
これは、現場で見た数々のカオスから得た学びです。

## 「やってみた」感あるけど、わりと本気

Claude使った食材識別とか、それっぽくプロンプト設計したけど、  
まあ正直、「家庭料理の中の家庭料理」みたいなレシピしか出てこない。
微調整などは、現在考慮していない。

でも設計は気合い入れた。

- リッチメニュー作った（LINE UXの山場）
- 紹介コード機能つけた
- レシピのSNSシェアもできる（広告をユーザーにやってもらうスタイル）


## 本当は書かなくてもいいけど、書くのがQiitaっぽい学び

### ここが反省点

| 項目                | 内容                      |
| ----------------- | ----------------------- |
| GitHub Actions未導入 | MVPではまったく必要ないが、スケールアップするなら必要。 |
| Claudeの認識精度に波がある  | 本番画像だと失敗もある。誰かが使ってくれるなら検討。   |
| LINEのUXは地味に難しい    | 「迷わず使える」を設計するのに時間がかかる。  |
| バックエンドは知ったかだった   | 分かったつもりでも、ゼロから作るのは時間がかかった。AI使っても  |


### MVPだけどSRE目線でやったこと

| 項目        | 具体内容                              |
| --------- | --------------------------------- |
| 環境分離      | SSM, DynamoDB, Lambdaをdev/prodで切替 |
| Secrets管理 | SSM Parameter Storeでハードコード撲滅      |
| IAM制御     | Lambdaには最小権限ロールのみ付与               |
| コスト管理     | 無料枠の使用量を記録、料金通知をCloudWatchで試験中    |


## 宣伝タイム：LINEで使えます

もういいから使ってくれ！これが言いたかった！  
そしてお母さん、お父さんに教えて！
ターゲットはAI を使いこなすQiitaユーザーではない！

以下のリンクから友達追加すれば、実家の冷蔵庫ライフがAIに救われる。かもしれない。

📲 [Cooksnap LINE公式](https://line.me/R/ti/p/@460swavv)  
🔗 友達紹介コード：NL9Y7E


## 次回予告（誰かが使ってくれたら）

- Terraform化し、Webアプリ版
- マネタイズ構想（広告か、プレミアムレシピ）
- GPT-4にするかClaude続けるか、レシピの精度の向上

## 最後に

MVPって本来はもっと雑でも良いはずなんですが、
「せっかくだし、今後ポートフォリオにもなるように」と思った瞬間、設計が真面目になってしまいました。

でも結果として、一人開発でも「再利用できるServerless基盤」として仕上がったと思います。
[Python] Singletonの実装

## 概要

今更どこに需要があるのかわかりませんが，Pythonにおけるシングルトンパターン（Singleton Pattern）の実現パターン（を自分用にChatGPTに訊いたもの）をメモしておきます．

## 方法1: クラス変数を使った実装

```python
class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            
        return cls._instance
```

## 方法2: デコレータを使った実装

```python
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class MyClass:
    pass
```

## 方法3: モジュールを使った実装（Pythonic）

```python
# singleton_module.py
class Config:
    def __init__(self):
        self.value = 42

config = Config()

# 別ファイルや他の場所から
# from singleton_module import config
```

### NOTE

* モジュール自体が一度しか読み込まれないため，モジュールレベルでインスタンスを作れば自然にシングルトンになります．
# SEOを最速で強化！無料で高品質な被リンクを手に入れるなら Backlink-List.com


SEO対策で最も効果的な手段の一つが「被リンク（バックリンク）」の獲得です。  
しかし、多くの被リンクサービスは**審査が必要だったり、掲載されるまでに時間がかかったり、有料だったり**と手間がかかります。

そんな悩みを一発で解決するのが [Backlink-List.com](https://backlink-list.com/) です。

## 🚀 Backlink-List.comとは？

Backlink-List.comは、**審査不要・即時登録可能な被リンクサイトを80以上まとめた無料ディレクトリ**です。  
高ドメイン評価（DR70〜90以上）の信頼できるサイトだけを厳選しています。

## ✅ 主な特徴

- 🔗 **即時登録OK**：審査不要、すぐにリンクを掲載できる  
- 📈 **高DRサイト多数**：Hashnode、Vocal.media、Tumblrなど  
- 📚 **使い方ガイド付き**：各サイトの投稿方法を丁寧に解説  
- 🔄 **毎日更新**：新しい被リンク先を日々追加中  
- 💯 **完全無料**

## 👤 こんな方におすすめ

- 自分のプロダクトやサービスを宣伝したい**スタートアップ創業者**  
- 検索順位を上げたい**ブロガー・アフィリエイター**  
- 複数のサイトを管理している**SEO担当者やフリーランサー**  
- 「登録したのにインデックスされない…」と悩んでいる方

## 🔧 活用ポイント

- Google Search ConsoleやAhrefsと連携し、どのリンクが効果的かを追跡
- 自サイトに合ったカテゴリのサイトを選び、戦略的に被リンクを構築
- 定期的にサイトをチェックして、新規追加されたリンク先を活用

## 📝 まとめ

Backlink-List.comは、**すぐに使える・無料・高品質**の三拍子がそろった被リンク集です。  
SEOにおいて「やっておいて損はない」施策のひとつとして、ぜひブックマークしておきましょう。

👉 [https://backlink-list.com/](https://backlink-list.com/) を今すぐチェック！  
🔖 お気に入りに追加して、アクセスアップに活用してください。
paiza.ioでnadesiko その34

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 086 C - Traveling

練習問題
時刻0のとき、平面上の(0, 0)にいます。平面上のN箇所の点を、ある時刻に移動できるかという問題です。


出力例 1
Copy

# 投入するソース

```
2
3 1 2
6 1 1

```

# 期待値

```
YES
```

# サンプルコード

```

空を、尋ねる
Nは、それのINT
時間位置は、[ {t: 0, x: 0, y: 0} ]
(N)回
  　空を、尋ねる
  　入力は、それを、「 」で、区切る
  　一時時間位置は、 {}
  　一時時間位置[「t」]は、入力[0]のINT
  　一時時間位置[「x」]は、入力[1]のINT
  　一時時間位置[「y」]は、入力[2]のINT
  　時間位置に、一時時間位置を、配列追加
ここまで
移動可能は、"Yes"
インデックスを、1から、Nまで、繰り返す
  　時間差異は、時間位置[インデックス][「t」]から、時間位置[インデックス - 1][「t」]を、引く
  　X差異は、時間位置[インデックス][「x」]から、時間位置[インデックス - 1][「x」]を、引く
  　X差異は、X差異のABS
  　Y差異は、時間位置[インデックス][「y」]から、時間位置[インデックス - 1][「y」]を、引く
  　Y差異は、Y差異のABS
  　距離差異は、X差異に、Y差異を、足す
  　もし、(時間差異 < 距離差異)ならば
  　　　  移動可能は、"No"
  　ここまで
  　時間差異偶奇は、時間差異を、2で、割った余り
  　距離差異偶奇は、距離差異を、2で、割った余り
  　もし、時間差異偶奇が、距離差異偶奇でなければ
    　　移動可能は、"No"
  　ここまで
ここまで
移動可能を、表示する




```


# 成果物

https://paiza.io/projects/g2ETorKTd9ffPxqS5UQmrw

以上。
paiza.ioでnadesiko その33

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 049 C - Daydream
文字列Sが与えられ、始め空の文字列Tの末尾に "dream", "dreamer", "erase", "eraser"を追加する処理を行って、S=Tにできるか判定する問題です。



# 投入するソース

```
erasedream
```

# 期待値

```
YES
```

# サンプルコード

```

尋ねる
入力は、それ
逆読は、それの、文字列分解の配列逆順を、「」で配列結合
逆読文字数は、逆読の文字数
ワードリストは、[]
ワードリスト[0]は、「dream」の文字列分解の配列逆順を、「」で配列結合
ワードリスト[1]は、「dreamer」の文字列分解の配列逆順を、「」で配列結合
ワードリスト[2]は、「erase」の文字列分解の配列逆順を、「」で配列結合
ワードリスト[3]は、「eraser」の文字列分解の配列逆順を、「」で配列結合
(逆読文字数　>　0)の間
  　一致フラグは、「偽」
  　ワードで、ワードリストを反復
    　　逆読で、ワードが、何文字目
    　　もし、それが、1ならば
      　　　　逆読は、逆読の1から、ワードの文字数だけ、文字削除
      　　　　逆読文字数は、逆読の文字数
      　　　　一致フラグは、「真」
      　　　　抜ける
    　　　　一致フラグは、「真」
    　　ここまで
  　ここまで
  　もし、一致フラグが、「偽」ならば
  　　　  抜ける
  　ここまで
ここまで
もし、逆読文字数が、0ならば
　  「YES」と表示
違えば
　  「NO」と表示
ここまで




```

# 成果物

https://paiza.io/projects/2Xwo4oYigzVIu0m3RBvwfg

以上。
paiza.ioでnadesiko その32

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 085 C - Otoshidama
10000円札と、5000円札と、1000円札が合計でN枚あって、合計金額がY円であった。このような条件を満たす各金額の札の枚数の組を1つ求める問題です。


# 投入するソース

```
9 45000

```

# 期待値

```
4 0 5

```

# サンプルコード

```

尋ねる
入力は、それを、「 」で、区切る
全札数は、入力[0]のINT
合計金額は、入力[1]のINT
結果は、「-1 -1 -1」
一万円札数を、0から、全札数まで、繰り返す
  　五千円札数を、0から、(全札数-一万円札数)まで、繰り返す
    　　一時合計は、一万円札数に、10000を、掛ける
    　　五千円札数に、5000を、掛ける
    　　一時合計は、一時合計に、それを、足す
    　　千円札数は、全札数から、(一万円札数に五千円札数を足す)を、引く
    　　千円札数に、1000を、掛ける
    　　一時合計は、一時合計に、それを、足す
    　　もし、一時合計が、合計金額ならば
    　　　　　  結果は、「{一万円札数} {五千円札数} {千円札数}」
    　　ここまで
  　ここまで
ここまで
結果を、表示する
```

# 成果物

https://paiza.io/projects/Ytidlv2pOHqxW2ptIUde-Q

以上。
ルーターをNASにする(完全自分用備忘録)

## USBメモリを差し込む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/363c4fc3-c570-48d0-b4af-578899856a36.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054974/10c93dfc-9080-44fb-86d0-8f959183a27b.png)

## 繋ぐ
\\192.168.68.1\sda3
表示できないがスラッシュ２つ
paiza.ioでnadesiko その31

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 085 B - Kagami Mochi
N枚の整数値が与えられ、それらの重複しない要素の数を数える問題です。


# 投入するソース

```
4
10
8
8
6
```

# 期待値

```
3
```

# サンプルコード

```

空を、尋ねる
Nは、それのINT
鏡餅は、{}
(N)回
  　空を、尋ねる
  　鏡餅[それ]は、「真」
ここまで
鏡餅のハッシュキー列挙の要素数を、表示する


```

# 成果物

https://paiza.io/projects/XcA3s_xafM2PKBWWDHh0yg


以上。
dnfで最新カーネルとモジュールの導入

# ELRepoを使った最新カーネルとモジュールの導入手順（RHEL/CentOS 9系）

CentOS Stream 9 や RHEL 9 系で、ELRepo を利用して最新のカーネル（kernel-ml など）を導入し、必要なカーネルモジュールを設定する手順を解説します。



##  現在のカーネル確認

```bash
uname -r
```



##  ELRepo リポジトリの追加

```bash
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
dnf install -y https://www.elrepo.org/elrepo-release-9.el9.elrepo.noarch.rpm
```



##  ELRepo の状態確認と有効化

```bash
dnf repolist all | grep elrepo-kernel
dnf config-manager --set-enabled elrepo-kernel
```



##  カーネルのインストール
dnf でカーネルをインストールすると、そのカーネル用の initramfs（初期RAMディスク）が自動的に生成されます。（後述）

### ◆kernel-lt（長期サポート版）をインストールしたい場合：

```bash
dnf install kernel-lt
```

### ◆kernel-ml（最新の安定版）をインストールしたい場合：

```bash
dnf install kernel-ml
```



##  インストール済みカーネルの確認

```bash
rpm -qa | grep kernel
```



##  デフォルトカーネルの設定

### ◆デフォルトの確認：

```bash
grubby --default-kernel
```

### ◆インストール済みのカーネル一覧：

```bash
grubby --info=ALL
```

### ◆デフォルトカーネルの変更：
#### ■対象カーネルの確認

```bash
ls -ld /boot/vmlinuz*
```
#### ■デフォルトカーネルを変更
```bash
grubby --set-default /boot/vmlinuz-6.13.2-1.el9.elrepo.x86_64
```

##  再起動＆確認

```bash
reboot
```
```bash
uname -r
```

##  カーネルモジュールのインストール

参考：カーネルモジュールとは
https://qiita.com/miyuki_samitani/items/941e911f9aaa1321e1f2
### ◆利用可能なモジュールを確認：
kernel-ml（最新の安定版）をインストールする場合
kernel-mlで使える追加モジュールや関連パッケージを表示
```bash
dnf list available kernel-ml*
```

### ◆インストール：
例：
```bash
dnf install -y kernel-ml-modules kernel-ml-modules-extra
```

### ◆確認：
```
rpm -qa | grep -E "kernel-ml-.*"
```

##  モジュール情報の更新と確認
### ◆モジュールファイルの確認と展開

```bash
find /lib/modules/$(uname -r) -type f -name "*.ko*"
```
```bash
cd /lib/modules/$(uname -r)/kernel/
find . -name "*.ko.xz" -exec unxz {} \;
```

### ◆モジュールの依存関係データベース（modules.dep）を生成・更新

モジュールを新たに追加・削除した後、依存モジュールを自動で読み込むために必要な情報を更新します。
```bash
depmod
```
##  モジュールのロード
### ◆対象モジュールの存在確認
※例として"bcma"
```bash
grep bcma /lib/modules/$(uname -r)/modules.dep
```
### ■モジュールの手動ロード
```bash
modprobe -v bcma
```

### ■モジュールの自動ロード設定
【/etc/modules-load.d/*.conf】
Linuxでは、/etc/modules-load.d/ にある .conf ファイルに書かれたモジュール名が、ブート時に自動で modprobe される仕組みです。
つまり、PCを再起動しても、bcma モジュールが自動でロードされるようになります。

```bash
echo "bcma" | tee /etc/modules-load.d/bcma.conf
```

## モジュールの確認
```bash
lsmod | grep bcma
```

## カーネルモジュールの情報を表示
```
modinfo bcma
```

## initramfs の再生成（必要時）
dnf でカーネルをインストールすると、そのカーネル用の initramfs（初期RAMディスク）が自動的に生成される。
```bash:現在使用中のinitramfs
ls -l /boot/initramfs-$(uname -r).img
```

### ◆ initramfs生成コマンド
すべてのカーネルの initramfs（初期 RAM ディスク）を強制的に再生成する。
これにより、カーネルやモジュールに関わる変更があった後、すべてのカーネルについて安全に起動できるように初期環境を更新する。



```bash
dracut --force --regenerate-all
```

| オプション              | 意味                                                 |
| ------------------ | -------------------------------------------------- |
| `--force`          | 既存の initramfs を上書きする                               |
| `--regenerate-all` | システムにインストールされている **すべてのカーネル** に対して initramfs を作り直す |

#### ■補足
【initramfs】
Linux の起動時、ハードディスクをマウントする前に使われる「初期環境」。
initramfs には、必要なカーネルモジュール（例：ファイルシステムドライバ、ストレージドライバなど）が入っている。

##  再起動

```bash
reboot
```

## おまけ


以上で、ELRepo を使ったカーネルおよびモジュールのインストール・設定は完了です。
paiza.ioでnadesiko その30

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 088 B - Card Game for Two
N枚のカードを二人で交互に取っていき、カードに書かれている数字の和の差を求める問題。

# 投入するソース

```
2
3 1

```

# 期待値

```
2
```

# サンプルコード

```

空を、尋ねる
Nは、それのINT
//Nを表示
空を、尋ねる
//それを表示
カード札は、それを、「 」で区切る
ボブ得点は、0
アリス得点は、0　
カード札を、配列数値ソート
カード札を、配列逆順
カード札の要素数から、1を、引く
インデックスを、0から、それまで、繰り返す
  カードは、カード札[インデックス]のINT
  インデックスを、2で、割った余り
  もし、それが、0ならば
    ボブ得点は、ボブ得点　+　カード
  違えば
    アリス得点は、アリス得点　+　カード
  ここまで
ここまで
解答は、ボブ得点から、アリス得点を、引く
解答を、表示する


```

# 成果物

https://paiza.io/projects/fw5z3HEbhpW_EkPbAJ39sQ

以上。
paiza.ioでnadesiko その29

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 083 B - Some Sums
1以上N以下の整数のうち、10進法での各桁の和がA以上B以下であるものの総和を求める問題です。


# 投入するソース

```
20 2 5

```

# 期待値

```
84
```

# サンプルコード

```

尋ねる
入力値 = それを、「 」で、区切る
N = 入力値[0]のINT
A = 入力値[1]のINT
B = 入力値[2]のINT
総和 = 0
繰返数を、1から、Nまで、繰り返す
  　一時数 = 繰返数
  　一時桁和 = 0
  　一時数が、1以上の間
　　　　一時数を、10で、割った余り
    　　一時桁和 = 一時桁和　+　それ
    　　一時数を、10で、割る
    　　一時数 = それを、切り捨て
  　ここまで
  　もし、AND(一時桁和 >= A, 一時桁和 <= B)ならば
  　　　  総和 = 総和 + 繰返数
  　ここまで
ここまで
総和を、表示する
```

# 成果物

https://paiza.io/projects/GtvD3A1lRQe-gLnYjBhGjw

以上。
【Kotlin.Room】sqliteデータベースファイルを見つける

Android-Studio の Device-Explorer から参照・コピーできる。

`/data/`下のアプリ固有のドメイン名のディレクトリ下にあるはず。

端末のFile-ExplorerやPCに繋いでのエクスプローラーでは権限的にたどり着けない。

https://qiita.com/dev-tatsuya/items/85b3b76efc801100f55f

https://takusan.negitoro.dev/posts/android_room_backup/

https://ryuta46.com/1319
paiza.ioでnadesiko その28

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 087 B - Coins
500円玉をA枚、100円玉をB枚、50円玉をC枚持っているとき、これらの硬貨の中から何枚かを選び、合計金額をちょうどX円にする組み合わせを求める問題です。

# 投入するソース

```
2
2
2
100
```

# 期待値

```
2
```

# サンプルコード

```

尋ねる
それを、指示に、代入
Aは、指示
尋ねる
Bは、それを整数変換
尋ねる
Cは、それを整数変換
尋ねる
Xは、それを整数変換
パターンは、0
aを、0から、Aまで、繰り返す
    bを、0から、Bまで、繰り返す
        cを、0から、Cまで、繰り返す
            合計は、0
            aに、500を、掛ける
            合計は、合計に、それを、足す
            bに、100を、掛ける
            合計は、合計に、それを、足す
            cに、50を、掛ける
            合計は、合計に、それを、足す
            もし、合計＝＝Xならば
                パターンは、パターンに、1を、足す
            ここまで。   
        ここまで。
    ここまで。
ここまで。
パターンを、表示する


```

# 成果物

https://paiza.io/projects/9r5pNUa-aoDBomkfQnKvAw

以上。
pyenv-winについてのメモ書き

## 環境
- Windows11 Pro
- pyenv-win 3.1.1

## はじめに
pyenv-winはWindows環境において、 　
Pythonを利用する際に必須とも言えるバージョン管理ツールです。

しかし、インストールを行なって初期設定を終えた後は
記憶が忘却の彼方に行ってしまっていたので、記録に残しておきます。

## pyenv-winについてざっくり説明
- 複数バージョンのPythonを管理し、切り替えを容易にする役割を担っています。
- 元はUnix系用の「pyenv」をWindows用にしたのが「pyenv-win」です。
- pyenv-win + venv でPythonの仮想環境を作れるので開発時に幸せになれます。

## インストール方法
1. 下記のコマンドを実行し、一時的にPowerShellポリシーの変更を行う。  
    実行すると、現在のPowerShellセッション内でのみポリシーが変わり  
    セッションを終了すると元のポリシーに戻ります。
    ```ps
    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
    ```
　
2. [公式のGitHUbページのクイックスタート](https://github.com/pyenv-win/pyenv-win?tab=readme-ov-file#quick-start)に従ってコマンドを実行する。
3. 環境変数などもよしなにしてくれているのでインストールは完了。

## pyenv-winの本体の更新
1. 公式のGitHubから最新版をzipでダウンロード
2. pyenv-winフォルダ内にある、「libexec」と「bin」のディレクトリを最新版のものにいれかえる
3. PowerShellで以下のコマンドを実行し、インストール可能なPythonのリスト更新する
    ```ps
    pyenv update
    ```
4. しばらく待機し、処理がおわるのをまつ(doneなどの表示はされません)
5. 下記コマンドを実行し利用できるPythonバージョンが増えていることを確認する
    ```ps
    pyenv install -l
    ```

## pyenv-winの各種コマンド

### pyenv-winの情報確認の操作

- ヘルプを表示する
  ```ps
  pyenv --help
  ```
　
- pyenv-winのバージョン確認
  ```ps
  pyenv --version	pyenv
  ```

### Pythonインストール周りの操作

- インストール済みと、現在利用中のPythonを確認する
  ```ps
  pyenv versions
  ```
　
- 現在のディレクトリで有効な Python を表示する
  ```ps
  pyenv version
  ```
　
- インストール可能なPythonを一覧表示する
  ```ps
  pyenv install --list
  ```
　
- インストール可能なPythonのリストを更新する
  ```ps
  pyenv update
  ```
　
- 指定バージョンのPythonをインストールする
  ```ps
  pyenv install PYTHON_VERSION
  ```
　
- 指定バージョンのPythonをアンインストールする
  ```ps
  pyenv uninstall PYTHON_VERSION
  ```

### Pythonバージョン切り替え

- globalで利用するPythonを指定バージョンのものへ切り替える
  ```ps
  pyenv global PYTHON_VERSION
  ```
　
- 特定ディレクトリ内でのみ、指定バージョンの Python へ切り替える
  ```ps
  pyenv local PYTHON_VERSION
  ```
　
- 指定バージョンのPythonのフルパスを表示する
  ```ps
  pyenv which PYTHON_VERSION
  ```

#### Pythonバージョンの適用先用語

- system python
  - pyenv-winを使わずに、直接インストールされているPythonを指定する
- global
  - pyenv環境におけるデフォルトのバージョンを指定する
- local
  - アプリケーション単位で指定する
- shell
  - 現在のshellでのみ有効なバージョンを指定する

## 元に戻すコマンド類

- 利用するPython環境をsystemのものに戻す
  ```ps
  pyenv global system
  ```
  ※ コマンドを実行しても上手くいかない事があるが、その際は次のコマンドで代用する。
　
- 切り替えたバージョンを外す
  ```ps
  pyenv global --unset
  ```

## あとがき

これでpyenv-win周りの知識が忘却の彼方に行っても大丈夫です！  
~~プライベートだとほぼ使ってないのはナイショ~~  

最近だと、[uv](https://github.com/astral-sh/uv)というのが流行っているらしい。  
安定性がどれだけなのかわからないが、キャッチアップしていきたいところです。

## 参考

- GitHub - pyenv-win/pyenv-win: pyenv for Windows.
	- https://github.com/pyenv-win/pyenv-win?tab=readme-ov-file
- pyenvをWindowsにインストール
    - https://zenn.dev/lot36z/articles/1c734bde03677c
- pyenvの使い方（基礎編）をご紹介
    - https://rainbow-engine.com/pyenv-howto-use/
- 【Python】pyenvのよく使うコマンドの使い方
    - https://namileriblog.com/python/pyenv-commands/
- Python 環境構築ガイド
    - https://github.com/led-mirage/Python-Dev-Setup-Guide?tab=readme-ov-file#4-7-pyenv-win-の更新
paiza.ioでnadesiko その27

# 概要
paiza.ioでnadesikoやってみた。
atcoder、見つけたのでやってみた。
練習問題やってみた。

# 練習問題
ABC 081 B - Shift Only
N個の整数値を受け取り、一度の操作ですべての数を2で割る。割り切れなくなるまで割っていった時、何回割ることが出来るか？


# 投入するソース

```
3
8 12 40

```

# 期待値

```
2
```

# サンプルコード

```

空を、尋ねて、整数変換
要素数1は、それ
空を、尋ねる
物は、それを「 」で区切る
//要素数1を、表示
//物を、表示
答は、100
要素数１は、要素数１から、１を、引く
枠を、0から、要素数1まで、繰り返す
　  皿は、物[枠]を、整数変換
　  操作数は、0
　  OKの間
　　    もし、皿＜２ならば
　　　      抜ける
　　    違えば
　　　      皿は、皿を、2で、割る
        　　操作数は、操作数に、１を、足す
　　　  ここまで
　　    皿を、２で、割った余り
　　    もし、それ＝＝１ならば
　　　      抜ける
　      ここまで
　  ここまで
    もし、操作数＜答ならば
　　    答は、操作数
　　ここまで
ここまで
答を、表示する


```

# 成果物

https://paiza.io/projects/OZhCKG6pLFmtICZFvb1sPA

以上。
【Rails】画像加工のツールを導入する方法について

# 記事概要
Ruby on Railsに画像加工のツールを導入する方法について、まとめる

# 前提
- Ruby on Railsでアプリケーションを作成している

# 導入するツール
## Active Storage
ファイルアップロード機能を簡単に実装できるGem

## ImageMagick
コマンドラインから画像に処理を加えることができるツール
画像の作成やサイズ変更、保存形式の変更などの処理がある

Gemではなくソフトウェアであるため、Homebrewからインストールする

## MiniMagick
ImageMagickの機能をRubyで扱えるようにしてくれるGem
RailsでImageMagickを扱うために必要

## ImageProcessing
MiniMagickでは提供できない、画像サイズを調整する機能を提供するGem

# 手順(ImageMagickをインストール)
1. 下記コマンドを実行する
    ```
    # アプリのディレクトリに移動
    % cd ~/[アプリ名]
    
    # ソフトウェア「ImageMagick」をインストール
    % brew install imagemagick
    ```

# 手順(Gemをインストール)
1. Gemfileに下記を追記
    ```ruby
    # 最終行に、下記を記述する
    gem 'mini_magick'
    gem 'image_processing', '~> 1.2'
    ```
1. MiniMagickとImageProcessingをインストールする
    インストール方法は、[こちら](https://qiita.com/likapantrip/items/d7317b9ece36b58dffd6#手順)を参照
1. MiniMagickを使用するため、設定ファイルを変更する
    ```config/application.rb
    module アプリ名
      class Application < Rails::Application
        # MiniMagickの設定変更
        config.active_storage.variant_processor = :mini_magick
        # 省略
      end
    end
    ```
1. サーバーを再起動する

# 手順(Active Storageをインストール)
1. 下記コマンドを実行し、Active Storageに関連したマイグレーションが作成される
    ```
    # アプリのディレクトリに移動
    % cd ~/[アプリ名]
    
    # Active Storageのインストール
    % rails active_storage:install
    ```
1. マイグレートする
    マイグレート方法は、[こちら](https://qiita.com/likapantrip/items/6e94b32d8ea9ad266964#手順マイグレーション)を参照
1. テーブルが3つ追加されたことを確認する

# 手順(画像を保存するための実装)
1. 「Active Storageのテーブル」と「画像を紐づけるテーブル」のアソシエーションを定義する
    ```message.rb
    class Message < ApplicationRecord
      has_one_attached :image
    end
    ```
1. 画像を紐づけるテーブル(messagesテーブル)に、カラムを追加する必要はない
1. コントローラーに、imageカラムの保存を許可する
    ```messages_controller.rb
    # 省略
    private
    def message_params
      # imageという名前で送られてきた画像ファイルの保存を許可
      params.require(:message).permit(:content, :image)
    end
    ```

# 手順(保存した画像を表示)
1. [image_tagメソッド](https://qiita.com/likapantrip/items/41e40c774daa310711de#image_tagメソッド)を記述し、画像を表示する
    ```erb
    <!-- 画像が存在する場合のみimage_tagが読み込まれる -->
    <%= image_tag message.image if message.image.attached? %>
    ```

# 手順(バリデーションを設定)
1. 画像かテキストどちらかが存在していれば、メッセージを送信できるように実装する
    ```message.rb
    class Message < ApplicationRecord
      has_one_attached :image
    
      # was_attached?メソッドの返り値がfalseならばバリデーションによる検証を行う
      validates :content, presence: true, unless: :was_attached?
    
      # 画像があればtrue、なければfalseを返す
      def was_attached?
        self.image.attached?
      end
    end
    ```

# Ruby on Railsまとめ
https://qiita.com/likapantrip/items/46b43c9d1309b6633f0a
INTE サプライマネジメント テストの主要トピックと最適な準備のヒントは何ですか?

ISMサプライマネジメント統合INTE試験は、サプライマネジメント協会（ISM）が提供する認定資格で、サプライマネジメントの様々な分野がどのように連携し、相互にサポートし合っているかを理解する能力を測ります。この試験で出題される主な分野には、効果的なサプライチェーンパフォーマンスのための長期目標設定に焦点を当てたサプライチェーン戦略の策定と、部門間の業務連携による効率性とコミュニケーションの向上を目指すプロセス統合が含まれます。この試験は、サプライチェーン機能とビジネス目標の整合性を確保するための強固な基盤を構築する上で役立ちます。

サプライマネジメント統合INTE試験の準備中、多くの受験者は、仕事と個人的な予定の両立といった共通の課題に直面します。この課題に対処する賢い方法は、短時間ながらも集中的な学習セッションを含む、固定された毎日の学習ルーチンを設定することです。また、信頼できるリソースの不足も問題となり、混乱や時間の無駄につながる可能性があります。最適な解決策は、試験に合わせた高品質で最新の教材を提供するPass4Successのような信頼できるプラットフォームを利用することです。合格の可能性を高めるには、定期的にトピックを復習し、練習問題を頻繁に解き、オンラインフォーラムに参加して他の学習者とアイデアを共有し、疑問を解消するようにしてください。

試験問題を入手する: https://www.pass4success.com/ism/exam/inte
Macで仮想デスクトップを管理しやすくする方法 - Spaceman, Hidden Bar

# 結論
- **Spaceman**を使用して、デスクトップごとの名前をつけて表示させる
- **^(ctrl)+数字**の**ショートカット**を使用する
- **Hidden Bar**を使用して、メニューバーを整理する
    - これを使うことで、Spacemanのデスクトップごとの名前がいつでも確認できるようになります。

## 本記事で扱う内容と扱わない内容
- 扱う内容
    - ノンエンジニアでもmacを上手に扱う方法
    - Spacemanとショートカットキーを使った仮想デスクトップの移動方法
- 扱わない内容
    - AppleScript等を使う方法
    - Appleのアプリ**ショートカット**を使う方法
## セットアップ
- Spacemanのセットアップ
- Macのショートカットのセットアップ
- Hidden Bar（メニューバー整理）のセットアップ
### Spacemanのセットアップ
https://github.com/Jaysce/Spaceman?tab=readme-ov-file

- ターミナルを開き、以下のコマンドを実行
```shell
brew install spaceman
```
- アプリケーションを開く
finderを開く　→ アプリケーション → Spaceman.app

- preferencesを開く
- Spaces
    - Style : `Named spaces`
    - Space : 数字（プルダウン）　名前（アルファベット3文字以内）

Spaceの数字はデスクトップの番号
デスクトップ番号を設定し、`Update name`を押すと、設定される
（アプリの使用上、設定できた感じがしないですが、設定されています。）
![スクリーンショット 2025-05-26 19.53.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626883/22a706a7-c78a-49e6-b22d-860d858a9b10.png)


### Macのセットアップ
- システム設定を開く
- キーボード → キーボードショートカット → Mission Contorol
- Mission Control のプルダウンを開く
- `デスクトップ[数字]へ切り替え`のすべてにチェックを入れる
- `完了`を押す
![スクリーンショット 2025-05-26 19.53.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626883/6ff5fe15-6a09-4353-8422-b9eea56a78a5.png)

### Hidden Bar（メニューバー整理）のセットアップ
- これにアクセスし、インストール
https://apps.apple.com/us/app/hidden-bar/id1452453066?mt=12
- 環境設定は適当でOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626883/7770eeb3-bffc-4af8-b93a-c6b60a50dfba.png)
- 「|」これの左側に**cmdを押しながらドラッグ**すると隠れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626883/2018d3b2-6761-4722-92d6-391b88c78782.png)
- 「|」より右側は常時表示される
- 「<」こいつをクリックすると展開される
    - Docker, Google Drive, OneDrive, LINEとかを入れています
    - 「<」こいつ自身も移動できます
- Spacemanは「|」より右側におくことでいつでもデスクトップごとの名前を確認できる


## 実践
メニューバーに表示されたデスクトップの名前を見ながら
^(ctrl)+[0~9]のショートカットキーを押すことで、任意の仮想デスクトップに移動が可能になる。
また、各デスクトップの作業場を決めることにもつながる。
![スクリーンショット 2025-05-26 20.55.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626883/363e1870-9e38-4a4a-90ee-c66b8d0acdca.png)
私は
OBS：obsidian
ARC：ブラウザ
PDF：pdfを開いて、メモをしたりする場所
DEV：開発する場所
AI：AIさわるとこ
etc ...

以上。

## 参考
https://github.com/Jaysce/Spaceman

https://applech2.com/archives/20210108-spaceman-for-mac-view-spaces-virtual-desktop.html
S3で指定した拡張子の総容量をもとめる方法

## 概要
S3バケットの中にある、特定の拡張子を調べるコマンドを記載します。

### 手順
- 対象S3があるアカウントのコンソールにログインする
- CloudShellを開く
- 以下コマンドを入力する
```
aws s3 ls s3://[バケット名]/[フォルダ名] --recursive | grep -E '\.([拡張子]|[拡張子])$' | awk '{total += $3} END {print total/1024/1024 " MB"}'
```

このコマンドを利用することで、指定した拡張子の総容量がMB単位で表示されます。
また、バケットの中にある特定フォルダの総容量はコンソール上から確認ができます。
手順は以下の公式サイトに記載されています。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/using-folders.html#calculate-folder
Tailwind CSSで even や odd を子に一律で適用したい

時々使いたいので備忘録に。

## 結論

例えば「子要素のうち奇数番目の子要素にだけfont-boldとmt-4を適用したい」ならこう

```html
<dl class="[&>*:nth-child(odd)]:font-bold [&>*:nth-child(odd)]:mt-4">
  <dt>ID</dt>
  <dd>1234</dd>
  <dt>Name</dt>
  <dd>Shigeru</dd>
  <dt>createdAt</dt>
  <dd>2025-01-01 00:00</dd>
  <dt>updatedAt</dt>
  <dd>2025-01-01 23:59</dd>
</dl>
```

## この書き方ってなに？

任意のvariantsを定義する機能（arbitrary variants）を使って、「子要素たちのうち奇数番目のもの」を指定している。この任意のvariantsを定義する機能（arbitrary variants）の中では `&` が自身を示すPlaceholderになっており、以降は普通にCSSセレクタを書いている。

この arbitrary variants については公式ドキュメントではここに使い方が載ってる。

https://tailwindcss.com/docs/hover-focus-and-other-states#using-arbitrary-variants

もちろん私は普段からドキュメントの隅々まで見ているので当然最初から知っていた...なんてわけがなく、下記で知った。

https://stackoverflow.com/questions/74367340/use-nth-childodd-css-selector-with-tailwind-on-the-parent-element
Expo SDK 53 × Firebase Auth の永続化ができない理由と、2025年時点での対策

:::note info
久しぶりの備忘録 かつ、疲労困憊の脳味噌でChatGPTに書かせています。
ハルシネーション検証・EAS build版での実行結果を踏まえた加筆修正はまた後日。
:::
## はじめに
Expo＋Firebaseでの認証実装時の、**永続化（persistence）の設定**にハマったので備忘録に残します。
「getReactNativePersistence」が動かず、警告が消せない状況に悩まされました。
2025年5月時点での最新状況と、**「今できる最適な対応」** を整理しておきます。

## 前提環境
- Expo SDK 53
- Firebase JS SDK 11.8.1
- TypeScript（Hermes有効）
- @react-native-async-storage/async-storage導入済

## 1. 「getReactNativePersistence」が使えない理由
Expo SDK 50以降、Firebase v10以降では、

- firebase/auth/react-native は廃止
- firebase/auth からも getReactNativePersistence のエクスポートがなくなった

このため、以前までのサンプルコードがそのままでは動きません。

## 2. 警告が出る現象と、Expo Goの制約
開発中、getAuth(app) だけで認証を使うと下記の警告が出ます。

```
@firebase/auth: Auth: You are initializing Firebase Auth for React Native without providing AsyncStorage. Auth state will default to memory persistence...
```
つまり「永続化（アプリ再起動後もログイン状態を保持）」が無効になり、毎回サインインが必要になります。

Expo Goでは、getReactNativePersistenceがランタイムで利用できません（Hermes/Metroの制約）。
そのため、開発中はこの警告を回避できず、永続化も効きません。

## 3. 本番環境での正しい対応（EAS Build・bare）
永続化を有効にするには、EAS Buildやbareワークフローでアプリをビルドし、
その環境で getReactNativePersistence を利用する必要があります。
Expo Goでは無理ですが、EAS Build後はPersistenceが機能します。

## 4. 実行環境ごとの分岐方法（2025年最新）
Expo SDK 50以降は
Constants.executionEnvironment
で、「Expo Go」「EAS Build（bare）」などの実行環境を判別できます。

```typescript
import Constants from "expo-constants";

if (Constants.executionEnvironment === "bare") {
  // 本番/EAS Build（永続化できる環境）
} else {
  // Expo GoやWeb（永続化は諦める）
}
```

## 5. 実際のコード例
```typescript
import { initializeApp } from "firebase/app";
import { getAuth, initializeAuth, Auth } from "firebase/auth";
import AsyncStorage from "@react-native-async-storage/async-storage";
import Constants from "expo-constants";

const firebaseConfig = {
  // ...Firebaseの設定...
};

const app = initializeApp(firebaseConfig);

let auth: Auth;

if (Constants.executionEnvironment === "bare") {
  // Expo GoやWebはgetAuthのみで利用（永続化は効かない）
  auth = getAuth(app);
} else {
  // EAS Buildやbareのときだけ永続化を明示的に設定
  const { getReactNativePersistence } = require('firebase/auth');
  auth = initializeAuth(app, {
    persistence: getReactNativePersistence(AsyncStorage),
  });
}

export { auth };
```
※ require をif文の中に書くことで、Expo Goでもクラッシュしません。

## 6. まとめ
- Expo GoではFirebase Authの永続化（persistence）はできない
- EAS Buildやbareアプリでのみ有効
- 実行環境の分岐には Constants.executionEnvironment を使うと安全
- 警告が消えないのは仕様と割り切るのが現状の正解

## おわりに
Firebase Authの永続化は、Expo Go開発時には割り切るしかありません。
本番環境でだけPersistenceが効くよう、分岐を入れて管理するのが無難です。

同じように詰まった方の参考になれば幸いです。
他にも気づいた点や新情報があれば、ぜひコメントで教えてください。

## 蛇足
Firestoreルールでauth使いたい＆自動サインインにしたいときに使える **匿名認証** というものを今回初めて知りました。ExpoもReactNativeも、しばらく見ない間にいろいろ変わったなぁ…

```typescript
  useEffect(() => {
    // アプリ起動時に現在の認証状態を確認
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (!user) {
        // ユーザーが未ログインなら匿名ログインを実行
        signInAnonymously(auth)
          .then(() => console.log('匿名ユーザーでサインインしました'))
          .catch((error) => console.error('匿名ログインに失敗:', error));
      }
      // ログイン済み (user が存在) の場合は何もしない（既存ユーザーを維持）
    });
    return unsubscribe; // コンポーネントアンマウント時にリスナー解除
  }, []);
  ```
GitHub Copilot Coding AgentのFirewall設定

# エラー

> I tried to connect to the following addresses, but was blocked by firewall rules:

# 概要

初期状態では、GitHub Copilot Coding Agentはインターネットに殆どアクセスできない。

FW（ファイアウォール）が設定されており、CopilotとGitHubのやりとりや、依存関係のダウンロードに必要な範囲だけ、アクセスが許可されている。

そこで、どこかの外部のサイトにアクセスが必要な場合は、FWにアクセス許可を追加するか、FWを無効にする必要がある。

# 設定方法

FWにアクセス許可を追加するには、`COPILOT_AGENT_FIREWALL_ALLOW_LIST_ADDITIONS` に、カンマ区切りでドメイン名やURLを記入すればOK。

なのだが、それをどこに書けば良いかが、とても分かり辛い。

Copilot coding agentは、GitHub Actionsで動いているようで、GitHubActionsの設定としても設定できるし、github.comのSettingsでも設定できるらしい。

## github.com の Settings で設定

手っ取り早く、github.com の Settings で設定する場合は下記の手順で追加できる。

1. github.com のリポジトリのページ
1. 右上の「Settings」
1. 左の「Environments」
1. 「copilot」
1. 「Environment variables」の「Add environment variable」
1. Nameに「COPILOT_AGENT_FIREWALL_ALLOW_LIST_ADDITIONS」を、Valueに許可したいドメインやURLを「,」区切りで入力
1. 「Add variable」

## `copilot-setup-steps.yml` で設定

もし、Copilot coding agent の実行環境を `.github/workflows/copilot-setup-steps.yml` でカスタマイズしているなら、envの部分を下記のように書けばOK。

```
env:
  COPILOT_AGENT_FIREWALL_ALLOW_LIST_ADDITIONS: 許可したいドメインやURLを「,」区切りで記述
```

# 参考

詳しくは下記を参照。なお、FWを無効にすることもできるが、自由度高くて何をしでかすか分からず危険なのでお勧めしないらしい。

- https://docs.github.com/ja/enterprise-cloud@latest/copilot/customizing-copilot/customizing-or-disabling-the-firewall-for-copilot-coding-agent
- https://docs.github.com/ja/enterprise-cloud@latest/copilot/customizing-copilot/customizing-the-development-environment-for-copilot-coding-agent
- https://docs.github.com/ja/enterprise-cloud@latest/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#creating-configuration-variables-for-a-repository
- https://dev.classmethod.jp/articles/github-actions-configuration-variables-vs-environment-variables/
SQLチューニングの落とし穴：インデックスが効かない意外なケース

# SQLチューニングの落とし穴：インデックスが効かない意外なケース

## はじめに

SQLのパフォーマンス改善において、インデックスは非常に強力な武器です。しかし、<b>「インデックスがあるのに遅い」</b>という現象に遭遇したことはありませんか？

本記事では、<b>ユーザーの入力パラメータによってインデックスの有無が実行計画に影響するケース</b>について解説します。

---

## ケーススタディ：user_idでの絞り込み

例えば、動画配信サービスの視聴履歴テーブル `WatchHistory` に対して、特定ユーザーの視聴回数をカウントする以下のSQLを考えてみます。

```sql
SELECT COUNT(*)
FROM WatchHistory
WHERE user_id = :uid;
```

このSQLは、あるユーザー（`user_id`）がどれだけの動画を見たかを調べるものです。非常にシンプルな構文ですが、指定されるパラメータ `:uid` の値によって、<b>インデックスが使われたり、フルテーブルスキャンになったりする</b>という現象が発生します。

---

## パターン別の実行結果

| パターン | `user_id`に対応する視聴記録件数 | 実行プランの傾向 |
|----------|-------------------------------|-------------------|
| 一般ユーザー（例：10万件） | 少ない（低選択率） | インデックススキャン |
| ヘビーユーザー（例：1,000万件） | 多い（高選択率） | フルテーブルスキャン |

インデックスは「絞り込み効果が高いとき」に威力を発揮します。しかし、大量の行が該当してしまう場合、<b>インデックス経由でランダムアクセスするより、全件読み込んだ方が速い</b>とDBMSが判断し、<b>インデックスを使わずフルスキャンに切り替える</b>ことがあります。

---

## 問題点：入力パラメータに依存する性能変動

このような状況では、以下のような問題が起こります。

- 同じSQL文でも、入力値によって実行時間が極端に変わる
- テスト環境では高速でも、本番で遅くなる
- 特定のヘビーユーザーに偏ったアクセスがあるとシステム全体が重くなる

つまり、<b>「パラメータ次第でインデックスが無効化されるリスク」</b>が潜んでいるのです。

---

## 対策

こうした問題に対応するには、いくつかの方法があります。

- `EXPLAIN`や`EXPLAIN ANALYZE`で実行計画を確認する
- 統計情報を適切に更新しておく（ANALYZEなど）
- ユースケースに応じてヒント句（例：`USE INDEX`）を使う
- ヘビーユーザーのデータを別テーブルやパーティションに分割する
- マテリアライズドビューやキャッシュの活用

---

## まとめ

インデックスは万能ではありません。同じクエリでも、ユーザーが入力するパラメータによって実行計画が大きく変わることがあります。とくに、選択率が高い値が入力された場合、インデックスが無視され、フルスキャンになることがある点には注意が必要です。

SQLチューニングでは、<b>「実際にどの値が使われるか？」を意識して、現実的なケースでの実行計画をチェックすることが重要</b>です。

---

## 参考

- 書籍：『達人に学ぶ SQL徹底指南書』（ミック著）
「AWKを教えて下さい。htmlのコメント箇所を削除して。」をAI先生ヘ。  



# (本日の)ChatGPT先生へ
#### (以下回答抜粋)
✅ 方法2：複数行のコメントにも対応する（やや高度）
```awk
awk '
/<!--/ { in_comment=1 }
in_comment { 
  if (/-->/) {
    sub(/.*-->/, "")
    in_comment=0
    if (length($0) > 0) print
  }
  next
}
{ print }
' input.html > output.html
```
・省略

# Gemini先生へ

# copilot先生へ

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

https://qiita.com/mrrclb48z/items/b6351b48e47bcf6265c0

# いつもと違うおすすめです。
#### Qiita内

https://qiita.com/mrrclb48z/items/e8c6883745d759b20ae6
ai image

最近見つけた画期的なAI画像生成ツール「SuperImage」を紹介します。2025年現在、Telegram上で高速かつ高品質なアート生成が可能で、暗号通貨や登録不要。試してみる価値ありです。


🔥 主な特徴


完全無料＆即時生成
クレジットや課金一切なし。プロンプト入力だけで4枚の画像を瞬時に生成。

アプリ不要
Telegram内で動作。参加はこちら：t.me/SuperImageAI。

3種類のAIモデル

HiDream：アニメ・ファンタジー風

FluxDev：リアルさと速度重視

SANA：芸術的な質感



Web3対応GPUネットワーク
ブロックチェーンインフラを利用した分散コンピューティングによる実行。

トークン報酬予定
将来的に積極的なユーザーにエアドロップ。


🎨 テスト結果：サイバーパンクなキツネ

プロンプト：「ネオン眼鏡をかけたサイバーパンクなキツネが雨中を歩いている」
→ 細かいディテールやネオンの輝き、創造性が高く、有料ツールに匹敵する結果に。
【Synced】HTB writeup的な

### 概要
ファイル転送プロトコルで良く知られているのFTPである。しかし、FTPは仕様上ファイルなどを丸ごと送信する。
これでは転送速度が遅い。ファイルの差分のみ（デルタ）を転送したいニーズがある。このニーズに答えたのがRsyncである。（アールシンク）これにより、転送に必要な帯域幅と時間を大幅に削減する事が出来る。
**用途**
・ディレクトリ間の同期
→ローカルのディレクトリとリモートのディレクトリを同期サせることが出来る。

・バックアップ
→特定のディレクトリやファイルをバックアップとして保存出来る。

・データの転送
→ネットワーク越しにファイルを転送出来る。

・サーバー間の同期
→サーバー間でファイルやディレクトリを同期させる事が出来る。

### 基本的なコマンドの見方

```
rsync [OPTION] [USER@]HOST::SRC [DEST]
```
**SRC** : コピー元のファイルまたはディレクトリ（複数指定可）

**DEST** : コピー先のファイルまたはディレクトリ

**OPTION** : rsync のオプション一覧

**USER@** : 認証アクセス時に指定（今回は認証情報がないため省略し、匿名アクセスを試行）

匿名ユーザーとして利用可能なディレクトリ一覧を表示するには`--list-only`オプションを使う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575047/602f1733-71a4-43e4-a457-822174f5fdf4.png)

表示結果をみてみると publicという匿名でも共有出来るフォルダがある。次はこいつの中身を確認してフラグを確認した

この中身を見る場合

```
rsync <target_IP>::public/flag.txt flag.txt
```
何も出力されないが、ここで自分のローカル側に該当の`flag.txt`がコピーされている。それを`cat`コマンドで見ればだいじょう




### 参考文献（2025年5月26日）

https://app.hackthebox.com/79ee2c6e-850c-4f64-a5ca-5ae9890f8974

https://qiita.com/shnagai/items/7403411b4aa193d0fa0d
MBOXをExcel用のCSVに変換する方法 - 専門家ガイド

<p><b>概要</b>：MBOXファイルをCSVに変換する方法を頻繁に検索していますか？もしそうなら、このブログはきっとお役に立ちます。MBOXファイルをCSVに変換する2つの方法をご紹介します。まずは、手動の方法と、高度な機能を備えたBLR MBOXエクスポーターの使い方について見てきました。</p>
<h2>MBOXファイルをCSVに変換する理由：</h2>
<ul>
<li>情報は、読みやすく整理された形式でCSVファイルに保存されます。</li>
<li>MBOX形式はMicrosoft Outlookではサポートされていません。Outlookでデータにアクセスするには、CSV形式に変換する必要があります。</li>
<li>CSVファイルはMBOXファイルよりも交換が容易で、プラットフォームへの依存度が高くなります。</li>
<li>CSV形式を使用することで、ユーザーはメールデータをより迅速に処理し、開発プロセスを効率化できます。</li>
</ul>
<h2>MBOXファイルをCSVにエクスポートするテクニック</h2>
<p>ここでは、MBOXファイルをCSVに変換する様々な方法を紹介します。</p>
<ul>
<li>手動手順</li>
<li>専門家による解決策</li>
</ul>
<h3><strong>方法1：エクスポート機能を使用してMBOXファイルをCSVに変換する</strong></h3>
<ul>
<li>メールソフト「Thunderbird」を起動します。</li>
<li>メールアカウントのウィンドウが開きます。受信トレイ、送信済みメール、スパム、ゴミ箱など、様々なフォルダが表示されます。</li>
<li>次に、メニューから「アドレス帳」を選択します。</li>
<li>インターフェースが表示されます。「ツール」を選択後、「エクスポート」を選択します。</li>
<li>最後に、変換したMBOXファイルをパソコン上の保存場所を参照して保存します。</li>
</ul>
<p><strong>方法2：Import/ExportNGアドオンを使用してMBOXファイルをCSVファイルに変換する</strong></p>
<ul>
<li>まず、Thunderbirdプログラムを起動してMBOXファイルをCSVファイルに変換します。</li>
<li>画面右側のメニューから、該当する項目を選択します。</li>
<li>次に、アドオンとテーマのボタンをクリックします。</li>
<li>検索ボックスに「ImportExportNG」と入力します。</li>
<li>これをThunderbirdのアカウントに追加します。</li>
<li>Thunderbirdアカウントを再起動します。</li>
<li>アカウントまたはフォルダを右クリックしてImportExportNGを選択します。</li>
<li>この時点で、「すべてのフォルダをエクスポート」または「すべてのフォルダを構造付きでエクスポート」を選択します。</li>
<li>ImportExportNGの手順を使用します。「OK」を押します。</li>
<li>最後に、変換したCSVファイルの保存場所を選択して「エクスポート」を押します。</li>
</ul>
<h3><strong>手動手法の欠点</strong></h3>
<ul>
<li>巨大なMBOXファイルへの使用は推奨されません。</li>
<li>手動手法では、データの損失や破損のリスクが高くなります。</li>
<li>手動手法では、カスタマイズやフィルターの選択ができません。</li>
<li>複数のメールを処理する場合、手動手法では多くの時間がかかります。</li>
</ul>
<h3><strong>方法3：MBOXファイルからCSVファイルへの変換ツール</strong></h3>
<p>MBOXファイルをCSVファイルに変換する最も人気があり効果的なツールは、<strong>BLR <a href="https://www.blrtools.com/mbox-exporter-tool.html">MBOXファイルコンバーター</a></strong>です。Thunderbird、Office 365、Gmailなど、多くのメールアプリケーションにMBOXファイルをインポートできます。さらに、PST、PDF、EML、EMLX、MSG、HTMLなど、様々な形式にMBOXファイルをオンラインでエクスポートできます。ファイルサイズ制限に関係なく、MBOXファイルの一括変換をサポートします。このプログラムを使えば、1つまたは複数のMBOXファイルを一度に簡単に処理できます。日付フィルター、重複メールの削除、フォルダ階層の保持などの機能も備えています。Windows OSのすべてのバージョンと互換性があります。</p>
<p><strong>MBOXファイルをCSVにエクスポートする簡単な方法</strong></p>
<ul>
<li>MBOXファイルエクスポートアプリケーションをインストール後、実行してください。</li>
<li>MBOXファイルがプログラムウィザードに含まれるはずです。</li>
<li>プレビューウィンドウで、変換するディレクトリを選択してください。</li>
<li>ドロップダウンメニューから保存形式としてCSVを選択してください。</li>
<li>その後、ツールのアドオン機能を選択してください。</li>
<li>ファイルの保存先パスを選択できます。</li>
<li>「変換」を選択したら、処理が完了するまでお待ちください。</li>
<li>最後に、CSV変換用に選択した保存先パスを確認してください。</li>
</ul>
<h4><strong>結論として、</strong></h4>
<p>このブログでは、MBOXファイルをCSVファイルに変換するいくつかのテクニックを紹介しました。手動で変換するには少し時間がかかります。同様に、手動で変換する場合、いくつかの制限があります。そのため、専門的な手順でMBOXファイルをCSVファイルに変換するのが最善の選択肢です。</p>
雇用保険法　参照先

雇用保険法
https://qiita.com/kaizen_nagoya/items/b6fec08b07be74a516e5

# 参照先

|雇用保険法|参照先|
|:--|:--|
|第五条|労働保険の保険料の徴収等に関する法律（昭和四十四年法律第八十四号。以下「徴収法」という。）|
|第六条|学校教育法（昭和二十二年法律第二十六号）|
|第六条|船員法（昭和二十二年法律第百号）|
|第六条|船員職業安定法（昭和二十三年法律第百三十号）|
|第六条|船員の雇用の促進に関する特別措置法（昭和五十二年法律第九十六号）
|第七条|徴収法|
|第九条|行政手続法（平成五年法律第八十八号）|
|第十条の四|労働施策の総合的な推進並びに労働者の雇用の安定及び職業生活の充実等に関する法律（昭和四十一年法律第百三十二号）|
|第十条の四|職業安定法（昭和二十二年法律第百四十一号）|
|第十条の四|徴収法|
|第十五条|職業訓練の実施等による特定求職者の就職の支援に関する法律（平成二十三年法律第四十七号）|
|第十八条|最低賃金法（昭和三十四年法律第百三十七号）|
|第二十二条|徴収法|
|第三十二条|職業安定法|
|第三十七条|健康保険法（大正十一年法律第七十号）|
|第三十七条|労働基準法（昭和二十二年法律第四十九号）|
|第三十七条|労働者災害補償保険法（昭和二十二年法律第五十号）|
|第四十五条|徴収法|
|第四十八条|徴収法|
|第四十九条|徴収法|
|第五十二条|職業安定法|
|第五十八条|職業安定法|
|第六十一条の七|民法（明治二十九年法律第八十九号）|
|第六十一条の七|児童福祉法（昭和二十二年法律第百六十四号）|
|第六十一条の七|労働基準法|
|第六十一条の十|労働基準法|
|第六十一条の十二|労働基準法|
|第六十二条|労働施策の総合的な推進並びに労働者の雇用の安定及び職業生活の充実等に関する法律|
|第六十二条|高年齢者等の雇用の安定等に関する法律（昭和四十六年法律第六十八号）|
|第六十二条|独立行政法人高齢・障害・求職者雇用支援機構法（平成十四年法律第百六十五号）|
|第六十三条|　職業能力開発促進法（昭和四十四年法律第六十四号）|
|第六十三条|高年齢者等の雇用の安定等に関する法律|
|第六十三条|独立行政法人高齢・障害・求職者雇用支援機構法|
|第六十四条|職業訓練の実施等による特定求職者の就職の支援に関する法律|
|第六十六条|徴収法|
|第六十七条の二|徴収法|
|第六十八条の二|子ども・子育て支援法（平成二十四年法律第六十五号）|
|第六十九条|行政不服審査法（平成二十六年法律第六十八号）|
|第七十四条|会計法（昭和二十二年法律第三十五号）|
|第七十五条|地方自治法（昭和二十二年法律第六十七号）|
|第七十六条|徴収法|
|第七十九条の二|船員の雇用の促進に関する特別措置法|

引用元がうまく表示できません。今、しばらくお待ちください。
OpenAIの新しいモデル「gpt 4.1」のプロンプトエンジニアリングガイド

こんにちは！株式会社ナイトレイの開発部のアレックスです！

この記事で、OpenAIの「GPT-4.1」という最新のAIモデルにぴったりな使い方や工夫をご紹介します！前に書いた記事「[LLMプロンプトエンジニアリングの普遍的テクニック](https://qiita.com/CodingDane/items/56fa73a5250e79376cb4)」では、いろんなAIで使えるプロンプトテクニックを紹介しました。良ければその記事もご覧ください。

GPT-4.1は、2025年5月14日にAPI向けに、5月24日にWeb版のChatGPTでも使えるようになりまして、**最大100万トークン**までの長いコンテキストを扱える新しいアーキテクチャで、**コーディング**、**指示の理解**、**長文処理**の性能が従来モデルよりも大きく向上しています。

さらに、小型モデルの「GPT-4.1 mini」や「GPT-4.1 nano」も登場しており、それぞれコストと速度の面で優れたバランスを持っています。

この記事では、OpenAIが公式に公開した「[Introducing GPT-4.1 in the API](https://openai.com/index/gpt-4-1/)」および「[GPT-4.1 Prompting Guide](https://cookbook.openai.com/examples/gpt4-1_prompting_guide)」の2つのガイドをベースに、そこに含まれるベンチマーク結果・開発者の活用事例・実践的なプロンプト手法などをふまえて、開発現場での工夫や効果的な使い方をご紹介していきます。

## GPT-4.1ってどんなモデル？

GPT-4.1は、以前のGPT-4やGPT-4oと比べて次のような違いがあります：

- **Long context！**最大で100万トークン（=Reactのコードベース8個分相当）を扱える
- **形式に沿った指示の解釈や否定命令**（例：「○○しないで」）がより正確にできる
- **コーディング性能**が上がった（SWE-bench Verifiedで54.6%）

つまり、明確で構造的な指示を与えることで、GPT-4.1はより正確かつ意図通りに動いてくれます。

## 1. エージェント風のプロンプト設計

GPT-4.1は、ステップごとに思考し、道具を使いながら作業を完了するようなプロンプト設計に向いています。

特に次の3つを明確に伝えると効果的です：

- **途中で止まらずに最後までやりきること**（Persistence）
- **必要ならちゃんとツールを使うこと**（Tool-Calling）
- **やる前に計画を立てて、終わったら振り返ること**（Planning）

## 2. ツールの使い方をはっきり伝える

GPT-4.1では、ツールの呼び出しにおいて、明確な構文・命名・入力構造が重要です。

- ツール名は `fetch_user_info` のように動作＋対象の形式
- 説明は短く簡潔に
- パラメータ名は `user_id`, `email` のように意味がわかるようにする

こうすることでツール呼び出しエラーが減り、意図通りの動作が期待できます。

## 3. 考えさせるプロンプトを使う（Chain-of-Thought）

GPT-4.1は、一足飛びの答えよりも段階的思考の促し（CoT）によって正確性が向上します。

この方法は、特に**難易度の高い質問や複数条件が絡む命令**に効果的です。

CoTについては「[LLMプロンプトエンジニアリングの普遍的テクニック](https://qiita.com/CodingDane/items/56fa73a5250e79376cb4)」でより詳しく説明しています！

## 4. 長い文章をうまく扱うための工夫

GPT-4.1は、最大で**100万トークン**の入力を処理できます。これは、従来のGPT-4o（128,000トークン）よりも約8倍です。

ただし、すべてを均等に読めるわけではありません。重要なのは：

- **命令はコンテキストの前方に置くのが効果的**（注意の集中が前に寄る傾向がある）
- **Markdown構造やXMLなどで情報を区切る**ことで重要な情報が際立つ
- **似たような文が並ぶと誤認識する**リスクがあるため、冗長さを避ける

## 5. はっきりしたルールを伝える

GPT-4.1は、「何をしてほしくないか」や「どの順番で対応すべきか」といった詳細な指示を従来以上に正確に守れるようになりました。

```
# インストラクション
- ユーザーの話には、要点をまとめて返事をする
- 返事の前に、いつも挨拶を入れる
- 外の情報は使わず、ツールで調べる
```

こういったMeta Prompting（手順を先に示す形式）は、複雑なシナリオにも有効です。

## まとめ：GPT-4.1から学んだこと

GPT-4.1の登場で、より実践的・構造的なAI活用が可能になりました。

- 曖昧な指示ではなく、**構造的で明確なプロンプト**が求められる
- **CoTによる段階的思考**の誘導が精度向上に寄与
- **100万トークン**という長文コンテキストへの対応により、法務・コードリーディング・大規模ドキュメント処理に強い
- エージェント的思考（ツール使用・マルチステップ・フィードバック）は、アプリ開発にも応用可能

## おまけ：GPT-4.1 miniとGPT-4.1 nanoについて

GPT-4.1には、小型モデルである「mini」と「nano」もあります。

- **GPT-4.1 mini**：
    - Chatgptのウェブ版では4o-miniの代わりになりました。
    - GPT-4oよりも速く、コストも約83%安いのに、同じかそれ以上の頭の良さを持っています。
    - コーディングや指示の理解にも強く、処理速度が早いので、リアルタイムのアプリや会話系のシステムにも向いています。
- **GPT-4.1 nano**：
    - 一番軽くて一番速いモデルです。
    - コストも非常に安く、分類や自動補完のようなシンプルで大量の処理が必要な場面で活躍します。
    - こちらも100万トークンの長い文脈に対応しています。

それぞれのモデルは、使う目的やコスト・スピードのバランスによって選ぶと良いです。

質問や感想があれば、ぜひコメントしてください！