$treeview $search $mathjax
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 }