Skip to content

Commit

Permalink
bug fixes and improvements
Browse files Browse the repository at this point in the history
all scheduling should now be available for FGC 2024.
  • Loading branch information
kyle-flynn committed Aug 21, 2024
1 parent b6ddbe9 commit 7caff29
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 12 deletions.
2 changes: 1 addition & 1 deletion back-end/api/src/controllers/Match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ router.post(
matchMakerArgs,
config
);
logger.info('mathmaker complete - sending results');
logger.info('matchmaker complete - sending results');
res.send(matches);
} catch (e) {
return next(e);
Expand Down
8 changes: 5 additions & 3 deletions front-end/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion front-end/src/apps/schedules/match-gen/random-matches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Tournament,
assignMatchTimes
} from '@toa-lib/models';
import { FGCSchedule } from '@toa-lib/models';
import { FC, useState } from 'react';
import { createMatchSchedule } from 'src/api/use-match-data';
import { MatchMakerQualityDropdown } from 'src/components/dropdowns/match-maker-dropdown';
Expand Down Expand Up @@ -53,7 +54,14 @@ export const RandomMatches: FC<Props> = ({
teamKeys,
name
});
onCreateMatches(assignMatchTimes(matches, scheduleItems));
onCreateMatches(
assignMatchTimes(
eventSchedule.hasPremiereField
? FGCSchedule.FGC2024.assignFields(matches)
: matches,
scheduleItems
)
);
showSnackbar('MatchMaker executed successfully.');
setLoading(false);
} catch (e) {
Expand Down
55 changes: 50 additions & 5 deletions front-end/src/apps/schedules/options/default-options.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { Grid, TextField } from '@mui/material';
import {
FormControl,
Grid,
InputLabel,
MenuItem,
Select,
SelectChangeEvent,
TextField
} from '@mui/material';
import { EventSchedule, calculateTotalMatches } from '@toa-lib/models';
import { ChangeEvent, FC, useEffect } from 'react';

Expand Down Expand Up @@ -35,13 +43,50 @@ export const DefaultScheduleOptions: FC<Props> = ({
});
};

const handleSelectChange = (event: SelectChangeEvent<boolean | number>) => {
if (!eventSchedule) return;
const { name, value } = event.target;
onChange({
...eventSchedule,
[name]: Boolean(value)
});
};

return (
<Grid
container
spacing={3}
sx={{ marginBottom: (theme) => theme.spacing(2) }}
>
<Grid item xs={12} sm={6} md={4} lg={3}>
<Grid item xs={12} sm={6} md={4} lg={2}>
<FormControl fullWidth>
<InputLabel>Premiere Field</InputLabel>
<Select
name='hasPremiereField'
label='Premiere Field?'
value={eventSchedule?.hasPremiereField ? 1 : 0}
disabled={disabled}
fullWidth
onChange={handleSelectChange}
type='number'
>
<MenuItem value={0}>No</MenuItem>
<MenuItem value={1}>Yes</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={2}>
<TextField
name='matchConcurrency'
label='Match Concurrency'
value={eventSchedule?.matchConcurrency}
disabled={disabled}
fullWidth
onChange={handleChange}
type='number'
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={2}>
<TextField
name='cycleTime'
label='Cycle Time'
Expand All @@ -52,7 +97,7 @@ export const DefaultScheduleOptions: FC<Props> = ({
type='number'
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<Grid item xs={12} sm={6} md={4} lg={2}>
<TextField
name='matchesPerTeam'
label='Matches Per Team'
Expand All @@ -63,7 +108,7 @@ export const DefaultScheduleOptions: FC<Props> = ({
type='number'
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<Grid item xs={12} sm={6} md={4} lg={2}>
<TextField
label='Teams Scheduled'
value={eventSchedule?.teamsParticipating}
Expand All @@ -72,7 +117,7 @@ export const DefaultScheduleOptions: FC<Props> = ({
type='number'
/>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={3}>
<Grid item xs={12} sm={6} md={4} lg={2}>
<TextField
label='Total Matches'
value={eventSchedule?.totalMatches}
Expand Down
2 changes: 1 addition & 1 deletion front-end/src/apps/schedules/tabs/schedule-matches.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const ScheduleMatches: FC<Props> = ({ eventSchedule, savedMatches }) => {
tournament={tournament}
onCreateMatches={handleCreateMatches}
/>
{matchesToDisplay && (
{matchesToDisplay.length > 0 && (
<>
<MatchTable matches={matchesToDisplay} teams={teams} />
<ScheduleMatchFooter
Expand Down
4 changes: 3 additions & 1 deletion front-end/src/components/tables/matches-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export const MatchTable: FC<Props> = ({ matches, teams }) => {
return [
e.name,
e.fieldNumber,
DateTime.fromISO(e.startTime).toLocaleString(DateTime.DATETIME_FULL),
DateTime.fromISO(e.scheduledTime).toLocaleString(
DateTime.DATETIME_FULL
),
...participants
];
}}
Expand Down
158 changes: 158 additions & 0 deletions lib/models/src/fgc/Schedule.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { DateTime } from 'luxon';
import { Match } from '../base/Match.js';
import {
EventSchedule,
generateScheduleItems as generateDefaultScheduleItems,
ScheduleItem
} from '../base/Schedule.js';

export namespace FGC2023 {
// We can safely assume for FGC2023 there will be 5 fields.
Expand Down Expand Up @@ -30,3 +36,155 @@ export namespace FGC2023 {
return newMatches;
}
}

export namespace FGC2024 {
export function assignFields(matches: Match<any>[]) {
// FGC2024 will have 5 fields.
// Assign them as such, while keeping 3 match concurrency.
const newMatches: Match<any>[] = [];
for (let i = 0; i < matches.length; i++) {
const match = matches[i];
let fieldNumber = 5;
const matchIndex = i % 6;
switch (matchIndex) {
case 0:
fieldNumber = 1;
break;
case 1:
fieldNumber = 4;
break;
case 2:
fieldNumber = 3;
break;
case 3:
fieldNumber = 2;
break;
case 4:
fieldNumber = 5;
break;
default:
fieldNumber = 3;
}
newMatches.push({ ...match, fieldNumber });
}
return newMatches;
}
}

// We'll leave this in for scientific purposes, but it turns out I'm actually a genius and don't need this.
// export function generateScheduleWithPremiereField(
// oldSchedule: EventSchedule
// ): ScheduleItem[] {
// const items = generateDefaultScheduleItems(oldSchedule);
// const schedule = JSON.parse(JSON.stringify(oldSchedule));
// let index = 0;
// let normalIndex = 0;
// let premiereIndex = 0;
// let [prevItem] = items;
// let breakPadding = 0;
// let breakIndex = 0;

// let needsBufferMatch = false;
// let bufferCount = 0;
// let dayPremiereTime = 0;
// let dayNormalTime = 0;
// for (const item of items) {
// if (prevItem.day !== item.day) {
// schedule.days[prevItem.day].endTime = DateTime.fromISO(prevItem.startTime)
// .plus({ minutes: prevItem.duration })
// .toISO();
// premiereIndex = 0;
// normalIndex = 0;
// index = 0;
// breakPadding = 0;
// breakIndex = 0;
// dayPremiereTime = 0;
// dayNormalTime = 0;
// needsBufferMatch = false;
// }

// if (item.isMatch) {
// // For all matches that are NOT on the final day. FIRST GLOBAL ONLY.
// // if (
// // item.day + 1 === schedule.days.length &&
// // schedule.type === 'Qualification'
// // ) {
// // item.duration = FGC_SIDE_FIELDS_CYCLE_TIME;
// // item.startTime = schedule.days[item.day].startTime
// // .add(7 * premiereIndex + breakPadding, 'minutes')
// // .toISOString();
// // index++;
// // if (index % 3 === 0) {
// // index = 0;
// // premiereIndex++;
// // }
// // // TODO - Test and make sure this reflects on the fields.
// // } else {
// if (!needsBufferMatch) {
// if (index % 7 < 4) {
// item.duration = schedule.cycleTime;
// item.startTime =
// DateTime.fromISO(schedule.days[item.day].startTime)
// .plus({ minutes: 10 * normalIndex + breakPadding })
// .toISO() ?? '';
// dayNormalTime += item.duration / 2;
// // console.log("CREATING NORMAL MATCH", index, item.duration, dayPremiereTime, dayNormalTime);
// } else {
// item.duration = schedule.cycleTime;
// item.startTime =
// DateTime.fromISO(schedule.days[item.day].startTime)
// .plus({ minutes: item.duration * premiereIndex + breakPadding })
// .toISO() ?? '';
// dayPremiereTime += item.duration;
// premiereIndex++;
// // console.log("CREATING PREMIERE MATCH", index, item.duration, dayPremiereTime, dayNormalTime);
// }
// if (index % 7 === 1) {
// normalIndex++;
// }
// if (index % 7 === 6) {
// // console.log("NEW MATCH PAIRS");
// index = 0;
// normalIndex++;
// bufferCount = 0;
// needsBufferMatch =
// dayPremiereTime - dayNormalTime === schedule.cycleTime;
// } else {
// index++;
// }
// } else {
// // console.log("BUFFER MATCH");
// item.duration = schedule.cycleTime;
// item.startTime =
// DateTime.fromISO(schedule.days[item.day].startTime)
// .plus({ minutes: item.duration * normalIndex + breakPadding })
// .toISO() ?? '';
// dayPremiereTime = 0;
// dayNormalTime = 0;
// bufferCount++;
// needsBufferMatch = bufferCount < 2;
// if (!needsBufferMatch) {
// normalIndex++;
// }
// }
// // }
// } else {
// const thisBreak = schedule.days[item.day].breaks[breakIndex];
// schedule.days[item.day].breaks[breakIndex].startTime = DateTime.fromISO(
// prevItem.startTime
// ).plus({ minutes: prevItem.duration });
// schedule.days[item.day].breaks[breakIndex].endTime = DateTime.fromISO(
// thisBreak.startTime
// ).plus({ minutes: thisBreak.duration });
// breakPadding += item.duration;
// breakIndex++;
// }
// prevItem = item;
// }
// if (items.length > 0) {
// schedule.days[prevItem.day].endTime = DateTime.fromISO(
// prevItem.startTime
// ).plus({ minutes: prevItem.duration });
// }
// return items;
// }

0 comments on commit 7caff29

Please sign in to comment.