LessonController.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. using Azure.Cosmos;
  2. using MathNet.Numerics.LinearAlgebra.Double;
  3. using Microsoft.AspNetCore.Http;
  4. using Microsoft.AspNetCore.Mvc;
  5. using StackExchange.Redis;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text.Json;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using TEAMModelBI.Tool;
  13. using TEAMModelOS.SDK.Context.BI;
  14. using TEAMModelOS.SDK.DI;
  15. using TEAMModelOS.SDK.Extension;
  16. using TEAMModelOS.SDK.Models;
  17. using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
  18. using TEAMModelOS.SDK.Models.Cosmos.BI.BITable;
  19. using TEAMModelOS.SDK.Models.Service.BI;
  20. namespace TEAMModelBI.Controllers.BISchool
  21. {
  22. [Route("Lesson")]
  23. [ApiController]
  24. public class LessonController : ControllerBase
  25. {
  26. private readonly AzureCosmosFactory _azureCosmos;
  27. private readonly AzureStorageFactory _azureStorage;
  28. private readonly AzureRedisFactory _azureRedis;
  29. private readonly DingDing _dingDing;
  30. public LessonController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing)
  31. {
  32. _azureCosmos = azureCosmos;
  33. _azureStorage = azureStorage;
  34. _azureRedis = azureRedis;
  35. _dingDing = dingDing;
  36. }
  37. [HttpPost("get-less")]
  38. public async Task<IActionResult> GetLess(JsonElement jsonElement)
  39. {
  40. if (!jsonElement.TryGetProperty("school", out JsonElement school)) return BadRequest();
  41. var table = _azureStorage.GetCloudTableClient().GetTableReference("BIStats");
  42. var tableSql = $" PartitionKey eq 'LessonHour' and school eq '{school}'";
  43. //lambda 表达式排序
  44. var lessStats = await table.QueryWhereString<LessStats>(tableSql.ToString());
  45. DenseMatrix openDense = null;
  46. DenseMatrix lessDense = null;
  47. List<List<double>> tempOpens = new();
  48. List<List<double>> tempLesss = new();
  49. foreach (var item in lessStats)
  50. {
  51. if (item.open != null)
  52. {
  53. List<double> opens = item.open.Split(',').ToList().ConvertAll(c => Convert.ToDouble(c));
  54. tempOpens.Add(opens);
  55. }
  56. if(item.lesson != null)
  57. {
  58. List<double> lesss = item.lesson.Split(',').ToList().ConvertAll(c => Convert.ToDouble(c));
  59. tempLesss.Add(lesss);
  60. }
  61. }
  62. openDense = DenseMatrix.OfColumns(tempOpens);
  63. lessDense = DenseMatrix.OfColumns(tempLesss);
  64. return Ok(new { state = 200 , openDense ,lessDense});
  65. }
  66. /// <summary>
  67. /// 测试 通过时间戳保存统计类型接口
  68. /// </summary>
  69. /// <param name="jsonElement"></param>
  70. /// <returns></returns>
  71. [HttpPost("set-bilessonstats")]
  72. public async Task<IActionResult> SetBILeesonStats(JsonElement jsonElement)
  73. {
  74. if (!jsonElement.TryGetProperty("unix", out JsonElement unix)) return BadRequest();
  75. if (!jsonElement.TryGetProperty("num", out JsonElement num)) return BadRequest();
  76. jsonElement.TryGetProperty("schoolId", out JsonElement schoolId);
  77. jsonElement.TryGetProperty("type", out JsonElement type);
  78. jsonElement.TryGetProperty("unixs", out JsonElement unixs);
  79. var cosmosClient = _azureCosmos.GetCosmosClient();
  80. DateTime expireYear = DateTime.UtcNow.AddYears(1); //一个月到期
  81. var UUID = Guid.NewGuid().ToString();
  82. List<long> unixsT = unixs.ToObject<List<long>>();
  83. RedisValue token = Environment.MachineName;
  84. foreach (var item in unixsT)
  85. {
  86. //await SetBILeesonStats(cosmosClient, item, num.GetInt32(), type: type.GetInt32(), schoolId: schoolId.GetString());
  87. //await BILeeson.SetCosmosDBStats(cosmosClient, _azureRedis, _dingDing, item, num.GetInt32(), type: type.GetInt32(), schoolId: schoolId.GetString());
  88. await BILeeson.SetTableStats(_azureStorage, _azureRedis, _dingDing, item, num.GetInt32(), type: type.GetInt32(), schoolId: schoolId.GetString());
  89. }
  90. //await BILeeson.SetBILeesonStats(cosmosClient, _azureRedis, unix.GetInt64(), num.GetInt32(), type: type.GetInt32(), schoolId: schoolId.GetString());
  91. //await SetBILeesonStats(cosmosClient, unix.GetInt64(), num.GetInt32(), type: -1, schoolId: schoolId.GetString());
  92. return Ok(new { state = 200 });
  93. }
  94. /// <summary>
  95. /// 通过时间戳保存统计类型
  96. /// </summary>
  97. /// <param name="cosmosClient">连接字符串</param>
  98. /// <param name="unix">时间戳</param>
  99. /// <param name="num">加减数量,可为负数</param>
  100. /// <param name="type">课例类型,0开课 1 课例</param>
  101. /// <param name="schoolId">学校ID,可不传</param>
  102. /// <returns></returns>
  103. public static async Task SetBILeesonStats(CosmosClient cosmosClient, long unix, int num, int type = 0, string schoolId = null)
  104. {
  105. //Monitor.TryEnter(unix); //锁对象
  106. SemaphoreSlim slimlock = new(1, 1); //对可同时访问资源或资源池的线程数加以限制
  107. await slimlock.WaitAsync();
  108. DateTimeOffset dateTime = DateTimeOffset.FromUnixTimeMilliseconds(unix);
  109. int year, month, day, hour, days;
  110. year = dateTime.Year;
  111. month = dateTime.Month;
  112. day = dateTime.Day;
  113. hour = dateTime.Hour;
  114. string hourId = $"{year}{month.ToString().PadLeft(2, '0')}{day.ToString().PadLeft(2, '0')}";
  115. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  116. days = dateTime.DayOfYear;
  117. double[] daDays = new double[yearDays];
  118. daDays[days] = num;
  119. List<double> yDays = new(daDays);
  120. double[] daHours = new double[23];
  121. daHours[hour] = num;
  122. List<double> yHours = new(daHours);
  123. var openRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{year}", new PartitionKey("LessonYear"));
  124. if (openRes.Status == 200)
  125. {
  126. using var json = await JsonDocument.ParseAsync(openRes.ContentStream);
  127. LessonStats lessonYear = json.ToObject<LessonStats>();
  128. if (type == 0)
  129. {
  130. if (lessonYear.open.Count == 0)
  131. lessonYear.open = yDays;
  132. else lessonYear.open[days] = lessonYear.open[days] + num;
  133. }
  134. else if (type == 1)
  135. {
  136. if (lessonYear.lesson.Count == 0)
  137. lessonYear.lesson = yDays;
  138. else lessonYear.lesson[days] = lessonYear.lesson[days] + num;
  139. }
  140. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonYear, lessonYear.id, new PartitionKey($"{lessonYear.code}"));
  141. }
  142. else
  143. {
  144. LessonStats lessonYear = new();
  145. lessonYear.id = $"{year}";
  146. lessonYear.code = "LessonYear";
  147. lessonYear.pk = "LessonYear";
  148. if (type == 0)
  149. lessonYear.open = yDays;
  150. else if (type == 1)
  151. lessonYear.lesson = yDays;
  152. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonYear, new PartitionKey($"{lessonYear.code}"));
  153. }
  154. var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{hourId}", new PartitionKey("LessonHour"));
  155. if (lessRes.Status == 200)
  156. {
  157. using var json = await JsonDocument.ParseAsync(lessRes.ContentStream);
  158. LessonStats lessonHour = json.ToObject<LessonStats>();
  159. if (type == 0)
  160. {
  161. if (lessonHour.open.Count == 0)
  162. lessonHour.open = yHours;
  163. else lessonHour.open[hour] = lessonHour.open[hour] + num;
  164. }
  165. else if (type == 1)
  166. {
  167. if (lessonHour.lesson.Count == 0)
  168. lessonHour.lesson = yHours;
  169. else lessonHour.lesson[hour] = lessonHour.lesson[hour] + num;
  170. }
  171. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonHour, lessonHour.id, new PartitionKey($"LessonHour"));
  172. }
  173. else
  174. {
  175. LessonStats lessonHour = new();
  176. lessonHour.id = $"{hourId}";
  177. lessonHour.code = "LessonHour";
  178. lessonHour.pk = "LessonHour";
  179. if (type == 0)
  180. lessonHour.open = yDays;
  181. else if (type == 1)
  182. lessonHour.lesson = yDays;
  183. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonHour, new PartitionKey("LessonHour"));
  184. }
  185. //学校统计
  186. if (!string.IsNullOrEmpty(schoolId))
  187. {
  188. var openResSc = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{year}", new PartitionKey($"LessonYear-{schoolId}"));
  189. if (openResSc.Status == 200)
  190. {
  191. using var jsonSc = await JsonDocument.ParseAsync(openResSc.ContentStream);
  192. LessonStats lessonYearSc = jsonSc.ToObject<LessonStats>();
  193. if (type == 0)
  194. if (lessonYearSc.open.Count == 0)
  195. lessonYearSc.open = yDays;
  196. else lessonYearSc.open[days] = lessonYearSc.open[days] + num;
  197. else if (type == 1)
  198. {
  199. if (lessonYearSc.lesson.Count == 0)
  200. lessonYearSc.lesson = yDays;
  201. else lessonYearSc.lesson[days] = lessonYearSc.lesson[days] + num;
  202. }
  203. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonYearSc, lessonYearSc.id, new PartitionKey($"LessonYear-{schoolId}"));
  204. }
  205. else
  206. {
  207. LessonStats lessonYearSc = new();
  208. lessonYearSc.id = $"{year}";
  209. lessonYearSc.code = $"LessonYear-{schoolId}";
  210. lessonYearSc.pk = "LessonYear";
  211. if (type == 0)
  212. lessonYearSc.open = yDays;
  213. else if (type == 1)
  214. lessonYearSc.lesson = yDays;
  215. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonYearSc, new PartitionKey($"LessonYear-{schoolId}"));
  216. }
  217. var lessResSc = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{hourId}", new PartitionKey($"LessonHour-{schoolId}"));
  218. if (lessResSc.Status == 200)
  219. {
  220. using var jsonSc = await JsonDocument.ParseAsync(lessResSc.ContentStream);
  221. LessonStats lessonHourSc = jsonSc.ToObject<LessonStats>();
  222. if (type == 0)
  223. if (lessonHourSc.open.Count == 0)
  224. lessonHourSc.open = yDays;
  225. else lessonHourSc.open[days] = lessonHourSc.open[days] + num;
  226. else if (type == 1)
  227. {
  228. if (lessonHourSc.lesson.Count == 0)
  229. lessonHourSc.lesson = yHours;
  230. else lessonHourSc.lesson[hour] = lessonHourSc.lesson[hour] + num;
  231. }
  232. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonHourSc, lessonHourSc.id, new PartitionKey($"LessonHour-{schoolId}"));
  233. }
  234. else
  235. {
  236. LessonStats lessonYearSc = new();
  237. lessonYearSc.id = $"{hourId}";
  238. lessonYearSc.code = $"LessonHour-{schoolId}";
  239. lessonYearSc.pk = "LessonHour";
  240. if (type == 0)
  241. lessonYearSc.open = yHours;
  242. else if (type == 1)
  243. lessonYearSc.lesson = yHours;
  244. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonYearSc, new PartitionKey($"LessonHour-{schoolId}"));
  245. }
  246. }
  247. slimlock.Release();
  248. //Monitor.Enter(unix);
  249. }
  250. /// <summary>
  251. /// 历史记录读取,并统计存储
  252. /// </summary>
  253. /// <param name="jsonElement"></param>
  254. /// <returns></returns>
  255. [HttpPost("get-alllesson")]
  256. public async Task<IActionResult> GetAllLessonRecords(JsonElement jsonElement)
  257. {
  258. jsonElement.TryGetProperty("site", out JsonElement site);
  259. var cosmosClient = _azureCosmos.GetCosmosClient();
  260. if ($"{site}".Equals(BIConst.Global))
  261. cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  262. List<LessonRecord> allLesson = new();
  263. await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonRecord>(queryText: $"select value(c) from c where c.pk='LessonRecord'", requestOptions: new QueryRequestOptions() { }))
  264. {
  265. allLesson.Add(item);
  266. }
  267. await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<LessonRecord>(queryText: $"select value(c) from c where c.pk='LessonRecord'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") }))
  268. {
  269. allLesson.Add(item);
  270. }
  271. (List<LessonStats> lessYears, List<LessonStats> lessHours) = await AllLessonStats(allLesson, _azureRedis);
  272. foreach (var itemY in lessYears)
  273. {
  274. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemY.id, new PartitionKey($"{itemY.code}"));
  275. if (response.Status == 200)
  276. {
  277. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  278. LessonStats lessonYear = json.ToObject<LessonStats>();
  279. lessonYear.open = itemY.open;
  280. lessonYear.lesson = itemY.lesson;
  281. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonYear, lessonYear.id, new PartitionKey($"{lessonYear.code}"));
  282. }
  283. else
  284. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(itemY, new PartitionKey($"{itemY.code}"));
  285. }
  286. foreach (var itemH in lessHours)
  287. {
  288. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemH.id, new PartitionKey($"{itemH.code}"));
  289. if (response.Status == 200)
  290. {
  291. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  292. LessonStats lessonHour = json.ToObject<LessonStats>();
  293. lessonHour.open = itemH.open;
  294. lessonHour.lesson = itemH.lesson;
  295. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonHour, lessonHour.id, new PartitionKey($"{lessonHour.code}"));
  296. }
  297. else
  298. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(itemH, new PartitionKey($"{itemH.code}"));
  299. }
  300. return Ok(new { state = 200, ycnt = lessYears.Count, hcnt = lessHours.Count, lessYears, lessHours });
  301. }
  302. #region 课例历史记录统计
  303. /// <summary>
  304. /// 统计所有课例
  305. /// </summary>
  306. /// <param name="lessRecs"></param>
  307. /// <returns></returns>
  308. public static async Task<(List<LessonStats> lessonYears, List<LessonStats> lessonHours)> AllLessonStats(List<LessonRecord> lessRecs, AzureRedisFactory azureRedis)
  309. {
  310. //统计所有
  311. List<LessCnt> allLess = lessRecs.Select(item => new LessCnt { hour = TimeHelper.GetDateTime(item.startTime).ToString("yyyyMMddHH"), cat = item.id, upload = item.upload, schoolId = item.school }).ToList();
  312. var openL = allLess.FindAll(f => f.upload == 0).GroupBy(g => g.hour).Select(s => new AllLess { key = s.Key, cnt = s.Count() }).ToList();
  313. var lessL = allLess.FindAll(s => s.upload == 1).GroupBy(g => g.hour).Select(s => new AllLess { key = s.Key, cnt = s.Count() }).ToList();
  314. List<LessonStats> lessYears = new();
  315. List<LessonStats> lessHours = new();
  316. //统计开课记录
  317. openL.ForEach(x =>
  318. {
  319. var (year, month, day, days, hour) = TimeHelper.GetDateTime(x.key);
  320. string id = $"{year}{month.ToString().PadLeft(2, '0')}{day.ToString().PadLeft(2, '0')}";
  321. LessonStats finHour = lessHours.Find(f => f.id.Equals(id));
  322. if (finHour != null)
  323. {
  324. if (finHour.open.Count == 0)
  325. {
  326. double[] da = new double[23];
  327. da[hour] = x.cnt;
  328. List<double> tempDays = new(da);
  329. finHour.open = tempDays;
  330. }
  331. else finHour.open[hour] = x.cnt;
  332. azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"BILesson:All:Open:{finHour.id}", $"{hour}", x.cnt);//一天24小时课例数 有上传 base.josn 小时为单位
  333. }
  334. else
  335. {
  336. //小时统计
  337. LessonStats lessonHour = new();
  338. lessonHour.id = id;
  339. lessonHour.code = "LessonHour";
  340. lessonHour.pk = "LessonHour";
  341. double[] daHours = new double[23];
  342. daHours[hour] = x.cnt;
  343. List<double> hourDays = new(daHours);
  344. lessonHour.open = hourDays;
  345. //lessonHour.ttl = 24 * 60 * 60 * 8; //设置过期时间 8天后自动删除
  346. lessHours.Add(lessonHour);
  347. }
  348. LessonStats findLess = lessYears.Find(f => f.id.Equals($"{year}"));
  349. if (findLess != null)
  350. {
  351. if (findLess.open.Count == 0)
  352. {
  353. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  354. double[] da = new double[yearDays];
  355. da[days] = x.cnt;
  356. List<double> tempDays = new(da);
  357. findLess.open = tempDays;
  358. }
  359. else findLess.open[days] = x.cnt;
  360. }
  361. else
  362. {
  363. LessonStats lessonYear = new();
  364. lessonYear.id = $"{year}";
  365. lessonYear.code = "LessonYear";
  366. lessonYear.pk = "LessonYear";
  367. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  368. double[] daDays = new double[yearDays];
  369. daDays[days] = x.cnt;
  370. List<double> yDays = new(daDays);
  371. lessonYear.open = yDays;
  372. lessYears.Add(lessonYear);
  373. }
  374. });
  375. //统计课例
  376. lessL.ForEach(x =>
  377. {
  378. var (year, month, day, days, hour) = TimeHelper.GetDateTime(x.key);
  379. string id = $"{year}{month.ToString().PadLeft(2, '0')}{day.ToString().PadLeft(2, '0')}";
  380. LessonStats finHour = lessHours.Find(f => f.id.Equals(id));
  381. if (finHour != null)
  382. {
  383. if (finHour.lesson.Count == 0)
  384. {
  385. double[] da = new double[23];
  386. da[hour] = x.cnt;
  387. List<double> tempDays = new(da);
  388. finHour.lesson = tempDays;
  389. }
  390. else finHour.lesson[hour] = x.cnt;
  391. }
  392. else
  393. {
  394. //小时统计
  395. LessonStats lessonHour = new();
  396. lessonHour.id = id;
  397. lessonHour.code = "LessonHour";
  398. lessonHour.pk = "LessonHour";
  399. double[] daHours = new double[23];
  400. daHours[hour] = x.cnt;
  401. List<double> hourDays = new(daHours);
  402. lessonHour.lesson = hourDays;
  403. lessHours.Add(lessonHour);
  404. }
  405. LessonStats findLess = lessYears.Find(f => f.id.Equals($"{year}"));
  406. if (findLess != null)
  407. {
  408. if (findLess.lesson.Count == 0)
  409. {
  410. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  411. double[] da = new double[yearDays];
  412. da[days] = x.cnt;
  413. List<double> tempDays = new(da);
  414. findLess.lesson = tempDays;
  415. }
  416. else findLess.lesson[days] = x.cnt;
  417. }
  418. else
  419. {
  420. LessonStats lessonYear = new();
  421. lessonYear.id = $"{year}";
  422. lessonYear.code = "LessonYear";
  423. lessonYear.pk = "LessonYear";
  424. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  425. double[] da = new double[yearDays];
  426. da[days] = x.cnt;
  427. List<double> tempDays = new(da);
  428. lessonYear.lesson = tempDays;
  429. lessYears.Add(lessonYear);
  430. }
  431. });
  432. //统计学校课例
  433. var scLess = lessRecs.Select(item => new LessCnt { hour = TimeHelper.GetDateTime(item.startTime).ToString("yyyyMMddHH"), cat = item.id, upload = item.upload, schoolId = item.school }).GroupBy(g => g.schoolId).Select(s => new ScLess { key = s.Key, lessCnt = s.ToList() }).ToList();
  434. foreach (var itemLess in scLess)
  435. {
  436. var openSCL = itemLess.lessCnt.FindAll(f => f.upload == 0).GroupBy(g => g.hour).Select(s => new ScLesson { key = s.Key, schoolId = itemLess.key, cnt = s.Count() }).ToList();
  437. var lessSCL = itemLess.lessCnt.FindAll(f => f.upload == 1).GroupBy(g => g.hour).Select(s => new ScLesson { key = s.Key, schoolId = itemLess.key, cnt = s.Count() }).ToList();
  438. openSCL.ForEach(f =>
  439. {
  440. if (!string.IsNullOrEmpty(f.schoolId))
  441. {
  442. var (year, month, day, days, hour) = TimeHelper.GetDateTime(f.key);
  443. string id = $"{year}{month.ToString().PadLeft(2, '0')}{day.ToString().PadLeft(2, '0')}";
  444. string codeHour = $"LessonHour-{f.schoolId}";
  445. LessonStats finHour = lessHours.Find(f => f.id.Equals(id) && f.code.Equals(codeHour));
  446. if (finHour != null)
  447. {
  448. if (finHour.open.Count == 0)
  449. {
  450. double[] da = new double[23];
  451. da[hour] = f.cnt;
  452. List<double> tempDays = new(da);
  453. finHour.open = tempDays;
  454. }
  455. else finHour.open[hour] = f.cnt;
  456. }
  457. else
  458. {
  459. //小时统计
  460. LessonStats lessonHour = new();
  461. lessonHour.id = id;
  462. lessonHour.code = codeHour;
  463. lessonHour.pk = "LessonHour";
  464. double[] daHours = new double[23];
  465. daHours[hour] = f.cnt;
  466. List<double> hourDays = new(daHours);
  467. lessonHour.open = hourDays;
  468. //lessonHour.ttl = 24 * 60 * 60 * 8; //设置过期时间
  469. lessHours.Add(lessonHour);
  470. }
  471. string codeYear = $"LessonYear-{f.schoolId}";
  472. LessonStats findLess = lessYears.Find(f => f.id.Equals($"{year}") && f.code.Equals(codeYear));
  473. if (findLess != null)
  474. {
  475. if (findLess.open.Count == 0)
  476. {
  477. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  478. double[] da = new double[yearDays];
  479. da[days] = f.cnt;
  480. List<double> tempDays = new(da);
  481. findLess.open = tempDays;
  482. }
  483. else findLess.open[days] = f.cnt;
  484. }
  485. else
  486. {
  487. LessonStats lessonYear = new();
  488. lessonYear.id = $"{year}";
  489. lessonYear.code = codeYear;
  490. lessonYear.code = "LessonYear";
  491. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  492. double[] daDays = new double[yearDays];
  493. daDays[days] = f.cnt;
  494. List<double> yDays = new(daDays);
  495. lessonYear.open = yDays;
  496. lessYears.Add(lessonYear);
  497. }
  498. }
  499. });
  500. lessSCL.ForEach(x =>
  501. {
  502. if (!string.IsNullOrEmpty(x.schoolId))
  503. {
  504. if (!string.IsNullOrEmpty(x.schoolId))
  505. {
  506. var (year, month, day, days, hour) = TimeHelper.GetDateTime(x.key);
  507. string id = $"{year}{month.ToString().PadLeft(2, '0')}{day.ToString().PadLeft(2, '0')}";
  508. string codeHour = $"LessonHour-{x.schoolId}";
  509. LessonStats finHour = lessHours.Find(f => f.id.Equals(id) && f.code.Equals(codeHour));
  510. if (finHour != null)
  511. {
  512. if (finHour.lesson.Count == 0)
  513. {
  514. double[] da = new double[23];
  515. da[hour] = x.cnt;
  516. List<double> tempDays = new(da);
  517. finHour.lesson = tempDays;
  518. }
  519. else finHour.lesson[hour] = x.cnt;
  520. }
  521. else
  522. {
  523. //小时统计
  524. LessonStats lessonHour = new();
  525. lessonHour.id = id;
  526. lessonHour.code = codeHour;
  527. lessonHour.pk = "LessonHour";
  528. double[] daHours = new double[23];
  529. daHours[hour] = x.cnt;
  530. List<double> hourDays = new(daHours);
  531. lessonHour.lesson = hourDays;
  532. lessHours.Add(lessonHour);
  533. }
  534. string codeYear = $"LessonYear-{x.schoolId}";
  535. LessonStats findLess = lessYears.Find(f => f.id.Equals($"{year}") && f.code.Equals(codeYear));
  536. if (findLess != null)
  537. {
  538. if (findLess.lesson.Count == 0)
  539. {
  540. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  541. double[] da = new double[yearDays];
  542. da[days] = x.cnt;
  543. List<double> tempDays = new(da);
  544. findLess.lesson = tempDays;
  545. }
  546. else findLess.lesson[days] = x.cnt;
  547. }
  548. else
  549. {
  550. LessonStats lessonYear = new();
  551. lessonYear.id = $"{year}";
  552. lessonYear.code = codeYear;
  553. lessonYear.pk = "LessonYear";
  554. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  555. double[] da = new double[yearDays];
  556. da[days] = x.cnt;
  557. List<double> tempDays = new(da);
  558. lessonYear.lesson = tempDays;
  559. lessYears.Add(lessonYear);
  560. }
  561. }
  562. }
  563. });
  564. };
  565. //openL.ForEach(x => {
  566. // var (year, days, hour) = TimeHelper.GetDateTime(x.key);
  567. // LessonYear findLess = lessYears.Find(f => f.id.Equals($"{year}"));
  568. // if (findLess != null)
  569. // {
  570. // if (findLess.openYear.Count == 0)
  571. // {
  572. // var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  573. // double[] da = new double[yearDays];
  574. // da[days] = x.cnt;
  575. // List<double> tempDays = new(da);
  576. // findLess.openYear = tempDays;
  577. // }
  578. // else findLess.openYear[days] = x.cnt;
  579. // }
  580. // else
  581. // {
  582. // LessonYear lessonYear = new();
  583. // lessonYear.id = $"{year}";
  584. // lessonYear.code = "LessonYear";
  585. // var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  586. // double[] da = new double[yearDays];
  587. // da[days] = x.cnt;
  588. // List<double> tempDays = new(da);
  589. // lessonYear.openYear = tempDays;
  590. // lessYears.Add(lessonYear);
  591. // }
  592. //});
  593. //lessL.ForEach(x => {
  594. // var (year, days, hour) = TimeHelper.GetDateTime(x.key);
  595. // LessonYear findLess = lessYears.Find(f => f.id.Equals($"{year}"));
  596. // if (findLess != null)
  597. // {
  598. // if (findLess.lessonYear.Count == 0)
  599. // {
  600. // var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  601. // double[] da = new double[yearDays];
  602. // da[days] = x.cnt;
  603. // List<double> tempDays = new(da);
  604. // findLess.lessonYear = tempDays;
  605. // }
  606. // else findLess.lessonYear[days] = x.cnt;
  607. // }
  608. // else
  609. // {
  610. // LessonYear lessonYear = new();
  611. // lessonYear.id = $"{year}";
  612. // lessonYear.code = "LessonYear";
  613. // var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  614. // double[] da = new double[yearDays];
  615. // da[days] = x.cnt;
  616. // List<double> tempDays = new(da);
  617. // lessonYear.lessonYear = tempDays;
  618. // lessYears.Add(lessonYear);
  619. // }
  620. //});
  621. return (lessYears, lessHours);
  622. }
  623. /// <summary>
  624. /// 统计学校课例
  625. /// </summary>
  626. public record ScLesson
  627. {
  628. public string key { get; set; }
  629. public string schoolId { get; set; }
  630. public int cnt { get; set; }
  631. }
  632. /// <summary>
  633. /// 统计学校课例详细信息
  634. /// </summary>
  635. public record ScLess
  636. {
  637. public string key { get; set; }
  638. public List<LessCnt> lessCnt { get; set; }
  639. }
  640. /// <summary>
  641. /// 统计所有课例
  642. /// </summary>
  643. public record AllLess
  644. {
  645. public string key { get; set; }
  646. public int cnt { get; set; }
  647. }
  648. /// <summary>
  649. /// 统计所有课例详细
  650. /// </summary>
  651. public record LessCnt
  652. {
  653. public string hour { get; set; }
  654. public string schoolId { get; set; }
  655. public string cat { get; set; }
  656. public int upload { get; set; }
  657. }
  658. #endregion
  659. }
  660. }