#!/usr/bin/env python3
"""Riconferma i tre vertici gia' misurati, con il criterio di attivazione e il
verificatore di oggi.

La campagna del 12 agosto ha misurato la frontiera con il motore attuale (ILS,
adapter e runtime hanno impronte identiche a quelle di oggi), ma con il criterio
di attivazione precedente e senza il controllo del baseline nel verificatore.
I numeri di frontiera restano quelli; qui si riconferma soltanto che ai tre
vertici le 34 famiglie risultano attive anche secondo il criterio nuovo, che
confronta valore osservato e limite dichiarato invece di limitarsi a constatare
che un numero esista.

Dodici esecuzioni: tre vertici, due semi, due ripetizioni. Nessuna ricerca.
"""
import hashlib, json, os, signal, subprocess, sys, time, platform
from pathlib import Path

HERE = Path(__file__).resolve().parent
RUNNER = HERE / "universal_vrp_all34_stress_case.js"
USCITA = HERE / "conferma-tre-vertici-risultati.json"
TIMEOUT_S = 300.0
ITERAZIONI = 100
SEMI = (11, 29)

FILE_SORGENTE = [
    HERE / "vrp_saas/lib/universal-constrained-vrp/ils.js",
    HERE / "vrp_saas/lib/universal-constrained-vrp-production/index.js",
    HERE / "vrp_saas/lib/universal-constrained-vrp-verifier/verifier.js",
    HERE / "vrp_saas/lib/production-ils-runtime/index.js",
    HERE / "vrp_saas/lib/production-ils-runtime/adapter.js",
    HERE / "universal_vrp_all34_stress_case.js",
]

VERTICI = [
    ("combinato 288 clienti / 72 mezzi", {"mode": "combined", "cells": 36}),
    ("clienti 88 con 10 mezzi",          {"mode": "customer", "freeJobs": 80}),
    ("mezzi 90",                          {"mode": "vehicle", "genericVehicles": 88}),
]

def sha256(p):
    h = hashlib.sha256()
    with p.open("rb") as f:
        for pezzo in iter(lambda: f.read(1 << 20), b""):
            h.update(pezzo)
    return h.hexdigest()

def esegui(spec):
    avvio = time.monotonic()
    p = subprocess.Popen(["node", str(RUNNER), json.dumps(spec, separators=(",", ":"))],
                         cwd=str(HERE), stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                         text=True, start_new_session=True)
    scaduto = False
    while p.poll() is None:
        if time.monotonic() - avvio >= TIMEOUT_S:
            scaduto = True
            os.killpg(p.pid, signal.SIGTERM)
            try: p.wait(timeout=5)
            except subprocess.TimeoutExpired:
                os.killpg(p.pid, signal.SIGKILL); p.wait()
            break
        time.sleep(0.25)
    out, err = p.communicate()
    secondi = time.monotonic() - avvio
    if scaduto:
        return {"status": "TIMEOUT", "wallS": secondi}
    righe = [r for r in out.splitlines() if r.strip()]
    try: dati = json.loads(righe[-1])
    except Exception:
        dati = {"status": "ERRORE_HARNESS", "stdout": out[-1500:], "stderr": err[-1500:]}
    dati["wallS"] = secondi
    return dati

def main():
    esiti = []
    print(f"Riconferma di {len(VERTICI)} vertici x {len(SEMI)} semi x 2 ripetizioni = "
          f"{len(VERTICI)*len(SEMI)*2} esecuzioni, tetto {int(TIMEOUT_S)} s ciascuna.\n", flush=True)
    for etichetta, base in VERTICI:
        for seme in SEMI:
            for ripetizione in (0, 1):
                spec = dict(base, solverSeed=seme, repetition=ripetizione,
                            iterationLimit=ITERAZIONI)
                r = esegui(spec)
                riga = {
                    "vertice": etichetta, "seme": seme, "ripetizione": ripetizione,
                    "status": r.get("status"),
                    "famiglieAttive": r.get("activeFamilyCount"),
                    "famiglieMancanti": r.get("missingFamilies"),
                    "verifica": r.get("verificationStatus"),
                    "obiettivo": r.get("objective"),
                    "improntaSoluzione": r.get("solutionHash"),
                    "improntaVerifica": r.get("verificationHash"),
                    "mezziAttivi": r.get("activeVehicles"),
                    "clienti": r.get("jobs"), "servizi": r.get("services"),
                    "secondi": round(r.get("wallS", 0), 1),
                }
                esiti.append(riga)
                print(f"  {etichetta:34s} seme {seme} ripetizione {ripetizione}  "
                      f"{riga['status']:8s} famiglie {riga['famiglieAttive']}/34  "
                      f"verifica {riga['verifica']}  {riga['secondi']} s", flush=True)
    passate = [e for e in esiti if e["status"] == "PASS"]
    tutte34 = all(e["famiglieAttive"] == 34 and not e["famiglieMancanti"] for e in passate)
    verifica = all(e["verifica"] == "PASS" for e in passate)
    riepilogo = {
        "macchina": platform.platform(), "python": sys.version.split()[0],
        "tettoTecnicoS": TIMEOUT_S, "iterazioni": ITERAZIONI, "semi": list(SEMI),
        "esecuzioni": len(esiti), "passate": len(passate),
        "tutteLe34InOgniPassata": tutte34,
        "verificatoreSuperatoInOgniPassata": verifica,
        "improntaSorgenti": {str(p.relative_to(HERE)): sha256(p) for p in FILE_SORGENTE},
        "esiti": esiti,
    }
    USCITA.write_text(json.dumps(riepilogo, indent=2, ensure_ascii=False) + "\n")
    print(f"\n{len(passate)}/{len(esiti)} concluse entro il tetto.")
    print(f"34 famiglie in ogni passata: {'SI' if tutte34 else 'NO'}")
    print(f"verificatore superato in ogni passata: {'SI' if verifica else 'NO'}")
    print(f"scritto: {USCITA.name}")

if __name__ == "__main__":
    main()
