StatisticsService.cs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. using Azure.Cosmos;
  2. using Azure.Messaging.ServiceBus;
  3. using DocumentFormat.OpenXml.Spreadsheet;
  4. using HTEXLib.COMM.Helpers;
  5. using Microsoft.AspNetCore.Http;
  6. using Microsoft.Extensions.Configuration;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using TEAMModelOS.SDK.DI;
  13. using TEAMModelOS.SDK.Extension;
  14. using TEAMModelOS.SDK.Models;
  15. using TEAMModelOS.SDK.Models.Service;
  16. namespace TEAMModelOS.SDK
  17. {
  18. public static class StatisticsService
  19. {
  20. /// <summary>
  21. /// 教师能力点操作
  22. /// </summary>
  23. public const string TeacherAbility = "TeacherAbility";
  24. /// <summary>
  25. /// 课堂实录
  26. /// </summary>
  27. public const string TeacherClass = "TeacherClass";
  28. /// <summary>
  29. /// 线下研修
  30. /// </summary>
  31. public const string OfflineRecord = "OfflineRecord";
  32. /// <summary>
  33. /// 教师投票活动
  34. /// </summary>
  35. public const string TeacherVote = "TeacherVote";
  36. /// <summary>
  37. /// 教师作业活动
  38. /// </summary>
  39. public const string TeacherHomework = "TeacherHomework";
  40. /// <summary>
  41. /// 教师问卷活动
  42. /// </summary>
  43. public const string TeacherSurvey = "TeacherSurvey";
  44. /// <summary>
  45. /// 教师评测活动
  46. /// </summary>
  47. public const string TeacherExamLite = "TeacherExamLite";
  48. public class TeacherTrainChangeMsg {
  49. public string areaId { get; set; }
  50. public List<TeacherTrainChangeMsgSchoolTeachers> schools { get; set; } = new List<TeacherTrainChangeMsgSchoolTeachers>();
  51. }
  52. public class TeacherTrainChangeMsgSchoolTeachers {
  53. public string school { get; set; }
  54. public List<string> teachers { get; set; } = new List<string>();
  55. }
  56. public static async Task DoChange(TeacherTrainChange change, AzureCosmosFactory _azureCosmos)
  57. {
  58. if (change.tmdids.IsNotEmpty() && change.update.Count() > 0 && !string.IsNullOrEmpty(change.school))
  59. {
  60. var client = _azureCosmos.GetCosmosClient();
  61. string insql = $"where c.id in ({string.Join(",", change.tmdids.Select(x => $"'{x}'"))})";
  62. string selsql = $"select value(c) from c {insql} ";
  63. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  64. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<TeacherTrain>(queryText: selsql,
  65. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{change.school}") }))
  66. {
  67. teacherTrains.Add(item);
  68. }
  69. List<Task<ItemResponse<TeacherTrain>>> task = new List<Task<ItemResponse<TeacherTrain>>>();
  70. teacherTrains.ForEach(x => {
  71. change.update.ToList().ForEach(u => {
  72. x.update.Add(u);
  73. });
  74. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<TeacherTrain>(x, x.id, new PartitionKey($"TeacherTrain-{change.school}")));
  75. });
  76. await task.TaskPage(5);
  77. var unchange = change.tmdids.Except(teacherTrains.Select(x => x.id));
  78. if (unchange != null)
  79. {
  80. task.Clear();
  81. unchange.ToList().ForEach(x => {
  82. TeacherTrain teacherTrain = new TeacherTrain
  83. {
  84. pk = "TeacherTrain",
  85. id = x,
  86. code = $"TeacherTrain-{change.school}",
  87. tmdid = x,
  88. school = change.school,
  89. update = new HashSet<string> { StatisticsService.TeacherAbility,
  90. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  91. };
  92. change.update.ToList().ForEach(u => {
  93. teacherTrain.update.Add(u);
  94. });
  95. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherTrain>(teacherTrain, new PartitionKey($"TeacherTrain-{change.school}")));
  96. });
  97. await task.TaskPage(5);
  98. }
  99. }
  100. }
  101. public static async Task SendServiceBus((string standard, List<string> tmdids, string school, List<string> update, int statistics) list, IConfiguration _configuration, AzureServiceBusFactory _serviceBus, CosmosClient client)
  102. {
  103. if (list.tmdids.IsNotEmpty() && list.update.IsNotEmpty())
  104. {
  105. string insql = $"where c.id in ({string.Join(",", list.tmdids.Select(x => $"'{x}'"))})";
  106. string selsql = $"select value(c) from c {insql} ";
  107. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  108. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<TeacherTrain>(queryText: selsql,
  109. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{list.school}") }))
  110. {
  111. teacherTrains.Add(item);
  112. }
  113. List<Task<ItemResponse<TeacherTrain>>> task = new List<Task<ItemResponse<TeacherTrain>>>();
  114. teacherTrains.ForEach(x => {
  115. list.update.ForEach(u => {
  116. x.update.Add(u);
  117. });
  118. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<TeacherTrain>(x, x.id, new PartitionKey($"TeacherTrain-{list.school}")));
  119. });
  120. await task.TaskPage(5);
  121. var unchange = list.tmdids.Except(teacherTrains.Select(x => x.id));
  122. if (unchange != null)
  123. {
  124. task.Clear();
  125. unchange.ToList().ForEach(x => {
  126. TeacherTrain teacherTrain = new TeacherTrain
  127. {
  128. pk = "TeacherTrain",
  129. id = x,
  130. code = $"TeacherTrain-{list.school}",
  131. tmdid = x,
  132. school = list.school,
  133. update = new HashSet<string> { StatisticsService.TeacherAbility,
  134. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  135. };
  136. list.update.ForEach(u => {
  137. teacherTrain.update.Add(u);
  138. });
  139. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TeacherTrain>(teacherTrain, new PartitionKey($"TeacherTrain-{list.school}")));
  140. });
  141. await task.TaskPage(1);
  142. }
  143. }
  144. }
  145. public static async Task GetAreaAndAreaSetting(string schoolId, string _standard, CosmosClient client, HttpContext httpContext)
  146. {
  147. School school = null;
  148. AreaSetting setting = null;
  149. string standard = "";
  150. if (string.IsNullOrEmpty(_standard))
  151. {
  152. standard = _standard;
  153. }
  154. else if (!string.IsNullOrEmpty(schoolId))
  155. {
  156. //优先找校级
  157. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(schoolId, new PartitionKey("AreaSetting"));
  158. //优先找校级
  159. school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(schoolId, new PartitionKey("Base"));
  160. }
  161. }
  162. //public static async Task<List<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>> StatisticsArea(CoreAPIHttpService _coreAPIHttpService, AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing, HashSet<string> updates)
  163. //{
  164. // List<(List<TeacherTrain> trains, List<RGroupList> yxtrain)> teacherTrains = new List<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>();
  165. // List<School> schools = new List<School>();
  166. // await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School")
  167. // .GetItemQueryIterator<School>(queryText: $"select value(c) from c where c.areaId='{area.id}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  168. // {
  169. // schools.Add(item);
  170. // }
  171. // await foreach ((List<TeacherTrain> trains, List<RGroupList> yxtrain) tarain in GetStatisticsSchool(_coreAPIHttpService, schools, setting, area, client, _dingDing, updates))
  172. // {
  173. // teacherTrains.Add(tarain);
  174. // }
  175. // return teacherTrains;
  176. //}
  177. //private static async IAsyncEnumerable<(List<TeacherTrain> trains, List<RGroupList> yxtrain)> GetStatisticsSchool(CoreAPIHttpService _coreAPIHttpService,List<School> schools, AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing, HashSet<string> updates)
  178. //{
  179. // foreach (var school in schools)
  180. // {
  181. // yield return await StatisticsSchool( _coreAPIHttpService,school.id, setting, area, client, _dingDing, updates);
  182. // }
  183. //}
  184. public static async Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain, List<TeacherTrain> updateTeacherTrains)> StatisticsSchoolQuik(CoreAPIHttpService _coreAPIHttpService, string school, AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing, HashSet<string> updates)
  185. {
  186. _coreAPIHttpService.check = false;
  187. List<RGroupList> yxtrain = await GroupListService.GetGroupListMemberByType(_coreAPIHttpService, client, "yxtrain", new List<string> { "school" }, $"{school}", _dingDing);
  188. List<TeacherTrain> trains = new List<TeacherTrain>();
  189. var members = yxtrain.SelectMany(x => x.members).ToList();
  190. if (members.Count <= 0)
  191. {
  192. return (trains, yxtrain, null) ;
  193. }
  194. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  195. .GetItemQueryIterator<TeacherTrain>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school}") }))
  196. {
  197. trains.Add(item);
  198. }
  199. if (updates != null)
  200. {
  201. foreach (var up in updates)
  202. {
  203. trains.ForEach(x => x.update.Add(up));
  204. }
  205. }
  206. var update = trains.FindAll(x => x.update.Count() > 0);
  207. var noupdate = trains.FindAll(x => x.update.Count() <= 0);
  208. var unStatistics = members.Select(x => x.id).Except(trains.Select(x => x.id));
  209. List<TeacherTrain> updateTeacherTrains = new List<TeacherTrain>();
  210. List<TeacherTrain> returnTrains = new List<TeacherTrain>();
  211. if (update.IsNotEmpty())
  212. {
  213. updateTeacherTrains.AddRange(update);
  214. }
  215. if (unStatistics != null)
  216. {
  217. foreach (string x in unStatistics)
  218. {
  219. var member = members.Find(y => y.id.Equals(x));
  220. updateTeacherTrains.Add(new TeacherTrain
  221. {
  222. pk = "TeacherTrain",
  223. id = x,
  224. code = $"TeacherTrain-{school}",
  225. tmdid = x,
  226. nickname = member.nickname,
  227. name = member.name,
  228. picture = member.picture,
  229. school = school,
  230. groupName=member.groupName,
  231. update = new HashSet<string> { TeacherAbility, TeacherClass, OfflineRecord }
  232. });
  233. }
  234. }
  235. //List<Study> studies = new List<Study>();
  236. //await foreach (var item in client.GetContainer("TEAMModelOS", "Common")
  237. // .GetItemQueryIterator<Study>(queryText: $"select value(c) from c where c.owner<>'area' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{school}") }))
  238. //{
  239. // studies.Add(item);
  240. //}
  241. returnTrains .AddRange(updateTeacherTrains) ;
  242. // await GetStatisticsTeacher(teacherTrains, setting, area, client, studies);
  243. //await foreach (var tarain in GetStatisticsTeacher(teacherTrains, setting, area, client))
  244. //{
  245. // returnTrains.Add(tarain);
  246. //}
  247. if (noupdate.IsNotEmpty())
  248. {
  249. returnTrains.AddRange(noupdate);
  250. }
  251. //移除不在研修名单的人员
  252. returnTrains.RemoveAll(x => !members.Select(y => y.id).Contains(x.id));
  253. returnTrains.ForEach(x => {
  254. var mbm = members.Find(y => y.id.Equals(x.id));
  255. if (mbm != null)
  256. {
  257. x.groupName = mbm?.groupName;
  258. x.name = !string.IsNullOrWhiteSpace(x.name) ? x.name : mbm?.name;
  259. x.nickname = mbm?.nickname;
  260. x.picture = mbm?.picture;
  261. x.groupName = mbm?.groupName;
  262. }
  263. });
  264. return (returnTrains, yxtrain, updateTeacherTrains);
  265. }
  266. public static async Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)> StatisticsSchool(CoreAPIHttpService _coreAPIHttpService,string school, AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing, HashSet<string> updates)
  267. {
  268. _coreAPIHttpService.check = false;
  269. List<RGroupList> yxtrain = await GroupListService.GetGroupListMemberByType(_coreAPIHttpService, client, "yxtrain", new List<string> { "school" }, $"{school}", _dingDing);
  270. List<TeacherTrain> trains = new List<TeacherTrain>();
  271. var members = yxtrain.SelectMany(x => x.members).ToList();
  272. if (members.Count <= 0)
  273. {
  274. return (trains, yxtrain);
  275. }
  276. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  277. .GetItemQueryIterator<TeacherTrain>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school}") }))
  278. {
  279. trains.Add(item);
  280. }
  281. if (updates != null)
  282. {
  283. foreach (var up in updates)
  284. {
  285. trains.ForEach(x => x.update.Add(up));
  286. }
  287. }
  288. var update = trains.FindAll(x => x.update.Count() > 0);
  289. var noupdate = trains.FindAll(x => x.update.Count() <= 0);
  290. var unStatistics = members.Select(x => x.id).Except(trains.Select(x => x.id));
  291. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  292. List<TeacherTrain> returnTrains = new List<TeacherTrain>();
  293. if (update.IsNotEmpty())
  294. {
  295. teacherTrains.AddRange(update);
  296. }
  297. if (unStatistics != null)
  298. {
  299. foreach (string x in unStatistics)
  300. {
  301. var member = members.Find(y => y.id.Equals(x));
  302. teacherTrains.Add(new TeacherTrain
  303. {
  304. pk = "TeacherTrain",
  305. id = x,
  306. code = $"TeacherTrain-{school}",
  307. tmdid = x,
  308. nickname=member.nickname,
  309. name = member.name,
  310. picture = member.picture,
  311. school = school,
  312. groupName = member.groupName,
  313. update = new HashSet<string> { TeacherAbility, TeacherClass, OfflineRecord }
  314. });
  315. }
  316. }
  317. List<Study> studies = new List<Study>();
  318. await foreach (var item in client.GetContainer("TEAMModelOS", "Common")
  319. .GetItemQueryIterator<Study>(queryText: $"select value(c) from c where c.owner<>'area' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{school}") }))
  320. {
  321. studies.Add(item);
  322. }
  323. returnTrains = await GetStatisticsTeacher(teacherTrains, setting, area, client, studies);
  324. //await foreach (var tarain in GetStatisticsTeacher(teacherTrains, setting, area, client))
  325. //{
  326. // returnTrains.Add(tarain);
  327. //}
  328. if (noupdate.IsNotEmpty())
  329. {
  330. returnTrains.AddRange(noupdate);
  331. }
  332. //移除不在研修名单的人员
  333. returnTrains.RemoveAll(x => !members.Select(y => y.id).Contains(x.id));
  334. returnTrains.ForEach(x => {
  335. var mbm = members.Find(y => y.id.Equals(x.id));
  336. if (mbm != null)
  337. {
  338. x.groupName = mbm?.groupName;
  339. x.name = !string.IsNullOrWhiteSpace(x.name) ? x.name : mbm?.name;
  340. x.nickname = mbm?.nickname;
  341. x.picture = mbm?.picture;
  342. x.groupName = mbm?.groupName;
  343. }
  344. });
  345. return (returnTrains, yxtrain);
  346. }
  347. public static async Task<List<TeacherTrain>> GetStatisticsTeacher(List<TeacherTrain> trains, AreaSetting setting, Area area, CosmosClient client, List<Study> studies)
  348. {
  349. List<Task<TeacherTrain>> teachers = new List<Task<TeacherTrain>>();
  350. foreach (var train in trains)
  351. {
  352. teachers.Add(StatisticsTeacher(train, setting, area, client, studies)); //yield return await StatisticsTeacher( train, setting, area, client);
  353. }
  354. int pagesize = 50;
  355. if (teachers.Count <= pagesize)
  356. {
  357. await Task.WhenAll(teachers);
  358. }
  359. else
  360. {
  361. int pages = (teachers.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  362. for (int i = 0; i < pages; i++)
  363. {
  364. var lists = teachers.Skip((i) * pagesize).Take(pagesize).ToList();
  365. await Task.WhenAll(lists);
  366. }
  367. }
  368. return trains;
  369. }
  370. public static async Task<TeacherTrain> StatisticsTeacher(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, List<Study> studies)
  371. {
  372. string _school = train.school;
  373. string _tmdid = train.tmdid;
  374. // TeacherTrain teacher_train = null;
  375. List<Task<TeacherTrain>> teachers = new List<Task<TeacherTrain>>();
  376. if (train.update.Count > 0)
  377. {
  378. foreach (string property in train.update)
  379. {
  380. teachers.Add(DoProperty(train.update, property, setting, area, client, train, studies));
  381. }
  382. int pagesize = 50;
  383. if (teachers.Count <= pagesize)
  384. {
  385. await Task.WhenAll(teachers);
  386. }
  387. else
  388. {
  389. int pages = (teachers.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  390. for (int i = 0; i < pages; i++)
  391. {
  392. var lists = teachers.Skip((i) * pagesize).Take(pagesize).ToList();
  393. await Task.WhenAll(lists);
  394. }
  395. }
  396. }
  397. //每次都统计活动相关的数据。
  398. // train= await DoActivity(train, setting, area, client, _school, _tmdid);
  399. train.totalTime = train.onlineTime + train.classTime + train.currency.submitTime + train.offlineTime;
  400. if (train.totalTime >= setting.allTime)
  401. {
  402. //如果总学生超过50 且不是优秀则至少是合格。
  403. if (train.finalScore != 2)
  404. {
  405. train.finalScore = 1;
  406. }
  407. }
  408. // 50> 学时>0 是不合格
  409. else if (train.totalTime < setting.allTime && train.totalTime > 0)
  410. {
  411. train.finalScore = 0;
  412. }
  413. else
  414. {
  415. //学时<=0 则是为
  416. train.finalScore = -1;
  417. }
  418. await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TeacherTrain>(train, new PartitionKey($"TeacherTrain-{_school}"));
  419. return train;
  420. }
  421. private static async Task<TeacherTrain> DoProperty(HashSet<string> updateProperty, string property, AreaSetting setting, Area area, CosmosClient client, TeacherTrain train, List<Study> studies)
  422. {
  423. string _school = train.school;
  424. string _tmdid = train.tmdid;
  425. switch (property)
  426. {
  427. case TeacherAbility:
  428. train = await DoTeacherAbility(train, setting, area, client, _school, _tmdid);
  429. train.update.Remove(TeacherAbility);
  430. break;
  431. //课堂实录更新
  432. case TeacherClass:
  433. train = await DoTeacherClass(train, setting, area, client, _school, _tmdid);
  434. train.update.Remove(TeacherClass);
  435. break;
  436. //线下研修
  437. case OfflineRecord:
  438. train = await DoOfflineRecord(train, setting, area, client, _school, _tmdid, studies);
  439. train.update.Remove(OfflineRecord);
  440. break;
  441. //投票
  442. case TeacherVote:
  443. train = await DoTeacherVote(train, setting, area, client, _school, _tmdid);
  444. train.update.Remove(TeacherVote);
  445. break;
  446. //问卷
  447. case TeacherSurvey:
  448. train = await DoTeacherSurvey(train, setting, area, client, _school, _tmdid);
  449. train.update.Remove(TeacherSurvey);
  450. break;
  451. //作业
  452. //case TeacherHomework:
  453. // train = await DoTeacherHomework(train, setting, area, client, _school, _tmdid);
  454. // train.updateProperty.Remove(TeacherHomework);
  455. // break;
  456. //评测
  457. case TeacherExamLite:
  458. train = await DoTeacherExamLite(train, setting, area, client, _school, _tmdid);
  459. train.update.Remove(TeacherExamLite);
  460. break;
  461. default:
  462. train.update.Remove(property);
  463. break;
  464. }
  465. return train;
  466. }
  467. public static async Task<TeacherTrain> DoTeacherVote(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  468. {
  469. int voteJoin = 0;
  470. int voteDone = 0;
  471. int voteAreaJoin = 0;
  472. int voteAreaDone = 0;
  473. //投票活动
  474. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  475. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'Vote' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  476. {
  477. if (!string.IsNullOrEmpty(item.owner))
  478. {
  479. if (item.owner.Equals("school"))
  480. {
  481. voteJoin += 1;
  482. if (item.taskStatus > 0)
  483. {
  484. voteDone += 1;
  485. }
  486. }
  487. else if (item.owner.Equals("area"))
  488. {
  489. voteAreaJoin += 1;
  490. if (item.taskStatus > 0)
  491. {
  492. voteAreaDone += 1;
  493. }
  494. }
  495. }
  496. }
  497. train.voteJoin = voteJoin;
  498. train.voteDone = voteDone;
  499. train.voteAreaJoin = voteAreaJoin;
  500. train.voteAreaDone = voteAreaDone;
  501. return train;
  502. }
  503. public static async Task<TeacherTrain> DoTeacherSurvey(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  504. {
  505. //问卷调查
  506. int surveyJoin = 0;
  507. int surveyDone = 0;
  508. int surveyAreaJoin = 0;
  509. int surveyAreaDone = 0;
  510. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  511. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'Survey' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  512. {
  513. if (!string.IsNullOrEmpty(item.owner))
  514. {
  515. if (item.owner.Equals("school"))
  516. {
  517. surveyJoin += 1;
  518. if (item.taskStatus > 0)
  519. {
  520. surveyDone += 1;
  521. }
  522. }
  523. else if (item.owner.Equals("area"))
  524. {
  525. surveyAreaJoin += 1;
  526. if (item.taskStatus > 0)
  527. {
  528. surveyAreaDone += 1;
  529. }
  530. }
  531. }
  532. }
  533. train.surveyJoin = surveyJoin;
  534. train.surveyDone = surveyDone;
  535. train.surveyAreaJoin = surveyAreaJoin;
  536. train.surveyAreaDone = surveyAreaDone;
  537. return train;
  538. }
  539. public static async Task<TeacherTrain> DoTeacherExamLite(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  540. {
  541. //问卷调查
  542. int examJoin = 0;
  543. int examDone = 0;
  544. int examAreaJoin = 0;
  545. int examAreaDone = 0;
  546. //评量检测
  547. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  548. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'ExamLite' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  549. {
  550. if (!string.IsNullOrEmpty(item.owner))
  551. {
  552. if (item.owner.Equals("school"))
  553. {
  554. examJoin += 1;
  555. if (item.taskStatus > 0)
  556. {
  557. examDone += 1;
  558. }
  559. }
  560. else if (item.owner.Equals("area"))
  561. {
  562. examAreaJoin += 1;
  563. if (item.taskStatus > 0)
  564. {
  565. examAreaDone += 1;
  566. }
  567. }
  568. }
  569. }
  570. train.examJoin = examJoin;
  571. train.examDone = examDone;
  572. train.examAreaJoin = examAreaJoin;
  573. train.examAreaDone = examAreaDone;
  574. return train;
  575. }
  576. /// <summary>
  577. /// 课堂实录更新
  578. /// </summary>
  579. /// <param name="train"></param>
  580. /// <param name="setting"></param>
  581. /// <param name="area"></param>
  582. /// <param name="client"></param>
  583. /// <param name="_school"></param>
  584. /// <param name="_tmdid"></param>
  585. /// <returns></returns>
  586. public static async Task<TeacherTrain> DoOfflineRecord(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid, List<Study> studies)
  587. {
  588. //owner: school area
  589. //线下 学校研修活动
  590. List<StuActivity> activities = new List<StuActivity>();
  591. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  592. .GetItemQueryIterator<StuActivity>(queryText: $"select value(c) from c where c.type = 'Study' and c.owner<>'area' and c.school='{_school}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  593. {
  594. activities.Add(item);
  595. }
  596. string insql = "";
  597. if (studies.IsEmpty())
  598. {
  599. studies = new List<Study>();
  600. if (activities.IsNotEmpty())
  601. {
  602. insql = $" where c.id in ({string.Join(",", activities.Select(o => $"'{o.id}'"))})";
  603. await foreach (var item in client.GetContainer("TEAMModelOS", "Common")
  604. .GetItemQueryIterator<Study>(queryText: $"select value(c) from c {insql} and c.owner<>'area' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{_school}") }))
  605. {
  606. studies.Add(item);
  607. }
  608. }
  609. }
  610. List<StudyRecord> studyRecords = new List<StudyRecord>();
  611. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  612. .GetItemQueryIterator<StudyRecord>(queryText: $"select value(c) from c {insql} ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StudyRecord-{_tmdid}") }))
  613. {
  614. studyRecords.Add(item);
  615. }
  616. List<HomeworkRecord> homeworkRecords = new List<HomeworkRecord>();
  617. List<Study> workids = studies.FindAll(x => !string.IsNullOrEmpty(x.workId));
  618. bool haswork = false;
  619. List<string> workidSubmits = new List<string>();
  620. if (workids.IsNotEmpty())
  621. {
  622. string rcdsql = $" where c.id in ({string.Join(",", workids.Select(o => $"'{o.workId}'"))})";
  623. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  624. .GetItemQueryIterator<HomeworkRecord>(queryText: $"select value(c) from c {rcdsql} ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"HomeworkRecord-{_tmdid}") }))
  625. {
  626. var content = item.content.FindAll(x => x.prime);
  627. if (content.IsNotEmpty())
  628. {
  629. workidSubmits.Add(item.id);
  630. }
  631. homeworkRecords.Add(item);
  632. }
  633. //标记已经有需要提交作业的线下研修活动。则需要检查至少有一次的作业提交记录。否则不能获得学时。
  634. haswork = true;
  635. }
  636. //如果交了至少一份作业
  637. //一份作业都没有交
  638. //标记是否计算所有学时。
  639. bool getAll = false;
  640. if (haswork)
  641. {
  642. //如果有作业就需要检查是否至少交了一份作业。 如果交了一份,并且通过了,则可以计算全部。具体查看mark qweorrty
  643. getAll = false;
  644. }
  645. else
  646. {
  647. //如果没有作业,则计算全部学时。
  648. getAll = true;
  649. }
  650. activities.ForEach(item => {
  651. Study study = studies.Find(y => y.id.Equals(item.id) && !string.IsNullOrEmpty(y.workId));
  652. if (study != null)
  653. {
  654. StudyRecord studyRecord = studyRecords.Find(y => y.id.Equals(item.id));
  655. if (studyRecord != null && studyRecord.status > 0)
  656. {
  657. //mark qweorrty
  658. var submit = workidSubmits.Find(y => y.Equals(study.workId));
  659. if (submit != null)
  660. {
  661. getAll = true;
  662. }
  663. }
  664. }
  665. });
  666. List<OfflineRecord> offlines = new List<OfflineRecord>();
  667. activities.ForEach(item =>
  668. {
  669. Study study = studies.Find(y => y.id.Equals(item.id));
  670. if (study != null)
  671. {
  672. StudyRecord studyRecord = studyRecords.Find(y => y.id.Equals(item.id));
  673. OfflineRecord record = new OfflineRecord
  674. {
  675. id = item.id,
  676. name = item.name,
  677. done = item.taskStatus,
  678. owner = item.owner,
  679. sethour = study.hour
  680. };
  681. bool workOk = false;
  682. if (!string.IsNullOrEmpty(study.workId))
  683. {
  684. HomeworkRecord homeworkRecord = homeworkRecords.Find(y => y.id.Equals(study.workId));
  685. record.other = homeworkRecord?.content;
  686. Attachment attachment = homeworkRecord?.content.Find(x => x.prime);
  687. record.haswork = 1;
  688. if (null != attachment)
  689. {
  690. record.url = attachment.url;
  691. record.upload = 1;
  692. record.hash = attachment.hash;
  693. record.size = attachment.size;
  694. workOk = true;
  695. }
  696. }
  697. if (studyRecord != null)
  698. {
  699. if (getAll)
  700. {
  701. record.hour = studyRecord.status == 1 ? study.hour : 0;
  702. record.score = studyRecord.status;
  703. if (record.score >= 0)
  704. {
  705. record.done = 1;
  706. }
  707. else
  708. {
  709. record.score = -1;
  710. }
  711. }
  712. else
  713. {
  714. if (workOk && !string.IsNullOrEmpty(study.workId))
  715. {
  716. record.hour = studyRecord.status == 1 ? study.hour : 0;
  717. record.score = studyRecord.status;
  718. if (record.score >= 0)
  719. {
  720. record.done = 1;
  721. }
  722. else
  723. {
  724. record.score = -1;
  725. }
  726. }
  727. else if (!workOk && !string.IsNullOrEmpty(study.workId))
  728. {
  729. //没有交任何作业,即使通过,也不会获得学时。
  730. record.hour = 0;
  731. record.score = studyRecord.status;
  732. }
  733. else
  734. {
  735. record.hour = studyRecord.status == 1 ? study.hour : 0;
  736. record.score = studyRecord.status;
  737. if (record.score >= 0)
  738. {
  739. record.done = 1;
  740. }
  741. else
  742. {
  743. record.score = -1;
  744. }
  745. }
  746. }
  747. }
  748. offlines.Add(record);
  749. }
  750. });
  751. //标记已经有需要提交作业的线下研修活动。则需要检查至少有一次的作业提交记录。否则不能获得学时。
  752. int sum = offlines.Select(x => x.hour).Sum();
  753. //if (haswork)
  754. //{
  755. // var workd= homeworkRecords.Where(z=>z.content.IsNotEmpty()).SelectMany(x => x.content).Where(y => y.prime);
  756. // if (workd != null && workd.Count() > 0) {
  757. // sum = offlines.Select(x => x.hour).Sum();
  758. // }
  759. //}
  760. //else
  761. //{
  762. // sum = offlines.Select(x => x.hour).Sum();
  763. //}
  764. //有作业,且没有交任何作业。
  765. if (workidSubmits.IsEmpty() && haswork)
  766. {
  767. train.offlineTime = 0;
  768. }
  769. else
  770. {
  771. train.offlineTime = sum > setting.offlineTime ? setting.offlineTime : sum;
  772. }
  773. train.offlineRecords = offlines;
  774. return train;
  775. }
  776. /// <summary>
  777. /// 课堂实录更新
  778. /// </summary>
  779. /// <param name="train"></param>
  780. /// <param name="setting"></param>
  781. /// <param name="area"></param>
  782. /// <param name="client"></param>
  783. /// <param name="_school"></param>
  784. /// <param name="_tmdid"></param>
  785. /// <returns></returns>
  786. public static async Task<TeacherTrain> DoTeacherClass(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  787. {
  788. string code = $"ClassVideo-{_school}";
  789. ClassVideo classVideo = null;
  790. try
  791. {
  792. classVideo = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<ClassVideo>($"{_tmdid}", new PartitionKey(code));
  793. }
  794. catch (Exception ex)
  795. {
  796. classVideo = null;
  797. }
  798. if (classVideo != null && classVideo.files.IsNotEmpty())
  799. {
  800. //2021.11.17 15:05,与J哥确认,取课堂实录第一个。前端也只show第一个视频。
  801. var files = classVideo.files[0];
  802. if (files.score > 0)
  803. {
  804. train.classTime = setting.classTime;
  805. }
  806. else
  807. {
  808. train.classTime = 0;
  809. }
  810. train.teacherClasses = new List<TeacherClass> { new Models.TeacherClass { url = files.url, score = files.score, hash = files.hash, name = files.name, size = files.size } };
  811. }
  812. else
  813. {
  814. train.classTime = 0;
  815. }
  816. return train;
  817. }
  818. public static async Task<TeacherTrain> DoTeacherAbility(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  819. {
  820. //视频播放
  821. List<string> abilityIds = new List<string>();
  822. TeacherFile file = null;
  823. try
  824. {
  825. file = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherFile>(_tmdid, new PartitionKey($"TeacherFile-{_school}"));
  826. }
  827. catch (CosmosException)
  828. {
  829. file = new TeacherFile
  830. {
  831. id = _tmdid,
  832. code = $"TeacherFile-{_school}",
  833. pk = "TeacherFile",
  834. ttl = -1,
  835. };
  836. await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherFile>(file, new PartitionKey($"TeacherFile-{_school}"));
  837. }
  838. List<AbilitySub> abilitySubs = new List<AbilitySub>();
  839. //认证材料
  840. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  841. .GetItemQueryIterator<AbilitySub>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilitySub-{_school}-{_tmdid}") }))
  842. {
  843. abilitySubs.Add(item);
  844. }
  845. List<Ability> abilities = new List<Ability>();
  846. string insql = "";
  847. if (abilitySubs.IsNotEmpty())
  848. {
  849. insql = $" where c.id in ({string.Join(",", abilitySubs.Select(o => $"'{o.id}'"))})";
  850. }
  851. await foreach (var item in client.GetContainer("TEAMModelOS", "Normal")
  852. .GetItemQueryIterator<Ability>(queryText: $"select c.comid, c.id,c.name,c.currency,c.no,c.dimension,c.hour,c.stds,c.abilityCount from c {insql} ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{area.standard}") }))
  853. {
  854. abilities.Add(item);
  855. }
  856. List<Debate> debates = new List<Debate>();
  857. if (abilities.IsNotEmpty())
  858. {
  859. await foreach (var item in client.GetContainer("TEAMModelOS", "School")
  860. .GetItemQueryIterator<Debate>(queryText: $"select distinct value(c) from c join b in c.replies where b.tmdid='{_tmdid}'and c.source='uploadscore' and c.comid in ({string.Join(",", abilities.Select(o => $"'{o.comid}'"))})",
  861. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Debate-{_school}") }))
  862. {
  863. debates.Add(item);
  864. }
  865. }
  866. Currency currency = new Currency();
  867. // Currency currencyAll = new Currency();
  868. abilitySubs.ForEach(item => {
  869. int currencyInt = item.from == 1 ? 1 : 0;
  870. Ability ability = abilities.Find(x => x.id.Equals(item.id));
  871. if (ability != null)
  872. {
  873. if (ability != null)
  874. {
  875. currencyInt = item.from == 0 ? ability.currency : 1;
  876. }
  877. else
  878. {
  879. currencyInt = 0;
  880. }
  881. if (item.uploads.IsNotEmpty())
  882. {
  883. if (currencyInt == 1)
  884. {
  885. currency.uploadDone += item.uploads.Count;
  886. }
  887. // currencyAll.uploadDone += item.uploads.Count;
  888. }
  889. //通过能力点自测
  890. if (item.exerciseScore > 0)
  891. {
  892. if (currencyInt == 1)
  893. {
  894. // 与J哥 ,郭杰确认。只计算通过能力点自测就能获得的成长值。 并取消已学能力点 learnAbility
  895. currency.exerciseAbility += ability.abilityCount;
  896. //并且完全看完视频和文档。
  897. if (item.allDone)
  898. {
  899. currency.learnAbility += 1;
  900. }
  901. }
  902. //并且完全看完视频和文档。
  903. //if (item.allDone)
  904. //{
  905. // currencyAll.learnAbility += 1;
  906. //}
  907. //currencyAll.exerciseAbility += ability.abilityCount;
  908. }
  909. List<TeacherHprecord> hprecords = new List<TeacherHprecord>();
  910. List<Debate> debateOrthers = debates.FindAll(x => x.comid.Equals(ability.comid) && x.replies.IsNotEmpty());
  911. int debateOrther = -1;
  912. List<string> replyIds = new List<string>();
  913. if (debateOrthers.IsNotEmpty())
  914. {
  915. debateOrther = debateOrthers.Count;
  916. var replies = debateOrthers.SelectMany(x => x.replies).Where(z => z.tmdid.Equals(_tmdid));
  917. if (replies != null && replies.Count() > 0)
  918. {
  919. replyIds = replies.Select(x => x.id).ToList();
  920. }
  921. }
  922. TeacherAbility teacherAbility = new Models.TeacherAbility
  923. {
  924. replyIds = replyIds,
  925. debateOrther = debateOrther,
  926. id = ability.id,
  927. currency = currencyInt,
  928. no = ability.no,
  929. name = ability.name,
  930. dimension = ability.dimension,
  931. zpscore = item.self == 0 ? 1 : item.self,
  932. hprecord = hprecords,
  933. uploadHas = item.uploads.Count
  934. };
  935. if (file != null)
  936. {
  937. double view = 0;
  938. file.fileRecords.ForEach(record => {
  939. var abilityVideo = record.files.FindAll(x => x.abilityId.Equals(item.id));
  940. if (abilityVideo.IsNotEmpty())
  941. {
  942. view += record.view;
  943. }
  944. });
  945. //能力点学时限制
  946. int limit = ability.hour * setting.lessonMinutes;
  947. //如果超过 8* 45分钟学时,则直接赋值360(limit)分钟。
  948. view = view / 60;
  949. view = view > limit ? limit : view;
  950. teacherAbility.videoTime = (int)view;
  951. teacherAbility.limitTime = ability.hour;
  952. teacherAbility.onlineTime = setting.lessonMinutes != 0 ? (int)(view / setting.lessonMinutes) : 0;
  953. }
  954. if (item.otherScore.IsNotEmpty())
  955. {
  956. var schoolScore = item.otherScore.Where(x => x.roleType.Equals("school")).FirstOrDefault();
  957. if (schoolScore != null && schoolScore.score >= 0)
  958. {
  959. teacherAbility.xzscore = schoolScore.score;
  960. teacherAbility.xztime = schoolScore.time;
  961. teacherAbility.xztmdid = schoolScore.tmdid;
  962. teacherAbility.xztmdname = schoolScore.tmdname;
  963. }
  964. var hprecord = item.otherScore.FindAll(x => x.roleType.Equals("member")).Select(y => new TeacherHprecord { tmdid = y.tmdid, tmdname = y.tmdname, score = y.score });
  965. if (hprecord != null)
  966. {
  967. var no = hprecord.Where(x => x.score == 0) != null ? hprecord.Where(x => x.score == 0).Count() : 0;
  968. var hg = hprecord.Where(x => x.score == 1) != null ? hprecord.Where(x => x.score == 1).Count() : 0;
  969. var yx = hprecord.Where(x => x.score == 2) != null ? hprecord.Where(x => x.score == 2).Count() : 0;
  970. if (no == hg && hg == yx && no == 0)
  971. {
  972. //未评分 合格,优秀都是0 则未评分
  973. teacherAbility.hpscore = -1;
  974. }
  975. else if (no == hg && hg == yx && no != 0)
  976. {
  977. //未评分,合格,优秀不为0 且一样,按优秀算
  978. teacherAbility.hpscore = 2;
  979. }
  980. else
  981. {
  982. bool ok = false;
  983. List<int> arr = new List<int>() { yx, hg, no };
  984. int max = arr.Max();
  985. //有优秀按优秀算
  986. if (max == yx && !ok)
  987. {
  988. teacherAbility.hpscore = 2;
  989. ok = true;
  990. }
  991. //最高评分是合格,按合格算
  992. if (max == hg && !ok)
  993. {
  994. teacherAbility.hpscore = 1;
  995. ok = true;
  996. }
  997. //最高评分是未评分则按未评分算
  998. if (max == no && !ok)
  999. {
  1000. teacherAbility.hpscore = 0;
  1001. ok = true;
  1002. }
  1003. }
  1004. teacherAbility.hprecord.AddRange(hprecord);
  1005. }
  1006. }
  1007. if (currencyInt == 1)
  1008. {
  1009. currency.subCount += 1;
  1010. currency.uploadTotal += ability.stds.FindAll(x => x.task.IsNotEmpty()).Select(y => y.task).Count();
  1011. currency.teacherAilities.Add(teacherAbility);
  1012. }
  1013. // currencyAll.subCount += 1;
  1014. // currencyAll.uploadTotal += ability.stds.FindAll(x => x.task.IsNotEmpty()).Select(y => y.task).Count();
  1015. // currencyAll.teacherAilities.Add(teacherAbility);
  1016. }
  1017. });
  1018. train.currency = currency;
  1019. // train.currencyAll = currencyAll;
  1020. train.currency.videoTime = train.currency.teacherAilities.Select(x => x.videoTime).Sum();
  1021. // train.currencyAll.videoTime = train.currencyAll.teacherAilities.Select(x => x.videoTime).Sum();
  1022. //如果总分钟数超过20学时,则直接复制20学时。
  1023. var videoTime = setting.lessonMinutes != 0 ? (int)(train.currency.videoTime / setting.lessonMinutes) : 0;
  1024. train.onlineTime = videoTime > setting.onlineTime ? setting.onlineTime : videoTime;
  1025. var bhg = train.currency.teacherAilities.FindAll(x => x.xzscore > 0);
  1026. //由于有教师在省平台勾选太多能力点,暂时获得xzscore 数量大于三个的,也能获得学时
  1027. int limitAbility = 3;
  1028. if (setting.limitAbility != -1) {
  1029. limitAbility=setting.limitAbility;
  1030. }
  1031. if (bhg.IsNotEmpty() && (bhg.Count == train.currency.subCount|| bhg.Count>= limitAbility))
  1032. {
  1033. ///要全部合格才能获得学时。
  1034. train.currency.submitTime = setting.submitTime;
  1035. // train.currencyAll.submitTime = setting.submitTime;
  1036. }
  1037. return train;
  1038. }
  1039. }
  1040. }