- 새 D03_PlanAnalysis_SheetTiles.py — 도엽 도곽으로 자른 선 겹 조각(등고 · 계곡 = 전국 등고선 · 세류 · 물 면 · 도로 · 건물 · 지명 = 도엽 zip) · zip 은 프로젝트 · 공용 지형 창고에서 복사(원본 안 지움) 뒤 받기 · 빈 도엽 = 빈 조각 · 받기 실패 저장 안 함 · B04 함수 부르기만 - 라우터 길 둘 — 보이는 도엽 목록(bbox) · 조각 하나 - 새 UI_SheetTiles.ts — 보기 멈춘 뒤 보이는 도엽 · 없는 조각만 하나씩 · 12 장 이하 다 · 13~30 계곡선만 · 넘음 숨김 · 서클 - UI_Layers — 도엽 선 겹 원천을 조각으로 · 시험 606 새 · 475 옛 겹 길 단언 바꿈 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
132 lines
6.2 KiB
Python
132 lines
6.2 KiB
Python
"""D 예정노선 영역 루틴(PLAN 604 · 요구 475 · 476-2) — 도엽 겹 = 서버가 받은 범위로 자름(범위 바뀜 = 새 사본) ·
|
|
받기 끝 = 지형면 · 받은 범위 먼저 → 겹(지문 바뀜 = 차례 +1 · 옛 답 버림) · 되돌리기 · 다시하기도 영역 확인 ·
|
|
기준점 10 km 밖 = 위치 칸 알림 · 서클 = 위치 칸 제목 오른쪽 하나(들어간 일 수).
|
|
|
|
./venv/Scripts/python.exe -m pytest resources/tester/test_475_plan_area_refresh.py -q
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from common_util.common_util_crs import tm_to_lonlat
|
|
from D03_PlanAnalysis import D03_PlanAnalysis_Router as router
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
D03 = ROOT / "D03_PlanAnalysis"
|
|
EPSG = 5186
|
|
BOX_A = (206000.0, 467000.0, 208000.0, 469000.0)
|
|
BOX_B = (204000.0, 466300.0, 208000.0, 469000.0) # 서쪽 2 km · 남쪽 0.7 km 늚
|
|
|
|
|
|
def _src(name: str) -> str:
|
|
return (D03 / name).read_text(encoding="utf-8")
|
|
|
|
|
|
def _line(x: float, y0: float, y1: float) -> dict:
|
|
coords = [list(tm_to_lonlat(x, y, EPSG)) for y in (y0, y1)]
|
|
return {
|
|
"type": "Feature",
|
|
"properties": {"x": x},
|
|
"geometry": {"type": "LineString", "coordinates": coords},
|
|
}
|
|
|
|
|
|
def _xs(path: Path) -> set[float]:
|
|
return {f["properties"]["x"] for f in json.loads(path.read_text("utf-8"))["features"]}
|
|
|
|
|
|
# ── 서버 — 도엽 겹 받은 범위 자름 ──
|
|
def test_sheet_clipped_to_received_box(tmp_path) -> None:
|
|
source = tmp_path / "도엽_등고선.display.geojson"
|
|
lines = [_line(x, 465000.0, 470000.0) for x in (203000.0, 205000.0, 207000.0, 209000.0)]
|
|
source.write_text(json.dumps({"type": "FeatureCollection", "features": lines}), "utf-8")
|
|
a = router._clip_to_box(tmp_path, source, BOX_A, EPSG)
|
|
assert a != source and _xs(a) == {207000.0} # 옛 범위 = 가운데 한 가닥
|
|
b = router._clip_to_box(tmp_path, source, BOX_B, EPSG)
|
|
assert b != a and _xs(b) == {205000.0, 207000.0} # 서쪽 2 km 띠 가닥이 들어옴
|
|
assert router._clip_to_box(tmp_path, source, BOX_B, EPSG) == b # 같은 범위 = 같은 저장본
|
|
for feature in json.loads(b.read_text("utf-8"))["features"]: # 잘린 꼴 ⊆ 받은 범위(경위도 외접)
|
|
for lon, lat in feature["geometry"]["coordinates"]:
|
|
west, south = tm_to_lonlat(BOX_B[0] - 50, BOX_B[1] - 50, EPSG)
|
|
east, north = tm_to_lonlat(BOX_B[2] + 50, BOX_B[3] + 50, EPSG)
|
|
assert west <= lon <= east and south <= lat <= north
|
|
|
|
|
|
def test_sheet_clip_failure_falls_back(tmp_path) -> None:
|
|
broken = tmp_path / "깨짐.geojson"
|
|
broken.write_text("{", "utf-8")
|
|
assert router._clip_to_box(tmp_path, broken, BOX_A, EPSG) == broken
|
|
|
|
|
|
def test_sheet_endpoint_clips() -> None:
|
|
src = (D03 / "D03_PlanAnalysis_Router.py").read_text("utf-8")
|
|
body = src[src.index("async def plan_layer_sheet") :]
|
|
body = body[: body.index("@router")]
|
|
assert "_clip_to_box, root, display, box, epsg" in body
|
|
|
|
|
|
# ── 화면 — 받기 끝 차례 · 차례 번호 · 등고 · 세류 길 ──
|
|
def test_follow_reads_surface_before_layers() -> None:
|
|
page = _src("D03_PlanAnalysis_UI_Page.ts")
|
|
follow = page[page.index("async function follow") :]
|
|
follow = follow[: follow.index("\n }\n")]
|
|
assert "Promise.all([loadSurface(), backdrop.load" not in page
|
|
assert follow.index("await loadSurface();") < follow.index("await backdrop.load(have);")
|
|
assert follow.index("await backdrop.load(have);") < follow.index("await ensureCovered();")
|
|
assert page.count("await backdrop.load(have);") == 2 # 받기 끝 · 처음 열기
|
|
|
|
|
|
def test_undo_redo_check_area() -> None:
|
|
page = _src("D03_PlanAnalysis_UI_Page.ts")
|
|
for name in ("function undo()", "function redo()"):
|
|
body = page[page.index(name) :]
|
|
assert "void ensureCovered();" in body[: body.index("\n }\n")], name
|
|
|
|
|
|
def test_layers_turn_drops_old_answers() -> None:
|
|
layers = _src("D03_PlanAnalysis_UI_Layers.ts")
|
|
load = layers[layers.index("async function load(have") :]
|
|
load = load[: load.index("\n }\n")]
|
|
assert "JSON.stringify(have) !== JSON.stringify(area)" in load
|
|
assert "areaTurn += 1;" in load and "pending.clear();" in load
|
|
fetch = layers[layers.index("async function fetchLayer") :]
|
|
assert fetch.index("if (mine !== areaTurn)") < fetch.index("Object.assign(data, got);")
|
|
fill = fetch[fetch.index("async function fill") : fetch.index("const canvasLayers")]
|
|
assert "data." not in fill and "gl.setData(" not in fill # 모아 두었다가 지금 차례만 씀
|
|
assert (
|
|
"pending.get(slot) === job && pending.delete(slot)" in layers
|
|
) # 옛 일이 새 기다림을 안 지움
|
|
# 등고 · 세류 = 보이는 도엽 조각(606) · 옛 화면 상자 · 보관함 지문 걷음
|
|
assert 'tiles.collection("등고선")' in layers
|
|
assert 'tiles.collection("하천중심선")' in layers
|
|
for gone in ("/geojson?layer=", "CONTOUR_PAD_M", "haveTag", "opts.have"):
|
|
assert gone not in layers, gone
|
|
|
|
|
|
# ── 서클 · 10 km 알림 ──
|
|
def test_one_circle_in_site_title() -> None:
|
|
page = _src("D03_PlanAnalysis_UI_Page.ts")
|
|
assert "createProgressCircle({ size: 16, inline: true })" in page
|
|
assert "siteCard.firstElementChild!.append(circle.root);" in page
|
|
assert (
|
|
"corner: true" not in page
|
|
and "circle.root);\n" not in page.split("map.root.append(")[1][:80]
|
|
)
|
|
assert "createPlanLayers({ projectId, map, track: work.track })" in page
|
|
terrain = _src("D03_PlanAnalysis_UI_Terrain.ts")
|
|
assert "params.work.track(watching(params))" in terrain # 지형 받기도 같은 셈
|
|
layers = _src("D03_PlanAnalysis_UI_Layers.ts")
|
|
assert "track(fetchLayer(" in layers and "track(uploadPlanForestRoads(" in layers
|
|
progress = (ROOT / "ui_template" / "ui_template_progress.ts").read_text("utf-8")
|
|
assert "ui-progress-circle--inline" in progress
|
|
css = (ROOT / "ui_template" / "ui_template_progress.css").read_text("utf-8")
|
|
assert ".ui-progress-circle--inline {" in css
|
|
|
|
|
|
def test_far_note() -> None:
|
|
page = _src("D03_PlanAnalysis_UI_Page.ts")
|
|
assert "farFromSite(epsg, site, [...points, ...allVertices()])" in page
|
|
assert "기준점 10 km 밖 점" in page
|
|
terrain = _src("D03_PlanAnalysis_UI_Terrain.ts")
|
|
assert "list.length - nearSite(epsg, at, list).length" in terrain
|