OverallEducationController.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. using Microsoft.Azure.Cosmos;
  2. using MathNet.Numerics.Distributions;
  3. using Microsoft.AspNetCore.Authorization;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.AspNetCore.Mvc;
  6. using Microsoft.Azure.Amqp.Framing;
  7. using Microsoft.Extensions.Configuration;
  8. using Microsoft.Extensions.Options;
  9. using Microsoft.OData.Edm;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Dynamic;
  13. using System.Linq;
  14. using System.Reflection;
  15. using System.Security.Claims;
  16. using System.Text;
  17. using System.Text.Json;
  18. using System.Threading.Tasks;
  19. using TEAMModelOS.Filter;
  20. using TEAMModelOS.Models;
  21. using TEAMModelOS.SDK;
  22. using TEAMModelOS.SDK.DI;
  23. using TEAMModelOS.SDK.Extension;
  24. using TEAMModelOS.SDK.Models;
  25. using TEAMModelOS.SDK.Models.Cosmos;
  26. using TEAMModelOS.SDK.Models.Cosmos.Common;
  27. using TEAMModelOS.SDK.Models.Service;
  28. using TEAMModelOS.SDK.Services;
  29. using static TEAMModelOS.Controllers.OverallEducationController;
  30. using static TEAMModelOS.SDK.Models.Cosmos.Student.StudentAnalysis;
  31. using static TEAMModelOS.SDK.Services.ActivityStudentService;
  32. namespace TEAMModelOS.Controllers
  33. {
  34. /// <summary>
  35. /// 学生五育画像接口
  36. /// </summary>
  37. [Route("overall-education")]
  38. [ApiController]
  39. public class OverallEducationController : ControllerBase
  40. {
  41. private readonly AzureCosmosFactory _azureCosmos;
  42. private readonly AzureStorageFactory _azureStorage;
  43. private readonly AzureRedisFactory _azureRedis;
  44. private readonly DingDing _dingDing;
  45. private readonly Option _option;
  46. private readonly IConfiguration _configuration;
  47. private readonly CoreAPIHttpService _coreAPIHttpService;
  48. private readonly AzureServiceBusFactory _serviceBus;
  49. private readonly SnowflakeId _snowflakeId;
  50. public OverallEducationController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, DingDing dingDing, CoreAPIHttpService coreAPIHttpService, IOptionsSnapshot<Option> option, IConfiguration configuration, SnowflakeId snowflakeId)
  51. {
  52. _azureCosmos = azureCosmos;
  53. _azureStorage = azureStorage;
  54. _azureRedis = azureRedis;
  55. _dingDing = dingDing;
  56. _option = option?.Value;
  57. _configuration = configuration;
  58. _coreAPIHttpService = coreAPIHttpService;
  59. _serviceBus = serviceBus;
  60. _snowflakeId = snowflakeId;
  61. }
  62. /// <summary>
  63. /// 获取看板的基本条件
  64. /// </summary>
  65. /// <param name="json"></param>
  66. /// <returns></returns>
  67. [HttpPost("overview-cond")]
  68. [AuthToken(Roles = "teacher,admin")]
  69. [Authorize(Roles = "IES")]
  70. public async Task<IActionResult> OverviewCond(JsonElement json)
  71. {
  72. json.TryGetProperty("schoolId", out JsonElement schoolId);
  73. json.TryGetProperty("periodId", out JsonElement periodId);
  74. var client = _azureCosmos.GetCosmosClient();
  75. StringBuilder classsql = new StringBuilder($"SELECT count(1) FROM c where ( c.graduate = 0 or IS_DEFINED(c.graduate) = false )");
  76. if (!string.IsNullOrEmpty($"{periodId}"))
  77. {
  78. classsql.Append($" and c.periodId='{periodId}' ");
  79. }
  80. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql<ClassInfo>(queryText: classsql.ToString(),
  81. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{schoolId}") }))
  82. {
  83. }
  84. return Ok();
  85. }
  86. [HttpPost("overview")]
  87. #if !DEBUG
  88. [AuthToken(Roles = "teacher,admin")]
  89. [Authorize(Roles = "IES")]
  90. #endif
  91. public async Task<IActionResult> Overview(JsonElement json)
  92. {
  93. try {
  94. json.TryGetProperty("studentYear", out JsonElement _studentYear);
  95. json.TryGetProperty("grades", out JsonElement _grades);
  96. json.TryGetProperty("school", out JsonElement _school);
  97. json.TryGetProperty("periodId", out JsonElement _periodId);
  98. json.TryGetProperty("semesterId", out JsonElement _semesterId);
  99. json.TryGetProperty("studyYear", out JsonElement _studyYear);
  100. json.TryGetProperty("studentId", out JsonElement _studentId);
  101. List<Class> classes = new List<Class>();
  102. List<Student> students = new List<Student>();
  103. List<Class> grade_classes = new List<Class>();
  104. List<Student> grade_students = new List<Student>();
  105. List<OverallEducation> grade_overallEducations = new List<OverallEducation>();
  106. List<OverallEducation> overallEducations = new List<OverallEducation>();
  107. HashSet<string> classIds = new HashSet<string>();
  108. var client = _azureCosmos.GetCosmosClient();
  109. School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{_school}", new PartitionKey("Base"));
  110. SchoolSetting schoolSetting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolSetting>($"{_school}", new PartitionKey("SchoolSetting"));
  111. Dictionary<string, object> dict = OverallEducationService.GetQueryCond(json);
  112. #region 此处代码用于处理 根据年级 学段获取 相关的班级。
  113. HashSet<int> years = new HashSet<int>();
  114. if (_grades.ValueKind.Equals(JsonValueKind.Array))
  115. {
  116. var yearsdata = SchoolService.GetYears(school, $"{_periodId}", _grades.ToObject<List<int>>());
  117. years = yearsdata.years;
  118. }
  119. if (int.TryParse($"{_studentYear}", out int studentYear))
  120. {
  121. if (!string.IsNullOrWhiteSpace($"{_studentId}"))
  122. {
  123. Student student= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemAsync<Student>($"{_studentId}", new PartitionKey($"Base-{school.id}"));
  124. Class classz = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<Class>($"{student.classId}", new PartitionKey($"Class-{school.id}"));
  125. years.Add(classz.year);
  126. }
  127. else {
  128. years.Add(studentYear);
  129. }
  130. }
  131. Period period = school.period.Find(z => z.id.Equals($"{_periodId}")); ;
  132. Semester semester = period.semesters.Find(x => x.id.Equals($"{_semesterId}"));
  133. if (!years.Any())
  134. {
  135. if (period != null && period.grades.IsNotEmpty())
  136. {
  137. List<int> grades = new List<int>();
  138. period.grades.Select((z, index) => index).ToList().ForEach(t => { grades.Add(t); });
  139. var yearsdata = SchoolService.GetYears(school, $"{_periodId}", grades);
  140. years = yearsdata.years;
  141. }
  142. }
  143. //标记是否是下钻到班级
  144. bool isClass = false;
  145. if (json.TryGetProperty("classIds", out JsonElement _classIds))
  146. {
  147. classIds = _classIds.ToObject<HashSet<string>>();
  148. if (classIds != null && classIds.Count > 0)
  149. {
  150. isClass = true;
  151. }
  152. }
  153. if (!string.IsNullOrWhiteSpace($"{_studentId}")) {
  154. ResponseMessage response= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReadItemStreamAsync($"{_studentId}", new PartitionKey($"Base-{school.id}"));
  155. if (response.StatusCode==System.Net.HttpStatusCode.OK) {
  156. Student student= JsonDocument.Parse(response.Content).RootElement.Deserialize<Student>();
  157. if (student != null && !string.IsNullOrWhiteSpace(student.classId)) {
  158. classIds.Add(student.classId);
  159. isClass=true;
  160. }
  161. }
  162. }
  163. if (years.Any() && years.Count > 0)
  164. {
  165. var gradeData = await OverallEducationService.GetGradeData(client, years, $"{_periodId}", $"{_school}", classIds, $"{_studyYear}", $"{_semesterId}", _azureRedis);
  166. classes = gradeData.classes;
  167. students = gradeData.students;
  168. grade_classes = gradeData.grade_classes;
  169. grade_students = gradeData.grade_students;
  170. grade_overallEducations = gradeData.overallEducations;
  171. overallEducations = gradeData.overallEducations.FindAll(x => students.Select(k => k.id).Contains(x.studentId));
  172. }
  173. #endregion
  174. List<(double score, OverallEducation student, string className, string picture)> ranking = new List<(double score, OverallEducation student, string className, string picture)>();
  175. List<(string classId, string className, double last, double best, double sum, double avg, int count)> classDatas = new List<(string classId, string className, double last, double best, double sum, double avg, int count)>();
  176. //pr计算 100 - (100 * (index + 1) - 50) / stuCount; index 整体排名 stuCount 总人数
  177. double basic_Score = 60;
  178. if (schoolSetting?.overallEducationSetting?.overallEducationInit != null && schoolSetting?.overallEducationSetting?.overallEducationInit >= 0)
  179. {
  180. basic_Score = schoolSetting.overallEducationSetting.overallEducationInit;
  181. }
  182. var hasData_labour = grade_overallEducations.Where(x => x.labour.Count > 0);
  183. double max_labour = 0;
  184. double min_labour = 0;
  185. if (hasData_labour != null && hasData_labour.Any())
  186. {
  187. var order_labour = hasData_labour.Select(x => new { score = x.labour.Sum(x => x.sumScore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  188. max_labour = order_labour.Max(z => z.score);
  189. min_labour = order_labour.Min(z => z.score);
  190. }
  191. var hasData_virtue = grade_overallEducations.Where(x => x.virtue.Count > 0);
  192. double max_virtue = 0;
  193. double min_virtue = 0;
  194. if (hasData_virtue != null && hasData_virtue.Any()) {
  195. var order_virtue = hasData_virtue.Select(x => new { score = x.virtue.Sum(x => x.sumScore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  196. max_virtue = order_virtue.Max(z => z.score);
  197. min_virtue = order_virtue.Min(z => z.score);
  198. }
  199. var hasData_lesson = grade_overallEducations.Where(x => x.lessonScore.Count > 0);
  200. double max_lesson_gscore = 0;
  201. double max_lesson_pscore = 0;
  202. double max_lesson_tscore = 0;
  203. double min_lesson_gscore = 0;
  204. double min_lesson_pscore = 0;
  205. double min_lesson_tscore = 0;
  206. if (hasData_lesson != null && hasData_lesson.Any()) {
  207. var order_gdata = hasData_lesson.Select(x => new { score = x.lessonScore.Sum(x => x.gscore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  208. max_lesson_gscore = order_gdata.Max(z => z.score);
  209. min_lesson_gscore = order_gdata.Min(z => z.score);
  210. var order_pdata = hasData_lesson.Select(x => new { score = x.lessonScore.Sum(x => x.pscore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  211. max_lesson_pscore = order_pdata.Max(z => z.score);
  212. min_lesson_pscore = order_pdata.Min(z => z.score);
  213. var order_tdata = hasData_lesson.Select(x => new { score = x.lessonScore.Sum(x => x.tscore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  214. max_lesson_tscore = order_tdata.Max(z => z.score);
  215. min_lesson_tscore = order_tdata.Min(z => z.score);
  216. }
  217. List<StudentDimensionScore> grade_dimensions = new List<StudentDimensionScore>();
  218. //全年级的数据
  219. foreach (var item in grade_overallEducations)
  220. {
  221. var student = students.Find(x => x.id.Equals(item.studentId));
  222. var clazz = classes.Find(x => x.id.Equals(item.classId));
  223. StudentDimensionScore dimensionScore = new StudentDimensionScore() { studentId = item.studentId,className=clazz?.name, classId = item.classId, studentName = student?.name, picture = student?.picture };
  224. StudentDimensionScoreDefault dimensionScoreDefault = new StudentDimensionScoreDefault { studentId=item.studentId };
  225. //排名指数计算=( 当前值分数- 298) / (9992 - 298) * (99 - 60) + 60
  226. //将每个人的积分转化为60-100
  227. //排名 = (积分 - 最低积分) / (最高积分 - 最低积分) * (最大排名 - 最小排名) + 最小排名
  228. //劳动
  229. var order_labour = hasData_labour.Select(x => new { score = x.labour.Sum(x => x.sumScore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  230. var labour = order_labour.Find(x => x.studentId.Equals(item.studentId));
  231. var labour_score = basic_Score;
  232. if (labour != null && labour.score > 0 && max_labour - min_labour>0)
  233. {
  234. dimensionScoreDefault.labour=1;
  235. labour_score = Math.Round((labour.score - min_labour) / (max_labour - min_labour) * (99 - basic_Score) + basic_Score,2);
  236. }
  237. dimensionScore.labour = labour_score;
  238. //德育
  239. var order_virtue = hasData_virtue.Select(x => new { score = x.virtue.Sum(x => x.sumScore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  240. var virtue = order_virtue.Find(x => x.studentId.Equals(item.studentId));
  241. var virtue_score = basic_Score;
  242. if (virtue != null && virtue.score > 0 && max_virtue - min_virtue>0)
  243. {
  244. dimensionScoreDefault.virtue=1;
  245. virtue_score = Math.Round((virtue.score - min_virtue) / (max_virtue - min_virtue) * (99 - basic_Score) + basic_Score,2);
  246. }
  247. dimensionScore.virtue = virtue_score;
  248. double intelligence = basic_Score;
  249. if (item.intelligence.IsNotEmpty())
  250. {
  251. //智育
  252. //if (schoolSetting.overallEducationSetting.intelligence.Equals("avg"))
  253. //{
  254. //}
  255. //else {
  256. //}
  257. List<EducationScore> intelligenceScore = new List<EducationScore>();
  258. if (schoolSetting.overallEducationSetting.examTypes.IsNotEmpty())
  259. {
  260. var datas = item.intelligence.FindAll(z => !string.IsNullOrWhiteSpace(z.examType) && schoolSetting.overallEducationSetting.examTypes.Contains(z.examType));
  261. if (datas.IsNotEmpty()) {
  262. intelligenceScore.AddRange(datas);
  263. }
  264. }
  265. else {
  266. intelligenceScore.AddRange(item.intelligence);
  267. }
  268. if (intelligenceScore.Count>0) {
  269. double sumScore = intelligenceScore.Average(x => x.sumScore);
  270. double totalScore = intelligenceScore.Average(x => x.totalScore);
  271. if (totalScore > 0)
  272. {
  273. intelligence = Math.Round(sumScore * 1.0 / totalScore * 100, 2);
  274. }
  275. else
  276. {
  277. intelligence = Math.Round(sumScore * 1.0 / intelligenceScore.Count, 2);
  278. }
  279. }
  280. dimensionScoreDefault.intelligence=1;
  281. dimensionScoreDefault.exam=1;
  282. }
  283. dimensionScore.exam = intelligence;
  284. var order_tdata = hasData_lesson.Select(x => new { score = x.lessonScore.Sum(x => x.tscore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  285. var order_gdata = hasData_lesson.Select(x => new { score = x.lessonScore.Sum(x => x.gscore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  286. var order_pdata = hasData_lesson.Select(x => new { score = x.lessonScore.Sum(x => x.pscore), studentId = x.studentId }).OrderByDescending(x => x.score).ToList();
  287. //合作
  288. var gdata = order_gdata.Find(x => x.studentId.Equals(item.studentId));
  289. var gdata_score = basic_Score;
  290. if (gdata != null && gdata.score > 0 && max_lesson_gscore - min_lesson_gscore>0)
  291. {
  292. dimensionScoreDefault.gscore=1;
  293. dimensionScoreDefault.intelligence=1;
  294. gdata_score = Math.Round((gdata.score - min_lesson_gscore) / (max_lesson_gscore - min_lesson_gscore) * (99 - basic_Score) + basic_Score,2);
  295. }
  296. dimensionScore.gscore = gdata_score;
  297. //态度
  298. var tdata = order_tdata.Find(x => x.studentId.Equals(item.studentId));
  299. var tdata_score = basic_Score;
  300. if (tdata != null && tdata.score > 0 && max_lesson_tscore - min_lesson_tscore>0)
  301. {
  302. dimensionScoreDefault.tscore=1;
  303. dimensionScoreDefault.intelligence=1;
  304. tdata_score = Math.Round((tdata.score - min_lesson_tscore) / (max_lesson_tscore - min_lesson_tscore) * (99 - basic_Score) + basic_Score,2);
  305. }
  306. dimensionScore.tscore = tdata_score;
  307. //能力
  308. var pdata = order_pdata.Find(x => x.studentId.Equals(item.studentId));
  309. var pdata_score = basic_Score;
  310. if (pdata != null && pdata.score > 0 && max_lesson_pscore - min_lesson_pscore>0)
  311. {
  312. dimensionScoreDefault.pscore=1;
  313. dimensionScoreDefault.intelligence=1;
  314. pdata_score = Math.Round((pdata.score - min_lesson_pscore) / (max_lesson_pscore - min_lesson_pscore) * (99 - basic_Score) + basic_Score,2);
  315. }
  316. dimensionScore.pscore = pdata_score;
  317. //态度
  318. double attitude = 0.1;
  319. //合作
  320. double cooperate = 0.1;
  321. //能力
  322. double ability = 0.1;
  323. //水平
  324. double standard = 0.7;
  325. var attitudeWeight = schoolSetting.overallEducationSetting.intelligenceWeight.Find(x => x.code.Equals("attitude"));
  326. attitude = attitudeWeight != null ? attitudeWeight.value : attitude;
  327. var cooperateWeight = schoolSetting.overallEducationSetting.intelligenceWeight.Find(x => x.code.Equals("cooperate"));
  328. cooperate = cooperateWeight != null ? cooperateWeight.value : cooperate;
  329. var abilityWeight = schoolSetting.overallEducationSetting.intelligenceWeight.Find(x => x.code.Equals("ability"));
  330. ability = abilityWeight != null ? abilityWeight.value : ability;
  331. var standardWeight = schoolSetting.overallEducationSetting.intelligenceWeight.Find(x => x.code.Equals("standard"));
  332. standard = standardWeight != null ? standardWeight.value : standard;
  333. dimensionScore.intelligence = Math.Round(intelligence * standard + pdata_score * ability + tdata_score * attitude + gdata_score * cooperate, 2);
  334. if (item.sports.IsNotEmpty())
  335. { //体育
  336. //if (schoolSetting.overallEducationSetting.sports.Equals("newest"))
  337. //{
  338. //}
  339. //else { dimensionScore.sports = basic_Score; }
  340. double sumScore = item.sports.OrderByDescending(x => x.examDate).First().sumScore;
  341. double totalScore = item.sports.OrderByDescending(x => x.examDate).First().totalScore;
  342. if (totalScore > 0)
  343. {
  344. dimensionScore.sports = Math.Round(sumScore * 1.0 / totalScore * 100, 2);
  345. }
  346. else
  347. {
  348. dimensionScore.sports = Math.Round(sumScore * 1.0 / item.sports.Count, 2);
  349. }
  350. dimensionScoreDefault.sports=1;
  351. }
  352. else
  353. {
  354. dimensionScore.sports = basic_Score;
  355. }
  356. if (item.art.IsNotEmpty())
  357. {
  358. //艺术
  359. //if (schoolSetting.overallEducationSetting.art.Equals("newest"))
  360. //{
  361. //}
  362. //else
  363. //{
  364. // dimensionScore.art = basic_Score;
  365. //}
  366. var art = item.art.OrderByDescending(x => x.examDate).First();
  367. double sumScore = art.sumScore;
  368. double totalScore = art.totalScore;
  369. if (totalScore > 0)
  370. {
  371. dimensionScore.art = Math.Round(sumScore * 1.0 / totalScore * 100, 2);
  372. }
  373. else
  374. {
  375. dimensionScore.art = Math.Round(sumScore * 1.0 / item.art.Count, 2);
  376. }
  377. dimensionScoreDefault.art=1;
  378. var subject_music = art.itemScore.Find(x => !string.IsNullOrWhiteSpace(x.id) ? x.id.Equals("subject_music") : x.type.Equals("subject_music"));
  379. var subject_painting = art.itemScore.Find(x => !string.IsNullOrWhiteSpace(x.id) ? x.id.Equals("subject_painting") : x.type.Equals("subject_painting"));
  380. if (subject_music != null)
  381. {
  382. dimensionScore.subject_music = Math.Round(subject_music.score * 1.0 / subject_music.totalScore *100, 2);
  383. dimensionScoreDefault.subject_music=1;
  384. }
  385. else
  386. {
  387. dimensionScore.subject_music = 0;
  388. }
  389. if (subject_painting != null)
  390. {
  391. dimensionScoreDefault.subject_painting=1;
  392. dimensionScore.subject_painting = Math.Round(subject_painting.score * 1.0 / subject_painting.totalScore *100, 2);
  393. }
  394. else
  395. {
  396. dimensionScore.subject_painting = 0;
  397. }
  398. }
  399. else
  400. {
  401. dimensionScore.art = basic_Score;
  402. }
  403. dimensionScore.score =Math.Round((dimensionScore.virtue + dimensionScore.intelligence + dimensionScore.labour + dimensionScore.art + dimensionScore.sports) / 5,2);
  404. schoolSetting.overallEducationSetting.reviewLevel.ForEach(z => {
  405. if (z.value[0] <= dimensionScore.score && z.value[1] > dimensionScore.score)
  406. {
  407. dimensionScore.level = z.code;
  408. }
  409. });
  410. grade_dimensions.Add(dimensionScore);
  411. }
  412. //处理年级排名
  413. // grade_dimensions.OrderByDescending(x => x.score).Select((z, index) => z.gradeRanking = (index + 1));
  414. grade_dimensions = grade_dimensions.OrderByDescending(x => x.score).ToList();
  415. int index = 1;
  416. foreach(var item in grade_dimensions)
  417. {
  418. item.gradeRanking = index;
  419. index++;
  420. }
  421. var group_class_dimensions = grade_dimensions.GroupBy(z => z.classId).Select(z => new { key = z.Key, list =z.OrderByDescending(x => x.score) });
  422. foreach (var classData in group_class_dimensions)
  423. {
  424. index = 1;
  425. // classData.list.OrderByDescending(x => x.score).Select((z, index) => z.classRanking = (index + 1));
  426. foreach (var item in classData.list)
  427. {
  428. item.classRanking = index;
  429. index++;
  430. }
  431. }
  432. // group_class_dimensions.ForEach(x=>x)
  433. List<StudentDimensionScore> dimensions = new List<StudentDimensionScore>();
  434. //当前条件的数据
  435. foreach (var item in overallEducations)
  436. {
  437. var dimension = grade_dimensions.Find(x => x.studentId.Equals(item.studentId));
  438. if (dimension != null)
  439. {
  440. var stud = students.Find(c => c.id.Equals(item.studentId));
  441. dimension.classId=stud.classId;
  442. dimensions.Add(dimension);
  443. }
  444. }
  445. var class_dimensions = dimensions.GroupBy(z => z.classId).Select(z => new { key = z.Key, list = z });
  446. List<dynamic> classDimensions = new List<dynamic>();
  447. List<AchievementScore> achievementScores = new List<AchievementScore>();
  448. foreach (var classData in class_dimensions)
  449. {
  450. ClassDimensionScore classDimensionScore = new ClassDimensionScore() { classId = classData.key };
  451. var clazz = classes.Find(x => x.id.Equals(classData.key));
  452. classDimensionScore.className = clazz?.name;
  453. classDimensionScore.max = Math.Round(classData.list.Max(x => x.score),2);
  454. classDimensionScore.min = Math.Round(classData.list.Min(x => x.score),2);
  455. classDimensionScore.score = Math.Round(classData.list.Average(x => x.score),2);
  456. classDimensionScore.pscore = Math.Round(classData.list.Average(x => x.pscore),2);
  457. classDimensionScore.tscore = Math.Round(classData.list.Average(x => x.tscore),2);
  458. classDimensionScore.gscore = Math.Round(classData.list.Average(x => x.gscore),2);
  459. classDimensionScore.exam = Math.Round(classData.list.Average(x => x.exam), 2);
  460. double intelligenceScore = Math.Round(classData.list.Average(x => x.intelligence), 2);
  461. schoolSetting.overallEducationSetting.reviewLevel.ForEach(z => {
  462. if (z.value[0] <= intelligenceScore && z.value[1] > intelligenceScore)
  463. {
  464. classDimensionScore.intelligenceLevel = z.code;
  465. }
  466. });
  467. classDimensionScore.intelligenceLevels= classData.list.GroupBy(x => x.level).Select(x => new CodeLong { code = x.Key, value = x.Count() }).ToList();
  468. if (!isClass)
  469. {
  470. achievementScores.Add(new AchievementScore
  471. {
  472. gscore = classDimensionScore.gscore,
  473. pscore = classDimensionScore.pscore,
  474. tscore = classDimensionScore.tscore,
  475. id = classData.key,
  476. name = clazz?.name,
  477. type = "class"
  478. });
  479. }
  480. schoolSetting.overallEducationSetting.reviewLevel.ForEach(z => {
  481. if (z.value[0] <= classDimensionScore.score && z.value[1] > classDimensionScore.score)
  482. {
  483. classDimensionScore.level = z.code;
  484. }
  485. });
  486. classDimensions.Add(classDimensionScore);
  487. }
  488. ///当前条件的
  489. double pscore_avg = 0;
  490. double tscore_avg = 0;
  491. double gscore_avg = 0;
  492. //年级
  493. double grade_pscore_avg = 0;
  494. double grade_tscore_avg = 0;
  495. double grade_gscore_avg = 0;
  496. if (isClass)
  497. {
  498. if (dimensions != null && dimensions.Any())
  499. { //能力年级平均分
  500. pscore_avg = Math.Round(dimensions.Average(x => x.pscore), 2);
  501. //态度年级平均分
  502. tscore_avg = Math.Round(dimensions.Average(x => x.tscore), 2);
  503. //合作年级平均分
  504. gscore_avg = Math.Round(dimensions.Average(x => x.gscore), 2);
  505. var studentAchievementScores = dimensions.Select(z => new AchievementScore { id = z.studentId, name = z.studentName, gscore = z.gscore, pscore = z.pscore, tscore = z.tscore, type = "student" });
  506. achievementScores.AddRange(studentAchievementScores);
  507. }
  508. }
  509. else
  510. {
  511. if (grade_dimensions != null && grade_dimensions.Any())
  512. { //能力年级平均分
  513. pscore_avg = Math.Round(grade_dimensions.Average(x => x.pscore), 2);
  514. //态度年级平均分
  515. tscore_avg = Math.Round(grade_dimensions.Average(x => x.tscore), 2);
  516. //合作年级平均分
  517. gscore_avg = Math.Round(grade_dimensions.Average(x => x.gscore), 2);
  518. }
  519. }
  520. if (grade_dimensions != null && grade_dimensions.Any())
  521. { //能力年级平均分
  522. grade_pscore_avg = Math.Round(grade_dimensions.Average(x => x.pscore), 2);
  523. //态度年级平均分
  524. grade_tscore_avg = Math.Round(grade_dimensions.Average(x => x.tscore), 2);
  525. //合作年级平均分
  526. grade_gscore_avg = Math.Round(grade_dimensions.Average(x => x.gscore), 2);
  527. }
  528. #region
  529. double data_count = overallEducations.Count;
  530. int sports_count90 = dimensions.Where(x => x.sports >= 90).Count();
  531. int sports_count60 = dimensions.Where(x => x.sports >= 60).Count();
  532. double sports_rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.sports >= 90).Count() * 1.0 / data_count *100: 0,2);
  533. double sports_rate60 =Math.Round(data_count > 0 ? dimensions.Where(x => x.sports >= 60).Count() * 1.0 / data_count * 100 : 0,2);
  534. int art_count90 = dimensions.Where(x => x.art >= 90).Count();
  535. int art_count60 = dimensions.Where(x => x.art >= 60).Count();
  536. double art_rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.art >= 90).Count() * 1.0 / data_count * 100 : 0, 2);
  537. double art_rate60 = Math.Round(data_count > 0 ? dimensions.Where(x => x.art >= 60).Count() * 1.0 / data_count * 100 : 0, 2);
  538. int subject_music_count90 = dimensions.Where(x => x.subject_music >= 90).Count();
  539. int subject_music_count60 = dimensions.Where(x => x.subject_music >= 60).Count();
  540. double subject_music_rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.subject_music >= 90).Count() * 1.0 / data_count * 100 : 0, 2);
  541. double subject_music_rate60 = Math.Round(data_count > 0 ? dimensions.Where(x => x.subject_music >= 60).Count() * 1.0 / data_count * 100 : 0, 2);
  542. int subject_painting_count90 = dimensions.Where(x => x.subject_painting >= 90).Count();
  543. int subject_painting_count60 = dimensions.Where(x => x.subject_painting >= 60).Count();
  544. double subject_painting_rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.subject_painting >= 90).Count() * 1.0 / data_count * 100 : 0, 2);
  545. double subject_painting_rate60 = Math.Round(data_count > 0 ? dimensions.Where(x => x.subject_painting >= 60).Count() * 1.0 / data_count * 100 : 0, 2);
  546. int labour_count90 = dimensions.Where(x => x.labour >= 90).Count();
  547. int labour_count60 = dimensions.Where(x => x.labour >= 60).Count();
  548. double labour_rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.labour >= 90).Count() * 1.0 / data_count * 100 : 0, 2);
  549. double labour_rate60 = Math.Round(data_count > 0 ? dimensions.Where(x => x.labour >= 60).Count() * 1.0 / data_count * 100 : 0, 2);
  550. int virtue_count90 = dimensions.Where(x => x.virtue >= 90).Count();
  551. int virtue_count60 = dimensions.Where(x => x.virtue >= 60).Count();
  552. double virtue_rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.virtue >= 90).Count() * 1.0 / data_count * 100 : 0, 2);
  553. double virtue_rate60 = Math.Round(data_count > 0 ? dimensions.Where(x => x.virtue >= 60).Count() * 1.0 / data_count * 100 : 0, 2);
  554. double rate90 = Math.Round(data_count > 0 ? dimensions.Where(x => x.score >= 90).Count() * 1.0 / data_count * 100 : 0, 2);
  555. double rate60 = Math.Round(data_count > 0 ? dimensions.Where(x => x.score >= 60).Count() * 1.0 / data_count * 100 : 0, 2);
  556. OverallEducation studentOverallEducation = null;
  557. var studyYear = int.Parse($"{_studyYear}");
  558. var semesterData= SchoolService.GetSemester(period, time: SchoolService.GetOpensByStudyYearAndSemester(period.semesters,studyYear,$"{_semesterId}"));
  559. var examData = await ExamService.getGradeScore(_coreAPIHttpService, _dingDing,_azureCosmos.GetCosmosClient(), grade_classes.Select(x=>x.id).ToList(), $"{_periodId}", school.id, schoolSetting.overallEducationSetting.examTypes
  560. , semesterData.date.ToUnixTimeMilliseconds(), semesterData.nextSemester.ToUnixTimeMilliseconds());
  561. var groupExam= examData.GroupBy(x => x.name).Select(y => new { key = y.Key, list = y });
  562. List<ExamScore> exam3Scores = new List<ExamScore>();
  563. foreach (var item in examData) {
  564. if (!string.IsNullOrWhiteSpace($"{_studentId}"))
  565. {
  566. var student = students.Find(x => x.id.Equals($"{_studentId}"));
  567. ExamScore exam3Score = new ExamScore();
  568. exam3Score.name = item.name;
  569. exam3Score.gradeScore=item.total;
  570. exam3Score.xdatas= new List<CodeDouble>
  571. {
  572. new CodeDouble
  573. {
  574. code=student.id,
  575. name= student.name,
  576. value=item.students.Find(x=>x.studentId.Equals(student.id)).scores
  577. }
  578. };
  579. exam3Score.classScore=item.classMore.Find(x=>x.classId.Equals(student.classId)).average;
  580. exam3Scores.Add(exam3Score);
  581. }
  582. else
  583. {
  584. if (isClass)
  585. {
  586. Class clazz = classes.First();
  587. ExamScore exam3Score = new ExamScore();
  588. exam3Score.name = item.name;
  589. exam3Score.gradeScore=item.total;
  590. exam3Score.classScore=item.classMore.Find(x => x.classId.Equals(clazz.id)).average;
  591. exam3Score.xdatas= item.students.Where(y=>y.classId.Equals(clazz.id)).Select(x=>new CodeDouble { code=x.studentId,name= students.Find(z=>z.id.Equals(x.studentId))?.name,value=x.scores }).ToList();
  592. exam3Scores.Add(exam3Score);
  593. }
  594. else
  595. {
  596. ExamScore exam3Score = new ExamScore();
  597. exam3Score.name = item.name;
  598. exam3Score.gradeScore=item.total;
  599. exam3Score.classScore=-1;
  600. exam3Score.xdatas= item.classMore.Select(x => new CodeDouble { code=x.classId, name= grade_classes.Find(z => z.id.Equals(x.classId))?.name, value=x.average }).ToList();
  601. exam3Scores.Add(exam3Score);
  602. }
  603. }
  604. }
  605. var examScores = exam3Scores.Select(x => new {
  606. x.name,
  607. x.gradeScore,
  608. x.classScore,
  609. data = x.xdatas.Where(c => !string.IsNullOrEmpty(c.name)).Select(z => new {
  610. z.code,
  611. z.name,
  612. z.value
  613. })
  614. });
  615. //学生统计数据
  616. dynamic studentStatistics = new ExpandoObject();
  617. if (!string.IsNullOrWhiteSpace($"{_studentId}"))
  618. {
  619. List<ExamDimensionScore> stuExamScores= new List<ExamDimensionScore>();
  620. exam3Scores.ForEach(z => {
  621. var stu = z.xdatas.Find(z => z.code.Equals($"{_studentId}"));
  622. if (stu!=null) {
  623. stuExamScores.Add(new ExamDimensionScore { examName=z.name, classScore=z.classScore,gradeScore=z.gradeScore,stuScore=stu.value });
  624. }
  625. });
  626. var student = students.Find(z => z.id.Equals($"{_studentId}"));
  627. var studentDimension = dimensions.Find(z => z.studentId.Equals($"{_studentId}"));
  628. if (studentDimension==null)
  629. {
  630. studentDimension=new StudentDimensionScore
  631. {
  632. stuExamScores=stuExamScores,
  633. art=60,
  634. classId=student.classId,
  635. className=student.classId,
  636. classRanking=0,
  637. exam=60,
  638. gradeRanking=0,
  639. gscore=60,
  640. intelligence=60,
  641. labour=60,
  642. level="",
  643. picture=student.picture,
  644. pscore=60,
  645. score=60,
  646. sports=60,
  647. studentId=student.id,
  648. studentName=student.name,
  649. subject_music=0,
  650. subject_painting=0,
  651. tscore=60,
  652. virtue=60,
  653. };
  654. }
  655. else {
  656. studentDimension.stuExamScores= stuExamScores;
  657. }
  658. var classDimension = classDimensions.Find(z => z.classId.Equals(student.classId));
  659. studentStatistics= new { studentDimension, inClass = classDimension, inGrade = new { grade_gscore_avg, grade_pscore_avg, grade_tscore_avg } };
  660. studentOverallEducation = overallEducations.FindAll(x => x.studentId.Equals($"{_studentId}")).FirstOrDefault();
  661. if (studentOverallEducation==null)
  662. {
  663. studentOverallEducation = new OverallEducation() { studentId=student.id, name= student.name, classId=student.classId, picture = student.picture, schoolCode= student.schoolId };
  664. }
  665. }
  666. #endregion
  667. return Ok(new
  668. {
  669. examScores,
  670. sports_count60,
  671. sports_count90,
  672. labour_count60,
  673. labour_count90,
  674. virtue_count60,
  675. virtue_count90,
  676. art_count60,
  677. art_count90,
  678. subject_music_count60,
  679. subject_music_count90,
  680. subject_painting_count60,
  681. subject_painting_count90,
  682. achievementScores,
  683. grade_pscore_avg,
  684. grade_tscore_avg,
  685. grade_gscore_avg,
  686. pscore_avg,
  687. tscore_avg,
  688. gscore_avg,
  689. classDimensions,
  690. dimensions=dimensions.OrderByDescending(x => x.score),
  691. data_count,
  692. classCount = classes.Count,
  693. rate90,
  694. rate60,
  695. sports_rate60,
  696. sports_rate90,
  697. art_rate60,
  698. art_rate90,
  699. labour_rate60,
  700. labour_rate90,
  701. virtue_rate60,
  702. virtue_rate90,
  703. subject_music_rate90,
  704. subject_music_rate60,
  705. subject_painting_rate90,
  706. subject_painting_rate60,
  707. studentCount = students.Count(),
  708. studentOverallEducation,
  709. studentStatistics
  710. });
  711. }
  712. catch (Exception ex)
  713. {
  714. await _dingDing.SendBotMsg($"{ex.Message}\n{ex.StackTrace}",GroupNames.成都开发測試群組);
  715. }
  716. return Ok();
  717. }
  718. public class ExamScore {
  719. public double gradeScore { get; set; }
  720. public double classScore { get; set; }
  721. public string name { get; set; }
  722. public List<CodeDouble> xdatas = new List<CodeDouble>();
  723. }
  724. /// <summary>
  725. /// 素养
  726. /// </summary>
  727. public class AchievementScore
  728. {
  729. //class 班级,student 学生
  730. public string type { get; set; } = "class";
  731. /// <summary>
  732. /// 班级名称 或者学生姓名
  733. /// </summary>
  734. public string name { get; set; }
  735. /// <summary>
  736. /// 班级id 或者学生id
  737. /// </summary>
  738. public string id { get; set; }
  739. public double gscore { get; set; }
  740. public double pscore { get; set; }
  741. public double tscore { get; set; }
  742. }
  743. public class ExamDimensionScore
  744. {
  745. public string examName { get; set; }
  746. public double stuScore { get; set; }
  747. public double classScore { get;set; }
  748. public double gradeScore { get; set; }
  749. }
  750. public class ClassDimensionScore
  751. {
  752. public string classId { get; set; }
  753. public string className { get; set; }
  754. public double score { get; set; }
  755. public double gscore { get; set; }
  756. public double pscore { get; set; }
  757. public double tscore { get; set; }
  758. public double exam { get; set; }
  759. public string intelligenceLevel { get; set; }
  760. public double max { get; set; }
  761. public double min { get; set; }
  762. public string level { get; set; }
  763. // 等级人数
  764. public List<CodeLong> intelligenceLevels { get; set; } = new List<CodeLong>();
  765. }
  766. public class StudentDimensionScore
  767. {
  768. public List<ExamDimensionScore> stuExamScores { get; set; } = new List<ExamDimensionScore>();
  769. public string className { get; set; }
  770. public string classId { get; set; }
  771. public string studentId { get; set; }
  772. public string studentName { get; set; }
  773. public string picture { get; set; }
  774. public double score { get; set; }
  775. public double sports { get; set; }
  776. public double art { get; set; }
  777. public double subject_music { get; set; }
  778. public double subject_painting { get; set; }
  779. public double labour { get; set; }
  780. public double intelligence { get; set; }
  781. public double virtue { get; set; }
  782. public double exam { get; set; }
  783. public double gscore { get; set; }
  784. public double pscore { get; set; }
  785. public double tscore { get; set; }
  786. public int classRanking { get; set; }
  787. public int gradeRanking { get; set; }
  788. public string level { get; set; }
  789. }
  790. /// <summary>
  791. /// 学生学生画像是否是默认初始化
  792. /// </summary>
  793. public class StudentDimensionScoreDefault
  794. {
  795. public string studentId { get; set; }
  796. public int sports { get; set; }
  797. public int art { get; set; }
  798. public int subject_music { get; set; }
  799. public int subject_painting { get; set; }
  800. public int labour { get; set; }
  801. public int intelligence { get; set; }
  802. public int virtue { get; set; }
  803. public int exam { get; set; }
  804. public int gscore { get; set; }
  805. public int pscore { get; set; }
  806. public int tscore { get; set; }
  807. }
  808. /*
  809. {
  810. "grades": [
  811. 0,1
  812. ],
  813. "periodId": "463db08d-cbe7-48a0-a81a-fc39b3c1fep1",
  814. "school": "hbcn",
  815. "classIds": [
  816. "e1729a0c-0e7c-4968-bec9-21254b70325b",
  817. "b44694b7-4cb2-46b8-8986-106696c4a282"
  818. ]
  819. }
  820. */
  821. }
  822. }