# 機能設計書 11-アルファベットジャンプ

## 概要

本ドキュメントは、K-Shoot MANIA の選曲画面における「アルファベットジャンプ」機能の設計を記述する。FXキー長押し+選曲操作で楽曲リストの先頭文字によるジャンプナビゲーションを実現する機能である。

### 本機能の処理概要

本機能は、選曲画面において大量の楽曲が存在する場合に、FXキー長押し中に方向キー操作を行うことで、指定したアルファベットの先頭文字を持つ楽曲へカーソルを即座にジャンプさせるナビゲーション機能である。

**業務上の目的・背景**：楽曲数が増加すると、通常の上下スクロールだけでは目的の楽曲を見つけるのに時間がかかる。アルファベットジャンプにより、曲名の先頭文字を指定して素早く目的の楽曲付近へ移動できるようにすることで、選曲体験の効率化を実現する。

**機能の利用シーン**：選曲画面で楽曲リストが表示されている状態で、FXキーを長押ししながら方向キーを操作する際に利用される。特に楽曲数が多い環境(数百曲以上)で効果を発揮する。

**主要な処理内容**：
1. FXキー長押し状態の検出と`alphabetjump`変数へのジャンプ先文字コードの設定
2. 楽曲リスト内で先頭文字が一致する楽曲の検索(フォルダ境界を考慮)
3. 一致する楽曲が見つかった場合のカーソル位置(`selnow`)の更新
4. ジャケット画像・スコア・楽曲情報の再読み込み(`refreshjacket`/`refreshscore`/`refreshsonginfo`)
5. 効果音(SE)の再生

**関連システム・外部連携**：BASS Audio Libraryによる効果音再生。

**権限による制御**：なし。全プレイヤーが利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 主画面 | FXキー長押し+選曲操作による先頭文字ジャンプナビゲーション(alphabetjump変数制御) |

## 機能種別

ナビゲーション処理 / 検索処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| alphabetjump | int | Yes | ジャンプ先のアルファベット文字コード(ASCII) | 0以外の値が設定されている場合に処理実行 |
| selnow | int | Yes | 現在の曲リストカーソル位置 | 0 <= selnow < mnum |
| mnum | int | Yes | 曲リストの総項目数 | 1以上 |

### 入力データソース

- FXキー長押し中の方向キー入力(キーボードまたはジョイスティック)から`alphabetjump`変数にアルファベット文字コードが設定される
- 現在の曲リスト情報(`minfo`配列、`minfostr`配列)

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| selnow | int | ジャンプ後の曲リストカーソル位置 |
| selnow_confsave | int | 保存用カーソル位置(config.ini保存用) |
| levm | int | ジャンプ後に利用可能な難易度レベル |

### 出力先

- 画面表示(選曲画面のカーソル位置更新)
- ジャケット画像、スコア表示、楽曲情報の再描画

## 処理フロー

### 処理シーケンス

```
1. alphabetjump != 0 かつ dialognow = 0 かつウィンドウアクティブを確認
   └─ ジャンプ処理開始条件の判定
2. 現在選択位置からフォルダ境界(minfo.*.0.0 = -3)を逆方向に検索し、検索開始位置(stat3___)を決定
   └─ フォルダ内の先頭位置を特定
3. alphabetjump文字をstat3_に格納し、検索開始位置からmnum分の楽曲をループ検索
   └─ 各楽曲のフォルダパスから先頭文字を抽出し、大文字化して比較
4. 一致する楽曲が見つかった場合、selnowを更新
   └─ selnow_confsave にも保存用位置を記録
5. 難易度レベル(levm)のフォールバック処理
   └─ 現在の難易度が利用不可の場合、他の難易度へ自動切替
6. refreshjacket / refreshscore / refreshsonginfo を呼び出し
   └─ ジャンプ先の楽曲情報を再読み込み
7. alphabetjump = 0 にリセット
   └─ ジャンプ処理完了
```

### フローチャート

```mermaid
flowchart TD
    A[alphabetjump != 0] --> B{dialognow = 0 かつ ウィンドウアクティブ?}
    B -->|No| G[alphabetjump = 0]
    B -->|Yes| C[フォルダ境界検索で開始位置決定]
    C --> D[楽曲リストをループ検索]
    D --> E{先頭文字一致?}
    E -->|Yes| F1[selnow更新 / SE再生]
    E -->|No| D
    F1 --> F2[難易度フォールバック]
    F2 --> F3[refreshjacket/refreshscore/refreshsonginfo]
    F3 --> G
    G --> H[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-11-1 | 先頭文字一致検索 | 楽曲フォルダパスの先頭文字を大文字化して比較する(`strupperf`) | 常時 |
| BR-11-2 | フォルダ境界制限 | 検索はフォルダ境界(`minfo.*.0.0 = -3`)で停止する | stat3___ > 0 の場合 |
| BR-11-3 | 難易度フォールバック | ジャンプ先で現在の難易度が存在しない場合、levm=3->2->1->0 の順で利用可能な難易度にフォールバックする | ジャンプ先の楽曲データで minfostr.selnow.levm.0 が空の場合 |
| BR-11-4 | 同一位置スキップ | ジャンプ先が現在位置と同じ場合はSE再生やカーソル更新を行わない | stat3__ = selnow の場合 |

### 計算ロジック

先頭文字の抽出処理:
1. `minfostr._cnt.cnt.0`(フォルダパス)から最後の`\`以降の文字列を取得
2. さらにその文字列から最後の`\`以降の文字列を取得(二重のパス解析)
3. 先頭1文字を`strupperf`で大文字化して比較

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

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

本機能ではデータベース操作は行わない。すべてのデータはメモリ上の配列(`minfo`、`minfostr`)で管理される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 該当なし | 一致する楽曲が見つからない場合 | ジャンプせず、カーソル位置を維持。alphabetjumpを0にリセット |

### リトライ仕様

なし。

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

トランザクション管理は不要。メモリ上の変数操作のみ。

## パフォーマンス要件

- 楽曲リスト全体(最大SONG_MAX件)を線形探索するため、楽曲数に比例した処理時間となる
- 1フレーム内で完了する必要がある(30ms以内)

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

特になし。ローカルアプリケーション内のUI操作のみ。

## 備考

- `alphabetjump`変数はFXキー長押し中の方向キー入力処理で設定される(本機能の外部)
- 本機能は`start_select`関数内のメインループ(1360行目付近)で毎フレーム判定される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.hsp | `src/scene/select.hsp` | `minfo`配列(SONG_MAX,4,5)と`minfostr`配列(256,SONG_MAX,4,13)の構造。minfo.*.0.0 の値(-1:フォルダ, -2:戻る, -3:フォルダ境界, 0-3:楽曲)を理解する |

**読解のコツ**: HSP(Hot Soup Processor)では多次元配列を`.`区切りでアクセスする。`minfo.selnow.0.0`は`minfo[selnow][0][0]`に相当する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.hsp | `src/scene/select.hsp` | `start_select`関数の6行目で`alphabetjump=0`に初期化される点 |

**主要処理フロー**:
1. **6行目**: `alphabetjump=0` - 初期化
2. **1360行目**: `if(alphabetjump!=0)` - ジャンプ処理の開始判定

#### Step 3: ジャンプ検索ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | select.hsp | `src/scene/select.hsp` | 1360-1437行目のアルファベットジャンプ処理本体 |

**主要処理フロー**:
- **1362-1373行目**: フォルダ境界を逆方向検索して開始位置(stat3___)を決定
- **1374-1376行目**: ジャンプ先文字をstat3_に格納(`poke`命令で文字コードを直接書き込み)
- **1377-1389行目**: 楽曲リストのループ検索。4つの難易度に対してフォルダパスの先頭文字を比較
- **1381-1382行目**: フォルダパスから先頭文字を抽出(二重のinstr+strmid処理)
- **1383行目**: `strupperf`による大文字化比較
- **1390-1432行目**: 一致時のselnow更新と難易度フォールバック処理
- **1433-1435行目**: refreshjacket / refreshscore / refreshsonginfo の呼び出し
- **1437行目**: `alphabetjump=0` リセット

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

```
start_select (メインループ)
    |
    +-- [alphabetjump判定] (1360行目)
    |       |
    |       +-- フォルダ境界検索 (1363-1373行目)
    |       +-- 楽曲検索ループ (1377-1389行目)
    |       +-- SE再生: BASS_SampleGetChannel / BASS_ChannelPlay (1391-1393行目)
    |       +-- 難易度フォールバック (1397-1431行目)
    |       +-- *refreshjacket (1433行目)
    |       +-- *refreshscore (1434行目)
    |       +-- *refreshsonginfo (1435行目)
    |
    +-- [alphabetjump=0リセット] (1437行目)
```

### データフロー図

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

FXキー長押し+方向キー --> alphabetjump変数設定 --------> alphabetjump(文字コード)
                                                            |
minfo配列 ----+                                             v
              |----> アルファベット検索ループ --------> selnow(カーソル位置)
minfostr配列 --+         |                                  |
                         v                                  v
                    先頭文字比較 --------> *refreshjacket -> ジャケット画像更新
                                       -> *refreshscore  -> スコア表示更新
                                       -> *refreshsonginfo -> 楽曲情報更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.hsp | `src/scene/select.hsp` | ソース | 選曲画面メイン処理。アルファベットジャンプの全ロジックを含む |
