Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Latest commit

 

History

41 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenQuest

Hackathon-Projekt: öffentliche Daten der Stadt Münster analysieren, aufbereiten und zurückgeben.

Domain: openquest.fun

Frontend prototype

The repository includes a mobile-first Next.js prototype for the Münster tree quest demo. It implements phases 1 and 2 of the prototype brief, plus a local admin review demo. The interface is in German.

Run locally

Requires Node.js 20.9 or newer and pnpm.

pnpm install --frozen-lockfile
pnpm dev

Open http://localhost:3000. For a production build, run pnpm build followed by pnpm start.

Phone app

The frontend can be packaged as an Android/iOS app with the phone's own camera and GPS (Capacitor): see docs/mobile-app.md.

Included features

  • Responsive Münster map with light, colorful OpenStreetMap tiles and a localized tree-density overlay from the city's public digital tree inventory. Individual street trees appear as small dots when zoomed in. The browser refreshes the visible area from Münster's WFS; public/data/muenster-trees-snapshot.json is a bundled 25 September 2026 fallback. The 24 regular Quest markers now use distinct, original WFS tree coordinates matched by recorded genus and nearby location (retrieved 26 September 2026); their street labels come from Münster's street WFS. Exact species, verification status, rarity, and game progress remain demo content because the tree inventory supplies genus and position only. The separate presentation tree at Hafenweg 7 keeps its fixed stage location and does not affect the density overlay. Tree data: Stadt Münster, Digitales Baumkataster, dl-de/by-2.0.
  • Markers for open, confirmed and reported missing trees, tree detail sheets, map filters and geolocation with a manual fallback.
  • Seven schematic game districts with clearer borders and owner colors, an always-visible top-three badge in each mapped quarter, a crown for the sole leader, shared ranks for ties, and a focused capture view with a personal progress goal. The shapes are not official Münster district boundaries.
  • Bottom navigation and initial missions, collection and profile screens.
  • Design 2.0 visual system across the map, tree profile, scan, collection, missions, profile and admin dashboard: floating navigation, richer motion, clearer status and a premium card presentation. A searchable nature lexicon at /lexicon contains 13 species/group portraits with leaf, bark, fruit, season and habitat cues. These are editorial prototype notes; they are not measured facts about an individual tree. Tree profiles and the card viewer link to the corresponding portrait.
  • The supplied OpenQuest chest-and-wordmark artwork is used throughout the app, with the chest as the browser icon. Display headings use a locally bundled Press Start 2P font; its OFL license is included in public/fonts/OFL.txt.
  • Shared player context with local progress and level calculation (src/lib/playerProgress.ts). V3 seeds the Eiche, Linde and Zierkirsche cards as revealed; other card images use the supplied OpenQuest back until a new scan unlocks them. The v1 demo save is migrated without treating earlier Festtanne tests as a stage reveal. Signed in, the header shows the server points instead of the local XP.
  • Camera scan in the collection and tree details: when starting from the Baumbuch, optionally choose a specific tree point (or scan freely), capture or choose a photo, see a scan animation and save each scan separately in browser localStorage. Repeated scans of the same individual tree increase the find count and history while its card image unlocks only once. A mobile camera-picker fallback is available if the live preview fails. Photos are checked by the real tree photo verification (see below); the presentation Festtanne keeps its scripted demo answer. Without verification (no API key) the dialog falls back to an explicitly labeled demo species response that the player can correct and that is queued as a pending species suggestion for the admin demo.
  • Tree photo verification: src/lib/treeScan.ts downscales the photo in the browser to about 1024 px JPEG (this drops EXIF and GPS tags), adds the browser position and the quest tree, and posts it to POST /api/verify. The route runs @openquest/tree-verification with the Münster WFS and OSM as neighbor tree sources. The scan dialog shows the verdict, the detected genus with probability, a hint on a genus mismatch and the reasons in German. XP and the card are only granted on approve; review is queued as an observation with status needs_review for the admin demo; reject grants nothing. The photo is not stored.
  • The Baumbuch lists only species with a supplied card image, shows the shared Ahorn artwork once, and can be filtered to revealed cards. Locked artwork is also hidden in the card viewer and lexicon. Species without card art remain available as text in the nature lexicon or as scan suggestions.
  • Ten normalized asset examples from the supplied assets_first_10.csv are bundled in src/data/treeAssetSamples.json. Their UUIDs, exact coordinates, genus, street, district, height, source and last-seen date are bound to ten additional map points. All ten lack a confirmed species, so precise species in the demo scan are suggestions only. The existing 24 quest markers retain their original WFS coordinates and synthetic ms-* identifiers unless a sample asset matches by location, genus and street key; the ten examples do not match them. A full asset export/API is needed to attach backend UUIDs and additional attributes to all markers.
  • Natural language search above the map (for example "die größten Birken in Hiltrup") over all 43,114 Münster trees via POST /api/tree-search. It uses Jev when OPENROUTER_API_KEY is set in .env or .env.local and falls back to rules otherwise. Matches are drawn as a separate map layer, the top 25 are numbered.
  • Admin review demo at /admin with eight sample reports plus local scan suggestions, search, status filters, map context, review notes, local decisions and CSV/GeoJSON export. Scan suggestions retain the selected tree ID and remain pending until reviewed.

Quest completion is not implemented yet. Demo scans add a local pending species suggestion, not an approved municipal update. They do not grant repeat XP or immediate territory points. Only reviewed, distinct tree IDs can enter the district ranking, so scanning one tree multiple times cannot multiply its score. The presentation Festtanne awards 25 XP once when first collected through its pin, matching the supplied card art. A bundled city-tree snapshot supports the density overlay and the Quest pins use selected municipal inventory coordinates; game states and precise species remain demo content. Map tiles require an internet connection.

For the stage demo, click Festtanne scannen on the map, then scan the small tree or select a photo. The test response proposes Festtanne, reveals its supplied full-art card, and adds it to the Baumbuch after confirmation. The pin is positioned on the OpenStreetMap building for Hafenweg 7; it is a presentation prop, not a public tree or territory contribution.

Territory ownership is a demo preview: only project-verified observations of distinct trees count once per player and district if the tree was observed within the last 30 days. The unique leader holds the district; a tie leaves it contested. Fictional rival contributions populate the leaderboard. Future player observations can join the scoring once mission submission and review are connected. Existing collection progress does not count as verified territory points.

Photo verification API

Put OPENROUTER_API_KEY into .env.local (never commit it). Without the key /api/verify answers 503 and the app falls back to the demo answer and says so in the dialog.

POST /api/verify takes multipart/form-data: image (JPEG, PNG or WebP, max 5 MB), optional lat, lon, accuracy (player position, meters) and either treeId (a quest tree from src/data/trees.ts) or expectedLat, expectedLon, expectedGenus. Optional capturedAt (ISO time) lets old gallery photos go to review. The server strips JPEG/PNG metadata before verification and allows 10 requests per minute and IP (in memory), because every call costs OpenRouter credits. The response is { expected, result } with the full TreeVerificationResult; errors are { error, message }.

curl -F image=@eval/images/platanus-2.jpg -F lat=51.964258 -F lon=7.627308 -F accuracy=8 -F treeId=ms-004 http://localhost:3000/api/verify

The admin area is a local demo without authentication or a backend. Review decisions only update browser localStorage; they never change official city data. Public deployment requires access control, server-side persistence and review rules.

Live mode against the OpenQuest API

Without an account the app stays in demo mode with the 24 sample trees and says DEMO in the map header. Tapping the tag (or the account card in the profile) opens login and sign up (username and password, no e-mail; the recovery codes are shown once after sign up). Signed in, the header says LIVE and the map shows real quests from the API instead of the sample trees; the density layer and the Jev search stay.

  • Proxy: the browser only calls /backend/... on its own origin. next.config.ts rewrites that to OPENQUEST_API_URL (default https://openquest-api.onrender.com), so there is no CORS setup. Rewrites are resolved at build time: set OPENQUEST_API_URL before pnpm build. The proxy timeout is 90 s because the free Render instance needs up to a minute to wake up; after 4 s the app shows "Server startet ...".
  • Client: src/lib/api.ts (typed calls, token in localStorage, German error texts per API error code, timeout). UI texts of the live game live in src/i18n/liveGame.ts.
  • Map: GET /quests/nearby around the map center (the map flies to the player position once it is known), radius 600 m, reloaded on moveend with debounce and a 60 s cache. Because the API returns at most 200 quests and the photo campaign is dense, verify_attribute quests are requested separately and merged. Quests are mapped onto the existing tree type (src/lib/quests.ts): German genus name, camera marker for photo quests, magnifier marker for "Art bestimmen", reward as badge, active claims in gold.
  • Flow: bottom sheet with the real quest, Quest annehmen (POST /quests/{id}/claim), then the scan dialog. The photo goes to /api/verify with the quest asset as expected tree. On approve and review the app calls POST /claims/{id}/submit right away with the same downscaled JPEG, the position and the payload ({} for photo quests, { value: <detected genus> } for verify_attribute). On reject nothing is submitted; the claim stays and the player can take a new photo or cancel the claim.
  • Points: they are only paid when a moderator approves. The app says "eingereicht, wird geprüft"; Missionen lists "Meine Quests" from GET /me/claims with status, rejection reason, confirmed and pending XP. With the gamification release the header also reads totalPoints and level from GET /me.

Validation

pnpm test        # app unit tests (src/lib/*.test.ts) and all workspace packages
pnpm typecheck
pnpm build

Prototype planning

Dashboard

Alle Bäume auf einer Karte, Suche per Jev: apps/dashboard (pnpm --filter @openquest/dashboard start).

Entscheidungen

Datenmodell

Backend

Importer

Daten

Recherche (Research Notes)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages