From 9d9736684335442fc6bda832e7af1f4717dfda5b Mon Sep 17 00:00:00 2001 From: Aritra Date: Sun, 15 Mar 2026 14:45:23 +0530 Subject: [PATCH] fist pass at making it more reliable --- src/firestore/app/run.ts | 5 ++++- src/firestore/app/task.ts | 30 ++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/firestore/app/run.ts b/src/firestore/app/run.ts index 283f8a3e..cd97695d 100644 --- a/src/firestore/app/run.ts +++ b/src/firestore/app/run.ts @@ -173,7 +173,7 @@ export class RoarRun { await this.user.checkUserExists(); if (!this.task.variantRef) { - await this.task.toFirestore(); + await this.task.setVariantRef(); } const userDocSnap = await getDoc(this.user.userRef); @@ -193,6 +193,7 @@ export class RoarRun { } } + // TODO: Check if grade and schoolLevel are needed for levante. const userDocData = _pick(userDocSnap.data(), [ 'grade', 'assessmentPid', @@ -203,6 +204,7 @@ export class RoarRun { ]); // Grab the testData and demoData flags from the user document. + // TODO: Check if testData and demoData are needed for levante. const { testData: isTestUser, demoData: isDemoUser } = userDocSnap.data(); // Update testData and demoData for this instance based on the test/demo @@ -243,6 +245,7 @@ export class RoarRun { const batch = writeBatch(this.user.db); batch.set(this.runRef, removeUndefined(runData)); + // TODO: Check if this next update is needed for levante. batch.update(this.user.userRef, { tasks: arrayUnion(this.task.taskId), variants: arrayUnion(this.task.variantId), diff --git a/src/firestore/app/task.ts b/src/firestore/app/task.ts index bf6fcd88..116a16af 100644 --- a/src/firestore/app/task.ts +++ b/src/firestore/app/task.ts @@ -14,6 +14,7 @@ import { where, getDoc, } from 'firebase/firestore'; +import _isEqual from 'lodash/isEqual'; import { mergeGameParams, removeUndefined, replaceValues } from '../util'; export interface TaskVariantBase { @@ -25,6 +26,7 @@ export interface TaskVariantBase { taskVersion?: string; gameConfig?: object; external?: boolean; + variantId?: string; variantName: string; variantParams: { [key: string]: unknown }; registered?: boolean; @@ -109,6 +111,7 @@ export class RoarTaskVariant { taskVersion = undefined, registered, external, + variantId = undefined, variantName, variantParams = {}, }: TaskVariantBase) { @@ -126,8 +129,8 @@ export class RoarTaskVariant { this.variantParams = variantParams; this.taskRef = doc(this.db, 'tasks', this.taskId); this.variantsCollectionRef = collection(this.taskRef, 'variants'); - this.variantId = undefined; - this.variantRef = undefined; + this.variantId = variantId; + this.variantRef = variantId ? doc(this.variantsCollectionRef, variantId) : undefined; } /** @@ -236,4 +239,27 @@ export class RoarTaskVariant { this.variantParams = merged; await this.toFirestore(); } + + async setVariantRef() { + // If this is being called that means the variantId was not provided in the constructor + if (!this.variantParams) { + // If variant params are not then there is no way to determine the variant ref + throw new Error('Cannot set variant ref without variant params or variant id. Please provide one of them.'); + } + + // Query all the variants and do a deep match on the params field + const q = query( + this.variantsCollectionRef, + orderBy('updatedAt', 'desc'), + ); + const querySnapshot = await getDocs(q); + // Go through the docs and match the this.variantParams with the params field in the doc + for (const docSnap of querySnapshot.docs) { + if (_isEqual(docSnap.data().params, this.variantParams)) { + this.variantId = docSnap.id; + break; + } + } + this.variantRef = doc(this.variantsCollectionRef, this.variantId); + } }