Simulate fuel usage considering how much fuel weight. On 'on board' list element should be a 'refuel' button that refuels just enough to do that flight; rename current 'Refuel' to ~'to full'.
A — weighted burn model (lib/sim/movement.ts): instantaneous burn rate proportional to total weight, r(F) = k·(We + ρF) L/km (ρ = 0.8 kg/L), calibrated so a full tank burns exactly the old constant. Closed forms:
fuel after distance D from F₀: (F₀ + We/ρ)·e^{−kρD} − We/ρ
required total fuel to cover D: (We/ρ)(e^{kρD} − 1)
Catalog gains per-type emptyWeightKg (ATR72 = 9300 kg OEW), exposed in the snapshot. All three burn call sites updated (landing, live snapshot, fly validation). Long legs now burn ~10% less as the plane lightens — landing-fuel assertions adjusted to the closed form.
B — refuel just enough: POST /api/planes/{id}/refuel accepts an optional body {mode?: 'full'|'forFlight', packageId?} (no body = today's behavior, all existing flows unchanged). forFlight computes exactly the liters needed for the loaded package's leg (409 if not loaded/expired or the leg doesn't fit even full; 400 on bad body). UI: per on-board cargo row a "Refuel" button (refuel-for-{pkg.id}); market button renamed "Refuel to full" (testid kept).
Version
package.json → 0.16.0, CHANGELOG entry at top
Checks (local)
tsc --noEmit clean; unit 255/255 green (was 238 — new weighted-burn + forFlight suites); playwright test --list = 34 tests in 9 files
e2e not run locally by design — CI verifies against the isolated stack
## What (issue #5)
*Simulate fuel usage considering how much fuel weight. On 'on board' list element should be a 'refuel' button that refuels just enough to do that flight; rename current 'Refuel' to ~'to full'.*
**A — weighted burn model** (`lib/sim/movement.ts`): instantaneous burn rate proportional to total weight, `r(F) = k·(We + ρF)` L/km (ρ = 0.8 kg/L), calibrated so a full tank burns exactly the old constant. Closed forms:
- fuel after distance D from F₀: `(F₀ + We/ρ)·e^{−kρD} − We/ρ`
- required total fuel to cover D: `(We/ρ)(e^{kρD} − 1)`
Catalog gains per-type `emptyWeightKg` (ATR72 = 9300 kg OEW), exposed in the snapshot. All three burn call sites updated (landing, live snapshot, fly validation). Long legs now burn ~10% less as the plane lightens — landing-fuel assertions adjusted to the closed form.
**B — refuel just enough**: `POST /api/planes/{id}/refuel` accepts an optional body `{mode?: 'full'|'forFlight', packageId?}` (no body = today's behavior, all existing flows unchanged). `forFlight` computes exactly the liters needed for the loaded package's leg (409 if not loaded/expired or the leg doesn't fit even full; 400 on bad body). UI: per on-board cargo row a "Refuel" button (`refuel-for-{pkg.id}`); market button renamed **"Refuel to full"** (testid kept).
## Version
- `package.json` → **0.16.0**, CHANGELOG entry at top
## Checks (local)
- `tsc --noEmit` clean; unit **255/255** green (was 238 — new weighted-burn + forFlight suites); `playwright test --list` = 34 tests in 9 files
- e2e not run locally by design — CI verifies against the isolated stack
Part A: r(F) = k(We + rho*F) L/km, k calibrated so a full tank burns exactly
the old constant; closed forms in lib/sim/movement.ts (fuelAtWeighted,
requiredFuelFor, burnRateConstant, FUEL_DENSITY_KG_PER_L). Catalog gains
emptyWeightKg (ATR72 OEW 9300 kg), exposed in the snapshot. All three burn
call sites (engine landing, state live fuel, fly validation) moved to the
weighted model; old constant-rate fuelAt removed.
Part B: POST /api/planes/{planeId}/refuel takes an optional body
{mode:'full'|'forFlight', packageId} — no body keeps today's fill-to-full
behavior exactly (fuel lands bit-exact on maxFuel); forFlight adds just
enough for the loaded package's destination leg (409 not-loaded/expired/
doesn't-fit, 400 bad body). UI: per-cargo-row 'Refuel' button
(refuel-for-{pkg.id}), market button renamed 'Refuel to full'.
OpenAPI: RefuelRequest schema + optional requestBody + 400 on refuel, fly's
409 description updated, CatalogEntry.emptyWeightKg. Tests: new weighted-burn
suite, forFlight action/route cases (incl. ~7670 km UNNT<->LPPD doesn't-fit),
openapi guards; landing-fuel assertions in engine.test.ts + e2e/actions.spec.ts
use the closed form; the e2e 'return leg unfuelable' scenario reworked — a full
tank now covers the EDDF<->LEZL round trip, so the 409 moves to the second
outbound. New e2e: row Refuel deducts exactly L*price / raises fuel by exactly
L via the endpoint's own response snapshot.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What (issue #5)
Simulate fuel usage considering how much fuel weight. On 'on board' list element should be a 'refuel' button that refuels just enough to do that flight; rename current 'Refuel' to ~'to full'.
A — weighted burn model (
lib/sim/movement.ts): instantaneous burn rate proportional to total weight,r(F) = k·(We + ρF)L/km (ρ = 0.8 kg/L), calibrated so a full tank burns exactly the old constant. Closed forms:(F₀ + We/ρ)·e^{−kρD} − We/ρ(We/ρ)(e^{kρD} − 1)Catalog gains per-type
emptyWeightKg(ATR72 = 9300 kg OEW), exposed in the snapshot. All three burn call sites updated (landing, live snapshot, fly validation). Long legs now burn ~10% less as the plane lightens — landing-fuel assertions adjusted to the closed form.B — refuel just enough:
POST /api/planes/{id}/refuelaccepts an optional body{mode?: 'full'|'forFlight', packageId?}(no body = today's behavior, all existing flows unchanged).forFlightcomputes exactly the liters needed for the loaded package's leg (409 if not loaded/expired or the leg doesn't fit even full; 400 on bad body). UI: per on-board cargo row a "Refuel" button (refuel-for-{pkg.id}); market button renamed "Refuel to full" (testid kept).Version
package.json→ 0.16.0, CHANGELOG entry at topChecks (local)
tsc --noEmitclean; unit 255/255 green (was 238 — new weighted-burn + forFlight suites);playwright test --list= 34 tests in 9 filesPart A: r(F) = k(We + rho*F) L/km, k calibrated so a full tank burns exactly the old constant; closed forms in lib/sim/movement.ts (fuelAtWeighted, requiredFuelFor, burnRateConstant, FUEL_DENSITY_KG_PER_L). Catalog gains emptyWeightKg (ATR72 OEW 9300 kg), exposed in the snapshot. All three burn call sites (engine landing, state live fuel, fly validation) moved to the weighted model; old constant-rate fuelAt removed. Part B: POST /api/planes/{planeId}/refuel takes an optional body {mode:'full'|'forFlight', packageId} — no body keeps today's fill-to-full behavior exactly (fuel lands bit-exact on maxFuel); forFlight adds just enough for the loaded package's destination leg (409 not-loaded/expired/ doesn't-fit, 400 bad body). UI: per-cargo-row 'Refuel' button (refuel-for-{pkg.id}), market button renamed 'Refuel to full'. OpenAPI: RefuelRequest schema + optional requestBody + 400 on refuel, fly's 409 description updated, CatalogEntry.emptyWeightKg. Tests: new weighted-burn suite, forFlight action/route cases (incl. ~7670 km UNNT<->LPPD doesn't-fit), openapi guards; landing-fuel assertions in engine.test.ts + e2e/actions.spec.ts use the closed form; the e2e 'return leg unfuelable' scenario reworked — a full tank now covers the EDDF<->LEZL round trip, so the 409 moves to the second outbound. New e2e: row Refuel deducts exactly L*price / raises fuel by exactly L via the endpoint's own response snapshot.