# 機能設計書 26-IR用MD5ハッシュ計算

## 概要

本ドキュメントは、メタデータを除外した正規化された譜面データからMD5ハッシュを計算するIR（インターネットランキング）連携用機能の設計を記述する。

### 本機能の処理概要

**業務上の目的・背景**：インターネットランキング（IR）システムでは、同一の譜面を一意に識別するためのハッシュ値が必要である。しかし、譜面ファイルにはタイトルや音楽ファイルパスなどのメタデータが含まれており、これらはプレイ内容に影響しない。メタデータの変更でハッシュが変わるとランキングが分断されるため、メタデータを除外した正規化されたデータからハッシュを計算する必要がある。

**機能の利用シーン**：プレイ画面での譜面読み込み時（loadKSHChartFile内のcsongmd5hash_ir_chart計算）、選曲画面でのCtrl+I操作（IRページ表示）時に使用される。

**主要な処理内容**：
1. 譜面ファイルの全行を走査
2. ignoreListに定義された除外対象のメタデータ行をフィルタリング
3. 残りの行を連結して正規化されたデータを構築
4. 正規化データに対してMD5ハッシュを計算

**関連システム・外部連携**：IRサーバー（ir.kshootmania.com）との連携で使用される。計算されたハッシュ値はIRページのURL構築やスコア送信時の譜面識別に使用される。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 5 | ゲームプレイ画面 | 主画面 | 譜面読み込み時のIR用ハッシュ計算 |
| 3 | 曲選択画面 | 参照画面 | Ctrl+I操作でのIRページ表示用ハッシュ計算 |

## 機能種別

データ変換 / ハッシュ計算

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| p1 | var | Yes | KSH譜面ファイルの内容（文字列型変数） | 空でないこと |

### 入力データソース

noteload命令で読み込まれたKSH譜面ファイルの全テキストデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値(ret) | str | 正規化された譜面データのMD5ハッシュ文字列 |

### 出力先

関数の戻り値として返される。呼び出し元でcsongmd5hash_ir_chartに格納される。

## 処理フロー

### 処理シーケンス

```
1. bufを初期化（p1と同じサイズで確保）
2. ignoreListを定義（除外対象のメタデータプレフィックス32種類）
3. 譜面ファイルの全行をループ
   ├─ notegetで1行取得
   ├─ ignoreListの各要素とStartsWith比較
   ├─ マッチした場合: スキップ（f=0）
   └─ マッチしない場合: bufに行+改行を追加（f=1）
4. varmd5命令で正規化データのMD5ハッシュを計算
5. ハッシュ文字列を返す
```

### フローチャート

```mermaid
flowchart TD
    A[getChartIRHash開始] --> B[buf初期化]
    B --> C[ignoreList定義]
    C --> D[行ループ開始]
    D --> E[notegetで1行取得]
    E --> F{ignoreList一致?}
    F -->|Yes| G[スキップ]
    F -->|No| H[bufに行+改行を追加]
    G --> I{次の行?}
    H --> I
    I -->|Yes| E
    I -->|No| J[varmd5でMD5計算]
    J --> K[ハッシュ文字列を返す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | メタデータ除外 | ignoreListに列挙された32種類のプレフィックスで始まる行を除外 | ハッシュ計算時 |
| BR-26-02 | 行末改行 | 正規化データの各行末に"\n"を付加 | buf構築時 |
| BR-26-03 | MD5アルゴリズム | varmd5命令でMD5ハッシュを計算 | 最終計算時 |

### 計算ロジック

除外対象のignoreList（32種類）:
```
"//", "title=", "title_img=", "artist=", "artist_img=",
"effect=", "illustrator=", "jacket=", "level=", "difficulty=",
"m=", "o=", "v=", "vo=", "mvol=", "bg=", "layer=", "po=",
"plength=", "pfiltergain=", "filtertype=", "chokkakuautovol=",
"chokkakuvol=", "chokkakuse=", "icon=", "ver=", "fx-l=", "fx-r=",
"#define", "information=", "ver_compat=", "title_translit=",
"artist_translit="
```

正規化アルゴリズム:
1. 全行を走査
2. ignoreListの各プレフィックスでStartsWith判定
3. マッチしない行のみをbufに連結（改行付き）
4. bufのMD5ハッシュを計算

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

本機能ではデータベース操作は発生しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 空データ | 譜面データが空の場合 | 空文字列のMD5ハッシュが返される |

### リトライ仕様

リトライは行わない。

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

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

## パフォーマンス要件

全行走査 x ignoreList数（32）の比較処理であるが、通常の譜面ファイルでは十分高速に完了する。

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

MD5ハッシュは暗号学的には安全ではないが、譜面識別の用途では衝突確率が十分低い。

## 備考

- loadKSHChartFile内では生ファイル全体のMD5ハッシュ（csongmd5hash）も別途計算されている。IR用ハッシュ（csongmd5hash_ir_chart）とは異なる値となる。
- ignoreListに"#define"が含まれるため、ユーザー定義エフェクトの定義行もハッシュ計算から除外される。

---

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

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

### 推奨読解順序

#### Step 1: getChartIRHash関数

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ir.hsp | `src/ir.hsp` | getChartIRHash関数の完全な実装 |

**主要処理フロー**:
1. **51行目**: 関数定義（defcfunc、戻り値あり関数）
2. **52行目**: buf初期化（入力と同サイズ）
3. **53行目**: ignoreList定義（32種類のメタデータプレフィックス）
4. **54-66行目**: 全行ループ - notegetで行取得、StartsWith判定、条件付きbuf追加
5. **67行目**: varmd5でMD5ハッシュ計算
6. **68行目**: ハッシュ文字列を返す

**読解のコツ**: HSP3のdefcfuncは戻り値を持つ関数定義。notegetは行番号で1行を取得する命令。StartsWith@はグローバル関数としてアクセスされている。

#### Step 2: 呼び出し元の確認

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | loadKSHChartFile内での呼び出し |
| 2-2 | select.hsp | `src/scene/select.hsp` | Ctrl+I操作での呼び出し |

**主要処理フロー**:
- **300行目**(play_chart_load.hsp): csongmd5hash_ir_chart = getChartIRHash(buf)
- **308行目**(select.hsp): exec "https://ir.kshootmania.com/md5/" + getChartIRHash(buf), 16

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

```
loadKSHChartFile (play_chart_load.hsp)
    |
    +-- getChartIRHash(buf) (ir.hsp 51-68行目)
          +-- noteget p1Line, cnt  (行取得)
          +-- StartsWith@(p1Line, ignoreList.cnt)  (除外判定)
          +-- varmd5 ret, buf, strlen(buf)  (MD5計算)

select.hsp (Ctrl+I処理)
    |
    +-- getChartIRHash(buf) (同上)
```

### データフロー図

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

KSHファイル全文 -----> 行単位スキャン
                           |
                      ignoreList照合 -----> メタデータ行除外
                           |
                      非メタデータ行連結 --> 正規化データ
                           |
                      varmd5 -----------> MD5ハッシュ文字列
                                           |
                                      csongmd5hash_ir_chart
                                      IRページURL構築
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ir.hsp | `src/ir.hsp` | ソース | getChartIRHash関数（51-68行目） |
| play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | ソース | 呼び出し元（300行目） |
| select.hsp | `src/scene/select.hsp` | ソース | Ctrl+I操作での呼び出し（308行目） |
| kshlib.as | `src/kshlib.as` | ソース | KSHLib_GetChartMD5Hash DLL関数宣言 |
