public ValueTask HandleAsync(ConnectedClient sender, JoinContest message, CancellationToken cancellationToken) { var existingContest = _contestStore.FindActiveByContestantId(sender.ClientId); if (existingContest != null) { throw new InvalidOperationException($"Already in contest {existingContest.ContestId}"); } var contest = _contestStore.Find(sender.Group); if (contest == null) { contest = new Contest(sender.Group); } contest.Join(sender.ClientId, message.Side); _contestStore.Save(contest); return(default);
public object GetUpdateFor(string clientId) { var contest = _contestStore.FindActiveByContestantId(clientId); if (contest == null) { // This is a bit of a hack. Either pass ConnectedClient to this method, // or have a domain-specific ISpectatorsStore that will be filled by ConnectHook. var client = _connectedClients.Find(clientId); if (client == null) { throw new InvalidOperationException("Client is not connected already."); } var contestId = client.Group; contest = _contestStore.Find(contestId); if (contest == null) { return(new ContestUpdate()); // Not started yet. } } var data = contest.GetData(); return(new ContestUpdate { Progress = data.Progress, Contestants = data.Contestants.SelectMany( x => x.Value.Select( contestantId => new ContestantUpdate { ContestantId = contestantId, Side = x.Key })).ToList(), HasStarted = data.HasStarted, HasEnded = data.HasEnded }); }