private static bool ValidateTimestamp(CharacterLootList list, byte[] timestamp) { if (list.Timestamp.Length != timestamp.Length) { return(false); } for (int i = 0; i < timestamp.Length; i++) { if (list.Timestamp[i] != timestamp[i]) { return(false); } } return(true); }
public async Task <ActionResult <LootListDto> > PostLootList(long characterId, byte phase, [FromBody] LootListSubmissionDto dto, [FromServices] IdGen.IIdGenerator <long> idGenerator) { var authorizationResult = await _authorizationService.AuthorizeAsync(User, characterId, AppPolicies.CharacterOwnerOrAdmin); if (!authorizationResult.Succeeded) { return(Unauthorized()); } var bracketTemplates = await _context.Brackets.AsNoTracking().Where(b => b.Phase == phase).OrderBy(b => b.Index).ToListAsync(); if (bracketTemplates.Count == 0) { return(NotFound()); } if (!ModelState.IsValid) { return(ValidationProblem()); } var character = await _context.Characters.FindAsync(characterId); if (character is null) { return(NotFound()); } if (character.Deactivated) { return(Problem("Character has been deactivated.")); } if (await _context.CharacterLootLists.AsNoTracking().AnyAsync(ll => ll.CharacterId == character.Id && ll.Phase == phase)) { return(Problem("A loot list for that character and phase already exists.")); } if (!dto.MainSpec.IsClass(character.Class)) { ModelState.AddModelError(nameof(dto.MainSpec), "Selected specialization does not fit the player's class."); return(ValidationProblem()); } if (dto.OffSpec != default && !dto.OffSpec.IsClass(character.Class)) { ModelState.AddModelError(nameof(dto.OffSpec), "Selected specialization does not fit the player's class."); return(ValidationProblem()); } var list = new CharacterLootList { CharacterId = character.Id, Character = character, Entries = new List <LootListEntry>(28), Status = LootListStatus.Editing, MainSpec = dto.MainSpec, OffSpec = dto.OffSpec, Phase = phase }; var entries = new List <LootListEntry>(); var brackets = await _context.Brackets .AsNoTracking() .Where(b => b.Phase == phase) .OrderBy(b => b.Index) .ToListAsync(); foreach (var bracket in brackets) { for (byte rank = bracket.MinRank; rank <= bracket.MaxRank; rank++) { for (int col = 0; col < bracket.MaxItems; col++) { var entry = new LootListEntry(idGenerator.CreateId()) { LootList = list, Rank = rank }; _context.LootListEntries.Add(entry); entries.Add(entry); } } } _context.CharacterLootLists.Add(list); await _context.SaveChangesAsync(); _telemetry.TrackEvent("LootListCreated", User, props => { props["CharacterId"] = character.Id.ToString(); props["CharacterName"] = character.Name; props["Phase"] = list.Phase.ToString(); }); var scope = await _context.GetCurrentPriorityScopeAsync(); var observedDates = await _context.Raids .AsNoTracking() .Where(r => r.RaidTeamId == character.TeamId) .OrderByDescending(r => r.StartedAt) .Select(r => r.StartedAt.Date) .Distinct() .Take(scope.ObservedAttendances) .ToListAsync(); var attendance = await _context.RaidAttendees .AsNoTracking() .Where(x => !x.IgnoreAttendance && x.RemovalId == null && x.CharacterId == character.Id && x.Raid.RaidTeamId == character.TeamId) .Select(x => x.Raid.StartedAt.Date) .Where(date => observedDates.Contains(date)) .Distinct() .CountAsync(); var now = _serverTimeZoneInfo.TimeZoneNow(); var donationMatrix = await _context.GetDonationMatrixAsync(d => d.CharacterId == characterId, scope); var donations = donationMatrix.GetCreditForMonth(characterId, now); var returnDto = new LootListDto { ApprovedBy = null, Bonuses = PrioCalculator.GetListBonuses(scope, attendance, character.MemberStatus, donations).ToList(), CharacterId = character.Id, CharacterMemberStatus = character.MemberStatus, CharacterName = character.Name, MainSpec = list.MainSpec, OffSpec = list.OffSpec, Phase = list.Phase, Status = list.Status, TeamId = character.TeamId, Timestamp = list.Timestamp }; if (returnDto.TeamId.HasValue) { returnDto.TeamName = await _context.RaidTeams.AsNoTracking().Where(t => t.Id == returnDto.TeamId).Select(t => t.Name).FirstOrDefaultAsync(); } foreach (var entry in entries) { var bracket = brackets.Find(b => entry.Rank >= b.MinRank && entry.Rank <= b.MaxRank); Debug.Assert(bracket is not null); returnDto.Entries.Add(new LootListEntryDto { Bracket = bracket.Index, BracketAllowsOffspec = bracket.AllowOffspec, BracketAllowsTypeDuplicates = bracket.AllowTypeDuplicates, Id = entry.Id, Rank = entry.Rank }); } return(CreatedAtAction(nameof(Get), new { characterId = character.Id, phase }, returnDto)); }
private void TrackListStatusChange(CharacterLootList list, [CallerMemberName] string method = null !) { TrackListStatusChange(list.CharacterId.ToString(), list.Phase.ToString(), list.Status.ToString(), method); }