Skip to main content

Personal achievement collections

This guide covers Dawarich 1.20.0.

Delivered series​

SeriesSubject and qualificationLevels
ThemesBenelux BE/NL/LU; Baltics EE/LV/LT; Scandinavia DK/NO/SE. Existing country visit codes; subdivisions need not be complete.Rare
CityUser-pinned catalog city; exact opened H3-r9 land area / administrative land area. One valid ground point opens a cell.1/5/10/25%: Common/Rare/Epic/Legendary
ReturnSelected Place; valid visits of at least 20 min; gap from previous visit end to new visit start. Overlaps merge.1/3/5 calendar years: Rare/Epic/Legendary
SeasonsSelected Place; four separate 20-min visits, each at least seven local days apart; local season of start. Years may differ.Epic
NatureIndividual national park, actual polygon observations; at least 30 observed min in one local day.Rare per park; 1/5/15 parks: Common/Rare/Epic
MilestonesNorth+South; East+West; all NE/NW/SE/SW; Arctic; Antarctic. At least 10 observed min per region in a local day, with 10 km boundary margins.Rare/Rare/Epic/Epic/Legendary

A valid temporal Visit is active, ended, at least twenty minutes in both saved and actual duration, Confirmed or Suggested with confidence >=70. Declined and deleted visits are excluded. The Place timezone is resolved offline by tzf2 and stored with lookup/data version and coordinates. Ambiguity requires an explicit IANA override; the profile timezone never changes seasons. Southern season names reverse; tropical latitudes below 23.44° use neutral DJF/MAM/JJA/SON labels.

Observed time is the union of consecutive device intervals, maximum gap ten minutes and maximum contribution two minutes/pair. Excluded observations break continuity. Split at local midnight; require the target within one local day. Moving inside a park is valid. Neither a flight line nor a border H3 cell proves a park visit. Presence in different hemispheres does not prove a continuous crossing.

Owner and public surfaces​

/achievements retains existing country/continent collections and adds themes. /achievements/cards contains six personal series, a series filter and 24-card pagination, city pinning and search/pinning of owned Places. Place drawers expose the same pin action. Details explain rules, evidence dates, per-region observed minutes, next city level and first-earned/revocation history. Archived Places retain their selected history; merges transfer card identity/events to the survivor.

Mutations: /achievements/places, /achievements/cities, and /achievements/cards/:id/toggle_sharing. They require an authenticated owner and achievements access. Explicit links use /shared/achievement_cards/:uuid, ?embed=1 and /shared/achievement_cards/:uuid/og.png. Public output uses the owner's locale, masks private observations and is always private, no-store. Dirty state, missing selection, disabled link or hidden Place/park yields 404. City mosaic sharing requires an additional explicit opt-in.

Map fog uses all retained history through the calculation time, independent of plan/date range; future-dated observations do not open cells or award city levels. It uses exact resolution-9 boundaries at every zoom and marks cells first opened in the selected period. It shows a calculating/updating/error status while background work runs. Old point-radius/point-threshold and zoom-parent fog controls are removed. The authenticated fog endpoint remains /api/v1/maps/hexagons/fog; it now returns h3_indexes, new_h3_indexes, and metadata including status, resolution, snapshot_id and pinned. Optional snapshot_id only accepts owned completed snapshots. City deep links validate a pinned city/card before attaching that snapshot to /map?exploration_city=...&exploration_snapshot=....

Geographic milestone artwork​

The five milestones use orthographic globes with continent coastlines and a coordinate grid. North/south keeps an equatorial separator and two tints; east/west keeps the prime meridian and different tints; the four quarters keep both separators and four tints even after completion. Unqualified regions remain dark. Arctic/Antarctic views tilt toward their pole and highlight the actual 66.56° cap while retaining the surrounding globe.

Display-only GlobeArtwork reads precomputed local SVG paths. The same detail layers survive fallback HTML, client hydration, the expanded card, public embeds and OG PNG. Public artwork reads only the already masked public evidence. The build/provenance recipe is in the corresponding guide. No achievement thresholds, source history or privacy rules change with artwork.

The optional silhouette details contract carries safe vector fill/stroke layers above the missing-region mask, with consistent coordinate/stroke normalization. Client validation rejects raw SVG markup, external paint servers and non-finite attributes. Verification for this artwork change: 26 targeted Ruby examples, 745 JavaScript tests, all five private/public/OG variants and a JavaScript-free fallback check on synthetic fixtures.

Geodata and local runtime​

Pilot cities: Berlin (OSM62422), Hamburg (62782), Dresden (191645). Pilot parks: Harz (90584), Saxon Switzerland (1595534), Eifel (2345991). This catalog is neither worldwide nor exhaustive for Germany. Unsupported boundaries are not synthesized. The park-count thresholds remain 1/5/15 as the regional catalog grows.

Bundled checksummed OSM geometry and public-domain Natural Earth 5.1.2 require PostGIS and the existing H3 binding. tzf2 supplies offline IANA lookup using its packaged boundary data; the gem lock includes macOS and Linux x86_64/aarch64. OG rendering uses the existing rsvg-convert. Normal supported Docker builds already use glibc-based Ruby images. Catalog build/update instructions and ODbL attribution are in the corresponding guide.

Geography installation is lazy and runs in the achievements queue, coalesced by a Redis claim. The first city/point calculation can take longer while the local geographic dataset is prepared. Completed datasets are immutable. Bump both catalog and geography versions for boundary changes; retain stable subject codes. Country/world areas are a union of country land, never a sum of overlapping cities. manifest.json pins internal subject codes independently of replaceable OSM relation IDs; a source replacement must preserve the existing card identity.

Resource footprint​

Card artwork is generated from shared vector geometry; there is no saved PNG per card or user. globes.json is 508,779 bytes (about 497 KiB; 168 KiB gzip) for all five geographic milestones. The three new compressed geodata bundles (countries, lakes and pilot cities/parks) total 6,073,773 bytes (about 5.79 MiB). Together those geometry assets add about 6.28 MiB before Git compression.

Shared-card OG PNGs are rendered in memory on request and sent with no-store; this implementation does not persist them in Active Storage or on disk. Browser screenshots and their ZIPs are local review artifacts outside this Git checkout. Exploration cells, snapshots and qualification evidence do consume database storage as history grows; that is separate from artwork files.

Database and workers​

Migrate normally. New exploration migrations preserve the dates/identities of the original local foundation; collection migrations add selections, city pins, current state, collectible snapshots and the event journal. Statement-level SQL triggers cover bulk writes as well as model callbacks. Both schema-dumper hooks restore triggers after db:schema:load; a clean-schema smoke test verifies this.

During a single-owner atomic import, both trigger families respect the existing transaction-local dawarich.defer_revisions setting. The outermost Revisions::ImportTransaction bumps collection and exploration state once after the import block, before monthly point/track revisions and commit. This follows source-trigger lock order and keeps live point writes free during a long import. Nested blocks retain deferral; rollback leaves the prior state intact.

Achievements::CollectionCheckJob runs concrete temporal/geographic rules and uses Exploration::Rebuild when cities are selected. Exploration::RebuildJob serves map fog. Exploration recovery starts only after a fog request or selected city activates the owner's state. Durable activated_at survives an enqueue failure, interrupted worker or discarded first snapshot; source writes alone only mark state dirty and never activate full-history exploration rebuilds. The migration preserves activation for existing snapshots, requests, failures and selected cities. Automatic park/milestone calculations remain independent. Their five-minute refresh jobs recover dirty/unbuilt state; claims expire after one hour. Existing Sidekiq achievements/low_priority queues are reused. Inspect state revision, published_revision, failed_at, requested_at, and the published dataset/snapshot and timezone data version when diagnosing stale output. Do not manually mark a stale revision published.

The per-user calculation lock and final source/dataset/privacy fences discard stale results. Point/Visit removal revokes new awards; journal rows remain. Deleting a user cascades the new tables. Re-earning never creates another first award event. Initial, dataset and timezone-data backfills are quiet. More than five new cards produce one digest notification, while the unlock deck still contains each card. Existing country award permanence and disputed-area rules are unchanged.