Merge remote-tracking branch 'origin/dev' into sub_laptop_6

This commit is contained in:
2026-10-25 23:18:38 +09:00
5 changed files with 37 additions and 14 deletions
+13 -3
View File
@@ -305,7 +305,14 @@ export function createSectionCanvas(onPick: (index: number | null) => void): Sec
labels.append(
svgEl(
"text",
{ x: ax + 8, y: ay - 10, class: "e03-label e03-label--fs", "data-role": "fs-label" },
{
x: ax,
y: ay,
dx: "0.6em",
dy: "-0.7em",
class: "e03-label e03-label--fs",
"data-role": "fs-label",
},
`Fs = ${fmt(critical.fs)}`,
),
);
@@ -313,7 +320,7 @@ export function createSectionCanvas(onPick: (index: number | null) => void): Sec
labels.append(
svgEl(
"text",
{ x: ax + 8, y: ay + 6, class: "e03-label" },
{ x: ax, y: ay, dx: "0.7em", dy: "0.5em", class: "e03-label" },
`Xc ${fmt(critical.center[0], 2)} · Zc ${fmt(critical.center[1], 2)} · R ${fmt(critical.radius, 2)} m`,
),
);
@@ -351,7 +358,10 @@ export function createSectionCanvas(onPick: (index: number | null) => void): Sec
maxScale: MAX_SCALE,
home: focusHome(fit, view, analysis, width, height, MAX_SCALE),
initial: zoom,
onChange: (state) => (zoom = state),
onChange: (state) => {
zoom = state;
labels.style.setProperty("--e03-label-k", String(1 / state.scale)); // 글자는 확대 안 함
},
});
};
+3 -3
View File
@@ -420,14 +420,14 @@
.e03-label {
fill: var(--color-text);
font-size: 12px;
font-size: calc(12px * var(--e03-label-k, 1));
paint-order: stroke;
stroke: var(--e03-plot);
stroke-width: 3px;
stroke-width: calc(3px * var(--e03-label-k, 1));
}
.e03-label--fs {
font-size: 14px;
font-size: calc(14px * var(--e03-label-k, 1));
font-weight: 700;
}
+9 -4
View File
@@ -137,6 +137,7 @@ def _row2d(row: dict[str, Any], method: str) -> dict[str, Any]:
cond: sides[side]["fs"] for cond, sides in cases.items() if side in sides
},
"fs_min": min(values) if values else None,
"min_by_condition": row.get("min") or {},
"method": method,
"verdict": "ng" if "ng" in verdicts else "ok" if verdicts == {"ok"} else None,
"representative": row.get("representative") or {},
@@ -556,19 +557,23 @@ def fill_3d(sheet: dict[str, Any], inputs: dict[str, Any]) -> tuple[str, str]:
ground = inputs["ground"]
labels = _labels(inputs["stations"])
rows2d = inputs["result2d"]["stations"]
crit = _criterion(ground, "dry")
sections = []
for i, sec in enumerate(inputs["sections3d"]):
r = 20 + i
_copy_row(sheet, 20, r, "ABCDEGH")
start, end = float(sec["start_m"]), float(sec["end_m"])
cond = sec.get("condition") or "dry" # 2D 는 3D 와 같은 조건끼리 견줌
inside = [
float(s["fs_min"])
float(s["min_by_condition"][cond])
for s in rows2d
if s.get("fs_min") is not None and start - 1e-6 <= float(s["chainage_m"]) <= end + 1e-6
if s["min_by_condition"].get(cond) is not None
and start - 1e-6 <= float(s["chainage_m"]) <= end + 1e-6
]
f3 = float(sec["f_min"])
ok = f3 >= crit - 1e-9
if sec.get("verdict") in ("ok", "ng"): # 판정 = E04 엔진 값(기준안전율도 E04)
ok = sec["verdict"] == "ok"
else:
ok = f3 >= _criterion(ground, cond) - 1e-9
_set(sheet, f"A{r}", f"{i + 1}구간" + (" (미리보기)" if sec.get("preview") else ""))
_set(sheet, f"B{r}", _label_at(labels, start))
_set(sheet, f"C{r}", _label_at(labels, end))
+1 -1
View File
@@ -165,7 +165,7 @@ def test_e01_requires_b06(monkeypatch):
call()
assert e.value.status_code == 404
seen, call = _e01(monkeypatch, [{**src, "project_year": 2026, "section_complete": 1}])
assert call() == {"project_id": "stab-id", "source_fingerprint": "f" * 40}
assert call() == {"project_id": "stab-id", "source_fingerprint": "f" * 40, "warnings": []}
assert seen["copied"] == ("stab-id", "s" * 36)
assert seen["kind"] == "STABILITY" and seen["source_project_id"] == "s" * 36
assert seen["name"] == "임도 안정성평가"
+11 -3
View File
@@ -157,7 +157,15 @@ def project(tmp_path, monkeypatch) -> Path:
{
"fingerprint": "3d-1",
"settings": {},
"summary": {"start_m": 0.0, "end_m": 200.0, "f_min": 1.42, "volume": 830.0},
"summary": {
"start_m": 0.0,
"end_m": 200.0,
"f_min": 1.42,
"volume": 830.0,
"condition": "wet",
"reference_fs": 1.3,
"verdict": "ok",
},
}
),
encoding="utf-8",
@@ -215,8 +223,8 @@ def test_처음_만듦_측점수_NG_그림(project):
assert s3["A26"]["값"] == "풍화토" and s3["B32"]["값"].startswith("0 ~ 100 m 위 지층")
assert s3["A32"]["값"] == "붕적토" and s3["B13"]["값"] == 1.3
s6 = by["3D요약"]["칸"]
assert s6["D20"]["값"] == 1.42 and s6["H20"] == {"값": "N.G", "서식": build.ST_NG}
assert s6["E20"]["값"] == pytest.approx(1.11) # 0~200 m 안 2D 최소
assert s6["D20"]["값"] == 1.42 and s6["H20"] == {"값": "O.K", "서식": build.ST_OK} # E04 판정
assert s6["E20"]["값"] == pytest.approx(1.11) # 0~200 m 안 2D 우기 최소(3D 와 같은 조건)
assert (build.initial_dir(project) / build.REPORT).is_file()
assert saved["fingerprint"] == build.analysis_fingerprint(project)