0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

マッチ・オブ・ザ・プレイヤー投票サービスを作ってみた

Last updated at Posted at 2025-10-01

きっかけ

10月に入るとBリーグ2025-2026が開幕するということでなにか応援することができないかと考えて思いついたのが、「試合観戦中に良いプレーをした選手に対して投票することができれば盛り上がるのではないか?」ということです。

Bリーグでは大きな試合で同様の試みが行われたようですが、それをもっと小規模・短時間でファンが結果をみて楽しめるものであり、一人一票と制限しなければ良いプレーを連発すればそれだけ得票数が増えるってのも面白いんじゃないかと思い、勉強がてら立ち上げたってことです。

で、バスケット界隈に不案内な私がなぜBリーグを選んだかといえば、登録選手やベンチ入り選手が少ないから、選手マストを作るのが楽だろうというそれだけの理由です。その後、ユニフォームの画像を準備するとか色々と手間がかかってしまいましたが、まあ全体でも15人程度で、私が好きなアメリカンフットボールでは100人近い登録がチームもあるのと比べれば、作業の総量が小さいことには間違いない。

技術仕様

一応Qiitaへ投稿するので、サービス稼働環境を書いときます。

github pages(フロント) <--> cloud run(API) <--> mongoDB Atlas(データベース)

フロントはhtml+javascript+cssで書いています。APIはflask+gunicornで動いていて、mongoDBへはcloud runで動くAPI経由でしかアクセスできません。

フロントからAPIへのアクセスは接続元URLを限定してやんわりと制限をかけています。一時的な大量アクセスも拒否するようなしくみを入れており、それらはflaskが提供するライブラリを利用しています。

APからmongoDBへはpymongoを利用してアクセスしています。

cloud run環境構築では、DockerFileではpython:3.13-slimと指定し、requirements.txtでは最新のライブラリがインストールされるようバージョン指定はしていません。

立ち上げてみての感想

コード自体は生成AIが大枠を書いてくれて、2,3日で基本的な処理が動くようになりましたが、一番手間がかかったのはUX部分です。

アリーナの観客席でスマホを使って投票することを前提としたので、デザインは基本スマホにあわせるよう入力欄や文字の大きさをちょこちょこ調整したりしました。

また一度動き始めても使っているうちにいろいろな機能を追加したくなった結果、データベースの構造が全く持って正規化されておらず、このあたりは思いつきで作り始めた弊害なんでしょう。ただし、複数のテーブルを読むということをなるべく少なくすることで、データベースアクセス時間を短くするとか、マスター系はキャシュに持たせていちいちアクセスしないとかちょっとした利便性を考えた機能は実装したつもりです。(そのかわり、選手マスタ更新しても反映されず、あれ?って思ったことが何回もありました。ブラウザ側のキャッシュの問題もあるし)

データベースについては正規化なんて微塵も考えずツギハギで作っていったのですが、NOSQLと呼ばれるmongoDBはその点で対応が柔軟で、新しく項目を追加してもそれ以前のデータと混在したところでエラーにはならず(レコードに存在しない項目があればしれっとNULLを返してくるだけ)、またテーブルを削除したあと再設定を忘れて動かしていると、勝手にテーブルが作られていたりなど、私のようなテキトーな人間にはとても優しくて大変気に入りました。(勝手に色々やってくれるぶん、間違いに気づかなかったりもしがちなのは事実だけど)

もちろんスクリプトを利用した大量の投票などは防止しなければなりませんが、ある程度の自由さで現地参戦ファンなどによる組織票も大いにありという寛大さを持ったただ楽しむことに集中するという、マネタイズもなにも全く意識していない仕組みとなっています。それくらい軽い気持ちで立ち上げたサービスですので、その点についてはまずご理解ください。

いずれにせよ、生成AIの力を全体の80%近く借りて立ち上げたサービスですが、github pagesやcloud run,mongoDBの環境設定についても色々と知ることができて大変面白かったです。

なお、このサービスでは公開されている選手の名前や背番号、所属チームの情報と投票された日時のみを登録しているだけなので、投票者関連の個人情報は一切取り扱っていません。本来ならば一人一票とか短期間での大量投票を防止するために、クッキーなどを利用することを考えるべきかもしれないし、いたずら投票を防止するためにユーザ認証をすることも必要かもしれません。しかし、誰でも気軽で自由に楽しめるという基本コンセプトを最初に宣言して作り始めたので、そういった物理的・心理的ハードルは極力排除するように心がけました。

{
  "_id": {
    "$oid": "xxxxxxxxxxxxxxxxxxxxxxx"
  },
  "team": "広島ドラゴンフライズ",
  "id": "HD02",
  "number": 1,
  "name": "市川 真人",
  "registration_date": {
    "$date": "2025-09-29T14:57:54.212Z"
  }
}
項目 説明
_id mongoDBが勝手に付番する管理番号(未使用)
team 所属チーム名
id 選手の判別コード(チームコード2桁+背番号2桁)
number 選手の背番号
name 選手名
registration_date データ登録時刻(UTC)

ランキング集計時にこのデータだけ参照して表示しようとしたので、チーム名や選手名はベタな日本語を登録しています。

最後に

あとは、実際にブースターのひとたちが使ってみてどうかってことですが、サービス立ち上げたことをXを中心にポストしても反応がほぼなし。気づくと1,2件とポツポツ登録してくれている形跡が見えるけれど、やっぱ怪しい得体が知れないサービスに接続するのは躊躇するのかなってことも考えます。まあそれだけセキュリティ意識が高くなってきて良いことではあるけれど。

おまけ

01.jpg

02.jpg

お暇なら自由に投票してみてください。広島ドラゴンフライズの開幕戦は10月4日ですので、現在の投票データは10月3日にクリアする予定です。

広くたくさんの人に使ってもらって色んな意見も聞きたいなって思ってて、そのための広報用画像も作ってたんだけど、そいつをXにポストしたら「紛らわしい画像をアップすることはファンやスポンサーに迷惑かけるかもしれんからダメですよ」ってメッセージがクラブ公式から届いたので、素直に削除しました。が、そのかわりの明らかに公式ではないと分かる画像を作ったので、そいつをおまけでのっけときます。

infomation.jpg

いじょうです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?