QRコードスタメン表提出機能を公開しました
個人開発で作っているもの
野球盤型競技用スコアブックアプリ(web)
実装の経緯
スコアブックでの記録を始めるにあたり、事前にスタメン(選手の打順、守備位置)を申告してもらい、スコアラーが登録する必要がありました。これまではスコアラーが 1 つの端末で双方に打順を聞き取りながら 1 つ 1 つ入力しており、体育館など限られた時間の中で競技の準備をする上で競技以外の時間短縮がカギとなっていました。
きっかけはフォームからの要望
問い合わせフォームから
- 「非公開で自チームのスタメンを保存できるようにしてほしい」
- 「スコアラーにスタメン表を送れるようにしてほしい」
との要望があり、どのように実現するか考えることにしました。
リーグや大会などの試合日は予め決まっていることがほとんどなので、前日までに各チームでスタメンを考えてくることが多く、会場に来てから考え始めることはほとんどありません。
前提としてスコアブックシステムは改変を防止するために、初期状態では作成者(スコアラー)にしか編集権限をもたせていません。
期日と対戦相手が決まっているのであれば事前に試合データを作成し、各チームに編集権限を与えることによって事前にスタメンを入れておくことは可能ですが、相手チームのスタメンを見ることができるので後出し有利となってしまいます。
そこで、それぞれのアカウントに自チームのスタメン表を保存する機能を持たせ、スタメン表のデータを QR コード化して会場でスコアラーに読み取ってもらうのがよいかと考えました。
動作デモ
前日に家でスタメンを保存して会場でスコアラーにスタメン設定画面からQRリーダを起動して読み取ってもらいましょう。
技術的なこと
QRコードの生成
import QRCode from "qrcode.react";
return(
<QRCode
size={148}
level={"H"}
value={JSON.stringify(
//文字列に置き換えたいJSONを入れる
)}
/>
)
QR コードの読み取り
今回読み取りには react-zxing
を使用しました。
import { useZxing } from "react-zxing";
export const QRcodeScanner: React.FC<{
closeFunc: () => void;
setter: (value: React.SetStateAction<any>) => void;
}> = ({ closeFunc, setter }) => {
const { ref } = useZxing({
onDecodeResult(result) {
setter(result.getText());
closeFunc();
},
});
return <video ref={ref} />;
};
return(
<Modal
visible={qrReaderOpen}
transparent
animationType={"slide"}
onRequestClose={() => setQrReaderOpen(false)}
>
<QRcodeScanner
closeFunc={() => setQrReaderOpen(false)}
setter={(value) => {
// valueに読み取り結果(文字列)が入るのでパース処理など
// スタメン設定に格納する処理を入れる
}}
/>
</Modal>
);
QR コード読み取り部分をモーダルにしたので、 closeFunc
でモーダルを閉じる処理を Prop として渡し、setter
で親コンポーネントの state に読み取り結果を渡すように実装しました。
精度を上げることにやったこと
安直にQRコードをそのまま配置してみたら全然認識されず、動作確認で使っていたQR生成サイトとどう違うのか考えたところ、白背景とpaddingを与えて境界を明確にしてやらないとQRコードの端の値が認識されず、精度が落ちるという気付きがありました。
その他
あとはアカウントごとにスタメン表を保存できるように
- DBのテーブルを設計・追加
- 作ったスタメン表を送信(保存)する画面(元々あったスタメン設定画面を複製して改造)
- バックエンドで送られてきたデータをinsert処理
- 保存データを取得する処理
を別途書いて終わりです。
QRコードの生成は元々試合データの編集許可を出すために作ったことがあったので、だいたいリリースまで丸一日ぐらいでした。
ただ、端末のカメラを起動するのがhttps
環境でしかできないので、vercelのdeploy preview使って都度動作確認しながらコードをプッシュし直すというなかなかに面倒な環境でした。
参考
Discussion