Refactor db access
This commit is contained in:
parent
e3d8da41bd
commit
0f71da4353
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
51
TaikoLocalServer/Services/CardService.cs
Normal file
51
TaikoLocalServer/Services/CardService.cs
Normal 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;
|
||||
}
|
||||
}
|
41
TaikoLocalServer/Services/DanScoreDatumService.cs
Normal file
41
TaikoLocalServer/Services/DanScoreDatumService.cs
Normal 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();
|
||||
}
|
||||
}
|
17
TaikoLocalServer/Services/Extentions/ServiceExtensions.cs
Normal file
17
TaikoLocalServer/Services/Extentions/ServiceExtensions.cs
Normal 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;
|
||||
}
|
||||
}
|
16
TaikoLocalServer/Services/Interfaces/ICardService.cs
Normal file
16
TaikoLocalServer/Services/Interfaces/ICardService.cs
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace TaikoLocalServer.Services.Interfaces;
|
||||
|
||||
public interface ISongBestDatumService
|
||||
{
|
||||
public Task<List<SongBestDatum>> GetAllSongBestData(uint baid);
|
||||
|
||||
public Task UpdateOrInsertSongBestDatum(SongBestDatum datum);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace TaikoLocalServer.Services.Interfaces;
|
||||
|
||||
public interface ISongPlayDatumService
|
||||
{
|
||||
public Task<List<SongPlayDatum>> GetSongPlayDatumByBaid(uint baid);
|
||||
|
||||
public Task AddSongPlayDatum(SongPlayDatum datum);
|
||||
}
|
16
TaikoLocalServer/Services/Interfaces/IUserDatumService.cs
Normal file
16
TaikoLocalServer/Services/Interfaces/IUserDatumService.cs
Normal 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);
|
||||
}
|
35
TaikoLocalServer/Services/SongBestDatumService.cs
Normal file
35
TaikoLocalServer/Services/SongBestDatumService.cs
Normal 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();
|
||||
}
|
||||
}
|
24
TaikoLocalServer/Services/SongPlayDatumService.cs
Normal file
24
TaikoLocalServer/Services/SongPlayDatumService.cs
Normal 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();
|
||||
}
|
||||
}
|
53
TaikoLocalServer/Services/UserDatumService.cs
Normal file
53
TaikoLocalServer/Services/UserDatumService.cs
Normal 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user