# utils/csv_utils.py — CSV read/write/export for city labels import os import csv import tempfile from typing import Dict from config import ASSETS_DIR, DIST_MIN, DIST_MAX try: import gradio as gr except ImportError: gr = None def _read_all_cities_csv(csv_path: str): with open(csv_path, "r", encoding="utf-8-sig") as f: rdr = csv.DictReader(f) rows = list(rdr) fieldnames = list(rdr.fieldnames or []) return rows, fieldnames def _write_all_cities_csv(csv_path: str, rows, fieldnames): with open(csv_path, "w", encoding="utf-8-sig", newline="") as f: w = csv.DictWriter(f, fieldnames=fieldnames) w.writeheader() for r in rows: w.writerow({k: r.get(k, "") for k in fieldnames}) def save_label_for_city_to_csv(city_name: str, ang: float, dist: float): if not city_name: if gr: try: gr.Info("Chua chon dia danh.") except Exception: pass return csv_path = os.path.join(ASSETS_DIR, "cities_custom.csv") if not os.path.exists(csv_path): if gr: try: gr.Warning("Chua co assets/cities_custom.csv.") except Exception: pass return rows, fns = _read_all_cities_csv(csv_path) for col in ("label_ang", "label_dist"): if col not in fns: fns.append(col) found = False for r in rows: if (r.get("name", "") or "").strip() == city_name.strip(): r["label_ang"] = f"{float(ang):.2f}" r["label_dist"] = f"{float(dist):.2f}" found = True break if not found: if gr: try: gr.Warning(f"Khong thay '{city_name}' trong cities_custom.csv.") except Exception: pass return _write_all_cities_csv(csv_path, rows, fns) # Reload DB from models.city import CityDB import models.city as mc mc.DB = CityDB() mc.ALL_CITIES = sorted(mc.DB.by_name.keys()) def export_cities_csv_with_labels(label_overrides: Dict[str, Dict[str, float]]): csv_path = os.path.join(ASSETS_DIR, "cities_custom.csv") rows = [] fns = ["name", "lat", "lon", "country", "aliases", "label_ang", "label_dist"] if os.path.exists(csv_path): with open(csv_path, "r", encoding="utf-8-sig") as f: rdr = csv.DictReader(f) rows = list(rdr) fns = list(dict.fromkeys(list(rdr.fieldnames or []) + ["label_ang", "label_dist"])) idx = {(r.get("name", "") or "").strip(): r for r in rows} for nm, cfg in (label_overrides or {}).items(): if nm in idx and isinstance(cfg, dict): if "ang" in cfg and cfg["ang"] is not None: idx[nm]["label_ang"] = f"{float(cfg['ang']):.2f}" if "dist" in cfg and cfg["dist"] is not None: idx[nm]["label_dist"] = f"{float(cfg['dist']):.2f}" out_path = os.path.join(tempfile.gettempdir(), "cities_custom.csv") with open(out_path, "w", encoding="utf-8-sig", newline="") as f: w = csv.DictWriter(f, fieldnames=fns) w.writeheader() for r in rows: w.writerow({k: r.get(k, "") for k in fns}) return out_path