# 機能設計書 141-median

## 概要

本ドキュメントは、Hack Standard Library (HSL) の `Math\median` 関数の機能設計を定義する。数値コレクションの中央値を計算する関数である。

### 本機能の処理概要

**業務上の目的・背景**：統計分析やデータ処理において、データセットの中央値を求めることは基本的かつ重要な操作である。平均値と異なり、中央値は外れ値の影響を受けにくいため、データの代表値として広く利用される。本機能は、数値コレクションに対して効率的に中央値を計算する手段を提供する。

**機能の利用シーン**：データ分析、統計計算、レポート生成、データの品質評価などの場面で利用される。例えば、ユーザーの応答時間の中央値を計算してパフォーマンス指標とする場合などに使用される。

**主要な処理内容**：
1. 入力された数値コレクションをソートする
2. コレクションの要素数を取得する
3. 要素数が0の場合はnullを返す
4. 要素数が奇数の場合、中央の値を返す
5. 要素数が偶数の場合、中央2つの値の平均を返す

**関連システム・外部連携**：外部システムとの連携はない。純粋な計算処理関数である。

**権限による制御**：権限による制御は存在しない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | 本プロジェクトはUIを持たないライブラリ |

## 機能種別

計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $numbers | Container<num> | Yes | 中央値を計算する数値コレクション | 型による静的チェックのみ |

### 入力データソース

関数呼び出し時の引数（数値を含むContainer型のコレクション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | ?float | 中央値（空のコレクションの場合はnull） |

### 出力先

関数の戻り値として返却

## 処理フロー

### 処理シーケンス

```
1. 入力コレクションをソート
   └─ Vec\sort()を使用して昇順にソート
2. 要素数を取得
   └─ C\count()を使用
3. 要素数が0か判定
   └─ 0の場合はnullを返却
4. 中央インデックスを計算
   └─ Math\int_div($count, 2)
5. 要素数の偶奇判定
   └─ $count % 2 === 0 で偶数判定
6. 偶数の場合
   └─ 中央2要素の平均をMath\mean()で計算
7. 奇数の場合
   └─ 中央の要素を直接返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[数値コレクションをソート]
    B --> C[要素数を取得]
    C --> D{要素数 = 0?}
    D -->|Yes| E[null を返却]
    D -->|No| F[中央インデックスを計算]
    F --> G{要素数は偶数?}
    G -->|Yes| H[中央2要素の平均を計算]
    G -->|No| I[中央要素を float に変換]
    H --> J[結果を返却]
    I --> J
    E --> K[終了]
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-141-1 | 空コレクション | 空のコレクションに対してはnullを返す | 要素数が0の場合 |
| BR-141-2 | 奇数要素 | 中央の1要素をfloatに変換して返す | 要素数が奇数の場合 |
| BR-141-3 | 偶数要素 | 中央2要素の算術平均を返す | 要素数が偶数の場合 |

### 計算ロジック

- 中央インデックス: `$middle_index = Math\int_div($count, 2)`
- 偶数の場合の中央値: `Math\mean(vec[$numbers[$middle_index], $numbers[$middle_index - 1]])`
- 奇数の場合の中央値: `(float)$numbers[$middle_index]`

## データベース操作仕様

該当なし（データベース操作を行わない純粋関数）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 型エラー | 非数値型の要素が含まれる場合 | 静的型チェックにより防止 |

### リトライ仕様

該当なし

## トランザクション仕様

該当なし（データベース操作を行わない）

## パフォーマンス要件

- 時間計算量: O(n log n) - ソート処理が支配的
- 空間計算量: O(n) - ソート用の一時配列

## セキュリティ考慮事項

- 純粋関数であり、副作用がないため特別なセキュリティ考慮は不要
- `[]`: 純粋コンテキストで実行可能

## 備考

- `Math\mean()`との違い：meanは算術平均、medianは中央値を計算
- ソート処理を内部で行うため、大量データの場合はパフォーマンスに注意

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

本関数はシンプルな数値コレクション（Container<num>）を受け取り、floatまたはnullを返す。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | containers.php | `src/math/containers.php` | Container<num>型の入力、?float型の出力を確認 |

**読解のコツ**: Hackの`num`型は`int`または`float`の共用型。`Container`は`vec`、`dict`、`keyset`などの具象型を抽象化する型。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | containers.php | `src/math/containers.php` | median関数の定義（82-95行目） |

**主要処理フロー**:
1. **83行目**: `Vec\sort($numbers)` で数値をソート
2. **84行目**: `C\count($numbers)` で要素数を取得
3. **85-86行目**: 空コレクションの場合はnullを返却
4. **88行目**: `Math\int_div($count, 2)` で中央インデックスを計算
5. **89-92行目**: 偶数の場合、中央2要素の平均を計算
6. **94行目**: 奇数の場合、中央要素をfloatに変換して返却

#### Step 3: 依存関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | order.php | `src/vec/order.php` | Vec\sort関数（91-102行目）のソート処理 |
| 3-2 | introspect.php | `src/c/introspect.php` | C\count関数（89-93行目）の要素数取得 |
| 3-3 | compute.php | `src/math/compute.php` | Math\int_div関数（191-196行目）の整数除算 |
| 3-4 | containers.php | `src/math/containers.php` | Math\mean関数（65-75行目）の平均計算 |

**主要処理フロー**:
- **Vec\sort**: Traversableを受け取り、ソート済みvecを返す
- **C\count**: Containerの要素数をO(1)で取得
- **Math\int_div**: 整数除算（切り捨て）を実行
- **Math\mean**: 算術平均を計算

### プログラム呼び出し階層図

```
Math\median($numbers)
    |
    +-- Vec\sort($numbers)
    |       └─ PHPの\sort()または\usort()を使用
    |
    +-- C\count($numbers)
    |       └─ PHPの\count()を使用
    |
    +-- Math\int_div($count, 2)
    |       └─ PHPの\intdiv()を使用
    |
    +-- Math\mean(vec[...])  [偶数の場合のみ]
            └─ C\count() + ループで平均計算
```

### データフロー図

```
[入力]                   [処理]                      [出力]

Container<num> ───> Vec\sort ───> ソート済みvec
                        │
                        v
                    C\count ───> 要素数($count)
                        │
                        v
                    分岐判定
                    /      \
            偶数 /          \ 奇数
               v              v
          Math\mean        float変換
               \            /
                v          v
                ?float ────────> 戻り値
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| containers.php | `src/math/containers.php` | ソース | median関数の定義、mean関数の定義 |
| order.php | `src/vec/order.php` | ソース | Vec\sort関数（ソート処理） |
| introspect.php | `src/c/introspect.php` | ソース | C\count関数（要素数取得） |
| compute.php | `src/math/compute.php` | ソース | Math\int_div関数（整数除算） |
| MathContainersTest.php | `tests/math/MathContainersTest.php` | テスト | median関数のテストケース |
