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