From d8ead761915438127c997fb67150c2975b232b6f Mon Sep 17 00:00:00 2001 From: amjed-ali-k Date: Thu, 26 Oct 2023 00:51:31 +0530 Subject: [PATCH] exam hall assignment --- .../exam/new/_components/NewExamForm.tsx | 139 +++++++++- src/lib/examTools/customHallAsiign.ts | 111 ++++---- src/lib/examTools/hallSort.ts | 237 +++++++++--------- 3 files changed, 311 insertions(+), 176 deletions(-) diff --git a/src/app/dashboard/tools/exam-seating/exam/new/_components/NewExamForm.tsx b/src/app/dashboard/tools/exam-seating/exam/new/_components/NewExamForm.tsx index 7251ef7..7aea760 100644 --- a/src/app/dashboard/tools/exam-seating/exam/new/_components/NewExamForm.tsx +++ b/src/app/dashboard/tools/exam-seating/exam/new/_components/NewExamForm.tsx @@ -1,7 +1,21 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { CheckIcon, Cross, Diamond, Users, X } from "lucide-react"; +import { + CheckCircle, + CheckCircle2, + CheckIcon, + Circle, + CircleDashed, + CircleSlash, + Cross, + Diamond, + PlayCircle, + StopCircle, + Users, + X, + XCircle, +} from "lucide-react"; import React, { useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; @@ -57,7 +71,13 @@ import { } from "@/components/ui/table"; import Link from "next/link"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { sum } from "radash"; +import { sum, flat, group, sift } from "radash"; +import { assignHallsCustom } from "@/lib/examTools/customHallAsiign"; +import { allocateSeats } from "@/lib/examTools/hallSort"; +import { + SeatObjectType, + SeatType, +} from "../../../new-class/_components/newClass"; type tabsType = "batches-section" | "halls-section" | "generate-section"; @@ -104,6 +124,12 @@ function CreateExamFrom() { onSuccess={() => settab("generate-section")} /> + + + ); @@ -111,6 +137,14 @@ function CreateExamFrom() { export default CreateExamFrom; +type IncomeStudent = { + name?: string | undefined; + rollNumber?: string | undefined; + regNumber?: string | undefined; + admnNumber?: string | undefined; + primaryNumber?: string | undefined; +}; + function GenerateSection({ finalHalls, finalBatches, @@ -118,7 +152,106 @@ function GenerateSection({ finalHalls: ExamHall[]; finalBatches: BatchWithSub[]; }) { - return
; + const seats = useMemo(() => { + const assignedHalls = assignHallsCustom( + finalBatches.map((e) => ({ + count: e.studentsCount, + subjectCode: parseInt(e.subject.code), + examType: e.type === "THEORY" ? 0 : 1, + })), + finalHalls.map((e) => ({ + name: e.id, + commonSeats: e.commonSeats, + theoryOnlySeats: e.theoryOnlySeats, + drawingOnlySeats: e.drawingOnlySeats, + })) + ); + + const remainingStudents = group( + flat( + finalBatches.map((e) => { + const st = e.students as IncomeStudent[]; + const students = st.map((k) => ({ + regNo: (k.name || k.primaryNumber)!, + subjectCode: parseInt(e.subject.code), + examType: e.type === "THEORY" ? 0 : 1, + })); + return students; + }) + ), + (e) => e.subjectCode + ); + + const indexes: { [key: string]: number } = {}; + + const seats = sift( + Object.keys(assignedHalls).map((e) => { + const hall = assignedHalls[e]; + const ogHall = finalHalls.find((k) => k.id === e); + const subjectCodes = Object.keys(assignedHalls[e]); + + const students: { + regNo: string; + subjectCode: number; + examType: number; + }[] = []; + + subjectCodes.map((subCode) => { + if (indexes[subCode] === undefined) indexes[subCode] = 0; + const count = hall[parseInt(subCode)]; + console.log( + `${count} students assigned from ${subCode} in Hall ${ogHall?.name}` + ); + const toAdd = remainingStudents[parseInt(subCode)]?.slice( + indexes[subCode], + indexes[subCode] - 1 + count + ); + indexes[subCode] += count; + if (!toAdd) return; + students.push(...toAdd); + indexes[subCode] ? (indexes[subCode] += count) : 0; + }); + if (!ogHall?.structure) return; + + const seatType = (ogHall.structure as SeatObjectType[][]).map((e) => + flat(e.map((k) => k.structure)) + ); + + // console.log("Structure", ogHall.structure); + return { + hall: ogHall.id, + hallName: ogHall.name, + hallStructure: ogHall.structure, + seats: allocateSeats(students, seatType as any), + }; + }) + ); + console.log(seats); + return seats; + }, [finalBatches, finalHalls]); + + return ( + + +
+
+ Validating inputs +
+
+ Processing data +
+
+ Alloting halls for + students +
+
+ Assigning students in + each halls +
+
+
+
+ ); } const schema = z.object({ diff --git a/src/lib/examTools/customHallAsiign.ts b/src/lib/examTools/customHallAsiign.ts index b21d0f6..0869e80 100644 --- a/src/lib/examTools/customHallAsiign.ts +++ b/src/lib/examTools/customHallAsiign.ts @@ -5,7 +5,7 @@ export interface ExamHallSeatsCount { commonSeats: number; theoryOnlySeats: number; drawingOnlySeats: number; - name: number; + name: string; } /** @@ -21,21 +21,27 @@ export enum ExamType { */ export type StudentCount = { count: number; // Number of students - branch: string; // Branch name + // branch: string; // Branch name subjectCode: number; // Subject code examType: ExamType; // Exam type }; +type ReturnType = { + [key: string]: { + [key: number]: number; + }; +}; + /** * Allocates exam halls to students * @param {StudentCount[]} studentCount - Array of student count per exam * @param {ExamHallSeatsCount[]} examHalls - Available exam halls - * @returns {Object} - Allocated seats per hall and subject + * @returns {ReturnType} - Allocated seats per hall and subject */ export function assignHallsCustom( studentCount: StudentCount[], examHalls: ExamHallSeatsCount[] -) { +): ReturnType { // Deep copy input to avoid mutation const _studentCount = JSON.parse( JSON.stringify(studentCount) @@ -89,11 +95,9 @@ export function assignHallsCustom( while (remainingSeats > 0 && remainingStudents > 0) { const remainingHalls = allowedHalls.filter((e) => getSeats(e) > 0); - console.log(remainingHalls.length); // find minimum seats const minSeats = remainingHalls.length > 0 ? getSeats(remainingHalls[0]) : 0; - console.log(minSeats); // find total seats remainingSeats = remainingHalls.reduce( (acc, curr) => acc + getSeats(curr), @@ -112,7 +116,6 @@ export function assignHallsCustom( if (!(remainingStudents > 1)) { throw "No students remaining"; } - console.log(remainingStudents); const seats2Assign = seatsToAssign < remainingStudents ? seatsToAssign @@ -191,50 +194,50 @@ export function getSeatsByType( return 0; } -// Test cases - -const fakeHalls = [ - { - branch: "EL", - count: 10, - examType: ExamType.THEORY, - subjectCode: 2003, - }, - { - branch: "CS", - count: 10, - examType: ExamType.THEORY, - subjectCode: 2004, - }, - { - branch: "CS", - count: 20, - examType: ExamType.DRAWING, - subjectCode: 2005, - }, -]; - -const fakeStudentCount = [ - { - theoryOnlySeats: 5, - drawingOnlySeats: 0, - commonSeats: 0, - name: 106, - }, - { - theoryOnlySeats: 5, - drawingOnlySeats: 0, - commonSeats: 0, - name: 107, - }, - { - theoryOnlySeats: 0, - drawingOnlySeats: 0, - commonSeats: 6, - name: 108, - }, -]; - -const res = assignHallsCustom(fakeHalls, fakeStudentCount); - -console.log(res); +// // Test cases + +// const fakeHalls = [ +// { +// branch: "EL", +// count: 10, +// examType: ExamType.THEORY, +// subjectCode: 2003, +// }, +// { +// branch: "CS", +// count: 10, +// examType: ExamType.THEORY, +// subjectCode: 2004, +// }, +// { +// branch: "CS", +// count: 20, +// examType: ExamType.DRAWING, +// subjectCode: 2005, +// }, +// ]; + +// const fakeStudentCount = [ +// { +// theoryOnlySeats: 5, +// drawingOnlySeats: 0, +// commonSeats: 0, +// name: "106", +// }, +// { +// theoryOnlySeats: 5, +// drawingOnlySeats: 0, +// commonSeats: 0, +// name: "107", +// }, +// { +// theoryOnlySeats: 0, +// drawingOnlySeats: 0, +// commonSeats: 6, +// name: "108", +// }, +// ]; + +// const res = assignHallsCustom(fakeHalls, fakeStudentCount); + +// console.log(res); diff --git a/src/lib/examTools/hallSort.ts b/src/lib/examTools/hallSort.ts index 1f2312e..55124eb 100644 --- a/src/lib/examTools/hallSort.ts +++ b/src/lib/examTools/hallSort.ts @@ -1,14 +1,14 @@ import { ExamType } from "./customHallAsiign"; enum SeatType { - NOT_USABLE, THEORY_ONLY, DRAWING_ONLY, THEORY_AND_DRAWING, // Add THEORY_AND_DRAWING seat type + NOT_USABLE, } interface Student { - regNo: number; + regNo: string; subjectCode: number; examType: ExamType; // Add examType to student } @@ -26,7 +26,7 @@ type ExamHallStucture = SeatType[][]; // Use SeatType enum in ExamHallStucture * @param {SeatType[][]} examHall - A 2D array representing the exam hall with seat types. * @returns {AllocatedSeat[]} An array of seating assignments for students including row and seat numbers. */ -function allocateSeats( +export function allocateSeats( students: Student[], examHall: ExamHallStucture ): AllocatedSeat[] { @@ -119,8 +119,7 @@ function allocateSeats( examHall[chosenSeat.row][chosenSeat.seat] = SeatType.NOT_USABLE; availableSeats[student.subjectCode].push(chosenSeat); } else { - console.log("No usable seat available for student:"); - console.log(student); + console.log(`No usable seat available for student: ${student.regNo}`); } } } @@ -128,117 +127,117 @@ function allocateSeats( return seating; } -const examHall: ExamHallStucture = [ - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - SeatType.THEORY_AND_DRAWING, - ], - [ - SeatType.THEORY_AND_DRAWING, - SeatType.THEORY_AND_DRAWING, - SeatType.NOT_USABLE, - ], -]; - -const students: Student[] = [ - { subjectCode: 2002, regNo: 1, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 2, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 3, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 4, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 5, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 6, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 7, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 8, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 9, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 10, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 11, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 12, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 13, examType: ExamType.THEORY }, - { subjectCode: 2005, regNo: 14, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 15, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 16, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 17, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 18, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 19, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 20, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 21, examType: ExamType.THEORY }, - { subjectCode: 2001, regNo: 22, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 23, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 24, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 25, examType: ExamType.THEORY }, - { subjectCode: 2002, regNo: 26, examType: ExamType.THEORY }, -]; - -const seating = allocateSeats(students, examHall); - -// Display seating as a table with rows and seats -const seatingTable = seating.reduce( - (acc, student) => { - acc[student.row][student.seat] = `${student.subjectCode}-${student.regNo}`; - return acc; - }, - examHall.map((row) => row.map(() => "")) -); - -console.log(seatingTable); +// const examHall: ExamHallStucture = [ +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// SeatType.THEORY_AND_DRAWING, +// ], +// [ +// SeatType.THEORY_AND_DRAWING, +// SeatType.THEORY_AND_DRAWING, +// SeatType.NOT_USABLE, +// ], +// ]; + +// const students: Student[] = [ +// { subjectCode: 2002, regNo: "1", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "2", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "3", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "4", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "5", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "6", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "7", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "8", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "9", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "10", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "11", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "12", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "13", examType: ExamType.THEORY }, +// { subjectCode: 2005, regNo: "14", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "15", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "16", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "17", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "18", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "19", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "20", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "21", examType: ExamType.THEORY }, +// { subjectCode: 2001, regNo: "22", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "23", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "24", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "25", examType: ExamType.THEORY }, +// { subjectCode: 2002, regNo: "26", examType: ExamType.THEORY }, +// ]; + +// const seating = allocateSeats(students, examHall); + +// // Display seating as a table with rows and seats +// const seatingTable = seating.reduce( +// (acc, student) => { +// acc[student.row][student.seat] = `${student.subjectCode}-${student.regNo}`; +// return acc; +// }, +// examHall.map((row) => row.map(() => "")) +// ); + +// console.log(seatingTable);