LCOV - code coverage report
Current view: top level - src/activitygen - AGActivityGenHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 73.0 % 211 154
Test Date: 2024-12-21 15:45:41 Functions: 71.4 % 21 15

            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              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1