From 70f6071d0d712827d6bf4f83ab374fbfe7e5042e Mon Sep 17 00:00:00 2001 From: Carifio24 Date: Wed, 31 Jul 2024 17:38:22 -0400 Subject: [PATCH] Add endpoints for getting the size of a classroom and for getting the number of Hubble measurements for a class. --- src/server.ts | 18 +++++++++++++++++ src/stories/hubbles_law/database.ts | 20 +++++++++++++++++++ src/stories/hubbles_law/router.ts | 30 ++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/server.ts b/src/server.ts index 45700aa..3ab65c2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -32,6 +32,7 @@ import { getStageState, updateStageState, deleteStageState, + findClassById, } from "./database"; import { getAPIKey, hasPermission } from "./authorization"; @@ -417,6 +418,23 @@ app.get("/educators", async (_req, res) => { res.json(queryResponse); }); +app.get("/classes/size/:classID", async (req, res) => { + const classID = Number(req.params.classID); + const cls = await findClassById(classID); + if (cls === null) { + res.status(404).json({ + message: `Class ${classID} not found`, + }); + return; + } + + const size = classSize(classID); + res.json({ + class_id: classID, + size + }); +}); + app.get("/story-state/:studentID/:storyName", async (req, res) => { const params = req.params; const studentID = Number(params.studentID); diff --git a/src/stories/hubbles_law/database.ts b/src/stories/hubbles_law/database.ts index 1bbaccb..5cfeb1b 100644 --- a/src/stories/hubbles_law/database.ts +++ b/src/stories/hubbles_law/database.ts @@ -365,6 +365,26 @@ export async function getClassMeasurements(studentID: number, return data ?? []; } +// The advantage of this over the function above is that it saves bandwidth, +// since we aren't sending the data itself. +// This is intended to be used with cases where we need to frequently check the class size, +// e.g. the beginning of stage 4 in the Hubble story +export async function getClassMeasurementCount(studentID: number, + classID: number | null, + excludeWithNull: boolean = false, +): Promise { + const cls = classID !== null ? await findClassById(classID) : null; + const asyncClass = cls?.asynchronous ?? true; + let data: HubbleMeasurement[] | null; + console.log(classID, asyncClass); + if (classID === null || asyncClass) { + data = await getHubbleMeasurementsForAsyncStudent(studentID, classID, excludeWithNull); + } else { + data = await getHubbleMeasurementsForSyncStudent(studentID, classID, excludeWithNull); + } + return data?.length ?? 0; +} + async function getHubbleStudentDataForAsyncStudent(studentID: number, classID: number | null): Promise { const classIDs = await getClassIDsForAsyncStudent(studentID, classID); return getHubbleStudentDataForClasses(classIDs); diff --git a/src/stories/hubbles_law/router.ts b/src/stories/hubbles_law/router.ts index fa1d071..54bab4d 100644 --- a/src/stories/hubbles_law/router.ts +++ b/src/stories/hubbles_law/router.ts @@ -32,7 +32,8 @@ import { getGalaxyById, removeSampleHubbleMeasurement, getAllNthSampleHubbleMeasurements, - tryToMergeClass + tryToMergeClass, + getClassMeasurementCount } from "./database"; import { @@ -257,6 +258,33 @@ router.get("/sample-galaxy", async (_req, res) => { res.json(galaxy); }); +router.get("/class-measurements/size/:studentID/:classID", async (req, res) => { + const studentID = parseInt(req.params.studentID); + const isValidStudent = (await findStudentById(studentID)) !== null; + if (!isValidStudent) { + res.status(404).json({ + message: "Invalid student ID", + }); + return; + } + + const classID = parseInt(req.params.classID); + const isValidClass = (await findClassById(classID)) !== null; + if (!isValidClass) { + res.status(404).json({ + message: "Invalid class ID", + }); + return; + } + + const completeOnly = (req.query.complete_only as string)?.toLowerCase() === "true"; + const count = await getClassMeasurementCount(studentID, classID, completeOnly); + res.status(200).json({ + student_id: studentID, + measurement_count: count, + }); +}); + router.get(["/class-measurements/:studentID/:classID", "/stage-3-data/:studentID/:classID"], async (req, res) => { const lastCheckedStr = req.query.last_checked as string; let lastChecked: number | null = parseInt(lastCheckedStr);