// --------------------------------------------------------------------------------------------- public ModuleAndDistractorDTO PrevModule(int userId, int currentModuleId) { user user = _userService.GetUserEntity(userId); distractor newDistractor = null; // pobranie listy modułów dotychczas wysłanych do tego użytkownika List <edumodule> prevModules = user.edumodule.ToList(); ModuleService.SortGroupPosition(ref prevModules); // ustalenie pozycji aktualnego modułu na liście obejrzanych modułów int idx = prevModules.FindIndex(mod => mod.id == currentModuleId); if (idx > 0) { return new ModuleAndDistractorDTO() { module = _moduleService.GetDTOWithQuestions(prevModules[idx - 1], userId), distractor = newDistractor == null ? null : DistractorMapper.GetDTO(newDistractor) } } ; return(null); }
// --------------------------------------------------------------------------------------------- public int GetRecentResults(int userId) { // Assumptions: // 1.the app serves consequent modules in pre-planned order // 2.user will not get next module until they answer current module's test // // This way latest modules are also the ones answered most recently, therefore // counting correct answers backwards from the last answered will give picture // of the most recent results of the user in their tests. // pobranie parametrów sterujących obliczeniem średnich wyników var nLastAnswersStr = ConfigurationManager.AppSettings["nLastAnswersForDiffTreshold"]; var nLastAnswers = Int32.Parse(nLastAnswersStr); // pobranie i posortowanie modułów użytkownika var modulesOfUser = _userService.GetUserEntity(userId).edumodule.ToList(); ModuleService.SortGroupPosition(ref modulesOfUser); // pobieranie odpowiedzi do modułów zaczynając od końca // dopóki nie zostanie osiągnięta wymagana liczba pytań // i obliczanie średniej trafności pierwszej odpowiedzi na pytanie int nAnswers = 0; int nGoodAnswers = 0; int i = modulesOfUser.Count(); user_question user_question; while (i > 0 && nAnswers < nLastAnswers) { i--; foreach (var q in modulesOfUser[i].test_question.ToList()) { nAnswers++; user_question = q.user_question.FirstOrDefault(); if (user_question != null) { nGoodAnswers += (user_question.first_result == true) ? 1 : 0; } } } // Jeżeli użytkownik nie odpowiedział jeszcze na wymaganą tu liczbę pytań - metoda zwraca -1 // i wynik jest pomijany przy decyzji o poziomie trudności kolejnego modułu. if (nAnswers < nLastAnswers) { return(-1); } // Użytkownik odpowiedział na wystarczającą liczbe pytań. else { return((nGoodAnswers / nAnswers) * 100); } }
// --------------------------------------------------------------------------------------------- /* Pobranie następnego modułu o wymaganym poziomie trudności (ten sam | up | down). * Jeżeli nie da się zmienić poziomu w żądanym kierunku - na tym samym poziomie. * Jeżeli to ostatni moduł materiału - zwraca null. */ private edumodule PickNextModule(int lastModuleId, ChangeDifficulty change, int userId) { edumodule newModule = null; edumodule lastModule = _moduleRepository.Get(lastModuleId); // ustalenie aktualnego poziomu trudności var difficultyNow = lastModule.difficulty; // ustalenie czy można poziom zmienić bool noWayUp = (change == ChangeDifficulty.UP && difficultyNow == "hard"); bool noWayDown = (change == ChangeDifficulty.DOWN && difficultyNow == "easy"); if (noWayUp || noWayDown) { change = ChangeDifficulty.NO_CHANGE; } // TODO: uporządkować przypadek parent == null - nie może występować // pobranie rodzeństwa bieżącego modułu int?parentId = lastModule.parent; var siblings = _moduleService.SelectChildren(parentId); // wykluczenie modułów nie przypisanych do żadnego nadrzędnego, // które powinny mieć rodzica (czyli na poziomie niższym niz "hard") siblings = siblings.Where(s => (s.parent != null || s.difficulty == "hard")).ToList(); ModuleService.SortGroupPosition(ref siblings); // ustalenie czy to ostatnie dziecko int idxChild = siblings.FindIndex(mod => mod.id == lastModuleId); bool lastChild = (idxChild == siblings.Count() - 1); // NIE ZMIENIAMY POZIOMU TRUDNOŚCI if (change == ChangeDifficulty.NO_CHANGE) { // to jeszcze nie ostatnie dziecko - podanie następnego brata if (!lastChild) { newModule = siblings[idxChild + 1]; } // TODO: wyeliminować przypadek gdy nie mamy id rodzica else if (parentId == null || parentId == 0) { newModule = null; } // to ostatnie dziecko - podanie pierwszego kuzyna else { newModule = PickNextModule(parentId ?? 0, ChangeDifficulty.DOWN, userId); } } // OBNIŻENIE POZIOMU TRUDNOŚCI - podanie pierwszego dziecka najbliższego brata else if (change == ChangeDifficulty.DOWN) { // to jeszcze nie ostatnie dziecko - podanie pierwszego dziecka następnego brata if (!lastChild) { var brother = siblings[idxChild + 1]; newModule = _moduleService.SelectChildren(brother.id)[0]; } // nie ma więcej modułów - ten był ostatni else if (lastModule.difficulty == "hard" || parentId == null || parentId == 0) { newModule = null; } // pobranie dziecka najbliższego kuzyna else { var cousin = PickNextModule(parentId ?? 0, ChangeDifficulty.DOWN, userId); newModule = (cousin == null) ? null : _moduleService.SelectChildren(cousin.id)[0]; } } // PODNIESIENIE POZIOMU TRUDNOŚCI - podanie kolejnego modułu w wersji trudniejszej else { // to nie jest ostatnie dziecko - podanie następnego brata bez zmiany trudności if (!lastChild) { newModule = siblings[idxChild + 1]; } // moduł bez rodzica - nie można podnieśc poziomu trudności else if (parentId == null || parentId == 0) { newModule = null; } // to jest ostatnie dziecko - podanie następnego trudniejszego else { newModule = PickNextModule(parentId ?? 0, ChangeDifficulty.NO_CHANGE, userId); } } if (newModule != null) { _logger.Info("User: "******"|" + "Picked " + newModule.title + " as next module"); } else { _logger.Info("User: "******"|" + "No new module picked"); } return(newModule); }
// --------------------------------------------------------------------------------------------- public ModuleAndDistractorDTO NextModule(int userId, int currentModuleId, List <Pad> lastEmoStates) { edumodule newModule; distractor newDistractor = null; user user = _userService.GetUserEntity(userId); // pobranie listy modułów dotychczas wysłanych do tego użytkownika List <edumodule> prevModules = user.edumodule.ToList(); ModuleService.SortGroupPosition(ref prevModules); // jeśli kolejny moduł będzie wysłany po raz pierwszy - zostanie // dopisany do modułów tego użytkownika var addToUserModules = true; // To jest PIERWSZY moduł pobierany przez tego użytkownika if (prevModules.Count() == 0) { newModule = _moduleRepository.Get(1); } // To już nie pierwszy lecz KOLEJNY moduł else { var difficultyAndDistractor = PickNextDiffAndDistract(userId, lastEmoStates); // ustalenie pozycji aktualnego modułu na liście obejrzanych modułów int idx = prevModules.FindIndex(mod => mod.id == currentModuleId); // aktualnie użytkownik ogląda któryś z wczesniej pobranych // => pobranie następnego, który oglądał po aktualnym if (idx < prevModules.Count() - 1 && idx > -1) { newModule = prevModules[idx + 1]; addToUserModules = false; } // aktualnie użytkownik ogląda ostatni z pobranych => // dostosowanie trudności do stanu emocjonalnego i dotychczasowych wyników użytkownika else { var nextDifficulty = difficultyAndDistractor.Item1; newModule = PickNextModule(currentModuleId, nextDifficulty, userId); } // pobranie następnego dystraktora (distractorService sprawdzi czy już można) var nextDistractorType = difficultyAndDistractor.Item2; newDistractor = _distractorService.NextDistractor(userId, nextDistractorType); } // zapisanie kolejnego modułu na liście wysłanych użytkownikowi // oraz zapamiętanie nowego ostatniego modułu użytkownika if (addToUserModules && newModule != null) { user.edumodule.Add(newModule); user.last_module = newModule.id; _userService.SaveChanges(); } return(new ModuleAndDistractorDTO() { module = newModule == null ? null : _moduleService.GetDTOWithQuestions(newModule, userId), distractor = newDistractor == null ? null : DistractorMapper.GetDTO(newDistractor) }); }