Example #1
0
    async def _alter_flashcard(self, flashcard: Flashcard):
        if not flashcard.is_audio_type():
            question = await self.mediator.input_question(
                pre_fill=flashcard.question
            )
        else:
            question = flashcard.question

        answer = await self.mediator.input_answer(
            pre_fill=flashcard.answer
        )
        source = await self.mediator.input_source(
            pre_fill=flashcard.source
        )
        phonetic_transcription = (
            await self.mediator.input_phonetic_transcription(
                flashcard_answer=answer,
                curr_ans_pronunciation=flashcard.phonetic_transcription,
            )
        )
        explanation = await self.mediator.input_explanation(
            pre_fill=flashcard.explanation
        )
        examples = await self.mediator.input_examples(
            data=flashcard.examples
        )

        flashcard.alter(
            question=question,
            answer=answer,
            source=source,
            phonetic_transcription=phonetic_transcription,
            explanation=explanation,
            examples=examples
        )
Example #2
0
    async def do_review_session(self, flashcard: Flashcard):
        if flashcard.is_audio_type():
            await self.mediator.print(
                f'{self.mediator.format_grey("Question")}: '
                f' Use Ctrl+C to play the audio.')
            self.media_player.play()
        else:
            await self.mediator.print(
                f'{self.mediator.format_grey("Question")}: '
                f'{flashcard.question}')

        entered_answer = await self.mediator.input_answer()

        if flashcard.is_audio_type():
            self.media_player.stop()

        entered_answer = normalize_text(entered_answer)
        answer_side = normalize_text(flashcard.answer)

        edit_dist, entered_ans_alignment, ans_side_alignment = (
            self.compute_edit_distance(entered_answer, answer_side))
        res = {
            "edit_dist": edit_dist,
            "entered_ans_alignment": entered_ans_alignment,
            "ans_side_alignment": ans_side_alignment
        }
        return res
Example #3
0
    async def _alter_flashcard(self, flashcard: Flashcard):
        if not flashcard.is_audio_type():
            question = await self.mediator.input_question(
                pre_fill=flashcard.question)
        else:
            question = flashcard.question

        answer = await self.mediator.input_answer(pre_fill=flashcard.answer)
        source = await self.mediator.input_source(pre_fill=flashcard.source)

        flashcard.alter(question=question, answer=answer, source=source)
Example #4
0
    async def make_review(self, flashcard: Flashcard, review_stat):
        previous_review_timestamp = await self.mediator.get_prev_review_timestamp(
            flashcard=flashcard)
        current_review_timestamp = datetime_now()

        session_res = await self.do_review_session(flashcard)
        assert session_res['edit_dist'] >= 0, 'Edit dist. cannot be negative'

        if session_res['edit_dist'] > 4:
            await self.mediator.print(
                f'Oops! You have too many errors! You have one more attempt.',
                red=True)
            session_res = await self.do_review_session(flashcard)

        if 0 <= session_res['edit_dist'] <= 4:
            flashcard.review_timestamp = FlashcardScheduler.to_next(
                flashcard_answer=flashcard.answer,
                previous_review_timestamp=previous_review_timestamp)
            review_stat.inc_right()
            current_result = 'success'
            colour_func = self.mediator.format_green
            if session_res['edit_dist'] > 0:
                colour_func = self.mediator.format_yellow
                await self.mediator.print(session_res['entered_ans_alignment'])
                await self.mediator.print(session_res['ans_side_alignment'],
                                          bottom_margin=1)
        else:
            flashcard.review_timestamp = FlashcardScheduler.to_init(
                flashcard_answer=flashcard.answer)
            review_stat.inc_wrong()
            colour_func = self.mediator.format_red
            current_result = 'failure'

            await self.mediator.print(session_res['entered_ans_alignment'])
            await self.mediator.print(session_res['ans_side_alignment'],
                                      bottom_margin=1)

        flashcard.review_version += 1

        await self.mediator.print_flashcard(
            flashcard,
            colour_func=colour_func,
            exclude_fields=[Flashcard.flashcard_id, Flashcard.question],
            bottom_margin=1)

        await self.mediator.update_flashcard_review_state(
            flashcard_id=flashcard.flashcard_id,
            current_review_timestamp=current_review_timestamp,
            current_result=current_result,
            next_review_timestamp=flashcard.review_timestamp,
            next_review_version=flashcard.review_version,
        )
        review_stat.inc_reviewed()
    async def print_flashcard(self,
                              flashcard: Flashcard,
                              include_fields=None,
                              exclude_fields=None,
                              colour_func=None,
                              bottom_margin=None):
        if exclude_fields is not None and include_fields is not None:
            raise Exception(
                'You can not specify both exclude_fields and include_fields')

        if exclude_fields is not None:
            fields = list(
                set(flashcard.printable_fields) - set(exclude_fields))
        elif include_fields is not None:
            fields = include_fields
        else:
            fields = None

        for key, value in flashcard.print_format(fields=fields):
            if colour_func is not None:
                key = colour_func(key)
            data = f'{key}: {value}'
            await self.async_std_io.print(data)

        if bottom_margin is not None:
            await self.async_std_io.print(*[''] * bottom_margin)
Example #6
0
    async def _wrapper(loop, user, file_path):
        logger_tu.info('Create english flashcards')
        logger_tu.info('User: %s', user)
        logger_tu.info('File: %s', file_path)

        mediator = EnglishMediator()
        is_login = await mediator.login_user(user)
        if not is_login:
            sys.exit(f'Failed to login user: {user}')

        mediator.set_loop(loop)

        with open(file_path) as fh:
            data = json.loads(fh.read())
        logger_tu.info(f'Loaded data: {len(data)}')

        for datum in data:
            logger_tu.info('Processing answer: %s', datum['answer'])
            flashcard: Flashcard = Flashcard.create(
                user_id=mediator.get_user_id(),
                flashcard_type=mediator.name(),
                question=datum['question'],
                answer=datum['answer'],
                source=datum['source'],
                phonetic_transcription=datum['phonetic_transcription'],
                explanation=datum['explanation'],
                examples=json.loads(datum['examples']))
            await mediator.save_flashcard(flashcard)
Example #7
0
    def add_flashcard(self, flashcard: Flashcard) -> None:
        with self.db_conn:
            self.db_cursor.execute(
                'INSERT INTO flashcards('
                '    flashcard_type, '
                '    user_id, '
                '    question, '
                '    answer, '
                '    review_timestamp, '
                '    review_version, '
                '    source, '
                '    explanation, '
                '    phonetic_transcription, '
                '    created '
                ') '
                'VALUES ('
                '    :flashcard_type, '
                '    :user_id, '
                '    :question, '
                '    :answer, '
                '    :review_timestamp, '
                '    :review_version, '
                '    :source, '
                '    :explanation, '
                '    :phonetic_transcription, '
                '    :created '
                ') ', {
                    'flashcard_type':
                    flashcard.flashcard_type,
                    'user_id':
                    flashcard.user_id,
                    'question':
                    flashcard.question,
                    'answer':
                    flashcard.answer,
                    'review_timestamp':
                    datetime_change_timezone(flashcard.review_timestamp,
                                             offset=0),
                    'review_version':
                    flashcard.review_version,
                    'source':
                    flashcard.source,
                    'explanation':
                    flashcard.explanation,
                    'phonetic_transcription':
                    flashcard.phonetic_transcription,
                    'created':
                    datetime_change_timezone(flashcard.created, offset=0)
                })
            flashcard.flashcard_id = self.db_cursor.lastrowid

            for example in flashcard.examples or []:
                self.db_cursor.execute(
                    'INSERT INTO flashcard_example(flashcard_id, example)'
                    'VALUES (:flashcard_id, :example)', {
                        'flashcard_id': flashcard.id,
                        'example': example
                    })
Example #8
0
    def _get_flashcards(self,
                        request: str,
                        request_params: dict = None) -> List[Flashcard]:

        request_params = request_params or {}
        query = self.db_cursor.execute(
            f'SELECT '
            f'    id as flashcard_id, '
            f'    flashcard_type, '
            f'    user_id, '
            f'    question, '
            f'    answer, '
            f'    review_timestamp, '
            f'    review_version, '
            f'    source, '
            f'    explanation, '
            f'    phonetic_transcription, '
            f'    created '
            f'FROM flashcards '
            f'{request}', request_params)
        flashcards = []
        for row in query.fetchall():
            data = dict(row)
            examples = self.db_cursor.execute(
                'SELECT example '
                'FROM flashcard_example '
                'WHERE flashcard_id = :flashcard_id',
                {'flashcard_id': data['flashcard_id']})
            data['examples'] = [r['example'] for r in examples]

            flashcard = Flashcard(
                user_id=data['user_id'],
                flashcard_type=data['flashcard_type'],
                question=data['question'],
                answer=data['answer'],
                created=convert_datetime_to_local(data['created']),
                review_timestamp=convert_datetime_to_local(
                    data['review_timestamp']),
                review_version=data['review_version'],
                flashcard_id=data['flashcard_id'],
                phonetic_transcription=data['phonetic_transcription'],
                source=data['source'],
                explanation=data['explanation'],
                examples=data['examples'])
            flashcards.append(flashcard)

        return flashcards
Example #9
0
 async def delete_flashcard(self, flashcard: Flashcard):
     await super().delete_flashcard(flashcard=flashcard)
     if flashcard.is_audio_type():
         audio_file = flashcard.get_audio_file(parent_dir=self.get_audio_dir())
         os.remove(str(audio_file))
    async def launch(self):
        await super().launch()

        await self.mediator.print(f'Creating New Flashcard', bold=True)
        data = await self._collect_data()

        if not data.get('answer') or not data.get('question'):
            await self.mediator.print(
                'Aborting creation. Either answer or question is empty.',
                bottom_margin=1,
                red=True
            )
            return

        flashcard: Flashcard = Flashcard.create(
            user_id=self.mediator.get_user_id(),
            flashcard_type=self.mediator.name(),
            question=data.get('question'),
            answer=data.get('answer'),
            source=data.get('source'),
            phonetic_transcription=data.get('phonetic_transcription'),
            explanation=data.get('explanation'),
            examples=data.get('examples')
        )

        duplicates: FlashcardContainer = (
            await self.mediator.search_flashcard(flashcard.answer)
        )
        question_duplicates: FlashcardContainer = (
            await self.mediator.search_flashcard(flashcard.question)
        )
        duplicates.extend(question_duplicates)

        for duplicate in duplicates:
            await self.mediator.print(
                f'Possible duplicate',
                bold=True,
            )
            await self.mediator.print_flashcard(
                duplicate,
                bottom_margin=1,
                colour_func=self.mediator.format_red,
                exclude_fields=[
                    Flashcard.explanation,
                    Flashcard.examples
                ]
            )

        await self.mediator.print(
            'Creating flashcard',
            bottom_margin=1,
            bold=True,
        )
        await self.mediator.print_flashcard(
            flashcard,
            colour_func=self.mediator.format_yellow,
            bottom_margin=1,
            exclude_fields=[
                Flashcard.flashcard_id,
                Flashcard.review_timestamp,
                Flashcard.created
            ]
        )
        await self.mediator.print(
            f'Possible duplicates: {len(duplicates)}',
            bold=True
        )

        confirmed: bool = await self.mediator.input_confirmation(
            'Do you want to create?'
        )
        if confirmed:
            await self.mediator.save_flashcard(flashcard)
            await self.mediator.print(
                'Flashcard saved.',
                bottom_margin=1,
                bold=True
            )
            await self.mediator.print_flashcard(
                flashcard=flashcard,
                colour_func=self.mediator.format_yellow,
                bottom_margin=1,
                include_fields=[
                    Flashcard.flashcard_id,
                    Flashcard.question,
                    Flashcard.answer
                ]
            )
        else:
            await self.mediator.print(
                'Aborting creation',
                bottom_margin=1,
                red=True
            )
Example #11
0
    async def _wrapper(loop, user, dir_path, source):
        logger_tu.info('Create audio english flashcards')
        logger_tu.info('User: %s', user)
        logger_tu.info('Directory: %s', dir_path)
        logger_tu.info('Source: %s', source)

        mediator = EnglishMediator()
        is_login = await mediator.login_user(user)
        if not is_login:
            sys.exit(f'Failed to login user: {user}')

        mediator.set_loop(loop)

        data = []
        for dirpath, dirnames, filenames in os.walk(dir_path):
            for file_name in filenames:
                file_path = pathlib.Path(os.path.join(dirpath, file_name))
                if file_path.suffix in ['.mp3']:
                    data.append({
                        'audio_file_path':
                        file_path,
                        'json_file_path':
                        file_path.with_suffix('.json'),
                    })

        for datum in data:
            now = datetime.now()
            now = now.strftime('%Y_%m_%d_%H_%M_%S_%f')

            audio_suffix = datum['audio_file_path'].suffix
            file_name = f'__audio__{now}{audio_suffix}'
            flashcard_audio_file_path = pathlib.Path(
                os.path.join(mediator.get_audio_dir(), file_name))
            flashcard_audio_file_path.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy(datum['audio_file_path'], flashcard_audio_file_path)

            question = file_name
            with open(datum['json_file_path']) as fh:
                json_data = json.load(fh)

            logger_tu.info('Processing %s answer: %s', question,
                           json_data['answer'])
            # Save as audio flashcard
            flashcard: Flashcard = Flashcard.create(
                user_id=mediator.get_user_id(),
                flashcard_type=mediator.name(),
                question=question,
                answer=json_data['answer'].strip().capitalize(),
                source=source,
                explanation=json_data['explanation'])
            await mediator.save_flashcard(flashcard)

            # Save as text flashcard
            flashcard: Flashcard = Flashcard.create(
                user_id=mediator.get_user_id(),
                flashcard_type=mediator.name(),
                question=json_data['question'],
                answer=json_data['answer'],
                source=source,
                explanation=json_data['explanation'])
            await mediator.save_flashcard(flashcard)