feat: 完成基础框架搭建
This commit is contained in:
@@ -1,9 +1,29 @@
|
|||||||
namespace Yi.Framework.DigitalCollectibles.Application.Jobs;
|
using Quartz;
|
||||||
|
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Managers;
|
||||||
|
|
||||||
|
namespace Yi.Framework.DigitalCollectibles.Application.Jobs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自动刷新填满矿池
|
/// 自动刷新填满矿池
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AutoRefreshMiningPoolJob
|
public class AutoRefreshMiningPoolJob : QuartzBackgroundWorkerBase
|
||||||
{
|
{
|
||||||
|
private readonly MiningPoolManager _miningPoolManager;
|
||||||
|
|
||||||
|
public AutoRefreshMiningPoolJob()
|
||||||
|
{
|
||||||
|
JobDetail = JobBuilder.Create<AutoRefreshMiningPoolJob>().WithIdentity(nameof(AutoRefreshMiningPoolJob))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//每天早上10点执行一次
|
||||||
|
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AutoRefreshMiningPoolJob))
|
||||||
|
.WithCronSchedule("0 0 10 * * ?")
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
await _miningPoolManager.RefreshMiningPoolAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,32 @@
|
|||||||
namespace Yi.Framework.DigitalCollectibles.Application.Jobs;
|
using Quartz;
|
||||||
|
using Volo.Abp.BackgroundWorkers.Quartz;
|
||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Entities;
|
||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Managers;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
|
namespace Yi.Framework.DigitalCollectibles.Application.Jobs;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 处理挂机挖矿定时任务
|
/// 处理挂机挖矿定时任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class OnHookAutoMiningJob
|
public class OnHookAutoMiningJob : QuartzBackgroundWorkerBase
|
||||||
{
|
{
|
||||||
|
private readonly MiningPoolManager _miningPoolManager;
|
||||||
|
|
||||||
|
public OnHookAutoMiningJob(MiningPoolManager miningPoolManager)
|
||||||
|
{
|
||||||
|
_miningPoolManager = miningPoolManager;
|
||||||
|
JobDetail = JobBuilder.Create<AutoRefreshMiningPoolJob>().WithIdentity(nameof(AutoRefreshMiningPoolJob))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//每小时执行一次
|
||||||
|
Trigger = TriggerBuilder.Create().WithIdentity(nameof(AutoRefreshMiningPoolJob))
|
||||||
|
.WithCronSchedule("0 0 * * * ?")
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
await _miningPoolManager.OnHookMiningAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
<ProjectReference Include="..\..\..\framework\Yi.Framework.Ddd.Application\Yi.Framework.Ddd.Application.csproj" />
|
<ProjectReference Include="..\..\..\framework\Yi.Framework.Ddd.Application\Yi.Framework.Ddd.Application.csproj" />
|
||||||
<ProjectReference Include="..\Yi.Framework.DigitalCollectibles.Application.Contracts\Yi.Framework.DigitalCollectibles.Application.Contracts.csproj" />
|
<ProjectReference Include="..\Yi.Framework.DigitalCollectibles.Application.Contracts\Yi.Framework.DigitalCollectibles.Application.Contracts.csproj" />
|
||||||
<ProjectReference Include="..\Yi.Framework.DigitalCollectibles.Domain\Yi.Framework.DigitalCollectibles.Domain.csproj" />
|
<ProjectReference Include="..\Yi.Framework.DigitalCollectibles.Domain\Yi.Framework.DigitalCollectibles.Domain.csproj" />
|
||||||
|
<PackageReference Include="Volo.Abp.BackgroundWorkers.Quartz" Version="$(AbpVersion)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public static class RarityEnumExtensions
|
|||||||
return display.Name!;
|
return display.Name!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static decimal[] GetProbabilityValues()
|
public static decimal[] GetProbabilityArray()
|
||||||
{
|
{
|
||||||
List<decimal> probabilityList = new List<decimal>();
|
List<decimal> probabilityList = new List<decimal>();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Yi.Framework.DigitalCollectibles.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
public enum MiningResultEnum
|
||||||
|
{
|
||||||
|
Success,
|
||||||
|
Empty,
|
||||||
|
PoolIsEmpty
|
||||||
|
}
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Enums\" />
|
|
||||||
<Folder Include="Etos\" />
|
<Folder Include="Etos\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Yi.Framework.DigitalCollectibles.Domain.Shared.Dtos;
|
namespace Yi.Framework.DigitalCollectibles.Domain.Dtos;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 矿池内容
|
/// 矿池内容
|
||||||
@@ -46,5 +46,9 @@ public class MiningPoolContent
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime EndTime{ get; set; }
|
public DateTime EndTime{ get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 总共剩余藏品数量
|
||||||
|
/// </summary>
|
||||||
|
public int TotalNumber => I0_OrdinaryNumber + I1_SeniorNumber + I2_RareNumber + I3_GemNumber + I4_LegendNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Entities;
|
||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Shared.Enums;
|
||||||
|
|
||||||
|
namespace Yi.Framework.DigitalCollectibles.Domain.Dtos;
|
||||||
|
|
||||||
|
public class MiningPoolResult
|
||||||
|
{
|
||||||
|
public MiningResultEnum Result { get; set; }
|
||||||
|
|
||||||
|
public CollectiblesAggregateRoot? Collectibles { get; set; }
|
||||||
|
}
|
||||||
@@ -2,9 +2,13 @@
|
|||||||
using Volo.Abp.Caching;
|
using Volo.Abp.Caching;
|
||||||
using Volo.Abp.Domain.Services;
|
using Volo.Abp.Domain.Services;
|
||||||
using Volo.Abp.Settings;
|
using Volo.Abp.Settings;
|
||||||
|
using Volo.Abp.Threading;
|
||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Dtos;
|
||||||
|
using Yi.Framework.DigitalCollectibles.Domain.Entities;
|
||||||
using Yi.Framework.DigitalCollectibles.Domain.Shared.Consts;
|
using Yi.Framework.DigitalCollectibles.Domain.Shared.Consts;
|
||||||
using Yi.Framework.DigitalCollectibles.Domain.Shared.Dtos;
|
using Yi.Framework.DigitalCollectibles.Domain.Shared.Enums;
|
||||||
using Yi.Framework.SettingManagement.Domain;
|
using Yi.Framework.SettingManagement.Domain;
|
||||||
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
||||||
|
|
||||||
namespace Yi.Framework.DigitalCollectibles.Domain.Managers;
|
namespace Yi.Framework.DigitalCollectibles.Domain.Managers;
|
||||||
|
|
||||||
@@ -14,45 +18,128 @@ namespace Yi.Framework.DigitalCollectibles.Domain.Managers;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MiningPoolManager : DomainService
|
public class MiningPoolManager : DomainService
|
||||||
{
|
{
|
||||||
/// <summary>
|
private readonly ISqlSugarRepository<CollectiblesAggregateRoot> _collectiblesRepository;
|
||||||
/// 每次挖矿概率,每天根据特定算法计算
|
private readonly ISqlSugarRepository<OnHookAggregateRoot> _onHookRepository;
|
||||||
/// </summary>
|
|
||||||
private static decimal CurrentMiningProbability { get; set; }
|
|
||||||
|
|
||||||
private readonly ISettingProvider _settingProvider;
|
private readonly ISettingProvider _settingProvider;
|
||||||
private readonly IDistributedCache<MiningPoolContent> _cache;
|
private readonly IDistributedCache<MiningPoolContent> _cache;
|
||||||
|
private readonly ISqlSugarRepository<CollectiblesUserStoreAggregateRoot> _userStoreRepository;
|
||||||
|
|
||||||
public MiningPoolManager(ISettingProvider settingProvider, IDistributedCache<MiningPoolContent> cache)
|
public MiningPoolManager(ISettingProvider settingProvider, IDistributedCache<MiningPoolContent> cache,
|
||||||
|
ISqlSugarRepository<CollectiblesAggregateRoot> collectiblesRepository,
|
||||||
|
ISqlSugarRepository<OnHookAggregateRoot> onHookRepository,
|
||||||
|
ISqlSugarRepository<CollectiblesUserStoreAggregateRoot> userStoreRepository)
|
||||||
{
|
{
|
||||||
_settingProvider = settingProvider;
|
_settingProvider = settingProvider;
|
||||||
this._cache = cache;
|
this._cache = cache;
|
||||||
|
_collectiblesRepository = collectiblesRepository;
|
||||||
|
_onHookRepository = onHookRepository;
|
||||||
|
_userStoreRepository = userStoreRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 最后一次计算挖矿概率的时间,如果时间跨了早上10点,重新计算
|
/// 每次挖矿概率,每天根据特定算法计算
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static DateTime LastComputeMiningProbabilityTime { get; set; }
|
private static decimal CurrentMiningProbability => AsyncHelper.RunSync(async () =>
|
||||||
|
{
|
||||||
|
return await ComputeMiningProbabilityAsync();
|
||||||
|
});
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 用户进行一次挖矿
|
/// 用户进行一次挖矿
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task MiningAsync(Guid userId)
|
public async Task<MiningPoolResult> MiningAsync(Guid userId)
|
||||||
{
|
{
|
||||||
//从矿池中开挖
|
var result = new MiningPoolResult();
|
||||||
|
//从矿池中开挖,判断矿池是否还有矿
|
||||||
//根据挖矿概率,进行挖掘
|
//根据挖矿概率,进行挖掘
|
||||||
//挖到了放到用户仓库即可
|
//挖到了放到用户仓库即可
|
||||||
|
|
||||||
//如果概率是挖到了矿,再从矿物中随机选择一个稀有度,再在当前稀有度中的矿物列表,随机选择一个具体的矿物
|
//如果概率是挖到了矿,再从矿物中随机选择一个稀有度,再在当前稀有度中的矿物列表,随机选择一个具体的矿物
|
||||||
|
var pool = await _cache.GetAsync(CacheConst.MiningPoolContent);
|
||||||
|
if (pool.TotalNumber == 0)
|
||||||
|
{
|
||||||
|
result.Result = MiningResultEnum.PoolIsEmpty;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
throw new NotImplementedException();
|
// 生成一个 0 到 1 之间的随机数
|
||||||
|
double randomValue = new Random().NextDouble();
|
||||||
|
//如果随机的概率在当前概率内,成功
|
||||||
|
if (randomValue.To<decimal>() < CurrentMiningProbability)
|
||||||
|
{
|
||||||
|
//成功后在藏品中根据稀有度概率必定获取一个
|
||||||
|
var probabilityArray = RarityEnumExtensions.GetProbabilityArray();
|
||||||
|
var index = GetRandomIndex(probabilityArray);
|
||||||
|
var rarityType = (RarityEnum)Enum.GetValues(typeof(RarityEnum)).GetValue(index);
|
||||||
|
var collectiblesList =
|
||||||
|
await _collectiblesRepository._DbQueryable.Where(x => x.Rarity == rarityType).ToListAsync();
|
||||||
|
int randomIndex = new Random().Next(collectiblesList.Count);
|
||||||
|
var currentCollectibles = collectiblesList[randomIndex];
|
||||||
|
result.Result = MiningResultEnum.Success;
|
||||||
|
result.Collectibles = currentCollectibles;
|
||||||
|
|
||||||
|
//使用结果新增给对应的用户
|
||||||
|
await _userStoreRepository.InsertAsync(new CollectiblesUserStoreAggregateRoot
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
CollectiblesId = result.Collectibles.Id,
|
||||||
|
IsRead = false
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Result = MiningResultEnum.Empty;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 挂机挖矿
|
||||||
|
/// </summary>
|
||||||
|
public async Task OnHookMiningAsync()
|
||||||
|
{
|
||||||
|
//获取当前激活的挂机挖矿
|
||||||
|
var currentOnHook = await _onHookRepository._DbQueryable.Where(x => x.IsActive == true)
|
||||||
|
.Where(x => x.EndTime <= DateTime.Now).ToListAsync();
|
||||||
|
|
||||||
|
//根据用户对挂机卡hash关系
|
||||||
|
var userOnHookDic = currentOnHook.GroupBy(x => x.UserId).ToDictionary(x => x.Key, y => y.First());
|
||||||
|
foreach (var onHookItem in userOnHookDic)
|
||||||
|
{
|
||||||
|
await MiningAsync(onHookItem.Value.UserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetRandomIndex(decimal[] probabilities)
|
||||||
|
{
|
||||||
|
// 生成0到1之间的随机数
|
||||||
|
Random random = new Random();
|
||||||
|
decimal randomValue = random.NextDouble().To<decimal>();
|
||||||
|
|
||||||
|
decimal cumulativeProbability = 0.0m;
|
||||||
|
|
||||||
|
for (int i = 0; i < probabilities.Length; i++)
|
||||||
|
{
|
||||||
|
cumulativeProbability += probabilities[i];
|
||||||
|
|
||||||
|
// 判断随机数是否小于当前的累积概率
|
||||||
|
if (randomValue < cumulativeProbability)
|
||||||
|
{
|
||||||
|
return i; // 返回中标的索引
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//剩余情况都是普通
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 计算当前挖矿概率
|
/// 计算当前挖矿概率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task ComputeMiningProbabilityAsync()
|
public static Task<decimal> ComputeMiningProbabilityAsync()
|
||||||
{
|
{
|
||||||
//当前的挖矿期望:当天的所有藏品能被刚好挖完
|
//当前的挖矿期望:当天的所有藏品能被刚好挖完
|
||||||
|
|
||||||
@@ -61,8 +148,8 @@ public class MiningPoolManager : DomainService
|
|||||||
//自动挖矿:1天可以挖24次 每次间隔60分钟(需要使用自动挖矿卡)
|
//自动挖矿:1天可以挖24次 每次间隔60分钟(需要使用自动挖矿卡)
|
||||||
//可影响因素:剩余手动挖矿次数+剩余自动挖矿次数
|
//可影响因素:剩余手动挖矿次数+剩余自动挖矿次数
|
||||||
|
|
||||||
//所有能够挖掘次数
|
//简单模式,1/15
|
||||||
throw new NotImplementedException();
|
return Task.FromResult(1m / 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -76,7 +163,7 @@ public class MiningPoolManager : DomainService
|
|||||||
|
|
||||||
DateTime startTime = DateTime.Today.AddHours(10);
|
DateTime startTime = DateTime.Today.AddHours(10);
|
||||||
DateTime endTime = startTime.AddDays(1);
|
DateTime endTime = startTime.AddDays(1);
|
||||||
var probabilityValues = RarityEnumExtensions.GetProbabilityValues();
|
var probabilityValues = RarityEnumExtensions.GetProbabilityArray();
|
||||||
var result = GenerateDistribution(maximumPoolLimit, probabilityValues);
|
var result = GenerateDistribution(maximumPoolLimit, probabilityValues);
|
||||||
|
|
||||||
//根据配置,将不同比例的矿,塞入矿池,
|
//根据配置,将不同比例的矿,塞入矿池,
|
||||||
|
|||||||
Reference in New Issue
Block a user