"""도엽 조각(PLAN 606) — 보이는 도엽 수 · 차례 · 30 장 넘음 = 목록 없음 · 조각 = 도곽 안 · 처음만 만듦 · 계곡선 = 등고선 중 25 m 배수 · 빈 도엽 = 빈 조각 · 받기 실패는 저장 안 함 · 화면 = 보이는 도엽만(12 · 30 문턱) · 옛 받은 범위 겹 길 안 씀. ./venv/Scripts/python.exe -m pytest resources/tester/test_606_sheet_tiles.py -q """ import json from pathlib import Path import pytest from B04_PreProcess.B04_PreProcess_Engine_MapSheet import sheet5k_center, sheet5k_to_bounds from D03_PlanAnalysis import D03_PlanAnalysis_SheetTiles as st ROOT = Path(__file__).resolve().parents[2] SHEET = "36901074" def _inside(collection, rect, eps=1e-6): lon0, lat0, lon1, lat1 = rect def walk(c): if isinstance(c[0], (int, float)): assert lon0 - eps <= c[0] <= lon1 + eps and lat0 - eps <= c[1] <= lat1 + eps else: for part in c: walk(part) for feature in collection["features"]: walk(feature["geometry"]["coordinates"]) def test_sheets_in_box_count_order_cap() -> None: lat, lon = sheet5k_center(SHEET) assert st.sheets_in_box((lon - 0.001, lat - 0.001, lon + 0.001, lat + 0.001)) == (1, [SHEET]) count, sheets = st.sheets_in_box((lon - 0.02, lat - 0.02, lon + 0.02, lat + 0.02)) assert count == len(sheets) == 9 and sheets[0] == SHEET # 가운데부터 count, sheets = st.sheets_in_box((lon - 0.1, lat - 0.1, lon + 0.1, lat + 0.1)) assert count > st.INDEX_MAX and sheets == [] @pytest.fixture() def shelf(tmp_path, monkeypatch): found = sorted(ROOT.glob(f"storage/*/*/*/B04_PreProcess/processed/map_sheets/{SHEET}.zip")) found += sorted((ROOT / "storage" / "_shared" / "sheets" / SHEET).glob("*.zip")) if not found: pytest.skip("도엽 zip 없음") monkeypatch.setattr(st, "SHEETS_ROOT", tmp_path) monkeypatch.setattr(st, "_project_zips", lambda no: found[:1] if no == SHEET else []) return tmp_path def test_zip_tile_clipped_and_made_once(shelf) -> None: path = st.ensure_tile(SHEET, "하천중심선") collection = json.loads(path.read_text(encoding="utf-8")) assert collection["features"] _inside(collection, sheet5k_to_bounds(SHEET)) stamp = path.stat().st_mtime_ns assert st.ensure_tile(SHEET, "하천중심선") == path and path.stat().st_mtime_ns == stamp assert (shelf / SHEET / f"{SHEET}.zip").is_file() # 옮겨 담음(원본은 그대로) def test_contour_and_index(shelf) -> None: full = json.loads(st.ensure_tile(SHEET, st.CONTOUR).read_text(encoding="utf-8")) index = json.loads(st.ensure_tile(SHEET, st.INDEX).read_text(encoding="utf-8")) levels = [f["properties"]["등고수치"] for f in full["features"]] assert levels and all(isinstance(v, (int, float)) for v in levels) assert index["features"] and all( f["properties"]["등고수치"] % 25 == 0 for f in index["features"] ) assert len(index["features"]) == sum(1 for v in levels if v % 25 == 0) _inside(full, sheet5k_to_bounds(SHEET)) def test_bad_name_rejected(shelf) -> None: with pytest.raises(KeyError): st.ensure_tile(SHEET, "../x") with pytest.raises(KeyError): st.ensure_tile("1234", "건물") def _no_download(monkeypatch, reason): import B04_PreProcess.B04_PreProcess_Engine_SheetStore as sheet_store monkeypatch.setattr( sheet_store, "ensure_sheets", lambda folder, nos: {"available": {}, "failed": {nos[0]: reason}}, ) def test_empty_sheet_gives_empty_tile(tmp_path, monkeypatch) -> None: monkeypatch.setattr(st, "SHEETS_ROOT", tmp_path) monkeypatch.setattr(st, "_project_zips", lambda no: []) _no_download(monkeypatch, "LookupError: 검색 결과 없음") path = st.ensure_tile("37507039", "건물") assert json.loads(path.read_text(encoding="utf-8"))["features"] == [] def test_download_failure_not_saved(tmp_path, monkeypatch) -> None: monkeypatch.setattr(st, "SHEETS_ROOT", tmp_path) monkeypatch.setattr(st, "_project_zips", lambda no: []) _no_download(monkeypatch, "PermissionError: 로그인") with pytest.raises(RuntimeError): st.ensure_tile("37507039", "건물") assert not list(tmp_path.rglob("*.geojson")) def _src(name: str) -> str: return (ROOT / "D03_PlanAnalysis" / name).read_text(encoding="utf-8") def test_screen_uses_visible_sheets() -> None: tiles = _src("D03_PlanAnalysis_UI_SheetTiles.ts") assert "export const FULL_MAX = 12;" in tiles and "export const INDEX_MAX = 30;" in tiles assert '"등고선" ? "계곡선" : null' in tiles # 13~30 = 계곡선만 layers = _src("D03_PlanAnalysis_UI_Layers.ts") assert "fetchPlanSheetLayer" not in layers assert "tiles.view(m, meta)" in layers assert len(layers.splitlines()) <= 700