ExamController.cs 128 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Dynamic;
  8. using System.IdentityModel.Tokens.Jwt;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Text.Json;
  13. using System.Threading.Tasks;
  14. using TEAMModelOS.Models;
  15. using TEAMModelOS.SDK.Models;
  16. using TEAMModelOS.SDK;
  17. using TEAMModelOS.SDK.Context.Constant.Common;
  18. using TEAMModelOS.SDK.DI;
  19. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  20. using TEAMModelOS.SDK.Extension;
  21. using TEAMModelOS.SDK;
  22. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  23. using TEAMModelOS.SDK.Models.Cosmos.Common;
  24. using TEAMModelOS.SDK.Models.Table;
  25. using Azure.Messaging.ServiceBus;
  26. using Microsoft.Extensions.Configuration;
  27. using TEAMModelOS.Filter;
  28. using TEAMModelOS.SDK.Models.Service;
  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. public ExamController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
  47. IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
  48. {
  49. _azureCosmos = azureCosmos;
  50. _serviceBus = serviceBus;
  51. _snowflakeId = snowflakeId;
  52. _dingDing = dingDing;
  53. _option = option?.Value;
  54. _azureStorage = azureStorage;
  55. _azureRedis = azureRedis;
  56. _configuration = configuration;
  57. }
  58. /// <summary>
  59. /// 保存考试信息
  60. /// </summary>
  61. /// <param name="request"></param>
  62. /// <returns></returns>
  63. [ProducesDefaultResponseType]
  64. [AuthToken(Roles = "teacher,admin")]
  65. [HttpPost("save")]
  66. public async Task<IActionResult> Save(ExamInfo request)
  67. {
  68. try
  69. {
  70. //新增
  71. //string code = request.code;
  72. var client = _azureCosmos.GetCosmosClient();
  73. ExamInfo exam;
  74. string code = request.code;
  75. request.ttl = -1;
  76. request.code = "Exam-" + request.code;
  77. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  78. request.createTime = now;
  79. if (request.startTime <= 0)
  80. {
  81. request.startTime = now;
  82. }
  83. //查询所有学生名单
  84. List<string> sids = new List<string>();
  85. //List<Student> students = new List<Student>();
  86. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{request.school}") }))
  87. {
  88. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  89. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  90. {
  91. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  92. while (accounts.MoveNext())
  93. {
  94. JsonElement account = accounts.Current;
  95. sids.Add(account.GetProperty("id").GetString());
  96. }
  97. }
  98. }
  99. int stuCount = 0;
  100. List<string> classes = ExamService.getClasses(request.classes,request.stuLists);
  101. for (int i = 0; i < classes.Count; i++)
  102. {
  103. List<string> ids = new List<string>();
  104. //处理班级人数(公共部分的校本名单)
  105. //List<Student> students = new List<Student>();
  106. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.classId = '{classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{request.school}") }))
  107. {
  108. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  109. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  110. {
  111. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  112. while (accounts.MoveNext())
  113. {
  114. JsonElement account = accounts.Current;
  115. ids.Add(account.GetProperty("id").GetString());
  116. }
  117. }
  118. }
  119. if (request.scope.Equals("private"))
  120. {
  121. //处理发布对象为自选名单(个人)
  122. List<StuList> stuLists = new List<StuList>();
  123. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<StuList>(queryText: $"select value(c) from c where c.id = '{classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList") }))
  124. {
  125. stuLists.Add(item);
  126. }
  127. if (stuLists.Count > 0)
  128. {
  129. foreach (StuList stuList in stuLists)
  130. {
  131. /*int index = 0;
  132. foreach (Students stus in stuList.students)
  133. {
  134. if (sids.Contains(stus.id))
  135. {
  136. if (!ids.Contains(stus.id))
  137. {
  138. ids.Add(stus.id);
  139. }
  140. }
  141. else {
  142. stuList.students.RemoveAt(index);
  143. }
  144. index++;
  145. }*/
  146. for (int j = 0; j < stuList.students.Count; j++) {
  147. if (sids.Contains(stuList.students[j].id))
  148. {
  149. if (!ids.Contains(stuList.students[j].id))
  150. {
  151. ids.Add(stuList.students[j].id);
  152. }
  153. }
  154. else
  155. {
  156. stuList.students.RemoveAt(j);
  157. }
  158. }
  159. if (stuList.tmids.Count > 0)
  160. {
  161. foreach (string tid in stuList.tmids)
  162. {
  163. ids.Add(tid);
  164. }
  165. }
  166. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(stuList, stuList.id, new PartitionKey(stuList.code));
  167. }
  168. }
  169. }
  170. else
  171. {
  172. //request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  173. //发布对象为自选名单(校本)
  174. List<StuList> stuLists = new List<StuList>();
  175. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<StuList>(queryText: $"select value(c) from c where c.id = '{classes[i]}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList-{request.school}") }))
  176. {
  177. stuLists.Add(item);
  178. }
  179. if (stuLists.Count > 0)
  180. {
  181. foreach (StuList stuList in stuLists)
  182. {
  183. for (int j = 0; j < stuList.students.Count; j++)
  184. {
  185. if (sids.Contains(stuList.students[j].id))
  186. {
  187. if (!ids.Contains(stuList.students[j].id))
  188. {
  189. ids.Add(stuList.students[j].id);
  190. }
  191. }
  192. else
  193. {
  194. stuList.students.RemoveAt(j);
  195. }
  196. }
  197. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync(stuList, stuList.id, new PartitionKey(stuList.code));
  198. }
  199. }
  200. }
  201. stuCount += ids.Count;
  202. }
  203. request.stuCount = stuCount;
  204. if (string.IsNullOrEmpty(request.id))
  205. {
  206. request.id = Guid.NewGuid().ToString();
  207. if (request.startTime > now)
  208. {
  209. request.progress = "pending";
  210. }
  211. else
  212. {
  213. request.progress = "going";
  214. }
  215. var messageBlob = new ServiceBusMessage();
  216. if (request.scope.Equals("school"))
  217. {
  218. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  219. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"exam/{request.id}", name = request.school }.ToJsonString());
  220. }
  221. else
  222. {
  223. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"exam/{request.id}");
  224. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"exam/{request.id}", name = request.creatorId }.ToJsonString());
  225. }
  226. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  227. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  228. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  229. int n = 0;
  230. List<string> sheetIds = new List<string>();
  231. foreach (PaperSimple simple in request.papers)
  232. {
  233. simple.blob =$"/exam/{request.id}/paper/{request.subjects[n].id}";
  234. n++;
  235. simple.sheet = null;
  236. }
  237. exam = await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  238. }
  239. else
  240. {
  241. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(request.id, new PartitionKey($"{request.code}"));
  242. if (info.progress.Equals("going"))
  243. {
  244. return Ok(new { v = "活动正在进行中" });
  245. }
  246. var messageBlob = new ServiceBusMessage();
  247. if (request.scope.Equals("school"))
  248. {
  249. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"exam/{request.id}");
  250. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"exam/{request.id}", name = request.school }.ToJsonString());
  251. }
  252. else
  253. {
  254. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"exam/{request.id}");
  255. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"exam/{request.id}", name = request.creatorId }.ToJsonString());
  256. }
  257. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  258. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  259. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  260. request.progress = info.progress;
  261. int n = 0;
  262. foreach (PaperSimple simple in request.papers)
  263. {
  264. simple.blob = "/exam/" + request.id + "/paper/" + request.subjects[n].id;
  265. n++;
  266. }
  267. exam = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(request, request.id, new PartitionKey($"{request.code}"));
  268. }
  269. return Ok(new { exam });
  270. }
  271. catch (Exception ex)
  272. {
  273. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/save()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  274. return BadRequest();
  275. }
  276. }
  277. //TODO blob 批量删除
  278. /// <summary>
  279. /// 删除
  280. /// </summary>
  281. /// <param name="request"></param>
  282. /// <returns></returns>
  283. [ProducesDefaultResponseType]
  284. //[AuthToken(Roles = "Teacher")]
  285. [HttpPost("delete")]
  286. public async Task<IActionResult> Delete(JsonElement request)
  287. {
  288. /* ResponseBuilder builder = ResponseBuilder.custom();
  289. IdPk items = await _azureCosmos.DeleteAsync<ExamInfo>(request.id, request.pk);
  290. await _azureCosmos.DeleteAll<Paper>(new Dictionary<string, object>() { { "code", request.id } });
  291. return builder.Data(items).build();*/
  292. try
  293. {
  294. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  295. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  296. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  297. var client = _azureCosmos.GetCosmosClient();
  298. //string school_code = code.ToString().Substring(typeof(ExamClassResult).Name.Length + 1);
  299. var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
  300. //删除blob 相关资料
  301. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, code.ToString(), new List<string> { $"exam/{id}" });
  302. //通知评测删除信息
  303. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"exam/{id}", name = $"{code}" }.ToJsonString());
  304. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  305. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  306. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  307. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  308. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(queryText: $"select c.id from c where c.examId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  309. {
  310. examClassResults.Add(item);
  311. }
  312. List<string> resultIds = new List<string>();
  313. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
  314. {
  315. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  316. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  317. {
  318. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  319. while (accounts.MoveNext())
  320. {
  321. JsonElement account = accounts.Current;
  322. resultIds.Add(account.GetProperty("id").GetString());
  323. }
  324. }
  325. }
  326. foreach (ExamClassResult classResult in examClassResults)
  327. {
  328. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(classResult.id, new PartitionKey($"ExamClassResult-{code}"));
  329. }
  330. await client.GetContainer("TEAMModelOS", "Common").DeleteItemsStreamAsync(resultIds, $"ExamResult-{id}");
  331. /*foreach (ExamResult result in results)
  332. {
  333. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(result.id, new PartitionKey($"ExamResult-{id}"));
  334. }*/
  335. //await _azureCosmos.DeleteAll(examClassResults);
  336. return Ok(new { id });
  337. }
  338. catch (Exception e)
  339. {
  340. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/delete()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  341. return BadRequest();
  342. }
  343. }
  344. /// <summary>
  345. /// 查询考试信息
  346. /// </summary>
  347. /// <param name="request"></param>
  348. /// <returns></returns>
  349. [ProducesDefaultResponseType]
  350. //[AuthToken(Roles = "Teacher")]
  351. [HttpPost("find")]
  352. public async Task<IActionResult> Find(JsonElement requert)
  353. {
  354. try
  355. {
  356. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  357. var client = _azureCosmos.GetCosmosClient();
  358. List<SchoolYear> years = await _azureStorage.FindListByDict<SchoolYear>(new Dictionary<string, object>() { { "RowKey", code }, { "PartitionKey", "Exam" } });
  359. int year = 0;
  360. if (years.Count > 0)
  361. {
  362. year = years[0].year;
  363. }
  364. else
  365. {
  366. long ct = 0;
  367. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: "SELECT top 1 c.createTime FROM c order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
  368. {
  369. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  370. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  371. {
  372. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  373. while (accounts.MoveNext())
  374. {
  375. JsonElement account = accounts.Current;
  376. ct = account.GetProperty("createTime").GetInt64();
  377. }
  378. }
  379. }
  380. year = DateTimeOffset.FromUnixTimeMilliseconds(ct).Year;
  381. SchoolYear sy = new()
  382. {
  383. RowKey = code.ToString(),
  384. PartitionKey = "Exam",
  385. year = year
  386. };
  387. await _azureStorage.Save<SchoolYear>(sy);
  388. }
  389. 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 ";
  390. if (requert.TryGetProperty("classIds", out JsonElement classIds))
  391. {
  392. List<string> ids = classIds.ToObject<List<string>>();
  393. HashSet<string> strs = new HashSet<string>();
  394. if (ids.Count > 1)
  395. {
  396. foreach (string id in ids)
  397. {
  398. strs.Add($"array_contains(c.classes,'{id}')");
  399. }
  400. }
  401. else
  402. {
  403. string ssr = ids.Count > 0 ? ids[0] : "";
  404. strs.Add($"array_contains(c.classes,'{ssr}')");
  405. }
  406. string ss = string.Join(" or ", strs);
  407. 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})";
  408. };
  409. string continuationToken = string.Empty;
  410. string token = default;
  411. //是否需要进行分页查询,默认不分页
  412. bool iscontinuation = false;
  413. if (requert.TryGetProperty("token", out JsonElement token_1))
  414. {
  415. token = token_1.GetString();
  416. iscontinuation = true;
  417. };
  418. //默认不指定返回大小
  419. int? topcout = null;
  420. if (requert.TryGetProperty("count", out JsonElement jcount))
  421. {
  422. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  423. {
  424. topcout = data;
  425. }
  426. }
  427. List<ExamInfo> examInfo = new List<ExamInfo>();
  428. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Exam-{code}") }))
  429. {
  430. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  431. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  432. {
  433. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  434. {
  435. //obj.TryGetProperty("progress", out JsonElement progress);
  436. examInfo.Add(obj.ToObject<ExamInfo>());
  437. }
  438. }
  439. if (iscontinuation)
  440. {
  441. continuationToken = item.GetContinuationToken();
  442. break;
  443. }
  444. }
  445. //List<string> examIds = new List<string>();
  446. /* List<ExamResult> examResults = new List<ExamResult>();
  447. foreach (ExamInfo info in examInfos) {
  448. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamResult>(
  449. queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{info.id}") }))
  450. {
  451. examResults.Add(item);
  452. }
  453. }*/
  454. /* List<(string id, double scores)> listExamInfo = new List<(string id, double scores)>();
  455. foreach (ExamInfo info in examInfos)
  456. {
  457. //记录某次考试所有学生得分总分
  458. double score = 0;
  459. double allScore = 0;
  460. int stuCount = 0;
  461. foreach (ExamResult examResult in examResults) {
  462. if (info.id == examResult.examId) {
  463. foreach (List<double> sc in examResult.studentScores) {
  464. score += sc.Sum();
  465. }
  466. stuCount = examResult.studentIds.Count;
  467. }
  468. }
  469. double ascore = stuCount > 0 ? Math.Round(score * 0.1 / stuCount, 2) : 0;
  470. foreach (PaperSimple simple in info.papers) {
  471. allScore += simple.point.Sum();
  472. }
  473. listExamInfo.Add((info.id, (allScore> 0 ? ascore / allScore * 100: 0)));
  474. }
  475. var examInfo = examInfos.Select(o =>
  476. new
  477. {
  478. o.id,
  479. o.scope,
  480. o.stuCount,
  481. o.name,
  482. o.period,
  483. o.startTime,
  484. o.endTime,
  485. o.type,
  486. o.progress,
  487. o.examType,
  488. o.createTime,
  489. o.subjects,
  490. o.grades,
  491. o.classes,
  492. score = listExamInfo.FirstOrDefault(c => c.id == o.id).scores,
  493. }
  494. );*/
  495. return Ok(new { examInfo, token = continuationToken, year });
  496. }
  497. catch (Exception e)
  498. {
  499. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  500. return BadRequest();
  501. }
  502. }
  503. [ProducesDefaultResponseType]
  504. //[AuthToken(Roles = "Teacher")]
  505. [HttpPost("find-summary")]
  506. public async Task<IActionResult> FindSummary(JsonElement requert)
  507. {
  508. try
  509. {
  510. //ResponseBuilder builder = ResponseBuilder.custom();
  511. //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
  512. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  513. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  514. //if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  515. //var jwt = new JwtSecurityToken(id_token.GetString());
  516. //if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
  517. //var id = jwt.Payload.Sub;
  518. var client = _azureCosmos.GetCosmosClient();
  519. List<ExamInfo> examInfo = new List<ExamInfo>();
  520. //var query = $"select value(c) from c ";
  521. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
  522. {
  523. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  524. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  525. {
  526. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  527. {
  528. //obj.TryGetProperty("progress", out JsonElement progress);
  529. examInfo.Add(obj.ToObject<ExamInfo>());
  530. }
  531. }
  532. }
  533. return Ok(new { examInfo });
  534. }
  535. catch (Exception e)
  536. {
  537. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  538. return BadRequest();
  539. }
  540. }
  541. /// <summary>
  542. /// 学生回答问题
  543. /// </summary>
  544. /// <param name="request"></param>
  545. /// <returns></returns>
  546. [ProducesDefaultResponseType]
  547. //[AuthToken(Roles = "Teacher")]
  548. [HttpPost("upsert-record")]
  549. public async Task<IActionResult> upsertRecord(JsonElement request)
  550. {
  551. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  552. //if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  553. if (!request.TryGetProperty("answer", out JsonElement answer)) return BadRequest();
  554. if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  555. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  556. //if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  557. if (!request.TryGetProperty("multipleRule", out JsonElement multipleRule)) return BadRequest();
  558. //if (!request.TryGetProperty("answers ", out JsonElement tandardAnswer)) return BadRequest();
  559. if (!request.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
  560. //根据不同评测的类型返回对应的编码
  561. if (!request.TryGetProperty("code", out JsonElement school)) return BadRequest();
  562. if (!request.TryGetProperty("scode", out JsonElement scode)) return BadRequest();
  563. try
  564. {
  565. //List<string> ids = new List<string>();
  566. //ids = classId.ToObject<List<string>>();
  567. var client = _azureCosmos.GetCosmosClient();
  568. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  569. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
  570. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and array_contains(c.studentIds,'{studentId}')",
  571. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  572. {
  573. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  574. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  575. {
  576. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  577. {
  578. examClassResults.Add(obj.ToObject<ExamClassResult>());
  579. }
  580. }
  581. }
  582. ExamClassResult classResult = new ExamClassResult();
  583. List<PaperSimple> standerAnswers = new List<PaperSimple>();
  584. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
  585. queryText: $"select A0.point,A0.answers from c join A0 in c.papers where c.id = '{id}'and A0.id = '{paperId}'",
  586. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  587. {
  588. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  589. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  590. {
  591. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  592. {
  593. standerAnswers.Add(obj.ToObject<PaperSimple>());
  594. }
  595. }
  596. }
  597. List<List<string>> ans = answer.ToObject<List<List<string>>>();
  598. List<List<string>> standard = new List<List<string>>();
  599. List<double> points = new List<double>();
  600. int rule = int.Parse(multipleRule.ToString());
  601. foreach (PaperSimple simple in standerAnswers)
  602. {
  603. standard = simple.answers;
  604. points = simple.point;
  605. }
  606. List<Task<string>> tasks = new List<Task<string>>();
  607. foreach (ExamClassResult result in examClassResults)
  608. {
  609. int index = result.studentIds.IndexOf(studentId.ToString());
  610. //存放客观题作答详情
  611. if (result.ans.Count == 0)
  612. {
  613. foreach (string cc in result.studentIds)
  614. {
  615. List<List<string>> anc = new List<List<string>>();
  616. foreach (List<string> opc in standard)
  617. {
  618. anc.Add(new List<string>());
  619. }
  620. result.ans.Add(anc);
  621. }
  622. }
  623. //List<List<string>> oq = new List<List<string>>();
  624. //classResult.studentAnswers[index] = ans;
  625. if (index == -1)
  626. {
  627. List<double> ansPoint = new List<double>();
  628. foreach (List<string> num in standard)
  629. {
  630. //ans.Add(new List<string>());
  631. ansPoint.Add(-1);
  632. }
  633. result.studentIds.Add(studentId.ToString());
  634. result.studentScores.Add(ansPoint);
  635. result.studentAnswers.Add(new List<string>());
  636. result.sum.Add(0);
  637. }
  638. //int flagCount = 0;
  639. /*foreach (List<string> str in ans) {
  640. if (str.Count == 0) {
  641. flagCount++;
  642. }
  643. } */
  644. int newIndex = result.studentIds.IndexOf(studentId.ToString());
  645. /* if (flagCount != standard.Count)
  646. {*/
  647. StringBuilder builder = new StringBuilder();
  648. builder.Append(result.examId).Append("/");
  649. builder.Append(result.subjectId).Append("/");
  650. builder.Append(studentId).Append("/");
  651. builder.Append("ans.json");
  652. /*string FileName = result.examId + "/" + result.subjectId + "/" + studentId;
  653. string blob = FileName + "/" + "ans.json";*/
  654. tasks.Add(_azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", builder.ToString(), false));
  655. result.studentAnswers[newIndex].Add(builder.ToString());
  656. //}
  657. //List<(int index ,string content, double count)> acount = new List<(int index,string content, double count)>();
  658. for (int i = 0; i < ans.Count; i++)
  659. {
  660. //List<string> op = new List<string>();
  661. var ac = ans[i].Count;
  662. var sc = standard[i].Count;
  663. //记录次数
  664. int n = 0;
  665. //result.studentAnswers[index][i] = ans[i];
  666. //算分处理
  667. if (sc > 0)
  668. {
  669. result.ans[index][i] = ans[i];
  670. if (ac == sc && sc == 1)
  671. {
  672. foreach (string right in ans[i])
  673. {
  674. if (standard[i].Contains(right))
  675. {
  676. result.studentScores[newIndex][i] = points[i];
  677. }
  678. else
  679. {
  680. result.studentScores[newIndex][i] = 0;
  681. }
  682. }
  683. }
  684. else
  685. {
  686. if (rule > 0)
  687. {
  688. int falseCount = 0;
  689. if (ac > 0)
  690. {
  691. foreach (string obj in ans[i])
  692. {
  693. if (!standard[i].Contains(obj))
  694. {
  695. falseCount++;
  696. }
  697. }
  698. switch (rule)
  699. {
  700. case 1:
  701. if (ac == sc)
  702. {
  703. if (falseCount == 0)
  704. {
  705. result.studentScores[newIndex][i] = points[i];
  706. }
  707. else
  708. {
  709. result.studentScores[newIndex][i] = 0;
  710. }
  711. }
  712. else
  713. {
  714. result.studentScores[newIndex][i] = 0;
  715. }
  716. break;
  717. case 2:
  718. if (falseCount > 0)
  719. {
  720. result.studentScores[newIndex][i] = 0;
  721. }
  722. else
  723. {
  724. if (ac == sc)
  725. {
  726. result.studentScores[newIndex][i] = points[i];
  727. }
  728. else
  729. {
  730. result.studentScores[newIndex][i] = points[i] / 2;
  731. }
  732. }
  733. break;
  734. case 3:
  735. if (falseCount > 0)
  736. {
  737. result.studentScores[newIndex][i] = 0;
  738. }
  739. else
  740. {
  741. if (ac == sc)
  742. {
  743. result.studentScores[newIndex][i] = points[i];
  744. }
  745. else
  746. {
  747. result.studentScores[newIndex][i] = System.Math.Round((double)ac / sc * points[i], 1);
  748. }
  749. }
  750. break;
  751. case 4:
  752. if (ac == sc)
  753. {
  754. result.studentScores[newIndex][i] = points[i];
  755. }
  756. else
  757. {
  758. double persent = (double)(sc - 2 * falseCount) / sc;
  759. if (persent <= 0)
  760. {
  761. result.studentScores[newIndex][i] = 0;
  762. }
  763. else
  764. {
  765. result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
  766. }
  767. }
  768. break;
  769. }
  770. }
  771. else
  772. {
  773. result.studentScores[newIndex][i] = 0;
  774. }
  775. }
  776. }
  777. }
  778. }
  779. /*if (result.studentScores.Contains(-1)) {
  780. }*/
  781. bool flag = true;
  782. foreach (List<double> scores in result.studentScores)
  783. {
  784. foreach (double score in scores)
  785. {
  786. if (score == -1)
  787. {
  788. flag = false;
  789. break;
  790. }
  791. }
  792. }
  793. if (flag)
  794. {
  795. ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{scode}"));
  796. result.progress = true;
  797. /*//标记单科单班总得分
  798. double score = 0;
  799. //标准差
  800. double powSum = 0;
  801. var scount = result.studentIds.Count;
  802. foreach (List<double> sc in result.studentScores) {
  803. score += sc.Sum();
  804. }
  805. foreach (string sid in result.studentIds) {
  806. double ssc = result.studentScores[result.studentIds.IndexOf(sid)].Sum();
  807. powSum += Math.Pow(ssc - scount > 0 ? Math.Round(score * 1.0 / scount, 2) : 0, 2);
  808. }
  809. result.standard = Math.Round(scount > 0 ? Math.Pow(powSum / scount, 0.5) : 0, 2);
  810. result.average = scount > 0 ? Math.Round(score / scount, 2) : 0;*/
  811. exam.subjects.ForEach(s =>
  812. {
  813. if (s.id.Equals(subjectId.ToString()))
  814. {
  815. s.classCount += 1;
  816. }
  817. });
  818. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"{scode}"));
  819. }
  820. result.sum[newIndex] = result.studentScores[newIndex].Sum();
  821. classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  822. }
  823. await Task.WhenAll(tasks);
  824. return Ok(new { classResult });
  825. }
  826. catch (Exception e)
  827. {
  828. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertRecord()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  829. return BadRequest();
  830. }
  831. }
  832. [ProducesDefaultResponseType]
  833. //[AuthToken(Roles = "Teacher")]
  834. [HttpPost("upsert-record-by-teacher")]
  835. public async Task<IActionResult> upsertRecordByTeacher(JsonElement request)
  836. {
  837. //ResponseBuilder builder = ResponseBuilder.custom();
  838. try
  839. {
  840. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  841. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  842. if (!request.TryGetProperty("point", out JsonElement point)) return BadRequest();
  843. if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  844. //if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  845. //此参数表明此次操作对象为个人还是校本的评测内容
  846. if (!request.TryGetProperty("school", out JsonElement school)) return BadRequest();
  847. if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  848. //要先处理状态,判断卷子是否存在,并判断卷子归属的考试是否允许再次提交
  849. //List<ExamInfo> exams = await _azureCosmos.FindByDict<ExamInfo>(new Dictionary<string, object> { { "id", request.examCode } });
  850. List<double> ans = point.ToObject<List<double>>();
  851. var client = _azureCosmos.GetCosmosClient();
  852. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  853. if (request.TryGetProperty("classId", out JsonElement classId))
  854. {
  855. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  856. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
  857. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  858. {
  859. examClassResults.Add(item);
  860. }
  861. }
  862. else
  863. {
  864. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  865. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and array_contains(c.studentIds,'{studentId}')",
  866. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  867. {
  868. examClassResults.Add(item);
  869. }
  870. }
  871. ExamClassResult classResult = new ExamClassResult();
  872. //ExamInfo classResult = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{code}"));
  873. //ExamClassResult classResult = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamClassResult>(id.ToString(), new PartitionKey($"{code}"));
  874. /*foreach (double index in ans) {
  875. classResult.studentScores.in
  876. }*/
  877. foreach (ExamClassResult result in examClassResults)
  878. {
  879. int index = result.studentIds.IndexOf(studentId.ToString());
  880. for (int i = 0; i < ans.Count; i++)
  881. {
  882. result.studentScores[index][i] = ans[i];
  883. }
  884. if (!result.progress)
  885. {
  886. bool flag = true;
  887. foreach (List<double> scores in result.studentScores)
  888. {
  889. foreach (double score in scores)
  890. {
  891. if (score == -1)
  892. {
  893. flag = false;
  894. break;
  895. }
  896. }
  897. }
  898. if (flag)
  899. {
  900. ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  901. result.progress = true;
  902. exam.subjects.ForEach(s =>
  903. {
  904. if (s.id.Equals(subjectId.ToString()))
  905. {
  906. s.classCount += 1;
  907. }
  908. });
  909. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{code}"));
  910. }
  911. }
  912. else
  913. {
  914. ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  915. exam.updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  916. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{code}"));
  917. }
  918. result.sum[index] = result.studentScores[index].Sum();
  919. classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
  920. }
  921. return Ok(new { classResult });
  922. }
  923. catch (Exception ex)
  924. {
  925. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertRecordByTeacher()\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  926. return BadRequest();
  927. }
  928. /*if (exams.IsNotEmpty())
  929. {
  930. ExamInfo examInfo = exams[0];
  931. //提交答案时间必须是状态已发布,且时间在起止时间内
  932. if (examInfo.startTime <= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() && examInfo.status == 200 &&
  933. examInfo.endTime >= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
  934. {
  935. return builder.Data(await _azureCosmos.SaveOrUpdate(request)).build();
  936. }
  937. else
  938. {
  939. return builder.Error(ResponseCode.FAILED, "请在作答时间段内提交答案!").build();
  940. }
  941. }
  942. else
  943. {
  944. return builder.Error(ResponseCode.DATA_EXIST, "考试不存在!").build();
  945. }*/
  946. }
  947. /// <summary>
  948. /// 查询评测详细信息(教师或者学生通用)
  949. /// </summary>
  950. /// <param name="request"></param>
  951. /// <returns></returns>
  952. [ProducesDefaultResponseType]
  953. //[AuthToken(Roles = "Teacher")]
  954. [HttpPost("find-summary-record")]
  955. public async Task<IActionResult> findSummaryRecord(JsonElement requert)
  956. {
  957. //var (id, school) = HttpContext.GetAuthTokenInfo();
  958. try
  959. {
  960. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  961. //if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
  962. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  963. if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
  964. if (!requert.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  965. // 如果只有学生id则返回学生参加过的考试 只返回相关摘要信息
  966. var client = _azureCosmos.GetCosmosClient();
  967. //string code = school_code.ToString().Substring(5);
  968. //ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{school_code}"));
  969. List<object> examClassResults = new List<object>();
  970. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id, c.code,c.info,c.studentIds,c.studentAnswers,c.studentScores,c.mark from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
  971. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school_code}") }))
  972. {
  973. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  974. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  975. {
  976. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  977. {
  978. examClassResults.Add(obj.ToObject<object>());
  979. }
  980. }
  981. }
  982. /*if (StringHelper.getKeyCount(requert) == 1 && requert.TryGetProperty("code", out JsonElement code))
  983. {
  984. List<object> props = new List<object>();
  985. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.code, c.examCode, c.status ,c.mark, c.score from c where c.id = {id}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamRecord-{school_code}") }))
  986. {
  987. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  988. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  989. {
  990. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  991. {
  992. props.Add(obj.ToObject<object>());
  993. }
  994. }
  995. }
  996. return Ok(new { props });
  997. }
  998. else
  999. {
  1000. if (requert.TryGetProperty("examCode", out JsonElement _))
  1001. {
  1002. //List<string> props = new List<string> { "id", "code", "examCode", "status", "mark", "score" };
  1003. //List<ExamRecord> examRecords = await _azureCosmos.FindByDict<ExamRecord>(request, props);
  1004. //return builder.Data(examRecords).Extend(new Dictionary<string, object> { { "props", props } }).build();
  1005. List<object> props = new List<object>();
  1006. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.code, c.examCode, c.status ,c.mark, c.score from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamRecord-{school_code}") }))
  1007. {
  1008. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1009. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1010. {
  1011. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1012. {
  1013. props.Add(obj.ToObject<object>());
  1014. }
  1015. }
  1016. }
  1017. return Ok(new { props });
  1018. }
  1019. }*/
  1020. return Ok(new { examClassResults });
  1021. }
  1022. catch (Exception ex)
  1023. {
  1024. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findSummaryRecord()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1025. return BadRequest();
  1026. }
  1027. }
  1028. //学生端查询评测列表
  1029. [ProducesDefaultResponseType]
  1030. //[AuthToken(Roles = "Student")]
  1031. [HttpPost("find-summary-by-student")]
  1032. public async Task<IActionResult> findSummaryStudent(JsonElement requert)
  1033. {
  1034. //ResponseBuilder builder = ResponseBuilder.custom();
  1035. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1036. try
  1037. {
  1038. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1039. //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1040. if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  1041. if (!requert.TryGetProperty("code", out JsonElement school)) return BadRequest();
  1042. if (!requert.TryGetProperty("scode", out JsonElement scode)) return BadRequest();
  1043. var client = _azureCosmos.GetCosmosClient();
  1044. var query = $"select c.id,c.code,c.school,c.creatorId,c.progress,A0.id paperId,A0.code paperCode,A0.name paperName,A0.multipleRule,A0.scope,A0.blob from c join A0 in c.papers where c.id ='{id}'";
  1045. List<object> papers = new List<object>();
  1046. List<object> subjects = new List<object>();
  1047. List<string> classIds = new List<string>();
  1048. //存放当前学生所在班级ID或者名单ID
  1049. HashSet<string> resultIds = new HashSet<string>();
  1050. //List<string> ids = new List<string>();
  1051. //处理班级人数(公共部分的校本名单)
  1052. //List<Student> students = new List<Student>();
  1053. await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.classId id from c where c.id = '{studentId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{school}") }))
  1054. {
  1055. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1056. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1057. {
  1058. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1059. while (accounts.MoveNext())
  1060. {
  1061. JsonElement account = accounts.Current;
  1062. resultIds.Add(account.GetProperty("id").GetString());
  1063. }
  1064. }
  1065. }
  1066. //获取自定义名单信息
  1067. List<StuList> stuLists = new List<StuList>();
  1068. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<StuList>(queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}'",
  1069. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList") }))
  1070. {
  1071. stuLists.Add(item);
  1072. }
  1073. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<StuList>(queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}'",
  1074. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StuList-{school}") }))
  1075. {
  1076. stuLists.Add(item);
  1077. }
  1078. if (stuLists.Count > 0)
  1079. {
  1080. foreach (StuList stuList in stuLists)
  1081. {
  1082. resultIds.Add(stuList.id);
  1083. }
  1084. }
  1085. var queryClassId = $"select c.classes id from c where c.id ='{id}'";
  1086. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryClassId, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1087. {
  1088. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1089. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1090. {
  1091. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1092. {
  1093. classIds = obj.GetProperty("id").ToObject<List<string>>();
  1094. //classIds = obj.ToObject<List<string>>();
  1095. }
  1096. }
  1097. }
  1098. //存放该学生所在班级参与当前评测的ID
  1099. List<string> infoIds = new List<string>();
  1100. foreach (string ids in resultIds)
  1101. {
  1102. if (classIds.Contains(ids))
  1103. {
  1104. infoIds.Add(ids);
  1105. }
  1106. }
  1107. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1108. {
  1109. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1110. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1111. {
  1112. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1113. {
  1114. papers.Add(obj.ToObject<object>());
  1115. }
  1116. }
  1117. }
  1118. var querySubject = $"select A0.id,A0.name from c join A0 in c.subjects where c.id ='{id}'";
  1119. //List<object> props = new List<object>();
  1120. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: querySubject, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{scode}") }))
  1121. {
  1122. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1123. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1124. {
  1125. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1126. {
  1127. subjects.Add(obj.ToObject<object>());
  1128. }
  1129. }
  1130. }
  1131. var queryAnswers = $"select c.id,c.code,c.studentIds,c.subjectId,c.studentAnswers,c.studentScores,c.sum,c.mark from c where c.examId ='{id}' and array_contains(c.studentIds,'{studentId}') and c.pk = 'ExamClassResult' ";
  1132. List<ExamClassResult> answers = new List<ExamClassResult>();
  1133. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryAnswers,
  1134. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
  1135. {
  1136. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1137. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1138. {
  1139. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1140. {
  1141. answers.Add(obj.ToObject<ExamClassResult>());
  1142. }
  1143. }
  1144. }
  1145. List<List<string>> stuAns = new();
  1146. List<List<double>> stuScore = new();
  1147. List<List<List<Details>>> mark = new();
  1148. List<double> total = new();
  1149. if (answers.Count > 0)
  1150. {
  1151. foreach (ExamClassResult result in answers)
  1152. {
  1153. int index = result.studentIds.IndexOf(studentId.ToString());
  1154. if (index == -1)
  1155. {
  1156. break;
  1157. }
  1158. stuAns.Add(result.studentAnswers[index]);
  1159. stuScore.Add(result.studentScores[index]);
  1160. if (result.mark.Count > 0)
  1161. {
  1162. mark = result.mark;
  1163. //mark.Add(result.mark[index]);
  1164. }
  1165. total.Add(result.sum.Where(s => s <= 59).Count());
  1166. total.Add(result.sum.Where(s => s > 59 && s <= 70).Count());
  1167. total.Add(result.sum.Where(s => s > 70 && s <= 80).Count());
  1168. total.Add(result.sum.Where(s => s > 80 && s <= 90).Count());
  1169. total.Add(result.sum.Where(s => s > 90 && s <= 100).Count());
  1170. }
  1171. }
  1172. if (papers.IsNotEmpty())
  1173. {
  1174. return Ok(new { papers, subjects, stuScore, stuAns, mark, total, claId = infoIds, status = 200 });
  1175. }
  1176. else
  1177. {
  1178. return Ok(new { papers, subjects, stuScore, stuAns, mark, total, claId = infoIds, status = 404 });
  1179. }
  1180. }
  1181. catch (Exception ex)
  1182. {
  1183. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/find-summary-by-student()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1184. return Ok(new { status = 400 });
  1185. }
  1186. }
  1187. //查询学生活动列表
  1188. [ProducesDefaultResponseType]
  1189. //[AuthToken(Roles = "Student")]
  1190. [HttpPost("find-all-by-student")]
  1191. public async Task<IActionResult> findAllStudent(JsonElement requert)
  1192. {
  1193. //ResponseBuilder builder = ResponseBuilder.custom();
  1194. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1195. try
  1196. {
  1197. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1198. if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
  1199. List<string> resultIds = new List<string>();
  1200. var client = _azureCosmos.GetCosmosClient();
  1201. //查询校本班级ID
  1202. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(
  1203. queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}' and c.pk = 'Class' "))
  1204. {
  1205. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1206. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1207. {
  1208. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1209. while (accounts.MoveNext())
  1210. {
  1211. JsonElement account = accounts.Current;
  1212. resultIds.Add(account.GetProperty("id").GetString());
  1213. }
  1214. }
  1215. }
  1216. //查询私人班级ID
  1217. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(
  1218. queryText: $"select c.id from c join A0 in c.students where A0.id = '{studentId}' and c.pk = 'Class' "))
  1219. {
  1220. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1221. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1222. {
  1223. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1224. while (accounts.MoveNext())
  1225. {
  1226. JsonElement account = accounts.Current;
  1227. resultIds.Add(account.GetProperty("id").GetString());
  1228. }
  1229. }
  1230. }
  1231. //StringBuilder builder = new StringBuilder();
  1232. HashSet<string> strs = new HashSet<string>();
  1233. if (resultIds.Count > 1)
  1234. {
  1235. foreach (string str in resultIds)
  1236. {
  1237. strs.Add($"array_contains(c.classes,'{str}')");
  1238. //builder.Append($"array_contains(c.targetClassIds,'{str}')").Append("or");
  1239. }
  1240. //builder.ToString().Substring(0, builder.ToString().Length - 2);
  1241. }
  1242. else
  1243. {
  1244. string ssr = resultIds.Count > 0 ? resultIds[0] : "";
  1245. strs.Add($"array_contains(c.classes,'{ssr}')");
  1246. //builder.Append($" array_contains(c.targetClassIds,'{ssr}')");
  1247. }
  1248. string ss = string.Join(" or ", strs);
  1249. //if (!requert.TryGetProperty("school", out JsonElement school)) return BadRequest();
  1250. 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' ";
  1251. List<object> props = new List<object>();
  1252. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query))
  1253. {
  1254. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1255. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1256. {
  1257. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1258. {
  1259. props.Add(obj.ToObject<object>());
  1260. }
  1261. }
  1262. }
  1263. 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'";
  1264. List<ExamClassResult> Classes = new List<ExamClassResult>();
  1265. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryClass))
  1266. {
  1267. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1268. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1269. {
  1270. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1271. {
  1272. Classes.Add(obj.ToObject<ExamClassResult>());
  1273. }
  1274. }
  1275. }
  1276. List<ExamClassResult> result = new List<ExamClassResult>();
  1277. foreach (ExamClassResult classResult in Classes)
  1278. {
  1279. int index = classResult.studentIds.IndexOf(studentId.ToString());
  1280. ExamClassResult result1 = new ExamClassResult();
  1281. result1.examId = classResult.examId;
  1282. result1.subjectId = classResult.subjectId;
  1283. result1.studentAnswers.Add(classResult.studentAnswers[index]);
  1284. result1.studentScores.Add(classResult.studentScores[index]);
  1285. result.Add(result1);
  1286. }
  1287. return Ok(new { props, result });
  1288. }
  1289. catch (Exception ex)
  1290. {
  1291. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1292. return BadRequest();
  1293. }
  1294. }
  1295. //查询学生活动列表
  1296. [ProducesDefaultResponseType]
  1297. //[AuthToken(Roles = "Student")]
  1298. [HttpPost("find-score-by-student")]
  1299. public async Task<IActionResult> findScoreByStudent(JsonElement requert)
  1300. {
  1301. //ResponseBuilder builder = ResponseBuilder.custom();
  1302. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1303. try
  1304. {
  1305. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1306. //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1307. var client = _azureCosmos.GetCosmosClient();
  1308. var query = $"select c.examId,c.subjectId,c.studentScores from c where array_contains(c.studentIds,'{id}') ";
  1309. List<object> props = new List<object>();
  1310. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query))
  1311. {
  1312. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1313. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1314. {
  1315. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1316. {
  1317. props.Add(obj.ToObject<object>());
  1318. }
  1319. }
  1320. }
  1321. return Ok(props);
  1322. }
  1323. catch (Exception ex)
  1324. {
  1325. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1326. return BadRequest();
  1327. }
  1328. }
  1329. //查询学生活动列表
  1330. [ProducesDefaultResponseType]
  1331. //[AuthToken(Roles = "Student")]
  1332. [HttpPost("finish")]
  1333. public async Task<IActionResult> finish(JsonElement requert)
  1334. {
  1335. //ResponseBuilder builder = ResponseBuilder.custom();
  1336. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1337. try
  1338. {
  1339. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1340. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1341. var client = _azureCosmos.GetCosmosClient();
  1342. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1343. info.progress = "finish";
  1344. info.endTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1345. List<ExamClassResult> classResults = new();
  1346. if (info.scope.Equals("school"))
  1347. {
  1348. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1349. queryText: $"select value(c) from c where c.examId = '{id}'",
  1350. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1351. {
  1352. classResults.Add(item);
  1353. }
  1354. }
  1355. else
  1356. {
  1357. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1358. queryText: $"select value(c) from c where c.examId = '{id}'",
  1359. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1360. {
  1361. classResults.Add(item);
  1362. }
  1363. }
  1364. foreach (ExamClassResult examClass in classResults)
  1365. {
  1366. examClass.progress = true;
  1367. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(examClass, examClass.id, new PartitionKey($"{examClass.code}"));
  1368. }
  1369. info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1370. return Ok(info);
  1371. }
  1372. catch (Exception ex)
  1373. {
  1374. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/finish\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1375. return BadRequest();
  1376. }
  1377. }
  1378. /*//查询任务列表
  1379. [ProducesDefaultResponseType]
  1380. //[AuthToken(Roles = "Student")]
  1381. [HttpPost("scoring")]
  1382. public async Task<IActionResult> Scoring(JsonElement requert)
  1383. {
  1384. //ResponseBuilder builder = ResponseBuilder.custom();
  1385. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1386. try
  1387. {
  1388. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1389. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1390. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1391. var client = _azureCosmos.GetCosmosClient();
  1392. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1393. int index = 0;
  1394. foreach (ExamSubject subject in info.subjects) {
  1395. if (!subject.id.Equals(subjectId.ToString()))
  1396. {
  1397. index++;
  1398. }
  1399. else {
  1400. break;
  1401. }
  1402. }
  1403. List<string> stuAns = new();
  1404. Dictionary<string, List<List<double>>> keyValues = new();
  1405. List<ExamClassResult> classResults = new();
  1406. if (info.scope.Equals("school"))
  1407. {
  1408. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1409. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1410. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1411. {
  1412. classResults.Add(item);
  1413. }
  1414. }
  1415. else
  1416. {
  1417. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1418. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1419. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1420. {
  1421. classResults.Add(item);
  1422. }
  1423. }
  1424. List<List<double>> itemScore = new();
  1425. for (int i = 0; i < info.papers[index].point.Count; i++)
  1426. {
  1427. List<double> score = new();
  1428. foreach (ExamClassResult examClass in classResults)
  1429. {
  1430. foreach (List<double> sc in examClass.studentScores)
  1431. {
  1432. score.Add(sc[i]);
  1433. }
  1434. }
  1435. itemScore.Add(score);
  1436. }
  1437. foreach (ExamClassResult examClass in classResults)
  1438. {
  1439. foreach (List<string> ans in examClass.studentAnswers)
  1440. {
  1441. if (ans.Count > 0)
  1442. {
  1443. stuAns.Add(ans[0]);
  1444. }
  1445. else
  1446. {
  1447. stuAns.Add("");
  1448. }
  1449. }
  1450. }
  1451. //info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1452. return Ok(new { score = itemScore , stuAns, paper = info.papers });
  1453. }
  1454. catch (Exception ex)
  1455. {
  1456. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1457. return BadRequest();
  1458. }
  1459. }*/
  1460. [ProducesDefaultResponseType]
  1461. //[AuthToken(Roles = "Student")]
  1462. [HttpPost("scoring")]
  1463. public async Task<IActionResult> scoring(JsonElement requert)
  1464. {
  1465. //ResponseBuilder builder = ResponseBuilder.custom();
  1466. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1467. try
  1468. {
  1469. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1470. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1471. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1472. //if (!requert.TryGetProperty("type", out JsonElement type)) return BadRequest();
  1473. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1474. var client = _azureCosmos.GetCosmosClient();
  1475. //var redisClient = _azureRedis.GetRedisClient(8);
  1476. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1477. List<ExamClassResult> classResults = new();
  1478. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  1479. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1480. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and array_contains(c.tIds,'{tId}') ",
  1481. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1482. {
  1483. attr.Add(item);
  1484. }
  1485. int index = 0;
  1486. foreach (ExamSubject subject in info.subjects)
  1487. {
  1488. if (!subject.id.Equals(subjectId.ToString()))
  1489. {
  1490. index++;
  1491. }
  1492. else
  1493. {
  1494. break;
  1495. }
  1496. }
  1497. List<dynamic> objs = new List<dynamic>();
  1498. /*if (type.GetInt32() != 1) {
  1499. return Ok(new { attr, paper = info.papers[index].blob });
  1500. }*/
  1501. //List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  1502. //List<SDK.Models.Cosmos.Common.Scoring> arbs = new();
  1503. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  1504. {
  1505. //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});
  1506. List<dynamic> sc = new List<dynamic>();
  1507. ss.qs = ss.qs.Where(s => !string.IsNullOrEmpty(s.tId)).ToList();
  1508. int indexScore = 0;
  1509. foreach (Item item in ss.items)
  1510. {
  1511. List<double> scc = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).ToList();
  1512. //item.scores.Where(x => x.tmdId.Equals(tId.GetString())).SelectMany(p => p.sc, (p, d) => new { });
  1513. if (scc.Count > 0)
  1514. {
  1515. sc.Add(new { sc = scc.FirstOrDefault(), item.ssc });
  1516. }
  1517. else
  1518. {
  1519. sc.Add(new { sc = ss.scores[indexScore], item.ssc });
  1520. }
  1521. indexScore++;
  1522. //sc.Add(item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).FirstOrDefault());
  1523. //item.scores = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  1524. }
  1525. var obj = new { ss.id, ss.stuId, ss.examId, ss.subjectId, item = sc, ss.qs, ss.blob, ss.tIds, ss.scores, ss.model, ss.mode };
  1526. objs.Add(obj);
  1527. }
  1528. return Ok(new { objs, paper = info.papers[index].blob });
  1529. }
  1530. catch (Exception ex)
  1531. {
  1532. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1533. return BadRequest();
  1534. }
  1535. }
  1536. //查找异常卷
  1537. [ProducesDefaultResponseType]
  1538. //[AuthToken(Roles = "Student")]
  1539. [HttpPost("find-err")]
  1540. public async Task<IActionResult> findErr(JsonElement requert)
  1541. {
  1542. //ResponseBuilder builder = ResponseBuilder.custom();
  1543. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1544. try
  1545. {
  1546. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1547. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1548. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1549. //if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1550. var client = _azureCosmos.GetCosmosClient();
  1551. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1552. List<ExamClassResult> classResults = new();
  1553. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  1554. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1555. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1556. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1557. {
  1558. attr.Add(item);
  1559. }
  1560. int index = 0;
  1561. foreach (ExamSubject subject in info.subjects)
  1562. {
  1563. if (!subject.id.Equals(subjectId.ToString()))
  1564. {
  1565. index++;
  1566. }
  1567. else
  1568. {
  1569. break;
  1570. }
  1571. }
  1572. List<dynamic> objs = new List<dynamic>();
  1573. List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  1574. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  1575. {
  1576. List<Qs> qs = ss.qs.Where(s => !string.IsNullOrEmpty(s.err)).ToList();
  1577. if (qs.Count > 0)
  1578. {
  1579. ss.qs = qs;
  1580. errs.Add(ss);
  1581. }
  1582. }
  1583. return Ok(new { errs, paper = info.papers[index].blob });
  1584. }
  1585. catch (Exception ex)
  1586. {
  1587. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1588. return BadRequest();
  1589. }
  1590. }
  1591. [ProducesDefaultResponseType]
  1592. //[AuthToken(Roles = "Student")]
  1593. [HttpPost("find-arb")]
  1594. public async Task<IActionResult> findArb(JsonElement requert)
  1595. {
  1596. //ResponseBuilder builder = ResponseBuilder.custom();
  1597. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1598. try
  1599. {
  1600. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1601. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1602. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1603. if (!requert.TryGetProperty("et", out JsonElement et)) return BadRequest();
  1604. //if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1605. var client = _azureCosmos.GetCosmosClient();
  1606. long time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1607. if (et.GetInt64() > time)
  1608. {
  1609. return Ok(new { msg = "还在进行中", code = 202 });
  1610. }
  1611. ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1612. List<ExamClassResult> classResults = new();
  1613. List<SDK.Models.Cosmos.Common.Scoring> attr = new List<SDK.Models.Cosmos.Common.Scoring>();
  1614. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1615. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1616. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1617. {
  1618. attr.Add(item);
  1619. }
  1620. int index = 0;
  1621. foreach (ExamSubject subject in info.subjects)
  1622. {
  1623. if (!subject.id.Equals(subjectId.ToString()))
  1624. {
  1625. index++;
  1626. }
  1627. else
  1628. {
  1629. break;
  1630. }
  1631. }
  1632. List<dynamic> objs = new List<dynamic>();
  1633. /*if (type.GetInt32() != 1) {
  1634. return Ok(new { attr, paper = info.papers[index].blob });
  1635. }*/
  1636. //List<SDK.Models.Cosmos.Common.Scoring> errs = new();
  1637. List<SDK.Models.Cosmos.Common.Scoring> arbs = new();
  1638. foreach (SDK.Models.Cosmos.Common.Scoring ss in attr)
  1639. {
  1640. List<Item> arb = ss.items.Where(s => s.flag == false).ToList();
  1641. if (arb.Count > 0)
  1642. {
  1643. ss.items = arb;
  1644. arbs.Add(ss);
  1645. }
  1646. }
  1647. return Ok(new { objs, paper = info.papers[index].blob });
  1648. }
  1649. catch (Exception ex)
  1650. {
  1651. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/scoring\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1652. return BadRequest();
  1653. }
  1654. }
  1655. //批阅,给老师随机分配阅卷数据,以及查询改老师已有的阅卷数据
  1656. [ProducesDefaultResponseType]
  1657. //[AuthToken(Roles = "Student")]
  1658. [HttpPost("review")]
  1659. public async Task<IActionResult> Review(JsonElement requert)
  1660. {
  1661. //ResponseBuilder builder = ResponseBuilder.custom();
  1662. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1663. try
  1664. {
  1665. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1666. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1667. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1668. if (!requert.TryGetProperty("count", out JsonElement count)) return BadRequest();
  1669. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1670. var client = _azureCosmos.GetCosmosClient();
  1671. //var redisClient = _azureRedis.GetRedisClient(8);
  1672. List<ExamClassResult> classResults = new();
  1673. List<SDK.Models.Cosmos.Common.Scoring> recs = new();
  1674. List<SDK.Models.Cosmos.Common.Scoring> all = new();
  1675. List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  1676. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1677. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' ",
  1678. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1679. {
  1680. attr.Add(item);
  1681. }
  1682. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  1683. {
  1684. if (scoring.tIds.Contains(tId.ToString()))
  1685. {
  1686. recs.Add(scoring);
  1687. }
  1688. else if (scoring.tIds.Count < scoring.count * scoring.model)
  1689. {
  1690. all.Add(scoring);
  1691. }
  1692. }
  1693. /*var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
  1694. foreach (var rcd in record)
  1695. {
  1696. var value = JsonDocument.Parse(rcd.Value.ToString());
  1697. value.RootElement.TryGetProperty("info", out JsonElement json);
  1698. List<tmdInfo> tmds = json.ToObject<List<tmdInfo>>();
  1699. foreach (tmdInfo tmd in tmds)
  1700. {
  1701. if (!string.IsNullOrEmpty(tmd.tmdId) && tmd.tmdId.Equals(tId.ToString()))
  1702. {
  1703. recs.Add(new { stuId = rcd.Name.ToString(), info = value });
  1704. break;
  1705. }
  1706. if (string.IsNullOrEmpty(tmd.tmdId))
  1707. {
  1708. all.Add(new { stuId = rcd.Name.ToString(), ans = value });
  1709. break;
  1710. }
  1711. }
  1712. *//*if (tId.ToString().Equals(tmdId.ToString()))
  1713. {
  1714. recs.Add(new { stuId = rcd.Name.ToString(), ans = value });
  1715. }
  1716. if (string.IsNullOrEmpty(tmdId.ToString()))
  1717. {
  1718. all.Add(new { stuId = rcd.Name.ToString(), ans = value });
  1719. }*//*
  1720. }*/
  1721. if (requert.TryGetProperty("stuId", out JsonElement stuId))
  1722. {
  1723. List<SDK.Models.Cosmos.Common.Scoring> value = new();
  1724. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1725. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.stuId = '{stuId}' ",
  1726. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1727. {
  1728. value.Add(item);
  1729. }
  1730. if (value.Count > 0)
  1731. {
  1732. foreach (SDK.Models.Cosmos.Common.Scoring scoring in value)
  1733. {
  1734. if (scoring.tIds.Contains(tId.ToString()))
  1735. {
  1736. break;
  1737. }
  1738. else
  1739. {
  1740. scoring.tIds.Add(tId.ToString());
  1741. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey(scoring.code));
  1742. }
  1743. }
  1744. }
  1745. /*var stuAns = await redisClient.HashGetAsync($"Exam:Scoring:{id}-{subjectId}", stuId.ToString());
  1746. var value = JsonDocument.Parse(stuAns.ToString());
  1747. //保证此学生与该老师绑定
  1748. value.RootElement.TryGetProperty("ans", out JsonElement blob);
  1749. value.RootElement.TryGetProperty("score", out JsonElement sc);
  1750. value.RootElement.TryGetProperty("info", out JsonElement json);
  1751. List<tmdInfo> tmds = json.ToObject<List<tmdInfo>>();
  1752. foreach (tmdInfo tmd in tmds)
  1753. {
  1754. if (string.IsNullOrEmpty(tmd.tmdId))
  1755. {
  1756. tmd.tmdId = tId.ToString();
  1757. break;
  1758. }
  1759. }
  1760. await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", stuId.ToString(), new { info = tmds, ans = blob, score = sc }.ToJsonString());*/
  1761. //var its = value.Where(x => x.items.s)
  1762. List<dynamic> objs = new List<dynamic>();
  1763. List<SDK.Models.Cosmos.Common.Scoring> val = new List<SDK.Models.Cosmos.Common.Scoring>();
  1764. foreach (SDK.Models.Cosmos.Common.Scoring ss in value)
  1765. {
  1766. //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 });
  1767. List<dynamic> sc = new List<dynamic>();
  1768. int indexScore = 0;
  1769. foreach (Item item in ss.items)
  1770. {
  1771. List<double> scc = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).ToList();
  1772. //item.scores.Where(x => x.tmdId.Equals(tId.GetString())).SelectMany(p => p.sc, (p, d) => new { });
  1773. if (scc.Count > 0)
  1774. {
  1775. sc.Add(new { sc = scc.FirstOrDefault(), item.ssc });
  1776. }
  1777. else
  1778. {
  1779. sc.Add(new { sc = ss.scores[indexScore], item.ssc });
  1780. }
  1781. indexScore++;
  1782. //sc.Add(item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).FirstOrDefault());
  1783. //item.scores = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  1784. }
  1785. var obj = new { ss.id, ss.stuId, ss.examId, ss.subjectId, item = sc, ss.qs, ss.blob, ss.tIds, ss.scores, ss.model, ss.mode };
  1786. objs.Add(obj);
  1787. }
  1788. return Ok(objs);
  1789. }
  1790. else
  1791. {
  1792. if (recs.Count == count.GetInt32())
  1793. {
  1794. return Ok(new { msg = "分配人数已到上限" });
  1795. }
  1796. else
  1797. {
  1798. if (all.Count == 0)
  1799. {
  1800. return Ok(new { msg = "暂无可选学生" });
  1801. }
  1802. //随机选取一名学生打分
  1803. Random random = new Random();
  1804. SDK.Models.Cosmos.Common.Scoring item = new();
  1805. List<SDK.Models.Cosmos.Common.Scoring> notYet = new();
  1806. notYet = all.Where(x => x.tIds.Count < x.count * x.model - 1).ToList();
  1807. if (notYet.Count > 0)
  1808. {
  1809. item = notYet[random.Next(notYet.Count)];
  1810. }
  1811. else
  1812. {
  1813. item = all[random.Next(all.Count)];
  1814. }
  1815. if (!item.tIds.Contains(tId.ToString()))
  1816. {
  1817. item.tIds.Add(tId.ToString());
  1818. }
  1819. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  1820. //序列化单个学生作答记录、得分情况、批注情况
  1821. /*var cs = JsonSerializer.Serialize(item);
  1822. var json = JsonDocument.Parse(cs);
  1823. json.RootElement.TryGetProperty("stuId", out JsonElement sId);
  1824. json.RootElement.TryGetProperty("ans", out JsonElement ans);
  1825. ans.TryGetProperty("score", out JsonElement sc);
  1826. ans.TryGetProperty("ans", out JsonElement blob);
  1827. ans.TryGetProperty("info", out JsonElement element);
  1828. List<tmdInfo> tmds = element.ToObject<List<tmdInfo>>();
  1829. foreach (tmdInfo tmd in tmds)
  1830. {
  1831. if (string.IsNullOrEmpty(tmd.tmdId))
  1832. {
  1833. tmd.tmdId = tId.ToString();
  1834. break;
  1835. }
  1836. }*/
  1837. //选取后,缓存池相应的减少,以便于分配给其他的老师
  1838. //await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { info = tmds, ans = blob, score = sc }.ToJsonString());
  1839. //ss.items.Add(ss.items.Where(x => x.scores.))
  1840. /*foreach (Item its in item.items)
  1841. {
  1842. its.scores = its.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  1843. }*/
  1844. //List<double> sc = new List<double>();
  1845. // var scc = item.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 });
  1846. List<dynamic> sc = new List<dynamic>();
  1847. int indexScore = 0;
  1848. foreach (Item its in item.items)
  1849. {
  1850. List<double> ssc = its.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).ToList();
  1851. //item.scores.Where(x => x.tmdId.Equals(tId.GetString())).SelectMany(p => p.sc, (p, d) => new { });
  1852. if (ssc.Count > 0)
  1853. {
  1854. sc.Add(new { sc = ssc.FirstOrDefault(), its.ssc });
  1855. }
  1856. else
  1857. {
  1858. sc.Add(new { sc = item.scores[indexScore], its.ssc });
  1859. }
  1860. indexScore++;
  1861. //sc.Add(item.scores.Where(x => x.tmdId.Equals(tId.GetString())).Select(c => c.sc).FirstOrDefault());
  1862. //item.scores = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  1863. }
  1864. var obj = new { item.id, item.stuId, item.examId, item.subjectId, item = sc, item.qs, item.blob, item.tIds, item.scores, item.model, item.mode };
  1865. return Ok(obj);
  1866. }
  1867. }
  1868. //var json = JsonDocument.Parse(record);
  1869. /*ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new Azure.Cosmos.PartitionKey($"Exam-hbcn"));
  1870. if (info.scope.Equals("school"))
  1871. {
  1872. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1873. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1874. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  1875. {
  1876. classResults.Add(item);
  1877. }
  1878. }
  1879. else
  1880. {
  1881. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  1882. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  1883. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.creatorId}") }))
  1884. {
  1885. classResults.Add(item);
  1886. }
  1887. }
  1888. List<Task<bool>> tasks = new List<Task<bool>>();
  1889. foreach (ExamClassResult examClass in classResults)
  1890. {
  1891. foreach (string stuId in examClass.studentIds)
  1892. {
  1893. int index = examClass.studentIds.IndexOf(stuId);
  1894. tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", stuId, new { ans = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "", score = examClass.studentScores[index] }.ToJsonString()));
  1895. }
  1896. }
  1897. await Task.WhenAll(tasks);
  1898. return Ok();*/
  1899. //info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
  1900. }
  1901. catch (Exception ex)
  1902. {
  1903. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/review\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1904. return BadRequest();
  1905. }
  1906. }
  1907. //批阅 提交分数
  1908. [ProducesDefaultResponseType]
  1909. //[AuthToken(Roles = "Student")]
  1910. [HttpPost("sub-result")]
  1911. public async Task<IActionResult> SubResult(JsonElement requert)
  1912. {
  1913. //ResponseBuilder builder = ResponseBuilder.custom();
  1914. //var (id, school) = HttpContext.GetAuthTokenInfo();
  1915. try
  1916. {
  1917. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1918. if (!requert.TryGetProperty("stuId", out JsonElement sId)) return BadRequest();
  1919. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  1920. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  1921. if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest();
  1922. if (!requert.TryGetProperty("count", out JsonElement count)) return BadRequest();
  1923. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1924. //if (!requert.TryGetProperty("mark", out JsonElement mark)) return BadRequest();
  1925. //requert.TryGetProperty("mark", out JsonElement mark);
  1926. var client = _azureCosmos.GetCosmosClient();
  1927. //var redisClient = _azureRedis.GetRedisClient(8);
  1928. List<ExamClassResult> classResults = new();
  1929. List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  1930. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  1931. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.stuId = '{sId}' and array_contains(c.tIds,'{tId}') ",
  1932. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  1933. {
  1934. attr.Add(item);
  1935. }
  1936. /*List<dynamic> recs = new List<dynamic>();
  1937. var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
  1938. foreach (var rcd in record)
  1939. {
  1940. var values = JsonDocument.Parse(rcd.Value.ToString());
  1941. values.RootElement.TryGetProperty("info", out JsonElement json);
  1942. List<tmdInfo> tmdInfos = json.ToObject<List<tmdInfo>>();
  1943. foreach (tmdInfo tmd in tmdInfos)
  1944. {
  1945. if (!string.IsNullOrEmpty(tmd.tmdId) && tmd.tmdId.Equals(tId.ToString()))
  1946. {
  1947. recs.Add(new { stuId = rcd.Name.ToString(), info = values });
  1948. break;
  1949. }
  1950. }
  1951. *//*if (tId.ToString().Equals(tmdId.ToString()))
  1952. {
  1953. recs.Add(new { stuId = rcd.Name.ToString(), ans = values });
  1954. }*//*
  1955. }*/
  1956. /*var stuAns = await redisClient.HashGetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString());
  1957. var value = JsonDocument.Parse(stuAns.ToString());
  1958. value.RootElement.TryGetProperty("ans", out JsonElement blob);
  1959. value.RootElement.TryGetProperty("info", out JsonElement element);
  1960. List<tmdInfo> tmds = element.ToObject<List<tmdInfo>>();*/
  1961. List<double> ssc = score.ToObject<List<double>>();
  1962. StringBuilder builder = new();
  1963. /*if (requert.TryGetProperty("mark", out JsonElement mark))
  1964. {
  1965. //存放老师批注信息到blob
  1966. builder.Append(id).Append('/');
  1967. builder.Append(subjectId).Append('/');
  1968. builder.Append(sId).Append("mark").Append('/');
  1969. //builder.Append(tId).Append('/');
  1970. builder.Append("ans.json");
  1971. await _azureStorage.UploadFileByContainer(code.ToString(), mark.ToJsonString(), "exam", builder.ToString(), false);
  1972. if (attr.Count > 0)
  1973. {
  1974. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  1975. {
  1976. foreach (Item item in scoring.items)
  1977. {
  1978. bool flag = false;
  1979. int index = 0;
  1980. if (item.scores.Count > 0)
  1981. {
  1982. foreach (Info info in item.scores)
  1983. {
  1984. if (!info.tmdId.Equals(tId.GetString()))
  1985. {
  1986. index++;
  1987. }
  1988. else
  1989. {
  1990. scoring.marks[index] = builder.ToString();
  1991. flag = true;
  1992. break;
  1993. }
  1994. }
  1995. }
  1996. if (flag)
  1997. {
  1998. break;
  1999. }
  2000. //List<Info> info = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  2001. }
  2002. int index = scoring.tIds.IndexOf(tId.GetString());
  2003. if (index != -1)
  2004. {
  2005. scoring.marks[index] = builder.ToString();
  2006. }
  2007. }
  2008. }
  2009. }*/
  2010. if (attr.Count > 0)
  2011. {
  2012. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  2013. {
  2014. int itemIndex = 0;
  2015. //int tIdIndex = scoring.tIds.IndexOf(tId.GetString());
  2016. if (requert.TryGetProperty("qu", out JsonElement qu))
  2017. {
  2018. List<int> nos = qu.ToObject<List<int>>();
  2019. foreach (int number in nos)
  2020. {
  2021. List<Info> items = scoring.items[number].scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  2022. if (items.Count > 0)
  2023. {
  2024. foreach (Info info in items)
  2025. {
  2026. info.sc = ssc[number];
  2027. }
  2028. }
  2029. else
  2030. {
  2031. Info info = new();
  2032. info.sc = ssc[number];
  2033. info.tmdId = tId.GetString();
  2034. info.index = number;
  2035. scoring.items[number].scores.Add(info);
  2036. }
  2037. }
  2038. }
  2039. else
  2040. {
  2041. foreach (Item item in scoring.items)
  2042. {
  2043. List<Info> items = item.scores.Where(x => x.tmdId.Equals(tId.GetString())).ToList();
  2044. if (items.Count > 0)
  2045. {
  2046. foreach (Info info in items)
  2047. {
  2048. info.sc = ssc[itemIndex];
  2049. }
  2050. }
  2051. else
  2052. {
  2053. Info info = new();
  2054. info.sc = ssc[itemIndex];
  2055. info.tmdId = tId.GetString();
  2056. info.index = itemIndex;
  2057. item.scores.Add(info);
  2058. }
  2059. itemIndex++;
  2060. }
  2061. }
  2062. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey(scoring.code));
  2063. }
  2064. }
  2065. //判定阅卷结算的条件
  2066. if (attr.Count == count.GetInt32())
  2067. {
  2068. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  2069. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
  2070. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  2071. {
  2072. classResults.Add(item);
  2073. }
  2074. foreach (ExamClassResult exam in classResults)
  2075. {
  2076. foreach (SDK.Models.Cosmos.Common.Scoring scoring in attr)
  2077. {
  2078. int index = exam.studentIds.IndexOf(scoring.stuId);
  2079. //均分
  2080. int n = 0;
  2081. foreach (Item item in scoring.items)
  2082. {
  2083. var ace = item.scores.Where(x => string.IsNullOrEmpty(x.tmdId)).ToList();
  2084. if (ace.Count > 0)
  2085. {
  2086. return Ok(new { code = 200 });
  2087. }
  2088. //判定是否仲裁卷
  2089. if (!item.flag)
  2090. {
  2091. //scoring.type = 3;
  2092. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey(scoring.code));
  2093. return Ok(new { msg = "试题分数差异过大" });
  2094. }
  2095. double sc = item.scores.Select(x => x.sc).ToList().Aggregate((i, j) => (i + j) / item.scores.Count);
  2096. scoring.scores[n] = sc;
  2097. n++;
  2098. }
  2099. if (index != -1)
  2100. {
  2101. exam.studentScores[index] = scoring.scores;
  2102. int itemIndex = 0;
  2103. foreach (Item item in scoring.items)
  2104. {
  2105. string tmdId = item.scores[itemIndex].tmdId;
  2106. //判定是否已经存在对应的批注信息
  2107. bool flag = exam.mark[index][itemIndex].Exists(x => x.tmdId.Equals(tmdId));
  2108. if (flag)
  2109. {
  2110. //重复打分更新部分值
  2111. exam.mark[index][itemIndex].Where(x => x.tmdId.Equals(tmdId)).ToList().ForEach(score =>
  2112. {
  2113. score.sc = item.scores[itemIndex].sc;
  2114. score.mark = item.scores[itemIndex].mark;
  2115. });
  2116. }
  2117. else
  2118. {
  2119. Details dt = new()
  2120. {
  2121. index = item.scores[itemIndex].index,
  2122. sc = item.scores[itemIndex].sc,
  2123. tmdId = item.scores[itemIndex].tmdId,
  2124. mark = item.scores[itemIndex].mark,
  2125. identity = item.scores[itemIndex].identity
  2126. };
  2127. exam.mark[index][itemIndex].Add(dt);
  2128. }
  2129. itemIndex++;
  2130. }
  2131. }
  2132. }
  2133. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, exam.id, new PartitionKey($"{exam.code}"));
  2134. }
  2135. }
  2136. return Ok(new { code = 200 });
  2137. }
  2138. catch (Exception ex)
  2139. {
  2140. await _dingDing.SendBotMsg($"OS,{_option.Location},exam/sub-result\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  2141. return BadRequest();
  2142. }
  2143. }
  2144. //查询阅卷类型数据
  2145. [ProducesDefaultResponseType]
  2146. //[AuthToken(Roles = "Student")]
  2147. [HttpPost("find-scoring")]
  2148. public async Task<IActionResult> findScoring(JsonElement requert)
  2149. {
  2150. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2151. if (!requert.TryGetProperty("stuId", out JsonElement sId)) return BadRequest();
  2152. if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  2153. if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
  2154. if (!requert.TryGetProperty("type", out JsonElement type)) return BadRequest();
  2155. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2156. var client = _azureCosmos.GetCosmosClient();
  2157. List<SDK.Models.Cosmos.Common.Scoring> attr = new();
  2158. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<SDK.Models.Cosmos.Common.Scoring>(
  2159. 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}') ",
  2160. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Scoring-{code}") }))
  2161. {
  2162. attr.Add(item);
  2163. }
  2164. return Ok(attr);
  2165. }
  2166. //申报异常卷内容
  2167. [ProducesDefaultResponseType]
  2168. //[AuthToken(Roles = "Student")]
  2169. [HttpPost("save-err")]
  2170. public async Task<IActionResult> saveErr(JsonElement requert)
  2171. {
  2172. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2173. if (!requert.TryGetProperty("err", out JsonElement err)) return BadRequest();
  2174. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2175. if (!requert.TryGetProperty("index", out JsonElement index)) return BadRequest();
  2176. if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  2177. var client = _azureCosmos.GetCosmosClient();
  2178. SDK.Models.Cosmos.Common.Scoring scoring = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<SDK.Models.Cosmos.Common.Scoring>(id.GetString(), new PartitionKey($"Scoring-{code}"));
  2179. if (null != scoring)
  2180. {
  2181. if (string.IsNullOrEmpty(scoring.qs[index.GetInt32()].tId))
  2182. {
  2183. scoring.qs[index.GetInt32()].err = err.GetString();
  2184. scoring.qs[index.GetInt32()].tId = tId.GetString();
  2185. scoring.qs[index.GetInt32()].index = index.GetInt32();
  2186. }
  2187. else
  2188. {
  2189. return Ok(new { msg = "改题已经被申报", code = 404 });
  2190. }
  2191. /* scoring.type = 2;
  2192. scoring.err = err.GetString();*/
  2193. }
  2194. else
  2195. {
  2196. return Ok(new { code = 404 });
  2197. }
  2198. var sc = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey($"{scoring.code}"));
  2199. return Ok(new { sc });
  2200. }
  2201. //处理异常卷内容
  2202. [ProducesDefaultResponseType]
  2203. //[AuthToken(Roles = "Student")]
  2204. [HttpPost("fd-err")]
  2205. public async Task<IActionResult> fdErr(JsonElement requert)
  2206. {
  2207. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2208. if (!requert.TryGetProperty("improve", out JsonElement improve)) return BadRequest();
  2209. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2210. if (!requert.TryGetProperty("index", out JsonElement index)) return BadRequest();
  2211. //if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  2212. var client = _azureCosmos.GetCosmosClient();
  2213. SDK.Models.Cosmos.Common.Scoring scoring = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<SDK.Models.Cosmos.Common.Scoring>(id.GetString(), new PartitionKey($"Scoring-{code}"));
  2214. if (null != scoring)
  2215. {
  2216. if (string.IsNullOrEmpty(scoring.qs[index.GetInt32()].improve))
  2217. {
  2218. scoring.qs[index.GetInt32()].improve = improve.GetString();
  2219. //scoring.qs[index.GetInt32()].tId = tId.GetString();
  2220. //scoring.qs[index.GetInt32()].index = index.GetInt32();
  2221. }
  2222. else
  2223. {
  2224. return Ok(new { msg = "改题已经被处理", code = 404 });
  2225. }
  2226. /* scoring.type = 2;
  2227. scoring.err = err.GetString();*/
  2228. }
  2229. else
  2230. {
  2231. return Ok(new { code = 404 });
  2232. }
  2233. var sc = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey($"{scoring.code}"));
  2234. return Ok(new { sc });
  2235. }
  2236. //处理仲裁卷内容
  2237. [ProducesDefaultResponseType]
  2238. //[AuthToken(Roles = "Student")]
  2239. [HttpPost("save-arb")]
  2240. public async Task<IActionResult> saveArb(JsonElement requert)
  2241. {
  2242. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  2243. if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest();//就是一维数组
  2244. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  2245. var client = _azureCosmos.GetCosmosClient();
  2246. List<double> scs = score.ToObject<List<double>>();
  2247. List<ExamClassResult> classResults = new();
  2248. SDK.Models.Cosmos.Common.Scoring scoring = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<SDK.Models.Cosmos.Common.Scoring>(id.GetString(), new PartitionKey($"Scoring-{code}"));
  2249. if (null != scoring)
  2250. {
  2251. scoring.scores = scs;
  2252. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
  2253. queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{scoring.subjectId}'",
  2254. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  2255. {
  2256. classResults.Add(item);
  2257. }
  2258. foreach (ExamClassResult exam in classResults)
  2259. {
  2260. int index = exam.studentIds.IndexOf(scoring.stuId);
  2261. if (index != -1)
  2262. {
  2263. exam.studentScores[index] = scoring.scores;
  2264. //exam.mark[index] = scoring.marks;
  2265. }
  2266. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, exam.id, new PartitionKey($"{exam.code}"));
  2267. }
  2268. }
  2269. else
  2270. {
  2271. return Ok(new { code = 404 });
  2272. }
  2273. var sc = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(scoring, scoring.id, new PartitionKey($"{scoring.code}"));
  2274. return Ok(new { sc });
  2275. }
  2276. //阅卷信息统计
  2277. [ProducesDefaultResponseType]
  2278. //[AuthToken(Roles = "Student")]
  2279. [HttpPost("analysis-scoring")]
  2280. public async Task<IActionResult> Analysis(JsonElement requert)
  2281. {
  2282. return null;
  2283. }
  2284. }
  2285. }