LessonService.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. using Azure.Cosmos;
  2. using Azure.Messaging.ServiceBus;
  3. using HTEXLib.COMM.Helpers;
  4. using Microsoft.Extensions.Configuration;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.SDK.DI;
  12. using TEAMModelOS.SDK.DI.CoreAPI;
  13. using TEAMModelOS.SDK.Extension;
  14. using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
  15. using TEAMModelOS.SDK.Models.Cosmos.Common;
  16. namespace TEAMModelOS.SDK.Models.Service
  17. {
  18. public class LessonService
  19. {
  20. public static readonly DateTime dateTime1970 = new DateTime(1970, 1, 1).ToLocalTime();
  21. public static Dictionary<string, object> GetLessonCond(JsonElement request)
  22. {
  23. Dictionary<string, object> dict = new Dictionary<string, object>();
  24. if (request.TryGetProperty("tmdid", out JsonElement tmdid) && !string.IsNullOrWhiteSpace($"{tmdid}"))
  25. {
  26. dict.Add("tmdid", tmdid);
  27. }
  28. if (request.TryGetProperty("courseId", out JsonElement courseId) && !string.IsNullOrWhiteSpace($"{courseId}"))
  29. {
  30. dict.Add("courseId", courseId);
  31. }
  32. if (request.TryGetProperty("courseIds", out JsonElement courseIds))
  33. {
  34. dict.Add("courseId[*]", courseIds);
  35. }
  36. if (request.TryGetProperty("periodId", out JsonElement periodId) && !string.IsNullOrWhiteSpace($"{periodId}"))
  37. {
  38. dict.Add("periodId", periodId);
  39. }
  40. if (request.TryGetProperty("subjectId", out JsonElement subjectId))
  41. {
  42. dict.Add("subjectId", subjectId);
  43. }
  44. if (request.TryGetProperty("groupIds", out JsonElement groupIds))
  45. {
  46. dict.Add("groupIds[*]", groupIds);
  47. }
  48. if (request.TryGetProperty("grade", out JsonElement grade))
  49. {
  50. dict.Add("grade[*]", grade);
  51. }
  52. if (request.TryGetProperty("category", out JsonElement category))
  53. {
  54. dict.Add("category[*]", category);
  55. }
  56. if (request.TryGetProperty("doubleGreen", out JsonElement doubleGreen) && doubleGreen.GetBoolean())
  57. {
  58. dict.Add(">=.tScore", 70);
  59. dict.Add(">=.pScore", 70);
  60. }
  61. if (request.TryGetProperty("quality", out JsonElement quality) && quality.GetBoolean())
  62. {
  63. dict.Add(">=.discuss", 1);
  64. }
  65. if (request.TryGetProperty("excellent", out JsonElement excellent) && excellent.GetBoolean())
  66. {
  67. dict.Add(">=.excellent", 1);
  68. }
  69. if (request.TryGetProperty("name", out JsonElement name) && !string.IsNullOrWhiteSpace($"{name}"))
  70. {
  71. dict.Add("$.name", name);
  72. }
  73. if (request.TryGetProperty("today", out JsonElement today) && today.GetBoolean())
  74. {
  75. DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  76. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(1);
  77. double dayOf00_00_00 = (dateTimeA - dateTime1970).TotalMilliseconds;
  78. double day1Of00_00_00 = (dateTimeB - dateTime1970).TotalMilliseconds;
  79. dict.Add(">=.startTime", dayOf00_00_00);
  80. dict.Add("<.startTime", day1Of00_00_00);
  81. }
  82. if (request.TryGetProperty("week", out JsonElement week) && week.GetBoolean())
  83. {
  84. // DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  85. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-7);
  86. double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  87. double dayB = (dateTimeB - dateTime1970).TotalMilliseconds;
  88. dict.Add("<=.startTime", now);
  89. dict.Add(">=.startTime", dayB);
  90. }
  91. //查询即将到期的且没有被清理的。
  92. if (request.TryGetProperty("expire", out JsonElement expire) && expire.ValueKind.Equals(JsonValueKind.True))
  93. {
  94. dict.Add(">.expire", 0);
  95. dict.Add("!=.status", 404);
  96. }
  97. //查询已经清理的
  98. if (request.TryGetProperty("is404", out JsonElement is404) && is404.ValueKind.Equals(JsonValueKind.True))
  99. {
  100. dict.Add("=.status", 404);
  101. }
  102. //只查有效的
  103. if (request.TryGetProperty("isOk", out JsonElement isOk) && isOk.ValueKind.Equals(JsonValueKind.True))
  104. {
  105. dict.Add("<=.expire", 0);
  106. dict.Add("!=.status", 404);
  107. }
  108. if (request.TryGetProperty("month", out JsonElement month) && month.GetBoolean())
  109. {
  110. //DateTime dateTimeA = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D"));
  111. DateTime dateTimeB = Convert.ToDateTime(DateTimeOffset.UtcNow.ToString("D")).AddDays(-30);
  112. double now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  113. double dayB = (dateTimeB - dateTime1970).TotalMilliseconds;
  114. dict.Add("<=.startTime", now);
  115. dict.Add(">=.startTime", dayB);
  116. }
  117. if (request.TryGetProperty("stime", out JsonElement stime) && !string.IsNullOrWhiteSpace($"{stime}"))
  118. {
  119. dict.Add(">=.startTime", stime);
  120. }
  121. if (request.TryGetProperty("etime", out JsonElement etime) && !string.IsNullOrWhiteSpace($"{etime}"))
  122. {
  123. dict.Add("<=.startTime", etime);
  124. }
  125. if (request.TryGetProperty("conds", out JsonElement conds) && conds.ValueKind.Equals(JsonValueKind.Array))
  126. {
  127. List<LessonSettingCond> settingConds = conds.Deserialize<List<LessonSettingCond>>();
  128. foreach (var item in settingConds)
  129. {
  130. dict.TryAdd($"{item.type}.{item.key}", item.val);
  131. //switch (item.type)
  132. //{
  133. // case ">=":
  134. // dict.TryAdd($">=.{item.key}",item.val);
  135. // break;
  136. // case "<=":
  137. // dict.TryAdd($"<=.{item.key}", item.val);
  138. // break;
  139. //}
  140. }
  141. }
  142. return dict;
  143. }
  144. public static async void DoLessonStudentRecord(DingDing _dingding, SnowflakeId snowflakeId, LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid,
  145. Teacher teacher, NotificationService _notificationService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration, LessonBase lessonBase)
  146. {
  147. try
  148. {
  149. int year = DateTimeOffset.UtcNow.Year;
  150. var clientSummaryList = lessonBase.report.clientSummaryList.Where(x => x.groupTaskCompleteCount != 0 || x.groupScore != 0 || x.score != 0 || x.tnteractScore != 0 || x.taskCompleteCount != 0);
  151. IEnumerable<LessonStudent> students = new List<LessonStudent>();
  152. if (clientSummaryList.Any())
  153. {
  154. students = lessonBase.student.Where(x => clientSummaryList.Select(x => x.seatID).Contains(x.seatID));
  155. }
  156. var stuids = students.Where(x => x.type == 2);
  157. if (stuids.Any())
  158. {
  159. stuids.ToList().ForEach(x => {
  160. x.school = string.IsNullOrWhiteSpace(x.school) ? school : x.school;
  161. });
  162. }
  163. var groups = stuids.Where(z => !string.IsNullOrWhiteSpace(z.school)).GroupBy(x => x.school).Select(y => new { code = y.Key, list = y.ToList() });
  164. List<StudentScoreRecord> lessonStudentRecords = new List<StudentScoreRecord>();
  165. foreach (var group in groups)
  166. {
  167. 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}";
  168. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentScoreRecord>(queryText: stusql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") }))
  169. {
  170. lessonStudentRecords.Add(item);
  171. }
  172. }
  173. var tmdids = students.Where(x => x.type == 1);
  174. if (tmdids.Any())
  175. {
  176. string tmdsql = $"select value(c) from c where c.tmdid in({string.Join(",", tmdids.Select(x => $"'{x}'"))}) and c.year={year}";
  177. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentScoreRecord>(queryText: tmdsql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"StudentScoreRecord") }))
  178. {
  179. lessonStudentRecords.Add(item);
  180. }
  181. }
  182. List<Task<ItemResponse<StudentScoreRecord>>> records = new List<Task<ItemResponse<StudentScoreRecord>>>();
  183. stuids.ToList().ForEach(x => {
  184. var record = lessonStudentRecords.Find(l => l.stuid.Equals(x.id) && l.code.Equals($"StudentScoreRecord") && l.school.Equals(x.school));
  185. ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID);
  186. if (record != null)
  187. {
  188. if (clientSummaryList != null)
  189. {
  190. var hasrecord= record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id));
  191. if (hasrecord != null)
  192. {
  193. hasrecord.gscore = clientSummaryList.groupScore;
  194. hasrecord.pscore = clientSummaryList.score;
  195. hasrecord.tscore = clientSummaryList.tnteractScore;
  196. hasrecord.tmdid = teacher.id;
  197. hasrecord.school = school;
  198. hasrecord.scope = lessonRecord.scope;
  199. hasrecord.lessonId = lessonRecord.id;
  200. hasrecord.courseId = lessonRecord.courseId;
  201. hasrecord.periodId = lessonRecord.periodId;
  202. hasrecord.subjectId = lessonRecord.subjectId;
  203. hasrecord.time = lessonRecord.startTime;
  204. }
  205. else {
  206. record.lessonRecords.Add(
  207. new StudentLessonRecord
  208. {
  209. gscore = clientSummaryList.groupScore,
  210. pscore = clientSummaryList.score,
  211. tscore = clientSummaryList.tnteractScore,
  212. tmdid = teacher.id,
  213. school = school,
  214. scope = lessonRecord.scope,
  215. lessonId = lessonRecord.id,
  216. courseId = lessonRecord.courseId,
  217. periodId = lessonRecord.periodId,
  218. subjectId = lessonRecord.subjectId,
  219. time = lessonRecord.startTime
  220. }
  221. );
  222. }
  223. }
  224. }
  225. else
  226. {
  227. record = new StudentScoreRecord
  228. {
  229. userType = Constant.ScopeStudent,
  230. id = $"{snowflakeId.NextId()}",
  231. year = year,
  232. stuid = x.id,
  233. school = x.school,
  234. code = $"StudentScoreRecord",
  235. pk = "StudentScoreRecord",
  236. ttl = -1,
  237. lessonRecords = new List<StudentLessonRecord> { new StudentLessonRecord
  238. {
  239. gscore = clientSummaryList.groupScore,
  240. pscore = clientSummaryList.score,
  241. tscore = clientSummaryList.tnteractScore,
  242. tmdid = teacher.id,
  243. school = school,
  244. scope = lessonRecord.scope,
  245. lessonId = lessonRecord.id,
  246. courseId = lessonRecord.courseId,
  247. periodId = lessonRecord.periodId,
  248. subjectId = lessonRecord.subjectId,
  249. time= lessonRecord.startTime
  250. }}
  251. };
  252. }
  253. record.userType = Constant.ScopeStudent;
  254. record.gscore = record.lessonRecords.Select(x => x.gscore).Sum();
  255. record.pscore = record.lessonRecords.Select(x => x.pscore).Sum();
  256. record.tscore = record.lessonRecords.Select(x => x.tscore).Sum();
  257. records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code)));
  258. });
  259. tmdids.ToList().ForEach(x => {
  260. var record = lessonStudentRecords.Find(l => l.tmdid.Equals(x.id) && l.code.Equals($"StudentScoreRecord"));
  261. ClientSummaryList clientSummaryList = lessonBase.report.clientSummaryList.Find(c => c.seatID == x.seatID);
  262. if (record != null)
  263. {
  264. if (clientSummaryList != null)
  265. {
  266. var hasrecord = record.lessonRecords.Find(x => x.lessonId.Equals(lessonRecord.id));
  267. if (hasrecord != null)
  268. {
  269. hasrecord.gscore = clientSummaryList.groupScore;
  270. hasrecord.pscore = clientSummaryList.score;
  271. hasrecord.tscore = clientSummaryList.tnteractScore;
  272. hasrecord.tmdid = teacher.id;
  273. hasrecord.school = school;
  274. hasrecord.scope = lessonRecord.scope;
  275. hasrecord.lessonId = lessonRecord.id;
  276. hasrecord.courseId = lessonRecord.courseId;
  277. hasrecord.periodId = lessonRecord.periodId;
  278. hasrecord.subjectId = lessonRecord.subjectId;
  279. hasrecord.time = lessonRecord.startTime;
  280. }
  281. else
  282. {
  283. record.lessonRecords.Add(
  284. new StudentLessonRecord
  285. {
  286. gscore = clientSummaryList.groupScore,
  287. pscore = clientSummaryList.score,
  288. tscore = clientSummaryList.tnteractScore,
  289. tmdid = teacher.id,
  290. school = school,
  291. scope = lessonRecord.scope,
  292. lessonId = lessonRecord.id,
  293. courseId = lessonRecord.courseId,
  294. periodId = lessonRecord.periodId,
  295. subjectId = lessonRecord.subjectId,
  296. time = lessonRecord.startTime
  297. }
  298. );
  299. }
  300. }
  301. }
  302. else
  303. {
  304. record = new StudentScoreRecord
  305. {
  306. userType = Constant.ScopeTmdUser,
  307. id = $"{snowflakeId.NextId()}",
  308. code = $"StudentScoreRecord",
  309. pk = "StudentScoreRecord",
  310. ttl = -1,
  311. year = year,
  312. tmdid = x.id,
  313. lessonRecords = new List<StudentLessonRecord>
  314. {
  315. new StudentLessonRecord
  316. {
  317. gscore = clientSummaryList.groupScore,
  318. pscore = clientSummaryList.score,
  319. tscore = clientSummaryList.tnteractScore,
  320. tmdid = teacher.id,
  321. school = school,
  322. scope = lessonRecord.scope,
  323. lessonId = lessonRecord.id,
  324. courseId = lessonRecord.courseId,
  325. periodId = lessonRecord.periodId,
  326. subjectId = lessonRecord.subjectId,
  327. time=lessonRecord.startTime
  328. }
  329. }
  330. };
  331. }
  332. record.userType = Constant.ScopeStudent;
  333. record.gscore = record.lessonRecords.Select(x => x.gscore).Sum();
  334. record.pscore = record.lessonRecords.Select(x => x.pscore).Sum();
  335. record.tscore = record.lessonRecords.Select(x => x.tscore).Sum();
  336. records.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(record, partitionKey: new PartitionKey(record.code)));
  337. });
  338. if (records.Any())
  339. {
  340. await Task.WhenAll(records);
  341. }
  342. }
  343. catch (Exception ex)
  344. {
  345. await _dingding.SendBotMsg($"学生个人课例统计信息异常,{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  346. }
  347. }
  348. public static async void DoAutoDeleteSchoolLessonRecord(LessonRecord lessonRecord, string scope, CosmosClient client, string school, string tmdid,
  349. Teacher teacher, NotificationService _notificationService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, IConfiguration _configuration)
  350. {
  351. if (lessonRecord.scope.Equals("school"))
  352. {
  353. SchoolSetting setting = null;
  354. Azure.Response schoolSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(school, new PartitionKey("SchoolSetting"));
  355. School schoolBase = await client.GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  356. if (schoolSetting.Status == 200)
  357. {
  358. setting = JsonDocument.Parse(schoolSetting.Content).RootElement.Deserialize<SchoolSetting>();
  359. if (setting.lessonSetting != null)
  360. {
  361. if (setting.lessonSetting.openAutoClean != 0 && setting.lessonSetting.openAutoClean != 1)
  362. {
  363. setting.lessonSetting.openAutoClean = 0;
  364. setting.lessonSetting.expireDays = Constant.school_lesson_expire;
  365. }
  366. }
  367. else
  368. {
  369. setting.lessonSetting = new LessonSetting() { openAutoClean = 0, expireDays = Constant.school_lesson_expire };
  370. }
  371. }
  372. else
  373. {
  374. setting = new SchoolSetting() { lessonSetting = new LessonSetting { openAutoClean = 0, expireDays = Constant.school_lesson_expire } };
  375. }
  376. int school_lesson_expire = 0;
  377. bool save = true;
  378. List<string> msg = new List<string>();
  379. if (setting.lessonSetting.openAutoClean == 1)
  380. {
  381. if (setting.lessonSetting.conds.IsEmpty())
  382. {
  383. save = false;
  384. }
  385. else
  386. {
  387. school_lesson_expire = setting.lessonSetting.expireDays;
  388. foreach (var item in setting.lessonSetting.conds)
  389. {
  390. switch (item.type)
  391. {
  392. case ">=":
  393. switch (item.key)
  394. {
  395. case "attendRate":
  396. if (!(lessonRecord.attendRate >= item.val))
  397. {
  398. save = false;
  399. msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
  400. }
  401. break;
  402. case "groupCount":
  403. if (!(lessonRecord.groupCount >= item.val))
  404. {
  405. save = false;
  406. msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
  407. }
  408. break;
  409. case "totalPoint":
  410. if (!(lessonRecord.totalPoint >= item.val))
  411. {
  412. save = false;
  413. msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
  414. }
  415. break;
  416. case "collateTaskCount":
  417. if (!(lessonRecord.collateTaskCount >= item.val))
  418. {
  419. save = false;
  420. msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
  421. }
  422. break;
  423. case "collateCount":
  424. if (!(lessonRecord.collateCount >= item.val))
  425. {
  426. save = false;
  427. msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
  428. }
  429. break;
  430. case "pushCount":
  431. if (!(lessonRecord.pushCount >= item.val))
  432. {
  433. save = false;
  434. msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
  435. }
  436. break;
  437. case "totalInteractPoint":
  438. if (!(lessonRecord.totalInteractPoint >= item.val))
  439. {
  440. save = false;
  441. msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
  442. }
  443. break;
  444. case "interactionCount":
  445. if (!(lessonRecord.interactionCount >= item.val))
  446. {
  447. save = false;
  448. msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
  449. }
  450. break;
  451. case "clientInteractionCount":
  452. if (!(lessonRecord.clientInteractionCount >= item.val))
  453. {
  454. save = false;
  455. msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
  456. }
  457. break;
  458. case "examQuizCount":
  459. if (!(lessonRecord.examQuizCount >= item.val))
  460. {
  461. save = false;
  462. msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
  463. }
  464. break;
  465. case "examPointRate":
  466. if (!(lessonRecord.examPointRate >= item.val))
  467. {
  468. save = false;
  469. msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
  470. }
  471. break;
  472. }
  473. break;
  474. case "<=":
  475. switch (item.key)
  476. {
  477. case "attendRate":
  478. if (!(lessonRecord.attendRate <= item.val))
  479. {
  480. save = false;
  481. msg.Add($"{item.key}:{lessonRecord.attendRate}{item.type}{item.val}");
  482. }
  483. break;
  484. case "groupCount":
  485. if (!(lessonRecord.groupCount <= item.val))
  486. {
  487. save = false;
  488. msg.Add($"{item.key}:{lessonRecord.groupCount}{item.type}{item.val}");
  489. }
  490. break;
  491. case "totalPoint":
  492. if (!(lessonRecord.totalPoint <= item.val))
  493. {
  494. save = false;
  495. msg.Add($"{item.key}:{lessonRecord.totalPoint}{item.type}{item.val}");
  496. }
  497. break;
  498. case "collateTaskCount":
  499. if (!(lessonRecord.collateTaskCount <= item.val))
  500. {
  501. save = false;
  502. msg.Add($"{item.key}:{lessonRecord.collateTaskCount}{item.type}{item.val}");
  503. }
  504. break;
  505. case "collateCount":
  506. if (!(lessonRecord.collateCount <= item.val))
  507. {
  508. save = false;
  509. msg.Add($"{item.key}:{lessonRecord.collateCount}{item.type}{item.val}");
  510. }
  511. break;
  512. case "pushCount":
  513. if (!(lessonRecord.pushCount <= item.val))
  514. {
  515. save = false;
  516. msg.Add($"{item.key}:{lessonRecord.pushCount}{item.type}{item.val}");
  517. }
  518. break;
  519. case "totalInteractPoint":
  520. if (!(lessonRecord.totalInteractPoint <= item.val))
  521. {
  522. save = false;
  523. msg.Add($"{item.key}:{lessonRecord.totalInteractPoint}{item.type}{item.val}");
  524. }
  525. break;
  526. case "interactionCount":
  527. if (!(lessonRecord.interactionCount <= item.val))
  528. {
  529. save = false;
  530. msg.Add($"{item.key}:{lessonRecord.interactionCount}{item.type}{item.val}");
  531. }
  532. break;
  533. case "clientInteractionCount":
  534. if (!(lessonRecord.clientInteractionCount <= item.val))
  535. {
  536. save = false;
  537. msg.Add($"{item.key}:{lessonRecord.clientInteractionCount}{item.type}{item.val}");
  538. }
  539. break;
  540. case "examQuizCount":
  541. if (!(lessonRecord.examQuizCount <= item.val))
  542. {
  543. save = false;
  544. msg.Add($"{item.key}:{lessonRecord.examQuizCount}{item.type}{item.val}");
  545. }
  546. break;
  547. case "examPointRate":
  548. if (!(lessonRecord.examPointRate <= item.val))
  549. {
  550. save = false;
  551. msg.Add($"{item.key}:{lessonRecord.examPointRate}{item.type}{item.val}");
  552. }
  553. break;
  554. }
  555. break;
  556. }
  557. }
  558. }
  559. }
  560. else
  561. {
  562. save = false;
  563. school_lesson_expire = Constant.school_lesson_expire;
  564. }
  565. if (!save && school_lesson_expire > 0)
  566. {
  567. // 1-时间戳,7-时间戳
  568. Dictionary<int, ExpireTag> result = new Dictionary<int, ExpireTag>();
  569. //暂定7天
  570. var now = DateTimeOffset.UtcNow;
  571. //剩余3天的通知
  572. //var day3= now.AddDays(school_lesson_expire - 3).ToUnixTimeMilliseconds();
  573. //result.Add(3, day3);
  574. //剩余1天的通知
  575. var day1 = now.AddDays(school_lesson_expire - (school_lesson_expire - 1)).ToUnixTimeMilliseconds();
  576. result.Add(1, new ExpireTag { expire = day1, tag = "notification" });
  577. //到期通知
  578. //不到五点上传的课例,七天之后直接删除。
  579. int addSecond = 0;
  580. if (now.Hour > 5)
  581. {
  582. // 到凌晨00点还差 (24 - now.Hour) *60 * 60 分钟,再加天数;
  583. addSecond = school_lesson_expire * 86400 + (24 - now.Hour) * 3600 - (now.Hour * 3600);
  584. //再加 00到05小时内的 随机秒数
  585. Random rand = new Random();
  586. int randInt = rand.Next(0, 18000);
  587. addSecond += randInt;
  588. }
  589. else
  590. {
  591. addSecond = school_lesson_expire * 24 * 60 * 60;
  592. }
  593. lessonRecord.expire = now.AddSeconds(addSecond).ToUnixTimeMilliseconds();
  594. result.Add(school_lesson_expire, new ExpireTag { expire = lessonRecord.expire, tag = "delete" });
  595. // result.Add(school_lesson_expire, lessonRecord.expire);
  596. string biz = "expire";
  597. Notification notification = new Notification
  598. {
  599. hubName = "hita",
  600. type = "msg",
  601. from = $"ies5:{Environment.GetEnvironmentVariable("Option:Location")}:private",
  602. to = new List<string> { tmdid },
  603. label = $"{biz}_lessonRecord",
  604. body = new
  605. {
  606. location = $"{Environment.GetEnvironmentVariable("Option:Location")}",
  607. biz = biz,
  608. tmdid = tmdid,
  609. tmdname = teacher.name,
  610. scope = scope,
  611. school = school,
  612. schoolName = schoolBase.name,
  613. sid = lessonRecord.id,
  614. sname = lessonRecord.name,
  615. stime = lessonRecord.startTime,
  616. expire = lessonRecord.expire,
  617. status = 1,
  618. //day = school_lesson_expire,
  619. time = now
  620. }.ToJsonString(),
  621. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  622. };
  623. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  624. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  625. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  626. var location = $"{Environment.GetEnvironmentVariable("Option:Location")}";
  627. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
  628. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  629. List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
  630. if (records.Count <= 0)
  631. {
  632. foreach (var item in result)
  633. {
  634. string PartitionKey = string.Format("{0}{1}{2}", lessonRecord.code, "-", $"expire-{item.Key}");
  635. //课堂的id ,
  636. //课堂的通知时间类型progress, 默认就会发送一条,到期前一天发送一条,最后已到期发送一条。
  637. var message = new ServiceBusMessage(new
  638. {
  639. id = lessonRecord.id,
  640. progress = item.Key,
  641. code = lessonRecord.code,
  642. scope = lessonRecord.scope,
  643. school = lessonRecord.school,
  644. opt = "delete",
  645. expire = lessonRecord.expire,
  646. tmdid = tmdid,
  647. tmdname = teacher.name,
  648. name = lessonRecord.name,
  649. startTime = lessonRecord.startTime,
  650. tag = item.Value.tag
  651. }.ToJsonString());
  652. message.ApplicationProperties.Add("name", "LessonRecordExpire");
  653. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), message, DateTimeOffset.FromUnixTimeMilliseconds(item.Value.expire));
  654. ChangeRecord changeRecord = new ChangeRecord
  655. {
  656. RowKey = lessonRecord.id,
  657. PartitionKey = PartitionKey,
  658. sequenceNumber = start,
  659. msgId = message.MessageId
  660. };
  661. await table.Save<ChangeRecord>(changeRecord);
  662. }
  663. }
  664. }
  665. else
  666. {
  667. if (lessonRecord.expire > 0)
  668. {
  669. var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
  670. List<ChangeRecord> records = await table.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", lessonRecord.id } });
  671. foreach (var record in records)
  672. {
  673. try
  674. {
  675. await table.DeleteSingle<ChangeRecord>(record.PartitionKey, record.RowKey);
  676. await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
  677. }
  678. catch (Exception)
  679. {
  680. continue;
  681. }
  682. }
  683. }
  684. lessonRecord.save = 1;
  685. lessonRecord.expire = -1;
  686. }
  687. }
  688. }
  689. public record ExpireTag
  690. {
  691. public long expire { get; set; }
  692. public string tag { get; set; }
  693. }
  694. /// <summary>
  695. ///
  696. /// </summary>
  697. /// <param name="client"></param>
  698. /// <param name="_dingDing"></param>
  699. /// <param name="data"></param>
  700. /// <returns></returns>
  701. public static LessonDis DisLessonCount(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis)
  702. {
  703. //创建课堂的情况
  704. if (oldRecord == null && newRecord != null)
  705. {
  706. lessonDis.record = 1;
  707. }
  708. //删除数据的情况
  709. //不再对LessonCount进行减
  710. else if (oldRecord != null && newRecord == null)
  711. {
  712. /*lessonDis.record = -1;
  713. //P分数量加减
  714. if (oldRecord.pScore >= 70)
  715. {
  716. lessonDis.disPCount = -1;
  717. }
  718. //T分数量加减
  719. if (oldRecord.tScore >= 70)
  720. {
  721. lessonDis.disTCount = -1;
  722. }
  723. if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70)
  724. {
  725. lessonDis.disTCount = -1;
  726. }*/
  727. }
  728. //无效操作
  729. else if (oldRecord == null && newRecord == null)
  730. {
  731. }
  732. //前后操作都有值,则表示更新
  733. else
  734. {
  735. //P分数量加减
  736. if (oldRecord.pScore >= 70)
  737. {
  738. if (newRecord.pScore < 70)
  739. {
  740. lessonDis.disPCount = -1;
  741. }
  742. }
  743. else
  744. {
  745. if (newRecord.pScore >= 70)
  746. {
  747. lessonDis.disPCount = 1;
  748. }
  749. }
  750. //T分数量加减
  751. if (oldRecord.tScore >= 70)
  752. {
  753. if (newRecord.tScore < 70)
  754. {
  755. lessonDis.disTCount = -1;
  756. }
  757. }
  758. else
  759. {
  760. if (newRecord.tScore >= 70)
  761. {
  762. lessonDis.disTCount = 1;
  763. }
  764. }
  765. //双绿灯数量
  766. if (oldRecord.tScore >= 70 && oldRecord.pScore >= 70)
  767. {
  768. if (newRecord.tScore < 70 || newRecord.pScore < 70)
  769. {
  770. lessonDis.disDCount = -1;
  771. }
  772. }
  773. else
  774. {
  775. if (newRecord.tScore >= 70 && newRecord.pScore >= 70)
  776. {
  777. lessonDis.disDCount = 1;
  778. }
  779. }
  780. }
  781. return lessonDis;
  782. }
  783. public static LessonDis DisLessonCount_2(LessonRecord oldRecord, LessonRecord newRecord, LessonDis lessonDis)
  784. {
  785. //创建课堂的情况
  786. if (oldRecord == null && newRecord != null)
  787. {
  788. lessonDis.record = 1;
  789. //P分数量加减
  790. if (newRecord.pScore >= 70)
  791. {
  792. lessonDis.disPCount = 1;
  793. }
  794. //T分数量加减
  795. if (newRecord.tScore >= 70)
  796. {
  797. lessonDis.disTCount = 1;
  798. }
  799. //双绿灯数量
  800. if (newRecord.tScore >= 70 && newRecord.pScore >= 70)
  801. {
  802. lessonDis.disDCount = 1;
  803. }
  804. }
  805. return lessonDis;
  806. }
  807. public static async Task FixLessonCount(CosmosClient client, DingDing _dingDing, LessonRecord record, LessonRecord oldRecord, LessonDis lessonDis)
  808. {
  809. LessonRecord data = null;
  810. try
  811. {
  812. if (record != null && oldRecord == null)
  813. {
  814. data = record;
  815. }
  816. if (record == null && oldRecord != null)
  817. {
  818. data = oldRecord;
  819. }
  820. if (record != null && oldRecord != null)
  821. {
  822. data = record;
  823. }
  824. int day = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).DayOfYear;
  825. int year = DateTimeOffset.FromUnixTimeMilliseconds(data.startTime).Year;
  826. int days = DateTimeHelper.getDays(year);
  827. //int years = DateTimeOffset.UtcNow.DayOfYear;
  828. string tbname = string.Empty;
  829. string code = string.Empty;
  830. if (data.scope != null && data.scope.Equals("school"))
  831. {
  832. if (string.IsNullOrEmpty(data.periodId))
  833. {
  834. code = $"LessonCount-{data.school}-{year}";
  835. tbname = "School";
  836. }
  837. else
  838. {
  839. code = $"LessonCount-{data.school}-{year}-{data.periodId}";
  840. tbname = "School";
  841. }
  842. }
  843. else
  844. {
  845. code = $"LessonCount-{year}";
  846. tbname = "Teacher";
  847. }
  848. var response = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(data.tmdid.ToString(), new PartitionKey(code));
  849. if (response.Status == 200)
  850. {
  851. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  852. LessonCount count = json.ToObject<LessonCount>();
  853. count.tCount[day - 1] += lessonDis.disTCount;
  854. count.pCount[day - 1] += lessonDis.disPCount;
  855. count.ptCount[day - 1] += lessonDis.disDCount;
  856. count.beginCount[day - 1] += lessonDis.record;
  857. await client.GetContainer("TEAMModelOS", tbname).ReplaceItemAsync(count, count.id, new PartitionKey(code));
  858. }
  859. else
  860. {
  861. LessonCount count = new()
  862. {
  863. id = data.tmdid,
  864. code = code,
  865. ttl = -1
  866. };
  867. double[] da = new double[days];
  868. List<double> list = new(da);
  869. List<double> listT = new(da);
  870. List<double> listP = new(da);
  871. List<double> listPT = new(da);
  872. list[day - 1] += lessonDis.record;
  873. listT[day - 1] += lessonDis.disTCount;
  874. listP[day - 1] += lessonDis.disPCount;
  875. listPT[day - 1] += lessonDis.disDCount;
  876. count.beginCount.AddRange(list);
  877. count.tCount.AddRange(listT);
  878. count.pCount.AddRange(listP);
  879. count.ptCount.AddRange(listPT);
  880. //count.courseIds.Add(data.courseId);
  881. await client.GetContainer("TEAMModelOS", tbname).CreateItemAsync(count, new PartitionKey(code));
  882. }
  883. }
  884. catch (Exception ex)
  885. {
  886. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-LessonCount-FixLessonCount\n{ex.Message}\n{ex.StackTrace}{data.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  887. }
  888. }
  889. }
  890. }