プロジェクト

全般

プロフィール

機能 #316

完了

ノーツレーダー細分化 Phase 3: B分類パターン軸の 0–200 anchor 実データ較正と本体正規化

機能 #316: ノーツレーダー細分化 Phase 3: B分類パターン軸の 0–200 anchor 実データ較正と本体正規化

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

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

100%

予定工数:

説明

目的

#313 設計の数値後決め事項(§8)のうち、B分類パターン軸の 0–200 正規化を担う後続チケット。Phase 2 (#315) で算出済みの 15 個の B分類サブ軸 raw 値に対し、実データ分布から 0–200 anchor テーブルを確定し、既存6主軸と同様に本体 NotesRadarCalculator で正規化する。

親設計: #313。前提: Phase 2 (#315) の raw 算出・伝送・保持縦串。

方針確認(ユーザー指示, 2026-06-19): anchor は server 側ではなく本後続チケットで決定する。設計 §8-9 の推奨(本体で anchor 正規化+raw も併送)に沿う。

対象 raw サブ軸(#315 で送出済み・全て raw)

  • NOTES: notes_density_peak_10s / notes_endgame
  • PATTERN(新規親): pattern_jack / pattern_trill / pattern_kaidan / pattern_randa
  • CHORD: chord_gachioshi / chord_denim / chord_jika
  • SCRATCH: scratch_single / scratch_ren / scratch_complex
  • RHYTHM(新規親): rhythm_24th / rhythm_henpyoshi / rhythm_irregular

スコープ

  1. 実データ収集: 実譜面群を全更新で再計算し、各 raw サブ軸の分布(分位点)を採取(#145 と同方式のバックフィル)。
  2. anchor テーブル確定: 既存6軸(NOTES_DENSITY_ANCHORS/NOTES_RADAR_ANCHORS 等)と同型の *_SCORE_ANCHORS / *_RADAR_ANCHORS を raw 分位点から決定。raw が count か density(/s) か(duration 正規化)も合わせて確定。
  3. 本体正規化の実装: NotesRadarCalculator.calculate で各サブ軸を radarFromAnchors(...) で 0–200 化。raw も併送を維持(#315 の feature_* raw 伝送は残す)。PATTERN / RHYTHM の親軸 0–200 値を新設するかも本チケットで決定(ドリルダウン用、#293 接続)。
  4. テスト: anchor 区間の境界(直下/直上)・単調性・0/200 クランプ、既存6軸と raw 値の不変(回帰)。

数値後決め事項(設計 §8 のうち本チケット該当)

  • §8-1: 全パターン軸の 0–200 anchor テーブル(実 raw 分布の分位点)。
  • §8-2: jack/trill/階段/連皿の ms 閾値を固定 ms か BPM 相対か(再調整)。
  • §8-3: 乱打エントロピー閾値・窓長 K の再調整。
  • §8-4: 皿複合の随伴窓 T_fukugo・寄与重み。
  • §8-5: デニム/ガチ押し size 閾値・密度ゲート。
  • §8-6: リズム off-grid 許容 T_offgrid_ratio・24分許容幅。
  • §8-9: パターン軸 raw を本体正規化(本チケットで本体採用)+raw 併送の責務分界。

関連

  • #313(設計)/ #314(Phase 1)/ #315(Phase 2: raw 算出)
  • #293(弱点分析・地力推定パネル)への接続(親→サブのドリルダウン)。

備考

Phase 2 で導入した暫定閾値(T_JACK_MS=110 等)と暫定アルゴリズムは、本チケットの実データ較正で確定値へ差し替える。閾値は定数差し替えで完結する設計。


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

次のチケットに後続 beatoraja - 機能 #315: ノーツレーダー細分化 Phase 2: B分類(パターン認識)サブ軸の新規解析実装完了いづ さん2026/06/232026/06/23

操作
次のチケットに先行 beatoraja - 機能 #317: ノーツレーダー細分化: CHARGE/LN サブ軸の新設と BSS の LN 再分類完了いづ さん2026/06/252026/06/25

操作

エージェント ちゃん さんが17日前に更新 操作 #1

  • 期日2026/06/24 にセット
  • 開始日2026/06/19 から 2026/06/24 に変更
  • 次のチケットに後続 機能 #315: ノーツレーダー細分化 Phase 2: B分類(パターン認識)サブ軸の新規解析実装 を追加

いづ さん さんが17日前に更新 操作 #2

DevContainer内では実データを作成できないので、まずはローカル環境で作成する必要がある

エージェント ちゃん さんが17日前に更新 操作 #3

  • ステータス未着手 から 実装中 に変更
  • 進捗率0 から 10 に変更

実装に着手しました。

  • ブランチ: feature/316
  • 対応方針: 実データ待ちの間に、データ非依存の**構造部分(15サブ軸の0–200正規化値・PATTERN/RHYTHM親軸の新設・raw併送維持・縦串配線・構造テスト)**を暫定線形anchorで先行実装。anchor数値の実データ較正(§8-1)と閾値再調整(§8-2〜8-6)はローカル採取CSV到着後に同ブランチで後続コミットする(定数差し替えで完結する設計)。

エージェント ちゃん さんが17日前に更新 操作 #4

サーバー側(izu-ir)引き継ぎ資料 — ノーツレーダー全特徴量の伝送仕様

本体(beatoraja)側で #314/#315/#316 を通じて実装した特徴量を、スコア送信時に IRChartData.valuesMap<String,String>)として feature_* キー81個で IR へ送出する。サーバーは集計・保持・正規化・#293接続が責務。以下はサーバー実装に必要な全情報。

0. 最重要の注意(命名の非対称)

  • 6主軸は歴史的経緯で _radar 接尾辞なしだが 0–200 正規化済みfeature_notes_density / feature_peak_density / feature_scratch_density / feature_charge / feature_chord / feature_soflan
  • サブ軸raw=接尾辞なし正規化=_radar 接尾辞。例:feature_pattern_jackrawfeature_pattern_jack_radar0–200 正規化
  • したがって「_radar が付くもの+6主軸」が 0–200 値、それ以外(6主軸を除く接尾辞なし feature_*)は raw。

1. 81キーの分類

(A) 0–200 正規化値=33個(サーバーは原則これを再正規化しない)

  • 6主軸(接尾辞なし):feature_notes_density / _peak_density / _scratch_density / _charge / _chord / _soflan
  • 新規親軸2個:feature_pattern_radar / feature_rhythm_radar(子サブ軸 _radar の単純平均)
  • A分類サブ軸 _radar 10個 / B分類サブ軸 _radar 15個

(B) raw 値=48個(サーバーが独自正規化したい場合に利用可)

  • 6主軸の生入力・中間量23個(feature_notes_total / _duration_seconds / _peak_window_notes / _scratch_total / _scratch_peak_window_notes / _ln_total / _ln_seconds_total / _charge_notes_during_ln / _charge_notes_during_ln_peak_window / _max_simultaneous_ln / _chord_timeline_count / _max_chord_size / _chord_peak_window_score / _chord_peak_window_notes / _speed_change_count / _stop_count / _scroll_change_count / _soflan_weighted_notes / _soflan_cluster_count / _soflan_affected_notes / _soflan_cluster_score / _soflan_max_change_rate / _soflan_stop_time_total
  • A分類 raw 10個・B分類 raw 15個(下表)

2. ドリルダウン木構造(#293 親→サブ)

親軸(0–200キー) 子サブ軸(raw / 正規化=_radar
NOTES feature_notes_density notes_density_peak_1s, notes_local_hardness, notes_density_peak_10s, notes_endgame
PEAK feature_peak_density peak_burst_1s, peak_sustained_3s
SCRATCH feature_scratch_density scratch_bss, scratch_single, scratch_ren, scratch_complex
CHARGE feature_charge (サブ軸なし)
CHORD feature_chord chord_max_size, chord_gachioshi, chord_denim, chord_jika
SOF-LAN feature_soflan soflan_accel, soflan_decel, soflan_stop, soflan_visual
PATTERN(新規)feature_pattern_radar pattern_jack, pattern_trill, pattern_kaidan, pattern_randa
RHYTHM(新規)feature_rhythm_radar rhythm_24th, rhythm_henpyoshi, rhythm_irregular

親軸値:feature_pattern_radar = (jack+trill+kaidan+randa の各 _radar)/4、feature_rhythm_radar = (24th+henpyoshi+irregular の各 _radar)/3。NOTES/PEAK/SCRATCH/CHORD/SOF-LAN は既存6主軸値がそのまま親。

3. 正規化方式(0–200)

  • 既存6主軸と完全に同一方式:raw を分位点アンカー(*_SCORE_ANCHORS)→ 固定14点 radar カーブ {0, 14.29, 35.71, 71.43, 100, 116.95, 133.90, 150.85, 167.80, 184.75, 191.53, 194.92, 198.31, 200} へ線形補間。実装は NotesRadarCalculator.radarFromAnchors
  • パーセンタイル方式:アンカーは実譜面 52,449件の raw 分布の分位点。採用分位点列 ≈ [0, 12.3, 34.2, 64.7, 82.5, 85.9, 88.9, 91.8, 94.4, 96.8, 97.9, 98.3, 99.0, 99.3]%(既存 NOTES 軸アンカーから逆算し全軸で共有)。
  • 意味:radar 値は「母集団内の難度順位」を表し、全軸で radar≈100 が同じパーセンタイル帯に対応=軸横断比較が可能(#293 の弱点抽出前提)。
  • 外れ値耐性:最上位アンカー(≈99.3%ile)超は 200 にクランプ。min-max ではないので極端譜面でスケールが歪まない。導出は本体リポジトリ scripts/analyze_notes_radar.py(B分類)/ scripts/analyze_notes_radar_aclass.py(A分類)で再現可能。

4. raw の count / density 区分(正規化入力)

正規化は軸ごとに「累積イベント数=秒速 density(/duration)」「rate/ratio/size=raw のまま(intensive)」を使い分け(duration 相関分析に基づく)。サーバーが raw から独自に再正規化する場合は同じ区分を踏襲すること。

  • DENSITY(/秒):notes_endgame, pattern_jack/trill/kaidan/randa, chord_gachioshi/denim/jika, scratch_single/ren/complex, rhythm_24th, soflan_stop, soflan_visual, scratch_bss
  • INTENSIVE(raw):notes_density_peak_10s, rhythm_henpyoshi, rhythm_irregular, notes_density_peak_1s, notes_local_hardness, peak_burst_1s, peak_sustained_3s, chord_max_size, soflan_accel, soflan_decel

5. 特例・留意点

  • soflan_visual は非ゼロが全体の約0.1%。母集団分位点だと全アンカー0=任意正値が200飽和(退化)するため、この軸だけ非ゼロ部分集合で較正(アンカー約47譜面ベース)。サーバーが集計する際もこの軸はサンプル数が極小である点に留意。
  • 疎な軸(例 chord_denim 非ゼロ21%、soflan_accel/decel 約20%):母集団パーセンタイル正規化の性質上、「そのパターンを少しでも持つ=少数派」なので radar が高めに出る。仕様どおりだが #293 の閾値設定時に考慮を。
  • アンカーは母集団(採取譜面群)依存:将来 anchor を更新する場合は gradle updateAllSongs--all)で全件再計算→songdata.dbsong テーブルから feature_* を CSV エクスポート→上記 scripts 実行→定数差し替え、で完結する設計(本体側作業)。
  • ms 閾値(T_JACK_MS=110 等)は設計§5の暫定値を据え置き。raw 算出ロジックは固定。

6. 集計責務(サーバー側)

  • 本体は 0–200 正規化+raw 併送まで。サーバーは既存6軸と同じ集計(達成率重み min(exscore/(notes*2), 1.0)・軸ごと上位N平均・EAV保持)をサブ軸へ拡張する想定。
  • 既に 0–200 のキー(6主軸+_radar+親軸)を二重正規化しないこと。 独自正規化したい場合のみ raw キー(§1-B)を使用。
  • 各サブ軸の集計上位N(設計§8-7)、soflan accel/decel/visual の二重計上回避重み(§8-8)はサーバー側で後決めの未確定事項。

7. 値の性質

  • feature_*譜面ごとに決定的(プレイ内容に依存しない譜面特徴)。文字列化は Double.toString
  • 旧スキーマ/旧クライアント互換:未知キーは EAV なので無痛。本体DBも auto-ALTER で列追加のみ(既存値不変)。

8. 参照

  • 設計:本体リポジトリ docs/notes-radar-subdivision-design.md(§8' に #316 確定状況)
  • 実装:NotesRadarCalculator / NotesRadarFeature(81 component) / IRChartData
  • 関連チケット:#313(設計)/ #314(A分類raw)/ #315(B分類raw)/ #316(本チケット=全サブ軸 0–200 正規化)/ #293(弱点分析パネル)

エージェント ちゃん さんが17日前に更新 操作 #6

  • ステータス実装中 から 完了 に変更
  • 進捗率10 から 100 に変更

対応が完了しました。

概要

ノーツレーダー細分化 Phase 3。#314(A分類10)/#315(B分類15) で raw のみだった全サブ軸を、既存6軸と同一のパーセンタイル方式で実データ較正し 0–200 正規化。raw 併送維持。主軸6+全サブ軸25 が「raw+0–200」で揃い、サーバー(izu-ir) へ完全なデータを渡せる状態になった。

変更点

  • B分類15軸+親軸2(PATTERN/RHYTHM)を 0–200 正規化(Phase 3a 構造 → 3b 実データ較正)。
  • A分類10軸を 0–200 正規化(Phase 3c)。NotesRadarFeature 54→81 component。A分類は既存主軸配下のため新規親軸なし。
  • 較正は実譜面 52,449件 のローカル全更新バックフィルの raw 分布から。既存 NOTES 軸アンカーのパーセンタイル方式を逆算し、同方式・同14点 radar カーブを全サブ軸へ適用(軸横断で radar 値が比較可能)。
  • count/density を軸ごとに個別判断(duration 相関)。累積カウントは density(/s)、rate/ratio/size は raw(intensive)。
  • soflan_visual のみ非ゼロ部分集合較正(非ゼロ0.1%で母集団だと全アンカー0=200飽和の退化を回避)。
  • 既存6軸は完全に不変(develop とバイト一致を検証、回帰テスト green)。IR 送出 feature_* キーは 81。
  • 変更ファイル: NotesRadarCalculator.java / NotesRadarFeature.java / SQLiteSongDatabaseAccessor.java / SongDataDto.java / SongDataResultSetHandler.java / IRChartData.java +テスト3+scripts/analyze_notes_radar.py / analyze_notes_radar_aclass.pydocs/notes-radar-subdivision-design.md(§8') + .gitignore
  • サーバー引き継ぎ資料(81キーの分類・ドリルダウン木・集計責務・再較正手順)は本チケットの前コメントに記載済み。

テスト

  • xvfb-run -a ./gradlew test : 成功(全 green)。各サブ軸の正規化値を feature 自身の raw+duration から再計算し一致検証、アンカー→radarカーブ一致、単調性・クランプ・親=子平均・既存6軸&raw不変回帰・EMPTY・DTO往復・旧スキーマ0埋め・IRキー81。

関連 MR

  • !70 (feature/316 → develop, マージ済み)

エージェント ちゃん さんが16日前に更新 操作 #7

  • 次のチケットに先行 機能 #317: ノーツレーダー細分化: CHARGE/LN サブ軸の新設と BSS の LN 再分類 を追加

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