using AutoMapper; using AutoMapper.Internal.Mappers; using Entities.Contracts; using Entities.DTO; using Microsoft.EntityFrameworkCore; using SharedDATA.Api; using TechHelper.Context; using TechHelper.Repository; using TechHelper.Services; namespace TechHelper.Server.Services { public class StudentSubmissionDetailService : IStudentSubmissionDetailService { private readonly IUnitOfWork _unitOfWork; private readonly IExamService examService; private readonly IMapper _mapper; public StudentSubmissionDetailService( IUnitOfWork unitOfWork, IExamService examService, IMapper mapper) { _unitOfWork = unitOfWork; this.examService = examService; _mapper = mapper; } public async Task GetSubmissionDetailAsync(Guid submissionId) { try { // 获取submission基本信息 var submission = await _unitOfWork.GetRepository() .GetAll(s => s.Id == submissionId) .Include(s => s.Assignment) .ThenInclude(a => a.Creator) .FirstOrDefaultAsync(); if (submission == null) { return ApiResponse.Error("未找到指定的提交记录"); } var assignment = await examService.GetAsync(submission.AssignmentId); if (assignment == null) { return ApiResponse.Error("未找到指定的作业"); } // 获取所有提交详情 var submissionDetails = await _unitOfWork.GetRepository() .GetAll(sd => sd.SubmissionId == submissionId) .Include(sd => sd.AssignmentQuestion) .ThenInclude(aq => aq.Question) .ThenInclude(q => q.Lesson) .ThenInclude(q => q.KeyPoints) .ToListAsync(); // 获取同作业的所有提交用于排名和成绩分布 var allSubmissions = await _unitOfWork.GetRepository() .GetAll(s => s.AssignmentId == submission.AssignmentId) .ToListAsync(); // 映射基本信息 var result = _mapper.Map(submission); result.Assignment = assignment.Result as AssignmentDto ?? new AssignmentDto(); var errorQuestion = submissionDetails .Where(sd => sd.IsCorrect == false && sd.AssignmentQuestion?.StructType == AssignmentStructType.Question && sd.AssignmentQuestion?.Question != null) .ToList(); // 计算基础统计 result.TotalQuestions = submissionDetails.Select(x => x.AssignmentQuestion.StructType == AssignmentStructType.Question && x.AssignmentQuestion?.Question != null).Count(); result.ErrorCount = errorQuestion.Count; result.CorrectCount = result.TotalQuestions - result.ErrorCount; result.AccuracyRate = result.TotalQuestions > 0 ? (float)result.CorrectCount / result.TotalQuestions : 0; // 计算错误类型分布 - 只获取题目类型的错误 result.ErrorTypeDistribution = errorQuestion .GroupBy(sd => sd.AssignmentQuestion.Question.Type.ToString()) .ToDictionary(g => g.Key, g => g.Count()); ; // 计算错误类型成绩分布 - 只获取题目类型的错误 result.ErrorTypeScoreDistribution = errorQuestion .GroupBy(sd => sd.AssignmentQuestion.Question.Type.ToString()) .ToDictionary(g => g.Key, g => g.Sum(sd => sd.PointsAwarded ?? 0)); // 计算成绩排名 var orderedSubmissions = allSubmissions .OrderByDescending(s => s.OverallGrade) .ToList(); result.TotalRank = orderedSubmissions.FindIndex(s => s.Id == submissionId) + 1; SetBCorrect(result.Assignment, errorQuestion); // 计算成绩分布 result.AllScores = allSubmissions.Select(s => s.OverallGrade).ToList(); result.AverageScore = submission.OverallGrade; result.ClassAverageScore = allSubmissions.Average(s => s.OverallGrade); // 计算课文错误分布 result.LessonErrorDistribution = errorQuestion .Where(eq => eq.AssignmentQuestion.Question.Lesson != null) .GroupBy(sd => sd.AssignmentQuestion.Question.Lesson.Title) .ToDictionary(g => g.Key, g => g.Count()); // 计算关键点错误分布 result.KeyPointErrorDistribution = errorQuestion .Where(eq => eq.AssignmentQuestion.Question.Lesson != null) .GroupBy(sd => sd.AssignmentQuestion.Question.KeyPoint.Key) .ToDictionary(g => g.Key, g => g.Count()); return ApiResponse.Success(result: result); } catch (Exception ex) { return ApiResponse.Error($"获取学生提交详细信息失败: {ex.Message}"); } } public void SetBCorrect(AssignmentDto assignment, List submissionDetails) { SetBCorrect(assignment.ExamStruct, submissionDetails); } public void SetBCorrect(AssignmentQuestionDto assignmentQuestion, List submissionDetails) { var sd = submissionDetails.FirstOrDefault(x => x.AssignmentQuestionId == assignmentQuestion.Id); if (sd != null) assignmentQuestion.BCorrect = sd.AssignmentQuestion.BCorrect; else assignmentQuestion.BCorrect = false; assignmentQuestion.ChildrenAssignmentQuestion?.ForEach( cq => SetBCorrect(cq, submissionDetails)); } //Task IStudentSubmissionDetailService.GetSubmissionDetailAsync(Guid submissionId) //{ // throw new NotImplementedException(); //} } }