using Azure.Core; using Microsoft.Azure.Cosmos; using Azure.Messaging.ServiceBus; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models.Cosmos; namespace TEAMModelOS.SDK.Models.Service { public class LessonService { public static readonly DateTime dateTime1970 = new DateTime(1970, 1, 1).ToLocalTime(); public static Dictionary GetLessonCond(JsonElement request) { Dictionary dict = new Dictionary(); if (request.TryGetProperty("tmdid", out JsonElement tmdid)) { if (tmdid.ValueKind.Equals(JsonValueKind.String) && !string.IsNullOrWhiteSpace($"{tmdid}")) { dict.Add("tmdid", tmdid); } else if(tmdid.ValueKind.Equals(JsonValueKind.Array)) { dict.Add("tmdid", tmdid); } } if (request.TryGetProperty("courseId", out JsonElement courseId) && !string.IsNullOrWhiteSpace($"{courseId}")) { dict.Add("courseId", courseId); } if (request.TryGetProperty("courseIds", out JsonElement courseIds)) { dict.Add("courseId[*]", courseIds); } if (request.TryGetProperty("periodId", out JsonElement periodId) && !string.IsNullOrWhiteSpace($"{periodId}")) { dict.Add("periodId", periodId); } if (request.TryGetProperty("subjectId", out JsonElement subjectId)) { dict.Add("subjectId", subjectId); } if (request.TryGetProperty("groupIds", out JsonElement groupIds)) { dict.Add("groupIds[*]", groupIds); } if (request.TryGetProperty("grade", out JsonElement grade)) { dict.Add("grade[*]", grade); } if (request.TryGetProperty("category", out JsonElement category)) { dict.Add("category[*]", category); } if (request.TryGetProperty("doubleGray", out JsonElement doubleGray) && doubleGray.GetBoolean()) { dict.Add("=.tLevel", -1); dict.Add("=.pLevel", -1); //dict.Add(">=.tScore", 70); //dict.Add(">=.pScore", 70); } if (request.TryGetProperty("doubleGreen", out JsonElement doubleGreen) && doubleGreen.GetBoolean()) { dict.Add("=.tLevel", 2); dict.Add("=.pLevel", 2); //dict.Add(">=.tScore", 70); //dict.Add(">=.pScore", 70); } if (request.TryGetProperty("doubleRed", out JsonElement doubleRed) && doubleRed.GetBoolean()) { dict.Add("=.tLevel", 0); dict.Add("=.pLevel", 0); //dict.Add(">=.tScore", 70); //dict.Add(">=.pScore", 70); } if (request.TryGetProperty("quality", out JsonElement quality) && quality.GetBoolean()) { dict.Add(">=.discuss", 1); } if (request.TryGetProperty("excellent", out JsonElement excellent) && excellent.GetBoolean()) { dict.Add(">=.excellent", 1); } if (request.TryGetProperty("name", out JsonElement name) && !string.IsNullOrWhiteSpace($"{name}")) { dict.Add("$.name", name); } if (request.TryGetProperty("today", out JsonElement today) && today.GetBoolean()) { DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")); DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(1); double dayOf00_00_00 = (dateTimeA - dateTime1970).TotalMilliseconds; double day1Of00_00_00 = (dateTimeB - dateTime1970).TotalMilliseconds; dict.Add(">=.startTime", dayOf00_00_00); dict.Add("<.startTime", day1Of00_00_00); } if (request.TryGetProperty("week", out JsonElement week) && week.GetBoolean()) { // DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")); DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-7); double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); double dayB = (dateTimeB - dateTime1970).TotalMilliseconds; dict.Add("<=.startTime", now); dict.Add(">=.startTime", dayB); } //查询即将到期的且没有被清理的。 if (request.TryGetProperty("expire", out JsonElement expire) && expire.ValueKind.Equals(JsonValueKind.True)) { dict.Add(">.expire", 0); dict.Add("!=.status", 404); } //查询已经清理的 if (request.TryGetProperty("is404", out JsonElement is404) && is404.ValueKind.Equals(JsonValueKind.True)) { dict.Add("=.status", 404); } //只查有效的 if (request.TryGetProperty("isOk", out JsonElement isOk) && isOk.ValueKind.Equals(JsonValueKind.True)) { dict.Add("<=.expire", 0); dict.Add("!=.status", 404); } if (request.TryGetProperty("month", out JsonElement month) && month.GetBoolean()) { //DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")); DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-30); double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); double dayB = (dateTimeB - dateTime1970).TotalMilliseconds; dict.Add("<=.startTime", now); dict.Add(">=.startTime", dayB); } if (request.TryGetProperty("stime", out JsonElement stime) && !string.IsNullOrWhiteSpace($"{stime}")) { dict.Add(">=.startTime", stime); } if (request.TryGetProperty("etime", out JsonElement etime) && !string.IsNullOrWhiteSpace($"{etime}")) { dict.Add("<=.startTime", etime); } if (request.TryGetProperty("conds", out JsonElement conds) && conds.ValueKind.Equals(JsonValueKind.Array)) { List settingConds = conds.Deserialize>(); foreach (var item in settingConds) { dict.TryAdd($"{item.type}.{item.key}", item.val); //switch (item.type) //{ // case ">=": // dict.TryAdd($">=.{item.key}",item.val); // break; // case "<=": // dict.TryAdd($"<=.{item.key}", item.val); // break; //} } } return dict; } public static async void DoLessonStudentRecord(DingDing _dingding, SnowflakeId snowflakeId, LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid, Teacher teacher, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, LessonBase lessonBase,AzureRedisFactory _azureRedis, List pickupMemberIds, List taskDatas, List iRSDatas) { School schoolBase = null; Period period = null; try { int year = DateTimeOffset.UtcNow.Year; string hs = lessonBase?.report?.clientSummaryList.ToJsonString(); var clientSummaryLists = lessonBase?.report?.clientSummaryList?.Where(x => x.groupTaskCompleteCount != 0 || x.groupScore != 0 || x.score != 0 || x.interactScore != 0 || x.taskCompleteCount != 0); IEnumerable students = new List(); if (clientSummaryLists!=null && clientSummaryLists.Any()) { var ids = clientSummaryLists.Select(x => x.seatID); students = lessonBase.student.Where(x => ids.Contains(x.seatID)); } List studentsBase = new List(); var stuids = students.Where(x => x.type == 2); if (stuids.Any()) { stuids.ToList().ForEach(x => { x.school = string.IsNullOrWhiteSpace(x.school) ? school : x.school; }); var result= await client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetList($"select value c from c where c.id in ({string.Join(",",stuids.Select(d=>$"'{d.id}'"))})", $"Base-{school}"); if (result.list.Any()) { studentsBase = result.list; } } var groups = stuids.Where(z => !string.IsNullOrWhiteSpace(z.school)).GroupBy(x => x.school).Select(y => new { code = y.Key, list = y.ToList() }); List lessonStudentRecords = new List(); foreach (var group in groups) { string stusql = $"select value(c) from c where c.stuid in({string.Join(",", group.list.Select(x => $"'{x.id}'"))}) and c.school='{group.code}' and c.year={year}"; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIteratorSql(queryText: stusql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") })) { lessonStudentRecords.Add(item); } } var tmdids = students.Where(x => x.type == 1); if (tmdids.Any()) { string tmdsql = $"select value(c) from c where c.tmdid in({string.Join(",", tmdids.Select(x => $"'{x}'"))}) and c.year={year}"; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIteratorSql(queryText: tmdsql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") })) { lessonStudentRecords.Add(item); } } (Semester currSemester, int studyYear, DateTimeOffset currSemesterDate, DateTimeOffset date, DateTimeOffset nextSemester) dataSemester = new(null,-1, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow) ; if (!string.IsNullOrWhiteSpace(school)) { schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); period = schoolBase.period.Find(x => x.id.Equals($"{lessonRecord.periodId}")); if (period!= null) { dataSemester= SchoolService.GetSemester(period); } } List >> records = new List>>(); HashSet overallEducations = new HashSet(); // 互动次数,-1 表示没有进行互动。 与 0 不同 int interactCount = -1; //抢权作答的学生 List buzzClients= new List(); if (iRSDatas.IsNotEmpty()) { var keys = iRSDatas.Where(z => z.isBuzz==false).Select(v => v.clientAnswers).SelectMany(z => z.Keys).ToList(); var values = iRSDatas.Where(z => z.isBuzz==false).Select(v => v.clientAnswers).SelectMany(z => z.Values).ToList(); interactCount= keys.Count(); var bclients = iRSDatas.Where(z => z.buzzClients.IsNotEmpty()).SelectMany(v => v.buzzClients); if (bclients!=null && bclients.Count()>0) { foreach (var bc in bclients) { if (int.TryParse(bc, out int b)) { buzzClients.Add(b); } } } } //任务发布次数 ,-1 表示没有进行互动。 与 0 不同 int taskCount = -1; var groupNames = lessonBase.report.clientSummaryList.Where(z => !string.IsNullOrEmpty(z.groupName))?.Select(z=>z.groupName)?.ToHashSet()?.OrderBy(z=>z)?.ToList(); List groupTaskJoinCounts = new List(); if (groupNames.IsNotEmpty()) { groupTaskJoinCounts = groupNames.Select(z => new IdCodeCount { name=z, count = 0 }).ToList(); } //組任務發佈數 int groupTaskCount = -1; if (taskDatas.IsNotEmpty()) { taskCount=0; bool hasGroupTask = false; int groupTaksCountTemp = 0; foreach (var taskData in taskDatas) { var isGroupItem = taskData.clientWorks.FindAll(z => z.isGroupItem); if (isGroupItem.IsNotEmpty()) { //有组任务 hasGroupTask = true; groupTaksCountTemp += 1; foreach (var item in isGroupItem) { int groupIndex = 0; int.TryParse(item.groupID,out groupIndex); //由于分组下标从1 开始,则需要判断是否与分组数组大小一致,且提交了作品,则数量+1 if ( groupIndex>0 && item.blobFiles.IsNotEmpty() && groupIndex <= groupTaskJoinCounts.Count) { groupTaskJoinCounts[groupIndex-1].count+=1; } } } else { //没有组任务 taskCount += 1; } } if (hasGroupTask) { groupTaskCount=groupTaksCountTemp; } } foreach (var x in stuids) { var record = lessonStudentRecords.Find(l => l.stuid.Equals(x.id) && l.code.Equals($"StudentScoreRecord") && l.school.Equals(x.school)); ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID); int stuInteractCount = -1; int stuInteractJoin = 0; //获取挑人的互动 var ids= pickupMemberIds.FindAll(z => z==x.seatID); if (ids.IsNotEmpty()) { stuInteractJoin=ids.Count; if (interactCount>=0) { stuInteractCount=interactCount+ids.Count; } else { stuInteractCount=ids.Count; } } //获取抢权的互动 var buzIds = buzzClients.FindAll(z => z==x.seatID); if (buzIds.IsNotEmpty()) { stuInteractJoin=stuInteractJoin+buzIds.Count; if (stuInteractCount>-1) { stuInteractCount = stuInteractCount + buzIds.Count; } else { stuInteractCount = buzIds.Count; } } //普通作答的互动 if (record != null) { if (clientSummaryList != null) { var hasrecord = record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id)); if (hasrecord != null) { hasrecord.gscore = clientSummaryList.groupScore; hasrecord.pscore = clientSummaryList.score; hasrecord.tscore = clientSummaryList.interactScore; hasrecord.tmdid = teacher.id; hasrecord.school = school; hasrecord.scope = lessonRecord.scope; hasrecord.lessonId = lessonRecord.id; hasrecord.courseId = lessonRecord.courseId; hasrecord.periodId = lessonRecord.periodId; hasrecord.subjectId = lessonRecord.subjectId; hasrecord.time = lessonRecord.startTime; } else { record.lessonRecords.Add( new StudentLessonRecord { gscore = clientSummaryList.groupScore, pscore = clientSummaryList.score, tscore = clientSummaryList.interactScore, tmdid = teacher.id, school = school, scope = lessonRecord.scope, lessonId = lessonRecord.id, courseId = lessonRecord.courseId, periodId = lessonRecord.periodId, subjectId = lessonRecord.subjectId, time = lessonRecord.startTime } ); } } } else { record = new StudentScoreRecord { userType = Constant.ScopeStudent, id = $"{snowflakeId.NextId()}", year = year, stuid = x.id, school = x.school, code = $"StudentScoreRecord", pk = "StudentScoreRecord", ttl = -1, lessonRecords = new List { new StudentLessonRecord { gscore = clientSummaryList.groupScore, pscore = clientSummaryList.score, tscore = clientSummaryList.interactScore, tmdid = teacher.id, school = school, scope = lessonRecord.scope, lessonId = lessonRecord.id, courseId = lessonRecord.courseId, periodId = lessonRecord.periodId, subjectId = lessonRecord.subjectId, time= lessonRecord.startTime }} }; } record.userType = Constant.ScopeStudent; record.gscore = record.lessonRecords.Select(x => x.gscore).Sum(); record.pscore = record.lessonRecords.Select(x => x.pscore).Sum(); record.tscore = record.lessonRecords.Select(x => x.tscore).Sum(); if (dataSemester.currSemester != null && (clientSummaryList.groupScore>0 || clientSummaryList.score > 0 || clientSummaryList.interactScore > 0)) { string oid = $"{dataSemester.studyYear}-{dataSemester.currSemester.id}-{record.stuid}"; string ocode = $"OverallEducation-{school}"; var student = studentsBase.Find(stu => stu.id.Equals(x.id)); ResponseMessage response = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemStreamAsync(oid, new PartitionKey(ocode)); OverallEducation overallEducation = null; if (response.StatusCode != System.Net.HttpStatusCode.OK) { overallEducation = new OverallEducation { id =oid, code = $"OverallEducation-{school}", pk = "OverallEducation", ttl = -1, name = x.name, classId = student?.classId, schoolCode = $"{school}", semesterId = dataSemester.currSemester.id, year = dataSemester.studyYear, periodId = $"{period.id}", stuYear = student.year, studentId = x.id, lessonScore= new List { new StudentLessonRecord { gscore = clientSummaryList.groupScore, pscore = clientSummaryList.score, tscore = clientSummaryList.interactScore, tmdid = teacher.id, school = school, scope = lessonRecord.scope, lessonId = lessonRecord.id, courseId = lessonRecord.courseId, periodId = lessonRecord.periodId, subjectId = lessonRecord.subjectId, time= lessonRecord.startTime }} }; } else { overallEducation=JsonDocument.Parse(response.Content).RootElement.ToObject(); var hasrecord = overallEducation.lessonScore.Find(x => x.lessonId.Equals(lessonRecord.id)); if (hasrecord != null) { hasrecord.gscore = clientSummaryList.groupScore; hasrecord.pscore = clientSummaryList.score; hasrecord.tscore = clientSummaryList.interactScore; hasrecord.tmdid = teacher.id; hasrecord.school = school; hasrecord.scope = lessonRecord.scope; hasrecord.lessonId = lessonRecord.id; hasrecord.courseId = lessonRecord.courseId; hasrecord.periodId = lessonRecord.periodId; hasrecord.subjectId = lessonRecord.subjectId; hasrecord.time = lessonRecord.startTime; } else { overallEducation.lessonScore.Add( new StudentLessonRecord { gscore = clientSummaryList.groupScore, pscore = clientSummaryList.score, tscore = clientSummaryList.interactScore, tmdid = teacher.id, school = school, scope = lessonRecord.scope, lessonId = lessonRecord.id, courseId = lessonRecord.courseId, periodId = lessonRecord.periodId, subjectId = lessonRecord.subjectId, time = lessonRecord.startTime } ); } } overallEducations.Add(overallEducation); } records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code))); } foreach (var x in tmdids) { var record = lessonStudentRecords.Find(l => l.tmdid.Equals(x.id) && l.code.Equals($"StudentScoreRecord")); ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID); if (record != null) { if (clientSummaryList != null) { var hasrecord = record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id)); if (hasrecord != null) { hasrecord.gscore = clientSummaryList.groupScore; hasrecord.pscore = clientSummaryList.score; hasrecord.tscore = clientSummaryList.interactScore; hasrecord.tmdid = teacher.id; hasrecord.school = school; hasrecord.scope = lessonRecord.scope; hasrecord.lessonId = lessonRecord.id; hasrecord.courseId = lessonRecord.courseId; hasrecord.periodId = lessonRecord.periodId; hasrecord.subjectId = lessonRecord.subjectId; hasrecord.time = lessonRecord.startTime; } else { record.lessonRecords.Add( new StudentLessonRecord { gscore = clientSummaryList.groupScore, pscore = clientSummaryList.score, tscore = clientSummaryList.interactScore, tmdid = teacher.id, school = school, scope = lessonRecord.scope, lessonId = lessonRecord.id, courseId = lessonRecord.courseId, periodId = lessonRecord.periodId, subjectId = lessonRecord.subjectId, time = lessonRecord.startTime } ); } } } else { record = new StudentScoreRecord { userType = Constant.ScopeTmdUser, id = $"{snowflakeId.NextId()}", code = $"StudentScoreRecord", pk = "StudentScoreRecord", ttl = -1, year = year, tmdid = x.id, lessonRecords = new List { new StudentLessonRecord { gscore = clientSummaryList.groupScore, pscore = clientSummaryList.score, tscore = clientSummaryList.interactScore, tmdid = teacher.id, school = school, scope = lessonRecord.scope, lessonId = lessonRecord.id, courseId = lessonRecord.courseId, periodId = lessonRecord.periodId, subjectId = lessonRecord.subjectId, time=lessonRecord.startTime } } }; } record.userType = Constant.ScopeStudent; record.gscore = record.lessonRecords.Select(x => x.gscore).Sum(); record.pscore = record.lessonRecords.Select(x => x.pscore).Sum(); record.tscore = record.lessonRecords.Select(x => x.tscore).Sum(); records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code))); } if (records.Any()) { await Task.WhenAll(records); } if (overallEducations.Any()) { foreach (var item in overallEducations) { await client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(item, partitionKey: new PartitionKey(item.code)); string key = $"OverallEducation:{item.schoolCode}:{item.periodId}:{item.year}:{item.semesterId}:{item.classId}"; await _azureRedis.GetRedisClient(8).HashSetAsync(key, item.studentId, item.ToJsonString()); await _azureRedis.GetRedisClient(8).KeyExpireAsync(key,new TimeSpan(180 *24 ,0,0)); } } } catch (Exception ex) { await _dingding.SendBotMsg($"学生个人课例统计信息异常,{ex.Message}\n{ex.StackTrace},{lessonRecord?.ToJsonString()}{school}", GroupNames.醍摩豆服務運維群組); } } public static async void DoAutoDeleteSchoolLessonRecord(LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid, Teacher teacher, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, CoreAPIHttpService _coreAPIHttpService,DingDing _dingDing,AzureRedisFactory _azureRedis) { if (lessonRecord.scope.Equals("school")) { SchoolSetting setting = null; ResponseMessage schoolSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(school, new PartitionKey("SchoolSetting")); School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync(school, new PartitionKey("Base")); if (schoolSetting.StatusCode == System.Net.HttpStatusCode.OK) { setting = JsonDocument.Parse(schoolSetting.Content).RootElement.Deserialize(); if (setting.lessonSetting != null) { //两种状态都不属于,则默认未开启。 if (setting.lessonSetting.openAutoClean != 0 && setting.lessonSetting.openAutoClean != 1) { setting.lessonSetting.openAutoClean = 0; setting.lessonSetting.expireDays = Constant.school_lesson_expire; } else { //属于 要么开启1,要么关闭0 } } else { setting.lessonSetting = new LessonSetting() { openAutoClean = 0, expireDays = Constant.school_lesson_expire }; } } else { setting = new SchoolSetting() { lessonSetting = new LessonSetting { openAutoClean = 0, expireDays = Constant.school_lesson_expire } }; } int school_lesson_expire = 0; bool save = true; List msg = new List(); if (setting.lessonSetting.openAutoClean == 1) { if (setting.lessonSetting.conds.IsEmpty()) { save = false; } else { school_lesson_expire = setting.lessonSetting.expireDays; foreach (var item in setting.lessonSetting.conds) { switch (item.type) { case ">=": switch (item.key) { case "attendRate": if (!(lessonRecord.attendRate >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}"); } break; case "groupCount": if (!(lessonRecord.groupCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}"); } break; case "totalPoint": if (!(lessonRecord.totalPoint >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}"); } break; case "collateTaskCount": if (!(lessonRecord.collateTaskCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}"); } break; case "collateCount": if (!(lessonRecord.collateCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}"); } break; case "pushCount": if (!(lessonRecord.pushCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}"); } break; case "totalInteractPoint": if (!(lessonRecord.totalInteractPoint >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}"); } break; case "interactionCount": if (!(lessonRecord.interactionCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}"); } break; case "clientInteractionCount": if (!(lessonRecord.clientInteractionCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}"); } break; case "examQuizCount": if (!(lessonRecord.examQuizCount >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}"); } break; case "examPointRate": if (!(lessonRecord.examPointRate >= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}"); } break; } break; case "<=": switch (item.key) { case "attendRate": if (!(lessonRecord.attendRate <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}"); } break; case "groupCount": if (!(lessonRecord.groupCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}"); } break; case "totalPoint": if (!(lessonRecord.totalPoint <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}"); } break; case "collateTaskCount": if (!(lessonRecord.collateTaskCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}"); } break; case "collateCount": if (!(lessonRecord.collateCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}"); } break; case "pushCount": if (!(lessonRecord.pushCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}"); } break; case "totalInteractPoint": if (!(lessonRecord.totalInteractPoint <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}"); } break; case "interactionCount": if (!(lessonRecord.interactionCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}"); } break; case "clientInteractionCount": if (!(lessonRecord.clientInteractionCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}"); } break; case "examQuizCount": if (!(lessonRecord.examQuizCount <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}"); } break; case "examPointRate": if (!(lessonRecord.examPointRate <= item.val)) { save = false; msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}"); } break; } break; } } } } /* 注释start 2023.3.22,该段逻辑在开课的时候已经处理,详见ActiveTaskTopic. LessonRecordEvent create ,无论有没有开启setting.lessonSetting.openAutoClean 自动删除策略,只要空间不足都会对课例进行自动清理管理。 else { ///未设置openAutoClean=1时,则检查学校使用空间是否充足。 double usize = 0; int tsize = schoolBase.tsize; //schoolBase.tsize //計算學校或個人的使用空間 RedisValue redisValue = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", $"{schoolBase.id}"); if (redisValue.HasValue && long.TryParse(redisValue.ToString(), out var bsize)) { usize = Math.Round(bsize / 1073741824.0 - (tsize), 2, MidpointRounding.AwayFromZero); //1073741824 1G } else //如果檢測不到緩存,觸發刷新計算空間 { await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = "records", name = $"{schoolBase.id}" }, _serviceBus, _configuration, _azureRedis); } ///空间充足的情况保存。 if (schoolBase.size - usize > 0) { save = true; } else { save = false; school_lesson_expire = Constant.school_lesson_expire; } } 注释end 2023.3.22,该段逻辑在开课的时候已经处理,详见ActiveTaskTopic. LessonRecordEvent create ,无论有没有开启setting.lessonSetting.openAutoClean 自动删除策略,只要空间不足都会对课例进行自动清理管理。 */ if (!save && school_lesson_expire > 0) { // 1-时间戳,7-时间戳 Dictionary result = new Dictionary(); //暂定7天 var now = DateTimeOffset.UtcNow; //剩余3天的通知 //var day3= now.AddDays(school_lesson_expire - 3).ToUnixTimeMilliseconds(); //result.Add(3, day3); //剩余1天的通知 var day1 = now.AddDays(school_lesson_expire - (school_lesson_expire - 1)).ToUnixTimeMilliseconds(); result.Add(1, new ExpireTag { expire = day1, tag = "notification" }); //到期通知 //不到五点上传的课例,七天之后直接删除。 int addSecond = 0; if (now.Hour > 5) { // 到凌晨00点还差 (24 - now.Hour) *60 * 60 分钟,再加天数; addSecond = school_lesson_expire * 86400 + (24 - now.Hour) * 3600 - (now.Hour * 3600); //再加 00到05小时内的 随机秒数 Random rand = new Random(); int randInt = rand.Next(0, 18000); addSecond += randInt; } else { addSecond = school_lesson_expire * 24 * 60 * 60; } lessonRecord.expire = now.AddSeconds(addSecond).ToUnixTimeMilliseconds(); result.Add(school_lesson_expire, new ExpireTag { expire = lessonRecord.expire, tag = "delete" }); // result.Add(school_lesson_expire, lessonRecord.expire); string biz = "expire"; string expireTime = DateTimeOffset.FromUnixTimeMilliseconds(lessonRecord.expire).ToString("yyyy-MM-dd HH:mm:ss"); Teacher targetTeacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync($"{tmdid}", new PartitionKey($"Base")); _coreAPIHttpService.PushNotify(new List { new IdNameCode { id = targetTeacher.id, name = targetTeacher.name, code = targetTeacher.lang } }, "expire-school_lessonRecord", Constant.NotifyType_IES5_Course, new Dictionary { { "tmdid", teacher.id }, { "tmdname", teacher.name }, { "schoolName", schoolBase.name }, { "schoolId", $"{school}" },{ "lessonId",lessonRecord.id }, { "expireTime", expireTime },{ "lessonName",lessonRecord.name } }, $"{Environment.GetEnvironmentVariable("Option:Location")}", _configuration, _dingDing, ""); var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord"); List records = await table.FindListByDict(new Dictionary() { { "RowKey", lessonRecord.id } }); if (records.Count <= 0) { foreach (var item in result) { string PartitionKey = string.Format("{0}{1}{2}", lessonRecord.code, "-", $"expire-{item.Key}"); //课堂的id , //课堂的通知时间类型progress, 默认就会发送一条,到期前一天发送一条,最后已到期发送一条。 var message = new ServiceBusMessage(new { id = lessonRecord.id, progress = item.Key, code = lessonRecord.code, scope = lessonRecord.scope, school = lessonRecord.school, opt = "delete", expire = lessonRecord.expire, tmdid = tmdid, tmdname = teacher.name, name = lessonRecord.name, startTime = lessonRecord.startTime, tag = item.Value.tag }.ToJsonString()); message.ApplicationProperties.Add("name", "LessonRecordExpire"); long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value.expire)); ChangeRecord changeRecord = new ChangeRecord { RowKey = lessonRecord.id, PartitionKey = PartitionKey, sequenceNumber = start, msgId = message.MessageId }; await table.Save(changeRecord); } } } else { if (lessonRecord.expire > 0) { var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord"); List records = await table.FindListByDict(new Dictionary() { { "RowKey", lessonRecord.id } }); foreach (var record in records) { try { await table.DeleteSingle(record.PartitionKey, record.RowKey); await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber); } catch (Exception) { continue; } } } lessonRecord.save = 1; lessonRecord.expire = -1; } } } public record ExpireTag { public long expire { get; set; } public string tag { get; set; } } /// /// /// /// /// /// /// public static LessonDis DisLessonCount(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis) { //创建课堂的情况 if (oldRecord == null && newRecord != null) { lessonDis.record = 1; } //删除数据的情况 //不再对LessonCount进行减 else if (oldRecord != null && newRecord == null) { /*lessonDis.record = -1; //P分数量加减 if (oldRecord.pScore >= 70) { lessonDis.disPCount = -1; } //T分数量加减 if (oldRecord.tScore >= 70) { lessonDis.disTCount = -1; } if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70) { lessonDis.disTCount = -1; }*/ } //无效操作 else if (oldRecord == null && newRecord == null) { } //前后操作都有值,则表示更新 else { //P分数量加减 if (oldRecord.pScore >= 70) { if (newRecord.pScore < 70) { lessonDis.disPCount = -1; } } else { if (newRecord.pScore >= 70) { lessonDis.disPCount = 1; } } //T分数量加减 if (oldRecord.tScore >= 70) { if (newRecord.tScore < 70) { lessonDis.disTCount = -1; } } else { if (newRecord.tScore >= 70) { lessonDis.disTCount = 1; } } //双绿灯数量 if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70) { if (newRecord.tScore < 70 || newRecord.pScore < 70) { lessonDis.disDCount = -1; } } else { if (newRecord.tScore >= 70 && newRecord.pScore >= 70) { lessonDis.disDCount = 1; } } } return lessonDis; } public static LessonDis DisLessonCount_2(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis) { //创建课堂的情况 if (oldRecord == null && newRecord != null) { lessonDis.record = 1; //P分数量加减 if (newRecord.pScore >= 70) { lessonDis.disPCount = 1; } //T分数量加减 if (newRecord.tScore >= 70) { lessonDis.disTCount = 1; } //双绿灯数量 if (newRecord.tScore >= 70 && newRecord.pScore >= 70) { lessonDis.disDCount = 1; } } return lessonDis; } public static async Task FixLessonCount(CosmosClient client, DingDing _dingDing, LessonRecord record, LessonRecord oldRecord, LessonDis lessonDis) { LessonRecord data = null; try { if (record != null && oldRecord == null) { data = record; } if (record == null && oldRecord != null) { data = oldRecord; } if (record != null && oldRecord != null) { data = record; } int day = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).DayOfYear; int year = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).Year; int days = DateTimeHelper.getDays(year); //int years = DateTimeOffset.UtcNow.DayOfYear; string tbname = string.Empty; string code = string.Empty; if (data.groupIds.Any()) { if (data.scope != null && data.scope.Equals("school")) { if (string.IsNullOrEmpty(data.periodId)) { code = $"LessonCount-{data.school}-{year}"; tbname = "School"; } else { code = $"LessonCount-{data.school}-{year}-{data.periodId}"; tbname = "School"; } } else { code = $"LessonCount-{year}"; tbname = "Teacher"; } var response = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(data.tmdid.ToString(), new PartitionKey(code)); if (response.StatusCode == System.Net.HttpStatusCode.OK) { using var json = await JsonDocument.ParseAsync(response.Content); LessonCount count = json.ToObject(); count.tCount[day - 1] += lessonDis.disTCount; count.pCount[day - 1] += lessonDis.disPCount; count.ptCount[day - 1] += lessonDis.disDCount; count.beginCount[day - 1] += lessonDis.record; await client.GetContainer("TEAMModelOS", tbname).ReplaceItemAsync(count, count.id, new PartitionKey(code)); } else { LessonCount count = new() { id = data.tmdid, code = code, ttl = -1 }; double[] da = new double[days]; List list = new(da); List listT = new(da); List listP = new(da); List listPT = new(da); list[day - 1] += lessonDis.record; listT[day - 1] += lessonDis.disTCount; listP[day - 1] += lessonDis.disPCount; listPT[day - 1] += lessonDis.disDCount; count.beginCount.AddRange(list); count.tCount.AddRange(listT); count.pCount.AddRange(listP); count.ptCount.AddRange(listPT); //count.courseIds.Add(data.courseId); await client.GetContainer("TEAMModelOS", tbname).CreateItemAsync(count, new PartitionKey(code)); } } } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-LessonCount-FixLessonCount\n{ex.Message}\n{ex.StackTrace}{data.ToJsonString()}", GroupNames.醍摩豆服務運維群組); } } } }