diff --git a/src/Gameboard.Api/Features/UnityGames/IUnityGameService.cs b/src/Gameboard.Api/Features/UnityGames/IUnityGameService.cs index e5207518..c3187cef 100644 --- a/src/Gameboard.Api/Features/UnityGames/IUnityGameService.cs +++ b/src/Gameboard.Api/Features/UnityGames/IUnityGameService.cs @@ -1,13 +1,12 @@ -using System.Collections.Generic; using System.Threading.Tasks; -using Gameboard.Api.Data; namespace Gameboard.Api.Features.UnityGames; public interface IUnityGameService { - Task AddChallengeEvent(NewUnityChallengeEvent model, string userId); Task AddChallenge(NewUnityChallenge newChallenge, User actor); - Task CreateMissionEvent(UnityMissionUpdate model, Api.User actor); + Task CreateMissionEvent(UnityMissionUpdate model, Api.User actor); Task DeleteChallengeData(string gameId); + bool IsUnityGame(Game game); + bool IsUnityGame(Data.Game game); } \ No newline at end of file diff --git a/src/Gameboard.Api/Features/UnityGames/UnityGameController.cs b/src/Gameboard.Api/Features/UnityGames/UnityGameController.cs index 2d094f7e..41c02c15 100644 --- a/src/Gameboard.Api/Features/UnityGames/UnityGameController.cs +++ b/src/Gameboard.Api/Features/UnityGames/UnityGameController.cs @@ -162,35 +162,25 @@ await _hub.Clients return result; } - /// - /// Log a challenge event for all members of the specified team. - /// - /// NewChallengeEvent - /// ChallengeEvent - [HttpPost("api/unity/challengeEvent")] - [Authorize] - public async Task CreateChallengeEvent([FromBody] NewUnityChallengeEvent model) - { - AuthorizeAny( - () => Actor.IsDirector, - () => Actor.IsAdmin, - () => Actor.IsDesigner - ); - - await Validate(model); - return await _unityGameService.AddChallengeEvent(model, Actor.Id); - } - [HttpPost("api/unity/mission-update")] [Authorize] - public async Task CreateMissionEvent([FromBody] UnityMissionUpdate model) + public async Task CreateMissionEvent([FromBody] UnityMissionUpdate model) { AuthorizeAny( () => Actor.IsAdmin ); await Validate(model); - await _unityGameService.CreateMissionEvent(model, Actor); + var challengeEvent = await _unityGameService.CreateMissionEvent(model, Actor); + + if (challengeEvent == null) + { + // this means that everything went fine, but that we've already been told the team completed this challenge + return Accepted(); + } + + // this means we actually created an event + return Ok(challengeEvent); } [Authorize] diff --git a/src/Gameboard.Api/Features/UnityGames/UnityGameService.cs b/src/Gameboard.Api/Features/UnityGames/UnityGameService.cs index 7cead5a7..1d2ded74 100644 --- a/src/Gameboard.Api/Features/UnityGames/UnityGameService.cs +++ b/src/Gameboard.Api/Features/UnityGames/UnityGameService.cs @@ -144,7 +144,7 @@ ConsoleActorMap actorMap UserId = actor.Id, TeamId = newChallenge.TeamId, Timestamp = DateTimeOffset.UtcNow, - Text = $"{teamCaptain.ApprovedName}'s journey into CubeSpace has begun...", + Text = $"{teamCaptain.ApprovedName}'s has gathered their team and departed into CubeSpace...", Type = ChallengeEventType.Started } }, @@ -157,21 +157,6 @@ ConsoleActorMap actorMap return newChallengeEntity; } - public async Task AddChallengeEvent(NewUnityChallengeEvent model, string userId) - { - var challengeEvent = new Data.ChallengeEvent - { - ChallengeId = model.ChallengeId, - UserId = userId, - TeamId = model.TeamId, - Text = model.Text, - Type = model.Type, - Timestamp = model.Timestamp - }; - - return await Store.AddUnityChallengeEvent(challengeEvent); - } - public async Task DeleteChallengeData(string gameId) { var challenges = await Store @@ -192,40 +177,63 @@ public async Task DeleteChallengeData(string gameId) await Store.DbContext.SaveChangesAsync(); } - public async Task CreateMissionEvent(UnityMissionUpdate model, Api.User actor) + public async Task CreateMissionEvent(UnityMissionUpdate model, Api.User actor) { - var challenge = await Store.DbContext + var unityMode = GetUnityModeString(); + var challengeCandidates = await Store.DbContext .Challenges .Include(c => c.Game) .Include(c => c.Events) .Include(c => c.Player) - .Where(c => c.TeamId == model.TeamId && c.Game.Mode.ToLower() == "unity") - .FirstOrDefaultAsync(); + .Where(c => c.TeamId == model.TeamId && c.Game.Mode == unityMode) + .ToListAsync(); - if (challenge == null) + if (challengeCandidates.Count() != 1) { throw new ChallengeResolutionFailure(model.TeamId); } + // if we return null to the controller above, it interprets this as an "ok cool, we already have this one" + // kind of thing + var challenge = challengeCandidates.First(); + if (IsMissionComplete(challenge.Events, model.MissionId)) + { + return null; + } + // record an event for this challenge - challenge.Events.Add(new Data.ChallengeEvent + var challengeEvent = new Data.ChallengeEvent { Id = Guid.NewGuid().ToString("n"), ChallengeId = challenge.Id, UserId = actor.Id, TeamId = model.TeamId, - Text = $"{challenge.Player} has found the codex for {model.MissionName}!", + Text = $"{challenge.Player.ApprovedName}'s team has found the codex for {model.MissionName}! {GetMissionCompleteDefinitionString(model.MissionId)}", Type = ChallengeEventType.Submission, Timestamp = DateTimeOffset.UtcNow - }); + }; + challenge.Events.Add(challengeEvent); // also update the score of the challenge challenge.Score += model.PointsScored; // save it up await Store.DbContext.SaveChangesAsync(); + + // return (used to determine HTTP status code in an above controller) + return challengeEvent; } + public bool IsUnityGame(Data.Game game) => game.Mode == GetUnityModeString(); + public bool IsUnityGame(Game game) => game.Mode == GetUnityModeString(); + private string GetUnityModeString() => "unity"; + + private string GetMissionCompleteDefinitionString(string missionId) + => $"[complete:{missionId}]"; + + private bool IsMissionComplete(IEnumerable events, string missionId) + => events.Any(e => e.Text.Contains(GetMissionCompleteDefinitionString(missionId))); + private Data.Player ResolveTeamCaptain(IEnumerable players, NewUnityChallenge newChallenge) { if (players.Count() == 0)