LCOV - code coverage report
Current view: top level - src/activitygen - AGActivityGenHandler.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 150 205 73.2 %
Date: 2024-05-01 15:34:42 Functions: 15 21 71.4 %

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

Generated by: LCOV version 1.14