|
@@ -0,0 +1,262 @@
|
|
|
+using ClouDASLibx;
|
|
|
+using Microsoft.AspNetCore.Mvc;
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Text.Json;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using TEAMModelOS.SDK.Models;
|
|
|
+
|
|
|
+using TEAMModelOS.SDK;
|
|
|
+using TEAMModelOS.SDK.DI;
|
|
|
+using TEAMModelOS.SDK.Extension;
|
|
|
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
|
|
|
+using TEAMModelOS.SDK.Helper.Common.StringHelper;
|
|
|
+using TEAMModelOS.SDK.Helper.Security.ShaHash;
|
|
|
+using TEAMModelOS.Services.Analysis;
|
|
|
+using Microsoft.Extensions.Options;
|
|
|
+using TEAMModelOS.Models;
|
|
|
+using Azure.Cosmos;
|
|
|
+using TEAMModelOS.SDK.Models.Cosmos.Student;
|
|
|
+using static TEAMModelOS.SDK.Models.Cosmos.Student.StudentAnalysis;
|
|
|
+using TEAMModelOS.SDK.Models.Cosmos.School;
|
|
|
+using static TEAMModelOS.SDK.Models.Cosmos.School.ClassAnalysis;
|
|
|
+using static TEAMModelOS.SDK.Models.Cosmos.School.GradeAnalysis;
|
|
|
+
|
|
|
+namespace TEAMModelOS.Controllers.Analysis
|
|
|
+{
|
|
|
+ [Route("analysis")]
|
|
|
+ [ApiController]
|
|
|
+ public class AnalysisController: ControllerBase
|
|
|
+ {
|
|
|
+ private readonly AzureCosmosFactory _azureCosmos;
|
|
|
+ private readonly DingDing _dingDing;
|
|
|
+ private readonly Option _option;
|
|
|
+ private const string CacheCosmosPrefix = "Analysis:";
|
|
|
+ private const int timeoutSeconds = 3600;
|
|
|
+ public AnalysisController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option)
|
|
|
+ {
|
|
|
+ _azureCosmos = azureCosmos;
|
|
|
+ _dingDing = dingDing;
|
|
|
+ _option = option?.Value;
|
|
|
+ }
|
|
|
+ [HttpPost("process")]
|
|
|
+ public async Task<IActionResult> getAnalysis(JsonElement request) {
|
|
|
+ //获取评测的ID
|
|
|
+ if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
|
|
|
+ if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
|
|
|
+ List<StudentAys> students = new List<StudentAys>();
|
|
|
+ List<ClassAys> classes = new List<ClassAys>();
|
|
|
+ List<GradeAys> grades = new List<GradeAys>();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var client = _azureCosmos.GetCosmosClient();
|
|
|
+ //获取本次评测所有科目结算结果
|
|
|
+ ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
|
|
|
+ School school = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(code.ToString(), new PartitionKey($"Base"));
|
|
|
+ List<ExamResult> examResults = new List<ExamResult>();
|
|
|
+ var query = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes from c where c.examId = '{id}' ";
|
|
|
+ await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamResult>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{id}") }))
|
|
|
+ {
|
|
|
+ examResults.Add(item);
|
|
|
+ }
|
|
|
+ //获取本次评测所有班级作答结果
|
|
|
+ List<ExamClassResult> examClassResults = new List<ExamClassResult>();
|
|
|
+ var queryClass = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.gradeId,c.info from c where c.examId = '{id}' and c.progress = true ";
|
|
|
+ await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(queryText: queryClass, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
|
|
|
+ {
|
|
|
+ examClassResults.Add(item);
|
|
|
+
|
|
|
+ }
|
|
|
+ //获取进线标准
|
|
|
+ int touch = 0;
|
|
|
+ foreach (Period period in school.period)
|
|
|
+ {
|
|
|
+ if (info.period.id.Equals(period.id))
|
|
|
+ {
|
|
|
+ touch = period.analysis.touch;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //获取进线人数
|
|
|
+ int personCount = (int)System.Math.Round(info.stuCount * (touch / 100.0), MidpointRounding.AwayFromZero);
|
|
|
+
|
|
|
+ /* //声明年级所有科目总分
|
|
|
+ List<double> total = new List<double>();*/
|
|
|
+
|
|
|
+ List<ClassRange> classReses = null;
|
|
|
+ //按科目获取所有学生的分数
|
|
|
+ Dictionary<string, List<double>> subjectTotal = new Dictionary<string, List<double>>();
|
|
|
+ Dictionary<string, double> paperScore = new Dictionary<string, double>();
|
|
|
+ foreach (ExamResult examResult in examResults)
|
|
|
+ {
|
|
|
+ //获取一张试卷的满分
|
|
|
+ paperScore.Add(examResult.subjectId, examResult.paper.point.Sum());
|
|
|
+ List<double> StuSubjectTotals = new List<double>();
|
|
|
+ classReses = examResult.classes;
|
|
|
+ //处理个人
|
|
|
+ foreach (var stuid in examResult.studentIds)
|
|
|
+ {
|
|
|
+ StudentAys student = null;
|
|
|
+ int index = examResult.studentIds.IndexOf(stuid);
|
|
|
+ if (students.Select(x => x.id).Contains(stuid))
|
|
|
+ {
|
|
|
+ student = students[index];
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ student = new StudentAys() { id=stuid } ;
|
|
|
+ students.Add(student);
|
|
|
+ }
|
|
|
+ var score = examResult.studentScores[index].Sum();
|
|
|
+ student.total += score;
|
|
|
+ StuSubjectTotals.Add(score);
|
|
|
+ if (student.subjects.Select(x => x.id).Contains(examResult.subjectId))
|
|
|
+ {
|
|
|
+ student.subjects.ForEach(y =>
|
|
|
+ {
|
|
|
+ if (y.id.Equals(examResult.subjectId))
|
|
|
+ {
|
|
|
+ y.score = score;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ StudentSubject subject = new StudentSubject
|
|
|
+ {
|
|
|
+ id = examResult.subjectId,
|
|
|
+ name = info.subjects.Where(x => x.id == examResult.subjectId).FirstOrDefault().name
|
|
|
+ };
|
|
|
+ subject.score = score;
|
|
|
+ student.subjects.Add(subject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ subjectTotal.Add(examResult.subjectId, StuSubjectTotals);
|
|
|
+ }
|
|
|
+ //以班级为单位
|
|
|
+ foreach (string classId in info.targetClassIds)
|
|
|
+ {
|
|
|
+ Class classroom = null;
|
|
|
+ var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(classId, new PartitionKey($"Class-{code}"));
|
|
|
+ if (sresponse.Status == 200)
|
|
|
+ {
|
|
|
+ using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
|
|
|
+ classroom = json.ToObject<Class>();
|
|
|
+
|
|
|
+ }
|
|
|
+ //处理班级
|
|
|
+ var classRes = classReses.Where(x => x.id == classId).FirstOrDefault();
|
|
|
+ var stuCount = classRes.range[1] - classRes.range[0] + 1;
|
|
|
+ var classStudents = students.GetRange(classRes.range[0], classRes.range[1] - classRes.range[0] + 1);
|
|
|
+ List<double> stuTotals = classStudents.Select(x=>x.total).ToList();
|
|
|
+ stuTotals.Sort(delegate (double s1, double s2) { return s2.CompareTo(s1); });
|
|
|
+ double ipoint = stuTotals[personCount];
|
|
|
+ //初始化进线人数
|
|
|
+ int lineCount = 0;
|
|
|
+ //初始化班级总分
|
|
|
+ double classTotal = stuTotals.Sum();
|
|
|
+ //标准差
|
|
|
+ double powSum = 0;
|
|
|
+ //计算标准差
|
|
|
+ //总平均分
|
|
|
+ double totalAverage = 0;
|
|
|
+ //获取整个班级 科目的分数情况
|
|
|
+ List<KeyValuePair<string, double>> keyValues = new List<KeyValuePair<string, double>>();
|
|
|
+ List<string> studentIds = new List<string>();
|
|
|
+ classStudents.ForEach(x => {
|
|
|
+ studentIds.Add(x.id);
|
|
|
+ x.classId = classId;
|
|
|
+ x.className = classroom.name;
|
|
|
+ x.name = classroom.students.Where(s => x.id == x.id).First().name;
|
|
|
+ //标准差
|
|
|
+ powSum += Math.Pow(x.total - totalAverage, 2);
|
|
|
+ //进线人数
|
|
|
+ if (x.total > ipoint) {
|
|
|
+ lineCount++;
|
|
|
+ }
|
|
|
+ //班级全科的pr
|
|
|
+ int index = stuTotals.IndexOf(x.total);
|
|
|
+ double CPR = 100 - (100 * (index + 1) - 50) / stuCount;
|
|
|
+ x.cpr = CPR;
|
|
|
+ //班级单科的pr
|
|
|
+ x.subjects.ForEach(y=> {
|
|
|
+ var subjectT= subjectTotal[y.id];
|
|
|
+ subjectT.Sort(delegate (double s1, double s2) { return s2.CompareTo(s1); });
|
|
|
+ int index = subjectT.IndexOf(y.score);
|
|
|
+ double CPR = 100 - (100 * (index + 1) - 50) / stuCount;
|
|
|
+ y.cpr = CPR;
|
|
|
+ //按科目获取一个班的分数
|
|
|
+ keyValues.Add(new KeyValuePair<string, double>(y.id, y.score));
|
|
|
+ });
|
|
|
+ });
|
|
|
+ totalAverage = classTotal / stuCount;
|
|
|
+ var pow = Math.Pow(powSum / stuCount, 0.5);
|
|
|
+ ClassAys classAys = new ClassAys
|
|
|
+ {
|
|
|
+ gradeId = classroom.gradeId,
|
|
|
+ studentIds = studentIds,
|
|
|
+ stuCount = stuCount,
|
|
|
+ classId = classId,
|
|
|
+ className = classroom.name,
|
|
|
+ totalAverage = totalAverage,
|
|
|
+ lineCount = lineCount,
|
|
|
+ standardDeviation = pow
|
|
|
+ };
|
|
|
+ foreach (var key in paperScore.Keys) {
|
|
|
+ var subScore= keyValues.Where(x => x.Key.Equals(key)).Select(x=>x.Value).ToList();
|
|
|
+ //计算及格率
|
|
|
+ int passCount = 0;
|
|
|
+ double passScore = paperScore[key] * 0.6;
|
|
|
+ subScore.ForEach(x => {
|
|
|
+ if (x > passScore) {
|
|
|
+ passCount += 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ double passPercent = passCount * 1.0 / stuCount ;
|
|
|
+ double average = subScore.Sum()* 1.0 / stuCount ;
|
|
|
+ classAys.subjects.Add(new AysSubject { id = key, passPercent= passPercent, passCount= passCount, average= average ,name= info.subjects.Where(x => x.id == key).FirstOrDefault().name });
|
|
|
+ }
|
|
|
+ classes.Add(classAys);
|
|
|
+ }
|
|
|
+ //处理年级
|
|
|
+ var tgrades= classes.GroupBy(x => x.gradeId).Select(x=>x.Key);
|
|
|
+ foreach (var greade in tgrades) {
|
|
|
+ var clases = classes.Where(x => x.gradeId.Equals(greade));
|
|
|
+ var classCount = clases.Count();
|
|
|
+ var stu= clases.SelectMany(x => x.studentIds).ToList();
|
|
|
+ var lineCount = clases.Select(x => x.lineCount).Sum();
|
|
|
+ var totalAverage = clases.Select(x => x.totalAverage).Sum() * 1.0 / classCount;
|
|
|
+ GradeAys gradeAys = new GradeAys
|
|
|
+ {
|
|
|
+ gradeId = greade,
|
|
|
+ studentIds = stu,
|
|
|
+ gradeName = info.grades.Where(x => x.id == greade).FirstOrDefault().name,
|
|
|
+ stuCount = stu.Count,
|
|
|
+ lineCount = lineCount,
|
|
|
+ totalAverage = totalAverage,
|
|
|
+ };
|
|
|
+ foreach (var key in paperScore.Keys)
|
|
|
+ {
|
|
|
+ var AysSubject = clases.SelectMany(c=>c.subjects).Where(x => x.id.Equals(key)).Select(x => x).ToList();
|
|
|
+ var passCount= AysSubject.Select(x => x.passCount).Sum();
|
|
|
+ var average = AysSubject.Select(x => x.average).Sum()*1.0/ classCount;
|
|
|
+ var passPercent = passCount * 1.0/ stu.Count;
|
|
|
+ AysSubject subject = new AysSubject {
|
|
|
+ id=key,
|
|
|
+ passCount= passCount,
|
|
|
+ passPercent= passPercent,
|
|
|
+ average= average,
|
|
|
+ name = info.subjects.Where(x => x.id == key).FirstOrDefault().name };
|
|
|
+ gradeAys.subjects.Add(subject);
|
|
|
+ }
|
|
|
+ grades.Add(gradeAys);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex) {
|
|
|
+
|
|
|
+ }
|
|
|
+ return Ok(new { students, classes, grades });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|