World airport dataset + distance cap on generated jobs (ISS-079, v0.44.0)
CI / build + unit + e2e (pull_request) Successful in 11m2s
CI / build + unit + e2e (pull_request) Successful in 11m2s
This commit is contained in:
@@ -101,6 +101,16 @@ export const JOB_BONUS_PER_REP = 0.01;
|
||||
// ponytail: balance-tunable — max job reward bonus (up to ×2 at rep ≥ 110).
|
||||
export const MAX_JOB_BONUS = 1.0;
|
||||
|
||||
// v0.44.0 (ISS-079): generated jobs are capped at this great-circle distance so every spawned
|
||||
// leg is flyable by at least one catalog plane even in worst-case headwind — the b777's full-tank
|
||||
// range is ~13045 km nominal and ~10871 km with the +20% wind factor (maxRangeKm ÷ 1.2), so 9000
|
||||
// leaves margin below it while still spanning most of a continent. ponytail: balance-tunable —
|
||||
// must stay ≤ maxRangeKm(b777) / 1.2 or some generated legs are permanently unflyable.
|
||||
export const MAX_JOB_LEG_KM = 9000;
|
||||
|
||||
// Bounded rejection attempts in generatePackage before the within-cap fallback kicks in.
|
||||
const LEG_CAP_MAX_ATTEMPTS = 25;
|
||||
|
||||
// Package deadlines: now + a plausible game-time window of 6–72 hours.
|
||||
const DEADLINE_MIN_HOURS = 6;
|
||||
const DEADLINE_MAX_HOURS = 72;
|
||||
@@ -171,6 +181,27 @@ export function generatePackage(input: {
|
||||
} else {
|
||||
di = Math.floor(rng() * airports.length);
|
||||
if (di === oi) di = (di + 1) % airports.length;
|
||||
// v0.44.0 (ISS-079): cap on generated legs — when BOTH endpoints are unforced, rejection-sample
|
||||
// the pair until it fits MAX_JOB_LEG_KM so spawned jobs stay flyable by at least one catalog plane.
|
||||
// Forced paths keep their pre-v0.44.0 draw behavior exactly (the engine's coverage spawn caps its
|
||||
// random dest itself via pickDestWithinCap). Under-cap pairs take just the two draws above, so the
|
||||
// RNG stream is byte-identical to before for them.
|
||||
if (input.originIcao === undefined) {
|
||||
let km = haversineKm(airports[oi].lat, airports[oi].lon, airports[di].lat, airports[di].lon);
|
||||
for (let attempt = 1; km > MAX_JOB_LEG_KM && attempt < LEG_CAP_MAX_ATTEMPTS; attempt++) {
|
||||
oi = Math.floor(rng() * airports.length);
|
||||
di = Math.floor(rng() * airports.length);
|
||||
if (di === oi) di = (di + 1) % airports.length;
|
||||
km = haversineKm(airports[oi].lat, airports[oi].lon, airports[di].lat, airports[di].lon);
|
||||
}
|
||||
if (km > MAX_JOB_LEG_KM) {
|
||||
// Exhausted: keep the last origin and pick uniformly from its within-cap neighbours. If none
|
||||
// exist (impossible in the curated dataset — every airport has a neighbour well inside the cap),
|
||||
// keep the over-cap pair rather than throw mid-tick.
|
||||
const fallback = pickDestWithinCap(airports, oi, rng);
|
||||
if (fallback >= 0) di = fallback;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oi === di) throw new Error('origin and destination must differ'); // both forced identical
|
||||
const origin = airports[oi];
|
||||
@@ -213,6 +244,19 @@ export function generatePackage(input: {
|
||||
};
|
||||
}
|
||||
|
||||
// v0.44.0 (ISS-079): uniform random index of an airport within MAX_JOB_LEG_KM of airports[originIdx]
|
||||
// (excluding the origin itself) — one RNG draw, -1 when no neighbour fits. Shared by generatePackage's
|
||||
// exhaustion fallback and the engine's coverage spawn so both cap identically without duplicating the scan.
|
||||
export function pickDestWithinCap(airports: SeedAirport[], originIdx: number, rng: Rng): number {
|
||||
const candidates: number[] = [];
|
||||
for (let j = 0; j < airports.length; j++) {
|
||||
if (j === originIdx) continue;
|
||||
if (haversineKm(airports[originIdx].lat, airports[originIdx].lon, airports[j].lat, airports[j].lon) <= MAX_JOB_LEG_KM) candidates.push(j);
|
||||
}
|
||||
if (candidates.length === 0) return -1;
|
||||
return candidates[Math.floor(rng() * candidates.length)];
|
||||
}
|
||||
|
||||
function pickHub(airports: SeedAirport[]): SeedAirport {
|
||||
return airports.find((a) => a.icao === HUB_ICAO) ?? airports[0];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user