リバーシ(オセロ)で遊べる箱庭リバーシを作ってみました。
対NPC戦・対人戦、どちらもできます。
もともとリアルタイムDBを使った対人戦ゲームの勉強がてら作っていたのですが、ついでにオセロAIとかも少し調べて実装してみました。
自分がオセロ素人なのでアレですが、NPCの中でも箱庭娘は地味に強くなった気がしますので、遊んでみてください。
以下、技術談義。
もうずっとアプリばかり作っていて、Web技術が完全におろそか&時代遅れな感じになっていたので、少しでも取り戻そうと勉強。
SPAとかPWAとか、そんな感じです。
(service workerは調整してもキャッシュがきつくて、思うように更新できず、いったん外してあるので、正確にはPWAにはなっていないのですが・・)
フロンドエンドはVue.js。laravelいじってた時の名残で、laravel-mixかませつつ、webpack使ってる感じです。
バックエンドはFirebase。基本無料なのと、リアルタイムDBに惹かれて使ってみました。
実験的なサービスのためにいちいち実費でサーバー(VM)借りて、環境設定してソフト入れてSSLも・・とかやらずに済むのでとても楽。
ホスティングのdeployやロールバックもとても簡単。
Firestoreも取り扱いがめっちゃ楽で、1時間経たずにリアルタイムな動きができてテンション上がったんですけど、だんだんとセキュリティ的に面倒なことに気付いてテンション下がり気味に・・
なんかこう、サーバー使ってる時のクセで、うちのドメインから以外はAPI接続禁止すればOKだよね、みたいのイメージしてたんですけど、いやいやこれJavaScriptでクライアントがダイレクトにつないでるやんけ・・どうするの・・的な。
で、これについてはFirestore側でJavaScript風コードでセキュリティルール策定するんですけど、微妙に手間がかかるのがネック。
NoSQLとかドキュメントベースのDBに慣れてないせいもあるのかもですが・・
結局コレクションごとのスキーマ的なものを書き、
createやupdateのパターンごとにバリデータ的なものを書き・・
ってこれなら、フィールドと型をあらかじめ設定できるほうが楽なんじゃ、と思いつつ。
テストもしづらいし。
セキュリティルールはとりあえず、
allow write: if request.auth.uid != null
とか、一応
allow write: if request.auth.uid != null && request.resource.data.title is string && request.resource.data.title.size() <= 100
みたいのでいいかなー、とか意外と軽く考えるかもですが、例えばこのルールだと確かにtitleは100文字以下の文字列に絞れるんですけど、逆にtitleが100文字以内であれば、fooとかいうフィールドに1万文字入れたリクエストなんかも通っちゃうんですよね。
なので
allow write: if request.auth.uid != null && request.resource.data.keys().hasOnly(['title']) && request.resource.data.title is string && request.resource.data.title.size() <= 100
みたいにしてゴリゴリ限定していく方向で・・。
これを全コレクション全フィールドでやるんだよ、おらぁ。
ちなみにrequest.resource.dataってのは、やってきたデータだけじゃなくて、更新後のresource.dataのイメージなので、更新するドキュメントにtitle以外のフィールドがあったりすると、hasOnlyにならなくて弾かれるぞ。ハマりポイント。
だからね、最初にね、全フィールド計画的にしようね。
サービスイン後にフィールドいじりたくなったら、メンテかけるか、止めたくなければ、バージョンフィールド作って、その値を元にバージョン別のセキュリティルール適用すればいいんじゃないかと思います。
あと他にも、Authenticationとか、許可済みコールバックにlocalhostが入ってたりするの、リリース時に消しておこうねっていう。
なんというか、今までと勝手が違う環境で、罠が多い・・
Firebase自体はまだベータな雰囲気がいろいろあるので、これからに期待したいです。