Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions app/src/components/tournament/TournamentAnswers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from "@mantine/core";
import { IconAlertCircle, IconTarget } from "@tabler/icons-react";
import { TOURNAMENT_CONFIG, getMaskedForecastDate } from "../../config";
import { getLeaderboard } from "../../utils/tournamentAPI";
import { getParticipant } from "../../utils/tournamentAPI";
import ForecastleChartCanvas from "../forecastle/ForecastleChartCanvas";

const addWeeksToDate = (dateString, weeks) => {
Expand Down Expand Up @@ -93,6 +93,8 @@ const getSubmissionByChallenge = (submissions, challenge) => {
const TournamentAnswers = ({
tournamentConfig = TOURNAMENT_CONFIG,
participantId,
completedCount: completedCountProp = null,
isActive = false,
}) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
Expand All @@ -107,14 +109,33 @@ const TournamentAnswers = ({
return;
}

if (!isActive && completedCountProp !== null) {
setLoading(false);
return;
}

if (
Number.isFinite(completedCountProp) &&
completedCountProp < tournamentConfig.numChallenges
) {
setSubmissionsByChallenge({});
setChallengeData({});
setParticipantFound(true);
setError(null);
setLoading(false);
return;
}

setLoading(true);
setError(null);

try {
const leaderboard = await getLeaderboard(tournamentConfig);
const participantEntry =
leaderboard.find((entry) => entry.participantId === participantId) ||
null;
const participantData = await getParticipant(
participantId,
tournamentConfig,
);
const participantEntry = participantData?.participant || null;
const participantSubmissions = participantData?.submissions || [];

if (!participantEntry) {
setParticipantFound(false);
Expand All @@ -128,7 +149,7 @@ const TournamentAnswers = ({
const nextSubmissionsByChallenge = {};
tournamentConfig.challenges.forEach((challenge) => {
const submission = getSubmissionByChallenge(
participantEntry.submissions || [],
participantSubmissions,
challenge,
);
const forecasts = getSubmissionForecasts(submission);
Expand Down Expand Up @@ -210,7 +231,7 @@ const TournamentAnswers = ({
};

loadAnswers();
}, [participantId, tournamentConfig]);
}, [participantId, tournamentConfig, completedCountProp, isActive]);

const completedCount = useMemo(
() => Object.keys(submissionsByChallenge).length,
Expand Down
5 changes: 5 additions & 0 deletions app/src/components/tournament/TournamentDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const TournamentDashboard = ({ tournamentConfig = TOURNAMENT_CONFIG }) => {
const [participantName, setParticipantName] = useState(null);
const [loading, setLoading] = useState(true);
const [activeTab, setActiveTab] = useState("challenges");
const [completedCount, setCompletedCount] = useState(null);

// Load participant data on mount
useEffect(() => {
Expand All @@ -32,6 +33,7 @@ const TournamentDashboard = ({ tournamentConfig = TOURNAMENT_CONFIG }) => {
const handleRegistration = (id, name) => {
setParticipantId(id);
setParticipantName(name);
setCompletedCount(0);
};

// Navigate to leaderboard
Expand Down Expand Up @@ -87,6 +89,7 @@ const TournamentDashboard = ({ tournamentConfig = TOURNAMENT_CONFIG }) => {
participantId={participantId}
participantName={participantName}
onAllCompleted={goToLeaderboard}
onProgressChange={setCompletedCount}
/>
</Tabs.Panel>

Expand All @@ -101,6 +104,8 @@ const TournamentDashboard = ({ tournamentConfig = TOURNAMENT_CONFIG }) => {
<TournamentAnswers
tournamentConfig={tournamentConfig}
participantId={participantId}
completedCount={completedCount}
isActive={activeTab === "answers"}
/>
</Tabs.Panel>
</Tabs>
Expand Down
5 changes: 5 additions & 0 deletions app/src/components/tournament/TournamentGame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ const TournamentGame = ({
participantId,
participantName,
onAllCompleted,
onProgressChange,
}) => {
const [currentChallengeIndex, setCurrentChallengeIndex] = useState(0);
const [completedChallenges, setCompletedChallenges] = useState(new Set());
Expand Down Expand Up @@ -236,6 +237,10 @@ const TournamentGame = ({
tournamentConfig,
]);

useEffect(() => {
onProgressChange?.(completedChallenges.size);
}, [completedChallenges, onProgressChange]);

useEffect(() => {
if (inputMode === "scoring") {
return;
Expand Down
26 changes: 13 additions & 13 deletions app/src/config/tournament.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const TOURNAMENT_REGISTRY = [
{
id: "ch-3",
enabled: true,
number: 2,
number: 3,
title: "California Influenza Forecast",
description:
"Predict California flu hospitalizations for 1, 2, and 3 weeks ahead",
Expand All @@ -131,24 +131,24 @@ export const TOURNAMENT_REGISTRY = [
{
id: "ch-4",
enabled: true,
number: 3,
title: "Massachusetts RSV Forecast",
number: 4,
title: "North Carolina COVID-19 Forecast",
description:
"Predict Massachusetts RSV hospitalizations for 1, 2, and 3 weeks ahead",
dataset: "rsv",
datasetKey: "rsv",
dataPath: "rsvforecasthub",
fileSuffix: "rsv.json",
location: "MA",
displayName: "Massachusetts",
target: "wk inc rsv hosp",
"Predict North Carolina COVID hospitalizations for 1, 2, and 3 weeks ahead",
dataset: "covid",
datasetKey: "covid19",
dataPath: "covid19forecasthub",
fileSuffix: "covid19.json",
location: "NC",
displayName: "North Carolina",
target: "wk inc covid hosp",
horizons: [1, 2, 3],
forecastDate: "2025-12-20",
forecastDate: "2025-09-13",
},
{
id: "ch-5",
enabled: true,
number: 3,
number: 5,
title: "Georgia COVID-19 Forecast",
description:
"Predict Georgia COVID hospitalizations for 1, 2, and 3 weeks ahead",
Expand Down
Loading