Merge remote-tracking branches 'origin/sub_laptop_4' and 'origin/sub_laptop_8' into main_laptop_1
This commit is contained in:
@@ -53,6 +53,8 @@ def _summary(rock: dict[str, Any]) -> str:
|
||||
+ f" — 위험 모드 평면 {s['modes']['planar']} · 쐐기 {s['modes']['wedge']} · "
|
||||
f"전도 {s['modes']['toppling']}"
|
||||
)
|
||||
if s.get("small_blocks"):
|
||||
text += f" · 소규모 블록 {s['small_blocks']} (판정에서 뺌 · 낙석 관리)"
|
||||
if rock["stale"]:
|
||||
text += " · 입력이 해석 뒤 바뀜 — E06 [해석] 뒤 [보고서 갱신]"
|
||||
return text
|
||||
@@ -100,7 +102,16 @@ def fill_rock(sheet: dict[str, Any], rock: dict[str, Any], labels: dict) -> None
|
||||
if bolt["force"]
|
||||
else "볼트 없음"
|
||||
)
|
||||
_set(sheet, "B8", f"{crack_text} · {bolt_text}")
|
||||
min_block = s.get("min_block_m3", d["min_block_m3"])
|
||||
_set(
|
||||
sheet,
|
||||
"B8",
|
||||
f"{crack_text} · {bolt_text} · "
|
||||
+ mark(
|
||||
f"최소 블록 {min_block:g} m³ (이보다 작으면 판정에서 뺌)",
|
||||
min_block == d["min_block_m3"],
|
||||
),
|
||||
)
|
||||
_set(sheet, "B9", _summary(rock))
|
||||
|
||||
tpl = {r: _row_styles(sheet, r) for r in (11, 12, 13, 15, 16, 17)}
|
||||
@@ -186,6 +197,8 @@ def _station_rows(sheet, put_row, r: int, entry: dict[str, Any], labels: dict) -
|
||||
notes.append("들림")
|
||||
elif case.get("sliding") in SLIDE_NAMES:
|
||||
notes.append(SLIDE_NAMES[case["sliding"]].format(a=ids[0], b=ids[-1]))
|
||||
if case.get("small"):
|
||||
notes.append("소규모 · 낙석 관리")
|
||||
if case.get("persistence_short"):
|
||||
notes.append("지속성 < 활동면")
|
||||
cond = CONDITION_NAMES.get(case["condition"], case["condition"])
|
||||
|
||||
@@ -40,6 +40,7 @@ DEFAULT_SETTINGS: dict[str, Any] = {
|
||||
"lateral_planar_deg": engine.LATERAL_PLANAR_DEG,
|
||||
"lateral_toppling_deg": engine.LATERAL_TOPPLING_DEG,
|
||||
"gamma_r": None, # None = E02 측점 암 물성 γt
|
||||
"min_block_m3": 0.1, # 이보다 작은 블록은 판정에서 뺌(SWedge 최소 쐐기 크기 · 소규모 = 낙석 관리)
|
||||
"water_fill_wet": 0.5, # 우기 = 균열 깊이 · 활동면 높이 ½(KDS 11 70 05 표 4.3-3 암반)
|
||||
"crack": {"mode": "none", "z": None},
|
||||
"bolt": {"force": 0.0, "plunge": 15.0},
|
||||
@@ -56,6 +57,7 @@ LIMITS: dict[str, list[float]] = {
|
||||
"lateral_deg": [5.0, 45.0],
|
||||
"gamma_r": [15.0, 35.0],
|
||||
"water_fill_wet": [0.0, 1.0],
|
||||
"min_block_m3": [0.0, 1000.0],
|
||||
"crack_z": [0.1, 100.0],
|
||||
"bolt_force": [0.0, 5000.0],
|
||||
"bolt_plunge": [-30.0, 60.0],
|
||||
@@ -145,6 +147,8 @@ def check_joints(doc: dict[str, Any]) -> list[dict[str, str]]:
|
||||
bad("settings.gamma_r")
|
||||
if not _in(settings.get("water_fill_wet"), "water_fill_wet"):
|
||||
bad("settings.water_fill_wet")
|
||||
if not _in(settings.get("min_block_m3"), "min_block_m3"):
|
||||
bad("settings.min_block_m3")
|
||||
crack = settings.get("crack") if isinstance(settings.get("crack"), dict) else {}
|
||||
if crack.get("mode") not in CRACK_MODES:
|
||||
bad("settings.crack.mode", "enum")
|
||||
@@ -186,6 +190,7 @@ def clean(doc: dict[str, Any]) -> dict[str, Any]:
|
||||
"lateral_toppling_deg": float(s["lateral_toppling_deg"]),
|
||||
"gamma_r": None if s.get("gamma_r") is None else float(s["gamma_r"]),
|
||||
"water_fill_wet": float(s["water_fill_wet"]),
|
||||
"min_block_m3": float(s["min_block_m3"]),
|
||||
"crack": {
|
||||
"mode": crack["mode"],
|
||||
"z": float(crack["z"]) if crack["mode"] == "depth" else None,
|
||||
@@ -282,6 +287,7 @@ def _cases_for(slope: dict, joints: list[dict], kin: dict, settings: dict, gamma
|
||||
upper = {"dip_direction": slope["dip_direction"], "dip": slope["upper_dip"]}
|
||||
by_id = {j["id"]: j for j in joints}
|
||||
bolt = settings["bolt"]
|
||||
min_block = settings["min_block_m3"]
|
||||
crack = settings["crack"] if settings["crack"]["mode"] != "none" else None
|
||||
out = []
|
||||
for jid in kin["planar"]:
|
||||
@@ -304,6 +310,7 @@ def _cases_for(slope: dict, joints: list[dict], kin: dict, settings: dict, gamma
|
||||
short = (
|
||||
r is not None and j.get("persistence_m") is not None and j["persistence_m"] < r["A"]
|
||||
)
|
||||
volume = r["W"] / gamma if r else None # 평면 = 폭 1 m 당 면적(m²) → m³
|
||||
out.append(
|
||||
{
|
||||
"mode": "planar",
|
||||
@@ -312,6 +319,8 @@ def _cases_for(slope: dict, joints: list[dict], kin: dict, settings: dict, gamma
|
||||
"F": _fmt(r["F"]) if r else None,
|
||||
"formed": r is not None,
|
||||
"persistence_short": short,
|
||||
"volume": _fmt(volume),
|
||||
"small": volume is not None and volume < min_block,
|
||||
"W": _fmt(r["W"]) if r else None,
|
||||
"A": _fmt(r["A"]) if r else None,
|
||||
"z": _fmt(r["z"]) if r else None,
|
||||
@@ -353,6 +362,7 @@ def _cases_for(slope: dict, joints: list[dict], kin: dict, settings: dict, gamma
|
||||
"sliding": r["mode"] if r else None,
|
||||
"W": _fmt(r["W"]) if r else None,
|
||||
"volume": _fmt(r["volume"]) if r else None,
|
||||
"small": r is not None and r["volume"] < min_block,
|
||||
}
|
||||
)
|
||||
return out
|
||||
@@ -384,7 +394,11 @@ def analyze(source: Path, joints_doc: dict, ground: dict) -> list[dict[str, Any]
|
||||
for case in cases:
|
||||
need = (factors.get(case["condition"]) or {}).get("cut")
|
||||
case["required"] = need
|
||||
case["ok"] = None if case["F"] is None or need is None else case["F"] >= need
|
||||
case["ok"] = (
|
||||
None
|
||||
if case["F"] is None or need is None or case["small"]
|
||||
else case["F"] >= need
|
||||
)
|
||||
out.append(
|
||||
{
|
||||
"key": key,
|
||||
@@ -406,18 +420,22 @@ def analyze(source: Path, joints_doc: dict, ground: dict) -> list[dict[str, Any]
|
||||
|
||||
|
||||
def _verdict(kin: dict, cases: list[dict]) -> dict[str, Any]:
|
||||
"""판정 — NG(기준 미달 하나라도) · check(전도만 · 블록 안 생김) · OK · none(위험 모드 없음)."""
|
||||
values = [c["F"] for c in cases if c["F"] is not None]
|
||||
"""판정 — NG(기준 미달 하나라도) · check(전도만 · 블록 안 생김) · OK · none(위험 모드 없음 ·
|
||||
블록이 모두 소규모). 소규모 블록(최소 블록 크기 미만)은 판정 · 최소 Fs 에서 뺌."""
|
||||
judged = [c for c in cases if not c["small"]]
|
||||
values = [c["F"] for c in judged if c["F"] is not None]
|
||||
min_f = min(values) if values else None
|
||||
if any(c["ok"] is False for c in cases):
|
||||
if any(c["ok"] is False for c in judged):
|
||||
verdict = "NG"
|
||||
elif kin["toppling"] or (cases and not values):
|
||||
elif kin["toppling"] or (judged and not values):
|
||||
verdict = "check"
|
||||
elif cases:
|
||||
elif judged:
|
||||
verdict = "OK"
|
||||
else:
|
||||
verdict = "none"
|
||||
small = {(c["mode"], tuple(c["ids"])) for c in cases if c["small"]}
|
||||
return {
|
||||
"small_blocks": len(small),
|
||||
"counts": {
|
||||
"planar": len(kin["planar"]),
|
||||
"wedge": len(kin["wedge"]),
|
||||
|
||||
@@ -149,6 +149,7 @@ def _summary(stations: list[dict[str, Any]]) -> dict[str, Any]:
|
||||
return {
|
||||
"slopes": len(stations),
|
||||
"verdicts": verdicts,
|
||||
"small_blocks": sum(item["small_blocks"] for item in stations),
|
||||
"modes": {
|
||||
mode: sum(item["counts"][mode] for item in stations)
|
||||
for mode in ("planar", "wedge", "toppling")
|
||||
|
||||
@@ -29,6 +29,7 @@ export interface RockSettings {
|
||||
lateral_toppling_deg: number;
|
||||
gamma_r: number | null;
|
||||
water_fill_wet: number;
|
||||
min_block_m3: number;
|
||||
crack: { mode: "none" | "critical" | "depth"; z: number | null };
|
||||
bolt: { force: number; plunge: number };
|
||||
}
|
||||
@@ -191,6 +192,30 @@ function select<T extends string>(
|
||||
return box;
|
||||
}
|
||||
|
||||
/** 최소 블록 크기 칸 + [기본값] — 기본값 = 근거 후보(사용자 확정 전) */
|
||||
function minBlockControl(view: JointsView, s: RockSettings): HTMLElement {
|
||||
const reset = createButton({
|
||||
label: t("E06_Defaults"),
|
||||
variant: "ghost",
|
||||
size: "sm",
|
||||
onClick: () => {
|
||||
s.min_block_m3 = view.defaults.settings.min_block_m3;
|
||||
view.change();
|
||||
view.rebuild();
|
||||
},
|
||||
});
|
||||
reset.disabled = !view.editable;
|
||||
const box = el("span", { className: "e06-setting__ctl" });
|
||||
box.append(
|
||||
numberInput(view, s.min_block_m3, "min_block_m3", (v) => (s.min_block_m3 = v ?? NaN), {
|
||||
step: "0.01",
|
||||
path: "settings.min_block_m3",
|
||||
}),
|
||||
reset,
|
||||
);
|
||||
return box;
|
||||
}
|
||||
|
||||
export function buildJointCards(view: JointsView): HTMLElement[] {
|
||||
const s = view.doc.settings;
|
||||
const setsCard = createPanelCard(t("E06_Card_Joints"), false);
|
||||
@@ -260,6 +285,7 @@ export function buildJointCards(view: JointsView): HTMLElement[] {
|
||||
path: "settings.water_fill_wet",
|
||||
}),
|
||||
),
|
||||
settingRow("E06_Set_MinBlock", minBlockControl(view, s)),
|
||||
settingRow(
|
||||
"E06_Set_Crack",
|
||||
select(
|
||||
@@ -299,6 +325,7 @@ export function buildJointCards(view: JointsView): HTMLElement[] {
|
||||
}),
|
||||
),
|
||||
el("p", { className: "e06-hint", text: t("E06_SettingsHint") }),
|
||||
el("p", { className: "e06-hint", text: t("E06_MinBlockHint") }),
|
||||
);
|
||||
return [setsCard, setCard];
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export interface RockCase {
|
||||
F: number | null;
|
||||
formed: boolean;
|
||||
persistence_short: boolean;
|
||||
small: boolean;
|
||||
required: number | null;
|
||||
ok: boolean | null;
|
||||
sliding?: string | null;
|
||||
@@ -44,6 +45,7 @@ export interface StationEntry {
|
||||
cases: RockCase[];
|
||||
counts: { planar: number; wedge: number; toppling: number };
|
||||
min_F: number | null;
|
||||
small_blocks: number;
|
||||
verdict: Verdict;
|
||||
}
|
||||
|
||||
@@ -53,6 +55,7 @@ export interface RockResult {
|
||||
slopes: number;
|
||||
verdicts: Partial<Record<Verdict, number>>;
|
||||
modes: Record<string, number>;
|
||||
small_blocks: number;
|
||||
};
|
||||
stations: StationEntry[];
|
||||
}
|
||||
@@ -200,7 +203,13 @@ export function buildDetail(e: StationEntry): HTMLElement {
|
||||
table.append(el("thead", { children: [head] }), el("tbody"));
|
||||
for (const c of e.cases) {
|
||||
const verdict: Verdict = c.F === null ? "check" : c.ok === false ? "NG" : "OK";
|
||||
const note = !c.formed ? t("E06_NotFormed") : c.persistence_short ? t("E06_Persist") : "";
|
||||
const note = !c.formed
|
||||
? t("E06_NotFormed")
|
||||
: c.small
|
||||
? t("E06_Small")
|
||||
: c.persistence_short
|
||||
? t("E06_Persist")
|
||||
: "";
|
||||
const tr = el("tr", { attrs: { "data-mode": c.mode, "data-cond": c.condition } });
|
||||
tr.append(
|
||||
el("td", { text: t(`E06_Mode_${c.mode}` as LocaleKey) }),
|
||||
@@ -208,11 +217,18 @@ export function buildDetail(e: StationEntry): HTMLElement {
|
||||
el("td", { text: t(`E06_Cond_${c.condition}` as LocaleKey) }),
|
||||
el("td", { text: `${fmt(c.F, 3)}${note ? ` ${note}` : ""}` }),
|
||||
el("td", { text: fmt(c.required) }),
|
||||
el("td", { children: [badge(verdict)] }),
|
||||
el("td", { children: [c.small ? el("span", { text: "–" }) : badge(verdict)] }),
|
||||
);
|
||||
table.tBodies[0].append(tr);
|
||||
}
|
||||
box.append(table);
|
||||
if (e.small_blocks)
|
||||
box.append(
|
||||
el("p", {
|
||||
className: "e06-hint",
|
||||
text: t("E06_SmallCount").replace("{n}", String(e.small_blocks)),
|
||||
}),
|
||||
);
|
||||
if (kin.toppling.length)
|
||||
box.append(el("p", { className: "e06-hint", text: t("E06_ToppleNote") }));
|
||||
return box;
|
||||
|
||||
@@ -134,6 +134,12 @@ select.e06-input {
|
||||
width: 5.5em;
|
||||
}
|
||||
|
||||
.e06-setting__ctl {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-4);
|
||||
}
|
||||
|
||||
/* ---- 가운데 ---- */
|
||||
.e06-toolbar {
|
||||
display: flex;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
| 전도 측방 한계 (°) | 절리가 사면 반대로 기운 방향 차이가 이 각 안이면 전도 후보 | 5 ~ 45 | 20 |
|
||||
| 암 단위중량 (kN/m³ · 비우면 E02) | 덩이 무게 계산 값 · 비우면 지반 조건(E02)의 그 측점 암 물성 γt · 그것도 없으면 25 | 15 ~ 35 | 빈 칸 |
|
||||
| 우기 수위 비 (0~1) | 우기 조건 물 차는 정도 · 0 = 마름 · 1 = 가득 참 | 0 ~ 1 | 0.5 |
|
||||
| 최소 블록 크기 (m³) | 이보다 작은 블록은 판정(N.G · O.K)과 최소 Fs 에서 빼고 「소규모 · 낙석 관리」로 표시 · 평면은 폭 1 m 당 부피 · 0 = 거르지 않음 · [기본값] 으로 되돌림 | 0 ~ 1,000 | 0.1 |
|
||||
| 인장균열 | 사면 윗면에서 아래로 갈라진 틈을 볼지 · 없음 · 임계(최소 안전율 자리) · 깊이 지정 | - | 없음 |
|
||||
| 균열 깊이 (m) | 「깊이 지정」 때만 보임 · 윗면에서 잰 균열 깊이 | 0.1 ~ 100 | 1 |
|
||||
| 볼트 힘 (평면 kN/m · 쐐기 kN) | 록볼트 · 앵커가 잡아 주는 힘 · 평면은 폭 1 m 당 · 쐐기는 덩이 하나당 | 0 ~ 5,000 | 0 |
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
- 측방 한계 기본 20° = 상용 Dips 기본 · 지식DB 03 은 전도에 30° 를 씀 — 화면에서 바꿀 수 있음.
|
||||
- 우기 수위 비 기본 0.5 = 비탈 높이 ½ 수위(KDS 11 70 05 암반).
|
||||
- 최소 블록 크기 기본 0.1 m³ = 상용 쐐기 해석(SWedge)의 최소 쐐기 크기 옵션과 같은 뜻(사용자 확정 전). 아주 얇은 쐐기가 들림으로 N.G 를 내는 것을 막음. 거른 블록 수는 비탈 상세와 보고서 요약에 나옴.
|
||||
- 인장균열 「임계」 = 균열 자리를 마루 뒤로 옮겨 가며 안전율이 가장 낮은 자리를 찾음. 균열 없는 쪽이 더 낮으면 균열 없음으로 셈. 평면 무너짐에만 씀.
|
||||
- 볼트 = 수동 지지력(덩이가 움직이면 버팀). 0 이면 보강 없음.
|
||||
|
||||
|
||||
@@ -497,3 +497,135 @@ def test_e05_rock_sheet(monkeypatch):
|
||||
rock.fill_rock(sheet, old, {})
|
||||
assert sheet["칸"]["A13"]["값"] == doc["sets"][0]["name"]
|
||||
assert sheet["칸"]["G13"]["값"] == "-" # 구간 모름
|
||||
|
||||
|
||||
# ---- 최소 블록 크기 (요구 351 · 536-1 덧) --------------------------------------------
|
||||
def _cases_with_volume(monkeypatch, volume: float, min_block: float):
|
||||
"""엔진을 가짜 부피로 바꿔 경계(< 최소 블록)만 본다 — 평면(W = γ·면적) · 쐐기 둘."""
|
||||
gamma = 25.0
|
||||
monkeypatch.setattr(
|
||||
model.engine,
|
||||
"plane_fs",
|
||||
lambda **_k: {"F": 0.5, "W": volume * gamma, "A": 5.0, "z": 0.0},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
model.engine,
|
||||
"wedge_fs",
|
||||
lambda **_k: {"F": 0.0, "volume": volume, "line_length": 2.0, "mode": "lift", "W": 1.0},
|
||||
)
|
||||
joints = [
|
||||
{"id": "J1", "dip_direction": 90, "dip": 40, "phi": 30, "c": 0},
|
||||
{"id": "J2", "dip_direction": 200, "dip": 50, "phi": 30, "c": 0},
|
||||
]
|
||||
slope = {"dip_direction": 90, "dip": 68, "upper_dip": 0, "height_m": 5}
|
||||
kin = {"planar": ["J1"], "wedge": [{"ids": ["J1", "J2"]}], "toppling": []}
|
||||
settings = dict(model.DEFAULT_SETTINGS, min_block_m3=min_block)
|
||||
return model._cases_for(slope, joints, kin, settings, gamma, [("dry", 0.0, 0.0)])
|
||||
|
||||
|
||||
def test_min_block_default():
|
||||
assert model.DEFAULT_SETTINGS["min_block_m3"] == 0.1
|
||||
assert model.upgrade({"sets": [], "settings": {}})["settings"]["min_block_m3"] == 0.1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"volume,small", [(0.0999, True), (0.1, False), (0.3, False), (0.0003, True)]
|
||||
)
|
||||
def test_min_block_boundary(monkeypatch, volume, small):
|
||||
"""최소 블록 0.1 m³ — 미만만 소규모(경계 = 거르지 않음) · 평면 · 쐐기 같은 규칙."""
|
||||
cases = _cases_with_volume(monkeypatch, volume, 0.1)
|
||||
assert [c["small"] for c in cases] == [small, small]
|
||||
|
||||
|
||||
def test_min_block_zero_keeps_all(monkeypatch):
|
||||
cases = _cases_with_volume(monkeypatch, 0.0003, 0.0)
|
||||
assert not any(c["small"] for c in cases)
|
||||
|
||||
|
||||
def test_min_block_verdict_and_counts(monkeypatch):
|
||||
"""얇은 쐐기(들림 Fs 0)가 N.G 를 내던 자리 — 거르면 판정 · 최소 Fs 에서 빠지고 거른 블록 수가 남음."""
|
||||
kin = {"planar": ["J1"], "wedge": [{"ids": ["J1", "J2"]}], "toppling": []}
|
||||
for min_block, verdict, n_small in ((0.0, "NG", 0), (0.1, "none", 2)):
|
||||
cases = _cases_with_volume(monkeypatch, 0.0003, min_block)
|
||||
for c in cases:
|
||||
c["required"] = 1.2
|
||||
c["ok"] = None if c["small"] else c["F"] >= 1.2
|
||||
out = model._verdict(kin, cases)
|
||||
assert (out["verdict"], out["small_blocks"]) == (verdict, n_small)
|
||||
assert out["min_F"] == (0.0 if not n_small else None)
|
||||
# 큰 블록 + 작은 블록 섞임 — 작은 것만 빠지고 큰 것으로 판정
|
||||
big = dict(_cases_with_volume(monkeypatch, 0.5, 0.1)[0], required=1.2, ok=False)
|
||||
tiny = dict(_cases_with_volume(monkeypatch, 0.0003, 0.1)[1], required=1.2, ok=None)
|
||||
tiny["F"] = 0.0
|
||||
out = model._verdict(kin, [big, tiny])
|
||||
assert (out["verdict"], out["min_F"], out["small_blocks"]) == ("NG", 0.5, 1)
|
||||
|
||||
|
||||
def test_min_block_check_range():
|
||||
doc = _doc()
|
||||
doc["settings"]["min_block_m3"] = -1
|
||||
assert {"path": "settings.min_block_m3", "code": "range"} in model.check_joints(doc)
|
||||
doc["settings"]["min_block_m3"] = 2.5
|
||||
assert model.check_joints(doc) == []
|
||||
assert model.clean(doc)["settings"]["min_block_m3"] == 2.5
|
||||
|
||||
|
||||
def test_analyze_min_block_filter(monkeypatch):
|
||||
"""측점 해석 전체 길 — 최소 블록을 크게 주면 모든 경우 소규모 · ok 없음 · 판정 none."""
|
||||
cross, design = _cross("left")
|
||||
monkeypatch.setattr(
|
||||
model,
|
||||
"rock_stations",
|
||||
lambda _s: [{"chainage_m": 20.0, "label": "STA", "ground_type": "ripping_rock"}],
|
||||
)
|
||||
monkeypatch.setattr(model.src, "cross_section", lambda _s, _c: {**cross, "design": design})
|
||||
ground = {
|
||||
"materials": [],
|
||||
"stations": [],
|
||||
"safety_factors": {"dry": {"cut": 1.5}, "wet": {"cut": 1.2}},
|
||||
"seismic": {"enabled": False},
|
||||
}
|
||||
base = model.analyze(None, _doc(), ground)[0]
|
||||
assert not any(c["small"] for c in base["cases"]) and base["small_blocks"] == 0
|
||||
doc = _doc()
|
||||
doc["settings"]["min_block_m3"] = 1000.0
|
||||
e = model.analyze(None, doc, ground)[0]
|
||||
assert all(c["small"] and c["ok"] is None for c in e["cases"])
|
||||
assert (e["verdict"], e["min_F"], e["small_blocks"]) == ("none", None, 1)
|
||||
|
||||
|
||||
def test_e05_rock_sheet_small(monkeypatch):
|
||||
"""E05 s11 — 최소 블록 글 · 소규모 요약 · 줄 비고."""
|
||||
from E05_StabReport import E05_StabReport_Build as build
|
||||
from E05_StabReport import E05_StabReport_Rock as rock
|
||||
from E06_StabRock import E06_StabRock_Router as router
|
||||
|
||||
cross, design = _cross("left")
|
||||
monkeypatch.setattr(
|
||||
model,
|
||||
"rock_stations",
|
||||
lambda _s: [{"chainage_m": 20.0, "label": "STA", "ground_type": "ripping_rock"}],
|
||||
)
|
||||
monkeypatch.setattr(model.src, "cross_section", lambda _s, _c: {**cross, "design": design})
|
||||
ground = {
|
||||
"materials": [],
|
||||
"stations": [],
|
||||
"safety_factors": {"dry": {"cut": 1.5}, "wet": {"cut": 1.2}},
|
||||
"seismic": {"enabled": False},
|
||||
}
|
||||
doc = _doc()
|
||||
doc["settings"]["min_block_m3"] = 1000.0
|
||||
stations = model.analyze(None, doc, ground)
|
||||
value = {
|
||||
"settings": doc["settings"],
|
||||
"sets": doc["sets"],
|
||||
"summary": router._summary(stations),
|
||||
"stations": stations,
|
||||
"stale": False,
|
||||
}
|
||||
sheet = next(s for s in build.form()["시트"] if s["id"] == "s11")
|
||||
rock.fill_rock(sheet, value, {})
|
||||
cells = sheet["칸"]
|
||||
assert "최소 블록 1000 m³" in cells["B8"]["값"] and "사용자 입력" in cells["B8"]["값"]
|
||||
assert "소규모 블록 1" in cells["B9"]["값"]
|
||||
assert any("소규모 · 낙석 관리" in str(c.get("값")) for c in cells.values())
|
||||
|
||||
@@ -40,6 +40,12 @@ export const ui_locales_e06 = {
|
||||
"우기 수위 비 (0~1 · 균열 · 활동면 높이 대비)",
|
||||
"Wet water ratio (0–1, of crack / sliding-plane height)",
|
||||
],
|
||||
E06_Set_MinBlock: ["최소 블록 크기 (m³)", "Minimum block size (m³)"],
|
||||
E06_Defaults: ["기본값", "Default"],
|
||||
E06_MinBlockHint: [
|
||||
"최소 블록 크기 기본 0.1 m³ = 상용 쐐기 해석(SWedge)의 최소 쐐기 크기 옵션과 같은 뜻 — 그보다 작은 블록은 판정에서 빼고 「소규모 · 낙석 관리」로 표시 (평면은 폭 1 m 당 부피) · 사용자 확정 전.",
|
||||
"Default minimum block 0.1 m³ = same meaning as the minimum wedge size option of commercial wedge analysis (SWedge): smaller blocks are left out of the verdict and flagged small — rockfall management (planar = volume per 1 m width) · not yet confirmed by user.",
|
||||
],
|
||||
E06_Set_Crack: ["인장균열", "Tension crack"],
|
||||
E06_Crack_None: ["없음", "None"],
|
||||
E06_Crack_Critical: ["임계(최소 안전율 자리)", "Critical (minimum FS)"],
|
||||
@@ -116,6 +122,11 @@ export const ui_locales_e06 = {
|
||||
E06_Cond_dry: ["건기", "Dry"],
|
||||
E06_Cond_wet: ["우기", "Wet"],
|
||||
E06_Cond_seismic: ["지진", "Seismic"],
|
||||
E06_Small: ["(소규모 · 낙석 관리)", "(small · rockfall management)"],
|
||||
E06_SmallCount: [
|
||||
"소규모 블록 {n}개 · 낙석 관리 — 판정에서 뺌",
|
||||
"{n} small block(s) · rockfall management — not judged",
|
||||
],
|
||||
E06_NotFormed: ["(블록 안 생김)", "(no block)"],
|
||||
E06_Persist: ["(지속성 < 활동면)", "(persistence < plane)"],
|
||||
E06_ToppleNote: [
|
||||
|
||||
Reference in New Issue
Block a user