ダイアナボート

ボートレース(競艇)全場無料予想サイト ダイアナボート(V4.27.102)

旧サイトの予想一覧画面。ボートレース三国・びわこの「予想 / 結果 / 払戻」が横に並んだ表
Episode.7

Astro + React で作った最初のクローズドサイト

大穴はレース単位だったが、3連単予想も始めたことでなんらか予想結果の確認をする画面が必要となった。手組みコーディング時代のボートレース予想サイトのフロントエンド実装について紹介しておく。

2026年9月23日5

目次

このエピソードを執筆している2026年9月、AI技術界隈では Jev(ジェブ)※1 ※2が盛り上がっている。僕はまだ触ったことはない(早期アクセスが埋まっているのかアカウントが作れない)が、ニュースサイトや Youtube などの要約をパッと見て新しいクラス分類モデルでも出たのか?と勘違いしてしまった。

Jev をボートレース予想に利用できる余地はあるだろうか。特徴量作成の部分で活用できる可能性があると思う。後のエピソードで詳しく紹介するが、僕は展示レースの動画解析にもチャレンジしている。もし Jev が動画でも利用できるようになり、動画から特徴量の抽出を安価に行えるのであれば、試してみる価値はありそうだ。

話がそれたが、今回のエピソードでは初期(2024年夏から11月頃)のフロントエンド実装について記録しておく(このフロントエンドは改良とモデルの微修正を重ね、2025年7月まで原型を留めた)。この時点では築地の知り合いだけがアクセスする noindex サイトだ。


SSG - Static Site Generation

この時点では URLを知っている人だけがアクセスするサイトであったため、パフォーマンスなど非機能的な品質をそこまで上げる必要はない。だが仕事がないEpisode.6参照)ので、大量のアクセスが発生するメジャーサイトになる事を妄想しつつ、構築するのも良いではないか。

当時の予想モデルは、EV(Expected Value: 期待値)算出なども行っていないためオッズは不使用、少なくともその日の天気予報データが精度が悪くとも気象庁から事前に取得できれば、他の特徴量と合わせて予想できる。

つまり、この当時は朝一括で全レースの予想を生成し、予定されている各レースの締切時間から加算してレース結果時間を算出、1日あたり 120〜156回(その日の開催場の数による)ページをビルドして生成しておけば良かったのである。(以前 Episode.2 でも述べたが、現在は各レースの「直前情報」から随時気象データを取得している)

もちろん、悪天候や転覆などで締切時間が変わる場合のハンドリングは必要だが、ページビュー毎にデータを取得しなくてもいい。ということで、SSG を実現する Astro※3 + React※4 を採用した。

ただ、今思うと僕にはもう少し黒い気持ちがあったかもしれない。この規模ではわざわざ SSG にする必要もないのだ。

直前まで勤めていた会社は、Headless CMS の会社で独自の SSGアーキテクチャを提供していた。6年近くその製品に付き合った。Astro を勉強しようと思ったのは、ある意味その製品アーキテクチャへの薄暗い対抗心、あるいは反発のようなものだったかもしれない。

デザイン

僕はデザイナーの能力はまったく持ち合わせていない。それでも人に見せるサイトだ。まずは体裁としてロゴを作った。大穴→ダイアナだけに穴のあいたシンプルなモチーフ。現在も当初のロゴのままだ。

だが、1つ謎がある。このロゴのフォント名がわからないのだ。WhatTheFont※5 などのサービスも使ったがはっきりしない。記録もない。この Mac に入っている 956 書体すべてで組んで突き合わせたが、一致するものは無かった。なかなか良いフォントだと思う。

次に予想画面だ。ボートレースは毎日開催される。気になったときにすぐ予想と結果を確認できるように、モバイルファーストで配置を決めた。スマホで横に2場ずつ。予想とその結果があれば払戻金額とともに1行で表示されるスタイル。どうしても文字が小さくなるため、枠の色と数字の視認性向上に苦労した。スタイルには Tailwind※6 を利用した。

モデルの精度推移や予想の的中率なども Recharts※7 を使って描画した。(これらのグラフは現在のサイト公開を機に裏の非公開管理画面のみでの表示となっている。)

当時の画面を記録として一部掲載しておこう。

現在の予想モデルと比べるとあまりにも精度が低い(16.829% は大穴レースの的中率)。が、今後のエピソードでどのように改善したのか紹介していく。

デプロイ

サイトのデプロイに関しては、正直何も考えず AWS Amplify を利用してしまった。当時この Amplify でのビルドにコストが結構かかることがわかっていれば採用はしなかったと思う。

結局コスト増のために、各レース結果分のビルドではなく、20分毎の定期的なビルドに変更していた。(現在のサイトは、ISR + Lambda で 5分おきに温め直す感じだ。)

2024年12月当時の予想サイトの1日のタスクは、以下のようになっていた。

時刻 タスク
04:30 24場ぶんの学習が始まる
〜06:25 学習が終わり、サイトを丸ごと再ビルド
07:00 当日の出走表を収集(24場)
07:40 24場ぶんの予想を生成 → 終わって再ビルド
日中 20分ごとに再ビルド
23:20 レース結果とオッズを収集(24場)

大穴予想の格下げ

先のスクリーンショットでも想像できるとおり、僕の大穴予想モデルは使い物になっていない状況だった。当初の目標「大穴レースがわかれば、全-全-全 120通り、12,000円賭ければいいんじゃね?」は、恐ろしくて実行できない。(Hさん、実現できずごめんなさい。)

当初TOPページだった大穴予想ページは格下げとなり、800予想(〇-〇-全 x2 の 8通り3連単)がTOPページとなった。

手組み時代の終焉

さて、今回で「手組み時代の予想システム構築」の記録は一区切りである。あらためて失敗や試行錯誤の連続の1年7ヶ月だった。もちろん学んだ事の方が多い。次回のエピソードでは、この手組み時代で学んだ事と2025年7月までの予想モデルの遷移の話を加え総括する。そして、AIバイブコーディングによる新予想システムの構築に進みたいと思う。

そうだ。もう一つ共有しておく。僕は、2024年10月1日に再就職することができた。会社の規模が小さいためより責任が伴うが働きがいのある環境である。(現在も在籍している。)

そして、いつものようにタイミング悪く、入社日の 10月1日に M-1グランプリの 1回戦に出場した。まさか入社日に重なるとは思っていなかったのだ。M-1グランプリの予選時間は吉本がアサインしてしまうのだ。入社早々かなり気まずかったが、失業期間のすばらしい記念となった。

つづく。

AstroReactTailwindRechartsSSGAmplifyJevM-1グランプリ一回戦敗退

関連情報

  1. TypeSafe AI(公式サイト) TypeSafeJev を作った AI ラボ。Jev は同社が「System One Model」と呼ぶ新しいモデル区分の第一弾で、人との会話ではなくソフトウェアの自動判断に向けて、型のついた確率つきの判断を返す。
  2. Introducing System One Models & Jev Diogo Almeida(TypeSafe、2026-09-15)Jev の発表記事。文字列を1トークンずつ生成する代わりに、プログラムの状態を入力として型つきの判断を1回の並列パスで返す。同等のタスクで既存のフロンティアモデルより 40〜200倍速い、入力100万トークンあたり $0.042 といった主張はここが出典。なお入力は現時点でテキストと構造化された状態のみで、画像・動画には未対応と明記されている。
  3. Astro(公式サイト) withastro(オープンソース)コンテンツ中心のサイト向けの web フレームワーク。既定では JavaScript をブラウザに送らず(Zero JavaScript, By Default)、動きが要る部分だけを島のように切り出して動かす Islands Architecture を採る。当時は 4.7 系。
  4. React(公式サイト) Meta とオープンソースコミュニティUI をコンポーネントの組み合わせとして書く JavaScript ライブラリ。Astro の「島」として、チャートなど動きのある部分だけをこれで書いた。
  5. WhatTheFont Font Finder MyFonts(Monotype)文字が写った画像をアップロードすると、データベースと照合して書体の候補を返すフォント判定サービス。似た書体の提案も出る。
  6. Tailwind CSS(公式サイト) Tailwind LabsHTML の class に `flex` や `pt-4` のような小さな部品を並べてデザインを組み立てるユーティリティファーストの CSS フレームワーク。画面幅ごとの出し分けも `sm:` `lg:` の接頭辞で書ける。当時は 3.4 系。
  7. Recharts(公式サイト) Recharts(github.com/recharts/recharts)React コンポーネントとして書けるグラフライブラリ。描画は SVG で、内部で D3 の一部を使っている。精度の推移や的中率の折れ線はこれで描いた。