LessonService.cs 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  1. using Azure.Core;
  2. using Azure.Cosmos;
  3. using Azure.Messaging.ServiceBus;
  4. using DocumentFormat.OpenXml.Drawing.Charts;
  5. using DocumentFormat.OpenXml.VariantTypes;
  6. using HTEXLib.COMM.Helpers;
  7. using MathNet.Numerics.Distributions;
  8. using Microsoft.Extensions.Configuration;
  9. using Microsoft.Extensions.Hosting;
  10. using OpenXmlPowerTools;
  11. using StackExchange.Redis;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Text.Json;
  17. using System.Threading.Tasks;
  18. using TEAMModelOS.SDK.DI;
  19. using TEAMModelOS.SDK.Extension;
  20. using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
  21. using TEAMModelOS.SDK.Models.Cosmos.Common;
  22. using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
  23. using TEAMModelOS.SDK.Services;
  24. namespace TEAMModelOS.SDK.Models.Service
  25. {
  26. public class LessonService
  27. {
  28. public static readonly DateTime dateTime1970 = new DateTime(1970, 1, 1).ToLocalTime();
  29. public static Dictionary<string, object> GetLessonCond(JsonElement request)
  30. {
  31. Dictionary<string, object> dict = new Dictionary<string, object>();
  32. if (request.TryGetProperty("tmdid", out JsonElement tmdid))
  33. {
  34. if (tmdid.ValueKind.Equals(JsonValueKind.String) && !string.IsNullOrWhiteSpace($"{tmdid}"))
  35. {
  36. dict.Add("tmdid", tmdid);
  37. }
  38. else if(tmdid.ValueKind.Equals(JsonValueKind.Array)) {
  39. dict.Add("tmdid", tmdid);
  40. }
  41. }
  42. if (request.TryGetProperty("courseId", out JsonElement courseId) && !string.IsNullOrWhiteSpace($"{courseId}"))
  43. {
  44. dict.Add("courseId", courseId);
  45. }
  46. if (request.TryGetProperty("courseIds", out JsonElement courseIds))
  47. {
  48. dict.Add("courseId[*]", courseIds);
  49. }
  50. if (request.TryGetProperty("periodId", out JsonElement periodId) && !string.IsNullOrWhiteSpace($"{periodId}"))
  51. {
  52. dict.Add("periodId", periodId);
  53. }
  54. if (request.TryGetProperty("subjectId", out JsonElement subjectId))
  55. {
  56. dict.Add("subjectId", subjectId);
  57. }
  58. if (request.TryGetProperty("groupIds", out JsonElement groupIds))
  59. {
  60. dict.Add("groupIds[*]", groupIds);
  61. }
  62. if (request.TryGetProperty("grade", out JsonElement grade))
  63. {
  64. dict.Add("grade[*]", grade);
  65. }
  66. if (request.TryGetProperty("category", out JsonElement category))
  67. {
  68. dict.Add("category[*]", category);
  69. }
  70. if (request.TryGetProperty("doubleGreen", out JsonElement doubleGreen) && doubleGreen.GetBoolean())
  71. {
  72. dict.Add("=.tLevel", 2);
  73. dict.Add("=.pLevel", 2);
  74. //dict.Add(">=.tScore", 70);
  75. //dict.Add(">=.pScore", 70);
  76. }
  77. if (request.TryGetProperty("doubleRed", out JsonElement doubleRed) && doubleRed.GetBoolean())
  78. {
  79. dict.Add("=.tLevel", 0);
  80. dict.Add("=.pLevel", 0);
  81. //dict.Add(">=.tScore", 70);
  82. //dict.Add(">=.pScore", 70);
  83. }
  84. if (request.TryGetProperty("quality", out JsonElement quality) && quality.GetBoolean())
  85. {
  86. dict.Add(">=.discuss", 1);
  87. }
  88. if (request.TryGetProperty("excellent", out JsonElement excellent) && excellent.GetBoolean())
  89. {
  90. dict.Add(">=.excellent", 1);
  91. }
  92. if (request.TryGetProperty("name", out JsonElement name) && !string.IsNullOrWhiteSpace($"{name}"))
  93. {
  94. dict.Add("$.name", name);
  95. }
  96. if (request.TryGetProperty("today", out JsonElement today) && today.GetBoolean())
  97. {
  98. DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  99. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(1);
  100. double dayOf00_00_00 = (dateTimeA - dateTime1970).TotalMilliseconds;
  101. double day1Of00_00_00 = (dateTimeB - dateTime1970).TotalMilliseconds;
  102. dict.Add(">=.startTime", dayOf00_00_00);
  103. dict.Add("<.startTime", day1Of00_00_00);
  104. }
  105. if (request.TryGetProperty("week", out JsonElement week) && week.GetBoolean())
  106. {
  107. // DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  108. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-7);
  109. double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  110. double dayB = (dateTimeB - dateTime1970).TotalMilliseconds;
  111. dict.Add("<=.startTime", now);
  112. dict.Add(">=.startTime", dayB);
  113. }
  114. //查询即将到期的且没有被清理的。
  115. if (request.TryGetProperty("expire", out JsonElement expire) && expire.ValueKind.Equals(JsonValueKind.True))
  116. {
  117. dict.Add(">.expire", 0);
  118. dict.Add("!=.status", 404);
  119. }
  120. //查询已经清理的
  121. if (request.TryGetProperty("is404", out JsonElement is404) && is404.ValueKind.Equals(JsonValueKind.True))
  122. {
  123. dict.Add("=.status", 404);
  124. }
  125. //只查有效的
  126. if (request.TryGetProperty("isOk", out JsonElement isOk) && isOk.ValueKind.Equals(JsonValueKind.True))
  127. {
  128. dict.Add("<=.expire", 0);
  129. dict.Add("!=.status", 404);
  130. }
  131. if (request.TryGetProperty("month", out JsonElement month) && month.GetBoolean())
  132. {
  133. //DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  134. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-30);
  135. double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  136. double dayB = (dateTimeB - dateTime1970).TotalMilliseconds;
  137. dict.Add("<=.startTime", now);
  138. dict.Add(">=.startTime", dayB);
  139. }
  140. if (request.TryGetProperty("stime", out JsonElement stime) && !string.IsNullOrWhiteSpace($"{stime}"))
  141. {
  142. dict.Add(">=.startTime", stime);
  143. }
  144. if (request.TryGetProperty("etime", out JsonElement etime) && !string.IsNullOrWhiteSpace($"{etime}"))
  145. {
  146. dict.Add("<=.startTime", etime);
  147. }
  148. if (request.TryGetProperty("conds", out JsonElement conds) && conds.ValueKind.Equals(JsonValueKind.Array))
  149. {
  150. List<LessonSettingCond> settingConds = conds.Deserialize<List<LessonSettingCond>>();
  151. foreach (var item in settingConds)
  152. {
  153. dict.TryAdd($"{item.type}.{item.key}", item.val);
  154. //switch (item.type)
  155. //{
  156. // case ">=":
  157. // dict.TryAdd($">=.{item.key}",item.val);
  158. // break;
  159. // case "<=":
  160. // dict.TryAdd($"<=.{item.key}", item.val);
  161. // break;
  162. //}
  163. }
  164. }
  165. return dict;
  166. }
  167. public static async void DoLessonStudentRecord(DingDing _dingding, SnowflakeId snowflakeId, LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid,
  168. Teacher teacher, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, LessonBase lessonBase,AzureRedisFactory _azureRedis,
  169. List<int> pickupMemberIds, List<TaskData> taskDatas, List<IRSData> iRSDatas)
  170. {
  171. School schoolBase = null;
  172. Period period = null;
  173. try
  174. {
  175. int year = DateTimeOffset.UtcNow.Year;
  176. string hs = lessonBase?.report?.clientSummaryList.ToJsonString();
  177. var clientSummaryLists = lessonBase?.report?.clientSummaryList?.Where(x => x.groupTaskCompleteCount != 0 || x.groupScore != 0 || x.score != 0 || x.interactScore != 0 || x.taskCompleteCount != 0);
  178. IEnumerable<LessonStudent> students = new List<LessonStudent>();
  179. if (clientSummaryLists.Any())
  180. {
  181. var ids = clientSummaryLists.Select(x => x.seatID);
  182. students = lessonBase.student.Where(x => ids.Contains(x.seatID));
  183. }
  184. List<Student> studentsBase = new List<Student>();
  185. var stuids = students.Where(x => x.type == 2);
  186. if (stuids.Any())
  187. {
  188. stuids.ToList().ForEach(x => {
  189. x.school = string.IsNullOrWhiteSpace(x.school) ? school : x.school;
  190. });
  191. var result= await client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<Student>($"select value c from c where c.id in ({string.Join(",",stuids.Select(d=>$"'{d.id}'"))})", $"Base-{school}");
  192. if (result.list.Any()) {
  193. studentsBase = result.list;
  194. }
  195. }
  196. var groups = stuids.Where(z => !string.IsNullOrWhiteSpace(z.school)).GroupBy(x => x.school).Select(y => new { code = y.Key, list = y.ToList() });
  197. List<StudentScoreRecord> lessonStudentRecords = new List<StudentScoreRecord>();
  198. foreach (var group in groups)
  199. {
  200. string stusql = $"select value(c) from c where c.stuid in({string.Join(",", group.list.Select(x => $"'{x.id}'"))}) and c.school='{group.code}' and c.year={year}";
  201. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentScoreRecord>(queryText: stusql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") }))
  202. {
  203. lessonStudentRecords.Add(item);
  204. }
  205. }
  206. var tmdids = students.Where(x => x.type == 1);
  207. if (tmdids.Any())
  208. {
  209. string tmdsql = $"select value(c) from c where c.tmdid in({string.Join(",", tmdids.Select(x => $"'{x}'"))}) and c.year={year}";
  210. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentScoreRecord>(queryText: tmdsql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") }))
  211. {
  212. lessonStudentRecords.Add(item);
  213. }
  214. }
  215. (Semester currSemester, int studyYear, DateTimeOffset currSemesterDate, DateTimeOffset date, DateTimeOffset nextSemester) dataSemester = new(null,-1, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow, DateTimeOffset.UtcNow) ;
  216. if (!string.IsNullOrWhiteSpace(school)) {
  217. schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  218. period = schoolBase.period.Find(x => x.id.Equals($"{lessonRecord.periodId}"));
  219. if (period!= null) {
  220. dataSemester= SchoolService.GetSemester(period);
  221. }
  222. }
  223. List <Task<ItemResponse<StudentScoreRecord>>> records = new List<Task<ItemResponse<StudentScoreRecord>>>();
  224. HashSet <OverallEducation> overallEducations = new HashSet<OverallEducation>();
  225. // 互动次数,-1 表示没有进行互动。 与 0 不同
  226. int interactCount = -1;
  227. //抢权作答的学生
  228. List<int > buzzClients= new List<int>();
  229. if (iRSDatas.IsNotEmpty()) {
  230. var keys = iRSDatas.Where(z => z.isBuzz==false).Select(v => v.clientAnswers).SelectMany(z => z.Keys).ToList();
  231. var values = iRSDatas.Where(z => z.isBuzz==false).Select(v => v.clientAnswers).SelectMany(z => z.Values).ToList();
  232. interactCount= keys.Count();
  233. var bclients = iRSDatas.Where(z => z.buzzClients.IsNotEmpty()).SelectMany(v => v.buzzClients);
  234. if (bclients!=null && bclients.Count()>0) {
  235. foreach (var bc in bclients) {
  236. if (int.TryParse(bc, out int b)) {
  237. buzzClients.Add(b);
  238. }
  239. }
  240. }
  241. }
  242. //任务发布次数 ,-1 表示没有进行互动。 与 0 不同
  243. int taskCount = -1;
  244. var groupNames = lessonBase.report.clientSummaryList.Where(z => !string.IsNullOrEmpty(z.groupName))?.Select(z=>z.groupName)?.ToHashSet()?.OrderBy(z=>z)?.ToList();
  245. List<IdCodeCount> groupTaskJoinCounts = new List<IdCodeCount>();
  246. if (groupNames.IsNotEmpty()) {
  247. groupTaskJoinCounts = groupNames.Select(z => new IdCodeCount { name=z, count = 0 }).ToList();
  248. }
  249. //組任務發佈數
  250. int groupTaskCount = -1;
  251. if (taskDatas.IsNotEmpty())
  252. {
  253. taskCount=0;
  254. bool hasGroupTask = false;
  255. int groupTaksCountTemp = 0;
  256. foreach (var taskData in taskDatas)
  257. {
  258. var isGroupItem = taskData.clientWorks.FindAll(z => z.isGroupItem);
  259. if (isGroupItem.IsNotEmpty())
  260. {
  261. //有组任务
  262. hasGroupTask = true;
  263. groupTaksCountTemp += 1;
  264. foreach (var item in isGroupItem)
  265. {
  266. int groupIndex = 0;
  267. int.TryParse(item.groupID,out groupIndex);
  268. //由于分组下标从1 开始,则需要判断是否与分组数组大小一致,且提交了作品,则数量+1
  269. if ( groupIndex>0 && item.blobFiles.IsNotEmpty() && groupIndex <= groupTaskJoinCounts.Count) {
  270. groupTaskJoinCounts[groupIndex-1].count+=1;
  271. }
  272. }
  273. }
  274. else
  275. {
  276. //没有组任务
  277. taskCount += 1;
  278. }
  279. }
  280. if (hasGroupTask) {
  281. groupTaskCount=groupTaksCountTemp;
  282. }
  283. }
  284. foreach (var x in stuids) {
  285. var record = lessonStudentRecords.Find(l => l.stuid.Equals(x.id) && l.code.Equals($"StudentScoreRecord") && l.school.Equals(x.school));
  286. ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID);
  287. int stuInteractCount = -1;
  288. int stuInteractJoin = 0;
  289. //获取挑人的互动
  290. var ids= pickupMemberIds.FindAll(z => z==x.seatID);
  291. if (ids.IsNotEmpty())
  292. {
  293. stuInteractJoin=ids.Count;
  294. if (interactCount>=0)
  295. {
  296. stuInteractCount=interactCount+ids.Count;
  297. }
  298. else
  299. {
  300. stuInteractCount=ids.Count;
  301. }
  302. }
  303. //获取抢权的互动
  304. var buzIds = buzzClients.FindAll(z => z==x.seatID);
  305. if (buzIds.IsNotEmpty()) {
  306. stuInteractJoin=stuInteractJoin+buzIds.Count;
  307. if (stuInteractCount>-1)
  308. {
  309. stuInteractCount = stuInteractCount + buzIds.Count;
  310. }
  311. else {
  312. stuInteractCount = buzIds.Count;
  313. }
  314. }
  315. //普通作答的互动
  316. if (record != null)
  317. {
  318. if (clientSummaryList != null)
  319. {
  320. var hasrecord = record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id));
  321. if (hasrecord != null)
  322. {
  323. hasrecord.gscore = clientSummaryList.groupScore;
  324. hasrecord.pscore = clientSummaryList.score;
  325. hasrecord.tscore = clientSummaryList.interactScore;
  326. hasrecord.tmdid = teacher.id;
  327. hasrecord.school = school;
  328. hasrecord.scope = lessonRecord.scope;
  329. hasrecord.lessonId = lessonRecord.id;
  330. hasrecord.courseId = lessonRecord.courseId;
  331. hasrecord.periodId = lessonRecord.periodId;
  332. hasrecord.subjectId = lessonRecord.subjectId;
  333. hasrecord.time = lessonRecord.startTime;
  334. }
  335. else
  336. {
  337. record.lessonRecords.Add(
  338. new StudentLessonRecord
  339. {
  340. gscore = clientSummaryList.groupScore,
  341. pscore = clientSummaryList.score,
  342. tscore = clientSummaryList.interactScore,
  343. tmdid = teacher.id,
  344. school = school,
  345. scope = lessonRecord.scope,
  346. lessonId = lessonRecord.id,
  347. courseId = lessonRecord.courseId,
  348. periodId = lessonRecord.periodId,
  349. subjectId = lessonRecord.subjectId,
  350. time = lessonRecord.startTime
  351. }
  352. );
  353. }
  354. }
  355. }
  356. else
  357. {
  358. record = new StudentScoreRecord
  359. {
  360. userType = Constant.ScopeStudent,
  361. id = $"{snowflakeId.NextId()}",
  362. year = year,
  363. stuid = x.id,
  364. school = x.school,
  365. code = $"StudentScoreRecord",
  366. pk = "StudentScoreRecord",
  367. ttl = -1,
  368. lessonRecords = new List<StudentLessonRecord> { new StudentLessonRecord
  369. {
  370. gscore = clientSummaryList.groupScore,
  371. pscore = clientSummaryList.score,
  372. tscore = clientSummaryList.interactScore,
  373. tmdid = teacher.id,
  374. school = school,
  375. scope = lessonRecord.scope,
  376. lessonId = lessonRecord.id,
  377. courseId = lessonRecord.courseId,
  378. periodId = lessonRecord.periodId,
  379. subjectId = lessonRecord.subjectId,
  380. time= lessonRecord.startTime
  381. }}
  382. };
  383. }
  384. record.userType = Constant.ScopeStudent;
  385. record.gscore = record.lessonRecords.Select(x => x.gscore).Sum();
  386. record.pscore = record.lessonRecords.Select(x => x.pscore).Sum();
  387. record.tscore = record.lessonRecords.Select(x => x.tscore).Sum();
  388. if (dataSemester.currSemester != null && (clientSummaryList.groupScore>0 || clientSummaryList.score > 0 || clientSummaryList.interactScore > 0))
  389. {
  390. string oid = $"{dataSemester.studyYear}-{dataSemester.currSemester.id}-{record.stuid}";
  391. string ocode = $"OverallEducation-{school}";
  392. var student = studentsBase.Find(stu => stu.id.Equals(x.id));
  393. Azure.Response response = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemStreamAsync(oid, new PartitionKey(ocode));
  394. OverallEducation overallEducation = null;
  395. if (response.Status != 200)
  396. {
  397. overallEducation = new OverallEducation
  398. {
  399. id =oid,
  400. code = $"OverallEducation-{school}",
  401. pk = "OverallEducation",
  402. ttl = -1,
  403. name = x.name,
  404. classId = student?.classId,
  405. schoolCode = $"{school}",
  406. semesterId = dataSemester.currSemester.id,
  407. year = dataSemester.studyYear,
  408. periodId = $"{period.id}",
  409. stuYear = student.year,
  410. studentId = x.id,
  411. lessonScore= new List<StudentLessonRecord> { new StudentLessonRecord
  412. {
  413. gscore = clientSummaryList.groupScore,
  414. pscore = clientSummaryList.score,
  415. tscore = clientSummaryList.interactScore,
  416. tmdid = teacher.id,
  417. school = school,
  418. scope = lessonRecord.scope,
  419. lessonId = lessonRecord.id,
  420. courseId = lessonRecord.courseId,
  421. periodId = lessonRecord.periodId,
  422. subjectId = lessonRecord.subjectId,
  423. time= lessonRecord.startTime
  424. }}
  425. };
  426. }
  427. else
  428. {
  429. overallEducation=JsonDocument.Parse(response.Content).RootElement.ToObject<OverallEducation>();
  430. var hasrecord = overallEducation.lessonScore.Find(x => x.lessonId.Equals(lessonRecord.id));
  431. if (hasrecord != null)
  432. {
  433. hasrecord.gscore = clientSummaryList.groupScore;
  434. hasrecord.pscore = clientSummaryList.score;
  435. hasrecord.tscore = clientSummaryList.interactScore;
  436. hasrecord.tmdid = teacher.id;
  437. hasrecord.school = school;
  438. hasrecord.scope = lessonRecord.scope;
  439. hasrecord.lessonId = lessonRecord.id;
  440. hasrecord.courseId = lessonRecord.courseId;
  441. hasrecord.periodId = lessonRecord.periodId;
  442. hasrecord.subjectId = lessonRecord.subjectId;
  443. hasrecord.time = lessonRecord.startTime;
  444. }
  445. else
  446. {
  447. overallEducation.lessonScore.Add(
  448. new StudentLessonRecord
  449. {
  450. gscore = clientSummaryList.groupScore,
  451. pscore = clientSummaryList.score,
  452. tscore = clientSummaryList.interactScore,
  453. tmdid = teacher.id,
  454. school = school,
  455. scope = lessonRecord.scope,
  456. lessonId = lessonRecord.id,
  457. courseId = lessonRecord.courseId,
  458. periodId = lessonRecord.periodId,
  459. subjectId = lessonRecord.subjectId,
  460. time = lessonRecord.startTime
  461. }
  462. );
  463. }
  464. }
  465. overallEducations.Add(overallEducation);
  466. }
  467. records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code)));
  468. }
  469. foreach (var x in tmdids) {
  470. var record = lessonStudentRecords.Find(l => l.tmdid.Equals(x.id) && l.code.Equals($"StudentScoreRecord"));
  471. ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID);
  472. if (record != null)
  473. {
  474. if (clientSummaryList != null)
  475. {
  476. var hasrecord = record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id));
  477. if (hasrecord != null)
  478. {
  479. hasrecord.gscore = clientSummaryList.groupScore;
  480. hasrecord.pscore = clientSummaryList.score;
  481. hasrecord.tscore = clientSummaryList.interactScore;
  482. hasrecord.tmdid = teacher.id;
  483. hasrecord.school = school;
  484. hasrecord.scope = lessonRecord.scope;
  485. hasrecord.lessonId = lessonRecord.id;
  486. hasrecord.courseId = lessonRecord.courseId;
  487. hasrecord.periodId = lessonRecord.periodId;
  488. hasrecord.subjectId = lessonRecord.subjectId;
  489. hasrecord.time = lessonRecord.startTime;
  490. }
  491. else
  492. {
  493. record.lessonRecords.Add(
  494. new StudentLessonRecord
  495. {
  496. gscore = clientSummaryList.groupScore,
  497. pscore = clientSummaryList.score,
  498. tscore = clientSummaryList.interactScore,
  499. tmdid = teacher.id,
  500. school = school,
  501. scope = lessonRecord.scope,
  502. lessonId = lessonRecord.id,
  503. courseId = lessonRecord.courseId,
  504. periodId = lessonRecord.periodId,
  505. subjectId = lessonRecord.subjectId,
  506. time = lessonRecord.startTime
  507. }
  508. );
  509. }
  510. }
  511. }
  512. else
  513. {
  514. record = new StudentScoreRecord
  515. {
  516. userType = Constant.ScopeTmdUser,
  517. id = $"{snowflakeId.NextId()}",
  518. code = $"StudentScoreRecord",
  519. pk = "StudentScoreRecord",
  520. ttl = -1,
  521. year = year,
  522. tmdid = x.id,
  523. lessonRecords = new List<StudentLessonRecord>
  524. {
  525. new StudentLessonRecord
  526. {
  527. gscore = clientSummaryList.groupScore,
  528. pscore = clientSummaryList.score,
  529. tscore = clientSummaryList.interactScore,
  530. tmdid = teacher.id,
  531. school = school,
  532. scope = lessonRecord.scope,
  533. lessonId = lessonRecord.id,
  534. courseId = lessonRecord.courseId,
  535. periodId = lessonRecord.periodId,
  536. subjectId = lessonRecord.subjectId,
  537. time=lessonRecord.startTime
  538. }
  539. }
  540. };
  541. }
  542. record.userType = Constant.ScopeStudent;
  543. record.gscore = record.lessonRecords.Select(x => x.gscore).Sum();
  544. record.pscore = record.lessonRecords.Select(x => x.pscore).Sum();
  545. record.tscore = record.lessonRecords.Select(x => x.tscore).Sum();
  546. records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code)));
  547. }
  548. if (records.Any())
  549. {
  550. await Task.WhenAll(records);
  551. }
  552. if (overallEducations.Any())
  553. {
  554. foreach (var item in overallEducations) {
  555. await client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(item, partitionKey: new PartitionKey(item.code));
  556. string key = $"OverallEducation:{item.schoolCode}:{item.periodId}:{item.year}:{item.semesterId}:{item.classId}";
  557. await _azureRedis.GetRedisClient(8).HashSetAsync(key, item.studentId, item.ToJsonString());
  558. await _azureRedis.GetRedisClient(8).KeyExpireAsync(key,new TimeSpan(180 *24 ,0,0));
  559. }
  560. }
  561. }
  562. catch (Exception ex)
  563. {
  564. await _dingding.SendBotMsg($"学生个人课例统计信息异常,{ex.Message}\n{ex.StackTrace},{lessonRecord?.ToJsonString()}{school}", GroupNames.醍摩豆服務運維群組);
  565. }
  566. }
  567. public static async void DoAutoDeleteSchoolLessonRecord(LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid,
  568. Teacher teacher, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, CoreAPIHttpService _coreAPIHttpService,DingDing _dingDing,AzureRedisFactory _azureRedis)
  569. {
  570. if (lessonRecord.scope.Equals("school"))
  571. {
  572. SchoolSetting setting = null;
  573. Azure.Response schoolSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(school, new PartitionKey("SchoolSetting"));
  574. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  575. if (schoolSetting.Status == 200)
  576. {
  577. setting = JsonDocument.Parse(schoolSetting.Content).RootElement.Deserialize<SchoolSetting>();
  578. if (setting.lessonSetting != null)
  579. {
  580. //两种状态都不属于,则默认未开启。
  581. if (setting.lessonSetting.openAutoClean != 0 && setting.lessonSetting.openAutoClean != 1)
  582. {
  583. setting.lessonSetting.openAutoClean = 0;
  584. setting.lessonSetting.expireDays = Constant.school_lesson_expire;
  585. }
  586. else {
  587. //属于 要么开启1,要么关闭0
  588. }
  589. }
  590. else
  591. {
  592. setting.lessonSetting = new LessonSetting() { openAutoClean = 0, expireDays = Constant.school_lesson_expire };
  593. }
  594. }
  595. else
  596. {
  597. setting = new SchoolSetting() { lessonSetting = new LessonSetting { openAutoClean = 0, expireDays = Constant.school_lesson_expire } };
  598. }
  599. int school_lesson_expire = 0;
  600. bool save = true;
  601. List<string> msg = new List<string>();
  602. if (setting.lessonSetting.openAutoClean == 1)
  603. {
  604. if (setting.lessonSetting.conds.IsEmpty())
  605. {
  606. save = false;
  607. }
  608. else
  609. {
  610. school_lesson_expire = setting.lessonSetting.expireDays;
  611. foreach (var item in setting.lessonSetting.conds)
  612. {
  613. switch (item.type)
  614. {
  615. case ">=":
  616. switch (item.key)
  617. {
  618. case "attendRate":
  619. if (!(lessonRecord.attendRate >= item.val))
  620. {
  621. save = false;
  622. msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
  623. }
  624. break;
  625. case "groupCount":
  626. if (!(lessonRecord.groupCount >= item.val))
  627. {
  628. save = false;
  629. msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
  630. }
  631. break;
  632. case "totalPoint":
  633. if (!(lessonRecord.totalPoint >= item.val))
  634. {
  635. save = false;
  636. msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
  637. }
  638. break;
  639. case "collateTaskCount":
  640. if (!(lessonRecord.collateTaskCount >= item.val))
  641. {
  642. save = false;
  643. msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
  644. }
  645. break;
  646. case "collateCount":
  647. if (!(lessonRecord.collateCount >= item.val))
  648. {
  649. save = false;
  650. msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
  651. }
  652. break;
  653. case "pushCount":
  654. if (!(lessonRecord.pushCount >= item.val))
  655. {
  656. save = false;
  657. msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
  658. }
  659. break;
  660. case "totalInteractPoint":
  661. if (!(lessonRecord.totalInteractPoint >= item.val))
  662. {
  663. save = false;
  664. msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
  665. }
  666. break;
  667. case "interactionCount":
  668. if (!(lessonRecord.interactionCount >= item.val))
  669. {
  670. save = false;
  671. msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
  672. }
  673. break;
  674. case "clientInteractionCount":
  675. if (!(lessonRecord.clientInteractionCount >= item.val))
  676. {
  677. save = false;
  678. msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
  679. }
  680. break;
  681. case "examQuizCount":
  682. if (!(lessonRecord.examQuizCount >= item.val))
  683. {
  684. save = false;
  685. msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
  686. }
  687. break;
  688. case "examPointRate":
  689. if (!(lessonRecord.examPointRate >= item.val))
  690. {
  691. save = false;
  692. msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
  693. }
  694. break;
  695. }
  696. break;
  697. case "<=":
  698. switch (item.key)
  699. {
  700. case "attendRate":
  701. if (!(lessonRecord.attendRate <= item.val))
  702. {
  703. save = false;
  704. msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
  705. }
  706. break;
  707. case "groupCount":
  708. if (!(lessonRecord.groupCount <= item.val))
  709. {
  710. save = false;
  711. msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
  712. }
  713. break;
  714. case "totalPoint":
  715. if (!(lessonRecord.totalPoint <= item.val))
  716. {
  717. save = false;
  718. msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
  719. }
  720. break;
  721. case "collateTaskCount":
  722. if (!(lessonRecord.collateTaskCount <= item.val))
  723. {
  724. save = false;
  725. msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
  726. }
  727. break;
  728. case "collateCount":
  729. if (!(lessonRecord.collateCount <= item.val))
  730. {
  731. save = false;
  732. msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
  733. }
  734. break;
  735. case "pushCount":
  736. if (!(lessonRecord.pushCount <= item.val))
  737. {
  738. save = false;
  739. msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
  740. }
  741. break;
  742. case "totalInteractPoint":
  743. if (!(lessonRecord.totalInteractPoint <= item.val))
  744. {
  745. save = false;
  746. msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
  747. }
  748. break;
  749. case "interactionCount":
  750. if (!(lessonRecord.interactionCount <= item.val))
  751. {
  752. save = false;
  753. msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
  754. }
  755. break;
  756. case "clientInteractionCount":
  757. if (!(lessonRecord.clientInteractionCount <= item.val))
  758. {
  759. save = false;
  760. msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
  761. }
  762. break;
  763. case "examQuizCount":
  764. if (!(lessonRecord.examQuizCount <= item.val))
  765. {
  766. save = false;
  767. msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
  768. }
  769. break;
  770. case "examPointRate":
  771. if (!(lessonRecord.examPointRate <= item.val))
  772. {
  773. save = false;
  774. msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
  775. }
  776. break;
  777. }
  778. break;
  779. }
  780. }
  781. }
  782. }
  783. /* 注释start 2023.3.22,该段逻辑在开课的时候已经处理,详见ActiveTaskTopic. LessonRecordEvent create ,无论有没有开启setting.lessonSetting.openAutoClean 自动删除策略,只要空间不足都会对课例进行自动清理管理。
  784. else
  785. {
  786. ///未设置openAutoClean=1时,则检查学校使用空间是否充足。
  787. double usize = 0;
  788. int tsize = schoolBase.tsize;
  789. //schoolBase.tsize
  790. //計算學校或個人的使用空間
  791. RedisValue redisValue = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", $"{schoolBase.id}");
  792. if (redisValue.HasValue && long.TryParse(redisValue.ToString(), out var bsize))
  793. {
  794. usize = Math.Round(bsize / 1073741824.0 - (tsize), 2, MidpointRounding.AwayFromZero); //1073741824 1G
  795. }
  796. else //如果檢測不到緩存,觸發刷新計算空間
  797. {
  798. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = "records", name = $"{schoolBase.id}" }, _serviceBus, _configuration, _azureRedis);
  799. }
  800. ///空间充足的情况保存。
  801. if (schoolBase.size - usize > 0)
  802. {
  803. save = true;
  804. }
  805. else {
  806. save = false;
  807. school_lesson_expire = Constant.school_lesson_expire;
  808. }
  809. } 注释end 2023.3.22,该段逻辑在开课的时候已经处理,详见ActiveTaskTopic. LessonRecordEvent create ,无论有没有开启setting.lessonSetting.openAutoClean 自动删除策略,只要空间不足都会对课例进行自动清理管理。
  810. */
  811. if (!save && school_lesson_expire > 0)
  812. {
  813. // 1-时间戳,7-时间戳
  814. Dictionary<int, ExpireTag> result = new Dictionary<int, ExpireTag>();
  815. //暂定7天
  816. var now = DateTimeOffset.UtcNow;
  817. //剩余3天的通知
  818. //var day3= now.AddDays(school_lesson_expire - 3).ToUnixTimeMilliseconds();
  819. //result.Add(3, day3);
  820. //剩余1天的通知
  821. var day1 = now.AddDays(school_lesson_expire - (school_lesson_expire - 1)).ToUnixTimeMilliseconds();
  822. result.Add(1, new ExpireTag { expire = day1, tag = "notification" });
  823. //到期通知
  824. //不到五点上传的课例,七天之后直接删除。
  825. int addSecond = 0;
  826. if (now.Hour > 5)
  827. {
  828. // 到凌晨00点还差 (24 - now.Hour) *60 * 60 分钟,再加天数;
  829. addSecond = school_lesson_expire * 86400 + (24 - now.Hour) * 3600 - (now.Hour * 3600);
  830. //再加 00到05小时内的 随机秒数
  831. Random rand = new Random();
  832. int randInt = rand.Next(0, 18000);
  833. addSecond += randInt;
  834. }
  835. else
  836. {
  837. addSecond = school_lesson_expire * 24 * 60 * 60;
  838. }
  839. lessonRecord.expire = now.AddSeconds(addSecond).ToUnixTimeMilliseconds();
  840. result.Add(school_lesson_expire, new ExpireTag { expire = lessonRecord.expire, tag = "delete" });
  841. // result.Add(school_lesson_expire, lessonRecord.expire);
  842. string biz = "expire";
  843. string expireTime = DateTimeOffset.FromUnixTimeMilliseconds(lessonRecord.expire).ToString("yyyy-MM-dd HH:mm:ss");
  844. Teacher targetTeacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>($"{tmdid}", new PartitionKey($"Base"));
  845. _coreAPIHttpService.PushNotify(new List<IdNameCode> { new IdNameCode { id = targetTeacher.id, name = targetTeacher.name, code = targetTeacher.lang } }, "expire-school_lessonRecord", Constant.NotifyType_IES5_Course,
  846. new Dictionary<string, object> { { "tmdid", teacher.id }, { "tmdname", teacher.name }, { "schoolName", schoolBase.name },
  847. { "schoolId", $"{school}" },{ "lessonId",lessonRecord.id }, { "expireTime", expireTime },{ "lessonName",lessonRecord.name } }, $"{Environment.GetEnvironmentVariable("Option:Location")}", _configuration, _dingDing, "");
  848. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  849. List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
  850. if (records.Count <= 0)
  851. {
  852. foreach (var item in result)
  853. {
  854. string PartitionKey = string.Format("{0}{1}{2}", lessonRecord.code, "-", $"expire-{item.Key}");
  855. //课堂的id ,
  856. //课堂的通知时间类型progress, 默认就会发送一条,到期前一天发送一条,最后已到期发送一条。
  857. var message = new ServiceBusMessage(new
  858. {
  859. id = lessonRecord.id,
  860. progress = item.Key,
  861. code = lessonRecord.code,
  862. scope = lessonRecord.scope,
  863. school = lessonRecord.school,
  864. opt = "delete",
  865. expire = lessonRecord.expire,
  866. tmdid = tmdid,
  867. tmdname = teacher.name,
  868. name = lessonRecord.name,
  869. startTime = lessonRecord.startTime,
  870. tag = item.Value.tag
  871. }.ToJsonString());
  872. message.ApplicationProperties.Add("name", "LessonRecordExpire");
  873. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value.expire));
  874. ChangeRecord changeRecord = new ChangeRecord
  875. {
  876. RowKey = lessonRecord.id,
  877. PartitionKey = PartitionKey,
  878. sequenceNumber = start,
  879. msgId = message.MessageId
  880. };
  881. await table.Save<ChangeRecord>(changeRecord);
  882. }
  883. }
  884. }
  885. else
  886. {
  887. if (lessonRecord.expire > 0)
  888. {
  889. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  890. List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
  891. foreach (var record in records)
  892. {
  893. try
  894. {
  895. await table.DeleteSingle<ChangeRecord>(record.PartitionKey, record.RowKey);
  896. await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
  897. }
  898. catch (Exception)
  899. {
  900. continue;
  901. }
  902. }
  903. }
  904. lessonRecord.save = 1;
  905. lessonRecord.expire = -1;
  906. }
  907. }
  908. }
  909. public record ExpireTag
  910. {
  911. public long expire { get; set; }
  912. public string tag { get; set; }
  913. }
  914. /// <summary>
  915. ///
  916. /// </summary>
  917. /// <param name="client"></param>
  918. /// <param name="_dingDing"></param>
  919. /// <param name="data"></param>
  920. /// <returns></returns>
  921. public static LessonDis DisLessonCount(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis)
  922. {
  923. //创建课堂的情况
  924. if (oldRecord == null && newRecord != null)
  925. {
  926. lessonDis.record = 1;
  927. }
  928. //删除数据的情况
  929. //不再对LessonCount进行减
  930. else if (oldRecord != null && newRecord == null)
  931. {
  932. /*lessonDis.record = -1;
  933. //P分数量加减
  934. if (oldRecord.pScore >= 70)
  935. {
  936. lessonDis.disPCount = -1;
  937. }
  938. //T分数量加减
  939. if (oldRecord.tScore >= 70)
  940. {
  941. lessonDis.disTCount = -1;
  942. }
  943. if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70)
  944. {
  945. lessonDis.disTCount = -1;
  946. }*/
  947. }
  948. //无效操作
  949. else if (oldRecord == null && newRecord == null)
  950. {
  951. }
  952. //前后操作都有值,则表示更新
  953. else
  954. {
  955. //P分数量加减
  956. if (oldRecord.pScore >= 70)
  957. {
  958. if (newRecord.pScore < 70)
  959. {
  960. lessonDis.disPCount = -1;
  961. }
  962. }
  963. else
  964. {
  965. if (newRecord.pScore >= 70)
  966. {
  967. lessonDis.disPCount = 1;
  968. }
  969. }
  970. //T分数量加减
  971. if (oldRecord.tScore >= 70)
  972. {
  973. if (newRecord.tScore < 70)
  974. {
  975. lessonDis.disTCount = -1;
  976. }
  977. }
  978. else
  979. {
  980. if (newRecord.tScore >= 70)
  981. {
  982. lessonDis.disTCount = 1;
  983. }
  984. }
  985. //双绿灯数量
  986. if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70)
  987. {
  988. if (newRecord.tScore < 70 || newRecord.pScore < 70)
  989. {
  990. lessonDis.disDCount = -1;
  991. }
  992. }
  993. else
  994. {
  995. if (newRecord.tScore >= 70 && newRecord.pScore >= 70)
  996. {
  997. lessonDis.disDCount = 1;
  998. }
  999. }
  1000. }
  1001. return lessonDis;
  1002. }
  1003. public static LessonDis DisLessonCount_2(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis)
  1004. {
  1005. //创建课堂的情况
  1006. if (oldRecord == null && newRecord != null)
  1007. {
  1008. lessonDis.record = 1;
  1009. //P分数量加减
  1010. if (newRecord.pScore >= 70)
  1011. {
  1012. lessonDis.disPCount = 1;
  1013. }
  1014. //T分数量加减
  1015. if (newRecord.tScore >= 70)
  1016. {
  1017. lessonDis.disTCount = 1;
  1018. }
  1019. //双绿灯数量
  1020. if (newRecord.tScore >= 70 && newRecord.pScore >= 70)
  1021. {
  1022. lessonDis.disDCount = 1;
  1023. }
  1024. }
  1025. return lessonDis;
  1026. }
  1027. public static async Task FixLessonCount(CosmosClient client, DingDing _dingDing, LessonRecord record, LessonRecord oldRecord, LessonDis lessonDis)
  1028. {
  1029. LessonRecord data = null;
  1030. try
  1031. {
  1032. if (record != null && oldRecord == null)
  1033. {
  1034. data = record;
  1035. }
  1036. if (record == null && oldRecord != null)
  1037. {
  1038. data = oldRecord;
  1039. }
  1040. if (record != null && oldRecord != null)
  1041. {
  1042. data = record;
  1043. }
  1044. int day = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).DayOfYear;
  1045. int year = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).Year;
  1046. int days = DateTimeHelper.getDays(year);
  1047. //int years = DateTimeOffset.UtcNow.DayOfYear;
  1048. string tbname = string.Empty;
  1049. string code = string.Empty;
  1050. if (data.groupIds.Any()) {
  1051. if (data.scope != null && data.scope.Equals("school"))
  1052. {
  1053. if (string.IsNullOrEmpty(data.periodId))
  1054. {
  1055. code = $"LessonCount-{data.school}-{year}";
  1056. tbname = "School";
  1057. }
  1058. else
  1059. {
  1060. code = $"LessonCount-{data.school}-{year}-{data.periodId}";
  1061. tbname = "School";
  1062. }
  1063. }
  1064. else
  1065. {
  1066. code = $"LessonCount-{year}";
  1067. tbname = "Teacher";
  1068. }
  1069. var response = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(data.tmdid.ToString(), new PartitionKey(code));
  1070. if (response.Status == 200)
  1071. {
  1072. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  1073. LessonCount count = json.ToObject<LessonCount>();
  1074. count.tCount[day - 1] += lessonDis.disTCount;
  1075. count.pCount[day - 1] += lessonDis.disPCount;
  1076. count.ptCount[day - 1] += lessonDis.disDCount;
  1077. count.beginCount[day - 1] += lessonDis.record;
  1078. await client.GetContainer("TEAMModelOS", tbname).ReplaceItemAsync(count, count.id, new PartitionKey(code));
  1079. }
  1080. else
  1081. {
  1082. LessonCount count = new()
  1083. {
  1084. id = data.tmdid,
  1085. code = code,
  1086. ttl = -1
  1087. };
  1088. double[] da = new double[days];
  1089. List<double> list = new(da);
  1090. List<double> listT = new(da);
  1091. List<double> listP = new(da);
  1092. List<double> listPT = new(da);
  1093. list[day - 1] += lessonDis.record;
  1094. listT[day - 1] += lessonDis.disTCount;
  1095. listP[day - 1] += lessonDis.disPCount;
  1096. listPT[day - 1] += lessonDis.disDCount;
  1097. count.beginCount.AddRange(list);
  1098. count.tCount.AddRange(listT);
  1099. count.pCount.AddRange(listP);
  1100. count.ptCount.AddRange(listPT);
  1101. //count.courseIds.Add(data.courseId);
  1102. await client.GetContainer("TEAMModelOS", tbname).CreateItemAsync(count, new PartitionKey(code));
  1103. }
  1104. }
  1105. }
  1106. catch (Exception ex)
  1107. {
  1108. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-LessonCount-FixLessonCount\n{ex.Message}\n{ex.StackTrace}{data.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  1109. }
  1110. }
  1111. }
  1112. }