TriggerExam.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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.Text;
  7. using System.Text.Json;
  8. using System.Threading.Tasks;
  9. using TEAMModelOS.SDK.DI;
  10. using TEAMModelOS.SDK.Extension;
  11. using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
  12. using TEAMModelOS.SDK.Models;
  13. using TEAMModelOS.SDK.Models.Cosmos;
  14. using TEAMModelOS.SDK.Models.Cosmos.Common;
  15. namespace TEAMModelFunction
  16. {
  17. public class TriggerExam
  18. {
  19. public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
  20. CosmosClient client, Document input ,string code,long stime,long etime, string school)
  21. {
  22. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
  23. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  24. List<ExamSubject> examSubjects = new List<ExamSubject>();
  25. if (info.scope.Equals("teacher", StringComparison.OrdinalIgnoreCase) || info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
  26. {
  27. 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}") }))
  28. {
  29. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  30. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  31. {
  32. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  33. {
  34. examClassResults.Add(obj.ToObject<ExamClassResult>());
  35. }
  36. }
  37. }
  38. }
  39. else {
  40. 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}") }))
  41. {
  42. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  43. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  44. {
  45. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  46. {
  47. examClassResults.Add(obj.ToObject<ExamClassResult>());
  48. }
  49. }
  50. }
  51. }
  52. List<ChangeRecord> records = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", info.progress } });
  53. //处理科目信息
  54. List<string> sub = new List<string>();
  55. foreach (ExamSubject subject in info.subjects)
  56. {
  57. sub.Add(subject.id);
  58. }
  59. //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}"));
  60. switch (info.progress)
  61. {
  62. case "pending":
  63. var message = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
  64. message.ApplicationProperties.Add("name", "Exam");
  65. if (records.Count > 0)
  66. {
  67. await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
  68. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
  69. records[0].sequenceNumber = start;
  70. await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
  71. //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
  72. }
  73. else
  74. {
  75. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
  76. ChangeRecord changeRecord = new ChangeRecord
  77. {
  78. RowKey = input.Id,
  79. PartitionKey = "pending",
  80. sequenceNumber = start,
  81. msgId = message.MessageId
  82. };
  83. await _azureStorage.Save<ChangeRecord>(changeRecord);
  84. //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
  85. }
  86. break;
  87. case "going":
  88. ActivityData data;
  89. if (info.scope == "school")
  90. {
  91. data = new ActivityData
  92. {
  93. id = info.id,
  94. code = $"Activity-{info.school}",
  95. type = "exam",
  96. name = info.name,
  97. startTime = info.startTime,
  98. endTime = info.endTime,
  99. scode = info.code,
  100. scope = info.scope,
  101. classes = info.targetClassIds.IsNotEmpty() ? info.targetClassIds : new List<string> { "" },
  102. tmdids = new List<string> { "" },
  103. progress = "going",
  104. owner = info.school,
  105. subjects = sub
  106. };
  107. await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
  108. }
  109. else if (info.scope == "private")
  110. {
  111. data = new ActivityData
  112. {
  113. id = info.id,
  114. code = $"Activity-Common",
  115. type = "exam",
  116. name = info.name,
  117. startTime = info.startTime,
  118. endTime = info.endTime,
  119. scode = info.code,
  120. scope = info.scope,
  121. progress = "going",
  122. classes = info.targetClassIds.IsNotEmpty() ? info.targetClassIds : new List<string> { "" },
  123. tmdids = new List<string> { "" },
  124. owner = info.creatorId,
  125. subjects = sub
  126. };
  127. await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
  128. }
  129. if (examClassResults.Count == 0)
  130. {
  131. foreach (string cla in info.targetClassIds)
  132. {
  133. int m = 0;
  134. foreach (ExamSubject subject in info.subjects)
  135. {
  136. string classCode = "";
  137. if (string.IsNullOrEmpty(info.school) || !info.scope.Equals("school",StringComparison.OrdinalIgnoreCase))
  138. {
  139. classCode = "ExamClassResult-" + info.creatorId;
  140. }
  141. else {
  142. classCode = "ExamClassResult-" + info.school;
  143. }
  144. ExamClassResult result = new ExamClassResult
  145. {
  146. code = classCode,
  147. examId = info.id,
  148. id = Guid.NewGuid().ToString(),
  149. subjectId = subject.id,
  150. year = info.year,
  151. scope = info.scope
  152. };
  153. result.info.id = cla;
  154. List<string> ans = new List<string>();
  155. List<double> ansPoint = new List<double>();
  156. List<string> ids = new List<string>();
  157. foreach (double p in info.papers[m].point)
  158. {
  159. //ans.Add(new List<string>());
  160. ansPoint.Add(-1);
  161. }
  162. var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
  163. if (sresponse.Status == 200)
  164. {
  165. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  166. Class classroom = json.ToObject<Class>();
  167. //result.info.id = classroom.id;
  168. result.info.name = classroom.name;
  169. result.gradeId = classroom.gradeId;
  170. //处理班级人数
  171. 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}") }))
  172. {
  173. using var json_stu = await JsonDocument.ParseAsync(item.ContentStream);
  174. if (json_stu.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  175. {
  176. var accounts = json_stu.RootElement.GetProperty("Documents").EnumerateArray();
  177. while (accounts.MoveNext())
  178. {
  179. JsonElement account = accounts.Current;
  180. ids.Add(account.GetProperty("id").GetString());
  181. }
  182. }
  183. }
  184. }
  185. if (info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
  186. {
  187. var stuResponse = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"StuList"));
  188. if (stuResponse.Status == 200) {
  189. using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream);
  190. StuList stuList = json.ToObject<StuList>();
  191. //result.info.id = stuList.id;
  192. result.info.name = stuList.name;
  193. //处理发布对象为自选名单(个人)
  194. foreach (Students students in stuList.students)
  195. {
  196. ids.Add(students.id);
  197. }
  198. if (stuList.tmids.Count > 0)
  199. {
  200. foreach (string tid in stuList.tmids)
  201. {
  202. ids.Add(tid);
  203. }
  204. }
  205. }
  206. }
  207. else {
  208. var stuResponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"StuList-{info.school}"));
  209. if (stuResponse.Status == 200)
  210. {
  211. using var json = await JsonDocument.ParseAsync(stuResponse.ContentStream);
  212. StuList stuList = json.ToObject<StuList>();
  213. //result.info.id = stuList.id;
  214. result.info.name = stuList.name;
  215. //处理发布对象为自选名单(校本)
  216. foreach (Students students in stuList.students)
  217. {
  218. ids.Add(students.id);
  219. }
  220. }
  221. }
  222. foreach (string stu in ids)
  223. {
  224. result.studentIds.Add(stu);
  225. result.studentAnswers.Add(ans);
  226. result.studentScores.Add(ansPoint);
  227. result.sum.Add(0);
  228. }
  229. //result.progress = info.progress;
  230. result.school = info.school;
  231. m++;
  232. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}"));
  233. }
  234. }
  235. // 发送信息通知
  236. var messageEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
  237. messageEnd.ApplicationProperties.Add("name", "Exam");
  238. if (records.Count > 0)
  239. {
  240. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
  241. await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
  242. records[0].sequenceNumber = end;
  243. await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
  244. //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
  245. }
  246. else
  247. {
  248. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
  249. ChangeRecord changeRecord = new ChangeRecord
  250. {
  251. RowKey = input.Id,
  252. PartitionKey = "going",
  253. sequenceNumber = end,
  254. msgId = messageEnd.MessageId
  255. };
  256. await _azureStorage.Save<ChangeRecord>(changeRecord);
  257. //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
  258. }
  259. }
  260. else
  261. {
  262. //处理单科结算时科目与试卷信息匹配的问题
  263. int gno = 0;
  264. foreach (ExamSubject subject in info.subjects)
  265. {
  266. if (subject.classCount == info.targetClassIds.Count)
  267. {
  268. await createClassResultAsync(info, examClassResults, subject, gno,_azureCosmos);
  269. }
  270. gno++;
  271. }
  272. }
  273. break;
  274. case "finish":
  275. int fno = 0;
  276. foreach (ExamSubject subject in info.subjects)
  277. {
  278. await createClassResultAsync(info, examClassResults, subject, fno, _azureCosmos);
  279. fno++;
  280. }
  281. //ActivityData data;
  282. if (info.scope == "school")
  283. {
  284. data = new ActivityData
  285. {
  286. id = info.id,
  287. code = $"Activity-{info.school}",
  288. type = "exam",
  289. name = info.name,
  290. startTime = info.startTime,
  291. endTime = info.endTime,
  292. scode = info.code,
  293. scope = info.scope,
  294. progress = "finish",
  295. classes = info.targetClassIds.IsNotEmpty() ? info.targetClassIds : new List<string> { "" },
  296. tmdids = new List<string> { "" },
  297. owner = info.school,
  298. subjects = sub
  299. };
  300. await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<ActivityData>(data, info.id, new Azure.Cosmos.PartitionKey(data.code));
  301. }
  302. else if (info.scope == "private")
  303. {
  304. data = new ActivityData
  305. {
  306. id = info.id,
  307. code = $"Activity-Common",
  308. type = "exam",
  309. name = info.name,
  310. startTime = info.startTime,
  311. endTime = info.endTime,
  312. scode = info.code,
  313. scope = info.scope,
  314. progress = "finish",
  315. classes = info.targetClassIds.IsNotEmpty() ? info.targetClassIds : new List<string> { "" },
  316. tmdids = new List<string> { "" },
  317. owner = info.creatorId,
  318. subjects = sub
  319. };
  320. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<ActivityData>(data, info.id, new Azure.Cosmos.PartitionKey(data.code));
  321. }
  322. break;
  323. }
  324. }
  325. public static async Task createClassResultAsync(ExamInfo info, List<ExamClassResult> examClassResults, ExamSubject subject, int no, AzureCosmosFactory _azureCosmos)
  326. {
  327. //保证试卷信息与科目信息同步
  328. ExamResult result = new ExamResult();
  329. //人数总和
  330. int Count = 0;
  331. int m = 0;
  332. List<ClassRange> classRanges = new List<ClassRange>();
  333. foreach (ExamClassResult classResult in examClassResults)
  334. {
  335. if (classResult.subjectId.Equals(subject.id))
  336. {
  337. foreach (List<double> scores in classResult.studentScores)
  338. {
  339. List<double> newScores = new List<double>();
  340. foreach (double sc in scores) {
  341. newScores.Add(sc > -1 ? sc : 0);
  342. }
  343. result.studentScores.Add(newScores);
  344. }
  345. //处理班级信息
  346. ClassRange range = new ClassRange();
  347. range.id = classResult.info.id;
  348. range.name = classResult.info.name;
  349. range.gradeId = classResult.gradeId;
  350. List<int> ran = new List<int>();
  351. int stuCount = classResult.studentIds.Count;
  352. Count += stuCount;
  353. if (m == 0)
  354. {
  355. ran.Add(0);
  356. ran.Add(stuCount - 1);
  357. }
  358. else
  359. {
  360. ran.Add(Count - stuCount);
  361. ran.Add(Count - 1);
  362. }
  363. m++;
  364. range.range = ran;
  365. classRanges.Add(range);
  366. //处理学生ID
  367. foreach (string id in classResult.studentIds)
  368. {
  369. result.studentIds.Add(id);
  370. }
  371. }
  372. }
  373. result.classes = classRanges;
  374. result.code = "ExamResult-" + info.id;
  375. result.school = info.school;
  376. result.id = subject.id;
  377. result.examId = info.id;
  378. result.subjectId = subject.id;
  379. result.year = info.year;
  380. result.paper = info.papers[no];
  381. //result.point = info.papers[j].point;
  382. result.scope = info.scope;
  383. result.name = info.name;
  384. result.time = info.startTime;
  385. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}"));
  386. }
  387. }
  388. }