using Microsoft.Azure.Cosmos;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
using TEAMModelOS.SDK.Models.Cosmos.BI.BITable;
namespace TEAMModelOS.SDK.Models.Service.BI
{
public class BILeesonService
{
///
/// 通过时间戳保存开课记录和课例记录统计
/// 统计数据存储在CosmosDB表中
///
/// cosmosDB连接
/// redis
/// 错误消息发送
/// 13位时间戳
/// 数量
/// 类型:0 开课记录 1 课例记录
/// 学校编码
///
public static async Task SetCosmosDBStats(CosmosClient cosmosClient, AzureRedisFactory _azureRedis, DingDing _dingDing, long unix, int num = 1, int type = 0, string schoolId = null)
{
try
{
DateTimeOffset dateTime = DateTimeOffset.FromUnixTimeMilliseconds(unix);
int year, month, day, hour, days;
year = dateTime.Year;
month = dateTime.Month;
day = dateTime.Day;
hour = dateTime.Hour;
days = dateTime.DayOfYear;
var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
DateTime expireDay = DateTime.UtcNow.AddDays(8); //8天后到期
DateTime expireYear = DateTime.UtcNow.AddDays(396); //一年后到期
var redisClient = _azureRedis.GetRedisClient(8);
string LessType = "Open";
if (type == 1)
LessType = "Lesson";
await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
var expDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{dateDay}");
if (expDay == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{dateDay}", expireDay); //设置八天后到期
var expYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{year}");
if (expYear == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{year}", expireYear); //设置一年后到期
//保存当天的统计 小时
var dayCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{dateDay}");
if (dayCnt != null && dayCnt.Length > 0)
{
double[] daHour = new double[23];
foreach (var item in dayCnt)
{
double val = ((double)item.Score);
int key = ((int)item.Element);
daHour[key] = val;
}
List lessHours = new(daHour);
var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{dateDay}", new PartitionKey("LessonHour"));
if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
{
using var json = await JsonDocument.ParseAsync(lessRes.Content);
LessonStats lessonStats = json.ToObject();
lessonStats.code = "LessonHour";
lessonStats.pk = "LessonHour";
if (type == 1)
lessonStats.lesson = lessHours;
else
lessonStats.open = lessHours;
await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(lessonStats, lessonStats.id, new PartitionKey("LessonHour"));
}
else
{
LessonStats lessonStats = new();
lessonStats.id = $"{dateDay}";
lessonStats.code = "LessonHour";
lessonStats.pk = "LessonHour";
if (type == 1)
lessonStats.lesson = lessHours;
else
lessonStats.open = lessHours;
await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync(lessonStats, new PartitionKey("LessonHour"));
}
}
//保一年的统计 天
var yearCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{year}");
if (yearCnt != null && yearCnt.Length > 0)
{
double[] daYear = new double[yearDays];
foreach (var item in yearCnt)
{
double val = ((double)item.Score);
int key = ((int)item.Element);
daYear[key] = val;
}
List lessYear = new(daYear);
var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{year}", new PartitionKey("LessonYear"));
if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
{
using var json = await JsonDocument.ParseAsync(lessRes.Content);
LessonStats lessonYear = json.ToObject();
lessonYear.code = "LessonYear";
lessonYear.pk = "LessonYear";
if (type == 1)
lessonYear.lesson = lessYear;
else
lessonYear.open = lessYear;
await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(lessonYear, lessonYear.id, new PartitionKey("LessonYear"));
}
else
{
LessonStats lessonYear = new();
lessonYear.id = $"{year}";
lessonYear.code = "LessonYear";
lessonYear.pk = "LessonYear";
if (type == 1)
lessonYear.lesson = lessYear;
else
lessonYear.open = lessYear;
await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync(lessonYear, new PartitionKey("LessonYear"));
}
}
if (!string.IsNullOrEmpty(schoolId))
{
await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
var scExpDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
if (scExpDay == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", expireDay); //设置八天后到期
var scExpYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{year}");
if (scExpYear == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", expireYear); //设置一年后到期
//保存当天的统计 小时
var dayScCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
if (dayScCnt != null && dayScCnt.Length > 0)
{
double[] daHour = new double[23];
foreach (var item in dayScCnt)
{
double val = ((double)item.Score);
int key = ((int)item.Element);
daHour[key] = val;
}
List lessHours = new(daHour);
var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{dateDay}", new PartitionKey($"LessonHour-{schoolId}"));
if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
{
using var json = await JsonDocument.ParseAsync(lessRes.Content);
LessonStats lessonStats = json.ToObject();
lessonStats.code = $"LessonHour-{schoolId}";
lessonStats.pk = "LessonHour";
if (type == 1)
lessonStats.lesson = lessHours;
else
lessonStats.open = lessHours;
await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(lessonStats, lessonStats.id, new PartitionKey($"LessonHour-{schoolId}"));
}
else
{
LessonStats lessonStats = new();
lessonStats.id = $"{dateDay}";
lessonStats.code = $"LessonHour-{schoolId}";
lessonStats.pk = "LessonHour";
if (type == 1)
lessonStats.lesson = lessHours;
else
lessonStats.open = lessHours;
await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync(lessonStats, new PartitionKey($"LessonHour-{schoolId}"));
}
}
//保一年的统计 天
var scYearCnt = redisClient.SortedSetRangeByScoreWithScores($"BILesson:{schoolId}:{LessType}:{year}");
if (scYearCnt != null && scYearCnt.Length > 0)
{
double[] daYear = new double[yearDays];
foreach (var item in scYearCnt)
{
double val = ((double)item.Score);
int key = ((int)item.Element);
daYear[key] = val;
}
List lessYear = new(daYear);
var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{year}", new PartitionKey($"LessonYear-{schoolId}"));
if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
{
using var json = await JsonDocument.ParseAsync(lessRes.Content);
LessonStats lessonYear = json.ToObject();
lessonYear.code = $"LessonYear-{schoolId}";
lessonYear.pk = "LessonYear";
if (type == 1)
lessonYear.lesson = lessYear;
else
lessonYear.open = lessYear;
await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(lessonYear, lessonYear.id, new PartitionKey($"LessonYear-{schoolId}"));
}
else
{
LessonStats lessonYear = new();
lessonYear.id = $"{year}";
lessonYear.code = $"LessonYear-{schoolId}";
lessonYear.pk = "LessonYear";
if (type == 1)
lessonYear.lesson = lessYear;
else
lessonYear.open = lessYear;
await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync(lessonYear, new PartitionKey($"LessonYear-{schoolId}"));
}
}
}
}
catch (Exception ex)
{
await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-SetBICosmosDBStats 课例统计异常 {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
}
}
///
/// 通过时间戳保存开课记录和课例记录统计
/// 统计数据存储在table表中
///
/// table连接池
/// redis连接池
/// 错误消息发送
/// 13位时间戳
/// 数量
/// 类型:0 开课记录 1 课例记录
/// 范围(默认学校范围):学校 school 个人 private
/// 学校编码
///
public static async Task SetTableStats(AzureStorageFactory _azureStorage, AzureRedisFactory _azureRedis, DingDing _dingDing, long unix, int num = 1, int type = 0,string scope = "private", string schoolId = null)
{
try
{
//SemaphoreSlim slimlock = new(1, 1); //对可同时访问资源或资源池的线程数加以限制 结束
//await slimlock.WaitAsync();
Monitor.TryEnter(unix); //锁对象
DateTimeOffset dateTime = DateTimeOffset.FromUnixTimeMilliseconds(unix);
int year, month, day, hour, days;
year = dateTime.Year;
month = dateTime.Month;
day = dateTime.Day;
hour = dateTime.Hour;
days = dateTime.DayOfYear;
var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
var table = _azureStorage.GetCloudTableClient().GetTableReference("BIStats");
var redisClient = _azureRedis.GetRedisClient(8);
DateTime expireDay = DateTime.UtcNow.AddDays(8); //8天后到期
DateTime expireYear = DateTime.UtcNow.AddDays(396); //一年后到期
////保存当天的统计 小时
//SortedSetEntry[] dayCnt = null;
////保一年的统计 天
//SortedSetEntry[] yearCnt = null;
string LessType = "Open";
if (type == 1)
LessType = "Lesson";
try
{
await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
var expDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{dateDay}");
if (expDay == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{dateDay}", expireDay); //设置八天后到期
var expYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{year}");
if (expYear == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{year}", expireYear); //设置一年后到期
////保存当天的统计 小时
//dayCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{dateDay}");
////保一年的统计 天
//yearCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{year}");
}
catch { }
double[] daHour = new double[23];
daHour[hour] = num;
string hourStats = string.Join(',', daHour);
double[] daYear = new double[yearDays];
daYear[hour] = num;
string yearStats = string.Join(',', daYear);
LessStats lessHour = table.Get("LessonHour", $"{dateDay}");
if (lessHour != null)
{
if (type == 1)
{
if (lessHour.lesson != null)
{
double[] tempLess = Array.ConvertAll(lessHour.lesson.Split(','), s => double.Parse(s));
tempLess[hour] = tempLess[hour] + num;
string strLess = string.Join(',', tempLess);
lessHour.lesson = strLess;
}
else
lessHour.lesson = hourStats;
}
else
{
if (lessHour.open != null)
{
double[] tempOpen = Array.ConvertAll(lessHour.open.Split(','), s => double.Parse(s));
tempOpen[hour] = tempOpen[hour] + num;
string sOpen = string.Join(',', tempOpen);
lessHour.open = sOpen;
}
else
lessHour.open = hourStats;
}
}
else
{
lessHour = new() { PartitionKey = "LessonHour", RowKey = $"{dateDay}" };
if (type == 1)
lessHour.lesson = hourStats;
else
lessHour.open = hourStats;
}
await table.SaveOrUpdate(lessHour);
LessStats lessYear = table.Get("LessonYear", $"{year}");
if (lessYear != null)
{
if (type == 1)
{
if (lessYear.lesson != null)
{
double[] tempLess = Array.ConvertAll(lessYear.lesson.Split(','), s => double.Parse(s));
tempLess[days] = tempLess[days] + num;
string sLess = string.Join(',', tempLess);
lessYear.lesson = sLess;
}
else
lessYear.lesson = yearStats;
}
else
{
if (lessYear.open != null)
{
double[] tempOpen = Array.ConvertAll(lessYear.open.Split(','), s => double.Parse(s));
tempOpen[days] = tempOpen[days] + num;
string sOpen = string.Join(',', tempOpen);
lessYear.open = sOpen;
}
else
lessYear.open = yearStats;
}
}
else
{
lessYear = new() { PartitionKey = "LessonYear", RowKey = $"{year}" };
if (type == 1)
lessYear.lesson = yearStats;
else
lessYear.open = yearStats;
}
try
{
await table.SaveOrUpdate(lessYear);
}
catch { }
//保存学校课例数据
if (!string.IsNullOrEmpty(schoolId) && scope.Equals("school"))
{
////保存学校当天的统计 小时
//SortedSetEntry[] dayScCnt = null;
////保学校一年的统计 天
//SortedSetEntry[] scYearCnt = null;
try
{
await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
var scExpDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
if (scExpDay == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", expireDay); //设置八天后到期
var scExpYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{year}");
if (scExpYear == null)
await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", expireYear); //设置一年后到期
////保存学校当天的统计 小时
//dayScCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
////保学校一年的统计 天
//scYearCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:{schoolId}:{LessType}:{year}");
}catch { }
double[] daScHour = new double[23];
daScHour[hour] = num;
string hourScStats = string.Join(',', daScHour);
double[] daScYear = new double[yearDays];
daScYear[hour] = num;
string strYearSc = string.Join(',', daScYear);
LessStats lessScHour = table.Get("LessonHour", $"{dateDay}-{schoolId}");
if (lessScHour != null)
{
if (type == 1)
{
if (lessScHour.lesson != null)
{
double[] tempLess = Array.ConvertAll(lessScHour.lesson.Split(','), s => double.Parse(s));
tempLess[hour] = tempLess[hour] + num;
string strLess = string.Join(',', tempLess);
lessScHour.lesson = strLess;
}
else
lessScHour.lesson = hourScStats;
}
else
{
if (lessScHour.open != null)
{
double[] tempOpen = Array.ConvertAll(lessScHour.open.Split(','), s => double.Parse(s));
tempOpen[hour] = tempOpen[hour] + num;
string sOpen = string.Join(',', tempOpen);
lessScHour.open = sOpen;
}
else
lessScHour.open = hourScStats;
}
}
else
{
lessScHour = new() { PartitionKey = "LessonHour", RowKey = $"{dateDay}-{schoolId}" };
if (type == 1)
lessScHour.lesson = hourScStats;
else
lessScHour.open = hourScStats;
}
try
{
await table.SaveOrUpdate(lessScHour);
}
catch { }
LessStats lessScYear = table.Get("LessonYear", $"{year}-{schoolId}");
if (lessScYear != null)
{
if (type == 1)
{
if (lessScYear.lesson != null)
{
double[] tempLess = Array.ConvertAll(lessScYear.lesson.Split(','), s => double.Parse(s));
tempLess[days] = tempLess[days] + num;
string sLess = string.Join(',', tempLess);
lessScYear.lesson = sLess;
}
else
lessScYear.lesson = strYearSc;
}
else
{
if (lessScYear.open != null)
{
double[] tempOpen = Array.ConvertAll(lessScYear.open.Split(','), s => double.Parse(s));
tempOpen[days] = tempOpen[days] + num;
string sOpen = string.Join(',', tempOpen);
lessScYear.open = sOpen;
}
else
lessScYear.open = strYearSc;
}
}
else
{
lessScYear = new() { PartitionKey = "LessonYear", RowKey = $"{year}" };
if (type == 1)
lessScYear.lesson = strYearSc;
else
lessScYear.open = strYearSc;
}
try
{
await table.SaveOrUpdate(lessScYear);
}
catch { }
//if (dayScCnt != null && dayScCnt.Length > 0)
//{
// double[] daHourSc = new double[23];
// foreach (var item in dayScCnt)
// {
// double val = ((double)item.Score);
// int key = ((int)item.Element);
// daHourSc[key] = val;
// }
// string hoursStatsSc = string.Join(",", daHourSc);
// LessStats lessStatsSc = table.Get("LessonHour", $"{dateDay}-{schoolId}");
// if (lessStatsSc != null)
// {
// if (type == 1)
// lessStatsSc.lesson = hoursStatsSc;
// else
// lessStatsSc.open = hoursStatsSc;
// }
// else
// {
// lessStatsSc = new() { PartitionKey = "LessonHour", RowKey = $"{dateDay}-{schoolId}" };
// if (type == 1)
// lessStatsSc.lesson = hoursStatsSc;
// else
// lessStatsSc.open = hoursStatsSc;
// lessStatsSc.time = dateDay;
// lessStatsSc.school = schoolId;
// }
// try
// {
// await table.SaveOrUpdate(lessStatsSc);
// }
// catch { }
//}
//if (scYearCnt != null && scYearCnt.Length > 0)
//{
// double[] daYearSc = new double[yearDays];
// foreach (var item in scYearCnt)
// {
// double val = ((double)item.Score);
// int key = ((int)item.Element);
// daYearSc[key] = val;
// }
// string tempStatsSc = string.Join(",", daYearSc);
// LessStats lessStatsSc = table.Get("LessonYear", $"{year}-{schoolId}");
// if (lessStatsSc != null)
// {
// if (type == 1)
// lessStatsSc.lesson = tempStatsSc;
// else
// lessStatsSc.open = tempStatsSc;
// }
// else
// {
// lessStatsSc = new() { PartitionKey = "LessonYear", RowKey = $"{year}-{schoolId}" };
// if (type == 1)
// lessStatsSc.lesson = tempStatsSc;
// else
// lessStatsSc.open = tempStatsSc;
// lessStatsSc.time = $"{year}";
// lessStatsSc.school = schoolId;
// }
// try
// {
// await table.SaveOrUpdate(lessStatsSc);
// }
// catch { }
//}
}
Monitor.Enter(unix); //锁对象 结束
//slimlock.Release(); // 对可同时访问资源或资源池的线程数加以限制 结束
}
catch (Exception ex)
{
await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-SetBITableStats BI记录课例统计数据异常!参数:{unix}|{num}|{type}|{scope}|{schoolId} ;错误信息:{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
}
}
}
}