TvlSim Logo  1.01.6
C++ Simulated Travel-Oriented Distribution System Library
Loading...
Searching...
No Matches
Simulator.cpp
Go to the documentation of this file.
1// //////////////////////////////////////////////////////////////////////
2// Import section
3// //////////////////////////////////////////////////////////////////////
4// STL
5#include <fstream>
6#include <string>
7#include <vector>
8#include <exception>
9#include <iomanip>
10// Boost
11#include <boost/make_shared.hpp>
12// StdAir (Standard Airline BOM)
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// SimCRS (Distribution)
26#include <simcrs/SIMCRS_Service.hpp>
27// SEvMgr (Event Management)
28#include <sevmgr/SEVMGR_Service.hpp>
29// TraDemGen (Demand Generation)
30#include <trademgen/TRADEMGEN_Service.hpp>
31// TravelCCM (Customer Choice Model)
32#include <travelccm/TRAVELCCM_Service.hpp>
33// AirTSP (Travel Solution Provider)
34#include <airtsp/AIRTSP_Service.hpp>
35// TvlSim (Travel Simulator)
40
41namespace 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}