line height text, refactored course schedule, added string representation functions to course meeting

This commit is contained in:
Sriram Hariharan
2023-03-06 16:51:46 -06:00
parent 007ade81a0
commit 9b76f8afa0
9 changed files with 182 additions and 56 deletions

View File

@@ -72,7 +72,7 @@ export class Course {
/** Which semester is the course from */
semester: Semester;
constructor(course: Course | Serialized<Course>) {
constructor(course: Serialized<Course>) {
Object.assign(this, course);
this.schedule = new CourseSchedule(course.schedule);
}

View File

@@ -0,0 +1,128 @@
import { Serialized } from 'chrome-extension-toolkit';
/**
* a map of the days of the week that a class is taught, and the corresponding abbreviation
*/
export const DAY_MAP = {
M: 'Monday',
T: 'Tuesday',
W: 'Wednesday',
TH: 'Thursday',
F: 'Friday',
S: 'Saturday',
SU: 'Sunday',
} as const;
/** A day of the week that a class is taught */
export type Day = typeof DAY_MAP[keyof typeof DAY_MAP];
/** A physical room that a class is taught in */
export type Room = {
/** The UT building code for where the class is taught */
building: string;
/** The room number for where the class is taught */
number: string;
};
/**
* This represents one "Meeting Time" for a course, which includes the day of the week that the course is taught, the time that the course is taught, and the location that the course is taught
*/
export class CourseMeeting {
/** The day of the week that the course is taught */
days: Day[];
/** The start time of the course, in minutes since midnight */
startTime: number;
/** The end time of the course, in minutes since midnight */
endTime: number;
/** The location that the course is taught */
room?: Room;
constructor(meeting: Serialized<CourseMeeting>) {
Object.assign(this, meeting);
}
/**
* Return the string representation of the days of the week that this meeting is taught
* @param options options for the string representation
* @returns string representation of the days of the week that this meeting is taught
*/
getDaysString(options: DaysStringOptions): string {
let { format, separator } = options;
let { days } = this;
if (format === 'short') {
days = Object.keys(DAY_MAP).filter(day => days.includes(DAY_MAP[day as keyof typeof DAY_MAP])) as Day[];
}
if (separator === 'none') {
return days.join('');
}
const listFormat = new Intl.ListFormat('en-US', {
style: separator,
type: 'conjunction',
});
return listFormat.format(days);
}
/**
* Return the string representation of the time range for the course
* @param options options for the string representation
* @returns string representation of the time range for the course
*/
getTimeString(options: TimeStringOptions): string {
const { startTime, endTime } = this;
const startHour = Math.floor(startTime / 60);
const startMinute = startTime % 60;
const endHour = Math.floor(endTime / 60);
const endMinute = endTime % 60;
let startTimeString = '';
let endTimeString = '';
if (startHour === 0) {
startTimeString = '12';
} else if (startHour > 12) {
startTimeString = `${startHour - 12}`;
} else {
startTimeString = `${startHour}`;
}
startTimeString += startMinute === 0 ? ':00' : `:${startMinute}`;
startTimeString += startHour >= 12 ? 'pm' : 'am';
if (endHour === 0) {
endTimeString = '12';
} else if (endHour > 12) {
endTimeString = `${endHour - 12}`;
} else {
endTimeString = `${endHour}`;
}
endTimeString += endMinute === 0 ? ':00' : `:${endMinute}`;
endTimeString += endHour >= 12 ? 'pm' : 'am';
if (options.capitalize) {
startTimeString = startTimeString.toUpperCase();
endTimeString = endTimeString.toUpperCase();
}
return `${startTimeString} ${options.separator} ${endTimeString}`;
}
}
/**
* Options to control the format of the time string
*/
type TimeStringOptions = {
/** the separator between the start and end times */
separator: string;
/** capitalizes the AM/PM */
capitalize?: boolean;
};
/**
* Options to control the format of the days string
*/
type DaysStringOptions = {
/** The format of the days string, short = MWF, long = Monday, Wednesday, Friday */
format: 'short' | 'long';
separator: Intl.ListFormatStyle | 'none';
};

View File

@@ -1,61 +1,27 @@
import { Serialized } from 'chrome-extension-toolkit';
/**
* a map of the days of the week that a class is taught, and the corresponding abbreviation
*/
const DAY_MAP = {
M: 'Monday',
T: 'Tuesday',
W: 'Wednesday',
TH: 'Thursday',
F: 'Friday',
S: 'Saturday',
SU: 'Sunday',
} as const;
/** A day of the week that a class is taught */
export type Day = typeof DAY_MAP[keyof typeof DAY_MAP];
/** A physical room that a class is taught in */
export type Room = {
/** The UT building code for where the class is taught */
building: string;
/** The room number for where the class is taught */
number: string;
};
/**
* This represents one "Meeting Time" for a course, which includes the day of the week that the course is taught, the time that the course is taught, and the location that the course is taught
*/
export type CourseMeeting = {
/** The day of the week that the course is taught */
day: Day;
/** The start time of the course, in minutes since midnight */
startTime: number;
/** The end time of the course, in minutes since midnight */
endTime: number;
/** The location that the course is taught */
room?: Room;
};
import { CourseMeeting, Day, DAY_MAP } from './CourseMeeting';
/**
* This represents the schedule for a course, which includes all the meeting times for the course, as well as helper functions for parsing, serializing, and deserializing the schedule
*/
export class CourseSchedule {
meetings: CourseMeeting[];
meetings: CourseMeeting[] = [];
constructor(courseSchedule: CourseSchedule | Serialized<CourseSchedule>) {
constructor(courseSchedule?: Serialized<CourseSchedule>) {
if (!courseSchedule) {
return;
}
Object.assign(this, courseSchedule);
}
/**
* Given a string representation of a schedule, parse it into a CourseSchedule object
* Given a string representation of the meeting information for a class, parse it into a CourseMeeting object
* @param dayLine a string representation of the days of the week that the course is taught: MWF, TR, etc.
* @param timeLine a string representation of a time-range that the course is taught: 10:00 am - 11:00 am, 1:00 pm - 2:00 pm, etc.
* @param roomLine a string representation of the room that the course is taught in: JGB 2.302, etc.
* @returns an array of CourseMeeting objects, which represent the schedule for the course
* @returns CourseMeeting object representing the meeting information
*/
static parse(dayLine: string, timeLine: string, roomLine: string): CourseMeeting[] {
static parse(dayLine: string, timeLine: string, roomLine: string): CourseMeeting {
try {
let days: Day[] = dayLine
.split('')
@@ -87,15 +53,15 @@ export class CourseSchedule {
const [building, number] = roomLine.split(' ');
return days.map(day => ({
day,
return new CourseMeeting({
days,
startTime,
endTime,
room: {
building,
number,
},
}));
});
} catch (e) {
throw new Error(`Failed to parse schedule: ${dayLine} ${timeLine} ${roomLine}`);
}