プロジェクト

全般

プロフィール

機能 #313

完了

ノーツレーダー6軸の細分化データモデル設計(弱点分析 #293 の前提整備)

機能 #313: ノーツレーダー6軸の細分化データモデル設計(弱点分析 #293 の前提整備)

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

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

100%

予定工数:

説明

目的

#293(弱点分析・地力推定パネル)の前提として、既存のノーツレーダー6軸(NOTES / PEAK / SCRATCH / SOFLAN / CHARGE / CHORD)を、より細かい音ゲー特性(単皿・連皿、LN拘束、最大1秒密度…等)へ細分化した内部データモデルの設計を先行検討する。本チケットの成果物は設計(採用方針の決定)であり、実装・パネル本体は別チケット(#293 ほか)で行う。

#293 ユーザーメモの「6軸を拡張したもっと細かい音ゲーデータを保持したほうがいいかもしれない。先にこちらを検討」を受けたもの。

スコープ

  • 対象: 細分化サブ軸の定義、データ取得方式、保持(スキーマ)方式、集計・正規化方式、既存6軸との関係、段階導入計画の決定。
  • 対象外: #293 の弱点分析パネルそのものの実装(未着手のまま保留)。弱点判定で比較する「全体平均」の定義は本設計確定後に #293 側で別途決定する(ユーザー指示)。

現状のデータパイプライン(調査結果)

6軸レーダー値は次の経路で算出・保持されている。

  1. beatoraja 本体が算出: bms.player.beatoraja.song.NotesRadarCalculator#calculate(BMSModel)NotesRadarFeature(約30フィールドの record)を生成。譜面ロード時 SongDataModelMapper#apply() で呼ばれる。
  2. SongData には最終6値のみ保持: featureNotesDensity / featurePeakDensity / featureScratchDensity / featureSoflan / featureCharge / featureChord(各 0〜200 にスケール済み)。NotesRadarFeature が持つ生メトリクス約24個は SongData に載らず破棄される
  3. plugin が伝送: bms.player.beatoraja.ir.IzuIRConnectionIRChartData)が上記6値を feature_* キーで ChartDataDto.valuesMap<String,String>)に詰めて送信。
  4. server が保持: ScoreService#upsertSong()chart.values() から feature_* を読み、songs テーブルの radar_notes / radar_peak / radar_scratch / radar_soflan / radar_charge / radar_chordDOUBLE PRECISION, マイグレーション V9__add_song_radar.sql)へ格納。エンティティは SongEntity
  5. 集計: PlayerNotesRadarAxis(enum, 軸→列マッピング)と PlayerNotesRadarQueryRepositoryaggregate / topEntries)が、mode='7' に限定し、各譜面の達成率 min(exscore/(notes*2), 1.0) で重み付けし、軸ごと上位10譜面を平均して 0〜200 値を返す。PlayerNotesRadarService#radar()/detail()

重要な含意: 細分化に必要な生データの多くは beatoraja 内部で既に計算されているが伝送・保持されていない。よって細分化は本質的に「解析の露出 → 伝送 → スキーマ → 集計」の拡張であり、新規の重い譜面解析はサブ軸の一部に限られる。

細分化サブ軸の提案とデータ源マッピング

ユーザー例の各サブ軸を、取得可能性で A: 既存計算の露出のみ / B: 新規解析が必要 に分類する。B は izu-ir 側で BMSModelTimeLine / Note / NormalNote / LongNote / Mode#isScratchKey)から追加算出する想定。

SCRATCH(皿)

サブ軸 定義(案) 区分 データ源 / 備考
単皿 孤立した皿の量 B 皿総数 scratchTotal から連皿分を除く。新規判定要
連皿 短間隔で連続する皿の密度 A寄り scratchPeakWindowNotes(3秒窓内皿数)を流用可。窓定義の精緻化は B
皿複合 皿と鍵盤が同時/近接する密度 B 皿タイムライン近傍の鍵盤数。新規解析
終盤皿 譜面終盤(末尾x%)の皿密度 B 「終盤」の定義(末尾何%か)要決定
皿直後鍵盤 皿の直後一定時間内の鍵盤量 B 皿後ms窓の鍵盤カウント。新規解析

CHARGE(LN/CN)

サブ軸 定義(案) 区分 データ源 / 備考
LN数 LN/CN 総本数 A longNoteTotal
LN拘束 LN の累積拘束時間 A longNoteSecondsTotal
LN中鍵盤 LN保持中に押す通常鍵盤量 A/B chargeNotesDuringLongNote(鍵盤/皿合算)。鍵盤のみへ分離は B
LN中皿 LN保持中の皿量 B 上記から皿のみ分離。新規解析
LN終端密度 LN終端付近のノーツ密度 B LN終端ms窓の密度。新規解析

PEAK(密度ピーク)

サブ軸 定義(案) 区分 データ源 / 備考
最大1秒密度 1秒窓の最大ノーツ数 B 既存は3秒窓 peakWindowNotes。1秒窓は新規
最大5秒密度 5秒窓の最大ノーツ数 B 新規窓
最大10秒密度 10秒窓の最大ノーツ数 B 新規窓
終盤ピーク 譜面終盤のピーク密度 B 「終盤」定義に依存
局所難率 局所的な難所の集中度 B 指標定義要決定(密度分散/上位窓比など)

SOFLAN / CHORD も同様に細分化余地あり(soflan* 系メトリクス、chordTimelineCount / maxChordSize / chordPeakWindowNotes 等)。本チケットで全軸の最終サブ軸セットを確定する。

データ取得の実現方式(要決定)

  • 案A: beatoraja の生メトリクスを SongData 経由で露出
    • NotesRadarFeature の生フィールドを SongData に載せ、plugin で feature_* に追加する。
    • 長所: 既存計算の再利用。短所: beatoraja 本体の改変に依存し、izu-ir が特定 beatoraja ビルドに強く結合する(脆い)。サブ軸の一部(B分類)はそもそも未計算。
  • 案B: izu-ir plugin 側に独自アナライザを実装(推奨)
    • plugin 内に NotesAnalyzer を新設し、beatoraja の BMSModel 系モデルクラスから全サブ軸を izu-ir 独自に算出
    • 長所: 軸定義を izu-ir が完全制御でき、beatoraja 内部実装に非依存。A/B 双方のサブ軸を一元的に扱える。短所: 解析ロジックの新規実装コスト。
    • 要確認(重要): スコア送信時に plugin が BMSModel(または BMS ファイル)へアクセスできるか。アクセス不可なら譜面ロード時にキャッシュして送信時に参照する設計が必要。

保持(スキーマ)方式(要決定)

  • 案1: songsradar_* 列を追加し続ける — 既存踏襲だが、〜15+列で列爆発・マイグレーション肥大。
  • 案2: 正規化テーブル song_chart_feature(song_sha256, axis_key, value, updated_at)(EAV) — 軸追加がデータ行追加で済み、集計クエリも axis_key で汎用化。推奨
  • 案3: songs.chart_features JSONB — 柔軟だが集計クエリ・型保証が弱い。

伝送層は ChartDataDto.values(任意キーの Map)が既に汎用なので、いずれの案でも plugin→server 互換性は高い。

集計・正規化方針

  • 既存同様、各サブ軸を 0〜200 アンカーテーブル方式でスケールし、達成率 min(exscore/(notes*2), 1.0) 重み付け+軸ごと上位N平均を踏襲。
  • 既存6軸は親カテゴリとして残し、サブ軸はそのドリルダウンとして表現(後方互換・UI 段階導入)。

#293 への接続

  • サブ軸の average を「親軸グループ平均」または「本人全サブ軸平均」と比較して弱点サブ軸を抽出する余地が生まれる。
  • 「全体平均」の具体定義(本人内平均 / 全プレイヤー横断平均)は、本設計でサブ軸セットが確定した後に #293 側で決定する。

段階導入計画(案)

  • Phase 1: A分類(既に算出済み or 軽微な算出)サブ軸の露出・伝送・保持・集計。
  • Phase 2: B分類(皿直後鍵盤・終盤系・1/5/10秒窓・局所難率・LN終端密度・LN中皿)の新規解析実装。
  • 各 Phase は別 機能 チケットとして起票予定。

未解決の検討事項(Open Questions)

  • plugin がスコア送信時に BMSModel / BMS ファイルへアクセスできるか(案B の前提)。
  • 「終盤」の定義(末尾何 % / 何秒か)。
  • 「局所難率」の具体指標定義。
  • スキーマ案(1/2/3)の最終選択。
  • 既存 songs 行のバックフィル方針(新サブ軸は再プレイ/再ロードまで NULL になる扱い)。
  • 全軸の最終サブ軸セット(SOFLAN/CHORD 含む)の確定。

テスト方針(将来実装時)

  • plugin: NotesAnalyzer 単体テスト(既知譜面で各サブ軸値の境界・期待値)。
  • server: 集計クエリ/正規化の境界テスト、コントローラ 404。
  • web: パネル描画・i18n(#293 側)。

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

関連している beatoraja - 機能 #145: ノーツレーダー機能完了いづ さん2026/06/09

操作
次のチケットに先行 beatoraja - 機能 #314: ノーツレーダー細分化 Phase 1: A分類サブ軸の露出・IR伝送・EAV保持・集計完了いづ さん2026/06/222026/06/22

操作

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