お久しぶりです. メリクリ!今年もぼっちだぜ(ヤケクソ)!!!
この記事はesys Advent Calendar 5日目(12/25分)の記事です.
ぼくはesys17で現在はimis21のM2です. *1
本記事では11月に行われた学祭の中のいち展示企画であるメイカー〆切祭に出展したオセロソフト dekunobouとの対戦コーナーの実装について解説しようと思います. メイカー〆切祭ってなんぞやって方は本アドカレ1日目で@skmmmpさんが書いてくれていますのでこちらをご覧ください.
概要
メイカー〆切祭でぼくは来場者の方々に自作のオセロAI dekunobouと対戦してもらう対戦コーナーを出展することになりました. オセロAIとの対戦コーナーは新型コロナウイルス流行前の学園祭でも出展しており, その際は人力で人間の着手をPCに入力し, 返ってきたAIからの着手を人間がオセロ盤に打つといういわゆる代指しを行うことで実現していました. しかしながら, 昨今の感染症拡大予防の風潮的に今回もこのような方法を取るのはよくなく, かつ実現方法に技術的進歩が見られないのはちょっとダサいと思ったので, 展示会場内でオセロソフトとの対戦用のWebサーバーを建てて来場者のスマートフォンからdekunobou と対戦できるようにしました. 本記事ではこの対戦システムについての解説を書きます.
実装したコードはこちらに上がっているので合わせてご覧下さい.
システム構成
オセロAIとの対戦システムのシステム構成は以下のとおりです. Raspberry PiをWiFiアクセスポイント兼Webサーバーとして, 来場者の方々にはここにアクセスしてもらうようにしました. そして, 別途AIの着手を生成するAPIサーバーをノートPCの方に建てて, Raspberry Pi に建てたWiFiアクセスポイントに接続しておき, クライアントが着手するたびに着手の生成をリクエストするようにしました. これは, Raspberry PiのCPUよりノートPCのCPUのほうが性能がよく, より速くそしてより強い着手を生成してくれるはずだと考えていたためです. また, このAPIサーバーにはデータベースを搭載し, ここにAIの戦績を記録するようにしました.
やりたかったこと
対戦システムでやりたかったことは以下のとおりです.
- レスポンシブ対応
- AIの戦績の記録と表示
- 先後選択機能の実装
- Captive Portal上への対戦ページの表示
- AIの強化(後日別の記事で解説する予定です)
これを, 昨年にWebで公開したオセロAI dekunobouとの対戦ページでの実装をベースにすることにしました. この実装はこちらに上がっています.
ここからはやりたかったことについて個別にどうやったかなど書いていこうと思います.
レスポンシブ対応
現在Webで公開中のオセロAIとの対戦ページではレスポンシブ対応を全くしていないため, スマートフォンからアクセスする場合は一度ユーザーが拡大しないとプレイできないという非常にユーザーアクセシビリティが悪い仕様になっています. そのため, 来場者の方に気持ちよくプレイしていただくため, レスポンシブ対応を行うことにしました. 学園祭本番までに実装する時間が限られていたこと, そして来場者のほとんど方はプレイする際スマートフォンを使用されるだろうということでモバイルのみレスポンシブ対応を行うことにしました. 実装はこちらをご覧ください.
github.com こちらに関しては後日PCのレスポンシブ対応も行った上でWebの方にも公開する予定です.
AIの戦績の記録と表示
来場者の方に自分のAIの強さを知っていただくには今のAIの戦績を表示するのが1番だと考えていました. そのため, コロナ前の学園祭でも黒板にAIの戦績を書いていました.
今回は対戦システムを通じて来場者の方に対戦してもらうため, 同時に複数の対局が行われることが予想され, 手動での集計は厳しいと考えていました. そのため, 戦績の記録と集計を自動で行うことにしました. 実現方法としてはよくある方法で, 対局が終了するごとにクライアントからリクエストを飛ばして勝敗と取った石の枚数を記録していくようにしました. データベースは今後自分のWebサイトでも戦績の表示を行いたいと考えていたため, Postgres SQLを使用しました. というのも公開しているWebページではAIの着手の生成にherokuを使用しており, herokuではPostgres SQLがサポートされているためです. この実装はこちらをご覧ください.こちらも今後Webの方に公開予定ですが今の実装だと脆弱性がありそうなので対策が必要だと考えています*2
先後選択機能の実装
Webに公開しているものだと人間は先手しか選べない仕様で, この仕様のままだと来場者の方に楽しんでいただけないと思っていました. そのため, こちらも実装することにしました. これは開発段階では優先度が低く(手番を選択できるかに関わらず動くものを出せるかのほうが重要なため)学園祭当日までの日数が限られていることを考えるとかなり優先度が低かったのですが, 時間が余ったため実装しました.
この実装はこちらをご覧ください.
Captive Portal上での対戦ページの表示
これが1番やりたかったことです. 今回, 純粋に来場者の方とAIの戦績を表示したかったため, 対戦システムはオンプレミスで設置するべきだと考えていました. そうすると取れる選択肢は来場者の方に対戦システムのローカルネットワーク上にアクセスしてもらうことしかありませんでした.
一般のユーザーからするとローカルネットワーク上にアクセスしてもらうのはこちらがWiFiアクセスポイントを建てておき, それに繋いでもらうことで簡単にできますが, そこからさらにもう1ステップ踏んでローカルネットワーク上のWebサイトにアクセスしてもらうのは難しいと考えていました. そのため, WiFiに接続時にブラウザが立ち上がって認証画面を表示するCaptive Portalを使用するのが最適だという結論になりました.
Raspberry PiにCaptive Portralを設定する記事があったのでこれを参考に設定を行いました.
しかしながら手元で動かしてみた結果Raspberry Piがインターネットに接続されていないとどうもCaptive Portalがうまく起動しないようだったので諦めてローカルネットワーク上に設置したWebサーバーにアクセスしてもらうことにしました. そして来場者の方にもわかりやすいように以下の写真のようにWebサーバーへのリンクをQRコードで表示しました.
実際の運用
当日, 来場者の方のスマートフォンでうまくアクセスできないときのための対策としてあらかじめ自分のiPadで接続しておき, これを常時対戦コーナーに設置しておくようにしました. これが功を奏し, 多くの来場者の方に対戦してもらえたと感じています.
反省点
今回の対戦システムの開発にあたって, iPhoneのテストはできていたのですがAndoroid端末が手元になくAndoroid端末でのテストができていませんでした. そのため, 結果としてAndoroid端末を使用されている方がうまく対戦システムに接続できないという問題が多発しました. ここは開発段階でAndoroid端末を持っている知り合いに声をかけてテストしてもらえばよかったなあと思っています. よくテストは大事だと言われていますが改めてテストの重要さを思い知りました.
最後に
今回初めてインフラ?周りからバックエンドそしてフロントエンドまで幅広い領域の開発を体験しました. 特にネットワーク周りの知識がなく, 本番当日までに間に合うかかなり不安でしたがなんとか間に合わせることができて良かったです. 開発中はなんか自分がつよつよになった感じがして気持ちよかったです.
オセロソフトのお世話してるとC++からCSSまで幅広く書くことになってフルスタック感がすごくてなんか自己肯定感上がる
— JJ1GUJ@WCSC33 11位 (@jj1guj) 2022年10月21日
今後就職したときとかに今回の経験を活かせるといいなあと思います.