public static async Task <Result <QuestionInfo> > GetNextQuestion(UserSubjectProgress progress, CancellationToken cancellationToken, IDbContext db) { UserQuestion nextQuestion = null; var applicableQuestionLevel = progress.Level == 3 ? 2 : progress.Level; var questions = progress.Questions.Where(x => x.Level == applicableQuestionLevel).ToList().Shuffle(); //Pega a primeira pergunta não respondida foreach (var userQuestion in questions) { if (userQuestion.Answered) { continue; } nextQuestion = userQuestion; break; } if (nextQuestion == null) { //if (progress.Questions.All(x => x.Level != applicableQuestionLevel)) // return Result.Fail<QuestionInfo>("Não foi possível obter nenhuma questão para o nível atual"); //Se não encontrou nenhuma é pq acabou o BDQ e tem que resetar as perguntas que ele respondeu errado foreach (var userQuestion in progress.Questions.Where(x => x.Level == applicableQuestionLevel).ToList()) { if (!userQuestion.Answered || userQuestion.HasAnsweredCorrectly) { continue; } //if (!userQuestion.Answered || userQuestion.HasAnsweredCorrectly || userQuestion.AnsweredCount > 99) continue; userQuestion.Answered = false; if (nextQuestion == null) { nextQuestion = userQuestion; } } //Atualiza no banco de dados if (nextQuestion != null) { await db.UserSubjectProgressCollection.ReplaceOneAsync(t => t.Id == progress.Id, progress, cancellationToken : cancellationToken); } } if (nextQuestion == null) { return(Result.Fail <QuestionInfo>("Não foi possível obter nenhuma questão para o nível atual")); } var question = await db.QuestionCollection .AsQueryable() .Where(x => x.Id == nextQuestion.QuestionId) .FirstOrDefaultAsync(cancellationToken: cancellationToken); //validando se a configuração das perguntas mudou var dbcorrectAnswer = question.Answers.FirstOrDefault(x => x.Points == 2); if (dbcorrectAnswer == null) { return(Result.Fail <QuestionInfo>("Pergunta com configuração errada. Por favor contate o suporte")); } if (nextQuestion.CorrectAnswerId != dbcorrectAnswer.Id) { nextQuestion.CorrectAnswerId = dbcorrectAnswer.Id; //Atualiza no banco de dados await db.UserSubjectProgressCollection.ReplaceOneAsync(t => t.Id == progress.Id, progress, cancellationToken : cancellationToken); } var rand = new Random(DateTime.Now.Millisecond + DateTime.Now.Second); var response = new QuestionInfo() { Text = question.Text, Id = question.Id, ModuleId = question.ModuleId, SubjectId = question.SubjectId, Answers = question.Answers.Select(a => new AnswerInfo() { Id = a.Id, Description = a.Description, Concepts = a.Concepts }).ToList().Shuffle(), Concepts = question.Concepts.Select(c => c.Name).ToList() }; return(Result.Ok(response)); }
public async Task <Result <QuestionInfo> > Handle(Contract request, CancellationToken cancellationToken) { try { var moduleId = ObjectId.Parse(request.ModuleId); var subjectId = ObjectId.Parse(request.SubjectId); var userId = ObjectId.Parse(request.UserId); var progress = await _db .UserSubjectProgressCollection .AsQueryable() .FirstOrDefaultAsync(x => x.ModuleId == moduleId && x.UserId == userId && x.SubjectId == subjectId, cancellationToken: cancellationToken); if (progress != null) { //Já está no nivel máximo if (progress.Level == 4) { return(Result.Fail <QuestionInfo>("Você já alcançou o nível máximo")); } //Não tem mais perguntas disponiveis //var applicableQuestionLevel = progress.Level == 3 ? 2 : progress.Level; //var currentQuestions = progress.Questions.Where(x => x.Level == applicableQuestionLevel).ToList(); //if (currentQuestions.All(x => x.HasAnsweredCorrectly || x.AnsweredCount > 1)) // return Result.Fail<QuestionInfo>("Não há a possibilidade de progredir no nivel atual. Você já alcançou o máximo de erros possíveis."); //Buscado a nova lista de respostas //var newQuestionList = await this.GetUserQuestionList(moduleId, subjectId, cancellationToken, progress); var newQuestionList = await this.GetUserQuestionList(moduleId, subjectId, cancellationToken); newQuestionList = newQuestionList.Shuffle(); // Retirando as perguntas não respondidas que não existem mais var questionCount = progress.Questions.Count; var newQuestionsIds = newQuestionList.Select(x => x.QuestionId); progress.Questions = progress.Questions .Where(x => x.HasAnsweredCorrectly || newQuestionsIds.Contains(x.QuestionId)) .OrderBy(x => x.Order).ToList(); if (questionCount != progress.Questions.Count || questionCount < newQuestionList.Count) { //Tirando as respostas existentes da nova lista var questionIdList = progress.Questions.Select(x => x.QuestionId).ToList(); progress.Questions.AddRange(newQuestionList .Where(x => !questionIdList.Contains(x.QuestionId)).OrderBy(x => x.Order)); //Ordenando depois de tudo pronto for (var i = 0; i < progress.Questions.Count; i++) { progress.Questions[i].Order = i; } //Atualiza no banco de dados await _db.UserSubjectProgressCollection.ReplaceOneAsync(t => t.Id == progress.Id, progress, cancellationToken : cancellationToken); } } else { progress = UserSubjectProgress.Create(moduleId, subjectId, userId); //progress.Questions = await this.GetUserQuestionList(moduleId, subjectId, cancellationToken, null); progress.Questions = await this.GetUserQuestionList(moduleId, subjectId, cancellationToken); //Atualiza no banco de dados await _db.UserSubjectProgressCollection.InsertOneAsync(progress, cancellationToken : cancellationToken); } var nextQuestion = await GetNextQuestion(progress, cancellationToken, _db); return(nextQuestion); } catch (Exception err) { Console.WriteLine(err.Message); throw; } }
private async Task SetModuleProgress(List <Module> modules, List <Track> tracks, List <UserProgress> userTracks, ObjectId userId, UserInfoDB userInfo, CancellationToken token) { var moduleId = ObjectId.Parse(userInfo.IdModuloEvento); var currentModule = modules.FirstOrDefault(t => t.Id == moduleId); if (currentModule != null) { await _db.ModuleGradeCollection.InsertOneAsync( ModuleGrade.Create( ObjectId.Parse(userInfo.IdModuloEvento), userId, CellIsEmpty(userInfo.Pontuacao) ? 0 : decimal.Parse(userInfo.Pontuacao.Replace(".", ",")), CellIsEmpty(userInfo.Presenca) ? 0 : decimal.Parse(userInfo.Presenca.Replace(".", ",")) ).Data, cancellationToken : token ); int currentLevel = GetLevelByGrade(userInfo.Pontuacao); var progressesToAdd = new List <UserSubjectProgress>(); if (currentModule.Subjects != null && currentModule.Subjects.Count > 0) { foreach (var subject in currentModule.Subjects) { var progress = UserSubjectProgress.Create(moduleId, subject.Id, userId); progress.Level = currentLevel; progress.Points = 100 * currentLevel; progressesToAdd.Add(progress); } await _db.UserSubjectProgressCollection.InsertManyAsync( progressesToAdd, cancellationToken : token ); } var moduleProgress = UserModuleProgress.Create(moduleId, userId); moduleProgress.Level = currentLevel; moduleProgress.Points = progressesToAdd.Sum(p => p.Points); await _db.UserModuleProgressCollection.InsertOneAsync( moduleProgress, cancellationToken : token ); var track = tracks.FirstOrDefault(t => userTracks.Any(ut => ut.Id == t.Id) && t.ModulesConfiguration.Any(m => m.ModuleId == moduleId) ); if (track != null) { var trackProgress = await _db.UserTrackProgressCollection .AsQueryable() .Where(t => t.TrackId == track.Id && t.UserId == userId) .FirstOrDefaultAsync(); if (trackProgress != null) { int modulesCompleted = 0; var trackConfig = track.ModulesConfiguration.FirstOrDefault(m => m.ModuleId == moduleId); if (trackConfig != null && currentLevel > trackConfig.Level) { modulesCompleted++; trackProgress.ModulesCompleted.Add(moduleId); trackProgress.Progress = (decimal)modulesCompleted / (decimal)track.ModulesConfiguration.Count; await _db.UserTrackProgressCollection.ReplaceOneAsync( t => t.Id == trackProgress.Id, trackProgress, cancellationToken : token ); } } } } }