fix(B07 표준도): 노선 저장값 일치
B06 계산과 같은 횡단경사 하한을 사용하고, 그리는 노선의 저장값을 도면과 지문에 함께 적용.
This commit is contained in:
@@ -141,7 +141,7 @@ def _section_geometry(values: dict[str, Any]) -> dict[str, Any]:
|
|||||||
bottom_width = _number(ditch.get("bottom_width_m"), 0.3)
|
bottom_width = _number(ditch.get("bottom_width_m"), 0.3)
|
||||||
depth = _number(ditch.get("depth_m"), 0.3)
|
depth = _number(ditch.get("depth_m"), 0.3)
|
||||||
slope = values.get("cross_slope_pct") if isinstance(values.get("cross_slope_pct"), dict) else {}
|
slope = values.get("cross_slope_pct") if isinstance(values.get("cross_slope_pct"), dict) else {}
|
||||||
cross_pct = _number(slope.get("max"), _number(slope.get("min"), 3.0))
|
cross_pct = _number(slope.get("min"), _number(slope.get("max"), 3.0))
|
||||||
cut_ratio = _number(values.get("cut_slope_ratio"), 1.0)
|
cut_ratio = _number(values.get("cut_slope_ratio"), 1.0)
|
||||||
fill_ratio = _number(values.get("fill_slope_ratio"), 1.2)
|
fill_ratio = _number(values.get("fill_slope_ratio"), 1.2)
|
||||||
|
|
||||||
|
|||||||
@@ -359,7 +359,7 @@ async def get_design_drawing(
|
|||||||
source_design = ((section or {}).get("data") or {}).get("mass_haul")
|
source_design = ((section or {}).get("data") or {}).get("mass_haul")
|
||||||
elif drawing_id == CROSS_STANDARD_ID:
|
elif drawing_id == CROSS_STANDARD_ID:
|
||||||
# 표준 횡단면도는 B06 「표준 횡단면 설정」 저장값으로 그린다(없으면 config 기본값).
|
# 표준 횡단면도는 B06 「표준 횡단면 설정」 저장값으로 그린다(없으면 config 기본값).
|
||||||
source_design = await standard_cross_source(project_id)
|
source_design = await standard_cross_source(project_id, route_id)
|
||||||
elif DEVELOPMENT_ID.fullmatch(drawing_id):
|
elif DEVELOPMENT_ID.fullmatch(drawing_id):
|
||||||
# 전개도 — 추가 흙막이 단 수 · 포장 빈 폭을 측점별 설계에서 읽음(377)
|
# 전개도 — 추가 흙막이 단 수 · 포장 빈 폭을 측점별 설계에서 읽음(377)
|
||||||
source_design = await _designs_by_chainage(route_id)
|
source_design = await _designs_by_chainage(route_id)
|
||||||
|
|||||||
@@ -354,22 +354,18 @@ async def plan_copy_key(
|
|||||||
return prints[drawing_id]["fingerprint"]
|
return prints[drawing_id]["fingerprint"]
|
||||||
|
|
||||||
|
|
||||||
async def standard_cross_source(project_id: UUID) -> Any:
|
async def standard_cross_source(project_id: UUID, route_id: int) -> Any:
|
||||||
"""표준 횡단면 설정(B06) — GET 과 지문이 같은 값을 씀."""
|
"""그리는 노선의 표준 횡단면 설정(B06) — GET 과 지문이 같은 값을 씀."""
|
||||||
from B06_Section.B06_Section_Repository import get_project_standard_cross_section
|
from B06_Section.B06_Section_Repository import get_longitudinal_section
|
||||||
from config.config_db import get_db_pool
|
from config.config_db import get_db_pool
|
||||||
|
|
||||||
pool = get_db_pool()
|
pool = get_db_pool()
|
||||||
async with pool.acquire() as connection:
|
async with pool.acquire() as connection:
|
||||||
async with connection.cursor() as cursor:
|
section = await get_longitudinal_section(connection, project_id, route_id)
|
||||||
await cursor.execute(
|
data = (section or {}).get("data") or {}
|
||||||
"SELECT company_id FROM projects WHERE id = %s AND deleted_at IS NULL",
|
options = data.get("options") if isinstance(data, dict) else None
|
||||||
(str(project_id),),
|
standard = options.get("standard_cross_section") if isinstance(options, dict) else None
|
||||||
)
|
return standard if isinstance(standard, dict) else None
|
||||||
row = await cursor.fetchone()
|
|
||||||
if not row:
|
|
||||||
return None
|
|
||||||
return await get_project_standard_cross_section(connection, int(row[0]), project_id)
|
|
||||||
|
|
||||||
|
|
||||||
async def drawing_fingerprints(
|
async def drawing_fingerprints(
|
||||||
@@ -424,7 +420,7 @@ async def drawing_fingerprints(
|
|||||||
|
|
||||||
async def read_standard() -> None:
|
async def read_standard() -> None:
|
||||||
if _STANDARD_ID in ids:
|
if _STANDARD_ID in ids:
|
||||||
sources["standard"] = await standard_cross_source(project_id)
|
sources["standard"] = await standard_cross_source(project_id, route_id)
|
||||||
|
|
||||||
async def read_cross() -> None:
|
async def read_cross() -> None:
|
||||||
if not has_sheet:
|
if not has_sheet:
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""517-1 B07 표준 횡단면도 = 그리는 노선의 B06 저장값."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from types import SimpleNamespace
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
if str(ROOT) not in sys.path:
|
||||||
|
sys.path.insert(0, str(ROOT))
|
||||||
|
|
||||||
|
from B06_Section import B06_Section_Repository as b06_repository # noqa: E402
|
||||||
|
from B07_DesignDetail.B07_DesignDetail_Engine_Cad_Standard import ( # noqa: E402
|
||||||
|
MM,
|
||||||
|
SECTION_LAYER_ID,
|
||||||
|
build_standard_cross_drawing,
|
||||||
|
)
|
||||||
|
from B07_DesignDetail import B07_DesignDetail_Router_Support_Fingerprint as fp # noqa: E402
|
||||||
|
from config import config_db # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
|
def _standard(cross_slope_pct: float) -> dict:
|
||||||
|
return {
|
||||||
|
"soil": {
|
||||||
|
"road_width_m": 3.0,
|
||||||
|
"shoulder_left_m": 0.5,
|
||||||
|
"shoulder_right_m": 0.5,
|
||||||
|
"cross_slope_pct": {"min": cross_slope_pct, "max": 5.0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_B06_저장값_3퍼센트로_표준도_선과_숫자를_그림():
|
||||||
|
drawing = build_standard_cross_drawing("cross_standard", "표준 횡단면도", _standard(3.0))
|
||||||
|
labels = [
|
||||||
|
entity["shapeData"]["label"] for entity in drawing["entities"] if entity["type"] == "Text"
|
||||||
|
]
|
||||||
|
assert "횡단경사 3%" in labels
|
||||||
|
|
||||||
|
outline = next(
|
||||||
|
entity
|
||||||
|
for entity in drawing["entities"]
|
||||||
|
if entity["type"] == "PolyLine" and entity["layerId"] == SECTION_LAYER_ID
|
||||||
|
)
|
||||||
|
road = next(
|
||||||
|
child["shapeData"]
|
||||||
|
for child in outline["children"]
|
||||||
|
if child["shapeData"]["startPoint"]["x"] == -2.0 * MM
|
||||||
|
and child["shapeData"]["endPoint"]["x"] == 2.0 * MM
|
||||||
|
)
|
||||||
|
assert road["startPoint"]["y"] == -2.0 * MM * 0.03
|
||||||
|
assert road["endPoint"]["y"] == 0.0
|
||||||
|
|
||||||
|
|
||||||
|
class _Acquire:
|
||||||
|
async def __aenter__(self):
|
||||||
|
return object()
|
||||||
|
|
||||||
|
async def __aexit__(self, *exc):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class _Pool:
|
||||||
|
def acquire(self):
|
||||||
|
return _Acquire()
|
||||||
|
|
||||||
|
|
||||||
|
def test_노선_둘이면_그리는_노선의_B06_저장값만_읽음(monkeypatch):
|
||||||
|
standards = {11: _standard(4.0), 22: _standard(3.0)}
|
||||||
|
|
||||||
|
async def get_section(_connection, _project_id, route_id):
|
||||||
|
return {"data": {"options": {"standard_cross_section": standards[route_id]}}}
|
||||||
|
|
||||||
|
monkeypatch.setattr(b06_repository, "get_longitudinal_section", get_section)
|
||||||
|
monkeypatch.setattr(config_db, "get_db_pool", lambda: _Pool())
|
||||||
|
|
||||||
|
source = asyncio.run(fp.standard_cross_source(uuid4(), 22))
|
||||||
|
assert source["soil"]["cross_slope_pct"]["min"] == 3.0
|
||||||
|
|
||||||
|
|
||||||
|
def test_표준도_지문도_그리는_노선값을_씀(monkeypatch, tmp_path):
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
async def standard_source(_project_id, route_id):
|
||||||
|
calls.append(route_id)
|
||||||
|
return _standard(3.0)
|
||||||
|
|
||||||
|
def fingerprints(_root, _longitudinal, _drawings, sources):
|
||||||
|
return {"standard": sources["standard"]}
|
||||||
|
|
||||||
|
monkeypatch.setattr(fp, "standard_cross_source", standard_source)
|
||||||
|
monkeypatch.setattr(fp, "compute_fingerprints", fingerprints)
|
||||||
|
result = asyncio.run(
|
||||||
|
fp.drawing_fingerprints(
|
||||||
|
uuid4(),
|
||||||
|
22,
|
||||||
|
tmp_path,
|
||||||
|
tmp_path / "longitudinal.json",
|
||||||
|
[SimpleNamespace(id="cross_standard", kind="cross_standard")],
|
||||||
|
{},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
assert calls == [22]
|
||||||
|
assert result["standard"]["soil"]["cross_slope_pct"]["min"] == 3.0
|
||||||
Reference in New Issue
Block a user