# 機能設計書 6-Clock

## 概要

本ドキュメントは、Three.jsライブラリにおける時間計測機能を提供するClockクラスの機能設計について記述する。Clockは、アニメーションや物理シミュレーションに必要なデルタ時間（前フレームからの経過時間）と累積経過時間を計測する機能を提供する。

**注意**: Clockクラスは **r183以降で非推奨** となっており、代わりにTimerクラスの使用が推奨される。

### 本機能の処理概要

Clockクラスは、performance.now()を使用して高精度な時間計測を行い、アニメーションループで使用するデルタ時間と累積経過時間を提供する。autoStart機能により、初回のgetDelta()呼び出し時に自動的に計測を開始する。

**業務上の目的・背景**：アニメーションや物理シミュレーションでは、フレーム間の時間差（デルタ時間）を正確に計測することが不可欠である。デルタ時間を使用することで、フレームレートに依存しない一定速度のアニメーションを実現できる。Clockはこの時間計測を簡単に行うためのユーティリティクラスとして設計された。

**機能の利用シーン**：
- requestAnimationFrameを使用したアニメーションループ
- 物理シミュレーションの時間ステップ計算
- パーティクルシステムの更新
- カメラコントロールの滑らかな移動

**主要な処理内容**：
1. **時間計測開始**: start()によるタイマー開始
2. **時間計測停止**: stop()によるタイマー停止
3. **デルタ時間取得**: getDelta()による前回呼び出しからの経過時間取得
4. **経過時間取得**: getElapsedTime()による総経過時間取得
5. **自動開始**: autoStartフラグによるgetDelta()初回呼び出し時の自動開始

**関連システム・外部連携**：
- requestAnimationFrameコールバック
- AnimationMixerのupdate()メソッド
- 各種Controls（OrbitControls等）のupdate()メソッド

**権限による制御**：特になし（ライブラリレベルの機能のため、アプリケーション側での権限管理は行わない）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 21 | WebGL基本サンプル | 補助機能 | アニメーションループの時間計測 |

## 機能種別

時間管理 / ユーティリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| autoStart | boolean | No | getDelta初回呼び出し時に自動開始するか | デフォルト: true |

### 入力データソース

- コンストラクタ引数
- start()、stop()メソッドの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| getDelta戻り値 | number | 前回呼び出しからの経過時間（秒） |
| getElapsedTime戻り値 | number | 開始からの総経過時間（秒） |
| startTime | number | 開始時刻（ミリ秒） |
| oldTime | number | 前回計測時刻（ミリ秒） |
| elapsedTime | number | 累積経過時間（秒） |
| running | boolean | 計測中かどうか |

### 出力先

- getDelta()、getElapsedTime()の戻り値

## 処理フロー

### 処理シーケンス

```
1. Clockインスタンス生成
   └─ コンストラクタ(autoStart = true)
       └─ プロパティ初期化（startTime=0, oldTime=0, elapsedTime=0, running=false）
       └─ 非推奨警告を出力

2. タイマー開始（明示的 or 自動）
   └─ start()
       └─ startTime = performance.now()
       └─ oldTime = startTime
       └─ elapsedTime = 0
       └─ running = true

3. デルタ時間取得
   └─ getDelta()
       └─ autoStartがtrue && 未開始の場合
           └─ start()を呼び出して0を返す
       └─ runningがtrueの場合
           └─ newTime = performance.now()
           └─ diff = (newTime - oldTime) / 1000
           └─ oldTime = newTime
           └─ elapsedTime += diff
           └─ diffを返す
       └─ runningがfalseの場合
           └─ 0を返す

4. 経過時間取得
   └─ getElapsedTime()
       └─ getDelta()を呼び出し（elapsedTimeを更新）
       └─ elapsedTimeを返す

5. タイマー停止
   └─ stop()
       └─ getElapsedTime()を呼び出し（最終更新）
       └─ running = false
       └─ autoStart = false
```

### フローチャート

```mermaid
flowchart TD
    A[Clock生成] --> B[プロパティ初期化]
    B --> C[非推奨警告]
    C --> D{getDelta呼び出し?}
    D -->|Yes| E{autoStart && !running?}
    E -->|Yes| F[start]
    F --> G[return 0]
    E -->|No| H{running?}
    H -->|Yes| I[newTime = performance.now]
    I --> J[diff = newTime - oldTime / 1000]
    J --> K[oldTime = newTime]
    K --> L[elapsedTime += diff]
    L --> M[return diff]
    H -->|No| N[return 0]
    D -->|No| O{getElapsedTime呼び出し?}
    O -->|Yes| P[getDelta]
    P --> Q[return elapsedTime]
    O -->|No| R{stop呼び出し?}
    R -->|Yes| S[getElapsedTime]
    S --> T[running = false]
    T --> U[autoStart = false]
    R -->|No| D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 自動開始 | autoStart=trueの場合、初回getDelta()で自動的にstart()が呼ばれる | getDelta()初回呼び出し時 |
| BR-02 | 初回デルタ0 | start()直後のgetDelta()は0を返す | start()呼び出し直後 |
| BR-03 | 停止後のautoStart無効化 | stop()を呼ぶとautoStartがfalseになる | stop()呼び出し時 |
| BR-04 | ミリ秒→秒変換 | 内部ではミリ秒、APIでは秒を使用 | getDelta()、getElapsedTime() |
| BR-05 | 非推奨クラス | r183以降、Timerクラスの使用が推奨される | 常時 |

### 計算ロジック

**デルタ時間の計算:**
```javascript
const newTime = performance.now();
diff = (newTime - this.oldTime) / 1000; // ミリ秒→秒
this.oldTime = newTime;
this.elapsedTime += diff;
```

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

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

該当なし（Clockはデータベースを使用しない）

## エラー処理

### エラーケース一覧

該当なし（Clockは明示的なエラー処理を行わない）

### リトライ仕様

該当なし

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

該当なし（メモリ上のオブジェクト操作のみ）

## パフォーマンス要件

- performance.now()は高精度（マイクロ秒レベル）の時間計測を提供
- getDelta()は軽量な操作であり、毎フレーム呼び出しても問題ない

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

該当なし（クライアントサイドのグラフィックスライブラリ）

## 備考

- **非推奨警告**: r183以降、Clockは非推奨。Timerクラスの使用を推奨
- ClockのgetDelta()は呼び出すたびにoldTimeが更新されるため、1フレームで複数回呼び出すと異なる値が返る（これがTimerに移行した理由の一つ）
- Page Visibility APIへの対応がない（タブ非表示時に大きなデルタ値が発生する可能性）

---

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

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

### 推奨読解順序

#### Step 1: クラス構造を理解する

Clockの基本構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Clock.js | `src/core/Clock.js` | クラス全体の構造とプロパティ |

**読解のコツ**: Clockは4つのプロパティ（autoStart、startTime、oldTime、elapsedTime、running）と4つのメソッド（start、stop、getElapsedTime、getDelta）を持つシンプルなクラス。

#### Step 2: コンストラクタを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Clock.js | `src/core/Clock.js` | コンストラクタでのプロパティ初期化と非推奨警告 |

**主要処理フロー**:
- **17-63行目**: コンストラクタ
- **26行目**: autoStartのデフォルト（true）
- **34行目**: startTimeの初期化（0）
- **43行目**: oldTimeの初期化（0）
- **51行目**: elapsedTimeの初期化（0）
- **59行目**: runningの初期化（false）
- **61行目**: 非推奨警告の出力

#### Step 3: タイマー制御を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Clock.js | `src/core/Clock.js` | start()、stop()メソッド |

**主要処理フロー**:
- **69-77行目**: start() - タイマー開始
- **71行目**: startTime = performance.now()
- **73-74行目**: oldTime、elapsedTimeのリセット
- **75行目**: running = true
- **82-88行目**: stop() - タイマー停止
- **84行目**: getElapsedTime()で最終更新
- **85-86行目**: running、autoStartをfalseに

#### Step 4: 時間取得を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Clock.js | `src/core/Clock.js` | getDelta()、getElapsedTime()メソッド |

**主要処理フロー**:
- **95-100行目**: getElapsedTime() - getDelta()を呼んでelapsedTimeを返す
- **107-131行目**: getDelta() - デルタ時間の計算
- **111-115行目**: autoStart処理
- **118-127行目**: デルタ時間の計算

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

```
Clock
    │
    ├─ constructor(autoStart = true)
    │      ├─ プロパティ初期化
    │      └─ warn('THREE.Clock: deprecated')
    │
    ├─ start()
    │      ├─ startTime = performance.now()
    │      ├─ oldTime = startTime
    │      ├─ elapsedTime = 0
    │      └─ running = true
    │
    ├─ stop()
    │      ├─ getElapsedTime()
    │      ├─ running = false
    │      └─ autoStart = false
    │
    ├─ getElapsedTime()
    │      ├─ getDelta()
    │      └─ return elapsedTime
    │
    └─ getDelta()
           ├─ [if autoStart && !running]
           │      ├─ start()
           │      └─ return 0
           │
           └─ [if running]
                  ├─ newTime = performance.now()
                  ├─ diff = (newTime - oldTime) / 1000
                  ├─ oldTime = newTime
                  ├─ elapsedTime += diff
                  └─ return diff
```

### データフロー図

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

                    ┌─────────────────────┐
autoStart ─────────→│ constructor()       │
                    │ startTime = 0       │
                    │ oldTime = 0         │
                    │ elapsedTime = 0     │
                    │ running = false     │
                    └─────────────────────┘
                              │
                              ↓
                    ┌─────────────────────┐
                    │ start()             │
performance.now() ──→│ startTime = now    │
                    │ oldTime = now       │
                    │ running = true      │
                    └─────────────────────┘
                              │
                              ↓
                    ┌─────────────────────┐
                    │ getDelta()          │
performance.now() ──→│                     │──→ delta (秒)
                    │ diff = (now-old)/1000│
                    │ oldTime = now       │
                    │ elapsedTime += diff │
                    └─────────────────────┘
                              │
                              ↓
                    ┌─────────────────────┐
                    │ getElapsedTime()    │
                    │ → getDelta()        │──→ elapsedTime (秒)
                    └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Clock.js | `src/core/Clock.js` | ソース | Clockクラス本体 |
| Timer.js | `src/core/Timer.js` | ソース | 推奨される代替クラス |
| utils.js | `src/utils.js` | ソース | warn関数の提供 |
