Kiki0203's picture
Upload 13 files
f9766bc verified
"""
utils.py
Helper utilities: progress persistence, notes, topic lists, learning paths, etc.
"""
import json
import os
from datetime import date
PROGRESS_FILE = "learning_progress.json"
NOTES_FILE = "notes.json"
TOPICS = [
"Photosynthesis",
"Machine Learning",
"World War II",
"Python Functions",
"Calculus",
"Climate Change",
"The French Revolution",
"DNA Replication",
"Object-Oriented Programming",
"The Solar System",
"Economics Supply & Demand",
"Quantum Mechanics",
]
LEARNING_PATHS = {
"machine learning": ["Python Functions", "Calculus", "Economics Supply & Demand", "Machine Learning"],
"quantum mechanics": ["Calculus", "The Solar System", "Quantum Mechanics"],
"dna replication": ["Photosynthesis", "DNA Replication"],
"calculus": ["Python Functions", "Calculus"],
"object-oriented programming": ["Python Functions", "Object-Oriented Programming"],
"climate change": ["Photosynthesis", "Economics Supply & Demand", "Climate Change"],
}
def get_topics() -> list:
return sorted(TOPICS)
def load_progress() -> dict:
"""Load progress from JSON file, or return empty structure."""
if os.path.exists(PROGRESS_FILE):
try:
with open(PROGRESS_FILE, "r") as f:
return json.load(f)
except (json.JSONDecodeError, IOError):
pass
return {
"topics_studied": [],
"scores": [],
"best_score": 0,
"topic_scores": {}, # {topic: best_score_int}
"sessions": [], # [{topic, score, date}]
}
def save_progress(progress: dict, topic: str = None, score: int = None) -> None:
"""Update and persist progress data."""
if "topic_scores" not in progress:
progress["topic_scores"] = {}
if "sessions" not in progress:
progress["sessions"] = []
if topic:
studied = progress.get("topics_studied", [])
if topic not in studied:
studied.append(topic)
progress["topics_studied"] = studied
if score is not None:
scores = progress.get("scores", [])
scores.append(score)
progress["scores"] = scores
if score > progress.get("best_score", 0):
progress["best_score"] = score
# Per-topic best score (store single int, not list)
if topic:
ts = progress["topic_scores"]
existing = ts.get(topic, 0)
# Handle legacy list format
if isinstance(existing, list):
existing = max(existing) if existing else 0
ts[topic] = max(existing, score)
progress["topic_scores"] = ts
# Session log
sessions = progress.get("sessions", [])
sessions.append({
"topic": topic or "Unknown",
"score": score,
"date": str(date.today())
})
progress["sessions"] = sessions
try:
with open(PROGRESS_FILE, "w") as f:
json.dump(progress, f, indent=2)
except IOError:
pass
def get_weak_topics(progress: dict) -> list:
"""Return topics where the best score is below 60%."""
result = []
for topic, score in progress.get("topic_scores", {}).items():
# Handle legacy list format
if isinstance(score, list):
score = max(score) if score else 0
if score < 60:
result.append(topic)
return result
def get_learning_path(topic: str) -> list:
"""Return recommended learning path for a topic, or empty list."""
return LEARNING_PATHS.get(topic.lower().strip(), [])
# ── Notes ────────────────────────────────────────────────────────────────────
def load_notes() -> list:
"""Load saved notes from JSON file."""
if os.path.exists(NOTES_FILE):
try:
with open(NOTES_FILE, "r") as f:
return json.load(f)
except (json.JSONDecodeError, IOError):
pass
return []
def save_note(note_text: str, topic: str) -> None:
"""Append a note and persist to file."""
notes = load_notes()
notes.append({
"topic": topic,
"note": note_text,
"date": str(date.today())
})
try:
with open(NOTES_FILE, "w") as f:
json.dump(notes, f, indent=2)
except IOError:
pass
def delete_note(index: int) -> None:
"""Delete a note by its index."""
notes = load_notes()
if 0 <= index < len(notes):
notes.pop(index)
try:
with open(NOTES_FILE, "w") as f:
json.dump(notes, f, indent=2)
except IOError:
pass