diff --git a/README.md b/README.md index fbd03fd..07f06ff 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/docs/development.md b/docs/development.md index e4c14a8..79eb8f0 100644 --- a/docs/development.md +++ b/docs/development.md @@ -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=` to write (the confirm +flag must echo the deployment's own `KEY_PREFIX`, or the script refuses), and +`--restore= --confirm-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 diff --git a/docs/project-structure.md b/docs/project-structure.md index ea88269..51c0b94 100644 --- a/docs/project-structure.md +++ b/docs/project-structure.md @@ -81,7 +81,7 @@ generated region data* in [development.md](development.md). behind a generated `boundaries/index.js` barrel - `panos/.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