Spaces:
Sleeping
Sleeping
| """ํ์ ๋ณ์ ์ ๋ฐ์ดํฐ ๋ก๋ + Haversine ์ต๊ทผ์ ๊ณ์ฐ.""" | |
| import math | |
| import csv | |
| from pathlib import Path | |
| from typing import Optional | |
| from api.config import SUBSTATIONS_CSV | |
| def _haversine_km(lat1: float, lon1: float, lat2: float, lon2: float) -> float: | |
| """๋ ์ง์ ๊ฐ ๊ฑฐ๋ฆฌ๋ฅผ Haversine ๊ณต์์ผ๋ก ๊ณ์ฐ (km).""" | |
| R = 6371.0 | |
| phi1, phi2 = math.radians(lat1), math.radians(lat2) | |
| dphi = math.radians(lat2 - lat1) | |
| dlam = math.radians(lon2 - lon1) | |
| a = math.sin(dphi / 2) ** 2 + math.cos(phi1) * math.cos(phi2) * math.sin(dlam / 2) ** 2 | |
| return R * 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) | |
| def _load_substations() -> list[dict]: | |
| """CSV์์ ๋ณ์ ์ ๋ฐ์ดํฐ ๋ก๋.""" | |
| path = Path(SUBSTATIONS_CSV) | |
| if not path.exists(): | |
| return [] | |
| with open(path, newline="", encoding="utf-8") as f: | |
| return list(csv.DictReader(f)) | |
| _SUBSTATIONS: list[dict] = _load_substations() | |
| def find_nearest_substation(lat: float, lon: float) -> Optional[dict]: | |
| """๊ฐ์ฅ ๊ฐ๊น์ด ๋ณ์ ์์ ๊ฑฐ๋ฆฌ(km) ๋ฐํ.""" | |
| if not _SUBSTATIONS: | |
| return None | |
| best = None | |
| best_dist = float("inf") | |
| for row in _SUBSTATIONS: | |
| try: | |
| d = _haversine_km(lat, lon, float(row["lat"]), float(row["lon"])) | |
| if d < best_dist: | |
| best_dist = d | |
| best = row | |
| except (ValueError, KeyError): | |
| continue | |
| if best is None: | |
| return None | |
| return { | |
| "name": best["name"], | |
| "distance_km": round(best_dist, 2), | |
| "voltage_kv": best.get("voltage_kv"), | |
| "remaining_kw": best.get("remaining_kw"), | |
| } | |