LessonRecordController.cs 17 KB

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