diff --git a/TrackerLibrary/DataAccess/IDataConnection.cs b/TrackerLibrary/DataAccess/IDataConnection.cs index 585c8c4..8862dad 100644 --- a/TrackerLibrary/DataAccess/IDataConnection.cs +++ b/TrackerLibrary/DataAccess/IDataConnection.cs @@ -10,6 +10,7 @@ public interface IDataConnection void CreateTeam(TeamModel model); void CreateTournament(TournamentModel model); void UpdateMatchup(MatchupModel model); + void CompleteTournament(TournamentModel model); List GetTeam_All(); List GetPerson_All(); List GetTournament_All(); diff --git a/TrackerLibrary/DataAccess/SqlConnector.cs b/TrackerLibrary/DataAccess/SqlConnector.cs index f8d96cf..4aaeae7 100644 --- a/TrackerLibrary/DataAccess/SqlConnector.cs +++ b/TrackerLibrary/DataAccess/SqlConnector.cs @@ -373,5 +373,17 @@ public void UpdateMatchup(MatchupModel model) } } } + + public void CompleteTournament(TournamentModel model) + { + using (IDbConnection connection = new System.Data.SqlClient.SqlConnection(GlobalConfig.CnnString(db))) + { + var p = new DynamicParameters(); + + p.Add("@id", model.Id); + + connection.Execute("dbo.spTournaments_Complete", p, commandType: CommandType.StoredProcedure); + } + } } } diff --git a/TrackerLibrary/DataAccess/TextConnector.cs b/TrackerLibrary/DataAccess/TextConnector.cs index 02e339a..7faf166 100644 --- a/TrackerLibrary/DataAccess/TextConnector.cs +++ b/TrackerLibrary/DataAccess/TextConnector.cs @@ -129,5 +129,20 @@ public void UpdateMatchup(MatchupModel model) { model.UpdateMatchupToFile(); } + + // TODO: Create a way to archive a tournament instead of deleting it. + public void CompleteTournament(TournamentModel model) + { + List tournaments = GlobalConfig.TournamentFile. + FullFilePath(). + LoadFile(). + ConvertToTournamentModels(); + + tournaments.Remove(model); + + tournaments.SaveToTournamentFile(); + + TournamentLogic.UpdateTournamentResults(model); + } } } diff --git a/TrackerLibrary/EmailLogic.cs b/TrackerLibrary/EmailLogic.cs index 1e76d7a..d19b2d2 100644 --- a/TrackerLibrary/EmailLogic.cs +++ b/TrackerLibrary/EmailLogic.cs @@ -1,17 +1,34 @@ -using System.Net.Mail; +using System.Collections.Generic; +using System.Net.Mail; namespace TrackerLibrary { public class EmailLogic { public static void SendEmail(string to, string subject, string body) + { + SendEmail(new List { to }, new List(), subject, body); + } + + public static void SendEmail(List to, List bcc, string subject, string body) { MailAddress fromMailAddress = new MailAddress( GlobalConfig.AppKeyLookup("senderEmail"), GlobalConfig.AppKeyLookup("senderDisplayName")); MailMessage mail = new MailMessage(); - mail.To.Add(to); + + foreach (string email in to) + { + mail.To.Add(email); + } + + foreach (string email in bcc) + { + mail.Bcc.Add(email); + } + // TODO: Continue here 39:42 + mail.From = fromMailAddress; mail.Subject = subject; mail.Body = body; diff --git a/TrackerLibrary/Models/TournamentModel.cs b/TrackerLibrary/Models/TournamentModel.cs index a40b2e6..0d195b8 100644 --- a/TrackerLibrary/Models/TournamentModel.cs +++ b/TrackerLibrary/Models/TournamentModel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace TrackerLibrary.Models { @@ -7,6 +8,7 @@ namespace TrackerLibrary.Models /// public class TournamentModel { + public event EventHandler OnTournamentComplete; /// /// The unique identifier for the tournament. /// @@ -31,5 +33,10 @@ public class TournamentModel /// The matchups that the differents teams have to play /// public List> Rounds { get; set; } = new List>(); + + public void CompleteTournament() + { + OnTournamentComplete?.Invoke(this, DateTime.Now); + } } } diff --git a/TrackerLibrary/TournamentLogic.cs b/TrackerLibrary/TournamentLogic.cs index 560fc13..890fdcf 100644 --- a/TrackerLibrary/TournamentLogic.cs +++ b/TrackerLibrary/TournamentLogic.cs @@ -120,6 +120,101 @@ private static int CheckCurrentRound(this TournamentModel model) { output++; } + else + { + return output; + } + } + + CompleteTournament(model); + + return output - 1; + } + + private static void CompleteTournament(TournamentModel model) + { + GlobalConfig.Connection.CompleteTournament(model); + TeamModel winner = model.Rounds.Last().First().Winner; + TeamModel runnerUp = model.Rounds.Last().First() + .Entries.First(e => e.TeamCompeting != winner) + .TeamCompeting; + + decimal winnerPrize = 0; + decimal runnerUpPrize = 0; + + if (model.Prizes.Count > 0) + { + decimal totalIncome = model.EnteredTeams.Count * model.EntryFee; + + PrizeModel firstPlacePrize = model.Prizes.FirstOrDefault(x => x.PlaceNumber == 1); + PrizeModel secondPlacePrize = model.Prizes.FirstOrDefault(x => x.PlaceNumber == 2); + + if (firstPlacePrize != null) + { + winnerPrize = firstPlacePrize.CalculatePrizePayout(totalIncome); + } + + if ((secondPlacePrize != null)) + { + runnerUpPrize = secondPlacePrize.CalculatePrizePayout(totalIncome); + } + } + + // Send email To all tournament + + string subject = string.Empty; + StringBuilder body = new StringBuilder(); + + subject = $"In {model.TournamentName}, {winner.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($"

{winner.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 (var team in model.EnteredTeams) + { + foreach (var teamMember in team.TeamMembers) + { + if (teamMember.EmailAddress.Length > 0) + { + bcc.Add(teamMember.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; diff --git a/TrackerUI/TournamentViewerForm.cs b/TrackerUI/TournamentViewerForm.cs index 543d170..67f91ad 100644 --- a/TrackerUI/TournamentViewerForm.cs +++ b/TrackerUI/TournamentViewerForm.cs @@ -20,6 +20,8 @@ public TournamentViewerForm(TournamentModel tournamentModel) tournament = tournamentModel; + tournament.OnTournamentComplete += Tournament_OnTournamentComplete; + WireUpLists(); LoadFormData(); @@ -27,6 +29,11 @@ public TournamentViewerForm(TournamentModel tournamentModel) LoadRounds(); } + private void Tournament_OnTournamentComplete(object sender, DateTime e) + { + this.Close(); + } + private void LoadFormData() { tournamentName.Text = tournament.TournamentName; diff --git a/scriptDB.sql b/scriptDB.sql index 4a86a6f..efa82bf 100644 --- a/scriptDB.sql +++ b/scriptDB.sql @@ -1,4 +1,4 @@ -GO +GO USE [master]; GO @@ -15,16 +15,17 @@ USE [Tournaments]; GO -CREATE TABLE [Prizes]( -[id] [int] IDENTITY(1,1) NOT NULL, -[PlaceNumber] [int] NOT NULL, -[PlaceName] [nvarchar](50) NOT NULL, -[PrizeAmount] [money] NOT NULL, -[PrizePercentage] [float] NOT NULL, -CONSTRAINT [PK_Prizes] PRIMARY KEY CLUSTERED ([id]) ---, ---CONSTRAINT [DF_Prizes_PrizeAmount] DEFAULT ((0)) FOR [PrizeAmount], ---CONSTRAINT [DF_Prizes_PrizePercentage] DEFAULT ((0)) FOR [PrizePercentage] +CREATE TABLE [Prizes] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [PlaceNumber] [int] NOT NULL, + [PlaceName] [nvarchar](50) NOT NULL, + [PrizeAmount] [money] NOT NULL, + [PrizePercentage] [float] NOT NULL, + CONSTRAINT [PK_Prizes] PRIMARY KEY CLUSTERED ([id]) + --, + --CONSTRAINT [DF_Prizes_PrizeAmount] DEFAULT ((0)) FOR [PrizeAmount], + --CONSTRAINT [DF_Prizes_PrizePercentage] DEFAULT ((0)) FOR [PrizePercentage] ); GO @@ -35,23 +36,25 @@ ALTER TABLE [Prizes] ADD CONSTRAINT [DF_Prizes_PrizePercentage] DEFAULT ((0)) FO GO -CREATE TABLE [TournamentPrizes]( -[id] [int] IDENTITY(1,1) NOT NULL, -[TournamentId] [int] NOT NULL, -[PrizeId] [int] NOT NULL, -CONSTRAINT [PK_Tournament_Prizes] PRIMARY KEY CLUSTERED ([id]) +CREATE TABLE [TournamentPrizes] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [TournamentId] [int] NOT NULL, + [PrizeId] [int] NOT NULL, + CONSTRAINT [PK_Tournament_Prizes] PRIMARY KEY CLUSTERED ([id]) ); GO -CREATE TABLE [Tournaments]( -[id] [int] IDENTITY(1,1) NOT NULL, -[TournamentName] [nvarchar](50) NOT NULL, -[EntryFee] [money] NOT NULL, -[Active] [bit] NOT NULL, -CONSTRAINT [PK_Tournaments] PRIMARY KEY CLUSTERED ([id]) ---, ---CONSTRAINT [DF_Tournaments_EntryFee] DEFAULT ((0)) FOR [EntryFee] +CREATE TABLE [Tournaments] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [TournamentName] [nvarchar](50) NOT NULL, + [EntryFee] [money] NOT NULL, + [Active] [bit] NOT NULL, + CONSTRAINT [PK_Tournaments] PRIMARY KEY CLUSTERED ([id]) + --, + --CONSTRAINT [DF_Tournaments_EntryFee] DEFAULT ((0)) FOR [EntryFee] ); GO @@ -59,60 +62,66 @@ ALTER TABLE [Tournaments] ADD CONSTRAINT [DF_Tournaments_EntryFee] DEFAULT ((0)) GO -CREATE TABLE [TournamentEntries]( -[id] [int] IDENTITY(1,1) NOT NULL, -[TournamentId] [int] NOT NULL, -[TeamId] [int] NOT NULL, -CONSTRAINT [PK_Tournament_Entries] PRIMARY KEY CLUSTERED ([id]), +CREATE TABLE [TournamentEntries] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [TournamentId] [int] NOT NULL, + [TeamId] [int] NOT NULL, + CONSTRAINT [PK_Tournament_Entries] PRIMARY KEY CLUSTERED ([id]), ); GO -CREATE TABLE [Teams]( -[id] [int] IDENTITY(1,1) NOT NULL, -[TeamName] [nvarchar](100) NOT NULL, -CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED ([id]), +CREATE TABLE [Teams] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [TeamName] [nvarchar](100) NOT NULL, + CONSTRAINT [PK_Teams] PRIMARY KEY CLUSTERED ([id]), ); GO -CREATE TABLE [TeamMembers]( -[id] [int] IDENTITY(1,1) NOT NULL, -[TeamId] [int] NOT NULL, -[PersonId] [int] NOT NULL, -CONSTRAINT [PK_Team_Members] PRIMARY KEY CLUSTERED ([id]) +CREATE TABLE [TeamMembers] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [TeamId] [int] NOT NULL, + [PersonId] [int] NOT NULL, + CONSTRAINT [PK_Team_Members] PRIMARY KEY CLUSTERED ([id]) ); GO -CREATE TABLE [People]( -[id] [int] IDENTITY(1,1) NOT NULL, -[FirstName] [nvarchar](100) NOT NULL, -[LastName] [nvarchar](100) NOT NULL, -[EmailAddress] [nvarchar](100) NOT NULL, -[CellPhoneNumber] [nvarchar](100), -CONSTRAINT [PK_People] PRIMARY KEY CLUSTERED ([id]) +CREATE TABLE [People] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [FirstName] [nvarchar](100) NOT NULL, + [LastName] [nvarchar](100) NOT NULL, + [EmailAddress] [nvarchar](100) NOT NULL, + [CellPhoneNumber] [nvarchar](100), + CONSTRAINT [PK_People] PRIMARY KEY CLUSTERED ([id]) ); GO -CREATE TABLE [Matchups]( -[id] [int] IDENTITY(1,1) NOT NULL, -[TournamentId] [int] NOT NULL, -[WinnerId] [int], -[MatchupRound] [int] NOT NULL, -CONSTRAINT [PK_Matchups] PRIMARY KEY CLUSTERED ([id]) +CREATE TABLE [Matchups] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [TournamentId] [int] NOT NULL, + [WinnerId] [int], + [MatchupRound] [int] NOT NULL, + CONSTRAINT [PK_Matchups] PRIMARY KEY CLUSTERED ([id]) ); GO -CREATE TABLE [MatchupEntries]( -[id] [int] IDENTITY(1,1) NOT NULL, -[MatchupId] [int] NOT NULL, -[ParentMatchupId] [int], -[TeamCompetingId] [int], -[Score] [int], -CONSTRAINT [PK_Matchup_Entries] PRIMARY KEY CLUSTERED ([id]) +CREATE TABLE [MatchupEntries] +( + [id] [int] IDENTITY(1,1) NOT NULL, + [MatchupId] [int] NOT NULL, + [ParentMatchupId] [int], + [TeamCompetingId] [int], + [Score] [int], + CONSTRAINT [PK_Matchup_Entries] PRIMARY KEY CLUSTERED ([id]) ); @@ -156,7 +165,7 @@ ALTER TABLE [MatchupEntries] ADD CONSTRAINT [FK_MatchupEntries_MatchupId] FOREIG REFERENCES [Matchups] ([id]); -GO +GO ALTER TABLE [MatchupEntries] ADD CONSTRAINT [FK_MatchupEntries_ParentMatchupId] FOREIGN KEY ([ParentMatchupId]) REFERENCES [Matchups] ([id]); @@ -183,7 +192,7 @@ BEGIN select me.* from MatchupEntries me - inner join Matchups m on me.MatchupId = m.id + inner join Matchups m on me.MatchupId = m.id where m.id = @MatchupId; END @@ -199,8 +208,8 @@ BEGIN SET NOCOUNT ON; - select m.* - from Matchups as m + select m.* + from Matchups as m where m.TournamentId = @TournamentId order by MatchupRound; @@ -217,7 +226,7 @@ BEGIN SET NOCOUNT ON; - select * + select * from People; END @@ -236,7 +245,7 @@ BEGIN select p.* from Prizes p - inner join TournamentPrizes t on p.id = t.PrizeId + inner join TournamentPrizes t on p.id = t.PrizeId where t.tournamentId = @TournamentId; END @@ -253,9 +262,9 @@ BEGIN SET NOCOUNT ON; - select t.* - from Teams as t - inner join TournamentEntries as e on t.id = e.TeamId + select t.* + from Teams as t + inner join TournamentEntries as e on t.id = e.TeamId where e.TournamentId = @TournamentId; END @@ -272,10 +281,10 @@ BEGIN SET NOCOUNT ON; - select p.* + select p.* from People as p - inner join TeamMembers as tm on p.id = tm.PersonId - inner join Teams as t on tm.TeamId = t.id + inner join TeamMembers as tm on p.id = tm.PersonId + inner join Teams as t on tm.TeamId = t.id where t.id = @TeamId @@ -317,8 +326,10 @@ AS BEGIN SET NOCOUNT ON; - insert into dbo.Prizes (PlaceNumber, PlaceName, PrizeAmount, PrizePercentage) - values (@PlaceNumber, @PlaceName, @PrizeAmount, @PrizePercentage); + insert into dbo.Prizes + (PlaceNumber, PlaceName, PrizeAmount, PrizePercentage) + values + (@PlaceNumber, @PlaceName, @PrizeAmount, @PrizePercentage); select @id = SCOPE_IDENTITY(); @@ -344,7 +355,8 @@ AS BEGIN SET NOCOUNT ON; - insert into People(FirstName, LastName, EmailAddress, CellPhoneNumber) + insert into People + (FirstName, LastName, EmailAddress, CellPhoneNumber) values(@FirstName, @LastName, @EmailAddress, @CellPhoneNumber); select @id = SCOPE_IDENTITY(); @@ -367,8 +379,10 @@ AS BEGIN SET NOCOUNT ON; - insert into Teams (TeamName) - values (@TeamName); + insert into Teams + (TeamName) + values + (@TeamName); select @Id = SCOPE_IDENTITY(); END @@ -391,8 +405,10 @@ AS BEGIN SET NOCOUNT ON; - insert into TeamMembers (TeamId,PersonId) - values (@TeamId,@PersonId); + insert into TeamMembers + (TeamId,PersonId) + values + (@TeamId, @PersonId); select @id = SCOPE_IDENTITY(); END @@ -411,7 +427,7 @@ AS BEGIN SET NOCOUNT ON; - select * + select * from dbo.Teams; END @@ -432,8 +448,10 @@ AS BEGIN SET NOCOUNT ON; - insert into Tournaments(TournamentName,EntryFee,Active) - values (@TournamentName,@EntryFee,1); + insert into Tournaments + (TournamentName,EntryFee,Active) + values + (@TournamentName, @EntryFee, 1); select @id = SCOPE_IDENTITY(); END @@ -457,8 +475,10 @@ AS BEGIN SET NOCOUNT ON; - insert into TournamentPrizes(TournamentId,PrizeId) - values (@TournamentId,@PrizeId); + insert into TournamentPrizes + (TournamentId,PrizeId) + values + (@TournamentId, @PrizeId); select @id = SCOPE_IDENTITY(); END @@ -482,8 +502,10 @@ AS BEGIN SET NOCOUNT ON; - insert into TournamentEntries(TournamentId,TeamId) - values (@TournamentId,@TeamId); + insert into TournamentEntries + (TournamentId,TeamId) + values + (@TournamentId, @TeamId); select @id = SCOPE_IDENTITY(); END @@ -504,8 +526,10 @@ AS BEGIN SET NOCOUNT ON; - insert into Matchups(TournamentId,MatchupRound) - values (@TournamentId,@MatchupRound); + insert into Matchups + (TournamentId,MatchupRound) + values + (@TournamentId, @MatchupRound); select @id = SCOPE_IDENTITY(); END @@ -528,8 +552,10 @@ AS BEGIN SET NOCOUNT ON; - insert into MatchupEntries(MatchupId,ParentMatchupId,TeamCompetingId) - values (@MatchupId,@ParentMatchupId,@TeamCompetingId); + insert into MatchupEntries + (MatchupId,ParentMatchupId,TeamCompetingId) + values + (@MatchupId, @ParentMatchupId, @TeamCompetingId); select @id = SCOPE_IDENTITY(); END @@ -559,7 +585,6 @@ END - GO -- ============================================= -- Author: Alejandro @@ -578,4 +603,25 @@ BEGIN set TeamCompetingId = @TeamCompetingId, Score = @Score where id = @Id; +END + + + + +GO +-- ============================================= +-- Author: Alejandro +-- Create date: 8/31/2025 +-- Description: Marks a tournament as complete. +-- ============================================= +CREATE PROCEDURE dbo.spTournaments_Complete + @id int +AS +BEGIN + SET NOCOUNT ON; + + update dbo.Tournaments + set Active = 0 + where id = @Id; + END \ No newline at end of file