mi024

College project "Projet IAD" master 1
git clone https://esimon.eu/repos/mi024.git
Log | Files | Refs | README

view_ctl.cpp (8761B)


      1 /**
      2  * @file
      3  * @brief Interface to the View database.
      4  */
      5 
      6 #include <cstddef>
      7 #include <iostream>
      8 #include <sstream>
      9 #include <stdexcept>
     10 #include <string>
     11 #include <vector>
     12 
     13 #include <boost/archive/binary_oarchive.hpp>
     14 #include <boost/make_shared.hpp>
     15 #include <boost/program_options.hpp>
     16 #include <boost/shared_ptr.hpp>
     17 #include <sqlite3.h>
     18 
     19 #include "factory.hpp"
     20 #include "nmlp_iostream_exports.hpp"
     21 #include "sqlite_utils.hpp"
     22 #include "view.hpp"
     23 
     24 static char const * const usage = "usage:\n"
     25                                   "\tview_ctl --help\n"
     26                                   "\tview_ctl add --interactive -d database\n"
     27                                   "\tview_ctl add name configfile -d database\n"
     28                                   "\tview_ctl del name -d database\n"
     29                                   "\tview_ctl list -d database\n";
     30 
     31 /** @brief Construct a View interactively. */
     32 boost::shared_ptr<View> interactive_build_view();
     33 
     34 /** @brief Construct a View from a configuration file. */
     35 boost::shared_ptr<View> detached_build_view(std::string const &name, std::string const &config_path);
     36 
     37 /** @brief Insert a View into a given database. */
     38 void add_view(std::string const &database_path, boost::shared_ptr<View> view);
     39 
     40 /** @brief Delete a View from a given database. */
     41 void del_view(std::string const &database_path, std::string const &name);
     42 
     43 /** @brief List the View of a given database. */
     44 void list_view(std::string const &database_path);
     45 
     46 int main(int argc, char **argv){
     47 	namespace po = boost::program_options;
     48 	std::string database_path;
     49 
     50 	po::options_description desc("Allowed options");
     51 	desc.add_options()
     52 		("command,a", po::value<std::string>(), "Select the operation to execute")
     53 		("configfile,c", po::value<std::string>(), "Configuration file containing a view description")
     54 		("database,d", po::value<std::string>(&database_path), "Select the target view database")
     55 		("help,h", "Print a summary of the options")
     56 		("interactive,i", "Start in interactive mode")
     57 		("name,n", po::value<std::string>(), "Name of the view to add/delete")
     58 		;
     59 
     60 	po::positional_options_description p;
     61 	p.add("command", 1).add("name", 1).add("configfile", 1);
     62 
     63 	po::variables_map vm;
     64 	po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm);
     65 	po::notify(vm);
     66 
     67 	if(vm.count("help")){
     68 		std::cout << usage << "\n" << desc << "\n";
     69 		return 0;
     70 	}
     71 
     72 	if(!vm.count("database")){
     73 		std::cout << usage;
     74 		return 1;
     75 	}
     76 
     77 	if(vm["command"].as<std::string>()=="add"){
     78 		if(vm.count("interactive"))
     79 			add_view(database_path, interactive_build_view());
     80 		else {
     81 			if(!vm.count("name") || !vm.count("configfile")){
     82 				std::cout << usage;
     83 				return 1;
     84 			}
     85 			add_view(database_path, detached_build_view(vm["name"].as<std::string>(), vm["configfile"].as<std::string>()));
     86 		}
     87 	} else if(vm["command"].as<std::string>()=="del"){
     88 		if(!vm.count("name")){
     89 			std::cout << usage;
     90 			return 1;
     91 		}
     92 		del_view(database_path, vm["name"].as<std::string>());
     93 	} else if(vm["command"].as<std::string>()=="list"){
     94 		list_view(database_path);
     95 	}
     96 }
     97 
     98 boost::shared_ptr<View> interactive_build_view(){
     99 	boost::shared_ptr<View> view=boost::make_shared<View>();
    100 
    101 	std::string name;
    102 	std::cout << "Name? ";
    103 	std::getline(std::cin, name);
    104 	view->name=name;
    105 
    106 	std::string kind;
    107 	std::cout << "Kind? ";
    108 	std::getline(std::cin, kind);
    109 	view->kind=kind;
    110 
    111 	std::cout << "Description? ";
    112 	std::string description;
    113 	std::getline(std::cin, description);
    114 	view->description=description;
    115 
    116 	std::cout << "View space dimension? ";
    117 	std::size_t view_dimension;
    118 	std::cin >> view_dimension;
    119 	view->view_dimension=view_dimension;
    120 
    121 	std::cout << "Concept space dimension? ";
    122 	std::size_t concept_dimension;
    123 	std::cin >> concept_dimension;
    124 	view->concept_dimension=concept_dimension;
    125 
    126 	std::cout << "########################\n";
    127 	std::cout << "### Encoder creation ###\n";
    128 	std::cout << "########################\n";
    129 	view->encoder=interactive_module_factory(std::cin, std::cout, view_dimension, concept_dimension);
    130 
    131 	std::cout << "########################\n";
    132 	std::cout << "### Decoder creation ###\n";
    133 	std::cout << "########################\n";
    134 	view->decoder=interactive_module_factory(std::cin, std::cout, concept_dimension, view_dimension);
    135 
    136 	return view;
    137 }
    138 
    139 boost::shared_ptr<View> detached_build_view(std::string const &name, std::string const &config_path){
    140 	namespace po = boost::program_options;
    141 
    142 	po::options_description desc("Config file options");
    143 	desc.add_options()
    144 		("kind", po::value<std::string>(), "Set the kind of view to be created")
    145 		("description", po::value<std::string>(), "Set the description of the view")
    146 		("view_dimension", po::value<std::size_t>(), "Set the dimension of the viewed space")
    147 		("concept_dimension", po::value<std::size_t>(), "Set the dimension of the concept space")
    148 		("encoder.module", po::value<std::vector<std::string> >(), "Add a module to the encoder")
    149 		("encoder.size", po::value<std::vector<std::size_t> >(), "Set the output size of the last encoder Linear module")
    150 		("encoder.variance", po::value<std::vector<float> >(), "Set the variance of the last encoder Linear module")
    151 		("decoder.module", po::value<std::vector<std::string> >(), "Add a module to the decoder")
    152 		("decoder.size", po::value<std::vector<std::size_t> >(), "Set the output size of the last decoder Linear module")
    153 		("decoder.variance", po::value<std::vector<float> >(), "Set the variance of the last decoder Linear module")
    154 		;
    155 
    156 	po::variables_map vm;
    157 	po::store(po::parse_config_file<char>(config_path.c_str(), desc, false), vm);
    158 	po::notify(vm);
    159 
    160 	boost::shared_ptr<View> view=boost::make_shared<View>();
    161 
    162 	if(!vm.count("kind"))
    163 		throw std::runtime_error("Missing 'kind' option in configuration file");
    164 	if(!vm.count("description"))
    165 		throw std::runtime_error("Missing 'description' option in configuration file");
    166 	if(!vm.count("view_dimension"))
    167 		throw std::runtime_error("Missing 'view_dimension' option in configuration file");
    168 	if(!vm.count("concept_dimension"))
    169 		throw std::runtime_error("Missing 'concept_dimension' option in configuration file");
    170 
    171 	view->name=name;
    172 	view->kind=vm["kind"].as<std::string>();
    173 	view->description=vm["description"].as<std::string>();
    174 	view->view_dimension=vm["view_dimension"].as<std::size_t>();
    175 	view->concept_dimension=vm["concept_dimension"].as<std::size_t>();
    176 
    177 	view->encoder=detached_module_factory(vm, "encoder.", view->view_dimension, view->concept_dimension);
    178 	view->decoder=detached_module_factory(vm, "decoder.", view->concept_dimension, view->view_dimension);
    179 
    180 	return view;
    181 }
    182 
    183 void add_view(std::string const &database_path, boost::shared_ptr<View> view){
    184 	/// @todo Can it be optimised?
    185 	std::stringstream buf;
    186 	boost::archive::binary_oarchive oa(buf);
    187 	oa << view;
    188 	std::string bufstr=buf.str();
    189 
    190 	DB_connection connection(database_path);
    191 	sqlite3_stmt *stmt;
    192 
    193 	std::stringstream ss;
    194 	ss << "INSERT INTO views VALUES ("
    195 		<< "'" << view->name << "',"
    196 		<< "'" << view->kind << "',"
    197 		<< "'" << view->description << "',"
    198 		<< "?)";
    199 	std::string sql=ss.str();
    200 
    201 	int err=sqlite3_prepare_v2(connection.handle, sql.c_str(), sql.size()+1, &stmt, 0);
    202 	DB_statement statement(stmt);
    203 	if(err!=SQLITE_OK)
    204 		throw std::runtime_error(sqlite3_errmsg(connection.handle));
    205 
    206 	if(sqlite3_bind_blob(stmt, 1, bufstr.c_str(), bufstr.size(), SQLITE_STATIC)!=SQLITE_OK)
    207 		throw std::runtime_error(sqlite3_errmsg(connection.handle));
    208 
    209 	if(sqlite3_step(stmt)!=SQLITE_DONE)
    210 		throw std::runtime_error(sqlite3_errmsg(connection.handle));
    211 }
    212 
    213 void del_view(std::string const &database_path, const std::string &name){
    214 	DB_connection connection(database_path);
    215 	sqlite3_stmt *stmt;
    216 
    217 	std::stringstream ss;
    218 	ss << "DELETE FROM views WHERE name='" << name << "'";
    219 	std::string sql=ss.str();
    220 
    221 	int err=sqlite3_prepare_v2(connection.handle, sql.c_str(), sql.size()+1, &stmt, 0);
    222 	DB_statement statement(stmt);
    223 	if(err!=SQLITE_OK)
    224 		throw std::runtime_error(sqlite3_errmsg(connection.handle));
    225 
    226 	if(sqlite3_step(stmt)!=SQLITE_DONE)
    227 		throw std::runtime_error(sqlite3_errmsg(connection.handle));
    228 }
    229 
    230 void list_view(std::string const &database_path){
    231 	DB_connection connection(database_path);
    232 	sqlite3_stmt *stmt;
    233 
    234 	std::stringstream ss;
    235 	ss << "SELECT name, kind, description FROM views";
    236 	std::string sql=ss.str();
    237 
    238 	int err=sqlite3_prepare_v2(connection.handle, sql.c_str(), sql.size()+1, &stmt, 0);
    239 	DB_statement statement(stmt);
    240 	if(err!=SQLITE_OK)
    241 		throw std::runtime_error(sqlite3_errmsg(connection.handle));
    242 
    243 	while((err=sqlite3_step(stmt))!=SQLITE_DONE){
    244 		if(err!=SQLITE_ROW)
    245 			throw std::runtime_error(sqlite3_errmsg(connection.handle));
    246 		std::cout << sqlite3_column_text(stmt, 0) << " (" << sqlite3_column_text(stmt, 1) << ")\n"
    247 		          << "\t" << sqlite3_column_text(stmt, 2) << "\n\n";
    248 	}
    249 }
    250