Added dynamic generation of exams as an option
This commit is contained in:
@@ -18,6 +18,7 @@ import {getExam} from "@/utils/exams";
|
|||||||
import {toast} from "react-toastify";
|
import {toast} from "react-toastify";
|
||||||
import {uuidv4} from "@firebase/util";
|
import {uuidv4} from "@firebase/util";
|
||||||
import {Assignment} from "@/interfaces/results";
|
import {Assignment} from "@/interfaces/results";
|
||||||
|
import Checkbox from "@/components/Low/Checkbox";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isCreating: boolean;
|
isCreating: boolean;
|
||||||
@@ -35,6 +36,8 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [startDate, setStartDate] = useState<Date | null>(assignment ? moment(assignment.startDate).toDate() : moment().add(1, "day").toDate());
|
const [startDate, setStartDate] = useState<Date | null>(assignment ? moment(assignment.startDate).toDate() : moment().add(1, "day").toDate());
|
||||||
const [endDate, setEndDate] = useState<Date | null>(assignment ? moment(assignment.endDate).toDate() : moment().add(8, "day").toDate());
|
const [endDate, setEndDate] = useState<Date | null>(assignment ? moment(assignment.endDate).toDate() : moment().add(8, "day").toDate());
|
||||||
|
// creates a new exam for each assignee or just one exam for all assignees
|
||||||
|
const [generateMultiple, setGenerateMultiple] = useState<boolean>(false);
|
||||||
|
|
||||||
const toggleModule = (module: Module) => {
|
const toggleModule = (module: Module) => {
|
||||||
const modules = selectedModules.filter((x) => x !== module);
|
const modules = selectedModules.filter((x) => x !== module);
|
||||||
@@ -55,7 +58,8 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
|
|||||||
name,
|
name,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
selectedModules
|
selectedModules,
|
||||||
|
generateMultiple,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -280,6 +284,11 @@ export default function AssignmentCreator({isCreating, assignment, assigner, gro
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<div className="flex gap-4 w-full justify-end">
|
||||||
|
<Checkbox isChecked={generateMultiple} onChange={() => setGenerateMultiple(d => !d)}>
|
||||||
|
Generate an unique exam for each student
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
<div className="flex gap-4 w-full justify-end">
|
<div className="flex gap-4 w-full justify-end">
|
||||||
<Button className="w-full max-w-[200px]" variant="outline" onClick={cancelCreation} disabled={isLoading} isLoading={isLoading}>
|
<Button className="w-full max-w-[200px]" variant="outline" onClick={cancelCreation} disabled={isLoading} isLoading={isLoading}>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@@ -49,12 +49,12 @@ function getRandomIndex(arr: any[]): number {
|
|||||||
return randomIndex;
|
return randomIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function POST(req: NextApiRequest, res: NextApiResponse) {
|
const generateExams = async (
|
||||||
const { selectedModules, assignees, ...body } = req.body as {
|
generateMultiple: Boolean,
|
||||||
selectedModules: Module[];
|
selectedModules: Module[],
|
||||||
assignees: string[];
|
assignees: string[]
|
||||||
};
|
): Promise<ExamWithUser[]> => {
|
||||||
|
if (generateMultiple) {
|
||||||
// for optimization purposes, it would be better to create a new endpoint that returned the answers for all users at once
|
// for optimization purposes, it would be better to create a new endpoint that returned the answers for all users at once
|
||||||
const allExams = await assignees.map(async (assignee) => {
|
const allExams = await assignees.map(async (assignee) => {
|
||||||
const selectedModulePromises = await selectedModules.map(
|
const selectedModulePromises = await selectedModules.map(
|
||||||
@@ -82,7 +82,49 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const exams = flatten(await Promise.all(allExams)).filter(
|
const exams = flatten(await Promise.all(allExams)).filter(
|
||||||
(x) => x !== null
|
(x) => x !== null
|
||||||
) as ExamWithUser[];
|
) as ExamWithUser[];
|
||||||
|
return exams;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedModulePromises = await selectedModules.map(
|
||||||
|
async (module: Module) => {
|
||||||
|
const exams: Exam[] = await getExams(db, module, "false", undefined);
|
||||||
|
const exam = exams[getRandomIndex(exams)];
|
||||||
|
|
||||||
|
if (exam) {
|
||||||
|
return { module: exam.module, id: exam.id };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const exams = await Promise.all(selectedModulePromises);
|
||||||
|
const examesFiltered = exams.filter((x) => x !== null) as ExamWithUser[];
|
||||||
|
return flatten(
|
||||||
|
assignees.map((assignee) =>
|
||||||
|
examesFiltered.map((exam) => ({ ...exam, assignee }))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function POST(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
const {
|
||||||
|
selectedModules,
|
||||||
|
assignees,
|
||||||
|
// Generarte multiple true would generate an unique exam for eacah user
|
||||||
|
// false would generate the same exam for all usersa
|
||||||
|
generateMultiple = false,
|
||||||
|
...body
|
||||||
|
} = req.body as {
|
||||||
|
selectedModules: Module[];
|
||||||
|
assignees: string[];
|
||||||
|
generateMultiple: Boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const exams: ExamWithUser[] = await generateExams(
|
||||||
|
generateMultiple,
|
||||||
|
selectedModules,
|
||||||
|
assignees
|
||||||
|
);
|
||||||
if (exams.length === 0) {
|
if (exams.length === 0) {
|
||||||
res
|
res
|
||||||
.status(400)
|
.status(400)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const getExams = async (
|
|||||||
// added userId as due to assignments being set from the teacher to the student
|
// added userId as due to assignments being set from the teacher to the student
|
||||||
// we need to make sure we are serving exams not executed by the user and not
|
// we need to make sure we are serving exams not executed by the user and not
|
||||||
// by the teacher that performed the request
|
// by the teacher that performed the request
|
||||||
userId: string
|
userId: string | undefined
|
||||||
): Promise<Exam[]> => {
|
): Promise<Exam[]> => {
|
||||||
const moduleRef = collection(db, module);
|
const moduleRef = collection(db, module);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user