ExamController.cs 94 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Dynamic;
  8. using System.IdentityModel.Tokens.Jwt;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Text.Json;
  13. using System.Threading.Tasks;
  14. using TEAMModelOS.Models;
  15. using TEAMModelOS.SDK.Models;
  16. using TEAMModelOS.SDK;
  17. using TEAMModelOS.SDK.Context.Constant.Common;
  18. using TEAMModelOS.SDK.DI;
  19. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  20. using TEAMModelOS.SDK.Extension;
  21. using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
  22. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  23. using TEAMModelOS.SDK.Models.Cosmos.Common;
  24. using TEAMModelOS.SDK.Models.Table;
  25. using Azure.Messaging.ServiceBus;
  26. using Microsoft.Extensions.Configuration;
  27. namespace TEAMModelOS.Controllers
  28. {
  29. [ProducesResponseType(StatusCodes.Status200OK)]
  30. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  31. //[Authorize(Roles = "IES5")
  32. [Route("common/exam")]
  33. [ApiController]
  34. public class ExamController : ControllerBase
  35. {
  36. private readonly AzureCosmosFactory _azureCosmos;
  37. private readonly SnowflakeId _snowflakeId;
  38. private readonly AzureServiceBusFactory _serviceBus;
  39. private readonly DingDing _dingDing;
  40. private readonly Option _option;
  41. private readonly AzureStorageFactory _azureStorage;
  42. private readonly AzureRedisFactory _azureRedis;
  43. public IConfiguration _configuration { get; set; }
  44. public ExamController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
  45. IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
  46. {
  47. _azureCosmos = azureCosmos;
  48. _serviceBus = serviceBus;
  49. _snowflakeId = snowflakeId;
  50. _dingDing = dingDing;
  51. _option = option?.Value;
  52. _azureStorage = azureStorage;
  53. _azureRedis = azureRedis;
  54. _configuration = configuration;
  55. }
  56. /// <summary>
  57. /// 保存考试信息
  58. /// </summary>
  59. /// <param name="request"></param>
  60. /// <returns></returns>
  61. [ProducesDefaultResponseType]
  62. //[AuthToken(Roles = "Teacher")]
  63. [HttpPost("save")]
  64. public async Task<IActionResult> Save(ExamInfo request)
  65. {
  66. try
  67. {
  68. //新增
  69. //string code = request.code;
  70. var client = _azureCosmos.GetCosmosClient();
  71. ExamInfo exam;
  72. string code = request.code;
  73. request.ttl = -1;
  74. request.code = "Exam-" + request.code;
  75. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  76. request.createTime = now;
  77. if (request.startTime <= 0)
  78. {
  79. request.startTime = now;
  80. }
  81. int stuCount = 0;
  82. for (int i = 0; i < request.classes.Count; i++)
  83. {
  84. List<string> ids = new List<string>();
  85. //处理班级人数(公共部分的校本名单)
  86. //List<Student> students = new List<Student>();
  87. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{request.classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{request.school}") }))
  88. {
  89. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  90. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  91. {
  92. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  93. while (accounts.MoveNext())
  94. {
  95. JsonElement account = accounts.Current;
  96. ids.Add(account.GetProperty("id").GetString());
  97. }
  98. }
  99. }
  100. if (request.scope.Equals("private"))
  101. {
  102. //处理发布对象为自选名单(个人)
  103. List<StuList> stuLists = new List<StuList>();
  104. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<StuList>(queryText: $"select value(c) from c where c.id = '{request.classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList") }))
  105. {
  106. stuLists.Add(item);
  107. }
  108. if (stuLists.Count > 0)
  109. {
  110. foreach (StuList stuList in stuLists)
  111. {
  112. foreach (Students students in stuList.students)
  113. {
  114. if (students.code.Contains(code))
  115. {
  116. if (!ids.Contains(students.id))
  117. {
  118. ids.Add(students.id);
  119. }
  120. }
  121. else
  122. {
  123. ids.Add(students.id);
  124. }
  125. }
  126. if (stuList.tmids.Count > 0)
  127. {
  128. foreach (string tid in stuList.tmids)
  129. {
  130. ids.Add(tid);
  131. }
  132. }
  133. }
  134. }
  135. }
  136. else
  137. {
  138. //request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  139. //发布对象为自选名单(校本)
  140. List<StuList> stuLists = new List<StuList>();
  141. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<StuList>(queryText: $"select value(c) from c where c.id = '{request.classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList-{request.school}") }))
  142. {
  143. stuLists.Add(item);
  144. }
  145. if (stuLists.Count > 0)
  146. {
  147. foreach (StuList stuList in stuLists)
  148. {
  149. foreach (Students students in stuList.students)
  150. {
  151. if (students.code.Contains(code))
  152. {
  153. if (!ids.Contains(students.id))
  154. {
  155. ids.Add(students.id);
  156. }
  157. }
  158. else
  159. {
  160. ids.Add(students.id);
  161. }
  162. }
  163. }
  164. }
  165. }
  166. stuCount += ids.Count;
  167. }
  168. request.stuCount = stuCount;
  169. if (string.IsNullOrEmpty(request.id))
  170. {
  171. request.id = Guid.NewGuid().ToString();
  172. if (request.startTime > now)
  173. {
  174. request.progress = "pending";
  175. }
  176. else
  177. {
  178. request.progress = "going";
  179. }
  180. var messageBlob = new ServiceBusMessage();
  181. if (request.scope.Equals("school"))
  182. {
  183. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  184. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"exam/{request.id}", name = request.school }.ToJsonString());
  185. }
  186. else
  187. {
  188. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"exam/{request.id}");
  189. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"exam/{request.id}", name = request.creatorId }.ToJsonString());
  190. }
  191. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  192. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  193. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  194. int n = 0;
  195. foreach (PaperSimple simple in request.papers)
  196. {
  197. simple.blob = "/exam/" + request.id + "/paper/" + request.subjects[n].id;
  198. n++;
  199. }
  200. //request.papers
  201. /*long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
  202. request.sequenceNumber = SequenceNumber;*/
  203. //await _azureStorage.GetBlobContainerClient("hbcn").GetBlobsCatalogSize($"exam/{request.id}");
  204. exam = await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  205. //await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
  206. //request.sequenceNumber = SequenceNumber;
  207. }
  208. else
  209. {
  210. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(request.id, new PartitionKey($"{request.code}"));
  211. if (info.progress.Equals("going"))
  212. {
  213. return Ok(new { v = "活动正在进行中" });
  214. }
  215. var messageBlob = new ServiceBusMessage();
  216. if (request.scope.Equals("school"))
  217. {
  218. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  219. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"exam/{request.id}", name = request.school }.ToJsonString());
  220. }
  221. else
  222. {
  223. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"exam/{request.id}");
  224. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"exam/{request.id}", name = request.creatorId }.ToJsonString());
  225. }
  226. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  227. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  228. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  229. request.progress = info.progress;
  230. int n = 0;
  231. foreach (PaperSimple simple in request.papers)
  232. {
  233. simple.blob = "/exam/" + request.id + "/paper/" + request.subjects[n].id;
  234. n++;
  235. }
  236. /* await _serviceBus.GetServiceBusClient().cancelMessage(Constants.TopicName, info.sequenceNumber);
  237. long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
  238. request.sequenceNumber = SequenceNumber;*/
  239. exam = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(request, request.id, new PartitionKey($"{request.code}"));
  240. //await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
  241. }
  242. //Survey homeWork = await _azureCosmos.SaveOrUpdate<Survey>(request.survey);
  243. //设定结束时间
  244. //string msgEndId = _snowflakeId.NextId() + "";
  245. //await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.endTime);
  246. return Ok(new { exam });
  247. }
  248. catch (Exception ex)
  249. {
  250. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/save()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  251. return BadRequest();
  252. }
  253. }
  254. //TODO blob 批量删除
  255. /// <summary>
  256. /// 删除
  257. /// </summary>
  258. /// <param name="request"></param>
  259. /// <returns></returns>
  260. [ProducesDefaultResponseType]
  261. //[AuthToken(Roles = "Teacher")]
  262. [HttpPost("delete")]
  263. public async Task<IActionResult> Delete(JsonElement request)
  264. {
  265. /* ResponseBuilder builder = ResponseBuilder.custom();
  266. IdPk items = await _azureCosmos.DeleteAsync<ExamInfo>(request.id, request.pk);
  267. await _azureCosmos.DeleteAll<Paper>(new Dictionary<string, object>() { { "code", request.id } });
  268. return builder.Data(items).build();*/
  269. try
  270. {
  271. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  272. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  273. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  274. var client = _azureCosmos.GetCosmosClient();
  275. //string school_code = code.ToString().Substring(typeof(ExamClassResult).Name.Length + 1);
  276. var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
  277. //删除blob 相关资料
  278. await _azureStorage.GetBlobServiceClient().DelectBlobs(code.ToString(), $"exam/{id}");
  279. //通知评测删除信息
  280. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"exam/{id}", name = $"{code}" }.ToJsonString());
  281. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  282. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  283. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  284. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  285. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(queryText: $"select c.id from c where c.examId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  286. {
  287. examClassResults.Add(item);
  288. }
  289. List<string> resultIds = new List<string>();
  290. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
  291. {
  292. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  293. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  294. {
  295. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  296. while (accounts.MoveNext())
  297. {
  298. JsonElement account = accounts.Current;
  299. resultIds.Add(account.GetProperty("id").GetString());
  300. }
  301. }
  302. }
  303. foreach (ExamClassResult classResult in examClassResults)
  304. {
  305. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(classResult.id, new PartitionKey($"ExamClassResult-{code}"));
  306. }
  307. await client.GetContainer("TEAMModelOS", "Common").DeleteItemsStreamAsync(resultIds, $"ExamResult-{id}");
  308. /*foreach (ExamResult result in results)
  309. {
  310. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(result.id, new PartitionKey($"ExamResult-{id}"));
  311. }*/
  312. //await _azureCosmos.DeleteAll(examClassResults);
  313. return Ok(new { id });
  314. }
  315. catch (Exception e)
  316. {
  317. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/delete()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  318. return BadRequest();
  319. }
  320. }
  321. /// <summary>
  322. /// 查询考试信息
  323. /// </summary>
  324. /// <param name="request"></param>
  325. /// <returns></returns>
  326. [ProducesDefaultResponseType]
  327. //[AuthToken(Roles = "Teacher")]
  328. [HttpPost("find")]
  329. public async Task<IActionResult> Find(JsonElement requert)
  330. {
  331. try
  332. {
  333. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  334. var client = _azureCosmos.GetCosmosClient();
  335. List<SchoolYear> years = await _azureStorage.FindListByDict<SchoolYear>(new Dictionary<string, object>() { { "RowKey", code }, { "PartitionKey", "Exam" } });
  336. int year = 0;
  337. if (years.Count > 0)
  338. {
  339. year = years[0].year;
  340. }
  341. else
  342. {
  343. long ct = 0;
  344. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: "SELECT top 1 c.createTime FROM c order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
  345. {
  346. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  347. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  348. {
  349. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  350. while (accounts.MoveNext())
  351. {
  352. JsonElement account = accounts.Current;
  353. ct = account.GetProperty("createTime").GetInt64();
  354. }
  355. }
  356. }
  357. year = DateTimeOffset.FromUnixTimeMilliseconds(ct).Year;
  358. SchoolYear sy = new()
  359. {
  360. RowKey = code.ToString(),
  361. PartitionKey = "Exam",
  362. year = year
  363. };
  364. await _azureStorage.Save<SchoolYear>(sy);
  365. }
  366. var query = $"select c.id,c.name,c.code,c.period,c.startTime,c.endTime,c.stuCount,c.type,c.progress,c.examType,c.createTime,c.source, c.subjects, c.grades, c.scope,c.classes,c.sRate,c.lostStu from c ";
  367. if (requert.TryGetProperty("classIds", out JsonElement classIds))
  368. {
  369. List<string> ids = classIds.ToObject<List<string>>();
  370. HashSet<string> strs = new HashSet<string>();
  371. if (ids.Count > 1)
  372. {
  373. foreach (string id in ids)
  374. {
  375. strs.Add($"array_contains(c.classes,'{id}')");
  376. }
  377. }
  378. else
  379. {
  380. string ssr = ids.Count > 0 ? ids[0] : "";
  381. strs.Add($"array_contains(c.classes,'{ssr}')");
  382. }
  383. string ss = string.Join(" or ", strs);
  384. query = $"select c.id,c.name,c.code,c.period,c.startTime,c.endTime,c.stuCount,c.type,c.progress,c.examType,c.createTime, c.source,c.subjects, c.grades, c.scope,c.classes,c.sRate,c.lostStu from c where ({ss})";
  385. };
  386. string continuationToken = string.Empty;
  387. string token = default;
  388. //是否需要进行分页查询,默认不分页
  389. bool iscontinuation = false;
  390. if (requert.TryGetProperty("token", out JsonElement token_1))
  391. {
  392. token = token_1.GetString();
  393. iscontinuation = true;
  394. };
  395. //默认不指定返回大小
  396. int? topcout = null;
  397. if (requert.TryGetProperty("count", out JsonElement jcount))
  398. {
  399. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  400. {
  401. topcout = data;
  402. }
  403. }
  404. List<ExamInfo> examInfo = new List<ExamInfo>();
  405. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Exam-{code}") }))
  406. {
  407. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  408. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  409. {
  410. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  411. {
  412. //obj.TryGetProperty("progress", out JsonElement progress);
  413. examInfo.Add(obj.ToObject<ExamInfo>());
  414. }
  415. }
  416. if (iscontinuation)
  417. {
  418. continuationToken = item.GetContinuationToken();
  419. break;
  420. }
  421. }
  422. //List<string> examIds = new List<string>();
  423. /* List<ExamResult> examResults = new List<ExamResult>();
  424. foreach (ExamInfo info in examInfos) {
  425. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamResult>(
  426. queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{info.id}") }))
  427. {
  428. examResults.Add(item);
  429. }
  430. }*/
  431. /* List<(string id, double scores)> listExamInfo = new List<(string id, double scores)>();
  432. foreach (ExamInfo info in examInfos)
  433. {
  434. //记录某次考试所有学生得分总分
  435. double score = 0;
  436. double allScore = 0;
  437. int stuCount = 0;
  438. foreach (ExamResult examResult in examResults) {
  439. if (info.id == examResult.examId) {
  440. foreach (List<double> sc in examResult.studentScores) {
  441. score += sc.Sum();
  442. }
  443. stuCount = examResult.studentIds.Count;
  444. }
  445. }
  446. double ascore = stuCount > 0 ? Math.Round(score * 0.1 / stuCount, 2) : 0;
  447. foreach (PaperSimple simple in info.papers) {
  448. allScore += simple.point.Sum();
  449. }
  450. listExamInfo.Add((info.id, (allScore> 0 ? ascore / allScore * 100: 0)));
  451. }
  452. var examInfo = examInfos.Select(o =>
  453. new
  454. {
  455. o.id,
  456. o.scope,
  457. o.stuCount,
  458. o.name,
  459. o.period,
  460. o.startTime,
  461. o.endTime,
  462. o.type,
  463. o.progress,
  464. o.examType,
  465. o.createTime,
  466. o.subjects,
  467. o.grades,
  468. o.classes,
  469. score = listExamInfo.FirstOrDefault(c => c.id == o.id).scores,
  470. }
  471. );*/
  472. return Ok(new { examInfo, token = continuationToken, year });
  473. }
  474. catch (Exception e)
  475. {
  476. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  477. return BadRequest();
  478. }
  479. }
  480. [ProducesDefaultResponseType]
  481. //[AuthToken(Roles = "Teacher")]
  482. [HttpPost("find-summary")]
  483. public async Task<IActionResult> FindSummary(JsonElement requert)
  484. {
  485. try
  486. {
  487. //ResponseBuilder builder = ResponseBuilder.custom();
  488. //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  489. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  490. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  491. //if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  492. //var jwt = new JwtSecurityToken(id_token.GetString());
  493. //if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
  494. //var id = jwt.Payload.Sub;
  495. var client = _azureCosmos.GetCosmosClient();
  496. List<ExamInfo> examInfo = new List<ExamInfo>();
  497. //var query = $"select value(c) from c ";
  498. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
  499. {
  500. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  501. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  502. {
  503. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  504. {
  505. //obj.TryGetProperty("progress", out JsonElement progress);
  506. examInfo.Add(obj.ToObject<ExamInfo>());
  507. }
  508. }
  509. }
  510. return Ok(new { examInfo });
  511. }
  512. catch (Exception e)
  513. {
  514. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  515. return BadRequest();
  516. }
  517. }
  518. /// <summary>
  519. /// 学生回答问题
  520. /// </summary>
  521. /// <param name="request"></param>
  522. /// <returns></returns>
  523. [ProducesDefaultResponseType]
  524. //[AuthToken(Roles = "Teacher")]
  525. [HttpPost("upsert-record")]
  526. public async Task<IActionResult> upsertRecord(JsonElement request)
  527. {
  528. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  529. //if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  530. if (!request.TryGetProperty("answer", out JsonElement answer)) return BadRequest();
  531. if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  532. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  533. if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  534. if (!request.TryGetProperty("multipleRule", out JsonElement multipleRule)) return BadRequest();
  535. //if (!request.TryGetProperty("answers ", out JsonElement tandardAnswer)) return BadRequest();
  536. if (!request.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
  537. //根据不同评测的类型返回对应的编码
  538. if (!request.TryGetProperty("code", out JsonElement school)) return BadRequest();
  539. if (!request.TryGetProperty("scode", out JsonElement scode)) return BadRequest();
  540. try
  541. {
  542. List<string> ids = new List<string>();
  543. ids = classId.ToObject<List<string>>();
  544. var client = _azureCosmos.GetCosmosClient();
  545. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  546. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
  547. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id in ({string.Join(",", ids.Select(o => $"'{o}'"))})",
  548. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  549. {
  550. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  551. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  552. {
  553. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  554. {
  555. examClassResults.Add(obj.ToObject<ExamClassResult>());
  556. }
  557. }
  558. }
  559. ExamClassResult classResult = new ExamClassResult();
  560. List<PaperSimple> standerAnswers = new List<PaperSimple>();
  561. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
  562. queryText: $"select A0.point,A0.answers from c join A0 in c.papers where c.id = '{id}'and A0.id = '{paperId}'",
  563. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  564. {
  565. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  566. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  567. {
  568. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  569. {
  570. standerAnswers.Add(obj.ToObject<PaperSimple>());
  571. }
  572. }
  573. }
  574. List<List<string>> ans = answer.ToObject<List<List<string>>>();
  575. List<List<string>> standard = new List<List<string>>();
  576. List<double> points = new List<double>();
  577. int rule = int.Parse(multipleRule.ToString());
  578. foreach (PaperSimple simple in standerAnswers)
  579. {
  580. standard = simple.answers;
  581. points = simple.point;
  582. }
  583. List<Task<string>> tasks = new List<Task<string>>();
  584. foreach (ExamClassResult result in examClassResults)
  585. {
  586. int index = result.studentIds.IndexOf(studentId.ToString());
  587. //存放客观题作答详情
  588. if (result.ans.Count == 0)
  589. {
  590. foreach (string cc in result.studentIds)
  591. {
  592. List<List<string>> anc = new List<List<string>>();
  593. foreach (List<string> opc in standard)
  594. {
  595. anc.Add(new List<string>());
  596. }
  597. result.ans.Add(anc);
  598. }
  599. }
  600. //List<List<string>> oq = new List<List<string>>();
  601. //classResult.studentAnswers[index] = ans;
  602. if (index == -1)
  603. {
  604. List<double> ansPoint = new List<double>();
  605. foreach (List<string> num in standard)
  606. {
  607. //ans.Add(new List<string>());
  608. ansPoint.Add(-1);
  609. }
  610. result.studentIds.Add(studentId.ToString());
  611. result.studentScores.Add(ansPoint);
  612. result.studentAnswers.Add(new List<string>());
  613. result.sum.Add(0);
  614. }
  615. //int flagCount = 0;
  616. /*foreach (List<string> str in ans) {
  617. if (str.Count == 0) {
  618. flagCount++;
  619. }
  620. } */
  621. int newIndex = result.studentIds.IndexOf(studentId.ToString());
  622. /* if (flagCount != standard.Count)
  623. {*/
  624. StringBuilder builder = new StringBuilder();
  625. builder.Append(result.examId).Append("/");
  626. builder.Append(result.subjectId).Append("/");
  627. builder.Append(studentId).Append("/");
  628. builder.Append("ans.json");
  629. /*string FileName = result.examId + "/" + result.subjectId + "/" + studentId;
  630. string blob = FileName + "/" + "ans.json";*/
  631. tasks.Add(_azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", builder.ToString(), false));
  632. result.studentAnswers[newIndex].Add(builder.ToString());
  633. //}
  634. //List<(int index ,string content, double count)> acount = new List<(int index,string content, double count)>();
  635. for (int i = 0; i < ans.Count; i++)
  636. {
  637. //List<string> op = new List<string>();
  638. var ac = ans[i].Count;
  639. var sc = standard[i].Count;
  640. //记录次数
  641. int n = 0;
  642. //result.studentAnswers[index][i] = ans[i];
  643. //算分处理
  644. if (sc > 0)
  645. {
  646. result.ans[index][i] = ans[i];
  647. if (ac == sc && sc == 1)
  648. {
  649. foreach (string right in ans[i])
  650. {
  651. if (standard[i].Contains(right))
  652. {
  653. result.studentScores[newIndex][i] = points[i];
  654. }
  655. else
  656. {
  657. result.studentScores[newIndex][i] = 0;
  658. }
  659. }
  660. }
  661. else
  662. {
  663. if (rule > 0)
  664. {
  665. int falseCount = 0;
  666. if (ac > 0)
  667. {
  668. foreach (string obj in ans[i])
  669. {
  670. if (!standard[i].Contains(obj))
  671. {
  672. falseCount++;
  673. }
  674. }
  675. switch (rule)
  676. {
  677. case 1:
  678. if (ac == sc)
  679. {
  680. if (falseCount == 0)
  681. {
  682. result.studentScores[newIndex][i] = points[i];
  683. }
  684. else
  685. {
  686. result.studentScores[newIndex][i] = 0;
  687. }
  688. }
  689. else
  690. {
  691. result.studentScores[newIndex][i] = 0;
  692. }
  693. break;
  694. case 2:
  695. if (falseCount > 0)
  696. {
  697. result.studentScores[newIndex][i] = 0;
  698. }
  699. else
  700. {
  701. if (ac == sc)
  702. {
  703. result.studentScores[newIndex][i] = points[i];
  704. }
  705. else
  706. {
  707. result.studentScores[newIndex][i] = points[i] / 2;
  708. }
  709. }
  710. break;
  711. case 3:
  712. if (falseCount > 0)
  713. {
  714. result.studentScores[newIndex][i] = 0;
  715. }
  716. else
  717. {
  718. if (ac == sc)
  719. {
  720. result.studentScores[newIndex][i] = points[i];
  721. }
  722. else
  723. {
  724. result.studentScores[newIndex][i] = System.Math.Round((double)ac / sc * points[i], 1);
  725. }
  726. }
  727. break;
  728. case 4:
  729. if (ac == sc)
  730. {
  731. result.studentScores[newIndex][i] = points[i];
  732. }
  733. else
  734. {
  735. double persent = (double)(sc - 2 * falseCount) / sc;
  736. if (persent <= 0)
  737. {
  738. result.studentScores[newIndex][i] = 0;
  739. }
  740. else
  741. {
  742. result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
  743. }
  744. }
  745. break;
  746. }
  747. }
  748. else
  749. {
  750. result.studentScores[newIndex][i] = 0;
  751. }
  752. }
  753. }
  754. }
  755. }
  756. /*if (result.studentScores.Contains(-1)) {
  757. }*/
  758. bool flag = true;
  759. foreach (List<double> scores in result.studentScores)
  760. {
  761. foreach (double score in scores)
  762. {
  763. if (score == -1)
  764. {
  765. flag = false;
  766. break;
  767. }
  768. }
  769. }
  770. if (flag)
  771. {
  772. ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{scode}"));
  773. result.progress = true;
  774. /*//标记单科单班总得分
  775. double score = 0;
  776. //标准差
  777. double powSum = 0;
  778. var scount = result.studentIds.Count;
  779. foreach (List<double> sc in result.studentScores) {
  780. score += sc.Sum();
  781. }
  782. foreach (string sid in result.studentIds) {
  783. double ssc = result.studentScores[result.studentIds.IndexOf(sid)].Sum();
  784. powSum += Math.Pow(ssc - scount > 0 ? Math.Round(score * 1.0 / scount, 2) : 0, 2);
  785. }
  786. result.standard = Math.Round(scount > 0 ? Math.Pow(powSum / scount, 0.5) : 0, 2);
  787. result.average = scount > 0 ? Math.Round(score / scount, 2) : 0;*/
  788. exam.subjects.ForEach(s =>
  789. {
  790. if (s.id.Equals(subjectId.ToString()))
  791. {
  792. s.classCount += 1;
  793. }
  794. });
  795. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"{scode}"));
  796. }
  797. result.sum[newIndex] = result.studentScores[newIndex].Sum();
  798. classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  799. }
  800. await Task.WhenAll(tasks);
  801. return Ok(new { classResult });
  802. }
  803. catch (Exception e)
  804. {
  805. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertRecord()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  806. return BadRequest();
  807. }
  808. }
  809. [ProducesDefaultResponseType]
  810. //[AuthToken(Roles = "Teacher")]
  811. [HttpPost("upsert-record-by-teacher")]
  812. public async Task<IActionResult> upsertRecordByTeacher(JsonElement request)
  813. {
  814. //ResponseBuilder builder = ResponseBuilder.custom();
  815. try
  816. {
  817. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  818. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  819. if (!request.TryGetProperty("point", out JsonElement point)) return BadRequest();
  820. if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  821. //if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  822. //此参数表明此次操作对象为个人还是校本的评测内容
  823. if (!request.TryGetProperty("school", out JsonElement school)) return BadRequest();
  824. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  825. //要先处理状态,判断卷子是否存在,并判断卷子归属的考试是否允许再次提交
  826. //List<ExamInfo> exams = await _azureCosmos.FindByDict<ExamInfo>(new Dictionary<string, object> { { "id", request.examCode } });
  827. List<double> ans = point.ToObject<List<double>>();
  828. var client = _azureCosmos.GetCosmosClient();
  829. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  830. if (request.TryGetProperty("classId", out JsonElement classId))
  831. {
  832. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  833. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
  834. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  835. {
  836. examClassResults.Add(item);
  837. }
  838. }
  839. else
  840. {
  841. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  842. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and array_contains(c.studentIds,'{studentId}')",
  843. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  844. {
  845. examClassResults.Add(item);
  846. }
  847. }
  848. ExamClassResult classResult = new ExamClassResult();
  849. //ExamInfo classResult = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{code}"));
  850. //ExamClassResult classResult = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamClassResult>(id.ToString(), new PartitionKey($"{code}"));
  851. /*foreach (double index in ans) {
  852. classResult.studentScores.in
  853. }*/
  854. foreach (ExamClassResult result in examClassResults)
  855. {
  856. int index = result.studentIds.IndexOf(studentId.ToString());
  857. for (int i = 0; i < ans.Count; i++)
  858. {
  859. result.studentScores[index][i] = ans[i];
  860. }
  861. if (!result.progress)
  862. {
  863. bool flag = true;
  864. foreach (List<double> scores in result.studentScores)
  865. {
  866. foreach (double score in scores)
  867. {
  868. if (score == -1)
  869. {
  870. flag = false;
  871. break;
  872. }
  873. }
  874. }
  875. if (flag)
  876. {
  877. ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  878. result.progress = true;
  879. exam.subjects.ForEach(s =>
  880. {
  881. if (s.id.Equals(subjectId.ToString()))
  882. {
  883. s.classCount += 1;
  884. }
  885. });
  886. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{code}"));
  887. }
  888. }
  889. else
  890. {
  891. ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  892. exam.updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  893. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{code}"));
  894. }
  895. result.sum[index] = result.studentScores[index].Sum();
  896. classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  897. }
  898. return Ok(new { classResult });
  899. }
  900. catch (Exception ex)
  901. {
  902. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertRecordByTeacher()\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  903. return BadRequest();
  904. }
  905. /*if (exams.IsNotEmpty())
  906. {
  907. ExamInfo examInfo = exams[0];
  908. //提交答案时间必须是状态已发布,且时间在起止时间内
  909. if (examInfo.startTime <= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() && examInfo.status == 200 &&
  910. examInfo.endTime >= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
  911. {
  912. return builder.Data(await _azureCosmos.SaveOrUpdate(request)).build();
  913. }
  914. else
  915. {
  916. return builder.Error(ResponseCode.FAILED, "请在作答时间段内提交答案!").build();
  917. }
  918. }
  919. else
  920. {
  921. return builder.Error(ResponseCode.DATA_EXIST, "考试不存在!").build();
  922. }*/
  923. }
  924. /// <summary>
  925. /// 查询评测详细信息(教师或者学生通用)
  926. /// </summary>
  927. /// <param name="request"></param>
  928. /// <returns></returns>
  929. [ProducesDefaultResponseType]
  930. //[AuthToken(Roles = "Teacher")]
  931. [HttpPost("find-summary-record")]
  932. public async Task<IActionResult> findSummaryRecord(JsonElement requert)
  933. {
  934. //var (id, school) = HttpContext.GetAuthTokenInfo();
  935. try
  936. {
  937. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  938. //if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
  939. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  940. if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
  941. if (!requert.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  942. // 如果只有学生id则返回学生参加过的考试 只返回相关摘要信息
  943. var client = _azureCosmos.GetCosmosClient();
  944. //string code = school_code.ToString().Substring(5);
  945. //ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{school_code}"));
  946. List<object> examClassResults = new List<object>();
  947. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id, c.code,c.info,c.studentIds,c.studentAnswers,c.studentScores,c.mark from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
  948. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school_code}") }))
  949. {
  950. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  951. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  952. {
  953. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  954. {
  955. examClassResults.Add(obj.ToObject<object>());
  956. }
  957. }
  958. }
  959. /*if (StringHelper.getKeyCount(requert) == 1 && requert.TryGetProperty("code", out JsonElement code))
  960. {
  961. List<object> props = new List<object>();
  962. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.code, c.examCode, c.status ,c.mark, c.score from c where c.id = {id}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamRecord-{school_code}") }))
  963. {
  964. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  965. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  966. {
  967. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  968. {
  969. props.Add(obj.ToObject<object>());
  970. }
  971. }
  972. }
  973. return Ok(new { props });
  974. }
  975. else
  976. {
  977. if (requert.TryGetProperty("examCode", out JsonElement _))
  978. {
  979. //List<string> props = new List<string> { "id", "code", "examCode", "status", "mark", "score" };
  980. //List<ExamRecord> examRecords = await _azureCosmos.FindByDict<ExamRecord>(request, props);
  981. //return builder.Data(examRecords).Extend(new Dictionary<string, object> { { "props", props } }).build();
  982. List<object> props = new List<object>();
  983. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.code, c.examCode, c.status ,c.mark, c.score from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamRecord-{school_code}") }))
  984. {
  985. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  986. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  987. {
  988. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  989. {
  990. props.Add(obj.ToObject<object>());
  991. }
  992. }
  993. }
  994. return Ok(new { props });
  995. }
  996. }*/
  997. return Ok(new { examClassResults });
  998. }
  999. catch (Exception ex)
  1000. {
  1001. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findSummaryRecord()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1002. return BadRequest();
  1003. }
  1004. }
  1005. //学生端查询评测列表
  1006. [ProducesDefaultResponseType]
  1007. //[AuthToken(Roles = "Student")]
  1008. [HttpPost("find-summary-by-student")]
  1009. public async Task<IActionResult> findSummaryStudent(JsonElement requert)
  1010. {
  1011. //ResponseBuilder builder = ResponseBuilder.custom();
  1012. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1013. try
  1014. {
  1015. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1016. //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1017. if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  1018. if (!requert.TryGetProperty("code", out JsonElement school)) return BadRequest();
  1019. if (!requert.TryGetProperty("scode", out JsonElement scode)) return BadRequest();
  1020. var client = _azureCosmos.GetCosmosClient();
  1021. var query = $"select c.id,c.code,c.school,c.creatorId,c.progress,A0.id paperId,A0.code paperCode,A0.name paperName,A0.multipleRule,A0.scope,A0.blob from c join A0 in c.papers where c.id ='{id}'";
  1022. List<object> papers = new List<object>();
  1023. List<object> subjects = new List<object>();
  1024. List<string> classIds = new List<string>();
  1025. //存放当前学生所在班级ID或者名单ID
  1026. HashSet<string> resultIds = new HashSet<string>();
  1027. //List<string> ids = new List<string>();
  1028. //处理班级人数(公共部分的校本名单)
  1029. //List<Student> students = new List<Student>();
  1030. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.classId id from c where c.id = '{studentId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{school}") }))
  1031. {
  1032. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1033. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1034. {
  1035. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1036. while (accounts.MoveNext())
  1037. {
  1038. JsonElement account = accounts.Current;
  1039. resultIds.Add(account.GetProperty("id").GetString());
  1040. }
  1041. }
  1042. }
  1043. //获取自定义名单信息
  1044. List<StuList> stuLists = new List<StuList>();
  1045. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<StuList>(queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}'",
  1046. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList") }))
  1047. {
  1048. stuLists.Add(item);
  1049. }
  1050. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<StuList>(queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}'",
  1051. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList-{school}") }))
  1052. {
  1053. stuLists.Add(item);
  1054. }
  1055. if (stuLists.Count > 0)
  1056. {
  1057. foreach (StuList stuList in stuLists)
  1058. {
  1059. resultIds.Add(stuList.id);
  1060. }
  1061. }
  1062. var queryClassId = $"select c.classes id from c where c.id ='{id}'";
  1063. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryClassId, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1064. {
  1065. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1066. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1067. {
  1068. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1069. {
  1070. classIds = obj.GetProperty("id").ToObject<List<string>>();
  1071. //classIds = obj.ToObject<List<string>>();
  1072. }
  1073. }
  1074. }
  1075. //存放该学生所在班级参与当前评测的ID
  1076. List<string> infoIds = new List<string>();
  1077. foreach (string ids in resultIds)
  1078. {
  1079. if (classIds.Contains(ids))
  1080. {
  1081. infoIds.Add(ids);
  1082. }
  1083. }
  1084. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1085. {
  1086. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1087. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1088. {
  1089. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1090. {
  1091. papers.Add(obj.ToObject<object>());
  1092. }
  1093. }
  1094. }
  1095. var querySubject = $"select A0.id,A0.name from c join A0 in c.subjects where c.id ='{id}'";
  1096. //List<object> props = new List<object>();
  1097. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: querySubject, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1098. {
  1099. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1100. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1101. {
  1102. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1103. {
  1104. subjects.Add(obj.ToObject<object>());
  1105. }
  1106. }
  1107. }
  1108. var queryAnswers = $"select c.id,c.code,c.studentIds,c.subjectId,c.studentAnswers,c.studentScores,c.sum,c.mark from c where c.examId ='{id}' and array_contains(c.studentIds,'{studentId}') and c.pk = 'ExamClassResult' ";
  1109. List<ExamClassResult> answers = new List<ExamClassResult>();
  1110. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryAnswers,
  1111. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  1112. {
  1113. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1114. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1115. {
  1116. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1117. {
  1118. answers.Add(obj.ToObject<ExamClassResult>());
  1119. }
  1120. }
  1121. }
  1122. List<List<string>> stuAns = new List<List<string>>();
  1123. List<List<double>> stuScore = new List<List<double>>();
  1124. List<string> mark = new List<string>();
  1125. List<double> total = new List<double>();
  1126. if (answers.Count > 0)
  1127. {
  1128. foreach (ExamClassResult result in answers)
  1129. {
  1130. int index = result.studentIds.IndexOf(studentId.ToString());
  1131. if (index == -1)
  1132. {
  1133. break;
  1134. }
  1135. stuAns.Add(result.studentAnswers[index]);
  1136. stuScore.Add(result.studentScores[index]);
  1137. if (result.mark.Count > 0)
  1138. {
  1139. mark.Add(result.mark[index]);
  1140. }
  1141. total.Add(result.sum.Where(s => s <= 59).Count());
  1142. total.Add(result.sum.Where(s => s > 59 && s <= 70).Count());
  1143. total.Add(result.sum.Where(s => s > 70 && s <= 80).Count());
  1144. total.Add(result.sum.Where(s => s > 80 && s <= 90).Count());
  1145. total.Add(result.sum.Where(s => s > 90 && s <= 100).Count());
  1146. }
  1147. }
  1148. return Ok(new { papers, subjects, stuScore, stuAns, mark, total, claId = infoIds });
  1149. }
  1150. catch (Exception ex)
  1151. {
  1152. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find-summary-by-student()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1153. return BadRequest();
  1154. }
  1155. }
  1156. //查询学生活动列表
  1157. [ProducesDefaultResponseType]
  1158. //[AuthToken(Roles = "Student")]
  1159. [HttpPost("find-all-by-student")]
  1160. public async Task<IActionResult> findAllStudent(JsonElement requert)
  1161. {
  1162. //ResponseBuilder builder = ResponseBuilder.custom();
  1163. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1164. try
  1165. {
  1166. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1167. if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  1168. List<string> resultIds = new List<string>();
  1169. var client = _azureCosmos.GetCosmosClient();
  1170. //查询校本班级ID
  1171. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(
  1172. queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}' and c.pk = 'Class' "))
  1173. {
  1174. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1175. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1176. {
  1177. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1178. while (accounts.MoveNext())
  1179. {
  1180. JsonElement account = accounts.Current;
  1181. resultIds.Add(account.GetProperty("id").GetString());
  1182. }
  1183. }
  1184. }
  1185. //查询私人班级ID
  1186. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(
  1187. queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}' and c.pk = 'Class' "))
  1188. {
  1189. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1190. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1191. {
  1192. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1193. while (accounts.MoveNext())
  1194. {
  1195. JsonElement account = accounts.Current;
  1196. resultIds.Add(account.GetProperty("id").GetString());
  1197. }
  1198. }
  1199. }
  1200. //StringBuilder builder = new StringBuilder();
  1201. HashSet<string> strs = new HashSet<string>();
  1202. if (resultIds.Count > 1)
  1203. {
  1204. foreach (string str in resultIds)
  1205. {
  1206. strs.Add($"array_contains(c.classes,'{str}')");
  1207. //builder.Append($"array_contains(c.targetClassIds,'{str}')").Append("or");
  1208. }
  1209. //builder.ToString().Substring(0, builder.ToString().Length - 2);
  1210. }
  1211. else
  1212. {
  1213. string ssr = resultIds.Count > 0 ? resultIds[0] : "";
  1214. strs.Add($"array_contains(c.classes,'{ssr}')");
  1215. //builder.Append($" array_contains(c.targetClassIds,'{ssr}')");
  1216. }
  1217. string ss = string.Join(" or ", strs);
  1218. //if (!requert.TryGetProperty("school", out JsonElement school)) return BadRequest();
  1219. var query = $"select c.id,c.code,c.name,c.startTime,c.endTime,c.type,c.progress,c.school,c.scope from c where ({ss}) and c.progress != 'pending' ";
  1220. List<object> props = new List<object>();
  1221. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query))
  1222. {
  1223. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1224. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1225. {
  1226. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1227. {
  1228. props.Add(obj.ToObject<object>());
  1229. }
  1230. }
  1231. }
  1232. var queryClass = $"select c.examId,c.subjectId,c.studentIds,c.studentAnswers,c.studentScores from c where array_contains(c.studentIds,'{studentId}') and c.pk = 'ExamClassResult'";
  1233. List<ExamClassResult> Classes = new List<ExamClassResult>();
  1234. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryClass))
  1235. {
  1236. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1237. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1238. {
  1239. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1240. {
  1241. Classes.Add(obj.ToObject<ExamClassResult>());
  1242. }
  1243. }
  1244. }
  1245. List<ExamClassResult> result = new List<ExamClassResult>();
  1246. foreach (ExamClassResult classResult in Classes)
  1247. {
  1248. int index = classResult.studentIds.IndexOf(studentId.ToString());
  1249. ExamClassResult result1 = new ExamClassResult();
  1250. result1.examId = classResult.examId;
  1251. result1.subjectId = classResult.subjectId;
  1252. result1.studentAnswers.Add(classResult.studentAnswers[index]);
  1253. result1.studentScores.Add(classResult.studentScores[index]);
  1254. result.Add(result1);
  1255. }
  1256. return Ok(new { props, result });
  1257. }
  1258. catch (Exception ex)
  1259. {
  1260. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1261. return BadRequest();
  1262. }
  1263. }
  1264. //查询学生活动列表
  1265. [ProducesDefaultResponseType]
  1266. //[AuthToken(Roles = "Student")]
  1267. [HttpPost("find-score-by-student")]
  1268. public async Task<IActionResult> findScoreByStudent(JsonElement requert)
  1269. {
  1270. //ResponseBuilder builder = ResponseBuilder.custom();
  1271. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1272. try
  1273. {
  1274. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1275. //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1276. var client = _azureCosmos.GetCosmosClient();
  1277. var query = $"select c.examId,c.subjectId,c.studentScores from c where array_contains(c.studentIds,'{id}') ";
  1278. List<object> props = new List<object>();
  1279. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query))
  1280. {
  1281. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1282. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1283. {
  1284. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1285. {
  1286. props.Add(obj.ToObject<object>());
  1287. }
  1288. }
  1289. }
  1290. return Ok(props);
  1291. }
  1292. catch (Exception ex)
  1293. {
  1294. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1295. return BadRequest();
  1296. }
  1297. }
  1298. //查询学生活动列表
  1299. [ProducesDefaultResponseType]
  1300. //[AuthToken(Roles = "Student")]
  1301. [HttpPost("finish")]
  1302. public async Task<IActionResult> finish(JsonElement requert)
  1303. {
  1304. //ResponseBuilder builder = ResponseBuilder.custom();
  1305. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1306. try
  1307. {
  1308. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1309. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1310. var client = _azureCosmos.GetCosmosClient();
  1311. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1312. info.progress = "finish";
  1313. info.endTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1314. List<ExamClassResult> classResults = new();
  1315. if (info.scope.Equals("school"))
  1316. {
  1317. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1318. queryText: $"select value(c) from c where c.examId = '{id}'",
  1319. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1320. {
  1321. classResults.Add(item);
  1322. }
  1323. }
  1324. else
  1325. {
  1326. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1327. queryText: $"select value(c) from c where c.examId = '{id}'",
  1328. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1329. {
  1330. classResults.Add(item);
  1331. }
  1332. }
  1333. foreach (ExamClassResult examClass in classResults)
  1334. {
  1335. examClass.progress = true;
  1336. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(examClass, examClass.id, new PartitionKey($"{examClass.code}"));
  1337. }
  1338. info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1339. return Ok(info);
  1340. }
  1341. catch (Exception ex)
  1342. {
  1343. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/finish\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1344. return BadRequest();
  1345. }
  1346. }
  1347. /*//查询任务列表
  1348. [ProducesDefaultResponseType]
  1349. //[AuthToken(Roles = "Student")]
  1350. [HttpPost("scoring")]
  1351. public async Task<IActionResult> Scoring(JsonElement requert)
  1352. {
  1353. //ResponseBuilder builder = ResponseBuilder.custom();
  1354. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1355. try
  1356. {
  1357. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1358. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1359. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1360. var client = _azureCosmos.GetCosmosClient();
  1361. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1362. int index = 0;
  1363. foreach (ExamSubject subject in info.subjects) {
  1364. if (!subject.id.Equals(subjectId.ToString()))
  1365. {
  1366. index++;
  1367. }
  1368. else {
  1369. break;
  1370. }
  1371. }
  1372. List<string> stuAns = new();
  1373. Dictionary<string, List<List<double>>> keyValues = new();
  1374. List<ExamClassResult> classResults = new();
  1375. if (info.scope.Equals("school"))
  1376. {
  1377. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1378. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1379. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1380. {
  1381. classResults.Add(item);
  1382. }
  1383. }
  1384. else
  1385. {
  1386. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1387. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1388. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1389. {
  1390. classResults.Add(item);
  1391. }
  1392. }
  1393. List<List<double>> itemScore = new();
  1394. for (int i = 0; i < info.papers[index].point.Count; i++)
  1395. {
  1396. List<double> score = new();
  1397. foreach (ExamClassResult examClass in classResults)
  1398. {
  1399. foreach (List<double> sc in examClass.studentScores)
  1400. {
  1401. score.Add(sc[i]);
  1402. }
  1403. }
  1404. itemScore.Add(score);
  1405. }
  1406. foreach (ExamClassResult examClass in classResults)
  1407. {
  1408. foreach (List<string> ans in examClass.studentAnswers)
  1409. {
  1410. if (ans.Count > 0)
  1411. {
  1412. stuAns.Add(ans[0]);
  1413. }
  1414. else
  1415. {
  1416. stuAns.Add("");
  1417. }
  1418. }
  1419. }
  1420. //info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1421. return Ok(new { score = itemScore , stuAns, paper = info.papers });
  1422. }
  1423. catch (Exception ex)
  1424. {
  1425. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1426. return BadRequest();
  1427. }
  1428. }*/
  1429. [ProducesDefaultResponseType]
  1430. //[AuthToken(Roles = "Student")]
  1431. [HttpPost("scoring")]
  1432. public async Task<IActionResult> scoring(JsonElement requert)
  1433. {
  1434. //ResponseBuilder builder = ResponseBuilder.custom();
  1435. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1436. try
  1437. {
  1438. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1439. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1440. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1441. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1442. var client = _azureCosmos.GetCosmosClient();
  1443. var redisClient = _azureRedis.GetRedisClient(8);
  1444. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1445. List<ExamClassResult> classResults = new();
  1446. List<dynamic> attr = new List<dynamic>();
  1447. //List<dynamic> all = new List<dynamic>();
  1448. var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
  1449. foreach (var rcd in record)
  1450. {
  1451. var value = JsonDocument.Parse(rcd.Value.ToString());
  1452. value.RootElement.TryGetProperty("tmdId", out JsonElement tmdId);
  1453. if (tId.ToString().Equals(tmdId.ToString()))
  1454. {
  1455. attr.Add(new { stuId = rcd.Name.ToString(), info = value });
  1456. }
  1457. }
  1458. int index = 0;
  1459. foreach (ExamSubject subject in info.subjects)
  1460. {
  1461. if (!subject.id.Equals(subjectId.ToString()))
  1462. {
  1463. index++;
  1464. }
  1465. else
  1466. {
  1467. break;
  1468. }
  1469. }
  1470. return Ok(new { attr, paper = info.papers[index].blob });
  1471. }
  1472. catch (Exception ex)
  1473. {
  1474. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1475. return BadRequest();
  1476. }
  1477. }
  1478. //批阅,给老师随机分配阅卷数据,以及查询改老师已有的阅卷数据
  1479. [ProducesDefaultResponseType]
  1480. //[AuthToken(Roles = "Student")]
  1481. [HttpPost("review")]
  1482. public async Task<IActionResult> Review(JsonElement requert)
  1483. {
  1484. //ResponseBuilder builder = ResponseBuilder.custom();
  1485. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1486. try
  1487. {
  1488. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1489. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1490. if (!requert.TryGetProperty("count", out JsonElement count)) return BadRequest();
  1491. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1492. var client = _azureCosmos.GetCosmosClient();
  1493. var redisClient = _azureRedis.GetRedisClient(8);
  1494. List<ExamClassResult> classResults = new();
  1495. List<dynamic> recs = new List<dynamic>();
  1496. List<dynamic> all = new List<dynamic>();
  1497. var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
  1498. foreach (var rcd in record)
  1499. {
  1500. var value = JsonDocument.Parse(rcd.Value.ToString());
  1501. value.RootElement.TryGetProperty("tmdId", out JsonElement tmdId);
  1502. if (tId.ToString().Equals(tmdId.ToString()))
  1503. {
  1504. recs.Add(new { stuId = rcd.Name.ToString(), ans = value });
  1505. }
  1506. if (string.IsNullOrEmpty(tmdId.ToString()))
  1507. {
  1508. all.Add(new { stuId = rcd.Name.ToString(), ans = value });
  1509. }
  1510. }
  1511. if (requert.TryGetProperty("stuId", out JsonElement stuId))
  1512. {
  1513. var stuAns = await redisClient.HashGetAsync($"Exam:Scoring:{id}-{subjectId}", stuId.ToString());
  1514. var value = JsonDocument.Parse(stuAns.ToString());
  1515. //保证此学生与该老师绑定
  1516. value.RootElement.TryGetProperty("ans", out JsonElement blob);
  1517. value.RootElement.TryGetProperty("score", out JsonElement sc);
  1518. await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", stuId.ToString(), new { ans = blob, score = sc, tmdId = tId }.ToJsonString());
  1519. return Ok(value);
  1520. }
  1521. else
  1522. {
  1523. if (recs.Count == count.GetInt32())
  1524. {
  1525. return Ok( new { msg = "分配人数已到上限"});
  1526. }
  1527. else
  1528. {
  1529. if (all.Count == 0) {
  1530. return Ok(new { msg = "暂无可选学生" });
  1531. }
  1532. //随机选取一名学生打分
  1533. Random random = new Random();
  1534. int n = random.Next(all.Count);
  1535. dynamic item = all[n];
  1536. //序列化单个学生作答记录、得分情况、批注情况
  1537. var cs = JsonSerializer.Serialize(item);
  1538. var json = JsonDocument.Parse(cs);
  1539. json.RootElement.TryGetProperty("stuId", out JsonElement sId);
  1540. json.RootElement.TryGetProperty("ans", out JsonElement ans);
  1541. ans.TryGetProperty("score", out JsonElement sc);
  1542. ans.TryGetProperty("ans", out JsonElement blob);
  1543. //选取后,缓存池相应的减少,以便于分配给其他的老师
  1544. await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = sc, tmdId = tId }.ToJsonString());
  1545. return Ok(item);
  1546. }
  1547. }
  1548. //var json = JsonDocument.Parse(record);
  1549. /*if (info.scope.Equals("school"))
  1550. {
  1551. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1552. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1553. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1554. {
  1555. classResults.Add(item);
  1556. }
  1557. }
  1558. else
  1559. {
  1560. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1561. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1562. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1563. {
  1564. classResults.Add(item);
  1565. }
  1566. }
  1567. List<Task<bool>> tasks = new List<Task<bool>>();
  1568. foreach (ExamClassResult examClass in classResults)
  1569. {
  1570. foreach (string stuId in examClass.studentIds)
  1571. {
  1572. int index = examClass.studentIds.IndexOf(stuId);
  1573. tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", stuId, new { ans = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0]: "", score = examClass.studentScores[index] }.ToJsonString()));
  1574. }
  1575. }
  1576. await Task.WhenAll(tasks);*/
  1577. //info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1578. }
  1579. catch (Exception ex)
  1580. {
  1581. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/review\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1582. return BadRequest();
  1583. }
  1584. }
  1585. //批阅 提交分数
  1586. [ProducesDefaultResponseType]
  1587. //[AuthToken(Roles = "Student")]
  1588. [HttpPost("sub-result")]
  1589. public async Task<IActionResult> SubResult(JsonElement requert)
  1590. {
  1591. //ResponseBuilder builder = ResponseBuilder.custom();
  1592. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1593. try
  1594. {
  1595. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1596. if (!requert.TryGetProperty("stuId", out JsonElement sId)) return BadRequest();
  1597. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1598. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1599. if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest();
  1600. if (!requert.TryGetProperty("count", out JsonElement count)) return BadRequest();
  1601. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1602. //if (!requert.TryGetProperty("mark", out JsonElement mark)) return BadRequest();
  1603. requert.TryGetProperty("mark", out JsonElement mark);
  1604. var client = _azureCosmos.GetCosmosClient();
  1605. var redisClient = _azureRedis.GetRedisClient(8);
  1606. List<ExamClassResult> classResults = new();
  1607. List<dynamic> recs = new List<dynamic>();
  1608. var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
  1609. foreach (var rcd in record)
  1610. {
  1611. var values = JsonDocument.Parse(rcd.Value.ToString());
  1612. values.RootElement.TryGetProperty("tmdId", out JsonElement tmdId);
  1613. if (tId.ToString().Equals(tmdId.ToString()))
  1614. {
  1615. recs.Add(new { stuId = rcd.Name.ToString(), ans = values });
  1616. }
  1617. }
  1618. var stuAns = await redisClient.HashGetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString());
  1619. var value = JsonDocument.Parse(stuAns.ToString());
  1620. value.RootElement.TryGetProperty("ans", out JsonElement blob);
  1621. //存放老师批注信息到blob
  1622. StringBuilder builder = new StringBuilder();
  1623. builder.Append(id).Append("/");
  1624. builder.Append(subjectId).Append("/");
  1625. builder.Append(sId).Append("mark").Append("/");
  1626. builder.Append("ans.json");
  1627. await _azureStorage.UploadFileByContainer(code.ToString(), mark.ToJsonString(), "exam", builder.ToString(), false);
  1628. await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = score, tmdId = tId, mark = builder.ToString() }.ToJsonString());
  1629. if (recs.Count == count.GetInt32())
  1630. {
  1631. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1632. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1633. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  1634. {
  1635. classResults.Add(item);
  1636. }
  1637. foreach (ExamClassResult exam in classResults)
  1638. {
  1639. foreach (dynamic re in recs)
  1640. {
  1641. var cs = JsonSerializer.Serialize(re);
  1642. var json = JsonDocument.Parse(cs);
  1643. json.RootElement.TryGetProperty("stuId", out JsonElement stuId);
  1644. json.RootElement.TryGetProperty("ans", out JsonElement ans);
  1645. ans.TryGetProperty("score", out JsonElement sc);
  1646. ans.TryGetProperty("mark", out JsonElement marks);
  1647. int index = exam.studentIds.IndexOf(stuId.ToString());
  1648. if (index != -1)
  1649. {
  1650. exam.studentScores[index] = sc.ToObject<List<double>>();
  1651. exam.mark[index] = marks.ToString();
  1652. }
  1653. }
  1654. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, exam.id, new PartitionKey($"{exam.code}"));
  1655. }
  1656. }
  1657. return Ok(new { code = 200 });
  1658. }
  1659. catch (Exception ex)
  1660. {
  1661. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/sub-result\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1662. return BadRequest();
  1663. }
  1664. }
  1665. }
  1666. }