TriggerArt.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. using Azure.Messaging.ServiceBus;
  2. using HTEXLib.COMM.Helpers;
  3. using Microsoft.Extensions.Configuration;
  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.Models;
  13. using TEAMModelOS.SDK;
  14. using Azure.Cosmos;
  15. using TEAMModelOS.SDK.Models.Cosmos.Common;
  16. using Azure.Core;
  17. using TEAMModelOS.SDK.Models.Service;
  18. using Microsoft.AspNetCore.Http;
  19. using OpenXmlPowerTools;
  20. using DocumentFormat.OpenXml.Office2010.Excel;
  21. using DocumentFormat.OpenXml.Office2016.Excel;
  22. using static TEAMModelOS.SDK.Models.Cosmos.Student.StudentAnalysis;
  23. namespace TEAMModelOS.FunctionV4.CosmosDB
  24. {
  25. public class TriggerArt
  26. {
  27. public static async Task Trigger(CoreAPIHttpService _coreAPIHttpService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
  28. CosmosClient client, JsonElement input, TriggerData tdata, AzureRedisFactory _azureRedis, IConfiguration _configuration)
  29. {
  30. try
  31. {
  32. if ((tdata.status != null && tdata.status.Value == 404))
  33. {
  34. await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(tdata.id, new PartitionKey(tdata.code));
  35. ActivityList data = input.ToObject<ActivityList>();
  36. //删除blob 相关资料
  37. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, tdata.school, new List<string> { $"art/{tdata.id}" });
  38. await ActivityService.DeleteActivity(_coreAPIHttpService, client, _dingDing, data);
  39. var table_cancel = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  40. List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
  41. foreach (var record in records)
  42. {
  43. try
  44. {
  45. await table_cancel.DeleteSingle<ChangeRecord>(record.PartitionKey, record.RowKey);
  46. await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
  47. }
  48. catch (Exception)
  49. {
  50. continue;
  51. }
  52. }
  53. return;
  54. }
  55. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  56. var adid = tdata.id;
  57. var adcode = "";
  58. string blobcntr = null;
  59. if (tdata.scope.Equals("school"))
  60. {
  61. adcode = $"Activity-{tdata.school}";
  62. blobcntr = tdata.school;
  63. }
  64. else
  65. {
  66. adcode = $"Activity-{tdata.creatorId}";
  67. blobcntr = tdata.creatorId;
  68. }
  69. ArtEvaluation art = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ArtEvaluation>(tdata.id, new Azure.Cosmos.PartitionKey($"{tdata.code}"));
  70. if (art != null)
  71. {
  72. string PartitionKey = string.Format("{0}{1}{2}", art.code, "-", art.progress);
  73. List<ChangeRecord> voteRecords = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id }, { "PartitionKey", PartitionKey } });
  74. switch (art.progress)
  75. {
  76. case "pending":
  77. var messageVote = new ServiceBusMessage(new { tdata.id, progress = "going", code = tdata.code }.ToJsonString());
  78. messageVote.ApplicationProperties.Add("name", "Art");
  79. if (voteRecords.Count > 0)
  80. {
  81. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVote, DateTimeOffset.FromUnixTimeMilliseconds(tdata.startTime));
  82. try
  83. {
  84. await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), voteRecords[0].sequenceNumber);
  85. }
  86. catch (Exception)
  87. {
  88. }
  89. voteRecords[0].sequenceNumber = start;
  90. await table.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
  91. }
  92. else
  93. {
  94. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVote, DateTimeOffset.FromUnixTimeMilliseconds(tdata.startTime));
  95. ChangeRecord changeRecord = new ChangeRecord
  96. {
  97. RowKey = tdata.id,
  98. PartitionKey = PartitionKey,
  99. sequenceNumber = start,
  100. msgId = messageVote.MessageId
  101. };
  102. await table.Save<ChangeRecord>(changeRecord);
  103. }
  104. break;
  105. case "going":
  106. if (art.classes.Count > 0)
  107. {
  108. List<string> classes = ExamService.getClasses(art.classes, art.stuLists);
  109. (List<RMember> tmdIds, List<RGroupList> classLists) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, classes, art.school, null);
  110. var addStudentsCls = tmdIds.FindAll(x => x.type == 2);
  111. var addTmdidsCls = tmdIds.FindAll(x => x.type == 1);
  112. List<string> tmds = new List<string>();
  113. if (addTmdidsCls.IsNotEmpty())
  114. {
  115. tmds.AddRange(addTmdidsCls.Select(x => x.id).ToList());
  116. }
  117. List<StuActivity> stuActivities = new List<StuActivity>();
  118. List<StuActivity> tmdActivities = new List<StuActivity>();
  119. List<StuActivity> tchActivities = new List<StuActivity>();
  120. List<string> sub = new();
  121. if (art.subjects.Count > 0)
  122. {
  123. foreach (var course in art.subjects)
  124. {
  125. sub.Add(course.id);
  126. }
  127. }
  128. if (tmds.IsNotEmpty())
  129. {
  130. tmds.ForEach(x =>
  131. {
  132. HashSet<string> classIds = new HashSet<string>();
  133. classLists.ForEach(z =>
  134. {
  135. z.members.ForEach(y =>
  136. {
  137. if (y.id.Equals(x) && y.type == 1)
  138. {
  139. classIds.Add(z.id);
  140. }
  141. });
  142. });
  143. tmdActivities.Add(new StuActivity
  144. {
  145. pk = "Activity",
  146. id = art.id,
  147. code = $"Activity-{x}",
  148. type = "Art",
  149. name = art.name,
  150. startTime = art.startTime,
  151. endTime = art.endTime,
  152. scode = art.code,
  153. scope = art.scope,
  154. school = art.school,
  155. creatorId = art.creatorId,
  156. subjects = sub,
  157. blob = null,
  158. owner = art.owner,
  159. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  160. ext = new Dictionary<string, JsonElement>() { { "subjects", art.subjects.ToJsonString().ToObject<JsonElement>() } },
  161. taskStatus = -1,
  162. classIds = classIds.ToList()
  163. });
  164. });
  165. }
  166. if (addStudentsCls.IsNotEmpty())
  167. {
  168. addStudentsCls.ForEach(x =>
  169. {
  170. HashSet<string> classIds = new HashSet<string>();
  171. classLists.ForEach(z =>
  172. {
  173. z.members.ForEach(y =>
  174. {
  175. if (y.id.Equals(x.id) && y.code.Equals(art.school) && y.type == 2)
  176. {
  177. classIds.Add(z.id);
  178. }
  179. });
  180. });
  181. stuActivities.Add(new StuActivity
  182. {
  183. pk = "Activity",
  184. id = art.id,
  185. code = $"Activity-{x.code.Replace("Base-", "")}-{x.id}",
  186. type = "Atr",
  187. name = art.name,
  188. startTime = art.startTime,
  189. endTime = art.endTime,
  190. scode = art.code,
  191. scope = art.scope,
  192. school = art.school,
  193. creatorId = art.creatorId,
  194. subjects = sub,
  195. blob = null,
  196. owner = art.owner,
  197. createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
  198. ext = new Dictionary<string, JsonElement>() { { "subjects", art.subjects.ToJsonString().ToObject<JsonElement>() } },
  199. taskStatus = -1,
  200. classIds = classIds.ToList()
  201. });
  202. });
  203. }
  204. await ActivityService.SaveStuActivity(client, _dingDing, stuActivities, tmdActivities, tchActivities);
  205. //await StatisticsService.SendServiceBus(list, _configuration, _serviceBus, client)
  206. }
  207. var messageVoteEnd = new ServiceBusMessage(new { tdata.id, progress = "finish", tdata.code }.ToJsonString());
  208. messageVoteEnd.ApplicationProperties.Add("name", "Art");
  209. if (voteRecords.Count > 0)
  210. {
  211. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.endTime));
  212. try
  213. {
  214. await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), voteRecords[0].sequenceNumber);
  215. }
  216. catch (Exception)
  217. {
  218. }
  219. voteRecords[0].sequenceNumber = end;
  220. await table.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
  221. }
  222. else
  223. {
  224. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.endTime));
  225. ChangeRecord changeRecord = new()
  226. {
  227. RowKey = tdata.id,
  228. PartitionKey = PartitionKey,
  229. sequenceNumber = end,
  230. msgId = messageVoteEnd.MessageId
  231. };
  232. await table.Save<ChangeRecord>(changeRecord);
  233. }
  234. break;
  235. case "finish":
  236. //判定是否是区级创建的活动内容
  237. if (art.lost.Count == 0 && art.pass == 0)
  238. {
  239. if (art.owner.Equals("area") && string.IsNullOrEmpty(art.pId))
  240. {
  241. /* List<(string id, string code, List<Tasks> settings)> artSchools = new();
  242. string ql = $"select c.id,c.school,c.settings,c.classes from c where c.pk = 'Art' and c.pId = '{art.id}'";
  243. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: ql))
  244. {
  245. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  246. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  247. {
  248. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  249. while (accounts.MoveNext())
  250. {
  251. JsonElement account = accounts.Current;
  252. List<Tasks> settings = account.GetProperty("settings").ToObject<List<Tasks>>();
  253. artSchools.Add((account.GetProperty("id").GetString(), account.GetProperty("school").GetString(), settings));
  254. }
  255. }
  256. }
  257. foreach (var (id, code, settings) in artSchools)
  258. {
  259. List<(string eId, string sId)> ids = new();
  260. var examIds = settings.SelectMany(s => s.task).Where(a => a.type == 1).Select(z => new { z.acId, z.subject }).ToList();
  261. examIds.ForEach(x =>
  262. {
  263. ids.Add((x.acId, x.subject));
  264. });
  265. List<(string code, string sub, List<string> stu)> stuInfo = await getLostAsync(ids, client, code);
  266. List<string> stus = new();
  267. foreach (var lost in stuInfo)
  268. {
  269. if (stus.Count == 0)
  270. {
  271. stus = stus.Union(lost.stu).ToList();
  272. }
  273. else {
  274. stus = stus.Intersect(lost.stu).ToList();
  275. }
  276. LostStudent lostStudent = new()
  277. {
  278. code = lost.code,
  279. subject = lost.sub,
  280. stu = lost.stu.Count
  281. };
  282. art.lost.Add(lostStudent);
  283. }
  284. art.miss.Add(stus.Count);
  285. }
  286. art.pass = 1;
  287. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync<ArtEvaluation>(art, art.id, new PartitionKey(art.code));*/
  288. }
  289. else
  290. {
  291. //获取当前艺术评价相关评测ID目前暂时排除区级发布的评测信息
  292. /*List<(string eId, string sId)> ids = new();
  293. var examId = art.settings.SelectMany(x => x.task).Where(c => c.type == 1).Select(z => new { z.acId, z.subject }).ToList();
  294. examId.ForEach(x =>
  295. {
  296. ids.Add((x.acId, x.subject));
  297. });
  298. List<(string code, string sub, List<string> stu)> stuInfo = await getLostAsync(ids, client, art.school);
  299. List<string> stus = new();
  300. foreach (var (code, sub, stu) in stuInfo)
  301. {
  302. if (stus.Count == 0)
  303. {
  304. stus = stus.Union(stu).ToList();
  305. }
  306. else
  307. {
  308. stus = stus.Intersect(stu).ToList();
  309. }
  310. LostStudent lostStudent = new()
  311. {
  312. code = code,
  313. subject = sub,
  314. stu = stu.Count
  315. };
  316. art.lost.Add(lostStudent);
  317. }
  318. art.miss.Add(stus.Count);
  319. //art.miss = stus.Count;
  320. art.pass = 1;
  321. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync<ArtEvaluation>(art, art.id, new PartitionKey(art.code));*/
  322. }
  323. }
  324. List<StudentArtResult> studentArtResults = new();
  325. string sql = $"SELECT value c FROM c where c.pk='ArtResult' ";
  326. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student)
  327. .GetItemQueryIterator<StudentArtResult>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtResult-{art.id}") }))
  328. {
  329. studentArtResults.Add(item);
  330. }
  331. //根据学校编码去获取区级ID
  332. School scInfo = new();
  333. //School scInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{art.school}", partitionKey: new Azure.Cosmos.PartitionKey("Base"));
  334. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{art.school}", partitionKey: new Azure.Cosmos.PartitionKey("Base"));
  335. if (response.Status == 200)
  336. {
  337. using var cJson = await JsonDocument.ParseAsync(response.ContentStream);
  338. scInfo = cJson.ToObject<School>();
  339. }
  340. ArtSetting setting = new();
  341. try
  342. {
  343. var artResponse = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{scInfo.areaId}", partitionKey: new Azure.Cosmos.PartitionKey("ArtSetting"));
  344. if (response.Status == 200)
  345. {
  346. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  347. setting = json.ToObject<ArtSetting>();
  348. }
  349. }
  350. catch (Exception e)
  351. {
  352. }
  353. List<Task<ItemResponse<StudentArtResult>>> tasks = new List<Task<ItemResponse<StudentArtResult>>>();
  354. //总分的占比情况
  355. foreach (var rs in studentArtResults)
  356. {
  357. foreach (var res in rs.results) {
  358. if (res.quotaId.Equals("quota_21") && res.score > -1 && res.score < 95) {
  359. /*res.score *= 1.5;
  360. if (res.score >= 95) {
  361. res.score = new Random().Next(90, 99);
  362. }*/
  363. res.score = Math.Round(res.score);
  364. }
  365. }
  366. //if (rs.totalScore == 0)
  367. //{
  368. foreach (var sc in rs.subjectScores)
  369. {
  370. //if (sc.score == 0)
  371. //{
  372. /* var subjectMore = rs.results.GroupBy(x => x.subjectId).Select(c => new { subject = c.Key, list = c.ToList().Select(m => new { m.quotaId,m.score}) });
  373. var totalScore = subjectMore.Select(x => new {
  374. x.subject,
  375. quotaScroe = x.list.Select(c => new {
  376. c.quotaId,
  377. c.score
  378. }),
  379. });*/
  380. var quotaPercent = setting.quotas.Select(x => new
  381. {
  382. x.id,
  383. x.percent,
  384. score = x.children.Select(c => new
  385. {
  386. real = rs.results.Where(r => r.quotaId.Equals(c.id) && r.subjectId.Equals(sc.subjectId) && r.score > -1).FirstOrDefault()?.score * c.percent * 0.01,
  387. score = c.children.Select(s => new
  388. {
  389. real = rs.results.Where(r => r.quotaId.Equals(s.id) && r.subjectId.Equals(sc.subjectId) && r.score > -1).FirstOrDefault()?.score * s.percent * 0.01
  390. }).Sum(n => n.real) * c.percent * 0.01
  391. }).Sum(n => n.real + n.score) * x.percent * 0.01
  392. });
  393. double realScore = Math.Round((double)quotaPercent.Sum(c => c.score), 2);
  394. sc.score = realScore;
  395. //}
  396. }
  397. rs.totalScore = Math.Round(rs.subjectScores.Where(m => m.score >= 0).Sum(z => z.score), 2);
  398. tasks.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync(rs, rs.id, new PartitionKey(rs.code)));
  399. //}
  400. }
  401. if (tasks.Count > 0)
  402. {
  403. await Task.WhenAll(tasks);
  404. }
  405. break;
  406. }
  407. }
  408. }
  409. catch (CosmosException e)
  410. {
  411. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-CosmosDB异常{e.Message}\n{e.StackTrace}\n{e.Status}", GroupNames.醍摩豆服務運維群組);
  412. }
  413. catch (Exception ex)
  414. {
  415. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}艺术评价异常{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  416. }
  417. }
  418. }
  419. }