/** * Calculates the transit time in milliseconds for a shipment. * @param distance - Euclidean distance in map units * @param vehicleSpeed - Vehicle speed in km/h (from maxSpeedOnRoad, maxAirspeed, etc.) */ export function calculateTransitTime( distance: number, vehicleSpeed: number, ): number { const hours = distance / vehicleSpeed; return hours * 60 * 60 * 1000; } /** * Calculates the total fuel cost for a shipment. * @param distance - Euclidean distance in map units * @param consumptionRate - Fuel consumed per unit of distance (from vehicle's fuelConsumptionRate) */ export function calculateFuelCost( distance: number, consumptionRate: number, ): number { return Math.ceil(distance * consumptionRate); } /** * Calculates the fuel consumed per game tick. * @param totalFuelCost - Total fuel for the trip * @param totalTicks - Total number of ticks for the trip */ export function calculateFuelPerTick( totalFuelCost: number, totalTicks: number, ): number { if (totalTicks <= 0) return totalFuelCost; return totalFuelCost / totalTicks; } /** * Calculates the number of game ticks for a given duration. * @param durationMs - Duration in milliseconds * @param tickIntervalMinutes - Game tick interval in minutes */ export function calculateTicksForDuration( durationMs: number, tickIntervalMinutes: number, ): number { const tickMs = tickIntervalMinutes * 60 * 1000; return Math.ceil(durationMs / tickMs); } /** * Gets the effective speed of a vehicle, preferring road speed. * Falls back to off-road, air, or sea speed. */ export function getVehicleEffectiveSpeed(vehicle: { combat?: { maxSpeedOnRoad?: number | null; maxSpeedOffRoad?: number | null; maxAirspeed?: number | null; maxKnots?: number | null; } | null; }): number { return ( vehicle.combat?.maxSpeedOnRoad ?? vehicle.combat?.maxSpeedOffRoad ?? vehicle.combat?.maxAirspeed ?? vehicle.combat?.maxKnots ?? 50 // default fallback speed ); }