pcp: создание плана новой цепочки из вкладки «Планы» (база/без истории, окно из двух ЗРВ)
Оператор берёт за основу прошлый план (предыстория) или начинает цепочку с нуля,
набирает окно из двух реальных ЗРВ и создаёт план-кандидат; сразу показывается прогноз
будущей цепочки от него. Рабочим (якорем) план становится после ручной отправки (promote)
и приёмки — отдельного механизма якорения не вводим.
pcp-tgu-service:
- сырые ЗРВ: PlanCalculationService.rawWindows + PlanProjectionService.rawZrvWindows,
GET /api/plans/{spacecraftId}/zrv (исходные окна снапшота, не cooked-проекция);
- CreateChainPlanUseCase + POST /api/plans/new-chain: опциональная база (клон включений
в окно) либо пустая миссия без истории; прогноз цепочки через projectAfterWindow;
- ZrvWindowMatcher (старт+КПП одной зоны, конец — другой); assertDraftSlotStillValid
переведён на него — единая проверка для replace/fork-forward и окна из двух ЗРВ;
- тесты: CreateChainPlanUseCaseTest (8), ZrvWindowMatcherTest (7), правки promote-тестов.
pcp-mission-planing-service:
- POST /api/missions/blank — пустая миссия для сценария «без истории» (+ 2 теста).
pcp-tgu-ops-ui:
- API fetchZrvWindows/createChainPlan; диалог «Создать план» во вкладке «Планы»
(выбор базы, стартовой и конечной ЗРВ) с показом спрогнозированной цепочки и ручной
отправкой; подсветка ЗРВ выбранного КА на таймлайне;
- «Целевая ЗРВ» убрана из редактора (он остаётся под replace-правку); удалён ставший
мёртвым editorForkForward; createChainWindows + тесты.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { parseUtc } from "../../utils/utcTime";
|
||||
import type { CreateChainPlanRequest, ZrvWindowResponse } from "../../api/tguPlanApi";
|
||||
|
||||
/**
|
||||
* Опция выбора ЗРВ в диалоге «Создать план». Из стартовой зоны берутся начало окна и КПП, из
|
||||
* конечной — конец окна. `start`/`stop` — naive UTC (ISO без зоны), как ждёт `LocalDateTime` бэка;
|
||||
* `startMs`/`endMs` — для сортировки/сравнения и подсветки на таймлайне.
|
||||
*/
|
||||
export type ZrvOption = {
|
||||
/** Детерминированный id зоны (для value в select и key). */
|
||||
id: string;
|
||||
startMs: number;
|
||||
endMs: number;
|
||||
/** Naive UTC начала зоны. */
|
||||
start: string;
|
||||
/** Naive UTC конца зоны. */
|
||||
stop: string;
|
||||
kppId: string;
|
||||
};
|
||||
|
||||
/** Будущие ЗРВ-зоны (строго позже nowMs), по возрастанию начала. */
|
||||
export function futureZrvOptions(windows: ZrvWindowResponse[], nowMs: number): ZrvOption[] {
|
||||
return windows
|
||||
.map((zrv) => {
|
||||
const startMs = parseUtc(zrv.startTime);
|
||||
const endMs = parseUtc(zrv.endTime);
|
||||
return {
|
||||
id: `${zrv.kppId}|${zrv.startTime}|${zrv.endTime}`,
|
||||
startMs,
|
||||
endMs,
|
||||
start: toNaiveUtc(startMs),
|
||||
stop: toNaiveUtc(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 toNaiveUtc(ms: number): string {
|
||||
return new Date(ms).toISOString().slice(0, 19);
|
||||
}
|
||||
Reference in New Issue
Block a user