How mission generation works
The mission board is generated, not curated. Given a snapshot of VATSIM plus your account state, the generator deterministically produces 8–12 missions per refresh. This page is the architectural overview; the four sibling pages drill into specific filters.
Principle
Five guardrails the generator never violates:
- Always offerable. Active players see a non-empty board even at quiet network hours.
- Reward flying where ATC exists. Without hard-gating to it — there's always a fallback.
- Match difficulty to tier. T1 Bush doesn't see transatlantic 777s.
- Avoid repetition. Within a player's recent history.
- Cheap to run. A full board takes <200ms server-side.
Inputs
generate(player_state, vatsim_snapshot, class_templates, rng_seed) → Mission[]
- player_state — your
cid, your tier and certified aircraft per class, your home country, your recent mission history (for the recency penalty). - vatsim_snapshot — current ATC roster (TWR / APP / CTR), METAR per airport, traffic levels. Polled once per generation.
- class_templates — static config per class: leg-length range, IFR/VFR rules, allowed aircraft, airport constraints, ATC-coverage weighting.
- rng_seed —
hash(cid + floor(now / refresh_interval)). Stable within a refresh window, rotates on refresh.
Five stages
- Class shortlist. For each class you've entered, pick the current tier template. Locked classes skipped.
- Departure selection. Filter airports by runway / surface category; prefer those with active ATC; score by home-country bias, weather difficulty, recency; sample a weighted top-K.
- Arrival selection. Sample a leg length from class range; filter airports within ±20%; apply class arrival constraints; score by ATC at arrival, weather, full-pair recency.
- Attributes. Attach aircraft, IFR/VFR flag, base reward, difficulty multiplier, 20% chance of a time-sensitive window, a scenario blurb.
- Board composition. Trim to 8–12 missions, ensure each entered class is represented, enforce the home-country 70/30 quota, sort by reward with one "easy local" anchor at the top.
Each stage is filter-then-score-then-sample. The early stages prune aggressively (a typical board considers fewer than 200 airports across all stages combined). The later stages rank and trim.
Determinism
Given identical inputs (same seed, same snapshot, same player state), the generator produces identical output. This is intentional:
- Tests use synthetic VATSIM snapshot fixtures to assert exact mission counts, class quotas, score ordering.
- Property tests check invariants — no two missions share
(dep, arr, aircraft_class); quota respected; reward monotone with leg length within a class. - "Regenerate board" UX is a no-surprise operation: same seed = same board.
Side effects (writing the snapshot to DB, fetching live state) happen around the generator, not inside it. The generator itself is a pure function.
Quiet-network fallback
When too few staffed airports survive Stage 2's coverage-first filter:
- Relax the coverage filter — fall back to all category-matching airports.
- Drop the ATC-coverage reward multiplier on those missions; flag them
coverage: "none"so the player sees the lower payout honestly. - Widen the recency penalty window if still short.
There's no separate "filler" pool. The structural airport catalog + class-template constraints already cover this. Coverage-first is the preference, category-only is the safety net.
Drill in: Multipliers reference · ATC coverage rules · Weather and METAR · Airport catalog.