LCOV - code coverage report
Current view: top level - src/utils/router - FareModul.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 0.0 % 203 0
Test Date: 2024-10-24 15:46:30 Functions: 0.0 % 11 0

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2002-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    FareModul.h
      15              : /// @author  Ricardo Euler
      16              : /// @date    Thu, 17 August 2018
      17              : ///
      18              : // Fare Modul for calculating prices during intermodal routing
      19              : /****************************************************************************/
      20              : #pragma once
      21              : #include <config.h>
      22              : 
      23              : #include <cassert>
      24              : #include <string>
      25              : #include <vector>
      26              : #include "EffortCalculator.h"
      27              : #include "FareToken.h"
      28              : #include "FareZones.h"
      29              : 
      30              : 
      31              : // ===========================================================================
      32              : // class definitions
      33              : // ===========================================================================
      34              : class ZoneCounter {
      35              : public:
      36              : 
      37            0 :     explicit ZoneCounter(unsigned int ct) :
      38            0 :         myCount(ct) {
      39              : 
      40              :     }
      41              : 
      42            0 :     inline void addZone(int zoneNumber) {
      43            0 :         zoneNumber = getOverlayZone(zoneNumber);
      44            0 :         if (zoneNumber == 0) {
      45              :             return;
      46              :         }
      47            0 :         long long int repNum = fareZoneToRep[zoneNumber];
      48              :         //assert power of 2
      49            0 :         if (bitcount(repNum) == 0) {
      50              :             return;
      51              :         }
      52            0 :         myCount = myCount | repNum;
      53              :     }
      54              : 
      55              : 
      56              :     int numZones() const {
      57            0 :         return bitcount(myCount);
      58              :     }
      59              : 
      60              : 
      61              : private:
      62              :     inline int bitcount(long long int intVal) const {
      63              :         int count = 0;
      64              :         long long int counter = intVal;
      65              : 
      66            0 :         while (counter != 0) {
      67            0 :             counter = counter & (counter - 1);
      68            0 :             ++count;
      69              :         }
      70              :         return count;
      71              :     }
      72              : 
      73              : private:
      74              :     long long int myCount;
      75              : 
      76              : 
      77              : };
      78              : 
      79              : 
      80              : 
      81              : /**
      82              :  * A fare state collects all the information that is necessary to compute the price. Is used as an edge label
      83              :  * in IntermodalRouter
      84              :  */
      85              : struct FareState {
      86              :     friend class FareModul;
      87              : 
      88              : public:
      89              : 
      90              :     /** default constructor for unlabeled edges**/
      91            0 :     explicit  FareState():
      92            0 :         myFareToken(FareToken::None),
      93              :         myCounter(std::numeric_limits<int>::max()),
      94            0 :         myTravelledDistance(std::numeric_limits<double>::max()),
      95            0 :         myVisistedStops(std::numeric_limits<int>::max()),
      96            0 :         myPriceDiff(0) {
      97              :     };
      98              : 
      99              :     /**
     100              :      *
     101              :      * @param token
     102              :      */
     103              :     explicit FareState(FareToken token):
     104              :         myFareToken(token),
     105              :         myCounter(0),
     106              :         myTravelledDistance(0),
     107              :         myVisistedStops(0),
     108              :         myPriceDiff(0) {}
     109              : 
     110              :     /** Destructor **/
     111              :     ~FareState() = default;
     112              : 
     113              :     /**
     114              :      * returns true if fare state is set and not on default
     115              :      * @return if state is set
     116              :      */
     117              :     bool isValid() const {
     118            0 :         return !(myFareToken == FareToken::None);
     119              :     }
     120              : 
     121              : private:
     122              : 
     123              :     /** fare token **/
     124              :     FareToken myFareToken;
     125              :     /** zone counter **/
     126              :     ZoneCounter myCounter;
     127              :     /** travelled distance in km**/
     128              :     double myTravelledDistance;
     129              :     /**num of visited stops**/
     130              :     int myVisistedStops;
     131              :     /** price diff to previous edge **/
     132              :     double myPriceDiff;
     133              : 
     134              : };
     135              : 
     136              : 
     137              : 
     138              : struct Prices {
     139              : 
     140              : 
     141              : 
     142              :     /** Prices for zones **/
     143              :     std::vector<double> zonePrices = std::vector<double> {1.9, 3.4, 4.9, 6.2, 7.7, 9.2};
     144              :     double  halle = 2.3;
     145              :     double leipzig = 2.7;
     146              :     double t1 = 1.5;
     147              :     double t2 = 1.6;
     148              :     double t3 = 1.6;
     149              :     double shortTrip = 1.6;
     150              :     double shortTripLeipzig = 1.9;
     151              :     double shortTripHalle = 1.7;
     152              :     double maxPrice = 10.6;
     153              : };
     154              : 
     155              : 
     156              : /**
     157              :  * The fare modul responsible for calculating prices
     158              :  */
     159              : class FareModul : public EffortCalculator {
     160              : public:
     161              : 
     162              :     /** Constructor ***/
     163            0 :     FareModul() :
     164            0 :         myFareStates()
     165            0 :     {};
     166              : 
     167              :     /**Implementation of EffortCalculator **/
     168            0 :     void init(const std::vector<std::string>& edges) override {
     169            0 :         myEdges = edges;
     170            0 :         myFareStates.resize(edges.size());
     171            0 :     }
     172              : 
     173            0 :     void addStop(const int stopEdge, const Parameterised& params) override {
     174            0 :         myStopFareZone[stopEdge] = StringUtils::toInt(params.getParameter("fareZone"));
     175            0 :         myStopFareToken[stopEdge] = FareUtil::stringToToken(params.getParameter("fareToken"));
     176            0 :         myStopStartToken[stopEdge] = FareUtil::stringToToken(params.getParameter("startToken"));
     177            0 :     }
     178              : 
     179              :     /**Implementation of EffortCalculator **/
     180            0 :     double getEffort(const int numericalID) const override {
     181              :         double  effort = 0;
     182            0 :         FareState const& state =  myFareStates.at(numericalID);
     183            0 :         if (state.isValid()) {
     184            0 :             effort = state.myPriceDiff;
     185              :         } else {
     186              :             effort = std::numeric_limits<double>::max();
     187              :         }
     188            0 :         return effort;
     189              :     }
     190              : 
     191              :     /** Implementation of EffortCalculator **/
     192            0 :     void update(const int edge, const int prev, const double length) override {
     193              : 
     194            0 :         std::string const& edgeType = myEdges[edge];
     195              : 
     196              :         //get propagated fare state
     197            0 :         FareState& state  = myFareStates.at(prev);
     198              : 
     199              :         double oldPr;
     200            0 :         if (state.myFareToken == FareToken::START) {
     201              :             oldPr = 0;
     202              :         } else {
     203            0 :             oldPr = computePrice(state);
     204              :         }
     205              :         //treat  public transport edges
     206            0 :         if (edgeType.c_str()[0] != '!') {
     207              :             updateFareStatePublic(state, edge, length);
     208            0 :         } else if (edgeType ==  "!stop") {
     209            0 :             updateFareStateStop(state, edge);
     210            0 :         } else if (edgeType == "!ped") {
     211              :             updateFareStatePedestrian(state, edge);
     212            0 :         } else if (edgeType == "!access") {
     213            0 :             updateFareStateAccess(state, edge, prev);
     214              :         } else {
     215              :             updateFareState(state, edge);
     216              :         }
     217              :         FareState& stateAtE = myFareStates[edge];
     218            0 :         double newPr = computePrice(stateAtE);
     219            0 :         stateAtE.myPriceDiff = newPr - oldPr;
     220              : 
     221              :         assert(stateAtE.myPriceDiff  >= 0);
     222              : 
     223            0 :     }
     224              : 
     225              :     /** Implementation of EffortCalculator
     226              :      *  _IntermodalEdge should be an Connector Edge  **/
     227            0 :     void setInitialState(const int edge) override {
     228              : //    assert( edge->getLine() == "!connector");
     229              : 
     230            0 :         myFareStates[edge] = FareState(FareToken::START);
     231              : 
     232            0 :     }
     233              : 
     234              : 
     235              : private:
     236              :     /** List of all fare states **/
     237              :     std::vector<FareState> myFareStates;
     238              : 
     239              :     /** List of all edge line attributes **/
     240              :     std::vector<std::string> myEdges;
     241              : 
     242              :     /** the fare zone this stop is a part of **/
     243              :     std::map<int, int> myStopFareZone;
     244              : 
     245              :     /** the faretoken that can be collected at this station **/
     246              :     std::map<int, FareToken> myStopFareToken;
     247              : 
     248              :     /** the faretoken that is used when a trip is started at this station **/
     249              :     std::map<int, FareToken> myStopStartToken;
     250              : 
     251              :     /** List of the prices **/
     252              :     Prices prices;
     253              : 
     254            0 :     double computePrice(FareState const& fareState) const {
     255            0 :         switch (fareState.myFareToken) {
     256            0 :             case FareToken ::H:
     257            0 :                 return prices.halle;
     258            0 :             case FareToken ::L:
     259            0 :                 return prices.leipzig;
     260            0 :             case FareToken ::T1:
     261            0 :                 return prices.t1;
     262            0 :             case FareToken ::T2:
     263            0 :                 return prices.t2;
     264            0 :             case FareToken ::T3:
     265            0 :                 return prices.t3;
     266            0 :             case FareToken::U:
     267            0 :                 return prices.zonePrices[0];
     268            0 :             case FareToken ::Z:
     269            0 :                 return prices.zonePrices[fareState.myCounter.numZones() - 1];
     270            0 :             case FareToken ::M:
     271            0 :                 return prices.maxPrice;
     272            0 :             case FareToken ::K:
     273            0 :                 return prices.shortTrip;
     274            0 :             case FareToken ::KL:
     275              :             case FareToken ::KLZ:
     276              :             case FareToken ::KLU:
     277            0 :                 return prices.shortTripLeipzig;
     278            0 :             case FareToken ::KH:
     279              :             case FareToken ::KHU:
     280              :             case FareToken ::KHZ:
     281            0 :                 return prices.shortTripHalle;
     282              :             case FareToken::Free:
     283              :                 return 1.4;
     284            0 :             case FareToken ::START:
     285            0 :                 return 0;
     286            0 :             case FareToken::ZU:
     287              :             case FareToken::None:
     288              :                 assert(false);
     289              : 
     290              :         }
     291            0 :         return std::numeric_limits<double>::max();
     292              :     }
     293              : 
     294              : 
     295              : 
     296            0 :     std::string output(const int edge) const override {
     297              : 
     298            0 :         FareState const&   my = myFareStates[edge];
     299            0 :         std::stringstream msg;
     300              :         /*
     301              :                 msg << "Final fare state at edge of type: " << myEdges[edge] << std::endl;
     302              :                 msg << "Faretoken" << FareUtil::tokenToString(my.myFareToken) << std::endl;
     303              :                 msg << "Price:" << computePrice(my) << std::endl;
     304              :                 msg << "Zones " << my.myCounter.numZones() << std::endl;
     305              :                 msg << "Stations: " << my.myVisistedStops << std::endl;
     306              :                 msg << "Distance:" << my.myTravelledDistance << std::endl;
     307              :         */
     308            0 :         msg << FareUtil::tokenToTicket(my.myFareToken) << " ";
     309            0 :         if (my.myFareToken == FareToken::Z) {
     310            0 :             msg << my.myCounter.numZones() << " ";
     311            0 :             if (my.myCounter.numZones() == 1) {
     312            0 :                 msg << "Zone";
     313              :             } else {
     314            0 :                 msg << "Zonen";
     315              :             }
     316              : 
     317            0 :         } else if (my.myFareToken == FareToken::U) {
     318            0 :             msg << my.myCounter.numZones() << "1 Zone";
     319              : 
     320              :         }
     321            0 :         msg << ":" << computePrice(my);
     322            0 :         return msg.str();
     323            0 :     }
     324              : 
     325            0 :     void updateFareStateStop(FareState const& currentFareState, const int stopEdge) {
     326              : 
     327            0 :         FareToken  collectedToken = myStopFareToken[stopEdge];
     328              : 
     329              :         //if station has no fare information, just propagate
     330            0 :         if (collectedToken  == FareToken::None) {
     331              :             std::cout << "Propagating fare state for stop w/o a price!" << std::endl;
     332            0 :             return;
     333              :         }
     334              : 
     335              :         FareToken const& token = currentFareState.myFareToken;
     336              : 
     337            0 :         FareState& stateAtE = myFareStates[stopEdge];
     338              : 
     339            0 :         stateAtE = currentFareState;
     340              : 
     341            0 :         stateAtE.myCounter.addZone(myStopFareZone[stopEdge]);
     342              : 
     343            0 :         stateAtE.myVisistedStops++;
     344              : 
     345            0 :         switch (token) {
     346            0 :             case FareToken ::Free:
     347            0 :                 stateAtE.myFareToken = myStopStartToken[stopEdge];
     348            0 :                 break;
     349              :             case FareToken::M :
     350              :                 break;
     351              : 
     352            0 :             case FareToken::Z :
     353            0 :                 if (stateAtE.myCounter.numZones() > 6) {
     354            0 :                     stateAtE.myFareToken = FareToken::M;
     355              :                 }
     356              :                 break;
     357              : 
     358            0 :             case FareToken::T1 :
     359              :             case FareToken::T2 :
     360              :             case FareToken::T3 :
     361            0 :                 if (collectedToken == FareToken::Z) {
     362            0 :                     stateAtE.myFareToken = stateAtE.myTravelledDistance <= 4000 ? FareToken::K : FareToken::Z;
     363              :                 }
     364              :                 break;
     365            0 :             case FareToken::U :
     366            0 :                 if (collectedToken == FareToken::H) {
     367            0 :                     stateAtE.myFareToken = FareToken::H;
     368              :                 }
     369            0 :                 if (collectedToken == FareToken::L) {
     370            0 :                     stateAtE.myFareToken = FareToken::L;
     371              :                 }
     372            0 :                 if (collectedToken == FareToken::Z) {
     373            0 :                     stateAtE.myFareToken = FareToken::Z;
     374              :                 }
     375              :                 break;
     376            0 :             case FareToken::H:
     377              :             case FareToken::L:
     378            0 :                 if (collectedToken == FareToken::Z) {
     379            0 :                     stateAtE.myFareToken = FareToken::Z;
     380              :                 }
     381              :                 break;
     382            0 :             case FareToken::KH:
     383            0 :                 if (stateAtE.myVisistedStops <= 4) {
     384            0 :                     if (collectedToken == FareToken::U) {
     385            0 :                         stateAtE.myFareToken = FareToken::KHU;
     386              :                     }
     387            0 :                     if (collectedToken == FareToken::Z) {
     388            0 :                         stateAtE.myFareToken = FareToken::KHZ;
     389              :                     }
     390              :                 } else {
     391            0 :                     if (collectedToken == FareToken::H) {
     392            0 :                         stateAtE.myFareToken = FareToken ::H;
     393              :                     }
     394            0 :                     if (collectedToken == FareToken::Z) {
     395            0 :                         stateAtE.myFareToken = FareToken ::Z;
     396              :                     }
     397            0 :                     if (collectedToken == FareToken::U) {
     398            0 :                         stateAtE.myFareToken = FareToken ::U;
     399              :                     }
     400              :                 }
     401              :                 break;
     402            0 :             case FareToken::KL:
     403            0 :                 if (stateAtE.myVisistedStops <= 4) {
     404            0 :                     if (collectedToken == FareToken::U) {
     405            0 :                         stateAtE.myFareToken = FareToken::KLU;
     406              :                     }
     407            0 :                     if (collectedToken == FareToken::Z) {
     408            0 :                         stateAtE.myFareToken = FareToken::KLZ;
     409              :                     }
     410              :                 } else {
     411            0 :                     if (collectedToken == FareToken::L) {
     412            0 :                         stateAtE.myFareToken = FareToken ::L;
     413              :                     }
     414            0 :                     if (collectedToken == FareToken::Z) {
     415            0 :                         stateAtE.myFareToken = FareToken ::Z;
     416              :                     }
     417            0 :                     if (collectedToken == FareToken::U) {
     418            0 :                         stateAtE.myFareToken = FareToken ::U;
     419              :                     }
     420              :                 }
     421              :                 break;
     422            0 :             case FareToken::K:
     423            0 :                 if (stateAtE.myTravelledDistance > 4000) {
     424            0 :                     if (collectedToken == FareToken::U) {
     425            0 :                         stateAtE.myFareToken = FareToken ::U;
     426              :                     }
     427            0 :                     if (collectedToken == FareToken::Z) {
     428            0 :                         stateAtE.myFareToken = FareToken ::Z;
     429              :                     }
     430              :                 }
     431              :                 break;
     432            0 :             case FareToken::KHU :
     433              :             case FareToken::KLU :
     434            0 :                 if (stateAtE.myVisistedStops > 4) {
     435            0 :                     if (collectedToken == FareToken::U) {
     436            0 :                         stateAtE.myFareToken = FareToken::U;
     437              :                     }
     438              :                 }
     439              :                 break;
     440              : 
     441            0 :             case FareToken::KLZ:
     442              :             case FareToken::KHZ:
     443            0 :                 if (stateAtE.myVisistedStops > 4) {
     444            0 :                     if (collectedToken == FareToken::Z) {
     445            0 :                         stateAtE.myFareToken = FareToken::Z;
     446              :                     }
     447              :                 }
     448              :                 break;
     449            0 :             case FareToken::ZU :
     450              :                 assert(false);
     451            0 :                 if (collectedToken == FareToken::U) {
     452            0 :                     stateAtE.myFareToken = FareToken::U;
     453              :                 } else {
     454            0 :                     stateAtE.myFareToken = FareToken::Z;
     455              :                 }
     456              : 
     457              :                 break;
     458              :             default:
     459              :                 std::cout << "Reached invalid position in fareToken selection!" << std::endl;
     460              :                 assert(false);
     461              :                 break;
     462              :         }
     463              :     }
     464              : 
     465              :     void updateFareStatePedestrian(FareState const& currentFareState, const int pedestrianEdge) {
     466              : 
     467              :         //only propagates the fare state
     468              :         FareState& stateAtE = myFareStates[pedestrianEdge];
     469              : 
     470            0 :         stateAtE = currentFareState;
     471              : 
     472            0 :         if (currentFareState.myFareToken == FareToken::START) {
     473            0 :             stateAtE.myFareToken = FareToken::Free;
     474              :         }
     475              : 
     476              :     }
     477              : 
     478              : 
     479              :     void updateFareStatePublic(FareState const& currentFareState, const int publicTransportEdge, const double length) {
     480              : 
     481              : 
     482            0 :         if (currentFareState.myFareToken == FareToken::None) {
     483              :             return;
     484              :         }
     485              : 
     486              :         FareState& stateAtE = myFareStates[publicTransportEdge];
     487              : 
     488            0 :         stateAtE = currentFareState;
     489            0 :         stateAtE.myTravelledDistance += length;
     490              :     }
     491              : 
     492              :     void updateFareState(FareState const& currentFareState, const int intermodalEdge) {
     493              : 
     494            0 :         if (currentFareState.myFareToken == FareToken::None) {
     495              :             return;
     496              :         }
     497              : 
     498              :         FareState& stateAtE = myFareStates[intermodalEdge];
     499              : 
     500            0 :         stateAtE = currentFareState;
     501              : 
     502            0 :         if (currentFareState.myFareToken == FareToken::START) {
     503            0 :             stateAtE.myFareToken = FareToken::Free;
     504              :         }
     505              : 
     506              :     }
     507              : 
     508            0 :     void updateFareStateAccess(FareState const& currentFareState, const int accessEdge, const int prev) {
     509              : 
     510              :         FareToken const& token = currentFareState.myFareToken;
     511              : 
     512            0 :         FareState& stateAtE = myFareStates[accessEdge];
     513              : 
     514            0 :         stateAtE = currentFareState;
     515              : 
     516            0 :         if (currentFareState.myFareToken == FareToken::START) {
     517            0 :             stateAtE.myFareToken = FareToken::Free;
     518              :         }
     519              : 
     520            0 :         if (myEdges[prev] == "!ped") {
     521            0 :             switch (token) {
     522              : 
     523              :                 case FareToken::Free ://we have not yet taken public transport
     524              :                     break;
     525            0 :                 case  FareToken::K :
     526            0 :                     if (currentFareState.myCounter.numZones() == 0) {
     527            0 :                         stateAtE.myFareToken = FareToken::U;
     528              :                     } else {
     529            0 :                         stateAtE.myFareToken = FareToken::Z;
     530              :                     }
     531              :                     break;
     532            0 :                 case  FareToken::KH :
     533            0 :                     stateAtE.myFareToken = FareToken::H;
     534            0 :                     break;
     535            0 :                 case  FareToken::KL :
     536            0 :                     stateAtE.myFareToken = FareToken::L;
     537            0 :                     break;
     538            0 :                 case  FareToken::KLU :
     539            0 :                     stateAtE.myFareToken = FareToken::L;
     540            0 :                     break;
     541            0 :                 case  FareToken::KHU:
     542            0 :                     stateAtE.myFareToken = FareToken::H;
     543            0 :                     break;
     544            0 :                 case  FareToken::KLZ :
     545            0 :                     stateAtE.myFareToken = FareToken::Z;
     546            0 :                     break;
     547            0 :                 case  FareToken::KHZ:
     548            0 :                     stateAtE.myFareToken = FareToken::Z;
     549            0 :                     break;
     550              :                 default:
     551              :                     return;
     552              :             }
     553              :         }
     554              : 
     555              :     }
     556              : };
        

Generated by: LCOV version 2.0-1