はじめに
当記事で作成したアプリ
アプリ名 : ポケカルキュレーター
記事を読む上での注意点
当記事は、プログラミング学習を始めて4ヶ月の業界未経験者が書いたものなので、技術的な内容などは誤りを含む可能性があります。あらかじめご了承ください。
開発背景
「ポケットモンスター スカーレット・バイオレット」が発売してから早くも4ヶ月が経ちました。皆さんはポケモンバトルを楽しんでいますか?
私はテラピース集めが大変で、あまり対戦には参加できていませんが、なんとか毎期マスターボール級まで到達することができています。
さて、それはそれとして、私は前年11月からプログラミングスクールRUNTEQに入学し、エンジニアを目指して学習を進めていました。
カリキュラムを終え、いよいよポートフォリオ作成に取り掛かろうとした時、私は大好きなポケモンバトルと結びついたサービスを作りたいと思い、企画を始めました。
アプリを作るにあたっては、現存する課題の調査と、その解決策の構想が必要です。そこで、現状のポケモンバトル(ランクマッチ)を遊ぶ上で、ユーザーが抱えている課題とは何なのでしょうか?
-
制限時間が短い
ランクマッチでは、1ターンに45秒のコマンドタイムが設定されています。
この短い時間で、ダメージ計算等をしながら最適な行動を探し出すのはかなりシビアです。
-
情報公開のインセンティブが弱い
ポケモンバトルは情報戦です。相手のポケモンがとってくる行動を予測できるかどうかで、勝敗が大きく左右されます。
しかし、情報を公開する側のメリットがほとんどありません。
ならば、情報の投稿にメリットを与えて、尚且つ高速なダメージ計算を可能にするツールがあれば、重宝するのではないだろうか。
そんな妄想の元で開発したのが、育成論投稿×ダメージ計算サービス「ポケカルキュレーター」 です。
アプリ名 : ポケカルキュレーター
▼サービスURL
https://www.poke-calculator.com/
▼GitHub URL
フロントエンド
https://github.com/hagoromo2000/poke_calculator_react
バックエンド
https://github.com/hagoromo2000/poke_calculator_rails
サービス概要と使い方
アプリの使い方を簡単に説明します。
ダメージ計算機能
基本的には、攻撃側、防御側、環境それぞれ値を変更すると、リアルタイムでフッターの計算結果が更新され、HPバーが変動するという形式です。
各項目は連動しています。 例えばポケモンを変更すると、自動で実数値も更新されます。
ここまではよくあるダメージ計算機の仕様ですが、ポケカルキュレータに特徴的なのは、後述する投稿機能との連動です。
投稿された育成論(ポケモンの能力値振り等のデータ)を、計算機に呼び出すことができます。
具体的には、「育成論から呼び出す」ボタンをクリックし、モーダルウインドウ内で投稿を選択すると、ポケモン、努力値、性格補正が自動入力されます。
育成論投稿機能
投稿された育成論は、育成論一覧に追加されます。
他のユーザーが投稿した育成論を検索、閲覧したり、ブックマークしたりできます。
ブックマークすると、一覧画面だけでなく,
育成論から呼び出す時にも絞り込みやすくなります。
ログイン機能
「育成論投稿」「ブックマーク」はログインユーザーのみが利用できる機能です。
肝心のログイン方法についてですが、新規登録時の手間を減らしたいという理由から、Googleログインのみとなっています。
Firebase Authを利用することで、初学者の私でもGoogleログインを実装できました。
ログイン機能については、工夫した点の第3項で後述します。
工夫した点
1.ポケモンのデータをどう取得するか(PokeAPIについて)
膨大な量のポケモン、わざ、とくせいのデータをどのようにして取得するかは、今回の開発において最初にぶつかった壁でした。
結論から言うと、PokeAPIを使用しました。
PokeAPIは、有志によって制作されている、ポケモン本編に関するあらゆる情報を網羅したデータベースと連携したRESTful APIです。
ポケモン個体の情報はもちろんのこと、ミニゲームのポフィン作りや、ポケスロンなどの情報まで網羅しています。
このPokeAPIが2023年1月に最新作スカーレットバイオレットの情報に対応したことで、今回の開発を企画することができました。
とはいえ、幾つかの問題があり、アプリ上では直接PokeAPIを叩いていません。
PokeAPIは1時間にリクエスト100回までの制限がある上、必要な情報のエンドポイントが分散しています。
例えば、ポケモンの能力値のデータと、日本語名のデータは異なるエンドポイントに存在します。
また、いちいちAPIを叩くと当然ラグも生じ、操作の快適性が損なわれます。
以上のような理由から、APIから必要な情報を事前に全て取得して、アプリで使いやすい形に整形した上で、Reactプロジェクト内にJSONデータとして持たせておく方法を取りました。
APIからの情報取得は、1時間100回の制限に引っかからないよう、Rubyで数十秒に1回リクエストを送ってレスポンスを保存するコードをかきました。(もっと良い方法がありそう…)
アプリ上で参照しているポケモンのデータは全てアプリが持っているJSONデータとなっています。
2.UIについて
必要な入力項目が多い分、UIについては工夫する必要があると開発初期段階から感じていました。
しかし、自分自身デザインには全く自信がありませんでした。
そこで、UIコンポーネントを最大限活用する方針をとりました。
配色についてはdaisyUIのcupcakeテーマを基盤としつつ、攻撃側と防御側を赤と青で分けて視覚的にわかりやすくなるように努めました。
また、ダメージバーなどの可動部分はFlowbiteのコンポーネントを採用しています。インストール不要でコードを貼り付けるだけで使えるので、大変使い勝手が良かったです。
また、アプリ内のJSONデータを参照する処理は、react-selectライブラリを使用して、サーチャブルセレクトボックスにすることを心がけました。
これにより、不正な値の入力を防ぎつつ、ユーザーの利便性を向上させています。
3.ログインについて
- ユーザー体験を良くしたい。
- 投稿までの敷居を下げたい。
- セキュリティの知識に不安があるため、個人情報を極力保持しないようにしたい。
上記のような理由から、ログイン機能の実装にはFirebase Authを用いたGoogleログインを採用しました。
元々はパスワード認証を検討していましたが、面倒な登録手続きによる離脱率の上昇や、自分自身のセキュリティ知識の不足を懸念していました。
そんな時、「TechFinder」をスクールの先輩がリリースいたしまして、そのログインの快適さに衝撃を受けました。
また、作者の方が実装経緯を以下リリース記事にて詳細に解説してくださっており、自分も導入に挑戦することにしました。
ここでも簡単に処理の流れを説明すると、
- FirebaseにReactから認証を依頼
- 成功すれば、IDtoken(JWT)を返却
- ReactからRailsにIDtokenが受け渡される
- Railsで検証
- firebaseが発行したuser_idを利用し、ユーザーを特定、もしくは新規作成
といったような形です。
4のRailsでの検証処理の記述につきましては、以下の記事が大変参考になります。
ログインデータの保持についてですが、セッションやクッキーでのTokenの保持はしておらず、投稿やマイページなどユーザーの特定が必要な際に、Firebase側からトークンを毎回取得し直してリクエストに載せて送っています。
主な使用技術
主な使用技術は以下のとおりです。
フロントエンド
- React 18.2.0
- TailwindCSS 3.2.7
- daisyUI 2.50.1
その他の主要ライブラリ
- react-router-dom 6.8.1
- react-loader-spinner 5.3.4
- react-select 5.7.0
- react-select-search 4.1.6
- react-paginate 8.1.4
- react-toastify 9.1.1
- react-firebase-hooks 5.1.1
- react-use 17.4.0
- axios 1.3.4
- heroicon/react 2.0.16
バックエンド
- Rails 6.1.7.2
- Ruby 3.1.2
- PostgreSQL
その他主要なgem
- rack-cors
- jwt
- jsonapi-serializer
インフラ
- インフラ
- Fly.io
- Vercel
- その他
- Firebase Authentication
技術選定理由
私がお世話になっているRUNTEQでは、主にRuby on Railsを扱っており、ポートフォリオもRuby on Railsで開発される方が多いです。
しかし、私が作りたいアプリの計算機としての利便性を考えた時、「いちいちページの再読み込みを挟んでいては使い勝手が悪い」と考え、フロントエンドの技術のキャッチアップを行いました。
具体的には、今年2月の前半をJavaScriptとReactのキャッチアップに充て、後半からアプリの開発を始めました。
Reactをフロントエンドに用いてSPAとして開発することを決め、必然的にバックエンドはスクールのカリキュラムで使い慣れているRailsを採用することになりました。
デザイン上の理由から、UIコンポーネントにdaisyUIを採用することに決めたので、CSSフレームワークはTailwindCSSを使うことになりました。扱うのは初めてでしたが、クラス名を考えなくて良い点や、微調整をしやすい点が大変使い勝手が良かったです。
作成期間
全体の作成期間は約1ヶ月、内訳としてはスクール内のMVPリリースまでが約20日、本リリースまでが約10日となっております。(作ること自体はかなり前から決めていたので、企画の期間は含んでおりません)
全体の開発手順としては
- 計算機能の実装
- 投稿関連機能の実装
- 計算機能と投稿機能の連携
といった流れで進めました。
1. 計算機能の実装(2023年2月中旬~2月末)
まずは、フロントエンド側のみでハリボテの計算画面を作成しました。
次に、攻撃力とわざの威力、防御力のみで計算をするようなシンプルなダメージ計算機能を作成しました。
そこから、計算対応させる必要のある要素をリストアップし(タイプ一致補正、タイプ相性、物理特殊…)、順番に計算に反映させていく方法で実装を進めました。
2. 投稿機能の実装(3月初頭~3月6日)
次に、バックエンドの開発もスタートしました。この時には、フロントエンド側にJSONデータを持たせる方針が固まっていたので、バックエンドのテーブル構成は極めてシンプルなものとなっていました。具体的には、UsersテーブルとPostsテーブル、Likesテーブルの3つのみでした。
この段階では、育成論の投稿機能と一覧機能を実装しました。
それが終わったタイミングで、スクール内でのMVPリリースを行いました。
しかし、MVPリリース前のデプロイで問題発生。
当初は、Railsのプロジェクト内にReactのディレクトリを配置する形で開発を進めていました。しかし、Fly.ioでRails側をデプロイしようとした際、Reactプロジェクトのみがデプロイされてしまう問題に直面。予想外の時間を取られてしまいました。
やはり、開発初期からのマメなデプロイが大切ですね…。
結局、ReactプロジェクトをRailsプロジェクトの外に出し、GitHubのリポジトリも分割することで解決しました。
3.計算機能と投稿機能の連携(3月7日~3月18日)
まずは、このアプリのコンセプトである、計算機への育成論データの呼び出し機能を実装しました。
そこから、呼び出し機能の利便性を向上させるためにブックマーク機能の実装を行いました。
また、マイページ作成や利用規約の設定、独自ドメイン取得などの周辺整備もこの段階でまとめて行いました。
これからの「ポケカルキュレーター」
課題点や今後実装したい点については以下のとおりです。
-
計算対応項目の拡充
現状、とくせいやわざの独自仕様に非対応なので、時間を見つけ次第、使用率の高いものから計算対応させていきたいです。
-
継続的なデータの更新・追加
「ポケットモンスター スカーレット・バイオレット」は先日DLCが発表されたばかりなので、追加ポケモンなどがあれば順次対応していく予定です。
-
認証周りの機能追加
退会機能が未実装なので、ユーザーに安心して利用していただけるように、早急に対応したいと考えています。
最後に
今回初めてサービスを1から作りましたが、作る過程での学びがとても多かったです。
特に、最初にコンポーネント設計をしっかり作っておかないと、コードが汚くなってしまうのは実感として強く持ったので、今後の開発に活かしていきたいと思います。
拙い記事でしたが、最後までお読みいただき、本当にありがとうございました!