SimCRS Logo  0.1.1
C++ Simulated Travel-Oriented Distribution System Library
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros Pages
simcrs.cpp
Go to the documentation of this file.
1 // STL
2 #include <sstream>
3 #include <fstream>
4 #include <string>
5 // Boost (Extended STL)
6 #include <boost/program_options.hpp>
7 // StdAir
8 #include <stdair/stdair_basic_types.hpp>
9 #include <stdair/basic/BasLogParams.hpp>
10 #include <stdair/basic/BasDBParams.hpp>
11 #include <stdair/basic/BasFileMgr.hpp>
12 #include <stdair/bom/TravelSolutionStruct.hpp>
13 #include <stdair/bom/BookingRequestStruct.hpp>
14 #include <stdair/service/Logger.hpp>
15 // SimFQT
16 #include <simfqt/SIMFQT_Types.hpp>
17 // SimCRS
20 
21 // //////// Constants //////
25 const std::string K_SIMCRS_DEFAULT_LOG_FILENAME ("simcrs.log");
26 
31  "/schedule01.csv");
32 
37  "/ond01.csv");
38 
43  "/yieldstore01.csv");
44 
49  "/fare01.csv");
50 
57 
61 const std::string K_SIMCRS_DEFAULT_DB_USER ("dsim");
62 const std::string K_SIMCRS_DEFAULT_DB_PASSWD ("dsim");
63 const std::string K_SIMCRS_DEFAULT_DB_DBNAME ("sim_dsim");
64 const std::string K_SIMCRS_DEFAULT_DB_HOST ("localhost");
65 const std::string K_SIMCRS_DEFAULT_DB_PORT ("3306");
66 
67 // ///////// Parsing of Options & Configuration /////////
68 // A helper function to simplify the main part.
69 template<class T> std::ostream& operator<< (std::ostream& os,
70  const std::vector<T>& v) {
71  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
72  return os;
73 }
74 
77 
79 int readConfiguration (int argc, char* argv[],
80  bool& ioIsBuiltin,
81  stdair::Filename_T& ioScheduleInputFilename,
82  stdair::Filename_T& ioOnDInputFilename,
83  stdair::Filename_T& ioYieldInputFilename,
84  stdair::Filename_T& ioFareInputFilename,
85  stdair::Filename_T& ioLogFilename,
86  std::string& ioDBUser, std::string& ioDBPasswd,
87  std::string& ioDBHost, std::string& ioDBPort,
88  std::string& ioDBDBName) {
89  // Default for the built-in input
90  ioIsBuiltin = K_SIMCRS_DEFAULT_BUILT_IN_INPUT;
91 
92  // Declare a group of options that will be allowed only on command line
93  boost::program_options::options_description generic ("Generic options");
94  generic.add_options()
95  ("prefix", "print installation prefix")
96  ("version,v", "print version string")
97  ("help,h", "produce help message");
98 
99  // Declare a group of options that will be allowed both on command
100  // line and in config file
101  boost::program_options::options_description config ("Configuration");
102  config.add_options()
103  ("builtin,b",
104  "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)")
105  ("schedule,s",
106  boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_SIMCRS_DEFAULT_SCHEDULE_INPUT_FILENAME),
107  "(CVS) input file for the schedules")
108  ("ond,o",
109  boost::program_options::value< std::string >(&ioOnDInputFilename)->default_value(K_SIMCRS_DEFAULT_OND_INPUT_FILENAME),
110  "(CVS) input file for the O&D definitions")
111  ("yield,y",
112  boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_SIMCRS_DEFAULT_YIELD_INPUT_FILENAME),
113  "(CVS) input file for the yields")
114  ("fare,f",
115  boost::program_options::value< std::string >(&ioFareInputFilename)->default_value(K_SIMCRS_DEFAULT_FARE_INPUT_FILENAME),
116  "(CVS) input file for the fares")
117  ("log,l",
118  boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_SIMCRS_DEFAULT_LOG_FILENAME),
119  "Filepath for the logs")
120  ("user,u",
121  boost::program_options::value< std::string >(&ioDBUser)->default_value(K_SIMCRS_DEFAULT_DB_USER),
122  "SQL database username")
123  ("passwd,p",
124  boost::program_options::value< std::string >(&ioDBPasswd)->default_value(K_SIMCRS_DEFAULT_DB_PASSWD),
125  "SQL database password")
126  ("host,H",
127  boost::program_options::value< std::string >(&ioDBHost)->default_value(K_SIMCRS_DEFAULT_DB_HOST),
128  "SQL database hostname")
129  ("port,P",
130  boost::program_options::value< std::string >(&ioDBPort)->default_value(K_SIMCRS_DEFAULT_DB_PORT),
131  "SQL database port")
132  ("dbname,m",
133  boost::program_options::value< std::string >(&ioDBDBName)->default_value(K_SIMCRS_DEFAULT_DB_DBNAME),
134  "SQL database name")
135  ;
136 
137  // Hidden options, will be allowed both on command line and
138  // in config file, but will not be shown to the user.
139  boost::program_options::options_description hidden ("Hidden options");
140  hidden.add_options()
141  ("copyright",
142  boost::program_options::value< std::vector<std::string> >(),
143  "Show the copyright (license)");
144 
145  boost::program_options::options_description cmdline_options;
146  cmdline_options.add(generic).add(config).add(hidden);
147 
148  boost::program_options::options_description config_file_options;
149  config_file_options.add(config).add(hidden);
150 
151  boost::program_options::options_description visible ("Allowed options");
152  visible.add(generic).add(config);
153 
154  boost::program_options::positional_options_description p;
155  p.add ("copyright", -1);
156 
157  boost::program_options::variables_map vm;
158  boost::program_options::
159  store (boost::program_options::command_line_parser (argc, argv).
160  options (cmdline_options).positional(p).run(), vm);
161 
162  std::ifstream ifs ("simcrs.cfg");
163  boost::program_options::store (parse_config_file (ifs, config_file_options),
164  vm);
165  boost::program_options::notify (vm);
166 
167  if (vm.count ("help")) {
168  std::cout << visible << std::endl;
170  }
171 
172  if (vm.count ("version")) {
173  std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
175  }
176 
177  if (vm.count ("prefix")) {
178  std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
180  }
181 
182  if (vm.count ("builtin")) {
183  ioIsBuiltin = true;
184  }
185  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
186  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
187 
188  //
189  std::ostringstream oErrorMessageStr;
190  oErrorMessageStr << "Either the -b/--builtin option, or the combination of "
191  << "the -s/--schedule, -o/--ond, -f/--fare and -y/--yield "
192  << "options must be specified";
193 
194  if (ioIsBuiltin == false) {
195  if (vm.count ("schedule")) {
196  ioScheduleInputFilename = vm["schedule"].as< std::string >();
197  std::cout << "Schedule input filename is: " << ioScheduleInputFilename
198  << std::endl;
199 
200  } else {
201  // The built-in option is not selected. However, no schedule input file
202  // is specified
203  std::cerr << oErrorMessageStr.str() << std::endl;
204  }
205 
206  if (vm.count ("ond")) {
207  ioOnDInputFilename = vm["ond"].as< std::string >();
208  std::cout << "O&D input filename is: " << ioOnDInputFilename << std::endl;
209 
210  } else {
211  // The built-in option is not selected. However, no schedule input file
212  // is specified
213  std::cerr << oErrorMessageStr.str() << std::endl;
214  }
215 
216  if (vm.count ("yield")) {
217  ioYieldInputFilename = vm["yield"].as< std::string >();
218  std::cout << "Yield input filename is: " << ioYieldInputFilename
219  << std::endl;
220 
221  } else {
222  // The built-in option is not selected. However, no schedule input file
223  // is specified
224  std::cerr << oErrorMessageStr.str() << std::endl;
225  }
226 
227  if (vm.count ("fare")) {
228  ioFareInputFilename = vm["fare"].as< std::string >();
229  std::cout << "Fare input filename is: " << ioFareInputFilename
230  << std::endl;
231 
232  } else {
233  // The built-in option is not selected. However, no schedule input file
234  // is specified
235  std::cerr << oErrorMessageStr.str() << std::endl;
236  }
237  }
238 
239  if (vm.count ("log")) {
240  ioLogFilename = vm["log"].as< std::string >();
241  std::cout << "Log filename is: " << ioLogFilename << std::endl;
242  }
243 
244  if (vm.count ("user")) {
245  ioDBUser = vm["user"].as< std::string >();
246  std::cout << "SQL database user name is: " << ioDBUser << std::endl;
247  }
248 
249  if (vm.count ("passwd")) {
250  ioDBPasswd = vm["passwd"].as< std::string >();
251  //std::cout << "SQL database user password is: " << ioDBPasswd << std::endl;
252  }
253 
254  if (vm.count ("host")) {
255  ioDBHost = vm["host"].as< std::string >();
256  std::cout << "SQL database host name is: " << ioDBHost << std::endl;
257  }
258 
259  if (vm.count ("port")) {
260  ioDBPort = vm["port"].as< std::string >();
261  std::cout << "SQL database port number is: " << ioDBPort << std::endl;
262  }
263 
264  if (vm.count ("dbname")) {
265  ioDBDBName = vm["dbname"].as< std::string >();
266  std::cout << "SQL database name is: " << ioDBDBName << std::endl;
267  }
268 
269  return 0;
270 }
271 
272 // ///////// M A I N ////////////
273 int main (int argc, char* argv[]) {
274 
275  // State whether the BOM tree should be built-in or parsed from an
276  // input file
277  bool isBuiltin;
278 
279  // Schedule input filename
280  stdair::Filename_T lScheduleInputFilename;
281 
282  // O&D input filename
283  stdair::Filename_T lOnDInputFilename;
284 
285  // Yield input filename
286  stdair::Filename_T lYieldInputFilename;
287 
288  // Fare input filename
289  stdair::Filename_T lFareInputFilename;
290 
291  // Output log File
292  stdair::Filename_T lLogFilename;
293 
294  // SQL database parameters
295  std::string lDBUser;
296  std::string lDBPasswd;
297  std::string lDBHost;
298  std::string lDBPort;
299  std::string lDBDBName;
300 
301  // CRS code
302  const SIMCRS::CRSCode_T lCRSCode ("1P");
303 
304  // Call the command-line option parser
305  const int lOptionParserStatus =
306  readConfiguration (argc, argv, isBuiltin,
307  lScheduleInputFilename, lOnDInputFilename,
308  lYieldInputFilename, lFareInputFilename, lLogFilename,
309  lDBUser, lDBPasswd, lDBHost, lDBPort, lDBDBName);
310 
311  if (lOptionParserStatus == K_SIMCRS_EARLY_RETURN_STATUS) {
312  return 0;
313  }
314 
315  // Set the database parameters
316  const stdair::BasDBParams lDBParams (lDBUser, lDBPasswd, lDBHost, lDBPort,
317  lDBDBName);
318 
319  // Set the log parameters
320  std::ofstream logOutputFile;
321  // Open and clean the log outputfile
322  logOutputFile.open (lLogFilename.c_str());
323  logOutputFile.clear();
324 
325  // Initialise the list of classes/buckets
326  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
327  SIMCRS::SIMCRS_Service simcrsService (lLogParams, lCRSCode);
328 
329  // Check wether or not (CSV) input files should be read
330  if (isBuiltin == true) {
331 
332  // Build the sample BOM tree
333  simcrsService.buildSampleBom();
334 
335  } else {
336  // Build the BOM tree from parsing input files
337  const SIMFQT::FareFilePath lFareFilePath (lFareInputFilename);
338  const AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
339  simcrsService.parseAndLoad (lScheduleInputFilename, lOnDInputFilename,
340  lYieldFilePath, lFareFilePath);
341  }
342 
343  // TODO (issue #37707): instead of building a sample, read the parameters
344  // from the command-line options, and build the corresponding
345  // booking request
346  const bool isForCRS = true;
347  const stdair::BookingRequestStruct& lBookingRequest =
348  simcrsService.buildSampleBookingRequest (isForCRS);
349 
350  // Calculate the travel solutions corresponding to the given booking request
351  stdair::TravelSolutionList_T lTravelSolutionList =
352  simcrsService.calculateSegmentPathList (lBookingRequest);
353 
354  // Check whether everything was fine
355  if (lTravelSolutionList.empty() == true) {
356  STDAIR_LOG_ERROR ("No travel solution has been found for: "
357  << lBookingRequest.display());
358  return -1;
359  }
360 
361  // Price the travel solution
362  simcrsService.fareQuote (lBookingRequest, lTravelSolutionList);
363 
364  // Choose a random travel solution: the first one.
365  stdair::TravelSolutionStruct& lChosenTravelSolution =
366  lTravelSolutionList.front();
367 
368  // Get the segment path of the travel solution.
369  const stdair::KeyList_T& lsegmentDateKeyList =
370  lChosenTravelSolution.getSegmentPath();
371 
372  const stdair::FareOptionList_T& lFareOptionList =
373  lChosenTravelSolution.getFareOptionList();
374 
375  // Check whether everything was fine
376  if (lFareOptionList.empty() == true) {
377  STDAIR_LOG_ERROR ("No fare option for the chosen travel solution: "
378  << lChosenTravelSolution.display());
379  return -1;
380  }
381 
382  //
383  const stdair::FareOptionStruct& lFareOption = lFareOptionList.front();
384  lChosenTravelSolution.setChosenFareOption (lFareOption);
385 
386  // DEBUG
387  const std::string& lSegmentDateKey = lsegmentDateKeyList.front();
388  STDAIR_LOG_DEBUG ("The chosen travel solution is: " << lSegmentDateKey
389  << ", the fare is: " << lFareOption.getFare() << " Euros.");
390 
391  // Make a booking (reminder: party size is 3)
392  const stdair::PartySize_T lPartySize (3);
393  const bool isSellSuccessful =
394  simcrsService.sell (lChosenTravelSolution, lPartySize);
395 
396  // DEBUG
397  STDAIR_LOG_DEBUG ("Sale ('" << lBookingRequest << "'): "
398  << " successful? " << isSellSuccessful);
399 
400  // DEBUG: Display the whole BOM tree
401  const std::string& lCSVDump = simcrsService.csvDisplay();
402  STDAIR_LOG_DEBUG (lCSVDump);
403 
404  // Close the Log outputFile
405  logOutputFile.close();
406 
407  /*
408  Note: as that program is not intended to be run on a server in
409  production, it is better not to catch the exceptions. When it
410  happens (that an exception is throwned), that way we get the
411  call stack.
412  */
413 
414  return 0;
415 }