104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
import json
|
|
import os
|
|
|
|
|
|
def normalize_points(raw_points):
|
|
"""Return route points as [(x, y), ...], dropping malformed entries."""
|
|
points = []
|
|
if not isinstance(raw_points, list):
|
|
return points
|
|
|
|
for point in raw_points:
|
|
if not isinstance(point, (list, tuple)) or len(point) < 2:
|
|
continue
|
|
try:
|
|
points.append((float(point[0]), float(point[1])))
|
|
except (TypeError, ValueError):
|
|
continue
|
|
return points
|
|
|
|
|
|
def _looks_like_points(raw_value):
|
|
if not isinstance(raw_value, list) or not raw_value:
|
|
return False
|
|
first = raw_value[0]
|
|
if not isinstance(first, (list, tuple)) or len(first) < 2:
|
|
return False
|
|
try:
|
|
float(first[0])
|
|
float(first[1])
|
|
except (TypeError, ValueError):
|
|
return False
|
|
return True
|
|
|
|
|
|
def normalize_route(raw_route, fallback_name=""):
|
|
"""Normalize {"name": ..., "points": ...} into a route dict."""
|
|
if raw_route is None:
|
|
return None
|
|
|
|
if isinstance(raw_route, dict):
|
|
name = str(raw_route.get("name") or fallback_name or "未命名路线").strip()
|
|
raw_points = (
|
|
raw_route.get("points")
|
|
or raw_route.get("waypoints")
|
|
or raw_route.get("path")
|
|
or []
|
|
)
|
|
else:
|
|
name = str(fallback_name or "未命名路线").strip()
|
|
raw_points = raw_route
|
|
|
|
points = normalize_points(raw_points)
|
|
if not points:
|
|
return None
|
|
return {"name": name or fallback_name or "未命名路线", "points": points}
|
|
|
|
|
|
def normalize_route_list(raw_routes, fallback_prefix):
|
|
routes = []
|
|
if raw_routes is None:
|
|
return routes
|
|
|
|
if _looks_like_points(raw_routes):
|
|
route = normalize_route(raw_routes, fallback_prefix)
|
|
return [route] if route else []
|
|
|
|
if isinstance(raw_routes, dict):
|
|
raw_routes = raw_routes.get("routes") or raw_routes.get("items") or []
|
|
|
|
if not isinstance(raw_routes, list):
|
|
return routes
|
|
|
|
for idx, raw_route in enumerate(raw_routes, start=1):
|
|
route = normalize_route(raw_route, f"{fallback_prefix}{idx}")
|
|
if route:
|
|
routes.append(route)
|
|
return routes
|
|
|
|
|
|
def normalize_route_profile(data, fallback_name=""):
|
|
if not isinstance(data, dict):
|
|
raise ValueError("路线方案 JSON 必须是对象格式")
|
|
|
|
name = str(data.get("name") or fallback_name or "未命名方案").strip()
|
|
patrol_routes = normalize_route_list(data.get("patrol_routes"), "巡逻路线")
|
|
if not patrol_routes:
|
|
raise ValueError("路线方案必须包含至少一条 patrol_routes")
|
|
|
|
return {
|
|
"name": name or fallback_name or "未命名方案",
|
|
"prepare_route": normalize_route(data.get("prepare_route"), "准备路线"),
|
|
"patrol_routes": patrol_routes,
|
|
"resurrection_routes": normalize_route_list(data.get("resurrection_routes"), "复活路线"),
|
|
"vendor_route": normalize_route(data.get("vendor_route"), "修理商路线"),
|
|
"mailbox_route": normalize_route(data.get("mailbox_route"), "邮箱路线"),
|
|
}
|
|
|
|
|
|
def load_route_profile(path):
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
fallback_name = os.path.splitext(os.path.basename(path))[0]
|
|
return normalize_route_profile(data, fallback_name=fallback_name)
|