From 56c45b33347c670c211f274ffe82bbc2c0d46e2b Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 8 Mar 2010 17:36:16 +0100 Subject: [PATCH] [Positioning] Add class OutputCSV OutputCSV writes Result to a CSV file. It extends OutputFileMedium. Update: - Output. - UserInterface (add option "output.csv-file"). - posexcept (add class no_output_csv_file). --- owlps-positioning/Makefile | 5 ++ owlps-positioning/src/output.cc | 18 +++++- owlps-positioning/src/output.hh | 1 + owlps-positioning/src/outputcsv.cc | 36 ++++++++++++ owlps-positioning/src/outputcsv.hh | 36 ++++++++++++ owlps-positioning/src/posexcept.cc | 6 ++ owlps-positioning/src/posexcept.hh | 7 +++ owlps-positioning/src/userinterface.cc | 6 +- owlps-positioning/tests/outputcsv_test.hh | 70 +++++++++++++++++++++++ 9 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 owlps-positioning/src/outputcsv.cc create mode 100644 owlps-positioning/src/outputcsv.hh create mode 100644 owlps-positioning/tests/outputcsv_test.hh diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index f089d42..6d3d7ea 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -57,6 +57,7 @@ OBJ_LIST = \ userinterface.o \ output.o \ outputterminal.o \ + outputcsv.o \ positioning.o \ input.o \ inputcsv.o \ @@ -148,6 +149,10 @@ input.o: \ outputterminal.o: \ $(SRC_DIR)/outputmedium.hh \ $(OBJ_DIR)/result.o +outputcsv.o: \ + $(SRC_DIR)/outputmedium.hh \ + $(OBJ_DIR)/outputfilemedium.o \ + $(OBJ_DIR)/result.o output.o: \ $(OBJ_DIR)/outputterminal.o \ $(OBJ_DIR)/configuration.o \ diff --git a/owlps-positioning/src/output.cc b/owlps-positioning/src/output.cc index c86d91e..b69a22a 100644 --- a/owlps-positioning/src/output.cc +++ b/owlps-positioning/src/output.cc @@ -1,8 +1,10 @@ #include "output.hh" -#include "outputterminal.hh" #include "configuration.hh" #include "posexcept.hh" +#include "outputterminal.hh" +#include "outputcsv.hh" + #include using namespace std ; @@ -48,6 +50,9 @@ void Output::initialise_output_media() if (*i == "Terminal") initialise_output_terminal() ; + else if (*i == "CSV") + initialise_output_csv() ; + else throw output_medium_type_unknown(*i) ; } @@ -60,6 +65,17 @@ void Output::initialise_output_terminal() } +void Output::initialise_output_csv() +{ + if (! Configuration::is_configured("output.csv-file")) + throw no_output_csv_file() ; + + output_media.push_back( + new OutputCSV( + Configuration::string_value("output.csv-file"))) ; +} + + void Output::write(const Result &result) const { for (vector::const_iterator i = output_media.begin() ; diff --git a/owlps-positioning/src/output.hh b/owlps-positioning/src/output.hh index 6f694e7..fbfa7fe 100644 --- a/owlps-positioning/src/output.hh +++ b/owlps-positioning/src/output.hh @@ -17,6 +17,7 @@ protected: //@{ void initialise_output_media(void) ; void initialise_output_terminal(void) ; + void initialise_output_csv(void) ; //@} public: diff --git a/owlps-positioning/src/outputcsv.cc b/owlps-positioning/src/outputcsv.cc new file mode 100644 index 0000000..b209c46 --- /dev/null +++ b/owlps-positioning/src/outputcsv.cc @@ -0,0 +1,36 @@ +#include "outputcsv.hh" +#include "request.hh" +#include "mobile.hh" + +#include + +using namespace std ; + + + +/* *** Operations *** */ + + +const string OutputCSV::result_to_csv(const Result &result) +{ + ostringstream csv_line ; + + const Request *const request = result.get_request() ; + if (request != NULL) + { + if (request->get_mobile() != NULL) + csv_line << request->get_mobile()->get_mac_addr() ; + csv_line << ';' << request->get_time_sent() ; + } + else + csv_line << ';' ; + + Point3D position = result.get_position() ; + csv_line + << ';' << position.get_x() + << ';' << position.get_y() + << ';' << position.get_z() ; + + csv_line << '\n' ; + return csv_line.str() ; +} diff --git a/owlps-positioning/src/outputcsv.hh b/owlps-positioning/src/outputcsv.hh new file mode 100644 index 0000000..e06a26d --- /dev/null +++ b/owlps-positioning/src/outputcsv.hh @@ -0,0 +1,36 @@ +#ifndef _OWLPS_POSITIONING_OUTPUTCSV_HH_ +#define _OWLPS_POSITIONING_OUTPUTCSV_HH_ + +#include "outputmedium.hh" +#include "outputfilemedium.hh" + +/// Writes a result to a CSV file +/** + * CSV format is: + * Mobile_MAC;Timestamp;X;Y;Z + */ +class OutputCSV: public OutputMedium, public OutputFileMedium +{ +protected: + const std::string result_to_csv(const Result &result) ; + +public: + OutputCSV(const std::string &filename): + OutputFileMedium(filename) {} + + void write(const Result &result) ; +} ; + + + +/* *** Operations *** */ + + +inline void OutputCSV::write(const Result &result) +{ + write_string_to_file(result_to_csv(result)) ; +} + + + +#endif // _OWLPS_POSITIONING_OUTPUTCSV_HH_ diff --git a/owlps-positioning/src/posexcept.cc b/owlps-positioning/src/posexcept.cc index cf0afcc..0cbf61a 100644 --- a/owlps-positioning/src/posexcept.cc +++ b/owlps-positioning/src/posexcept.cc @@ -113,6 +113,12 @@ const char* output_medium_type_unknown::what() const throw() } +const char* no_output_csv_file::what() const throw() +{ + return "No input CSV file specified in the configuration!" ; +} + + /* *** Algorithms *** */ diff --git a/owlps-positioning/src/posexcept.hh b/owlps-positioning/src/posexcept.hh index 9b3c879..d67f1cc 100644 --- a/owlps-positioning/src/posexcept.hh +++ b/owlps-positioning/src/posexcept.hh @@ -109,6 +109,13 @@ public: } ; +class no_output_csv_file: public posexcept +{ +public: + const char* what() const throw() ; +} ; + + /* *** Algorithms *** */ diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index e187d4f..a0c59f7 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -110,8 +110,10 @@ this option more than once (but at least once). Allowed: Real.") // Output options ("output.medium,O", po::value< vector >()->composing(), "Medium to which the results will be wrote. You can specify \ -this option more than once. Allowed: Terminal. If this option is \ -absent, results will be printed on the terminal.") +this option more than once. Allowed: Terminal, CSV. \ +If this option is absent, results will be printed on the terminal.") + ("output.csv-file", po::value(), + "CSV file to use for output (when output.medium = CSV).") ; // End of options } diff --git a/owlps-positioning/tests/outputcsv_test.hh b/owlps-positioning/tests/outputcsv_test.hh new file mode 100644 index 0000000..c44fa95 --- /dev/null +++ b/owlps-positioning/tests/outputcsv_test.hh @@ -0,0 +1,70 @@ +#include + +#include "outputcsv.hh" + +class OutputCSV_test: public CxxTest::TestSuite +{ +private: + std::string csv_file_name ; + +public: + + OutputCSV_test(void) + { + Stock::clear() ; + csv_file_name = "/tmp/OutputCSV_test_csv_file.csv" ; + } + + + ~OutputCSV_test(void) + { + TestUtil::remove_file(csv_file_name) ; + Stock::clear() ; + } + + + static OutputCSV_test* createSuite(void) + { + return new OutputCSV_test() ; + } + + + static void destroySuite(OutputCSV_test *suite) + { + delete suite ; + } + + + void test_outputcsv(void) + { + OutputCSV *outputcsv1 = new OutputCSV(csv_file_name) ; + for (std::vector::const_iterator i = + TestUtil::results.begin() ; + i != TestUtil::results.end() ; ++i) + outputcsv1->write(*i) ; + delete outputcsv1 ; + + unsigned int result_count = 0 ; + std::ifstream inputcsv(csv_file_name.c_str()) ; + while (inputcsv) + { + std::string line ; + getline(inputcsv, line) ; + + const Result &result = TestUtil::results.at(result_count) ; + std::ostringstream result_csv ; + result_csv + << result.get_request()->get_mobile()->get_mac_addr() << ';' + << result.get_request()->get_time_sent() << ';' + << result.get_position().get_x() << ';' + << result.get_position().get_y() << ';' + << result.get_position().get_z() ; + + TS_ASSERT_EQUALS(line, result_csv.str()) ; + + if (++result_count >= TestUtil::results.size()) + break ; + } + } + +} ;