diff --git a/frontend/src/components/stages/ranking_reveal_view.ts b/frontend/src/components/stages/ranking_reveal_view.ts index 33106884f..69d04bf4c 100644 --- a/frontend/src/components/stages/ranking_reveal_view.ts +++ b/frontend/src/components/stages/ranking_reveal_view.ts @@ -128,9 +128,11 @@ export class RankingReveal extends MobxLitElement { participantMap = {[currentId]: participantMap[currentId]}; } - const maxOptions = Math.max( - ...Object.values(participantMap).map((lst) => lst.length), - ); + const participantAnswers = Object.values(participantMap); + const maxOptions = + participantAnswers.length > 0 + ? Math.max(...participantAnswers.map((lst) => lst.length)) + : 0; return html`
${headerText}
@@ -183,6 +185,7 @@ export class RankingReveal extends MobxLitElement { ${this.renderWinner()}
+ ${this.renderResultsTable()} `; } } diff --git a/functions/src/stages/asset_allocation.utils.ts b/functions/src/stages/asset_allocation.utils.ts index e569e403a..61dc2271e 100644 --- a/functions/src/stages/asset_allocation.utils.ts +++ b/functions/src/stages/asset_allocation.utils.ts @@ -3,7 +3,6 @@ import { AssetAllocationStageParticipantAnswer, AssetAllocationStagePublicData, ParticipantProfileExtended, - createAssetAllocationStagePublicData, } from '@deliberation-lab/utils'; import * as admin from 'firebase-admin'; @@ -27,15 +26,16 @@ export async function addParticipantAnswerToAssetAllocationStagePublicData( // Read current public data first (all reads must come before writes) const publicDoc = await transaction.get(publicDocument); - let publicData = publicDoc.data() as + const publicData = publicDoc.data() as | AssetAllocationStagePublicData | undefined; - // Create initial public data if it doesn't exist + // Public stage data should be initialized on cohort creation if (!publicData) { - publicData = createAssetAllocationStagePublicData({ - id: stage.id, - }); + console.warn( + `Public stage data not found for stage ${stage.id} in cohort ${participant.currentCohortId}. This should have been initialized on cohort creation.`, + ); + return; } // Update public data with participant's allocation diff --git a/functions/src/stages/flipcard.utils.ts b/functions/src/stages/flipcard.utils.ts index c0379c392..4e58504b0 100644 --- a/functions/src/stages/flipcard.utils.ts +++ b/functions/src/stages/flipcard.utils.ts @@ -30,24 +30,31 @@ export async function addParticipantAnswerToFlipCardStagePublicData( const publicDoc = await transaction.get(publicDocument); const publicData = publicDoc.data() as FlipCardStagePublicData | undefined; - if (publicData) { - // Update public data with participant's flip history and selections - const updatedPublicData: FlipCardStagePublicData = { - ...publicData, - participantFlipHistory: { - ...publicData.participantFlipHistory, - [participant.publicId]: answer.flipHistory, - }, - participantSelections: { - ...publicData.participantSelections, - [participant.publicId]: answer.selectedCardIds, - }, - }; - - transaction.set(publicDocument, { - ...updatedPublicData, - timestamp: admin.firestore.FieldValue.serverTimestamp(), - }); + if (!publicData) { + console.warn( + `Public stage data not found for stage ${stage.id} in cohort ${participant.currentCohortId}. This should have been initialized on cohort creation.`, + ); + return; } + + const currentPublicData = publicData; + + // Update public data with participant's flip history and selections + const updatedPublicData: FlipCardStagePublicData = { + ...currentPublicData, + participantFlipHistory: { + ...currentPublicData.participantFlipHistory, + [participant.publicId]: answer.flipHistory, + }, + participantSelections: { + ...currentPublicData.participantSelections, + [participant.publicId]: answer.selectedCardIds, + }, + }; + + transaction.set(publicDocument, { + ...updatedPublicData, + timestamp: admin.firestore.FieldValue.serverTimestamp(), + }); }); } diff --git a/functions/src/stages/multi_asset_allocation.utils.ts b/functions/src/stages/multi_asset_allocation.utils.ts index 4cc3bfdc9..c5c0a8010 100644 --- a/functions/src/stages/multi_asset_allocation.utils.ts +++ b/functions/src/stages/multi_asset_allocation.utils.ts @@ -4,7 +4,7 @@ import { MultiAssetAllocationStagePublicData, ParticipantProfile, } from '@deliberation-lab/utils'; -import * as admin from 'firebase-admin'; + import {app} from '../app'; /** @@ -42,16 +42,18 @@ export async function addParticipantAnswerToMultiAssetAllocationStagePublicData( | undefined; if (!publicData) { - console.error( - `Public data for stage ${stage.id} does not exist. Cannot update.`, + console.warn( + `Public stage data not found for stage ${stage.id} in cohort ${participant.currentCohortId}. This should have been initialized on cohort creation.`, ); return; } + const currentPublicData = publicData; + const updatedPublicData: MultiAssetAllocationStagePublicData = { - ...publicData, + ...currentPublicData, participantAnswerMap: { - ...publicData.participantAnswerMap, + ...currentPublicData.participantAnswerMap, [participant.publicId]: answer, }, }; diff --git a/functions/src/stages/ranking.utils.ts b/functions/src/stages/ranking.utils.ts index 97adedfdd..14ab48e87 100644 --- a/functions/src/stages/ranking.utils.ts +++ b/functions/src/stages/ranking.utils.ts @@ -41,9 +41,18 @@ export async function addParticipantAnswerToRankingStagePublicData( .collection('publicStageData') .doc(LAS_WTL_STAGE_ID); // Update public stage data (current participant rankings, current winner) - const publicStageData = ( - await publicDocument.get() - ).data() as RankingStagePublicData; + const publicDoc = await publicDocument.get(); + const publicStageData = publicDoc.data() as + | RankingStagePublicData + | undefined; + + if (!publicStageData) { + console.warn( + `Public stage data not found for stage ${stage.id} in cohort ${participant.currentCohortId}. This should have been initialized on cohort creation.`, + ); + return; + } + publicStageData.participantAnswerMap[participant.publicId] = answer.rankingList; diff --git a/functions/src/stages/survey.utils.ts b/functions/src/stages/survey.utils.ts index 29eee027f..984e55c74 100644 --- a/functions/src/stages/survey.utils.ts +++ b/functions/src/stages/survey.utils.ts @@ -2,6 +2,7 @@ import { ParticipantProfileExtended, SurveyStageParticipantAnswer, SurveyStagePublicData, + SurveyStageConfig, } from '@deliberation-lab/utils'; import {app} from '../app'; @@ -25,9 +26,18 @@ export async function addParticipantAnswerToSurveyStagePublicData( .doc(stage.id); // Update public stage data (current participant rankings, current winner) - const publicStageData = ( - await publicDocument.get() - ).data() as SurveyStagePublicData; + const publicDoc = await transaction.get(publicDocument); + const publicStageData = publicDoc.data() as + | SurveyStagePublicData + | undefined; + + if (!publicStageData) { + console.warn( + `Public stage data not found for stage ${stage.id} in cohort ${participant.currentCohortId}. This should have been initialized on cohort creation.`, + ); + return; + } + publicStageData.participantAnswerMap[participant.publicId] = answer.answerMap; diff --git a/utils/src/utils/algebraic.utils.ts b/utils/src/utils/algebraic.utils.ts index be97251f5..381c025c2 100644 --- a/utils/src/utils/algebraic.utils.ts +++ b/utils/src/utils/algebraic.utils.ts @@ -194,7 +194,7 @@ export function getRankingCandidatesFromWTL( * filter rankings so that they only include those candidates. */ export function filterRankingsByCandidates( participantRankings: Record, - candidateList = [], + candidateList: string[] = [], ) { Object.keys(participantRankings).forEach((id) => { participantRankings[id] = participantRankings[id].filter(