Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Judge dashboard change and debug #501

Merged
merged 13 commits into from
Sep 17, 2024
Merged
49 changes: 25 additions & 24 deletions components/Organizer/ScheduleTab/ScheduleTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,26 @@ const ScheduleTab = () => {
const [timesJudged, setTimesJudged] = useState<number>(1);
const [maxTimesJudged, setMaxTimesJudged] = useState<number>(0);
const [potentialSchedule, setPotentialSchedule] = useState<JudgingSessionData[] | undefined>(undefined);
const [hackathonSettings, setHackathonSettings] = useState<HackathonSettingsData | undefined>(undefined);

const { baseTheme } = useContext(ThemeContext);

// Get hackathon settings
useEffect(() => {
const fetchHackathonSettings = async () => {
const res = await fetch('/api/hackathon-settings');
if (res.ok) {
const settings = await res.json();
setHackathonSettings(settings as HackathonSettingsData);
}
};
fetchHackathonSettings();
}, []);

const TimeForJudgeToScoreOneTeam = parseInt(hackathonSettings?.JUDGING_TIME_PER_TEAM as string, 10);
const JudgingDuration = hackathonSettings?.JUDGING_DURATION as number;
const MaximumNumberOfTeamsOneJudgeCanFinishInJudgingTime = JudgingDuration / TimeForJudgeToScoreOneTeam;

// Get judging sessions
const { data: judgingSessions, error: judgingSessionsError } = useCustomSWR<JudgingSessionData[]>({
url: '/api/judging-sessions',
Expand All @@ -37,13 +54,6 @@ const ScheduleTab = () => {
errorMessage: 'Failed to get list of teams.',
});

// Get hackathon settings
const { data: hackathonSettings, error: hackathonError } = useCustomSWR<HackathonSettingsData>({
url: '/api/hackathon-settings',
method: RequestType.GET,
errorMessage: 'Failed to get hackathon times.',
});

// Confirm potential schedule
const handleConfirmPotentialSchedules = (potentialSchedule: JudgingSessionData[] | undefined) => {
// Exit early if we don't have data yet
Expand All @@ -67,33 +77,23 @@ const ScheduleTab = () => {
let judgingTimes = generateTimes(
new Date(hackathonSettings?.JUDGING_START as string),
new Date(hackathonSettings?.JUDGING_END as string),
10
TimeForJudgeToScoreOneTeam
);
setPotentialSchedule(matchTeams(teams, judges, judgingTimes, timesJudged));
};

useEffect(() => {
if (!teamsData || !judgesData) return;
setMaxTimesJudged(Math.floor((judgesData?.length * 12) / teamsData?.length));
}, [teamsData, judgesData]);
setMaxTimesJudged(
Math.floor((judgesData?.length * MaximumNumberOfTeamsOneJudgeCanFinishInJudgingTime) / teamsData?.length)
);
}, [teamsData, judgesData, hackathonSettings]);

useEffect(() => {
// Exit early if we don't have data yet
if (!judgingSessions) return;

// Sort judging sessions by time
const time = new Date('2022-10-23T11:00:00').getTime();

// Set the data after filtering it by time
setPotentialSchedule(
judgingSessions.filter(judgingSession => {
let time = new Date(judgingSession.time as string);
return (
new Date(hackathonSettings?.JUDGING_START as string) <= time &&
time <= new Date(hackathonSettings?.JUDGING_END as string)
);
})
);
// Set the data
setPotentialSchedule(judgingSessions);
}, [judgingSessions, hackathonSettings]);

// Combine all the loading, null, and error states
Expand Down Expand Up @@ -162,6 +162,7 @@ const ScheduleTab = () => {
handleChange={function (value: SetStateAction<string>): void {
throw new Error('Function not implemented.');
}}
TimeForJudgeToScoreOneTeam={TimeForJudgeToScoreOneTeam}
sessionTimeStart={new Date(hackathonSettings?.JUDGING_START as string)}
sessionTimeEnd={new Date(hackathonSettings?.JUDGING_END as string)}
/>
Expand Down
33 changes: 28 additions & 5 deletions components/Organizer/SettingsTab/HackathonSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, DatePicker, Select, Space } from 'antd';
import { Button, DatePicker, Input, Select, Space } from 'antd';
import dayjs from 'dayjs';
import React, { useContext, useEffect, useState } from 'react';
import { handleSubmitFailure, handleSubmitSuccess } from '../../../lib/helpers';
Expand Down Expand Up @@ -89,6 +89,7 @@ const HackathonSettings = () => {
setHackathonSetting(settings as HackathonSettingsData);
setStatusMessage('Successfully saved to database!');
handleSubmitSuccess('Successfully saved to database!');
window.location.reload();
} else {
setStatusMessage('Failed to save to database!');
handleSubmitFailure('Failed to save to database!');
Expand All @@ -114,14 +115,16 @@ const HackathonSettings = () => {
};

const handleJudgingChange = (_: any, dateStrings: [string, string]) => {
const newJudgingStart = dayjs(dateStrings[0], { utc: true }).format('MM/DD/YYYY hh:mm A');
const newJudgingEnd = dayjs(dateStrings[1], { utc: true }).format('MM/DD/YYYY hh:mm A');
const newJudgingStart = dayjs(dateStrings[0], { utc: true });
const newJudgingEnd = dayjs(dateStrings[1], { utc: true });
const judgingDuration = newJudgingEnd.diff(newJudgingStart, 'minute');
setHackathonSetting(prev => {
if (prev)
return {
...prev,
JUDGING_START: newJudgingStart,
JUDGING_END: newJudgingEnd,
JUDGING_START: newJudgingStart.format('MM/DD/YYYY hh:mm A'),
JUDGING_END: newJudgingEnd.format('MM/DD/YYYY hh:mm A'),
JUDGING_DURATION: judgingDuration,
};
return undefined;
});
Expand Down Expand Up @@ -161,6 +164,26 @@ const HackathonSettings = () => {
defaultValue={[dayjs(hackathonSetting?.JUDGING_START), dayjs(hackathonSetting?.JUDGING_END)]}
/>

<br />

<div>Time for Judge to Score One Team (minutes):</div>
<Input
value={hackathonSetting?.JUDGING_TIME_PER_TEAM}
onChange={e => {
setHackathonSetting(prev => {
if (prev) {
return {
...prev,
JUDGING_TIME_PER_TEAM: e.target.value,
};
}
return prev;
});
}}
placeholder="Enter time in minutes"
style={{ width: 138 }}
/>

<br />
<br />

Expand Down
2 changes: 1 addition & 1 deletion components/hacker/HackerDash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ export default function HackerDash({ userApplicationStatus, setUserApplicationSt
<div style={{ padding: '20px' }}>
<Header user={user} signOut={signOut} setting={setting as HackathonSettingsData} />

<TeamManagement />
{/* <TeamManagement /> */}
<JudgingSchedule judgingSessionData={judgingSessionData} />
<Leaderboard />

Expand Down
8 changes: 3 additions & 5 deletions components/hacker/JudgingSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,25 +34,23 @@ const JudgingSchedule = ({ judgingSessionData }: JudgingScheduleProps) => {
return (
<div className={styles.Container}>
Judging Schedule
<div className={styles.Description}>
You will be assigned a table and judge for judging. Please be at your table at the time indicated below.
</div>
<div className={styles.Description}>You will be assigned a table and judge for judging.</div>
{judgingSessionData?.length === 0 ? (
<div className={styles.Placeholder}>Schedule will show up here when hacking ends!</div>
) : (
<div className={styles.TableContainer}>
<table>
<thead>
<tr>
<th>Time</th>
{/* <th>Time</th> */}
<th>Table</th>
<th>Judge</th>
</tr>
</thead>
<tbody>
{judgingSessionData?.map(entry => (
<tr key={entry.time.toString()}>
<td>{renderJudgingTime(entry.time.toString())}</td>
{/* <td>{renderJudgingTime(entry.time.toString())}</td> */}
<td>{entry.team.locationNum}</td>
<td>{entry.judge.name}</td>
</tr>
Expand Down
52 changes: 2 additions & 50 deletions components/judges/JudgeDash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ async function handleSubmit(
mutate('/api/teams');
mutate('/api/judging-form');
handleSubmitSuccess(`Successfully ${isNewForm ? 'submitted' : 'updated'}!`);
if (isNewForm) window.location.reload();
setIsNewForm(false);
} else {
handleSubmitFailure(await res.text());
Expand All @@ -54,8 +55,6 @@ async function handleSubmit(
export default function JudgeDash() {
const { data: session, status } = useSession();
const [teamID, setTeamID] = useState('');
const [currentScheduleItem, setCurrentScheduleItem] = useState<JudgingSessionData | undefined>(undefined);
const [nextScheduleItem, setNextScheduleItem] = useState<JudgingSessionData | undefined>(undefined);
const [isNewForm, setIsNewForm] = useState(false);
const [nextIndex, setNextIndex] = useState(-1);
const { mutate } = useSWRConfig();
Expand Down Expand Up @@ -132,51 +131,6 @@ export default function JudgeDash() {
return (await res.json()) as JudgingSessionData[];
});

// Initialize state if data was just received
useEffect(() => {
if (nextIndex === -1 && scheduleData) {
const now = Date.now();
let index = scheduleData.findIndex(el => now < new Date(el.time as string).getTime());
if (index === -1) index = scheduleData.length;
let currentlyGoingTime = new Date(scheduleData[index - 1]?.time as string).getTime() + judgingLength;
setNextScheduleItem(scheduleData[index]);
setCurrentScheduleItem(now < currentlyGoingTime ? scheduleData[index - 1] : undefined);
setNextIndex(index);
}
}, [scheduleData, nextIndex, judgingLength]);

// Loop to manage current schedule state
useEffect(() => {
const interval = setInterval(() => {
const now = Date.now();
if (scheduleData && nextIndex > -1) {
// Data has been received and state is initialized
let time2 = new Date(scheduleData[scheduleData.length - 1]?.time as string).getTime() + judgingLength;
if (now <= time2) {
// Not yet done judging
let time3 = new Date((currentScheduleItem?.time as string) || 0).getTime() + judgingLength;

if (
nextIndex < scheduleData.length &&
now >= new Date((nextScheduleItem?.time as string) || 0).getTime()
) {
// Next event should be current
setNextScheduleItem(scheduleData[nextIndex + 1]);
setCurrentScheduleItem(scheduleData[nextIndex]);
setNextIndex(nextIndex + 1);
} else if (now > time3) {
// Next event has not yet arrived but current event is over
setCurrentScheduleItem(undefined);
}
} else {
// Done judging
setCurrentScheduleItem(undefined);
}
}
}, 1000);
return () => clearInterval(interval);
});

const handleTeamChange: Dispatch<SetStateAction<string>> = e => {
setTeamID(e);
setTimeout(() => {
Expand Down Expand Up @@ -204,9 +158,7 @@ export default function JudgeDash() {
</div>
</div>
</div>
{scheduleData && (
<JudgeSchedule data={scheduleData} cutoffIndex={nextIndex} handleChange={handleTeamChange} />
)}
{scheduleData && <JudgeSchedule data={scheduleData} handleChange={handleTeamChange} />}
<br />
<br />
{teamsData && <TeamSelect teamsData={teamsData} currentTeamID={teamID} handleChange={handleTeamChange} />}
Expand Down
7 changes: 0 additions & 7 deletions components/judges/TeamSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,6 @@ export default function TeamSelect(props: TeamSelectProps) {
))}
</OptGroup>
)}
<OptGroup label="All Teams">
{teamsData.map(team => (
<Option value={team._id} key={`${team._id}ALL`}>
{team.haveJudged ? withCheckMark(team.name) : team.name}
</Option>
))}
</OptGroup>
</Select>
</Space>
);
Expand Down
Loading
Loading