# 機能設計書 64-Vec\sample

## 概要

本ドキュメントは、Hack Standard Library（HSL）の`Vec\sample`関数の機能設計を記載する。この関数は、Traversableから指定されたサイズの非偏りランダムサンプルを抽出し、新しいvecとして返す。

### 本機能の処理概要

**業務上の目的・背景**：
データ分析、テスト、抽選処理などにおいて、大量のデータからランダムにサンプルを抽出する必要がある場面は多い。例えば、A/Bテストのユーザー割り当て、品質検査のサンプル抽出、アンケート対象者の無作為抽出などに使用される。この関数は、統計的に偏りのないランダムサンプリングを実現する。

**機能の利用シーン**：
- ユーザーデータからのランダムサンプル抽出
- テストデータの生成
- 抽選・くじ引きの実装
- 機械学習の訓練/検証データ分割
- ランダムな推薦アイテムの選択

**主要な処理内容**：
1. 入力Traversableをシャッフル（Vec\shuffle使用）
2. シャッフル後のvecから先頭n要素を取得（Vec\take使用）
3. サンプルサイズが元のコレクションサイズを超える場合、すべての要素を返す

**関連システム・外部連携**：
外部システムとの連携はない。内部でランダム数生成を使用するが、暗号学的に安全ではない点に注意。

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

## 関連画面

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

## 機能種別

計算処理 / ランダムサンプリング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| $traversable | Traversable<Tv> | Yes | サンプル抽出対象のコレクション | なし |
| $sample_size | int | Yes | 抽出するサンプル数 | 非負の整数でなければならない（負の場合はinvariant違反） |

### 入力データソース

プログラムコードからの直接呼び出し。vec、keyset、Set、Vectorなど、Traversableを実装する任意の型を受け付ける。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | vec<Tv> | ランダムに抽出されたサンプル要素を含むvec。サイズはmin(sample_size, 元のサイズ) |

### 出力先

呼び出し元への戻り値として返却。

## 処理フロー

### 処理シーケンス

```
1. サンプルサイズの検証
   └─ invariant($sample_size >= 0, ...)

2. 入力コレクションをシャッフル
   └─ $shuffled = Vec\shuffle($traversable)

3. シャッフル後のvecから先頭n要素を取得
   └─ Vec\take($shuffled, $sample_size)

4. 結果vecを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{sample_size >= 0?}
    B -->|No| C[InvariantException]
    B -->|Yes| D[shuffleで要素をシャッフル]
    D --> E[takeで先頭n要素を取得]
    E --> F[結果vecを返却]
    F --> G[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 非偏りサンプリング | すべての要素が等確率で選択される（統計的に偏りがない） | 常時 |
| BR-02 | サイズ制限 | サンプルサイズが元のコレクションサイズを超える場合、全要素を返す | sample_size > コレクションサイズ |
| BR-03 | 非決定的 | 同じ入力に対して異なる結果を返す可能性がある | 常時 |
| BR-04 | 暗号非安全 | ランダム性は暗号学的に安全ではない（予測可能性がある） | 常時 |

### 計算ロジック

Fisher-Yatesシャッフルアルゴリズム（shuffle関数内部）を使用し、各要素が選択される確率は等しくなる。

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | InvariantException | sample_sizeが負の値の場合 | 非負の値を指定する |

### リトライ仕様

リトライは意味がない（ランダム関数であり、同じ入力でも異なる結果を返す）。

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

トランザクション管理は不要（メモリ内処理のみ）。

## パフォーマンス要件

- 時間計算量: O(n)、nは入力コレクションのサイズ（シャッフルがボトルネック）
- 空間計算量: O(n)、シャッフル用の一時vecが必要（sample_sizeに関わらず全要素をシャッフル）

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

- **暗号学的に安全ではない**: セキュリティ上重要な用途（暗号鍵生成、トークン生成等）には使用しないこと
- くじ引きや抽選など、予測不可能性が厳密に求められる場合は`SecureRandom`を使用すべき

## 備考

- `sample_size`が0の場合、空のvecが返される
- 元のコレクションは変更されない（非破壊的操作）
- イテレータを入力した場合、内部でvecに変換される

---

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

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

### 推奨読解順序

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

ランダムサンプリングの基本概念と、shuffleおよびtakeの関係を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.php | `src/vec/select.php` | sample関数の定義場所 |

**読解のコツ**: この関数は内部でshuffle→takeのパイプライン処理を行う。パイプ演算子`|>`はHack特有の記法で、左辺の結果を右辺の関数の最初の引数として渡す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.php | `src/vec/select.php` | sample関数の実装（207-216行目） |

**主要処理フロー**:
1. **207行目**: 関数シグネチャ - Traversableとサンプルサイズを受け取る
2. **208-212行目**: サンプルサイズの非負検証（invariant）
3. **213-215行目**: shuffleでシャッフルし、takeで先頭要素を取得

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | order.php | `src/vec/order.php` | shuffle関数（67-73行目） |
| 3-2 | select.php | `src/vec/select.php` | take関数（251-266行目） |

**主要処理フロー**:
- **shuffle (67-73行目)**: PHPのshuffle関数を使用してvecをランダムに並べ替え
- **take (251-266行目)**: 先頭n要素を新しいvecとして返す

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

```
Vec\sample()
    │
    ├─ Vec\shuffle()
    │      └─ \shuffle() (PHP組み込み関数)
    │
    └─ Vec\take()
           └─ foreach反復で先頭n要素を取得
```

### データフロー図

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

Traversable<Tv>    ───▶  Vec\shuffle()  ───────────▶
$sample_size       ───▶                                   vec<Tv>
                              │                         (サンプル)
                              ▼
                         Vec\take()
                              │
                              ▼
                         先頭n要素を抽出
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.php | `src/vec/select.php` | ソース | sample関数の実装 |
| order.php | `src/vec/order.php` | ソース | shuffle関数の実装（依存） |
| select.php | `src/vec/select.php` | ソース | take関数の実装（依存） |
| VecSelectTest.php | `tests/vec/VecSelectTest.php` | テスト | sampleのユニットテスト（374-404行目） |
