# 画面設計書 2-Places画面

## 概要

本ドキュメントは、Wikipedia iOSアプリのPlaces画面の設計仕様を記載したものである。

### 本画面の処理概要

Places画面は、地図上に現在地周辺のWikipedia記事を表示する画面である。ユーザーは地図またはリスト形式で近くの記事を探索できる。

**業務上の目的・背景**：ユーザーが物理的な場所に関連するWikipediaコンテンツを発見できるようにする。旅行中や散歩中など、現在地周辺の興味深い場所や歴史的建造物について学ぶことができる。位置情報と知識の融合により、より文脈に沿った学習体験を提供する。

**画面へのアクセス方法**：タブバーの2番目の項目（Places）をタップすることでアクセス。

**主要な操作・処理内容**：
1. 地図上での記事ピン表示とタップによるプレビュー
2. 地図とリスト表示の切り替え（セグメントコントロール）
3. 現在地への再センタリング
4. エリア内の記事検索（「この地域を検索」ボタン）
5. トップ記事/保存済み記事のフィルタリング
6. 検索バーからの場所・記事検索
7. プロファイル・タブボタンからの画面遷移

**画面遷移**：
- 遷移元：タブバー
- 遷移先：Article画面、ArticlePopover画面、Search画面、プロファイル画面、タブ一覧画面

**権限による表示制御**：位置情報の許可状態により、現在地表示やユーザー位置へのセンタリング機能の可否が変化。初回表示時に位置情報許可ダイアログを表示。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 18 | 近くの記事（Places） | 主機能 | 現在地周辺のWikipedia記事を地図上に表示 |
| 19 | 地図/リスト切替 | 補助機能 | 地図表示とリスト表示の切り替え |
| 20 | 位置情報検索 | 主機能 | 位置情報を利用した記事検索、地図エリア内の記事取得 |
| 11 | 記事検索 | 補助機能 | 検索バーからの記事検索 |
| 44 | プロファイル画面 | 遷移先機能 | プロファイルボタンタップでプロファイル画面へ遷移 |
| 61 | タブ一覧 | 遷移先機能 | タブボタンタップでタブ一覧画面へ遷移 |

## 画面種別

地図/一覧（切替可能）

## URL/ルーティング

- エントリーポイント：タブバー経由
- Storyboard ID：`PlacesViewController`
- Objective-C名：`WMFPlacesViewController`

## 入出力項目

| 項目名 | 入力/出力 | データ型 | 説明 |
|--------|----------|----------|------|
| 現在地座標 | 入力 | CLLocationCoordinate2D | ユーザーの現在位置 |
| 表示領域 | 入力 | MKCoordinateRegion | 地図の表示範囲 |
| 検索テキスト | 入力 | String | 検索バーに入力されたテキスト |
| フィルタ種別 | 入力 | PlaceSearchFilter | .top / .saved |
| 記事リスト | 出力 | [WMFArticle] | 表示する記事の配列 |

## 表示項目

| 項目名 | データソース | 表示条件 | 備考 |
|--------|-------------|----------|------|
| 地図ビュー | MapKit | 常時（地図モード時） | ArticlePlaceViewでピン表示 |
| 記事リスト | WMFArticle | 常時（リストモード時） | ArticleLocationCollectionViewController |
| 現在地ボタン | - | 位置情報許可時 | 現在地へ再センタリング |
| 検索再実行ボタン | - | 地図移動後 | 「この地域を検索」 |
| フィルタボタン | - | 常時 | トップ記事/保存済み記事切替 |

## イベント仕様

### 1-地図ピンタップ

地図上のArticlePlaceViewをタップすると、ArticlePopoverViewControllerがポップオーバーで表示され、記事のプレビューを確認できる。グループ化されたピンの場合は、地図がズームインしてグループを展開。

### 2-地図/リスト切替

セグメントコントロールで地図表示とリスト表示を切り替え。`updateViewModeFromSegmentedControl`メソッドで処理。VoiceOver有効時はリストビューがデフォルト。

### 3-現在地再センタリング

`recenterOnUserLocationButton`タップで`recenterOnUserLocation`メソッドが呼び出され、地図が現在地を中心に再配置される。

### 4-エリア検索

地図を移動後に表示される「Results in this area」ボタンをタップすると、`redoSearch`メソッドで表示領域内の記事を再検索。

### 5-フィルタ変更

フィルタボタンタップでUIAlertControllerを表示。「Top read articles」または「Saved articles」を選択し、`currentSearchFilter`を更新して検索を再実行。

### 6-検索実行

検索バーに入力後、`PlaceSearchService`を通じてWikipedia APIおよびWikidata APIで検索を実行。検索結果は地図上のピンまたはリストに反映。

## データベース更新仕様

### 操作別データベース影響一覧

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 記事取得 | WMFArticle | SELECT/INSERT/UPDATE | 位置情報付き記事の取得・作成 |
| 検索履歴保存 | PlaceSearch | INSERT | 検索履歴の保存 |
| 保存記事フィルタ | WMFArticle | SELECT | 保存済み記事のフィルタリング |

### テーブル別更新項目詳細

#### WMFArticle

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | quadKey, coordinate | 表示領域内の記事 | quadKeyで空間検索最適化 |
| UPDATE | placesSortOrder | 検索結果の順序 | 表示順序管理 |

## メッセージ仕様

| メッセージID | メッセージ内容 | 表示条件 | 種別 |
|-------------|---------------|----------|------|
| places-search-this-area | Results in this area | 地図移動後 | ボタン |
| places-no-saved-articles-have-location | None of your saved articles have location information | 保存記事フィルタで結果なし | 警告 |
| places-search-did-you-mean | Did you mean %1$@? | 検索結果なし時の候補あり | 提案 |

## 例外処理

- **位置情報未許可**：位置情報許可プロンプトを表示、またはデフォルト検索を実行
- **検索結果なし**：「Did you mean」ボタンで代替候補を提示
- **ネットワークエラー**：WMFAlertManagerでエラーメッセージを表示

## 備考

- PlacesViewControllerはArticleLocationCollectionViewControllerを継承
- MKMapViewをラップしたMapViewクラスを使用
- quadKeyによる空間インデックスでパフォーマンス最適化
- アニメーション付きのピングループ化機能

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

位置情報付き記事の管理方法を理解。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ArticlePlace.swift | `Wikipedia/Code/ArticlePlace.swift` | 地図上のピンを表すモデル、MKAnnotation準拠 |
| 1-2 | PlaceSearch.swift | `Wikipedia/Code/PlaceSearch.swift` | 検索条件を表すモデル、filter/type/region |

**読解のコツ**: quadKeyは空間を分割するキーで、効率的な範囲検索に使用される。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PlacesViewController.swift | `Wikipedia/Code/PlacesViewController.swift` | メインViewController、行116-188でviewDidLoad |

**主要処理フロー**:
1. **行116 viewDidLoad**: MapViewの初期化、LocationManagerの設定
2. **行190 viewWillAppear**: 位置情報の認証状態確認、検索実行
3. **行562-584 currentSearch**: 検索条件設定時にperformSearchを呼び出し

#### Step 3: 検索・データ取得層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | PlaceSearchService.swift | `Wikipedia/Code/PlaceSearchService.swift` | 検索サービス、API呼び出しとCore Data連携 |
| 3-2 | WMFLocationSearchFetcher.swift | `WMF/Sources/WMF/Fetchers/WMFLocationSearchFetcher.swift` | 位置情報ベースのAPI検索 |

#### Step 4: 地図表示層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MapView.swift | `Wikipedia/Code/MapView.swift` | MKMapViewのラッパー |
| 4-2 | ArticlePlaceView.swift | `Wikipedia/Code/ArticlePlaceView.swift` | 地図上のピンカスタムビュー |

### プログラム呼び出し階層図

```
PlacesViewController
    │
    ├─ MapView (MKMapView wrapper)
    │      └─ ArticlePlaceView (custom annotation)
    │
    ├─ PlaceSearchService
    │      ├─ WMFLocationSearchFetcher (API)
    │      ├─ WMFSearchFetcher (text search)
    │      └─ MWKDataStore (Core Data)
    │
    ├─ LocationManager
    │      └─ CLLocationManager
    │
    ├─ ArticleLocationCollectionViewController (list view)
    │
    └─ ArticlePopoverViewController (preview)
```

### データフロー図

```
[入力]               [処理]                    [出力]

User Location ───▶ LocationManager ───▶ Map Center Update
                         │
Map Region ───────▶ PlaceSearchService ───▶ API Request
                         │
API Response ─────▶ articleFetchedResultsController ───▶ Map Pins
                         │
                         ▼
                    Core Data (WMFArticle)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PlacesViewController.swift | `Wikipedia/Code/PlacesViewController.swift` | ソース | メインViewController |
| MapView.swift | `Wikipedia/Code/MapView.swift` | ソース | 地図ビューラッパー |
| ArticlePlaceView.swift | `Wikipedia/Code/ArticlePlaceView.swift` | ソース | ピンカスタムビュー |
| ArticlePlace.swift | `Wikipedia/Code/ArticlePlace.swift` | ソース | ピンデータモデル |
| PlaceSearchService.swift | `Wikipedia/Code/PlaceSearchService.swift` | ソース | 検索サービス |
| PlaceSearch.swift | `Wikipedia/Code/PlaceSearch.swift` | ソース | 検索条件モデル |
| ArticlePopoverViewController.swift | `Wikipedia/Code/ArticlePopoverViewController.swift` | ソース | 記事プレビュー |
| ArticleLocationCollectionViewController.swift | `Wikipedia/Code/ArticleLocationCollectionViewController.swift` | ソース | リスト表示VC |
| LocationManager.swift | `Wikipedia/Code/LocationManager.swift` | ソース | 位置情報管理 |
