追加仕様 詳細設計(2026-06-13)本体側¶
親 #162 に対する追加表示要素の本体側設計。既存の「MainController.changeState() を唯一の更新funnelとする」方針を基本踏襲しつつ、GAS によるゲージ種別のプレイ中変化だけは追従用の副経路を追加する。
追加する表示要素と取得元¶
| 要素 |
取得元 |
更新タイミング |
| ランダムオプション(1P) |
BMSPlayer.getOptionInformation().randomoption を Random.getRandom(id, mode) 経由で名称化 |
changeState→PLAY(静的) |
| ランダムオプション(2P/DP) |
randomoption2(DP/バトル時のみ) |
同上 |
| ゲージオプション(現在値) |
BMSPlayer.getGauge().getType() を名称化 |
初期: changeState、以後: GAS変化時
|
| GAS On/Off・モード |
PlayerConfig.getGaugeAutoShift()(GAUGEAUTOSHIFT_NONE=Off) |
changeState(静的) |
| ランダムレーンパターン |
BMSPlayer.getOptionInformation().laneShufflePattern[0](RANDOM/R-RANDOM時のみ) |
changeState→PLAY(静的) |
| プレーヤー名 |
PlayerConfig.getName() |
起動時/常時 |
| 取得段位 |
新規 PlayerConfig フィールド(手動設定文字列) |
起動時/常時 |
| 一言(目標など) |
新規 PlayerConfig フィールド |
起動時/常時 |
取得段位・一言はユーザー判断により「手動設定の文字列を PlayerConfig に保持しランチャーUIで設定」とする。
重要:GAS のリアルタイム更新(既存funnelの限界)¶
GAS=on 時、ゲージ種別は BMSPlayer のプレイループ内(BMSPlayer.java:643-677 の GAS 処理ブロック)で gauge.setType(...) により切り替わる。これは changeState() を通らないため、既存の「changeState のみで ObsState を更新」方式では追従できない。
対応方針:
-
ObsState に in-play 用の軽量更新 API(例: updatePlayGauge(int gaugeType))を追加。playing フェーズのスナップショットのうちゲージ表記だけを差し替え、volatile 参照を入れ替える。
-
BMSPlayer 側に直近反映済みのゲージ種別を保持し、GAS 処理直後に 種別が変化したときのみ ObsState を更新(毎フレーム呼ばない/obsEnabled でガード)。
-
スレッド安全性は維持:
changeState() も BMSPlayer.update() も同じゲームスレッドから呼ばれるため単一ライタ。HTTP スレッドは volatile スナップショットを読むだけでロック不要、という #181 の前提を崩さない。
レーンパターン(仕様C)は laneShufflePattern がプレイ開始時に確定し以後不変のため副経路は不要。changeState(PLAY) で BMSPlayer 生成(MainController.java:263)後にスナップショットへ格納する。
/state.json スキーマ拡張¶
profile(全phase共通・常時)を追加し、nowPlaying に playOption を追加する。表記済み文字列で渡し、HTML 側は流し込むだけ、の方針は維持。
{
"phase": "select | playing | result",
"profile": {
"name": "izu",
"dan": "発狂八段", // 手動設定 (PlayerConfig)
"comment": "目標:皆伝" // 手動設定 (PlayerConfig)
},
"nowPlaying": {
// ...既存フィールド...
"playOption": {
"random": "R-RANDOM", // 1P
"random2": null, // DP/バトル時のみ
"gauge": "HARD", // ★GASでライブ更新される現在のゲージ
"gaugeAutoShift": true, // On/Off
"gaugeAutoShiftMode": "BEST CLEAR",
"lane": "3 1 6 4 2 7 5" // RANDOM/R-RANDOM時のみ。他はnull
}
},
"lastResult": { /* 既存 */ },
"session": { /* 既存 */ }
}
表記の整形(本体側で確定)¶
既存配列・enum を流用する。
- ランダム名:
{OFF, MIRROR, RANDOM, R-RANDOM, S-RANDOM, SPIRAL, H-RANDOM, ALL-SCR, RANDOM-EX, S-RANDOM-EX}(PlayConfigurationView の scoreOptions と同一インデックス。R-RANDOM = Random.ROTATE)。PMS(9K) は OPTION_PMS 準拠。
- ゲージ名:
{ASSIST EASY, EASY, NORMAL, HARD, EX-HARD, HAZARD, CLASS, EX-CLASS, EXHARD-CLASS}(GrooveGauge の type 定数 0–8 に対応。コース/段位プレイの CLASS 系も含めて網羅)。
- GAS モード名:
{NONE, CONTINUE, SURVIVAL TO GROOVE, BEST CLEAR, SELECT TO UNDER}(GAUGEAUTOSHIFT_* 0–4)。
- レーンパターン:
IntegerIndexPropertyTypes.getAssignedLane()(#180)と同等のロジックで laneShufflePattern を整形(割当元レーン番号をスペース区切り)。#180 と重複するため共通ヘルパへの切り出しを推奨。RANDOM/R-RANDOM(=ROTATE) のみ対象(spec準拠。EX/CROSS 系は将来拡張余地)。
設定(Config / PlayerConfig)¶
-
PlayerConfig に String dan(取得段位)と String obsComment(一言)を追加。getter/setter と PlayerConfigPersistenceDto への追加、デフォルト空文字。
- ランチャー
PlayConfigurationView(プレイヤー設定タブ)にテキスト入力欄2つを追加。FXML・コントローラのバインド・リソースバンドルのキーを同期。
-
obsEnabled / obsPort(既定 7322)は本チケット既存設計のまま。
- 既存設計どおり
bms.player.beatoraja.stream.obs に ObsState ほかを配置。整形ヘルパ(ランダム名/ゲージ名/GAS名/レーンパターン)も同パッケージへ。
動作確認の想定¶
7K 譜面を RANDOM + GAS=BEST CLEAR でプレイし、http://localhost:7322/now-playing.html を開く。ランダム=RANDOM、レーンパターン=置換列、ゲージが初期 HARD から GAS 発動で NORMAL/EASY 等へ1秒ポーリングでライブに変化、GAS バッジ On、プロフィールに名前/段位/一言が表示されることを確認する。
本コメントは詳細設計であり実装着手前。ステータスは変更していない。