AnalysisController.cs 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919
  1. using ClouDASLibx;
  2. using Microsoft.AspNetCore.Mvc;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text.Json;
  7. using System.Threading.Tasks;
  8. using TEAMModelOS.SDK.Models;
  9. using TEAMModelOS.SDK;
  10. using TEAMModelOS.SDK.DI;
  11. using TEAMModelOS.SDK.Extension;
  12. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  13. using Microsoft.Extensions.Options;
  14. using TEAMModelOS.Models;
  15. using Azure.Cosmos;
  16. using System.Text;
  17. using Microsoft.AspNetCore.Authorization;
  18. using TEAMModelOS.Filter;
  19. using TEAMModelOS.SDK.Models.Service;
  20. namespace TEAMModelOS.Controllers.Analysis
  21. {
  22. [Route("analysis")]
  23. [ApiController]
  24. public class AnalysisController : ControllerBase
  25. {
  26. private readonly AzureCosmosFactory _azureCosmos;
  27. private readonly DingDing _dingDing;
  28. private readonly Option _option;
  29. private const string CacheCosmosPrefix = "Analysis:";
  30. private const int timeoutSeconds = 3600;
  31. private readonly CoreAPIHttpService _coreAPIHttpService;
  32. public AnalysisController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option,CoreAPIHttpService coreAPIHttpService)
  33. {
  34. _azureCosmos = azureCosmos;
  35. _dingDing = dingDing;
  36. _option = option?.Value;
  37. _coreAPIHttpService = coreAPIHttpService;
  38. }
  39. [ProducesDefaultResponseType]
  40. [HttpPost("process")]
  41. [Authorize(Roles = "IES")]
  42. [AuthToken(Roles = "teacher,admin")]
  43. public async Task<IActionResult> getAnalysis(JsonElement request)
  44. {
  45. //获取评测的ID
  46. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  47. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  48. List<StudentAys> students = new List<StudentAys>();
  49. List<ClassAys> classes = new List<ClassAys>();
  50. List<GradeAys> grades = new List<GradeAys>();
  51. List<Dictionary<string, dynamic>> PointAnalysis = new List<Dictionary<string, dynamic>>();
  52. List<string> scatterKey = new List<string>
  53. {
  54. "name",
  55. "className",
  56. "x",
  57. "y",
  58. "memberId",
  59. "score",
  60. "trueNum",
  61. "falseNum",
  62. "hardList",
  63. "carefulList",
  64. "scatter"
  65. };
  66. List<string> paperKey = new List<string>
  67. {
  68. "id",
  69. "type",
  70. "areaName",
  71. "score",
  72. "diff",
  73. "identify",
  74. "classScoreRate",
  75. "gradeScoreRate",
  76. "areaScoreRate",
  77. "highScoreRate",
  78. "lowScoreRate",
  79. "knowledgePoint",
  80. "R1",
  81. "R2",
  82. "R3",
  83. "R4",
  84. "R5",
  85. "R6",
  86. "PH",
  87. "PL",
  88. "X",
  89. "Y",
  90. "knowledge",
  91. "examScoreRate"
  92. };
  93. List<string> knowkey = new List<string>
  94. {
  95. "id",
  96. "className",
  97. "seatNO",
  98. "point",
  99. "anwPoint",
  100. "persent"
  101. };
  102. List<string> keynowWrong = new List<string>
  103. {
  104. "name",
  105. "point",
  106. "itemNO",
  107. "persent",
  108. "wrong",
  109. "rhw",
  110. "rlw"
  111. };
  112. ExamInfo info = null;
  113. double ipoint = 0;
  114. List<KeyValuePair<string, List<List<string>>>> subjectPaperDatas = new List<KeyValuePair<string, List<List<string>>>>();
  115. List<Dictionary<string, object>> valuePairs = new List<Dictionary<string, object>>();
  116. List<KeyValuePair<string, List<KeyValuePair<string, List<double>>>>> classSubjectPaperDatas = new List<KeyValuePair<string, List<KeyValuePair<string, List<double>>>>>();
  117. List<KeyValuePair<string, List<string>>> knowNameDatas = new List<KeyValuePair<string, List<string>>>();
  118. List<KeyValuePair<string, List<string>>> knowPerDatas = new List<KeyValuePair<string, List<string>>>();
  119. List<KeyValuePair<string, List<double>>> knowAllPerDatas = new List<KeyValuePair<string, List<double>>>();
  120. List<KeyValuePair<string, List<double>>> knowScoreDatas = new List<KeyValuePair<string, List<double>>>();
  121. List<KeyValuePair<string, List<List<string>>>> wrongDatas = new List<KeyValuePair<string, List<List<string>>>>();
  122. List<KeyValuePair<string, List<KeyValuePair<string, List<double>>>>> stuPerDatas = new List<KeyValuePair<string, List<KeyValuePair<string, List<double>>>>>();
  123. //声明认知层次变量
  124. List<KeyValuePair<string, List<int>>> fieldNameDatas = new List<KeyValuePair<string, List<int>>>();
  125. List<KeyValuePair<string, List<string>>> fieldPerDatas = new List<KeyValuePair<string, List<string>>>();
  126. List<KeyValuePair<string, List<double>>> fieldAllPerDatas = new List<KeyValuePair<string, List<double>>>();
  127. List<KeyValuePair<string, List<double>>> fieldScoreDatas = new List<KeyValuePair<string, List<double>>>();
  128. List<KeyValuePair<string, List<List<string>>>> fieldwrongDatas = new List<KeyValuePair<string, List<List<string>>>>();
  129. List<KeyValuePair<string, List<KeyValuePair<string, List<double>>>>> fieldStuPerDatas = new List<KeyValuePair<string, List<KeyValuePair<string, List<double>>>>>();
  130. //获取进线标准以及踩线分数
  131. int touch = 0;
  132. int income = 0;
  133. List<ExamResult> examResults = new List<ExamResult>();
  134. try
  135. {
  136. var client = _azureCosmos.GetCosmosClient();
  137. //获取本次评测所有科目结算结果
  138. info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  139. //School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(code.ToString(), new PartitionKey($"Base"));
  140. var query = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes,c.sRate,c.average,c.standard,c.lostStus,c.record,c.phc,c.plc from c where c.examId = '{id}' ";
  141. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
  142. {
  143. examResults.Add(item);
  144. }
  145. //获取本次评测所有班级作答结果
  146. List<ExamClassResult> examClassResults = new List<ExamClassResult>();
  147. if (info.owner.Equals("teacher") && info.scope.Equals("school"))
  148. {
  149. var queryClass = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.gradeId,c.info,c.standard,c.krate,c.phc,c.plc,c.pc,c.frate,c.fphc,c.fplc,c.fpc,c.status from c where c.examId = '{id}' and c.progress = true ";
  150. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") }))
  151. {
  152. examClassResults.Add(item);
  153. }
  154. }
  155. else {
  156. var queryClass = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.gradeId,c.info,c.standard,c.krate,c.phc,c.plc,c.pc,c.frate,c.fphc,c.fplc,c.fpc,c.status from c where c.examId = '{id}' and c.progress = true ";
  157. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
  158. {
  159. examClassResults.Add(item);
  160. }
  161. }
  162. if (examClassResults.Count ==0) {
  163. return Ok(new { code = 404 ,msg = "数据还在结算中!"});
  164. }
  165. touch = info.touch;
  166. income = info.income;
  167. /*foreach (Period period in school.period)
  168. {
  169. if (info.period.id.Equals(period.id))
  170. {
  171. }
  172. }*/
  173. //计算每个年级参考人数并计算进线分数
  174. List<KeyValuePair<string, double>> keys = new List<KeyValuePair<string, double>>();
  175. List<double> gradeTotal = new List<double>();
  176. /*foreach (Grade grade in info.grades) {
  177. double ipoint = 0;
  178. int gradeCount = 0;
  179. //List<double> gradeTotal = new List<double>();
  180. HashSet<string> sno = new HashSet<string>();
  181. foreach (ExamClassResult examClassResult in examClassResults) {
  182. if (grade.id.Equals(examClassResult.gradeId)) {
  183. gradeCount += examClassResult.studentIds.Count;
  184. foreach (string s in examClassResult.studentIds) {
  185. sno.Add(s);
  186. }
  187. }
  188. }
  189. foreach (string sid in sno) {
  190. double total = 0;
  191. foreach (ExamClassResult examClassResult in examClassResults) {
  192. if (grade.id.Equals(examClassResult.gradeId))
  193. {
  194. int index = examClassResult.studentIds.IndexOf(sid);
  195. if (index == -1) continue;
  196. total += examClassResult.studentScores[index].Sum();
  197. }
  198. }
  199. gradeTotal.Add(total);
  200. }
  201. gradeTotal.Sort((s1, s2) => { return s2.CompareTo(s1); });
  202. //获取进线人数
  203. int personCount = (int)System.Math.Round(gradeCount / info.subjects.Count * (touch / 100.0), MidpointRounding.AwayFromZero);
  204. ipoint = gradeTotal[personCount];
  205. keys.Add(new KeyValuePair<string, double>(grade.id, ipoint));
  206. }*/
  207. //获取进线人数
  208. int personCount = (int)System.Math.Round(info.stuCount * (income / 100.0), MidpointRounding.AwayFromZero);
  209. /* //声明年级所有科目总分
  210. List<double> total = new List<double>();*/
  211. List<ClassRange> classReses = null;
  212. //按科目获取所有学生的分数
  213. Dictionary<string, List<double>> subjectTotal = new Dictionary<string, List<double>>();
  214. Dictionary<string, double> paperScore = new Dictionary<string, double>();
  215. List<KeyValuePair<string, List<KeyValuePair<string, List<string>>>>> subjectScatter = new List<KeyValuePair<string, List<KeyValuePair<string, List<string>>>>>();
  216. List<KeyValuePair<string, Dictionary<string, List<double>>>> gscores = new List<KeyValuePair<string, Dictionary<string, List<double>>>>();
  217. //声明全科总分
  218. double totalAll = 0;
  219. List<string> stuIds = new();
  220. foreach (ExamResult examResult in examResults)
  221. {
  222. (KeyValuePair<string, List<List<string>>> subjectData, KeyValuePair<string, List<KeyValuePair<string, List<double>>>> classSubjectData, Dictionary<string, List<double>> gscore) = DoExerciseScatteres(examResult, paperKey);
  223. (KeyValuePair<string, List<string>> knowName, KeyValuePair<string, List<string>> knowPer, KeyValuePair<string, List<double>> knowAllPer, KeyValuePair<string, List<double>> kScore, KeyValuePair<string, List<List<string>>> wrong, KeyValuePair<string, List<KeyValuePair<string, List<double>>>> stuPer) = DoKnowledgePoint(examResult, info, keynowWrong);
  224. (KeyValuePair<string, List<int>> fieldName, KeyValuePair<string, List<string>> fieldPer, KeyValuePair<string, List<double>> fieldAllPer, KeyValuePair<string, List<double>> fScore, KeyValuePair<string, List<List<string>>> fieldWrong, KeyValuePair<string, List<KeyValuePair<string, List<double>>>> fieldStuPer) = DoLevel(examResult, info, keynowWrong);
  225. gscores.Add(new KeyValuePair<string, Dictionary<string, List<double>>>(examResult.subjectId, gscore));
  226. /* Dictionary<string, dynamic> gpoint = new Dictionary<string, dynamic>();
  227. Dictionary<string, dynamic> glevel = new Dictionary<string, dynamic>();*/
  228. Dictionary<string, object> gpointList = new Dictionary<string, object>();
  229. subjectPaperDatas.Add(subjectData);
  230. classSubjectPaperDatas.Add(classSubjectData);
  231. subjectScatter.Add(DoSubjectScatter(examResult));
  232. knowNameDatas.Add(knowName);
  233. knowPerDatas.Add(knowPer);
  234. knowAllPerDatas.Add(knowAllPer);
  235. knowScoreDatas.Add(kScore);
  236. wrongDatas.Add(wrong);
  237. stuPerDatas.Add(stuPer);
  238. fieldNameDatas.Add(fieldName);
  239. fieldPerDatas.Add(fieldPer);
  240. fieldAllPerDatas.Add(fieldAllPer);
  241. fieldScoreDatas.Add(fScore);
  242. fieldwrongDatas.Add(fieldWrong);
  243. fieldStuPerDatas.Add(fieldStuPer);
  244. //gpointList.Add("subjectId", examResult.subjectId);
  245. //gpointList.Add("pointKey", DoKnowledgePoint(examResult, info));
  246. //gpointList.Add("levelKey", DoLevel(examResult, info));
  247. valuePairs.Add(gpointList);
  248. //获取一张试卷的满分
  249. totalAll += examResult.paper.point.Sum();
  250. paperScore.Add(examResult.subjectId, examResult.paper.point.Sum());
  251. List<double> StuSubjectTotals = new List<double>();
  252. classReses = examResult.classes;
  253. //处理个人
  254. foreach (var stuid in examResult.studentIds)
  255. {
  256. if (!stuIds.Contains(stuid))
  257. {
  258. stuIds.Add(stuid);
  259. }
  260. StudentAys student = null;
  261. int index = examResult.studentIds.IndexOf(stuid);
  262. if (students.Select(x => x.id).Contains(stuid))
  263. {
  264. student = students[index];
  265. }
  266. else
  267. {
  268. student = new StudentAys() { id = stuid };
  269. students.Add(student);
  270. }
  271. var score = Math.Round(examResult.studentScores[index].Sum(),2);
  272. student.total += score;
  273. student.total = Math.Round(student.total, 2);
  274. StuSubjectTotals.Add(score);
  275. if (student.subjects.Select(x => x.id).Contains(examResult.subjectId))
  276. {
  277. student.subjects.ForEach(y =>
  278. {
  279. if (y.id.Equals(examResult.subjectId))
  280. {
  281. y.score = score;
  282. y.sRate = Math.Round(examResult.paper.point.Sum() > 0 ? score / examResult.paper.point.Sum() : 0, 2);
  283. }
  284. });
  285. }
  286. else
  287. {
  288. StudentSubject subject = new StudentSubject
  289. {
  290. id = examResult.subjectId,
  291. scores = examResult.studentScores[examResult.studentIds.IndexOf(stuid)],
  292. name = info.subjects.Where(x => x.id == examResult.subjectId).FirstOrDefault().name,
  293. point = stuPerDatas.Where(x => x.Key == examResult.subjectId).SelectMany(va => va.Value).Where(stu => stu.Key == stuid).Select(pi => pi.Value).First(),
  294. fieldPoint = fieldStuPerDatas.Where(x => x.Key == examResult.subjectId).SelectMany(va => va.Value).Where(stu => stu.Key == stuid).Select(pi => pi.Value).First()
  295. };
  296. subject.score = score;
  297. subject.sRate = Math.Round(examResult.paper.point.Sum() > 0 ? score / examResult.paper.point.Sum() * 100 : 0, 2);
  298. student.subjects.Add(subject);
  299. }
  300. }
  301. subjectTotal.Add(examResult.subjectId, StuSubjectTotals);
  302. }
  303. //double powAll = 0;
  304. foreach (StudentAys student1 in students)
  305. {
  306. gradeTotal.Add(student1.total);
  307. student1.sRate = totalAll > 0 ? Math.Round(student1.total / totalAll * 100, 2) : 0;
  308. //powAll += Math.Pow(student1.total - examResult.studentIds.Count > 0 ? Math.Round(score * 1.0 / examResult.studentIds.Count, 2) : 0, 2);
  309. }
  310. //处理进线分数
  311. gradeTotal.Sort((s1, s2) => { return s2.CompareTo(s1); });
  312. if (personCount == 0)
  313. {
  314. ipoint = gradeTotal[personCount] + 1;
  315. }
  316. else
  317. {
  318. if (personCount == gradeTotal.Count)
  319. {
  320. ipoint = gradeTotal[personCount - 1];
  321. }
  322. else {
  323. ipoint = gradeTotal[personCount];
  324. }
  325. }
  326. //以班级为单位(此处处理的是行政班级,教学班如果被移除则会无法分析)
  327. List<string> clas = ExamService.getClasses(info.classes, info.stuLists);
  328. (List<RMember> members, List<RGroupList> classLists) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, clas, info.school, null,-1,info.startTime);
  329. foreach (RGroupList rGroup in classLists)
  330. {
  331. /* Class classroom = null;
  332. var sresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(classId, new PartitionKey($"Class-{code}"));
  333. if (sresponse.Status == 200)
  334. {
  335. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  336. classroom = json.ToObject<Class>();
  337. }*/
  338. //处理班级
  339. var classRes = classReses.Where(x => x.id == rGroup.id).FirstOrDefault();
  340. var stuCount = classRes.range[1] - classRes.range[0] + 1;
  341. // 班级缺考人数
  342. var lostClassCount = examClassResults.Where(x => x.info.id.Equals(rGroup.id)).FirstOrDefault().status.Where(r => r == 1).ToList().Count;
  343. List<StudentAys> classStudents = new();
  344. /* foreach (string sid in stuIds)
  345. {
  346. foreach (var stu in students)
  347. {
  348. if (stu.id == sid && stu.classId == classRes.id)
  349. {
  350. classStudents.Add(stu);
  351. }
  352. }
  353. };*/
  354. for (int i = classRes.range[0]; i <= classRes.range[1]; i++) {
  355. foreach (var stu in students)
  356. {
  357. if (stu.id == examResults[0].studentIds[i])
  358. {
  359. classStudents.Add(stu);
  360. }
  361. }
  362. }
  363. //var classStudents = students.GetRange(classRes.range[0], classRes.range[1] - classRes.range[0] + 1);
  364. List<double> stuTotals = classStudents.Select(x => x.total).ToList();
  365. stuTotals.Sort((s1, s2) => { return s2.CompareTo(s1); });
  366. //初始化进线人数
  367. int lineCount = 0;
  368. //初始化班级总分
  369. double classTotal = stuTotals.Sum();
  370. //标准差
  371. double powSum = 0;
  372. //计算标准差
  373. //总平均分
  374. double totalAverage = 0;
  375. totalAverage = stuCount - lostClassCount > 0 ? classTotal * 1.0 / (stuCount - lostClassCount) : 0;
  376. //totalAverage = classTotal / stuCount;
  377. //获取整个班级 科目的分数情况
  378. List<KeyValuePair<string, double>> keyValues = new List<KeyValuePair<string, double>>();
  379. List<string> studentIds = new List<string>();
  380. List<KeyValuePair<string, List<double>>> pointClassTotal = new List<KeyValuePair<string, List<double>>>();
  381. List<KeyValuePair<string, List<double>>> fieldClassTotal = new List<KeyValuePair<string, List<double>>>();
  382. subjectTotal.Keys.ToList().ForEach(sub =>
  383. {
  384. var points = new List<double>();
  385. var fields = new List<double>();
  386. knowNameDatas.Where(su => su.Key == sub).First().Value.ForEach(x => { points.Add(0); });
  387. fieldNameDatas.Where(su => su.Key == sub).First().Value.ForEach(x => { fields.Add(0); });
  388. pointClassTotal.Add(new KeyValuePair<string, List<double>>(sub, points));
  389. fieldClassTotal.Add(new KeyValuePair<string, List<double>>(sub, fields));
  390. });
  391. /*List<Student> stus = new List<Student>();
  392. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<Student>(queryText: $"select c.id,c.name,c.no from c where c.classId = '{classId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{code}") }))
  393. {
  394. stus.Add(item);
  395. }*/
  396. classStudents.ForEach(x =>
  397. {
  398. studentIds.Add(x.id);
  399. x.classId = rGroup.id;
  400. x.className = rGroup.name;
  401. //x.className = examClassResults.FirstOrDefault(e => e.info.id.Equals(rGroup.id)).info.name;
  402. x.gradeId = examClassResults.FirstOrDefault(e => e.info.id.Equals(rGroup.id)).gradeId;
  403. var stu = members.Where(s => s.id == x.id).FirstOrDefault();
  404. if (stu != null)
  405. {
  406. x.nickname = stu.nickname;
  407. x.name = stu.name;
  408. x.no = stu.no;
  409. }
  410. else
  411. {
  412. x.nickname = x.nickname;
  413. x.name = x.id;
  414. x.no = "-";
  415. }
  416. /* //班级得分率
  417. x.csRate = totalAll > 0 ? Math.Round(totalAverage / totalAll,2) : 0;*/
  418. //标准差 介于缺考人员的判定逻辑 多科考试必须多科同时缺考才能算整个评测缺考
  419. int inx = examClassResults.FirstOrDefault(e => e.info.id.Equals(rGroup.id)).studentIds.IndexOf(x.id);
  420. var statu = examClassResults.Where(e => e.info.id.Equals(rGroup.id)).Select(x => x.status).ToList();
  421. bool flag = false;
  422. foreach (var ets in statu) {
  423. if (ets[inx] == 0) {
  424. flag = true;
  425. break;
  426. }
  427. }
  428. if (flag) {
  429. powSum += Math.Pow(x.total - totalAverage, 2);
  430. }
  431. //进线人数
  432. if (x.total >= ipoint)
  433. {
  434. lineCount++;
  435. }
  436. //班级全科的pr
  437. int index = stuTotals.IndexOf(x.total);
  438. //double CPR = stuCount - lostClassCount > 0 ? Math.Floor(100 - (100 * (index + 1) - 50) * 1.0 / (stuCount - lostClassCount)) : 0;
  439. double CPR = 100 - (100 * (index + 1) - 50) / stuCount;
  440. x.cpr = CPR;
  441. x.csort = index + 1;
  442. //班级单科的pr
  443. x.subjects.ForEach(y =>
  444. {
  445. //y.point
  446. var subjectT = classStudents.SelectMany(s => s.subjects).Where(sub => sub.id == y.id).Select(scr => scr.score).ToList();
  447. subjectT.Sort((s1, s2) => { return s2.CompareTo(s1); });
  448. int index = subjectT.IndexOf(y.score);
  449. //double CPR = stuCount - lostClassCount > 0 ? Math.Floor(100 - (100 * (index + 1) - 50) * 1.0 / (stuCount - lostClassCount)) : 0;
  450. double CPR = 100 - (100 * (index + 1) - 50) / stuCount;
  451. y.cpr = CPR;
  452. y.csort = index + 1;
  453. //按科目获取一个班的分数
  454. keyValues.Add(new KeyValuePair<string, double>(y.id, y.score));
  455. var pintTalt = pointClassTotal.Where(su => su.Key == y.id).Select(pint => pint.Value).First();
  456. for (int i = 0; i < y.point.Count; i++)
  457. {
  458. pintTalt[i] = pintTalt[i] + y.point[i];
  459. }
  460. var fieldTalt = fieldClassTotal.Where(su => su.Key == y.id).Select(pint => pint.Value).First();
  461. for (int i = 0; i < y.fieldPoint.Count; i++)
  462. {
  463. fieldTalt[i] = fieldTalt[i] + y.fieldPoint[i];
  464. }
  465. });
  466. });
  467. var pow = stuCount - lostClassCount > 0 ? Math.Pow(powSum / (stuCount - lostClassCount), 0.5) : 0;
  468. //var pow = Math.Pow(powSum / stuCount, 0.5);
  469. ClassAys classAys = new ClassAys
  470. {
  471. gradeId = examClassResults.FirstOrDefault(e => e.info.id.Equals(rGroup.id)).gradeId ?? "",
  472. year = rGroup.year,
  473. studentIds = studentIds,
  474. stuCount = stuCount,
  475. classId = rGroup.id,
  476. csRate = totalAll > 0 ? Math.Round(totalAverage / totalAll * 100, 2) : 0,
  477. className = rGroup.name,
  478. totalAverage = totalAverage,
  479. lineCount = lineCount,
  480. standardDeviation = Math.Round(pow,2)
  481. };
  482. foreach (var key in paperScore.Keys)
  483. {
  484. var subScore = keyValues.Where(x => x.Key.Equals(key)).Select(x => x.Value).ToList();
  485. //计算及格率
  486. int passCount = 0;
  487. double passScore = paperScore[key] * 0.6;
  488. subScore.ForEach(x =>
  489. {
  490. if (x > passScore)
  491. {
  492. passCount += 1;
  493. }
  494. });
  495. double passPercent = stuCount - lostClassCount > 0 ? Math.Round(passCount * 1.0 / (stuCount - lostClassCount), 2) : 0;
  496. //double passPercent = Math.Round(passCount * 1.0 / stuCount,2) ;
  497. double average = stuCount - lostClassCount > 0 ? Math.Round(subScore.Sum() * 1.0 / (stuCount - lostClassCount), 2) : 0;
  498. //double average = Math.Round(subScore.Sum() * 1.0 / stuCount,2) ;
  499. List<double> tt = new List<double>();
  500. List<double> fieldPoints = new List<double>();
  501. var pp = pointClassTotal.Where(su => su.Key == key).Select(pint => pint.Value).First();
  502. pp.ForEach(s =>
  503. {
  504. tt.Add(stuCount - lostClassCount > 0 ? Math.Round(s * 1.0 / (stuCount - lostClassCount), 2) : 0);
  505. });
  506. var ff = fieldClassTotal.Where(su => su.Key == key).Select(pint => pint.Value).First();
  507. ff.ForEach(s =>
  508. {
  509. fieldPoints.Add(stuCount - lostClassCount > 0 ? Math.Round(s * 1.0 / (stuCount - lostClassCount), 2) : 0);
  510. });
  511. double val = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).standard;
  512. List<double> krate = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).krate;
  513. List<int> phc = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).phc;
  514. List<int> plc = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).plc;
  515. List<int> pc = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).pc;
  516. List<double> frate = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).frate;
  517. List<int> fphc = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).fphc;
  518. List<int> fplc = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).fplc;
  519. List<int> fpc = examClassResults.FirstOrDefault(c => c.subjectId == key && c.info.id == rGroup.id).fpc;
  520. classAys.subjects.Add(new AysSubject
  521. {
  522. point = tt,
  523. field = fieldPoints,
  524. id = key,
  525. passPercent = passPercent,
  526. passCount = passCount,
  527. average = average,
  528. standard = val,
  529. krate = krate,
  530. phc = phc,
  531. plc = plc,
  532. pc = pc,
  533. frate = frate,
  534. fphc = fphc,
  535. fplc = fplc,
  536. fpc = fpc,
  537. sRate = paperScore[key] > 0 ? Math.Round(average / paperScore[key] * 100, 2) : 0,
  538. name = info.subjects.Where(x => x.id == key).FirstOrDefault().name,
  539. item = classSubjectPaperDatas.Where(subd => subd.Key == key).First().Value.Where(cls => cls.Key == rGroup.id).First().Value
  540. });
  541. }
  542. classes.Add(classAys);
  543. }
  544. //处理年级
  545. var tgrades = classes.GroupBy(x => x.year).Select(x => x.Key).OrderBy(c => c).ToList();
  546. int n = 0;
  547. if (tgrades.Count > 0)
  548. {
  549. if (info.grades.Count > 0) {
  550. foreach (var greade in tgrades)
  551. {
  552. string gid = info.grades.Count > 0 ? info.grades[n].id ?? "-" : "-";
  553. var clases = classes.Where(x => x.year.Equals(greade));
  554. var classCount = clases.Count();
  555. var stu = clases.SelectMany(x => x.studentIds).ToList();
  556. var lineCount = clases.Select(x => x.lineCount).Sum();
  557. var totalAverage = clases.Select(x => x.totalAverage).Sum() * 1.0 / classCount;
  558. GradeAys gradeAys = new GradeAys
  559. {
  560. gradeId = gid,
  561. studentIds = stu,
  562. gradeName = info.grades.Count > 0 ? info.grades[n].name ?? "-" : "-",
  563. stuCount = stu.Count,
  564. lineCount = lineCount,
  565. totalAverage = totalAverage,
  566. };
  567. foreach (var key in paperScore.Keys)
  568. {
  569. var AysSubject = clases.SelectMany(c => c.subjects).Where(x => x.id.Equals(key)).Select(x => x).ToList();
  570. var passCount = AysSubject.Select(x => x.passCount).Sum();
  571. var average = Math.Round(AysSubject.Select(x => x.average).Sum() * 1.0 / classCount);
  572. var passPercent = stu.Count > 0 ? Math.Round(passCount * 1.0 / stu.Count, 2) : 0;
  573. //var passPercent = Math.Round(passCount * 1.0 / stu.Count,2);
  574. AysSubject subject = new AysSubject
  575. {
  576. id = key,
  577. passCount = passCount,
  578. passPercent = passPercent,
  579. average = average,
  580. name = info.subjects.Where(x => x.id == key).FirstOrDefault().name,
  581. item = gscores.Where(x => x.Key == key).FirstOrDefault().Value.Where(cls => cls.Key == gid).FirstOrDefault().Value
  582. };
  583. gradeAys.subjects.Add(subject);
  584. }
  585. grades.Add(gradeAys);
  586. //处理学生年级相关的pr值
  587. var studentAys = students;
  588. int lostGrade = 0;
  589. if (!gid.Equals("-")) {
  590. studentAys = students.Where(x => x.gradeId != null && x.gradeId.Equals(gid)).ToList();
  591. lostGrade = examClassResults.Where(x => x.gradeId.Equals(gid)).SelectMany(y => y.status).Where (r => r == 1).ToList().Count;
  592. }
  593. var stuGradeTotal = studentAys.Select(x => x.total).ToList();
  594. stuGradeTotal.Sort((s1, s2) => { return s2.CompareTo(s1); });
  595. var stuCount = stuGradeTotal.Count;
  596. studentAys.ForEach(x =>
  597. {
  598. //年级全科的pr
  599. int index = stuGradeTotal.IndexOf(x.total);
  600. //double GPR = stuCount - lostGrade > 0 ? Math.Floor(100 - (100 * (index + 1) - 50) * 1.0 / (stuCount - lostGrade)) : 0;
  601. double GPR = 100 - (100 * (index + 1) - 50) / stuCount;
  602. x.gpr = GPR;
  603. x.gsort = index + 1;
  604. //年级单科的pr
  605. x.subjects.ForEach(y =>
  606. {
  607. var subjectT = studentAys.SelectMany(s => s.subjects).Where(sub => sub.id == y.id).Select(scr => scr.score).ToList();
  608. subjectT.Sort((s1, s2) => { return s2.CompareTo(s1); });
  609. int index = subjectT.IndexOf(y.score);
  610. //double GPR = stuCount- lostGrade > 0 ? Math.Floor(100 - (100 * (index + 1) - 50) * 1.0 / (stuCount - lostGrade)) : 0;
  611. double GPR = 100 - (100 * (index + 1) - 50) / stuCount;
  612. y.gpr = GPR;
  613. y.gsort = index + 1;
  614. });
  615. });
  616. n++;
  617. }
  618. }
  619. }
  620. subjectScatter.ForEach(x =>
  621. {
  622. string subjectId = x.Key;
  623. x.Value.ForEach(s =>
  624. {
  625. string stuId = s.Key;
  626. var data = s.Value;
  627. var stu = students.Where(stu => stu.id == stuId).First();
  628. students.Where(stu => stu.id == stuId).First().subjects.Where(sub => sub.id == subjectId).ToList().ForEach(sc =>
  629. {
  630. //处理阵列的索引1的班级名称
  631. data[1] = stu.className;
  632. sc.scatter = data;
  633. //data[3] = sc.sRate.ToString();
  634. //sc.sRate = double.Parse(data[3]);
  635. });
  636. });
  637. });
  638. }
  639. catch (Exception ex)
  640. {
  641. await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/process()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  642. }
  643. var sub = examResults.Select(e => new
  644. {
  645. e.id,
  646. info.subjects.FirstOrDefault(c => c.id == e.id).name,
  647. e.record,
  648. e.phc,
  649. e.plc,
  650. e.sRate,
  651. e.average,
  652. e.standard
  653. });
  654. /*var sub = info.subjects.Select(x => new
  655. {
  656. id = x.id,
  657. name = x.name,
  658. record = examResults.FirstOrDefault(c => c.id == x.id).record,
  659. phc = examResults.FirstOrDefault(c => c.id == x.id).phc,
  660. plc = examResults.FirstOrDefault(c => c.id == x.id).plc,
  661. sRate = examResults.FirstOrDefault(c => c.id == x.id).sRate,
  662. average = examResults.FirstOrDefault(c => c.id == x.id).average,
  663. standard = examResults.FirstOrDefault(c => c.id == x.id).standard
  664. });*/
  665. var subAll = new { info.sRate, info.average, info.standard, total = info.stuCount,lost = info.lostStu.Count };
  666. return Ok(new
  667. {
  668. students,
  669. classes,
  670. grades,
  671. paper = subjectPaperDatas,
  672. subjects = sub,
  673. scatterKey,
  674. paperKey,
  675. pointLevelKey = valuePairs,
  676. ipoint,
  677. touchScore = touch,
  678. knowKey = knowkey,
  679. wrongKey = keynowWrong,
  680. wrong = wrongDatas,
  681. knowName = knowNameDatas,
  682. knowPer = knowPerDatas,
  683. knowAllper = knowAllPerDatas,
  684. fieldwrong = fieldwrongDatas,
  685. fieldName = fieldNameDatas,
  686. fieldPer = fieldPerDatas,
  687. fieldAllPer = fieldAllPerDatas,
  688. kScores = knowScoreDatas,
  689. fScores = fieldScoreDatas,
  690. all = subAll
  691. });
  692. }
  693. private static (KeyValuePair<string, List<List<string>>>, KeyValuePair<string, List<KeyValuePair<string, List<double>>>>, Dictionary<string, List<double>>) DoExerciseScatteres(ExamResult e, List<string> paperKey)
  694. {
  695. List<int> examAnswer = new List<int>();
  696. List<string> examPersent = new List<string>();
  697. for (int n = 0; n < e.paper.point.Count; n++)
  698. {
  699. examAnswer.Add(0);
  700. }
  701. //参考人数
  702. double Qnum = 0;
  703. e.studentIds.ForEach(i =>
  704. {
  705. if (!i.Equals("0"))
  706. {
  707. Qnum++;
  708. }
  709. });
  710. List<List<string>> datas = new List<List<string>>();
  711. List<string[]> itemAnalysis = new List<string[]>();
  712. Dictionary<string, List<int>> gradeItemScore = new Dictionary<string, List<int>>();
  713. Dictionary<string, int> gradeItemStuCount = new Dictionary<string, int>();
  714. List<KeyValuePair<string, List<double>>> classdatas = new List<KeyValuePair<string, List<double>>>();
  715. try
  716. {
  717. e.classes.ForEach(c =>
  718. {
  719. //初始化每题得分情况
  720. List<int> answerCount = new List<int>();
  721. List<double> persent = new List<double>();
  722. int peopleCount = 0;
  723. for (int n = 0; n < e.paper.point.Count; n++)
  724. {
  725. answerCount.Add(0);
  726. }
  727. int qCount = 0;
  728. //每个班级得分占比
  729. for (int i = c.range[0]; i <= c.range[1]; i++)
  730. {
  731. if (e.studentScores[i].Sum() > 0)
  732. {
  733. for (int j = 0; j < e.studentScores[i].Count; j++)
  734. {
  735. if (e.studentScores[i][j] > 0)
  736. {
  737. //记录班级每题得分数
  738. answerCount[j] = answerCount[j] + 1;
  739. //记录年级每题得分数
  740. examAnswer[j] = examAnswer[j] + 1;
  741. }
  742. }
  743. }
  744. else
  745. {
  746. qCount++;
  747. }
  748. peopleCount = c.range[1] - c.range[0] + 1 - qCount;
  749. }
  750. foreach (int p in answerCount)
  751. {
  752. var t = peopleCount > 0 ? Math.Round(p * 1.0 / peopleCount * 100, 2) : 0;
  753. //var t = Math.Round(p * 1.0 / peopleCount * 100,2);
  754. persent.Add(t);
  755. }
  756. classdatas.Add(new KeyValuePair<string, List<double>>(c.id, persent));
  757. if (!string.IsNullOrEmpty(c.gradeId))
  758. {
  759. if (gradeItemScore.ContainsKey(c.gradeId))
  760. {
  761. var we = gradeItemScore[c.gradeId];
  762. List<int> count = we;
  763. for (int index = 0; index < count.Count; index++)
  764. {
  765. count[index] = count[index] + answerCount[index];
  766. }
  767. gradeItemScore[c.gradeId] = count;
  768. // gradeItemScore[c.gradeId].ForEach(x => { x = x + answerCount[index]; index += 1; });
  769. gradeItemStuCount[c.gradeId] = gradeItemStuCount[c.gradeId] + peopleCount;
  770. }
  771. else
  772. {
  773. gradeItemScore.Add(c.gradeId, answerCount);
  774. gradeItemStuCount.Add(c.gradeId, peopleCount);
  775. }
  776. }
  777. });
  778. double[] point = StringHelper.ListTodouble(e.paper.point);
  779. List<string> stus = e.studentIds.Except(e.lostStus).ToList();
  780. List<List<double>> etuScores = new();
  781. foreach (string stu in stus) {
  782. int index = e.studentIds.IndexOf(stu);
  783. etuScores.Add(e.studentScores[index]);
  784. }
  785. double[,] result = StringHelper.ListToDouble(etuScores);
  786. var cdm = new ClouDASMatrix(result, point);
  787. //试题Y
  788. List<double> answer = cdm.AnswerRate;
  789. //试题X
  790. List<double> quality = cdm.QualityRate;
  791. //试题区域
  792. List<string> topic = cdm.TopicFallArea;
  793. //试题相关分析结果
  794. List<(double Diff, double D, double R0,double R1, double R2, double R3, double R4, double R5, double R6, double PH, double PL)> rs = cdm.RS;
  795. for (int i = 0; i < rs.Count; i++)
  796. {
  797. string[] ex = new string[] { };
  798. string ss = rs[i].ToString()[1..^1];
  799. ex = ss.Split(",");
  800. itemAnalysis.Add(ex);
  801. }
  802. foreach (int p in examAnswer)
  803. {
  804. var t = Qnum > 0 ? Math.Round(p * 1.0 / Qnum * 100, 2) : 0;
  805. //var t = Math.Round(p * 1.0 / Qnum * 100,2);
  806. examPersent.Add(t.ToString());
  807. }
  808. for (int k = 0; k < e.paper.point.Count; k++)
  809. {
  810. List<string> values = new List<string>();
  811. paperKey.ForEach(x =>
  812. {
  813. values.Add("-");
  814. });
  815. values[0] = (k + 1).ToString();
  816. if (e.paper.type.Count > 0)
  817. {
  818. values[1] = e.paper.type[k].ToString();
  819. }
  820. else
  821. {
  822. values[1] = "";
  823. }
  824. values[2] = topic[k].ToString();
  825. values[3] = e.paper.point[k].ToString();
  826. /* List<string> sk = new List<string>();
  827. foreach (string kl in e.paper.knowledge[k]) {
  828. sk.Add(kl);
  829. }*/
  830. values[22] = string.Join(",", e.paper.knowledge[k]);
  831. if (itemAnalysis.Count > 0)
  832. {
  833. values[4] = itemAnalysis[k][0].Trim();
  834. values[5] = itemAnalysis[k][1].Trim();
  835. values[6] = itemAnalysis[k][2].Trim();
  836. values[12] = itemAnalysis[k][3].Trim();
  837. values[13] = itemAnalysis[k][4].Trim();
  838. values[14] = itemAnalysis[k][5].Trim();
  839. values[15] = itemAnalysis[k][6].Trim();
  840. values[16] = itemAnalysis[k][7].Trim();
  841. values[17] = itemAnalysis[k][8].Trim();
  842. values[18] = itemAnalysis[k][9].Trim();
  843. values[19] = itemAnalysis[k][10].Trim();
  844. }
  845. else
  846. {
  847. values[4] = "0";
  848. values[5] = "0";
  849. values[6] = "0";
  850. values[12] = "0";
  851. values[13] = "0";
  852. values[14] = "0";
  853. values[15] = "0";
  854. values[16] = "0";
  855. values[17] = "0";
  856. values[18] = "0";
  857. values[19] = "0";
  858. }
  859. Dictionary<string, double> its = new Dictionary<string, double>();
  860. classdatas.ForEach(cls => { its.Add(cls.Key, cls.Value[k]); });
  861. StringBuilder classBuilder = new StringBuilder();
  862. foreach (var key in its.Keys)
  863. {
  864. classBuilder.Append(key + ":" + its[key] + ",");
  865. }
  866. var cstr = classBuilder.ToString();
  867. values[7] = cstr[..^1];
  868. StringBuilder gradeBuilder = new StringBuilder();
  869. //处理年级的这个题的得分
  870. foreach (var key in gradeItemScore.Keys)
  871. {
  872. var data = gradeItemStuCount[key] > 0 ? Math.Round(gradeItemScore[key][k] * 1.0 / gradeItemStuCount[key] * 100, 2) : 0;
  873. //var data = Math.Round(gradeItemScore[key][k] * 1.0 / gradeItemStuCount[key] * 100, 2);
  874. gradeBuilder.Append(key + ":" + data + ",");
  875. }
  876. var gstr = gradeBuilder.ToString();
  877. values[8] = string.IsNullOrEmpty(gstr) ? "-" : gstr.Substring(0, gstr.Length - 1);
  878. values[20] = quality[k].ToString();
  879. values[21] = answer[k].ToString();
  880. // string pointName = "";
  881. values[23] = examPersent[k];
  882. datas.Add(values);
  883. }
  884. Dictionary<string, List<double>> dict = new Dictionary<string, List<double>>();
  885. //处理年级的这个题的得分
  886. foreach (var key in gradeItemScore.Keys)
  887. {
  888. List<double> gscores = new List<double>();
  889. gradeItemScore[key].ForEach(x =>
  890. {
  891. var data = gradeItemStuCount[key] > 0 ? Math.Round(x * 1.0 / gradeItemStuCount[key] * 100, 2) : 0;
  892. //var data = Math.Round(x * 1.0 / gradeItemStuCount[key] * 100, 2);
  893. gscores.Add(data);
  894. });
  895. dict.TryAdd(key, gscores);
  896. }
  897. KeyValuePair<string, List<List<string>>> keyValue = new(e.subjectId, datas);
  898. KeyValuePair<string, List<KeyValuePair<string, List<double>>>> classdata = new(e.subjectId, classdatas);
  899. return (keyValue, classdata, dict);
  900. }
  901. catch (Exception ex)
  902. {
  903. // throw new BizException(ex.Message);
  904. }
  905. return (default, default, default);
  906. }
  907. //落点分析
  908. private KeyValuePair<string, List<KeyValuePair<string, List<string>>>> DoSubjectScatter(ExamResult e)
  909. {
  910. List<KeyValuePair<string, List<string>>> datas = new List<KeyValuePair<string, List<string>>>();
  911. double[] point = StringHelper.ListTodouble(e.paper.point);
  912. double[,] result = StringHelper.ListToDouble(e.studentScores);
  913. try
  914. {
  915. var cdm = new ClouDASMatrix(result, point);
  916. //学生通过率
  917. List<double> pass = cdm.ScoringRate;
  918. //学生稳定度
  919. List<double> sta = cdm.StabilityRate;
  920. //落点区域
  921. List<string> stu = cdm.StuFallArea;
  922. //需努力的题型
  923. List<int[]> strive = cdm.StriveTopic;
  924. //需小心的题型
  925. List<int[]> careful = cdm.CarefulTopic;
  926. int i = 0;
  927. for (int k = e.studentIds.Count - 1; k >= 0; k--)
  928. {
  929. if (e.studentIds[k].Equals("0"))
  930. {
  931. e.studentIds.Remove(e.studentIds[k]);
  932. }
  933. }
  934. e.studentIds.ForEach(s =>
  935. {
  936. /* if (e.studentScores[i].Sum() != 0)
  937. {*/
  938. List<string> info = new List<string>
  939. {
  940. s,
  941. "-",
  942. sta[i] > 1 ? "1" : sta[i].ToString(),
  943. pass[i].ToString(),
  944. i + 1 + "",
  945. Math.Round(e.studentScores[i].Sum(),2).ToString()
  946. };
  947. int right = 0;
  948. int wrong = 0;
  949. foreach (int p in e.studentScores[i])
  950. {
  951. if (p > 0)
  952. {
  953. right++;
  954. }
  955. else
  956. {
  957. wrong++;
  958. }
  959. }
  960. info.Add(right + "");
  961. info.Add(wrong + "");
  962. int[] str = strive[i];
  963. string striveAll = "";
  964. foreach (int n in str)
  965. {
  966. striveAll += n.ToString() + ",";
  967. }
  968. int[] care = careful[i];
  969. string careAll = "";
  970. foreach (int n in care)
  971. {
  972. careAll += n.ToString() + ",";
  973. }
  974. if (string.IsNullOrEmpty(striveAll))
  975. {
  976. info.Add("-");
  977. }
  978. else
  979. {
  980. info.Add(striveAll.Substring(0, striveAll.Length - 1));
  981. }
  982. if (string.IsNullOrEmpty(careAll))
  983. {
  984. info.Add("-");
  985. }
  986. else
  987. {
  988. info.Add(careAll.Substring(0, careAll.Length - 1)); ;
  989. }
  990. info.Add(stu[i].ToString());
  991. KeyValuePair<string, List<string>> keyValue = new KeyValuePair<string, List<string>>(s, info);
  992. datas.Add(keyValue);
  993. //}
  994. i++;
  995. });
  996. return new KeyValuePair<string, List<KeyValuePair<string, List<string>>>>(e.subjectId, datas);
  997. }
  998. catch (Exception ex)
  999. {
  1000. BadRequest(ex.Message + ex.StackTrace);
  1001. Console.WriteLine("---------------------" + ex.Message + "--------------------------");
  1002. }
  1003. return default;
  1004. }
  1005. private static (KeyValuePair<string, List<string>>, KeyValuePair<string, List<string>>, KeyValuePair<string, List<double>>, KeyValuePair<string, List<double>>, KeyValuePair<string, List<List<string>>>, KeyValuePair<string, List<KeyValuePair<string, List<double>>>>) DoKnowledgePoint(ExamResult exam, ExamInfo info, List<string> keynowWrong)
  1006. {
  1007. HashSet<string> knowledge = new HashSet<string>();
  1008. //HashSet<string> area = new HashSet<string>();
  1009. List<double> point = new List<double>();
  1010. List<List<double>> result = new List<List<double>>();
  1011. List<ClassRange> classes = new List<ClassRange>();
  1012. //List<string> ids = new List<string>();
  1013. List<KeyValuePair<string, List<double>>> datas = new List<KeyValuePair<string, List<double>>>();
  1014. //求单个知识点所占分数
  1015. List<string> per = new List<string>();
  1016. //List<string> gper = new List<string>();
  1017. //List<string> knowPer = new List<string>();
  1018. //Dictionary<string, object> wrongMap = new Dictionary<string, object>();
  1019. List<List<string>> wrongPersent = new List<List<string>>();
  1020. //定位试卷信息
  1021. int index = 0;
  1022. foreach (ExamSubject subject in info.subjects)
  1023. {
  1024. if (subject.id.Equals(exam.subjectId))
  1025. {
  1026. break;
  1027. }
  1028. else
  1029. {
  1030. index++;
  1031. }
  1032. }
  1033. if (info.papers[index].knowledge != null && info.papers[index].knowledge.Count > 0)
  1034. {
  1035. info.papers[index].knowledge.ForEach(k =>
  1036. {
  1037. k.ForEach(e =>
  1038. {
  1039. knowledge.Add(e);
  1040. });
  1041. });
  1042. }
  1043. else
  1044. {
  1045. return (default, default, default, default, default, default);
  1046. }
  1047. point = info.papers[index].point;
  1048. result = exam.studentScores;
  1049. classes = exam.classes;
  1050. //ids = exam.studentIds;
  1051. //确定高分组 低分组人数
  1052. //List<List<double>> re = exam.studentScores;
  1053. /* List<double> resultSum = new List<double>();
  1054. foreach (List<double> data in re)
  1055. {
  1056. resultSum.Add(data.Sum());
  1057. }*/
  1058. //确定高分组 最低分数
  1059. double[] points = StringHelper.ListTodouble(exam.paper.point);
  1060. double[,] scs = StringHelper.ListToDouble(exam.studentScores);
  1061. var cdm = new ClouDASMatrix(scs, points);
  1062. //scores.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1063. int rhwCount = cdm.SH.Count();
  1064. double rhw = cdm.SH.LastOrDefault().Item2;
  1065. int rhlCount = cdm.SL.Count();
  1066. double rhl = cdm.SL.FirstOrDefault().Item2;
  1067. /* resultSum.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1068. int rhwCount = 0;
  1069. double rhw = 0;
  1070. int rhlCount = 0;
  1071. double rhl = 0;
  1072. if (resultSum.Count > 3)
  1073. {
  1074. rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
  1075. rhw = rhwCount > 0 ? resultSum[rhwCount - 1] : 0;
  1076. rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
  1077. rhl = rhlCount > 0 ? resultSum[rhlCount] : 0;
  1078. }
  1079. else {
  1080. rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
  1081. rhw = rhwCount > 0 ? resultSum[rhwCount] : 0;
  1082. rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
  1083. rhl = rhlCount > 0 ? resultSum[rhlCount-1] : 0;
  1084. } */
  1085. List<string> knowledgeName = new List<string>();
  1086. foreach (string cla in knowledge)
  1087. {
  1088. knowledgeName.Add(cla);
  1089. }
  1090. for (int k = 0; k < knowledgeName.Count; k++)
  1091. {
  1092. if (null == knowledgeName[k])
  1093. {
  1094. knowledgeName.Remove(knowledgeName[k]);
  1095. }
  1096. }
  1097. //初始化年级总分
  1098. double total = 0;
  1099. //处理年级单个知识点得分率
  1100. foreach (List<double> grade in result)
  1101. {
  1102. total += grade.Sum();
  1103. }
  1104. //试卷总分
  1105. double TotalPoint = point.Sum();
  1106. List<double> knowScore = new List<double>();
  1107. //得分率
  1108. List<double> Score = new List<double>();
  1109. //分值
  1110. List<double> kScore = new List<double>();
  1111. for (int k = 0; k < knowledgeName.Count; k++)
  1112. {
  1113. double OnePoint = 0;
  1114. List<string> valuew = new List<string>();
  1115. List<string> itemNo = new List<string>();
  1116. keynowWrong.ForEach(x =>
  1117. {
  1118. valuew.Add("-");
  1119. });
  1120. valuew[0] = knowledgeName[k];
  1121. int n = 0;
  1122. int wrong = 0;
  1123. int rhwC = 0;
  1124. int rhlC = 0;
  1125. double scores = 0;
  1126. //知识点分值
  1127. double gPoint = 0;
  1128. info.papers[index].knowledge.ForEach(kno =>
  1129. {
  1130. if (kno.Contains(knowledgeName[k]))
  1131. {
  1132. var itemPersent = kno.Count > 0 ? 1 / Convert.ToDouble(kno.Count) : 0;
  1133. OnePoint += point[n] * itemPersent;
  1134. itemNo.Add((n + 1).ToString());
  1135. //处理单个知识点错题人数
  1136. int phCount = 0;
  1137. int plCount = 0;
  1138. foreach (string id in exam.studentIds)
  1139. {
  1140. int index = exam.studentIds.IndexOf(id);
  1141. if (exam.studentScores[index][n] == 0)
  1142. {
  1143. wrong++;
  1144. if (exam.studentScores[index].Sum() >= rhw && phCount < rhwCount)
  1145. {
  1146. rhwC++;
  1147. phCount++;
  1148. continue;
  1149. }
  1150. if (exam.studentScores[index].Sum() <= rhl && plCount < (exam.studentIds.Count - rhlCount))
  1151. {
  1152. rhlC++;
  1153. plCount++;
  1154. continue;
  1155. }
  1156. continue;
  1157. }
  1158. else
  1159. {
  1160. //单个知识点得分情况
  1161. scores += exam.studentScores[index][n] * itemPersent;
  1162. //scoreCount++;
  1163. }
  1164. /*if (exam.studentScores[index].Sum() >= rhw && phCount < rhwCount)
  1165. {
  1166. rhwC++;
  1167. phCount++;
  1168. continue;
  1169. }
  1170. if (exam.studentScores[index].Sum() <= rhl && plCount < (exam.studentIds.Count - rhlCount))
  1171. {
  1172. rhlC++;
  1173. plCount++;
  1174. continue;
  1175. }*/
  1176. }
  1177. gPoint += point[n];
  1178. }
  1179. valuew[1] = OnePoint.ToString();
  1180. string itemNos = "";
  1181. if (itemNo.Count > 0)
  1182. {
  1183. valuew[2] = string.Join(",", itemNo);
  1184. /*foreach (string np in itemNo)
  1185. {
  1186. itemNos += np + ",";
  1187. }
  1188. valuew[2] = itemNos[0..^1];*/
  1189. }
  1190. else
  1191. {
  1192. valuew[2] = itemNos;
  1193. }
  1194. n++;
  1195. });
  1196. kScore.Add(gPoint);
  1197. Score.Add(scores);
  1198. knowScore.Add(OnePoint);
  1199. //该知识点平均得分
  1200. double sc = (exam.studentIds.Count - exam.lostStus.Count) > 0 ? Math.Round(scores * 1.0 / (exam.studentIds.Count - exam.lostStus.Count), 2) : 0;
  1201. //错题关系表
  1202. valuew[3] = (OnePoint > 0 ? Math.Round(sc / OnePoint, 2) : 0).ToString(); ;
  1203. valuew[4] = wrong.ToString();
  1204. valuew[5] = rhwC.ToString();
  1205. valuew[6] = rhlC.ToString();
  1206. wrongPersent.Add(valuew);
  1207. //知识点占比
  1208. double persent = TotalPoint > 0 ? OnePoint / TotalPoint : 0;
  1209. //double persent = OnePoint / TotalPoint;
  1210. per.Add(persent.ToString("0.00"));
  1211. }
  1212. //本次考试知识点占比
  1213. List<double> allPer = new List<double>();
  1214. foreach (double sc in Score)
  1215. {
  1216. allPer.Add(exam.studentIds.Count > 0 ? Math.Round(sc * 1.0 / exam.studentIds.Count, 2) : 0);
  1217. }
  1218. int stuNo = 0;
  1219. exam.studentIds.ForEach(e =>
  1220. {
  1221. List<double> valueKnow = new List<double>();
  1222. foreach (string know in knowledge)
  1223. {
  1224. double anwPoint = 0;
  1225. double itemPersent = 0;
  1226. int sno = 0;
  1227. info.papers[index].knowledge.ForEach(kno =>
  1228. {
  1229. if (kno.Contains(know))
  1230. {
  1231. //当前知识点在该题占比多少
  1232. itemPersent = kno.Count > 0 ? 1 / Convert.ToDouble(kno.Count) : 0;
  1233. //itemPersent = 1 / Convert.ToDouble(kno.Count);
  1234. anwPoint += result[stuNo][sno] * itemPersent;
  1235. }
  1236. sno++;
  1237. });
  1238. valueKnow.Add(anwPoint);
  1239. }
  1240. KeyValuePair<string, List<double>> keyValue = new KeyValuePair<string, List<double>>(e, valueKnow);
  1241. datas.Add(keyValue);
  1242. stuNo++;
  1243. });
  1244. KeyValuePair<string, List<string>> key1 = new KeyValuePair<string, List<string>>(exam.subjectId, knowledgeName);
  1245. KeyValuePair<string, List<string>> key2 = new KeyValuePair<string, List<string>>(exam.subjectId, per);
  1246. KeyValuePair<string, List<double>> key3 = new KeyValuePair<string, List<double>>(exam.subjectId, allPer);
  1247. KeyValuePair<string, List<double>> key4 = new KeyValuePair<string, List<double>>(exam.subjectId, kScore);
  1248. KeyValuePair<string, List<List<string>>> keyValue = new KeyValuePair<string, List<List<string>>>(exam.subjectId, wrongPersent);
  1249. KeyValuePair<string, List<KeyValuePair<string, List<double>>>> valuePair = new KeyValuePair<string, List<KeyValuePair<string, List<double>>>>(exam.subjectId, datas);
  1250. return (key1, key2, key3, key4, keyValue, valuePair);
  1251. }
  1252. private static (KeyValuePair<string, List<int>>, KeyValuePair<string, List<string>>, KeyValuePair<string, List<double>>, KeyValuePair<string, List<double>>, KeyValuePair<string, List<List<string>>>, KeyValuePair<string, List<KeyValuePair<string, List<double>>>>) DoLevel(ExamResult exam, ExamInfo info, List<string> keynowWrong)
  1253. {
  1254. List<double> point = new List<double>();
  1255. List<List<double>> result = new List<List<double>>();
  1256. List<ClassRange> classes = new List<ClassRange>();
  1257. List<KeyValuePair<string, List<double>>> datas = new List<KeyValuePair<string, List<double>>>();
  1258. //求单个认知层次所占分数
  1259. List<string> per = new List<string>();
  1260. List<List<string>> wrongPersent = new List<List<string>>();
  1261. List<int> knowledgeName = new List<int>();
  1262. //定位试卷信息
  1263. int index = 0;
  1264. foreach (ExamSubject subject in info.subjects)
  1265. {
  1266. if (subject.id.Equals(exam.subjectId))
  1267. {
  1268. break;
  1269. }
  1270. else
  1271. {
  1272. index++;
  1273. }
  1274. }
  1275. knowledgeName.Add(1);
  1276. knowledgeName.Add(2);
  1277. knowledgeName.Add(3);
  1278. knowledgeName.Add(4);
  1279. knowledgeName.Add(5);
  1280. knowledgeName.Add(6);
  1281. //double Qnum = 0;
  1282. point = info.papers[index].point;
  1283. result = exam.studentScores;
  1284. classes = exam.classes;
  1285. //ids = exam.studentIds;
  1286. //确定高分组 低分组人数
  1287. /*List<List<double>> re = exam.studentScores;
  1288. List<double> resultSum = new List<double>();
  1289. foreach (List<double> data in re)
  1290. {
  1291. resultSum.Add(data.Sum());
  1292. }*/
  1293. double[] points = StringHelper.ListTodouble(exam.paper.point);
  1294. double[,] scs = StringHelper.ListToDouble(exam.studentScores);
  1295. var cdm = new ClouDASMatrix(scs, points);
  1296. //scores.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1297. int rhwCount = cdm.SH.Count();
  1298. double rhw = cdm.SH.LastOrDefault().Item2;
  1299. int rhlCount = cdm.SL.Count();
  1300. double rhl = cdm.SL.FirstOrDefault().Item2;
  1301. //确定高分组 最低分数
  1302. /* resultSum.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1303. int rhwCount = 0;
  1304. double rhw = 0;
  1305. int rhlCount = 0;
  1306. double rhl = 0;
  1307. if (resultSum.Count > 3)
  1308. {
  1309. rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
  1310. rhw = rhwCount > 0 ? resultSum[rhwCount - 1] : 0;
  1311. rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
  1312. rhl = rhlCount > 0 ? resultSum[rhlCount] : 0;
  1313. }
  1314. else
  1315. {
  1316. rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
  1317. rhw = rhwCount > 0 ? resultSum[rhwCount] : 0;
  1318. rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
  1319. rhl = rhlCount > 0 ? resultSum[rhlCount - 1] : 0;
  1320. }*/
  1321. //初始化年级总分
  1322. double total = 0;
  1323. //处理年级单个知识点得分率
  1324. foreach (List<double> grade in result)
  1325. {
  1326. total += grade.Sum();
  1327. }
  1328. //试卷总分
  1329. double TotalPoint = point.Sum();
  1330. List<double> knowScore = new List<double>();
  1331. //得分率
  1332. List<double> Score = new List<double>();
  1333. //分值
  1334. List<double> kScore = new List<double>();
  1335. //List<double> allPer = new List<double>();
  1336. for (int k = 0; k < knowledgeName.Count; k++)
  1337. {
  1338. double OnePoint = 0;
  1339. List<string> valuew = new List<string>();
  1340. List<string> itemNo = new List<string>();
  1341. keynowWrong.ForEach(x =>
  1342. {
  1343. valuew.Add("-");
  1344. });
  1345. valuew[0] = knowledgeName[k].ToString();
  1346. int n = 0;
  1347. int wrong = 0;
  1348. int rhwC = 0;
  1349. int rhlC = 0;
  1350. //int scoreCount = 0;
  1351. double scores = 0;
  1352. //所有认知层次得分
  1353. double anwGPoint = 0;
  1354. double gPoint = 0;
  1355. info.papers[index].field.ForEach(kno =>
  1356. {
  1357. if (kno == knowledgeName[k])
  1358. {
  1359. OnePoint += point[n];
  1360. itemNo.Add((n + 1).ToString());
  1361. //处理认知层次错题人数
  1362. int phCount = 0;
  1363. int plCount = 0;
  1364. foreach (string id in exam.studentIds)
  1365. {
  1366. int index = exam.studentIds.IndexOf(id);
  1367. if (exam.studentScores[index][n] == 0)
  1368. {
  1369. wrong++;
  1370. if (exam.studentScores[index].Sum() >= rhw && phCount < rhwCount)
  1371. {
  1372. rhwC++;
  1373. phCount++;
  1374. continue;
  1375. }
  1376. if (exam.studentScores[index].Sum() <= rhl && plCount < (exam.studentIds.Count - rhlCount))
  1377. {
  1378. rhlC++;
  1379. plCount++;
  1380. continue;
  1381. }
  1382. continue;
  1383. }
  1384. else
  1385. {
  1386. //单个认知层次得分情况
  1387. scores += exam.studentScores[index][n];
  1388. }
  1389. /* if (exam.studentScores[index].Sum() >= rhw && phCount < rhwCount && exam.studentScores[index][n] == 0)
  1390. {
  1391. rhwC++;
  1392. phCount++;
  1393. continue;
  1394. }
  1395. if (exam.studentScores[index].Sum() <= rhl && plCount < (exam.studentIds.Count - rhlCount) && exam.studentScores[index][n] == 0)
  1396. {
  1397. rhlC++;
  1398. plCount++;
  1399. continue;
  1400. }*/
  1401. //anwGPoint += exam.studentScores[index][n];
  1402. }
  1403. gPoint += point[n];
  1404. }
  1405. valuew[1] = OnePoint.ToString();
  1406. string itemNos = "";
  1407. if (itemNo.Count > 0)
  1408. {
  1409. foreach (string np in itemNo)
  1410. {
  1411. itemNos += np + ",";
  1412. }
  1413. valuew[2] = itemNos[0..^1];
  1414. }
  1415. else
  1416. {
  1417. valuew[2] = itemNos;
  1418. }
  1419. n++;
  1420. });
  1421. Score.Add(scores);
  1422. kScore.Add(gPoint);
  1423. knowScore.Add(OnePoint);
  1424. double sc = (exam.studentIds.Count - exam.lostStus.Count) > 0 ? Math.Round(scores * 1.0 / (exam.studentIds.Count - exam.lostStus.Count), 2) : 0;
  1425. //错题关系表
  1426. valuew[3] = (OnePoint > 0 ? Math.Round(sc / OnePoint, 2) : 0).ToString();
  1427. valuew[4] = wrong.ToString();
  1428. valuew[5] = rhwC.ToString();
  1429. valuew[6] = rhlC.ToString();
  1430. wrongPersent.Add(valuew);
  1431. //认知层次占比
  1432. double persent = TotalPoint > 0 ? OnePoint / TotalPoint : 0;
  1433. //allPer.Add(OnePoint > 0 ? Math.Round(sc / OnePoint, 2) : 0);
  1434. per.Add(persent.ToString("0.00"));
  1435. }
  1436. //本次考试认知层次占比
  1437. List<double> allPer = new List<double>();
  1438. foreach (double sc in Score)
  1439. {
  1440. allPer.Add(exam.studentIds.Count > 0 ? Math.Round(sc * 1.0 / exam.studentIds.Count, 2) : 0);
  1441. }
  1442. int stuNo = 0;
  1443. exam.studentIds.ForEach(e =>
  1444. {
  1445. List<double> valueKnow = new List<double>();
  1446. foreach (int know in knowledgeName)
  1447. {
  1448. double anwPoint = 0;
  1449. double itemPersent = 0;
  1450. int sno = 0;
  1451. info.papers[index].field.ForEach(kno =>
  1452. {
  1453. if (kno == know)
  1454. {
  1455. //当前认知层次在该题占比多少
  1456. itemPersent = 1;
  1457. anwPoint += result[stuNo][sno] * itemPersent;
  1458. }
  1459. sno++;
  1460. });
  1461. valueKnow.Add(anwPoint);
  1462. }
  1463. KeyValuePair<string, List<double>> keyValue = new KeyValuePair<string, List<double>>(e, valueKnow);
  1464. datas.Add(keyValue);
  1465. stuNo++;
  1466. });
  1467. KeyValuePair<string, List<int>> key1 = new KeyValuePair<string, List<int>>(exam.subjectId, knowledgeName);
  1468. KeyValuePair<string, List<string>> key2 = new KeyValuePair<string, List<string>>(exam.subjectId, per);
  1469. KeyValuePair<string, List<double>> key3 = new KeyValuePair<string, List<double>>(exam.subjectId, allPer);
  1470. KeyValuePair<string, List<double>> key4 = new KeyValuePair<string, List<double>>(exam.subjectId, kScore);
  1471. KeyValuePair<string, List<List<string>>> keyValue = new KeyValuePair<string, List<List<string>>>(exam.subjectId, wrongPersent);
  1472. KeyValuePair<string, List<KeyValuePair<string, List<double>>>> valuePair = new KeyValuePair<string, List<KeyValuePair<string, List<double>>>>(exam.subjectId, datas);
  1473. return (key1, key2, key3, key4, keyValue, valuePair);
  1474. }
  1475. [ProducesDefaultResponseType]
  1476. [HttpPost("simple")]
  1477. [Authorize(Roles = "IES")]
  1478. [AuthToken(Roles = "teacher,admin")]
  1479. public async Task<IActionResult> simple(JsonElement request)
  1480. {
  1481. //获取评测的ID
  1482. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1483. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1484. try
  1485. {
  1486. List<Dictionary<string, object>> averageMap = new List<Dictionary<string, object>>();
  1487. List<Dictionary<string, object>> averageTotal = new List<Dictionary<string, object>>();
  1488. var client = _azureCosmos.GetCosmosClient();
  1489. //todo 需要检查数据是否存在
  1490. ExamInfo info = new();
  1491. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
  1492. if (response.Status == 200)
  1493. {
  1494. using var cJson = await JsonDocument.ParseAsync(response.ContentStream);
  1495. info = cJson.ToObject<ExamInfo>();
  1496. }
  1497. else {
  1498. return Ok(new { averageMap, averageTotal });
  1499. }
  1500. List<ExamResult> examResults = new List<ExamResult>();
  1501. var query = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes,c.afp,c.akp,c.lostStus from c where c.examId = '{id}' ";
  1502. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
  1503. {
  1504. examResults.Add(item);
  1505. }
  1506. foreach (ExamResult result in examResults)
  1507. {
  1508. List<double> ClassAverage = new List<double>();
  1509. List<ClassSimple> ClassName = new List<ClassSimple>();
  1510. Dictionary<string, object> mapSubject = new Dictionary<string, object>();
  1511. Dictionary<string, object> mapClass = new Dictionary<string, object>();
  1512. int subIndex = 0;
  1513. foreach (var sub in info.subjects)
  1514. {
  1515. if (sub.id.Equals(result.subjectId))
  1516. {
  1517. break;
  1518. }
  1519. else
  1520. {
  1521. subIndex++;
  1522. }
  1523. }
  1524. List<double> points = info.papers[subIndex].point;
  1525. HashSet<string> kn = new HashSet<string>();
  1526. foreach (List<string> know in info.papers[subIndex].knowledge) {
  1527. foreach (string k in know) {
  1528. kn.Add(k);
  1529. }
  1530. }
  1531. List<int> fs = new() { 1,2,3,4,5,6 };
  1532. mapClass.Add("subjectId", result.subjectId);
  1533. foreach (ClassRange range in result.classes)
  1534. {
  1535. ClassSimple classSimple = new()
  1536. {
  1537. id = range.id,
  1538. name = range.name
  1539. };
  1540. ClassName.Add(classSimple);
  1541. double totalClass = 0;
  1542. List<string> counts = new();
  1543. for (int i = range.range[0]; i <= range.range[1]; i++)
  1544. {
  1545. if (result.lostStus.Contains(result.studentIds[i])) {
  1546. counts.Add(result.studentIds[i]);
  1547. continue;
  1548. }
  1549. totalClass += result.studentScores.Count > 0 ? result.studentScores[i].Sum() : 0;
  1550. }
  1551. ClassAverage.Add(range.range[1] - range.range[0] + 1 - counts.Count > 0 ? totalClass * 1.0 / (range.range[1] - range.range[0] + 1 - counts.Count) : 0);
  1552. }
  1553. mapClass.Add("className", ClassName);
  1554. mapClass.Add("ClassAverage", ClassAverage);
  1555. averageMap.Add(mapClass);
  1556. List<double> wn = await getWrongNum(result, points);
  1557. List<double> SubjectTotal = new List<double>();
  1558. foreach (List<double> score in result.studentScores)
  1559. {
  1560. SubjectTotal.Add(score.Sum());
  1561. }
  1562. mapSubject.Add("subjectId", result.subjectId);
  1563. mapSubject.Add("total", SubjectTotal);
  1564. mapSubject.Add("wrongNum", wn);
  1565. mapSubject.Add("akp", result.akp);
  1566. mapSubject.Add("afp", result.afp);
  1567. mapSubject.Add("kn",kn);
  1568. mapSubject.Add("fs", fs);
  1569. averageTotal.Add(mapSubject);
  1570. }
  1571. return Ok(new { averageMap, averageTotal });
  1572. }
  1573. catch (Exception e)
  1574. {
  1575. await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/simple()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1576. return BadRequest();
  1577. }
  1578. }
  1579. private Task<List<double>> getWrongNum(ExamResult result, List<double> points)
  1580. {
  1581. int num = 0;
  1582. List<double> wn = new List<double>();
  1583. foreach (var point in points)
  1584. {
  1585. int wnum = 0;
  1586. double p = point * 0.8;
  1587. foreach (ClassRange range in result.classes)
  1588. {
  1589. for (int i = range.range[0]; i <= range.range[1]; i++)
  1590. {
  1591. //判断推送的数据中,学生正常得分数据
  1592. if (result.studentScores[i].Count > 0)
  1593. {
  1594. if (result.studentScores[i][num] < point)
  1595. {
  1596. if (result.studentScores[i][num] < p)
  1597. {
  1598. wnum++;
  1599. }
  1600. else
  1601. {
  1602. continue;
  1603. }
  1604. }
  1605. else
  1606. {
  1607. continue;
  1608. }
  1609. }
  1610. else
  1611. {
  1612. wnum++;
  1613. }
  1614. }
  1615. }
  1616. wn.Add(wnum);
  1617. num++;
  1618. }
  1619. return Task.FromResult(wn);
  1620. }
  1621. public class ClassSimple
  1622. {
  1623. public string id { get; set; }
  1624. public string name { get; set; }
  1625. }
  1626. [ProducesDefaultResponseType]
  1627. [HttpPost("studentAnalysis")]
  1628. [Authorize(Roles = "IES")]
  1629. [AuthToken(Roles = "teacher,admin,student")]
  1630. public async Task<IActionResult> studentAnalysis(JsonElement request)
  1631. {
  1632. //获取个人或者校本
  1633. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1634. //评测Id
  1635. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1636. if (!request.TryGetProperty("sId", out JsonElement sId)) return BadRequest();
  1637. if (!request.TryGetProperty("cId", out JsonElement cId)) return BadRequest();
  1638. if (!request.TryGetProperty("gId", out JsonElement gId)) return BadRequest();
  1639. try
  1640. {
  1641. List<Dictionary<string, object>> averageMap = new();
  1642. List<Dictionary<string, object>> averageTotal = new();
  1643. List<List<double>> classAllAverage = new();
  1644. School school = new();
  1645. var client = _azureCosmos.GetCosmosClient();
  1646. ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
  1647. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(code.ToString(), new PartitionKey($"Base"));
  1648. if (response.Status == 200)
  1649. {
  1650. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  1651. school = json.ToObject<School>();
  1652. }
  1653. //School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(code.ToString(), new PartitionKey($"Base"));
  1654. List<ExamResult> examResults = new List<ExamResult>();
  1655. var query = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes from c where c.examId = '{id}' ";
  1656. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
  1657. {
  1658. examResults.Add(item);
  1659. }
  1660. if (examResults.Count == 0)
  1661. {
  1662. return Ok(new { code = ResponseCode.DATA_EMPTY_NULL, v = "正在结算中" });
  1663. }
  1664. int indexClass = 0;
  1665. HashSet<string> cla = new HashSet<string>();
  1666. HashSet<string> stu = new HashSet<string>();
  1667. double totalScore = 0;
  1668. List<List<double>> allList = new List<List<double>>();
  1669. double income = 0;
  1670. foreach (Period period in school.period)
  1671. {
  1672. if (info.period.id.Equals(period.id))
  1673. {
  1674. income = period.analysis.income;
  1675. }
  1676. }
  1677. //获取进线人数
  1678. int count = (int)System.Math.Round(info.stuCount * (income / 100.0), MidpointRounding.AwayFromZero);
  1679. foreach (ExamResult result in examResults)
  1680. {
  1681. List<double> ClassAverage = new List<double>();
  1682. List<int> personCount = new List<int>();
  1683. List<string> ClassId = new List<string>();
  1684. Dictionary<string, object> mapClass = new Dictionary<string, object>();
  1685. int index = result.studentIds.IndexOf(sId.ToString());
  1686. //个人总分
  1687. totalScore += result.studentScores[index].Sum();
  1688. mapClass.Add("subjectId", result.subjectId);
  1689. double totalGrade = 0;
  1690. List<double> gradeScores = new List<double>();
  1691. List<List<double>> classScores = new List<List<double>>();
  1692. //此处声明集合存储原本的成绩序列
  1693. List<List<double>> cScores = new List<List<double>>();
  1694. /*var sc = result.classes.GroupBy(m => new { m.gradeId }).Select(c => new { gId = c.Key.gradeId, ranges = c.ToList() }).ToList();
  1695. foreach (var aa in sc)
  1696. {
  1697. foreach (ClassRange range in aa.ranges)
  1698. {
  1699. List<double> scores = new();
  1700. List<double> finalScores = new();
  1701. ClassId.Add(range.id);
  1702. cla.Add(range.id);
  1703. double totalClass = 0;
  1704. for (int i = range.range[0]; i <= range.range[1]; i++)
  1705. {
  1706. totalClass += result.studentScores[i].Sum();
  1707. scores.Add(result.studentScores[i].Sum());
  1708. finalScores.Add(result.studentScores[i].Sum());
  1709. gradeScores.Add(result.studentScores[i].Sum());
  1710. totalGrade += result.studentScores[i].Sum();
  1711. stu.Add(result.studentIds[i]);
  1712. }
  1713. classScores.Add(scores);
  1714. cScores.Add(finalScores);
  1715. ClassAverage.Add(range.range[1] - range.range[0] + 1 > 0 ? Math.Round(totalClass * 1.0 / (range.range[1] - range.range[0] + 1), 2) : 0);
  1716. personCount.Add(range.range[1] - range.range[0] + 1);
  1717. }
  1718. classAllAverage.Add(ClassAverage);
  1719. gradeScores.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1720. indexClass = ClassId.IndexOf(cId.ToString());
  1721. //单科成绩
  1722. allList.Add(cScores[indexClass]);
  1723. classScores[indexClass].Sort((s1, s2) => { return s2.CompareTo(s1); });
  1724. mapClass.Add("scoreSum", result.paper.point.Sum());
  1725. mapClass.Add("score", result.studentScores[index].Sum());
  1726. mapClass.Add("classAverage", ClassAverage[indexClass]);
  1727. mapClass.Add("classCount", personCount[indexClass]);
  1728. mapClass.Add("classRank", classScores[indexClass].IndexOf(result.studentScores[index].Sum()));
  1729. mapClass.Add("gradeAverage", result.studentIds.Count > 0 ? Math.Round(totalGrade * 1.0 / result.studentIds.Count, 2) : 0);
  1730. mapClass.Add("gradeCount", result.studentIds.Count);
  1731. mapClass.Add("gradeRank", gradeScores.IndexOf(result.studentScores[index].Sum()));
  1732. averageMap.Add(mapClass);
  1733. }
  1734. */
  1735. foreach (ClassRange range in result.classes)
  1736. {
  1737. List<double> scores = new List<double>();
  1738. List<double> finalScores = new List<double>();
  1739. ClassId.Add(range.id);
  1740. cla.Add(range.id);
  1741. double totalClass = 0;
  1742. for (int i = range.range[0]; i <= range.range[1]; i++)
  1743. {
  1744. totalClass += result.studentScores[i].Sum();
  1745. scores.Add(result.studentScores[i].Sum());
  1746. finalScores.Add(result.studentScores[i].Sum());
  1747. gradeScores.Add(result.studentScores[i].Sum());
  1748. totalGrade += result.studentScores[i].Sum();
  1749. stu.Add(result.studentIds[i]);
  1750. }
  1751. classScores.Add(scores);
  1752. cScores.Add(finalScores);
  1753. ClassAverage.Add(range.range[1] - range.range[0] + 1 > 0 ? Math.Round(totalClass * 1.0 / (range.range[1] - range.range[0] + 1), 2) : 0);
  1754. personCount.Add(range.range[1] - range.range[0] + 1);
  1755. }
  1756. }
  1757. //处理班级/年级全科均分
  1758. List<double> AllAverage = new List<double>();
  1759. double a = 0;
  1760. for (int k = 0; k < cla.Count; k++)
  1761. {
  1762. for (int i = 0; i < classAllAverage.Count; i++)
  1763. {
  1764. a += classAllAverage[i][k];
  1765. }
  1766. AllAverage.Add(a);
  1767. }
  1768. List<double> classScore = new List<double>();
  1769. for (int i = 0; i < allList[0].Count; i++)
  1770. {
  1771. double b = 0;
  1772. for (int m = 0; m < allList.Count; m++)
  1773. {
  1774. b += allList[m][i];
  1775. }
  1776. classScore.Add(b);
  1777. }
  1778. classScore.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1779. //处理年级总分以及排名
  1780. List<double> GradeScore = new List<double>();
  1781. foreach (string ss in stu)
  1782. {
  1783. double score = 0;
  1784. foreach (ExamResult result in examResults)
  1785. {
  1786. int index = result.studentIds.IndexOf(ss);
  1787. score += result.studentScores[index].Sum();
  1788. }
  1789. GradeScore.Add(score);
  1790. }
  1791. GradeScore.Sort((s1, s2) => { return s2.CompareTo(s1); });
  1792. double ipoint = GradeScore[count];
  1793. return Ok(new { income = ipoint, rankc = classScore.IndexOf(totalScore), rankg = GradeScore.IndexOf(totalScore), classAverage = Math.Round(AllAverage[indexClass], 2), gradeAverage = cla.Count > 0 ? Math.Round(AllAverage.Sum() * 1.0 / cla.Count, 2) : 0, averageMap }); ;
  1794. }
  1795. catch (Exception e)
  1796. {
  1797. await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/studentAnalysis()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1798. return BadRequest();
  1799. }
  1800. }
  1801. [ProducesDefaultResponseType]
  1802. [HttpPost("education-analysis")]
  1803. [Authorize(Roles = "IES")]
  1804. [AuthToken(Roles = "teacher,admin,student")]
  1805. public async Task<IActionResult> education(JsonElement request) {
  1806. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1807. if (!request.TryGetProperty("period", out JsonElement period)) return BadRequest();
  1808. if (!request.TryGetProperty("gId", out JsonElement gId)) return BadRequest();
  1809. try {
  1810. var client = _azureCosmos.GetCosmosClient();
  1811. List<ExamInfo> infos = new List<ExamInfo>();
  1812. var query = $"select c.id,c.name,c.source from c where c.period.id = '{period}'";
  1813. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
  1814. {
  1815. infos.Add(item);
  1816. }
  1817. return Ok();
  1818. } catch (Exception e) {
  1819. return Ok(new { code = 500});
  1820. }
  1821. }
  1822. public async Task<string> getGId(int cyear, string periodId, string code)
  1823. {
  1824. var client = _azureCosmos.GetCosmosClient();
  1825. School sc = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(code, new Azure.Cosmos.PartitionKey("Base"));
  1826. string gradeId = "";
  1827. foreach (Period period in sc.period)
  1828. {
  1829. if (period.id.Equals(periodId))
  1830. {
  1831. foreach (Semester semester in period.semesters)
  1832. {
  1833. if (semester.start == 1)
  1834. {
  1835. int year = DateTimeOffset.UtcNow.Year;
  1836. int month = DateTimeOffset.UtcNow.Month;
  1837. int day = DateTimeOffset.UtcNow.Day;
  1838. int time = 0;
  1839. if (month == semester.month)
  1840. {
  1841. time = day >= semester.day ? 0 : 1;
  1842. }
  1843. else
  1844. {
  1845. time = month > semester.month ? 0 : 1;
  1846. }
  1847. int eyear = year - time;
  1848. gradeId = (eyear - cyear).ToString();
  1849. }
  1850. }
  1851. }
  1852. }
  1853. return gradeId;
  1854. }
  1855. }
  1856. }