using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using TrackerLibrary.Models; namespace TrackerLibrary { public static class TournamentLogic { // Order our list randomly of teams // Check if it is big enough - if not , add byes 2*2*2*2 - 2^4 // Create our first round of matchups // Create every round after that - 8 matchups - 4 matchups - 2 matchups - 1 matchup public static void CreateRounds(TournamentModel model) { List randomizedTeams = RandomizeTeamOrder(model.EnteredTeams); int rounds = FindNumberOfRounds(randomizedTeams.Count); int byes = NumberOfByes(rounds, randomizedTeams.Count); model.Rounds.Add(CreateFirstRound(byes, randomizedTeams)); CreateOtherRounds(model, rounds); //UpdateTournamentResults(model); } public static void UpdateTournamentResults(TournamentModel model) { int startingRound = model.CheckCurrentRound(); List toScore = new List(); foreach (List round in model.Rounds) { foreach (MatchupModel rm in round) { if (rm.Winner == null && (rm.Entries.Any(x => x.Score != 0) || rm.Entries.Count == 1)) { toScore.Add(rm); } } } MarkWinnersInMatchups(toScore); AdvanceWinners(toScore, model); toScore.ForEach(x => GlobalConfig.Connection.UpdateMatchup(x)); int endigRound = model.CheckCurrentRound(); if (endigRound > startingRound) { model.AlertUsersToNewRound(); } } public static void AlertUsersToNewRound(this TournamentModel model) { int currentRoundNumber = model.CheckCurrentRound(); List currentRound = model.Rounds.Where(x => x.First().MatchupRound == currentRoundNumber).First(); foreach (MatchupModel matchup in currentRound) { foreach (MatchupEntryModel me in matchup.Entries) { foreach (PersonModel p in me.TeamCompeting.TeamMembers) { AlertPersonToNewRound(p, me.TeamCompeting.TeamName, matchup.Entries.Where(x => x.TeamCompeting != me.TeamCompeting).FirstOrDefault()); } } } } private static void AlertPersonToNewRound(PersonModel p, string teamName, MatchupEntryModel competitor) { if (p.EmailAddress.Length == 0) { return; } string subject; StringBuilder body = new StringBuilder(); if (competitor != null) { subject = $"You have a new matchup with {competitor.TeamCompeting.TeamName}"; body.AppendLine("

You Have a new matchup

"); body.Append("Competitor: "); body.Append(competitor.TeamCompeting.TeamName); body.AppendLine(); body.AppendLine(); body.AppendLine("Have a great time!"); body.AppendLine("~Tournament Tracker"); } else { subject = "You have a bye week this round"; body.AppendLine("Enjoy your round off!"); body.AppendLine("~Tournament Tracker"); } string to = p.EmailAddress; EmailLogic.SendEmail(to, subject, body.ToString()); ; } private static int CheckCurrentRound(this TournamentModel model) { int output = 1; foreach (List round in model.Rounds) { if (round.All(x => x.Winner != null)) { output += 1; } else { return output; } } // Tournament is complete CpmpleteTournament(model); return output - 1; } private static void CpmpleteTournament(TournamentModel model) { GlobalConfig.Connection.CompleteTournament(model); TeamModel winners = model.Rounds.Last().First().Winner; TeamModel runnerUp = model.Rounds.Last().First().Entries.Where(x => x.TeamCompeting != winners).First().TeamCompeting; decimal winnerPrize = 0; decimal runnerUpPrize = 0; if (model.Prizes.Count > 0) { decimal totalIncome = model.EnteredTeams.Count * model.EntryFee; PrizeModel firstPlacePrize = model.Prizes.Where(x => x.PlaceNumber == 1).FirstOrDefault(); PrizeModel secondPlacePrize = model.Prizes.Where(x => x.PlaceNumber == 2).FirstOrDefault(); if (firstPlacePrize != null) { winnerPrize = firstPlacePrize.CalculatePrizePayout(totalIncome); } if (secondPlacePrize != null) { runnerUpPrize = secondPlacePrize.CalculatePrizePayout(totalIncome); } } // Send Email to all tournament List to = new List(); string subject; StringBuilder body = new StringBuilder(); subject = $"In {model.TournamentName}, {winners.TeamName} has won"; body.AppendLine("

We have a WINNER!

"); body.AppendLine("

Congratulations to our winner on a great tournament.

"); body.AppendLine("
"); if (winnerPrize > 0) { body.AppendLine($"

{winners.TeamName} will receive ${winnerPrize}

"); } if (runnerUpPrize > 0) { body.AppendLine($"

{runnerUp.TeamName} will receive ${runnerUpPrize}

"); } body.AppendLine("

Thanks for a great tournament everyone

"); body.AppendLine("~Tournament Tracker"); List bcc = new List(); foreach (TeamModel t in model.EnteredTeams) { foreach (PersonModel p in t.TeamMembers) { if (p.EmailAddress.Length > 0) { bcc.Add(p.EmailAddress); } } } EmailLogic.SendEmail(new List(), bcc, subject, body.ToString()); model.CompleteTournament(); } private static decimal CalculatePrizePayout(this PrizeModel prize, decimal totalIncome) { decimal output = 0; if (prize.PrizeAmount > 0) { output = prize.PrizeAmount; } else { output = decimal.Multiply(totalIncome, Convert.ToDecimal(prize.PrizePercentage / 100)); } return output; } private static void AdvanceWinners(List models, TournamentModel tournament) { foreach (MatchupModel m in models) { foreach (List round in tournament.Rounds) { foreach (MatchupModel rm in round) { foreach (MatchupEntryModel me in rm.Entries) { if (me.ParentMatchup != null) { if (me.ParentMatchup.Id == m.Id) { me.TeamCompeting = m.Winner; GlobalConfig.Connection.UpdateMatchup(rm); } } } } } } } private static void MarkWinnersInMatchups(List models) { // greaterWins string greaterWins = ConfigurationManager.AppSettings["greaterWins"]; foreach (MatchupModel m in models) { if (m.Entries.Count == 1) { m.Winner = m.Entries[0].TeamCompeting; continue; } // "0" means false or low scare wins if (greaterWins == "0") { if (m.Entries[0].Score < m.Entries[1].Score) { m.Winner = m.Entries[0].TeamCompeting; } else if (m.Entries[1].Score < m.Entries[0].Score) { m.Winner = m.Entries[1].TeamCompeting; } else { throw new Exception("We do not allow ties in this application"); } } else { // 1 mean true, or high score wins if (m.Entries[0].Score > m.Entries[1].Score) { m.Winner = m.Entries[0].TeamCompeting; } else if (m.Entries[1].Score > m.Entries[0].Score) { m.Winner = m.Entries[1].TeamCompeting; } else { throw new Exception("We do not allow ties in this application"); } } } } private static void CreateOtherRounds(TournamentModel model, int rounds) { int round = 2; List previousRound = model.Rounds[0]; List currRound = new List(); MatchupModel currMatchup = new MatchupModel(); while (round <= rounds) { foreach (MatchupModel match in previousRound) { currMatchup.Entries.Add(new MatchupEntryModel { ParentMatchup = match }); if (currMatchup.Entries.Count > 1) { currMatchup.MatchupRound = round; currRound.Add(currMatchup); currMatchup = new MatchupModel(); } } model.Rounds.Add(currRound); previousRound = currRound; currRound = new List(); round += 1; } } private static List CreateFirstRound(int byes, List teams) { List output = new List(); MatchupModel curr = new MatchupModel(); foreach (TeamModel team in teams) { curr.Entries.Add(new MatchupEntryModel { TeamCompeting = team }); if (byes > 0 || curr.Entries.Count > 1) { curr.MatchupRound = 1; output.Add(curr); curr = new MatchupModel(); if (byes > 0) { byes -= 1; } } } return output; } private static int NumberOfByes(int rounds, int numberOfTeams) { //Math.Pow(2, rounds); int output = 0; int totalTeams = 1; for (int i = 1; i <= rounds; i++) { totalTeams *= 2; } output = totalTeams - numberOfTeams; return output; } private static int FindNumberOfRounds(int teamCount) { int output = 1; int val = 2; while (val < teamCount) { output += 1; val *= 2; } return output; } private static List RandomizeTeamOrder(List teams) { // cards.OrderBy(a => Guid.NewGuid()).ToList(); return teams.OrderBy(t => Guid.NewGuid()).ToList(); } } }