YAMAGATA STUDIO
ブログ一覧に戻る
surf monitorの開発

surf monitorの開発

2025年04月11日
ManusGensparkClineGemini

surf monitorという海岸ポイントの天候情報からマリンスポーツに適しているかどうかを判定するWebアプリを作成した。

ほぼ自分ではコーディングせず以下のツールのみ使用。

  • Google AI Studio(gemini 2.5 pro)で要件定義
  • Manusでプロトタイプ作成
  • Gensparkでサーフポイントの情報収集
  • Cline(gemini 2.5 pro)で微修正

Manusでプロトタイプ作成した時点でほぼ今の形はできていた。 (今思えば要件定義のファイルあれば最初からClineで最初から作っても良かったかも)

以下のようなプロンプトでプロトタイプを作成した。

以下の要件のWebアプリ作りたいです。
「要調査」と記載してある部分はあなたが深く調べて最適なものを提案してください。
まずはReadmeを作成してもらい、Readmeに従って開発を進めてください。

# サーフポイントリアルタイム監視アプリ 要件定義

## 1. 概要

九州エリアを中心としたサーフポイントの天候情報をリアルタイムで収集・分析し、サーフィン、SUP、ウィンドサーフィンなどのマリンスポーツに適したコンディションかを判定・表示するWebアプリケーション。PWAに対応し、スマートフォンでの利用体験を向上させる。

## 2. 目的

*   ユーザーが各マリンスポーツに適したサーフポイントを簡単に見つけられるようにする。
*   リアルタイムの天候情報とWebカメラ映像を提供し、現地状況の把握を助ける。
*   データに基づいたコンディション判定により、安全で快適なマリンスポーツ体験をサポートする。

## 3. ターゲットユーザー

*   サーファー、SUP愛好家、ウィンドサーファー(初心者~上級者)
*   これからマリンスポーツを始めたいと考えている人
*   特定のエリアの波や風の状況をリアルタイムで知りたい人

## 4. 主要機能

### 4.1. コンディション判定

*   **対象スポーツ:** サーフィン、SUP、ウィンドサーフィン
*   **判定ロジック:** 各スポーツごとに、以下のデータ項目に基づきコンディションを判定し、スコア(0-100点)と4段階評価(最適, 良い, 可能, 不可)を算出する。
    *   **利用データ項目 (提案):**
        *   波高 (m)
        *   波周期 (s)
        *   風速 (m/s)
        *   風向 (角度または16方位など)
        *   潮位 (m または H/L)
        *   天気 (晴れ、曇り、雨など)
    *   **判定基準 (提案):**
        *   **サーフィン:**
            *   スコア要素: 波高(適度な高さ)、周期(長いほど良い)、風(弱いオフショア/サイドオフショアが良い)
            *   評価例:
                *   最適 (80-100): 波高 1.0-1.5m, 周期 8s+, 風 0-3m/s オフショア
                *   良い (60-79): 波高 0.5-2.0m, 周期 6s+, 風 0-5m/s オフ/サイドオフ
                *   可能 (40-59): 上記以外だが、危険性が低いコンディション
                *   不可 (0-39): フラット、クローズアウト、強風オンショアなど
        *   **SUP (クルージング想定):**
            *   スコア要素: 波高(低いほど良い)、風(弱いほど良い)
            *   評価例:
                *   最適 (80-100): 波高 < 0.2m, 風 < 2m/s
                *   良い (60-79): 波高 < 0.5m, 風 < 3m/s
                *   可能 (40-59): 上記以外だが、危険性が低いコンディション
                *   不可 (0-39): 高波、強風など
        *   **ウィンドサーフィン:**
            *   スコア要素: 風速(強いほど良い、上限あり)、風向(サイドショア/オンショアが良い場合も)
            *   評価例:
                *   最適 (80-100): 風 8-15m/s (サイドショア/オンショア)
                *   良い (60-79): 風 5-18m/s
                *   可能 (40-59): 上記以外だが、プレー可能な風がある
                *   不可 (0-39): 微風、または危険な強風
        *   **スコア閾値 (共通・提案):** 最適(80-100), 良い(60-79), 可能(40-59), 不可(0-39)
    *   **適用範囲:** 全ての登録ポイントで共通の基準を適用する。

### 4.2. サーフポイント表示

*   **一覧表示:**
    *   **地図表示:** 登録されているサーフポイントを地図上にピンで表示する。ピンの色やアイコンで現在のコンディション評価(最適/良い/可能/不可)を視覚的に示す。
    *   **リスト表示:** 地図と連動し、条件の良い(スコアが高い)ポイントから順にリスト表示する。リストにはポイント名、現在の評価、主要なコンディション情報(波高、風速など)を簡潔に表示する。
    *   **絞り込み/並び替え:** スポーツ種別(サーフィン/SUP/ウィンドサーフィン)で表示する評価を切り替えられるようにする。エリアによる絞り込み機能も設ける。
*   **詳細表示:**
    *   一覧からポイントを選択すると、そのポイントの詳細画面を表示する。
    *   **表示項目:**
        *   ポイント名
        *   現在のコンディション判定結果(各スポーツのスコアと評価)
        *   詳細な天候データ(波高、周期、風速、風向、潮位、天気)
        *   今後の天気・波・風の予報(例: 3時間ごと24時間分など)
        *   Webカメラ映像(利用可能な場合。ない場合は「カメラなし」と表示)
        *   ポイントの場所を示す地図
        *   **付帯情報 (管理画面から入力):**
            *   トイレの有無
            *   水道の有無
            *   着替えスペースの有無
            *   周辺のマリンスポーツ関連店舗情報(ショップ、レンタルなど)

### 4.3. データ収集・更新

*   **実行環境:** Cloud Run Job (Python)
*   **実行頻度:** 10分に1回(デフォルト設定。変更可能とする)
*   **処理内容:**
    1.  Firestoreから対象サーフポイントのリスト(緯度経度など)を取得。
    2.  選択されたデータソースAPIから各ポイントの最新の天候情報を取得。
    3.  取得したデータに基づき、各スポーツのコンディションを判定(スコア・評価算出)。
    4.  判定結果と最新の天候情報をFirestoreの各ポイントデータに保存(上書き)。予報データも同時に取得・保存する。
*   **データソース (提案・要調査):**
    *   **第一候補: Open-Meteo API**
        *   理由: 無料枠あり、必要な気象・波浪データ(緯度経度指定可)、潮位予測も提供可能性、商用利用に関する規約が比較的明確。
        *   要確認事項: 最新の利用規約、必要なデータ項目が全て取得可能か、API制限、クレジット表示の要否。
    *   代替候補: 気象庁データ、他の気象API(有料含む)、信頼できる波情報サイトのAPI(提供があれば)
    *   **注意:** Webスクレイピングは原則として避ける(利用規約違反、サイト構造変更への脆弱性)。

### 4.4. Webカメラ表示

*   Firestoreに登録された公開WebカメラのURL(例: YouTube Live埋め込みURL、MJPEGストリームURLなど)を詳細画面に埋め込み表示する。
*   URLが登録されていないポイントでは、「Webカメラはありません」等のメッセージを表示する。
*   **注意:** 埋め込み表示が各Webカメラの提供元によって許可されているか、利用規約を確認する必要がある。

### 4.5. ユーザー機能

*   **認証:** Firebase Authenticationを利用したメールアドレス/パスワード認証、Google認証などを実装。
*   **ログイン状態:**
    *   未ログインユーザーでも、ポイント一覧・詳細表示、コンディション確認、Webカメラ閲覧など、主要な機能は利用可能とする。
    *   ログインユーザーのみ、以下の機能を利用可能とする。
*   **お気に入り登録:**
    *   ユーザーは好みのサーフポイントを「お気に入り」として登録・解除できる。
    *   お気に入りリストページや、一覧表示でのフィルタリング機能を提供する。

### 4.6. 管理機能

*   **目的:** アプリケーション管理者(開発者)がサーフポイント情報やその他の設定を管理するためのWebインターフェース。
*   **機能:**
    *   サーフポイントのCRUD (作成, 読み取り, 更新, 削除)
        *   ポイント名、緯度経度、エリア、WebカメラURL、付帯情報(トイレ有無など)、周辺店舗情報などの登録・編集。
    *   (将来的には)ユーザー管理、お知らせ配信機能など。
*   **アクセス:** Basic認証や特定のGoogleアカウントによるログインなどでアクセスを制限する。

### 4.7. PWA (Progressive Web App) 機能

*   **目的:** スマートフォンでのネイティブアプリに近い利用体験を提供する。
*   **実装:**
    *   `next-pwa`等のライブラリを使用し、Service Workerを実装する。
    *   Web App Manifest (`manifest.json`) を設定し、以下を可能にする:
        *   「ホーム画面に追加」機能(アイコン、アプリ名、テーマカラーを設定)
        *   ホーム画面に追加されたアイコンからアプリを起動。
        *   起動時にアドレスバーなどを非表示にする(Standaloneモード)。
*   **オフライン表示:**
    *   Service Workerのキャッシュ機能を利用し、オフライン時やネットワーク不安定時でも、最後に取得したコンディション情報やポイント情報を表示できるようにする。
*   **ホーム画面追加ボタン制御:**
    *   アプリがブラウザで開かれた場合のみ「ホーム画面に追加する」ボタンを表示する。
    *   ホーム画面のアイコンから起動された場合(Standaloneモード)は、このボタンを非表示にする。

## 5. データ要件

### 5.1. 取得データ項目

*   **必須:** ポイント名、緯度経度、波高、波周期、風速、風向、潮位、天気
*   **任意:** WebカメラURL、付帯情報(トイレ、水道、着替え場所)、周辺店舗情報
*   **予報データ:** 上記天候データの時間別予報

### 5.2. Firestoreデータ構造 (提案)

*   **`points` コレクション:**
    *   ドキュメントID: (自動生成)
    *   `name`: String
    *   `location`: GeoPoint
    *   `area`: String (例: "福岡")
    *   `webcamUrl`: String (null許容)
    *   `hasToilet`: Boolean
    *   `hasWater`: Boolean
    *   `hasChangingRoom`: Boolean
    *   `nearbyShops`: Array<Map> or String (構造は要検討)
    *   `latestConditions`: Map
        *   `updatedAt`: Timestamp (データ更新時刻)
        *   `surfing`: Map { `score`: Number, `rating`: String, `waveHeight`: Number, ... }
        *   `sup`: Map { `score`: Number, `rating`: String, `windSpeed`: Number, ... }
        *   `windsurfing`: Map { `score`: Number, `rating`: String, `windSpeed`: Number, ... }
        *   `common`: Map { `tide`: String/Number, `weather`: String } (共通データ)
    *   `forecast`: Array<Map> (時系列予報データ)
        *   `time`: Timestamp
        *   `surfing`: Map { `score`: Number, `rating`: String, ... }
        *   `sup`: Map { `score`: Number, `rating`: String, ... }
        *   `windsurfing`: Map { `score`: Number, `rating`: String, ... }
        *   `common`: Map { `tide`: String/Number, `weather`: String }
*   **`users` コレクション:**
    *   ドキュメントID: Firebase Auth UID
    *   `favoritePoints`: Array<String> (ポイントのドキュメントIDを格納)
    *   `createdAt`: Timestamp

## 6. 技術要件

*   **バックエンド (データ収集):** Python, Cloud Run Job
*   **フロントエンド:** Next.js (React), TypeScript (推奨)
*   **データベース:** Firestore (Database ID: `marin-sports`)
*   **認証:** Firebase Authentication
*   **インフラ:** Google Cloud Platform (GCP)
*   **地図表示ライブラリ:** Mapbox GL JS, Google Maps Platform (要APIキー、利用料確認), Leaflet など
*   **UIライブラリ:** Material UI (MUI), Chakra UI, Tailwind CSS など (選択が必要)

## 7. 非機能要件

*   **パフォーマンス:**
    *   データ更新頻度: 10分間隔(Cloud Run Jobのスケジュール)
    *   フロントエンド表示: 地図やリストの表示がスムーズであること。初回ロード時間を最適化する(Next.jsの機能活用)。
*   **ユーザビリティ:**
    *   レスポンシブデザイン: PC、タブレット、スマートフォンで適切に表示・操作できること。
    *   PWA対応: ホーム画面追加、オフライン表示。
    *   直感的なUI: コンディション評価やポイント情報が分かりやすいこと。
*   **メンテナンス性:**
    *   管理画面によるポイント情報の容易な更新。
    *   コードの可読性、コンポーネント化。
*   **セキュリティ:**
    *   管理画面へのアクセス制御。
    *   FirebaseセキュリティルールによるFirestoreへのアクセス制御。
*   **拡張性:**
    *   対象エリアやポイントの追加が容易であること。
    *   対応スポーツの追加や判定ロジックの変更に対応しやすい構造。