diff --git a/Callvote.API/Features/Votes/UserIndentifier.cs b/Callvote.API/Features/Votes/UserIndentifier.cs index 572e5d6..c10756b 100644 --- a/Callvote.API/Features/Votes/UserIndentifier.cs +++ b/Callvote.API/Features/Votes/UserIndentifier.cs @@ -51,7 +51,7 @@ public UserIndentifier(int userId, string name, string uniqueId) /// The first instance to compare. /// The second instance to compare. /// true if the two instances are equal; otherwise, false. - public static bool operator ==(UserIndentifier left, UserIndentifier right) => left.Equals(right); + public static bool operator ==(UserIndentifier left, UserIndentifier right) => (left == null || right == null) && left.Equals(right); /// /// Determines whether two instances of the class are not equal. @@ -59,13 +59,13 @@ public UserIndentifier(int userId, string name, string uniqueId) /// The first instance to compare. /// The second instance to compare. /// true if the two instances not are equal; otherwise, false. - public static bool operator !=(UserIndentifier left, UserIndentifier right) => !left.Equals(right); + public static bool operator !=(UserIndentifier left, UserIndentifier right) => (left == null || right == null) && !left.Equals(right); /// - public bool Equals(UserIndentifier other) => this.UniqueUserId == other.UniqueUserId && this.UserId == other.UserId; + public override bool Equals(object obj) => obj is UserIndentifier other && this.Equals(other); /// - public override bool Equals(object obj) => obj is UserIndentifier other && this.Equals(other); + public bool Equals(UserIndentifier other) => other is not null && this.UniqueUserId == other.UniqueUserId; /// public override int GetHashCode() => this.UniqueUserId.GetHashCode(); diff --git a/Callvote.API/Features/Votes/Vote.cs b/Callvote.API/Features/Votes/Vote.cs index c54a79d..48b09c5 100644 --- a/Callvote.API/Features/Votes/Vote.cs +++ b/Callvote.API/Features/Votes/Vote.cs @@ -432,19 +432,57 @@ public virtual string BuildResultsMessage() /// /// Starts the by registering the commands and starting the coroutine. /// - internal void StartVote() + /// Returns the . + internal CallVoteStatus StartVote() { + CallingVoteEventArgs e = new(this); + EventsHandlers.OnCallingVote(e); + if (!e.IsAllowed) + { + return CallVoteStatus.VoteCancelled; + } + this.RegisterAllVoteOptions(); this.StartVoteCoroutine(); + + CalledVoteEventArgs ev = new(this); + EventsHandlers.OnCalledVote(ev); + return CallVoteStatus.VoteStarted; } /// /// Stops the by unregistering the command and stopping the coroutine. /// - internal void FinishVote() + /// If the voting will display the results message or invoke the Callback. + internal void FinishVote(bool isForced = false) { + VoteEndingEventArgs e = new(this); + if (!e.IsAllowed) + { + return; + } + this.UnregisterVoteOptionsCommand(); this.StopVoteCoroutine(); + + if (!isForced) + { + return; + } + + if (this.Callback == null) + { + DisplayHandler.Show(this.ResultsMessageDuration, this.BuildResultsMessage(), this.AllowedPlayers); + } + else + { + this?.Callback.Invoke(this); + } + + // Prevents being null when it's later used in the event + Vote vote = this; + VoteEndedEventArgs ev = new(vote); + EventsHandlers.OnVoteEnded(ev); } /// diff --git a/Callvote.API/Features/Votes/VoteHandler.cs b/Callvote.API/Features/Votes/VoteHandler.cs index 833122a..a0a6d30 100644 --- a/Callvote.API/Features/Votes/VoteHandler.cs +++ b/Callvote.API/Features/Votes/VoteHandler.cs @@ -1,8 +1,8 @@ using System; +using System.Collections.Generic; +using System.Linq; using Callvote.API.Enums; -using Callvote.API.Events; -using Callvote.API.Events.EventArgs; -using Callvote.API.Features.Displays; +using Utils.NonAllocLINQ; namespace Callvote.API.Features.Votes { @@ -23,6 +23,10 @@ static VoteHandler() } #endif + public static IReadOnlyCollection ReadOnlyActiveParallelVotes => ActiveParallelVotes; + + internal static HashSet ActiveParallelVotes { get; } = new HashSet(); + /// /// Gets the currently active instance. Null when no vote is in progress. /// @@ -43,28 +47,25 @@ static VoteHandler() /// If queueing is enabled the will be enqueued and the is started immediately. /// /// The to start or enqueue. + /// If the vote will be ran in parallel. /// A representing if the action was sucessfull, or for example, if the queue is full. - public static CallVoteStatus CallVote(Vote vote) + public static CallVoteStatus CallVote(Vote vote, bool isParallel = false) { if (vote == null) { throw new ArgumentNullException(nameof(vote), "Vote cannot be null!"); } - if (!IsVoteActive) + if (isParallel) { - CallingVoteEventArgs e = new(vote); - EventsHandlers.OnCallingVote(e); - if (!e.IsAllowed) - { - return CallVoteStatus.VoteCancelled; - } + ActiveParallelVotes.Add(vote); + return CurrentVote.StartVote(); + } + if (!IsVoteActive) + { CurrentVote = vote; - CurrentVote.StartVote(); - CalledVoteEventArgs ev = new(CurrentVote); - EventsHandlers.OnCalledVote(ev); - return CallVoteStatus.VoteStarted; + return CurrentVote.StartVote(); } return CallVoteStatus.VoteInProgress; @@ -82,31 +83,76 @@ public static void FinishVote(bool isForced = false) return; } - VoteEndingEventArgs e = new(CurrentVote); - if (!e.IsAllowed) + CurrentVote?.FinishVote(isForced); + + CurrentVote = null; + } + + public static void StopParallelVote(Vote vote, bool isForced = false) + { + if (vote == null) + { + return; + } + + if (!ActiveParallelVotes.Contains(vote) && !vote.IsCoroutineActive) { return; } - CurrentVote?.FinishVote(); + CurrentVote?.FinishVote(isForced); + ActiveParallelVotes.Remove(vote); + } + + public static void StopParallelVote(long voteId, bool isForced = false) + { + if (voteId == 0) + { + return; + } - if (!isForced) + if (!ActiveParallelVotes.TryGetFirst(v => v.VoteId == voteId, out Vote vote)) { - if (CurrentVote?.Callback == null) - { - DisplayHandler.Show(CurrentVote.ResultsMessageDuration, CurrentVote.BuildResultsMessage(), CurrentVote.AllowedPlayers); - } - else - { - CurrentVote?.Callback.Invoke(CurrentVote); - } + return; } - Vote vote = CurrentVote; - CurrentVote = null; + StopParallelVote(vote, isForced); + } + + public static void StopParallelVotes(UserIndentifier user, bool isForced = false) + { + if (user == null) + { + return; + } + + foreach (Vote vote in ActiveParallelVotes.Where(v => v.CallVotePlayer == user)) + { + StopParallelVote(vote, isForced); + } + } + + public static void StopParallelVotes(IEnumerable votes, bool isForced = false) + { + if (votes == null) + { + return; + } + + foreach (Vote vote in votes) + { + StopParallelVote(vote, isForced); + } + } + + public static void StopAllParallelVotes(bool isForced = false) + { + foreach (Vote vote in ActiveParallelVotes) + { + StopParallelVote(vote, isForced); + } - VoteEndedEventArgs ev = new(vote); - EventsHandlers.OnVoteEnded(ev); + ActiveParallelVotes.Clear(); } ///