1
0
mirror of synced 2024-11-23 22:41:01 +01:00

Refactor db access

This commit is contained in:
asesidaa 2022-09-09 00:27:47 +08:00
parent e3d8da41bd
commit 0f71da4353
24 changed files with 481 additions and 195 deletions

View File

@ -1,30 +1,24 @@
namespace TaikoLocalServer.Controllers.Api;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Api;
[ApiController]
[Route("api/[controller]")]
public class CardsController : BaseController<CardsController>
{
private readonly TaikoDbContext context;
private readonly ICardService cardService;
public CardsController(TaikoDbContext context)
public CardsController(ICardService cardService)
{
this.context = context;
this.cardService = cardService;
}
[HttpDelete("{accessCode}")]
public async Task<IActionResult> DeleteUser(string accessCode)
{
var card = await context.Cards.FindAsync(accessCode);
var result = await cardService.DeleteCard(accessCode);
if (card is null)
{
return NotFound();
}
context.Cards.Remove(card);
await context.SaveChangesAsync();
return NoContent();
return result ? NoContent() : NotFound();
}
}

View File

@ -1,6 +1,7 @@
using SharedProject.Models;
using SharedProject.Models.Responses;
using Swan.Mapping;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Api;
@ -10,16 +11,18 @@ public class DashboardController : BaseController<DashboardController>
{
private readonly TaikoDbContext context;
public DashboardController(TaikoDbContext context)
private readonly ICardService cardService;
public DashboardController(TaikoDbContext context, ICardService cardService)
{
this.context = context;
this.cardService = cardService;
}
[HttpGet]
public DashboardResponse GetDashboard()
public async Task<DashboardResponse> GetDashboard()
{
var cards = context.Cards.AsEnumerable();
var users = cards.Select(card => card.CopyPropertiesToNew<User>()).ToList();
var users = await cardService.GetUsersFromCards();
return new DashboardResponse
{
Users = users

View File

@ -2,6 +2,8 @@
using SharedProject.Models;
using SharedProject.Models.Responses;
using SharedProject.Utils;
using TaikoLocalServer.Services;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Api;
@ -11,15 +13,18 @@ public class UserSettingsController : BaseController<UserSettingsController>
{
private readonly TaikoDbContext context;
public UserSettingsController(TaikoDbContext context)
private readonly IUserDatumService userDatumService;
public UserSettingsController(TaikoDbContext context, IUserDatumService userDatumService)
{
this.context = context;
this.userDatumService = userDatumService;
}
[HttpGet]
public async Task<ActionResult<UserSetting>> GetUserSetting(uint baid)
{
var user = await context.UserData.FirstOrDefaultAsync(datum => datum.Baid == baid);
var user = await userDatumService.GetFirstUserDatumOrNull(baid);
if (user is null)
{
@ -46,7 +51,7 @@ public class UserSettingsController : BaseController<UserSettingsController>
[HttpPost]
public async Task<IActionResult> SaveUserSetting(uint baid, UserSetting userSetting)
{
var user = await context.UserData.FindAsync(baid);
var user = await userDatumService.GetFirstUserDatumOrNull(baid);
if (user is null)
{
@ -65,8 +70,7 @@ public class UserSettingsController : BaseController<UserSettingsController>
user.Title = userSetting.Title;
user.TitlePlateId = userSetting.TitlePlateId;
context.Update(user);
await context.SaveChangesAsync();
await userDatumService.UpdateUserDatum(user);
return NoContent();
}

View File

@ -1,4 +1,5 @@
using System.Text.Json;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Game;
@ -6,24 +7,35 @@ namespace TaikoLocalServer.Controllers.Game;
[Route("/v12r03/chassis/baidcheck.php")]
public class BaidController : BaseController<BaidController>
{
private readonly TaikoDbContext context;
private readonly IUserDatumService userDatumService;
public BaidController(TaikoDbContext context)
private readonly ICardService cardService;
private readonly ISongBestDatumService songBestDatumService;
private readonly IDanScoreDatumService danScoreDatumService;
public BaidController(IUserDatumService userDatumService, ICardService cardService,
ISongBestDatumService songBestDatumService, IDanScoreDatumService danScoreDatumService)
{
this.context = context;
this.userDatumService = userDatumService;
this.cardService = cardService;
this.songBestDatumService = songBestDatumService;
this.danScoreDatumService = danScoreDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult GetBaid([FromBody] BAIDRequest request)
public async Task<IActionResult> GetBaid([FromBody] BAIDRequest request)
{
Logger.LogInformation("Baid request: {Request}", request.Stringify());
BAIDResponse response;
if (!context.Cards.Any(card => card.AccessCode == request.AccessCode))
var card = await cardService.GetCardByAccessCode(request.AccessCode);
if (card is null)
{
Logger.LogInformation("New user from access code {AccessCode}", request.AccessCode);
var newId = context.Cards.Any() ? context.Cards.Max(card => card.Baid) + 1 : 1;
Logger.LogInformation("New user with access code {AccessCode}", request.AccessCode);
var newId = cardService.GetNextBaid();
response = new BAIDResponse
{
@ -43,15 +55,11 @@ public class BaidController : BaseController<BaidController>
return Ok(response);
}
var baid = context.Cards.First(card => card.AccessCode == request.AccessCode).Baid;
var baid = card.Baid;
var userData = new UserDatum();
if (context.UserData.Any(datum => datum.Baid == baid))
{
userData = context.UserData.First(datum => datum.Baid == baid);
}
var userData = await userDatumService.GetFirstUserDatumOrDefault(baid);
var songBestData = context.SongBestData.Where(datum => datum.Baid == baid).ToList();
var songBestData = await songBestDatumService.GetAllSongBestData(baid);
var achievementDisplayDifficulty = userData.AchievementDisplayDifficulty;
if (userData.AchievementDisplayDifficulty == Difficulty.None)
@ -102,16 +110,13 @@ public class BaidController : BaseController<BaidController>
var costumeFlag = new byte[10];
Array.Fill(costumeFlag, byte.MaxValue);
var danData = context.DanScoreData
.Where(datum => datum.Baid == baid)
.Include(datum => datum.DanStageScoreData)
.ToList();
var danData = await danScoreDatumService.GetDanScoreDatumByBaid(baid);
var maxDan = danData.Where(datum => datum.ClearState != DanClearState.NotClear)
.Select(datum => datum.DanId)
.DefaultIfEmpty()
.Max();
var gotDanFlagArray = FlagCalculator.ComputeGotDanFlags(danData);
Logger.LogInformation("Got dan array {Array}", gotDanFlagArray.Stringify());
response = new BAIDResponse
{

View File

@ -1,23 +1,25 @@
namespace TaikoLocalServer.Controllers.Game;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Game;
[Route("/v12r03/chassis/crownsdata.php")]
[ApiController]
public class CrownsDataController : BaseController<CrownsDataController>
{
private readonly TaikoDbContext context;
private readonly ISongBestDatumService songBestDatumService;
public CrownsDataController(TaikoDbContext context)
public CrownsDataController(ISongBestDatumService songBestDatumService)
{
this.context = context;
this.songBestDatumService = songBestDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult CrownsData([FromBody] CrownsDataRequest request)
public async Task<IActionResult> CrownsData([FromBody] CrownsDataRequest request)
{
Logger.LogInformation("CrownsData request : {Request}", request.Stringify());
var songBestData = context.SongBestData.Where(datum => datum.Baid == request.Baid).ToList();
var songBestData = await songBestDatumService.GetAllSongBestData(request.Baid);
var crown = new ushort[Constants.CROWN_FLAG_ARRAY_SIZE];
var dondafulCrown = new byte[Constants.DONDAFUL_CROWN_FLAG_ARRAY_SIZE];

View File

@ -1,19 +1,21 @@
namespace TaikoLocalServer.Controllers.Game;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Game;
[Route("/v12r03/chassis/getdanscore.php")]
[ApiController]
public class GetDanScoreController : BaseController<GetDanScoreController>
{
private readonly TaikoDbContext context;
private readonly IDanScoreDatumService danScoreDatumService;
public GetDanScoreController(TaikoDbContext context)
public GetDanScoreController(IDanScoreDatumService danScoreDatumService)
{
this.context = context;
this.danScoreDatumService = danScoreDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult GetDanScore([FromBody] GetDanScoreRequest request)
public async Task<IActionResult> GetDanScore([FromBody] GetDanScoreRequest request)
{
Logger.LogInformation("GetDanScore request : {Request}", request.Stringify());
@ -22,10 +24,7 @@ public class GetDanScoreController : BaseController<GetDanScoreController>
Result = 1
};
var danScoreData = context.DanScoreData
.Where(datum => datum.Baid == request.Baid)
.Include(datum => datum.DanStageScoreData)
.ToList();
var danScoreData = await danScoreDatumService.GetDanScoreDatumByBaid(request.Baid);
foreach (var danId in request.DanIds)
{

View File

@ -1,25 +1,27 @@
namespace TaikoLocalServer.Controllers.Game;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Game;
[Route("/v12r03/chassis/getscorerank.php")]
[ApiController]
public class GetScoreRankController : BaseController<GetScoreRankController>
{
private readonly TaikoDbContext context;
private readonly ISongBestDatumService songBestDatumService;
public GetScoreRankController(TaikoDbContext context)
public GetScoreRankController(ISongBestDatumService songBestDatumService)
{
this.context = context;
this.songBestDatumService = songBestDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult GetScoreRank([FromBody] GetScoreRankRequest request)
public async Task<IActionResult> GetScoreRank([FromBody] GetScoreRankRequest request)
{
Logger.LogInformation("GetScoreRank request : {Request}", request.Stringify());
var kiwamiScores = new byte[Constants.KIWAMI_SCORE_RANK_ARRAY_SIZE];
var miyabiScores = new ushort[Constants.MIYABI_CORE_RANK_ARRAY_SIZE];
var ikiScores = new ushort[Constants.IKI_CORE_RANK_ARRAY_SIZE];
var songBestData = context.SongBestData.Where(datum => datum.Baid == request.Baid).ToList();
var songBestData = await songBestDatumService.GetAllSongBestData(request.Baid);
for (var songId = 0; songId < Constants.MUSIC_ID_MAX; songId++)
{

View File

@ -40,6 +40,7 @@ public class InitialDataCheckController : BaseController<InitialDataCheckControl
IsClose = false,
DefaultSongFlg = enabledArray,
AchievementSongBit = enabledArray,
SongIntroductionEndDatetime = DateTime.Now.AddYears(10).ToString(Constants.DATE_TIME_FORMAT),
AryShopFolderDatas =
{
new InitialdatacheckResponse.InformationData

View File

@ -1,30 +1,36 @@
namespace TaikoLocalServer.Controllers.Game;
using TaikoLocalServer.Services;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Controllers.Game;
[Route("/v12r03/chassis/mydonentry.php")]
[ApiController]
public class MyDonEntryController : BaseController<MyDonEntryController>
{
private readonly TaikoDbContext context;
private readonly IUserDatumService userDatumService;
private readonly ICardService cardService;
public MyDonEntryController(TaikoDbContext context)
public MyDonEntryController(IUserDatumService userDatumService, ICardService cardService)
{
this.context = context;
this.userDatumService = userDatumService;
this.cardService = cardService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult GetMyDonEntry([FromBody] MydonEntryRequest request)
public async Task<IActionResult> GetMyDonEntry([FromBody] MydonEntryRequest request)
{
Logger.LogInformation("MyDonEntry request : {Request}", request.Stringify());
var newId = context.Cards.Any() ? context.Cards.Max(card => card.Baid) + 1 : 1;
context.Cards.Add(new Card
var newId = cardService.GetNextBaid();
await cardService.AddCard(new Card
{
AccessCode = request.AccessCode,
Baid = newId
});
context.UserData.Add(new UserDatum
var newUser = new UserDatum
{
Baid = newId,
MyDonName = request.MydonName,
@ -35,9 +41,10 @@ public class MyDonEntryController : BaseController<MyDonEntryController>
ColorBody = 1,
ColorLimb = 3,
FavoriteSongsArray = "{}"
});
context.SaveChanges();
};
await userDatumService.InsertUserDatum(newUser);
var response = new MydonEntryResponse
{
Result = 1,

View File

@ -1,23 +1,37 @@
using System.Buffers.Binary;
using System.Globalization;
using System.Text.Json;
using TaikoLocalServer.Services.Interfaces;
using Throw;
namespace TaikoLocalServer.Controllers.Game;
using StageData = PlayResultDataRequest.StageData;
[Route("/v12r03/chassis/playresult.php")]
[ApiController]
public class PlayResultController : BaseController<PlayResultController>
{
private readonly TaikoDbContext context;
private readonly IUserDatumService userDatumService;
public PlayResultController(TaikoDbContext context)
private readonly ISongPlayDatumService songPlayDatumService;
private readonly ISongBestDatumService songBestDatumService;
private readonly IDanScoreDatumService danScoreDatumService;
public PlayResultController(IUserDatumService userDatumService, ISongPlayDatumService songPlayDatumService,
ISongBestDatumService songBestDatumService, IDanScoreDatumService danScoreDatumService)
{
this.context = context;
this.userDatumService = userDatumService;
this.songPlayDatumService = songPlayDatumService;
this.songBestDatumService = songBestDatumService;
this.danScoreDatumService = danScoreDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult UploadPlayResult([FromBody] PlayResultRequest request)
public async Task<IActionResult> UploadPlayResult([FromBody] PlayResultRequest request)
{
Logger.LogInformation("PlayResult request : {Request}", request.Stringify());
var decompressed = GZipBytesUtil.DecompressGZipBytes(request.PlayresultData);
@ -29,88 +43,75 @@ public class PlayResultController : BaseController<PlayResultController>
var response = new PlayResultResponse
{
Result = 1
};
var lastPlayDatetime = DateTime.ParseExact(playResultData.PlayDatetime, Constants.DATE_TIME_FORMAT, CultureInfo.InvariantCulture);
UpdateUserData(request, playResultData, lastPlayDatetime);
};
var lastPlayDatetime = DateTime.ParseExact(playResultData.PlayDatetime, Constants.DATE_TIME_FORMAT,
CultureInfo.InvariantCulture);
await UpdateUserData(request, playResultData, lastPlayDatetime);
var playMode = (PlayMode)playResultData.PlayMode;
if (playMode == PlayMode.DanMode)
{
UpdateDanPlayData(request, playResultData);
context.SaveChanges();
await UpdateDanPlayData(request, playResultData);
return Ok(response);
}
var bestData = context.SongBestData.Where(datum => datum.Baid == request.BaidConf).ToList();
var bestData = await songBestDatumService.GetAllSongBestData(request.BaidConf);
for (var songNumber = 0; songNumber < playResultData.AryStageInfoes.Count; songNumber++)
{
var stageData = playResultData.AryStageInfoes[songNumber];
UpdateBestData(request, stageData, bestData);
UpdatePlayData(request, songNumber, stageData, lastPlayDatetime);
await UpdateBestData(request, stageData, bestData);
await UpdatePlayData(request, songNumber, stageData, lastPlayDatetime);
}
context.SaveChanges();
return Ok(response);
}
private void UpdateDanPlayData(PlayResultRequest request, PlayResultDataRequest playResultDataRequest)
private async Task UpdateDanPlayData(PlayResultRequest request, PlayResultDataRequest playResultDataRequest)
{
if (playResultDataRequest.IsNotRecordedDan)
{
Logger.LogInformation("Dan score will not be saved!");
return;
}
var danScoreDataQuery = context.DanScoreData
.Where(datum => datum.Baid == request.BaidConf &&
datum.DanId == playResultDataRequest.DanId)
.Include(datum => datum.DanStageScoreData);
var danScoreData = new DanScoreDatum
{
Baid = request.BaidConf,
DanId = playResultDataRequest.DanId
};
var insert = true;
if (danScoreDataQuery.Any())
{
danScoreData = danScoreDataQuery.First();
insert = false;
}
danScoreData.ClearState = (DanClearState)Math.Max(playResultDataRequest.DanResult, (uint)danScoreData.ClearState);
danScoreData.ArrivalSongCount = Math.Max((uint)playResultDataRequest.AryStageInfoes.Count, danScoreData.ArrivalSongCount);
var danScoreData =
await danScoreDatumService.GetSingleDanScoreDatum(request.BaidConf, playResultDataRequest.DanId) ??
new DanScoreDatum
{
Baid = request.BaidConf,
DanId = playResultDataRequest.DanId
};
danScoreData.ClearState =
(DanClearState)Math.Max(playResultDataRequest.DanResult, (uint)danScoreData.ClearState);
danScoreData.ArrivalSongCount =
Math.Max((uint)playResultDataRequest.AryStageInfoes.Count, danScoreData.ArrivalSongCount);
danScoreData.ComboCountTotal = Math.Max(playResultDataRequest.ComboCntTotal, danScoreData.ComboCountTotal);
danScoreData.SoulGaugeTotal = Math.Max(playResultDataRequest.SoulGaugeTotal, danScoreData.SoulGaugeTotal);
UpdateDanStageData(playResultDataRequest, danScoreData);
if (insert)
{
context.DanScoreData.Add(danScoreData);
return;
}
context.DanScoreData.Update(danScoreData);
await danScoreDatumService.InsertOrUpdateDanScoreDatum(danScoreData);
}
private void UpdateDanStageData(PlayResultDataRequest playResultDataRequest, DanScoreDatum danScoreData)
{
for (var songNumber = 0; songNumber < playResultDataRequest.AryStageInfoes.Count; songNumber++)
for (var i = 0; i < playResultDataRequest.AryStageInfoes.Count; i++)
{
var stageData = playResultDataRequest.AryStageInfoes[songNumber];
var add = true;
var stageData = playResultDataRequest.AryStageInfoes[i];
var danStageData = new DanStageScoreDatum
{
Baid = danScoreData.Baid,
DanId = danScoreData.DanId,
SongNumber = (uint)songNumber
};
if (danScoreData.DanStageScoreData.Any(datum => datum.SongNumber == songNumber))
{
danStageData = danScoreData.DanStageScoreData.First(datum => datum.SongNumber == songNumber);
add = false;
}
var songNumber = i;
var danStageData = danScoreData.DanStageScoreData.FirstOrDefault(datum => datum.SongNumber == songNumber,
new DanStageScoreDatum
{
Baid = danScoreData.Baid,
DanId = danScoreData.DanId,
SongNumber = (uint)songNumber
});
danStageData.HighScore = Math.Max(danStageData.HighScore, stageData.PlayScore);
danStageData.ComboCount = Math.Max(danStageData.ComboCount, stageData.ComboCnt);
@ -120,19 +121,18 @@ public class PlayResultController : BaseController<PlayResultController>
danStageData.OkCount = Math.Min(danStageData.OkCount, stageData.OkCnt);
danStageData.BadCount = Math.Min(danStageData.BadCount, stageData.NgCnt);
if (add)
var index = danScoreData.DanStageScoreData.IndexOf(danStageData);
if (index == -1)
{
context.DanStageScoreData.Add(danStageData);
continue;
danScoreData.DanStageScoreData.Add(danStageData);
}
context.DanStageScoreData.Update(danStageData);
}
}
private void UpdatePlayData(PlayResultRequest request, int songNumber, PlayResultDataRequest.StageData stageData, DateTime lastPlayDatetime)
private async Task UpdatePlayData(PlayResultRequest request, int songNumber, StageData stageData,
DateTime lastPlayDatetime)
{
var playData = new SongPlayDatum
var songPlayDatum = new SongPlayDatum
{
Baid = request.BaidConf,
SongNumber = (uint)songNumber,
@ -150,18 +150,15 @@ public class PlayResultController : BaseController<PlayResultController>
PlayTime = lastPlayDatetime,
Difficulty = (Difficulty)stageData.Level
};
context.SongPlayData.Add(playData);
await songPlayDatumService.AddSongPlayDatum(songPlayDatum);
}
private void UpdateUserData(PlayResultRequest request, PlayResultDataRequest playResultData, DateTime lastPlayDatetime)
private async Task UpdateUserData(PlayResultRequest request, PlayResultDataRequest playResultData,
DateTime lastPlayDatetime)
{
var userdata = new UserDatum
{
Baid = request.BaidConf
};
if (context.UserData.Any(datum => datum.Baid == request.BaidConf))
{
userdata = context.UserData.First(datum => datum.Baid == request.BaidConf);
}
var userdata = await userDatumService.GetFirstUserDatumOrNull(request.BaidConf);
userdata.ThrowIfNull();
userdata.Title = playResultData.Title;
userdata.TitlePlateId = playResultData.TitleplateId;
@ -184,49 +181,38 @@ public class PlayResultController : BaseController<PlayResultController>
userdata.LastPlayDatetime = lastPlayDatetime;
userdata.LastPlayMode = playResultData.PlayMode;
context.UserData.Update(userdata);
await userDatumService.UpdateUserDatum(userdata);
}
private void UpdateBestData(PlayResultRequest request, PlayResultDataRequest.StageData stageData, IEnumerable<SongBestDatum> bestData)
private async Task UpdateBestData(PlayResultRequest request, StageData stageData,
IEnumerable<SongBestDatum> bestData)
{
var insert = false;
var data = stageData;
var bestDatum = bestData
.FirstOrDefault(datum => datum.SongId == data.SongNo &&
datum.Difficulty == (Difficulty)data.Level);
.FirstOrDefault(datum => datum.SongId == stageData.SongNo &&
datum.Difficulty == (Difficulty)stageData.Level,
new SongBestDatum
{
Baid = request.BaidConf,
SongId = stageData.SongNo,
Difficulty = (Difficulty)stageData.Level
});
// Determine whether it is dondaful crown as this is not reflected by play result
var crown = PlayResultToCrown(stageData);
if (bestDatum is null)
{
insert = true;
bestDatum = new SongBestDatum
{
Baid = request.BaidConf,
SongId = stageData.SongNo,
Difficulty = (Difficulty)stageData.Level
};
}
bestDatum.UpdateBestData(crown, stageData.ScoreRank, stageData.PlayScore, stageData.ScoreRate);
if (insert)
{
context.SongBestData.Add(bestDatum);
}
else
{
context.SongBestData.Update(bestDatum);
}
await songBestDatumService.UpdateOrInsertSongBestDatum(bestDatum);
}
private static CrownType PlayResultToCrown(PlayResultDataRequest.StageData stageData)
private static CrownType PlayResultToCrown(StageData stageData)
{
var crown = (CrownType)stageData.PlayResult;
if (crown == CrownType.Gold && stageData.OkCnt == 0)
{
crown = CrownType.Dondaful;
}
return crown;
}
}

View File

@ -1,4 +1,5 @@
using Throw;
using TaikoLocalServer.Services.Interfaces;
using Throw;
namespace TaikoLocalServer.Controllers.Game;
@ -6,16 +7,16 @@ namespace TaikoLocalServer.Controllers.Game;
[ApiController]
public class SelfBestController : BaseController<SelfBestController>
{
private readonly TaikoDbContext context;
private readonly ISongBestDatumService songBestDatumService;
public SelfBestController(TaikoDbContext context)
public SelfBestController(ISongBestDatumService songBestDatumService)
{
this.context = context;
this.songBestDatumService = songBestDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult SelfBest([FromBody] SelfBestRequest request)
public async Task<IActionResult> SelfBest([FromBody] SelfBestRequest request)
{
Logger.LogInformation("SelfBest request : {Request}", request.Stringify());
@ -30,10 +31,10 @@ public class SelfBestController : BaseController<SelfBestController>
var requestDifficulty = (Difficulty)request.Level;
requestDifficulty.Throw().IfOutOfRange();
var playerBestData = context.SongBestData
.Where(datum => datum.Baid == request.Baid &&
(datum.Difficulty == requestDifficulty ||
(datum.Difficulty == Difficulty.UraOni && requestDifficulty == Difficulty.Oni)))
var playerBestData = await songBestDatumService.GetAllSongBestData(request.Baid);
playerBestData = playerBestData
.Where(datum => datum.Difficulty == requestDifficulty ||
(datum.Difficulty == Difficulty.UraOni && requestDifficulty == Difficulty.Oni))
.ToList();
foreach (var songNo in request.ArySongNoes)
{

View File

@ -1,6 +1,7 @@
using System.Buffers.Binary;
using System.Collections;
using System.Text.Json;
using TaikoLocalServer.Services.Interfaces;
using Throw;
namespace TaikoLocalServer.Controllers.Game;
@ -9,16 +10,19 @@ namespace TaikoLocalServer.Controllers.Game;
[ApiController]
public class UserDataController : BaseController<UserDataController>
{
private readonly TaikoDbContext context;
private readonly IUserDatumService userDatumService;
private readonly ISongPlayDatumService songPlayDatumService;
public UserDataController(TaikoDbContext context)
public UserDataController(IUserDatumService userDatumService, ISongPlayDatumService songPlayDatumService)
{
this.context = context;
this.userDatumService = userDatumService;
this.songPlayDatumService = songPlayDatumService;
}
[HttpPost]
[Produces("application/protobuf")]
public IActionResult GetUserData([FromBody] UserDataRequest request)
public async Task<IActionResult> GetUserData([FromBody] UserDataRequest request)
{
Logger.LogInformation("UserData request : {Request}", request.Stringify());
@ -43,8 +47,7 @@ public class UserDataController : BaseController<UserDataController>
var toneArray = new byte[16];
Array.Fill(toneArray, byte.MaxValue);
var recentSongs = context.SongPlayData
.Where(datum => datum.Baid == request.Baid)
var recentSongs = (await songPlayDatumService.GetSongPlayDatumByBaid(request.Baid))
.AsEnumerable()
.OrderByDescending(datum => datum.PlayTime)
.ThenByDescending(datum => datum.SongNumber)
@ -64,11 +67,7 @@ public class UserDataController : BaseController<UserDataController>
recentSongs = recentSet.ToArray();
var userData = new UserDatum();
if (context.UserData.Any(datum => datum.Baid == request.Baid))
{
userData = context.UserData.First(datum => datum.Baid == request.Baid);
}
var userData = await userDatumService.GetFirstUserDatumOrDefault(request.Baid);
var favoriteSongs = Array.Empty<uint>();
try

View File

@ -2,6 +2,9 @@ using System.Security.Authentication;
using Microsoft.AspNetCore.HttpLogging;
using Microsoft.AspNetCore.HttpOverrides;
using TaikoLocalServer.Middlewares;
using TaikoLocalServer.Services;
using TaikoLocalServer.Services.Extentions;
using TaikoLocalServer.Services.Interfaces;
using TaikoLocalServer.Settings;
var builder = WebApplication.CreateBuilder(args);
@ -44,6 +47,7 @@ builder.Services.AddCors(options =>
.AllowAnyHeader();
});
});
builder.Services.AddTaikoDbServices();
var app = builder.Build();

View File

@ -0,0 +1,51 @@
using SharedProject.Models;
using Swan.Mapping;
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Services;
public class CardService : ICardService
{
private readonly TaikoDbContext context;
public CardService(TaikoDbContext context)
{
this.context = context;
}
public async Task<Card?> GetCardByAccessCode(string accessCode)
{
return await context.Cards.FindAsync(accessCode);
}
public uint GetNextBaid()
{
return context.Cards.Any() ? context.Cards.Max(card => card.Baid) + 1 : 1;
}
public async Task<List<User>> GetUsersFromCards()
{
return await context.Cards.Select(card => card.CopyPropertiesToNew<User>(null)).ToListAsync();
}
public async Task AddCard(Card card)
{
context.Add(card);
await context.SaveChangesAsync();
}
public async Task<bool> DeleteCard(string accessCode)
{
var card = await context.Cards.FindAsync(accessCode);
if (card is null)
{
return false;
}
context.Cards.Remove(card);
await context.SaveChangesAsync();
return true;
}
}

View File

@ -0,0 +1,41 @@
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Services;
public class DanScoreDatumService : IDanScoreDatumService
{
private readonly TaikoDbContext context;
public DanScoreDatumService(TaikoDbContext context)
{
this.context = context;
}
public async Task<List<DanScoreDatum>> GetDanScoreDatumByBaid(uint baid)
{
return await context.DanScoreData.Where(datum => datum.Baid == baid)
.Include(datum => datum.DanStageScoreData)
.ToListAsync();
}
public async Task<DanScoreDatum?> GetSingleDanScoreDatum(uint baid, uint danId)
{
return await context.DanScoreData.Include(datum => datum.DanStageScoreData)
.FirstOrDefaultAsync(datum => datum.Baid == baid &&
datum.DanId == danId);
}
public async Task InsertOrUpdateDanScoreDatum(DanScoreDatum datum)
{
var existing = await context.DanScoreData.FindAsync(datum.Baid, datum.DanId);
if (existing is null)
{
await context.DanScoreData.AddAsync(datum);
await context.SaveChangesAsync();
return;
}
context.DanScoreData.Update(datum);
await context.SaveChangesAsync();
}
}

View File

@ -0,0 +1,17 @@
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Services.Extentions;
public static class ServiceExtensions
{
public static IServiceCollection AddTaikoDbServices(this IServiceCollection services)
{
services.AddScoped<ICardService, CardService>();
services.AddScoped<IUserDatumService, UserDatumService>();
services.AddScoped<ISongPlayDatumService, SongPlayDatumService>();
services.AddScoped<ISongBestDatumService, SongBestDatumService>();
services.AddScoped<IDanScoreDatumService, DanScoreDatumService>();
return services;
}
}

View File

@ -0,0 +1,16 @@
using SharedProject.Models;
namespace TaikoLocalServer.Services.Interfaces;
public interface ICardService
{
public Task<Card?> GetCardByAccessCode(string accessCode);
public uint GetNextBaid();
public Task<List<User>> GetUsersFromCards();
public Task AddCard(Card card);
public Task<bool> DeleteCard(string accessCode);
}

View File

@ -0,0 +1,10 @@
namespace TaikoLocalServer.Services.Interfaces;
public interface IDanScoreDatumService
{
public Task<List<DanScoreDatum>> GetDanScoreDatumByBaid(uint baid);
public Task<DanScoreDatum?> GetSingleDanScoreDatum(uint baid, uint danId);
public Task InsertOrUpdateDanScoreDatum(DanScoreDatum datum);
}

View File

@ -0,0 +1,8 @@
namespace TaikoLocalServer.Services.Interfaces;
public interface ISongBestDatumService
{
public Task<List<SongBestDatum>> GetAllSongBestData(uint baid);
public Task UpdateOrInsertSongBestDatum(SongBestDatum datum);
}

View File

@ -0,0 +1,8 @@
namespace TaikoLocalServer.Services.Interfaces;
public interface ISongPlayDatumService
{
public Task<List<SongPlayDatum>> GetSongPlayDatumByBaid(uint baid);
public Task AddSongPlayDatum(SongPlayDatum datum);
}

View File

@ -0,0 +1,16 @@
namespace TaikoLocalServer.Services.Interfaces;
public interface IUserDatumService
{
public Task<UserDatum?> GetFirstUserDatumOrNull(uint baid);
public Task<UserDatum> GetFirstUserDatumOrDefault(uint baid);
public Task<List<UserDatum>> GetAllUserData();
public Task UpdateOrInsertUserDatum(UserDatum userDatum);
public Task InsertUserDatum(UserDatum userDatum);
public Task UpdateUserDatum(UserDatum userDatum);
}

View File

@ -0,0 +1,35 @@
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Services;
public class SongBestDatumService : ISongBestDatumService
{
private readonly TaikoDbContext context;
public SongBestDatumService(TaikoDbContext context)
{
this.context = context;
}
public async Task<List<SongBestDatum>> GetAllSongBestData(uint baid)
{
return await context.SongBestData.Where(datum => datum.Baid == baid).ToListAsync();
}
public async Task UpdateOrInsertSongBestDatum(SongBestDatum datum)
{
var existing = await context.SongBestData.AnyAsync(
bestDatum => bestDatum.Baid == datum.Baid &&
bestDatum.Difficulty == datum.Difficulty &&
bestDatum.SongId == datum.SongId);
if (existing)
{
context.SongBestData.Update(datum);
await context.SaveChangesAsync();
return;
}
await context.SongBestData.AddAsync(datum);
await context.SaveChangesAsync();
}
}

View File

@ -0,0 +1,24 @@
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Services;
class SongPlayDatumService : ISongPlayDatumService
{
private readonly TaikoDbContext context;
public SongPlayDatumService(TaikoDbContext context)
{
this.context = context;
}
public async Task<List<SongPlayDatum>> GetSongPlayDatumByBaid(uint baid)
{
return await context.SongPlayData.Where(datum => datum.Baid == baid).ToListAsync();
}
public async Task AddSongPlayDatum(SongPlayDatum datum)
{
await context.SongPlayData.AddAsync(datum);
await context.SaveChangesAsync();
}
}

View File

@ -0,0 +1,53 @@
using TaikoLocalServer.Services.Interfaces;
namespace TaikoLocalServer.Services;
public class UserDatumService : IUserDatumService
{
private readonly TaikoDbContext context;
public UserDatumService(TaikoDbContext context)
{
this.context = context;
}
public async Task<UserDatum?> GetFirstUserDatumOrNull(uint baid)
{
return await context.UserData.FindAsync(baid);
}
public async Task<UserDatum> GetFirstUserDatumOrDefault(uint baid)
{
return await context.UserData.FindAsync(baid) ?? new UserDatum();
}
public async Task<List<UserDatum>> GetAllUserData()
{
return await context.UserData.ToListAsync();
}
public async Task UpdateOrInsertUserDatum(UserDatum userDatum)
{
if (await context.UserData.AnyAsync(datum => datum.Baid == userDatum.Baid))
{
context.UserData.Add(userDatum);
await context.SaveChangesAsync();
return;
}
context.Update(userDatum);
await context.SaveChangesAsync();
}
public async Task InsertUserDatum(UserDatum userDatum)
{
context.UserData.Add(userDatum);
await context.SaveChangesAsync();
}
public async Task UpdateUserDatum(UserDatum userDatum)
{
context.Update(userDatum);
await context.SaveChangesAsync();
}
}