diff --git a/.vs/TournamentManager/DesignTimeBuild/.dtbcache.v2 b/.vs/TournamentManager/DesignTimeBuild/.dtbcache.v2 index e5076c70ac9cda529afde7927fc1dff71499ceb4..28511334a479f5b5701ef7bf215af0394f20c23a 100644 Binary files a/.vs/TournamentManager/DesignTimeBuild/.dtbcache.v2 and b/.vs/TournamentManager/DesignTimeBuild/.dtbcache.v2 differ diff --git a/.vs/TournamentManager/v16/.suo b/.vs/TournamentManager/v16/.suo index 99bee51a68bf15ba9fd68d62c8344795d85ad1c2..feedc3ab649c204e2904e9047d10fef384fe17f3 100644 Binary files a/.vs/TournamentManager/v16/.suo and b/.vs/TournamentManager/v16/.suo differ diff --git a/TournamentManager.csproj.user b/TournamentManager.csproj.user index d81df0bb4c5c1793b6b08d1da0a40db8b091eadd..31512808a5436a2c90c4cf5642da6350ab225814 100644 --- a/TournamentManager.csproj.user +++ b/TournamentManager.csproj.user @@ -4,7 +4,7 @@ <ShowAllFiles>false</ShowAllFiles> </PropertyGroup> <ItemGroup> - <Compile Update="src\CalculateControl.cs"> + <Compile Update="src\ComputeControl.cs"> <SubType>UserControl</SubType> </Compile> <Compile Update="src\ExportControl.cs"> diff --git a/obj/Debug/net5.0-windows/TournamentManager.csproj.CoreCompileInputs.cache b/obj/Debug/net5.0-windows/TournamentManager.csproj.CoreCompileInputs.cache index 14a5c34bada98649481229c8762402687adcd32d..a7639951418afae6c1a38e0b5bcda512c42a3611 100644 --- a/obj/Debug/net5.0-windows/TournamentManager.csproj.CoreCompileInputs.cache +++ b/obj/Debug/net5.0-windows/TournamentManager.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -9c56342d8d0782585dfb5a8f145b7388446bfec3 +32b0d61a8a00098f0ff2a6864f4e5e9054b43933 diff --git a/obj/Debug/net5.0-windows/TournamentManager.csproj.FileListAbsolute.txt b/obj/Debug/net5.0-windows/TournamentManager.csproj.FileListAbsolute.txt index 66ce1be8491dea720e0b44e462355d801bf3f4ac..76fe7e106299cee003f9a3382dfa816de333c951 100644 --- a/obj/Debug/net5.0-windows/TournamentManager.csproj.FileListAbsolute.txt +++ b/obj/Debug/net5.0-windows/TournamentManager.csproj.FileListAbsolute.txt @@ -52,4 +52,4 @@ C:\Users\micha\School\RiderProjects\c-sharp-semestral-project-1\obj\Debug\net5.0 C:\Users\micha\School\RiderProjects\c-sharp-semestral-project-1\obj\Debug\net5.0-windows\TournamentManager.genruntimeconfig.cache C:\Users\micha\School\RiderProjects\c-sharp-semestral-project-1\obj\Debug\net5.0-windows\TournamentManager.src.GroupControl.resources C:\Users\micha\School\RiderProjects\c-sharp-semestral-project-1\obj\Debug\net5.0-windows\TournamentManager.src.ExportControl.resources -C:\Users\micha\School\RiderProjects\c-sharp-semestral-project-1\obj\Debug\net5.0-windows\TournamentManager.src.CalculateControl.resources +C:\Users\micha\School\RiderProjects\c-sharp-semestral-project-1\obj\Debug\net5.0-windows\TournamentManager.src.ComputeControl.resources diff --git a/obj/Debug/net5.0-windows/TournamentManager.csproj.GenerateResource.cache b/obj/Debug/net5.0-windows/TournamentManager.csproj.GenerateResource.cache index 31ceece9a93e9f4390f2c97b676c835609f78207..a6324fb688133d11bccf7fc3c90aa5696ff67aed 100644 Binary files a/obj/Debug/net5.0-windows/TournamentManager.csproj.GenerateResource.cache and b/obj/Debug/net5.0-windows/TournamentManager.csproj.GenerateResource.cache differ diff --git a/obj/Debug/net5.0-windows/TournamentManager.csprojAssemblyReference.cache b/obj/Debug/net5.0-windows/TournamentManager.csprojAssemblyReference.cache index 8ec9cabf84c61390d17139e208b06a1c2e561174..fad52e5112686b1fe17ecd9e1f07ec50c3268c70 100644 Binary files a/obj/Debug/net5.0-windows/TournamentManager.csprojAssemblyReference.cache and b/obj/Debug/net5.0-windows/TournamentManager.csprojAssemblyReference.cache differ diff --git a/obj/Debug/net5.0-windows/TournamentManager.dll b/obj/Debug/net5.0-windows/TournamentManager.dll index 513211d477b05fd7d7935f6e68d867d5c9833c9d..f913267a235359355f923b45a0a82f2e98e4e8ff 100644 Binary files a/obj/Debug/net5.0-windows/TournamentManager.dll and b/obj/Debug/net5.0-windows/TournamentManager.dll differ diff --git a/obj/Debug/net5.0-windows/TournamentManager.pdb b/obj/Debug/net5.0-windows/TournamentManager.pdb index 3718a08aacd85fc4ec5c661428cd3a0b94b7fabc..e2a7d3eca6a21eb8e550166d0c0691d88aa0df9f 100644 Binary files a/obj/Debug/net5.0-windows/TournamentManager.pdb and b/obj/Debug/net5.0-windows/TournamentManager.pdb differ diff --git a/obj/Debug/net5.0-windows/TournamentManager.src.CalculateControl.resources b/obj/Debug/net5.0-windows/TournamentManager.src.ComputeControl.resources similarity index 100% rename from obj/Debug/net5.0-windows/TournamentManager.src.CalculateControl.resources rename to obj/Debug/net5.0-windows/TournamentManager.src.ComputeControl.resources diff --git a/obj/Debug/net5.0-windows/ref/TournamentManager.dll b/obj/Debug/net5.0-windows/ref/TournamentManager.dll index 9d23fe7715471eaeaa998cc797350f152a8eb0f7..0d05c167696644b2e9e1280cc0d81f971ea45da8 100644 Binary files a/obj/Debug/net5.0-windows/ref/TournamentManager.dll and b/obj/Debug/net5.0-windows/ref/TournamentManager.dll differ diff --git a/obj/rider.project.restore.info b/obj/rider.project.restore.info index d820c47ca79fafdeda233a59374f8ad43d39bde2..1e682781d2c191141cabdfcdc47360e0544842b4 100644 --- a/obj/rider.project.restore.info +++ b/obj/rider.project.restore.info @@ -1 +1 @@ -16225768046431808 \ No newline at end of file +16226427414345850 \ No newline at end of file diff --git a/src/CalculateGroupsEventArgs.cs b/src/CalculateGroupsEventArgs.cs deleted file mode 100644 index 2a16a293eab1b1aa700962f5e7bc2f106b95a649..0000000000000000000000000000000000000000 --- a/src/CalculateGroupsEventArgs.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace TournamentManager -{ - public class CalculateGroupsEventArgs - { - public int GroupSize { get; } - - public CalculateGroupsEventArgs(int groupSize) - { - GroupSize = groupSize; - } - } -} \ No newline at end of file diff --git a/src/CalculateControl.Designer.cs b/src/ComputeControl.Designer.cs similarity index 98% rename from src/CalculateControl.Designer.cs rename to src/ComputeControl.Designer.cs index e7c195fb299b9dfe9761f509346d68c185e8d447..dac0386ae478ad069a25fd1a18429b7cf1ba6a33 100644 --- a/src/CalculateControl.Designer.cs +++ b/src/ComputeControl.Designer.cs @@ -1,7 +1,7 @@  namespace TournamentManager.src { - partial class CalculateControl + partial class ComputeControl { /// <summary> /// Required designer variable. @@ -107,7 +107,7 @@ namespace TournamentManager.src this.Controls.Add(this.cbGroupSize); this.Controls.Add(this.label1); this.Controls.Add(this.btnGroups); - this.Name = "CalculateControl"; + this.Name = "ComputeControl"; this.Size = new System.Drawing.Size(490, 92); this.ResumeLayout(false); this.PerformLayout(); diff --git a/src/CalculateControl.cs b/src/ComputeControl.cs similarity index 55% rename from src/CalculateControl.cs rename to src/ComputeControl.cs index f8f1bd7f9a19a2e6ee9d94ebe89f712a40fdaf4f..e0d384932e0cd64e52347c4126ab5a79fac515f6 100644 --- a/src/CalculateControl.cs +++ b/src/ComputeControl.cs @@ -11,14 +11,17 @@ using System.Windows.Forms; namespace TournamentManager.src { - public partial class CalculateControl : UserControl + public partial class ComputeControl : UserControl { - public event CalculateGroupsEventArgsDelegate CalculateGroups; + public event ComputeEventArgsDelegate ComputeGroups; + public event ComputeEventArgsDelegate ComputePlayOff; + + public delegate void ComputeEventArgsDelegate(object sender, ComputeEventArgs e); + protected void OnComputeGroups(ComputeEventArgs args) => ComputeGroups?.Invoke(this, args); + protected void OnComputePlayOff(ComputeEventArgs args) => ComputePlayOff?.Invoke(this, args); - public delegate void CalculateGroupsEventArgsDelegate(object sender, CalculateGroupsEventArgs e); - protected void OnCalculateGroups(CalculateGroupsEventArgs args) => CalculateGroups?.Invoke(this, args); - public CalculateControl() + public ComputeControl() { InitializeComponent(); Func<int, int, int, IEnumerable<string> > createRange = (x, y, z) => @@ -36,12 +39,17 @@ namespace TournamentManager.src //TODO: throw some message return; } - OnCalculateGroups(new CalculateGroupsEventArgs(int.Parse(cbGroupSize.SelectedItem.ToString()!))); + OnComputeGroups(new ComputeEventArgs(int.Parse(cbGroupSize.SelectedItem.ToString()!))); } private void btnPlayOff_Click(object sender, EventArgs e) { - //TODO: Calculate playoff + if (cbEliminate.SelectedItem == null) + { + //TODO: throw some message + return; + } + OnComputePlayOff(new ComputeEventArgs(int.Parse(cbEliminate.SelectedItem.ToString()!))); } } } diff --git a/src/CalculateControl.resx b/src/ComputeControl.resx similarity index 100% rename from src/CalculateControl.resx rename to src/ComputeControl.resx diff --git a/src/ComputeEventArgs.cs b/src/ComputeEventArgs.cs new file mode 100644 index 0000000000000000000000000000000000000000..0f2bab36b0146a010f328de805cbe10456e7d2cf --- /dev/null +++ b/src/ComputeEventArgs.cs @@ -0,0 +1,12 @@ +namespace TournamentManager +{ + public class ComputeEventArgs + { + public int Amount { get; } + + public ComputeEventArgs(int amount) + { + Amount = amount; + } + } +} \ No newline at end of file diff --git a/src/Group.cs b/src/Group.cs index 6bb10c6d689cbb5d8682f89c1ac51a939e33944c..55aa62de42952e821aedbfc721a1968e0260ad30 100644 --- a/src/Group.cs +++ b/src/Group.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; using System.Runtime.Serialization; namespace TournamentManager @@ -6,12 +8,43 @@ namespace TournamentManager public class Group : ISerializable { public List<Participant> Members { get; set; } - public List<Match> Matches { get; set; } + public int[,] Matches { get; set; } public Group() { Members = new List<Participant>(); - Matches = new List<Match>(); + } + + public Participant ExtractGroupMember(string name) + { + Participant? result; + if ((result = Members.FirstOrDefault(m => + name.Equals($"{m.FirstName} {m.Surname}"))) == null) + { + throw new Exception("I should define my own exception fr"); + } + + return result; + + + } + public int GetIndex(Participant opponent) + { + if (!Members.Contains(opponent)) + throw new Exception("this should not happen"); + return Members.FindIndex(x => x.Equals(opponent)); + } + + public (int firstIndex, int secondIndex) GetIndices(Participant firstOpponent, Participant secondOpponent) + { + return (firstIndex: GetIndex(firstOpponent), secondIndex: GetIndex(secondOpponent)); + } + + public (int first, int second) GetScore(Participant firstOpponent, Participant secondOpponent) + { + var indices = GetIndices(firstOpponent, secondOpponent); + return (Matches[indices.firstIndex, indices.secondIndex], + Matches[indices.secondIndex, indices.firstIndex]); } public void GetObjectData(SerializationInfo info, StreamingContext context) diff --git a/src/GroupControl.cs b/src/GroupControl.cs index 7d7a44c0af7db32e037c1c3d457b883bc6ab4d18..38a2ba9eaa71b27df00ce8f824bacd1b41ce98ba 100644 --- a/src/GroupControl.cs +++ b/src/GroupControl.cs @@ -35,6 +35,7 @@ namespace TournamentManager.src public void AddGroups(int groupCount) { + cbGroup.Items.Clear(); for (int i = 0; i < groupCount; i++) { cbGroup.Items.Add($"Group {i + 1}"); diff --git a/src/ManageTournamentForm.Designer.cs b/src/ManageTournamentForm.Designer.cs index 5fad2fd4a92f686a633c02c425e144de4c6d09bd..9871f4a901e035b26026c77e687feb4be340fa2a 100644 --- a/src/ManageTournamentForm.Designer.cs +++ b/src/ManageTournamentForm.Designer.cs @@ -38,7 +38,7 @@ namespace TournamentManager this.groupBox3 = new System.Windows.Forms.GroupBox(); this.groupControl = new TournamentManager.src.GroupControl(); this.groupBox4 = new System.Windows.Forms.GroupBox(); - this.calculateControl = new TournamentManager.src.CalculateControl(); + this.computeControl = new TournamentManager.src.ComputeControl(); this.groupBox5 = new System.Windows.Forms.GroupBox(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); @@ -100,7 +100,7 @@ namespace TournamentManager // // groupBox4 // - this.groupBox4.Controls.Add(this.calculateControl); + this.groupBox4.Controls.Add(this.computeControl); this.groupBox4.Location = new System.Drawing.Point(395, 172); this.groupBox4.Name = "groupBox4"; this.groupBox4.Size = new System.Drawing.Size(501, 138); @@ -110,10 +110,10 @@ namespace TournamentManager // // calculateControl // - this.calculateControl.Location = new System.Drawing.Point(5, 22); - this.calculateControl.Name = "calculateControl"; - this.calculateControl.Size = new System.Drawing.Size(491, 111); - this.calculateControl.TabIndex = 0; + this.computeControl.Location = new System.Drawing.Point(5, 22); + this.computeControl.Name = "computeControl"; + this.computeControl.Size = new System.Drawing.Size(491, 111); + this.computeControl.TabIndex = 0; // // groupBox5 // @@ -154,6 +154,6 @@ namespace TournamentManager private src.GroupControl groupControl; private System.Windows.Forms.GroupBox groupBox4; private System.Windows.Forms.GroupBox groupBox5; - private src.CalculateControl calculateControl; + private src.ComputeControl computeControl; } } \ No newline at end of file diff --git a/src/ManageTournamentForm.cs b/src/ManageTournamentForm.cs index a2797a4e4fe936bcd28924aeea255688de536f1a..abdbca62a85546ea008fb905eccc0eb0d0852398 100644 --- a/src/ManageTournamentForm.cs +++ b/src/ManageTournamentForm.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; using System.Windows.Forms; namespace TournamentManager @@ -13,23 +15,29 @@ namespace TournamentManager private const string EditParticipantError = "Participant with this name is already signed in competition"; private const string ErrorCaption = "Error"; private readonly ObservableCollection<Participant> _participants = new(); - private readonly ObservableCollection<Group> _groups = new(); + private List<Group> _groups; + private PlayOffTree _playOff; public ManageTournamentForm(string path) { InitializeComponent(); + enterantCntrl.SubmitParticipantClick += OnSubmitParticipantClicked; _participants.CollectionChanged += HandleParticipantsChanged; manageParticipantsControl.ParticipantsModified += HandleOnParticipantRemovedClicked; - calculateControl.CalculateGroups += HandleOnCalculateGroupsClicked; + computeControl.ComputeGroups += HandleOnComputeGroupsClicked; + computeControl.ComputePlayOff += HandleOnComputePlayOffClicked; groupControl.CbGroupItemSelected += HandleOnGroupSelected; groupControl.OpponentsSelected += HandleOnGroupOpponentsSelected; groupControl.SubmitClicked += HandleOnGroupControlSubmitClicked; + foreach (var p in _participants) { manageParticipantsControl.CbAddParticipant($"{p.FirstName} {p.Surname}"); } } + + #region eventHandlers protected void OnSubmitParticipantClicked(object sender, EventArgs e) { @@ -76,14 +84,14 @@ namespace TournamentManager } - private void HandleOnCalculateGroupsClicked(object sender, CalculateGroupsEventArgs e) + private void HandleOnComputeGroupsClicked(object sender, ComputeEventArgs e) { - var numberOfGroups = (_participants.Count - 1) / e.GroupSize + 1; + var numberOfGroups = (_participants.Count - 1) / e.Amount + 1; var groupIndex = 0; var orderedParticipants = _participants.OrderBy(x => x.Rating); groupControl.AddGroups(numberOfGroups); - + _groups = new List<Group>(); for (int i = 0; i < numberOfGroups; i++) { _groups.Add(new Group()); @@ -97,7 +105,30 @@ namespace TournamentManager groupIndex = 0; } _groups[groupIndex].Members.Add(participant); + } + foreach (var group in _groups) + { + var memberCount = group.Members.Count; + group.Matches = new int[memberCount, memberCount]; + } + } + + private async void HandleOnComputePlayOffClicked(object sender, ComputeEventArgs e) + { + try + { + var toKeep = (int)Math.Round(((double)_participants.Count / (double)100) * (double)(100 - e.Amount), 0); + var sortedParticipants = (await ComputeAllGroupOrders()).Take(toKeep).ToList(); + _playOff = new PlayOffTree(sortedParticipants); + } + catch (Exception ex) + { + // This throws the exception in a UI thread as not to get "swallowed" + + // Invoke -> runs the code on the UI thread as soon as possible, finishes executing only after + // the code invoked on the UI thread is finished + Invoke(new Action(() => throw ex)); } } @@ -122,14 +153,11 @@ namespace TournamentManager return; } - var match = _groups[e.GroupIndex].Matches.FirstOrDefault(m => - e.FirstOpponent.Equals($"{m.Opponents.Item1.FirstName} {m.Opponents.Item1.Surname}") && - e.SecondOpponent.Equals($"{m.Opponents.Item2.FirstName} {m.Opponents.Item2.Surname}")); - if (match == null ) - { - return; - } - groupControl.SetTextBoxes(match.Scores); + var group = _groups[e.GroupIndex]; + var firstOpponent = group.ExtractGroupMember(e.FirstOpponent); + var secondOpponent = group.ExtractGroupMember(e.SecondOpponent); + + groupControl.SetTextBoxes(group.GetScore(firstOpponent, secondOpponent)); } private void HandleOnGroupControlSubmitClicked(object sender, MatchSelectedEventArgs e) @@ -142,13 +170,50 @@ namespace TournamentManager var group = _groups[e.GroupIndex]; Func<string[], Participant> matchOpponent = x => group.Members .FirstOrDefault(p => p.FirstName.Equals(x[0]) && p.Surname.Equals(x[1])); - - var firstOpponentName = e.FirstOpponent.Split(" "); - var secondOpponentName = e.SecondOpponent.Split(" "); - group.Matches.Add(new Match(new Tuple<Participant, Participant> - (matchOpponent(firstOpponentName), matchOpponent(secondOpponentName)), - e.Score )); + var firstOpponent = matchOpponent(e.FirstOpponent.Split(" ")); + var secondOpponent = matchOpponent(e.SecondOpponent.Split(" ")); + group.Matches[group.GetIndex(firstOpponent), group.GetIndex(secondOpponent)] = e.Score.first; + group.Matches[group.GetIndex(secondOpponent), group.GetIndex(firstOpponent)] = e.Score.second; + } + #endregion + + #region HelperFunctions + + private Task<List<Participant>> ComputeAllGroupOrders() + { + return Task.Factory.StartNew(() => + { + return _groups.AsParallel().SelectMany(x => ComputeGroupOrder(x)) + .OrderByDescending(x => x.Item2) + .ThenByDescending(x => x.Item3) + .Select(x => x.Item1) + .ToList(); + }, TaskCreationOptions.None); + } + + private List<Tuple<Participant, int, int>> ComputeGroupOrder(Group group) + { + return group.Members.Select(m => + { + var memberCount = group.Members.Count; + var index = group.GetIndex(m); + var victories = 0; + var points = 0; + for (int i = 0; i < memberCount; i++) + { + points += group.Matches[index, i]; + if (group.Matches[index, i] > group.Matches[i, index]) + { + victories++; + } + } + + return new Tuple<Participant, int, int>(m, victories, points); + }).ToList(); + } + + #endregion } } \ No newline at end of file diff --git a/src/Match.cs b/src/Match.cs index a3858392d159555246c13a88316fa087885b1306..30fe410cda96bd78f80626ce25e8fe7054da95b6 100644 --- a/src/Match.cs +++ b/src/Match.cs @@ -1,4 +1,5 @@ using System; +using System.Security.Cryptography; namespace TournamentManager { @@ -7,6 +8,7 @@ namespace TournamentManager public Tuple<Participant, Participant> Opponents { get; set; } public (int first, int second) Scores { get; set; } + public Match() { } public Match(Tuple<Participant, Participant> opponents, (int first, int second) scores) { if (opponents.Item1.Equals(opponents.Item2)) @@ -16,8 +18,6 @@ namespace TournamentManager Opponents = opponents; Scores = scores; - - } } diff --git a/src/PlayOff.cs b/src/PlayOff.cs deleted file mode 100644 index f1cd8f088c12693b8a1d5dd6d134f9f169428a93..0000000000000000000000000000000000000000 --- a/src/PlayOff.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TournamentManager -{ - public class PlayOff - { - - } -} \ No newline at end of file diff --git a/src/PlayOffTree.cs b/src/PlayOffTree.cs new file mode 100644 index 0000000000000000000000000000000000000000..030f351cb441f0a5a41ec1e0d2cbd07bdded91ba --- /dev/null +++ b/src/PlayOffTree.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace TournamentManager +{ + public class PlayOffTree + { + public PlayOffTreeNode Root { get; } + + public PlayOffTree( List<Participant> participants) + { + Root = ComputeTree(participants); + } + + private PlayOffTreeNode ComputeTree(List<Participant> participants) + { + var depth = CalculateTreeDepth(participants.Count); + var unevenHalf = (int)Math.Pow(2, depth - 1); + var participantsUpper = participants.Take(unevenHalf).ToList(); + var participantsLower = participants.Skip(unevenHalf).ToList(); + return ComputeTreeStep(ref participantsUpper, ref participantsLower, depth); + } + + private PlayOffTreeNode ComputeTreeStep(ref List<Participant> participantsUpper, + ref List<Participant> participantsLower, int depth) + { + var match = new Match(); + var node = new PlayOffTreeNode(match); + switch (depth) + { + case 1: + { + var upper = participantsUpper.Last(); + var lower = participantsLower.FirstOrDefault(); + match.Opponents = new Tuple<Participant, Participant>(upper, lower); + participantsUpper.Remove(upper); + participantsLower.Remove(lower); + break; + } + default: + { + node.PredecessorLeft = ComputeTreeStep(ref participantsUpper, ref participantsLower, depth - 1); + node.PredecessorRight = ComputeTreeStep(ref participantsUpper, ref participantsLower, depth - 1); + break; + } + } + + return node; + } + + private int CalculateTreeDepth(int minSize) + { + var size = 1; + while (size < minSize) + { + size *= 2; + } + + return (int)Math.Log2(size); + } + + } +} \ No newline at end of file diff --git a/src/PlayOffTreeNode.cs b/src/PlayOffTreeNode.cs new file mode 100644 index 0000000000000000000000000000000000000000..ef6388f56ab336f1aa301579aadd2a4b27eb8666 --- /dev/null +++ b/src/PlayOffTreeNode.cs @@ -0,0 +1,17 @@ +using System; +using TournamentManager.src; + +namespace TournamentManager +{ + public class PlayOffTreeNode + { + public Match TreeMatch { get; set; } + public PlayOffTreeNode PredecessorLeft { get; set; } + public PlayOffTreeNode PredecessorRight { get; set; } + + public PlayOffTreeNode( Match match) + { + TreeMatch = match; + } + } +} \ No newline at end of file