$treeview $search $mathjax
AirSched Logo  1.00.0
$projectbrief
$projectbrief
$searchbox

airsched.cpp

Go to the documentation of this file.
00001 // STL
00002 #include <cassert>
00003 #include <sstream>
00004 #include <fstream>
00005 #include <string>
00006 // Boost (Extended STL)
00007 #include <boost/date_time/posix_time/posix_time.hpp>
00008 #include <boost/date_time/gregorian/gregorian.hpp>
00009 #include <boost/program_options.hpp>
00010 #include <boost/tokenizer.hpp>
00011 #include <boost/lexical_cast.hpp>
00012 // StdAir
00013 #include <stdair/STDAIR_Service.hpp>
00014 #include <stdair/bom/BomDisplay.hpp>
00015 #include <stdair/bom/BookingRequestStruct.hpp>
00016 #include <stdair/bom/TravelSolutionStruct.hpp>
00017 #include <stdair/service/Logger.hpp>
00018 // AirSched
00019 #include <airsched/AIRSCHED_Service.hpp>
00020 #include <airsched/batches/BookingRequestParser.hpp>
00021 #include <airsched/config/airsched-paths.hpp>
00022 
00023 // //////// Type definitions ///////
00024 typedef std::vector<std::string> WordList_T;
00025 
00026 
00027 // //////// Constants //////
00031 const std::string K_AIRSCHED_DEFAULT_LOG_FILENAME ("airsched.log");
00032 
00036 const std::string K_AIRSCHED_DEFAULT_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00037                                                      "/schedule03.csv");
00038 
00044 const bool K_AIRSCHED_DEFAULT_BUILT_IN_INPUT = false;
00045 
00050 const bool K_AIRSCHED_DEFAULT_BOOKING_REQUEST_MODE = false;
00051 
00056 const std::string K_AIRSCHED_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");
00057 
00058 // //////////////////////////////////////////////////////////////////////
00059 std::string createStringFromWordList (const WordList_T& iWordList) {
00060   std::ostringstream oStr;
00061 
00062   unsigned short idx = iWordList.size();
00063   for (WordList_T::const_iterator itWord = iWordList.begin();
00064        itWord != iWordList.end(); ++itWord, --idx) {
00065     const std::string& lWord = *itWord;
00066     oStr << lWord;
00067     if (idx > 1) {
00068       oStr << " ";
00069     }
00070   }
00071   
00072   return oStr.str();
00073 }
00074 
00075 // ///////// Parsing of Options & Configuration /////////
00076 // A helper function to simplify the main part.
00077 template<class T> std::ostream& operator<< (std::ostream& os,
00078                                             const std::vector<T>& v) {
00079   std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " ")); 
00080   return os;
00081 }
00082 
00084 const int K_AIRSCHED_EARLY_RETURN_STATUS = 99;
00085 
00087 int readConfiguration (int argc, char* argv[],
00088                        bool& ioIsBuiltin, bool& ioReadBookingRequestFromCmdLine,
00089                        stdair::Filename_T& ioInputFilename,
00090                        std::string& ioLogFilename,
00091                        std::string& ioBookingRequestString) {
00092 
00093   // Default for the built-in input
00094   ioIsBuiltin = K_AIRSCHED_DEFAULT_BUILT_IN_INPUT;
00095   
00096   // Default for the booking request mode (whether it is read from command-line)
00097   ioReadBookingRequestFromCmdLine = K_AIRSCHED_DEFAULT_BOOKING_REQUEST_MODE;
00098 
00099   //
00100   WordList_T lWordList;
00101 
00102   // Declare a group of options that will be allowed only on command line
00103   boost::program_options::options_description generic ("Generic options");
00104   generic.add_options()
00105     ("prefix", "print installation prefix")
00106     ("version,v", "print version string")
00107     ("help,h", "produce help message");
00108     
00109   // Declare a group of options that will be allowed both on command
00110   // line and in config file
00111   boost::program_options::options_description config ("Configuration");
00112   config.add_options()
00113     ("builtin,b",
00114      "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")
00115     ("input,i",
00116      boost::program_options::value< std::string >(&ioInputFilename)->default_value(K_AIRSCHED_DEFAULT_INPUT_FILENAME),
00117      "(CSV) input file specifying the schedule (flight-period) entries")
00118     ("log,l",
00119      boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_AIRSCHED_DEFAULT_LOG_FILENAME),
00120      "Filename for the logs")
00121     ("read_booking_request,r",
00122      "Indicates that a booking request is given as a command-line option. That latter must then be given with the -b/--bkg_req option")
00123     ("bkg_req,q",
00124      boost::program_options::value< WordList_T >(&lWordList)->multitoken(),
00125      "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)")
00126     ;
00127 
00128   // Hidden options, will be allowed both on command line and
00129   // in config file, but will not be shown to the user.
00130   boost::program_options::options_description hidden ("Hidden options");
00131   hidden.add_options()
00132     ("copyright",
00133      boost::program_options::value< std::vector<std::string> >(),
00134      "Show the copyright (license)");
00135         
00136   boost::program_options::options_description cmdline_options;
00137   cmdline_options.add(generic).add(config).add(hidden);
00138 
00139   boost::program_options::options_description config_file_options;
00140   config_file_options.add(config).add(hidden);
00141 
00142   boost::program_options::options_description visible ("Allowed options");
00143   visible.add(generic).add(config);
00144         
00145   boost::program_options::positional_options_description p;
00146   p.add ("copyright", -1);
00147         
00148   boost::program_options::variables_map vm;
00149   boost::program_options::
00150     store (boost::program_options::command_line_parser (argc, argv).
00151            options (cmdline_options).positional(p).run(), vm);
00152 
00153   std::ifstream ifs ("airsched.cfg");
00154   boost::program_options::store (parse_config_file (ifs, config_file_options),
00155                                  vm);
00156   boost::program_options::notify (vm);
00157     
00158   if (vm.count ("help")) {
00159     std::cout << visible << std::endl;
00160     return K_AIRSCHED_EARLY_RETURN_STATUS;
00161   }
00162 
00163   if (vm.count ("version")) {
00164     std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00165     return K_AIRSCHED_EARLY_RETURN_STATUS;
00166   }
00167 
00168   if (vm.count ("prefix")) {
00169     std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00170     return K_AIRSCHED_EARLY_RETURN_STATUS;
00171   }
00172 
00173   if (vm.count ("builtin")) {
00174     ioIsBuiltin = true;
00175   }
00176   const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00177   std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00178 
00179   //
00180   std::ostringstream oErrorMessageStr;
00181   oErrorMessageStr << "Either the -b/--builtin option, or the -i/--input option"
00182                    << " must be specified";
00183 
00184   if (ioIsBuiltin == false) {
00185     if (vm.count ("input")) {
00186       ioInputFilename = vm["input"].as< std::string >();
00187       std::cout << "Input filename is: " << ioInputFilename << std::endl;
00188 
00189     } else {
00190       // The built-in option is not selected. However, no schedule input file
00191       // is specified
00192       std::cerr << oErrorMessageStr.str() << std::endl;
00193     }
00194   }
00195 
00196   //
00197   if (vm.count ("read_booking_request")) {
00198     ioReadBookingRequestFromCmdLine = true;
00199   }
00200   const std::string readBookingRequestFromCmdLineStr =
00201     (ioReadBookingRequestFromCmdLine == true)?"yes":"no";
00202   std::cout << "A booking request is to be given as command-line option? "
00203             << readBookingRequestFromCmdLineStr << std::endl;
00204 
00205   if (ioReadBookingRequestFromCmdLine == true) {
00206 
00207     if (lWordList.empty() == true) {
00208       std::cerr << "When the --read_booking_request/-r option is given, "
00209                 << "a query must also be provided (with the --bkg_req/-b "
00210                 << "option at the end of the command-line)" << std::endl;
00211       return K_AIRSCHED_EARLY_RETURN_STATUS;
00212     }
00213     
00214     // Rebuild the booking request query string
00215     ioBookingRequestString = createStringFromWordList (lWordList);
00216     std::cout << "The booking request string is: " << ioBookingRequestString
00217               << std::endl;
00218   }
00219 
00220   if (vm.count ("log")) {
00221     ioLogFilename = vm["log"].as< std::string >();
00222     std::cout << "Log filename is: " << ioLogFilename << std::endl;
00223   }
00224 
00225   return 0;
00226 }
00227 
00228 // //////////////////////////////////////////////////////////////
00229 stdair::BookingRequestStruct
00230 parseBookingRequest (const std::string& iRequestOption) {
00231   typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00232   boost::char_separator<char> sep(" -:");
00233 
00234   tokenizer tokens (iRequestOption, sep);
00235 
00236   // Origin (e.g., "NCE")
00237   tokenizer::iterator tok_iter = tokens.begin();
00238   assert (tok_iter != tokens.end());
00239   const stdair::AirportCode_T iOrigin (*tok_iter);
00240 
00241   // Destination (e.g., "BKK")
00242   ++tok_iter; assert (tok_iter != tokens.end());
00243   const stdair::AirportCode_T iDestination (*tok_iter);
00244   
00245   // POS (e.g., "NCE")
00246   ++tok_iter; assert (tok_iter != tokens.end());
00247   const stdair::AirportCode_T iPOS (*tok_iter);
00248   
00249   // Preferred departure date (e.g., "2007-04-21")
00250   ++tok_iter; assert (tok_iter != tokens.end());
00251   const short lDepDateYear = boost::lexical_cast<short> (*tok_iter);
00252   ++tok_iter; assert (tok_iter != tokens.end());
00253   const short lDepDateMonth = boost::lexical_cast<short> (*tok_iter);
00254   ++tok_iter; assert (tok_iter != tokens.end());
00255   const short lDepDateDay = boost::lexical_cast<short> (*tok_iter);
00256   const stdair::Date_T iDepartureDate(lDepDateYear, lDepDateMonth, lDepDateDay);
00257 
00258   // Request date (e.g., "2007-03-21")
00259   ++tok_iter; assert (tok_iter != tokens.end());
00260   const short lReqDateYear = boost::lexical_cast<short> (*tok_iter);
00261   ++tok_iter; assert (tok_iter != tokens.end());
00262   const short lReqDateMonth = boost::lexical_cast<short> (*tok_iter);
00263   ++tok_iter; assert (tok_iter != tokens.end());
00264   const short lReqDateDay = boost::lexical_cast<short> (*tok_iter);
00265   const stdair::Date_T iRequestDate (lReqDateYear, lReqDateMonth, lReqDateDay);
00266 
00267   // Request time (e.g., "08:34:23")
00268   ++tok_iter; assert (tok_iter != tokens.end());
00269   const short lReqTimeHours = boost::lexical_cast<short> (*tok_iter);
00270   ++tok_iter; assert (tok_iter != tokens.end());
00271   const short lReqTimeMinutes = boost::lexical_cast<short> (*tok_iter);
00272   ++tok_iter; assert (tok_iter != tokens.end());
00273   const short lReqTimeSeconds = boost::lexical_cast<short> (*tok_iter);
00274   const stdair::Duration_T iRequestTime (lReqTimeHours, lReqTimeMinutes,
00275                                          lReqTimeSeconds);
00276 
00277   // Request date-time (aggregation of the two items above)
00278   const stdair::DateTime_T iRequestDateTime (iRequestDate, iRequestTime);
00279   
00280   // Preferred cabin (e.g., "C")
00281   ++tok_iter; assert (tok_iter != tokens.end());
00282   const stdair::CabinCode_T iPreferredCabin (*tok_iter);
00283   
00284   // Party size (e.g., 1)
00285   ++tok_iter; assert (tok_iter != tokens.end());
00286   const stdair::NbOfSeats_T iPartySize = 1;
00287   
00288   // Channel (e.g., "DF")
00289   ++tok_iter; assert (tok_iter != tokens.end());
00290   const stdair::ChannelLabel_T iChannel (*tok_iter);
00291   
00292   // Trip type (e.g., "RO")
00293   ++tok_iter; assert (tok_iter != tokens.end());
00294   const stdair::TripType_T iTripType (*tok_iter);
00295   
00296   // Stay duration (e.g., 5)
00297   ++tok_iter; assert (tok_iter != tokens.end());
00298   const stdair::DayDuration_T iStayDuration = 5;
00299   
00300   // Frequent flyer (e.g., "NONE")
00301   ++tok_iter; assert (tok_iter != tokens.end());
00302   const stdair::FrequentFlyer_T iFrequentFlyerType ("NONE");
00303   
00304   // Preferred departure time (e.g., "10:00:00")
00305   ++tok_iter; assert (tok_iter != tokens.end());
00306   const short lPrefTimeHours = boost::lexical_cast<short> (*tok_iter);
00307   ++tok_iter; assert (tok_iter != tokens.end());
00308   const short lPrefTimeMinutes = boost::lexical_cast<short> (*tok_iter);
00309   ++tok_iter; assert (tok_iter != tokens.end());
00310   const short lPrefTimeSeconds = boost::lexical_cast<short> (*tok_iter);
00311   const stdair::Duration_T iPreferredDepartureTime (lPrefTimeHours,
00312                                                     lPrefTimeMinutes,
00313                                                     lPrefTimeSeconds);
00314 
00315   // Willingness-to-pay (e.g., 2000.0)
00316   ++tok_iter; assert (tok_iter != tokens.end());
00317   const stdair::WTP_T iWTP = 2000.0;
00318   
00319   // Value of time (e.g., 20.0)
00320   ++tok_iter; assert (tok_iter != tokens.end());
00321   const stdair::PriceValue_T iValueOfTime = 20.0;
00322   
00323   // Change fee acceptation (e.g., true)
00324   //++tok_iter; assert (tok_iter != tokens.end());
00325   const stdair::ChangeFees_T iChangeFees = true;
00326   const stdair::Disutility_T iChangeFeeDisutility = 50;
00327   
00328   // Non refundable acceptation (e.g., true)
00329   //++tok_iter; assert (tok_iter != tokens.end());
00330   const stdair::NonRefundable_T iNonRefundable = true;
00331   const stdair::Disutility_T iNonRefundableDisutility = 50;
00332 
00333   // Build and return the booking request structure
00334   return stdair::BookingRequestStruct (iOrigin,
00335                                        iDestination, iPOS,
00336                                        iDepartureDate, iRequestDateTime,
00337                                        iPreferredCabin, iPartySize,
00338                                        iChannel, iTripType, iStayDuration,
00339                                        iFrequentFlyerType,
00340                                        iPreferredDepartureTime, iWTP,
00341                                        iValueOfTime, iChangeFees,
00342                                        iChangeFeeDisutility, iNonRefundable,
00343                                        iNonRefundableDisutility);
00344 }
00345 
00346 // ///////// M A I N ////////////
00347 int main (int argc, char* argv[]) {
00348 
00349   // State whether the BOM tree should be built-in or parsed from an
00350   // input file
00351   bool isBuiltin;
00352 
00353   // A booking request should be given as command-line option
00354   bool readBookingRequestFromCmdLine;
00355     
00356   // Input file name
00357   stdair::Filename_T lInputFilename;
00358 
00359   // Output log File
00360   stdair::Filename_T lLogFilename;
00361 
00362   // Booking request string
00363   std::string lBookingRequestString;
00364     
00365   // Call the command-line option parser
00366   const int lOptionParserStatus = 
00367     readConfiguration (argc, argv, isBuiltin, readBookingRequestFromCmdLine,
00368                        lInputFilename, lLogFilename, lBookingRequestString);
00369 
00370   if (lOptionParserStatus == K_AIRSCHED_EARLY_RETURN_STATUS) {
00371     return 0;
00372   }
00373 
00374   // Set the log parameters
00375   std::ofstream logOutputFile;
00376   // Open and clean the log outputfile
00377   logOutputFile.open (lLogFilename.c_str());
00378   logOutputFile.clear();
00379 
00380   // Initialise the AirSched service object
00381   const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00382   AIRSCHED::AIRSCHED_Service airschedService (lLogParams);
00383 
00384   // Check wether or not (CSV) input files should be read
00385   if (isBuiltin == true) {
00386 
00387     // Build the sample BOM tree
00388     airschedService.buildSampleBom();
00389 
00390   } else {
00391     // Build the BOM tree from parsing input files
00392     const stdair::ScheduleFilePath lScheduleFilePath (lInputFilename);
00393     airschedService.parseAndLoad (lScheduleFilePath);
00394   }
00395 
00396   // Check wether or not a booking request is given as a command-line option
00397   if (readBookingRequestFromCmdLine == false) {
00398     lBookingRequestString = K_AIRSCHED_DEFAULT_BOOKING_REQUEST;
00399   }    
00400 
00401   // DEBUG
00402   STDAIR_LOG_DEBUG("Booking request string: '" << lBookingRequestString << "'");
00403 
00404   // Create a booking request object
00405   const stdair::BookingRequestStruct& lBookingRequest =
00406     parseBookingRequest (lBookingRequestString);
00407 
00408   //
00409   stdair::TravelSolutionList_T lTravelSolutionList;
00410   airschedService.buildSegmentPathList (lTravelSolutionList, lBookingRequest);
00411   
00412   // DEBUG
00413   STDAIR_LOG_DEBUG ("Parsed booking request: " << lBookingRequest);
00414 
00415   // DEBUG
00416   std::ostringstream oStream;
00417   stdair::BomDisplay::csvDisplay (oStream, lTravelSolutionList);
00418   STDAIR_LOG_DEBUG (oStream.str());
00419 
00420   // Close the Log outputFile
00421   logOutputFile.close();
00422 
00423   return 0;     
00424 }