CrazyIter_Bin 3 years ago
parent
commit
3b5c7424fc

+ 0 - 527
TEAMModelAPI/Controllers/School/ActivityController.cs

@@ -1,527 +0,0 @@
-using Azure.Cosmos;
-using HTEXLib.Translator;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Options;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.Json;
-using System.Threading.Tasks;
-using TEAMModelOS.Filter;
-using TEAMModelOS.Models;
-using TEAMModelOS.Models.Dto;
-using TEAMModelOS.SDK;
-using TEAMModelOS.SDK.DI;
-using TEAMModelOS.SDK.Extension;
-using TEAMModelOS.SDK.Models;
-
-namespace TEAMModelAPI.Controllers
-{
-    [ProducesResponseType(StatusCodes.Status200OK)]
-    [ProducesResponseType(StatusCodes.Status400BadRequest)]
-    [ApiController]
-    [Route("activity")]
-    public class ActivityController:ControllerBase
-    {
-        public AzureCosmosFactory _azureCosmos;
-        private readonly AzureStorageFactory _azureStorage;
-        private readonly AzureRedisFactory _azureRedis;
-        private readonly DingDing _dingDing;
-        private readonly Option _option;
-        private readonly IConfiguration _configuration;
-        public DOXC2HTMLTranslator _DOXC2HTMLTranslator { get; set; }
-        //public PPTX2HTEXTranslator _PPTX2HTEXTranslator { get; set; }
-        public HTML2ITEMV3Translator _HTML2ITEMV3Translator { get; set; }
-        public ActivityController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration)
-        {
-            _azureCosmos = azureCosmos;
-            _azureStorage = azureStorage;
-            _azureRedis = azureRedis;
-            _dingDing = dingDing;
-            _option = option?.Value;
-            _configuration = configuration;
-        }
-
-        [ProducesDefaultResponseType]
-        [HttpGet("import-exam")]
-        [ApiToken(Auth = "91", Name = "汇入评测基础数据", Limit = false)]
-        public async Task<IActionResult> importExam(JsonElement request)
-        {
-            //获取评测的ID
-            if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
-            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
-            try
-            {
-                var client = _azureCosmos.GetCosmosClient();
-                ExamInfo info = exam.ToObject<ExamInfo>();
-                info.progress = "going";
-                await client.GetContainer(Constant.TEAMModelOS, "Common").UpsertItemAsync(info, new PartitionKey($"Exam-{code}"));
-                return Ok(new { info });
-            }
-            catch (Exception e)
-            {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/import-exam()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
-                return BadRequest();
-            }
-        }
-        [ProducesDefaultResponseType]
-        [HttpGet("upsert-record")]
-        [ApiToken(Auth = "90", Name = "批量汇入作答数据", Limit = false)]
-        public async Task<IActionResult> upsertRecord(JsonElement request)
-        {
-
-            if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
-            if (!request.TryGetProperty("students", out JsonElement students)) return BadRequest();
-            if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
-            //根据不同评测的类型返回对应的编码
-            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
-            try
-            {
-                var client = _azureCosmos.GetCosmosClient();
-                //List<string> ids = students.ToObject<List<string>>();
-                List<students> stus = students.ToObject<List<students>>();
-                ExamInfo info = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.GetString(), new PartitionKey($"Exam-{code}"));
-                string classCode = info.scope.Equals("school") ? info.school : info.creatorId;
-                List<ExamClassResult> examClassResults = new();
-                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
-                           queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
-                           requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{classCode}") }))
-                {
-                    examClassResults.Add(item);
-                }
-                int n = 0;
-                foreach (ExamSubject subject in info.subjects)
-                {
-                    if (!subject.id.Equals(subjectId.GetString()))
-                    {
-                        n++;
-                    }
-                    else
-                    {
-                        break;
-                    }
-                }
-                //获取试卷信息
-                PaperSimple standerAnswers = new PaperSimple();
-                List<List<string>> standard = new List<List<string>>();
-                List<double> points = new List<double>();
-                standerAnswers = info.papers[n];
-                standard = standerAnswers.answers;
-                points = standerAnswers.point;
-                int rule = standerAnswers.multipleRule;
-                List<string> value = new List<string>();
-                await foreach (var s in stuTask(stus, examClassResults, standard, points, rule, info, subjectId.GetString(), client))
-                {
-                    if (s.code == 1)
-                    {
-                        value.Add(s.value);
-                    }
-                }
-                if (value.Count > 0)
-                {
-                    return Ok(new { code = 1, msg = "学生ID异常", value = value });
-                }
-                else
-                {
-                    return Ok(new { code = 0 });
-                }
-
-            }
-            catch (Exception e)
-            {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},activity/upsert-record()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
-                return BadRequest();
-            }
-
-        }
-        private async IAsyncEnumerable<(int code, string value)> stuTask(List<students> stus, List<ExamClassResult> examClassResults, List<List<string>> standard,
-            List<double> points, int rule, ExamInfo info, string subjectId, CosmosClient client)
-        {
-            foreach (var s in stus)
-            {
-                string value = "";
-                int code = 0;
-                List<List<string>> ans = s.answer;
-                bool isExist = examClassResults.Exists(e => e.studentIds.Contains(s.id));
-                if (!isExist)
-                {
-                    value = s.id;
-                    code = 1;
-                }
-                else
-                {
-                    foreach (ExamClassResult result in examClassResults)
-                    {
-                        if (!result.studentIds.Contains(s.id))
-                        {
-                            continue;
-                        }
-                        else
-                        {
-                            int newIndex = result.studentIds.IndexOf(s.id);
-                            StringBuilder builder = new StringBuilder();
-                            builder.Append(result.examId).Append('/');
-                            builder.Append(result.subjectId).Append('/');
-                            builder.Append(s.id).Append('/');
-                            builder.Append("ans.json");
-                            result.studentAnswers[newIndex].Clear();
-                            result.studentAnswers[newIndex].Add(builder.ToString());
-                            for (int i = 0; i < ans.Count; i++)
-                            {
-                                if (ans[i] == null)
-                                {
-                                    continue;
-                                    //ans[i] = new List<string>();
-                                }
-                                var ac = ans[i].Count;
-                                var sc = standard[i].Count;
-                                //记录次数
-                                int n = 0;
-                                //算分处理
-                                if (sc > 0)
-                                {
-                                    result.ans[newIndex][i] = ans[i];
-                                    if (ac == sc && sc == 1)
-                                    {
-                                        foreach (string right in ans[i])
-                                        {
-                                            if (standard[i].Contains(right))
-                                            {
-                                                result.studentScores[newIndex][i] = points[i];
-                                            }
-                                            else
-                                            {
-                                                result.studentScores[newIndex][i] = 0;
-                                            }
-                                        }
-
-                                    }
-                                    else
-                                    {
-                                        if (rule > 0)
-                                        {
-                                            int falseCount = 0;
-                                            if (ac > 0)
-                                            {
-                                                foreach (string obj in ans[i])
-                                                {
-                                                    if (!standard[i].Contains(obj))
-                                                    {
-                                                        falseCount++;
-                                                    }
-                                                }
-                                                switch (rule)
-                                                {
-                                                    case 1:
-                                                        if (ac == sc)
-                                                        {
-                                                            if (falseCount == 0)
-                                                            {
-                                                                result.studentScores[newIndex][i] = points[i];
-                                                            }
-                                                            else
-                                                            {
-                                                                result.studentScores[newIndex][i] = 0;
-                                                            }
-                                                        }
-                                                        else
-                                                        {
-                                                            result.studentScores[newIndex][i] = 0;
-                                                        }
-                                                        break;
-                                                    case 2:
-                                                        if (falseCount > 0)
-                                                        {
-                                                            result.studentScores[newIndex][i] = 0;
-                                                        }
-                                                        else
-                                                        {
-                                                            if (ac == sc)
-                                                            {
-                                                                result.studentScores[newIndex][i] = points[i];
-                                                            }
-                                                            else
-                                                            {
-                                                                result.studentScores[newIndex][i] = points[i] / 2;
-                                                            }
-
-                                                        }
-                                                        break;
-                                                    case 3:
-                                                        if (falseCount > 0)
-                                                        {
-                                                            result.studentScores[newIndex][i] = 0;
-                                                        }
-                                                        else
-                                                        {
-                                                            if (ac == sc)
-                                                            {
-                                                                result.studentScores[newIndex][i] = points[i];
-                                                            }
-                                                            else
-                                                            {
-                                                                result.studentScores[newIndex][i] = System.Math.Round((double)ac / sc * points[i], 1);
-                                                            }
-
-                                                        }
-                                                        break;
-                                                    case 4:
-                                                        if (ac == sc)
-                                                        {
-                                                            result.studentScores[newIndex][i] = points[i];
-                                                        }
-                                                        else
-                                                        {
-                                                            double persent = (double)(sc - 2 * falseCount) / sc;
-                                                            if (persent <= 0)
-                                                            {
-                                                                result.studentScores[newIndex][i] = 0;
-                                                            }
-                                                            else
-                                                            {
-                                                                result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
-                                                            }
-                                                        }
-                                                        break;
-                                                }
-                                            }
-                                            else
-                                            {
-                                                result.studentScores[newIndex][i] = 0;
-                                            }
-
-                                        }
-                                    }
-                                }
-                            }
-                            bool flag = true;
-                            foreach (List<double> scores in result.studentScores)
-                            {
-                                foreach (double score in scores)
-                                {
-                                    if (score == -1)
-                                    {
-                                        flag = false;
-                                        break;
-                                    }
-                                }
-                            }
-                            if (flag)
-                            {
-                                result.progress = true;
-                                info.subjects.ForEach(s =>
-                                {
-                                    if (s.id.Equals(subjectId.ToString()))
-                                    {
-                                        s.classCount += 1;
-                                    }
-                                });
-                                await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, info.id.ToString(), new PartitionKey($"{info.code}"));
-                            }
-                            result.sum[newIndex] = result.studentScores[newIndex].Sum();
-                            await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
-                            break;
-                        }
-                    }
-                }
-                yield return (code, value);
-            }
-        }
-        [ProducesDefaultResponseType]
-        [HttpGet("parse-word")]
-        [ApiToken(Auth = "92", Name = "录入试卷数据", Limit = false)]
-        public async Task<IActionResult> ParseWord([FromForm] FileDto fileDto)
-        {
-            if (!FileType.GetExtention(fileDto.file.FileName).ToLower().Equals("docx"))
-            {
-                return BadRequest(new Dictionary<string, object> { { "msg", "type is not docx!" }, { "code", 404} });
-            }
-
-            try
-            {
-                var client = _azureCosmos.GetCosmosClient();
-                var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(fileDto.examId, new PartitionKey($"Exam-{fileDto.code}"));
-                ExamInfo examInfo;
-                if (response.Status == 200)
-                {
-                    using var json = await JsonDocument.ParseAsync(response.ContentStream);
-                    examInfo = json.ToObject<ExamInfo>();
-
-                }
-                else
-                {
-                    return Ok(new { error = 404, msg = "请先导入评测信息" });
-                }
-                foreach (PaperSimple paper in examInfo.papers)
-                {
-                    if (paper.id.Contains(fileDto.subjectId))
-                    {
-                        return Ok(new { error = 500, msg = "该试卷信息已存在" });
-                    }
-                }
-                PaperSimple simple = new();
-                var doc = _DOXC2HTMLTranslator.Translate(fileDto.file.OpenReadStream());
-                (List<HTEXLib.DOCX.Models.ItemInfo> tests, List<string> error) = _HTML2ITEMV3Translator.Translate(doc);
-                List<Task<string>> tasks = new List<Task<string>>();
-                PaperDto paperDto = new()
-                {
-                    id = Guid.NewGuid().ToString(),
-                    name = fileDto.name,
-                    code = fileDto.code,
-                    scope = "school",
-                    multipleRule = fileDto.multipleRule,
-                    gradeIds = fileDto.gradeIds,
-                    subjectId = fileDto.subjectId,
-                    periodId = fileDto.periodId
-                };
-                foreach (HTEXLib.DOCX.Models.ItemInfo item in tests)
-                {
-                    Slides slides = new();
-                    ItemDto dto = new();
-                    Scoring scoring = new();
-                    dto.id = Guid.NewGuid().ToString();
-                    dto.exercise.answer = item.answer;
-                    dto.exercise.explain = item.explain;
-                    dto.exercise.type = item.type;
-                    dto.exercise.opts = item.option.Count;
-                    dto.exercise.knowledge = item.knowledge;
-                    dto.exercise.field = item.field;
-                    dto.exercise.level = item.level;
-                    dto.exercise.subjectId = fileDto.subjectId;
-                    dto.exercise.periodId = fileDto.periodId;
-                    dto.exercise.gradeIds = fileDto.gradeIds;
-                    slides.url = dto.id + ".json";
-                    slides.type = dto.exercise.type;
-                    scoring.ans = dto.exercise.answer;
-                    scoring.score = dto.exercise.score;
-                    scoring.knowledge = dto.exercise.knowledge;
-                    scoring.field = dto.exercise.field;
-                    slides.scoring = scoring;
-                    //添加试卷信息
-                    paperDto.slides.Add(slides);
-                    if (!slides.type.Equals("compose"))
-                    {
-                        simple.point.Add(dto.exercise.score);
-                        simple.answers.Add(dto.exercise.answer);
-                        simple.knowledge.Add(dto.exercise.knowledge);
-                        simple.type.Add(dto.exercise.type);
-                        simple.field.Add((int)dto.exercise.field);
-                    }
-                    if (item.children.Count > 0)
-                    {
-                        foreach (HTEXLib.DOCX.Models.ItemInfo its in item.children)
-                        {
-                            Slides cslides = new();
-                            Scoring cscoring = new();
-                            ItemDto dtoChildren = new ItemDto();
-                            dtoChildren.id = Guid.NewGuid().ToString();
-                            dtoChildren.pid = dto.id;
-                            dtoChildren.exercise.answer = its.answer;
-                            dtoChildren.exercise.explain = its.explain;
-                            dtoChildren.exercise.type = its.type;
-                            dtoChildren.exercise.opts = its.option.Count;
-                            dtoChildren.exercise.knowledge = its.knowledge;
-                            dtoChildren.exercise.field = its.field;
-                            dtoChildren.exercise.level = its.level;
-                            dtoChildren.exercise.scope = "school";
-                            dtoChildren.exercise.score = its.score;
-                            dtoChildren.exercise.subjectId = fileDto.subjectId;
-                            dtoChildren.exercise.periodId = fileDto.periodId;
-                            dtoChildren.exercise.gradeIds = fileDto.gradeIds;
-                            dtoChildren.exercise.children.Add(dtoChildren.id);
-                            info info1 = new();
-                            info1.uid = dtoChildren.id;
-                            info1.question = its.question;
-                            info1.option = its.option;
-                            dtoChildren.item.Add(info1);
-                            dto.exercise.children.Add(dtoChildren.id);
-                            //处理子题的slides
-                            cslides.url = dtoChildren.id + ".json";
-                            cslides.type = dtoChildren.exercise.type;
-                            cscoring.ans = dtoChildren.exercise.answer;
-                            cscoring.score = dtoChildren.exercise.score;
-                            cscoring.knowledge = dtoChildren.exercise.knowledge;
-                            cscoring.field = dtoChildren.exercise.field;
-                            cslides.scoring = scoring;
-                            paperDto.slides.Add(cslides);
-                            //添加试卷信息
-                            simple.point.Add(dtoChildren.exercise.score);
-                            simple.answers.Add(dto.exercise.answer);
-                            simple.knowledge.Add(dto.exercise.knowledge);
-                            simple.type.Add(dto.exercise.type);
-                            simple.field.Add((int)dto.exercise.field);
-
-                            StringBuilder stringBuilder = new StringBuilder();
-                            stringBuilder.Append(fileDto.examId).Append("/");
-                            stringBuilder.Append("paper").Append("/");
-                            stringBuilder.Append(fileDto.subjectId).Append("/");
-                            stringBuilder.Append(dtoChildren.id + ".json");
-                            tasks.Add(_azureStorage.UploadFileByContainer(fileDto.code, dtoChildren.ToJsonString(), "exam", stringBuilder.ToString(), false));
-                        }
-                    }
-                    info @info = new();
-                    @info.uid = dto.id;
-                    @info.question = item.question;
-                    @info.option = item.option;
-                    dto.item.Add(@info);
-                    dto.exercise.scope = "school";
-                    dto.exercise.score = item.score;
-                    StringBuilder builder = new StringBuilder();
-                    builder.Append(fileDto.examId).Append('/');
-                    builder.Append("paper").Append('/');
-                    builder.Append(fileDto.subjectId).Append('/');
-                    builder.Append(dto.id + ".json");
-                    tasks.Add(_azureStorage.UploadFileByContainer(fileDto.code, dto.ToJsonString(), "exam", builder.ToString(), false));
-
-
-                }
-                StringBuilder paperBuilder = new StringBuilder();
-                paperBuilder.Append(fileDto.examId).Append('/');
-                paperBuilder.Append("paper").Append('/');
-                paperBuilder.Append(fileDto.subjectId).Append('/');
-                paperBuilder.Append("index.json");
-                tasks.Add(_azureStorage.UploadFileByContainer(fileDto.code, paperDto.ToJsonString(), "exam", paperBuilder.ToString(), false));
-
-                //开始给ExamInfo paper赋值
-                simple.id = fileDto.subjectId;
-                simple.code = "Paper-" + fileDto.code;
-                simple.name = fileDto.name;
-                simple.blob = paperBuilder.ToString().Replace("index.json", "");
-                simple.scope = "school";
-                simple.multipleRule = fileDto.multipleRule;
-
-                examInfo.papers.Add(simple);
-                await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(examInfo, examInfo.id, new PartitionKey($"{examInfo.code}"));
-                await Task.WhenAll(tasks);
-
-                return Ok(new { code = 200 });
-            }
-            catch (Exception e)
-            {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/word()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
-                return BadRequest();
-            }
-
-        }
-
-        private class students
-        {
-            public string id { get; set; }
-            public List<List<string>> answer { get; set; }
-        }
-        public class FileDto
-        {
-            public string periodId { get; set; }
-            public string code { get; set; }
-            public string name { get; set; }
-            public int multipleRule { get; set; }
-            public string examId { get; set; }
-            public string subjectId { get; set; }
-            public List<string> gradeIds { get; set; }
-            public IFormFile file { get; set; }
-        }
-    }
-}

+ 479 - 18
TEAMModelAPI/Controllers/School/ExamController.cs

@@ -24,6 +24,9 @@ using Microsoft.Extensions.Configuration;
 using TEAMModelOS.Filter;
 using Microsoft.AspNetCore.Authorization;
 using HTEXLib.COMM.Helpers;
+using HTEXLib.Translator;
+using TEAMModelOS.Models.Dto;
+
 namespace TEAMModelAPI.Controllers
 {
     [ProducesResponseType(StatusCodes.Status200OK)]
@@ -38,6 +41,9 @@ namespace TEAMModelAPI.Controllers
         private readonly DingDing _dingDing;
         private readonly Option _option;
         private readonly IConfiguration _configuration;
+        public DOXC2HTMLTranslator _DOXC2HTMLTranslator { get; set; }
+        //public PPTX2HTEXTranslator _PPTX2HTEXTranslator { get; set; }
+        public HTML2ITEMV3Translator _HTML2ITEMV3Translator { get; set; }
         public ExamController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration)
         {
             _azureCosmos = azureCosmos;
@@ -48,30 +54,485 @@ namespace TEAMModelAPI.Controllers
             _configuration = configuration;
         }
 
-        /// <summary>
-        ///  获取试卷和评测的条件信息
-        /// </summary>
-        /// <param name="request"></param>
-        /// <returns></returns>
         [ProducesDefaultResponseType]
-        [HttpPost("get-paper-exam-condition")]
-        [ApiToken(Auth = "11", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
-        public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
+        [HttpGet("import-exam")]
+        [ApiToken(Auth = "201", Name = "汇入评测基础数据", Limit = false)]
+        public async Task<IActionResult> importExam(JsonElement request)
+        {
+            //获取评测的ID
+            if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
+            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                ExamInfo info = exam.ToObject<ExamInfo>();
+                info.progress = "going";
+                await client.GetContainer(Constant.TEAMModelOS, "Common").UpsertItemAsync(info, new PartitionKey($"Exam-{code}"));
+                return Ok(new { info });
+            }
+            catch (Exception e)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/import-exam()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
+            }
+        }
+        [ProducesDefaultResponseType]
+        [HttpGet("upsert-record")]
+        [ApiToken(Auth = "202", Name = "批量汇入作答数据", Limit = false)]
+        public async Task<IActionResult> upsertRecord(JsonElement request)
+        {
+
+            if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
+            if (!request.TryGetProperty("students", out JsonElement students)) return BadRequest();
+            if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
+            //根据不同评测的类型返回对应的编码
+            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                //List<string> ids = students.ToObject<List<string>>();
+                List<students> stus = students.ToObject<List<students>>();
+                ExamInfo info = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.GetString(), new PartitionKey($"Exam-{code}"));
+                string classCode = info.scope.Equals("school") ? info.school : info.creatorId;
+                List<ExamClassResult> examClassResults = new();
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamClassResult>(
+                           queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}'",
+                           requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{classCode}") }))
+                {
+                    examClassResults.Add(item);
+                }
+                int n = 0;
+                foreach (ExamSubject subject in info.subjects)
+                {
+                    if (!subject.id.Equals(subjectId.GetString()))
+                    {
+                        n++;
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                //获取试卷信息
+                PaperSimple standerAnswers = new PaperSimple();
+                List<List<string>> standard = new List<List<string>>();
+                List<double> points = new List<double>();
+                standerAnswers = info.papers[n];
+                standard = standerAnswers.answers;
+                points = standerAnswers.point;
+                int rule = standerAnswers.multipleRule;
+                List<string> value = new List<string>();
+                await foreach (var s in stuTask(stus, examClassResults, standard, points, rule, info, subjectId.GetString(), client))
+                {
+                    if (s.code == 1)
+                    {
+                        value.Add(s.value);
+                    }
+                }
+                if (value.Count > 0)
+                {
+                    return Ok(new { code = 1, msg = "学生ID异常", value = value });
+                }
+                else
+                {
+                    return Ok(new { code = 0 });
+                }
+
+            }
+            catch (Exception e)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},activity/upsert-record()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
+            }
+
+        }
+        private async IAsyncEnumerable<(int code, string value)> stuTask(List<students> stus, List<ExamClassResult> examClassResults, List<List<string>> standard,
+            List<double> points, int rule, ExamInfo info, string subjectId, CosmosClient client)
+        {
+            foreach (var s in stus)
+            {
+                string value = "";
+                int code = 0;
+                List<List<string>> ans = s.answer;
+                bool isExist = examClassResults.Exists(e => e.studentIds.Contains(s.id));
+                if (!isExist)
+                {
+                    value = s.id;
+                    code = 1;
+                }
+                else
+                {
+                    foreach (ExamClassResult result in examClassResults)
+                    {
+                        if (!result.studentIds.Contains(s.id))
+                        {
+                            continue;
+                        }
+                        else
+                        {
+                            int newIndex = result.studentIds.IndexOf(s.id);
+                            StringBuilder builder = new StringBuilder();
+                            builder.Append(result.examId).Append('/');
+                            builder.Append(result.subjectId).Append('/');
+                            builder.Append(s.id).Append('/');
+                            builder.Append("ans.json");
+                            result.studentAnswers[newIndex].Clear();
+                            result.studentAnswers[newIndex].Add(builder.ToString());
+                            for (int i = 0; i < ans.Count; i++)
+                            {
+                                if (ans[i] == null)
+                                {
+                                    continue;
+                                    //ans[i] = new List<string>();
+                                }
+                                var ac = ans[i].Count;
+                                var sc = standard[i].Count;
+                                //记录次数
+                                int n = 0;
+                                //算分处理
+                                if (sc > 0)
+                                {
+                                    result.ans[newIndex][i] = ans[i];
+                                    if (ac == sc && sc == 1)
+                                    {
+                                        foreach (string right in ans[i])
+                                        {
+                                            if (standard[i].Contains(right))
+                                            {
+                                                result.studentScores[newIndex][i] = points[i];
+                                            }
+                                            else
+                                            {
+                                                result.studentScores[newIndex][i] = 0;
+                                            }
+                                        }
+
+                                    }
+                                    else
+                                    {
+                                        if (rule > 0)
+                                        {
+                                            int falseCount = 0;
+                                            if (ac > 0)
+                                            {
+                                                foreach (string obj in ans[i])
+                                                {
+                                                    if (!standard[i].Contains(obj))
+                                                    {
+                                                        falseCount++;
+                                                    }
+                                                }
+                                                switch (rule)
+                                                {
+                                                    case 1:
+                                                        if (ac == sc)
+                                                        {
+                                                            if (falseCount == 0)
+                                                            {
+                                                                result.studentScores[newIndex][i] = points[i];
+                                                            }
+                                                            else
+                                                            {
+                                                                result.studentScores[newIndex][i] = 0;
+                                                            }
+                                                        }
+                                                        else
+                                                        {
+                                                            result.studentScores[newIndex][i] = 0;
+                                                        }
+                                                        break;
+                                                    case 2:
+                                                        if (falseCount > 0)
+                                                        {
+                                                            result.studentScores[newIndex][i] = 0;
+                                                        }
+                                                        else
+                                                        {
+                                                            if (ac == sc)
+                                                            {
+                                                                result.studentScores[newIndex][i] = points[i];
+                                                            }
+                                                            else
+                                                            {
+                                                                result.studentScores[newIndex][i] = points[i] / 2;
+                                                            }
+
+                                                        }
+                                                        break;
+                                                    case 3:
+                                                        if (falseCount > 0)
+                                                        {
+                                                            result.studentScores[newIndex][i] = 0;
+                                                        }
+                                                        else
+                                                        {
+                                                            if (ac == sc)
+                                                            {
+                                                                result.studentScores[newIndex][i] = points[i];
+                                                            }
+                                                            else
+                                                            {
+                                                                result.studentScores[newIndex][i] = System.Math.Round((double)ac / sc * points[i], 1);
+                                                            }
+
+                                                        }
+                                                        break;
+                                                    case 4:
+                                                        if (ac == sc)
+                                                        {
+                                                            result.studentScores[newIndex][i] = points[i];
+                                                        }
+                                                        else
+                                                        {
+                                                            double persent = (double)(sc - 2 * falseCount) / sc;
+                                                            if (persent <= 0)
+                                                            {
+                                                                result.studentScores[newIndex][i] = 0;
+                                                            }
+                                                            else
+                                                            {
+                                                                result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
+                                                            }
+                                                        }
+                                                        break;
+                                                }
+                                            }
+                                            else
+                                            {
+                                                result.studentScores[newIndex][i] = 0;
+                                            }
+
+                                        }
+                                    }
+                                }
+                            }
+                            bool flag = true;
+                            foreach (List<double> scores in result.studentScores)
+                            {
+                                foreach (double score in scores)
+                                {
+                                    if (score == -1)
+                                    {
+                                        flag = false;
+                                        break;
+                                    }
+                                }
+                            }
+                            if (flag)
+                            {
+                                result.progress = true;
+                                info.subjects.ForEach(s =>
+                                {
+                                    if (s.id.Equals(subjectId.ToString()))
+                                    {
+                                        s.classCount += 1;
+                                    }
+                                });
+                                await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(info, info.id.ToString(), new PartitionKey($"{info.code}"));
+                            }
+                            result.sum[newIndex] = result.studentScores[newIndex].Sum();
+                            await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
+                            break;
+                        }
+                    }
+                }
+                yield return (code, value);
+            }
+        }
+        [ProducesDefaultResponseType]
+        [HttpGet("parse-word")]
+        [ApiToken(Auth = "203", Name = "录入试卷数据", Limit = false)]
+        public async Task<IActionResult> ParseWord([FromForm] FileDto fileDto)
         {
-            json.TryGetProperty("periodId", out JsonElement _periodId);
-            var (id, school) = HttpContext.GetApiTokenInfo();
-            School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
-            var exmaType = new { type = new List<string> { "regular", "simulation", "normal" } };//regula ,正规考,  simulation 模拟靠考,normal 普通考
-            var exmaMode = new { type = new List<string> { "0", "1", "2" } };//0 线上评测,  1 课中评测 ,2 阅卷评测
-            var period= data.period.Find(x => x.id.Equals($"{_periodId}"));
-            if (period != null)
+            if (!FileType.GetExtention(fileDto.file.FileName).ToLower().Equals("docx"))
             {
-                return Ok(new { period.subjects, period.analysis, period.grades , exmaType, exmaMode });
+                return BadRequest(new Dictionary<string, object> { { "msg", "type is not docx!" }, { "code", 404 } });
+            }
+
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(fileDto.examId, new PartitionKey($"Exam-{fileDto.code}"));
+                ExamInfo examInfo;
+                if (response.Status == 200)
+                {
+                    using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                    examInfo = json.ToObject<ExamInfo>();
+
+                }
+                else
+                {
+                    return Ok(new { error = 404, msg = "请先导入评测信息" });
+                }
+                foreach (PaperSimple paper in examInfo.papers)
+                {
+                    if (paper.id.Contains(fileDto.subjectId))
+                    {
+                        return Ok(new { error = 500, msg = "该试卷信息已存在" });
+                    }
+                }
+                PaperSimple simple = new();
+                var doc = _DOXC2HTMLTranslator.Translate(fileDto.file.OpenReadStream());
+                (List<HTEXLib.DOCX.Models.ItemInfo> tests, List<string> error) = _HTML2ITEMV3Translator.Translate(doc);
+                List<Task<string>> tasks = new List<Task<string>>();
+                PaperDto paperDto = new()
+                {
+                    id = Guid.NewGuid().ToString(),
+                    name = fileDto.name,
+                    code = fileDto.code,
+                    scope = "school",
+                    multipleRule = fileDto.multipleRule,
+                    gradeIds = fileDto.gradeIds,
+                    subjectId = fileDto.subjectId,
+                    periodId = fileDto.periodId
+                };
+                foreach (HTEXLib.DOCX.Models.ItemInfo item in tests)
+                {
+                    Slides slides = new();
+                    ItemDto dto = new();
+                    Scoring scoring = new();
+                    dto.id = Guid.NewGuid().ToString();
+                    dto.exercise.answer = item.answer;
+                    dto.exercise.explain = item.explain;
+                    dto.exercise.type = item.type;
+                    dto.exercise.opts = item.option.Count;
+                    dto.exercise.knowledge = item.knowledge;
+                    dto.exercise.field = item.field;
+                    dto.exercise.level = item.level;
+                    dto.exercise.subjectId = fileDto.subjectId;
+                    dto.exercise.periodId = fileDto.periodId;
+                    dto.exercise.gradeIds = fileDto.gradeIds;
+                    slides.url = dto.id + ".json";
+                    slides.type = dto.exercise.type;
+                    scoring.ans = dto.exercise.answer;
+                    scoring.score = dto.exercise.score;
+                    scoring.knowledge = dto.exercise.knowledge;
+                    scoring.field = dto.exercise.field;
+                    slides.scoring = scoring;
+                    //添加试卷信息
+                    paperDto.slides.Add(slides);
+                    if (!slides.type.Equals("compose"))
+                    {
+                        simple.point.Add(dto.exercise.score);
+                        simple.answers.Add(dto.exercise.answer);
+                        simple.knowledge.Add(dto.exercise.knowledge);
+                        simple.type.Add(dto.exercise.type);
+                        simple.field.Add((int)dto.exercise.field);
+                    }
+                    if (item.children.Count > 0)
+                    {
+                        foreach (HTEXLib.DOCX.Models.ItemInfo its in item.children)
+                        {
+                            Slides cslides = new();
+                            Scoring cscoring = new();
+                            ItemDto dtoChildren = new ItemDto();
+                            dtoChildren.id = Guid.NewGuid().ToString();
+                            dtoChildren.pid = dto.id;
+                            dtoChildren.exercise.answer = its.answer;
+                            dtoChildren.exercise.explain = its.explain;
+                            dtoChildren.exercise.type = its.type;
+                            dtoChildren.exercise.opts = its.option.Count;
+                            dtoChildren.exercise.knowledge = its.knowledge;
+                            dtoChildren.exercise.field = its.field;
+                            dtoChildren.exercise.level = its.level;
+                            dtoChildren.exercise.scope = "school";
+                            dtoChildren.exercise.score = its.score;
+                            dtoChildren.exercise.subjectId = fileDto.subjectId;
+                            dtoChildren.exercise.periodId = fileDto.periodId;
+                            dtoChildren.exercise.gradeIds = fileDto.gradeIds;
+                            dtoChildren.exercise.children.Add(dtoChildren.id);
+                            info info1 = new();
+                            info1.uid = dtoChildren.id;
+                            info1.question = its.question;
+                            info1.option = its.option;
+                            dtoChildren.item.Add(info1);
+                            dto.exercise.children.Add(dtoChildren.id);
+                            //处理子题的slides
+                            cslides.url = dtoChildren.id + ".json";
+                            cslides.type = dtoChildren.exercise.type;
+                            cscoring.ans = dtoChildren.exercise.answer;
+                            cscoring.score = dtoChildren.exercise.score;
+                            cscoring.knowledge = dtoChildren.exercise.knowledge;
+                            cscoring.field = dtoChildren.exercise.field;
+                            cslides.scoring = scoring;
+                            paperDto.slides.Add(cslides);
+                            //添加试卷信息
+                            simple.point.Add(dtoChildren.exercise.score);
+                            simple.answers.Add(dto.exercise.answer);
+                            simple.knowledge.Add(dto.exercise.knowledge);
+                            simple.type.Add(dto.exercise.type);
+                            simple.field.Add((int)dto.exercise.field);
+
+                            StringBuilder stringBuilder = new StringBuilder();
+                            stringBuilder.Append(fileDto.examId).Append("/");
+                            stringBuilder.Append("paper").Append("/");
+                            stringBuilder.Append(fileDto.subjectId).Append("/");
+                            stringBuilder.Append(dtoChildren.id + ".json");
+                            tasks.Add(_azureStorage.UploadFileByContainer(fileDto.code, dtoChildren.ToJsonString(), "exam", stringBuilder.ToString(), false));
+                        }
+                    }
+                    info @info = new();
+                    @info.uid = dto.id;
+                    @info.question = item.question;
+                    @info.option = item.option;
+                    dto.item.Add(@info);
+                    dto.exercise.scope = "school";
+                    dto.exercise.score = item.score;
+                    StringBuilder builder = new StringBuilder();
+                    builder.Append(fileDto.examId).Append('/');
+                    builder.Append("paper").Append('/');
+                    builder.Append(fileDto.subjectId).Append('/');
+                    builder.Append(dto.id + ".json");
+                    tasks.Add(_azureStorage.UploadFileByContainer(fileDto.code, dto.ToJsonString(), "exam", builder.ToString(), false));
+
+
+                }
+                StringBuilder paperBuilder = new StringBuilder();
+                paperBuilder.Append(fileDto.examId).Append('/');
+                paperBuilder.Append("paper").Append('/');
+                paperBuilder.Append(fileDto.subjectId).Append('/');
+                paperBuilder.Append("index.json");
+                tasks.Add(_azureStorage.UploadFileByContainer(fileDto.code, paperDto.ToJsonString(), "exam", paperBuilder.ToString(), false));
+
+                //开始给ExamInfo paper赋值
+                simple.id = fileDto.subjectId;
+                simple.code = "Paper-" + fileDto.code;
+                simple.name = fileDto.name;
+                simple.blob = paperBuilder.ToString().Replace("index.json", "");
+                simple.scope = "school";
+                simple.multipleRule = fileDto.multipleRule;
+
+                examInfo.papers.Add(simple);
+                await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(examInfo, examInfo.id, new PartitionKey($"{examInfo.code}"));
+                await Task.WhenAll(tasks);
+
+                return Ok(new { code = 200 });
             }
-            else {
-                return Ok(new { error = 1, msg = "学段不存在!" });
+            catch (Exception e)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},analysis/word()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
             }
 
         }
+
+        private class students
+        {
+            public string id { get; set; }
+            public List<List<string>> answer { get; set; }
+        }
+        public class FileDto
+        {
+            public string periodId { get; set; }
+            public string code { get; set; }
+            public string name { get; set; }
+            public int multipleRule { get; set; }
+            public string examId { get; set; }
+            public string subjectId { get; set; }
+            public List<string> gradeIds { get; set; }
+            public IFormFile file { get; set; }
+        }
+
+
     }
 }

+ 36 - 9
TEAMModelAPI/Controllers/School/SchoolController.cs

@@ -59,7 +59,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpGet("get-school-info")]
-        [ApiToken(Auth = "2",Name = "学校基础信息", RW = "R", Limit =false)]
+        [ApiToken(Auth = "101",Name = "学校基础信息", RW = "R", Limit =false)]
         public async Task<IActionResult> GetSchoolInfo()
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -81,7 +81,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpGet("get-teacher-list")]
-        [ApiToken(Auth = "3", Name = "学校教师列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "102", Name = "学校教师列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetTeacherList()
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -102,7 +102,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-teacher-info")]
-        [ApiToken(Auth = "4", Name = "学校教师信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "103", Name = "学校教师信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetTeacherInfo(JsonElement json )
         {
             json.TryGetProperty("tmdid", out JsonElement _tmdid);
@@ -148,7 +148,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-group-list")]
-        [ApiToken(Auth = "5", Name = "学校教师列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "104", Name = "学校教师列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetGroupList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -245,7 +245,7 @@ namespace TEAMModelAPI.Controllers
 
         [ProducesDefaultResponseType]
         [HttpPost("get-group-members")]
-        [ApiToken(Auth = "6", Name = "获取名单详细信息和成员信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "105", Name = "获取名单详细信息和成员信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetGroupMembers(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -258,7 +258,7 @@ namespace TEAMModelAPI.Controllers
        
         [ProducesDefaultResponseType]
         [HttpPost("get-course-list")]
-        [ApiToken(Auth = "7", Name = "获取课程列表信息",RW ="R", Limit = false)]
+        [ApiToken(Auth = "106", Name = "获取课程列表信息",RW ="R", Limit = false)]
         public async Task<IActionResult> GetCourseList(JsonElement json) {
             var client = _azureCosmos.GetCosmosClient();
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -283,7 +283,7 @@ namespace TEAMModelAPI.Controllers
        
         [ProducesDefaultResponseType]
         [HttpPost("get-course-info")]
-        [ApiToken(Auth = "8", Name = "课程详细信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "107", Name = "课程详细信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetCourseInfo(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -307,7 +307,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-room-list")]
-        [ApiToken(Auth = "9", Name = "获取物理教室列表", RW = "R", Limit = false)]
+        [ApiToken(Auth = "108", Name = "获取物理教室列表", RW = "R", Limit = false)]
         public async Task<IActionResult> GetRoomList(JsonElement json)
         {
             var client = _azureCosmos.GetCosmosClient();
@@ -334,7 +334,7 @@ namespace TEAMModelAPI.Controllers
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("get-room-info")]
-        [ApiToken(Auth = "10", Name = "获取物理教室详细信息", RW = "R", Limit = false)]
+        [ApiToken(Auth = "109", Name = "获取物理教室详细信息", RW = "R", Limit = false)]
         public async Task<IActionResult> GetRoomInfo(JsonElement json)
         {
             var (id, school) = HttpContext.GetApiTokenInfo();
@@ -352,5 +352,32 @@ namespace TEAMModelAPI.Controllers
                 return Ok(new { error = 1, msg = "教室不存在!" });
             }
         }
+
+        /// <summary>
+        ///  获取试卷和评测的条件信息
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-paper-exam-condition")]
+        [ApiToken(Auth = "110", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
+        public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
+        {
+            json.TryGetProperty("periodId", out JsonElement _periodId);
+            var (id, school) = HttpContext.GetApiTokenInfo();
+            School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
+            var exmaType = new { type = new List<string> { "regular", "simulation", "normal" } };//regula ,正规考,  simulation 模拟靠考,normal 普通考
+            var exmaMode = new { type = new List<string> { "0", "1", "2" } };//0 线上评测,  1 课中评测 ,2 阅卷评测
+            var period = data.period.Find(x => x.id.Equals($"{_periodId}"));
+            if (period != null)
+            {
+                return Ok(new { period.subjects, period.analysis, period.grades, exmaType, exmaMode });
+            }
+            else
+            {
+                return Ok(new { error = 1, msg = "学段不存在!" });
+            }
+
+        }
     }
 }