using Azure.Cosmos; using Azure.Messaging.ServiceBus; using Microsoft.Azure.Documents; 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.Helper.Common.CollectionHelper; using TEAMModelOS.SDK.Models; using TEAMModelOS.SDK.Models.Cosmos; using TEAMModelOS.SDK.Models.Cosmos.Common; namespace TEAMModelFunction { public class TriggerExam { public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing, CosmosClient client, Document input ,string code,long stime,long etime, string school) { ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync(input.Id, new Azure.Cosmos.PartitionKey($"{code}")); List examClassResults = new List(); List examSubjects = new List(); if (info.scope.Equals("teacher", StringComparison.OrdinalIgnoreCase) || info.scope.Equals("private", StringComparison.OrdinalIgnoreCase)) { await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{info.creatorId}") })) { using var json = await JsonDocument.ParseAsync(item.ContentStream); if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0) { foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray()) { examClassResults.Add(obj.ToObject()); } } } } else { await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{school}") })) { using var json = await JsonDocument.ParseAsync(item.ContentStream); if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0) { foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray()) { examClassResults.Add(obj.ToObject()); } } } } List records = await _azureStorage.FindListByDict(new Dictionary() { { "RowKey", input.Id }, { "PartitionKey", info.progress } }); //处理科目信息 List sub = new List(); foreach (ExamSubject subject in info.subjects) { sub.Add(subject.id); } //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}")); switch (info.progress) { case "pending": var message = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString()); message.ApplicationProperties.Add("name", "Exam"); if (records.Count > 0) { await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber); long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime)); records[0].sequenceNumber = start; await _azureStorage.SaveOrUpdate(records[0]); //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}")); } else { long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime)); ChangeRecord changeRecord = new ChangeRecord { RowKey = input.Id, PartitionKey = "pending", sequenceNumber = start, msgId = message.MessageId }; await _azureStorage.Save(changeRecord); //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}")); } break; case "going": ActivityData data; if (info.scope == "school") { data = new ActivityData { id = info.id, code = $"Activity-{info.school}", type = "exam", name = info.name, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, classes = info.classes.IsNotEmpty() ? info.classes : new List { "" }, tmdids = new List { "" }, progress = "going", subjects = sub }; await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync(data, new Azure.Cosmos.PartitionKey(data.code)); } else if (info.scope == "private") { data = new ActivityData { id = info.id, code = $"Activity-Common", type = "exam", name = info.name, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, progress = "going", classes = info.classes.IsNotEmpty() ? info.classes : new List { "" }, tmdids = new List { "" }, subjects = sub }; await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync(data, new Azure.Cosmos.PartitionKey(data.code)); } (List tmdids, List students) = await TriggerStuActivity.GetStuList(client, info.classes, info.school); List stuActivities = new List(); List tmdActivities = new List(); if (tmdids.IsNotEmpty()) { tmdids.ForEach(x => { tmdActivities.Add(new StuActivity { pk = "Activity", id = info.id, code = $"Activity-{x}", type = "survey", name = info.name, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, school = info.school, creatorId = info.creatorId, subjects = new List { "" } }); }); } if (students.IsNotEmpty()) { students.ForEach(x => { stuActivities.Add(new StuActivity { pk = "Activity", id = info.id, code = $"Activity-{info.school}-{x}", type = "survey", name = info.name, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, school = info.school, creatorId = info.creatorId, subjects = new List { "" } }); }); } await TriggerStuActivity.SaveStuActivity(client, stuActivities, tmdActivities); if (examClassResults.Count == 0) { foreach (string cla in info.classes) { int m = 0; foreach (ExamSubject subject in info.subjects) { string classCode = ""; if (string.IsNullOrEmpty(info.school) || !info.scope.Equals("school",StringComparison.OrdinalIgnoreCase)) { classCode = "ExamClassResult-" + info.creatorId; } else { classCode = "ExamClassResult-" + info.school; } ExamClassResult result = new ExamClassResult { code = classCode, examId = info.id, id = Guid.NewGuid().ToString(), subjectId = subject.id, year = info.year, scope = info.scope }; result.info.id = cla; List ans = new List(); List ansPoint = new List(); List ids = new List(); foreach (double p in info.papers[m].point) { //ans.Add(new List()); ansPoint.Add(-1); } var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}")); if (sresponse.Status == 200) { using var json = await JsonDocument.ParseAsync(sresponse.ContentStream); Class classroom = json.ToObject(); //result.info.id = classroom.id; result.info.name = classroom.name; result.gradeId = classroom.gradeId; //处理班级人数 await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{classroom.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{info.school}") })) { using var json_stu = await JsonDocument.ParseAsync(item.ContentStream); if (json_stu.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0) { var accounts = json_stu.RootElement.GetProperty("Documents").EnumerateArray(); while (accounts.MoveNext()) { JsonElement account = accounts.Current; ids.Add(account.GetProperty("id").GetString()); } } } } if (info.scope.Equals("private", StringComparison.OrdinalIgnoreCase)) { var stuResponse = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"StuList")); if (stuResponse.Status == 200) { using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream); StuList stuList = json.ToObject(); //result.info.id = stuList.id; result.info.name = stuList.name; //处理发布对象为自选名单(个人) foreach (Students students in stuList.students) { ids.Add(students.id); } if (stuList.tmids.Count > 0) { foreach (string tid in stuList.tmids) { ids.Add(tid); } } } } else { var stuResponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"StuList-{info.school}")); if (stuResponse.Status == 200) { using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream); StuList stuList = json.ToObject(); //result.info.id = stuList.id; result.info.name = stuList.name; //处理发布对象为自选名单(校本) foreach (Students students in stuList.students) { ids.Add(students.id); } } } foreach (string stu in ids) { result.studentIds.Add(stu); result.studentAnswers.Add(ans); result.studentScores.Add(ansPoint); result.sum.Add(0); } //result.progress = info.progress; result.school = info.school; m++; await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}")); } } // 发送信息通知 var messageEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString()); messageEnd.ApplicationProperties.Add("name", "Exam"); if (records.Count > 0) { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime)); await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber); records[0].sequenceNumber = end; await _azureStorage.SaveOrUpdate(records[0]); //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}")); } else { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime)); ChangeRecord changeRecord = new ChangeRecord { RowKey = input.Id, PartitionKey = "going", sequenceNumber = end, msgId = messageEnd.MessageId }; await _azureStorage.Save(changeRecord); //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}")); } } else { //处理单科结算时科目与试卷信息匹配的问题 int gno = 0; foreach (ExamSubject subject in info.subjects) { if (subject.classCount == info.classes.Count) { await createClassResultAsync(info, examClassResults, subject, gno,_azureCosmos); } gno++; } } break; case "finish": int fno = 0; foreach (ExamSubject subject in info.subjects) { await createClassResultAsync(info, examClassResults, subject, fno, _azureCosmos); fno++; } //计算单次考试简易统计信息 List examResults = new List(); await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator( queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}") })) { examResults.Add(item); } //记录某次考试所有学生得分总分 double score = 0; double allScore = 0; int stuCount = 0; List losStu = new List(); //先与第一个值取并集 if (examResults.Count >0 ) { losStu.Union(examResults[0].lostStus); foreach (ExamResult examResult in examResults) { if (info.id == examResult.examId) { foreach (List sc in examResult.studentScores) { score += sc.Sum(); } stuCount = examResult.studentIds.Count; } //取交集 losStu = losStu.Intersect(examResult.lostStus).ToList(); } } double ascore = stuCount > 0 ? Math.Round(score * 1.0 / stuCount, 2) : 0; foreach (PaperSimple simple in info.papers) { allScore += simple.point.Sum(); } info.sRate = allScore > 0 ? Math.Round(ascore / allScore * 100,2) : 0; info.lostStu = losStu; await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new Azure.Cosmos.PartitionKey(info.code)); //ActivityData data; if (info.scope == "school") { data = new ActivityData { id = info.id, code = $"Activity-{info.school}", type = "exam", name = info.name, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, progress = "finish", classes = info.classes.IsNotEmpty() ? info.classes : new List { "" }, tmdids = new List { "" }, subjects = sub }; await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(data, info.id, new Azure.Cosmos.PartitionKey(data.code)); } else if (info.scope == "private") { data = new ActivityData { id = info.id, code = $"Activity-Common", type = "exam", name = info.name, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, progress = "finish", classes = info.classes.IsNotEmpty() ? info.classes : new List { "" }, tmdids = new List { "" }, subjects = sub }; await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(data, info.id, new Azure.Cosmos.PartitionKey(data.code)); } break; } } public static async Task createClassResultAsync(ExamInfo info, List examClassResults, ExamSubject subject, int no, AzureCosmosFactory _azureCosmos) { //保证试卷信息与科目信息同步 ExamResult result = new ExamResult(); //人数总和 int Count = 0; int m = 0; double score = 0; double allScore = info.papers[no].point.Sum(); List classRanges = new List(); List lostStu = new List(); List csRate = new List(); foreach (ExamClassResult classResult in examClassResults) { double classSrate = 0; if (classResult.subjectId.Equals(subject.id)) { //记录缺考学生索引位置 int index = 0; foreach (List scores in classResult.studentScores) { List newScores = new List(); int count = 0; foreach (double sc in scores) { newScores.Add(sc > -1 ? sc : 0); if(sc == -1) { count++; } } if (count == scores.Count) { lostStu.Add(classResult.studentIds[index]); //mcount++; } classSrate += newScores.Sum(); score += newScores.Sum(); result.studentScores.Add(newScores); index++; } //处理班级信息 ClassRange range = new ClassRange(); range.id = classResult.info.id; range.name = classResult.info.name; range.gradeId = classResult.gradeId; List ran = new List(); int stuCount = classResult.studentIds.Count; Count += stuCount; if (m == 0) { ran.Add(0); ran.Add(stuCount - 1); } else { ran.Add(Count - stuCount); ran.Add(Count - 1); } m++; range.range = ran; classRanges.Add(range); //处理学生ID foreach (string id in classResult.studentIds) { result.studentIds.Add(id); } csRate.Add(result.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore); } } result.csRate = csRate; result.lostStus = lostStu; result.sRate =result.studentIds.Count> 0 ? Math.Round(score *1.0 / result.studentIds.Count ,2 ): 0 / allScore; result.classes = classRanges; result.code = "ExamResult-" + info.id; result.school = info.school; result.id = subject.id; result.examId = info.id; result.subjectId = subject.id; result.year = info.year; result.paper = info.papers[no]; //result.point = info.papers[j].point; result.scope = info.scope; result.name = info.name; result.time = info.startTime; await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}")); } } }