docs: refresh README and docs for the region tree and pipeline scripts

Update project overview to describe region tree refactor, document data
pipeline scripts, clarify project structure, and align with current practices.
This commit is contained in:
tiennm99 committed 2026-08-30 20:52:36 +07:00
1 parent 997695659b
commit bed486c742
3 files changed
+31 -22

No files matched your search

+5 -5
View File
@@ -1,10 +1,10 @@
# VNGeoGuessr
A GeoGuessr clone focused on Vietnamese locations with accurate boundary detection and anti-cheat security. Play geolocation guessing games across 5 Vietnamese locations using real street-level imagery.
A GeoGuessr clone focused on Vietnamese locations with accurate boundary detection and anti-cheat security. Play geolocation guessing games across a region tree covering the whole country using real street-level imagery.
## 🎮 Features
- **5 Vietnamese Locations**: Ha Noi, Da Nang, Ho Chi Minh, Da Lat, Duc Hoa (Long An)
- **Region Tree**: Whole country, 5 provinces, 61 districts — including Da Lat (Lam Dong) and Duc Hoa (Long An)
- **360° Street View**: Mapillary panoramic images with PhotoSphere viewer
- **Anti-Cheat Security**: Server-side session management prevents cheating
- **Distance-Based Scoring**: 0-5 point system based on accuracy
@@ -25,7 +25,7 @@ For detailed information about this project, see the documentation in `/docs/`:
## 🚀 Getting Started
### Prerequisites
- Node.js 18+
- Node.js 24+
- npm 11+
- Redis server (for leaderboards)
@@ -56,13 +56,13 @@ Open [http://localhost:3000](http://localhost:3000) to play the game.
- **Street View**: Mapillary API + PhotoSphere Viewer
- **Maps**: Leaflet + OpenStreetMap
- **Geographic Data**: Nominatim API + Turf.js
- **Storage**: Redis (leaderboards) + In-memory sessions
- **Storage**: Upstash Redis (leaderboards and game sessions)
- **UI Components**: shadcn/ui
## 🎯 How to Play
1. Enter your username
2. Select a Vietnamese location
2. Pick a region from the country/province/district tree
3. View the 360° street panorama
4. Place your guess on the map
5. Earn points based on accuracy (closer = more points)
+17 -12
View File
@@ -130,20 +130,21 @@ sends; the path form Upstash also supports (`GET /set/key/value`) returns 404.
Run the scripts in this order -- each reads what the previous one wrote:
```bash
node scripts/build-region-boundaries.mjs # OSM/Nominatim -> boundaries + region tree
node scripts/build-pano-index.mjs # Mapillary z14 tiles -> per-province pano index
node scripts/assign-pano-districts.mjs # clip + partition panos by district; writes counts.js
npm run data:boundaries # OSM/Nominatim -> boundaries + region tree
npm run data:panos # Mapillary z14 tiles -> per-province pano index
npm run data:districts # clip + partition panos by district; writes counts.js
```
Each script's header comment carries its flags and its cost; read it before
running. Two things worth knowing up front:
Each underlying script's header comment carries its flags and its cost; read it
before running. Two things worth knowing up front:
- `build-region-boundaries.mjs --regenerate` rebuilds the provinces, the barrel
and the tree from what is already on disk, with no network calls. Use it after
- `npm run data:repartition` reruns the boundaries step with `--regenerate`
(rebuilds the provinces, the barrel and the tree from what is already on
disk) and then the districts step, with no network calls. Use it after
hand-editing a boundary.
- `build-pano-index.mjs` spends Mapillary tile requests against a 50,000/day
cap. `assign-pano-districts.mjs` spends none -- it only re-partitions indexes
that already exist, and refuses to rewrite `counts.js` on a partial run.
- `npm run data:panos` spends Mapillary tile requests against a 50,000/day cap.
`npm run data:districts` spends none -- it only re-partitions indexes that
already exist, and refuses to rewrite `counts.js` on a partial run.
### Migrating leaderboards
@@ -153,8 +154,12 @@ default** and copies rather than moves, so the source boards survive.
Deploy first, then migrate. The new code writes to the new keys immediately; a
migration run before the deploy would copy a board that is still being written
to under its old name. Run the script's `--help` for the apply, verify and
restore flags.
to under its old name. Run `npm run leaderboard:migrate` with no flags for a
dry run; add `--apply --confirm-prefix=<key prefix>` to write (the confirm
flag must echo the deployment's own `KEY_PREFIX`, or the script refuses), and
`--restore=<backup.json> --confirm-prefix=<key prefix>` to undo from the
backup file the apply run wrote. `--dry-run` is a guard, not a mode switch --
combining it with `--apply` throws instead of guessing which one you meant.
## shadcn/ui Configuration
+9 -5
View File
@@ -81,7 +81,7 @@ generated region data* in [development.md](development.md).
behind a generated `boundaries/index.js` barrel
- `panos/<province>.json` - Panorama ids, coordinates, and district assignment,
behind a generated `panos/index.js` barrel. **Server-side only** - roughly
29MB of exact answers
28MB of exact answers
### Utility Libraries (`src/lib/`)
- `utils.js` - Utility functions including `cn()` for class name merging
@@ -110,9 +110,13 @@ Each carries a header comment with its flags and its cost.
- `lib/leaderboard-migration.mjs` - Copy, verify, regression-check and restore
## Tests (`tests/`)
Vitest, one file per module. `fake-upstash-redis.js`, `mock-upstash.js`,
`redis-harness.js` and `wait-for-srh.js` are the shared harness that lets the
same files run against either the in-memory fake or a real Redis.
Vitest, mostly one file per `src/lib/` module, plus a route test for
`new-game`, `guess`, and `debug/region-coverage`. The `skip`, `leaderboard`,
`debug/mapillary`, and `debug/pano` routes have no dedicated test file; their
underlying `src/lib/` logic (`leaderboard.js`, `mapillary.js`) is still
covered. `fake-upstash-redis.js`, `mock-upstash.js`, `redis-harness.js` and
`wait-for-srh.js` are the shared harness that lets the same files run against
either the in-memory fake or a real Redis.
Nothing here exercises the React components: there is no component-test
dependency, so `GameClient.js`, `RegionPicker.js`, `RegionSelect.js` and the
@@ -130,5 +134,5 @@ coverage page are covered by manual testing only.
- Project planning documents and implementation plans
## Public Assets (`public/`)
- `*.svg` - SVG icons and graphics
- `zlp.jpg` - Donation QR code image
- Static assets served directly by Next.js