"""Price vs backlash: the Rinnegan drive (HDP30 v2.0) against off-the-shelf NEMA 17 gearboxes.

Run:  python compare_cots.py     (PLOT_THEME=light for the website cream)
Writes cots_price_vs_backlash.png next to this file.

Fairness rules:
  - Our drive is plotted at its WORST single backlash reading across all 12 slow runs on gearbox 2
    (0.111 deg = 6.7 arcmin, the 0.03 deg detection threshold left in), not the 2 arcmin typical.
  - Commercial numbers are datasheet / listing maximums, gearbox only, as listed in October 2026.
    Marketplace prices move; the source is noted for each.
  - Our price is the drive without a motor, about $5. It leaves out printer time and labour.
"""
import os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

from analysis import HERE, OUT, DPI, INK, INK2, GRID, C_CH1, C_CH2, C_ALT

OURS_WORST_DEG = 0.111            # departure, CCW 0.4 A test 2 (numbers_backlash.txt)
OURS_TYPICAL_DEG = 0.03
OURS_PRICE = 5.0                  # the drive without a motor

# (label, price USD, backlash arcmin, kind, label offset in points)
COTS = [
    ("StepperOnline MG 5:1", 24.0, 30, "planetary", (-10, -4)),
    ("StepperOnline MG 10:1", 35.07, 30, "planetary", (8, 6)),
    ("StepperOnline MG 20:1", 42.54, 50, "planetary", (8, 2)),
    ("Precision right-angle planetary", 245.59, 5, "planetary", (-10, 10)),
    ("PGFUN harmonic 30:1", 99.99, 2, "harmonic", (8, -4)),
    ("VXB harmonic 50:1", 139.99, 20 / 60, "harmonic", (-6, 10)),
    ("VXB harmonic 100:1", 214.88, 20 / 60, "harmonic", (8, -4)),
]
COL = {"planetary": C_CH1, "harmonic": C_ALT}


def main():
    fig, ax = plt.subplots(figsize=(11.5, 7))
    for lab, p, b, kind, off in COTS:
        ax.scatter(p, b, s=110, color=COL[kind], zorder=4, edgecolors="none")
        ha = "right" if off[0] < 0 else "left"
        ax.annotate(lab, (p, b), textcoords="offset points", xytext=off, ha=ha, color=INK2, fontsize=10.5)

    worst = OURS_WORST_DEG * 60
    typ = OURS_TYPICAL_DEG * 60
    ax.plot([OURS_PRICE, OURS_PRICE], [typ, worst], color=C_CH2, lw=2, alpha=0.5, zorder=3)
    ax.scatter(OURS_PRICE, typ, s=70, facecolors="none", edgecolors=C_CH2, linewidths=1.8, zorder=4)
    ax.scatter(OURS_PRICE, worst, s=240, marker="*", color=C_CH2, zorder=5, edgecolors="none")
    ax.annotate(f"Rinnegan drive (HDP30)\nworst reading {worst:.1f} arcmin, ~${OURS_PRICE:.0f}",
                (OURS_PRICE, worst), textcoords="offset points", xytext=(12, 4), color=INK,
                fontsize=12, fontweight="bold")
    ax.annotate(f"typical {typ:.1f} arcmin", (OURS_PRICE, typ), textcoords="offset points",
                xytext=(10, -4), color=C_CH2, fontsize=10.5)

    ax.set_xscale("log")
    ax.set_yscale("log")
    ax.set_xlim(3, 400)
    ax.set_ylim(0.2, 100)
    ax.set_xticks([5, 10, 20, 50, 100, 200])
    ax.set_xticklabels(["$5", "$10", "$20", "$50", "$100", "$200"])
    ax.set_yticks([0.25, 0.5, 1, 2, 5, 10, 20, 50, 100])
    ax.set_yticklabels(["0.25", "0.5", "1", "2", "5", "10", "20", "50", "100"])
    ax.grid(True, which="major")
    ax.grid(False, which="minor")
    ax.set_xlabel("price, gearbox only  [USD, log scale]")
    ax.set_ylabel("backlash  [arcmin, log scale]   (lower is better)")
    ax.text(3.3, 0.24, "lower left = cheaper and tighter", color=INK2, fontsize=11)
    ax.legend(handles=[Line2D([], [], marker="*", ls="", color=C_CH2, ms=14, label="Rinnegan drive, worst case (measured)"),
                       Line2D([], [], marker="o", ls="", color=C_CH1, ms=9, label="planetary (datasheet max)"),
                       Line2D([], [], marker="o", ls="", color=C_ALT, ms=9, label="metal strain wave (datasheet max)")],
              loc="upper left")
    ax.set_title("PRICE vs BACKLASH: even at its worst reading, it beats every planetary under $200")
    fig.text(0.01, 0.01, "Commercial: listed maximums, Oct 2026 listings. Ours: worst of 12 slow runs on one unit, "
             r"price = about \$5 for the drive without a motor, no labour.", color=INK2, fontsize=9)
    fig.tight_layout(rect=(0, 0.03, 1, 1))
    fig.savefig(os.path.join(OUT, "cots_price_vs_backlash.png"), dpi=DPI)
    print("written", os.path.join(OUT, "cots_price_vs_backlash.png"))


if __name__ == "__main__":
    main()
