From 7b3fae51b79719889afb5a8532179c0c6522a736 Mon Sep 17 00:00:00 2001 From: asesidaa <1061472754@qq.com> Date: Thu, 16 Feb 2023 15:26:13 +0800 Subject: [PATCH] Rank and unlock fixes --- Application/Common/Helpers/TimeHelper.cs | 4 +- Application/DependencyInjection.cs | 43 +- Application/Dto/CardDetailDto.cs | 4 +- Application/Dto/ScoreRankDto.cs | 54 +++ Application/Game/Card/Read/ReadAvatarQuery.cs | 4 +- Application/Game/Card/Read/ReadItemQuery.cs | 2 +- .../Game/Card/Read/ReadNavigatorQuery.cs | 4 +- Application/Game/Card/Read/ReadSkinQuery.cs | 2 +- .../Game/Card/Read/ReadSoundEffectQuery.cs | 2 +- Application/Game/Card/Read/ReadTitleQuery.cs | 2 +- Application/Game/Rank/GetEventRankQuery.cs | 2 +- .../Game/Rank/GetGlobalScoreRankQuery.cs | 35 +- .../Game/Rank/GetMonthlyScoreRankQuery.cs | 35 +- .../Game/Rank/GetTenpoScoreRankQuery.cs | 42 +- Application/Game/Server/CertifyCommand.cs | 4 +- Application/Interfaces/ICardDbContext.cs | 6 + Application/Jobs/MaintainTenpoIdJob.cs | 37 ++ Application/Jobs/UpdateGlobalScoreRankJob.cs | 120 ++++++ Application/Jobs/UpdateMonthlyScoreRankJob.cs | 117 ++++++ Application/Jobs/UpdatePlayNumRankJob.cs | 4 + Application/Mappers/CardBDatumMapper.cs | 4 + Application/Mappers/ScoreRankMapper.cs | 11 + Domain/Entities/GlobalScoreRank.cs | 6 + Domain/Entities/MonthlyScoreRank.cs | 6 + Domain/Entities/ScoreRank.cs | 33 ++ Domain/Entities/ShopScoreRank.cs | 6 + .../20230215165703_AddScoreRanks.Designer.cs | 377 ++++++++++++++++++ .../20230215165703_AddScoreRanks.cs | 99 +++++ .../Migrations/CardDbContextModelSnapshot.cs | 162 ++++++++ Infrastructure/Persistence/CardDbContext.cs | 72 ++++ MainServer/Configurations/game.json | 12 +- .../Controllers/Game/RankingController.cs | 5 +- doc/unlock_reward.md | 8 + 33 files changed, 1276 insertions(+), 48 deletions(-) create mode 100644 Application/Dto/ScoreRankDto.cs create mode 100644 Application/Jobs/MaintainTenpoIdJob.cs create mode 100644 Application/Jobs/UpdateGlobalScoreRankJob.cs create mode 100644 Application/Jobs/UpdateMonthlyScoreRankJob.cs create mode 100644 Application/Mappers/ScoreRankMapper.cs create mode 100644 Domain/Entities/GlobalScoreRank.cs create mode 100644 Domain/Entities/MonthlyScoreRank.cs create mode 100644 Domain/Entities/ScoreRank.cs create mode 100644 Domain/Entities/ShopScoreRank.cs create mode 100644 Infrastructure/Migrations/20230215165703_AddScoreRanks.Designer.cs create mode 100644 Infrastructure/Migrations/20230215165703_AddScoreRanks.cs create mode 100644 doc/unlock_reward.md diff --git a/Application/Common/Helpers/TimeHelper.cs b/Application/Common/Helpers/TimeHelper.cs index b5d31bf..a14bd26 100644 --- a/Application/Common/Helpers/TimeHelper.cs +++ b/Application/Common/Helpers/TimeHelper.cs @@ -4,11 +4,11 @@ public static class TimeHelper { public static string CurrentTimeToString() { - return DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"); + return DateTime.Now.ToString("yyyy/MM/dd hh:mm:ss"); } public static string DateToString(DateTime time) { - return time.ToString("yyyy-MM-dd"); + return time.ToString("yyyy/MM/dd hh:mm:ss"); } } \ No newline at end of file diff --git a/Application/DependencyInjection.cs b/Application/DependencyInjection.cs index 242bb3b..3106887 100644 --- a/Application/DependencyInjection.cs +++ b/Application/DependencyInjection.cs @@ -20,12 +20,11 @@ public static class DependencyInjection services.AddQuartz(q => { q.UseMicrosoftDependencyInjectionJobFactory(); - var jobKey = new JobKey("UpdatePlayNumRankJob"); - q.AddJob(options => options.WithIdentity(jobKey)); - + + q.AddJob(options => options.WithIdentity(UpdatePlayNumRankJob.KEY)); q.AddTrigger(options => { - options.ForJob(jobKey) + options.ForJob(UpdatePlayNumRankJob.KEY) .WithIdentity("UpdatePlayNumRankJob-trigger") .StartNow() .WithSimpleSchedule(x => @@ -33,6 +32,42 @@ public static class DependencyInjection x.WithIntervalInHours(24).RepeatForever(); }); }); + + q.AddJob(options => options.WithIdentity(UpdateGlobalScoreRankJob.KEY)); + q.AddTrigger(options => + { + options.ForJob(UpdateGlobalScoreRankJob.KEY) + .WithIdentity("UpdateGlobalScoreRankJob-trigger") + .StartNow() + .WithSimpleSchedule(x => + { + x.WithIntervalInHours(24).RepeatForever(); + }); + }); + + q.AddJob(options => options.WithIdentity(UpdateMonthlyScoreRankJob.KEY)); + q.AddTrigger(options => + { + options.ForJob(UpdateMonthlyScoreRankJob.KEY) + .WithIdentity("UpdateMonthlyScoreRankJob-trigger") + .StartNow() + .WithSimpleSchedule(x => + { + x.WithIntervalInHours(24).RepeatForever(); + }); + }); + + q.AddJob(options => options.WithIdentity(MaintainTenpoIdJob.KEY)); + q.AddTrigger(options => + { + options.ForJob(MaintainTenpoIdJob.KEY) + .WithIdentity("MaintainTenpoIdJob-trigger") + .StartNow() + .WithSimpleSchedule(x => + { + x.WithIntervalInHours(24).RepeatForever(); + }); + }); }); services.AddQuartzHostedService(options => { diff --git a/Application/Dto/CardDetailDto.cs b/Application/Dto/CardDetailDto.cs index 8808023..d38dd6a 100644 --- a/Application/Dto/CardDetailDto.cs +++ b/Application/Dto/CardDetailDto.cs @@ -50,8 +50,8 @@ public class CardDetailDto public long ScoreBi1 { get; set; } [XmlElement(ElementName = "last_play_tenpo_id")] - [DefaultValue("GC local server")] - public string LastPlayTenpoId { get; set; } = "GC local server"; + [DefaultValue("1337")] + public string LastPlayTenpoId { get; set; } = "1337"; [XmlElement("fcol1")] public int Fcol1 { get; set; } diff --git a/Application/Dto/ScoreRankDto.cs b/Application/Dto/ScoreRankDto.cs new file mode 100644 index 0000000..676b1fe --- /dev/null +++ b/Application/Dto/ScoreRankDto.cs @@ -0,0 +1,54 @@ +using System.Xml.Serialization; + +namespace Application.Dto; + +public class ScoreRankDto +{ + [XmlAttribute(AttributeName = "id")] + public int Id { get; set; } + + [XmlElement(ElementName = "card_id")] + public long CardId { get; set; } + + [XmlElement(ElementName = "player_name")] + public string PlayerName { get; set; } = string.Empty; + + [XmlElement(ElementName = "rank")] + public long Rank { get; set; } + + [XmlElement(ElementName = "rank2")] + public long Rank2 { get; set; } + + [XmlElement(ElementName = "score_bi1")] + public long TotalScore { get; set; } + + [XmlElement(ElementName = "score_i1")] + public int AvatarId { get; set; } + + [XmlElement(ElementName = "fcol2")] + public long TitleId { get; set; } + + [XmlElement(ElementName = "fcol1")] + public long Fcol1 { get; set; } + + [XmlElement(ElementName = "pref_id")] + public int PrefId { get; set; } + + [XmlElement(ElementName = "pref")] + public string Pref { get; set; } = string.Empty; + + [XmlElement(ElementName = "area_id")] + public int AreaId { get; set; } + + [XmlElement(ElementName = "area")] + public string Area { get; set; } = string.Empty; + + [XmlElement(ElementName = "last_play_tenpo_id")] + public int LastPlayTenpoId { get; set; } + + [XmlElement(ElementName = "tenpo_name")] + public string TenpoName { get; set; } = string.Empty; + + [XmlElement(ElementName = "title")] + public string Title { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/Application/Game/Card/Read/ReadAvatarQuery.cs b/Application/Game/Card/Read/ReadAvatarQuery.cs index 9cb1f55..11af88e 100644 --- a/Application/Game/Card/Read/ReadAvatarQuery.cs +++ b/Application/Game/Card/Read/ReadAvatarQuery.cs @@ -30,11 +30,11 @@ public class ReadAvatarQueryHandler : CardRequestHandlerBase(), Status = new RankStatus { - TableName = "TenpoScoreRank", + TableName = "EventRank", StartDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today), Rows = 0, diff --git a/Application/Game/Rank/GetGlobalScoreRankQuery.cs b/Application/Game/Rank/GetGlobalScoreRankQuery.cs index 2cc68a5..62e6759 100644 --- a/Application/Game/Rank/GetGlobalScoreRankQuery.cs +++ b/Application/Game/Rank/GetGlobalScoreRankQuery.cs @@ -2,7 +2,10 @@ using Application.Common.Extensions; using Application.Common.Helpers; using Application.Common.Models; +using Application.Dto; using Application.Interfaces; +using Application.Mappers; +using Microsoft.EntityFrameworkCore; namespace Application.Game.Rank; @@ -10,22 +13,40 @@ public record GetGlobalScoreRankQuery() : IRequestWrapper; public class GetGlobalScoreRankQueryHandler : IRequestHandlerWrapper { - public Task> Handle(GetGlobalScoreRankQuery request, CancellationToken cancellationToken) + private readonly ICardDbContext cardDbContext; + + public GetGlobalScoreRankQueryHandler(ICardDbContext cardDbContext) { + this.cardDbContext = cardDbContext; + } + + public async Task> Handle(GetGlobalScoreRankQuery request, CancellationToken cancellationToken) + { + var ranks = await cardDbContext.GlobalScoreRanks.OrderBy(rank => rank.Rank) + .Take(30).ToListAsync(cancellationToken: cancellationToken); + + var dtoList = ranks.Select((rank, i) => + { + var dto = rank.ScoreRankToDto(); + dto.Id = i; + dto.Rank2 = dto.Rank; + return dto; + }).ToList(); + var container = new GlobalScoreRankContainer { - Ranks = new List(), + Ranks = dtoList, Status = new RankStatus { - TableName = "TenpoScoreRank", + TableName = "GlobalScoreRank", StartDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today), - Rows = 0, - Status = 0 + Rows = dtoList.Count, + Status = 1 } }; - return Task.FromResult(new ServiceResult(container.SerializeCardData())); + return new ServiceResult(container.SerializeCardData()); } } @@ -35,7 +56,7 @@ public class GlobalScoreRankContainer [XmlArray(ElementName = "score_rank")] [XmlArrayItem(ElementName = "record")] // ReSharper disable once UnusedAutoPropertyAccessor.Global - public List Ranks { get; init; } = new(); + public List Ranks { get; init; } = new(); [XmlElement("ranking_status")] public RankStatus Status { get; set; } = new(); diff --git a/Application/Game/Rank/GetMonthlyScoreRankQuery.cs b/Application/Game/Rank/GetMonthlyScoreRankQuery.cs index 354d3bf..915846f 100644 --- a/Application/Game/Rank/GetMonthlyScoreRankQuery.cs +++ b/Application/Game/Rank/GetMonthlyScoreRankQuery.cs @@ -2,7 +2,10 @@ using Application.Common.Extensions; using Application.Common.Helpers; using Application.Common.Models; +using Application.Dto; using Application.Interfaces; +using Application.Mappers; +using Microsoft.EntityFrameworkCore; namespace Application.Game.Rank; @@ -10,22 +13,40 @@ public record GetMonthlyScoreRankQuery() : IRequestWrapper; public class GetMonthlyScoreRankQueryHandler : IRequestHandlerWrapper { - public Task> Handle(GetMonthlyScoreRankQuery request, CancellationToken cancellationToken) + private readonly ICardDbContext cardDbContext; + + public GetMonthlyScoreRankQueryHandler(ICardDbContext cardDbContext) { + this.cardDbContext = cardDbContext; + } + + public async Task> Handle(GetMonthlyScoreRankQuery request, CancellationToken cancellationToken) + { + var ranks = await cardDbContext.MonthlyScoreRanks.OrderBy(rank => rank.Rank) + .Take(30).ToListAsync(cancellationToken: cancellationToken); + + var dtoList = ranks.Select((rank, i) => + { + var dto = rank.ScoreRankToDto(); + dto.Id = i; + dto.Rank2 = dto.Rank; + return dto; + }).ToList(); + var container = new MonthlyScoreRankContainer { - Ranks = new List(), + Ranks = dtoList, Status = new RankStatus { - TableName = "TenpoScoreRank", + TableName = "MonthlyScoreRank", StartDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today), - Rows = 0, - Status = 0 + Rows = dtoList.Count, + Status = 1 } }; - return Task.FromResult(new ServiceResult(container.SerializeCardData())); + return new ServiceResult(container.SerializeCardData()); } } @@ -35,7 +56,7 @@ public class MonthlyScoreRankContainer [XmlArray(ElementName = "m_score_rank")] [XmlArrayItem(ElementName = "record")] // ReSharper disable once UnusedAutoPropertyAccessor.Global - public List Ranks { get; init; } = new(); + public List Ranks { get; init; } = new(); [XmlElement("ranking_status")] public RankStatus Status { get; set; } = new(); diff --git a/Application/Game/Rank/GetTenpoScoreRankQuery.cs b/Application/Game/Rank/GetTenpoScoreRankQuery.cs index 2988cd4..325b0b2 100644 --- a/Application/Game/Rank/GetTenpoScoreRankQuery.cs +++ b/Application/Game/Rank/GetTenpoScoreRankQuery.cs @@ -4,29 +4,57 @@ using Application.Common.Helpers; using Application.Common.Models; using Application.Dto; using Application.Interfaces; +using Application.Mappers; +using Domain.Entities; +using Microsoft.EntityFrameworkCore; namespace Application.Game.Rank; -public record GetTenpoScoreRankQuery() : IRequestWrapper; +public record GetTenpoScoreRankQuery(int TenpoId) : IRequestWrapper; public class GetTenpoScoreRankQueryHandler : IRequestHandlerWrapper { - public Task> Handle(GetTenpoScoreRankQuery request, CancellationToken cancellationToken) + private readonly ICardDbContext cardDbContext; + + public GetTenpoScoreRankQueryHandler(ICardDbContext cardDbContext) { + this.cardDbContext = cardDbContext; + } + + public async Task> Handle(GetTenpoScoreRankQuery request, CancellationToken cancellationToken) + { + var ranks = await cardDbContext.GlobalScoreRanks.Where(rank => rank.LastPlayTenpoId == request.TenpoId) + .OrderByDescending(rank => rank.TotalScore) + .Take(30) + .ToListAsync(cancellationToken: cancellationToken); + ranks = ranks.Select((rank, i) => + { + rank.Rank = i + 1; + return rank; + }).ToList(); + + var dtoList = ranks.Select((rank, i) => + { + var dto = rank.ScoreRankToDto(); + dto.Id = i; + dto.Rank2 = dto.Rank; + return dto; + }).ToList(); + var container = new TenpoScoreRankContainer { - Ranks = new List(), + Ranks = dtoList, Status = new RankStatus { TableName = "TenpoScoreRank", StartDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today), - Rows = 0, - Status = 0 + Rows = dtoList.Count, + Status = 1 } }; - return Task.FromResult(new ServiceResult(container.SerializeCardData())); + return new ServiceResult(container.SerializeCardData()); } } @@ -36,7 +64,7 @@ public class TenpoScoreRankContainer [XmlArray(ElementName = "t_score_rank")] [XmlArrayItem(ElementName = "record")] // ReSharper disable once UnusedAutoPropertyAccessor.Global - public List Ranks { get; init; } = new(); + public List Ranks { get; init; } = new(); [XmlElement("ranking_status")] public RankStatus Status { get; set; } = new(); diff --git a/Application/Game/Server/CertifyCommand.cs b/Application/Game/Server/CertifyCommand.cs index e8f7fe5..9b9058a 100644 --- a/Application/Game/Server/CertifyCommand.cs +++ b/Application/Game/Server/CertifyCommand.cs @@ -57,9 +57,9 @@ public partial class CertifyCommandHandler : IRequestHandler CardPlayCounts { get; set; } public DbSet PlayNumRanks { get; set; } + + public DbSet GlobalScoreRanks { get; set; } + + public DbSet MonthlyScoreRanks { get; set; } + + public DbSet ShopScoreRanks { get; set; } public Task SaveChangesAsync(CancellationToken cancellationToken); diff --git a/Application/Jobs/MaintainTenpoIdJob.cs b/Application/Jobs/MaintainTenpoIdJob.cs new file mode 100644 index 0000000..d1ea338 --- /dev/null +++ b/Application/Jobs/MaintainTenpoIdJob.cs @@ -0,0 +1,37 @@ +using System.Diagnostics.CodeAnalysis; +using Application.Interfaces; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Quartz; + +namespace Application.Jobs; + +public class MaintainTenpoIdJob : IJob +{ + private readonly ILogger logger; + + private readonly ICardDbContext cardDbContext; + + public static readonly JobKey KEY = new("MaintainTenpoIdJob"); + + public MaintainTenpoIdJob(ILogger logger, ICardDbContext cardDbContext) + { + this.logger = logger; + this.cardDbContext = cardDbContext; + } + + [SuppressMessage("ReSharper.DPA", "DPA0007: Large number of DB records", + Justification = "All details might be read")] + public async Task Execute(IJobExecutionContext context) + { + logger.LogInformation("Starting changing null values in card detail table"); + + var details = await cardDbContext.CardDetails.Where(detail => detail.LastPlayTenpoId == null).ToListAsync(); + details.ForEach(detail => detail.LastPlayTenpoId="1337"); + + cardDbContext.CardDetails.UpdateRange(details); + var count = await cardDbContext.SaveChangesAsync(new CancellationToken()); + + logger.LogInformation("Updated {Count} entries in card detail table", count); + } +} \ No newline at end of file diff --git a/Application/Jobs/UpdateGlobalScoreRankJob.cs b/Application/Jobs/UpdateGlobalScoreRankJob.cs new file mode 100644 index 0000000..41ff884 --- /dev/null +++ b/Application/Jobs/UpdateGlobalScoreRankJob.cs @@ -0,0 +1,120 @@ +using System.Diagnostics.CodeAnalysis; +using Application.Interfaces; +using Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Quartz; + +namespace Application.Jobs; + +public class UpdateGlobalScoreRankJob : IJob +{ + private readonly ILogger logger; + + private readonly ICardDbContext cardDbContext; + + public static readonly JobKey KEY = new("UpdateGlobalScoreRankJob"); + + public UpdateGlobalScoreRankJob(ILogger logger, ICardDbContext cardDbContext) + { + this.logger = logger; + this.cardDbContext = cardDbContext; + } + + [SuppressMessage("ReSharper.DPA", "DPA0007: Large number of DB records", + Justification = "All play record will be read")] + public async Task Execute(IJobExecutionContext context) + { + logger.LogInformation("Starting update global rank"); + + var cardMains = await cardDbContext.CardMains.ToListAsync(); + + var totalScoresByCardId = await cardDbContext.CardDetails.Where(detail => detail.Pcol1 == 21) + .GroupBy(detail => detail.CardId) + .Select(detailGroup => new + { + CardId = detailGroup.Key, + TotalScore = detailGroup.Sum(detail => detail.ScoreUi1) + }) + .ToListAsync(); + + var avatarAndTitles = await cardDbContext.CardDetails.Where(detail => detail.Pcol1 == 0 && + detail.Pcol2 == 0 && + detail.Pcol3 == 0).ToListAsync(); + + var ranks = new List(); + foreach (var record in totalScoresByCardId) + { + var cardId = record.CardId; + var score = record.TotalScore; + var card = cardMains.FirstOrDefault(card => card.CardId == cardId); + if (card is null) + { + logger.LogWarning("Card id {CardId} missing in main card table!", cardId); + continue; + } + + var detail = avatarAndTitles.First(detail => detail.CardId == cardId); + + var globalRank = new GlobalScoreRank + { + CardId = cardId, + PlayerName = card.PlayerName, + Fcol1 = detail.Fcol1, + Area = "Local", + AreaId = 1, + Pref = "nesys", + PrefId = 1337, + LastPlayTenpoId = 1337, + TenpoName = "GCLocalServer", + AvatarId = (int)detail.ScoreI1, + Title = "Title", + TitleId = detail.Fcol2, + TotalScore = score + }; + + ranks.Add(globalRank); + } + + ranks.AddRange(GetFakeRanks()); + ranks.Sort((rank, other) => -rank.TotalScore.CompareTo(other.TotalScore)); + ranks = ranks.Select((rank, i) => + { + rank.Rank = i + 1; + return rank; + }).ToList(); + + await cardDbContext.GlobalScoreRanks.UpsertRange(ranks).RunAsync(); + await cardDbContext.SaveChangesAsync(new CancellationToken()); + + logger.LogInformation("Updating global score rank done"); + } + + private static IEnumerable GetFakeRanks() + { + var fakeList = new List(); + for (int i = 0; i < 5; i++) + { + var rank = new GlobalScoreRank + { + CardId = 1020392010281502 + i, + PlayerName = $"Fake{i}", + Fcol1 = 0, + Area = "Local", + AreaId = 1, + Pref = "nesys", + PrefId = 1337, + LastPlayTenpoId = 1337, + TenpoName = "GCLocalServer", + AvatarId = i + 10, + Title = "Title", + TitleId = i + 100, + TotalScore = (i + 1) * 1000000 + }; + + fakeList.Add(rank); + } + + return fakeList; + } +} \ No newline at end of file diff --git a/Application/Jobs/UpdateMonthlyScoreRankJob.cs b/Application/Jobs/UpdateMonthlyScoreRankJob.cs new file mode 100644 index 0000000..f30191b --- /dev/null +++ b/Application/Jobs/UpdateMonthlyScoreRankJob.cs @@ -0,0 +1,117 @@ +using Application.Interfaces; +using Domain.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Quartz; + +namespace Application.Jobs; + +public class UpdateMonthlyScoreRankJob : IJob +{ + private readonly ILogger logger; + + private readonly ICardDbContext cardDbContext; + + public static readonly JobKey KEY = new JobKey("UpdateMonthlyScoreRankJob"); + + public UpdateMonthlyScoreRankJob(ILogger logger, ICardDbContext cardDbContext) + { + this.logger = logger; + this.cardDbContext = cardDbContext; + } + + public async Task Execute(IJobExecutionContext context) + { + logger.LogInformation("Starting update montly global rank"); + + var cardMains = await cardDbContext.CardMains.ToListAsync(); + + var totalScoresByCardId = await cardDbContext.CardDetails.Where(detail => detail.Pcol1 == 21 && detail.LastPlayTime >= DateTime.Today.AddDays(-30)) + .GroupBy(detail => detail.CardId) + .Select(detailGroup => new + { + CardId = detailGroup.Key, + TotalScore = detailGroup.Sum(detail => detail.ScoreUi1) + }) + .ToListAsync(); + + var avatarAndTitles = await cardDbContext.CardDetails.Where(detail => detail.Pcol1 == 0 && + detail.Pcol2 == 0 && + detail.Pcol3 == 0).ToListAsync(); + + var ranks = new List(); + foreach (var record in totalScoresByCardId) + { + var cardId = record.CardId; + var score = record.TotalScore; + var card = cardMains.FirstOrDefault(card => card.CardId == cardId); + if (card is null) + { + logger.LogWarning("Card id {CardId} missing in main card table!", cardId); + continue; + } + + var detail = avatarAndTitles.First(detail => detail.CardId == cardId); + + var globalRank = new MonthlyScoreRank + { + CardId = cardId, + PlayerName = card.PlayerName, + Fcol1 = detail.Fcol1, + Area = "Local", + AreaId = 1, + Pref = "nesys", + PrefId = 1337, + LastPlayTenpoId = 1337, + TenpoName = "GCLocalServer", + AvatarId = (int)detail.ScoreI1, + Title = "Title", + TitleId = detail.Fcol2, + TotalScore = score + }; + + ranks.Add(globalRank); + } + + ranks.AddRange(GetFakeRanks()); + ranks.Sort((rank, other) => -rank.TotalScore.CompareTo(other.TotalScore)); + ranks = ranks.Select((rank, i) => + { + rank.Rank = i + 1; + return rank; + }).ToList(); + + await cardDbContext.MonthlyScoreRanks.UpsertRange(ranks).RunAsync(); + await cardDbContext.SaveChangesAsync(new CancellationToken()); + + logger.LogInformation("Updating monthly score rank done"); + } + + private static IEnumerable GetFakeRanks() + { + var fakeList = new List(); + for (int i = 0; i < 5; i++) + { + var rank = new MonthlyScoreRank + { + CardId = 1020392010281502 + i, + PlayerName = $"Fake{i}", + Fcol1 = 0, + Area = "Local", + AreaId = 1, + Pref = "nesys", + PrefId = 1337, + LastPlayTenpoId = 1337, + TenpoName = "GCLocalServer", + AvatarId = i + 10, + Title = "Title", + TitleId = i + 100, + TotalScore = (i + 1) * 1000000 + }; + + fakeList.Add(rank); + } + + return fakeList; + } +} \ No newline at end of file diff --git a/Application/Jobs/UpdatePlayNumRankJob.cs b/Application/Jobs/UpdatePlayNumRankJob.cs index 69d842e..96b1739 100644 --- a/Application/Jobs/UpdatePlayNumRankJob.cs +++ b/Application/Jobs/UpdatePlayNumRankJob.cs @@ -14,6 +14,8 @@ public class UpdatePlayNumRankJob : IJob private readonly ICardDbContext cardDbContext; private readonly IMusicDbContext musicDbContext; + + public static readonly JobKey KEY = new JobKey("UpdatePlayNumRankJob"); public UpdatePlayNumRankJob(ILogger logger, ICardDbContext cardDbContext, IMusicDbContext musicDbContext) @@ -61,5 +63,7 @@ public class UpdatePlayNumRankJob : IJob }).ToList(); await cardDbContext.PlayNumRanks.UpsertRange(result).RunAsync(); await cardDbContext.SaveChangesAsync(new CancellationToken()); + + logger.LogInformation("Updating play num rank done"); } } \ No newline at end of file diff --git a/Application/Mappers/CardBDatumMapper.cs b/Application/Mappers/CardBDatumMapper.cs index a457cec..2f3399e 100644 --- a/Application/Mappers/CardBDatumMapper.cs +++ b/Application/Mappers/CardBDatumMapper.cs @@ -7,7 +7,11 @@ namespace Application.Mappers; [Mapper] public static partial class CardBDatumMapper { + [MapProperty(nameof(CardBdatum.Bdata), nameof(CardBDatumDto.CardBdata))] + [MapProperty(nameof(CardBdatum.BdataSize), nameof(CardBDatumDto.BDataSize))] public static partial CardBDatumDto CardBDatumToDto(this CardBdatum cardBdatum); + [MapProperty(nameof(CardBDatumDto.CardBdata), nameof(CardBdatum.Bdata))] + [MapProperty(nameof(CardBDatumDto.BDataSize), nameof(CardBdatum.BdataSize))] public static partial CardBdatum DtoToCardBDatum(this CardBDatumDto dto); } \ No newline at end of file diff --git a/Application/Mappers/ScoreRankMapper.cs b/Application/Mappers/ScoreRankMapper.cs new file mode 100644 index 0000000..212da2f --- /dev/null +++ b/Application/Mappers/ScoreRankMapper.cs @@ -0,0 +1,11 @@ +using Application.Dto; +using Domain.Entities; +using Riok.Mapperly.Abstractions; + +namespace Application.Mappers; + +[Mapper] +public static partial class ScoreRankMapper +{ + public static partial ScoreRankDto ScoreRankToDto(this ScoreRank rank); +} \ No newline at end of file diff --git a/Domain/Entities/GlobalScoreRank.cs b/Domain/Entities/GlobalScoreRank.cs new file mode 100644 index 0000000..93c10af --- /dev/null +++ b/Domain/Entities/GlobalScoreRank.cs @@ -0,0 +1,6 @@ +namespace Domain.Entities; + +public class GlobalScoreRank : ScoreRank +{ + +} \ No newline at end of file diff --git a/Domain/Entities/MonthlyScoreRank.cs b/Domain/Entities/MonthlyScoreRank.cs new file mode 100644 index 0000000..be97c23 --- /dev/null +++ b/Domain/Entities/MonthlyScoreRank.cs @@ -0,0 +1,6 @@ +namespace Domain.Entities; + +public class MonthlyScoreRank : ScoreRank +{ + +} \ No newline at end of file diff --git a/Domain/Entities/ScoreRank.cs b/Domain/Entities/ScoreRank.cs new file mode 100644 index 0000000..fd1c481 --- /dev/null +++ b/Domain/Entities/ScoreRank.cs @@ -0,0 +1,33 @@ +namespace Domain.Entities; + +public class ScoreRank +{ + public long CardId { get; set; } + + public string PlayerName { get; set; } = string.Empty; + + public long Rank { get; set; } + + public long TotalScore { get; set; } + + public int AvatarId { get; set; } + + public long TitleId { get; set; } + + public long Fcol1 { get; set; } + + public int PrefId { get; set; } + + public string Pref { get; set; } = string.Empty; + + public int AreaId { get; set; } + + public string Area { get; set; } = string.Empty; + + public int LastPlayTenpoId { get; set; } + + public string TenpoName { get; set; } = string.Empty; + + public string Title { get; set; } = string.Empty; + +} \ No newline at end of file diff --git a/Domain/Entities/ShopScoreRank.cs b/Domain/Entities/ShopScoreRank.cs new file mode 100644 index 0000000..0f861ae --- /dev/null +++ b/Domain/Entities/ShopScoreRank.cs @@ -0,0 +1,6 @@ +namespace Domain.Entities; + +public class ShopScoreRank : ScoreRank +{ + +} \ No newline at end of file diff --git a/Infrastructure/Migrations/20230215165703_AddScoreRanks.Designer.cs b/Infrastructure/Migrations/20230215165703_AddScoreRanks.Designer.cs new file mode 100644 index 0000000..8cf08a0 --- /dev/null +++ b/Infrastructure/Migrations/20230215165703_AddScoreRanks.Designer.cs @@ -0,0 +1,377 @@ +// +using Infrastructure.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Infrastructure.Migrations +{ + [DbContext(typeof(CardDbContext))] + [Migration("20230215165703_AddScoreRanks")] + partial class AddScoreRanks + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "7.0.2"); + + modelBuilder.Entity("Domain.Entities.CardBdatum", b => + { + b.Property("CardId") + .HasColumnType("INTEGER") + .HasColumnName("card_id"); + + b.Property("Bdata") + .HasColumnType("TEXT") + .HasColumnName("bdata"); + + b.Property("BdataSize") + .HasColumnType("INTEGER") + .HasColumnName("bdata_size"); + + b.HasKey("CardId"); + + b.ToTable("card_bdata", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.CardDetail", b => + { + b.Property("CardId") + .HasColumnType("INTEGER") + .HasColumnName("card_id"); + + b.Property("Pcol1") + .HasColumnType("INTEGER") + .HasColumnName("pcol1"); + + b.Property("Pcol2") + .HasColumnType("INTEGER") + .HasColumnName("pcol2"); + + b.Property("Pcol3") + .HasColumnType("INTEGER") + .HasColumnName("pcol3"); + + b.Property("Fcol1") + .HasColumnType("INTEGER") + .HasColumnName("fcol1"); + + b.Property("Fcol2") + .HasColumnType("INTEGER") + .HasColumnName("fcol2"); + + b.Property("Fcol3") + .HasColumnType("INTEGER") + .HasColumnName("fcol3"); + + b.Property("LastPlayTenpoId") + .HasColumnType("TEXT") + .HasColumnName("last_play_tenpo_id"); + + b.Property("LastPlayTime") + .HasColumnType("INTEGER") + .HasColumnName("last_play_time"); + + b.Property("ScoreBi1") + .HasColumnType("INTEGER") + .HasColumnName("score_bi1"); + + b.Property("ScoreI1") + .HasColumnType("INTEGER") + .HasColumnName("score_i1"); + + b.Property("ScoreUi1") + .HasColumnType("INTEGER") + .HasColumnName("score_ui1"); + + b.Property("ScoreUi2") + .HasColumnType("INTEGER") + .HasColumnName("score_ui2"); + + b.Property("ScoreUi3") + .HasColumnType("INTEGER") + .HasColumnName("score_ui3"); + + b.Property("ScoreUi4") + .HasColumnType("INTEGER") + .HasColumnName("score_ui4"); + + b.Property("ScoreUi5") + .HasColumnType("INTEGER") + .HasColumnName("score_ui5"); + + b.Property("ScoreUi6") + .HasColumnType("INTEGER") + .HasColumnName("score_ui6"); + + b.HasKey("CardId", "Pcol1", "Pcol2", "Pcol3"); + + b.ToTable("card_detail", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.CardMain", b => + { + b.Property("CardId") + .HasColumnType("INTEGER") + .HasColumnName("card_id"); + + b.Property("AchieveStatus") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("achieve_status"); + + b.Property("Created") + .HasColumnType("TEXT") + .HasColumnName("created"); + + b.Property("Fcol1") + .HasColumnType("INTEGER") + .HasColumnName("fcol1"); + + b.Property("Fcol2") + .HasColumnType("INTEGER") + .HasColumnName("fcol2"); + + b.Property("Fcol3") + .HasColumnType("INTEGER") + .HasColumnName("fcol3"); + + b.Property("Modified") + .HasColumnType("TEXT") + .HasColumnName("modified"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("player_name"); + + b.Property("ScoreI1") + .HasColumnType("INTEGER") + .HasColumnName("score_i1"); + + b.HasKey("CardId"); + + b.ToTable("card_main", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.CardPlayCount", b => + { + b.Property("CardId") + .HasColumnType("INTEGER") + .HasColumnName("card_id"); + + b.Property("LastPlayedTime") + .HasColumnType("INTEGER") + .HasColumnName("last_played_time"); + + b.Property("PlayCount") + .HasColumnType("INTEGER") + .HasColumnName("play_count"); + + b.HasKey("CardId"); + + b.ToTable("CardPlayCount", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.GlobalScoreRank", b => + { + b.Property("CardId") + .HasColumnType("INTEGER"); + + b.Property("Area") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AreaId") + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("INTEGER"); + + b.Property("Fcol1") + .HasColumnType("INTEGER"); + + b.Property("LastPlayTenpoId") + .HasColumnType("INTEGER"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Pref") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("TenpoName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TitleId") + .HasColumnType("INTEGER"); + + b.Property("TotalScore") + .HasColumnType("INTEGER"); + + b.HasKey("CardId"); + + b.ToTable("GlobalScoreRank", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.MonthlyScoreRank", b => + { + b.Property("CardId") + .HasColumnType("INTEGER"); + + b.Property("Area") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AreaId") + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("INTEGER"); + + b.Property("Fcol1") + .HasColumnType("INTEGER"); + + b.Property("LastPlayTenpoId") + .HasColumnType("INTEGER"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Pref") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("TenpoName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TitleId") + .HasColumnType("INTEGER"); + + b.Property("TotalScore") + .HasColumnType("INTEGER"); + + b.HasKey("CardId"); + + b.ToTable("MonthlyScoreRank", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.PlayNumRank", b => + { + b.Property("MusicId") + .HasColumnType("INTEGER"); + + b.Property("Artist") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PlayCount") + .HasColumnType("INTEGER"); + + b.Property("PrevRank") + .HasColumnType("INTEGER"); + + b.Property("PrevRank2") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("Rank2") + .HasColumnType("INTEGER"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("MusicId"); + + b.ToTable("PlayNumRank", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.ShopScoreRank", b => + { + b.Property("CardId") + .HasColumnType("INTEGER"); + + b.Property("Area") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AreaId") + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("INTEGER"); + + b.Property("Fcol1") + .HasColumnType("INTEGER"); + + b.Property("LastPlayTenpoId") + .HasColumnType("INTEGER"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Pref") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("TenpoName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TitleId") + .HasColumnType("INTEGER"); + + b.Property("TotalScore") + .HasColumnType("INTEGER"); + + b.HasKey("CardId"); + + b.ToTable("ShopScoreRank", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Infrastructure/Migrations/20230215165703_AddScoreRanks.cs b/Infrastructure/Migrations/20230215165703_AddScoreRanks.cs new file mode 100644 index 0000000..136bad3 --- /dev/null +++ b/Infrastructure/Migrations/20230215165703_AddScoreRanks.cs @@ -0,0 +1,99 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Infrastructure.Migrations +{ + /// + public partial class AddScoreRanks : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "GlobalScoreRank", + columns: table => new + { + CardId = table.Column(type: "INTEGER", nullable: false), + PlayerName = table.Column(type: "TEXT", nullable: false), + Rank = table.Column(type: "INTEGER", nullable: false), + TotalScore = table.Column(type: "INTEGER", nullable: false), + AvatarId = table.Column(type: "INTEGER", nullable: false), + TitleId = table.Column(type: "INTEGER", nullable: false), + Fcol1 = table.Column(type: "INTEGER", nullable: false), + PrefId = table.Column(type: "INTEGER", nullable: false), + Pref = table.Column(type: "TEXT", nullable: false), + AreaId = table.Column(type: "INTEGER", nullable: false), + Area = table.Column(type: "TEXT", nullable: false), + LastPlayTenpoId = table.Column(type: "INTEGER", nullable: false), + TenpoName = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_GlobalScoreRank", x => x.CardId); + }); + + migrationBuilder.CreateTable( + name: "MonthlyScoreRank", + columns: table => new + { + CardId = table.Column(type: "INTEGER", nullable: false), + PlayerName = table.Column(type: "TEXT", nullable: false), + Rank = table.Column(type: "INTEGER", nullable: false), + TotalScore = table.Column(type: "INTEGER", nullable: false), + AvatarId = table.Column(type: "INTEGER", nullable: false), + TitleId = table.Column(type: "INTEGER", nullable: false), + Fcol1 = table.Column(type: "INTEGER", nullable: false), + PrefId = table.Column(type: "INTEGER", nullable: false), + Pref = table.Column(type: "TEXT", nullable: false), + AreaId = table.Column(type: "INTEGER", nullable: false), + Area = table.Column(type: "TEXT", nullable: false), + LastPlayTenpoId = table.Column(type: "INTEGER", nullable: false), + TenpoName = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_MonthlyScoreRank", x => x.CardId); + }); + + migrationBuilder.CreateTable( + name: "ShopScoreRank", + columns: table => new + { + CardId = table.Column(type: "INTEGER", nullable: false), + PlayerName = table.Column(type: "TEXT", nullable: false), + Rank = table.Column(type: "INTEGER", nullable: false), + TotalScore = table.Column(type: "INTEGER", nullable: false), + AvatarId = table.Column(type: "INTEGER", nullable: false), + TitleId = table.Column(type: "INTEGER", nullable: false), + Fcol1 = table.Column(type: "INTEGER", nullable: false), + PrefId = table.Column(type: "INTEGER", nullable: false), + Pref = table.Column(type: "TEXT", nullable: false), + AreaId = table.Column(type: "INTEGER", nullable: false), + Area = table.Column(type: "TEXT", nullable: false), + LastPlayTenpoId = table.Column(type: "INTEGER", nullable: false), + TenpoName = table.Column(type: "TEXT", nullable: false), + Title = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ShopScoreRank", x => x.CardId); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "GlobalScoreRank"); + + migrationBuilder.DropTable( + name: "MonthlyScoreRank"); + + migrationBuilder.DropTable( + name: "ShopScoreRank"); + } + } +} diff --git a/Infrastructure/Migrations/CardDbContextModelSnapshot.cs b/Infrastructure/Migrations/CardDbContextModelSnapshot.cs index 60b4594..b1302cb 100644 --- a/Infrastructure/Migrations/CardDbContextModelSnapshot.cs +++ b/Infrastructure/Migrations/CardDbContextModelSnapshot.cs @@ -174,6 +174,114 @@ namespace Infrastructure.Migrations b.ToTable("CardPlayCount", (string)null); }); + modelBuilder.Entity("Domain.Entities.GlobalScoreRank", b => + { + b.Property("CardId") + .HasColumnType("INTEGER"); + + b.Property("Area") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AreaId") + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("INTEGER"); + + b.Property("Fcol1") + .HasColumnType("INTEGER"); + + b.Property("LastPlayTenpoId") + .HasColumnType("INTEGER"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Pref") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("TenpoName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TitleId") + .HasColumnType("INTEGER"); + + b.Property("TotalScore") + .HasColumnType("INTEGER"); + + b.HasKey("CardId"); + + b.ToTable("GlobalScoreRank", (string)null); + }); + + modelBuilder.Entity("Domain.Entities.MonthlyScoreRank", b => + { + b.Property("CardId") + .HasColumnType("INTEGER"); + + b.Property("Area") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AreaId") + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("INTEGER"); + + b.Property("Fcol1") + .HasColumnType("INTEGER"); + + b.Property("LastPlayTenpoId") + .HasColumnType("INTEGER"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Pref") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("TenpoName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TitleId") + .HasColumnType("INTEGER"); + + b.Property("TotalScore") + .HasColumnType("INTEGER"); + + b.HasKey("CardId"); + + b.ToTable("MonthlyScoreRank", (string)null); + }); + modelBuilder.Entity("Domain.Entities.PlayNumRank", b => { b.Property("MusicId") @@ -206,6 +314,60 @@ namespace Infrastructure.Migrations b.ToTable("PlayNumRank", (string)null); }); + + modelBuilder.Entity("Domain.Entities.ShopScoreRank", b => + { + b.Property("CardId") + .HasColumnType("INTEGER"); + + b.Property("Area") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("AreaId") + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("INTEGER"); + + b.Property("Fcol1") + .HasColumnType("INTEGER"); + + b.Property("LastPlayTenpoId") + .HasColumnType("INTEGER"); + + b.Property("PlayerName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Pref") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("PrefId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("TenpoName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TitleId") + .HasColumnType("INTEGER"); + + b.Property("TotalScore") + .HasColumnType("INTEGER"); + + b.HasKey("CardId"); + + b.ToTable("ShopScoreRank", (string)null); + }); #pragma warning restore 612, 618 } } diff --git a/Infrastructure/Persistence/CardDbContext.cs b/Infrastructure/Persistence/CardDbContext.cs index d57e821..5cbb1fa 100644 --- a/Infrastructure/Persistence/CardDbContext.cs +++ b/Infrastructure/Persistence/CardDbContext.cs @@ -27,6 +27,13 @@ public partial class CardDbContext : DbContext, ICardDbContext public virtual DbSet PlayNumRanks { get; set; } = null!; + public virtual DbSet GlobalScoreRanks { get; set; } = null!; + + public virtual DbSet MonthlyScoreRanks { get; set; } = null!; + + public virtual DbSet ShopScoreRanks { get; set; } = null!; + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (optionsBuilder.IsConfigured) @@ -128,7 +135,72 @@ public partial class CardDbContext : DbContext, ICardDbContext entity.Property(e => e.PrevRank); entity.Property(e => e.PrevRank2); }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.CardId); + + entity.ToTable("GlobalScoreRank"); + + entity.Property(e => e.CardId).ValueGeneratedNever(); + entity.Property(e => e.Fcol1); + entity.Property(e => e.AvatarId); + entity.Property(e => e.Title); + entity.Property(e => e.TitleId); + entity.Property(e => e.Rank); + entity.Property(e => e.AreaId); + entity.Property(e => e.Area); + entity.Property(e => e.LastPlayTenpoId); + entity.Property(e => e.TenpoName); + entity.Property(e => e.PrefId); + entity.Property(e => e.Pref); + entity.Property(e => e.TotalScore); + entity.Property(e => e.PlayerName); + }); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.CardId); + + entity.ToTable("MonthlyScoreRank"); + + entity.Property(e => e.CardId).ValueGeneratedNever(); + entity.Property(e => e.Fcol1); + entity.Property(e => e.AvatarId); + entity.Property(e => e.Title); + entity.Property(e => e.TitleId); + entity.Property(e => e.Rank); + entity.Property(e => e.AreaId); + entity.Property(e => e.Area); + entity.Property(e => e.LastPlayTenpoId); + entity.Property(e => e.TenpoName); + entity.Property(e => e.PrefId); + entity.Property(e => e.Pref); + entity.Property(e => e.TotalScore); + entity.Property(e => e.PlayerName); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.CardId); + + entity.ToTable("ShopScoreRank"); + + entity.Property(e => e.CardId).ValueGeneratedNever(); + entity.Property(e => e.Fcol1); + entity.Property(e => e.AvatarId); + entity.Property(e => e.Title); + entity.Property(e => e.TitleId); + entity.Property(e => e.Rank); + entity.Property(e => e.AreaId); + entity.Property(e => e.Area); + entity.Property(e => e.LastPlayTenpoId); + entity.Property(e => e.TenpoName); + entity.Property(e => e.PrefId); + entity.Property(e => e.Pref); + entity.Property(e => e.TotalScore); + entity.Property(e => e.PlayerName); + }); OnModelCreatingPartial(modelBuilder); } diff --git a/MainServer/Configurations/game.json b/MainServer/Configurations/game.json index e8b45c2..3dad1df 100644 --- a/MainServer/Configurations/game.json +++ b/MainServer/Configurations/game.json @@ -13,7 +13,7 @@ 632, 659, 666, 668, 670, 672, 676, 680, 682, 685, 686, 697, 700, 701, 711, 720, 749, 875, 876, 877 ], - "UnlockReward": [ + "UnlockRewards": [ { "RewardId" : 1, "RewardType" : 1, @@ -23,29 +23,29 @@ }, { "RewardId" : 2, - "RewardType" : 2, + "RewardType" : 0, "TargetId" : 11, "TargetNum": 1, "KeyNum": 1 }, { "RewardId" : 3, - "RewardType" : 3, + "RewardType" : 2, "TargetId" : 11, "TargetNum": 1, "KeyNum": 1 }, { "RewardId" : 4, - "RewardType" : 4, + "RewardType" : 7, "TargetId" : 11, "TargetNum": 1, "KeyNum": 1 }, { "RewardId" : 5, - "RewardType" : 5, - "TargetId" : 11, + "RewardType" : 8, + "TargetId" : 1, "TargetNum": 1, "KeyNum": 1 } diff --git a/MainServer/Controllers/Game/RankingController.cs b/MainServer/Controllers/Game/RankingController.cs index d7b5c19..a759776 100644 --- a/MainServer/Controllers/Game/RankingController.cs +++ b/MainServer/Controllers/Game/RankingController.cs @@ -11,7 +11,8 @@ namespace MainServer.Controllers.Game; public class RankingController : BaseController { [HttpGet("ranking.php")] - public async Task> Ranking([FromQuery(Name = "cmd_type")] int rankType) + public async Task> Ranking([FromQuery(Name = "cmd_type")] int rankType, + [FromQuery(Name = "tenpo_id")] int tenpoId) { var type = (RankingCommandType)rankType; type.Throw().IfOutOfRange(); @@ -22,7 +23,7 @@ public class RankingController : BaseController RankingCommandType.PlayNumRank => await Mediator.Send(new GetPlayNumRankQuery()), RankingCommandType.EventRank => await Mediator.Send(new GetEventRankQuery()), RankingCommandType.MonthlyRank => await Mediator.Send(new GetMonthlyScoreRankQuery()), - RankingCommandType.ShopRank => await Mediator.Send(new GetTenpoScoreRankQuery()), + RankingCommandType.ShopRank => await Mediator.Send(new GetTenpoScoreRankQuery(tenpoId)), _ => throw new ArgumentOutOfRangeException(nameof(type), type, "Should not happen!") }; diff --git a/doc/unlock_reward.md b/doc/unlock_reward.md new file mode 100644 index 0000000..950438a --- /dev/null +++ b/doc/unlock_reward.md @@ -0,0 +1,8 @@ +| Reward type | case | +| ----------- | ---- | +| Music | 0 | +| Item | 1 | +| Avatar | 2 | +| Navigator | 7 | +| GC | 8 | +