# 機能設計書 97-IRページ表示

## 概要

本ドキュメントは、K-Shoot MANIAにおけるCtrl+Iショートカットで選択中譜面のインターネットランキング(IR)ページをブラウザで開く機能の設計を記述する。

### 本機能の処理概要

本機能は、選曲画面でCtrl+Iキーの同時押しを検出し、選択中の譜面のIRハッシュを計算した上で、IRウェブサイト(ir.kshootmania.com)の該当譜面ページをデフォルトブラウザで開く機能である。

**業務上の目的・背景**：プレイヤーが選択中の譜面のインターネットランキング情報を素早く確認できるようにするため、ショートカットキーで直接IRページにアクセスする手段を提供する。

**機能の利用シーン**：選曲画面(SCENE_SELECT)で通常の譜面(minfo.selnow.0.0=0)が選択されている状態でCtrl+Iを押下した際に動作する。コースモードの譜面では動作しない。

**主要な処理内容**：
1. Ctrlキーの押下状態を検出
2. Iキーの押下(前フレームとの差分)を検出
3. 選択中の譜面が通常譜面であることを確認
4. 譜面ファイルの存在を確認し、内容を読み込み
5. UTF-8 BOM処理
6. getChartIRHash(No.95)でMD5ハッシュを計算
7. exec命令でブラウザを起動しIRページURLを開く

**関連システム・外部連携**：IRウェブサイト(https://ir.kshootmania.com/md5/{hash})をデフォルトブラウザで開く。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 曲選択画面 | 主画面 | Ctrl+Iショートカットでexec命令によりブラウザでIRページを開く |

## 機能種別

ユーザーインタラクション / 外部連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Ctrlキー状態 | int | Yes | Ctrlキーの押下状態(getkey) | 押下中=1 |
| Iキー状態 | int | Yes | Iキーの押下状態(getkey) | 前フレームとの差分で押下検出 |
| minfo.selnow.0.0 | int | Yes | 選択中アイテムの種別 | 0(通常譜面)の場合のみ処理 |
| filePath | str | Yes | 選択中譜面のファイルパス | fileExistsで存在確認 |

### 入力データソース

- キーボード入力: getkey命令による'I'キーとCtrlキーの状態検出
- 選択中譜面情報: minfo配列とfilePath変数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| URL | str | https://ir.kshootmania.com/md5/{hash} 形式のURL |

### 出力先

デフォルトブラウザ(exec命令の第2引数16でURLを開く)

## 処理フロー

### 処理シーケンス

```
1. Ctrlキー押下中を確認
2. Iキーの押下(前フレーム差分)を検出
3. 選択中が通常譜面(minfo.selnow.0.0 = 0)であることを確認
4. fileExists(filePath)で譜面ファイルの存在を確認
5. noteload filePath, -1 で譜面ファイルを読み込み
6. UTF-8 BOM(0xBFBBEF)が存在する場合はDeleteUTF8BOM処理
7. getChartIRHash(buf)でMD5ハッシュを計算
8. exec "https://ir.kshootmania.com/md5/" + hash, 16 でブラウザ起動
```

### フローチャート

```mermaid
flowchart TD
    A[Ctrlキー押下中] --> B{Iキー新規押下?}
    B -->|Yes| C{通常譜面?}
    B -->|No| Z[何もしない]
    C -->|Yes| D{ファイル存在?}
    C -->|No| Z
    D -->|Yes| E[譜面ファイル読み込み]
    D -->|No| Z
    E --> F{UTF-8 BOM?}
    F -->|Yes| G[DeleteUTF8BOM]
    F -->|No| H[getChartIRHash]
    G --> H
    H --> I[exec: ブラウザでIRページを開く]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-97-01 | 通常譜面のみ対応 | minfo.selnow.0.0 = 0(通常譜面)の場合のみIRページを開く | Ctrl+I押下時 |
| BR-97-02 | IRページURL形式 | https://ir.kshootmania.com/md5/{32文字MD5ハッシュ} | IRページ表示時 |
| BR-97-03 | UTF-8 BOM処理 | 譜面ファイルの先頭3バイトが0xBFBBEFの場合はBOMを除去 | 譜面読み込み後 |

### 計算ロジック

特になし(ハッシュ計算はNo.95参照)。

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

本機能ではデータベースは使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| N/A | ファイル未発見 | fileExists(filePath)がfalseの場合 | 処理をスキップ |

### リトライ仕様

特になし。

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

特になし。

## パフォーマンス要件

ショートカットキー操作のため、ユーザー体感で即座にブラウザが起動すべきである。

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

exec命令でURLを外部ブラウザに渡すため、URLインジェクションのリスクはないがMD5ハッシュは固定長32文字の16進数のみ。

## 備考

- exec命令の第2引数16はHSP3でURL/ファイルをシステムのデフォルトアプリケーションで開く指定
- Ctrl+Iの他に、Ctrl+C(パスコピー)、Ctrl+E(エディタ起動)、Ctrl+O(フォルダ表示)のショートカットも存在する

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | select.hsp | `src/scene/select.hsp` | ctrlIKey/ctrlIKeyPrev変数: Iキー状態のフレーム差分管理 |
| 1-2 | select.hsp | `src/scene/select.hsp` | minfo配列: 選択中アイテムの種別情報 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | select.hsp | `src/scene/select.hsp` | Ctrl+Iショートカット処理(298-312行目) |

**主要処理フロー**:
1. **299行目**: getkey ctrlIKey, 'I' でIキー状態取得
2. **300行目**: 前フレーム差分チェック(ctrlIKey & ctrlIKeyPrev=0)
3. **301行目**: 通常譜面チェック(minfo.selnow.0.0 = 0)
4. **302行目**: fileExists(filePath)でファイル存在確認
5. **303-304行目**: noteload filePath, -1 で譜面読み込み
6. **305-306行目**: UTF-8 BOM検出とDeleteUTF8BOM処理
7. **308行目**: exec + getChartIRHash(buf) でブラウザ起動

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

```
select.hsp (Ctrl+Iショートカット)
    |
    +-- getkey ctrlIKey, 'I'
    |
    +-- fileExists(filePath)  ← filesystem_utils.as
    |
    +-- noteload filePath, -1
    |
    +-- DeleteUTF8BOM(buf)  ← BOM処理
    |
    +-- getChartIRHash(buf)  ← ir.hsp (No.95)
    |       +── ignoreListフィルタリング
    |       └── varmd5
    |
    └── exec "https://ir.kshootmania.com/md5/{hash}", 16
```

### データフロー図

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

Ctrl+Iキー入力 ──────> 譜面種別チェック
                            |
譜面ファイル ─────────> noteload → BOM処理 → getChartIRHash
                            |
                            v
                     MD5ハッシュ ────────> exec(URL) ──> ブラウザ起動
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| select.hsp | `src/scene/select.hsp` | ソース | Ctrl+Iショートカット処理(298-312行目) |
| ir.hsp | `src/ir.hsp` | ソース | getChartIRHash関数 |
| filesystem_utils.as | `src/filesystem_utils.as` | ソース | fileExists関数 |
