OmniAICreator/Qiita-1.07M huggingface dataset:
Arch Linux環境でdiscordを起動しても、スピーカーとマイクが機能していない。

## オーディオ周り（出力）の確認
**pulseaudio or pipewire 使用確認**
最近のArch Linuxでは pipewire が標準になっていますが、古い設定だと pulseaudio を使っているかも。

まず、どちらを使っているか確認しましょう：
```
pactl info
```
* Server Name: PulseAudio → PulseAudio使用中
* Server Name: PulseAudio (on PipeWire x.x.x) → PipeWire使用中

**自分の場合はこんな感じで返されました。**
```bash
pactl info
Connection failure: Connection refused
pa_context_connect() failed: Connection refused
```

おそらく PulseAudio/PipeWireの音声サーバーが動作していない か、起動していない 可能性が高いです。

## まず使っているオーディオスタックを確認
Archでは今は PipeWire が主流ですが、以下でどちらを使ってるかを調べます。
```bash
pacman -Qs pipewire
pacman -Qs pulseaudio
```

```bash
pacman -Qs pipewire
local/gst-plugin-pipewire 1:1.4.1-1
    Multimedia graph framework - pipewire plugin
local/libpipewire 1:1.4.1-1
    Low-latency audio/video router and processor - client library
local/libwireplumber 0.5.8-1
    Session / policy manager implementation for PipeWire - client library
local/pipewire 1:1.4.1-1
    Low-latency audio/video router and processor
local/pipewire-alsa 1:1.4.1-1
    Low-latency audio/video router and processor - ALSA configuration
local/pipewire-audio 1:1.4.1-1
    Low-latency audio/video router and processor - Audio support
local/pipewire-jack 1:1.4.1-1
    Low-latency audio/video router and processor - JACK replacement
local/pipewire-session-manager 1:1.4.1-1
    Session manager for PipeWire (default provider)
local/wireplumber 0.5.8-1
    Session / policy manager implementation for PipeWire

pacman -Qs pulseaudio
local/pamixer 1.6-3
    Pulseaudio command-line mixer like amixer
local/pavucontrol 1:6.1-1
    PulseAudio Volume Control
```
## この記述から分かること
* PipeWire 関連パッケージはほぼ揃っている
* ただし pipewire-pulse が未インストールっぽい
  * これがないと PulseAudio API（≒Discordなど）が動かず、pactl も失敗します
* pulseaudio 本体は入っておらず、PipeWire中心でOKな構成になってます
* pavucontrol はインストール済み
## 解決ステップ：pipewire-pulse のインストール＆有効化
pipewire-pulse をインストール
```
sudo pacman -S pipewire-pulse
```
ユーザーサービスとして有効化＆起動
```bash
systemctl --user daemon-reexec
systemctl --user enable --now pipewire pipewire-pulse wireplumber
```
Hyprlandの設定に起動時実行を追加（まだなら）
```ini
exec-once = systemctl --user start pipewire pipewire-pulse wireplumber
```
または .bash_profile, .zprofile, .profile などに以下を追記：
```
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
```
これで Wayland 環境でも pipewire が正しく起動するようになるかと。

一度ログアウト → 再ログイン（または再起動）後に以下を試してください：
```
pactl info
```
→ 今度は "Server Name" や "Default Sink" などの情報が表示されるはずです。

その後に pavucontrol や Discord を起動すれば、音声入出力の設定が可能になるはずです。
JavaScript【よく使う配列・オブジェクト処理まとめ】

この記事では、よく使う配列・オブジェクトの処理の使い方とサンプルコードを一覧として残していきます。

※本記事は今後も必要に応じて随時更新していく予定です。

---

##  Object.keys（オブジェクトのキーを取得）

`Object.keys()` は、オブジェクトのキー（左側の値）だけを配列として取得したいときに使います。

### サンプルコード

```javascript
const user = {
  name: "Alice",
  age: 30,
  isAdmin: false,
};

console.log(Object.keys(user));
// 出力: ["name", "age", "isAdmin"]

```
##  Array.forEach（配列に対してループ処理）

`forEach`メソッドは、配列の各要素に対して指定したコールバック関数を実行する際に使用します。ループ処理を簡潔に記述できる。

### サンプルコード
```javascript
const array = [1, 2, 3, 4, 5];

array.forEach((element, index) => {
  console.log(`Index: ${index}, Element: ${element}`);
});
// Expected output:
// Index: 0, Element: 1
// Index: 1, Element: 2
// Index: 2, Element: 3
// Index: 3, Element: 4
// Index: 4, Element: 5

```

##  Array.includes(配列にある特定の値をチェック)

`includes`メソッドは、配列に特定の値が含まれているかどうかを確認するために使用します。配列に特定の要素が含まれているかを簡単に判定できます。

### サンプルコード
```javascript
const fruits = ["apple", "banana", "cherry"];

console.log(fruits.includes("banana")); // Expected output: true
console.log(fruits.includes("orange")); // Expected output: false
```

##  Array.map(配列の各要素に対して処理を行う)
`map`メソッドは、配列の各要素に対して処理を行い、その結果を新しい配列として返すメソッドです。元の配列は変更されません。


### サンプルコード
```javascript
const numbers = [1, 2, 3, 4, 5];

const doubled = numbers.map((num) => num * 2);

console.log(doubled);  // Expected output: [2, 4, 6, 8, 10]

```

##  Array.filter(条件に一致する要素を抽出)
`filter`メソッドは、条件に一致する配列の要素を新しい配列として抽出するメソッドです。特定の条件を満たす要素だけを取り出す際に使います。


### サンプルコード
```javascript
const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = numbers.filter((num) => num % 2 === 0);

console.log(evenNumbers);  // Expected output: [2, 4, 6]

```

## Object.assign(オブジェクトをコピー)

 `Object.assign` メソッドは、オブジェクトをコピーしたり、複数のオブジェクトをマージするために使われます。特に、オブジェクトのプロパティを他のオブジェクトにコピーする際に便利です。

### サンプルコード
```javascript
const person = { name: 'John', age: 30 };
const copyPerson = Object.assign({}, person);

console.log(copyPerson); // { name: 'John', age: 30 }
console.log(person === copyPerson); // false (別のオブジェクト)

```
AtCoder水色になりました

# はじめに
ABC400で入水しました

![スクリーンショット 2025-04-05 23.29.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/707794/b6ee8318-b1ec-412b-a328-6869fc297f00.png)

~~AGC~~ ARC Div.2のRatedをようやく獲得しました。
日曜日にあることが多いので、出るかはわかりません。

### 入水について
直近のABCでは水perfを連発していたので、時間の問題だとは思っていました。
これまでにも入水チャンスはあって逃してきたので、期待せず目の前の成績に集中できたのは良かったと思います。
(例えばABC399のバチャは大事故となったので、問題との相性は大きいと思います)

### ABC400について
ABC100、ABC200、ABC300のテーマと絡んでいて面白かったです。400人の高橋君や400等分されたケーキは想像しづらいものがありましたが、抽象化の訓練だと思うことにしました。

# 自分について
- IT企業で会社員をやっています。2年目になりました。
仕事でプログラムを書く機会はなく、むしろ企画職として法律や規定に携わる業務がほとんどです。
就活の一環として応用情報を取りましたが、今の業務では出番がありません。

- タイトな期限の仕事が日常的に降ってきて残業したりもするので、
平日に精進の時間が取れるかは微妙になりました。

- 自分がついている業務をするような人で、休みの日にプログラミングというのは皆無に近いです。プログラミングがまず要りません。
それとは別に、社会人になるタイミングで競技プログラミングを離れる人は多いと思います。自分は離れなかった側なので、そういう話を今後はできるといいかもしれません。

# 基本的な考え方
- [AtCoder Problems](https://kenkoooo.com/atcoder/#/table/)のABCの問題を片っ端から解く方針をずっと維持しています。
始めた当時は6問ABCがまだ30回分くらいしかなかったので、AB問題くらいならわかりそうと思って大体埋めてしまい、
そのあとは茶色、緑色と進んでいきました。

- 予定がなければ必ずABCにRatedで出ています。
ここ2年くらいは終了後に必ずツイートして他の方のツイートも見て、自分がわからなかった問題の解法を知るようにしています。
また、これまで出られなかった回は大体バーチャル参加で走っています。（後述）
- 学生の頃から、[AtCoder Daily Training（通称ADT）](https://atcoder.jp/contests/adt_top)に出ています。
木曜日は20:30から始まる回があるので、社会人になってからも時々出ています。
- yukicoderやCodeForcesにも関心があったのですが、学生の頃からそれほど時間をとれなかったので、結局触れずじまいです。

# 心がけ
- メインのスキルセットはプログラミングではないので、むしろそれゆえに、毎週のABC Ratedは優先順位を高めにして対応しています。
プログラミングをある程度できるようにしたいと思って始めたわけですが、ブランクができるとおそらくもう戻ってはこられないでしょう。
    -できない場合は、週のうちどこかで必ず時間をとって何かを解きます。最近ではその枠がADTになっています。
- 冷えた（レートが下がった）回は、冷えた要因の問題をコンテスト直後にしばらく復習します。解説を読み、コードを自分の中で再生成する形式でupsolveします。
いま解けるべきレベルの問題であり、かつ考えていて頭に残っているためです
    - このレベルの問題が、かつては水色帯の問題であり、最近は青色前半の問題も入ってくるようになりました。逆に、黄色以上の問題は軽く解説を読むのみで、凸包や高速ゼータ変換が出てきたら読むのを諦めて寝ます。
    - 基本的に、今いるレート帯の問題をそれなりの速度で解ければ、レートは上昇していくようになっています。
ただ、自分の場合は分野の得手不得手が比較的はっきりしており、得意を伸ばすことで苦手をカバーする戦略が通りやすくなりました。

# おわりに
青色になりたいですが、このままだと16年くらいかかります（え？）
ASP.NET Coreで.netのバージョン違いのエラーが出たので対応方法を調べてみた

# はじめに
.netでクリーンアーキテクチャであれこれ開発してみたくなって、
githubからcloneしてきたソリューションをデバックしたところ、以下のようなエラーが発生。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4014590/ce7e5efc-da2b-475d-858b-20fa59dc6052.png)


あんまり見たことないので、せっかくなら記事にしちゃえ～の精神で、解決方法を探していきたいと思います。

# 何のエラー？

Github Copilot先輩は以下のように返答してくれました。

```
このエラーは、指定されたバージョンの .NET Core ランタイムまたは 
ASP.NET Core ランタイムが見つからないために発生しています。具体的に
は、アプリケーションが .NET 6.0.0 ランタイムを必要としているが、
システムにはインストールされていないことが原因です。
```

なるほど👀。ようするに、いまランタイムで実行している.netのバージョンが違うので、動かそうにもできませんよと怒られてしまっている状態ですね。

今回私が用意したASP.NET Coreは.net6.0対応なので、まずはいま手元にあるバージョンを以下のコマンドで確認してみましょう。

```
.NET SDK のバージョン
dotnet --list-sdks
```
続いて、今回怒られているランタイムのバージョンも見てみましょう。

```
.NET ランタイムバージョン
dotnet --list-runtimes
```

とすると、SDKとランタイムとも.net9.0である（2025年最新版）であることがわかりました。
うーん？一番新しい.netで動かないのはなぜなんだろう...？下位互換性が機能しないものなのか...？という疑問が発生。

# 対応方法
上記についてとりあえず後述に回して、とりあえず.net6.0をダウンロードします。

Powershellで実施。
```
wget https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-6.0.0-windows-x64-installer -OutFile dotnet-runtime-6.0.0-win-x64.exe
Start-Process -FilePath .\dotnet-runtime-6.0.0-win-x64.exe -ArgumentList '/quiet' -Wait
Remove-Item .\dotnet-runtime-6.0.0-win-x64.exe
```

そして、もう一度ビルドしてみると...
同じエラーが発生！！！Σ（・□・；）

詳しく調査すると、SDK・ランタイム両方とも.net6.0にする必要があるそうです。上記ではランタイムのみでしたのでSDKもインストールします。

すると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4014590/b08eefa5-e202-46f2-9c43-01f994ec9198.png)

無事起動されましたね！！

# .netに下位互換性はないの？
先ほどぶち当たった問題です。6.0以上のバージョンがすでにあるにも関わらず、あえて下位のバージョンをインストールしなければならないのはなかなかに不条理。

これについて生成AIに文句を言うと、このように返答されました。

```
.NET実行環境には特別な互換性の仕組みがあります。新しいバージョン（9.0など）をインストールしても、古いバージョン（6.0など）のアプリケーションは自動的には動作しません。
これには主に以下の理由があります：

ランタイムの独立性:
各.NETバージョンは独自のランタイム環境を持ち、
アプリケーションはビルド時に特定のバージョンを対象に設計されます。

破壊的変更の可能性: 
メジャーバージョン間では互換性のない変更が導入されることがあります。

ロールフォワードポリシー: 
.NET 5以降は、適切に設定されていれば「ロールフォワード」機能で上位バージョンで動作させることは可能ですが、デフォルトでは厳格に指定されたバージョンのみ使用します。

ASP.NET Coreアプリケーションの場合は特に、フレームワーク依存として公開されていると、指定されたバージョンのランタイムが必要になります。
```

どうやら、ランタイムには特定バージョンに依ることが必要らしく、最新のSDKを入れたところで動きませんよってことなのですね。
なるほど、.netのバージョン引き上げが苦労するわけですね...。


自己完結型（self-contained）デプロイメントという概念も紹介されましたが、未知の事項なのでまたいずれ試してみたいですね。
[Ubuntu24.04] いつも悩む、ApacheでPHPを動作させる

# 経緯
　LAN内にwebサーバーを立てる必要があったので必要なものをさっくりインストールして動作確認してみたところ、`Userdir`に作成した`index.html`へアクセスするとがめん真っ白、再起動すると「ファイルのダウンロード」になってしまって画面が表示されない。これで何時間無駄にしたか...

# 結論：ここを調べろ！

　`x`は環境に合わせて変更。

```
vi /etc/apache2/mods-enabled/php8.x.conf
```

　こいつだ！
 
```
 # Running PHP scripts in user directories is disabled by default
# 
# To re-enable PHP in user directories comment the following lines
# (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
# prevents .htaccess files from disabling it.

### 以下をコメントアウト！
#<IfModule mod_userdir.c>
#    <Directory /home/*/public_html>
#        php_admin_flag engine Off
#    </Directory>
#</IfModule>
```

　最初の設定ってたまにしかやらんので忘れるわぁ...。


　ちなみに、`.html`でphpを実行したい場合は同ファイル上にある`FilesMatch`を以下のように訂正する。

 ```
 <FilesMatch ".+\.(phar|php|phtml|html|htmls)$">
    SetHandler application/x-httpd-php
</FilesMatch>
```
TypeScriptをパターンマッチングでシンプルに：TS-Pattern入門

複雑なデータ構造を扱う際、長く複雑なif/elseやswitch文に疲れていませんか？そんなときに便利なのが、軽量ライブラリ「TS-Pattern」です。関数型プログラミングのスタイルでパターンマッチングを実現します。この記事では、パターンマッチングの利点、TS-Patternを使ったコードの書き方、実際の使用例、メリット・デメリット、そして効果的な使い方のコツを紹介します。

# なぜパターンマッチングか？

パターンマッチングとは、データ構造に基づいて判断を行うプログラミング手法です。TS-Patternは、直感的で型安全なAPIでパターンマッチングを実現します。データの形状をそのままコードに反映できるため、コードが非常に読みやすく、エラーの可能性も減少します。

以下の例で、従来の方法とTS-Patternを比較してみましょう。

TS-Patternを使わない場合：
```
function getStatusMessage(status: string): string {
    if (status === "success") {
        return "成功しました！";
    } else if (status === "error") {
        return "エラーが発生しました。";
    } else {
        return "不明なステータスです。";
    }
}
```

TS-Patternを使った場合：
```
import { match } from 'ts-pattern';

function getStatusMessage(status: string): string {
    return match(status)
        .with("success", () => "成功しました！")
        .with("error", () => "エラーが発生しました。")
        .otherwise(() => "不明なステータスです。")
}
```

従来の方法は、条件が増えると管理が難しくなりますが、TS-Patternを使うと、簡潔で読みやすいコードになります。

# TS-PatternのAPI概要

TS-Patternの中心はmatch関数です。この関数はパターンマッチングの入り口であり、値とパターンを照合し、該当するアクションを実行します。

```
import { match } from 'ts-pattern';

// Example using strings
const result = match(valueToMatch)
    .with("pattern1", () => {/* pattern1の処理 */})
    .with("pattern2", () => {/* pattern2の処理 */})
    .otherwise(() => {/* デフォルト処理 */});
```

`.otherwise()`を使用すると、どのパターンにも一致しない場合のデフォルト処理を設定できます。

詳細なドキュメントはこちらを参照してください：https://github.com/gvergnaud/ts-pattern

# TS-Patternのメリット・デメリット

メリット：

* 可読性：コードが読みやすく、意図が明確

* 表現力：データ構造を直接表現するパターン

* 型安全：TypeScriptの型システムを利用

* 簡潔さ：長い条件分岐を短く記述可能

デメリット：

* 学習曲線：パターンマッチングに慣れるまでに時間がかかる

* 依存性の追加：新しいライブラリ導入による依存関係の増加

# 効果的な使い方のコツ

* 簡単なケースから始める：基本的なパターンから徐々に複雑なケースへ

* TypeScriptを活用：型推論を最大限利用する

* 直感的なパターンを目指す：データ構造と似た形状のパターンを作成

* 積極的な試行錯誤：さまざまなパターンを試して学ぶ

* 公式ドキュメントを活用：公式のドキュメントをよく読み、理解を深める

# まとめ

TS-Patternを使えば、複雑な条件分岐をシンプルで表現力豊かなパターンマッチングに置き換えられます。ぜひTS-Patternを試して、TypeScriptでのパターンマッチングの快適さを体感してください。

# 参考資料
* TS-Pattern GitHub Repository: https://github.com/gvergnaud/ts-pattern
* TypeScript Handbook — Pattern Matching: https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions
Drizzle ORM でダミーデータを流し込む方法


https://orm.drizzle.team/docs/seed-overview

おそらく最後の `Drizzle ORM`。
テスト用のデータを流し込むシーダーについて。
こちらもちゃんと用意されている。（まだテスト版みたい）


## 適当にテストデータを作成する

```bash
$ npm i drizzle-seed
```

前の記事で作成した `users - posts` テーブルについて、データを流し込んでみる。

```ts:db/seed.ts
import { reset, seed } from "drizzle-seed"
import * as schema from './schema'
import { db } from '@/db'

async function main() {
  await reset(db as any, schema)
  await seed(db as any, schema).refine((f) => ({
    users: {
      count: 5,
      with: {
        posts: 10
      }
    }
  }))
}

main()
```

これを `tsx` で実行する。

```
$ npx tsx ./db/seed.ts

# 確認する
$ npx drizzle-kit studio
```

:::note warn
実行時にこのエラーが出てくることがある。
その時は `npm i pg` をするとよい。
まだテスト版のせいか、PostgreSQL モジュールが必須になってるみたい。
> Error: Cannot find module 'pg'  
:::

`studio` で見てみたらこんな感じ！  
個数しか指定していないのに、いい感じにデータが流し込めている。すごい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/5932cbbd-1e91-4cce-b94d-39513a153a79.png)

実はもっとハイテクで、疑似乱数ジェネレーターが組み込まれていて、シード値に基づいていい感じにしているみたい。
でも、そこまで細かく使うことはないかなぁ...



## Generator と Faker を用いて、適当にテストデータを作成する

標準で `int` や `string`、またよく使いそうな値に関して、ランダム生成用の関数が用意されている。

https://orm.drizzle.team/docs/seed-functions

通常の用途ではこれで十分だが、日本語にはまだ対応していないので、有名な `faker` ライブラリを併用するとよさそう。

https://fakerjs.dev/

```bash
$ npm install @faker-js/faker --save-dev
```

```ts:db/seed.ts
import { reset, seed } from "drizzle-seed"
import * as schema from './schema'
import { db } from '@/db'
import { fakerJA } from '@faker-js/faker'

const faker = fakerJA

async function main() {
  await reset(db as any, schema)
  await seed(db as any, schema).refine((f) => ({
    users: {
      count: 10,
      columns: {
        name: f.valuesFromArray({
          values: [...Array(100)].map(() => faker.person.fullName()),
          isUnique: true,
        }),
        age: f.weightedRandom([
          {
              weight: 0.3,
              value: f.int({ minValue: 18, maxValue: 30 })
          },
          {
              weight: 0.7,
              value: f.int({ minValue: 31, maxValue: 80 })
          }
        ]),
      },
    },
    posts: {
      count: 100,
      columns: {
        userId: f.int({ minValue: 1, maxValue: 10 }),
        title: f.valuesFromArray({
          values: [...Array(100)].map(() => faker.lorem.sentence()),
          isUnique: true,
        }),
        body: f.valuesFromArray({
          values: [...Array(100)].map(() => faker.lorem.paragraph()),
          isUnique: true,
        }),
      }
    }
  }))
}

main()
```

まだこのライブラリは SQLite に対応していないみたいなので、`db` は `any` で差し込む必要がある。
`reset()` でいわゆる truncate ができる。

結果はこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833190/92c86d42-08a8-4051-b358-80a47011d756.png)

これが Drizzle の最適解になりそう。
ただ正直ランダムにする理由も特にないので、べた書きSQLでも十分かとも思う今日この頃。
【初心者向け】クラウドとwebアプリって何が違うの？

## クラウドとは？

「クラウド」とは、インターネット経由でソフトウェアやデータを利用できる仕組みのことです。  
データやシステムはユーザーのパソコン内にあるのではなく、**インターネット上のサーバー（＝クラウド）で動いている**のが特徴です。

ユーザーはソフトをインストールすることなく、ブラウザやアプリを通じて、必要なサービスにアクセスできます。

### クラウドサービスの例（SaaS中心）
:::note info
以下のようなサービスは、すべてクラウド上で提供されています。

- **Google ドライブ**：ファイルの保存や共有をクラウドで行えるオンラインストレージ
- **freee会計**：中小企業向けのクラウド会計ソフト
- **Salesforce**：営業管理・顧客管理（CRM）を行うビジネス向けプラットフォーム
- **Zoom**：インターネット経由でWeb会議を行えるオンラインミーティングツール
- **Notion**：ドキュメント、タスク、データベースを統合した情報共有ツール
:::

いずれも**インターネットにつながっていれば、どこからでもアクセスできる**のが大きな特長です。


## Webアプリとは？

「Webアプリ」とは、インターネットブラウザを通じて利用するアプリケーションのことです。  
パソコンに専用のソフトウェアをインストールする必要はなく、**Google ChromeやSafari、Edgeなどのブラウザ上で直接動作する**のがポイントです。

### Webアプリの具体例
:::note info
- **Gmail**：ブラウザ上でメールの送受信ができるGoogleのサービス
- **YouTube**：動画を視聴・投稿できるWebベースの動画共有アプリ
- **食べログ**：飲食店の検索や予約ができるグルメ情報サービス
- **Slack（Web版）**：ビジネスチャットをブラウザで操作可能なコミュニケーションツール
- **楽天市場（Web版）**：ECサイト
:::
これらはすべて、**ユーザーがブラウザからアクセスして利用するWebアプリケーション**です。


## クラウドとWebアプリの違いって？

「Webアプリもクラウドっぽいけど、何が違うの？」という声はよく聞かれます。  
混乱が起きやすいのは、**この2つが対立するものではなく、分類の軸が違う**からです。

:::note info
- **クラウド**：どこで動いているか（＝インフラや提供形態に関する分類）  
- **Webアプリ**：どう見えるか、どう操作するか（＝ユーザーインターフェースに関する分類）
:::

つまり、**クラウド上で提供されるWebアプリ**もあれば、**社内ネットワークだけで動くWebアプリ（非クラウド）** もあります。

> ✅ 多くのクラウドサービス（SaaS）はWebアプリ形式で提供されています  
> ❌ でもWebアプリだからといって、必ずしもクラウドサービスとは限りません


## 🎯 結論：クラウドは「仕組み」、Webアプリは「形」

- **クラウド = 提供の方法（どこで動いていて、どう使うか）**
- **Webアプリ = ユーザーインターフェースの形（どう見えるか、どう操作するか）**

つまり、  
> ✅ 「Webアプリ」はクラウドサービスの**一部の形態**であることが多い  
> ✅ でも「Webアプリ」だからといって、必ずしもクラウド上で動いているとは限らない

というわけなんです。
LINEグループの秘書ボット「タスキーちゃん🐙」

LINEグループの日常的な雑務をAIを使って完全に自動化できるチャットボット **🐙 タスキー(ちゃん)** を作りました（from the word "task"）。

## グループ内の雑務とは？
- カレンダーイベントの自動作成（Googleカレンダー）
- リマインダーの設定・自動送信
- 出欠管理（調整さん風に自動化）

## 構造化スキーマで完全自動化
例えば「明日の16時からミーティング」とLINEで入力  
AIが以下のようなJSONを生成します：

```json
{
  "title": "ミーティング",
  "dateTime": "2025-04-07T16:00:00",
  "duration": 60,
  "description": null
}
```

この構造化された出力を元にLambdaでイベントを作成し、自動でGoogleカレンダーのリンクをグループに返します。

## 実際の実装例（一部抜粋）
```
const schema = {
  type: "json_schema",
  json_schema: {
    name: "calendar_event_schema",
    schema: {
      type: "object",
      properties: {
        title: { type: "string" },
        dateTime: { type: "string" },
        duration: { type: "integer" },
        description: { type: ["string", "null"] },
      },
      required: ["title", "dateTime", "duration", "description"],
      additionalProperties: false
    },
    strict: true
  }
};
```

リマインダーも出欠管理もほぼ同じです。

## 見て頂く方が早いかもです：
![イベント作成の例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3456732/0956129a-f9bd-4c56-a9b0-e7f784680bce.jpeg)

![リマインダー設定の例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3456732/25c198e2-6e20-4cc3-af9b-6a51945beba2.jpeg)

![出欠管理の例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3456732/4da28c68-deba-4739-9e07-7a7ebd722d88.jpeg)

## 🐙 タスキー(ちゃん)の特徴

- @🐙 タスキーでメンションされたメッセージのみに反応
- @Allは無視
- 会話は保存・保管しない
- リマインダーと出欠管理の内容のみ一時保存
- 期限が切れたら自動削除
- 現在MVP段階




## 👇 LINEに追加して試す
ぜひお試し頂けると嬉しい限りです🙇
[LINEに追加](https://lin.ee/cThSiQ3)
Laravel×PHP×Vueで学ぶ！Webサイトの仕組みをざっくり図解＆解説【初心者向け】

# はじめに
LaravelやVue.jsを学んでいると、よく「Webアプリケーションの仕組みを理解しましょう」と言われますよね。

でも実際のところ…

- 「どこで何が動いてるの？」
- 「セッションとかCookieってどう関係してるの？」
- 「`web.php`、コントローラー、モデル、ビューってどうつながってるの？」

そんな疑問を持っている方向けに、この記事では **Laravel × PHP × MySQL × nginx × Vue.js** を使ったWebアプリの仕組みを **セッション・Cookie・HTTP・CDN** などのキーワードを交えつつ、図解で丁寧に解説します！

---

# ①使用技術スタックと役割

| 技術         | 役割 |
|--------------|------|
| **Laravel**  | Webアプリ全体の骨組み（MVC構成） |
| **PHP**      | サーバーサイド言語。Laravelの実行言語 |
| **MySQL**    | データベース。ユーザー情報などを保存 |
| **nginx**    | Webサーバー。HTTPリクエストをLaravelに渡す |
| **Vue.js**   | フロントエンドで動的な表示を担う |
| **CDN**      | 静的ファイル（画像・CSS・JS）を高速配信 |

---

# ②Webサイト全体の流れ（図解）

```plaintext
[ブラウザ]
   ↓ HTTPリクエスト（GET / POST など）
[CDN] ← 画像・CSS・JSはここで返される
   ↓（動的ページはnginxへ）
[nginx（Webサーバー）]
   ↓
[Laravelの public/index.php]
   ↓
[routes/web.php（ルーティング）]
   ↓
[Controller（処理ロジック）]
   ↓
[Model（DBアクセス）]
   ↓
[View（Blade or Vue.js）]
   ↓
[HTTPレスポンス]
   ↓
[ブラウザにHTML表示]
```

# ③Laravelの構成ファイルと役割
- **routes/web.php（ルーティング）**
URLとコントローラーの処理を結びつけます。
```php
Route::get('/users', [UserController::class, 'index']);
```

- **Controller（コントローラー）**
HTTPリクエストを受けて、処理・DB操作を行い、ビューを返します。
```php
class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = User::all();
        return view('users.index', compact('users'));
    }
}
```

- **Model（モデル）**
DBテーブルと連携する部分。Eloquent ORMを使用します。
```php
class User extends Model
{
    protected $fillable = ['name', 'email'];
}
```

-  **View（ビュー）: Bladeテンプレート or Vue.js**
HTMLの見た目部分。Bladeならサーバーで生成、Vueならフロントで動的表示。
```blade
<!-- resources/views/users/index.blade.php -->
<h1>ユーザー一覧</h1>
@foreach ($users as $user)
    <p>{{ $user->name }}</p>
@endforeach
```

# ④HTTP通信・セッション・Cookieの関係性
- **リクエスト（Request）**
ユーザーがサーバーに送る「お願い」。
URL、パラメータ、Cookie、ヘッダーなどを含みます。
```php
$request->input('email');
```
- **レスポンス（Response）**
サーバーから返す「お返し」。
HTMLやJSON、Cookie、ステータスコードなどが含まれます。
```php
return response()->json(['status' => 'OK']);
```
- **セッション（Session）**
ログイン状態など、サーバー側で一時的に保存する情報。
```php
session(['user_id' => $user->id]);
```
Laravelは、セッションIDをCookieに保存し、値はサーバー側で管理します。
- **Cookie**
ユーザーのブラウザに保存される小さなデータ。
セッションIDやログイン情報の記録などに使われます。
```php
setcookie('visited', 'true', time() + 3600);
```
# ⑤CDN（Content Delivery Network）とは？
画像やCSS・JSファイルなどを世界中のCDNサーバーから配信し、Webページの表示を高速化する仕組みです。
- **CDNを使ったVue.jsの読み込み例**
```html
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
```

# ⑥まとめ
Laravelを使ったWebアプリは、
	**1.	ブラウザからのHTTPリクエスト**
	**2.	nginxが受け取り、Laravelの**ルーティング（web.php）**へ**
	**3.	Controllerが処理、必要に応じてModelでDBアクセス**
	**4.	**View（BladeやVue.js）**で画面を作成**
	**5.	最後にHTTPレスポンスとしてブラウザへ返却**

という流れで動いています。

さらに、**セッションやCookie**がログイン状態を維持したり、**CDN**が表示速度を上げたりと、いろいろな仕組みが裏で支えています。
(PATH問題)VSCodeでPythonのパスを解決したプロジェクトを作る

# はじめに

vscodeで、以下のようなフォルダ構成のプロジェクトを作りたいなと思ったとき、例えば`tests/test_codes/`配下に配置するテストコードから`app`配下をimportして実行するようなテストコードを書こうとしても、`app`が見つからなくてimortできない、ということに陥る。

```text
-- project root/
 |-- app/     # ★テスト対象
 | |-- app.py
 | |-- ... (いろんなファイルやモジュール)
 | |-- ... (略)
 | `-- ... (略)
 |-- tests/   # テスト関連
 | |-- test_codes/      # テストスクリプト
 | | |-- ... (いろんなテストファイルやモジュール)
 | | |-- ... (略)
 | | `-- ... (略)
 | |-- test_utilities/  # ★テストを便利にするスクリプト用モジュール
 | | |-- ... (いろんなファイルやモジュール)
 | | |-- ... (略)
 | | `-- ... (略)
```

例えばPyCharmの場合では、Projectのパネルからappディレクトリを右クリックして「Mark Directory as > Sources Root」すればPYTHONPATHが通るので簡単なのだが、同じことをvscodeでも実現して、一つのプロジェクトとして操作しやすくするにはどうしたらいいか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126949/dc0ae772-5b40-45cf-be0b-fcb4a1da2ef0.png)

# 方針

`app`を参照したいプログラムでPython的に`sys.path.append()`を使ってパスを通すというのは、煩雑だし、不必要な依存関係を作ったりVSCode自体がこれを認識しない可能性がある（Ctrl-左クリックで当該スクリプトに飛べない可能性がある）のでナシの方向で。

`tests/`配下のスクリプトから`app/`にパスが通っている、ということには、自分の使い方の場合（Pluginには[ms-python.python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)を、ターミナルにはpwshを使用）、2パターンの問題を解決する必要があるようでした。

- VSCodeが`app/`をPYTHONPATHとして認識する
- ターミナル(pwsh)が`app/`をPYTHONPATHとして認識する

ということで、それぞれに対して設定をしていこうと思います。
また、どのパスをPYTHONPATHとして識別したいか？については、プロジェクトによるので、プロジェクトディレクトリ内で解決するようにできないかな、と考えています。

# 設定案

ちょっと調べたところ、以下の方法で行けた。もっと良い方法があればアドバイスいただけると嬉しいです。

## vscode向け設定： settings.jsonで`app`をソースディレクトリに設定

以下にsettings.jsonを作成。

```text
-- project root/
 |-- .vscode/
 | `-- settings.json  # 追加
 |-- app/
 | |-- app.py
 ```

以下を追記。
(`"${workspaceFolder}/app"`と書いたほうがいいかも。調べ中。)

```json:settings.json
{
    "python.analysis.extraPaths": [".", "./app"],
    "python.autoComplete.extraPaths": [".", "./app"]
}
```

## Terminal(pwsh)向け設定： PYTHONPATHを設定するスクリプトを作って力技で`app`をソースディレクトリに設定

以下のようなを作成。

```text
-- project root/
 |-- misc/
 | `-- setup.ps1  # 追加
 |-- app/
 | |-- app.py
 ```

内容は以下のような感じ。
(以下の例は`tests`ディレクトリも対象にしてます。Windows向けのセパレータです。)

 ```pwsh:setup.ps1
 $script_dir = Split-Path -Path $MyInvocation.MyCommand.Path -Parent
$project_root_dir = Resolve-Path -Path (Join-Path -Path $script_dir -ChildPath "..")

$app_dir = Join-Path -Path $project_root_dir -ChildPath "app"
$tests_dir = Join-Path -Path $project_root_dir -ChildPath "tests"
$env:PYTHONPATH="${project_root_dir};${app_dir};${tests_dir}"
 ```

## vscode向け設定：venvへパスを通す

どうしたらいいのか調べていないのだけど、`project root/`配下で`venv`という名前でvenvを作れば勝手にパスが通ってくれる。

## Terminal(pwsh)向け設定：venvへパスを通す

面倒だけど、`. venv\Scripts\activate.ps1`してる。
Hyprlandの設定ファイルでモニターの位置関係を調整する

## GUIでやる方法は知らん
最近Arch Linux + Hyprland + HyDEの環境を構築して楽しく遊んでいるのですが、
そこまで情報が沢山あるわけでも無さそうなので備忘録として残しておきます。
GUIでできる方法があればそっちのほうが便利だとは思いますが私は知りません。
エロい人誰か教えてください。
## ✅ ステップ1：モニターの名前を確認
とりあえず今使ってるモニター名を正確に確認します。
```bash: terminal
hyprctl monitors
```
出力例：
```bash: terminal
Monitor eDP-1 (enabled)
  ...
Monitor HDMI-A-1 (enabled)
  ...
```
この例では：
```
メイン：eDP-1（ノートPCの内蔵ディスプレイ）

サブ：HDMI-A-1（外付けディスプレイ）
```
## ✅ ステップ2：hyprland.conf に位置関係を設定
vimでもnanoで何でもいいので、~/.config/hypr/hyprland.conf に以下のようなセクションを追加または修正します：
```vim: hyprland.conf
monitor=HDMI-A-1,preferred,0x0,1
monitor=eDP-1,preferred,1920x0,1
```
ここでの意味：

* monitor=<モニター名>,<解像度 or preferred>,<XxY位置>,<スケール>

* HDMI-A-1（左）を (0x0) に

* eDP-1（右）を 1920x0 に → 解像度に合わせて右に配置（横1920ピクセル）
    
※ 解像度はご自身のモニターに合わせるようにしてください（例：2560なら 2560x0）。

## ✅ ステップ3：Hyprlandを再読み込み
設定を反映するには、Hyprlandを再起動 or 設定の再読み込みをします：
```bash:terminal
hyprctl reload
```
もしくはrebootでもいいですが、自分は変更内容を保存した瞬間に反映された気がします。。。
## 🎯 確認
hyprctl monitors で確認すると、位置が反映された状態になります。マウスカーソルを左右に動かしてモニター間を移動できればOK〜
VSCodeで仮想環境（venv）をJupyter Notebookのカーネルに追加する方法【macOS】

LangChainのチュートリアルを触るために VScode から Jupyter Notebook の設定をしていたところ、仮想環境がカーネルに表示されず詰まったので、手順をメモ。  

---

## 🧪 作業環境
- macOS（Apple Silicon）
- Python 3.9
- VSCode
- 仮想環境：`venv`（ディレクトリ名：`myenv`）
- Jupyter Notebook
- 使用ライブラリ例：LangChain

---

## 1. 仮想環境の作成とアクティベート

```bash
python3 -m venv myenv
source myenv/bin/activate
```

---

## 2. 必要なパッケージをインストール

仮想環境が有効になっている状態で以下を実行：

```bash
pip install ipykernel jupyter
```

他にも使いたいライブラリ（例：langchain）があればこのタイミングで入れてOK。

---

## 3. 仮想環境をJupyterのカーネルとして登録

```bash
python -m ipykernel install --user --name=myenv --display-name "Python (myenv)"
```
---

## 4. カーネルが登録されたか確認

```bash
jupyter kernelspec list
```

出力例：
```bash
Available kernels:
  myenv      /Users/*****/Library/Jupyter/kernels/myenv
  python3    /Users/*****/path/to/python3
```

---

5. VSCodeでカーネル選択

- .ipynb ファイルを開く
- 右上のカーネル選択メニューをクリック
- 「Python (myenv)」を選択！

---

## ❗️カーネルが表示されないときの対処法

仮想環境を登録したのに、VSCodeに出てこないことがあります。
その場合は、以下の順で試してみてください：

### ✅ 対処ステップ
- VSCodeを再起動
  → 一番手軽＆効果的。大抵これで直ります。
- VSCodeのPython拡張機能を確認
  → 「拡張機能」パネルで「Python」が有効かどうかチェック。
- コマンドパレットでインタプリタを選択
  Cmd + Shift + P を押してコマンドパレットを開く
  「Python: Select Interpreter」を選択 
  表示されたリストから myenv を選択！
- もしリストに出てこなければ、一番下の「Enter interpreter path」→「Find」を選び、/Users/*****/myenv/bin/python を指定。
  コマンドパレットで再読み込み
  Cmd + Shift + P で再びコマンドパレットを開く
  「Reload Window」を実行
- Jupyter Extensionの再インストール
- Python拡張と併せて「Jupyter」も一度削除→再インストール
  それでも出ないときは
- jupyter kernelspec list でパスが正しいか確認
  myenv の中に ipykernel がインストールされているかチェック

---

## ✅ 動作確認

以下のコードを実行して、仮想環境が正しく設定されているか確認します。

```bash
import sys
print(sys.executable)
```
仮想環境のパスが出れば成功です！🎉

---

## 🎁 おまけ：LangChainのインストール
```bash
pip install langchain
```
依存ライブラリも自動で入りますが、必要に応じて openai, dotenv, chromadb なども追加して使えます。

---

📝 まとめ

チュートリアル実行時にブラウザを使用したくなかったので、VScode上で動作するように環境を設定しました。
※この記事は生成AIを活用して作成したので、読みにくかったらすみません。
LLMの歴史を振り返ってみる


## 0. はじめに
会社業務でLLMをいじる機会がありそうなので、勉強と備忘録も兼ねて調べたことをまとめていきます。(情報の多くはchatGPTくんから仕入れたものですのであしからず)

## 1．導入
LLM（大規模言語モデル）は近年急速に進化しており、ChatGPTやGeminiなどの高度なAIが登場しています。しかし、そのルーツは統計的言語モデル（LM: Language Model）にまで遡ります。本記事では、LLMの歴史を初期の言語モデルから概観します。

---

## 2. 初期の言語モデル（1950〜1990年代）

### 2.1 統計的言語モデルとN-gram
最も初期の言語モデルは、統計的手法を用いたものです。単語やフレーズの出現確率を利用するN-gramモデルが代表的でした。

- **Claude Shannon (1948)**
  - *A Mathematical Theory of Communication*
  - → 言語の確率モデルの概念を示し、情報理論の基礎を築いた。
  - [論文リンク](https://ieeexplore.ieee.org/document/6773024)

- **Brown et al. (1992)**
  - *Class-Based n-gram Models of Natural Language*
  - → N-gramモデルの改良として、単語をクラスに分ける手法を提案。
  - [論文リンク](https://aclanthology.org/J92-4003.pdf)

### 2.2 隠れマルコフモデル（HMM）
N-gramモデルの発展として、隠れマルコフモデル（HMM）を用いた手法が登場しました。特に音声認識分野で広く用いられました。

- **Rabiner (1989)**
  - *A tutorial on hidden Markov models and selected applications in speech recognition*
  - → HMMを用いた言語モデル・音声認識の基礎を確立。
  - [論文リンク](https://ieeexplore.ieee.org/document/18626)

- **Jelinek (1990)**
  - *Self-organized language modeling for speech recognition*
  - → IBMの研究者が、HMMをベースとした言語モデルの自動学習を提案。
  - [論文リンク](https://aclanthology.org/H90-1052.pdf)

---

## 3. ニューラルネットワーク時代（2000年代〜2010年代）

2000年代に入り、ニューラルネットワークを活用した言語モデルが登場しました。

- **Bengio et al. (2003)**
  - *A Neural Probabilistic Language Model*
  - → 初めてニューラルネットワークを使った言語モデルを提案。
  - [論文リンク](https://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf)

この時期には、Word2Vec（2013）、Seq2Seq（2014）、Attention機構（2015）などの技術が登場し、最終的に**Transformer（2017）**が発表されました。

---

## 4. LLMの誕生と発展（2018年〜現在）

Transformerモデルを基盤にしたLLMが登場し、大規模なデータを学習することで驚異的な性能を発揮するようになりました。

- **2018年**：BERT（Google）登場。事前学習＋ファインチューニングの概念が確立。
- **2019年**：GPT-2（OpenAI）登場。生成AIの可能性を示す。
- **2020年**：GPT-3（OpenAI）登場。パラメータ数175BのLLM時代が本格化。
- **2022年**：ChatGPTリリース。実用的な対話AIが普及。
- **2023年〜現在**：GPT-4、Claude、Geminiなど、様々なLLMが登場。

---

## 5. 今後の展望
LLMは今後、以下の方向へ進化すると予測されます。

1. **マルチモーダル化**（テキスト＋画像＋音声＋動画）
2. **効率化**（少ない計算資源で高精度な推論）
3. **専門特化**（エンジニアリング分野などでの活用）

特に、**MBSE（モデルベースシステムエンジニアリング）** や **UAF（統一アーキテクチャフレームワーク）** などの分野でも、LLMの活用が期待されています。

---

## 6. まとめ
LLMは、統計的手法からニューラルネットワーク、Transformerを経て現在の大規模モデルへと発展してきました。  
今後もさらなる進化が期待されるため、最新技術をウォッチし続けることが重要です。

---

### 参考文献
- Shannon, C. (1948). *A Mathematical Theory of Communication*.
- Brown, P. F., et al. (1992). *Class-Based n-gram Models of Natural Language*.
- Rabiner, L. (1989). *A tutorial on hidden Markov models and selected applications in speech recognition*.
- Bengio, Y., et al. (2003). *A Neural Probabilistic Language Model*.
統計検定準1級・第４章の勉強したところをまとめた

# 1変数の変数変換による確率密度関数の導出
公式ワークブックとは違うが, 自分なりに理解した方法で説明する.

確率変数 $X$ の確率密度関数を $f_X(x)$, 累積分布関数を $F_X(x)$とする. 
このとき、$Y = g(X)$ と変数変換した確率変数 $Y$ の確率密度関数 $f_Y(y)$ を考える.

まず, 確率変数 $Y$ の累積分布関数を $F_Y(y)$ を求める.

```math
\begin{align*}
F_Y(y) &= P(Y \leq y) \\
       &= P(g(X) \leq y) \\
       &= P(X \leq g^{-1}(y)) \tag{1}
\end{align*}
```

次に, $Y$ の確率密度関数 $f_Y(y)$ は、$F_Y(y)$ を $y$ で微分することで求められるので, (1) を $y$ で微分する.

```math
\begin{align*}
f_Y(y) &= \frac{d}{dy} F_Y(y) \\
       &= \frac{d}{dy} P(X \leq g^{-1}(y)) \\
       &= \frac{d}{dy} \int_{-\infty}^{g^{-1}(y)} f_X(x)dx \\
       &= \frac{d}{dy} \left\{ F_X(g^{-1}(y)) - F_X(-\infty) \right\} \\ 
       &= f_X(g^{-1}(y)) \cdot \frac{d}{dy} g^{-1}(y)
\end{align*}
```
ただし, $F_X(-\infty) = 0$

よって確率密度関数 $f_Y(y)$ は, $g(x)$が単調減少である場合も考慮し, 絶対値をつけて以下の式で求まる.

```math
f_Y(y) = f_X(g^{-1}(y)) \cdot \left| \frac{d}{dy} g^{-1}(y) \right|
```

# 例題 4.1(3)で確認

$Y = e^X$ のとき、$Y$ の分布関数 $F_Y(y)$ は以下のように求まる.

```math
\begin{align*}
F_Y(y) &= P(Y \leq y) \\
       &= P(e^X \leq y) \\
       &= P(X \leq \log y) \\
       &= \int_{-\infty}^{\log y} f_X(x) \, dx \\
       &= F_X(\log y) - F_X(-\infty)
\end{align*}
```

よって $Y$ の確率密度関数 $f_Y(y)$ は,

```math
\begin{align*}
f_Y(y) &= \frac{d}{dy} \left\{ F_X(\log y) \right\} \\
       &= f_X(\log y) \cdot \frac {d} {dy} \log y \\
       &= f_X(\log y) \cdot \frac{1}{y} \tag{2}
\end{align*}
```

ここで, $X$ は以下のように $\mathcal{N}(\mu, \sigma^2)$ の正規分布に従うので, 

$$
f_X(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)
$$

この $x$ に $\log y$ を代入すると (2) は, 

```math
\begin{align*}
f_Y(y) &= f_X(\log y) \cdot \frac{1}{y}\\
&= \frac{1}{y \sqrt{2\pi\sigma^2}} \exp\left( -\frac{(\log y - \mu)^2}{2\sigma^2} \right)
\end{align*}
```

# データの変換

#### 対数変換
データが正規分布に従うようにする. 対数変換を行うと, 非負値のデータを $-\infty$ から $\infty$ の値を取るデータに変換できる.

$$
\log x
$$ 

#### べき乗変換
データが正規分布に従うようにする.

$$
x^a
$$ 

#### Box-Cox変換
対数変換とべき乗変換をひとまとめにした変換. パラメータ $\lambda$ に対し以下のように変換する. 

```math
\left \{
    \begin{array}{l}
    \frac {x^{\lambda}-1} {\lambda} & (\lambda \ne 0) \\
    \log x & (\lambda = 0)
    \end{array}
\right.
```
Box-Cox変換は非負のデータしか変換できない.

#### ロジット変換
確率 $p$ のような 0 から 1 の値しかとらないものを $-\infty$ から $\infty$ を取る値に変換する. 

$$
\log { \frac {p} {1-p} }
$$

#### プロビット変換
ロジット変換同様に, 0 から 1 の値しかとらないものを $-\infty$ から $\infty$ を取る値に変換する. 
標準正規分布の累積分布関数 $\Phi(x)$ の逆関数 $\Phi^{-1}$ によって変換.

$$
\Phi(x) = \int_{-\infty}^{x} \frac {1} {\sqrt {2\pi}} e^{-t^2/2} dt
$$
もっとモダンにcssを書いてみよう（where, is, has）

最近ではtailwindなどのcssフレームワークを使うことが多いのでcssを直書きする場面がどんどん減ってきています。

しかし、それでもUIライブラリーの中身を修正したりする時にはcssを書く必要が出てきますよね。
ということで、今回はもう少しモダンな書き方を３つ見ていきます！

## :where()
`:where()`は複数のセレクタをまとめるための擬似クラスで、詳細度に影響を与えません。
詳細度は他のcssよりどれだけ優先されるかを表すものです。以下の記事に詳しく書いてました！

https://qiita.com/ryokkkke/items/ec1ca2baebe4a984f7a6

``` css
main h1, main h2, main h3 {
  color: #ffffff;
}
```

``` css
main :where(h1, h2, h3) {
  color: #ffffff;
}
```

## :is()
`:is()`も複数のセレクタをまとめます。しかし、`:where()`と違ってグループ内の最も詳細度の高いセレクタの詳細度を継承します。もっと優先させることができると思っていただければ！

``` css
main h1, main h2, main h3 {
  color: #ffffff;
}
```

``` css
main :is(h1, h2, h3) {
  color: #ffffff;
}
```

## :has()
`:has()`は「〜を持つ要素」を選択する親セレクタです。JavaScriptでの判定がなくても子要素の状態に基づいて親要素を選択できます。

``` css
.parent.checked {
  background: lightgreen;
}
```

``` css
.parent:has(input:checked) {
  background: lightgreen;
}
```

## おわりに
こういう豆知識的なものが集まって生産性がどんどん上がっていくのでもっと勉強していきたいですね。
【PHP入門】クラスの基本とオブジェクト指向の考え方をわかりやすく整理してみた【Laravelにも活きる】

# はじめに

Laravelでは、コントローラーやモデルなど、ほとんどが「クラス」として定義されています。  
そのため、PHPの「クラス」の仕組みや、オブジェクト指向の考え方を理解することは非常に重要です。

この記事では、PHPのクラスについて基本から実務での使いどころまで、初心者向けに整理してみます。

---

# ①クラスとは？

クラスとは、**モノの設計図**のようなものです。  
「プロパティ（変数）」と「メソッド（関数）」をまとめたもので、**似たような処理を再利用・整理できる仕組み**です。

---

# ②クラスの基本構文

```php
class User {
    public $name;

    public function greet() {
        return "こんにちは、" . $this->name . "さん";
    }
}
```
**用語解説：**
- class → クラス定義
- public $name → プロパティ（データ）
- greet() → メソッド（処理）
- $this → このクラス自身を指す特別な変数

**インスタンス化（使うにはnewが必要）**
```php
$user = new User();      // クラスのインスタンスを生成
$user->name = "田中";    // プロパティに値をセット
echo $user->greet();     // メソッドを呼び出す
```
出力:
```plaintext
こんにちは、田中さん
```

# ②アクセス修飾子とは？
プロパティやメソッドの前についている public や private は**アクセス制御**を表します。

![スクリーンショット 2025-04-06 20.46.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/9598466e-0d81-48b3-8697-4dda32eff348.png)

**コンストラクタとは？**
クラスが生成されるときに最初に呼び出される特別なメソッドです。
```php
class User {
    public $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function greet() {
        return "こんにちは、" . $this->name . "さん";
    }
}

$user = new User("佐藤");
echo $user->greet(); // => こんにちは、佐藤さん
```

**Laravelでのクラス活用例（Controller）**
```php
class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();
        return view('posts.index', compact('posts'));
    }
}
```
この PostController もクラスです。
Laravelでは **「コントローラーも、モデルも、リクエストも」** すべてクラスで定義されています。

# ③クラスを使うメリット
![スクリーンショット 2025-04-06 20.50.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/d109c315-86fe-433e-b2a8-2f9896ca3a77.png)

# ④まとめ
![スクリーンショット 2025-04-06 20.51.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/84220fc0-3001-4c90-bd3b-63369f13fc5c.png)
Laravelの理解を深めるためにも、PHPのクラスの基本をしっかり押さえておきましょう！
個人サイトをWordPressからAstro & CloudFlarePagesに移行した

# サイト移行完了
ずっと放置していたサイトリニューアル作業に着手し、ひとまず形として世に出せるところまで来たので公開しました。

https://yuumekou.net/

技術的にはWordPressからAstro & CloudFlarePagesに移行しました。

元々はMarkdownで管理していたデータをWordPress用にカスタマイズして公開していたので、そのカスタマイズ作業がなくなる分、ずっと管理がしやすくなります。デザインや機能も凝ろうと思えば自分で追加できるし。

まだ細かい作業（アイコンとか）が残っているのでブラッシュアップは必要ですが、ひとまず公開まで漕ぎ着けることができてよかったです。

# Astroに移行しようと思った理由
最初に公開していたサイトはHTML・CSS・JavaScriptで構築していた超原始的なものでした。

さすがにその状態での管理は地獄だったので、流行りのWordPressに乗っかり、初回リニューアルを実施。

WordPressは色々リッチな機能も組み込みやすくて便利ではありました。が、固有の書き方や手作業が必要になるため、元ネタを書き溜めるのに使っていたMarkdownそのままでは記事に出来ないのが徐々に負担に……。

また、カスタマイズにも限界があるというか、やろうと思えば色々出来はするのですが、構造を意識してカスタマイズをかける必要があるというのがこれまた面倒に。

何か良い手立てはないものかと考えていた頃、知人がHugoでサイト構築を行なっていることを知り、静的サイトジェネレータなるものを知ってほほーんと。

https://gohugo.io/

これはなかなかええんじゃなかろうかと思っていたところ、出始めだったAstroに出会ったという形です。

https://astro.build/

ブログ的なサイト運用を考えると動的な振る舞いはまずないだろうし、ちょうど学習していたReactと同じような構文で書けるという点も気に入り、Astroによる第二次サイトリニューアルを決めたという感じです。

# 気づいたらAstroが色々便利になっていた
少しだけ当時Astroを触っていたのですが、転職活動などもあってそのまま放置状態に。

一ヶ月前に重い腰を上げて再度Astroを覗いてみたところ、当時と比べるとめちゃくちゃパワーアップしていましたね。まだその頃はテーマストアとかなかった気がするのですが、充実したラインナップぶり。

https://astro.build/themes/1/

今回はその中でFuwariというテーマを活用させてもらうことにしました。

https://github.com/saicaca/fuwari

# Astroのカスタマイズ容易性
最初こそ色々戸惑いましたが、ドキュメントがしっかりしていたので比較的スムーズに飲み込めるようになりました。

ルーティングやページ構成、記事の順番制御などを改造して、元サイトからコンテンツを取り込みつつ、全体的な見直しをかけたのが現在の状態です。

WordPressではデフォルトで使えたマーカー機能は存在しませんでしたが、そこもCopilotと相談しながら自作プラグインで解決できたので、やっぱり最後は自力で何とかできるのってとてもいいなと思いました。

# CloudFlarePagesの快適さ
色々調べている中で、GitHubPagesかCloudFlarePagesの選択肢が残ったのですが、元々広告設定をしていてそこも引き継ぎたかったので、広告NGなGitHubPagesを避けてCloudFlarePagesを選択。

結果として、CloudFlarePagesはドメイン移行もサイト構築もめちゃくちゃスムーズでかなり気持ち良かったです。デフォルトで自動デプロイ対応もありがたいですね。

# 何はともあれ
どうせ記事投稿するならリニューアルしてから、なんて思っているうちに完全に放置状態になってしまっていたので、ひとまずサイトリニューアルできて良かったです。

技術的にも良い経験でした。

Thank you Astro & CloudFlarePages!!
Rails + HTTPartyでOpenAI APIを使ってみた

# はじめに

最近、ChatGPTをはじめとする生成AIが話題ですが、OpenAIが提供するAPIを使えば、自分のアプリにも自然言語生成を簡単に組み込むことができます。

この記事では、**RailsアプリからHTTPartyを使ってOpenAIのChat API（GPT-4）を呼び出す方法**を紹介します。

## 対象読者

- OpenAI APIをRailsで使いたい人  
- ChatGPTの力をアプリに組み込みたい人

###  Step1: OpenAI APIキーの取得と管理

まずは、OpenAIの公式サイトからAPIキーを取得します。

- [OpenAI APIキー取得ページ](https://platform.openai.com/account/api-keys)

取得したAPIキーは、セキュリティ上 `.env` などで安全に管理しましょう。または、creadentilas.yml.encに保存しましょう。

```bash
# .env
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## Step2: HTTPartyのインストール

OpenAI APIをHTTP経由で叩くために `httparty` を使います。

```ruby
# Gemfile
gem 'httparty'
```

```bash
$ bundle install
```

## Step3: OpenAIクライアントクラスの作成
Railsのサービスクラスとして、OpenAIと会話するためのクラスを作成します。

```ruby
# app/services/openai_service.rb

require 'httparty'

class OpenaiService
  include HTTParty
  base_uri 'https://api.openai.com/v1'

  def initialize
    @headers = {
      "Authorization" => "Bearer #{ENV['OPENAI_API_KEY']}",
      "Content-Type" => "application/json"
    }
  end

  def chat(prompt)
    body = {
      model: "gpt-4",
      messages: [
        { role: "user", content: prompt }
      ],
      temperature: 0.7
    }

    response = self.class.post(
      "/chat/completions",
      headers: @headers,
      body: body.to_json
    )

    if response.success?
      response.parsed_response["choices"][0]["message"]["content"]
    else
      "エラー: #{response.code} - #{response.body}"
    end
  end
end
```

## Step4: 実際に使ってみる
ターミナルまたはコントローラから呼び出して確認してみます。
```ruby
service = OpenaiService.new
puts service.chat("GPT-4について簡単に説明してください。")
```

## まとめ
今回は、RailsアプリからHTTPartyを使ってOpenAIのChat API（GPT-4）を呼び出す方法を紹介しました。

- OpenAIのAPIキーは `.env` や `credentials.yml.enc` で安全に管理
- HTTPartyを使えば、シンプルなHTTP通信でChatGPTのような応答が実現可能
- `temperature` パラメータで応答の創造性をコントロールできる
- `role: system` を使えば、GPTの性格や専門性を自在に設定できる

OpenAI APIを使うことで、自分のアプリに自然な対話・分析・文章生成機能を簡単に組み込めます。
【PHP初心者向け】配列・連想配列・多次元配列の違いと使い方を丁寧に解説【Laravelでもよく出ます】

# はじめに

LaravelやPHPで開発していると、「配列」「連想配列」「多次元配列」といった言葉が頻繁に出てきます。  
しかし、それぞれの違いや使い方をきちんと説明するのは意外と難しいものです。

この記事では、配列の基本から、連想配列・多次元配列までを初心者向けにわかりやすく整理します。  
Laravelでの活用シーンにも軽く触れます。

---

# ①配列とは？

配列（array）は、**複数の値を1つの変数にまとめて扱う仕組み**です。

## 通常の（インデックス）配列

```php
$fruits = ['apple', 'banana', 'orange'];
```
**特徴:**
- インデックス(番号)で管理される
- インデックス**0から始まる**

**要素の取り出し:**

```php
echo $fruits[0]; // apple
echo $fruits[1]; // banana
```
# ②連想配列とは？
連想配列（associative array）は、**文字列のキーを使って値を管理する配列**です。

```php
$user = [
    'name' => '田中',
    'age' => 28,
    'email' => 'tanaka@example.com'
];
```
**要素の取り出し：**
```php
echo $user['name'];  // 田中
echo $user['email']; // tanaka@example.com
```

**特徴:**
- 配列のキーを**自由に定義できる**
- Laravelでは、**Bladeに変数を渡す時などによく使われる**

# ③多次元連想配列とは？
多次元配列とは、**配列の中に配列が入っている構造**のことです。
特に Laravel のようなフレームワークでは、リレーションデータや複数件のデータを扱う場面で頻繁に登場します。

**1.インデックス配列 × 連想配列**
```php
$users = [
    ['name' => '田中', 'age' => 28],
    ['name' => '佐藤', 'age' => 35],
    ['name' => '鈴木', 'age' => 22],
];
```
```php
echo $users[1]['name']; // 佐藤
```
**2.ネストされた連想配列**
```php
$product = [
    'name' => 'ノートパソコン',
    'specs' => [
        'cpu' => 'Intel i7',
        'memory' => '16GB',
        'storage' => '512GB SSD'
    ]
];
```
```php
echo $product['specs']['cpu']; // Intel i7
```

# ④配列の主な操作まとめ
![スクリーンショット 2025-04-06 20.30.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/c330e65a-310e-423d-8b82-c360b025e70b.png)

# ⑤Laravelでの使用例（Blade編）
Bladeテンプレートでの多次元配列のループ処理例：
```blade
@foreach ($users as $user)
    <p>{{ $user['name'] }}（{{ $user['age'] }}歳）</p>
@endforeach
```

# ⑥まとめ

![スクリーンショット 2025-04-06 20.34.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/5110248d-b00f-41ee-a6c6-8c8699713f3f.png)
配列の構造を理解しておくことで、Laravelのデータ操作やビューへの出力もスムーズになります！
🚀 MacにFlutterを使ったiOS開発環境をセットアップ

FlutterでiOSアプリを開発するための、Mac環境でのセットアップ手順を簡単にまとめました。

# 公式ドキュメント

このページを見ながら取り組みました。

https://docs.flutter.dev/get-started/install/macos/mobile-ios

公式ドキュメントはとても大事。基本的にはこちらに従うのが安心です。

# Rosetta 2 のインストール

Apple Silicon Mac の場合、一部Flutterのコンポーネントに Rosetta 2 が必要です。

**インストール確認コマンド：**

```bash
test -f /Library/Apple/usr/share/rosetta/rosetta && echo "Installed" || echo "Not installed"
```

**未インストールの場合：**

```bash
sudo softwareupdate --install-rosetta --agree-to-license
```
# Xcode のインストールとセットアップ

FlutterでiOSアプリをビルドするにはXcodeが必須です。

**Xcodeのバージョン確認：**

```bash
xcodebuild -version
```

**初期セットアップ：**

```bash
sudo sh -c 'xcode-select -s /Applications/Xcode.app/Contents/Developer && xcodebuild -runFirstLaunch'
```

**ライセンスへの同意：**

```bash
sudo xcodebuild -license
```

# CocoaPods のインストール

FlutterではCocoaPodsも必要になります。

[CocoaPods の導入手順（Qiita）](https://qiita.com/nobumory/items/3b3c5039088fa7869c61)

# VS Codeの拡張機能インストール

Flutter開発用の拡張機能をインストールしましょう。

[Flutter 拡張機能（VS Code）](https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter)


# Flutter SDK のインストール

### ダウンロードと解凍

Flutter公式サイトからmacOSに合ったSDKをダウンロードし、解凍します。

```bash
unzip ~/Downloads/flutter_macos_arm64_3.29.2-stable.zip -d ~/development/tools/
```

### パスの設定

```bash
vi ~/.zshenv
```

追記：

```bash
export PATH=$HOME/development/tools/flutter/bin:$PATH
```

設定を反映：

```bash
exec $SHELL -l
```

# 環境チェック

最後に `flutter doctor` を実行して、環境が整っているか確認します。

```bash
flutter doctor
```

✅ が並んでいれば準備OKです。

❌ が出たら、エラー内容を読んで対応してみましょう。

これでFlutterの準備は完了です。
次は `flutter create` でプロジェクトを作って動かしてみましょう！
Swift のマクロ機能で作る、ディープリンク enum 自動生成ツール「URLPattern」

### 概要
URLディープリンクは、現在ほとんどのサービスで広く使用されている基本的な技術です。しかし、Swift環境でディープリンクを実装するには、通常、URLパスの直接操作や正規表現の使用が必要になります。

```swift
// 従来の手法：手動でURLを処理
let paths = url.pathComponents

if paths.count == 2 && paths[1] == "home" {
  // ホームを処理
} else let match = try? url.path.firstMatch(of: /\/posts\/([^\/]+)$/) {
  // 投稿を処理
}
```

このような方法では、コードの可読性や拡張性が低下し、特に不正なパターンをコンパイル時に検出することができません。

`URLPattern` はこれらの問題を解決し、コンパイル時のURL検証と値のマッピングを提供します：

```swift
@URLPattern
enum DeepLink {
  @URLPath("/home")
  case home

  @URLPath("/posts/{postId}")
  case post(postId: String)

  @URLPath("/posts/{postId}/comments/{commentId}")
  case postComment(postId: String, commentId: String)
}
```

### 主な特徴
✅ URLパターンをコンパイル時に検証
🔍 URLパラメータと列挙型ケースの正しいマッピングを保証
🛠️ String、Int、Float、Double のパラメータ型に対応

GitHubでチェック：[URLPattern](https://github.com/heoblitz/URLPattern)
シェルの基本概念をまとめる

# 概要
半年以上前、高専の講義にてUNIXに関する内容を教わった。その講義を担当して頂いた教諭が非常に分かりやすい説明であったため、現在でもUNIXへの得意意識がついていると思う。しかし、コマンドの種類やシェル変数の引用方法など、時間が経てば忘れてしまう。そのため、今回シェルの基本的な動作についてこの記事にまとめようと思う。
**あくまで本人の確認用で作成した記事であるため、拙い文章になっています。ご理解のほどお願いします。**


## 目次
- シェルの根幹




# シェルの根幹
- 外部、内部コマンド
- パス
- リダイレクション
- パターンマッチ
- パーミッション
- コマンド置換
- エイリアス
- プロンプト


### 外部、内部コマンド
内部コマンド(シェルビルトインコマンド)は、shellの内部にあるコマンド。組み込みされているため、処理速度が早い。

外部コマンドは、shellの外部にあるコマンド実行ファイル。**binファイル**内にコマンドが存在する。
```shell:zsh
$ /bin #binディレクトリ
```

### パス
#### 絶対パス
ルートディレクトリからカレントディレクトリまでのパス。
`/usr/you/desktop/hoge`

#### 相対パス
ホームディレクトリやカレントディレクトリなど、相対的に見たパス。
`~/desktop/puge`

### リダイレクション
Linuxにおける入力出力のようなもの。

標準入力　キーボード　>
標準出力　画面　< もしくは >>
標準エラー出力　2>

```shell:zsh
$ cat < aaa.txt #標準出力
a
$ cat > aaa.txt #標準入力
b                #終了Ctrl d
$ cat < aaa.txt #標準出力
b
```
#### パイプ
複数のコマンドを繋げる物
リダイレクションも適用可能
```shell:zsh
$ ls
aaa aab abb bba baa cba abc
$ ls | grep a
aaa aab abb abc
```
### パターンマッチ
文字列を引用する際の簡易省略法
`*`　任意の文字列
`?`　任意の文字
`[]`　いずれかの文字
`[!]`　いずれか以外の文字


### パーミッション
アクセス権を示す

```shell:zsh
$ ls -l
#ファイルタイプ　アクセス権　
-rw-r--r--@  1 you  staff       0  3 31 22:34 uuu
drwxr-xr-x@ 12 you  staff     384  2 16 20:01 hoge
drwxr-xr-x@  8 you  staff     256 11 18 09:20 puge
drwxr-xr-x@ 10 you  staff     320  1  6 08:43 foo

```

- `r`　は4
- `w`　は2
- `x`　は1

ファイルタイプ
- `-`　通常ファイル
- `d`　ディレクトリ
- `l`　シンボリックリンク
- `s`　ソケット

### コマンド置換


` `` `　か　`$()`　を使用する。

###　エイリアス
コマンドの簡易化を行える。シェルスクリプトほどの応用は効かないが、設定していて損はないと思う。
ホームディレクトリ直下の`.zshrc`に設定する。

::: note info
bashの場合は`.bashrc`
:::

```shell:zsh
$ alias cdd="cd /Users/you/desktop"
#デスクトップ移動を簡易化
```

### プロンプト
シェルの先端部分。
```shell:zsh
$ expart PS1="%K{black}%F{white}[%D]%k %F{black}%n %2d %% "
#私のプロンプト設定。
#[25-04-06] you /Users/you % 
```


# 終わりに
現状、シェルの基本的概念まで記載した。逐次、そのほかの内容も記載していこうと思う。
もし、本記事の内容に誤り等がございましたら、コメントの方お願いします。
MonoGameでフォントファイルを暗号化する

## 1. 作成に至った動機
MonoGame上でFreeTypeを使ってフォントの描画が可能になりました。
しかし、フォントファイルをそのまま同梱することを許可しているフォントは少ない。
それでも、ファイルの暗号化をしていればOKだったりする場合もあります。
そんな条件まれですが、どうしてもフォントを使いたかったので作ってみました。

## 2. 目標
MonoGameのコンテンツマネージャ(MGCB Editor)経由で暗号化したファイルを取得する。
あと、ついでにファイルの圧縮/展開も自動で行う。

## 3. 開発環境
　Microsoft Visual Studio Community 2022
　　.NET 6.0/8.0 C#
　FreeTypeSharp 3.0.0
　SimpleFreeTypeSharp (https://qiita.com/fumifumi0453/items/3ccf9be78b5f456af143)

## 4. 参考にしたサイト
　Aristurtle - MonoGame Content Pipeline Extension
　　-(https://aristurtle.net/tutorials/content-pipeline-extension/01_introduction.html)

## 5. プロジェクト作成の注意点
今回作成するものはMonoGame本体ではなくツールなので、アプリケーションプロジェクトではなく、ライブラリのプロジェクトを選択します。
今回作成するのはカスタムパイプラインなので、専用プロジェクトの「MonoGame Custom Pipeline Extension」を選択します。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741278/8ebff631-1d43-495b-9726-8abbd215c1b8.png)

## 5.ソース
https://github.com/fumifumi0453/CustomPipeline/tree/master

## 6.解説
#### CustomPipelineプロジェクト
　メインプロジェクト。
　今回作成したものはすべてここに収まっている。
　MGCB EditorとMonoGameExampleで参照している。
##### ・BinaryImporterクラス
　MGCB Editorで選択するImporter
　機能としては、リソースファイルのデータを読み込む
##### ・BinaryProcessorクラス
　MGCB Editorで選択するProcessor
　機能としては、画面上でパラメータを指定しContentWriterに渡す
##### ・BinaryContentクラス
　Processpr-ContentWriter間の受け渡しデータフォーマット
　設計ミスにより、Content.Loadで取得するデータフォーマットにもなっている。
　おそらく分けた方が良い
##### ・BinaryContentWriterクラス
　実際にコンテンツデータを書き込むContentTypeWriter
##### ・BinaryContentReaderクラス
　実際にコンテンツデータを読み込むContentTypeReader
##### ・KanjiByteConverterクラス
　コンテンツデータの変換/暗号化/復号化を行っているクラス
　暗号はシーザー暗号を使用。

#### ExampleAppプロジェクト
　テスト用実行プロジェクト

### 7.実行結果
・MGCB Editor実行前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741278/adc5cf3f-3754-45fe-922d-35987ec5daa9.png)

・MGBC Editor実行後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741278/3edcb89c-2345-460d-a367-816523631455.png)
ファイル内容
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741278/f5f89361-d8ef-4b0c-aeb1-017efa39339a.png)
しっかり意味わからんデータになってますね。

ExampleApp実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3741278/62f8b557-f6ad-474c-abf2-f459240b0b63.png)

### 8.終わりに
作り終わった後に気づいてしまったのですが、ContentWriterはバイナリデータを直接書き出せたみたいでした。
文字列出力しかサポートしていないと思ってた私バカじゃん(泣)
アクセシブルなユーザーインターフェースの構築：すべての人にオンラインの力を

![Screenshot 2025-04-06 at 8.21.08 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3975900/dc4c81af-196f-4920-ab31-7d330f8bb3eb.png)


デジタル時代において、インターネットは私たちの日常生活に欠かせない存在になりました。買い物や教育、エンターテインメントやコミュニケーションまで、ウェブは世界との関わり方を大きく変えました。

しかし、すべての人が同じようにオンラインを体験しているわけではありません。視覚、聴覚、認知、運動能力に障害を持つ人々は、さまざまな困難に直面しています。だからこそ、障害の有無にかかわらず、誰もが平等にオンラインの恩恵を受けられるよう、アクセシブルなユーザーインターフェース（UI）の構築が必要です。

デジタル製品やウェブサイトを設計する際には、アクセシビリティを優先することが重要です。アクセシブルなUIは、障害を持つ人々が支援技術を使ってコンテンツに触れ、インターフェースを操作し、タスクを効率的に行えるよう障壁を取り除きます。さらに、アクセシブルなデザインは障害者だけでなく、すべてのユーザーにとって使いやすさを向上させ、全体的なユーザー体験を向上させます。

本記事では、開発者が知っておくべきアクセシビリティの基本的な側面を紹介します。ウェブアクセシビリティ（a11y）の重要性、ARIA（Accessible Rich Internet Applications）の役割、さらにReact Ariaライブラリを活用したアクセシブルなUIコンポーネントの作り方について解説します。

# Webアクセシビリティ（a11y）とは？

Webアクセシビリティ（a11y）は、「アクセシビリティ（accessibility）」の略称で、障害の有無にかかわらず、誰もが使えるウェブサイトを設計・構築する取り組みです。スクリーンリーダーや音声認識ソフトウェアなどの支援技術がウェブページを正しく解釈し、障害者に有意義な体験を提供できるようにします。

アクセシビリティを確保するためには、WAI（Web Accessibility Initiative）が定めるガイドラインを遵守することが推奨されます。これらのガイドラインは「認知可能」「操作可能」「理解可能」「堅牢性（Robust）」の4つの原則（POUR）に基づいており、開発者がアクセシブルな製品を簡単に作れるようサポートしています。

# 様々な困難への対応

デジタル製品の利用時に直面する一般的な課題と、それを解決するアクセシブルデザインについて説明します。

* 視覚障害：スクリーンリーダーがコンテンツを読み取れるように、HTMLのセマンティック構造を正しく設定し、画像に代替テキストを提供します。

* 聴覚障害：音声や映像コンテンツには字幕やトランスクリプトを提供し、情報へのアクセスを保証します。

* 認知障害：シンプルで一貫性があり、予測可能なインターフェース設計が求められます。

* 運動障害：キーボード操作を可能にし、音声コマンドや代替入力デバイスを利用するユーザーがUIと円滑にインタラクトできるようにします。

# ARIAでアクセシビリティを向上させる

ARIA（Accessible Rich Internet Applications）は、UIの見た目を変えずにアクセシビリティを高めるHTML拡張標準です。ARIAには「ロール（役割）」「ステート（状態）」「プロパティ（属性）」という主要な要素があります。

* ARIAロール：要素の役割を定義します。
```
<div role="button" tabindex="0" onclick="handleButtonClick()">
  Click Me
</div>
```

* ARIAステート：要素の現在の状態を伝えます。
```
<button aria-expanded="false" aria-controls="expandable-content" onclick="toggleExpandableContent()">
  Toggle Content
</button>
<div id="expandable-content" aria-hidden="true">
  <!-- Content goes here -->
</div>
```

* ARIAプロパティ：要素の補足情報を提供します。
```
<button aria-label="Search" onclick="performSearch()">
  <img src="search-icon.png" alt="Search Icon">
</button>
```

# React AriaでReactのアクセシブルなUIを構築

React Ariaは、React Hooksを提供する強力なライブラリであり、アクセシブルなUIコンポーネントを簡単に構築できます。

インストール方法：
```
npm install @react-aria/utils
```

React Ariaを使ったボタンの作成例：
```
import { useButton } from '@react-aria/button';

function AccessibleButton({ onClick, label }) {
  const { buttonProps } = useButton({ onPress: onClick });

  return (
    <button {...buttonProps}>
      {label}
    </button>
  );
}
```

# まとめ

アクセシブルなUIの構築は、すべてのユーザーに包括的なオンライン環境を提供するために重要です。Webアクセシビリティガイドラインを守り、ARIA標準を採用し、React Ariaなどのツールを活用することで、すべてのユーザーが障壁なくオンラインを楽しめるようになります。

# 参考リソース
1. Web Accessibility Initiative (WAI): https://www.w3.org/WAI/policies/
2. Web Content Accessibility Guidelines (WCAG): https://www.w3.org/TR/WCAG21/
3. React Aria: https://react-spectrum.adobe.com/react-aria/getting-started.html
4. ARIA Roles, States, and Properties: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA