AirInv Logo  1.00.0
C++ Simulated Airline Inventory Management System library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
airinv_parseInventory.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 // StdAir
15 #include <stdair/basic/BasLogParams.hpp>
16 #include <stdair/basic/BasDBParams.hpp>
17 #include <stdair/service/Logger.hpp>
18 // AirInv
20 #include <airinv/config/airinv-paths.hpp>
21 
22 // //////// Constants //////
26 const std::string K_AIRINV_DEFAULT_LOG_FILENAME ("airinv_parseInventory.log");
27 
31 const std::string K_AIRINV_DEFAULT_INVENTORY_FILENAME (STDAIR_SAMPLE_DIR
32  "/invdump01.csv");
36 const std::string K_AIRINV_DEFAULT_SCHEDULE_FILENAME (STDAIR_SAMPLE_DIR
37  "/schedule01.csv");
41 const std::string K_AIRINV_DEFAULT_OND_FILENAME (STDAIR_SAMPLE_DIR
42  "/ond01.csv");
46 const std::string K_AIRINV_DEFAULT_FRAT5_INPUT_FILENAME (STDAIR_SAMPLE_DIR
47  "/frat5.csv");
51 const std::string K_AIRINV_DEFAULT_FF_DISUTILITY_INPUT_FILENAME (STDAIR_SAMPLE_DIR
52  "/ffDisutility.csv");
53 
57 const std::string K_AIRINV_DEFAULT_YIELD_FILENAME (STDAIR_SAMPLE_DIR
58  "/yieldstore01.csv");
59 
63 const std::string K_AIRINV_DEFAULT_SEGMENT_DATE_KEY ("SV,5,2010-03-11,KBP,JFK");
64 
68 const stdair::ClassCode_T K_AIRINV_DEFAULT_CLASS_CODE ("Y");
69 
73 const stdair::PartySize_T K_AIRINV_DEFAULT_PARTY_SIZE (2);
74 
79 const bool K_AIRINV_DEFAULT_BUILT_IN_INPUT = false;
80 
85 const bool K_AIRINV_DEFAULT_FOR_SCHEDULE = false;
86 
90 const int K_AIRINV_EARLY_RETURN_STATUS = 99;
91 
92 // ///////// Parsing of Options & Configuration /////////
93 // A helper function to simplify the main part.
94 template<class T> std::ostream& operator<< (std::ostream& os,
95  const std::vector<T>& v) {
96  std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " "));
97  return os;
98 }
99 
103 int readConfiguration (int argc, char* argv[],
104  bool& ioIsBuiltin, bool& ioIsForSchedule,
105  stdair::Filename_T& ioInventoryFilename,
106  stdair::Filename_T& ioScheduleInputFilename,
107  stdair::Filename_T& ioODInputFilename,
108  stdair::Filename_T& ioFRAT5Filename,
109  stdair::Filename_T& ioFFDisutilityFilename,
110  stdair::Filename_T& ioYieldInputFilename,
111  std::string& ioSegmentDateKey,
112  stdair::ClassCode_T& ioClassCode,
113  stdair::PartySize_T& ioPartySize,
114  std::string& ioLogFilename) {
115  // Default for the built-in input
116  ioIsBuiltin = K_AIRINV_DEFAULT_BUILT_IN_INPUT;
117 
118  // Default for the inventory or schedule option
119  ioIsForSchedule = K_AIRINV_DEFAULT_FOR_SCHEDULE;
120 
121  // Declare a group of options that will be allowed only on command line
122  boost::program_options::options_description generic ("Generic options");
123  generic.add_options()
124  ("prefix", "print installation prefix")
125  ("version,v", "print version string")
126  ("help,h", "produce help message");
127 
128  // Declare a group of options that will be allowed both on command
129  // line and in config file
130 
131  boost::program_options::options_description config ("Configuration");
132  config.add_options()
133  ("builtin,b",
134  "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")
135  ("for_schedule,f",
136  "The BOM tree should be built from a schedule file (instead of from an inventory dump)")
137  ("inventory,i",
138  boost::program_options::value< std::string >(&ioInventoryFilename)->default_value(K_AIRINV_DEFAULT_INVENTORY_FILENAME),
139  "(CSV) input file for the inventory")
140  ("schedule,s",
141  boost::program_options::value< std::string >(&ioScheduleInputFilename)->default_value(K_AIRINV_DEFAULT_SCHEDULE_FILENAME),
142  "(CSV) input file for the schedule")
143  ("ond,o",
144  boost::program_options::value< std::string >(&ioODInputFilename)->default_value(K_AIRINV_DEFAULT_OND_FILENAME),
145  "(CSV) input file for the O&D")
146  ("frat5,F",
147  boost::program_options::value< std::string >(&ioFRAT5Filename)->default_value(K_AIRINV_DEFAULT_FRAT5_INPUT_FILENAME),
148  "(CSV) input file for the FRAT5 Curve")
149  ("ff_disutility,D",
150  boost::program_options::value< std::string >(&ioFFDisutilityFilename)->default_value(K_AIRINV_DEFAULT_FF_DISUTILITY_INPUT_FILENAME),
151  "(CSV) input file for the FF disutility Curve")
152  ("yield,y",
153  boost::program_options::value< std::string >(&ioYieldInputFilename)->default_value(K_AIRINV_DEFAULT_YIELD_FILENAME),
154  "(CSV) input file for the yield")
155  ("segment_date_key,k",
156  boost::program_options::value< std::string >(&ioSegmentDateKey)->default_value(K_AIRINV_DEFAULT_SEGMENT_DATE_KEY),
157  "Segment-date key")
158  ("class_code,c",
159  boost::program_options::value< stdair::ClassCode_T >(&ioClassCode)->default_value(K_AIRINV_DEFAULT_CLASS_CODE),
160  "Class code")
161  ("party_size,p",
162  boost::program_options::value< stdair::PartySize_T >(&ioPartySize)->default_value(K_AIRINV_DEFAULT_PARTY_SIZE),
163  "Party size")
164  ("log,l",
165  boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_AIRINV_DEFAULT_LOG_FILENAME),
166  "Filename for the logs")
167  ;
168 
169  // Hidden options, will be allowed both on command line and
170  // in config file, but will not be shown to the user.
171  boost::program_options::options_description hidden ("Hidden options");
172  hidden.add_options()
173  ("copyright",
174  boost::program_options::value< std::vector<std::string> >(),
175  "Show the copyright (license)");
176 
177  boost::program_options::options_description cmdline_options;
178  cmdline_options.add(generic).add(config).add(hidden);
179 
180  boost::program_options::options_description config_file_options;
181  config_file_options.add(config).add(hidden);
182  boost::program_options::options_description visible ("Allowed options");
183  visible.add(generic).add(config);
184 
185  boost::program_options::positional_options_description p;
186  p.add ("copyright", -1);
187 
188  boost::program_options::variables_map vm;
189  boost::program_options::
190  store (boost::program_options::command_line_parser (argc, argv).
191  options (cmdline_options).positional(p).run(), vm);
192 
193  std::ifstream ifs ("airinv.cfg");
194  boost::program_options::store (parse_config_file (ifs, config_file_options),
195  vm);
196  boost::program_options::notify (vm);
197 
198  if (vm.count ("help")) {
199  std::cout << visible << std::endl;
200  return K_AIRINV_EARLY_RETURN_STATUS;
201  }
202 
203  if (vm.count ("version")) {
204  std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
205  return K_AIRINV_EARLY_RETURN_STATUS;
206  }
207 
208  if (vm.count ("prefix")) {
209  std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
210  return K_AIRINV_EARLY_RETURN_STATUS;
211  }
212 
213  if (vm.count ("builtin")) {
214  ioIsBuiltin = true;
215  }
216  const std::string isBuiltinStr = (ioIsBuiltin == true)?"yes":"no";
217  std::cout << "The BOM should be built-in? " << isBuiltinStr << std::endl;
218 
219  if (vm.count ("for_schedule")) {
220  ioIsForSchedule = true;
221  }
222  const std::string isForScheduleStr = (ioIsForSchedule == true)?"yes":"no";
223  std::cout << "The BOM should be built from schedule? " << isForScheduleStr
224  << std::endl;
225 
226  if (ioIsBuiltin == false) {
227 
228  if (ioIsForSchedule == false) {
229  // The BOM tree should be built from parsing an inventory dump
230  if (vm.count ("inventory")) {
231  ioInventoryFilename = vm["inventory"].as< std::string >();
232  std::cout << "Input inventory filename is: " << ioInventoryFilename
233  << std::endl;
234 
235  } else {
236  // The built-in option is not selected. However, no inventory dump
237  // file is specified
238  std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
239  << " -f/--for_schedule and -s/--schedule options "
240  << "must be specified" << std::endl;
241  }
242 
243  } else {
244  // The BOM tree should be built from parsing a schedule (and O&D) file
245  if (vm.count ("schedule")) {
246  ioScheduleInputFilename = vm["schedule"].as< std::string >();
247  std::cout << "Input schedule filename is: " << ioScheduleInputFilename
248  << std::endl;
249 
250  } else {
251  // The built-in option is not selected. However, no schedule file
252  // is specified
253  std::cerr << "Either one among the -b/--builtin, -i/--inventory or "
254  << " -f/--for_schedule and -s/--schedule options "
255  << "must be specified" << std::endl;
256  }
257 
258  if (vm.count ("ond")) {
259  ioODInputFilename = vm["ond"].as< std::string >();
260  std::cout << "Input O&D filename is: " << ioODInputFilename << std::endl;
261  }
262 
263  if (vm.count ("frat5")) {
264  ioFRAT5Filename = vm["frat5"].as< std::string >();
265  std::cout << "FRAT5 input filename is: " << ioFRAT5Filename << std::endl;
266 
267  }
268 
269  if (vm.count ("ff_disutility")) {
270  ioFFDisutilityFilename = vm["ff_disutility"].as< std::string >();
271  std::cout << "FF disutility input filename is: "
272  << ioFFDisutilityFilename << std::endl;
273 
274  }
275 
276  if (vm.count ("yield")) {
277  ioYieldInputFilename = vm["yield"].as< std::string >();
278  std::cout << "Input yield filename is: "
279  << ioYieldInputFilename << std::endl;
280  }
281  }
282  }
283 
284  if (vm.count ("log")) {
285  ioLogFilename = vm["log"].as< std::string >();
286  std::cout << "Log filename is: " << ioLogFilename << std::endl;
287  }
288 
289  return 0;
290 }
291 
292 
293 // ///////// M A I N ////////////
294 int main (int argc, char* argv[]) {
295 
296  // State whether the BOM tree should be built-in or parsed from an
297  // input file
298  bool isBuiltin;
299  bool isForSchedule;
300 
301  // Input file names
302  stdair::Filename_T lInventoryFilename;
303  stdair::Filename_T lScheduleInputFilename;
304  stdair::Filename_T lODInputFilename;
305  stdair::Filename_T lFRAT5InputFilename;
306  stdair::Filename_T lFFDisutilityInputFilename;
307  stdair::Filename_T lYieldInputFilename;
308 
309  // Parameters for the sale
310  std::string lSegmentDateKey;
311  stdair::ClassCode_T lClassCode;
312  stdair::PartySize_T lPartySize;
313 
314  // Output log File
315  stdair::Filename_T lLogFilename;
316 
317  // Call the command-line option parser
318  const int lOptionParserStatus =
319  readConfiguration (argc, argv, isBuiltin, isForSchedule, lInventoryFilename,
320  lScheduleInputFilename, lODInputFilename,
321  lFRAT5InputFilename, lFFDisutilityInputFilename,
322  lYieldInputFilename, lSegmentDateKey, lClassCode,
323  lPartySize, lLogFilename);
324 
325  if (lOptionParserStatus == K_AIRINV_EARLY_RETURN_STATUS) {
326  return 0;
327  }
328 
329  // Set the log parameters
330  std::ofstream logOutputFile;
331  // Open and clean the log outputfile
332  logOutputFile.open (lLogFilename.c_str());
333  logOutputFile.clear();
334 
335  // Initialise the inventory service
336  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
337  AIRINV::AIRINV_Master_Service airinvService (lLogParams);
338 
339  // DEBUG
340  STDAIR_LOG_DEBUG ("Welcome to AirInv");
341 
342  // Check wether or not a (CSV) input file should be read
343  if (isBuiltin == true) {
344 
345  // Build the sample BOM tree for RMOL
346  airinvService.buildSampleBom();
347 
348  // Define a specific segment-date key for the sample BOM tree
349  lSegmentDateKey = "BA,9,2011-06-10,LHR,SYD";
350 
351  } else {
352  if (isForSchedule == true) {
353  // Build the BOM tree from parsing a schedule file (and O&D list)
354  stdair::ScheduleFilePath lScheduleFilePath (lScheduleInputFilename);
355  stdair::ODFilePath lODFilePath (lODInputFilename);
356  stdair::FRAT5FilePath lFRAT5FilePath (lFRAT5InputFilename);
357  stdair::FFDisutilityFilePath lFFDisutilityFilePath (lFFDisutilityInputFilename);
358  AIRRAC::YieldFilePath lYieldFilePath (lYieldInputFilename);
359  airinvService.parseAndLoad (lScheduleFilePath, lODFilePath,
360  lFRAT5FilePath, lFFDisutilityFilePath,
361  lYieldFilePath);
362 
363  if (lSegmentDateKey == K_AIRINV_DEFAULT_SEGMENT_DATE_KEY) {
364  // Define a specific segment-date key for the schedule-based inventory
365  lSegmentDateKey = "SQ,11,2010-01-15,SIN,BKK";
366  }
367 
368  } else {
369  // Build the BOM tree from parsing an inventory dump file
370  AIRINV::InventoryFilePath lInventoryFilePath (lInventoryFilename);
371  airinvService.parseAndLoad (lInventoryFilePath);
372  }
373  }
374 
375  // Make a booking
376  const bool isSellSuccessful =
377  airinvService.sell (lSegmentDateKey, lClassCode, lPartySize);
378 
379  // DEBUG
380  STDAIR_LOG_DEBUG ("Sale ('" << lSegmentDateKey << "', " << lClassCode << ": "
381  << lPartySize << ") successful? " << isSellSuccessful);
382 
383  // DEBUG: Display the whole BOM tree
384  const std::string& lCSVDump = airinvService.csvDisplay();
385  STDAIR_LOG_DEBUG (lCSVDump);
386 
387  // Close the Log outputFile
388  logOutputFile.close();
389 
390  /*
391  Note: as that program is not intended to be run on a server in
392  production, it is better not to catch the exceptions. When it
393  happens (that an exception is throwned), that way we get the
394  call stack.
395  */
396 
397  return 0;
398 }