Skip to content

Commit 171d835

Browse files
committed
Enhance graph visualizer to map items, stats, and abilities for a complete content journey
1 parent 2b24390 commit 171d835

2 files changed

Lines changed: 82 additions & 39 deletions

File tree

scripts/export_graph_mermaid.py

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -10,60 +10,97 @@ def load_graph():
1010

1111
def generate_mermaid():
1212
nodes = load_graph()
13+
1314
lines = ["graph TD"]
1415

15-
# Define styles
16+
# Define styles with better contrast
1617
lines.append("classDef quest fill:#4b0082,stroke:#f9f,stroke-width:2px,color:#fff;")
1718
lines.append("classDef location fill:#00008b,stroke:#ccf,stroke-width:2px,color:#fff;")
1819
lines.append("classDef cadence fill:#006400,stroke:#cfc,stroke-width:2px,color:#fff;")
20+
lines.append("classDef item fill:#444,stroke:#fff,stroke-width:1px,color:#fff;")
21+
lines.append("classDef stat fill:#8b4513,stroke:#ff8c00,stroke-width:1px,color:#fff;")
22+
lines.append("classDef ability fill:#2f4f4f,stroke:#00ced1,stroke-width:1px,color:#fff;")
1923
lines.append("classDef root fill:#8b8b00,stroke:#ff9,stroke-width:4px,color:#fff;")
2024

21-
# Filter for significant nodes to avoid clutter
22-
# Focus on Quests, Locations, Cadences
23-
significant_types = ["Quest", "Location", "Cadence"]
24-
sig_nodes = {n["id"]: n for n in nodes if n["type"] in significant_types}
25-
26-
for nid, node in sig_nodes.items():
27-
# Node Label
28-
name = node["name"].replace('"', "'")
29-
style = ""
25+
# We want to show almost everything now
26+
# Filter out some very common ones if they make it too noisy,
27+
# but for now let's include all for a "Complete Map"
28+
29+
for node in nodes:
30+
nid = node["id"]
31+
ntype = node["type"]
32+
name = node["name"]
3033

31-
if node["name"] == "Prologue":
32-
style = ":::root"
33-
elif node["type"] == "Quest":
34-
style = ":::quest"
35-
elif node["type"] == "Location":
36-
style = ":::location"
37-
elif node["type"] == "Cadence":
38-
style = ":::cadence"
34+
# 1. Define Node
35+
style = ntype.lower()
36+
if nid == "quest_prologue":
37+
style = "root"
38+
39+
# Shorten some names for the graph
40+
display_name = name.replace('"', "'")
41+
lines.append(f'{nid}["{display_name}"]:::{style}')
3942

40-
lines.append(f'{nid}["{name}"]{style}')
43+
# 2. In-Edges (Requirements)
44+
in_edges = node.get("in_edges", {})
45+
46+
# Quest Requirements
47+
if "requires_quest" in in_edges:
48+
for req_id in in_edges["requires_quest"]:
49+
# If Location requires Quest, it's an "Enables" link
50+
if ntype == "Location":
51+
lines.append(f"{req_id} -->|Enables| {nid}")
52+
else:
53+
lines.append(f"{req_id} -->|Requires| {nid}")
54+
55+
# Ability Requirements (for Refinements usually)
56+
if "requires_ability" in in_edges:
57+
for req_id in in_edges["requires_ability"]:
58+
lines.append(f"{req_id} -.->|Allows| {nid}")
59+
60+
# Stat Requirements
61+
if "requires_stat" in in_edges:
62+
for stat_name, val in in_edges["requires_stat"].items():
63+
stat_id = f"stat_{stat_name.lower()}"
64+
lines.append(f"{stat_id} -.->|Requires {val}| {nid}")
4165

42-
# 2. Location Unlocks (Quest -> Location)
43-
if "unlocks_location" in node["out_edges"]:
44-
for edge in node["out_edges"]["unlocks_location"]:
45-
target_id = edge["targetId"]
46-
if target_id in sig_nodes:
66+
# 3. Out-Edges (Unlocks / Rewards / Productions)
67+
out_edges = node.get("out_edges", {})
68+
69+
# Cadence/Ability Unlocks
70+
for unlock_type in ["unlocks_cadence", "unlocks_ability", "provides_ability"]:
71+
if unlock_type in out_edges:
72+
for edge in out_edges[unlock_type]:
73+
target_id = edge["targetId"]
4774
lines.append(f"{nid} ==>|Unlocks| {target_id}")
75+
76+
# Location Unlocks (explicit)
77+
if "unlocks_location" in out_edges:
78+
for edge in out_edges["unlocks_location"]:
79+
target_id = edge["targetId"]
80+
lines.append(f"{nid} ==>|Unlocks| {target_id}")
4881

49-
# 3. Requirements (Location -> Quest)
50-
if "requires_quest" in node["in_edges"]:
51-
for req_id in node["in_edges"]["requires_quest"]:
52-
if req_id in sig_nodes:
53-
# Avoid duplicate edges with 'requires_quest' which is also on Quest nodes.
54-
if node["type"] == "Location":
55-
lines.append(f"{req_id} -->|Enables| {nid}")
56-
elif node["type"] == "Quest":
57-
lines.append(f"{req_id} -->|Requires| {nid}")
82+
# Item Rewards / Production
83+
for reward_type in ["rewards", "produces", "rewards_item"]:
84+
if reward_type in out_edges:
85+
for edge in out_edges[reward_type]:
86+
target_id = edge["targetId"]
87+
qty = edge.get("quantity", 1)
88+
lines.append(f"{nid} --o|Gives {qty}| {target_id}")
5889

59-
# 4. Cadence Unlocks (Quest -> Cadence)
60-
if "unlocks_cadence" in node["out_edges"]:
61-
for edge in node["out_edges"]["unlocks_cadence"]:
90+
# Item Consumption
91+
if "consumes" in out_edges:
92+
for edge in out_edges["consumes"]:
6293
target_id = edge["targetId"]
63-
if target_id in sig_nodes:
64-
lines.append(f"{nid} ==>|Unlocks| {target_id}")
94+
qty = edge.get("quantity", 1)
95+
# Link Item to the consumer
96+
lines.append(f"{target_id} --x|Consumes {qty}| {nid}")
97+
98+
# Containment (Optional, but useful for locations)
99+
if ntype == "Location" and "contains" in out_edges:
100+
for edge in out_edges["contains"]:
101+
target_id = edge["targetId"]
102+
# lines.append(f"{nid} -.->|Home of| {target_id}") # Usually too noisy
65103

66-
# Output
67104
return "\n".join(lines)
68105

69106
if __name__ == "__main__":

scripts/visualize_graph.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ def generate_html(mermaid_code):
4040
.quest-box {{ background-color: #4b0082; border: 1px solid #f9f; }}
4141
.location-box {{ background-color: #00008b; border: 1px solid #ccf; }}
4242
.cadence-box {{ background-color: #006400; border: 1px solid #cfc; }}
43+
.item-box {{ background-color: #444; border: 1px solid #fff; }}
44+
.stat-box {{ background-color: #8b4513; border: 1px solid #ff8c00; }}
45+
.ability-box {{ background-color: #2f4f4f; border: 1px solid #00ced1; }}
4346
4447
#graph-container {{
4548
width: 100%;
@@ -64,6 +67,9 @@ def generate_html(mermaid_code):
6467
<div class="legend-item"><div class="legend-box quest-box"></div> Quest</div>
6568
<div class="legend-item"><div class="legend-box location-box"></div> Location</div>
6669
<div class="legend-item"><div class="legend-box cadence-box"></div> Cadence</div>
70+
<div class="legend-item"><div class="legend-box item-box"></div> Item</div>
71+
<div class="legend-item"><div class="legend-box stat-box"></div> Stat</div>
72+
<div class="legend-item"><div class="legend-box ability-box"></div> Ability</div>
6773
</div>
6874
</div>
6975
<div id="graph-container">

0 commit comments

Comments
 (0)