FlutterKaigi 2024
(OGP 画像)
昨日 FlutterKaigi 公式 medium からも、有明周辺のランチ事情についてのアナウンスがなされました。
昨年 FlutterKaigi 2023 公式アプリで好評だったランチマップについて、今年はチームメンバーの負荷を考慮し提供されておりません。
ちなみに昨年のランチマップでは、会場スポンサーとして協賛いただいていた 株式会社ナビタイムジャパン のマップと合わせ、提供されていました。
FlutterKaigi 2023 で提供していたランチマップのスクリーンショット。
カンファレンスアプリの一機能としてランチマップが提供されていました。
初期コンテンツとして読み込んだ時 | 右へスクロールした時 | 動線 |
---|---|---|
そこで今回、非公式という形で有明周辺のランチマップを設計・実装してみました。
情報出所は 食べログ から参照させてもらっています。
そもそも、こうしたランチマップを制作したきっかけは、有明近辺にそのようなスポットが少ないのでは無いかという疑問から。
結論として全くそんな心配は無く、よしなりにお店をピックアップできる環境と認識できました。
ここで今回捕捉するのは、下記 3 点の中で 2 点目を取り上げます。
- Supabase の DB 設計
- Database Function の使いどころ
- 気合いで seed.sql を書いて、データを流し込む
DB 設計
位置情報 (緯度や経度) をいかにして記録するのか。
緯度、経度についてぞれぞれ double 型
として格納する必要はありません。
Postgres 内で地理データを操作できるようにする Postgres 拡張機能 PostGIS のお世話になります。
緯度、経度のシンプルなセットから構成されている Point 型 を使って、位置情報を DB に保存することを目指します。
create table if not exists public.shops (
id uuid not null primary key default uuid_generate_v4(),
name varchar(100) not null,
comment varchar(500),
link_url varchar(500),
location geography(POINT) not null,
is_open bool not null,
created_at timestamp with time zone default timezone('utc' :: text, now()) not null,
updated_at timestamp with time zone default timezone('utc' :: text, now()) not null
);
Database Function の使いどころ
まず今回 FlutterKaigi 2024 では、有明セントラルタワーホール&カンファレンスにて、午前の部から終日にわたって開催されます。
この開催場所から近い順に直線距離 (と、歩いてかかる想定時間) を算出することを目指します。しかし、この直線距離の算出を Flutter アプリ内で計算するのは、非常にたいへんで複雑なロジックが求められます。
そのロジックの責務を Postgre 関数で気軽に書くことのできる Database Function に任せてしまおうというのが、今回の狙いのひとつになります。
余談: PostGIS の例で参照されており、そちらの考えを参考にさせていただきました。
create or replace function nearby_shops(lat float, long float)
returns setof record
language sql
as $$
select id, name, st_astext(location) as location, st_distance(location, st_point(long, lat)::geography) as dist_meters
from public.shops
order by location <-> st_point(long, lat)::geography;
$$;
関数を作成したら、あとは Flutter アプリから supabaseClient.rpc
で読み込みます。
なお、centerLat
と centerLng
には、有明セントラルタワーホール&カンファレンスの緯度や経度が入ります。
Stream? stream({
Shop? condition,
}) {
final data = supabaseClient.rpc('nearby_shops',
params: {'lat': centerLat, 'long': centerLng}).asStream();
return data;
}
歩いてかかる想定時間は、取得した直線距離を基に、Flutter アプリ内で計算します。
ちなみに、時速 4km と仮定し、徒歩の時間を計算しました。
seed.sql を書く
基本的には新規のデータを追加する際の SQL を書けば良いのですが、ここでの肝は Point 型 の書き方になります。
insert into public.shops
(name, comment, link_url, location, is_open)
values
('春華秋実', '', '', st_point(139.791585, 35.6319108), true);
実際に値を渡す順番として st_point()
では、経度の次に緯度が入ります。
st_point(<経度>, <緯度>)
数学における座標軸で x 軸に経度が入り、y 軸に緯度が入ることを想像してください。
あと、こればかりは気合いで SQL を書いていくのみ。ですがこちらは割愛させていただきます。
最後に
あくまで Supabase プロジェクトについては、課金プランまで上げる措置をとっていませんので、ある一定の時間を経ればアクセスできなくなる可能性があります。
非営利な技術コミュニティに対し、コミット可能なコミュニティプランを検討して欲しいなどと考える場面も多い今日このころ。
というわけで、今回も FlutterKaigi コアスタッフのひとりとして 前・当日を迎えましょう。