RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
alchemy_graph_manager.gd
Go to the documentation of this file.
1extends RefCounted
2
3
6
7const DataCacheManager = preload("res://scripts/systems/dataCacheManager/data_cache_manager.gd")
8
9var definitions := {}
10var reactions := []
11var data_cache_manager = DataCacheManager.new()
12
13
14
15func load_graph(definitions_path:String, reactions_path:String) -> void:
16 load_graph_data(
17 data_cache_manager.load_json(definitions_path),
18 data_cache_manager.load_json(reactions_path)
19 )
20
21
22
23func load_graph_data(definition_data:Dictionary, reaction_data:Dictionary) -> void:
24 definitions.clear()
25 reactions.clear()
26 _load_definitions(definition_data)
27 _load_reactions(reaction_data)
28
29
30
31func validate_graph(starter_ids:Array = []) -> Dictionary:
32 var issues := {
33 "missing_inputs": [],
34 "missing_results": [],
35 "duplicate_reactions": [],
36 "unreachable_results": []
37 }
38 var seen_reaction_ids := {}
39 for reaction in reactions:
40 var reaction_id = str(reaction.get("id", ""))
41 if reaction_id != "":
42 if seen_reaction_ids.has(reaction_id):
43 issues["duplicate_reactions"].append(reaction_id)
44 seen_reaction_ids[reaction_id] = true
45 for input in reaction.get("inputs", []):
46 var input_id = str(input)
47 if input_id != "" and not definitions.has(input_id):
48 issues["missing_inputs"].append({"reaction": reaction_id, "id": input_id})
49 var result_id = str(reaction.get("result", ""))
50 if result_id != "" and not definitions.has(result_id):
51 issues["missing_results"].append({"reaction": reaction_id, "id": result_id})
52 if not starter_ids.is_empty():
53 var reachable = get_reachable_results(starter_ids)
54 for reaction in reactions:
55 var result = str(reaction.get("result", ""))
56 if result != "" and not reachable.has(result):
57 issues["unreachable_results"].append(result)
58 return issues
59
60
61
62func get_reachable_results(starter_ids:Array) -> Dictionary:
63 var known := {}
64 for starter in starter_ids:
65 var id = str(starter)
66 if id != "":
67 known[id] = true
68 var changed := true
69 while changed:
70 changed = false
71 for reaction in reactions:
72 var result = str(reaction.get("result", ""))
73 if result == "" or known.has(result):
74 continue
75 var can_make := true
76 for input in reaction.get("inputs", []):
77 if not known.has(str(input)):
78 can_make = false
79 break
80 for catalyst in reaction.get("catalysts", []):
81 if not known.has(str(catalyst)):
82 can_make = false
83 break
84 if can_make:
85 known[result] = true
86 changed = true
87 return known
88
89
90
91func get_dead_end_results(starter_ids:Array = []) -> Array:
92 var reachable = get_reachable_results(starter_ids) if not starter_ids.is_empty() else _all_results()
93 var consumed := {}
94 for reaction in reactions:
95 for input in reaction.get("inputs", []):
96 consumed[str(input)] = true
97 for catalyst in reaction.get("catalysts", []):
98 consumed[str(catalyst)] = true
99 var dead_ends := []
100 for id in reachable.keys():
101 if not consumed.has(id) and _is_compound(id):
102 dead_ends.append(id)
103 dead_ends.sort()
104 return dead_ends
105
106
107
108func get_summary(starter_ids:Array = []) -> Dictionary:
109 var reachable = get_reachable_results(starter_ids) if not starter_ids.is_empty() else _all_results()
110 return {
111 "definitions": definitions.keys().size(),
112 "reactions": reactions.size(),
113 "reachable": reachable.keys().size(),
114 "dead_ends": get_dead_end_results(starter_ids)
115 }
116
117
118func _all_results() -> Dictionary:
119 var results := {}
120 for reaction in reactions:
121 var result = str(reaction.get("result", ""))
122 if result != "":
123 results[result] = true
124 return results
125
126
127func _is_compound(id:String) -> bool:
128 if not definitions.has(id):
129 return false
130 return bool(definitions[id].has("tier"))
131
132
133func _load_definitions(definition_data:Dictionary) -> void:
134 for element in definition_data.get("elements", []):
135 if element is Dictionary:
136 var id = str(element.get("id", ""))
137 if id != "":
138 definitions[id] = element.duplicate(true)
139 for compound in definition_data.get("compounds", []):
140 if compound is Dictionary:
141 var id = str(compound.get("id", ""))
142 if id != "":
143 definitions[id] = compound.duplicate(true)
144
145
146func _load_reactions(reaction_data:Dictionary) -> void:
147 for reaction in reaction_data.get("reactions", []):
148 if reaction is Dictionary:
149 reactions.append(reaction.duplicate(true))
150
151
152func get_cache_stats() -> Dictionary:
153 return data_cache_manager.get_cache_stats()