OmniAICreator/Qiita-1.07M huggingface dataset:
モジュール '@blocknote/core' にエクスポートされたメンバー 'locales' がありません。になる件

## はじめに

React学習の一環として作成中のメモアプリにて、NotionライクなUIにしたく`BlockNote`を使って見た所、以下のビルドエラーに遭遇しました。

```bash
モジュール '"@blocknote/core"' にエクスポートされたメンバー 'locales' がありません
```


## 目次

1. [Block Noteとは？](#-block-noteとは)
2. [事象](#-事象)
3. [原因](#-原因)
5. [まとめ](#-まとめ)
6. [参考文献](#-参考文献)

## 🧷 Block Noteとは？
[BlockNote](https://www.blocknotejs.org/) は React で Notion のようなブロックベースのテキストエディタを実装できるライブラリです。

デフォルトの状態でほぼ Notion といっても過言でないぐらい美しく、使いやすく、その上とても簡単に高クオリティなテキストエディタを実装できます。

カスタムブロックやAIツールなど、独自の機能でカスタマイズすることも可能です。

## 🧷 事象
テキストエディタのインスタンス：editor の設定にて、日本語化を行うために`locales`をインポートすると、以下ビルドエラーに...

### ビルドエラー
```bash
モジュール '"@blocknote/core"' にエクスポートされたメンバー 'locales' がありません
```

### 修正前のソースコード

```json: package.json
  "dependencies": {
    "@blocknote/core": "^0.29.1",
    "@blocknote/mantine": "^0.29.1",
    "@blocknote/react": "^0.29.1",
```
```tsx
// BlockNote 本体のエディタ型、部分ブロック型、日本語ローカライズ辞書（locales）をインポート
import { BlockNoteEditor, PartialBlock, locales } from '@blocknote/core';

// BlockNote の React 用フック（エディタ生成用）をインポート
import { useCreateBlockNote } from '@blocknote/react';

// Mantine 用 BlockNote スタイルを読み込み（UIに必要）
import '@blocknote/mantine/style.css';

// Mantine 版の BlockNote エディタビューをインポート
import { BlockNoteView } from '@blocknote/mantine';

// 親コンポーネントから props として受け取る型定義
interface EditorProps {
  onChange: (value: string) => void;       // ドキュメントが変更されたときに呼ばれるコールバック
  initialContent?: string | null;          // 初期表示するコンテンツ（JSON 文字列形式）
}

// Editor コンポーネント定義
function Editor({ onChange, initialContent }: EditorProps) {
  // BlockNote のエディタインスタンスを作成
  const editor: BlockNoteEditor = useCreateBlockNote({
    dictionary: locales.ja, // 日本語ローカライズを適用（ただし locales が存在しない可能性がある点に注意）
    initialContent: initialContent
      ? (JSON.parse(initialContent) as PartialBlock[]) // JSON 文字列をパースして初期ブロックとして使う
      : undefined, // コンテンツがなければ空の状態で開始
  });

  return (
    <div>
      {/* エディタ本体を表示。内容が変更されるたびに onChange を呼び出す */}
      <BlockNoteView
        editor={editor}
        onChange={() => onChange(JSON.stringify(editor.document, null, 2))} // ドキュメントを JSON 形式で親に渡す
      />
    </div>
  );
}

export default Editor;
```

## 🧷 原因
以下インポート方法に誤りがありました。

`locales`を別インポートすることで無事エラーが解消！
```tsx
import { BlockNoteEditor, PartialBlock, locales } from '@blocknote/core';
```

　👇👇👇

```tsx
import * as locales from '@blocknote/core/locales';
```

### 修正後のソースコード(import箇所のみ)
```tsx
import { BlockNoteEditor, PartialBlock } from '@blocknote/core';
import * as locales from '@blocknote/core/locales'; // locales だけ別でインポート
import { useCreateBlockNote } from '@blocknote/react';
import '@blocknote/mantine/style.css';
import { BlockNoteView } from '@blocknote/mantine';

  // 略
```

## 🎉 まとめ
BlockNote かなり手軽にNotion風のテキストエディタが実装できちゃいます。
UI/UX でお悩みの方、宜しければご活用ください😆

## 💫 参考文献
* [BlockNote](https://www.blocknotejs.org/)
* [BlockNoteでNotionライクなテキストエディタを実装する](https://techblog.leadingmark.jp/20240819)
KubernetesでNamespaceが消えない時にやったこと

## 問題
Namespace を消そうとしてもコマンドが終わらないってこと、たまにありますよね。
```bash
$ kubectl delete ns vault
namespace "vault" deleted


...
```

今回は、「ファイナライザを削除して Namespace を強制削除する卍」といった方法はとりたくない環境だったので、ちゃんと原因を特定してみました。

## 状況
消えない Namespace の状態を確認すると、Terminating で止まっていました。
```
$ kubectl get ns vault
NAME    STATUS        AGE
vault   Terminating   76d
```

## 解決方法
Kubernetes で Namespace 内に存在するすべての種類のリソースを取得する魔法のようなワンライナーがあるらしいので使ってみます。

https://cloud.google.com/kubernetes-engine/docs/troubleshooting/terminating-namespaces?hl=ja#remove_resource

```
$ kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get -n vault
No resources found in vault namespace.
...
No resources found in vault namespace.
NAME             STORE                    REFRESH INTERVAL   STATUS              READY
vault-eso-test   vault-backend-k8s-auth   15s                SecretSyncedError   False
No resources found in vault namespace.
...
No resources found in vault namespace.
```
どうやらこのリソースが残ってしまっているみたいでした。
```
NAME             STORE                    REFRESH INTERVAL   STATUS              READY
vault-eso-test   vault-backend-k8s-auth   15s                SecretSyncedError   False
```
消してみる。
```
$ kubectl delete ExternalSecret vault-eso-test
Error from server (InternalError): Internal error occurred: failed calling webhook "validate.externalsecret.external-secrets.io": failed to call webhook: Post "https://external-secrets-webhook.vault.svc:443/validate-external-secrets-io-v1beta1-externalsecret?timeout=5s": service "external-secrets-webhook" not found
```

うーん消せない...
どうやら、「Webhook がもう存在しないのに、それを参照してるリソースが残ってる」らしいので、Webhook一覧を見てみます。
```
$ kubectl get validatingwebhookconfigurations --all-namespaces
NAME                               WEBHOOKS   AGE
externalsecret-validate            1          76d
xxx                                1          448d
xxx                                9          451d
xxx                                1          451d
xxx                                1          451d
secretstore-validate               2          76d
```

怪しそうなWebhookが2つほどありました。
まずは、エラーメッセージに出ている「externalsecret-validate」を消してみます。
```
$ kubectl delete validatingwebhookconfiguration externalsecret-validate
validatingwebhookconfiguration.admissionregistration.k8s.io "externalsecret-validate" deleted
```
お、リソースが消せました！
```
$ kubectl delete ExternalSecret vault-eso-test
externalsecret.external-secrets.io "vault-eso-test" deleted
```
でも、Namespace は Termination のままでした...
なので「secretstore-validate」も消してみます。
```
$ kubectl delete validatingwebhookconfigurations secretstore-validate 
validatingwebhookconfiguration.admissionregistration.k8s.io "secretstore-validate" deleted
```
削除後、Namespace を削除する途中で固まっていたシェルを確認すると、コマンドが終わっており Namespace も消えていました！

## おわりに
今回は、カスタムリソース（Operator）をインストールしていた Namespace を削除しようしたら、うまくリソースを消せなかったことが原因で Namespace が Termination のまま止まっていました。そもそも、カスタムリソースをインストールすると CRD もインストールされると思いますが、CRD はクラスタスコープのリソースなので Namespace を消すだけでは消えないんですよね...
なので、カスタムリソースをどの Namespace にインストールしたかは、ちゃんとhelmfile等のコードに残して確認できるようにしておくことが大切と学びました。
PHPくんのことなんも分かってなかったから基礎から学んでみる

新卒からずっと業務で読み書きしてるPHP。親のように思っているが実際のところなんとなくで書けてしまうので基礎的な部分が分かってないと思いchatGPTに聞きつつファクトチェックしつつ勉強してみました。
（ちなみにo3に聞いたら2割くらいしか理解できなかったのでいつもお世話になっている4oに頼んで噛み砕きながら理解していきました）

# PHPはどうやって動いている？
ユーザー（ブラウザ）からリクエストが来たとき、PHP自体はそのリクエストを受け取ることはできない。
そのため、PHPの前段にapacheやnginxなどのwebサーバーを置き、リクエストはそこで受け取って、そこから裏側のPHPに通す。

:::note info
PHP単体でもビルトインサーバーがあるのでリクエストを受け取ることは可能だがシングルスレッドプロセス（後述）でしか動かないので開発環境用などにしか使えない。
https://www.php.net/manual/ja/features.commandline.webserver.php
:::

## PHP内部での動き
前段のwebサーバーからリクエストが送られてきたときPHPはどのように動くのかという部分。

PHPは基本**シングルスレッド、マルチプロセス**で動く。
単一のスレッド内で、リクエストごとにプロセスを増やして処理する。
受けられるリクエスト数を増やしたい場合は、サーバー本体のメモリ容量内でプールサイズを増やして対応する。

## PHP実行の種類
PHPの基本的な機能としては上記の通りだが、実際にPHPを実行する方法にはいくつか種類があり、プロセス管理の方法によって分類される。
webサーバーとプロセスを共有しないかつ起動済みのプロセスを使う（リクエストに応じてプロセスを開始しない）**php-fpm（FastCGI Process Manager）** が現在のデファクト。
以下の記事が分かりやすかったです。

https://qiita.com/yodai/items/c4c68b6d72f4596c5a87

## webサーバーの種類（apache、nginx）
前段に置くwebサーバーとしての選択肢は主にapacheかnginxに絞られる。
歴史的にはapacheが古くから使われており、nginxが後発。

比較すると、
- apache
  - マルチプロセッシングモジュール（MPM)で、利用用途に応じて変更可能。かつてのデフォルトはPHPと同じようにマルチプロセス方式。nginxと同じようにイベント駆動のモデルにもできるが、処理の仕組み上nginxよりは遅い。 
- nginx
  - イベント駆動・非同期I/O。リクエストごとにプロセスを増やさないため、C10K問題が起きない。

https://qiita.com/kamihork/items/296ee689a8d48c2bebcd

:::note info
C10K問題
> クライアントが約1万台に達すると、Webサーバーのハードウェア性能に余裕があるにもかかわらず、レスポンス性能が大きく下がる問題
:::

どちらを選択するかは要件によるが、多くの場合は処理が軽く大量アクセスを捌けるnginx（+ php-fpm）の構成にしておけば問題ないと思う。

# 実際にホストする際には
今回はコンテナ化した上で、AWSの各種サービスでホスティングする場合にどのような構成にすべきか考える。
LaravelみたいなフルスタックフレームワークでWEBアプリを新規開発することを想定して、できるだけマネージドなECS（Fargate）とApp Runnerの２つを考えてみる。それぞれのサービスの詳細は今回割愛。

### ECS（Fargate）
前述のnginx + php-fpmの構成にする場合、それぞれでイメージを用意してコンテナを分ける（docker公式としても1コンテナ=1責務というベストプラクティスを提唱している）。
そのため、1タスク内にnginx用のコンテナとphp-fpm用のコンテナを配置する構成になる。

### App Runner
dockerイメージを用意するだけで（ほぼ）そのままアプリケーションをホストできる。
App Runnerではマルチコンテナ構成にできないので、**php-apacheのようなモジュール版のapacheイメージ（または非公式のnginx+php-fpmが同居したイメージ）でシングルコンテナという構成**をとる。
App Runnerのスケーリングはリクエスト数に応じてインスタンスが増えるため、適切にスケーリングができていればapacheで起こりうるC10K問題も起きない（可能性が高い）。


# 感想
こうして整理するととても勉強になった。調べてみるとどんどん分からないことが出てくるので今後深堀ってみたい。
実務だとAWSのサービス選定の基準になるのでこういう知識はインフラがクラウドで抽象化されたとしても必要になるからやっぱ体系的に理解しておくべきだと思った。
関西弁で解説するSolana入門: 並列処理

# Solana の並列処理の仕組みと制約について関西弁で解説

おう、Solana の並列処理の仕組みについて、関西弁でざっくり説明したるわ！

:::note info
駆け出しエンジニアの頃、[ゆめたろう](https://qiita.com/Yametaro)さんの解説記事をよく参考にしていました。
本記事は Qiita の伝統にのっとり、Solana の基本概念について関西弁で解説するシリーズです。
:::

## Solana の並列処理の基本的な考え方

まずな、Solana がめっちゃ早いっちゅうのは知ってるやろ？これ、「並列処理」っちゅう仕組みがあるからなんや。普通のブロックチェーンやと、トランザクションを一つずつ順番に処理していくねん。でも Solana はちゃう！同時にようけのトランザクションを処理できんねん。

ほなトランザクションがぶつかったらどないすんねん？って？そこがミソやねん。

## アカウントモデルとトランザクションの仕組み

Solana では、全部のデータが「アカウント」っちゅうものに入っとんねん。このアカウントに対して、トランザクションで命令（インストラクション）を送るわけや。

で、ここがポイントやねんけど、**各命令は、どのアカウントを読み取り専用で使うねん、どのアカウントを書き込み用で使うねん**っちゅうのを前もって宣言せなあかんねん。

```
こんな感じやねん：
- 送信者のアカウント（書き込み可能、署名者）
- 受信者のアカウント（書き込み可能）
- システムプログラム（読み取り専用）
```

## 並列処理の仕組み

ほな、Solana のランタイムは何をしてんかっていうと：

1. **トランザクションを実行する前に、どのアカウントが書き込まれるかを先に見とんねん**
2. **同じアカウントに書き込むトランザクションは「ぶつかる」から、順番に処理せなあかん**
3. **ぶつからへんトランザクション（別々のアカウントを書き換えるだけのやつ）は並列で同時に実行できるねん！**

つまり、あんたのトランザクションとわいのトランザクションが全然別のアカウントをいじるだけなら、同時に処理できるっちゅうわけや！これめっちゃ速いねん！

## 制約について

ほな、こんな制約もあるから気いつけてな：

1. **書き込むアカウントは前もって宣言せなあかん**：
   「あ、ついでにこっちもいじりたいわ〜」みたいな後出しジャンケンはできんねん。前もって全部言わんとあかん。

2. **最大命令の深さ制限（4 段階まで）**：
   プログラム A がプログラム B を呼び出して〜っていうのも、深さが最大 4 段階までしかできんねん。これ以上深くなったら「もうあかんわ！」って怒られんで。

3. **トランザクションのサイズ制限（1,232 バイト）**：
   トランザクションのサイズにも制限あんねん。大きすぎるとエラーになるから、でっかいトランザクションは複数に分けて送る必要あるで。

4. **プログラムの署名制限**：
   プログラムが署名できるのは自分の PDA（プログラム派生アドレス）だけやねん。他人のアカウントには署名できへんのや。

## 実際にどない使うのん？

ほな、実際にどう使うかっちゅうと、例えば SOL を送金するときは：

```
// 送金するインストラクションを作るとき
{
  programId: SystemProgram.programId,  // どのプログラムを呼び出すねん
  keys: [
    {pubkey: あんたのウォレット, isSigner: true, isWritable: true},  // 送る人
    {pubkey: 相手のウォレット, isSigner: false, isWritable: true}   // 受け取る人
  ],
  data: ...  // 送金額とかのデータ
}
```

こんな風に、どのアカウントを読み書きするかを明確に宣言するから、ランタイムが「あ、このトランザクションとこのトランザクションはぶつからへんな！同時に実行したろ！」って判断できるわけや！

## 結論

要するに、Solana がめっちゃ速いのは、トランザクション同士がぶつからへんかどうかを前もって知ることができて、ぶつからへんトランザクションはどんどん並列で実行できるからなんや！これが Solana の「クソ早い」理由やねん！

でも気いつけなあかんのは、ちゃんとどのアカウントを書き換えるか前もって宣言せなあかんことや。後出しジャンケンできへんで〜！

あと、命令の深さやトランザクションのサイズにも制限あるから、複雑なことしようと思ったら、ちょっと工夫せなあかんねん。

ほな、これで Solana の並列処理の仕組みと制約については、ある程度わかったんちゃう？

:::note info
【ARM3rd とは】
ARM3rd はグローバル L1/L2 の開発支援、App Chain 企画、キラーアプリケーション創出に特化した、Web3・AI のプロフェッショナルファームです。Arweave や Solana はじめグローバルの Tier 1 プロトコル、および日本のエンタープライズとの卓越した協業実績を有しています。

- [Website](http://arm3rd.com/)
- [Founder Twitter](https://x.com/kyohei_nft/)
  :::
関西弁で解説するSolana入門: アカウントモデル

おっちゃ、Solana のアカウントモデルについて関西弁で解説したるで〜！めっちゃわかりやすくするからな！

:::note info
駆け出しエンジニアの頃、[ゆめたろう](https://qiita.com/Yametaro)さんの解説記事をよく参考にしていました。
本記事は Qiita の伝統にのっとり、Solana の基本概念について関西弁で解説するシリーズです。
:::

## Solana のアカウントモデルってなんやねん？

まずな、Solana ではすべてのデータは「アカウント」っちゅうもんに入れとんねん。これがめっちゃ大事や！

簡単に言うたら、キーとバリューのペアみたいなもんや。データベースの各エントリーを「アカウント」って呼んどるわけや。

## アカウントの重要ポイントはこんなもんや！

### 1. 容量とか中身とか

アカウントには最大 10MB ものデータが入るねん。デカいやろ？
そして中身は「実行できるプログラムコード」か「プログラムの値」のどっちかや。

### 2. レントってなんやねん？

アカウントを維持するには「レントデポジット」っちゅう SOL が必要やねん。これはデータの量に比例しとんねん。でもな、アカウントを閉じたら全額返ってくるから Suica のデポジットみたいなもんやと思ったらええで！

### 3. 所有権の話

全部のアカウントには「所有者」があって、それはプログラムやねん。アカウントのデータを変えたり、ラムポート残高を引き出したりできるんは、そのアカウントを所有してるプログラムだけやねん。でも誰でもバランスを増やすことはできるで！誰からでも SOL 送れるっちゅうことやな。

### 4. プログラムの特徴

プログラム（スマートコントラクト）は、実行できるコードを格納する「ステートレス」なアカウントなんや。つまり、コードと値が分かれてて、プログラムはコードだけで出来とるわけや。

### 5. データアカウントってなんや？

データアカウントは、プログラムの状態を保存したり管理するためにプログラムが作るもんや。

### 6. ネイティブプログラムってなに？

ネイティブプログラムは、Solana ランタイムに最初から組み込まれてるプログラムやねん。

### 7. Sysvar アカウントってなんやねん？

Sysvar アカウントは、ネットワーククラスタの状態を格納する特別なアカウントやねん。

## アカウントの構成ってどないなっとん？

### 1. アドレスの話

各アカウントは、Ed25519 っちゅう楕円曲線暗号の「PublicKey」の 32 バイトの一意のアドレスで識別できるねん。これがアカウントの一意の識別子や思ったらええで。

### 2. アカウント情報

Solana の全てのアカウントは最大 10MB のサイズで、その構造は「AccountInfo」って呼ばれとるねん。

### 3. AccountInfo の中身

- **データ（data）**: アカウントの状態を格納するバイト配列や。プログラムの場合は実行可能なコードが入っとる。
- **実行可能か否か（executable）**: これはブールフラグで、「プログラムである（true）」か「プログラムではない（false）」かを示すねん。
- **ラムポート（lamports）**: アカウントの残高をラムポートで表現しとる。1 SOL は 10 億ラムポートやで！
- **所有者（owner）**: アカウントを所有するプログラムの公開鍵（プログラム ID）やねん。

### 4. データの変更・引き出し権限

アカウントのデータを変えたり、ラムポート引き出したりできるんは所有者として指定されたプログラムだけや。でも、誰でもバランスを増やす（SOL 送る）ことはできるで！

### 5. チェーン上のデータ保存

チェーン上にデータを保存するには、データのサイズに比例した量の SOL をアカウントに送る必要があるねん。これを「レント（賃料）」って呼んどるけど、デポジットみたいなもんやから、アカウント閉じたら全額戻ってくるで！

## ネイティブプログラムについて

Solana には、バリデータの実装の一部である「ネイティブプログラム」ってのがあって、これがネットワークの核心機能を提供しとるねん。

よく使うネイティブプログラムは「システムプログラム」と「BPF ローダー」やねん：

### 1. システムプログラム

デフォルトでは、全ての新しいアカウントはシステムプログラムが所有しとる。システムプログラムは以下のことができるねん：

- 新しいアカウントを作る（これ、システムプログラムだけができるねん！）
- データのスペースを割り当てる
- プログラムの所有権を別のプログラムに再割り当てする

### 2. ウォレットについて

Solana のウォレットは単に「システムプログラムによって所有されるアカウント」やねん。ウォレットのラムポートバランスが、そのアカウントが持ってる SOL の量やねん。

### 3. BPF ローダープログラム

BPF ローダーは、ネイティブプログラム以外の全てのプログラムの「オーナー」として指定されたプログラムで、カスタムプログラムのデプロイ、アップグレード、実行を担当しとるねん。

ほんま、こないにシンプルに言うと、Solana のアカウントモデルは、アドレスをキーとして、データをバリューとして扱う大きなデータストアみたいなもんや！それぞれのアカウントに所有者があって、それがデータを変更できるねん。これがわかったら、Solana の基本が掴めたも同然やで！どや、わかりやすかったやろ？

:::note info
【ARM3rd とは】
ARM3rd はグローバル L1/L2 の開発支援、App Chain 企画、キラーアプリケーション創出に特化した、Web3・AI のプロフェッショナルファームです。Arweave や Solana はじめグローバルの Tier 1 プロトコル、および日本のエンタープライズとの卓越した協業実績を有しています。

- [Website](http://arm3rd.com/)
- [Founder Twitter](https://x.com/kyohei_nft/)
  :::
関西弁で解説するSolana入門: SPL Token

せやねん！今日は Solana の **SPL(Solana Program Library) Token** について関西弁で解説していくわ！難しそうに聞こえるかもしれへんけど、めっちゃわかりやすく説明するさかい安心してな！

:::note info
駆け出しエンジニアの頃、[ゆめたろう](https://qiita.com/Yametaro)さんの解説記事をよく参考にしていました。
本記事は Qiita の伝統にのっとり、Solana の基本概念について関西弁で解説するシリーズです。
:::

## SPL Token って何やねん？

SPL Token っちゅうんは、簡単に言うたら **Solana 上で動く独自のお金や資産** みたいなもんや！ETH 上の ERC-20 トークンみたいなもんやで。

例えばな、USDC（ドルと連動したステーブルコイン）とかは、Solana 上では SPL Token として存在しとるんや。

## SPL Token の基本構造

SPL Token の仕組みは 3 つの重要な部品からできてるねん：

1. **トークンプログラム** - これがトークンの命令（インストラクション）を全部管理してる本体や！「誰かにトークン送れ」とか「新しいトークン作れ」みたいな指示を処理するプログラムやねん。

2. **ミントアカウント** - これが「どんなトークンか」を表すアカウントや。例えば、「このトークンの総供給量は何枚や」とか「小数点以下何桁まで分割できるか」みたいな情報が入ってる。要するに**トークンの設計図**みたいなもんやな！

3. **トークンアカウント** - これが「誰がどれだけのトークンを持ってるか」を記録するアカウントや。ユーザーごとに、トークンの種類ごとに別々のトークンアカウントが必要やねん。

## 例えでわかりやすく言うたろか？

例えば、ミントアカウントは「円」という通貨そのものを表してて、トークンアカウントは「あんたの財布に 1000 円入ってる」という状態を表すねん。

トークンプログラムは銀行みたいなもんで、「A さんの財布から B さんの財布に 500 円送りや」みたいな操作を処理してくれるわけや！

## 関連トークンアカウントってなんやねん？

ちょっと複雑に聞こえるかもしれんけど、簡単なんよ。「関連トークンアカウント」は、あるウォレットアドレスと特定のトークンの組み合わせから**決まった方法で導き出されるアドレス**のことやねん。

これがあるから、例えば USDC を送りたいときに、いちいち「相手の USDC 用のアドレスどこ？」って聞く必要がないねん。相手のウォレットアドレスさえわかれば、自動的にその USDC 用のトークンアカウントがわかるわけや！めっちゃ便利やろ？

## トークンの作り方

SPL Token を作るのは意外と簡単やで！

1. まず**ミントアカウント**を作る（これがトークンの「種類」を表すねん）
2. そのトークンを保存するための**トークンアカウント**を作る
3. トークンプログラムに**「ミントして」**って命令を出して、トークンを生み出す

たったこれだけや！

## Solana のトークンプログラムは 2 種類あるねん

最近では、元祖の**トークンプログラム**と、新しい機能が追加された**トークン拡張プログラム（Token2022）**の 2 種類があるねん。

新しい Token2022 の方がええ機能たくさんあるから、新しくトークン作るなら、こっちを使った方がええで！例えば、トークンに名前やシンボル、画像 URL なんかの**メタデータをくっつけられる**ようになったんや！

## まとめ

SPL Token は、Solana 上で価値やセキュリティを持つデジタル資産を作るための仕組みやねん。ミントアカウントが「どんなトークンか」を定義して、トークンアカウントが「誰がどれだけ持ってるか」を記録する。そして、トークンプログラムがこれらを操作する命令を処理するってわけや！

めっちゃシンプルやろ？これでマッチョな Solana トークンの知識が身についたで！何か質問あったら、どんどん聞いてな！

:::note info
【ARM3rd とは】
ARM3rd はグローバル L1/L2 の開発支援、App Chain 企画、キラーアプリケーション創出に特化した、Web3・AI のプロフェッショナルファームです。Arweave や Solana はじめグローバルの Tier 1 プロトコル、および日本のエンタープライズとの卓越した協業実績を有しています。

- [Website](http://arm3rd.com/)
- [Founder Twitter](https://x.com/kyohei_nft/)
  :::
関西弁で解説するSolana入門: アカウントモデル・トランザクション・スマートコントラクト開発

Solana 開発の基本をビシッと関西弁で説明したろか！いこまっさ！


:::note info
駆け出しエンジニアの頃、[ゆめたろう](https://qiita.com/Yametaro)さんの解説記事をよく参考にしていました。
本記事は Qiita の伝統にのっとり、Solana の基本概念について関西弁で解説します。
:::

### アカウントモデル

ほな、まず最初にアカウントやねん。Solana では**全てのデータはアカウントに入ってる**んや。キーバリューストアみたいなもんやと思てくれたらええ。アカウントは最大 10MB までデータ入れられて、「プログラム（実行可能なコード）」か「プログラムの値」のどっちかになるねん。

アカウントを使うには「レント」ちゅう SOL のデポジットが必要やけど、アカウント閉じたら返ってくるから安心してな。借家の敷金みたいなもんや。

各アカウントには「所有者のプログラム」がおって、**そのプログラムだけがデータを変更できる**んや。誰でも SOL 送ることはできるけどな！

### トランザクションと命令

次に大事なのがトランザクションと命令（Instruction）や。Solana でネットワークと話すには**トランザクションを送信**するねん。トランザクションの中には**命令**が 1 つか複数入ってる。

トランザクションのポイントはこれや：

1. 複数の命令が入ってたら、**追加した順番で処理**される
2. **原子性**があるから、全部の命令が成功するか、全部失敗するかのどっちかや
3. トランザクションの**最大サイズは 1,232 バイト**やから、でかすぎんようにせなあかん

### トランザクション手数料

Solana で命令を処理するには**トランザクション手数料**を払わなあかんねん。これは：

1. バリデータさんへのお礼
2. スパム攻撃を減らすため
3. ネットワークの経済的安定のため

手数料は**署名ごとの基本料金**と**計算リソースの量**で決まるんや。優先料金も払えば処理優先度が上がるで！

### プログラム（スマートコントラクト）

Solana での「スマートコントラクト」は**プログラム**って呼ばれてるねん。プログラムは**実行可能なコードを持つオンチェーンアカウント**や。

プログラムは主に**Rust 言語**で書くんやけど、2 つの方法があるねん：

1. **Anchor**：初心者向けのフレームワーク。ボイラープレートコードを減らしてくれるから楽やで
2. **ネイティブ Rust**：より柔軟やけど、複雑になるわ

### PDA（Program Derived Address）

めっちゃ便利なのが PDA やねん。これは**決定論的**なアドレスで、「シード」と「プログラム ID」から導き出せるねん。特徴は：

1. **秘密鍵が存在せえへん**（Ed25519 曲線上にない）
2. プログラムが PDA に対して**プログラム的に「署名」できる**
3. PDA を導出しても自動的にアカウントが作られるわけやないから、ちゃんと作成せなあかん

### CPI（Cross-Program Invocation）

CPI は**あるプログラムから別のプログラム**を呼び出すことや。これで複数のプログラムを組み合わせられるねん。

CPI で大事なのは：

1. 呼び出し元の**署名権限**は呼び出し先に拡張される
2. 呼び出し深さは**最大 4 まで**
3. プログラムは自分の ID から導出された PDA に対して**署名できる**

### SPL トークン

Solana のトークンは**SPL（Solana Program Library）トークン**と呼ばれてて、こんな感じでできてるねん：

1. **トークンプログラム**：トークンを操作するための命令がある
2. **ミントアカウント**：トークンの種類を表す（総供給量や小数点の桁数など）
3. **トークンアカウント**：誰がどのトークンをいくら持ってるかを追跡
4. **関連トークンアカウント**：所有者とミントから決定的に導出されるトークンアカウント

### ネットワーククラスタ

Solana には 3 つの主要クラスタがあるねん：

1. **Devnet**：開発者がアプリをテストするため。タダでトークンがもらえるし、リセットされることもある
2. **Testnet**：新しい機能のテスト用。Devnet より新しいバージョンが動いてる
3. **Mainnet Beta**：本番環境。ほんまの SOL が流通してる

## Solana 開発に必要なもの

1. **Rust**の基本知識：プログラム書くなら必須や
2. **Anchor**フレームワーク：初心者には絶対おすすめ
3. **spl-token**：トークン操作するなら必須のライブラリ
4. **公開 RPC エンドポイント**か**プライベート RPC**：Solana ネットワークと通信するため
5. **Phantom**などの**ウォレット**：テスト・デプロイするとき必要や

ほな、開発頑張りや！わからんかったらいつでも聞いてな！

:::note info
【ARM3rd とは】
ARM3rd はグローバル L1/L2 の開発支援、App Chain 企画、キラーアプリケーション創出に特化した、Web3・AI のプロフェッショナルファームです。Arweave や Solana はじめグローバルの Tier 1 プロトコル、および日本のエンタープライズとの卓越した協業実績を有しています。

- [Website](http://arm3rd.com/)
- [Founder Twitter](https://x.com/kyohei_nft/)
  :::
JavaScript勉強ログ　関数の基本の書き方

## 関数の書き方
関数は「定義」してから「呼び出す」ことで処理が実行されます。何度も同じ処理を書かなくていい（再利用性）、コードが整理されるなどのメリットがあります。

```JavaScript
function functionName() {
  // 処理内容。定義しただけでは実行されない。
  // 関数を呼び出したときにこの処理が実行される。
}

functionName(); // 関数を呼び出して、処理を実行

functionName();
functionName(); // 何度でも呼び出して使える
```

## 引数（ひきすう）
引数とは、関数に渡す「入力値」のようなものです。

関数は、実行時に値（引数）を受け取って、それに応じた処理を行えます。同じ関数でも、引数を変えることで違う動作をさせることができます。引数は複数渡すことも可能です。

- 関数を定義するときの () 内の名前をパラメータ（受け取る側）
- 関数を呼び出すときに渡す実際の値を引数（渡す側）
- 呼び出し時の引数は、定義時のパラメータに渡される
```JavaScript
function functionName(parameter) {
  // 処理内容。parameter に引数が渡される。
}

functionName(argument); // 関数を呼び出し、argument を渡す
```

## 複数の引数
関数は、複数の引数を受け取ることができます。カンマ（,）で区切って定義・呼び出しをします。

```JavaScript
function greet(name, time) {
  console.log(`こんにちは、${name}さん。${time}ですね！`);
}

greet("太郎", "午後3時"); // → こんにちは、太郎さん。午後3時ですね！
```
Vibe Codingで始めるツールづくり

# はじめに

Vibe Codingは、Coding Agentの台頭により、コーディング作業が劇的に素早く、簡単になりました。
今回は、サクッとツールを作るときのコツについて紹介します。


## ツールづくりのコツ

要件が全てです。が日常でめんどくさいなと感じたときにツール作ったらいけないかな？をちょっと考えてみるのが良いと思います。
手元でサクッと動かすという点ではローカル環境で動かすことを前提に考えると楽かもしれません。
最近で作ったツールだと、

- sitemap.xmlのURL一覧からスクレイピングして各HTMLをマークダウンファイルに変換して保存するツール
- jpgやpng画像をwebpに変換するクライアントアプリ
- 会議室の利用状況を取得するChrome拡張機能

等です。


これらをどのようなプロンプトで作ったかを紹介します。

プロンプトにわたすことは基本的にこの4点です。

- やりたいこと
- 言語・フレームワークの指定(制約の設定)
- どの環境で動かしたいか
- どのようなアウトプットを期待しているか


これらをまとめます。
慣れないうちは、やりたいことだけを伝えていきなりソースコードを生成させないように指示します。


```
特定のsitemap.xmlのURL一覧からスクレイピングして各HTMLをマークダウンファイルに変換して保存するツールを作りたい。
まずは要件を設定するところからはじめたいです。
```

このようにプロンプトを書くと、事前に要件を整理出来ます。
納得がいったら、ソースコードを生成させます。

後は動かしてみて要件を満たす作りになっているかを確認し、出来ていなかったらエラーが出ている場合はエラーを見に行き、エラーが出ていない場合は、ソースコードを見に行きます。(生成されたタイミングである程度ソースをなめておくと良いです。)
以降はやりたいことを伝え、動いていることを常に担保しつつ新しい要件を追加していく


### アドバイス

Vibe Codingをする上で、効率良く成果を出すためのプラスアドバイスがあります。
3つあります。

1. 早めにテストコードを生成しておく
2. コードを生成するたびにコミットする
3. チャットが長くなってきたら、Summaryにまとめて次のチャットへ


これらはどれも精度を高める、維持するためのものです。
コード量が膨大、チャット量が膨大になるとハルシネーションや要件を満たさなくなったりすることが頻発するので工夫が必要です。
さっきまで動いていたのに動かなくなった、というのは結構起こるので意識してみてください。


### まとめ

要件の設定も大事ですが、精度を高めるための工夫も大事です！
どんどん身の回りの不便をツールを作って解決していきましょう〜
【Mac】コマンドでファイルをダウンロードする方法

`curl`を使用してファイルをダウンロードできます。
`-O`を使用して以下のようにします。

```terminal
curl -O [URL]
```

`[URL]`はダウンロードしたいファイルのURLです。
`-O`オプションは、URLの最後の部分をファイル名として使用して保存することを意味します。

例えば、以下のURLから画像ファイルをダウンロードしたいとします。

```text
https://example.com/image.jpg
```

この場合、ターミナルを開いて次のコマンドを入力します。

```terminal
curl -O https://example.com/image.jpg
```

このコマンドを実行すると、カレントディレクトリに`image.jpg`という名前でファイルが保存されます。

ダウンロードしたファイルに特定の名前を付けたい場合は、`-o`オプションを使用します。

```terminal
curl -o my_image.jpg https://example.com/image.jpg
```

このコマンドを実行すると、`my_image.jpg`という名前でファイルが保存されます。

## 参考

https://curl.se/docs/manpage.html
【転職記】3年のブランクを経て、エンジニアとして再出発を掴んだ話

## はじめに

2025年4月23日、ようやく内定をいただきました。  
そして本日、4月30日にオファー面談が無事に終わり、正式に入社が決定しました。

ただ、不思議と「ホッとした」という気持ちよりも、  
むしろ「早く活躍したい」「これからもっと価値を出していきたい」  
そんな前向きな気持ちでいっぱいです。

僕は、IT業界から3年間離れていました。
それでも、
「もう一度この業界で生きていきたい」
「数十年と活躍していけるエンジニアになろう」  
そんな想いから、2024年はコンピュータサイエンスの学習にフルコミットしました。
CSを学んでどう変わったのかについては、以下の記事で詳しくまとめています。

https://qiita.com/TechCraft/items/19651e5af959c57dc5ee


本記事では、そんな僕が転職活動を通して、何を感じ、何を考え、どのように内定にたどり着いたのかを、リアルに記録しました。
エンジニア転職を目指している方にとって、少しでも参考になれば嬉しいです。

---

## ブランク明けの転職活動

本格的に転職活動を始めたのは、2025年3月末ごろ。  
30社以上にエントリーし、いくつかの企業では最終面接まで進みました。

不安がなかったわけではありませんが、  
「自分の技術が通用するのか？」ではなく、  
「活躍したい」「貢献したい」という気持ちの方が大きかったです。

とはいえ、思うように進まない日々もあり、悔しさや焦りを感じる日も多くありました。
自信を失いかけたこともありました。
そんなとき、大きな支えになってくれた方々がいました。

---

## 支えてくれた人の存在

中でも特に支えになったのが、Recursionの転職サポート担当の方です。

僕のこれまでの経験や考えにじっくり耳を傾け、  
強みを言語化してくれたり、価値観に合った企業を一緒に探してくれたりしました。

エントリーや日程調整のやり取りもスムーズで、  
なにより話しやすく、常に寄り添ってくれるような安心感がありました。

このサポートがあったからこそ、最後まで走り続けることができたと心から思っています。

---

## 面接を通じて変化した視点

複数の企業の方とお話しする中で、  
「良いものを早く作ること」に惹かれていた自分の中に、新たな視点が芽生えました。

それは「課題を見つけ、どう解決するか」という視点です。 

ただ作るだけでなく、課題発見から解決までを意識する。
そんなエンジニアでありたいと、強く思うようになりました。

その後実際に、そのビジョンを評価してくださる企業も多くありました。

---

## 伝える工夫とその効果

同時に、複数の面接を重ねる中で、自分の強みであるCSの知識やこれまでの経験がうまく伝わっていないと感じる場面もありました。

CSの知識や経験は表面的に見えるものではないので、伝えるには工夫が必要だと感じました。
そこで、冒頭で紹介した「CS未経験だった僕が、1年かけて学んだこととその変化」というブログを書いたのです。
実際にその記事を見た企業の方が評価してくださり、選考が進みやすくなった感覚もあったので、それ以降はキータでの発信を続けることにしました。

また、限られた面接時間の中では、  
「これまで何を考え、どんな行動をしてきたか」まで十分に伝えきれていない感覚もありました。
自分の価値観や生き方は、これまでの行動の積み重ねにこそ表れると思います。
だからこそ、単なるスキル一覧や志望動機だけではなく、「自分がどんな人間で、何を大切にしてきたか」を丁寧に伝える必要があると考えるようになりました。
そこで、ポートフォリオサイトにこれまでの経歴や背景を詳しく記載するようにしました。

これらの伝える工夫をした結果、スカウトメールが増えたり、選考通過率が目に見えて向上したのです。  
少しずつでも、ちゃんと伝わるようになってきた。  
そう思えた瞬間でした。


---

## 一度は見送り。でも、それでも伝えたかった。

今回入社する企業の最終面接を終えた後、「見送り」の連絡を受け取りました。  
けれど、僕の中では「この会社で働きたい」という想いが明確にありました。

「まだ伝えきれていないことがある」  
「自分の強みが、正しく届いていないかもしれない」

そう感じた僕は、Recursionの担当の方にお願いして、  
自分の想いやこれまでの活動をまとめたより詳しい文書を企業に届けてもらいました。

---

## 想いは届いた

数日後、企業から「再度検討させていただきます」との連絡がありました。  
そして最終的に、結論が覆り、内定をいただくことができました。

企業の方は、Qiitaでの発信やCS学習の継続、GitHubでの様々なプロジェクトを、
その背景にある思考や想いとあわせて、改めて丁寧に見てくださいました。
その中で、「なぜ？」と本質を追求する姿勢など、自分の強みを見出し、評価してくださいました。

また、諦めなかった姿勢も、高く評価していただきました。

---

## スタート地点に立った今、思うこと

今回の内定はゴールではなく、新たなスタートです。

入社後は、これまで以上に積極性を発揮し、  
課題解決に向き合い、価値を生み出すエンジニアでありたいと思います。

---

## 最後に

この転職活動を通して、僕が一番実感したのは
「想いが持つ力」でした。

でも、想いだけでは届きません。  
日々の学習と行動の積み重ねがあったからこそ、  
その想いが裏付けを持ち、届いたのだと思います。

そしてなにより、支えてくれた方々の存在が本当に大きかったです。

- 技術的な相談やコードレビューに親身に対応してくださった、Recursion共同創立者のジェフリーさん  
- 転職の悩みに丁寧に寄り添ってくださった、同じく共同創立者のしんやさん  
- 常に伴走してくれた、Recursion転職サポートの担当の方  
- 真剣に向き合ってくださった企業の皆さま  
- そして、ブレずに学び続けた自分自身にも

関わってくれたすべての方に、心から感謝しています。

ここからが、僕の第二のエンジニア人生。
想いと責任を胸に、また一歩ずつ、自分の道を歩んでいきます。
Cursorをセットアップしてみた

## はじめに
自社でのCursor標準利用に備え、業務用Macにセットアップしてみた話。というかメモ
Vimmerになろうと思ってたんだけどな・・・

## インストール
1. [公式サイト](https://www.cursor.com/ja)の[ダウンロード MACOS]よりDMGをダウンロード
1. ダウンロードされた「Cursor-darwin-universal.dmg」を実行しインストール

## サインアップ
1. Cursorを起動し、[Sign up]をクリック
1. サインアップアカウントを指定する。私は業務用のGoogleアカウントで。
1. 指定したアカウントが表示されてるので、そのまま[Yes, LOG IN]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/8c307c14-c362-4f18-9825-c509ffd3edc3.png)
## 初期設定
1. サインアップが完了するとこの画面が表示されるので[Import from VS Code]
![images.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/cf815850-7227-46b4-9e4b-a479a5c84959.png)
1. そして[Import]
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/2d168a56-14da-4723-9d23-fa954dbf1f72.png)
1. あんまVSCode使ってないから特に引き継ぐのないけど...と思ってたら意外と待たされる。体感3分。
1. テーマ選択が表示されるので、とりあえず「Cursor Dark」で
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/0587c8ba-2c0f-4f58-a057-aae386460d7b.png)
1. 次のQuick Startはとりあえずデフォで
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/dd8a0188-a912-41ab-a578-da2d6d03143a.png)
1. Data Sharingでは念のため「Privacy Mode」を選択
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/ba920998-9273-440e-bcd0-945142f7ab3f.png)
1. Review Settingsでは、もちろん「Japanese」を選択。英語できるようになりたい・・・
![image7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/40375c71-f762-402a-8d62-33bb38e6a92c.png)
1. 以上でセットアップ完了！🙌
![image8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/9b321e1e-562c-40dd-acda-0a78f3561120.png)

## 動作確認
SwiftUIの公式プラクティスを読み込ませサマってもらった。おぉ、いい感じ。
![image9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3980043/723d4afd-994d-4921-9e68-cba6342c511a.png)

## おわりに
まだセットアップしただけなので、これからガシガシ使っていこうと思う。
特に既存のコードベースに対してどのくらい効果を発揮するのか楽しみ^ ^
JestでuseNavigateをモックしてテストする

## はじめに
`Jest`を活用したテストで、`React Router` の `useNavigate` をモックし、`MemoryRouter` を活用してテストする方法についてまとめます。

## 問題点
戻るボタン押下時のページ遷移のテストを実施したいと考えて、以下のテストを作成しました。


```tsx:UserCard.test.tsx
it('ホーム画面に遷移する', async () => {
    render(
      <BrowserRouter>
        <ChakraProvider>
          <UserCard />
        </ChakraProvider>
      </BrowserRouter>
    );

    // 戻るボタン押下時のテスト
    const backButton = await screen.findByTestId('back-button');
    await user.click(backButton);
    await expect(mockNavigate).toHaveBeenCalledWith('/');
});
```

しかし、このテストではエラーが発生しました。
```terminal
expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: "/"

    Number of calls: 0

      58 |     user.click(backButton);
      59 |
    > 60 |     await expect(mockNavigate).toHaveBeenCalledWith('/');
         |                                ^
      61 |   });
      62 | });
      63 |
```

## 原因と解決方法

元々は `BrowserRouter` を使用していましたが、テスト環境では `MemoryRouter` の方が適しているようです。
というのも、実際のブラウザ動作を必要としないユニットテストやコンポーネントテストでは、`MemoryRouter` を使うのが一般的らしい。

そのため、`MemoryRouter` の `initialEntries` を使って、意図したパスでコンポーネントをレンダリングすることで解決できました。

```tsx:UserCard.test.tsx
render(
  <MemoryRouter initialEntries={['/cards/testuser']}>
    <ChakraProvider>
      <UserCard />
    </ChakraProvider>
  </MemoryRouter>
);
```

:::note info
initialEntries のポイント
- 特定のパスでコンポーネントをレンダリングできる
- ルートパラメータ（例：testuser）を設定できる
- 実際のブラウザ URL を変更せず、ルーティングコンテキストを提供できる
:::

また `useNavigate` もモック化する必要があります。
```tsx
const mockNavigate = jest.fn();
jest.mock('react-router', () => ({
  ...jest.requireActual('react-router'),
  useNavigate: () => mockNavigate,
}));
```
:::note info
useNavigateをモック化するポイント
- react-router モジュールの useNavigate だけをモック化して、それ以外の関数等はそのまま使用可能
- useNavigate が呼び出されたことを監視できる
:::


## さいごに
ページ遷移のテストで、useNavigateとreact router をモック化する正しい方法を学ぶことができました。


## 参考サイト

https://qiita.com/KM_20005/items/2762ec6e2e487e384b8b

https://qiita.com/shiva_it/items/48e92101a31e4a2ba50d

https://qiita.com/taurosuke/items/9e656fd3aa2d1975d5d9
【PHP】基礎構文(変数、配列、ループ処理）

## 変数の定義
変数名の前に$をつけて定義する
```
$変数名 = "〇〇"
```

変数の注意点は
- 大文字と小文字で区別される（$titleと$Titleは別の変数として判断）
- 半角英数字、＿のみ使用
- $の直後に数字は不可

## 定数の定義
変数とは異なり、上書きすることはできない。
```
const 定数名 = 〇〇
```
定数名は大文字

## データ型
### スカラー型
- 文字列型(string)
- 整数型(intまたはinteger)
- 浮動小数点型(floatまたはdouble)
- 論理型(bool)
trueまたはfalseのみ
```
例
$d=true;
```

### 複合型
- 配列型(array)
```PHP
$e=array(1,2,3);
または
$e=[1,2,3]
```
- オブジェクト型(object)
クラスのインスタンスを表す
```PHP
class Person{
 public $name;
 }
 $f = new Person();
 $f ->name = "Taro";
```

### 特殊型
- NULL型
存在しないことを示す
```PHP
$g =null;
```
- リソース型(resource)
```PHP
$h = fopen("file.text, "r");
```

### データ型を調べたいとき
```PHP
var_dump();
```
## 配列

#### 基本構文
```
古い書き方
$content = array(データ1,データ2,データ3);
新しい書き方
$content = [データ1,データ2,データ3];
```
#### インデックス配列
```PHP
$fruits = ["apple", "banana","cherry"];
echo $fruits[0]; //appleと出力
```
明示的にキーを指定することもできる
```PHP
$number = [0 => "zero", 1=> "one"];
```

#### 連想配列（キーを文字列に）
```PHP
$person = [
"name"=>"Taro",
"age"=>25,
];

echo $person["name"]; //Taroと出力
```
#### 要素の追加と削除
- 末尾に追加
```PHP
$colors = [];
$colors[] ="red";
$colors[] = "green";
```
- キー指定で追加
```PHP
Scolors["bg"] = "blue";
```
- 削除
```PHP
unset($colors["bg"]);
```
## 繰り返し処理（Rubyと比較）

### forループ
- PHP
```PHP
for ($i = 0; $i < 5; $i++) {
    echo $i . "\n";
}
```
for(初期化;条件;更新）{}の構文

- Ruby
```Ruby
for i in 0...5
  puts i
end
```
範囲オブジェクト0...5を使用

### Whileループ
- PHP
```php
$i = 0;
while ($i < 5) {
    echo $i . "\n";
    $i++;
}
```
- Ruby
```Ruby
i = 0
while i < 5
  puts i
  i += 1
end
```

### foreachループ
- PHP
```php
$fruits = ["apple", "banana", "cherry"];
foreach ($fruits as $fruit) {
    echo $fruit . "\n";
}
```
- Ruby
```ruby
fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
  puts fruit
end

```
SSO（シングルサインオン）とは？

### SSO（Single Sign-On）とは？

**SSO（シングルサインオン）** は、1回のログインで複数のサービスにアクセスできる認証方式です。たとえば、GoogleアカウントでGmail、Google Drive、YouTubeにログインするように、**一度の認証で複数のサービスにアクセス可能** になります。

---

### 図でわかるSSOの仕組み（7ステップ解説）

以下の図は、SSOの基本的な認証フローをわかりやすく表しています。

```mermaid
sequenceDiagram
    participant ユーザー
    participant サービスプロバイダ1
    participant 認証プロバイダ
    participant データベース
    participant サービスプロバイダ2

    ユーザー->>サービスプロバイダ1: アクセス要求（1）
    サービスプロバイダ1-->>ユーザー: 認証が必要（2）
    ユーザー->>認証プロバイダ: リダイレクト（3）
    ユーザー->>認証プロバイダ: 認証情報を送信（4）
    認証プロバイダ->>データベース: 資格情報の検証（5）
    データベース-->>認証プロバイダ: 検証成功
    認証プロバイダ-->>サービスプロバイダ1: トークンを送信（6）
    サービスプロバイダ1-->>ユーザー: アクセス許可（7）
    
    ユーザー->>サービスプロバイダ2: アクセス要求（既に認証済み）
    サービスプロバイダ2-->>ユーザー: アクセス許可（8）
```


#### 登場する主な構成要素
- **ユーザー（User）**：サービスにアクセスしようとする人
- **サービスプロバイダ（Service Provider）**：利用したいサービス（例：アプリやWebサービス）
- **アイデンティティプロバイダ（Identity Provider）**：ユーザーの認証情報を管理するシステム（例：Google, Microsoftなど）

---

### 認証フロー（図の番号に対応）

1. **ユーザーがサービスにアクセスを要求**
   - 例：ユーザーが「Service Provider 1」にアクセス。

2. **サービスプロバイダが認証要求をアイデンティティプロバイダにリダイレクト**
   - セッションが存在しない場合、ログインが必要。

3. **ユーザーがアイデンティティプロバイダにリダイレクトされる**

4. **ユーザーが認証情報（ID・パスワードなど）を入力**

5. **アイデンティティプロバイダが認証情報を検証**
   - データベースなどでユーザー情報を確認。

6. **認証が成功するとトークンが発行され、サービスプロバイダへ送信**

7. **トークンを受け取ったサービスプロバイダがユーザーにアクセスを許可**

これで、ユーザーは再ログインなしに**他のサービスプロバイダ（例：Service Provider 2）にもアクセス可能**となります（すでに認証済みだから）。

---

### SSOのメリット

- **ユーザーにとっての利便性向上**  
  毎回ログインする手間がなくなり、業務効率が向上します。

- **セキュリティの向上**  
  パスワードの使い回しを防げるほか、集中管理によりセキュリティポリシーを一元化できます。

- **管理者側の負担軽減**  
  ID・パスワード管理の一元化で、パスワード忘れなどの対応が減少。

---

### 注意点・デメリット

- **アイデンティティプロバイダに障害が起こると全サービスに影響**
- **認証が突破されると、すべてのサービスに不正アクセスされる可能性**

これらを補うためには、**多要素認証（MFA）**の併用が推奨されます。

---

## まとめ

SSOは、現代のクラウドサービス利用において欠かせない認証方式のひとつです。便利で効率的ですが、**セキュリティ設計と組み合わせて使うことが重要**です。
ゼロから始めるAIシステム開発 #14 「Difyを触ってみた」

## Dify触ってみた
Dify触ってみたので所感を書いていきます。入門書はこちらを拝読。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/524b2e70-9f5e-42a5-a7a0-1ed20a7ba8ed.png)

https://amzn.to/4iEBzU0

## Difyとは
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/965976bb-bf17-4a27-94c6-20c82eaba659.png)

Dify（ディファイ）とは、**ノーコード／ローコードでAIアプリを簡単に構築・公開できるプラットフォーム。** ChatGPTなどのLLMを使ったAIアプリをGUIで簡単に作れる。OpenAI、Anthropic、Amazon Bedrock、Geminiなど複数のLLMに対応。（OpenAIのGPTsなどでも似たようなことができるが、GPTsならOpenAIのChatGPTしか使えないので各社のLLMを選べるメリットがある）チャットボットなどはかなり簡単に作れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/38819045-328f-458b-92ff-572af15afad5.png)
選べるLLM群。下にずらっと続く。

## 使い方イメージ
入門書の営業メール作成アプリはこんな感じ。**チャットボット形式だとかなりシンプル**でGUIでノードを設定するところさえ無い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/c48de308-a175-499a-9cff-ea9568c6abc4.png)
プロンプトと変数を設定し、使用するときは変数に値（自分の名前や相手企業の情報など）を入力するだけ。後述するが繰り返して使うことが想定されるため、プロンプトは可能な限り凝ったほうがDifyを使うバリューが高いだろう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/05e42bf2-dfec-4af2-b1ff-1691089c2260.png)


## GUIで複雑な機構も実現可能
チャットフロー形式のアプリでは、**コードなしでもプログラム的なことはかなり自由度高く実現可能。** ただしそれだけ複雑なことをやるのであればコードのほうが楽なところも結構ある。極端な例を出せば、繰り返しのチェックなどで変数をインクリメントするにはコードならi++とかi=i+1で済むのだが、Difyでは変数用のノードを作って…いろいろ設定して…前と後ろをつなげて…と結構面倒くさい。もちろんアプリ実装の手間などが無いので、相当複雑にならない限りはDifyに軍配が上がると思われるが。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/bad13fe8-810e-4006-81bc-9e22a35fd909.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/9119ea51-6823-44b9-8812-ef9b243d3f75.png)
入門書にある稟議書精査アプリのフローチャート。いくらでも複雑な分岐が可能に思えるが、そのたびにこのノードを一つ設定する必要があるのでまあまあ面倒。LLMにどんな話題か判定させてその結果を分けることも可能。

## 向いている用途
単発の作業であればその内容をLLMに入力したほうが断然早いので、**定期的に何度もやる作業**か、あるいは**企業が自社の社員に提供して効率化・正規化を図る**などの用途に向いているように思う。入門書には営業電話練習BOTなんてのもあったが確かに**練習**は繰り返しやるものだし、毎回レギュレーションをLLMに教えるのも大変なので向いている用途かもしれない。

## 料金
使った分だけ払う従量課金制。ただこれは、**LLMのAPIキーを要求されるのでLLM側に払う課金体制。** Dify自身には無料/有料プランがあるが、無料だと作れるアプリが5つなど結構制限が厳しい（入門書のアプリを全部残しておくことさえできない）。先述したように、基本的に他人に使わせたり事業規模が大きいところに需要がありそうなので、**Difyを使う意味がある人・企業なら課金前提になる**かもしれない。実際に一番安い課金プランでも59＄とまあまあお高め。

## まとめ
まだ入門書が2割ほど残っている（RAGなども実現可能）がとりあえずの感想としては、便利だがそこそこ限定的といった感じ。**AmazonBedrockよりは全然簡単な印象。** 作ったアプリは簡単にインポート・エクスポートができるので自分が使わなくても**Difyマネージャー**みたいなお仕事はあるかもしれない。

## おまけ（近況報告）
メイン内容以外の、ここ1ヵ月の勉強内容を報告するコーナー。
### ミナイは スクレイピングを おぼえた！
といっても簡単な、静的なサイトのみ。Javascriptで生成される動的なサイトはまだ無理。pixivとかどうなってんのアレ。
### ミナイは Pyautoguiを おぼえた！
勉強する前はPythonならどんなアプリでも操作できるイメージがあったけど、APIが使えない場合は力業で画面操作するしかないんですね…。つまづくときはだいたい画像認識がうまく行ってない。

APIが使えるならAPI、そうでないならスクレイピング、それでもダメならPyautoguiという感じで自動化を進めております。**数秒節約するために数時間・数日かけるの面白すぎる。** 昔は挫折したけど本質的にはプログラムが好きなのかもしれない。

### 為替予測プログラム近況
現状、3つのLSTMモデルを並行して予測を実践中。これによって**分散投資**と疑似的な**アンサンブル学習**を実現できている（はず）。ここ2週間の損益はこちら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3885923/34aa926a-b677-4f4a-b925-9f6641fba8ca.png)
約200回のトレードでなんとかプラスを実現。トランプショック環境下でもそれなりに頑健性を保てている気がするのでしばらくこれでやってみる予定。Pyautoguiによる自動化も進めており、進捗は8割くらい。
Ruby で PHP の unserialize 関数で unserialize できる文字列を生成する


## はじめに

Ruby Script で、 PHP の `unserialize` 関数を通して使用する文字列を生成したくなった。
Gem `php-serialize` を使うと簡単に扱えたのでそのメモ。

## php-serialize について

https://github.com/jqr/php-serialize

Gemfile 等に `gem 'php-serialize'` を追加した後、下記のように呼び出すことができる。

```rb:example.rb
require 'php-serialize'

PHP.serialize({'foo' => 'bar'})               #=> "a:1:{s:3:\"foo\";s:3:\"bar\";}"
PHP.unserialize('a:1:{s:3:"foo";s:3:"bar";}') #=> {"foo"=>"bar"}
```

## さいごに なぜ `php-serialize` が必要だったか

WordPress の記事等コンテンツのエクスポートファイルである WXR (WordPress eXtended RSS) ファイルの生成に Ruby Script を使用した。
WordPress は PHP で動作する都合上 多くの場所で `serialize`, `unserialize` を実行している。

`serialize` 対象のデータは、実行内容によって変化するような内容であったため、動的に `serialize` できるようにする必要があった。

## Ref

https://github.com/jqr/php-serialize
UnityのLayer設定と衝突判定（Physics 2D）

Unityでゲーム開発していると、物理演算や衝突判定を効率よく管理したくなりますよね。
特に、Physics 2Dを使ったゲームでは、Layer設定と衝突判定を上手く使いこなすことで、ゲームのパフォーマンスや挙動を大きく改善できます。

今回は、UnityのLayer設定とLayer Collision Matrixを使った衝突判定の管理方法について、実際の設定方法も交えて解説します！

## Layer設定とは？
Unityでは、ゲームオブジェクトにLayerを割り当てることで、物理演算や衝突判定、さらにはレンダリングまでグループ分けできます。
これを使うことで、例えばPlayerとEnemyの衝突判定を別々にしたり、UIは衝突しないように設定したりできます。

### 代表的なLayerの例
Player: プレイヤーキャラクター

Enemy: 敵キャラクター

Water: 水エリア

UI: ユーザーインターフェイス（衝突しないことが多い）

TransparentFX: 透過エフェクト

## Layer Collision Matrixとは？
Layer Collision Matrixは、異なるLayer同士が衝突するかどうかを設定するためのツールです。
設定画面では、各Layer同士の衝突を許可するかどうかをチェックボックスで管理します。

例えば、以下のように設定できます：

PlayerとEnemyは衝突するが、UIとは衝突しない

WaterはすべてのLayerと衝突しない

この設定によって、ゲーム内でどのオブジェクトが他のオブジェクトと衝突するかを簡単に管理できます。

## Layer Collision Matrixの設定画面
![Layer Collision Matrix設定画面](http://syunpp.com/wp-content/uploads/2025/04/Layer.png)
上の画像は、UnityのPhysics 2D設定画面にある「Layer Collision Matrix」を示しています。この画面では、異なるLayer同士が衝突するかどうかを設定することができます。

### 画像の説明
行と列: それぞれの行と列は、**異なるLayer（Player、Enemy、Waterなど）**を表しています。

チェックボックス: チェックボックスにより、どのLayer同士が衝突するかを設定できます。例えば、PlayerとEnemyが衝突する場合、対応するセルにチェックを入れます。

Disable All / Enable All: すべてのLayer間の衝突判定を一括で無効（Disable）や有効（Enable）にするボタンです。これにより、すべての衝突判定を簡単に調整できます。

### 設定の活用例
PlayerとEnemyは衝突するけれど、UIは衝突しない設定

WaterLayerは、すべてのオブジェクトと衝突しない設定

このように、各Layerが衝突するかどうかを簡単に設定できます。これにより、物理演算の計算負荷を削減し、ゲームのパフォーマンスを最適化できます。

## 実際の設定方法
1. Layerを設定する
まず、ゲームオブジェクトに適切なLayerを設定します。これにより、物理演算や衝突判定の対象が決まります。

2. Layer Collision Matrixで設定を管理する
次に、Physics 2Dの設定画面で「Layer Collision Matrix」にアクセスし、衝突するLayer同士を選択します。
例えば、下記のように設定できます：

PlayerとEnemyは衝突するが、UIとは衝突しない

WaterはすべてのLayerと衝突しない

## パフォーマンスの最適化
Layer Collision Matrixを上手く活用することで、物理演算の計算量を減らすことができます。
例えば、UIオブジェクトや背景オブジェクトは衝突判定が不要な場合が多いため、衝突しないLayerに設定することで、物理演算の計算負荷を軽減できます。

## まとめ
Layer設定を活用することで、ゲームオブジェクトを整理し、管理しやすくなる

Layer Collision Matrixを使用して、異なるLayer同士の衝突を効率的に制御

衝突判定を不要なLayerで管理することで、パフォーマンスの最適化が可能

このように、Layerと衝突判定をうまく管理することで、ゲーム開発の効率を大きくアップさせることができます！

## ブログでもUnityや個人開発ネタを発信中！
開発ノウハウやアプリ制作過程、Unity連携系のハマりポイントなど
より深掘りした内容をブログにまとめています！
▶ https://syunpp.com

## 公開中のアプリ一覧はこちら！
実際にUnityで開発してリリース済みのアプリ一覧をまとめています！
▶ https://syunpp.com/公開中のアプリ一覧/
ONLYOFFICEでTakao Gothicをデフォルトフォントに設定する方法

[ONLYOFFICE](https://www.onlyoffice.com/ja?utm_source=qiita&utm_medium=article&utm_campaign=takao)は日本国内で注目を集めています。高い互換性と多機能性を兼ね備えたこのオープンソースのオフィススイートは、ドキュメント編集やチームでの共同作業を円滑に進めるためのツールとして、多くのユーザーに支持されています。  

本記事では、ONLYOFFICEで日本語ユーザーに人気のフォント「Takao Gothic」をデフォルトフォントとして設定する手順を詳しくご紹介します。

![Image 2025年4月30日 22_47_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2655664/614a16c5-71ce-4fa4-8064-c4727e998560.png)


## ONLYOFFICEのデフォルトフォントについて

ONLYOFFICEでは、新たに作成するドキュメントのデフォルトフォントとして以下の設定がプリセットされています：

* DOCXおよびPDF形式：Arial（11 pt）
* XLSX形式：Calibri（11 pt）
* PPTX形式：Arial（各種プレースホルダーも含む）

しかし、一部のユーザーにとって、これらのフォントでは日本語の文書作成時に最適な表示が難しい場合があります。そのため、Takao Gothicのようなフォントをデフォルトに変更することで、より日本語に適した文書作成体験が実現します。

## ONLYOFFICEのデフォルトフォントを変更する方法

デフォルトフォントを変更するプロセスは以下の手順を参考に進めてください。このガイドではDocker版のONLYOFFICEを例にしています。

### ステップ1：コンテナへのアクセス

まず、ONLYOFFICEのファイルコンテナにアクセスする必要があります。以下のコマンドを実行してください：

```
sudo docker exec -it onlyoffice-files bash
```

### ステップ2：テンプレートフォルダに移動

次に、空のファイルテンプレートが保存されているフォルダに移動します：

```
cd /var/www/products/ASC.Files/server/DocStore/new
```

### ステップ3：ファイルを確認

現在のファイルテンプレート一覧を表示します：

```
ls
```

必要に応じて、言語設定（例：en-USフォルダの内容）に基づいて編集するフォルダを選択してください。

### ステップ4：コンテナ外へファイルコピー

編集対象のテンプレートファイルをホストマシンにコピーします：

```
sudo docker cp onlyoffice-files:/var/www/products/ASC.Files/server/DocStore/new/en-US /root/en-US
```

### ステップ5：フォント設定の変更

コピーされたファイルを[ONLYOFFICEデスクトップエディター](https://www.onlyoffice.com/ja/download-desktop.aspx#desktop?utm_source=qiita&utm_medium=article&utm_campaign=takao)で開きます。必要に応じてデフォルトのフォントを「Takao Gothic」に変更し、保存します。

### ステップ6：テンプレートをコンテナへコピー

編集したファイルをコンテナ内に戻します：

```
sudo docker cp /root/en-US/. onlyoffice-files:/var/www/products/ASC.Files/server/DocStore/new/en-US
```

これにより、新しいドキュメントはTakao Gothicフォントで作成されるようになります。

## DEB/RPM版およびWindows版の特別な手順

### DEB/RPM版

DEBまたはRPMパッケージを使用している場合、テンプレートファイルは以下のフォルダに保存されています：

```
/var/www/docspace/products/ASC.Files/server/DocStore/new/
```

編集方法やファイルの移動手順はDocker版と同様です。

### Windows版

Windows版を使用している場合、テンプレートファイルの保存先は以下のパスです：

```
C:\Program Files (x86)\Ascensio System SIA\DocSpace\products\ASC.Files\DocStore\new
```

Windowsエクスプローラーを使用して対象ファイルを編集、保存しなおしてください。

## カスタマイズのメリット

デフォルトフォントをTakao Gothicにカスタマイズすることで、日本語文書の美観と可読性が格段に向上します。また、このプロセスを完了することで、より効率的なワークフローを構築できます。ONLYOFFICEの柔軟なカスタマイズ性を活用し、最適な文書作成環境を手に入れてください。
いまさらjquery

### 概要
本当にいまさらながらwebpackでprojectを作ったのでその備忘録です(なんねんまえ?)
webpackというのはみなさんご存じのとおりhtml css jsをひとまとめにしてくれるやつです
似たようなのにgrunt, glupとかもあります
けど今なら正直viteかな

```sh
npm init -y
# bootstrap installation
npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
npm i --save bootstrap @popperjs/core
npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader
#jquery installation
npm i --save jquery
```

```
my-project/
├── src/
│   ├── js/
│   │   └── main.js
│   ├── scss/
│   │   └── styles.scss
│   └── index.html
├── package-lock.json
├── package.json
└── webpack.config.js
```

```webpack.config.js
'use strict'

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const autoprefixer = require('autoprefixer')

module.exports = {
  mode: 'development',
  entry: './src/js/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  devServer: {
    static: path.resolve(__dirname, 'dist'),
    port: 8000,
    hot: true
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    })
  ],
  module: {
    rules: [
      {
        test: /\.(scss)$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  autoprefixer
                ]
              }
            }
          },
          {
            loader: 'sass-loader'
          }
        ]
      }
    ]
  }
}
```

```package.json
{
  // ...
  "scripts": {
    "start": "webpack serve",
    "build": "webpack build --mode=production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  // ...
}
```


### コピペ元
[What is Webpack?](https://getbootstrap.com/docs/5.3/getting-started/webpack/)

[ProvidePlugin](https://webpack.js.org/plugins/provide-plugin/)
未経験からプログラマーに転職して半年が経ったので振り返る

# はじめに
早いもので、未経験からプログラマーに転職して半年が経ちました。
今は初めての案件で既存プログラムに改修を加えています。
詳細設計フェーズを終え、製造フェーズに突入中です。
この半年で感じたことなどを振り返っていきたいと思います。

# 経歴
私は高卒で経理事務をしていました。
Excelなどのオフィスは日々利用していましたが、プログラミングは全く触ったことがありませんでした。
ある日通信制大学での授業で、少しプログラミングを触れたことで「もっと勉強してこの世界に入りたい」と感じ、勉強して転職しました。

# 前職の経験が役に立ったこと
### 手順書作成
経理事務では、手順書を作成することが多くあります。
それはプログラマーにも共通していました。
環境構築の既存手順書がかなり修正しないといけない時などに、
役に立ちました。

### テキストメッセージの慣れ
前職では、自分宛のメッセージでなくとも情報をキャッチして対応しなければなりませんでした。
今の現場ではTeamsが3つメールは2つあり、いろいろなところから自分に関係ある情報を把握しておく必要があります。
これは前職の経験が生きたと思います。

# 意識したこと
### 人間関係の構築
基本的にオンラインコミュニケーションだったので、対面の時にできるだけ良い印象を持ってもらえるように努力しました。
挨拶を積極的に行ったり、お菓子を配ったり。
その人の人となりを知らなければ、同じ文章でも伝わり方が全然違うからです。

### 研修したことは必ずまとめておく
最初の一ヶ月間は学習期間でした。
その内容をNotionにまとめておくことで、その後案件に入った時、都度見返すことができて大変よかったです。

### 完成度より期日
未経験は承知の上で案件に入れてもらっているので、質よりも速度を大事にしました。あとで修正できる時間を確保するためにも、今後も続けるべきことだと思います。

### 根拠を持つこと
質より速度をとると言っても、レビューで指摘された時や理由を聞かれた時にしっかり自分の意思や意図を伝えられるように、行う作業には根拠を持つように意識しました。これは質問する時なども意識するべきだと思います。

# 苦戦したこと
### 既存のシステム理解
既存システムが膨大なので、全てを理解することは難しいです。
いきなり全てを理解しようとするのではなく、
全体の流れや、サービス内容から自分の関わる機能まで視点を変えながら少しずつ理解するようにしました。

### 既存のソースコードの理解
他人の書いたソースコードの理解は難しいです。
まずはドキュメントを読み込み、それ対応する箇所がどこなのかを見つけることが最初にするべきことでした。
その後、修正すべき点はどこかを見つけ出していきました。

# さいごに
走り書きで書いてしまったので、振り返って追記していきたいと思います。
これから目指している人、入社したばかりの人の参考になりましたら幸いです。
Shift_JISで保存されているmp3タグをUTF-8へ直す

# 概要

mp3音楽ファイルを整理していると、曲名やアーティスト名が文字化けしているファイルがあることに気づきました。どうも`Shift_JIS`でmp3タグが保存されていることが原因のようでした。複数のmp3ファイルが文字化けしているため、一気に文字コード変換をかけたいです。今回は音楽ファイルを保存しているのがUbuntuサーバ上だったこともあり、「easy tag」を使用して複数の音楽ファイルの文字コードを変換しました。mp3タグの文字コード変換に関する情報があまりなく、ここに個人的な手順をまとめておきます。

<!-- TODO 文字化けしているかどうかを判断する方法があれば追記する -->

## easy tagをインストール

```bash
sudo apt -y install easytag
easytag --version
# easytag 2.4.3
# Website: https://wiki.gnome.org/Apps/EasyTAG
```

### 「easy tag」にて編集

現状、複数のフォルダに複数のmp3ファイルがあり、mp3タグが`Shift_JIS`のものとUTF-8のものが混在しています。
そのため、easy tagの設定を、文字コード変換作業がしやすいような設定に変更します。

- Interface
  - 「Display changed files in list using:」を「赤色」の方が見やすそう
- Files
  - 「Preserve modification time when writing files」をオフ
  - 「Update parent directory modification time when writing files」をオフ
- ID3 Tags
  - 「Non-standard encoding for reading ID3 tags:」を「日本語（Shift-JIS）」へ
  - ID3v2でタグを書き込む：バージョンを「ID3v2.4」へ
  - 「古いバージョンID3v2タグを自動的に変換する」をオフ（本当にオフにしたほうが良いかは未確認）

修正のコツを示します。

- 設定ウィンドウ（メニューバー > Edit > Preference）の「ID3 Tags」を表示しっぱなしにする
- 必要に応じて「Non-standard encoding for reading ID3 tags:」のチェックボックスオン・オフを切り替え「日本語（Shift-JIS）」とUTF-8を切り替え、対象のファイルを探す
  - 切り替え後は「リストの更新」を行うこと（メニューバー > View >　フォルダの再読み込み（Ctrl + R））
- 「日本語（Shift-JIS）」の状態（文字化けせずに表示されている状態）の時に、Force Save Files（Ctrl + Shift + S）で保存する

<!-- TODO 画像で示す -->

## 修正したファイルについて

easy tagにてファイルを編集した後、どのファイルを編集したのか分からなくなる時があります。通常の場合、ファイルの更新日時が変更されているので、以下のようなコマンドで一覧できます。
例えば、2025年1月23日に修正したファイルを出力するコマンドです。

```bash
cd /path/to/music_dir
find . -type f -newermt "2025-01-23"
```

<!-- TODO 詳細を追記する -->


### mpvで音楽ファイルを確認する手順

Rhythmboxをインストールできなかったので、あきらめて代わりにmpvというツールを使います。

```bash
sudo apt -y install mpv

# pseudo-gui を指定することで、必ずGUIが表示されるようになる
mpv --player-operation-mode=pseudo-gui "/path/to/music/test.mp3"

# 画面表示させずに起動してしまい、終了したいとき
kill $(ps aux | grep mpv | awk '{print $2}' | head -n 1)
```

<!-- TODO mpv --version -->

参考情報です。

- [Could there be a UI when playing music? · Issue #1808 · mpv-player/mpv](https://github.com/mpv-player/mpv/issues/1808)

以上です。
権限セット作成方法

本橋孝昭です。

今回は権限セット　作成方法について解説を行います


## 事前注意事項

Plaugroundは少し癖があります。
作成方法や言語設定方法は以下に記載があります

https://quip.com/HA9rAfhZw0as/Pathfinder-Week0-Get-Ready-For-Pathfinder

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/7d3877f1-cce9-4ca6-8494-da6a8043521a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/8d87ed2a-a3d3-4b29-8ee0-a06625bbf93b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/814e7d08-6f51-4a6c-90f7-62c58cce882c.png)


　さて、権限セット作成について確認しましょう

## 右上の設定　をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4f5c70f2-c111-441a-beca-a3f95bbfe691.png)

## 　権限セット　と入力し「権限セット」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/bfd020a6-e6b0-4148-9198-a29dde74a1d2.png)

## 新規　ボタンをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/80d0fddd-a6b4-4e4c-a9b2-6cc48f1f4f9f.png)

## 表示ラベル　API名　説明　を記載し保存

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/51a93f9d-f9e5-498f-a714-01d66e9355fa.png)


以上で権限セットは作成です

では、次に権限セットの編集を行いましょう

例として取引先オブジェクトに「参照」権限を付与しましょう

## アプリケーションのオブジェクト設定をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/29496ef8-2663-41b4-9edb-44bb3b35262f.png)

## 取引先　をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/f57ac925-3045-4d41-8a11-0ae6da0d67ea.png)

## 編集　をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/9ecfe723-6052-42c4-bfa5-b92ecb6ec6d5.png)


## 有効　にチェックを入れて「保存」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/1ca7415b-57bb-44ad-9808-6c2f5aa729c8.png)


以上で権限付与は完了です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/b8f04229-4e88-44b2-9efb-381027d03cdb.png)


では最後に作成した権限セットをユーザーに割り当てましょう

## 権限セットの　「割り当ての管理」　をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/2c62dfe7-5a56-412f-aeec-6de8d0fe1b9e.png)

## 右の　「割り当てを追加」　をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/fc43f20b-d688-4a7d-9b61-65a8ed87377f.png)

## 割り当てるユーザーを選択して「次へ」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/8b9e6e78-6f25-4ac9-83ad-a4cc3d3c539d.png)





## 有効期限を設定し「割り当て」をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/eff2aadc-5d46-4a50-ac49-4f040a344a41.png)


## 完了　をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/2b4e3f1b-dfa8-4bd4-af35-178f30e4253a.png)


現在の割り当てにユーザーが登録されていれば成功です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/4d609698-b20f-49a8-a674-758eaa13cd0e.png)