def test_get_points_different_size_stat( self ): """ Tests if a list of statistics have back the right points. The list and the expected points are the following: (0,)->6 (1,)->3 (0, 0)->8 (0, 1)->4 (1, 0)->5 (1, 1)->2 (0, 0, 0)->10 (0, 0, 1)->6 (0, 1, 0)->6 (0, 1, 1)->2 (1, 0, 0)->7 (1, 0, 1)->4 (1, 1, 0)->4 (1, 1, 1)->1 """ # Mock the __ini__ with patch.object(FilteredDictionary, "__init__", lambda x: None): myFilteredDictionary=FilteredDictionary() myFilteredDictionary.base_language="hungarian" myFilteredDictionary.learning_language="swedish" myFilteredDictionary.recent_stat_list={i:list(i) for i in list(itertools.product([0,1], repeat=1)) + list(itertools.product([0,1], repeat=2)) + list(itertools.product([0,1], repeat=3))} myFilteredDictionary.word_dict={"1":('v', ['AAA'], 'aaa', '') } expected_list=[6,3,8,4,5,2,10,6,6,2,7,4,4,1] # run with all statuses -> result zipped with the expected valus -> pairs substracted from each other -> sum -> it must be 0 self.assertEqual( sum( [ j[0]-j[1] for j in zip( [myFilteredDictionary.get_points(i) for i in myFilteredDictionary.recent_stat_list], expected_list) ] ), 0 )
class ConsolePrala(object): COLOR_DEFAULT = "\033[00m" COLOR_POS = "\033[1;33m" #yellow COLOR_QUESTION = "\033[1;37m" #white COLOR_INPUT = "\033[1;34m" #ligth blue #COLOR_RESULT_STATUS_WRONG="\033[0;31m" #red COLOR_RESULT_STATUS_WRONG = "\033[41m\033[1;37m" #red background-white foreground #COLOR_RESULT_STATUS_RIGHT="\033[0;32m" #green COLOR_RESULT_STATUS_RIGHT = "\033[42m\033[1;37m" #green background-white foreground COLOR_GOOD_ANSWER_WRONG = "\033[1;31m" #light red COLOR_GOOD_ANSWER_RIGHT = "\033[0;32m" #green COLOR_STAT = "\033[1;33m" #yellow COLOR_CORRECTION_RIGHT = "\033[0;32m" #green COLOR_CORRECTION_WRONG = "\033[1;31m" #light red COLOR_NUMBER_OF_WORDS = "\033[1;32m" #light green COLOR_NOTE = "\033[0;37m" #gray POSITION_POS = "\033[9;10H" POSITION_QUESTION = "\033[10;10H" POSITION_INPUT = "\033[14;10H" POSITION_RESULT_STATUS = "\033[12;10H" POSITION_CORRECTION = "\033[14;10H" POSITION_GOOD_ANSWER = "\033[15;10H" POSITION_STAT = "\033[21;10H" STATUS_WRONG = "WRONG" STATUS_RIGHT = "RIGHT" TEMPLATE_INI_FILE_NAME = "template.in" TEMPLATE_DICT_FILE_NAME = "template.dict" # INI_FILE_NAME="config.ini" def __init__(self, file_name, part_of_speech_filter="", extra_filter=""): config_ini = ConfigIni.getInstance() language = config_ini.getLanguage() base_language = to_name(config_ini.getBaseLanguage()).lower() learning_language = to_name(config_ini.getLearningLanguage()).lower() self.say_out = config_ini.isSayOut(), self.show_pattern = config_ini.isShowPattern(), self.show_note = config_ini.isShowNote() self.myFilteredDictionary = FilteredDictionary(file_name, base_language, learning_language, part_of_speech_filter, extra_filter) def round(self, wrong_record=None): """ It is a round of asking question Input wrong_record - It is unrelevant until all words was answerd - If it is EMPTY then the chance depends on the points - If it is NOT EMPTY the the same question will be asked until it answered """ self.clear_console() record = self.myFilteredDictionary.get_next_random_record(wrong_record) # show the part of speech self.out_pos(record.part_of_speach) # shows the question word self.out_question(record.base_word + " - ", "(" + str(len(record.learning_words)) + ")", " " + record.note if self.show_note else "") # show stat overall = self.myFilteredDictionary.get_recent_stat_list() overall_str = str(overall[1]) + "/" + str(overall[0]) + ( "/" + str(overall[2]) if overall[2] > 0 else "") + " (" + (str( int(100 * overall[1] / overall[0])) if overall[0] > 0 else "") + "%)" actual = record.get_recent_stat() points = self.myFilteredDictionary.get_points(actual) self.out_stat(overall_str, actual, points) # say out the question if self.say_out: record.say_out_base() # replace every alphabetic character to _ to show under cursor if self.show_pattern: template = re.sub(r"[^, \!]", "_", ", ".join(record.learning_words)) else: template = "" # cut the answer by the separator -> list line = [i.strip() for i in self.get_input(template).split(",")] # shows the difference between the the answer and the good answer -> tuple # [0] -> False/True # [1] -> list of list of the positions of the difference in the words result = record.check_answer(line) # write back the stat self.myFilteredDictionary.add_result_to_stat(record.word_id, result[0]) # good answer if result[0]: self.out_good_answer_right(record.learning_words) # wrong answer else: self.out_correction(result[1], line, record.learning_words) self.out_good_answer_wrong(record.learning_words) #shows statistics overall = self.myFilteredDictionary.get_recent_stat_list() overall_str = str(overall[1]) + "/" + str(overall[0]) + ( "/" + str(overall[2]) if overall[2] > 0 else "") + " (" + str( int(100 * overall[1] / overall[0])) + "%)" actual = record.get_recent_stat() points = self.myFilteredDictionary.get_points(actual) self.out_stat(overall_str, actual, points) # say out the right answer if self.say_out: record.say_out_learning() #waitin for a click to continue input() return None if result[0] else record def clear_console(self): sys.stdout.write("\033[2J") def out_question(self, question, number_of_words, note): sys.stdout.write(type(self).POSITION_QUESTION) sys.stdout.write(type(self).COLOR_QUESTION) print(question, end="") sys.stdout.write(type(self).COLOR_NUMBER_OF_WORDS) print(number_of_words, end="") sys.stdout.write(type(self).COLOR_NOTE) print(note) sys.stdout.write(type(self).COLOR_DEFAULT) def get_input(self, template): sys.stdout.write(type(self).POSITION_INPUT) sys.stdout.write(type(self).COLOR_INPUT) print(template) sys.stdout.write(type(self).POSITION_INPUT) return input() def out_result_status(self, status): sys.stdout.write(type(self).POSITION_RESULT_STATUS) if status: sys.stdout.write(type(self).COLOR_RESULT_STATUS_RIGHT) print(type(self).STATUS_RIGHT) else: sys.stdout.write(type(self).COLOR_RESULT_STATUS_WRONG) print(type(self).STATUS_WRONG) sys.stdout.write(type(self).COLOR_DEFAULT) def out_pos(self, pos): sys.stdout.write(type(self).POSITION_POS) sys.stdout.write(type(self).COLOR_POS) print(pos, sep=", ") def out_good_answer_right(self, answer): #sys.stdout.write(type(self).POSITION_GOOD_ANSWER) #sys.stdout.write(type(self).COLOR_GOOD_ANSWER_RIGHT) #print( *answer, sep=", ") #sys.stdout.write(type(self).COLOR_DEFAULT) self.out_result_status(True) def out_good_answer_wrong(self, answer): sys.stdout.write(type(self).POSITION_GOOD_ANSWER) sys.stdout.write(type(self).COLOR_GOOD_ANSWER_WRONG) print(*answer, sep=", ") sys.stdout.write(type(self).COLOR_DEFAULT) self.out_result_status(False) def out_stat(self, overall, specific, points): sys.stdout.write(type(self).POSITION_STAT) sys.stdout.write(type(self).COLOR_STAT) print(overall, specific, "(" + str(points) + ")") sys.stdout.write(type(self).COLOR_DEFAULT) def out_correction(self, result, line, learning_words): sys.stdout.write(type(self).POSITION_CORRECTION) zipped_list = list( zip( line + ["_" * len(i) for i in learning_words][len(line):], learning_words + [" " * len(i) for i in line][len(learning_words):])) for word_failed_position_pair in zip( [i[0] + ("_" * len(i[1]))[len(i[0]):] for i in zipped_list], result): for pos in range(len(word_failed_position_pair[0])): if pos in word_failed_position_pair[1]: sys.stdout.write(type(self).COLOR_CORRECTION_WRONG) else: sys.stdout.write(type(self).COLOR_CORRECTION_RIGHT) print(word_failed_position_pair[0][pos], end="") print(", ", end="") sys.stdout.write(type(self).COLOR_DEFAULT) # this need to use the class with "with" def __enter__(self): return self # this need to us the class with "with" # the reason of using it "with" is to get back the default coursor color at the end def __exit__(self, exc_type, value, traceback): sys.stdout.write(type(self).COLOR_DEFAULT) print("") return isinstance( value, KeyboardInterrupt) #Supress the KeyboardInterrupt exception
class AskingCanvas(QWidget): FIELD_DISTANCE = 3 def __init__(self, status_bar, file_name, part_of_speech_filter, extra_filter): super().__init__() config_ini = ConfigIni.getInstance() self.status_bar = status_bar self.myFilteredDictionary = FilteredDictionary( file_name, config_ini.getBaseLanguage(), config_ini.getLearningLanguage(), part_of_speech_filter, extra_filter) good_answer = [""] self.pos_field = TextLabel("", font="Courier New", size=10, color=Qt.gray) self.question_field = TextLabel("", font="Courier New", size=13, color=QColor(212, 140, 95)) self.note_field = TextLabel("", font="Courier New", size=10, color=Qt.gray, bold=True, italic=True) self.answer_field = AnswerComplexField( good_answer, spacing=AskingCanvas.FIELD_DISTANCE, font="Courier new", size=15, color=Qt.blue, bg=self.palette().color(QPalette.Background)) #self.answer_field.disableText() self.good_answer_field = ExpectedAnswerComplexField( good_answer, spacing=AskingCanvas.FIELD_DISTANCE, font="Courier new", size=15, color=Qt.black, bg=self.palette().color(QPalette.Background)) self.result_lamp = ResultLamp(failed_position_list=None) self.ok_button = OKButton(self) # -------------------- # general grid setting # -------------------- # grid = QGridLayout() self.setLayout(grid) grid.setSpacing(1) # space between the fields # -------------------- # Fields location # -------------------- fields_columns = 4 # PART OF SPEECH field grid.addWidget(self.pos_field, 0, 0, 1, fields_columns) # QUESTION field grid.addWidget(self.question_field, 1, 0, 1, fields_columns - 1) # NOTE field grid.addWidget(self.note_field, 1, fields_columns - 1, 1, 1, Qt.AlignRight) # ANSWER field grid.addWidget(self.answer_field, 5, 0, 1, fields_columns - 1) # EXPECTED ANSWER field grid.addWidget(self.good_answer_field, 6, 0, 1, fields_columns - 1) # OK buttn grid.addWidget(self.ok_button, 5, fields_columns - 1, 1, 1, Qt.AlignRight) # RESULT lamp grid.addWidget(self.result_lamp, 6, fields_columns - 1, 1, 1, Qt.AlignRight) # self.setGeometry(300, 300, 450, 150) # self.setWindowTitle(_("TITLE_WINDOW")) # self.show() def showStat(self): overall = self.myFilteredDictionary.get_recent_stat_list() good = str(overall[1]) all = str(overall[0]) remains = str(overall[2]) if overall[2] > 0 else "" success = str(int(100 * overall[1] / overall[0])) + "%" if overall[0] != 0 else "" recent_stat = self.record.get_recent_stat() sequence = ", ".join([str(i) for i in recent_stat]) points = str(self.myFilteredDictionary.get_points(recent_stat)) message = good + "/" + all + ( "/" + remains if len(remains.strip()) > 0 else "") + " | " + success + " | " + points + " | " + sequence self.status_bar.showMessage(message) def round(self, wrong_record=None): """ Frame of asking word. The other part of hte round is in the OKButton's on_click() method -calculates the the new word to ask -fill up the POS field -fill up the QUESTION field -fill up the ANSWER field -fill up the EXPECTED ANSWER field -say out the question -waiting for the user response Input wrong_record - It is unrelevant until all words was answerd - If it is EMPTY then the chance depends on the points - If it is NOT EMPTY the the same question will be asked until it answered """ # hides the result lamp self.result_lamp.set_result(None) self.record = self.myFilteredDictionary.get_next_random_record( wrong_record) good_answer = self.record.learning_words # pos field self.pos_field.setText(self.record.part_of_speach) # question self.question_field.setText(self.record.base_word) config_ini = ConfigIni.getInstance() # note field if config_ini.isShowNote(): self.note_field.setText(self.record.note) # answer self.answer_field.setExpectedWordList(good_answer) self.answer_field.enableText() # expected answer self.good_answer_field.setExpectedWordList(good_answer) # say out the question in a thread if config_ini.isSayOut(): Thread(target=self.record.say_out_base, args=()).start() self.answer_field.setFirstFocus() # shows statistics self.showStat()