def get_question(handler_input,
                     first_question: bool = False,
                     player_obj: object = None) -> str:
        """Returns a question for survival mode."""
        if not first_question:
            QuestionAttr.increment_questions_answered(handler_input)

        ## Get new question
        flag_get_new_question = True
        while flag_get_new_question:
            new_question = SMQuestions.get_sampled_num(handler_input)

            if not GenQuestions.check_same_question(handler_input,
                                                    new_question):
                flag_get_new_question = False

        ## Save question
        QuestionAttr.save_question(handler_input, new_question)

        ## Messages
        ms_question_intro = SMQuestions.get_ms_question_intro(
            handler_input,
            first_question=first_question,
            player_obj=player_obj)
        ms_question = GenQuestions.format_question(new_question)

        speech_list = (ms_question_intro, ms_question)
        return get_linear_nlg(speech_list)
    def get_question(handler_input, first_question: bool = False) -> str:
        """Returns question for the user."""
        attr = handler_input.attributes_manager.session_attributes

        if not first_question:
            QuestionAttr.increment_questions_answered(handler_input)

        sc_questions = attr['sc_questions']
        question = sc_questions.pop()

        attr['sc_questions'] = sc_questions
        QuestionAttr.save_question(handler_input, question)

        return GenQuestions.format_question(question)
    def record_wrong_question(handler_input) -> None:
        """Saves the question as a session attribute.

        Implementation NOTE:
        Currently using series of get statements
        May be able to use a while loop instead that checks if data type is dict.
        May also like to change to try-except statement.
        """
        attr = handler_input.attributes_manager.session_attributes

        ## Keys
        wrong_quest_by_date = attr['wrong_quest_by_date']
        today = attr['today']
        table_1, table_2 = QuestionAttr.get_question_tables(handler_input,
                                                            integers=False)
        log_all(wrong_quest_by_date, today, table_1, table_2)

        ## Get Dicts
        incorrect_today_dict = wrong_quest_by_date.get(today, {})
        tbl_1_incorrect_dict = incorrect_today_dict.get(table_1, {})
        tbl_2_val = tbl_1_incorrect_dict.get(table_2, 0)
        log_all(incorrect_today_dict, tbl_1_incorrect_dict, tbl_2_val)

        ## Val
        tbl_2_val += 1

        ## Update dicts
        tbl_1_incorrect_dict[table_2] = tbl_2_val
        incorrect_today_dict[table_1] = tbl_1_incorrect_dict
        wrong_quest_by_date[today] = incorrect_today_dict
        attr['wrong_quest_by_date'] = wrong_quest_by_date

        log_all(incorrect_today_dict, tbl_1_incorrect_dict, tbl_2_val)
        return
    def get_higher_table_difficulty(
        handler_input, 
        player_obj: object = None,
        tables: tuple = None,
        answered_tables: list = None
        ) -> float:
        """Returns z_score for the table with the highest difficulty.
        
        Difficulty is a constructed measure dependent on greatness of tables, 
        e.g., 6 > 5."""
        if not player_obj:
            player_obj = PlayerDict.load_player_obj(handler_input)
        if tables is None:
            tables = QuestionAttr.get_question_tables(handler_input, integers=True)
        if answered_tables is None:
            answered_tables = player_obj.get_answered_tables(integers = True)
            
        inflated_mean_table = mean(answered_tables) + 1
        higher_table = max( [int(table) for table in tables])

        z_score = calc_z_score(
            data_point= higher_table,
            data_mean = inflated_mean_table,
            data=  answered_tables,
            required_data_length= stats.data.SUF_ANSWERED_TABLES
        )
        return z_score
    def get_same_question(handler_input) -> str:
        """Returns the same question to the user."""
        question = QuestionAttr.get_question_tables(handler_input,
                                                    integers=False)

        question = GenQuestions.format_question(question)
        return question
    def get_question(
        handler_input,
        player_object: object,
        practice_type: str,
        first_question: bool = False,
    ) -> str:
        """Asks the user a multiplication question based on custom practice type."""
        attr = handler_input.attributes_manager.session_attributes
        if not first_question:
            QuestionAttr.increment_questions_answered(handler_input)

        flag_get_new_question = True
        while flag_get_new_question:
            new_question = CP_QuestionByType.get_question_type(
                handler_input, player_object, practice_type)

            if (not GenQuestions.check_same_question(handler_input,
                                                     new_question)
                    or practice_type == custom_practice.data.PRACT_TYPES[
                        0]  # can repeat on incorrect from date.
                ):
                flag_get_new_question = False

        ## Message Intro
        ms_intro = CP_Questions.get_ms_question_intro(handler_input,
                                                      player_object,
                                                      practice_type,
                                                      first_question,
                                                      new_question)

        ## Save Question
        QuestionAttr.save_question(
            handler_input, new_question
        )  # NOTE: Save question after for duplicates on incorrect-problems.
        ms_question = GenQuestions.format_question(new_question)

        ## Punct for interrogative
        if attr.get('interrogative_question', False):
            punct = '?'
            attr['interrogative_question'] = False
        else:
            punct = ''

        speech_list = (ms_intro, ' ', ms_question, punct)
        speech = ''.join(speech_list)
        return CardFuncs.format_prompt(speech)
예제 #7
0
    def get_sm_pause_length(handler_input) -> str:
        """Returns pause for survival mode dependent on the problem difficulty."""
        tables = QuestionAttr.get_question_tables(handler_input, True)
        harder_table = max(tables)

        pause_level = round(harder_table * (1 / 10) + 1, 2)
        pause_level = pause_level if pause_level < 3 else 3

        return Pauser.get_p_level(level=pause_level)
    def check_same_question(handler_input, new_question: tuple) -> bool:
        """Returns boolean representing if same question asked to the user."""
        old_question_1, old_question_2 = QuestionAttr.get_question_tables(
            handler_input, integers=True)
        log_all(old_question_1, old_question_2, new_question[0],
                new_question[1])

        return (new_question[0] == old_question_1
                and new_question[1] == old_question_2)
예제 #9
0
    def handle(self, handler_input):
        logger.info("HAN    GetAnswerHandler")
        speech_list = []

        ms_answer = GetAnswerSpeech.get_ms_answer(handler_input)
        next_question = FPQuestions.get_question(handler_input)
        QuestionAttr.increment_questions_answered(handler_input,
                                                  False)  # undo increment.
        ## NOTE: would not need to de-increment with better modulation.

        speech_list += Pauser.make_ms_pause_level_list(ms_answer, 2,
                                                       next_question)

        reprompt = next_question

        speech = ' '.join(speech_list)
        card_title, card_text = CardFuncs.get_card_info(handler_input, speech)
        return (handler_input.response_builder.speak(speech).ask(
            reprompt).set_card(SimpleCard(card_title, card_text)).response)
예제 #10
0
    def check_answer(handler_input) -> bool:
        """Returns boolean if user answer is correct."""
        table_1, table_2 = QuestionAttr.get_question_tables(handler_input, True)
        answer = SlotUtils.get_slot_val_by_name(handler_input, 'answer')
        
        if not answer:
            logger.error("check_answer: No answer found.")
            ## NOTE: if this error is being thrown, need to incorporate 
            ## FallbackUtils.return_unknown_slot_response()
            return False

        return (table_1 * table_2 == int(answer))
    def calculate_excite_level(handler_input,
                               player_obj: object = None,
                               survival_mode: bool = False) -> int:
        """Returns congratulations level to return to the user.

        Conditions checked:
        - Consecutive incorrect
        - Consecutive correct
        - If user has high (f) error on table
        - Table difficulty vs average table difficulty
        """
        attr = handler_input.attributes_manager.session_attributes

        consecutive_incorrect = attr.get('consecutive_incorrect', 0)
        consecutive_correct = attr.get('consecutive_correct', 0)
        consecutive_correct = (consecutive_correct +
                               1) if consecutive_correct is not None else 1
        excite_level = 0

        if consecutive_incorrect and (not survival_mode):
            return consecutive_incorrect - (1 - random.random())

        elif ((consecutive_correct) % 5 == 0) and (not survival_mode):
            return CongratLevel.get_level_consecutive_correct(
                consecutive_correct)

        tables = QuestionAttr.get_question_tables(handler_input,
                                                  integers=False)
        if not player_obj:
            player_obj = PlayerDict.load_player_obj(handler_input)

        ## Check table error frequency
        higher_f_error = UserStats.get_higher_table_error_freq(
            handler_input, player_obj=player_obj, tables=tables)
        logger.debug(f"higher_f_error   {higher_f_error}")

        if higher_f_error >= 1.5:  ## Arbitrary value. NOTE: Revist.
            return higher_f_error

        ## Check Relative Table difficulty
        higher_table_difficulty = UserStats.get_higher_table_difficulty(
            handler_input, player_obj=player_obj, tables=tables)
        logger.debug(f"higher_table_difficulty  {higher_table_difficulty}")
        if higher_table_difficulty > 1.5:
            return higher_table_difficulty

        return excite_level
예제 #12
0
    def remove_question_from_incorrect_questions(handler_input) -> None:
        """Removes the question from the incorrect questions.
        
        Also checks if dictionary is empty and deletes.
        """
        attr = handler_input.attributes_manager.session_attributes
        wrong_quest_by_date = attr['wrong_quest_by_date']

        date_key = CP_Utils.get_oldest_date(wrong_quest_by_date)
        date_dict = wrong_quest_by_date[date_key]

        table_1, table_2 = QuestionAttr.get_question_tables(handler_input, integers = False)
        
        log_all( date_dict, table_1, table_2)
        
        table_1_dict = date_dict[table_1]
        num_incorrect = table_1_dict[table_2]
        log_all(table_1_dict, num_incorrect)

        ## Reduce counts of incorrect.
        num_incorrect = CP_Utils.reduce_num_incorrect(num_incorrect)

        ## Resave dictionaries.
        table_1_dict[table_2] = num_incorrect
        date_dict[table_1] = table_1_dict
        wrong_quest_by_date[date_key] = date_dict

        log_all(table_1_dict, date_dict, wrong_quest_by_date)

        ## Should refactor into many different methods.
        logger.debug(num_incorrect)
        if num_incorrect == 1:      # already asked, so delete & any unnecessary dicts
            CP_Attr.del_dict_key(table_1_dict, key = table_2)

            if len(table_1_dict.keys()) == 0:
                CP_Attr.del_dict_key(date_dict, table_1)
            
                if len(date_dict.keys()) == 0:
                    CP_Attr.del_dict_key(wrong_quest_by_date, key = date_key)
                    
        logger.debug(wrong_quest_by_date)
        attr['wrong_quest_by_date'] = wrong_quest_by_date
        return
    def get_ms_answer(handler_input, include_correct_ans: bool = True) -> str:
        """Returns message of what the answer is.

        Format: Num1 * Num2 = Num3"""
        table_1, table_2 = QuestionAttr.get_question_tables(handler_input,
                                                            integers=True)
        user_answer = SlotUtils.get_slot_val_by_name(handler_input, 'answer')
        answer = str(table_1 * table_2) + '.'

        ms_question = check_answer.data.MS_QUESTION.format(table_1, table_2)

        speech_list = [
            ms_question,
            check_answer.data.MT_EQUALS,
            answer,
        ]
        if include_correct_ans:
            ms_ans = check_answer.data.MS_NOT_ANS.format(user_answer)
            speech_list.append(ms_ans)

        return get_linear_nlg(speech_list)
예제 #14
0
    def get_higher_table_error_freq(
        handler_input, 
        player_obj: object = None,
        tables: tuple = None
        ) -> float:
        """Returns z_score for the highest error tables."""
        if not player_obj:
            player_obj = PlayerDict.load_player_obj(handler_input)
        if tables is None:
            tables = QuestionAttr.get_question_tables(handler_input, integers=False)
        
        times_tables_info = player_obj.get_times_table_info()
        times_tables_mean_err_list = []
        
        for table in times_tables_info.keys():
            table_mean = float(times_tables_info[table]['mean'])
            table_data = times_tables_info[table]['table_data']

            if len(table_data) > stats.data.SUF_TABLE_DATA:
                times_tables_mean_err_list.append(1 - table_mean)   # inversed, so errors are higher.
        
        ## Exit if not enough data.
        if len(times_tables_mean_err_list) <= stats.data.SUF_ERR_LIST:
            return 0
        
        question_tables_err =  []
        for table in tables:
            table = str(table)
            table_info = float( times_tables_info[table]['mean'])
            table_info = (1 - table_info)   # inverse mean.
            question_tables_err.append( table_info)
        
        max_table_err = max(question_tables_err)
        z_score = calc_z_score(
            data_point= max_table_err,
            data= times_tables_mean_err_list,
        )

        return ( z_score)