#!/usr/bin/env python3 """Нормализация исходных таблиц NORMY_* → JSON в data/seed/racion/.""" from __future__ import annotations import json import re import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] DEFAULT_SOURCE = ROOT.parents[1] / "для разбора и внедрения /тест/RACION_EXPORT/tables/NORMY" OUT_DIR = ROOT / "data/seed/racion" def _parse_float_list(raw: str) -> list[float]: """POPR_K / Normy — элементы разделены «;», десятичная запятая внутри числа.""" out: list[float] = [] for part in raw.strip().split(";"): p = part.strip() if not p: continue p = p.replace(",", ".") try: out.append(float(p)) except ValueError: continue return out def _read_cp1251(path: Path) -> str: for enc in ("cp1251", "utf-8", "latin-1"): try: return path.read_text(encoding=enc) except UnicodeDecodeError: continue return path.read_text(encoding="latin-1", errors="replace") def _parse_moskwa_lactir(text: str) -> dict: rows: list[dict] = [] udoy_boundaries: list[float] = [] for line in text.splitlines(): line = line.strip() if not line or line.startswith("=") or "NPITV" in line or "Database:" in line: continue m = re.match( r"^\s*([\d.]+)\s+(\d+)\s+([\d.eE+-]+)\s+(.+)$", line, ) if not m: continue npitv = int(float(m.group(1))) pom = int(m.group(2)) koef = float(m.group(3)) popr_k = _parse_float_list(m.group(4)) rows.append({"npitv": npitv, "pom": pom, "koef": koef, "popr_k": popr_k}) if npitv == 0 and pom == 2 and koef == 0.0: udoy_boundaries = popr_k return {"udoy_boundaries": udoy_boundaries, "rows": rows} def _parse_piter_lactir(text: str, *, mass_kg_values: list[float] | None = None) -> dict: entries: list[dict] = [] for line in text.splitlines(): line = line.strip() if not line or line.startswith("=") or "NPITV" in line or "Database:" in line: continue m = re.match( r"^\s*([\d.]+)\s+([\d.eE+-]+)\s+([\d.eE+-]+)\s+(.+)$", line, ) if not m: continue npitv = int(float(m.group(1))) konc = float(m.group(2)) udoy = float(m.group(3)) normy = _parse_float_list(m.group(4)) entries.append({"npitv": npitv, "konc": konc, "udoy": udoy, "normy": normy}) masses = mass_kg_values or [400, 450, 500, 550, 600, 650, 700, 750] return {"mass_kg_values": masses, "entries": entries} def _parse_normy_info(text: str) -> dict: rows: list[dict] = [] for line in text.splitlines(): line = line.strip() if not line or line.startswith("=") or "NPEREM" in line or "Database:" in line: continue m = re.match(r"^\s*(\d+)\s+(.+)$", line) if not m: continue nperem = int(m.group(1)) znachenie = _parse_float_list(m.group(2)) rows.append({"nperem": nperem, "znachenie": znachenie}) by_nperem = {r["nperem"]: r["znachenie"] for r in rows} mass_kg_values = by_nperem.get(14) or by_nperem.get(13) or [400, 450, 500, 550, 600, 650, 700, 750] return {"rows": rows, "mass_kg_values": mass_kg_values} def main() -> int: source = Path(sys.argv[1]) if len(sys.argv) > 1 else DEFAULT_SOURCE if not source.is_dir(): print(f"Source not found: {source}", file=sys.stderr) return 1 OUT_DIR.mkdir(parents=True, exist_ok=True) moskwa_path = source / "NORMY_MOSKWA_LACTIR.txt" piter_path = source / "NORMY_PITER_LACTIR.txt" info_path = source / "NORMY_INFO.txt" if not moskwa_path.exists() or not piter_path.exists(): print(f"Missing NORMY files in {source}", file=sys.stderr) return 1 normy_info = _parse_normy_info(_read_cp1251(info_path)) if info_path.exists() else { "rows": [], "mass_kg_values": [400, 450, 500, 550, 600, 650, 700, 750], } moskwa = _parse_moskwa_lactir(_read_cp1251(moskwa_path)) piter = _parse_piter_lactir( _read_cp1251(piter_path), mass_kg_values=normy_info.get("mass_kg_values"), ) (OUT_DIR / "moskwa_lactir.json").write_text( json.dumps(moskwa, ensure_ascii=False, indent=2), encoding="utf-8" ) (OUT_DIR / "piter_lactir.json").write_text( json.dumps(piter, ensure_ascii=False, indent=2), encoding="utf-8" ) (OUT_DIR / "normy_info.json").write_text( json.dumps(normy_info, ensure_ascii=False, indent=2), encoding="utf-8" ) print(f"Wrote {OUT_DIR}/moskwa_lactir.json ({len(moskwa['rows'])} rows)") print(f"Wrote {OUT_DIR}/piter_lactir.json ({len(piter['entries'])} entries)") print(f"Wrote {OUT_DIR}/normy_info.json ({len(normy_info['rows'])} rows)") return 0 if __name__ == "__main__": raise SystemExit(main())