OmniAICreator/Qiita-1.07M huggingface dataset:
Kotlinのinline関数の使い方

### 基本概念

`inline`関数はKotlinの重要な機能で、関数呼び出しのオーバーヘッドを削減するために使用されます。通常の関数呼び出しでは、呼び出し元のコードから関数本体へジャンプし、処理後に呼び出し元に戻る必要がありますが、`inline`関数はコンパイル時に関数の本体が呼び出し元のコードに直接埋め込まれます。

### 使用方法

```kotlin
inline fun performOperation(action: () -> Unit) {
    println("操作を開始します")
    action()
    println("操作を完了しました")
}

fun main() {
    performOperation {
        println("処理を実行中...")
    }
}
```

この例では、`performOperation`関数を呼び出すと、コンパイラはこの関数のコードを呼び出し元の場所に展開します。結果として以下のようなコードになります：

```kotlin
fun main() {
    println("操作を開始します")
    println("処理を実行中...")
    println("操作を完了しました")
}
```

### `inline`関数のメリット

1. **パフォーマンスの向上**:
   - 関数呼び出しのオーバーヘッドを削減
   - 特に高頻度で呼び出される小さな関数に有効

2. **ラムダ関数のオブジェクト生成の回避**:
   - 通常、ラムダは実行時にオブジェクトとして生成されますが、`inline`を使用するとこのオブジェクト生成を回避できます

3. **非ローカルリターン**:
   - `inline`関数内のラムダからは外側の関数から直接リターンできます

```kotlin
inline fun forEach(items: List<String>, action: (String) -> Unit) {
    for (item in items) {
        action(item)
    }
}

fun processList(items: List<String>) {
    forEach(items) { item ->
        if (item.isEmpty()) {
            return  // processList関数からリターン
        }
        println(item)
    }
    println("すべての処理が完了しました") // 空の項目があると実行されない
}
```

### 高度な使用例

#### `crossinline`修飾子

非ローカルリターンを禁止する場合に使用します。

```kotlin
inline fun executeWithCallback(crossinline callback: () -> Unit) {
    val runnable = Runnable { callback() }
    runnable.run()
}
```

#### `noinline`修飾子

特定のラムダパラメータに対して`inline`化を無効にしたい場合に使用します。

```kotlin
inline fun execute(action: () -> Unit, noinline callback: () -> Unit) {
    action()
    val runnable = Runnable { callback() }
    runnable.run()
}
```

#### リソース管理のためのinline関数

`use`関数は典型的な`inline`関数の例です。

```kotlin
inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
    try {
        return block(this)
    } finally {
        this.close()
    }
}

fun readFile(path: String): String {
    FileReader(path).use { reader ->
        return reader.readText()
    }
}
```

## ベストプラクティス

1. **適切なサイズの関数に使用する**:
   - 小さな関数に最適（大きな関数ではコード肥大化の原因になる）
   - 頻繁に呼び出される関数に有効

2. **ラムダを引数に取る関数に使用する**:
   - ラムダ生成のオーバーヘッドを削減できる
   - 特に高階関数で効果的

3. **型引数を持つ関数の最適化**:
   - 型消去を回避できる場合がある

開発で適切に使用することで、パフォーマンスが最適化され、メンテナンス性の高いアプリケーションを構築できると思います。ちょっとだけお役に立てれば嬉しいです。
新規開発を目指すなら「Spring Boot → Spring → Hibernate」の順番がベスト

Spring Boot

理由: 設定が簡単で、すぐにアプリを動かせるため、Webアプリ開発の基礎を学ぶのに最適。

学習内容: Spring Bootの基本、Spring MVC、データベース連携（Spring Data JPA）、REST API開発。

Spring（Spring Framework）

理由: Spring Bootの内部でSpringが動いているため、Springの仕組みを理解するとより柔軟な開発が可能になる。

学習内容: DI（依存性注入）、AOP（アスペクト指向プログラミング）、Spring Security、Spring Cloud。

Hibernate

理由: Spring Bootの学習でSpring Data JPAを通じてHibernateの基本を習得できるため、次のステップとしてHibernateの詳細を学ぶと、データベース操作の理解が深まる。

学習内容: O/Rマッピング、キャッシュ管理、トランザクション制御、ネイティブクエリ。
パケットを大泉洋に例えるとTCP/IPの概要が掴みやすかった話。

https://www.youtube.com/watch?v=p-J3iNHHEA8&ab_channel=%E3%82%86%E3%82%8B%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E7%A7%91%E5%AD%A6%E3%83%A9%E3%82%B8%E3%82%AA

パケットを水曜どうでしょうの大泉洋に例えた話
[2]OpenAI APIのセットアップをしていく！！

※知り合い向けに書いた記事を公開しています。後から文体など修正予定です🙏

Part2！！！今回は、OpenAI（ChatGPTを作っている会社）のAPIをSwiftで使う準備をしていくよ〜〜💨💨

目次：
[Part1. カメラで撮影した写真を表示する](https://qiita.com/drafts/c267a9d70a3e69929ded)
[Part2. OpenAI APIのセットアップ](https://qiita.com/kohapizza/items/11f7f25c9f923100e61c) ←ここ！
[Part3. 画像をOpenAIのAPIに送信する](https://qiita.com/kohapizza/items/5416fb7f9429d2e1f734)

### Packageの追加
OpenAIのPackageを追加していくよ！
Packageを追加するとは、他の人や自分が作った便利なライブラリ（コードのかたまり）をプロジェクトに取り込むっていう意味だよ！つまり、ここでは、OpenAIの機能をSwiftで簡単に使えるようにしてくれているhttps://github.com/MacPaw/OpenAI/tree/843e087929aa806adb611dbca93f9a4a7f28be04?tab=readme-ov-fileを取り込んでいくっていうこと！

この先色んなライブラリを使用していくと思うから、やり方を覚えていこう！



メニューバーの「File」 -> 「Add Package Dependencies...」をクリックして、
![スクリーンショット 2025-05-19 15.05.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784072/27757dbc-acc3-4235-a38d-72a9ca579a68.png)

右上の検索バーに「openai」と入れて「Add Package」！
![スクリーンショット 2025-05-19 15.05.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784072/c2467edb-bdcd-4aab-ba80-858a6c1f649c.png)

「Add Package」
![スクリーンショット 2025-05-19 15.06.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3784072/22b919c4-4e5c-49b8-adb0-c59d9a090fd4.png)


### 確かめてみる
ViewController.swiftの```import UIKit```の下に```import OpenAI```を追加してみよう！
エラーが出なければセットアップ完了！
[Laravel]DBインサート時のtimestamp値の違い

# 概要
LaravelにはDB保存メソッドが複数あるが、timestampの扱いが異なる。
忘れないよう自分用にまとめておく。

## なぜこの記事を？
MySQLバージョンアップの検証時に困ったため。
タイムゾーン設定をどちらもJSTにすべきところ、MySQLのタイムゾーンをUTCにしてしまっていた。
その際timestamp値が既存データと異なっていたのだが、**正しい時間のデータも存在してしまっており**原因の特定に時間がかかってしまった。
原因は`save`ではtimestampを補完し、`insert`ではtimestampを補完しないため値に差異が出てしまっていたこと。

# メソッド別クエリまとめ
## 前提
- 対象は`name`(varchar), `created_at`(timestamp)のカラムのみを持つ`user`テーブルと`User`モデル
- saveは以下のコードを実行する
```php
$user = new User(['name' => 'hoge']);
$user->save();
```
- insertは以下のコードを実行する
```php
$users = [
    ['name' => 'hoge'],
];
User::insert($users);
```
- タイムゾーンは以下とする
    - アプリケーションサーバー: JST
    - MySQLサーバー: UTC
- 実行日時はUTCの`2025-05-01 00:00:00`

### save
#### 発行されるクエリ
```sql
insert into `user` (`name`, `created_at`) values (`hoge`, 2025-05-01 00:00:00)
```
#### 設定が`NOT NULL DEFAULT CURRENT_TIMESTAMP`
`created_at`に**アプリケーションサーバーのタイムゾーン準拠(JST)の値**が入る。

#### 設定なし(NULL許容)
`created_at`に**アプリケーションサーバーのタイムゾーン準拠(JST)の値**が入る。

### insert
#### 発行されるクエリ
```sql
insert into `user` (`name`) values (`hoge`);
```

#### 設定が`NOT NULL DEFAULT CURRENT_TIMESTAMP`
`created_at`に**MySQLサーバー準拠の値(UTC)**が入る。

#### 設定なし(NULL許容)
`created_at`に`NULL`が入る

## まとめ
(そもそもtimestamp使わないほうが良いというはなしはいったん横に置いておいて)
DB保存時は同一の値が入るようコード側で記載を統一しておくのが無難と感じた。
【Reactアプリ100本ノック】12 Clock

## はじめに
ゆかっしゅです。
2021年に事務職からデザイナー/コーダーにジョブチェンジをし、現在はフロントエンドエンジニアにスキルアップするべく、モダンフロントエンドを学習しています。

ReactやTypeScriptの基礎学習は終了したのに、なかなか0から自分だけでアプリを作れないので手を動かすべく「Reactアプリ100本ノック」 に挑戦してみようと思います。

また、今回からはchatGPTにお題を作ってもらっています。
本家はこちら

https://qiita.com/Sicut_study/items/cbf1a15fa31727a74514

## Reactアプリ100本ノックルール
- 主要なライブラリやフレームワークはReactである必要がありますが、その他のツールやライブラリ（例: Redux, Next.js, Styled Componentsなど）を組み合わせて使用することは自由
- TypeScriptを利用する
- 要件をみたせばデザインなどは自由

## 12. Clock
![スクリーンショット 2025-05-19 143623.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4068307/0aaf1f55-ccbc-4681-bcbb-6c367b79c8dc.png)

## 問題
毎秒更新されるアナログ時計

## 目的
useStateとuseEffect、Dateオブジェクトを使用して針を設定します。
現時刻のわかるアナログ時計アプリを作成します。

## 達成条件
- 時針、分針、秒針が表示されている
- 針が現在の時刻にあっている
- 時間経過とともに針が動く

## 実際に解いてみた
### 利用技術
React(19.0.0)
TypeScript(5.0)
Next.js(15.3.1)
Tailwindcss(4.0)
jotai(2.12.3)
Vercel

解答時間　2時間

特にライブラリ(react-clock等)を使わずに作成しました。
現在時間は取得できてるのに時針と分針の角度がなぜか合わず、少し苦戦しました。

### リンク
https://react-app-100.vercel.app/

## おわりに
今回からChatGPTにお題を作ってもらっているのですが、あと80個もお題があるか今から不安です...。
今回からgithubのリポジトリも公開することにしました。
お粗末なコードで恐縮ですが、アドバイス等あればぜひよろしくお願いいたします。

https://github.com/saku6911/react_app_100
npx nuxi initコマンドで任意のモジュールを選択したかった

# はじめに
Nuxt.jsのプロジェクトを作成する際に使用するコマンド`npx nuxi init`の実行中、インストールするモジュールを選択するステップがありますが、そこで任意のモジュールだけを選択する方法がわからなかったため、備忘録として記録します。

# わからなかったポイント
下図の画面「Would you like to install any of the official modules?」で、特定のモジュールだけを選択状態にしたかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551450/b39190bd-dee6-4b99-a155-d56ec02d01a7.png)

# 操作方法
* 矢印キーでモジュールを選択
* 全選択または全解除する場合、キーボードの「a」を押す
* **1項目ずつ選択または解除する場合、<font color="red">キーボードの「スペースキー」を押す</font>**

1項目ずつ選択した画面イメージは下図。
![スクリーンショット 2025-05-19 14.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551450/8a97564e-8904-4634-9a98-c91586b720be.png)

以上です。
再帰処理(その4)

# 再帰処理の問題点
プログラミング言語で関数呼び出しをするときは、コンピュータ内部で以下のような事をやっています。
```
１．関数を呼び出しする前に、戻り場所を覚える。
２．関数を呼び出す（＝実行する）。
３．関数の呼び出しが終了したら、覚えておいた戻り場所を取り出して、プログラムの実行をその場所から再開する。
```
再帰処理においては、手続き内から、自分の手続きを何度も何度も呼び出すため、とてもたくさんの戻り場所を覚えなくてはいけません。呼び出す手続きがたとえ同じであっても、呼び出す箇所が変化しているので都度戻る場所を覚えなければいけません。すると、そのうち戻り場所を覚えられなくなってしまい、プログラムが異常終了してしまいます。

# 末尾再帰
この問題を解決するには「末尾再帰」という書き方で手続きを書く必要があります。
(Scheme 言語に限ります。他のプログラミング言語の場合は末尾再帰で書いたとしても解決できるとは限りません。)
sum 手続きを例に説明します。
```
(define (sum items)
  (if (null? items)
      0
      (+ (car items))
         (sum (cdr items))))
```
これはリストの入れ子を考慮しない、単純な sum 手続きです。これを末尾再帰で書いてみます。
```
(define (sum items)
  (define (iter lst sum)
    (if (null? lst)
        sum
        (iter (cdr lst) (+ (car lst) sum))))
  (iter items 0))
```
sum 手続きに内部手続き iter を用意して、iter 手続きの引数に sum を持つようにします。
sum 手続きは、内部手続き iter を、lst に items を、sum に 0 を指定して評価します。

lst が空リストの場合は 0 ではなく sum を返します。
lst が空リストでない場合は、
```
１．iter の lst には (cdr lst) を指定して、次の処理の準備をします。
２．iter の sum には、(car lst) つまり先頭の要素を sum と足し算した結果を指定します。
```
このようにすることで sum には各要素を合計した値で更新されていき、リストが空になったとき最終的な合計が格納されます。特に２．の部分は他プログラミング言語で書くところの
```
sum = sum + var
```
と同じです。Scheme ではいわゆる「代入」を使わずに、「引数に何かを足し算したものを新しい引数にして再帰呼び出しする」として値を加えるという操作をします。

ここで、内部手続き iter は、最後の行で再帰呼び出しをする書き方になっています。この書き方を「末尾再帰」と言い、Scheme においては末尾再帰を使って手続きを書けば、再帰呼び出しの際に戻り場所を覚えなくても済むように設計されています。
# 実行
```
gosh> (sum '(1 2 3 4 5))
15
```
実行しただけでは、変化はわかりづらいと思います。trace 手続きを使うと違いがわかるのですが、ここでは割愛します。
# まとめ
今回は末尾再帰を説明しました。Scheme においては、末尾再帰で手続きを書けば、どれだけ再帰呼び出しをしてもプログラムが異常終了することはありません。
# 蛇足
個人的には末尾再帰の書き方は好きではありません。私の価値観では末尾再帰でない普通の書き方のほうがはるかにエレガントです。さらに、コンピュータの内部の都合でプログラムの書き方を強制（矯正？）されるというのが好きになれません。
Understanding WMI Provider Host (WmiPrvSE.exe) in Windows

[WMI Provider Host](https://blog.corenexis.com/fix-wmi-provider-host-cpu-issues-in-windows), also known as WmiPrvSE.exe, is a crucial Windows system process that allows other applications on your PC to request information about the system. WMI stands for Windows Management Instrumentation, a core component used by system administrators and developers to monitor and manage system devices, drivers, services, and applications. You might notice WmiPrvSE.exe running in the background when tools or scripts are querying system data, such as for performance metrics or event logs. While it generally consumes minimal resources, high CPU usage by this process can sometimes indicate a misbehaving application or script constantly requesting system data. In most cases, WMI Provider Host is safe and essential for Windows to function properly. However, if you suspect abnormal behavior, it's a good idea to scan for malware or check which applications are making frequent WMI calls.
![Fix-WMI-Provider-Host-CPU-Issues-in-Windows-768x512.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4091577/555a36c1-1b32-4517-a852-8a46099693d4.png)
Node.jsとかいう

# Node.jsとは
Node.jsはサーバーサイドでJavascriptを実行できるようにしてくれるもの
(プラットフォームという方が近い)
# Node.jsでできること
・サーバー構築
・データベースにアクセス可能
・アプリケーションプログラムを動かす
# なぜNode.jsを使うのか
・クライアントとサーバーサイドが同じ言語で書ける
・スケーラブル
・非同期処理に強い
・リアルタイム通信が強い
# ディレクトリ構造
テンプレート的な...
```
プロジェクト名
    ├── app.js　　　　 //メインのアプリケーションファイル
    ├── package.json　 //プロジェクトの設定ファイル
    ├── views/　　　　 //テンプレートファイルを格納
        　├── index.ejs
    ├── public/　　　　//静的ファイルを格納(CSS・js・画像など)
        　├── css/
        　├── js/
    ├── routes/　　　　//ルーティング関連のコード
        　├── route.js
```
# Express
Node.jsのフレームワーク
・ルーティング
・ミドルウェアの利用
・静的ファイルの提供
これらが格段に簡単になる
```Node.js
//Expressの利用
const express = require('express');
const app = express();
//ルーティング
app.get('/index', (req, res) => {
    res.render('index.ejs');
});
//ミドルウェアの利用
app.use(express.json());
//静的ファイルの提供
app.use(express.static('public'));
```
# EJS(Embedded JavaScript)とは
HTMLのコードの中にJavascriptを埋め込む(=Embedded)ことができるファイル
# 構文的な何か
基本的にはExpressを利用した構文
(Expressを利用しないと文が3倍くらいになる)
### サーバー起動
```Node.js
app.listen(<ポート番号>, () => {
  //サーバーが指定のポート番号で稼働
});
```
### publicファイルの読み込み
view側からの読み込みはpublicを起点としたパスを指定する
以下はapp.jsの読み込み
```Node.js
app.use(express.static('public'));
```
### ルーティング
特定のパスにアクセスされた場合の処理を記述
下記例だと/パスにアクセスされた場合にindex.ejsに飛ばす処理となっている
オブジェクトを第二引数としてデータを渡せばejsファイルで利用することができる
```Node.js
router.get('/', (req, res) => {
    res.render('index.ejs',<オブジェクト>);    //index.ejsへルーティング
    //オブジェクトがない場合はres.render('index.ejs');でok
});
```
```:オブジェクト例
    const data = {
        title: 'ホームページ',
        userName: 'アクア',
        items: ['水', '霧', '氷']
    };
    res.render('index.ejs', data);　　//連想配列を送る
    res.render('index.ejs',{ title:'ホームページ'});　　//単一でも送れる
```
### ルーティングのインポート
エクスポート側
```Node.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
    res.render('index.ejs');    //index.ejsへルーティング
});
module.exports = router;    //モジュールをエクスポート
```
インポート側
```Node.js
const express = require('express');
const app = express();
//ルーティングのインポート
const router = require('./routes/route');
app.use('/',router);    //ルートの利用
```
### オブジェクトの違い
単にディレクトリやコードを綺麗にするための物なので
app.jsに全てぶちこんでも問題はない
```Node.js
//アプリケーション全体を管理するオブジェクト
const app = express();
//ルーティング専用オブジェクト
const router = express.Router();
```
### EJSファイルでのJavascriptの利用
Javascriptのコードを記述するには<% %>または<%= %>で囲む
<% %>は変数の定義や関数の利用
<%= %>は変数の値などをブラウザに表示したい場合に利用する
```:ejsファイル
<% const item = {id:1,name:'水'} %>
<p>id: <%= item.id %></p>
<p>name: <%= item.name %></p>
```
### データベース接続(MySQL)
```Node.js
const mysql = require('mysql2');
//MySQL接続の設定
const connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  database: 'データベース名',
  password: 'パスワード'
});

//接続テスト
connection.connect(err => {
  if (!err) {
    console.log('接続成功');
  } else {
    console.error('接続エラー:', err.message);
  }
});

//SQL文の実行
connection.query('SELECT * FROM テーブル名', (error, results, fields) => {
  if (!error) {
    console.log('クエリ結果:', results);
  } else {
    console.error('クエリエラー:', error.message);
  }
});

//接続を閉じる
connection.end(err => {
  if (!err) {
    console.log('接続切断');
  } else {
    console.error('切断エラー:', err.message);
  }
});
```
k8s cronjobについて

# 概要
k8s cronjobについて勉強したのでわかったことについてまとめます

# cronjob
k8sで特定の処理を定期的に実行するのに使用されます

# 例
[1]で紹介されていたcronjob manifestを以下に示します。
以下の設定をapplyすると毎分おきに現在時刻とhelloのメッセージを表示する処理が行われます

```
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
```

上記の設定に様々なオプションの設定が行えます

## startingDeadlineSeconds
このオプションを使ってジョブが開始されてから何秒までに終了させるのかを設定できます。これにより何らかの原因でジョブが正常に実行できなかった場合に無限ループを防ぐことが可能となります。
指定時間を過ぎた場合k8s側でジョブが失敗されたと処理されます。

```
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  startingDeadlineSeconds: 30 # 30秒後にはジョブが終了する
  
  jobTemplate:
  (省略）
```

## concurrencyPolicy
このオプションを使ってジョブの実行を同時並行で行うかどうかを設定できます。デフォルトはAllowとなっており、forbidを指定すると無効化できる。
下記の例ではReplaceとなっており、この場合新しいジョブを実行する際に以前のジョブが終了していない場合、以前のジョブを終了してから新しいジョブを実行するようになります

```
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  startingDeadlineSeconds: 30 
  concurrencyPolicy: Replace
  
  jobTemplate:
  (省略）
```

## suspend
このオプションを有効化するとジョブの中断が可能となる.

```
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  startingDeadlineSeconds: 30 
  concurrencyPolicy: Replace

  suspend: false # ここでは中断を無効化している
  
  jobTemplate:
  (省略）
```

# 参考
[1] https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
whisper.cppをMac(M4)で高速処理する[Core ML support]+実行を楽にするおまけ

公式Doc見ながら構築していく
https://github.com/ggml-org/whisper.cpp

## はじめに git clone
```
git clone https://github.com/ggml-org/whisper.cpp.git
cd whisper.cpp
```
## pyenvで環境設定
pythonは3.11推奨ということだったので。
pyenv自体はbrewで入れてるよ
```
pyenv install 3.11.12
pyenv local 3.11.12
python -m venv .env-for-whisper
source .env-for-whisper/bin/activate
```

## 必要なものをpipでインストール
```
pip install ane_transformers
pip install openai-whisper
pip install coremltools
pip install torch==2.5.0
```

## model generate
modelはmediumを使います。
(large-v1はなぞのエラーで落ちます)
(友人の話ではlarge-v3はできたよーとのこと(私は試してない))
```
./models/generate-coreml-model.sh medium
```

## エラーが出る場合
まず最新のxcodeをインストールしているか確認すること！
次に以下のようなエラーが出た場合、
`xcrun: error: unable to find utility "coremlc", not a developer tool or in PATH`
xcrunのパスを確認しましょう。
```
xcode-select -p
(私の場合のoutput-> /Library/Developer/CommandLineTools)
```
このような場合はパス変更が必要です、以下のコマンドで変更します。
```
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
```
念のために動くか確認しておきましょう。
```
xcrun coremlc
coremlc: error: usage: coremlc <command> <inputdocument> <outputpath> [options ...]
```
動いた！

## 改めてmodelのgenerateとdownload
```
./models/generate-coreml-model.sh medium
./models/download-ggml-model.sh medium
```
うまくいったら以下な感じのログ出る
```
models/coreml-encoder-medium.mlmodelc -> models/ggml-medium-encoder.mlmodelc
```

あとは公式の手順通りにビルドをかける。
```
cmake -B build -DWHISPER_COREML=1
cmake --build build -j --config Release
```

## サンプル音声で出力を確認
```
./build/bin/whisper-cli -m /Users/asadeyy/tools/whisper.cpp/models/ggml-medium.bin -f samples/jfk.wav
```
以下ログ(抜粋)
```
system_info: n_threads = 4 / 14 | WHISPER : COREML = 1 | OPENVINO = 0 | Metal : EMBED_LIBRARY = 1 | CPU : NEON = 1 | ARM_FMA = 1 | FP16_VA = 1 | MATMUL_INT8 = 1 | DOTPROD = 1 | ACCELERATE = 1 | AARCH64_REPACK = 1 |

main: processing 'samples/jfk.wav' (176000 samples, 11.0 sec), 4 threads, 1 processors, 5 beams + best of 5, lang = en, task = transcribe, timestamps = 1 ...


[00:00:00.000 --> 00:00:11.000]   And so, my fellow Americans, ask not what your country can do for you; ask what you can do for your country.
```
でぎだ！！！

# おまけ(ailias設定して使いやすくすっぞ)
`.zshrc`を開こう
```
vim ~/.zshrc
```
一番下に以下を追加
```
alias whisper-medium='~/tools/whisper.cpp/build/bin/whisper-cli -m ~/tools/whisper.cpp/models/ggml-medium.bin -f'
```
こんな感じで実行できるよ！
日本語の場合は`ja`をいれて、文字起こしのtxtが欲しいので`-otxt`を付与する。
```
whisper-medium 音声ファイル.wav -l ja -otxt
```

## あとがき
やっぱりcoreML使うと爆速でええですね。てか凄すぎる。
みなさんも良い文字起こしライフを！

(※本記事は[以前zennのスクラップに雑書きしていたもの](https://zenn.dev/asadeyy/scraps/5bcf874e848bcc)を読みやすく再編したものです。)
ピカチュウの「10まんボルト」をモデル化


## はじめに

アニメやゲームでおなじみの **「10まんボルト」**。  
「10万ボルト」という圧倒的な高電圧を、ピカチュウはいったいどうやって生み出しているのでしょうか？

この記事では、**電気工学・信号処理・Python**を使って、  
「10まんボルト」を科学的に**モデル化＆可視化**してみたいと思います。

---

## 1. そもそも「10まんボルト」って何？

「10万ボルト」は電圧の単位で、実際の電力設備や雷の規模に近い高電圧です。  
例えば、電力会社の超高圧送電線が約10万ボルト〜50万ボルト程度。

つまり、ピカチュウは変電所クラスの**高電圧電気エネルギー**を放出していると言えます。  
これを工学的に分解すると、以下の2つの成分に着目できます。

- **1. 直流成分（DC）**：ピカチュウの基礎的な電圧出力
- **2. ノイズ成分（AC）**：不安定に重畳する微小な交流成分

---

## 2. モデル1：10万ボルトの直流電圧に0.5Vのサイン波ノイズ

### 数式モデル

$$
V(t) = 100,000 + 0.5 \times \sin(2\pi f t)
$$

- **100,000V**： ピカチュウの基本出力（直流）
- **0.5V**： 電子機器誤動作を誘発するレベルの高周波ノイズ
- **f**： ノイズ周波数（ここでは1kHzと設定）

### Python実装（可視化コード）

```python
import numpy as np
import matplotlib.pyplot as plt

# Sampling parameters
fs = 10000  # Sampling frequency (Hz)
t = np.linspace(0, 0.02, fs)  # 0.02 seconds duration

# Voltage model
dc_voltage = 100000  # 100kV DC
noise_amplitude = 0.5  # 0.5V noise
frequency = 1000  # 1kHz

# Signal with noise
v_t = dc_voltage + noise_amplitude * np.sin(2 * np.pi * frequency * t)

# Plot
plt.plot(t, v_t)
plt.xlabel('Time (s)')
plt.ylabel('Voltage (V)')
plt.title("Pikachu's 100kV with 0.5V Sine Wave Noise")
plt.show()


```
⸻

3. 微分してみる（dV/dt解析）

電圧変化率（dV/dt）は、スパイク発生や電磁波ノイズの原因となる指標です。

定数100,000Vは微分で消え、ノイズ部分だけが残ります。

$$
\frac{dV(t)}{dt} = 0.5 \times 2\pi f \times \cos(2\pi f t)
$$

これにより、時間変化の激しいスパイク特性を評価できます。

⸻

4. モデル2：減衰正弦波モデル（スパーク・サージ再現）

「10まんボルト」はスパーク放電や雷サージのように
減衰しながら振動していると考えることもできます。

数式モデル

$$
V(t) = 100,000 \times e^{-\alpha t} \times \sin(2\pi f t)
$$
	•	α： 減衰率（ここでは500）
	•	f： 振動周波数（1kHz）

Python実装（可視化コード）

```Python
import numpy as np
import matplotlib.pyplot as plt

# Sampling parameters
fs = 10000  # Sampling frequency (Hz)
t = np.linspace(0, 0.02, fs)  # 0.02 seconds duration

# Damped sine wave model
alpha = 500  # Damping factor
frequency = 1000  # 1kHz
damped_wave = 100000 * np.exp(-alpha * t) * np.sin(2 * np.pi * frequency * t)

# Plot
plt.plot(t, damped_wave)
plt.xlabel('Time (s)')
plt.ylabel('Voltage (V)')
plt.title('Damped 100kV Sine Wave (Discharge Model)')
plt.show()

```
【オンプレ→クラウドのデータ転送を自動化】AWS DataSyncとは？

# 【オンプレ→クラウドのデータ転送を自動化】AWS DataSyncとは？

「オンプレミスからS3へ安全にデータを転送したい」  
「大量のファイルを定期的に移動させたい」  
そんなときに活躍するのが **AWS DataSync** です。

---

## 🔸 AWS DataSyncとは？

**AWS DataSync** は、オンプレミスや他のクラウドから**AWS上のストレージ（S3, EFS, FSxなど）へ高速・安全にデータを転送するマネージドサービス**です。

- ✅ 大規模データを数百TBレベルでも転送可能  
- ✅ ネットワーク経由で**エージェントを使って簡単接続**  
- ✅ GUIやAPIからスケジュール設定・自動化も可能

---

## 🔸 対応するデータソース・宛先

| ソース（転送元）                        | デスティネーション（転送先）           |
|-------------------------------------|------------------------------------|
| オンプレミスのNFS / SMB             | Amazon S3                          |
| AWS内のEFS / FSx / S3              | Amazon EFS, Amazon FSx, S3など     |
| 他クラウドのファイル共有（SMB/NFS） | S3やEFSなど                         |

---

## 🔸 主なユースケース

| ユースケース                   | 説明                                                     |
|----------------------------|----------------------------------------------------------|
| オンプレのファイルサーバ移行       | SMB/NFSからS3/EFSへ簡単・高速にデータ移行                    |
| 定期的なバックアップ             | 毎日夜間に自動でバックアップをクラウドに転送                    |
| ビッグデータの一括転送           | 分析基盤（RedshiftやAthena）に使うための一時的なデータ移動など     |
| ストレージの階層化（コールド化） | 頻繁に使わないデータをS3 Glacierへ移してコスト削減               |

---

## 🔸 DataSyncのメリット

- ✅ 最大**10倍の高速転送**（並列処理＋最適化）  
- ✅ **転送時にデータ整合性チェック**（MD5検証）あり  
- ✅ **VPCエンドポイント経由の通信**でセキュア  
- ✅ **AWS BackupやStorage Gatewayと連携可能**  
- ✅ GUIだけで簡単操作。CLI/APIでも自動化対応

---

## 🔸 利用の流れ（ざっくり）

1. **エージェントをデプロイ**（オンプレ or EC2 上）  
2. **ソースと宛先を指定**（NFS, SMB, S3など）  
3. **転送タスクを作成＆実行**（オプションでスケジュール設定も可）  
4. **CloudWatchで進捗モニタリング・ログ確認**

---

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

| サービス        | 特徴                                       |
|---------------|------------------------------------------|
| AWS DataSync  | 大容量ファイルの高速・定期転送に最適。オンプレとS3/EFS間も対応。 |
| AWS Transfer Family | SFTP/FTPS/FTP対応。ユーザー単位でのファイル受け渡しに適している。 |
| Snowball Edge | 超大容量（数PB）を物理デバイス経由で移行。ネットが遅い環境向き。 |

---

## 🔸 まとめ

AWS DataSyncは、**安全・高速・自動的にデータを移動したい組織**に最適なサービスです。  
オンプレからクラウドへの移行や、クラウド内でのバックアップ・アーカイブ処理にも大活躍します。

**GUIベースで導入が簡単**なので、インフラの知識がそれほどなくてもすぐに使い始められます！

---

## 🔗 公式リンク

- [AWS DataSync – AWS公式](https://aws.amazon.com/jp/datasync/)  
- [DataSync ユーザーガイド](https://docs.aws.amazon.com/datasync/latest/userguide/what-is-datasync.html)

---

📘 AWSのストレージ＆データ移行系サービスについて今後も発信していきます。よければフォロー＆いいねお願いします！
NotebookLMの音声要約を使った決算短信分析法

# はじめに

企業の決算短信は大量の情報が詰まっており、読み解くのに時間がかかります。  
本記事では **NotebookLM** の「音声要約(Audio Overview)」機能を使い、短時間で要点を抽出し、投資判断に役立つ視点まで含めた分析フローをご紹介します。

---

## 目次

1. [背景](#背景)  
2. [NotebookLMの音声要約とは](#notebooklmの音声要約とは)  
3. [手順概要](#手順概要)  
4. [実践：音声要約の実行](#実践音声要約の実行)  
   - 4.1 [決算短信PDFを読み込む](#決算短信pdfを読み込む)  
   - 4.2 [Audio Overviewを起動](#audio-overviewを起動)  
   - 4.3 [プロンプトを設定](#プロンプトを設定)  
5. [実行結果例と解説](#実行結果例と解説)  
6. [まとめ](#まとめ)  

---

## 背景

- 決算短信には「売上高」「営業利益」「経常利益」「純利益」をはじめ、  
  事業セグメントや業績変動要因、今後の見通しなど重要情報が多い。  
- 投資家・ビジネスパーソンは「定量データの解釈」と「投資価値判断」を同時に行いたい。  
- 本手法では、notebook lmのAIホストに的確な指示（プロンプト）を与え、  
  音声要約から**投資判断に必要な要素**まで一気通貫で取得します。

---

## NotebookLMの音声要約とは

- PDFやドキュメントを読み込ませると、  
  AIが読み上げ用の原稿を自動生成 → 音声にしてくれる機能。  
- テキスト要約よりも聞き流しがしやすく、  
  会議や移動中のキャッチアップにも有効。  
- カスタマイズ画面で「AIホストのフォーカス」を細かく指定可能。

---

## 手順概要

1. 決算短信PDF(URL)をNotebookLMにアップロード  
2. メニューから **Audio Overview → Customise** を選択  
3. 投資家向けプロンプトを貼り付け  
4. 「Generate」で音声要約を作成  
5. 生成された要約スクリプトを確認・活用  

---

## 実践：音声要約の実行

### 決算短信PDFを読み込む

1. NotebookLMを開き、画面左の「Sources」エリアにPDFをドラッグ & ドロップ  
2. 「Select all sources」にチェックを入れる  
3. **例として以下のPDFを読み込ませています**  
   - https://www.nihon-e.co.jp/ir/library/pdf/closing/h37-20250411-01.pdf  

---

### Audio Overviewを起動

1. 右上メニューから **Studio → Audio Overview** をクリック  
2. 「Deep Dive conversation」「Customize」ボタンが表示されるので **Customize** を選択  

---

### プロンプトを設定

以下のプロンプトを入力します。

> **日本語プロンプト（投資判断の視点あり）**  
> ```
> 決算短信の内容について、  
> 売上高・営業利益・経常利益・純利益などの主要な財務指標にフォーカスし、  
> 前年同期比の増減要因や今後の見通しを中心に解説してください。  
> あわせて、成長性・収益性・財務の安定性・事業の将来性といった観点から、  
> この会社に投資する価値があるかどうかについても触れてください。  
> 投資家やビジネスパーソン向けの要約を意識してください。
> ```

![Screenshot 2025-05-19 at 13.00.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/7b7b7912-6c4a-4cca-8ba3-06cb53994258.png)

---

## 実行結果例と解説

1. **要約スクリプト取得**  
   - AIが自動生成した「読み上げ用原稿」がテキストで出力される  
2. **音声ファイルのダウンロード**  
   - 生成された音声を再生・ダウンロードし、社内資料やプレゼンに流用可能  
3. **分析ポイント**  
   - **定量分析**：売上・利益の増減要因  
   - **定性分析**：事業セグメントごとの成長ドライバー  
   - **投資判断**：資本効率や業界ポジション、将来リスクの評価  

---

## まとめ

- NotebookLMの音声要約を使えば、膨大な決算短信を短時間で「聞き流し」ながら重要情報をキャッチアップ可能。  
- プロンプトで「投資判断の軸」を明示することで、  
  要点＋投資価値判断まで含めたレポートが一度に得られます。  
- 本手法をテンプレート化しておけば、他社決算や業界レポートでも同様のフローで効率的に分析できます。  

---

以上が **NotebookLMの音声要約を使った決算短信分析法** のご紹介です。  
ぜひ自社の決算分析にお役立てください！
【全4回】Kaggle - House Price挑戦記

# はじめに
2025年4月1日から機械学習エンジニアにキャリアチェンジをした、完全なる初心者である筆者による、Kaggleの有名なコンペティション、House Pricesの挑戦を、全4回に分けて記録しました。

このコンペ、あまりにも有名すぎて調べるといくらでも解説などが載っています。しかし、多くの解説が「これが上手くいきます」以上の説明がなく、その手前の「なぜその作業をしようと考えたのか」「どんなことを試してみたら上手く行かなかったのか」や「その失敗からなぜそのような作業をしたのか」という説明が少ないと思います。

なので、この一連の記事では「データをのぞいてみる」ところから、可能な限り全ての作業を一つずつ「なぜそうしたのか」の説明もしながらHouse Pricesコンペティションを進めました。

ですから、この連載の目的は「Kaggleに勝つ」「ハイスコアを目指す」ではなく、「MLエンジニアとしての思考・試行を分解する」ことにあります。他人の記事を探せばいくらでもハイスコアを取る方法は書いてありますが、一つひとつの作業や試行を真の意味で理解をするために、それらはいっさい参考にしていません。

言うなればこの連載は「コンペの挑戦実況」を書き起こしたものです。
かなり長く、またメモ書きをほぼそのまま記事化しているので、ところどころおかしな文になっているかもしれませんが、ご了承ください。

## ソースコード
この連載で書かれたコードについては、下記のリポジトリをご覧ください。
[GitHub: kaggle-house-prices](https://github.com/automatedtomato/kaggle-house-prices)

# 記事一覧

## ①全ての作業を自動化する
- [挑戦記①：全ての作業を言語化する](https://qiita.com/automatedtomato/items/655590c5be21f7c8b63e)
セットアップからデータの取得、探索的データ分析と特徴量作成まで。

## ②ベースラインモデル作成
- [挑戦記②：ベースラインモデル作成](https://qiita.com/automatedtomato/items/8b5abc0bbd51b70e590f)
作成した特徴量をもとに、簡単な線形モデルで特徴量同士の関係などを把握。

## ③ランダムフォレスト回帰
- [挑戦記③：ランダムフォレスト回帰](https://qiita.com/automatedtomato/items/fc24c591452dc7791924)
特徴量同士の非線形的な関係を捉えるため、決定木系のモデルに移行。Optunaを使用したハイパーパラメータチューニングなど。

## ④XGBoostから提出まで
- [挑戦記④：XGBoost実装から提出まで](https://qiita.com/automatedtomato/items/748e2f948d6bdca3ef1e)
ブースティングによる予測精度の向上と過学習の抑制のため、XGBoostを本番モデルとして選定。SHAP分析による可視化など。
WindowManager 1.4.0で置き換えが必要になったisAtLeastBreakpointの解説

[Jetpack WindowManager 1.4.0](https://developer.android.com/jetpack/androidx/releases/window?hl=en#version_14_2) で `WindowWidthSizeClass` / `WindowHeightSizeClass` への直接のアクセスが deprecated になりました。

```kotlin
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
// deprecated
if (windowSizeClass.windowHeightSizeClass == WindowHeightSizeClass.COMPACT) {
    // Height is Compact
}
```

deprecated になって代わりに `isAtLeastBreakpoint` の API が追加されたので、その置き換え方のメモです。

:::note warn
`WindowSizeClass` には `androidx.window.core.layout.WindowSizeClass` と `androidx.compose.material3.windowsizeclass.WindowSizeClass` が存在しますが、ここでの内容は前者のものになります。
:::

## 置き換え

`WindowSizeClass` には以下の定数が用意されており、それを `isAtLeastBreakpoint` に渡すことで特定のサイズ以上かを確認することができます。
もちろん任意の値を渡すことも可能です。

```kotlin
const val WIDTH_DP_MEDIUM_LOWER_BOUND = 600
const val WIDTH_DP_EXPANDED_LOWER_BOUND = 840
const val HEIGHT_DP_MEDIUM_LOWER_BOUND = 480
const val HEIGHT_DP_EXPANDED_LOWER_BOUND = 900
```

:::note info
1.5.0 以降では上記の定数に加えて Width に Large と Extra Large の定数が追加されます。
```kotlin
const val WIDTH_DP_LARGE_LOWER_BOUND = 1200
const val WIDTH_DP_EXTRA_LARGE_LOWER_BOUND = 1600
```
:::

また、`isAtLeastBreakpoint` には Width/Height を個別に判定するメソッドも用意されています。

```kotlin
fun isWidthAtLeastBreakpoint(widthDpBreakpoint: Int): Boolean
fun isHeightAtLeastBreakpoint(heightDpBreakpoint: Int): Boolean
fun isAtLeastBreakpoint(widthDpBreakpoint: Int, heightDpBreakpoint: Int): Boolean
```


### 特定の WindowSizeClass 以上かの判定

`isAtLeastBreakpoint` が true であればセットしたサイズ以上になります。

```kotlin
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
if (windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)) {
    // Width is Medium or higher
}

if (windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND)) {
    // Height is Medium or higher
}

if (
    windowSizeClass.isAtLeastBreakpoint(
        widthDpBreakpoint = WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND,
        heightDpBreakpoint = WindowSizeClass.HEIGHT_DP_EXPANDED_LOWER_BOUND,
    )
) {
    // Width and height are Expanded or higher
}
```


### 特定の WindowSizeClass 以下かの判定

以下であることを返してくれる関数はないので、`isAtLeastBreakpoint` の否定で判定する必要があります。

```kotlin
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
if (!windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND)) {
    // Width is Compact
}

if (windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_EXPANDED_LOWER_BOUND)) {
    // Height is Medium or lower
}

if (
    !windowSizeClass.isAtLeastBreakpoint(
        widthDpBreakpoint = WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND,
        heightDpBreakpoint = WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND,
    )
) {
    // Width and height are Compact
}
```

### 組み合わせ

`isWidthAtLeastBreakpoint` と `isHeightAtLeastBreakpoint` の組み合わせで複雑な条件の判定もできます。

```kotlin
if (
    windowSizeClass.isWidthAtLeastBreakpoint(WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) &&
    !windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND)
) {
    // Width is Medium or higher, height is Compact
}
```
激闘！AIのAPIとdatabese連携！

# 本日のプロジェクト作業まとめ
本日は、Vercel AI SDKを使用したNext.jsベースのAIチャットボットアプリケーションの構築と設定を行いました。主に以下の作業を実施しました：

## 1. 環境構築
- プロジェクトの基礎となるmuscle_botディレクトリを作成
- 必要な依存パッケージをインストール（Next.js、React、Tailwind CSS、Vercel AI SDKなど）
## 2. 認証設定
- Auth.js (旧NextAuth.js) の設定
- .env.localファイルにAUTH_SECRETを設定
## 3. Groq (xAI) の設定
- Groq APIキーを取得し、.env.localファイルにXAI_API_KEYとして設定
- デフォルトAIプロバイダをxaiに設定
- providers.tsファイルを修正し、Groqのllama3-70b-8192モデルをデフォルトとして設定
## 4. データベース接続問題の解決
- PostgreSQLデータベース接続が課題となったため、middleware.tsを修正して認証チェックをバイパス
- これにより、データベース依存なしでアプリケーションの動作が可能に
```middleware.ts
export async function middleware(request: NextRequest) {
  // すべてのリクエストを許可する
  return NextResponse.next();
}
```
## 5. AIチャットボット機能の実装
- テキスト対話機能を実装（Groq APIを使用）
- ユーザーからのメッセージ入力と応答表示の機能を確認
- llama3-70bモデルによる高品質な応答生成を確認
### 課題と解決策
- データベース接続エラー：

    - Supabaseの接続URLに問題があったため、認証バイパスで一時的に解決
- AI SDKの更新に伴う互換性問題：
    - openaiのインポートパスが変更されていたため、@ai-sdk/openaiからインポートするよう修正
###  次のステップ
- Vercel PostgresまたはSupabaseの正しい接続設定
- データベースマイグレーションの実行
- ユーザー認証の完全な実装
- チャット履歴の保存機能の有効化
## 結論
データベース接続の課題はあるものの、AIチャットの基本機能は正常に動作しています。ミドルウェアの修正により、認証チェックをバイパスし、Groq API経由でのAI応答生成が機能しているため、基本的なチャットボットの動作を確認できました
Databricks Genie MCPサーバーによるシステムテーブルへの問い合わせ

こちらで紹介されているMCPサーバーを動かしてみます。

https://qiita.com/taka_yayoi/items/6db18b3d4f0054d4f43e

リポジトリはこちら。

https://github.com/jaibehl97/databricks_genie_mcp/tree/main

以前動かしたこちらと似ていますが、上のリポジトリの方が多くのツールを公開しています。

https://qiita.com/taka_yayoi/items/b29edb7daa50057d9e36

# ローカルマシンでの設定

## MCPサーバーの設定

```sh
git clone https://github.com/jaibehl97/databricks_genie_mcp/
cd databricks_genie_mcp
```

uvを使ってパッケージをインストールしておきます。

```sh
uv venv
source .venv/bin/activate
uv pip install -r requirements.txt
```

認証情報を`.env`ファイルに格納しておきます。

```sh
vi .env
```
```.env
DATABRICKS_HOST=https://<Databricksホスト名>.cloud.databricks.com
DATABRICKS_TOKEN=<パーソナルアクセストークン>
```

## MCPホスト(クライアント)の設定

Cloude Desktopで動かしたいので、`claude_desktop_config.json`を編集します。

```json:claude_desktop_config.json
{
  "mcpServers": {
    "databricks-genie": {
      "command": "uv",
      "args": [
          "--directory",
          "/Users/takaaki.yayoi/Documents/Cursor/Genie_MCP/databricks_genie_mcp/",
          "run",
          "server.py" 
      ],
      "workingDirectory": "/Users/takaaki.yayoi/Documents/Cursor/Genie_MCP/databricks_genie_mcp/" 
    }

  }
}
```

このようになっていれば、MCPサーバーが稼働しています。

![Screenshot 2025-05-19 at 13.47.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/13abd096-999d-4882-b663-bc6f9a65fe4d.png)

# Databricksでの設定

接続先となるGenieスペースを作成しておきます。`system`配下にあるシステムテーブルを適宜追加します。

![Screenshot 2025-05-19 at 13.48.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/de85f217-e421-4ad4-a295-2f297eb5fda5.png)

ここでのMCPサーバーはGenieスペースのIDを引数にしますので、作成したGenieスペースのIDをコピーしておきます。URLから抽出できます。

> https://<ホスト名>.cloud.databricks.com/genie/rooms/01f034636a8f1484baa721f5e0150d4a/

上の場合、rooms以降の`01f034636a8f1484baa721f5e0150d4a`がIDです。

# Claude Desktopからの問い合わせ

Genieに問い合わせるような質問をしていきます。

> 01f034636a8f1484baa721f5e0150d4aのGenieスペースに今月の消費を聞いて

ツールが呼び出される際には同意が求められます。

![Screenshot 2025-05-19 at 12.44.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/980c9c22-6697-4216-b38f-b10339501d66.png)
![Screenshot 2025-05-19 at 12.45.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/96c2a07b-6a28-42fb-8ecf-28ac499a4549.png)

結果が返ってきます。

![Screenshot 2025-05-19 at 13.51.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/42334b5b-eb6c-4f4b-a90c-87e71c98a0b8.png)

スレッド内であれば、以降はスペースのIDを指定する必要はありません。

> ノートブックで最も何が頻繁に実行されているのか？

![Screenshot 2025-05-19 at 13.53.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/577159d2-1c7a-4161-8d3c-d9ffab7f0523.png)

元記事でも言及されているように、システムテーブルとGenieの組み合わせは強力ですね。それにMCPが加わることで活用の場が広がる感じです。

あと、CursorもMCPをサポートしているので、全く同じ設定で利用することができます。これも標準化のメリット。

![Screenshot 2025-05-19 at 14.09.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f06a346b-6895-4f2f-84eb-71dbb42403c1.png)

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
自動車産業について

# はじめに
自動車産業についてのコースを学んだのでその内容をアウトプットとして書かせていただきました

# 本題

:::note info
## わからない用語メモ
- OEM(Original Equipment Manufacturer)
  - 自社のブランドを他社に製造を委託するビジネスモデル
- SOW(Share off wallet)
    - 特定の顧客が購入した商品のカテゴリのうちの自社の商品、サービスが占める割合
- CASE
    - 自動車の技術革新を指す。以下の頭文字を合わせた造語。
        - Connected：自動車のIoT
        - Autonomous：自動運転
        - Shared & Services：所有->共有
        - Electric：電気自動車

- MAAS（Mobility as a Service)
    - 移動すること自体をサービスとして捉える
    - CASEの先にある未来として注目される

- 電気自動車の種類
    - BEV(Battery Electric Vehicle)
        - バッテリ式電気自動車
        - エンジンの代わりにバッテリの電力を使用
    - HEV(Hybrid Electric Vehicle)
        - ハイブリッド自動車
        - ガソリン、電力の２つの動力を備える車
    - PHEV(Plug in Hybrid Electric Vehicle)
        - プラグインハイブリッド自動車
        - HEVと同様2つの動力を持つ
        - 外部電源が利用できるのが特徴
    - FCEV(Fuel Cell Electric Vehicle)
        - 燃料電池自動車
        - 他のEVとは違い水素を燃料とする
- Agnostic Service
    - 標準化を促進するサービス（ここの理解はまだ自信がないです）

:::

- 自動車は最初ハードウェアとOSで構成されていた
- 近年はあらゆるものにつながる機能を有する自動車、コネクテッドカーがトレンドとなる
    - 自動車<->自動車の通信
    - 自動車<->クラウドの通信
- そういった中で、OEMは一回の売り上げを伸ばすよりも、SOWを増やしていくことにシフトするようになった
- またコネクテッドカー、自動運転等の自動車業界の先進技術を指すCASEといった言葉も誕生した
- 自動車業界ではCASEの促進のためAgnostic Solutionの提供が行われている
- 今までの自動車業界のビジネス形態はB2B,B2B2Cといったものであった
- 今後はEcosystem to Customer(E2C)が主流の形態となっていく


# 終わりに
自動車業界の歴史は今まで学んだことがなく何もかもが新鮮でした。

# 参考文献
- https://ferret-plus.com/7464
- https://www.investopedia.com/terms/s/share-of-wallet.asp
- https://mba.globis.ac.jp/about_mba/glossary/detail-12199.html
- https://www.nikken-totalsourcing.jp/business/tsunagu/column/553/
- https://www.mlit.go.jp/sogoseisaku/japanmaas/promotion/
- https://www.techtarget.com/whatis/definition/agnostic
- https://www.shindengen.co.jp/column/vol3/
コーディングテストでチームにぴったりなエンジニアを仲間にしよう

こんにちは！
ポーラ・オルビスホールディングスのITプロダクト開発チームでスクラムマスターをしている川田です。

私たちITプロダクト開発チームでは、エンジニア採用にコーディングテストを取り入れています。今回は、私たちの採用プロセスにおいてコーディングテストをどのように活用しているか共有したいと思います:grinning:

# なぜコーディングテストを導入したのか
私たちが採用プロセスにコーディングテストを導入した理由はシンプルで、面接だけで候補者の方の技術的なスキルを判断するのが難しいと感じたからです。
私たちが本格的に内製開発を始めてから2年が経過し、担当するプロダクトも徐々に増えてきました。チームをさらに拡大して内製開発の範囲を広げていきたいと考えていますが、エンジニアをゼロから育てる余力を生み出すのは難しい状況です。そのため、言語や環境は問わず多少なりとも何らかの開発経験があり、チームの利用技術をキャッチアップしながら組織と共にご自身も成長していける方が私たちのチームにマッチすると考えています。技術のキャッチアップや自己成長の面は職務経歴書や面接を通じて判断できますが、スキル面の判断に課題を感じ、コーディングテストの導入に至りました。

# どのようにテストを行っているか
テストの実施は、コーディングテストを行うためのWebサービスを利用しています。外部サービスを利用する分のコストは必要になりますが、テストという側面で考えたとき同一の環境および同一の条件でテストを実施できるため、候補者の方にとって公平性が担保できるという大きなメリットがあります。また、数多くのテスト問題の提供、各企業にフィットしたテスト問題のカスタマイズや作成代行、テストの採点やスコアリングの自動化、過去の受験データや他社の受験データを元にした分析といった、企業側の採用を手助けする機能が提供されていることも非常に助かっています:+1:
コーディングテストのサービスは数多くあり、1つのサービスの中でも複数のプランが提供されています。最低限の機能が揃っているエントリープランや、短期の契約（6か月～）もあるため、それらを利用してスモールスタートしてみるのもよいと思います:ok_hand:

# どのようなテストを行っているか（テスト設計）
テストの内容については以下に示したジャンルの問題をいくつか選定し、それらを採用ポジションや経験年数に応じて組み合わせたものを数パターンほど準備しています。

1. 簡易なweb画面を作る問題
1. アルゴリズムを考えて実装する問題
1. 様々な知識を問う選択式の問題

テスト設計にあたっては同程度の経験年数をお持ちの候補者の中でどのくらいに位置するのかを見るのはもちろんですが、経験年数を問わず共通の問題を出題することで年次によって回答がどのように変化するかといった観点も考慮しています。現状ではまだデータを集めている段階ですが、将来的にはこの結果を元にテスト内容の見直しを行っていきたいと考えています。
また、テストのレベルとして極端に難しいものは取り入れていません。私たちが利用しているサービスでは、競技プログラミングで使われるようなレベルの問題や数学的な考え方を知らないと解けないような問題も提供されています。そのような難しい問題に解答できる高いレベルがあることは非常にすばらしいですが、チームで業務を進めるうえではまず基本となるプログラミング的な思考ができるかどうかが重要と考えているためです。そもそも、あまり難しい問題や長時間にわたる問題を選定すると候補者の方にとって負担になるため、バランスを考えたテスト設計が重要です。

# テスト結果をどうやって判断しているか
テストの結果の判断についてはあらかじめ以下のような評価基準を定めておき、その内容に基づいて採点結果や実際のソースコードを元に判断しています。

|観点|内容|
|:-|:-|
|解答の正確性|採点結果を元に、正しく解答できているか|
|アルゴリズム・データ構造|使用しているアルゴリズムやデータ構造が適切か|
|エラーハンドリング|要件に応じた正しいエラーハンドリングができているか|
|保守性|適度な関数化を行っているかなどから判断|
|可読性|命名規則、コメントの内容などから判断|

あらかじめ評価基準を決めておくことで、何となくよさそうといったあいまいな判断や判断軸のブレを防ぐことができ、公平性の担保に繋がります。
また、確認すべきポイントが明確になるため判断の効率アップも見込めますが、私たちのチームではコーディングテストを単なるスクリーニングとは考えていないため、効率のみを追求していません。採点された点数だけで判断せず、ソースコードの内容やコードの説明（解答の提出後に時間無制限で説明を記載できる機能、ですが書いていただく方は少ない・・・:sweat_smile:）に至るまでしっかりと確認し、チームでご活躍いただけるかどうかを判断していきたいと考えています。

# まとめ
組織風土やスキルレベルがミスマッチしてしまうと、企業と候補者の方それぞれにとってデメリットになります。そのため、面接によって組織の風土や雰囲気とマッチするか確認するのと同じようにコーディングテストが利用できればと考えています。
採用を担当されている方に対して私たちの取り組みが参考になれば嬉しいと共に、候補者の方に対しても私たちがコーディングテストを実施する背景を理解いただき、ぜひ前向きにチャレンジするきっかけとなれば嬉しいです:relaxed:

# :two_men_holding_hands:一緒に働く仲間を募集しています:two_women_holding_hands:
私たちITプロダクト開発チームに興味を持っていただき、いっちょテストを受けてみるか:muscle:と思っていただいた方は、ご応募お待ちしております！:bow:

https://engineer.po-holdings.co.jp/

https://hrmos.co/pages/po-holdings/jobs/0000061

https://hrmos.co/pages/po-holdings/jobs/0000038
Let's Encryptで証明書取得及び証明書廃止の手順

案外忘れやすいLet's Encryptでの証明書取得と廃止の方法。

メモ代わりに記事に残しておきます。

まず、証明書の取得は以下のコマンド。-w にはApacheのDocumentRootを設定。-dには認証するドメインを指定する。
```
certbot certonly --webroot -w /var/home/site/xxxx.yyyy.info -d xxxx.yyyy.info
```
そして、証明書の廃止は以下のコマンド。--cert-pathには廃止する証明書のファイルを設定する。コマンド実行後に色々聞かれるが全て[Y]esで答えていくこと。
```
certbot revoke --cert-path=/etc/letsencrypt/live/xxxx.yyyy.info/cert.pem
```
Spring Bootで1:NリレーションのCRUD APIを構築する際に注意したこと（N+1対策含む）


Spring Boot × JPAで1:Nリレーションを扱うAPIを実装した際に、パフォーマンスや設計上で注意すべき点をまとめました。  
本記事では以下の2点にフォーカスしています：

- `@ManyToOne`の遅延読み込みによる **N+1問題**
- `fetch join` を使った **パフォーマンス改善**

---

## 🧱 ドメイン前提：Session × Feedback

- 1つの `Session` に対して複数の `Feedback` を持つ構成
- JPA上のマッピングは以下の通りです：

```java
@Entity
public class Feedback {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String message;
    private LocalDateTime createdAt;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "session_id")
    private Session session;
}
```

## 🐌 問題：N+1クエリの発生
以下のように取得すると、session の参照ごとに追加のSQLが発行されます。
```java
List<Feedback> feedbacks = feedbackRepository.findAll();
for (Feedback feedback : feedbacks) {
    System.out.println(feedback.getSession().getSubject());
}
```

## ✅ 解決策：fetch joinによる一括取得
```java
@Query("SELECT f FROM Feedback f JOIN FETCH f.session")
List<Feedback> findAllWithSession();
```
このように明示的に JOIN FETCH を使うことで、Feedback取得時に関連Sessionも同時に取得できます。

→ getSession() を呼び出しても 追加クエリは発行されません。

## ⚠ リレーション先の例外対応（おまけ）
セッションIDを使って関連エンティティを取得する際は、以下のように NotFoundException を投げると責任分離しやすくなります。
```java
private Session getSessionOrThrow(Long sessionId) {
    return sessionRepository.findById(sessionId)
        .orElseThrow(() -> new FeedbackNotFoundException("該当セッションが存在しません"));
}
```
---

## 🧪 使用技術・環境

- Java 17
- Spring Boot 3.2.x
- Spring Data JPA
- MySQL 8.x
- Lombok

---

## 📂 ソースコード・関連リンク

- 🔗 GitHub リポジトリ:  
  [LikeLion-Backend-Assignments/week03](https://github.com/hyeon-marina/LikeLion-Backend-Assignments/tree/main/week03)

- 📝 Zenn実装記録記事（成長ログ）:  
  [【LikeLion Backend】Week 3｜Spring Bootで1:NリレーションのCRUD APIを実装してみた](https://zenn.dev/hyeon_marina247/articles/351ddd1766aeb1)

---

## 🏷️ タグ
SpringBoot Java JPA FetchJoin N+1 Backend
【Spatial.ioメタバース】全キー入力ログ表示スクリプト

[Spatial.io](https://www.spatial.io/)で開発を行っていく際に、「このキー、ちゃんと認識されてる？」「特定のキーを押したときの処理を作りたいな」と感じることはありませんか？この記事では、どんなキーが押されたかをリアルタイムに確認できる便利なC#スクリプトとその使い方を解説します。

## 1. このスクリプトでできること
- キーボードのどのキーが押されたかをリアルタイムでログに出力します。
- ブラウザの開発者コンソールで確認可能です（前回の記事参照）。

## 2. 動作環境
- Windows 11
- Unity 2021.3.44f1
- **Spatial Creator Toolkit**
- Web ブラウザ（今回はChrome）

## 3. 実際のコード
以下が、押された全てのキー入力を検知して出力するC#スクリプトです。
```csharp
using UnityEngine;
using System; // Enum.GetValues を使うために必要

public class KeyInputLogger : MonoBehaviour
{
    // Inspectorから有効/無効を切り替えられるフラグ
    public bool enableKeyLogging = true;

    // 全てのKeyCodeを格納する配列
    private KeyCode[] _allKeyCodes;

    void Awake()
    {
        // KeyCode列挙型の全ての値を取得して配列に格納
        // この処理は一度だけ行えば良いためAwakeで行う
        _allKeyCodes = (KeyCode[])Enum.GetValues(typeof(KeyCode));
    }

    void Update()
    {
        // enableKeyLoggingがtrueの場合のみキー入力をログに出力
        LogAllKeyInputs();
    }

    // 全てのキー入力をチェックし、押されていたらログに出力するメソッド
    void LogAllKeyInputs()
    {
        // フラグがfalse、またはKeyCode配列が未初期化の場合は何もしない
        if (!enableKeyLogging || _allKeyCodes == null)
            return;

        // 格納されている全てのKeyCodeを順番にチェック
        foreach (KeyCode kcode in _allKeyCodes)
        {
            // Input.GetKeyDown() はキーが押された最初のフレームでtrueを返す
            if (Input.GetKeyDown(kcode))
            {
                // ログに見やすいようにプレフィックスとKeyCode名を出力
                Debug.Log($"[KeyInputLogger] キー入力検出: {kcode}");
            }
        }
    }
}
```
### 解説
- `Awake()`: スクリプトが有効になった最初のフレームでKeyCode列挙型の全ての値を_allKeyCodes配列にキャッシュします。これにより、Update()内で毎回取得する負荷を避けます。
- `Update()`: 毎フレーム`LogAllKeyInputs()`メソッドを呼び出します。
- `LogAllKeyInputs()`:
    - `enableKeyLogging` フラグで機能のON/OFFを切り替えられます。デバッグ時以外はfalseにしておくことを推奨します（後述の注意点参照）。
    - `_allKeyCodes` 配列内の全てのキーコードを反復処理し、`Input.GetKeyDown(kcode)` を使用して各キーが「押された瞬間」であるかをチェックします。
    - キーが押された場合、`Debug.Log()`でそのキーコード名をコンソールに出力します。ログのプレフィックス`[KeyInputLogger]`は、他のログと区別しやすくするためのものです。

## 4. Spatial.io環境でのログ確認
1. 上記のC#スクリプトをプロジェクト内に作成します（例: KeyInputLogger.cs）。
2. シーン内に空の`GameObject`を作成します。
3. 作成した`GameObject`に`KeyInputLogger.cs`スクリプトをアタッチします。
4. Inspectorウィンドウで、アタッチした`KeyInputLogger`コンポーネントの`Enable Key Logging`チェックボックスがオンになっていることを確認します。
    
    ![スクリーンショット 2025-05-19 112908.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4047011/00df4844-36e9-438a-aacf-d669b66d9b97.png)
    
5. ブラウザでF12キーを押して開発者ツールを開きます。
6. Consoleタブを選択します。
7. フィルタ入力欄に`[KeyInputLogger]`と入力すると、このスクリプトからのログのみに絞り込めます。
    
    ![スクリーンショット 2025-05-19 113249.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4047011/c3a5ac40-f2d3-45ed-86d7-b26a9b45129c.png)

これで、Spatial環境で実際にどのキー入力が認識されているかを確認できます。

## **まとめ**

今回は、押された全てのキーボード入力をログに出力する簡単なデバッグ用スクリプトを紹介しました。 

このスクリプトを使うことで、開発初期段階でのキー入力の確認や、特定のキーが意図した通りに認識されるかのテストが容易になります。

パフォーマンスに注意しつつ、開発の一助としてご活用ください！
WordPress納めでMySQLでしなければいけないこと

世の中では年賀状じまいが流行ってますが、WordPressじまいをされる方もいらっしゃるのではないでしょうか。

WordPressのサイトを閉じる時はSSL証明書の廃止、ドメインの廃止、WordPress関連のファイルの削除、MySQLデータベースの削除を行うと思うのですが、何か忘れているものがあると思いませんか？

それは、MySQLの権限情報です。データベースを作った後でGRANT～って権限を与えていたと思うのですが、あの権限情報も削除する必要があります。

それでは早速、例を見ていきましょう。

## 権限情報の確認
以下のコマンドで現在付与している権限の状態がみれます。
```
mysql> SHOW GRANTS FOR `admin`@`%`;
```
実行すると以下のように指定したユーザに付与している権限の一覧が表示されます。
```
+-------------------------------------------------------------+
| Grants for admin@%                                        |
+-------------------------------------------------------------+
| GRANT USAGE ON *.* TO `admin`@`%`                         |
| GRANT ALL PRIVILEGES ON `************jp`.* TO `admin`@`%` |
| GRANT ALL PRIVILEGES ON `***********com`.* TO `admin`@`%`  |
| GRANT ALL PRIVILEGES ON `***********site`.* TO `admin`@`%`  |
| GRANT ALL PRIVILEGES ON `************db`.* TO `admin`@`%`     |
+-------------------------------------------------------------+
5 rows in set (0.00 sec)
```
## 権限情報の削除
それでは、権限の削除を行ってみましょう。

下記コマンドで権限の削除ができます。
```
REVOKE ALL PRIVILEGES ON **********site.* from `admin`@`%`;
```
## 削除後の権限情報の確認
```
mysql> SHOW GRANTS FOR `admin`@`%`;
```
削除後に権限情報を確認すると、指定した権限が削除されていることがわかります。
```
+-------------------------------------------------------------+
| Grants for admin@%                                        |
+-------------------------------------------------------------+
| GRANT USAGE ON *.* TO `admin`@`%`                         |
| GRANT ALL PRIVILEGES ON `************jp`.* TO `admin`@`%` |
| GRANT ALL PRIVILEGES ON `***********com`.* TO `admin`@`%`  |
| GRANT ALL PRIVILEGES ON `************db`.* TO `admin`@`%`     |
+-------------------------------------------------------------+
5 rows in set (0.00 sec)
```
## まとめ
データベースだけ削除して終わりだと、権限情報だけ残っていく一方になりますので、気をつけましょう。

特に気をつけたいのが、使っているのか使っていないのかわからない権限が残っていたりすると、ややこしい事になります。

ですので、Drop Databaseをする前に、Show Grantsで権限情報を確認されることをお勧めします。

以上、お疲れ様でした！
バブルソートについて調べてみた

## はじめに
　大学の授業でバブルソートについて習ったので、自分自身の理解を深める目的で、最低限の情報だけ記事にまとめてみました。

## 操作
　バブルソートは、隣り合う要素を比較して、大小関係が逆になっていたら入れ替えるという操作を繰り返すことで、ソートを行います。一段階ごとに最後の要素から確定していきます。また、ここでは入れ替えが発生しなかった段階で終了するものとします。

データ数をnとすると、要素は0番目からn-1番目までとなります

一段階目
0番目と1番目を比較し、大小関係が逆になっていたら入れ替える
1番目と2番目を比較し、大小関係が逆になっていたら入れ替える

繰り返し

n-2番目とn-1番目を比較し、大小関係が逆になっていたら入れ替える

二段階目
0番目と1番目を比較し、大小関係が逆になっていたら入れ替える
1番目と2番目を比較し、大小関係が逆になっていたら入れ替える

繰り返し

n-3番目とn-2番目を比較し、大小関係が逆になっていたら入れ替える

.
.
.

n-1段階目
0番目と1番目を比較し、大小関係が逆になっていたら入れ替える

### 可視化
　今説明した処理の流れを可視化してみました

![bubble_sort_animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922095/35be5930-f1f4-4522-b84d-af2d839cb935.gif)

## 計算量
　1段階目の比較回数は、最初の0番目と1番目、1番目と2番目...n-2番目とn-1番目の順に比較していくので、n-1回になります。それ以降は１段階ごとに１回ずつ比較回数は減っていき、最後のn-1段階目で1回になるので、1～n-1までの和が、全体としての比較回数になります。

$$ 比較回数=(𝑛−1)+(𝑛−2)+⋯+1 = \frac{(𝑛−1)((𝑛−1)+1)}{2} = \frac{𝑛^2−n}{2} $$

ということで、データ数をnとしたときの計算量はO(n^2)です。

この手順だけ見るとソート済みでも比較回数は同じになりますが、交換が発生しなかったらソート終了という仕様にできるので、最良ケースの場合はO(n)となります。


## 安定ソート
　場所の入れ替えが発生するのは隣同士のみで、入れ替え条件に同値の場合は含まれないので、同じ大きさの値がソート前と後で入れ替わることはありません。したがって安定ソートだと言えます。
 
## 内部ソート
　バブルソートは隣り合う大小関係が逆になっている部分を入れ替えていくソート方法ですが、後述のコードを見ればわかる通り、入れ替えなどの操作が配列自身のメモリ領域内で完結できるので、内部ソートです。

## コード
pythonで書くと、こんな感じになります。
```python
def bubble_sort(arr):
    n = len(arr)
    swaped = True
    while swaped:
        swaped = False
        for i in range(n-1):
            if arr[i] > arr[i + 1]:  # 入れ替えが発生する場合
                arr[i], arr[i + 1] = arr[i + 1], arr[i]
                swaped = True
        n -= 1
```

## 総評

### 強み
- シンプルで実装が簡単
- 安定ソート

### 弱み
- 計算量がO(n^2)のため遅い
- 交換回数が多い

→　初心者向けのソートとして適正あり

## 最後に
　ここまで読んで下さりありがとうございました。先週調べた選択ソートと同様に、初心者の学習用にとどまる感じでしょうか。安定ソートかつ内部ソートなので、特定の場面で光ったりしそうですが、やはり遅いのがネックですね。
[writeup] picoCTF "The Numbers"

# 今回の問題
picoCTFより"The Numbers"を解いていきます。

# 実際に解いていく
### 1. 問題文をダウンロードする
![Numbers from picoCTF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3945501/3c5bce0e-b805-4ba8-8a93-1582328f30ec.png)
「The numbers... what do they mean?」という説明とともに、上図の画像がダウンロードできました。
それでは、この画像の暗号を解読していきましょう。

### 2. 暗号の特徴を書き出す
この暗号の特徴を以下に書き出します。
- 整数と { } が使用されている
- 使用されている数字は 1 ~ 21 まで

さらに推測すると、
- 暗号の形が OOOOOOO{OO~OO} に見える。FLAGの形式に似ている
- { } は変化しなさそう

以上より、最初の「16 9 3 15 3 20 6」は「p i c o c t f」になると予想しました。

数字からアルファベットに変換するところまではわかりました。
それでは、この変換規則はどのようなものなのでしょうか。

### 3. 各数字をアルファベットに変換する
「16」から「p」になるにはどのような規則が考えられるでしょうか？
それは、**アルファベット順**です。
- アルファベット順の16番目 → p
- アルファベット順の9番目 → i
- アルファベット順の3番目 → c

このようにして、各数字をアルファベット順に変換していきます。
すると、 PICOCTF{THENUMBERSMASON} が求められます。
これにてFLAG獲得です。お疲れ様でした。

# もう少し考えてみる
今回は各数字をアルファベット順に変換しました。
しかし、手動で一つずつ変換していくのは大変です。自動で行ってくれるサイトはないのでしょうか？

...ありますよ！
以下の便利なWebサイトを使えば一発で解けちゃいます！
[decode.cf](https://www.dcode.fr/letter-number-cipher)

# まとめ
今回の問題は、各数字をアルファベット順に対応させることで、数字からFLAGを獲得しました。

振り返ってみると、画像に出てきた数字が 1 ~ 21 までで、アルファベットの全個数に収まっていたことからも予想できたかもしれません。

# 補足
・なし
自作AIツール紹介

AIツールを作るのが好きな個人開発者。一人でコツコツとサービスを作っています。Qiita では開発メモや失敗談、モデル調整の試行錯誤を書いていく予定。

## 最近の作品
- [無料で使えるAI画像生成ツール](https://muryou-aigazou.com/ja)
- [ビックリマン風シールが作れるメーカー](https://muryou-aigazou.com/ja/bikkuriman-generator)