StatisticsService.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  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. namespace TEAMModelOS.SDK
  15. {
  16. public static class StatisticsService
  17. {
  18. /// <summary>
  19. /// 教师能力点操作
  20. /// </summary>
  21. public const string TeacherAility = "TeacherAility";
  22. /// <summary>
  23. /// 课堂实录
  24. /// </summary>
  25. public const string TeacherClass = "TeacherClass";
  26. /// <summary>
  27. /// 线下研修
  28. /// </summary>
  29. public const string OfflineRecord = "OfflineRecord";
  30. /// <summary>
  31. /// 教师投票活动
  32. /// </summary>
  33. public const string TeacherVote = "TeacherVote";
  34. /// <summary>
  35. /// 教师作业活动
  36. /// </summary>
  37. public const string TeacherHomework = "TeacherHomework";
  38. /// <summary>
  39. /// 教师问卷活动
  40. /// </summary>
  41. public const string TeacherSurvey = "TeacherSurvey";
  42. /// <summary>
  43. /// 教师评测活动
  44. /// </summary>
  45. public const string TeacherExamLite = "TeacherExamLite";
  46. public static async Task DoChange(TeacherTrainChange change, AzureCosmosFactory _azureCosmos)
  47. {
  48. if (change.tmdids.IsNotEmpty() && change.update.Count() > 0 && !string.IsNullOrEmpty(change.school)) {
  49. var client = _azureCosmos.GetCosmosClient();
  50. string insql = $"where c.id in ({string.Join(",", change.tmdids.Select(x => $"'{x}'"))})";
  51. string selsql = $"select value(c) from c {insql} ";
  52. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  53. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<TeacherTrain>(queryText: selsql,
  54. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{change.school}") }))
  55. {
  56. teacherTrains.Add(item);
  57. }
  58. List<Task<ItemResponse<TeacherTrain>>> task = new List<Task<ItemResponse<TeacherTrain>>>();
  59. teacherTrains.ForEach(x => {
  60. x.update.UnionWith(change.update);
  61. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<TeacherTrain>(x, x.id, new PartitionKey($"TeacherTrain-{change.school}")));
  62. });
  63. await task.TaskPage(5);
  64. var unchange = change.tmdids.Except(teacherTrains.Select(x => x.id));
  65. if (unchange != null)
  66. {
  67. task.Clear();
  68. unchange.ToList().ForEach(x => {
  69. TeacherTrain teacherTrain = new TeacherTrain
  70. {
  71. pk = "TeacherTrain",
  72. id = x,
  73. code = $"TeacherTrain-{change.school}",
  74. tmdid = x,
  75. school = change.school,
  76. update = new HashSet<string> { StatisticsService.TeacherAility,
  77. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  78. };
  79. teacherTrain.update.UnionWith(change.update);
  80. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherTrain>(teacherTrain, new PartitionKey($"TeacherTrain-{change.school}")));
  81. });
  82. await task.TaskPage(5);
  83. }
  84. }
  85. }
  86. public static async Task SendServiceBus((string standard, List<string> tmdids, string school, List<string> update, int statistics)list, IConfiguration _configuration, AzureServiceBusFactory _serviceBus) {
  87. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  88. if (list.tmdids.IsNotEmpty() && list.update.IsNotEmpty()) {
  89. TeacherTrainChange change = new TeacherTrainChange
  90. {
  91. standard = list.standard,
  92. tmdids = list.tmdids,
  93. school = list.school,
  94. update = new HashSet<string>(list.update),
  95. statistics = list.statistics
  96. };
  97. var messageChange = new ServiceBusMessage(change.ToJsonString());
  98. messageChange.ApplicationProperties.Add("name", "TeacherTrainChange");
  99. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
  100. }
  101. }
  102. public static async Task GetAreaAndAreaSetting( string schoolId, string _standard, CosmosClient client, HttpContext httpContext)
  103. {
  104. School school = null;
  105. AreaSetting setting = null;
  106. string standard = "";
  107. if (string.IsNullOrEmpty(_standard))
  108. {
  109. standard = _standard;
  110. }
  111. else if(!string.IsNullOrEmpty(schoolId)) {
  112. //优先找校级
  113. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(schoolId, new PartitionKey("AreaSetting"));
  114. //优先找校级
  115. school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(schoolId, new PartitionKey("Base"));
  116. }
  117. }
  118. public static async Task<List<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>> StatisticsArea(AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing, HashSet<string> updates)
  119. {
  120. List<(List<TeacherTrain> trains, List<RGroupList> yxtrain)> teacherTrains = new List<(List<TeacherTrain> trains, List<RGroupList> yxtrain)>() ;
  121. List<School> schools = new List<School>();
  122. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School")
  123. .GetItemQueryIterator<School>(queryText: $"select value(c) from c where c.areaId='{area.id}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  124. {
  125. schools.Add(item);
  126. }
  127. await foreach ((List<TeacherTrain> trains, List<RGroupList> yxtrain) tarain in GetStatisticsSchool(schools, setting, area, client,_dingDing,updates))
  128. {
  129. teacherTrains.Add(tarain);
  130. }
  131. return teacherTrains;
  132. }
  133. private static async IAsyncEnumerable<(List<TeacherTrain> trains, List<RGroupList> yxtrain)> GetStatisticsSchool(List<School> schools, AreaSetting setting, Area area, CosmosClient client, DingDing _dingDing, HashSet<string> updates)
  134. {
  135. foreach (var school in schools)
  136. {
  137. yield return await StatisticsSchool(school.id, setting, area, client,_dingDing,updates);
  138. }
  139. }
  140. public static async Task<(List<TeacherTrain> trains, List<RGroupList> yxtrain)> StatisticsSchool(string school, AreaSetting setting, Area area, CosmosClient client,DingDing _dingDing,HashSet<string> updates) {
  141. List<RGroupList> yxtrain = await GroupListService.GetGroupListMemberByType(client, "yxtrain", new List<string> { "school" }, $"{school}", _dingDing);
  142. List<TeacherTrain> trains = new List<TeacherTrain>();
  143. var members = yxtrain.SelectMany(x => x.members).ToList();
  144. if (members.Count <= 0)
  145. {
  146. return (trains, yxtrain);
  147. }
  148. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  149. .GetItemQueryIterator<TeacherTrain>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school}") })) {
  150. trains.Add(item);
  151. }
  152. if (updates != null) {
  153. foreach (var up in updates)
  154. {
  155. trains.ForEach(x => x.update.Add(up));
  156. }
  157. }
  158. var update = trains.FindAll(x => x.update.Count() > 0);
  159. var noupdate = trains.FindAll(x => x.update.Count() <=0);
  160. var unStatistics = members.Select(x => x.id).Except(trains.Select(x => x.id));
  161. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  162. List<TeacherTrain> returnTrains = new List<TeacherTrain>();
  163. if (update.IsNotEmpty()) {
  164. teacherTrains.AddRange(update);
  165. }
  166. if (unStatistics != null) {
  167. foreach (string x in unStatistics) {
  168. var member = members.Find(y => y.id.Equals(x));
  169. teacherTrains.Add(new TeacherTrain
  170. {
  171. pk = "TeacherTrain",
  172. id = x,
  173. code = $"TeacherTrain-{school}",
  174. tmdid = x,
  175. name = member.name,
  176. picture=member.picture,
  177. school = school,
  178. update = new HashSet<string> { TeacherAility,TeacherClass,OfflineRecord }
  179. });
  180. }
  181. }
  182. List<Study> studies = new List<Study>();
  183. await foreach (var item in client.GetContainer("TEAMModelOS", "Common")
  184. .GetItemQueryIterator<Study>(queryText: $"select value(c) from c where c.owner<>'area' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{school}") }))
  185. {
  186. studies.Add(item);
  187. }
  188. returnTrains = await GetStatisticsTeacher(teacherTrains, setting, area, client,studies);
  189. //await foreach (var tarain in GetStatisticsTeacher(teacherTrains, setting, area, client))
  190. //{
  191. // returnTrains.Add(tarain);
  192. //}
  193. if (noupdate.IsNotEmpty())
  194. {
  195. returnTrains.AddRange(noupdate);
  196. }
  197. //移除不在研修名单的人员
  198. returnTrains.RemoveAll(x => !members.Select(y => y.id).Contains(x.id));
  199. returnTrains.ForEach(x => {
  200. var mbm= members.Find(y => y.id.Equals(x.id));
  201. if (mbm != null)
  202. {
  203. x.groupName = mbm?.groupName;
  204. x.name = mbm?.name;
  205. x.picture = mbm?.picture;
  206. }
  207. });
  208. return (returnTrains, yxtrain);
  209. }
  210. private static async Task<List<TeacherTrain>> GetStatisticsTeacher(List<TeacherTrain> trains, AreaSetting setting, Area area, CosmosClient client, List<Study> studies)
  211. {
  212. List<Task<TeacherTrain>> teachers = new List<Task<TeacherTrain>>();
  213. foreach (var train in trains)
  214. {
  215. teachers.Add(StatisticsTeacher(train, setting, area, client,studies)); //yield return await StatisticsTeacher( train, setting, area, client);
  216. }
  217. int pagesize = 50;
  218. if (teachers.Count <= pagesize)
  219. {
  220. await Task.WhenAll(teachers);
  221. }
  222. else
  223. {
  224. int pages = (teachers.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  225. for (int i = 0; i < pages; i++)
  226. {
  227. var lists = teachers.Skip((i) * pagesize).Take(pagesize).ToList();
  228. await Task.WhenAll(lists);
  229. }
  230. }
  231. return trains;
  232. }
  233. public static async Task<TeacherTrain> StatisticsTeacher(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client,List<Study> studies) {
  234. string _school = train.school;
  235. string _tmdid = train.tmdid;
  236. // TeacherTrain teacher_train = null;
  237. List<Task<TeacherTrain>> teachers = new List<Task<TeacherTrain>>();
  238. if (train.update.Count > 0) {
  239. foreach (string property in train.update) {
  240. teachers.Add(DoProperty(train.update, property, setting, area, client, train,studies));
  241. }
  242. int pagesize = 50;
  243. if (teachers.Count <= pagesize)
  244. {
  245. await Task.WhenAll(teachers);
  246. }
  247. else
  248. {
  249. int pages = (teachers.Count + pagesize) / pagesize; //256是批量操作最大值,pages = (total + max -1) / max;
  250. for (int i = 0; i < pages; i++)
  251. {
  252. var lists = teachers.Skip((i) * pagesize).Take(pagesize).ToList();
  253. await Task.WhenAll(lists);
  254. }
  255. }
  256. }
  257. //每次都统计活动相关的数据。
  258. // train= await DoActivity(train, setting, area, client, _school, _tmdid);
  259. train.totalTime = train.onlineTime + train.classTime + train.currency.submitTime + train.offlineTime;
  260. if (train.totalTime >= setting.allTime)
  261. {
  262. //如果总学生超过50 且不是优秀则至少是合格。
  263. if (train.finalScore != 2)
  264. {
  265. train.finalScore = 1;
  266. }
  267. }
  268. // 50> 学时>0 是不合格
  269. else if (train.totalTime < setting.allTime && train.totalTime > 0)
  270. {
  271. train.finalScore = 0;
  272. }
  273. else {
  274. //学时<=0 则是为
  275. train.finalScore = -1;
  276. }
  277. await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TeacherTrain>(train, new PartitionKey($"TeacherTrain-{_school}"));
  278. return train;
  279. }
  280. private static async Task<TeacherTrain> DoProperty(HashSet<string> updateProperty,string property, AreaSetting setting, Area area, CosmosClient client, TeacherTrain train ,List<Study> studies )
  281. {
  282. string _school = train.school;
  283. string _tmdid = train.tmdid;
  284. switch (property) {
  285. case TeacherAility:
  286. train = await DoTeacherAility(train, setting, area, client, _school, _tmdid);
  287. train.update.Remove(TeacherAility);
  288. break;
  289. //课堂实录更新
  290. case TeacherClass:
  291. train = await DoTeacherClass(train, setting, area, client, _school, _tmdid);
  292. train.update.Remove(TeacherClass);
  293. break;
  294. //线下研修
  295. case OfflineRecord:
  296. train = await DoOfflineRecord(train, setting, area, client, _school, _tmdid,studies);
  297. train.update.Remove(OfflineRecord);
  298. break;
  299. //投票
  300. case TeacherVote:
  301. train = await DoTeacherVote(train, setting, area, client, _school, _tmdid);
  302. train.update.Remove(TeacherVote);
  303. break;
  304. //问卷
  305. case TeacherSurvey:
  306. train = await DoTeacherSurvey(train, setting, area, client, _school, _tmdid);
  307. train.update.Remove(TeacherSurvey);
  308. break;
  309. //作业
  310. //case TeacherHomework:
  311. // train = await DoTeacherHomework(train, setting, area, client, _school, _tmdid);
  312. // train.updateProperty.Remove(TeacherHomework);
  313. // break;
  314. //评测
  315. case TeacherExamLite:
  316. train = await DoTeacherExamLite(train, setting, area, client, _school, _tmdid);
  317. train.update.Remove(TeacherExamLite);
  318. break;
  319. default:
  320. train.update.Remove(property);
  321. break;
  322. }
  323. return train;
  324. }
  325. public static async Task<TeacherTrain> DoTeacherVote(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid) {
  326. int voteJoin = 0;
  327. int voteDone = 0;
  328. int voteAreaJoin = 0;
  329. int voteAreaDone = 0;
  330. //投票活动
  331. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  332. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'Vote' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  333. {
  334. if (!string.IsNullOrEmpty(item.owner))
  335. {
  336. if (item.owner.Equals("school"))
  337. {
  338. voteJoin += 1;
  339. if (item.taskStatus > 0)
  340. {
  341. voteDone += 1;
  342. }
  343. }
  344. else if (item.owner.Equals("area"))
  345. {
  346. voteAreaJoin += 1;
  347. if (item.taskStatus > 0)
  348. {
  349. voteAreaDone += 1;
  350. }
  351. }
  352. }
  353. }
  354. train.voteJoin = voteJoin;
  355. train.voteDone = voteDone;
  356. train.voteAreaJoin = voteAreaJoin;
  357. train.voteAreaDone = voteAreaDone;
  358. return train;
  359. }
  360. public static async Task<TeacherTrain> DoTeacherSurvey(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  361. {
  362. //问卷调查
  363. int surveyJoin = 0;
  364. int surveyDone = 0;
  365. int surveyAreaJoin = 0;
  366. int surveyAreaDone = 0;
  367. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher")
  368. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'Survey' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  369. {
  370. if (!string.IsNullOrEmpty(item.owner))
  371. {
  372. if (item.owner.Equals("school"))
  373. {
  374. surveyJoin += 1;
  375. if (item.taskStatus > 0)
  376. {
  377. surveyDone += 1;
  378. }
  379. }
  380. else if (item.owner.Equals("area"))
  381. {
  382. surveyAreaJoin += 1;
  383. if (item.taskStatus > 0)
  384. {
  385. surveyAreaDone += 1;
  386. }
  387. }
  388. }
  389. }
  390. train.surveyJoin = surveyJoin;
  391. train.surveyDone = surveyDone;
  392. train.surveyAreaJoin = surveyAreaJoin;
  393. train.surveyAreaDone = surveyAreaDone;
  394. return train;
  395. }
  396. public static async Task<TeacherTrain> DoTeacherExamLite(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  397. {
  398. //问卷调查
  399. int examJoin = 0;
  400. int examDone = 0;
  401. int examAreaJoin = 0;
  402. int examAreaDone = 0;
  403. //评量检测
  404. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  405. .GetItemQueryIterator<StuActivity>(queryText: $"select c.owner, c.taskStatus from c where c.type = 'ExamLite' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Activity-{_tmdid}") }))
  406. {
  407. if (!string.IsNullOrEmpty(item.owner))
  408. {
  409. if (item.owner.Equals("school"))
  410. {
  411. examJoin += 1;
  412. if (item.taskStatus > 0)
  413. {
  414. examDone += 1;
  415. }
  416. }
  417. else if (item.owner.Equals("area"))
  418. {
  419. examAreaJoin += 1;
  420. if (item.taskStatus > 0)
  421. {
  422. examAreaDone += 1;
  423. }
  424. }
  425. }
  426. }
  427. train.examJoin = examJoin;
  428. train.examDone = examDone;
  429. train.examAreaJoin = examAreaJoin;
  430. train.examAreaDone = examAreaDone;
  431. return train;
  432. }
  433. /// <summary>
  434. /// 课堂实录更新
  435. /// </summary>
  436. /// <param name="train"></param>
  437. /// <param name="setting"></param>
  438. /// <param name="area"></param>
  439. /// <param name="client"></param>
  440. /// <param name="_school"></param>
  441. /// <param name="_tmdid"></param>
  442. /// <returns></returns>
  443. public static async Task<TeacherTrain> DoOfflineRecord(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid, List<Study> studies) {
  444. //owner: school area
  445. //线下 学校研修活动
  446. List<StuActivity> activities = new List<StuActivity>();
  447. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  448. .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}") }))
  449. {
  450. activities.Add(item);
  451. }
  452. string insql = "";
  453. if (studies.IsEmpty()) {
  454. studies = new List<Study>();
  455. if (activities.IsNotEmpty())
  456. {
  457. insql = $" where c.id in ({string.Join(",", activities.Select(o => $"'{o.id}'"))})";
  458. }
  459. await foreach (var item in client.GetContainer("TEAMModelOS", "Common")
  460. .GetItemQueryIterator<Study>(queryText: $"select value(c) from c {insql} and c.owner<>'area' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{_school}") }))
  461. {
  462. studies.Add(item);
  463. }
  464. }
  465. List<StudyRecord> studyRecords = new List<StudyRecord>();
  466. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  467. .GetItemQueryIterator<StudyRecord>(queryText: $"select value(c) from c {insql} ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StudyRecord-{_tmdid}") }))
  468. {
  469. studyRecords.Add(item);
  470. }
  471. List<HomeworkRecord> homeworkRecords = new List<HomeworkRecord>();
  472. List<Study> workids= studies.FindAll(x => !string.IsNullOrEmpty(x.workId));
  473. bool haswork=false;
  474. if (workids.IsNotEmpty()) {
  475. string rcdsql = $" where c.id in ({string.Join(",", workids.Select(o => $"'{o.workId}'"))})";
  476. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  477. .GetItemQueryIterator<HomeworkRecord>(queryText: $"select value(c) from c {rcdsql} ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"HomeworkRecord-{_tmdid}") }))
  478. {
  479. homeworkRecords.Add(item);
  480. }
  481. //标记已经有需要提交作业的线下研修活动。则需要检查至少有一次的作业提交记录。否则不能获得学时。
  482. haswork = true;
  483. }
  484. List<OfflineRecord> offlines = new List<OfflineRecord>();
  485. activities.ForEach(item => {
  486. if (item.id.Equals("c974b96d-cdf6-48d5-9074-8c1a02d2cac5")) {
  487. Console.WriteLine(item.id);
  488. }
  489. Study study = studies.Find(y => y.id.Equals(item.id));
  490. if (study != null) {
  491. StudyRecord studyRecord = studyRecords.Find(y => y.id.Equals(item.id));
  492. OfflineRecord record = new OfflineRecord
  493. {
  494. id = item.id,
  495. name = item.name,
  496. done = item.taskStatus,
  497. owner = item.owner
  498. };
  499. record.sethour = study.hour;
  500. if (!string.IsNullOrEmpty(study.workId))
  501. {
  502. HomeworkRecord homeworkRecord = homeworkRecords.Find(y => y.id.Equals(study.workId));
  503. Attachment attachment = homeworkRecord != null ? homeworkRecord.content.Find(x => x.prime) : null;
  504. record.haswork = 1;
  505. //有作业的必须检查有没有提交作业,只有提交作业通过才能统计获得学时。
  506. if (null != attachment)
  507. {
  508. record.url = attachment.url;
  509. record.upload = 1;
  510. record.hash = attachment.hash;
  511. record.size = attachment.size;
  512. if (null != studyRecord)
  513. {
  514. //通过获得学时
  515. record.hour = studyRecord.status == 1 ? study.hour : 0;
  516. record.score = studyRecord.status;
  517. if (record.score >= 0)
  518. {
  519. record.done = 1;
  520. }
  521. else
  522. {
  523. record.score = -1;
  524. }
  525. }
  526. else
  527. {
  528. }
  529. }
  530. else {
  531. }
  532. }
  533. else
  534. {
  535. //没有作业的 可以直接统计通过获得学时
  536. if (null != studyRecord)
  537. {
  538. //通过获得学时
  539. record.hour = studyRecord.status == 1 ? study.hour : 0;
  540. record.score = studyRecord.status;
  541. if (record.score >= 0)
  542. {
  543. record.done = 1;
  544. }
  545. else
  546. {
  547. record.score = -1;
  548. }
  549. }
  550. }
  551. offlines.Add(record);
  552. }
  553. });
  554. //标记已经有需要提交作业的线下研修活动。则需要检查至少有一次的作业提交记录。否则不能获得学时。
  555. int sum = 0;
  556. if (haswork)
  557. {
  558. var workd= homeworkRecords.Where(z=>z.content.IsNotEmpty()).SelectMany(x => x.content).Where(y => y.prime);
  559. if (workd != null && workd.Count() > 0) {
  560. sum = offlines.Select(x => x.hour).Sum();
  561. }
  562. }
  563. else
  564. {
  565. sum = offlines.Select(x => x.hour).Sum();
  566. }
  567. train.offlineTime =sum >setting.offlineTime?setting.offlineTime: sum;
  568. train.offlineRecords= offlines;
  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> DoTeacherClass(TeacherTrain train, AreaSetting setting, Area area, CosmosClient client, string _school, string _tmdid)
  582. {
  583. string code = $"ClassVideo-{_school}";
  584. ClassVideo classVideo = null;
  585. try { classVideo = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<ClassVideo>($"{_tmdid}", new PartitionKey(code));
  586. } catch (Exception ex) {
  587. classVideo = null;
  588. }
  589. if (classVideo != null && classVideo.files.IsNotEmpty())
  590. {
  591. //2021.11.17 15:05,与J哥确认,取课堂实录第一个。前端也只show第一个视频。
  592. var files = classVideo.files[0];
  593. if (files.score > 0)
  594. {
  595. train.classTime = setting.classTime;
  596. }
  597. else
  598. {
  599. train.classTime = 0;
  600. }
  601. train.teacherClasses = new List<TeacherClass> { new Models.TeacherClass { url = files.url, score = files.score, hash = files.hash, name = files.name, size = files.size } };
  602. }
  603. else {
  604. train.classTime = 0;
  605. }
  606. return train;
  607. }
  608. public static async Task<TeacherTrain> DoTeacherAility(TeacherTrain train, AreaSetting setting,Area area , CosmosClient client,string _school,string _tmdid) {
  609. //视频播放
  610. List<string> abilityIds = new List<string> ();
  611. TeacherFile file = null;
  612. try
  613. {
  614. file = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<TeacherFile>(_tmdid, new PartitionKey($"TeacherFile-{_school}"));
  615. }
  616. catch (CosmosException )
  617. {
  618. file = new TeacherFile
  619. {
  620. id = _tmdid,
  621. code = $"TeacherFile-{_school}",
  622. pk = "TeacherFile",
  623. ttl = -1,
  624. };
  625. await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<TeacherFile>(file, new PartitionKey($"TeacherFile-{_school}"));
  626. }
  627. List<AbilitySub> abilitySubs= new List<AbilitySub> ();
  628. //认证材料
  629. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher")
  630. .GetItemQueryIterator<AbilitySub>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilitySub-{_school}-{_tmdid}") }))
  631. {
  632. abilitySubs.Add(item);
  633. }
  634. List<Ability> abilities = new List<Ability>();
  635. string insql = "";
  636. if (abilitySubs.IsNotEmpty()) {
  637. insql =$" where c.id in ({string.Join(",", abilitySubs.Select(o => $"'{o.id}'"))})";
  638. }
  639. await foreach (var item in client.GetContainer("TEAMModelOS", "Normal")
  640. .GetItemQueryIterator<Ability>(queryText: $"select 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}") }))
  641. {
  642. abilities.Add(item);
  643. }
  644. Currency currency= new Currency();
  645. Currency currencyAll = new Currency();
  646. abilitySubs.ForEach(item => {
  647. int currencyInt = item.from == 1 ? 1 : 0;
  648. Ability ability = abilities.Find(x=>x.id.Equals(item.id));
  649. if (ability != null) {
  650. if (ability != null)
  651. {
  652. currencyInt = item.from == 0 ? ability.currency : 1;
  653. }
  654. else
  655. {
  656. currencyInt = 0;
  657. }
  658. if (item.uploads.IsNotEmpty())
  659. {
  660. if (currencyInt == 1)
  661. {
  662. currency.uploadDone += item.uploads.Count;
  663. }
  664. currencyAll.uploadDone += item.uploads.Count;
  665. }
  666. //通过能力点自测
  667. if (item.exerciseScore > 0)
  668. {
  669. if (currencyInt == 1)
  670. {
  671. // 与J哥 ,郭杰确认。只计算通过能力点自测就能获得的成长值。 并取消已学能力点 learnAbility
  672. currency.exerciseAbility += ability.abilityCount;
  673. //并且完全看完视频和文档。
  674. if (item.allDone)
  675. {
  676. currency.learnAbility += 1;
  677. }
  678. }
  679. //并且完全看完视频和文档。
  680. if (item.allDone)
  681. {
  682. currencyAll.learnAbility += 1;
  683. }
  684. currencyAll.exerciseAbility += ability.abilityCount;
  685. }
  686. List<TeacherHprecord> hprecords = new List<TeacherHprecord>();
  687. TeacherAility teacherAility = new Models.TeacherAility
  688. {
  689. id = ability.id,
  690. currency = currencyInt,
  691. no = ability.no,
  692. name = ability.name,
  693. dimension = ability.dimension,
  694. zpscore = item.self,
  695. hprecord = hprecords,
  696. uploadHas = item.uploads.Count
  697. };
  698. if (file != null)
  699. {
  700. long view = 0;
  701. file.fileRecords.ForEach(record => {
  702. var abilityVideo = record.files.FindAll(x => x.abilityId.Equals(item.id));
  703. if (abilityVideo.IsNotEmpty())
  704. {
  705. view += record.view;
  706. }
  707. });
  708. //能力点学时限制
  709. int limit = ability.hour * setting.lessonMinutes;
  710. //如果超过 8* 45分钟学时,则直接赋值360(limit)分钟。
  711. view = view / 60;
  712. view = view > limit ? limit : view;
  713. teacherAility.videoTime = view;
  714. teacherAility.limitTime = ability.hour;
  715. teacherAility.onlineTime = view / setting.lessonMinutes;
  716. }
  717. if (item.otherScore.IsNotEmpty())
  718. {
  719. var schoolScore = item.otherScore.Where(x => x.roleType.Equals("school")).FirstOrDefault();
  720. if (schoolScore != null && schoolScore.score >= 0)
  721. {
  722. teacherAility.xzscore = schoolScore.score;
  723. teacherAility.xztime = schoolScore.time;
  724. teacherAility.xztmdid = schoolScore.tmdid;
  725. teacherAility.xztmdname = schoolScore.tmdname;
  726. }
  727. var hprecord = item.otherScore.FindAll(x => x.roleType.Equals("member")).Select(y => new TeacherHprecord { tmdid = y.tmdid, tmdname = y.tmdname, score = y.score });
  728. if (hprecord != null)
  729. {
  730. var no = hprecord.Where(x => x.score == 0) != null ? hprecord.Where(x => x.score == 0).Count() : 0;
  731. var hg = hprecord.Where(x => x.score == 1) != null ? hprecord.Where(x => x.score == 1).Count() : 0;
  732. var yx = hprecord.Where(x => x.score == 2) != null ? hprecord.Where(x => x.score == 2).Count() : 0;
  733. if (no == hg && hg == yx && no == 0)
  734. {
  735. teacherAility.hpscore = -1;
  736. }
  737. else if (no == hg && hg == yx && no != 0)
  738. {
  739. teacherAility.hpscore = 2;
  740. }
  741. else
  742. {
  743. bool ok = false;
  744. List<int> arr = new List<int>() { yx, hg, no };
  745. int max = arr.Max();
  746. if (max == yx && !ok)
  747. {
  748. teacherAility.hpscore = 2;
  749. ok = true;
  750. }
  751. if (max == hg && !ok)
  752. {
  753. teacherAility.hpscore = 1;
  754. ok = true;
  755. }
  756. if (max == no && !ok)
  757. {
  758. teacherAility.hpscore = 0;
  759. ok = true;
  760. }
  761. }
  762. teacherAility.hprecord.AddRange(hprecord);
  763. }
  764. }
  765. if (currencyInt == 1)
  766. {
  767. currency.subCount += 1;
  768. currency.uploadTotal += ability.stds.FindAll(x => x.task.IsNotEmpty()).Select(y => y.task).Count();
  769. currency.teacherAilities.Add(teacherAility);
  770. }
  771. currencyAll.subCount += 1;
  772. currencyAll.uploadTotal += ability.stds.FindAll(x => x.task.IsNotEmpty()).Select(y => y.task).Count();
  773. currencyAll.teacherAilities.Add(teacherAility);
  774. }
  775. });
  776. train.currency = currency;
  777. train.currencyAll = currencyAll;
  778. train.currency.videoTime = train.currency.teacherAilities.Select(x => x.videoTime).Sum();
  779. train.currencyAll.videoTime= train.currencyAll.teacherAilities.Select(x => x.videoTime).Sum();
  780. //如果总分钟数超过20学时,则直接复制20学时。
  781. var videoTime = (int)train.currency.videoTime / setting.lessonMinutes;
  782. train.onlineTime = videoTime > setting.onlineTime ? setting.onlineTime:videoTime;
  783. var bhg = train.currency.teacherAilities.FindAll(x => x.xzscore > 0);
  784. if (bhg.IsNotEmpty()&& bhg.Count == train.currency.subCount)
  785. {
  786. ///要全部合格才能获得学时。
  787. train.currency.submitTime = setting.submitTime;
  788. train.currencyAll.submitTime = setting.submitTime;
  789. }
  790. return train;
  791. }
  792. }
  793. }