AirSched Logo  0.1.2
C++ Simulated Airline Schedule Manager Library
SegmentPathPeriod.cpp
Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 #include <sstream>
00007 // Boost.Serialization
00008 #include <boost/archive/text_iarchive.hpp>
00009 #include <boost/archive/text_oarchive.hpp>
00010 #include <boost/serialization/access.hpp>
00011 // StdAir
00012 #include <stdair/basic/BasConst_General.hpp>
00013 #include <stdair/basic/BasConst_Inventory.hpp>
00014 #include <stdair/basic/BasConst_Period_BOM.hpp>
00015 #include <stdair/basic/BasConst_TravelSolution.hpp>
00016 #include <stdair/bom/Inventory.hpp>
00017 #include <stdair/bom/FlightPeriod.hpp>
00018 #include <stdair/bom/SegmentPeriod.hpp>
00019 #include <stdair/bom/BomManager.hpp>
00020 // AirSched
00021 #include <airsched/bom/SegmentPathPeriod.hpp>
00022 
00023 namespace AIRSCHED {
00024 
00025   // ////////////////////////////////////////////////////////////////////
00026   SegmentPathPeriod::SegmentPathPeriod()
00027     :  _key (stdair::PeriodStruct (stdair::BOOST_DEFAULT_DATE_PERIOD,
00028                                    stdair::DEFAULT_DOW_STRING),
00029              stdair::NULL_BOOST_TIME_DURATION, stdair::NULL_BOOST_TIME_DURATION,
00030              DateOffsetList_T(),
00031              stdair::DEFAULT_NBOFAIRLINES),
00032        _parent (NULL) {
00033     assert (false);
00034   }
00035 
00036   // ////////////////////////////////////////////////////////////////////
00037   SegmentPathPeriod::SegmentPathPeriod (const SegmentPathPeriod& iSPP)
00038     :  _key (iSPP._key), _parent (NULL) {
00039     assert (false);
00040   }
00041   
00042   // ////////////////////////////////////////////////////////////////////
00043   SegmentPathPeriod::SegmentPathPeriod (const Key_T& iKey)
00044     :  _key (iKey), _parent (NULL) {
00045   }
00046   
00047   // ////////////////////////////////////////////////////////////////////
00048   SegmentPathPeriod::~SegmentPathPeriod() {
00049   }
00050 
00051   // ////////////////////////////////////////////////////////////////////
00052   std::string SegmentPathPeriod::toString() const {
00053     std::ostringstream oStr;
00054     oStr << _key.toString();
00055     return oStr.str();
00056   }
00057 
00058   // ////////////////////////////////////////////////////////////////////
00059   void SegmentPathPeriod::serialisationImplementation() {
00060     std::ostringstream oStr;
00061     boost::archive::text_oarchive oa (oStr);
00062     oa << *this;
00063 
00064     std::istringstream iStr;
00065     boost::archive::text_iarchive ia (iStr);
00066     ia >> *this;
00067   }
00068 
00069   // ////////////////////////////////////////////////////////////////////
00070   template<class Archive>
00071   void SegmentPathPeriod::serialize (Archive& ioArchive,
00072                                      const unsigned int iFileVersion) {
00073     ioArchive & _key;
00074   }
00075 
00076   // ////////////////////////////////////////////////////////////////////
00077   stdair::SegmentPeriod* SegmentPathPeriod::getLastSegmentPeriod () const {
00078     // Retrieve the last segment of the list
00079     const stdair::SegmentPeriodList_T& lSegmentPeriodList =
00080       stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
00081     stdair::SegmentPeriodList_T::const_reverse_iterator itLastSegment =
00082       lSegmentPeriodList.rbegin();
00083 
00084     if (itLastSegment == lSegmentPeriodList.rend()) {
00085       return NULL;
00086     }
00087     
00088     stdair::SegmentPeriod* oSegment_ptr = *itLastSegment;
00089     assert (oSegment_ptr != NULL);
00090 
00091     return oSegment_ptr;
00092   }
00093 
00094   // ////////////////////////////////////////////////////////////////////
00095   stdair::SegmentPeriod* SegmentPathPeriod::getFirstSegmentPeriod () const{
00096     // Retrieve the first segment of the list
00097     const stdair::SegmentPeriodList_T& lSegmentPeriodList =
00098       stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
00099     stdair::SegmentPeriodList_T::const_iterator itFirstSegment = 
00100       lSegmentPeriodList.begin();
00101 
00102     if (itFirstSegment == lSegmentPeriodList.end()) {
00103       return NULL;
00104     }
00105     
00106     stdair::SegmentPeriod* oSegment_ptr = *itFirstSegment;
00107     assert (oSegment_ptr != NULL);
00108 
00109     return oSegment_ptr;
00110   }
00111 
00112   // ////////////////////////////////////////////////////////////////////
00113   const stdair::AirportCode_T& SegmentPathPeriod::getDestination () const {
00114     const stdair::SegmentPeriod* lLastSegment_ptr = getLastSegmentPeriod();
00115     assert (lLastSegment_ptr != NULL);
00116     return lLastSegment_ptr->getOffPoint();
00117   }  
00118 
00119   // ////////////////////////////////////////////////////////////////////
00120   bool SegmentPathPeriod::
00121   isAirlineFlown (const stdair::AirlineCode_T& iAirlineCode) const {
00122     bool oAirlineFlown = false;
00123 
00124     const stdair::SegmentPeriodList_T& lSegmentPeriodList = 
00125       stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
00126     for (stdair::SegmentPeriodList_T::const_iterator itSegmentPeriod =
00127            lSegmentPeriodList.begin();
00128          itSegmentPeriod != lSegmentPeriodList.end(); ++itSegmentPeriod) {
00129       const stdair::SegmentPeriod* lSegmentPeriod_ptr = *itSegmentPeriod;
00130       assert (lSegmentPeriod_ptr != NULL);
00131 
00132       const stdair::FlightPeriod& lFlightPeriod =
00133         stdair::BomManager::getParent<stdair::FlightPeriod>(*lSegmentPeriod_ptr);
00134       const stdair::Inventory& lInventory =
00135         stdair::BomManager::getParent<stdair::Inventory> (lFlightPeriod);
00136       const stdair::AirlineCode_T& lSegmentAirlineCode =
00137         lInventory.getAirlineCode ();
00138       if (lSegmentAirlineCode == iAirlineCode) {
00139         oAirlineFlown = true;
00140         break;
00141       }
00142     }
00143 
00144     return oAirlineFlown;
00145   }
00146 
00147   // ////////////////////////////////////////////////////////////////////
00148   SegmentPathPeriodKey SegmentPathPeriod::
00149   connectWithAnotherSegment(const SegmentPathPeriod& iSingleSegmentPath) const {
00150     SegmentPathPeriodKey oSegmentPathPeriodKey;
00151 
00152     // Retrieve the (only) segment period of the single segment path.
00153     const stdair::SegmentPeriod* lNextSegmentPeriod_ptr =
00154       iSingleSegmentPath.getFirstSegmentPeriod();
00155     assert (lNextSegmentPeriod_ptr != NULL);
00156 
00157     // Retrive the last segment period of the current segment path and check
00158     // if the combination of the last segment and the next segment that we
00159     // want to add to the current segment path will create a new segment
00160     // (i.e., the two segment period belongs to the same flight number).
00161     const stdair::SegmentPeriod* lLastSegmentPeriod_ptr = getLastSegmentPeriod ();
00162     assert (lLastSegmentPeriod_ptr != NULL);
00163     const stdair::FlightPeriod& lLastFlightPeriod = stdair::BomManager::
00164       getParent<stdair::FlightPeriod> (*lLastSegmentPeriod_ptr);
00165     const stdair::Inventory& lLastInventory =
00166       stdair::BomManager::getParent<stdair::Inventory> (lLastFlightPeriod);
00167     
00168     const stdair::FlightPeriod& lNextFlightPeriod = stdair::BomManager::
00169       getParent<stdair::FlightPeriod> (*lNextSegmentPeriod_ptr);
00170     const stdair::Inventory& lNextInventory =
00171       stdair::BomManager::getParent<stdair::Inventory> (lNextFlightPeriod);
00172     
00173     if (lLastFlightPeriod.getFlightNumber()==lNextFlightPeriod.getFlightNumber()
00174         && lLastInventory.getAirlineCode() == lNextInventory.getAirlineCode()) {
00175       return oSegmentPathPeriodKey;
00176     }
00177     
00178     // Check if the new segment period will create a circle.
00179     const stdair::AirportCode_T& lDestination =
00180       lNextSegmentPeriod_ptr->getOffPoint();
00181     if (checkCircle (lDestination) == true) {
00182       return oSegmentPathPeriodKey;
00183     }
00184 
00185     // Check if a passenger can connect from the last segment of the
00186     // current segment path to the first segment of the to-be-added
00187     // segment path. If yes, build a new departure period for the new
00188     // segment path.
00189     DateOffsetList_T lBoardingDateOffsetList = 
00190       getBoardingDateOffsetList();
00191     const stdair::PeriodStruct& lCurrentDeparturePeriod = getDeparturePeriod();
00192     const stdair::PeriodStruct& lNextDeparturePeriod =
00193       iSingleSegmentPath.getDeparturePeriod();
00194     const stdair::Duration_T& lLastOffTime =
00195       lLastSegmentPeriod_ptr->getOffTime();
00196     const stdair::Duration_T& lNextBoardingTime =
00197       lNextSegmentPeriod_ptr->getBoardingTime();
00198     // If the next boarding time is later than the last off time, check if
00199     // the passengers will have enough time for the transfer. If the next
00200     // boarding time is earlier than the last off time, check if the passengers
00201     // can connect to a flight in the next day.
00202     if (lNextBoardingTime >= lLastOffTime) {
00203       const stdair::Duration_T lStopTime = lNextBoardingTime - lLastOffTime;
00204       if (lStopTime < stdair::DEFAULT_MINIMAL_CONNECTION_TIME) {
00205         return oSegmentPathPeriodKey;
00206       } else {
00207         // Calulcate the date offset of the next segment compare to
00208         // the first one. In this case, this value is equal to the offset
00209         // of the off date of the last segment compare to the boarding date
00210         // of the first segment.
00211         const stdair::DateOffset_T& lLastBoardingDateOffset =
00212           lBoardingDateOffsetList.at (getNbOfSegments() - 1);
00213         const stdair::DateOffset_T lNextBoardingDateOffset =
00214           lLastBoardingDateOffset + lLastSegmentPeriod_ptr->getOffDateOffset()
00215           - lLastSegmentPeriod_ptr->getBoardingDateOffset();
00216         const stdair::DateOffset_T lNegativeNextBoardingDateOffset =
00217           stdair::DateOffset_T (0) - lNextBoardingDateOffset;
00218 
00219         // Compute the adjusted departure period of the next segment by
00220         // substracting the origin one with the boarding date offset.
00221         const stdair::PeriodStruct lAdjustedNextDeparturePeriod =
00222           lNextDeparturePeriod.addDateOffset (lNegativeNextBoardingDateOffset);
00223 
00224         // Build the intersection of the two periods.
00225         const stdair::PeriodStruct lNewDeparturePeriod =
00226           lCurrentDeparturePeriod.intersection (lAdjustedNextDeparturePeriod);
00227         stdair::Duration_T lNewElapsed = getElapsedTime() + lStopTime +
00228           lNextSegmentPeriod_ptr->getElapsedTime();
00229         lBoardingDateOffsetList.push_back (lNextBoardingDateOffset);
00230         oSegmentPathPeriodKey.setPeriod (lNewDeparturePeriod);
00231         oSegmentPathPeriodKey.setElapsedTime (lNewElapsed);
00232       }
00233     } else {
00234       const stdair::Duration_T lStopTime = 
00235         lNextBoardingTime - lLastOffTime + stdair::Duration_T (24, 0, 0);
00236       if (lStopTime < stdair::DEFAULT_MINIMAL_CONNECTION_TIME) {
00237         return oSegmentPathPeriodKey;
00238       } else {
00239         // Calulcate the date offset of the next segment compare to
00240         // the first one.
00241         const stdair::DateOffset_T& lLastBoardingDateOffset =
00242           lBoardingDateOffsetList.at (getNbOfSegments() - 1);
00243         const stdair::DateOffset_T lNextBoardingDateOffset =
00244           lLastBoardingDateOffset + lLastSegmentPeriod_ptr->getOffDateOffset()
00245           - lLastSegmentPeriod_ptr->getBoardingDateOffset() +
00246           stdair::DateOffset_T (1);
00247         const stdair::DateOffset_T lNegativeNextBoardingDateOffset =
00248           stdair::DateOffset_T (0) - lNextBoardingDateOffset;
00249 
00250         // Compute the adjusted departure period of the next segment by
00251         // substracting the origin one with the boarding date offset.
00252         const stdair::PeriodStruct lAdjustedNextDeparturePeriod =
00253           lNextDeparturePeriod.addDateOffset (lNegativeNextBoardingDateOffset);
00254 
00255         // Build the intersection of the two periods.
00256         const stdair::PeriodStruct lNewDeparturePeriod =
00257           lCurrentDeparturePeriod.intersection (lAdjustedNextDeparturePeriod);
00258         stdair::Duration_T lNewElapsed = getElapsedTime() + lStopTime +
00259           lNextSegmentPeriod_ptr->getElapsedTime();
00260         lBoardingDateOffsetList.push_back (lNextBoardingDateOffset);
00261         oSegmentPathPeriodKey.setPeriod (lNewDeparturePeriod);
00262         oSegmentPathPeriodKey.setElapsedTime (lNewElapsed);
00263       }
00264     }
00265     
00266     const stdair::Duration_T& lBoardingTime = getBoardingTime();
00267     oSegmentPathPeriodKey.setBoardingTime (lBoardingTime);
00268     oSegmentPathPeriodKey.setBoardingDateOffsetList (lBoardingDateOffsetList);
00269     
00270     return oSegmentPathPeriodKey;
00271   }
00272 
00273   // ////////////////////////////////////////////////////////////////////
00274   bool SegmentPathPeriod::
00275   checkCircle (const stdair::AirlineCode_T& iDestination) const {
00276     const stdair::SegmentPeriodList_T& lSegmentPeriodList =
00277       stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
00278     for (stdair::SegmentPeriodList_T::const_iterator itSegment =
00279            lSegmentPeriodList.begin();
00280          itSegment != lSegmentPeriodList.end(); ++itSegment) {
00281       const stdair::SegmentPeriod* lCurrentSegment_ptr = *itSegment;
00282       assert (lCurrentSegment_ptr != NULL);
00283       const stdair::AirlineCode_T& lCurrentBoardingPoint =
00284         lCurrentSegment_ptr->getBoardingPoint();
00285       if (lCurrentBoardingPoint == iDestination) {
00286         return true;
00287       }
00288     }
00289     return false;
00290   }
00291 
00292   // ////////////////////////////////////////////////////////////////////
00293   bool SegmentPathPeriod::
00294   isDepartureDateValid (const stdair::Date_T& iDepartureDate) const {
00295     const stdair::PeriodStruct& lPeriod = getDeparturePeriod ();
00296 
00297     // Check if the departure date is within the date range.
00298     const stdair::DatePeriod_T& lDeparturePeriod = lPeriod.getDateRange ();
00299     if (lDeparturePeriod.contains (iDepartureDate) == false) {
00300       return false;
00301     }
00302 
00303     // Check if the departure date is valid within the DOW.
00304     // 0 = Sunday, 1 = Monday, etc.
00305     const short lDay = iDepartureDate.day_of_week ();
00306     const stdair::DoWStruct& lDoW = lPeriod.getDoW ();
00307     if (lDoW.getStandardDayOfWeek (lDay) == false) {
00308       return false;
00309     }
00310 
00311     return true;
00312   }
00313 
00314 }