summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--apworld/__init__.py6
-rw-r--r--apworld/player_logic.py10
-rw-r--r--apworld/regions.py3
-rw-r--r--apworld/static_logic.py23
-rw-r--r--data/ids.txtpb531
-rw-r--r--proto/data.proto2
-rw-r--r--proto/human.proto13
-rw-r--r--tools/assign_ids/CMakeLists.txt9
-rw-r--r--tools/assign_ids/main.cpp172
-rw-r--r--tools/datapacker/main.cpp21
11 files changed, 779 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 10025ce..fab2c86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -3,4 +3,5 @@ cmake_minimum_required(VERSION 3.28)
3project(lingo2_archipelago) 3project(lingo2_archipelago)
4 4
5add_subdirectory(proto) 5add_subdirectory(proto)
6add_subdirectory(tools/assign_ids)
6add_subdirectory(tools/datapacker) 7add_subdirectory(tools/datapacker)
diff --git a/apworld/__init__.py b/apworld/__init__.py index 013910e..1544c7b 100644 --- a/apworld/__init__.py +++ b/apworld/__init__.py
@@ -25,10 +25,10 @@ class Lingo2World(World):
25 options_dataclass = Lingo2Options 25 options_dataclass = Lingo2Options
26 options: Lingo2Options 26 options: Lingo2Options
27 27
28 item_name_to_id = {}
29 location_name_to_id = {}
30
31 static_logic = Lingo2StaticLogic() 28 static_logic = Lingo2StaticLogic()
29 item_name_to_id = static_logic.item_name_to_id
30 location_name_to_id = static_logic.location_name_to_id
31
32 player_logic: Lingo2PlayerLogic 32 player_logic: Lingo2PlayerLogic
33 33
34 def generate_early(self): 34 def generate_early(self):
diff --git a/apworld/player_logic.py b/apworld/player_logic.py index f54573f..675c6ae 100644 --- a/apworld/player_logic.py +++ b/apworld/player_logic.py
@@ -1,3 +1,4 @@
1from .generated import common_pb2 as common_pb2
1from typing import TYPE_CHECKING, NamedTuple 2from typing import TYPE_CHECKING, NamedTuple
2 3
3if TYPE_CHECKING: 4if TYPE_CHECKING:
@@ -5,7 +6,6 @@ if TYPE_CHECKING:
5 6
6 7
7class PlayerLocation(NamedTuple): 8class PlayerLocation(NamedTuple):
8 name: str
9 code: int | None 9 code: int | None
10 10
11 11
@@ -15,10 +15,6 @@ class Lingo2PlayerLogic:
15 def __init__(self, world: "Lingo2World"): 15 def __init__(self, world: "Lingo2World"):
16 self.locations_by_room = {} 16 self.locations_by_room = {}
17 17
18 code = 1
19 for door in world.static_logic.objects.doors: 18 for door in world.static_logic.objects.doors:
20 if not door.HasField("room_id"): 19 if door.type == common_pb2.DoorType.STANDARD:
21 continue 20 self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.ap_id))
22
23 self.locations_by_room.setdefault(door.room_id, []).append(PlayerLocation(door.name, code))
24 code += 1
diff --git a/apworld/regions.py b/apworld/regions.py index 24c2281..d388678 100644 --- a/apworld/regions.py +++ b/apworld/regions.py
@@ -11,7 +11,8 @@ def create_region(room, world: "Lingo2World") -> Region:
11 new_region = Region(room.name, world.player, world.multiworld) 11 new_region = Region(room.name, world.player, world.multiworld)
12 12
13 for location in world.player_logic.locations_by_room.get(room.id, {}): 13 for location in world.player_logic.locations_by_room.get(room.id, {}):
14 new_location = Lingo2Location(world.player, location.name, location.code, new_region) 14 new_location = Lingo2Location(world.player, world.static_logic.location_id_to_name[location.code],
15 location.code, new_region)
15 new_region.locations.append(new_location) 16 new_region.locations.append(new_location)
16 17
17 return new_region 18 return new_region
diff --git a/apworld/static_logic.py b/apworld/static_logic.py index 6c38f1f..d3ed85c 100644 --- a/apworld/static_logic.py +++ b/apworld/static_logic.py
@@ -1,9 +1,30 @@
1from .generated import common_pb2 as common_pb2
1from .generated import data_pb2 as data_pb2 2from .generated import data_pb2 as data_pb2
2import pkgutil 3import pkgutil
3 4
4class Lingo2StaticLogic: 5class Lingo2StaticLogic:
6 item_id_to_name: dict[int, str]
7 location_id_to_name: dict[int, str]
8
9 item_name_to_id: dict[str, int]
10 location_name_to_id: dict[str, int]
11
5 def __init__(self): 12 def __init__(self):
6 file = pkgutil.get_data(__name__, "generated/data.binpb") 13 self.item_id_to_name = {}
14 self.location_id_to_name = {}
7 15
16 file = pkgutil.get_data(__name__, "generated/data.binpb")
8 self.objects = data_pb2.AllObjects() 17 self.objects = data_pb2.AllObjects()
9 self.objects.ParseFromString(bytearray(file)) 18 self.objects.ParseFromString(bytearray(file))
19
20 for door in self.objects.doors:
21 if door.type == common_pb2.DoorType.STANDARD:
22 location_name = f"{self.objects.rooms[door.room_id].display_name} - {door.name}"
23 self.location_id_to_name[door.ap_id] = location_name
24
25 if door.type != common_pb2.DoorType.EVENT:
26 item_name = f"{self.objects.rooms[door.room_id].display_name} - {door.name}"
27 self.item_id_to_name[door.ap_id] = item_name
28
29 self.item_name_to_id = {name: ap_id for ap_id, name in self.item_id_to_name.items()}
30 self.location_name_to_id = {name: ap_id for ap_id, name in self.location_id_to_name.items()}
diff --git a/data/ids.txtpb b/data/ids.txtpb new file mode 100644 index 0000000..d6ad423 --- /dev/null +++ b/data/ids.txtpb
@@ -0,0 +1,531 @@
1maps {
2 key: "the_entry"
3 value {
4 doors {
5 key: "Blue Alcove Entrance"
6 value: 12
7 }
8 doors {
9 key: "Blue Alcove Exit"
10 value: 8
11 }
12 doors {
13 key: "Colored Doors Area Entrance"
14 value: 33
15 }
16 doors {
17 key: "Composite Room Entrance"
18 value: 24
19 }
20 doors {
21 key: "Control Center White Door"
22 value: 22
23 }
24 doors {
25 key: "Corners Painting"
26 value: 7
27 }
28 doors {
29 key: "D Room Entrance"
30 value: 34
31 }
32 doors {
33 key: "D Room Panels"
34 value: 36
35 }
36 doors {
37 key: "Daedalus Entrance"
38 value: 26
39 }
40 doors {
41 key: "Flip Area Entrance"
42 value: 25
43 }
44 doors {
45 key: "Flipped Pyramid Area Entrance"
46 value: 30
47 }
48 doors {
49 key: "Flipped Second Room Left Door"
50 value: 15
51 }
52 doors {
53 key: "Flipped Second Room Right Door"
54 value: 14
55 }
56 doors {
57 key: "Four Corner Panels"
58 value: 6
59 }
60 doors {
61 key: "Gallery Entrance"
62 value: 37
63 }
64 doors {
65 key: "L Room Entrance"
66 value: 38
67 }
68 doors {
69 key: "Least Blue Last Panels"
70 value: 39
71 }
72 doors {
73 key: "Liberated Entrance"
74 value: 29
75 }
76 doors {
77 key: "Lime Room Entrance"
78 value: 20
79 }
80 doors {
81 key: "Link Area Entrance"
82 value: 2
83 }
84 doors {
85 key: "Literate Entrance"
86 value: 31
87 }
88 doors {
89 key: "Near D Room Painting"
90 value: 35
91 }
92 doors {
93 key: "Noon Door"
94 value: 10
95 }
96 doors {
97 key: "Orange Door Hider"
98 value: 19
99 }
100 doors {
101 key: "Parthenon Entrance"
102 value: 32
103 }
104 doors {
105 key: "Rabbithole Door"
106 value: 9
107 }
108 doors {
109 key: "Red Alcove Exit"
110 value: 5
111 }
112 doors {
113 key: "Red Blue Area Left Door"
114 value: 17
115 }
116 doors {
117 key: "Red Blue Area Right Door"
118 value: 18
119 }
120 doors {
121 key: "Red Room Painting"
122 value: 40
123 }
124 doors {
125 key: "Repetitive Entrance"
126 value: 27
127 }
128 doors {
129 key: "Revitalized Entrance"
130 value: 21
131 }
132 doors {
133 key: "Right Eye Entrance"
134 value: 16
135 }
136 doors {
137 key: "Scarf Door"
138 value: 11
139 }
140 doors {
141 key: "Second Room Left Door"
142 value: 13
143 }
144 doors {
145 key: "Second Room Right Door"
146 value: 4
147 }
148 doors {
149 key: "Shop Entrance"
150 value: 28
151 }
152 doors {
153 key: "Third Eye Painting"
154 value: 41
155 }
156 doors {
157 key: "Trick Door"
158 value: 1
159 }
160 doors {
161 key: "Trick To Shop Door"
162 value: 3
163 }
164 doors {
165 key: "X Area Entrance"
166 value: 23
167 }
168 rooms {
169 key: "Blue Alcove"
170 value {
171 panels {
172 key: "ARMY"
173 value: 80
174 }
175 panels {
176 key: "BLUE"
177 value: 79
178 }
179 }
180 }
181 rooms {
182 key: "Colored Doors Area"
183 value {
184 panels {
185 key: "OPEN"
186 value: 60
187 }
188 }
189 }
190 rooms {
191 key: "Ctrl Tutorial"
192 value {
193 panels {
194 key: "RIGHT"
195 value: 64
196 }
197 }
198 }
199 rooms {
200 key: "D Room"
201 value {
202 panels {
203 key: "BASEBALL"
204 value: 70
205 }
206 panels {
207 key: "BIKERS"
208 value: 71
209 }
210 panels {
211 key: "BLACK"
212 value: 74
213 }
214 panels {
215 key: "BOWLER"
216 value: 77
217 }
218 panels {
219 key: "CARPENTER"
220 value: 78
221 }
222 panels {
223 key: "COWBOY"
224 value: 75
225 }
226 panels {
227 key: "RED"
228 value: 72
229 }
230 panels {
231 key: "SPRAY"
232 value: 76
233 }
234 panels {
235 key: "SUN"
236 value: 73
237 }
238 }
239 }
240 rooms {
241 key: "Eye Room"
242 value {
243 panels {
244 key: "I"
245 value: 90
246 }
247 }
248 }
249 rooms {
250 key: "Flipped Link Area"
251 value {
252 panels {
253 key: "WANDER"
254 value: 42
255 }
256 }
257 }
258 rooms {
259 key: "Flipped Pyramid Area"
260 value {
261 panels {
262 key: "TURN (1)"
263 value: 48
264 }
265 panels {
266 key: "TURN (2)"
267 value: 49
268 }
269 }
270 }
271 rooms {
272 key: "Flipped Right Eye"
273 value {
274 panels {
275 key: "HERE"
276 value: 86
277 }
278 panels {
279 key: "WHERE"
280 value: 85
281 }
282 }
283 }
284 rooms {
285 key: "Flipped Second Room"
286 value {
287 panels {
288 key: "CLUE"
289 value: 46
290 }
291 panels {
292 key: "SLENDER"
293 value: 47
294 }
295 }
296 }
297 rooms {
298 key: "Gallery Return"
299 value {
300 panels {
301 key: "RETURN"
302 value: 61
303 }
304 }
305 }
306 rooms {
307 key: "Least Blue Last"
308 value {
309 panels {
310 key: "AIL"
311 value: 58
312 }
313 panels {
314 key: "CAPABLE (1)"
315 value: 50
316 }
317 panels {
318 key: "CAPABLE (2)"
319 value: 51
320 }
321 panels {
322 key: "CORNERS"
323 value: 59
324 }
325 panels {
326 key: "LABEL"
327 value: 57
328 }
329 panels {
330 key: "LUSTRE"
331 value: 52
332 }
333 panels {
334 key: "OLD"
335 value: 55
336 }
337 panels {
338 key: "STEALER"
339 value: 54
340 }
341 panels {
342 key: "TRUST"
343 value: 56
344 }
345 panels {
346 key: "WANT"
347 value: 53
348 }
349 }
350 }
351 rooms {
352 key: "Lime Room"
353 value {
354 panels {
355 key: "COLOR"
356 value: 45
357 }
358 panels {
359 key: "HIDE"
360 value: 43
361 }
362 panels {
363 key: "SEEK"
364 value: 44
365 }
366 }
367 }
368 rooms {
369 key: "Link Area"
370 value {
371 panels {
372 key: "WANDER"
373 value: 63
374 }
375 }
376 }
377 rooms {
378 key: "Parthenon Return"
379 value {
380 panels {
381 key: "RETURN"
382 value: 87
383 }
384 }
385 }
386 rooms {
387 key: "Rabbit Hole"
388 value {
389 panels {
390 key: "PUZZLE"
391 value: 84
392 }
393 }
394 }
395 rooms {
396 key: "Red Alcove"
397 value {
398 panels {
399 key: "BROW"
400 value: 88
401 }
402 panels {
403 key: "DEAD"
404 value: 89
405 }
406 }
407 }
408 rooms {
409 key: "Red Blue Halls"
410 value {
411 panels {
412 key: "CENTER"
413 value: 97
414 }
415 panels {
416 key: "CENTER DAY"
417 value: 99
418 }
419 panels {
420 key: "DAY"
421 value: 98
422 }
423 panels {
424 key: "RAIN"
425 value: 101
426 }
427 panels {
428 key: "RAIN WOMAN"
429 value: 103
430 }
431 panels {
432 key: "WANDER"
433 value: 100
434 }
435 panels {
436 key: "WOMAN"
437 value: 102
438 }
439 }
440 }
441 rooms {
442 key: "Right Eye"
443 value {
444 panels {
445 key: "EYE"
446 value: 81
447 }
448 panels {
449 key: "FAINT"
450 value: 83
451 }
452 panels {
453 key: "WANDER"
454 value: 82
455 }
456 }
457 }
458 rooms {
459 key: "Shop Entrance"
460 value {
461 panels {
462 key: "TURN"
463 value: 104
464 }
465 }
466 }
467 rooms {
468 key: "Starting Room"
469 value {
470 panels {
471 key: "EYE"
472 value: 93
473 }
474 panels {
475 key: "HI"
476 value: 91
477 }
478 panels {
479 key: "HINT"
480 value: 94
481 }
482 panels {
483 key: "THAN"
484 value: 96
485 }
486 panels {
487 key: "THIN"
488 value: 95
489 }
490 panels {
491 key: "TRICK"
492 value: 92
493 }
494 }
495 }
496 rooms {
497 key: "Trick Room"
498 value {
499 panels {
500 key: "INK"
501 value: 62
502 }
503 }
504 }
505 rooms {
506 key: "Wrath Room"
507 value {
508 panels {
509 key: "CORN"
510 value: 69
511 }
512 panels {
513 key: "DICE"
514 value: 68
515 }
516 panels {
517 key: "HOLE"
518 value: 66
519 }
520 panels {
521 key: "RABBIT"
522 value: 65
523 }
524 panels {
525 key: "WREATH"
526 value: 67
527 }
528 }
529 }
530 }
531}
diff --git a/proto/data.proto b/proto/data.proto index 3417c4c..bea2563 100644 --- a/proto/data.proto +++ b/proto/data.proto
@@ -23,6 +23,7 @@ message Connection {
23 23
24message Door { 24message Door {
25 uint64 id = 1; 25 uint64 id = 1;
26 uint64 ap_id = 11;
26 uint64 map_id = 9; 27 uint64 map_id = 9;
27 uint64 room_id = 10; 28 uint64 room_id = 10;
28 string name = 2; 29 string name = 2;
@@ -39,6 +40,7 @@ message Door {
39 40
40message Panel { 41message Panel {
41 uint64 id = 1; 42 uint64 id = 1;
43 uint64 ap_id = 10;
42 uint64 room_id = 2; 44 uint64 room_id = 2;
43 string name = 3; 45 string name = 3;
44 46
diff --git a/proto/human.proto b/proto/human.proto index d5d03ff..1dcf2ab 100644 --- a/proto/human.proto +++ b/proto/human.proto
@@ -124,3 +124,16 @@ message HumanRoom {
124 repeated Letter letters = 5; 124 repeated Letter letters = 5;
125 repeated HumanPort ports = 6; 125 repeated HumanPort ports = 6;
126} 126}
127
128message IdMappings {
129 message RoomIds {
130 map<string, uint64> panels = 1;
131 }
132
133 message MapIds {
134 map<string, uint64> doors = 1;
135 map<string, RoomIds> rooms = 2;
136 }
137
138 map<string, MapIds> maps = 1;
139}
diff --git a/tools/assign_ids/CMakeLists.txt b/tools/assign_ids/CMakeLists.txt new file mode 100644 index 0000000..0a9f62d --- /dev/null +++ b/tools/assign_ids/CMakeLists.txt
@@ -0,0 +1,9 @@
1find_package(Protobuf REQUIRED)
2
3add_executable(assign_ids
4 main.cpp
5)
6set_property(TARGET assign_ids PROPERTY CXX_STANDARD 20)
7set_property(TARGET assign_ids PROPERTY CXX_STANDARD_REQUIRED ON)
8target_include_directories(assign_ids PUBLIC ${CMAKE_BINARY_DIR})
9target_link_libraries(assign_ids PUBLIC protos protobuf::libprotobuf)
diff --git a/tools/assign_ids/main.cpp b/tools/assign_ids/main.cpp new file mode 100644 index 0000000..1824c6f --- /dev/null +++ b/tools/assign_ids/main.cpp
@@ -0,0 +1,172 @@
1#include <google/protobuf/message.h>
2#include <google/protobuf/text_format.h>
3
4#include <cstdint>
5#include <fstream>
6#include <iostream>
7#include <map>
8#include <sstream>
9#include <string>
10
11#include "proto/human.pb.h"
12
13namespace com::fourisland::lingo2_archipelago {
14namespace {
15
16template <typename T>
17T ReadMessageFromFile(const std::string& path) {
18 std::cout << "Processing " << path << std::endl;
19
20 std::ifstream file(path);
21 std::stringstream buffer;
22 buffer << file.rdbuf();
23
24 T message;
25 google::protobuf::TextFormat::ParseFromString(buffer.str(), &message);
26
27 return message;
28}
29
30class AssignIds {
31 public:
32 AssignIds(const std::string& mapdir) : mapdir_(mapdir) {}
33
34 void Run() {
35 std::filesystem::path datadir_path = mapdir_;
36 std::filesystem::path ids_path = datadir_path / "ids.txtpb";
37
38 ReadIds(ids_path);
39
40 ProcessMaps(datadir_path);
41
42 WriteIds(ids_path);
43 }
44
45 void ReadIds(std::filesystem::path path) {
46 id_mappings_ = ReadMessageFromFile<IdMappings>(path.string());
47
48 for (const auto& [_, map] : id_mappings_.maps()) {
49 for (const auto& [_, id] : map.doors()) {
50 if (id > next_id_) {
51 next_id_ = id;
52 }
53 }
54
55 for (const auto& [_, room] : map.rooms()) {
56 for (const auto& [_, id] : room.panels()) {
57 if (id > next_id_) {
58 next_id_ = id;
59 }
60 }
61 }
62 }
63
64 next_id_++;
65 }
66
67 void WriteIds(std::filesystem::path path) {
68 std::string output;
69 google::protobuf::TextFormat::PrintToString(id_mappings_, &output);
70
71 {
72 std::ofstream outputfile(path.string());
73 outputfile << output;
74 }
75 }
76
77 void ProcessMaps(std::filesystem::path path) {
78 std::filesystem::path maps_dir = path / "maps";
79 for (auto const& dir_entry :
80 std::filesystem::directory_iterator(maps_dir)) {
81 ProcessMap(dir_entry.path());
82 }
83 }
84
85 void ProcessMap(std::filesystem::path path) {
86 std::string map_name = path.filename();
87
88 ProcessDoorsFile(path / "doors.txtpb", map_name);
89 ProcessRooms(path / "rooms", map_name);
90 }
91
92 void ProcessDoorsFile(std::filesystem::path path,
93 const std::string& current_map_name) {
94 if (!std::filesystem::exists(path)) {
95 return;
96 }
97
98 auto doors = ReadMessageFromFile<HumanDoors>(path.string());
99
100 for (const HumanDoor& door : doors.doors()) {
101 ProcessDoor(door, current_map_name);
102 }
103 }
104
105 void ProcessDoor(const HumanDoor& h_door,
106 const std::string& current_map_name) {
107 if (!id_mappings_.maps().contains(current_map_name) ||
108 !id_mappings_.maps()
109 .at(current_map_name)
110 .doors()
111 .contains(h_door.name())) {
112 auto& maps = *id_mappings_.mutable_maps();
113 auto& doors = *maps[current_map_name].mutable_doors();
114 doors[h_door.name()] = next_id_++;
115 }
116 }
117
118 void ProcessRooms(std::filesystem::path path,
119 const std::string& current_map_name) {
120 for (auto const& dir_entry : std::filesystem::directory_iterator(path)) {
121 auto room = ReadMessageFromFile<HumanRoom>(dir_entry.path().string());
122 ProcessRoom(room, current_map_name);
123 }
124 }
125
126 void ProcessRoom(const HumanRoom& h_room,
127 const std::string& current_map_name) {
128 for (const HumanPanel& h_panel : h_room.panels()) {
129 if (!id_mappings_.maps().contains(current_map_name) ||
130 !id_mappings_.maps()
131 .at(current_map_name)
132 .rooms()
133 .contains(h_room.name()) ||
134 !id_mappings_.maps()
135 .at(current_map_name)
136 .rooms()
137 .at(h_room.name())
138 .panels()
139 .contains(h_panel.name())) {
140 auto& maps = *id_mappings_.mutable_maps();
141 auto& rooms = *maps[current_map_name].mutable_rooms();
142 auto& panels = *rooms[h_room.name()].mutable_panels();
143 panels[h_panel.name()] = next_id_++;
144 }
145 }
146 }
147
148 private:
149 std::string mapdir_;
150
151 uint64_t next_id_ = 0;
152
153 IdMappings id_mappings_;
154};
155
156} // namespace
157} // namespace com::fourisland::lingo2_archipelago
158
159int main(int argc, char** argv) {
160 if (argc != 2) {
161 std::cout << "Incorrect argument count." << std::endl;
162 std::cout << "Usage: assign_ids [path to map directory]" << std::endl;
163 return 1;
164 }
165
166 std::string mapdir = argv[1];
167
168 com::fourisland::lingo2_archipelago::AssignIds assign_ids(mapdir);
169 assign_ids.Run();
170
171 return 0;
172} \ No newline at end of file
diff --git a/tools/datapacker/main.cpp b/tools/datapacker/main.cpp index 1dcd109..4b26141 100644 --- a/tools/datapacker/main.cpp +++ b/tools/datapacker/main.cpp
@@ -42,6 +42,7 @@ class DataPacker {
42 42
43 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt); 43 ProcessConnectionsFile(datadir_path / "connections.txtpb", std::nullopt);
44 ProcessMaps(datadir_path); 44 ProcessMaps(datadir_path);
45 ProcessIdsFile(datadir_path / "ids.txtpb");
45 46
46 { 47 {
47 std::ofstream outputfile(outputpath_); 48 std::ofstream outputfile(outputpath_);
@@ -389,6 +390,26 @@ class DataPacker {
389 } 390 }
390 } 391 }
391 392
393 void ProcessIdsFile(std::filesystem::path path) {
394 auto ids = ReadMessageFromFile<IdMappings>(path.string());
395
396 for (const auto& [map_name, map] : ids.maps()) {
397 for (const auto& [door_name, ap_id] : map.doors()) {
398 uint64_t door_id =
399 container_.FindOrAddDoor(map_name, door_name, std::nullopt);
400 container_.all_objects().mutable_doors(door_id)->set_ap_id(ap_id);
401 }
402
403 for (const auto& [room_name, room] : map.rooms()) {
404 for (const auto& [panel_name, ap_id] : room.panels()) {
405 uint64_t panel_id = container_.FindOrAddPanel(
406 map_name, room_name, panel_name, std::nullopt, std::nullopt);
407 container_.all_objects().mutable_panels(panel_id)->set_ap_id(ap_id);
408 }
409 }
410 }
411 }
412
392 std::string mapdir_; 413 std::string mapdir_;
393 std::string outputpath_; 414 std::string outputpath_;
394 415