# 機能設計書 32-Comparable拡張

## 概要

本ドキュメントは、mrubyのComparableモジュールにclampメソッドを追加する拡張gem（mruby-compar-ext）の機能設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：CRuby互換のComparable#clampメソッドを提供し、値を指定した範囲内に制約する操作を簡潔に記述できるようにする。数値や文字列等、Comparableをincludeするあらゆるクラスで利用可能。

**機能の利用シーン**：ユーザ入力値の範囲制限（例: 0〜100の範囲に収める）、設定値のバリデーション、数値計算結果のクリッピング等。

**主要な処理内容**：
1. clamp(min, max)形式: selfがminより小さければmin、maxより大きければmax、それ以外はselfを返す
2. clamp(range)形式: Rangeオブジェクトのbegin/endをmin/maxとして同様に処理する
3. 排他的範囲（exclude_end）の場合はArgumentErrorを発生させる
4. min/maxの比較不能時やmin>max時のエラーハンドリング

**関連システム・外部連携**：なし。

**権限による制御**：なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面なし |

## 機能種別

計算処理 / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| min | Object (Comparable) | No | 下限値（nilの場合は下限なし） | <=>で比較可能であること |
| max | Object (Comparable) | No | 上限値（nilの場合は上限なし） | <=>で比較可能であること |
| range | Range | No | min/maxの代わりにRangeで指定 | exclude_end?がfalseであること |

### 入力データソース

メソッド呼び出し時の引数。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| result | Object | min, self, maxのいずれか |

### 出力先

メソッドの戻り値。

## 処理フロー

### 処理シーケンス

```
1. 引数解析
   └─ max==nilかつmin.kind_of?(Range)の場合、Rangeからmin/maxを展開
2. 排他的範囲チェック
   └─ exclude_end?がtrueの場合ArgumentError
3. min/max比較
   └─ min <=> maxがnilなら比較失敗エラー、>0ならmin>maxエラー
4. selfとminの比較
   └─ self <=> minが0ならself、<0ならminを返す
5. selfとmaxの比較
   └─ self <=> maxが>0ならmaxを返す
6. selfを返す
```

### フローチャート

```mermaid
flowchart TD
    A[clamp呼び出し] --> B{max==nil?}
    B -->|Yes| C{min.kind_of? Range?}
    C -->|Yes| D[Range展開: max=min.end, min=min.begin]
    D --> E{exclude_end?}
    E -->|Yes| F[ArgumentError]
    C -->|No| G[min/max確定]
    B -->|No| G
    E -->|No| G
    G --> H{min,max両方non-nil?}
    H -->|Yes| I{min <=> max}
    I -->|nil| J[ArgumentError: 比較失敗]
    I -->|>0| K[ArgumentError: min>max]
    I -->|<=0| L[self <=> min比較]
    H -->|No| L
    L --> M{self < min?}
    M -->|Yes| N[return min]
    M -->|No| O{self > max?}
    O -->|Yes| P[return max]
    O -->|No| Q[return self]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 排他的範囲禁止 | exclude_end?がtrueのRangeではclamp不可 | Range形式で呼び出し時 |
| BR-02 | min<=max制約 | minはmax以下でなければならない | min,max両方がnon-nil時 |
| BR-03 | nil端点許容 | min/maxがnilの場合はその方向の制約なし | 片方がnilの場合 |

### 計算ロジック

- `self <=> min < 0` -> min を返す
- `self <=> max > 0` -> max を返す
- それ以外 -> self を返す

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentError | 排他的範囲でclamp | "cannot clamp with an exclusive range" |
| - | ArgumentError | min/max比較失敗 | "comparison of X with Y failed" |
| - | ArgumentError | min > max | "min argument must be smaller than max argument" |

### リトライ仕様

なし。

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

なし。

## パフォーマンス要件

<=>演算子の呼び出し回数は最大3回（min<=>max, self<=>min, self<=>max）。定数時間。

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

なし。

## 備考

- 純Rubyで実装されており、Cコードは含まない
- CRuby互換のAPI

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | compar.rb | `mrbgems/mruby-compar-ext/mrblib/compar.rb` | Comparableモジュールへのclampメソッド追加 |

**読解のコツ**: `NONE`定数はmrubyの「引数未指定」を表すセンチネル値。`NONE.equal?(v)`で引数が渡されたか判定する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | compar.rb | `mrbgems/mruby-compar-ext/mrblib/compar.rb` | clampメソッド（43-74行目） |

**主要処理フロー**:
1. **45-53行目**: Range引数の展開とexclude_end?チェック
2. **55-62行目**: min/max間の比較バリデーション
3. **64-68行目**: selfとminの比較
4. **69-72行目**: selfとmaxの比較
5. **73行目**: self返却

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

```
Comparable#clamp
    |
    +-- Range#end, Range#begin, Range#exclude_end?
    |       (Range引数展開時)
    |
    +-- Object#<=>
    |       (比較演算)
    |
    +-- Object#class
            (エラーメッセージ生成時)
```

### データフロー図

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

self (Comparable)  ──▶ clamp(min, max) ──▶ min / self / max
min (Comparable)
max (Comparable)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| compar.rb | `mrbgems/mruby-compar-ext/mrblib/compar.rb` | ソース(Ruby) | clampメソッドの実装 |
| mrbgem.rake | `mrbgems/mruby-compar-ext/mrbgem.rake` | 設定 | gem定義 |
| compar.rb | `mrbgems/mruby-compar-ext/test/compar.rb` | テスト | clampメソッドのテスト |
