LessonRecordController.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using Azure.Storage.Blobs.Models;
  2. using DocumentFormat.OpenXml.Office2010.Excel;
  3. using HTEX.Lib.ETL;
  4. using HTEX.Lib.ETL.Lesson;
  5. using Microsoft.AspNetCore.Mvc;
  6. using Microsoft.Azure.Cosmos;
  7. using Microsoft.OData.UriParser;
  8. using System.CodeDom;
  9. using System.Collections.Generic;
  10. using System.IO;
  11. using System.Runtime.InteropServices;
  12. using System.Text.Json;
  13. using System.Xml;
  14. using TEAMModelOS.SDK;
  15. using TEAMModelOS.SDK.DI;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Helper.Common.FileHelper;
  18. using TEAMModelOS.SDK.Models;
  19. using TEAMModelOS.SDK.Models.Cosmos.BI;
  20. using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
  21. namespace HTEX.DataETL.Controllers
  22. {
  23. [ApiController]
  24. [Route("lesson-record")]
  25. public class LessonRecordController : ControllerBase
  26. {
  27. private readonly ILogger<LessonRecordController> _logger;
  28. private readonly AzureCosmosFactory _azureCosmos;
  29. private readonly AzureStorageFactory _azureStorage;
  30. private readonly IConfiguration _configuration;
  31. private readonly IWebHostEnvironment _webHostEnvironment;
  32. public LessonRecordController(ILogger<LessonRecordController> logger, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage
  33. , IConfiguration configuration, IWebHostEnvironment environment)
  34. {
  35. _logger = logger;
  36. _azureCosmos = azureCosmos;
  37. _azureStorage = azureStorage;
  38. _configuration = configuration;
  39. _webHostEnvironment = environment;
  40. }
  41. [HttpPost("process-local")]
  42. public async Task<IActionResult> ProcessLocal(JsonElement json)
  43. {
  44. List<StudentLessonData> studentLessonDatas = new List<StudentLessonData>();
  45. string? id = json.GetProperty("id").GetString();
  46. if (!string.IsNullOrWhiteSpace(id))
  47. {
  48. string? lessonPath= _configuration.GetValue<string>("LessonPath");
  49. string? path = $"{lessonPath}\\locals\\{id}";
  50. var files = FileHelper.ListAllFiles(path);
  51. // var sampleJson =System.IO. File.ReadAllTextAsync(path);
  52. LessonBase? lessonBase = null;
  53. List<LocalStudent> localStudents = new List<LocalStudent>();
  54. List<TaskData> taskDatas = new List<TaskData>();
  55. List<SmartRatingData> smartRatingDatas = new List<SmartRatingData>();
  56. List<IRSData> irsDatas = new List<IRSData>();
  57. List<CoworkData> coworkDatas = new List<CoworkData>();
  58. List<ExamData> examDatas = new List<ExamData>();
  59. TimeLineData? timeLineData = null;
  60. foreach (var item in files)
  61. {
  62. if (item.Contains("IES\\base.json"))
  63. {
  64. string jsons = await System.IO.File.ReadAllTextAsync(item);
  65. jsons = jsons.Replace("\"Uncall\"", "0").Replace("Uncall", "0");
  66. lessonBase = jsons.ToObject<LessonBase>();
  67. var data = LessonETLService.GetBaseData(lessonBase);
  68. localStudents = data.studentLessonDatas;
  69. }
  70. if (item.Contains("IES\\TimeLine.json"))
  71. {
  72. string jsons = await System.IO.File.ReadAllTextAsync(item);
  73. timeLineData = jsons.ToObject<TimeLineData>();
  74. }
  75. if (item.Contains("IES\\Task.json"))
  76. {
  77. string jsons = await System.IO.File.ReadAllTextAsync(item);
  78. taskDatas = jsons.ToObject<List<TaskData>>();
  79. }
  80. if (item.Contains("IES\\SmartRating.json"))
  81. {
  82. string jsons = await System.IO.File.ReadAllTextAsync(item);
  83. smartRatingDatas = jsons.ToObject<List<SmartRatingData>>();
  84. }
  85. if (item.Contains("IES\\IRS.json"))
  86. {
  87. string jsons = await System.IO.File.ReadAllTextAsync(item);
  88. irsDatas = jsons.ToObject<List<IRSData>>();
  89. }
  90. if (item.Contains("IES\\Cowork.json"))
  91. {
  92. string jsons = await System.IO.File.ReadAllTextAsync(item);
  93. coworkDatas = jsons.ToObject<List<CoworkData>>();
  94. }
  95. try
  96. {
  97. if (item.Contains($"\\{id}\\Exam\\") && item.EndsWith("Exam.json"))
  98. {
  99. string examsFile = item;
  100. if (examsFile.EndsWith("Exam.json"))
  101. {
  102. ExamData? examData = null;
  103. string jsons = await System.IO.File.ReadAllTextAsync(item);
  104. jsons = jsons.Replace("\"publish\": \"0\"", "\"publish\": 0").Replace("\"publish\": \"1\"", "\"publish\": 1");
  105. examData = jsons.ToObject<ExamData>();
  106. if (examData != null && examData.exam.papers.IsNotEmpty())
  107. {
  108. string paperId = examData.exam.papers.First().id;
  109. string paperPath = $"{path}\\ExamPaper\\{paperId}\\index.json";
  110. string jsonp = await System.IO.File.ReadAllTextAsync(paperPath);
  111. LessonPaper lessonPaper = jsonp.ToObject<LessonPaper>();
  112. examData.paper = lessonPaper;
  113. examDatas.Add(examData);
  114. }
  115. }
  116. }
  117. }
  118. catch (Exception ex)
  119. {
  120. _logger.LogError(ex, ex.Message);
  121. }
  122. }
  123. if (lessonBase!=null && timeLineData!=null)
  124. {
  125. studentLessonDatas = localStudents.ToJsonString().ToObject<List<StudentLessonData>>();
  126. studentLessonDatas = LessonETLService.GetBaseInfo( lessonBase!, studentLessonDatas, id);
  127. studentLessonDatas = LessonETLService.GetIRSData(lessonBase, timeLineData, irsDatas, studentLessonDatas, examDatas, id);
  128. studentLessonDatas = LessonETLService.GetCoworkData(lessonBase, timeLineData, coworkDatas, studentLessonDatas,id);
  129. studentLessonDatas = LessonETLService.GetExamData(lessonBase, timeLineData, examDatas, studentLessonDatas, Constant.objectiveTypes, id);
  130. studentLessonDatas = LessonETLService.GetSmartRatingData(lessonBase, timeLineData, smartRatingDatas, studentLessonDatas, id);
  131. studentLessonDatas = LessonETLService.GetTaskData(lessonBase, timeLineData, taskDatas, studentLessonDatas,id);
  132. var pickupData = LessonETLService.GetPickupData(lessonBase, timeLineData, studentLessonDatas, id);
  133. studentLessonDatas= pickupData.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.json");
  136. LessonDataAnalysisCluster lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisCluster>();
  137. var lessonItems= LessonETLService.ProcessStudentDataV2(studentLessonDatas, lessonDataAnalysis);
  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(lessonItems, $"{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-history-students")]
  152. public async Task<IActionResult> ProcessHistoryStudents(JsonElement json)
  153. {
  154. string? lessonBasePath = _configuration.GetValue<string>("LessonPath");
  155. string? pathLessons = $"{lessonBasePath}\\lessons";
  156. string? pathAnalysis = $"{lessonBasePath}\\analysis";
  157. string jsons = await System.IO.File.ReadAllTextAsync($"{pathAnalysis}\\analysis.json");
  158. LessonDataAnalysisCluster lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisCluster>();
  159. List<string> filesLessons = FileHelper.ListAllFiles(pathLessons, "-local.json");
  160. var runtimePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  161. XmlDocument xmlDocument = new XmlDocument();
  162. xmlDocument.Load($"{runtimePath}\\summary.xml");
  163. foreach (string fileLesson in filesLessons)
  164. {
  165. try {
  166. string localjson = await System.IO.File.ReadAllTextAsync(fileLesson);
  167. var lessonLocal = localjson.ToObject<LessonLocal>();
  168. List<StudentLessonData> studentLessonDatas = lessonLocal.studentLessonDatas.ToJsonString().ToObject<List<StudentLessonData>>();
  169. studentLessonDatas = LessonETLService.GetBaseInfo(lessonLocal.lessonBase!, studentLessonDatas, lessonLocal?.lessonRecord?.id);
  170. studentLessonDatas = LessonETLService.GetIRSData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.irsDatas, studentLessonDatas, lessonLocal.examDatas, lessonLocal?.lessonRecord?.id);
  171. studentLessonDatas = LessonETLService.GetCoworkData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.coworkDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
  172. studentLessonDatas = LessonETLService.GetExamData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.examDatas, studentLessonDatas, Constant.objectiveTypes, lessonLocal.lessonRecord.id);
  173. studentLessonDatas = LessonETLService.GetSmartRatingData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.smartRatingDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
  174. studentLessonDatas = LessonETLService.GetTaskData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, lessonLocal.taskDatas, studentLessonDatas, lessonLocal.lessonRecord.id);
  175. var pickupData = LessonETLService.GetPickupData(lessonLocal.lessonBase!, lessonLocal.timeLineData!, studentLessonDatas, lessonLocal.lessonRecord.id);
  176. studentLessonDatas= pickupData.studentLessonDatas;
  177. string owner = lessonLocal.lessonRecord.scope.Equals("school") ? lessonLocal.lessonRecord.school : lessonLocal.lessonRecord.tmdid;
  178. var lessonItems = LessonETLService.ProcessStudentDataV2(studentLessonDatas, lessonDataAnalysis);
  179. await LessonETLService.ExportToExcelAzureBlob(lessonItems, _azureStorage, owner, $"{lessonLocal.lessonRecord.id}/student-analysis.xlsx", xmlDocument);
  180. if (lessonLocal.lessonRecord.id.Equals("476665953166430208"))
  181. {
  182. int s = 1;
  183. }
  184. await _azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(studentLessonDatas.ToJsonString(), "records", $"{lessonLocal.lessonRecord.id}/student-analysis.json");
  185. } catch (Exception ex )
  186. {
  187. throw new Exception($"{fileLesson}",ex);
  188. }
  189. }
  190. return Ok();
  191. }
  192. /// <summary>
  193. /// 课例数据ETL处理过程
  194. /// </summary>
  195. /// <param name="json"></param>
  196. /// <returns></returns>
  197. [HttpPost("process-history")]
  198. public async Task<IActionResult> ProcessHistory(JsonElement json)
  199. {
  200. List<string> localIds = new List<string>();
  201. string? lessonBasePath = _configuration.GetValue<string>("LessonPath");
  202. string? pathLessons = $"{lessonBasePath}\\lessons";
  203. string? pathAnalysis = $"{lessonBasePath}\\analysis";
  204. var filesLessons = FileHelper.ListAllFiles(pathLessons);
  205. foreach (var file in filesLessons)
  206. {
  207. if (file.EndsWith("-local.json"))
  208. {
  209. string lessonId = file.Split("\\").Last().Replace("-local.json", "");
  210. localIds.Add(lessonId);
  211. }
  212. }
  213. bool loadLocal = true;
  214. List<LessonDataAnalysisMonth> lessonDataAnalysisMonths = new List<LessonDataAnalysisMonth>();
  215. var filesAnalysis = FileHelper.ListAllFiles(pathAnalysis);
  216. long stime = 1690819200000;//2023-08-01 00:00:00
  217. foreach (var file in filesAnalysis) {
  218. //读取每月的数据
  219. if (file.EndsWith("-m-analysis.json"))
  220. {
  221. string jsons = await System.IO.File.ReadAllTextAsync(file);
  222. LessonDataAnalysisMonth lessonDataAnalysis = jsons.ToObject<LessonDataAnalysisMonth>();
  223. lessonDataAnalysisMonths.Add(lessonDataAnalysis);
  224. }
  225. }
  226. if (lessonDataAnalysisMonths.IsNotEmpty()) {
  227. var maxUpdateTime = lessonDataAnalysisMonths.Max(x => x.updateTime);
  228. if (maxUpdateTime>0)
  229. {
  230. //更新周期是一周
  231. if (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()- maxUpdateTime>604800000)
  232. {
  233. stime=maxUpdateTime;
  234. loadLocal =true;
  235. }
  236. else
  237. {
  238. stime=maxUpdateTime;
  239. loadLocal=false;
  240. }
  241. }
  242. }
  243. HashSet<string> yearMonth = new HashSet<string>();
  244. long newest = 0;
  245. bool force = false;
  246. if ((json.TryGetProperty("force", out JsonElement _force)&& _force.ValueKind.Equals(JsonValueKind.True)))
  247. {
  248. force= _force.GetBoolean();
  249. }
  250. // if (loadLocal ||force)
  251. {
  252. List<LessonRecord> lessonRecords = new List<LessonRecord>();
  253. var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  254. .GetList<LessonRecord>($"SELECT value c FROM c where c.startTime>={stime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' and c.school<>'hbcn' and c.school<>'habook' and (c.tLevel>0 or c.pLevel>0) ", null);
  255. if (resultSchool.list.IsNotEmpty())
  256. {
  257. newest= resultSchool.list.Max(x => x.startTime);
  258. lessonRecords.AddRange(resultSchool.list);
  259. }
  260. else
  261. {
  262. newest=stime;
  263. }
  264. var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  265. .GetList<LessonRecord>($"SELECT value c FROM c where c.startTime>={stime} and c.expire<=0 and c.status<>404 and c.duration>300 and c.pk='LessonRecord' and (c.tLevel>0 or c.pLevel>0) ", null);
  266. if (resultTeacher.list.IsNotEmpty())
  267. {
  268. long max = resultTeacher.list.Max(x => x.startTime);
  269. if (max<newest)
  270. {
  271. newest=max;
  272. }
  273. lessonRecords.AddRange(resultTeacher.list);
  274. }
  275. List<string> ignore = new List<string>() { "PgJump", "PgRcv", "PgAdd" };
  276. if (lessonRecords.IsNotEmpty())
  277. {
  278. await foreach (var item in LessonETLService.GetLessonLocal(lessonRecords, localIds, _azureStorage, pathLessons))
  279. {
  280. string yearMonthPath = DateTimeOffset.FromUnixTimeMilliseconds(item.lessonRecord.startTime).ToString("yyyyMM");
  281. if (item.lessonBase!=null && item.lessonBase.student!=null)
  282. {
  283. TechCount techCount = new TechCount
  284. {
  285. lessonId=item.lessonRecord?.id,
  286. examCount = item.examDatas.Count,
  287. taskCount = item.taskDatas.Count,
  288. irsCount = item.irsDatas.Count,
  289. coworkCount = item.coworkDatas.Count,
  290. smartRatingCount =item.smartRatingDatas.Count,
  291. timeCount=item.sokratesDatas.Where(x => !ignore.Contains(x.Event) && !x.Event.Contains("End", StringComparison.OrdinalIgnoreCase)).GroupBy(x => x.Event).Select(x => new CodeLong() { code=x.Key, value= x.ToList().Count }).ToList()
  292. };
  293. await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord.id}-count.json", techCount.ToJsonString());
  294. await System.IO.File.WriteAllTextAsync($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json", item.ToJsonString());
  295. }
  296. else
  297. {
  298. System.IO.File.Delete($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-local.json");
  299. System.IO.File.Delete($"{pathLessons}\\MM{yearMonthPath}\\{item.lessonRecord!.id}-count.json");
  300. }
  301. }
  302. }
  303. List<TechCount> techCounts = new List<TechCount>();
  304. filesLessons = FileHelper.ListAllFiles(pathLessons, "-local.json");
  305. await foreach (var item in LessonETLService.GetTeachCount(lessonRecords, filesLessons, pathLessons, ignore, Constant.objectiveTypes, _azureStorage, force))
  306. {
  307. techCounts.Add(item);
  308. }
  309. LessonETLService. GenAnalysisData(pathAnalysis, newest, techCounts);
  310. }
  311. return Ok(new { yearMonth });
  312. }
  313. }
  314. }