using Exam.Application.Interface.Exam; using Exam.Infrastructure.Data.Entity; using Exam.Infrastructure.Enums; using Exam.Infrastructure.Extensions; using Exam.Share; using Exam.Share.Dtos.ExamManage; using Exam.Share.ViewResponses.Exam; using Hotline.Application.Exam.Core.Extensions; using Hotline.Application.Exam.Extensions; using Hotline.Application.Exam.Interface.Strategy; using Hotline.Application.Exam.QueryExtensions.ExamManages; using Hotline.Application.Exam.Strategy; using Hotline.Exams.ExamManages; using Hotline.Repository.SqlSugar; using Hotline.Repository.SqlSugar.DataPermissions; using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages; using Hotline.Share.Dtos.ExamManages; using Hotline.Share.Exams.Extensions; using Hotline.Share.Requests.Exam; using Hotline.Share.ViewResponses; using Hotline.Share.ViewResponses.Exam; using Hotline.Users; using JiebaNet.Segmenter.Common; using MapsterMapper; using Hotline.Application.Exam.Core.Utilities; using Hotline.Application.Exam.Interface.ExamManages; using Hotline.Exams.Validate; using Hotline.Repository.SqlSugar.Exam.Repositories; using XF.Domain.Authentications; using XF.Domain.Dependency; using XF.Domain.Exceptions; using XF.Domain.Repository; using ExamQuestion = Hotline.Exams.Questions.ExamQuestion; using Hotline.Repository.SqlSugar.Exam.Service; using Hotline.Repository.SqlSugar.Exam.Extensions; using Exam.Infrastructure.Data.Interface; using Hotline.Repository.SqlSugar.Exam.Interface; using DocumentFormat.OpenXml.Drawing.Charts; using SqlSugar; using System.Threading; using DocumentFormat.OpenXml.Office2013.Excel; using Hotline.Share.Enums.Exams; using DocumentFormat.OpenXml.Wordprocessing; using Hotline.Repository.SqlSugar.Exam.Repositories.ExamManages; using Hotline.Exams.Questions; using Hotline.Exams.Sourcewares; using Hotline.Share.Dtos.Questions; using DocumentFormat.OpenXml.Office2010.Excel; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; namespace Hotline.Application.Exam.Service.ExamManages { public class UserExamService : ApiService, IUserExamService, IScopeDependency { private readonly IUserExamRepository _repository; private readonly IUserExamItemRepository _userExamItemRepository; private readonly IUserExamItemOptionRepository _userExamItemOptionRepository; private readonly IExamAnswerRepository _examAnswerRepository; private readonly IExamManageRepository _examManageRepository; private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder; private readonly IServiceProvider _serviceProvider; private readonly IMapper _mapper; private readonly ISessionContext _sessionContext ; public UserExamService(IUserExamRepository repository, IUserExamItemRepository userExamItemRepository, IUserExamItemOptionRepository userExamItemOptionRepository, IExamAnswerRepository examAnswerRepository, IExamManageRepository examManageRepository, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider, IMapper mapper, ISessionContext sessionContext) : base(repository, mapper, sessionContext) { this._repository = repository; this._userExamItemRepository = userExamItemRepository; this._userExamItemOptionRepository = userExamItemOptionRepository; this._examAnswerRepository = examAnswerRepository; this._examManageRepository = examManageRepository; this._dataPermissionFilterBuilder = dataPermissionFilterBuilder; this._serviceProvider = serviceProvider; this._mapper = mapper; this._sessionContext = sessionContext; } #region public method public Task GetAsync(EntityQueryRequest entityQueryRequest) { throw new NotImplementedException(); } public Task<(int, List)> GetListAsync(UserExamPagedRequest queryRequest) { throw new NotImplementedException(); } public async Task GetExamQuestionDto(ExamQuestionRequest examQuestionRequest) { var expression = examQuestionRequest.GetExpression(); var userUserExpression = examQuestionRequest.GetUserExamExpression(); //var question = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(expression).FirstAsync(); var querable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(expression); var userExamTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(userUserExpression); querable = querable.InnerJoin(userExamTable, (q, u) => q.ExamId == u.ExamId).Select((q, u) => q); var question = await querable.FirstAsync(); if (question != null) { var examQuestionDto = _mapper.Map(question); var questionScore = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).GetAsync(x => x.QuestionType == question.QuestionType && x.ExamManageId == question.ExamId); if (questionScore != null) { examQuestionDto.Score = questionScore.Score; } if (examQuestionDto.QuestionType.CheckSelectType()) { var questionOptions = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.ExamQuestionId == question.Id).ToListAsync(); List userItemItemOptions = await GetUserExteamItemOptios(question); if (questionOptions != null) { examQuestionDto.QuestionOptions = new List(); questionOptions.ForEach(item => { var examQuestionOptionsDto = _mapper.Map(item); if (userItemItemOptions != null) { examQuestionOptionsDto.IsSelected = userItemItemOptions.Any(m => m.QuestionOptionId == item.Id); } examQuestionDto.QuestionOptions.Add(examQuestionOptionsDto); }); } } else { List examAnswers = await GetExamAnswers(examQuestionRequest); examQuestionDto.Answer = examAnswers != null ? examAnswers.FirstOrDefault()?.Answer : null; } return examQuestionDto; } else { throw new UserFriendlyException(ExamErrorMessage.ServiceError, string.Format(ExamErrorMessage.IsNotExists, string.Concat(typeof(ExamQuestion).GetDescription(), ":", examQuestionRequest.QuestionId))); } } private async Task> GetExamAnswers(ExamQuestionRequest examQuestionRequest) { var examAnswerRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userExamItemRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userExamItemTable = userExamItemRepository.Queryable().Where(i => i.QuestionId == examQuestionRequest.QuestionId); var userExamTable = _repository.Queryable().Where(u => u.UserId == _sessionContext.UserId && u.Id == examQuestionRequest.UserExamId); var examAnswerTable = examAnswerRepository.Queryable(); var examAnswers = await examAnswerTable.InnerJoin(userExamItemTable, (e, i) => e.UserExamItemId == i.Id) .InnerJoin(userExamTable, (e, i, u) => i.UserExamId == u.Id) .Select((e, i, u) => e).ToListAsync(); return examAnswers; } private async Task> GetUserExteamItemOptios(Exams.ExamManages.ExamQuestionBak quesetion) { var userExamItemOptionsRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userExamItemOptionsTable = userExamItemOptionsRepository.Queryable(); var userExamItemTable = _userExamItemRepository.Queryable(); var userExamTable = _repository.Queryable(); var userItemItemOptions = await userExamItemOptionsTable .InnerJoin(userExamItemTable, (o, u) => o.UserExamItemId == u.Id) .InnerJoin(userExamTable, (o, u, e) => u.UserExamId == e.Id) .Where((o, u, e) => u.QuestionId == quesetion.QuestionId && e.UserId == _sessionContext.UserId && e.ExamStatus == EExamStatus.Executing). Select((o, u, e) => o).ToListAsync(); return userItemItemOptions; } public async Task> GetExamQuestionViewResponses(ExamQuestionGroupRequest examQuestionGroupRequest) { if (examQuestionGroupRequest.ExamId.IsNull() && examQuestionGroupRequest.UserId.IsNull()) throw UserFriendlyException.SameMessage("查询参数不能为空"); var expression = examQuestionGroupRequest.GetExpression(); var examManageTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(expression); var testPaperItemTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var queryable = await examManageTable.InnerJoin(testPaperItemTable, (e, i) => e.Id == i.ExamId) .Select((e, i) => i).ToListAsync(); var result = queryable.GroupBy(x => x.QuestionType).Select(m => new ExamQuestionViewResponse { QuestionType = m.Key, Questions = m.GroupBy(g => g.QuestionId).Select(n => new SimpleViewResponse { Id = n.Key }).ToList() }).ToList(); return result; } public async Task> GetGradingQuestionViewResponces(ExamQuestionGroupRequest examQuestionGroupRequest) { var expression = examQuestionGroupRequest.GetExpression(); var examManageTable = _examManageRepository.Queryable().Where(expression); var testPaperItemTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var queryable = await examManageTable.InnerJoin(testPaperItemTable, (e, i) => e.Id == i.ExamId) .Select((e, i) => i).ToListAsync(); var examQuestionScores = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.ExamManageId == examQuestionGroupRequest.ExamId).ToListAsync(); var userExamItemTable = _userExamItemRepository.Queryable(); var userExamTable = _repository.Queryable().Where(x => x.ExamId == examQuestionGroupRequest.ExamId && x.UserId == examQuestionGroupRequest.UserId); var userExamItems = await userExamItemTable.InnerJoin(userExamTable, (i, u) => i.UserExamId == u.Id) .Select((i, u) => i).ToListAsync(); var result = queryable.GroupBy(x => x.QuestionType).Select(m => new GradingQuestionViewResponce { QuestionType = m.Key, Questions = m.Select(n => new GradingExamViewResponse { IsCorrect = CheckCorrect(n, examQuestionScores, userExamItems), Id = userExamItems.FirstOrDefault(x => x.QuestionId == n.QuestionId)?.Id ?? n.Id }).ToList() }).ToList(); return result; } private bool CheckCorrect(Exams.ExamManages.ExamQuestionBak n, List examQuestionScores, List userExamItems) { var examQuestionScore = examQuestionScores.FirstOrDefault(x => x.QuestionType == n.QuestionType); var userItem = userExamItems.FirstOrDefault(x => x.QuestionId == n.QuestionId); if (userItem != null && examQuestionScore != null) { return userItem.Score == examQuestionScore.Score; } return false; } public async Task> GetPagedListAsync(UserExamPagedRequest queryRequest) { SqlSugar.ISugarQueryable queryable = GetQueryable(queryRequest); var list = await queryable.ToPageListAsync(queryRequest.PageIndex, queryRequest.PageSize); var total = await queryable.CountAsync(); var result = new UserExamResultPageViewResponse { Items = list, Pagination = new Pagination(queryRequest.PageIndex, queryRequest.PageSize, total) }; return result; } public async Task GradingAsync(GradingExamItemDto gradingExtamItemDto, CancellationToken cancellationToken) { var userExamItem = await _userExamItemRepository.GetAsync(m => m.Id == gradingExtamItemDto.UserExamItemId); if (userExamItem != null) { userExamItem = _mapper.Map(gradingExtamItemDto, userExamItem); await _userExamItemRepository.UpdateWithValidateAsync(userExamItem, cancellationToken); } return await GetNextExamQuestion(gradingExtamItemDto); } public async Task SubmitAsync(SubmitExamDto submitExamDto, CancellationToken cancellationToken) { var userExam = await _repository.GetAsync(x => x.Id == submitExamDto.Id); if (userExam != null) { userExam = _mapper.Map(submitExamDto, userExam); userExam.ExamStatus = EExamStatus.Complete; await _repository.UpdateWithValidateAsync(userExam, cancellationToken); await CompleteExamManage(userExam.ExamId, cancellationToken); } } private async Task CompleteExamManage(string examId, CancellationToken cancellationToken) { var userExams = await _repository.Queryable().Where(x => x.ExamId == examId).ToListAsync(); if (userExams.All(x => x.IsSubmit)) { var examManage = await _examManageRepository.GetAsync(x => x.Id == examId); examManage.ExamStatus = EExamStatus.Complete; await _examManageRepository.UpdateWithValidateAsync(examManage, cancellationToken); } } public async Task ExamAsync(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken) { var userExam = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == updateUserExamItemDto.UserExamId).FirstAsync(); var startExamViewResponse = await CheckExamValid(userExam, cancellationToken); if (!startExamViewResponse.CheckValidate()) { await SetExamStatus(userExam, startExamViewResponse, cancellationToken); return startExamViewResponse; } var hasUserExamItem = _userExamItemRepository.Queryable().Where(x => x.UserExamId == updateUserExamItemDto.UserExamId && x.QuestionId == updateUserExamItemDto.QuestionId).Any(); if (!hasUserExamItem) { var addUserExamItemDto = _mapper.Map(updateUserExamItemDto); await AddExamAsync(_userExamItemRepository, addUserExamItemDto, cancellationToken); } else { await UpdateExamAsync(_userExamItemRepository, updateUserExamItemDto, cancellationToken); } await CalcuteExamItemScore(_userExamItemRepository, updateUserExamItemDto, cancellationToken); return startExamViewResponse; } private async Task SetExamStatus(ExamUserExam userExam, StartExamViewResponse startExamViewResponse, CancellationToken cancellationToken) { userExam.ExamStatus = startExamViewResponse.IsCompleted ? EExamStatus.Complete : EExamStatus.NoStart; userExam.ToUpdate(_sessionContext); await _repository.UpdateWithValidateAsync(userExam, cancellationToken); } public async Task StartUserExamAsync(StartUserExamDto startUserExamDto, CancellationToken cancellationToken) { var userExam = await _repository.GetAsync(x => x.Id == startUserExamDto.Id); if (userExam == null) return new StartExamViewResponse { IsJoin = false }; if (userExam.ExamStatus == EExamStatus.NoStart || userExam.ExamStatus == EExamStatus.Complete) userExam.StartTime = DateTime.Now; var startExamViewResponse = await CheckExamValid(userExam, cancellationToken); if (!startExamViewResponse.CheckValidate()) { await SetExamStatus(userExam, startExamViewResponse, cancellationToken); return startExamViewResponse; } if (userExam.ExamStatus == EExamStatus.NoStart) { userExam.ExamStatus = Share.Enums.Exams.EExamStatus.Executing; userExam.ToUpdate(_sessionContext); await _repository.UpdateWithValidateAsync(userExam, cancellationToken); } // TODO: 删除之前选项和答案 else if (userExam.ExamStatus == EExamStatus.Complete) { await ReExam(userExam, cancellationToken); } var examManage = await _examManageRepository.GetAsync(x => x.Id == userExam.ExamId); return new StartExamViewResponse { StartTime = userExam.StartTime, TimeSpan = examManage?.TimeSpan, IsCompleted = false }; } /// /// 重考 /// /// /// /// private async Task ReExam(ExamUserExam userExam, CancellationToken cancellationToken) { //新增重考记录 var reExamUserExam = _mapper.Map(userExam); reExamUserExam.IsCheck = false; reExamUserExam.IsSubmit = false; reExamUserExam.IsSuccess = false; reExamUserExam.IsReExam = true; reExamUserExam.Score = 0; reExamUserExam.ExamStatus = EExamStatus.NoStart; reExamUserExam.ToInsert(_sessionContext); await _repository.AddWithValidateAsync(reExamUserExam, cancellationToken); } private async Task CheckExamValid(ExamUserExam examUserExam, CancellationToken cancellationToken) { var examManage = await _examManageRepository.Queryable().Where(x => x.Id == examUserExam.ExamId).FirstAsync(); var startExamViewResponse = new StartExamViewResponse { IsJoin = true, IsCompleted = false }; if (examManage != null) { var examStrategyProxy = new ExamStrategyProxy(); var examStrategys = new List(); startExamViewResponse = AddCheckStartTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys); startExamViewResponse = AddCheckEndTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys); startExamViewResponse = AddCheckValidateTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys); startExamViewResponse = AddCheckValidateCountStrategy(examUserExam, examManage, startExamViewResponse, examStrategys); examStrategyProxy.Initial(examStrategys); if (!examStrategyProxy.Validate()) { startExamViewResponse = (StartExamViewResponse)examStrategyProxy.GetResult(); return startExamViewResponse; } } startExamViewResponse.IsStart = true; if (examManage.ExamStatus == EExamStatus.NoStart) { await UpdateExamStatus(examManage, cancellationToken); } startExamViewResponse.TimeSpan = examManage?.TimeSpan ?? 0; startExamViewResponse.StartTime = examUserExam?.StartTime; return startExamViewResponse; } private async Task UpdateExamStatus(ExamManage? examManage, CancellationToken cancellationToken) { examManage.ExamStatus = EExamStatus.Executing; examManage.ToUpdate(_sessionContext); await _examManageRepository.UpdateWithValidateAsync(examManage, cancellationToken); } private StartExamViewResponse AddCheckValidateCountStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List examStrategys) { if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) { var checkStartTime = new CheckValidateCountStrategy(1, 1) { CallBack = () => { var response = new StartExamViewResponse { IsJoin = false, IsStart = false, IsCompleted = true, StartTime = examUserExam.StartTime, TimeSpan = examManage.TimeSpan }; return response; } }; examStrategys.Add(checkStartTime); return startExamViewResponse; } else { var count = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).CountAsync(x => x.ExamId == examManage.Id && x.UserId == examUserExam.UserId).Result; var checkStartTime = new CheckValidateCountStrategy(examManage.Count, count) { CallBack = () => { var response = new StartExamViewResponse { IsJoin = false, IsStart = false, IsCompleted = true, StartTime = examUserExam.StartTime, TimeSpan = examManage.TimeSpan }; return response; } }; examStrategys.Add(checkStartTime); return startExamViewResponse; } } private StartExamViewResponse AddCheckValidateTimeStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List examStrategys) { if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) return startExamViewResponse; var checkStartTime = new CheckValidateTimeStrategy(examManage.TimeSpan, examUserExam.StartTime) { CallBack = () => { var response = new StartExamViewResponse { IsJoin = false, IsStart = false, IsCompleted = true, StartTime = examUserExam.StartTime, TimeSpan = examManage.TimeSpan }; return response; } }; examStrategys.Add(checkStartTime); return startExamViewResponse; } private StartExamViewResponse AddCheckEndTimeStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List examStrategys) { if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) return startExamViewResponse; var checkStartTime = new CheckEndTimeStrategy(examManage.EndTime, DateTime.Now) { CallBack = () => { var response = new StartExamViewResponse { IsJoin = false, IsStart = false, IsCompleted = true, StartTime = examUserExam.StartTime, TimeSpan = examManage.TimeSpan }; return response; } }; examStrategys.Add(checkStartTime); return startExamViewResponse; } private static StartExamViewResponse AddCheckStartTimeStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List examStrategys) { if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) return startExamViewResponse; var checkStartTime = new CheckStartTimeStrategy(examManage.StartTime, examUserExam.StartTime) { CallBack = () => { var response = new StartExamViewResponse { IsJoin = false, IsStart = false, IsCompleted = false, StartTime = examUserExam.StartTime, TimeSpan = examManage.TimeSpan }; return response; } }; examStrategys.Add(checkStartTime); return startExamViewResponse; } public async Task CompleteGradingAsync(GradingExamDto gradingExtamDto, CancellationToken cancellationToken) { var userExam = await _repository.GetAsync(x => x.Id == gradingExtamDto.Id); if (userExam == null) return; var userExamItems = await _userExamItemRepository.Queryable().Where(x => x.UserExamId == gradingExtamDto.Id).ToListAsync(); if (userExamItems != null) { var totalScore = userExamItems.Sum(x => x.Score); userExam.Score = totalScore; var examManage = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).GetAsync(x => x.Id == userExam.ExamId); userExam.IsSuccess = totalScore >= examManage.CutoffScore; userExam.ExamStatus = Share.Enums.Exams.EExamStatus.Complete; userExam.ToUpdate(_sessionContext); await _repository.UpdateWithValidateAsync(userExam, cancellationToken); } } public async Task> GetGradingExamQuestion(GradingExamRequest gradingExamRequest) { var expression = gradingExamRequest.GetExpression(); ISugarQueryable queryable = GetViewExamQuestionTempDtos(expression); queryable = queryable.MergeTable().Where((q) => !(q.QuestionType == EQuestionType.Single || q.QuestionType == EQuestionType.Multi || q.QuestionType == EQuestionType.Judge)); var queryResult = await queryable.ToListAsync(); var gradingExamQuestionDtos = queryResult.GroupBy(x => new { Id = x.Id, QuestionType = x.QuestionType }).Select(g => new GradingExamQuestionDto { Answer = g.FirstOrDefault().Answer, QuestionType = g.Key.QuestionType, Id = g.Key.Id, QuestionScore = g.FirstOrDefault().QuestionScore, Score = g.FirstOrDefault().Score, Title = g.FirstOrDefault().Title, CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Join(",", g.Where(i => i.IsAnswer).Select(n => n.Label).Distinct()) : g.FirstOrDefault()?.CorrectAnswer }).ToList(); return gradingExamQuestionDtos; } private ISugarQueryable GetViewExamQuestionTempDtos(Expression> expression) { var userExamTable = _repository.Queryable().Where(expression); var questionScoreRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userExamItemTable = _userExamItemRepository.Queryable(); var userExamItemOptionTable = _userExamItemOptionRepository.Queryable(); var examAnswerTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var questionTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var quesitonOptionTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var testPaperItemAnswerTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var questionScoreTable = questionScoreRepository.Queryable(); return userExamTable.InnerJoin(userExamItemTable, (e, i) => e.Id == i.UserExamId) .InnerJoin(questionTable, (e, i, q) => i.QuestionId == q.QuestionId && q.ExamId == e.ExamId) .LeftJoin(userExamItemOptionTable, (e, i, q, o) => i.Id == o.UserExamItemId) .LeftJoin(quesitonOptionTable, (e, i, q, o, qo) => o.QuestionOptionId == qo.Id) .LeftJoin(examAnswerTable, (e, i, q, o, qo, a) => i.Id == a.UserExamItemId) .LeftJoin(testPaperItemAnswerTable, (e, i, q, o, qo, a, ta) => ta.QuestionId == q.QuestionId) .InnerJoin(questionScoreTable, (e, i, q, o, qo, a, ta, s) => q.QuestionType == s.QuestionType && e.ExamId == s.ExamManageId) .Select( (e, i, q, o, qo, a, ta, s) => new GradingExamQuestionTempDto { Id = i.Id, QuestionType = q.QuestionType, CorrectAnswer = ta.Id != null ? ta.Answer : string.Empty, Answer = a.Id != null ? a.Answer : string.Empty, Title = q.Title, QuestionOptionId = o.Id, QuestionId = q.QuestionId, ExamQuestionId = q.Id, UserExamItemId = i.Id, Content = qo.Content, Label = qo.Label, IsAnswer = qo.IsAnswer, IsSelected = o.Id != null, QuestionScore = s.Score, Score = i.Score } ); } public async Task ViewGradingExamQuestion(ViewGradingExamRequest viewGradingExamRequest) { var gradingExtamItemDto = _mapper.Map(viewGradingExamRequest); return await GetNextExamQuestion(gradingExtamItemDto); } public async Task GetUnExamUsers(UnExamUserReportPagedRequest unExamUserReportPagedRequest) { if (unExamUserReportPagedRequest.EndTime == null) unExamUserReportPagedRequest.ResolveEndTime(); var examManageRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var expression = unExamUserReportPagedRequest.GetExpression(); var userExamExpression = unExamUserReportPagedRequest.GetUserExamExpression(); var examManageTable = examManageRepository.Queryable().Where(expression); var userTable = userRepository.Queryable(); var userExamTable = _repository.Queryable().Where(userExamExpression); var queryResult = userExamTable.InnerJoin(examManageTable, (ue, e) => ue.ExamId == e.Id) .InnerJoin(userTable, (ue, e, u) => ue.UserId == u.Id) .Select((ue, e, u) => new UnExamUserViewResponse { ExamName = e.Name, OrgName = u.Organization.Name, UserName = u.Name }) .MergeTable() .OrderByPropertyNameIF(!string.IsNullOrEmpty(unExamUserReportPagedRequest.SortField), unExamUserReportPagedRequest.SortField, (OrderByType)(unExamUserReportPagedRequest.SortRule ?? 0)); var total = await queryResult.CountAsync(); var items = await queryResult.ToPageListAsync(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize); return new UnExamUserPageViewResponse { Items = items, Pagination = new Pagination(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize, total) }; } public async Task GetUserExamResults(UserExamResultReportPagedRequest userExamResultReportPagedRequest) { if (userExamResultReportPagedRequest.EndTime == null) userExamResultReportPagedRequest.ResolveEndTime(); var examManageRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var expression = userExamResultReportPagedRequest.GetExpression(); var userExamExpression = userExamResultReportPagedRequest.GetUserExamExpression(); var examManageTable = examManageRepository.Queryable().Where(expression); var userTable = userRepository.Queryable(); var userExamTable = _repository.Queryable().Where(userExamExpression); var queryResult = userExamTable.InnerJoin(examManageTable, (ue, e) => ue.ExamId == e.Id) .InnerJoin(userTable, (ue, e, u) => ue.UserId == u.Id) .Select((ue, e, u) => new UserExamResultViewResponse { ExamName = e.Name, OrgName = u.Organization.Name, UserName = u.Name, TotalScore = e.TotalScore, CutoffScore = e.CutoffScore, Score = ue.Score ?? 0, }) .MergeTable() .OrderByPropertyNameIF(!string.IsNullOrEmpty(userExamResultReportPagedRequest.SortField), userExamResultReportPagedRequest.SortField, (OrderByType)(userExamResultReportPagedRequest.SortRule ?? 0)) .OrderByDescending(x => x.Score) ; var total = await queryResult.CountAsync(); var items = await queryResult.ToPageListAsync(userExamResultReportPagedRequest.PageIndex, userExamResultReportPagedRequest.PageSize); return new UserExamResultPageViewResponse { Items = items, Pagination = new Pagination(userExamResultReportPagedRequest.PageIndex, userExamResultReportPagedRequest.PageSize, total) }; } public async Task GetGradingResultPagedList(GradingPagedRequest gradingPagedRequest) { // 只要有阅卷记录就在已阅卷列表中,已阅卷和未阅卷会有重复数据,只有所有记录都已阅卷才会从未阅卷列表中排除 var userExamTable = _repository.Queryable().Where(x => x.IsSubmit); var examManageTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var queryable = userExamTable.InnerJoin(examManageTable, (u, e) => u.ExamId == e.Id).GroupBy((u, e) => new { ExamName = e.Name, ExamCode = e.Code, CutoffScore = e.CutoffScore, TotalScore = e.TotalScore, Id = e.Id, Status = e.Status, Remark = e.Remark }).Select((u, e) => new GradingResultViewResponse { CutoffScore = e.CutoffScore, TotalScore = e.TotalScore, ExamName = e.Name, ExamCode = e.Code, IsCheck = SqlFunc.Subqueryable().Where(x => x.ExamId == e.Id && !x.IsCheck).Count() <= 0, Id = e.Id, Remark = e.Remark }).MergeTable(); queryable = queryable.WhereIF(gradingPagedRequest.IsCheck != null, x => x.IsCheck == gradingPagedRequest.IsCheck); var list = await queryable.ToPageListAsync(gradingPagedRequest.PageIndex, gradingPagedRequest.PageSize); var total = await queryable.CountAsync(); var result = new GradingResultPageViewResponse { Items = list, Pagination = new Pagination(gradingPagedRequest.PageIndex, gradingPagedRequest.PageSize, total) }; return result; } public async Task BatchGradingAsync(BatchGradingExamItemDto batchGradingExamItemDto, CancellationToken cancellationToken) { var userExamItemIds = batchGradingExamItemDto.Items.Select(x => x.UserExamItemId); var userExamItems = await _userExamItemRepository.Queryable().Where(m => userExamItemIds.Contains(m.Id)).ToListAsync(); if (userExamItems != null && userExamItemIds.Any()) { var updateUserExamItems = new List(); userExamItems.ForEach(x => { var gradingExamItemDto = batchGradingExamItemDto.Items.Find(m => m.UserExamItemId == x.Id); var updateUserExamItem = _mapper.Map(gradingExamItemDto, x); updateUserExamItem.IsCheck = true; updateUserExamItems.Add(updateUserExamItem); }); updateUserExamItems.ToUpdate(_sessionContext); await _userExamItemRepository.UpdateWithValidateAsync(updateUserExamItems, cancellationToken); var userExamId = userExamItems.FirstOrDefault()?.UserExamId; // 计算本次考试得分 var userExamItemsInCheck = await _userExamItemRepository.Queryable() .InnerJoin((u, q) => u.QuestionId == q.QuestionId) .Where((u, q) => u.UserExamId == userExamId && (q.QuestionType == EQuestionType.Single || q.QuestionType == EQuestionType.Multi || q.QuestionType == EQuestionType.Judge)).Select((u, q) => new UpdateUserExamItemDto { QuestionId = u.QuestionId, QuestionType = q.QuestionType, UserExamId = u.UserExamId, Id = u.Id }).Distinct().ToListAsync(); await CalcuteExamItemScore(_userExamItemRepository, userExamItemsInCheck, cancellationToken); await CalcuteTotalScore(_userExamItemRepository, userExamId, cancellationToken); } } public async Task> GetUserListAsync(ExamUserQueryRequest examUserQueryRequest) { var userExamTable = _repository.Queryable().Where(x => x.ExamId == examUserQueryRequest.ExamId); var queryable = await userExamTable.InnerJoin((ux, u) => ux.UserId == u.Id).Select((ux, u) => new ExamUserViewResponse { ExamId = ux.ExamId, UserId = ux.UserId, UserName = u.Name, Id = ux.Id }).ToListAsync(); return queryable; } #endregion #region private method private async Task CalcuteExamItemScore(IUserExamItemRepository userExamRepository, UpdateUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken) { if (!addUserExamItemDto.QuestionType.CheckSelectType()) return; var testPaperItemOptionsRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examManageRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var testPaperItemRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examQuestionScoreRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var testPaperOptionsTable = testPaperItemOptionsRepository.Queryable().Where(x => x.QuestionId == addUserExamItemDto.QuestionId && x.IsAnswer); var testPaperItemTable = testPaperItemRepository.Queryable(); var userExamTable = _repository.Queryable().Where(x => x.Id == addUserExamItemDto.UserExamId); var examManageTable = examManageRepository.Queryable(); var testPaperOptionIds = await testPaperOptionsTable.InnerJoin(testPaperItemTable, (t, i) => t.ExamQuestionId == i.Id) .InnerJoin(examManageTable, (t, i, e) => i.ExamId == e.Id) .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId) .Select((t, i, e, u) => t.Id).ToListAsync(); var isCorrect = addUserExamItemDto.UserExamItemOptionDtos.Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(testPaperOptionIds.OrderBy(x => x)); var userExamItem = await userExamRepository.GetAsync(x => x.UserExamId == addUserExamItemDto.UserExamId && x.QuestionId == addUserExamItemDto.QuestionId); var examQuesiontScores = await examQuestionScoreRepository.Queryable().Where(x => x.QuestionType == addUserExamItemDto.QuestionType) .InnerJoin(userExamTable, (e, u) => e.Id == u.ExamId) .Select((e, u) => e).ToListAsync(); userExamItem.IsCheck = true; userExamItem.Score = isCorrect ? examQuesiontScores.FirstOrDefault()?.Score : 0; userExamItem.ToUpdate(_sessionContext); await userExamRepository.UpdateWithValidateAsync(userExamItem, cancellationToken); } private async Task CalcuteExamItemScore(IUserExamItemRepository userExamItemRepository, List addUserExamItemDtos, CancellationToken cancellationToken) { var questionIds = addUserExamItemDtos.Select(x => x.QuestionId).ToList(); var userExamIds = addUserExamItemDtos.Select(x => x.UserExamId).ToList(); var questionTypes = addUserExamItemDtos.Select(x => x.QuestionType).ToList(); List examQuestionOptions = await GetQuestionOptionBaks(questionIds, userExamIds, true).ToListAsync(); var userExamItemOptionRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examQuestionScoreRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userExamTable = _repository.Queryable().Where(x => userExamIds.Contains(x.Id)); var userExamItems = await userExamItemRepository.Queryable().Where(x => userExamIds.Contains(x.UserExamId)).ToListAsync(); var userExamItemIds = userExamItems.Select(x => x.Id).ToList(); var userExamItemOptions = await userExamItemOptionRepository.Queryable().Where(x => userExamItemIds.Contains(x.UserExamItemId)).ToListAsync(); var examQuesiontScores = await examQuestionScoreRepository.Queryable().Where(x => questionTypes.Contains(x.QuestionType)) .InnerJoin(userExamTable, (e, u) => e.ExamManageId == u.ExamId) .Select((e, u) => e).ToListAsync(); foreach (var addUserExamItemDto in addUserExamItemDtos) { var examQuestionOptionIds = examQuestionOptions.Where(x => x.QuestionId == addUserExamItemDto.QuestionId).Select(x => x.Id).ToList(); var isCorrect = userExamItemOptions.Where(x => x.UserExamItemId == addUserExamItemDto.Id).Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(examQuestionOptionIds.OrderBy(x => x)); var userExamItem = userExamItems.FirstOrDefault(x => x.QuestionId == addUserExamItemDto.QuestionId); if (userExamItem != null) { userExamItem.IsCheck = true; userExamItem.Score = isCorrect ? examQuesiontScores.FirstOrDefault(x => x.QuestionType == addUserExamItemDto.QuestionType)?.Score : 0; userExamItem.ToUpdate(_sessionContext); } } await userExamItemRepository.UpdateWithValidateAsync(userExamItems, cancellationToken); } private ISugarQueryable GetQuestionOptionBaks(List questionIds, List userExamIds, bool isFilterAnswer) { var questionRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var questionTable = questionRepository.Queryable().Where(x => x.QuestionType == EQuestionType.Single || x.QuestionType == EQuestionType.Multi || x.QuestionType == EQuestionType.Judge); var userExamTable = _repository.Queryable().Where(x => userExamIds.Contains(x.Id)); var examManageRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examManageTable = examManageRepository.Queryable(); var examQuestionOptionsRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examQuestionOptionsTable = examQuestionOptionsRepository.Queryable() .Where(x => questionIds.Contains(x.QuestionId)) .WhereIF(isFilterAnswer, x => x.IsAnswer); var examQuestionOptions = examQuestionOptionsTable.InnerJoin(questionTable, (t, i) => t.ExamQuestionId == i.Id) .InnerJoin(examManageTable, (t, i, e) => i.ExamId == e.Id) .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId) .Select((t, i, e, u) => new ExamQuestionOptionsBak { Id = t.Id, Content = t.Content, IsAnswer = t.IsAnswer, Label = t.Label, ExamQuestionId = t.ExamQuestionId, QuestionId = t.QuestionId }); return examQuestionOptions; } private async Task CalcuteTotalScore(IUserExamItemRepository userExamItemRepository, string userExamId, CancellationToken cancellationToken) { var userExam = await _repository.GetAsync(x => x.Id == userExamId); if (userExam != null) { var userExamItems = await userExamItemRepository.Queryable().Where(x => x.UserExamId == userExamId).ToListAsync(); var examManageRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examManage = await examManageRepository.GetAsync(x => x.Id == userExam.ExamId); var totalScore = userExamItems.Sum(x => x.Score); userExam.Score = totalScore; userExam.IsCheck = true; userExam.ExamStatus = EExamStatus.Complete; if (examManage != null) { userExam.IsSuccess = userExam.Score > examManage.CutoffScore; } userExam.ToUpdate(_sessionContext); await _repository.UpdateWithValidateAsync(userExam, cancellationToken); } } private async Task AddExamAsync(IRepository userExamItemRepository, AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken) { var userExamItem = await AddUserExamItem(addUserExamItemDto, cancellationToken); userExamItem.UserExamItemOptionses = await AddUserExamItemOptions(addUserExamItemDto, cancellationToken); userExamItem.ExamAnswers = await AddExamAnswer(addUserExamItemDto, userExamItem.Id, cancellationToken); await userExamItemRepository.AddNav(userExamItem) .Include(x => x.UserExamItemOptionses) .Include(x => x.ExamAnswers) .ExecuteCommandAsync(); } private async Task UpdateExamAsync(IRepository userExamItemRepository, UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken) { var userExamItem = await UpdateUserExamItem(updateUserExamItemDto, cancellationToken); userExamItem.UserExamItemOptionses = await ModifyUserItemOptions(updateUserExamItemDto, cancellationToken); userExamItem.ExamAnswers = await UpdateExamAnswer(updateUserExamItemDto, cancellationToken); await userExamItemRepository.UpdateNav(userExamItem) .Include(x => x.UserExamItemOptionses) .Include(x => x.ExamAnswers) .ExecuteCommandAsync(); } private async Task GetNextExamQuestion(GradingExamItemDto gradingExtamItemDto) { // TODO: 获取未阅卷的第一道题 var current = _userExamItemRepository.Queryable().Where(x => x.Id == gradingExtamItemDto.UserExamItemId); var userExamItemTable = _userExamItemRepository.Queryable().Where(x => !x.IsCheck); var userExamItem = current.InnerJoin(userExamItemTable, (c, u) => c.UserExamId == u.UserExamId).OrderBy((c, u) => c.SortIndex).First(); if (userExamItem != null) { var testPaperItem = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == userExamItem.Id && !x.QuestionType.CheckSelectType()).First(); if (testPaperItem == null) return null; var gradingExamQuestionDto = new GradingExamQuestionDto(); gradingExamQuestionDto = _mapper.Map(testPaperItem, gradingExamQuestionDto); var examAnswer = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.UserExamItemId == userExamItem.Id).First(); var testPaperItemAnswer = await new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().FirstAsync(x => x.QuestionId == testPaperItem.QuestionId && x.ExamQuestionId == testPaperItem.Id); gradingExamQuestionDto.Answer = examAnswer.Answer ?? string.Empty; gradingExamQuestionDto.CorrectAnswer = testPaperItemAnswer != null ? testPaperItemAnswer.Answer ?? string.Empty : string.Empty; return gradingExamQuestionDto; } return null; } private async Task> AddExamAnswer(AddUserExamItemDto addUserExamItemDto, string id, CancellationToken cancellationToken) { if (addUserExamItemDto.QuestionType.CheckSelectType()) return null; var examAnswers = new List(); var examAnswer = new ExamAnswer { UserId = _sessionContext.UserId, UserExamItemId = id, Answer = addUserExamItemDto.Answer }; examAnswer.ToInsert(_sessionContext); await _examAnswerRepository.ValidateAddAsync(examAnswer, cancellationToken); examAnswers.Add(examAnswer); return examAnswers; } private async Task GetNextExamQuestion(AddUserExamItemDto addUserExamItemDto) { // TODO: 获取未阅卷的第一道题 var testPaperItemRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var examRepository = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider); var userExamTable = _repository.Queryable().Where(x => x.Id == addUserExamItemDto.UserExamId); var userExamItemTable = _userExamItemRepository.Queryable().WhereIF(addUserExamItemDto.QuestionId.IsNotNullOrEmpty(), x => x.QuestionId == addUserExamItemDto.QuestionId); var examTable = examRepository.Queryable(); var testPaperItemTable = testPaperItemRepository.Queryable(); var current = examTable.InnerJoin(testPaperItemTable, (e, t) => e.Id == t.ExamId) .InnerJoin(userExamTable, (e, t, u) => e.Id == u.ExamId) .InnerJoin(userExamItemTable, (e, t, u, i) => t.QuestionId == i.QuestionId).Select((e, t, u, i) => t); var nextTable = testPaperItemTable.InnerJoin(current, (t, c) => t.SortIndex > c.SortIndex).OrderBy((t, c) => t.SortIndex).Select((t, c) => t); var userExamItem = userExamItemTable.InnerJoin(nextTable, (u, n) => u.QuestionId == n.QuestionId).OrderBy((u, n) => u.SortIndex).Select((u, n) => u).First(); if (userExamItem != null) { var question = testPaperItemRepository.Queryable().Where(x => x.Id == userExamItem.Id).First(); if (question == null) return null; var userExamQuestionDto = new UserExamQuestionDto(); userExamQuestionDto = _mapper.Map(question, userExamQuestionDto); if (question.QuestionType.CheckSelectType()) { var userExamItemOptionTable = _userExamItemOptionRepository.Queryable().Where(x => x.UserExamItemId == userExamItem.Id); var quesitonOptionTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var queryResult = userExamItemOptionTable.InnerJoin(quesitonOptionTable, (u, q) => u.QuestionOptionId == q.Id) .Select((u, q) => new UserExamItemOptionDto { Content = q.Content, QuestionOptionId = u.QuestionOptionId, UserExamItemId = u.UserExamItemId }); userExamQuestionDto.UserExamItemOptionDtos = queryResult.ToList(); } else { var examAnswer = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.UserExamItemId == userExamItem.Id).First(); userExamQuestionDto.Answer = examAnswer.Answer ?? string.Empty; } return userExamQuestionDto; } else { return null; } } private async Task> UpdateExamAnswer(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken) { var examAnswerTable = _examAnswerRepository.Queryable(); var userExamItemTable = _userExamItemRepository.Queryable().Where(x => x.Id == updateUserExamItemDto.Id); var examAnswer = await examAnswerTable.InnerJoin(userExamItemTable, (e, u) => e.UserExamItemId == u.Id).Select((e, u) => e).FirstAsync(); if (!updateUserExamItemDto.QuestionType.CheckSelectType()) { var examAnswers = new List(); if (examAnswer != null) { examAnswer.Answer = updateUserExamItemDto.Answer; examAnswer.UserId = _sessionContext.UserId; examAnswer.UserExamItemId = updateUserExamItemDto.Id; examAnswer.ToUpdate(_sessionContext); await _examAnswerRepository.UpdateWithValidateAsync(examAnswer, cancellationToken); examAnswers.Add(examAnswer); } else { examAnswer = new ExamAnswer { Answer = updateUserExamItemDto.Answer, UserId = _sessionContext.UserId, UserExamItemId = updateUserExamItemDto.Id }; examAnswer.ToInsert(_sessionContext); await _examAnswerRepository.ValidateAddAsync(examAnswer, cancellationToken); examAnswers.Add(examAnswer); } return examAnswers; } return null; } private async Task> ModifyUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken) { if (updateUserExamItemDto.QuestionType.CheckSelectType()) { var entityQuestionRequest = new EntityQueryRequest { Expression = ExpressionableUtility.CreateExpression() .AndIF(updateUserExamItemDto.Id.IsNotEmpty(), x => x.UserExamItemId == updateUserExamItemDto.Id).ToExpression() }; await DeleteUserExamItemOptions(entityQuestionRequest, cancellationToken); //await UpdateUserItemOptions(updateUserExamItemDto, cancellationToken); var addUserExamItemDto = _mapper.Map(updateUserExamItemDto); addUserExamItemDto.UserExamItemOptionDtos = new List(); updateUserExamItemDto.UserExamItemOptionDtos.ForEach(item => { addUserExamItemDto.UserExamItemOptionDtos.Add(_mapper.Map(item)); }); return await AddUserExamItemOptions(addUserExamItemDto, cancellationToken); } return null; } private async Task UpdateUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken) { if (updateUserExamItemDto.QuestionType.CheckSelectType()) { var userExamItemOptions = await _userExamItemOptionRepository.Queryable().Where(x => x.UserExamItemId == updateUserExamItemDto.Id).ToListAsync(); var entities = new List(); if (updateUserExamItemDto.UserExamItemOptionDtos != null) { updateUserExamItemDto.UserExamItemOptionDtos.Where(m => m.OperationStatus == EEOperationStatus.Update).ToList().ForEach(x => { var entity = userExamItemOptions.FirstOrDefault(m => m.Id == x.Id); if (entity != null) { entities.Add(_mapper.Map(x, entity)); } }); } entities.ToUpdate(_sessionContext); await _userExamItemOptionRepository.UpdateWithValidateAsync(entities, cancellationToken); } } private async Task UpdateUserExamItem(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken) { var userExamItem = await _userExamItemRepository.GetAsync(x => x.UserExamId == updateUserExamItemDto.UserExamId && x.QuestionId == updateUserExamItemDto.QuestionId); userExamItem = _mapper.Map(updateUserExamItemDto, userExamItem); updateUserExamItemDto.Id = userExamItem.Id; userExamItem.ToUpdate(_sessionContext); await _userExamItemRepository.UpdateWithValidateAsync(userExamItem, cancellationToken); if (updateUserExamItemDto.QuestionType.CheckSelectType()) { if (updateUserExamItemDto.UserExamItemOptionDtos != null) { updateUserExamItemDto.UserExamItemOptionDtos.ForEach(x => x.UserExamItemId = updateUserExamItemDto.Id); } } return userExamItem; } private async Task> AddUserExamItemOptions(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken) { var userExamItemOptions = new List(); if (addUserExamItemDto.QuestionType.CheckSelectType()) { if (addUserExamItemDto.UserExamItemOptionDtos != null) { addUserExamItemDto.UserExamItemOptionDtos.ToList().ForEach(x => { userExamItemOptions.Add(_mapper.Map(x)); }); } } userExamItemOptions.ToInsert(_sessionContext); await _userExamItemOptionRepository.ValidateAddAsync(userExamItemOptions, cancellationToken); return userExamItemOptions; } private async Task AddUserExamItem(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken) { var userExamItem = _mapper.Map(addUserExamItemDto); userExamItem.ToInsert(_sessionContext); await _userExamItemRepository.ValidateAddAsync(userExamItem, cancellationToken); if (addUserExamItemDto.QuestionType.CheckSelectType()) { if (addUserExamItemDto.UserExamItemOptionDtos != null) { addUserExamItemDto.UserExamItemOptionDtos.ForEach(x => x.UserExamItemId = userExamItem.Id); } } return userExamItem; } private async Task DeleteUserExamItemOptions(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken) { await _userExamItemOptionRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken); } private SqlSugar.ISugarQueryable GetQueryable(UserExamPagedRequest queryRequest) { if (_sessionContext.UserId != null) { queryRequest.UserId = _sessionContext.UserId; } var expression = queryRequest.GetExpression(); var userExamTable = _repository.Queryable().Where(expression); var examManageExpression = queryRequest.GetExamManageExpression(); var examManageTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(examManageExpression); var queryable = userExamTable.InnerJoin(examManageTable, (u, e) => u.ExamId == e.Id).Select((u, e) => new UserExamResultViewResponse { Id = u.Id, CutoffScore = e.CutoffScore, TotalScore = e.TotalScore, ExamName = e.Name, Score = u.Score ?? 0, Status = u.Status, SortIndex = u.SortIndex, ExamStatus = u.ExamStatus == EExamStatus.Absent? EExamStatus.Complete: u.ExamStatus, IsSuccess = u.IsCheck ? u.IsSuccess : null, EndTime = e.EndTime, StartTime = e.StartTime, TimeSpan = e.TimeSpan, ExamType = e.ExamType, ExamId = e.Id, IsCheck = u.IsCheck, IsReExam = u.IsReExam, CanReExam = SqlFunc.Subqueryable().Where(x => x.UserExamId == u.Id).Count() < e.Count }); return queryable; } public async Task> View(string id) { List viewExamQuestionDtos = await GetViewExamQuestion(id, null); var examQuestionIds = viewExamQuestionDtos.Select(x => x.ExamQuestionId).ToList(); var questionIds = viewExamQuestionDtos.Select(x => x.QuestionId).ToList(); var userExamIds = new List { id }; //List questionAnswers = await GetQuestionAnswers(id, questionIds); List questionOptions = await GetQuestionOptions(questionIds, userExamIds); List questionKnowladges = await GetQuestionKnowladges(examQuestionIds); List sourcewares = await GetSourcewares(examQuestionIds); ResolveExamQuestions(viewExamQuestionDtos, questionOptions, questionKnowladges, sourcewares); return viewExamQuestionDtos; } public async Task View(string id, string questionId) { List viewExamQuestionDtos = await GetViewExamQuestion(id, questionId); var examQuestionIds = viewExamQuestionDtos.Select(x => x.ExamQuestionId).ToList(); var questionIds = viewExamQuestionDtos.Select(x => x.QuestionId).ToList(); var userExamIds = new List { id }; //List questionAnswers = await GetQuestionAnswers(id, questionIds); List questionOptions = await GetQuestionOptions(questionIds, userExamIds); List questionKnowladges = await GetQuestionKnowladges(examQuestionIds); List sourcewares = await GetSourcewares(examQuestionIds); ResolveExamQuestions(viewExamQuestionDtos, questionOptions, questionKnowladges, sourcewares); return viewExamQuestionDtos.FirstOrDefault(); } private static void ResolveExamQuestions(List viewExamQuestionDtos, List questionOptions, List questionKnowladges, List sourcewares) { viewExamQuestionDtos.ForEach(item => { item.QuestionKnowladgeDtos = questionKnowladges.Where(x => x.QuestionId == item.ExamQuestionId).ToList(); item.QuestionSourcewareDtos = sourcewares.Where(x => x.QuestionId == item.ExamQuestionId).ToList(); if (item.QuestionType.CheckSelectType()) { item.QuestionOptions = questionOptions.Where(x => x.QuestionId == item.ExamQuestionId).ToList(); item.CorrectAnswer = string.Join(",", item.QuestionOptions.Where(m => m.IsAnswer).Select(m => m.Label).ToArray()); } }); } private async Task> GetSourcewares(List questionIds) { var questionSourcewareTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var sourcewareTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var querable = questionSourcewareTable.InnerJoin((qsb, qs) => qsb.SourcewareId == qs.Id).InnerJoin(sourcewareTable, (qsb, qs, s) => qs.SourcewareId == s.Id).Select((qsb, qs, s) => new QuestionSourcewareDto { Id = qs.Id, Name = s.Name, QuestionId = qsb.ExamQuestionId, SourcewareId = s.Id, AttachmentId = s.AttachmentId }).MergeTable().Where(x => questionIds.Contains(x.QuestionId)); return await querable.ToListAsync(); } private async Task> GetQuestionKnowladges(List questionIds) { var questionKnowladgeTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); return await questionKnowladgeTable.Where(x => questionIds.Contains(x.ExamQuestionId)) .InnerJoin((kb, k) => kb.KnowladgeId == k.Id).Select((kb, k) => new QuestionKnowladgeDto { Id = kb.Id, QuestionId = kb.ExamQuestionId, KnowladgeId = k.KnowladgeId, Title = kb.Title }).ToListAsync(); } private async Task> GetQuestionOptions(List questionIds, List userExamIds) { var selectQuestionOptions = GetQuestionOptionBaks(questionIds, userExamIds, false).MergeTable(); var userExamItemOptionTable = _userExamItemOptionRepository.Queryable(); var querable = selectQuestionOptions .LeftJoin(userExamItemOptionTable, (op, uio) => op.Id == uio.QuestionOptionId) .Select((op, uio) => new ViewQuestionOptionDto { Content = op.Content, Id = op.Id, IsAnswer = op.IsAnswer, Label = op.Label, QuestionId = op.ExamQuestionId, IsSelected = uio.Id != null }).MergeTable().OrderBy(x => x.Label); return await querable.Distinct() .ToListAsync(); } private async Task> GetQuestionAnswers(string id, List questionIds) { var userExamTable = _repository.Queryable().Where(x => x.Id == id); var userExamItemTable = _userExamItemRepository.Queryable(); var examAnswerTable = _examAnswerRepository.Queryable(); var questionTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var questionAnswerTable = new ExamRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable(); var querable = examAnswerTable .InnerJoin(userExamItemTable, (a, ui) => ui.Id == a.UserExamItemId && ui.UserExamId == id) .LeftJoin(questionAnswerTable, (a, ui, qab) => qab.QuestionId == ui.QuestionId) .LeftJoin((a, ui, qab, qa) => qab.QuestionAnswerId == qa.Id) .LeftJoin(questionTable, (a, ui, qab, qa, q) => qab.QuestionId == q.QuestionId && questionIds.Contains(q.Id)) .Select((a, ui, qab, qa, q) => new ViewQuestionAnswerDto { Answer = a.Answer, CorrectAnswer = qa.Answer != null ? qa.Answer : string.Empty, QuestionId = q.Id }).MergeTable(); return await querable.ToListAsync(); } private async Task> GetViewExamQuestion(string id, string questionId) { var expression = ExpressionableUtility.CreateExpression() .And(x => x.Id == id).ToExpression(); ISugarQueryable queryable = GetViewExamQuestionTempDtos(expression); queryable = queryable.MergeTable().WhereIF(!string.IsNullOrEmpty(questionId), x => x.QuestionId == questionId); var queryResult = await queryable.ToListAsync(); var viewExamQuestion = queryResult.GroupBy(x => new { Id = x.Id, QuestionType = x.QuestionType }).Select(g => new ViewExamQuestionDto { Answer = g.FirstOrDefault().Answer, QuestionType = g.Key.QuestionType, QuestionId = g.FirstOrDefault().QuestionId, ExamQuestionId = g.FirstOrDefault().ExamQuestionId, Id = g.Key.Id, Score = g.FirstOrDefault().QuestionScore, RealScore = g.FirstOrDefault().Score, Title = g.FirstOrDefault().Title, CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Empty : g.FirstOrDefault()?.CorrectAnswer }).ToList(); return viewExamQuestion; } #endregion } }