機能一覧 Feature list

Parky モバイルアプリの機能は、ユーザージャーニーに沿って ① 駐車前検索 / ② 駐車中 / ③ 駐車後 / ④ その他 の4フローに分類されます。

Parky mobile app features are organized along the user journey into four flows: 1) Search before parking / 2) During parking / 3) After parking / 4) Other.

4.1 機能構成 4.1 Feature composition

flowchart LR
  subgraph F1["① 駐車場検索 (駐車前)"]
    S1[目的地検索]
    S2[AI検索]
    S3[現在地検索]
    S4[並び替え]
    S5[フィルタ]
    S6[ランキング]
    S7[Google Maps共有受信]
    S8[所要時間→入庫時刻自動設定]
  end
  subgraph F2["② 駐車開始〜駐車中"]
    P1[駐車セッション管理]
    P2[駐車中バブル表示]
    P3[料金シミュレーション]
    P4[駐車中メモ]
    P5[通知・アラート]
    P6[保存機能]
    P7[レビュー閲覧]
  end
  subgraph F3["③ 駐車終了後"]
    E1[個人評価 Good/Bad]
    E2[駐車後メモ]
    E3[レビュー投稿]
    E4[駐車履歴]
  end
  subgraph F4["④ その他"]
    O1[メディア]
    O2[バッジ/レベル]
    O3[認証]
    O4[広告]
    O5[プレミアム]
    O6[サポート]
    O7[駐車場新規登録申請]
  end

4.2 機能一覧表 4.2 Feature list table

# フローFlow 機能名Feature 種別Type 説明Description
01 ① 駐車場検索1) Parking search 目的地から駐車場検索Search parking lots by destination 機能Feature 目的地付近の駐車場を取得する(半径指定/Mapbox ジオコーディング+PostGIS 近傍検索)Fetch parking lots near a destination (radius-based, Mapbox geocoding + PostGIS proximity search)
02 ① 駐車場検索1) Parking search 並び替えSorting UI制御UI control 検索結果を「安い順」「近い順」「評価順」「空き順」に切り替えSwitch search results between cheapest / nearest / highest rated / most available
03 ① 駐車場検索1) Parking search 検索絞り込み(フィルタ)Search filter UI制御UI control 車両制限・料金上限・24h営業・屋根・タグ等の条件で絞り込みFilter by vehicle limits, price cap, 24h open, covered, tags, and similar conditions
04 ① 駐車場検索1) Parking search AI検索AI search 機能Feature 自然言語(例:「21時から朝まで安く停めたい」)を LLM が検索条件に変換An LLM converts natural language (e.g. "cheap parking from 9pm until morning") into search parameters
05 ① 駐車場検索1) Parking search 現在地検索Current location search 機能Feature 現在地付近の駐車場を取得する(GPS + 半径デフォルト500m)Fetch parking lots near the current location (GPS, default 500m radius)
06 ① 駐車場検索1) Parking search ランキング表示Ranking display UI制御UI control 最適候補上位3件に「🥇🥈🥉」バッジを付与Attach gold/silver/bronze medal badges to the top three best-matching candidates
07 ② 駐車中2) During parking 駐車セッション管理Parking session management 機能Feature 駐車開始・終了、駐車中状態(経過時間・料金)を管理(parking_sessionsManage parking start/end and in-parking state such as elapsed time and fee (parking_sessions)
07.5 ② 駐車中2) During parking エリアスポンサー表示・チェックインArea sponsor display & check-in 機能Feature マップ上にカテゴリ別アイコンでスポンサー表示(Canvas SVG描画)。セッション画面に「おすすめスポット」カード(サムネイル・距離)。タップでチェックイン(sponsor_checkins)、長押しで外部リンク。nearby_sponsors() RPC で取得。Category-specific SVG icon markers on map. Session screen shows sponsor recommendation cards (thumbnail, distance). Tap to check in (sponsor_checkins), long press for external link. Data from nearby_sponsors() RPC.
08 ② 駐車中2) During parking 駐車中バブル表示In-parking bubble UI制御UI control Map 上および OS ホーム画面(Live Activity / Widget)で料金・経過時間を簡易表示Compact display of fee and elapsed time on the map and the OS home screen (Live Activity / Widget)
09 ② 駐車中2) During parking 料金シミュレーションFee simulation 機能Feature 入庫時刻と利用時間から料金ルール(時間帯×曜日×最大料金)を評価し想定料金を算出Evaluates pricing rules (time-of-day × day-of-week × cap) from entry time and duration to estimate the expected fee
10 ② 駐車中2) During parking 駐車中メモIn-parking memo 機能Feature テキスト+写真4枚までを紐付けて保存(場所メモ・写真メモ)Save a text note plus up to four photos (location notes, photo memos)
11 ② 駐車中2) During parking 通知機能Notifications 機能Feature 料金閾値アラート・最大料金到達・予定時間超過等をPush+アプリ内通知で送信Send push and in-app notifications for fee threshold alerts, cap reached, schedule overrun, and so on
12 ② 駐車中2) During parking 駐車場保存(Saved)Save parking lot 機能Feature 駐車場をお気に入りに追加(user_saved_parkingsAdd a parking lot to favorites (user_saved_parkings)
13 ② 駐車中2) During parking レビュー閲覧View reviews 機能Feature 評価・コメント・写真を他ユーザー投稿から取得Read ratings, comments, and photos submitted by other users
14 ② 駐車中2) During parking レビュー並び替えReview sorting UI制御UI control 新着順・評価順にソートSort by newest or by rating
15 ③ 駐車終了後3) After parking 個人評価 Good/BadPersonal rating (Good/Bad) 機能Feature 駐車体験を Good/Bad で評価(個人履歴用、他ユーザーには非公開)Rate the parking experience as Good/Bad (for personal history only, not visible to others)
16 ③ 駐車終了後3) After parking 駐車後メモPost-parking memo 機能Feature 何のための駐車だったか・支払い金額・領収書写真等を記録Record the purpose of the trip, amount paid, receipt photos, and more
17 ③ 駐車終了後3) After parking レビュー投稿Post review 機能Feature 星評価+コメント+写真を他ユーザーに公開(parking_reviewsPublish a star rating, comment, and photos for other users to see (parking_reviews)
18 ④ その他4) Other メディアMedia 機能Feature 記事コンテンツ(articles)を取得・表示Fetch and display article content (articles)
19 ④ その他4) Other バッジ / レベルBadges / levels 機能Feature 行動に応じて EXP を付与、レベル算出、条件達成でバッジ付与Grant EXP per user action, compute level, and award badges when conditions are met
20 ④ その他4) Other 認証Authentication 機能Feature ユーザー登録・ログイン・OTP・SNS・パスワード再設定Sign up, sign in, OTP, social login, and password reset
21 ④ その他4) Other 広告表示Ads その他Other 駐車場詳細・検索結果・記事詳細で広告を表示(ads + boostsShow ads on parking lot details, search results, and article pages (ads + boosts)
22 ④ その他4) Other プレミアムプランPremium plan 機能Feature サブスクリプション課金(IAP)・解約・ステータス管理Subscription billing (IAP), cancellation, and status management
23 ④ その他4) Other サポートSupport 機能Feature 問い合わせ送信・履歴閲覧・管理者とのスレッド(support_ticketsSubmit inquiries, view history, and thread with admins (support_tickets)
24 ④ その他4) Other 駐車場新規登録申請New parking lot registration 機能Feature ユーザーが新規駐車場を申請し、管理者がレビューUsers submit a new parking lot for admin review
25 ④ その他4) Other 誤情報報告Error reporting 機能Feature 駐車場情報の誤りを報告(error_reportsReport incorrect parking lot information (error_reports)
26 ① 駐車場検索1) Parking search Google Maps共有受信Google Maps share intake 機能Feature Google Maps アプリの共有メニューからParkyを選択すると、共有されたスポット/経路の目的地が駐車場検索の目的地に自動設定される(Android: Share Intent、iOS: Share Extension)When users select Parky from Google Maps' share menu, the shared spot or route destination is automatically set as the parking search destination (Android: Share Intent, iOS: Share Extension)
27 ① 駐車場検索1) Parking search 所要時間→入庫時刻自動設定Travel time → auto-set entry time 機能Feature 現在地と目的地が確定した時点で Mapbox Directions API(driving-traffic)を呼び出し、車での所要時間を算出。現在時刻+所要時間を入庫開始時刻の初期値に自動設定するOnce origin and destination are determined, call the Mapbox Directions API (driving-traffic) to calculate driving time. Automatically set current time + travel time as the default entry time

4.3 機能詳細 4.3 Feature details

F01 / F05 目的地検索・現在地検索 F01 / F05 Destination & current location search

目的Purpose

目的地(住所・駅名・ランドマーク)または現在地の周辺にある駐車場を、距離・料金・条件を加味して提示する。

Present parking lots around a destination (address, station name, or landmark) or the current location, ranked by distance, price, and conditions.

主要フローMain flow

  1. 入力:住所文字列 or 現在地の GPS 座標
  2. Input: an address string or current GPS coordinates
  3. 住所の場合は Mapbox Geocoding API で座標に変換
  4. If an address is given, convert it to coordinates via the Mapbox Geocoding API
  5. RPC nearby_parking_lots(lat, lng, radius_m) で PostGIS 近傍検索
  6. Run a PostGIS proximity search via the RPC nearby_parking_lots(lat, lng, radius_m)
  7. 各駐車場に対してクライアント側で料金シミュレーションを実行(入出庫時刻が指定されていれば)
  8. Run client-side fee simulation for each lot when entry and exit times are provided
  9. 並び替え・ランキングバッジ付与
  10. Sort results and attach ranking badges

入力Inputs

  • 目的地(文字列 or 座標)
  • Destination (string or coordinates)
  • 検索半径(デフォルト500m、ユーザー設定可)
  • Search radius (default 500m, user-configurable)
  • 入出庫時刻(任意、指定時は料金計算を実行)
  • Entry/exit times (optional; triggers fee calculation when set)
  • フィルタ条件(任意)
  • Filter conditions (optional)

出力Outputs

  • 駐車場配列(id, 名前, 座標, 距離, 想定料金, 評価, タグ, 主画像)
  • An array of parking lots (id, name, coordinates, distance, estimated fee, rating, tags, main image)
  • 検索履歴への1件追加(重複チェック付き)
  • One entry added to the search history (with duplicate checking)

例外Exceptions

  • GPS 権限拒否 → 権限リクエスト画面へ遷移
  • GPS permission denied → navigate to the permission request screen
  • ネット通信エラー → オフラインキャッシュを表示 + リトライ
  • Network error → show the offline cache and retry
  • ジオコーディング失敗(住所不明)→ サジェスト候補を表示
  • Geocoding failure (unknown address) → show suggestion candidates
F04 AI検索 F04 AI search

目的Purpose

自然言語の入力を LLM で検索条件に変換し、ユーザーの手間を削減する。

Convert natural language input into search parameters via an LLM to reduce user effort.

主要フローMain flow

  1. ユーザーが自然言語を入力(例:「池袋で23時から朝9時まで、2000円以下で停めたい」)
  2. The user enters natural language (e.g. "I want to park in Ikebukuro from 11pm to 9am for under 2000 yen")
  3. クライアントが Cloudflare Workers ai-search-parse を呼び出し
  4. The client invokes the Cloudflare Workers ai-search-parse
  5. Cloudflare Workers が LLM に定型プロンプトで問い合わせ、JSON 構造を返却
    {
      "location": "池袋",
      "entry_at": "2026-04-14T23:00:00+09:00",
      "exit_at": "2026-04-15T09:00:00+09:00",
      "max_price": 2000,
      "filters": ["24h営業"]
    }
  6. The Cloudflare Workers queries the LLM with a fixed prompt and returns a JSON structure
    {
      "location": "池袋",
      "entry_at": "2026-04-14T23:00:00+09:00",
      "exit_at": "2026-04-15T09:00:00+09:00",
      "max_price": 2000,
      "filters": ["24h営業"]
    }
  7. クライアントは通常の検索処理に投入
  8. The client feeds the result into the normal search pipeline

安全策Safety measures

  • LLM 応答は JSON スキーマ検証。失敗時は「解釈できませんでした」と再入力を促す
  • LLM responses are validated against a JSON schema; on failure show "Could not interpret" and prompt the user to re-enter
  • プロンプトインジェクション対策としてシステムプロンプトで出力形式を厳格指定
  • To guard against prompt injection, the system prompt rigorously specifies the output format
  • Cloudflare Workers はレート制限(匿名:1分3回、ログイン:1分10回)
  • The Cloudflare Workers is rate-limited (anonymous: 3/min, signed-in: 10/min)
F07 駐車セッション管理 F07 Parking session management

ライフサイクルLifecycle

  • pending → ユーザーが「駐車開始」タップ直後、GPS/認証待ち
  • pending → immediately after the user taps "Start parking"; waiting for GPS / authorization
  • parking → 入庫確定、計時・料金計算開始、Live Activity 表示
  • parking → entry confirmed; timer and fee calculation start; Live Activity is shown
  • ended → ユーザーが「駐車終了」タップ、料金確定、レビュー導線へ
  • ended → user taps "End parking"; final fee confirmed and review flow begins
  • cancelled → 誤操作等でキャンセル(5分以内のみ)
  • cancelled → cancelled due to a mistap or similar (within 5 minutes only)

保持情報Stored data

parking_sessions: id, user_id, parking_lot_id, started_at, ended_at, total_amount, vehicle_type, memo, status

parking_sessions: id, user_id, parking_lot_id, started_at, ended_at, total_amount, vehicle_type, memo, status

料金計算Fee calculation

  • クライアント側で parking_lot_pricing_rules を評価し想定料金を随時表示
  • The client evaluates parking_lot_pricing_rules and continuously displays the estimated fee
  • 駐車終了時にサーバー側 RPC finalize_parking_session で最終金額を確定(クライアント計算と照合)
  • At end-of-parking, the server RPC finalize_parking_session finalizes the total (cross-checked against the client calculation)

バックグラウンド挙動Background behavior

  • アプリがバックグラウンド → iOS: Live Activity で継続表示、Android: 常駐通知
  • When backgrounded → iOS: Live Activity keeps showing, Android: persistent notification
  • 通信が途切れた場合はローカルタイマーで継続、復帰時に同期
  • If the network drops, a local timer keeps running and state syncs once connectivity returns
F09 料金シミュレーション F09 Fee simulation

計算ロジックCalculation logic

駐車場の料金ルール(parking_lot_pricing_rules)は時間帯・曜日別のユニット料金と最大料金(キャップ)の組合せで定義されます。クライアントは以下を評価します。

Parking lot pricing rules (parking_lot_pricing_rules) are defined as combinations of per-time-slot, per-day-of-week unit charges and a maximum (cap) fee. The client evaluates them as follows.

  1. 入庫時刻と出庫時刻から利用時間帯を特定(日跨ぎ対応)
  2. Determine the used time ranges from entry and exit times (supporting day rollover)
  3. 各ルールを適用可能な区間に分割し、ユニット料金 × 使用ユニット数を集計
  4. Split each rule into applicable intervals and sum up unit price × unit count
  5. 各ルールの最大料金(cap)と集計値を比較し、小さい方を採用
  6. Compare each rule's cap to the accumulated total and take the smaller value
  7. 合計金額と内訳を UI に表示
  8. Display the total and breakdown in the UI

入力Inputs

  • 駐車場ID / 入庫時刻 / 出庫時刻 / 車両種別
  • Parking lot ID / entry time / exit time / vehicle type

出力Outputs

  • 合計金額 / 適用ルール一覧 / 各ルールの適用区間と内訳
  • Total amount / list of applied rules / the applied interval and breakdown for each rule

実装場所Implementation location

  • クライアント:domain/pricing/pricing_calculator.dart(純関数・テスト容易)
  • Client: domain/pricing/pricing_calculator.dart (pure functions, easy to test)
  • サーバー:同ロジックの PostgreSQL 関数 calc_parking_fee(lot_id, entry, exit) を用意し、管理者ポータル・モバイル両方で再利用
  • Server: a PostgreSQL function calc_parking_fee(lot_id, entry, exit) implements the same logic and is reused by both the admin portal and the mobile app
F11 通知機能 F11 Notifications

通知種別(駐車関連)Notification types (parking-related)

種別Type トリガTrigger チャネルChannel
料金閾値アラートFee threshold alert 現在料金がユーザー設定の閾値を超えたCurrent fee exceeded the user-configured threshold Push + 振動Push + vibration
最大料金到達Cap reached cap に到達Cap was reached PushPush
予定時間到達Planned exit time approaching 設定した予定出庫時刻の10分前10 minutes before the configured planned exit time Push + アプリ内通知Push + in-app notification
長時間駐車Long-stay parking 24時間経過24 hours have elapsed Push(1日1回)Push (once per day)

詳細は 08. 通知設計 参照。

See 08. Notification design for details.

F19 バッジ / レベル F19 Badges / levels

管理者ポータルと同じバッジエンジンを利用します(badge_definitions + user_badge_progress)。モバイルクライアントは以下のみを担当します。

Uses the same badge engine as the admin portal (badge_definitions + user_badge_progress). The mobile client is only responsible for the following.

  • 行動時に user_activity_logs へログを INSERT(metadata JSONB にイベント詳細)
  • On user actions, INSERT a log row into user_activity_logs with event details in the metadata JSONB column
  • DB トリガ or Cloudflare Workers が EXP 付与とバッジ進捗更新を実行
  • A DB trigger or Cloudflare Workers grants EXP and updates badge progress
  • モバイルはバッジ獲得時に user_badges の Realtime 変更を購読し、アニメーションでフィードバック
  • The mobile app subscribes to Realtime changes on user_badges and plays an animation when a badge is earned
F20 認証 F20 Authentication

サインアップSign up

  1. メール+パスワード入力
  2. Enter email and password
  3. OTP(メール 6桁コード)で認証
  4. Authenticate via OTP (6-digit email code)
  5. プロフィール入力(表示名・車種)
  6. Enter profile info (display name, vehicle type)
  7. app_users に 1 行作成
  8. Insert one row into app_users

サインインSign in

  • メール+パスワード
  • Email + password
  • SNS ログイン(Apple, Google — 将来)
  • Social login (Apple, Google — future)
  • 生体認証によるローカル再認証(アプリ起動時の短縮フロー)
  • Biometric local re-authentication (a shortened flow at app launch)

パスワード再設定Password reset

  • メールで OTP 送信 → 新パスワード設定
  • Send an OTP by email, then set a new password

ステータスStatus

  • user_status: active / withdrawn / suspended(コードマスター)
  • user_status: active / withdrawn / suspended (code master)
  • suspended 時は認証成功後にサインアウトし、管理者からの案内を表示
  • When suspended, sign the user out after successful auth and show the admin notice
F22 プレミアムプラン F22 Premium plan

プランPlans

  • Free — 基本機能
  • Free — basic features
  • Plus — AI検索使い放題・広告非表示・駐車履歴エクスポート
  • Plus — unlimited AI search, ad-free, parking history export
  • 詳細は subscription_plans マスター参照
  • See the subscription_plans master for details

購入フローPurchase flow

  1. プラン画面で「購入」タップ
  2. Tap "Buy" on the plan screen
  3. StoreKit2 / Play Billing で決済
  4. Process payment via StoreKit2 / Play Billing
  5. アプリ → Cloudflare Workers verify-iap-receipt にレシート送信
  6. App sends the receipt to the Cloudflare Workers verify-iap-receipt
  7. Cloudflare Workers が Apple / Google サーバーでレシート検証
  8. The Cloudflare Workers verifies the receipt against Apple / Google servers
  9. 成功時:user_subscriptions に行を追加、app_users.premium = true
  10. On success: insert a row into user_subscriptions and set app_users.premium = true
  11. クライアント側で機能ゲートを解除
  12. The client unlocks feature gates
F26 Google Maps共有受信 F26 Google Maps share intake

目的Purpose

Google Maps で見ているスポットや経路の目的地を、1タップでParkyの駐車場検索の目的地に設定する。

Set a spot or route destination from Google Maps as the Parky parking search destination in a single tap.

主要フローMain flow

  1. ユーザーがGoogle Mapsの「共有」→アプリ一覧から「Parky」を選択
  2. User taps "Share" in Google Maps → selects "Parky" from the app list
  3. ParkyアプリがShare Intent(Android)/ Share Extension(iOS)でテキスト(Google Maps URL)を受信
  4. Parky receives the text (a Google Maps URL) via Share Intent (Android) / Share Extension (iOS)
  5. URLをパースし、緯度経度・地名を抽出
  6. Parse the URL and extract latitude, longitude, and place name
  7. 駐車場検索画面を開き、抽出した地点を目的地に自動設定
  8. Open the parking search screen with the extracted location pre-set as the destination

Google Maps URLパースパターンGoogle Maps URL parse patterns

  • 場所共有: /maps/place/.../@{lat},{lng},...@ 以降の緯度経度を抽出
  • Place share: /maps/place/.../@{lat},{lng},... → extract lat/lng after @
  • クエリ形式: ?q={lat},{lng} → クエリパラメータから抽出
  • Query format: ?q={lat},{lng} → extract from query params
  • 経路共有: /maps/dir/{出発地}/{目的地}/... → 目的地部分を抽出
  • Route share: /maps/dir/{origin}/{destination}/... → extract the destination
  • 短縮URL: maps.app.goo.gl/xxxxx → HTTP HEADでリダイレクト先を展開し、上記パターンで解析
  • Short URL: maps.app.goo.gl/xxxxx → resolve redirect via HTTP HEAD, then parse with above patterns
  • 地名抽出: /place/{地名}/ パターンからデコード
  • Place name: decode from the /place/{name}/ pattern

プラットフォーム実装Platform implementation

Android iOS
受信メカニズムReceive mechanism intent-filter (ACTION_SEND, text/plain) Share Extension
FlutterパッケージFlutter package receive_sharing_intent or share_handler

例外Exceptions

  • パース失敗(未知のURL形式)→ 手動入力画面にフォールバックし、受信URLをテキストフィールドに表示
  • Parse failure (unknown URL format) → fall back to manual input screen showing the received URL in the text field
  • 短縮URLの展開失敗(ネットワークエラー)→ リトライ or 手動入力
  • Short URL resolution failure (network error) → retry or manual input
F27 所要時間→入庫時刻自動設定 F27 Travel time → auto-set entry time

目的Purpose

現在地から目的地までの車での所要時間を自動算出し、入庫開始時刻の初期値を設定することで、料金シミュレーションの精度を向上させる。

Automatically calculate driving time from the current location to the destination and pre-fill the entry time, improving fee simulation accuracy.

主要フローMain flow

  1. 目的地が確定(手動入力 or Google Maps共有受信)かつ現在地GPSが取得済み
  2. Destination is set (manual input or Google Maps share) and current GPS location is available
  3. Mapbox Directions API(driving-traffic プロファイル)を呼び出し
  4. Call the Mapbox Directions API (driving-traffic profile)
  5. レスポンスの duration(秒)を取得
  6. Obtain duration (in seconds) from the response
  7. 入庫開始時刻 = 現在時刻 + duration を自動設定(ユーザーは手動で変更可能)
  8. Auto-set entry time = current time + duration (user can override manually)
  9. 料金シミュレーション(F09)が自動再計算される
  10. Fee simulation (F09) automatically recalculates

APIAPI

GET https://api.mapbox.com/directions/v5/mapbox/driving-traffic/
  {origin_lng},{origin_lat};{dest_lng},{dest_lat}
  ?access_token={token}

レスポンス例:

Example response:

{
  "routes": [{
    "duration": 1830,    // 秒 (30分30秒)
    "distance": 12500    // メートル
  }]
}

料金Pricing

  • Mapbox Directions API: 月100,000リクエスト無料(driving-traffic 含む)
  • Mapbox Directions API: 100,000 requests/month free (including driving-traffic)

UXUX

  • 所要時間表示:「目的地まで約31分(12.5km)」のようにUIに表示
  • Display travel time: show "About 31 min to destination (12.5 km)" in the UI
  • 入庫時刻フィールドに自動入力されるが、タップで変更可能(あくまで初期値)
  • Entry time field is auto-filled but can be changed by tapping (it is only a default)
  • driving-traffic プロファイルによりリアルタイム渋滞を考慮した所要時間を取得
  • The driving-traffic profile provides travel times that account for real-time traffic conditions

例外Exceptions

  • GPS未取得 → 所要時間計算をスキップ、入庫時刻は空欄のまま(ユーザー手動入力)
  • GPS not available → skip travel time calculation, leave entry time blank (user enters manually)
  • Directions API エラー → 所要時間表示なし、入庫時刻は空欄
  • Directions API error → no travel time shown, entry time left blank