using Azure.Cosmos; using Azure.Messaging.ServiceBus; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK; using TEAMModelOS.SDK.Models; using TEAMModelOS.SDK.Models.Service; using HTEXLib.COMM.Helpers; using ClouDASLibx; using System.Text.Json; using System.Collections.Generic; using System.Threading.Tasks; using System; using System.Linq; namespace TEAMModelOS.FunctionV4 { public class TriggerExam { public static async Task Trigger(CoreAPIHttpService _coreAPIHttpService, AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing, CosmosClient client, JsonElement input, TriggerData data) { List examClassResults = new(); List examSubjects = new(); try { if ((data.status != null && data.status.Value == 404)) { await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(data.id, new PartitionKey(data.code)); ActivityList activity = input.ToObject(); await ActivityService.DeleteActivity(_coreAPIHttpService, client, _dingDing, activity); var table_cancel = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord"); List records = await table_cancel.FindListByDict(new Dictionary() { { "RowKey", data.id } }); foreach (var record in records) { try { await table_cancel.DeleteSingle(record.PartitionKey, record.RowKey); await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber); } catch (Exception) { continue; } } return; } ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync(data.id, new Azure.Cosmos.PartitionKey($"{data.code}")); if (info != null) { if (info.scope.Equals("teacher", StringComparison.OrdinalIgnoreCase) || info.scope.Equals("private", StringComparison.OrdinalIgnoreCase)) { await foreach (var item in client.GetContainer(Constant.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(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{data.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()); } } } } var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord"); string PartitionKey = string.Format("{0}{1}{2}", info.code, "-", info.progress); List records = await table.FindListByDict(new Dictionary() { { "RowKey", data.id }, { "PartitionKey", PartitionKey } }); //处理科目信息 List sub = new List(); foreach (ExamSubject subject in info.subjects) { sub.Add(subject.id); } //整合名单 List classes = ExamService.getClasses(info.classes, info.stuLists); //ChangeRecord record = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}")); switch (info.progress) { case "pending": var message = new ServiceBusMessage(new { id = data.id, progress = "going", code = data.code }.ToJsonString()); message.ApplicationProperties.Add("name", "Exam"); if (records.Count > 0) { try { await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), records[0].sequenceNumber); } catch (Exception) { } long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(data.startTime)); records[0].sequenceNumber = start; await table.SaveOrUpdate(records[0]); //await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}")); } else { long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(data.startTime)); //string pk = String.Format("{0}{1}{2}", info.code, "-", "pending"); ChangeRecord changeRecord = new ChangeRecord { RowKey = data.id, PartitionKey = PartitionKey, sequenceNumber = start, msgId = message.MessageId }; await table.Save(changeRecord); //await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}")); } break; case "going": try { //向学生或醍摩豆账号发起通知 #region //Notice notice = new Notice() //{ // msgId = info.id, // creation = info.startTime, // expire = info.endTime, // creatorId = info.creatorId, // stuids = studentss, // tmdids = tmdids, // type = "notice",//评测参加通知 // priority = "normal", // school = info.school, // scope = info.scope, // //data = new { }.ToJsonString() // body = new Body { sid = info.id, scode = info.code, spk = info.pk, biztype = "exam-join" } //}; //var messageBlob = new ServiceBusMessage(notice.ToJsonString()); //messageBlob.ApplicationProperties.Add("name", "Notice"); //await _serviceBus.GetServiceBusClient().SendMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageBlob); #endregion //List classes = new List(); //处理活动中间件 List members = await Activity(_coreAPIHttpService, info, classes, client, _dingDing, sub, examClassResults); if (examClassResults.Count == 0) { foreach (string cla in classes) { int m = 0; RGroupList rGroup = new(); rGroup = members.Where(m => m.id.Equals(cla)).FirstOrDefault(); foreach (ExamSubject subject in info.subjects) { string classCode = string.Empty; string cname = string.Empty; if (string.IsNullOrEmpty(info.school) || !info.scope.Equals("school", StringComparison.OrdinalIgnoreCase)) { classCode = "ExamClassResult-" + info.creatorId; } else { classCode = "ExamClassResult-" + info.school; } cname = members.Where(m => m.id.Equals(cla)).FirstOrDefault()?.name; ExamClassResult result = new() { code = classCode, examId = info.id, id = Guid.NewGuid().ToString(), subjectId = subject.id, year = info.year, scope = info.scope }; result.info.id = cla; result.info.name = cname; List ans = new List(); List> anses = new List>(); List> marks = new List>(); List ansPoint = new List(); List<(string sId, string scode)> ids = new List<(string sId, string scode)>(); foreach (double p in info.papers[m].point) { //Details details = new Details(); //ans.Add(new List()); anses.Add(new List()); marks.Add(new List
()); ansPoint.Add(-1); } var sresponse = await client.GetContainer(Constant.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(); School sc = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync(info.school, new Azure.Cosmos.PartitionKey("Base")); foreach (Period period in sc.period) { if (period.id.Equals(classroom.periodId)) { foreach (Semester semester in period.semesters) { if (semester.start == 1) { int year = DateTimeOffset.UtcNow.Year; int month = DateTimeOffset.UtcNow.Month; int day = DateTimeOffset.UtcNow.Day; int time = 0; if (month == semester.month) { time = day >= semester.day ? 0 : 1; } else { time = month > semester.month ? 0 : 1; } int eyear = year - time; result.gradeId = (eyear - classroom.year).ToString(); } } } } //result.info.id = classroom.id; //result.info.name = classroom.name; //result.gradeId = classroom.year.ToString(); //处理班级人数 /* await foreach (var item in client.GetContainer(Constant.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(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"GroupList")); if (stuResponse.Status == 200) { using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream); GroupList stuList = json.ToObject(); //result.info.id = stuList.id; result.info.name = stuList.name; //处理发布对象为自选名单(个人) foreach (Member stus in stuList.members) { if (!ids.Contains(stus.id)) { ids.Add(stus.id); } } } } else { var stuResponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"GroupList-{info.school}")); if (stuResponse.Status == 200) { using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream); GroupList stuList = json.ToObject(); //result.info.id = stuList.id; result.info.name = stuList.name; //处理发布对象为自选名单(校本) foreach (Member stus in stuList.members) { if (!ids.Contains(stus.id)) { ids.Add(stus.id); } } } }*/ foreach (RMember member in rGroup.members) { ids.Add((member.id, member.code)); } //ids = members.Where(c => c.id.Equals(cla)).SelectMany(m => m.members).Select(g => g.id).ToList(); foreach (var (sId, scode) in ids) { result.mark.Add(marks); result.studentIds.Add(sId); //result.scIds.Add(scode ?? ""); result.studentAnswers.Add(ans); result.studentScores.Add(ansPoint); result.ans.Add(anses); result.sum.Add(0); result.status.Add(1); } //result.progress = info.progress; result.school = info.school; m++; await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}")); } } } else { //处理单科结算时科目与试卷信息匹配的问题 int gno = 0; foreach (ExamSubject subject in info.subjects) { if (subject.classCount == classes.Count) { await createClassResultAsync(info, examClassResults, subject, gno, _azureCosmos, _dingDing, _azureStorage); } gno++; } var isScore = examClassResults.SelectMany(e => e.studentScores).ToList().Exists(c => c.Contains(-1)); int newStatus = 0; if (!isScore) { newStatus = 1; } Settlement settlement = await getMore(client, info, examClassResults); long nowTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); //判断评分状态是否发生变化,便于实时的更新评测基本信息 if (info.average != settlement.score || info.sStatus != newStatus) { info.sRate = settlement.rate; info.sStatus = newStatus; info.updateTime = nowTime; info.average = settlement.score; await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, info.id, new PartitionKey(info.code)); } } } catch (Exception e) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测going状态异常{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組); } finally { // 发送信息通知 var messageEnd = new ServiceBusMessage(new { id = data.id, progress = "finish", code = data.code }.ToJsonString()); messageEnd.ApplicationProperties.Add("name", "Exam"); if (records.Count > 0) { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(data.endTime)); try { await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), records[0].sequenceNumber); } catch (Exception) { } records[0].sequenceNumber = end; await table.SaveOrUpdate(records[0]); //await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}")); } else { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(data.endTime)); //string pk = String.Format("{0}{1}{2}", info.code, "-", "going"); ChangeRecord changeRecord = new ChangeRecord { RowKey = data.id, PartitionKey = PartitionKey, sequenceNumber = end, msgId = messageEnd.MessageId }; await table.Save(changeRecord); //await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}")); } } break; case "finish": int fno = 0; try { //用来判定是否完成评分 //bool isScore = true; await resultStatus(client, examClassResults); Settlement settlement = await getMore(client, info, examClassResults); var isScore = examClassResults.SelectMany(e => e.studentScores).ToList().Exists(c => c.Contains(-1)); int newStatus = 0; if (!isScore) { newStatus = 1; } await Activity(_coreAPIHttpService, info, classes, client, _dingDing, sub, examClassResults); foreach (ExamSubject subject in info.subjects) { await createClassResultAsync(info, examClassResults, subject, fno, _azureCosmos, _dingDing, _azureStorage); fno++; } //判断均分是否发生变化,便于实时的更新评测基本信息 if (info.sRate != settlement.rate || info.average != settlement.score || info.sStatus != newStatus || info.qRate != settlement.qrate) { info.sRate = settlement.rate; info.average = settlement.score; info.sStatus = newStatus; info.lostStu = settlement.stus; info.stuCount = settlement.total; info.qRate = settlement.qrate; //处理试卷活动结束统计账户信息 List idList = await GroupListService.GetFinishMemberInfo(_coreAPIHttpService, client, _dingDing, info.school, info.classes, info.stuLists, null); info.staffIds = idList; await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, info.id, new Azure.Cosmos.PartitionKey(info.code)); } } catch (Exception e) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测finish状态异常{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組); } break; } } } catch (CosmosException e) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-CosmosDB异常{e.Message}\n{e.StackTrace}\n{e.Status}", GroupNames.醍摩豆服務運維群組); } catch (Exception e) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测结算异常{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組); } } public static async Task resultStatus(CosmosClient client, List examClassResults) { List>> tasks = new(); //结算单科单班的标准差和平均分 foreach (ExamClassResult classResult in examClassResults) { //标记单科单班总得分 double subScore = 0; //标准差 double sPowSum = 0; List newSumScore = new List(); var scount = classResult.studentIds.Count; int index = 0; if (classResult.status.Count > 0) { foreach (var sta in classResult.status) { if (sta == 1) { for (int i = 0; i < classResult.studentScores[index].Count; i++) { if (classResult.studentScores[index][i] == -1) { classResult.studentScores[index][i] = 0; } } } else if (sta == 0) { //var ans = classResult.studentAnswers[index]; //该学生缺考,历史数据的判定 //if (ans.Count == 0) //{ for (int i = 0; i < classResult.studentScores[index].Count; i++) { if (classResult.studentScores[index][i] == -1) { classResult.studentScores[index][i] = 0; } } /*if (ans.Count == 0) { classResult.status[index] = 1; } */ //} } index++; } } else { List sta = new(); foreach (var id in classResult.studentIds) { sta.Add(0); } classResult.status = sta; foreach (var ans in classResult.studentAnswers) { //该学生缺考,历史数据的判定 if (ans.Count == 0) { for (int i = 0; i < classResult.studentScores[index].Count; i++) { if (classResult.studentScores[index][i] == -1) { classResult.studentScores[index][i] = 0; } } classResult.status[index] = 1; } index++; } } int sIndex = 0; foreach (List sc in classResult.studentScores) { List newSc = new List(); foreach (double ssc in sc) { if (ssc == -1) { newSc.Add(0); } else { newSc.Add(ssc); } } double nc = Math.Round(newSc.Sum(), 2); newSumScore.Add(nc); subScore += nc; classResult.sum[sIndex] = nc; sIndex++; } double rateScore = scount > 0 ? Math.Round(subScore * 1.0 / scount, 2) : 0; foreach (double scs in newSumScore) { sPowSum += Math.Pow(scs - rateScore, 2); } classResult.standard = Math.Round(scount > 0 ? Math.Pow(sPowSum / scount, 0.5) : 0, 2); classResult.average = scount > 0 ? Math.Round(subScore / scount, 2) : 0; classResult.progress = true; tasks.Add(client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(classResult, classResult.id, new PartitionKey($"{classResult.code}"))); } await Task.WhenAll(tasks); } public static async Task getMore(CosmosClient client, ExamInfo info, List examClassResults) { //计算单次考试简易统计信息 Settlement settlement = new(); List examResults = new(); await foreach (var item in client.GetContainer(Constant.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); } if (examResults.Count > 0) { //记录某次考试所有学生得分总分 double score = 0; double allScore = 0; int stuCount = 0; //标准差 double powSum = 0; List losStu = new List(); //当前完成考试得人数 int total = examResults[0].studentIds.Distinct().Count(); //先与第一个值取并集 losStu = losStu.Union(examResults[0].lostStus).ToList(); foreach (ExamResult examResult in examResults) { if (info.id == examResult.examId) { foreach (List sc in examResult.studentScores) { score += sc.Sum(); } stuCount = examResult.studentIds.Count; } //powSum += Math.Pow(score - examResult.studentIds.Count > 0 ? Math.Round(score * 1.0 / examResult.studentIds.Count, 2) : 0, 2); //取交集 losStu = losStu.Intersect(examResult.lostStus).ToList(); } double NewsRateScore = stuCount > 0 ? Math.Round(score * 1.0 / stuCount, 2) : 0; foreach (PaperSimple simple in info.papers) { allScore += simple.point.Sum(); } //计算全科标准差 double qk = 0; foreach (string id in examResults[0].studentIds) { //计算整体缺考人数 foreach (var ec in examClassResults) { int index = ec.studentIds.IndexOf(id); if (index > -1) { if (ec.status[index] == 1) { qk++; break; } } } double sc = 0; foreach (ExamResult result in examResults) { if (result.studentScores.Count > 0) { sc += result.studentScores[result.studentIds.IndexOf(id)].Sum(); } } powSum += Math.Pow(sc - NewsRateScore, 2); } info.standard = Math.Round(total > 0 ? Math.Pow(powSum / total, 0.5) : 0, 2); double NewsRate = allScore > 0 ? Math.Round(NewsRateScore / allScore * 100, 2) : 0; double qrate = Math.Round(qk / total * 100, 2); settlement.rate = NewsRate; settlement.score = NewsRateScore; settlement.stus = losStu; settlement.total = total; settlement.qrate = qrate; } return settlement; } //处理全部学生选题计数 public static async Task examRecordCount(ExamInfo info, ExamSubject subject, DingDing _dingDing, int no, ExamResult er, List classResults, AzureCosmosFactory _azureCosmos) { try { List scores = new List(); foreach (List sc in er.studentScores) { scores.Add(sc.Sum()); } //确定高分组 最低分数 //var srowallorder = scores.EnumerateIndexed().OrderByDescending(g => g.Item2); //各生總分排序 //var srowallorder = scores.OrderByDescending(g => g); double[] point = StringHelper.ListTodouble(er.paper.point); double[,] result = StringHelper.ListToDouble(er.studentScores); var cdm = new ClouDASMatrix(result, point); scores.Sort((s1, s2) => { return s2.CompareTo(s1); }); int rhwCount = cdm.SH.Count(); double rhw = cdm.SH.LastOrDefault().Item2; int rhlCount = cdm.SL.Count(); double rhl = cdm.SL.FirstOrDefault().Item2; List phs = new(); List pls = new(); //分别获取高分组低分组人员 foreach (var ph in cdm.SH) { phs.Add(er.studentIds[ph.Item1]); } foreach (var pl in cdm.SL) { pls.Add(er.studentIds[pl.Item1]); } /* if (scores.Count > 3) { rhwCount = Convert.ToInt32(Math.Floor(scores.Count * 0.27)); rhw = rhwCount > 0 ? scores[rhwCount - 1] : 0; rhlCount = Convert.ToInt32(Math.Ceiling(scores.Count * 0.73)); rhl = rhlCount > 0 ? scores[rhlCount] : 0; } else { rhwCount = Convert.ToInt32(Math.Floor(scores.Count * 0.27)); rhw = rhwCount > 0 ? scores[rhwCount] : 0; rhlCount = Convert.ToInt32(Math.Ceiling(scores.Count * 0.73)); rhl = rhlCount > 0 ? scores[rhlCount - 1] : 0; }*/ /*int rhwCount = Convert.ToInt32(Math.Floor(scores.Count * 0.27)); double rhw = rhwCount > 0 ? scores[rhwCount-1] : 0; //var rhww = srowallorder.Take(Convert.ToInt32(Math.Floor(scores.Count * 0.27))); //确定低分组 最高分数 //scores.Sort((s1, s2) => { return s1.CompareTo(s2); }); int rhlCount = Convert.ToInt32(Math.Ceiling(scores.Count * 0.73)); double rhl = rhlCount > 0 ? scores[rhlCount-1] : 0;*/ //var rhll = srowallorder.Skip(Convert.ToInt32(Math.Ceiling(scores.Count * 0.73))); //存放高分组学生ID List phId = new(); List plId = new(); List>> opth = new(); List>> optl = new(); List akp = await knowledgeCount(info, subject, _dingDing, no, classResults, rhwCount, rhw, rhlCount, rhl, _azureCosmos); List afp = await fieldCount(info, subject, _dingDing, no, classResults, rhwCount, rhw, rhlCount, rhl, _azureCosmos); int PHCount = 0; int PLCount = 0; foreach (ExamClassResult classResult in classResults) { if (classResult.subjectId.Equals(subject.id)) { foreach (string id in classResult.studentIds) { int index = classResult.studentIds.IndexOf(id); if (classResult.studentScores.Count > 0) { if (phs.Contains(id)) { if (classResult.ans.Count > 0) { opth.Add(classResult.ans[index]); PHCount++; continue; } } if (pls.Contains(id)) { if (classResult.ans.Count > 0) { optl.Add(classResult.ans[index]); PLCount++; continue; } } } } } } er.phc = getMore(info, no, opth); er.plc = getMore(info, no, optl); er.afp = afp; er.akp = akp; } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测作答记录结算异常{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組); } } public static async Task> Activity(CoreAPIHttpService _coreAPIHttpService, ExamInfo info, List classes, CosmosClient client, DingDing _dingDing, List sub, List results) { List<(string pId, List gid)> ps = new List<(string pId, List gid)>(); if (info.groupLists.Count > 0) { var group = info.groupLists; foreach (var gp in group) { foreach (KeyValuePair> pp in gp) { ps.Add((pp.Key, pp.Value)); } } } (List tchList, List classLists) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, classes, info.school, ps); var addStudentsCls = tchList.FindAll(x => x.type == 2); var addTmdidsCls = tchList.FindAll(x => x.type == 1); List stuActivities = new List(); List tmdActivities = new List(); if (addTmdidsCls.IsNotEmpty()) { addTmdidsCls.ForEach(x => { HashSet classIds = new HashSet(); classLists.ForEach(z => { z.members.ForEach(y => { if (y.id.Equals(x.id) && y.type == 1) { classIds.Add(z.id); } }); }); bool iss = false; //标记学生作答状态 int ts = 0; if (results.Count > 0) { foreach (ExamClassResult exam in results) { int index = exam.studentIds.IndexOf(x.id); if (index != -1) { if (exam.studentAnswers[index].Count > 0) { bool flag = exam.studentScores[index].Exists(x => x == -1); if (!flag) { ts = 1; iss = true; break; } else { ts = 0; } } else { ts = -1; } } } } else { ts = -1; } tmdActivities.Add(new StuActivity { pk = "Activity", id = info.id, code = $"Activity-{x.id}", type = "Exam", name = info.name, source = info.source, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, school = info.school, creatorId = info.creatorId, subjects = sub, blob = null, owner = info.owner, createTime = info.createTime, taskStatus = ts, qamode = info.qamode, ext = new Dictionary() { { "type", info.examType.ToJsonString().ToObject() }, { "subjects", info.subjects.ToJsonString().ToObject() } }, sStatus = iss ? 1 : 0, classIds = classIds.ToList() }); }); } if (addStudentsCls.IsNotEmpty()) { addStudentsCls.ForEach(x => { HashSet classIds = new HashSet(); classLists.ForEach(z => { z.members.ForEach(y => { if (y.id.Equals(x.id) && y.code.Equals(info.school) && y.type == 2) { classIds.Add(z.id); } }); }); bool iss = false; //标记学生作答状态 int ts = 0; if (results.Count > 0) { foreach (ExamClassResult exam in results) { int index = exam.studentIds.IndexOf(x.id); if (index != -1) { if (exam.studentAnswers[index].Count > 0) { bool flag = exam.studentScores[index].Exists(x => x == -1); if (!flag) { ts = 1; iss = true; break; } else { ts = 0; } } else { ts = -1; } } } } else { ts = -1; } stuActivities.Add(new StuActivity { pk = "Activity", id = info.id, code = $"Activity-{x.code.Replace("Base-", "")}-{x.id}", type = "Exam", name = info.name, source = info.source, startTime = info.startTime, endTime = info.endTime, scode = info.code, scope = info.scope, school = info.school, creatorId = info.creatorId, subjects = sub, blob = null, owner = info.owner, classIds = classIds.ToList(), createTime = info.createTime, qamode = info.qamode, ext = new Dictionary() { { "type", info.examType.ToJsonString().ToObject() }, { "subjects", info.subjects.ToJsonString().ToObject() } }, taskStatus = ts, sStatus = iss ? 1 : 0, }); }); } await ActivityService.SaveStuActivity(client, _dingDing, stuActivities, tmdActivities, null); return classLists; } public static async Task> knowledgeCount(ExamInfo info, ExamSubject subject, DingDing _dingDing, int no, List classResults, double rhwCount, double rhw, double rhlCount, double rhl, AzureCosmosFactory _azureCosmos) { List akp = new(); try { int phcount = 0; int plcount = 0; //存放并去重知识点 HashSet kname = new HashSet(); if (info.papers[no].knowledge.Count > 0) { info.papers[no].knowledge.ForEach(kno => { kno.ForEach(k => { kname.Add(k); }); }); List knowledgeName = new List(); foreach (string cla in kname) { knowledgeName.Add(cla); } for (int k = 0; k < knowledgeName.Count; k++) { if (null == knowledgeName[k]) { knowledgeName.Remove(knowledgeName[k]); } } foreach (ExamClassResult classResult in classResults) { if (classResult.subjectId.Equals(subject.id)) { //List phc = new List(); List ph = new List(); List pl = new List(); List pc = new List(); List persent = new List(); for (int i = 0; i < knowledgeName.Count; i++) { //初始化单个知识点得分 double score = 0; double allScore = 0; int n = 0; int phCount = 0; int plCount = 0; int pCount = 0; foreach (List str in info.papers[no].knowledge) { if (str.Contains(knowledgeName[i])) { var itemPersent = str.Count > 0 ? 1 / Convert.ToDouble(str.Count) : 0; allScore += info.papers[no].point.Count > 0 ? info.papers[no].point[n] * itemPersent : 0; foreach (string id in classResult.studentIds) { int index = classResult.studentIds.IndexOf(id); if (classResult.studentScores.Count > 0) { if (classResult.studentScores[index].Count > 0) { score += classResult.studentScores[index][n] == -1 ? 0 : classResult.studentScores[index][n] * itemPersent; if (classResult.studentScores[index].Sum() >= rhw && phcount < rhwCount) { if (classResult.studentScores[index][n] <= 0) { phCount++; } phcount++; continue; } if (classResult.studentScores[index].Sum() <= rhl && plcount < (info.stuCount - rhlCount)) { if (classResult.studentScores[index][n] <= 0) { plCount++; } plcount++; continue; } if (classResult.studentScores[index][n] <= 0) { pCount++; } } } } } n++; } pc.Add(pCount); ph.Add(phCount); pl.Add(plCount); double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0; persent.Add(allScore > 0 ? Math.Round(per / allScore,2) : 0); } classResult.phc = ph; classResult.plc = pl; classResult.pc = pc; classResult.krate = persent; } //await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}")); } foreach (string k in knowledgeName) { double score = 0; double allScore = 0; int count = 0; foreach (ExamClassResult result in classResults) { if (result.subjectId.Equals(subject.id)) { int n = 0; foreach (List str in info.papers[no].knowledge) { if (str.Contains(k)) { var itemPersent = str.Count > 0 ? 1 / Convert.ToDouble(str.Count) : 0; allScore += info.papers[no].point.Count > 0 ? info.papers[no].point[n] * itemPersent : 0; if (result.studentScores.Count > 0) { foreach (List sc in result.studentScores) { double tsc = sc[n] == -1 ? 0 : sc[n]; score += tsc * itemPersent; } } } n++; } count += result.studentIds.Count; } } double per = count > 0 ? Math.Round(score / count, 2) : 0; akp.Add(allScore > 0 ? Math.Round(per / allScore, 2) : 0); } } return akp; } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测知识点结算异常{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組); return null; } } public static async Task> fieldCount(ExamInfo info, ExamSubject subject, DingDing _dingDing, int no, List classResults, double rhwCount, double rhw, double rhlCount, double rhl, AzureCosmosFactory _azureCosmos) { List afp = new(); try { int phcount = 0; int plcount = 0; //存放并去重知识点 List knowledgeName = new List() { 1, 2, 3, 4, 5, 6 }; /* knowledgeName.Add(1); knowledgeName.Add(2); knowledgeName.Add(3); knowledgeName.Add(4); knowledgeName.Add(5); knowledgeName.Add(6);*/ foreach (ExamClassResult classResult in classResults) { if (classResult.subjectId.Equals(subject.id)) { //List phc = new List(); List ph = new List(); List pl = new List(); List pc = new List(); List persent = new List(); for (int i = 0; i < knowledgeName.Count; i++) { //初始化单个知识点得分 double score = 0; double allScore = 0; int n = 0; int phCount = 0; int plCount = 0; int pCount = 0; if (info.papers[no].field.Count > 0) { foreach (int str in info.papers[no].field) { if (str == knowledgeName[i]) { var itemPersent = 1; allScore += info.papers[no].point.Count > 0 ? info.papers[no].point[n] * itemPersent : 0; foreach (string id in classResult.studentIds) { int index = classResult.studentIds.IndexOf(id); if (classResult.studentScores.Count > 0) { if (classResult.studentScores[index].Count > 0) { score += classResult.studentScores[index][n] == -1 ? 0 : classResult.studentScores[index][n]; if (classResult.studentScores[index].Sum() >= rhw && phcount < rhwCount) { if (classResult.studentScores[index][n] <= 0) { phCount++; } phcount++; continue; } if (classResult.studentScores[index].Sum() <= rhl && plcount < (info.stuCount - rhlCount)) { if (classResult.studentScores[index][n] <= 0) { plCount++; } plcount++; continue; } if (classResult.studentScores[index][n] <= 0) { pCount++; } } } } } n++; } pc.Add(pCount); ph.Add(phCount); pl.Add(plCount); double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0; persent.Add(allScore > 0 ? Math.Round(per / allScore, 2) : 0); } } classResult.fphc = ph; classResult.fplc = pl; classResult.fpc = pc; classResult.frate = persent; } //await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}")); } for (int i = 0; i < knowledgeName.Count; i++) { double score = 0; double allScore = 0; int count = 0; foreach (ExamClassResult result in classResults) { if (result.subjectId.Equals(subject.id)) { int n = 0; foreach (int str in info.papers[no].field) { if (str == knowledgeName[i]) { var itemPersent = 1; allScore += info.papers[no].point.Count > 0 ? info.papers[no].point[n] * itemPersent : 0; if (result.studentScores.Count > 0) { foreach (List sc in result.studentScores) { double tsc = sc[n] == -1 ? 0 : sc[n]; score += tsc * itemPersent; } } } n++; } count += result.studentIds.Count; } } double per = count > 0 ? Math.Round(score / count, 2) : 0; afp.Add(allScore > 0 ? Math.Round(per / allScore, 2) : 0); } return afp; } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测认知层次结算异常{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組); return null; } } //处理选题计数 public static List> getMore(ExamInfo info, int no, List>> list) { List> recorde = new List>(); try { for (int i = 0; i < info.papers[no].answers.Count; i++) { if (info.papers[no].answers[i].Count <= 0) { recorde.Add(new Dictionary()); continue; } Dictionary optCount = new Dictionary(); foreach (List> stu in list) { if (stu.Count == info.papers[no].answers.Count) { var item = stu[i]; foreach (string opt in item) { if (optCount.ContainsKey(opt)) { optCount[opt] = optCount[opt] + 1; } else { optCount[opt] = 1; } } } } recorde.Add(optCount); } return recorde; } catch (Exception) { return recorde; } } public static async Task createClassResultAsync(ExamInfo info, List examClassResults, ExamSubject subject, int no, AzureCosmosFactory _azureCosmos, DingDing _dingDing, AzureStorageFactory _azureStorage) { //保证试卷信息与科目信息同步 ExamResult result = new ExamResult(); //人数总和 int Count = 0; int m = 0; double score = 0; //标准差 //double powSum = 0; double allScore = info.papers[no].point.Sum(); List classRanges = new List(); List lostStu = new List(); List csRate = new List(); List>> opt = new List>>(); foreach (ExamClassResult classResult in examClassResults) { double classSrate = 0; if (classResult.subjectId.Equals(subject.id)) { foreach (List> op in classResult.ans) { opt.Add(op); } //记录缺考学生索引位置 int index_stu = 0; foreach (var ans in classResult.studentAnswers) { if (ans.Count == 0) { if (!lostStu.Contains(classResult.studentIds[index_stu])) { lostStu.Add(classResult.studentIds[index_stu]); } } index_stu++; } 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); } 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); } if (allScore > 0) { csRate.Add(classResult.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore); } else { csRate.Add(0); } //powSum += Math.Pow(classSrate - result.average, 2); //处理选项计数内容 } } /*foreach (string id in result.lostStus) { if (!examClassResults[0].studentIds.Contains(id)) { int index = result.lostStus.IndexOf(id); result.lostStus.RemoveAt(index); } }*/ //处理人员变更时被移除的人员 if (result.lostStus.Count > 0) { for (int i = 0; i < result.lostStus.Count; i++) { if (!examClassResults[0].studentIds.Contains(result.lostStus[i])) { result.lostStus.RemoveAt(i); } } } result.record = getMore(info, no, opt); result.average = result.studentIds.Count > 0 ? Math.Round(score * 1.0 / result.studentIds.Count, 2) : 0; double stand = 0; int sco = 0; List>> tasks = new(); foreach (ExamClassResult classResult in examClassResults) { //double classSrate = 0; if (classResult.subjectId.Equals(subject.id)) { stand += classResult.standard; sco++; } tasks.Add(_azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(classResult, classResult.id, new PartitionKey($"{classResult.code}"))); } await Task.WhenAll(tasks); result.standard = sco > 0 ? Math.Round(stand / sco, 2) : 0; result.csRate = csRate; result.lostStus = lostStu; result.sRate = allScore > 0 ? Math.Round(result.average / allScore * 100, 2) : 0; 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 examRecordCount(info, subject, _dingDing, no, result, examClassResults, _azureCosmos); await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}")); } public class Settlement { public double rate { get; set; } public double score { get; set; } public List stus { get; set; } = new List(); public int total { get; set; } public double qrate { get; set; } } } }