LessonService.cs 47 KB

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