SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AGWorkAndSchool.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // Generates trips to work and to school
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
14 // activitygen module
15 // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include "AGWorkAndSchool.h"
37 #include <list>
38 #include "../city/AGCar.h"
39 
40 
41 // ===========================================================================
42 // method definitions
43 // ===========================================================================
44 bool
46  //buildDestinations();
47  // generation of the waiting list for the accompaniment
49 
51 
52  if (myHousehold->getCarNbr() < (int)personsDrivingCars.size()) {
53  return false; //to rebuild the household
54  }
55  if (childrenNeedingCarAccompaniment.size() != 0 && myHousehold->getCarNbr() == 0) {
56  return false; //to rebuild the household
57  }
58  if (adultNeedingCarAccompaniment.size() != 0 && myHousehold->getCarNbr() == 0) {
59  return false;
60  }
61 
62  carAllocation();
63 
64  if (personsDrivingCars.empty() && notNeedingDrivers.empty()) {
65  genDone = true;
66  return true; // no trip to generate
67  }
68 
69  if (! carsToTrips()) {
70  return false;
71  }
72 
73  genDone = true;
74  return true;
75 }
76 
77 void
79  std::list<AGChild>::const_iterator itC;
80  for (itC = myHousehold->getChildren().begin(); itC != myHousehold->getChildren().end(); ++itC) {
81  if (itC->haveASchool()) {
82  if (this->availableTranspMeans(myHousehold->getPosition(), itC->getSchoolLocation()) == 0) {
83  //in this case the school is far from home and bus stations too
84  this->childrenNeedingCarAccompaniment.push_back(*itC);
85  }
86  }
87  }
88 }
89 
90 void
92  std::list<AGAdult>::const_iterator itA;
93  for (itA = myHousehold->getAdults().begin(); itA != myHousehold->getAdults().end(); ++itA) {
94  if (itA->isWorking()) {
95  if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) % 2 == 0) {
96  //not too close, to not being able to go by foot
97  if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) > 4) {
98  //too far from home ==> Car or Bus AND Car and bus are possible
99  workingPeoplePossCar.push_back(*itA);
100  } else if (this->possibleTranspMean(itA->getWorkPosition().getPosition()) == 4) {
101  //only the car is possible (and there is one (use of possibleTranspMean))
102  if (myHousehold->getCarNbr() > (int)personsDrivingCars.size()) {
103  personsDrivingCars.push_back(*itA);
104  } else {
105  adultNeedingCarAccompaniment.push_back(*itA);
106  }
107  }
108  }
109  }
110  }
111 
112  // sometimes, people still have choice: when vehicles are available and their car take a bus.
113  std::list<AGAdult>::iterator it;
114  for (it = workingPeoplePossCar.begin(); it != workingPeoplePossCar.end(); ++it) {
115  if (possibleTranspMean(it->getWorkPosition().getPosition()) == 6 && myHousehold->getCarNbr() > (int)personsDrivingCars.size()) {
116  //car or bus (always because of workDestinations' construction) AND at least one car not used
117  if (myHousehold->getAdults().front().decide(this->carPreference)) {
118  personsDrivingCars.push_back(*it);
119  }
120  }
121  }
122 }
123 
124 void
126  // only two adults are possibles: no car, 1 car, 2 cars and more
127  // the only choice case: 1 car / 2 adults needing this car (otherwise no choice problems)
128  if (! personsDrivingCars.empty() && ! adultNeedingCarAccompaniment.empty()) {
129  //in that case there is only one element in each list and only one car.
130  if (adultNeedingCarAccompaniment.front().getWorkPosition().getOpening() >= personsDrivingCars.front().getWorkPosition().getOpening()) {
131  //we will invert the driver and the accompanied
133  adultNeedingCarAccompaniment.pop_front();
135  personsDrivingCars.pop_front();
136  }
137  }
138  if (personsDrivingCars.empty() && ! childrenNeedingCarAccompaniment.empty()) {
139  //at least one adult exists because no household contains less than one adult
140  if (workingPeoplePossCar.size() != myHousehold->getAdultNbr()) { //personsDrivingCars.size() + adultNeedingCarAccompaniment.size() is equal to 0
141  std::list<AGAdult>::const_iterator itUA;
142  for (itUA = myHousehold->getAdults().begin(); itUA != myHousehold->getAdults().end(); ++itUA) {
143  if (! itUA->isWorking()) {
144  notNeedingDrivers.push_back(*itUA);
145  break;
146  }
147  }
148  } else {
149  personsDrivingCars.push_back(workingPeoplePossCar.front());
150  workingPeoplePossCar.pop_front();
151  }
152  }
153 }
154 
155 bool
157  std::list<AGAdult>::const_iterator itDriA;
158  std::list<AGCar>::const_iterator itCar = myHousehold->getCars().begin();
159  for (itDriA = personsDrivingCars.begin(); itDriA != personsDrivingCars.end(); ++itDriA) {
160  //check if the number of cars is lower than the number of drivers
161  if (itCar == myHousehold->getCars().end()) {
162  return false;
163  }
164  AGTrip trip(myHousehold->getPosition(), itDriA->getWorkPosition().getPosition(), *itCar, depHour(myHousehold->getPosition(), itDriA->getWorkPosition().getPosition(), itDriA->getWorkPosition().getOpening()));
165  ++itCar;
166  tempTrip.push_back(trip);
167  }
168 
169  std::list<AGAdult>::iterator itAccA;
170  for (itAccA = adultNeedingCarAccompaniment.begin(); itAccA != adultNeedingCarAccompaniment.end(); ++itAccA) {
171  AGTrip trip(myHousehold->getPosition(), itAccA->getWorkPosition().getPosition(), depHour(myHousehold->getPosition(), itAccA->getWorkPosition().getPosition(), itAccA->getWorkPosition().getOpening()));
172  tempAccTrip.push_back(trip);
173  }
174 
175  std::list<AGChild>::iterator itAccC;
176  for (itAccC = childrenNeedingCarAccompaniment.begin(); itAccC != childrenNeedingCarAccompaniment.end(); ++itAccC) {
177  AGTrip trip(myHousehold->getPosition(), itAccC->getSchoolLocation(), depHour(myHousehold->getPosition(), itAccC->getSchoolLocation(), itAccC->getSchoolOpening()));
178  tempAccTrip.push_back(trip);
179  }
180 
184  }
185 
187  return true;
188 }
189 
190 bool
192  return (myHousehold->getCarNbr() > static_cast<int>(notNeedingDrivers.size() + personsDrivingCars.size()));
193 }
194 
195 bool
197  bool finish = false;
198  int diff1, diff2;
199  int arrTime;
200  std::list<AGTrip>::iterator it1, it2;
201 
202  while (!finish) {
203  finish = true;
204  for (it1 = tempAccTrip.begin(); it1 != tempAccTrip.end(); ++it1) {
205  for (it2 = tempAccTrip.begin(); it2 != tempAccTrip.end(); ++it2) {
206  if (it1 == it2) {
207  continue;
208  }
209  diff1 = it2->getTime() - it1->getRideBackArrTime(this->timePerKm);
210  diff2 = it1->getTime() - it2->getRideBackArrTime(this->timePerKm);
211 
212  if (diff1 < 0 || diff2 < 0) {
213  if (diff2 < diff1) {
214  arrTime = it2->getArrTime(this->timePerKm);
215  it2->addLayOver(*it1);
216  it2->setDepTime(it2->estimateDepTime(arrTime, this->timePerKm));
217  tempAccTrip.erase(it1);
218  } else {
219  arrTime = it1->getArrTime(this->timePerKm);
220  it1->addLayOver(*it2);
221  it1->setDepTime(it1->estimateDepTime(arrTime, this->timePerKm));
222  tempAccTrip.erase(it2);
223  }
224  finish = false;
225  break;
226  }
227  }
228  if (!finish) {
229  break; // return to while
230  }
231  }
232  }
233  return finish;
234 }
235 
236 bool
238  bool check = false;
239  std::list<AGTrip>::iterator itAccT;
240  std::list<AGTrip>::iterator itDriT;
241  std::list<AGAdult>::iterator itA;
242  for (itAccT = tempAccTrip.begin(); itAccT != tempAccTrip.end(); ++itAccT) {
243  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
244  if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm)) {
245  check = true;
246  }
247  }
248  for (itA = notNeedingDrivers.begin(); itA != notNeedingDrivers.end(); ++itA) {
249  if (!itA->isWorking()) {
250  check = true;
251  } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening()) {
252  check = true;
253  }
254  }
255  if (!check) { //at least one trip is not performed by the existing drivers because it is to late for them
256  return false;
257  }
258  check = false;
259  }
260  return true;
261 }
262 
263 void
265  int arrTime;
266  std::list<AGTrip>::iterator itAccT;
267  std::list<AGTrip>::iterator itDriT;
268  std::list<AGAdult>::iterator itA;
269  bool alreadyDone;
270 
274  for (itAccT = tempAccTrip.begin(); itAccT != tempAccTrip.end(); ++itAccT) {
275  alreadyDone = false;
276  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
277  if (!alreadyDone) {
278  if (itAccT->getArrTime(this->timePerKm) < itDriT->getArrTime(this->timePerKm) && !alreadyDone) {
279  //Add the accompaniment trip to the driver's trip OR new trip
280  if (itAccT->getRideBackArrTime(this->timePerKm) < itDriT->getTime()) {
281  //there is enough time to accompany people and go back home before going to work
282  itAccT->setVehicleName(itDriT->getVehicleName());
283  itAccT->addLayOver(itAccT->getArr()); //final destination is the last accompaniment stop: not the destination of the course
284  itAccT->setArr(myHousehold->getPosition()); //final destination of the whole trip: home
285  myPartialActivityTrips.push_back(*itAccT);
286  alreadyDone = true;
287  } else {
288  //the driver drives people to their working place or school and goes directly to work after that
289  arrTime = itDriT->getArrTime(this->timePerKm);
290  itDriT->addLayOver(*itAccT);
291  itDriT->setDepTime(itDriT->estimateDepTime(arrTime, this->timePerKm));
292  //tempAccTrip.erase(itAccT);
293  //--itAccT; //because of erasure
294  alreadyDone = true;
295  }
296  }
297  }
298  }
299 
300  for (itA = notNeedingDrivers.begin(); itA != notNeedingDrivers.end(); ++itA) {
301  if (!itA->isWorking() && !alreadyDone) {
302  std::string nameC = getUnusedCar();
303  if (nameC.size() != 0) {
304  itAccT->setVehicleName(getUnusedCar());
305  itAccT->addLayOver(itAccT->getArr());
306  itAccT->setArr(myHousehold->getPosition());
307  myPartialActivityTrips.push_back(*itAccT);
308  alreadyDone = true;
309  }
310  } else if (itAccT->getRideBackArrTime(this->timePerKm) < itA->getWorkPosition().getOpening() && !alreadyDone) {
311  std::string nameC = getUnusedCar();
312  if (nameC.size() != 0) {
313  itAccT->setVehicleName(getUnusedCar());
314  itAccT->addLayOver(itAccT->getArr());
315  itAccT->setArr(myHousehold->getPosition());
316  myPartialActivityTrips.push_back(*itAccT);
317  alreadyDone = true;
318  }
319  }
320  }
321  }
322 
326  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
327  myPartialActivityTrips.push_back(*itDriT);
328  }
329 
333  for (itA = personsDrivingCars.begin(); itA != personsDrivingCars.end(); ++itA) {
334  for (itDriT = tempTrip.begin(); itDriT != tempTrip.end(); ++itDriT) {
335  if (itA->getWorkPosition().getPosition() == itDriT->getArr()) {
336  AGTrip trip(itA->getWorkPosition().getPosition(), myHousehold->getPosition(), itDriT->getVehicleName(), itA->getWorkPosition().getClosing());
337  myPartialActivityTrips.push_back(trip);
338  tempTrip.erase(itDriT);
339  break;
340  }
341  }
342  }
343 }
344 
345 std::string
347  std::string nameCar = "";
348  std::string nameCarUsed = "";
349  //only two cars can be used in the household, so: the first one or the last one is not used.
350  if (!tempTrip.empty()) {
351  nameCarUsed = tempTrip.front().getVehicleName();
352  } else if (!myPartialActivityTrips.empty()) {
353  nameCarUsed = myPartialActivityTrips.front().getVehicleName();
354  }
355 
356  if (nameCarUsed.size() != 0) {
357  if (myHousehold->getCars().front().getName() == nameCarUsed) {
358  nameCar = myHousehold->getCars().back().getName();
359  } else {
360  nameCar = myHousehold->getCars().front().getName();
361  }
362  }
363  return nameCar;
364 }
365 
366 void
368  //give to a non working adult the ability to drive children or someone else.
370  std::list<AGAdult>::const_iterator itUA;
371  for (itUA = myHousehold->getAdults().begin(); itUA != myHousehold->getAdults().end(); ++itUA) {
372  if (! itUA->isWorking()) {
373  notNeedingDrivers.push_back(*itUA);
374  break;
375  }
376  }
377  }
378 }
379 
380 /****************************************************************************/