solarfit-api / api /clients /substation.py
LIM
perf: reduce MAX_BASE_TILES=8, mini-batch inference
0939b04
Raw
History Blame Contribute Delete
1.67 kB
"""ํ•œ์ „ ๋ณ€์ „์†Œ ๋ฐ์ดํ„ฐ ๋กœ๋” + 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"),
}