OmniAICreator/Qiita-1.07M huggingface dataset:
[ffmpeg] 動画から音を取り出そう

## インストール方法(インストール済みの人は飛ばして)
ffmpegをインストールする方法は、お使いのOSによって異なります。

**Windowsの場合**

1.  **ダウンロード:**

      - ffmpegの公式ウェブサイト（[https://ffmpeg.org/download.html](https://www.google.com/url?sa=E&source=gmail&q=https://ffmpeg.org/download.html)）にアクセスします。
      - "Windows builds by BtbN" のリンクをクリックします。
      - 必要に応じて "Version"、"Architecture"、"Linking" を選択し、"Download" ボタンをクリックしてダウンロードします。
      - ダウンロードしたzipファイルを解凍します。

2.  **環境変数の設定:**

      - 解凍したフォルダ内の `bin` フォルダのパスを環境変数 `Path` に追加します。
          - 例：解凍したフォルダが `C:\ffmpeg` の場合、`C:\ffmpeg\bin` を `Path` に追加します。
      - 環境変数の設定方法は以下の通りです。
          - Windowsキー + R を押して `sysdm.cpl` と入力し、Enterキーを押します。
          - 「システムのプロパティ」ウィンドウが開いたら、「詳細設定」タブをクリックします。
          - 「環境変数」ボタンをクリックします。
          - 「システム環境変数」の "Path" を選択し、「編集」ボタンをクリックします。
          - 「新規」ボタンをクリックし、`C:\ffmpeg\bin` を追加します。
          - 各ウィンドウで「OK」ボタンをクリックして閉じます。

3.  **インストールの確認:**

      - コマンドプロンプトを開き、`ffmpeg -version` と入力してEnterキーを押します。
      - ffmpegのバージョン情報が表示されれば、インストールは成功です。

**macOSの場合**

1.  **Homebrewのインストール:**

      - Homebrewがインストールされていない場合は、ターミナルで以下のコマンドを実行してインストールします。
        ```bash
        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
        ```

2.  **ffmpegのインストール:**

      - ターミナルで以下のコマンドを実行してffmpegをインストールします。
        ```bash
        brew install ffmpeg
        ```

3.  **インストールの確認:**

      - ターミナルで `ffmpeg -version` と入力してEnterキーを押します。
      - ffmpegのバージョン情報が表示されれば、インストールは成功です。

**Linuxの場合**

多くのLinuxディストリビューションでは、パッケージマネージャーを使ってffmpegをインストールできます。

  * **Ubuntu/Debian:**

    ```bash
    sudo apt-get update
    sudo apt-get install ffmpeg
    ```

  * **Fedora:**

    ```bash
    sudo dnf install ffmpeg
    ```

  * **Arch Linux:**

    ```bash
    sudo pacman -S ffmpeg
    ```

**インストールの確認:**

  - ターミナルで `ffmpeg -version` と入力してEnterキーを押します。
  - ffmpegのバージョン情報が表示されれば、インストールは成功です。


## 実行コマンド

movから


```
ffmpeg -i input.mov -vn -acodec libmp3lame output.mp3
```
```
ffmpeg -i input.mov -vn -acodec pcm_s16le output.wav
 ```

mp4から

 


```
ffmpeg -i input.mp4 -vn -acodec pcm_s16le output.wav
```
```
ffmpeg -i input.mp4 -vn -acodec libmp3lame output.mp3
```
Spresense向けPrivate LoRaのライブラリを登録してみた！

# 初めに
Spresense って、ものすごく省電力なので、通信は LPWA が向いていると思います。
そこで、Spresense で使えるLPWAを調べていると、

・LTE-M
・ELTRES
・Wi-SUN
・Zeta
・LoRa

等があり、かなり選択肢が豊富にありそうです。
その中で、LoRaを使ってみようと思いました。

# ブログ（元ネタ）
この記事は、以下のブログにあるものです。

https://spresense.livedoor.blog/archives/37459951.html

# 基板情報

Spresense向けのPrivate LoRa Add-onボードには、下記の「DTH-SSLR」があります。

https://dragon-torch.tech/cat-components/extension-boards/dth-sslr/

こちらは、プライベートなアンライセンスバンドを利用しており、
利用に関して課金等がないため、運用のハードルが低く、IoTをお試しするのに非常に入りやすいです。

https://clealink.jp/top/technology/PrivateLoRa/

# GitHubとライブラリ登録

ただ、このボードのソースコードはzipでのリリースで、いくつかのサンプル等も追加したかったので、ベンダに確認の上、少し整理してgitに展開しました。

https://github.com/Interested-In-Spresense/E220900t22s_jp

これを Arduino のライブラリマネージャに登録しました。
※ライブラリ名で怒られているけど登録できました。

https://github.com/arduino/library-registry/blob/main/repositories.txt

みんなで、ブラッシュアップしてもらえるとよいなと思います！

LTEとつないで、アクセスポイントになるサンプルなどを足そうかな。
[CloudTrail Lake]自然言語によるクエリ機能のアップデート

## ■初めに  
自然言語によるクエリ生成機能は2024年6月からありましたが、リージョンも絞られたプレビュー版だったので今回はリージョンを広げた正式なリリースに近いものかもしれません。（プレビュー表示のままですが）

AWS CloudTrail Lake が AI を活用した機能によりログ分析を強化

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/aws-cloudtrail-lake-log-analysis-ai-powered-features/

## ■まずAWS CloudTrail Lakeについて
CloudTrail Lakeは、AWSアカウント内で発生したAPIイベントを長期的に保存・分析できる機能です。
これまでは詳細なクエリ分析にSQLが必須でしたが、6月のプレビューで自然言語によるクエリ生成機能が追加されました。
SQLに不慣れな方でも気軽にログデータからインサイトを得られるようになっていたという所ですね。

## ■自然言語によるクエリ機能が導入
具体的には「最近、特定のIAMユーザーが行った操作を知りたい」といった自然な文章で問い合わせを行うだけで、AIが自動的に最適なクエリを生成し、必要なイベントを抽出します。
これによって、セキュリティ分析やトラブルシューティングといった作業の効率が大きく向上できると思われます。

## ■今回のアップデートについて
要点を絞ると2点かと思います。

・7つのAWSリージョンで一般公開された
・クエリ結果のAI要約が、バージニア北部、オレゴン、東京の各リージョンで利用できるようになった

## ■アップデートをログインして確認する  
使い方は変わってないかと思いますが、CloudTrailのメニューからCloudTrail Lakeを選択する事で利用できます。
東京リージョンで確認できているという点が今回の肝です。
勝手に日本語でいけるようになったと勘違いしてましたが、プロンプトと要約結果は英語になります…

![20241216034944.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/32eb9d3a-38b5-6f61-35e0-490fec0e68cd.png)

結果の要約は以下から。

![20241216035019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/3e48af0f-b69f-4972-8071-a3aa12a776d5.png)

## ■最後に  
自然言語でのログ分析が可能になったことで、運用チーム全体のスキルセットに依存せず、誰でも簡単に必要な情報を抽出できるようになります。
日本語化にも対応期待です！
ScrollViewを使ったアイテムリストの作成

## ScrollViewの作成
1.まず、UI>ScrollViewからScrollViewを作成する
2.strechにしておく
3.Hirizontalを削除する
4.ViewPortの水平をoffに
5.contentに下記のContentスクリプト、GridRayout、ContentSizeFitterをアタッチ
6.ViewPort、handle、GridRayoutを調整
7.Constrainntを変更
8.ContentスクリプトのTargetにはcontentを、_objectには増やしたいオブジェクトを入れる
9.ボタンなどでcontentスクリプトを操作する
## スクリプト
```ruby:Content.cs
     [SerializeField] GameObject _object;
     [SerializeField] GameObject Target;
     void Update()
     {
            ContentNum = Target.transform.childCount;
            count1 = ContentNum;
            
            Object2 = Instantiate(_object);
            Object2.name = _object.name + (count1 + 1);
            Object2.transform.SetParent(Target.transform);
            var rect=Object2.GetComponent<RectTransform>();
            Object2.transform.localScale = new Vector3(43.8f, 63.6f, 0);
            rect.transform.localPosition = new Vector3(0, 0, 0);
}
```
試験苦手マンが情報処理資格を取得するためにやったこと

情報処理技術者試験の一つである応用情報技術者試験に合格するための最短経路をまとめました。試験が苦手な方でも効率よく学習できるよう、実践した具体的なステップを紹介します。私が受けたときとはだいぶ試験の様子も変わっているようですが、基本は同じはずです。



## 午前試験対策

### 過去問を解きまくる

通勤時間やスキマ時間を活用して、過去問をひたすら解きます。以下のサイトが非常に便利です。スマホ1つあればランダム問題にし、ひたすら10問中8問以上の正解がコンスタントに出るまで繰り返し解き続けてください。

https://www.ap-siken.com/apkakomon.php

また、過去問を繰り返し解く中で、問題文と回答をほぼ丸暗記します。百人一首を覚える感覚で記憶するのがおすすめです。（問題文の冒頭を見たら、回答記号と回答の冒頭が出てくるような感じ）

### 新しい問題への対応

午前の2割り程度は新しい問題が出題されることが多いです。
そのため、時事ネタの対策も忘れずに行いましょう。直近の情報セキュリティ事故やニュースを調べておくと良いです。以下の情報源を参考にしてください：

https://www.ipa.go.jp/security/vuln/index.html

https://www.ipa.go.jp/jinzai/mitou/it/2024/index.html

https://www.ipa.go.jp/security/10threats/index.html

## 午後試験対策

### 1. 過去問を5年分解く

午前と同じく、ひたすら過去5年分くらいの午後試験の問題を解きます。
解く中で、自分が理解しやすい問題や得意なテーマをピックアップし、取り組む分野を5–6つに絞り込みましょう

### 2. 慣れを重視

午後試験では問題に慣れることが最重要です。特に

3. 分野ごとの注意点

プロジェクトマネジメント:  
プロジェクトマネジメントの手法そのものに基本パターンが多く、工夫された問題が出ることは少ないため、練習の効果が出やすい分野

データベース（DB）:  
応用情報では複雑な内容は出題されにくい

組み込みシステム:  
基礎的な内容が多く、パターン化されていることが多い

## 総括

試験対策の鍵は「徹底した過去問演習」と「覚えるべき内容を効率的に覚える」ことです。特に、午前試験では問題文を覚える勢いで取り組み、午後試験では得意分野に注力することで効率的な学習が可能です。また、時事ネタや直近のトレンドに対応することで、試験本番でもスムーズに対応できるようになります。苦手意識を克服し、ぜひ合格を目指しましょう！

ただし、この内容は試験に合格する方法です。実践で役に立つ体系的知識を身に着けたり、行動力を養うものではありません。 __目的が手段になってしまわないように注意しましょう。__

参考にした記事:

https://qiita.com/railgun-0402/items/fdc7ef895ca59bcd8c75
【TypeScript】type-challenges 初級編 3312・Parameters 解説

## お題
`Parameters<T>`を使用せずに、関数型から引数の型を取得し、配列を構想する形`MyParameters`を実装する。

## やりたいこと
```typescript
const foo = (arg1: string, arg2: number): void => {}

type FunctionParamsType = MyParameters<typeof foo> // [arg1: string, arg2: number]
```

## 解答
```typescript
type MyParameters<T extends (...args:any[]) => any> = 
  T extends (...args: infer Arg) => any
  ? Arg
  : never;
```

## 解説
### 処理の流れ
- `<T extends (...args:any[]) => any>`
`T`が関数型であることを制約する。
- `T extends (...args: infer Arg) => any`
`infer`を使って、引数の型を推論する。
:::note warn
Argの中身について
`Arg`が推論される値は、引数リスト全体である。
```ts
type ExampleFunction = (x: number, y: string) => boolean;

type Result = MyParameters<ExampleFunction>;
```
引数部分の`(x: number, y: string)`が、配列（タプル）型`[number, string]`として`Arg`に推論される。
:::

### 関数の型を宣言するには？
:::note info
**関数の型を宣言する**とは...
関数の実装を示さず、関数のインターフェースを定義すること。
:::

関数の型宣言をする構文は2つある。
1\. アロー関数構文
```ts
type 型の名前 = (引数名: 引数の型) => 戻り値の型;

type fn1 = (str: string) => string;
// string型を受け取り、string型を返す関数の型宣言
```

2\. メソッド構文
```ts
type 型の名前 = {
  (引数名: 引数の型): 戻り値の型
};

type fn2 = {
  (str: string): string;
};
```

### 残余引数/可変長引数（...）とは...
引数の数が決まっていない関数を作ることができ、**引数の個数が決まっていない引数**のことを残余引数と呼ぶ。

:::note info
**残余引数の書き方**
引数の前に、`...`を書く。
```ts
function func(...params) {
  // ...
};
```
:::

:::note warn
**残余引数のルール**
- 受け取った引数は配列になる
```ts
function func(...params) {
  console.log(params)
};
func(1, 2, 3); // => [1, 2, 3]
```
- 型注釈するには、配列の型を書く
```ts
// 残余引数がnumber型の場合
function func(...params: number[]) {
  // ...
}
```
:::

:::note alert
**残余引数のルール**
- 残余引数を複数持たせることはできない
```ts
// 構文エラーが出る例

function func(...params1, ...params2) {};
// A rest parameter must be last in a parameter list. 
```

- 残余引数は必ず最後の引数でなければならない 
```ts
// 構文エラーが出る例

function func(...params, param1) {};
// A rest parameter must be last in a parameter list. 
```
:::

### 関数の型の宣言と残余引数を使うことで...
上記の解説から、`(...args: any[]) => any`の意味がわかるようになる！

### 関数から関数の型を宣言するには...
**typeof演算子**を使用する。
```ts
function func(num: number): number {
 return num + 1
};

type Increment = typeof func; // => (num: number) => number
```

### inferとは...
https://qiita.com/yuto99999/items/057e28323118c4ac5de0#infer%E3%81%A8%E3%81%AF

## 参考記事
### 関数の型の宣言について
- [関数の型の宣言 | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/functions/function-type-declaration)

### 残余引数について
- [残余引数/可変長引数 | TypeScript入門『サバイバルTypeScript』](https://typescriptbook.jp/reference/functions/rest-parameters)

## 今回の問題
https://github.com/type-challenges/type-challenges/blob/main/questions/03312-easy-parameters/README.ja.md
ブループリントの自動マージを実装してみる


こちらの記事は、Unreal Engine (UE) Advent Calendar 2024 シリーズ4の21日目の記事です。

https://qiita.com/advent-calendar/2024/ue


## はじめに
複数人で開発しているときに、ブループリントの変更が衝突して、マージ方法に悩んだ方は多いかと思います。
通常はなるべく同時に編集しないようにするなどの回避策をとるかと思うのですが、
ある程度自動でマージできないかと考え、実験してみたので共有します。

この記事では、ざっくりとどういう事を行ったのか概要だけ記載しますので、詳細は GitHub に上げているプロジェクトを参照してください。

一応、差分ツールは公式で用意されていますが、差分を確認しつつ手動でコピペするなどの対応になるかと思います。
https://logicalbeat.jp/blog/5290/

このツールで、競合している個所をピックアップし(プロパティ単位など細かい粒度で)、どちらを採用するかの選択まで行えたら完璧なんですが......

## 注意点
今回の内容は実験的なものですので、実際のプロジェクトで使用しようとするとまだまだ課題が多いと思います。
それにより、データが破損したりしても責任はとれないので、参考程度に留めておいてください。
ネット上に情報が少ない機能を利用していることもあって、安定性に不安が残ります......

## プロジェクト
https://github.com/uxtuno/BlueprintMergeTest

※確認にはビルドが必要になります。

## 環境
エンジンバージョン : 5.5.1

## 今回やった事 (概要)
Base, Mine, Other の 3 つの BP に対して下記の要素ごとにマージを実行します

* コンポーネント
  * SceneComponent が追加されていた場合、末尾への追加のみ対応 
* 変数
* 関数
* イベントグラフ
* プロパティのデフォルト値

Mine, Other をそれぞれ Base と比較し、片方のみ変更していた場合はそちらを採用します。
両方で変更されていた場合コンフリクトと判断し、ログに出力して Base の内容から変更されません。
ただし、両方の変更が同じ場合は変更が反映されます。(どちらを採用しても同じなので、とりあえず Mine を採用)

## プロジェクト確認方法
上記で共有した、GitHub からプロジェクトを落としたら、
BlueprintMergeTool というフォルダがあるのでその中の、
EUB_MergeTool を右クリックし、Editor Utility Blueprint を実行してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952668/85f5a4c2-8adf-da37-58f7-6f82e0a5bd3d.png)

すると、BP_Merged という BP が生成されるので、こちらがマージ結果となります。

## 結果

### マージ前
Base
![スクリーンショット 2024-12-16 020331.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952668/c8302379-5035-dd26-ac29-55b29a2d11e6.png)

Mine
![スクリーンショット 2024-12-16 020610.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952668/7dbd0bd6-66f1-539b-7b39-8441cba5c558.png)

Other
![スクリーンショット 2024-12-16 020645.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952668/e1206078-5b17-6bb3-589a-821339eda344.png)

### マージ後
Merged
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952668/b7aaba9a-9594-bdd8-f292-019c099ea5d4.png)

画像からだと分かりにくいですが、設定されている StaticMesh などプロパティを含めてマージされていることが分かります。(Mine と、Other のうち片方でのみ変更されている場合)
Base にのみ存在する BaseFunc (関数) はマージ結果からは削除されています。
ぜひ GitHub から落として色々試してみてください。
(複雑な BP をマージしようとするとすぐバグりそうですが......)

## 今後について
現状は実験のため、最低限の機能にとどまっていますが、機能の拡張について下記のようなものが考えられると思います。(実装するかは別として)
* コンフリクトした際に、どちらを採用するかを選択できるようにする
    * UI が欲しい......
* 関数単位にとどまらず、関数内の各ノードのプロパティ単位でマージできるようにする
    * 現状は、同じ関数を変更するとコンフリクト扱いになるが、プロパティの変更箇所が被っていなければマージできるようにする
    * ノード間の接続なども認識してマージできればいいが、大変そう......
* バージョン管理ツールと連携して、BP のファイルが競合していた場合にマージを実行できるようにする
    *  実際のプロジェクトで運用するためには必須の機能かと思います
*  変数、関数などの並び順を考慮した実装にする
    *  現状は並び順が意図せず変わってしまうケースあり


## まとめ
今回は、BP の自動マージについて実験してみました。

プロパティ単位や、関数単位などでマージできるので、この機能を発展させていけば、
他の人が作業中のファイルを触りたい時に、小規模の変更であればローカルで先に変更しておき、他の人の作業がサブミットされた後に自動マージするなど、ワークフローの選択肢が増えるのではないかと思いました。

今回共有したプロジェクトは、
BP のマージに限らず、BP 内の変数や関数をコードから編集する方法について色々調べながら実装していったので、(主にエンジンコード内)
何か参考になる箇所があれば幸いです。

また、他にこういうやり方があるよーなど、知見がある方はアドバイスを頂けると嬉しいです！


(時間とやる気があれば、実際のコードの説明も追記しておきます......)
Pythonを基礎から学ぶその4　デスクトップのアプリを作るその1

この記事は、[JavaとPythonを基礎から学びたい私のための Advent Calendar 2024](https://qiita.com/advent-calendar/2024/aruhitonocalendar)の16日目の記事です。
アプリを作ってみたいと思います。
# デスクトップアプリ
Pythonでは、パソコンで動くデスクトップのアプリを簡単に実装できるみたいです。おそらく、今後社会人になってPythonを使って何か作ることになるはずなので結構必須だと思われます。
C#ではUnity、C++はUnreal Engine、JavaならAndroid Studioなどアプリを作成するためのツールが存在するように、Pythonにもアプリを作るためのツールはあるみたいです。ただ、今日はコードだけでアプリを作れると知ったのでコードで作ってみようと思います。Pythonのゲームエンジンは後日勉強する機会があれば書きます。
# tkinter
Pythonの標準ライブラリとして存在しているようです。何もなくてもいいので、とりあえずアプリとして動くところまでやってみます。
以下が、アプリが動くものになります
```Test.py
import tkinter as tk

A=tk.Tk()

A.mainloop()
```
結果:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961125/2a0705d3-cb9d-b400-5f46-812073c20d18.png)
3行でお手軽に作れるみたいです。簡単でよかった。
## 解説
上から順に解説していきます。
```
import tkinter as tk
```
tkinterをimportします。それだけ。
```
A=tk.Tk()
```
AはtkinterのTkです。ここでウィンドウが作成されるようです。ここにいろいろな要素を追加して、アプリっぽくしていくみたいです。
```
A.mainloop()
```
<b>これがないと動きません。</b>アプリを動き続けている間、この行が動き続けていました。どうやら、アプリが終わるまでアプリのイベントを処理するためのもののようです。調べてみたところ、アプリのイベントが発生したかどうかを判定し続けるもののようです。
## アプリにいろいろ手を加える
今の状態のアプリは何もないし、名前も初期状態の「TK」から何も変わってません。これにいろいろ手を加えて、それっぽくしていきます。
### 名前を変える
```
A.title("アプリもどき")
```
ここで付けたタイトルは、windowsパソコンでは左上に表示されるアプリの名前です。Macは持ってないのでどこに表示されるか知りませんが、どちらであってもこれで名前を付けることが出きるっぽいです。
# アプリのサイズを変える
現状では初期状態の画面サイズは結構小さいです。これを結構大きくすることができるようです。
```
A.geometry("1000x800")
```
ジオメトリなるものを使うことでアプリのサイズを変更することができるようです。注意すべきなのは、1000x800のxの部分でしょう。小文字のアルファベットのxでした。
# 文字を表示する
味気ないので文字を表示します。
```
label=tk.Label(text='文字が出ました')
label.pack()
```
labelなるものを使うようです。「文字が出ました」と表示できました。２行目のlabel.pack()のカッコ内に表示させる場所を指定できるようです。
今日はここまで
# まとめ
tkinderを使うことで、コードだけでアプリを作ることができた。geometryをつかうことで画面サイズを、titleでアプリ名を変更できた。また、labelを使うことで文字を出せた。

今日はここまでで、最終的にこうなりました。
```
import tkinter as tk

A=tk.Tk()
A.geometry("1000x800")
A.title("アプリもどき")
label=tk.Label(text='文字が出ました')
label.pack()
A.mainloop()

```
# 参考文献

https://www.acrovision.jp/career/?p=2844

https://engineer-life.dev/python-desktop-app/

https://pythonsoba.tech/tkinter/

https://natu-ym.com/python-window-text/
php-srcをデバックしてみた


PHP([php-src](https://github.com/php/php-src))をコンパイルしてデバッグしてみたくなったので手順を残しておく。


# 環境

`VS Code`で`Dev Container`環境を構築します。

## ディレクトリ

```
|- .devcontainer/
|    |- devcontainer.json
|    |- Dockerfile
|
|- .vscode/
|    |- launch.json
|
|- php-src/
|
|- test.php
```
## コンテナの設定

### Deockerfile

```dockerfile:Dockerfile
FROM ubuntu:latest

RUN apt-get update && apt-get upgrade -y \ 
&& apt-get install -y make \
git zip unzip gcc gdb autoconf bison re2c pkg-config libxml2-dev libsqlite3-dev

CMD ["/bin/bash"]
```

* 基本的なPHPのビルドに必要なツールをインストールする

### devcontainer.json

```json:devcontainer.json
{
    "build": {
        "dockerfile": "Dockerfile",
        "context": ".."
    },
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-vscode.cpptools"
            ]
        }
    }
}
```

* `C/C++`の拡張機能をインストールされるようにする
* 必要な拡張がある場合はここで追加しておく

## デバッグ用の設定

```json:launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Main",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/php-src/sapi/cli/php",  // ビルドしたPHP (CLI) のパス
            "args": ["${workspaceFolder}/test.php"],               // 検証したいPHPスクリプトのパス
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

```

* GUIでデバッグできるように設定する

## PHPをビルドする

```sh
git clone https://github.com/php/php-src.git
cd php-src
./buildconf
./configure --enable-debug
make -j4
cd ..
```

ビルドすると、`./sapi/cli/php`にPHPのCLIが作成される

### 動作確認

```sh
> ./php-src/sapi/cli/php --version
PHP 8.5.0-dev (cli) (built: Dec 15 2024 17:10:01) (NTS DEBUG)
Copyright (c) The PHP Group
Zend Engine v4.5.0-dev, Copyright (c) Zend Technologies
```

## デバッグをする

試しに`var_dump`をデバッグしてみる

```php:test.php
<?php
var_dump("あ");
```

`実行とデバッグ`から`デバッグの開始`を実行する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348184/20c17a2d-e57b-5a72-9cdd-3784f9687487.png)



# まとめ

開発チームでPHPのバージョンアップ対応を進める中でPHPの挙動を確認するためにphp-srcを見たり、PHPのカンファレンスで話を聞く中でPHPの中身をいじってみたいと興味が湧いてきたのでデバッグしてみました。
今後は`AST`(抽象構文技)とかOpecodeとかも理解したいなぁと考えています。


# 参考

- [php-src debug マニュアル](https://speakerdeck.com/onopon/php-src-debug-maniyuaru)
- [php-srcを読んでみよう](https://speakerdeck.com/tzmfreedom/php-src-codereading)
- [PHPの内部コードをデバッグする (VSCode)](https://knooto.info/php-internals-debug/)
Ubuntu 22.04.4 LTS　で GDAL(osgeo) を pipenv install する

#### 経緯
Python で、地理空間データで座標変換を行うために osgeo を Install しようとしたところ非常に苦労。Linux まわりの情報はあまり落ちていなかったので忘備録。
※ AI に助けてもらいました。

## 環境
- OS: WSL2（Win11）
- python:  3.10.2
- 仮想環境: pipenv
- ---

Ubuntu 上で **`pipenv`** を用いて **GDAL** をインストールするには、GDAL が依存するライブラリ（特に C ライブラリや必要な開発ファイル）を先にシステムへインストールしておく必要があります。その後、GDAL を正しくインストールできます。
以下は、段階的に GDAL をセットアップする手順を説明します。
### **1. Ubuntu に必要な依存関係をインストールする**
#### GDAL のインストールに必要なパッケージ
GDAL パッケージ（Python バインディング）をインストールするために、まず GDAL の C ライブラリやヘッダーファイルなどの開発ツールをインストールする必要があります。以下を実行してください：
```bash:Bash
sudo apt update
sudo apt install build-essential libgdal-dev python3-dev
```
- **`libgdal-dev`**: GDAL の C ライブラリや開発ヘッダーファイル
- **`python3-dev`**: Python の開発ヘッダーファイル（GDAL の Python バインディングに必要）
- **`build-essential`**: コンパイルに必要な基本的なツール

インストールが完了したら、`libgdal` のバージョンを確認してください：
```bash:Bash
gdal-config --version
```
例：`3.4.1` などのバージョンが表示されます。この番号と一致する Python 用 GDAL バージョンを後でインストールします。
### **2. pipenv 環境を作成**
**新しいプロジェクトのフォルダ**を作成し、その中で `pipenv` を使用して GDAL をセットアップします。
1. **プロジェクトディレクトリを作成して移動**：
```bash:Bash
   mkdir my_gdal_project
   cd my_gdal_project
```
1. **`pipenv` 環境をセットアップ**： あなたがインストールしている Python バージョンに基づいて仮想環境を作成します（例では Python 3.10 を使用）。
```bash:Bash
   pipenv --python 3.10
```
1. **GDAL をインストール**： Pipenv を使って Python モジュールとしての GDAL をインストールします。
> **注意**: インストール時に GDAL のバージョン番号を指定する場合が多いです（システムの GDAL バージョンと互換性を保つため）。以下のようにバージョンを直接指定できます：
>
```bash:Bash
   pipenv install gdal==3.4.1
```
※ `3.4.1` の部分は、`gdal-config --version` の出力に一致させます。
### **4. インストールの確認**
インストール後、仮想環境を有効化して GDAL をインポートし、動作確認を行います：
1. **仮想環境を有効化**：
```bash:Bash
   pipenv shell
```
1. **Python インタプリタで GDAL をインポート**：
```python:Python
from osgeo import gdal

print(gdal.VersionInfo())
```
実行結果として GDAL のバージョンが表示されれば、セットアップは完了です。
OSSコントリビューションを簡単なところから始めてみよう

昨今のプロダクト開発でOSSを何も使っていないという人はほぼいないという前提で、日々OSSを使っていてバグを踏むことも稀にあるんじゃないかと思います。

ここでは、簡単なところから始めるOSSコントリビューションについて書いてみます。

## OSSコントリビュートは難しくない

もうこれに尽きます。
簡単なところではドキュメントの日本語や英語に誤字脱字を見つけたら、それに対してPull Requestを投げるだけでも十分なのです。

### Issueを検索・立てる

もし技術的なところで困ったらまずはIssueを見てみましょう。
検索をして自分と同じ状況で困ってる人がいたら、そのIssueや内部のコメントにリアクションをしたり、「I have same issue」と追加コメント入れたりするだけでOKです。リアクションが多ければ多いほど人目につく＝誰かが対応してくれるかもしれない優先度が上がるのです。

もし困ってる人が他にいなさそうで、自分だけ踏んだバグそうでしたらIssueを作りましょう。
ただし各OSSでIssueの書き方にテンプレートやルールがある場合もあるので注意が必要です。（大体はREADME.mdやCONTRIBUTING.mdに記載あり）

英語に自信がないという方は、日本語で書いたIssueの下書きをAI「この文章をエンジニアがGithubで使う英文に書き換えてください」とでも投げれば大丈夫です。

### git fork → 修正 → Pull Requestを投げる

この部分は皆さん解説されているので詳細は参考サイトを参照してください。

参考：

https://zenn.dev/kaz_z/articles/first-contributions

https://qiita.com/y-vectorfield/items/b955617712f3b66359f2

## マネージャーの人はOSSコントリビューションチャンスを見逃すな

マネージャーやテックリードの場合、技術的課題や問題について議論する場面も増えると思います。
そういうときは是非メンバーにOSSコントリビューションチャンスを譲ってほしいわけです。

例えばペアプロやモブプロでドキュメントの相互リーディングをやっていたときに見つけた誤りや他言語との差分。これらを修正する作業をそのままメンバーに振りましょう。
また、ジュニア層のメンバーが技術的につまずいてる点がOSSのバグが起因だったとき。このときも具体的な修正の方法や方針を提示したうえでOSSに対するPull Requestまですべてメンバーにやらせてください。

こうすることでメンバーは自信が持てますし、キャリアとしてもプラスになります。
OSSコントリビューションは、仕事を作ることと同じです。自分が損をするという思考にならないよう「メンバーの成長が自分のアウトプット」と意識することが大事です。

組織全体で快適なOSSライフを楽しみましょう！
単体テストに関する依存の分類

## はじめに

この記事では、単体テストにおける依存の分類について解説します。用語の定義などは Vladimir Khorikov 氏の単体テストの考え方/使い方（2022, マイナビ出版）に準拠しています。

## 依存の分類

単体テストにおいて重要な考え方の1つは「依存」の管理です。テストが依存する対象を正しく分類し、管理することで、テストの信頼性を向上させることができます。ここでは、依存を以下のように分類します。

1. **共有依存 (Shared Dependency)**  
2. **プライベート依存 (Private Dependency)**  
3. **プロセス外依存 (Out-of-Process Dependency)**  
4. **揮発性依存 (Volatile Dependency)**  

### 1. 共有依存 (Shared Dependency)

#### 定義
テストケース間で共有される依存のことです。同時に実行されるテストが互いに影響を及ぼし、予期しない動作を引き起こす原因となります。

#### 具体例

- **共有データベース**: 複数のテストケースが同じデータベースに依存し、テスト中にデータの変更が行われると、他のテストに影響が及ぶ可能性があります。
- **ファイルシステム**: 一つのテストが特定のファイルを書き換えると、別のテストがその変更に影響を受ける場合があります。

#### 解決方法

- テストごとに独立したデータセットを使用する。
- モックやスタブを利用し、共有リソースへの依存を排除する。

### 2. プライベート依存 (Private Dependency)

#### 定義
テストケース間で共有されない依存です。プライベート依存はさらに以下の2つに分類されます。

- **可変依存**: テストごとに異なる状態や振る舞いを持つ依存。
- **不変依存**: どのテストでも状態が変わらない依存。

#### 具体例

- **可変依存**: テストごとに異なるパラメータを受け取る関数。
  ```typescript
  function calculatePrice(discount: number): number {
      return 100 - discount;
  }

- **不変依存**: 定数や固定値を返す関数。
  ```typescript
  function getTaxRate(): number {
      return 10; // 固定の税率
  }
  ```
  
#### 重要性

プライベート依存を適切に管理することで、テストの独立性を保つことができます。可変依存ではテストデータを工夫し、不変依存では変更の必要がないことを確認できます。

### 3. プロセス外依存 (Out-of-Process Dependency)

#### 定義

アプリケーションのプロセス外で稼働する依存です。例えば、異なるプロセス間でデータをやり取りする際に利用されることが一般的です。

#### 具体例

- データベース: SQLクエリを実行する際の依存。
- メッセージキュー: RabbitMQやAmazon SQSなどの外部サービス。

#### 注意点

データベース依存は通常プロセス外依存で共有依存ですが、分離されたテスト用のインメモリデータベースを使用すれば、共有依存を排除できます。

### 4. 揮発性依存 (Volatile Dependency)

#### 定義

呼び出すたびに異なる振る舞いをする依存や、開発者の環境に特定の設定が必要となる依存のことです。

#### 具体例

- 現在日時
```
function getCurrentTime(): Date {
    return new Date();
}
```

- ランダム値

```
function generateRandomNumber(): number {
    return Math.random();
}
```

#### 問題点

揮発性依存はテスト結果を不安定にする可能性があります。テスト実行のたびに異なる結果が得られるため、失敗の原因を特定しづらくなります。

#### 解決方法

- 現在日時やランダム値を返す関数をモックに置き換える。
- 依存を明示的に注入する（例: 現在日時を引数として渡す）。


## 結論

単体テストを効果的に設計するためには、依存を正しく分類し、影響を最小限に抑える工夫が必要です。特に共有依存や揮発性依存はテストの信頼性に重大な影響を及ぼすため、注意深く管理しましょう。
コロケーションで散らばりがちな関連実装をわかりやすくする

自分でいつもコロケーションという単語を忘れてしまうので備忘録として残しておきます。

ここで言うコロケーション（Colocation）とは、プログラミングにおいてコードや関連リソースを意味的にまとまった単位（ドメインや機能単位）でディレクトリ構造に整理するアプローチです。
これにより、人間の可読性やトレーサビリティが向上し、開発者がコード全体の意図を素早く把握しやすくなります。

とりあえず最近触ってるNext.jsのPage Routerを用いたコロケーションの例について書きます。

## Next.jsのPage Routerにおけるコロケーション

2.1 Next.jsのディレクトリ構造

Next.jsのPage Routerはpagesディレクトリを基点としてルーティングを行います。以下の例は画面定義を前提としたコロケーションです：

```
/pages
  /about
    index.tsx         # Aboutページのエントリーポイント
    about.module.css  # Aboutページ専用のCSS
    about.test.tsx    # Aboutページのテストコード
  /dashboard
    index.tsx         # ダッシュボードのエントリーポイント
    components/
      Widget.tsx      # ダッシュボード内のウィジェットコンポーネント
      Widget.module.css
    utils/
      dataFetcher.ts  # ダッシュボード専用のユーティリティ
```

ドメインで分ける場合はもうUI層とドメイン層を分解するほうがいいかもしれません。私はこんな感じで使ってます。

```
/pages
  /about
    index.tsx         # Aboutページのエントリーポイント
    about.module.css  # Aboutページ専用のCSS
    about.test.tsx    # Aboutページのテストコード
  /dashboard
    index.tsx         # ダッシュボードのエントリーポイント
    utils/
      dataFetcher.ts  # ダッシュボード専用のユーティリティ
/components
  /OwnCompanyInfo     # Aboutページに使うドメイン
    /handlers         # onSubmitやonClickを扱う
    /hooks            # Hooksを扱う（useXXX)
    /services         # APIやデータ変換
    /ui               # UIコンポーネント群
      /view           # 参照系のUIコンポーネント
      /edit           # 編集系のコンポーネント
  /UserProfile        # ダッシュボードに使うドメイン
```

このディレクトリ構成でPage Routerを使っていると、実はApp Routerに移行するときもすんなりできてしまうメリットもあります。
`ui` と `hooks` ディレクトリはClient Component、 `hndlers` はServer Component、 `services` は Server Action という感じです。


### 循環参照をなくす

コロケーションを使う場合はあまり気にしなくても良いですが、ドメインを分割する場合は各コンポーネント定義がバラバラになるので循環参照が発生する `index.ts` によるエクスポートを使わないようにすると良いかもしれません。Barrel Filesと言われているようです。

```typescript:components/index.ts
export { CompanyInfo, CompanyDetail } from './OwnCompanyInfo';
export { UserProfile, UserPhoto } from './UserProfile';
```

これを `import { xxx } from '@components'` のように使ってしまうと、例えばAbutページでは不要な `CompanyInfo` のコンポーネントも事前ロードされてしまいます。何かしらの共通処理やグローバルな状態管理を使ってると意図しないデータ参照・取得が行われてしまうので注意が必要です。
私は知らなかったので目からウロコでした。

https://tkdodo.eu/blog/please-stop-using-barrel-files

## まとめ

- コロケーションはファイルをたくさん開くと混乱する人には親切設計
- 人間がわかりやすい実装は結果的に保守性やメンテナンス性の向上になる
- どこまでやるかはメンバーと相談して決めましょう
- ベストプラクティスはないので、都度システムやチームに応じてアーキテクチャもディレクトリごと変える覚悟は必要
【Tips】Power Automate でフローを試行錯誤して作っているときに、実行履歴を見やすくする

# はじめに
いろいろと編集してはテスト実行、編集してはテスト実行…と繰り返しているうちに、こんな状況になってしまい、**どの実行でどんなことをしていたか思い出せなくなる**人のためのTipsです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/1c5f6eff-02d3-08b2-2778-5cfb82c6ada4.png)

# 事前準備
特に実験用に使うことの多い、`フローを手動でトリガーする`トリガーで使える方法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/4dd25c19-1abc-9cd6-b816-adf0b360bd32.png)

方法としては、トリガーの入力に、以降のフローで全く必要のないメモ用のテキストを追加しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/27a222a1-a214-dca6-f1e3-2dedc05de47e.png)

# 実行時
テスト実行を行う際に、メモを要求されますので、変更内容や実行の目的を入力して実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/497aed9f-d4c6-1a7c-0929-050751968cc3.png)


# 確認方法
実行履歴の列の構成を編集して、トリガーに追加したメモを表示するようチェックを入れて保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/bcb6a5aa-629d-3cac-a023-8cd9e0513e79.png)

そうすると、実行履歴の一覧にメモが表示されるので、あとから履歴を参照しやすくなります！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/7086dbe1-cba2-d99d-bf20-d794e4ffca04.png)

# おわりに
こんなことをしなくても、ソリューションに追加したフローであれば、下書き保存やバージョン履歴の確認・復元ができます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2572227/4bf7b0aa-5e92-6430-6e55-6d9c5ac62a01.png)

…が、おそらくこういった簡易メモは残せないようですので、手軽に履歴を残したい場合には使える（かもしれない）方法です！ぜひお試しあれ！
【Day17】便利なプラグインをここらで解説【QAC24】


# 昨日説明したやつの延長線上なんですが

Overview として以下に Tauri v2 の Plugin の情報があります。

https://v2.tauri.app/plugin/

が、全てを紹介していくのも当然面倒極まりないので、便利そう...？なものをいくつかピックアップしてみました。

# `Clipboard`

これは名の通り Clipboard を管理するための Plugin です。

https://v2.tauri.app/plugin/clipboard/

`writeText`と`readText`というメソッドを使うことで、クリップボードの書き込み、読み込みが出来ます。

```typescript
import { writeText, readText } from "@tauri-apps/plugin-clipboard-manager";

await writeText("Hello, clipboard!");

console.log(await readText());
// おおよそ "Hello, clipboard!" になるだろう。
```

# `Dialog`

様々なダイアログを表示するための Plugin です。

https://v2.tauri.app/plugin/dialog/

実演した方がはやいでしょう。

```typescript
import { confirm } from "@tauri-apps/plugin-dialog";

const result = await confirm("進めちゃうよ！", {
  title: "かくにん！",
  kind: "warning",
});
console.log(result);
```

![スクリーンショット 2024-12-15 233209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/d053b32d-4f94-6caa-fa19-b76bff9670bc.png)

雑にやっちゃうとこんな感じのコードで、いい感じのダイアログが出てきます。

...あれ？ TypeScript デフォの`alert`とか`confirm`とか...？
考えてみればあそこらへんは同期処理なので、もしかしたら正式にはこっちを使う方がいいのかもしれませんね。
なにより、デフォルトのものは WebView のデザインなので少しダサいというかなんというかごにょごにょ...

# `File System`

前述なのでほぼ省略です。

https://v2.tauri.app/plugin/file-system/

ファイルの作成や削除、読み込み、書き込みが出来ます。
以外にもコピーとかなんかそこらへんも出来ちゃいます。

更には`watch`を使うことで、ファイルの変更がされたかどうかを監視することもできます。
これなんか凄そうですよね。

# `HTTP Client`

記事を書きながら調べているのですが、`Dialog`同様「ほほ～...」ってなりました。
HTTP リクエストを送るための Plugin です。

https://v2.tauri.app/plugin/http-client/

TypeScript ではデフォルトで`fetch`というものがあり、これを使うことで HTTP リクエストを送ることが出来ます。
同様のものとしてこの`HTTP Client`があり、関数の名前も同じく`fetch`です。

何が違うかというと、権限設定によってリクエストできるページや、出来ないページを設定することが出来るという点です。
それ以外は基本デフォルト`fetch`と同じなのですが、セキュリティを意識する上ではこちらの`HTTP Client`を使う方がいいかもしれませんね。

# `Single Instance`

これは TypeScript 側でどうのこーのみたいなプラグインではありませんが、アプリケーションの起動を制御するための Plugin です。

https://v2.tauri.app/plugin/single-instance/

どういうことかというと、アプリケーションが複数起動されるのを防ぐための Plugin です。
例えば、アプリケーションが複数起動されると、データの競合が起こる可能性があるので、それを防ぐために使います。

# `Store`

かなり便利な Plugin です。

https://v2.tauri.app/plugin/store/

これは、何かしらのデータを保存したいときに使います。

```typescript
import { load } from "@tauri-apps/plugin-store";

const store = await load("anything-store", { autoSave: false });

await store.set("username", "Harold");

const val = await store.get<string>("username");
console.log(val);
// Harold が出力されるはず

await store.save();
```

このように、`load`でストアを読み込み、`set`で値を設定、`get`で値を取得、`save`で保存することが出来ます。

このストアに保存したデータは Rust 側でも取得することが出来て、多分セーブデータとかに使えそうですね。
中身は良くも悪くも JSON なので...まぁ、うん。

# まとめ

このように、様々なプラグインがデフォルトで用意されています。
これを活用することでより幅広い表現が出来ると思うのですが...アイデアは思いつきましたか？

一番上のリンクのページを見てもらえばわかる通り、まだたくさんあるので気になった方は片っ端から見てみてください。

さーて次回はついに主人公を配置します。
これだけで一気に「おぉ...」ってなるので...（代わりにコードはえぐ汚いが）
Raspberry Pi 5のOSバージョン確認

# 1.はじめに
インストール時にバージョン記載を見つけられなかったので探していきたいと思います。

# 2.Raspberry Pi Imagerから
リリース日しか分からないです。
![20241216_00h44m06s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962266/aadb6b4e-3e20-0cdc-e13c-a74e1f83dd14.png)

# ３Debianのバージョン確認
```:debian_version
$ cat /etc/debian_version
12.8
```

# ４．カーネルバージョンの確認
```:debian_version
$ uname -a
#カーネルバージョンが出力されます。
```
ホットキーでアプリをアクティブにする方法

# はじめに
この記事は [Raycast Advent Calendar 2024](https://qiita.com/advent-calendar/2024/raycast) に参加しています。

15日目の記事は @se_eiji さんの [RaycastのAIをRaycast以外から利用する](https://qiita.com/se_eiji/items/00c8448594f094231763) でした。

# 背景
私は今年の7月頃から本格的に [Raycast](https://www.raycast.com/) を使い始めました。Raycast を使う前は [Alfred](https://www.alfredapp.com/) というランチャーアプリを使っていましたが、Alfred から Raycast に移行する際にあたり、どうしても Raycast に欲しい機能がありました。

Raycast は今年の7月に使い始める前から聞いたことはあり、実際、Alfred と Raycastの両方を起動して使っており「いつかは移行できたらいいなぁ」と Raycast を試しつつ、Raycast が更新される度にアップデートをしては、欲しい機能が実装されていないことを確認して、そっ閉じするということを繰り返していました。

# 欲しかった機能
私が欲しかった機能は、**ホットキーを使ってアプリケーションをアクティブにする機能**です。

Alfred の場合、こちらのスクリーンショットのように、ホットキーを追加することで、ホットキーを押下した際には常にそのアプリケーションをアクティブにすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3960293/5895ef09-48d3-641f-fdac-fb68bde1649e.png)

これと同じ機能を Raycast でも実現しようと思い、設定 → Extensions → Apps と進み、こちらの画面からホットキーを追加してみましたが上手く行きません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3960293/f8a92519-026e-d736-b804-74ffbe4f7dce.png)


Alfred と同じようにホットキーを作動させると、アプリケーション・ウィンドウがアクティブになるのではなく、トグルになることが判明しました。

私は windows manager を使用してレイアウトを自動調節するようにしているのですが、アプリケーション・ウィンドウがトグルしてしまうと、現状のレイアウトが崩れてしまいます。


レイアウトが崩れる様子（左下のターミナルをアクティブにしようとしている）
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3960293/ee452774-f9dd-e0eb-6f57-5d64afca039f.gif)


アプリケーションのウィンドウをアクティブにしようとする度に調整したレイアウトが崩れてしまうと、それだけで作業をする気力がなくなってしまいます。（弱すぎ）

また、「このホットキーを押したら、必ず◯◯のアプリケーションが前面に来る」といった冪等性（idempotence：2重に行っても一度だけ有効になる）を利用することでホットキー押下 → すぐにタイピングを始める、といったこともできなくなってしまいます。

# 解決方法を教えて頂きました！
このことを [Singularity Society](https://singularitysociety.org/) の第1回 BootCamp を通じて知り合った Y さんに相談したところ、サクッと解決方法を教えて下さいました。

script commands を使います。script commands については、[こちらの Raycast のブログ](https://www.raycast.com/blog/getting-started-with-script-commands)に詳しく書かれているので、そちらを参照してみて下さい。

以下の script command を適当な場所に保存し、保存したアプリケーションに対してホットキーを割り当てることで、ホットキー押下により必ず特定のアプリが前面に、そして有効に、することができます。

```bash
#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Open Alacritty
# @raycast.mode silent

# Optional parameters:
# @raycast.icon 🤖

# Documentation:
# @raycast.description Opens Alacritty

open /Applications/Alacritty.app
```

この欲しかった機能を Raycast で実現できるようになってからは、一気に Alfred から Raycast への移行が進みました。今では Raycast なしで mac を使うことは出来なくなるほど Raycast に依存した生活を送っています。

# 謝辞
Y さん、ありがとうございます！そして、Raycast の便利な使い方についていつも共有して下さる [Raycast コミュニティ](https://raycast.connpass.com/)の皆さんに感謝申し上げます。ありがとうございます！:bow:

Raycst のこれからの益々の発展を楽しみにしています！
目標をシンプルにしたら、チームが自律的に動き出した話

この記事は [目標づくり Advent Calendar 2024](https://adventar.org/calendars/10578) の16日目の記事です。

# はじめに

私は2023年10月に現在のチームにテックリードとしてジョインしましたが、チームのパフォーマンスは決して高くない状況でした。
この記事では、そんな状況から、目標づくりを通じてチームをどのように変えていったのかをお伝えしたいと思います。


# 我々は Low パフォーマーでした

下の図は、私がチームにジョインした時期のマイルストーンのイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314315/b6030ede-e745-943c-29ce-f3f737bca83c.png)

複数のマイルストーンが並行して進行しており、リリースの順序もめちゃくちゃでした。
長いマイルストーンは半年近く開発しており、スピード感はあまりない状況でした。

チームの持つ業務の都合で仕方がない面もあるのですが、改善が必要な状況であることは明らかでした。


# OKR が機能していなかった

私たちの会社では3か月ごとにOKRを設定します。
しかし、業務都合で OKR に集中できなかったり、3か月の中で注力ポイントが変わってしまうことがあり、このOKRが本来の目的である「チームを同じ方向に向かわせ、モチベーションを高める」という役割を果たせていませんでした。

結果として、当初のOKRは形骸化し、チームのモチベーションを下げる要因にさえなっていました。


# 目標づくりからチームを変えたかった

チームには、日々降ってくる仕事をこなすだけのマインドが少しありました。
これを変えたいと考えた私は、2024年1月のOKR設定のタイミングで、「2024年内に会社をリードするチームになろう」と声をかけました。

単なる精神論ではなく、OKRを追い求めることで最高のチームに近づいていけるような、そんな目標を作ろうと決意しました。

# 目標づくりで意識したこと

目標を設定する際、以下の点を特に意識しました。

## とにかくシンプルにする

- 「何を作るか」は目標に設定せず、提供した価値にも着目しないことにしました
- その代わり、リリースした機能のボリュームのみに着目することにしました
- 正確なパフォーマンス測定より分かりやすさを優先し、着目するメトリクスも極力減らしました

## 定量的にする

- 機能のボリュームを測る方法を統一し、過去や他人と比較できるようにしました
- 進捗を可視化し、チーム全員が現状を把握できるようにしました

## 共通言語としての目標

- 目標がチーム内の共通言語、スローガンとして毎日意識されるようなものを目指しました
- 週次の定例でも必ず目標の進捗を確認するようにしました

# その結果

これらの取り組みの結果、チームは Medium パフォーマーのレベルまで成長しました。
以下の図は今年7月から現在までのマイルストーンの様子です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314315/88d7e582-8b2e-f10b-3512-5e3f9158a69a.png)

2週間に1度のリリースを守れるようになってきており、開発のボリュームも倍以上になりました。
この改善はメンバーが目標達成のために自律的に考えて動いてくれた結果達成されたもので、私はあまり何もしていません！

# まとめ

Low パフォーマーから Medium パフォーマーへの変革において、最も重要だったのは「シンプルで明確な目標設定」でした。抽象的な目標や複雑な指標ではなく、シンプルで全員が理解できる目標を設定することで、チームは自律的に動き始めました。

今後は High パフォーマーを目指して、開発プロセスの大きな課題を解消するなど、さらなる改善を続けていきたいと思います。
スケジュールも Slideshow に表示させよう

## RSS があれば何でもできる！
[MeePet を Android 端末として使う](https://qiita.com/harycurl/items/8bb100d914c97fe4bb68) の記事で、 Android の Slideshow アプリを使って MeePet をサイネージ化した。
RSS ファイルをティッカーとして流すことができるので、予定も RSS ファイルにしてしまえばティッカーとして流せる！ということに気づき、やってみることにした。

## Android の Web サーバーへファイルをアップロードする
[PHP を雑に書いて Web 情報取得（株価指数を大きな文字で表示）](https://qiita.com/harycurl/items/d9cd0e98bfe4ee8de175) の記事で紹介した Termux を MeePet に入れ、 MeePet 内で PHP 環境を完結できるようにした。

https://pc.watch.impress.co.jp/docs/column/nishikawa/1409411.html

基本的には上記記事の通りにやれば構築できる。ただし、 8080 ポートは Slideshow の設定用に使われるので、 Apache Web サーバーのポートを 8008 に移動させた。

次に予定のファイルであるが、Android にファイルを転送するのは面倒なので、 Web サーバーの機能を使うことにする。

予め、奇数行に日時、偶数行に内容を記したファイルを用意しておく（文字コードは UTF-8 で）。
```:schedule.txt
13(金)
TUT-Code記事のアップ
14(土)
PHPスクレイピング記事のアップ
15(日)
MeePetでQPython記事のアップ
```

MeePet へのファイルアップロードはこちらのサイトをそのまま使った。

https://web.just4fun.biz/?PHP/PHP%E3%81%AB%E3%82%88%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E3%81%AE%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%82%B3%E3%83%BC%E3%83%89

## スクリプトで RSS ファイルに変換
[気象庁予報の JSON ファイルを PHP で RSS 形式に変換してみる](https://qiita.com/harycurl/items/64b8958ce0e1914e900e) で行った方法と同様に行える。
Web サーバーにアップロードしたファイルを、 PHP ファイルを実行することで RSS に変換する。
```php:schedule_rss_gen.php
<?php
$lines = file('../data/schedule.txt');

$fp = fopen("../rss/schedule.xml", "w");
fwrite($fp, "\xEF\xBB\xBF");
fwrite($fp, '<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>予定</title>
<link>http://localhost/</link>
<description>予定</description>
<lastBuildDate>'.gmdate("D, d M Y H:i:s T").'</lastBuildDate>
');
foreach ($lines as $line_num => $line) {
    if ($line_num % 2 == 0) {
        fwrite($fp, '<item><title>' . $line . '</title>');
    } else {
        fwrite($fp, '<description>' . $line . '</description></item>');
    }
}
fwrite($fp, '</channel></rss>');
fclose($fp);
echo 'Schedule RSS file generated.';
?>
```

## Slideshow で RSS ファイルを指定する
あとは、出来上がった RSS ファイルを Slideshow に設定するだけである。
天気 RSS に引き続いて表示させたい。
2つ以上の RSS はカンマを挟んで列挙すれば続けてティッカー表示させることができる。
が、ここでカンマの後ろに余分なスペースを空けてしまい、2本目がエラーで読み込まれない事態に。
スペースを入れずに列挙する。
![slideshow_schedule_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/b0f08cfe-2425-90bd-86b1-7e28db7b1d25.png)

これで無事に予定のティッカーも表示されるようになった。
![slideshow_schedule_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/35ad2087-c6ad-64c1-96f5-df026a9d6df9.jpeg)
学校配布書類管理アプリ　ミキティーが学校の配布書類の管理が困ってるって言ってたので・・夫が寝た後に好きな夫の挑戦②

# 1 はじめに
私、50歳で初めて子供ができたじじパパ。プログラミング初心者ですが、プログラミングで子育てがもっと楽しくならないか模索中。

### 1-1 夫が寝た後にを見るのが好き
テレビでミキティーが、学校の配布書類の管理が大変！！って言ってたから、なんか管理が楽になるアプリ作れないかなと。

### 1-2 奥さんにAIを使って欲しい
AIつよつよ夫婦になって、今後のキャリア形成に活かせたらと思い、AI利用を奥さんに勧めるもなかなか上手く行きません(^^;;
なんかAIで便利になるものを実際に作れたら、もっと興味を持ってくれるのでは？？と考えました。

### Part①はこちら

https://qiita.com/mgdemg1004/items/638705bf7cfbaca54cbf

# 記事の内容（Part①の続き）

学校からの配布書類を管理するアプリを作成したいのですが、難しいので以下記事のアプリ作成に挑戦しました。

https://qiita.com/mkthrkw/items/c3fd56a8cc21f13e3cb8

• LINEとGASを連携させ、ユーザーのアップロードした画像を処理する方法
• GASを使って画像をDifyに送信する方法
• DifyでAIを活用し画像からデータを抽出し、Googleスプレッドシートに保存する方法

### 前回の続き 
途中で詰まったりして、少しほったらかしにしてました・・・。
しかし、夫が寝た後にを見て、やらねばと奮起して取り組み・・・

なんと、詰まって何時間もわからなかったところが、すぐ解決して、完成しました！！
このもの作りってこういうこと多いかも。煮詰まったら寝ろってこと？？

Lineでレシートの画像を送付すると
![IMG_6577.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531581/41472123-aa0d-2895-a286-438ff0f00f96.jpeg)

Googleスプレッドシートに自動的に保管されます
![スクリーンショット 2024-12-16 0.28.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531581/1371d961-da35-1fd3-7f8f-cced5e179f05.jpeg)

# 配布書類管理に応用
領収書管理が出来たので、それを配布書類に応用しました。
これも結構苦戦して、３日位かかりましたが成功しました。
詳細は後日また報告します。
### 完成イメージ

https://x.com/irifuneshinmori/status/1868812552123388160?s=46&t=m_0fdZgl8nb-uJn435XEZw

# まとめ
基本的に、参考記事通りにやって成功しました。

Part①で出来たこと
✅画像をスマホ撮影
✅Lineで画像送付
✅GoogleDriveに保存（自動）
✅Lineに「画像受け取れました」のメッセージ受取（自動）

Part②で出来たこと
✅受取画像をDifyに送付
✅DifyのLLMで画像のテキストを読み取り
✅上記をGoogle Spreadsheetに保存

配布書類の管理に応用

# 次の挑戦
◻︎Notion 情報管理

に挑戦していきたいと思います。
【VisionOS】Blendarで作成したモデルをVision Proで表示させる

## はじめに
今年の6月 ついに日本でもVision Proが発売されました。

Vison Proに心を躍らせて、購入された方も少なくないのではないでしょうか？

この記事では、Blendarで作成したモデルを表示させる方法を紹介しようと思います。

## USDZファイルを作成する

まずは、Blenderで作成したモデルをUSDZファイルに書き出します。

`File > Export > Universal Scene Description(.usd*)` を選択します。
![スクリーンショット 2024-12-15 23.53.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/e7eb040e-3f2f-d551-e7e6-eaa65eab5ecc.png)

その後、ファイル名を指定する時に `****.usdz` にして、Exportします。 
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/0b91d288-dce8-5556-6cbd-3c5d122b7878.png)

## Vision Proでモデルを表示させる
作成した USDZファイル をプロジェクトのフォルダの中に配置します。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/cfe37f57-9d3f-5c29-30e6-ef24d7707cca.png)

次は、コードを書いていきます！
３Dモデルを表示させるには、`Model3D` を使います。

https://developer.apple.com/documentation/realitykit/model3d/

↓実装イメージはこんな感じです。

```swift
var body: some View {
    Model3D(named: "model"){model in
        model
            .resizable()
            .aspectRatio(contentMode: .fit)
    } placeholder: {
        ProgressView()
    }
    .frame(width: 400, height: 300)
}
```

+ `named: "model"` のところにファイル名を指定することで、表示させるモデルを指定することができます
+ `.resizable()`・`.aspectRatio(contentMode: .fit)` でモデルのアスペクト比を固定して、サイズがwindowに合うようにしてくれています
+ `placeholder: { ... }` のところで、読み込み中の時に `ProgressView()`を表示するようにしています

実際にアプリを起動してみるとこんな感じになりました。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/e7d40041-4cb7-e309-b3d8-220146437413.png)

## まとめ

この記事では、Blendarで作成したモデルをVision Proで表示させる方法について解説しました。
ぜひ参考にしてみてください！

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
UbuntuでOpenVPNサーバーを5分で構築した話【openvpn-install】

はじめまして、合同会社AI Forward代表の寺園です。

業務でVPNサーバーが必要になり、Ubuntuで簡単に構築できる方法を探していたところ、`openvpn-install`というスクリプトを見つけました。

これが思いのほか手軽だったので、導入手順や使用したVPS（Contabo）のおすすめポイントを紹介します。

## Contaboの東京リージョンが高速でおすすめ

まず、VPN用サーバーとして**Contabo**のVPSを選びました。

選択したのは以下の条件です

- **契約期間:** 1ヶ月
- **リージョン:** Asia (Japan)（東京リージョン）
- **50 GB NVMe, Ubuntu 24.04, 10 TB Out + Unlimited In**
- 約**5.85 USD（約900円/月）**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3962261/0a59460e-86ea-42f4-f537-6d732805ffe0.png)

実は最初、ヨーロッパリージョン（ドイツなど）で1.7 USD安いプランも試してみましたが、通信速度がとても遅く、`fast.com`で500kbps程度しか出ませんでした。

`speedtest.net`で現地サーバーに接続しても5mbps程度しか出ませんでした。

東京リージョンならその差額分（270円程度）以上の快適さ（検証した時は100mbps前後）が得られます。特別な理由がなければ、少し高くても東京リージョンを選ぶことを強くおすすめします。

## Ubuntu 24.04上でのOpenVPN構築手順

ここで使用するのはNyr氏が公開している`openvpn-install`スクリプトです。

GitHubはこちら → [Nyr/openvpn-install](https://github.com/Nyr/openvpn-install)

### 手順概要

1. **サーバー初期設定**  
   VPSを契約し、付与されたIPアドレスに`root`ユーザーでSSH接続します。
   
   ※初期設定後はrootユーザーでの直接ログインを無効化し、一般ユーザーでの鍵認証ログインへ切り替えることをおすすめします。
2. **パッケージ更新**
   ```bash
   sudo apt update
   sudo apt upgrade -y
   ```

3. **スクリプトのダウンロードと実行**
   ```bash
   wget https://raw.githubusercontent.com/Nyr/openvpn-install/master/openvpn-install.sh
   chmod +x openvpn-install.sh
   sudo ./openvpn-install.sh
   ```

   実行すると対話式で以下のような項目を聞かれますが、基本的にデフォルトで問題ありません

   - プロトコル(UDP推奨)：UDP
   - ポート番号(デフォルト)：1194
   - DNSサーバー選択(デフォルト）：1
   - クライアント名(デフォルト）：client

   これでOpenVPNがセットアップされ、`client.ovpn`といったクライアント設定ファイルが自動生成されます。

### クライアントファイル（.ovpn）の取得

サーバー上にできあがった`client.ovpn`ファイルをローカル端末に持ってくる必要があります。

ここでは、2つの方法を紹介します。

#### 方法1：scpコマンドで取得（安全でおすすめ）

scpコマンドを使えば、サーバーから直接ローカル端末にファイルをダウンロードできます。

```bash
scp user@example.com:~/client.ovpn .
```

- example.comはサーバーのIPアドレスまたはドメイン名に置き換えてください。
- userはサーバーのユーザー名です。デフォルトでは`root`が一般的です。

実行後、`client.ovpn`がローカルのカレントディレクトリにダウンロードされます。

#### 方法2：一時的なオンラインストレージを活用（楽だけどちょっと危ないかも）

file.ioという無料サービスを使うと、ファイルを一時的にアップロードしてURL経由でダウンロードできます。

このサービスは1回ダウンロードするとファイルが削除される仕組みです。

```bash
curl -F "file=@./client.ovpn" https://file.io
```

実行するとURLが返ってくるので、そのURLをローカル端末で開けば`client.ovpn`を簡単にダウンロードできます。

この方法は、scpを使えない環境で役立ちます。

## 使用感

- 対話式でセットアップが終わるので、面倒な設定ファイル編集は必要ありません。
- 東京リージョンVPS上だと速度も良好で、動画視聴にも耐えうる快適さでした。
- クライアントを増やしたい場合も、再度スクリプトを実行すれば追加・削除が簡単です。

## WireGuard版も存在

同じNyr氏が、WireGuard用のスクリプトも公開しています。

GitHubはこちら → [Nyr/wireguard-install](https://github.com/Nyr/wireguard-install)

WireGuardはOpenVPNより軽量で高速と評判なので、さらなるパフォーマンスを求める場合は、WireGuard版を試してみるのも良い選択肢です。

## 注意点

- **ポート開放を忘れずに**  
  OpenVPNのデフォルトポート1194/udpをファイアウォールで許可してください。  
  （`sudo ufw allow 1194/udp` などで対応）

- **`client.ovpn`ファイルは秘密鍵も含まれます**  
  外部に漏れないよう慎重に扱ってください。
kerberos認証の仕組みをまとめてみた　~LinuC303での学習内容を元に~

# 概要
- LinuC303の勉強を始めたはいいが、202の勉強を丸暗記で乗り越えたためほとんど話を思い出せなかった
- LinuC303の黒本が高すぎて買えないので、自分なりに調べた内容を図にして頭に定着させてみようと思う

# 図にしてみる

![client端末.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616564/e2b8946c-6d8f-f989-275e-17365f76f91e.png)

きっとこういうこと
- 初回認証時に①-③を実行して資格情報の検証をする
- TGTを発行された後は、ユーザの利用資格が検証済みなので、別のサーバにアクセスする際も④以降の処理だけが動作する
    - 資格情報の検証が１度で済むから**SSO**


# 感想とどうでもいいこと
- client端末から各サーバに認証をする様が複数の首を持つケルベロスに見えるからkerberos認証なんだと思っていた
    - きっと認証のための番犬という意味のほう
- Project **Athena**の中で作られたからギリシャ神話の番犬なのかな

# 参考
https://ja.wikipedia.org/wiki/Project_Athena
Jetpack Composeでインナーシャドーをつけたい

自作のAndroidアプリのデザインでインナーシャドーをつけてたのですが、なんとJetpack Composeにはインナーシャドーがない！

FigmaでイキったUIデザインをしてたら大罠に引っかかりました。
Figmaにあるから簡単にできるもんだと思ってた。

この衝撃のメモ

## 自作でInner shadowのmodifierを作ろう

この記事を読めば１発で作れました。ありがとう。海外のつよつよエンジニア

https://medium.com/@kappdev/inner-shadow-in-jetpack-compose-d80dcd56f6cf

私は、ui/modifier/InnerShadowModifier.ktを作ってそこに書きました。
そのままコピペするだけでいけました。

## Modifierでセットしてみよう

以下のコードのように書くと画像のように確認できます。

``` sample.kt
.innerShadow(
    shape = RectangleShape, 
    color = ShadowBlack,
    offsetY = (2).dp, 
    offsetX = (2).dp,
    blur = 4.dp
)
```

![Screenshot 2024-12-16 at 0.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628307/2cadea2b-d3f4-0c26-0cde-4184858f889d.png)

### Figmaのデザイン通りに実装できそう

対応するFigmaの数値を入れるだけで作れるようになりました。
ありがとう。海外のつよつよエンジニア

Figmaの画面
![Screenshot 2024-12-16 at 0.28.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3628307/885963d4-2cae-7be0-3afd-17a63c0905e6.png)
ページネーションのマークアップ

## よくあるマークアップ
```html
<ol>
	<li><a href="/page/1/">最初のページへ</a></li>
	<li><a href="/page/6/">前へ</a></li>
	<li><a href="/page/1/">1</a></li>
	<li><a href="/page/2/">2</a></li>
    <li>…</li>
    <li><a href="/page/6/">6</a></li>
    <li>7</li>
    <li><a href="/page/8/">8</a></li>
    <li>…</li>
    <li><a href="/page/12/">12</a></li>
    <li><a href="/page/8/">次へ</a></li>
    <li><a href="/page/13/">最後のページへ</a></li>
</ol>
```

このマークアップは一見正しそうに見えますが、以下の問題点があります。

- スクリーンリーダーの読み上げが以下のように読まれる（VoiceOverの場合）
    - いち りんく　最初のページへ
    - に りんく　前へ
    - さん りんく　わん
    - よん　りんく とぅー
    - ご
    - ろく　りんく　ろく
    - なな　せぶん
- ページネーションなのかどうかがわからない
- n個目の`li`の連番とページ番号の連番が少し分かりにくい
- 現在何ページ目なのかが判断しづらい
- 飛ばされたページ部分が読み上げられないので何ページ目かを読み上げる数字が一気に飛ぶ


## 改善
```html
<nav aria-label="お知らせ ページネーション">
    <ol>
    	<li><a href="/page/1/">最初のページへ</a></li>
    	<li><a href="/page/6/">前へ</a></li>
    	<li><a href="/page/1/">1</a></li>
    	<li><a href="/page/2/">2</a></li>
        <li><span class="sr-only">3〜5ページをスキップ</span><span aria-hidden="true">…</span></li>
        <li><a href="/page/6/">6</a></li>
        <li><a role="link" aria-disabled="true" aria-current="page">7</a></li>
        <li><a href="/page/8/">8</a></li>
        <li><span class="sr-only">9〜11ページをスキップ</span><span aria-hidden="true">…</span></li>
        <li><a href="/page/12/">12</a></li>
        <li><a href="/page/8/">次へ</a></li>
        <li><a href="/page/13/">最後のページへ</a></li>
    </ol>
</nav>
```

- スクリーンリーダーの読み上げが以下のように読まれる（VoiceOverの場合）
    - お知らせページネーション　ナビゲーション
    - いち りんく　最初のページへ
    - に りんく　前へ
    - さん りんく　わん
    - よん　りんく　とぅー
    - ご　3〜5ページをスキップ
    - ろく　りんく　しっくす
    - なな　単色表示現在のページ　りんく せぶん


## やったこと
- `nav`要素で囲い、`aria-label`でページネーションであることを明示した
- カレントのリンクに`aria-current="page"`を付与した
- カレントのリンクをクリックしてページがリロードされてしまうのを避けるために`href`属性を無くし、無くしたことで失われる`role="link"`を追加した
- スキップされる部分のテキストにスクリーンリーダー用のテキストを追加した

ちょっと体験がよくなりましたね。

## 少し気になること
- `ol`を使うと`li`の何個目なのかが読み上げられるので少し混乱しますが、ページ数は最後に読まれるので許容できそうです
    - 個人的には`ul`よりも`ol`の方がまだ良いかなと思います

## まとめ
ページネーション一つとっても考えることは意外と多いですね。

スクリーンリーダー向けに調整しすぎるのも良くありませんが、実際スクリーンリーダーで読み上げてみて混乱したり何が何だかわからなくなるような場合は調整した方が良さそうです。

ただ、表示されるテキストとアクセシブルネームが違う場合ボイスコントロールが直感的ではなくなるときもあるので注意した方が良いでしょう。

`aria-xxx`は基本的に使用しない方がいいと[APG](https://www.w3.org/WAI/ARIA/apg/patterns/)にも書いてありますが、特にリンクやボタンなどに関しては`aria-label`の使用はなるべく控えた方がいいでしょう。

## 参考
- [Page by Page: How Pagination Makes the Web Accessible](https://htmhell.dev/adventcalendar/2024/14/)
最初に「あい」を学ぶことば日本語でプログラミング入門（ステップ２ なでしこの場合）

# はじめに
本記事シリーズは母国語のプログラミング言語が存在するという文化的価値をアピールするためのもので、プログラミング一般の入門を意図するものではありません。ステップ２としては、実用的な日本語プログラミング言語では第２世代に入る「なでしこ」で「あい」を学んでいきます。ついでにプログラミングの妙を遊ぶというお題となります。

## なでしこ
なでしこ(V1の場合)は、日本語に近い語順で記述できる、オープンソースのインタプリタ言語で実装言語はDelphi（デルファイ）です。
実装言語がC#の中間コードコンパイラ言語V2の開発は中断されて、現在はWebアプリケーションでもあるAltJSのV3に開発の力点をシフトしました。実装言語はNode.js(JavaScript)。V1は新規の機能は追加されていませんが現在もメンテ・利用されつづけています。なでしこは2005年に登場し、来年2025年で生誕２０周年を迎えます。

## なでしこの入手方法
なでしこバージョン1(Windows版)を下記の公式サイトからダウンロードできます。

https://www.nadesi.com/index.php?%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89


# お題のソースコード
```mind:ai.nako
あいとは
    人や物事を大切に思う心。
```

これをプログラムとして実行してみます。出現する単語を定義しておけば、なでしこはあらゆる文章をプログラムとして受け付けます。（ただし文意を維持して実行できるようにするには工夫が必要です。）
プログラム実行文に出現する単語をあらかじめ定義しておきます。話を簡単にするため、主に予約語を使ったユーザー単語定義と文字列定数の定義を用います。

```mind:ai.nako
人は　　"自分や自分以外の人間、"
物事は　"もろもろの物や事柄は"
大切は　"大切と思っている心のありようのことで、漢字では「愛」と表記します。"

●思う心（人や物事を大切に）
　「｛人｝｛物事｝｛大切｝」を表示。

●あいとは
    人や物事を大切に思う心。

あい。
```

# お題のソースコードを実行
では、実行してみます。実行環境はなでしこパッドです。

```
自分や自分以外の人間、もろもろの物や事柄は大切と思っている心のありようのことで、漢字では「愛」と表記します。
```

無事に成功しました:tada:

# おわりに
いかがでしたでしょうか？わたしはわが国に母語によるプログラミング言語が存在することを誇りに思っております。言語は文化。こんにちの日本語のポップスやアニメソングなどが海外でそのまま歌われるような近況を鑑みますと、純然たる技術基盤として超強力な米欧発プログラミング言語勢と存在意義を争うこともなく、日本語の文化として海外でも日本語プログラミング言語の愛される日が来るのやもしれません。