LessonRecordController.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. using DocumentFormat.OpenXml.Drawing.Charts;
  2. using HTEX.Lib.ETL.Lesson;
  3. using MathNet.Numerics.Distributions;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.Azure.Cosmos;
  6. using StackExchange.Redis;
  7. using System.Collections.Generic;
  8. using System.Text.Json;
  9. using System.Xml;
  10. using TEAMModelOS.SDK;
  11. using TEAMModelOS.SDK.DI;
  12. using TEAMModelOS.SDK.Extension;
  13. using TEAMModelOS.SDK.Helper.Common.FileHelper;
  14. using TEAMModelOS.SDK.Models;
  15. using TEAMModelOS.SDK.Models.Cosmos.Common;
  16. using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
  17. namespace HTEX.DataETL.Controllers
  18. {
  19. [ApiController]
  20. [Route("lesson-record")]
  21. public class LessonRecordController : ControllerBase
  22. {
  23. private readonly ILogger<LessonRecordController> _logger;
  24. private readonly AzureCosmosFactory _azureCosmos;
  25. private readonly AzureStorageFactory _azureStorage;
  26. private readonly IConfiguration _configuration;
  27. private readonly IWebHostEnvironment _webHostEnvironment;
  28. private readonly DingDing _dingDing;
  29. private readonly AzureRedisFactory _azureRedis;
  30. public LessonRecordController(ILogger<LessonRecordController> logger, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage , IConfiguration configuration, IWebHostEnvironment environment,DingDing dingDing,AzureRedisFactory azureRedis )
  31. {
  32. _logger = logger;
  33. _azureCosmos = azureCosmos;
  34. _azureStorage = azureStorage;
  35. _configuration = configuration;
  36. _webHostEnvironment = environment;
  37. _dingDing = dingDing;
  38. _azureRedis = azureRedis;
  39. }
  40. [HttpPost("process-local")]
  41. public async Task<IActionResult> ProcessLocal(JsonElement json)
  42. {
  43. List<StudentLessonData> studentLessonDatas = new List<StudentLessonData>();
  44. string? id = json.GetProperty("id").GetString();
  45. if (!string.IsNullOrWhiteSpace(id))
  46. {
  47. string? lessonPath = _configuration.GetValue<string>("LessonPath");
  48. string? path = $"{lessonPath}\\locals\\{id}";
  49. var files = FileHelper.ListAllFiles(path);
  50. // var sampleJson =System.IO. File.ReadAllTextAsync(path);
  51. LessonBase? lessonBase = null;
  52. List<LocalStudent> localStudents = new List<LocalStudent>();
  53. List<TaskData> taskDatas = new List<TaskData>();
  54. List<SmartRatingData> smartRatingDatas = new List<SmartRatingData>();
  55. List<IRSData> irsDatas = new List<IRSData>();
  56. List<CoworkData> coworkDatas = new List<CoworkData>();
  57. List<ExamData> examDatas = new List<ExamData>();
  58. TimeLineData? timeLineData = null;
  59. foreach (var item in files)
  60. {
  61. if (item.Contains("IES\\base.json"))
  62. {
  63. string jsons = await System.IO.File.ReadAllTextAsync(item);
  64. jsons = jsons.Replace("\"Uncall\"", "0").Replace("Uncall", "0");
  65. lessonBase = jsons.ToObject<LessonBase>();
  66. var data = LessonETLService.GetBaseData(lessonBase);
  67. localStudents = data.studentLessonDatas;
  68. }
  69. if (item.Contains("IES\\TimeLine.json"))
  70. {
  71. string jsons = await System.IO.File.ReadAllTextAsync(item);
  72. timeLineData = jsons.ToObject<TimeLineData>();
  73. }
  74. if (item.Contains("IES\\Task.json"))
  75. {
  76. string jsons = await System.IO.File.ReadAllTextAsync(item);
  77. taskDatas = jsons.ToObject<List<TaskData>>();
  78. }
  79. if (item.Contains("IES\\SmartRating.json"))
  80. {
  81. string jsons = await System.IO.File.ReadAllTextAsync(item);
  82. smartRatingDatas = jsons.ToObject<List<SmartRatingData>>();
  83. }
  84. if (item.Contains("IES\\IRS.json"))
  85. {
  86. string jsons = await System.IO.File.ReadAllTextAsync(item);
  87. irsDatas = jsons.ToObject<List<IRSData>>();
  88. }
  89. if (item.Contains("IES\\Cowork.json"))
  90. {
  91. string jsons = await System.IO.File.ReadAllTextAsync(item);
  92. coworkDatas = jsons.ToObject<List<CoworkData>>();
  93. }
  94. try
  95. {
  96. if (item.Contains($"\\{id}\\Exam\\") && item.EndsWith("Exam.json"))
  97. {
  98. string examsFile = item;
  99. if (examsFile.EndsWith("Exam.json"))
  100. {
  101. ExamData? examData = null;
  102. string jsons = await System.IO.File.ReadAllTextAsync(item);
  103. jsons = jsons.Replace("\"publish\": \"0\"", "\"publish\": 0").Replace("\"publish\": \"1\"", "\"publish\": 1");
  104. examData = jsons.ToObject<ExamData>();
  105. if (examData != null && examData.exam.papers.IsNotEmpty())
  106. {
  107. string paperId = examData.exam.papers.First().id;
  108. string paperPath = $"{path}\\ExamPaper\\{paperId}\\index.json";
  109. string jsonp = await System.IO.File.ReadAllTextAsync(paperPath);
  110. LessonPaper lessonPaper = jsonp.ToObject<LessonPaper>();
  111. examData.paper = lessonPaper;
  112. examDatas.Add(examData);
  113. }
  114. }
  115. }
  116. }
  117. catch (Exception ex)
  118. {
  119. _logger.LogError(ex, ex.Message);
  120. }
  121. }
  122. if (lessonBase!=null && timeLineData!=null)
  123. {
  124. studentLessonDatas = localStudents.ToJsonString().ToObject<List<StudentLessonData>>();
  125. studentLessonDatas = LessonETLService.GetBaseInfo(lessonBase!, studentLessonDatas, id);
  126. studentLessonDatas = LessonETLService.GetIRSData(lessonBase, timeLineData, irsDatas, studentLessonDatas, examDatas, id);
  127. studentLessonDatas = LessonETLService.GetCoworkData(lessonBase, timeLineData, coworkDatas, studentLessonDatas, id);
  128. studentLessonDatas = LessonETLService.GetExamData(lessonBase, timeLineData, examDatas, studentLessonDatas, Constant.objectiveTypes, id);
  129. studentLessonDatas = LessonETLService.GetSmartRatingData(lessonBase, timeLineData, smartRatingDatas, studentLessonDatas, id);
  130. studentLessonDatas = LessonETLService.GetTaskData(lessonBase, timeLineData, taskDatas, studentLessonDatas, id);
  131. var pickupData = LessonETLService.GetPickupData(lessonBase, timeLineData, studentLessonDatas, id);
  132. studentLessonDatas= pickupData.studentLessonDatas;
  133. var codeBools= LessonETLService.GetCodeBools(studentLessonDatas);
  134. await System.IO.File.WriteAllTextAsync(Path.Combine(path, $"student-analysis.json"), studentLessonDatas.ToJsonString());
  135. string jsons = await System.IO.File.ReadAllTextAsync($"{lessonPath}\\analysis\\analysis-model.json");
  136. LessonDataAnalysisModel lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisModel>();
  137. var studentLessons = LessonETLService.ProcessStudentDataV2(studentLessonDatas, lessonDataAnalysis,codeBools);
  138. XmlDocument xmlDocument = new XmlDocument();
  139. var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  140. xmlDocument.Load($"{runtimePath}\\summary.xml");
  141. await LessonETLService.ExportToExcelLocal(studentLessons, $"{path}\\analysis.xlsx", xmlDocument);
  142. }
  143. }
  144. return Ok();
  145. }
  146. /// <summary>
  147. ///
  148. /// </summary>
  149. /// <param name="json"></param>
  150. /// <returns></returns>
  151. [HttpPost("process-fix-history-students")]
  152. public async Task<IActionResult> ProcessFixHistoryStudents(JsonElement json)
  153. {
  154. string? pathAnalysis = $"F:\\lesson-local\\analysis";
  155. try
  156. {
  157. string jsons = await System.IO.File.ReadAllTextAsync($"F:\\lesson-local\\analysis\\analysis-model.json");
  158. var s = JsonSerializer.Deserialize<LessonDataAnalysisModel>(jsons);
  159. LessonDataAnalysisModel lessonDataAnalysis = JsonDocument.Parse(jsons).RootElement.ToObject<LessonDataAnalysisModel>();
  160. var per = LessonETLService.GetPersent(lessonDataAnalysis.irs, 2);
  161. }
  162. catch (Exception ex)
  163. {
  164. Console.WriteLine(ex.ToString());
  165. }
  166. return Ok();
  167. }
  168. /// <summary>
  169. ///
  170. /// </summary>
  171. /// <param name="json"></param>
  172. /// <returns></returns>
  173. [HttpPost("process-history-students")]
  174. public async Task<IActionResult> ProcessHistoryStudents(JsonElement json)
  175. {
  176. string? lessonBasePath = _configuration.GetValue<string>("LessonPath");
  177. string? pathLessons = $"{lessonBasePath}\\lessons";
  178. string? pathAnalysis = $"{lessonBasePath}\\analysis";
  179. string jsons = await System.IO.File.ReadAllTextAsync($"{pathAnalysis}\\analysis-model.json");
  180. LessonDataAnalysisModel lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisModel>();
  181. List<string> filesLessons = FileHelper.ListAllFiles(pathLessons, "-local.json");
  182. var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  183. XmlDocument xmlDocument = new XmlDocument();
  184. xmlDocument.Load($"{runtimePath}\\summary.xml");
  185. List<School> schools = new List<School>();
  186. // await Parallel.ForEachAsync(filesLessons, async (fileLesson, _) =>
  187. List<string> localIds = new List<string>();
  188. foreach (var file in filesLessons)
  189. {
  190. if (file.EndsWith("-local.json"))
  191. {
  192. string lessonId = file.Split("\\").Last().Replace("-local.json", "");
  193. localIds.Add(lessonId);
  194. }
  195. }
  196. long stime = 1693497600000;//2023-08-01 00:00:00
  197. long etime = 1731513599000;//2023-08-01 00:00:00
  198. var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  199. .GetList<LessonRecord>($"SELECT value c FROM c where ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.startTime<={etime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ");
  200. List<string> ignore = new List<string>() { "PgJump", "PgRcv", "PgAdd" };
  201. int index = 0;
  202. if (resultSchool.list.IsNotEmpty())
  203. {
  204. List<StudentSemesterRecord> studentSemesterRecords= new List<StudentSemesterRecord>();
  205. List<OverallEducation> overallEducations= new List<OverallEducation>();
  206. List<Student> studentsBase = new List<Student>();
  207. List<LessonLocal>lessonLocals = new List<LessonLocal>();
  208. await Parallel.ForEachAsync(resultSchool.list, async (lessonRecord, cancellationToken) =>
  209. {
  210. var item = await LessonETLService.GetLessonLocal(lessonRecord,localIds,_azureStorage,pathLessons);
  211. lessonLocals.Add(item);
  212. index++;
  213. });
  214. var schoolGroup = lessonLocals.Where(x=>!string.IsNullOrWhiteSpace(x.lessonRecord?.school)).GroupBy(x => x.lessonRecord?.school).Select(x => new { key=x.Key ,list=x.ToList()});
  215. string schoolSql = $"select value c from c where c.id in ({string.Join(",", schoolGroup.Select(x => $"'{x.key}'"))})";
  216. var schoolResults= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<School>(schoolSql, "Base");
  217. if (schoolResults.list.IsNotEmpty())
  218. {
  219. schools.AddRange(schoolResults.list);
  220. }
  221. foreach (var group in schoolGroup)
  222. {
  223. var studentIds = group.list.SelectMany(x => x.studentLessonDatas).Where(x=>!string.IsNullOrWhiteSpace(x.id)).Select(x => x.id).Distinct();
  224. string studentSql = $"select value c from c where c.id in ({string.Join(",", studentIds.Select(x => $"'{x}'"))})";
  225. var studentResults= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<Student>(studentSql, $"Base-{group.key}");
  226. if (studentResults.list.IsNotEmpty())
  227. {
  228. studentsBase.AddRange(studentResults.list);
  229. }
  230. string studentSemesterRecordSql = $"select value c from c where c.stuid in ({string.Join(",", studentIds.Select(x => $"'{x}'"))}) and c.studyYear>=2023";
  231. var studentSemesterRecordResults = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<StudentSemesterRecord>(studentSemesterRecordSql, $"StudentSemesterRecord-{group.key}");
  232. if (studentSemesterRecordResults.list.IsNotEmpty())
  233. {
  234. studentSemesterRecords.AddRange(studentSemesterRecordResults.list);
  235. }
  236. string overallEducationSql = $"select value c from c where c.studentId in ({string.Join(",", studentIds.Select(x => $"'{x}'"))}) and c.year>=2023";
  237. var overallEducationResults = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<OverallEducation>(overallEducationSql, $"OverallEducation-{group.key}");
  238. if (overallEducationResults.list.IsNotEmpty())
  239. {
  240. overallEducations.AddRange(overallEducationResults.list);
  241. }
  242. }
  243. List<(string id,string owner, List<StudentLessonData> studentLessonData)> studentLessonDatas= new List<(string id, string owner, List<StudentLessonData>)>();
  244. List<(string id, string owner, List<StudentLessonItem> studentLessons,List<CodeBool> codeBools, List<StudentLessonData> studentLessonData)> lessonItems = new List<(string id, string owner, List<StudentLessonItem> studentLessons, List<CodeBool> codeBools, List<StudentLessonData> studentLessonData)>();
  245. int n = 0;
  246. foreach (var item in lessonLocals)
  247. {
  248. var studata = await LessonETLService.DoStudentLessonData(Constant.objectiveTypes, _azureStorage, item, _dingDing, _azureCosmos.GetCosmosClient(), "China", _azureRedis, studentSemesterRecords, overallEducations, lessonDataAnalysis, studentsBase, schools);
  249. if (studata.codeBools.FindAll(x=>x.value).IsNotEmpty())
  250. {
  251. string owner = item.lessonRecord.scope.Equals("school") ? item.lessonRecord.school : item.lessonRecord.tmdid;
  252. studentLessonDatas.Add((item.lessonRecord.id, owner, studata.studentLessonDatas));
  253. lessonItems.Add((item.lessonRecord.id, owner, studata.lessonItems,studata.codeBools,studata.studentLessonDatas));
  254. }
  255. n++;
  256. }
  257. int p = 0;
  258. //XmlDocument xmlDocument = new XmlDocument();
  259. //var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  260. //xmlDocument.Load($"{runtimePath}\\summary.xml");
  261. await Parallel.ForEachAsync(lessonItems, async (lessonItem, cancellationToken) =>
  262. {
  263. lessonItem.studentLessons = LessonETLService.ProcessStudentDataV2(lessonItem.studentLessonData, lessonDataAnalysis, lessonItem.codeBools);
  264. await LessonETLService.ExportToExcelAzureBlob(lessonItem.studentLessons, _azureStorage, lessonItem.owner, $"{lessonItem.id}/student-analysis.xlsx", xmlDocument);
  265. p++;
  266. });
  267. int s = 0;
  268. await Parallel.ForEachAsync(studentLessonDatas, async (studentLessonData, cancellationToken) =>
  269. {
  270. await _azureStorage.GetBlobContainerClient(studentLessonData.owner).UploadFileByContainer(studentLessonData.studentLessonData.ToJsonString(), "records", $"{studentLessonData.id}/student-analysis.json");
  271. s++;
  272. });
  273. int m =0;
  274. await Parallel.ForEachAsync(studentSemesterRecords, async (studentSemester, cancellationToken) =>
  275. {
  276. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(studentSemester, new PartitionKey(studentSemester.code));
  277. m++;
  278. });
  279. int k = 0;
  280. await Parallel.ForEachAsync(overallEducations, async (overallEducation, cancellationToken) =>
  281. {
  282. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).UpsertItemAsync(overallEducation, partitionKey: new PartitionKey(overallEducation.code));
  283. //string key = $"OverallEducation:{overallEducation.schoolCode}:{overallEducation.periodId}:{overallEducation.year}:{overallEducation.semesterId}:{overallEducation?.classId}";
  284. //await _azureRedis.GetRedisClient(8).HashSetAsync(key, overallEducation.studentId, overallEducation.ToJsonString());
  285. //await _azureRedis.GetRedisClient(8).KeyExpireAsync(key, new TimeSpan(180 *24, 0, 0));
  286. k++;
  287. });
  288. }
  289. return Ok();
  290. }
  291. /// <summary>
  292. /// 课例数据ETL处理过程
  293. /// </summary>
  294. /// <param name="json"></param>
  295. /// <returns></returns>
  296. [HttpPost("process-history")]
  297. public async Task<IActionResult> ProcessHistory(JsonElement json)
  298. {
  299. List<string> localIds = new List<string>();
  300. string? lessonBasePath = _configuration.GetValue<string>("LessonPath");
  301. string? pathLessons = $"{lessonBasePath}\\lessons";
  302. string? pathAnalysis = $"{lessonBasePath}\\analysis";
  303. var filesLessons = FileHelper.ListAllFiles(pathLessons);
  304. foreach (var file in filesLessons)
  305. {
  306. if (file.EndsWith("-local.json"))
  307. {
  308. string lessonId = file.Split("\\").Last().Replace("-local.json", "");
  309. localIds.Add(lessonId);
  310. }
  311. }
  312. bool loadLocal = true;
  313. List<LessonDataAnalysisMonth> lessonDataAnalysisMonths = new List<LessonDataAnalysisMonth>();
  314. var filesAnalysis = FileHelper.ListAllFiles(pathAnalysis);
  315. long stime = 1693497600000;//2023-09-01 00:00:00
  316. foreach (var file in filesAnalysis)
  317. {
  318. //读取每月的数据
  319. if (file.EndsWith("-m-analysis.json"))
  320. {
  321. string jsons = await System.IO.File.ReadAllTextAsync(file);
  322. LessonDataAnalysisMonth lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisMonth>();
  323. lessonDataAnalysisMonths.Add(lessonDataAnalysis);
  324. }
  325. }
  326. if (lessonDataAnalysisMonths.IsNotEmpty())
  327. {
  328. var maxUpdateTime = lessonDataAnalysisMonths.Max(x => x.updateTime);
  329. if (maxUpdateTime>0)
  330. {
  331. //更新周期是一周
  332. if (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()- maxUpdateTime>604800000)
  333. {
  334. stime=maxUpdateTime;
  335. loadLocal =true;
  336. }
  337. else
  338. {
  339. stime=maxUpdateTime;
  340. loadLocal=false;
  341. }
  342. }
  343. }
  344. HashSet<string> yearMonth = new HashSet<string>();
  345. long newest = 0;
  346. bool force = false;
  347. if ((json.TryGetProperty("force", out JsonElement _force)&& _force.ValueKind.Equals(JsonValueKind.True)))
  348. {
  349. force= _force.GetBoolean();
  350. }
  351. // if (loadLocal ||force)
  352. {
  353. List<LessonRecord> lessonRecords = new List<LessonRecord>();
  354. var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  355. .GetList<LessonRecord>($"SELECT value c FROM c where ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ", null);
  356. if (resultSchool.list.IsNotEmpty())
  357. {
  358. newest= resultSchool.list.Max(x => x.startTime);
  359. lessonRecords.AddRange(resultSchool.list);
  360. }
  361. else
  362. {
  363. newest=stime;
  364. }
  365. var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  366. .GetList<LessonRecord>($"SELECT value c FROM c where ( c.analysis>=0 or IS_DEFINED(c.analysis) = false ) and c.startTime>={stime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' ", null);
  367. if (resultTeacher.list.IsNotEmpty())
  368. {
  369. long max = resultTeacher.list.Max(x => x.startTime);
  370. if (max<newest)
  371. {
  372. newest=max;
  373. }
  374. lessonRecords.AddRange(resultTeacher.list);
  375. }
  376. List<string> ignore = new List<string>() { "PgJump", "PgRcv", "PgAdd" };
  377. if (lessonRecords.IsNotEmpty())
  378. {
  379. await Parallel.ForEachAsync(lessonRecords, async(record, _)=>{
  380. LessonLocal item = await LessonETLService.GetLessonLocal(record, localIds, _azureStorage, pathLessons);
  381. string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
  382. item.lessonRecord.learningCategory= item.lessonBase?.summary?.learningCategory;
  383. if (item.lessonRecord.learningCategory == null)
  384. {
  385. item.lessonRecord.learningCategory = new LearningCategory();
  386. }
  387. await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
  388. });
  389. //await foreach (var item in LessonETLService.GetLessonLocal(lessonRecords, localIds, _azureStorage, pathLessons))
  390. // {
  391. // string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
  392. // item.lessonRecord.learningCategory= item.lessonBase?.summary?.learningCategory;
  393. // if (item.lessonRecord.learningCategory == null)
  394. // {
  395. // item. lessonRecord.learningCategory = new LearningCategory();
  396. // }
  397. // await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
  398. // }
  399. }
  400. List<TechCount> techCounts = new List<TechCount>();
  401. filesLessons = FileHelper.ListAllFiles(pathLessons, "-local.json");
  402. //await foreach (var item in LessonETLService.GetTeachCount(_azureCosmos,lessonRecords, filesLessons, pathLessons, ignore, Constant.objectiveTypes, _azureStorage, force))
  403. //{
  404. // techCounts.Add(item);
  405. //}
  406. await Parallel.ForEachAsync(filesLessons, async (item, _) => {
  407. TechCount techCount= await LessonETLService.GetTeachCount(_azureCosmos, item, pathLessons, ignore, Constant.objectiveTypes, _azureStorage, force);
  408. if (techCount != null) {
  409. techCounts.Add(techCount);
  410. }
  411. });
  412. await LessonETLService.GenAnalysisData(pathAnalysis, newest, techCounts,_azureStorage);
  413. }
  414. return Ok(new { yearMonth });
  415. }
  416. }
  417. }