StatisticsService.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. using Azure.Cosmos;
  2. using HTEXLib.COMM.Helpers;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using TEAMModelOS.SDK.DI;
  9. using TEAMModelOS.SDK.Models;
  10. namespace TEAMModelOS.SDK
  11. {
  12. public static class StatisticsService
  13. {
  14. /// <summary>
  15. /// 视频观看记录
  16. /// </summary>
  17. public const string VideoRecord= "VideoRecord";
  18. /// <summary>
  19. /// 教师能力点操作
  20. /// </summary>
  21. public const string TeacherAility = "TeacherAility";
  22. /// <summary>
  23. /// 课堂实录
  24. /// </summary>
  25. public const string TeacherClass = "TeacherClass";
  26. /// <summary>
  27. /// 线下研修
  28. /// </summary>
  29. public const string OfflineRecord = "OfflineRecord";
  30. public static async Task<List<TeacherTrain> > StatisticsArea(AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing)
  31. {
  32. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  33. List<School> schools = new List<School>();
  34. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School")
  35. .GetItemQueryIterator<School>(queryText: $"select value(c) from c where c.areaId='{area.id}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  36. {
  37. schools.Add(item);
  38. }
  39. await foreach (var tarain in GetStatisticsSchool(schools, setting, area, client,_dingDing))
  40. {
  41. teacherTrains.AddRange(tarain);
  42. }
  43. return teacherTrains;
  44. }
  45. private static async IAsyncEnumerable<List<TeacherTrain>> GetStatisticsSchool(List<School> schools, AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing)
  46. {
  47. foreach (var school in schools)
  48. {
  49. yield return await StatisticsSchool(school.id, setting, area, client,_dingDing);
  50. }
  51. }
  52. public static async Task<List<TeacherTrain>> StatisticsSchool(string school, AreaSetting setting, Area area, CosmosClient client,DingDing _dingDing) {
  53. List<RGroupList> yxtrain = await GroupListService.GetGroupListMemberByType(client, "yxtrain", new List<string> { "school" }, $"{school}", _dingDing);
  54. List<TeacherTrain> trains = new List<TeacherTrain>();
  55. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  56. .GetItemQueryIterator<TeacherTrain>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school}") })) {
  57. trains.Add(item);
  58. }
  59. var update = trains.FindAll(x => x.updateProperty.Count() > 0);
  60. var noupdate = trains.FindAll(x => x.updateProperty.Count() <=0);
  61. var members= yxtrain.SelectMany(x => x.members);
  62. var unStatistics = members.Select(x => x.id).Except(trains.Select(x => x.id));
  63. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  64. List<TeacherTrain> returnTrains = new List<TeacherTrain>();
  65. if (update.IsNotEmpty()) {
  66. teacherTrains.AddRange(update);
  67. }
  68. if (unStatistics != null) {
  69. foreach (string x in unStatistics) {
  70. teacherTrains.Add(new TeacherTrain
  71. {
  72. id = x,
  73. code = $"TeacherTrain-{school}",
  74. tmdid = x,
  75. school = school,
  76. updateProperty = new HashSet<string> { VideoRecord,TeacherAility,TeacherClass,OfflineRecord }
  77. });
  78. }
  79. }
  80. await foreach (var tarain in GetStatisticsTeacher(teacherTrains, setting, area, client))
  81. {
  82. returnTrains.Add(tarain);
  83. }
  84. if (noupdate.IsNotEmpty()) {
  85. returnTrains.AddRange(noupdate);
  86. }
  87. return returnTrains;
  88. }
  89. private static async IAsyncEnumerable<TeacherTrain> GetStatisticsTeacher(List<TeacherTrain> trains, AreaSetting setting, Area area, CosmosClient client)
  90. {
  91. foreach (var train in trains)
  92. {
  93. yield return await StatisticsTeacher( train, setting, area, client);
  94. }
  95. }
  96. public static async Task<TeacherTrain> StatisticsTeacher(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client) {
  97. string _school = train.school;
  98. string _tmdid = train.tmdid;
  99. TeacherTrain teacher_train = null;
  100. if (train.updateProperty.Count > 0) {
  101. await foreach (var tarain in DoProperty(train.updateProperty, setting, area, client, train)){
  102. teacher_train=tarain;
  103. }
  104. }
  105. //每次都统计活动相关的数据。
  106. train= await DoActivity(train, setting, area, client, _school, _tmdid);
  107. train.totalTime = train.onlineTime + train.classTime + train.submitTime + train.offlineTime;
  108. return train;
  109. }
  110. private static async IAsyncEnumerable<TeacherTrain> DoProperty(HashSet<string> updateProperty, AreaSetting setting, Area area, CosmosClient client, TeacherTrain train )
  111. {
  112. string _school = train.school;
  113. string _tmdid = train.tmdid;
  114. foreach (var property in updateProperty)
  115. {
  116. //视频观看更新
  117. if (property.Equals(VideoRecord, StringComparison.OrdinalIgnoreCase))
  118. {
  119. train = await DoVideoRecord(train, setting, area, client, _school, _tmdid);
  120. train.updateProperty.Remove(VideoRecord);
  121. yield return train;
  122. }
  123. //认证材料更新
  124. if (property.Equals(TeacherAility, StringComparison.OrdinalIgnoreCase))
  125. {
  126. train = await DoTeacherAility(train, setting, area, client, _school, _tmdid);
  127. train.updateProperty.Remove(TeacherAility);
  128. yield return train;
  129. }
  130. //课堂实录更新
  131. if (property.Equals(TeacherClass, StringComparison.OrdinalIgnoreCase))
  132. {
  133. train = await DoTeacherClass(train, setting, area, client, _school, _tmdid);
  134. train.updateProperty.Remove(TeacherClass);
  135. yield return train;
  136. }
  137. //线下研修
  138. if (property.Equals(OfflineRecord, StringComparison.OrdinalIgnoreCase))
  139. {
  140. train = await DoOfflineRecord(train, setting, area, client, _school, _tmdid);
  141. train.updateProperty.Remove(OfflineRecord);
  142. yield return train;
  143. }
  144. }
  145. }
  146. public static async Task<TeacherTrain> DoActivity(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid) {
  147. //问卷调查
  148. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  149. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'Survey' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  150. {
  151. if (!string.IsNullOrEmpty(item.owner))
  152. {
  153. if (item.owner.Equals("school"))
  154. {
  155. train.surveyJoin += 1;
  156. if (item.taskStatus > 0)
  157. {
  158. train.surveyDone += 1;
  159. }
  160. }
  161. else if (item.owner.Equals("area"))
  162. {
  163. train.surveyAreaJoin += 1;
  164. if (item.taskStatus > 0)
  165. {
  166. train.surveyAreaDone += 1;
  167. }
  168. }
  169. }
  170. }
  171. //评量检测
  172. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  173. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'ExamLite' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  174. {
  175. if (!string.IsNullOrEmpty(item.owner))
  176. {
  177. if (item.owner.Equals("school"))
  178. {
  179. train.examJoin += 1;
  180. if (item.taskStatus > 0)
  181. {
  182. train.examDone += 1;
  183. }
  184. }
  185. else if (item.owner.Equals("area"))
  186. {
  187. train.examAreaJoin += 1;
  188. if (item.taskStatus > 0)
  189. {
  190. train.examAreaDone += 1;
  191. }
  192. }
  193. }
  194. }
  195. //投票活动
  196. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  197. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'Vote' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  198. {
  199. if (!string.IsNullOrEmpty(item.owner))
  200. {
  201. if (item.owner.Equals("school"))
  202. {
  203. train.voteJoin += 1;
  204. if (item.taskStatus > 0)
  205. {
  206. train.voteDone += 1;
  207. }
  208. }
  209. else if (item.owner.Equals("area"))
  210. {
  211. train.voteAreaJoin += 1;
  212. if (item.taskStatus > 0)
  213. {
  214. train.voteAreaDone += 1;
  215. }
  216. }
  217. }
  218. }
  219. return train;
  220. }
  221. /// <summary>
  222. /// 课堂实录更新
  223. /// </summary>
  224. /// <param name="train"></param>
  225. /// <param name="setting"></param>
  226. /// <param name="area"></param>
  227. /// <param name="client"></param>
  228. /// <param name="_school"></param>
  229. /// <param name="_tmdid"></param>
  230. /// <returns></returns>
  231. public static async Task<TeacherTrain> DoOfflineRecord(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid) {
  232. //owner: school area
  233. //线下 学校研修活动
  234. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  235. .GetItemQueryIterator<StuActivity>(queryText: $"select value(c) from c where c.type = 'Study' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  236. {
  237. Study study = null;
  238. try
  239. {
  240. study = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Study>(item.id, new PartitionKey(item.scode));
  241. }
  242. catch (CosmosException ex) {
  243. continue;
  244. }
  245. StudyRecord studyRecord;
  246. Attachment attachment = null;
  247. try {
  248. studyRecord= await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<StudyRecord>(item.id, new PartitionKey($"StudyRecord-{_tmdid}"));
  249. }
  250. catch (CosmosException ) {
  251. studyRecord = null;
  252. }
  253. try
  254. {
  255. if (!string.IsNullOrEmpty(study.workId)) {
  256. HomeworkRecord homeworkRecord = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<HomeworkRecord>(study.workId, new PartitionKey($"HomeworkRecord-{_tmdid}"));
  257. attachment= homeworkRecord.content.Find(x => x.prime);
  258. }
  259. }
  260. catch (CosmosException)
  261. {
  262. attachment = null;
  263. }
  264. if (!string.IsNullOrEmpty(item.owner))
  265. {
  266. OfflineRecord record = new OfflineRecord
  267. {
  268. id = item.id,
  269. name = item.name,
  270. done = item.taskStatus,
  271. owner = item.owner
  272. };
  273. if (null != studyRecord)
  274. {
  275. //通过获得学时
  276. record.hour = studyRecord.status == 1 ? study.hour : 0;
  277. train.offlineTime = record.hour;
  278. if (studyRecord.status == 1)
  279. {
  280. record.score = 1;
  281. record.done = 1;
  282. }
  283. if (studyRecord.status == 0)
  284. {
  285. record.score = -1;
  286. }
  287. if (studyRecord.status == 2)
  288. {
  289. record.score = 0;
  290. record.done = 1;
  291. }
  292. }
  293. if (null != attachment)
  294. {
  295. record.url = attachment.url;
  296. record.upload = 1;
  297. record.hash = attachment.hash;
  298. record.size = attachment.size;
  299. }
  300. train.offlineRecords.Add(record);
  301. }
  302. }
  303. return train;
  304. }
  305. /// <summary>
  306. /// 课堂实录更新
  307. /// </summary>
  308. /// <param name="train"></param>
  309. /// <param name="setting"></param>
  310. /// <param name="area"></param>
  311. /// <param name="client"></param>
  312. /// <param name="_school"></param>
  313. /// <param name="_tmdid"></param>
  314. /// <returns></returns>
  315. public static async Task<TeacherTrain> DoTeacherClass(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  316. {
  317. string code = $"ClassVideo-{_school}";
  318. ClassVideo classVideo = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<ClassVideo>($"{_tmdid}", new PartitionKey(code));
  319. if (classVideo != null && classVideo.files.IsNotEmpty())
  320. {
  321. //2021.11.17 15:05,与J哥确认,取课堂实录第一个。前端也只show第一个视频。
  322. var files = classVideo.files[0];
  323. if (files.score > 0)
  324. {
  325. train.classTime += 5;
  326. }
  327. train.teacherClasses.Add(new Models.TeacherClass {url=files.url,score=files.score,hash=files.hash,name=files.name,size=files.size });
  328. }
  329. return train;
  330. }
  331. public static async Task<TeacherTrain> DoVideoRecord(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid) {
  332. TeacherFile file = null;
  333. try
  334. {
  335. file = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherFile>(_tmdid, new PartitionKey($"VideoRecord-{_school}"));
  336. }
  337. catch (CosmosException ex)
  338. {
  339. file = new TeacherFile
  340. {
  341. id = _tmdid,
  342. code = $"VideoRecord-{_school}" ,
  343. pk = "TeacherFile",
  344. ttl = -1,
  345. };
  346. await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherFile>(file, new PartitionKey($"VideoRecord-{_school}"));
  347. }
  348. if (file != null)
  349. {
  350. train.videoTime = file.fileRecords.Where(x => x.type.Equals("video")).Select(y => y.duration).Sum();
  351. }
  352. train.onlineTime = (int)train.videoTime / setting.lessonMinutes;
  353. return train;
  354. }
  355. public static async Task<TeacherTrain> DoTeacherAility(TeacherTrain train, AreaSetting setting,Area area , CosmosClient client,string _school,string _tmdid) {
  356. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  357. .GetItemQueryIterator<AbilitySub>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilitySub-{_school}-{_tmdid}") }))
  358. {
  359. int currency = item.from == 1 ? 1 : 0;
  360. Ability ability = null;
  361. try
  362. {
  363. ability = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Ability>(item.id, new PartitionKey($"Ability-{area.standard}"));
  364. if (item.from == 0)
  365. {
  366. currency = ability.currency;
  367. }
  368. else
  369. {
  370. currency = 1;
  371. }
  372. }
  373. catch (CosmosException ex)
  374. {
  375. currency = 0;
  376. continue;
  377. }
  378. if (currency == 1) {
  379. train.uploadTotal += ability.stds.FindAll(x=> x.task.IsNotEmpty()).Select(y=>y.task).Count();
  380. if (item.uploads.IsNotEmpty())
  381. {
  382. train.uploadDone += item.uploads.Count;
  383. }
  384. train.subCount += 1;
  385. if (item.exerciseScore > 0)
  386. {
  387. train.exerciseAbility += 1;
  388. }
  389. List<TeacherHprecord> hprecords = new List<TeacherHprecord>();
  390. TeacherAility teacherAility = new Models.TeacherAility
  391. {
  392. id = ability.id,
  393. currency = currency,
  394. no = ability.no,
  395. dimension = ability.dimension,
  396. zpscore = item.self,
  397. hprecord = hprecords,
  398. uploadHas = item.uploads.Count
  399. };
  400. //train.learnAbility += item.abilityCount;
  401. if (item.otherScore.IsNotEmpty())
  402. {
  403. var schoolScore = item.otherScore.Where(x => x.roleType.Equals("school")).FirstOrDefault();
  404. if (schoolScore != null && schoolScore.score > 0)
  405. {
  406. teacherAility.xzscore = schoolScore.score;
  407. }
  408. var hprecord= item.otherScore.FindAll(x => x.roleType.Equals("member")).Select(y => new TeacherHprecord { tmdid = y.tmdid,tmdname=y.tmdname,score=y.score });
  409. if (hprecord != null) {
  410. var no = hprecord.Where(x => x.score == 0) != null ? hprecord.Where(x => x.score == 0).Count() : 0;
  411. var hg = hprecord.Where(x => x.score == 1) != null ? hprecord.Where(x => x.score == 1).Count() : 0;
  412. var yx = hprecord.Where(x => x.score == 2) != null ? hprecord.Where(x => x.score == 2).Count() : 0;
  413. if (no == hg && hg == yx && no == 0)
  414. {
  415. teacherAility.hpscore = -1;
  416. }
  417. else if (no == hg && hg == yx && no != 0)
  418. {
  419. teacherAility.hpscore = 2;
  420. }
  421. else {
  422. bool ok = false;
  423. List<int> arr = new List<int>() { yx,hg,no};
  424. int max = arr.Max();
  425. if (max == yx && !ok) {
  426. teacherAility.hpscore = 2;
  427. ok = true;
  428. }
  429. if (max == hg && !ok)
  430. {
  431. teacherAility.hpscore = 1;
  432. ok = true;
  433. }
  434. if (max == no && !ok)
  435. {
  436. teacherAility.hpscore = 0;
  437. ok = true;
  438. }
  439. }
  440. teacherAility.hprecord.AddRange(hprecord);
  441. }
  442. }
  443. train.teacherAilities.Add(teacherAility);
  444. }
  445. }
  446. var bhg = train.teacherAilities.FindAll(x => x.xzscore <= 0);
  447. if (bhg.IsEmpty()) {
  448. ///要全部合格才能获得学时。
  449. train.submitTime = setting.submitTime;
  450. }
  451. return train;
  452. }
  453. }
  454. }