ミキサーのUIを全部テンキー化したら、確定判定バグがもう一つ見つかった話 〜函館ダークマター係数1.000 vs 0.766比較検証まで シリーズ第7弾〜
予想屋yuji ― 71歳・隠居・Ubuntu・Python独学。競馬予想AIを半年間開発中。
前回記事:ミキサーに3つの構造バグが潜んでいた話 〜発見・修正・函館係数変更の結果まで
はじめに
「入力しづらい」
函館のダークマター係数を変更する作業中、何度も半角数字・アルファベット小文字・全角漢字を切り替えながら入力する羽目になった。V6.4で[t]キーを新設したときに増えた入力経路が、ここで限界を迎えた。
UIを全面テンキー化すれば解決する。そう決めて着手したところ、V6.4で一度直したはずの「確定判定」のロジックに、また同じ種類のバグが見つかった。
直したはずの場所が、また漏れていた。
5日間(6/18〜6/19)の作業内容と、その後の函館ダークマター係数の比較検証、そして月をまたいで実現したYouTube初投稿までを報告する。
今週の変更サマリー
| No. | 日付 | 内容 | 分類 |
|---|---|---|---|
| No.57 | 06/18 | apply_screen テンキー化 | 改善 |
| No.58 | 06/18 | venue_screen テンキー化 | 改善 |
| No.59 | 06/18 | horse_dist_screen テンキー化 | 改善 |
| No.60 | 06/19 | venue_screen [3]自動集計後の適用選択を全面再設計 | 再設計 |
| No.61 | 06/19 | proposals表示ラベル改称(確定→推奨/暫定→参考) | 改善 |
| No.62 | 06/19 | [4]検証ダークマター係数スキップバグ修正 | BUGfix |
UI全面テンキー化(No.57〜61)
V6.4期間で新設した[t]キー(暫定項目個別確認)など、入力インターフェースが「半角数字・アルファベット小文字・全角漢字混在」という状態になっていた。函館ダークマター係数の変更作業中に「入力しづらい」という問題が顕在化し、No.57〜61で全面テンキー化を実施した。
apply_screen・venue_screen・horse_dist_screenの入力受付箇所をすべてテンキー数字選択に統一(No.57〜59)。
venue_screen [3]の全面再設計(No.60)
旧[1][2](確定項目一括追加)・旧[3](会場指定一括追加)はユーザーの意図確認なしにpendingへ放り込む設計だった。これはV6.4で発覚した「問題A」(推奨値を確認なしに確定値として扱っていた事故)と同じ危うさを残していた。旧[4](暫定項目1件ずつ確認)だけが安全な設計だった。
全入力経路をテンキー数字選択に統一し、意図確認なしの一括反映経路を廃止。全経路でy/N確認を経る設計に変更した。
表示ラベルの改称(No.61)
| 区分 | 変更前 | 変更後 |
|---|---|---|
| N≧10の項目 | 確定 | 推奨 |
| N<10の項目 | ✅暫定(N=n) | 参考(N=n) |
「確定」という表示は「適用済み」と読めてしまう。実態は「推奨値ですよ」というだけなので、誤読を避けるために改称した。既存CSVに旧値('確定'/'✅暫定')が残っている場合も、チェックロジック側で両方受け入れるよう後方互換対応済み。
[4]検証モードに再発したダークマター係数バグ(No.62)
発覚の経緯
函館のダークマター係数を0.766→1.000に変更・保存した後、[4]検証モードを実行したところ、係数変更前と検証結果が完全に同一になるという事象が発生した。
V6.4のNo.54で「[4]がハードコードされた5月時点の推奨値を参照していた」問題は直したはずだった。だが今回はそれとは別の場所に、似た構造のバグが残っていた。
原因
調べると、以下の2点が不整合を起こしていた。
| 項目 | 内容 |
|---|---|
| calc_venue_proposals()の仕様 | ダークマター係数のtentativeを、サンプル数に関わらず常に'-'固定で返す |
| _vk_run_kensyou()の判定 |
if p.get('tentative') not in ('推奨', '確定'): continue となっており、'-'がこのタプルに含まれていなかった |
結果、ダークマター係数は[4]検証で常にスキップされ、new_factorsに反映されないままcurrent_factorsのコピーが使われ続けていた。
実は同じ「'-'=確定相当」という判定は、V6.4のNo.57で_is_kakutei()にすでに実装済みだった。
# V6.4 No.57で修正済みの_is_kakutei()
def _is_kakutei(p):
t = p.get('tentative', '')
return t == '確定' or t == '-' # ダークマターは'-'→確定扱い
ところが_vk_run_kensyou()は別の関数として独立に実装されていたため、この判定が反映されていなかった。「直したはずの場所」ではなく、「直したロジックと同じはずなのに実装が分かれていた場所」が漏れていた。
修正内容(No.62)
判定タプルに'-'を追加。
# 修正前
if p.get('tentative') not in ('推奨', '確定'): continue
# 修正後
if p.get('tentative') not in ('推奨', '確定', '-'): continue
今回の教訓
_is_kakutei()と_vk_run_kensyou()は同じ「確定判定」を行っているが、実装タイミングが異なるため判定条件が乖離していた。今後も同様のロジックが追加された場合は両者の一致を必ず確認すること。
函館ダークマター係数 1.000 vs 0.766 比較検証
No.62修正前の段階で、函館ダークマター係数(現在値1.000)を推奨値0.766に変更した場合の検証を[4]モードで実施。その後、No.62修正によりバグが解消されたため、改めて1.000と0.766の比較検証が有効に実施された。
検証結果サマリ(函館24レース)
| 指標 | 現在係数(1.000) | 推奨係数(0.766) |
|---|---|---|
| 1着的中率 | 25.0%(6/24) | 20.8%(5/24)▼-4.2pt |
| 3着内的中率 | 41.7%(10/24) | 41.7%(10/24)±0.0pt |
| 1位馬が変わったレース | ― | 8件/24件(改善6件・悪化2件) |
1着的中率は1.000側が優位。3着内率は変化なし。0.766による悪化2件は、いずれも現行係数で既に的中(1着・2着)していた馬を外してしまったケースであり、改善6件より影響が大きかった。
ただしN=24は函館シーズン(6/12〜7/19)の序盤サンプルであり、mixer自動集計のN=22〜24で0.766が推奨されている根拠の安定性にも注意が必要。函館ダークマター係数は当面1.000のまま継続し、Nが増えた段階で再検証する方針とした。
おまけ:YouTube初投稿とBUY的中
V6.6期間の作業はここまでだが、月をまたいだ6/20〜21に、半年間積み上げてきたものの「出口」がもう一つ動いた。
予想出力をもとにした動画制作チャンネル「隠居ジジィの競馬予想チャンネル」を開設し、初投稿に踏み切った。台本生成→VOICEVOXで音声化→Claudeがffmpegで画像と同期合成、という手順を確立するまでに、動画編集アプリVrewとの相性不一致など一通りの試行錯誤があった。
投稿日の6/21、動画内でBUY最推しとして紹介した阪神12R・タガノアバンドーネ(指数差6.33pt×騎手Sランク)が1着。複勝110円で回収率110%。
初投稿のレースで、複勝特化アルゴリズムが初めて実戦で機能したことを確認できた。
まとめ
| 項目 | No. | ステータス |
|---|---|---|
| UI全面テンキー化 | No.57〜60 | ✅ 完了 |
| 表示ラベル改称(確定→推奨) | No.61 | ✅ 完了(後方互換対応済み) |
| [4]検証ダークマター係数スキップバグ | No.62 | ✅ 解決済み |
| 函館ダークマター係数 1.000 vs 0.766 | ― | 🔄 検証済み・1.000継続・再検証待ち |
UIを使いやすくする作業のはずが、その過程で「直したつもりだったロジックの未統一」という別の構造問題を見つけることになった。同じ判定を複数の関数が別々に持っている場所は、今後も増えていくはずなので、横展開チェックの習慣はこれからも欠かせない。
次回V6.6以降では、函館シーズンが進んでNが蓄積した段階でのダークマター係数再検証と、V5py押しレース精度向上に着手する予定。
今週の気づき
「直したつもりの場所が、また漏れていた。同じロジックを二度書くと、二度同じバグを作る」
制作者:yuji(@yujiiwadate0247)― 予想屋yuji 競馬予想システム V6.6期間 2026/06