Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
7469f8f
ui: expand stable graph onto a larger virtual canvas
Chychyndr Sep 26, 2026
ef7f98d
ui: keep camera stable when a hero is selected
Chychyndr Sep 26, 2026
429b91d
ui: make hero names and win rates use fixed graph geometry
Chychyndr Sep 26, 2026
34e3817
ui: render every highlighted relationship as one straight line
Chychyndr Sep 26, 2026
0f86085
data: spread heroes across the organic global canvas
Chychyndr Sep 26, 2026
5c638bd
test: expect the larger organic virtual canvas
Chychyndr Sep 26, 2026
01bb8c5
test: raise spacing gates for the organic global layout
Chychyndr Sep 26, 2026
a750bf7
ui: match reference emphasis and stable label layering
Chychyndr Sep 26, 2026
ed31f74
ui: strengthen selected hero and label emphasis
Chychyndr Sep 26, 2026
399b269
ui: reframe the same global layout only on compact screens
Chychyndr Sep 26, 2026
9bac4d5
ui: spread fixed win-rate pills toward outer endpoints
Chychyndr Sep 26, 2026
f2d08be
test: enforce one stable global focus layout
Chychyndr Sep 26, 2026
0ff337a
ui: keep selected hero clear of the desktop card
Chychyndr Sep 26, 2026
53827c8
ui: add portrait masks over relationship lines
Chychyndr Sep 26, 2026
90627ee
ui: hide straight edges beneath hero portraits
Chychyndr Sep 26, 2026
a63b4c9
ui: clear dimmed background nodes from active lanes
Chychyndr Sep 26, 2026
37c0690
ui: suppress background portraits that block focus links
Chychyndr Sep 26, 2026
55c03ae
test: capture owner reference heroes on the global layout
Chychyndr Sep 26, 2026
57eafb9
test: audit visual edge occlusion instead of hidden geometry
Chychyndr Sep 26, 2026
d562ebe
ui: anchor hero names on each node's stable open side
Chychyndr Sep 26, 2026
223cb5b
ui: keep compact win-rate pills on-screen and on-line
Chychyndr Sep 26, 2026
003f12a
ui: place hero card opposite the selected node
Chychyndr Sep 26, 2026
300f529
ui: support opposite-side desktop hero card
Chychyndr Sep 26, 2026
aa4372e
ui: keep desktop camera unchanged on hero selection
Chychyndr Sep 26, 2026
36393c1
ui: keep win-rate pills on clear deterministic line slots
Chychyndr Sep 26, 2026
8a0c557
test: accept deterministic on-line win-rate slots
Chychyndr Sep 26, 2026
a7f0733
ui: widen fixed line slots and compact focus padding
Chychyndr Sep 26, 2026
79131a1
test: enforce deterministic bounded line slots
Chychyndr Sep 26, 2026
e13b7e1
ui: choose least-obstructed fixed win-rate slot
Chychyndr Sep 26, 2026
1dfb461
ui: anchor names against each hero's strongest global links
Chychyndr Sep 26, 2026
afc275c
ui: keep win-rate pills clear of fixed hero names
Chychyndr Sep 26, 2026
854b286
ui: anchor fixed names away from incident edges
Chychyndr Sep 26, 2026
cab1a50
ui: place fixed names in stable open graph sectors
Chychyndr Sep 26, 2026
e2e3cfc
fix: keep the full global graph visible in focus
Chychyndr Sep 26, 2026
136d91b
style: preserve dimmed heroes under active edges
Chychyndr Sep 26, 2026
5487383
test: allow organic hero label directions
Chychyndr Sep 26, 2026
5a27348
test: capture Claude graph reference for visual parity
Chychyndr Sep 26, 2026
85c1705
fix: keep win-rate badges clear of every portrait
Chychyndr Sep 26, 2026
f4997a1
test: remove temporary Claude capture
Chychyndr Sep 26, 2026
aeecfc9
fix: search win-rate badge positions at fine resolution
Chychyndr Sep 26, 2026
3a22658
test: accept fine on-edge badge placement
Chychyndr Sep 26, 2026
e54d977
style: mask active edges behind every hero portrait
Chychyndr Sep 26, 2026
50c0400
test: audit stable direct focus geometry for every hero
Chychyndr Sep 26, 2026
b2262eb
fix: fit win-rate badges into dense straight-edge gaps
Chychyndr Sep 26, 2026
d89d7f5
test: cover full safe badge range on straight edges
Chychyndr Sep 26, 2026
660b71e
fix: solve straight-edge win-rate badges globally
Chychyndr Sep 26, 2026
588e154
test: assert visual badge constraints instead of sampling grid
Chychyndr Sep 26, 2026
30e87c9
feat: allow edge labels to ignore their own endpoint obstacles
Chychyndr Sep 26, 2026
8570b43
fix: free badge space near each relationship endpoint
Chychyndr Sep 26, 2026
873c8e4
test: cover per-edge endpoint obstacle exclusions
Chychyndr Sep 26, 2026
9de2e9a
fix: keep dense edge badges visible and separated
Chychyndr Sep 26, 2026
771cc44
fix: keep every relationship present before focus
Chychyndr Sep 26, 2026
9de97d7
test: prove focus only emphasizes existing edges
Chychyndr Sep 26, 2026
9f0cf21
docs: lock the one-graph Claude interaction model
Chychyndr Sep 26, 2026
e8e4b8d
docs: describe stable full-edge focus behavior
Chychyndr Sep 26, 2026
2d05e2f
docs: document persistent relationship geometry
Chychyndr Sep 26, 2026
3f18ab6
fix: preload every focus-eligible relationship
Chychyndr Sep 26, 2026
2a1e0fc
fix: keep edge badges clear of graph content
Chychyndr Sep 26, 2026
cc517a1
fix: give straight edge badges usable inline clearance
Chychyndr Sep 26, 2026
e314500
test: expect the persistent focus edge set in overview
Chychyndr Sep 26, 2026
da22f7f
test: wait for focused labels before geometry audit
Chychyndr Sep 26, 2026
0647cdc
fix: add a last inline badge scale before dropping labels
Chychyndr Sep 26, 2026
538cba6
docs: define the persistent focus-edge union
Chychyndr Sep 26, 2026
c243328
docs: clarify overview edge scope
Chychyndr Sep 26, 2026
18e6177
docs: scope the persistent graph to focus-eligible edges
Chychyndr Sep 26, 2026
8d2002c
ui: mark the persistent graph focus state
Chychyndr Sep 26, 2026
31cbe1d
style: quiet the persistent edge web behind focus
Chychyndr Sep 26, 2026
9283159
test: lock the persistent edge set for every hero
Chychyndr Sep 26, 2026
f44c417
refactor: remove obsolete overlay visibility helpers
Chychyndr Sep 26, 2026
f35f7d1
test: remove obsolete sparse visibility cases
Chychyndr Sep 26, 2026
8ee769d
fix: preserve node and edge geometry in focus
Chychyndr Sep 26, 2026
28631b9
test: lock focus to the overview geometry
Chychyndr Sep 26, 2026
256fd9e
test: audit immutable geometry for every hero
Chychyndr Sep 26, 2026
175c14b
docs: record Claude parity requirement for graph work
Chychyndr Sep 26, 2026
dd21b8f
docs: forbid desktop focus camera shifts
Chychyndr Sep 26, 2026
23d4109
docs: lock desktop focus camera
Chychyndr Sep 26, 2026
5670c67
docs: document immutable desktop camera
Chychyndr Sep 26, 2026
c05b64d
fix: align layout edges with focus relationships
Chychyndr Sep 26, 2026
e3ef43c
test: lock layout to focus edge semantics
Chychyndr Sep 26, 2026
b32b98c
fix: use published ranking for layout neighbors
Chychyndr Sep 26, 2026
fdab7d8
feat: clear active lines away from foreign heroes
Chychyndr Sep 26, 2026
23a5fe7
test: cover straight-edge portrait clearance
Chychyndr Sep 26, 2026
e16fc6c
fix: prioritize local focus neighborhoods in layout
Chychyndr Sep 26, 2026
b91fdb4
test: keep clearance focused on real crossings
Chychyndr Sep 26, 2026
3a11e54
fix: limit clearance to true line-through-node cases
Chychyndr Sep 26, 2026
1fb52b7
test: match minimal line clearance contract
Chychyndr Sep 26, 2026
805f8d9
refactor: keep one stable relationship order
Chychyndr Sep 26, 2026
178fd5f
data: regenerate focus-aware hero layout
Chychyndr Sep 26, 2026
838a2a0
fix: settle focus graph before visual cleanup
Chychyndr Sep 26, 2026
f7aa4d9
data: settle focus-aware hero neighborhoods
Chychyndr Sep 26, 2026
1507b4f
test: allow organic hull breathing room
Chychyndr Sep 26, 2026
798b991
style: quiet persistent background relationships
Chychyndr Sep 26, 2026
652aacd
fix: keep visible hero labels separated
Chychyndr Sep 26, 2026
180907b
test: audit hero label collisions in every focus
Chychyndr Sep 26, 2026
2c22fea
docs: describe focus-aware organic layout pipeline
Chychyndr Sep 26, 2026
50fff9a
fix: give crowded hero labels more breathing room
Chychyndr Sep 26, 2026
b5b9ab7
test: capture Pudge label regression screenshot
Chychyndr Sep 26, 2026
1a81762
docs: distinguish layout edges from rendered graph
Chychyndr Sep 26, 2026
15445ec
fix: reduce background edge fog
Chychyndr Sep 26, 2026
f792902
fix: penalize long focus edges during layout
Chychyndr Sep 26, 2026
82ea979
data: regenerate long-edge-aware layout
Chychyndr Sep 26, 2026
db01317
revert: drop regressive long-edge boost
Chychyndr Sep 26, 2026
2054de9
revert: restore verified focus-aware snapshot
Chychyndr Sep 26, 2026
7f2ce16
fix: keep global graph context visible in focus
Chychyndr Sep 26, 2026
87a7eb9
fix: lighten dense active edge fans
Chychyndr Sep 26, 2026
8a4af9c
fix: avoid poor deterministic layout basin
Chychyndr Sep 26, 2026
3ea5c05
data: regenerate alternate deterministic layout seed
Chychyndr Sep 26, 2026
1c662c3
fix: keep emergency win-rate pills readable
Chychyndr Sep 26, 2026
f434056
fix: keep desktop win-rate pills at readable size
Chychyndr Sep 26, 2026
a985550
revert: restore verified compact pill fallback
Chychyndr Sep 26, 2026
765dbe6
fix: keep desktop win-rate text readable when pill shrinks
Chychyndr Sep 26, 2026
eddfc76
test: forbid hero labels peeking under context card
Chychyndr Sep 26, 2026
1a544c6
fix: hide labels fully covered by context card
Chychyndr Sep 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ https://www.figma.com/design/rydgq1wV8C0hlVb5n7Ohws/DotaGraph-Design?node-id=1-2
Interaction reference:
https://claude.ai/public/artifacts/ddbdfd38-f9ac-4261-a764-cdbac4e405ec

The Claude artifact is an interaction reference, not a pixel-perfect target.
For issue #120 / PR #121 graph-layout work, the owner explicitly requires reproducing the Claude artifact interaction model and approved screenshots as closely as possible before adding DotaGraph-specific improvements. In that scope, do not reinterpret the reference into a rigid Focus layout or a second graph: the same pre-positioned heroes and straight relationship geometry stay in place, and selection only changes emphasis plus contextual labels/cards.

Never use generative-image output as final hero art, item art, UI icons, screenshots, or product assets. Use lawful real assets with explicit provenance.

Expand Down Expand Up @@ -293,7 +293,7 @@ The overview must not randomly reorganize on every page load.

Prefer deterministic/precomputed positions, seeded layout, or cached stable positions generated as part of the data build.

Hover and Focus must not relayout the graph. Hero coordinates are the committed Overview coordinates in every interaction state. On desktop, hero selection keeps the Overview camera scale and anchor; a small translation may make room for the HeroCard, but selection must not recenter or rezoom around a new focus layout. Compact viewports may reframe the same graph when needed for the card.
Hover and Focus must not relayout the graph. Hero coordinates are the committed Overview coordinates in every interaction state. On desktop, hero selection keeps the exact Overview camera transform: no recentering, rezooming, or translation to make room for HeroCard. Compact viewports may reframe the same committed graph when needed for the card.

## URL state

Expand Down
8 changes: 4 additions & 4 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ The stable hero field should use the graph canvas generously. Keep the topology

## Interaction

Overview keeps the whole graph as a weak spiderweb.
Overview keeps one persistent focus-eligible relationship graph present as a weak spiderweb. It is the union of every relationship that can become one of a hero's highlighted incoming/outgoing Focus edges, so every line that may be emphasized later already exists in Overview at the same endpoints.

Hover reveals only local context and never relayouts the graph.
Hover reveals local context only by changing emphasis and never relayouts or inserts relationship geometry.

Focus preserves the exact Overview graph layout. All heroes remain at their committed positions; unrelated heroes become subdued, while incoming and outgoing relationships and their endpoint heroes are emphasized in place. Focus must never construct or overlay a second arrangement of the same heroes. On desktop the Overview camera keeps the same scale and anchor when a hero is selected; the graph may translate slightly to make room for the HeroCard. Compact viewports may reframe the same graph only when needed to keep the selected hero usable with the context card.
Focus preserves the exact Overview graph layout and edge set. All heroes remain at their committed positions; unrelated heroes become subdued, while incoming and outgoing relationships and their endpoint heroes are emphasized in place. Selecting a hero must never insert replacement lines, construct an overlay graph, or move endpoints. On desktop the Overview camera keeps the same scale and anchor when a hero is selected. Compact viewports may reframe the same graph only when needed to keep the selected hero usable with the context card.

Selecting or leaving a hero moves the camera with a short eased transition. Manual drag or wheel input immediately takes control and cancels that camera animation.

Expand All @@ -51,7 +51,7 @@ Matchup keeps the graph visible, emphasizes one pair, and changes the compact ca

The percentage belongs to the source hero of the arrow.

The accepted current behavior is source-anchored, collision-aware placement on the active edge itself. Labels normally stay on the source half of the edge; when the selected hero is the source, the badge may sit farther down that half so dense outgoing fans remain readable. On short fixed-layout edges, the badge may scale down to stay on the line without covering a portrait. If the gap is still physically too short, the full badge moves onto a short collinear continuation of that same relationship. Source-side continuation is preferred; target-side continuation is allowed when the source-side ray conflicts with another active relationship or badge. Hero names use collision-aware placement outside active relationship paths and render on an opaque canvas backing.
The accepted current behavior is source-anchored, collision-aware placement on the active straight edge itself. Labels normally stay nearer the source side; when the selected hero is the source, the badge may slide farther along the same segment so dense outgoing fans remain readable. On short fixed-layout edges, the badge may scale down. The badge center must remain on its own source-to-target segment; it must never detach onto a leader, continuation, bend, or overlay route. Hero names use deterministic anchors around their committed node and render on an opaque canvas backing.

## Product chrome decisions

Expand Down
19 changes: 10 additions & 9 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,20 @@ Hero coordinates are generated offline from real current-patch matchup observati

The layout build:
- reads the canonical hero catalog;
- derives primary affinity candidates from current-patch OpenDota pair observations with the normal 500-match sample floor but without the one-sided 95% headline confidence penalty;
- keeps up to five strongest real incident affinities per hero;
- when a rare hero would otherwise have fewer than two geometry neighbors, may use geometry-only current-patch observations down to the explicit 100-match fallback floor;
- starts from the same published current-patch relationships and ranking order used by the frontend, including the normal sample floor and one-sided 95% confidence ranking;
- selects up to five strongest incoming and five strongest outgoing Focus relationships for every hero, then lays out the union of those focus-eligible edges;
- when a rare hero would otherwise have fewer than two geometry neighbors, may use geometry-only current-patch observations down to the explicit fallback sample floor;
- never publishes those geometry-only fallback edges as counters or uses them to change displayed percentages;
- runs a deterministic force-directed solver;
- pulls low-degree heroes toward the centroid of their real affinity neighbors so they do not become detached hull islands;
- performs deterministic collision relaxation with a 58 px minimum center distance;
- applies a final uniform presentation-spread pass, capped at 1.18×, so the stable topology uses more of the 1200×760 graph canvas without changing relative angles;
- runs a deterministic 700-iteration force-directed solver with stronger local attraction so Focus neighbors form natural neighborhoods without rows, columns, or a selected-hero scaffold;
- only pulls genuinely sparse degree-0/1 heroes toward nearby graph structure; normally connected heroes keep their real relationship topology;
- performs deterministic portrait collision relaxation with a 58 px minimum center distance;
- applies a tiny deterministic straight-edge clearance nudge only to true line-through-node cases, followed by another collision settle;
- applies a final uniform presentation-spread pass, capped at 1.50× into the larger virtual canvas, without changing the topology or relative angles;
- writes fixed coordinates plus spacing, isolation, and edge-distance quality metrics.

The browser never runs a force simulation. Overview, Hover, Focus, and Matchup all use the same committed stable hero coordinates after that spread pass. Desktop Focus keeps the Overview camera scale and anchor as well as the node positions; it may apply only a small translation to make room for the context card. Compact Focus may reframe that same coordinate system for the context card. No interaction state derives a second set of node positions.
The browser never runs a force simulation. Overview, Hover, Focus, and Matchup all use the same committed stable hero coordinates after that spread pass. Desktop Focus keeps the exact Overview camera transform as well as the node positions; it does not translate, recenter, or rezoom for the context card. Compact Focus may reframe that same coordinate system for the context card. No interaction state derives a second set of node positions.

The SVG renderer keeps display density separate from the full production relationship corpus. Overview renders a sparse deterministic backbone. Focus keeps that backbone as low-contrast context and adds the selected hero's real active edges (up to five incoming and five outgoing), while unrelated heroes are dimmed in place. This preserves one continuous graph throughout the interaction without changing counter semantics.
The SVG renderer keeps one persistent published relationship graph in the DOM. Overview renders every published relationship at very low contrast, while the offline force solver uses the smaller 1029-edge union that can actually become active in Focus to determine useful local neighborhoods. Hover and Focus only change emphasis on already-rendered straight lines; selecting a hero never inserts a second edge set, substitutes endpoints, or creates a focus overlay. Up to five incoming and five outgoing relationships become prominent while unrelated heroes are dimmed in place. Lower-ranked published pairs remain part of the weak background web even when they cannot enter the current Focus limit. This preserves one continuous graph throughout the interaction without changing counter semantics.

Changing layout parameters must not change what `A -> B` means, alter the user-visible source win rate, or promote geometry-only evidence into the headline counter set.

Expand Down
12 changes: 6 additions & 6 deletions docs/UX_STATES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Overview

- All validated current-patch heroes are visible.
- A sparse deterministic relationship backbone gives graph structure without rendering the full production relationship corpus.
- The persistent Focus-eligible edge union is already present as a low-contrast spiderweb; every edge that can become one of a hero's highlighted incoming/outgoing relationships exists before selection, and Focus never inserts new relationship geometry.
- The initial camera fits and centers the actual hero bounds instead of assuming the fixed canvas center.
- No win-rate labels.
- Search remains visible.
Expand All @@ -17,27 +17,27 @@

- Hovered node grows slightly.
- Hero name appears in a dedicated top label layer so nearby portrait nodes cannot cover it.
- Local edges gain contrast while the sparse Overview backbone stays low-contrast.
- Local edges gain contrast while the same complete Overview edge set stays low-contrast.
- Hero coordinates and the rest of the Overview graph stay in place.
- No large panel opens.
- No relayout.

## Focus

- Desktop Focus keeps the Overview camera scale and anchor; selecting a hero may translate the same graph slightly to make room for HeroCard, but does not recenter or rezoom it.
- Desktop Focus keeps the exact Overview camera transform. Selecting a hero does not translate, recenter, or rezoom the graph for HeroCard.
- Compact Focus may reframe the same committed graph coordinates to keep the selected hero usable above the context card.
- No viewport mode creates a second focus topology.
- Gold ring.
- The same Overview hero nodes remain visible at the same committed coordinates.
- Unrelated heroes are dimmed in place; active relationship heroes are emphasized where they already live in the graph.
- The sparse Overview backbone remains as low-contrast context.
- The exact Overview edge set remains as low-contrast context; Focus only changes classes/emphasis on existing lines.
- Up to five incoming relationships in coral.
- Up to five outgoing relationships in cyan.
- Hero names sit outside active relationship paths, stay clear of the desktop HeroCard, and have an opaque canvas backing so edges cannot visually cut through the text.
- Tiny arrowheads clarify direction.
- Win-rate pills remain attached to their relationship line whenever the fixed geometry has enough room. A cramped edge may use a smaller pill or a short collinear continuation. The source side is preferred; the target side is allowed when the source-side ray would conflict with another active relationship or badge.
- Win-rate pills remain centered on their own straight relationship segment. A cramped edge may use a smaller pill or slide farther along that same segment, but it never detaches onto a continuation or leader.
- Win-rate pills must not overlap any visible hero-name label or visible hero portrait.
- Active relationship lines must not cross unrelated active hero portraits; blocked straight segments must use deterministic collision-free routing.
- Active relationship lines stay straight source-to-target segments. Node masks interrupt the visible stroke under unrelated portraits so the renderer never reroutes the relationship into bends or alternate geometry.
- Focus never creates a second node arrangement or moves heroes into a separate ring/arc layout.
- The HeroCard section headings do not show “x/5” counters.
- HeroCard appears.
Expand Down
81 changes: 41 additions & 40 deletions pipeline/dotagraph_pipeline/generate_current_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,43 +392,54 @@ def _normalize_immortal_pairs(
]


def _relationship_sort_key(
item: RankedRelationship,
) -> tuple[float, float, int, str, str]:
return (
-item.ranking_score,
-item.baseline_adjusted_delta,
-item.sample_size,
item.source,
item.target,
)


def _select_layout_relationships(
ranked: list[RankedRelationship],
*,
neighbors_per_hero: int = 5,
) -> list[RankedRelationship]:
incident: dict[str, list[RankedRelationship]] = {}
"""Select exactly the relationship union that can become active in Focus.

The UI ranks incoming and outgoing relationships independently and can show
up to maxVisiblePerDirection from each side. The offline layout must use the
same candidate union; otherwise a line can become prominent even though its
endpoints never attracted each other during layout generation.
"""

incoming: dict[str, list[RankedRelationship]] = {}
outgoing: dict[str, list[RankedRelationship]] = {}

for relationship in ranked:
incident.setdefault(relationship.source, []).append(relationship)
incident.setdefault(relationship.target, []).append(relationship)
outgoing.setdefault(relationship.source, []).append(relationship)
incoming.setdefault(relationship.target, []).append(relationship)

selected: dict[tuple[str, str], RankedRelationship] = {}
limit = max(1, neighbors_per_hero)
hero_slugs = sorted(set(incoming) | set(outgoing))

for hero_slug in sorted(incident):
relationships = sorted(
incident[hero_slug],
key=lambda item: (
-item.baseline_adjusted_delta,
-item.sample_size,
item.source,
item.target,
),
)
for relationship in relationships[:limit]:
pair_key = tuple(sorted((relationship.source, relationship.target)))
selected[pair_key] = relationship

return sorted(
selected.values(),
key=lambda item: (
-item.baseline_adjusted_delta,
-item.sample_size,
item.source,
item.target,
),
)
for hero_slug in hero_slugs:
for relationships in (
outgoing.get(hero_slug, []),
incoming.get(hero_slug, []),
):
for relationship in sorted(
relationships,
key=_relationship_sort_key,
)[:limit]:
selected[(relationship.source, relationship.target)] = relationship

return sorted(selected.values(), key=_relationship_sort_key)


def _ensure_layout_neighbors(
Expand Down Expand Up @@ -479,15 +490,7 @@ def _ensure_layout_neighbors(
if degrees.get(hero_slug, 0) >= minimum_neighbors:
break

return sorted(
selected_by_pair.values(),
key=lambda item: (
-item.baseline_adjusted_delta,
-item.sample_size,
item.source,
item.target,
),
)
return sorted(selected_by_pair.values(), key=_relationship_sort_key)


def _layout_edges(
Expand Down Expand Up @@ -553,12 +556,10 @@ def generate(
pairs,
minimum_sample=CURRENT_SCOPE.minimum_sample,
)
layout_candidates = rank_relationships(
pairs,
minimum_sample=CURRENT_SCOPE.minimum_sample,
confidence_z=0.0,
layout_relationships = _select_layout_relationships(
ranked,
neighbors_per_hero=CURRENT_SCOPE.max_visible_per_direction,
)
layout_relationships = _select_layout_relationships(layout_candidates)
layout_fallback_candidates = rank_relationships(
pairs,
minimum_sample=CURRENT_SCOPE.layout_fallback_minimum_sample,
Expand Down
Loading
Loading