Files
Aislo/E02_StabGround/E02_StabGround_UI_Water.ts
T

185 lines
5.9 KiB
TypeScript

/* =============================================================================
* E02_StabGround_UI_Water.ts
* E02 지하수 카드(요구 347 · 351 · PLAN 532-3) — 건기 규칙 · 우기 갈래 넷(KDS 기본 · 지표 아래 깊이 비율 ·
* r_u · 사용자 수위선 구간) · 「KDS 기본 · 우기 기준안전율 1.2 와 짝」 안내 · [기본값].
* 엔진 꼴로 바꾸기는 서버(`E02_StabGround_Model.station_groundwater`) — 여기는 값만 고침.
* ========================================================================== */
import { createButton, el } from "@ui/ui_template_elements";
import { createText } from "@ui/ui_template_text";
import { t, type LocaleKey } from "@ui/ui_template_locale";
import { WATER_KEYS, WATER_RULES, WET_MODES, type WetMode } from "./logic/E02_StabGround_Check";
import {
card,
clone,
headButtons,
hook,
numInput,
selectInput,
table,
type E02View,
} from "./E02_StabGround_UI_Tables";
const L = (key: string): string => t(key as LocaleKey);
function field(label: string, input: HTMLElement): HTMLElement {
const node = el("label", { className: "ui-field e02-field" });
node.append(el("span", { className: "ui-field__label", text: label }), input);
return node;
}
function removeButton(view: E02View, onClick: () => void): HTMLButtonElement {
const button = createButton({
label: t("E02_Btn_Remove"),
variant: "danger-ghost",
size: "sm",
onClick,
});
button.hidden = !view.editable;
return button;
}
/** 사용자 수위선 구간 표 — 줄마다 시작 · 끝 · 점(offset · 깊이) · [점 추가] · [지움] */
function linesBody(view: E02View): HTMLElement {
const water = view.ground.groundwater;
if (!water.lines.length) return hook(createText(t("E02_Line_Empty")), "e02-empty");
const rows = water.lines.map((line, i) => {
const base = `groundwater.lines.${i}`;
const points = el("div", { className: "e02-points" });
points.dataset.path = `${base}.points`;
line.points.forEach((point, k) => {
const pair = el("span", { className: "e02-point" });
pair.append(
numInput(view, `${base}.points.${k}.0`, point[0], (v) => (point[0] = v as number)),
numInput(view, `${base}.points.${k}.1`, point[1], (v) => (point[1] = v as number)),
removeButton(view, () => {
line.points.splice(k, 1);
view.rebuild();
}),
);
points.append(pair);
});
const addPoint = createButton({
label: t("E02_Btn_AddPoint"),
variant: "ghost",
size: "sm",
onClick: () => {
const last = line.points[line.points.length - 1];
line.points.push(last ? [last[0] + 5, last[1]] : [0, 1]);
view.rebuild();
},
});
addPoint.hidden = !view.editable;
points.append(addPoint);
return [
numInput(view, `${base}.from_m`, line.from_m, (v) => (line.from_m = v as number)),
numInput(view, `${base}.to_m`, line.to_m, (v) => (line.to_m = v as number)),
points,
removeButton(view, () => {
water.lines.splice(i, 1);
view.rebuild();
}),
];
});
return table([t("E02_Col_From"), t("E02_Col_To"), t("E02_Col_Points"), ""], rows);
}
export function waterCard(view: E02View): HTMLElement {
const water = view.ground.groundwater;
const d = view.defaults.groundwater;
const rule = (key: (typeof WATER_KEYS)[number]): HTMLElement =>
field(
L(`E02_Water_${key}`),
selectInput(
view,
`groundwater.${key}`,
WATER_RULES.map((r) => ({ value: r, text: L(`E02_Rule_${r}`) })),
water[key],
(v) => (water[key] = v as (typeof WATER_RULES)[number]),
{ src: `groundwater.${key}`, def: L(`E02_Rule_${d[key]}`) },
),
);
const mode = selectInput(
view,
"groundwater.wet_mode",
WET_MODES.map((m) => ({ value: m, text: L(`E02_WetMode_${m}`) })),
water.wet_mode,
(v) => {
water.wet_mode = v as WetMode;
view.rebuild();
},
{ src: "groundwater.wet_mode", def: L(`E02_WetMode_${d.wet_mode}`) },
);
const grid = el("div", { className: "e02-grid" });
grid.append(rule("dry"), field(t("E02_WetMode"), mode));
const body: HTMLElement[] = [];
if (water.wet_mode === "kds") grid.append(rule("wet_soil"), rule("wet_rock"));
if (water.wet_mode === "depth_ratio")
grid.append(
field(
t("E02_DepthRatio"),
numInput(
view,
"groundwater.depth_ratio",
water.depth_ratio,
(v) => (water.depth_ratio = v as number),
{ src: "groundwater.depth_ratio", def: d.depth_ratio },
),
),
);
if (water.wet_mode === "ru")
grid.append(
field(
t("E02_Ru"),
numInput(view, "groundwater.ru", water.ru, (v) => (water.ru = v as number), {
src: "groundwater.ru",
def: d.ru,
}),
),
);
if (water.wet_mode === "line")
body.push(hook(createText(t("E02_Line_Hint")), "e02-hint"), linesBody(view));
const { section, head } = card(
"E02_Card_Water",
hook(createText(t("E02_Water_Hint")), "e02-hint"),
grid,
...body,
);
const stations = view.ground.stations;
const first = stations[0]?.chainage_m ?? 0;
const last = stations[stations.length - 1]?.chainage_m ?? 100;
const buttons = [
createButton({
label: t("E02_Btn_Defaults"),
variant: "ghost",
size: "sm",
onClick: () => {
view.ground.groundwater = clone(d);
view.rebuild();
},
}),
];
if (water.wet_mode === "line")
buttons.unshift(
createButton({
label: t("E02_Btn_AddLine"),
variant: "ghost",
size: "sm",
onClick: () => {
water.lines.push({
from_m: first,
to_m: last > first ? last : first + 20,
points: [
[-10, 1],
[10, 1],
],
});
view.rebuild();
},
}),
);
headButtons(view, head, ...buttons);
return section;
}