レース結果を紙で管理しない
水泳のレース結果はスプリットシートと呼ばれる専用の紙に記録されるのが一般的です。その場合、マネージャーがラップタイム(一定距離ごとにかかった時間)を通過タイムから計算する必要があります。表計算ソフトで計算する部活もなかにはあるでしょうが、さらに効率よくレース結果を記録・フィードバックする仕組みがあるべきだと考えました。
ウェブサイトではなく、「画像として返す」
通過タイムを入力すればラップタイムを計算してくれるウェブサイトを作るのは容易です。しかし既存の業態(=マネージャーがシートにタイムを書き込み、選手に返す)を置き換えるには不十分だと考えました。あくまで「スプリットシートを電子的に作成してくれるアプリ」でないと浸透しないでしょう。そのためポータブルで他人とのシェアがしやすい、画像での出力とすることにしました。
紙から置き換える価値のあるものにする
当初は既存のスプリットシートをそのまま再現したデザインにする予定でしたが、わざわざ紙から移行しようと思える付加価値をつけるべきだと考えました。最初に思いついたのはグラフの描画です。一定距離ごとのタイムの推移を折れ線グラフで表示する機能があれば、それこそデジタルでしか提供できない価値だと考えました。そして折れ線グラフをメインに、所有感が生まれるような、そして他人に自慢したくなるような「記録証」のデザインを作り上げました。
LINEボットとして開発
入力が文字列(タイムや種目名、大会名など)に対し、出力はその情報を載せた画像です。このI/Oのイメージに沿ったのがLINEのボットでした。TiMにおける開発経験もあること、さらにネイティブアプリへの関心が薄かったこと、導入の容易さ(インストールが不要で友だち追加するだけで利用可能)が主な採択理由です。しかしチャットボットという特質上、かなり単純な操作しか実現できないのが欠点です。
画像化を実現する技術
Pythonのmatplotlibのように、グラフを画像として出力するライブラリは十分に存在します。しかしグラフだけでなくその周辺のデザインにこだわりたいとき、これらのグラフ描画ライブラリでは力不足です。細部にこだわったデザインを作り上げたいとき、やはりやりなれたブラウザにレンダリングを任せ、JSやCSSでシートを構築するのが筋がいいと感じました。そして以前Sheepfoldで使用経験のあるPuppeteer(ヘッドレスブラウザ)を活用し、レンダリング後に画面をキャプチャすることで画像化が実現できると見込みました。ただし以下のような課題にぶつかり、PoCには多大な時間がかかりました。
- AWS Lambda上でのPuppeteer・Chromiumが起動しない
- 日本語フォントが表示されない
- インターネットに接続せずにページを描画する戦略
- 動的なデータの描画が難しい=描画を担うJSに動的なデータを渡すにはどうすればよいか
- JSの描画とキャプチャの同期
これらの課題を乗り越え、「Lambda上でヘッドレスブラウザを起動し、動的なデータをもとに描画、キャプチャ結果をS3にアップロードする」サーバーレスアプリケーションを開発できました。現在プライベートリポジトリですがいずれ公開予定です。
複数のリポジトリとサービス
MiZはいくつかのサービスにより構成されています。より細かく責任を切り分け、それぞれをマイクロサービス化することも可能です。全てTypeScriptで書かれています。
MiZ
- メインのサービス。Serverless Frameworkを活用
- LINEサーバーを経由したユーザーメッセージの受け取り・認証
- メッセージ内容をもとに実行内容の識別
- DynamoDBに対するデータ操作
- ユーザーに返信する
「SWIM」の各文字を上下逆にしたり鏡面反転させると「ZMIM」になる。ここから「水」を連想するサービス名としてMiZとした
MiZ-LIFF
LINE Front-end Frameworkアプリケーション。Next.jsを活用。LINEクライアントアプリ上で起動するウェブアプリ
- ユーザーの認証
- DynamoDBに対するデータ操作
Paparazzo
「画像化を実現する技術」で言及したサーバーレスアプリケーション。MiZとおなじくServerless Frameworkを活用しているが、MiZとビジネスロジックを共有していない。ビルド時に後述のWarabeを取り込む
- トリガー時に受け取ったJSONデータをヘッドレスブラウザに流す
- キャプチャ結果をS3にアップロードする
Paparazzoはpaparazzi(パパラッチ・イタリア語)の単数形。「Puppeteerを使って写真を撮る」ことから思いついた
Warabe
単一のHTMLファイルを吐き出すVite + Svelteアプリケーション。JSやCSSをインクルードした単一のHTMLファイルを生成する。
- PuppeteerのAPIからデータを受け取り、描画する
「童(わらべ)」は「GHOST IN THE SHELL / 攻殻機動隊」ラストシーンのセリフより。Svelteと語感が似ていることから
MiZ-Web
公式ウェブサイト。他サービスとは完全に独立している。Next.js+Vercel
- マークダウン形式の利用規約のHTML化