@@ -14,35 +14,42 @@ def __init__(self, graph):
1414 js += f'numWinners = { graph .summarize ().numWinners } ;\n '
1515 js += f'longestLabelApxWidth = { longestLabelApxWidth } ;\n '
1616 js += f'totalVotesPerRound = { totalVotesPerRound } ;\n '
17- js += 'graph = {"nodes" : [], "links" : []};\n '
18-
19- # Maps Candidates to a unique index. Used for color indexing.
20- indices = {candidate : i for i , candidate in enumerate (graph .eliminationOrder )}
17+ # Maps Candidates to a single char key (a-z) ordered by elimination order.
18+ # Position in charMap doubles as the color index. Supports up to 26 candidates.
19+ elimination_order = list (graph .eliminationOrder )
20+ candidate_to_char = {c : chr (ord ('a' ) + i ) for i , c in enumerate (elimination_order )}
21+ char_map = {chr (ord ('a' ) + i ): c .name for i , c in enumerate (elimination_order )}
2122
2223 nodeIndices = {}
23- for i , node in enumerate (graph .nodes ):
24+ nodes = []
25+ for node in graph .nodes :
2426 # Skip inactive (exhausted) nodes
2527 if not node .candidate .isActive :
2628 continue
2729
28- nodeIndices [node ] = i
29- js += f'graph.nodes.push({{ "name": { json .dumps (node .label )} ,\n '
30- js += f' "round": { node .roundNum } ,\n '
31- js += f' "value": { node .count } ,\n '
32- js += f' "isWinner": { int (node .isWinner )} ,\n '
33- js += f' "isEliminated": { int (node .isEliminated )} ,\n '
34- js += f' "index": "{ indices [node .candidate ]} "}});\n '
30+ nodeIndices [node ] = len (nodes )
31+ nodes .append ([
32+ candidate_to_char [node .candidate ],
33+ node .roundNum ,
34+ node .count ,
35+ int (node .isWinner ),
36+ int (node .isEliminated ),
37+ ])
38+
39+ links = []
3540 for link in graph .links :
3641 # Skip inactive (exhausted) nodes
3742 if not link .source .candidate .isActive :
3843 continue
3944 if not link .target .candidate .isActive :
4045 continue
4146
42- sourceIndex = nodeIndices [link .source ]
43- targetIndex = nodeIndices [link .target ]
44- js += f'graph.links.push({{ "source": { sourceIndex } ,\n '
45- js += f' "target": { targetIndex } ,\n '
46- js += f' "candidateIndex": { indices [link .source .candidate ]} ,\n '
47- js += f' "value": { link .value :0.3f} }});\n '
47+ links .append ([
48+ nodeIndices [link .source ],
49+ nodeIndices [link .target ],
50+ round (link .value , 3 ),
51+ ])
52+
53+ js += f'charMap = { json .dumps (char_map )} ;\n '
54+ js += f'graphCompressed = { json .dumps ({"nodes" : nodes , "links" : links })} ;\n '
4855 self .js = js
0 commit comments