From 003f655585f260542e237f1de6f4a958674b7bc3 Mon Sep 17 00:00:00 2001 From: Yuchen Ji Date: Mon, 20 Jun 2022 02:10:04 +0800 Subject: [PATCH] Update server for better query performance --- .../GC-local-server-rewrite.csproj | 6 +- .../controllers/ApiController.cs | 215 ++++++++++++++++-- SharedProject/SharedProject.csproj | 6 + SharedProject/enums/Difficulty.cs | 8 +- SharedProject/models/SongPlayData.cs | 2 +- SharedProject/models/UserDetail.cs | 4 + 6 files changed, 219 insertions(+), 22 deletions(-) diff --git a/GC-local-server-rewrite/GC-local-server-rewrite.csproj b/GC-local-server-rewrite/GC-local-server-rewrite.csproj index daafb88..abbc67a 100644 --- a/GC-local-server-rewrite/GC-local-server-rewrite.csproj +++ b/GC-local-server-rewrite/GC-local-server-rewrite.csproj @@ -11,13 +11,13 @@ - + - - + + diff --git a/GC-local-server-rewrite/controllers/ApiController.cs b/GC-local-server-rewrite/controllers/ApiController.cs index 01ceeeb..8f0295b 100644 --- a/GC-local-server-rewrite/controllers/ApiController.cs +++ b/GC-local-server-rewrite/controllers/ApiController.cs @@ -1,4 +1,5 @@ -using EmbedIO; +using ChoETL; +using EmbedIO; using EmbedIO.Routing; using EmbedIO.WebApi; using GCLocalServerRewrite.common; @@ -6,6 +7,7 @@ using GCLocalServerRewrite.models; using SharedProject.enums; using SharedProject.models; using SQLite.Net2; +using Swan.Logging; namespace GCLocalServerRewrite.controllers; @@ -13,24 +15,102 @@ public class ApiController : WebApiController { private readonly SQLiteConnection cardSqLiteConnection; + private readonly Dictionary musics; + private readonly Dictionary musicExtras; + public ApiController() { cardSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.CardDbName); + var musicSqLiteConnection = DatabaseHelper.ConnectDatabase(Configs.SETTINGS.MusicDbName); + musics = musicSqLiteConnection.Table().ToDictionary(music => music.MusicId); + musicExtras = musicSqLiteConnection.Table().ToDictionary(music => music.MusicId); } - - [Route(HttpVerbs.Get, "/PlayOption")] - public PlayOption? GetPlayOption([QueryField] long cardId) - { - var result = cardSqLiteConnection.Table() - .Where(detail => detail.CardId == cardId && - detail.Pcol1 == 0 && detail.Pcol2 == 0 && detail.Pcol3 == 0); - if (!result.Any()) + [Route(HttpVerbs.Get, "/Users")] + // ReSharper disable once UnusedMember.Global + public List GetUsers() + { + var result = cardSqLiteConnection.Table().ToList().ConvertAll(card => new User + { + CardId = card.CardId, + PlayerName = card.PlayerName + }); + + return result; + } + + [Route(HttpVerbs.Get, "/UserDetail/{cardId}")] + // ReSharper disable once UnusedMember.Global + public UserDetail? GetUserDetail(long cardId) + { + var cardResult = cardSqLiteConnection.Table().Where(card => card.CardId == cardId); + + if (!cardResult.Any()) { return null; } - var cardDetail = result.First(); + var card = cardResult.First(); + + return ToUserDetail(card); + } + + private UserDetail ToUserDetail(Card card) + { + var userDetail = new UserDetail + { + CardId = card.CardId, + PlayerName = card.PlayerName + }; + var songPlayDataDict = new Dictionary(); + + ProcessCardDetail(userDetail, songPlayDataDict); + + userDetail.SongPlayDataList = songPlayDataDict.Values.ToList(); + userDetail.TotalSongCount = musics.Count; + userDetail.TotalStageCount = userDetail.TotalSongCount * 3 + musicExtras.Count; + userDetail.AverageScore = (int)(userDetail.TotalScore / userDetail.PlayedStageCount); + userDetail.PlayedSongCount = songPlayDataDict.Count; + return userDetail; + } + + private void ProcessCardDetail(UserDetail userDetail, IDictionary songPlayDataDict) + { + var option = cardSqLiteConnection.Table() + .FirstOrDefault(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == 0, new CardDetail + { + CardId = userDetail.CardId + }); + SetOptions(option, userDetail); + + var songCounts = cardSqLiteConnection.Table() + .Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == 20); + + foreach (var detail in songCounts) + { + SetCounts(detail, songPlayDataDict, userDetail); + } + + var songScores = cardSqLiteConnection.Table() + .Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == 21); + + foreach (var detail in songScores) + { + SetDetails(detail, songPlayDataDict, userDetail); + } + + var favorites = cardSqLiteConnection.Table() + .Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == 10) + .ToDictionary(detail => detail.Pcol2); + + foreach (var (musicId, songPlayData) in songPlayDataDict) + { + songPlayData.IsFavorite = favorites[musicId].Fcol1 != 0; + } + } + + private static void SetOptions(CardDetail cardDetail, UserDetail userDetail) + { var fastSlow = (int)cardDetail.ScoreUi1; var feverTrance = (int)cardDetail.ScoreUi2; @@ -41,14 +121,121 @@ public class ApiController : WebApiController if (!Enum.IsDefined(typeof(PlayOptions.FeverTranceShow), feverTrance)) { - feverTrance = (int)PlayOptions.FeverTranceShow.NotUsed; + feverTrance = (int)PlayOptions.FeverTranceShow.Show; } - return new PlayOption + userDetail.PlayOption = new PlayOption { - CardId = cardId, + CardId = cardDetail.CardId, FastSlowIndicator = (PlayOptions.FastSlowIndicator)fastSlow, FeverTrance = (PlayOptions.FeverTranceShow)feverTrance }; - } + } + private void SetDetails(CardDetail cardDetail, IDictionary songPlayDataDict, + UserDetail userDetail) + { + var musicId = cardDetail.Pcol2; + + AddSongPlayDataIfNotExist(songPlayDataDict, musicId); + + for (var i = 0; i < 4; i++) + { + var songPlayDetailData = songPlayDataDict[musicId].SongPlaySubDataList[i]; + songPlayDetailData.Difficulty = (Difficulty)i; + + if (i != cardDetail.Pcol3) + { + continue; + } + + songPlayDetailData.Score = (int)cardDetail.ScoreUi1; + songPlayDetailData.MaxChain = (int)cardDetail.ScoreUi3; + + userDetail.TotalScore += cardDetail.ScoreUi1; + + if (cardDetail.ScoreUi1 >= 900000) + { + userDetail.SAboveStageCount++; + } + + if (cardDetail.ScoreUi1 >= 950000) + { + userDetail.SPlusAboveStageCount++; + } + + if (cardDetail.ScoreUi1 >= 990000) + { + userDetail.SPlusPlusAboveStageCount++; + } + } + } + + private void SetCounts(CardDetail cardDetail, IDictionary songPlayDataDict, UserDetail userDetail) + { + var musicId = cardDetail.Pcol2; + + AddSongPlayDataIfNotExist(songPlayDataDict, musicId); + + for (var i = 0; i < 4; i++) + { + var songPlayDetailData = songPlayDataDict[musicId].SongPlaySubDataList[i]; + + songPlayDetailData.Difficulty = (Difficulty)i; + + if (i != cardDetail.Pcol3) + { + continue; + } + + songPlayDetailData.PlayCount = (int)cardDetail.ScoreUi1; + songPlayDetailData.ClearState = ClearState.Failed; + userDetail.PlayedStageCount++; + + if (cardDetail.ScoreUi2 > 0) + { + userDetail.ClearedStageCount++; + songPlayDetailData.ClearState = ClearState.Clear; + } + + if (cardDetail.ScoreUi3 > 0) + { + userDetail.NoMissStageCount++; + songPlayDetailData.ClearState = ClearState.NoMiss; + } + + if (cardDetail.ScoreUi4 > 0) + { + userDetail.FullChainStageCount++; + songPlayDetailData.ClearState = ClearState.FullChain; + } + + if (cardDetail.ScoreUi6 > 0) + { + userDetail.PerfectStageCount++; + songPlayDetailData.ClearState = ClearState.Perfect; + } + } + } + + private void AddSongPlayDataIfNotExist(IDictionary songPlayDataDict, int musicId) + { + if (songPlayDataDict.ContainsKey(musicId)) + { + return; + } + + var musicData = musics[musicId]; + var songPlayData = new SongPlayData + { + Artist = musicData.Artist ?? string.Empty, + Title = musicData.Title ?? string.Empty, + SongPlaySubDataList = new SongPlayDetailData[4] + }; + + for (var i = 0; i < 4; i++) + { + songPlayData.SongPlaySubDataList[i] = new SongPlayDetailData(); + } + songPlayDataDict[musicId] = songPlayData; + } } \ No newline at end of file diff --git a/SharedProject/SharedProject.csproj b/SharedProject/SharedProject.csproj index 52b24a0..c647bae 100644 --- a/SharedProject/SharedProject.csproj +++ b/SharedProject/SharedProject.csproj @@ -7,4 +7,10 @@ SharedProject + + + + + + diff --git a/SharedProject/enums/Difficulty.cs b/SharedProject/enums/Difficulty.cs index abc02e2..3d7357c 100644 --- a/SharedProject/enums/Difficulty.cs +++ b/SharedProject/enums/Difficulty.cs @@ -2,8 +2,8 @@ public enum Difficulty { - Simple, - Normal, - Hard, - Extra + Simple = 0, + Normal = 1, + Hard = 2, + Extra = 3 } \ No newline at end of file diff --git a/SharedProject/models/SongPlayData.cs b/SharedProject/models/SongPlayData.cs index 18fec40..4f56ae9 100644 --- a/SharedProject/models/SongPlayData.cs +++ b/SharedProject/models/SongPlayData.cs @@ -6,7 +6,7 @@ public class SongPlayData public string Artist { get; set; } = string.Empty; - public List SongPlaySubDataList { get; set; } = new List(4); + public SongPlayDetailData[] SongPlaySubDataList { get; set; } = new SongPlayDetailData[4]; public bool IsFavorite { get; set; } diff --git a/SharedProject/models/UserDetail.cs b/SharedProject/models/UserDetail.cs index 90ec832..06dd528 100644 --- a/SharedProject/models/UserDetail.cs +++ b/SharedProject/models/UserDetail.cs @@ -12,6 +12,8 @@ public class UserDetail: User public int PlayedSongCount { get; set; } + public int PlayedStageCount { get; set; } + public int TotalStageCount { get; set; } public int ClearedStageCount { get; set; } @@ -27,4 +29,6 @@ public class UserDetail: User public int SPlusAboveStageCount { get; set; } public int SPlusPlusAboveStageCount { get; set; } + + public List? SongPlayDataList { get; set; } } \ No newline at end of file