using Microsoft.Azure.Cosmos; using Azure.Messaging.ServiceBus; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models.Cosmos.Common; namespace TEAMModelOS.SDK.Models.Service { public static class ArtService { public static List GetParentByChildId(List quotas, string childId) { List list_quotas = new List(); list_quotas = TreeToList(quotas, list_quotas, null); List parents = new List(); parents = GetParents(list_quotas, parents, $"{childId}"); if (parents.IsNotEmpty()) { int len = parents.Count; parents.ForEach(x => { x.level= len-x.level+1; }); } return parents; } private static List GetParents(List list, List parents, string cid, int level = 1) { var child = list.Find(x => x.id.Equals(cid)); if (child != null) { child.level = level; parents.Add(child); if (!child.pid.Equals(child.id)) { level++; return GetParents(list, parents, child.pid, level); } else { return parents; } } else { return parents; } } private static List TreeToList(List trees, List nodes, string pid) { List list = new List(); trees.ForEach(x => { var node = new ArtQuota { pid = string.IsNullOrWhiteSpace(pid) ? x.id : pid, id = x.id, name = x.name, percent = x.percent, type = x.type, }; list.Add(node); }); nodes.AddRange(list); foreach (ArtQuota tree in trees) { if (tree.children.IsNotEmpty()) { TreeToList(tree.children, nodes, tree.id); } } return nodes; } public async static Task GenArtPDF (List studentIds, string _artId, string _schoolId, string head_lang,AzureServiceBusFactory _serviceBus, IConfiguration _configuration) { var messageBlobPDF = new ServiceBusMessage(new { studentIds, artId= _artId, schoolCode = $"{_schoolId}", headLang= head_lang, bizType = "ArtStudentPdf" }.ToJsonString()); var GenPdfQueue = _configuration.GetValue("Azure:ServiceBus:GenPdfQueue"); await _serviceBus.GetServiceBusClient().SendMessageAsync(GenPdfQueue, messageBlobPDF); } public async static Task<(List studentPdfs, List artResults)> GenStuArtPDF(List studentIds, string _artId,string _schoolId,string head_lang ,AzureCosmosFactory _azureCosmos, CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing) { var client = _azureCosmos.GetCosmosClient(); string query = $" select value c from c where c.school = '{_schoolId}' "; if (studentIds.Any()) { query = $" select value c from c where c.school = '{_schoolId}' and c.studentId in ({string.Join(",", studentIds.Select(z => $"'{z}'"))})"; } List artResults = new List(); await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIteratorSql (queryText: query, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtResult-{_artId}") })) { artResults.Add(item); } School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync($"{_schoolId}", new PartitionKey("Base")); string path = Path.Combine("", $"Lang/{head_lang}.json"); string comment1 = ""; string comment2 = ""; string comment3 = ""; string comment4 = ""; string comment5 = ""; string comment_subject_music = ""; string comment_subject_painting = ""; var jsonDoc = readFileJson(path); if (jsonDoc != null) { if (jsonDoc.RootElement.TryGetProperty("art-template-comment1", out JsonElement _c1)) { comment1 = $"{_c1}"; } if (jsonDoc.RootElement.TryGetProperty("art-template-comment2", out JsonElement _c2)) { comment2 = $"{_c2}"; } if (jsonDoc.RootElement.TryGetProperty("art-template-comment3", out JsonElement _c3)) { comment3 = $"{_c3}"; } if (jsonDoc.RootElement.TryGetProperty("art-template-comment4", out JsonElement _c4)) { comment4 = $"{_c4}"; } if (jsonDoc.RootElement.TryGetProperty("art-template-comment5", out JsonElement _c5)) { comment5 = $"{_c5}"; } if (jsonDoc.RootElement.TryGetProperty("art-template-subject_music", out JsonElement _subject_music)) { comment_subject_music = $"{_subject_music}"; } if (jsonDoc.RootElement.TryGetProperty("art-template-subject_painting", out JsonElement _subject_painting)) { comment_subject_painting = $"{_subject_painting}"; } } ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync($"{_artId}", new PartitionKey($"Art-{_schoolId}")); ArtSetting artSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync($"{school.areaId}", new PartitionKey($"ArtSetting")); var allExamIds = art.settings.SelectMany(x => x.task).Where(z => z.type == 1); var subjects = art.subjects; //获取学校的所有艺术科目的uuid,并映射找到相应的知识点,知识块。 var schoolSubjects = school.period.SelectMany(x => x.subjects).Where(s => !string.IsNullOrWhiteSpace(s.bindId) && subjects.Select(z => z.id).Contains(s.bindId)); StringBuilder sql = new StringBuilder($"select value(c) from c"); List>> subjectBindBlocks = new List>>(); foreach (var schSub in schoolSubjects) { List blocks = new List(); string code = $"Knowledge-{_schoolId}-{schSub.id}"; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School") .GetItemQueryIteratorSql(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") })) { item.blocks.ForEach(x => { var block = blocks.Find(z => z.name.Equals(x.name)); if (block != null) { block.points.AddRange(x.points); } else { blocks.Add(x); } }); } subjectBindBlocks.Add(new KeyValuePair>(schSub.bindId, blocks)); } List exams = new List(); List examResults = new(); if (allExamIds.Any()) { var queryExam = $"select value c from c where c.id in ({string.Join(",", allExamIds.Select(x => $"'{x.acId}'"))}) "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIteratorSql(queryText: queryExam, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{_schoolId}") })) { exams.Add(item); } foreach (var allexamId in allExamIds) { var queryResult = $"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,c.examId from c where c.examId = '{allexamId.acId}' and c.subjectId = '{allexamId.subject}' "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIteratorSql(queryText: queryResult, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{allexamId.acId}") })) { examResults.Add(item); } } } (List rmembers, List groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, art.classes, art.school); List studentPdfs = new List(); artResults.ForEach(x => { var allSubject = x.results.GroupBy(g => g.quotaId).Select(s => new { key = s.Key, list = s.ToList() }).ToList(); var groupSubject = x.results.GroupBy(g => $"{g.quotaId}-{g.subjectId}").Select(s => new { key = s.Key, list = s.ToList() }).ToList(); //综合-所有科目的艺术评测指标维度。 List allSubjectArtQuotaPdfs = new List(); allSubject.ForEach(a => { ArtQuotaPdf artPdf = new ArtQuotaPdf(); List parents = ArtService.GetParentByChildId(artSetting.quotas, $"{a.key}"); parents.ForEach(x => { switch (true) { case bool when x.level == 1: artPdf.quota1 = x.id; artPdf.quotaN1 = x.name; artPdf.quotaP1 = x.percent; if (a.key.Equals(x.id)) { artPdf.quotaName = x.name; } break; case bool when x.level == 2: artPdf.quota2 = x.id; artPdf.quotaN2 = x.name; artPdf.quotaP2 = x.percent; if (a.key.Equals(x.id)) { artPdf.quotaName = x.name; } break; case bool when x.level == 3: artPdf.quota3 = x.id; artPdf.quotaN3 = x.name; artPdf.quotaP3 = x.percent; if (a.key.Equals(x.id)) { artPdf.quotaName = x.name; } break; } }); var noneScore = a.list.FindAll(x => x.score == -1); if (!noneScore.IsNotEmpty()) { //全部未打分。 if (noneScore.Count >= art.subjects.Count) { artPdf.quotaId = a.key; artPdf.score = 0; artPdf.scoreData = "-"; artPdf.percent = "0"; } else { //有一部分打分的,只算有分的平均分。 var hasScore = a.list.FindAll(x => x.score >= 0); if (hasScore.IsNotEmpty()) { var avgScore = hasScore.Sum(x => x.score) * 1.0 / a.list.Count; var avg = decimal.Round(decimal.Parse($"{avgScore}"), 2); artPdf.quotaId = a.key; artPdf.score = double.Parse($"{avg}"); artPdf.scoreData = $"{avg}"; artPdf.percent = $"{avg}"; } else { artPdf.quotaId = a.key; artPdf.score = 0; artPdf.scoreData = "-"; artPdf.percent = "0"; } } } else { artPdf.quotaId = a.key; artPdf.score = 0; artPdf.scoreData = "-"; artPdf.percent = "0"; } allSubjectArtQuotaPdfs.Add(artPdf); }); string level = ""; double allScore = 0; if (allSubjectArtQuotaPdfs.Any()) { allScore = allSubjectArtQuotaPdfs.Sum(a => a.score) / allSubjectArtQuotaPdfs.Count; } if (allScore >= 100) { allScore = 100; level = "优秀(A+)"; } if (allScore <= 0) { allScore = 0; level = "待及格(D)"; } if (allScore < 100) { artSetting.reviewLevel.ForEach(r => { if (r.value[0] <= allScore && r.value[1] > allScore) { level = r.code; } }); } var rmbs = rmembers.FindAll(r => r.id.Equals(x.studentId) && r.type == 2 && x.code.Equals(x.school)); if (rmbs.IsNotEmpty()) { x.studentName = rmbs[0].name; } List classNames = new List(); HashSet periodIds = new HashSet(); x.classIds.ForEach(c => { var gps = groups.FindAll(g => g.id.Equals(c)); if (gps.IsNotEmpty()) { classNames.Add(gps[0].name); if (!string.IsNullOrWhiteSpace(gps[0].periodId)) { periodIds.Add(gps[0].periodId); } } }); allSubjectArtQuotaPdfs.ForEach(x => x.level = level); var allSubjectQuotas = allSubjectArtQuotaPdfs.OrderBy(o => o.quota1).ThenBy(o => o.quota2).ThenBy(o => o.quota3); StringBuilder comment = new StringBuilder(); switch (true) { case bool when level.Contains("(A+)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优异")); break; case bool when level.Contains("(A)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优秀")); break; case bool when level.Contains("(B+)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优良")); break; case bool when level.Contains("(B)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现良好")); break; case bool when level.Contains("(C+)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "还需加强")); break; case bool when level.Contains("(C)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "有待提高")); break; case bool when level.Contains("(D)"): comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "还需努力")); break; } var score80 = allSubjectArtQuotaPdfs.Where(x => x.score >= 80); if (score80.Any()) { List quota = new List(); var quota3s = score80.Where(c => !string.IsNullOrWhiteSpace(c.quota3)).Select(z => z.quotaN3); if (quota3s.Any()) { quota.AddRange(quota3s); } var quota2s = score80.Where(c => string.IsNullOrWhiteSpace(c.quota3) && !string.IsNullOrWhiteSpace(c.quota2)).Select(z => z.quotaN2); if (quota2s.Any()) { quota.AddRange(quota2s); } comment.Append(comment2.Replace("{quotasHigh}", string.Join("、", quota))); } var score60 = allSubjectArtQuotaPdfs.Where(x => x.score < 60); if (score60.Any()) { List quota = new List(); var quota3s = score60.Where(c => !string.IsNullOrWhiteSpace(c.quota3)).Select(z => z.quotaN3); if (quota3s.Any()) { quota.AddRange(quota3s); } var quota2s = score60.Where(c => string.IsNullOrWhiteSpace(c.quota3) && !string.IsNullOrWhiteSpace(c.quota2)).Select(z => z.quotaN2); if (quota2s.Any()) { quota.AddRange(quota2s); } comment.Append(comment3.Replace("{quotasLow}", string.Join("、", quota))); } string periodId = ""; string periodName = ""; if (periodIds.Any()) { var ps = school.period.FindAll(x => periodIds.Contains(x.id)); if (ps.Any()) { periodName = String.Join(",", ps.Select(x => x.name)); periodId = String.Join(",", ps.Select(x => x.id)); } } List subjectPdfs = new List(); exams.ForEach(exam => { var result = examResults.FindAll(e => e.examId.Equals(exam.id)); if (result.Any()) { var datas = DoKnowledgePoint(result.First(), exam, x.studentId); if (exam.subjects.Any()) { ArtSubjectPdf artSubjectPdf = new ArtSubjectPdf() { subjectId = exam.subjects.First().id, subjectName = exam.subjects.First().name }; datas.pointScores.Value.ForEach(k => { var artPointPdfs = GetBlockAndDimension(k.score, k.tscore, artSubjectPdf.subjectId, k.name, subjectBindBlocks, artSetting); artSubjectPdf.pointPdfs.AddRange(artPointPdfs); }); var pointHigh = artSubjectPdf.pointPdfs.Where(z => z.percent >= 0.8).Select(z => z.point).ToHashSet(); var pointLow = artSubjectPdf.pointPdfs.Where(z => z.percent < 0.6).Select(z => z.point).ToHashSet(); StringBuilder comment = new StringBuilder(); if (pointHigh.Any()) { comment.Append(comment4.Replace("{pointHigh}", string.Join("、", pointHigh))); } if (pointLow.Any()) { comment.Append(comment5.Replace("{pointLow}", string.Join("、", pointLow))); } if (artSubjectPdf.subjectId.Equals("subject_music")) { comment.Append(comment_subject_music); } if (artSubjectPdf.subjectId.Equals("subject_painting")) { comment.Append(comment_subject_painting); } artSubjectPdf.comment = comment.ToString(); subjectPdfs.Add(artSubjectPdf); } } }); ArtStudentPdf studentPdf = new ArtStudentPdf { artId = art.id, schoolCode = school.id, schoolName = school.name, periodId = periodId, periodName = periodName, studentId = x.studentId, studentName = x.studentName, picture = x.picture, classNames = classNames, artName = art.name, level = level, score = allScore, allSubjectQuotas = allSubjectQuotas.ToList(), comment = comment.ToString(), subjectPdfs = subjectPdfs, }; studentPdfs.Add(studentPdf); }); // _ = _httpTrigger.RequestHttpTrigger(new { studentPdfs = studentPdfs, artResults, schoolCode = $"{_schoolId}" }, _option.Location, "gen-art-pdf"); return (studentPdfs, artResults); } private static JsonDocument readFileJson(string path) { var sampleJson = System.IO.File.ReadAllBytes(path).AsSpan(); Utf8JsonReader reader = new Utf8JsonReader(sampleJson); if (JsonDocument.TryParseValue(ref reader, out JsonDocument jsonDoc)) { return jsonDoc; } else { return null; } } //获取本次评测所有科目结算结果 /* List examResults = new(); ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync(examId.ToString(), new PartitionKey($"Exam-{code}")); 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 = '{examId}' and c.subjectId = '{subjectId}' "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIteratorSql(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{examId}") })) { examResults.Add(item); }*/ private static (KeyValuePair> knowledgeName, KeyValuePair> pointScore, KeyValuePair> pointTScore, KeyValuePair> pointScores) DoKnowledgePoint(ExamResult exam, ExamInfo info, string studentId) { HashSet knowledge = new(); List point = new(); List> result = new(); List classes = new(); //定位试卷信息 int index = 0; foreach (ExamSubject subject in info.subjects) { if (subject.id.Equals(exam.subjectId)) { break; } else { index++; } } if (info.papers[index].knowledge != null && info.papers[index].knowledge.Count > 0) { info.papers[index].knowledge.ForEach(k => { k.ForEach(e => { knowledge.Add(e); }); }); } else { return (default, default, default, default); } point = info.papers[index].point; result = exam.studentScores; classes = exam.classes; List knowledgeName = new List(); foreach (string cla in knowledge) { knowledgeName.Add(cla); } for (int k = 0; k < knowledgeName.Count; k++) { if (null == knowledgeName[k]) { knowledgeName.Remove(knowledgeName[k]); } } List knowScore = new(); //学生得分情况 List<(string name, double score)> pointScore = new(); List<(string name, double score)> pointTScore = new(); List<(string name, double score, double tscore)> pointScores = new(); for (int k = 0; k < knowledgeName.Count; k++) { double OnePoint = 0; List itemNo = new(); int n = 0; double scores = 0; info.papers[index].knowledge.ForEach(kno => { if (kno.Contains(knowledgeName[k])) { var itemPersent = kno.Count > 0 ? 1 / Convert.ToDouble(kno.Count) : 0; OnePoint += point[n] * itemPersent; int stuIndex = exam.studentIds.IndexOf(studentId); if (exam.studentScores[stuIndex][n] > 0) { scores += exam.studentScores[stuIndex][n] * itemPersent; } } n++; }); //单个知识点的配分 pointScore.Add((knowledgeName[k], OnePoint)); pointTScore.Add((knowledgeName[k], scores)); pointScores.Add((knowledgeName[k], OnePoint, scores)); } KeyValuePair> key1 = new(exam.subjectId, knowledgeName); KeyValuePair> key2 = new(exam.subjectId, pointScore); KeyValuePair> key3 = new(exam.subjectId, pointTScore); KeyValuePair> key4 = new(exam.subjectId, pointScores); return (key1, key2, key3, key4); } private static List GetBlockAndDimension(double score, double tscore, string subjectId, string point, List>> subjectBindBlocks, ArtSetting artSetting) { var block = subjectBindBlocks.Find(z => z.Key.Equals(subjectId)); List artPointPdfs = new List(); if (!string.IsNullOrWhiteSpace(block.Key)) { block.Value.ForEach(z => { if (z.points.Contains(point)) { var dims = artSetting.dimensions.FindAll(m => m.blocks.Contains(z.name)); if (dims.Any()) { foreach (var dim in dims) { artPointPdfs.Add( new ArtPointPdf { dimension = dim.dimension, block = z.name, point = point, totalScore = score, score = tscore, percent = score > 0 ? tscore * 1.0 / score : 0, } ); } } } }); } return artPointPdfs; } } }