操作
バグ #426
完了IRに露出する totalDuration が実プレー時間でなく判定ズレ総和になっている
バグ #426:
IRに露出する totalDuration が実プレー時間でなく判定ズレ総和になっている
説明
背景¶
izu-ir #425「1曲しかプレーしてないのに本日のプレイ時間が『569時間3分』になる」の調査で、根本原因が beatoraja 側の totalDuration 計測にあると判明した。
#277 で IRScoreData に露出した totalDuration の仕様は「単一プレーの実経過時間(ミリ秒):完走なら曲丸々、途中終了ならそこまで、選曲画面等は除外」だが、実際にセットされている値はプレー時間ではない。
原因¶
bms.player.beatoraja.play.PlayScoreDataBuilder#setJudgeDuration が、avgjudge(平均判定ズレ)算出用の中間値 avgduration を、そのまま score.setTotalDuration(avgduration) に流用している。
private static void setJudgeDuration(ScoreData score, BMSModel model) {
long count = 0;
long avgduration = 0;
...
long time = n.getMicroPlayTime();
avgduration += state >= 1 && state <= 4 ? Math.abs(time) : 1000000;
count++;
...
score.setTotalDuration(avgduration); // ← バグ: 判定ズレ総和であって経過時間ではない
score.setAvgjudge(avgduration / count); // ← 本来の用途(平均判定ズレ)
}
-
avgdurationは「全ノートの判定ズレ絶対値Math.abs(n.getMicroPlayTime())の総和(未判定ノートは 1,000,000 マイクロ秒のペナルティ)」で、avgjudge = avgduration / count(平均判定ズレ)を出すための分子。 -
n.getMicroPlayTime()の実体はJudgeManager#updateMicroでn.setMicroPlayTime(mfast)(mfast = 判定の早遅ズレ・マイクロ秒・符号付き)としてセットされる値で、recentTimings.record(mfast)でも使われる判定精度の値。プレー経過時間ではない。 - 結果、
totalDurationはノート数に比例して肥大化し、単位もマイクロ秒。izu-ir 側はこれをミリ秒のプレー時間として解釈するため、約20億 → 569時間 に化ける。- 本番実測:
chart_score_logs1行でtotal_duration = 2,048,601,381(≒569時間)。
- 本番実測:
対応方針¶
setJudgeDuration 内で avgjudge 計算はそのまま維持し、totalDuration には「最後に判定されたノートの曲内時刻(ミリ秒)」を設定する。TimeLine#getMilliTime() がミリ秒の曲内時刻。
long playDurationMillis = 0;
...
if (state >= 1 && state <= 4) {
playDurationMillis = Math.max(playDurationMillis, tl.getMilliTime());
}
...
score.setTotalDuration(playDurationMillis);
score.setAvgjudge(count == 0 ? 0 : avgduration / count);
- 完走なら最終ノート ≒ 曲丸々、途中終了なら最後に叩いたノートまで、を満たし #277 の仕様に合致する。
- メソッド名
setJudgeDurationの責務(avgjudge)に対するtotalDuration混入を解消する。 - テスト追加: 判定済みノートの最大
milliTimeがtotalDurationに入ること、avgjudgeが従来通りであること。
izu-ir 側¶
- izu-ir 側のロジック変更は不要。修正版 beatoraja.jar 取り込み後、以降に送られる値が正しくなる。
- #425 では本番の壊れた行(
player_id='izu',total_duration=2048601381)を0に是正する。
関連¶
- izu-ir #425(本件の発見元・569時間表示バグ)
- #277(
IRScoreDataへのtotalDuration露出)
エージェント ちゃん さんが10日前に更新
- ステータス を 未着手 から 実装中 に変更
- 進捗率 を 0 から 10 に変更
実装に着手しました。
- ブランチ:
feature/426 - 対応方針:
PlayScoreDataBuilder#setJudgeDurationでtotalDurationに判定ズレ総和(avgduration)を流用しているのを止め、判定済みノートの最大TimeLine#getMilliTime()(ミリ秒の曲内時刻)を設定するよう修正。avgjudgeの算出は従来どおり維持し、ゼロ除算ガードも追加。
エージェント ちゃん さんが10日前に更新
- ステータス を 実装中 から 完了 に変更
- 進捗率 を 10 から 100 に変更
対応が完了しました。
概要¶
IR に露出する totalDuration が、実プレー時間ではなく判定ズレ総和(avgjudge 用の中間値)になっていたバグを修正。ノート数に比例して肥大化し、izu-ir 側で約569時間と表示される原因だった。
変更点¶
-
PlayScoreDataBuilder#setJudgeDurationでtotalDurationにavgduration(判定ズレ絶対値の総和・マイクロ秒)を流用していたのを廃止し、判定済みノート(state 1〜4)のTimeLine#getMilliTime()(ミリ秒の曲内時刻)の最大値を設定するよう修正(完走なら曲丈々、途中終了なら最後に叩いたノートまで、#277 の仕様に合致)。 -
avgjudgeの算出は従来どおり維持し、count == 0の除算ゼロガードを追加。 - テストから呼べるようメソッドを
private static→ パッケージプライベートstaticに変更。 - 変更ファイル:
src/bms/player/beatoraja/play/PlayScoreDataBuilder.java、src/test/java/bms/player/beatoraja/play/PlayScoreDataBuilderTest.java(新規・テスト3件)
テスト¶
-
.\gradlew.bat test: 成功(新規PlayScoreDataBuilderTest3件 + 回帰確認としてplay.*/ScoreDataTest/ir.*すべてグリーン)
関連 MR¶
- !107 (feature/426 → develop)
操作