import { content } from "@deadhead/content"; import type { Contract, PlayerState } from "@deadhead/schema"; import { contractTripGameHours, MS_PER_HOUR } from "@deadhead/sim"; import { useState } from "react"; import { cargoName, formatDuration } from "../format"; import { Pill, type Tone } from "../ui"; /** The good's name as shown on a contract: a Priority good may have its own name (CR-007). */ export function goodName(contract: Pick): string { const good = content.good(contract.goodId); if (!good) return contract.goodId; return contract.priority && good.priorityName ? good.priorityName : good.name; } /** A delivery window in game hours, e.g. "5h" or "2.5h". */ export function formatWindow(hours: number): string { const rounded = hours < 10 ? Math.round(hours * 10) / 10 : Math.round(hours); return `${rounded}h`; } /** Real time for a span of game hours, e.g. "5m 12s". */ export function realTimeOf(gameHours: number): string { return formatDuration((gameHours * MS_PER_HOUR) / content.config.timeCompression); } const CLASS_TONES: Record = { heavy: "cyan", "high-value": "emerald", dangerous: "rose", }; /** "HIGH-VALUE · T1": the cargo class, with the tier when it has one. */ export function ClassChip({ contract }: { contract: Pick }) { return ( {cargoName(contract.cargoTypeId)} {contract.tier > 0 && ` · T${contract.tier}`} ); } /** * "PRIORITY · within 5h" (game hours). Tap to switch to real time; hovering * shows both. */ export function PriorityChip({ windowHours }: { windowHours: number }) { const [real, setReal] = useState(false); return ( ); } /** * True when a Priority contract has idle ships at its origin and none of them * can make the window (CR-007). Display only; the sim decides at dispatch. */ export function tooSlowForAll(state: PlayerState, contract: Contract, now: number): boolean { if (!contract.priority || contract.deliveryWindowGameHours === null) return false; const idle = state.ships.filter((s) => s.status === "idle" && s.locationId === contract.originId); if (idle.length === 0) return false; return idle.every((ship) => { const model = content.shipModel(ship.modelId); return ( !model || contractTripGameHours(model, contract, now, content) > contract.deliveryWindowGameHours! ); }); }