Skip to content
This repository has been archived by the owner on Dec 21, 2022. It is now read-only.

Commit

Permalink
Merge pull request #95 from MaaAssistantArknights/feat/custom-level
Browse files Browse the repository at this point in the history
  • Loading branch information
AlisaAkiron authored Aug 31, 2022
2 parents 9dfe8c0 + 05d9cd3 commit 0570b7a
Show file tree
Hide file tree
Showing 22 changed files with 1,520 additions and 32 deletions.
520 changes: 520 additions & 0 deletions api-spec.json

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions src/MaaCopilotServer.Api/Controllers/ArknightsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
// Licensed under the AGPL-3.0 license.

using MaaCopilotServer.Api.Swagger;
using MaaCopilotServer.Application.Arknights.AddOrUpdateCustomLevels;
using MaaCopilotServer.Application.Arknights.GetDataVersion;
using MaaCopilotServer.Application.Arknights.GetLevelList;
using MaaCopilotServer.Application.Arknights.GetOperatorList;
using MaaCopilotServer.Application.Arknights.RemoveCustomLevels;
using MediatR;
using Microsoft.AspNetCore.Mvc;

Expand Down Expand Up @@ -118,4 +120,48 @@ public async Task<ActionResult> GetArkOperatorList([FromQuery] GetOperatorListQu
{
return await GetResponse(query);
}

/// <summary>
/// Add or update custom level data.
/// </summary>
/// <param name="command">The level list.</param>
/// <returns>An asynchronous operation representing the response.</returns>
/// <remarks>
/// <list type="bullet">
/// <item>
/// <term>200</term>
/// <description>
/// Total database changes count, added and updated level ids.
/// </description>
/// </item>
/// </list>
/// </remarks>
[HttpPost("custom/add")]
[ProducesResponseType(typeof(MaaApiResponseModel<AddOrUpdateCustomLevelsDto>), StatusCodes.Status200OK)]
public async Task<ActionResult> AddOrUpdateCustomLevels([FromBody] AddOrUpdateCustomLevelsCommandBatch command)
{
return await GetResponse(command);
}

/// <summary>
/// Remove custom level data.
/// </summary>
/// <param name="command">The remove level ids.</param>
/// <returns>An asynchronous operation representing the response.</returns>
/// <remarks>
/// <list type="bullet">
/// <item>
/// <term>200</term>
/// <description>
/// Total database changes count and removed level ids.
/// </description>
/// </item>
/// </list>
/// </remarks>
[HttpPost("custom/remove")]
[ProducesResponseType(typeof(MaaApiResponseModel<RemoveCustomLevelsDto>), StatusCodes.Status200OK)]
public async Task<ActionResult> RemoveCustomLevels([FromBody] RemoveCustomLevelsCommand command)
{
return await GetResponse(command);
}
}
4 changes: 3 additions & 1 deletion src/MaaCopilotServer.Api/Jobs/ArknightsDataUpdate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ private async Task RunJob(CancellationToken cancellationToken)
return;
}

var dbLevelData = await db.ArkLevelData.ToListAsync(cancellationToken);
var dbLevelData = await db.ArkLevelData
.Where(x => x.Custom == false)
.ToListAsync(cancellationToken);
var dbCharData = await db.ArkCharacterInfos.ToListAsync(cancellationToken);
var currentData = await GetParsedData();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// This file is a part of MaaCopilotServer project.
// MaaCopilotServer belongs to the MAA organization.
// Licensed under the AGPL-3.0 license.

using System.Text.Json.Serialization;
using MaaCopilotServer.Application.Common.Helpers;
using MaaCopilotServer.Domain.Entities;
using MaaCopilotServer.Domain.Enums;
using MaaCopilotServer.GameData;
using Microsoft.EntityFrameworkCore;
using ArkI18N = MaaCopilotServer.Domain.Entities.ArkI18N;

namespace MaaCopilotServer.Application.Arknights.AddOrUpdateCustomLevels;

public record AddOrUpdateCustomLevelsCommand
{
/// <summary>
/// Arknights level name.
/// </summary>
[JsonPropertyName("name")]
public ArkI18NDto Name { get; set; } = new();

/// <summary>
/// Arknights level category one. Typically zone name.
/// </summary>
[JsonPropertyName("cat_one")]
public ArkI18NDto CatOne { get; set; } = new();

/// <summary>
/// Arknights level category two. Typically chapter name.
/// </summary>
[JsonPropertyName("cat_two")]
public ArkI18NDto CatTwo { get; set; } = new();

/// <summary>
/// Arknights level category three. Typically level code.
/// </summary>
[JsonPropertyName("cat_three")]
public ArkI18NDto CatThree { get; set; } = new();

/// <summary>
/// Arknights level id. Custom levels will have `copilot-custom/` prefix added to their id automatically.
/// </summary>
[JsonPropertyName("level_id")]
public string LevelId { get; set; } = string.Empty;

/// <summary>
/// Map width, defaults to 0.
/// </summary>
[JsonPropertyName("width")]
public int Width { get; set; } = 0;

/// <summary>
/// Map height, defaults to 0.
/// </summary>
[JsonPropertyName("height")]
public int Height { get; set; } = 0;
}

[Authorized(UserRole.Admin)]
public record AddOrUpdateCustomLevelsCommandBatch : IRequest<MaaApiResponse>
{
/// <summary>
/// Custom levels to add or update.
/// </summary>
[JsonPropertyName("custom_levels")]
// ReSharper disable once CollectionNeverUpdated.Global
public List<AddOrUpdateCustomLevelsCommand> Commands { get; set; } = new();
}

public class AddOrUpdateCustomLevelsCommandBatchHandler : IRequestHandler<AddOrUpdateCustomLevelsCommandBatch, MaaApiResponse>
{
private readonly IMaaCopilotDbContext _dbContext;
private readonly ICurrentUserService _currentUserService;

public AddOrUpdateCustomLevelsCommandBatchHandler(IMaaCopilotDbContext dbContext, ICurrentUserService currentUserService)
{
_dbContext = dbContext;
_currentUserService = currentUserService;
}

public async Task<MaaApiResponse> Handle(AddOrUpdateCustomLevelsCommandBatch request, CancellationToken cancellationToken)
{
var uid = _currentUserService.GetUserIdentity();
if (uid is null)
{
return MaaApiResponseHelper.InternalError();
}

var dbE = _dbContext.ArkLevelData
.Include(x => x.Name)
.Include(x => x.CatOne)
.Include(x => x.CatTwo)
.Include(x => x.CatThree)
.Where(x => x.Custom == true)
.ToList();

var pending = request.Commands.Select(x =>
new ArkLevelData(uid.Value)
{
Name = x.Name.ToDomainEntityFromDto(),
CatOne = x.CatOne.ToDomainEntityFromDto(),
CatTwo = x.CatTwo.ToDomainEntityFromDto(),
CatThree = x.CatThree.ToDomainEntityFromDto(),
Height = x.Height,
Width = x.Width,
Custom = true,
LevelId = $"copilot-custom/{x.LevelId}",
Keyword = Helpers.BuildKeyword(
x.Name.ToGameDataEntityFromDto(),
x.CatOne.ToGameDataEntityFromDto(),
x.CatTwo.ToGameDataEntityFromDto(),
x.CatThree.ToGameDataEntityFromDto())
.ToDomainEntityFromGameDataEntity()
})
.ToList();

var added = new List<string>();
var updated = new List<string>();

foreach (var command in pending)
{
var exist = dbE.FirstOrDefault(x => x.LevelId == command.LevelId);
if (exist is null)
{
await _dbContext.ArkLevelData.AddAsync(command, cancellationToken);
added.Add(command.LevelId);
continue;
}

exist.Name.Update(command.Name.ToGameDataEntityFromDomainEntity());
exist.CatOne.Update(command.CatOne.ToGameDataEntityFromDomainEntity());
exist.CatTwo.Update(command.CatTwo.ToGameDataEntityFromDomainEntity());
exist.CatThree.Update(command.CatThree.ToGameDataEntityFromDomainEntity());

exist.Keyword ??= new ArkI18N();
exist.Keyword.Update(command.Keyword!.ToGameDataEntityFromDomainEntity());

exist.LevelId = command.LevelId;
exist.Width = command.Width;
exist.Height = command.Height;

_dbContext.ArkLevelData.Update(exist);
updated.Add(command.LevelId);
}

var changes = await _dbContext.SaveChangesAsync(cancellationToken);

return MaaApiResponseHelper.Ok(new AddOrUpdateCustomLevelsDto
{
DbContextChanges = changes, Added = added, Updated = updated
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This file is a part of MaaCopilotServer project.
// MaaCopilotServer belongs to the MAA organization.
// Licensed under the AGPL-3.0 license.

using System.Text.Json.Serialization;

namespace MaaCopilotServer.Application.Arknights.AddOrUpdateCustomLevels;

public record AddOrUpdateCustomLevelsDto
{
/// <summary>
/// Total number of database changes.
/// </summary>
[JsonPropertyName("db_context_changes")]
public int DbContextChanges { get; set; }

/// <summary>
/// Added levels.
/// </summary>
[JsonPropertyName("added")]
public List<string> Added { get; set; } = new();

/// <summary>
/// Updated levels.
/// </summary>
[JsonPropertyName("updated")]
public List<string> Updated { get; set; } = new();
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public class GetLevelListDto
/// <param name="levelId">The level id.</param>
/// <param name="width">The width of the level.</param>
/// <param name="height">The height of the level.</param>
public GetLevelListDto(string catOne, string catTwo, string catThree, string name, string levelId, int width, int height)
/// <param name="custom">Whether the level is added manually or not.</param>
public GetLevelListDto(string catOne, string catTwo, string catThree, string name, string levelId, int width, int height, bool custom = false)
{
CatOne = catOne;
CatTwo = catTwo;
Expand All @@ -31,6 +32,7 @@ public GetLevelListDto(string catOne, string catTwo, string catThree, string nam
LevelId = levelId;
Width = width;
Height = height;
Custom = custom;
}

#pragma warning disable CS8618
Expand Down Expand Up @@ -85,4 +87,11 @@ public GetLevelListDto() { }
[Required]
[JsonPropertyName("height")]
public int Height { get; set; }

/// <summary>
/// Whether the level is added manually or not.
/// </summary>
[Required]
[JsonPropertyName("custom")]
public bool Custom { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ public record GetLevelListQuery : IRequest<MaaApiResponse>
/// </summary>
[FromQuery(Name = "language")]
public string Language { get; set; } = string.Empty;

/// <summary>
/// Query managed level or custom level.
/// </summary>
[FromQuery(Name = "custom")]
public string Custom { get; set; } = string.Empty;
}

public class GetLevelListQueryHandler : IRequestHandler<GetLevelListQuery, MaaApiResponse>
Expand All @@ -44,6 +50,16 @@ public async Task<MaaApiResponse> Handle(GetLevelListQuery request, Cancellation
.Include(x => x.CatThree)
.AsQueryable();

switch (request.Custom)
{
case "true":
query = query.Where(x => x.Custom == true);
break;
case "false":
query = query.Where(x => x.Custom == false);
break;
}

var qFunc = request.Language.GetLevelQueryFunc();
var mFunc = request.Language.GetLevelMapperFunc();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// This file is a part of MaaCopilotServer project.
// MaaCopilotServer belongs to the MAA organization.
// Licensed under the AGPL-3.0 license.

using System.Text.Json.Serialization;
using MaaCopilotServer.Application.Common.Helpers;
using MaaCopilotServer.Domain.Enums;
using Microsoft.EntityFrameworkCore;

namespace MaaCopilotServer.Application.Arknights.RemoveCustomLevels;

[Authorized(UserRole.SuperAdmin)]
public record RemoveCustomLevelsCommand : IRequest<MaaApiResponse>
{
/// <summary>
/// A list of level ids that is pending to be removed.
/// </summary>
[JsonPropertyName("level_ids")]
public List<string> LevelIds { get; set; } = new();
}

public class RemoveCustomLevelsCommandHandler : IRequestHandler<RemoveCustomLevelsCommand, MaaApiResponse>
{
private readonly IMaaCopilotDbContext _dbContext;
private readonly ICurrentUserService _currentUserService;

public RemoveCustomLevelsCommandHandler(IMaaCopilotDbContext dbContext, ICurrentUserService currentUserService)
{
_dbContext = dbContext;
_currentUserService = currentUserService;
}

public async Task<MaaApiResponse> Handle(RemoveCustomLevelsCommand request, CancellationToken cancellationToken)
{
var uid = _currentUserService.GetUserIdentity();
if (uid is null)
{
return MaaApiResponseHelper.InternalError();
}

var removed = new List<string>();

foreach (var levelId in request.LevelIds)
{
var exist = await _dbContext.ArkLevelData
.Where(x => x.Custom)
.FirstOrDefaultAsync(x => x.LevelId == $"copilot-custom/{levelId}",
cancellationToken: cancellationToken);

if (exist is null)
{
continue;
}

exist.Delete(uid.Value);
_dbContext.ArkLevelData.Remove(exist);
removed.Add(exist.LevelId);
}

var changes = await _dbContext.SaveChangesAsync(cancellationToken);
return MaaApiResponseHelper.Ok(new RemoveCustomLevelsDto
{
DbContextChanges = changes, Removed = removed
});
}
}
Loading

0 comments on commit 0570b7a

Please sign in to comment.