diff --git a/src/main.cpp b/src/main.cpp index 8abf701..34385ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,27 +10,73 @@ #include #include #include +#include +#include #include +#include +#include "robinsonizer_mode.hpp" +#include "engine.hpp" void print_help() { std::cout << "usage: autogram [-h|--version]\n"; - std::cout << " -h, --help show this help text and exit\n"; - std::cout << " --version show version number and exit\n"; + std::cout << " -a, --autogram autogram type, default relaxed\n"; + std::cout << " -h, --help show this help text and exit\n"; + std::cout << " -i, --maxiiter maximum iterations before restart, default 10\n"; + std::cout << " -l, --lang language, default en\n"; + std::cout << " -s, --start start of sentence\n"; + std::cout << " -v, --verbose increase verbosity\n"; + std::cout << " --version show version number and exit\n"; } void print_version() { std::cout << "autogram version 1.0\n"; } +void read_nums_from_db(std::vector& numerals, const std::string& db_path, int lang_id) { + sqlite3* db {nullptr}; + int rc = sqlite3_open(db_path.c_str(), &db); + if (rc) { + sqlite3_close(db); + throw std::runtime_error("can't open database"); + } + std::unique_ptr dbh {db, sqlite3_close}; + const char* query = "SELECT num FROM numerals WHERE language_id = ? ORDER BY value"; + sqlite3_stmt* stmt {nullptr}; + sqlite3_prepare_v2(db, query, -1, &stmt, nullptr); + std::unique_ptr stmth {stmt, sqlite3_finalize}; + sqlite3_bind_int(stmt, 1, lang_id); + while (true) { + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + const unsigned char* data = sqlite3_column_text(stmt, 0); + std::string num {reinterpret_cast(data)}; + numerals.push_back(num); + } else { + break; + } + } +} + int main(int argc, const char * argv[]) { try { + robinsonizer_mode mode {robinsonizer_mode::lax_autogram}; + std::string lang {"en"}; + std::string start; + int maxiter {0}; + std::string db_path {"numerals.db"}; + unsigned int verbose {0}; int opt_char, opt_val; struct option long_options[] = { + {"autogram", required_argument, nullptr, 'a'}, {"help", no_argument, nullptr, 'h'}, + {"max-iter", required_argument, nullptr, 'i'}, + {"lang", required_argument, nullptr, 'l'}, + {"start", required_argument, nullptr, 's'}, + {"verbose", required_argument, nullptr, 'v'}, {"version", no_argument, &opt_val, 1}, {nullptr, 0, nullptr, 0} }; - while ((opt_char = getopt_long(argc, const_cast(argv), "h", long_options, nullptr)) != -1) { + while ((opt_char = getopt_long(argc, const_cast(argv), "a:hi:l:s:v", long_options, nullptr)) != -1) { std::string arg {optarg ? optarg : ""}; switch (opt_char) { case 0: { @@ -42,9 +88,32 @@ int main(int argc, const char * argv[]) { } break; } + case 'a': + if (arg == "relaxed") { + mode = robinsonizer_mode::lax_autogram; + } else if (arg == "strict") { + mode = robinsonizer_mode::strict_autogram; + } else if (arg == "pangram") { + mode = robinsonizer_mode::pangram; + } else { + throw std::invalid_argument("invalid autogram type"); + } + break; case 'h': print_help(); return EXIT_SUCCESS; + case 'i': + maxiter = atoi(optarg); + break; + case 'l': + lang = arg; + break; + case 's': + start = arg; + break; + case 'v': + verbose++; + break; case '?': throw std::runtime_error("unrecognized option"); } @@ -55,11 +124,22 @@ int main(int argc, const char * argv[]) { for (int i = optind; i < argc; ++i) { try { // process file argv[i] + db_path = argv[i]; + break; // ignore other args } catch (const std::runtime_error& ex) { std::cerr << "autogram: " << ex.what() << '\n'; } } - std::cout << "hello, autogram\n"; + + std::vector numerals; + numerals.push_back(lang == "nl" ? "en" : "and"); + read_nums_from_db(numerals, db_path, (lang == "nl" ? 1 : 2)); + if (start.size() == 0) start = "This sentence contains"; + if (maxiter == 0) maxiter = 10; + engine robinsonizer {start, std::move(numerals), maxiter, mode, verbose}; + robinsonizer.run(); + std::cout << robinsonizer << '\n'; + } catch (const std::exception& ex) { std::cerr << "autogram: " << ex.what() << '\n'; return EXIT_FAILURE;