AirTSP Logo  1.01.0
C++ Simulated Airline Travel Solution Provider Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SegmentPathPeriod.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 #include <sstream>
7 // Boost.Serialization
8 #include <boost/archive/text_iarchive.hpp>
9 #include <boost/archive/text_oarchive.hpp>
10 #include <boost/serialization/access.hpp>
11 // StdAir
12 #include <stdair/basic/BasConst_General.hpp>
13 #include <stdair/basic/BasConst_Inventory.hpp>
14 #include <stdair/basic/BasConst_Period_BOM.hpp>
15 #include <stdair/basic/BasConst_TravelSolution.hpp>
16 #include <stdair/bom/Inventory.hpp>
17 #include <stdair/bom/FlightPeriod.hpp>
18 #include <stdair/bom/SegmentPeriod.hpp>
19 #include <stdair/bom/BomManager.hpp>
20 // AirTSP
22 
23 namespace AIRTSP {
24 
25  // ////////////////////////////////////////////////////////////////////
26  SegmentPathPeriod::SegmentPathPeriod()
27  : _key (stdair::PeriodStruct (stdair::BOOST_DEFAULT_DATE_PERIOD,
28  stdair::DEFAULT_DOW_STRING),
29  stdair::NULL_BOOST_TIME_DURATION, stdair::NULL_BOOST_TIME_DURATION,
31  stdair::DEFAULT_NBOFAIRLINES),
32  _parent (NULL) {
33  assert (false);
34  }
35 
36  // ////////////////////////////////////////////////////////////////////
37  SegmentPathPeriod::SegmentPathPeriod (const SegmentPathPeriod& iSPP)
38  : _key (iSPP._key), _parent (NULL) {
39  assert (false);
40  }
41 
42  // ////////////////////////////////////////////////////////////////////
43  SegmentPathPeriod::SegmentPathPeriod (const Key_T& iKey)
44  : _key (iKey), _parent (NULL) {
45  }
46 
47  // ////////////////////////////////////////////////////////////////////
49  }
50 
51  // ////////////////////////////////////////////////////////////////////
52  std::string SegmentPathPeriod::toString() const {
53  std::ostringstream oStr;
54  oStr << _key.toString();
55  return oStr.str();
56  }
57 
58  // ////////////////////////////////////////////////////////////////////
59  void SegmentPathPeriod::serialisationImplementationExport() const {
60  std::ostringstream oStr;
61  boost::archive::text_oarchive oa (oStr);
62  oa << *this;
63  }
64 
65  // ////////////////////////////////////////////////////////////////////
66  void SegmentPathPeriod::serialisationImplementationImport() {
67  std::istringstream iStr;
68  boost::archive::text_iarchive ia (iStr);
69  ia >> *this;
70  }
71 
72  // ////////////////////////////////////////////////////////////////////
73  template<class Archive>
74  void SegmentPathPeriod::serialize (Archive& ioArchive,
75  const unsigned int iFileVersion) {
76  ioArchive & _key;
77  }
78 
79  // ////////////////////////////////////////////////////////////////////
80  // Explicit template instantiation
81  namespace ba = boost::archive;
82  template
83  void SegmentPathPeriod::serialize<ba::text_oarchive> (ba::text_oarchive&,
84  unsigned int);
85  template
86  void SegmentPathPeriod::serialize<ba::text_iarchive> (ba::text_iarchive&,
87  unsigned int);
88  // ////////////////////////////////////////////////////////////////////
89 
90  // ////////////////////////////////////////////////////////////////////
91  stdair::SegmentPeriod* SegmentPathPeriod::getLastSegmentPeriod () const {
92  // Retrieve the last segment of the list
93  const stdair::SegmentPeriodList_T& lSegmentPeriodList =
94  stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
95  stdair::SegmentPeriodList_T::const_reverse_iterator itLastSegment =
96  lSegmentPeriodList.rbegin();
97 
98  if (itLastSegment == lSegmentPeriodList.rend()) {
99  return NULL;
100  }
101 
102  stdair::SegmentPeriod* oSegment_ptr = *itLastSegment;
103  assert (oSegment_ptr != NULL);
104 
105  return oSegment_ptr;
106  }
107 
108  // ////////////////////////////////////////////////////////////////////
109  stdair::SegmentPeriod* SegmentPathPeriod::getFirstSegmentPeriod () const{
110  // Retrieve the first segment of the list
111  const stdair::SegmentPeriodList_T& lSegmentPeriodList =
112  stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
113  stdair::SegmentPeriodList_T::const_iterator itFirstSegment =
114  lSegmentPeriodList.begin();
115 
116  if (itFirstSegment == lSegmentPeriodList.end()) {
117  return NULL;
118  }
119 
120  stdair::SegmentPeriod* oSegment_ptr = *itFirstSegment;
121  assert (oSegment_ptr != NULL);
122 
123  return oSegment_ptr;
124  }
125 
126  // ////////////////////////////////////////////////////////////////////
127  const stdair::AirportCode_T& SegmentPathPeriod::getDestination () const {
128  const stdair::SegmentPeriod* lLastSegment_ptr = getLastSegmentPeriod();
129  assert (lLastSegment_ptr != NULL);
130  return lLastSegment_ptr->getOffPoint();
131  }
132 
133  // ////////////////////////////////////////////////////////////////////
135  isAirlineFlown (const stdair::AirlineCode_T& iAirlineCode) const {
136  bool oAirlineFlown = false;
137 
138  const stdair::SegmentPeriodList_T& lSegmentPeriodList =
139  stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
140  for (stdair::SegmentPeriodList_T::const_iterator itSegmentPeriod =
141  lSegmentPeriodList.begin();
142  itSegmentPeriod != lSegmentPeriodList.end(); ++itSegmentPeriod) {
143  const stdair::SegmentPeriod* lSegmentPeriod_ptr = *itSegmentPeriod;
144  assert (lSegmentPeriod_ptr != NULL);
145 
146  const stdair::FlightPeriod& lFlightPeriod =
147  stdair::BomManager::getParent<stdair::FlightPeriod>(*lSegmentPeriod_ptr);
148  const stdair::Inventory& lInventory =
149  stdair::BomManager::getParent<stdair::Inventory> (lFlightPeriod);
150  const stdair::AirlineCode_T& lSegmentAirlineCode =
151  lInventory.getAirlineCode ();
152  if (lSegmentAirlineCode == iAirlineCode) {
153  oAirlineFlown = true;
154  break;
155  }
156  }
157 
158  return oAirlineFlown;
159  }
160 
161  // ////////////////////////////////////////////////////////////////////
163  connectWithAnotherSegment(const SegmentPathPeriod& iSingleSegmentPath) const {
164  SegmentPathPeriodKey oSegmentPathPeriodKey;
165 
166  // Retrieve the (only) segment period of the single segment path.
167  const stdair::SegmentPeriod* lNextSegmentPeriod_ptr =
168  iSingleSegmentPath.getFirstSegmentPeriod();
169  assert (lNextSegmentPeriod_ptr != NULL);
170 
171  // Retrive the last segment period of the current segment path and check
172  // if the combination of the last segment and the next segment that we
173  // want to add to the current segment path will create a new segment
174  // (i.e., the two segment period belongs to the same flight number).
175  const stdair::SegmentPeriod* lLastSegmentPeriod_ptr = getLastSegmentPeriod ();
176  assert (lLastSegmentPeriod_ptr != NULL);
177  const stdair::FlightPeriod& lLastFlightPeriod = stdair::BomManager::
178  getParent<stdair::FlightPeriod> (*lLastSegmentPeriod_ptr);
179  const stdair::Inventory& lLastInventory =
180  stdair::BomManager::getParent<stdair::Inventory> (lLastFlightPeriod);
181 
182  const stdair::FlightPeriod& lNextFlightPeriod = stdair::BomManager::
183  getParent<stdair::FlightPeriod> (*lNextSegmentPeriod_ptr);
184  const stdair::Inventory& lNextInventory =
185  stdair::BomManager::getParent<stdair::Inventory> (lNextFlightPeriod);
186 
187  if (lLastFlightPeriod.getFlightNumber()==lNextFlightPeriod.getFlightNumber()
188  && lLastInventory.getAirlineCode() == lNextInventory.getAirlineCode()) {
189  return oSegmentPathPeriodKey;
190  }
191 
192  // Check if the new segment period will create a circle.
193  const stdair::AirportCode_T& lDestination =
194  lNextSegmentPeriod_ptr->getOffPoint();
195  if (checkCircle (lDestination) == true) {
196  return oSegmentPathPeriodKey;
197  }
198 
199  // Check if a passenger can connect from the last segment of the
200  // current segment path to the first segment of the to-be-added
201  // segment path. If yes, build a new departure period for the new
202  // segment path.
203  DateOffsetList_T lBoardingDateOffsetList =
205  const stdair::PeriodStruct& lCurrentDeparturePeriod = getDeparturePeriod();
206  const stdair::PeriodStruct& lNextDeparturePeriod =
207  iSingleSegmentPath.getDeparturePeriod();
208  const stdair::Duration_T& lLastOffTime =
209  lLastSegmentPeriod_ptr->getOffTime();
210  const stdair::Duration_T& lNextBoardingTime =
211  lNextSegmentPeriod_ptr->getBoardingTime();
212  // If the next boarding time is later than the last off time, check if
213  // the passengers will have enough time for the transfer. If the next
214  // boarding time is earlier than the last off time, check if the passengers
215  // can connect to a flight in the next day.
216  if (lNextBoardingTime >= lLastOffTime) {
217  const stdair::Duration_T lStopTime = lNextBoardingTime - lLastOffTime;
218  if (lStopTime < stdair::DEFAULT_MINIMAL_CONNECTION_TIME) {
219  return oSegmentPathPeriodKey;
220  } else {
221  // Calulcate the date offset of the next segment compare to
222  // the first one. In this case, this value is equal to the offset
223  // of the off date of the last segment compare to the boarding date
224  // of the first segment.
225  const stdair::DateOffset_T& lLastBoardingDateOffset =
226  lBoardingDateOffsetList.at (getNbOfSegments() - 1);
227  const stdair::DateOffset_T lNextBoardingDateOffset =
228  lLastBoardingDateOffset + lLastSegmentPeriod_ptr->getOffDateOffset()
229  - lLastSegmentPeriod_ptr->getBoardingDateOffset();
230  const stdair::DateOffset_T lNegativeNextBoardingDateOffset =
231  stdair::DateOffset_T (0) - lNextBoardingDateOffset;
232 
233  // Compute the adjusted departure period of the next segment by
234  // substracting the origin one with the boarding date offset.
235  const stdair::PeriodStruct lAdjustedNextDeparturePeriod =
236  lNextDeparturePeriod.addDateOffset (lNegativeNextBoardingDateOffset);
237 
238  // Build the intersection of the two periods.
239  const stdair::PeriodStruct lNewDeparturePeriod =
240  lCurrentDeparturePeriod.intersection (lAdjustedNextDeparturePeriod);
241  stdair::Duration_T lNewElapsed = getElapsedTime() + lStopTime +
242  lNextSegmentPeriod_ptr->getElapsedTime();
243  lBoardingDateOffsetList.push_back (lNextBoardingDateOffset);
244  oSegmentPathPeriodKey.setPeriod (lNewDeparturePeriod);
245  oSegmentPathPeriodKey.setElapsedTime (lNewElapsed);
246  }
247  } else {
248  const stdair::Duration_T lStopTime =
249  lNextBoardingTime - lLastOffTime + stdair::Duration_T (24, 0, 0);
250  if (lStopTime < stdair::DEFAULT_MINIMAL_CONNECTION_TIME) {
251  return oSegmentPathPeriodKey;
252  } else {
253  // Calulcate the date offset of the next segment compare to
254  // the first one.
255  const stdair::DateOffset_T& lLastBoardingDateOffset =
256  lBoardingDateOffsetList.at (getNbOfSegments() - 1);
257  const stdair::DateOffset_T lNextBoardingDateOffset =
258  lLastBoardingDateOffset + lLastSegmentPeriod_ptr->getOffDateOffset()
259  - lLastSegmentPeriod_ptr->getBoardingDateOffset() +
260  stdair::DateOffset_T (1);
261  const stdair::DateOffset_T lNegativeNextBoardingDateOffset =
262  stdair::DateOffset_T (0) - lNextBoardingDateOffset;
263 
264  // Compute the adjusted departure period of the next segment by
265  // substracting the origin one with the boarding date offset.
266  const stdair::PeriodStruct lAdjustedNextDeparturePeriod =
267  lNextDeparturePeriod.addDateOffset (lNegativeNextBoardingDateOffset);
268 
269  // Build the intersection of the two periods.
270  const stdair::PeriodStruct lNewDeparturePeriod =
271  lCurrentDeparturePeriod.intersection (lAdjustedNextDeparturePeriod);
272  stdair::Duration_T lNewElapsed = getElapsedTime() + lStopTime +
273  lNextSegmentPeriod_ptr->getElapsedTime();
274  lBoardingDateOffsetList.push_back (lNextBoardingDateOffset);
275  oSegmentPathPeriodKey.setPeriod (lNewDeparturePeriod);
276  oSegmentPathPeriodKey.setElapsedTime (lNewElapsed);
277  }
278  }
279 
280  const stdair::Duration_T& lBoardingTime = getBoardingTime();
281  oSegmentPathPeriodKey.setBoardingTime (lBoardingTime);
282  oSegmentPathPeriodKey.setBoardingDateOffsetList (lBoardingDateOffsetList);
283 
284  return oSegmentPathPeriodKey;
285  }
286 
287  // ////////////////////////////////////////////////////////////////////
289  checkCircle (const stdair::AirlineCode_T& iDestination) const {
290  const stdair::SegmentPeriodList_T& lSegmentPeriodList =
291  stdair::BomManager::getList<stdair::SegmentPeriod> (*this);
292  for (stdair::SegmentPeriodList_T::const_iterator itSegment =
293  lSegmentPeriodList.begin();
294  itSegment != lSegmentPeriodList.end(); ++itSegment) {
295  const stdair::SegmentPeriod* lCurrentSegment_ptr = *itSegment;
296  assert (lCurrentSegment_ptr != NULL);
297  const stdair::AirlineCode_T& lCurrentBoardingPoint =
298  lCurrentSegment_ptr->getBoardingPoint();
299  if (lCurrentBoardingPoint == iDestination) {
300  return true;
301  }
302  }
303  return false;
304  }
305 
306  // ////////////////////////////////////////////////////////////////////
308  isDepartureDateValid (const stdair::Date_T& iDepartureDate) const {
309  const stdair::PeriodStruct& lPeriod = getDeparturePeriod ();
310 
311  // Check if the departure date is within the date range.
312  const stdair::DatePeriod_T& lDeparturePeriod = lPeriod.getDateRange ();
313  if (lDeparturePeriod.contains (iDepartureDate) == false) {
314  return false;
315  }
316 
317  // Check if the departure date is valid within the DOW.
318  // 0 = Sunday, 1 = Monday, etc.
319  const short lDay = iDepartureDate.day_of_week ();
320  const stdair::DoWStruct& lDoW = lPeriod.getDoW ();
321  if (lDoW.getStandardDayOfWeek (lDay) == false) {
322  return false;
323  }
324 
325  return true;
326  }
327 
328 }