AirInv Logo  0.1.2
C++ Simulated Airline Inventory Management System library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
GuillotineBlockHelper.cpp
Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 #include <cmath>
00007 // StdAir
00008 #include <stdair/basic/BasConst_Inventory.hpp>
00009 #include <stdair/bom/BomRetriever.hpp>
00010 #include <stdair/bom/BomManager.hpp>
00011 #include <stdair/bom/SegmentDate.hpp>
00012 #include <stdair/bom/SegmentCabin.hpp>
00013 #include <stdair/bom/FareFamily.hpp>
00014 #include <stdair/bom/BookingClass.hpp>
00015 #include <stdair/bom/GuillotineBlock.hpp>
00016 #include <stdair/service/Logger.hpp>
00017 // AirInv
00018 #include <airinv/basic/BasConst_Curves.hpp>
00019 #include <airinv/bom/GuillotineBlockHelper.hpp>
00020 #include <airinv/bom/FlightDateHelper.hpp>
00021 #include <airinv/bom/SegmentCabinHelper.hpp>
00022 
00023 namespace AIRINV {
00024 
00025   // ////////////////////////////////////////////////////////////////////
00026   void GuillotineBlockHelper::
00027   takeSnapshots (stdair::GuillotineBlock& ioGuillotineBlock,
00028                  const stdair::DateTime_T& iSnapshotTime) {
00029     // Retrieve the segment-cabin index and take the snapshots for
00030     // each segment-cabin.
00031     const stdair::SegmentCabinIndexMap_T& lSegmentCabinIndexMap =
00032       ioGuillotineBlock.getSegmentCabinIndexMap();
00033     for (stdair::SegmentCabinIndexMap_T::const_iterator itSCIdx =
00034            lSegmentCabinIndexMap.begin();
00035          itSCIdx != lSegmentCabinIndexMap.end(); ++itSCIdx) {
00036       const stdair::SegmentCabin* lSC_ptr = itSCIdx->first;
00037       assert (lSC_ptr != NULL);
00038       const stdair::BlockNumber_T& lSCIdx = itSCIdx->second;
00039 
00040       const stdair::Date_T& lSnapshotDate = iSnapshotTime.date();
00041       
00042       // Compare the date of the snapshot time and the departure date of
00043       // the segment-cabin in order to verify the necescity of taking snapshots.
00044       const stdair::SegmentDate& lSegmentDate =
00045         stdair::BomManager::getParent<stdair::SegmentDate> (*lSC_ptr);
00046       const stdair::Date_T& lDepartureDate = lSegmentDate.getBoardingDate();
00047       const stdair::DateOffset_T lDateOffset = lDepartureDate - lSnapshotDate;
00048       const stdair::DTD_T lDTD = lDateOffset.days() + 1;
00049       
00050       if (lDTD >= 0 && lDTD <= stdair::DEFAULT_MAX_DTD) {
00051         SegmentCabinHelper::updateAvailabilities (*lSC_ptr);
00052         takeSnapshots (ioGuillotineBlock, lDTD, *lSC_ptr, lSCIdx);
00053         registerProductAndPriceOrientedBookings (ioGuillotineBlock,
00054                                                  lDTD, *lSC_ptr, lSCIdx);
00055       }
00056     }
00057   }
00058 
00059   // ////////////////////////////////////////////////////////////////////
00060   void GuillotineBlockHelper::
00061   takeSnapshots (stdair::GuillotineBlock& ioGuillotineBlock,
00062                  const stdair::DTD_T& iDTD,
00063                  const stdair::SegmentCabin& iSegmentCabin,
00064                  const stdair::BlockNumber_T iSegmentCabinIdx) {
00065 
00066     // Extract the views for the corresponding DTD and segment-cabin.
00067     stdair::SegmentCabinDTDSnapshotView_T lBookingView = ioGuillotineBlock.
00068       getSegmentCabinDTDBookingSnapshotView (iSegmentCabinIdx,
00069                                              iSegmentCabinIdx, iDTD);
00070     stdair::SegmentCabinDTDSnapshotView_T lCancellationView = ioGuillotineBlock.
00071       getSegmentCabinDTDCancellationSnapshotView (iSegmentCabinIdx,
00072                                                   iSegmentCabinIdx, iDTD);
00073     stdair::SegmentCabinDTDSnapshotView_T lAvailabilityView = ioGuillotineBlock.
00074       getSegmentCabinDTDAvailabilitySnapshotView (iSegmentCabinIdx,
00075                                                   iSegmentCabinIdx, iDTD);
00076     
00077     // Retrieve the block index of the segment-cabin.
00078     std::ostringstream lSCMapKey;
00079     lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE
00080               << iSegmentCabin.describeKey();    
00081     const stdair::BlockIndex_T& lCabinIdx =
00082       ioGuillotineBlock.getBlockIndex (lSCMapKey.str());
00083     lAvailabilityView[lCabinIdx] = iSegmentCabin.getAvailabilityPool();
00084     
00085 
00086     // Browse the booking class list
00087     const stdair::BookingClassList_T& lBCList =
00088       stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
00089     for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
00090          itBC != lBCList.end(); ++itBC) {
00091       const stdair::BookingClass* lBookingClass_ptr = *itBC;
00092       assert (lBookingClass_ptr != NULL);
00093 
00094       // Retrieve the block index of the booking class.
00095       const stdair::BlockIndex_T& lIdx =
00096         ioGuillotineBlock.getBlockIndex (lBookingClass_ptr->describeKey());
00097 
00098       // DEBUG
00099       // STDAIR_LOG_DEBUG ("Taking snapshot for "
00100       //                   << iSegmentCabin.describeKey() << ", "
00101       //                   << lBookingClass_ptr->describeKey()
00102       //                   << ", DTD: " << iDTD << ", nb of bookings: "
00103       //                   << lBookingClass_ptr->getNbOfBookings());
00104 
00105       // Write the snapshot.
00106       lBookingView[lIdx]=lBookingClass_ptr->getNbOfBookings();
00107       lCancellationView[lIdx] =
00108         lBookingClass_ptr->getNbOfCancellations();
00109       lAvailabilityView[lIdx] =
00110         lBookingClass_ptr->getSegmentAvailability();
00111     }
00112   }
00113 
00114   // ////////////////////////////////////////////////////////////////////
00115   void GuillotineBlockHelper::registerProductAndPriceOrientedBookings
00116   (stdair::GuillotineBlock& ioGuillotineBlock, const stdair::DTD_T& iDTD,
00117    const stdair::SegmentCabin& iSegmentCabin,
00118    const stdair::BlockNumber_T iSegmentCabinIdx) {
00119 
00120     // Extract the views for the corresponding DTD and segment-cabin.
00121     stdair::SegmentCabinDTDRangeSnapshotView_T lRangeBookingView =
00122       ioGuillotineBlock.getSegmentCabinDTDRangeBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD, iDTD + 1);
00123     stdair::SegmentCabinDTDRangeSnapshotView_T lRangeCancellationView =
00124       ioGuillotineBlock.getSegmentCabinDTDRangeCancellationSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD, iDTD + 1);
00125     stdair::SegmentCabinDTDSnapshotView_T lProductAndPriceOrientedBookingView =
00126       ioGuillotineBlock.getSegmentCabinDTDProductAndPriceOrientedBookingSnapshotView (iSegmentCabinIdx, iSegmentCabinIdx, iDTD);
00127     
00128     // Retrieve the block index of the segment-cabin.
00129     std::ostringstream lSCMapKey;
00130     lSCMapKey << stdair::DEFAULT_SEGMENT_CABIN_VALUE_TYPE
00131               << iSegmentCabin.describeKey();    
00132     const stdair::BlockIndex_T& lCabinIdx =
00133       ioGuillotineBlock.getBlockIndex (lSCMapKey.str());
00134 
00135     // Retrieve the lowest class and treat the number of gross
00136     // bookings of this class the price oriented bookings.
00137     const stdair::BookingClassList_T& lBCList =
00138       stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
00139     stdair::BookingClassList_T::const_reverse_iterator itBC = lBCList.rbegin();
00140     assert (itBC != lBCList.rend());
00141     stdair::BookingClass* lLowestClass_ptr = *itBC; ++itBC;
00142     assert (lLowestClass_ptr != NULL);
00143 
00144     // Retrieve the block index of the booking class.
00145     const stdair::BlockIndex_T& lClassIdx =
00146       ioGuillotineBlock.getBlockIndex (lLowestClass_ptr->describeKey());
00147 
00148     // Compute the number of gross bookings for this class.
00149     const stdair::NbOfBookings_T lNbOfNetBkgs = 
00150       lRangeBookingView[lClassIdx][0] - lRangeBookingView[lClassIdx][1];
00151     const stdair::NbOfCancellations_T lNbOfCx =
00152       lRangeCancellationView[lClassIdx][0]-lRangeCancellationView[lClassIdx][1];
00153     const stdair::NbOfBookings_T lNbOfGrossBkgs = lNbOfNetBkgs + lNbOfCx;
00154 
00155     // Write this number of bookings to the price-oriented value.
00156     lProductAndPriceOrientedBookingView[lCabinIdx] = lNbOfGrossBkgs;
00157 
00158     // Retrieve the lowest yield.
00159     const stdair::Yield_T& lLowestYield = lLowestClass_ptr->getYield();
00160     
00161     // Boolean for "no lower class available" verification.
00162     bool noLowerClassAvl = true;
00163     if (lLowestClass_ptr->getSegmentAvailability() >= 1.0) {
00164       noLowerClassAvl = false;
00165     }
00166 
00167     // Retrieve the FRAT5 coefficient and compute the sell-up coef.
00168     const double lFRAT5Coef = getFRAT5Coefficient (iDTD);
00169     const double lSellUpCoef = -log(0.5) / (lFRAT5Coef - 1); 
00170     
00171     // Browse the booking class list
00172     for (; itBC != lBCList.rend(); ++itBC) {
00173       const stdair::BookingClass* lBookingClass_ptr = *itBC;
00174       assert (lBookingClass_ptr != NULL);
00175 
00176       // Retrieve the yield of the this class.
00177       const stdair::Yield_T& lYield = lBookingClass_ptr->getYield();
00178       assert (lYield > lLowestYield);
00179       
00180       // Retrieve the block index of the booking class.
00181       const stdair::BlockIndex_T& lIdx =
00182         ioGuillotineBlock.getBlockIndex (lBookingClass_ptr->describeKey());
00183 
00184       // Compute the number of gross bookings for this class.
00185       const stdair::NbOfBookings_T lNetBkgs = 
00186         lRangeBookingView[lIdx][0] - lRangeBookingView[lIdx][1];
00187       const stdair::NbOfCancellations_T lCx =
00188         lRangeCancellationView[lIdx][0] - lRangeCancellationView[lIdx][1];
00189       const stdair::NbOfBookings_T lGrossBkgs = lNetBkgs + lCx;
00190       
00191       // If there is a lower class available, these gross bookings
00192       // will be considered product-oriented. Otherwise, they will be
00193       // considered price-oriented
00194       if (noLowerClassAvl == false) {
00195         lProductAndPriceOrientedBookingView[lIdx] = lGrossBkgs;
00196       } else {
00197         // Convert the bookings to Q-equivalent bookings.
00198         const stdair::NbOfBookings_T lQEquiBkgs =
00199           lGrossBkgs / exp ((1.0 - lYield/lLowestYield) * lSellUpCoef);
00200         lProductAndPriceOrientedBookingView[lCabinIdx] += lQEquiBkgs;
00201         
00202         if (lBookingClass_ptr->getSegmentAvailability() >= 1.0) {
00203           noLowerClassAvl = false;
00204         }
00205       }
00206     }
00207   }
00208 
00209   // ////////////////////////////////////////////////////////////////////
00210   double GuillotineBlockHelper::getFRAT5Coefficient (const stdair::DTD_T& iDTD){
00211     FRAT5Curve_T::const_iterator itFRAT5 =
00212       DEFAULT_PICKUP_FRAT5_CURVE.lower_bound (iDTD);
00213     assert (itFRAT5 != DEFAULT_PICKUP_FRAT5_CURVE.end());
00214 
00215     if (itFRAT5 == DEFAULT_PICKUP_FRAT5_CURVE.begin()) {
00216       return itFRAT5->second;
00217     }
00218     
00219     assert (itFRAT5 != DEFAULT_PICKUP_FRAT5_CURVE.begin());
00220     FRAT5Curve_T::const_iterator itNextFRAT5 = itFRAT5; --itNextFRAT5;
00221 
00222     const stdair::DTD_T& lPrevDTD = itFRAT5->first;
00223     const stdair::DTD_T& lNextDTD = itNextFRAT5->first;
00224     const double& lPrevFRAT5 = itFRAT5->second;
00225     const double& lNextFRAT5 = itNextFRAT5->second;
00226     assert (lPrevDTD > lNextDTD);
00227 
00228     double oFRAT5 = lPrevFRAT5
00229       + (iDTD - lNextDTD) * (lNextFRAT5 - lPrevFRAT5) / (lPrevDTD - lNextDTD);
00230 
00231     return oFRAT5;
00232   }
00233 }