didier/data/courses.py

68 lines
1.8 KiB
Python

from dataclasses import dataclass
from typing import Optional
import dacite
import json
from os import path
@dataclass
class Course:
abbreviations: list[str]
code: str
name: str
year: int
alt: Optional[str] = None
def load_courses() -> dict[str, Course]:
"""Create a list of all courses"""
# Allows testing
filepath = path.join(path.dirname(__file__), "..", "files", "courses.json")
with open(filepath, "r") as file:
data = json.load(file)
courses = {}
for course_name in data:
# Add name into the dict to allow flexibility
course_data = data[course_name]
course_data["name"] = course_name
courses[course_name] = dacite.from_dict(data_class=Course, data=course_data)
return courses
def find_course_from_name(name: str, courses: Optional[dict[str, Course]] = None, case_insensitive: bool = True) -> Optional[Course]:
# Allow passing a course dict in to avoid having to create it all the time
if courses is None:
courses = load_courses()
if case_insensitive:
name = name.lower()
def _perhaps_lower(inp: str) -> str:
"""Cast a string to lowercase if necessary"""
if case_insensitive:
return inp.lower()
return inp
# Iterate over all courses to look for a match
for course_name, course in courses.items():
# Check name first
if _perhaps_lower(course_name) == name:
return course
# Then abbreviations
for abbreviation in course.abbreviations:
if _perhaps_lower(abbreviation) == name:
return course
# Finally alternative names
if course.alt is not None and _perhaps_lower(course.alt) == name:
return course
return None