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

simcrs.cpp

Go to the documentation of this file.
00001 // STL
00002 #include <sstream>
00003 #include <fstream>
00004 #include <string>
00005 // Boost (Extended STL)
00006 #include <boost/program_options.hpp>
00007 // StdAir
00008 #include <stdair/stdair_basic_types.hpp>
00009 #include <stdair/basic/BasLogParams.hpp>
00010 #include <stdair/basic/BasDBParams.hpp>
00011 #include <stdair/basic/BasFileMgr.hpp>
00012 #include <stdair/bom/TravelSolutionStruct.hpp>
00013 #include <stdair/bom/BookingRequestStruct.hpp>
00014 #include <stdair/service/Logger.hpp>
00015 // SimFQT
00016 #include <simfqt/SIMFQT_Types.hpp>
00017 // SimCRS
00018 #include <simcrs/SIMCRS_Service.hpp>
00019 #include <simcrs/config/simcrs-paths.hpp>
00020 
00021 // //////// Constants //////
00025 const std::string K_SIMCRS_DEFAULT_LOG_FILENAME ("simcrs.log");
00026 
00030 const std::string K_SIMCRS_DEFAULT_SCHEDULE_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00031                                                             "/schedule01.csv");
00032 
00036 const std::string K_SIMCRS_DEFAULT_OND_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00037                                                        "/ond01.csv");
00038 
00042 const std::string K_SIMCRS_DEFAULT_FRAT5_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00043                                                        "/frat5.csv");
00047 const std::string K_SIMCRS_DEFAULT_FF_DISUTILITY_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00048                                                                "/ffDisutility.csv");
00049 
00053 const std::string K_SIMCRS_DEFAULT_YIELD_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00054                                                          "/yieldstore01.csv");
00055     
00059 const std::string K_SIMCRS_DEFAULT_FARE_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00060                                                         "/fare01.csv");
00061 
00067 const bool K_SIMCRS_DEFAULT_BUILT_IN_INPUT = false;
00068 
00072 const std::string K_SIMCRS_DEFAULT_DB_USER ("dsim");
00073 const std::string K_SIMCRS_DEFAULT_DB_PASSWD ("dsim");
00074 const std::string K_SIMCRS_DEFAULT_DB_DBNAME ("sim_dsim");
00075 const std::string K_SIMCRS_DEFAULT_DB_HOST ("localhost");
00076 const std::string K_SIMCRS_DEFAULT_DB_PORT ("3306");
00077 
00078 // ///////// Parsing of Options & Configuration /////////
00079 // A helper function to simplify the main part.
00080 template<class T> std::ostream& operator<< (std::ostream& os,
00081                                             const std::vector<T>& v) {
00082   std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " ")); 
00083   return os;
00084 }
00085 
00087 const int K_SIMCRS_EARLY_RETURN_STATUS = 99;
00088 
00090 int readConfiguration (int argc, char* argv[],
00091                        bool& ioIsBuiltin,
00092                        stdair::Filename_T& ioScheduleInputFilename,
00093                        stdair::Filename_T& ioOnDInputFilename,
00094                        stdair::Filename_T& ioFRAT5Filename,
00095                        stdair::Filename_T& ioFFDisutilityFilename,
00096                        stdair::Filename_T& ioYieldInputFilename,
00097                        stdair::Filename_T& ioFareInputFilename,
00098                        stdair::Filename_T& ioLogFilename,
00099                        std::string& ioDBUser, std::string& ioDBPasswd,
00100                        std::string& ioDBHost, std::string& ioDBPort,
00101                        std::string& ioDBDBName) {
00102   // Default for the built-in input
00103   ioIsBuiltin = K_SIMCRS_DEFAULT_BUILT_IN_INPUT;
00104 
00105   // Declare a group of options that will be allowed only on command line
00106   boost::program_options::options_description generic ("Generic options");
00107   generic.add_options()
00108     ("prefix", "print installation prefix")
00109     ("version,v", "print version string")
00110     ("help,h", "produce help message");
00111     
00112   // Declare a group of options that will be allowed both on command
00113   // line and in config file
00114   boost::program_options::options_description config ("Configuration");
00115   config.add_options()
00116     ("builtin,b",
00117      "The sample BOM tree can be either built-in or parsed from input files. In that latter case, the input files must be specified as well (e.g., -s/--schedule,  -o/--ond, -f/--fare, -y/--yield)")
00118     ("schedule,s",
00119      boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_SIMCRS_DEFAULT_SCHEDULE_INPUT_FILENAME),
00120      "(CVS) input file for the schedules")
00121     ("ond,o",
00122      boost::program_options::value< std::string >(&ioOnDInputFilename)->default_value(K_SIMCRS_DEFAULT_OND_INPUT_FILENAME),
00123      "(CVS) input file for the O&D definitions")
00124     ("frat5,F",
00125      boost::program_options::value< std::string >(&ioFRAT5Filename)->default_value(K_SIMCRS_DEFAULT_FRAT5_INPUT_FILENAME),
00126      "(CSV) input file for the FRAT5 Curve")
00127     ("ff_disutility,D",
00128      boost::program_options::value< std::string >(&ioFFDisutilityFilename)->default_value(K_SIMCRS_DEFAULT_FF_DISUTILITY_INPUT_FILENAME),
00129      "(CSV) input file for the FF disutility Curve")
00130     ("yield,y",
00131      boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_SIMCRS_DEFAULT_YIELD_INPUT_FILENAME),
00132      "(CVS) input file for the yields")
00133     ("fare,f",
00134      boost::program_options::value< std::string >(&ioFareInputFilename)->default_value(K_SIMCRS_DEFAULT_FARE_INPUT_FILENAME),
00135      "(CVS) input file for the fares")
00136     ("log,l",
00137      boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_SIMCRS_DEFAULT_LOG_FILENAME),
00138      "Filepath for the logs")
00139     ("user,u",
00140      boost::program_options::value< std::string >(&ioDBUser)->default_value(K_SIMCRS_DEFAULT_DB_USER),
00141      "SQL database username")
00142     ("passwd,p",
00143      boost::program_options::value< std::string >(&ioDBPasswd)->default_value(K_SIMCRS_DEFAULT_DB_PASSWD),
00144      "SQL database password")
00145     ("host,H",
00146      boost::program_options::value< std::string >(&ioDBHost)->default_value(K_SIMCRS_DEFAULT_DB_HOST),
00147      "SQL database hostname")
00148     ("port,P",
00149      boost::program_options::value< std::string >(&ioDBPort)->default_value(K_SIMCRS_DEFAULT_DB_PORT),
00150      "SQL database port")
00151     ("dbname,m",
00152      boost::program_options::value< std::string >(&ioDBDBName)->default_value(K_SIMCRS_DEFAULT_DB_DBNAME),
00153      "SQL database name")
00154     ;
00155 
00156   // Hidden options, will be allowed both on command line and
00157   // in config file, but will not be shown to the user.
00158   boost::program_options::options_description hidden ("Hidden options");
00159   hidden.add_options()
00160     ("copyright",
00161      boost::program_options::value< std::vector<std::string> >(),
00162      "Show the copyright (license)");
00163         
00164   boost::program_options::options_description cmdline_options;
00165   cmdline_options.add(generic).add(config).add(hidden);
00166 
00167   boost::program_options::options_description config_file_options;
00168   config_file_options.add(config).add(hidden);
00169 
00170   boost::program_options::options_description visible ("Allowed options");
00171   visible.add(generic).add(config);
00172         
00173   boost::program_options::positional_options_description p;
00174   p.add ("copyright", -1);
00175         
00176   boost::program_options::variables_map vm;
00177   boost::program_options::
00178     store (boost::program_options::command_line_parser (argc, argv).
00179            options (cmdline_options).positional(p).run(), vm);
00180 
00181   std::ifstream ifs ("simcrs.cfg");
00182   boost::program_options::store (parse_config_file (ifs, config_file_options),
00183                                  vm);
00184   boost::program_options::notify (vm);
00185     
00186   if (vm.count ("help")) {
00187     std::cout << visible << std::endl;
00188     return K_SIMCRS_EARLY_RETURN_STATUS;
00189   }
00190 
00191   if (vm.count ("version")) {
00192     std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00193     return K_SIMCRS_EARLY_RETURN_STATUS;
00194   }
00195 
00196   if (vm.count ("prefix")) {
00197     std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00198     return K_SIMCRS_EARLY_RETURN_STATUS;
00199   }
00200 
00201   if (vm.count ("builtin")) {
00202     ioIsBuiltin = true;
00203   }
00204   const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00205   std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00206 
00207   //
00208   std::ostringstream oErrorMessageStr;
00209   oErrorMessageStr << "Either the -b/--builtin option, or the combination of "
00210                    << "the -s/--schedule, -o/--ond, -f/--fare and -y/--yield "
00211                    << "options must be specified";
00212 
00213   if (ioIsBuiltin == false) {
00214     if (vm.count ("schedule")) {
00215       ioScheduleInputFilename = vm["schedule"].as< std::string >();
00216       std::cout << "Schedule input filename is: " << ioScheduleInputFilename
00217                 << std::endl;
00218 
00219     } else {
00220       // The built-in option is not selected. However, no schedule input file
00221       // is specified
00222       std::cerr << oErrorMessageStr.str() << std::endl;
00223     }
00224 
00225     if (vm.count ("ond")) {
00226       ioOnDInputFilename = vm["ond"].as< std::string >();
00227       std::cout << "O&D input filename is: " << ioOnDInputFilename << std::endl;
00228 
00229     } else {
00230       // The built-in option is not selected. However, no schedule input file
00231       // is specified
00232       std::cerr << oErrorMessageStr.str() << std::endl;
00233     }
00234 
00235     if (vm.count ("frat5")) {
00236       ioFRAT5Filename = vm["frat5"].as< std::string >();
00237       std::cout << "FRAT5 input filename is: " << ioFRAT5Filename << std::endl;
00238 
00239     } else {
00240       // The built-in option is not selected. However, no frat5 input file
00241       // is specified
00242       std::cerr << oErrorMessageStr.str() << std::endl;
00243     }
00244 
00245     if (vm.count ("ff_disutility")) {
00246       ioFFDisutilityFilename = vm["ff_disutility"].as< std::string >();
00247       std::cout << "FF disutility input filename is: "
00248                 << ioFFDisutilityFilename << std::endl;
00249 
00250     } else {
00251       // The built-in option is not selected. However, no ff
00252       // disutility input file is specified
00253       std::cerr << oErrorMessageStr.str() << std::endl;
00254     }
00255 
00256     if (vm.count ("yield")) {
00257       ioYieldInputFilename = vm["yield"].as< std::string >();
00258       std::cout << "Yield input filename is: " << ioYieldInputFilename
00259                 << std::endl;
00260 
00261     } else {
00262       // The built-in option is not selected. However, no schedule input file
00263       // is specified
00264       std::cerr << oErrorMessageStr.str() << std::endl;
00265     }
00266 
00267     if (vm.count ("fare")) {
00268       ioFareInputFilename = vm["fare"].as< std::string >();
00269       std::cout << "Fare input filename is: " << ioFareInputFilename
00270                 << std::endl;
00271 
00272     } else {
00273       // The built-in option is not selected. However, no schedule input file
00274       // is specified
00275       std::cerr << oErrorMessageStr.str() << std::endl;
00276     }
00277   }
00278 
00279   if (vm.count ("log")) {
00280     ioLogFilename = vm["log"].as< std::string >();
00281     std::cout << "Log filename is: " << ioLogFilename << std::endl;
00282   }
00283 
00284   if (vm.count ("user")) {
00285     ioDBUser = vm["user"].as< std::string >();
00286     std::cout << "SQL database user name is: " << ioDBUser << std::endl;
00287   }
00288 
00289   if (vm.count ("passwd")) {
00290     ioDBPasswd = vm["passwd"].as< std::string >();
00291     //std::cout << "SQL database user password is: " << ioDBPasswd << std::endl;
00292   }
00293 
00294   if (vm.count ("host")) {
00295     ioDBHost = vm["host"].as< std::string >();
00296     std::cout << "SQL database host name is: " << ioDBHost << std::endl;
00297   }
00298 
00299   if (vm.count ("port")) {
00300     ioDBPort = vm["port"].as< std::string >();
00301     std::cout << "SQL database port number is: " << ioDBPort << std::endl;
00302   }
00303 
00304   if (vm.count ("dbname")) {
00305     ioDBDBName = vm["dbname"].as< std::string >();
00306     std::cout << "SQL database name is: " << ioDBDBName << std::endl;
00307   }
00308 
00309   return 0;
00310 }
00311 
00312 // ///////// M A I N ////////////
00313 int main (int argc, char* argv[]) {
00314 
00315   // State whether the BOM tree should be built-in or parsed from an
00316   // input file
00317   bool isBuiltin;
00318 
00319   // Schedule input filename
00320   stdair::Filename_T lScheduleInputFilename;
00321     
00322   // O&D input filename
00323   stdair::Filename_T lOnDInputFilename;
00324 
00325   // FRAT5 input filename
00326   std::string lFRAT5InputFilename;
00327 
00328   // FF disutility input filename
00329   std::string lFFDisutilityInputFilename;
00330     
00331   // Yield input filename
00332   stdair::Filename_T lYieldInputFilename;
00333     
00334   // Fare input filename
00335   stdair::Filename_T lFareInputFilename;
00336     
00337   // Output log File
00338   stdair::Filename_T lLogFilename;
00339 
00340   // SQL database parameters
00341   std::string lDBUser;
00342   std::string lDBPasswd;
00343   std::string lDBHost;
00344   std::string lDBPort;
00345   std::string lDBDBName;
00346                        
00347   // CRS code
00348   const SIMCRS::CRSCode_T lCRSCode ("1P");
00349     
00350   // Call the command-line option parser
00351   const int lOptionParserStatus = 
00352     readConfiguration (argc, argv, isBuiltin,
00353                        lScheduleInputFilename, lOnDInputFilename,
00354                        lFRAT5InputFilename, lFFDisutilityInputFilename,
00355                        lYieldInputFilename, lFareInputFilename, lLogFilename,
00356                        lDBUser, lDBPasswd, lDBHost, lDBPort, lDBDBName);
00357 
00358   if (lOptionParserStatus == K_SIMCRS_EARLY_RETURN_STATUS) {
00359     return 0;
00360   }
00361     
00362   // Set the database parameters
00363   const stdair::BasDBParams lDBParams (lDBUser, lDBPasswd, lDBHost, lDBPort,
00364                                        lDBDBName);
00365     
00366   // Set the log parameters
00367   std::ofstream logOutputFile;
00368   // Open and clean the log outputfile
00369   logOutputFile.open (lLogFilename.c_str());
00370   logOutputFile.clear();
00371     
00372   // Initialise the list of classes/buckets
00373   const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00374   SIMCRS::SIMCRS_Service simcrsService (lLogParams, lCRSCode);
00375 
00376   // Check wether or not (CSV) input files should be read
00377   if (isBuiltin == true) {
00378 
00379     // Build the sample BOM tree
00380     simcrsService.buildSampleBom();
00381 
00382   } else {
00383     // Build the BOM tree from parsing input files
00384     stdair::ScheduleFilePath lScheduleFilePath (lScheduleInputFilename);
00385     stdair::ODFilePath lODFilePath (lOnDInputFilename);
00386     stdair::FRAT5FilePath lFRAT5FilePath (lFRAT5InputFilename);
00387     stdair::FFDisutilityFilePath lFFDisutilityFilePath (lFFDisutilityInputFilename);
00388     const SIMFQT::FareFilePath lFareFilePath (lFareInputFilename);
00389     const AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
00390     simcrsService.parseAndLoad (lScheduleFilePath, lODFilePath,
00391                                 lFRAT5FilePath, lFFDisutilityFilePath,
00392                                 lYieldFilePath, lFareFilePath);
00393   }
00394 
00395   // TODO (issue #37707): instead of building a sample, read the parameters
00396   //      from the command-line options, and build the corresponding
00397   //      booking request
00398   const bool isForCRS = true;
00399   const stdair::BookingRequestStruct& lBookingRequest =
00400     simcrsService.buildSampleBookingRequest (isForCRS);
00401 
00402   // Calculate the travel solutions corresponding to the given booking request
00403   stdair::TravelSolutionList_T lTravelSolutionList =
00404     simcrsService.calculateSegmentPathList (lBookingRequest);
00405   
00406   // Check whether everything was fine
00407   if (lTravelSolutionList.empty() == true) {
00408     STDAIR_LOG_ERROR ("No travel solution has been found for: "
00409                       << lBookingRequest.display());
00410     return -1;
00411   }
00412 
00413   // Price the travel solution
00414   simcrsService.fareQuote (lBookingRequest, lTravelSolutionList);
00415 
00416   // Choose a random travel solution: the first one.
00417   stdair::TravelSolutionStruct& lChosenTravelSolution =
00418     lTravelSolutionList.front();
00419 
00420   // Get the segment path of the travel solution.
00421   const stdair::KeyList_T& lsegmentDateKeyList =
00422     lChosenTravelSolution.getSegmentPath();
00423 
00424   const stdair::FareOptionList_T& lFareOptionList =
00425     lChosenTravelSolution.getFareOptionList();
00426 
00427   // Check whether everything was fine
00428   if (lFareOptionList.empty() == true) {
00429     STDAIR_LOG_ERROR ("No fare option for the chosen travel solution: "
00430                       << lChosenTravelSolution.display());
00431     return -1;
00432   }
00433 
00434   //
00435   const stdair::FareOptionStruct& lFareOption = lFareOptionList.front();
00436   lChosenTravelSolution.setChosenFareOption (lFareOption);
00437 
00438   // DEBUG
00439   const std::string& lSegmentDateKey = lsegmentDateKeyList.front();
00440   STDAIR_LOG_DEBUG ("The chosen travel solution is: " << lSegmentDateKey
00441                     << ", the fare is: " << lFareOption.getFare() << " Euros.");
00442 
00443   // Make a booking (reminder: party size is 3)
00444   const stdair::PartySize_T lPartySize (3);
00445   const bool isSellSuccessful =
00446     simcrsService.sell (lChosenTravelSolution, lPartySize);
00447 
00448   // DEBUG
00449   STDAIR_LOG_DEBUG ("Sale ('" << lBookingRequest << "'): "
00450                     << " successful? " << isSellSuccessful);
00451 
00452   // DEBUG: Display the whole BOM tree
00453   const std::string& lCSVDump = simcrsService.csvDisplay();
00454   STDAIR_LOG_DEBUG (lCSVDump);
00455 
00456   // Close the Log outputFile
00457   logOutputFile.close();
00458 
00459   /*
00460     Note: as that program is not intended to be run on a server in
00461     production, it is better not to catch the exceptions. When it
00462     happens (that an exception is throwned), that way we get the
00463     call stack.
00464   */
00465 
00466   return 0;
00467 }