summaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp117
1 files changed, 88 insertions, 29 deletions
diff --git a/main.cpp b/main.cpp
index 306c5cc..41ce02a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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 &params) {
- int logId = gMultiLog.add(p1.fname + " - " + p2.fname + ": ");
+static void playMatch(MultiLog &multiLog, Player &p1, Player &p2, int index, const Params &params) {
+ 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 &params) {
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 &params) {
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 &params) {
}
}
- 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 &params) {
recordResult(p1, p2, mres);
}
-static void playerPit(Scheduler &scheduler, Player &p1, Player &p2, const Params &params) {
- 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 &params) {
+ for (int i = 0; i < params.num_matches; i++) {
+ scheduler.submit([i, &p1, &p2, &params, &multiLog]() {
+ playMatch(multiLog, p1, p2, i + 1, params);
+ });
}
}
-static void fullCompetition(Scheduler &scheduler, vector<Player> &players, const Params &params) {
+static void fullCompetition(Scheduler &scheduler, MultiLog &multiLog, vector<Player> &players, const Params &params) {
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;