00001
00005
00006 #include <cassert>
00007 #include <iostream>
00008 #include <sstream>
00009 #include <fstream>
00010 #include <string>
00011
00012 #include <boost/program_options.hpp>
00013 #include <boost/tokenizer.hpp>
00014 #include <boost/regex.hpp>
00015 #include <boost/swap.hpp>
00016 #include <boost/algorithm/string/case_conv.hpp>
00017
00018 #include <stdair/basic/BasLogParams.hpp>
00019 #include <stdair/basic/BasDBParams.hpp>
00020 #include <stdair/service/Logger.hpp>
00021
00022 #include <airinv/AIRINV_Master_Service.hpp>
00023 #include <airinv/config/airinv-paths.hpp>
00024
00025 #include <airinv/ui/cmdline/SReadline.hpp>
00026
00027
00031 const std::string K_AIRINV_DEFAULT_LOG_FILENAME ("airinv.log");
00032
00036 const std::string K_AIRINV_DEFAULT_INVENTORY_FILENAME (STDAIR_SAMPLE_DIR
00037 "/invdump01.csv");
00041 const std::string K_AIRINV_DEFAULT_SCHEDULE_FILENAME (STDAIR_SAMPLE_DIR
00042 "/schedule01.csv");
00046 const std::string K_AIRINV_DEFAULT_OND_FILENAME (STDAIR_SAMPLE_DIR
00047 "/ond01.csv");
00048
00052 const std::string K_AIRINV_DEFAULT_YIELD_FILENAME (STDAIR_SAMPLE_DIR
00053 "/yieldstore01.csv");
00054
00059 const bool K_AIRINV_DEFAULT_BUILT_IN_INPUT = false;
00060
00065 const bool K_AIRINV_DEFAULT_FOR_SCHEDULE = false;
00066
00070 const int K_AIRINV_EARLY_RETURN_STATUS = 99;
00071
00076 typedef std::vector<std::string> TokenList_T;
00077
00081 struct Command_T {
00082 typedef enum {
00083 NOP = 0,
00084 QUIT,
00085 HELP,
00086 LIST,
00087 DISPLAY,
00088 SELECT,
00089 SELL,
00090 LAST_VALUE
00091 } Type_T;
00092 };
00093
00094
00095
00096 template<class T> std::ostream& operator<< (std::ostream& os,
00097 const std::vector<T>& v) {
00098 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
00099 return os;
00100 }
00101
00105 int readConfiguration (int argc, char* argv[],
00106 bool& ioIsBuiltin, bool& ioIsForSchedule,
00107 stdair::Filename_T& ioInventoryFilename,
00108 stdair::Filename_T& ioScheduleInputFilename,
00109 stdair::Filename_T& ioODInputFilename,
00110 stdair::Filename_T& ioYieldInputFilename,
00111 std::string& ioLogFilename) {
00112
00113 ioIsBuiltin = K_AIRINV_DEFAULT_BUILT_IN_INPUT;
00114
00115
00116 ioIsForSchedule = K_AIRINV_DEFAULT_FOR_SCHEDULE;
00117
00118
00119 boost::program_options::options_description generic ("Generic options");
00120 generic.add_options()
00121 ("prefix", "print installation prefix")
00122 ("version,v", "print version string")
00123 ("help,h", "produce help message");
00124
00125
00126
00127
00128 boost::program_options::options_description config ("Configuration");
00129 config.add_options()
00130 ("builtin,b",
00131 "The sample BOM tree can be either built-in or parsed from an input file. That latter must then be given with the -i/--inventory or -s/--schedule option")
00132 ("for_schedule,f",
00133 "The BOM tree should be built from a schedule file (instead of from an inventory dump)")
00134 ("inventory,i",
00135 boost::program_options::value< std::string >(&ioInventoryFilename)->default_value(K_AIRINV_DEFAULT_INVENTORY_FILENAME),
00136 "(CSV) input file for the inventory")
00137 ("schedule,s",
00138 boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_AIRINV_DEFAULT_SCHEDULE_FILENAME),
00139 "(CSV) input file for the schedule")
00140 ("ond,o",
00141 boost::program_options::value< std::string >(&ioODInputFilename)->default_value(K_AIRINV_DEFAULT_OND_FILENAME),
00142 "(CSV) input file for the O&D")
00143 ("yield,y",
00144 boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_AIRINV_DEFAULT_YIELD_FILENAME),
00145 "(CSV) input file for the yield")
00146 ("log,l",
00147 boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_AIRINV_DEFAULT_LOG_FILENAME),
00148 "Filename for the logs")
00149 ;
00150
00151
00152
00153 boost::program_options::options_description hidden ("Hidden options");
00154 hidden.add_options()
00155 ("copyright",
00156 boost::program_options::value< std::vector<std::string> >(),
00157 "Show the copyright (license)");
00158
00159 boost::program_options::options_description cmdline_options;
00160 cmdline_options.add(generic).add(config).add(hidden);
00161
00162 boost::program_options::options_description config_file_options;
00163 config_file_options.add(config).add(hidden);
00164 boost::program_options::options_description visible ("Allowed options");
00165 visible.add(generic).add(config);
00166
00167 boost::program_options::positional_options_description p;
00168 p.add ("copyright", -1);
00169
00170 boost::program_options::variables_map vm;
00171 boost::program_options::
00172 store (boost::program_options::command_line_parser (argc, argv).
00173 options (cmdline_options).positional(p).run(), vm);
00174
00175 std::ifstream ifs ("airinv.cfg");
00176 boost::program_options::store (parse_config_file (ifs, config_file_options),
00177 vm);
00178 boost::program_options::notify (vm);
00179
00180 if (vm.count ("help")) {
00181 std::cout << visible << std::endl;
00182 return K_AIRINV_EARLY_RETURN_STATUS;
00183 }
00184
00185 if (vm.count ("version")) {
00186 std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00187 return K_AIRINV_EARLY_RETURN_STATUS;
00188 }
00189
00190 if (vm.count ("prefix")) {
00191 std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00192 return K_AIRINV_EARLY_RETURN_STATUS;
00193 }
00194
00195 if (vm.count ("builtin")) {
00196 ioIsBuiltin = true;
00197 }
00198 const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00199 std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00200
00201 if (vm.count ("for_schedule")) {
00202 ioIsForSchedule = true;
00203 }
00204 const std::string isForScheduleStr = (ioIsForSchedule == true)?"yes":"no";
00205 std::cout << "The BOM should be built from schedule? " << isForScheduleStr
00206 << std::endl;
00207
00208 if (ioIsBuiltin == false) {
00209
00210 if (ioIsForSchedule == false) {
00211
00212 if (vm.count ("inventory")) {
00213 ioInventoryFilename = vm["inventory"].as< std::string >();
00214 std::cout << "Input inventory filename is: " << ioInventoryFilename
00215 << std::endl;
00216
00217 } else {
00218
00219
00220 std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
00221 << " -f/--for_schedule and -s/--schedule options "
00222 << "must be specified" << std::endl;
00223 }
00224
00225 } else {
00226
00227 if (vm.count ("schedule")) {
00228 ioScheduleInputFilename = vm["schedule"].as< std::string >();
00229 std::cout << "Input schedule filename is: " << ioScheduleInputFilename
00230 << std::endl;
00231
00232 } else {
00233
00234
00235 std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
00236 << " -f/--for_schedule and -s/--schedule options "
00237 << "must be specified" << std::endl;
00238 }
00239
00240 if (vm.count ("ond")) {
00241 ioODInputFilename = vm["ond"].as< std::string >();
00242 std::cout << "Input O&D filename is: " << ioODInputFilename << std::endl;
00243 }
00244
00245 if (vm.count ("yield")) {
00246 ioYieldInputFilename = vm["yield"].as< std::string >();
00247 std::cout << "Input yield filename is: " << ioYieldInputFilename << std::endl;
00248 }
00249 }
00250 }
00251
00252 if (vm.count ("log")) {
00253 ioLogFilename = vm["log"].as< std::string >();
00254 std::cout << "Log filename is: " << ioLogFilename << std::endl;
00255 }
00256
00257 return 0;
00258 }
00259
00260
00261 void initReadline (swift::SReadline& ioInputReader) {
00262
00263
00264 std::vector<std::string> Completers;
00265
00266
00267
00268
00269 Completers.push_back ("help");
00270 Completers.push_back ("list %airline_code %flight_number");
00271 Completers.push_back ("select %airline_code %flight_number %flight_date");
00272 Completers.push_back ("display");
00273 Completers.push_back ("sell %booking_class %party_size %origin %destination");
00274 Completers.push_back ("quit");
00275
00276
00277
00278
00279 ioInputReader.RegisterCompletions (Completers);
00280 }
00281
00282
00283 Command_T::Type_T extractCommand (TokenList_T& ioTokenList) {
00284 Command_T::Type_T oCommandType = Command_T::LAST_VALUE;
00285
00286
00287 if (ioTokenList.empty() == false) {
00288 TokenList_T::iterator itTok = ioTokenList.begin();
00289 std::string lCommand (*itTok);
00290 boost::algorithm::to_lower (lCommand);
00291
00292 if (lCommand == "help") {
00293 oCommandType = Command_T::HELP;
00294
00295 } else if (lCommand == "list") {
00296 oCommandType = Command_T::LIST;
00297
00298 } else if (lCommand == "display") {
00299 oCommandType = Command_T::DISPLAY;
00300
00301 } else if (lCommand == "select") {
00302 oCommandType = Command_T::SELECT;
00303
00304 } else if (lCommand == "sell") {
00305 oCommandType = Command_T::SELL;
00306
00307 } else if (lCommand == "quit") {
00308 oCommandType = Command_T::QUIT;
00309 }
00310
00311
00312
00313 ioTokenList.erase (itTok);
00314
00315 } else {
00316 oCommandType = Command_T::NOP;
00317 }
00318
00319 return oCommandType;
00320 }
00321
00322
00323 void parseFlightKey (const TokenList_T& iTokenList,
00324 stdair::AirlineCode_T& ioAirlineCode,
00325 stdair::FlightNumber_T& ioFlightNumber) {
00326
00327 if (iTokenList.empty() == false) {
00328
00329
00330 TokenList_T::const_iterator itTok = iTokenList.begin();
00331 if (itTok->empty() == false) {
00332 ioAirlineCode = *itTok;
00333 boost::algorithm::to_upper (ioAirlineCode);
00334 }
00335
00336
00337 ++itTok;
00338 if (itTok != iTokenList.end()) {
00339
00340 if (itTok->empty() == false) {
00341 try {
00342
00343 ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
00344
00345 } catch (boost::bad_lexical_cast& eCast) {
00346 std::cerr << "The flight number ('" << *itTok
00347 << "') cannot be understood. "
00348 << "The default value (all) is kept."
00349 << std::endl;
00350 return;
00351 }
00352 }
00353
00354 } else {
00355 return;
00356 }
00357 }
00358 }
00359
00360
00361 void parseFlightDateKey (const TokenList_T& iTokenList,
00362 stdair::AirlineCode_T& ioAirlineCode,
00363 stdair::FlightNumber_T& ioFlightNumber,
00364 stdair::Date_T& ioDepartureDate) {
00365
00366 const std::string kMonthStr[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
00367 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
00368
00369 unsigned short ioDepartureDateYear = ioDepartureDate.year();
00370 unsigned short ioDepartureDateMonth = ioDepartureDate.month();
00371 std::string ioDepartureDateMonthStr = kMonthStr[ioDepartureDateMonth-1];
00372 unsigned short ioDepartureDateDay = ioDepartureDate.day();
00373
00374
00375 if (iTokenList.empty() == false) {
00376
00377
00378 TokenList_T::const_iterator itTok = iTokenList.begin();
00379 if (itTok->empty() == false) {
00380 ioAirlineCode = *itTok;
00381 boost::algorithm::to_upper (ioAirlineCode);
00382 }
00383
00384
00385 ++itTok;
00386 if (itTok != iTokenList.end()) {
00387
00388 if (itTok->empty() == false) {
00389 try {
00390
00391 ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
00392
00393 } catch (boost::bad_lexical_cast& eCast) {
00394 std::cerr << "The flight number ('" << *itTok
00395 << "') cannot be understood. "
00396 << "The default value (all) is kept."
00397 << std::endl;
00398 return;
00399 }
00400 }
00401
00402 } else {
00403 return;
00404 }
00405
00406
00407 ++itTok;
00408 if (itTok != iTokenList.end()) {
00409
00410 if (itTok->empty() == false) {
00411 try {
00412
00413 ioDepartureDateYear = boost::lexical_cast<unsigned short> (*itTok);
00414 if (ioDepartureDateYear < 100) {
00415 ioDepartureDateYear += 2000;
00416 }
00417
00418 } catch (boost::bad_lexical_cast& eCast) {
00419 std::cerr << "The year of the flight departure date ('" << *itTok
00420 << "') cannot be understood. The default value ("
00421 << ioDepartureDateYear << ") is kept. " << std::endl;
00422 return;
00423 }
00424 }
00425
00426 } else {
00427 return;
00428 }
00429
00430
00431 ++itTok;
00432 if (itTok != iTokenList.end()) {
00433
00434 if (itTok->empty() == false) {
00435 try {
00436
00437 const boost::regex lMonthRegex ("^(\\d{1,2})$");
00438 const bool isMonthANumber = regex_match (*itTok, lMonthRegex);
00439
00440 if (isMonthANumber == true) {
00441 const unsigned short lMonth =
00442 boost::lexical_cast<unsigned short> (*itTok);
00443 if (lMonth > 12) {
00444 throw boost::bad_lexical_cast();
00445 }
00446 ioDepartureDateMonthStr = kMonthStr[lMonth-1];
00447
00448 } else {
00449 const std::string lMonthStr (*itTok);
00450 if (lMonthStr.size() < 3) {
00451 throw boost::bad_lexical_cast();
00452 }
00453 std::string lMonthStr1 (lMonthStr.substr (0, 1));
00454 boost::algorithm::to_upper (lMonthStr1);
00455 std::string lMonthStr23 (lMonthStr.substr (1, 2));
00456 boost::algorithm::to_lower (lMonthStr23);
00457 ioDepartureDateMonthStr = lMonthStr1 + lMonthStr23;
00458 }
00459
00460 } catch (boost::bad_lexical_cast& eCast) {
00461 std::cerr << "The month of the flight departure date ('" << *itTok
00462 << "') cannot be understood. The default value ("
00463 << ioDepartureDateMonthStr << ") is kept. " << std::endl;
00464 return;
00465 }
00466 }
00467
00468 } else {
00469 return;
00470 }
00471
00472
00473 ++itTok;
00474 if (itTok != iTokenList.end()) {
00475
00476 if (itTok->empty() == false) {
00477 try {
00478
00479 ioDepartureDateDay = boost::lexical_cast<unsigned short> (*itTok);
00480
00481 } catch (boost::bad_lexical_cast& eCast) {
00482 std::cerr << "The day of the flight departure date ('" << *itTok
00483 << "') cannot be understood. The default value ("
00484 << ioDepartureDateDay << ") is kept. " << std::endl;
00485 return;
00486 }
00487 }
00488
00489 } else {
00490 return;
00491 }
00492
00493
00494 std::ostringstream lDepartureDateStr;
00495 lDepartureDateStr << ioDepartureDateYear << "-" << ioDepartureDateMonthStr
00496 << "-" << ioDepartureDateDay;
00497
00498 try {
00499
00500 ioDepartureDate =
00501 boost::gregorian::from_simple_string (lDepartureDateStr.str());
00502
00503 } catch (boost::gregorian::bad_month& eCast) {
00504 std::cerr << "The flight departure date ('" << lDepartureDateStr.str()
00505 << "') cannot be understood. The default value ("
00506 << ioDepartureDate << ") is kept. " << std::endl;
00507 return;
00508 }
00509
00510 }
00511 }
00512
00513
00514 void parseBookingClassKey (const TokenList_T& iTokenList,
00515 stdair::ClassCode_T& ioBookingClass,
00516 stdair::PartySize_T& ioPartySize,
00517 stdair::AirportCode_T& ioOrigin,
00518 stdair::AirportCode_T& ioDestination) {
00519
00520 if (iTokenList.empty() == false) {
00521
00522
00523 TokenList_T::const_iterator itTok = iTokenList.begin();
00524 if (itTok->empty() == false) {
00525 ioBookingClass = *itTok;
00526 boost::algorithm::to_upper (ioBookingClass);
00527 }
00528
00529
00530 ++itTok;
00531 if (itTok != iTokenList.end()) {
00532
00533 if (itTok->empty() == false) {
00534 try {
00535
00536 ioPartySize = boost::lexical_cast<stdair::PartySize_T> (*itTok);
00537
00538 } catch (boost::bad_lexical_cast& eCast) {
00539 std::cerr << "The party size ('" << *itTok
00540 << "') cannot be understood. The default value ("
00541 << ioPartySize << ") is kept." << std::endl;
00542 return;
00543 }
00544 }
00545
00546 } else {
00547 return;
00548 }
00549
00550
00551 ++itTok;
00552 if (itTok != iTokenList.end()) {
00553
00554 if (itTok->empty() == false) {
00555 ioOrigin = *itTok;
00556 boost::algorithm::to_upper (ioOrigin);
00557 }
00558
00559 } else {
00560 return;
00561 }
00562
00563
00564 ++itTok;
00565 if (itTok != iTokenList.end()) {
00566
00567 if (itTok->empty() == false) {
00568 ioDestination = *itTok;
00569 boost::algorithm::to_upper (ioDestination);
00570 }
00571
00572 } else {
00573 return;
00574 }
00575 }
00576 }
00577
00578
00579 std::string toString (const TokenList_T& iTokenList) {
00580 std::ostringstream oStr;
00581
00582
00583 unsigned short idx = 0;
00584 for (TokenList_T::const_iterator itTok = iTokenList.begin();
00585 itTok != iTokenList.end(); ++itTok, ++idx) {
00586 if (idx != 0) {
00587 oStr << " ";
00588 }
00589 oStr << *itTok;
00590 }
00591
00592 return oStr.str();
00593 }
00594
00595
00596 TokenList_T extractTokenList (const TokenList_T& iTokenList,
00597 const std::string& iRegularExpression) {
00598 TokenList_T oTokenList;
00599
00600
00601
00602 const std::string lFullLine = toString (iTokenList);
00603
00604
00605 boost::regex expression (iRegularExpression);
00606
00607 std::string::const_iterator start = lFullLine.begin();
00608 std::string::const_iterator end = lFullLine.end();
00609
00610 boost::match_results<std::string::const_iterator> what;
00611 boost::match_flag_type flags = boost::match_default | boost::format_sed;
00612 regex_search (start, end, what, expression, flags);
00613
00614
00615
00616 const unsigned short lMatchSetSize = what.size();
00617 for (unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
00618 const std::string lMatchedString (std::string (what[matchIdx].first,
00619 what[matchIdx].second));
00620
00621 oTokenList.push_back (lMatchedString);
00622
00623 }
00624
00625
00626
00627
00628 return oTokenList;
00629 }
00630
00631
00632 TokenList_T extractTokenListForFlight (const TokenList_T& iTokenList) {
00639 const std::string lRegEx ("^([[:alpha:]]{2,3})?"
00640 "[[:space:]]*([[:digit:]]{1,4})?$");
00641
00642
00643 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00644 return oTokenList;
00645 }
00646
00647
00648 TokenList_T extractTokenListForFlightDate (const TokenList_T& iTokenList) {
00659 const std::string lRegEx("^([[:alpha:]]{2,3})?"
00660 "[[:space:]]*([[:digit:]]{1,4})?"
00661 "[/ ]*"
00662 "([[:digit:]]{2,4})?[/-]?[[:space:]]*"
00663 "([[:alpha:]]{3}|[[:digit:]]{1,2})?[/-]?[[:space:]]*"
00664 "([[:digit:]]{1,2})?$");
00665
00666
00667 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00668 return oTokenList;
00669 }
00670
00671
00672 TokenList_T extractTokenListForClass (const TokenList_T& iTokenList) {
00681 const std::string lRegEx ("^([[:alpha:]])?"
00682 "[[:space:]]*([[:digit:]]{1,3})?"
00683 "[[:space:]]*([[:alpha:]]{3})?"
00684 "[[:space:]]*([[:alpha:]]{3})?$");
00685
00686
00687 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00688 return oTokenList;
00689 }
00690
00691
00692
00693 int main (int argc, char* argv[]) {
00694
00695
00696
00697 bool isBuiltin;
00698 bool isForSchedule;
00699
00700
00701 stdair::Filename_T lInventoryFilename;
00702 stdair::Filename_T lScheduleInputFilename;
00703 stdair::Filename_T lODInputFilename;
00704 stdair::Filename_T lYieldInputFilename;
00705
00706
00707 const unsigned int lHistorySize (100);
00708 const std::string lHistoryFilename ("airinv.hist");
00709 const std::string lHistoryBackupFilename ("airinv.hist.bak");
00710
00711
00712 stdair::AirlineCode_T lLastInteractiveAirlineCode;
00713 stdair::FlightNumber_T lLastInteractiveFlightNumber;
00714 stdair::Date_T lLastInteractiveDate;
00715 stdair::AirlineCode_T lInteractiveAirlineCode;
00716 stdair::FlightNumber_T lInteractiveFlightNumber;
00717 stdair::Date_T lInteractiveDate;
00718 stdair::AirportCode_T lInteractiveOrigin;
00719 stdair::AirportCode_T lInteractiveDestination;
00720 stdair::ClassCode_T lInteractiveBookingClass;
00721 stdair::PartySize_T lInteractivePartySize;
00722
00723
00724 std::string lSegmentDateKey;
00725
00726
00727 stdair::Filename_T lLogFilename;
00728
00729
00730 const int lOptionParserStatus =
00731 readConfiguration (argc, argv, isBuiltin, isForSchedule, lInventoryFilename,
00732 lScheduleInputFilename, lODInputFilename,
00733 lYieldInputFilename, lLogFilename);
00734
00735 if (lOptionParserStatus == K_AIRINV_EARLY_RETURN_STATUS) {
00736 return 0;
00737 }
00738
00739
00740 std::ofstream logOutputFile;
00741
00742 logOutputFile.open (lLogFilename.c_str());
00743 logOutputFile.clear();
00744
00745
00746 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00747 AIRINV::AIRINV_Master_Service airinvService (lLogParams);
00748
00749
00750 STDAIR_LOG_DEBUG ("Welcome to AirInv");
00751
00752
00753 if (isBuiltin == true) {
00754
00755
00756 airinvService.buildSampleBom();
00757
00758
00759 lInteractiveAirlineCode = "BA";
00760 lInteractiveFlightNumber = 9;
00761 lInteractiveDate = stdair::Date_T (2011, 06, 10);
00762 lInteractiveBookingClass = "Q";
00763 lInteractivePartySize = 2;
00764 lInteractiveOrigin = "LHR";
00765 lInteractiveDestination = "SYD";
00766
00767 } else {
00768 if (isForSchedule == true) {
00769
00770 AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
00771 airinvService.parseAndLoad (lScheduleInputFilename, lODInputFilename,
00772 lYieldFilePath);
00773
00774
00775 lInteractiveAirlineCode = "SQ";
00776 lInteractiveFlightNumber = 11;
00777 lInteractiveDate = stdair::Date_T (2010, 01, 15);
00778 lInteractiveBookingClass = "Y";
00779 lInteractivePartySize = 2;
00780 lInteractiveOrigin = "SIN";
00781 lInteractiveDestination = "BKK";
00782
00783 } else {
00784
00785 airinvService.parseAndLoad (lInventoryFilename);
00786
00787
00788 lInteractiveAirlineCode = "SV";
00789 lInteractiveFlightNumber = 5;
00790 lInteractiveDate = stdair::Date_T (2010, 03, 11);
00791 lInteractiveBookingClass = "Y";
00792 lInteractivePartySize = 2;
00793 lInteractiveOrigin = "KBP";
00794 lInteractiveDestination = "JFK";
00795 }
00796 }
00797
00798
00799 lLastInteractiveAirlineCode = lInteractiveAirlineCode;
00800 lLastInteractiveFlightNumber = lInteractiveFlightNumber;
00801 lLastInteractiveDate = lInteractiveDate;
00802
00803
00804 STDAIR_LOG_DEBUG ("====================================================");
00805 STDAIR_LOG_DEBUG ("= Beginning of the interactive session =");
00806 STDAIR_LOG_DEBUG ("====================================================");
00807
00808
00809 swift::SReadline lReader (lHistoryFilename, lHistorySize);
00810 initReadline (lReader);
00811
00812
00813 std::string lUserInput;
00814 bool EndOfInput (false);
00815 Command_T::Type_T lCommandType (Command_T::NOP);
00816
00817 while (lCommandType != Command_T::QUIT && EndOfInput == false) {
00818
00819 std::ostringstream oPromptStr;
00820 oPromptStr << "airinv "
00821 << lInteractiveAirlineCode << lInteractiveFlightNumber
00822 << " / " << lInteractiveDate
00823 << "> ";
00824
00825 TokenList_T lTokenListByReadline;
00826 lUserInput = lReader.GetLine (oPromptStr.str(), lTokenListByReadline,
00827 EndOfInput);
00828
00829
00830 lReader.SaveHistory (lHistoryBackupFilename);
00831
00832
00833 if (EndOfInput) {
00834 std::cout << std::endl;
00835 break;
00836 }
00837
00838
00839 lCommandType = extractCommand (lTokenListByReadline);
00840
00841 switch (lCommandType) {
00842
00843
00844 case Command_T::HELP: {
00845 std::cout << std::endl;
00846 std::cout << "Commands: " << std::endl;
00847 std::cout << " help" << "\t\t" << "Display this help" << std::endl;
00848 std::cout << " quit" << "\t\t" << "Quit the application" << std::endl;
00849 std::cout << " list" << "\t\t"
00850 << "List airlines, flights and departure dates" << std::endl;
00851 std::cout << " select" << "\t\t"
00852 << "Select a flight-date to become the current one"
00853 << std::endl;
00854 std::cout << " display" << "\t"
00855 << "Display the current flight-date" << std::endl;
00856 std::cout << " sell" << "\t\t"
00857 << "Make a booking on the current flight-date" << std::endl;
00858 std::cout << std::endl;
00859 break;
00860 }
00861
00862
00863 case Command_T::QUIT: {
00864 break;
00865 }
00866
00867
00868 case Command_T::LIST: {
00869
00870 TokenList_T lTokenList = extractTokenListForFlight (lTokenListByReadline);
00871
00872 stdair::AirlineCode_T lAirlineCode ("all");
00873 stdair::FlightNumber_T lFlightNumber (0);
00874
00875
00876 parseFlightKey (lTokenList, lAirlineCode, lFlightNumber);
00877
00878
00879 const std::string lFlightNumberStr = (lFlightNumber ==0)?" (all)":"";
00880 std::cout << "List of flights for "
00881 << lAirlineCode << " " << lFlightNumber << lFlightNumberStr
00882 << std::endl;
00883
00884
00885 const std::string& lFlightDateListStr =
00886 airinvService.list (lAirlineCode, lFlightNumber);
00887
00888 if (lFlightDateListStr.empty() == false) {
00889 std::cout << lFlightDateListStr << std::endl;
00890 STDAIR_LOG_DEBUG (lFlightDateListStr);
00891
00892 } else {
00893 std::cerr << "There is no result for "
00894 << lAirlineCode << " " << lFlightNumber << lFlightNumberStr
00895 << ". Just type the list command without any parameter "
00896 << "to see the flight-dates for all the airlines and for all "
00897 << "the flight numbers."
00898 << std::endl;
00899 }
00900
00901 break;
00902 }
00903
00904
00905 case Command_T::SELECT: {
00906
00907 TokenList_T lTokenList =
00908 extractTokenListForFlightDate (lTokenListByReadline);
00909
00910
00911 if (lTokenList.empty() == false) {
00912
00913 TokenList_T::const_iterator itTok = lTokenList.begin();
00914
00915 if (*itTok == "-") {
00916
00917
00918 boost::swap (lInteractiveAirlineCode, lLastInteractiveAirlineCode);
00919 boost::swap (lInteractiveFlightNumber, lLastInteractiveFlightNumber);
00920 boost::swap (lInteractiveDate, lLastInteractiveDate);
00921
00922 break;
00923 }
00924 }
00925
00926
00927
00928 parseFlightDateKey (lTokenList, lInteractiveAirlineCode,
00929 lInteractiveFlightNumber, lInteractiveDate);
00930
00931
00932 const bool isFlightDateValid =
00933 airinvService.check (lInteractiveAirlineCode, lInteractiveFlightNumber,
00934 lInteractiveDate);
00935 if (isFlightDateValid == false) {
00936 std::ostringstream oFDKStr;
00937 oFDKStr << "The " << lInteractiveAirlineCode
00938 << lInteractiveFlightNumber << " / " << lInteractiveDate
00939 << " flight-date is not valid. Make sure it exists (e.g.,"
00940 << " with the list command). The current flight-date is kept"
00941 << " selected.";
00942 std::cout << oFDKStr.str() << std::endl;
00943 STDAIR_LOG_ERROR (oFDKStr.str());
00944
00945
00946 lInteractiveAirlineCode = lLastInteractiveAirlineCode;
00947 lInteractiveFlightNumber = lLastInteractiveFlightNumber;
00948 lInteractiveDate = lLastInteractiveDate;
00949
00950 break;
00951 }
00952
00953
00954 std::ostringstream oFDKStr;
00955 oFDKStr << "Selected the " << lInteractiveAirlineCode
00956 << lInteractiveFlightNumber << " / " << lInteractiveDate
00957 << " flight-date";
00958 std::cout << oFDKStr.str() << std::endl;
00959 STDAIR_LOG_DEBUG (oFDKStr.str());
00960
00961
00962 lLastInteractiveAirlineCode = lInteractiveAirlineCode;
00963 lLastInteractiveFlightNumber = lInteractiveFlightNumber;
00964 lLastInteractiveDate = lInteractiveDate;
00965
00966 break;
00967 }
00968
00969
00970 case Command_T::DISPLAY: {
00971
00972 const std::string& lCSVFlightDateDump =
00973 airinvService.csvDisplay (lInteractiveAirlineCode,
00974 lInteractiveFlightNumber, lInteractiveDate);
00975 std::cout << lCSVFlightDateDump << std::endl;
00976 STDAIR_LOG_DEBUG (lCSVFlightDateDump);
00977
00978 break;
00979 }
00980
00981
00982 case Command_T::SELL: {
00983
00984 TokenList_T lTokenList = extractTokenListForClass (lTokenListByReadline);
00985
00986
00987
00988 parseBookingClassKey (lTokenList, lInteractiveBookingClass,
00989 lInteractivePartySize,
00990 lInteractiveOrigin, lInteractiveDestination);
00991
00992
00993 const std::string& lCSVFlightDateDumpBefore =
00994 airinvService.csvDisplay (lInteractiveAirlineCode,
00995 lInteractiveFlightNumber, lInteractiveDate);
00996
00997 STDAIR_LOG_DEBUG (lCSVFlightDateDumpBefore);
00998
00999
01000 std::ostringstream oSDKStr;
01001 oSDKStr << lInteractiveAirlineCode << ","
01002 << lInteractiveFlightNumber << ","
01003 << lInteractiveDate << ","
01004 << lInteractiveOrigin << "," << lInteractiveDestination;
01005 const std::string lSegmentDateKey (oSDKStr.str());
01006
01007
01008 const bool isSellSuccessful =
01009 airinvService.sell (lSegmentDateKey,
01010 lInteractiveBookingClass, lInteractivePartySize);
01011
01012
01013 const std::string isSellSuccessfulStr =
01014 (isSellSuccessful == true)?"Yes":"No";
01015 std::ostringstream oSaleStr;
01016 oSaleStr << "Sale ('" << lSegmentDateKey << "', "
01017 << lInteractiveBookingClass << ": " << lInteractivePartySize
01018 << ") successful? " << isSellSuccessfulStr;
01019 std::cout << oSaleStr.str() << std::endl;
01020
01021
01022 STDAIR_LOG_DEBUG (oSaleStr.str());
01023
01024
01025 const std::string& lCSVFlightDateDumpAfter =
01026 airinvService.csvDisplay (lInteractiveAirlineCode,
01027 lInteractiveFlightNumber, lInteractiveDate);
01028
01029 STDAIR_LOG_DEBUG (lCSVFlightDateDumpAfter);
01030
01031 break;
01032 }
01033
01034
01035 case Command_T::NOP: {
01036 break;
01037 }
01038
01039 case Command_T::LAST_VALUE:
01040 default: {
01041
01042 std::ostringstream oStr;
01043 oStr << "That command is not yet understood: '" << lUserInput
01044 << "' => " << lTokenListByReadline;
01045 STDAIR_LOG_DEBUG (oStr.str());
01046 std::cout << oStr.str() << std::endl;
01047 }
01048 }
01049 }
01050
01051
01052 STDAIR_LOG_DEBUG ("End of the session. Exiting.");
01053 std::cout << "End of the session. Exiting." << std::endl;
01054
01055
01056 logOutputFile.close();
01057
01058
01059
01060
01061
01062
01063
01064
01065 return 0;
01066 }