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
00016 #include <stdair/basic/BasLogParams.hpp>
00017 #include <stdair/basic/BasConst_BomDisplay.hpp>
00018 #include <stdair/basic/BasDBParams.hpp>
00019 #include <stdair/basic/BasConst_DefaultObject.hpp>
00020 #include <stdair/basic/BasConst_Inventory.hpp>
00021 #include <stdair/basic/BasConst_Request.hpp>
00022 #include <stdair/service/Logger.hpp>
00023 #include <stdair/stdair_exceptions.hpp>
00024 #include <stdair/stdair_basic_types.hpp>
00025 #include <stdair/stdair_date_time_types.hpp>
00026 #include <stdair/bom/TravelSolutionStruct.hpp>
00027 #include <stdair/bom/BookingRequestStruct.hpp>
00028 #include <stdair/bom/ParsedKey.hpp>
00029 #include <stdair/bom/BomKeyManager.hpp>
00030 #include <stdair/command/CmdBomManager.hpp>
00031
00032 #include <stdair/ui/cmdline/SReadline.hpp>
00033
00034 #include <simfqt/SIMFQT_Service.hpp>
00035 #include <simfqt/config/simfqt-paths.hpp>
00036
00037
00038
00042 const std::string K_SIMFQT_DEFAULT_LOG_FILENAME ("simfqt.log");
00043
00047 const std::string K_SIMFQT_DEFAULT_FARE_INPUT_FILENAME (STDAIR_SAMPLE_DIR
00048 "/fare01.csv");
00049
00054 const bool K_SIMFQT_DEFAULT_BUILT_IN_INPUT = false;
00055
00059 const int K_SIMFQT_EARLY_RETURN_STATUS = 99;
00060
00065 typedef std::vector<std::string> TokenList_T;
00066
00070 struct Command_T {
00071 typedef enum {
00072 NOP = 0,
00073 QUIT,
00074 HELP,
00075 LIST,
00076 DISPLAY,
00077 PRICE,
00078 LAST_VALUE
00079 } Type_T;
00080 };
00081
00082
00083
00084 template<class T> std::ostream& operator<< (std::ostream& os,
00085 const std::vector<T>& v) {
00086 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
00087 return os;
00088 }
00089
00093 int readConfiguration (int argc, char* argv[], bool& ioIsBuiltin,
00094 stdair::Filename_T& ioFareInputFilename,
00095 std::string& ioLogFilename) {
00096
00097
00098 ioIsBuiltin = K_SIMFQT_DEFAULT_BUILT_IN_INPUT;
00099
00100
00101 boost::program_options::options_description generic ("Generic options");
00102 generic.add_options()
00103 ("prefix", "print installation prefix")
00104 ("version,v", "print version string")
00105 ("help,h", "produce help message");
00106
00107
00108
00109 boost::program_options::options_description config ("Configuration");
00110 config.add_options()
00111 ("builtin,b",
00112 "The sample BOM tree can be either built-in or parsed from an input file. That latter must then be given with the -f/--fare option")
00113 ("fare,f",
00114 boost::program_options::value< std::string >(&ioFareInputFilename)->default_value(K_SIMFQT_DEFAULT_FARE_INPUT_FILENAME),
00115 "(CSV) input file for the fare rules")
00116 ("log,l",
00117 boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_SIMFQT_DEFAULT_LOG_FILENAME),
00118 "Filename for the logs")
00119 ;
00120
00121
00122
00123 boost::program_options::options_description hidden ("Hidden options");
00124 hidden.add_options()
00125 ("copyright",
00126 boost::program_options::value< std::vector<std::string> >(),
00127 "Show the copyright (license)");
00128
00129 boost::program_options::options_description cmdline_options;
00130 cmdline_options.add(generic).add(config).add(hidden);
00131
00132 boost::program_options::options_description config_file_options;
00133 config_file_options.add(config).add(hidden);
00134
00135 boost::program_options::options_description visible ("Allowed options");
00136 visible.add(generic).add(config);
00137
00138 boost::program_options::positional_options_description p;
00139 p.add ("copyright", -1);
00140
00141 boost::program_options::variables_map vm;
00142 boost::program_options::
00143 store (boost::program_options::command_line_parser (argc, argv).
00144 options (cmdline_options).positional(p).run(), vm);
00145
00146 std::ifstream ifs ("simfqt.cfg");
00147 boost::program_options::store (parse_config_file (ifs, config_file_options),
00148 vm);
00149 boost::program_options::notify (vm); if (vm.count ("help")) {
00150 std::cout << visible << std::endl;
00151 return K_SIMFQT_EARLY_RETURN_STATUS;
00152 }
00153
00154 if (vm.count ("version")) {
00155 std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00156 return K_SIMFQT_EARLY_RETURN_STATUS;
00157 }
00158
00159 if (vm.count ("prefix")) {
00160 std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00161 return K_SIMFQT_EARLY_RETURN_STATUS;
00162 }
00163
00164 if (vm.count ("builtin")) {
00165 ioIsBuiltin = true;
00166 }
00167 const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
00168 std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
00169
00170 if (ioIsBuiltin == false) {
00171
00172
00173 if (vm.count ("fare")) {
00174 ioFareInputFilename = vm["fare"].as< std::string >();
00175 std::cout << "Input fare filename is: " << ioFareInputFilename
00176 << std::endl;
00177
00178 } else {
00179
00180
00181 std::cerr << "Either one among the -b/--builtin and -f/--fare "
00182 << "options must be specified" << std::endl;
00183 }
00184 }
00185
00186 if (vm.count ("log")) {
00187 ioLogFilename = vm["log"].as< std::string >();
00188 std::cout << "Log filename is: " << ioLogFilename << std::endl;
00189 }
00190
00191 return 0;
00192
00193 }
00194
00195
00196 void initReadline (swift::SReadline& ioInputReader) {
00197
00198
00199 std::vector<std::string> Completers;
00200
00201
00202
00203
00204 Completers.push_back ("help");
00205 Completers.push_back ("list");
00206 Completers.push_back ("display %airport_code %airport_code %departure_date");
00207 Completers.push_back ("price %airline_code %flight_number %departure_date %airport_code %airport_code %departure_time %booking_date %booking_time %POS %channel% %trip_type %stay_duration");
00208 Completers.push_back ("quit");
00209
00210
00211
00212 ioInputReader.RegisterCompletions (Completers);
00213 }
00214
00215
00216 Command_T::Type_T extractCommand (TokenList_T& ioTokenList) {
00217 Command_T::Type_T oCommandType = Command_T::LAST_VALUE;
00218
00219
00220 if (ioTokenList.empty() == false) {
00221 TokenList_T::iterator itTok = ioTokenList.begin();
00222 std::string& lCommand (*itTok);
00223 boost::algorithm::to_lower (lCommand);
00224
00225 if (lCommand == "help") {
00226 oCommandType = Command_T::HELP;
00227
00228 } else if (lCommand == "list") {
00229 oCommandType = Command_T::LIST;
00230
00231 } else if (lCommand == "display") {
00232 oCommandType = Command_T::DISPLAY;
00233
00234 } else if (lCommand == "price") {
00235 oCommandType = Command_T::PRICE;
00236
00237 } else if (lCommand == "quit") {
00238 oCommandType = Command_T::QUIT;
00239
00240 }
00241
00242
00243
00244 ioTokenList.erase (itTok);
00245
00246 } else {
00247 oCommandType = Command_T::NOP;
00248 }
00249
00250 return oCommandType;
00251 }
00252
00253
00254
00255
00256 bool retrieveDate (std::string iYearString,
00257 std::string iMonthString,
00258 std::string iDayString,
00259 stdair::Date_T& ioDate) {
00260
00261 const std::string kMonthStr[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
00262 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
00263
00264
00265 unsigned short lDateYear;
00266 try {
00267
00268 lDateYear = boost::lexical_cast<unsigned short> (iYearString);
00269 if (lDateYear < 100) {
00270 lDateYear += 2000;
00271 }
00272
00273 } catch (boost::bad_lexical_cast& eCast) {
00274 std::cerr << "The year ('" << iYearString
00275 << "') cannot be understood." << std::endl;
00276 return false;
00277 }
00278
00279
00280 std::string lDateMonthStr;
00281 try {
00282
00283 const boost::regex lMonthRegex ("^(\\d{1,2})$");
00284 const bool isMonthANumber = regex_match (iMonthString, lMonthRegex);
00285
00286 if (isMonthANumber == true) {
00287 const unsigned short lMonth =
00288 boost::lexical_cast<unsigned short> (iMonthString);
00289 if (lMonth > 12) {
00290 throw boost::bad_lexical_cast();
00291 }
00292 if (lMonth != 0) {
00293 lDateMonthStr = kMonthStr[lMonth-1];
00294 } else {
00295 std::cerr << "The month ('" << iMonthString
00296 << "') cannot be understood." << std::endl;
00297 return false;
00298 }
00299
00300 } else {
00301 if (iMonthString.size() < 3) {
00302 throw boost::bad_lexical_cast();
00303 }
00304 std::string lMonthStr1 (iMonthString.substr (0, 1));
00305 boost::algorithm::to_upper (lMonthStr1);
00306 std::string lMonthStr23 (iMonthString.substr (1, 2));
00307 boost::algorithm::to_lower (lMonthStr23);
00308 lDateMonthStr = lMonthStr1 + lMonthStr23;
00309 }
00310
00311 } catch (boost::bad_lexical_cast& eCast) {
00312 std::cerr << "The month ('" << iMonthString
00313 << "') cannot be understood." << std::endl;
00314 return false;
00315 }
00316
00317
00318 unsigned short lDateDay;
00319 try {
00320
00321 lDateDay = boost::lexical_cast<unsigned short> (iDayString);
00322
00323 } catch (boost::bad_lexical_cast& eCast) {
00324 std::cerr << "The day ('" << iDayString
00325 << "') cannot be understood." << std::endl;
00326 return false;
00327 }
00328
00329
00330 std::ostringstream lDateStr;
00331 lDateStr << lDateYear << "-" << lDateMonthStr
00332 << "-" << lDateDay;
00333 try {
00334
00335 ioDate =
00336 boost::gregorian::from_simple_string (lDateStr.str());
00337
00338 } catch (boost::gregorian::bad_month& eCast) {
00339 std::cerr << "The month of the date ('" << lDateStr.str()
00340 << "') cannot be understood." << std::endl;
00341 return false;
00342 } catch (boost::gregorian::bad_day_of_month& eCast) {
00343 std::cerr << "The date ('" << lDateStr.str()
00344 << "') is not correct: the day of month does not exist."
00345 << std::endl;
00346 return false;
00347 } catch (boost::gregorian::bad_year& eCast) {
00348 std::cerr << "The year ('" << lDateStr.str()
00349 << "') is not correct."
00350 << std::endl;
00351 return false;
00352 }
00353
00354 return true;
00355 }
00356
00357
00358
00359
00360 bool retrieveTime (std::string iHourString,
00361 std::string iMinuteString,
00362 stdair::Duration_T& oTime) {
00363
00364
00365 unsigned short lTimeHour;
00366 try {
00367
00368 lTimeHour = boost::lexical_cast<unsigned short> (iHourString);
00369
00370 } catch (boost::bad_lexical_cast& eCast) {
00371 std::cerr << "The hour of the time ('" << iHourString
00372 << "') cannot be understood." << std::endl;
00373 return false;
00374 }
00375
00376
00377 unsigned short lTimeMinute;
00378 try {
00379
00380 lTimeMinute = boost::lexical_cast<unsigned short> (iMinuteString);
00381
00382 } catch (boost::bad_lexical_cast& eCast) {
00383 std::cerr << "The minute of the time ('" << iMinuteString
00384 << "') cannot be understood." << std::endl;
00385 return false;
00386 }
00387
00388
00389
00390 std::ostringstream lTimeStr;
00391 lTimeStr << lTimeHour << ":" << lTimeMinute;
00392 oTime =
00393 boost::posix_time::duration_from_string (lTimeStr.str());
00394
00395 return true;
00396 }
00397
00398
00399
00400
00401 const stdair::BookingRequestStruct parseTravelSolutionAndBookingRequestKey
00402 (const TokenList_T& iTokenList,
00403 stdair::TravelSolutionList_T& ioInteractiveTravelSolutionList,
00404 const stdair::BookingRequestStruct& ioBookingRequestStruct) {
00405
00406 TokenList_T::const_iterator itTok = iTokenList.begin();
00407
00408 if (itTok->empty() == true) {
00409
00410 std::cerr << "Wrong list of parameters. "
00411 << "The default booking request and travel solution list are kept."
00412 << std::endl;
00413 return ioBookingRequestStruct;
00414
00415
00416 } else {
00417
00418
00419
00420 stdair::AirlineCode_T lAirlineCode;
00421 stdair::FlightNumber_T lflightNumber;
00422 stdair::Date_T lDepartureDate;
00423 stdair::Duration_T lDepartureTime;
00424 stdair::AirportCode_T lOriginAirport;
00425 stdair::AirportCode_T lDestinationAirport;
00426 stdair::Date_T lRequestDate;
00427 stdair::Duration_T lRequestTime;
00428 stdair::CityCode_T lPOS;
00429 stdair::ChannelLabel_T lChannel;
00430 stdair::TripType_T lTripType;
00431 unsigned short lStayDuration;
00432
00433
00434 lAirlineCode = *itTok;
00435 boost::algorithm::to_upper (lAirlineCode);
00436
00437
00438 ++itTok;
00439 if (itTok->empty() == false) {
00440 try {
00441
00442 lflightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
00443
00444 } catch (boost::bad_lexical_cast& eCast) {
00445 std::cerr << "The flight number ('" << *itTok
00446 << "') cannot be understood."
00447 << std::endl;
00448 return ioBookingRequestStruct;
00449 }
00450 }
00451
00452
00453 ++itTok;
00454 if (itTok->empty() == true) {
00455 return ioBookingRequestStruct;
00456 }
00457 const std::string lDepartureYearString = *itTok;
00458 ++itTok;
00459 if (itTok->empty() == true) {
00460 return ioBookingRequestStruct;
00461 }
00462 const std::string lDepartureMonthString = *itTok;
00463 ++itTok;
00464 if (itTok->empty() == true) {
00465 return ioBookingRequestStruct;
00466 }
00467 const std::string lDepartureDayString = *itTok;
00468 const bool IsDepartureDateReadable =
00469 retrieveDate (lDepartureYearString, lDepartureMonthString,
00470 lDepartureDayString, lDepartureDate);
00471
00472 if (IsDepartureDateReadable == false) {
00473 std::cerr << "The default booking request and travel solution list are kept."
00474 << std::endl;
00475 return ioBookingRequestStruct;
00476 }
00477
00478
00479 ++itTok;
00480 if (itTok->empty() == false) {
00481 lOriginAirport = *itTok;
00482 boost::algorithm::to_upper (lOriginAirport);
00483 }
00484
00485
00486 ++itTok;
00487 if (itTok->empty() == false) {
00488 lDestinationAirport = *itTok;
00489 boost::algorithm::to_upper (lDestinationAirport);
00490 }
00491
00492
00493 ++itTok;
00494 if (itTok->empty() == true) {
00495 return ioBookingRequestStruct;
00496 }
00497 const std::string lDepartureHourString = *itTok;
00498 ++itTok;
00499 if (itTok->empty() == true) {
00500 return ioBookingRequestStruct;
00501 }
00502 const std::string lDepartureMinuteString = *itTok;
00503 const bool IsDepartureTimeReadable =
00504 retrieveTime (lDepartureHourString, lDepartureMinuteString,
00505 lDepartureTime);
00506
00507 if (IsDepartureTimeReadable == false) {
00508 std::cerr << "The default booking request and travel solution list are kept."
00509 << std::endl;
00510 return ioBookingRequestStruct;
00511 }
00512
00513
00514 ++itTok;
00515 if (itTok->empty() == true) {
00516 return ioBookingRequestStruct;
00517 }
00518 const std::string lRequestYearString = *itTok;
00519 ++itTok;
00520 if (itTok->empty() == true) {
00521 return ioBookingRequestStruct;
00522 }
00523 const std::string lRequestMonthString = *itTok;
00524 ++itTok;
00525 if (itTok->empty() == true) {
00526 return ioBookingRequestStruct;
00527 }
00528 const std::string lRequestDayString = *itTok;
00529 const bool IsRequestDateReadable =
00530 retrieveDate (lRequestYearString, lRequestMonthString,
00531 lRequestDayString, lRequestDate);
00532
00533 if (IsRequestDateReadable == false) {
00534 std::cerr << "The default booking request and travel solution list are kept."
00535 << std::endl;
00536 return ioBookingRequestStruct;
00537 }
00538
00539
00540 ++itTok;
00541 if (itTok->empty() == true) {
00542 return ioBookingRequestStruct;
00543 }
00544 const std::string lRequestHourString = *itTok;
00545 ++itTok;
00546 if (itTok->empty() == true) {
00547 return ioBookingRequestStruct;
00548 }
00549 const std::string lRequestMinuteString = *itTok;
00550 const bool IsRequestTimeReadable =
00551 retrieveTime (lRequestHourString, lRequestMinuteString,
00552 lRequestTime);
00553
00554 if (IsRequestTimeReadable == false) {
00555 std::cerr << "The default booking request and travel solution list are kept."
00556 << std::endl;
00557 return ioBookingRequestStruct;
00558 }
00559
00560
00561 ++itTok;
00562 if (itTok->empty() == false) {
00563 lPOS = *itTok;
00564 boost::algorithm::to_upper (lPOS);
00565 }
00566
00567
00568 ++itTok;
00569 if (itTok->empty() == false) {
00570 lChannel = *itTok;
00571 boost::algorithm::to_upper (lChannel);
00572 }
00573
00574
00575 ++itTok;
00576 if (itTok->empty() == false) {
00577 lTripType = *itTok;
00578 boost::algorithm::to_upper (lTripType);
00579 }
00580
00581
00582 ++itTok;
00583 if (itTok->empty() == false) {
00584 try {
00585
00586 lStayDuration = boost::lexical_cast<unsigned short> (*itTok);
00587
00588 } catch (boost::bad_lexical_cast& eCast) {
00589 std::cerr << "The stay duration ('" << *itTok
00590 << "') cannot be understood." << std::endl;
00591 return ioBookingRequestStruct;
00592 }
00593 }
00594
00595
00596
00597
00598
00599 ioInteractiveTravelSolutionList.pop_front();
00600
00601 stdair::TravelSolutionStruct lTravelSolution;
00602 std::ostringstream oStr;
00603 oStr << lAirlineCode
00604 << stdair::DEFAULT_KEY_FLD_DELIMITER
00605 << lflightNumber
00606 << stdair::DEFAULT_KEY_SUB_FLD_DELIMITER
00607 << lDepartureDate
00608 << stdair::DEFAULT_KEY_FLD_DELIMITER
00609 << lOriginAirport
00610 << stdair::DEFAULT_KEY_SUB_FLD_DELIMITER
00611 << lDestinationAirport
00612 << stdair::DEFAULT_KEY_FLD_DELIMITER
00613 << lDepartureTime;
00614 lTravelSolution.addSegment (oStr.str());
00615 ioInteractiveTravelSolutionList.push_front(lTravelSolution);
00616
00617
00618 stdair::DateTime_T lRequestDateTime (lRequestDate, lRequestTime);
00619 const stdair::BookingRequestStruct &lBookingRequestStruct =
00620 stdair::BookingRequestStruct(lOriginAirport,
00621 lDestinationAirport,
00622 lPOS,
00623 lDepartureDate,
00624 lRequestDateTime,
00625 stdair::CABIN_ECO,
00626 stdair::DEFAULT_PARTY_SIZE,
00627 lChannel,
00628 lTripType,
00629 lStayDuration,
00630 stdair::FREQUENT_FLYER_MEMBER,
00631 lDepartureTime,
00632 stdair::DEFAULT_WTP,
00633 stdair::DEFAULT_VALUE_OF_TIME);
00634
00635 return lBookingRequestStruct;
00636 }
00637 }
00638
00639
00640
00641
00642 void parseFlightDateKey (const TokenList_T& iTokenList,
00643 stdair::AirportCode_T& ioOrigin,
00644 stdair::AirportCode_T& ioDestination,
00645 stdair::Date_T& ioDepartureDate) {
00646
00647 TokenList_T::const_iterator itTok = iTokenList.begin();
00648
00649
00650 if (itTok->empty() == true) {
00651
00652 std::cerr << "Wrong parameters specified. Default paramaters '"
00653 << ioOrigin << "-" << ioDestination
00654 << "/" << ioDepartureDate
00655 << "' are kept."
00656 << std::endl;
00657
00658 } else {
00659
00660
00661 ioOrigin = *itTok;
00662 boost::algorithm::to_upper (ioOrigin);
00663
00664
00665 ++itTok;
00666 if (itTok->empty() == false) {
00667 ioDestination = *itTok;
00668 boost::algorithm::to_upper (ioDestination);
00669 }
00670
00671
00672 ++itTok;
00673 if (itTok->empty() == true) {
00674 return;
00675 }
00676 std::string lYearString = *itTok;
00677 ++itTok;
00678 if (itTok->empty() == true) {
00679 return;
00680 }
00681 std::string lMonthString = *itTok;
00682 ++itTok;
00683 if (itTok->empty() == true) {
00684 return;
00685 }
00686 std::string lDayString = *itTok;
00687 const bool IsDepartureDateReadable =
00688 retrieveDate (lYearString, lMonthString, lDayString,
00689 ioDepartureDate);
00690 if (IsDepartureDateReadable == false) {
00691 std::cerr << "Default paramaters '"
00692 << ioOrigin << "-" << ioDestination
00693 << "/" << ioDepartureDate
00694 << "' are kept."
00695 << std::endl;
00696 return;
00697 }
00698 }
00699 }
00700
00701
00702 std::string toString (const TokenList_T& iTokenList) {
00703 std::ostringstream oStr;
00704
00705
00706 unsigned short idx = 0;
00707 for (TokenList_T::const_iterator itTok = iTokenList.begin();
00708 itTok != iTokenList.end(); ++itTok, ++idx) {
00709 if (idx != 0) {
00710 oStr << " ";
00711 }
00712 oStr << *itTok;
00713 }
00714
00715 return oStr.str();
00716 }
00717
00718
00719 TokenList_T extractTokenList (const TokenList_T& iTokenList,
00720 const std::string& iRegularExpression) {
00721 TokenList_T oTokenList;
00722
00723
00724
00725 const std::string lFullLine = toString (iTokenList);
00726
00727
00728 boost::regex expression (iRegularExpression);
00729
00730 std::string::const_iterator start = lFullLine.begin();
00731 std::string::const_iterator end = lFullLine.end();
00732
00733 boost::match_results<std::string::const_iterator> what;
00734 boost::match_flag_type flags = boost::match_default | boost::format_sed;
00735 regex_search (start, end, what, expression, flags);
00736
00737
00738
00739 const unsigned short lMatchSetSize = what.size();
00740 for (unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
00741 const std::string lMatchedString (std::string (what[matchIdx].first,
00742 what[matchIdx].second));
00743
00744 oTokenList.push_back (lMatchedString);
00745
00746 }
00747
00748
00749
00750
00751 return oTokenList;
00752 }
00753
00754
00755
00756 TokenList_T extractTokenListForTSAndBR (const TokenList_T& iTokenList) {
00778 const std::string lRegEx("^([[:alpha:]]{2,3})"
00779 "[[:space:]]+([[:digit:]]{1,4})"
00780 "[/ ]*"
00781 "[[:space:]]+([[:digit:]]{2,4})[/-]?"
00782 "[[:space:]]*([[:alpha:]]{3}|[[:digit:]]{1,2})[/-]?"
00783 "[[:space:]]*([[:digit:]]{1,2})[[:space:]]*"
00784 "[[:space:]]+([[:alpha:]]{3})"
00785 "[[:space:]]+([[:alpha:]]{3})"
00786 "[[:space:]]+([[:digit:]]{1,2})[:]?([[:digit:]]{1,2})"
00787 "[[:space:]]+([[:digit:]]{2,4})[/-]?"
00788 "[[:space:]]*([[:alpha:]]{3}|[[:digit:]]{1,2})[/-]?"
00789 "[[:space:]]*([[:digit:]]{1,2})"
00790 "[[:space:]]+([[:digit:]]{1,2})[:]?([[:digit:]]{1,2})"
00791 "[[:space:]]+([[:alpha:]]{3})"
00792 "[[:space:]]+([[:alpha:]]{2})"
00793 "[[:space:]]+([[:alpha:]]{2})"
00794 "[[:space:]]+([[:digit:]]{1})$");
00795
00796
00797 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00798 return oTokenList;
00799 }
00800
00801
00802
00803 TokenList_T extractTokenListForOriDestDate (const TokenList_T& iTokenList) {
00813 const std::string lRegEx("^([[:alpha:]]{3})"
00814 "[[:space:]]*[/-]?"
00815 "[[:space:]]*([[:alpha:]]{3})"
00816 "[[:space:]]*[/-]?"
00817 "[[:space:]]*([[:digit:]]{2,4})"
00818 "[[:space:]]*[/-]?"
00819 "[[:space:]]*([[:alpha:]]{3}|[[:digit:]]{1,2})"
00820 "[[:space:]]*[/-]?"
00821 "[[:space:]]*([[:digit:]]{1,2})$");
00822
00823
00824 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00825 return oTokenList;
00826 }
00827
00828
00829 int main (int argc, char* argv[]) {
00830
00831
00832
00833 bool isBuiltin;
00834
00835
00836 stdair::Filename_T lFareInputFilename;
00837
00838
00839 const unsigned int lHistorySize (100);
00840 const std::string lHistoryFilename ("simfqt.hist");
00841 const std::string lHistoryBackupFilename ("simfqt.hist.bak");
00842
00843
00844 stdair::AirportCode_T lInteractiveOrigin;
00845 stdair::AirportCode_T lInteractiveDestination;
00846 stdair::Date_T lInteractiveDepartureDate;
00847
00848
00849 stdair::Filename_T lLogFilename;
00850
00851
00852 const int lOptionParserStatus =
00853 readConfiguration (argc, argv, isBuiltin, lFareInputFilename, lLogFilename);
00854
00855 if (lOptionParserStatus == K_SIMFQT_EARLY_RETURN_STATUS) {
00856 return 0;
00857 }
00858
00859
00860 std::ofstream logOutputFile;
00861
00862 logOutputFile.open (lLogFilename.c_str());
00863 logOutputFile.clear();
00864
00865
00866 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00867 SIMFQT::SIMFQT_Service simfqtService (lLogParams);
00868
00869
00870 STDAIR_LOG_DEBUG ("Welcome to SimFQT display");
00871
00872
00873 if (isBuiltin == true) {
00874
00875 simfqtService.buildSampleBom();
00876 } else {
00877
00878 SIMFQT::FareFilePath lFareFilePath (lFareInputFilename);
00879 simfqtService.parseAndLoad (lFareFilePath);
00880 }
00881
00882
00883 const std::string& lCSVDump = simfqtService.csvDisplay();
00884 STDAIR_LOG_DEBUG (lCSVDump);
00885
00886
00887 STDAIR_LOG_DEBUG ("====================================================");
00888 STDAIR_LOG_DEBUG ("= Beginning of the interactive session =");
00889 STDAIR_LOG_DEBUG ("====================================================");
00890
00891
00892 swift::SReadline lReader (lHistoryFilename, lHistorySize);
00893 initReadline (lReader);
00894
00895
00896 std::string lUserInput;
00897 bool EndOfInput (false);
00898 Command_T::Type_T lCommandType (Command_T::NOP);
00899
00900 while (lCommandType != Command_T::QUIT && EndOfInput == false) {
00901
00902 stdair::TravelSolutionList_T lInteractiveTravelSolutionList;
00903 stdair::TravelSolutionStruct lInteractiveTravelSolution;
00904
00905
00906
00907
00908 const bool isCRSBookingRequest = !isBuiltin;
00909 const stdair::BookingRequestStruct& lInteractiveBookingRequest =
00910 simfqtService.buildBookingRequest (isCRSBookingRequest);
00911
00912
00913 if (isBuiltin == true) {
00914 lInteractiveOrigin = "LHR";
00915 lInteractiveDestination = "SYD";
00916 lInteractiveDepartureDate = stdair::Date_T(2011,06,10);
00917 simfqtService.buildSampleTravelSolutions (lInteractiveTravelSolutionList);
00918 } else {
00919 lInteractiveOrigin = "SIN";
00920 lInteractiveDestination = "BKK";
00921 lInteractiveDepartureDate = stdair::Date_T(2010,01,30);
00922
00923 const std::string lBA9_SegmentDateKey ("SQ, 970, 2010-01-30, SIN, BKK, 07:10");
00924
00925
00926 lInteractiveTravelSolution.addSegment (lBA9_SegmentDateKey);
00927
00928
00929 lInteractiveTravelSolutionList.push_back (lInteractiveTravelSolution);
00930 }
00931
00932
00933 std::ostringstream oPromptStr;
00934 oPromptStr << "simfqt "
00935 << "> ";
00936
00937 TokenList_T lTokenListByReadline;
00938 lUserInput = lReader.GetLine (oPromptStr.str(), lTokenListByReadline,
00939 EndOfInput);
00940
00941
00942 lReader.SaveHistory (lHistoryBackupFilename);
00943
00944 if (EndOfInput) {
00945 std::cout << std::endl;
00946 break;
00947 }
00948
00949
00950 lCommandType = extractCommand (lTokenListByReadline);
00951
00952 switch (lCommandType) {
00953
00954
00955 case Command_T::HELP: {
00956
00957
00958 stdair::TravelSolutionStruct& lTravelSolutionStruct =
00959 lInteractiveTravelSolutionList.front();
00960
00961 const stdair::SegmentPath_T& lSegmentPath =
00962 lTravelSolutionStruct.getSegmentPath();
00963
00964 const std::string& lSegmentDateKey = lSegmentPath.front();
00965
00966 const stdair::ParsedKey& lParsedKey =
00967 stdair::BomKeyManager::extractKeys (lSegmentDateKey);
00968
00969 const stdair::DateTime_T& lRequestDateTime =
00970 lInteractiveBookingRequest.getRequestDateTime();
00971 const stdair::Time_T lRequestTime =
00972 lRequestDateTime.time_of_day();
00973 std::cout << std::endl;
00974
00975 std::cout << "Commands: " << std::endl;
00976 std::cout << " help" << "\t\t" << "Display this help" << std::endl;
00977 std::cout << " quit" << "\t\t" << "Quit the application" << std::endl;
00978 std::cout << " list" << "\t\t"
00979 << "List all the fare rule O&Ds and the corresponding date ranges" << std::endl;
00980 std::cout << " display" << "\t"
00981 << "Display all fare rules for an O&D and a departure date. \n" << "\t\t"
00982 << "If no parameters specified or wrong list of parameters, default values are used: \n"<< "\t\t"
00983 << " display " << lInteractiveOrigin << " "
00984 << lInteractiveDestination << " "
00985 << lInteractiveDepartureDate << std::endl;
00986 std::cout << " price" << "\t\t"
00987 << "Price the travel solution corresponding to a booking request. \n" << "\t\t"
00988 << "If no parameters specified or wrong list of parameters, default value are used: \n" << "\t\t"
00989 << " price "
00990 << lParsedKey._airlineCode << " "
00991 << lParsedKey._flightNumber << " "
00992 << lParsedKey._departureDate << " "
00993 << lParsedKey._boardingPoint << " "
00994 << lParsedKey._offPoint << " "
00995 << lParsedKey._boardingTime << " "
00996 << lRequestDateTime.date() << " "
00997 << lRequestTime.hours() << ":" << lRequestTime.minutes() << " "
00998 << lInteractiveBookingRequest.getPOS() << " "
00999 << lInteractiveBookingRequest.getBookingChannel() << " "
01000 << lInteractiveBookingRequest.getTripType() << " "
01001 << lInteractiveBookingRequest.getStayDuration() << std::endl;
01002 std::cout << std::endl;
01003 break;
01004 }
01005
01006
01007 case Command_T::QUIT: {
01008 break;
01009 }
01010
01011
01012 case Command_T::LIST: {
01013
01014
01015
01016 const std::string& lAirportPairDateListStr =
01017 simfqtService.list ();
01018
01019 if (lAirportPairDateListStr.empty() == false) {
01020 std::cout << lAirportPairDateListStr << std::endl;
01021 STDAIR_LOG_DEBUG (lAirportPairDateListStr);
01022
01023 } else {
01024 std::cerr << "There is no result for airport pairs and date ranges."
01025 << "Make sure your input file is not empty."
01026 << std::endl;
01027 }
01028
01029 break;
01030 }
01031
01032
01033 case Command_T::DISPLAY: {
01034
01035
01036 if (lTokenListByReadline.empty() == true) {
01037
01038 std::cout << "No parameters specified. Default paramaters '"
01039 << lInteractiveOrigin << "-" << lInteractiveDestination
01040 << "/" << lInteractiveDepartureDate
01041 << "' are kept."
01042 << std::endl;
01043
01044 } else {
01045
01046
01047 TokenList_T lTokenList =
01048 extractTokenListForOriDestDate (lTokenListByReadline);
01049
01050
01051
01052
01053 parseFlightDateKey (lTokenList, lInteractiveOrigin,
01054 lInteractiveDestination, lInteractiveDepartureDate);
01055
01056 }
01057
01058
01059
01060 const bool isAirportPairDateValid =
01061 simfqtService.check (lInteractiveOrigin, lInteractiveDestination,
01062 lInteractiveDepartureDate);
01063
01064 if (isAirportPairDateValid == false) {
01065 std::ostringstream oFDKStr;
01066 oFDKStr << "The airport pair/departure date: "
01067 << lInteractiveOrigin << "-" << lInteractiveDestination
01068 << "/" << lInteractiveDepartureDate
01069 << " does not correpond to any fare rule.\n"
01070 << "Make sure it exists with the 'list' command.";
01071 std::cout << oFDKStr.str() << std::endl;
01072 STDAIR_LOG_ERROR (oFDKStr.str());
01073
01074 break;
01075 }
01076
01077
01078 std::cout << "List of fare rules for "
01079 << lInteractiveOrigin << "-"
01080 << lInteractiveDestination << "/"
01081 << lInteractiveDepartureDate
01082 << std::endl;
01083
01084 const std::string& lFareRuleListStr =
01085 simfqtService.csvDisplay (lInteractiveOrigin,
01086 lInteractiveDestination,
01087 lInteractiveDepartureDate);
01088
01089 assert (lFareRuleListStr.empty() == false);
01090 std::cout << lFareRuleListStr << std::endl;
01091 STDAIR_LOG_DEBUG (lFareRuleListStr);
01092
01093 break;
01094 }
01095
01096
01097 case Command_T::PRICE: {
01098
01099
01100 if (lTokenListByReadline.empty() == true) {
01101
01102 lInteractiveTravelSolution = lInteractiveTravelSolutionList.front();
01103
01104 std::cout << "No parameters specified. Default booking request and default travel solution list are kept.\n"
01105 << "Booking request: << "
01106 << lInteractiveBookingRequest.display() << " >>"
01107 << "\nTravel Solution: << "
01108 << lInteractiveTravelSolution.display() << " >>"
01109 << "\n********** \n"
01110 << "Fare quote"
01111 << "\n**********"
01112 << std::endl;
01113
01114
01115 try {
01116 simfqtService.quotePrices (lInteractiveBookingRequest,
01117 lInteractiveTravelSolutionList);
01118 } catch (stdair::ObjectNotFoundException& E) {
01119 std::cerr << "The given travel solution corresponding to the given booking request can not be priced.\n"
01120 << E.what()
01121 << std::endl;
01122 break;
01123 }
01124 } else {
01125
01126
01127 TokenList_T lTokenList =
01128 extractTokenListForTSAndBR (lTokenListByReadline);
01129
01130
01131
01132
01133 stdair::BookingRequestStruct lFinalBookingRequest
01134 = parseTravelSolutionAndBookingRequestKey (lTokenList,
01135 lInteractiveTravelSolutionList,
01136 lInteractiveBookingRequest);
01137
01138
01139 assert (lInteractiveTravelSolutionList.size() >= 1);
01140 lInteractiveTravelSolution = lInteractiveTravelSolutionList.front();
01141
01142
01143
01144 std::cout << "Booking request: << "
01145 << lFinalBookingRequest.display() << " >>"
01146 << "\nTravel Solution: << "
01147 << lInteractiveTravelSolution.display() << " >>"
01148 << "\n********** \n"
01149 << "Fare quote"
01150 << "\n**********"
01151 << std::endl;
01152
01153
01154 try {
01155 simfqtService.quotePrices (lFinalBookingRequest,
01156 lInteractiveTravelSolutionList);
01157 } catch (stdair::ObjectNotFoundException& E) {
01158 std::cerr << "The given travel solution corresponding to the given booking request can not be priced.\n"
01159 << E.what()
01160 << std::endl;
01161 break;
01162 }
01163 }
01164
01165
01166
01167 lInteractiveTravelSolution = lInteractiveTravelSolutionList.front();
01168 std::cout << "Travel Solution: << "
01169 << lInteractiveTravelSolution.display() << " >>\n"
01170 << std::endl;
01171
01172 break;
01173 }
01174
01175
01176 case Command_T::NOP: {
01177 break;
01178 }
01179 case Command_T::LAST_VALUE:
01180 default: {
01181
01182 std::ostringstream oStr;
01183 oStr << "The '" << lUserInput << "' command is not yet understood.\n"
01184 << "Type help to have more information." << std::endl;
01185
01186 STDAIR_LOG_DEBUG (oStr.str());
01187 std::cout << oStr.str() << std::endl;
01188 }
01189 }
01190 }
01191
01192
01193 STDAIR_LOG_DEBUG ("End of the session. Exiting.");
01194 std::cout << "End of the session. Exiting." << std::endl;
01195
01196
01197 logOutputFile.close();
01198
01199
01200
01201
01202
01203
01204
01205
01206 return 0;
01207 }