Skip to content
87 changes: 87 additions & 0 deletions Constants/Teachers_tt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import json
from Samples.samples import (SubjectTeacherMap, WorkingDays, SampleChromosome)

class TeacherTimetable:
def __init__(self):
# Create timetable for each teacher
self.teacher_timetable = {
teacher: {day: [] for day in WorkingDays.days}
for teachers in SubjectTeacherMap.subject_teacher_map.values()
for teacher in teachers
}
self.teacher_assignments = {teacher: {} for teachers in SubjectTeacherMap.subject_teacher_map.values() for teacher in teachers}

def generate_teacher_timetable(self, chromosome):
"""
Populate the teacher's timetable based on the provided chromosome schedule.
Now includes the course (Week 1, Week 2, etc.) information.
"""
for week, days in chromosome.items():
for day, sections in days.items():
for section, classes in sections.items():
for entry in classes:
teacher_id = entry["teacher_id"]
subject_id = entry["subject_id"]
time_slot = entry["time_slot"]
classroom_id = entry["classroom_id"]

# Conflict check: Ensure the teacher is not already assigned at this time slot
if teacher_id in self.teacher_assignments and time_slot in self.teacher_assignments[teacher_id]:
continue # Skip this assignment if there's a conflict

# Add the class to the teacher's timetable
self.teacher_timetable[teacher_id][day].append({
"course": week, # Include course information (Week 1, Week 2)
"section": section,
"subject_id": subject_id,
"time_slot": time_slot,
"classroom_id": classroom_id,
})

# Update the teacher's assignments to reflect the added class
if teacher_id not in self.teacher_assignments:
self.teacher_assignments[teacher_id] = {}
self.teacher_assignments[teacher_id][time_slot] = {
"course": week,
"section": section,
"subject_id": subject_id,
"classroom_id": classroom_id,
"day": day
}

return self.teacher_timetable

def save_timetable_to_json(self, file_path="Constants/teacher_timetable.json"):
"""
Create a dictionary and save the teacher's timetable to a JSON file.
"""
try:
# Create a dictionary explicitly from the teacher timetable
timetable_dict = {
teacher: {
day: classes
for day, classes in days.items()
}
for teacher, days in self.teacher_timetable.items()
}

# Save the dictionary to a JSON file
with open(file_path, "w") as json_file:
json.dump(timetable_dict, json_file, indent=4)

print(f"Timetable successfully saved to '{file_path}'.")
except Exception as e:
print(f"Error saving timetable to '{file_path}': {e}")

if __name__ == "__main__":
teacher_timetable = TeacherTimetable()
# Generate timetable from the sample chromosome (Week 1 and Week 2)
w = {
"Week 2": SampleChromosome.schedule2,
"Week 1": SampleChromosome.schedule1
}

teacher_tt=teacher_timetable.generate_teacher_timetable(w)
print(teacher_tt)
# Save timetable to a JSON file
teacher_timetable.save_timetable_to_json()
83 changes: 35 additions & 48 deletions Constants/section_allocation.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import random
from collections import defaultdict
from typing import List, Dict
from Constants.constant import SectionsConstants
from Constants.constant import SectionsConstants, Defaults
from Samples.Adhocs.common import generate_students


class StudentScorer:
def __init__(self, attribute_weights: Dict[str, int] = None):
def __init__(self, students: list, attribute_weights: Dict[str, int] = None):
"""
Initialize the scorer with attribute weights.

Defaults to SectionsConstants.ATTRIBUTE_WEIGHTS if not provided.
"""

self.attribute_weights = attribute_weights or SectionsConstants.ATTRIBUTE_WEIGHTS
self.students = students


def calculate_dynamic_cgpa_threshold(self, students: List[Dict], top_percentage: int = 30) -> float:
"""
Calculate the CGPA threshold for the top X% of students.
Calculate the CGPA threshold for the top X% of students.

Args:
students (List[Dict]): List of student dictionaries with 'CGPA'.
top_percentage (int): Percentage of students considered top.
Args:
students (List[Dict]): List of student dictionaries with 'CGPA'.
top_percentage (int): Percentage of students considered top.

Returns:
float: The CGPA threshold.
Returns:
float: The CGPA threshold.

"""

Expand Down Expand Up @@ -111,54 +113,39 @@ def divide_students_into_sections(self, students: List[Dict], class_strength: in

return sections

def entry_point_for_section_divide(self):

# Calculate the dynamic CGPA threshold
cgpa_threshold_calc = self.calculate_dynamic_cgpa_threshold(
self.students,
top_percentage=30
)

# Assign conditions and scores
self.assign_dynamic_conditions(cgpa_threshold_calc)
students_with_scores = self.assign_scores_to_students(self.students)

# Divide students into sections
class_strength = Defaults.max_class_capacity
sections = self.divide_students_into_sections(
students_with_scores,
class_strength
)

section_allocated_students = list()

def generate_students(num_students: int = 500) -> List[Dict]:
"""
Generate a list of random students with CGPA and hostler status.
for i, section in enumerate(sections, 1):
for student in section:
student["section"] = chr(64 + i)
section_allocated_students.append(student)

Args:
num_students (int): Number of students to generate.
return section_allocated_students

Returns:
List[Dict]: List of student dictionaries.
"""

return [
{
'ID': i,
'CGPA': round(random.uniform(6.0, 9.8), 2),
'Hostler': random.choice([True, False])
}
for i in range(1, num_students + 1)
]


if __name__ == "__main__":
# Initialize constants and scorer
scorer = StudentScorer()
students = generate_students(num_students=500)

# Calculate the dynamic CGPA threshold
cgpa_threshold = scorer.calculate_dynamic_cgpa_threshold(students, top_percentage=30)
print(f"Dynamic CGPA Threshold (Top 30%): {cgpa_threshold}")

# Assign conditions and scores
scorer.assign_dynamic_conditions(cgpa_threshold)
students_with_scores = scorer.assign_scores_to_students(students)

# Divide students into sections
class_strength = 50
sections = scorer.divide_students_into_sections(students_with_scores, class_strength)

# Display the sections
for i, section in enumerate(sections, 1):
print(f"Section {i} (Total Students: {len(section)}):")
for student in section:
print(
f" Student ID: {student['ID']}, CGPA: {student['CGPA']}, "
f"Hostler: {student['Hostler']}, score: {student['score']}"
)

scorer = StudentScorer(generate_students(num_students=500))
from icecream import ic
ic(scorer.entry_point_for_section_divide())
Loading