# idealistyu/city-ex architecture

> Architecture diagram of the GitHub repository idealistyu/city-ex, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/idealistyu/city-ex
- Repository: https://github.com/idealistyu/city-ex

## Overview

城市制霸 is a browser-based China city-footprint map: users choose a province or search for a city, assign one of five visit levels, and see the map and totals update. The main entry coordinates navigation and marking; browser-local state powers statistics and achievements. Users can also export map images, back up and restore marks, or encode marks in a share link that another visitor can open without a server. The graph reflects documented features and sampled module boundaries; some UI wiring is inferred only where the entry-point comments or README describe it.

Main entry points: [`src/main.js`](https://github.com/idealistyu/city-ex/blob/main/src/main.js) (App Coordinator), [`src/store.js`](https://github.com/idealistyu/city-ex/blob/main/src/store.js) (Mark Storage), [`src/achievements-page.js`](https://github.com/idealistyu/city-ex/blob/main/src/achievements-page.js) (Achievement Cards), [`src/map.js`](https://github.com/idealistyu/city-ex/blob/main/src/map.js) (Map View)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interaction["Map Interaction"]
  node_main["App Coordinator<br/>[main.js]"]
  node_map["Map View<br/>[map.js]"]
  node_levels["Levels and Totals<br/>[levels.js]"]
  node_picker["Level Picker<br/>[picker.js]"]
  node_locator["City Search<br/>[locator.js]"]
end

subgraph group_state["Local Progress"]
  node_store[("Mark Storage<br/>[store.js]")]
  node_browser[("Browser Storage")]
  node_backup["Backup Controls<br/>[backup-ui.js]"]
  node_backupcore["Backup Import Export<br/>[backup.js]"]
end

subgraph group_insights["Achievements"]
  node_achievementcalc["Achievement Rules<br/>[achievements.js]"]
  node_achievementstate["Unlock Tracking<br/>[achievements-ui.js]"]
  node_achievementpage["Achievement Cards"]
  node_badges["Badge Artwork<br/>[badges.js]"]
end

subgraph group_sharing["Export and Sharing"]
  node_imageui["Image Export UI<br/>[image-ui.js]"]
  node_countryexport["Country Image Export<br/>[export.js]"]
  node_provinceexport["Province Image Export<br/>[export-province.js]"]
  node_shareui["Share Controls<br/>[share-ui.js]"]
  node_share["Share Link Codec<br/>[share.js]"]
end

subgraph group_data["Map Data"]
  node_mapdata["Map Geometry<br/>[map-data.json]"]
  node_finedata["Fine Geometry<br/>[map-fine.json]"]
end

node_visitor(("Visitor"))
node_friend(("Link Recipient"))

node_visitor -->|"uses map"| node_main
node_main -->|"controls view"| node_map
node_main -->|"opens picker"| node_picker
node_main -->|"opens search"| node_locator
node_main -->|"reads and marks"| node_store
node_main -->|"updates totals"| node_levels
node_main -->|"coordinates achievements"| node_achievementstate
node_main -->|"offers export"| node_imageui
node_main -->|"offers backup"| node_backup
node_main -->|"offers sharing"| node_shareui
node_map -->|"reads geometry"| node_mapdata
node_map -->|"loads detail"| node_finedata
node_locator -->|"reads marks"| node_store
node_store -->|"persists locally"| node_browser
node_backup -->|"imports and exports"| node_backupcore
node_backupcore -->|"restores marks"| node_store
node_store -->|"notifies changes"| node_achievementstate
node_achievementstate -->|"evaluates progress"| node_achievementcalc
node_achievementstate -->|"opens page"| node_achievementpage
node_achievementpage -->|"reads progress"| node_achievementcalc
node_achievementpage -->|"reads marks"| node_store
node_achievementpage -->|"renders badges"| node_badges
node_imageui -->|"exports country"| node_countryexport
node_imageui -->|"exports province"| node_provinceexport
node_countryexport -->|"builds map"| node_map
node_provinceexport -->|"loads detail"| node_finedata
node_provinceexport -->|"rasterizes image"| node_countryexport
node_shareui -->|"encodes marks"| node_share
node_shareui -->|"reads marks"| node_store
node_share -->|"encodes link for"| node_friend
node_friend -->|"opens shared view"| node_main

click node_main "https://github.com/idealistyu/city-ex/blob/main/src/main.js"
click node_map "https://github.com/idealistyu/city-ex/blob/main/src/map.js"
click node_levels "https://github.com/idealistyu/city-ex/blob/main/src/levels.js"
click node_picker "https://github.com/idealistyu/city-ex/blob/main/src/picker.js"
click node_locator "https://github.com/idealistyu/city-ex/blob/main/src/locator.js"
click node_store "https://github.com/idealistyu/city-ex/blob/main/src/store.js"
click node_backup "https://github.com/idealistyu/city-ex/blob/main/src/backup-ui.js"
click node_backupcore "https://github.com/idealistyu/city-ex/blob/main/src/backup.js"
click node_achievementcalc "https://github.com/idealistyu/city-ex/blob/main/src/achievements.js"
click node_achievementstate "https://github.com/idealistyu/city-ex/blob/main/src/achievements-ui.js"
click node_achievementpage "https://github.com/idealistyu/city-ex/blob/main/src/achievements-page.js"
click node_badges "https://github.com/idealistyu/city-ex/blob/main/src/badges.js"
click node_imageui "https://github.com/idealistyu/city-ex/blob/main/src/image-ui.js"
click node_countryexport "https://github.com/idealistyu/city-ex/blob/main/src/export.js"
click node_provinceexport "https://github.com/idealistyu/city-ex/blob/main/src/export-province.js"
click node_shareui "https://github.com/idealistyu/city-ex/blob/main/src/share-ui.js"
click node_share "https://github.com/idealistyu/city-ex/blob/main/src/share.js"
click node_mapdata "https://github.com/idealistyu/city-ex/blob/main/src/map-data.json"
click node_finedata "https://github.com/idealistyu/city-ex/blob/main/src/map-fine.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_map,node_levels,node_picker,node_locator toneBlue
class node_store,node_browser,node_backup,node_backupcore toneAmber
class node_achievementcalc,node_achievementstate,node_achievementpage,node_badges toneMint
class node_imageui,node_countryexport,node_provinceexport,node_shareui,node_share toneRose
class node_mapdata,node_finedata,node_visitor,node_friend toneIndigo
```

## Components

### Map Interaction

- [App Coordinator](https://github.com/idealistyu/city-ex/blob/main/src/main.js): `src/main.js`
- [Map View](https://github.com/idealistyu/city-ex/blob/main/src/map.js): `src/map.js`
- [Levels and Totals](https://github.com/idealistyu/city-ex/blob/main/src/levels.js): `src/levels.js`
- [Level Picker](https://github.com/idealistyu/city-ex/blob/main/src/picker.js): `src/picker.js`
- [City Search](https://github.com/idealistyu/city-ex/blob/main/src/locator.js): `src/locator.js`

### Local Progress

- [Mark Storage](https://github.com/idealistyu/city-ex/blob/main/src/store.js): `src/store.js`
- **Browser Storage**
- [Backup Controls](https://github.com/idealistyu/city-ex/blob/main/src/backup-ui.js): `src/backup-ui.js`
- [Backup Import Export](https://github.com/idealistyu/city-ex/blob/main/src/backup.js): `src/backup.js`

### Achievements

- [Achievement Rules](https://github.com/idealistyu/city-ex/blob/main/src/achievements.js): `src/achievements.js`
- [Unlock Tracking](https://github.com/idealistyu/city-ex/blob/main/src/achievements-ui.js): `src/achievements-ui.js`
- [Achievement Cards](https://github.com/idealistyu/city-ex/blob/main/src/achievements-page.js): `src/achievements-page.js`
- [Badge Artwork](https://github.com/idealistyu/city-ex/blob/main/src/badges.js): `src/badges.js`

### Export and Sharing

- [Image Export UI](https://github.com/idealistyu/city-ex/blob/main/src/image-ui.js): `src/image-ui.js`
- [Country Image Export](https://github.com/idealistyu/city-ex/blob/main/src/export.js): `src/export.js`
- [Province Image Export](https://github.com/idealistyu/city-ex/blob/main/src/export-province.js): `src/export-province.js`
- [Share Controls](https://github.com/idealistyu/city-ex/blob/main/src/share-ui.js): `src/share-ui.js`
- [Share Link Codec](https://github.com/idealistyu/city-ex/blob/main/src/share.js): `src/share.js`

### Map Data

- [Map Geometry](https://github.com/idealistyu/city-ex/blob/main/src/map-data.json): `src/map-data.json`
- [Fine Geometry](https://github.com/idealistyu/city-ex/blob/main/src/map-fine.json): `src/map-fine.json`

### Other components

- **Visitor**
- **Link Recipient**

## Connections

- Visitor → App Coordinator: uses map
- App Coordinator → Map View: controls view
- App Coordinator → Level Picker: opens picker
- App Coordinator → City Search: opens search
- App Coordinator → Mark Storage: reads and marks
- App Coordinator → Levels and Totals: updates totals
- App Coordinator → Unlock Tracking: coordinates achievements
- App Coordinator → Image Export UI: offers export
- App Coordinator → Backup Controls: offers backup
- App Coordinator → Share Controls: offers sharing
- Map View → Map Geometry: reads geometry
- Map View → Fine Geometry: loads detail
- City Search → Mark Storage: reads marks
- Mark Storage → Browser Storage: persists locally
- Backup Controls → Backup Import Export: imports and exports
- Backup Import Export → Mark Storage: restores marks
- Mark Storage → Unlock Tracking: notifies changes
- Unlock Tracking → Achievement Rules: evaluates progress
- Unlock Tracking → Achievement Cards: opens page
- Achievement Cards → Achievement Rules: reads progress
- Achievement Cards → Mark Storage: reads marks
- Achievement Cards → Badge Artwork: renders badges
- Image Export UI → Country Image Export: exports country
- Image Export UI → Province Image Export: exports province
- Country Image Export → Map View: builds map
- Province Image Export → Fine Geometry: loads detail
- Province Image Export → Country Image Export: rasterizes image
- Share Controls → Share Link Codec: encodes marks
- Share Controls → Mark Storage: reads marks
- Share Link Codec → Link Recipient: encodes link for
- Link Recipient → App Coordinator: opens shared view
