TvlSim Logo  1.00.0
C++ Simulated Travel-Oriented Distribution System Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tvlsim.cpp
Go to the documentation of this file.
1 
5 // STL
6 #include <cassert>
7 #include <iostream>
8 #include <sstream>
9 #include <fstream>
10 #include <string>
11 // Boost (Extended STL)
12 #include <boost/program_options.hpp>
13 #include <boost/tokenizer.hpp>
14 #include <boost/regex.hpp>
15 #include <boost/swap.hpp>
16 #include <boost/algorithm/string/case_conv.hpp>
17 // GNU Readline Wrapper
18 #include <stdair/ui/cmdline/SReadline.hpp>
19 // StdAir
20 #include <stdair/stdair_basic_types.hpp>
21 #include <stdair/stdair_json.hpp>
22 #include <stdair/stdair_exceptions.hpp>
23 #include <stdair/basic/BasConst_General.hpp>
24 #include <stdair/basic/BasLogParams.hpp>
25 #include <stdair/basic/BasDBParams.hpp>
26 #include <stdair/basic/DemandGenerationMethod.hpp>
27 #include <stdair/basic/BasConst_BomDisplay.hpp>
28 #include <stdair/bom/RMEventStruct.hpp>
29 #include <stdair/service/Logger.hpp>
30 // TVLSIM
32 #include <tvlsim/TVLSIM_Types.hpp>
34 #include <tvlsim/config/tvlsim-paths.hpp>
35 
36 // //////// Type definitions ///////
40 typedef std::vector<std::string> WordList_T;
41 
45 typedef std::list<stdair::Date_T> DateList_T;
46 
47 
48 // //////// Constants //////
52 const std::string K_TVLSIM_DEFAULT_LOG_FILENAME ("tvlsim.log");
53 
58  "/rds01/schedule05.csv");
59 
64  "/ond01.csv");
65 
70  "/frat5.csv");
75  "/ffDisutility.csv");
76 
81  "/rds01/yield.csv");
82 
87  "/rds01/fare.csv");
88 
93  "/rds01/demand05.csv");
94 
99 
103 const stdair::RandomSeed_T K_TRADEMGEN_DEFAULT_RANDOM_SEED =
104  stdair::DEFAULT_RANDOM_SEED;
105 
110 
116 const bool K_TVLSIM_DEFAULT_BUILT_IN_INPUT = false;
117 
121 const std::string K_TVLSIM_DEFAULT_QUERY_STRING ("my good old query");
122 
126 const int K_TVLSIM_EARLY_RETURN_STATUS = 99;
127 
131 const std::string K_TVLSIM_DEFAULT_DB_USER ("tvlsim");
132 const std::string K_TVLSIM_DEFAULT_DB_PASSWD ("tvlsim");
133 const std::string K_TVLSIM_DEFAULT_DB_DBNAME ("sim_tvlsim");
134 const std::string K_TVLSIM_DEFAULT_DB_HOST ("localhost");
135 const std::string K_TVLSIM_DEFAULT_DB_PORT ("3306");
136 
137 
138 // //////////////////////////////////////////////////////////////////////
143 typedef std::vector<std::string> TokenList_T;
144 
145 // //////////////////////////////////////////////////////////////////////
146 TokenList_T GlobalTokenListForDate;
147 
148 // //////////////////////////////////////////////////////////////////////
152 struct Command_T {
153  typedef enum {
154  NOP = 0,
155  QUIT,
156  HELP,
157  RUN,
158  RESET,
159  OPTIMISE,
160  LIST_EVENT,
161  LIST_FLIGHT_DATE,
162  DISPLAY_FLIGHT_DATE,
163  DISPLAY_STATUS,
164  DISPLAY_CONFIG,
165  SELL,
166  SET_BREAK_POINT,
167  JSON_LIST_EVENT,
168  JSON_LIST_FLIGHT_DATE,
169  JSON_DISPLAY_FLIGHT_DATE,
170  JSON_SET_BREAK_POINT,
171  JSON_RUN,
172  JSON_RESET,
173  JSON_STATUS,
174  JSON_CONFIG,
175  LAST_VALUE
176  } Type_T;
177 };
178 
179 // //////////////////////////////////////////////////////////////////////
180 void tokeniseStringIntoWordList (const std::string& iPhrase,
181  WordList_T& ioWordList) {
182  // Empty the word list
183  ioWordList.clear();
184 
185  // Boost Tokeniser
186  typedef boost::tokenizer<boost::char_separator<char> > Tokeniser_T;
187 
188  // Define the separators
189  const boost::char_separator<char> lSepatorList(" .,;:|+-*/_=!@#$%`~^&(){}[]?'<>\"");
190 
191  // Initialise the phrase to be tokenised
192  Tokeniser_T lTokens (iPhrase, lSepatorList);
193  for (Tokeniser_T::const_iterator tok_iter = lTokens.begin();
194  tok_iter != lTokens.end(); ++tok_iter) {
195  const std::string& lTerm = *tok_iter;
196  ioWordList.push_back (lTerm);
197  }
198 
199 }// //////////////////////////////////////////////////////////////////////
200 std::string createStringFromWordList (const WordList_T& iWordList) {
201  std::ostringstream oStr;
202 
203  unsigned short idx = iWordList.size();
204  for (WordList_T::const_iterator itWord = iWordList.begin();
205  itWord != iWordList.end(); ++itWord, --idx) {
206  const std::string& lWord = *itWord;
207  oStr << lWord;
208  if (idx > 1) {
209  oStr << " ";
210  }
211  }
212 
213  return oStr.str();
214 }
215 
216 
217 // ///////// Parsing of Options & Configuration /////////
218 // A helper function to simplify the main part.
219 template<class T> std::ostream& operator<< (std::ostream& os,
220  const std::vector<T>& v) {
221  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
222  return os;
223 }
224 
228 int readConfiguration (int argc, char* argv[],
229  bool& ioIsBuiltin, stdair::RandomSeed_T& ioRandomSeed,
230  TVLSIM::NbOfRuns_T& ioRandomRuns, std::string& ioQueryString,
231  stdair::Filename_T& ioScheduleInputFilename,
232  stdair::Filename_T& ioOnDInputFilename,
233  stdair::Filename_T& ioFRAT5Filename,
234  stdair::Filename_T& ioFFDisutilityFilename,
235  stdair::Filename_T& ioYieldInputFilename,
236  stdair::Filename_T& ioFareInputFilename,
237  stdair::Filename_T& ioDemandInputFilename,
238  std::string& ioLogFilename,
239  stdair::DemandGenerationMethod& ioDemandGenerationMethod,
240  std::string& ioDBUser, std::string& ioDBPasswd,
241  std::string& ioDBHost, std::string& ioDBPort,
242  std::string& ioDBDBName) {
243 
244  // Demand generation method as a single char (e.g., 'P' or 'S').
245  char lDemandGenerationMethodChar;
246 
247  // Default for the built-in input
248  ioIsBuiltin = K_TVLSIM_DEFAULT_BUILT_IN_INPUT;
249 
250  // Initialise the travel query string, if that one is empty
251  if (ioQueryString.empty() == true) {
252  ioQueryString = K_TVLSIM_DEFAULT_QUERY_STRING;
253  }
254 
255  // Transform the query string into a list of words (STL strings)
256  WordList_T lWordList;
257  tokeniseStringIntoWordList (ioQueryString, lWordList);
258 
259  // Declare a group of options that will be allowed only on command line
260  boost::program_options::options_description generic ("Generic options");
261  generic.add_options()
262  ("prefix", "print installation prefix")
263  ("version,v", "print version string")
264  ("help,h", "produce help message");
265 
266  // Declare a group of options that will be allowed both on command
267  // line and in config file
268  boost::program_options::options_description config ("Configuration");
269  config.add_options()
270  ("builtin,b",
271  "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., -d/--demand, -s/--schedule, -o/--ond, -f/--fare, -y/--yield)")
272  ("seed,S",
273  boost::program_options::value<stdair::RandomSeed_T>(&ioRandomSeed)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_SEED),
274  "Seed for the random generation")
275  ("runs,r",
276  boost::program_options::value<TVLSIM::NbOfRuns_T>(&ioRandomRuns)->default_value(K_TRADEMGEN_DEFAULT_RANDOM_DRAWS),
277  "Number of simulation runs")
278  ("schedule,s",
279  boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_TVLSIM_DEFAULT_SCHEDULE_INPUT_FILENAME),
280  "(CSV) input file for the schedules")
281  ("ond,o",
282  boost::program_options::value< std::string >(&ioOnDInputFilename)->default_value(K_TVLSIM_DEFAULT_OND_INPUT_FILENAME),
283  "(CSV) input file for the O&D definitions")
284  ("frat5,F",
285  boost::program_options::value< std::string >(&ioFRAT5Filename)->default_value(K_TVLSIM_DEFAULT_FRAT5_INPUT_FILENAME),
286  "(CSV) input file for the FRAT5 Curve")
287  ("ff_disutility,D",
288  boost::program_options::value< std::string >(&ioFFDisutilityFilename)->default_value(K_TVLSIM_DEFAULT_FF_DISUTILITY_INPUT_FILENAME),
289  "(CSV) input file for the FF disutility Curve")
290  ("yield,y",
291  boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_TVLSIM_DEFAULT_YIELD_INPUT_FILENAME),
292  "(CSV) input file for the yields")
293  ("fare,f",
294  boost::program_options::value< std::string >(&ioFareInputFilename)->default_value(K_TVLSIM_DEFAULT_FARE_INPUT_FILENAME),
295  "(CSV) input file for the fares")
296  ("demand,d",
297  boost::program_options::value< std::string >(&ioDemandInputFilename)->default_value(K_TVLSIM_DEFAULT_DEMAND_INPUT_FILENAME),
298  "(CSV) input file for the demand distributions")
299  ("log,l",
300  boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_TVLSIM_DEFAULT_LOG_FILENAME),
301  "Filepath for the logs")
302  ("demandgeneration,G",
303  boost::program_options::value< char >(&lDemandGenerationMethodChar)->default_value(K_TVLSIM_DEMAND_GENERATION_METHOD_CHAR),
304  "Method used to generate the demand (i.e., booking requests): Poisson Process (e.g., P) or Statistics Order (e.g., S)")
305  ("user,u",
306  boost::program_options::value< std::string >(&ioDBUser)->default_value(K_TVLSIM_DEFAULT_DB_USER),
307  "SQL database hostname (e.g., tvlsim)")
308  ("passwd,p",
309  boost::program_options::value< std::string >(&ioDBPasswd)->default_value(K_TVLSIM_DEFAULT_DB_PASSWD),
310  "SQL database hostname (e.g., tvlsim)")
311  ("host,H",
312  boost::program_options::value< std::string >(&ioDBHost)->default_value(K_TVLSIM_DEFAULT_DB_HOST),
313  "SQL database hostname (e.g., localhost)")
314  ("port,P",
315  boost::program_options::value< std::string >(&ioDBPort)->default_value(K_TVLSIM_DEFAULT_DB_PORT),
316  "SQL database port (e.g., 3306)")
317  ("dbname,n",
318  boost::program_options::value< std::string >(&ioDBDBName)->default_value(K_TVLSIM_DEFAULT_DB_DBNAME),
319  "SQL database name (e.g., tvlsim)")
320  ("query,q",
321  boost::program_options::value< WordList_T >(&lWordList)->multitoken(),
322  "Query word list")
323  ;
324 
325  // Hidden options, will be allowed both on command line and
326  // in config file, but will not be shown to the user.
327  boost::program_options::options_description hidden ("Hidden options");
328  hidden.add_options()
329  ("copyright",
330  boost::program_options::value< std::vector<std::string> >(),
331  "Show the copyright (license)");
332 
333  boost::program_options::options_description cmdline_options;
334  cmdline_options.add(generic).add(config).add(hidden);
335 
336  boost::program_options::options_description config_file_options;
337  config_file_options.add(config).add(hidden);
338 
339  boost::program_options::options_description visible ("Allowed options");
340  visible.add(generic).add(config);
341 
342  boost::program_options::positional_options_description p;
343  p.add ("copyright", -1);
344 
345  boost::program_options::variables_map vm;
346  boost::program_options::
347  store (boost::program_options::command_line_parser (argc, argv).
348  options (cmdline_options).positional(p).run(), vm);
349 
350  std::ifstream ifs ("simulate.cfg");
351  boost::program_options::store (parse_config_file (ifs, config_file_options),
352  vm);
353  boost::program_options::notify (vm);
354 
355  if (vm.count ("help")) {
356  std::cout << visible << std::endl;
358  }
359 
360  if (vm.count ("version")) {
361  std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
363  }
364 
365  if (vm.count ("prefix")) {
366  std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
368  }
369 
370  if (vm.count ("builtin")) {
371  ioIsBuiltin = true;
372  }
373  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
374  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
375 
376  //
377  std::ostringstream oErrorMessageStr;
378  oErrorMessageStr << "Either the -b/--builtin option, or the combination of "
379  << "the -d/--demand, -s/--schedule, -o/--ond, -f/--fare "
380  << "and -y/--yield options must be specified";
381 
382  if (ioIsBuiltin == false) {
383  if (vm.count ("schedule")) {
384  ioScheduleInputFilename = vm["schedule"].as< std::string >();
385  std::cout << "Schedule input filename is: " << ioScheduleInputFilename
386  << std::endl;
387 
388  } else {
389  // The built-in option is not selected. However, no schedule input file
390  // is specified
391  std::cerr << oErrorMessageStr.str() << std::endl;
392  }
393 
394  if (vm.count ("ond")) {
395  ioOnDInputFilename = vm["ond"].as< std::string >();
396  std::cout << "O&D input filename is: " << ioOnDInputFilename << std::endl;
397 
398  } else {
399  // The built-in option is not selected. However, no schedule input file
400  // is specified
401  std::cerr << oErrorMessageStr.str() << std::endl;
402  }
403 
404  if (vm.count ("frat5")) {
405  ioFRAT5Filename = vm["frat5"].as< std::string >();
406  std::cout << "FRAT5 input filename is: " << ioFRAT5Filename << std::endl;
407 
408  } else {
409  // The built-in option is not selected. However, no frat5 input file
410  // is specified
411  std::cerr << oErrorMessageStr.str() << std::endl;
412  }
413 
414  if (vm.count ("ff_disutility")) {
415  ioFFDisutilityFilename = vm["ff_disutility"].as< std::string >();
416  std::cout << "FF disutility input filename is: "
417  << ioFFDisutilityFilename << std::endl;
418 
419  } else {
420  // The built-in option is not selected. However, no ff
421  // disutility input file is specified
422  std::cerr << oErrorMessageStr.str() << std::endl;
423  }
424 
425  if (vm.count ("yield")) {
426  ioYieldInputFilename = vm["yield"].as< std::string >();
427  std::cout << "Yield input filename is: " << ioYieldInputFilename << std::endl;
428 
429  } else {
430  // The built-in option is not selected. However, no schedule input file
431  // is specified
432  std::cerr << oErrorMessageStr.str() << std::endl;
433  }
434 
435  if (vm.count ("fare")) {
436  ioFareInputFilename = vm["fare"].as< std::string >();
437  std::cout << "Fare input filename is: " << ioFareInputFilename << std::endl;
438 
439  } else {
440  // The built-in option is not selected. However, no schedule input file
441  // is specified
442  std::cerr << oErrorMessageStr.str() << std::endl;
443  }
444 
445  if (vm.count ("demand")) {
446  ioDemandInputFilename = vm["demand"].as< std::string >();
447  std::cout << "Demand input filename is: " << ioDemandInputFilename
448  << std::endl;
449  } else {
450  // The built-in option is not selected. However, no schedule input file
451  // is specified
452  std::cerr << oErrorMessageStr.str() << std::endl;
453  }
454  }
455 
456  if (vm.count ("log")) {
457  ioLogFilename = vm["log"].as< std::string >();
458  std::cout << "Log filename is: " << ioLogFilename << std::endl;
459  }
460 
461  //
462  if (vm.count ("demandgeneration")) {
463  ioDemandGenerationMethod =
464  stdair::DemandGenerationMethod (lDemandGenerationMethodChar);
465  std::cout << "Demand generation method is: "
466  << ioDemandGenerationMethod.describe() << std::endl;
467  }
468 
469  //
470  std::cout << "The random generation seed is: " << ioRandomSeed << std::endl;
471 
472  //
473  std::cout << "The number of simulation runs is: " << ioRandomRuns
474  << std::endl;
475 
476  //
477  if (vm.count ("user")) {
478  ioDBUser = vm["user"].as< std::string >();
479  //std::cout << "SQL database user name is: " << ioDBUser << std::endl;
480  }
481 
482  if (vm.count ("passwd")) {
483  ioDBPasswd = vm["passwd"].as< std::string >();
484  //std::cout << "SQL database user password is: " << ioDBPasswd << std::endl;
485  }
486 
487  if (vm.count ("host")) {
488  ioDBHost = vm["host"].as< std::string >();
489  // std::cout << "SQL database host name is: " << ioDBHost << std::endl;
490  }
491 
492  if (vm.count ("port")) {
493  ioDBPort = vm["port"].as< std::string >();
494  //std::cout << "SQL database port number is: " << ioDBPort << std::endl;
495  }
496 
497  if (vm.count ("dbname")) {
498  ioDBDBName = vm["dbname"].as< std::string >();
499  //std::cout << "SQL database name is: " << ioDBDBName << std::endl;
500  }
501 
502  //
503  ioQueryString = createStringFromWordList (lWordList);
504  //std::cout << "The query string is: " << ioQueryString << std::endl;
505 
506  return 0;
507 }
508 
509 // //////////////////////////////////////////////////////////////////
510 void initReadline (swift::SReadline& ioInputReader) {
511 
512  // Prepare the list of my own completers
513  std::vector<std::string> Completers;
514 
515  // The following is supported:
516  // - "identifiers"
517  // - special identifier %file - means to perform a file name completion
518  Completers.push_back ("help");
519  Completers.push_back ("run");
520  Completers.push_back ("reset");
521  Completers.push_back ("optimise");
522  Completers.push_back ("display_config");
523  Completers.push_back ("display_status");
524  Completers.push_back ("display_flight_date");
525  Completers.push_back ("list_event");
526  Completers.push_back ("list_event BookingRequest");
527  Completers.push_back ("list_event Cancellation");
528  Completers.push_back ("list_event OptimisationNotificationForFlightDate");
529  Completers.push_back ("list_event OptimisationNotificationForNetwork");
530  Completers.push_back ("list_event ScheduleChange");
531  Completers.push_back ("list_event Snapshot");
532  Completers.push_back ("list_event RevenueManagement");
533  Completers.push_back ("list_event BreakPoint");
534  Completers.push_back ("list_flight_date");
535  Completers.push_back ("set_break_point");
536  Completers.push_back ("sell");
537  Completers.push_back ("json_list_event");
538  Completers.push_back ("json_list_event BookingRequest");
539  Completers.push_back ("json_list_event Cancellation");
540  Completers.push_back ("json_list_event OptimisationNotificationForFlightDate");
541  Completers.push_back ("json_list_event OptimisationNotificationForNetwork");
542  Completers.push_back ("json_list_event ScheduleChange");
543  Completers.push_back ("json_list_event Snapshot");
544  Completers.push_back ("json_list_event RevenueManagement");
545  Completers.push_back ("json_list_event BreakPoint");
546  Completers.push_back ("json_list_flight_date");
547  Completers.push_back ("json_display_flight_date");
548  Completers.push_back ("json_display_status");
549  Completers.push_back ("json_set_break_point");
550  Completers.push_back ("json_run");
551  Completers.push_back ("json_reset");
552  Completers.push_back ("json_display_config");
553  Completers.push_back ("quit");
554 
555  // Now register the completers.
556  // Actually it is possible to re-register another set at any time
557  ioInputReader.RegisterCompletions (Completers);
558 }
559 
560 // //////////////////////////////////////////////////////////////////
561 void parseFlightKey (const TokenList_T& iTokenList,
562  stdair::AirlineCode_T& ioAirlineCode,
563  stdair::FlightNumber_T& ioFlightNumber) {
564 
565  // Interpret the user input
566  if (iTokenList.empty() == false) {
567  // Read the airline code
568  TokenList_T::const_iterator itTok = iTokenList.begin();
569  if (itTok->empty() == false) {
570  ioAirlineCode = *itTok;
571  boost::algorithm::to_upper (ioAirlineCode);
572  }
573 
574  // Read the flight-number
575  ++itTok;
576  if (itTok != iTokenList.end()) {
577 
578  if (itTok->empty() == false) {
579  try {
580 
581  ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
582 
583  } catch (boost::bad_lexical_cast& eCast) {
584  std::cerr << "The flight number ('" << *itTok
585  << "') cannot be understood. "
586  << "The default value (all) is kept."
587  << std::endl;
588  return;
589  }
590  }
591 
592  } else {
593  return;
594  }
595  }
596 }
597 
598 // //////////////////////////////////////////////////////////////////
599 void parseBookingClassKey (const TokenList_T& iTokenList,
600  stdair::ClassCode_T& ioBookingClass,
601  stdair::PartySize_T& ioPartySize,
602  stdair::AirportCode_T& ioOrigin,
603  stdair::AirportCode_T& ioDestination) {
604  // Interpret the user input
605  if (iTokenList.empty() == false) {
606 
607  // Read the booking class
608  TokenList_T::const_iterator itTok = iTokenList.begin();
609  if (itTok->empty() == false) {
610  ioBookingClass = *itTok;
611  boost::algorithm::to_upper (ioBookingClass);
612  }
613 
614  // Read the party size
615  ++itTok;
616  if (itTok != iTokenList.end()) {
617 
618  if (itTok->empty() == false) {
619  try {
620 
621  ioPartySize = boost::lexical_cast<stdair::PartySize_T> (*itTok);
622 
623  } catch (boost::bad_lexical_cast& eCast) {
624  std::cerr << "The party size ('" << *itTok
625  << "') cannot be understood. The default value ("
626  << ioPartySize << ") is kept." << std::endl;
627  return;
628  }
629  }
630 
631  } else {
632  return;
633  }
634 
635  // Read the origin
636  ++itTok;
637  if (itTok != iTokenList.end()) {
638 
639  if (itTok->empty() == false) {
640  ioOrigin = *itTok;
641  boost::algorithm::to_upper (ioOrigin);
642  }
643 
644  } else {
645  return;
646  }
647 
648  // Read the destination
649  ++itTok;
650  if (itTok != iTokenList.end()) {
651 
652  if (itTok->empty() == false) {
653  ioDestination = *itTok;
654  boost::algorithm::to_upper (ioDestination);
655  }
656 
657  } else {
658  return;
659  }
660  }
661 }
662 
663 // //////////////////////////////////////////////////////////////////
664 void parseDateKey (const TokenList_T& iTokenList,
665  stdair::Date_T& ioDate) {
666  //
667  const std::string kMonthStr[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
668  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
669  //
670  unsigned short ioDateYear = ioDate.year();
671  unsigned short ioDateMonth = ioDate.month();
672  std::string ioDateMonthStr = kMonthStr[ioDateMonth-1];
673  unsigned short ioDateDay = ioDate.day();
674 
675  // Interpret the user input
676  if (iTokenList.empty() == false) {
677 
678  // Read the year
679  TokenList_T::const_iterator itTok = iTokenList.begin();
680  if (itTok->empty() == false) {
681  try {
682 
683  ioDateYear = boost::lexical_cast<unsigned short> (*itTok);
684  if (ioDateYear < 100) {
685  ioDateYear += 2000;
686  }
687 
688  } catch (boost::bad_lexical_cast& eCast) {
689  std::cerr << "The year of the date ('" << *itTok
690  << "') cannot be understood. The default value ("
691  << ioDate << ") is kept. " << std::endl;
692  return;
693  }
694 
695  } else {
696  return;
697  }
698 
699  // Read the month
700  ++itTok;
701  if (itTok != iTokenList.end()) {
702 
703  if (itTok->empty() == false) {
704  try {
705 
706  const boost::regex lMonthRegex ("^(\\d{1,2})$");
707  const bool isMonthANumber = regex_match (*itTok, lMonthRegex);
708 
709  if (isMonthANumber == true) {
710  const unsigned short lMonth =
711  boost::lexical_cast<unsigned short> (*itTok);
712  if (lMonth > 12 || lMonth < 1) {
713  throw boost::bad_lexical_cast();
714  }
715  ioDateMonthStr = kMonthStr[lMonth-1];
716 
717  } else {
718  const std::string lMonthStr (*itTok);
719  if (lMonthStr.size() < 3) {
720  throw boost::bad_lexical_cast();
721  }
722  std::string lMonthStr1 (lMonthStr.substr (0, 1));
723  boost::algorithm::to_upper (lMonthStr1);
724  std::string lMonthStr23 (lMonthStr.substr (1, 2));
725  boost::algorithm::to_lower (lMonthStr23);
726  ioDateMonthStr = lMonthStr1 + lMonthStr23;
727  }
728 
729  } catch (boost::bad_lexical_cast& eCast) {
730  std::cerr << "The month of the date ('" << *itTok
731  << "') cannot be understood. The default value ("
732  << ioDate << ") is kept. " << std::endl;
733  return;
734  }
735  }
736 
737  } else {
738  return;
739  }
740 
741  // Read the day
742  ++itTok;
743  if (itTok != iTokenList.end()) {
744 
745  if (itTok->empty() == false) {
746  try {
747 
748  ioDateDay = boost::lexical_cast<unsigned short> (*itTok);
749 
750  } catch (boost::bad_lexical_cast& eCast) {
751  std::cerr << "The day of the date ('" << *itTok
752  << "') cannot be understood. The default value ("
753  << ioDate << ") is kept. " << std::endl;
754  return;
755  }
756  }
757 
758  } else {
759  return;
760  }
761 
762  // Re-compose the date
763  std::ostringstream lDateStr;
764  lDateStr << ioDateYear << "-" << ioDateMonthStr
765  << "-" << ioDateDay;
766 
767  try {
768 
769  ioDate =
770  boost::gregorian::from_simple_string (lDateStr.str());
771 
772  } catch (boost::gregorian::bad_day_of_month& eCast) {
773  std::cerr << "The date ('" << lDateStr.str()
774  << "') cannot be understood. The default value ("
775  << ioDate << ") is kept. " << std::endl;
776  return;
777  }
778 
779  }
780 }
781 
782 // //////////////////////////////////////////////////////////////////
783 void parseDateListKey (stdair::Date_T& iDefaultDate,
784  DateList_T& ioDateList) {
785 
786  // To re-compose a date, three tokens are needed.
787  if (GlobalTokenListForDate.size() < 3) {
788  ioDateList.push_back (iDefaultDate);
789  return;
790  }
791 
792  // To re-compose a date, three tokens are needed.
793  while (GlobalTokenListForDate.size() >= 3) {
794  // Try to re-compose the airline code and the flight number
795  parseDateKey (GlobalTokenListForDate, iDefaultDate);
796  ioDateList.push_back (iDefaultDate);
797  // Erase the first three tokens (corresponding to the year,
798  // month and date of the first date
799  GlobalTokenListForDate.erase(GlobalTokenListForDate.begin(),
800  GlobalTokenListForDate.begin()+3);
801  }
802 
803 }
804 
805 // //////////////////////////////////////////////////////////////////
806 void parseFlightDateKey (TokenList_T& iTokenList,
807  stdair::AirlineCode_T& ioAirlineCode,
808  stdair::FlightNumber_T& ioFlightNumber,
809  stdair::Date_T& ioDate) {
810 
811  // To re-compose the airline code, the flight number and the date,
812  // five tokens are needed.
813  if (iTokenList.size() < 5) {
814  return;
815  }
816 
817  // Try to re-compose the airline code and the flight number
818  parseFlightKey (iTokenList, ioAirlineCode, ioFlightNumber);
819  // Erase the first two tokens (corresponding to the airline code
820  // and the flight number)
821  assert (iTokenList.size() >= 2);
822  iTokenList.erase(iTokenList.begin(),iTokenList.begin()+2);
823  // Try to re-compose the date
824  parseDateKey (iTokenList, ioDate);
825  assert (iTokenList.size() >= 3);
826  iTokenList.erase(iTokenList.begin(),iTokenList.begin()+3);
827 }
828 
829 // //////////////////////////////////////////////////////////////////
830 Command_T::Type_T extractCommand (TokenList_T& ioTokenList) {
831  Command_T::Type_T oCommandType = Command_T::LAST_VALUE;
832 
833  // Interpret the user input
834  if (ioTokenList.empty() == false) {
835  TokenList_T::iterator itTok = ioTokenList.begin();
836  std::string lCommand (*itTok);
837  boost::algorithm::to_lower (lCommand);
838 
839  if (lCommand == "help") {
840  oCommandType = Command_T::HELP;
841 
842  } else if (lCommand == "run") {
843  oCommandType = Command_T::RUN;
844 
845  } else if (lCommand == "optimise") {
846  oCommandType = Command_T::OPTIMISE;
847 
848  } else if (lCommand == "reset") {
849  oCommandType = Command_T::RESET;
850 
851  } else if (lCommand == "list_event") {
852  oCommandType = Command_T::LIST_EVENT;
853 
854  } else if (lCommand == "list_flight_date") {
855  oCommandType = Command_T::LIST_FLIGHT_DATE;
856 
857  } else if (lCommand == "display_status") {
858  oCommandType = Command_T::DISPLAY_STATUS;
859 
860  } else if (lCommand == "display_config") {
861  oCommandType = Command_T::DISPLAY_CONFIG;
862 
863  } else if (lCommand == "display_flight_date") {
864  oCommandType = Command_T::DISPLAY_FLIGHT_DATE;
865 
866  } else if (lCommand == "set_break_point") {
867  oCommandType = Command_T::SET_BREAK_POINT;
868 
869  } else if (lCommand == "sell") {
870  oCommandType = Command_T::SELL;
871 
872  } else if (lCommand == "json_list_event") {
873  oCommandType = Command_T::JSON_LIST_EVENT;
874 
875  } else if (lCommand == "json_list_flight_date") {
876  oCommandType = Command_T::JSON_LIST_FLIGHT_DATE;
877 
878  } else if (lCommand == "json_display_flight_date") {
879  oCommandType = Command_T::JSON_DISPLAY_FLIGHT_DATE;
880 
881  } else if (lCommand == "json_set_break_point") {
882  oCommandType = Command_T::JSON_SET_BREAK_POINT;
883 
884  } else if (lCommand == "json_run") {
885  oCommandType = Command_T::JSON_RUN;
886 
887  } else if (lCommand == "json_reset") {
888  oCommandType = Command_T::JSON_RESET;
889 
890  } else if (lCommand == "json_display_status") {
891  oCommandType = Command_T::JSON_STATUS;
892 
893  } else if (lCommand == "json_display_config") {
894  oCommandType = Command_T::JSON_CONFIG;
895 
896  } else if (lCommand == "quit") {
897  oCommandType = Command_T::QUIT;
898  }
899 
900  // Remove the first token (the command), as the corresponding information
901  // has been extracted in the form of the returned command type enumeration
902  ioTokenList.erase (itTok);
903 
904  } else {
905  oCommandType = Command_T::NOP;
906  }
907 
908  return oCommandType;
909 }
910 
911 // /////////////////////////////////////////////////////////
912 std::string toString (const TokenList_T& iTokenList) {
913  std::ostringstream oStr;
914 
915  // Re-create the string with all the tokens, trimmed by read-line
916  unsigned short idx = 0;
917  for (TokenList_T::const_iterator itTok = iTokenList.begin();
918  itTok != iTokenList.end(); ++itTok, ++idx) {
919  if (idx != 0) {
920  oStr << " ";
921  }
922  oStr << *itTok;
923  }
924 
925  return oStr.str();
926 }
927 
928 // /////////////////////////////////////////////////////////
929 bool regex_callback(const boost::match_results<std::string::const_iterator>& what)
930 {
931  // Put the matched strings in the list of tokens to be returned back
932  // to the caller
933  // what[1] contains the year of the date
934  // what[2] contains the day of the date
935  // what[3] contains the month of the date
936  const unsigned short lMatchSetSize = what.size();
937  for (unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
938  const std::string lMatchedString (std::string (what[matchIdx].first,
939  what[matchIdx].second));
940  //if (lMatchedString.empty() == false) {
941  GlobalTokenListForDate.push_back (lMatchedString);
942  //}
943  }
944  return true;
945 }
946 
947 // /////////////////////////////////////////////////////////
948 void extractTokenListDate (const TokenList_T& iTokenList,
949  const std::string& iRegularExpression) {
950  TokenList_T oTokenList;
951 
952  // Re-create the string with all the tokens (which had been trimmed
953  // by read-line)
954  const std::string lFullLine = toString (iTokenList);
955 
956  // See the caller for the regular expression
957  boost::regex expression (iRegularExpression);
958 
959  std::string::const_iterator start = lFullLine.begin();
960  std::string::const_iterator end = lFullLine.end();
961 
962  // construct the iterators
963  boost::sregex_iterator m1(start, end, expression);
964  boost::sregex_iterator m2;
965  std::for_each(m1, m2, &regex_callback);
966 
967 }
968 
969 // /////////////////////////////////////////////////////////
970 TokenList_T extractTokenList (const TokenList_T& iTokenList,
971  const std::string& iRegularExpression) {
972  TokenList_T oTokenList;
973 
974  // Re-create the string with all the tokens (which had been trimmed
975  // by read-line)
976  const std::string lFullLine = toString (iTokenList);
977 
978  // See the caller for the regular expression
979  boost::regex expression (iRegularExpression);
980 
981  std::string::const_iterator start = lFullLine.begin();
982  std::string::const_iterator end = lFullLine.end();
983 
984  boost::match_results<std::string::const_iterator> what;
985  boost::match_flag_type flags = boost::match_default;
986  regex_search (start, end, what, expression, flags);
987 
988  // Put the matched strings in the list of tokens to be returned back
989  // to the caller
990  const unsigned short lMatchSetSize = what.size();
991  for (unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
992  const std::string lMatchedString (std::string (what[matchIdx].first,
993  what[matchIdx].second));
994  //if (lMatchedString.empty() == false) {
995  oTokenList.push_back (lMatchedString);
996  //}
997  }
998 
999  // DEBUG
1000  //std::cout << "After (token list): " << oTokenList << std::endl;
1001 
1002  return oTokenList;
1003 }
1004 
1005 // /////////////////////////////////////////////////////////
1006 TokenList_T extractTokenListForFlightDate (const TokenList_T& iTokenList) {
1017  const std::string lRegEx("^([[:alpha:]]{2,3})?"
1018  "[[:space:]]*([[:digit:]]{1,4})?"
1019  "[/ ]*"
1020  "([[:digit:]]{2,4})?[/-]?[[:space:]]*"
1021  "([[:alpha:]]{3}|[[:digit:]]{1,2})?[/-]?[[:space:]]*"
1022  "([[:digit:]]{1,2})?$");
1023 
1024  //
1025  const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
1026  return oTokenList;
1027 }
1028 
1029 // /////////////////////////////////////////////////////////
1030 void extractTokenListForDate (const TokenList_T& iTokenList) {
1038  const std::string lRegEx("([[:digit:]]{2,4})[/-]?"
1039  "([[:alpha:]]{3}|[[:digit:]]{1,2})[/-]?"
1040  "([[:digit:]]{1,2})");
1041 
1042  // const std::string lRegEx("[[:digit:]]{2}");
1043  //
1044  extractTokenListDate (iTokenList, lRegEx);
1045 
1046 }
1047 
1048 // /////////////////////////////////////////////////////////
1049 TokenList_T extractTokenListForFlight (const TokenList_T& iTokenList) {
1056  const std::string lRegEx ("^([[:alpha:]]{2,3})?"
1057  "[[:space:]]*([[:digit:]]{1,4})?$");
1058 
1059  //
1060  const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
1061  return oTokenList;
1062 }
1063 
1064 // /////////////////////////////////////////////////////////
1065 TokenList_T extractTokenListForClass (const TokenList_T& iTokenList) {
1081  const std::string lRegEx ("^([[:alpha:]]{2,3})?"
1082  "[[:space:]]*([[:digit:]]{1,4})?"
1083  "[/, ]*"
1084  "([[:digit:]]{2,4})?[/-]?[[:space:]]*"
1085  "([[:alpha:]]{3}|[[:digit:]]{1,2})?[/-]?[[:space:]]*"
1086  "([[:digit:]]{1,2})?"
1087  "[[:space:]]*([[:alpha:]]{1})?"
1088  "[[:space:]]*([[:digit:]]{1,3})?"
1089  "[[:space:]]*([[:alpha:]]{3})?"
1090  "[[:space:]]*([[:alpha:]]{3})?$");
1091 
1092  //
1093  const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
1094  return oTokenList;
1095 }
1096 
1097 // ///////// M A I N ////////////
1098 int main (int argc, char* argv[]) {
1099 
1100  // Readline history
1101  const unsigned int lHistorySize (100);
1102  const std::string lHistoryFilename ("tvlsim.hist");
1103  const std::string lHistoryBackupFilename ("tvlsim.hist.bak");
1104 
1105  // State whether the BOM tree should be built-in or parsed from an
1106  // input file
1107  bool isBuiltin;
1108 
1109  // Default parameters for the interactive session
1110  stdair::AirlineCode_T lDefaultAirlineCode;
1111  stdair::FlightNumber_T lDefaultFlightNumber;
1112  stdair::Date_T lDefaultDate;
1113  stdair::AirportCode_T lDefaultOrigin;
1114  stdair::AirportCode_T lDefaultDestination;
1115  stdair::ClassCode_T lDefaultBookingClass;
1116  stdair::PartySize_T lDefaultPartySize;
1117 
1118  // Random generation seed
1119  stdair::RandomSeed_T lRandomSeed;
1120 
1121  // Number of simulation runs to be performed
1122  TVLSIM::NbOfRuns_T lNbOfRuns;
1123 
1124  // Query
1125  std::string lQuery;
1126 
1127  // Start date
1128  stdair::Date_T lStartDate (2009, boost::gregorian::Feb, 01);
1129 
1130  // End date
1131  stdair::Date_T lEndDate (2012, boost::gregorian::Sep, 01);
1132 
1133  // Schedule input file name
1134  stdair::Filename_T lScheduleInputFilename;
1135 
1136  // O&D input filename
1137  std::string lOnDInputFilename;
1138 
1139  // FRAT5 input filename
1140  std::string lFRAT5InputFilename;
1141 
1142  // FF disutility input filename
1143  std::string lFFDisutilityInputFilename;
1144 
1145  // Yield input filename
1146  std::string lYieldInputFilename;
1147 
1148  // Fare input filename
1149  std::string lFareInputFilename;
1150 
1151  // Demand input file name
1152  stdair::Filename_T lDemandInputFilename;
1153 
1154  // Output log File
1155  std::string lLogFilename;
1156 
1157  // Demand generation method.
1158  stdair::DemandGenerationMethod
1159  lDemandGenerationMethod (K_TVLSIM_DEMAND_GENERATION_METHOD_CHAR);
1160 
1161  // SQL database parameters
1162  std::string lDBUser;
1163  std::string lDBPasswd;
1164  std::string lDBHost;
1165  std::string lDBPort;
1166  std::string lDBDBName;
1167 
1168  // Call the command-line option parser
1169  const int lOptionParserStatus =
1170  readConfiguration (argc, argv, isBuiltin, lRandomSeed, lNbOfRuns, lQuery,
1171  lScheduleInputFilename, lOnDInputFilename,
1172  lFRAT5InputFilename, lFFDisutilityInputFilename,
1173  lYieldInputFilename, lFareInputFilename,
1174  lDemandInputFilename, lLogFilename,
1175  lDemandGenerationMethod,
1176  lDBUser, lDBPasswd, lDBHost, lDBPort, lDBDBName);
1177 
1178  if (lOptionParserStatus == K_TVLSIM_EARLY_RETURN_STATUS) {
1179  return 0;
1180  }
1181 
1182  // Set the database parameters
1183  stdair::BasDBParams lDBParams (lDBUser, lDBPasswd, lDBHost, lDBPort,
1184  lDBDBName);
1185 
1186  // Set the log parameters
1187  std::ofstream logOutputFile;
1188  // open and clean the log outputfile
1189  logOutputFile.open (lLogFilename.c_str());
1190  logOutputFile.clear();
1191 
1192  // Check wether or not (CSV) input files should be read to initiate the
1193  // default parameters
1194  if (isBuiltin == true) {
1195 
1196  // Update the default parameters for the following interactive session
1197  lStartDate = stdair::Date_T (2011, 01, 01);
1198  lEndDate = stdair::Date_T (2011, 12, 01);
1199  lDefaultAirlineCode = "BA";
1200  lDefaultFlightNumber = 9;
1201  lDefaultDate = stdair::Date_T (2011, 06, 10);
1202  lDefaultBookingClass = "Q";
1203  lDefaultPartySize = 2;
1204  lDefaultOrigin = "LHR";
1205  lDefaultDestination = "SYD";
1206 
1207  } else {
1208 
1209  // Update the default parameters for the following interactive session
1210  lDefaultAirlineCode = "SQ";
1211  lDefaultFlightNumber = 12;
1212  lDefaultDate = stdair::Date_T (2009, 02, 9);
1213  lDefaultBookingClass = "Y";
1214  lDefaultPartySize = 2;
1215  lDefaultOrigin = "SIN";
1216  lDefaultDestination = "BKK";
1217  }
1218 
1219  // Initialise the simulation context
1220  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
1221  TVLSIM::TVLSIM_Service tvlsimService (lLogParams, lDBParams, lStartDate, lEndDate,
1222  lRandomSeed, lDemandGenerationMethod,
1223  lNbOfRuns);
1224 
1225  // Check wether or not (CSV) input files should be read
1226  if (isBuiltin == true) {
1227 
1228  // Build the sample BOM tree
1229  tvlsimService.buildSampleBom();
1230 
1231  } else {
1232 
1233  // Build the BOM tree from parsing input files
1234  stdair::ScheduleFilePath lScheduleFilePath (lScheduleInputFilename);
1235  stdair::ODFilePath lODFilePath (lOnDInputFilename);
1236  stdair::FRAT5FilePath lFRAT5FilePath (lFRAT5InputFilename);
1237  stdair::FFDisutilityFilePath lFFDisutilityFilePath (lFFDisutilityInputFilename);
1238  const SIMFQT::FareFilePath lFareFilePath (lFareInputFilename);
1239  const AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
1240  const TRADEMGEN::DemandFilePath lDemandFilePath (lDemandInputFilename);
1241  tvlsimService.setInputFiles (lScheduleFilePath, lODFilePath,
1242  lFRAT5FilePath, lFFDisutilityFilePath,
1243  lYieldFilePath, lFareFilePath,
1244  lDemandFilePath);
1245  tvlsimService.parseAndLoad ();
1246  }
1247 
1248  // Initialise the snapshot and RM events
1249  tvlsimService.initSnapshotAndRMEvents();
1250 
1251  // DEBUG
1252  STDAIR_LOG_DEBUG ("====================================================");
1253  STDAIR_LOG_DEBUG ("= Beginning of the interactive session =");
1254  STDAIR_LOG_DEBUG ("====================================================");
1255 
1256  // Initialise the GNU readline wrapper
1257  swift::SReadline lReader (lHistoryFilename, lHistorySize);
1258  initReadline (lReader);
1259 
1260  // Now we can ask user for a line
1261  std::string lUserInput;
1262  bool EndOfInput (false);
1263  Command_T::Type_T lCommandType (Command_T::NOP);
1264 
1265  while (lCommandType != Command_T::QUIT && EndOfInput == false) {
1266  // Prompt
1267  std::ostringstream oPromptStr;
1268  oPromptStr << "tvlsim "
1269  << "> ";
1270  // Call read-line, which will fill the list of tokens
1271  TokenList_T lTokenListByReadline;
1272  lUserInput = lReader.GetLine (oPromptStr.str(), lTokenListByReadline,
1273  EndOfInput);
1274 
1275  // The history can be saved to an arbitrary file at any time
1276  lReader.SaveHistory (lHistoryBackupFilename);
1277 
1278  // The end-of-input typically corresponds to a CTRL-D typed by the user
1279  if (EndOfInput) {
1280  std::cout << std::endl;
1281  break;
1282  }
1283 
1284  // Interpret the user input
1285  lCommandType = extractCommand (lTokenListByReadline);
1286 
1287  GlobalTokenListForDate.clear();
1288 
1289  switch (lCommandType) {
1290 
1291  // ////////////////////////////// Help ////////////////////////
1292  case Command_T::HELP: {
1293  std::cout << std::endl;
1294  std::cout << "Commands:\n" << std::endl;
1295  std::cout << " help" << "\t\t\t\t" << "Display this help."
1296  << std::endl;
1297  std::cout << " quit" << "\t\t\t\t" << "Quit the application."
1298  << std::endl;
1299  std::cout << " display_config" << "\t\t\t" << "Display the configuration."
1300  << std::endl;
1301  std::cout << " display_status" << "\t\t\t"
1302  << "Display the simulation status."
1303  << std::endl;
1304  std::cout << " list_event" << "\t\t\t"
1305  << "List events in the queue."
1306  << std::endl
1307  << "\t\t\t\tIt is possible to filter events according to their types:"
1308  << std::endl
1309  << "\t\t\t\t 'list_event BookingRequest' "
1310  << "list all the booking requests."
1311  << std::endl
1312  << "\t\t\t\t 'list_event Cancellation' "
1313  << "list all the cancellation events."
1314  << std::endl
1315  << "\t\t\t\t 'list_event Snapshot' "
1316  << "list all the snap shots."
1317  << std::endl
1318  << "\t\t\t\t 'list_event RevenueManagement' "
1319  << "list all the revenue management events."
1320  << std::endl
1321  << "\t\t\t\t 'list_event BreakPoint' "
1322  << "list all the break points."
1323  << std::endl;
1324  std::cout << " list_flight_date" << "\t\t"
1325  << "List airlines, flights and departure dates."
1326  << std::endl;
1327  std::cout << " display_flight_date" << "\t\t"
1328  << "Display the given flight-date."
1329  << std::endl
1330  << "\t\t\t\tIf the parameters list is empty or wrong, default values are used:"
1331  << std::endl
1332  << "\t\t\t\t 'display_flight_date " << lDefaultAirlineCode
1333  << lDefaultFlightNumber << " " << lDefaultDate << "'"
1334  << std::endl;
1335  std::cout << " set_break_point" << "\t\t"
1336  << "Insert the given break points in the event list."
1337  << std::endl
1338  << "\t\t\t\tIf the parameters list is empty or wrong, a default value is used:"
1339  << std::endl
1340  << "\t\t\t\t 'set_break_point " << lDefaultDate << "'"
1341  << std::endl;
1342  std::cout << " run" << "\t\t\t\t"
1343  << "Perform the simulation until the next break-point, if any."
1344  << std::endl;
1345  std::cout << " reset" << "\t\t\t\t" << "Reset the service (including the "
1346  << "event queue)."
1347  << std::endl;
1348  std::cout << " sell" << "\t\t\t\t" << "Make a booking on the given flight-date."
1349  << std::endl
1350  << "\t\t\t\tIf the parameters list is empty or wrong, default values are used:"
1351  << std::endl
1352  << "\t\t\t\t 'sell " << lDefaultAirlineCode
1353  << lDefaultFlightNumber << " " << lDefaultDate << " "
1354  << lDefaultBookingClass << " " << lDefaultPartySize << " "
1355  << lDefaultOrigin << " " << lDefaultDestination << "'"
1356  << std::endl;
1357  std::cout << " optimise" << "\t\t\t" << "Optimise the given flight-date."
1358  << std::endl
1359  << "\t\t\t\tIf the parameters list is empty or wrong, default values are used:"
1360  << std::endl
1361  << "\t\t\t\t 'optimise " << lDefaultAirlineCode
1362  << lDefaultFlightNumber << " " << lDefaultDate << "'"
1363  << std::endl;
1364  std::cout << " \n\nDebug Commands:\n"
1365  << std::endl;
1366  std::cout << " json_display_status" << "\t\t"
1367  << "Display the simulation status in a JSON format."
1368  << std::endl;
1369  std::cout << " json_display_config" << "\t\t"
1370  << "Display the simulation configuration in a JSON format."
1371  << std::endl;
1372  std::cout << " json_list_event" << "\t\t"
1373  << "List events in the queue in a JSON format."
1374  << std::endl;
1375  std::cout << " json_list_flight_date" << "\t\t"
1376  << "List airlines, flights and departure dates in a JSON format."
1377  << std::endl;
1378  std::cout << " json_display_flight_date" << "\t"
1379  << "Display the given flight-date in a JSON format."
1380  << std::endl;
1381  std::cout << " json_set_break_point" << "\t\t"
1382  << "Insert the given break points in the event list."
1383  << std::endl;
1384  std::cout << " json_run" << "\t\t\t"
1385  << "Perform the simulation until the next break-point, if any."
1386  << std::endl;
1387  std::cout << " json_reset" << "\t\t\t"
1388  << "Reset the service (including the event queue)."
1389  << std::endl;
1390  std::cout << std::endl;
1391  break;
1392  }
1393 
1394  // ////////////////////////////// Quit ////////////////////////
1395  case Command_T::QUIT: {
1396  break;
1397  }
1398 
1399  // ////////////////////////////// Quit ////////////////////////
1400  case Command_T::DISPLAY_CONFIG: {
1401 
1402  //
1403  std::ostringstream oConfigStr;
1404 
1405  // Display the config
1406  oConfigStr << tvlsimService.configDisplay () << std::endl;
1407  std::cout << oConfigStr.str();
1408  STDAIR_LOG_DEBUG (oConfigStr.str());
1409  break;
1410  }
1411 
1412  // ////////////////////////////// Run ////////////////////////
1413  case Command_T::RUN: {
1414 
1415  // Perform a simulation
1416  tvlsimService.simulate ();
1417  break;
1418  }
1419 
1420  // ////////////////////////////// Display simulation status ////////////////////////
1421 
1422  case Command_T::DISPLAY_STATUS: {
1423  //
1424  std::cout << "Simulation Status" << std::endl;
1425 
1426  // Delegate the call to the dedicated service
1427  const std::string& lSimulationStatusStr =
1428  tvlsimService.simulationStatusDisplay();
1429 
1430  // DEBUG: Display the simulation status string
1431  std::cout << lSimulationStatusStr << std::endl;
1432  STDAIR_LOG_DEBUG (lSimulationStatusStr);
1433 
1434  break;
1435  }
1436 
1437  // ////////////////////////////// Reset /////////////////////////
1438  case Command_T::RESET: {
1439  //
1440  std::cout << "Reset" << std::endl;
1441  tvlsimService.reset ();
1442 
1443  //
1444  break;
1445  }
1446 
1447  // ////////////////////////////// List Events /////////////////////////
1448  case Command_T::LIST_EVENT: {
1449 
1450  //
1451  std::ostringstream oEventListStr;
1452 
1453  if (lTokenListByReadline.empty() == true) {
1454 
1455  // If no parameter is given, list all the events in the queue
1456  oEventListStr << tvlsimService.listEvents ();
1457 
1458  } else if (lTokenListByReadline.size() == 1) {
1459 
1460  assert (lTokenListByReadline.empty() == false);
1461  const std::string lEventTypeStr (lTokenListByReadline[0]);
1462 
1463  // If exactly one parameter is given, try to convert it into
1464  // an event type
1465  try {
1466 
1467  const stdair::EventType lEventType (lEventTypeStr);
1468  const stdair::EventType::EN_EventType& lActualEventType =
1469  lEventType.getType();
1470  oEventListStr << tvlsimService.listEvents (lActualEventType);
1471 
1472  } catch (stdair::CodeConversionException e) {
1473  oEventListStr << "The event type '" << lEventTypeStr
1474  << "' is not known. Try 'help' for "
1475  << "more information on the 'list_event' command."
1476  << std::endl;
1477  }
1478  } else {
1479 
1480  // If more than one parameter is given, display an error message
1481  oEventListStr << "The event type is not understood: try 'help' for "
1482  << "more information on the 'list_event' command."
1483  << std::endl;
1484  }
1485  std::cout << oEventListStr.str() << std::endl;
1486  STDAIR_LOG_DEBUG (oEventListStr.str());
1487 
1488  //
1489  break;
1490  }
1491 
1492  // ////////////////////////////// Set Break Point ////////////////////////
1493 
1494  case Command_T::SET_BREAK_POINT: {
1495 
1496  //
1497  extractTokenListForDate (lTokenListByReadline);
1498 
1499  stdair::Date_T lDate (lDefaultDate);
1500  DateList_T lDateList;
1501  // Parse the parameters given by the user, giving default values
1502  // in case the user does not specify some (or all) of them
1503  parseDateListKey (lDate, lDateList);
1504 
1505  assert (lDateList.size() >= 1);
1506 
1507  // Construct the break point list
1508  stdair::BreakPointList_T lBreakPointList;
1509  for (DateList_T::const_iterator itDate = lDateList.begin();
1510  itDate != lDateList.end(); itDate++) {
1511  const stdair::Date_T& lDate = *itDate;
1512  stdair::BreakPointStruct lBreakPoint (lDate);
1513  lBreakPointList.push_back(lBreakPoint);
1514  }
1515  const stdair::Count_T lBPListSize = lBreakPointList.size();
1516  assert (lBPListSize >= 1);
1517 
1518  // Add the break points to the simulation
1519  const stdair::Count_T lNumberOfBreakPointsAdded =
1520  tvlsimService.initBreakPointEvents (lBreakPointList);
1521 
1522  //
1523  std::ostringstream oBreakPointStr;
1524  oBreakPointStr << lNumberOfBreakPointsAdded << " out of "
1525  << lBreakPointList.size() << " break point";
1526  if (lBPListSize > 1) {
1527  oBreakPointStr << "s have";
1528  } else {
1529  oBreakPointStr << " has";
1530  }
1531  oBreakPointStr << " been added to the queue.";
1532  std::cout << oBreakPointStr.str() << std::endl;
1533  STDAIR_LOG_DEBUG (oBreakPointStr.str());
1534 
1535  break;
1536  }
1537 
1538  // ////////////////////////////// List Flight Date /////////////////////////
1539  case Command_T::LIST_FLIGHT_DATE: {
1540 
1541  //
1542  TokenList_T lTokenList = extractTokenListForFlight (lTokenListByReadline);
1543 
1544  stdair::AirlineCode_T lAirlineCode ("all");
1545  stdair::FlightNumber_T lFlightNumber (0);
1546  // Parse the parameters given by the user, giving default values
1547  // in case the user does not specify some (or all) of them
1548  parseFlightKey (lTokenList, lAirlineCode, lFlightNumber);
1549 
1550  //
1551  const std::string lFlightNumberStr = (lFlightNumber ==0)?" (all)":"";
1552  std::cout << "List of flights for "
1553  << lAirlineCode << " " << lFlightNumber << lFlightNumberStr
1554  << std::endl;
1555 
1556  // DEBUG: Display the flight-date
1557  const std::string& lFlightDateListStr =
1558  tvlsimService.list (lAirlineCode, lFlightNumber);
1559 
1560  if (lFlightDateListStr.empty() == false) {
1561  std::cout << lFlightDateListStr << std::endl;
1562  STDAIR_LOG_DEBUG (lFlightDateListStr);
1563 
1564  } else {
1565  std::cerr << "There is no result for "
1566  << lAirlineCode << " " << lFlightNumber << lFlightNumberStr
1567  << ". Just type the 'list' command without any parameter "
1568  << "to see the flight-dates for all the airlines and for all "
1569  << "the flight numbers."
1570  << std::endl;
1571  }
1572 
1573  //
1574  break;
1575  }
1576 
1577  // ////////////////////////////// Display ////////////////////////
1578  case Command_T::DISPLAY_FLIGHT_DATE: {
1579 
1580  //
1581  TokenList_T lTokenList = extractTokenListForFlightDate (lTokenListByReadline);
1582 
1583  stdair::AirlineCode_T lAirlineCode (lDefaultAirlineCode);
1584  stdair::FlightNumber_T lFlightNumber (lDefaultFlightNumber);
1585  stdair::Date_T lFlightDate (lDefaultDate);
1586 
1587  // Parse the parameters given by the user, giving default values
1588  // in case the user does not specify some (or all) of them
1589  parseFlightDateKey (lTokenList, lAirlineCode, lFlightNumber, lFlightDate);
1590 
1591  // DEBUG: Display the flight-date
1592  const std::string& lCSVFlightDateDump =
1593  tvlsimService.csvDisplay (lAirlineCode, lFlightNumber, lFlightDate);
1594 
1595  std::cout << lCSVFlightDateDump << std::endl;
1596  STDAIR_LOG_DEBUG (lCSVFlightDateDump);
1597 
1598  break;
1599  }
1600 
1601  // ////////////////////////////// Sell ////////////////////////
1602  case Command_T::SELL: {
1603  //
1604  TokenList_T lTokenList = extractTokenListForClass (lTokenListByReadline);
1605 
1606  stdair::AirlineCode_T lAirlineCode (lDefaultAirlineCode);
1607  stdair::FlightNumber_T lFlightNumber (lDefaultFlightNumber);
1608  stdair::Date_T lFlightDate (lDefaultDate);
1609  stdair::AirportCode_T lOrigin (lDefaultOrigin);
1610  stdair::AirportCode_T lDestination (lDefaultDestination);
1611  stdair::ClassCode_T lBookingClass (lDefaultBookingClass);
1612  stdair::PartySize_T lPartySize (lDefaultPartySize);
1613 
1614  // Parse the parameters given by the user, giving default values
1615  // in case the user does not specify some (or all) of them
1616  parseFlightDateKey (lTokenList, lAirlineCode,lFlightNumber, lFlightDate);
1617  parseBookingClassKey (lTokenList, lBookingClass,
1618  lPartySize, lOrigin, lDestination);
1619 
1620  std::ostringstream oSDKStr;
1621  oSDKStr << lAirlineCode << ","
1622  << lFlightNumber << ","
1623  << lFlightDate << ","
1624  << lOrigin << "," << lDestination;
1625  const std::string lSegmentDateKey (oSDKStr.str());
1626 
1627  // Perform the sell
1628  const bool isSellSuccessful =
1629  tvlsimService.sell (lSegmentDateKey, lBookingClass,
1630  lPartySize);
1631 
1632  // DEBUG
1633  const std::string isSellSuccessfulStr =
1634  (isSellSuccessful == true)?"Yes":"No";
1635  std::ostringstream oSaleStr;
1636  oSaleStr << "Sale ('" << lSegmentDateKey << "', "
1637  << lBookingClass << ": " << lPartySize
1638  << ") successful? " << isSellSuccessfulStr;
1639  std::cout << oSaleStr.str() << std::endl;
1640 
1641  // DEBUG
1642  STDAIR_LOG_DEBUG (oSaleStr.str());
1643 
1644  break;
1645  }
1646 
1647  // ////////////////////////////// Optimise ////////////////////////
1648  case Command_T::OPTIMISE: {
1649 
1650  //
1651  TokenList_T lTokenList = extractTokenListForFlightDate (lTokenListByReadline);
1652 
1653  stdair::AirlineCode_T lAirlineCode (lDefaultAirlineCode);
1654  stdair::FlightNumber_T lFlightNumber (lDefaultFlightNumber);
1655  stdair::Date_T lFlightDate (lDefaultDate);
1656 
1657  // Parse the parameters given by the user, giving default values
1658  // in case the user does not specify some (or all) of them
1659  parseFlightDateKey (lTokenList, lAirlineCode, lFlightNumber, lFlightDate);
1660 
1661  // Build the flight date key description using the correct format
1662  const std::string& lDepartureDateStr =
1663  boost::gregorian::to_iso_extended_string (lFlightDate);
1664  std::ostringstream oStr;
1665  oStr << lFlightNumber
1666  << stdair::DEFAULT_KEY_SUB_FLD_DELIMITER << " " << lDepartureDateStr;
1667  const stdair::KeyDescription_T lFDKeyDescription (oStr.str());
1668 
1669  // Retrieve the simulation status in order to know the current date
1670  const TVLSIM::SimulationStatus& lSimulationStatus =
1671  tvlsimService.getSimulationStatus();
1672  const stdair::Date_T& lCurrentDate =
1673  lSimulationStatus.getCurrentDate();
1674  const stdair::DateTime_T lRMDateTime (lCurrentDate,
1675  stdair::DEFAULT_NULL_DURATION);
1676 
1677  // Build the revenue management event corresponding to the given
1678  // inventory, the given flight date and the current date time
1679  const stdair::RMEventStruct lRMEvent (lAirlineCode, lFDKeyDescription,
1680  lRMDateTime);
1681 
1682  // DEBUG
1683  std::ostringstream oOptimiseStr;
1684  oOptimiseStr << "Optimise " << lAirlineCode << " " << lFDKeyDescription;
1685 
1686  // Launch the optimiser
1687  try {
1688  tvlsimService.optimise (lRMEvent);
1689  } catch (stdair::ObjectNotFoundException lObjectNotFoundException) {
1690  oOptimiseStr << " FAILED: " << lObjectNotFoundException.what();
1691  }
1692 
1693  // DEBUG
1694  oOptimiseStr << std::endl;
1695  std::cout << oOptimiseStr.str();
1696  STDAIR_LOG_DEBUG (oOptimiseStr.str());
1697 
1698  break;
1699  }
1700 
1701  // ////////////////////////////// JSon Event List ////////////////////////
1702 
1703  case Command_T::JSON_LIST_EVENT: {
1704 
1705  //
1706  std::cout << "JSON List Events" << std::endl;
1707 
1708  //
1709  std::ostringstream lJSONEventListStr;
1710  lJSONEventListStr << "{\"event_list\":";
1711 
1712  if (lTokenListByReadline.empty() == true) {
1713 
1714  // If no parameter is given, list all the events in the queue
1715  lJSONEventListStr << "{ \"event_type\":\"" << "all";
1716 
1717  } else if (lTokenListByReadline.size() == 1) {
1718 
1719  // If one parameter is given, filter according to this event type
1720  assert (lTokenListByReadline.empty() == false);
1721  const std::string lEventTypeStr (lTokenListByReadline[0]);
1722  lJSONEventListStr << "{ \"event_type\":\"" << lEventTypeStr;
1723 
1724  }
1725  lJSONEventListStr << "\"}}";
1726 
1727  // Delegate the call to the dedicated service
1728  const stdair::JSONString lJSONEventTypeString (lJSONEventListStr.str());
1729  const std::string& lCSVEventListDump =
1730  tvlsimService.jsonHandler (lJSONEventTypeString);
1731 
1732  // DEBUG: Display the events queue JSON string
1733  std::cout << lCSVEventListDump << std::endl;
1734  STDAIR_LOG_DEBUG (lCSVEventListDump);
1735 
1736  break;
1737  }
1738 
1739  // ////////////////////////////// JSon Flight Date List ////////////////////////
1740 
1741  case Command_T::JSON_LIST_FLIGHT_DATE: {
1742 
1743  //
1744  TokenList_T lTokenList = extractTokenListForFlight (lTokenListByReadline);
1745 
1746  stdair::AirlineCode_T lAirlineCode ("all");
1747  stdair::FlightNumber_T lFlightNumber (0);
1748  // Parse the parameters given by the user, giving default values
1749  // in case the user does not specify some (or all) of them
1750  parseFlightKey (lTokenList, lAirlineCode, lFlightNumber);
1751 
1752  //
1753  const std::string lFlightNumberStr = (lFlightNumber ==0)?" (all)":"";
1754  std::cout << "JSON list of flights for "
1755  << lAirlineCode << " " << lFlightNumber << lFlightNumberStr
1756  << std::endl;
1757 
1758  std::ostringstream lMyCommandJSONstream;
1759  lMyCommandJSONstream << "{\"list\":"
1760  << "{ \"airline_code\":\"" << lAirlineCode
1761  << "\",\"flight_number\":\"" << lFlightNumber
1762  << "\"}}";
1763 
1764  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1765  const std::string& lFlightDateListJSONStr =
1766  tvlsimService.jsonHandler (lJSONCommandString);
1767 
1768  // Display the flight-date JSON string
1769  std::cout << lFlightDateListJSONStr << std::endl;
1770  STDAIR_LOG_DEBUG (lFlightDateListJSONStr);
1771 
1772  break;
1773  }
1774 
1775  // ////////////////////////////// JSon Flight Date Display ////////////////////////
1776 
1777  case Command_T::JSON_DISPLAY_FLIGHT_DATE: {
1778 
1779  //
1780  TokenList_T lTokenList = extractTokenListForFlightDate (lTokenListByReadline);
1781 
1782  stdair::AirlineCode_T lAirlineCode (lDefaultAirlineCode);
1783  stdair::FlightNumber_T lFlightNumber (lDefaultFlightNumber);
1784  stdair::Date_T lFlightDate (lDefaultDate);
1785  // Parse the parameters given by the user, giving default values
1786  // in case the user does not specify some (or all) of them
1787  parseFlightDateKey (lTokenList, lAirlineCode, lFlightNumber, lFlightDate);
1788 
1789  // Construct the JSON command string for the current parameters (current
1790  // airline code, current flight number and current date)
1791  std::ostringstream lMyCommandJSONstream;
1792  lMyCommandJSONstream << "{\"flight_date\":"
1793  << "{ \"departure_date\":\"" << lFlightDate
1794  << "\",\"airline_code\":\"" << lAirlineCode
1795  << "\",\"flight_number\":\"" << lFlightNumber
1796  << "\"}}";
1797 
1798  // Get the flight-date details in a JSON string
1799  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1800  const std::string& lCSVFlightDateDump =
1801  tvlsimService.jsonHandler (lJSONCommandString);
1802 
1803  // Display the flight-date JSON string
1804  std::cout << lCSVFlightDateDump << std::endl;
1805  STDAIR_LOG_DEBUG (lCSVFlightDateDump);
1806 
1807  break;
1808  }
1809 
1810  // ////////////////////////////// JSon Set Break Point ////////////////////////
1811 
1812  case Command_T::JSON_SET_BREAK_POINT: {
1813 
1814  //
1815  extractTokenListForDate (lTokenListByReadline);
1816 
1817  stdair::Date_T lDate (lDefaultDate);
1818  DateList_T lDateList;
1819  // Parse the parameters given by the user, giving default values
1820  // in case the user does not specify some (or all) of them
1821  parseDateListKey (lDate, lDateList);
1822 
1823  assert (lDateList.size() >= 1);
1824 
1825  // Construct the JSON command string for the current parameters (current
1826  // airline code, current flight number and current date)
1827  std::ostringstream lMyCommandJSONstream;
1828  lMyCommandJSONstream << "{\"break_point\":[";
1829 
1830  for (DateList_T::const_iterator itDate = lDateList.begin();
1831  itDate != lDateList.end(); itDate++) {
1832  const stdair::Date_T lDate = *itDate;
1833  if (itDate == lDateList.begin()) {
1834  lMyCommandJSONstream << "{\"bp\":\"" << lDate << "\"}";
1835  } else {
1836  lMyCommandJSONstream <<",{\"bp\":\"" << lDate << "\"}";
1837  }
1838  }
1839  lMyCommandJSONstream << "]}";
1840 
1841  // Add the break point to the simulation
1842  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1843  const std::string& lCSVBPDump =
1844  tvlsimService.jsonHandler (lJSONCommandString);
1845 
1846  // Display the BP JSON string
1847  std::cout << lCSVBPDump << std::endl;
1848  STDAIR_LOG_DEBUG (lCSVBPDump);
1849 
1850  break;
1851  }
1852 
1853  // ////////////////////////////// JSon Reset ////////////////////////
1854 
1855  case Command_T::JSON_RESET: {
1856 
1857  std::cout << "JSON Reset" << std::endl;
1858 
1859  std::ostringstream lMyCommandJSONstream;
1860  lMyCommandJSONstream << "{\"reset\": \"1\"}";
1861 
1862  // Delegate the call to the dedicated service
1863  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1864  const std::string& lCSVEventListDump =
1865  tvlsimService.jsonHandler (lJSONCommandString);
1866 
1867  // DEBUG: Display the events queue JSON string
1868  std::cout << lCSVEventListDump << std::endl;
1869  STDAIR_LOG_DEBUG (lCSVEventListDump);
1870 
1871  break;
1872  }
1873 
1874  // ////////////////////////////// JSon Run ////////////////////////
1875 
1876  case Command_T::JSON_RUN: {
1877  //
1878  std::cout << "JSON Run" << std::endl;
1879 
1880  std::ostringstream lMyCommandJSONstream;
1881  lMyCommandJSONstream << "{\"run\": \"1\"}";
1882 
1883  // Delegate the call to the dedicated service
1884  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1885  const std::string& lCSVEventListDump =
1886  tvlsimService.jsonHandler (lJSONCommandString);
1887 
1888  // DEBUG: Display the events queue JSON string
1889  STDAIR_LOG_DEBUG (lCSVEventListDump);
1890 
1891  break;
1892  }
1893 
1894  // ////////////////////////////// JSon Display Status ////////////////////////
1895 
1896  case Command_T::JSON_STATUS: {
1897  //
1898  std::cout << "JSON Display status" << std::endl;
1899 
1900  std::ostringstream lMyCommandJSONstream;
1901  lMyCommandJSONstream << "{\"status\": \"1\"}";
1902 
1903  // Delegate the call to the dedicated service
1904  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1905  const std::string& lSimulationStatusJSonDump =
1906  tvlsimService.jsonHandler (lJSONCommandString);
1907 
1908  // DEBUG: Display the simulation status JSON string
1909  std::cout << lSimulationStatusJSonDump << std::endl;
1910  STDAIR_LOG_DEBUG (lSimulationStatusJSonDump);
1911 
1912  break;
1913  }
1914 
1915  // ////////////////////////////// JSon Config Display ////////////////////////
1916 
1917  case Command_T::JSON_CONFIG: {
1918  //
1919  std::cout << "JSON Configuration Display" << std::endl;
1920 
1921  std::ostringstream lMyCommandJSONstream;
1922  lMyCommandJSONstream << "{\"config\": \"1\"}";
1923 
1924  // Delegate the call to the dedicated service
1925  const stdair::JSONString lJSONCommandString (lMyCommandJSONstream.str());
1926  const std::string& lConfigurationStatusJSonDump =
1927  tvlsimService.jsonHandler (lJSONCommandString);
1928 
1929  // DEBUG: Display the configuration JSON string
1930  std::cout << lConfigurationStatusJSonDump << std::endl;
1931  STDAIR_LOG_DEBUG (lConfigurationStatusJSonDump);
1932 
1933  break;
1934  }
1935 
1936 
1937  // /////////////////////////// Default / No value ///////////////////////
1938  case Command_T::NOP: {
1939  break;
1940  }
1941 
1942  case Command_T::LAST_VALUE:
1943  default: {
1944  // DEBUG
1945  std::ostringstream oStr;
1946  oStr << "That command is not yet understood: '" << lUserInput
1947  << "' => " << lTokenListByReadline;
1948  STDAIR_LOG_DEBUG (oStr.str());
1949  std::cout << oStr.str() << std::endl;
1950  }
1951  }
1952  }
1953 
1954  // DEBUG
1955  STDAIR_LOG_DEBUG ("End of the session. Exiting.");
1956  std::cout << "End of the session. Exiting." << std::endl;
1957 
1958  // Close the Log outputFile
1959  logOutputFile.close();
1960 
1961  /*
1962  Note: as that program is not intended to be run on a server in
1963  production, it is better not to catch the exceptions. When it
1964  happens (that an exception is throwned), that way we get the
1965  call stack.
1966  */
1967 
1968  return 0;
1969 }