機能 #181
エージェント ちゃん さんが24日前に更新
親: #162
## 担当範囲
OBS 連携のうち **beatoraja 本体側**。状態の収集・保持と、ローカル HTTP サーバによる配信を担う。
## 設計
### コンポーネント
- **ObsState** — スレッドセーフな現在状態の保持。更新時に不変スナップショット(または完成済み JSON 文字列)を生成し `volatile` 参照に差し替える方式で、ゲームスレッド/HTTP スレッド間のロックを不要にする。
- **SessionStats** — セッション統計。`MainController` 既存の `boottime` を起点に起動時初期化し、リザルト到達時に加算。
- **ObsHttpServer** — `com.sun.net.httpserver.HttpServer` を利用。スレッドは既存 `RuntimeTaskManager.startVirtual(...)`(`StreamController` と同じ流儀)で回す。
### 接続点
- **`MainController.changeState(MainStateType)`(MainController.java:248)** を唯一の更新funnelとして利用。全画面遷移がここを通るため、状態クラスを侵食せず最小改変で phase(select / playing / result)と曲情報・スコアを `ObsState` に反映できる。
- 曲情報/スコアの取得元は **`PlayerResource`**(model / songdata / score を保持)。
### /state.json スキーマ(暫定)
判定済みの表記文字列で渡し、HTML 側は流し込むだけにする方針。
```jsonc
{
"phase": "select | playing | result",
"nowPlaying": {
"title": "...", "artist": "...", "genre": "...",
"level": "★12", "mode": "7K",
"bpm": "150-200", "notes": 1234,
"bestLamp": "HARD", "bestScore": "AAA 92.3%"
},
"lastResult": {
"title": "...", "lamp": "FULLCOMBO", "rank": "AAA",
"exscore": 2345, "diff": "+58", "updated": true
},
"session": {
"playCount": 14, "clearCount": 11,
"startedAt": "2026-06-12T20:00:00", "newRecords": 3
}
}
```
### 設定
- `Config` に `obsEnabled` / `obsPort`(既定値の例: 7322)を追加。
- MVP は設定ファイル直書きのみ。ランチャー UI へのトグル追加は後追い。
- バインドは localhost 固定。
### 配置
- 新規パッケージ案: `bms.player.beatoraja.stream.obs`(既存 stream パッケージと同系統)。
- 静的ファイル(#182 の HTML)は同サーバから配信する。