OmniAICreator/Qiita-1.07M huggingface dataset:
default exportと名前付きエクスポート

# 目的

`default export`と名前付きエクスポートの違いがわからなかったのでまとめる。

# 結論

* デフォルトエクスポート: ファイル内で1つの主要な機能を提供する場合
* 名前付きエクスポート: ファイル内で複数の関連する機能を提供する場合

# そもそもモジュールのエクスポートってなんだ？

モジュールのエクスポートとは、あるファイル内で定義された関数、クラス、変数、またはコンポーネントを他のファイルから利用できるようにする`JavaScript`や`TypeScript`の仕組みのこと。

# デフォルトエクスポート

* `{}`なしで呼び出す
* 任意の名前で`import`できる(`Pagination`の部分は`MyPagination`でも可)
    * 名前を自由に変更できるがゆえ、チーム開発では一貫性を保つのが難しい場合も（同じモジュールを指しているのに名前が異なると、コードの可読性が低下する）


```tsx:importしてモジュールを使う側
import Pagination from '@/app/ui/invoices/pagination';
```

* 1ファイルからは1つのエクスポート（以下の例で言うと`Pagination`）だけが可能

```tsx:モジュールとして提供する側
// app/ui/invoices/pagination.tsx
export default function Pagination({ totalPages }: { totalPages: number }) {
  return <div>Pagination Component with {totalPages} pages</div>;
}
```

# 名前付きエクスポート

* `{}`つきで呼び出す

```tsx:importしてモジュールを使う側
import { CreateInvoice } from '@/app/ui/invoices/buttons';
```
* 名前付きエクスポートは、インポート時にエクスポート名を明示するため、どの機能がどのファイルから来ているのかが分かりやすい（コードの追跡やリファクタリング時には優位）
* 　1ファイルから複数のエクスポート（以下の例でいうと`CreateInvoice`と`DeleteInvoice`）が可能

```tsx:モジュールとして提供する側
// app/ui/invoices/buttons.tsx
export const CreateInvoice = () => {
  return <button>Create Invoice</button>;
};

export const DeleteInvoice = () => {
  return <button>Delete Invoice</button>;
};
```

## 名前付きエクスポートだとこんなメリットもある

* 名前付きエクスポートは、静的解析ツール（`ESLint`や`TypeScript`）で追跡しやすく、リファクタリング時に安全性が高い

```tsx
// 名前付きエクスポートのリファクタリング例
export const CreateInvoice = () => { ... };
export const DeleteInvoice = () => { ... };

// 名前を変更した場合、importしてモジュールを使う側も変更するよう検出してくれる
export const AddInvoice = () => { ... }; // CreateInvoice → AddInvoice に変更
```

# 思ったこと

「1ファイル1目的」のモジュールにした方が良い設計になりそうだが、
関連性が高い機能をまとめることで管理が楽になる場合もある。

「1ファイル1目的」の原則を守るべきか、関連性が高い機能をまとめるべきか、プロジェクトの規模やチームのコーディング規約に応じて、あらかじめ決めおくのがよさそう。
60秒で作る！クリックで爆発するPart【Roblox開発 #2】



## 🎓 この教材で学べること

* `ClickDetector` の使い方
* `Explosion` の生成と設定方法
* `Part` にイベントを仕込む基礎
* イベント発火型のインタラクション処理
* Roblox Studioでの簡易トラブルシュート

---


## 🧱 準備するもの

| 項目 | 内容                                 |
| -- | ---------------------------------- |
| 1  | Roblox Studio を起動する                |
| 2  | Scene に「Part」を1つ配置                 |
| 3  | そのPartに「ClickDetector」と「Script」を追加 |

---

## 🔧 スクリプト全体（Scriptの中身）

```lua
-- 親のPartを取得
local part = script.Parent

-- ClickDetectorのクリックイベントに接続
part.ClickDetector.MouseClick:Connect(function(player)
	
	-- 爆発を作成して位置を指定
	local explosion = Instance.new("Explosion")
	explosion.Position = part.Position
	explosion.BlastRadius = 10 -- 爆風の範囲
	explosion.BlastPressure = 500000 -- 爆風の強さ
	
	explosion.Parent = workspace -- ワールドに追加して有効化
	
	-- 爆発後、Partを消す（任意）
	part:Destroy()
end)
```

---

## 🧠 解説ポイント

| 行数   | 解説内容                                      |
| ---- | ----------------------------------------- |
| 2    | `script.Parent` でクリック対象のPartを指定           |
| 4    | `ClickDetector.MouseClick` でプレイヤーのクリックを検出 |
| 6〜10 | `Explosion` を作成し、位置や範囲、圧力を設定              |
| 12   | Workspaceに追加 → 爆発が発生！                     |
| 14   | おまけ：クリックされたPartを削除（派手に見せたいときに◎）           |

---

## 🔍 よくあるつまずきポイント

| 問題                 | 対処方法                                                |
| ------------------ | --------------------------------------------------- |
| Partが爆発しない         | `ClickDetector` が入っているか、確認                          |
| 何も起きない             | `Explosion.Parent = workspace` を忘れていないか確認           |
| 破壊されたくないオブジェクトも壊れる | `Explosion.DestroyJointRadiusPercent = 0` を設定して調整可能 |

---
MySQL 基本的な命令

```
# 登录 mysql
mysql -u root -p

# 创建新数据库
CREATE DATABASE sample;

# 展示所有库
SHOW DATABASES;

# 选择指定库
USE sample;

# 查看库下的表
SHOW TABLES;

# 删除数据库
DROP DATABASE sample;

# 创建新用户
CREATE USER myusr@localhost IDENTIFIED BY '12345';

# 给用户basic库下的所有权限
GRANT ALL ON basic.* TO myusr@localhost;

# 查看当前登录用户
SELECT USER();

# 创建表
CREATE TABLE `usr` (`uid` VARCHAR(7), `passwd` VARCHAR(15), `uname` VARCHAR(20), `family` INT);

# 删除表
DROP TABLE `usr`;

# 添加字段
ALTER TABLE `usr` ADD `updated` DATE AFTER `family`;

# 删除字段
ALTER TABLE `usr` DROP `updated`;

# 修改字段名称跟类型
ALTER TABLE `usr` CHANGE COLUMN `udated` `updated` DATE;

# 修改字段类型
ALTER TABLE usr MODFIY updated DATETIME;

# 查看表字段
SHOW FIELDS FROM `usr`;

# 插入数据
INSERT INTO `usr` (`uid`, `passwd`, `uname`, `family`) VALUES('yyamada', '12345', '山田祥寛', 3);

# 设置密码
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';






```
7.2.2 nilへの対応についての考察


レシーバがnilの場合の対応について以下のように記述がある。

```text
ポインタ型のレシーバは関数の引数にポインタを渡す場合と同じ用に動作します。メソッドに渡されるのはポインタのコピーなのです。関数にnilが渡された場合と同様、コピーのポインタを変更しても、オリジナルは変更されません。つまり、nilを受け取ってnilではないものに変更するようなポインタレシーバは書けません
```

以下のように書いてみる

```go
func (n *Node) InitIfNil() {
    if n == nil {
        n = &Node{}        // ★ ここでレシーバ変数だけが別の番地を持つ
    }
}
list := (*Node)(nil)
list.InitIfNil()
fmt.Println(list == nil)   // -> true  （呼び出し側は変わらない）
```

コード中に記載したようにメソッドの呼び出し時にポインタをコピーして実行しているので、メソッドの中でポインタを変更しても呼び出し側には影響がない。

どうしても変更したいような場合には以下のようにポインタのポインタを利用する
```go
func Init(pp **Node) {
    if *pp == nil {
        *pp = &Node{}
    }
}

var list *Node = nil
Init(&list) 
```

このように元のポインタ変数へのポインタ(`**Node`)を引数に取れば元のポインタ変数を直接触れるのでnil -> 非nilに変更出来る。

ただし、Go言語においてメソッドのレシーバ型に許されるのは T か *T のみとなるため、メソッドを使う場合この手法は有効でない。
60秒で作る！プレイヤーを追いかけるPart

### ✅ この教材で学べること

* `RunService.Heartbeat` の使い方
* プレイヤーキャラの検索方法
* `Vector3`で距離を求める方法
* `CFrame`の加算で動かす方法

---

### 🧱 準備するもの

| 項目 | 内容                                                     |
| -- | ------------------------------------------------------ |
| 1  | Roblox Studio を起動する                                    |
| 2  | Scene に「Part」をひとつ置く（名前変更不要）                            |
| 3  | その Part に「Script」を挿入する（右クリック → Insert Object → Script） |

---

### 🧠 スクリプト全体

```lua
-- 対象となるPartを取得
local part = script.Parent

-- Heartbeat: 毎フレームごとに処理を繰り返すイベント
game:GetService("RunService").Heartbeat:Connect(function()

	-- 一番近いプレイヤーを探すための変数
	local closestPlayer = nil
	local shortestDistance = math.huge -- 初期値は超デカい数（＝無限大）

	-- 全プレイヤーをチェック
	for _, player in pairs(game.Players:GetPlayers()) do
		local char = player.Character
		if char and char:FindFirstChild("HumanoidRootPart") then
			local dist = (char.HumanoidRootPart.Position - part.Position).Magnitude
			if dist < shortestDistance then
				shortestDistance = dist
				closestPlayer = char.HumanoidRootPart
			end
		end
	end

	-- 一番近かったプレイヤーに向かって移動する
	if closestPlayer then
		local direction = (closestPlayer.Position - part.Position).Unit
		part.CFrame = part.CFrame + direction * 0.5 -- 距離に応じて動かす（0.5はスピード）
	end
end)
```

---

### 🔍 解説ポイント

| 行数    | 説明                                            |
| ----- | --------------------------------------------- |
| 1     | `script.Parent` はこのスクリプトが入ってるPart自体のこと。       |
| 3     | `RunService.Heartbeat` は毎フレーム動作。ゲームの心臓みたいなもの。 |
| 6〜15  | プレイヤーを1人ずつ調べて、\*\*「いちばん近い人」\*\*を見つけるループ。      |
| 17〜20 | 近いプレイヤーに向かって移動。`Unit`は方向を1に揃える処理。             |

---

### 💡 アドバイス

* `direction * 0.5` を `* 0.2` や `* 1.0` に変えるとスピードが変わるよ。
* `TweenService` を使えば、もっと滑らかで柔らかい動きにもできる（上級編）。

---
Cursor CLIを使ってエイリアスを秒で登録する

# はじめに

エイリアスをもう少し楽に登録したいを実現できたので記事にまとめてみました。

![zs.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924509/0465a1b7-27a6-49e4-82c8-c2c8574a59cc.gif)

#### Before

:::note alert
エイリアス登録って便利だとは聞くけど、正直なところ：

- `cat ~/.zshrc` や `vi ~/.bashrc` って毎回打つのがめんどくさい  
- `vi` エディタ、操作しにくい  
- 登録するのに少し壁があるので、「まあいっか」で後回しにしがち


:::

こんな感じで自分にとって、設定ファイルを編集すること自体がちょっとしたハードルでしたが、

#### After 
:::note info
- **Cursor上で `.zshrc` を編集できるように**
- エイリアス登録に使うコマンドすら**エイリアス化**して快適に登録
- ターミナル操作が **直感的** & **ストレスフリー** 
:::

## 目次

- [Cursor CLIツールを使えるようにする](#1-cursor-cliツールを使えるようにする)
- [エイリアス登録に必要なコマンドをエイリアス登録する](#2-エイリアス登録に必要なコマンドをエイリアス登録する)
- [注意点](#3-注意点)
- [おわりに](#おわりに)
---

## 1. Cursor CLIツールを使えるようにする

まず、`cursor` コマンドをターミナルから使えるようにする必要があります。  
以下の記事で手順を確認できます。


https://qiita.com/tacarzen/items/03f118a3a0fd37134052



## 2. エイリアス登録に必要なコマンドをエイリアス登録する

`.zshrc` を開いて編集して、反映して...という作業を一発でできるようにするためのエイリアスを登録します。

```bash
# Cursorでファイルを開く
alias cur="open -a Cursor"

# Cursorで.zshrcを開く
alias z="cur ~/.zshrc"

# 設定の反映
alias s="source ~/.zshrc"
```

### 登録方法

ターミナルで `.zshrc` を開く（初回だけ）

```bash
open -a Cursor ~/.zshrc
```
上記で ``.zshrc`` を開いたら、以下の alias をコピペして保存します：

```bash
alias z="open -a Cursor ~/.zshrc"
alias s="source ~/.zshrc"
alias cur="open -a Cursor"
```

反映する
```bash
source ~/.zshrc
```

これで次回から、
```bash
z  # .zshrc を Cursor で開く
s  # 設定をすぐ反映
```
という高速エイリアス登録ができるようになります


## 3. 注意点

### バックアップを取る

編集しやすくなったのはいいですが、`.zshrc` には環境構築やツール連携に関わる大事な設定が入っているので、**編集ミスや上書きのリスクを減らすために、初期状態のコピーを取っておくのが良さそうです。**

```bash
# 例えば
cp ~/.zshrc ~/.zshrc.bak
```

### コマンド名の衝突に注意

すでに使っているエイリアスとかぶらないように、**他のエイリアスと被っていないか確認**しておきましょう。

```bash
alias  # 現在のエイリアス一覧を表示
```


## おわりに
「Be Lazy」を体現するための快適なツールになりそうです！


エイリアスが登録されるまでの流れはぜひ以下の記事をお読み下さい


https://qiita.com/Shoya-Miyata/items/097311457c6d2562ae2c
【kintoneノーコード開発】kintoneグラフ・集計表の機能を活用してみよう

# はじめに
こんにちは、現在kintoneノーコード開発で日々試行錯誤しているばんちゃん（[@Banchan_k12](https://x.com/Banchan_k12)）です。
前回に続き、kintoneの機能を活用してみようというテーマで、今回はグラフ・集計表の機能を活用してみませんか？というご紹介です。

### 対象
- アプリに蓄積しているでデータを可視化して現状把握、進捗確認したい方
- データを活用する際に、誰もがパッと見てわかるようにしたい方

# グラフ・集計表の機能を使うと
CSVでデータを書き出し、表計算ソフトなどでグラフや表を成形するためにかかっていた時間と手間が、kintoneアプリ内でグラフ・集計表を作成・保存することで、常に最新のデータと連動したグラフをすぐに確認することができるようになります


#### :point_up:kintoneで設定できるグラフの種類
![20250521-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/21c0a9ce-7e8f-4baa-8057-8ac37acc9844.jpeg)

:::note info
kintone ヘルプ
[グラフの種類と使い分け](https://jp.cybozu.help/k/ja/id/040581.html"「グラフの種類と使い分け")
:::

#### :point_up:できること
- フィルターや集計条件の指定が色々設定できる
    - 特定の条件に一致するデータをグラフ化できる
- 複数グラフの設定ができる
    - 1つのアプリ内で複数のグラフを作成して切り替え表示可能

![20250521-10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/95940f8b-81dd-44b7-bce9-bbf0053962c7.jpeg)

- お知らせに表示できる
    - 作成したグラフをポータルのお知らせに貼り付けることが可能
    - ポータルのお知らせ画面でユーザーに共有して見ることができる

![20250521-11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/8a2c705c-f3a1-481c-8e42-e2dfacf91671.jpeg)

- グラフから一覧画面へ遷移できる

![20250521-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/4b47b29d-e84e-4a31-ad9c-913c9a8c5ea7.jpeg)

:::note warn
クロス集計表はレコード一覧画面には遷移できません
:::

#### :point_up:グラフの作成
- アプリの設定画面から作成
![20250521-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/bfb87212-7665-4ee4-affe-9b5c3c9b7499.jpeg)


- アプリの一覧画面から作成
![20250521-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/2623041c-9402-4ffe-a0f8-686f0565e5b0.jpeg)
![20250521-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/ae01aa7f-1e94-4a85-b824-8ff588a8afcf.jpeg)

:::note info
詳しい項目設定はkintoneヘルプをご参照ください
kintone ヘルプ
[グラフを作成する](https://jp.cybozu.help/k/ja/id/040468.html"グラフを作成する")
:::

:::note warn
グラフの設定を「保存する」には、アプリの管理権限が必要です
「適用」はアプリの管理権限がないユーザーも設定でき、グラフ・集計した結果の表示urlを「ブックマーク」することができます
[ページのブックマーク](https://jp.cybozu.help/k/ja/id/040289.html"ページのブックマーク")

![20250521-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957411/c6abd2e6-ecef-4c1f-85c8-a0db0fe5e333.jpeg)

:::

#### :point_up:設定時のコツ
- グラフで使用するフィールドは入力ルールを統一する
    - 全角・半角、ひらがな・カタカナなど、入力データに表記ゆれがあると正しく集計できないため、ドロップダウンやラジオボタンなど選択肢フィールドを使用することで表記ゆれを防ぐ
- 集計対象は「数値フィールド、「計算」フィールド（数値の計算）で設定する
    - 金額、個数は「数値」フィールド、「計算」フィールド（数値の計算）を使用して集計される
- グラフタイトルやラベルはわかりやすく
    - グラフを共有する場合は誰が見ても「何のグラフか」を理解しやすいように設定する

# まとめ
レコードの一覧画面だけでは全体が見えてこないデータも、グラフ・集計表を設定して可視化することで、現状把握、認識しやすくなりますね。上手に活用することで、チーム内の「見える化」や次のアクションへの「意思決定」もスムーズに行えるようになるのではないでしょうか。
rootアカウントのセキュリティ

# rootアカウントの推奨される使用方法
1. rootを管理者個人のアカウントとして使用しない。（常用しない）
1. 運用時はrootで直接ログインせず、一般ユーザーでログインし作業をする。
1. root権限が必要な時は`su`で権限昇格し作業を行う。（`su`コマンドについても権限を厳しく行う）
1\. ３よりもセキュリティレベルを向上させる手段として、`su`を全面的に禁止し、`sudo root`を特定のユーザーのみ行えるようにする。

**今回はrootアカウントに対して様々な制限を行っていきます**

 ## ローカルログイン制限
 `/etc/pam.d/login`ファイルに対して`pam_securetty.so`を設定
 以下の行を追加する
```:/etc/pam.d/login
auth     required     pam_securetty.so
```
:::note info
`pam_securetty,so`は`/etc/securetty`を読み込み、ファイル内に書かれている端末（例：tty1）からのrootログインを許可する
:::

## SSHログイン制限
一般的にリモートログイン用に、OpenSSH(sshd)がインストールされており、デフォルトではrootログインが許可されていますが、サーバ運用時にはセキュリティ的に禁止にすべきです。
```:/etc/ssh/sshd_config
ParmitRootLogin=yes
↓
PermitRootLogin=no
```
設定変更後はsshdを再起動します
```:bash
$ sudo systemctl restart sshd
```
## `su`コマンドの制限
今回はLinuxデフォルトの`wheel`グループを使用して制限していきます。
**１　`wheel`グループ以外は`su`コマンド使用不可にする**
```:/etc/pam.d/su
#auth     ewquired     pam_wheel.so use_uid
↓　＃を外す
auth     ewquired     pam_wheel.so use_uid
```
**２　`su`コマンドを使用させるユーザを`wheel`グループに追加する**
```:bash
usermod -aG wheel user01
```
:::note info
`su`コマンドのログは以下で確認可能
```:bash
$ journalctl /usr/bin/su
又は、
$ grep "su" /var/log/secure
```
:::

## `sudo`コマンドの制限
`sudo`コマンドは`su`代替として使用できコマンドです。不適切な権限の不利かたをするととても危険な状態に陥ります
**【`su`と`sudo`の違い】**
|  | su | sudo |
|:-:|:-:|:-:|
| 設定の範囲 | ユーザ単位 | ユーザ単位、コマンド単位 |
| 入力するパスワード | rootのパスワード | ユーザのパスワード |

**0 設定ファイル**
`sudo`コマンドの全体の設定ファイルは`/etc/sudoers`です。
書き込む際の書式は
```:/etc/sudoers
ユーザー名　ホスト名=(実行設定ユーザ名)　コマンド
```
各項目の書式
| 項目 | 概要 | 書式 |
|:-:|:-:|:-:|
| ユーザ名 | コマンドの実行を許可するユーザ、グループの指定 | user01,%gp01,#uid,ALL |
| ホスト名 | 実行を許可するホスト | host.com,8.8.8.8,8.8.8.0/24,ALL |
| 実行設定ユーザ名 | コマンド実行時のユーザ設定を指定 | user01,%gp01,#uid,ALL |
| コマンド |  実行を許可するコマンドの指定 | /usr/bin/passwd |


**1 デフォルトの設定**
デフォルトの設定として、以下のように`wheel`グループはすべての権限が与えられている。
```:/etc/sudoers
%wheel    ALL=(ALL)   ALL
```
**2 個別設定**
ここでは例として`user01`に`sudo`コマンドは使えるが`sudo passwd root`は使えないように設定する。
```:bash
$ echo 'user01 ALL=(ALL) NOPASSWD:ALL,!/usr/bin/passwd root' >> /etc/sudoers/user01
$ chmod 440 /etc/sudoers.d/user01 
```
このコマンドで設定することができる。
`/etc/sudoers`に直接書き込むコマンドとして、`visudo`があるが筆者的におおもとの設定ファイルを触るのは怖かったので、`.d`の補助ファイルを使用した。
設定を消すときは、`/etc/sudoers.d/user01`を消すだけなのでとても楽。
Docker：user 起動した、コンテナをrootでログインする


以下のコマンドでDockerコンテナへ入り、操作を行うとします。
```
# docker exec -it <コンテナ名>
```


```
[user@e87140ca08ea batch]$ docker exec -it <コンテナ名> bash
user@e87140ca08ea:/src$
```

## 対応方法

`docker exec` コマンド実行時に、 `-u 0` をオプションに追加します。

```
# docker exec -it -u 0 <コンテナ名>
```

上記コマンドを実行すると、そのコンテナ内をrootユーザーとして操作が行えるようになります。

```
root@e87140ca08ea:/src#
```

## 理由

`-u root` ではNGとなります。`/etc/passwd`にてユーザ`root`のユーザIDが「0」で作成され、優先されるからです。
ios-speech

# Web音声アプリ開発で詰まったポイントと解決法まとめ（2025年5月版）

## はじめに

音声認識＋音声合成のWebアプリを作る中で、以下のような構成を実装しました：

- Next.js + Clerk + FastAPI + Azure Speech Service
- 音声録音：`MediaRecorder`
- 音声認識：Azure Speech to Text
- 音声合成：Azure Text to Speech（TTS）

その中で特にハマったポイントと、対処法をまとめておきます。

---

## 🧩 詰まったポイントと解決方法

### 1. iOSでTTS音声が自動再生されない

#### ❌ 問題点：
iOS Safariでは自動再生（`audio.play()`）がブロックされることが多く、TTS音声が再生されない。

#### ✅ 解決策：
- `autoPlay` フラグを `false` にして、`ユーザー操作時のみ再生` にする。
- iOSデバイスを `navigator.userAgent` で検知し、再生方法を分岐。

```tsx
useEffect(() => {
  const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
  if (autoPlay && !isIOS) {
    audioRef.current?.play().catch(err => console.warn("iOS autoplay blocked:", err));
  }
}, [audioUrl]);
```

---

### 2. MediaRecorder の MIME type 問題

#### ❌ 問題点：
ブラウザにより `MediaRecorder` でサポートされる MIME type が異なる。

#### ✅ 解決策：
録音前に `isTypeSupported()` を使って、利用可能な MIME type を判定。

```ts
let mimeType = '';
if (MediaRecorder.isTypeSupported('audio/webm')) {
  mimeType = 'audio/webm';
} else if (MediaRecorder.isTypeSupported('audio/ogg')) {
  mimeType = 'audio/ogg';
}
```

---

### 3. ffmpeg で webm から wav 変換エラー

#### ❌ 問題点：
Azure Speech で WAV形式が必要 → `ffmpeg` を使って変換。
だが、環境によっては webm がうまくデコードできず `Invalid data found` エラー。

#### ✅ 解決策：
- `ffmpeg -i` に `-f wav -ar 16000 -ac 1` の明示指定を追加。
- それでも失敗する場合は `application/octet-stream` としても別ルートで処理。
- 変換失敗時の fallback ロジックを用意する。

---

## 🔊 最終構成のアーキテクチャ（簡略図）

```
ユーザー音声
   ↓録音(MediaRecorder)
FastAPI
   ↓送信(blob形式)
ffmpeg（WAV変換）
   ↓
Azure Speech to Text
   ↓
OpenAI API（対話生成）
   ↓
Azure TTS
   ↓
クライアント再生（audio.play）
```

---

## おわりに

iOSやブラウザ間の違い、MediaRecorderや音声再生のクセ、そしてffmpegやTTSの仕様にかなり悩まされました。

同じように音声アプリを作る方の参考になれば幸いです。

---
Spring Securityがhttpリクエストヘッダーやレスポンスヘッダーにキー設定あるのか

HTTPリクエスト/レスポンスヘッダーにどのように関与するかについては、公式ドキュメントにしっかり記載されています。ただし、「キーを設定する」という表現ではなく、セキュリティヘッダーを追加・制御するという形で記述されています。

## Spring Securityがレスポンスヘッダーに追加する内容（公式）

https://docs.spring.io/spring-security/reference/servlet/exploits/headers.html

| ヘッダー名                       | 内容                                             | デフォルト      |
| --------------------------- | ---------------------------------------------- | ---------- |
| `Cache-Control`             | no-cache, no-store, max-age=0, must-revalidate | 有効         |
| `Pragma`                    | no-cache                                       | 有効         |
| `Expires`                   | 0                                              | 有効         |
| `X-Content-Type-Options`    | nosniff                                        | 有効         |
| `X-Frame-Options`           | DENY                                           | 有効         |
| `Strict-Transport-Security` | max-age=31536000 ; includeSubDomains           | HTTPS時に有効  |
| `Content-Security-Policy`   | 任意（設定時）                                        | 無効（手動設定必要） |


##  Spring Securityがリクエストヘッダーを検査する内容（公式）

####  Authorization ヘッダーについて:
Spring Securityは、Authorization ヘッダー（Bearer TokenやBasic認証）を解析して、認証情報を取得します。

https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html

#### CSRF トークンのヘッダー送信:

フロントエンドは X-CSRF-TOKEN や X-XSRF-TOKEN ヘッダーにトークンを入れてリクエストします。

https://docs.spring.io/spring-security/reference/servlet/exploits/csrf.html

#### 補足：公式ドキュメントの探し方

https://docs.spring.io/spring-security/reference/index.html

「Exploits」セクションにヘッダーの記述あり

「HTTP Security」セクションに詳細なDSLの使い方あり
XIAO ESP32C6+SSD1306、円弧を書いて遊ぶ。(キラキラをかえせ(何の事?


いろいろ注意
----

- 過去ログを見よ!!!
- 3.2.0
- いろいろ　7話、おもしろかった(何の今期アニメ(キーワードは、キラキラ
- いろいろ　数学パズルの愛好家の方がマイコン系より、多い事がわかった。(実装系に人気がない
- 平方根を使うより塗り潰しのアルゴリズムの方が速いか?


結果
----

![image_original(38).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/0e945e3f-0b1a-40fb-b18b-5993498bde72.jpeg)


プログラム
----


```c++


//OLED_SSD1331_enko2_XIAO_ESP32C6


//ヘッダーファイル
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128     // OLED display width, in pixels
#define SCREEN_HEIGHT 64     // OLED display height, in pixels
#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


int i_sqrt(int n){
    //30
    if( n > (32*32-1) ) return 32;
    if( n > (31*31-1) ) return 31;
    if( n > (30*30-1) ) return 30;
    //20
    if( n > (29*29-1) ) return 29;
    if( n > (28*28-1) ) return 28;
    if( n > (27*27-1) ) return 27;
    if( n > (26*26-1) ) return 26;
    if( n > (25*25-1) ) return 25;
    if( n > (24*24-1) ) return 24;
    if( n > (23*23-1) ) return 23;
    if( n > (22*22-1) ) return 22;
    if( n > (21*21-1) ) return 21;
    if( n > (20*20-1) ) return 20;
    //10
    if( n > (19*19-1) ) return 19;
    if( n > (18*18-1) ) return 18;
    if( n > (17*17-1) ) return 17;
    if( n > (16*16-1) ) return 16;
    if( n > (15*15-1) ) return 15;
    if( n > (14*14-1) ) return 14;
    if( n > (13*13-1) ) return 13;
    if( n > (12*12-1) ) return 12;
    if( n > (11*11-1) ) return 11;
    if( n > (10*10-1) ) return 10;
    //1
    if( n > (9*9-1) ) return 9;
    if( n > (8*8-1) ) return 8;
    if( n > (7*7-1) ) return 7;
    if( n > (6*6-1) ) return 6;
    if( n > (5*5-1) ) return 5;
    if( n > (4*4-1) ) return 4;
    if( n > (3*3-1) ) return 3;
    if( n > (2*2-1) ) return 2;
    if( n > (1*1-1) ) return 1;
    return 0;
}


//初期化
void setup() {

  //I2Cの初期化
  Wire.begin(D9, D10);  //XIAO ESP32C6+SSD1306
  //Wire.begin(D10,D9); //XIAO ESP32C6+GROVE

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

}  //setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.fillScreen(BLACK);

  for (int y = 0; y < 30; y++) {

    //(r*r) = (y*y) + (x*x)
    //(30*30) = (y*y) + (x*x)
    //(30*30) - (y*y) = (x*x)
    //x = SQRT(x*x)

    int x, xx;

    xx = (30 * 30) - (y * y);
    x = i_sqrt(xx);

    display.drawPixel(x, y, WHITE);

    delay(50);
    display.display();
  }

  // 描画バッファの内容を画面に表示
  display.display();


  delay(5000);  //5秒待つ

}  //loop



```
ChatGPTを使用したアプリ開発記【背景色の改修】

## ✅ 全体構文
```App.js
<div className="min-h-screen bg-gradient-to-br from-blue-200 via-blue-100 to-white p-8 font-sans">
```

### 🔹 min-h-screen
•	意味：最小高さを「画面の高さ（100vh）」にします。
•	目的：ページ全体を埋めるように背景が表示されるようにする。
•	効果：投稿が少なくても背景が途切れず、常に縦に全画面に背景が広がります。

### 🔹 bg-gradient-to-br
•	意味：背景を「右下方向（bottom right）」に向けたグラデーションにします。
•	略語：
bg：背景
gradient-to-br：グラデーションの方向（Top → Bottom Right）


### 🔹 from-blue-200
•	意味：グラデーションの始点の色が blue-200。
•	blue-200 は淡い水色系の色で、背景を柔らかく見せる効果があります。


### 🔹 via-blue-100
•	意味：グラデーションの途中の色が blue-100。
•	役割：中間色を挟むことで滑らかな色の移り変わりを実現。


### 🔹 to-white
•	意味：グラデーションの終点の色が white（白）。
•	結果：淡い水色から白へ自然にフェードしていく背景になります。


### 🔹 p-8
•	意味：パディング（内側の余白）を全方向 8（= Tailwind基準で 2rem）与えます。
•	効果：画面の左右上下に適度な空間を保って、レイアウトが詰まらず見やすくなります。


### 🔹 font-sans
•	意味：サンセリフ体（ゴシック体）をフォントとして指定。
•	理由：Webアプリでは視認性が高いため、Sans-serif がよく使われます。

## ✅ UI

![スクリーンショット 2025-05-16 16.39.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1058366/7f40cf38-58c3-4b90-a4a7-f57a47074018.png)
windows11で、sketchup6 その114

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
タートルグラフィックスを見つけたのでやってみた。

# 参考にしたページ

https://qiita.com/fujim2/items/a4a3e3b8c1824c09fd02


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/44dddd42-0200-4f11-a6e3-e879c62c2530.png)

# サンプルコード

```
class Kame6
	def initialize
		@ANGLE = 0;
		@LX = 10;
		@LY = 10;
		@pen = 0
		model = Sketchup.active_model
		@entities = model.active_entities
		pd()
		tree(10.0, 30, 0.7, 12)
	end
	def fmod(a, b)
		x = (a / b).floor
		return a - b * x
	end
	def turn(a)
		@ANGLE = fmod(@ANGLE + a, 360.0)
	end
	def gmove(l)
		p = []
		rd = Math::PI / 180.0
		x = l * Math::cos(rd * @ANGLE)
		y = -l * Math::sin(rd * @ANGLE)
		px = @LX
		py = @LY
		p << [px, py, 0]
		@LX += x
		@LY += y
		p << [@LX, @LY, 0]
		if @pen == 1
			@entities.add_curve(p)
		end
	end
	def pd()
		@pen = 1
	end
	def pu()
		@pen = 0
	end
	def rt(th)
		turn(-th)
	end
	def lt(th)
		turn(th)
	end
	def fd(len)
		gmove(len)
	end
	def bk(len)
		gmove(-len)
	end
	def tree(len, th, r, n)
		if (n > 0) 
			fd(len)
			lt(th)
			tree(len * r, th, r, n - 1)
			rt(2.0 * th)
			tree(len * r, th, r, n - 1)
			lt(th)
			bk(len)
		end
	end
end





```

以上。
windows11で、sketchup6 その113

# 概要
windows11に、sketchup6を入れてみた。
rubyで、3Dを書く。
タートルグラフィックスを見つけたのでやってみた。

# 参考にしたページ

https://qiita.com/Geochelone/items/4c618105885abd5b27ef

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/23019a04-2c19-4294-b9e0-33c51d8c6887.png)

# サンプルコード

```
class Kame5
	def initialize
		model = Sketchup.active_model
		@entities = model.active_entities
		@ANGLE = 0
		@LX = 10
		@LY = 10
		@pen = 0
		run()
	end
	def fmod(a, b)
		x = (a / b).floor
		return a - b * x
	end
	def penup()
		@pen = 0
	end
	def down()
		@pen = 1
	end
	def turn(a)
		@ANGLE = fmod(@ANGLE + a, 360.0)
	end
	def move(l)
		p = []
		rd = Math::PI / 180.0
		x = l * Math::cos(rd * @ANGLE)
		y = -l * Math::sin(rd * @ANGLE)
		px = @LX
		py = @LY
		p << [px, py, 0]
		@LX += x
		@LY += y
		p << [@LX, @LY, 0]
		if @pen == 1
			@entities.add_curve(p)
		end
	end
	def goto(x, y)
		p = []
		px = @LX
		py = @LY
		p << [px, py, 0]
		@LX = x
		@LY = y
		p << [@LX, @LY, 0]
		if @pen == 1
			@entities.add_curve(p)
		end
	end
	def circle(r)
		if @pen == 1
			@entities.add_circle([@LX, @LY + r, 0], Z_AXIS, r, 24)
		end
	end
	def circle2(r, d)
		if @pen == 1
			center = [@LX, @LY + r, 0]
			vector = Geom::Vector3d.new 0, 0, 1
			normal = vector.normalize!
			@entities.add_arc center, X_AXIS, normal, r / 2, (@ANGLE).degrees, (@ANGLE + d).degrees
		end
	end
	def dot(r)
		r = r / 2
		face = @entities.add_circle([@LX, @LY, 0], Z_AXIS, r, 24)
		circle = @entities.add_face face
	end
	def setheading(h)
		@ANGLE = h + 90
	end
	def setx(x)
		@LX = x
	end
	# まるかいてちょん
	def maru_chon(i)
		penup()
		goto(50 * i, 100)
		down()
		circle(50)
		penup()
		goto(30 * i, 140)
		dot(20)
	end
	# お豆に芽が出てて―
	def omame()
		penup()
		goto(0, 80)
		down()
		circle(20)
		goto(0, 50)
	end
	# お空に三日月のぼってた
	def osora_mikaduki()
		penup()
		goto(-40, 50)
		down()
		goto(40, 50)
		penup()
		goto(0, -30)
		down()
		setheading(90)
		circle2(80, 180)
		setheading(90)
	end
	# 植木鉢1
	def uekibachi_1()
		penup()
		goto(90, -40)
		down()
		setheading(180)
		circle2(100, 180)
		setx(-90)
		setheading(0)
		circle2(100, 180)
	end
	# 植木鉢2
	def uekibachi_2()
		penup()
		goto(0, -200)
		down()
		setheading(0)
		circle2(370, 160)
		setheading(200)
		circle2(370, 160)
		penup()
		goto(-67, 0)
		down()
		goto(67, 0)
	end
	# ひげを付けたら
	def hige(i)
		penup()
		goto(90 * i, 80)
		down()
		goto(130 * i, 90)
		penup()
		goto(90 * i, 60)
		down()
		goto(130 * i, 60)
		penup()
		goto(90 * i, 40)
		down()
		goto(130 * i, 30)
	end
	def run()
		maru_chon(-1)
		maru_chon(1)
		omame()
		osora_mikaduki()
		uekibachi_1()
		uekibachi_2()
		hige(-1)
		hige(1)
	end
end

```

以上。
Cursor使ってるとき、コピペでコンテキストチップとして扱われるの腹立つよな。

これが知りたかったんだよ

# Mac版プレーンテキスト貼り付け
⌥ + ⌘ + ⇧ + V

# Win版プレーンテキスト貼り付け
Ctrl + Shift + V

以上。
いちいちVScodeのLiveServerつかうのめんどくさい。自分のサイトをアプリみたいにアイコンダブルクリックで立ち上げたい。

## 何ができるようになるか？
アイコンダブルクリックでローカルで自分のサイトを立ち上げられる。
LiveServerをつかう。いちいちVScodeのLiveServerつかうのめんどくさくない？
突然ちょろっと開発状況見せたい時とかあるよね

## 前提条件
`Homebrew` と `Node.js`がインストールされてること。
そもそもインストールされてるか忘れた場合は以下のコマンドを打つ。
```
node -v
```

インストール済みであれば以下のような表示が出る。
```
v18.16.0
```

未インストールであれば以下のような表示となる。
```
zsh: command not found: node
```

Homebrewが未インストールであれば以下のコマンドでインストール
```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

Homebrewのパスを設定
```
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
```

Homebrewを使っている人は以下のコマンドでインストールしよう。
```
brew install node
```

## 手順

グローバルにLiveServerを入れる
```
npm install -g live-server
```

入ったか確認する。
```
live-server --version
```


**任意の名前.command** を作る
```
#!/bin/bash
live-server "ターゲットディレクトリのパス" --port=5503 &

# サーバーが起動するまで待機
sleep 3

# 指定のURLをブラウザで開く
open "http://127.0.0.1:5503/index.html"

```

実行権限を付与
```
chmod +x /ファイルのあるパス/任意の名前.command
```

**これで完了**
あとは任意の名前.commandをダブルクリックするだけ！
各サービスのModel Context Protocolのアーキテクチャ一覧

MCP(サーバー)の構成を探る

## MCP(サーバー)の標準ディレクトリ構成を知りたい
Model Context Protocol(MCP)はLLMとアプリケーションを繋ぎこむためのプロトコルです。ざっくりLLM側のMCPホストからMCPクライアントを通じてMCPサーバーへのリクエストを飛ばすAPIとして機能します。MCPの中にも区分があり、やり取りのヘルパーに近いPrompt、ファイルなどのResource、リモコンに近いToolがあります。

AIブームの中各サービスMCPを公開しています(特にサーバー、Toolの部分)が、Model Context Protocolが日々進化しておりWebサービスでいうMVCのようにアーキテクチャが定まっていない印象です。

[GitDiagram](https://gitdiagram.com)というLLMでgit repositoryの構成を図解してくれるサービスがあり、試す対象として良さそうに思ったので各社のMCP実装に対してかけてみます。

## AWS
![aws_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/970e5d2a-b400-443c-8d07-b52099567722.png)

https://github.com/awslabs/mcp

## Azure
![azure_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/977ec3c7-833a-42cc-8909-e1123bbaf365.png)

https://github.com/Azure/azure-mcp

## Blender
![blender_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/3e112d11-f573-4dcc-9ff4-b380c92b6417.png)

https://github.com/ahujasid/blender-mcp

## GitHub
![github_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/658ee6c1-c71b-4ad8-949f-5e5dc16de6b7.png)

https://github.com/github/github-mcp-server

## Grafana
![grafana_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/788a4b1a-7e14-40dd-aed5-319633c1c078.png)

https://github.com/grafana/mcp-grafana

## Neo4j
![neo4j_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/2d929a04-e1d2-4a74-99ff-41006c10ddac.png)

https://github.com/neo4j-contrib/mcp-neo4j/

## Notion
![notion_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/596f9e67-7d0e-4c86-972e-526474cb7cbe.png)

https://github.com/makenotion/notion-mcp-server

## Playwright
![playwright_mcp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103496/0649102c-f4f2-4d74-ae5a-502d86518048.png)

https://github.com/microsoft/playwright-mcp
基本的なメソッド(Ruby)

# 基本的なメソッド(Ruby)
Rubyには配列や数値、ハッシュを扱うための便利なメソッドが多数あります。今回はよく使う基本的なものをまとめてみました。

## 配列

### array[index]
指定したindexで要素を取得する。負の数で末尾からも指定可能です。

```Ruby
array = ['water', 'tea', 'coffee']
puts array[1]   # => "tea"
puts array[-1]  # => "coffee"
```
### array.first
配列の最初の要素を取得する。

```Ruby
array = ['water', 'tea', 'coffee']
puts array.first # => "water"
```

### array.last
配列の最後の要素を取得する。

```Ruby
array = ['water', 'tea', 'coffee']
puts array.last # => "coffee"
```

### array.join
配列の要素を結合して一つの文字列にする。

```Ruby
array = ['water', 'tea', 'coffee']
puts array.join("-") # => "water-tea-coffee"
```

### array.map
各要素に処理をして、新しい配列として返します。
元の配列は変更されない

```Ruby
array = ['water', 'tea', 'coffee']
new_array = []
new_array = array.map{|data|   data　+ "です" } #　ですを追加
puts new_array # => ["waterです", "teaです", "coffeeです"]
```

### array.each
各要素に対して処理を実行します。返り値は元の配列です。
元の配列は変更されません
副作用が主な仕様目的(表示、　保存など)

```Ruby
array = ['water', 'tea', 'coffee']
new_array = []
new_array = array.each{|data| puts data } #　配列の中身を表示
```

### array.sort
昇順に並べ替えます。

```Ruby
array = [9, 2, 5, 8, 2]
puts array.sort # => [2, 2, 5, 8, 9]
```

### array.reverse
配列の要素の並びを逆にする。

```Ruby
array = [9, 2, 5, 8, 2]
puts array.reverse # => [2, 8, 5, 2, 9]
```

### array.include?
値が含まれているか確認する。
返り値はboolean型

```Ruby
array = [9, 2, 5, 8, 2]
puts array.include?(6) # => false
```

### array.uniq
重複を取り除きます。

```Ruby
array = [9, 2, 5, 8, 2]
puts array.uniq # => [9, 2, 5, 8]
```

### array.max
配列から最大値を出力する。

```Ruby
array = [9, 2, 5, 8, 2]
puts array.max # => 9
```

### array.min
配列の最小値を出力する。

```Ruby
array = [9, 2, 5, 8, 2]
puts array.min # => 2
```

### array.sum
配列の要素の合計を求める。

```Ruby
array = [9, 2, 5, 8, 2]
puts array.sum # => 26
```

### array.chomp
改行や指定した文字列を削除するメソッド
指定なしの場合は改行を削除。

## 文字列
```Ruby
text = "helloo"
puts text.chomp("o") # => "hello"
```

## 数字
### number.to_i
int型に変換

```Ruby
number = '12'
puts number.to_i + 18 # => 30
```

### number.to_f
froot型に変換

```Ruby
number = '12'
puts number.to_f # => 12.0
```

### number.ceil
小数点を切り上げ

```Ruby
number = 12.1
puts number.ceil # => 13
```

### number.floor
小数点を切り捨て

```Ruby
number = '12.1'
puts number.to_i # => 12
```

### number.round
四捨五入をする

```Ruby
number = '12.5'
puts number.round # => 16
```

## ハッシュ
Hashはキー（key）と値（value）の組み合わせを管理するデータ構造

### hash.key?(key) / hash.has_key?(key)
指定のキーが有るか確認する。
```Ruby
hash = { "apple" => 100, "banana" => 200 }
```
この例では：
* "apple" がキー、100 が値
* "banana" がキー、200 が値

```Ruby
hash = { 1 => "water", 2 => "tea" }
puts hash.key?("water") # => false（キーの存在確認）
puts hash.has_value?("water") # => true（値の存在確認）
```

## まとめ
他にも様々あるので、調べて活用していきたい。
【公ド読】コードの読みやすさと保守容易性を改良する

【公式ドキュメントを読もうシリーズ】コードの読みやすさと保守容易性を改良する

## シリーズ概要

[https://qiita.com/yasu_programming/items/cec66f9e8d5d571e9ce3](https://qiita.com/yasu_programming/items/cec66f9e8d5d571e9ce3)

## URL

[https://docs.github.com/ja/copilot/copilot-chat-cookbook/refactoring-code/improving-code-readability-and-maintainability](https://docs.github.com/ja/copilot/copilot-chat-cookbook/refactoring-code/improving-code-readability-and-maintainability)

## 説明

リファクタリングに関しての具体的な方法に関して書かれている。

わかりづらい変数名 -> 理解しやすい変数名

> `Improve the variable names in this function`

複雑なif文の条件式 -> 理解しやすい関数

> `Simplify this code. Avoid using if/else chains but retain all function return values.`

深い入れ子の条件式 -> 早期リターンによる可読性の高い関数

> `Rewrite this code to avoid the nested if/else statements`

複数の責務が混ざっている関数 -> 責務の分離

> `How could the processOrder method be refactored to be more useful and easier to maintain`

## 所感

リファクタリングの方法をGithub Copilotで対応してくれる。

解像度の高いプロンプトを渡して、いいリファクタリングをしてもらえるようにしたい。
MBRでQEMUの起動

# 【超入門】自作MBRでQEMUを動かしてみる（macOS編）

## はじめに

QEMUと16進数1行コマンドだけで、**自作ブートセクタ（MBR）を作ってPCを起動する**ミニ実験です。

> 「BIOSが自作バイナリを読んで、CPUがあなたの命令で動き出す」
> 
> 
> ——それを512バイトで実現します。
> 

---

## ✅ 前提

- OS：macOS（Intel / Apple Silicon どちらもOK）
- QEMUがインストール済み（していない場合は↓）

```bash
brew install qemu
```

---

## 作業ディレクトリの準備
好きなディレクトリに作業ディレクトリを作成
```bash
mkdir ~/mbr-test
cd ~/mbr-test
```

---

## 自作MBR（ブートセクタ）バイナリを作る

```bash
# 1. 512バイトの空ファイル（全0）を作成
dd if=/dev/zero bs=512 count=1 of=img.bin status=none

# 2. 先頭に無限ループ命令 EB FE を書き込む
printf '\xeb\xfe' | dd of=img.bin bs=1 seek=0 conv=notrunc status=none

# 3. 最後の2バイトに「起動可能ディスク」サイン 55 AA を書き込む
printf '\x55\xaa' | dd of=img.bin bs=1 seek=510 conv=notrunc status=none
```

---

## 確認（念のため）

```bash
ls -lh img.bin
# → 512B になっていればOK！

xxd img.bin | tail
# → 最後が 55aa で終わっていればOK
```

---

## QEMUで起動

```bash
qemu-system-x86_64 -drive file=img.bin,format=raw
```
---

## 成功の目印

- 「Boot failed」などのエラーメッセージは出ない
- 黒い画面に点滅カーソルだけが表示される

---

## 🧠 補足：このimg.binの中身は？

| 範囲 | 内容 |
| --- | --- |
| 0x0000 | `EB FE` = `jmp $`（無限ループ） |
| 0x0002〜 | `00` パディング（509バイト） |
| 0x01FE〜 | `55 AA`（MBRの合言葉） |

この最小構成だけで「ブート可能なHDDイメージ」としてBIOSに認識され、QEMUで実行されます。
競プロ日記#25/05/21

# アルゴ式
[線分上の格子点の個数](https://algo-method.com/tasks/474)
- 「2つの格子点の各座標の差を取って最大公約数を取る→そこから-1した値」ということに気づけなかった。
```

// 最大公約数を求める関数
long long GCD(long long A, long long B) {
    if (B == 0)
        return A;
    else
        return GCD(B, A % B);
}

int main() {

    long long A, B, C, D;
    cin >> A >> B >> C >> D;

    long long G = GCD(abs(C - A), abs(D - B));
    cout << G - 1 << endl;
}
```

[Ax を B の倍数に (1)](https://algo-method.com/tasks/1107Dxp2)
- 割ればいいだけなのに無理にfor文で求めるというコーディングにとらわれすぎ解法で一度WAしてしまった。
- さすがに自分で気づけたが...
```
int main() {
    long long A,B,N;
    cin >> A >> B >> N;
    cout << N / B << endl;
}
```

[Ax を B の倍数に (2)](https://algo-method.com/tasks/461)
- [Ax を B の倍数に (1)](https://algo-method.com/tasks/1107Dxp2)の応用。A,Bが互いに素じゃない可能性を考慮して最大公約数Gで割ってしまえば[Ax を B の倍数に (1)](https://algo-method.com/tasks/1107Dxp2)に帰着できる。

[和と積が素数](https://algo-method.com/tasks/517)
- 和と積がともに整数となるa+bは3のみ

[素数の乱舞](https://algo-method.com/tasks/665)

[約数が奇数個](https://algo-method.com/tasks/355)
- 正の整数 Nの約数が奇数個 ⇔ Nは平方数ということに気づけば一瞬だった...
- 基本は約数というのはペアになるが唯一平方数の場合だけは異なる整数のペアにならない

[約数が 3 個](https://algo-method.com/tasks/358)
- 正の整数Nが3この約数を持つ⇔ある素数pが存在してN=p^2と表せる→つまりN以下の正数のうち素数の平方で表せるものを数え上げるということに気づけなかった...
- 解説AC

[N! の約数の個数](https://algo-method.com/tasks/452)
- ルシャンドル関数を知りませんでした

[あまりが等しい (2)](https://algo-method.com/tasks/551)
- 解説AC
- 解説読めば理解できるなあ程度。A0の式をそれぞれから引くという発想がない

[最大公約数の種類数 (1)](https://algo-method.com/tasks/530)
- 「題意を満たす⇔最小公倍数の約数の個数を求めること」という言いかえができなかった...
```
// N の約数をすべて求める関数
vector<long long> calc_divisors(long long N) {
    vector<long long> res;
    for (long long i = 1; i * i <= N; ++i) {
        if (N % i != 0) continue;
        res.push_back(i);
        if (N / i != i) res.push_back(N / i);
    }
    sort(res.begin(), res.end());
    return res;
}

int main() {
    // 入力
    long long N, M;
    cin >> N >> M;

    // M の約数の個数を答える
    cout << calc_divisors(M).size() << endl;
}
```

[最大公約数の種類数 (2)](https://algo-method.com/tasks/521/submissions/1737330)
- [最大公約数の種類数 (1)](https://algo-method.com/tasks/530)を応用するという意味では実質的な誘導があったから理解できるが、普通に一から答えを出すのは無理だと思う。題材は最大公約数じゃなかったがABC405のC問題とかちょっと似た考え方で解いたのを覚えている

[最大公約数の種類数 (3)](https://algo-method.com/tasks/578)
- 解説なし問題でわからずじまいだったので仕方なくGPT先生に聞いた。
- GPT先生は天才だった。
- M/GCD が N 乗数（整数の N 乗）になっているかを確認するという観点


[ミラー-ラビンの素数判定法](https://algo-method.com/tasks/513)
- 虚無
- 何の誘導もない素数判定問題（ただし高速で）かつヒント的なものもミラーラビン素数判定方のWikipediaへのリンクのみで泣く泣く解説を見るもサンプルコードと503で開けないページへのリンクだけだった...

[ポラードのロー素因数分解法](https://algo-method.com/tasks/553)
- 虚無（[ミラー-ラビンの素数判定法](https://algo-method.com/tasks/513)と同じ）
- 高速な素因数分解法だというのでどこかで使うタイミングがあれば活用したい

# 雑談
アルゴ式が一通り落ち着いた（上級は未着手...）ので「競技プログラミングの鉄則」を読み物として読破していたが実装まで含めてゴリゴリ身に着けていきたい。やはり読んだだけでは勝てない...
始めてQwik使ってみたメモ

新規サイトのフレームワーク選定でQwikを触ってみたので、メモ代わりに気づいたことを記載。
触り始めたばかりなので、何かあれば追記していく予定。

# yarn使う場合はv3以降が良さげ
特に公式サイト
https://qwik.dev/docs/getting-started/
にも記載がないけども、多分yarnのv3以上じゃないと動かない。
```
yarn create qwik
```
で以下のようなエラーが出た
```
# yarn create qwik
yarn create v1.22.22
[1/4] Resolving packages...
[2/4] Fetching packages...
warning create-qwik@1.14.0: The engine "pnpm" appears to be invalid.
error create-qwik@1.14.0: The engine "yarn" is incompatible with this module. Expected version ">=3.0.0". Got "1.22.22"
error Found incompatible module.
info Visit https://yarnpkg.com/en/docs/cli/create for documentation about this command.
```
yarnのバージョンを3以上にしろというので、corepackでyarnを最新版にしてリトライしたら成功した。
普段、Dockerのnodeイメージを使っているため、初期状態のyarn v1を使っていたのでここで引っかかった。
もしかしたらnpmでcreateしたあとyarn installでも動くかもしれないけど推奨されないと思う。

# bodyタグに変更を加えにくい
割と衝撃的だったのでメモ。
サイト全体でroot.tsxにheadとbodyを記載するので、bodyタグ自体にclassを入れるとサイト全体で共通で使うことになる。
通常のレイアウト組む場合は全然問題ないのだけども、
画面を上下にスクロールさせたときの余白の色はbodyの背景色になるので背景色が異なる画面を作る場合に微妙だなと。
何かしら変更する手段はあるのかもしれないけども、いかんせん資料が少ない…
おんJ民がnpmパッケージを公開してみた【TypeScript製お絵かきライブラリ】

ワイはおーぷん2ちゃんねるのなんでも実況J（ジュピター）板の住民、おんJ民や。


よろしく頼むで

# 🤔 何を作ったのか
HTMLの`<canvas>`って、レイヤー機能がないやん？

だからワイ、レイヤー付きのお絵かきライブラリを作ってnpmで公開したんやで。
パッケージ名はこれや：`pnpm i @onjmin/oekaki`

https://www.npmjs.com/package/@onjmin/oekaki

DEMO

https://unj.netlify.app/oekaki/demo

(DEMOは `Svelte` + `@onjmin/oekaki` の例やが多分他のFWでも使えるやで)

# 🎯 背景と動機
実はワイ、掲示板アプリを作ってるんやけど、
その１機能として **「お絵描き機能」** を搭載したかったんや。

---

お絵かき系のnpmパッケージやと `fabric.js` が有名や。
でも、レイヤー管理しようとするとめっちゃ面倒くさい。

🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺
1. canvasを複数重ねて自前でレイヤー風に管理
2. 各レイヤーの状態保存・切り替え・描画制御

🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺🥺

とかやろうとすると、 **「これもう自分で作った方が早いやろ」** ってなったんや。
だから `fabric.js` を捨てて、TypeScriptでフルスクラッチ実装したんやで。

---

当初は、お絵描きのロジックをそのまま アプリ内libディレクトリっぽい場所に置いてたんやけど、
気づいたら `4ファイル` にまで肥大化してもうて

> これリポジトリごと分離した方が良くね？

ってことで、 **お絵描きライブラリ部分だけnpmパッケージとして独立＆公開** したんや。

結果的に管理も開発もかなりスッキリしたんやで 🫵😎

# 開発環境のセットアップ

### 1. GitHubでリポジトリを作成
まずはパッケージ用に**GitHubで新しいリポジトリを作成。**
自動で生成された初期コミット付きのリポジトリを**git clone**して、ローカルで開発を始めたで。

### 2. 開発に必要なパッケージのインストール

##### 以下のパッケージを使ったで：

- `typescript`：TypeScriptで書くなら当然これがベースや。

- `@biomejs/biome`：フォーマット・リントこなせる便利ツール。
eslintやprettierを組み合わせるよりも楽。

- `tsup`：超高速なTypeScript用バンドラー。
バンドラーでググって上位に出てきたやつを選んだだけやで

- `typedoc`：TypeScriptの型から自動でドキュメントを生成してくれるやつ。
資料を作るのに時間かけてられんからな

📚**完成したドキュメント**：https://onjmin.github.io/oekaki

```json
	"devDependencies": {
		"@biomejs/biome": "1.9.4",
		"tsup": "8.5.0",
		"typedoc": "0.28.4",
		"typescript": "5.8.3"
	}
```

##### 💩不要と判断したモノ💩
- ビルド不要のTS実行環境 → `tsx`
デバッグしながら書くならtsxは便利なんやけど
もう出来上がってたから要らね

- 🧪 テストツール → `jest`
リント（biome）で型・構文エラーをきっちり潰せば正直十分じゃねーの？

### 3. npm公開までの流れ
アカウントだけ作れば誰でも公開できるやで
名前空間も取り放題や

```json
	"scripts": {
		"build": "tsup",
		"lint": "biome check .",
		"format": "biome format . --write",
		"docs": "typedoc src/index.ts --out docs",
		"release": "pnpm run build && pnpm run lint && pnpm run format && pnpm run docs",
		"patch": "pnpm version patch",
		"publish-dangerous-dont-use-this-command": "pnpm publish --access public"
	}
```

基本的には更新がしたくなったら３回コマンド叩けば済むようにしてるで

`pnpm run release`：ビルド + リントチェック + 整形 + ドキュメント生成
`pnpm run patch`：npmパッケージのバージョンを上げる
`pnpm publish --access public`：更新後の内容を公開

### おわり
意外と簡単やな😳
【Elasticsearch】あいまい検索、複数のフィールドで検索

## あいまい検索とは
ある一つのワードを元に複数の項目で検索をかける

## Elasticsearchでのあいまい検索の仕方
「本」というワードで検索をかけたい場合

```json
{
  "query": {
    "bool": {
      "should": [
        { "wildcard": { "name.keyword": "*本*" }},
        { "wildcard": { "kana.keyword": "*本*" }},
        { "wildcard": { "mail.keyword": "*本*" }},
        { "wildcard": { "department.keyword": "*本*" }}
      ],
      "minimum_should_match": 1
    }
  }
}
```

`should` でOR検索、つまりどれかが一致していれば、という条件を書くことができる。
`minimum_should_match` にはn件一致していれば、という条件が入る。今回はどれか1つが一致していればよいので1。

`wildcard`で部分一致検索ができる。`"*本*"`のように前後に`*`を入れることで、例えば「本田」や「営業本部」等が検索結果としてヒットするようになる。

ちなみに`name.keyword`ではなく、`name`のみにすると、形態素解析が入るため、例えば検索ワードを「山田」として実行すると、「山」もしくは「田」のどちらかが入っていればヒットする扱いになるため、「本田」も「宮田」も「田中」もヒットするようになる。
CiscoサーバのSDカード障害：トラブル対応メモ

# SDカードとは
**SDカード（Secure Digitalカード）**

フラッシュメモリを使った小型の記憶媒体で、データの読み書きが可能です。
写真や動画、ドキュメントの保存のほか、ハイパーバイザー（ESXi）やシステム情報を保存するためのOS起動ディスク（Boot Device）としても使われます。

| 種類       | 役割           | 特徴                |
| -------- | ------------ | ----------------- |
| SDカード    | 起動用ストレージなど   | 小さくて安価。書き換え耐性は低め   |
| メモリ（RAM） | 一時的な処理 | 超高速。電源を切ると中身は消える  |
| HDD      | 大容量データ保存     | 遅めだが安価。物理的回転ディスク  |
| SSD      | 高速データ保存      | 速く信頼性高い。vSANなどに多用 |

OSはSDカードで読みだされ、メモリ上に展開されて動作します。
仮想マシンの保存先（ストレージ）は、vSAN構成ならSSDやNVMeが使われます。

### 参考：SDカードだけでの運用が非推奨になりつつある
VMwareは、将来的なvSphereのリリースでSDカードやUSBデバイスをブートデバイスとしてサポートしない方針を示しています。

https://blogs.vmware.com/vsphere/2021/09/esxi-7-boot-media-consideration-vmware-technical-guidance.html?utm_source=chatgpt.com

**耐久性の問題**：SDカードは書き込み耐性が低く、頻繁な書き込みにより劣化しやすいです。特に、ログや一時ファイルの書き込みが多い環境では寿命が短くなります。
**パフォーマンスの制限**：SDカードの読み書き速度はHDDやSSDに比べて遅く、サーバーのパフォーマンスに影響を与える可能性があります。
**信頼性の欠如**：SDカードはエンタープライズ向けの使用を想定しておらず、障害発生時の診断や監視が難しいです。

# "flexflash"と"bootbank"エラー
**FlexFlash**
SDカードコントローラーのCisco用名称で、SDカード自体とその管理を行うコンポーネントです。
flexflash エラー → SDカードそのものかコントローラに障害

**bootbank**
ESXiのシステム構成ファイルが格納されたパーティション名。通常、SDカード上にbootbankが存在します。ESXiの基本ファイルを格納し、起動時に使用します。
bootbank エラー → ESXiの起動領域にアクセス失敗している

→ bootbank障害は、再起動で解消されます。
SDカードの接触不良や一時的なマウント失敗が原因で、再起動によってSDカードが正しく再認識され、正常にマウントされます。


#### 参考：

https://www.fsi-embedded.jp/embedded_news/sdcard/vol9/

# 状況別まとめ
### CIMCでSDカードSlot1・2が壊れている表示があるが、WebClient上は正常に見える
CIMCの障害検知は物理的な接触や状態で判断する一方、
WebClientでは論理的にOSがSDカードを読めていれば正常稼働しているように見えます。

- **CIMCのセンサー誤検知や一時的な通信不具合**によるもので、SDカード自体やOSの動作には影響がない

もしくは

- SDカードはブート時に必要な情報を保持しているため、現在の動作に問題がなくても、**次回再起動時にbootbankの読み込みに失敗**し、ESXiが起動できなくなる

ことが考えられます。

### SDカード交換でメンテナンスモードが自動的に解除された
ESXiが保持していた構成情報（メンテ状態を含む）がSDカードとともに失われ、vCenterとの整合性が崩れたことが原因と考えられます。

ESXiの状態情報は基本的にメモリや内部構成ファイルにありますが、SDカードにも一部が保存されているため、交換時に反映されないことがあります。

対応：**SDカード交換時にはDRSをオフにしておく**

### 同期モードAutoでSlot1を交換したらOSが起動しなくなった
通常、プライマリ→セカンダリへコピーが行われます。

- 同期モードAutoなら、Slot1（プライマリ）を交換しても、CIMCは「先に認識したほう」をプライマリと判断し、Slot2 → Slot1の自動同期が正常に動作します

しかし、

- 新しい空のSDカードがプライマリと誤認識され、空のデータが正常なカードに上書きされることもあります

対応：**SDカード交換時には同期モードをmanualにしておく**

## xxx.用語

#### プライマリとセカンダリ（Primary / Secondary）
2枚で冗長化。プライマリがメイン、セカンダリがバックアップ。

#### 自動同期
プライマリに書き込まれたデータをセカンダリに同期し、障害時のリカバリに備える。

CIMCがどちらのSDカードをプライマリとして認識するかを決定する。認識の順序や物理的接続状態によってプライマリが入れ替わることもある。

#### ハイパーバイザー（Hypervisor）
複数の仮想マシン（VM）を1台の物理サーバ上で動かすためのソフトウェア。
物理サーバのリソース（CPU、メモリ、ストレージ）を仮想マシンに割り当て管理する。

ESXi本体であり、SDカードの同期処理そのものは制御しない。同期状態に依存して起動するため、SDカードの整合性は重要。
【virtualbox】GuestAdditionsのバージョンの不整合エラーの解決

### 該当エラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575047/8209c4da-f604-4511-871c-86d00be01661.png)
ホスト側のGuest AdditionsとゲストOS側のGuest Additionsのバージョンが違う。

・`VBoxService --version`では7.1.6r17084（ISO版）
・`dpkg -l | grep virtualbox-guest-*`では 7.0.20-dfsg-1.2（リポジトリ版）

### 解決策
ISOイメージ版で統一することにする。

**1.Debianパッケージ版の削除**
```
sudo apt purge -y virtualbox-guest-utils virtualbox-guest-x11
```
**2.必要パッケージのインストール**
```
sudo apt update
sudo apt install -y dkms build-essential linux-headers-$(uname -r)
```
**3.Guest Additions CDを挿入・マウント**
```
sudo mkdir -p /mnt/cdrom
sudo mount /dev/cdrom /cdrom
```
**4.ISOのインストール**
```
sudo sh /mnt/cdrom/VBoxLinuxAdditions.run
```
**5.ゲストを再起動**
```
sudo reboot
```
**バージョン確認**
```
VboxService --version
modinfo vboxguest | grep ^version
```
ここで同じバージョンが出ればOK
Push swapアルゴリズム実装メモ：座標圧縮の活用

## はじめに

42の課題「Push swap」に取り組んだ際の実装メモをまとめました。この記事では、特に座標圧縮テクニックを活用した効率的なソートアルゴリズムの実装方法について解説します。

## Push swapとは

Push swapは、2つのスタック（AとB）と限られた操作命令（push, swap, rotate等）を使って、スタックAの要素をソートする課題です。目標は、もともとAにランダムで入っていた整数（int型）を最小限の操作回数でAに昇順にソートすることです。

## 座標圧縮の必要性

大きな値や範囲の広い値を扱う場合、実際の値ではなく「相対的な大小関係」だけが重要になります。座標圧縮を使うことで数字をindexのように扱えるになります。これはビット演算を使用する基数ソート（Radix Sort）では必須です！！

## 実装の概要
```c
// 座標圧縮を行う関数
void coordinate_compression(int tab[],  int n)
{
    // 各要素について、自分より大きい要素の数を数える
    for (int i = 0; i < n; i++)
    {
        int rank = 0;
        for (int j = 0; j < n; j++) 
        {
            if (tab[j] < tab[i]) {
                rank++;
            }
        }
        // 自分より小さい要素の数がそのままランク（圧縮後の値）になる
        tab[i] = rank;
    }
}
```
座標圧縮の考え方：
- 前からランクを付けていく
- ランクは、自分より小さい数字が何個あるかを数える
- 自分より小さい要素が見つかれば、その数をカウント
- 結果、最小値は0、2番目に小さい値は1...と変換される

## Push swapでの応用

Push swapでは、入力値を座標圧縮することで、以下の利点があります：

1. **比較の簡素化**: 圧縮後の値は0からn-1の連続した整数になるため、比較操作が高速化
2. **アルゴリズムの単純化**: 大きな数字や負の数を気にせず、インデックスのように扱える
3. **メモリ効率**: ビット演算やバケットソートなどの最適化が容易になる

## 実装上の注意点

- 座標圧縮は入力の前処理として一度だけ行う
- 同じ値は同じランクに圧縮される点に注意←扱う前に同じ値があるかCheck！

## まとめ

Push swap課題において座標圧縮は非常に強力なテクニックです。入力値の範囲に関係なく、常に0からn-1の整数でアルゴリズムを構築できるため、最適化が容易になります。特に大規模データセットや幅広い値を扱う場合に効果を発揮します。

この手法はPush swapに限らず、競技プログラミングやアルゴリズム実装の様々な場面で活用できる便利なテクニックだと思います！是非ご活用ください！
課題に基づくプロトタイプ作成計画

## phase 1
課題: 論文を読む時間がない。膨大な情報の中から必要なキーワードや概念を見つけるのが大変。
ターゲット: 学生、研究者、技術者、業界アナリスト。
マイルストーン:
M1.1: 論文のテキストをペーストすると、要約とキーワードを生成するWebアプリ。
M1.2: 複数論文のURLを入力すると、それぞれを要約し、共通するテーマを抽出する。

課題: 初心者が特定の科学分野（例：量子力学、遺伝子工学の基礎）を理解するのに時間がかかる。用語や概念を気軽に質問できる相手がいない。
ターゲット: 専門外から参入するビジネスパーソン、学習者、他分野の研究者。
マイルストーン:
M2.1: 特定の教科書や公開情報を元に、基本的な質問に答えるチャットボット。
M2.2: ユーザーのレベルに合わせて回答を調整する機能（例：「初心者向けに優しく」「専門家向けに詳細に」）。

課題: プログラミング学習中にエラーが出た際、解決策を探すのに時間がかかる。エラーメッセージの解読が難しい。
ターゲット: ジュニアプログラマ、プログラミング学習者。
マイルストーン:
M3.1: エラーメッセージを入力すると、原因と解決策の候補を提示するWebアプリ。
M3.2: 使用言語やフレームワークを指定して、より的確なアドバイスを生成する。

課題: 特定の科学分野（例：新素材、ゲノム編集）の最新ニュースやトレンドを効率的に追うのが難しい。
ターゲット: 業界のビジネスディベロッパー、投資家、研究企画担当者。
マイルストーン:
M4.1: 特定キーワードでのWeb検索結果を要約し、ハイライトする。
M4.2: 毎日自動で実行し、指定のメールアドレスに要約を送信する。

課題: データ分析でグラフや図を作成する際、毎回コードを記述するのが面倒。最適な可視化方法が分からない。
ターゲット: 研究者、データアナリスト。
マイルストーン:
M5.1: シンプルなCSV（数値データ）から棒グラフ/折れ線グラフのPythonコードを生成。
M5.2: グラフの種類や軸の指定など、簡単なカスタマイズオプションを追加。
64ビットLinuxシステムコールの呼び出し

## 64ビットLinuxシステムコールの呼び出し時の決まり
引数はrdi → rsi → rdx → r10 → r8 → r9 の順に設定する
raxにはシステムコール番号を入れる。
返り値はraxに入る。

## write引数の設定
```
ssize_t write(int fd, const void *buf, size_t count);
```
```
mov rax, 1      ; システムコール番号1 = write
mov rdi, 1      ; 第1引数 fd = 標準出力（1）
mov rsi, msg    ; 第2引数 buf = 文字列アドレス
mov rdx, 10     ; 第3引数 count = 書き込むバイト数
syscall
```

## exit引数の設定
```
void exit(int status);
```
```
mov rax, 60     ; 番号60 = exit
mov rdi, 0      ; 第1引数 status = 終了コード
syscall
```
## アセンブリ言語のHelloWorld
### コード
```
; ファイル名: hello.asm
section .data
    msg db 'Hello, World!', 0x0A   ; 文字列 + 改行コード（LF）
    len equ $ - msg                ; 文字列の長さを計算

section .text
    global _start

_start:
    ; システムコール: sys_write（番号1）
    mov rax, 1          ; システムコール番号: 1（write）
    mov rdi, 1          ; ファイル記述子: 1（標準出力）
    mov rsi, msg        ; 文字列のアドレス
    mov rdx, len        ; 文字列の長さ
    syscall             ; システムコールを呼び出す

    ; システムコール: sys_exit（番号60）
    mov rax, 60         ; システムコール番号: 60（exit）
    xor rdi, rdi        ; 終了コード: 0
    syscall             ; システムコールを呼び出す
```
### 動作確認
```
nasm -f elf64 hello.asm -o hello.o
ld hello.o -o hello
./hello
```
```
ubuntu@ubuntu:~/kaihatsu/linuxasm$ ./hello
Hello, World!
ubuntu@ubuntu:~/kaihatsu/linuxasm$
```
kali linuxで公開鍵エラーが発生した件について

### 該当エラー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3575047/7ba3381b-bc81-417a-9e67-135703cafda0.png)

このエラーをかみ砕いてみると、、、、
要は、APT（パッケージマネージャー）がリポジトリのメタデータをダウンロードしたものの、手元に公開鍵が手元になく署名の検証ができないために「安全じゃない」と判断し、更新を拒否しているというもの。

### よくみると・・・
```
Missing key 827C8569F2518CC677FECA1AED65462EC8D5E4C5, which is needed to verify signature.
```
鍵ねぇよ！！改ざん検知できないよ！！このままじゃ！！と言ってくれている。
もっと、見てみると、/etc/apt/trusted.gpg.d/の中にないらしい。
なんでそもそもこんなエラーが急に出たんだ...？？？謎である。
ともかく早く解決しよう...。

### 解決策
`kali-archive-keyring`を再DLしようとしたが、そもそもAPTが使えないんだから無理じゃんとなり、オフライン的に実装することに...。

**1.`/etc/apt/sources.list`を公式に戻す。**
まずは、`sources.list`が正しい公式リポジトリを指しているか確認。
```
cat /etc/apt/sources.list
```
皆さん大好きnanoエディタで編集
```
nano /etc/apt/sources.list
```
sources.listの中身について
```
deb http://http.kali.org/kali kali-rolling main non-free contrib
```
:::note info
↑の1文のみにしてください。僕はサードパーティーが入っていました。おそらくこれが原因でしょうか...（？）
:::

**2.公式のキーリングパッケージを手動でDL**
https://http.kali.org/pool/main/k/kali-archive-keyring/
に飛んで、kali-archive-keyring_2025.1_all.debのURLをコピーする。

**3.kali linuxでwget**
```
wget http://http.kali.org/pool/main/k/kali-archive-keyring/kali-archive-keyring_2025.1_all.deb
```
**4.dpkgでインストール**
```
sudo dpkg -i kali-archive-keyring_2025.1_all.deb
```
成功したら、必要な公開鍵が`etc/apt/trusted.gpg.d/`に配置。

**5.いつも通りapt**
```
sudo apt update
sudo apt upgrade -y
```
### 参考文献（参照日2025年5月22）
https://qiita.com/y518gaku/items/435838097c700bbe6d1b

https://eset-info.canon-its.jp/malware_info/term/detail/00198.html