Merge remote-tracking branch 'origin/sub_laptop_7' into main_laptop_1
This commit is contained in:
@@ -17,7 +17,9 @@
|
||||
* `ROUTE_CARRY_STATES`)도 측점 열쇠로 새 노선 측점에 옮김(구조물 조절 = 관 · 구조물 열쇠만 · 서버와 같음).
|
||||
* ========================================================================== */
|
||||
|
||||
import { readState, writeState, type StateName } from "../A00_Common/b_page_state";
|
||||
import { readState, stateKey, writeState, type StateName } from "../A00_Common/b_page_state";
|
||||
import { renameChainageKeys } from "./logic/B06_Section_Station_Swap";
|
||||
import { afterAnySwap } from "./B06_Section_Swap_Bus";
|
||||
import { pipeIdAt, pipeIdNear } from "../A00_Common/design/design_pipe_ids";
|
||||
import { showToast } from "@ui/ui_template_elements";
|
||||
import {
|
||||
@@ -466,3 +468,36 @@ export function carryChainageStates(
|
||||
}
|
||||
return outside.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 측점이 움직임(갈아끼움 · 옛 0.01 m 글 → 새 글) — 조정창 맵이 안 선 누가거리 칸(B05 만 연 페이지 · 새로고침 ·
|
||||
* 세월 · BOX · 연동)을 세션에서 바로 새 자리로(415-3). 칸 = `ROUTE_CARRY_STATES`(측점 열쇠 칸 빼고) · 조정창
|
||||
* 맵이 이번에 옮긴 칸(`owned`)은 그대로.
|
||||
*/
|
||||
function moveIdleStates(moves: ReadonlyMap<string, string>, owned: ReadonlySet<string>): void {
|
||||
if (!moves.size || !current) return;
|
||||
const { projectId, routeId } = current;
|
||||
const move = (cells: Record<string, unknown>) =>
|
||||
Object.fromEntries(renameChainageKeys(new Map(Object.entries(cells)), moves));
|
||||
for (const state of Object.keys(ROUTE_CARRY_STATES)) {
|
||||
if ((KEYED_STATES as readonly string[]).includes(state)) continue;
|
||||
const name = state as StateName;
|
||||
const key = stateKey(name, projectId, routeId);
|
||||
if (!key || owned.has(key)) continue;
|
||||
const raw = readState<Record<string, unknown>>(name, projectId, routeId);
|
||||
if (!raw || typeof raw !== "object") continue;
|
||||
// 연동 = { detached: {누가거리: …}, grade: {…} } 두 겹
|
||||
const next =
|
||||
state === "revetlink"
|
||||
? Object.fromEntries(
|
||||
Object.entries(raw).map(([part, cells]) => [
|
||||
part,
|
||||
cells && typeof cells === "object" ? move(cells as Record<string, unknown>) : cells,
|
||||
]),
|
||||
)
|
||||
: move(raw);
|
||||
writeState(name, next, projectId, routeId);
|
||||
}
|
||||
}
|
||||
|
||||
afterAnySwap((_detail, moves, owned) => moveIdleStates(moves, owned));
|
||||
|
||||
@@ -21,7 +21,37 @@ export function onAnySwap(fn: DetailListener): () => void {
|
||||
return () => anyListeners.delete(fn);
|
||||
}
|
||||
|
||||
/** 알림 한 번 동안 조정창 맵이 옮긴 세션 칸(열쇠 글) — 뒤 차례(`afterAnySwap`)는 그 칸을 다시 안 옮김(415-3). */
|
||||
const moved = new Set<string>();
|
||||
const afterListeners = new Set<
|
||||
(
|
||||
detail: SectionDetailResponse,
|
||||
moves: ReadonlyMap<string, string>,
|
||||
owned: ReadonlySet<string>,
|
||||
) => void
|
||||
>();
|
||||
|
||||
/** 조정창 맵이 세션 칸을 옮겼다고 적음(`_UI_Page_Link_Session`). */
|
||||
export function markMovedStates(keys: Iterable<string>): void {
|
||||
for (const key of keys) moved.add(key);
|
||||
}
|
||||
|
||||
/** 갈아끼움 알림이 다 돈 뒤 부름 — `owned` = 그 사이 조정창 맵이 옮긴 세션 칸. */
|
||||
export function afterAnySwap(
|
||||
fn: (
|
||||
detail: SectionDetailResponse,
|
||||
moves: ReadonlyMap<string, string>,
|
||||
owned: ReadonlySet<string>,
|
||||
) => void,
|
||||
): () => void {
|
||||
afterListeners.add(fn);
|
||||
return () => afterListeners.delete(fn);
|
||||
}
|
||||
|
||||
/** 갈아끼운 쪽(`Section_Store`)이 부름. */
|
||||
export function emitSwap(detail: SectionDetailResponse, moves: ReadonlyMap<string, string>): void {
|
||||
moved.clear();
|
||||
anyListeners.forEach((fn) => fn(detail, moves));
|
||||
const owned = new Set(moved);
|
||||
afterListeners.forEach((fn) => fn(detail, moves, owned));
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import { culvertCardState } from "./B06_Section_UI_Cross_View_Structure";
|
||||
import type { PipeRevetChoice } from "../A00_Common/design/design_structure_pipe_calc";
|
||||
import { renameChainageKeys } from "./logic/B06_Section_Station_Swap";
|
||||
import { onAnySwap } from "./B06_Section_Swap_Bus";
|
||||
import { markMovedStates, onAnySwap } from "./B06_Section_Swap_Bus";
|
||||
import { readByKey, writeByKey } from "../A00_Common/b_page_state";
|
||||
|
||||
/** 세션에 담기는 측점별 조작값 한 겹 맵. */
|
||||
@@ -65,6 +65,7 @@ export function moveSessionMaps(moves: ReadonlyMap<string, string>): void {
|
||||
next.forEach((value, key) => map.values.set(key, value));
|
||||
map.persist();
|
||||
}
|
||||
markMovedStates(latest.keys()); // 나머지 누가거리 칸은 `Station_Keys` 가 옮김(415-3)
|
||||
}
|
||||
|
||||
// 상세 갈아끼움(어느 보기가 했든)마다 한 번 — 조정창 값을 옮긴 측점 자리로
|
||||
|
||||
@@ -122,6 +122,10 @@ const snap = () => ({
|
||||
m.writeCrossDesignChoice(P, R, 45.054, choice("left_cut")); // 관 측점 고침
|
||||
m.writeState("shoulderext", { "@at": { "grid:1": 20 }, "grid:1": { left: 0.7 } }, P, R); // 사면 쉬프트
|
||||
m.writeState("bermdepth", { "@at": { "grid:3": 60 }, "grid:3": { right: 0.4 } }, P, R); // 소단 깊이
|
||||
// 누가거리 조절(415-3) — 조정창 맵 없이(B05 만 연 페이지 · 새로고침) · 관 자리 옹벽 · 세월 · 연동 두 겹 · 격자 폭
|
||||
m.writeState("revetx", { "45.05:outlet": { x: 0.3 }, "20.00:inlet": { x: 0.1 } }, P, R);
|
||||
m.writeState("fordadjust", { 45.05: { w: 1 } }, P, R);
|
||||
m.writeState("revetlink", { detached: { 45.05: true }, grade: {} }, P, R);
|
||||
out.before = snap();
|
||||
const stop = m.followSwaps(
|
||||
P,
|
||||
@@ -134,6 +138,11 @@ const snap = () => ({
|
||||
m.useDesignStore(P, null).set("stations", list(50));
|
||||
await new Promise((resolve) => setTimeout(resolve, 30));
|
||||
out.pipeMoved = { ...snap(), toasts: globalThis.__toasts.length };
|
||||
out.adjusts = {
|
||||
revetx: m.readState("revetx", P, R),
|
||||
fordadjust: m.readState("fordadjust", P, R),
|
||||
revetlink: m.readState("revetlink", P, R),
|
||||
};
|
||||
// 관 한 번 더(10 m) — 둘째 옮김도 그대로(첫 옮김 뒤 관 id 를 앎)
|
||||
m.writeState("pipe-ids", { next: 2, ids: [{ id: "pipe-s1", at: 55 }] }, P);
|
||||
m.useDesignStore(P, null).set("stations", list(55));
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
소단 깊이 · 관 측점 고침 그대로 · 두 번 옮겨도) · 노선 입력이 바뀐 때만 넘김 규칙(대조).
|
||||
- H2 [저장] 도중 계산 줄 먹이기 멈춤 — 관 초안이 비어도 열 때 읽은 옛 관 목록으로 안 돎 · 맞춤 고리도 쉼 ·
|
||||
저장 끝 = 저장 목록 다시 읽음 · 새 자리 그대로(다시 셈 0).
|
||||
- 415-3 누가거리 조절(옹벽 · 세월 · BOX · 집수 · 연동)도 관 새 자리로 — 조정창 맵이 안 선 페이지도.
|
||||
- 415-2 관 옮김 → 되돌리기 = 묶음 입력 · 공용 측점도 원래 · 다시하기 = 옮긴 자리.
|
||||
- M4 새 시설 측점 서버 미리보기 걷음 — 미리보기 요청 0(`test_273_2` · `test_318` 이 맡음) · 여기는 코드 자리.
|
||||
|
||||
@@ -107,9 +108,10 @@ def test_H1_관_옮김_뒤_고침_그대로(h1):
|
||||
|
||||
def test_H1_노선이_바뀌면_넘김_규칙(h1):
|
||||
routed = h1["routeMoved"]
|
||||
# 대조 — 노선 입력이 바뀐 때 = 지반 유형만 넘기고 단면 유형 · 사면 쉬프트 · 소단 깊이 버림
|
||||
# 대조 — 노선 입력이 바뀐 때 = 넘김 규칙(단면 유형 버림 · 지반 유형 · 사면 쉬프트 · 소단 깊이 넘김 = 417)
|
||||
assert routed["choices"] == [[40, "soil", None], [55, "soil", None]]
|
||||
assert routed["shoulder"] == [] and routed["berm"] == []
|
||||
assert routed["shoulder"] == [["grid:1", {"left": 0.7}]]
|
||||
assert routed["berm"] == [["grid:3", {"right": 0.4}]]
|
||||
|
||||
|
||||
def test_H2_저장_도중_먹이기_멈춤(h2):
|
||||
@@ -150,3 +152,11 @@ def test_415_2_관_옮김_되돌리기_측점_원래(h2):
|
||||
assert undo["undone"]["input"] == base and undo["undone"]["stations"] == base
|
||||
assert undo["redone"]["input"] == undo["movedAgain"]["input"]
|
||||
assert undo["redone"]["stations"] == undo["movedAgain"]["stations"]
|
||||
|
||||
|
||||
def test_415_3_누가거리_조절_관_새_자리로(h1):
|
||||
# 조정창 맵이 안 선 페이지(B05 만 · 새로고침)도 관 측점 누가거리 조절이 새 자리로 · 격자 값 그대로
|
||||
adjusts = h1["adjusts"]
|
||||
assert adjusts["revetx"] == {"50.00:outlet": {"x": 0.3}, "20.00:inlet": {"x": 0.1}}
|
||||
assert adjusts["fordadjust"] == {"50.00": {"w": 1}}
|
||||
assert adjusts["revetlink"] == {"detached": {"50.00": True}, "grade": {}}
|
||||
|
||||
Reference in New Issue
Block a user