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 : std::string edge = attrs.getString(SUMO_ATTR_EDGE);
262 12 : double positionOnEdge = attrs.getFloat(SUMO_ATTR_POSITION);
263 12 : AGPosition posi(myCity.getStreet(edge), positionOnEdge);
264 12 : int beginAge = attrs.getInt(AGEN_ATTR_BEGINAGE);
265 12 : int endAge = attrs.getInt(AGEN_ATTR_ENDAGE);
266 12 : int capacity = attrs.getInt(AGEN_ATTR_CAPACITY);
267 12 : int openingHour = attrs.getInt(AGEN_ATTR_OPENING);
268 12 : int closingHour = attrs.getInt(AGEN_ATTR_CLOSING);
269 12 : AGSchool sch(capacity, posi, beginAge, endAge, openingHour, closingHour);
270 12 : myCity.schools.push_back(sch);
271 :
272 0 : } catch (const std::exception& e) {
273 0 : WRITE_ERROR("Error while parsing the element " +
274 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_SCHOOL) + ": " +
275 : e.what());
276 0 : throw ProcessError();
277 0 : }
278 12 : }
279 :
280 : void
281 126 : AGActivityGenHandler::parseBusStation(const SUMOSAXAttributes& attrs) {
282 : try {
283 126 : std::string edge = attrs.getString(SUMO_ATTR_EDGE);
284 126 : double positionOnEdge = attrs.getFloat(SUMO_ATTR_POSITION);
285 126 : int id = attrs.getInt(SUMO_ATTR_ID);
286 126 : AGPosition posi(myCity.getStreet(edge), positionOnEdge);
287 126 : myCity.statData.busStations.insert(std::pair<int, AGPosition>(id, posi));
288 :
289 0 : } catch (const std::exception& e) {
290 0 : WRITE_ERROR("Error while parsing the element " +
291 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BUSSTATION) + ": " +
292 : e.what());
293 0 : throw ProcessError();
294 0 : }
295 126 : }
296 :
297 : void
298 11 : AGActivityGenHandler::parseBusLine(const SUMOSAXAttributes& attrs) {
299 : try {
300 11 : myCurrentObject = "busLine";
301 11 : AGBusLine busL(attrs.getString(SUMO_ATTR_ID));
302 11 : busL.setMaxTripTime(attrs.getInt(AGEN_ATTR_MAX_TRIP_DURATION));
303 11 : myCity.busLines.push_front(busL);
304 11 : currentBusLine = &*myCity.busLines.begin();
305 :
306 11 : } catch (const std::exception& e) {
307 0 : WRITE_ERROR("Error while parsing the element " +
308 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BUSLINE) + ": " +
309 : e.what());
310 0 : throw ProcessError();
311 0 : }
312 11 : }
313 :
314 : void
315 0 : AGActivityGenHandler::parseStations() {
316 11 : isRevStation = false;
317 11 : }
318 :
319 : void
320 0 : AGActivityGenHandler::parseRevStations() {
321 11 : isRevStation = true;
322 11 : }
323 :
324 : void
325 140 : AGActivityGenHandler::parseStation(const SUMOSAXAttributes& attrs) {
326 140 : if (myCurrentObject != "busLine") {
327 : return;
328 : }
329 :
330 : try {
331 140 : bool ok = true;
332 140 : int refID = attrs.get<int>(SUMO_ATTR_REFID, myCurrentObject.c_str(), ok);
333 140 : if (!ok) {
334 0 : throw ProcessError();
335 : }
336 140 : if (myCity.statData.busStations.count(refID) == 0) {
337 0 : throw ProcessError(TLF("Unknown bus station '%'.", refID));
338 : }
339 140 : if (!isRevStation) {
340 140 : currentBusLine->locateStation(myCity.statData.busStations.find(refID)->second);
341 : } else {
342 140 : currentBusLine->locateRevStation(myCity.statData.busStations.find(refID)->second);
343 : }
344 :
345 0 : } catch (const std::exception& e) {
346 0 : WRITE_ERROR("Error while parsing the element " +
347 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_STATION) + ": " +
348 : e.what());
349 0 : throw ProcessError();
350 0 : }
351 : }
352 :
353 : void
354 30 : AGActivityGenHandler::parseFrequency(const SUMOSAXAttributes& attrs) {
355 30 : if (myCurrentObject != "busLine") {
356 : return;
357 : }
358 :
359 : try {
360 30 : int beginB = attrs.getInt(SUMO_ATTR_BEGIN);
361 30 : int endB = attrs.getInt(SUMO_ATTR_END);
362 30 : int rateB = attrs.getInt(AGEN_ATTR_RATE);
363 30 : currentBusLine->generateBuses(beginB, endB, rateB);
364 :
365 0 : } catch (const std::exception& e) {
366 0 : WRITE_ERROR("Error while parsing the element " +
367 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_FREQUENCY) + ": " +
368 : e.what());
369 0 : throw ProcessError();
370 0 : }
371 : }
372 :
373 : void
374 0 : AGActivityGenHandler::parsePopulation() {
375 10 : myCurrentObject = "population";
376 10 : }
377 :
378 : void
379 30 : AGActivityGenHandler::parseBracket(const SUMOSAXAttributes& attrs) {
380 : try {
381 :
382 30 : int beginAge = attrs.getInt(AGEN_ATTR_BEGINAGE); //included in the bracket
383 30 : int endAge = attrs.getInt(AGEN_ATTR_ENDAGE); //NOT included in the bracket
384 : bool overlapping = false;
385 : // evaluate age
386 30 : if (beginAge < endAge) {
387 60 : for (auto it = myCity.statData.ageSpan.begin(); it != myCity.statData.ageSpan.end(); ++it) {
388 30 : if (!(beginAge >= it->second || endAge <= it->first)) {
389 : overlapping = true;
390 : }
391 : }
392 30 : if (!overlapping) {
393 29 : myCity.statData.ageSpan[beginAge] = endAge;
394 :
395 29 : if (myCurrentObject == "population") {
396 29 : myCity.statData.population[endAge] = attrs.getInt(AGEN_ATTR_PEOPLENBR);
397 : }
398 : } else {
399 2 : WRITE_ERROR("Error while parsing the element " +
400 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": begin and end age of the population is overlapping");
401 1 : throw ProcessError();
402 : }
403 : } else {
404 0 : WRITE_ERROR("Error while parsing the element " +
405 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": begin and end age of the population are not properly set");
406 0 : throw ProcessError();
407 : }
408 :
409 1 : } catch (const std::exception& e) {
410 2 : WRITE_ERROR("Error while parsing the element " +
411 : SUMOXMLDefinitions::Tags.getString(AGEN_TAG_BRACKET) + ": " +
412 : e.what());
413 1 : throw ProcessError();
414 1 : }
415 29 : }
416 :
417 :
418 : /****************************************************************************/
|