Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
johnmeshulam committed Jan 15, 2025
2 parents 1523b9b + d78397b commit 20e0481
Show file tree
Hide file tree
Showing 33 changed files with 990 additions and 876 deletions.
1 change: 1 addition & 0 deletions apps/backend/src/websocket/handlers/judging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ export const handleUpdateAwardWinners = async (
const newAwards = [];
Object.entries(body).forEach(([awardName, winners]) => {
const updatedAward = [...awards].filter(a => a.name === awardName);
if (updatedAward.length === 0) return; // Award isn't handed out in this division
updatedAward
.sort((a, b) => a.place - b.place)
.forEach((award, index) => newAwards.push({ ...award, winner: winners[index] }));
Expand Down
1 change: 0 additions & 1 deletion apps/frontend/components/admin/division-award-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ const DivisionAwardEditor: React.FC<DivisionAwardEditorProps> = ({ divisionId, a
apiFetch(`/api/admin/divisions/${copyFromDivision._id}/awards/schema`)
.then(res => res.json())
.then(data => {
console.log(data);
if (Object.entries(data).length > 0) {
setAwards(getExistingAwards(data));
formikRef.current?.setValues(getInitialValues(data), true);
Expand Down
2 changes: 1 addition & 1 deletion apps/frontend/components/audience-display/message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const Message: React.FC<MessageProps> = ({ message }) => {
textAlign: 'center',
mx: '50px',
borderRadius: 8,
border: `1rem solid #d22e92`,
border: `1rem solid rgb(48, 89, 191)`,
minWidth: '30%'
}}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ObjectId } from 'mongodb';
import { ObjectId, WithId } from 'mongodb';
import { Paper, Box, IconButton, Avatar, Stack, Typography } from '@mui/material';
import DescriptionIcon from '@mui/icons-material/Description';
import ContactPageRoundedIcon from '@mui/icons-material/ContactPageRounded';
Expand All @@ -8,7 +8,8 @@ import {
CoreValuesAwardsTypes,
CoreValuesAwards,
SELECTED_TEAM_COLOR,
SUGGESTED_TEAM_COLOR
SUGGESTED_TEAM_COLOR,
Award
} from '@lems/types';
import {
rubricsSchemas,
Expand All @@ -24,6 +25,7 @@ import { rankArray } from '@lems/utils/arrays';
interface CategoryDeliberationsGridProps {
category: JudgingCategory;
teams: Array<DeliberationTeam>;
divisionAwards: Array<WithId<Award>>;
selectedTeams: Array<ObjectId>;
updateTeamAwards?: (
teamId: ObjectId,
Expand All @@ -39,6 +41,7 @@ interface CategoryDeliberationsGridProps {
const CategoryDeliberationsGrid: React.FC<CategoryDeliberationsGridProps> = ({
category,
teams,
divisionAwards,
selectedTeams,
updateTeamAwards,
disabled = false,
Expand All @@ -53,7 +56,10 @@ const CategoryDeliberationsGrid: React.FC<CategoryDeliberationsGridProps> = ({
section.fields.map(field => ({ field: field.id, headerName: field.title }))
);

const awards = schema.awards?.map(award => ({ field: award.id, headerName: award.title })) || [];
const awards =
schema.awards
?.filter(schemaAward => divisionAwards.find(award => award.name === schemaAward.id))
.map(award => ({ field: award.id, headerName: award.title })) || [];
const rankingRounds = [teams[0]?.gpScores.map(gp => gp.round)].flat();

let rows = teams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const CategoryDeliberationLayout: React.FC = () => {
const {
deliberation,
teams,
awards,
selectedTeams,
availableTeams,
eligibleTeams,
Expand Down Expand Up @@ -40,6 +41,7 @@ const CategoryDeliberationLayout: React.FC = () => {
showNormalizedScores={true}
showRanks={true}
suggestedTeam={picklist.length < picklistLimit ? suggestedTeam : null}
divisionAwards={awards}
/>
</Grid>
<Grid size={1.5}>
Expand Down
75 changes: 51 additions & 24 deletions apps/frontend/components/deliberations/deliberation.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import React, { useEffect, createContext, forwardRef, useImperativeHandle, useMemo } from 'react';
import React, {
useEffect,
createContext,
forwardRef,
useImperativeHandle,
useMemo,
useCallback
} from 'react';
import { ObjectId, WithId } from 'mongodb';
import { DragDropContext, OnDragEndResponder } from 'react-beautiful-dnd';
import {
Expand Down Expand Up @@ -26,6 +33,7 @@ import { getDefaultPicklistLimit } from '../../lib/utils/math';
export interface DeliberationContextType {
deliberation: WithId<JudgingDeliberation>;
teams: Array<DeliberationTeam>;
awards: Array<WithId<Award>>;
eligibleTeams: Array<ObjectId>;
selectedTeams: Array<ObjectId>;
availableTeams: Array<ObjectId>;
Expand Down Expand Up @@ -214,38 +222,56 @@ export const Deliberation = forwardRef<DeliberationRef, DeliberationProps>(
}
};

const teamWonAward = (team: WithId<Team>) =>
awards.find(
award =>
typeof award.winner !== 'string' &&
award.name !== 'robot-performance' &&
award.name !== 'advancement' &&
award.winner?._id === team._id
);

const ineligibleTeams = teams
.filter(
team =>
!team.registered ||
state.disqualifications.includes(team._id) ||
teamWonAward(team) ||
!!rubrics.find(r => r.teamId === team._id && ['empty', 'in-progress'].includes(r.status))
)
.map(team => team._id);
const teamWonAward = useCallback(
(team: WithId<Team>) =>
awards.find(
award =>
typeof award.winner !== 'string' &&
award.name !== 'robot-performance' &&
award.name !== 'advancement' &&
award.winner?._id === team._id
),
[awards]
);

const eligibleTeams = useMemo(
const ineligibleTeams = useMemo(
() =>
teams
.filter(
team =>
!ineligibleTeams.includes(team._id) &&
(checkEligibility(team, teams, state.disqualifications) ||
state.manualEligibility?.includes(team._id))
!team.registered ||
state.disqualifications.includes(team._id) ||
teamWonAward(team) ||
!!rubrics.find(
r => r.teamId === team._id && ['empty', 'in-progress'].includes(r.status)
)
)
.map(team => team._id),
[teams, ineligibleTeams, checkEligibility, state.disqualifications, state.manualEligibility]
[rubrics, state.disqualifications, teamWonAward, teams]
);

const eligibleTeams = useMemo(() => {
// HACK: For some reason, if checkEligibility is not called once before actually using it, it will not work,
// and return the 2nd team twice, eliminating the 1st team from the list of eligible teams.
// Since this is a terrible idea to just throw out the best team from champions award, we call it once here.
checkEligibility(teams[0], teams, state.disqualifications);

return teams
.filter(
team =>
!ineligibleTeams.includes(team._id) &&
(checkEligibility(team, teams, state.disqualifications) ||
state.manualEligibility?.includes(team._id))
)
.map(team => team._id);
}, [
teams,
ineligibleTeams,
checkEligibility,
state.disqualifications,
state.manualEligibility
]);

const selectedTeams = [...new Set(Object.values(state.awards).flat(1))];
const availableTeams = eligibleTeams.filter(teamId => !selectedTeams.includes(teamId));
const additionalTeams = teams.filter(
Expand Down Expand Up @@ -278,6 +304,7 @@ export const Deliberation = forwardRef<DeliberationRef, DeliberationProps>(
value={{
deliberation: state,
teams,
awards,
eligibleTeams,
selectedTeams,
availableTeams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { DeliberationContext } from '../../deliberation';
const OptionalAwardsDeliberationLayout: React.FC = () => {
const {
teams,
awards,
selectedTeams,
additionalTeams,
deliberation,
Expand All @@ -27,15 +28,19 @@ const OptionalAwardsDeliberationLayout: React.FC = () => {
disqualifyTeam
} = useContext(DeliberationContext);

const limits = CoreValuesAwardsTypes.reduce(
const cvAwards = CoreValuesAwardsTypes.filter(awardName =>
awards.find(award => award.name === awardName)
);

const limits = cvAwards.reduce(
(acc, award) => {
acc[award] = picklistLimits[award as AwardNames] ?? AwardLimits[award as AwardNames]!;
return acc;
},
{} as { [key in AwardNames]?: number }
);

const nextStageUnlocked = CoreValuesAwardsTypes.every(
const nextStageUnlocked = cvAwards.every(
award => deliberation.awards[award]!.length === limits[award]
);

Expand All @@ -45,9 +50,11 @@ const OptionalAwardsDeliberationLayout: React.FC = () => {
<CategoryDeliberationsGrid
category="core-values"
teams={teams.filter(team => eligibleTeams.includes(team._id))}
divisionAwards={awards}
selectedTeams={selectedTeams}
showNormalizedScores={false}
showRanks={false}
disabled
/>
</Grid>
<Grid size={3}>
Expand Down Expand Up @@ -77,7 +84,7 @@ const OptionalAwardsDeliberationLayout: React.FC = () => {
{/* 1.5 x number of lists*/}
<Grid size={4.5}>
<Stack direction="row" spacing="2" gap={2} height="100%">
{CoreValuesAwardsTypes.map((award, index) => (
{cvAwards.map((award, index) => (
<AwardList
key={index}
title={localizedAward[award].name}
Expand Down
7 changes: 5 additions & 2 deletions apps/frontend/components/export/export-rubric-feedback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { WithId } from 'mongodb';
import { Box, Stack } from '@mui/material';
import Grid from '@mui/material/Grid2';
import { rubricsSchemas } from '@lems/season';
import { Rubric, JudgingCategory, DivisionWithEvent, Team } from '@lems/types';
import { Rubric, JudgingCategory, DivisionWithEvent, Team, Award } from '@lems/types';
import { RubricAwards } from './rubrics/rubric-awards';
import { SessionFeedbackHeader } from './rubrics/feedback-page/session-feedback-header';
import SessionFeedbackTable from './rubrics/feedback-page/session-feedback-table';
Expand All @@ -12,12 +12,14 @@ interface ExportRubricFeedbackProps {
rubrics: Array<WithId<Rubric<JudgingCategory>>>;
division: WithId<DivisionWithEvent>;
team: WithId<Team>;
awards: Array<WithId<Award>>;
}

export const ExportRubricFeedback: React.FC<ExportRubricFeedbackProps> = ({
rubrics,
division,
team
team,
awards
}) => {
const cvrubric = rubrics.find(r => r.category === 'core-values');
if (!cvrubric) return null;
Expand All @@ -33,6 +35,7 @@ export const ExportRubricFeedback: React.FC<ExportRubricFeedbackProps> = ({
<RubricAwards
rubric={cvrubric}
schema={rubricsSchemas[cvrubric.category]}
divisionAwards={awards}
size={12}
/>
</Box>
Expand Down
6 changes: 4 additions & 2 deletions apps/frontend/components/export/export-rubric.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { WithId } from 'mongodb';
import { DivisionWithEvent, JudgingCategory, Rubric, Team } from '@lems/types';
import { Award, DivisionWithEvent, JudgingCategory, Rubric, Team } from '@lems/types';
import Grid from '@mui/material/Grid2';
import { Box, Stack } from '@mui/material';
import { rubricsSchemas } from '@lems/season';
Expand All @@ -11,13 +11,15 @@ interface ExportRubricProps {
division: WithId<DivisionWithEvent>;
team: WithId<Team>;
rubric: WithId<Rubric<JudgingCategory>>;
awards: Array<WithId<Award>>;
showFeedback?: boolean;
}

export const ExportRubric: React.FC<ExportRubricProps> = ({
division,
team,
rubric,
awards,
showFeedback = true
}) => {
const schema = rubricsSchemas[rubric.category];
Expand Down Expand Up @@ -47,7 +49,7 @@ export const ExportRubric: React.FC<ExportRubricProps> = ({
division={division}
team={{ number: team.number.toString() }}
/>
<RubricAwards size={8} rubric={rubric} schema={schema} />
<RubricAwards size={8} rubric={rubric} schema={schema} divisionAwards={awards} />
</Grid>
<Box sx={{ flex: 1, minHeight: 0 }}>
<RubricTable rubric={rubric} showFeedback={showFeedback} />
Expand Down
20 changes: 14 additions & 6 deletions apps/frontend/components/export/rubrics/rubric-awards.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ResponsiveStyleValue } from '@mui/system';
import { JudgingCategory, Rubric } from '@lems/types';
import { Award, JudgingCategory, Rubric } from '@lems/types';
import Grid, { GridSize } from '@mui/material/Grid2';
import {
Checkbox,
Expand All @@ -13,16 +13,25 @@ import { RubricsSchema } from '@lems/season';
import UncheckedIcon from '@mui/icons-material/CircleOutlined';
import CheckedIcon from '@mui/icons-material/TaskAltRounded';
import Markdown from 'react-markdown';
import { WithId } from 'mongodb';

interface RubricAwardsProps {
size: ResponsiveStyleValue<GridSize>;
rubric: Rubric<JudgingCategory>;
divisionAwards: Array<WithId<Award>>;
schema: RubricsSchema;
}

export const RubricAwards: React.FC<RubricAwardsProps> = ({ size, rubric, schema }) => {
const awards = schema.awards;
if (!awards) return <></>;
export const RubricAwards: React.FC<RubricAwardsProps> = ({
size,
rubric,
divisionAwards,
schema
}) => {
const awards = schema.awards?.filter(schemaAward =>
divisionAwards?.find(award => award.name === schemaAward.id)
);
if (!awards) return null;

return (
<Grid size={size}>
Expand All @@ -38,8 +47,7 @@ export const RubricAwards: React.FC<RubricAwardsProps> = ({ size, rubric, schema
px: 2,
'@media print': {
borderRadius: 0,
borderBottom:
index < awards.length - 1 ? '0.5px solid rgba(0,0,0,0.2)' : 'none',
borderBottom: index < awards.length - 1 ? '0.5px solid rgba(0,0,0,0.2)' : 'none',
paddingBottom: 1,
paddingTop: 1
}
Expand Down
Loading

0 comments on commit 20e0481

Please sign in to comment.