koflash/flashcards.py
2026-09-21 21:25:31 -04:00

156 lines
5 KiB
Python

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