public class LessonAppService :ApplicationService, ILessonService { private readonly ILessonRepository _lessonRepository; private readonly IAsyncQueryableExecuter _asyncExecuter; private Lesson _activeLesson; private Question _currentQuestion; private Answer _currentAnswer; private List _UserLessons; private LessonState _lessonState; public LessonAppService(ILessonRepository lessonRepository,IAsyncQueryableExecuter asyncExecuter) { _lessonRepository = lessonRepository; _asyncExecuter = asyncExecuter; } public async Task CreateAsync(CreateLessonDTO input) { try { var lessonCount = await _lessonRepository.CountAsync(x => x.CreatorId == CurrentUser.Id); var lesson = ObjectMapper.Map(input); lesson.LessonNumber = lessonCount + 1; lesson.CreatorId = CurrentUser.Id; lesson.isServerGenerated = false; lesson = await _lessonRepository.InsertAsync(lesson); UpdatePrivateFields(lesson); return ObjectMapper.Map(lesson); } catch (Exception ex) { // Handle the exception here, or re-throw it if appropriate throw new Exception("An error occurred while creating the lesson.", ex); } } public async Task SetActiveLesson(Guid lessonId) { try { var lessons = _UserLessons; var lesson = lessons .Where(x => x.CreatorId == CurrentUser.Id && x.Id == lessonId) .FirstOrDefault(); if (lesson is not null) { _activeLesson = lesson; if (!lesson.LessonStates.Any() || _activeLesson != lesson) { var lessonState= await UpdateLessonStateAsync(true); } var updatedLesson= await _lessonRepository.UpdateAsync(_activeLesson); UpdatePrivateFields(updatedLesson); } else { throw new Exception("Lesson not found."); } } catch (Exception ex) { // Handle the exception here, or re-throw it if appropriate throw new Exception("An error occurred while setting the active lesson.", ex); } } private void UpdatePrivateFields(Lesson lesson) { _activeLesson = lesson; _lessonState = lesson.LessonStates.Last(); _currentQuestion = _activeLesson.Questions.Find(x => x.Id == _lessonState.CurrentQuestion); _currentAnswer = _currentQuestion.Answer; } public async Task TryAnswerQuestionAsync(CreateUpdateAnswerDTO userResponse) { try { var currentQuestionId = _lessonState.CurrentQuestion; var question =_currentQuestion; var answer = ObjectMapper.Map(userResponse); // determine if answered successfully bool isAnsweredSuccessfully = question.SuccessRate > 50; if (isAnsweredSuccessfully)await CheckLessonCompletion(); question.Answer = answer; question.AnsweredSeccesfully = isAnsweredSuccessfully; var lesson = await _lessonRepository.UpdateAsync(_activeLesson); UpdatePrivateFields(lesson); await UpdateLessonStateAsync(false); if (_lessonState.IsLessonComplete) { await ActivateNextLesson(_activeLesson.Id); } return ObjectMapper.Map(lesson); } catch (Exception ex) { // Handle the exception here, log it, and return an error message to the user throw new Exception("Failed to answer the question. Please try again later.", ex); } } public async Task> GetUserLessons() { try { var queryable = await _lessonRepository.WithDetailsAsync(); var lessonsQuery = queryable.Where(x => x.CreatorId == CurrentUser.Id).OrderBy(x => x.LessonNumber); var lessons = await lessonsQuery.ToListAsync(); _UserLessons = lessons; return ObjectMapper.Map, List>(lessons); } catch (Exception ex) { // Handle exception here Console.WriteLine($"Error occurred: {ex.Message}"); return null; } } private async Task ActivateNextLesson(Guid lessonId) { var CurrentLessonIndex = _UserLessons.FindIndex(x => x.Id == _activeLesson.Id); var nextLesson = _UserLessons[CurrentLessonIndex + 1]; UpdatePrivateFields(nextLesson); await UpdateLessonStateAsync(); return nextLesson; } private async Task CheckLessonCompletion() { try { var questionCount = _activeLesson.Questions.Count; var questionIndex = _activeLesson.Questions.FindIndex(x => x.Id == _currentQuestion.Id); if (_currentQuestion.AnsweredSeccesfully && questionCount == questionIndex) { _activeLesson.IsLessonComplete = true; _lessonState.IsLessonComplete = true; var updatedLesson = await _lessonRepository.UpdateAsync(_activeLesson); UpdatePrivateFields(updatedLesson); await UpdateLessonStateAsync(); return true; } return false; } catch (Exception ex) { throw new Exception("Error occurred while checking lesson completion.", ex); } } private async Task UpdateLessonStateAsync(bool isNewLesson = false) { var newLessonStaate = new LessonState() { CurrentQuestion = _activeLesson.Questions.First().Id, IsLessonComplete = false, LessonStartTime = DateTime.UtcNow, LessonEndTime = null, IsLessonActive = true }; try { if (!isNewLesson) { newLessonStaate.CurrentQuestion = _currentQuestion.Id; newLessonStaate.IsLessonComplete = _activeLesson.IsLessonComplete; newLessonStaate.LessonEndTime = _lessonState.LessonEndTime; newLessonStaate.IsLessonActive = _lessonState.IsLessonActive; newLessonStaate.IsLessonComplete = _lessonState.IsLessonComplete; } _activeLesson.LessonStates.AddLast(newLessonStaate); await _lessonRepository.UpdateAsync(_activeLesson); _lessonState = newLessonStaate; return newLessonStaate; } catch (Exception ex) { // Handle the exception here, log it, and return an error message to the user throw new Exception("Failed to update the lesson state. Please try again later.", ex); } } }