1
0
mirror of synced 2024-11-30 17:04:28 +01:00

Rank and unlock fixes

This commit is contained in:
asesidaa 2023-02-16 15:26:13 +08:00
parent 9d58e71e06
commit 7b3fae51b7
33 changed files with 1276 additions and 48 deletions

View File

@ -4,11 +4,11 @@ public static class TimeHelper
{ {
public static string CurrentTimeToString() 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) public static string DateToString(DateTime time)
{ {
return time.ToString("yyyy-MM-dd"); return time.ToString("yyyy/MM/dd hh:mm:ss");
} }
} }

View File

@ -20,12 +20,11 @@ public static class DependencyInjection
services.AddQuartz(q => services.AddQuartz(q =>
{ {
q.UseMicrosoftDependencyInjectionJobFactory(); q.UseMicrosoftDependencyInjectionJobFactory();
var jobKey = new JobKey("UpdatePlayNumRankJob");
q.AddJob<UpdatePlayNumRankJob>(options => options.WithIdentity(jobKey));
q.AddJob<UpdatePlayNumRankJob>(options => options.WithIdentity(UpdatePlayNumRankJob.KEY));
q.AddTrigger(options => q.AddTrigger(options =>
{ {
options.ForJob(jobKey) options.ForJob(UpdatePlayNumRankJob.KEY)
.WithIdentity("UpdatePlayNumRankJob-trigger") .WithIdentity("UpdatePlayNumRankJob-trigger")
.StartNow() .StartNow()
.WithSimpleSchedule(x => .WithSimpleSchedule(x =>
@ -33,6 +32,42 @@ public static class DependencyInjection
x.WithIntervalInHours(24).RepeatForever(); x.WithIntervalInHours(24).RepeatForever();
}); });
}); });
q.AddJob<UpdateGlobalScoreRankJob>(options => options.WithIdentity(UpdateGlobalScoreRankJob.KEY));
q.AddTrigger(options =>
{
options.ForJob(UpdateGlobalScoreRankJob.KEY)
.WithIdentity("UpdateGlobalScoreRankJob-trigger")
.StartNow()
.WithSimpleSchedule(x =>
{
x.WithIntervalInHours(24).RepeatForever();
});
});
q.AddJob<UpdateMonthlyScoreRankJob>(options => options.WithIdentity(UpdateMonthlyScoreRankJob.KEY));
q.AddTrigger(options =>
{
options.ForJob(UpdateMonthlyScoreRankJob.KEY)
.WithIdentity("UpdateMonthlyScoreRankJob-trigger")
.StartNow()
.WithSimpleSchedule(x =>
{
x.WithIntervalInHours(24).RepeatForever();
});
});
q.AddJob<MaintainTenpoIdJob>(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 => services.AddQuartzHostedService(options =>
{ {

View File

@ -50,8 +50,8 @@ public class CardDetailDto
public long ScoreBi1 { get; set; } public long ScoreBi1 { get; set; }
[XmlElement(ElementName = "last_play_tenpo_id")] [XmlElement(ElementName = "last_play_tenpo_id")]
[DefaultValue("GC local server")] [DefaultValue("1337")]
public string LastPlayTenpoId { get; set; } = "GC local server"; public string LastPlayTenpoId { get; set; } = "1337";
[XmlElement("fcol1")] [XmlElement("fcol1")]
public int Fcol1 { get; set; } public int Fcol1 { get; set; }

View File

@ -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;
}

View File

@ -30,11 +30,11 @@ public class ReadAvatarQueryHandler : CardRequestHandlerBase<ReadAvatarQuery, st
{ {
Id = i, Id = i,
CardId = request.CardId, CardId = request.CardId,
AvatarId = i, AvatarId = i + 1,
Created = "2013-01-01 08:00:00", Created = "2013-01-01 08:00:00",
Modified = "2013-01-01 08:00:00", Modified = "2013-01-01 08:00:00",
NewFlag = 0, NewFlag = 0,
UseFlag = 1 UseFlag = i == 10 ? 0 : 1
}; };
list.Add(avatar); list.Add(avatar);
} }

View File

@ -29,7 +29,7 @@ public class ReadItemQueryHandler : CardRequestHandlerBase<ReadItemQuery, string
{ {
Id = i, Id = i,
CardId = request.CardId, CardId = request.CardId,
ItemId = i, ItemId = i + 1,
ItemNum = 90, ItemNum = 90,
Created = "2013-01-01", Created = "2013-01-01",
Modified = "2013-01-01", Modified = "2013-01-01",

View File

@ -31,11 +31,11 @@ public class ReadNavigatorQueryHandler : CardRequestHandlerBase<ReadNavigatorQue
{ {
Id = i, Id = i,
CardId = request.CardId, CardId = request.CardId,
NavigatorId = i, NavigatorId = i + 1,
Created = "2013-01-01 08:00:00", Created = "2013-01-01 08:00:00",
Modified = "2013-01-01 08:00:00", Modified = "2013-01-01 08:00:00",
NewFlag = 0, NewFlag = 0,
UseFlag = 1 UseFlag = i == 10 ? 0 : 1
}; };
list.Add(navigator); list.Add(navigator);
} }

View File

@ -29,7 +29,7 @@ public class ReadSkinQueryHandler : CardRequestHandlerBase<ReadSkinQuery, string
{ {
Id = i, Id = i,
CardId = request.CardId, CardId = request.CardId,
SkinId = i, SkinId = i + 1,
Created = "2013-01-01 08:00:00", Created = "2013-01-01 08:00:00",
Modified = "2013-01-01 08:00:00", Modified = "2013-01-01 08:00:00",
NewFlag = 0, NewFlag = 0,

View File

@ -28,7 +28,7 @@ public class ReadSoundEffectQueryHandler : CardRequestHandlerBase<ReadSoundEffec
{ {
Id = i, Id = i,
CardId = request.CardId, CardId = request.CardId,
SoundEffectId = i, SoundEffectId = i + 1,
Created = "2013-01-01 08:00:00", Created = "2013-01-01 08:00:00",
Modified = "2013-01-01 08:00:00", Modified = "2013-01-01 08:00:00",
NewFlag = 0, NewFlag = 0,

View File

@ -29,7 +29,7 @@ public class ReadTitleQueryHandler : CardRequestHandlerBase<ReadTitleQuery, stri
{ {
Id = i, Id = i,
CardId = request.CardId, CardId = request.CardId,
TitleId = i, TitleId = i + 1,
Created = "2013-01-01 08:00:00", Created = "2013-01-01 08:00:00",
Modified = "2013-01-01 08:00:00", Modified = "2013-01-01 08:00:00",
NewFlag = 0, NewFlag = 0,

View File

@ -17,7 +17,7 @@ public class GetEventRankQueryHandler : IRequestHandlerWrapper<GetEventRankQuery
Ranks = new List<object>(), Ranks = new List<object>(),
Status = new RankStatus Status = new RankStatus
{ {
TableName = "TenpoScoreRank", TableName = "EventRank",
StartDate = TimeHelper.DateToString(DateTime.Today), StartDate = TimeHelper.DateToString(DateTime.Today),
EndDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today),
Rows = 0, Rows = 0,

View File

@ -2,7 +2,10 @@
using Application.Common.Extensions; using Application.Common.Extensions;
using Application.Common.Helpers; using Application.Common.Helpers;
using Application.Common.Models; using Application.Common.Models;
using Application.Dto;
using Application.Interfaces; using Application.Interfaces;
using Application.Mappers;
using Microsoft.EntityFrameworkCore;
namespace Application.Game.Rank; namespace Application.Game.Rank;
@ -10,22 +13,40 @@ public record GetGlobalScoreRankQuery() : IRequestWrapper<string>;
public class GetGlobalScoreRankQueryHandler : IRequestHandlerWrapper<GetGlobalScoreRankQuery, string> public class GetGlobalScoreRankQueryHandler : IRequestHandlerWrapper<GetGlobalScoreRankQuery, string>
{ {
public Task<ServiceResult<string>> Handle(GetGlobalScoreRankQuery request, CancellationToken cancellationToken) private readonly ICardDbContext cardDbContext;
public GetGlobalScoreRankQueryHandler(ICardDbContext cardDbContext)
{ {
this.cardDbContext = cardDbContext;
}
public async Task<ServiceResult<string>> 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 var container = new GlobalScoreRankContainer
{ {
Ranks = new List<object>(), Ranks = dtoList,
Status = new RankStatus Status = new RankStatus
{ {
TableName = "TenpoScoreRank", TableName = "GlobalScoreRank",
StartDate = TimeHelper.DateToString(DateTime.Today), StartDate = TimeHelper.DateToString(DateTime.Today),
EndDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today),
Rows = 0, Rows = dtoList.Count,
Status = 0 Status = 1
} }
}; };
return Task.FromResult(new ServiceResult<string>(container.SerializeCardData())); return new ServiceResult<string>(container.SerializeCardData());
} }
} }
@ -35,7 +56,7 @@ public class GlobalScoreRankContainer
[XmlArray(ElementName = "score_rank")] [XmlArray(ElementName = "score_rank")]
[XmlArrayItem(ElementName = "record")] [XmlArrayItem(ElementName = "record")]
// ReSharper disable once UnusedAutoPropertyAccessor.Global // ReSharper disable once UnusedAutoPropertyAccessor.Global
public List<object> Ranks { get; init; } = new(); public List<ScoreRankDto> Ranks { get; init; } = new();
[XmlElement("ranking_status")] [XmlElement("ranking_status")]
public RankStatus Status { get; set; } = new(); public RankStatus Status { get; set; } = new();

View File

@ -2,7 +2,10 @@
using Application.Common.Extensions; using Application.Common.Extensions;
using Application.Common.Helpers; using Application.Common.Helpers;
using Application.Common.Models; using Application.Common.Models;
using Application.Dto;
using Application.Interfaces; using Application.Interfaces;
using Application.Mappers;
using Microsoft.EntityFrameworkCore;
namespace Application.Game.Rank; namespace Application.Game.Rank;
@ -10,22 +13,40 @@ public record GetMonthlyScoreRankQuery() : IRequestWrapper<string>;
public class GetMonthlyScoreRankQueryHandler : IRequestHandlerWrapper<GetMonthlyScoreRankQuery, string> public class GetMonthlyScoreRankQueryHandler : IRequestHandlerWrapper<GetMonthlyScoreRankQuery, string>
{ {
public Task<ServiceResult<string>> Handle(GetMonthlyScoreRankQuery request, CancellationToken cancellationToken) private readonly ICardDbContext cardDbContext;
public GetMonthlyScoreRankQueryHandler(ICardDbContext cardDbContext)
{ {
this.cardDbContext = cardDbContext;
}
public async Task<ServiceResult<string>> 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 var container = new MonthlyScoreRankContainer
{ {
Ranks = new List<object>(), Ranks = dtoList,
Status = new RankStatus Status = new RankStatus
{ {
TableName = "TenpoScoreRank", TableName = "MonthlyScoreRank",
StartDate = TimeHelper.DateToString(DateTime.Today), StartDate = TimeHelper.DateToString(DateTime.Today),
EndDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today),
Rows = 0, Rows = dtoList.Count,
Status = 0 Status = 1
} }
}; };
return Task.FromResult(new ServiceResult<string>(container.SerializeCardData())); return new ServiceResult<string>(container.SerializeCardData());
} }
} }
@ -35,7 +56,7 @@ public class MonthlyScoreRankContainer
[XmlArray(ElementName = "m_score_rank")] [XmlArray(ElementName = "m_score_rank")]
[XmlArrayItem(ElementName = "record")] [XmlArrayItem(ElementName = "record")]
// ReSharper disable once UnusedAutoPropertyAccessor.Global // ReSharper disable once UnusedAutoPropertyAccessor.Global
public List<object> Ranks { get; init; } = new(); public List<ScoreRankDto> Ranks { get; init; } = new();
[XmlElement("ranking_status")] [XmlElement("ranking_status")]
public RankStatus Status { get; set; } = new(); public RankStatus Status { get; set; } = new();

View File

@ -4,29 +4,57 @@ using Application.Common.Helpers;
using Application.Common.Models; using Application.Common.Models;
using Application.Dto; using Application.Dto;
using Application.Interfaces; using Application.Interfaces;
using Application.Mappers;
using Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace Application.Game.Rank; namespace Application.Game.Rank;
public record GetTenpoScoreRankQuery() : IRequestWrapper<string>; public record GetTenpoScoreRankQuery(int TenpoId) : IRequestWrapper<string>;
public class GetTenpoScoreRankQueryHandler : IRequestHandlerWrapper<GetTenpoScoreRankQuery, string> public class GetTenpoScoreRankQueryHandler : IRequestHandlerWrapper<GetTenpoScoreRankQuery, string>
{ {
public Task<ServiceResult<string>> Handle(GetTenpoScoreRankQuery request, CancellationToken cancellationToken) private readonly ICardDbContext cardDbContext;
public GetTenpoScoreRankQueryHandler(ICardDbContext cardDbContext)
{ {
this.cardDbContext = cardDbContext;
}
public async Task<ServiceResult<string>> 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 var container = new TenpoScoreRankContainer
{ {
Ranks = new List<object>(), Ranks = dtoList,
Status = new RankStatus Status = new RankStatus
{ {
TableName = "TenpoScoreRank", TableName = "TenpoScoreRank",
StartDate = TimeHelper.DateToString(DateTime.Today), StartDate = TimeHelper.DateToString(DateTime.Today),
EndDate = TimeHelper.DateToString(DateTime.Today), EndDate = TimeHelper.DateToString(DateTime.Today),
Rows = 0, Rows = dtoList.Count,
Status = 0 Status = 1
} }
}; };
return Task.FromResult(new ServiceResult<string>(container.SerializeCardData())); return new ServiceResult<string>(container.SerializeCardData());
} }
} }
@ -36,7 +64,7 @@ public class TenpoScoreRankContainer
[XmlArray(ElementName = "t_score_rank")] [XmlArray(ElementName = "t_score_rank")]
[XmlArrayItem(ElementName = "record")] [XmlArrayItem(ElementName = "record")]
// ReSharper disable once UnusedAutoPropertyAccessor.Global // ReSharper disable once UnusedAutoPropertyAccessor.Global
public List<object> Ranks { get; init; } = new(); public List<ScoreRankDto> Ranks { get; init; } = new();
[XmlElement("ranking_status")] [XmlElement("ranking_status")]
public RankStatus Status { get; set; } = new(); public RankStatus Status { get; set; } = new();

View File

@ -57,9 +57,9 @@ public partial class CertifyCommandHandler : IRequestHandler<CertifyCommand, str
var response = $"host=card_id=7020392000147361,relay_addr={relayConfig.RelayServer},relay_port={relayConfig.RelayPort}\n" + var response = $"host=card_id=7020392000147361,relay_addr={relayConfig.RelayServer},relay_port={relayConfig.RelayPort}\n" +
"no=1337\n" + "no=1337\n" +
"name=Local\n" + "name=GCLocalServer\n" +
"pref=nesys\n" + "pref=nesys\n" +
"addr=nesys@home\n" + "addr=Local\n" +
"x-next-time=15\n" + "x-next-time=15\n" +
$"x-img=http://{request.Host}/news.png\n" + $"x-img=http://{request.Host}/news.png\n" +
$"x-ranking=http://{request.Host}/ranking/ranking.php\n" + $"x-ranking=http://{request.Host}/ranking/ranking.php\n" +

View File

@ -15,6 +15,12 @@ public interface ICardDbContext
public DbSet<PlayNumRank> PlayNumRanks { get; set; } public DbSet<PlayNumRank> PlayNumRanks { get; set; }
public DbSet<GlobalScoreRank> GlobalScoreRanks { get; set; }
public DbSet<MonthlyScoreRank> MonthlyScoreRanks { get; set; }
public DbSet<ShopScoreRank> ShopScoreRanks { get; set; }
public Task<int> SaveChangesAsync(CancellationToken cancellationToken); public Task<int> SaveChangesAsync(CancellationToken cancellationToken);

View File

@ -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<MaintainTenpoIdJob> logger;
private readonly ICardDbContext cardDbContext;
public static readonly JobKey KEY = new("MaintainTenpoIdJob");
public MaintainTenpoIdJob(ILogger<MaintainTenpoIdJob> 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);
}
}

View File

@ -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<UpdateGlobalScoreRankJob> logger;
private readonly ICardDbContext cardDbContext;
public static readonly JobKey KEY = new("UpdateGlobalScoreRankJob");
public UpdateGlobalScoreRankJob(ILogger<UpdateGlobalScoreRankJob> 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<GlobalScoreRank>();
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<GlobalScoreRank> GetFakeRanks()
{
var fakeList = new List<GlobalScoreRank>();
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;
}
}

View File

@ -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<UpdateMonthlyScoreRankJob> logger;
private readonly ICardDbContext cardDbContext;
public static readonly JobKey KEY = new JobKey("UpdateMonthlyScoreRankJob");
public UpdateMonthlyScoreRankJob(ILogger<UpdateMonthlyScoreRankJob> 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<MonthlyScoreRank>();
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<MonthlyScoreRank> GetFakeRanks()
{
var fakeList = new List<MonthlyScoreRank>();
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;
}
}

View File

@ -15,6 +15,8 @@ public class UpdatePlayNumRankJob : IJob
private readonly IMusicDbContext musicDbContext; private readonly IMusicDbContext musicDbContext;
public static readonly JobKey KEY = new JobKey("UpdatePlayNumRankJob");
public UpdatePlayNumRankJob(ILogger<UpdatePlayNumRankJob> logger, ICardDbContext cardDbContext, public UpdatePlayNumRankJob(ILogger<UpdatePlayNumRankJob> logger, ICardDbContext cardDbContext,
IMusicDbContext musicDbContext) IMusicDbContext musicDbContext)
{ {
@ -61,5 +63,7 @@ public class UpdatePlayNumRankJob : IJob
}).ToList(); }).ToList();
await cardDbContext.PlayNumRanks.UpsertRange(result).RunAsync(); await cardDbContext.PlayNumRanks.UpsertRange(result).RunAsync();
await cardDbContext.SaveChangesAsync(new CancellationToken()); await cardDbContext.SaveChangesAsync(new CancellationToken());
logger.LogInformation("Updating play num rank done");
} }
} }

View File

@ -7,7 +7,11 @@ namespace Application.Mappers;
[Mapper] [Mapper]
public static partial class CardBDatumMapper 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); 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); public static partial CardBdatum DtoToCardBDatum(this CardBDatumDto dto);
} }

View File

@ -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);
}

View File

@ -0,0 +1,6 @@
namespace Domain.Entities;
public class GlobalScoreRank : ScoreRank
{
}

View File

@ -0,0 +1,6 @@
namespace Domain.Entities;
public class MonthlyScoreRank : ScoreRank
{
}

View File

@ -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;
}

View File

@ -0,0 +1,6 @@
namespace Domain.Entities;
public class ShopScoreRank : ScoreRank
{
}

View File

@ -0,0 +1,377 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<long>("CardId")
.HasColumnType("INTEGER")
.HasColumnName("card_id");
b.Property<string>("Bdata")
.HasColumnType("TEXT")
.HasColumnName("bdata");
b.Property<long>("BdataSize")
.HasColumnType("INTEGER")
.HasColumnName("bdata_size");
b.HasKey("CardId");
b.ToTable("card_bdata", (string)null);
});
modelBuilder.Entity("Domain.Entities.CardDetail", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER")
.HasColumnName("card_id");
b.Property<long>("Pcol1")
.HasColumnType("INTEGER")
.HasColumnName("pcol1");
b.Property<long>("Pcol2")
.HasColumnType("INTEGER")
.HasColumnName("pcol2");
b.Property<long>("Pcol3")
.HasColumnType("INTEGER")
.HasColumnName("pcol3");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER")
.HasColumnName("fcol1");
b.Property<long>("Fcol2")
.HasColumnType("INTEGER")
.HasColumnName("fcol2");
b.Property<long>("Fcol3")
.HasColumnType("INTEGER")
.HasColumnName("fcol3");
b.Property<string>("LastPlayTenpoId")
.HasColumnType("TEXT")
.HasColumnName("last_play_tenpo_id");
b.Property<long>("LastPlayTime")
.HasColumnType("INTEGER")
.HasColumnName("last_play_time");
b.Property<long>("ScoreBi1")
.HasColumnType("INTEGER")
.HasColumnName("score_bi1");
b.Property<long>("ScoreI1")
.HasColumnType("INTEGER")
.HasColumnName("score_i1");
b.Property<long>("ScoreUi1")
.HasColumnType("INTEGER")
.HasColumnName("score_ui1");
b.Property<long>("ScoreUi2")
.HasColumnType("INTEGER")
.HasColumnName("score_ui2");
b.Property<long>("ScoreUi3")
.HasColumnType("INTEGER")
.HasColumnName("score_ui3");
b.Property<long>("ScoreUi4")
.HasColumnType("INTEGER")
.HasColumnName("score_ui4");
b.Property<long>("ScoreUi5")
.HasColumnType("INTEGER")
.HasColumnName("score_ui5");
b.Property<long>("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<long>("CardId")
.HasColumnType("INTEGER")
.HasColumnName("card_id");
b.Property<string>("AchieveStatus")
.IsRequired()
.HasColumnType("TEXT")
.HasColumnName("achieve_status");
b.Property<string>("Created")
.HasColumnType("TEXT")
.HasColumnName("created");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER")
.HasColumnName("fcol1");
b.Property<long>("Fcol2")
.HasColumnType("INTEGER")
.HasColumnName("fcol2");
b.Property<long>("Fcol3")
.HasColumnType("INTEGER")
.HasColumnName("fcol3");
b.Property<string>("Modified")
.HasColumnType("TEXT")
.HasColumnName("modified");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT")
.HasColumnName("player_name");
b.Property<long>("ScoreI1")
.HasColumnType("INTEGER")
.HasColumnName("score_i1");
b.HasKey("CardId");
b.ToTable("card_main", (string)null);
});
modelBuilder.Entity("Domain.Entities.CardPlayCount", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER")
.HasColumnName("card_id");
b.Property<long>("LastPlayedTime")
.HasColumnType("INTEGER")
.HasColumnName("last_played_time");
b.Property<long>("PlayCount")
.HasColumnType("INTEGER")
.HasColumnName("play_count");
b.HasKey("CardId");
b.ToTable("CardPlayCount", (string)null);
});
modelBuilder.Entity("Domain.Entities.GlobalScoreRank", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER");
b.Property<string>("Area")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("AreaId")
.HasColumnType("INTEGER");
b.Property<int>("AvatarId")
.HasColumnType("INTEGER");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER");
b.Property<int>("LastPlayTenpoId")
.HasColumnType("INTEGER");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Pref")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PrefId")
.HasColumnType("INTEGER");
b.Property<long>("Rank")
.HasColumnType("INTEGER");
b.Property<string>("TenpoName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("TitleId")
.HasColumnType("INTEGER");
b.Property<long>("TotalScore")
.HasColumnType("INTEGER");
b.HasKey("CardId");
b.ToTable("GlobalScoreRank", (string)null);
});
modelBuilder.Entity("Domain.Entities.MonthlyScoreRank", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER");
b.Property<string>("Area")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("AreaId")
.HasColumnType("INTEGER");
b.Property<int>("AvatarId")
.HasColumnType("INTEGER");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER");
b.Property<int>("LastPlayTenpoId")
.HasColumnType("INTEGER");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Pref")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PrefId")
.HasColumnType("INTEGER");
b.Property<long>("Rank")
.HasColumnType("INTEGER");
b.Property<string>("TenpoName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("TitleId")
.HasColumnType("INTEGER");
b.Property<long>("TotalScore")
.HasColumnType("INTEGER");
b.HasKey("CardId");
b.ToTable("MonthlyScoreRank", (string)null);
});
modelBuilder.Entity("Domain.Entities.PlayNumRank", b =>
{
b.Property<int>("MusicId")
.HasColumnType("INTEGER");
b.Property<string>("Artist")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PlayCount")
.HasColumnType("INTEGER");
b.Property<int>("PrevRank")
.HasColumnType("INTEGER");
b.Property<int>("PrevRank2")
.HasColumnType("INTEGER");
b.Property<int>("Rank")
.HasColumnType("INTEGER");
b.Property<int>("Rank2")
.HasColumnType("INTEGER");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("MusicId");
b.ToTable("PlayNumRank", (string)null);
});
modelBuilder.Entity("Domain.Entities.ShopScoreRank", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER");
b.Property<string>("Area")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("AreaId")
.HasColumnType("INTEGER");
b.Property<int>("AvatarId")
.HasColumnType("INTEGER");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER");
b.Property<int>("LastPlayTenpoId")
.HasColumnType("INTEGER");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Pref")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PrefId")
.HasColumnType("INTEGER");
b.Property<long>("Rank")
.HasColumnType("INTEGER");
b.Property<string>("TenpoName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("TitleId")
.HasColumnType("INTEGER");
b.Property<long>("TotalScore")
.HasColumnType("INTEGER");
b.HasKey("CardId");
b.ToTable("ShopScoreRank", (string)null);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,99 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddScoreRanks : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "GlobalScoreRank",
columns: table => new
{
CardId = table.Column<long>(type: "INTEGER", nullable: false),
PlayerName = table.Column<string>(type: "TEXT", nullable: false),
Rank = table.Column<long>(type: "INTEGER", nullable: false),
TotalScore = table.Column<long>(type: "INTEGER", nullable: false),
AvatarId = table.Column<int>(type: "INTEGER", nullable: false),
TitleId = table.Column<long>(type: "INTEGER", nullable: false),
Fcol1 = table.Column<long>(type: "INTEGER", nullable: false),
PrefId = table.Column<int>(type: "INTEGER", nullable: false),
Pref = table.Column<string>(type: "TEXT", nullable: false),
AreaId = table.Column<int>(type: "INTEGER", nullable: false),
Area = table.Column<string>(type: "TEXT", nullable: false),
LastPlayTenpoId = table.Column<int>(type: "INTEGER", nullable: false),
TenpoName = table.Column<string>(type: "TEXT", nullable: false),
Title = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_GlobalScoreRank", x => x.CardId);
});
migrationBuilder.CreateTable(
name: "MonthlyScoreRank",
columns: table => new
{
CardId = table.Column<long>(type: "INTEGER", nullable: false),
PlayerName = table.Column<string>(type: "TEXT", nullable: false),
Rank = table.Column<long>(type: "INTEGER", nullable: false),
TotalScore = table.Column<long>(type: "INTEGER", nullable: false),
AvatarId = table.Column<int>(type: "INTEGER", nullable: false),
TitleId = table.Column<long>(type: "INTEGER", nullable: false),
Fcol1 = table.Column<long>(type: "INTEGER", nullable: false),
PrefId = table.Column<int>(type: "INTEGER", nullable: false),
Pref = table.Column<string>(type: "TEXT", nullable: false),
AreaId = table.Column<int>(type: "INTEGER", nullable: false),
Area = table.Column<string>(type: "TEXT", nullable: false),
LastPlayTenpoId = table.Column<int>(type: "INTEGER", nullable: false),
TenpoName = table.Column<string>(type: "TEXT", nullable: false),
Title = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_MonthlyScoreRank", x => x.CardId);
});
migrationBuilder.CreateTable(
name: "ShopScoreRank",
columns: table => new
{
CardId = table.Column<long>(type: "INTEGER", nullable: false),
PlayerName = table.Column<string>(type: "TEXT", nullable: false),
Rank = table.Column<long>(type: "INTEGER", nullable: false),
TotalScore = table.Column<long>(type: "INTEGER", nullable: false),
AvatarId = table.Column<int>(type: "INTEGER", nullable: false),
TitleId = table.Column<long>(type: "INTEGER", nullable: false),
Fcol1 = table.Column<long>(type: "INTEGER", nullable: false),
PrefId = table.Column<int>(type: "INTEGER", nullable: false),
Pref = table.Column<string>(type: "TEXT", nullable: false),
AreaId = table.Column<int>(type: "INTEGER", nullable: false),
Area = table.Column<string>(type: "TEXT", nullable: false),
LastPlayTenpoId = table.Column<int>(type: "INTEGER", nullable: false),
TenpoName = table.Column<string>(type: "TEXT", nullable: false),
Title = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShopScoreRank", x => x.CardId);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "GlobalScoreRank");
migrationBuilder.DropTable(
name: "MonthlyScoreRank");
migrationBuilder.DropTable(
name: "ShopScoreRank");
}
}
}

View File

@ -174,6 +174,114 @@ namespace Infrastructure.Migrations
b.ToTable("CardPlayCount", (string)null); b.ToTable("CardPlayCount", (string)null);
}); });
modelBuilder.Entity("Domain.Entities.GlobalScoreRank", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER");
b.Property<string>("Area")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("AreaId")
.HasColumnType("INTEGER");
b.Property<int>("AvatarId")
.HasColumnType("INTEGER");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER");
b.Property<int>("LastPlayTenpoId")
.HasColumnType("INTEGER");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Pref")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PrefId")
.HasColumnType("INTEGER");
b.Property<long>("Rank")
.HasColumnType("INTEGER");
b.Property<string>("TenpoName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("TitleId")
.HasColumnType("INTEGER");
b.Property<long>("TotalScore")
.HasColumnType("INTEGER");
b.HasKey("CardId");
b.ToTable("GlobalScoreRank", (string)null);
});
modelBuilder.Entity("Domain.Entities.MonthlyScoreRank", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER");
b.Property<string>("Area")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("AreaId")
.HasColumnType("INTEGER");
b.Property<int>("AvatarId")
.HasColumnType("INTEGER");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER");
b.Property<int>("LastPlayTenpoId")
.HasColumnType("INTEGER");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Pref")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PrefId")
.HasColumnType("INTEGER");
b.Property<long>("Rank")
.HasColumnType("INTEGER");
b.Property<string>("TenpoName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("TitleId")
.HasColumnType("INTEGER");
b.Property<long>("TotalScore")
.HasColumnType("INTEGER");
b.HasKey("CardId");
b.ToTable("MonthlyScoreRank", (string)null);
});
modelBuilder.Entity("Domain.Entities.PlayNumRank", b => modelBuilder.Entity("Domain.Entities.PlayNumRank", b =>
{ {
b.Property<int>("MusicId") b.Property<int>("MusicId")
@ -206,6 +314,60 @@ namespace Infrastructure.Migrations
b.ToTable("PlayNumRank", (string)null); b.ToTable("PlayNumRank", (string)null);
}); });
modelBuilder.Entity("Domain.Entities.ShopScoreRank", b =>
{
b.Property<long>("CardId")
.HasColumnType("INTEGER");
b.Property<string>("Area")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("AreaId")
.HasColumnType("INTEGER");
b.Property<int>("AvatarId")
.HasColumnType("INTEGER");
b.Property<long>("Fcol1")
.HasColumnType("INTEGER");
b.Property<int>("LastPlayTenpoId")
.HasColumnType("INTEGER");
b.Property<string>("PlayerName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Pref")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("PrefId")
.HasColumnType("INTEGER");
b.Property<long>("Rank")
.HasColumnType("INTEGER");
b.Property<string>("TenpoName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<long>("TitleId")
.HasColumnType("INTEGER");
b.Property<long>("TotalScore")
.HasColumnType("INTEGER");
b.HasKey("CardId");
b.ToTable("ShopScoreRank", (string)null);
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View File

@ -27,6 +27,13 @@ public partial class CardDbContext : DbContext, ICardDbContext
public virtual DbSet<PlayNumRank> PlayNumRanks { get; set; } = null!; public virtual DbSet<PlayNumRank> PlayNumRanks { get; set; } = null!;
public virtual DbSet<GlobalScoreRank> GlobalScoreRanks { get; set; } = null!;
public virtual DbSet<MonthlyScoreRank> MonthlyScoreRanks { get; set; } = null!;
public virtual DbSet<ShopScoreRank> ShopScoreRanks { get; set; } = null!;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ {
if (optionsBuilder.IsConfigured) if (optionsBuilder.IsConfigured)
@ -129,6 +136,71 @@ public partial class CardDbContext : DbContext, ICardDbContext
entity.Property(e => e.PrevRank2); entity.Property(e => e.PrevRank2);
}); });
modelBuilder.Entity<GlobalScoreRank>(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<MonthlyScoreRank>(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<ShopScoreRank>(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); OnModelCreatingPartial(modelBuilder);
} }

View File

@ -13,7 +13,7 @@
632, 659, 666, 668, 670, 672, 676, 680, 682, 685, 686, 697, 700, 701, 632, 659, 666, 668, 670, 672, 676, 680, 682, 685, 686, 697, 700, 701,
711, 720, 749, 875, 876, 877 711, 720, 749, 875, 876, 877
], ],
"UnlockReward": [ "UnlockRewards": [
{ {
"RewardId" : 1, "RewardId" : 1,
"RewardType" : 1, "RewardType" : 1,
@ -23,29 +23,29 @@
}, },
{ {
"RewardId" : 2, "RewardId" : 2,
"RewardType" : 2, "RewardType" : 0,
"TargetId" : 11, "TargetId" : 11,
"TargetNum": 1, "TargetNum": 1,
"KeyNum": 1 "KeyNum": 1
}, },
{ {
"RewardId" : 3, "RewardId" : 3,
"RewardType" : 3, "RewardType" : 2,
"TargetId" : 11, "TargetId" : 11,
"TargetNum": 1, "TargetNum": 1,
"KeyNum": 1 "KeyNum": 1
}, },
{ {
"RewardId" : 4, "RewardId" : 4,
"RewardType" : 4, "RewardType" : 7,
"TargetId" : 11, "TargetId" : 11,
"TargetNum": 1, "TargetNum": 1,
"KeyNum": 1 "KeyNum": 1
}, },
{ {
"RewardId" : 5, "RewardId" : 5,
"RewardType" : 5, "RewardType" : 8,
"TargetId" : 11, "TargetId" : 1,
"TargetNum": 1, "TargetNum": 1,
"KeyNum": 1 "KeyNum": 1
} }

View File

@ -11,7 +11,8 @@ namespace MainServer.Controllers.Game;
public class RankingController : BaseController<RankingController> public class RankingController : BaseController<RankingController>
{ {
[HttpGet("ranking.php")] [HttpGet("ranking.php")]
public async Task<ActionResult<string>> Ranking([FromQuery(Name = "cmd_type")] int rankType) public async Task<ActionResult<string>> Ranking([FromQuery(Name = "cmd_type")] int rankType,
[FromQuery(Name = "tenpo_id")] int tenpoId)
{ {
var type = (RankingCommandType)rankType; var type = (RankingCommandType)rankType;
type.Throw().IfOutOfRange(); type.Throw().IfOutOfRange();
@ -22,7 +23,7 @@ public class RankingController : BaseController<RankingController>
RankingCommandType.PlayNumRank => await Mediator.Send(new GetPlayNumRankQuery()), RankingCommandType.PlayNumRank => await Mediator.Send(new GetPlayNumRankQuery()),
RankingCommandType.EventRank => await Mediator.Send(new GetEventRankQuery()), RankingCommandType.EventRank => await Mediator.Send(new GetEventRankQuery()),
RankingCommandType.MonthlyRank => await Mediator.Send(new GetMonthlyScoreRankQuery()), 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!") _ => throw new ArgumentOutOfRangeException(nameof(type), type, "Should not happen!")
}; };

8
doc/unlock_reward.md Normal file
View File

@ -0,0 +1,8 @@
| Reward type | case |
| ----------- | ---- |
| Music | 0 |
| Item | 1 |
| Avatar | 2 |
| Navigator | 7 |
| GC | 8 |