プロジェクト

全般

プロフィール

バグ #426

完了

IRに露出する totalDuration が実プレー時間でなく判定ズレ総和になっている

バグ #426: IRに露出する totalDuration が実プレー時間でなく判定ズレ総和になっている

エージェント ちゃん さんが10日前に追加. 10日前に更新.

ステータス:
完了
優先度:
通常
担当者:
対象バージョン:
開始日:
2026/06/26
期日:
進捗率:

100%

予定工数:

説明

背景

izu-ir #425「1曲しかプレーしてないのに本日のプレイ時間が『569時間3分』になる」の調査で、根本原因が beatoraja 側の totalDuration 計測にあると判明した。

#277IRScoreData に露出した 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#updateMicron.setMicroPlayTime(mfast)mfast = 判定の早遅ズレ・マイクロ秒・符号付き)としてセットされる値で、recentTimings.record(mfast) でも使われる判定精度の値。プレー経過時間ではない。
  • 結果、totalDuration はノート数に比例して肥大化し、単位もマイクロ秒。izu-ir 側はこれをミリ秒のプレー時間として解釈するため、約20億 → 569時間 に化ける。
    • 本番実測: chart_score_logs 1行で 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 混入を解消する。
  • テスト追加: 判定済みノートの最大 milliTimetotalDuration に入ること、avgjudge が従来通りであること。

izu-ir 側

  • izu-ir 側のロジック変更は不要。修正版 beatoraja.jar 取り込み後、以降に送られる値が正しくなる。
  • #425 では本番の壊れた行(player_id='izu', total_duration=2048601381)を 0 に是正する。

関連

  • izu-ir #425(本件の発見元・569時間表示バグ)
  • #277(IRScoreData への totalDuration 露出)

関連するチケット 1 (0件未完了1件完了)

関連している beatoraja - バグ #427: ハード落ちなど途中終了した場合でも楽曲トータルのノーツ数がIRに送信されている完了いづ さん2026/06/26

操作

他の形式にエクスポート: PDF Atom