import { parseLocal, toLocalIso } from "../../utils/localTime"; import type { CreateChainPlanRequest, ZrvWindowResponse } from "../../api/tguPlanApi"; /** * Опция выбора ЗРВ в диалоге «Создать план». Из стартовой зоны берутся начало окна и КПП, из * конечной — конец окна. `start`/`stop` — naive (ISO без зоны, локальное), как ждёт `LocalDateTime` бэка; * `startMs`/`endMs` — для сортировки/сравнения и подсветки на таймлайне. */ export type ZrvOption = { /** Детерминированный id зоны (для value в select и key). */ id: string; startMs: number; endMs: number; /** Naive (локальное) начала зоны. */ start: string; /** Naive (локальное) конца зоны. */ stop: string; kppId: string; }; /** Будущие ЗРВ-зоны (строго позже nowMs), по возрастанию начала. */ export function futureZrvOptions(windows: ZrvWindowResponse[], nowMs: number): ZrvOption[] { return windows .map((zrv) => { const startMs = parseLocal(zrv.startTime); const endMs = parseLocal(zrv.endTime); return { id: `${zrv.kppId}|${zrv.startTime}|${zrv.endTime}`, startMs, endMs, start: toNaive(startMs), stop: toNaive(endMs), kppId: zrv.kppId }; }) .filter((option) => option.startMs > nowMs) .sort((a, b) => a.startMs - b.startMs); } /** * Собирает тело запроса создания плана новой цепочки из выбора оператора. Окно — от начала стартовой * зоны до конца конечной; `basePlanId` — предыстория (или null для цепочки без истории). Бросает, * если конец окна не позже начала (конечная зона раньше стартовой). */ export function buildChainPlanRequest( spacecraftId: string, basePlanId: string | null, start: ZrvOption, end: ZrvOption ): CreateChainPlanRequest { if (end.endMs <= start.startMs) { throw new Error("Конец окна должен быть позже начала: выберите конечную ЗРВ не раньше стартовой."); } return { spacecraftId, basePlanId, windowStart: start.start, windowStop: end.stop, windowKppId: start.kppId }; } function toNaive(ms: number): string { return toLocalIso(ms); }