LessonService.cs 46 KB

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