"""f01_eos_role -- concept map: EOS box in the centre, arrows out to the six
uses (molar density/volume, residual H and S, fugacity coefficient, VLE /
K-values, process simulation, safety & metering). Pure schematic built from
matplotlib primitives; no computed data (data-integrity rule: exempt as a
concept map, no curves are drawn).
"""
import sys
sys.path.insert(0, "/home/claude/eos_lecture/code")
from eosstyle import *
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch

fig, ax = blank(9.0, 6.2)

def box(cx, cy, w, h, text, fc=PAPER, ec=GRAPHITE, tc=INK, fs=10.5, lw=1.2, weight="normal"):
    b = FancyBboxPatch((cx - w/2, cy - h/2), w, h,
                        boxstyle="round,pad=0.012,rounding_size=0.018",
                        linewidth=lw, edgecolor=ec, facecolor=fc, zorder=3)
    ax.add_patch(b)
    ax.text(cx, cy, text, ha="center", va="center", fontsize=fs, color=tc,
             zorder=4, weight=weight, linespacing=1.35)
    return b

def arrow(p0, p1, color=GRAPHITE, lw=1.5, style="-|>"):
    a = FancyArrowPatch(p0, p1, arrowstyle=style, mutation_scale=13,
                         linewidth=lw, color=color, zorder=2,
                         shrinkA=2, shrinkB=2, connectionstyle="arc3,rad=0.0")
    ax.add_patch(a)

# central EOS box
cx, cy = 0.5, 0.52
box(cx, cy, 0.20, 0.135, "Equation of\nState\nP(T,V,n)", fc=NAVY, tc="white", fs=12, weight="bold")

# six satellite boxes arranged around the centre, generous spacing
satellites = [
    (0.14, 0.80, "Molar density /\nmolar volume\n" + r"$V=Z\,RT/P$"),
    (0.50, 0.80, "Residual enthalpy\nand entropy\n" + r"$H^{res},\,S^{res}$"),
    (0.86, 0.80, "Fugacity\ncoefficient " + r"$\varphi_i$"),
    (0.86, 0.20, "VLE and\nK-values\n" + r"$K_i=y_i/x_i$"),
    (0.50, 0.20, "Process simulation\n(flowsheet models)"),
    (0.14, 0.20, "Safety and metering\n(relief, custody transfer)"),
]
labels_sub = [
    None,
    None,
    None,
    None,
    "compressors  \xb7  flash drums  \xb7  pipelines",
    None,
]

for (sx, sy, txt), sub in zip(satellites, labels_sub):
    box(sx, sy, 0.235, 0.13, txt, fc="#F4F6F7", ec=GRAPHITE, tc=INK, fs=9.7)
    if sub:
        ax.text(sx, sy - 0.115, sub, ha="center", va="top", fontsize=10.5, color=SLATE)

# arrows from centre to each satellite, stopping at box edges
import numpy as np
for sx, sy, _ in satellites:
    dx, dy = sx - cx, sy - cy
    n = np.hypot(dx, dy)
    ux, uy = dx/n, dy/n
    p0 = (cx + ux*0.115, cy + uy*0.078)
    p1 = (sx - ux*0.13, sy - uy*0.085)
    arrow(p0, p1, color=GRAPHITE, lw=1.5)

ax.text(0.5, 1.0, "The equation of state as the closure relation of process thermodynamics",
        ha="center", va="top", fontsize=12.5, color=NAVY, weight="bold")

save(fig, "f01_eos_role")
