Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // activitygen module
5 : // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
6 : // This program and the accompanying materials are made available under the
7 : // terms of the Eclipse Public License 2.0 which is available at
8 : // https://www.eclipse.org/legal/epl-2.0/
9 : // This Source Code may also be made available under the following Secondary
10 : // Licenses when the conditions for such availability set forth in the Eclipse
11 : // Public License 2.0 are satisfied: GNU General Public License, version 2
12 : // or later which is available at
13 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
14 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
15 : /****************************************************************************/
16 : /// @file AGActivityGenHandler.cpp
17 : /// @author Piotr Woznica
18 : /// @author Daniel Krajzewicz
19 : /// @author Jakob Erdmann
20 : /// @author Michael Behrisch
21 : /// @author Walter Bamberger
22 : /// @date July 2010
23 : ///
24 : // The handler for parsing the statistics file.
25 : /****************************************************************************/
26 : #include <config.h>
27 :
28 : #include "AGActivityGenHandler.h"
29 : #include <iostream>
30 : #include <utility>
31 : #include <map>
32 : #include <string>
33 : #include <utils/options/OptionsCont.h>
34 : #include <utils/common/MsgHandler.h>
35 : #include <utils/common/StringTokenizer.h>
36 : #include <utils/common/UtilExceptions.h>
37 : #include <utils/xml/SUMOSAXHandler.h>
38 : #include <utils/xml/SUMOXMLDefinitions.h>
39 : #include <router/RONet.h>
40 : #include "city/AGCity.h"
41 : #include "city/AGSchool.h"
42 : #include "city/AGPosition.h"
43 : #include "city/AGBusLine.h"
44 :
45 :
46 : // ===========================================================================
47 : // method definitions
48 : // ===========================================================================
49 10 : AGActivityGenHandler::AGActivityGenHandler(AGCity& city, RONet* net)
50 : : SUMOSAXHandler("sumo-stat"),
51 20 : myCity(city), net(net) {}
52 :
53 :
54 10 : AGActivityGenHandler::~AGActivityGenHandler() {}
55 :
56 :
57 : void
58 626 : AGActivityGenHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
59 : try {
60 626 : switch (element) {
61 10 : case AGEN_TAG_GENERAL:
62 10 : parseGeneralCityInfo(attrs);
63 : break;
64 114 : case AGEN_TAG_STREET:
65 114 : parseStreets(attrs);
66 : break;
67 : case AGEN_TAG_WORKHOURS:
68 : parseWorkHours();
69 : break;
70 18 : case AGEN_TAG_OPENING:
71 18 : parseOpeningHour(attrs);
72 : break;
73 27 : case AGEN_TAG_CLOSING:
74 27 : parseClosingHour(attrs);
75 : break;
76 : case AGEN_TAG_SCHOOLS:
77 : parseSchools();
78 : break;
79 12 : case AGEN_TAG_SCHOOL:
80 12 : parseSchool(attrs);
81 : break;
82 126 : case AGEN_TAG_BUSSTATION:
83 126 : parseBusStation(attrs);
84 : break;
85 11 : case AGEN_TAG_BUSLINE:
86 11 : parseBusLine(attrs);
87 : break;
88 : case AGEN_TAG_STATIONS:
89 : parseStations();
90 : break;
91 : case AGEN_TAG_REV_STATIONS:
92 : parseRevStations();
93 : break;
94 140 : case AGEN_TAG_STATION:
95 140 : parseStation(attrs);
96 : break;
97 30 : case AGEN_TAG_FREQUENCY:
98 30 : parseFrequency(attrs);
99 : break;
100 : case AGEN_TAG_POPULATION:
101 : parsePopulation();
102 : break;
103 : /*case AGEN_TAG_CHILD_ACOMP:
104 : parseChildrenAccompaniment();
105 : break;*/
106 30 : case AGEN_TAG_BRACKET:
107 30 : parseBracket(attrs);
108 : break;
109 10 : case AGEN_TAG_PARAM:
110 10 : parseParameters(attrs);
111 : break;
112 6 : case AGEN_TAG_ENTRANCE:
113 6 : parseCityGates(attrs);
114 : break;
115 : default:
116 : break;
117 : }
118 1 : } catch (const std::exception& e) {
119 2 : throw ProcessError(e.what());
120 1 : }
121 625 : }
122 :
123 :
124 : void
125 10 : AGActivityGenHandler::parseGeneralCityInfo(const SUMOSAXAttributes& attrs) {
126 : try {
127 : bool ok;
128 10 : myCity.statData.inhabitants = attrs.getInt(AGEN_ATTR_INHABITANTS);
129 10 : myCity.statData.households = attrs.getInt(AGEN_ATTR_HOUSEHOLDS);
130 10 : myCity.statData.limitAgeChildren = attrs.getOpt<int>(AGEN_ATTR_CHILDREN, nullptr, ok, 18);
131 10 : myCity.statData.limitAgeRetirement = attrs.getOpt<int>(AGEN_ATTR_RETIREMENT, nullptr, ok, 63);
132 10 : myCity.statData.carRate = attrs.getOpt<double>(AGEN_ATTR_CARS, nullptr, ok, 0.58);
133 10 : myCity.statData.unemployement = attrs.getOpt<double>(AGEN_ATTR_UNEMPLOYEMENT, nullptr, ok, 0.06);
134 10 : myCity.statData.laborDemand = attrs.getOpt<double>(AGEN_ATTR_LABORDEMAND, nullptr, ok, 1.05);
135 10 : myCity.statData.maxFootDistance = attrs.getOpt<double>(AGEN_ATTR_MAX_FOOT_DIST, nullptr, ok, 300.0);
136 10 : myCity.statData.incomingTraffic = attrs.getOpt<int>(AGEN_ATTR_IN_TRAFFIC, nullptr, ok, 0);
137 10 : myCity.statData.outgoingTraffic = attrs.getOpt<int>(AGEN_ATTR_OUT_TRAFFIC, nullptr, ok, 0);
138 0 : } catch (const std::exception& e) {
139 0 : WRITE_ERROR("Error while parsing the element " +
140 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_GENERAL) + ": " +
141 : e.what());
142 0 : throw ProcessError();
143 0 : }
144 10 : }
145 :
146 : void
147 10 : AGActivityGenHandler::parseParameters(const SUMOSAXAttributes& attrs) {
148 : try {
149 : bool ok;
150 10 : myCity.statData.carPreference = attrs.getOpt<double>(AGEN_ATTR_CARPREF, nullptr, ok, 0.0);
151 10 : myCity.statData.speedTimePerKm = attrs.getOpt<double>(AGEN_ATTR_CITYSPEED, nullptr, ok, 360.0);
152 10 : myCity.statData.freeTimeActivityRate = attrs.getOpt<double>(AGEN_ATTR_FREETIMERATE, nullptr, ok, 0.15);
153 10 : myCity.statData.uniformRandomTrafficRate = attrs.getOpt<double>(AGEN_ATTR_UNI_RAND_TRAFFIC, nullptr, ok, 0.0);
154 10 : myCity.statData.departureVariation = attrs.getOpt<double>(AGEN_ATTR_DEP_VARIATION, nullptr, ok, 0.0);
155 0 : } catch (const std::exception& e) {
156 0 : WRITE_ERROR("Error while parsing the element " +
157 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_PARAM) + ": " +
158 : e.what());
159 0 : throw ProcessError();
160 0 : }
161 10 : }
162 :
163 : void
164 114 : AGActivityGenHandler::parseStreets(const SUMOSAXAttributes& attrs) {
165 : try {
166 : double pop = 0;
167 : double work = 0;
168 :
169 114 : std::string eid = attrs.getString(SUMO_ATTR_EDGE);
170 114 : if (attrs.hasAttribute(AGEN_ATTR_POPULATION)) {
171 114 : pop = attrs.getFloat(AGEN_ATTR_POPULATION);
172 114 : if (std::isnan(pop)) {
173 : pop = 0;
174 0 : WRITE_WARNINGF(TL("Invalid % value of edge % is treated as zero."), SUMOXMLDefinitions::Attrs.getString(AGEN_ATTR_POPULATION), eid);
175 : }
176 : }
177 114 : if (attrs.hasAttribute(AGEN_ATTR_OUT_WORKPOSITION)) {
178 114 : work = attrs.getFloat(AGEN_ATTR_OUT_WORKPOSITION);
179 114 : if (std::isnan(work)) {
180 : work = 0;
181 0 : WRITE_WARNINGF(TL("Invalid % value of edge % is treated as zero."), SUMOXMLDefinitions::Attrs.getString(AGEN_ATTR_OUT_WORKPOSITION), eid);
182 : }
183 : }
184 114 : AGStreet* street = dynamic_cast<AGStreet*>(net->getEdge(eid));
185 114 : if (street == nullptr) {
186 0 : WRITE_ERRORF(TL("Edge '%' is not known."), eid);
187 : return;
188 : }
189 114 : street->setPopulation(pop * street->getLength());
190 114 : street->setWorkplaceNumber(work * street->getLength());
191 114 : myCity.streets.push_back(street);
192 0 : } catch (const std::exception& e) {
193 0 : WRITE_ERROR("Error while parsing the element " +
194 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_STREET) + ": " +
195 : e.what());
196 0 : throw ProcessError();
197 0 : }
198 : }
199 :
200 : void
201 6 : AGActivityGenHandler::parseCityGates(const SUMOSAXAttributes& attrs) {
202 : try {
203 6 : std::string edge = attrs.getString(SUMO_ATTR_EDGE);
204 6 : double positionOnEdge = attrs.getFloat(SUMO_ATTR_POSITION);
205 6 : AGPosition posi(myCity.getStreet(edge), positionOnEdge);
206 6 : myCity.statData.incoming[(int)myCity.cityGates.size()] = attrs.getFloat(AGEN_ATTR_INCOMING);
207 6 : myCity.statData.outgoing[(int)myCity.cityGates.size()] = attrs.getFloat(AGEN_ATTR_OUTGOING);
208 6 : myCity.cityGates.push_back(posi);
209 :
210 0 : } catch (const std::exception& e) {
211 0 : WRITE_ERROR("Error while parsing the element " +
212 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_CITYGATES) + ": " +
213 : e.what());
214 0 : throw ProcessError();
215 0 : }
216 6 : }
217 :
218 : void
219 0 : AGActivityGenHandler::parseWorkHours() {
220 9 : myCurrentObject = "workHours";
221 9 : }
222 :
223 : void
224 18 : AGActivityGenHandler::parseOpeningHour(const SUMOSAXAttributes& attrs) {
225 18 : if (myCurrentObject == "workHours") {
226 : try {
227 18 : myCity.statData.beginWorkHours[attrs.getInt(AGEN_ATTR_HOUR)] = attrs.getFloat(AGEN_ATTR_PROP);
228 :
229 0 : } catch (const std::exception& e) {
230 0 : WRITE_ERROR("Error while parsing the element " +
231 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_OPENING) + ": "
232 : + e.what());
233 0 : throw ProcessError();
234 0 : }
235 : }
236 18 : }
237 :
238 : void
239 27 : AGActivityGenHandler::parseClosingHour(const SUMOSAXAttributes& attrs) {
240 27 : if (myCurrentObject == "workHours") {
241 : try {
242 27 : myCity.statData.endWorkHours[attrs.getInt(AGEN_ATTR_HOUR)] = attrs.getFloat(AGEN_ATTR_PROP);
243 :
244 0 : } catch (const std::exception& e) {
245 0 : WRITE_ERROR("Error while parsing the element " +
246 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_CLOSING) + ": "
247 : + e.what());
248 0 : throw ProcessError();
249 0 : }
250 : }
251 27 : }
252 :
253 : void
254 0 : AGActivityGenHandler::parseSchools() {
255 4 : myCurrentObject = "schools";
256 4 : }
257 :
258 : void
259 12 : AGActivityGenHandler::parseSchool(const SUMOSAXAttributes& attrs) {
260 : try {
261 12 : bool ok = true;
262 12 : std::string edge = attrs.getString(SUMO_ATTR_EDGE, &ok);
263 12 : if (!ok) {
264 0 : throw ProcessError("Cannot parse edge attribute");
265 : }
266 12 : double positionOnEdge = attrs.hasAttribute(SUMO_ATTR_POSITION) ? attrs.getFloat(SUMO_ATTR_POSITION) : 0.;
267 12 : AGPosition posi(myCity.getStreet(edge), positionOnEdge);
268 12 : int beginAge = attrs.getInt(AGEN_ATTR_BEGINAGE);
269 12 : int endAge = attrs.getInt(AGEN_ATTR_ENDAGE);
270 12 : int capacity = attrs.getInt(AGEN_ATTR_CAPACITY);
271 12 : int openingHour = attrs.getInt(AGEN_ATTR_OPENING);
272 12 : int closingHour = attrs.getInt(AGEN_ATTR_CLOSING);
273 12 : AGSchool sch(capacity, posi, beginAge, endAge, openingHour, closingHour);
274 12 : myCity.schools.push_back(sch);
275 :
276 0 : } catch (const std::exception& e) {
277 0 : WRITE_ERROR("Error while parsing the element " +
278 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_SCHOOL) + ": " +
279 : e.what());
280 0 : throw ProcessError();
281 0 : }
282 12 : }
283 :
284 : void
285 126 : AGActivityGenHandler::parseBusStation(const SUMOSAXAttributes& attrs) {
286 : try {
287 126 : bool ok = true;
288 126 : std::string edge = attrs.getString(SUMO_ATTR_EDGE, &ok);
289 126 : if (!ok) {
290 0 : throw ProcessError("Cannot parse edge attribute");
291 : };
292 126 : double positionOnEdge = attrs.hasAttribute(SUMO_ATTR_POSITION) ? attrs.getFloat(SUMO_ATTR_POSITION) : 0.;
293 126 : int id = attrs.getInt(SUMO_ATTR_ID);
294 126 : AGPosition posi(myCity.getStreet(edge), positionOnEdge);
295 126 : myCity.statData.busStations.insert(std::pair<int, AGPosition>(id, posi));
296 :
297 0 : } catch (const std::exception& e) {
298 0 : WRITE_ERROR("Error while parsing the element " +
299 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BUSSTATION) + ": " +
300 : e.what());
301 0 : throw ProcessError();
302 0 : }
303 126 : }
304 :
305 : void
306 11 : AGActivityGenHandler::parseBusLine(const SUMOSAXAttributes& attrs) {
307 : try {
308 11 : myCurrentObject = "busLine";
309 11 : AGBusLine busL(attrs.getString(SUMO_ATTR_ID));
310 11 : busL.setMaxTripTime(attrs.getInt(AGEN_ATTR_MAX_TRIP_DURATION));
311 11 : myCity.busLines.push_front(busL);
312 11 : currentBusLine = &*myCity.busLines.begin();
313 :
314 11 : } catch (const std::exception& e) {
315 0 : WRITE_ERROR("Error while parsing the element " +
316 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BUSLINE) + ": " +
317 : e.what());
318 0 : throw ProcessError();
319 0 : }
320 11 : }
321 :
322 : void
323 0 : AGActivityGenHandler::parseStations() {
324 11 : isRevStation = false;
325 11 : }
326 :
327 : void
328 0 : AGActivityGenHandler::parseRevStations() {
329 11 : isRevStation = true;
330 11 : }
331 :
332 : void
333 140 : AGActivityGenHandler::parseStation(const SUMOSAXAttributes& attrs) {
334 140 : if (myCurrentObject != "busLine") {
335 : return;
336 : }
337 :
338 : try {
339 140 : bool ok = true;
340 140 : int refID = attrs.get<int>(SUMO_ATTR_REFID, myCurrentObject.c_str(), ok);
341 140 : if (!ok) {
342 0 : throw ProcessError();
343 : }
344 140 : if (myCity.statData.busStations.count(refID) == 0) {
345 0 : throw ProcessError(TLF("Unknown bus station '%'.", refID));
346 : }
347 140 : if (!isRevStation) {
348 140 : currentBusLine->locateStation(myCity.statData.busStations.find(refID)->second);
349 : } else {
350 140 : currentBusLine->locateRevStation(myCity.statData.busStations.find(refID)->second);
351 : }
352 :
353 0 : } catch (const std::exception& e) {
354 0 : WRITE_ERROR("Error while parsing the element " +
355 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_STATION) + ": " +
356 : e.what());
357 0 : throw ProcessError();
358 0 : }
359 : }
360 :
361 : void
362 30 : AGActivityGenHandler::parseFrequency(const SUMOSAXAttributes& attrs) {
363 30 : if (myCurrentObject != "busLine") {
364 : return;
365 : }
366 :
367 : try {
368 30 : int beginB = attrs.getInt(SUMO_ATTR_BEGIN);
369 30 : int endB = attrs.getInt(SUMO_ATTR_END);
370 30 : int rateB = attrs.getInt(AGEN_ATTR_RATE);
371 30 : currentBusLine->generateBuses(beginB, endB, rateB);
372 :
373 0 : } catch (const std::exception& e) {
374 0 : WRITE_ERROR("Error while parsing the element " +
375 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_FREQUENCY) + ": " +
376 : e.what());
377 0 : throw ProcessError();
378 0 : }
379 : }
380 :
381 : void
382 0 : AGActivityGenHandler::parsePopulation() {
383 10 : myCurrentObject = "population";
384 10 : }
385 :
386 : void
387 30 : AGActivityGenHandler::parseBracket(const SUMOSAXAttributes& attrs) {
388 : try {
389 :
390 30 : int beginAge = attrs.getInt(AGEN_ATTR_BEGINAGE); //included in the bracket
391 30 : int endAge = attrs.getInt(AGEN_ATTR_ENDAGE); //NOT included in the bracket
392 : bool overlapping = false;
393 : // evaluate age
394 30 : if (beginAge < endAge) {
395 60 : for (auto it = myCity.statData.ageSpan.begin(); it != myCity.statData.ageSpan.end(); ++it) {
396 30 : if (!(beginAge >= it->second || endAge <= it->first)) {
397 : overlapping = true;
398 : }
399 : }
400 30 : if (!overlapping) {
401 29 : myCity.statData.ageSpan[beginAge] = endAge;
402 :
403 29 : if (myCurrentObject == "population") {
404 29 : myCity.statData.population[endAge] = attrs.getInt(AGEN_ATTR_PEOPLENBR);
405 : }
406 : } else {
407 2 : WRITE_ERROR("Error while parsing the element " +
408 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": begin and end age of the population is overlapping");
409 1 : throw ProcessError();
410 : }
411 : } else {
412 0 : WRITE_ERROR("Error while parsing the element " +
413 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": begin and end age of the population are not properly set");
414 0 : throw ProcessError();
415 : }
416 :
417 1 : } catch (const std::exception& e) {
418 2 : WRITE_ERROR("Error while parsing the element " +
419 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": " +
420 : e.what());
421 1 : throw ProcessError();
422 1 : }
423 29 : }
424 :
425 :
426 : /****************************************************************************/
|