StatisticsService.cs 50 KB

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