mirror of
https://github.com/tiennm99/vngeoguessr.git
synced 2026-10-13 22:16:31 +00:00
4770de51d4e05dca009554b3d1c4a74f76bdaf02
A guess is credited to the district its panorama sits in, then to that district's province, then to Vietnam. Each level keeps its own board, so a player can top District 7 without touching the national table. Every existing point survives untouched. The country maps to the leaderboard:vietnam and distance:vietnam keys that already exist rather than to a new leaderboard:city:vn, so the national board keeps accumulating instead of restarting. The ':city:' segment in the key namespace is now a misnomer -- it holds district and province codes alike -- but renaming it to ':region:' would strand every key holding a player's history, so it stays, with a comment recording why. Da Lat and Duc Hoa keep their bare codes for the same reason. Ha Noi, Da Nang and Ho Chi Minh keep their totals on the province: those points predate districts and cannot be attributed to one, so their boards stay continuous while district boards start at zero. Levels are written in parallel. They are independent keys and none reads another's state, so serialising them would add two round trips of latency to every guess for nothing. Region codes and the leaderboard limit are validated inside the library rather than only in the routes. The key builder lowercases whatever it is handed straight into a Redis key, and the routes are not its only callers -- the migration script and anything added later bypass them entirely. The adapter gains scanKeys, which the migration needs to enumerate what it is about to touch. It applies the key prefix to the pattern and strips it from the results, because a caller that scanned 'leaderboard:*' directly would match nothing at all: every physical key carries the prefix, and an empty result is indistinguishable from an empty database. An empty KEY_PREFIX is no longer accepted, since enumeration with no prefix would reach every other project sharing the database. The migration seeds Lam Dong and Long An from Da Lat and Duc Hoa, whose history they inherit. It runs after the deploy, not before: migrating first leaves a window where a Da Lat guess credits the town and the country but not the province. It copies absolute scores so a second run converges rather than doubling, and empties the destination first so a player trimmed out of the source cannot survive in the copy with a stale score. An empty source is refused before that delete -- otherwise the destination is wiped and nothing written back, which reads as a clean no-op. Afterwards it confirms each destination matches its source and that nothing else went backwards, accepting that boards grow while the app serves traffic. Its backup can be restored through the same script. The migration logic lives in scripts/lib/ so its guards are reachable from a test rather than only by running it against a live database.
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.
🎮 Features
- 5 Vietnamese Locations: Ha Noi, Da Nang, Ho Chi Minh, Da Lat, 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
- Persistent Leaderboards: Redis-powered top 200 player rankings
- Accurate Boundaries: Nominatim API + Turf.js for precise city detection
📚 Documentation
For detailed information about this project, see the documentation in /docs/:
- Project Overview - Project summary and key characteristics
- Features - Complete feature list and game mechanics
- Tech Stack - Technology stack and dependencies
- Development Guidelines - Development setup and coding standards
- Game Flow - Complete gameplay flow documentation
- Project Structure - Codebase organization and architecture
🚀 Getting Started
Prerequisites
- Node.js 18+
- npm 11+
- Redis server (for leaderboards)
Development
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build
# Start production server
npm start
# Run linting
npm run lint
Open http://localhost:3000 to play the game.
🏗️ Built With
- Frontend: Next.js 15 + React 19 + Tailwind CSS 4
- Street View: Mapillary API + PhotoSphere Viewer
- Maps: Leaflet + OpenStreetMap
- Geographic Data: Nominatim API + Turf.js
- Storage: Redis (leaderboards) + In-memory sessions
- UI Components: shadcn/ui
🎯 How to Play
- Enter your username
- Select a Vietnamese location
- View the 360° street panorama
- Place your guess on the map
- Earn points based on accuracy (closer = more points)
- Compete for the top 200 leaderboard spots!
📋 Development Notes
- JavaScript Only: No TypeScript files
- Individual Parameters: Functions use separate parameters, not object destructuring
- Server-Side Security: Game coordinates never sent to client
- Session Management: Automatic cleanup after 30 minutes
🤝 Contributing
This project follows specific development guidelines. Please read the Development Guidelines before contributing.
Description
GeoGuessr clone for Vietnamese locations — Mapillary panoramas, Turf.js boundaries, Upstash REST leaderboards
Readme
Apache-2.0
14 MiB
0 Stars
1 Watchers
0 Forks
Languages
JavaScript
98.2%
CSS
1.8%