ExamController.cs 160 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947
  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.DI;
  18. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  19. using TEAMModelOS.SDK.Extension;
  20. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  21. using TEAMModelOS.SDK.Models.Cosmos.Common;
  22. using TEAMModelOS.SDK.Models.Table;
  23. using Azure.Messaging.ServiceBus;
  24. using Microsoft.Extensions.Configuration;
  25. using TEAMModelOS.Filter;
  26. using TEAMModelOS.SDK.Models.Service;
  27. using TEAMModelOS.SDK.Models.Cosmos;
  28. using HTEXLib.COMM.Helpers;
  29. namespace TEAMModelOS.Controllers
  30. {
  31. [ProducesResponseType(StatusCodes.Status200OK)]
  32. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  33. //[Authorize(Roles = "IES5")
  34. [Route("common/exam")]
  35. [ApiController]
  36. public class ExamController : ControllerBase
  37. {
  38. private readonly AzureCosmosFactory _azureCosmos;
  39. private readonly SnowflakeId _snowflakeId;
  40. private readonly AzureServiceBusFactory _serviceBus;
  41. private readonly DingDing _dingDing;
  42. private readonly Option _option;
  43. private readonly AzureStorageFactory _azureStorage;
  44. private readonly AzureRedisFactory _azureRedis;
  45. public IConfiguration _configuration { get; set; }
  46. private readonly NotificationService _notificationService;
  47. public ExamController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
  48. IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, NotificationService notificationService, IConfiguration configuration)
  49. {
  50. _azureCosmos = azureCosmos;
  51. _serviceBus = serviceBus;
  52. _snowflakeId = snowflakeId;
  53. _dingDing = dingDing;
  54. _option = option?.Value;
  55. _azureStorage = azureStorage;
  56. _azureRedis = azureRedis;
  57. _configuration = configuration;
  58. _notificationService = notificationService;
  59. }
  60. /// <summary>
  61. /// 保存考试信息
  62. /// </summary>
  63. /// <param name="request"></param>
  64. /// <returns></returns>
  65. [ProducesDefaultResponseType]
  66. [AuthToken(Roles = "teacher,admin")]
  67. [HttpPost("save")]
  68. public async Task<IActionResult> Save(ExamInfo request)
  69. {
  70. try
  71. {
  72. //新增
  73. //string code = request.code;
  74. var client = _azureCosmos.GetCosmosClient();
  75. ExamInfo exam;
  76. string code = request.code;
  77. request.ttl = -1;
  78. request.code = "Exam-" + request.code;
  79. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  80. request.createTime = now;
  81. if (request.startTime <= 0)
  82. {
  83. request.startTime = now;
  84. }
  85. //查询所有学生名单
  86. /* List<string> sids = new List<string>();
  87. //List<Student> students = new List<Student>();
  88. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{request.school}") }))
  89. {
  90. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  91. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  92. {
  93. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  94. while (accounts.MoveNext())
  95. {
  96. JsonElement account = accounts.Current;
  97. sids.Add(account.GetProperty("id").GetString());
  98. }
  99. }
  100. }*/
  101. //int stuCount = 0;
  102. List<(string pId, List<string> gid)> ps = new();
  103. var group = request.groupLists;
  104. if (group.Count > 0)
  105. {
  106. foreach (var keys in group)
  107. {
  108. foreach (KeyValuePair<string, List<string>> pp in keys)
  109. {
  110. ps.Add((pp.Key, pp.Value));
  111. }
  112. }
  113. }
  114. List<string> classes = ExamService.getClasses(request.classes, request.stuLists);
  115. (List<RMember> tchList, List<RGroupList> classLists) = await GroupListService.GetStutmdidListids(client, _dingDing, classes, request.school, ps);
  116. request.stuCount = tchList.Count;
  117. /*for (int i = 0; i < classes.Count; i++)
  118. {
  119. List<string> ids = new List<string>();
  120. //处理班级人数(公共部分的校本名单)
  121. //List<Student> students = new List<Student>();
  122. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{request.school}") }))
  123. {
  124. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  125. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  126. {
  127. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  128. while (accounts.MoveNext())
  129. {
  130. JsonElement account = accounts.Current;
  131. ids.Add(account.GetProperty("id").GetString());
  132. }
  133. }
  134. }
  135. if (request.scope.Equals("private"))
  136. {
  137. //处理发布对象为自选名单(个人)
  138. List<GroupList> stuLists = new List<GroupList>();
  139. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<GroupList>(queryText: $"select value(c) from c where c.id = '{classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList") }))
  140. {
  141. stuLists.Add(item);
  142. }
  143. }
  144. else
  145. {
  146. //request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  147. //发布对象为自选名单(校本)
  148. List<GroupList> stuLists = new List<GroupList>();
  149. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<GroupList>(queryText: $"select value(c) from c where c.id = '{classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{request.school}") }))
  150. {
  151. stuLists.Add(item);
  152. }
  153. }
  154. stuCount += ids.Count;
  155. }*/
  156. if (string.IsNullOrEmpty(request.id))
  157. {
  158. request.id = Guid.NewGuid().ToString();
  159. if (request.startTime > now)
  160. {
  161. request.progress = "pending";
  162. }
  163. else
  164. {
  165. request.progress = "going";
  166. }
  167. var messageBlob = new ServiceBusMessage();
  168. if (request.scope.Equals("school"))
  169. {
  170. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  171. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"exam/{request.id}", name = request.school }.ToJsonString());
  172. }
  173. else
  174. {
  175. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"exam/{request.id}");
  176. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"exam/{request.id}", name = request.creatorId }.ToJsonString());
  177. }
  178. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  179. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  180. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  181. int n = 0;
  182. List<string> sheetIds = new List<string>();
  183. foreach (PaperSimple simple in request.papers)
  184. {
  185. simple.blob = $"/exam/{request.id}/paper/{request.subjects[n].id}";
  186. n++;
  187. simple.sheet = null;
  188. }
  189. exam = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  190. }
  191. else
  192. {
  193. ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(request.id, new PartitionKey($"{request.code}"));
  194. if (info.progress.Equals("going"))
  195. {
  196. return Ok(new { v = "活动正在进行中" });
  197. }
  198. var messageBlob = new ServiceBusMessage();
  199. if (request.scope.Equals("school"))
  200. {
  201. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  202. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"exam/{request.id}", name = request.school }.ToJsonString());
  203. }
  204. else
  205. {
  206. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"exam/{request.id}");
  207. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"exam/{request.id}", name = request.creatorId }.ToJsonString());
  208. }
  209. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  210. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  211. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  212. request.progress = info.progress;
  213. int n = 0;
  214. foreach (PaperSimple simple in request.papers)
  215. {
  216. simple.blob = "/exam/" + request.id + "/paper/" + request.subjects[n].id;
  217. n++;
  218. }
  219. exam = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(request, request.id, new PartitionKey($"{request.code}"));
  220. }
  221. return Ok(new { exam });
  222. }
  223. catch (Exception ex)
  224. {
  225. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/save()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  226. return BadRequest();
  227. }
  228. }
  229. //TODO blob 批量删除
  230. /// <summary>
  231. /// 删除
  232. /// </summary>
  233. /// <param name="request"></param>
  234. /// <returns></returns>
  235. [ProducesDefaultResponseType]
  236. //[AuthToken(Roles = "teacher")]
  237. [HttpPost("delete")]
  238. public async Task<IActionResult> Delete(JsonElement request)
  239. {
  240. /* ResponseBuilder builder = ResponseBuilder.custom();
  241. IdPk items = await _azureCosmos.DeleteAsync<ExamInfo>(request.id, request.pk);
  242. await _azureCosmos.DeleteAll<Paper>(new Dictionary<string, object>() { { "code", request.id } });
  243. return builder.Data(items).build();*/
  244. try
  245. {
  246. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  247. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  248. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  249. var client = _azureCosmos.GetCosmosClient();
  250. //string school_code = code.ToString().Substring(typeof(ExamClassResult).Name.Length + 1);
  251. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
  252. //删除blob 相关资料
  253. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, code.ToString(), new List<string> { $"exam/{id}" });
  254. //通知评测删除信息
  255. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"exam/{id}", name = $"{code}" }.ToJsonString());
  256. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  257. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  258. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  259. //删除阅卷配置
  260. var cresponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Correct-{code}"));
  261. if (cresponse.Status == 200)
  262. {
  263. using var json = await JsonDocument.ParseAsync(cresponse.ContentStream);
  264. Correct correct = json.ToObject<Correct>();
  265. if (correct.subs.IsNotEmpty())
  266. {
  267. foreach (var sub in correct.subs)
  268. {
  269. //List<string> correctIds = new List<string>();
  270. if (sub.markers.IsNotEmpty())
  271. {
  272. foreach (var marker in sub.markers)
  273. {
  274. await ExamService.deleteAsync(client, id.GetString(), marker.id);
  275. }
  276. }
  277. if (sub.err.Count > 0)
  278. {
  279. foreach (var tId in sub.err)
  280. {
  281. await ExamService.deleteAsync(client, id.GetString(), tId);
  282. }
  283. }
  284. if (sub.arb.Count > 0)
  285. {
  286. foreach (var tId in sub.arb)
  287. {
  288. await ExamService.deleteAsync(client, id.GetString(), tId);
  289. }
  290. }
  291. }
  292. }
  293. await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(id.GetString(), new PartitionKey($"Correct-{code}"));
  294. }
  295. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  296. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(queryText: $"select c.id from c where c.examId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  297. {
  298. examClassResults.Add(item);
  299. }
  300. List<string> resultIds = new List<string>();
  301. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"select c.id from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
  302. {
  303. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  304. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  305. {
  306. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  307. while (accounts.MoveNext())
  308. {
  309. JsonElement account = accounts.Current;
  310. resultIds.Add(account.GetProperty("id").GetString());
  311. }
  312. }
  313. }
  314. foreach (ExamClassResult classResult in examClassResults)
  315. {
  316. await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(classResult.id, new PartitionKey($"ExamClassResult-{code}"));
  317. }
  318. await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemsStreamAsync(resultIds, $"ExamResult-{id}");
  319. /*foreach (ExamResult result in results)
  320. {
  321. await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(result.id, new PartitionKey($"ExamResult-{id}"));
  322. }*/
  323. //await _azureCosmos.DeleteAll(examClassResults);
  324. return Ok(new { id });
  325. }
  326. catch (Exception e)
  327. {
  328. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/delete()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  329. return BadRequest();
  330. }
  331. }
  332. /// <summary>
  333. /// 查询考试信息
  334. /// </summary>
  335. /// <param name="request"></param>
  336. /// <returns></returns>
  337. [ProducesDefaultResponseType]
  338. //[AuthToken(Roles = "teacher")]
  339. [HttpPost("find")]
  340. public async Task<IActionResult> Find(JsonElement requert)
  341. {
  342. try
  343. {
  344. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  345. var client = _azureCosmos.GetCosmosClient();
  346. List<SchoolYear> years = await _azureStorage.FindListByDict<SchoolYear>(new Dictionary<string, object>() { { "RowKey", code }, { "PartitionKey", "Exam" } });
  347. int year = 0;
  348. if (years.Count > 0)
  349. {
  350. year = years[0].year;
  351. }
  352. else
  353. {
  354. long ct = 0;
  355. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: "SELECT top 1 c.createTime FROM c order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
  356. {
  357. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  358. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  359. {
  360. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  361. while (accounts.MoveNext())
  362. {
  363. JsonElement account = accounts.Current;
  364. ct = account.GetProperty("createTime").GetInt64();
  365. }
  366. }
  367. }
  368. year = ct == 0 ? DateTimeOffset.UtcNow.Year : DateTimeOffset.FromUnixTimeMilliseconds(ct).Year;
  369. SchoolYear sy = new()
  370. {
  371. RowKey = code.ToString(),
  372. PartitionKey = "Exam",
  373. year = year
  374. };
  375. await _azureStorage.Save<SchoolYear>(sy);
  376. }
  377. 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.owner, c.scope,c.classes,c.sRate,c.lostStu from c ";
  378. if (requert.TryGetProperty("classIds", out JsonElement classIds))
  379. {
  380. List<string> ids = classIds.ToObject<List<string>>();
  381. HashSet<string> strs = new HashSet<string>();
  382. if (ids.Count > 1)
  383. {
  384. foreach (string id in ids)
  385. {
  386. strs.Add($"array_contains(c.classes,'{id}')");
  387. }
  388. }
  389. else
  390. {
  391. string ssr = ids.Count > 0 ? ids[0] : "";
  392. strs.Add($"array_contains(c.classes,'{ssr}')");
  393. }
  394. string ss = string.Join(" or ", strs);
  395. 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.owner, c.scope,c.classes,c.sRate,c.lostStu from c where ({ss})";
  396. };
  397. string continuationToken = string.Empty;
  398. string token = default;
  399. //是否需要进行分页查询,默认不分页
  400. bool iscontinuation = false;
  401. if (requert.TryGetProperty("token", out JsonElement token_1))
  402. {
  403. token = token_1.GetString();
  404. iscontinuation = true;
  405. };
  406. //默认不指定返回大小
  407. int? topcout = null;
  408. if (requert.TryGetProperty("count", out JsonElement jcount))
  409. {
  410. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  411. {
  412. topcout = data;
  413. }
  414. }
  415. List<ExamInfo> examInfo = new List<ExamInfo>();
  416. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Exam-{code}") }))
  417. {
  418. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  419. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  420. {
  421. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  422. {
  423. //obj.TryGetProperty("progress", out JsonElement progress);
  424. examInfo.Add(obj.ToObject<ExamInfo>());
  425. }
  426. }
  427. if (iscontinuation)
  428. {
  429. continuationToken = item.GetContinuationToken();
  430. break;
  431. }
  432. }
  433. //List<string> examIds = new List<string>();
  434. /* List<ExamResult> examResults = new List<ExamResult>();
  435. foreach (ExamInfo info in examInfos) {
  436. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(
  437. queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{info.id}") }))
  438. {
  439. examResults.Add(item);
  440. }
  441. }*/
  442. /* List<(string id, double scores)> listExamInfo = new List<(string id, double scores)>();
  443. foreach (ExamInfo info in examInfos)
  444. {
  445. //记录某次考试所有学生得分总分
  446. double score = 0;
  447. double allScore = 0;
  448. int stuCount = 0;
  449. foreach (ExamResult examResult in examResults) {
  450. if (info.id == examResult.examId) {
  451. foreach (List<double> sc in examResult.studentScores) {
  452. score += sc.Sum();
  453. }
  454. stuCount = examResult.studentIds.Count;
  455. }
  456. }
  457. double ascore = stuCount > 0 ? Math.Round(score * 0.1 / stuCount, 2) : 0;
  458. foreach (PaperSimple simple in info.papers) {
  459. allScore += simple.point.Sum();
  460. }
  461. listExamInfo.Add((info.id, (allScore> 0 ? ascore / allScore * 100: 0)));
  462. }
  463. var examInfo = examInfos.Select(o =>
  464. new
  465. {
  466. o.id,
  467. o.scope,
  468. o.stuCount,
  469. o.name,
  470. o.period,
  471. o.startTime,
  472. o.endTime,
  473. o.type,
  474. o.progress,
  475. o.examType,
  476. o.createTime,
  477. o.subjects,
  478. o.grades,
  479. o.classes,
  480. score = listExamInfo.FirstOrDefault(c => c.id == o.id).scores,
  481. }
  482. );*/
  483. return Ok(new { examInfo, token = continuationToken, year });
  484. }
  485. catch (Exception e)
  486. {
  487. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  488. return BadRequest();
  489. }
  490. }
  491. [ProducesDefaultResponseType]
  492. //[AuthToken(Roles = "teacher")]
  493. [HttpPost("find-summary")]
  494. public async Task<IActionResult> FindSummary(JsonElement requert)
  495. {
  496. try
  497. {
  498. //ResponseBuilder builder = ResponseBuilder.custom();
  499. //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  500. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  501. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  502. //if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  503. //var jwt = new JwtSecurityToken(id_token.GetString());
  504. //if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
  505. //var id = jwt.Payload.Sub;
  506. var client = _azureCosmos.GetCosmosClient();
  507. List<ExamInfo> examInfo = new List<ExamInfo>();
  508. //var query = $"select value(c) from c ";
  509. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
  510. {
  511. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  512. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  513. {
  514. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  515. {
  516. //obj.TryGetProperty("progress", out JsonElement progress);
  517. examInfo.Add(obj.ToObject<ExamInfo>());
  518. }
  519. }
  520. }
  521. return Ok(new { examInfo });
  522. }
  523. catch (Exception e)
  524. {
  525. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  526. return BadRequest();
  527. }
  528. }
  529. /// <summary>
  530. /// 学生回答问题
  531. /// </summary>
  532. /// <param name="request"></param>
  533. /// <returns></returns>
  534. [ProducesDefaultResponseType]
  535. [AuthToken(Roles = "student,teacher")]
  536. [HttpPost("upsert-record")]
  537. public async Task<IActionResult> upsertRecord(JsonElement request)
  538. {
  539. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  540. //学校编码
  541. //if (!request.TryGetProperty("school", out JsonElement school)) return BadRequest();
  542. if (!request.TryGetProperty("answer", out JsonElement answer)) return BadRequest();
  543. //if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  544. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  545. if (!request.TryGetProperty("classIds", out JsonElement classId)) return BadRequest();
  546. if (!request.TryGetProperty("multipleRule", out JsonElement multipleRule)) return BadRequest();
  547. //if (!request.TryGetProperty("answers ", out JsonElement tandardAnswer)) return BadRequest();
  548. if (!request.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
  549. //根据不同评测的类型返回对应的编码
  550. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  551. if (!request.TryGetProperty("scode", out JsonElement scode)) return BadRequest();
  552. var (userId, _, _, school) = HttpContext.GetAuthTokenInfo();
  553. try
  554. {
  555. List<string> ids = new List<string>();
  556. ids = classId.ToObject<List<string>>();
  557. var client = _azureCosmos.GetCosmosClient();
  558. ExamInfo info = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.GetString(), new PartitionKey($"{scode}"));
  559. //确定当前学生所在班级且该班级参与该活动
  560. List<string> cIds = new();
  561. if (ids.Count == 0) return Ok(new { code = 1, msg = "未找到相关班级信息" });
  562. if (string.IsNullOrEmpty(userId)) return Ok(new { code = 1, msg = "当前用户信息未找到" });
  563. foreach (string cId in ids)
  564. {
  565. //List<string> stus = new List<string>();
  566. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(
  567. queryText: $"select c.classId as id from c where c.classId = '{cId}' and c.id = '{userId}'",
  568. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{info.school}") }))
  569. {
  570. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  571. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  572. {
  573. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  574. while (accounts.MoveNext())
  575. {
  576. JsonElement account = accounts.Current;
  577. cIds.Add(account.GetProperty("id").GetString());
  578. }
  579. break;
  580. }
  581. }
  582. if (info.scope.Equals("private"))
  583. {
  584. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(
  585. queryText: $"select c.id from c join A0 in c.members where c.id = '{cId}' and A0.id = '{userId}'",
  586. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList") }))
  587. {
  588. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  589. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  590. {
  591. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  592. while (accounts.MoveNext())
  593. {
  594. JsonElement account = accounts.Current;
  595. cIds.Add(account.GetProperty("id").GetString());
  596. }
  597. break;
  598. }
  599. }
  600. /*await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(
  601. queryText: $"select c.id from c where c.id = '{cId}' and array_contains(c.tmids,'{userId}') ",
  602. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList") }))
  603. {
  604. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  605. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  606. {
  607. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  608. while (accounts.MoveNext())
  609. {
  610. JsonElement account = accounts.Current;
  611. cIds.Add(account.GetProperty("id").GetString());
  612. }
  613. break;
  614. }
  615. }*/
  616. }
  617. else
  618. {
  619. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(
  620. queryText: $"select c.id from c join A0 in c.members where c.id = '{cId}' and A0.id = '{userId}'",
  621. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{info.school}") }))
  622. {
  623. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  624. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  625. {
  626. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  627. while (accounts.MoveNext())
  628. {
  629. JsonElement account = accounts.Current;
  630. cIds.Add(account.GetProperty("id").GetString());
  631. }
  632. break;
  633. }
  634. }
  635. }
  636. }
  637. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  638. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(
  639. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id in ({string.Join(",", cIds.Select(o => $"'{o}'"))})",
  640. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  641. {
  642. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  643. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  644. {
  645. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  646. {
  647. examClassResults.Add(obj.ToObject<ExamClassResult>());
  648. }
  649. }
  650. }
  651. ExamClassResult classResult = new ExamClassResult();
  652. List<PaperSimple> standerAnswers = new List<PaperSimple>();
  653. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(
  654. queryText: $"select A0.point,A0.answers from c join A0 in c.papers where c.id = '{id}'and A0.id = '{paperId}'",
  655. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  656. {
  657. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  658. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  659. {
  660. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  661. {
  662. standerAnswers.Add(obj.ToObject<PaperSimple>());
  663. }
  664. }
  665. }
  666. List<List<string>> ans = answer.ToObject<List<List<string>>>();
  667. List<List<string>> standard = new List<List<string>>();
  668. List<double> points = new List<double>();
  669. int rule = int.Parse(multipleRule.ToString());
  670. foreach (PaperSimple simple in standerAnswers)
  671. {
  672. standard = simple.answers;
  673. points = simple.point;
  674. }
  675. List<Task<string>> tasks = new List<Task<string>>();
  676. foreach (ExamClassResult result in examClassResults)
  677. {
  678. int index = result.studentIds.IndexOf(userId.ToString());
  679. //存放客观题作答详情
  680. if (result.ans.Count == 0)
  681. {
  682. foreach (string cc in result.studentIds)
  683. {
  684. List<List<string>> anc = new List<List<string>>();
  685. foreach (List<string> opc in standard)
  686. {
  687. anc.Add(new List<string>());
  688. }
  689. result.ans.Add(anc);
  690. }
  691. }
  692. //处理新增学生作答信息
  693. //List<List<string>> oq = new List<List<string>>();
  694. //classResult.studentAnswers[index] = ans;
  695. if (index == -1)
  696. {
  697. List<double> ansPoint = new List<double>();
  698. List<List<string>> anc = new List<List<string>>();
  699. List<List<Details>> mark = new List<List<Details>>();
  700. foreach (List<string> num in standard)
  701. {
  702. List<string> newAns = new List<string>();
  703. foreach (string san in num)
  704. {
  705. newAns.Add(san);
  706. }
  707. anc.Add(newAns);
  708. ansPoint.Add(-1);
  709. mark.Add(new List<Details>());
  710. }
  711. result.mark.Add(mark);
  712. result.ans.Add(anc);
  713. result.studentIds.Add(userId.ToString());
  714. result.studentScores.Add(ansPoint);
  715. result.studentAnswers.Add(new List<string>());
  716. result.sum.Add(0);
  717. }
  718. //int flagCount = 0;
  719. /*foreach (List<string> str in ans) {
  720. if (str.Count == 0) {
  721. flagCount++;
  722. }
  723. } */
  724. int newIndex = result.studentIds.IndexOf(userId.ToString());
  725. /* if (flagCount != standard.Count)
  726. {*/
  727. StringBuilder builder = new StringBuilder();
  728. builder.Append(result.examId).Append("/");
  729. builder.Append(result.subjectId).Append("/");
  730. builder.Append(userId).Append("/");
  731. builder.Append("ans.json");
  732. /*string FileName = result.examId + "/" + result.subjectId + "/" + studentId;
  733. string blob = FileName + "/" + "ans.json";*/
  734. tasks.Add(_azureStorage.UploadFileByContainer(code.ToString(), ans.ToJsonString(), "exam", builder.ToString(), false));
  735. result.studentAnswers[newIndex].Add(builder.ToString());
  736. //}
  737. //List<(int index ,string content, double count)> acount = new List<(int index,string content, double count)>();
  738. for (int i = 0; i < ans.Count; i++)
  739. {
  740. var ac = ans[i].Count;
  741. var sc = standard[i].Count;
  742. //算分处理
  743. if (sc > 0)
  744. {
  745. result.ans[newIndex][i] = ans[i];
  746. if (ac == sc && sc == 1)
  747. {
  748. foreach (string right in ans[i])
  749. {
  750. if (standard[i].Contains(right))
  751. {
  752. result.studentScores[newIndex][i] = points[i];
  753. }
  754. else
  755. {
  756. result.studentScores[newIndex][i] = 0;
  757. }
  758. }
  759. }
  760. else
  761. {
  762. if (rule > 0)
  763. {
  764. int falseCount = 0;
  765. if (ac > 0)
  766. {
  767. foreach (string obj in ans[i])
  768. {
  769. if (!standard[i].Contains(obj))
  770. {
  771. falseCount++;
  772. }
  773. }
  774. switch (rule)
  775. {
  776. case 1:
  777. if (ac == sc)
  778. {
  779. if (falseCount == 0)
  780. {
  781. result.studentScores[newIndex][i] = points[i];
  782. }
  783. else
  784. {
  785. result.studentScores[newIndex][i] = 0;
  786. }
  787. }
  788. else
  789. {
  790. result.studentScores[newIndex][i] = 0;
  791. }
  792. break;
  793. case 2:
  794. if (falseCount > 0)
  795. {
  796. result.studentScores[newIndex][i] = 0;
  797. }
  798. else
  799. {
  800. if (ac == sc)
  801. {
  802. result.studentScores[newIndex][i] = points[i];
  803. }
  804. else
  805. {
  806. result.studentScores[newIndex][i] = points[i] / 2;
  807. }
  808. }
  809. break;
  810. case 3:
  811. if (falseCount > 0)
  812. {
  813. result.studentScores[newIndex][i] = 0;
  814. }
  815. else
  816. {
  817. if (ac == sc)
  818. {
  819. result.studentScores[newIndex][i] = points[i];
  820. }
  821. else
  822. {
  823. result.studentScores[newIndex][i] = System.Math.Round((double)ac / sc * points[i], 1);
  824. }
  825. }
  826. break;
  827. case 4:
  828. if (ac == sc)
  829. {
  830. result.studentScores[newIndex][i] = points[i];
  831. }
  832. else
  833. {
  834. double persent = (double)(sc - 2 * falseCount) / sc;
  835. if (persent <= 0)
  836. {
  837. result.studentScores[newIndex][i] = 0;
  838. }
  839. else
  840. {
  841. result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
  842. }
  843. }
  844. break;
  845. }
  846. }
  847. else
  848. {
  849. result.studentScores[newIndex][i] = 0;
  850. }
  851. }
  852. }
  853. }
  854. }
  855. /*if (result.studentScores.Contains(-1)) {
  856. }*/
  857. bool flag = true;
  858. foreach (List<double> scores in result.studentScores)
  859. {
  860. foreach (double score in scores)
  861. {
  862. if (score == -1)
  863. {
  864. flag = false;
  865. break;
  866. }
  867. }
  868. }
  869. //bool isAns = true;
  870. bool isAns = result.studentScores[newIndex].Exists(s => s == -1);
  871. if (flag)
  872. {
  873. result.progress = true;
  874. info.subjects.ForEach(s =>
  875. {
  876. if (s.id.Equals(subjectId.ToString()))
  877. {
  878. s.classCount += 1;
  879. }
  880. });
  881. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, id.ToString(), new PartitionKey($"{scode}"));
  882. }
  883. if (isAns)
  884. {
  885. try
  886. {
  887. if (string.IsNullOrEmpty(school))
  888. {
  889. StuActivity activity = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>(id.ToString(), new PartitionKey($"Activity-{userId}"));
  890. activity.taskStatus = 0;
  891. await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync(activity, activity.id, new PartitionKey($"{activity.code}"));
  892. }
  893. else
  894. {
  895. StuActivity activity = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>(id.ToString(), new PartitionKey($"Activity-{info.school}-{userId}"));
  896. activity.taskStatus = 0;
  897. await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync(activity, activity.id, new PartitionKey($"{activity.code}"));
  898. }
  899. }
  900. catch (CosmosException e)
  901. {
  902. if (e.Status == 404)
  903. {
  904. StuActivity activity = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>(id.ToString(), new PartitionKey($"Activity-{userId}"));
  905. activity.taskStatus = 0;
  906. await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync(activity, activity.id, new PartitionKey($"{activity.code}"));
  907. }
  908. }
  909. }
  910. else
  911. {
  912. try
  913. {
  914. if (string.IsNullOrEmpty(school))
  915. {
  916. StuActivity activity = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>(id.ToString(), new PartitionKey($"Activity-{userId}"));
  917. activity.taskStatus = 1;
  918. await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync(activity, activity.id, new PartitionKey($"{activity.code}"));
  919. }
  920. else
  921. {
  922. StuActivity activity = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>(id.ToString(), new PartitionKey($"Activity-{info.school}-{userId}"));
  923. activity.taskStatus = 1;
  924. await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync(activity, activity.id, new PartitionKey($"{activity.code}"));
  925. }
  926. }
  927. catch (CosmosException e)
  928. {
  929. if (e.Status == 404)
  930. {
  931. StuActivity activity = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemAsync<StuActivity>(id.ToString(), new PartitionKey($"Activity-{userId}"));
  932. activity.taskStatus = 1;
  933. await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync(activity, activity.id, new PartitionKey($"{activity.code}"));
  934. }
  935. }
  936. }
  937. result.sum[newIndex] = result.studentScores[newIndex].Sum();
  938. classResult = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  939. }
  940. await Task.WhenAll(tasks);
  941. return Ok(new { classResult });
  942. }
  943. catch (Exception e)
  944. {
  945. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertRecord()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  946. return BadRequest();
  947. }
  948. }
  949. [ProducesDefaultResponseType]
  950. //[AuthToken(Roles = "teacher")]
  951. [HttpPost("upsert-record-by-teacher")]
  952. public async Task<IActionResult> upsertRecordByTeacher(JsonElement request)
  953. {
  954. //ResponseBuilder builder = ResponseBuilder.custom();
  955. try
  956. {
  957. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  958. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  959. if (!request.TryGetProperty("point", out JsonElement point)) return BadRequest();
  960. if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  961. //if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  962. //此参数表明此次操作对象为个人还是校本的评测内容
  963. if (!request.TryGetProperty("school", out JsonElement school)) return BadRequest();
  964. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  965. //要先处理状态,判断卷子是否存在,并判断卷子归属的考试是否允许再次提交
  966. //List<ExamInfo> exams = await _azureCosmos.FindByDict<ExamInfo>(new Dictionary<string, object> { { "id", request.examCode } });
  967. List<double> ans = point.ToObject<List<double>>();
  968. var client = _azureCosmos.GetCosmosClient();
  969. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  970. if (request.TryGetProperty("classId", out JsonElement classId))
  971. {
  972. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  973. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
  974. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  975. {
  976. examClassResults.Add(item);
  977. }
  978. }
  979. else
  980. {
  981. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  982. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and array_contains(c.studentIds,'{studentId}')",
  983. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  984. {
  985. examClassResults.Add(item);
  986. }
  987. }
  988. ExamClassResult classResult = new ExamClassResult();
  989. //ExamInfo classResult = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{code}"));
  990. //ExamClassResult classResult = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamClassResult>(id.ToString(), new PartitionKey($"{code}"));
  991. /*foreach (double index in ans) {
  992. classResult.studentScores.in
  993. }*/
  994. foreach (ExamClassResult result in examClassResults)
  995. {
  996. int index = result.studentIds.IndexOf(studentId.ToString());
  997. for (int i = 0; i < ans.Count; i++)
  998. {
  999. result.studentScores[index][i] = ans[i];
  1000. }
  1001. if (!result.progress)
  1002. {
  1003. bool flag = true;
  1004. foreach (List<double> scores in result.studentScores)
  1005. {
  1006. foreach (double score in scores)
  1007. {
  1008. if (score == -1)
  1009. {
  1010. flag = false;
  1011. break;
  1012. }
  1013. }
  1014. }
  1015. if (flag)
  1016. {
  1017. ExamInfo exam = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1018. result.progress = true;
  1019. exam.subjects.ForEach(s =>
  1020. {
  1021. if (s.id.Equals(subjectId.ToString()))
  1022. {
  1023. s.classCount += 1;
  1024. }
  1025. });
  1026. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{code}"));
  1027. }
  1028. }
  1029. else
  1030. {
  1031. ExamInfo exam = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1032. exam.updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1033. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{code}"));
  1034. }
  1035. result.sum[index] = result.studentScores[index].Sum();
  1036. classResult = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  1037. }
  1038. return Ok(new { classResult });
  1039. }
  1040. catch (Exception ex)
  1041. {
  1042. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertRecordByTeacher()\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1043. return BadRequest();
  1044. }
  1045. /*if (exams.IsNotEmpty())
  1046. {
  1047. ExamInfo examInfo = exams[0];
  1048. //提交答案时间必须是状态已发布,且时间在起止时间内
  1049. if (examInfo.startTime <= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() && examInfo.status == 200 &&
  1050. examInfo.endTime >= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
  1051. {
  1052. return builder.Data(await _azureCosmos.SaveOrUpdate(request)).build();
  1053. }
  1054. else
  1055. {
  1056. return builder.Error(ResponseCode.FAILED, "请在作答时间段内提交答案!").build();
  1057. }
  1058. }
  1059. else
  1060. {
  1061. return builder.Error(ResponseCode.DATA_EXIST, "考试不存在!").build();
  1062. }*/
  1063. }
  1064. /// <summary>
  1065. /// 查询评测详细信息(教师或者学生通用)
  1066. /// </summary>
  1067. /// <param name="request"></param>
  1068. /// <returns></returns>
  1069. [ProducesDefaultResponseType]
  1070. //[AuthToken(Roles = "teacher")]
  1071. [HttpPost("find-summary-record")]
  1072. public async Task<IActionResult> findSummaryRecord(JsonElement requert)
  1073. {
  1074. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1075. try
  1076. {
  1077. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1078. //if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
  1079. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1080. if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
  1081. if (!requert.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  1082. // 如果只有学生id则返回学生参加过的考试 只返回相关摘要信息
  1083. var client = _azureCosmos.GetCosmosClient();
  1084. //string code = school_code.ToString().Substring(5);
  1085. //ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{school_code}"));
  1086. List<object> examClassResults = new List<object>();
  1087. await foreach (var item in client.GetContainer(Constant.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}'",
  1088. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school_code}") }))
  1089. {
  1090. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1091. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1092. {
  1093. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1094. {
  1095. examClassResults.Add(obj.ToObject<object>());
  1096. }
  1097. }
  1098. }
  1099. /*if (StringHelper.getKeyCount(requert) == 1 && requert.TryGetProperty("code", out JsonElement code))
  1100. {
  1101. List<object> props = new List<object>();
  1102. await foreach (var item in client.GetContainer(Constant.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}") }))
  1103. {
  1104. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1105. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1106. {
  1107. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1108. {
  1109. props.Add(obj.ToObject<object>());
  1110. }
  1111. }
  1112. }
  1113. return Ok(new { props });
  1114. }
  1115. else
  1116. {
  1117. if (requert.TryGetProperty("examCode", out JsonElement _))
  1118. {
  1119. //List<string> props = new List<string> { "id", "code", "examCode", "status", "mark", "score" };
  1120. //List<ExamRecord> examRecords = await _azureCosmos.FindByDict<ExamRecord>(request, props);
  1121. //return builder.Data(examRecords).Extend(new Dictionary<string, object> { { "props", props } }).build();
  1122. List<object> props = new List<object>();
  1123. await foreach (var item in client.GetContainer(Constant.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}") }))
  1124. {
  1125. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1126. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1127. {
  1128. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1129. {
  1130. props.Add(obj.ToObject<object>());
  1131. }
  1132. }
  1133. }
  1134. return Ok(new { props });
  1135. }
  1136. }*/
  1137. return Ok(new { examClassResults });
  1138. }
  1139. catch (Exception ex)
  1140. {
  1141. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findSummaryRecord()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1142. return BadRequest();
  1143. }
  1144. }
  1145. //学生端查询评测列表
  1146. [ProducesDefaultResponseType]
  1147. //[AuthToken(Roles = "Student")]
  1148. [HttpPost("find-summary-by-student")]
  1149. public async Task<IActionResult> findSummaryStudent(JsonElement requert)
  1150. {
  1151. //ResponseBuilder builder = ResponseBuilder.custom();
  1152. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1153. try
  1154. {
  1155. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1156. //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1157. if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  1158. if (!requert.TryGetProperty("code", out JsonElement school)) return BadRequest();
  1159. if (!requert.TryGetProperty("scode", out JsonElement scode)) return BadRequest();
  1160. var client = _azureCosmos.GetCosmosClient();
  1161. var query = $"select c.id,c.code,c.school,c.creatorId,c.progress,A0.id paperId,A0.code paperCode,A0.name paperName,A0.knowledge,A0.point,A0.field,A0.multipleRule,A0.scope,A0.blob,A0.time from c join A0 in c.papers where c.id ='{id}'";
  1162. List<PaperSimple> papers = new List<PaperSimple>();
  1163. List<object> subjects = new List<object>();
  1164. List<string> classIds = new List<string>();
  1165. //List<string> stus = new List<string>();
  1166. //存放当前学生所在班级ID或者名单ID
  1167. HashSet<string> resultIds = new HashSet<string>();
  1168. //List<string> ids = new List<string>();
  1169. //处理班级人数(公共部分的校本名单)
  1170. //List<Student> students = new List<Student>();
  1171. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(queryText: $"select c.classId id from c where c.id = '{studentId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{school}") }))
  1172. {
  1173. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1174. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1175. {
  1176. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1177. while (accounts.MoveNext())
  1178. {
  1179. JsonElement account = accounts.Current;
  1180. resultIds.Add(account.GetProperty("id").GetString());
  1181. }
  1182. }
  1183. }
  1184. //获取自定义名单信息
  1185. List<GroupList> stuLists = new List<GroupList>();
  1186. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<GroupList>(queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}'",
  1187. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList") }))
  1188. {
  1189. stuLists.Add(item);
  1190. }
  1191. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<GroupList>(queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}'",
  1192. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"GroupList-{school}") }))
  1193. {
  1194. stuLists.Add(item);
  1195. }
  1196. if (stuLists.Count > 0)
  1197. {
  1198. foreach (GroupList stuList in stuLists)
  1199. {
  1200. resultIds.Add(stuList.id);
  1201. }
  1202. }
  1203. var queryClassId = $"select c.classes id,c.stuLists stus from c where c.id ='{id}'";
  1204. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: queryClassId, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1205. {
  1206. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1207. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1208. {
  1209. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1210. {
  1211. classIds.AddRange(obj.GetProperty("id").ToObject<List<string>>());
  1212. classIds.AddRange(obj.GetProperty("stus").ToObject<List<string>>());
  1213. //classIds = obj.ToObject<List<string>>();
  1214. }
  1215. }
  1216. }
  1217. //存放该学生所在班级参与当前评测的ID
  1218. List<string> infoIds = new List<string>();
  1219. foreach (string ids in resultIds)
  1220. {
  1221. if (classIds.Contains(ids))
  1222. {
  1223. infoIds.Add(ids);
  1224. }
  1225. }
  1226. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<PaperSimple>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1227. {
  1228. papers.Add(item);
  1229. }
  1230. var querySubject = $"select A0.id,A0.name from c join A0 in c.subjects where c.id ='{id}'";
  1231. //List<object> props = new List<object>();
  1232. List<string> subId = new();
  1233. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: querySubject, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1234. {
  1235. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1236. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1237. {
  1238. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1239. {
  1240. subjects.Add(obj.ToObject<object>());
  1241. subId.Add(obj.GetProperty("id").GetString());
  1242. }
  1243. }
  1244. }
  1245. var queryAnswers = $"select c.id,c.code,c.studentIds,c.subjectId,c.studentAnswers,c.studentScores,c.sum,c.mark,c.krate,c.frate from c where c.examId ='{id}' and array_contains(c.studentIds,'{studentId}') and c.pk = 'ExamClassResult' ";
  1246. List<ExamClassResult> answers = new List<ExamClassResult>();
  1247. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: queryAnswers,
  1248. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  1249. {
  1250. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1251. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1252. {
  1253. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1254. {
  1255. answers.Add(obj.ToObject<ExamClassResult>());
  1256. }
  1257. }
  1258. }
  1259. List<List<string>> stuAns = new();
  1260. List<List<double>> stuScore = new();
  1261. List<List<List<Details>>> mark = new();
  1262. List<List<double>> total = new();
  1263. List<double> average = new();
  1264. if (answers.Count > 0)
  1265. {
  1266. foreach (ExamClassResult result in answers)
  1267. {
  1268. List<double> sTotal = new();
  1269. int index = result.studentIds.IndexOf(studentId.ToString());
  1270. if (index == -1)
  1271. {
  1272. break;
  1273. }
  1274. stuAns.Add(result.studentAnswers[index]);
  1275. stuScore.Add(result.studentScores[index]);
  1276. mark.Add(result.mark[index]);
  1277. average.Add(result.average);
  1278. sTotal.Add(result.sum.Where(s => s <= 59).Count());
  1279. sTotal.Add(result.sum.Where(s => s > 59 && s <= 70).Count());
  1280. sTotal.Add(result.sum.Where(s => s > 70 && s <= 80).Count());
  1281. sTotal.Add(result.sum.Where(s => s > 80 && s <= 90).Count());
  1282. sTotal.Add(result.sum.Where(s => s > 90 && s <= 100).Count());
  1283. total.Add(sTotal);
  1284. }
  1285. }
  1286. List<(List<string> kn, List<double> kps, List<double> ckps)> know = new();
  1287. List<(List<int> fs, List<double> fps, List<double> cfps)> fp = new();
  1288. foreach (var s in stuTask(subId, papers, answers, studentId.GetString()))
  1289. {
  1290. know = s.know;
  1291. fp = s.filed;
  1292. }
  1293. if (papers.IsNotEmpty())
  1294. {
  1295. var knowledge = know.Select(k => new { k.kn, k.kps, k.ckps });
  1296. var filed = fp.Select(k => new { k.fs, k.fps, k.cfps });
  1297. //papers = papers
  1298. return Ok(new { papers, subjects, stuScore, stuAns, mark, total, claId = infoIds, knowledge, filed, average, status = 200 });
  1299. }
  1300. else
  1301. {
  1302. return Ok(new { papers, subjects, stuScore, stuAns, mark, total, claId = infoIds, status = 404 });
  1303. }
  1304. }
  1305. catch (Exception ex)
  1306. {
  1307. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find-summary-by-student()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1308. return Ok(new { status = 400 });
  1309. }
  1310. }
  1311. private IEnumerable<(List<(List<string> kn, List<double> kps, List<double> ckps)> know, List<(List<int> fs, List<double> fps, List<double> cfps)> filed)> stuTask(List<string> subjectIds, List<PaperSimple> papers, List<ExamClassResult> answers, string stuId)
  1312. {
  1313. List<(List<string> kn, List<double> kps, List<double> ckps)> know = new List<(List<string> kn, List<double> kps, List<double> ckps)>();
  1314. List<(List<int> fs, List<double> fps, List<double> cfps)> filed = new List<(List<int> fs, List<double> fps, List<double> cfps)>();
  1315. int no = 0;
  1316. foreach (string sub in subjectIds)
  1317. {
  1318. List<double> kp = new();
  1319. List<double> fp = new();
  1320. List<double> ckp = new();
  1321. List<double> cfp = new();
  1322. List<int> fields = new() { 1, 2, 3, 4, 5, 6 };
  1323. //获取该试卷所有知识点和认知层次分布
  1324. List<List<string>> kones = papers[no].knowledge;
  1325. List<int> fs = papers[no].field;
  1326. List<double> point = papers[no].point;
  1327. //去重知识点
  1328. HashSet<string> knowles = new();
  1329. List<string> knowledges = new();
  1330. if (kones.Count > 0)
  1331. {
  1332. kones.ForEach(kno =>
  1333. {
  1334. kno.ForEach(k =>
  1335. {
  1336. knowles.Add(k);
  1337. });
  1338. });
  1339. }
  1340. foreach (string cla in knowles)
  1341. {
  1342. knowledges.Add(cla);
  1343. }
  1344. for (int k = 0; k < knowledges.Count; k++)
  1345. {
  1346. if (null == knowledges[k])
  1347. {
  1348. knowledges.Remove(knowledges[k]);
  1349. }
  1350. }
  1351. foreach (ExamClassResult result in answers)
  1352. {
  1353. if (result.subjectId.Equals(sub))
  1354. {
  1355. int index = result.studentIds.IndexOf(stuId.ToString());
  1356. //处理知识点
  1357. foreach (string k in knowledges)
  1358. {
  1359. //初始化单个知识点得分
  1360. double score = 0;
  1361. double allScore = 0;
  1362. int n = 0;
  1363. foreach (List<string> str in kones)
  1364. {
  1365. if (str.Contains(k))
  1366. {
  1367. var itemPersent = str.Count > 0 ? 1 / Convert.ToDouble(str.Count) : 0;
  1368. allScore += point.Count > 0 ? point[n] * itemPersent : 0;
  1369. if (result.studentScores.Count > 0)
  1370. {
  1371. if (result.studentScores[index].Count > 0)
  1372. {
  1373. score += result.studentScores[index][n] == -1 ? 0 : result.studentScores[index][n];
  1374. }
  1375. }
  1376. }
  1377. n++;
  1378. }
  1379. kp.Add(allScore > 0 ? Math.Round(score / allScore, 2) : 0);
  1380. }
  1381. //处理认知层次
  1382. foreach (int k in fields)
  1383. {
  1384. //初始化认知层次得分
  1385. double score = 0;
  1386. double allScore = 0;
  1387. int n = 0;
  1388. foreach (int str in fs)
  1389. {
  1390. if (str == k)
  1391. {
  1392. var itemPersent = 1;
  1393. allScore += point.Count > 0 ? point[n] * itemPersent : 0;
  1394. if (result.studentScores.Count > 0)
  1395. {
  1396. if (result.studentScores[index].Count > 0)
  1397. {
  1398. score += result.studentScores[index][n] == -1 ? 0 : result.studentScores[index][n];
  1399. }
  1400. }
  1401. }
  1402. n++;
  1403. }
  1404. fp.Add(allScore > 0 ? Math.Round(score / allScore, 2) : 0);
  1405. }
  1406. ckp = result.krate;
  1407. cfp = result.frate;
  1408. }
  1409. }
  1410. know.Add((knowledges, kp, ckp));
  1411. filed.Add((fields, fp, cfp));
  1412. no++;
  1413. }
  1414. yield return (know, filed);
  1415. }
  1416. //查询学生活动列表
  1417. [ProducesDefaultResponseType]
  1418. //[AuthToken(Roles = "Student")]
  1419. [HttpPost("find-all-by-student")]
  1420. public async Task<IActionResult> findAllStudent(JsonElement requert)
  1421. {
  1422. //ResponseBuilder builder = ResponseBuilder.custom();
  1423. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1424. try
  1425. {
  1426. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1427. if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  1428. List<string> resultIds = new List<string>();
  1429. var client = _azureCosmos.GetCosmosClient();
  1430. //查询校本班级ID
  1431. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(
  1432. queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}' and c.pk = 'Class' "))
  1433. {
  1434. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1435. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1436. {
  1437. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1438. while (accounts.MoveNext())
  1439. {
  1440. JsonElement account = accounts.Current;
  1441. resultIds.Add(account.GetProperty("id").GetString());
  1442. }
  1443. }
  1444. }
  1445. //查询私人班级ID
  1446. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(
  1447. queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}' and c.pk = 'Class' "))
  1448. {
  1449. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1450. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1451. {
  1452. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1453. while (accounts.MoveNext())
  1454. {
  1455. JsonElement account = accounts.Current;
  1456. resultIds.Add(account.GetProperty("id").GetString());
  1457. }
  1458. }
  1459. }
  1460. //StringBuilder builder = new StringBuilder();
  1461. HashSet<string> strs = new HashSet<string>();
  1462. if (resultIds.Count > 1)
  1463. {
  1464. foreach (string str in resultIds)
  1465. {
  1466. strs.Add($"array_contains(c.classes,'{str}')");
  1467. //builder.Append($"array_contains(c.targetClassIds,'{str}')").Append("or");
  1468. }
  1469. //builder.ToString().Substring(0, builder.ToString().Length - 2);
  1470. }
  1471. else
  1472. {
  1473. string ssr = resultIds.Count > 0 ? resultIds[0] : "";
  1474. strs.Add($"array_contains(c.classes,'{ssr}')");
  1475. //builder.Append($" array_contains(c.targetClassIds,'{ssr}')");
  1476. }
  1477. string ss = string.Join(" or ", strs);
  1478. //if (!requert.TryGetProperty("school", out JsonElement school)) return BadRequest();
  1479. 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' ";
  1480. List<object> props = new List<object>();
  1481. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: query))
  1482. {
  1483. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1484. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1485. {
  1486. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1487. {
  1488. props.Add(obj.ToObject<object>());
  1489. }
  1490. }
  1491. }
  1492. 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'";
  1493. List<ExamClassResult> Classes = new List<ExamClassResult>();
  1494. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: queryClass))
  1495. {
  1496. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1497. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1498. {
  1499. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1500. {
  1501. Classes.Add(obj.ToObject<ExamClassResult>());
  1502. }
  1503. }
  1504. }
  1505. List<ExamClassResult> result = new List<ExamClassResult>();
  1506. foreach (ExamClassResult classResult in Classes)
  1507. {
  1508. int index = classResult.studentIds.IndexOf(studentId.ToString());
  1509. ExamClassResult result1 = new ExamClassResult();
  1510. result1.examId = classResult.examId;
  1511. result1.subjectId = classResult.subjectId;
  1512. result1.studentAnswers.Add(classResult.studentAnswers[index]);
  1513. result1.studentScores.Add(classResult.studentScores[index]);
  1514. result.Add(result1);
  1515. }
  1516. return Ok(new { props, result });
  1517. }
  1518. catch (Exception ex)
  1519. {
  1520. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1521. return BadRequest();
  1522. }
  1523. }
  1524. //查询学生活动列表
  1525. [ProducesDefaultResponseType]
  1526. //[AuthToken(Roles = "Student")]
  1527. [HttpPost("find-score-by-student")]
  1528. public async Task<IActionResult> findScoreByStudent(JsonElement requert)
  1529. {
  1530. //ResponseBuilder builder = ResponseBuilder.custom();
  1531. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1532. try
  1533. {
  1534. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1535. //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1536. var client = _azureCosmos.GetCosmosClient();
  1537. var query = $"select c.examId,c.subjectId,c.studentScores from c where array_contains(c.studentIds,'{id}') ";
  1538. List<object> props = new List<object>();
  1539. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: query))
  1540. {
  1541. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1542. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1543. {
  1544. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1545. {
  1546. props.Add(obj.ToObject<object>());
  1547. }
  1548. }
  1549. }
  1550. return Ok(props);
  1551. }
  1552. catch (Exception ex)
  1553. {
  1554. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1555. return BadRequest();
  1556. }
  1557. }
  1558. //查询学生活动列表
  1559. [ProducesDefaultResponseType]
  1560. //[AuthToken(Roles = "Student")]
  1561. [HttpPost("finish")]
  1562. public async Task<IActionResult> finish(JsonElement requert)
  1563. {
  1564. //ResponseBuilder builder = ResponseBuilder.custom();
  1565. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1566. try
  1567. {
  1568. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1569. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1570. var client = _azureCosmos.GetCosmosClient();
  1571. ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1572. info.progress = "finish";
  1573. info.endTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1574. List<ExamClassResult> classResults = new();
  1575. if (info.scope.Equals("school"))
  1576. {
  1577. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  1578. queryText: $"select value(c) from c where c.examId = '{id}'",
  1579. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1580. {
  1581. classResults.Add(item);
  1582. }
  1583. }
  1584. else
  1585. {
  1586. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  1587. queryText: $"select value(c) from c where c.examId = '{id}'",
  1588. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1589. {
  1590. classResults.Add(item);
  1591. }
  1592. }
  1593. foreach (ExamClassResult examClass in classResults)
  1594. {
  1595. examClass.progress = true;
  1596. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(examClass, examClass.id, new PartitionKey($"{examClass.code}"));
  1597. }
  1598. info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1599. return Ok(info);
  1600. }
  1601. catch (Exception ex)
  1602. {
  1603. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/finish\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1604. return BadRequest();
  1605. }
  1606. }
  1607. /*//查询任务列表
  1608. [ProducesDefaultResponseType]
  1609. //[AuthToken(Roles = "Student")]
  1610. [HttpPost("scoring")]
  1611. public async Task<IActionResult> Scoring(JsonElement requert)
  1612. {
  1613. //ResponseBuilder builder = ResponseBuilder.custom();
  1614. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1615. try
  1616. {
  1617. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1618. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1619. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1620. var client = _azureCosmos.GetCosmosClient();
  1621. ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1622. int index = 0;
  1623. foreach (ExamSubject subject in info.subjects) {
  1624. if (!subject.id.Equals(subjectId.ToString()))
  1625. {
  1626. index++;
  1627. }
  1628. else {
  1629. break;
  1630. }
  1631. }
  1632. List<string> stuAns = new();
  1633. Dictionary<string, List<List<double>>> keyValues = new();
  1634. List<ExamClassResult> classResults = new();
  1635. if (info.scope.Equals("school"))
  1636. {
  1637. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  1638. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1639. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1640. {
  1641. classResults.Add(item);
  1642. }
  1643. }
  1644. else
  1645. {
  1646. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  1647. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1648. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1649. {
  1650. classResults.Add(item);
  1651. }
  1652. }
  1653. List<List<double>> itemScore = new();
  1654. for (int i = 0; i < info.papers[index].point.Count; i++)
  1655. {
  1656. List<double> score = new();
  1657. foreach (ExamClassResult examClass in classResults)
  1658. {
  1659. foreach (List<double> sc in examClass.studentScores)
  1660. {
  1661. score.Add(sc[i]);
  1662. }
  1663. }
  1664. itemScore.Add(score);
  1665. }
  1666. foreach (ExamClassResult examClass in classResults)
  1667. {
  1668. foreach (List<string> ans in examClass.studentAnswers)
  1669. {
  1670. if (ans.Count > 0)
  1671. {
  1672. stuAns.Add(ans[0]);
  1673. }
  1674. else
  1675. {
  1676. stuAns.Add("");
  1677. }
  1678. }
  1679. }
  1680. //info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1681. return Ok(new { score = itemScore , stuAns, paper = info.papers });
  1682. }
  1683. catch (Exception ex)
  1684. {
  1685. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1686. return BadRequest();
  1687. }
  1688. }*/
  1689. [ProducesDefaultResponseType]
  1690. [AuthToken(Roles = "teacher,admin")]
  1691. [HttpPost("scoring")]
  1692. public async Task<IActionResult> scoring(JsonElement requert)
  1693. {
  1694. //ResponseBuilder builder = ResponseBuilder.custom();
  1695. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1696. try
  1697. {
  1698. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1699. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1700. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1701. //if (!requert.TryGetProperty("type", out JsonElement type)) return BadRequest();
  1702. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1703. if (!requert.TryGetProperty("count", out JsonElement scount)) return BadRequest();
  1704. var client = _azureCosmos.GetCosmosClient();
  1705. //var redisClient = _azureRedis.GetRedisClient(8);
  1706. ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1707. List<ExamClassResult> classResults = new();
  1708. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  1709. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1710. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and array_contains(c.tIds,'{tId}') ",
  1711. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1712. {
  1713. attr.Add(item);
  1714. }
  1715. List<SDK.Models.Cosmos.Common.Scoring> attrSc = new List<SDK.Models.Cosmos.Common.Scoring>();
  1716. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1717. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1718. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1719. {
  1720. attrSc.Add(item);
  1721. }
  1722. int index = 0;
  1723. foreach (ExamSubject subject in info.subjects)
  1724. {
  1725. if (!subject.id.Equals(subjectId.ToString()))
  1726. {
  1727. index++;
  1728. }
  1729. else
  1730. {
  1731. break;
  1732. }
  1733. }
  1734. List<dynamic> objs = new List<dynamic>();
  1735. List<dynamic> wobjs = new List<dynamic>();
  1736. /*if (type.GetInt32() != 1) {
  1737. return Ok(new { attr, paper = info.papers[index].blob });
  1738. }*/
  1739. //List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  1740. //List<SDK.Models.Cosmos.Common.Scoring> arbs = new();
  1741. Correct correct = null;
  1742. var cResponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Correct-{code}"));
  1743. if (cResponse.Status == 200)
  1744. {
  1745. using var cJson = await JsonDocument.ParseAsync(cResponse.ContentStream);
  1746. correct = cJson.ToObject<Correct>();
  1747. }
  1748. int finishCount = 0;
  1749. foreach (SDK.Models.Cosmos.Common.Scoring ss in attrSc)
  1750. {
  1751. for (int i = 0; i < correct.num; i++)
  1752. {
  1753. List<double> tsc = new List<double>();
  1754. foreach (Item item in ss.items)
  1755. {
  1756. if (item.scores.Count > 0)
  1757. {
  1758. if (i >= item.scores.Count)
  1759. {
  1760. break;
  1761. }
  1762. else
  1763. {
  1764. tsc.Add(item.scores[i].sc);
  1765. }
  1766. }
  1767. }
  1768. bool flag = tsc.Exists(s => s == -1);
  1769. if (!flag && tsc.Count > 0)
  1770. {
  1771. finishCount++;
  1772. }
  1773. }
  1774. }
  1775. if (attr.Count > 0)
  1776. {
  1777. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  1778. {
  1779. //var scc = ss.items.SelectMany(p => p.scores, (p, d) => new { p.ssc, d.sc, d.tmdId }).Where(x => x.tmdId.Equals(tId.GetString())).Select(m => new { m.sc ,m.ssc});
  1780. List<dynamic> sc = new List<dynamic>();
  1781. List<dynamic> allSc = new List<dynamic>();
  1782. ss.qs = ss.qs.Where(s => !string.IsNullOrEmpty(s.tId)).ToList();
  1783. int indexScore = 0;
  1784. (string ansBlob, List<double> scores) = await getMoreStuInfo(client, ss.stuId, ss.examId, ss.subjectId, code.GetString());
  1785. foreach (Item item in ss.items)
  1786. {
  1787. var count = item.scores.GroupBy(i => new { i.tmdId, i.sc }).Select(c => c.Key.sc).ToList();
  1788. allSc.Add(count.FirstOrDefault());
  1789. List<double> scc = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).ToList();
  1790. List<string> blob = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.mark).ToList();
  1791. //item.scores.Where(x => x.tmdId.Equals(tId.GetString())).SelectMany(p => p.sc, (p, d) => new { });
  1792. if (scc.Count > 0)
  1793. {
  1794. sc.Add(new { sc = scc.FirstOrDefault(), blob = blob.FirstOrDefault(), item.ssc });
  1795. }
  1796. else
  1797. {
  1798. ss.scores = scores;
  1799. sc.Add(new { sc = ss.scores[indexScore], blob = "", item.ssc });
  1800. }
  1801. indexScore++;
  1802. }
  1803. var obj = new { ss.id, ss.stuId, ss.examId, ss.subjectId, item = sc, ss.qs, blob = ansBlob, ss.tIds, scores = scores, ss.model, ss.mode };
  1804. objs.Add(obj);
  1805. }
  1806. }
  1807. else
  1808. {
  1809. if (requert.TryGetProperty("stuId", out JsonElement stuId))
  1810. {
  1811. objs = await Review(attrSc, id.GetString(), code.GetString(), subjectId.GetString(), scount.GetInt32(), tId.GetString(), stuId.GetString());
  1812. }
  1813. else
  1814. {
  1815. objs = await Review(attrSc, id.GetString(), code.GetString(), subjectId.GetString(), scount.GetInt32(), tId.GetString(), "");
  1816. }
  1817. }
  1818. var fp = attr.Count > 0 ? Math.Round(finishCount * 1.0 / (attrSc.Count * correct.num), 2) : 0;
  1819. return Ok(new { objs, paper = info.papers[index].blob, fp });
  1820. }
  1821. catch (Exception ex)
  1822. {
  1823. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1824. return BadRequest();
  1825. }
  1826. }
  1827. //查找异常卷
  1828. [ProducesDefaultResponseType]
  1829. //[AuthToken(Roles = "Student")]
  1830. [HttpPost("find-err")]
  1831. public async Task<IActionResult> findErr(JsonElement requert)
  1832. {
  1833. //ResponseBuilder builder = ResponseBuilder.custom();
  1834. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1835. try
  1836. {
  1837. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1838. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1839. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1840. //if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1841. var client = _azureCosmos.GetCosmosClient();
  1842. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
  1843. if (response.Status == 200)
  1844. {
  1845. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  1846. ExamInfo info = json.ToObject<ExamInfo>();
  1847. //ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1848. List<ExamClassResult> classResults = new();
  1849. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  1850. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1851. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1852. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1853. {
  1854. attr.Add(item);
  1855. }
  1856. int index = 0;
  1857. foreach (ExamSubject subject in info.subjects)
  1858. {
  1859. if (!subject.id.Equals(subjectId.ToString()))
  1860. {
  1861. index++;
  1862. }
  1863. else
  1864. {
  1865. break;
  1866. }
  1867. }
  1868. List<dynamic> objs = new List<dynamic>();
  1869. List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  1870. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  1871. {
  1872. List<Qs> qs = ss.qs.Where(s => !string.IsNullOrEmpty(s.err)).ToList();
  1873. if (qs.Count > 0)
  1874. {
  1875. ss.qs = qs;
  1876. errs.Add(ss);
  1877. }
  1878. }
  1879. return Ok(new { errs, paper = info.papers[index].blob });
  1880. }
  1881. else
  1882. {
  1883. return BadRequest();
  1884. }
  1885. }
  1886. catch (Exception ex)
  1887. {
  1888. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find-err\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1889. return BadRequest();
  1890. }
  1891. }
  1892. [ProducesDefaultResponseType]
  1893. //[AuthToken(Roles = "Student")]
  1894. [HttpPost("find-arb")]
  1895. public async Task<IActionResult> findArb(JsonElement requert)
  1896. {
  1897. //ResponseBuilder builder = ResponseBuilder.custom();
  1898. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1899. try
  1900. {
  1901. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1902. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1903. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1904. if (!requert.TryGetProperty("et", out JsonElement et)) return BadRequest();
  1905. //if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1906. var client = _azureCosmos.GetCosmosClient();
  1907. long time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1908. if (et.GetInt64() > time)
  1909. {
  1910. return Ok(new { msg = "还在进行中", code = 202 });
  1911. }
  1912. ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1913. List<ExamClassResult> classResults = new();
  1914. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  1915. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1916. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1917. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1918. {
  1919. attr.Add(item);
  1920. }
  1921. int index = 0;
  1922. foreach (ExamSubject subject in info.subjects)
  1923. {
  1924. if (!subject.id.Equals(subjectId.ToString()))
  1925. {
  1926. index++;
  1927. }
  1928. else
  1929. {
  1930. break;
  1931. }
  1932. }
  1933. List<dynamic> objs = new List<dynamic>();
  1934. /*if (type.GetInt32() != 1) {
  1935. return Ok(new { attr, paper = info.papers[index].blob });
  1936. }*/
  1937. //List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  1938. List<SDK.Models.Cosmos.Common.Scoring> arbs = new();
  1939. //List<(string id,List<double>)> osc = new List<(string id, List<double>)>();
  1940. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  1941. {
  1942. //List<double> original = new List<double>();
  1943. List<Item> arb = ss.items.Where(s => s.flag == false).ToList();
  1944. (string ansBlob, List<double> scores) = await getMoreStuInfo(client, ss.stuId, ss.examId, ss.subjectId, code.GetString());
  1945. ss.blob = ansBlob;
  1946. ss.scores = scores;
  1947. if (arb.Count > 0)
  1948. {
  1949. ss.items = arb;
  1950. arbs.Add(ss);
  1951. }
  1952. }
  1953. return Ok(new { arbs = arbs.Select(a => new { a.items, a.blob, a.stuId, a.subjectId, a.id, a.scores }), paper = info.papers[index].blob });
  1954. }
  1955. catch (Exception ex)
  1956. {
  1957. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find-arb\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1958. return BadRequest();
  1959. }
  1960. }
  1961. //批阅,给老师随机分配阅卷数据,以及查询改老师已有的阅卷数据
  1962. private async Task<List<dynamic>> Review(List<SDK.Models.Cosmos.Common.Scoring> attr, string id, string code, string subjectId, int count, string tId, string stuId)
  1963. {
  1964. //ResponseBuilder builder = ResponseBuilder.custom();
  1965. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1966. try
  1967. {
  1968. var client = _azureCosmos.GetCosmosClient();
  1969. //var redisClient = _azureRedis.GetRedisClient(8);
  1970. List<ExamClassResult> classResults = new();
  1971. List<SDK.Models.Cosmos.Common.Scoring> recs = new();
  1972. List<SDK.Models.Cosmos.Common.Scoring> all = new();
  1973. //List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  1974. /*await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1975. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' ",
  1976. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1977. {
  1978. attr.Add(item);
  1979. }*/
  1980. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  1981. {
  1982. if (scoring.tIds.Contains(tId.ToString()))
  1983. {
  1984. recs.Add(scoring);
  1985. }
  1986. else if (scoring.tIds.Count < scoring.count * scoring.model)
  1987. {
  1988. all.Add(scoring);
  1989. }
  1990. }
  1991. if (!string.IsNullOrEmpty(stuId))
  1992. {
  1993. List<SDK.Models.Cosmos.Common.Scoring> value = new();
  1994. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1995. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.stuId = '{stuId}' ",
  1996. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1997. {
  1998. value.Add(item);
  1999. }
  2000. if (value.Count > 0)
  2001. {
  2002. foreach (SDK.Models.Cosmos.Common.Scoring scoring in value)
  2003. {
  2004. if (scoring.tIds.Contains(tId.ToString()))
  2005. {
  2006. break;
  2007. }
  2008. else
  2009. {
  2010. scoring.tIds.Add(tId.ToString());
  2011. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey(scoring.code));
  2012. }
  2013. }
  2014. }
  2015. List<dynamic> objs = new List<dynamic>();
  2016. List<SDK.Models.Cosmos.Common.Scoring> val = new List<SDK.Models.Cosmos.Common.Scoring>();
  2017. foreach (SDK.Models.Cosmos.Common.Scoring ss in value)
  2018. {
  2019. //var scc = ss.items.SelectMany(p => p.scores, (p, d) => new { p.ssc, d.sc, d.tmdId }).Where(x => x.tmdId.Equals(tId.GetString())).Select(m => new { m.sc, m.ssc });
  2020. List<dynamic> sc = new List<dynamic>();
  2021. int indexScore = 0;
  2022. ss.qs = ss.qs.Where(s => !string.IsNullOrEmpty(s.tId)).ToList();
  2023. (string ansBlob, List<double> scores) = await getMoreStuInfo(client, ss.stuId, ss.examId, ss.subjectId, code);
  2024. foreach (Item item in ss.items)
  2025. {
  2026. List<double> scc = item.scores.Where(x => x.tmdId.Equals(tId)).Select(c => c.sc).ToList();
  2027. //item.scores.Where(x => x.tmdId.Equals(tId.GetString())).SelectMany(p => p.sc, (p, d) => new { });
  2028. if (scc.Count > 0)
  2029. {
  2030. sc.Add(new { sc = scc.FirstOrDefault(), item.ssc });
  2031. }
  2032. else
  2033. {
  2034. ss.scores = scores;
  2035. sc.Add(new { sc = ss.scores[indexScore], item.ssc });
  2036. }
  2037. indexScore++;
  2038. }
  2039. var obj = new { ss.id, ss.stuId, ss.examId, ss.subjectId, item = sc, ss.qs, blob = ansBlob, ss.tIds, scores = scores, ss.model, ss.mode };
  2040. objs.Add(obj);
  2041. }
  2042. return objs;
  2043. }
  2044. else
  2045. {
  2046. List<SDK.Models.Cosmos.Common.Scoring> notYet = new();
  2047. notYet = all.Where(x => x.tIds.Count < x.count * x.model - 1).ToList();
  2048. List<dynamic> objs = new List<dynamic>();
  2049. for (int i = 0; i < count; i++)
  2050. {
  2051. Random random = new Random();
  2052. SDK.Models.Cosmos.Common.Scoring item = new();
  2053. if (notYet.Count > 0)
  2054. {
  2055. int index = random.Next(notYet.Count);
  2056. item = notYet[index];
  2057. notYet.RemoveAt(index);
  2058. }
  2059. else
  2060. {
  2061. int index = random.Next(all.Count);
  2062. item = all[index];
  2063. all.RemoveAt(index);
  2064. }
  2065. if (!item.tIds.Contains(tId.ToString()))
  2066. {
  2067. item.tIds.Add(tId.ToString());
  2068. }
  2069. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  2070. List<dynamic> sc = new List<dynamic>();
  2071. (string ansBlob, List<double> scores) = await getMoreStuInfo(client, item.stuId, item.examId, item.subjectId, code);
  2072. int indexScore = 0;
  2073. item.qs = item.qs.Where(s => !string.IsNullOrEmpty(s.tId)).ToList();
  2074. foreach (Item its in item.items)
  2075. {
  2076. List<double> ssc = its.scores.Where(x => x.tmdId.Equals(tId)).Select(c => c.sc).ToList();
  2077. if (ssc.Count > 0)
  2078. {
  2079. sc.Add(new { sc = ssc.FirstOrDefault(), its.ssc });
  2080. }
  2081. else
  2082. {
  2083. item.scores = scores;
  2084. sc.Add(new { sc = item.scores[indexScore], its.ssc });
  2085. }
  2086. indexScore++;
  2087. }
  2088. var obj = new { item.id, item.stuId, item.examId, item.subjectId, item = sc, item.qs, blob = ansBlob, item.tIds, scores = scores, item.model, item.mode };
  2089. objs.Add(obj);
  2090. }
  2091. return objs;
  2092. /*if (recs.Count == count.GetInt32())
  2093. {
  2094. return Ok(new { msg = "分配人数已到上限" });
  2095. }
  2096. else
  2097. {
  2098. if (all.Count == 0)
  2099. {
  2100. return Ok(new { msg = "暂无可选学生" });
  2101. }
  2102. //随机选取一名学生打分
  2103. Random random = new Random();
  2104. SDK.Models.Cosmos.Common.Scoring item = new();
  2105. List<SDK.Models.Cosmos.Common.Scoring> notYet = new();
  2106. notYet = all.Where(x => x.tIds.Count < x.count * x.model - 1).ToList();
  2107. if (notYet.Count > 0)
  2108. {
  2109. item = notYet[random.Next(notYet.Count)];
  2110. }
  2111. else
  2112. {
  2113. item = all[random.Next(all.Count)];
  2114. }
  2115. if (!item.tIds.Contains(tId.ToString()))
  2116. {
  2117. item.tIds.Add(tId.ToString());
  2118. }
  2119. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  2120. List<dynamic> sc = new List<dynamic>();
  2121. (string ansBlob, List<double> scores) = await getMoreStuInfo(client, item.stuId, item.examId, item.subjectId, code.GetString());
  2122. int indexScore = 0;
  2123. foreach (Item its in item.items)
  2124. {
  2125. List<double> ssc = its.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).ToList();
  2126. if (ssc.Count > 0)
  2127. {
  2128. sc.Add(new { sc = ssc.FirstOrDefault(), its.ssc });
  2129. }
  2130. else
  2131. {
  2132. item.scores = scores;
  2133. sc.Add(new { sc = item.scores[indexScore], its.ssc });
  2134. }
  2135. indexScore++;
  2136. }
  2137. var obj = new { item.id, item.stuId, item.examId, item.subjectId, item = sc, item.qs, blob = ansBlob, item.tIds, scores = scores, item.model, item.mode };
  2138. return Ok(obj);
  2139. }*/
  2140. }
  2141. }
  2142. catch (Exception ex)
  2143. {
  2144. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/review\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  2145. return new List<dynamic>() { new { code = 404, msg = "分配任务异常" } };
  2146. }
  2147. }
  2148. //批阅 提交分数
  2149. [ProducesDefaultResponseType]
  2150. [AuthToken(Roles = "teacher,admin")]
  2151. [HttpPost("sub-result")]
  2152. public async Task<IActionResult> SubResult(JsonElement requert)
  2153. {
  2154. //ResponseBuilder builder = ResponseBuilder.custom();
  2155. //var (id, school) = HttpContext.GetAuthTokenInfo();
  2156. try
  2157. {
  2158. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2159. if (!requert.TryGetProperty("stuId", out JsonElement sId)) return BadRequest();
  2160. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  2161. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  2162. if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest();
  2163. if (!requert.TryGetProperty("count", out JsonElement count)) return BadRequest();
  2164. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2165. requert.TryGetProperty("mark", out JsonElement mark);
  2166. var client = _azureCosmos.GetCosmosClient();
  2167. var (userid, name, _, school) = HttpContext.GetAuthTokenInfo();
  2168. //取得学校基本信息
  2169. var schresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school.ToString(), new PartitionKey("Base"));
  2170. string schname = string.Empty;
  2171. if (schresponse.Status == 200)
  2172. {
  2173. using var schjson = await JsonDocument.ParseAsync(schresponse.ContentStream);
  2174. schjson.RootElement.TryGetProperty("name", out JsonElement jsonschname);
  2175. schname = jsonschname.ToString();
  2176. }
  2177. List<ExamClassResult> classResults = new();
  2178. List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  2179. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  2180. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.stuId = '{sId}' and array_contains(c.tIds,'{tId}') ",
  2181. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  2182. {
  2183. attr.Add(item);
  2184. }
  2185. List<double> ssc = score.ToObject<List<double>>();
  2186. List<string> marks = mark.ToObject<List<string>>();
  2187. StringBuilder builder = new();
  2188. if (attr.Count > 0)
  2189. {
  2190. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  2191. {
  2192. int itemIndex = 0;
  2193. //int tIdIndex = scoring.tIds.IndexOf(tId.GetString());
  2194. if (requert.TryGetProperty("qu", out JsonElement qu))
  2195. {
  2196. List<int> nos = qu.ToObject<List<int>>();
  2197. foreach (int number in nos)
  2198. {
  2199. List<Info> items = scoring.items[number].scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  2200. if (items.Count > 0)
  2201. {
  2202. foreach (Info info in items)
  2203. {
  2204. info.sc = ssc[number];
  2205. info.mark = marks.Count > 0 ? marks[number] : "";
  2206. }
  2207. }
  2208. else
  2209. {
  2210. Info info = new();
  2211. info.sc = ssc[number];
  2212. info.tmdId = tId.GetString();
  2213. info.mark = marks.Count > 0 ? marks[number] : "";
  2214. info.index = number;
  2215. scoring.items[number].scores.Add(info);
  2216. }
  2217. }
  2218. }
  2219. else
  2220. {
  2221. foreach (Item item in scoring.items)
  2222. {
  2223. List<Info> items = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  2224. if (items.Count > 0)
  2225. {
  2226. foreach (Info info in items)
  2227. {
  2228. info.sc = ssc[itemIndex];
  2229. info.mark = marks.Count > 0 ? marks[itemIndex] : "";
  2230. }
  2231. }
  2232. else
  2233. {
  2234. if (ssc[itemIndex] >= 0)
  2235. {
  2236. Info info = new();
  2237. info.sc = ssc[itemIndex];
  2238. info.tmdId = tId.GetString();
  2239. info.mark = marks.Count > 0 ? marks[itemIndex] : "";
  2240. info.index = itemIndex;
  2241. item.scores.Add(info);
  2242. }
  2243. }
  2244. itemIndex++;
  2245. }
  2246. }
  2247. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey(scoring.code));
  2248. }
  2249. }
  2250. else
  2251. {
  2252. return BadRequest();
  2253. }
  2254. Correct correct = null;
  2255. var cResponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Correct-{code}"));
  2256. if (cResponse.Status == 200)
  2257. {
  2258. using var cJson = await JsonDocument.ParseAsync(cResponse.ContentStream);
  2259. correct = cJson.ToObject<Correct>();
  2260. }
  2261. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  2262. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  2263. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  2264. {
  2265. classResults.Add(item);
  2266. }
  2267. bool isFinish = false;
  2268. int scount = attr.Select(a => a.items[0].scores).ToList().Count;
  2269. foreach (SDK.Models.Cosmos.Common.Scoring sc in attr)
  2270. {
  2271. foreach (var item in sc.items)
  2272. {
  2273. if (item.scores.Count == 0)
  2274. {
  2275. isFinish = false;
  2276. break;
  2277. }
  2278. else
  2279. {
  2280. if (item.scores.Count != correct.num)
  2281. {
  2282. isFinish = false;
  2283. break;
  2284. }
  2285. else
  2286. {
  2287. isFinish = true;
  2288. }
  2289. }
  2290. }
  2291. }
  2292. if (isFinish)
  2293. {
  2294. foreach (ExamClassResult exam in classResults)
  2295. {
  2296. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  2297. {
  2298. int index = exam.studentIds.IndexOf(scoring.stuId);
  2299. if (index != -1)
  2300. {
  2301. int itemIndex = 0;
  2302. foreach (Item item in scoring.items)
  2303. {
  2304. var ace = item.scores.Where(x => string.IsNullOrEmpty(x.tmdId)).ToList();
  2305. if (ace.Count > 0)
  2306. {
  2307. return Ok(new { code = 1, msg = "用户信息未找到" });
  2308. }
  2309. //判定是否仲裁卷
  2310. if (!item.flag)
  2311. {
  2312. item.isArb = 0;
  2313. string bizcode = "scoring-arb";
  2314. List<string> ids = new List<string>();
  2315. foreach (CorSub sub in correct.subs)
  2316. {
  2317. ids = sub.arb;
  2318. }
  2319. //request.subs.Select(r => r.markers).ToList();
  2320. Notification notification = new Notification
  2321. {
  2322. hubName = "hita",
  2323. type = "msg",
  2324. from = $"ies5:{_option.Location}:private",
  2325. to = ids,
  2326. label = $"{bizcode}_school",
  2327. body = new { location = _option.Location, biz = bizcode, tmdid = userid, tmdname = name.ToString(), schoolcode = school, schoolname = $"{schname}", examname = correct.name, status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
  2328. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  2329. };
  2330. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  2331. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  2332. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  2333. var location = _option.Location;
  2334. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
  2335. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey(scoring.code));
  2336. return Ok(new { msg = "需要仲裁", code = 2 });
  2337. }
  2338. if (item.scores.Count > 0)
  2339. {
  2340. double sc = item.scores.Select(x => x.sc).ToList().Aggregate((i, j) => (i + j) / item.scores.Count);
  2341. scoring.scores[itemIndex] = sc;
  2342. }
  2343. string tmdId = tId.GetString();
  2344. //定位老师是几阅
  2345. int indexOfSc = 0;
  2346. foreach (Info info in item.scores)
  2347. {
  2348. if (info.tmdId.Equals(tmdId))
  2349. {
  2350. break;
  2351. }
  2352. else
  2353. {
  2354. indexOfSc++;
  2355. }
  2356. }
  2357. //判定是否已经存在对应的批注信息
  2358. bool flag = exam.mark[index][itemIndex].Exists(x => x.tmdId.Equals(tmdId));
  2359. if (flag)
  2360. {
  2361. //重复打分更新部分值
  2362. exam.mark[index][itemIndex].Where(x => x.tmdId.Equals(tmdId)).ToList().ForEach(score =>
  2363. {
  2364. score.sc = item.scores[indexOfSc].sc;
  2365. score.mark = item.scores[indexOfSc].mark;
  2366. });
  2367. }
  2368. else
  2369. {
  2370. Details dt = new()
  2371. {
  2372. index = item.scores[indexOfSc].index,
  2373. sc = item.scores[indexOfSc].sc,
  2374. tmdId = item.scores[indexOfSc].tmdId,
  2375. mark = item.scores[indexOfSc].mark,
  2376. identity = item.scores[indexOfSc].identity
  2377. };
  2378. exam.mark[index][itemIndex].Add(dt);
  2379. }
  2380. itemIndex++;
  2381. }
  2382. exam.studentScores[index] = scoring.scores;
  2383. exam.sum[index] = exam.studentScores[index].Sum();
  2384. }
  2385. }
  2386. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(exam, exam.id, new PartitionKey($"{exam.code}"));
  2387. }
  2388. }
  2389. return Ok(new { code = 200 });
  2390. }
  2391. catch (Exception ex)
  2392. {
  2393. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/sub-result\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  2394. return BadRequest();
  2395. }
  2396. }
  2397. //查询阅卷类型数据
  2398. [ProducesDefaultResponseType]
  2399. //[AuthToken(Roles = "Student")]
  2400. [HttpPost("find-scoring")]
  2401. public async Task<IActionResult> findScoring(JsonElement requert)
  2402. {
  2403. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2404. if (!requert.TryGetProperty("stuId", out JsonElement sId)) return BadRequest();
  2405. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  2406. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  2407. if (!requert.TryGetProperty("type", out JsonElement type)) return BadRequest();
  2408. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2409. var client = _azureCosmos.GetCosmosClient();
  2410. List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  2411. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  2412. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.stuId = '{sId}' and c.type = '{type}' and array_contains(c.tIds,'{tId}') ",
  2413. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  2414. {
  2415. attr.Add(item);
  2416. }
  2417. return Ok(attr);
  2418. }
  2419. //申报异常卷内容
  2420. [ProducesDefaultResponseType]
  2421. [AuthToken(Roles = "teacher,admin")]
  2422. [HttpPost("save-err")]
  2423. public async Task<IActionResult> saveErr(JsonElement requert)
  2424. {
  2425. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2426. if (!requert.TryGetProperty("err", out JsonElement err)) return BadRequest();
  2427. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2428. if (!requert.TryGetProperty("index", out JsonElement index)) return BadRequest();
  2429. if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  2430. var client = _azureCosmos.GetCosmosClient();
  2431. var (userid, name, _, school) = HttpContext.GetAuthTokenInfo();
  2432. //取得学校基本信息
  2433. var schresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school.ToString(), new PartitionKey("Base"));
  2434. string schname = string.Empty;
  2435. if (schresponse.Status == 200)
  2436. {
  2437. using var schjson = await JsonDocument.ParseAsync(schresponse.ContentStream);
  2438. schjson.RootElement.TryGetProperty("name", out JsonElement jsonschname);
  2439. schname = jsonschname.ToString();
  2440. }
  2441. SDK.Models.Cosmos.Common.Scoring scoring = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<SDK.Models.Cosmos.Common.Scoring>(id.GetString(), new PartitionKey($"Scoring-{code}"));
  2442. if (null != scoring)
  2443. {
  2444. Correct correct = null;
  2445. var cResponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(scoring.examId, new PartitionKey($"Correct-{code}"));
  2446. if (cResponse.Status == 200)
  2447. {
  2448. using var cJson = await JsonDocument.ParseAsync(cResponse.ContentStream);
  2449. correct = cJson.ToObject<Correct>();
  2450. }
  2451. if (string.IsNullOrEmpty(scoring.qs[index.GetInt32()].tId))
  2452. {
  2453. scoring.qs[index.GetInt32()].err = err.GetString();
  2454. scoring.qs[index.GetInt32()].tId = tId.GetString();
  2455. scoring.qs[index.GetInt32()].index = index.GetInt32();
  2456. }
  2457. else
  2458. {
  2459. return Ok(new { msg = "改题已经被申报", code = 404 });
  2460. }
  2461. string bizcode = "scoring-err";
  2462. List<string> ids = new List<string>();
  2463. foreach (CorSub sub in correct.subs)
  2464. {
  2465. ids = sub.err;
  2466. }
  2467. //request.subs.Select(r => r.markers).ToList();
  2468. Notification notification = new Notification
  2469. {
  2470. hubName = "hita",
  2471. type = "msg",
  2472. from = $"ies5:{_option.Location}:private",
  2473. to = ids,
  2474. label = $"{bizcode}_school",
  2475. body = new { location = _option.Location, biz = bizcode, tmdid = userid, tmdname = name.ToString(), schoolcode = school, schoolname = $"{schname}", examname = correct.name, status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
  2476. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  2477. };
  2478. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  2479. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  2480. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  2481. var location = _option.Location;
  2482. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
  2483. /* scoring.type = 2;
  2484. scoring.err = err.GetString();*/
  2485. }
  2486. else
  2487. {
  2488. return Ok(new { code = 404 });
  2489. }
  2490. var sc = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey($"{scoring.code}"));
  2491. return Ok(new { sc });
  2492. }
  2493. //处理异常卷内容
  2494. [ProducesDefaultResponseType]
  2495. //[AuthToken(Roles = "Student")]
  2496. [HttpPost("fd-err")]
  2497. public async Task<IActionResult> fdErr(JsonElement requert)
  2498. {
  2499. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2500. if (!requert.TryGetProperty("improve", out JsonElement improve)) return BadRequest();
  2501. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2502. if (!requert.TryGetProperty("index", out JsonElement index)) return BadRequest();
  2503. //if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  2504. var client = _azureCosmos.GetCosmosClient();
  2505. SDK.Models.Cosmos.Common.Scoring scoring = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<SDK.Models.Cosmos.Common.Scoring>(id.GetString(), new PartitionKey($"Scoring-{code}"));
  2506. if (null != scoring)
  2507. {
  2508. if (string.IsNullOrEmpty(scoring.qs[index.GetInt32()].improve))
  2509. {
  2510. scoring.qs[index.GetInt32()].improve = improve.GetString();
  2511. //scoring.qs[index.GetInt32()].tId = tId.GetString();
  2512. //scoring.qs[index.GetInt32()].index = index.GetInt32();
  2513. }
  2514. else
  2515. {
  2516. return Ok(new { msg = "改题已经被处理", code = 404 });
  2517. }
  2518. /* scoring.type = 2;
  2519. scoring.err = err.GetString();*/
  2520. }
  2521. else
  2522. {
  2523. return Ok(new { code = 404 });
  2524. }
  2525. var sc = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey($"{scoring.code}"));
  2526. return Ok(new { sc });
  2527. }
  2528. //处理仲裁卷内容
  2529. [ProducesDefaultResponseType]
  2530. //[AuthToken(Roles = "Student")]
  2531. [HttpPost("save-arb")]
  2532. public async Task<IActionResult> saveArb(JsonElement requert)
  2533. {
  2534. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2535. if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest();
  2536. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2537. if (!requert.TryGetProperty("index", out JsonElement indexScore)) return BadRequest();
  2538. var client = _azureCosmos.GetCosmosClient();
  2539. //List<double> scs = score.ToObject<List<double>>();
  2540. List<ExamClassResult> classResults = new();
  2541. int sin = indexScore.GetInt32();
  2542. SDK.Models.Cosmos.Common.Scoring scoring = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<SDK.Models.Cosmos.Common.Scoring>(id.GetString(), new PartitionKey($"Scoring-{code}"));
  2543. if (null != scoring)
  2544. {
  2545. scoring.scores[sin] = score.GetDouble();
  2546. scoring.items[sin].isArb = 1;
  2547. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
  2548. queryText: $"select value(c) from c where c.examId = '{scoring.examId}' and c.subjectId = '{scoring.subjectId}'",
  2549. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  2550. {
  2551. classResults.Add(item);
  2552. }
  2553. foreach (ExamClassResult exam in classResults)
  2554. {
  2555. int index = exam.studentIds.IndexOf(scoring.stuId);
  2556. if (index != -1)
  2557. {
  2558. exam.studentScores[index][sin] = score.GetDouble();
  2559. //exam.mark[index] = scoring.marks;
  2560. }
  2561. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(exam, exam.id, new PartitionKey($"{exam.code}"));
  2562. }
  2563. }
  2564. else
  2565. {
  2566. return Ok(new { code = 404 });
  2567. }
  2568. var sc = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey($"{scoring.code}"));
  2569. return Ok(new { sc });
  2570. }
  2571. //阅卷信息统计
  2572. [ProducesDefaultResponseType]
  2573. //[AuthToken(Roles = "Student")]
  2574. [HttpPost("analysis-scoring")]
  2575. public async Task<IActionResult> Analysis(JsonElement requert)
  2576. {
  2577. try
  2578. {
  2579. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2580. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2581. //if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  2582. //if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  2583. var client = _azureCosmos.GetCosmosClient();
  2584. var queryTeacher = $"select c.id,c.name from c ";
  2585. //List<object> props = new List<object>();
  2586. List<(string id, string name)> tInfos = new();
  2587. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: queryTeacher, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  2588. {
  2589. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  2590. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  2591. {
  2592. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  2593. {
  2594. tInfos.Add((obj.GetProperty("id").GetString(), obj.GetProperty("name").GetString()));
  2595. }
  2596. }
  2597. }
  2598. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
  2599. if (response.Status == 200)
  2600. {
  2601. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  2602. ExamInfo info = json.ToObject<ExamInfo>();
  2603. List<ExamClassResult> classResults = new();
  2604. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  2605. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  2606. queryText: $"select value(c) from c where c.examId = '{id}' ",
  2607. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  2608. {
  2609. attr.Add(item);
  2610. }
  2611. List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  2612. List<(string subjectId, int count)> ps = new List<(string subjectId, int count)>();
  2613. List<(string subjectId, int count)> tps = new List<(string subjectId, int count)>();
  2614. List<(string subjectId, int count)> arbs = new List<(string subjectId, int count)>();
  2615. List<(string subjectId, int count)> tarbs = new List<(string subjectId, int count)>();
  2616. List<(string subjectId, int count)> cs = new List<(string subjectId, int count)>();
  2617. foreach (ExamSubject subject in info.subjects)
  2618. {
  2619. int qsCount = 0;
  2620. int tqsCount = 0;
  2621. int arbCount = 0;
  2622. int tarbCount = 0;
  2623. int csCount = 0;
  2624. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  2625. {
  2626. if (subject.id.Equals(ss.subjectId))
  2627. {
  2628. List<Qs> qs = ss.qs.Where(s => !string.IsNullOrEmpty(s.err)).ToList();
  2629. if (qs.Count > 0)
  2630. {
  2631. qsCount++;
  2632. }
  2633. List<Qs> tqs = ss.qs.Where(s => !string.IsNullOrEmpty(s.improve)).ToList();
  2634. if (tqs.Count > 0)
  2635. {
  2636. tqsCount++;
  2637. }
  2638. List<Item> arb = ss.items.Where(s => s.flag == false).ToList();
  2639. if (arb.Count > 0)
  2640. {
  2641. arbCount++;
  2642. }
  2643. List<Item> tarb = ss.items.Where(s => s.isArb == 1 && s.flag == false).ToList();
  2644. if (tarb.Count > 0)
  2645. {
  2646. tarbCount++;
  2647. }
  2648. bool flag = ss.scores.Exists(s => s == -1);
  2649. if (!flag) csCount++;
  2650. }
  2651. }
  2652. ps.Add((subject.id, qsCount));
  2653. tps.Add((subject.id, tqsCount));
  2654. arbs.Add((subject.id, arbCount));
  2655. tarbs.Add((subject.id, tarbCount));
  2656. cs.Add((subject.id, csCount));
  2657. }
  2658. //阅卷老师
  2659. List<object> teachers = new();
  2660. Correct correct = null;
  2661. List<(string sub, List<string> ids)> errIds = new();
  2662. List<(string sub, List<string> ids)> arbIds = new();
  2663. var cResponse = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Correct-{code}"));
  2664. if (cResponse.Status == 200)
  2665. {
  2666. using var cJson = await JsonDocument.ParseAsync(cResponse.ContentStream);
  2667. correct = cJson.ToObject<Correct>();
  2668. foreach (CorSub corSub in correct.subs)
  2669. {
  2670. List<string> eName = new();
  2671. List<string> aName = new();
  2672. foreach (string s in corSub.err)
  2673. {
  2674. eName.Add(tInfos.Where(t => t.id.Equals(s)).Select(s => s.name).First());
  2675. }
  2676. foreach (string s in corSub.arb)
  2677. {
  2678. aName.Add(tInfos.Where(t => t.id.Equals(s)).Select(s => s.name).First());
  2679. }
  2680. errIds.Add((corSub.id, eName));
  2681. arbIds.Add((corSub.id, aName));
  2682. foreach (CorTmd corTmd in corSub.markers)
  2683. {
  2684. int qus = 0;
  2685. int quf = 0;
  2686. int tArbs = 0;
  2687. int fArbs = 0;
  2688. int sCount = 0;
  2689. int fCount = 0;
  2690. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  2691. {
  2692. if (ss.subjectId.Equals(corSub.id))
  2693. {
  2694. foreach (Qs qs in ss.qs)
  2695. {
  2696. if (!string.IsNullOrEmpty(qs.err) && qs.tId.Equals(corTmd.id))
  2697. {
  2698. qus++;
  2699. }
  2700. if (!string.IsNullOrEmpty(qs.improve) && qs.tId.Equals(corTmd.id))
  2701. {
  2702. quf++;
  2703. }
  2704. }
  2705. List<double> sigles = new();
  2706. foreach (Item item in ss.items)
  2707. {
  2708. if (item.scores.Exists(sc => sc.tmdId.Equals(corTmd.id)) && item.isArb == 1)
  2709. {
  2710. tArbs++;
  2711. }
  2712. if (item.flag == true && item.isArb == 1)
  2713. {
  2714. fArbs++;
  2715. }
  2716. var tsc = item.scores.Where(t => t.tmdId.Equals(corTmd.id)).Select(s => s.sc).ToList();
  2717. sigles.AddRange(tsc);
  2718. }
  2719. bool flag = sigles.Exists(s => s == -1);
  2720. if (!flag && sigles.Count == ss.items.Count)
  2721. {
  2722. fCount++;
  2723. }
  2724. sCount = corTmd.count;
  2725. }
  2726. }
  2727. var obj = new
  2728. {
  2729. sId = corSub.id,
  2730. sName = corSub.name,
  2731. name = corTmd.name,
  2732. qus,
  2733. quf,
  2734. tArbs,
  2735. fArbs,
  2736. fCount,
  2737. sCount,
  2738. };
  2739. teachers.Add(obj);
  2740. }
  2741. }
  2742. }
  2743. var sc = info.subjects.Select(s => new
  2744. {
  2745. s.name,
  2746. count = info.stuCount,
  2747. num = info.stuCount * correct.num,
  2748. tqs = tps.Where(p => p.subjectId.Equals(s.id)).Select(c => c.count).First(),
  2749. qs = ps.Where(p => p.subjectId.Equals(s.id)).Select(c => c.count).First(),
  2750. errName = errIds.Where(q => q.sub.Equals(s.id)).Select(c => c.ids).FirstOrDefault(),
  2751. tarbs = tarbs.Where(p => p.subjectId.Equals(s.id)).Select(c => c.count).First(),
  2752. arbs = arbs.Where(p => p.subjectId.Equals(s.id)).Select(c => c.count).First(),
  2753. arbName = arbIds.Where(q => q.sub.Equals(s.id)).Select(c => c.ids).FirstOrDefault(),
  2754. cs = cs.Where(p => p.subjectId.Equals(s.id)).Select(c => c.count).First()
  2755. }); ;
  2756. return Ok(new { sc, teachers });
  2757. }
  2758. else
  2759. {
  2760. return BadRequest();
  2761. }
  2762. }
  2763. catch (Exception ex)
  2764. {
  2765. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/analysis-scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  2766. return BadRequest();
  2767. }
  2768. }
  2769. /*private async Task deleteAsync(CosmosClient client, string id, string tId)
  2770. {
  2771. List<string> correctIds = new List<string>();
  2772. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.cid = '{id}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CorrectTask-{tId}") }))
  2773. {
  2774. using var jsonTask = await JsonDocument.ParseAsync(item.ContentStream);
  2775. if (jsonTask.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  2776. {
  2777. var accounts = jsonTask.RootElement.GetProperty("Documents").EnumerateArray();
  2778. while (accounts.MoveNext())
  2779. {
  2780. JsonElement account = accounts.Current;
  2781. correctIds.Add(account.GetProperty("id").GetString());
  2782. }
  2783. }
  2784. }
  2785. if (correctIds.Count > 0)
  2786. {
  2787. await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemsStreamAsync(correctIds, $"CorrectTask-{tId}");
  2788. }
  2789. }*/
  2790. private async Task<(string blob, List<double>)> getMoreStuInfo(CosmosClient client, string stuId, string examId, string subjectId, string code)
  2791. {
  2792. var queryClass = $"select c.studentAnswers,c.studentIds,c.studentScores from c where array_contains(c.studentIds,'{stuId}') and c.examId = '{examId}' and c.subjectId = '{subjectId}'";
  2793. List<List<string>> ans = new List<List<string>>();
  2794. List<string> ids = new List<string>();
  2795. List<List<double>> scs = new List<List<double>>();
  2796. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  2797. {
  2798. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  2799. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  2800. {
  2801. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  2802. while (accounts.MoveNext())
  2803. {
  2804. JsonElement account = accounts.Current;
  2805. ans = account.GetProperty("studentAnswers").ToObject<List<List<string>>>();
  2806. ids = account.GetProperty("studentIds").ToObject<List<string>>();
  2807. scs = account.GetProperty("studentScores").ToObject<List<List<double>>>();
  2808. }
  2809. }
  2810. }
  2811. int num = ids.IndexOf(stuId);
  2812. string ansBlob = "";
  2813. List<double> scores = new List<double>();
  2814. if (num >= 0)
  2815. {
  2816. if (ans[num].Count > 0)
  2817. {
  2818. ansBlob = ans[num].First();
  2819. }
  2820. scores = scs[num];
  2821. }
  2822. return (ansBlob, scores);
  2823. }
  2824. }
  2825. }