# 通知設計書 2-IRスコア送信通知

## 概要

本ドキュメントは、K-Shoot MANIAのリザルト画面におけるInternet Ranking（IR）スコア送信状態のポップアップ通知機能の設計を記述する。IR送信結果やチャート未登録状態をユーザーに通知するための処理について、トリガー条件、表示仕様、処理フローを網羅的に定義する。

### 本通知の処理概要

本通知は、リザルト画面右下にポップアップUIを表示し、IRサーバーへのスコア送信結果またはチャート未登録状態をユーザーに通知する。未登録チャートの場合は「Unregistered chart」メッセージと共にFX-L+Rの500ms長押しによる自動登録機能を提供する。

**業務上の目的・背景**：Internet Ranking（IR）はプレイヤー間のスコア競争を可能にするオンライン機能である。スコア送信の成否をリアルタイムでプレイヤーに通知することで、ランキング登録状況の把握と、未登録チャートへの即座の対応を可能にしている。

**通知の送信タイミング**：リザルト画面初期化直後のIR送信処理完了時に自動的に表示される。具体的には、(1) auto=0かつadjmode=0かつiscmdline=0で、(2) shortmode+longmode+analogmode=0（ASISTなし）で、(3) tochu_esc=0（途中終了なし）の条件を満たすとき、ksm_id（IRログイン状態）が有効であればir_send_score関数が呼ばれ、その結果に応じてポップアップが設定される。

**通知の受信者**：現在プレイ中のプレイヤー（リザルト画面を閲覧しているユーザー）。

**通知内容の概要**：IRスコア送信の成否メッセージ、未登録チャートの場合は登録促進メッセージ、HiSPEED type "C"使用時はスコア未送信理由メッセージ。

**期待されるアクション**：未登録チャートの場合、FX-L+FX-Rを500ms長押しすることでチャートの自動登録とスコア再送信が行われる。送信成功の場合はメッセージ確認のみ。

## 通知種別

アプリ内通知（ポップアップ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（リザルト画面初期化時にIR送信を実行し、結果を即座にポップアップ表示） |
| 優先度 | 中（プレイ結果の記録に関わるが、ゲーム進行に影響なし） |
| リトライ | 有（FX-L+R長押しによる手動リトライ。チャート登録後に自動でスコア再送信） |

### 送信先決定ロジック

ポップアップ表示先はリザルト画面右下の固定位置。IRサーバーへの送信先はhosts変数で定義されたIRサーバーURL（ソースコード公開版では削除済み）。

## 通知テンプレート

### メール通知の場合

本通知はアプリ内ポップアップのため、メール関連項目は該当しない。

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A |
| 送信元名称 | N/A |
| 件名 | N/A |
| 形式 | アプリ内ポップアップ（170px幅） |

### 本文テンプレート

パターン1: 未登録チャート
```
Unregistered chart
Hold FX-L+R to register this chart
```

パターン2: 送信成功
```
{IRサーバーからのレスポンスメッセージ}
```

パターン3: HiSPEED type "C"使用時
```
Score was not sent
(HiSPEED type "C" was used)
```

パターン4: IR接続失敗
```
Connection failed.
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | ポップアップ通知のため添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| is_chart_registered | チャート登録状態（-1:不明, 0:未登録, 1:登録済） | ir_send_score関数の戻り値 | Yes |
| output@ksm_ir | IRサーバーからのレスポンスメッセージ | IRサーバーHTTPレスポンス | No |
| bom | UTF-8 BOM | 定数（0xEF, 0xBB, 0xBF） | No |
| no_hstype_c | HiSPEED type "C"未使用フラグ | ゲーム設定 | Yes |
| ksm_id | IRログインID | IRログイン処理 | Yes |
| popup_text | ポップアップ表示テキスト | ir_popup_set_text関数で設定 | Yes |
| popup_height | ポップアップの高さ | テキスト描画領域計算から算出 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面遷移 | リザルト画面初期化 | auto=0, adjmode=0, iscmdline=0, ASSIST未使用, 途中終了なし, ksm_idが有効 | リザルト画面表示時に自動的にIRスコア送信を実行 |
| 画面操作 | FX-L+FX-R 500ms長押し | ir_regchart_wait=1かつis_chart_registered=0 | 未登録チャート時のチャート登録とスコア再送信 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| auto=1 | オートプレイ時はIR送信しない |
| adjmode=1 | 調整モード時はIR送信しない |
| iscmdline=1 | コマンドライン起動時はIR送信しない |
| shortmode+longmode+analogmode>0 | ASSIST使用時はIR送信しない |
| tochu_esc=1 | 途中終了時はIR送信しない |
| ksm_id=0 | IRにログインしていない場合はIR送信しない |
| no_hstype_c=0 | HiSPEED type "C"使用時はスコア送信しない（通知のみ） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[リザルト画面初期化] --> B[ir_popup_init]
    B --> C{IR送信条件チェック}
    C -->|条件NG| D[ポップアップなし]
    C -->|条件OK| E{ksm_idが有効?}
    E -->|No| D
    E -->|Yes| F{no_hstype_c=1?}
    F -->|No| G[ir_popup_set_text: HiSPEED C未対応メッセージ]
    F -->|Yes| H[ir_send_score実行]
    H --> I{is_chart_registered}
    I -->|0: 未登録| J[ir_popup_set_text: 未登録チャートメッセージ]
    J --> K[ir_regchart_wait=1]
    I -->|1: 登録済| L[ir_popup_set_text: サーバーレスポンス]
    I -->|-1: 不明| D
    K --> M{FX-L+R 500ms長押し?}
    M -->|No| N[ポップアップ表示継続]
    M -->|Yes| O[ir_send_chart + ir_send_score]
    O --> P{登録成功?}
    P -->|Yes| Q[ir_popup_set_text: 成功メッセージ]
    P -->|No| R[ir_popup_set_text: 再度未登録メッセージ]
    D --> S[終了]
    G --> S
    L --> S
    N --> S
    Q --> S
    R --> S
```

## データベース参照・更新仕様

### 参照テーブル一覧

本通知はデータベースを使用しない。IRサーバーとのHTTP通信で情報を送受信する。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | HTTP API通信ベース |

### テーブル別参照項目詳細

該当なし（IRサーバーAPI経由）。

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | N/A | IRサーバー側でスコアデータを管理 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| IR接続失敗 | IRサーバーに接続できない場合 | "Connection failed." ダイアログ表示（ir.hsp:34） |
| チャート未登録 | 譜面がIRサーバーに登録されていない場合 | 未登録メッセージをポップアップ表示し、FX-L+R長押しでの登録を促す |
| スコア送信失敗 | サーバーエラーまたはネットワーク障害 | IRサーバーからのレスポンスメッセージをポップアップ表示 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 手動リトライ（回数制限なし、hold_fxlr_time>=50000で停止） |
| リトライ間隔 | ユーザー操作依存（FX-L+R 500ms長押し） |
| リトライ対象エラー | チャート未登録（ir_regchart_wait=1の場合のみ） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（1リザルト画面につき1回の自動送信 + 手動リトライ） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

時間帯制限なし。リザルト画面表示中に自動実行される。

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

- IRサーバーとの通信にはksm_id（認証情報）を使用する
- 通信内容はスコアデータとチャートハッシュ（MD5）のみで、個人情報は含まない
- IRコア実装（認証・通信処理）はソースコード公開版では削除されており、実際の通信プロトコルの詳細は不明
- RC4暗号化モジュール（third_party/rc4_crypt.hsp）がインクルードされているが、IR通信での使用有無は削除済みコードのため確認不可

## 備考

- ir_popup_init / ir_popup_set_text / ir_popup_draw の3関数でポップアップUIを実装（ir.hsp:70-117）
- ポップアップのUI幅は170px（getsize(170)）
- ポップアップの表示・非表示にはフェードイン/フェードアウトアニメーション（各200ms）が適用される
- hold_fxlr_time変数でFX-L+R同時押下の継続時間を管理し、500ms以上で登録処理を発動
- hold_fxlr_time>=50000の場合は再登録処理を防止（1回限りの実行制御）
- IRコア実装（ir_send_score, ir_send_chart, ir_login等）はソースコード公開版では削除されており、常に-1を返す

---

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

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

### 推奨読解順序

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

ポップアップUIのデータ構造と状態管理変数を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ir.hsp | `src/ir.hsp` | モジュール先頭（1-25行目）: ksm_irモジュールの定数定義（IMG_IR_POPUP, IMG_IR_POPUP_TEMP等）とグローバル変数（output, popup_text）を確認 |
| 1-2 | kshootmania.hsp | `kshootmania.hsp` | 104-105行目: IMG_IR_POPUP(170)、IMG_IR_POPUP_TEMP(171)の画像バッファ定数定義を確認 |

**読解のコツ**: HSP3の`#module`〜`#global`ブロック内の変数は`変数名@モジュール名`でアクセスされる。ir.hsp内のpopup_startt, popup_endtなどはksm_irモジュールのローカル変数。

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

ポップアップの初期化はon_update_result内で行われる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | result.hsp | `src/scene/result.hsp` | 4行目: `ir_popup_init`呼び出し（ポップアップ初期化） |
| 2-2 | result.hsp | `src/scene/result.hsp` | 584-602行目: IR送信処理とポップアップテキスト設定 |

**主要処理フロー**:
1. **4行目**: `ir_popup_init` - ポップアップUIの初期化
2. **586行目**: IR送信条件の判定（auto, adjmode, iscmdline, ASSIST, tochu_esc）
3. **588行目**: `ksm_id`の有効性チェック
4. **589-590行目**: `no_hstype_c`チェックとir_send_score呼び出し
5. **592-596行目**: 未登録チャート時のメッセージ設定とir_regchart_wait=1
6. **597行目**: 登録済みの場合のレスポンスメッセージ設定

#### Step 3: ポップアップUI実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ir.hsp | `src/ir.hsp` | 70-75行目: ir_popup_init - 初期化処理 |
| 3-2 | ir.hsp | `src/ir.hsp` | 77-98行目: ir_popup_set_text - テキスト設定とUI構築 |
| 3-3 | ir.hsp | `src/ir.hsp` | 100-117行目: ir_popup_draw - フェードイン/アウト付き描画 |

**主要処理フロー**:
- **70-75行目**: `ir_popup_init` - popup_startt=0, popup_endt=-10000に初期化、200px幅の一時画像バッファ作成
- **77-98行目**: `ir_popup_set_text` - テキスト描画領域計算（alDrawText_CalcRect）、背景画像コピー、テキスト描画、表示タイマー設定
- **100-117行目**: `ir_popup_draw` - 4フェーズ（表示前/フェードイン/表示中/フェードアウト）のアルファ値計算、画面右下への描画

#### Step 4: チャート手動登録処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | result.hsp | `src/scene/result.hsp` | 773-796行目: FX-L+R長押しによるチャート登録処理 |

**主要処理フロー**:
- **778行目**: `hold_fxlr_time+=t-tp` - FX-L+R同時押下時間の累積
- **784行目**: 500ms以上かつ50000未満の場合に登録処理開始
- **785-786行目**: `ir_send_chart` + `ir_send_score` - チャート登録とスコア再送信
- **795行目**: `hold_fxlr_time=50000` - 再登録防止

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

```
on_update_result (result.hsp:1)
    |
    +-- ir_popup_init (ir.hsp:70)
    |       +-- alCreateImage IMG_IR_POPUP_TEMP
    |
    +-- [IR送信条件チェック] (result.hsp:586-601)
    |       +-- ir_send_score (ir.hsp:38) ──▶ IRサーバー
    |       +-- ir_popup_set_text (ir.hsp:77)
    |               +-- alDrawText_CalcRect : テキスト領域計算
    |               +-- alDrawText : テキスト描画
    |
    +-- [メインループ] (result.hsp:606-849)
    |       +-- [FX-L+R長押し検出] (result.hsp:773-796)
    |       |       +-- ir_send_chart (ir.hsp:42)
    |       |       +-- ir_send_score (ir.hsp:38)
    |       |       +-- ir_popup_set_text (ir.hsp:77)
    |       |
    |       +-- ir_popup_draw (ir.hsp:100)
    |               +-- alCopyModeAlpha : フェード制御
    |               +-- alCopyImageToScreen : 描画
```

### データフロー図

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

プレイ結果
  totalscore ────────┐
  critical/near/err ─┼──▶ ir_send_score ──────▶ IRサーバー
  csongmd5hash ──────┤     (ir.hsp:38)              |
                     |                               |
IRログイン情報       |                               v
  ksm_id ────────────┘                        レスポンス
                                                     |
                                                     v
                                              ir_popup_set_text
                                              (ir.hsp:77)
                                                     |
                                                     v
                                              ポップアップUI
                                              (画面右下 170px幅)

FX-L+R長押し ──────▶ ir_send_chart ──────────▶ IRサーバー（チャート登録）
(500ms以上)          (ir.hsp:42)
                           |
                           v
                     ir_send_score ──────────▶ IRサーバー（スコア再送信）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ir.hsp | `src/ir.hsp` | ソース | IRモジュール。ポップアップUI（init/set_text/draw）、スコア送信、チャート登録、URLエンコード機能 |
| result.hsp | `src/scene/result.hsp` | ソース | リザルト画面。IR送信トリガー、ポップアップ表示呼び出し、FX-L+R長押し検出 |
| kshootmania.hsp | `kshootmania.hsp` | ソース | 定数定義（IMG_IR_POPUP, ksm_id）、メインエントリーポイント、IR初期化 |
| rc4_crypt.hsp | `third_party/rc4_crypt.hsp` | サードパーティ | RC4暗号化（IR通信で使用される可能性） |
| alib_hash.as | `third_party/alib_hash.as` | サードパーティ | MD5ハッシュ計算（チャートハッシュ生成に使用） |
