diff options
Diffstat (limited to 'main.cpp')
-rw-r--r-- | main.cpp | 117 |
1 files changed, 88 insertions, 29 deletions
@@ -23,13 +23,13 @@ #include "error.h" #include "multilog.h" #include "referee.h" -#include "params.h" using namespace std; -// TODO no globals -static MultiLog gMultiLog; +const char *const matchcachedir = "comp_cache"; +const char *const playerlogdir = "comp_playerlogs"; +const char *const gamelogdir = "comp_gamelogs"; static char hexchar(int n) { @@ -158,7 +158,10 @@ MatchResult MatchResult::inverted() const { } struct Params { + bool referee_verbose = false; string refereePath; + int num_matches = 5; + size_t timeout_msec = 10000; }; static string gameCodeName(const Player &p1, const Player &p2, int index) { @@ -226,19 +229,18 @@ static void recordResult(Player &p1, Player &p2, const MatchResult &result) { p2.results.push_back(result.inverted()); } -static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { - int logId = gMultiLog.add(p1.fname + " - " + p2.fname + ": "); +static void playMatch(MultiLog &multiLog, Player &p1, Player &p2, int index, const Params ¶ms) { + int logId = multiLog.add(p1.fname + " - " + p2.fname + ": "); if (optional<MatchResult> optres = readMatchCache(p1, p2, index)) { - gMultiLog.append(logId, optres->describe(p1, p2) + " (cached)"); - gMultiLog.complete(logId); + multiLog.append(logId, optres->describe(p1, p2) + " (cached)"); + multiLog.complete(logId); recordResult(p1, p2, *optres); return; } MatchResult mres; - string gamelog_path = gameLogPath(p1, p2, index); ofstream gamelog(gamelog_path); if (!gamelog) { @@ -246,7 +248,7 @@ static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { throw StopCompetitionError(); } - Referee referee(params.refereePath, {p1.fname, p2.fname}); + Referee referee(params.referee_verbose, params.refereePath, {p1.fname, p2.fname}); gamelog << "Player 1: " << p1.fname << "\n" << "Player 2: " << p2.fname << "\n\n" << flush; @@ -279,7 +281,7 @@ static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { readEvent->callback(*oline); - if (mres.ms1 / 1000 > timeout_msec || mres.ms2 / 1000 > timeout_msec) { + if (mres.ms1 / 1000 > params.timeout_msec || mres.ms2 / 1000 > params.timeout_msec) { mres.status = MatchResult::Status::timeout; mres.sc1 = mres.sc2 = 0; referee.terminate(); @@ -326,8 +328,8 @@ static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { } } - gMultiLog.append(logId, mres.describe(p1, p2)); - gMultiLog.complete(logId); + multiLog.append(logId, mres.describe(p1, p2)); + multiLog.complete(logId); gamelog << "\nResult: " << mres.describe(p1, p2) << "\n" << "P1 took " << mres.ms1 / 1000000.0 << " seconds\n" @@ -337,35 +339,92 @@ static void playMatch(Player &p1, Player &p2, int index, const Params ¶ms) { recordResult(p1, p2, mres); } -static void playerPit(Scheduler &scheduler, Player &p1, Player &p2, const Params ¶ms) { - for (int i = 0; i < num_matches; i++) { - scheduler.submit([&p1, &p2, i, params]() { playMatch(p1, p2, i + 1, params); }); +static void playerPit(Scheduler &scheduler, MultiLog &multiLog, Player &p1, Player &p2, const Params ¶ms) { + for (int i = 0; i < params.num_matches; i++) { + scheduler.submit([i, &p1, &p2, ¶ms, &multiLog]() { + playMatch(multiLog, p1, p2, i + 1, params); + }); } } -static void fullCompetition(Scheduler &scheduler, vector<Player> &players, const Params ¶ms) { +static void fullCompetition(Scheduler &scheduler, MultiLog &multiLog, vector<Player> &players, const Params ¶ms) { for (size_t p1i = 0; p1i < players.size(); p1i++) { for (size_t p2i = p1i + 1; p2i < players.size(); p2i++) { - playerPit(scheduler, players[p1i], players[p2i], params); - playerPit(scheduler, players[p2i], players[p1i], params); + playerPit(scheduler, multiLog, players[p1i], players[p2i], params); + playerPit(scheduler, multiLog, players[p2i], players[p1i], params); } } } -int main(int argc, char **argv) { - if (argc < 3) { - cerr << "Usage: " << argv[0] << " <referee> <players...>" << endl; - return 1; - } +static void usage(const char *argv0) { + cerr << "Usage: " << argv0 << " [OPTIONS] <referee> <players...>\n" + " --noansi Don't use fancy back-updating log output\n" + " --vs Verbose scheduler output (use with --noansi)\n" + " --vr Verbose referee-handling output (use with --noansi)\n" + " -j <NUM> Set number of parallel games (default ncores/2)\n" + " -n <NUM> Set number of matches per player pairing (default " + << Params{}.num_matches << ")\n" + " -T <MSEC> Set player timeout in milliseconds (default " + << Params{}.timeout_msec << ")\n"; +} +int main(int argc, char **argv) { Params params; - params.refereePath = argv[1]; - vector<Player> players; - for (int i = 2; i < argc; i++) { - players.emplace_back(argv[i]); + bool multilog_fancy = true; + bool scheduler_verbose = false; + int num_threads = std::thread::hardware_concurrency() / 2; + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + usage(argv[0]); + return 0; + } else if (strcmp(argv[i], "--noansi") == 0) { + multilog_fancy = false; + } else if (strcmp(argv[i], "--vs") == 0) { + scheduler_verbose = true; + } else if (strcmp(argv[i], "--vr") == 0) { + params.referee_verbose = true; + } else if (strcmp(argv[i], "-j") == 0 && i + 1 < argc) { + char *endp; + num_threads = strtol(argv[i+1], &endp, 10); + if (!argv[i][0] || *endp || num_threads <= 0) { + cerr << "Invalid number to -j" << endl; + return 1; + } + i++; + } else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { + char *endp; + params.num_matches = strtol(argv[i+1], &endp, 10); + if (!argv[i][0] || *endp || params.num_matches <= 0) { + cerr << "Invalid number to -n" << endl; + return 1; + } + i++; + } else if (strcmp(argv[i], "-T") == 0 && i + 1 < argc) { + char *endp; + params.timeout_msec = strtoull(argv[i+1], &endp, 10); + if (!argv[i][0] || *endp || params.timeout_msec <= 0) { + cerr << "Invalid number to -T" << endl; + return 1; + } + i++; + } else if (argv[i][0] == '-') { + cerr << "Unknown option/flag '" << argv[i] << "'" << endl; + return 1; + } else if (params.refereePath.empty()) { + params.refereePath = argv[i]; + } else { + players.emplace_back(argv[i]); + } + } + + if (players.empty()) { + usage(argv[0]); + return 1; } + MultiLog multiLog{multilog_fancy}; mkdirp(matchcachedir); mkdirp(playerlogdir); @@ -373,8 +432,8 @@ int main(int argc, char **argv) { signal(SIGPIPE, [](int){}); - Scheduler scheduler(num_threads); - fullCompetition(scheduler, players, params); + Scheduler scheduler(scheduler_verbose, num_threads); + fullCompetition(scheduler, multiLog, players, params); scheduler.finish(); vector<pair<string, int>> scores; |