/// <summary>
        /// Adds all of the AddCharacters to the given campaign and removes all of the RemoveCharacters from the given
        /// campaign if they were originally part of the given campaign
        /// </summary>
        /// <param name="campaignId"></param>
        /// <param name="model"></param>
        /// <exception cref="DataNotFoundException">If one of the CharacterIds does not point to a character in the database</exception>
        /// <exception cref="DataNotCreatedException">
        /// If one or more of the changes was not persisted to the database.
        /// If this exception is thrown, the campaign may be in an invalid state.
        /// </exception>
        /// <returns></returns>
        private async Task ModifyCampaignAsGm(Guid campaignId, CampaignModification model)
        {
            using (var db = new DatabaseContext(options))
            {
                int should = 0;

                if (model.AddCharacters != null)
                {
                    foreach (var cid in model.AddCharacters)
                    {
                        var character = await db.Characters.SingleOrDefaultAsync(c => c.CharacterId == cid);

                        if (character == null)
                        {
                            throw new DataNotFoundException($"Could not find character {cid}");
                        }

                        // only update if we need to
                        if (character.CampaignId != campaignId)
                        {
                            character.CampaignId = campaignId;
                            should += 1;
                        }
                    }
                }

                if (model.RemoveCharacters != null)
                {
                    foreach (var cid in model.RemoveCharacters)
                    {
                        var character = await db.Characters.SingleOrDefaultAsync(c => c.CharacterId == cid);

                        if (character == null)
                        {
                            throw new DataNotFoundException($"Could not find character {cid}");
                        }

                        // only set the character's campaign to null if it was originally the id of the campaign being modified
                        if (character.CampaignId == campaignId)
                        {
                            character.CampaignId = null;
                            should += 1;
                        }
                    }
                }

                int actual = await db.SaveChangesAsync();

                if (actual != should)
                {
                    throw new DataNotCreatedException($"Error saving one or more of the updates: Expected {should}, recieved {actual}");
                }
            }
        }
        /// <summary>
        /// Adds all of the AddCharacters that belong to the user to the given campaign
        /// and removes all of the RemoveCharacters that belong to the user and are in the given campaign from that campaign
        /// </summary>
        /// <param name="campaignId"></param>
        /// <param name="userId"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task ModifyCampaignBasic(Guid campaignId, string userId, CampaignModification model)
        {
            // nothing to do, dont bother going further
            if ((model.AddCharacters == null || model.AddCharacters.Count == 0) &&
                (model.RemoveCharacters == null || model.RemoveCharacters.Count == 0))
            {
                return;
            }

            using (var db = new DatabaseContext(options))
            {
                var userCharacters = await db.Characters
                                     .Where(c => c.UserId == userId)
                                     .ToListAsync();

                int should = 0;

                if (model.AddCharacters != null)
                {
                    // only the characters whose ids are in the list to add to the given campaign
                    var toAdd = userCharacters.Where(c => model.AddCharacters.Any(id => id == c.CharacterId));
                    foreach (var character in toAdd)
                    {
                        character.CampaignId = campaignId;
                        should += 1;
                    }
                }

                if (model.RemoveCharacters != null)
                {
                    // only the characters whose ids are in the list to remove from the given campaign and are currently in the given campaign
                    var toRemove = userCharacters.Where(c => c.CampaignId == campaignId && model.RemoveCharacters.Any(id => id == c.CharacterId));
                    foreach (var character in toRemove)
                    {
                        character.CampaignId = null;
                        should += 1;
                    }
                }

                int actual = await db.SaveChangesAsync();

                if (should != actual)
                {
                    throw new DataNotCreatedException($"Error saving one or more of the updates: Expected {should}, recieved {actual}");
                }
            }
        }
Exemple #3
0
        public async Task <IActionResult> ModifyCampaign(Guid campaignId, CampaignModification model, bool sendUpdate = true)
        {
            try
            {
                var campaign = await games.ModifyCampaign(campaignId, users.GetUserId(), model);

                if (sendUpdate)
                {
                    await sockets.SendCampaign(campaign);
                }

                return(Json(campaign));
            }
            catch (DataNotFoundException e)
            {
                logger.LogInformation(0, e, "Campaign or characters could not be found");
                return(NotFound());
            }
        }
        /// <summary>
        /// Modifies a campaign to fit the updates given in CampaignModification
        /// </summary>
        /// <param name="campaignId"></param>
        /// <param name="userId"></param>
        /// <param name="model"></param>
        /// <exception cref="DataNotFoundException"></exception>
        /// <exception cref="DataNotCreatedException"></exception>
        /// <returns></returns>
        public async Task <CampaignView> ModifyCampaign(Guid campaignId, string userId, CampaignModification model)
        {
            Campaign campaign;

            using (var db = new DatabaseContext(options))
            {
                campaign = await db.Campaigns
                           .Include(c => c.Characters)
                           .SingleOrDefaultAsync(c => c.CampaignId == campaignId);

                if (campaign == null)
                {
                    throw new DataNotFoundException($"Could not find campaign {campaignId}");
                }

                // only update the name if it is set, valid, coming from the GM, and different than the current name
                if (!string.IsNullOrWhiteSpace(model.Name) &&
                    userId == campaign.GmUserId &&
                    campaign.Name != model.Name)
                {
                    campaign.Name = model.Name;
                    int changes = await db.SaveChangesAsync();

                    if (changes != 1)
                    {
                        throw new DataNotCreatedException("Could not update campaign name");
                    }
                }
            }

            if (campaign.GmUserId == userId)
            {
                await ModifyCampaignAsGm(campaignId, model);
            }
            else
            {
                await ModifyCampaignBasic(campaignId, userId, model);
            }

            // reload the updated campaign, the existing reference isnt updated
            using (var db = new DatabaseContext(options))
            {
                campaign = await db.Campaigns
                           .Include(c => c.Characters)
                           .SingleAsync(c => c.CampaignId == campaignId);

                return(new CampaignView(campaign));
            }
        }