$treeview $search $mathjax
TraDemGen Logo  1.00.2
$projectbrief
$projectbrief
$searchbox

Command-Line Test to Demonstrate How To Use TraDemGen elements

 */
// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <sstream>
#include <fstream>
#include <map>
#include <cmath>
// Boost Unit Test Framework (UTF)
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE DemandGenerationTest
#include <boost/test/unit_test.hpp>
// StdAir
#include <stdair/stdair_basic_types.hpp>
#include <stdair/basic/BasConst_General.hpp>
#include <stdair/basic/BasLogParams.hpp>
#include <stdair/basic/BasDBParams.hpp>
#include <stdair/basic/BasFileMgr.hpp>
#include <stdair/basic/ProgressStatusSet.hpp>
#include <stdair/bom/EventStruct.hpp>
#include <stdair/bom/BookingRequestStruct.hpp>
#include <stdair/service/Logger.hpp>
// TraDemGen
#include <trademgen/TRADEMGEN_Exceptions.hpp>
#include <trademgen/TRADEMGEN_Service.hpp>
#include <trademgen/bom/DemandStreamKey.hpp>
#include <trademgen/config/trademgen-paths.hpp>

namespace boost_utf = boost::unit_test;

// (Boost) Unit Test XML Report
std::ofstream utfReportStream ("DemandGenerationTestSuite_utfresults.xml");

struct UnitTestConfig {
  UnitTestConfig() {
    boost_utf::unit_test_log.set_stream (utfReportStream);
    boost_utf::unit_test_log.set_format (boost_utf::XML);
    boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
    //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
  }
  
  ~UnitTestConfig() {
  }
};

// Specific type definitions
typedef std::pair<stdair::Count_T, stdair::Count_T> NbOfEventsPair_T;
typedef std::map<const stdair::DemandStreamKeyStr_T,
                 NbOfEventsPair_T> NbOfEventsByDemandStreamMap_T;

// //////////////////////////////////////////////////////////////////////
void testDemandGenerationHelper (const unsigned short iTestFlag,
                                 const stdair::Filename_T& iDemandInputFilename,
                                 const stdair::DemandGenerationMethod& iDemandGenerationMethod,
                                 const bool isBuiltin) {

  // Seed for the random generation
  const stdair::RandomSeed_T lRandomSeed = stdair::DEFAULT_RANDOM_SEED;
  
  // Output log File
  std::ostringstream oStr;
  oStr << "DemandGenerationTestSuite_" << iTestFlag << ".log";
  const stdair::Filename_T lLogFilename (oStr.str());

  // Set the log parameters
  std::ofstream logOutputFile;
  // Open and clean the log outputfile
  logOutputFile.open (lLogFilename.c_str());
  logOutputFile.clear();

  // Initialise the TraDemGen service object
  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
  TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams, lRandomSeed);

  NbOfEventsByDemandStreamMap_T lNbOfEventsMap;
  
  // Total number of events
  stdair::Count_T lRefExpectedNbOfEvents (0);
  stdair::Count_T lRefActualNbOfEvents (0);

  // Check whether or not a (CSV) input file should be read
  if (isBuiltin == true) {

    // Build the default sample BOM tree (filled with demand streams) for TraDemGen
    trademgenService.buildSampleBom();

    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("SIN-BKK 2010-Feb-08 Y",
                                       NbOfEventsPair_T (4, 60)));
    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("BKK-HKG 2010-Feb-08 Y",
                                       NbOfEventsPair_T (4, 60)));
    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("SIN-HKG 2010-Feb-08 Y",
                                       NbOfEventsPair_T (4, 60)));

    // Total number of events, for the 3 demand streams: 180
    lRefExpectedNbOfEvents = 180;
    lRefActualNbOfEvents = 186;

  } else {

    // Create the DemandStream objects, and insert them within the BOM tree
    const TRADEMGEN::DemandFilePath lDemandFilePath (iDemandInputFilename);
    trademgenService.parseAndLoad (lDemandFilePath);

    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("SIN-HND 2010-Feb-08 Y",
                                       NbOfEventsPair_T (1, 10)));
    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("SIN-HND 2010-Feb-09 Y",
                                       NbOfEventsPair_T (1, 10)));
    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("SIN-BKK 2010-Feb-08 Y",
                                       NbOfEventsPair_T (1, 10)));
    lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
                           value_type ("SIN-BKK 2010-Feb-09 Y",
                                       NbOfEventsPair_T (1, 10)));

    // Total number of events, for the 4 demand streams: 40
    lRefExpectedNbOfEvents = 40;
    lRefActualNbOfEvents = 40;
  }
  
  // Retrieve the expected (mean value of the) number of events to be
  // generated
  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
    trademgenService.getExpectedTotalNumberOfRequestsToBeGenerated();

  BOOST_CHECK_EQUAL (lRefExpectedNbOfEvents,
                     std::floor (lExpectedNbOfEventsToBeGenerated));
  
  BOOST_CHECK_MESSAGE (lRefExpectedNbOfEvents ==
                       std::floor (lExpectedNbOfEventsToBeGenerated),
                       "Expected total number of requests to be generated: "
                       << lExpectedNbOfEventsToBeGenerated
                       << " (=> "
                       << std::floor (lExpectedNbOfEventsToBeGenerated)
                       << "). Reference value: " << lRefExpectedNbOfEvents);

  const stdair::Count_T& lActualNbOfEventsToBeGenerated =
    trademgenService.generateFirstRequests(iDemandGenerationMethod);

  // DEBUG
  STDAIR_LOG_DEBUG ("Expected number of events: "
                    << lExpectedNbOfEventsToBeGenerated << ", actual: "
                    << lActualNbOfEventsToBeGenerated);
  
  // Total number of events, for all the demand streams:
  BOOST_CHECK_EQUAL (lRefActualNbOfEvents, lActualNbOfEventsToBeGenerated);
  
  BOOST_CHECK_MESSAGE (lRefActualNbOfEvents == lActualNbOfEventsToBeGenerated,
                       "Actual total number of requests to be generated: "
                       << lExpectedNbOfEventsToBeGenerated
                       << " (=> "
                       << std::floor (lExpectedNbOfEventsToBeGenerated)
                       << "). Reference value: " << lRefActualNbOfEvents);

  const bool isQueueDone = trademgenService.isQueueDone();
  BOOST_REQUIRE_MESSAGE (isQueueDone == false,
                         "The event queue should not be empty.");

  stdair::Count_T idx = 1;
  while (trademgenService.isQueueDone() == false) {

    // Get the next event from the event queue
    stdair::EventStruct lEventStruct;
    stdair::ProgressStatusSet lPPS = trademgenService.popEvent (lEventStruct);

    // DEBUG
    STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'.");
      
    // Extract the corresponding demand/booking request
    const stdair::BookingRequestStruct& lPoppedRequest =
      lEventStruct.getBookingRequest();
    
    // DEBUG
    STDAIR_LOG_DEBUG ("Poped booking request: '"
                      << lPoppedRequest.describe() << "'.");
    
    // Retrieve the corresponding demand stream
    const stdair::DemandGeneratorKey_T& lDemandStreamKey =
      lPoppedRequest.getDemandGeneratorKey();

    // Check that the number of booking requests to be generated are correct
    const NbOfEventsByDemandStreamMap_T::iterator itNbOfEventsMap =
      lNbOfEventsMap.find (lDemandStreamKey);
    BOOST_REQUIRE_MESSAGE (itNbOfEventsMap != lNbOfEventsMap.end(),
                           "The demand stream key '" << lDemandStreamKey
                           << "' is not expected in that test");

    const NbOfEventsPair_T& lNbOfEventsPair = itNbOfEventsMap->second;
    stdair::Count_T lCurrentNbOfEvents = lNbOfEventsPair.first;
    const stdair::Count_T& lExpectedTotalNbOfEvents = lNbOfEventsPair.second;

    // Assess whether more events should be generated for that demand stream
    const bool stillHavingRequestsToBeGenerated = trademgenService.
      stillHavingRequestsToBeGenerated (lDemandStreamKey, lPPS,
                                        iDemandGenerationMethod);

    if (lCurrentNbOfEvents == 1) {
      const stdair::ProgressStatus& lDemandStreamProgressStatus =
        lPPS.getSpecificGeneratorStatus();
      const stdair::Count_T& lNbOfRequests =
        lDemandStreamProgressStatus.getExpectedNb();

      BOOST_CHECK_EQUAL (lNbOfRequests, lExpectedTotalNbOfEvents);
      BOOST_CHECK_MESSAGE (lNbOfRequests == lExpectedTotalNbOfEvents,
                           "[" << lDemandStreamKey
                           << "] Total number of requests to be generated: "
                           << lNbOfRequests << "). Expected value: "
                           << lExpectedTotalNbOfEvents);
    }

    // DEBUG
    STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "][" << lCurrentNbOfEvents
                      << "/" << lExpectedTotalNbOfEvents
                      << "] is now processed. "
                      << "Still generate events for that demand stream? "
                      << stillHavingRequestsToBeGenerated);

    // If there are still events to be generated for that demand stream,
    // generate and add them to the event queue
    if (stillHavingRequestsToBeGenerated == true) {
      const stdair::BookingRequestPtr_T lNextRequest_ptr =
        trademgenService.generateNextRequest (lDemandStreamKey,
                                              iDemandGenerationMethod);
      assert (lNextRequest_ptr != NULL);

      const stdair::Duration_T lDuration =
        lNextRequest_ptr->getRequestDateTime()
        - lPoppedRequest.getRequestDateTime();
      BOOST_REQUIRE_GT (lDuration.total_milliseconds(), 0);
      BOOST_REQUIRE_MESSAGE (lDuration.total_milliseconds() > 0,
                             "[" << lDemandStreamKey
                             << "] The date-time of the generated event ("
                             << lNextRequest_ptr->getRequestDateTime()
                             << ") is lower than the date-time "
                             << "of the current event ("
                             << lPoppedRequest.getRequestDateTime() << ")");
      
      // DEBUG
      STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "][" << lCurrentNbOfEvents
                        << "/" << lExpectedTotalNbOfEvents
                        << "] Added request: '" << lNextRequest_ptr->describe()
                        << "'. Is queue done? "
                        << trademgenService.isQueueDone());

      // Keep, within the dedicated map, the current counters of events updated.
      ++lCurrentNbOfEvents;
      itNbOfEventsMap->second = NbOfEventsPair_T (lCurrentNbOfEvents,
                                                  lExpectedTotalNbOfEvents);
    }
    
    // Iterate
    ++idx;
  }
  // Compensate for the last iteration
  --idx;

  if (iDemandGenerationMethod == stdair::DemandGenerationMethod::STA_ORD) {
    //
    BOOST_CHECK_EQUAL (idx, lRefActualNbOfEvents);
    BOOST_CHECK_MESSAGE (idx == lRefActualNbOfEvents,
                         "The total actual number of events is "
                         << lRefActualNbOfEvents << ", but " << idx
                         << " events have been generated");
  }
  
  trademgenService.reset();

  // DEBUG
  STDAIR_LOG_DEBUG ("End of the simulation");

  // Close the log file
  logOutputFile.close();

}


// /////////////// Main: Unit Test Suite //////////////

// Set the UTF configuration (re-direct the output to a specific file)
BOOST_GLOBAL_FIXTURE (UnitTestConfig);

// Start the test suite
BOOST_AUTO_TEST_SUITE (master_test_suite)


BOOST_AUTO_TEST_CASE (trademgen_simple_simulation_test) {

  // Input file name
  const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/demand01.csv");

  // Generate the date time of the requests with the statistic order method.
  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
  
  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;
  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(0,
                                                   lInputFilename,
                                                   lDemandGenerationMethod,
                                                   isBuiltin));
  
}

BOOST_AUTO_TEST_CASE (trademgen_missing_input_file_test) {

  // Input file name
  const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv");

  // Generate the date time of the requests with the statistic order method.
  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
  
  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = false;
  BOOST_CHECK_THROW (testDemandGenerationHelper(1,
                                                lInputFilename,
                                                lDemandGenerationMethod,
                                                isBuiltin),
                     TRADEMGEN::DemandInputFileNotFoundException);
  
}

BOOST_AUTO_TEST_CASE (trademgen_default_bom_simulation_test) {
  
  // Generate the date time of the requests with the statistic order method.
  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
  
  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = true;
  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(2,
                                                   " " ,
                                                   lDemandGenerationMethod,
                                                   isBuiltin));
  
}

BOOST_AUTO_TEST_CASE (trademgen_poisson_process_test) {
  
  // Generate the date time of the requests with the poisson process.
  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::POI_PRO);
  
  // State whether the BOM tree should be built-in or parsed from an input file
  const bool isBuiltin = true;
  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(3,
                                                   " " ,
                                                   lDemandGenerationMethod,
                                                   isBuiltin));
  
}

// End the test suite
BOOST_AUTO_TEST_SUITE_END()

/*!