# 通知設計書 1-Twitterスコアシェア通知

## 概要

本ドキュメントは、K-Shoot MANIAのリザルト画面におけるTwitterスコアシェア通知機能の設計を記述する。プレイ結果（スコア・難易度・ランク・クリア種別）をTwitterに共有するための通知処理について、トリガー条件、テンプレート構成、処理フローを網羅的に定義する。

### 本通知の処理概要

本通知は、リザルト画面でプレイ結果をTwitterに共有する機能を提供する。ツイートボタンのクリックまたはFX-R+L同時押下をトリガーとして、スクリーンショットのクリップボードコピーとブラウザ経由でのTwitter Intent URLへの遷移を行う。

**業務上の目的・背景**：音楽ゲームにおいてプレイ結果をSNSで共有することは、プレイヤーのモチベーション向上とコミュニティの活性化に重要な役割を果たす。本通知は、K-Shoot MANIAのプレイ結果をTwitterに手軽に投稿するための機能であり、ゲーム体験の共有と認知度向上を目的としている。

**通知の送信タイミング**：リザルト画面が表示されてから768ms経過後、ユーザーがF11キー押下、ジョイスティックボタン13押下、または画面右上のツイートボタン（右端90px・上端24pxの領域）をマウス右クリックしたタイミングで発動する。さらにFX-L+FX-Rの同時押下でもツイートテキストとサイトURLが画面に表示される。

**通知の受信者**：Twitterのタイムラインを閲覧するフォロワーおよび一般ユーザー。実際のツイート投稿はプレイヤー自身がブラウザ上で確認・実行する。

**通知内容の概要**：曲名、アーティスト名、難易度（LT/CH/EX/IN）、レベル、クリア種別（FAILED/CLEARED/FULL COMBO/PERFECT等）、スコア（8桁ゼロ埋め）、ハッシュタグ「#kshootmania」を含むテキスト。コース時はコースタイトルも先頭に付加される。

**期待されるアクション**：プレイヤーがブラウザで開かれたTwitter Intent画面でツイート内容を確認し投稿する。また、クリップボードにコピーされたスクリーンショットをCtrl+Vで画像添付することが案内される。

## 通知種別

ソーシャルシェア通知（外部ブラウザ経由のTwitter Web Intent）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ユーザー操作トリガーで即座にブラウザ起動） |
| 優先度 | 低（ユーザー任意のアクション） |
| リトライ | なし（ブラウザ起動のみ、投稿はユーザー責任） |

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

送信先はTwitterのWeb Intent URL（`https://twitter.com/intent/tweet`）固定。受信者の決定はTwitterプラットフォーム側に委ねられ、プレイヤーのフォロワーがタイムラインで受信する。

## 通知テンプレート

### メール通知の場合

本通知はメールではなくTwitter Web Intent方式のため、メール関連項目は該当しない。

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A |
| 送信元名称 | N/A |
| 件名 | N/A |
| 形式 | URL（Twitter Web Intent） |

### 本文テンプレート

```
{コースタイトル（コース時のみ）}
{曲名} / {アーティスト名}
[{難易度略称}] Lv{レベル} {クリア種別} (SCORE: {8桁スコア})
{カスタムハッシュタグ（conf.ini tweet_option由来）} #kshootmania
```

具体例:
```
Example Song / Example Artist
[EX] Lv15 CLEARED! (SCORE: 08765432)
#kshootmania
```

ASSIST使用時:
```
Example Song / Example Artist
[EX] Lv15 ASSIST CLEARED! (SCORE: 08765432)
#kshootmania
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| スクリーンショット | BMP（クリップボード） | ツイートボタン押下時に自動コピー | リザルト画面のスクリーンショットをクリップボードにコピー。ユーザーがCtrl+Vで手動添付 |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| _csongtitle | 曲タイトル（UTF-8エンコード済み） | csongtitle変数（KSHファイルのtitle=行） | Yes |
| _csongartist | アーティスト名（UTF-8エンコード済み） | csongartist変数（KSHファイルのartist=行） | Yes |
| _ccoursetitle | コースタイトル（UTF-8、コース時のみ） | ccoursetitle変数 | No |
| stat2 | 難易度略称（LT/CH/EX/IN） | csongdifficulty変数（0-3） | Yes |
| csonglevel | レベル値 | csonglevel変数（KSHファイルのlevel=行） | Yes |
| stat1 | クリア種別テキスト | stat6（クリア状態0-3）とeffratetype（ゲージ種別）から決定 | Yes |
| stat3+stat4 | 8桁ゼロ埋めスコア | totalscore変数 | Yes |
| dirtweetopt | カスタムハッシュタグ | conf.iniのtweet_option設定 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | F11キー押下 | リザルト画面表示後768ms経過、tweetfl=0 | キーボードのF11キーによるツイート発動 |
| 画面操作 | ジョイスティックボタン13押下 | リザルト画面表示後768ms経過、tweetfl=0 | ゲームコントローラーのボタン13によるツイート発動 |
| 画面操作 | ツイートボタン右クリック | 画面右上領域内でのマウス右クリック、tweetfl=0 | 画面右端90px×上端24px領域のボタンクリック |
| 画面操作 | FX-L+FX-R同時押下 | リザルト画面表示後768ms経過 | 詳細情報（アプリ名・URL）を画面表示。直接ツイートは発動しない |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| tweetfl=1 | 既にツイート処理が発動済みの場合、再度のツイートを抑止 |
| リザルト画面表示後768ms未満 | 画面遷移直後の誤操作防止のため、768ms経過するまでツイート操作を無効化 |
| ginfo2()!=0 | ウィンドウが非アクティブの場合は操作を受け付けない |
| click_keyp=1 | 前フレームで既にクリックされていた場合（連続クリック防止） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[リザルト画面表示] --> B[ツイートテキスト生成]
    B --> C{768ms経過?}
    C -->|No| D[入力待機]
    D --> C
    C -->|Yes| E{ツイートトリガー検出?}
    E -->|No| D
    E -->|Yes| F{tweetfl=0?}
    F -->|No| D
    F -->|Yes| G[tweetfl=1に設定]
    G --> H[BUF_RESULT_TWEETバッファに画面コピー]
    H --> I[ClipB_SetBmpでクリップボードにスクリーンショットコピー]
    I --> J[ダイアログ表示：スクリーンショットコピー完了通知]
    J --> K[tweet_textをURLエンコード]
    K --> L[exec命令でブラウザ起動：Twitter Intent URL]
    L --> M[終了]
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。ゲーム内変数およびKSHファイルの譜面データから情報を取得する。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | ファイルベースのデータ管理 |

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

該当なし。

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| N/A | N/A | データベース更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ブラウザ起動失敗 | デフォルトブラウザが設定されていない場合 | OS側のexec命令に委ねる。アプリ側でのエラーハンドリングなし |
| クリップボードコピー失敗 | クリップボードアクセス権限がない場合 | 明示的なエラーハンドリングなし |
| UTF-8エンコード失敗 | 特殊文字を含む曲名の場合 | isutf8フラグに基づきBOM付きUTF-8またはShift-JISからの変換で対処 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（ただしtweetflフラグにより1リザルト画面につき1回） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

時間帯制限なし。リザルト画面が表示されている間のみ操作可能。

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

- ツイート内容はプレイデータのみで個人情報を含まない
- Twitter Intent URLを使用するため、OAuth認証等のトークン管理はTwitter側に委ねる
- URLエンコードはurlencode関数で実施し、特殊文字のインジェクションを防止
- tweet_text変数は最大140*3バイト(420バイト)に制限される（`sdim tweet_text,140*3`）

## 備考

- tweet_notifytype変数で通知状態を管理し、表示期間は1200msに設定されている（result.hsp 818行目: `tweet_notifyt+1200>t-time_scene_start`）
- conf.iniのtweet_option設定（dirtweetopt変数経由）でカスタムハッシュタグを追加可能
- コースモード時はコースタイトルが先頭行に追加される
- ASSIST使用時（shortmode+longmode+analogmode>0）は「ASSIST」プレフィックスがクリア種別に付加される
- スクリーンショットのクリップボードコピー完了後にダイアログが表示され、Ctrl+Vでの画像添付を案内する

---

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

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

### 推奨読解順序

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

まず、ツイートテキスト生成に使われる変数群を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | result.hsp | `src/scene/result.hsp` | ツイート関連変数（tweet_text, tweet_notifytype, tweetfl, _csongtitle, _csongartist）の定義を確認 |
| 1-2 | kshootmania.hsp | `kshootmania.hsp` | IMG_RESULT_TWEETBTN（166番）、BUF_RESULT_TWEET（183番）の画像バッファ定数定義を確認 |

**読解のコツ**: HSP3言語の変数はグローバルスコープが基本で、`sdim`は文字列変数の初期化、`dim`は整数配列の初期化を行う。`stat`系変数はHSP3の組み込み一時変数で、result.hsp内ではstat1〜stat6が別目的で再利用されるため注意が必要。

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

処理の起点はリザルト画面の初期化関数`on_update_result`である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | result.hsp | `src/scene/result.hsp` | `on_update_result`関数がリザルト画面全体の処理を担当 |

**主要処理フロー**:
1. **509-582行目**: ツイートテキストの生成。UTF-8エンコード、クリア種別テキスト決定、スコアフォーマット、ハッシュタグ付与
2. **621-623行目**: ツイートキー入力の検出（F11キー・ジョイスティック）
3. **625-627行目**: マウスクリックによるツイートボタン検出
4. **629-633行目**: ツイートフラグの設定とトリガー処理
5. **830-841行目**: ツイート実行処理（クリップボードコピー、ダイアログ、ブラウザ起動）

#### Step 3: ツイートテキスト生成ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | result.hsp | `src/scene/result.hsp` | 509-582行目: クリア種別（stat6）とゲージ種別（effratetype）の組み合わせからツイートテキストを構築するロジック |

**主要処理フロー**:
- **510行目**: `click_keyp=1`, `tweet_keyp=1` - 前フレーム入力状態の初期化
- **513-519行目**: コースモード時のコースタイトル処理（UTF-8エンコード）
- **520-526行目**: 曲名・アーティスト名のUTF-8エンコード
- **527-555行目**: stat6(0-3)とeffratetype(-1,0,1)に基づくクリア種別テキスト生成
- **556-558行目**: ASSIST使用時のプレフィックス追加
- **564-572行目**: 難易度略称の決定（csongdifficulty: 0=LT, 1=CH, 2=EX, 3=IN）
- **573-580行目**: 最終ツイートテキストの組み立て

#### Step 4: ツイート実行処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | result.hsp | `src/scene/result.hsp` | 830-841行目: ブラウザ起動とクリップボード処理 |
| 4-2 | ir.hsp | `src/ir.hsp` | 122-127行目: urlencode関数の実装（URLエンコード処理、ハイフンとドットのデコード） |

**主要処理フロー**:
- **832-833行目**: BUF_RESULT_TWEETバッファにリザルト画面をコピー
- **834行目**: `ClipB_SetBmp`でクリップボードにスクリーンショットをコピー
- **835行目**: `tweetfl=0` - ツイートフラグリセット
- **836行目**: ダイアログ表示（スクリーンショットコピー完了通知）
- **839行目**: `urlencode`でツイートテキストをURLエンコード
- **840行目**: `exec`命令でTwitter Intent URL（`https://twitter.com/intent/tweet?text=...`）をブラウザで開く

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

```
on_update_result (result.hsp:1)
    |
    +-- [ツイートテキスト生成] (result.hsp:509-582)
    |       +-- utf8enc() : Shift-JIS to UTF-8変換
    |       +-- stat6/effratetype判定 : クリア種別テキスト生成
    |
    +-- [メインループ] (result.hsp:606-849)
    |       +-- [入力検出] (result.hsp:621-628)
    |       |       +-- getkey 122 : F11キー検出
    |       |       +-- getjoykeystat(13) : ジョイスティック検出
    |       |       +-- マウスクリック検出 : 画面右上領域判定
    |       |
    |       +-- [通知表示] (result.hsp:818-822)
    |       |       +-- IMG_RESULT_TWEETBTN描画
    |       |       +-- tweet_notifytype/tweet_notifytでアニメーション
    |       |
    |       +-- [ツイート実行] (result.hsp:830-841)
    |               +-- ClipB_SetBmp : スクリーンショットコピー
    |               +-- dialog : 完了通知ダイアログ
    |               +-- urlencode (ir.hsp:122-127)
    |               +-- exec : ブラウザ起動
```

### データフロー図

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

KSHファイル
  csongtitle ────────┐
  csongartist ───────┤
  csongdifficulty ───┼──▶ ツイートテキスト生成 ──▶ tweet_text変数
  csonglevel ────────┤     (result.hsp:509-582)
                     |
プレイ結果           |
  totalscore ────────┤
  stat6(クリア状態) ─┤
  effratetype ───────┘

conf.ini
  dirtweetopt ──────────▶ ハッシュタグ追加 ──────▶ tweet_text変数

ユーザー操作
  F11/ボタン/クリック ──▶ ツイート実行処理
                           (result.hsp:830-841)
                              |
                              +──▶ クリップボード (スクリーンショット)
                              +──▶ ブラウザ (Twitter Intent URL)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| result.hsp | `src/scene/result.hsp` | ソース | リザルト画面処理。ツイートテキスト生成・入力検出・ツイート実行のメイン処理 |
| ir.hsp | `src/ir.hsp` | ソース | URLエンコード関数（urlencode/urlenc/utf8enc_auto）の実装 |
| kshootmania.hsp | `kshootmania.hsp` | ソース | 定数定義（IMG_RESULT_TWEETBTN, BUF_RESULT_TWEET等）、メインエントリーポイント |
| play_chart_load.hsp | `src/scene/play/play_chart_load.hsp` | ソース | KSHファイル読み込み。csongtitle, csongartist, csongdifficulty, csonglevelの設定 |
| mod_encode.hsp | `third_party/mod_encode.hsp` | サードパーティ | UTF-8エンコード/デコード処理（utf8enc関数） |
| clipboard.as | `third_party/clipboard.as` | サードパーティ | クリップボード操作（ClipB_SetBmp関数） |
