LCOV - code coverage report
Current view: top level - src/activitygen/activities - AGFreeTime.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 102 102 100.0 %
Date: 2024-04-27 15:34:54 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2010-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    AGFreeTime.cpp
      17             : /// @author  Piotr Woznica
      18             : /// @author  Daniel Krajzewicz
      19             : /// @author  Walter Bamberger
      20             : /// @author  Michael Behrisch
      21             : /// @date    July 2010
      22             : ///
      23             : // Generates trips related to after-work activities
      24             : // like visiting the family or party.
      25             : /****************************************************************************/
      26             : #include <config.h>
      27             : 
      28             : #include <cmath>
      29             : #include <utils/common/RandHelper.h>
      30             : #include <utils/common/StdDefs.h>
      31             : #include <activitygen/city/AGCity.h>
      32             : #include <activitygen/city/AGTime.h>
      33             : #include "AGFreeTime.h"
      34             : 
      35             : 
      36             : // ===========================================================================
      37             : // static member definitions
      38             : // ===========================================================================
      39             : const int AGFreeTime::DAY = 1;
      40             : const int AGFreeTime::EVENING = 2;
      41             : const int AGFreeTime::NIGHT = 4;
      42             : 
      43             : const int AGFreeTime::TB_DAY = AGTime(0, 8, 0).getTime();
      44             : const int AGFreeTime::TE_DAY = AGTime(0, 18, 0).getTime();
      45             : const int AGFreeTime::TB_EVENING = AGTime(0, 19, 0).getTime();
      46             : const int AGFreeTime::TE_EVENING = AGTime(0, 23, 59).getTime();
      47             : const int AGFreeTime::TB_NIGHT = AGTime(0, 23, 0).getTime();
      48             : const int AGFreeTime::TE_NIGHT = AGTime(1, 5, 0).getTime();
      49             : 
      50             : 
      51             : // ===========================================================================
      52             : // method definitions
      53             : // ===========================================================================
      54             : int
      55        3011 : AGFreeTime::decideTypeOfTrip() {
      56        3011 :     if (myHousehold->getAdults().front().decide(freqOut)) {
      57             :         int num_poss = 0; //(possibleType % 2) + (possibleType / 4) + ((possibleType / 2) % 2);
      58         454 :         if (possibleType & DAY) {
      59             :             ++num_poss;
      60             :         }
      61         454 :         if (possibleType & EVENING) {
      62         454 :             ++num_poss;
      63             :         }
      64         454 :         if (possibleType & NIGHT) {
      65          94 :             ++num_poss;
      66             :         }
      67             : 
      68         454 :         if (num_poss == 0) {
      69             :             return 0;
      70             :         }
      71         454 :         double alea = RandHelper::rand(); //(float)(rand() % 1000) / 1000.0;
      72         454 :         int decision = (int)floor(alea * (double)num_poss);
      73             : 
      74         454 :         if (possibleType & DAY) {
      75         122 :             if (decision == 0) {
      76             :                 return DAY;
      77             :             } else {
      78          58 :                 --decision;
      79             :             }
      80             :         }
      81         390 :         if (possibleType & EVENING) {
      82         390 :             if (decision == 0) {
      83             :                 return EVENING;
      84             :             } else {
      85          50 :                 --decision;
      86             :             }
      87             :         }
      88          50 :         if (possibleType & NIGHT) {
      89          50 :             if (decision == 0) {
      90          50 :                 return NIGHT;
      91             :             }
      92             :         }
      93             :     }
      94             :     return 0;
      95             : }
      96             : 
      97             : int
      98        1506 : AGFreeTime::possibleTypeOfTrip() {
      99             :     int val = 0;
     100        1506 :     if (myHousehold->getAdults().front().getAge() >= myStatData->limitAgeRetirement && tReady == 0) {
     101             :         val += DAY + EVENING;
     102             :     } else {
     103        1072 :         if (myHousehold->getPeopleNbr() > myHousehold->getAdultNbr()) {
     104             :             val += NIGHT;
     105             :         }
     106             : 
     107             :         std::list<AGAdult>::const_iterator itA;
     108             :         bool noBodyWorks = true;
     109        2799 :         for (itA = myHousehold->getAdults().begin(); itA != myHousehold->getAdults().end(); ++itA) {
     110        1727 :             if (itA->isWorking()) {
     111             :                 noBodyWorks = false;
     112             :             }
     113             :         }
     114        1072 :         if (noBodyWorks) {
     115          25 :             val += DAY;
     116             :         }
     117             : 
     118        1072 :         if (tReady < AGTime(0, 22, 0).getTime()) {
     119        1072 :             val += EVENING;
     120             :         }
     121             :     }
     122        1506 :     return val;
     123             : }
     124             : 
     125             : bool
     126          64 : AGFreeTime::typeFromHomeDay(int day) {
     127          64 :     int backHome = whenBackHomeThisDay(day);
     128          64 :     if (myHousehold->getCars().empty()) {
     129             :         return true;
     130             :     }
     131          51 :     AGPosition destination(myHousehold->getTheCity()->getRandomStreet());
     132          50 :     int depTime = randomTimeBetween(MAX2(backHome, TB_DAY), (TB_DAY + TE_DAY) / 2);
     133          50 :     int arrTime = this->arrHour(myHousehold->getPosition(), destination, depTime);
     134          50 :     int retTime = randomTimeBetween(arrTime, TE_DAY);
     135          50 :     if (depTime < 0 || retTime < 0) {
     136             :         return true;    // not enough time during the day
     137             :     }
     138          50 :     AGTrip depTrip(myHousehold->getPosition(), destination, myHousehold->getCars().front().getName(), depTime, day);
     139          50 :     AGTrip retTrip(destination, myHousehold->getPosition(), myHousehold->getCars().front().getName(), retTime, day);
     140             : 
     141          50 :     myPartialActivityTrips.push_back(depTrip);
     142             :     myPartialActivityTrips.push_back(retTrip);
     143             :     return true;
     144          50 : }
     145             : 
     146             : bool
     147         340 : AGFreeTime::typeFromHomeEvening(int day) {
     148         340 :     int backHome = whenBackHomeThisDay(day);
     149         340 :     if (myHousehold->getCars().empty()) {
     150             :         return true;
     151             :     }
     152         235 :     AGPosition destination(myHousehold->getTheCity()->getRandomStreet());
     153         235 :     int depTime = randomTimeBetween(MAX2(backHome, TB_EVENING), TE_EVENING);
     154         235 :     int arrTime = this->arrHour(myHousehold->getPosition(), destination, depTime);
     155         235 :     int retTime = randomTimeBetween(arrTime, TE_EVENING);
     156         235 :     if (depTime < 0 || retTime < 0) {
     157             :         return true;    // not enough time during the day
     158             :     }
     159         235 :     AGTrip depTrip(myHousehold->getPosition(), destination, myHousehold->getCars().front().getName(), depTime, day);
     160         235 :     AGTrip retTrip(destination, myHousehold->getPosition(), myHousehold->getCars().front().getName(), retTime, day);
     161             : 
     162         235 :     myPartialActivityTrips.push_back(depTrip);
     163             :     myPartialActivityTrips.push_back(retTrip);
     164             :     return true;
     165         235 : }
     166             : 
     167             : bool
     168          50 : AGFreeTime::typeFromHomeNight(int day) {
     169          50 :     int backHome = whenBackHomeThisDay(day);
     170          50 :     int ActivitiesNextDay = whenBeginActivityNextDay(day); // is equal to 2 days if there is nothing the next day
     171             :     int nextDay = 0;
     172          50 :     if (myHousehold->getCars().empty()) {
     173             :         return true;
     174             :     }
     175          41 :     AGPosition destination(myHousehold->getTheCity()->getRandomStreet());
     176             : 
     177          41 :     int depTime = randomTimeBetween(MAX2(backHome, TB_NIGHT), TE_NIGHT);
     178          41 :     int arrTime = this->arrHour(myHousehold->getPosition(), destination, depTime);
     179             :     //we have to go back home before the beginning of next day activities.
     180          41 :     int lastRetTime = this->depHour(destination, myHousehold->getPosition(), MIN2(TE_NIGHT, ActivitiesNextDay));
     181          41 :     int retTime = randomTimeBetween(arrTime, lastRetTime);
     182          41 :     if (depTime < 0 || retTime < 0) {
     183             :         return true;    // not enough time during the day
     184             :     }
     185             : 
     186             :     AGTime departureTime(depTime);
     187          41 :     nextDay = departureTime.getDay();
     188          41 :     departureTime.setDay(0);
     189          41 :     AGTrip depTrip(myHousehold->getPosition(), destination, myHousehold->getCars().front().getName(), departureTime.getTime(), day + nextDay);
     190             : 
     191             :     AGTime returnTime(depTime);
     192          41 :     nextDay = returnTime.getDay();
     193          41 :     returnTime.setDay(0);
     194          41 :     AGTrip retTrip(destination, myHousehold->getPosition(), myHousehold->getCars().front().getName(), returnTime.getTime(), day + nextDay);
     195             : 
     196          41 :     myPartialActivityTrips.push_back(depTrip);
     197             :     myPartialActivityTrips.push_back(retTrip);
     198             :     return true;
     199          41 : }
     200             : 
     201             : bool
     202        1506 : AGFreeTime::generateTrips() {
     203        1506 :     tReady = whenBackHome();
     204        1506 :     possibleType = possibleTypeOfTrip();
     205             :     int type;
     206             : 
     207        4516 :     for (int day = 1; day <= nbrDays; ++day) {
     208        3011 :         type = decideTypeOfTrip();
     209        3011 :         if (type == 0) {
     210        2557 :             continue;
     211         454 :         } else if (type == DAY) {
     212          64 :             if (!typeFromHomeDay(day)) {
     213             :                 return false;
     214             :             }
     215         390 :         } else if (type == EVENING) {
     216         340 :             if (!typeFromHomeEvening(day)) {
     217             :                 return false;
     218             :             }
     219          50 :         } else if (type == NIGHT) {
     220          50 :             if (!typeFromHomeNight(day)) {
     221             :                 return false;
     222             :             }
     223             :         }
     224             :     }
     225        1505 :     genDone = true;
     226        1505 :     return genDone;
     227             : }
     228             : 
     229             : int
     230        1506 : AGFreeTime::whenBackHome() {
     231             :     int timeBack = 0;
     232        2688 :     for (std::list<AGTrip>::iterator itT = myPreviousTrips->begin(); itT != myPreviousTrips->end(); ++itT) {
     233        1182 :         if (timeBack < itT->getArrTime(this->timePerKm) && itT->isDaily()) {
     234        1105 :             timeBack = itT->getArrTime(this->timePerKm);
     235             :         }
     236             :     }
     237        1506 :     return timeBack;
     238             : }
     239             : 
     240             : int
     241         454 : AGFreeTime::whenBackHomeThisDay(int day) {
     242             :     int timeBack = 0;
     243         829 :     for (std::list<AGTrip>::iterator itT = myPreviousTrips->begin(); itT != myPreviousTrips->end(); ++itT) {
     244         375 :         if (timeBack < itT->getArrTime(this->timePerKm) && (itT->getDay() == day || itT->isDaily())) {
     245         352 :             timeBack = itT->getArrTime(this->timePerKm);
     246             :         }
     247             :     }
     248         454 :     return timeBack;
     249             : }
     250             : 
     251             : int
     252          50 : AGFreeTime::whenBeginActivityNextDay(int day) {
     253             :     AGTime timeBack(1, 0, 0);
     254         136 :     for (std::list<AGTrip>::iterator itT = myPreviousTrips->begin(); itT != myPreviousTrips->end(); ++itT) {
     255          86 :         if (timeBack.getTime() > itT->getTime() && (itT->getDay() == (day + 1) || itT->isDaily())) {
     256          38 :             timeBack.setTime(itT->getTime());
     257             :         }
     258             :     }
     259          50 :     timeBack.addDays(1); // this the beginning of activities of the next day
     260          50 :     return timeBack.getTime();
     261             : }
     262             : 
     263             : 
     264             : /****************************************************************************/

Generated by: LCOV version 1.14