/* ============================================================================= * A00_Common/design/design_follow_server.ts * 계산 자리 follow 「서버」(PLAN 511-B B-5) — 끌기 도구 꼴: 조작 중 = 화면 셈(미리보기) · 잠잠 뒤 서버 Node * route · follow 두 단계(`stage.follow` · until follow · 저장 정본 맥락은 창구가 프로젝트 id 로 붙임)를 묻고 * 답이 오면 묶음을 노선부터 다시 돌림 → 같은 노선 초안이면 서버 값(곁 자료 다시 붙임)으로 바꿈. * 판이 both 면 null(화면 셈 그대로). 열쇠 = 노선 초안 + 저장 노선 계획고 편집(follow 는 노선에만 기댐). * ========================================================================== */ import { readState } from "../b_page_state"; import { withFollowSides, type FollowSides, } from "../../B05_Profile/logic/B05_Profile_Pipeline_Grade"; import { calcOnServerNow } from "./design_calc_sites"; import { afterQuiet, serverCalc } from "./design_calc_server"; import type { FollowPatch, PipelineInputs } from "./logic/design_pipeline_types"; const ID = "stage.follow"; let held: { key: string; patch: FollowPatch } | null = null; let asked: string | null = null; /** 서버 follow 값 — 같은 열쇠 답이 있으면 그 값 · 없으면 null(화면 셈) + 잠잠 뒤 묻고 `redraw`. */ export function followFromServer( projectId: string, inputs: Readonly, before: unknown, savedEdits: unknown, redraw: () => void, ): FollowPatch | null { if (!calcOnServerNow("follow") || !inputs.route) return null; const key = JSON.stringify([inputs.route, savedEdits]); if (held?.key === key) return held.patch; if (asked === key) return null; asked = key; const { route, alignment, pipes, structures, plusStations } = inputs; const stages = { until: "follow", input: { route, alignment, pipes, structures, plusStations }, before_draft: before, pipe_ids: readState("pipe-ids", projectId), saved_edits: savedEdits, }; const body = JSON.stringify({ run: [ID], inputs: { stages } }); void afterQuiet(ID, (signal) => serverCalc("follow", [ID], body, signal)).then((results) => { if (asked === key) asked = null; const got = results?.[ID] as ({ patch: FollowPatch } & FollowSides) | undefined; if (!got) return; held = { key, patch: withFollowSides(got.patch, got) }; redraw(); }); return null; }