Max range display is the guaranteed (worst-case headwind) full-tank range (ISS-099, v0.51.0)
CI / build + unit + e2e (pull_request) Successful in 12m19s
CI / build + unit + e2e (pull_request) Successful in 12m19s
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { FUEL_DISCOUNT_PER_REP, MAX_FUEL_DISCOUNT, MAX_PLANE_DISCOUNT, PLANE_DISCOUNT_PER_REP, PLANE_TYPES, repRate, STARTER_MODEL } from './catalog';
|
||||
import { STARTING_REPUTATION } from './seed';
|
||||
import { guaranteedRangeKm, MAX_WIND_BURN_FACTOR, maxRangeKm, requiredFuelFor } from '@/lib/sim/movement';
|
||||
|
||||
// v0.28.0 (ISS-047) — catalog sanity: the progression ladder must stay well-formed as types are added.
|
||||
describe('PLANE_TYPES', () => {
|
||||
@@ -43,3 +44,25 @@ describe('repRate', () => {
|
||||
expect(repRate(1_000_000, FUEL_DISCOUNT_PER_REP, MAX_FUEL_DISCOUNT)).toBe(MAX_FUEL_DISCOUNT);
|
||||
});
|
||||
});
|
||||
|
||||
// v0.51.0 (ISS-099) — max range consistency: for EVERY catalog type the displayed guaranteed range
|
||||
// must be flyable on a full tank under worst-case headwind burn (the same requiredFuelFor ≤ maxFuel
|
||||
// rule as flyPlane's fuel guard), and tight — not padded. The closed form inverts exactly, so the
|
||||
// "≤" side allows only float noise (~1e-11 L → relative 1e-9 tolerance).
|
||||
describe('max range consistency (v0.51.0, ISS-099)', () => {
|
||||
for (const t of Object.values(PLANE_TYPES)) {
|
||||
it(`${t.id}: guaranteed range is flyable in worst-case headwind and not padded`, () => {
|
||||
const r = guaranteedRangeKm(t.burnPerKm, t.emptyWeightKg, t.maxFuel);
|
||||
expect(requiredFuelFor(t.burnPerKm * MAX_WIND_BURN_FACTOR, t.emptyWeightKg, t.maxFuel, r))
|
||||
.toBeLessThanOrEqual(t.maxFuel * (1 + 1e-9));
|
||||
// Tight: 5% beyond the displayed range no longer fits a full tank.
|
||||
expect(requiredFuelFor(t.burnPerKm * MAX_WIND_BURN_FACTOR, t.emptyWeightKg, t.maxFuel, 1.05 * r))
|
||||
.toBeGreaterThan(t.maxFuel);
|
||||
});
|
||||
|
||||
it(`${t.id}: the no-wind closed form inverts requiredFuelFor exactly`, () => {
|
||||
const r = maxRangeKm(t.burnPerKm, t.emptyWeightKg, t.maxFuel);
|
||||
expect(requiredFuelFor(t.burnPerKm, t.emptyWeightKg, t.maxFuel, r)).toBeLessThanOrEqual(t.maxFuel * (1 + 1e-9));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user