#!/usr/bin/env python3
"""
verify_P041.py -- Addendum 41: strange/up quark energies.

This verifier checks the Fano-rational strange/up formulas and the six-quark
mass table in 41_Addendum_LightQuarks.tex.  The new strange and up energy
anchors are numerically close to the quoted values.  The flagged issues are
stale table arithmetic for the older bottom/charm/top rows, an incorrect top
exponent leading to 188 GeV instead of the formula's 176.1 GeV, and a slot-count
bookkeeping mismatch.
"""

from __future__ import annotations

import math
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
from verify_common import CheckResult, Verifier


class _ModernVerifier(Verifier):
    """Local adapter: identical tolerance logic, modern output format."""

    def __init__(self, name: str):
        self.name = name
        self.results = []
        print(name)

    def record(self, label, ok, computed="", claimed="", detail=""):
        self.results.append(CheckResult(label, ok, computed, claimed, detail))
        n = len(self.results)
        desc, info = label, detail
        i = detail.find("Expected")
        if i >= 0:
            desc = f"{label} -- {detail[i:]}"
            info = detail[:i].rstrip().rstrip(";")
        print(f"  [{'PASS' if ok else 'FAIL'}] {n:>2}. {desc}")
        if computed != "" or claimed != "":
            print(f"        computed: {computed}")
            print(f"        claimed : {claimed}")
        if info:
            print(f"        {info}")
        return bool(ok)

    def summary(self) -> int:
        passed = sum(bool(r.ok) for r in self.results)
        failed = len(self.results) - passed
        print(f"\n{'='*60}\nRESULT: {passed} PASS / {failed} FAIL")
        return 1 if failed else 0


v = _ModernVerifier("P041 -- Strange and Up Quark Energies")

ROOT = Path(__file__).resolve().parents[1]
TEX = (ROOT / "41_Addendum_LightQuarks.tex").read_text()

PI = math.pi
N_IM = 7
N_C = 3
ME = 0.511
MU0 = 4 * PI**3 + PI**2 + PI
MU1 = 16 * PI**3 / 5 + 3 * PI**2 / 4 + 2 * PI / 3
MU = MU1 / MU0


def mass_mev(energy: float) -> float:
    return ME * math.exp(MU * (energy - PI))


def pct(value: float, target: float) -> float:
    return 100 * (value - target) / abs(target)


E_D = math.log(MU1) / MU
E_S = PI**2 - 1 / N_IM
E_B = PI ** (N_IM / N_C)
E_U = PI ** (N_IM / (N_IM - N_C + 1))
E_C = PI**2 + PI
E_T = E_C + math.log(MU0) / MU
E_U_ALT = PI**2 - math.log(MU0)

M_D = mass_mev(E_D)
M_S = mass_mev(E_S)
M_B = mass_mev(E_B)
M_U = mass_mev(E_U)
M_C = mass_mev(E_C)
M_T_GEV = mass_mev(E_T) / 1000
M_U_ALT = mass_mev(E_U_ALT)


v.check("mu0", MU0, 137.036, rel=3e-6)
v.check("mu1", MU1, 108.717, rel=5e-6)
v.check("MU", MU, 0.7933, rel=6e-5)
v.check("strange energy pi^2-1/7", E_S, 9.727, rel=3e-5)
v.check("strange mass", M_S, 95.1, rel=3e-3)
v.check("strange residual", pct(M_S, 93.4), 1.8, rel=1.2e-1)
v.check("Fano displacement E_mu-E_s", PI**2 - E_S, 1 / 7, rel=1e-12)
v.check("up exponent denominator", N_IM - N_C + 1, 5, rel=1e-12)
v.check("up energy pi^(7/5)", E_U, 4.967, rel=2e-4)
v.check("up mass", M_U, 2.185, rel=6e-3)
v.check("up residual", pct(M_U, 2.16), 1.2, rel=6e-1)

v.check("down table energy", E_D, 5.911, rel=2e-4)
v.check("down table mass", M_D, 4.59, rel=2e-3)
v.check("bottom table energy", E_B, 14.46, rel=4e-4)
v.check(
    "bottom table mass",
    M_B,
    4141.0,
    rel=5e-3,
    detail="Expected fail: pi^(7/3) gives about 4039.9 MeV with the paper's mass formula.",
)
v.check("charm table energy", E_C, 13.011, rel=2e-5)
v.check(
    "charm table mass",
    M_C,
    1267.0,
    rel=5e-3,
    detail="Expected fail: pi^2+pi gives about 1285.1 MeV with the paper's mass formula.",
)
v.check("top table energy", E_T, 19.213, rel=7e-6)
v.check(
    "top table mass",
    M_T_GEV,
    188.0,
    rel=5e-3,
    detail="Expected fail: exact substitution gives about 176.1 GeV, not 188 GeV.",
)
v.check(
    "top exponent in recomputation paragraph",
    MU * (E_T - PI),
    12.816,
    rel=2e-3,
    detail="Expected fail: MU*(19.213-pi) is about 12.752, so the 188 GeV line is stale.",
)
v.check(
    "bottom residual",
    pct(M_B, 4180.0),
    -0.9,
    rel=2e-1,
    detail="Expected fail: exact mass gives about -3.35%.",
)
v.check(
    "charm residual",
    pct(M_C, 1270.0),
    -0.2,
    rel=5e-1,
    detail="Expected fail: exact mass gives about +1.19%.",
)
v.check(
    "top residual",
    pct(M_T_GEV, 173.0),
    8.7,
    rel=5e-2,
    detail="Expected fail: exact mass gives about +1.8%.",
)

v.check(
    "alternative up candidate mass",
    M_U_ALT,
    2.16,
    rel=2e-3,
    detail="Expected fail: pi^2-ln(mu0) gives about 2.144 MeV, close but not 0.0% error.",
)
v.check(
    "alternative up candidate residual",
    pct(M_U_ALT, 2.16),
    0.0,
    abs_tol=0.05,
    detail="Expected fail: exact residual is about -0.73%.",
)
v.record(
    "open-slot count matches the displayed table",
    False,
    computed="table lists slots 4, 12, 20, and 21: four displayed slot entries",
    claimed="five remaining open slots",
    detail="Expected bookkeeping fail: the prose count does not match the displayed rows.",
)
v.record(
    "all six quark energies are derived rather than conjectural",
    "conjecture level" not in TEX,
    computed="abstract says Conjectures I/J close the slots at the conjecture level",
    claimed="all six quark energies are derived with no free parameters",
    detail="Expected status note: the formulas are proposed anchors, not proved derivations in this addendum.",
)

sys.exit(v.summary())
