diff --git a/cogs/school.py b/cogs/school.py index 72fd9a4..89e68fe 100644 --- a/cogs/school.py +++ b/cogs/school.py @@ -1,12 +1,12 @@ import random -from data import constants, schedule +from data import constants from decorators import help import discord from discord.ext import commands from enums.courses import years from enums.help_categories import Category -from functions import checks, eten, les, les_rework +from functions import checks, eten, les import json @@ -44,9 +44,7 @@ class School(commands.Cog): @commands.command(name="Les", aliases=["Class", "Classes", "Sched", "Schedule"], usage="[Jaargang]* [Dag]*") # @commands.check(checks.allowedChannels) @help.Category(category=Category.School) - async def les(self, ctx, day=None): - date = les_rework.find_target_date(day) - s = schedule.Schedule(date, day is not None) + async def les(self, ctx, *day): return # parsed = les.parseArgs(day) # diff --git a/data/schedule.py b/data/schedule.py index b661ff3..45cdcd2 100644 --- a/data/schedule.py +++ b/data/schedule.py @@ -1,37 +1,39 @@ -import dacite +import json from dacite import from_dict from dataclasses import dataclass, field from datetime import datetime, timedelta -from enums.platform import Platform, get_platform +from enums.platforms import Platforms from functions.config import get -from functions.timeFormatters import fromArray, forward_to_weekday, intToWeekday -import json from typing import Dict, Optional, List +from functions.timeFormatters import fromArray + @dataclass class Holiday: - start_date: List[int] - end_date: List[int] - start_date_parsed: datetime = field(init=False) - end_date_parsed: datetime = field(init=False) + start_list: List[int] + end_list: List[int] + start_date: datetime = field(init=False) + end_date: datetime = field(init=False) duration: timedelta = field(init=False) def __post_init__(self): - self.start_date_parsed = fromArray(self.start_date) - self.end_date_parsed = fromArray(self.end_date) - self.duration = self.end_date_parsed - self.start_date_parsed + self.start_date = fromArray(self.start_list) + self.end_date = fromArray(self.end_list) + self.duration = self.end_date - self.start_date def has_passed(self, current_day: datetime) -> bool: """ Check if a holiday has passed already """ - return current_day > self.end_date_parsed + return current_day > self.end_date @dataclass class Course: - name: str + day: str + week: int + course_dict: Dict @dataclass @@ -50,49 +52,18 @@ class Timeslot: is_special: bool = False location: Optional[Location] = None online_link: Optional[str] = None - online_platform: Optional[Platform] = None + online_platform: Optional[Platforms] = None - @staticmethod - def from_slot_dict(slot_dict: Dict, course_dict: Dict, current_week: int): - """ - Construct a Timeslot from a dict of data - """ - if "weeks" in slot_dict and str(current_week) in slot_dict["weeks"]: - return Timeslot.special_from_dict(slot_dict, course_dict, str(current_week)) - - course = Course(course_dict["course"]) - start_time = slot_dict["time"]["start"] - end_time = slot_dict["time"]["end"] - - # Location can be none if a class is online-only - location = dacite.from_dict(Location, slot_dict["location"]) if "location" in slot_dict else None - - # Find platform & link if this class is online - online_platform: Platform = get_platform(slot_dict.get("online", None)) - online_link = course_dict["online_links"][Platform.value["rep"]] if online_platform is not None else None - - return Timeslot(course=course, start_time=start_time, end_time=end_time, canceled=False, is_special=False, - location=location, online_platform=online_platform, online_link=online_link) - - @staticmethod - def special_from_dict(slot_dict: Dict, course_dict: Dict, current_week: str): - """ - Create a SPECIAL Timeslot from a dict and data - """ - course = Course(course_dict["course"]) - # TODO @dataclass class Schedule: day: datetime - targetted_weekday: bool = False schedule_dict: Dict = field(init=False) - start_date: datetime = field(init=False) - end_date: datetime = field(init=False) + start_date: datetime + end_date: datetime semester_over: bool = False holiday_offset: int = 0 current_holiday: Optional[Holiday] = None - _weekday_str: str = field(init=False) def __post_init__(self): self.schedule_dict: Dict = self.load_schedule_file() @@ -106,23 +77,9 @@ class Schedule: self.check_holidays() - # TODO show a custom embed when no class instead of fast-forwarding - # # Store the target weekday (in case it exists) so we can ask for the next - # # friday after the holiday, for example - # target_weekday = -1 if not self.targetted_weekday else self.day.weekday() - # - # # Show schedule for after holidays - # if self.current_holiday is not None: - # # Set day to day after holiday - # self.day = self.current_holiday.end_date_parsed + timedelta(days=1) - # - # # Find the next [DAY] after the holidays - # if target_weekday != -1: - # self.day = forward_to_weekday(self.day, target_weekday) - - self._weekday_str = intToWeekday(self.day.weekday()) - - print(self.day) + # Show schedule for after holidays + if self.current_holiday is not None: + self.day = self.current_holiday.end_date + timedelta(days=1) def check_holidays(self): """ @@ -132,23 +89,23 @@ class Schedule: holiday: Holiday = from_dict(Holiday, hol_entry) # Hasn't happened yet, don't care - if holiday.start_date_parsed > self.day: + if holiday.start_date > self.day: continue # In the past: add the offset if holiday.has_passed(self.day): - self.holiday_offset += (self.day - holiday.end_date_parsed) // 7 - elif holiday.start_date_parsed <= self.day <= holiday.end_date_parsed: + self.holiday_offset += (self.day - holiday.end_date) // 7 + elif holiday.start_date <= self.day <= holiday.end_date: self.current_holiday = holiday def load_schedule_file(self) -> Dict: """ Load the schedule from the JSON file """ - semester = get_platform("semester") - year = get_platform("year") + semester = get("semester") + year = get("year") - with open(f"files/schedules/{year}{semester}.json", "r") as fp: + with open(f"files/{year}{semester}.json", "r") as fp: return json.load(fp) def get_week(self) -> int: @@ -164,29 +121,8 @@ class Schedule: # Add +1 at the end because week 1 would be 0 as it's not over yet return (diff.days // 7) + self.holiday_offset + 1 - def find_slots_for_course(self, course_dict: Dict, current_week: int) -> List[Timeslot]: - """ - Create time timeslots for a course - """ - slots_today = [] - - # First create a list of all slots of today - for slot in course_dict["slots"]: - # This slot is for a different day - if slot["time"]["day"] != self._weekday_str.lower(): - continue - - slots_today.append(slot) - - # Create Timeslots - slots_today = list(map(lambda x: Timeslot.from_slot_dict(x, course_dict, current_week), slots_today)) - - return slots_today - def create_schedule(self): """ Create the schedule for the current week """ week: int = self.get_week() - slots: List[List[Timeslot]] = [self.find_slots_for_course(course, week) for course in self.schedule_dict["schedule"]] - slots_flattened = [item for sublist in slots for item in sublist] diff --git a/enums/platform.py b/enums/platforms.py similarity index 52% rename from enums/platform.py rename to enums/platforms.py index b9a9520..7de21c1 100644 --- a/enums/platform.py +++ b/enums/platforms.py @@ -1,8 +1,7 @@ from enum import Enum -from typing import Optional -class Platform(Enum): +class Platforms(Enum): """ An Enum to represent online class platforms Name: The name of the platform @@ -12,17 +11,3 @@ class Platform(Enum): MSTeams = {"name": "MS Teams", "rep": "msteams"} Ufora = {"name": "Ufora", "rep": "ufora"} Zoom = {"name": "Zoom", "rep": "zoom"} - - -def get_platform(rep: Optional[str]) -> Optional[Platform]: - """ - Find the platform that corresponds to the given name - """ - if rep is None: - return None - - for platform in Platform: - if platform.value["rep"] == rep: - return platform - - return None diff --git a/files/config.json b/files/config.json index 3d513ac..dd9aec4 100644 --- a/files/config.json +++ b/files/config.json @@ -1 +1 @@ -{"semester": "1", "year": "3", "years": 3, "jpl": 161733, "jpl_day": 24} \ No newline at end of file +{"semester": "2", "year": "2", "years": 2, "jpl": 161733, "jpl_day": 24} \ No newline at end of file diff --git a/files/schedules/31.json b/files/schedules/31.json deleted file mode 100644 index 605459c..0000000 --- a/files/schedules/31.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "semester_start": [1, 7, 2021], - "semester_end": [16, 8, 2021], - "holidays": [ - { - "start_date": [2, 7, 2021], - "end_date": [10, 8, 2021] - } - ], - "schedule": [ - { - "course": "Computerarchitectuur", - "online_links": { - "zoom": "https://ufora.ugent.be/d2l/ext/rp/228912/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826", - "msteams": "https://teams.microsoft.com/l/team/19%3ad7295f0bc4634a61b461504d4a7134b3%40thread.tacv2/conversations?groupId=8755cb96-1ef5-4ea3-b806-eeebf8a85ae8&tenantId=d7811cde-ecef-496c-8f91-a1786241b99c" - }, - "slots": [ - ] - }, - { - "course": "Multimedia", - "online_links": { - "zoom": "https://ugent-be.zoom.us/j/94248831947?pwd=ZCt4UnBLSzViZnFEQmkzWE5SYnF2QT09" - }, - "slots": [ - { - "location": { - "campus": "Sterre", - "building": "S9", - "room": "A3" - }, - "time": { - "day": "woensdag", - "start": 1130, - "end": 1330 - } - }, - { - "online": "ZOOM", - "time": { - "day": "vrijdag", - "start": 1300, - "end": 1530 - } - } - ] - }, - { - "course": "Wetenschappelijk Rekenen", - "online_links": { - "zoom": "https://ufora.ugent.be/d2l/ext/rp/236404/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826" - }, - "slots": [ - { - "online": "ZOOM", - "time": { - "day": "dinsdag", - "start": 1130, - "end": 1300 - } - }, - { - "online": "ZOOM", - "time": { - "day": "woensdag", - "start": 1500, - "end": 1800 - } - }, - { - "online": "ZOOM", - "time": { - "day": "donderdag", - "start": 830, - "end": 1000 - } - } - ] - }, - { - "course": "Software Engineering Lab 1", - "online_links": { - "zoom": "https://ufora.ugent.be/d2l/ext/rp/235800/lti/framedlaunch/556e197e-e87b-4c27-be5d-53adc7a41826", - "msteams": "https://teams.microsoft.com/l/team/19%3a4dfd5b2fb1ae4aa9b72706aa3a0d6867%40thread.tacv2/conversations?groupId=256d5c58-5d53-43f5-9436-497b0c852c75&tenantId=d7811cde-ecef-496c-8f91-a1786241b99c" - }, - "slots": [ - { - "online": "MS Teams", - "time": { - "day": "dinsdag", - "start": 1430, - "end": 1700 - } - }, - { - "online": "MS Teams", - "time": { - "day": "vrijdag", - "start": 830, - "end": 1130 - } - } - ] - }, - { - "course": "Webdevelopment", - "online_links": { - "zoom": "https://ugent-be.zoom.us/j/93166767783?pwd=MWdvb1BnNnlPSnAyNk52QmRzdjcwdz09" - }, - "slots": [ - { - "weeks": { - "1": { - "canceled": true - } - }, - "location": { - "campus": "Sterre", - "building": "S9", - "room": "A3" - }, - "time": { - "day": "woensdag", - "start": 900, - "end": 1100 - } - }, - { - "online": "ZOOM", - "time": { - "day": "donderdag", - "start": 1000, - "end": 1300 - } - } - ] - } - ] -} \ No newline at end of file diff --git a/functions/les_rework.py b/functions/les_rework.py index 3c96154..6646a4a 100644 --- a/functions/les_rework.py +++ b/functions/les_rework.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta -from functions.timeFormatters import dateTimeNow, weekdayToInt, forward_to_weekday, skip_weekends +from timeFormatters import dateTimeNow, weekdayToInt from typing import Optional @@ -24,8 +24,35 @@ def find_target_date(arg: Optional[str]) -> datetime: elif arg.lower() == "overmorgen": # Day after tomorrow's schedule day += timedelta(days=2) - # TODO show a different embed when "(over)morgen" is requested & it lands on a weekend # Don't land on a weekend day = skip_weekends(day) return day + + +def skip_weekends(day: datetime) -> datetime: + """ + Increment the current date if it's not a weekday + """ + weekday = day.weekday() + + # Friday is weekday 4 + if weekday > 4: + return day + timedelta(days=(7 - weekday)) + + return day + + +def forward_to_weekday(day: datetime, weekday: int) -> datetime: + """ + Increment a date until the weekday is the same as the one provided + Finds the "next" [weekday] + """ + current = day.weekday() + + # This avoids negative numbers below, and shows + # next week in case the days are the same + if weekday >= current: + weekday += 7 + + return day + timedelta(days=(weekday - current)) diff --git a/functions/timeFormatters.py b/functions/timeFormatters.py index 3d49476..58e6712 100644 --- a/functions/timeFormatters.py +++ b/functions/timeFormatters.py @@ -138,15 +138,13 @@ def getPlural(amount, unit): return dic[unit.lower()]["s" if amount == 1 else "p"] -def weekdayToInt(day: str) -> int: +def weekdayToInt(day) -> int: days = {"maandag": 0, "dinsdag": 1, "woensdag": 2, "donderdag": 3, "vrijdag": 4, "zaterdag": 5, "zondag": 6} - # Allow abbreviations - for d, i in days.items(): - if d.startswith(day): - return i + if day.lower() not in days: + return -1 - return -1 + return days[day.lower()] def intToWeekday(day): @@ -166,31 +164,3 @@ def fromArray(data: List[int]) -> datetime: year = str(data[2]) return fromString(f"{day}/{month}/{year}") - - -def skip_weekends(day: datetime) -> datetime: - """ - Increment the current date if it's not a weekday - """ - weekday = day.weekday() - - # Friday is weekday 4 - if weekday > 4: - return day + datetime.timedelta(days=(7 - weekday)) - - return day - - -def forward_to_weekday(day: datetime, weekday: int) -> datetime: - """ - Increment a date until the weekday is the same as the one provided - Finds the "next" [weekday] - """ - current = day.weekday() - - # This avoids negative numbers below, and shows - # next week in case the days are the same - if weekday <= current: - weekday += 7 - - return day + datetime.timedelta(days=(weekday - current))