$treeview $search $mathjax
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::serialisationImplementationExport() const { 00060 std::ostringstream oStr; 00061 boost::archive::text_oarchive oa (oStr); 00062 oa << *this; 00063 } 00064 00065 // //////////////////////////////////////////////////////////////////// 00066 void SegmentPathPeriod::serialisationImplementationImport() { 00067 std::istringstream iStr; 00068 boost::archive::text_iarchive ia (iStr); 00069 ia >> *this; 00070 } 00071 00072 // //////////////////////////////////////////////////////////////////// 00073 template<class Archive> 00074 void SegmentPathPeriod::serialize (Archive& ioArchive, 00075 const unsigned int iFileVersion) { 00076 ioArchive & _key; 00077 } 00078 00079 // //////////////////////////////////////////////////////////////////// 00080 // Explicit template instantiation 00081 namespace ba = boost::archive; 00082 template 00083 void SegmentPathPeriod::serialize<ba::text_oarchive> (ba::text_oarchive&, 00084 unsigned int); 00085 template 00086 void SegmentPathPeriod::serialize<ba::text_iarchive> (ba::text_iarchive&, 00087 unsigned int); 00088 // //////////////////////////////////////////////////////////////////// 00089 00090 // //////////////////////////////////////////////////////////////////// 00091 stdair::SegmentPeriod* SegmentPathPeriod::getLastSegmentPeriod () const { 00092 // Retrieve the last segment of the list 00093 const stdair::SegmentPeriodList_T& lSegmentPeriodList = 00094 stdair::BomManager::getList<stdair::SegmentPeriod> (*this); 00095 stdair::SegmentPeriodList_T::const_reverse_iterator itLastSegment = 00096 lSegmentPeriodList.rbegin(); 00097 00098 if (itLastSegment == lSegmentPeriodList.rend()) { 00099 return NULL; 00100 } 00101 00102 stdair::SegmentPeriod* oSegment_ptr = *itLastSegment; 00103 assert (oSegment_ptr != NULL); 00104 00105 return oSegment_ptr; 00106 } 00107 00108 // //////////////////////////////////////////////////////////////////// 00109 stdair::SegmentPeriod* SegmentPathPeriod::getFirstSegmentPeriod () const{ 00110 // Retrieve the first segment of the list 00111 const stdair::SegmentPeriodList_T& lSegmentPeriodList = 00112 stdair::BomManager::getList<stdair::SegmentPeriod> (*this); 00113 stdair::SegmentPeriodList_T::const_iterator itFirstSegment = 00114 lSegmentPeriodList.begin(); 00115 00116 if (itFirstSegment == lSegmentPeriodList.end()) { 00117 return NULL; 00118 } 00119 00120 stdair::SegmentPeriod* oSegment_ptr = *itFirstSegment; 00121 assert (oSegment_ptr != NULL); 00122 00123 return oSegment_ptr; 00124 } 00125 00126 // //////////////////////////////////////////////////////////////////// 00127 const stdair::AirportCode_T& SegmentPathPeriod::getDestination () const { 00128 const stdair::SegmentPeriod* lLastSegment_ptr = getLastSegmentPeriod(); 00129 assert (lLastSegment_ptr != NULL); 00130 return lLastSegment_ptr->getOffPoint(); 00131 } 00132 00133 // //////////////////////////////////////////////////////////////////// 00134 bool SegmentPathPeriod:: 00135 isAirlineFlown (const stdair::AirlineCode_T& iAirlineCode) const { 00136 bool oAirlineFlown = false; 00137 00138 const stdair::SegmentPeriodList_T& lSegmentPeriodList = 00139 stdair::BomManager::getList<stdair::SegmentPeriod> (*this); 00140 for (stdair::SegmentPeriodList_T::const_iterator itSegmentPeriod = 00141 lSegmentPeriodList.begin(); 00142 itSegmentPeriod != lSegmentPeriodList.end(); ++itSegmentPeriod) { 00143 const stdair::SegmentPeriod* lSegmentPeriod_ptr = *itSegmentPeriod; 00144 assert (lSegmentPeriod_ptr != NULL); 00145 00146 const stdair::FlightPeriod& lFlightPeriod = 00147 stdair::BomManager::getParent<stdair::FlightPeriod>(*lSegmentPeriod_ptr); 00148 const stdair::Inventory& lInventory = 00149 stdair::BomManager::getParent<stdair::Inventory> (lFlightPeriod); 00150 const stdair::AirlineCode_T& lSegmentAirlineCode = 00151 lInventory.getAirlineCode (); 00152 if (lSegmentAirlineCode == iAirlineCode) { 00153 oAirlineFlown = true; 00154 break; 00155 } 00156 } 00157 00158 return oAirlineFlown; 00159 } 00160 00161 // //////////////////////////////////////////////////////////////////// 00162 SegmentPathPeriodKey SegmentPathPeriod:: 00163 connectWithAnotherSegment(const SegmentPathPeriod& iSingleSegmentPath) const { 00164 SegmentPathPeriodKey oSegmentPathPeriodKey; 00165 00166 // Retrieve the (only) segment period of the single segment path. 00167 const stdair::SegmentPeriod* lNextSegmentPeriod_ptr = 00168 iSingleSegmentPath.getFirstSegmentPeriod(); 00169 assert (lNextSegmentPeriod_ptr != NULL); 00170 00171 // Retrive the last segment period of the current segment path and check 00172 // if the combination of the last segment and the next segment that we 00173 // want to add to the current segment path will create a new segment 00174 // (i.e., the two segment period belongs to the same flight number). 00175 const stdair::SegmentPeriod* lLastSegmentPeriod_ptr = getLastSegmentPeriod (); 00176 assert (lLastSegmentPeriod_ptr != NULL); 00177 const stdair::FlightPeriod& lLastFlightPeriod = stdair::BomManager:: 00178 getParent<stdair::FlightPeriod> (*lLastSegmentPeriod_ptr); 00179 const stdair::Inventory& lLastInventory = 00180 stdair::BomManager::getParent<stdair::Inventory> (lLastFlightPeriod); 00181 00182 const stdair::FlightPeriod& lNextFlightPeriod = stdair::BomManager:: 00183 getParent<stdair::FlightPeriod> (*lNextSegmentPeriod_ptr); 00184 const stdair::Inventory& lNextInventory = 00185 stdair::BomManager::getParent<stdair::Inventory> (lNextFlightPeriod); 00186 00187 if (lLastFlightPeriod.getFlightNumber()==lNextFlightPeriod.getFlightNumber() 00188 && lLastInventory.getAirlineCode() == lNextInventory.getAirlineCode()) { 00189 return oSegmentPathPeriodKey; 00190 } 00191 00192 // Check if the new segment period will create a circle. 00193 const stdair::AirportCode_T& lDestination = 00194 lNextSegmentPeriod_ptr->getOffPoint(); 00195 if (checkCircle (lDestination) == true) { 00196 return oSegmentPathPeriodKey; 00197 } 00198 00199 // Check if a passenger can connect from the last segment of the 00200 // current segment path to the first segment of the to-be-added 00201 // segment path. If yes, build a new departure period for the new 00202 // segment path. 00203 DateOffsetList_T lBoardingDateOffsetList = 00204 getBoardingDateOffsetList(); 00205 const stdair::PeriodStruct& lCurrentDeparturePeriod = getDeparturePeriod(); 00206 const stdair::PeriodStruct& lNextDeparturePeriod = 00207 iSingleSegmentPath.getDeparturePeriod(); 00208 const stdair::Duration_T& lLastOffTime = 00209 lLastSegmentPeriod_ptr->getOffTime(); 00210 const stdair::Duration_T& lNextBoardingTime = 00211 lNextSegmentPeriod_ptr->getBoardingTime(); 00212 // If the next boarding time is later than the last off time, check if 00213 // the passengers will have enough time for the transfer. If the next 00214 // boarding time is earlier than the last off time, check if the passengers 00215 // can connect to a flight in the next day. 00216 if (lNextBoardingTime >= lLastOffTime) { 00217 const stdair::Duration_T lStopTime = lNextBoardingTime - lLastOffTime; 00218 if (lStopTime < stdair::DEFAULT_MINIMAL_CONNECTION_TIME) { 00219 return oSegmentPathPeriodKey; 00220 } else { 00221 // Calulcate the date offset of the next segment compare to 00222 // the first one. In this case, this value is equal to the offset 00223 // of the off date of the last segment compare to the boarding date 00224 // of the first segment. 00225 const stdair::DateOffset_T& lLastBoardingDateOffset = 00226 lBoardingDateOffsetList.at (getNbOfSegments() - 1); 00227 const stdair::DateOffset_T lNextBoardingDateOffset = 00228 lLastBoardingDateOffset + lLastSegmentPeriod_ptr->getOffDateOffset() 00229 - lLastSegmentPeriod_ptr->getBoardingDateOffset(); 00230 const stdair::DateOffset_T lNegativeNextBoardingDateOffset = 00231 stdair::DateOffset_T (0) - lNextBoardingDateOffset; 00232 00233 // Compute the adjusted departure period of the next segment by 00234 // substracting the origin one with the boarding date offset. 00235 const stdair::PeriodStruct lAdjustedNextDeparturePeriod = 00236 lNextDeparturePeriod.addDateOffset (lNegativeNextBoardingDateOffset); 00237 00238 // Build the intersection of the two periods. 00239 const stdair::PeriodStruct lNewDeparturePeriod = 00240 lCurrentDeparturePeriod.intersection (lAdjustedNextDeparturePeriod); 00241 stdair::Duration_T lNewElapsed = getElapsedTime() + lStopTime + 00242 lNextSegmentPeriod_ptr->getElapsedTime(); 00243 lBoardingDateOffsetList.push_back (lNextBoardingDateOffset); 00244 oSegmentPathPeriodKey.setPeriod (lNewDeparturePeriod); 00245 oSegmentPathPeriodKey.setElapsedTime (lNewElapsed); 00246 } 00247 } else { 00248 const stdair::Duration_T lStopTime = 00249 lNextBoardingTime - lLastOffTime + stdair::Duration_T (24, 0, 0); 00250 if (lStopTime < stdair::DEFAULT_MINIMAL_CONNECTION_TIME) { 00251 return oSegmentPathPeriodKey; 00252 } else { 00253 // Calulcate the date offset of the next segment compare to 00254 // the first one. 00255 const stdair::DateOffset_T& lLastBoardingDateOffset = 00256 lBoardingDateOffsetList.at (getNbOfSegments() - 1); 00257 const stdair::DateOffset_T lNextBoardingDateOffset = 00258 lLastBoardingDateOffset + lLastSegmentPeriod_ptr->getOffDateOffset() 00259 - lLastSegmentPeriod_ptr->getBoardingDateOffset() + 00260 stdair::DateOffset_T (1); 00261 const stdair::DateOffset_T lNegativeNextBoardingDateOffset = 00262 stdair::DateOffset_T (0) - lNextBoardingDateOffset; 00263 00264 // Compute the adjusted departure period of the next segment by 00265 // substracting the origin one with the boarding date offset. 00266 const stdair::PeriodStruct lAdjustedNextDeparturePeriod = 00267 lNextDeparturePeriod.addDateOffset (lNegativeNextBoardingDateOffset); 00268 00269 // Build the intersection of the two periods. 00270 const stdair::PeriodStruct lNewDeparturePeriod = 00271 lCurrentDeparturePeriod.intersection (lAdjustedNextDeparturePeriod); 00272 stdair::Duration_T lNewElapsed = getElapsedTime() + lStopTime + 00273 lNextSegmentPeriod_ptr->getElapsedTime(); 00274 lBoardingDateOffsetList.push_back (lNextBoardingDateOffset); 00275 oSegmentPathPeriodKey.setPeriod (lNewDeparturePeriod); 00276 oSegmentPathPeriodKey.setElapsedTime (lNewElapsed); 00277 } 00278 } 00279 00280 const stdair::Duration_T& lBoardingTime = getBoardingTime(); 00281 oSegmentPathPeriodKey.setBoardingTime (lBoardingTime); 00282 oSegmentPathPeriodKey.setBoardingDateOffsetList (lBoardingDateOffsetList); 00283 00284 return oSegmentPathPeriodKey; 00285 } 00286 00287 // //////////////////////////////////////////////////////////////////// 00288 bool SegmentPathPeriod:: 00289 checkCircle (const stdair::AirlineCode_T& iDestination) const { 00290 const stdair::SegmentPeriodList_T& lSegmentPeriodList = 00291 stdair::BomManager::getList<stdair::SegmentPeriod> (*this); 00292 for (stdair::SegmentPeriodList_T::const_iterator itSegment = 00293 lSegmentPeriodList.begin(); 00294 itSegment != lSegmentPeriodList.end(); ++itSegment) { 00295 const stdair::SegmentPeriod* lCurrentSegment_ptr = *itSegment; 00296 assert (lCurrentSegment_ptr != NULL); 00297 const stdair::AirlineCode_T& lCurrentBoardingPoint = 00298 lCurrentSegment_ptr->getBoardingPoint(); 00299 if (lCurrentBoardingPoint == iDestination) { 00300 return true; 00301 } 00302 } 00303 return false; 00304 } 00305 00306 // //////////////////////////////////////////////////////////////////// 00307 bool SegmentPathPeriod:: 00308 isDepartureDateValid (const stdair::Date_T& iDepartureDate) const { 00309 const stdair::PeriodStruct& lPeriod = getDeparturePeriod (); 00310 00311 // Check if the departure date is within the date range. 00312 const stdair::DatePeriod_T& lDeparturePeriod = lPeriod.getDateRange (); 00313 if (lDeparturePeriod.contains (iDepartureDate) == false) { 00314 return false; 00315 } 00316 00317 // Check if the departure date is valid within the DOW. 00318 // 0 = Sunday, 1 = Monday, etc. 00319 const short lDay = iDepartureDate.day_of_week (); 00320 const stdair::DoWStruct& lDoW = lPeriod.getDoW (); 00321 if (lDoW.getStandardDayOfWeek (lDay) == false) { 00322 return false; 00323 } 00324 00325 return true; 00326 } 00327 00328 }