Special jobs: data-driven special-status registry with priority status (ISS-073, v0.37.0)
CI / build + unit + e2e (pull_request) Failing after 7m56s

This commit is contained in:
2026-09-21 09:30:36 +00:00
parent 718e3a0177
commit ea740fc378
22 changed files with 276 additions and 36 deletions
+25 -3
View File
@@ -9,6 +9,7 @@ import { loadAirportsGeoJson } from '@/lib/airports';
import { haversineKm, initialBearingDeg } from '@/lib/geo';
import { weatherFor } from '@/lib/weather';
import { PLANE_TYPES } from '@/lib/game/catalog';
import { SPECIALS } from '@/lib/game/specials';
import { MARKET_TARGET_OPEN_PACKAGES, mulberry32 } from '@/lib/game/seed';
import { arrivalTimeFor, fuelAtWeighted, requiredFuelFor, windBurnFactor } from './movement';
import {
@@ -234,6 +235,26 @@ describe('deliverPackages (v0.12.0 arrival delivery)', () => {
); // rep per delivered package
});
it('adds the registry rep bonus for a special package at delivery (v0.37.0)', async () => {
const { inst, km } = await setupFlight('deliver-special.db');
const accountBefore = (await inst.db.select().from(schema.account))[0]!;
await inst.db.insert(schema.packages).values([
{ id: 'p-prio', originIcao: FROM, destIcao: TO, reward: 5_000, cargoType: 'Mail', cargoCount: 10, special: 'priority', deadlineSimTime: T0 + 24 * 3_600_000, status: 'loaded', planeId: 'plane-starter', createdSimTime: T0 },
]);
const clock = T0 + travelMs(km, PLANE_TYPES.atr72.speedKmh); // exactly at arrival
expect(await deliverPackages(inst, clock)).toBe(1);
const account = (await inst.db.select().from(schema.account))[0]!;
expect(account.cash).toBeCloseTo(accountBefore.cash + 5_000, 9);
// Distance-based gain + the registry rep bonus — double-rounded like every other award.
expect(account.reputation).toBeCloseTo(
Math.round((accountBefore.reputation + reputationGainFor(km) + SPECIALS.priority.repBonus) * 100) / 100,
9,
);
});
it('leaves planes without route info alone', async () => {
const inst = await freshDb('deliver-noroute.db');
// Flying plane whose dest_icao is missing — defensive skip, no crash.
@@ -433,9 +454,10 @@ describe('spawnOpenPackages', () => {
expect(icaoSet.has(p.destIcao)).toBe(true);
expect(p.originIcao).not.toBe(p.destIcao);
expect(p.planeId).toBeNull();
// Same deadline window as the seed: now + 6–72h game time.
expect(p.deadlineSimTime).toBeGreaterThan(clock + 6 * 3_600_000 - 1);
expect(p.deadlineSimTime).toBeLessThanOrEqual(clock + 72 * 3_600_000);
// Same deadline window as the seed: now + 6–72h game time — scaled by any special status (v0.37.0).
const scale = p.special ? SPECIALS[p.special]?.deadlineScale ?? 1 : 1;
expect(p.deadlineSimTime).toBeGreaterThan(clock + 6 * 3_600_000 * scale - 1);
expect(p.deadlineSimTime).toBeLessThanOrEqual(clock + 72 * 3_600_000 * scale);
}
// Already at target → nothing more to spawn.