Пример #1
0
        public QuestionPackData CreateAlphabetQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            ConfigAI.AppendToTeacherReport("New Question Pack");

            // Fully ordered alphabet, only 1 pack
            var alphabetLetters = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetAllLetters(parameters.letterFilters),
                new SelectionParameters(parameters.correctSeverity, getMaxData: true, useJourney: parameters.useJourneyForCorrect)
                );

            alphabetLetters.Sort((x, y) =>
            {
                return(x.Number - y.Number);
            }
                                 );

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "Letters: " + alphabetLetters.Count;
                foreach (var l in alphabetLetters)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.CreateFromCorrect(null, alphabetLetters));
        }
Пример #2
0
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            // Ordered words
            var words = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetWordsByCategory(category, parameters.wordFilters),
                new SelectionParameters(parameters.correctSeverity, getMaxData: true, useJourney: parameters.useJourneyForCorrect)
                );

            // sort by id
            words.Sort((x, y) =>
            {
                return(x.Id.CompareTo(y.Id));
            }
                       );
            if (skipWordZero)
            {
                words.RemoveAt(0);
            }

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "Words: " + words.Count;
                foreach (var w in words)
                {
                    debugString += " " + w;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.CreateFromCorrect(null, words));
        }
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            // First, get all letters (only base letters, tho, due to forced letter filters)
            int nBaseLettersRequired = 1;

            if (letterAlterationFilters.differentBaseLetters)
            {
                nBaseLettersRequired = nCorrect + nWrong;
            }
            var chosenLetters = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetAllLetters(parameters.letterFilters),
                new SelectionParameters(parameters.correctSeverity, nRequired: nBaseLettersRequired, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs)
                );
            var baseLetters = chosenLetters;

            // Then, find all the different variations and add them to a pool
            var letterPool = vocabularyHelper.GetAllLetterAlterations(baseLetters, letterAlterationFilters);

            // Choose randomly from that pool
            var correctAnswers = letterPool.RandomSelect(nCorrect);
            var wrongAnswers   = letterPool;

            foreach (LetterData data in correctAnswers)
            {
                wrongAnswers.Remove(data);
            }

            if (avoidWrongLettersWithSameSound)
            {
                wrongAnswers.RemoveAll(wrongLetter => correctAnswers.Any(correctLetter => correctLetter.PhonemeSound.Equals(wrongLetter.PhonemeSound)));
            }

            wrongAnswers = wrongAnswers.RandomSelect(Mathf.Min(nWrong, wrongAnswers.Count));

            var question = correctAnswers[0];

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + question;
                debugString += "\nCorrect Answers: " + correctAnswers.Count;
                foreach (var l in correctAnswers)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Answers: " + wrongAnswers.Count;
                foreach (var l in wrongAnswers)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctAnswers, wrongAnswers));
        }
        public List <QuestionPackData> CreateAllQuestionPacks()
        {
            var packs            = new List <QuestionPackData>();
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            var db      = AppManager.I.DB;
            var choice1 = db.GetWordDataById("the_sun");
            var choice2 = db.GetWordDataById("the_moon");

            var wordsWithArticle = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetWordsByArticle(Database.WordDataArticle.Determinative, parameters.wordFilters),
                new SelectionParameters(parameters.correctSeverity, nPacks, useJourney: parameters.useJourneyForCorrect)
                );

            foreach (var wordWithArticle in wordsWithArticle)
            {
                int articleLength      = 2;
                var letterAfterArticle = vocabularyHelper.GetLettersInWord(wordWithArticle)[articleLength];
                var correctWords       = new List <Database.WordData>();
                var wrongWords         = new List <Database.WordData>();

                switch (letterAfterArticle.SunMoon)
                {
                case Database.LetterDataSunMoon.Sun:
                    correctWords.Add(choice1);
                    wrongWords.Add(choice2);
                    break;

                case Database.LetterDataSunMoon.Moon:
                    correctWords.Add(choice2);
                    wrongWords.Add(choice1);
                    break;
                }

                // Debug
                if (ConfigAI.VerboseQuestionPacks)
                {
                    string debugString = "--------- TEACHER: question pack result ---------";
                    debugString += "\nQuestion: " + wordWithArticle;
                    debugString += "\nCorrect Word: " + correctWords.Count;
                    foreach (var l in correctWords)
                    {
                        debugString += " " + l;
                    }
                    debugString += "\nWrong Word: " + wrongWords.Count;
                    foreach (var l in wrongWords)
                    {
                        debugString += " " + l;
                    }
                    ConfigAI.AppendToTeacherReport(debugString);
                }

                var pack = QuestionPackData.Create(wordWithArticle, correctWords, wrongWords);
                packs.Add(pack);
            }

            return(packs);
        }
Пример #5
0
        public List <IQuestionPack> GenerateQuestionPacks(IQuestionBuilder questionBuilder)
        {
            // Safety fallback, used for release to avoid crashing the application.
            // @note: This WILL block the game if an error happens EVERYTIME, so make sure that never happens!
            List <QuestionPackData> questionPackDataList = null;
            int safetyCounter = 10;

            while (true)
            {
                try
                {
                    // Generate packs
                    questionPackDataList = questionBuilder.CreateAllQuestionPacks();
                    break;
                }
                catch (System.Exception e)
                {
                    if (!ConfigAI.TeacherSafetyFallbackEnabled)
                    {
                        throw e;
                    }
                    else
                    {
                        safetyCounter--;
                        UnityEngine.Debug.LogError("Teacher fallback triggered (" + safetyCounter + "): " + e.ToString());
                        ConfigAI.PrintTeacherReport(logOnly: true);

                        if (safetyCounter <= 0)
                        {
                            break;
                        }
                    }
                }
            }

            // Apply ordering
            if (questionBuilder.Parameters != null && questionBuilder.Parameters.sortPacksByDifficulty)
            {
                QuestionBuilderHelper.SortPacksByDifficulty(questionPackDataList);
            }

            // Fix blatant repetitions
            if (questionPackDataList.Count > 2)
            {
                FixRepetitions(questionPackDataList);
            }

            ConfigAI.ReportPacks(questionPackDataList);

            var questionPackList = ConvertQuestionPackDataToQuestionPack(questionPackDataList);

            return(questionPackList);
        }
Пример #6
0
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            // Get a question phrase at random
            int nToUse           = 1;
            var selectionParams1 = new SelectionParameters(parameters.correctSeverity, nToUse, useJourney: parameters.useJourneyForCorrect,
                                                           packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs);

            selectionParams1.AssignJourney(parameters.insideJourney);
            var usablePhrases = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetPhrasesByCategory(Database.PhraseDataCategory.Question, parameters.wordFilters, parameters.phraseFilters), selectionParams1);
            var question = usablePhrases[0];

            // Get the linked reply phrase
            var reply = vocabularyHelper.GetLinkedPhraseOf(question);

            var correctAnswers = new List <Database.PhraseData>();

            correctAnswers.Add(reply);

            // Get random wrong phrases
            var selectionParams2 = new SelectionParameters(parameters.correctSeverity, nWrong,
                                                           useJourney: parameters.useJourneyForWrong,
                                                           packListHistory: PackListHistory.NoFilter,
                                                           journeyFilter: SelectionParameters.JourneyFilter.CurrentJourney);

            selectionParams2.AssignJourney(parameters.insideJourney);

            var wrongPhrases = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetPhrasesNotIn(parameters.wordFilters, parameters.phraseFilters, question, reply), selectionParams2);

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + question;
                debugString += "\nCorrect Answers: " + correctAnswers.Count;
                foreach (var l in correctAnswers)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Answers: " + wrongPhrases.Count;
                foreach (var l in wrongPhrases)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctAnswers, wrongPhrases));
        }
Пример #7
0
        private List <MiniGameData> selectMiniGames(int nMinigamesToSelect)
        {
            List <MiniGameData> newPlaySessionMiniGames = selectMiniGamesForCurrentPlaySession(nMinigamesToSelect);

            if (ConfigAI.VerboseTeacher)
            {
                var debugString = "";
                debugString += ConfigAI.FormatTeacherReportHeader("Minigames Selected");
                foreach (var minigame in newPlaySessionMiniGames)
                {
                    debugString += "\n" + minigame.Code;
                }
                Debug.Log(debugString);
            }

            return(newPlaySessionMiniGames);
        }
Пример #8
0
        private QuestionPackData CreateSingleQuestionPackData(LetterData letter, LetterForm correctForm)
        {
            var teacher = AppManager.I.Teacher;

            // Find a word with the letter in that form
            var usableWords = teacher.VocabularyAi.SelectData(
                () => FindEligibleWords(maximumWordLength, letter, correctForm),
                new SelectionParameters(parameters.correctSeverity, 1, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_words)
                );
            var question = usableWords[0];

            // Place the correct letter and form
            var correctAnswers = new List <LetterData>();
            var letterWithForm = AppManager.I.VocabularyHelper.ConvertToLetterWithForcedForm(letter, correctForm);

            correctAnswers.Add(letterWithForm);

            // Place the other forms as wrong forms
            var wrongAnswers = new List <LetterData>();

            foreach (var wrongForm in letter.GetAvailableForms())
            {
                if (wrongForm == correctForm)
                {
                    continue;
                }
                letterWithForm = AppManager.I.VocabularyHelper.ConvertToLetterWithForcedForm(letter, wrongForm);
                wrongAnswers.Add(letterWithForm);
            }

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + question;
                debugString += "\nCorrect Answers: " + correctAnswers.Count;
                foreach (var l in correctAnswers)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctAnswers, wrongAnswers));
        }
Пример #9
0
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            var selectionParams1 = new SelectionParameters(parameters.correctSeverity, nCorrect,
                                                           useJourney: parameters.useJourneyForCorrect,
                                                           packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs);

            selectionParams1.AssignJourney(parameters.insideJourney);
            var correctLetters = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetAllLetters(parameters.letterFilters), selectionParams1);

            var selectionParams2 = new SelectionParameters(parameters.wrongSeverity, nWrong,
                                                           useJourney: parameters.useJourneyForWrong,
                                                           packListHistory: PackListHistory.NoFilter);

            selectionParams2.AssignJourney(parameters.insideJourney);
            var wrongLetters = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetLettersNotIn(LetterEqualityStrictness.Letter, parameters.letterFilters, correctLetters.ToArray()),
                selectionParams2
                );

            var question = firstCorrectIsQuestion ? correctLetters[0] : null;

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nCorrect Letters: " + correctLetters.Count;
                foreach (var l in correctLetters)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Letters: " + wrongLetters.Count;
                foreach (var l in wrongLetters)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctLetters, wrongLetters));
        }
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            var correctWords = teacher.VocabularyAi.SelectData(
                () => words_cache,
                new SelectionParameters(parameters.correctSeverity, nCorrect, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs)
                );


            wrongWords_cache.Clear();
            wrongWords_cache.AddRange(vocabularyHelper.GetWordsNotInOptimized(parameters.wordFilters, correctWords));
            var wrongWords = teacher.VocabularyAi.SelectData(
                () => wrongWords_cache,
                new SelectionParameters(parameters.wrongSeverity, nWrong, useJourney: parameters.useJourneyForWrong,
                                        packListHistory: PackListHistory.NoFilter,
                                        journeyFilter: SelectionParameters.JourneyFilter.CurrentJourney)
                );

            var question = firstCorrectIsQuestion ? correctWords[0] : null;

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nCorrect Words: " + correctWords.Count;
                foreach (var l in correctWords)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Words: " + wrongWords.Count;
                foreach (var l in wrongWords)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctWords, wrongWords));
        }
Пример #11
0
        public void LoadCurrentPlaySessionData(string currentPlaySessionId)
        {
            var pos = new JourneyPosition(currentPlaySessionId);

            currentJourneyContents       = progressionContents.GetContentsUpToPlaySession(pos);
            currentPlaySessionContents   = progressionContents.GetContentsOfPlaySession(pos);
            currentLearningBlockContents = progressionContents.GetContentsOfLearningBlock(pos);
            currentStageContents         = progressionContents.GetContentsOfStage(pos);

            if (ConfigAI.VerbosePlaySessionInitialisation)
            {
                string debugString = "";
                debugString += ConfigAI.FormatTeacherReportHeader("Play Session Initalisation (" + currentPlaySessionId + ")");
                debugString += "\n Current PS:\n" + currentPlaySessionContents;
                debugString += "\n Current LB:\n" + currentLearningBlockContents;
                debugString += "\n Current ST:\n" + currentStageContents;
                debugString += "\n Current journey:\n" + currentJourneyContents;
                debugString += "\n Whole contents:\n" + progressionContents.AllContents;
                ConfigAI.AppendToTeacherReport(debugString);
            }
        }
Пример #12
0
        private QuestionPackData CreateSingleQuestionPackData(WordDataCategory dataCategory)
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            // Ordered words
            var selectionParams1 = new SelectionParameters(parameters.correctSeverity, getMaxData: true,
                                                           useJourney: parameters.useJourneyForCorrect);

            selectionParams1.AssignJourney(parameters.insideJourney);
            parameters.wordFilters.allowedCategories = new[] { dataCategory };
            var words = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetAllWords(parameters.wordFilters),
                selectionParams1
                );

            // sort by id
            words.Sort((x, y) => int.Parse(x.SortValue) - int.Parse(y.SortValue));
            if (skipWordZero)
            {
                words.RemoveAt(0);
            }

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "Words: " + words.Count;
                foreach (var w in words)
                {
                    debugString += " " + w;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            if (maxAnswers > 0)
            {
                words = words.GetRange(0, Mathf.Min(words.Count, maxAnswers));
            }

            return(QuestionPackData.CreateFromCorrect(null, words));
        }
Пример #13
0
        private List <T> WeightedDataSelect <T>(List <T> source_data_list, int nToSelect, SelectionSeverity severity) where T : IData
        {
            VocabularyDataType dataType = VocabularyDataType.Letter;

            if (typeof(T) == typeof(LetterData))
            {
                dataType = VocabularyDataType.Letter;
            }
            else if (typeof(T) == typeof(WordData))
            {
                dataType = VocabularyDataType.Word;
            }
            else if (typeof(T) == typeof(PhraseData))
            {
                dataType = VocabularyDataType.Phrase;
            }

            // Given a (filtered) list of data, select some using weights
            var score_data_list = dbManager.Query <VocabularyScoreData>("SELECT * FROM " + typeof(VocabularyScoreData).Name + " WHERE VocabularyDataType = '" + (int)dataType + "'");

            if (ConfigAI.VerboseDataSelection)
            {
                weightedData_debugString += ConfigAI.FormatTeacherReportHeader("Selection Weights");
                weightedData_debugString  = "";
            }

            var weights_list = new List <float>();

            foreach (var sourceData in source_data_list)
            {
                float cumulativeWeight = 0;
                if (ConfigAI.VerboseDataSelection)
                {
                    weightedData_debugString += "\n" + sourceData.GetId() + " ---";
                }


                // Get score data
                var   score_data         = score_data_list.Find(x => x.ElementId == sourceData.GetId());
                float currentScore       = 0;
                int   daysSinceLastScore = 0;
                if (score_data != null)
                {
                    var timespanFromLastScoreToNow = GenericHelper.GetTimeSpanBetween(score_data.UpdateTimestamp, GenericHelper.GetTimestampForNow());
                    daysSinceLastScore = timespanFromLastScoreToNow.Days;
                    currentScore       = score_data.Score;
                }

                //UnityEngine.Debug.Log("Data " + id + " score: " + currentScore + " days " + daysSinceLastScore);

                // Score Weight [0,1]: higher the lower the score [-1,1] is
                var scoreWeight = 0.5f * (1 - currentScore);
                cumulativeWeight += scoreWeight * ConfigAI.Vocabulary_Score_Weight;
                if (ConfigAI.VerboseDataSelection)
                {
                    weightedData_debugString += " \tScore: " + scoreWeight * ConfigAI.Vocabulary_Score_Weight + "(" + scoreWeight + ")";
                }

                // RecentPlay Weight  [1,0]: higher the more in the past we saw that data
                const float dayLinerWeightDecrease = 1f / ConfigAI.DaysForMaximumRecentPlayMalus;
                float       weightMalus            = daysSinceLastScore * dayLinerWeightDecrease;
                float       recentPlayWeight       = 1f - UnityEngine.Mathf.Min(1, weightMalus);
                cumulativeWeight += recentPlayWeight * ConfigAI.Vocabulary_RecentPlay_Weight;
                if (ConfigAI.VerboseDataSelection)
                {
                    weightedData_debugString += " \tRecent: " + recentPlayWeight * ConfigAI.Vocabulary_RecentPlay_Weight + "(" + recentPlayWeight + ")";
                }

                // Current focus weight [1,0]: higher if the data is part of the current play session / learning block / stage
                float currentPlaySessionWeight = 0;
                if (currentPlaySessionContents.Contains(sourceData))
                {
                    currentPlaySessionWeight = 1;
                }
                else if (currentLearningBlockContents.Contains(sourceData))
                {
                    currentPlaySessionWeight = 0.5f;
                }
                else if (currentStageContents.Contains(sourceData))
                {
                    currentPlaySessionWeight = 0.2f;
                }
                cumulativeWeight += currentPlaySessionWeight * ConfigAI.Vocabulary_CurrentPlaySession_Weight;
                if (ConfigAI.VerboseDataSelection)
                {
                    weightedData_debugString += " \tFocus: " + currentPlaySessionWeight * ConfigAI.Vocabulary_CurrentPlaySession_Weight + "(" + currentPlaySessionWeight + ")";
                }

                // If the cumulative weight goes to the negatives, we give it a fixed weight
                // TODO check if we shound use if (cumulativeWeight <= ConfigAI.Vocabulary_MinTotal_Weight)
                // TODO check the "continue" because it wont' save the data
                if (cumulativeWeight <= 0)
                {
                    cumulativeWeight = ConfigAI.Vocabulary_MinTotal_Weight;
                    continue;
                }

                // Save cumulative weight
                weights_list.Add(cumulativeWeight);
                if (ConfigAI.VerboseDataSelection)
                {
                    weightedData_debugString += " TOTw: " + cumulativeWeight;
                }
            }

            //return source_data_list;

            if (ConfigAI.VerboseDataSelection)
            {
                ConfigAI.AppendToTeacherReport(weightedData_debugString);
            }

            // Select data from the list
            var selected_data_list = new List <T>();

            if (source_data_list.Count > 0)
            {
                int      nToSelectFromCurrentList = 0;
                List <T> chosenData = null;
                switch (severity)
                {
                case SelectionSeverity.AsManyAsPossible:
                case SelectionSeverity.AllRequired:
                    nToSelectFromCurrentList = UnityEngine.Mathf.Min(source_data_list.Count, nToSelect);
                    chosenData = RandomHelper.RouletteSelectNonRepeating(source_data_list, weights_list, nToSelectFromCurrentList);
                    selected_data_list.AddRange(chosenData);
                    break;

                case SelectionSeverity.MayRepeatIfNotEnough:
                    int nRemainingToSelect = nToSelect;
                    while (nRemainingToSelect > 0)
                    {
                        var listCopy = new List <T>(source_data_list);
                        nToSelectFromCurrentList = UnityEngine.Mathf.Min(source_data_list.Count, nRemainingToSelect);
                        chosenData = RandomHelper.RouletteSelectNonRepeating(listCopy, weights_list, nToSelectFromCurrentList);
                        selected_data_list.AddRange(chosenData);
                        nRemainingToSelect -= nToSelectFromCurrentList;
                    }
                    break;
                }
            }
            return(selected_data_list);
        }
Пример #14
0
        private QuestionPackData CreateSingleQuestionPackData(int inRoundPackIndex, HashSet <LetterData> availableLettersWithForms)
        {
            var teacher = AppManager.I.Teacher;

            /*bool useJourneyForLetters = parameters.useJourneyForCorrect;
             * // @note: we also force the journey if the packs must be used together, as the data filters for journey clash with the new filter
             * if (packsUsedTogether)
             * {
             *  useJourneyForLetters = false;
             * }*/

            int SAFE_COUNT = 0;

            while (true)
            {
                var commonLetter = availableLettersWithForms.ToList().RandomSelectOne();

                var correctLetters = new List <LetterData>();
                correctLetters.Add(commonLetter);
                availableLettersWithForms.Remove(commonLetter);
                currentRound_letters.Add(commonLetter);
                //Debug.Log(availableLettersWithForms.ToDebugStringNewline());

                // Find words with that letter
                // Check if it has enough words
                var selectionParams2 =
                    new SelectionParameters(SelectionSeverity.AllRequired, nCorrect,
                                            useJourney: parameters.useJourneyForCorrect,
                                            packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_words);
                selectionParams2.AssignJourney(parameters.insideJourney);
                List <WordData> wordsWithCommonLetter = null;
                try {
                    wordsWithCommonLetter = teacher.VocabularyAi.SelectData(
                        () => FindWordsWithCommonLetter(commonLetter), selectionParams2);
                } catch (Exception) {
                    //Debug.LogWarning(e);
                    SAFE_COUNT++;
                    if (SAFE_COUNT == 100)
                    {
                        throw new Exception("Could not find enough data for WordsWithLetter");
                    }
                    continue;
                }
                var correctWords = wordsWithCommonLetter;
                currentRound_words.AddRange(correctWords);

                // Get words without the letter (only for the first pack of a round)
                var wrongWords = new List <WordData>();
                if (inRoundPackIndex == 0)
                {
                    var selectionParams3 =
                        new SelectionParameters(parameters.wrongSeverity, nWrong,
                                                useJourney: parameters.useJourneyForWrong,
                                                packListHistory: PackListHistory.NoFilter,
                                                journeyFilter: parameters.JourneyFilter);
                    selectionParams3.AssignJourney(parameters.insideJourney);

                    wrongWords = teacher.VocabularyAi.SelectData(
                        () => FindWrongWords(correctWords), selectionParams3);
                    currentRound_words.AddRange(wrongWords);
                }


                /*
                 * // Get a letter
                 * var usableLetters = teacher.VocabularyAi.SelectData(
                 * () => FindLettersThatAppearInWords(atLeastNWords: nCorrect),
                 * new SelectionParameters(parameters.correctSeverity, 1, useJourney: useJourneyForLetters,
                 *      packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_letters));
                 * var commonLetter = usableLetters[0];
                 * currentRound_letters.Add(commonLetter);
                 */
                /*
                 *  // Get words with the letter
                 *  // (but without the previous letters)
                 *  var correctWords = teacher.VocabularyAi.SelectData(
                 *      () => FindWordsWithCommonLetter(commonLetter),
                 *      new SelectionParameters(parameters.correctSeverity, nCorrect,
                 *          useJourney: parameters.useJourneyForCorrect,
                 *          packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_words));
                 *  currentRound_words.AddRange(correctWords);
                 *
                 *  // Get words without the letter (only for the first pack of a round)
                 *  var wrongWords = new List<WordData>();
                 *  if (inRoundPackIndex == 0)
                 *  {
                 *      wrongWords = teacher.VocabularyAi.SelectData(
                 *          () => FindWrongWords(correctWords),
                 *          new SelectionParameters(parameters.wrongSeverity, nWrong,
                 *              useJourney: parameters.useJourneyForWrong,
                 *              packListHistory: PackListHistory.NoFilter,
                 *              journeyFilter: SelectionParameters.JourneyFilter.CurrentJourney));
                 *      currentRound_words.AddRange(wrongWords);
                 *  }
                 */
                var pack = QuestionPackData.Create(commonLetter, correctWords, wrongWords);

                if (ConfigAI.VerboseQuestionPacks)
                {
                    string debugString = "--------- TEACHER: question pack result ---------";
                    debugString += "\nQuestion: " + commonLetter;
                    debugString += "\nCorrect Answers: " + correctWords.Count;
                    foreach (var l in correctWords)
                    {
                        debugString += " " + l;
                    }
                    debugString += "\nWrong Answers: " + wrongWords.Count;
                    foreach (var l in wrongWords)
                    {
                        debugString += " " + l;
                    }
                    ConfigAI.AppendToTeacherReport(debugString);
                }

                return(pack);
            }
        }
Пример #15
0
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            parameters.wordFilters.allowedCategories = null; // Reset forced category

            // Get a phrase
            int nToUse           = 1;
            var selectionParams1 =
                new SelectionParameters(parameters.correctSeverity, nToUse, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs);

            selectionParams1.AssignJourney(parameters.insideJourney);
            var usablePhrases = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetAllPhrases(
                    parameters.wordFilters,
                    parameters.phraseFilters), selectionParams1);
            var question = usablePhrases.RandomSelectOne();

            // Get words related to the phrase
            var             correctWords = new List <WordData>();
            List <WordData> relatedWords = new List <WordData>();

            var phraseWords = vocabularyHelper.GetWordsInPhrase(question, parameters.wordFilters);

            relatedWords.AddRange(phraseWords);

            if (usePhraseAnswersIfFound && question.Answers.Length > 0)
            {
                var answerWords = vocabularyHelper.GetAnswersToPhrase(question, parameters.wordFilters);
                correctWords.AddRange(answerWords);
                relatedWords.AddRange(answerWords);
            }
            else
            {
                correctWords.AddRange(phraseWords);
            }

            // Choose the word/s we want to use
            if (!useAllCorrectWords)
            {
                correctWords = correctWords.RandomSelect(nCorrect);
            }

            // Get wrong words from the same category of the correct one
            parameters.wordFilters.allowedCategories = new[] { correctWords[0].Category };
            var selectionParams2 =
                new SelectionParameters(parameters.correctSeverity, nWrong, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: PackListHistory.NoFilter,
                                        journeyFilter: parameters.JourneyFilter);
            var wrongWords = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetWordsNotIn(parameters.wordFilters, relatedWords.ToArray()),
                selectionParams2
                );

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + question;
                debugString += "\nCorrect Answers: " + correctWords.Count;
                foreach (var l in correctWords)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Answers: " + wrongWords.Count;
                foreach (var l in wrongWords)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctWords, wrongWords));
        }
        private QuestionPackData CreateSingleQuestionPackData(HashSet <LetterData> availableLettersWithForms)
        {
            QuestionPackData pack = null;
            var teacher           = AppManager.I.Teacher;

            int SAFE_COUNT = 0;

            while (true)
            {
                var commonLetter = availableLettersWithForms.ToList().RandomSelectOne();

                var correctLetters = new List <LetterData>();
                correctLetters.Add(commonLetter);
                availableLettersWithForms.Remove(commonLetter);
                //Debug.Log("Test " + SAFE_COUNT + ": Trying letter " + commonLetter);

                // Check if it has enough words
                List <WordData> wordsWithCommonLetter = null;
                try {
                    wordsWithCommonLetter = teacher.VocabularyAi.SelectData(
                        () => FindWordsWithCommonLetter(commonLetter),
                        new SelectionParameters(SelectionSeverity.AllRequired, nWords,
                                                useJourney: parameters.useJourneyForCorrect,
                                                packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_words));
                } catch (Exception) {
                    SAFE_COUNT++;
                    if (SAFE_COUNT == 100)
                    {
                        throw new Exception("Could not find enough data for CommonLettersInWord");
                    }
                    continue;
                }
                //Debug.Log("Found letter " + commonLetter + " at trial count: " + SAFE_COUNT);

                var lettersNotInCommon = teacher.VocabularyAi.SelectData(
                    () => FindLettersNotInCommon(wordsWithCommonLetter),
                    new SelectionParameters(parameters.wrongSeverity, nWrong, useJourney: parameters.useJourneyForWrong,
                                            journeyFilter: SelectionParameters.JourneyFilter.CurrentJourney,
                                            getMaxData: true                  // needed to skip priority filtering, which will filter out forms!
                                            ));
                lettersNotInCommon = lettersNotInCommon.RandomSelect(nWrong); // needed to skip priority filtering, which will filter out forms!

                pack = QuestionPackData.Create(wordsWithCommonLetter, correctLetters, lettersNotInCommon);

                if (ConfigAI.VerboseQuestionPacks)
                {
                    string debugString = "--------- TEACHER: question pack result ---------";
                    debugString += "\nQuestion: " + wordsWithCommonLetter.ToDebugString();
                    debugString += "\nCorrect Answers: " + correctLetters.Count;
                    foreach (var l in correctLetters)
                    {
                        debugString += " " + l;
                    }
                    debugString += "\nWrong Answers: " + lettersNotInCommon.Count;
                    foreach (var l in lettersNotInCommon)
                    {
                        debugString += " " + l;
                    }
                    ConfigAI.AppendToTeacherReport(debugString);
                }
                return(pack);
            }
        }
Пример #17
0
        private QuestionPackData CreateSingleQuestionPackData(int inRoundPackIndex)
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            // Choose a single eligible word
            var usableWords = teacher.VocabularyAi.SelectData(
                () => FindEligibleWords(maxWordLength: maximumWordLength),
                new SelectionParameters(parameters.correctSeverity, 1, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_words)
                );
            var wordQuestion = usableWords[0];

            currentRound_words.Add(wordQuestion);
            //UnityEngine.Debug.LogWarning("Chosen word: " + question);

            // Get letters of that word
            var wordLetters = vocabularyHelper.GetLettersInWord(wordQuestion);
            //UnityEngine.Debug.LogWarning("Found letters: " + wordLetters.ToArray().ToDebugString());

            bool useJourneyForLetters = parameters.useJourneyForCorrect;

            // @note: we force journey in this case to be off so that all letters can be found
            // @note: we also force the journey if the packs must be used together, as the data filters for journey clash with the new filter
            if (useAllCorrectLetters || packsUsedTogether)
            {
                useJourneyForLetters = false;
            }

            // Get some letters (from that word)
            var correctLetters = teacher.VocabularyAi.SelectData(
                () => FindCorrectLetters(wordQuestion, wordLetters),
                new SelectionParameters(parameters.correctSeverity, nCorrect, getMaxData: useAllCorrectLetters,
                                        useJourney: useJourneyForLetters, filteringIds: previousPacksIDs_letters));

            currentRound_letters.AddRange(correctLetters);

            // Get some wrong letters (not from that word, nor other words, nor previous letters)
            // Only for the first pack of the round
            var wrongLetters = new List <LetterData>();

            if (inRoundPackIndex == 0)
            {
                wrongLetters = teacher.VocabularyAi.SelectData(
                    () => FindWrongLetters(wordQuestion, wordLetters),
                    new SelectionParameters(
                        parameters.wrongSeverity, nWrong, useJourney: parameters.useJourneyForWrong,
                        journeyFilter: SelectionParameters.JourneyFilter.CurrentJourney));
                currentRound_letters.AddRange(wrongLetters);
            }

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + wordQuestion;
                debugString += "\nCorrect Answers: " + correctLetters.Count;
                foreach (var l in correctLetters)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Answers: " + wrongLetters.Count;
                foreach (var l in wrongLetters)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(wordQuestion, correctLetters, wrongLetters));
        }
Пример #18
0
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            // Get a phrase
            int nToUse        = 1;
            var usablePhrases = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetAllPhrases(
                    parameters.wordFilters,
                    parameters.phraseFilters),
                new SelectionParameters(parameters.correctSeverity, nToUse, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs)
                );
            var question = usablePhrases[0];

            // Get words related to the phrase
            var             correctWords = new List <WordData>();
            List <WordData> relatedWords = null;

            if (usePhraseAnswersIfFound && question.Answers.Length > 0)
            {
                relatedWords = vocabularyHelper.GetAnswersToPhrase(question, parameters.wordFilters);
            }
            else
            {
                relatedWords = vocabularyHelper.GetWordsInPhrase(question, parameters.wordFilters);
            }

            correctWords.AddRange(relatedWords);

            if (!useAllCorrectWords)
            {
                correctWords = correctWords.RandomSelect(nCorrect);
            }

            var wrongWords = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetWordsNotIn(parameters.wordFilters, relatedWords.ToArray()),
                new SelectionParameters(parameters.correctSeverity, nWrong, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: PackListHistory.NoFilter,
                                        journeyFilter: SelectionParameters.JourneyFilter.CurrentJourney)
                );

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + question;
                debugString += "\nCorrect Answers: " + correctWords.Count;
                foreach (var l in correctWords)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Answers: " + wrongWords.Count;
                foreach (var l in wrongWords)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctWords, wrongWords));
        }
Пример #19
0
        private List <MiniGameData> PerformSelection_Random(PlaySessionData playSessionData, int numberToSelect)
        {
            // Get all minigames ids for the given playsession (from PlaySessionData)
            // ... also, keep the weights around
            var minigame_id_list         = new List <string>();
            var playsession_weights_dict = new Dictionary <MiniGameCode, float>();

            foreach (var minigameInPlaySession in playSessionData.Minigames)
            {
                minigame_id_list.Add(minigameInPlaySession.MiniGameCode.ToString());
                playsession_weights_dict[minigameInPlaySession.MiniGameCode] = minigameInPlaySession.Weight;
            }

            // Get all minigame data, filter by availability (from the static DB)
            var minigame_data_list = dbManager.FindMiniGameData(x => x.Active && minigame_id_list.Contains(x.GetId()));

            // Create the weights list too
            var weights_list = new List <float>(minigame_data_list.Count);

            // Retrieve the current score data (state) for each minigame (from the dynamic DB)
            var minigame_score_list = dbManager.Query <MiniGameScoreData>("SELECT * FROM " + typeof(MiniGameScoreData).Name);

            //UnityEngine.Debug.Log("M GAME SCORE LIST: " + minigame_score_list.Count);
            //foreach(var l in minigame_score_list) UnityEngine.Debug.Log(l.ElementId);

            // Determine the final weight for each minigame
            var required_minigames = new List <MiniGameData>();

            string debugString = ConfigAI.FormatTeacherReportHeader("Minigame Selection");

            foreach (var minigame_data in minigame_data_list)
            {
                float cumulativeWeight   = 0;
                var   minigame_scoredata = minigame_score_list.Find(x => x.MiniGameCode == minigame_data.Code);
                int   daysSinceLastScore = 0;
                if (minigame_scoredata != null)
                {
                    var timespanFromLastScoreToNow = GenericHelper.GetTimeSpanBetween(minigame_scoredata.UpdateTimestamp, GenericHelper.GetTimestampForNow());
                    daysSinceLastScore = timespanFromLastScoreToNow.Days;
                }
                debugString += minigame_data.Code + " --- \t";

                // PlaySession Weight [0,1]
                float playSessionWeight = playsession_weights_dict[minigame_data.Code] / 100f; //  [0-100]
                cumulativeWeight += playSessionWeight * ConfigAI.MiniGame_PlaySession_Weight;
                debugString      += " PSw: " + playSessionWeight * ConfigAI.MiniGame_PlaySession_Weight + "(" + playSessionWeight + ")";

                // Some minigames are required to appear (weight 100+)
                if (playsession_weights_dict[minigame_data.Code] >= 100)
                {
                    required_minigames.Add(minigame_data);
                    debugString += " REQUIRED!\n";
                    continue;
                }

                // RecentPlay Weight  [1,0]
                const float dayLinerWeightDecrease = 1f / ConfigAI.DaysForMaximumRecentPlayMalus;
                float       weightMalus            = daysSinceLastScore * dayLinerWeightDecrease;
                float       recentPlayWeight       = 1f - UnityEngine.Mathf.Min(1, weightMalus);
                cumulativeWeight += recentPlayWeight * ConfigAI.MiniGame_RecentPlay_Weight;
                debugString      += " RPw: " + recentPlayWeight * ConfigAI.MiniGame_RecentPlay_Weight + "(" + recentPlayWeight + ")";

                // Save cumulative weight
                weights_list.Add(cumulativeWeight);
                debugString += " TOTw: " + cumulativeWeight + "\n";
            }
            if (ConfigAI.VerboseMinigameSelection)
            {
                ConfigAI.AppendToTeacherReport(debugString);
            }

            // Number checks
            int actualNumberToSelect = UnityEngine.Mathf.Min(numberToSelect, minigame_data_list.Count);

            // Remove the required ones
            actualNumberToSelect -= required_minigames.Count;
            foreach (var requiredMinigame in required_minigames)
            {
                minigame_data_list.Remove(requiredMinigame);
            }

            if (actualNumberToSelect > 0 && minigame_data_list.Count == 0)
            {
                throw new System.Exception("Cannot find even a single minigame for play session " + playSessionData.Id);
            }

            if (actualNumberToSelect > minigame_data_list.Count)
            {
                UnityEngine.Debug.LogWarning("Could not select the requested number of " + numberToSelect + " minigames for play session " + playSessionData.Id + " (only " + minigame_data_list.Count + " are available)");
            }

            // Choose N minigames based on these weights
            var selectedMiniGameData = RandomHelper.RouletteSelectNonRepeating(minigame_data_list, weights_list, actualNumberToSelect);

            // Output
            var finalList = new List <MiniGameData>();

            finalList.AddRange(required_minigames);
            finalList.AddRange(selectedMiniGameData);

            return(finalList);
        }
        public List <QuestionPackData> CreateAllQuestionPacks()
        {
            var packs            = new List <QuestionPackData>();
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            var db      = AppManager.I.DB;
            var choice1 = db.GetWordDataById("with_article");
            var choice2 = db.GetWordDataById("without_article");

            int nPerType = nPacks / 2;

            var list_choice1 = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetWordsByArticle(Database.WordDataArticle.Determinative, parameters.wordFilters),
                new SelectionParameters(parameters.correctSeverity, nPerType, useJourney: parameters.useJourneyForCorrect)
                );

            var list_choice2 = teacher.VocabularyAi.SelectData(
                () => vocabularyHelper.GetWordsByArticle(Database.WordDataArticle.None, parameters.wordFilters),
                new SelectionParameters(parameters.wrongSeverity, nPerType, useJourney: parameters.useJourneyForCorrect)
                );

            foreach (var wordWithArticle in list_choice1)
            {
                var correctWords = new List <Database.WordData>();
                var wrongWords   = new List <Database.WordData>();
                correctWords.Add(choice1);
                wrongWords.Add(choice2);

                var pack = QuestionPackData.Create(wordWithArticle, correctWords, wrongWords);
                packs.Add(pack);
            }

            foreach (var wordWithoutArticle in list_choice2)
            {
                var correctWords = new List <Database.WordData>();
                var wrongWords   = new List <Database.WordData>();
                correctWords.Add(choice2);
                wrongWords.Add(choice1);

                var pack = QuestionPackData.Create(wordWithoutArticle, correctWords, wrongWords);
                packs.Add(pack);
            }

            // Shuffle the packs at the end
            packs.Shuffle();

            if (ConfigAI.VerboseQuestionPacks)
            {
                foreach (var pack in packs)
                {
                    string debugString = "--------- TEACHER: question pack result ---------";
                    debugString += "\nQuestion: " + pack.question;
                    debugString += "\nCorrect Word: " + pack.correctAnswers.Count;
                    foreach (var l in pack.correctAnswers)
                    {
                        debugString += " " + l;
                    }
                    debugString += "\nWrong Word: " + pack.wrongAnswers.Count;
                    foreach (var l in pack.wrongAnswers)
                    {
                        debugString += " " + l;
                    }
                    ConfigAI.AppendToTeacherReport(debugString);
                }
            }

            return(packs);
        }
        private QuestionPackData CreateSingleQuestionPackData()
        {
            var teacher          = AppManager.I.Teacher;
            var vocabularyHelper = AppManager.I.VocabularyHelper;

            //Debug.Log(FindLettersThatAppearInWords(maxWordLength: maximumWordLength).ToDebugStringNewline());

            // First, choose a letter (base only, due to filters)
            var eligibleLetters = teacher.VocabularyAi.SelectData(
                () => FindLettersThatAppearInWords(maxWordLength: maximumWordLength),
                new SelectionParameters(parameters.correctSeverity, 1, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_letters)
                );
            //Debug.Log(eligibleLetters.ToDebugStringNewline());

            // Choose one letter randomly from the eligible ones
            var chosenLetter = eligibleLetters.RandomSelectOne();
            //Debug.Log("Chosen: " + chosenLetter);

            // Find a word with the letter (strict)
            var usableWords = teacher.VocabularyAi.SelectData(
                () => FindWordsWithLetterStrict(chosenLetter, maximumWordLength),
                new SelectionParameters(parameters.correctSeverity, 1, useJourney: parameters.useJourneyForCorrect,
                                        packListHistory: parameters.correctChoicesHistory, filteringIds: previousPacksIDs_words)
                );
            var question = usableWords[0];

            // Get the correct form inside the word
            //Debug.Log("Word is: " + question.ToString());
            //Debug.Log("Letters: " + vocabularyHelper.GetLettersInWord(question).ToDebugString());
            //Debug.Log("Letters correct: " + vocabularyHelper.GetLettersInWord(question).Where(l => l.IsSameLetterAs(chosenLetter, LetterEqualityStrictness.LetterOnly)).ToDebugString());
            var chosenLetterWithForm = vocabularyHelper.GetLettersInWord(question).Where(l => l.IsSameLetterAs(chosenLetter, LetterEqualityStrictness.LetterOnly)).ToList().RandomSelectOne();
            //chosenLetterWithForm = vocabularyHelper.ExtractLettersWithForms(chosenLetterWithForm);
            //Debug.Log("Correct form: " + chosenLetterWithForm + " form is " + chosenLetterWithForm.Form);

            // Place the correct alteration in the correct list
            var correctAnswers = new List <LetterData>();

            correctAnswers.Add(chosenLetterWithForm);

            // Place some alterations in the wrong list
            List <LetterData> baseLetters;

            if (letterAlterationFilters.differentBaseLetters)
            {
                baseLetters = AppManager.I.VocabularyHelper.GetAllLetters(parameters.letterFilters);
            }
            else
            {
                baseLetters = eligibleLetters;
            }

            // Filter out unknown letters
            var filteredBaseLetters = teacher.VocabularyAi.SelectData(
                () => baseLetters,
                new SelectionParameters(parameters.wrongSeverity, getMaxData: true, useJourney: true,
                                        packListHistory: PackListHistory.NoFilter)
                );
            //Debug.LogWarning("Filtered bases: " + filteredBaseLetters.ToDebugStringNewline());

            var alterationsPool = AppManager.I.VocabularyHelper.GetAllLetterAlterations(filteredBaseLetters, letterAlterationFilters);
            var wrongAnswers    = new List <LetterData>();

            //Debug.Log("N Alterations before remove correct: " + alterationsPool.Count + " " + alterationsPool.ToDebugString());

            // Remove the correct alteration (making sure to get the actual form)
            for (int i = 0; i < alterationsPool.Count; i++)
            {
                if (alterationsPool[i].IsSameLetterAs(chosenLetterWithForm, LetterEqualityStrictness.WithVisualForm))
                {
                    alterationsPool.RemoveAt(i);
                }
            }

            //Debug.Log("N Alterations after remove correct: " + alterationsPool.Count + " " + alterationsPool.ToDebugString());
            wrongAnswers.AddRange(alterationsPool.RandomSelect(nWrongs));

            if (ConfigAI.VerboseQuestionPacks)
            {
                string debugString = "--------- TEACHER: question pack result ---------";
                debugString += "\nQuestion: " + question;
                debugString += "\nCorrect Answers: " + correctAnswers.Count;
                foreach (var l in correctAnswers)
                {
                    debugString += " " + l;
                }
                debugString += "\nWrong Answers: " + wrongAnswers.Count;
                foreach (var l in wrongAnswers)
                {
                    debugString += " " + l;
                }
                ConfigAI.AppendToTeacherReport(debugString);
            }

            return(QuestionPackData.Create(question, correctAnswers, wrongAnswers));
        }
Пример #22
0
        public List <T> SelectData <T>(System.Func <List <T> > builderSelectionFunction, SelectionParameters selectionParams, bool isTest = false, bool canReturnZero = false) where T : IVocabularyData
        {
            // skip if we require 0 values
            if (selectionParams.nRequired == 0 && !selectionParams.getMaxData)
            {
                return(new List <T>());
            }

            if (ConfigAI.VerboseDataSelection)
            {
                debugString_selectData  = "";
                debugString_selectData += ConfigAI.FormatTeacherReportHeader("Data Selection: " + typeof(T).Name);
            }

            // (1) Filtering based on the builder's logic
            var dataList      = builderSelectionFunction();
            int nAfterBuilder = dataList.Count;

            if (ConfigAI.VerboseDataFiltering)
            {
                debugString_selectData += ("\n  Builder: " + dataList.Count);
            }

            // (2) Filtering based on journey
            if (selectionParams.useJourney && !ConfigAI.ForceJourneyIgnore)
            {
                switch (selectionParams.journeyFilter)
                {
                case SelectionParameters.JourneyFilter.CurrentJourney:
                    dataList = dataList.FindAll(x => currentJourneyContents.Contains(x));
                    break;

                case SelectionParameters.JourneyFilter.UpToFullCurrentStage:
                    dataList = dataList.FindAll(x => currentJourneyContents.Contains(x) || currentStageContents.Contains(x));
                    break;

                case SelectionParameters.JourneyFilter.CurrentLearningBlockOnly:
                    dataList = dataList.FindAll(x => currentLearningBlockContents.Contains(x));
                    break;
                }
            }
            if (selectionParams.severity == SelectionSeverity.AllRequired)
            {
                if (!CheckRequiredNumberReached(dataList, selectionParams, nAfterBuilder))
                {
                    throw new Exception("The teacher could not find " + selectionParams.nRequired + " data instances after applying the journey logic.");
                }
            }
            if (ConfigAI.VerboseDataFiltering)
            {
                debugString_selectData += ("\n  Journey: " + dataList.Count);
            }
            //Debug.Log("Journey: " + dataList.ToDebugStringNewline());

            // (3) Filtering based on pack-list history
            switch (selectionParams.packListHistory)
            {
            case PackListHistory.NoFilter:
                // we do not care which are picked, in this case
                break;

            case PackListHistory.ForceAllDifferent:
                // filter only by those that have not been found already in this pack, if possible
                dataList = dataList.FindAll(x => !selectionParams.filteringIds.Contains(x.GetId()));
                if (!CheckRequiredNumberReached(dataList, selectionParams, nAfterBuilder))
                {
                    UnityEngine.Debug.Log(debugString_selectData);
                    throw new System.Exception("The teacher could not find " + selectionParams.nRequired + " data instances after applying the pack-history logic.");
                }
                break;

            case PackListHistory.RepeatWhenFull:
                // reset the previous pack list if needed
                var tmpDataList = dataList.FindAll(x => !selectionParams.filteringIds.Contains(x.GetId()));
                if (tmpDataList.Count < selectionParams.nRequired)
                {
                    // reset and re-pick
                    selectionParams.filteringIds.Clear();
                    dataList = dataList.FindAll(x => !selectionParams.filteringIds.Contains(x.GetId()));
                }
                else
                {
                    dataList = tmpDataList;
                }
                break;
            }
            if (ConfigAI.VerboseDataFiltering)
            {
                debugString_selectData += ("\n  History: " + dataList.Count);
            }
            //Debug.Log("History: " + dataList.ToDebugStringNewline());
            //if(selectionParams.filteringIds != null) Debug.Log("Filtered ids:: " + selectionParams.filteringIds.ToDebugStringNewline());

            // (4) Priority filtering based on current focus
            List <T> priorityFilteredList = dataList;

            if (!isTest && !selectionParams.getMaxData && selectionParams.priorityFilter != SelectionParameters.PriorityFilter.NoPriority)
            {
                HashSet <T> priorityFilteredHash = new HashSet <T>();
                string      s = ConfigAI.FormatTeacherReportHeader("Priority Filtering");

                switch (selectionParams.priorityFilter)
                {
                case SelectionParameters.PriorityFilter.CurrentThenExpand:
                {
                    int nBefore    = selectionParams.nRequired;
                    int nRemaining = selectionParams.nRequired;
                    AddToHashSetFilteringByContents(currentPlaySessionContents, dataList, priorityFilteredHash, ref nRemaining);

                    s += "\n Required: " + nRemaining + " " + typeof(T).Name.ToString();
                    s += "\n" + (nBefore - nRemaining) + " from PS";
                    if (nRemaining > 0)
                    {
                        nBefore = nRemaining;
                        AddToHashSetFilteringByContents(currentLearningBlockContents, dataList, priorityFilteredHash, ref nRemaining);
                        s += "\n" + (nBefore - nRemaining) + " from LB";
                    }
                    if (nRemaining > 0)
                    {
                        nBefore = nRemaining;
                        AddToHashSetFilteringByContents(currentStageContents, dataList, priorityFilteredHash, ref nRemaining);
                        s += "\n" + (nBefore - nRemaining) + " from ST";
                    }
                    if (nRemaining > 0)
                    {
                        nBefore = nRemaining;
                        AddToHashSetFilteringByContents(currentJourneyContents, dataList, priorityFilteredHash, ref nRemaining);
                        s += "\n" + (nBefore - nRemaining) + " from the current Journey";
                    }
                    // @note: when journey filtering is disabled, we may still have to get some data from the rest of the journey
                    if (nRemaining > 0 && !selectionParams.useJourney)
                    {
                        nBefore = nRemaining;
                        AddToHashSetFilteringByContents(progressionContents.AllContents, dataList, priorityFilteredHash, ref nRemaining);
                        s += "\n" + (nBefore - nRemaining) + " from the complete contents.";
                    }
                }
                break;

                case SelectionParameters.PriorityFilter.CurrentThenPast:
                {
                    int nBefore    = selectionParams.nRequired;
                    int nRemaining = selectionParams.nRequired;
                    var loopPos    = AppManager.I.Player.CurrentJourneyPosition;
                    s += "\n Required: " + nRemaining + " " + typeof(T).Name.ToString();
                    while (nRemaining > 0)
                    {
                        var loopContents = progressionContents.GetContentsOfPlaySession(loopPos);
                        AddToHashSetFilteringByContents(loopContents, dataList, priorityFilteredHash, ref nRemaining);
                        s += "\n" + (nBefore - nRemaining) + " from PS " + loopPos.ToDisplayedString(true);
                        if (loopPos.Equals(JourneyPosition.InitialJourneyPosition))
                        {
                            break;
                        }
                        loopPos = AppManager.I.JourneyHelper.FindPreviousJourneyPosition(loopPos);
                    }
                }
                break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (ConfigAI.VerboseDataFiltering)
                {
                    ConfigAI.AppendToTeacherReport(s);
                }
                priorityFilteredList = new List <T>();
                priorityFilteredList.AddRange(priorityFilteredHash);
                if (ConfigAI.VerboseDataFiltering)
                {
                    debugString_selectData += ("\n  Priority: " + priorityFilteredList.Count);
                }
            }
            //Debug.Log("Priority: " + priorityFilteredList.ToDebugStringNewline());

            // (5) Weighted selection on the remaining number
            List <T> selectedList = null;

            if (selectionParams.getMaxData)
            {
                selectedList = priorityFilteredList;
            }
            else
            {
                selectedList = WeightedDataSelect(priorityFilteredList, selectionParams.nRequired, selectionParams.severity);
            }
            if (ConfigAI.VerboseDataFiltering)
            {
                debugString_selectData += ("\n  Selection: " + selectedList.Count);
            }
            //if (selectedList.Count > 0) Debug.Log("Selection: " + selectedList.ToDebugStringNewline());

            if (ConfigAI.VerboseDataFiltering && !isTest)
            {
                foreach (var selectedEntry in selectedList)
                {
                    debugString_selectData += "   [" + selectedEntry + "]";
                }
                ConfigAI.AppendToTeacherReport(debugString_selectData);
            }

            if (selectedList.Count == 0)
            {
                if (canReturnZero)
                {
                    return(selectedList);
                }

                throw new System.Exception("The teacher could not find any data with the current filters. The game does not seem to be playable at the selected play session."
                                           + "\n" + debugString_selectData);
            }

            // Update the filtering ids
            if (selectionParams.packListHistory != PackListHistory.NoFilter)
            {
                selectionParams.filteringIds.AddRange(selectedList.ConvertAll <string>(x => x.GetId()).ToArray());
            }

            // Reorder the selected data based on intrinsic difficulty
            if (selectionParams.sortDataByDifficulty)
            {
                selectedList.Sort((x, y) => (int)(x.GetIntrinsicDifficulty() - y.GetIntrinsicDifficulty()));
            }

            return(selectedList);
        }