fix some tournament state bugs

This commit is contained in:
Martin Michelsen
2022-12-08 18:38:46 -08:00
parent 5f04cbaecb
commit bdff48c343
4 changed files with 57 additions and 21 deletions
+40 -18
View File
@@ -122,7 +122,7 @@ Tournament::Match::Match(
if (this->preceding_a->round_num != this->preceding_b->round_num) { if (this->preceding_a->round_num != this->preceding_b->round_num) {
throw logic_error("preceding matches have different round numbers"); throw logic_error("preceding matches have different round numbers");
} }
this->round_num = this->preceding_a->round_num; this->round_num = this->preceding_a->round_num + 1;
} }
Tournament::Match::Match( Tournament::Match::Match(
@@ -136,15 +136,17 @@ Tournament::Match::Match(
string Tournament::Match::str() const { string Tournament::Match::str() const {
string winner_str = this->winner_team ? this->winner_team->str() : "(none)"; string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
return "[Match winner=" + winner_str + "]"; return string_printf("[Match round=%zu winner=%s]", this->round_num, winner_str.c_str());
} }
bool Tournament::Match::resolve_if_no_players() { bool Tournament::Match::resolve_if_no_players() {
if (this->winner_team) {
return true;
}
// If both matches before this one are resolved and neither winner team has // If both matches before this one are resolved and neither winner team has
// any humans on it, skip this match entirely and just make one team advance // any humans on it, skip this match entirely and just make one team advance
// arbitrarily // arbitrarily
if (!this->winner_team && if (this->preceding_a->winner_team &&
this->preceding_a->winner_team &&
this->preceding_b->winner_team && this->preceding_b->winner_team &&
this->preceding_a->winner_team->player_serial_numbers.empty() && this->preceding_a->winner_team->player_serial_numbers.empty() &&
this->preceding_b->winner_team->player_serial_numbers.empty()) { this->preceding_b->winner_team->player_serial_numbers.empty()) {
@@ -156,7 +158,7 @@ bool Tournament::Match::resolve_if_no_players() {
} }
} }
void Tournament::Match::resolve_following_matches() { void Tournament::Match::on_winner_team_set() {
auto tournament = this->tournament.lock(); auto tournament = this->tournament.lock();
if (!tournament) { if (!tournament) {
return; return;
@@ -164,16 +166,10 @@ void Tournament::Match::resolve_following_matches() {
tournament->pending_matches.erase(this->shared_from_this()); tournament->pending_matches.erase(this->shared_from_this());
// Resolve all matches up the chain until we can't anymore (this // Resolve the following match if possible (this skips CPU-only matches). If
// automatically skips CPU-only matches) // the following match can't be resolved, mark it pending.
auto following = this->following.lock(); auto following = this->following.lock();
while (following && following->resolve_if_no_players()) { if (following && !following->resolve_if_no_players()) {
tournament->pending_matches.erase(following);
following = following->following.lock();
}
// If there's a following match that wasn't resolved, mark it pending
if (following) {
tournament->pending_matches.emplace(following); tournament->pending_matches.emplace(following);
} }
@@ -201,7 +197,7 @@ void Tournament::Match::set_winner_team(shared_ptr<Team> team) {
this->preceding_a->winner_team->is_active = false; this->preceding_a->winner_team->is_active = false;
} }
this->resolve_following_matches(); this->on_winner_team_set();
} }
shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team( shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team(
@@ -373,7 +369,7 @@ void Tournament::start() {
// Resolve all possible CPU-only matches // Resolve all possible CPU-only matches
for (auto m : this->zero_round_matches) { for (auto m : this->zero_round_matches) {
m->resolve_following_matches(); m->on_winner_team_set();
} }
} }
@@ -384,7 +380,7 @@ void Tournament::print_bracket(FILE* stream) const {
fputc(' ', stream); fputc(' ', stream);
} }
string match_str = m->str(); string match_str = m->str();
fprintf(stream, "%s\n", match_str.c_str()); fprintf(stream, "%s%s\n", match_str.c_str(), this->pending_matches.count(m) ? " (PENDING)" : "");
if (m->preceding_a) { if (m->preceding_a) {
print_match(m->preceding_a, indent_level + 1); print_match(m->preceding_a, indent_level + 1);
} }
@@ -392,7 +388,33 @@ void Tournament::print_bracket(FILE* stream) const {
print_match(m->preceding_b, indent_level + 1); print_match(m->preceding_b, indent_level + 1);
} }
}; };
print_match(this->final_match, 0); fprintf(stream, "Tournament %02hhX: %s\n", this->number, this->name.c_str());
string map_name = this->map->map.name;
fprintf(stream, " Map: %08" PRIX32 " (%s)\n", this->map->map.map_number.load(), map_name.c_str());
string rules_str = this->rules.str();
fprintf(stream, " Rules: %s\n", rules_str.c_str());
fprintf(stream, " Structure: %s, %zu entries\n", this->is_2v2 ? "2v2" : "1v1", this->num_teams);
switch (this->current_state) {
case State::REGISTRATION:
fprintf(stream, " State: REGISTRATION\n");
break;
case State::IN_PROGRESS:
fprintf(stream, " State: IN_PROGRESS\n");
break;
case State::COMPLETE:
fprintf(stream, " State: COMPLETE\n");
break;
default:
fprintf(stream, " State: UNKNOWN\n");
break;
}
fprintf(stream, " Standings:\n");
print_match(this->final_match, 2);
fprintf(stream, " Pending matches:\n");
for (const auto& match : this->pending_matches) {
string match_str = match->str();
fprintf(stream, " %s\n", match_str.c_str());
}
} }
+1 -2
View File
@@ -76,7 +76,7 @@ public:
std::string str() const; std::string str() const;
bool resolve_if_no_players(); bool resolve_if_no_players();
void resolve_following_matches(); void on_winner_team_set();
void set_winner_team(std::shared_ptr<Team> team); void set_winner_team(std::shared_ptr<Team> team);
std::shared_ptr<Team> opponent_team_for_team(std::shared_ptr<Team> team) const; std::shared_ptr<Team> opponent_team_for_team(std::shared_ptr<Team> team) const;
}; };
@@ -108,7 +108,6 @@ public:
void start(); void start();
void print_bracket(FILE* stream) const; void print_bracket(FILE* stream) const;
void print_bracket_stderr() const;
private: private:
PrefixedLogger log; PrefixedLogger log;
+5 -1
View File
@@ -1051,6 +1051,10 @@ static void on_ep3_server_data_request(shared_ptr<ServerState> s, shared_ptr<Cli
if (winner_team_id == -1) { if (winner_team_id == -1) {
throw runtime_error("match concluded, but winner team not specified"); throw runtime_error("match concluded, but winner team not specified");
} }
auto tourn = l->tournament_match->tournament.lock();
tourn->print_bracket(stderr);
if (winner_team_id == 0) { if (winner_team_id == 0) {
l->tournament_match->set_winner_team(l->tournament_match->preceding_a->winner_team); l->tournament_match->set_winner_team(l->tournament_match->preceding_a->winner_team);
} else if (winner_team_id == 1) { } else if (winner_team_id == 1) {
@@ -1060,7 +1064,7 @@ static void on_ep3_server_data_request(shared_ptr<ServerState> s, shared_ptr<Cli
} }
send_ep3_tournament_match_result(l, l->tournament_match); send_ep3_tournament_match_result(l, l->tournament_match);
auto tourn = l->tournament_match->tournament.lock(); tourn->print_bracket(stderr);
if (tourn && (tourn->get_state() == Episode3::Tournament::State::COMPLETE)) { if (tourn && (tourn->get_state() == Episode3::Tournament::State::COMPLETE)) {
s->ep3_tournament_index->delete_tournament(tourn->get_number()); s->ep3_tournament_index->delete_tournament(tourn->get_number());
} }
+11
View File
@@ -131,6 +131,8 @@ Server commands:\n\
dice-boost=ON/OFF: Enable/disable dice boost\n\ dice-boost=ON/OFF: Enable/disable dice boost\n\
start-tournament \"Tournament Name\"\n\ start-tournament \"Tournament Name\"\n\
End registration for a tournament and allow matches to begin.\n\ End registration for a tournament and allow matches to begin.\n\
tournament-state \"Tournament Name\"\n\
Print the current state of a tournament.\n\
\n\ \n\
Proxy commands (these will only work when exactly one client is connected):\n\ Proxy commands (these will only work when exactly one client is connected):\n\
sc <data>\n\ sc <data>\n\
@@ -415,6 +417,15 @@ Proxy commands (these will only work when exactly one client is connected):\n\
fprintf(stderr, "no such tournament exists\n"); fprintf(stderr, "no such tournament exists\n");
} }
} else if (command_name == "tournament-status") {
string name = get_quoted_string(command_args);
auto tourn = this->state->ep3_tournament_index->get_tournament(name);
if (tourn) {
tourn->print_bracket(stderr);
} else {
fprintf(stderr, "no such tournament exists\n");
}
// PROXY COMMANDS // PROXY COMMANDS