# 機能設計書 33-チェーンカウント

## 概要

本ドキュメントは、K-Shoot MANIAのゲームプレイにおけるチェーンカウント機能の設計を記述する。連続成功判定のチェーン数（コンボ数）をカウントし、最大チェーン数を記録する機能である。

### 本機能の処理概要

**業務上の目的・背景**：音楽ゲームにおいてプレイヤーの連続判定精度を評価するために、チェーン（コンボ）数を管理する必要がある。最大チェーン数はスコアとともにプレイ実績として記録され、フルコンボ判定の基準となる。

**機能の利用シーン**：ゲームプレイ中にCRITICALまたはNEAR判定が連続するたびにチェーン数がインクリメントされ、ERRORが発生するとリセットされる。100チェーンごとに特別なエフェクトが表示される。プレイ終了後、最大チェーン数が結果画面に表示され、全ノート成功時にはフルコンボとして記録される。

**主要な処理内容**：
1. CRITICAL/NEAR成功時にchainnow（現在チェーン数）をインクリメント
2. ERROR判定時にchainnowを0にリセット
3. chainnow > chainmax の場合にchainmax（最大チェーン数）を更新
4. 100チェーンごとにchainefft（チェーンエフェクト時刻）を記録
5. チェーン成功時にchainvt（チェーン表示時刻）を記録
6. コースモード用のchainnow_song/chainmax_song（曲別チェーン）の管理

**関連システム・外部連携**：結果画面でのフルコンボ判定、スコアファイルへの最大チェーン数保存、IRスコア送信。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | ゲームプレイ画面 | 主画面 | 連続成功判定のチェーン数カウントと最大チェーン(chainmax)の記録 |
| 6 | リザルト画面 | 結果表示画面 | 最大チェーン数の表示 |

## 機能種別

計算処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| chainnow | int | Yes | 現在のチェーン数 | 0以上の整数 |
| chainmax | int | Yes | 最大チェーン数 | 0以上の整数 |
| chainnow_song | int | Yes | 曲別現在チェーン数 | 0以上の整数 |
| chainmax_song | int | Yes | 曲別最大チェーン数 | 0以上の整数 |

### 入力データソース

BT/FXノート判定（processButtonNoteJudgment）、レーザーノート判定（processLaserNoteJudgment）での各判定結果。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| chainnow | int | 現在のチェーン数（ERROR時に0リセット） |
| chainmax | int | プレイ全体の最大チェーン数 |
| chainnow_song | int | 曲別の現在チェーン数 |
| chainmax_song | int | 曲別の最大チェーン数 |
| chainvt | int | 最終チェーン成功時刻（表示用） |
| chainefft | int | 100チェーンエフェクト時刻 |
| noerror | int | エラーなしフラグ（1=パーフェクト候補） |

### 出力先

- 画面表示: ゲームプレイ画面のコンボ数表示（play_draw_frame.hsp）
- 結果画面: 最大チェーン数表示（result.hsp）

## 処理フロー

### 処理シーケンス

```
1. CRITICAL/NEAR判定成功時
   ├─ chainnow++ / chainnow_song++
   ├─ if chainnow > chainmax → chainmax = chainnow
   ├─ if chainnow_song > chainmax_song → chainmax_song = chainnow_song
   ├─ if chainnow % 100 == 0 → chainefft = t（エフェクト発動）
   └─ chainvt = t（表示更新時刻）

2. ERROR判定時
   ├─ chainnow = 0 / chainnow_song = 0
   ├─ noerror = 0 / noerror_song = 0
   └─ chainmaxは更新しない
```

### フローチャート

```mermaid
flowchart TD
    A[ノート判定] --> B{判定結果}
    B -->|CRITICAL/NEAR| C[chainnow++]
    B -->|ERROR| D[chainnow=0]
    C --> E[chainnow_song++]
    E --> F{chainnow > chainmax?}
    F -->|Yes| G[chainmax = chainnow]
    F -->|No| H{chainnow % 100 == 0?}
    G --> H
    H -->|Yes| I["chainefft = t"]
    H -->|No| J["chainvt = t"]
    I --> J
    D --> K[chainnow_song=0]
    K --> L[noerror=0, noerror_song=0]
    J --> M[完了]
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-33-01 | チェーンインクリメント | CRITICAL/NEAR成功時にchainnowを1加算 | 全成功判定時 |
| BR-33-02 | チェーンリセット | ERROR判定時にchainnowを0にリセット | 全ERROR時 |
| BR-33-03 | 最大チェーン更新 | chainnow > chainmax の場合のみchainmaxを更新 | チェーン加算時 |
| BR-33-04 | 100チェーンエフェクト | chainnowが100の倍数の時にエフェクト時刻を記録 | chainnow\100=0 |
| BR-33-05 | noerrorフラグ管理 | ERROR発生時にnoerror=0。初期値1でパーフェクト候補 | ERROR判定時 |
| BR-33-06 | コースモード分離管理 | コース全体(chainnow/chainmax)と曲別(chainnow_song/chainmax_song)を別々に管理 | コースモード時 |

### 計算ロジック

```
// 成功判定時
chainnow++
chainnow_song++
if chainnow > chainmax: chainmax = chainnow
if chainnow_song > chainmax_song: chainmax_song = chainnow_song
if chainnow % 100 == 0: chainefft = t  // 100コンボエフェクト
chainvt = t  // チェーン表示更新

// ERROR判定時
chainnow = 0
chainnow_song = 0
noerror = 0
noerror_song = 0
```

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

本機能はデータベースを使用しない。チェーン数はメモリ上の変数として管理される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | 特にエラーケースなし | - |

### リトライ仕様

リトライは不要。

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

トランザクション管理は不要。

## パフォーマンス要件

ノート判定ごとに実行される単純なインクリメント/リセット処理。パフォーマンス上の懸念なし。

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

特になし。

## 備考

- `chainnow\100`はHSPの剰余演算子で、`chainnow % 100`に相当する
- コースモード時、chainmax/chainnowはコース全体を通して累積される
- noerror=1のまま楽曲が終了するとパーフェクト（全CRITICAL/NEAR）として記録される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | play_game_logic.hsp | `src/scene/play/play_game_logic.hsp` | initGamePlayVariables関数でchainnow, chainmax, noerror等の初期化を確認（46-52行目） |

**読解のコツ**: `chainnow_song`/`chainmax_song`は曲単位のチェーン、`chainnow`/`chainmax`はコース全体のチェーン。通常モード時は両者が同値になる。

#### Step 2: チェーン加算の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_button_note.hsp | `src/scene/play/play_button_note.hsp` | BTチップCRITICAL判定時（22-28行目）のchainnow++, chainmax更新を確認 |
| 2-2 | play_button_note.hsp | `src/scene/play/play_button_note.hsp` | NEAR判定時（44-54行目）のchainnow++, chainmax更新を確認 |
| 2-3 | play_laser_note.hsp | `src/scene/play/play_laser_note.hsp` | レーザースラム判定成功時（314-320行目）のchainnow++を確認 |

**主要処理フロー**:
- **22行目**: `chainnow++:chainnow_song++` - CRITICAL成功時のインクリメント
- **25行目**: `if(chainnow>chainmax):chainmax=chainnow` - 最大チェーン更新
- **27行目**: `if(chainnow\100=0):chainefft=t` - 100チェーンエフェクト

#### Step 3: チェーンリセットの処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | play_button_note.hsp | `src/scene/play/play_button_note.hsp` | ERROR判定時（354行目）の`chainnow=0:chainnow_song=0`を確認 |
| 3-2 | play_laser_note.hsp | `src/scene/play/play_laser_note.hsp` | レーザーERROR時（573行目）の`chainnow=0:chainnow_song=0`を確認 |

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

```
on_update_play (play_update.hsp)
    |
    +-- processButtonNoteJudgment (play_button_note.hsp)
    |       +-- CRITICAL: chainnow++, chainmax更新, chainefft更新
    |       +-- NEAR:     chainnow++, chainmax更新
    |       +-- ERROR:    chainnow=0, noerror=0
    |
    +-- processLaserNoteJudgment (play_laser_note.hsp)
            +-- スラム成功: chainnow++, chainmax更新
            +-- 追従成功:   chainnow++, chainmax更新
            +-- ERROR:      chainnow=0, noerror=0
```

### データフロー図

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

CRITICAL判定 ────> chainnow++              chainmax ──> result.hsp
NEAR判定     ────> chainmax更新            chainnow ──> play_draw_frame.hsp
ERROR判定    ────> chainnow=0              chainefft -> エフェクト表示
                   noerror=0               noerror ──> フルコンボ判定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| play_game_logic.hsp | `src/scene/play/play_game_logic.hsp` | ソース | チェーン関連変数の初期化 |
| play_button_note.hsp | `src/scene/play/play_button_note.hsp` | ソース | BT/FXノート判定でのチェーン加算/リセット |
| play_laser_note.hsp | `src/scene/play/play_laser_note.hsp` | ソース | レーザーノート判定でのチェーン加算/リセット |
| play_update.hsp | `src/scene/play/play_update.hsp` | ソース | メインループ |
| play_draw_frame.hsp | `src/scene/play/play_draw_frame.hsp` | ソース | コンボ数の画面表示 |
| result.hsp | `src/scene/result.hsp` | ソース | 最大チェーン数・フルコンボ判定の表示 |
