$treeview $search $mathjax
TraDemGen Logo  1.00.2
$projectbrief
$projectbrief
$searchbox

DemandManager.cpp

Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 // Boost
00007 #include <boost/make_shared.hpp>
00008 // StdAir
00009 #include <stdair/basic/ProgressStatusSet.hpp>
00010 #include <stdair/basic/BasConst_Request.hpp>
00011 #include <stdair/bom/BomManager.hpp>
00012 #include <stdair/bom/EventStruct.hpp>
00013 #include <stdair/bom/BookingRequestStruct.hpp>
00014 #include <stdair/bom/TravelSolutionStruct.hpp>
00015 #include <stdair/bom/CancellationStruct.hpp>
00016 #include <stdair/factory/FacBom.hpp>
00017 #include <stdair/factory/FacBomManager.hpp>
00018 #include <stdair/service/Logger.hpp>
00019 // SEvMgr
00020 #include <sevmgr/SEVMGR_Service.hpp>
00021 // TraDemGen
00022 #include <trademgen/basic/DemandCharacteristics.hpp>
00023 #include <trademgen/basic/DemandDistribution.hpp>
00024 #include <trademgen/bom/DemandStruct.hpp>
00025 #include <trademgen/bom/DemandStream.hpp>
00026 #include <trademgen/command/DemandManager.hpp>
00027 
00028 namespace TRADEMGEN {
00029 
00030   // //////////////////////////////////////////////////////////////////////
00031   void DemandManager::
00032   buildSampleBomStd (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00033                      stdair::RandomGeneration& ioSharedGenerator,
00034                      const POSProbabilityMass_T& iPOSProbMass) {
00035     // Sanity check
00036     assert (ioSEVMGR_ServicePtr != NULL);
00037 
00038     // Key of the demand stream
00039     const stdair::AirportCode_T lOrigin ("SIN");
00040     const stdair::AirportCode_T lDestination ("BKK");
00041     const stdair::Date_T lDepDate (2011, 2, 14);
00042     const stdair::CabinCode_T lCabin ("Y");
00043 
00044     //
00045     const DemandStreamKey lDemandStreamKey (lOrigin, lDestination, lDepDate,
00046                                             lCabin);
00047 
00048     // DEBUG
00049     // STDAIR_LOG_DEBUG ("Demand stream key: " << lDemandStreamKey.describe());
00050     
00051     // Distribution for the number of requests
00052     const stdair::MeanValue_T lDemandMean (10.0);
00053     const stdair::StdDevValue_T lDemandStdDev (1.0);
00054     const DemandDistribution lDemandDistribution (lDemandMean, lDemandStdDev);
00055     
00056     // Seed
00057     const stdair::RandomSeed_T& lRequestDateTimeSeed =
00058       generateSeed (ioSharedGenerator);
00059     const stdair::RandomSeed_T& lDemandCharacteristicsSeed =
00060       generateSeed (ioSharedGenerator);
00061 
00062     //
00063     ArrivalPatternCumulativeDistribution_T lDTDProbDist;
00064     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-330,
00065                                                                            0));
00066     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-40,
00067                                                                            0.2));
00068     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-20,
00069                                                                            0.6));
00070     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-1,
00071                                                                            1.0));
00072     //
00073     POSProbabilityMassFunction_T lPOSProbDist;
00074     lPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("BKK", 0.3));
00075     lPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("SIN", 0.7));
00076     //
00077     ChannelProbabilityMassFunction_T lChannelProbDist;
00078     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("DF",
00079                                                                            0.1));
00080     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("DN",
00081                                                                            0.3));
00082     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("IF",
00083                                                                            0.4));
00084     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("IN",
00085                                                                            0.2));
00086     //
00087     TripTypeProbabilityMassFunction_T lTripProbDist;
00088     lTripProbDist.insert (TripTypeProbabilityMassFunction_T::value_type ("RO",
00089                                                                          0.6));
00090     lTripProbDist.insert (TripTypeProbabilityMassFunction_T::value_type ("RI",
00091                                                                          0.2));
00092     lTripProbDist.insert (TripTypeProbabilityMassFunction_T::value_type ("OW",
00093                                                                          0.2));
00094     //
00095     StayDurationProbabilityMassFunction_T lStayProbDist;
00096     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(0,
00097                                                                            0.1));
00098     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(1,
00099                                                                            0.1));
00100     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(2,
00101                                                                            .15));
00102     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(3,
00103                                                                            .15));
00104     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(4,
00105                                                                            .15));
00106     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(5,
00107                                                                            .35));
00108     //
00109     FrequentFlyerProbabilityMassFunction_T lFFProbDist;
00110     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("P",
00111                                                                           0.01));
00112     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("G",
00113                                                                           0.05));
00114     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("S",
00115                                                                           0.15));
00116     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("M",
00117                                                                           0.3));
00118     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("N",
00119                                                                           0.49));
00120     //
00121     PreferredDepartureTimeContinuousDistribution_T lPrefDepTimeProbDist;
00122     lPrefDepTimeProbDist.
00123       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (6 * stdair::HOUR_CONVERTED_IN_SECONDS, 0));
00124     lPrefDepTimeProbDist.
00125       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (7 * stdair::HOUR_CONVERTED_IN_SECONDS,
00126                                                                           0.1));
00127     lPrefDepTimeProbDist.
00128       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (9 * stdair::HOUR_CONVERTED_IN_SECONDS,
00129                                                                           0.3));
00130     lPrefDepTimeProbDist.
00131       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (17 * stdair::HOUR_CONVERTED_IN_SECONDS,
00132                                                                           0.4));
00133     lPrefDepTimeProbDist.
00134       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (19 * stdair::HOUR_CONVERTED_IN_SECONDS,
00135                                                                           0.80));
00136     lPrefDepTimeProbDist.
00137       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (20 * stdair::HOUR_CONVERTED_IN_SECONDS,
00138                                                                           0.95));
00139     lPrefDepTimeProbDist.
00140       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (22 * stdair::HOUR_CONVERTED_IN_SECONDS,
00141                                                                           1));
00142     //
00143     ValueOfTimeContinuousDistribution_T lTimeValueProbDist;
00144     lTimeValueProbDist.insert(ValueOfTimeContinuousDistribution_T::value_type(15,
00145                                                                               0));
00146     lTimeValueProbDist.insert(ValueOfTimeContinuousDistribution_T::value_type(60,
00147                                                                               1));
00148 
00149     //
00150     const stdair::WTP_T lWTP (1000.0);
00151     const stdair::ChangeFeesRatio_T lChangeFees (0.5);
00152     const stdair::Disutility_T lChangeFeeDisutility (50);
00153     const stdair::NonRefundableRatio_T lNonRefundable (0.5);
00154     const stdair::Disutility_T lNonRefundableDisutility (50);
00155 
00156 
00157     // Delegate the call to the dedicated command
00158     DemandStream& lDemandStream = 
00159       createDemandStream (ioSEVMGR_ServicePtr, lDemandStreamKey, lDTDProbDist,
00160                           lPOSProbDist, lChannelProbDist, lTripProbDist,
00161                           lStayProbDist, lFFProbDist,
00162                           lChangeFees, lChangeFeeDisutility,
00163                           lNonRefundable, lNonRefundableDisutility,
00164                           lPrefDepTimeProbDist,
00165                           lWTP, lTimeValueProbDist, lDemandDistribution,
00166                           ioSharedGenerator.getBaseGenerator(),
00167                           lRequestDateTimeSeed,
00168                           lDemandCharacteristicsSeed, iPOSProbMass);
00169 
00170     // Calculate the expected total number of events for the current
00171     // demand stream
00172     const stdair::NbOfRequests_T& lExpectedTotalNbOfEvents =
00173       lDemandStream.getMeanNumberOfRequests();
00174 
00178     ioSEVMGR_ServicePtr->addStatus (stdair::EventType::BKG_REQ,
00179                                     lExpectedTotalNbOfEvents);
00180   }
00181 
00182   // //////////////////////////////////////////////////////////////////////
00183   DemandStream& DemandManager::createDemandStream
00184   (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00185    const DemandStreamKey& iKey,
00186    const ArrivalPatternCumulativeDistribution_T& iArrivalPattern,
00187    const POSProbabilityMassFunction_T& iPOSProbMass,
00188    const ChannelProbabilityMassFunction_T& iChannelProbMass,
00189    const TripTypeProbabilityMassFunction_T& iTripTypeProbMass,
00190    const StayDurationProbabilityMassFunction_T& iStayDurationProbMass,
00191    const FrequentFlyerProbabilityMassFunction_T& iFrequentFlyerProbMass,
00192    const stdair::ChangeFeesRatio_T& iChangeFeeProb,
00193    const stdair::Disutility_T& iChangeFeeDisutility,
00194    const stdair::NonRefundableRatio_T& iNonRefundableProb,
00195    const stdair::Disutility_T& iNonRefundableDisutility,
00196    const PreferredDepartureTimeContinuousDistribution_T& iPreferredDepartureTimeContinuousDistribution,
00197    const stdair::WTP_T& iMinWTP,
00198    const ValueOfTimeContinuousDistribution_T& iValueOfTimeContinuousDistribution,
00199    const DemandDistribution& iDemandDistribution,
00200    stdair::BaseGenerator_T&  ioSharedGenerator,
00201    const stdair::RandomSeed_T& iRequestDateTimeSeed,
00202    const stdair::RandomSeed_T& iDemandCharacteristicsSeed,
00203    const POSProbabilityMass_T& iDefaultPOSProbablityMass) {
00204 
00205     // Sanity check
00206     assert (ioSEVMGR_ServicePtr != NULL);
00207 
00208         // 
00209     DemandStream& oDemandStream =
00210       stdair::FacBom<DemandStream>::instance().create (iKey);
00211 
00212     oDemandStream.setAll (iArrivalPattern, iPOSProbMass,
00213                           iChannelProbMass, iTripTypeProbMass,
00214                           iStayDurationProbMass, iFrequentFlyerProbMass,
00215                           iChangeFeeProb, iChangeFeeDisutility,
00216                           iNonRefundableProb, iNonRefundableDisutility,
00217                           iPreferredDepartureTimeContinuousDistribution,
00218                           iMinWTP, iValueOfTimeContinuousDistribution,
00219                           iDemandDistribution, ioSharedGenerator,
00220                           iRequestDateTimeSeed, iDemandCharacteristicsSeed,
00221                           iDefaultPOSProbablityMass);
00222 
00223     ioSEVMGR_ServicePtr->addEventGenerator (oDemandStream);
00224 
00225     return oDemandStream;
00226   }
00227     
00228   // //////////////////////////////////////////////////////////////////////
00229   void DemandManager::
00230   createDemandCharacteristics (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00231                                stdair::RandomGeneration& ioSharedGenerator,
00232                                const POSProbabilityMass_T& iPOSProbMass,
00233                                const DemandStruct& iDemand) {
00234     // Sanity check
00235     assert (ioSEVMGR_ServicePtr != NULL);
00236         
00237     //
00238     stdair::BaseGenerator_T& lSharedGenerator =
00239       ioSharedGenerator.getBaseGenerator();
00240     
00241     // Parse the date period and DoW and generate demand characteristics.
00242     const stdair::DatePeriod_T lDateRange = iDemand._dateRange;
00243     for (boost::gregorian::day_iterator itDate = lDateRange.begin();
00244          itDate != lDateRange.end(); ++itDate) {
00245       const stdair::Date_T& currentDate = *itDate;
00246 
00247       // Retrieve, for the current day, the Day-Of-the-Week (thanks to Boost)
00248       const unsigned short currentDoW = currentDate.day_of_week().as_number();
00249         
00250       // The demand structure stores which Days (-Of-the-Week) are
00251       // active within the week. For each day (Mon., Tue., etc.), a boolean
00252       // states whether the Flight is active for that day.
00253       const stdair::DoWStruct& lDoWList = iDemand._dow;
00254       const bool isDoWActive = lDoWList.getStandardDayOfWeek (currentDoW);
00255 
00256       if (isDoWActive == true) {
00257         const DemandStreamKey lDemandStreamKey (iDemand._origin,
00258                                                 iDemand._destination,
00259                                                 currentDate,
00260                                                 iDemand._prefCabin);
00261         // DEBUG
00262         // STDAIR_LOG_DEBUG ("Demand stream key: " << lDemandStreamKey.describe());
00263         
00264         //
00265         const DemandDistribution lDemandDistribution (iDemand._demandMean,
00266                                                       iDemand._demandStdDev);
00267         
00268         // Seed
00269         const stdair::RandomSeed_T& lRequestDateTimeSeed =
00270           generateSeed (ioSharedGenerator);
00271         const stdair::RandomSeed_T& lDemandCharacteristicsSeed =
00272           generateSeed (ioSharedGenerator);
00273         
00274         // Delegate the call to the dedicated command
00275         DemandStream& lDemandStream = 
00276           createDemandStream (ioSEVMGR_ServicePtr, lDemandStreamKey,
00277                               iDemand._dtdProbDist, iDemand._posProbDist,
00278                               iDemand._channelProbDist,
00279                               iDemand._tripProbDist,
00280                               iDemand._stayProbDist, iDemand._ffProbDist,
00281                               iDemand._changeFeeProb,
00282                               iDemand._changeFeeDisutility,
00283                               iDemand._nonRefundableProb,
00284                               iDemand._nonRefundableDisutility,
00285                               iDemand._prefDepTimeProbDist,
00286                               iDemand._minWTP,
00287                               iDemand._timeValueProbDist,
00288                               lDemandDistribution, lSharedGenerator,
00289                               lRequestDateTimeSeed,
00290                               lDemandCharacteristicsSeed,
00291                               iPOSProbMass);
00292         
00293         // Calculate the expected total number of events for the current
00294         // demand stream
00295         const stdair::NbOfRequests_T& lExpectedTotalNbOfEvents =
00296           lDemandStream.getMeanNumberOfRequests();
00297         
00302         ioSEVMGR_ServicePtr->addStatus (stdair::EventType::BKG_REQ,
00303                                         lExpectedTotalNbOfEvents);
00304       }
00305     }
00306   }
00307 
00308   // ////////////////////////////////////////////////////////////////////
00309   stdair::RandomSeed_T DemandManager::
00310   generateSeed (stdair::RandomGeneration& ioSharedGenerator) {
00311     stdair::RealNumber_T lVariateUnif = ioSharedGenerator() * 1e9;
00312     stdair::RandomSeed_T oSeed = static_cast<stdair::RandomSeed_T>(lVariateUnif);
00313     return oSeed;
00314   }
00315   
00316   // ////////////////////////////////////////////////////////////////////
00317   const bool DemandManager::
00318   stillHavingRequestsToBeGenerated (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00319                                     const stdair::DemandStreamKeyStr_T& iKey,
00320                                     stdair::ProgressStatusSet& ioPSS,
00321                                     const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
00322     // Sanity check
00323     assert (ioSEVMGR_ServicePtr != NULL);
00324     
00325     // Retrieve the DemandStream which corresponds to the given key.
00326     const DemandStream& lDemandStream =
00327       ioSEVMGR_ServicePtr->getEventGenerator<DemandStream,stdair::DemandStreamKeyStr_T>(iKey);
00328 
00329     // Retrieve the progress status of the demand stream.
00330     stdair::ProgressStatus
00331       lProgressStatus (lDemandStream.getNumberOfRequestsGeneratedSoFar(),
00332                        lDemandStream.getMeanNumberOfRequests(),
00333                        lDemandStream.getTotalNumberOfRequestsToBeGenerated());
00334     ioPSS.setSpecificGeneratorStatus (lProgressStatus, iKey);
00335     
00336     return lDemandStream.stillHavingRequestsToBeGenerated (iDemandGenerationMethod);
00337   }
00338 
00339   // ////////////////////////////////////////////////////////////////////
00340   stdair::BookingRequestPtr_T DemandManager::
00341   generateNextRequest (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00342                        stdair::RandomGeneration& ioGenerator,
00343                        const stdair::DemandStreamKeyStr_T& iKey,
00344                        const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
00345     // Sanity check
00346     assert (ioSEVMGR_ServicePtr != NULL);
00347 
00348     // Retrieve the DemandStream which corresponds to the given key.
00349     DemandStream& lDemandStream =
00350       ioSEVMGR_ServicePtr->getEventGenerator<DemandStream,stdair::DemandStreamKeyStr_T>(iKey);
00351 
00352     // Generate the next booking request
00353     stdair::BookingRequestPtr_T lBookingRequest =
00354       lDemandStream.generateNextRequest (ioGenerator,
00355                                          iDemandGenerationMethod);
00356 
00357     const stdair::DateTime_T& lBookingRequestDateTime =
00358       lBookingRequest->getRequestDateTime();
00359     const stdair::Date_T& lBookingRequestDate =
00360       lBookingRequestDateTime.date();
00361     const stdair::Duration_T& lBookingRequestTime =
00362       lBookingRequestDateTime.time_of_day();
00363     const stdair::Date_T& lPreferedDepartureDate =
00364       lBookingRequest->getPreferedDepartureDate();
00365     const stdair::Duration_T& lPreferedDepartureTime =
00366       lBookingRequest->getPreferredDepartureTime(); 
00367 
00368     if ((lPreferedDepartureDate > lBookingRequestDate) ||
00369         (lPreferedDepartureDate == lBookingRequestDate &&
00370          lPreferedDepartureTime > lBookingRequestTime)) {
00371 
00372       // Create an event structure
00373       stdair::EventStruct lEventStruct (stdair::EventType::BKG_REQ,
00374                                         lBookingRequest);
00375 
00383       ioSEVMGR_ServicePtr->addEvent (lEventStruct);
00384 
00385     } else {
00386 
00387       // Update the expected number of eventss for the given event type (i.e.,
00388       // booking request)
00389       stdair::Count_T lCurrentBRNumber = 
00390         ioSEVMGR_ServicePtr->getActualTotalNumberOfEventsToBeGenerated (stdair::EventType::BKG_REQ);
00391       lCurrentBRNumber--;
00392       ioSEVMGR_ServicePtr->updateStatus (stdair::EventType::BKG_REQ, lCurrentBRNumber);
00393 
00394     }
00395 
00396     return lBookingRequest;
00397   }
00398 
00399   // ////////////////////////////////////////////////////////////////////
00400   stdair::Count_T DemandManager::
00401   generateFirstRequests (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00402                          stdair::RandomGeneration& ioGenerator,
00403                          const stdair::DemandGenerationMethod& iDemandGenerationMethod) {
00404     // Sanity check
00405     assert (ioSEVMGR_ServicePtr != NULL);
00406 
00407     // Actual total number of events to be generated
00408     stdair::NbOfRequests_T lActualTotalNbOfEvents = 0.0;
00409 
00410     // Retrieve the DemandStream list
00411     const DemandStreamList_T& lDemandStreamList =
00412       ioSEVMGR_ServicePtr->getEventGeneratorList<DemandStream>();
00413 
00414     for (DemandStreamList_T::const_iterator itDemandStream =
00415            lDemandStreamList.begin();
00416          itDemandStream != lDemandStreamList.end(); ++itDemandStream) {
00417       DemandStream* lDemandStream_ptr = *itDemandStream;
00418       assert (lDemandStream_ptr != NULL);
00419 
00420       lDemandStream_ptr->setBoolFirstDateTimeRequest(true);
00421 
00422       // Calculate the expected total number of events for the current
00423       // demand stream
00424       const stdair::NbOfRequests_T& lActualNbOfEvents =
00425         lDemandStream_ptr->getTotalNumberOfRequestsToBeGenerated();
00426       lActualTotalNbOfEvents += lActualNbOfEvents;
00427 
00428       // Retrieve the key of the demand stream
00429       const DemandStreamKey& lKey = lDemandStream_ptr->getKey();
00430 
00431       // Check whether there are still booking requests to be generated
00432       const bool stillHavingRequestsToBeGenerated =
00433         lDemandStream_ptr->stillHavingRequestsToBeGenerated (iDemandGenerationMethod);
00434    
00435       if (stillHavingRequestsToBeGenerated) {
00436         // Generate the next event (booking request), and insert it
00437         // into the event queue
00438         generateNextRequest (ioSEVMGR_ServicePtr, ioGenerator,
00439                              lKey.toString(),
00440                              iDemandGenerationMethod);
00441       }
00442     }
00443     
00444     // Update the progress status for the given event type (i.e.,
00445     // booking request)
00446     ioSEVMGR_ServicePtr->updateStatus (stdair::EventType::BKG_REQ,
00447                                        lActualTotalNbOfEvents);
00448 
00449     // Retrieve the actual total number of events to be generated
00450     const stdair::Count_T oTotalNbOfEvents = std::floor (lActualTotalNbOfEvents);
00451 
00452     //
00453     return oTotalNbOfEvents;
00454   }
00455   
00456   // ////////////////////////////////////////////////////////////////////
00457   void DemandManager::reset (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00458                              stdair::BaseGenerator_T& ioShareGenerator) {
00459     // Sanity check
00460     assert (ioSEVMGR_ServicePtr != NULL);
00461 
00462     // TODO: check whether it is really necessary to destroy the
00463     // objects manually. Indeed, FacSupervisor::cleanAll() should
00464     // destroy any BOM object.
00465 
00466     // Reset all the DemandStream objects
00467     const DemandStreamList_T& lDemandStreamList =
00468       ioSEVMGR_ServicePtr->getEventGeneratorList<DemandStream>();
00469     for (DemandStreamList_T::const_iterator itDS = lDemandStreamList.begin();
00470          itDS != lDemandStreamList.end(); ++itDS) {
00471       DemandStream* lCurrentDS_ptr = *itDS;
00472       assert (lCurrentDS_ptr != NULL);
00473       
00474       lCurrentDS_ptr->reset (ioShareGenerator);
00475     }
00476 
00484     ioSEVMGR_ServicePtr->reset();
00485   }
00486   
00487   // ////////////////////////////////////////////////////////////////////
00488   bool DemandManager::
00489   generateCancellation (stdair::RandomGeneration& ioGenerator,
00490                         const stdair::TravelSolutionStruct& iTravelSolution,
00491                         const stdair::PartySize_T& iPartySize,
00492                         const stdair::DateTime_T& iRequestTime,
00493                         const stdair::Date_T& iDepartureDate,
00494                         stdair::EventStruct& ioEventStruct) {
00495 
00496     // Draw a random number to decide if we generate a
00497     // cancellation. For instance, the probability will be hardcoded.
00498     // The cancellation time will be generated uniformly.
00499     double lRandomNumber = ioGenerator();
00500    
00501     if (lRandomNumber >= 0.05) {
00502       return false;
00503     }
00504     lRandomNumber /= 0.05;
00505     
00506     // Hardcode the latest cancellation time.
00507     const stdair::Time_T lMidNight =
00508       boost::posix_time::hours (0);
00509     const stdair::DateTime_T lDepartureDateTime =
00510       boost::posix_time::ptime (iDepartureDate, lMidNight);
00511 
00512     // Time to departure.
00513     const stdair::Duration_T lTimeToDeparture = lDepartureDateTime-iRequestTime;
00514 
00515     // Cancellation time to departure
00516     const long lTimeToDepartureInSeconds = lTimeToDeparture.total_seconds();
00517     const long lCancellationTimeToDepartureInSeconds =
00518       static_cast<long> (lTimeToDepartureInSeconds * lRandomNumber);
00519     const stdair::Duration_T lCancellationTimeToDeparture (0, 0, lCancellationTimeToDepartureInSeconds);
00520     
00521     // Cancellation time
00522     const stdair::DateTime_T lCancellationTime =
00523       lDepartureDateTime - lCancellationTimeToDeparture;
00524     const stdair::Duration_T lTimeBetweenCancellationAndTheRequest = 
00525       lCancellationTime - iRequestTime;
00526 
00527     if (lTimeBetweenCancellationAndTheRequest.is_negative() == true) { 
00528       return false;
00529     }
00530 
00531     // Build the list of Class ID's.
00532     stdair::BookingClassIDList_T lClassIDList;
00533     
00534     const stdair::ClassObjectIDMapHolder_T& lClassObjectIDMapHolder =
00535       iTravelSolution.getClassObjectIDMapHolder();
00536     const stdair::FareOptionStruct& lChosenFareOption =
00537       iTravelSolution.getChosenFareOption ();
00538     const stdair::ClassList_StringList_T& lClassPath =
00539       lChosenFareOption.getClassPath(); 
00540     const stdair::SegmentPath_T& lSegmentPath =
00541       iTravelSolution.getSegmentPath();
00542     stdair::ClassList_StringList_T::const_iterator itClassKeyList =
00543       lClassPath.begin();
00544     for (stdair::ClassObjectIDMapHolder_T::const_iterator itClassObjectIDMap =
00545            lClassObjectIDMapHolder.begin();
00546          itClassObjectIDMap != lClassObjectIDMapHolder.end();
00547          ++itClassObjectIDMap, ++itClassKeyList) {
00548       const stdair::ClassObjectIDMap_T& lClassObjectIDMap = *itClassObjectIDMap;
00549       
00550       // TODO: Remove this hard-coded part.
00551       std::ostringstream ostr;
00552       const stdair::ClassList_String_T& lClassList = *itClassKeyList;
00553       assert (lClassList.empty() == false);
00554 
00555       ostr << lClassList.at(0);
00556       const stdair::ClassCode_T lClassCode (ostr.str());
00557 
00558       stdair::ClassObjectIDMap_T::const_iterator itClassID =
00559         lClassObjectIDMap.find (lClassCode);
00560       assert (itClassID != lClassObjectIDMap.end());
00561       const stdair::BookingClassID_T& lClassID = itClassID->second;
00562 
00563       lClassIDList.push_back (lClassID);
00564 
00565       
00566     }
00567     
00568     // Create the cancellation.
00569     stdair::CancellationStruct lCancellationStruct (lSegmentPath,
00570                                                     lClassIDList,
00571                                                     iPartySize,
00572                                                     lCancellationTime);
00573     
00574     stdair::CancellationPtr_T lCancellation_ptr =
00575       boost::make_shared<stdair::CancellationStruct> (lCancellationStruct);
00576 
00577     // Create an event structure
00578     stdair::EventStruct lEventStruct (stdair::EventType::CX, lCancellation_ptr);
00579     ioEventStruct = lEventStruct;
00580     
00581     return true;
00582   }
00583   
00584   // //////////////////////////////////////////////////////////////////////
00585   void DemandManager::
00586   buildSampleBom (SEVMGR::SEVMGR_ServicePtr_T ioSEVMGR_ServicePtr,
00587                   stdair::RandomGeneration& ioSharedGenerator,
00588                   const POSProbabilityMass_T& iPOSProbMass) {
00589     // Sanity check
00590     assert (ioSEVMGR_ServicePtr != NULL);
00591 
00592     //
00593     ArrivalPatternCumulativeDistribution_T lDTDProbDist;
00594     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-330,
00595                                                                            0));
00596     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-150,
00597                                                                            0.1));
00598     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-92,
00599                                                                            0.2));
00600     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-55,
00601                                                                            0.3));
00602     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-34,
00603                                                                            0.4));
00604     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-21,
00605                                                                            0.5));
00606     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-12,
00607                                                                            0.6));
00608     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-6,
00609                                                                            0.7));
00610     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-3,
00611                                                                            0.8));
00612     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(-1,
00613                                                                            0.9));
00614     lDTDProbDist.insert(ArrivalPatternCumulativeDistribution_T::value_type(0,
00615                                                                            1.0));
00616 
00617     //
00618     ChannelProbabilityMassFunction_T lChannelProbDist;
00619     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("DF",
00620                                                                            0.0));
00621     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("DN",
00622                                                                            0.0));
00623     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("IF",
00624                                                                            0.0));
00625     lChannelProbDist.insert (ChannelProbabilityMassFunction_T::value_type ("IN",
00626                                                                            1.0));
00627 
00628     //
00629     TripTypeProbabilityMassFunction_T lTripProbDist;
00630     lTripProbDist.insert (TripTypeProbabilityMassFunction_T::value_type ("RO",
00631                                                                          0.0));
00632     lTripProbDist.insert (TripTypeProbabilityMassFunction_T::value_type ("RI",
00633                                                                          0.0));
00634     lTripProbDist.insert (TripTypeProbabilityMassFunction_T::value_type ("OW",
00635                                                                          1.0));
00636 
00637     //
00638     StayDurationProbabilityMassFunction_T lStayProbDist;
00639     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(0,
00640                                                                            0.1));
00641     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(1,
00642                                                                            0.1));
00643     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(2,
00644                                                                            .15));
00645     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(3,
00646                                                                            .15));
00647     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(4,
00648                                                                            .15));
00649     lStayProbDist.insert(StayDurationProbabilityMassFunction_T::value_type(5,
00650                                                                            .35));
00651 
00652     //
00653     FrequentFlyerProbabilityMassFunction_T lFFProbDist;
00654     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("P",
00655                                                                           0.1));
00656     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("G",
00657                                                                           0.01));
00658     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("S",
00659                                                                           0.09));
00660     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("M",
00661                                                                           0.4));
00662     lFFProbDist.insert(FrequentFlyerProbabilityMassFunction_T::value_type("N",
00663                                                                           0.4));
00664 
00665     //
00666     ValueOfTimeContinuousDistribution_T lTimeValueProbDist;
00667     lTimeValueProbDist.insert(ValueOfTimeContinuousDistribution_T::value_type(15,
00668                                                                               0));
00669     lTimeValueProbDist.insert(ValueOfTimeContinuousDistribution_T::value_type(60,
00670                                                                               1));
00671 
00672     /*===================================================================================*/
00673 
00674     // Key of the demand stream
00675     const stdair::AirportCode_T lSINOrigin ("SIN");
00676     const stdair::AirportCode_T lBKKDestination ("BKK");
00677     const stdair::Date_T lDepDate (2010, 2, 8);
00678     const stdair::CabinCode_T lCabin ("Y");
00679 
00680     //
00681     const DemandStreamKey lSINBKKDemandStreamKey (lSINOrigin, lBKKDestination, lDepDate,
00682                                                   lCabin);
00683 
00684     // DEBUG
00685     // STDAIR_LOG_DEBUG ("Demand stream key: " << lDemandStreamKey.describe());
00686     
00687     // Distribution for the number of requests
00688     const stdair::MeanValue_T lSINBKKDemandMean (60.0);
00689     const stdair::StdDevValue_T lSINBKKDemandStdDev (4.0);
00690     const DemandDistribution lSINBKKDemandDistribution (lSINBKKDemandMean, lSINBKKDemandStdDev);
00691     
00692     // Seed
00693     const stdair::RandomSeed_T& lSINBKKRequestDateTimeSeed =
00694       generateSeed (ioSharedGenerator);
00695     const stdair::RandomSeed_T& lSINBKKDemandCharacteristicsSeed =
00696       generateSeed (ioSharedGenerator);
00697 
00698     
00699     //
00700     POSProbabilityMassFunction_T lSINBKKPOSProbDist;    
00701     lSINBKKPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("SIN", 1.0));
00702     lSINBKKPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("BKK", 0.0)); 
00703         
00704     //
00705     PreferredDepartureTimeContinuousDistribution_T lSINPrefDepTimeProbDist;
00706     lSINPrefDepTimeProbDist.
00707       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (6 * stdair::HOUR_CONVERTED_IN_SECONDS, 0));
00708     lSINPrefDepTimeProbDist.
00709       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (8 * stdair::HOUR_CONVERTED_IN_SECONDS,
00710                                                                           0.7));
00711     lSINPrefDepTimeProbDist.
00712       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (10 * stdair::HOUR_CONVERTED_IN_SECONDS,
00713                                                                           0.8));
00714     lSINPrefDepTimeProbDist.
00715       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (12 * stdair::HOUR_CONVERTED_IN_SECONDS,
00716                                                                           0.9));
00717     lSINPrefDepTimeProbDist.
00718       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (14 * stdair::HOUR_CONVERTED_IN_SECONDS,
00719                                                                           1.0));    
00720 
00721     //
00722     const stdair::WTP_T lSINBKKWTP (400.0);
00723     const stdair::ChangeFeesRatio_T lChangeFees (0.5);
00724     const stdair::Disutility_T lChangeFeeDisutility (50);
00725     const stdair::NonRefundableRatio_T lNonRefundable (0.5);
00726     const stdair::Disutility_T lNonRefundableDisutility (50);
00727 
00728 
00729     // Delegate the call to the dedicated command
00730     DemandStream& lSINBKKDemandStream = 
00731       createDemandStream (ioSEVMGR_ServicePtr, lSINBKKDemandStreamKey, lDTDProbDist,
00732                           lSINBKKPOSProbDist, lChannelProbDist, lTripProbDist,
00733                           lStayProbDist, lFFProbDist,
00734                           lChangeFees, lChangeFeeDisutility,
00735                           lNonRefundable, lNonRefundableDisutility,
00736                           lSINPrefDepTimeProbDist,
00737                           lSINBKKWTP, lTimeValueProbDist,
00738                           lSINBKKDemandDistribution,
00739                           ioSharedGenerator.getBaseGenerator(),
00740                           lSINBKKRequestDateTimeSeed,
00741                           lSINBKKDemandCharacteristicsSeed, iPOSProbMass);
00742 
00743     // Calculate the expected total number of events for the current
00744     // demand stream
00745     const stdair::NbOfRequests_T& lSINBKKExpectedNbOfEvents =
00746       lSINBKKDemandStream.getMeanNumberOfRequests();
00747 
00748     /*===================================================================================*/
00749 
00750     // Key of the demand stream
00751     const stdair::AirportCode_T lBKKOrigin ("BKK");
00752     const stdair::AirportCode_T lHKGDestination ("HKG");
00753 
00754     //
00755     const DemandStreamKey lBKKHKGDemandStreamKey (lBKKOrigin, lHKGDestination, lDepDate,
00756                                                   lCabin);
00757 
00758     // DEBUG
00759     // STDAIR_LOG_DEBUG ("Demand stream key: " << lDemandStreamKey.describe());
00760     
00761     // Distribution for the number of requests
00762     const stdair::MeanValue_T lBKKHKGDemandMean (60.0);
00763     const stdair::StdDevValue_T lBKKHKGDemandStdDev (4.0);
00764     const DemandDistribution lBKKHKGDemandDistribution (lBKKHKGDemandMean, lBKKHKGDemandStdDev);
00765     
00766     // Seed
00767     const stdair::RandomSeed_T& lBKKHKGRequestDateTimeSeed =
00768       generateSeed (ioSharedGenerator);
00769     const stdair::RandomSeed_T& lBKKHKGDemandCharacteristicsSeed =
00770       generateSeed (ioSharedGenerator);
00771 
00772     
00773     //
00774     POSProbabilityMassFunction_T lBKKHKGPOSProbDist;    
00775     lBKKHKGPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("BKK", 1.0));
00776     lBKKHKGPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("HKG", 0.0)); 
00777         
00778     //
00779     PreferredDepartureTimeContinuousDistribution_T lBKKPrefDepTimeProbDist;
00780     lBKKPrefDepTimeProbDist.
00781       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (8 * stdair::HOUR_CONVERTED_IN_SECONDS, 0));
00782     lBKKPrefDepTimeProbDist.
00783       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (10 * stdair::HOUR_CONVERTED_IN_SECONDS,
00784                                                                           0.2));
00785     lBKKPrefDepTimeProbDist.
00786       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (1 * stdair::HOUR_CONVERTED_IN_SECONDS,
00787                                                                           0.6));
00788     lBKKPrefDepTimeProbDist.
00789       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (14 * stdair::HOUR_CONVERTED_IN_SECONDS,
00790                                                                           0.8));
00791     lBKKPrefDepTimeProbDist.
00792       insert (PreferredDepartureTimeContinuousDistribution_T::value_type (16 * stdair::HOUR_CONVERTED_IN_SECONDS,
00793                                                                           1.0));    
00794 
00795     //
00796     const stdair::WTP_T lBKKHKGWTP (400.0);
00797 
00798 
00799     // Delegate the call to the dedicated command
00800     DemandStream& lBKKHKGDemandStream = 
00801       createDemandStream (ioSEVMGR_ServicePtr, lBKKHKGDemandStreamKey, lDTDProbDist,
00802                           lBKKHKGPOSProbDist, lChannelProbDist, lTripProbDist,
00803                           lStayProbDist, lFFProbDist,
00804                           lChangeFees, lChangeFeeDisutility,
00805                           lNonRefundable, lNonRefundableDisutility,
00806                           lBKKPrefDepTimeProbDist,
00807                           lBKKHKGWTP, lTimeValueProbDist,
00808                           lBKKHKGDemandDistribution,
00809                           ioSharedGenerator.getBaseGenerator(),
00810                           lBKKHKGRequestDateTimeSeed,
00811                           lBKKHKGDemandCharacteristicsSeed, iPOSProbMass);
00812 
00813     // Calculate the expected total number of events for the current
00814     // demand stream
00815     const stdair::NbOfRequests_T& lBKKHKGExpectedNbOfEvents =
00816       lBKKHKGDemandStream.getMeanNumberOfRequests();
00817 
00818     /*===================================================================================*/
00819 
00820     // Key of the demand stream
00821 
00822     //
00823     const DemandStreamKey lSINHKGDemandStreamKey (lSINOrigin, lHKGDestination, lDepDate,
00824                                                   lCabin);
00825 
00826     // DEBUG
00827     // STDAIR_LOG_DEBUG ("Demand stream key: " << lDemandStreamKey.describe());
00828     
00829     // Distribution for the number of requests
00830     const stdair::MeanValue_T lSINHKGDemandMean (60.0);
00831     const stdair::StdDevValue_T lSINHKGDemandStdDev (4.0);
00832     const DemandDistribution lSINHKGDemandDistribution (lSINHKGDemandMean, lSINHKGDemandStdDev);
00833     
00834     // Seed
00835     const stdair::RandomSeed_T& lSINHKGRequestDateTimeSeed =
00836       generateSeed (ioSharedGenerator);
00837     const stdair::RandomSeed_T& lSINHKGDemandCharacteristicsSeed =
00838       generateSeed (ioSharedGenerator);
00839 
00840     
00841     //
00842     POSProbabilityMassFunction_T lSINHKGPOSProbDist;    
00843     lSINHKGPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("SIN", 1.0));
00844     lSINHKGPOSProbDist.insert (POSProbabilityMassFunction_T::value_type ("HKG", 0.0)); 
00845         
00846     //
00847     const stdair::WTP_T lSINHKGWTP (750.0);
00848 
00849 
00850     // Delegate the call to the dedicated command
00851     DemandStream& lSINHKGDemandStream = 
00852       createDemandStream (ioSEVMGR_ServicePtr, lSINHKGDemandStreamKey, lDTDProbDist,
00853                           lSINHKGPOSProbDist, lChannelProbDist, lTripProbDist,
00854                           lStayProbDist, lFFProbDist, 
00855                           lChangeFees, lChangeFeeDisutility,
00856                           lNonRefundable, lNonRefundableDisutility,
00857                           lSINPrefDepTimeProbDist,
00858                           lSINHKGWTP, lTimeValueProbDist, lSINHKGDemandDistribution,
00859                           ioSharedGenerator.getBaseGenerator(),
00860                           lSINHKGRequestDateTimeSeed,
00861                           lSINHKGDemandCharacteristicsSeed, iPOSProbMass);
00862 
00863     // Calculate the expected total number of events for the current
00864     // demand stream
00865     const stdair::NbOfRequests_T& lSINHKGExpectedNbOfEvents =
00866       lSINHKGDemandStream.getMeanNumberOfRequests();
00867 
00868     /*===================================================================================*/
00869 
00873     const stdair::NbOfRequests_T lExpectedTotalNbOfEvents =
00874       lSINBKKExpectedNbOfEvents + lBKKHKGExpectedNbOfEvents + lSINHKGExpectedNbOfEvents;
00875     ioSEVMGR_ServicePtr->addStatus (stdair::EventType::BKG_REQ,
00876                                     lExpectedTotalNbOfEvents);
00877   }
00878 
00879 }
00880