Skip to content

Commit

Permalink
exam hall assignment
Browse files Browse the repository at this point in the history
  • Loading branch information
amjed-ali-k committed Oct 25, 2023
1 parent 5209d48 commit d8ead76
Show file tree
Hide file tree
Showing 3 changed files with 311 additions and 176 deletions.
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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";

Expand Down Expand Up @@ -104,21 +124,134 @@ function CreateExamFrom() {
onSuccess={() => settab("generate-section")}
/>
</TabsContent>
<TabsContent value="generate-section">
<GenerateSection
finalBatches={finalBatches}
finalHalls={finalHalls}
/>
</TabsContent>
</Tabs>
</div>
);
}

export default CreateExamFrom;

type IncomeStudent = {
name?: string | undefined;
rollNumber?: string | undefined;
regNumber?: string | undefined;
admnNumber?: string | undefined;
primaryNumber?: string | undefined;
};

function GenerateSection({
finalHalls,
finalBatches,
}: {
finalHalls: ExamHall[];
finalBatches: BatchWithSub[];
}) {
return <div></div>;
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 (
<Card className="w-full">
<CardContent className="p-4">
<div className="flex flex-col space-y-2">
<div className="flex items-center">
<CheckCircle2 className="mr-2 text-green-500" /> Validating inputs
</div>
<div className="flex items-center">
<CheckCircle2 className="mr-2 text-green-500" /> Processing data
</div>
<div className="flex items-center">
<CheckCircle2 className="mr-2 text-green-500" /> Alloting halls for
students
</div>
<div className="flex items-center">
<PlayCircle className="mr-2 animate-spin" /> Assigning students in
each halls
</div>
</div>
</CardContent>
</Card>
);
}

const schema = z.object({
Expand Down
111 changes: 57 additions & 54 deletions src/lib/examTools/customHallAsiign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface ExamHallSeatsCount {
commonSeats: number;
theoryOnlySeats: number;
drawingOnlySeats: number;
name: number;
name: string;
}

/**
Expand All @@ -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)
Expand Down Expand Up @@ -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),
Expand All @@ -112,7 +116,6 @@ export function assignHallsCustom(
if (!(remainingStudents > 1)) {
throw "No students remaining";
}
console.log(remainingStudents);
const seats2Assign =
seatsToAssign < remainingStudents
? seatsToAssign
Expand Down Expand Up @@ -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);
Loading

0 comments on commit d8ead76

Please sign in to comment.