# 機能設計書 37-AUTO SYNC補正

## 概要

本ドキュメントは、K-Shoot MANIAのゲームプレイにおけるAUTO SYNC補正機能の設計を記述する。プレイ中の判定タイミングを自動で補正し、プレイヤーの入力傾向に基づいてオフセット値を調整する機能である。

### 本機能の処理概要

**業務上の目的・背景**：オーディオ出力デバイスのレイテンシや個人のタイミング傾向により、判定タイミングにずれが生じる場合がある。AUTO SYNC機能はプレイ中にリアルタイムで判定誤差を収集し、自動的に補正値（sync変数）を調整することで、プレイ体験を改善する。

**機能の利用シーン**：ゲームプレイ中にCRITICAL/NEAR判定が発生するたびに判定誤差が`sync`変数に加算され、判定タイミングが自動的に補正される。プレイ終了時、蓄積された`sync`値が0でない場合、譜面ファイルのオフセット値（o=）への保存を確認するダイアログが表示される。手動調整（Ctrl+Alt+矢印キー）も可能。

**主要な処理内容**：
1. CRITICAL/NEAR判定時に`sync += arstat.cnt.0 * autosync / 90`で判定誤差を累積
2. autosync変数（0=無効, 1=有効）で自動補正のON/OFFを制御
3. adjmode=1（調整モード）時は常に補正が有効
4. processSyncValueManualChangeInput関数でCtrl+Alt+矢印キーによる手動±5ms/±1ms調整
5. プレイ終了時にsync!=0の場合、譜面ファイルへのオフセット保存確認ダイアログを表示

**関連システム・外部連携**：config.iniのautosync設定、譜面ファイルのo=パラメータへの書き戻し。

**権限による制御**：autosync設定（config.ini）で有効/無効が切り替わる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | ゲームプレイ画面 | 主画面 | processSyncValueManualChangeInputによるプレイ中の判定タイミング自動補正 |

## 機能種別

計算処理 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| autosync | int | Yes | 自動補正有効フラグ（0=無効, 1=有効） | 0または1 |
| adjmode | int | Yes | 調整モードフラグ（0=通常, 1=調整モード） | 0または1 |
| arstat.cnt.0 | int | Yes | 判定誤差（ms） | 整数 |
| sync | double | Yes | 累積補正値（ms） | 浮動小数点 |

### 入力データソース

BT/FXノート判定（processButtonNoteJudgment）での判定誤差値。config.iniからのautosync設定。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sync | double | 累積タイミング補正値（ms） |
| offset | int | 譜面ファイルのオフセット値（保存時に更新） |

### 出力先

- メモリ: processPlayTiming関数での再生位置補正（t += sync）
- ファイル: 譜面ファイルのo=パラメータ（ユーザーが保存を選択した場合）

## 処理フロー

### 処理シーケンス

```
1. 自動補正（CRITICAL/NEAR判定時）
   └─ sync += arstat.cnt.0 * (autosync*(adjmode=0) + adjmode) / 90

2. 手動補正（processSyncValueManualChangeInput）
   ├─ Ctrl+Alt+→（Shift付き）: sync += 1.0
   ├─ Ctrl+Alt+→（Shiftなし）: sync += 5.0
   ├─ Ctrl+Alt+←（Shift付き）: sync -= 1.0
   └─ Ctrl+Alt+←（Shiftなし）: sync -= 5.0

3. タイミング適用（processPlayTiming）
   └─ t += sync（補正値を現在時刻に加算）

4. プレイ終了時（processEscKeyInput）
   ├─ sync != 0 の場合 → 保存確認ダイアログ表示
   ├─ 「はい」選択 → 譜面ファイルのo=値を更新して保存
   └─ 「いいえ」選択 → 保存せず終了
```

### フローチャート

```mermaid
flowchart TD
    A[CRITICAL/NEAR判定] --> B{autosync=1 or adjmode=1?}
    B -->|Yes| C["sync += arstat.cnt.0 * 係数 / 90"]
    B -->|No| D[補正なし]
    C --> E[processPlayTiming]
    D --> E
    E --> F["t += sync"]
    F --> G{プレイ終了?}
    G -->|No| A
    G -->|Yes| H{sync != 0?}
    H -->|Yes| I[保存確認ダイアログ]
    I -->|Yes| J["譜面ファイルのo=値を更新"]
    I -->|No| K[保存せず終了]
    H -->|No| K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-37-01 | 自動補正係数 | sync加算時の分母は90で、判定誤差の約1/90が毎回加算される | autosync=1 or adjmode=1 |
| BR-37-02 | 手動調整量 | Ctrl+Alt+矢印キーで±5ms、Shift追加で±1ms | 手動操作時 |
| BR-37-03 | 保存確認 | sync!=0の場合のみ保存確認ダイアログを表示 | プレイ終了時 |
| BR-37-04 | オフセット更新 | 保存時はo=パラメータを`offset - int(sync)`に更新 | 保存選択時 |

### 計算ロジック

```
// 自動補正（判定成功時に毎回呼ばれる）
sync += arstat.cnt.0 * (autosync * (adjmode==0) + adjmode) / 90.0

// 手動調整
// Ctrl+Alt+→+Shift: sync += 1.0
// Ctrl+Alt+→:       sync += 5.0
// Ctrl+Alt+←+Shift: sync -= 1.0
// Ctrl+Alt+←:       sync -= 5.0

// タイミング適用
t = t + sync  // 補正値を再生時刻に加算

// 譜面保存時
offset_new = offset - int(sync)
```

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

本機能はデータベースを使用しない。譜面ファイルへの書き戻しはファイルI/O。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ファイル書き込みエラー | 譜面ファイルが読み取り専用の場合 | HSPのnotesave命令のエラーハンドリングに依存 |

### リトライ仕様

リトライは不要。

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

譜面ファイルへの書き込みはnoteload→noteadd→notesaveの3ステップで行われる。

## パフォーマンス要件

判定ごとの加算は単純な浮動小数点演算。パフォーマンス上の懸念なし。

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

譜面ファイルの書き換えが行われるため、元ファイルのバックアップは行われない点に注意。

## 備考

- `sync`は浮動小数点(double)で管理されるが、int(sync)でms整数値に変換して使用される
- autosync=0かつadjmode=0の場合、自動補正は行われないが手動調整は可能
- zure変数とzuremax変数に判定誤差の累計と回数が記録され、平均ずれの計算に使用される

---

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

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

### 推奨読解順序

#### Step 1: 自動補正の蓄積を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | play_button_note.hsp | `src/scene/play/play_button_note.hsp` | CRITICAL判定時（16行目）のsync加算: `sync+=double(arstat.cnt.0)*(autosync*(adjmode=0)+adjmode)/90` |

**読解のコツ**: `autosync*(adjmode=0)+adjmode`は、adjmode=1時は常に1、adjmode=0時はautosync値となる条件式。

#### Step 2: 手動調整を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processSyncValueManualChangeInput関数（91-109行目） |

**主要処理フロー**:
- **97-98行目**: Ctrl+Alt+→+Shift: `sync+=1.0`
- **99-100行目**: Ctrl+Alt+→: `sync+=5.0`
- **103-104行目**: Ctrl+Alt+←+Shift: `sync-=1.0`
- **105-106行目**: Ctrl+Alt+←: `sync-=5.0`

#### Step 3: タイミング適用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_audio.hsp | `src/scene/play/play_audio.hsp` | processPlayTiming関数（82行目）: `t+=sync` |

#### Step 4: 保存処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | play_key_input.hsp | `src/scene/play/play_key_input.hsp` | processEscKeyInput関数（176-234行目）の保存確認ダイアログと譜面書き戻し処理 |

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

```
on_update_play (play_update.hsp)
    |
    +-- processPlayTiming (play_audio.hsp)
    |       +-- t += sync（補正値適用）
    |
    +-- processSyncValueManualChangeInput (play_key_input.hsp:91-109)
    |       +-- Ctrl+Alt+矢印で手動調整
    |
    +-- processButtonNoteJudgment (play_button_note.hsp)
    |       +-- sync += arstat.cnt.0 * .../90（自動補正蓄積）
    |
    +-- processEscKeyInput (play_key_input.hsp:111-240)
            +-- sync!=0: 保存確認ダイアログ
            +-- 譜面ファイルのo=値更新
```

### データフロー図

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

判定誤差      ────> sync蓄積(自動)          sync ──> t += sync
(arstat.cnt.0)                                       (processPlayTiming)

Ctrl+Alt+矢印 ────> sync調整(手動)          o= ──> 譜面ファイル保存
                                                    (ユーザー確認後)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_key_input.hsp | `src/scene/play/play_key_input.hsp` | ソース | processSyncValueManualChangeInput、processEscKeyInput(保存処理) |
| play_button_note.hsp | `src/scene/play/play_button_note.hsp` | ソース | CRITICAL/NEAR判定時のsync蓄積 |
| play_audio.hsp | `src/scene/play/play_audio.hsp` | ソース | processPlayTimingでのsync適用 |
| play_update.hsp | `src/scene/play/play_update.hsp` | ソース | processSyncValueManualChangeInputの呼び出し（34行目） |
