Merge remote-tracking branches 'origin/sub_laptop_2', 'origin/sub_laptop_3', 'origin/sub_laptop_4' and 'origin/sub_laptop_7' into main_laptop_1
This commit is contained in:
@@ -69,11 +69,13 @@ def frozen():
|
||||
|
||||
|
||||
CALLS: list[float] = []
|
||||
REACHES: list[object] = []
|
||||
|
||||
|
||||
def _fake_analyze(cross, design, *, layers=None, ground=None, conditions=("dry", "wet"), **kw):
|
||||
"""엔진 출력 꼴 그대로 · 값은 누가거리로 정함(1.0 + ch/100 · 건기 +0.3)."""
|
||||
CALLS.append(float(cross["chainage_m"]))
|
||||
REACHES.append(kw.get("search_reach"))
|
||||
model = section_model_from_b06(
|
||||
cross, design, layers=layers, ground=ground, materials=kw.get("materials")
|
||||
)
|
||||
@@ -209,6 +211,33 @@ def test_지문이_같으면_다시_안셈(project):
|
||||
assert body["fresh"] and any(v["required"] == 9.0 and v["ok"] is False for v in fill_dry)
|
||||
|
||||
|
||||
def test_탐색_한계는_저장되고_지문이_바뀜(project):
|
||||
first = _analyze()
|
||||
assert set(REACHES) == {"model_end"}
|
||||
body = asyncio.run(router.result2d(UUID(PID), USER))
|
||||
assert body["search_reach"] == "model_end"
|
||||
|
||||
async def go(reach):
|
||||
out = await router.analyze2d(UUID(PID), router.AnalyzeRequest(search_reach=reach))
|
||||
while router._TASKS:
|
||||
await asyncio.gather(*list(router._TASKS))
|
||||
return out
|
||||
|
||||
REACHES.clear()
|
||||
second = asyncio.run(go("2h"))
|
||||
assert second["status"] == "accepted" and second["fingerprint"] != first["fingerprint"]
|
||||
assert set(REACHES) == {"2h"} and len(REACHES) == N_STATIONS
|
||||
assert asyncio.run(router.result2d(UUID(PID), USER))["search_reach"] == "2h"
|
||||
assert asyncio.run(go(None))["status"] == "fresh" # 값 없음 = 저장값 그대로
|
||||
REACHES.clear()
|
||||
assert asyncio.run(go(12.5))["status"] == "accepted" and set(REACHES) == {12.5}
|
||||
assert asyncio.run(router.result2d(UUID(PID), USER))["search_reach"] == 12.5
|
||||
asyncio.run(go("model_end"))
|
||||
assert (
|
||||
router.plan_run(project, router._ground(project))["fp"] == first["fingerprint"]
|
||||
) # 기본 = 옛 지문
|
||||
|
||||
|
||||
def test_진행률_올라감(project, monkeypatch):
|
||||
seen = []
|
||||
|
||||
@@ -446,6 +475,7 @@ process.stdout.write(JSON.stringify({
|
||||
zAt: [m.zAt([[0, 0], [10, 10]], 2.5), m.zAt([[10, 10], [0, 0]], -5)],
|
||||
stride: [m.labelStride(100, 64), m.labelStride(40, 64), m.labelStride(10, 64), m.labelStride(0.1, 64)],
|
||||
labels: [1, 2, 5].map((k) => m.planLabelKeys(input.rows, 20, k, null)),
|
||||
basis: input.basisRows.map((r) => m.basisOf(r, "dry")),
|
||||
labelsActive: [m.planLabelKeys(input.rows, 20, 5, "e"), m.planLabelKeys(input.rows, 20, 5, "b")],
|
||||
}));
|
||||
"""
|
||||
@@ -500,7 +530,28 @@ def test_logic_TS():
|
||||
"pore_pressure": 4.47,
|
||||
}
|
||||
fs_list = [None, 1.0, 1.2, 1.35, 1.5, 1.65, 1.875, 2.25, 9.0]
|
||||
payload = {"rows": rows, "view": sec, "fsList": fs_list, "shape": shape, "slice": slice_row}
|
||||
|
||||
def side(fs, method, check=False, edge=None):
|
||||
return {"fs": fs, "method": method, "surface_check": check, "edge": edge}
|
||||
|
||||
basis_rows = [
|
||||
{
|
||||
"cases": {
|
||||
"dry": {"left": side(1.2, "bishop"), "right": side(2.0, "spencer", True, True)}
|
||||
}
|
||||
},
|
||||
{"cases": {"dry": {"left": side(1.1, "morgenstern_price", True, False)}}},
|
||||
{"cases": {"dry": {"left": {"fs": 1.5}}}}, # 옛 저장본 — 새 칸 없음
|
||||
{"cases": {}},
|
||||
]
|
||||
payload = {
|
||||
"basisRows": basis_rows,
|
||||
"rows": rows,
|
||||
"view": sec,
|
||||
"fsList": fs_list,
|
||||
"shape": shape,
|
||||
"slice": slice_row,
|
||||
}
|
||||
proc = subprocess.run(
|
||||
["node", "-e", SCRIPT, str(TYPESCRIPT), str(TS)],
|
||||
input=json.dumps(payload),
|
||||
@@ -577,6 +628,13 @@ def test_logic_TS():
|
||||
)
|
||||
assert out["ticks"][0] <= -3 and out["ticks"][-1] >= 47 and 0 in out["ticks"]
|
||||
assert out["zAt"] == [2.5, 0]
|
||||
# 판정 면 칸 — 가장 낮은 비탈의 방법 · 면 확인 · 모형 끝 면은 비탈 하나라도
|
||||
assert out["basis"] == [
|
||||
{"method": "bishop", "circular": True, "surfaceCheck": True, "edge": True},
|
||||
{"method": "morgenstern_price", "circular": False, "surfaceCheck": True, "edge": False},
|
||||
{"method": None, "circular": None, "surfaceCheck": False, "edge": False},
|
||||
{"method": None, "circular": None, "surfaceCheck": False, "edge": False},
|
||||
]
|
||||
# 평면 띠 측점 글 솎음 — 간격 px × 걸음 ≥ 64 · 본 측점 중 걸음 배수 · 고른 측점은 늘
|
||||
assert out["stride"] == [1, 2, 10, 100]
|
||||
assert out["labels"] == [["a", "b", "c", "d", "e"], ["a", "c", "e"], ["a"]]
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
목차 쪽 번호 = 실제 · 부록 절편 · 측점표 쪽 나눔 고르게 · 옛 작업본 갱신(목차 자리 · 서식 붙임).
|
||||
"""
|
||||
|
||||
import base64
|
||||
import io
|
||||
import json
|
||||
import shutil
|
||||
@@ -21,6 +22,7 @@ from common_util.common_util_workbook_xlsx import workbook_to_xlsx
|
||||
from E02_StabGround import E02_StabGround_Model as ground_model
|
||||
from E05_StabReport import E05_StabReport_Build as build
|
||||
from E05_StabReport import E05_StabReport_Figure as figure
|
||||
from E05_StabReport import E05_StabReport_Maps as maps
|
||||
from E05_StabReport import E05_StabReport_Print as printer
|
||||
from E05_StabReport import E05_StabReport_Store as store
|
||||
|
||||
@@ -175,6 +177,8 @@ def project(tmp_path, monkeypatch) -> Path:
|
||||
{
|
||||
"fingerprint": "3d-1",
|
||||
"settings": {},
|
||||
"grid": {"x0": 0.0, "y0": 0.0, "dx": 10.0, "nx": 3, "ny": 2}, # 565-2 3D 지도
|
||||
"f": [1.1, 1.6, None, 2.5, 0.9, 3.2],
|
||||
"summary": {
|
||||
"start_m": 0.0,
|
||||
"end_m": 200.0,
|
||||
@@ -252,7 +256,14 @@ def test_처음_만듦_측점수_NG_그림(project):
|
||||
assert [toc[f"B{r}"]["값"] for r in (4, 5)] == [printer.TITLES["s2"], printer.TITLES["s3"]]
|
||||
assert toc["A10"]["값"] == "부록" # 보강검토 없음 → 본문 6 + 부록 and toc["C4"]["값"] == 2
|
||||
figs = sorted((project / "E05_StabReport" / "fig").glob("*.png"))
|
||||
assert len(figs) == len(REPS) + 1 and meta["figures"][-1] == build.BAND_KEY
|
||||
assert len(figs) == len(REPS) + 2 and meta["figures"][-2:] == [build.BAND_KEY, maps.MAP3D_KEY]
|
||||
# 565-2 3D 안전율 지도 = 3D요약 표 밑 「3. …」 줄 + 그림 한 행(우기 구간뿐 → 우기)
|
||||
pic = by["3D요약"]["그림"][-1]
|
||||
assert pic["열쇠"] == maps.MAP3D_KEY and pic["닻"] == "A23:H23"
|
||||
assert by["3D요약"]["칸"]["A22"]["값"] == "3. 3D 안전율 지도"
|
||||
assert "광역요약" not in [
|
||||
s["이름"] for s in book["시트"] if s.get("그림")
|
||||
] # 광역 전 = 그림 없음
|
||||
assert [f["열쇠"] for f in by["대표단면"]["그림"]] == [build.fig_key(k) for k, _ in REPS]
|
||||
assert by["대표단면"]["인쇄"]["쪽나눔"] == [28, 56, 84]
|
||||
assert by["대표단면"]["칸"]["B30"]["값"] == "깎기 높이 15 m 이상"
|
||||
@@ -297,6 +308,8 @@ def test_광역요약_E07_저장본(project):
|
||||
"level_hi_pct": 20.0,
|
||||
},
|
||||
"computed_at": "2026-10-25T21:00:00",
|
||||
"grid": {"x0": 0.0, "y0": 0.0, "dx": 2.0, "nx": 2, "ny": 2}, # 565-2 광역 지도
|
||||
"cls": base64.b64encode(bytes([1, 6, 0, 4])).decode("ascii"),
|
||||
"stations": [
|
||||
{
|
||||
"chainage_m": 0.0,
|
||||
@@ -348,7 +361,12 @@ def test_광역요약_E07_저장본(project):
|
||||
book, _ = store.load(project)
|
||||
s7 = _sheets(book)["광역요약"]["칸"]
|
||||
assert [s7[f"C{r}"]["값"] for r in range(12, 18)] == [100.0, 20.0, 12.0, 8.0, 0.0, 36.0]
|
||||
assert [s7[f"A{r}"]["값"] for r in (22, 23)] == ["1+0", "2+0"] and "A24" not in s7
|
||||
assert [s7[f"A{r}"]["값"] for r in (22, 23)] == ["1+0", "2+0"]
|
||||
assert s7["A25"]["값"] == "4. 광역 위험 지도" # 565-2 위험 측점 표 밑
|
||||
assert _sheets(book)["광역요약"]["그림"] == [
|
||||
{"열쇠": maps.AREA_KEY, "닻": "A26:H26", "이름": "광역 위험 지도"}
|
||||
]
|
||||
assert build.fig_path(build.stage_dir(project), maps.AREA_KEY).is_file()
|
||||
assert (
|
||||
s7["E22"]["값"] == "높음 (100.0 %)"
|
||||
and s7["E23"]["값"] == "보통 (5.6 %)"
|
||||
@@ -439,12 +457,12 @@ def test_xlsx_되읽기_pdf_쪽수(project):
|
||||
_create(project)
|
||||
book, _ = store.load(project)
|
||||
figs = store.figures_of(project, book)
|
||||
assert len(figs) == len(REPS) + 1
|
||||
assert len(figs) == len(REPS) + 2 # 대표 단면 · 위험 띠 · 3D 지도(565-2)
|
||||
wb = load_workbook(io.BytesIO(workbook_to_xlsx(book, figs)))
|
||||
assert wb.sheetnames == [
|
||||
"표지", "목차", "개요", "입력조건", "측점표", "대표단면", "3D요약", "광역요약", "부록_절편",
|
||||
] # fmt: skip
|
||||
assert len(wb["대표단면"]._images) == len(REPS) and len(wb["3D요약"]._images) == 1
|
||||
assert len(wb["대표단면"]._images) == len(REPS) and len(wb["3D요약"]._images) == 2
|
||||
assert [b.id for b in wb["대표단면"].row_breaks.brk] == [28, 56, 84]
|
||||
assert wb["측점표"]["J9"].value == "N.G" and wb["측점표"]["J9"].fill.fgColor.rgb.endswith(
|
||||
"FFC7CE"
|
||||
@@ -458,8 +476,9 @@ def test_xlsx_되읽기_pdf_쪽수(project):
|
||||
texts = [p.extract_text() for p in PdfReader(io.BytesIO(pdf)).pages]
|
||||
stab = [i for i, t in enumerate(texts) if "산정 안전율" in t]
|
||||
assert len(stab) == len(book["시트"][4]["인쇄"]["쪽나눔"]) + 1 # 측점표 = 나눈 덩이 수
|
||||
# 표지 1 + 목차 1 + 개요 1 + 입력조건 1 + 측점표 n + 대표단면 3 + 3D 1 + 광역 1 + 부록 3
|
||||
assert len(texts) == 4 + len(stab) + len(REPS) + 1 + 1 + len(REPS)
|
||||
# 표지 1 + 목차 1 + 개요 1 + 입력조건 1 + 측점표 n + 대표단면 3 + 3D 2(지도) + 광역 1 + 부록 3
|
||||
assert len(texts) == 4 + len(stab) + len(REPS) + 2 + 1 + len(REPS)
|
||||
assert sum("3. 3D 안전율 지도" in t for t in texts) == 1 # 565-2 그림 제목 줄
|
||||
body = len(texts) - 1
|
||||
assert f"/ {body}" not in texts[0] and "검증 임도" not in texts[0].split("보고서")[0]
|
||||
assert all(f"- {i} / {body} -" in texts[i] and "검증 임도" in texts[i] for i in range(1, body))
|
||||
@@ -524,6 +543,16 @@ def test_길_저장_409_갱신_초기화_내보내기(project, monkeypatch):
|
||||
assert x.status_code == 200 and load_workbook(io.BytesIO(x.content)).sheetnames[0] == "표지"
|
||||
back = client.post(f"{url}/reset").json()
|
||||
assert "값" not in _sheets(back["book"])["표지"]["칸"].get("C10", {})
|
||||
# 565-2 페이지 단독 [해석](3D 저장본 바뀜) 뒤 열면 저절로 갱신 · 보기만 회사는 띠만
|
||||
r3 = project / "E04_Stab3D" / "results" / "0.00_200.00_wet.json"
|
||||
r3.write_text(r3.read_text(encoding="utf-8").replace("1.42", "1.40"), encoding="utf-8")
|
||||
app.dependency_overrides[verify_session] = lambda: {"role": "USER", "company_id": 9}
|
||||
view = client.get(url).json()
|
||||
assert view["stale"] is True and "refreshed" not in view
|
||||
app.dependency_overrides[verify_session] = lambda: {"role": "USER", "company_id": 3}
|
||||
auto = client.get(url).json()
|
||||
assert auto["refreshed"] is True and auto["stale"] is False and auto["overwritten"] == []
|
||||
assert _sheets(auto["book"])["3D요약"]["칸"]["D20"]["값"] == 1.40
|
||||
|
||||
|
||||
def test_서명_화면_왕복_같음(project):
|
||||
@@ -534,3 +563,26 @@ def test_서명_화면_왕복_같음(project):
|
||||
assert s3["칸"]["B22"]["값"] == 10.0
|
||||
trip = json.loads(json.dumps(s3).replace("10.0", "10"))
|
||||
assert trip["칸"]["B22"]["값"] == 10 and build.sheet_sign(trip) == build.sheet_sign(s3)
|
||||
|
||||
|
||||
def test_565_2_스테레오넷_측점_고름_그림():
|
||||
"""암반 그림 = 판정 나쁜 측점(NG > 검토 > O.K) · 같으면 최소 Fs 낮은 쪽."""
|
||||
from E06_StabRock import E06_StabRock_Model as rock_model
|
||||
|
||||
joints = [
|
||||
{"id": "J1", "name": "J1", "dip_direction": 115.0, "dip": 45.0, "phi": 30.0, "c": 0.0},
|
||||
{"id": "J2", "name": "J2", "dip_direction": 200.0, "dip": 70.0, "phi": 30.0, "c": 0.0},
|
||||
]
|
||||
slope = {"dip_direction": 110.0, "dip": 70.0, "side": "left", "height_m": 8.0}
|
||||
rows = [
|
||||
{"chainage_m": 0.0, "verdict": "OK", "min_F": 0.9, "joints": joints, "slope": slope},
|
||||
{"chainage_m": 20.0, "verdict": "NG", "min_F": 1.2, "joints": joints, "slope": slope},
|
||||
{"chainage_m": 40.0, "verdict": "NG", "min_F": 1.05, "joints": joints, "slope": slope},
|
||||
]
|
||||
assert maps._rock_pick({"stations": rows})["chainage_m"] == 40.0
|
||||
net = rock_model.station_net(
|
||||
rows[2], {"lateral_planar_deg": 20.0, "lateral_toppling_deg": 10.0}
|
||||
)
|
||||
svg = maps.stereonet_svg(net["equal_angle"], "평사투영")
|
||||
assert svg.count("r='3.5'") == 2 and "평면 위험 영역" in svg # 극점 둘
|
||||
assert svg.count("<path") >= 4 # 비탈 · 절리 대원 둘 · 위험 영역
|
||||
|
||||
Reference in New Issue
Block a user