import csv import os import pickle import random import sys import termios import tty from pathlib import Path class Flashcards: def __init__(self): self.cards = {} self.selected_category = None self.current_cards = None self.current_card_index = 0 self.side = 0 # 0 = korean, 1 = eng self.difficult_cards = [] self.difficult_pickle_path = "difficult_cards.pkl" self.load_difficult_cards() def save_difficult_cards(self): with open(self.difficult_pickle_path, "wb") as f: pickle.dump(self.difficult_cards, f) def load_difficult_cards(self): if Path(self.difficult_pickle_path).exists(): with open(self.difficult_pickle_path, "rb") as f: self.difficult_cards = pickle.load(f) @staticmethod def get_key(): fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(fd) return sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) @staticmethod def clear(): print("\033[2J\033[H", end="") def main(self): self.parse_cards() self.select_category() self.loop() def select_category(self): self.current_card_index = 0 self.side = 0 self.clear() print("Categories") print('============================') for idx, category in enumerate(list(self.cards.keys())): print(f"[{idx}] {category}") if len(self.difficult_cards) > 0: print('[d] Difficult Cards') print("\n") resp = input("Select a Category: ") if resp == 'd': self.selected_category = "Difficult Cards" self.current_cards = random.sample(self.difficult_cards, len(self.difficult_cards)) else: self.selected_category = list(self.cards.keys())[int(resp)] self.current_cards = random.sample(self.cards[self.selected_category], len(self.cards[self.selected_category])) def parse_cards(self): for root, dirs, files in os.walk("."): for file_name in files: file_path = os.path.join(root, file_name) if '.tsv' in file_path: with open(file_path, 'r') as f: reader = csv.reader(f, delimiter="\t") for idx, row in enumerate(reader): if idx == 0: self.cards[row[0]] = [] self.cards[row[0]].append(row[1:]) self.cards = dict(sorted(self.cards.items())) def loop(self): while True: self.card_screen() key = self.get_key() if key == "k": self.flip_card() elif key == "j": self.flip_card() elif key == "l": self.next_card() elif key == "h": self.prev_card() elif key == "d": self.add_difficult_card() elif key == "x": self.rm_difficult_card() elif key == "c": self.select_category() elif key == "q": break def next_card(self): if self.current_card_index < len(self.current_cards) - 1: self.current_card_index += 1 def prev_card(self): if self.current_card_index > 0: self.current_card_index -= 1 def add_difficult_card(self): if self.current_cards[self.current_card_index] not in self.difficult_cards: print("adding card...") self.save_difficult_cards() self.difficult_cards.append(self.current_cards[self.current_card_index]) def rm_difficult_card(self): print("removing card...") self.save_difficult_cards() discarded = self.current_cards.pop(self.current_card_index) self.difficult_cards.remove(discarded) if self.current_card_index > len(self.difficult_cards) - 1: self.current_card_index = len(self.difficult_cards) - 1 if len(self.difficult_cards) == 0: self.current_card_index = 0 self.side = 0 self.select_category() def card_screen(self): self.clear() print(f"{self.selected_category} | {self.current_card_index + 1}/{len(self.current_cards)} | DC {len(self.difficult_cards)} {'*' if self.current_cards[self.current_card_index] in self.difficult_cards else ''}") print('----------------------------------------------\n') print(self.current_cards[self.current_card_index][self.side]) print('\n\n\n\n') print('vim keys to move cards | q: quit | c: change category') print('d: add to difficult cards | x: remove from difficult cards') def flip_card(self): if self.side == 0: self.side = 1 else: self.side = 0 if __name__ == "__main__": f = Flashcards() f.main()