提交代码

This commit is contained in:
zpc 2024-12-04 14:00:40 +08:00
parent d39d798bb5
commit 977b3a8a7e
20 changed files with 801 additions and 199 deletions

View File

@ -66,7 +66,7 @@ namespace CloudGaming.Code.AppExtend
{
if (!httpRequest.Headers.TryGetValue("Version", out var _version))
{
_version = "1.0.0";
_version = "1.0.1";
}
version = _version;
}

View File

@ -1,6 +1,7 @@
using AutoMapper;
using CloudGaming.Code.Cache.Special;
using CloudGaming.DtoModel;
using CloudGaming.DtoModel.Game;
using CloudGaming.DtoModel.Mall;
using CloudGaming.DtoModel.RedemptionCode;
@ -54,12 +55,23 @@ namespace CloudGaming.Code.Cache
#region
private CommonDataEntityCache<T_App_Config>? _appConfigCache;
private CommonDataEntityCache<AppConfigCache>? _appConfigCache;
/// <summary>
/// 配置缓存列表
/// </summary>
public List<T_App_Config> AppConfigList => GetCacheList(ref _appConfigCache);
public List<AppConfigCache> AppConfigList
{
get
{
if (_appConfigCache == null)
{
_appConfigCache = new AppConfigEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper, _gamingBase.AppConfig);
}
return _appConfigCache.DataList ?? new List<AppConfigCache>();
}
}
#endregion
@ -261,7 +273,7 @@ namespace CloudGaming.Code.Cache
/// <summary>
/// 获取实体缓存
/// </summary>
public static CommonDataEntityCache<T> GetDataEntityCache<T>(CloudGamingBase cloudGamingBase, Expression<Func<T, bool>>? expWhere = null, int cacheTime =36000) where T : class
public static CommonDataEntityCache<T> GetDataEntityCache<T>(CloudGamingBase cloudGamingBase, Expression<Func<T, bool>>? expWhere = null, int cacheTime = 36000) where T : class
{
var typeLock = typeof(T);
var namespaceKey = typeLock.Namespace;

View File

@ -0,0 +1,40 @@
using AutoMapper;
using CloudGaming.AppConfigModel;
using CloudGaming.Code.DataAccess;
using CloudGaming.DtoModel;
using CloudGaming.DtoModel.Game;
using HuanMeng.DotNetCore.CacheHelper;
using HuanMeng.DotNetCore.Redis;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.Cache.Special
{
/// <summary>
///
/// </summary>
/// <param name="dao"></param>
/// <param name="database"></param>
/// <param name="mapper"></param>
/// <param name="appConfig"></param>
public class AppConfigEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : RedisDataEntityCache<AppConfigCache>(database, 0)
{
public override string key => $"cache:appconfig:list";
public override List<AppConfigCache> GetDataList()
{
var list = dao.DaoExt.Context.T_App_Config.ToList();
var appList = mapper.Map<List<AppConfigCache>>(list);
return appList;
}
}
}

View File

@ -4,6 +4,7 @@ using Bogus;
using CloudGaming.Code.Config;
using CloudGaming.Code.DataAccess;
using CloudGaming.DtoModel;
using CloudGaming.DtoModel.Game;
using CloudGaming.GameModel.Db.Db_Game;
@ -38,23 +39,24 @@ namespace CloudGaming.Code.Cache.Special
var gameCbtList = dao.DaoPhone.Context.T_GameCBT.AsNoTracking().Where(it => it.IsOnline).ToList() ?? new List<T_GameCBT>();
var gameListDict = dao.DaoGame.Context.T_Game_List.AsNoTracking().ToDictionary(g => g.GameId);
var gameChildList = dao.DaoGame.Context.T_Game_ChildList.AsNoTracking().ToList();
var gameTypesDict = dao.DaoGame.Context.T_Game_Types.AsNoTracking().ToDictionary(type => type.TypeId);
var gameTagsDict = dao.DaoGame.Context.T_Game_Tags.AsNoTracking().ToDictionary(tag => tag.TagId);
//游戏分享头像
var gameUserShare = dao.DaoGame.Context.T_Game_UserShare.AsNoTracking().GroupBy(it => it.GameId).ToDictionary(it => it.Key, it => it.Last().NickName);
var appConfig = dao.DaoExt.Context.T_App_Config.AsNoTracking().Where(it => it.ConfigType == 3).ToList();
var config = appConfig.GetAppConfig(3, 1, null);
//默认游戏钻石消耗
var defaultConsumeDiamondNumHour = 0;
if (!string.IsNullOrEmpty(config?.ConfigValue))
var appConfig = dao.DaoExt.Context.T_App_Config.AsNoTracking().Where(it => it.ConfigType == 3).ToList();
if (appConfig != null && appConfig.Count > 0)
{
int.TryParse(config?.ConfigValue, out defaultConsumeDiamondNumHour);
}
//var lorem = new Bogus.DataSets.Lorem(locale: "zh_CN");
var faker = new Faker("zh_CN");
//f.r
var appConfigList = mapper.Map<List<AppConfigCache>>(appConfig);
var config = appConfigList.GetAppConfig(3, 1, null);
//lorem.
if (!string.IsNullOrEmpty(config?.ConfigValue))
{
int.TryParse(config?.ConfigValue, out defaultConsumeDiamondNumHour);
}
}
var faker = new Faker("zh_CN");
var gameInfos = gameCbtList
.Where(gameCbt => gameListDict.ContainsKey(gameCbt.GameId))
.Select(gameCbt =>

View File

@ -23,9 +23,9 @@ namespace CloudGaming.Code.Cache.Special;
/// <param name="database"></param>
/// <param name="mapper"></param>
/// <param name="appConfig"></param>
public class ProductCacheEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<ProductCache>(database, GameEntityCache.GameEntityCacheLock, 60 * 60 * 12)
public class ProductCacheEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<ProductCache>(database, 60 * 60 * 12)
{
public override string key => "App:Product";
public override string key => "cache:Product:list";
/// <summary>
///

View File

@ -22,7 +22,7 @@ namespace CloudGaming.Code.Cache.Special;
/// <param name="dao"></param>
/// <param name="database"></param>
/// <param name="mapper"></param>
public class RedemptionCodeEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<RedemptionCodeCache>(database, GameEntityCache.GameEntityCacheLock, 60 * 60 * 1)
public class RedemptionCodeEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<RedemptionCodeCache>(database,60 * 60 * 1)
{
public override List<RedemptionCodeCache> GetDataList()
{
@ -47,5 +47,5 @@ public class RedemptionCodeEntityCache(DAO dao, IDatabase database, IMapper mapp
return sevenDayCache;
}
public override string key => "App:RedemptionCode";
public override string key => "cache:RedemptionCode:list";
}

View File

@ -22,7 +22,7 @@ namespace CloudGaming.Code.Cache.Special;
/// <param name="dao"></param>
/// <param name="database"></param>
/// <param name="mapper"></param>
public class SevenDayEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<SevenDayCache>(database, GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7)
public class SevenDayEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache<SevenDayCache>(database, 60 * 60 * 24 * 7)
{
public override List<SevenDayCache> GetDataList()
{
@ -47,5 +47,5 @@ public class SevenDayEntityCache(DAO dao, IDatabase database, IMapper mapper) :
return sevenDayCache;
}
public override string key => "App:SevenDay";
public override string key => "cache:SevenDay:list";
}

View File

@ -1,3 +1,5 @@
using CloudGaming.DtoModel;
using System;
using System.Collections.Generic;
using System.Linq;
@ -18,24 +20,14 @@ public static class AppConfigBLLExtend
/// <param name="app_Configs"></param>
/// <param name="appRequestInfo"></param>
/// <returns></returns>
public static bool GetAppIsChecking(this List<T_App_Config> app_Configs, AppRequestConfig appRequestInfo)
public static bool GetAppIsChecking(this List<AppConfigCache> app_Configs, AppRequestConfig appRequestInfo)
{
var config = GetAppConfig(app_Configs, 7, 1, appRequestInfo);
if (config == null || string.IsNullOrEmpty(config.ConfigValue))
if (config == null)
{
return false;
}
var version = config.ConfigValue.Replace(".", "");
if (!int.TryParse(version, out int versionNum))
{
return false;
}
if (appRequestInfo.VersionNum >= versionNum)
{
return config.IsShow;
}
return false;
return config.IsEnabled;
}
/// <summary>
@ -46,9 +38,9 @@ public static class AppConfigBLLExtend
/// <param name="cfgId"></param>
/// <param name="appRequestInfo"></param>
/// <returns></returns>
public static T_App_Config GetAppConfig(this List<T_App_Config> app_Configs, int cfgType, int cfgId, AppRequestConfig? appRequestInfo)
public static AppConfigCache GetAppConfig(this List<AppConfigCache> app_Configs, int cfgType, int cfgId, AppRequestConfig? appRequestInfo)
{
var list = GetAppCfgList(app_Configs, cfgType, cfgId, appRequestInfo?.Channel, appRequestInfo?.Platform, appRequestInfo?.Continent, appRequestInfo?.CountryName);
var list = GetAppCfgList(app_Configs, cfgType, cfgId, appRequestInfo?.Channel, appRequestInfo?.Platform, appRequestInfo.VersionNum, appRequestInfo?.Continent, appRequestInfo?.CountryName);
return list.FirstOrDefault();
}
@ -60,9 +52,9 @@ public static class AppConfigBLLExtend
/// <param name="cfgId"></param>
/// <param name="appRequestInfo"></param>
/// <returns></returns>
public static List<T_App_Config> GetAppCfgList(this List<T_App_Config> app_Configs, int cfgType, int cfgId, AppRequestConfig appRequestInfo)
public static List<AppConfigCache> GetAppCfgList(this List<AppConfigCache> app_Configs, int cfgType, int cfgId, AppRequestConfig appRequestInfo)
{
return GetAppCfgList(app_Configs, cfgType, cfgId, appRequestInfo.Channel, appRequestInfo.Platform, appRequestInfo.Continent, appRequestInfo.CountryName);
return GetAppCfgList(app_Configs, cfgType, cfgId, appRequestInfo.Channel, appRequestInfo.Platform, appRequestInfo.VersionNum, appRequestInfo.Continent, appRequestInfo.CountryName);
}
/// <summary>
@ -73,80 +65,27 @@ public static class AppConfigBLLExtend
/// <param name="cfgId"></param>
/// <param name="bossId"></param>
/// <param name="plat"></param>
/// <param name="appVersion"></param>
/// <param name="continent"></param>
/// <param name="countryName"></param>
/// <returns></returns>
public static List<T_App_Config> GetAppCfgList(this List<T_App_Config> app_Configs, int cfgType, int cfgId, string bossId, string plat = "", string continent = "", string countryName = "")
public static List<AppConfigCache> GetAppCfgList(this List<AppConfigCache> app_Configs, int cfgType, int cfgId, string bossId, string plat = "", int appVersion = 0, string continent = "", string countryName = "")
{
//有很多老配置没有appid的参与
var lst = app_Configs.Where(it => it.ConfigType == cfgType && it.ConfigId == cfgId).ToList();
#region
if (!string.IsNullOrEmpty(continent))
{
var tempList = lst.Where(it => !string.IsNullOrEmpty(it.Continent) && (it.Continent + ",").Contains(continent + ",")).ToList();
if (tempList == null || tempList.Count == 0)
{
tempList = lst.Where(it => string.IsNullOrEmpty(it.Continent)).ToList();
}
lst = tempList;
}
else
{
lst = lst.Where(it => string.IsNullOrEmpty(it.Continent)).ToList();
}
// 计算地区、国家
lst = lst.Where(it => it.IsContinentMatch(continent)).ToList();
lst = lst.Where(it => it.IsCountryNameMatch(countryName)).ToList();
// 计算平台
lst = lst.Where(it => it.IsPlatformMatch(plat)).ToList();
if (!string.IsNullOrEmpty(countryName))
{
var tempList = lst.Where(it => !string.IsNullOrEmpty(it.CountryName) && (it.CountryName + ",").Contains(countryName + ",")).ToList();
if (tempList == null || tempList.Count == 0)
{
tempList = lst.Where(it => string.IsNullOrEmpty(it.CountryName)).ToList();
}
lst = tempList;
}
else
{
lst = lst.Where(it => string.IsNullOrEmpty(it.CountryName)).ToList();
}
#endregion
#region
if (!string.IsNullOrEmpty(plat))
{
var tempList = lst.Where(a => a.Plat != null && a.Plat == plat).ToList();
if (tempList == null || tempList.Count == 0)
{
tempList = lst.Where(a => a.Plat == null || string.IsNullOrEmpty(a.Plat)).ToList();
}
lst = tempList;
}
else
{
lst = lst.Where(a => a.Plat == null || string.IsNullOrEmpty(a.Plat)).ToList();
}
#endregion
#region
if (!string.IsNullOrEmpty(bossId))
{
var lsts = lst.Where(a => a.BossId != null && (a.BossId == bossId || a.BossId.Contains(bossId))).ToList();
if (lsts == null || lsts.Count == 0)
{
lsts = lst.Where(it => it.BossId == null || string.IsNullOrEmpty(it.BossId)).ToList();
}
lst = lsts;
}
else
{
lst = lst.Where(it => it.BossId == null || string.IsNullOrEmpty(it.BossId)).ToList();
}
#endregion
// 计算版本号
lst = lst.Where(it => it.IsAppVersion(appVersion)).ToList();
// 计算渠道号
lst = lst.Where(it => it.IsChannelIdMatch(bossId)).ToList();
return lst;
}

View File

@ -55,7 +55,7 @@ public class MonitorBLL : CloudGamingBase
List<StatisticsDto> userLogin = new List<StatisticsDto>();
List<StatisticsDto> userRegistr = new List<StatisticsDto>();
List<StatisticsDto> userActive = new List<StatisticsDto>();
var nowDay = int.Parse(DateTime.Now.ToString("yyyyMMdd"));
while (curr <= endDate)
{
int day = int.Parse(curr.ToString("yyyyMMdd"));
@ -68,9 +68,20 @@ public class MonitorBLL : CloudGamingBase
StatisticsDto _UserLogin = new StatisticsDto(currDateStr, 0, "全部");
StatisticsDto _userRegistr = new StatisticsDto(currDateStr, 0, "全部");
StatisticsDto _userActive = new StatisticsDto(currDateStr, 0, "全部");
if (day == nowDay)
{
var m = AppConfig.GetAppMonitorInfo();
_UserLogin.Value += m.TodayLoggedInUsers;
_userRegistr.Value += m.TodayRegisteredUsers;
_userActive.Value += 0;
}
foreach (var _channel in channels)
{
var item = _Statistics_Users.FirstOrDefault(it => it.Channel == _channel);
if (item == null)
{
item = new T_Statistics_User();
@ -80,7 +91,6 @@ public class MonitorBLL : CloudGamingBase
_userActive.Value += item.ActiveCount;
//item.ActiveCount
statisticsDtoUserList.Add(new StatisticsDto(currDateStr, item.LoginCount, item.Channel));
statisticsDtoRegistrList.Add(new StatisticsDto(currDateStr, item.RegistrCount, item.Channel));
statisticsDtoActiveList.Add(new StatisticsDto(currDateStr, item.ActiveCount, item.Channel));

View File

@ -63,4 +63,5 @@ public class MonitorProcessor : AppJobBase
appMonitorInfo.CurrentQueuedUsers = currentQueuedUsers;
appMonitorInfo.CurrentPlayingUsers = currentPlayingUsers;
}
}
}

View File

@ -8,68 +8,130 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.Code.Monitor
namespace CloudGaming.Code.Monitor;
/// <summary>
/// 订单数据统计
/// </summary>
[QuartzTrigger("OrderMonitorProcessor", "* 25 4 * * ?")]
public class OrderMonitorProcessor : AppJobBase
{
/// <summary>
/// 订单数据统计
/// </summary>
[QuartzTrigger("UserMonitorProcessor", "* 25 4 * * ?")]
//[QuartzTrigger("OrderMonitorProcessor", "0 0/1 * * * ?")]
public class OrderMonitorProcessor : AppJobBase
public OrderMonitorProcessor(IServiceScopeFactory scopeFactory) : base(scopeFactory)
{
public OrderMonitorProcessor(IServiceScopeFactory scopeFactory) : base(scopeFactory)
}
public override async Task AppConfigProcessLoop(AppConfig appConfig, AppMonitorInfo appMonitorInfo, IServiceProvider serviceProvider, CloudGamingBase cloudGamingBase)
{
var dao = cloudGamingBase.Dao;
var now = DateTime.Now.AddDays(-1);
int day = int.Parse(now.ToString("yyyyMMdd"));
var nowDay = DateOnly.FromDateTime(now);
//意向订单次数
var intendedOrder = await dao.DaoUser.Context.T_User_IntentOrder.Where(it => it.CreatedDay == day).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Count());
//支付订单次数
var paidOrders = await dao.DaoUser.Context.T_User_Order.Where(it => it.PaymentDay == nowDay).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Count());
//支付金额
var paidOrdersPrice = await dao.DaoUser.Context.T_User_Order.Where(it => it.PaymentDay == nowDay).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Sum(it => it.TotalPrice));
//数据源
var orderStatistics = await dao.DaoExt.Context.T_Statistics_Order
.Where(it => it.LoginDay == day)
.ToDictionaryAsync(it => it.Channel ?? "");
// 更新或创建统计记录
void UpdateStatistics(string channel, int intendedOrderCount, int paidOrders, decimal rechargeAmount)
{
}
public override async Task AppConfigProcessLoop(AppConfig appConfig, AppMonitorInfo appMonitorInfo, IServiceProvider serviceProvider, CloudGamingBase cloudGamingBase)
{
var dao = cloudGamingBase.Dao;
var now = DateTime.Now.AddDays(-1);
int day = int.Parse(now.ToString("yyyyMMdd"));
var nowDay = DateOnly.FromDateTime(now);
//意向订单次数
var intendedOrder = await dao.DaoUser.Context.T_User_IntentOrder.Where(it => it.CreatedDay == day).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Count());
//支付订单次数
var paidOrders = await dao.DaoUser.Context.T_User_Order.Where(it => it.PaymentDay == nowDay).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Count());
//支付金额
var paidOrdersPrice = await dao.DaoUser.Context.T_User_Order.Where(it => it.PaymentDay == nowDay).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Sum(it => it.TotalPrice));
//数据源
var orderStatistics = await dao.DaoExt.Context.T_Statistics_Order
.Where(it => it.LoginDay == day)
.ToDictionaryAsync(it => it.Channel ?? "");
// 更新或创建统计记录
void UpdateStatistics(string channel, int intendedOrderCount, int paidOrders, decimal rechargeAmount)
if (!orderStatistics.TryGetValue(channel, out var statisticsUser))
{
if (!orderStatistics.TryGetValue(channel, out var statisticsUser))
statisticsUser = new T_Statistics_Order()
{
statisticsUser = new T_Statistics_Order()
{
RechargeAmount = 0,
Channel = channel,
CreatedAt = DateTime.Now,
IntendedOrderCount = 0,
PaidOrders = 0,
LoginDate = nowDay,
LoginDay = day,
UpdatedAt = DateTime.Now,
};
dao.DaoExt.Context.T_Statistics_Order.Add(statisticsUser);
orderStatistics.Add(channel, statisticsUser);
}
statisticsUser.RechargeAmount = rechargeAmount;
statisticsUser.IntendedOrderCount = intendedOrderCount;
statisticsUser.PaidOrders = paidOrders;
statisticsUser.UpdatedAt = DateTime.Now;
RechargeAmount = 0,
Channel = channel,
CreatedAt = DateTime.Now,
IntendedOrderCount = 0,
PaidOrders = 0,
LoginDate = nowDay,
LoginDay = day,
UpdatedAt = DateTime.Now,
};
dao.DaoExt.Context.T_Statistics_Order.Add(statisticsUser);
orderStatistics.Add(channel, statisticsUser);
}
foreach (var item in intendedOrder)
{
UpdateStatistics(item.Key, item.Value, paidOrders.GetValueOrDefault(item.Key, 0), paidOrdersPrice.GetValueOrDefault(item.Key, 0));
}
await dao.DaoExt.Context.SaveChangesAsync();
statisticsUser.RechargeAmount = rechargeAmount;
statisticsUser.IntendedOrderCount = intendedOrderCount;
statisticsUser.PaidOrders = paidOrders;
statisticsUser.UpdatedAt = DateTime.Now;
}
foreach (var item in intendedOrder)
{
UpdateStatistics(item.Key, item.Value, paidOrders.GetValueOrDefault(item.Key, 0), paidOrdersPrice.GetValueOrDefault(item.Key, 0));
}
await dao.DaoExt.Context.SaveChangesAsync();
}
}
[QuartzTrigger("OrderHourMonitorProcessor", "0 5 * * * ?")]
public class OrderHourMonitorProcessor : AppJobBase
{
public OrderHourMonitorProcessor(IServiceScopeFactory scopeFactory) : base(scopeFactory)
{
}
public override async Task AppConfigProcessLoop(AppConfig appConfig, AppMonitorInfo appMonitorInfo, IServiceProvider serviceProvider, CloudGamingBase cloudGamingBase)
{
var dao = cloudGamingBase.Dao;
var now = DateTime.Now.AddHours(-1);
int day = int.Parse(now.ToString("yyyyMMdd"));
var newDayHour = now.Date.AddHours(now.Hour);
var oldDayHour = now.Date.AddHours(now.AddHours(1).Hour);
int dayHour = int.Parse(now.ToString("yyyyMMddHH"));
var nowDay = DateOnly.FromDateTime(now);
//意向订单次数
var intendedOrder = await dao.DaoUser.Context.T_User_IntentOrder.Where(it => it.CreatedDay == day && it.CreatedAt >= newDayHour && it.CreatedAt <= oldDayHour).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Count());
//支付订单次数
var paidOrders = await dao.DaoUser.Context.T_User_Order.Where(it => it.PaymentDay == nowDay && it.CreatedAt >= newDayHour && it.CreatedAt <= oldDayHour).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Count());
//支付金额
var paidOrdersPrice = await dao.DaoUser.Context.T_User_Order.Where(it => it.PaymentDay == nowDay && it.CreatedAt >= newDayHour && it.CreatedAt <= oldDayHour).GroupBy(it => it.Channel).ToDictionaryAsync(it => it.Key ?? "", it => it.Sum(it => it.TotalPrice));
//数据源
var orderStatistics = await dao.DaoExt.Context.T_Statistics_OrderHour
.Where(it => it.LoginHour == dayHour)
.ToDictionaryAsync(it => it.Channel ?? "");
// 更新或创建统计记录
void UpdateStatistics(string channel, int intendedOrderCount, int paidOrders, decimal rechargeAmount)
{
if (!orderStatistics.TryGetValue(channel, out var statisticsUser))
{
statisticsUser = new T_Statistics_OrderHour()
{
RechargeAmount = 0,
Channel = channel,
CreatedAt = DateTime.Now,
IntendedOrderCount = 0,
PaidOrders = 0,
LoginDate = nowDay,
LoginDay = day,
UpdatedAt = DateTime.Now,
LoginHour = dayHour,
};
dao.DaoExt.Context.T_Statistics_OrderHour.Add(statisticsUser);
orderStatistics.Add(channel, statisticsUser);
}
statisticsUser.RechargeAmount = rechargeAmount;
statisticsUser.IntendedOrderCount = intendedOrderCount;
statisticsUser.PaidOrders = paidOrders;
statisticsUser.UpdatedAt = DateTime.Now;
}
foreach (var item in intendedOrder)
{
UpdateStatistics(item.Key, item.Value, paidOrders.GetValueOrDefault(item.Key, 0), paidOrdersPrice.GetValueOrDefault(item.Key, 0));
}
await dao.DaoExt.Context.SaveChangesAsync();
}
}

View File

@ -0,0 +1,186 @@
using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CloudGaming.DtoModel;
/// <summary>
///
/// </summary>
[AutoMap(typeof(T_App_Config))]
public class AppConfigCache : T_App_Config
{
private int? appVersionNum;
/// <summary>
/// 版本号
/// </summary>
public int AppVersionNum
{
get
{
if (appVersionNum == null)
{
if (AppVersion == null || string.IsNullOrEmpty(AppVersion))
{
appVersionNum = 0;
}
else
{
var tempAppVersion = AppVersion;
if (AppVersion.StartsWith("+") || AppVersion.StartsWith("-"))
{
tempAppVersion = AppVersion.Substring(1);
}
tempAppVersion = tempAppVersion.Replace(".", "");
if (int.TryParse(tempAppVersion, out var _appVersion))
{
appVersionNum = _appVersion;
}
else
{
appVersionNum = -1;
}
}
}
return appVersionNum ?? -1;
}
}
/// <summary>
/// 判断版本号
/// </summary>
/// <param name="version"></param>
/// <returns></returns>
public bool IsAppVersion(string version)
{
if (version == null || string.IsNullOrEmpty(version))
{
return IsAppVersion(0);
}
if (int.TryParse(version.Replace(".", ""), out var v))
{
return IsAppVersion(version);
}
return false;
}
/// <summary>
/// 判断版本号
/// </summary>
/// <param name="version"></param>
/// <returns></returns>
public bool IsAppVersion(int version)
{
if (AppVersionNum == -1)
{
return false;
}
if (version == 0 && string.IsNullOrEmpty(AppVersion))
{
return true;
}
else if (version == 0 && !string.IsNullOrEmpty(AppVersion))
{
return false;
}
if (string.IsNullOrEmpty(AppVersion))
{
return true;
}
if (AppVersion.StartsWith("+"))
{
//大于 如 1.0.1< 1.0.2
if (AppVersionNum < version)
{
return true;
}
return false;
}
if (AppVersion.StartsWith("-"))
{
//小于 如 1.0.1< 1.0.2
if (AppVersionNum > version)
{
return true;
}
return false;
}
if (AppVersionNum == version)
{
return true;
}
return false;
}
/// <summary>
/// 判断当前配置的洲是否匹配给定的洲。
/// </summary>
/// <param name="continent">要匹配的洲名称。</param>
/// <returns>如果匹配则返回 true否则返回 false。</returns>
public bool IsContinentMatch(string continent)
{
// 如果给定的洲不为空,则检查当前配置的洲是否包含给定的洲
if (!string.IsNullOrEmpty(continent))
{
return !string.IsNullOrEmpty(this.Continent) && (this.Continent + ",").Contains(continent + ",");
}
// 如果给定的洲为空,则检查当前配置的洲是否为空
return string.IsNullOrEmpty(this.Continent);
}
/// <summary>
/// 判断当前配置的国家是否匹配给定的国家。
/// </summary>
/// <param name="countryName">要匹配的国家名称。</param>
/// <returns>如果匹配则返回 true否则返回 false。</returns>
public bool IsCountryNameMatch(string countryName)
{
// 如果给定的国家不为空,则检查当前配置的国家是否包含给定的国家
if (!string.IsNullOrEmpty(countryName))
{
return !string.IsNullOrEmpty(this.CountryName) && (this.CountryName + ",").Contains(countryName + ",");
}
// 如果给定的国家为空,则检查当前配置的国家是否为空
return string.IsNullOrEmpty(this.CountryName);
}
/// <summary>
/// 判断当前配置的平台是否匹配给定的平台。
/// </summary>
/// <param name="plat">要匹配的平台名称。</param>
/// <returns>如果匹配则返回 true否则返回 false。</returns>
public bool IsPlatformMatch(string plat)
{
// 如果给定的平台不为空,则检查当前配置的平台是否等于给定的平台
if (!string.IsNullOrEmpty(plat))
{
return (this.Plat == null || string.IsNullOrEmpty(this.Plat)) || this.Plat == plat;
}
// 如果给定的平台为空,则检查当前配置的平台是否为空
return this.Plat == null || string.IsNullOrEmpty(this.Plat);
}
/// <summary>
/// 判断当前配置的渠道号是否匹配给定的渠道号。
/// </summary>
/// <param name="bossId">要匹配的渠道号。</param>
/// <returns>如果匹配则返回 true否则返回 false。</returns>
public bool IsChannelIdMatch(string bossId)
{
// 如果给定的渠道号不为空,则检查当前配置的渠道号是否包含或等于给定的渠道号
if (!string.IsNullOrEmpty(bossId))
{
return (this.ChannelId == null || string.IsNullOrEmpty(this.ChannelId)) || (this.ChannelId != null && (this.ChannelId == bossId || this.ChannelId.Contains(bossId)));
}
// 如果给定的渠道号为空,则检查当前配置的渠道号是否为空
return this.ChannelId == null || string.IsNullOrEmpty(this.ChannelId);
}
}

View File

@ -45,7 +45,12 @@ public partial class CloudGamingCBTContext : DbContext
/// <summary>
/// App配置
/// app渠道表
/// </summary>
public virtual DbSet<T_App_Channel> T_App_Channel { get; set; }
/// <summary>
/// App配置表
/// </summary>
public virtual DbSet<T_App_Config> T_App_Config { get; set; }
@ -64,16 +69,31 @@ public partial class CloudGamingCBTContext : DbContext
/// </summary>
public virtual DbSet<T_Statistics_Game> T_Statistics_Game { get; set; }
/// <summary>
/// 游戏统计数据-每小时
/// </summary>
public virtual DbSet<T_Statistics_GameHour> T_Statistics_GameHour { get; set; }
/// <summary>
/// 订单统计表
/// </summary>
public virtual DbSet<T_Statistics_Order> T_Statistics_Order { get; set; }
/// <summary>
/// 订单统计表
/// </summary>
public virtual DbSet<T_Statistics_OrderHour> T_Statistics_OrderHour { get; set; }
/// <summary>
/// 用户统计表
/// </summary>
public virtual DbSet<T_Statistics_User> T_Statistics_User { get; set; }
/// <summary>
/// 用户统计表
/// </summary>
public virtual DbSet<T_Statistics_UserHour> T_Statistics_UserHour { get; set; }
/// <summary>
/// 用户登录日志表,每天每个用户只有一条数据
/// </summary>
@ -94,17 +114,45 @@ public partial class CloudGamingCBTContext : DbContext
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<T_App_Channel>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_App_Ch__3214EC07E413C19A");
entity.ToTable(tb => tb.HasComment("app渠道表"));
entity.Property(e => e.ChannelId)
.HasMaxLength(10)
.HasComment("渠道号");
entity.Property(e => e.CreateAt)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.Desc)
.HasMaxLength(50)
.HasComment("备注");
entity.Property(e => e.Name)
.HasMaxLength(255)
.HasComment("渠道名称");
entity.Property(e => e.UpdateAt)
.HasComment("修改时间")
.HasColumnType("datetime");
});
modelBuilder.Entity<T_App_Config>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK_T_APP_CONFIG");
entity.ToTable(tb => tb.HasComment("App配置"));
entity.ToTable(tb => tb.HasComment("App配置"));
entity.Property(e => e.BossId)
.HasMaxLength(200)
entity.Property(e => e.ActionId).HasComment("配置值类型");
entity.Property(e => e.AppVersion)
.HasMaxLength(20)
.HasComment("app版本号");
entity.Property(e => e.ChannelId)
.HasMaxLength(100)
.HasComment("渠道号")
.UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.ConfigId).HasComment("配置值");
entity.Property(e => e.ConfigId).HasComment("配置Id");
entity.Property(e => e.ConfigType).HasComment("配置类型");
entity.Property(e => e.ConfigValue)
.HasComment("配置值")
@ -117,21 +165,19 @@ public partial class CloudGamingCBTContext : DbContext
.HasMaxLength(200)
.HasComment("国家 例:中国")
.UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.CreatTime)
entity.Property(e => e.CreateTime)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.Desc)
.HasComment("备注")
.UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.ExtJson).HasComment("扩展信息");
entity.Property(e => e.IsShow).HasComment("是否启用");
entity.Property(e => e.IsEnabled).HasComment("是否启用");
entity.Property(e => e.Name)
.HasMaxLength(200)
.HasComment("配置名称")
.UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.Plat)
.HasMaxLength(100)
.IsUnicode(false)
.HasMaxLength(10)
.HasComment("平台。安卓还是苹果")
.UseCollation("Chinese_PRC_CI_AS");
entity.Property(e => e.UpdateTime)
@ -223,6 +269,30 @@ public partial class CloudGamingCBTContext : DbContext
});
modelBuilder.Entity<T_Statistics_GameHour>(entity =>
{
entity.HasKey(e => e.Id).HasName("_copy_1_copy_1");
entity.ToTable(tb => tb.HasComment("游戏统计数据-每小时"));
entity.Property(e => e.Channel)
.HasMaxLength(10)
.HasComment("渠道号");
entity.Property(e => e.CreatedAt)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.LoginDate).HasComment("日期");
entity.Property(e => e.LoginDay).HasComment("天");
entity.Property(e => e.LoginHour).HasComment("精确到小时");
entity.Property(e => e.PlayGameCount).HasComment("用户玩游戏人数");
entity.Property(e => e.PlayGameTimeCount).HasComment("用户玩游戏时长");
entity.Property(e => e.StartGameCount).HasComment("启动游戏次数");
entity.Property(e => e.UpdatedAt)
.HasComment("修改时间")
.HasColumnType("datetime");
});
modelBuilder.Entity<T_Statistics_Order>(entity =>
{
entity.HasKey(e => e.Id).HasName("_copy_3");
@ -248,6 +318,32 @@ public partial class CloudGamingCBTContext : DbContext
});
modelBuilder.Entity<T_Statistics_OrderHour>(entity =>
{
entity.HasKey(e => e.Id).HasName("_copy_3_copy_1");
entity.ToTable(tb => tb.HasComment("订单统计表"));
entity.Property(e => e.Channel)
.HasMaxLength(10)
.HasComment("渠道号");
entity.Property(e => e.CreatedAt)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.IntendedOrderCount).HasComment("意向订单次数");
entity.Property(e => e.LoginDate).HasComment("日期");
entity.Property(e => e.LoginDay).HasComment("天");
entity.Property(e => e.LoginHour).HasComment("小时");
entity.Property(e => e.PaidOrders).HasComment("支付订单次数");
entity.Property(e => e.RechargeAmount)
.HasComment("支付订单金额")
.HasColumnType("decimal(18, 0)");
entity.Property(e => e.UpdatedAt)
.HasComment("修改时间")
.HasColumnType("datetime");
});
modelBuilder.Entity<T_Statistics_User>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_Statis__3214EC07FE2CF78F");
@ -271,6 +367,32 @@ public partial class CloudGamingCBTContext : DbContext
});
modelBuilder.Entity<T_Statistics_UserHour>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_Statis__3214EC07FE2CF78F_copy_1");
entity.ToTable(tb => tb.HasComment("用户统计表"));
entity.Property(e => e.Channel)
.HasMaxLength(10)
.HasComment("渠道号");
entity.Property(e => e.CreatedAt)
.HasComment("创建时间")
.HasColumnType("datetime");
entity.Property(e => e.LoginCount).HasComment("用户登录数");
entity.Property(e => e.LoginDate).HasComment("日期");
entity.Property(e => e.LoginDay).HasComment("天");
entity.Property(e => e.LoginHour)
.HasMaxLength(255)
.IsUnicode(false)
.HasComment("小时");
entity.Property(e => e.RegistrCount).HasComment("用户注册数");
entity.Property(e => e.UpdatedAt)
.HasComment("修改时间")
.HasColumnType("datetime");
});
modelBuilder.Entity<T_User_LoginDay_Log>(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_User_L__3214EC0786EBC26A");

View File

@ -0,0 +1,38 @@
using System;
namespace CloudGaming.GameModel.Db.Db_Ext;
/// <summary>
/// app渠道表
/// </summary>
public partial class T_App_Channel
{
public T_App_Channel() { }
public virtual int Id { get; set; }
/// <summary>
/// 渠道名称
/// </summary>
public virtual string Name { get; set; } = null!;
/// <summary>
/// 渠道号
/// </summary>
public virtual string ChannelId { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime CreateAt { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime UpdateAt { get; set; }
/// <summary>
/// 备注
/// </summary>
public virtual string? Desc { get; set; }
}

View File

@ -1,9 +1,9 @@
using System;
using System;
namespace CloudGaming.GameModel.Db.Db_Ext;
/// <summary>
/// App配置
/// App配置
/// </summary>
public partial class T_App_Config
{
@ -16,41 +16,46 @@ public partial class T_App_Config
/// </summary>
public virtual int ConfigType { get; set; }
/// <summary>
/// 配置值类型
/// </summary>
public virtual int ActionId { get; set; }
/// <summary>
/// 配置值
/// </summary>
public virtual int ConfigId { get; set; }
public virtual string? ConfigValue { get; set; }
/// <summary>
/// 是否启用
/// </summary>
public virtual bool IsShow { get; set; }
public virtual bool IsEnabled { get; set; }
/// <summary>
/// 配置名称
/// </summary>
public virtual string Name { get; set; } = null!;
/// <summary>
/// 备注
/// </summary>
public virtual string? Desc { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime? UpdateTime { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime? CreatTime { get; set; }
/// <summary>
/// 渠道号
/// </summary>
public virtual string? BossId { get; set; }
public virtual string? ChannelId { get; set; }
/// <summary>
/// 平台。安卓还是苹果
/// </summary>
public virtual string? Plat { get; set; }
/// <summary>
/// app版本号
/// </summary>
public virtual string? AppVersion { get; set; }
/// <summary>
/// 州 例:亚洲
/// </summary>
@ -62,17 +67,17 @@ public partial class T_App_Config
public virtual string? CountryName { get; set; }
/// <summary>
/// 配置值
/// 创建时间
/// </summary>
public virtual string? ConfigValue { get; set; }
public virtual DateTime CreateTime { get; set; }
/// <summary>
/// 配置名称
/// 修改时间
/// </summary>
public virtual string? Name { get; set; }
public virtual DateTime UpdateTime { get; set; }
/// <summary>
/// 扩展信息
/// 配置Id
/// </summary>
public virtual string? ExtJson { get; set; }
public virtual int ConfigId { get; set; }
}

View File

@ -0,0 +1,58 @@
using System;
namespace CloudGaming.GameModel.Db.Db_Ext;
/// <summary>
/// 游戏统计数据-每小时
/// </summary>
public partial class T_Statistics_GameHour
{
public T_Statistics_GameHour() { }
public virtual int Id { get; set; }
/// <summary>
/// 日期
/// </summary>
public virtual DateOnly LoginDate { get; set; }
/// <summary>
/// 天
/// </summary>
public virtual int LoginDay { get; set; }
/// <summary>
/// 精确到小时
/// </summary>
public virtual int LoginHour { get; set; }
/// <summary>
/// 用户玩游戏时长
/// </summary>
public virtual int PlayGameTimeCount { get; set; }
/// <summary>
/// 用户玩游戏人数
/// </summary>
public virtual int PlayGameCount { get; set; }
/// <summary>
/// 启动游戏次数
/// </summary>
public virtual int StartGameCount { get; set; }
/// <summary>
/// 渠道号
/// </summary>
public virtual string Channel { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime CreatedAt { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime UpdatedAt { get; set; }
}

View File

@ -0,0 +1,58 @@
using System;
namespace CloudGaming.GameModel.Db.Db_Ext;
/// <summary>
/// 订单统计表
/// </summary>
public partial class T_Statistics_OrderHour
{
public T_Statistics_OrderHour() { }
public virtual int Id { get; set; }
/// <summary>
/// 日期
/// </summary>
public virtual DateOnly LoginDate { get; set; }
/// <summary>
/// 天
/// </summary>
public virtual int LoginDay { get; set; }
/// <summary>
/// 小时
/// </summary>
public virtual int LoginHour { get; set; }
/// <summary>
/// 意向订单次数
/// </summary>
public virtual int IntendedOrderCount { get; set; }
/// <summary>
/// 支付订单次数
/// </summary>
public virtual int PaidOrders { get; set; }
/// <summary>
/// 支付订单金额
/// </summary>
public virtual decimal RechargeAmount { get; set; }
/// <summary>
/// 渠道号
/// </summary>
public virtual string Channel { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime CreatedAt { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime UpdatedAt { get; set; }
}

View File

@ -0,0 +1,53 @@
using System;
namespace CloudGaming.GameModel.Db.Db_Ext;
/// <summary>
/// 用户统计表
/// </summary>
public partial class T_Statistics_UserHour
{
public T_Statistics_UserHour() { }
public virtual int Id { get; set; }
/// <summary>
/// 日期
/// </summary>
public virtual DateOnly LoginDate { get; set; }
/// <summary>
/// 天
/// </summary>
public virtual int LoginDay { get; set; }
/// <summary>
/// 小时
/// </summary>
public virtual string LoginHour { get; set; } = null!;
/// <summary>
/// 用户登录数
/// </summary>
public virtual int LoginCount { get; set; }
/// <summary>
/// 用户注册数
/// </summary>
public virtual int RegistrCount { get; set; }
/// <summary>
/// 渠道号
/// </summary>
public virtual string Channel { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public virtual DateTime CreatedAt { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public virtual DateTime UpdatedAt { get; set; }
}

View File

@ -117,7 +117,7 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T
/// </summary>
protected int cacheTime;
protected RedisDataEntityCache(IDatabase database, object lockObj, int cacheTime = 36000) : base(lockObj, cacheTime)
protected RedisDataEntityCache(IDatabase database,int cacheTime = 36000) : base(new object(), cacheTime)
{
this.lockObj = lockObj;
this.cacheTime = cacheTime;
@ -133,7 +133,7 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T
/// <summary>
/// 数据
/// </summary>
public virtual List<T> DataList
public override List<T> DataList
{
get
{
@ -151,7 +151,14 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T
{
tempDataList = GetDataList();
database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
if (cacheTime == 0)
{
database.StringSet(key, tempDataList);
}
else
{
database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
}
}
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
database.KeyDeleteAsync($"lock:{key}").Wait();
@ -181,21 +188,30 @@ public abstract class RedisDataEntityCache<T> : CommonDataEntityCache<T> where T
public virtual bool ClearData()
{
lock (lockObj)
if (database.StringSetLock($"lock:{key}", "", 5))
{
database.KeyDelete(key);
_dataList = null;
database.KeyDeleteAsync($"lock:{key}").Wait();
}
return true;
}
public virtual void ReloadData()
{
lock (lockObj)
if (database.StringSetLock($"lock:{key}", "", 5))
{
var tempDataList = GetDataList();
database.StringSet(key, tempDataList, TimeSpan.FromMinutes(cacheTime));
if (cacheTime == 0)
{
database.StringSet(key, tempDataList);
}
else
{
database.StringSet(key, tempDataList, TimeSpan.FromSeconds(cacheTime));
}
_dataList = tempDataList;
database.KeyDeleteAsync($"lock:{key}").Wait();
}
}
}

View File

@ -182,7 +182,7 @@ namespace HuanMeng.DotNetCore.Redis
/// <param name="value"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public static bool StringSet(this IDatabase database, string key, object value, TimeSpan? expiry)
public static bool StringSet(this IDatabase database, string key, object value, TimeSpan? expiry = null)
{
return database.StringSet(key, (value == null ? "" : JsonConvert.SerializeObject(value)), expiry, When.Always);
}
@ -265,7 +265,7 @@ namespace HuanMeng.DotNetCore.Redis
/// <param name="server">Redis 服务器实例</param>
/// <param name="pattern">匹配的模式(支持通配符)</param>
/// <returns>匹配的键的数量</returns>
public static int ScanKeysCount(this IServer server, string pattern,int database = -1)
public static int ScanKeysCount(this IServer server, string pattern, int database = -1)
{
int count = 0;
long cursor = 0; // 游标,用于记录扫描进度