summary refs log tree commit diff stats
path: root/tools/validator/human_processor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/validator/human_processor.cpp')
-rw-r--r--tools/validator/human_processor.cpp425
1 files changed, 425 insertions, 0 deletions
diff --git a/tools/validator/human_processor.cpp b/tools/validator/human_processor.cpp new file mode 100644 index 0000000..5382443 --- /dev/null +++ b/tools/validator/human_processor.cpp
@@ -0,0 +1,425 @@
1#include "human_processor.h"
2
3#include <google/protobuf/message.h>
4#include <google/protobuf/text_format.h>
5
6#include <filesystem>
7#include <fstream>
8#include <iostream>
9#include <map>
10#include <optional>
11#include <sstream>
12#include <string>
13
14#include "structs.h"
15
16namespace com::fourisland::lingo2_archipelago {
17namespace {
18
19template <typename T>
20T ReadMessageFromFile(const std::string& path) {
21 std::cout << "Processing " << path << std::endl;
22
23 std::ifstream file(path);
24 std::stringstream buffer;
25 buffer << file.rdbuf();
26
27 T message;
28 google::protobuf::TextFormat::ParseFromString(buffer.str(), &message);
29
30 return message;
31}
32
33class HumanProcessor {
34 public:
35 HumanProcessor(const std::string& mapdir, CollectedInfo& info)
36 : mapdir_(mapdir), info_(info) {}
37
38 void Run() {
39 std::filesystem::path datadir_path = mapdir_;
40
41 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt);
42 ProcessMaps(datadir_path);
43 ProcessIdsFile(datadir_path / "ids.txtpb");
44 }
45
46 private:
47 void ProcessMaps(std::filesystem::path path) {
48 std::filesystem::path maps_dir = path / "maps";
49 for (auto const& dir_entry :
50 std::filesystem::directory_iterator(maps_dir)) {
51 ProcessMap(dir_entry.path());
52 }
53 }
54
55 void ProcessMap(std::filesystem::path path) {
56 std::string map_name = path.filename();
57
58 ProcessConnectionsFile(path / "connections.txtpb", map_name);
59 ProcessDoorsFile(path / "doors.txtpb", map_name);
60 ProcessRooms(path / "rooms", map_name);
61 }
62
63 void ProcessRooms(std::filesystem::path path,
64 const std::string& current_map_name) {
65 for (auto const& dir_entry : std::filesystem::directory_iterator(path)) {
66 auto room = ReadMessageFromFile<HumanRoom>(dir_entry.path().string());
67 ProcessRoom(room, current_map_name);
68 }
69 }
70
71 void ProcessRoom(const HumanRoom& h_room,
72 const std::string& current_map_name) {
73 RoomIdentifier room_identifier;
74 room_identifier.set_map(current_map_name);
75 room_identifier.set_name(h_room.name());
76
77 RoomInfo& room_info = info_.rooms[room_identifier];
78 room_info.definitions.push_back(h_room);
79
80 for (const HumanPanel& h_panel : h_room.panels()) {
81 ProcessPanel(h_panel, current_map_name, h_room.name());
82 }
83
84 for (const HumanPainting& h_painting : h_room.paintings()) {
85 ProcessPainting(h_painting, current_map_name, h_room.name());
86 }
87
88 for (const HumanPort& h_port : h_room.ports()) {
89 ProcessPort(h_port, current_map_name, h_room.name());
90 }
91
92 for (const HumanLetter& h_letter : h_room.letters()) {
93 ProcessLetter(h_letter, current_map_name, h_room.name());
94 }
95
96 for (const HumanMastery& h_mastery : h_room.masteries()) {
97 ProcessMastery(h_mastery, current_map_name, h_room.name());
98 }
99
100 for (const HumanKeyholder& h_keyholder : h_room.keyholders()) {
101 ProcessKeyholder(h_keyholder, current_map_name, h_room.name());
102 }
103 }
104
105 void ProcessPanel(const HumanPanel& h_panel,
106 const std::string& current_map_name,
107 const std::string& current_room_name) {
108 PanelIdentifier panel_identifier;
109 panel_identifier.set_map(current_map_name);
110 panel_identifier.set_room(current_room_name);
111 panel_identifier.set_name(h_panel.name());
112
113 PanelInfo& panel_info = info_.panels[panel_identifier];
114 panel_info.definitions.push_back(h_panel);
115 panel_info.proxies[h_panel.answer()].definitions.push_back(Proxy());
116
117 for (const Proxy& h_proxy : h_panel.proxies()) {
118 ProxyInfo& proxy_info = panel_info.proxies[h_proxy.answer()];
119 proxy_info.definitions.push_back(h_proxy);
120 }
121
122 if (h_panel.has_required_door()) {
123 DoorIdentifier required_door_identifier =
124 *GetCompleteDoorIdentifier(h_panel.required_door(), current_map_name);
125 DoorInfo& required_door_info = info_.doors[required_door_identifier];
126 required_door_info.panels_referenced_by.push_back(panel_identifier);
127 }
128
129 if (h_panel.has_required_room()) {
130 RoomIdentifier required_room_identifier =
131 *GetCompleteRoomIdentifier(h_panel.required_room(), current_map_name);
132 RoomInfo& required_room_info = info_.rooms[required_room_identifier];
133 required_room_info.panels_referenced_by.push_back(panel_identifier);
134 }
135 }
136
137 void ProcessPainting(const HumanPainting& h_painting,
138 const std::string& current_map_name,
139 const std::string& current_room_name) {
140 PaintingIdentifier painting_identifier;
141 painting_identifier.set_map(current_map_name);
142 painting_identifier.set_room(current_room_name);
143 painting_identifier.set_name(h_painting.name());
144
145 PaintingInfo& painting_info = info_.paintings[painting_identifier];
146 painting_info.definitions.push_back(h_painting);
147
148 if (h_painting.has_required_door()) {
149 DoorIdentifier required_door_identifier = *GetCompleteDoorIdentifier(
150 h_painting.required_door(), current_map_name);
151 DoorInfo& required_door_info = info_.doors[required_door_identifier];
152 required_door_info.paintings_referenced_by.push_back(painting_identifier);
153 }
154 }
155
156 void ProcessPort(const HumanPort& h_port, const std::string& current_map_name,
157 const std::string& current_room_name) {
158 PortIdentifier port_identifier;
159 port_identifier.set_map(current_map_name);
160 port_identifier.set_room(current_room_name);
161 port_identifier.set_name(h_port.name());
162
163 PortInfo& port_info = info_.ports[port_identifier];
164 port_info.definitions.push_back(h_port);
165
166 if (h_port.has_required_door()) {
167 DoorIdentifier required_door_identifier =
168 *GetCompleteDoorIdentifier(h_port.required_door(), current_map_name);
169 DoorInfo& required_door_info = info_.doors[required_door_identifier];
170 required_door_info.ports_referenced_by.push_back(port_identifier);
171 }
172 }
173
174 void ProcessLetter(const HumanLetter& h_letter,
175 const std::string& current_map_name,
176 const std::string& current_room_name) {
177 LetterIdentifier letter_identifier =
178 std::make_tuple(h_letter.key()[0], h_letter.level2());
179 LetterInfo& letter_info = info_.letters[letter_identifier];
180
181 RoomIdentifier room_identifier;
182 room_identifier.set_map(current_map_name);
183 room_identifier.set_name(current_room_name);
184 letter_info.defined_in.push_back(room_identifier);
185 }
186
187 void ProcessMastery(const HumanMastery& h_mastery,
188 const std::string& current_map_name,
189 const std::string& current_room_name) {
190 // Nothing really to validate about masteries yet.
191 }
192
193 void ProcessKeyholder(const HumanKeyholder& h_keyholder,
194 const std::string& current_map_name,
195 const std::string& current_room_name) {
196 KeyholderIdentifier keyholder_identifier;
197 keyholder_identifier.set_map(current_map_name);
198 keyholder_identifier.set_room(current_room_name);
199 keyholder_identifier.set_name(h_keyholder.name());
200
201 KeyholderInfo& keyholder_info = info_.keyholders[keyholder_identifier];
202 keyholder_info.definitions.push_back(h_keyholder);
203 }
204
205 void ProcessDoorsFile(std::filesystem::path path,
206 const std::string& current_map_name) {
207 if (!std::filesystem::exists(path)) {
208 return;
209 }
210
211 auto doors = ReadMessageFromFile<HumanDoors>(path.string());
212
213 for (const HumanDoor& door : doors.doors()) {
214 ProcessDoor(door, current_map_name);
215 }
216 }
217
218 void ProcessDoor(const HumanDoor& h_door,
219 const std::string& current_map_name) {
220 DoorIdentifier door_identifier;
221 door_identifier.set_map(current_map_name);
222 door_identifier.set_name(h_door.name());
223
224 DoorInfo& door_info = info_.doors[door_identifier];
225 door_info.definitions.push_back(h_door);
226
227 if (h_door.has_location_room()) {
228 RoomIdentifier location_room_identifier;
229 location_room_identifier.set_map(current_map_name);
230 location_room_identifier.set_name(h_door.location_room());
231 info_.rooms[location_room_identifier].doors_referenced_by.push_back(
232 door_identifier);
233 }
234
235 for (const PaintingIdentifier& pi : h_door.move_paintings()) {
236 auto complete_painting_identifier =
237 GetCompletePaintingIdentifier(pi, current_map_name, std::nullopt);
238 if (complete_painting_identifier) {
239 PaintingInfo& move_painting_info =
240 info_.paintings[*complete_painting_identifier];
241 move_painting_info.doors_referenced_by.push_back(door_identifier);
242 } else {
243 door_info.malformed_identifiers.paintings.push_back(pi);
244 }
245 }
246
247 for (const PanelIdentifier& pi : h_door.panels()) {
248 auto complete_panel_identifier = GetCompletePanelIdentifierWithoutAnswer(
249 pi, current_map_name, std::nullopt);
250 if (complete_panel_identifier) {
251 PanelInfo& panel_info = info_.panels[*complete_panel_identifier];
252 panel_info.doors_referenced_by.push_back(door_identifier);
253
254 if (pi.has_answer()) {
255 panel_info.proxies[pi.answer()].doors_referenced_by.push_back(
256 door_identifier);
257 }
258 } else {
259 door_info.malformed_identifiers.panels.push_back(pi);
260 }
261 }
262
263 for (const KeyholderIdentifier& ki : h_door.keyholders()) {
264 auto complete_keyholder_identifier =
265 GetCompleteKeyholderIdentifierWithoutKey(ki, current_map_name,
266 std::nullopt);
267 if (complete_keyholder_identifier) {
268 KeyholderInfo& keyholder_info =
269 info_.keyholders[*complete_keyholder_identifier];
270 keyholder_info.doors_referenced_by.push_back(door_identifier);
271 } else {
272 door_info.malformed_identifiers.keyholders.push_back(ki);
273 }
274 }
275
276 for (const RoomIdentifier& ri : h_door.rooms()) {
277 RoomIdentifier complete_room_identifier =
278 *GetCompleteRoomIdentifier(ri, current_map_name);
279 RoomInfo& room_info = info_.rooms[complete_room_identifier];
280 room_info.doors_referenced_by.push_back(door_identifier);
281 }
282
283 for (const DoorIdentifier& di : h_door.doors()) {
284 DoorIdentifier complete_door_identifier =
285 *GetCompleteDoorIdentifier(di, current_map_name);
286 DoorInfo& other_door_info = info_.doors[complete_door_identifier];
287 other_door_info.doors_referenced_by.push_back(door_identifier);
288 }
289 }
290
291 void ProcessConnectionsFile(std::filesystem::path path,
292 std::optional<std::string> current_map_name) {
293 if (!std::filesystem::exists(path)) {
294 return;
295 }
296
297 auto connections = ReadMessageFromFile<HumanConnections>(path.string());
298
299 for (const HumanConnection& connection : connections.connections()) {
300 ProcessConnection(connection, current_map_name);
301 }
302 }
303
304 void ProcessConnection(const HumanConnection& human_connection,
305 const std::optional<std::string>& current_map_name) {
306 if (human_connection.has_from_room()) {
307 if (current_map_name) {
308 RoomIdentifier room_identifier;
309 room_identifier.set_map(*current_map_name);
310 room_identifier.set_name(human_connection.from_room());
311
312 RoomInfo& room_info = info_.rooms[room_identifier];
313 room_info.connections_referenced_by.push_back(human_connection);
314 } else {
315 // Not sure where else to store this right now.
316 std::cout << "A global connection used from_room." << std::endl;
317 }
318 } else if (human_connection.has_from()) {
319 ProcessSingleConnection(human_connection, human_connection.from(),
320 current_map_name);
321 }
322
323 if (human_connection.has_to_room()) {
324 if (current_map_name) {
325 RoomIdentifier room_identifier;
326 room_identifier.set_map(*current_map_name);
327 room_identifier.set_name(human_connection.to_room());
328
329 RoomInfo& room_info = info_.rooms[room_identifier];
330 room_info.connections_referenced_by.push_back(human_connection);
331 } else {
332 // Not sure where else to store this right now.
333 std::cout << "A global connection used to_room." << std::endl;
334 }
335 } else if (human_connection.has_to()) {
336 ProcessSingleConnection(human_connection, human_connection.to(),
337 current_map_name);
338 }
339
340 if (human_connection.has_door()) {
341 auto door_identifier =
342 GetCompleteDoorIdentifier(human_connection.door(), current_map_name);
343 if (door_identifier) {
344 DoorInfo& door_info = info_.doors[*door_identifier];
345 door_info.connections_referenced_by.push_back(human_connection);
346 } else {
347 // Not sure where else to store this right now.
348 std::cout
349 << "A connection used the following malformed door identifier: "
350 << human_connection.door().ShortDebugString() << std::endl;
351 }
352 }
353 }
354
355 void ProcessSingleConnection(
356 const HumanConnection& human_connection,
357 const HumanConnection::Endpoint& endpoint,
358 const std::optional<std::string>& current_map_name) {
359 if (endpoint.has_room()) {
360 auto room_identifier =
361 GetCompleteRoomIdentifier(endpoint.room(), current_map_name);
362 if (room_identifier) {
363 RoomInfo& room_info = info_.rooms[*room_identifier];
364 room_info.connections_referenced_by.push_back(human_connection);
365 } else {
366 // Not sure where else to store this right now.
367 std::cout
368 << "A connection used the following malformed room identifier: "
369 << endpoint.room().ShortDebugString() << std::endl;
370 }
371 } else if (endpoint.has_painting()) {
372 auto painting_identifier = GetCompletePaintingIdentifier(
373 endpoint.painting(), current_map_name, std::nullopt);
374 if (painting_identifier) {
375 PaintingInfo& painting_info = info_.paintings[*painting_identifier];
376 painting_info.connections_referenced_by.push_back(human_connection);
377 } else {
378 // Not sure where else to store this right now.
379 std::cout
380 << "A connection used the following malformed painting identifier: "
381 << endpoint.painting().ShortDebugString() << std::endl;
382 }
383 } else if (endpoint.has_port()) {
384 auto port_identifier = GetCompletePortIdentifier(
385 endpoint.port(), current_map_name, std::nullopt);
386 if (port_identifier) {
387 PortInfo& port_info = info_.ports[*port_identifier];
388 port_info.connections_referenced_by.push_back(human_connection);
389 } else {
390 // Not sure where else to store this right now.
391 std::cout
392 << "A connection used the following malformed port identifier: "
393 << endpoint.port().ShortDebugString() << std::endl;
394 }
395 } else if (endpoint.has_panel()) {
396 auto panel_identifier = GetCompletePanelIdentifierWithoutAnswer(
397 endpoint.panel(), current_map_name, std::nullopt);
398 if (panel_identifier) {
399 PanelInfo& panel_info = info_.panels[*panel_identifier];
400 panel_info.connections_referenced_by.push_back(human_connection);
401
402 if (endpoint.panel().has_answer()) {
403 panel_info.proxies[endpoint.panel().answer()]
404 .connections_referenced_by.push_back(human_connection);
405 }
406 }
407 }
408 }
409
410 void ProcessIdsFile(std::filesystem::path path) {
411 // Ignore this for now.
412 }
413
414 std::string mapdir_;
415 CollectedInfo& info_;
416};
417
418} // namespace
419
420void ProcessHumanData(const std::string& mapdir, CollectedInfo& info) {
421 HumanProcessor human_processor(mapdir, info);
422 human_processor.Run();
423}
424
425} // namespace com::fourisland::lingo2_archipelago