From 018f365812cd9d64439b31a8719272c656107384 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Sat, 4 Jan 2025 19:35:11 -0600 Subject: [PATCH] [MTGOSDK/API/Play] Tournament: Fix round, endtime calculation Re-compute the number of rounds and end-time based on the type of tournament elimination style and by the number of players in the event. --- .../src/API/Play/Tournaments/Tournament.cs | 61 ++++++++++++++++++- .../Tournaments/TournamentEliminationStyle.cs | 13 ++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 MTGOSDK/src/API/Play/Tournaments/TournamentEliminationStyle.cs diff --git a/MTGOSDK/src/API/Play/Tournaments/Tournament.cs b/MTGOSDK/src/API/Play/Tournaments/Tournament.cs index d6afdc74..ca8e30af 100644 --- a/MTGOSDK/src/API/Play/Tournaments/Tournament.cs +++ b/MTGOSDK/src/API/Play/Tournaments/Tournament.cs @@ -36,12 +36,36 @@ public sealed class Tournament(dynamic tournament) : Event /// /// The time the event is scheduled to end. /// - public DateTime EndTime => @base.ScheduledEndTime; + /// + /// This is a rough approximation of the end time, based on the current number + /// of players in the tournament. The actual end time may be earlier than this + /// time if a round finishes early. + /// + public DateTime EndTime + { + get + { + DateTime endTime = StartTime.AddMinutes( + // Minutes per round + 2 minutes between rounds. + ((2 * Unbind(@base).MatchTimeLimit) * TotalRounds) + + (2 * (TotalRounds - 1)) + + // Minutes for deckbuilding. + Try(() => Unbind(@base).MinutesForDeckbuilding) + ); + + // Round up to the nearest 10 minutes. + return endTime.AddMinutes(10 - (endTime.Minute % 10)); + } + } /// /// The number of rounds in the tournament. /// - public int TotalRounds => @base.TotalRounds; + public int TotalRounds => + EliminationStyle == TournamentEliminationStyle.Swiss + ? Math.Max(@base.TotalRounds, Math.Max(GetNumberOfRounds(TotalPlayers), + GetNumberOfRounds(MinimumPlayers))) + : @base.TotalRounds; // // ITournament wrapper properties @@ -54,6 +78,15 @@ public sealed class Tournament(dynamic tournament) : Event public TournamentState State => Cast(Unbind(@base).State); + /// + /// The kind of elimination style used in the tournament + /// (i.e. "Swiss", "SingleElimination") + /// + public TournamentEliminationStyle EliminationStyle => + Try(() => Cast( + Unbind(@base).TournamentEliminationStyle), + fallback: TournamentEliminationStyle.Swiss); + /// /// The time remaining in the current round or tournament phase. /// @@ -91,6 +124,30 @@ public sealed class Tournament(dynamic tournament) : Event .OrderByDescending(s => s.Rank) .ToList(); + // + // ITournament wrapper methods + // + + /// + /// Computes the number of rounds for a given size tournament. + /// + /// The number of players in the tournament. + /// The number of rounds required for the given number of players. + public static int GetNumberOfRounds(int players) => + players switch + { + >= 2 and <= 3 => 2, + >= 4 and <= 8 => 3, + >= 9 and <= 16 => 4, + >= 17 and <= 32 => 5, + >= 33 and <= 64 => 6, + >= 65 and <= 128 => 7, + >= 129 and <= 226 => 8, + >= 227 and <= 409 => 9, + >= 410 => 10, + _ => 1 + }; + // // ITournament wrapper events // diff --git a/MTGOSDK/src/API/Play/Tournaments/TournamentEliminationStyle.cs b/MTGOSDK/src/API/Play/Tournaments/TournamentEliminationStyle.cs new file mode 100644 index 00000000..a97121cd --- /dev/null +++ b/MTGOSDK/src/API/Play/Tournaments/TournamentEliminationStyle.cs @@ -0,0 +1,13 @@ +/** @file + Copyright (c) 2024, Cory Bennett. All rights reserved. + SPDX-License-Identifier: Apache-2.0 +**/ + +namespace MTGOSDK.API.Play.Tournaments; + +public enum TournamentEliminationStyle +{ + Invalid, + Swiss, + SingleElimination +}