Skip to content

Commit

Permalink
Refactor nit-* cli main functions with guards
Browse files Browse the repository at this point in the history
Guard from escaping exceptions,
and properly handle command-line option errors.

Issue #11
Issue #9
  • Loading branch information
rakhimov committed Jun 3, 2018
1 parent 23d11dc commit 0470bab
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 142 deletions.
31 changes: 31 additions & 0 deletions cli/guard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <exception>
#include <iostream>

#include <boost/exception/all.hpp>

#include <nit/error.h>

/// Guards a main function from exceptions.
///
/// @tparam T Function type returning integer code.
///
/// @param[in] runner The body of the main function.
///
/// @returns The return of the runner if no exceptions are encountered.
/// 1 if an exception is encountered.
template <class T>
int guard(T&& runner) noexcept {
try {
return runner();
} catch (const nit::Error& nit_err) {
std::cerr << boost::diagnostic_information(nit_err);
return 1;
} catch (const boost::exception& boost_err) {
std::cerr << "Unexpected Boost Exception:\n"
<< boost::diagnostic_information(boost_err);
return 1;
} catch (const std::exception& err) {
std::cerr << "Unexpected Exception:\n" << err.what();
return 1;
}
}
116 changes: 59 additions & 57 deletions cli/nit-colex.cc
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#include <exception>
#include <iostream>
#include <string>
#include <vector>

#include <boost/format.hpp>
#include <boost/program_options.hpp>

#include <nit/eval/card.h>
#include <nit/eval/card_set.h>
#include <nit/util/combinations.h>

#include "guard.h"

namespace po = boost::program_options;

#if 0
Expand All @@ -30,66 +32,66 @@ expandRankSet(size_t numCards)
}
#endif

int main(int argc, char** argv) {
namespace {

int runColex(int argc, char** argv) {
// set up the program options, handle the help case, and extract the values.
po::options_description desc(
"nit-colex, a utility which prints all combinations "
"of poker hands, using canonical suits, or only ranks");

// clang-format off
desc.add_options()
("help,?", "produce help message")
("num-cards,n", po::value<std::size_t>()->default_value(2),
"number of cards in hands")
("ranks", "print the set of rank values");
// clang-format on

po::variables_map vm;
try {
// set up the program options, handle the help case, and extract the
// values
po::options_description desc(
"nit-colex, a utility which prints all combinations "
"of poker hands, using canonical suits, or only ranks");

// clang-format off
desc.add_options()
("help,?", "produce help message")
("num-cards,n", po::value<std::size_t>()->default_value(2),
"number of cards in hands")
("ranks", "print the set of rank values");
// clang-format on

po::variables_map vm;
po::store(po::command_line_parser(argc, argv)
.style(po::command_line_style::unix_style)
.options(desc)
.run(),
vm);
po::notify(vm);

// check for help
if (vm.count("help") || argc == 1) {
std::cout << desc << std::endl;
return 1;
po::store(po::parse_command_line(argc, argv, desc), vm);
} catch (const std::exception& err) {
std::cerr << "Option error: " << err.what() << "\n\n" << desc << std::endl;
return 1;
}
po::notify(vm);

// check for help
if (vm.count("help") || argc == 1) {
std::cout << desc << std::endl;
return 1;
}

// extract the options
std::size_t num_cards = vm["num-cards"].as<std::size_t>();

std::set<nit::CardSet> canonicalHands;
std::map<std::string, std::size_t> rankHands;
nit::combinations cards(52, num_cards);
do {
nit::CardSet hand;
for (std::size_t i = 0; i < num_cards; i++) {
hand.insert(nit::Card(cards[i]));
}
canonicalHands.insert(hand.canonize());
rankHands[hand.rankstr()] = hand.rankColex();
} while (cards.next());

// extract the options
std::size_t num_cards = vm["num-cards"].as<std::size_t>();

std::set<nit::CardSet> canonicalHands;
std::map<std::string, std::size_t> rankHands;
nit::combinations cards(52, num_cards);
do {
nit::CardSet hand;
for (std::size_t i = 0; i < num_cards; i++) {
hand.insert(nit::Card(cards[i]));
}
canonicalHands.insert(hand.canonize());
rankHands[hand.rankstr()] = hand.rankColex();
} while (cards.next());

if (vm.count("ranks") > 0) {
for (auto& rankHand : rankHands)
std::cout << boost::format("%s: %d\n") % rankHand.first %
rankHand.second;
} else {
for (const auto& canonicalHand : canonicalHands)
std::cout << boost::format("%s: %d\n") % canonicalHand.str() %
canonicalHand.colex();
if (vm.count("ranks") > 0) {
for (auto& rankHand : rankHands)
std::cout << rankHand.first << ": " << rankHand.second << '\n';
} else {
for (const auto& canonicalHand : canonicalHands) {
std::cout << canonicalHand.str() << ": " << canonicalHand.colex() << '\n';
}
} catch (std::exception& e) {
std::cerr << "-- caught exception--\n" << e.what() << "\n";
return 1;
} catch (...) {
std::cerr << "Exception of unknown type!\n";
return 1;
}

return 0;
}

} // namespace

int main(int argc, char** argv) {
return guard([&argc, &argv] { return runColex(argc, argv); });
}
30 changes: 22 additions & 8 deletions cli/nit-eval.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <exception>
#include <iostream>
#include <string>
#include <vector>
Expand All @@ -6,16 +7,20 @@

#include <nit/enum/showdown_enumerator.h>

#include "guard.h"

namespace po = boost::program_options;

int main(int argc, char** argv) {
namespace {

int runEval(int argc, char** argv) {
po::options_description desc("nit-eval, a poker hand evaluator");

// clang-format off
desc.add_options()
("help,?", "produce help message")
("game,g", po::value<std::string>()->default_value("h"),
"game to use for evaluation")
"game to use for evaluation")
("board,b", po::value<std::string>(), "community cards for he/o/o8")
("hand,h", po::value<std::vector<std::string>>(), "a hand for evaluation")
("quiet,q", "produces no output");
Expand All @@ -26,12 +31,13 @@ int main(int argc, char** argv) {
p.add("hand", -1);

po::variables_map vm;
po::store(po::command_line_parser(argc, argv)
.style(po::command_line_style::unix_style)
.options(desc)
.positional(p)
.run(),
vm);
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
} catch (const std::exception& err) {
std::cerr << "Option error: " << err.what() << "\n\n"
<< desc << std::endl;
return 1;
}
po::notify(vm);

// check for help
Expand Down Expand Up @@ -81,4 +87,12 @@ int main(int argc, char** argv) {
<< results[i].str() << ")" << std::endl;
}
}

return 0;
}

} // namespace

int main(int argc, char** argv) {
return guard([&argc, &argv] { return runEval(argc, argv); });
}
Loading

0 comments on commit 0470bab

Please sign in to comment.