StatisticsService.cs 50 KB

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