Skip to content

Commit

Permalink
Added the option to filter full or locked parallels
Browse files Browse the repository at this point in the history
  • Loading branch information
antoninkriz committed Sep 4, 2023
1 parent 13a08ae commit e894acb
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 8 deletions.
50 changes: 46 additions & 4 deletions ctu-timetable-generator/src/app/generator/_menuForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useContext } from 'react';
import {
Alert,
AlertIcon,
AlertTitle,
AlertTitle, Box,
Button,
Checkbox,
Code,
Expand Down Expand Up @@ -30,7 +30,7 @@ import { Link } from '@chakra-ui/next-js';
import { AsyncSelect, Select } from 'chakra-react-select';
import type { SWRResponse } from 'swr';
import type {
Course, Data,
Course, CourseAvailableOnly, Data,
} from '@src/types';
import { OptionClass, ParallelType } from '@src/types';
import { GITHUB_URL } from '@src/consts';
Expand Down Expand Up @@ -58,6 +58,10 @@ type FormComponentProps = {
setCourses: (courses: Array<Course>) => void
preferences: { [courseId: string]: { [parallelType in ParallelType]: boolean } }
setPreferences: (courseId: string, parallelType: ParallelType, value: boolean) => void
allowLocked: CourseAvailableOnly
setAllowLocked: (courseId: string, value: boolean) => void
allowFull: CourseAvailableOnly
setAllowFull: (courseId: string, value: boolean) => void
computeCallback: () => void
disabled: boolean
};
Expand All @@ -70,6 +74,10 @@ function FormComponent({
setCourses,
preferences,
setPreferences,
allowLocked,
setAllowLocked,
allowFull,
setAllowFull,
computeCallback,
disabled,
onCloseMenu = () => {},
Expand All @@ -94,7 +102,7 @@ function FormComponent({
const optionsCourses = data && semester !== undefined ? data[semester].map((course) => new OptionClass(course, `${course.code} | ${course.name}`)) : [];

const paddingCellX = {
base: 2,
base: 1,
md: 4,
};

Expand Down Expand Up @@ -150,6 +158,8 @@ function FormComponent({
<Th px={paddingCellX}>Přednášky</Th>
<Th px={paddingCellX}>Cvičení</Th>
<Th px={paddingCellX}>Laboratoře</Th>
<Th px={paddingCellX}><Tooltip label={<Box textAlign="center">Brát v potaz i paralelky,<br />které nemají povolenou registraci</Box>}>🔒</Tooltip></Th>
<Th px={paddingCellX}><Tooltip label={<Box textAlign="center">Brát v potaz i paralelky,<br />které jsou již naplněné</Box>}>🔋</Tooltip></Th>
</Tr>
</Thead>
<Tbody>
Expand Down Expand Up @@ -186,6 +196,22 @@ function FormComponent({
/>
)}
</Td>
<Td px={paddingCellX}>
<Checkbox
defaultChecked
checked={allowLocked[course.code]}
onChange={(e) => setAllowLocked(course.code, e.target.checked)}
isDisabled={disabled}
/>
</Td>
<Td px={paddingCellX}>
<Checkbox
defaultChecked
checked={allowFull[course.code]}
onChange={(e) => setAllowFull(course.code, e.target.checked)}
isDisabled={disabled}
/>
</Td>
</Tr>
))}
</Tbody>
Expand Down Expand Up @@ -216,11 +242,15 @@ export function MenuSide({
setCourses,
preferences,
setPreferences,
allowLocked,
setAllowLocked,
allowFull,
setAllowFull,
computeCallback,
disabled,
}: FormComponentProps) {
return (
<Flex display={{ base: 'none', xl: 'block' }} w="lg" shadow="md">
<Flex display={{ base: 'none', xl: 'block' }} w="xl" shadow="md">
<Stack w="full" h="full" flex={1} spacing={6} p={6}>
<FormComponent
dataResponse={dataResponse}
Expand All @@ -230,6 +260,10 @@ export function MenuSide({
setCourses={setCourses}
preferences={preferences}
setPreferences={setPreferences}
allowLocked={allowLocked}
setAllowLocked={setAllowLocked}
allowFull={allowFull}
setAllowFull={setAllowFull}
computeCallback={computeCallback}
disabled={disabled}
/>
Expand All @@ -246,6 +280,10 @@ export function MenuDrawer({
setCourses,
preferences,
setPreferences,
allowLocked,
setAllowLocked,
allowFull,
setAllowFull,
computeCallback,
disabled,
}: FormComponentProps) {
Expand All @@ -267,6 +305,10 @@ export function MenuDrawer({
setCourses={setCourses}
preferences={preferences}
setPreferences={setPreferences}
allowLocked={allowLocked}
setAllowLocked={setAllowLocked}
allowFull={allowFull}
setAllowFull={setAllowFull}
computeCallback={computeCallback}
disabled={disabled}
onCloseMenu={onClose}
Expand Down
5 changes: 4 additions & 1 deletion ctu-timetable-generator/src/app/generator/_worker/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ addEventListener('message', async (event: MessageEvent<MessageData>) => {
// Get courses sorted by the number of their parallels and filter out the parallels based on preferences
const coursesSelected = Object.entries(event.data.preferences).map(([courseId, preferences]) => ({
...courses[courseId],
parallels: courses[courseId].parallels.filter((parallel) => preferences[parallel.type]),
parallels: courses[courseId].parallels
.filter((parallel) => preferences[parallel.type])
.filter((parallel) => event.data.allowFull[courseId] || !parallel.is_full)
.filter((parallel) => event.data.allowLocked[courseId] || parallel.can_register),
})).sort((a, b) => (a.parallels.length - b.parallels.length) || (a.code.localeCompare(b.code)));

const compactCourses = coursesSelected.map((course) => ({
Expand Down
49 changes: 46 additions & 3 deletions ctu-timetable-generator/src/app/generator/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { arrayDifference, useToastDataWrapper } from '@src/app/generator/lib';
import type {
Course, CoursePreferences, MessageData, MessageResult,
} from '@src/types';
import { MessageResultTypes, ParallelType } from '@src/types';
import { CourseAvailableOnly, MessageResultTypes, ParallelType } from '@src/types';
import { MenuDrawer, MenuSide } from '@src/app/generator/_menuForm';
import { ProgressBar } from '@src/app/generator/_progress';
import { TimeTable } from '@src/app/generator/_timeTable';
Expand Down Expand Up @@ -57,11 +57,14 @@ export default function Generator() {
const [semester, setSemester] = useState<string | undefined>(undefined);
const [courses, setCourses] = useState<Array<Course>>([]);
const [preferences, setPreferences] = useState<CoursePreferences>({});
const [allowLocked, setAllowLocked] = useState<CourseAvailableOnly>({});
const [allowFull, setAllowFull] = useState<CourseAvailableOnly>({});
const setCoursesUpdatePreferences = (coursesNew: Array<Course>) => {
const diffAdded = arrayDifference(coursesNew, courses);
const diffRemoved = arrayDifference(courses, coursesNew);

setPreferences((p) => {
if (coursesNew.length === 0) return {};
const diffAdded = arrayDifference(coursesNew, courses);
const diffRemoved = arrayDifference(courses, coursesNew);

const res = diffAdded.reduce((obj, course) => {
obj[course.code] = {
Expand All @@ -79,6 +82,28 @@ export default function Generator() {
return res;
});
setCourses(coursesNew);
setAllowLocked((a) => {
const res = diffAdded.reduce((obj, course) => {
obj[course.code] = true;
return obj;
}, { ...a });
for (const courseRemoved of diffRemoved) {
delete res[courseRemoved.code];
}

return res;
});
setAllowFull((a) => {
const res = diffAdded.reduce((obj, course) => {
obj[course.code] = true;
return obj;
}, { ...a });
for (const courseRemoved of diffRemoved) {
delete res[courseRemoved.code];
}

return res;
});
};
const preferencesUpdate = (courseId: string, parallelType: ParallelType, value: boolean) => setPreferences((p) => ({
...p,
Expand All @@ -87,6 +112,14 @@ export default function Generator() {
[parallelType]: value,
},
}));
const allowFullUpdate = (courseId: string, value: boolean) => setAllowFull((a) => ({
...a,
[courseId]: value,
}));
const allowLockedUpdate = (courseId: string, value: boolean) => setAllowLocked((a) => ({
...a,
[courseId]: value,
}));

const computeCallback = () => {
if (dataResponse.data && semester) {
Expand All @@ -95,6 +128,8 @@ export default function Generator() {
postMessage({
semester: dataResponse.data[semester],
preferences,
allowLocked,
allowFull,
});
}
};
Expand Down Expand Up @@ -135,6 +170,10 @@ export default function Generator() {
setCourses={setCoursesUpdatePreferences}
preferences={preferences}
setPreferences={preferencesUpdate}
allowLocked={allowLocked}
setAllowLocked={allowLockedUpdate}
allowFull={allowFull}
setAllowFull={allowFullUpdate}
computeCallback={computeCallback}
disabled={isComputing}
/>
Expand All @@ -150,6 +189,10 @@ export default function Generator() {
setCourses={setCoursesUpdatePreferences}
preferences={preferences}
setPreferences={preferencesUpdate}
allowLocked={allowLocked}
setAllowLocked={allowLockedUpdate}
allowFull={allowFull}
setAllowFull={allowFullUpdate}
computeCallback={computeCallback}
disabled={isComputing}
/>
Expand Down
9 changes: 9 additions & 0 deletions ctu-timetable-generator/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export type Parallel = {
type: ParallelType
num: number | null
capacity: number | null
occupied_places: number | null
timetable: Array<Event>
can_register: boolean
is_full: boolean
};

export type ParallelCompact = Omit<Parallel, 'capacity' | 'timetable'> & {
Expand Down Expand Up @@ -75,6 +78,10 @@ export type CoursePreferences = {
}
};

export type CourseAvailableOnly = {
[classId: string]: boolean
};

export class OptionClass<T> {
value: T;

Expand All @@ -90,6 +97,8 @@ export class OptionClass<T> {
export type MessageData = {
semester: Semester
preferences: CoursePreferences
allowLocked: CourseAvailableOnly
allowFull: CourseAvailableOnly
};

export const enum MessageResultTypes {
Expand Down

0 comments on commit e894acb

Please sign in to comment.