Graph under filter (weight class: light heavyweight · era: all eras · min bouts: 5): 105 nodes · 405 edges drawn from 740 in-filter fights. Source: VM4 4.6 gold dataset (ufc_gold_dataset_final.csv) joined with canonical_fighter_ids.json (Data lane v1.1) for the per-fighter display name, nickname, and ufcstats_id.
Eligibility rule: a fighter becomes a node iff they have at least 5 in-filter bouts (each W / L / Draw counts; NC / Overturned / DQ rows are dropped upstream via classifyMethodForEra). Edge construction: one row per in-filter fight between two eligible fighters; trilogies / rematches fold into a single edge whose `count` carries the bout total. Edge color: red shaded toward the dominant fighter when one side won ≥60% of the decisive bouts (draws excluded from the share); muted neutral when the split is closer or every meeting drew.
Node color: red when the fighter’s most recent in-filter fight is within 24 months of the dataset’s latest fight date (reference: 2026-05-16); muted grey otherwise. The reference date is the dataset’s most recent fight (not today) so the “active” set is frozen with the data — a re-run on the same snapshot always produces the same coloring. Node radius: clamp(6 + √wins, 6, 20) px. Square-root softens the curve so an 8-win and a 15-win fighter are visually distinct without dwarfing the rest; the upper clamp keeps a 25+ win all-timer from crowding the canvas.
Layout: Fruchterman-Reingold force-directed algorithm (FR91). Pairwise repulsion + per-edge attraction + temperature decay. Iterations: 100 . Initial temperature: 72.0 px . Decay per iteration: 0.95 . Ideal edge length K: 45.9 px (computed as √(area / n) × 0.7 over the 720×720 canvas inner area). Layout is computed server-side using a mulberry32 PRNG seeded by the “lhw-all-5” filter tuple — the same filter always produces the same positions, no client-side animation, no Math.random.
Dropped fights by reason: unparseable Event_Date = 0 · era filter = 0 · weight-class filter = 7,963 · NC / Overturned / DQ method = 16 · missing canonical (either fighter unmapped) = 0 · fighters below min-bouts threshold = 185. Title-bout edge thickening is currently disabled — the gold-dataset Method field does not carry a reliable title flag, so every edge renders at the base stroke width. Wiring this up requires a per-fight `Title_Bout` column we don’t yet have; documented as a known limitation.
Honest framing: the graph is a descriptive map of who shared a cage with whom under the active filter. No causal claim is implied — dense edge clusters reflect roster turnover and matchmaking patterns (champions and contenders fight each other repeatedly), not “skill clusters”. Edge dominance is a raw count of in-filter wins, not a quality adjustment. Hover tooltips show canonical record + 3 most recent in-filter fights; missing nickname renders as “—” rather than fabricated text. Click any node to open the fighter profile at /fighter/<slug>.