TvlSim Logo  1.00.0
C++ Simulated Travel-Oriented Distribution System Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Simulator.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // Boost
5 #include <boost/make_shared.hpp>
6 // STL
7 #include <fstream>
8 #include <string>
9 #include <vector>
10 #include <exception>
11 #include <iomanip>
12 // StdAir
13 #include <stdair/stdair_demand_types.hpp>
14 #include <stdair/basic/ProgressStatusSet.hpp>
15 #include <stdair/basic/BasChronometer.hpp>
16 #include <stdair/bom/BookingRequestStruct.hpp>
17 #include <stdair/bom/SnapshotStruct.hpp>
18 #include <stdair/bom/CancellationStruct.hpp>
19 #include <stdair/bom/RMEventStruct.hpp>
20 #include <stdair/bom/BreakPointStruct.hpp>
21 #include <stdair/bom/EventStruct.hpp>
22 #include <stdair/bom/TravelSolutionStruct.hpp>
23 #include <stdair/service/Logger.hpp>
24 #include <stdair/STDAIR_Service.hpp>
25 // Distribution
26 #include <simcrs/SIMCRS_Service.hpp>
27 // SEVMGR
28 #include <sevmgr/SEVMGR_Service.hpp>
29 // TRADEMGEN
30 #include <trademgen/TRADEMGEN_Service.hpp>
31 // TRAVELCCM
32 #include <travelccm/TRAVELCCM_Service.hpp>
33 // Airsched
34 #include <airsched/AIRSCHED_Service.hpp>
35 // Dsim
36 #include <tvlsim/TVLSIM_Types.hpp>
40 
41 namespace TVLSIM {
42 
43  // ////////////////////////////////////////////////////////////////////
44  void Simulator::
45  simulate (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
46  TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
47  TRAVELCCM::TRAVELCCM_Service& ioTRAVELCCM_Service,
48  stdair::STDAIR_Service& ioSTDAIR_Service,
49  SimulationStatus& ioSimulationStatus,
50  const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
51 
52  if (ioSimulationStatus.getMode() == SimulationMode::START ||
53  ioSimulationStatus.getMode() == SimulationMode::DONE) {
54 
59  // Retrieve the expected (mean value of the) number of events to be
60  // generated
61  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
62  ioTRADEMGEN_Service.getExpectedTotalNumberOfRequestsToBeGenerated();
63  const stdair::Count_T& lActualNbOfEventsToBeGenerated =
64  ioTRADEMGEN_Service.generateFirstRequests(iDemandGenerationMethod);
65 
66  // DEBUG
67  STDAIR_LOG_DEBUG ("Expected number of events: "
68  << lExpectedNbOfEventsToBeGenerated << ", actual: "
69  << lActualNbOfEventsToBeGenerated);
70 
71  }
72 
73  // Change the current mode of the simulation status
74  ioSimulationStatus.setMode (SimulationMode::RUNNING);
75 
76  // Initialise the (Boost) progress display object
77  //boost::progress_display lProgressDisplay(lActualNbOfEventsToBeGenerated);
78 
86  while (ioTRADEMGEN_Service.isQueueDone() == false) {
87 
88  // Get the next event from the event queue
89  stdair::EventStruct lEventStruct;
90  stdair::ProgressStatusSet lPSS =
91  ioTRADEMGEN_Service.popEvent (lEventStruct);
92 
93  // Update the simulation status with the current date
94  const stdair::DateTime_T& lCurrentEventDateTime =
95  lEventStruct.getEventTime ();
96  const stdair::Date_T& lCurrentEventDate =
97  lCurrentEventDateTime.date();
98  ioSimulationStatus.setCurrentDate(lCurrentEventDate);
99 
100  // DEBUG
101  STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'.");
102 
103  // Check the event type
104  const stdair::EventType::EN_EventType& lEventType =
105  lEventStruct.getEventType();
106 
107  stdair::BasChronometer lNextEventChronometer;
108  lNextEventChronometer.start();
109 
110  switch (lEventType) {
111 
112  case stdair::EventType::BKG_REQ:
113  playBookingRequest (ioSIMCRS_Service,
114  ioTRADEMGEN_Service,
115  ioTRAVELCCM_Service,
116  lEventStruct,
117  lPSS,
118  ioSimulationStatus,
119  iDemandGenerationMethod);
120  break;
121 
122  case stdair::EventType::CX:
123  playCancellation (ioSIMCRS_Service,
124  lEventStruct);
125  break;
126 
127  case stdair::EventType::SNAPSHOT:
128  playSnapshotEvent (ioSIMCRS_Service,
129  lEventStruct);
130  break;
131 
132  case stdair::EventType::RM:
133  playRMEvent (ioSIMCRS_Service,
134  lEventStruct);
135  break;
136 
137  case stdair::EventType::BRK_PT:
138  // Change the current mode of the simulation status
139  ioSimulationStatus.setMode (SimulationMode::BREAK);
140  updateStatus (ioTRADEMGEN_Service, lEventType, ioSimulationStatus);
141  return;
142  break;
143 
144  case stdair::EventType::OPT_NOT_4_FD:
145  case stdair::EventType::OPT_NOT_4_NET:
146  case stdair::EventType::SKD_CHG:
147  break;
148  default: assert (false);
149  break;
150  }
151 
152  // Update the simulation status
153  const double lNextEventMeasure = lNextEventChronometer.elapsed();
154  updateStatus (ioTRADEMGEN_Service, lEventType,
155  ioSimulationStatus, lNextEventMeasure);
156 
157  // Update the progress display
158  //++lProgressDisplay;
159 
160  }
161 
162  // Change the current mode of the simulation status
163  ioSimulationStatus.setMode (SimulationMode::DONE);
164  }
165 
166  // ////////////////////////////////////////////////////////////////////
167  void Simulator::
168  updateStatus (const TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
169  const stdair::EventType::EN_EventType& iEN_EventType,
170  SimulationStatus& ioSimulationStatus,
171  const double& iEventMeasure) {
172  // Update the global simulation status
173  const stdair::ProgressStatus& lProgressStatus =
174  ioTRADEMGEN_Service.getProgressStatus ();
175  ioSimulationStatus.setCurrentProgressStatus (lProgressStatus);
176 
177  // Re-Calculate the progress percentage for the given event type
178  const stdair::ProgressStatus& lProgressStatusByType =
179  ioTRADEMGEN_Service.getProgressStatus (iEN_EventType);
180 
181  // Update the simulation status for the current type
182  ioSimulationStatus.updateProgress(iEN_EventType,
183  lProgressStatusByType,
184  iEventMeasure);
185 
186  }
187 
188  // ////////////////////////////////////////////////////////////////////
189  void Simulator::
190  playBookingRequest (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
191  TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
192  TRAVELCCM::TRAVELCCM_Service& ioTRAVELCCM_Service,
193  const stdair::EventStruct& iEventStruct,
194  stdair::ProgressStatusSet& ioPSS,
195  SimulationStatus& ioSimulationStatus,
196  const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
197 
198  // Extract the corresponding demand/booking request
199  const stdair::BookingRequestStruct& lPoppedRequest =
200  iEventStruct.getBookingRequest();
201 
202  // Check if the request if valid
203  const stdair::Date_T& lDepDate = lPoppedRequest.getPreferedDepartureDate();
204  const stdair::Duration_T& lDepTime = lPoppedRequest.getPreferredDepartureTime();
205  const stdair::DateTime_T& lReqDateTime = lPoppedRequest.getRequestDateTime();
206  const stdair::Date_T& lReqDate = lReqDateTime.date();
207  const stdair::Duration_T& lReqTime = lReqDateTime.time_of_day();
208  const bool isRequestDateValid =
209  ((lDepDate > lReqDate) || (lDepDate == lReqDate && lDepTime > lReqTime));
210  assert (isRequestDateValid == true);
211 
212  // DEBUG
213  STDAIR_LOG_DEBUG ("Poped booking request: '" << lPoppedRequest.describe()
214  << "'.");
215 
216  // Retrieve the corresponding demand stream
217  const stdair::DemandGeneratorKey_T& lDemandStreamKey =
218  lPoppedRequest.getDemandGeneratorKey();
219 
220  // Assess whether more events should be generated for that demand stream
221  const bool stillHavingRequestsToBeGenerated =
222  ioTRADEMGEN_Service.stillHavingRequestsToBeGenerated (lDemandStreamKey,
223  ioPSS,
224  iDemandGenerationMethod);
225 
226  // DEBUG
227  // STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "] is now processed. "
228  // << "Still generate events for that demand stream? "
229  // << stillHavingRequestsToBeGenerated);
230  STDAIR_LOG_DEBUG ("Progress status" << ioPSS.describe());
231 
232  // If there are still events to be generated for that demand stream,
233  // generate and add them to the event queue
234  if (stillHavingRequestsToBeGenerated) {
235  stdair::BookingRequestPtr_T lNextRequest_ptr =
236  ioTRADEMGEN_Service.generateNextRequest (lDemandStreamKey,
237  iDemandGenerationMethod);
238  assert (lNextRequest_ptr != NULL);
239 
240  // Sanity check
241  const stdair::Duration_T lDuration =
242  lNextRequest_ptr->getRequestDateTime()
243  - lPoppedRequest.getRequestDateTime();
244  if (lDuration.total_milliseconds() < 0) {
245  STDAIR_LOG_NOTIFICATION ("[" << lDemandStreamKey
246  << "] The date-time of the generated event ("
247  << lNextRequest_ptr->getRequestDateTime()
248  << ") is lower than the date-time "
249  << "of the current event ("
250  << lPoppedRequest.getRequestDateTime()
251  << ")");
252  assert (false);
253  }
254 
255  // DEBUG
256  // STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "] Added request: '"
257  // << lNextRequest_ptr->describe()
258  // << "'. Is queue done? "
259  // << ioTRADEMGEN_Service.isQueueDone());
260  }
261 
262  // Retrieve a list of travel solutions corresponding the given
263  // booking request.
264  stdair::TravelSolutionList_T lTravelSolutionList =
265  ioSIMCRS_Service.calculateSegmentPathList (lPoppedRequest);
266 
267  if (lTravelSolutionList.empty() == false) {
268 
269  // Get the fare quote for each travel solution.
270  ioSIMCRS_Service.fareQuote (lPoppedRequest, lTravelSolutionList);
271 
272  // Get the availability for each travel solution.
273  ioSIMCRS_Service.calculateAvailability (lTravelSolutionList);
274 
275  // Get a travel solution choice.
276  const stdair::TravelSolutionStruct* lChosenTS_ptr =
277  ioTRAVELCCM_Service.chooseTravelSolution (lTravelSolutionList,
278  lPoppedRequest);
279  if (lChosenTS_ptr != NULL) {
280  // DEBUG
281  STDAIR_LOG_DEBUG ("Chosen TS: " << lChosenTS_ptr->describe());
282 
283  // Retrieve and convert the party size
284  const stdair::NbOfSeats_T& lPartySizeDouble =
285  lPoppedRequest.getPartySize();
286  const stdair::PartySize_T lPartySize = std::floor (lPartySizeDouble);
287 
288  // Delegate the sell to the corresponding SimCRS service
289  bool saleSucceedful =
290  ioSIMCRS_Service.sell (*lChosenTS_ptr, lPartySize);
291 
292  // If the sale succeeded, generate the potential cancellation event.
293  if (saleSucceedful == true) {
294  ioSimulationStatus.increaseGlobalNumberOfBookings(lPartySize);
295  ioTRADEMGEN_Service.generateCancellation (*lChosenTS_ptr,
296  lPartySize, lReqDateTime,
297  lDepDate);
298  }
299 
300  // LOG
301  const stdair::DateTime_T lDepartureDateTime =
302  boost::posix_time::ptime (lDepDate, boost::posix_time::hours (0));
303  const stdair::Duration_T lDTDRequest = lReqDateTime - lDepartureDateTime;
304  const double lDTD = double(lDTDRequest.total_seconds()) / 86400.0;
305  std::ostringstream oStr;
306  const stdair::SegmentPath_T& lSegmentPath =
307  lChosenTS_ptr->getSegmentPath();
308  for (stdair::SegmentPath_T::const_iterator itSegPath =
309  lSegmentPath.begin();
310  itSegPath != lSegmentPath.end(); ++itSegPath) {
311  oStr << *itSegPath << ";";
312  }
313  STDAIR_LOG_NOTIFICATION (oStr.str() << std::setprecision(10) << lDTD);
314  }
315  else {
316  // DEBUG
317  STDAIR_LOG_DEBUG ("There is no chosen travel solution "
318  <<"for this request: "<< lPoppedRequest.describe());
319  }
320  } else {
321  // DEBUG
322  STDAIR_LOG_DEBUG ("No travel solution has been found for: "
323  << lPoppedRequest);
324  }
325  }
326 
327  // ////////////////////////////////////////////////////////////////////
328  void Simulator::
329  playCancellation (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
330  const stdair::EventStruct& iEventStruct) {
331  // Retrieve the cancellation struct from the event.
332  const stdair::CancellationStruct lCancellationStruct =
333  iEventStruct.getCancellation();
334 
335  // DEBUG
336  // STDAIR_LOG_DEBUG ("Play cancellation: "<<lCancellationStruct.describe());
337  ioSIMCRS_Service.playCancellation (lCancellationStruct);
338  }
339 
340 
341  // ////////////////////////////////////////////////////////////////////
342  void Simulator::
343  playSnapshotEvent (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
344  const stdair::EventStruct& iEventStruct) {
345  // Retrieve the snapshot struct from the event.
346  const stdair::SnapshotStruct lSnapshotStruct =
347  iEventStruct.getSnapshotStruct();
348 
349  // DEBUG
350  // STDAIR_LOG_DEBUG ("Taking snapshots: " << lSnapshotStruct.describe());
351 
352  ioSIMCRS_Service.takeSnapshots (lSnapshotStruct);
353  }
354 
355  // ////////////////////////////////////////////////////////////////////
356  void Simulator::
357  playRMEvent (SIMCRS::SIMCRS_Service& ioSIMCRS_Service,
358  const stdair::EventStruct& iEventStruct) {
359  // Retrieve the RM event struct from the event.
360  const stdair::RMEventStruct lRMEvent = iEventStruct.getRMEvent();
361 
362  // DEBUG
363  STDAIR_LOG_DEBUG ("Running RM system: " << lRMEvent.describe());
364 
365  ioSIMCRS_Service.optimise (lRMEvent);
366  }
367 
368  // ////////////////////////////////////////////////////////////////////
369  const stdair::Count_T Simulator::
370  initialiseBreakPoint (const TRADEMGEN::TRADEMGEN_Service& ioTRADEMGEN_Service,
371  SEVMGR::SEVMGR_Service& ioSEVMGR_Service,
372  const stdair::BreakPointList_T& iBreakPointList,
373  SimulationStatus& ioSimulationStatus) {
374 
375  // Number of break points actually added to the event queue.
376  stdair::Count_T lBreakPointNumber = 0;
377 
378  // Get the start and end date of the simulation
379  const stdair::Date_T& lStartDate = ioSimulationStatus.getStartDate();
380  const stdair::Date_T& lEndDate = ioSimulationStatus.getEndDate();
381 
382  // Try to add each break point of the list to the event queue.
383  for (stdair::BreakPointList_T::const_iterator itBPEvent =
384  iBreakPointList.begin();
385  itBPEvent != iBreakPointList.end(); ++itBPEvent) {
386  const stdair::BreakPointStruct& lBPEvent = *itBPEvent;
387  const stdair::DateTime_T& lDateTimeBP =
388  lBPEvent.getBreakPointTime();
389  const stdair::Date_T lDateBP = lDateTimeBP.date();
390  // If the break point is within the simulation period, add it to the
391  // queue.
392  if (lDateBP < lEndDate && lDateBP >= lStartDate) {
393  stdair::BreakPointPtr_T lBPEventPtr =
394  boost::make_shared<stdair::BreakPointStruct> (lBPEvent);
395  // Create an event structure
396  stdair::EventStruct lEventStruct (stdair::EventType::BRK_PT,
397  lBPEventPtr);
398  ioSEVMGR_Service.addEvent (lEventStruct);
399  lBreakPointNumber ++;
400  }
401  }
402 
403  if (lBreakPointNumber > 0) {
404  // Update the status of break point events within the event queue.
405  const bool hasProgressStatus =
406  ioSEVMGR_Service.hasProgressStatus(stdair::EventType::BRK_PT);
407  if (hasProgressStatus == false) {
408  ioSEVMGR_Service.addStatus (stdair::EventType::BRK_PT,
409  lBreakPointNumber);
410  } else {
411  stdair::Count_T lCurrentBPNumber = ioSEVMGR_Service.
412  getActualTotalNumberOfEventsToBeGenerated (stdair::EventType::BRK_PT);
413  lCurrentBPNumber += lBreakPointNumber;
414  ioSEVMGR_Service.updateStatus (stdair::EventType::BRK_PT,
415  lCurrentBPNumber);
416  }
417  // Update the global Simulation Status
418  updateStatus(ioTRADEMGEN_Service, stdair::EventType::BRK_PT,
419  ioSimulationStatus);
420  }
421  return lBreakPointNumber;
422  }
423 }