# -*- coding: utf-8 -*-
"""
第3轮: 无求解快速图名筛查
==========================
原理: get_magnetic_graph_point 对"图名不存在"与"图存在但无结果/点号越界"
应返回不同报错文案。先用已知图名(TorqueVsAngle/FluxDensityAirgap)与伪名
(Bogus_XYZ)标定两类文案, 再穷举前缀x后缀组合, 秒级筛出真实存在的轴向力图名。
命中后单次求解并读取全波形。

用法: python axial_probe2.py [--quit] [--no-solve]
"""
import json
import os
import sys
import time

BASE = os.path.dirname(os.path.abspath(__file__))
MOT_SRC = os.path.join(BASE, "MARS-12S10P_SSSR_D76-C150_V5.0-0819.mot")
OUT_DIR = os.path.join(BASE, "output_motorcad")

PREFIXES = ["", "OC", "OC_", "OC ", "OL", "OL_", "OL ", "Load", "Load_",
            "Load ", "OnLoad_", "OnLoad", "On Load ", "OpenCircuit_",
            "OpenCircuit", "Open Circuit ", "NoLoad_", "No Load ", "Th1_",
            "Th1", "1_", "Transient_", "Static_", "Rotor_", "Stator_"]
SUFFIXES = ["Axial_Force_Rotor", "Axial_Force_Stator",
            "Axial Force Rotor", "Axial Force Stator"]
EXTRA = ["Axial_Force", "Axial Force", "Axial Force (Rotor)",
         "Axial Force (Stator)", "AxialForceRotor", "AxialForceStator",
         "Axial_Force_Rotor_OL", "Axial_Force_Rotor_OC",
         "Axial_Force_Stator_OL", "Axial_Force_Stator_OC",
         "Fz_Rotor_OL_Lumped", "Fz_Stator_OL_Lumped",
         "Ft_Rotor_OL_Lumped", "Fr_Stator_OL_Lumped"]
CONTROLS_GOOD = ["TorqueVsAngle", "FluxDensityAirgap"]
CONTROLS_BAD = ["Bogus_XYZ_NotAGraph"]


def err_of(mc, name):
    try:
        x, y = mc.get_magnetic_graph_point(name, 0)
        return ("OK", (x, y))
    except Exception as e:
        return ("ERR", str(e))


def stats(ys):
    if not ys:
        return None
    return {"mean": sum(ys) / len(ys), "min": min(ys), "max": max(ys),
            "pk2pk": max(ys) - min(ys), "n": len(ys)}


def read_graph(mc, name, maxpts=200):
    xs, ys = [], []
    for i in range(maxpts):
        try:
            x, y = mc.get_magnetic_graph_point(name, i)
        except Exception:
            break
        xs.append(x)
        ys.append(y)
    return xs, ys


def main(argv):
    quit_after = "--quit" in argv
    no_solve = "--no-solve" in argv
    os.makedirs(OUT_DIR, exist_ok=True)
    ts = time.strftime("%m%d_%H%M%S")

    from ansys.motorcad.core import MotorCAD
    print("启动 Motor-CAD (前台) ...")
    mc = MotorCAD()
    results = {"when": ts, "probe_round": 3}
    try:
        mc.load_from_file(MOT_SRC)

        # ---- 标定两类报错文案 ----
        calib = {}
        for n in CONTROLS_GOOD + CONTROLS_BAD:
            calib[n] = err_of(mc, n)
            print("  标定 %s -> %s" % (n, calib[n]))
        results["calibration"] = {k: list(v) for k, v in calib.items()}
        bad_msg = calib[CONTROLS_BAD[0]][1]

        # ---- 穷举筛查 (无求解, 快) ----
        cands = [p + s for p in PREFIXES for s in SUFFIXES] + EXTRA
        exists, not_exists, odd = [], [], {}
        for n in cands:
            kind, payload = err_of(mc, n)
            if kind == "OK":
                exists.append(n)
            elif payload == bad_msg:
                not_exists.append(n)
            else:
                odd[n] = payload   # 报错文案不同于"不存在" => 图可能存在
        results["screen"] = {"exists_ok": exists, "odd_errors": odd,
                             "n_not_exists": len(not_exists)}
        print("筛查: 直接OK %s; 异样报错 %s; 不存在 %d 个"
              % (exists, json.dumps(odd, ensure_ascii=False), len(not_exists)))

        promising = exists + list(odd.keys())
        if promising and not no_solve:
            for var in ["ElectromagneticForcesCalc_Load",
                        "ElectromagneticForcesCalc_OC"]:
                mc.set_variable(var, True)
            print("有候选, 单次求解后读全波形 ...")
            t0 = time.time()
            mc.do_magnetic_calculation()
            print("  耗时 %.1f s" % (time.time() - t0))
            waves = {}
            for n in promising + CONTROLS_GOOD:
                xs, ys = read_graph(mc, n)
                if ys:
                    waves[n] = {"stats": stats(ys), "x": xs, "y": ys}
                    print("  [波形] %s: %s" % (n, stats(ys)))
            results["waveforms"] = waves
        elif not promising:
            print("[如实] 全部候选均为'不存在', 需换思路 (数值ID枚举或GUI人工查图名)")

        res_path = os.path.join(OUT_DIR, "probe2_results_%s.json" % ts)
        with open(res_path, "w", encoding="utf-8") as f:
            json.dump(results, f, ensure_ascii=False, indent=2)
        print("RESULTS: %s" % res_path)
        return 0
    finally:
        if quit_after:
            try:
                mc.quit()
            except Exception:
                pass
        else:
            print("[提示] Motor-CAD 保持前台打开供检查。")


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
