diff --git a/Api/Controllers/v1/ZombieSiegeParticipantsController.cs b/Api/Controllers/v1/ZombieSiegeParticipantsController.cs new file mode 100644 index 0000000..a62f706 --- /dev/null +++ b/Api/Controllers/v1/ZombieSiegeParticipantsController.cs @@ -0,0 +1,108 @@ +using Application.DataTransferObjects.ZombieSiegeParticipant; +using Application.Errors; +using Application.Interfaces; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Api.Controllers.v1 +{ + [Route("api/v{version:apiVersion}/[controller]")] + [ApiController] + [ApiVersion("1.0")] + [Authorize] + public class ZombieSiegeParticipantsController(IZombieSiegeParticipantRepository zombieSiegeParticipantRepository, ILogger logger) : ControllerBase + { + [HttpGet("{zombieSiegeParticipantId:guid}")] + public async Task> GetZombieSiegeParticipant( + Guid zombieSiegeParticipantId, CancellationToken cancellationToken) + { + try + { + var zombieSiegeParticipantResult = + await zombieSiegeParticipantRepository.GetZombieSiegeParticipantAsync(zombieSiegeParticipantId, + cancellationToken); + + return zombieSiegeParticipantResult.IsFailure + ? BadRequest(zombieSiegeParticipantResult.Error) + : Ok(zombieSiegeParticipantResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("Player/{playerId:guid}")] + public async Task>> GetPlayerZombieSiegeParticipants(Guid playerId, [FromQuery] int last, + CancellationToken cancellationToken) + { + try + { + var playerZombieSiegeParticipantsResult = + await zombieSiegeParticipantRepository.GetPlayerZombieSiegeParticipantsAsync(playerId, last, + cancellationToken); + + return playerZombieSiegeParticipantsResult.IsFailure + ? BadRequest(playerZombieSiegeParticipantsResult.Error) + : Ok(playerZombieSiegeParticipantsResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + public async Task> InsertZombieSiegeParticipants( + List createZombieSiegeParticipants, CancellationToken cancellationToken) + { + try + { + if (!ModelState.IsValid) return UnprocessableEntity(ModelState); + + var createResult = + await zombieSiegeParticipantRepository.InsertZombieSiegeParticipantsAsync( + createZombieSiegeParticipants, cancellationToken); + + return createResult.IsFailure + ? BadRequest(createResult.Error) + : Ok(createResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut("{zombieSiegeParticipantId:guid}")] + public async Task> UpdateZombieSiegeParticipant( + Guid zombieSiegeParticipantId, UpdateZombieSiegeParticipantDto updateZombieSiegeParticipant, + CancellationToken cancellationToken) + { + try + { + if (!ModelState.IsValid) return UnprocessableEntity(ModelState); + + if (zombieSiegeParticipantId != updateZombieSiegeParticipant.Id) + return Conflict(ZombieSiegeParticipantErrors.IdConflict); + + var updateResult = + await zombieSiegeParticipantRepository.UpdateZombieSiegeParticipantAsync( + updateZombieSiegeParticipant, cancellationToken); + + return updateResult.IsFailure + ? BadRequest(updateResult.Error) + : Ok(updateResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + } +} diff --git a/Api/Controllers/v1/ZombieSiegesController.cs b/Api/Controllers/v1/ZombieSiegesController.cs new file mode 100644 index 0000000..17e84ff --- /dev/null +++ b/Api/Controllers/v1/ZombieSiegesController.cs @@ -0,0 +1,143 @@ +using Application.DataTransferObjects.ZombieSiege; +using Application.Errors; +using Application.Interfaces; +using Asp.Versioning; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Api.Controllers.v1 +{ + [Route("api/v{version:apiVersion}/[controller]")] + [ApiController] + [ApiVersion("1.0")] + [Authorize] + public class ZombieSiegesController(IZombieSiegeRepository zombieSiegeRepository, ILogger logger, IClaimTypeService claimTypeService) : ControllerBase + { + [HttpGet("{zombieSiegeId:guid}")] + public async Task> GetZombieSiege(Guid zombieSiegeId, + CancellationToken cancellationToken) + { + try + { + var zombieSiegeResult = + await zombieSiegeRepository.GetZombieSiegeAsync(zombieSiegeId, cancellationToken); + + return zombieSiegeResult.IsFailure + ? BadRequest(zombieSiegeResult.Error) + : Ok(zombieSiegeResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("Alliance/{allianceId:guid}")] + public async Task>> GetAllianceZombieSieges(Guid allianceId, [FromQuery] int take, + CancellationToken cancellationToken) + { + try + { + var allianceZombieSiegesResult = + await zombieSiegeRepository.GetAllianceZombieSiegesAsync(allianceId, take, cancellationToken); + + if (allianceZombieSiegesResult.IsFailure) return BadRequest(allianceZombieSiegesResult.Error); + + return allianceZombieSiegesResult.Value.Count > 0 + ? Ok(allianceZombieSiegesResult.Value) + : NoContent(); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("[action]/{zombieSiegeId:guid}")] + public async Task> GetZombieSiegeDetail(Guid zombieSiegeId, + CancellationToken cancellationToken) + { + try + { + var zombieSiegeDetailResult = + await zombieSiegeRepository.GetZombieSiegeDetailAsync(zombieSiegeId, cancellationToken); + + return zombieSiegeDetailResult.IsFailure + ? BadRequest(zombieSiegeDetailResult.Error) + : Ok(zombieSiegeDetailResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + public async Task> CreateZombieSiege(CreateZombieSiegeDto createZombieSiegeDto, + CancellationToken cancellationToken) + { + try + { + if (!ModelState.IsValid) return UnprocessableEntity(ModelState); + + var createResult = + await zombieSiegeRepository.CreateZombieSiegeAsync(createZombieSiegeDto, claimTypeService.GetFullName(User), cancellationToken); + + return createResult.IsFailure + ? BadRequest(createResult.Error) + : CreatedAtAction(nameof(GetZombieSiege), + new { zombieSiegeId = createResult.Value.Id }, createResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut("{zombieSiegeId:guid}")] + public async Task> UpdateZombieSiege(Guid zombieSiegeId, UpdateZombieSiegeDto updateZombieSiegeDto, + CancellationToken cancellationToken) + { + try + { + if (!ModelState.IsValid) return UnprocessableEntity(ModelState); + + if (zombieSiegeId != updateZombieSiegeDto.Id) return Conflict(ZombieSiegeErrors.IdConflict); + + var updateResult = await zombieSiegeRepository.UpdateZombieSiegeAsync(updateZombieSiegeDto, + claimTypeService.GetFullName(User), cancellationToken); + + return updateResult.IsFailure + ? BadRequest(updateResult.Error) + : Ok(updateResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{zombieSiegeId:guid}")] + public async Task> DeleteZombieSiege(Guid zombieSiegeId, CancellationToken cancellationToken) + { + try + { + var deleteResult = await zombieSiegeRepository.DeleteZombieSiegeAsync(zombieSiegeId, cancellationToken); + + return deleteResult.IsFailure + ? BadRequest(deleteResult.Error) + : Ok(deleteResult.Value); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + } +} diff --git a/Application/Application.csproj b/Application/Application.csproj index e65ee66..c83acf7 100644 --- a/Application/Application.csproj +++ b/Application/Application.csproj @@ -11,6 +11,7 @@ + diff --git a/Application/ApplicationDependencyInjection.cs b/Application/ApplicationDependencyInjection.cs index 9521342..35d62ac 100644 --- a/Application/ApplicationDependencyInjection.cs +++ b/Application/ApplicationDependencyInjection.cs @@ -28,6 +28,8 @@ public static class ApplicationDependencyInjection services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); + services.AddScoped(); services.AddTransient(); diff --git a/Application/DataTransferObjects/ZombieSiege/CreateZombieSiegeDto.cs b/Application/DataTransferObjects/ZombieSiege/CreateZombieSiegeDto.cs new file mode 100644 index 0000000..f664115 --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiege/CreateZombieSiegeDto.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace Application.DataTransferObjects.ZombieSiege; + +public class CreateZombieSiegeDto +{ + [Required] + public Guid AllianceId { get; set; } + + [Required] + public int AllianceSize { get; set; } + + [Required] + public int Level { get; set; } + + [Required] + public required string EventDate { get; set; } +} \ No newline at end of file diff --git a/Application/DataTransferObjects/ZombieSiege/UpdateZombieSiegeDto.cs b/Application/DataTransferObjects/ZombieSiege/UpdateZombieSiegeDto.cs new file mode 100644 index 0000000..170b2dc --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiege/UpdateZombieSiegeDto.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; + +namespace Application.DataTransferObjects.ZombieSiege; + +public class UpdateZombieSiegeDto +{ + [Required] + public Guid Id { get; set; } + + [Required] + public Guid AllianceId { get; set; } + + [Required] + public int AllianceSize { get; set; } + + [Required] + public int Level { get; set; } + + [Required] + public required string EventDate { get; set; } +} \ No newline at end of file diff --git a/Application/DataTransferObjects/ZombieSiege/ZombieSiegeDetailDto.cs b/Application/DataTransferObjects/ZombieSiege/ZombieSiegeDetailDto.cs new file mode 100644 index 0000000..52779ee --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiege/ZombieSiegeDetailDto.cs @@ -0,0 +1,8 @@ +using Application.DataTransferObjects.ZombieSiegeParticipant; + +namespace Application.DataTransferObjects.ZombieSiege; + +public class ZombieSiegeDetailDto : ZombieSiegeDto +{ + public ICollection ZombieSiegeParticipants { get; set; } = []; +} \ No newline at end of file diff --git a/Application/DataTransferObjects/ZombieSiege/ZombieSiegeDto.cs b/Application/DataTransferObjects/ZombieSiege/ZombieSiegeDto.cs new file mode 100644 index 0000000..80870a1 --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiege/ZombieSiegeDto.cs @@ -0,0 +1,22 @@ +namespace Application.DataTransferObjects.ZombieSiege; + +public class ZombieSiegeDto +{ + public Guid Id { get; set; } + + public int Level { get; set; } + + public int TotalLevel20Players { get; set; } + + public Guid AllianceId { get; set; } + + public DateTime EventDate { get; set; } + + public required string CreatedBy { get; set; } + + public DateTime? ModifiedOn { get; set; } + + public string? ModifiedBy { get; set; } + + public int AllianceSize { get; set; } +} \ No newline at end of file diff --git a/Application/DataTransferObjects/ZombieSiegeParticipant/CreateZombieSiegeParticipantDto.cs b/Application/DataTransferObjects/ZombieSiegeParticipant/CreateZombieSiegeParticipantDto.cs new file mode 100644 index 0000000..fa5d244 --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiegeParticipant/CreateZombieSiegeParticipantDto.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace Application.DataTransferObjects.ZombieSiegeParticipant; + +public class CreateZombieSiegeParticipantDto +{ + [Required] + public Guid PlayerId { get; set; } + + [Required] + public Guid ZombieSiegeId { get; set; } + + [Required] + public int SurvivedWaves { get; set; } +} \ No newline at end of file diff --git a/Application/DataTransferObjects/ZombieSiegeParticipant/UpdateZombieSiegeParticipantDto.cs b/Application/DataTransferObjects/ZombieSiegeParticipant/UpdateZombieSiegeParticipantDto.cs new file mode 100644 index 0000000..d16a11c --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiegeParticipant/UpdateZombieSiegeParticipantDto.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; + +namespace Application.DataTransferObjects.ZombieSiegeParticipant; + +public class UpdateZombieSiegeParticipantDto +{ + [Required] + public Guid Id { get; set; } + + [Required] + public Guid PlayerId { get; set; } + + [Required] + public Guid ZombieSiegeId { get; set; } + + [Required] + public int SurvivedWaves { get; set; } +} \ No newline at end of file diff --git a/Application/DataTransferObjects/ZombieSiegeParticipant/ZombieSiegeParticipantDto.cs b/Application/DataTransferObjects/ZombieSiegeParticipant/ZombieSiegeParticipantDto.cs new file mode 100644 index 0000000..8de5422 --- /dev/null +++ b/Application/DataTransferObjects/ZombieSiegeParticipant/ZombieSiegeParticipantDto.cs @@ -0,0 +1,14 @@ +namespace Application.DataTransferObjects.ZombieSiegeParticipant; + +public class ZombieSiegeParticipantDto +{ + public Guid Id { get; set; } + + public Guid PlayerId { get; set; } + + public required string PlayerName { get; set; } + + public Guid ZombieSiegeId { get; set; } + + public int SurvivedWaves { get; set; } +} \ No newline at end of file diff --git a/Application/Errors/ZombieSiegeErrors.cs b/Application/Errors/ZombieSiegeErrors.cs new file mode 100644 index 0000000..3de4cf7 --- /dev/null +++ b/Application/Errors/ZombieSiegeErrors.cs @@ -0,0 +1,9 @@ +namespace Application.Errors; + +public static class ZombieSiegeErrors +{ + public static readonly Error NotFound = new("Error.ZombieSiege.NotFound", + "The zombie siege with the specified identifier was not found"); + + public static readonly Error IdConflict = new("Error.ZombieSiege.IdConflict", "There is a conflict with the id's"); +} \ No newline at end of file diff --git a/Application/Errors/ZombieSiegeParticipantErrors.cs b/Application/Errors/ZombieSiegeParticipantErrors.cs new file mode 100644 index 0000000..2853161 --- /dev/null +++ b/Application/Errors/ZombieSiegeParticipantErrors.cs @@ -0,0 +1,9 @@ +namespace Application.Errors; + +public static class ZombieSiegeParticipantErrors +{ + public static readonly Error NotFound = new("Error.ZombieSiegeParticipant.NotFound", + "The zombie siege participant with the specified identifier was not found"); + + public static readonly Error IdConflict = new("Error.ZombieSiegeParticipant.IdConflict", "There is a conflict with the id's"); +} \ No newline at end of file diff --git a/Application/Interfaces/IZombieSiegeParticipantRepository.cs b/Application/Interfaces/IZombieSiegeParticipantRepository.cs new file mode 100644 index 0000000..acedf74 --- /dev/null +++ b/Application/Interfaces/IZombieSiegeParticipantRepository.cs @@ -0,0 +1,15 @@ +using Application.Classes; +using Application.DataTransferObjects.ZombieSiegeParticipant; + +namespace Application.Interfaces; + +public interface IZombieSiegeParticipantRepository +{ + Task> GetZombieSiegeParticipantAsync(Guid zombieSiegeParticipantId, CancellationToken cancellationToken); + + Task> InsertZombieSiegeParticipantsAsync(List createZombieSiegeParticipants, CancellationToken cancellationToken); + + Task>> GetPlayerZombieSiegeParticipantsAsync(Guid playerId, int last, CancellationToken cancellationToken); + + Task> UpdateZombieSiegeParticipantAsync(UpdateZombieSiegeParticipantDto updateZombieSiegeParticipantDto, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Application/Interfaces/IZombieSiegeRepository.cs b/Application/Interfaces/IZombieSiegeRepository.cs new file mode 100644 index 0000000..eebb450 --- /dev/null +++ b/Application/Interfaces/IZombieSiegeRepository.cs @@ -0,0 +1,19 @@ +using Application.Classes; +using Application.DataTransferObjects.ZombieSiege; + +namespace Application.Interfaces; + +public interface IZombieSiegeRepository +{ + Task> GetZombieSiegeAsync(Guid zombieSiegeId, CancellationToken cancellationToken); + + Task> GetZombieSiegeDetailAsync(Guid zombieSiegeId, CancellationToken cancellationToken); + + Task>> GetAllianceZombieSiegesAsync(Guid allianceId, int take, CancellationToken cancellationToken); + + Task> CreateZombieSiegeAsync(CreateZombieSiegeDto createZombieSiegeDto, string createdBy, CancellationToken cancellationToken); + + Task> UpdateZombieSiegeAsync(UpdateZombieSiegeDto updateZombieSiegeDto, string modifiedBy, CancellationToken cancellationToken); + + Task> DeleteZombieSiegeAsync(Guid zombieSiegeId, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Application/Profiles/ZombieSiegeParticipantProfile.cs b/Application/Profiles/ZombieSiegeParticipantProfile.cs new file mode 100644 index 0000000..5365848 --- /dev/null +++ b/Application/Profiles/ZombieSiegeParticipantProfile.cs @@ -0,0 +1,19 @@ +using Application.DataTransferObjects.ZombieSiegeParticipant; +using AutoMapper; +using Database.Entities; + +namespace Application.Profiles; + +public class ZombieSiegeParticipantProfile : Profile +{ + public ZombieSiegeParticipantProfile() + { + CreateMap() + .ForMember(des => des.PlayerName, opt => opt.MapFrom(src => src.Player.PlayerName)); + + CreateMap() + .ForMember(des => des.Id, opt => opt.MapFrom(src => Guid.CreateVersion7())); + + CreateMap(); + } +} \ No newline at end of file diff --git a/Application/Profiles/ZombieSiegeProfile.cs b/Application/Profiles/ZombieSiegeProfile.cs new file mode 100644 index 0000000..d4ac486 --- /dev/null +++ b/Application/Profiles/ZombieSiegeProfile.cs @@ -0,0 +1,27 @@ +using Application.DataTransferObjects.ZombieSiege; +using AutoMapper; +using Database.Entities; + +namespace Application.Profiles; + +public class ZombieSiegeProfile : Profile +{ + public ZombieSiegeProfile() + { + CreateMap() + .ForMember(des => des.TotalLevel20Players, + opt => opt.MapFrom(src => src.ZombieSiegeParticipants.Count(p => p.SurvivedWaves == 20))); + + CreateMap() + .ForMember(des => des.TotalLevel20Players, + opt => opt.MapFrom(src => src.ZombieSiegeParticipants.Count(p => p.SurvivedWaves == 20))); + + CreateMap() + .ForMember(des => des.Id, opt => opt.MapFrom(src => Guid.CreateVersion7())) + .ForMember(des => des.EventDate, opt => opt.MapFrom(src => DateTime.Parse(src.EventDate))); + + CreateMap() + .ForMember(des => des.EventDate, opt => opt.MapFrom(src => DateTime.Parse(src.EventDate))) + .ForMember(des => des.ModifiedOn, opt => opt.MapFrom(src => DateTime.Now)); + } +} \ No newline at end of file diff --git a/Application/Repositories/PlayerRepository.cs b/Application/Repositories/PlayerRepository.cs index d971502..c6dff42 100644 --- a/Application/Repositories/PlayerRepository.cs +++ b/Application/Repositories/PlayerRepository.cs @@ -108,6 +108,12 @@ public class PlayerRepository(ApplicationContext context, IMapper mapper, ILogge if (vsDuels.Count > 0) context.MarshalGuardParticipants.RemoveRange(marshalGuards); + var zombieSieges = await context.ZombieSiegeParticipants + .Where(zombieSiege => zombieSiege.PlayerId == playerToDelete.Id) + .ToListAsync(cancellationToken); + + if (zombieSieges.Count > 0) context.ZombieSiegeParticipants.RemoveRange(zombieSieges); + context.Players.Remove(playerToDelete); try diff --git a/Application/Repositories/ZombieSiegeParticipantRepository.cs b/Application/Repositories/ZombieSiegeParticipantRepository.cs new file mode 100644 index 0000000..d4ca049 --- /dev/null +++ b/Application/Repositories/ZombieSiegeParticipantRepository.cs @@ -0,0 +1,83 @@ +using Application.Classes; +using Application.DataTransferObjects.ZombieSiegeParticipant; +using Application.Errors; +using Application.Interfaces; +using AutoMapper; +using AutoMapper.QueryableExtensions; +using Database; +using Database.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Application.Repositories; + +public class ZombieSiegeParticipantRepository(ApplicationContext context, IMapper mapper, ILogger logger) : IZombieSiegeParticipantRepository +{ + public async Task> GetZombieSiegeParticipantAsync(Guid zombieSiegeParticipantId, CancellationToken cancellationToken) + { + var zombieSiegeParticipantById = await context.ZombieSiegeParticipants + .ProjectTo(mapper.ConfigurationProvider) + .AsNoTracking() + .FirstOrDefaultAsync(zombieSiegeParticipant => zombieSiegeParticipant.Id == zombieSiegeParticipantId, + cancellationToken); + + return zombieSiegeParticipantById is null + ? Result.Failure(ZombieSiegeParticipantErrors.NotFound) + : Result.Success(zombieSiegeParticipantById); + } + + public async Task> InsertZombieSiegeParticipantsAsync(List createZombieSiegeParticipants, CancellationToken cancellationToken) + { + var zombieSiegeParticipants = mapper.Map>(createZombieSiegeParticipants); + + try + { + await context.ZombieSiegeParticipants.AddRangeAsync(zombieSiegeParticipants, cancellationToken); + await context.SaveChangesAsync(cancellationToken); + return Result.Success(true); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return Result.Failure(GeneralErrors.DatabaseError); + } + } + + public async Task>> GetPlayerZombieSiegeParticipantsAsync(Guid playerId, int last, CancellationToken cancellationToken) + { + var playerZombieSieges = await context.ZombieSiegeParticipants + .Where(zombieSiegeParticipant => zombieSiegeParticipant.PlayerId == playerId) + .OrderByDescending(zombieSiegeParticipant => zombieSiegeParticipant.ZombieSiege.EventDate) + .ProjectTo(mapper.ConfigurationProvider) + .Take(last) + .AsNoTracking() + .ToListAsync(cancellationToken); + + return Result.Success(playerZombieSieges); + } + + public async Task> UpdateZombieSiegeParticipantAsync(UpdateZombieSiegeParticipantDto updateZombieSiegeParticipantDto, + CancellationToken cancellationToken) + { + var zombieSiegeParticipantToUpdate = await context.ZombieSiegeParticipants + .FirstOrDefaultAsync( + zombieSiegeParticipant => zombieSiegeParticipant.Id == updateZombieSiegeParticipantDto.Id, + cancellationToken); + + if (zombieSiegeParticipantToUpdate is null) + return Result.Failure(ZombieSiegeErrors.NotFound); + + mapper.Map(updateZombieSiegeParticipantDto, zombieSiegeParticipantToUpdate); + + try + { + await context.SaveChangesAsync(cancellationToken); + return Result.Success(mapper.Map(zombieSiegeParticipantToUpdate)); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return Result.Failure(GeneralErrors.DatabaseError); + } + } +} \ No newline at end of file diff --git a/Application/Repositories/ZombieSiegeRepository.cs b/Application/Repositories/ZombieSiegeRepository.cs new file mode 100644 index 0000000..d507083 --- /dev/null +++ b/Application/Repositories/ZombieSiegeRepository.cs @@ -0,0 +1,116 @@ +using Application.Classes; +using Application.DataTransferObjects.ZombieSiege; +using Application.Errors; +using Application.Interfaces; +using AutoMapper; +using AutoMapper.QueryableExtensions; +using Database; +using Database.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace Application.Repositories; + +public class ZombieSiegeRepository(ApplicationContext context, IMapper mapper, ILogger logger) : IZombieSiegeRepository +{ + public async Task> GetZombieSiegeAsync(Guid zombieSiegeId, CancellationToken cancellationToken) + { + var zombieSiegeById = await context.ZombieSieges + .ProjectTo(mapper.ConfigurationProvider) + .AsNoTracking() + .FirstOrDefaultAsync(zombieSiege => zombieSiege.Id == zombieSiegeId, cancellationToken); + + return zombieSiegeById is null + ? Result.Failure(ZombieSiegeErrors.NotFound) + : Result.Success(zombieSiegeById); + } + + public async Task> GetZombieSiegeDetailAsync(Guid zombieSiegeId, CancellationToken cancellationToken) + { + var zombieSiegeDetail = await context.ZombieSieges + .ProjectTo(mapper.ConfigurationProvider) + .AsNoTracking() + .FirstOrDefaultAsync(zombieSiege => zombieSiege.Id == zombieSiegeId, cancellationToken); + + return zombieSiegeDetail is null + ? Result.Failure(ZombieSiegeErrors.NotFound) + : Result.Success(zombieSiegeDetail); + } + + public async Task>> GetAllianceZombieSiegesAsync(Guid allianceId, int take, CancellationToken cancellationToken) + { + var allianceZombieSieges = await context.ZombieSieges + .Where(zombieSiege => zombieSiege.AllianceId == allianceId) + .OrderByDescending(zombieSiege => zombieSiege.EventDate) + .ProjectTo(mapper.ConfigurationProvider) + .AsNoTracking() + .Take(take) + .ToListAsync(cancellationToken); + + return Result.Success(allianceZombieSieges); + } + + public async Task> CreateZombieSiegeAsync(CreateZombieSiegeDto createZombieSiegeDto, string createdBy, + CancellationToken cancellationToken) + { + var newZombieSiege = mapper.Map(createZombieSiegeDto); + newZombieSiege.CreatedBy = createdBy; + + try + { + await context.ZombieSieges.AddAsync(newZombieSiege, cancellationToken); + await context.SaveChangesAsync(cancellationToken); + + return Result.Success(mapper.Map(newZombieSiege)); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return Result.Failure(GeneralErrors.DatabaseError); + } + } + + public async Task> UpdateZombieSiegeAsync(UpdateZombieSiegeDto updateZombieSiegeDto, string modifiedBy, + CancellationToken cancellationToken) + { + var zombieSiegeToUpdate = await context.ZombieSieges + .FirstOrDefaultAsync(zombieSiege => zombieSiege.Id == updateZombieSiegeDto.Id, cancellationToken); + + if (zombieSiegeToUpdate is null) return Result.Failure(ZombieSiegeErrors.NotFound); + + mapper.Map(updateZombieSiegeDto, zombieSiegeToUpdate); + zombieSiegeToUpdate.ModifiedBy = modifiedBy; + + try + { + await context.SaveChangesAsync(cancellationToken); + return Result.Success(mapper.Map(zombieSiegeToUpdate)); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return Result.Failure(GeneralErrors.DatabaseError); + } + + } + + public async Task> DeleteZombieSiegeAsync(Guid zombieSiegeId, CancellationToken cancellationToken) + { + var zombieSiegeToDelete = await context.ZombieSieges + .FirstOrDefaultAsync(zombieSiege => zombieSiege.Id == zombieSiegeId, cancellationToken); + + if (zombieSiegeToDelete is null) return Result.Failure(ZombieSiegeErrors.NotFound); + + try + { + context.ZombieSieges.Remove(zombieSiegeToDelete); + await context.SaveChangesAsync(cancellationToken); + return Result.Success(true); + } + catch (Exception e) + { + logger.LogError(e, e.Message); + return Result.Failure(GeneralErrors.DatabaseError); + } + } +} \ No newline at end of file diff --git a/Database/ApplicationContext.cs b/Database/ApplicationContext.cs index 3a03ff6..d83ac61 100644 --- a/Database/ApplicationContext.cs +++ b/Database/ApplicationContext.cs @@ -36,6 +36,10 @@ public class ApplicationContext(DbContextOptions options) : public DbSet DesertStormParticipants { get; set; } + public DbSet ZombieSieges { get; set; } + + public DbSet ZombieSiegeParticipants { get; set; } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); diff --git a/Database/Configurations/ZombieSiegeConfiguration.cs b/Database/Configurations/ZombieSiegeConfiguration.cs new file mode 100644 index 0000000..1080a27 --- /dev/null +++ b/Database/Configurations/ZombieSiegeConfiguration.cs @@ -0,0 +1,26 @@ +using Database.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Database.Configurations; + +public class ZombieSiegeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(zombieSiege => zombieSiege.Id); + builder.Property(zombieSiege => zombieSiege.Id).ValueGeneratedNever(); + + builder.Property(zombieSiege => zombieSiege.EventDate).IsRequired(); + builder.Property(zombieSiege => zombieSiege.AllianceSize).IsRequired(); + builder.Property(zombieSiege => zombieSiege.CreatedBy).IsRequired().HasMaxLength(150); + builder.Property(zombieSiege => zombieSiege.Level).IsRequired(); + builder.Property(zombieSiege => zombieSiege.ModifiedOn).IsRequired(false); + builder.Property(zombieSiege => zombieSiege.ModifiedBy).IsRequired(false).HasMaxLength(150); + + builder.HasOne(zombieSiege => zombieSiege.Alliance) + .WithMany(alliance => alliance.ZombieSieges) + .HasForeignKey(zombieSiege => zombieSiege.AllianceId) + .OnDelete(DeleteBehavior.Cascade); + } +} \ No newline at end of file diff --git a/Database/Configurations/ZombieSiegeParticipantConfiguration.cs b/Database/Configurations/ZombieSiegeParticipantConfiguration.cs new file mode 100644 index 0000000..3bc2c61 --- /dev/null +++ b/Database/Configurations/ZombieSiegeParticipantConfiguration.cs @@ -0,0 +1,28 @@ +using Database.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Database.Configurations; + +public class ZombieSiegeParticipantConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(zombieSiegeParticipant => zombieSiegeParticipant.Id); + builder.Property(zombieSiegeParticipant => zombieSiegeParticipant.Id).ValueGeneratedNever(); + + builder.Property(zombieSiegeParticipant => zombieSiegeParticipant.PlayerId).IsRequired(); + builder.Property(zombieSiegeParticipant => zombieSiegeParticipant.ZombieSiegeId).IsRequired(); + builder.Property(zombieSiegeParticipant => zombieSiegeParticipant.SurvivedWaves).IsRequired(); + + builder.HasOne(zombieSiegeParticipant => zombieSiegeParticipant.Player) + .WithMany(player => player.ZombieSiegeParticipants) + .HasForeignKey(zombieSiegeParticipant => zombieSiegeParticipant.PlayerId) + .OnDelete(DeleteBehavior.Restrict); + + builder.HasOne(zombieSiegeParticipant => zombieSiegeParticipant.ZombieSiege) + .WithMany(zombieSiege => zombieSiege.ZombieSiegeParticipants) + .HasForeignKey(zombieSiegeParticipant => zombieSiegeParticipant.ZombieSiegeId) + .OnDelete(DeleteBehavior.Cascade); + } +} \ No newline at end of file diff --git a/Database/Entities/Alliance.cs b/Database/Entities/Alliance.cs index 8bf66f7..c45e3f3 100644 --- a/Database/Entities/Alliance.cs +++ b/Database/Entities/Alliance.cs @@ -25,4 +25,6 @@ public class Alliance : BaseEntity public ICollection MarshalGuards { get; set; } = []; public ICollection VsDuels { get; set; } = []; + + public ICollection ZombieSieges { get; set; } = []; } \ No newline at end of file diff --git a/Database/Entities/Player.cs b/Database/Entities/Player.cs index a6d4f63..5f319b6 100644 --- a/Database/Entities/Player.cs +++ b/Database/Entities/Player.cs @@ -33,4 +33,6 @@ public class Player : BaseEntity public ICollection Notes { get; set; } = []; public ICollection CustomEventParticipants { get; set; } = []; + + public ICollection ZombieSiegeParticipants { get; set; } = []; } \ No newline at end of file diff --git a/Database/Entities/ZombieSiege.cs b/Database/Entities/ZombieSiege.cs new file mode 100644 index 0000000..6c6af4f --- /dev/null +++ b/Database/Entities/ZombieSiege.cs @@ -0,0 +1,22 @@ +namespace Database.Entities; + +public class ZombieSiege : BaseEntity +{ + public int Level { get; set; } + + public Guid AllianceId { get; set; } + + public Alliance Alliance { get; set; } = null!; + + public DateTime EventDate { get; set; } + + public required string CreatedBy { get; set; } + + public DateTime? ModifiedOn { get; set; } + + public string? ModifiedBy { get; set; } + + public int AllianceSize { get; set; } + + public ICollection ZombieSiegeParticipants { get; set; } = []; +} \ No newline at end of file diff --git a/Database/Entities/ZombieSiegeParticipant.cs b/Database/Entities/ZombieSiegeParticipant.cs new file mode 100644 index 0000000..8b63c14 --- /dev/null +++ b/Database/Entities/ZombieSiegeParticipant.cs @@ -0,0 +1,14 @@ +namespace Database.Entities; + +public class ZombieSiegeParticipant : BaseEntity +{ + public Player Player { get; set; } = null!; + + public Guid PlayerId { get; set; } + + public Guid ZombieSiegeId { get; set; } + + public ZombieSiege ZombieSiege { get; set; } = null!; + + public int SurvivedWaves { get; set; } +} \ No newline at end of file diff --git a/Database/Migrations/20241126121120_AddZombieSiege.Designer.cs b/Database/Migrations/20241126121120_AddZombieSiege.Designer.cs new file mode 100644 index 0000000..670cffe --- /dev/null +++ b/Database/Migrations/20241126121120_AddZombieSiege.Designer.cs @@ -0,0 +1,1106 @@ +// +using System; +using Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Database.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20241126121120_AddZombieSiege")] + partial class AddZombieSiege + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("dbo") + .HasAnnotation("ProductVersion", "9.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Database.Entities.Admonition", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reason") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId"); + + b.ToTable("Admonitions", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.Alliance", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Abbreviation") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("nvarchar(5)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Server") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Alliances", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.CustomEvent", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("IsParticipationEvent") + .HasColumnType("bit"); + + b.Property("IsPointsEvent") + .HasColumnType("bit"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.ToTable("CustomEvents", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.CustomEventParticipant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AchievedPoints") + .HasColumnType("bigint"); + + b.Property("CustomEventId") + .HasColumnType("uniqueidentifier"); + + b.Property("Participated") + .HasColumnType("bit"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("CustomEventId"); + + b.HasIndex("PlayerId"); + + b.ToTable("CustomEventParticipants", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.DesertStorm", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("OpponentName") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("OpponentServer") + .HasColumnType("int"); + + b.Property("OpposingParticipants") + .HasColumnType("int"); + + b.Property("Won") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.ToTable("DesertStorms", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.DesertStormParticipant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("DesertStormId") + .HasColumnType("uniqueidentifier"); + + b.Property("Participated") + .HasColumnType("bit"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.Property("Registered") + .HasColumnType("bit"); + + b.Property("StartPlayer") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("DesertStormId"); + + b.HasIndex("PlayerId"); + + b.ToTable("DesertStormParticipants", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.MarshalGuard", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceSize") + .HasColumnType("int"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("RewardPhase") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.ToTable("MarshalGuards", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.MarshalGuardParticipant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("MarshalGuardId") + .HasColumnType("uniqueidentifier"); + + b.Property("Participated") + .HasColumnType("bit"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("MarshalGuardId"); + + b.HasIndex("PlayerId"); + + b.ToTable("MarshalGuardParticipants", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.Note", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.Property("PlayerNote") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId"); + + b.ToTable("Notes", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.Player", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("CreatedOn") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("PlayerName") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("RankId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.HasIndex("RankId"); + + b.ToTable("Players", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.Rank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("nvarchar(2)"); + + b.HasKey("Id"); + + b.ToTable("Ranks", "dbo"); + + b.HasData( + new + { + Id = new Guid("b1c10a1c-5cf3-4e22-9fc1-d9b165b85dd3"), + Name = "R5" + }, + new + { + Id = new Guid("0fc2f68a-0a4d-4922-981e-c624e4c39024"), + Name = "R4" + }, + new + { + Id = new Guid("4970e1f5-f7f5-43e8-88cc-7f8fc4075418"), + Name = "R3" + }, + new + { + Id = new Guid("d8d0c587-f269-45ff-b13e-4631298bf0af"), + Name = "R2" + }, + new + { + Id = new Guid("326edef0-5074-43a5-9db9-edc71221a0f7"), + Name = "R1" + }); + }); + + modelBuilder.Entity("Database.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("PlayerName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("SecurityStamp") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("Users", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.VsDuel", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.Property("OpponentName") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("OpponentPower") + .HasColumnType("bigint"); + + b.Property("OpponentServer") + .HasColumnType("int"); + + b.Property("OpponentSize") + .HasColumnType("int"); + + b.Property("Won") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.ToTable("VsDuels", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.VsDuelParticipant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.Property("VsDuelId") + .HasColumnType("uniqueidentifier"); + + b.Property("WeeklyPoints") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId"); + + b.HasIndex("VsDuelId"); + + b.ToTable("VsDuelParticipants", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiege", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceSize") + .HasColumnType("int"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.ToTable("ZombieSieges", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiegeParticipant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.Property("SurvivedWaves") + .HasColumnType("int"); + + b.Property("ZombieSiegeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId"); + + b.HasIndex("ZombieSiegeId"); + + b.ToTable("ZombieSiegeParticipants", "dbo"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter("[NormalizedName] IS NOT NULL"); + + b.ToTable("Roles", "dbo"); + + b.HasData( + new + { + Id = new Guid("d8b9f882-95f0-4ba0-80ed-9c22c27ac88a"), + Name = "SystemAdministrator", + NormalizedName = "SYSTEMADMINISTRATOR" + }, + new + { + Id = new Guid("47de05ba-ff1e-46b6-9995-269084006c24"), + Name = "Administrator", + NormalizedName = "ADMINISTRATOR" + }, + new + { + Id = new Guid("5cc27946-5601-4a25-b9a9-75b8a11c0cf4"), + Name = "User", + NormalizedName = "USER" + }, + new + { + Id = new Guid("207bb0a3-ad50-49bb-bc41-b266fce66529"), + Name = "ReadOnly", + NormalizedName = "READONLY" + }); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "dbo"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("nvarchar(max)"); + + b.Property("ClaimValue") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims", "dbo"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasColumnType("nvarchar(max)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins", "dbo"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "dbo"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserTokens", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.Admonition", b => + { + b.HasOne("Database.Entities.Player", "Player") + .WithMany("Admonitions") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Database.Entities.CustomEvent", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("CustomEvents") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.CustomEventParticipant", b => + { + b.HasOne("Database.Entities.CustomEvent", "CustomEvent") + .WithMany("CustomEventParticipants") + .HasForeignKey("CustomEventId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Database.Entities.Player", "Player") + .WithMany("CustomEventParticipants") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CustomEvent"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Database.Entities.DesertStorm", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("DesertStorms") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.DesertStormParticipant", b => + { + b.HasOne("Database.Entities.DesertStorm", "DesertStorm") + .WithMany("DesertStormParticipants") + .HasForeignKey("DesertStormId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Database.Entities.Player", "Player") + .WithMany("DesertStormParticipants") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DesertStorm"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Database.Entities.MarshalGuard", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("MarshalGuards") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.MarshalGuardParticipant", b => + { + b.HasOne("Database.Entities.MarshalGuard", "MarshalGuard") + .WithMany("MarshalGuardParticipants") + .HasForeignKey("MarshalGuardId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Database.Entities.Player", "Player") + .WithMany("MarshalGuardParticipants") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("MarshalGuard"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Database.Entities.Note", b => + { + b.HasOne("Database.Entities.Player", "Player") + .WithMany("Notes") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Database.Entities.Player", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("Players") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Database.Entities.Rank", "Rank") + .WithMany("Players") + .HasForeignKey("RankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Database.Entities.User", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("Users") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.VsDuel", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("VsDuels") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.VsDuelParticipant", b => + { + b.HasOne("Database.Entities.Player", "Player") + .WithMany("VsDuelParticipants") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Database.Entities.VsDuel", "VsDuel") + .WithMany("VsDuelParticipants") + .HasForeignKey("VsDuelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("VsDuel"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiege", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("ZombieSieges") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiegeParticipant", b => + { + b.HasOne("Database.Entities.Player", "Player") + .WithMany("ZombieSiegeParticipants") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Database.Entities.ZombieSiege", "ZombieSiege") + .WithMany("ZombieSiegeParticipants") + .HasForeignKey("ZombieSiegeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("ZombieSiege"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Database.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Database.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Database.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Database.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Database.Entities.Alliance", b => + { + b.Navigation("CustomEvents"); + + b.Navigation("DesertStorms"); + + b.Navigation("MarshalGuards"); + + b.Navigation("Players"); + + b.Navigation("Users"); + + b.Navigation("VsDuels"); + + b.Navigation("ZombieSieges"); + }); + + modelBuilder.Entity("Database.Entities.CustomEvent", b => + { + b.Navigation("CustomEventParticipants"); + }); + + modelBuilder.Entity("Database.Entities.DesertStorm", b => + { + b.Navigation("DesertStormParticipants"); + }); + + modelBuilder.Entity("Database.Entities.MarshalGuard", b => + { + b.Navigation("MarshalGuardParticipants"); + }); + + modelBuilder.Entity("Database.Entities.Player", b => + { + b.Navigation("Admonitions"); + + b.Navigation("CustomEventParticipants"); + + b.Navigation("DesertStormParticipants"); + + b.Navigation("MarshalGuardParticipants"); + + b.Navigation("Notes"); + + b.Navigation("VsDuelParticipants"); + + b.Navigation("ZombieSiegeParticipants"); + }); + + modelBuilder.Entity("Database.Entities.Rank", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Database.Entities.VsDuel", b => + { + b.Navigation("VsDuelParticipants"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiege", b => + { + b.Navigation("ZombieSiegeParticipants"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Database/Migrations/20241126121120_AddZombieSiege.cs b/Database/Migrations/20241126121120_AddZombieSiege.cs new file mode 100644 index 0000000..99bae23 --- /dev/null +++ b/Database/Migrations/20241126121120_AddZombieSiege.cs @@ -0,0 +1,160 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Database.Migrations +{ + /// + public partial class AddZombieSiege : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "CreatedOn", + schema: "dbo", + table: "Players", + type: "datetime2", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldDefaultValue: new DateTime(2024, 11, 20, 10, 20, 41, 226, DateTimeKind.Local).AddTicks(9868)); + + migrationBuilder.AlterColumn( + name: "CreatedOn", + schema: "dbo", + table: "Notes", + type: "datetime2", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldDefaultValue: new DateTime(2024, 11, 20, 10, 20, 41, 225, DateTimeKind.Local).AddTicks(5440)); + + migrationBuilder.AlterColumn( + name: "CreatedOn", + schema: "dbo", + table: "Alliances", + type: "datetime2", + nullable: false, + oldClrType: typeof(DateTime), + oldType: "datetime2", + oldDefaultValue: new DateTime(2024, 11, 20, 10, 20, 41, 211, DateTimeKind.Local).AddTicks(7279)); + + migrationBuilder.CreateTable( + name: "ZombieSieges", + schema: "dbo", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + Level = table.Column(type: "int", nullable: false), + AllianceId = table.Column(type: "uniqueidentifier", nullable: false), + EventDate = table.Column(type: "datetime2", nullable: false), + CreatedBy = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + ModifiedOn = table.Column(type: "datetime2", nullable: true), + ModifiedBy = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true), + AllianceSize = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ZombieSieges", x => x.Id); + table.ForeignKey( + name: "FK_ZombieSieges_Alliances_AllianceId", + column: x => x.AllianceId, + principalSchema: "dbo", + principalTable: "Alliances", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ZombieSiegeParticipants", + schema: "dbo", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + PlayerId = table.Column(type: "uniqueidentifier", nullable: false), + ZombieSiegeId = table.Column(type: "uniqueidentifier", nullable: false), + SurvivedWaves = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ZombieSiegeParticipants", x => x.Id); + table.ForeignKey( + name: "FK_ZombieSiegeParticipants_Players_PlayerId", + column: x => x.PlayerId, + principalSchema: "dbo", + principalTable: "Players", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_ZombieSiegeParticipants_ZombieSieges_ZombieSiegeId", + column: x => x.ZombieSiegeId, + principalSchema: "dbo", + principalTable: "ZombieSieges", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_ZombieSiegeParticipants_PlayerId", + schema: "dbo", + table: "ZombieSiegeParticipants", + column: "PlayerId"); + + migrationBuilder.CreateIndex( + name: "IX_ZombieSiegeParticipants_ZombieSiegeId", + schema: "dbo", + table: "ZombieSiegeParticipants", + column: "ZombieSiegeId"); + + migrationBuilder.CreateIndex( + name: "IX_ZombieSieges_AllianceId", + schema: "dbo", + table: "ZombieSieges", + column: "AllianceId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ZombieSiegeParticipants", + schema: "dbo"); + + migrationBuilder.DropTable( + name: "ZombieSieges", + schema: "dbo"); + + migrationBuilder.AlterColumn( + name: "CreatedOn", + schema: "dbo", + table: "Players", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(2024, 11, 20, 10, 20, 41, 226, DateTimeKind.Local).AddTicks(9868), + oldClrType: typeof(DateTime), + oldType: "datetime2"); + + migrationBuilder.AlterColumn( + name: "CreatedOn", + schema: "dbo", + table: "Notes", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(2024, 11, 20, 10, 20, 41, 225, DateTimeKind.Local).AddTicks(5440), + oldClrType: typeof(DateTime), + oldType: "datetime2"); + + migrationBuilder.AlterColumn( + name: "CreatedOn", + schema: "dbo", + table: "Alliances", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(2024, 11, 20, 10, 20, 41, 211, DateTimeKind.Local).AddTicks(7279), + oldClrType: typeof(DateTime), + oldType: "datetime2"); + } + } +} diff --git a/Database/Migrations/ApplicationContextModelSnapshot.cs b/Database/Migrations/ApplicationContextModelSnapshot.cs index 7eae5cb..5a613dd 100644 --- a/Database/Migrations/ApplicationContextModelSnapshot.cs +++ b/Database/Migrations/ApplicationContextModelSnapshot.cs @@ -26,7 +26,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.Admonition", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("CreatedBy") @@ -62,7 +61,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.Alliance", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("Abbreviation") @@ -71,9 +69,7 @@ namespace Database.Migrations .HasColumnType("nvarchar(5)"); b.Property("CreatedOn") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValue(new DateTime(2024, 11, 20, 10, 20, 41, 211, DateTimeKind.Local).AddTicks(7279)); + .HasColumnType("datetime2"); b.Property("ModifiedBy") .HasMaxLength(150) @@ -98,7 +94,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.CustomEvent", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AllianceId") @@ -145,7 +140,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.CustomEventParticipant", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AchievedPoints") @@ -172,7 +166,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.DesertStorm", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AllianceId") @@ -217,7 +210,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.DesertStormParticipant", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("DesertStormId") @@ -247,7 +239,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.MarshalGuard", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AllianceId") @@ -287,7 +278,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.MarshalGuardParticipant", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("MarshalGuardId") @@ -311,7 +301,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.Note", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("CreatedBy") @@ -320,9 +309,7 @@ namespace Database.Migrations .HasColumnType("nvarchar(150)"); b.Property("CreatedOn") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValue(new DateTime(2024, 11, 20, 10, 20, 41, 225, DateTimeKind.Local).AddTicks(5440)); + .HasColumnType("datetime2"); b.Property("ModifiedBy") .HasMaxLength(150) @@ -349,7 +336,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.Player", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AllianceId") @@ -361,9 +347,7 @@ namespace Database.Migrations .HasColumnType("nvarchar(150)"); b.Property("CreatedOn") - .ValueGeneratedOnAdd() - .HasColumnType("datetime2") - .HasDefaultValue(new DateTime(2024, 11, 20, 10, 20, 41, 226, DateTimeKind.Local).AddTicks(9868)); + .HasColumnType("datetime2"); b.Property("Level") .HasColumnType("int"); @@ -514,7 +498,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.VsDuel", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("AllianceId") @@ -562,7 +545,6 @@ namespace Database.Migrations modelBuilder.Entity("Database.Entities.VsDuelParticipant", b => { b.Property("Id") - .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); b.Property("PlayerId") @@ -583,6 +565,65 @@ namespace Database.Migrations b.ToTable("VsDuelParticipants", "dbo"); }); + modelBuilder.Entity("Database.Entities.ZombieSiege", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceId") + .HasColumnType("uniqueidentifier"); + + b.Property("AllianceSize") + .HasColumnType("int"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("EventDate") + .HasColumnType("datetime2"); + + b.Property("Level") + .HasColumnType("int"); + + b.Property("ModifiedBy") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.Property("ModifiedOn") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("AllianceId"); + + b.ToTable("ZombieSieges", "dbo"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiegeParticipant", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("PlayerId") + .HasColumnType("uniqueidentifier"); + + b.Property("SurvivedWaves") + .HasColumnType("int"); + + b.Property("ZombieSiegeId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("PlayerId"); + + b.HasIndex("ZombieSiegeId"); + + b.ToTable("ZombieSiegeParticipants", "dbo"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") @@ -912,6 +953,36 @@ namespace Database.Migrations b.Navigation("VsDuel"); }); + modelBuilder.Entity("Database.Entities.ZombieSiege", b => + { + b.HasOne("Database.Entities.Alliance", "Alliance") + .WithMany("ZombieSieges") + .HasForeignKey("AllianceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Alliance"); + }); + + modelBuilder.Entity("Database.Entities.ZombieSiegeParticipant", b => + { + b.HasOne("Database.Entities.Player", "Player") + .WithMany("ZombieSiegeParticipants") + .HasForeignKey("PlayerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("Database.Entities.ZombieSiege", "ZombieSiege") + .WithMany("ZombieSiegeParticipants") + .HasForeignKey("ZombieSiegeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Player"); + + b.Navigation("ZombieSiege"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) @@ -976,6 +1047,8 @@ namespace Database.Migrations b.Navigation("Users"); b.Navigation("VsDuels"); + + b.Navigation("ZombieSieges"); }); modelBuilder.Entity("Database.Entities.CustomEvent", b => @@ -1006,6 +1079,8 @@ namespace Database.Migrations b.Navigation("Notes"); b.Navigation("VsDuelParticipants"); + + b.Navigation("ZombieSiegeParticipants"); }); modelBuilder.Entity("Database.Entities.Rank", b => @@ -1017,6 +1092,11 @@ namespace Database.Migrations { b.Navigation("VsDuelParticipants"); }); + + modelBuilder.Entity("Database.Entities.ZombieSiege", b => + { + b.Navigation("ZombieSiegeParticipants"); + }); #pragma warning restore 612, 618 } } diff --git a/Ui/src/app/app-routing.module.ts b/Ui/src/app/app-routing.module.ts index 74d41eb..50f1ac4 100644 --- a/Ui/src/app/app-routing.module.ts +++ b/Ui/src/app/app-routing.module.ts @@ -19,6 +19,8 @@ import {ChangePasswordComponent} from "./pages/change-password/change-password.c import {DesertStormDetailComponent} from "./pages/desert-storm/desert-storm-detail/desert-storm-detail.component"; import {ResetPasswordComponent} from "./Authentication/reset-password/reset-password.component"; import {CustomEventComponent} from "./pages/custom-event/custom-event.component"; +import {ZombieSiegeComponent} from "./pages/zombie-siege/zombie-siege.component"; +import {ZombieSiegeDetailComponent} from "./pages/zombie-siege/zombie-siege-detail/zombie-siege-detail.component"; const routes: Routes = [ {path: 'players', component: PlayerComponent, canActivate: [authGuard]}, @@ -34,6 +36,8 @@ const routes: Routes = [ {path: 'account', component: AccountComponent, canActivate: [authGuard]}, {path: 'change-password', component: ChangePasswordComponent, canActivate: [authGuard]}, {path: 'custom-event', component: CustomEventComponent, canActivate: [authGuard]}, + {path: 'zombie-siege', component: ZombieSiegeComponent, canActivate: [authGuard]}, + {path: 'zombie-siege-detail/:id', component: ZombieSiegeDetailComponent, canActivate: [authGuard]}, {path: 'login', component: LoginComponent}, {path: 'confirm-email', component: EmailConfirmationComponent}, {path: 'sign-up', component: SignUpComponent}, diff --git a/Ui/src/app/app.module.ts b/Ui/src/app/app.module.ts index 16e8248..a3a980d 100644 --- a/Ui/src/app/app.module.ts +++ b/Ui/src/app/app.module.ts @@ -47,6 +47,9 @@ import { ForgotPasswordComponent } from './Authentication/forgot-password/forgot import { ResetPasswordComponent } from './Authentication/reset-password/reset-password.component'; import { CustomEventComponent } from './pages/custom-event/custom-event.component'; import { UnderDevelopmentComponent } from './helpers/under-development/under-development.component'; +import { ZombieSiegeComponent } from './pages/zombie-siege/zombie-siege.component'; +import { ZombieSiegeParticipantsModalComponent } from './modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component'; +import { ZombieSiegeDetailComponent } from './pages/zombie-siege/zombie-siege-detail/zombie-siege-detail.component'; @NgModule({ declarations: [ @@ -84,7 +87,10 @@ import { UnderDevelopmentComponent } from './helpers/under-development/under-dev ForgotPasswordComponent, ResetPasswordComponent, CustomEventComponent, - UnderDevelopmentComponent + UnderDevelopmentComponent, + ZombieSiegeComponent, + ZombieSiegeParticipantsModalComponent, + ZombieSiegeDetailComponent ], imports: [ BrowserModule, diff --git a/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.css b/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.css new file mode 100644 index 0000000..e1268fe --- /dev/null +++ b/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.css @@ -0,0 +1,14 @@ +.check-box-container { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.check-box-container .form-check { + flex: 1 1 calc(50% - 10px); + box-sizing: border-box; +} + +.text-color { + color: #43c315; +} diff --git a/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.html b/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.html new file mode 100644 index 0000000..b75634c --- /dev/null +++ b/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.html @@ -0,0 +1,29 @@ + + + + + + diff --git a/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.ts b/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.ts new file mode 100644 index 0000000..1e897a8 --- /dev/null +++ b/Ui/src/app/modals/zombie-siege-participants-modal/zombie-siege-participants-modal.component.ts @@ -0,0 +1,45 @@ +import {Component, inject, Input, OnInit} from '@angular/core'; +import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap"; +import {PlayerService} from "../../services/player.service"; +import {PlayerModel} from "../../models/player.model"; + +@Component({ + selector: 'app-zombie-siege-participants-modal', + templateUrl: './zombie-siege-participants-modal.component.html', + styleUrl: './zombie-siege-participants-modal.component.css' +}) +export class ZombieSiegeParticipantsModalComponent implements OnInit { + + private readonly _playerService: PlayerService = inject(PlayerService); + + public activeModal: NgbActiveModal = inject(NgbActiveModal); + public playerParticipated: { playerId: string, playerName: string, survivedWaves: number; }[] = []; + public waves: number[] = [0,1,2,3,4,5,6,7,8,9,10, 11,12,13,14,15,16,17,18,19,20]; + public isUpdate: boolean = false; + + @Input() players: { playerId: string, playerName: string, survivedWaves: number; }[] | undefined; + @Input({required: true}) allianceId!: string; + + ngOnInit() { + if (this.players) { + this.playerParticipated = [...this.players]; + this.isUpdate = true; + } else { + this.getPlayers(); + this.isUpdate = false; + } + } + + getPlayers() { + this._playerService.getAlliancePlayer(this.allianceId).subscribe({ + next: ((response) => { + if (response) { + response.forEach((player: PlayerModel) => { + this.playerParticipated.push({playerId: player.id, playerName: player.playerName, survivedWaves: 0}) + }); + this.playerParticipated.sort((a, b) => a.playerName.localeCompare(b.playerName)); + } + }) + }); + } +} diff --git a/Ui/src/app/models/zombieSiege.model.ts b/Ui/src/app/models/zombieSiege.model.ts new file mode 100644 index 0000000..2060fb3 --- /dev/null +++ b/Ui/src/app/models/zombieSiege.model.ts @@ -0,0 +1,24 @@ +import {ZombieSiegeParticipantModel} from "./zombieSiegeParticipant.model"; + +export interface ZombieSiegeModel { + id: string; + allianceId: string; + eventDate: Date; + createdBy: string; + modifiedOn?: Date; + modifiedBy?: string; + allianceSize: number; + level: number; + totalLevel20Players: number; +} + +export interface ZombieSiegeDetailModel extends ZombieSiegeModel{ + zombieSiegeParticipants: ZombieSiegeParticipantModel[]; +} + +export interface CreateZombieSiegeModel { + allianceId: string; + allianceSize: number; + level: number; + eventDate: string; +} diff --git a/Ui/src/app/models/zombieSiegeParticipant.model.ts b/Ui/src/app/models/zombieSiegeParticipant.model.ts new file mode 100644 index 0000000..ba00588 --- /dev/null +++ b/Ui/src/app/models/zombieSiegeParticipant.model.ts @@ -0,0 +1,13 @@ +export interface ZombieSiegeParticipantModel { + id: string; + playerId: string; + zombieSiegeId: string; + survivedWaves: number; + playerName: string; +} + +export interface CreateZombieSiegeParticipantModel { + playerId: string; + zombieSiegeId: string; + survivedWaves: number; +} diff --git a/Ui/src/app/navigation/navigation.component.html b/Ui/src/app/navigation/navigation.component.html index 9aeb1dc..88b0dd3 100644 --- a/Ui/src/app/navigation/navigation.component.html +++ b/Ui/src/app/navigation/navigation.component.html @@ -40,6 +40,11 @@ + +