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 )
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
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)
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)
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)
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 })
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
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 )
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)