推しアイデア
みんなで同時にラジオ体操できる!
―
みんなで同時にラジオ体操できる!
「夏休みに薄っぺらいラジオ体操カードを首にかけて蒸し暑い公園で朝一番から眠気MAXでやったラジオ体操」を思い出したかったので
リアルタイム処理やバックエンドの全てなど、たくさん supabase の機能を使っているところ!
ラジオ体操ができます!!!
みんなで同時にラジオ体操ができます! 他の参加者のアイコンが見えて楽しいです。
ラジオ体操した日にはスタンプが押されます! 現在の継続日数や累計日数も確認することができます。
Supabaseテーマのハッカソンなので、 Supabase がサポートする以下5つの機能全て使いました!✨️
みんなでラジオ体操を行う機能で使用しています。 ルーム参加者を固有のチャンネルへ登録し、各ユーザーの状態(途中抜け・切断してないか)を Presence で監視しています。 Socket.io に近い触り心地でかなり楽でした。
リアルタイムな機能を複数ページにわたって展開する都合上、同じルームの参加者などの状態は分離して保持しておく必要がありました。 今回は Riverpod を使用し、状態保持を Provider に一任することで解決しました。
ユーザのプロフィール画像を保存 / 取得するのに使いました。 保存時は File をアップロード、表示は URL を用いています。 ファイル名から public URL を取得できる関数が用意されていていいかんじでした。
supabase Auth を介して google アカウントのサインインを実装しました。 モバイル OS ごとに個別対応が必要だと踏んでいましたが、意外と軽微に抑えられていてよかったです。
バックエンドはすべてSupabase Edge Functions, Supabase Databaseを使用しています✨️
ER図: https://github.com/progate-hackathon-usagi/progate-usagi/blob/main/er.md
プロフィール情報のprofile
テーブルと、ラジオ体操記録を保存するexercise_log
テーブルがあります。
また継続・累計日数集計用にv_user_profile_with_exercise_days
ビュー(DDL)を用意しました。
機能に合わせて必要なCRUDを実装しています。
API設計・実装において以下の点を考慮しました。
console.log()
を差し込む201 Created
を使用するuser_profile: {...}
のように名前をつけて返す{...}
を受け取る日付単位で重複削除されたv_user_profile_with_exercise_days
ビューを用いて集計を行っています。
累計日数は、v_user_profile_with_exercise_days
ビューの行数を数えています。
select count(*)
でもよかったのですが、継続日数取得がSQLでの実装が難しくコードでカバーすることを決めたため、集計操作がシンプルになるよう同じくコード上で集計を行っています。
継続日数は、v_user_profile_with_exercise_days
ビューから取得したデータに対し、「昨日または今日ラジオ体操をしている」ユーザの「昨日または今日から遡って連続してラジオ体操した日付の行数」を数えています。
継続日数取得は1行ずつ操作するためO(N)の計算量が必要ですが、100年続けてもせいぜい36500行なので実用に耐えうると判断しました。
普段はdayjsに甘えるのですが、今回は組み込み型のDateを使用し、日付の比較処理等を書きました。日付の「一致」「一日前」を判定するだけで苦労したり、getMonthが0-11
を返したりなど、非常に不便でした。