AirTSP Logo  1.01.0
C++ Simulated Airline Travel Solution Provider Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
airtsp.cpp
Go to the documentation of this file.
1 // STL
2 #include <cassert>
3 #include <sstream>
4 #include <fstream>
5 #include <string>
6 // Boost (Extended STL)
7 #include <boost/date_time/posix_time/posix_time.hpp>
8 #include <boost/date_time/gregorian/gregorian.hpp>
9 #include <boost/program_options.hpp>
10 #include <boost/tokenizer.hpp>
11 #include <boost/lexical_cast.hpp>
12 // StdAir
13 #include <stdair/STDAIR_Service.hpp>
14 #include <stdair/bom/BomDisplay.hpp>
15 #include <stdair/bom/BookingRequestStruct.hpp>
16 #include <stdair/bom/TravelSolutionStruct.hpp>
17 #include <stdair/service/Logger.hpp>
18 // AirTSP
21 #include <airtsp/config/airtsp-paths.hpp>
22 
23 // //////// Type definitions ///////
24 typedef std::vector<std::string> WordList_T;
25 
26 
27 // //////// Constants //////
31 const std::string K_AIRTSP_DEFAULT_LOG_FILENAME ("airtsp.log");
32 
36 const std::string K_AIRTSP_DEFAULT_INPUT_FILENAME (STDAIR_SAMPLE_DIR
37  "/schedule03.csv");
38 
45 
51 
56 const std::string K_AIRTSP_DEFAULT_BOOKING_REQUEST ("NCE BKK NCE 2007-04-21 2007-03-21 08:32:00 C 1 DF RO 5 NONE 10:00:00 2000.0 20.0");
57 
58 // //////////////////////////////////////////////////////////////////////
59 std::string createStringFromWordList (const WordList_T& iWordList) {
60  std::ostringstream oStr;
61 
62  unsigned short idx = iWordList.size();
63  for (WordList_T::const_iterator itWord = iWordList.begin();
64  itWord != iWordList.end(); ++itWord, --idx) {
65  const std::string& lWord = *itWord;
66  oStr << lWord;
67  if (idx > 1) {
68  oStr << " ";
69  }
70  }
71 
72  return oStr.str();
73 }
74 
75 // ///////// Parsing of Options & Configuration /////////
76 // A helper function to simplify the main part.
77 template<class T> std::ostream& operator<< (std::ostream& os,
78  const std::vector<T>& v) {
79  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
80  return os;
81 }
82 
85 
87 int readConfiguration (int argc, char* argv[],
88  bool& ioIsBuiltin, bool& ioReadBookingRequestFromCmdLine,
89  stdair::Filename_T& ioInputFilename,
90  std::string& ioLogFilename,
91  std::string& ioBookingRequestString) {
92 
93  // Default for the built-in input
94  ioIsBuiltin = K_AIRTSP_DEFAULT_BUILT_IN_INPUT;
95 
96  // Default for the booking request mode (whether it is read from command-line)
97  ioReadBookingRequestFromCmdLine = K_AIRTSP_DEFAULT_BOOKING_REQUEST_MODE;
98 
99  //
100  WordList_T lWordList;
101 
102  // Declare a group of options that will be allowed only on command line
103  boost::program_options::options_description generic ("Generic options");
104  generic.add_options()
105  ("prefix", "print installation prefix")
106  ("version,v", "print version string")
107  ("help,h", "produce help message");
108 
109  // Declare a group of options that will be allowed both on command
110  // line and in config file
111  boost::program_options::options_description config ("Configuration");
112  config.add_options()
113  ("builtin,b",
114  "The sample BOM tree can be either built-in or parsed from input files. In that latter case, the -i/--input option must be specified as well")
115  ("input,i",
116  boost::program_options::value< std::string >(&ioInputFilename)->default_value(K_AIRTSP_DEFAULT_INPUT_FILENAME),
117  "(CSV) input file specifying the schedule (flight-period) entries")
118  ("log,l",
119  boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_AIRTSP_DEFAULT_LOG_FILENAME),
120  "Filename for the logs")
121  ("read_booking_request,r",
122  "Indicates that a booking request is given as a command-line option. That latter must then be given with the -b/--bkg_req option")
123  ("bkg_req,q",
124  boost::program_options::value< WordList_T >(&lWordList)->multitoken(),
125  "Booking request word list (e.g. 'NCE BKK NCE 2007-04-21 2007-04-21 10:00:00 C 1 DF RO 5 NONE 10:0:0 2000.0 20.0'), which should be located at the end of the command line (otherwise, the other options would be interpreted as part of that booking request word list)")
126  ;
127 
128  // Hidden options, will be allowed both on command line and
129  // in config file, but will not be shown to the user.
130  boost::program_options::options_description hidden ("Hidden options");
131  hidden.add_options()
132  ("copyright",
133  boost::program_options::value< std::vector<std::string> >(),
134  "Show the copyright (license)");
135 
136  boost::program_options::options_description cmdline_options;
137  cmdline_options.add(generic).add(config).add(hidden);
138 
139  boost::program_options::options_description config_file_options;
140  config_file_options.add(config).add(hidden);
141 
142  boost::program_options::options_description visible ("Allowed options");
143  visible.add(generic).add(config);
144 
145  boost::program_options::positional_options_description p;
146  p.add ("copyright", -1);
147 
148  boost::program_options::variables_map vm;
149  boost::program_options::
150  store (boost::program_options::command_line_parser (argc, argv).
151  options (cmdline_options).positional(p).run(), vm);
152 
153  std::ifstream ifs ("airtsp.cfg");
154  boost::program_options::store (parse_config_file (ifs, config_file_options),
155  vm);
156  boost::program_options::notify (vm);
157 
158  if (vm.count ("help")) {
159  std::cout << visible << std::endl;
161  }
162 
163  if (vm.count ("version")) {
164  std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
166  }
167 
168  if (vm.count ("prefix")) {
169  std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
171  }
172 
173  if (vm.count ("builtin")) {
174  ioIsBuiltin = true;
175  }
176  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
177  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
178 
179  //
180  std::ostringstream oErrorMessageStr;
181  oErrorMessageStr << "Either the -b/--builtin option, or the -i/--input option"
182  << " must be specified";
183 
184  if (ioIsBuiltin == false) {
185  if (vm.count ("input")) {
186  ioInputFilename = vm["input"].as< std::string >();
187  std::cout << "Input filename is: " << ioInputFilename << std::endl;
188 
189  } else {
190  // The built-in option is not selected. However, no schedule input file
191  // is specified
192  std::cerr << oErrorMessageStr.str() << std::endl;
193  }
194  }
195 
196  //
197  if (vm.count ("read_booking_request")) {
198  ioReadBookingRequestFromCmdLine = true;
199  }
200  const std::string readBookingRequestFromCmdLineStr =
201  (ioReadBookingRequestFromCmdLine == true)?"yes":"no";
202  std::cout << "A booking request is to be given as command-line option? "
203  << readBookingRequestFromCmdLineStr << std::endl;
204 
205  if (ioReadBookingRequestFromCmdLine == true) {
206 
207  if (lWordList.empty() == true) {
208  std::cerr << "When the --read_booking_request/-r option is given, "
209  << "a query must also be provided (with the --bkg_req/-b "
210  << "option at the end of the command-line)" << std::endl;
212  }
213 
214  // Rebuild the booking request query string
215  ioBookingRequestString = createStringFromWordList (lWordList);
216  std::cout << "The booking request string is: " << ioBookingRequestString
217  << std::endl;
218  }
219 
220  if (vm.count ("log")) {
221  ioLogFilename = vm["log"].as< std::string >();
222  std::cout << "Log filename is: " << ioLogFilename << std::endl;
223  }
224 
225  return 0;
226 }
227 
228 // //////////////////////////////////////////////////////////////
229 stdair::BookingRequestStruct
230 parseBookingRequest (const std::string& iRequestOption) {
231  typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
232  boost::char_separator<char> sep(" -:");
233 
234  tokenizer tokens (iRequestOption, sep);
235 
236  // Origin (e.g., "NCE")
237  tokenizer::iterator tok_iter = tokens.begin();
238  assert (tok_iter != tokens.end());
239  const stdair::AirportCode_T iOrigin (*tok_iter);
240 
241  // Destination (e.g., "BKK")
242  ++tok_iter; assert (tok_iter != tokens.end());
243  const stdair::AirportCode_T iDestination (*tok_iter);
244 
245  // POS (e.g., "NCE")
246  ++tok_iter; assert (tok_iter != tokens.end());
247  const stdair::AirportCode_T iPOS (*tok_iter);
248 
249  // Preferred departure date (e.g., "2007-04-21")
250  ++tok_iter; assert (tok_iter != tokens.end());
251  const short lDepDateYear = boost::lexical_cast<short> (*tok_iter);
252  ++tok_iter; assert (tok_iter != tokens.end());
253  const short lDepDateMonth = boost::lexical_cast<short> (*tok_iter);
254  ++tok_iter; assert (tok_iter != tokens.end());
255  const short lDepDateDay = boost::lexical_cast<short> (*tok_iter);
256  const stdair::Date_T iDepartureDate(lDepDateYear, lDepDateMonth, lDepDateDay);
257 
258  // Request date (e.g., "2007-03-21")
259  ++tok_iter; assert (tok_iter != tokens.end());
260  const short lReqDateYear = boost::lexical_cast<short> (*tok_iter);
261  ++tok_iter; assert (tok_iter != tokens.end());
262  const short lReqDateMonth = boost::lexical_cast<short> (*tok_iter);
263  ++tok_iter; assert (tok_iter != tokens.end());
264  const short lReqDateDay = boost::lexical_cast<short> (*tok_iter);
265  const stdair::Date_T iRequestDate (lReqDateYear, lReqDateMonth, lReqDateDay);
266 
267  // Request time (e.g., "08:34:23")
268  ++tok_iter; assert (tok_iter != tokens.end());
269  const short lReqTimeHours = boost::lexical_cast<short> (*tok_iter);
270  ++tok_iter; assert (tok_iter != tokens.end());
271  const short lReqTimeMinutes = boost::lexical_cast<short> (*tok_iter);
272  ++tok_iter; assert (tok_iter != tokens.end());
273  const short lReqTimeSeconds = boost::lexical_cast<short> (*tok_iter);
274  const stdair::Duration_T iRequestTime (lReqTimeHours, lReqTimeMinutes,
275  lReqTimeSeconds);
276 
277  // Request date-time (aggregation of the two items above)
278  const stdair::DateTime_T iRequestDateTime (iRequestDate, iRequestTime);
279 
280  // Preferred cabin (e.g., "C")
281  ++tok_iter; assert (tok_iter != tokens.end());
282  const stdair::CabinCode_T iPreferredCabin (*tok_iter);
283 
284  // Party size (e.g., 1)
285  ++tok_iter; assert (tok_iter != tokens.end());
286  const stdair::NbOfSeats_T iPartySize = 1;
287 
288  // Channel (e.g., "DF")
289  ++tok_iter; assert (tok_iter != tokens.end());
290  const stdair::ChannelLabel_T iChannel (*tok_iter);
291 
292  // Trip type (e.g., "RO")
293  ++tok_iter; assert (tok_iter != tokens.end());
294  const stdair::TripType_T iTripType (*tok_iter);
295 
296  // Stay duration (e.g., 5)
297  ++tok_iter; assert (tok_iter != tokens.end());
298  const stdair::DayDuration_T iStayDuration = 5;
299 
300  // Frequent flyer (e.g., "NONE")
301  ++tok_iter; assert (tok_iter != tokens.end());
302  const stdair::FrequentFlyer_T iFrequentFlyerType ("NONE");
303 
304  // Preferred departure time (e.g., "10:00:00")
305  ++tok_iter; assert (tok_iter != tokens.end());
306  const short lPrefTimeHours = boost::lexical_cast<short> (*tok_iter);
307  ++tok_iter; assert (tok_iter != tokens.end());
308  const short lPrefTimeMinutes = boost::lexical_cast<short> (*tok_iter);
309  ++tok_iter; assert (tok_iter != tokens.end());
310  const short lPrefTimeSeconds = boost::lexical_cast<short> (*tok_iter);
311  const stdair::Duration_T iPreferredDepartureTime (lPrefTimeHours,
312  lPrefTimeMinutes,
313  lPrefTimeSeconds);
314 
315  // Willingness-to-pay (e.g., 2000.0)
316  ++tok_iter; assert (tok_iter != tokens.end());
317  const stdair::WTP_T iWTP = 2000.0;
318 
319  // Value of time (e.g., 20.0)
320  ++tok_iter; assert (tok_iter != tokens.end());
321  const stdair::PriceValue_T iValueOfTime = 20.0;
322 
323  // Change fee acceptation (e.g., true)
324  //++tok_iter; assert (tok_iter != tokens.end());
325  const stdair::ChangeFees_T iChangeFees = true;
326  const stdair::Disutility_T iChangeFeeDisutility = 50;
327 
328  // Non refundable acceptation (e.g., true)
329  //++tok_iter; assert (tok_iter != tokens.end());
330  const stdair::NonRefundable_T iNonRefundable = true;
331  const stdair::Disutility_T iNonRefundableDisutility = 50;
332 
333  // Build and return the booking request structure
334  return stdair::BookingRequestStruct (iOrigin,
335  iDestination, iPOS,
336  iDepartureDate, iRequestDateTime,
337  iPreferredCabin, iPartySize,
338  iChannel, iTripType, iStayDuration,
339  iFrequentFlyerType,
340  iPreferredDepartureTime, iWTP,
341  iValueOfTime, iChangeFees,
342  iChangeFeeDisutility, iNonRefundable,
343  iNonRefundableDisutility);
344 }
345 
346 // ///////// M A I N ////////////
347 int main (int argc, char* argv[]) {
348 
349  // State whether the BOM tree should be built-in or parsed from an
350  // input file
351  bool isBuiltin;
352 
353  // A booking request should be given as command-line option
354  bool readBookingRequestFromCmdLine;
355 
356  // Input file name
357  stdair::Filename_T lInputFilename;
358 
359  // Output log File
360  stdair::Filename_T lLogFilename;
361 
362  // Booking request string
363  std::string lBookingRequestString;
364 
365  // Call the command-line option parser
366  const int lOptionParserStatus =
367  readConfiguration (argc, argv, isBuiltin, readBookingRequestFromCmdLine,
368  lInputFilename, lLogFilename, lBookingRequestString);
369 
370  if (lOptionParserStatus == K_AIRTSP_EARLY_RETURN_STATUS) {
371  return 0;
372  }
373 
374  // Set the log parameters
375  std::ofstream logOutputFile;
376  // Open and clean the log outputfile
377  logOutputFile.open (lLogFilename.c_str());
378  logOutputFile.clear();
379 
380  // Initialise the AirTSP service object
381  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
382  AIRTSP::AIRTSP_Service airtspService (lLogParams);
383 
384  // Check wether or not (CSV) input files should be read
385  if (isBuiltin == true) {
386 
387  // Build the sample BOM tree
388  airtspService.buildSampleBom();
389 
390  } else {
391  // Build the BOM tree from parsing input files
392  const stdair::ScheduleFilePath lScheduleFilePath (lInputFilename);
393  airtspService.parseAndLoad (lScheduleFilePath);
394  }
395 
396  // Check wether or not a booking request is given as a command-line option
397  if (readBookingRequestFromCmdLine == false) {
398  lBookingRequestString = K_AIRTSP_DEFAULT_BOOKING_REQUEST;
399  }
400 
401  // DEBUG
402  STDAIR_LOG_DEBUG("Booking request string: '" << lBookingRequestString << "'");
403 
404  // Create a booking request object
405  const stdair::BookingRequestStruct& lBookingRequest =
406  parseBookingRequest (lBookingRequestString);
407 
408  //
409  stdair::TravelSolutionList_T lTravelSolutionList;
410  airtspService.buildSegmentPathList (lTravelSolutionList, lBookingRequest);
411 
412  // DEBUG
413  STDAIR_LOG_DEBUG ("Parsed booking request: " << lBookingRequest);
414 
415  // DEBUG
416  std::ostringstream oStream;
417  stdair::BomDisplay::csvDisplay (oStream, lTravelSolutionList);
418  STDAIR_LOG_DEBUG (oStream.str());
419 
420  // Close the Log outputFile
421  logOutputFile.close();
422 
423  return 0;
424 }