StatisticsService.cs 43 KB

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