AirInv Logo  1.00.0
C++ Simulated Airline Inventory Management System library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SegmentCabinHelper.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 #include <sstream>
7 #include <limits>
8 // StdAir
9 #include <stdair/basic/BasConst_Inventory.hpp>
10 #include <stdair/basic/float_utils.hpp>
11 #include <stdair/bom/BomManager.hpp>
12 #include <stdair/bom/FlightDate.hpp>
13 #include <stdair/bom/LegCabin.hpp>
14 #include <stdair/bom/SegmentCabin.hpp>
15 #include <stdair/bom/FareFamily.hpp>
16 #include <stdair/bom/BookingClass.hpp>
17 #include <stdair/bom/SimpleNestingStructure.hpp>
18 #include <stdair/bom/NestingNode.hpp>
19 #include <stdair/bom/Policy.hpp>
20 #include <stdair/factory/FacBomManager.hpp>
21 // AirInv
24 
25 namespace AIRINV {
26 
27  // ////////////////////////////////////////////////////////////////////
28  void SegmentCabinHelper::initialiseAU (stdair::SegmentCabin& iSegmentCabin) {
29 
30  // Initialise the capacity and availability pool.
31  const stdair::LegCabinList_T& lLCList =
32  stdair::BomManager::getList<stdair::LegCabin> (iSegmentCabin);
33 
34  stdair::CabinCapacity_T lCapacity =
35  std::numeric_limits<stdair::CabinCapacity_T>::max();
36  for (stdair::LegCabinList_T::const_iterator itLC = lLCList.begin();
37  itLC != lLCList.end(); ++itLC) {
38 
39  const stdair::LegCabin* lLC_ptr = *itLC;
40  assert (lLC_ptr != NULL);
41 
42  const stdair::CabinCapacity_T& lCabinCap = lLC_ptr->getOfferedCapacity();
43  if (lCapacity > lCabinCap) {
44  lCapacity = lCabinCap;
45  }
46  }
47  iSegmentCabin.setCapacity (lCapacity);
48  iSegmentCabin.setAvailabilityPool (lCapacity);
49 
50  // Browse the list of booking classes and set the AU of each booking
51  // class to the availability pool of the cabin.
52  const stdair::BookingClassList_T& lBCList =
53  stdair::BomManager::getList<stdair::BookingClass> (iSegmentCabin);
54  for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
55  itBC != lBCList.end(); ++itBC) {
56  stdair::BookingClass* lBC_ptr = *itBC;
57  assert (lBC_ptr != NULL);
58  lBC_ptr->setAuthorizationLevel (lCapacity);
59  }
60  }
61 
62  // ////////////////////////////////////////////////////////////////////
64  updateFromReservation (const stdair::FlightDate& iFlightDate,
65  stdair::SegmentCabin& ioSegmentCabin,
66  const stdair::PartySize_T& iNbOfBookings){
67  // Update the commited space of the segment-cabin.
68  ioSegmentCabin.updateFromReservation (iNbOfBookings);
69 
70  // Update the availability of the flight-date.
71  FlightDateHelper::updateAvailability (iFlightDate, ioSegmentCabin,
72  iNbOfBookings);
73  }
74 
75  // ////////////////////////////////////////////////////////////////////
77  buildPseudoBidPriceVector (stdair::SegmentCabin& ioSegmentCabin) {
78  // Retrieve the segment-cabin capacity.
79  const stdair::Availability_T& lAvlPool =
80  ioSegmentCabin.getAvailabilityPool();
81  unsigned int lAvlPoolInt;
82  if (lAvlPool < 0) {
83  lAvlPoolInt = 0;
84  } else {
85  assert (lAvlPool >= 0);
86  lAvlPoolInt = static_cast<unsigned int> (lAvlPool);
87  }
88  stdair::BidPriceVector_T lPseudoBidPriceVector (lAvlPoolInt, 0.0);
89 
90  // Browse the leg-cabin list.
91  const stdair::LegCabinList_T& lLCList =
92  stdair::BomManager::getList<stdair::LegCabin> (ioSegmentCabin);
93  for (stdair::LegCabinList_T::const_iterator itLC = lLCList.begin();
94  itLC != lLCList.end(); ++itLC) {
95  const stdair::LegCabin* lLC_ptr = *itLC;
96  assert (lLC_ptr != NULL);
97 
98  const stdair::BidPriceVector_T& lBPV = lLC_ptr->getBidPriceVector();
99  stdair::BidPriceVector_T::const_reverse_iterator itBP = lBPV.rbegin();
100  for (stdair::BidPriceVector_T::reverse_iterator itPBP =
101  lPseudoBidPriceVector.rbegin();
102  itPBP != lPseudoBidPriceVector.rend(); ++itPBP, ++itBP) {
103  assert (itBP != lBPV.rend());
104  stdair::BidPrice_T& lCurrentPBP = *itPBP;
105  const stdair::BidPrice_T& lCurrentBP = *itBP;
106  lCurrentPBP += lCurrentBP;
107  }
108  }
109 
110  ioSegmentCabin.setBidPriceVector (lPseudoBidPriceVector);
111 
112  // // DEBUG
113  // std::ostringstream oStr;
114  // oStr << "Pseudo BPV: ";
115  // for (stdair::BidPriceVector_T::const_iterator itBP =
116  // lPseudoBidPriceVector.begin(); itBP != lPseudoBidPriceVector.end();
117  // ++itBP) {
118  // const stdair::BidPrice_T& lCurrentBP = *itBP;
119  // oStr << lCurrentBP << " ";
120  // }
121  // oStr << std::endl;
122  // // STDAIR_LOG_DEBUG (oStr.str());
123  // std::cout << oStr.str() << std::endl;
124  }
125 
126  // ////////////////////////////////////////////////////////////////////
128  updateBookingControlsUsingPseudoBidPriceVector (const stdair::SegmentCabin& iSegmentCabin) {
129  // Retrieve the pseudo bid price vector.
130  const stdair::BidPriceVector_T& lPseudoBPV =
131  iSegmentCabin.getBidPriceVector();
132  const stdair::Availability_T& lAvlPool= iSegmentCabin.getAvailabilityPool();
133 
134  // Update the cumulative booking limit for all booking classes.
135  // Browse the nesting structure
136  const stdair::SimpleNestingStructure& lYieldBasedNestingStructure =
137  stdair::BomManager::getObject<stdair::SimpleNestingStructure>(iSegmentCabin, stdair::YIELD_BASED_NESTING_STRUCTURE_CODE);
138  const stdair::NestingNodeList_T& lNestingNodeList =
139  stdair::BomManager::getList<stdair::NestingNode>(lYieldBasedNestingStructure);
140  for (stdair::NestingNodeList_T::const_iterator itNS =
141  lNestingNodeList.begin();
142  itNS != lNestingNodeList.end(); ++itNS) {
143  stdair::NestingNode* lNestingNode_ptr = *itNS;
144  assert (lNestingNode_ptr != NULL);
145  const stdair::Yield_T lNodeYield =
146  lNestingNode_ptr->getYield();
147  if (lNodeYield < 0) {
148  continue;
149  }
150  const stdair::BookingClassList_T& lBCList =
151  stdair::BomManager::getList<stdair::BookingClass> (*lNestingNode_ptr);
152  stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
153  assert(itBC != lBCList.end());
154  // Browse the booking class list of the current node
155  const stdair::Yield_T& lYield = lNestingNode_ptr->getYield();
156  const FloatingPoint<double> lYieldFlotingPoint (lYield);
157  stdair::BookingLimit_T lCumuBL = lAvlPool;
158  for (stdair::BidPriceVector_T::const_reverse_iterator itBP =
159  lPseudoBPV.rbegin(); itBP != lPseudoBPV.rend(); ++itBP) {
160  const stdair::BidPrice_T& lBP = *itBP;
161  const FloatingPoint<double> lBPFlotingPoint (lBP);
162  const bool isAlmostEqual =
163  lYieldFlotingPoint.AlmostEquals(lBPFlotingPoint);
164 
165  if ((lYield < lBP) && (isAlmostEqual == false)) {
166  lCumuBL = itBP - lPseudoBPV.rbegin();
167  break;
168  }
169  }
170  for (; itBC != lBCList.end(); ++itBC) {
171  stdair::BookingClass* lBC_ptr = *itBC;
172  assert (lBC_ptr != NULL);
173  lBC_ptr->setCumulatedBookingLimit (lCumuBL);
174  // DEBUG
175  // STDAIR_LOG_DEBUG("Updating the BL for class: "
176  // << lBC_ptr->describeKey()
177  // << ", with yield " << lNodeYield
178  // << " and BL: " << lCumuBL);
179  }
180  }
181  // Update the authorization levels from the booking limits
182  updateAUs (iSegmentCabin);
183  }
184 
185  // ////////////////////////////////////////////////////////////////////
186  void SegmentCabinHelper::updateAUs(const stdair::SegmentCabin& iSegmentCabin){
187  // Browse the nesting structure and compute the AU from the
188  // cumulative booking counter and the cumulative booking limit.
189  stdair::NbOfBookings_T lCumulativeBookingCounter = 0.0;
190  // Browse the nesting structure
191  const stdair::SimpleNestingStructure& lYieldBasedNestingStructure =
192  stdair::BomManager::getObject<stdair::SimpleNestingStructure>(iSegmentCabin, stdair::YIELD_BASED_NESTING_STRUCTURE_CODE);
193  const stdair::NestingNodeList_T& lNestingNodeList =
194  stdair::BomManager::getList<stdair::NestingNode>(lYieldBasedNestingStructure);
195  for (stdair::NestingNodeList_T::const_reverse_iterator itNS =
196  lNestingNodeList.rbegin();
197  itNS != lNestingNodeList.rend(); ++itNS) {
198  stdair::NestingNode* lNestingNode_ptr = *itNS;
199  assert (lNestingNode_ptr != NULL);
200  const stdair::Yield_T lNodeYield =
201  lNestingNode_ptr->getYield();
202  if (lNodeYield < 0) {
203  continue;
204  }
205  const stdair::BookingClassList_T& lBCList =
206  stdair::BomManager::getList<stdair::BookingClass> (*lNestingNode_ptr);
207  stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
208  assert(itBC != lBCList.end());
209  const stdair::BookingLimit_T& lCumuBookingLimit =
210  (*itBC)->getCumulatedBookingLimit();
211  // Browse the booking class list of the current node to update the
212  // cumulative booking counter
213  for (; itBC != lBCList.end(); ++itBC) {
214  stdair::BookingClass* lBC_ptr = *itBC;
215  assert (lBC_ptr != NULL);
216  assert(lCumuBookingLimit == lBC_ptr->getCumulatedBookingLimit());
217  const stdair::NbOfBookings_T& lNbOfBookings = lBC_ptr->getNbOfBookings();
218  lCumulativeBookingCounter += lNbOfBookings;
219  }
220  stdair::AuthorizationLevel_T lAU =
221  lCumulativeBookingCounter + lCumuBookingLimit;
222  // Browse the booking class list of the current node to set
223  // the authorization level of all booking classes of the node
224  for (itBC = lBCList.begin(); itBC != lBCList.end(); ++itBC) {
225  stdair::BookingClass* lBC_ptr = *itBC;
226  assert (lBC_ptr != NULL);
227  lBC_ptr->setAuthorizationLevel (lAU);
228  // DEBUG
229  // STDAIR_LOG_DEBUG ("Updating the AU for class: "
230  // << lBC_ptr->describeKey()
231  // << ", with BL: " << lCumuBookingLimit
232  // << ", CumuBkg: " << lCumulativeBookingCounter
233  // << ", AU: " << lAU);
234  }
235  }
236  }
237 
238  // ////////////////////////////////////////////////////////////////////
240  updateAvailabilities (const stdair::SegmentCabin& iSegmentCabin) {
241  // Browse the nesting structure and compute the avl from the
242  // cumulative booking counter and the AU.
243  stdair::NbOfBookings_T lCumulativeBookingCounter = 0.0;
244  const stdair::SimpleNestingStructure& lYieldBasedNestingStructure =
245  stdair::BomManager::getObject<stdair::SimpleNestingStructure>(iSegmentCabin, stdair::YIELD_BASED_NESTING_STRUCTURE_CODE);
246  const stdair::NestingNodeList_T& lNestingNodeList =
247  stdair::BomManager::getList<stdair::NestingNode>(lYieldBasedNestingStructure);
248  for (stdair::NestingNodeList_T::const_reverse_iterator itNS =
249  lNestingNodeList.rbegin();
250  itNS != lNestingNodeList.rend(); ++itNS) {
251  stdair::NestingNode* lNestingNode_ptr = *itNS;
252  assert (lNestingNode_ptr != NULL);
253  const stdair::Yield_T& lNodeYield = lNestingNode_ptr->getYield();
254  if (lNodeYield < 0) {
255  continue;
256  }
257  const stdair::BookingClassList_T& lBCList =
258  stdair::BomManager::getList<stdair::BookingClass> (*lNestingNode_ptr);
259  stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
260  assert(itBC != lBCList.end());
261  stdair::BookingClass* lFirstBC_ptr = *itBC;
262  assert (lFirstBC_ptr != NULL);
263  const stdair::AuthorizationLevel_T& lNodeAU =
264  lFirstBC_ptr->getAuthorizationLevel();
265  // Browse the booking class list of the current node to update the
266  // cumulative booking counter
267  for (; itBC != lBCList.end(); ++itBC) {
268  stdair::BookingClass* lBC_ptr = *itBC;
269  assert (lBC_ptr != NULL);
270  assert(lNodeAU == lBC_ptr->getAuthorizationLevel());
271  const stdair::NbOfBookings_T& lNbOfBookings = lBC_ptr->getNbOfBookings();
272  lCumulativeBookingCounter += lNbOfBookings;
273  }
274  const stdair::Availability_T lNodeAvl = lNodeAU - lCumulativeBookingCounter;
275  // Browse the booking class list of the current node to set
276  // the availability of all booking classes of the node
277  for (itBC = lBCList.begin(); itBC != lBCList.end(); ++itBC) {
278  stdair::BookingClass* lBC_ptr = *itBC;
279  assert (lBC_ptr != NULL);
280  lBC_ptr->setSegmentAvailability (lNodeAvl);
281  }
282  }
283 
284  // Cascading
285  stdair::NestingNodeList_T::const_iterator itCurrentNode =
286  lNestingNodeList.begin();
287  assert (itCurrentNode != lNestingNodeList.end());
288  stdair::NestingNodeList_T::const_iterator itNextNode = itCurrentNode;
289  ++itNextNode;
290  for (; itNextNode != lNestingNodeList.end(); ++itCurrentNode, ++itNextNode) {
291  assert(itCurrentNode != lNestingNodeList.end());
292  stdair::NestingNode* lCurrentNode_ptr = *itCurrentNode;
293  assert (lCurrentNode_ptr != NULL);
294  const stdair::Yield_T& lCurrentNodeYield = lCurrentNode_ptr->getYield();
295  if (lCurrentNodeYield < 0) {
296  break;
297  }
298  const stdair::BookingClassList_T& lCurrentBCList =
299  stdair::BomManager::getList<stdair::BookingClass> (*lCurrentNode_ptr);
300  stdair::BookingClassList_T::const_iterator itCurrentBC =
301  lCurrentBCList.begin();
302  stdair::BookingClass* lCurrentBC_ptr = *(itCurrentBC);
303  assert (lCurrentBC_ptr != NULL);
304  assert(itNextNode != lNestingNodeList.end());
305  stdair::NestingNode* lNextNode_ptr = *itNextNode;
306  assert (lNextNode_ptr != NULL);
307  const stdair::Yield_T& lNextNodeYield = lNextNode_ptr->getYield();
308  if (lNextNodeYield < 0) {
309  break;
310  }
311  const stdair::BookingClassList_T& lNextBCList =
312  stdair::BomManager::getList<stdair::BookingClass> (*lNextNode_ptr);
313  stdair::BookingClassList_T::const_iterator itNextBC =
314  lNextBCList.begin();
315  stdair::BookingClass* lNextBC_ptr = *(itNextBC);
316  assert (lNextBC_ptr != NULL);
317  const stdair::Availability_T& lCurrentAvl =
318  lCurrentBC_ptr->getSegmentAvailability();
319  const stdair::Availability_T& lNextAvl =
320  lNextBC_ptr->getSegmentAvailability();
321  if (lCurrentAvl < lNextAvl) {
322  for (; itNextBC != lNextBCList.end(); ++itNextBC) {
323  lNextBC_ptr = *itNextBC;
324  assert (lNextBC_ptr != NULL);
325  lNextBC_ptr->setSegmentAvailability (lCurrentAvl);
326  }
327  }
328  }
329  }
330 
331  // ////////////////////////////////////////////////////////////////////
333  initYieldBasedNestingStructure (stdair::SegmentCabin& ioSegmentCabin) {
334  // Create the nesting structure.
335  stdair::NestingStructureKey lKey (stdair::YIELD_BASED_NESTING_STRUCTURE_CODE);
336  stdair::SimpleNestingStructure& lNestingStructure =
337  stdair::FacBom<stdair::SimpleNestingStructure>::instance().create(lKey);
338  stdair::FacBomManager::addToListAndMap (ioSegmentCabin, lNestingStructure);
339  stdair::FacBomManager::linkWithParent (ioSegmentCabin, lNestingStructure);
340 
341  // Build a multimap of booking classes with their yields as keys.
342  std::multimap<const stdair::Yield_T, stdair::BookingClass*> lClassMap;
343  const stdair::BookingClassList_T& lBCList =
344  stdair::BomManager::getList<stdair::BookingClass> (ioSegmentCabin);
345  for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
346  itBC != lBCList.end(); ++itBC) {
347  stdair::BookingClass* lBC_ptr = *itBC;
348  assert (lBC_ptr != NULL);
349  const stdair::Yield_T& lYield = lBC_ptr->getYield();
350  lClassMap.insert(std::multimap<const stdair::Yield_T, stdair::BookingClass*>::value_type(lYield, lBC_ptr));
351  }
352 
353  stdair::Yield_T lLastYield = -1.0;
354  stdair::NestingNode* lCurrentNode_ptr = NULL;
355  for (std::multimap<const stdair::Yield_T, stdair::BookingClass*>::reverse_iterator itBC = lClassMap.rbegin();
356  itBC != lClassMap.rend(); ++itBC) {
357  const stdair::Yield_T& lCurrentYield = itBC->first;
358  stdair::BookingClass* lBC_ptr = itBC->second;
359 
360  // Compare the current yield and the last one.
361  // TODO: use float utils
362  //if (lCurrentYield.AlmostEquals (lLastYield) == false) {
363  if (lCurrentYield != lLastYield) {
364  // Create a nesting node
365  stdair::NestingNodeCode_T lNodeCode (lBC_ptr->describeKey());
366  stdair::NestingNodeKey lNodeKey (lNodeCode);
367  stdair::NestingNode& lNestingNode =
368  stdair::FacBom<stdair::NestingNode>::instance().create (lNodeKey);
369  stdair::FacBomManager::addToList (lNestingStructure, lNestingNode);
370  stdair::FacBomManager::linkWithParent (lNestingStructure, lNestingNode);
371  lCurrentNode_ptr = &lNestingNode;
372  lCurrentNode_ptr->setYield(lCurrentYield);
373  // Add the booking class to the node.
374  stdair::FacBomManager::addToList (lNestingNode, *lBC_ptr);
375  lLastYield = lCurrentYield;
376  } else {
377  // Add the booking class to the current node.
378  stdair::FacBomManager::addToList (*lCurrentNode_ptr, *lBC_ptr);
379  }
380  }
381  }
382 
383  // ////////////////////////////////////////////////////////////////////
385  initListOfUsablePolicies (stdair::SegmentCabin& ioSegmentCabin) {
386  const stdair::FareFamilyList_T& lFareFamilyList =
387  stdair::BomManager::getList<stdair::FareFamily> (ioSegmentCabin);
388  stdair::FareFamilyList_T::const_iterator itFF = lFareFamilyList.begin();
389 
390  unsigned int lPolicyCounter = 0;
391  std::ostringstream oStr;
392  oStr << lPolicyCounter;
393  stdair::PolicyKey lKey (oStr.str());
394  stdair::Policy& lPolicy =
395  stdair::FacBom<stdair::Policy>::instance().create(lKey);
396  stdair::FacBomManager::addToList (ioSegmentCabin, lPolicy);
397  stdair::FacBomManager::linkWithParent (ioSegmentCabin, lPolicy);
398  createPolicies (ioSegmentCabin, lFareFamilyList, itFF, lPolicy,
399  lPolicyCounter,
400  std::numeric_limits<stdair::Yield_T>::max());
401  }
402 
403  // ////////////////////////////////////////////////////////////////////
404  void SegmentCabinHelper::
405  createPolicies (stdair::SegmentCabin& ioSegmentCabin,
406  const stdair::FareFamilyList_T& iFareFamilyList,
407  const stdair::FareFamilyList_T::const_iterator& itFF,
408  stdair::Policy& ioCurrentPolicy,
409  unsigned int& ioPolicyCounter,
410  const stdair::Yield_T& iPreviousYield) {
411  if (itFF != iFareFamilyList.end()) {
412  // We add a booking class of the next Fare Family if it is cheapest than
413  // the previous booking class in the policy.
414  // Assumption: the fare family list is sorted according to their fares:
415  // Fare_1 > Fare_2 > ... > Fare_n
416  const stdair::FareFamily* lFF_ptr = *itFF;
417  //Retrieve the booking class list of the current fare family
418  const stdair::BookingClassList_T& lBookingClassList =
419  stdair::BomManager::getList<stdair::BookingClass> (*lFF_ptr);
420  stdair::BookingClassList_T::const_iterator itBC =
421  lBookingClassList.begin();
422  stdair::FareFamilyList_T::const_iterator lItFF = itFF;
423  lItFF++;
424 
425  // Browse the booking class list
426  for (; itBC != lBookingClassList.end(); ++itBC) {
427  stdair::BookingClass* lBC_ptr = *itBC;
428  assert(lBC_ptr != NULL);
429  const stdair::Yield_T& lCurrentYield = lBC_ptr->getYield();
430  if (lCurrentYield >= iPreviousYield) {
431  continue;
432  }
433  assert(lCurrentYield < iPreviousYield);
434  // Add the current booking class to the list, update the current policy
435  // and call the same method for the next fare family
436  ++ioPolicyCounter;
437  std::ostringstream oStr;
438  oStr << ioPolicyCounter;
439  stdair::PolicyKey lKey (oStr.str());
440  stdair::Policy& lNewPolicy =
441  stdair::FacBom<stdair::Policy>::instance().create(lKey);
442  stdair::FacBomManager::addToList (ioSegmentCabin, lNewPolicy);
443  stdair::FacBomManager::linkWithParent (ioSegmentCabin, lNewPolicy);
444 
445  // Copy the list of booking classes of the current policy to the new one
446  bool hasAListOfBC =
447  stdair::BomManager::hasList<stdair::BookingClass> (ioCurrentPolicy);
448  if (hasAListOfBC == true) {
449  const stdair::BookingClassList_T& lToBeCopiedBCList =
450  stdair::BomManager::getList<stdair::BookingClass> (ioCurrentPolicy);
451  for (stdair::BookingClassList_T::const_iterator itBCToBeCopied =
452  lToBeCopiedBCList.begin();
453  itBCToBeCopied != lToBeCopiedBCList.end(); ++itBCToBeCopied) {
454  stdair::BookingClass* lBCToBeCopied_ptr = *itBCToBeCopied;
455  assert (lBCToBeCopied_ptr != NULL);
456  stdair::FacBomManager::addToList (lNewPolicy, *lBCToBeCopied_ptr);
457  }
458  }
459  stdair::FacBomManager::addToList(lNewPolicy, *lBC_ptr);
460 
461  createPolicies (ioSegmentCabin, iFareFamilyList, lItFF, lNewPolicy,
462  ioPolicyCounter, lCurrentYield);
463  }
464  }
465 
466  }
467 
468 }