TriggerExam.cs 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  1. using Azure.Cosmos;
  2. using Azure.Messaging.ServiceBus;
  3. using Microsoft.Azure.Documents;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Text.Json;
  9. using System.Threading.Tasks;
  10. using TEAMModelOS.SDK.DI;
  11. using TEAMModelOS.SDK.Extension;
  12. using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
  13. using TEAMModelOS.SDK.Models;
  14. using TEAMModelOS.SDK.Models.Cosmos;
  15. using TEAMModelOS.SDK.Models.Cosmos.Common;
  16. namespace TEAMModelFunction
  17. {
  18. public class TriggerExam
  19. {
  20. public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
  21. CosmosClient client, Document input, string code, long stime, long etime, string school)
  22. {
  23. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
  24. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  25. List<ExamSubject> examSubjects = new List<ExamSubject>();
  26. if (info.scope.Equals("teacher", StringComparison.OrdinalIgnoreCase) || info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
  27. {
  28. 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}") }))
  29. {
  30. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  31. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  32. {
  33. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  34. {
  35. examClassResults.Add(obj.ToObject<ExamClassResult>());
  36. }
  37. }
  38. }
  39. }
  40. else
  41. {
  42. 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}") }))
  43. {
  44. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  45. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  46. {
  47. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  48. {
  49. examClassResults.Add(obj.ToObject<ExamClassResult>());
  50. }
  51. }
  52. }
  53. }
  54. List<ChangeRecord> records = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", info.progress } });
  55. //处理科目信息
  56. List<string> sub = new List<string>();
  57. foreach (ExamSubject subject in info.subjects)
  58. {
  59. sub.Add(subject.id);
  60. }
  61. //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}"));
  62. switch (info.progress)
  63. {
  64. case "pending":
  65. var message = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
  66. message.ApplicationProperties.Add("name", "Exam");
  67. if (records.Count > 0)
  68. {
  69. await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
  70. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
  71. records[0].sequenceNumber = start;
  72. await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
  73. //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
  74. }
  75. else
  76. {
  77. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
  78. ChangeRecord changeRecord = new ChangeRecord
  79. {
  80. RowKey = input.Id,
  81. PartitionKey = "pending",
  82. sequenceNumber = start,
  83. msgId = message.MessageId
  84. };
  85. await _azureStorage.Save<ChangeRecord>(changeRecord);
  86. //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
  87. }
  88. break;
  89. case "going":
  90. //ActivityData data;
  91. //if (info.scope == "school")
  92. //{
  93. // data = new ActivityData
  94. // {
  95. // id = info.id,
  96. // code = $"Activity-{info.school}",
  97. // type = "exam",
  98. // name = info.name,
  99. // startTime = info.startTime,
  100. // endTime = info.endTime,
  101. // scode = info.code,
  102. // scope = info.scope,
  103. // classes = info.classes.IsNotEmpty() ? info.classes : new List<string> { "" },
  104. // tmdids = new List<string> { "" },
  105. // progress = "going",
  106. // subjects = sub
  107. // };
  108. // await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
  109. //}
  110. //else if (info.scope == "private")
  111. //{
  112. // data = new ActivityData
  113. // {
  114. // id = info.id,
  115. // code = $"Activity-Common",
  116. // type = "exam",
  117. // name = info.name,
  118. // startTime = info.startTime,
  119. // endTime = info.endTime,
  120. // scode = info.code,
  121. // scope = info.scope,
  122. // progress = "going",
  123. // classes = info.classes.IsNotEmpty() ? info.classes : new List<string> { "" },
  124. // tmdids = new List<string> { "" },
  125. // subjects = sub
  126. // };
  127. // await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
  128. //}
  129. (List<string> tmdids, List<Students> studentss) = await TriggerStuActivity.GetStuList(client, info.classes, info.school);
  130. List<StuActivity> stuActivities = new List<StuActivity>();
  131. List<StuActivity> tmdActivities = new List<StuActivity>();
  132. if (tmdids.IsNotEmpty())
  133. {
  134. tmdids.ForEach(x =>
  135. {
  136. tmdActivities.Add(new StuActivity
  137. {
  138. pk = "Activity",
  139. id = info.id,
  140. code = $"Activity-{x}",
  141. type = "Exam",
  142. name = info.name,
  143. startTime = info.startTime,
  144. endTime = info.endTime,
  145. scode = info.code,
  146. scope = info.scope,
  147. school = info.school,
  148. creatorId = info.creatorId,
  149. subjects = sub,
  150. blob = null
  151. });
  152. });
  153. }
  154. if (studentss.IsNotEmpty())
  155. {
  156. studentss.ForEach(x =>
  157. {
  158. stuActivities.Add(new StuActivity
  159. {
  160. pk = "Activity",
  161. id = info.id,
  162. code = $"Activity-{info.school}-{x.id}",
  163. type = "Exam",
  164. name = info.name,
  165. startTime = info.startTime,
  166. endTime = info.endTime,
  167. scode = info.code,
  168. scope = info.scope,
  169. school = info.school,
  170. creatorId = info.creatorId,
  171. subjects = sub,
  172. blob = null
  173. });
  174. });
  175. }
  176. await TriggerStuActivity.SaveStuActivity(client, stuActivities, tmdActivities);
  177. if (examClassResults.Count == 0)
  178. {
  179. foreach (string cla in info.classes)
  180. {
  181. int m = 0;
  182. foreach (ExamSubject subject in info.subjects)
  183. {
  184. string classCode = "";
  185. if (string.IsNullOrEmpty(info.school) || !info.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
  186. {
  187. classCode = "ExamClassResult-" + info.creatorId;
  188. }
  189. else
  190. {
  191. classCode = "ExamClassResult-" + info.school;
  192. }
  193. ExamClassResult result = new ExamClassResult
  194. {
  195. code = classCode,
  196. examId = info.id,
  197. id = Guid.NewGuid().ToString(),
  198. subjectId = subject.id,
  199. year = info.year,
  200. scope = info.scope
  201. };
  202. result.info.id = cla;
  203. List<string> ans = new List<string>();
  204. List<double> ansPoint = new List<double>();
  205. List<string> ids = new List<string>();
  206. foreach (double p in info.papers[m].point)
  207. {
  208. //ans.Add(new List<string>());
  209. ansPoint.Add(-1);
  210. }
  211. var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
  212. if (sresponse.Status == 200)
  213. {
  214. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  215. Class classroom = json.ToObject<Class>();
  216. //result.info.id = classroom.id;
  217. result.info.name = classroom.name;
  218. result.gradeId = classroom.gradeId;
  219. //处理班级人数
  220. 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}") }))
  221. {
  222. using var json_stu = await JsonDocument.ParseAsync(item.ContentStream);
  223. if (json_stu.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  224. {
  225. var accounts = json_stu.RootElement.GetProperty("Documents").EnumerateArray();
  226. while (accounts.MoveNext())
  227. {
  228. JsonElement account = accounts.Current;
  229. ids.Add(account.GetProperty("id").GetString());
  230. }
  231. }
  232. }
  233. }
  234. if (info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
  235. {
  236. var stuResponse = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"StuList"));
  237. if (stuResponse.Status == 200)
  238. {
  239. using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream);
  240. StuList stuList = json.ToObject<StuList>();
  241. //result.info.id = stuList.id;
  242. result.info.name = stuList.name;
  243. //处理发布对象为自选名单(个人)
  244. foreach (Students stus in stuList.students)
  245. {
  246. ids.Add(stus.id);
  247. }
  248. if (stuList.tmids.Count > 0)
  249. {
  250. foreach (string tid in stuList.tmids)
  251. {
  252. ids.Add(tid);
  253. }
  254. }
  255. }
  256. }
  257. else
  258. {
  259. var stuResponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"StuList-{info.school}"));
  260. if (stuResponse.Status == 200)
  261. {
  262. using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream);
  263. StuList stuList = json.ToObject<StuList>();
  264. //result.info.id = stuList.id;
  265. result.info.name = stuList.name;
  266. //处理发布对象为自选名单(校本)
  267. foreach (Students stus in stuList.students)
  268. {
  269. ids.Add(stus.id);
  270. }
  271. }
  272. }
  273. foreach (string stu in ids)
  274. {
  275. result.mark.Add("");
  276. result.studentIds.Add(stu);
  277. result.studentAnswers.Add(ans);
  278. result.studentScores.Add(ansPoint);
  279. result.sum.Add(0);
  280. }
  281. //result.progress = info.progress;
  282. result.school = info.school;
  283. m++;
  284. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}"));
  285. }
  286. }
  287. // 发送信息通知
  288. var messageEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
  289. messageEnd.ApplicationProperties.Add("name", "Exam");
  290. if (records.Count > 0)
  291. {
  292. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
  293. await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
  294. records[0].sequenceNumber = end;
  295. await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
  296. //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
  297. }
  298. else
  299. {
  300. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
  301. ChangeRecord changeRecord = new ChangeRecord
  302. {
  303. RowKey = input.Id,
  304. PartitionKey = "going",
  305. sequenceNumber = end,
  306. msgId = messageEnd.MessageId
  307. };
  308. await _azureStorage.Save<ChangeRecord>(changeRecord);
  309. //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
  310. }
  311. }
  312. else
  313. {
  314. //处理单科结算时科目与试卷信息匹配的问题
  315. int gno = 0;
  316. foreach (ExamSubject subject in info.subjects)
  317. {
  318. if (subject.classCount == info.classes.Count)
  319. {
  320. await createClassResultAsync(info, examClassResults, subject, gno, _azureCosmos, _dingDing, _azureStorage);
  321. }
  322. gno++;
  323. }
  324. }
  325. break;
  326. case "finish":
  327. int fno = 0;
  328. foreach (ExamSubject subject in info.subjects)
  329. {
  330. await createClassResultAsync(info, examClassResults, subject, fno, _azureCosmos, _dingDing, _azureStorage);
  331. fno++;
  332. }
  333. //计算单次考试简易统计信息
  334. List<ExamResult> examResults = new List<ExamResult>();
  335. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamResult>(
  336. queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}") }))
  337. {
  338. examResults.Add(item);
  339. }
  340. //结算单科单班的标准差和平均分
  341. foreach (ExamClassResult classResult in examClassResults)
  342. {
  343. //标记单科单班总得分
  344. double subScore = 0;
  345. //标准差
  346. double sPowSum = 0;
  347. var scount = classResult.studentIds.Count;
  348. foreach (List<double> sc in classResult.studentScores)
  349. {
  350. subScore += sc.Sum();
  351. }
  352. foreach (string sid in classResult.studentIds)
  353. {
  354. double ssc = classResult.studentScores[classResult.studentIds.IndexOf(sid)].Sum();
  355. sPowSum += Math.Pow(ssc - scount > 0 ? Math.Round(subScore * 1.0 / scount, 2) : 0, 2);
  356. }
  357. classResult.standard = Math.Round(scount > 0 ? Math.Pow(sPowSum / scount, 0.5) : 0, 2);
  358. classResult.average = scount > 0 ? Math.Round(subScore / scount, 2) : 0;
  359. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}"));
  360. }
  361. //记录某次考试所有学生得分总分
  362. double score = 0;
  363. double allScore = 0;
  364. int stuCount = 0;
  365. //整体平均分
  366. double average = 0;
  367. //标准差
  368. double powSum = 0;
  369. List<string> losStu = new List<string>();
  370. //先与第一个值取并集
  371. if (examResults.Count > 0)
  372. {
  373. losStu.Union(examResults[0].lostStus);
  374. foreach (ExamResult examResult in examResults)
  375. {
  376. if (info.id == examResult.examId)
  377. {
  378. foreach (List<double> sc in examResult.studentScores)
  379. {
  380. score += sc.Sum();
  381. }
  382. stuCount = examResult.studentIds.Count;
  383. }
  384. //powSum += Math.Pow(score - examResult.studentIds.Count > 0 ? Math.Round(score * 1.0 / examResult.studentIds.Count, 2) : 0, 2);
  385. //取交集
  386. losStu = losStu.Intersect(examResult.lostStus).ToList();
  387. }
  388. }
  389. double NewsRateScore = stuCount > 0 ? Math.Round(score * 1.0 / stuCount, 2) : 0;
  390. foreach (PaperSimple simple in info.papers)
  391. {
  392. allScore += simple.point.Sum();
  393. }
  394. //计算全科标准差
  395. foreach (string id in examResults[0].studentIds)
  396. {
  397. double sc = 0;
  398. foreach (ExamResult result in examResults)
  399. {
  400. sc += result.studentScores[result.studentIds.IndexOf(id)].Sum();
  401. }
  402. powSum += Math.Pow(sc - NewsRateScore, 2);
  403. }
  404. info.standard = Math.Round(examResults[0].studentIds.Count > 0 ? Math.Pow(powSum / examResults[0].studentIds.Count, 0.5) : 0, 2);
  405. double NewsRate = allScore > 0 ? Math.Round(NewsRateScore / allScore * 100, 2) : 0;
  406. info.lostStu = losStu;
  407. //判断均分是否发生变化,便于实时的更新评测基本信息
  408. if (info.sRate != NewsRate || info.average != NewsRateScore)
  409. {
  410. info.sRate = NewsRate;
  411. info.average = NewsRateScore;
  412. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync<ExamInfo>(info, info.id, new Azure.Cosmos.PartitionKey(info.code));
  413. }
  414. break;
  415. }
  416. }
  417. //处理全部学生选题计数
  418. public static async Task examRecordCount(ExamInfo info, ExamSubject subject, DingDing _dingDing, int no, AzureStorageFactory _azureStorage, ExamResult result)
  419. {
  420. try
  421. {
  422. string blobcntr = "";
  423. if (info.scope.Equals("school"))
  424. {
  425. blobcntr = info.school;
  426. }
  427. else
  428. {
  429. blobcntr = info.creatorId;
  430. }
  431. List<double> scores = new List<double>();
  432. foreach (List<double> sc in result.studentScores)
  433. {
  434. scores.Add(sc.Sum());
  435. }
  436. //确定高分组 最低分数
  437. scores.Sort((s1, s2) => { return s2.CompareTo(s1); });
  438. double rhwCount = scores.Count * 0.27;
  439. double rhw = rhwCount > 0 ? scores[int.Parse(rhwCount.ToString("0"))] : 0;
  440. //double rhw = resultSum[int.Parse(rhwCount.ToString("0"))];
  441. //确定低分组 最高分数
  442. scores.Sort((s1, s2) => { return s1.CompareTo(s2); });
  443. double rhlCount = scores.Count * 0.27;
  444. double rhl = rhlCount > 0 ? scores[int.Parse(rhlCount.ToString("0"))] : 0;
  445. //存放高分组学生ID
  446. List<string> phId = new List<string>();
  447. List<string> plId = new List<string>();
  448. foreach (string id in result.studentIds)
  449. {
  450. int index = result.studentIds.IndexOf(id);
  451. if (result.studentScores[index].Sum() >= rhw)
  452. {
  453. phId.Add(id);
  454. continue;
  455. }
  456. if (result.studentScores[index].Sum() <= rhl)
  457. {
  458. plId.Add(id);
  459. continue;
  460. }
  461. }
  462. var ContainerClient = _azureStorage.GetBlobContainerClient(blobcntr);
  463. List<string> items = await ContainerClient.List($"exam/{info.id}/{subject.id}");
  464. List<List<List<string>>> ansList = new List<List<List<string>>>();
  465. List<List<List<string>>> phAnsList = new List<List<List<string>>>();
  466. List<List<List<string>>> plAnsList = new List<List<List<string>>>();
  467. List<string> phItems = new List<string>();
  468. List<string> plItems = new List<string>();
  469. foreach (string item in items)
  470. {
  471. //确定高分组选项内容
  472. foreach (string id in phId) {
  473. if (item.Contains($"/{id}/"))
  474. {
  475. var phDownload = await _azureStorage.GetBlobContainerClient(blobcntr).GetBlobClient(item).DownloadAsync();
  476. var phjson = await JsonDocument.ParseAsync(phDownload.Value.Content);
  477. var phRecord = phjson.RootElement.ToObject<List<List<string>>>();
  478. phAnsList.Add(phRecord);
  479. break;
  480. }
  481. }
  482. //确定低分组选项内容
  483. foreach (string id in plId)
  484. {
  485. if (item.Contains($"/{id}/"))
  486. {
  487. var plDownload = await _azureStorage.GetBlobContainerClient(blobcntr).GetBlobClient(item).DownloadAsync();
  488. var pljson = await JsonDocument.ParseAsync(plDownload.Value.Content);
  489. var plRecord = pljson.RootElement.ToObject<List<List<string>>>();
  490. plAnsList.Add(plRecord);
  491. break;
  492. }
  493. }
  494. var Download = await _azureStorage.GetBlobContainerClient(blobcntr).GetBlobClient(item).DownloadAsync();
  495. var json = await JsonDocument.ParseAsync(Download.Value.Content);
  496. var Record = json.RootElement.ToObject<List<List<string>>>();
  497. ansList.Add(Record);
  498. }
  499. result.record = getMore(info, no, ansList);
  500. result.phc = getMore(info, no, phAnsList);
  501. result.plc = getMore(info, no, plAnsList);
  502. }
  503. catch (Exception ex)
  504. {
  505. await _dingDing.SendBotMsg($"评测作答记录结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  506. }
  507. }
  508. //处理选题计数
  509. public static List<Dictionary<string, int>> getMore(ExamInfo info, int no, List<List<List<string>>> list)
  510. {
  511. List<Dictionary<string, int>> recorde = new List<Dictionary<string, int>>();
  512. try
  513. {
  514. for (int i = 0; i < info.papers[no].answers.Count; i++)
  515. {
  516. if (info.papers[no].answers[i].Count <= 0)
  517. {
  518. recorde.Add(new Dictionary<string, int>());
  519. continue;
  520. }
  521. Dictionary<string, int> optCount = new Dictionary<string, int>();
  522. foreach (List<List<string>> stu in list)
  523. {
  524. if (stu.Count == info.papers[no].answers.Count)
  525. {
  526. var item = stu[i];
  527. foreach (string opt in item)
  528. {
  529. if (optCount.ContainsKey(opt))
  530. {
  531. optCount[opt] = optCount[opt] + 1;
  532. }
  533. else
  534. {
  535. optCount[opt] = 1;
  536. }
  537. }
  538. }
  539. }
  540. recorde.Add(optCount);
  541. }
  542. return recorde;
  543. }
  544. catch (Exception)
  545. {
  546. return recorde;
  547. }
  548. }
  549. public static async Task createClassResultAsync(ExamInfo info, List<ExamClassResult> examClassResults, ExamSubject subject, int no, AzureCosmosFactory _azureCosmos, DingDing _dingDing, AzureStorageFactory _azureStorage)
  550. {
  551. //保证试卷信息与科目信息同步
  552. ExamResult result = new ExamResult();
  553. //人数总和
  554. int Count = 0;
  555. int m = 0;
  556. double score = 0;
  557. //标准差
  558. double powSum = 0;
  559. double allScore = info.papers[no].point.Sum();
  560. List<ClassRange> classRanges = new List<ClassRange>();
  561. List<string> lostStu = new List<string>();
  562. List<double> csRate = new List<double>();
  563. foreach (ExamClassResult classResult in examClassResults)
  564. {
  565. double classSrate = 0;
  566. if (classResult.subjectId.Equals(subject.id))
  567. {
  568. //记录缺考学生索引位置
  569. int index = 0;
  570. foreach (List<double> scores in classResult.studentScores)
  571. {
  572. List<double> newScores = new List<double>();
  573. int count = 0;
  574. foreach (double sc in scores)
  575. {
  576. newScores.Add(sc > -1 ? sc : 0);
  577. if (sc == -1)
  578. {
  579. count++;
  580. }
  581. }
  582. if (count == scores.Count)
  583. {
  584. lostStu.Add(classResult.studentIds[index]);
  585. //mcount++;
  586. }
  587. classSrate += newScores.Sum();
  588. score += newScores.Sum();
  589. result.studentScores.Add(newScores);
  590. index++;
  591. }
  592. //处理班级信息
  593. ClassRange range = new ClassRange();
  594. range.id = classResult.info.id;
  595. range.name = classResult.info.name;
  596. range.gradeId = classResult.gradeId;
  597. List<int> ran = new List<int>();
  598. int stuCount = classResult.studentIds.Count;
  599. Count += stuCount;
  600. if (m == 0)
  601. {
  602. ran.Add(0);
  603. ran.Add(stuCount - 1);
  604. }
  605. else
  606. {
  607. ran.Add(Count - stuCount);
  608. ran.Add(Count - 1);
  609. }
  610. m++;
  611. range.range = ran;
  612. classRanges.Add(range);
  613. //处理学生ID
  614. foreach (string id in classResult.studentIds)
  615. {
  616. result.studentIds.Add(id);
  617. }
  618. csRate.Add(result.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore);
  619. //powSum += Math.Pow(classSrate - result.average, 2);
  620. }
  621. }
  622. result.average = result.studentIds.Count > 0 ? Math.Round(score * 1.0 / result.studentIds.Count, 2) : 0;
  623. foreach (ExamClassResult classResult in examClassResults)
  624. {
  625. //double classSrate = 0;
  626. if (classResult.subjectId.Equals(subject.id))
  627. {
  628. foreach (string id in classResult.studentIds)
  629. {
  630. double sc = classResult.studentScores[classResult.studentIds.IndexOf(id)].Sum();
  631. powSum += Math.Pow(sc - result.average, 2);
  632. }
  633. }
  634. }
  635. //处理选项计数内容
  636. await examRecordCount(info, subject, _dingDing, no, _azureStorage, result);
  637. result.standard = Math.Round(result.studentIds.Count > 0 ? Math.Pow(powSum / result.studentIds.Count, 0.5) : 0, 2);
  638. result.csRate = csRate;
  639. result.lostStus = lostStu;
  640. result.sRate = Math.Round(result.average / allScore * 100, 2);
  641. result.classes = classRanges;
  642. result.code = "ExamResult-" + info.id;
  643. result.school = info.school;
  644. result.id = subject.id;
  645. result.examId = info.id;
  646. result.subjectId = subject.id;
  647. result.year = info.year;
  648. result.paper = info.papers[no];
  649. //result.point = info.papers[j].point;
  650. result.scope = info.scope;
  651. result.name = info.name;
  652. result.time = info.startTime;
  653. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}"));
  654. }
  655. }
  656. }