export interface TankLevels { morning: number refilled: number evening: number consumption: number } export interface TravelDaySortable { date?: string dayOfTravel?: string | number } /** Chronological order: date ascending, then day of travel ascending. */ export function compareTravelDaysChronological(a: TravelDaySortable, b: TravelDaySortable): number { const dateCompare = new Date(a.date || 0).getTime() - new Date(b.date || 0).getTime() if (dateCompare !== 0) return dateCompare return Number(a.dayOfTravel || 0) - Number(b.dayOfTravel || 0) } export function getNextTravelDayNumber(entries: TravelDaySortable[]): string { const maxDay = entries.reduce((max, entry) => Math.max(max, Number(entry.dayOfTravel) || 0), 0) return String(maxDay + 1) } /** Closing level at end of travel day: evening stand, else calculated balance, else morning. */ export function getClosingTankLevel(tank?: Partial | null): number { if (!tank) return 0 const evening = Number(tank.evening) || 0 if (evening > 0) return evening const morning = Number(tank.morning) || 0 const refilled = Number(tank.refilled) || 0 const consumption = Number(tank.consumption) || 0 const fromBalance = morning + refilled - consumption if (fromBalance > 0) return fromBalance return morning } export interface LogEntryTankSource { freshwater?: Partial fuel?: Partial greywater?: { level?: number } destination?: string } export interface CarryOverFromPreviousDay { freshwater: TankLevels fuel: TankLevels greywaterLevel: number departure: string } export function emptyTankLevels(morning = 0): TankLevels { return { morning, refilled: 0, evening: 0, consumption: 0 } } export { formatTankLiters } from './numberFormat.js' export function getClosingGreywaterLevel(greywater?: { level?: number } | null): number { return Number(greywater?.level) || 0 } export function carryOverTankLevelsFromPreviousDay(previousEntry?: LogEntryTankSource | null): { freshwater: TankLevels; fuel: TankLevels } { if (!previousEntry) { return { freshwater: emptyTankLevels(), fuel: emptyTankLevels() } } return { freshwater: emptyTankLevels(getClosingTankLevel(previousEntry.freshwater)), fuel: emptyTankLevels(getClosingTankLevel(previousEntry.fuel)) } } export function carryOverFromPreviousDay(previousEntry?: LogEntryTankSource | null): CarryOverFromPreviousDay { const { freshwater, fuel } = carryOverTankLevelsFromPreviousDay(previousEntry) const departure = previousEntry?.destination?.trim() || '' const greywaterLevel = getClosingGreywaterLevel(previousEntry?.greywater) return { freshwater, fuel, greywaterLevel, departure } } export function hasCarryOverFromPreviousDay(carryOver: CarryOverFromPreviousDay): boolean { return ( carryOver.freshwater.morning > 0 || carryOver.fuel.morning > 0 || carryOver.greywaterLevel > 0 || carryOver.departure.length > 0 ) }