more complex
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
"""
|
||||
Generates small illustrative dummy CSV datasets under data/dummy/ so the
|
||||
timetable template generator has something to schedule and render.
|
||||
Generates a larger, deliberately harder dummy CSV dataset under data/dummy/
|
||||
so the timetable template generator has something non-trivial to schedule
|
||||
and render — more departments/batches/sections than the previous small
|
||||
dataset, tighter room and instructor contention (fewer rooms/instructors
|
||||
relative to demand), a second block, and mixed lecture durations (90 vs
|
||||
120 minutes) so weaknesses in the scheduler surface as WARNINGs/conflicts
|
||||
instead of everything trivially fitting.
|
||||
|
||||
Run once:
|
||||
python data/dummy/generate_dummy_data.py
|
||||
@@ -23,13 +28,18 @@ def write_csv(relative_path, header, rows):
|
||||
|
||||
|
||||
def main():
|
||||
# ---- blocks & rooms (Building/Block A only) ----
|
||||
# ---- blocks: two blocks now, Block A (bigger) and Block B (smaller) ----
|
||||
write_csv(
|
||||
"blocks/blocks.csv",
|
||||
["block_id", "block_name"],
|
||||
[["A", "Block A"]],
|
||||
[
|
||||
["A", "Block A"],
|
||||
["B", "Block B"],
|
||||
],
|
||||
)
|
||||
|
||||
# ---- rooms: deliberately tight relative to demand (see offerings
|
||||
# below) so room contention is real, spread across both blocks ----
|
||||
write_csv(
|
||||
"blocks/rooms.csv",
|
||||
["room_id", "room_name", "block_id", "room_type", "capacity"],
|
||||
@@ -40,21 +50,32 @@ def main():
|
||||
["A-201", "Room 201", "A", "classroom", 60],
|
||||
["A-L01", "Computer Lab 1", "A", "lab", 35],
|
||||
["A-L02", "Computer Lab 2", "A", "lab", 35],
|
||||
["B-101", "Room 101 (B)", "B", "classroom", 50],
|
||||
["B-102", "Room 102 (B)", "B", "classroom", 50],
|
||||
["B-L01", "Electronics Lab", "B", "lab", 30],
|
||||
],
|
||||
)
|
||||
|
||||
# ---- departments / programs / batches ----
|
||||
# batch_code = session(2) + program_id(6) e.g. 25021519
|
||||
batches_25 = [
|
||||
["25021519", "CS", "BSCS", "25"],
|
||||
["25021520", "CS", "BSSE", "25"],
|
||||
["25031519", "EE", "BSEE", "25"],
|
||||
]
|
||||
batches_26 = [
|
||||
["26021519", "CS", "BSCS", "26"],
|
||||
["26021520", "CS", "BSSE", "26"],
|
||||
["26031519", "EE", "BSEE", "26"],
|
||||
]
|
||||
# ---- departments / programs / batches: 3 departments, 2 programs
|
||||
# each, 2 sessions (25/26) -> 12 batches total (was 6) ----
|
||||
department_programs = {
|
||||
"CS": ["BSCS", "BSSE"],
|
||||
"EE": ["BSEE", "BSCE"],
|
||||
"BBA": ["BBA", "BSAF"],
|
||||
}
|
||||
program_codes = {
|
||||
"BSCS": "021519", "BSSE": "021520",
|
||||
"BSEE": "031519", "BSCE": "031520",
|
||||
"BBA": "041519", "BSAF": "041520",
|
||||
}
|
||||
|
||||
batches_25 = []
|
||||
batches_26 = []
|
||||
for department, programs in department_programs.items():
|
||||
for program in programs:
|
||||
code = program_codes[program]
|
||||
batches_25.append([f"25{code}", department, program, "25"])
|
||||
batches_26.append([f"26{code}", department, program, "26"])
|
||||
|
||||
write_csv(
|
||||
"batch_codes/25/batches.csv",
|
||||
@@ -70,62 +91,86 @@ def main():
|
||||
all_batches = batches_25 + batches_26
|
||||
|
||||
# ---- courses ----
|
||||
# One row per subject: lectures/labs per week are counted separately so
|
||||
# a single course can carry both, and each course names its preferred
|
||||
# lecture/lab room (the scheduler falls back to another same-type room
|
||||
# only if the preferred one is busy).
|
||||
# is_general courses are shared across every batch of the same session
|
||||
# (so they can be scheduled together on Tuesday first, with no clash).
|
||||
# course_id, course_name, credit_hours, lectures_per_week,
|
||||
# labs_per_week, is_general, lecture_room_id, lab_room_id,
|
||||
# lecture_duration_minutes
|
||||
#
|
||||
# Mixed lecture durations: most courses are 90-min x N/week, but a few
|
||||
# are the special "2 hours once a week" case (lecture_duration_minutes
|
||||
# 120, lectures_per_week 1). Labs vary 0/1/2 per week. Deliberately
|
||||
# more courses per department than the room/instructor pool can
|
||||
# comfortably absorb without contention.
|
||||
courses = [
|
||||
# course_id, course_name, credit_hours, lectures_per_week, labs_per_week, is_general, lecture_room_id, lab_room_id
|
||||
["CS101", "Programming Fundamentals", 4, 2, 1, "no", "A-101", "A-L01"],
|
||||
["CS201", "Data Structures", 4, 2, 1, "no", "A-102", "A-L01"],
|
||||
["EE101", "Basic Electronics", 4, 2, 1, "no", "A-201", "A-L02"],
|
||||
["GEN101", "Functional English", 3, 2, 0, "yes", "A-103", ""],
|
||||
["GEN102", "Islamic Studies", 2, 1, 0, "yes", "A-103", ""],
|
||||
# CS department courses
|
||||
["CS101", "Programming Fundamentals", 4, 2, 1, "no", "A-101", "A-L01", 90],
|
||||
["CS201", "Data Structures", 4, 2, 1, "no", "A-102", "A-L01", 90],
|
||||
["CS301", "Operating Systems", 3, 1, 1, "no", "A-101", "A-L02", 120],
|
||||
["CS302", "Database Systems", 4, 2, 2, "no", "A-102", "A-L02", 90],
|
||||
# EE department courses
|
||||
["EE101", "Basic Electronics", 4, 2, 1, "no", "A-201", "A-L02", 90],
|
||||
["EE201", "Digital Logic Design", 4, 2, 1, "no", "B-101", "B-L01", 90],
|
||||
["EE301", "Signals and Systems", 3, 1, 0, "no", "B-102", "", 120],
|
||||
# BBA department courses
|
||||
["BBA101", "Principles of Management", 3, 2, 0, "no", "B-101", "", 90],
|
||||
["BBA201", "Financial Accounting", 3, 2, 0, "no", "B-102", "", 90],
|
||||
["BBA301", "Marketing Management", 3, 1, 0, "no", "A-103", "", 120],
|
||||
# General (shared) courses
|
||||
["GEN101", "Functional English", 3, 2, 0, "yes", "A-103", "", 90],
|
||||
["GEN102", "Islamic Studies", 2, 1, 0, "yes", "A-103", "", 90],
|
||||
["GEN103", "Pakistan Studies", 2, 1, 0, "yes", "B-101", "", 120],
|
||||
]
|
||||
write_csv(
|
||||
"courses/courses.csv",
|
||||
[
|
||||
"course_id", "course_name", "credit_hours", "lectures_per_week",
|
||||
"labs_per_week", "is_general", "lecture_room_id", "lab_room_id",
|
||||
"lecture_duration_minutes",
|
||||
],
|
||||
courses,
|
||||
)
|
||||
|
||||
# ---- course offerings: course + section (a section groups the batches
|
||||
# taking that section together) + who teaches it ----
|
||||
# A course can have many sections; here each CS/EE batch of a session is
|
||||
# its own section (Section A/B/...), while general courses have a single
|
||||
# section "ALL" grouping every batch of that session.
|
||||
offerings = []
|
||||
|
||||
dept_course = {"CS": ["CS101", "CS201"], "EE": ["EE101"]}
|
||||
# ---- course offerings: course + section (batches in that section) +
|
||||
# instructor ----
|
||||
# Deliberately tight instructor pool reused across many sections/
|
||||
# courses (some instructors will end up wanted in overlapping slots),
|
||||
# forcing real contention in Phase 2/Phase 3.
|
||||
dept_courses = {
|
||||
"CS": ["CS101", "CS201", "CS301", "CS302"],
|
||||
"EE": ["EE101", "EE201", "EE301"],
|
||||
"BBA": ["BBA101", "BBA201", "BBA301"],
|
||||
}
|
||||
# Small pools relative to (department batches x courses) demand.
|
||||
dept_instructors = {
|
||||
"CS": ["1001", "1002", "1003", "1006"],
|
||||
"CS": ["1001", "1002", "1003"],
|
||||
"EE": ["1004", "1005"],
|
||||
"BBA": ["1007", "1008"],
|
||||
}
|
||||
|
||||
offerings = []
|
||||
section_letters = ["A", "B", "C", "D"]
|
||||
dept_section_counter = {"CS": 0, "EE": 0}
|
||||
dept_section_counter = {"CS": 0, "EE": 0, "BBA": 0}
|
||||
|
||||
for batch_code, department, program, session in all_batches:
|
||||
section_id = section_letters[dept_section_counter[department] % len(section_letters)]
|
||||
dept_section_counter[department] += 1
|
||||
|
||||
for i, course_id in enumerate(dept_course[department]):
|
||||
instr_pool = dept_instructors[department]
|
||||
instr_pool = dept_instructors[department]
|
||||
for i, course_id in enumerate(dept_courses[department]):
|
||||
# Deliberately narrow instructor rotation (2-3 instructors
|
||||
# covering 3-4 courses per department) so the same instructor
|
||||
# teaches multiple courses/sections -> instructor contention.
|
||||
instr = instr_pool[i % len(instr_pool)]
|
||||
offerings.append([course_id, section_id, batch_code, instr])
|
||||
|
||||
# general courses: one offering per (course, session), section "ALL"
|
||||
# grouping every batch code sharing that session, separated by "|"
|
||||
# grouping every batch code sharing that session
|
||||
for session, batch_group in (
|
||||
("25", [b[0] for b in batches_25]),
|
||||
("26", [b[0] for b in batches_26]),
|
||||
):
|
||||
offerings.append(["GEN101", "ALL", "|".join(batch_group), "1002"])
|
||||
offerings.append(["GEN102", "ALL", "|".join(batch_group), "1006"])
|
||||
offerings.append(["GEN103", "ALL", "|".join(batch_group), "1006"])
|
||||
|
||||
write_csv(
|
||||
"courses/course_offering.csv",
|
||||
@@ -143,6 +188,8 @@ def main():
|
||||
"1004": "Dr. Farah Iqbal",
|
||||
"1005": "Mr. Usman Ali",
|
||||
"1006": "Ms. Hira Shah",
|
||||
"1007": "Dr. Nadia Farooq",
|
||||
"1008": "Mr. Kamran Sheikh",
|
||||
}
|
||||
instructors = []
|
||||
for course_id, section_id, batch_codes, instr_code in offerings:
|
||||
@@ -154,10 +201,10 @@ def main():
|
||||
instructors,
|
||||
)
|
||||
|
||||
# ---- students (roll_no = batch_code-seq) ----
|
||||
# ---- students (roll_no = batch_code-seq): 18 per batch (was 5) ----
|
||||
students = []
|
||||
for batch_code, department, program, session in all_batches:
|
||||
for seq in range(1, 6): # 5 sample students per batch
|
||||
for seq in range(1, 19):
|
||||
roll_no = f"{batch_code}-{seq:03d}"
|
||||
students.append([roll_no, batch_code, f"Student {roll_no}"])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user