diff --git a/sampleData/sampleData_AllAttendanceLists.csv b/sampleData/sampleData_AllAttendanceLists.csv index 6d2668c..f278768 100644 --- a/sampleData/sampleData_AllAttendanceLists.csv +++ b/sampleData/sampleData_AllAttendanceLists.csv @@ -1,59 +1,89 @@ CourseCode_01 -['Std_ID_170', 'Std_ID_077', 'Std_ID_097', 'Std_ID_202', 'Std_ID_080', 'Std_ID_126', 'Std_ID_112', 'Std_ID_175', 'Std_ID_180', 'Std_ID_139', 'Std_ID_181', 'Std_ID_222', 'Std_ID_243', 'Std_ID_167', 'Std_ID_136', 'Std_ID_021', 'Std_ID_041', 'Std_ID_231', 'Std_ID_062', 'Std_ID_138', 'Std_ID_236', 'Std_ID_221', 'Std_ID_006', 'Std_ID_135', 'Std_ID_209', 'Std_ID_239', 'Std_ID_043', 'Std_ID_182', 'Std_ID_246', 'Std_ID_083', 'Std_ID_056', 'Std_ID_047', 'Std_ID_193', 'Std_ID_107', 'Std_ID_216', 'Std_ID_005', 'Std_ID_096', 'Std_ID_140', 'Std_ID_233', 'Std_ID_168'] +['Std_ID_001', 'Std_ID_005', 'Std_ID_009', 'Std_ID_013', 'Std_ID_017', 'Std_ID_021', 'Std_ID_025', 'Std_ID_029', 'Std_ID_033', 'Std_ID_037', 'Std_ID_041', 'Std_ID_045', 'Std_ID_049', 'Std_ID_053', 'Std_ID_057', 'Std_ID_061', 'Std_ID_065', 'Std_ID_069', 'Std_ID_073', 'Std_ID_077', 'Std_ID_081', 'Std_ID_085', 'Std_ID_089', 'Std_ID_093', 'Std_ID_097', 'Std_ID_101', 'Std_ID_105', 'Std_ID_109', 'Std_ID_113', 'Std_ID_117', 'Std_ID_121', 'Std_ID_125', 'Std_ID_400', 'Std_ID_405', 'Std_ID_410'] CourseCode_02 -['Std_ID_238', 'Std_ID_132', 'Std_ID_079', 'Std_ID_139', 'Std_ID_116', 'Std_ID_093', 'Std_ID_190', 'Std_ID_121', 'Std_ID_108', 'Std_ID_005', 'Std_ID_210', 'Std_ID_018', 'Std_ID_152', 'Std_ID_033', 'Std_ID_199', 'Std_ID_073', 'Std_ID_193', 'Std_ID_220', 'Std_ID_222', 'Std_ID_188', 'Std_ID_217', 'Std_ID_008', 'Std_ID_123', 'Std_ID_159', 'Std_ID_227', 'Std_ID_136', 'Std_ID_187', 'Std_ID_216', 'Std_ID_056', 'Std_ID_026', 'Std_ID_099', 'Std_ID_146', 'Std_ID_055', 'Std_ID_057', 'Std_ID_035', 'Std_ID_049', 'Std_ID_144', 'Std_ID_232', 'Std_ID_098', 'Std_ID_058'] +['Std_ID_002', 'Std_ID_006', 'Std_ID_010', 'Std_ID_014', 'Std_ID_018', 'Std_ID_022', 'Std_ID_026', 'Std_ID_030', 'Std_ID_034', 'Std_ID_038', 'Std_ID_042', 'Std_ID_046', 'Std_ID_050', 'Std_ID_054', 'Std_ID_058', 'Std_ID_062', 'Std_ID_066', 'Std_ID_070', 'Std_ID_074', 'Std_ID_078', 'Std_ID_082', 'Std_ID_086', 'Std_ID_090', 'Std_ID_094', 'Std_ID_098', 'Std_ID_102', 'Std_ID_106', 'Std_ID_110', 'Std_ID_114', 'Std_ID_118', 'Std_ID_122', 'Std_ID_126', 'Std_ID_401', 'Std_ID_406', 'Std_ID_411'] CourseCode_03 -['Std_ID_098', 'Std_ID_070', 'Std_ID_049', 'Std_ID_191', 'Std_ID_109', 'Std_ID_196', 'Std_ID_209', 'Std_ID_189', 'Std_ID_039', 'Std_ID_219', 'Std_ID_009', 'Std_ID_033', 'Std_ID_059', 'Std_ID_174', 'Std_ID_169', 'Std_ID_122', 'Std_ID_057', 'Std_ID_249', 'Std_ID_142', 'Std_ID_229', 'Std_ID_038', 'Std_ID_132', 'Std_ID_140', 'Std_ID_081', 'Std_ID_243', 'Std_ID_150', 'Std_ID_099', 'Std_ID_224', 'Std_ID_097', 'Std_ID_193', 'Std_ID_043', 'Std_ID_055', 'Std_ID_061', 'Std_ID_212', 'Std_ID_205', 'Std_ID_146', 'Std_ID_100', 'Std_ID_149', 'Std_ID_116', 'Std_ID_233'] +['Std_ID_003', 'Std_ID_007', 'Std_ID_011', 'Std_ID_015', 'Std_ID_019', 'Std_ID_023', 'Std_ID_027', 'Std_ID_031', 'Std_ID_035', 'Std_ID_039', 'Std_ID_043', 'Std_ID_047', 'Std_ID_051', 'Std_ID_055', 'Std_ID_059', 'Std_ID_063', 'Std_ID_067', 'Std_ID_071', 'Std_ID_075', 'Std_ID_079', 'Std_ID_083', 'Std_ID_087', 'Std_ID_091', 'Std_ID_095', 'Std_ID_099', 'Std_ID_103', 'Std_ID_107', 'Std_ID_111', 'Std_ID_115', 'Std_ID_119', 'Std_ID_123', 'Std_ID_127', 'Std_ID_402', 'Std_ID_407', 'Std_ID_412'] CourseCode_04 -['Std_ID_142', 'Std_ID_085', 'Std_ID_103', 'Std_ID_059', 'Std_ID_243', 'Std_ID_106', 'Std_ID_069', 'Std_ID_014', 'Std_ID_015', 'Std_ID_088', 'Std_ID_136', 'Std_ID_020', 'Std_ID_097', 'Std_ID_190', 'Std_ID_194', 'Std_ID_201', 'Std_ID_125', 'Std_ID_182', 'Std_ID_138', 'Std_ID_105', 'Std_ID_076', 'Std_ID_007', 'Std_ID_066', 'Std_ID_189', 'Std_ID_129', 'Std_ID_133', 'Std_ID_034', 'Std_ID_130', 'Std_ID_247', 'Std_ID_024', 'Std_ID_027', 'Std_ID_115', 'Std_ID_064', 'Std_ID_132', 'Std_ID_113', 'Std_ID_118', 'Std_ID_162', 'Std_ID_154', 'Std_ID_181', 'Std_ID_114'] +['Std_ID_004', 'Std_ID_008', 'Std_ID_012', 'Std_ID_016', 'Std_ID_020', 'Std_ID_024', 'Std_ID_028', 'Std_ID_032', 'Std_ID_036', 'Std_ID_040', 'Std_ID_044', 'Std_ID_048', 'Std_ID_052', 'Std_ID_056', 'Std_ID_060', 'Std_ID_064', 'Std_ID_068', 'Std_ID_072', 'Std_ID_076', 'Std_ID_080', 'Std_ID_084', 'Std_ID_088', 'Std_ID_092', 'Std_ID_096', 'Std_ID_100', 'Std_ID_104', 'Std_ID_108', 'Std_ID_112', 'Std_ID_116', 'Std_ID_120', 'Std_ID_124', 'Std_ID_128', 'Std_ID_403', 'Std_ID_408', 'Std_ID_413'] CourseCode_05 -['Std_ID_203', 'Std_ID_236', 'Std_ID_192', 'Std_ID_198', 'Std_ID_213', 'Std_ID_147', 'Std_ID_051', 'Std_ID_095', 'Std_ID_226', 'Std_ID_077', 'Std_ID_230', 'Std_ID_035', 'Std_ID_142', 'Std_ID_195', 'Std_ID_182', 'Std_ID_064', 'Std_ID_229', 'Std_ID_239', 'Std_ID_119', 'Std_ID_231', 'Std_ID_217', 'Std_ID_054', 'Std_ID_163', 'Std_ID_148', 'Std_ID_249', 'Std_ID_068', 'Std_ID_202', 'Std_ID_225', 'Std_ID_101', 'Std_ID_126', 'Std_ID_150', 'Std_ID_197', 'Std_ID_025', 'Std_ID_140', 'Std_ID_124', 'Std_ID_053', 'Std_ID_075', 'Std_ID_074', 'Std_ID_243', 'Std_ID_169'] +['Std_ID_001', 'Std_ID_002', 'Std_ID_005', 'Std_ID_006', 'Std_ID_009', 'Std_ID_010', 'Std_ID_013', 'Std_ID_014', 'Std_ID_017', 'Std_ID_018', 'Std_ID_021', 'Std_ID_022', 'Std_ID_025', 'Std_ID_026', 'Std_ID_029', 'Std_ID_030', 'Std_ID_033', 'Std_ID_034', 'Std_ID_037', 'Std_ID_038', 'Std_ID_041', 'Std_ID_042', 'Std_ID_045', 'Std_ID_046', 'Std_ID_049', 'Std_ID_050', 'Std_ID_053', 'Std_ID_054', 'Std_ID_057', 'Std_ID_058', 'Std_ID_061', 'Std_ID_062', 'Std_ID_065', 'Std_ID_066', 'Std_ID_069', 'Std_ID_070', 'Std_ID_073', 'Std_ID_404', 'Std_ID_409', 'Std_ID_414'] CourseCode_06 -['Std_ID_129', 'Std_ID_175', 'Std_ID_049', 'Std_ID_238', 'Std_ID_056', 'Std_ID_187', 'Std_ID_064', 'Std_ID_151', 'Std_ID_201', 'Std_ID_022', 'Std_ID_169', 'Std_ID_220', 'Std_ID_147', 'Std_ID_223', 'Std_ID_011', 'Std_ID_053', 'Std_ID_166', 'Std_ID_111', 'Std_ID_219', 'Std_ID_112', 'Std_ID_203', 'Std_ID_054', 'Std_ID_106', 'Std_ID_025', 'Std_ID_073', 'Std_ID_234', 'Std_ID_027', 'Std_ID_215', 'Std_ID_028', 'Std_ID_208', 'Std_ID_192', 'Std_ID_172', 'Std_ID_015', 'Std_ID_164', 'Std_ID_110', 'Std_ID_010', 'Std_ID_078', 'Std_ID_006', 'Std_ID_204', 'Std_ID_029'] +['Std_ID_003', 'Std_ID_004', 'Std_ID_007', 'Std_ID_008', 'Std_ID_011', 'Std_ID_012', 'Std_ID_015', 'Std_ID_016', 'Std_ID_019', 'Std_ID_020', 'Std_ID_023', 'Std_ID_024', 'Std_ID_027', 'Std_ID_028', 'Std_ID_031', 'Std_ID_032', 'Std_ID_035', 'Std_ID_036', 'Std_ID_039', 'Std_ID_040', 'Std_ID_043', 'Std_ID_044', 'Std_ID_047', 'Std_ID_048', 'Std_ID_051', 'Std_ID_052', 'Std_ID_055', 'Std_ID_056', 'Std_ID_059', 'Std_ID_060', 'Std_ID_063', 'Std_ID_064', 'Std_ID_067', 'Std_ID_068', 'Std_ID_071', 'Std_ID_072', 'Std_ID_075'] CourseCode_07 -['Std_ID_040', 'Std_ID_102', 'Std_ID_186', 'Std_ID_206', 'Std_ID_113', 'Std_ID_135', 'Std_ID_145', 'Std_ID_165', 'Std_ID_028', 'Std_ID_235', 'Std_ID_144', 'Std_ID_085', 'Std_ID_026', 'Std_ID_203', 'Std_ID_231', 'Std_ID_124', 'Std_ID_190', 'Std_ID_089', 'Std_ID_074', 'Std_ID_222', 'Std_ID_179', 'Std_ID_127', 'Std_ID_041', 'Std_ID_133', 'Std_ID_181', 'Std_ID_095', 'Std_ID_034', 'Std_ID_219', 'Std_ID_148', 'Std_ID_037', 'Std_ID_061', 'Std_ID_188', 'Std_ID_171', 'Std_ID_238', 'Std_ID_242', 'Std_ID_029', 'Std_ID_182', 'Std_ID_072', 'Std_ID_161', 'Std_ID_093'] +['Std_ID_076', 'Std_ID_077', 'Std_ID_078', 'Std_ID_079', 'Std_ID_080', 'Std_ID_081', 'Std_ID_082', 'Std_ID_083', 'Std_ID_084', 'Std_ID_085', 'Std_ID_086', 'Std_ID_087', 'Std_ID_088', 'Std_ID_089', 'Std_ID_090', 'Std_ID_091', 'Std_ID_092', 'Std_ID_093', 'Std_ID_094', 'Std_ID_095', 'Std_ID_096', 'Std_ID_097', 'Std_ID_098', 'Std_ID_099', 'Std_ID_100', 'Std_ID_101', 'Std_ID_102', 'Std_ID_103', 'Std_ID_104', 'Std_ID_105', 'Std_ID_106', 'Std_ID_107', 'Std_ID_108', 'Std_ID_109', 'Std_ID_110', 'Std_ID_111', 'Std_ID_112', 'Std_ID_113', 'Std_ID_114', 'Std_ID_115', 'Std_ID_116', 'Std_ID_117', 'Std_ID_118', 'Std_ID_119', 'Std_ID_120', 'Std_ID_121', 'Std_ID_122', 'Std_ID_123', 'Std_ID_124', 'Std_ID_125', 'Std_ID_126', 'Std_ID_127', 'Std_ID_128'] CourseCode_08 -['Std_ID_009', 'Std_ID_108', 'Std_ID_116', 'Std_ID_111', 'Std_ID_058', 'Std_ID_086', 'Std_ID_128', 'Std_ID_106', 'Std_ID_187', 'Std_ID_115', 'Std_ID_101', 'Std_ID_096', 'Std_ID_063', 'Std_ID_192', 'Std_ID_091', 'Std_ID_195', 'Std_ID_236', 'Std_ID_039', 'Std_ID_042', 'Std_ID_052', 'Std_ID_032', 'Std_ID_137', 'Std_ID_181', 'Std_ID_071', 'Std_ID_127', 'Std_ID_130', 'Std_ID_089', 'Std_ID_165', 'Std_ID_175', 'Std_ID_207', 'Std_ID_121', 'Std_ID_233', 'Std_ID_033', 'Std_ID_080', 'Std_ID_240', 'Std_ID_152', 'Std_ID_209', 'Std_ID_050', 'Std_ID_017', 'Std_ID_075'] +['Std_ID_129', 'Std_ID_133', 'Std_ID_137', 'Std_ID_141', 'Std_ID_145', 'Std_ID_149', 'Std_ID_153', 'Std_ID_157', 'Std_ID_161', 'Std_ID_165', 'Std_ID_169', 'Std_ID_173', 'Std_ID_177', 'Std_ID_181', 'Std_ID_185', 'Std_ID_189', 'Std_ID_193', 'Std_ID_197', 'Std_ID_201', 'Std_ID_205', 'Std_ID_209', 'Std_ID_213', 'Std_ID_217', 'Std_ID_221', 'Std_ID_225', 'Std_ID_229', 'Std_ID_233', 'Std_ID_237', 'Std_ID_241', 'Std_ID_245', 'Std_ID_249', 'Std_ID_253', 'Std_ID_050', 'Std_ID_051', 'Std_ID_052'] CourseCode_09 -['Std_ID_043', 'Std_ID_203', 'Std_ID_040', 'Std_ID_163', 'Std_ID_142', 'Std_ID_137', 'Std_ID_220', 'Std_ID_126', 'Std_ID_032', 'Std_ID_157', 'Std_ID_159', 'Std_ID_219', 'Std_ID_175', 'Std_ID_015', 'Std_ID_177', 'Std_ID_217', 'Std_ID_008', 'Std_ID_070', 'Std_ID_048', 'Std_ID_033', 'Std_ID_188', 'Std_ID_078', 'Std_ID_097', 'Std_ID_121', 'Std_ID_183', 'Std_ID_016', 'Std_ID_181', 'Std_ID_080', 'Std_ID_119', 'Std_ID_206', 'Std_ID_093', 'Std_ID_195', 'Std_ID_002', 'Std_ID_098', 'Std_ID_200', 'Std_ID_090', 'Std_ID_167', 'Std_ID_088', 'Std_ID_041', 'Std_ID_164'] +['Std_ID_130', 'Std_ID_134', 'Std_ID_138', 'Std_ID_142', 'Std_ID_146', 'Std_ID_150', 'Std_ID_154', 'Std_ID_158', 'Std_ID_162', 'Std_ID_166', 'Std_ID_170', 'Std_ID_174', 'Std_ID_178', 'Std_ID_182', 'Std_ID_186', 'Std_ID_190', 'Std_ID_194', 'Std_ID_198', 'Std_ID_202', 'Std_ID_206', 'Std_ID_210', 'Std_ID_214', 'Std_ID_218', 'Std_ID_222', 'Std_ID_226', 'Std_ID_230', 'Std_ID_234', 'Std_ID_238', 'Std_ID_242', 'Std_ID_246', 'Std_ID_250', 'Std_ID_254', 'Std_ID_053', 'Std_ID_054', 'Std_ID_055'] CourseCode_10 -['Std_ID_229', 'Std_ID_167', 'Std_ID_228', 'Std_ID_193', 'Std_ID_025', 'Std_ID_205', 'Std_ID_163', 'Std_ID_225', 'Std_ID_194', 'Std_ID_240', 'Std_ID_247', 'Std_ID_233', 'Std_ID_181', 'Std_ID_121', 'Std_ID_152', 'Std_ID_131', 'Std_ID_026', 'Std_ID_217', 'Std_ID_124', 'Std_ID_010', 'Std_ID_054', 'Std_ID_129', 'Std_ID_003', 'Std_ID_211', 'Std_ID_090', 'Std_ID_092', 'Std_ID_024', 'Std_ID_144', 'Std_ID_201', 'Std_ID_049', 'Std_ID_171', 'Std_ID_082', 'Std_ID_136', 'Std_ID_042', 'Std_ID_224', 'Std_ID_027', 'Std_ID_021', 'Std_ID_160', 'Std_ID_235', 'Std_ID_072'] +['Std_ID_131', 'Std_ID_135', 'Std_ID_139', 'Std_ID_143', 'Std_ID_147', 'Std_ID_151', 'Std_ID_155', 'Std_ID_159', 'Std_ID_163', 'Std_ID_167', 'Std_ID_171', 'Std_ID_175', 'Std_ID_179', 'Std_ID_183', 'Std_ID_187', 'Std_ID_191', 'Std_ID_195', 'Std_ID_199', 'Std_ID_203', 'Std_ID_207', 'Std_ID_211', 'Std_ID_215', 'Std_ID_219', 'Std_ID_223', 'Std_ID_227', 'Std_ID_231', 'Std_ID_235', 'Std_ID_239', 'Std_ID_243', 'Std_ID_247', 'Std_ID_251', 'Std_ID_255', 'Std_ID_056', 'Std_ID_057', 'Std_ID_058'] CourseCode_11 -['Std_ID_208', 'Std_ID_237', 'Std_ID_061', 'Std_ID_133', 'Std_ID_119', 'Std_ID_132', 'Std_ID_168', 'Std_ID_238', 'Std_ID_170', 'Std_ID_190', 'Std_ID_066', 'Std_ID_093', 'Std_ID_243', 'Std_ID_148', 'Std_ID_205', 'Std_ID_033', 'Std_ID_078', 'Std_ID_191', 'Std_ID_111', 'Std_ID_090', 'Std_ID_079', 'Std_ID_083', 'Std_ID_086', 'Std_ID_020', 'Std_ID_029', 'Std_ID_022', 'Std_ID_131', 'Std_ID_071', 'Std_ID_055', 'Std_ID_141', 'Std_ID_049', 'Std_ID_115', 'Std_ID_202', 'Std_ID_122', 'Std_ID_075', 'Std_ID_222', 'Std_ID_149', 'Std_ID_021', 'Std_ID_018', 'Std_ID_124'] +['Std_ID_132', 'Std_ID_136', 'Std_ID_140', 'Std_ID_144', 'Std_ID_148', 'Std_ID_152', 'Std_ID_156', 'Std_ID_160', 'Std_ID_164', 'Std_ID_168', 'Std_ID_172', 'Std_ID_176', 'Std_ID_180', 'Std_ID_184', 'Std_ID_188', 'Std_ID_192', 'Std_ID_196', 'Std_ID_200', 'Std_ID_204', 'Std_ID_208', 'Std_ID_212', 'Std_ID_216', 'Std_ID_220', 'Std_ID_224', 'Std_ID_228', 'Std_ID_232', 'Std_ID_236', 'Std_ID_240', 'Std_ID_244', 'Std_ID_248', 'Std_ID_252', 'Std_ID_256', 'Std_ID_059', 'Std_ID_060', 'Std_ID_061'] CourseCode_12 -['Std_ID_066', 'Std_ID_052', 'Std_ID_091', 'Std_ID_008', 'Std_ID_148', 'Std_ID_003', 'Std_ID_040', 'Std_ID_187', 'Std_ID_170', 'Std_ID_147', 'Std_ID_111', 'Std_ID_027', 'Std_ID_142', 'Std_ID_188', 'Std_ID_202', 'Std_ID_176', 'Std_ID_079', 'Std_ID_145', 'Std_ID_058', 'Std_ID_089', 'Std_ID_190', 'Std_ID_044', 'Std_ID_062', 'Std_ID_112', 'Std_ID_099', 'Std_ID_220', 'Std_ID_203', 'Std_ID_222', 'Std_ID_117', 'Std_ID_061', 'Std_ID_118', 'Std_ID_217', 'Std_ID_109', 'Std_ID_223', 'Std_ID_002', 'Std_ID_019', 'Std_ID_121', 'Std_ID_100', 'Std_ID_152', 'Std_ID_213'] +['Std_ID_129', 'Std_ID_130', 'Std_ID_133', 'Std_ID_134', 'Std_ID_137', 'Std_ID_138', 'Std_ID_141', 'Std_ID_142', 'Std_ID_145', 'Std_ID_146', 'Std_ID_149', 'Std_ID_150', 'Std_ID_153', 'Std_ID_154', 'Std_ID_157', 'Std_ID_158', 'Std_ID_161', 'Std_ID_162', 'Std_ID_165', 'Std_ID_166', 'Std_ID_169', 'Std_ID_170', 'Std_ID_173', 'Std_ID_174', 'Std_ID_177', 'Std_ID_178', 'Std_ID_181', 'Std_ID_182', 'Std_ID_185', 'Std_ID_186', 'Std_ID_189', 'Std_ID_190', 'Std_ID_062', 'Std_ID_063', 'Std_ID_064'] CourseCode_13 -['Std_ID_175', 'Std_ID_205', 'Std_ID_019', 'Std_ID_142', 'Std_ID_243', 'Std_ID_246', 'Std_ID_186', 'Std_ID_228', 'Std_ID_137', 'Std_ID_080', 'Std_ID_130', 'Std_ID_105', 'Std_ID_216', 'Std_ID_201', 'Std_ID_135', 'Std_ID_218', 'Std_ID_096', 'Std_ID_109', 'Std_ID_026', 'Std_ID_229', 'Std_ID_207', 'Std_ID_014', 'Std_ID_179', 'Std_ID_192', 'Std_ID_158', 'Std_ID_102', 'Std_ID_011', 'Std_ID_094', 'Std_ID_057', 'Std_ID_010', 'Std_ID_062', 'Std_ID_090', 'Std_ID_125', 'Std_ID_219', 'Std_ID_153', 'Std_ID_122', 'Std_ID_248', 'Std_ID_181', 'Std_ID_058', 'Std_ID_037'] +['Std_ID_131', 'Std_ID_132', 'Std_ID_135', 'Std_ID_136', 'Std_ID_139', 'Std_ID_140', 'Std_ID_143', 'Std_ID_144', 'Std_ID_147', 'Std_ID_148', 'Std_ID_151', 'Std_ID_152', 'Std_ID_155', 'Std_ID_156', 'Std_ID_159', 'Std_ID_160', 'Std_ID_163', 'Std_ID_164', 'Std_ID_167', 'Std_ID_168', 'Std_ID_171', 'Std_ID_172', 'Std_ID_175', 'Std_ID_176', 'Std_ID_179', 'Std_ID_180', 'Std_ID_183', 'Std_ID_184', 'Std_ID_187', 'Std_ID_188', 'Std_ID_191', 'Std_ID_192', 'Std_ID_065', 'Std_ID_066', 'Std_ID_067'] CourseCode_14 -['Std_ID_018', 'Std_ID_052', 'Std_ID_227', 'Std_ID_003', 'Std_ID_208', 'Std_ID_012', 'Std_ID_162', 'Std_ID_042', 'Std_ID_141', 'Std_ID_063', 'Std_ID_019', 'Std_ID_096', 'Std_ID_192', 'Std_ID_124', 'Std_ID_245', 'Std_ID_200', 'Std_ID_219', 'Std_ID_092', 'Std_ID_222', 'Std_ID_020', 'Std_ID_077', 'Std_ID_109', 'Std_ID_174', 'Std_ID_087', 'Std_ID_028', 'Std_ID_083', 'Std_ID_122', 'Std_ID_201', 'Std_ID_117', 'Std_ID_054', 'Std_ID_080', 'Std_ID_010', 'Std_ID_221', 'Std_ID_131', 'Std_ID_024', 'Std_ID_234', 'Std_ID_036', 'Std_ID_177', 'Std_ID_161', 'Std_ID_126'] +['Std_ID_193', 'Std_ID_194', 'Std_ID_195', 'Std_ID_196', 'Std_ID_197', 'Std_ID_198', 'Std_ID_199', 'Std_ID_200', 'Std_ID_201', 'Std_ID_202', 'Std_ID_203', 'Std_ID_204', 'Std_ID_205', 'Std_ID_206', 'Std_ID_207', 'Std_ID_208', 'Std_ID_209', 'Std_ID_210', 'Std_ID_211', 'Std_ID_212', 'Std_ID_213', 'Std_ID_214', 'Std_ID_215', 'Std_ID_216', 'Std_ID_217', 'Std_ID_218', 'Std_ID_219', 'Std_ID_220', 'Std_ID_221', 'Std_ID_222', 'Std_ID_223', 'Std_ID_224', 'Std_ID_225', 'Std_ID_226', 'Std_ID_227', 'Std_ID_228', 'Std_ID_229', 'Std_ID_230', 'Std_ID_231', 'Std_ID_232', 'Std_ID_233', 'Std_ID_234', 'Std_ID_235', 'Std_ID_236', 'Std_ID_237', 'Std_ID_238', 'Std_ID_239', 'Std_ID_240', 'Std_ID_241', 'Std_ID_242', 'Std_ID_243', 'Std_ID_244', 'Std_ID_245', 'Std_ID_246', 'Std_ID_247', 'Std_ID_248', 'Std_ID_249', 'Std_ID_250', 'Std_ID_251', 'Std_ID_252', 'Std_ID_253', 'Std_ID_254', 'Std_ID_255', 'Std_ID_256'] CourseCode_15 -['Std_ID_142', 'Std_ID_050', 'Std_ID_115', 'Std_ID_076', 'Std_ID_011', 'Std_ID_035', 'Std_ID_191', 'Std_ID_059', 'Std_ID_032', 'Std_ID_030', 'Std_ID_012', 'Std_ID_015', 'Std_ID_150', 'Std_ID_121', 'Std_ID_124', 'Std_ID_061', 'Std_ID_075', 'Std_ID_133', 'Std_ID_166', 'Std_ID_069', 'Std_ID_094', 'Std_ID_158', 'Std_ID_144', 'Std_ID_199', 'Std_ID_096', 'Std_ID_177', 'Std_ID_014', 'Std_ID_022', 'Std_ID_004', 'Std_ID_233', 'Std_ID_172', 'Std_ID_180', 'Std_ID_223', 'Std_ID_073', 'Std_ID_018', 'Std_ID_057', 'Std_ID_224', 'Std_ID_099', 'Std_ID_062', 'Std_ID_232'] +['Std_ID_257', 'Std_ID_261', 'Std_ID_265', 'Std_ID_269', 'Std_ID_273', 'Std_ID_277', 'Std_ID_281', 'Std_ID_285', 'Std_ID_289', 'Std_ID_293', 'Std_ID_297', 'Std_ID_301', 'Std_ID_305', 'Std_ID_309', 'Std_ID_313', 'Std_ID_317', 'Std_ID_321', 'Std_ID_325', 'Std_ID_329', 'Std_ID_333', 'Std_ID_337', 'Std_ID_341', 'Std_ID_345', 'Std_ID_349', 'Std_ID_353', 'Std_ID_357', 'Std_ID_361', 'Std_ID_365', 'Std_ID_369', 'Std_ID_373', 'Std_ID_377', 'Std_ID_381', 'Std_ID_100', 'Std_ID_101', 'Std_ID_102'] CourseCode_16 -['Std_ID_020', 'Std_ID_124', 'Std_ID_097', 'Std_ID_092', 'Std_ID_100', 'Std_ID_119', 'Std_ID_177', 'Std_ID_011', 'Std_ID_017', 'Std_ID_114', 'Std_ID_087', 'Std_ID_007', 'Std_ID_132', 'Std_ID_208', 'Std_ID_082', 'Std_ID_002', 'Std_ID_116', 'Std_ID_057', 'Std_ID_210', 'Std_ID_045', 'Std_ID_005', 'Std_ID_139', 'Std_ID_028', 'Std_ID_051', 'Std_ID_144', 'Std_ID_207', 'Std_ID_056', 'Std_ID_042', 'Std_ID_211', 'Std_ID_231', 'Std_ID_203', 'Std_ID_196', 'Std_ID_009', 'Std_ID_106', 'Std_ID_133', 'Std_ID_151', 'Std_ID_058', 'Std_ID_101', 'Std_ID_125', 'Std_ID_232'] +['Std_ID_258', 'Std_ID_262', 'Std_ID_266', 'Std_ID_270', 'Std_ID_274', 'Std_ID_278', 'Std_ID_282', 'Std_ID_286', 'Std_ID_290', 'Std_ID_294', 'Std_ID_298', 'Std_ID_302', 'Std_ID_306', 'Std_ID_310', 'Std_ID_314', 'Std_ID_318', 'Std_ID_322', 'Std_ID_326', 'Std_ID_330', 'Std_ID_334', 'Std_ID_338', 'Std_ID_342', 'Std_ID_346', 'Std_ID_350', 'Std_ID_354', 'Std_ID_358', 'Std_ID_362', 'Std_ID_366', 'Std_ID_370', 'Std_ID_374', 'Std_ID_378', 'Std_ID_382', 'Std_ID_103', 'Std_ID_104', 'Std_ID_105'] CourseCode_17 -['Std_ID_122', 'Std_ID_224', 'Std_ID_056', 'Std_ID_221', 'Std_ID_054', 'Std_ID_237', 'Std_ID_180', 'Std_ID_052', 'Std_ID_020', 'Std_ID_131', 'Std_ID_106', 'Std_ID_231', 'Std_ID_011', 'Std_ID_064', 'Std_ID_069', 'Std_ID_062', 'Std_ID_239', 'Std_ID_019', 'Std_ID_227', 'Std_ID_053', 'Std_ID_119', 'Std_ID_160', 'Std_ID_184', 'Std_ID_240', 'Std_ID_250', 'Std_ID_030', 'Std_ID_177', 'Std_ID_241', 'Std_ID_038', 'Std_ID_129', 'Std_ID_098', 'Std_ID_104', 'Std_ID_158', 'Std_ID_026', 'Std_ID_202', 'Std_ID_015', 'Std_ID_058', 'Std_ID_109', 'Std_ID_152', 'Std_ID_190'] +['Std_ID_259', 'Std_ID_263', 'Std_ID_267', 'Std_ID_271', 'Std_ID_275', 'Std_ID_279', 'Std_ID_283', 'Std_ID_287', 'Std_ID_291', 'Std_ID_295', 'Std_ID_299', 'Std_ID_303', 'Std_ID_307', 'Std_ID_311', 'Std_ID_315', 'Std_ID_319', 'Std_ID_323', 'Std_ID_327', 'Std_ID_331', 'Std_ID_335', 'Std_ID_339', 'Std_ID_343', 'Std_ID_347', 'Std_ID_351', 'Std_ID_355', 'Std_ID_359', 'Std_ID_363', 'Std_ID_367', 'Std_ID_371', 'Std_ID_375', 'Std_ID_379', 'Std_ID_383', 'Std_ID_106', 'Std_ID_107', 'Std_ID_108'] CourseCode_18 -['Std_ID_117', 'Std_ID_136', 'Std_ID_149', 'Std_ID_126', 'Std_ID_006', 'Std_ID_063', 'Std_ID_151', 'Std_ID_060', 'Std_ID_012', 'Std_ID_090', 'Std_ID_154', 'Std_ID_240', 'Std_ID_065', 'Std_ID_162', 'Std_ID_102', 'Std_ID_043', 'Std_ID_144', 'Std_ID_121', 'Std_ID_156', 'Std_ID_066', 'Std_ID_083', 'Std_ID_199', 'Std_ID_143', 'Std_ID_047', 'Std_ID_207', 'Std_ID_189', 'Std_ID_177', 'Std_ID_250', 'Std_ID_210', 'Std_ID_197', 'Std_ID_003', 'Std_ID_246', 'Std_ID_077', 'Std_ID_215', 'Std_ID_086', 'Std_ID_204', 'Std_ID_223', 'Std_ID_067', 'Std_ID_115', 'Std_ID_082'] +['Std_ID_260', 'Std_ID_264', 'Std_ID_268', 'Std_ID_272', 'Std_ID_276', 'Std_ID_280', 'Std_ID_284', 'Std_ID_288', 'Std_ID_292', 'Std_ID_296', 'Std_ID_300', 'Std_ID_304', 'Std_ID_308', 'Std_ID_312', 'Std_ID_316', 'Std_ID_320', 'Std_ID_324', 'Std_ID_328', 'Std_ID_332', 'Std_ID_336', 'Std_ID_340', 'Std_ID_344', 'Std_ID_348', 'Std_ID_352', 'Std_ID_356', 'Std_ID_360', 'Std_ID_364', 'Std_ID_368', 'Std_ID_372', 'Std_ID_376', 'Std_ID_380', 'Std_ID_384', 'Std_ID_109', 'Std_ID_110', 'Std_ID_111'] CourseCode_19 -['Std_ID_250', 'Std_ID_067', 'Std_ID_022', 'Std_ID_114', 'Std_ID_060', 'Std_ID_133', 'Std_ID_236', 'Std_ID_039', 'Std_ID_005', 'Std_ID_032', 'Std_ID_071', 'Std_ID_132', 'Std_ID_087', 'Std_ID_229', 'Std_ID_047', 'Std_ID_029', 'Std_ID_235', 'Std_ID_216', 'Std_ID_199', 'Std_ID_204', 'Std_ID_163', 'Std_ID_168', 'Std_ID_147', 'Std_ID_014', 'Std_ID_187', 'Std_ID_179', 'Std_ID_160', 'Std_ID_035', 'Std_ID_167', 'Std_ID_173', 'Std_ID_248', 'Std_ID_026', 'Std_ID_211', 'Std_ID_003', 'Std_ID_112', 'Std_ID_105', 'Std_ID_191', 'Std_ID_095', 'Std_ID_011', 'Std_ID_092'] +['Std_ID_257', 'Std_ID_258', 'Std_ID_261', 'Std_ID_262', 'Std_ID_265', 'Std_ID_266', 'Std_ID_269', 'Std_ID_270', 'Std_ID_273', 'Std_ID_274', 'Std_ID_277', 'Std_ID_278', 'Std_ID_281', 'Std_ID_282', 'Std_ID_285', 'Std_ID_286', 'Std_ID_289', 'Std_ID_290', 'Std_ID_293', 'Std_ID_294', 'Std_ID_297', 'Std_ID_298', 'Std_ID_301', 'Std_ID_302', 'Std_ID_305', 'Std_ID_306', 'Std_ID_309', 'Std_ID_310', 'Std_ID_313', 'Std_ID_314', 'Std_ID_317', 'Std_ID_318', 'Std_ID_112', 'Std_ID_113', 'Std_ID_114'] CourseCode_20 -['Std_ID_222', 'Std_ID_125', 'Std_ID_188', 'Std_ID_088', 'Std_ID_095', 'Std_ID_046', 'Std_ID_201', 'Std_ID_051', 'Std_ID_104', 'Std_ID_130', 'Std_ID_092', 'Std_ID_057', 'Std_ID_217', 'Std_ID_181', 'Std_ID_227', 'Std_ID_136', 'Std_ID_064', 'Std_ID_133', 'Std_ID_059', 'Std_ID_065', 'Std_ID_169', 'Std_ID_233', 'Std_ID_129', 'Std_ID_123', 'Std_ID_193', 'Std_ID_079', 'Std_ID_172', 'Std_ID_204', 'Std_ID_208', 'Std_ID_246', 'Std_ID_001', 'Std_ID_174', 'Std_ID_007', 'Std_ID_189', 'Std_ID_203', 'Std_ID_205', 'Std_ID_183', 'Std_ID_048', 'Std_ID_121', 'Std_ID_177'] +['Std_ID_259', 'Std_ID_260', 'Std_ID_263', 'Std_ID_264', 'Std_ID_267', 'Std_ID_268', 'Std_ID_271', 'Std_ID_272', 'Std_ID_275', 'Std_ID_276', 'Std_ID_279', 'Std_ID_280', 'Std_ID_283', 'Std_ID_284', 'Std_ID_287', 'Std_ID_288', 'Std_ID_291', 'Std_ID_292', 'Std_ID_295', 'Std_ID_296', 'Std_ID_299', 'Std_ID_300', 'Std_ID_303', 'Std_ID_304', 'Std_ID_307', 'Std_ID_308', 'Std_ID_311', 'Std_ID_312', 'Std_ID_315', 'Std_ID_316', 'Std_ID_319', 'Std_ID_320', 'Std_ID_115', 'Std_ID_116', 'Std_ID_117'] + +CourseCode_21 +['Std_ID_321', 'Std_ID_322', 'Std_ID_323', 'Std_ID_324', 'Std_ID_325', 'Std_ID_326', 'Std_ID_327', 'Std_ID_328', 'Std_ID_329', 'Std_ID_330', 'Std_ID_331', 'Std_ID_332', 'Std_ID_333', 'Std_ID_334', 'Std_ID_335', 'Std_ID_336', 'Std_ID_337', 'Std_ID_338', 'Std_ID_339', 'Std_ID_340', 'Std_ID_341', 'Std_ID_342', 'Std_ID_343', 'Std_ID_344', 'Std_ID_345', 'Std_ID_346', 'Std_ID_347', 'Std_ID_348', 'Std_ID_349', 'Std_ID_350', 'Std_ID_351', 'Std_ID_352', 'Std_ID_353', 'Std_ID_354', 'Std_ID_355', 'Std_ID_356', 'Std_ID_357', 'Std_ID_358', 'Std_ID_359', 'Std_ID_360', 'Std_ID_361', 'Std_ID_362', 'Std_ID_363', 'Std_ID_364', 'Std_ID_365', 'Std_ID_366', 'Std_ID_367', 'Std_ID_368', 'Std_ID_369', 'Std_ID_370', 'Std_ID_371', 'Std_ID_372', 'Std_ID_373', 'Std_ID_374', 'Std_ID_375', 'Std_ID_376', 'Std_ID_377', 'Std_ID_378', 'Std_ID_379', 'Std_ID_380', 'Std_ID_381', 'Std_ID_382', 'Std_ID_383', 'Std_ID_384'] + +CourseCode_22 +['Std_ID_385', 'Std_ID_389', 'Std_ID_393', 'Std_ID_397', 'Std_ID_401', 'Std_ID_405', 'Std_ID_409', 'Std_ID_413', 'Std_ID_417', 'Std_ID_421', 'Std_ID_425', 'Std_ID_429', 'Std_ID_433', 'Std_ID_437', 'Std_ID_441', 'Std_ID_445', 'Std_ID_449', 'Std_ID_453', 'Std_ID_457', 'Std_ID_461', 'Std_ID_465', 'Std_ID_469', 'Std_ID_473', 'Std_ID_477', 'Std_ID_481', 'Std_ID_485', 'Std_ID_489', 'Std_ID_493', 'Std_ID_497', 'Std_ID_150', 'Std_ID_151', 'Std_ID_152'] + +CourseCode_23 +['Std_ID_386', 'Std_ID_390', 'Std_ID_394', 'Std_ID_398', 'Std_ID_402', 'Std_ID_406', 'Std_ID_410', 'Std_ID_414', 'Std_ID_418', 'Std_ID_422', 'Std_ID_426', 'Std_ID_430', 'Std_ID_434', 'Std_ID_438', 'Std_ID_442', 'Std_ID_446', 'Std_ID_450', 'Std_ID_454', 'Std_ID_458', 'Std_ID_462', 'Std_ID_466', 'Std_ID_470', 'Std_ID_474', 'Std_ID_478', 'Std_ID_482', 'Std_ID_486', 'Std_ID_490', 'Std_ID_494', 'Std_ID_498', 'Std_ID_153', 'Std_ID_154', 'Std_ID_155'] + +CourseCode_24 +['Std_ID_387', 'Std_ID_391', 'Std_ID_395', 'Std_ID_399', 'Std_ID_403', 'Std_ID_407', 'Std_ID_411', 'Std_ID_415', 'Std_ID_419', 'Std_ID_423', 'Std_ID_427', 'Std_ID_431', 'Std_ID_435', 'Std_ID_439', 'Std_ID_443', 'Std_ID_447', 'Std_ID_451', 'Std_ID_455', 'Std_ID_459', 'Std_ID_463', 'Std_ID_467', 'Std_ID_471', 'Std_ID_475', 'Std_ID_479', 'Std_ID_483', 'Std_ID_487', 'Std_ID_491', 'Std_ID_495', 'Std_ID_499', 'Std_ID_156', 'Std_ID_157', 'Std_ID_158'] + +CourseCode_25 +['Std_ID_388', 'Std_ID_392', 'Std_ID_396', 'Std_ID_400', 'Std_ID_404', 'Std_ID_408', 'Std_ID_412', 'Std_ID_416', 'Std_ID_420', 'Std_ID_424', 'Std_ID_428', 'Std_ID_432', 'Std_ID_436', 'Std_ID_440', 'Std_ID_444', 'Std_ID_448', 'Std_ID_452', 'Std_ID_456', 'Std_ID_460', 'Std_ID_464', 'Std_ID_468', 'Std_ID_472', 'Std_ID_476', 'Std_ID_480', 'Std_ID_484', 'Std_ID_488', 'Std_ID_492', 'Std_ID_496', 'Std_ID_500', 'Std_ID_159', 'Std_ID_160', 'Std_ID_161'] + +CourseCode_26 +['Std_ID_385', 'Std_ID_386', 'Std_ID_389', 'Std_ID_390', 'Std_ID_393', 'Std_ID_394', 'Std_ID_397', 'Std_ID_398', 'Std_ID_401', 'Std_ID_402', 'Std_ID_405', 'Std_ID_406', 'Std_ID_409', 'Std_ID_410', 'Std_ID_413', 'Std_ID_414', 'Std_ID_417', 'Std_ID_418', 'Std_ID_421', 'Std_ID_422', 'Std_ID_425', 'Std_ID_426', 'Std_ID_429', 'Std_ID_430', 'Std_ID_433', 'Std_ID_434', 'Std_ID_437', 'Std_ID_438', 'Std_ID_441', 'Std_ID_442', 'Std_ID_445', 'Std_ID_446', 'Std_ID_449', 'Std_ID_450', 'Std_ID_162', 'Std_ID_163', 'Std_ID_164'] + +CourseCode_27 +['Std_ID_387', 'Std_ID_388', 'Std_ID_391', 'Std_ID_392', 'Std_ID_395', 'Std_ID_396', 'Std_ID_399', 'Std_ID_400', 'Std_ID_403', 'Std_ID_404', 'Std_ID_407', 'Std_ID_408', 'Std_ID_411', 'Std_ID_412', 'Std_ID_415', 'Std_ID_416', 'Std_ID_419', 'Std_ID_420', 'Std_ID_423', 'Std_ID_424', 'Std_ID_427', 'Std_ID_428', 'Std_ID_431', 'Std_ID_432', 'Std_ID_435', 'Std_ID_436', 'Std_ID_439', 'Std_ID_440', 'Std_ID_443', 'Std_ID_444', 'Std_ID_447', 'Std_ID_448', 'Std_ID_451', 'Std_ID_452', 'Std_ID_165', 'Std_ID_166', 'Std_ID_167'] + +CourseCode_28 +['Std_ID_453', 'Std_ID_454', 'Std_ID_455', 'Std_ID_456', 'Std_ID_457', 'Std_ID_458', 'Std_ID_459', 'Std_ID_460', 'Std_ID_461', 'Std_ID_462', 'Std_ID_463', 'Std_ID_464', 'Std_ID_465', 'Std_ID_466', 'Std_ID_467', 'Std_ID_468', 'Std_ID_469', 'Std_ID_470', 'Std_ID_471', 'Std_ID_472', 'Std_ID_473', 'Std_ID_474', 'Std_ID_475', 'Std_ID_476', 'Std_ID_477', 'Std_ID_478', 'Std_ID_479', 'Std_ID_480', 'Std_ID_481', 'Std_ID_482', 'Std_ID_483', 'Std_ID_484', 'Std_ID_485', 'Std_ID_486', 'Std_ID_487', 'Std_ID_488', 'Std_ID_489', 'Std_ID_490', 'Std_ID_491', 'Std_ID_492', 'Std_ID_493', 'Std_ID_494', 'Std_ID_495', 'Std_ID_496', 'Std_ID_497', 'Std_ID_498', 'Std_ID_499', 'Std_ID_500'] + +CourseCode_29 +['Std_ID_001', 'Std_ID_025', 'Std_ID_050', 'Std_ID_075', 'Std_ID_100', 'Std_ID_125', 'Std_ID_150', 'Std_ID_175', 'Std_ID_200', 'Std_ID_225', 'Std_ID_250', 'Std_ID_275', 'Std_ID_300', 'Std_ID_325', 'Std_ID_350', 'Std_ID_375', 'Std_ID_400', 'Std_ID_425', 'Std_ID_450', 'Std_ID_475', 'Std_ID_500'] + +CourseCode_30 +['Std_ID_010', 'Std_ID_020', 'Std_ID_030', 'Std_ID_040', 'Std_ID_060', 'Std_ID_070', 'Std_ID_080', 'Std_ID_090', 'Std_ID_110', 'Std_ID_120', 'Std_ID_130', 'Std_ID_140', 'Std_ID_160', 'Std_ID_170', 'Std_ID_180', 'Std_ID_190', 'Std_ID_210', 'Std_ID_220', 'Std_ID_230', 'Std_ID_240', 'Std_ID_260', 'Std_ID_270', 'Std_ID_280', 'Std_ID_290', 'Std_ID_310', 'Std_ID_320', 'Std_ID_330', 'Std_ID_340', 'Std_ID_360', 'Std_ID_370', 'Std_ID_380', 'Std_ID_390', 'Std_ID_410', 'Std_ID_420', 'Std_ID_430', 'Std_ID_440', 'Std_ID_460', 'Std_ID_470', 'Std_ID_480', 'Std_ID_490'] diff --git a/sampleData/sampleData_AllClassroomsAndTheirCapacities.csv b/sampleData/sampleData_AllClassroomsAndTheirCapacities.csv index e131df0..c1aec4c 100644 --- a/sampleData/sampleData_AllClassroomsAndTheirCapacities.csv +++ b/sampleData/sampleData_AllClassroomsAndTheirCapacities.csv @@ -1,11 +1,16 @@ ALL OF THE CLASSROOMS; AND THEIR CAPACITIES IN THE SYSTEM -Classroom_01;40 -Classroom_02;40 -Classroom_03;40 -Classroom_04;40 -Classroom_05;40 -Classroom_06;40 -Classroom_07;40 -Classroom_08;40 -Classroom_09;40 -Classroom_10;40 +Classroom_01;50 +Classroom_02;50 +Classroom_03;75 +Classroom_04;75 +Classroom_05;100 +Classroom_06;100 +Classroom_07;120 +Classroom_08;120 +Classroom_09;150 +Classroom_10;150 +Classroom_11;200 +Classroom_12;200 +Classroom_13;80 +Classroom_14;80 +Classroom_15;60 diff --git a/sampleData/sampleData_AllCourses.csv b/sampleData/sampleData_AllCourses.csv index ce098ca..6da3c53 100644 --- a/sampleData/sampleData_AllCourses.csv +++ b/sampleData/sampleData_AllCourses.csv @@ -18,4 +18,14 @@ CourseCode_16 CourseCode_17 CourseCode_18 CourseCode_19 -CourseCode_20 \ No newline at end of file +CourseCode_20 +CourseCode_21 +CourseCode_22 +CourseCode_23 +CourseCode_24 +CourseCode_25 +CourseCode_26 +CourseCode_27 +CourseCode_28 +CourseCode_29 +CourseCode_30 \ No newline at end of file diff --git a/sampleData/sampleData_AllStudents.csv b/sampleData/sampleData_AllStudents.csv index 1560409..cbd046c 100644 --- a/sampleData/sampleData_AllStudents.csv +++ b/sampleData/sampleData_AllStudents.csv @@ -248,4 +248,254 @@ Std_ID_246 Std_ID_247 Std_ID_248 Std_ID_249 -Std_ID_250 \ No newline at end of file +Std_ID_250 +Std_ID_251 +Std_ID_252 +Std_ID_253 +Std_ID_254 +Std_ID_255 +Std_ID_256 +Std_ID_257 +Std_ID_258 +Std_ID_259 +Std_ID_260 +Std_ID_261 +Std_ID_262 +Std_ID_263 +Std_ID_264 +Std_ID_265 +Std_ID_266 +Std_ID_267 +Std_ID_268 +Std_ID_269 +Std_ID_270 +Std_ID_271 +Std_ID_272 +Std_ID_273 +Std_ID_274 +Std_ID_275 +Std_ID_276 +Std_ID_277 +Std_ID_278 +Std_ID_279 +Std_ID_280 +Std_ID_281 +Std_ID_282 +Std_ID_283 +Std_ID_284 +Std_ID_285 +Std_ID_286 +Std_ID_287 +Std_ID_288 +Std_ID_289 +Std_ID_290 +Std_ID_291 +Std_ID_292 +Std_ID_293 +Std_ID_294 +Std_ID_295 +Std_ID_296 +Std_ID_297 +Std_ID_298 +Std_ID_299 +Std_ID_300 +Std_ID_301 +Std_ID_302 +Std_ID_303 +Std_ID_304 +Std_ID_305 +Std_ID_306 +Std_ID_307 +Std_ID_308 +Std_ID_309 +Std_ID_310 +Std_ID_311 +Std_ID_312 +Std_ID_313 +Std_ID_314 +Std_ID_315 +Std_ID_316 +Std_ID_317 +Std_ID_318 +Std_ID_319 +Std_ID_320 +Std_ID_321 +Std_ID_322 +Std_ID_323 +Std_ID_324 +Std_ID_325 +Std_ID_326 +Std_ID_327 +Std_ID_328 +Std_ID_329 +Std_ID_330 +Std_ID_331 +Std_ID_332 +Std_ID_333 +Std_ID_334 +Std_ID_335 +Std_ID_336 +Std_ID_337 +Std_ID_338 +Std_ID_339 +Std_ID_340 +Std_ID_341 +Std_ID_342 +Std_ID_343 +Std_ID_344 +Std_ID_345 +Std_ID_346 +Std_ID_347 +Std_ID_348 +Std_ID_349 +Std_ID_350 +Std_ID_351 +Std_ID_352 +Std_ID_353 +Std_ID_354 +Std_ID_355 +Std_ID_356 +Std_ID_357 +Std_ID_358 +Std_ID_359 +Std_ID_360 +Std_ID_361 +Std_ID_362 +Std_ID_363 +Std_ID_364 +Std_ID_365 +Std_ID_366 +Std_ID_367 +Std_ID_368 +Std_ID_369 +Std_ID_370 +Std_ID_371 +Std_ID_372 +Std_ID_373 +Std_ID_374 +Std_ID_375 +Std_ID_376 +Std_ID_377 +Std_ID_378 +Std_ID_379 +Std_ID_380 +Std_ID_381 +Std_ID_382 +Std_ID_383 +Std_ID_384 +Std_ID_385 +Std_ID_386 +Std_ID_387 +Std_ID_388 +Std_ID_389 +Std_ID_390 +Std_ID_391 +Std_ID_392 +Std_ID_393 +Std_ID_394 +Std_ID_395 +Std_ID_396 +Std_ID_397 +Std_ID_398 +Std_ID_399 +Std_ID_400 +Std_ID_401 +Std_ID_402 +Std_ID_403 +Std_ID_404 +Std_ID_405 +Std_ID_406 +Std_ID_407 +Std_ID_408 +Std_ID_409 +Std_ID_410 +Std_ID_411 +Std_ID_412 +Std_ID_413 +Std_ID_414 +Std_ID_415 +Std_ID_416 +Std_ID_417 +Std_ID_418 +Std_ID_419 +Std_ID_420 +Std_ID_421 +Std_ID_422 +Std_ID_423 +Std_ID_424 +Std_ID_425 +Std_ID_426 +Std_ID_427 +Std_ID_428 +Std_ID_429 +Std_ID_430 +Std_ID_431 +Std_ID_432 +Std_ID_433 +Std_ID_434 +Std_ID_435 +Std_ID_436 +Std_ID_437 +Std_ID_438 +Std_ID_439 +Std_ID_440 +Std_ID_441 +Std_ID_442 +Std_ID_443 +Std_ID_444 +Std_ID_445 +Std_ID_446 +Std_ID_447 +Std_ID_448 +Std_ID_449 +Std_ID_450 +Std_ID_451 +Std_ID_452 +Std_ID_453 +Std_ID_454 +Std_ID_455 +Std_ID_456 +Std_ID_457 +Std_ID_458 +Std_ID_459 +Std_ID_460 +Std_ID_461 +Std_ID_462 +Std_ID_463 +Std_ID_464 +Std_ID_465 +Std_ID_466 +Std_ID_467 +Std_ID_468 +Std_ID_469 +Std_ID_470 +Std_ID_471 +Std_ID_472 +Std_ID_473 +Std_ID_474 +Std_ID_475 +Std_ID_476 +Std_ID_477 +Std_ID_478 +Std_ID_479 +Std_ID_480 +Std_ID_481 +Std_ID_482 +Std_ID_483 +Std_ID_484 +Std_ID_485 +Std_ID_486 +Std_ID_487 +Std_ID_488 +Std_ID_489 +Std_ID_490 +Std_ID_491 +Std_ID_492 +Std_ID_493 +Std_ID_494 +Std_ID_495 +Std_ID_496 +Std_ID_497 +Std_ID_498 +Std_ID_499 +Std_ID_500 \ No newline at end of file diff --git a/src/main/java/org/example/se302/service/ScheduleGeneratorService.java b/src/main/java/org/example/se302/service/ScheduleGeneratorService.java index a9d6d31..94dd1ef 100644 --- a/src/main/java/org/example/se302/service/ScheduleGeneratorService.java +++ b/src/main/java/org/example/se302/service/ScheduleGeneratorService.java @@ -6,105 +6,261 @@ import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; /** - * Service for generating exam schedules using Constraint Satisfaction Problem - * (CSP) solving. - * Implements backtracking algorithm with MRV and LCV heuristics. - * Works with the day/timeSlotIndex based ExamAssignment architecture. + * Service for generating exam schedules using a greedy constraint-based + * algorithm. + * + * Constraints enforced: + * 1. No student can have two exams at the same time + * 2. No student can have more than 2 exams per day + * 3. Students need at least 1 hour break between consecutive exams + * 4. Number of concurrent exams cannot exceed available classrooms + * + * Features: + * - Multiple exams can be scheduled in the same time slot (in different + * classrooms) + * - Timeout protection (30 seconds max) + * - Clear error messages on failure */ public class ScheduleGeneratorService { private final DataManager dataManager; - private final ConstraintValidator validator; private final AtomicBoolean cancelled; private ProgressListener progressListener; + // Timeout in milliseconds (30 seconds) + private static final long TIMEOUT_MS = 30000; + + // Minimum break between exams in slots (1 hour = 1 slot typically) + private static final int MIN_BREAK_SLOTS = 1; + + // Maximum exams per student per day + private static final int MAX_EXAMS_PER_DAY = 2; + public ScheduleGeneratorService() { this.dataManager = DataManager.getInstance(); - this.validator = new ConstraintValidator(); this.cancelled = new AtomicBoolean(false); } /** * Generate an exam schedule based on configuration. - * Uses multi-restart optimization to find the best schedule among multiple attempts. + * Uses greedy algorithm with conflict detection. */ public ScheduleResult generateSchedule(ScheduleConfiguration config) { cancelled.set(false); + long startTime = System.currentTimeMillis(); // Validate input if (dataManager.getTotalCourses() == 0) { - return ScheduleResult.failure("No courses to schedule"); + return ScheduleResult.failure("No courses to schedule. Please import course data first."); } if (dataManager.getTotalClassrooms() == 0) { - return ScheduleResult.failure("No classrooms available"); + return ScheduleResult.failure("No classrooms available. Please import classroom data first."); } - // Get courses ordered by MRV heuristic - List coursesToSchedule = getCoursesOrderedByMRV(); + List courses = new ArrayList<>(dataManager.getCourses()); + List classrooms = new ArrayList<>(dataManager.getClassrooms()); - // Multi-restart optimization: try multiple schedules and pick the best - int numRestarts = 5; // Generate 5 different schedules - ScheduleState bestSchedule = null; - double bestScore = Double.MAX_VALUE; - int successfulAttempts = 0; + // Build conflict graph: which courses share students + Map> conflictGraph = buildConflictGraph(courses); - updateProgress(0, numRestarts, "Generating schedules (multi-restart optimization)..."); + // Sort courses by number of conflicts (most constrained first) + courses.sort((c1, c2) -> { + int conflicts1 = conflictGraph.getOrDefault(c1.getCourseCode(), Collections.emptySet()).size(); + int conflicts2 = conflictGraph.getOrDefault(c2.getCourseCode(), Collections.emptySet()).size(); + if (conflicts1 != conflicts2) { + return Integer.compare(conflicts2, conflicts1); // More conflicts first + } + // Tiebreaker: more students first + return Integer.compare(c2.getEnrolledStudentsCount(), c1.getEnrolledStudentsCount()); + }); - for (int attempt = 0; attempt < numRestarts; attempt++) { + // Initialize schedule state + ScheduleState scheduleState = initializeScheduleState(config); + + // Track student exam assignments: studentId -> list of (day, slot) pairs + Map> studentExams = new HashMap<>(); + + // Track classroom usage: "day-slot" -> set of used classroom IDs + Map> slotClassrooms = new HashMap<>(); + + int totalCourses = courses.size(); + int scheduledCount = 0; + + updateProgress(0, totalCourses, "Starting schedule generation..."); + + // Try to schedule each course + for (int i = 0; i < courses.size(); i++) { + // Check timeout + if (System.currentTimeMillis() - startTime > TIMEOUT_MS) { + return ScheduleResult.failure( + String.format("Scheduling timed out after 30 seconds. Scheduled %d/%d courses. " + + "Try increasing the number of days or time slots.", scheduledCount, totalCourses)); + } + + // Check cancellation if (cancelled.get()) { return ScheduleResult.cancelled(); } - // Create fresh schedule state for this attempt - ScheduleState scheduleState = initializeScheduleState(config); + Course course = courses.get(i); + List enrolledStudentsList = course.getEnrolledStudents(); + Set enrolledStudents = new HashSet<>(enrolledStudentsList); - updateProgress(attempt, numRestarts, - String.format("Attempt %d/%d: Starting backtracking...", attempt + 1, numRestarts)); + updateProgress(i, totalCourses, "Scheduling " + course.getCourseCode() + "..."); - // Randomize search order slightly for diversity - List shuffledCourses = new ArrayList<>(coursesToSchedule); - if (attempt > 0) { - // Keep MRV heuristic but add small random perturbation - shuffledCourses = perturbCourseOrder(shuffledCourses, attempt); - } + // Find a valid slot for this course + boolean assigned = false; + String failureReason = ""; - // Run backtracking - boolean success = backtrack(scheduleState, shuffledCourses, 0, config); + // Try each day and slot + dayLoop: for (int day = 0; day < config.getNumDays() && !assigned; day++) { + for (int slot = 0; slot < config.getSlotsPerDay() && !assigned; slot++) { + // Check if this slot is valid for all enrolled students + String slotKey = day + "-" + slot; + boolean slotValid = true; + String reason = ""; - if (success) { - successfulAttempts++; + for (String studentId : enrolledStudents) { + // Check constraint 1: No concurrent exams + List studentExamList = studentExams.getOrDefault(studentId, new ArrayList<>()); + for (int[] exam : studentExamList) { + if (exam[0] == day && exam[1] == slot) { + slotValid = false; + reason = "Student " + studentId + " already has exam at this time"; + break; + } + } + if (!slotValid) + break; - // Evaluate this schedule using objective function - double score = ScheduleObjective.evaluateSchedule(scheduleState, config, dataManager); + // Check constraint 2: Max 2 exams per day + int examsToday = 0; + for (int[] exam : studentExamList) { + if (exam[0] == day) + examsToday++; + } + if (examsToday >= MAX_EXAMS_PER_DAY) { + slotValid = false; + reason = "Student " + studentId + " already has " + MAX_EXAMS_PER_DAY + " exams on day " + + (day + 1); + break; + } - updateProgress(attempt + 1, numRestarts, - String.format("Attempt %d/%d: Found schedule (score: %.1f, best: %.1f)", - attempt + 1, numRestarts, score, bestScore)); + // Check constraint 3: At least 1 hour break between exams + for (int[] exam : studentExamList) { + if (exam[0] == day) { + int slotDiff = Math.abs(exam[1] - slot); + if (slotDiff > 0 && slotDiff <= MIN_BREAK_SLOTS) { + slotValid = false; + reason = "Student " + studentId + " needs at least 1 hour break between exams"; + break; + } + } + } + if (!slotValid) + break; + } - if (score < bestScore) { - bestScore = score; - bestSchedule = scheduleState.copy(); + if (!slotValid) { + failureReason = reason; + continue; + } + + // Check constraint 4: Find available classroom + Set usedClassrooms = slotClassrooms.getOrDefault(slotKey, new HashSet<>()); + Classroom selectedClassroom = null; + + // Sort classrooms by capacity (prefer smallest that fits) + List sortedClassrooms = new ArrayList<>(classrooms); + sortedClassrooms.sort(Comparator.comparingInt(Classroom::getCapacity)); + + for (Classroom classroom : sortedClassrooms) { + if (!usedClassrooms.contains(classroom.getClassroomId()) && + classroom.getCapacity() >= course.getEnrolledStudentsCount()) { + selectedClassroom = classroom; + break; + } + } + + if (selectedClassroom == null) { + failureReason = "No available classroom with sufficient capacity at day " + (day + 1) + " slot " + + (slot + 1); + continue; + } + + // All constraints satisfied - assign the exam + ExamAssignment assignment = scheduleState.getAssignment(course.getCourseCode()); + scheduleState.updateAssignment( + assignment.getCourseCode(), + day, + slot, + selectedClassroom.getClassroomId()); + + // Update tracking structures + for (String studentId : enrolledStudents) { + studentExams.computeIfAbsent(studentId, k -> new ArrayList<>()) + .add(new int[] { day, slot }); + } + + usedClassrooms.add(selectedClassroom.getClassroomId()); + slotClassrooms.put(slotKey, usedClassrooms); + + assigned = true; + scheduledCount++; } - } else { - updateProgress(attempt + 1, numRestarts, - String.format("Attempt %d/%d: No valid schedule", attempt + 1, numRestarts)); + } + + if (!assigned) { + return ScheduleResult.failure( + String.format("Could not schedule course %s. %s. " + + "Scheduled %d/%d courses before failure. " + + "Try increasing days/slots or reducing course conflicts.", + course.getCourseCode(), failureReason, scheduledCount, totalCourses)); } } - if (cancelled.get()) { - return ScheduleResult.cancelled(); + // Validate final schedule + int violations = validateSchedule(scheduleState, studentExams); + scheduleState.setConstraintViolations(violations); + + updateProgress(totalCourses, totalCourses, + String.format("Complete! Scheduled all %d courses.", totalCourses)); + + return ScheduleResult.success(scheduleState); + } + + /** + * Build conflict graph - courses that share students cannot be scheduled at the + * same time. + */ + private Map> buildConflictGraph(List courses) { + Map> conflictGraph = new HashMap<>(); + + // Map student to their courses + Map> studentCourses = new HashMap<>(); + for (Course course : courses) { + for (String studentId : course.getEnrolledStudents()) { + studentCourses.computeIfAbsent(studentId, k -> new HashSet<>()) + .add(course.getCourseCode()); + } } - if (bestSchedule != null) { - updateProgress(numRestarts, numRestarts, - String.format("Complete! Best schedule: score %.1f (%d/%d attempts succeeded)", - bestScore, successfulAttempts, numRestarts)); - return ScheduleResult.success(bestSchedule); - } else { - return ScheduleResult.failure( - "No valid schedule found in " + numRestarts + " attempts. " + - "Try increasing days/slots or relaxing constraints."); + // Build conflict edges + for (Set coursesOfStudent : studentCourses.values()) { + if (coursesOfStudent.size() > 1) { + List courseList = new ArrayList<>(coursesOfStudent); + for (int i = 0; i < courseList.size(); i++) { + for (int j = i + 1; j < courseList.size(); j++) { + String c1 = courseList.get(i); + String c2 = courseList.get(j); + conflictGraph.computeIfAbsent(c1, k -> new HashSet<>()).add(c2); + conflictGraph.computeIfAbsent(c2, k -> new HashSet<>()).add(c1); + } + } + } } + + return conflictGraph; } /** @@ -113,7 +269,7 @@ public class ScheduleGeneratorService { private ScheduleState initializeScheduleState(ScheduleConfiguration config) { ScheduleState state = new ScheduleState(); - // CRITICAL: Set configuration so ScheduleState knows about days/slots + // Set configuration so ScheduleState knows about days/slots state.setConfiguration(config); // Set available classrooms @@ -133,257 +289,45 @@ public class ScheduleGeneratorService { } /** - * Backtracking algorithm core. + * Validate the final schedule and count any violations. */ - private boolean backtrack(ScheduleState scheduleState, List courses, int courseIndex, - ScheduleConfiguration config) { - // Check cancellation - if (cancelled.get()) { - return false; - } + private int validateSchedule(ScheduleState scheduleState, Map> studentExams) { + int violations = 0; - // Base case: all courses assigned - if (courseIndex >= courses.size()) { - return true; - } + for (Map.Entry> entry : studentExams.entrySet()) { + List exams = entry.getValue(); - Course currentCourse = courses.get(courseIndex); - - // Update progress - updateProgress(courseIndex, courses.size(), - "Scheduling " + currentCourse.getCourseCode() + "..."); - - ExamAssignment assignment = scheduleState.getAssignment(currentCourse.getCourseCode()); - - // Get time slots ordered by strategy - List orderedTimeSlots = getTimeSlotsOrderedByStrategy(config, scheduleState); - - // Try each time slot - for (DaySlotPair timeSlot : orderedTimeSlots) { - if (cancelled.get()) { - return false; + // Group exams by day + Map> examsByDay = new HashMap<>(); + for (int[] exam : exams) { + examsByDay.computeIfAbsent(exam[0], k -> new ArrayList<>()).add(exam[1]); } - // Get suitable classrooms for this day/slot (ordered by strategy) - List suitableClassrooms = getSuitableClassroomsOrdered( - currentCourse, timeSlot.day, timeSlot.slot, scheduleState, config); + for (Map.Entry> dayEntry : examsByDay.entrySet()) { + List slots = dayEntry.getValue(); - // Try each classroom - for (Classroom classroom : suitableClassrooms) { - // Temporarily assign (using updateAssignment to maintain assignedCourses counter) - scheduleState.updateAssignment( - assignment.getCourseCode(), - timeSlot.day, - timeSlot.slot, - classroom.getClassroomId() - ); + // Check max 2 exams per day + if (slots.size() > MAX_EXAMS_PER_DAY) { + violations++; + } - // Validate assignment - pass allowBackToBack from config - ConstraintValidator.ValidationResult validationResult = validator.validateAssignment(assignment, - scheduleState, config.isAllowBackToBackExams()); + // Check for concurrent exams (should not happen, but validate) + Set uniqueSlots = new HashSet<>(slots); + if (uniqueSlots.size() != slots.size()) { + violations++; + } - if (validationResult.isValid()) { - // Assignment is valid, try to assign remaining courses - if (backtrack(scheduleState, courses, courseIndex + 1, config)) { - return true; // Success! + // Check break time + Collections.sort(slots); + for (int i = 1; i < slots.size(); i++) { + if (slots.get(i) - slots.get(i - 1) <= MIN_BREAK_SLOTS) { + violations++; } } - - // Backtrack: reset assignment (using updateAssignment to maintain assignedCourses counter) - scheduleState.updateAssignment( - assignment.getCourseCode(), - -1, - -1, - null - ); } } - // No valid assignment found - return false; - } - - /** - * MRV Heuristic: Order courses by "most constrained first". - */ - private List getCoursesOrderedByMRV() { - List courses = new ArrayList<>(dataManager.getCourses()); - - // Sort by number of enrolled students (descending) - // More students = more constrained - courses.sort((c1, c2) -> Integer.compare( - c2.getEnrolledStudentsCount(), - c1.getEnrolledStudentsCount())); - - return courses; - } - - /** - * Add small random perturbation to course order while preserving MRV bias. - * This creates diverse schedules for multi-restart optimization. - * - * @param courses Original course list - * @param seed Seed for deterministic randomization - * @return Perturbed course list - */ - private List perturbCourseOrder(List courses, int seed) { - Random random = new Random(seed * 1000L); // Deterministic seed for reproducibility - List perturbed = new ArrayList<>(courses); - - // Swap 2-3 random pairs (limited perturbation maintains MRV benefits) - int swaps = 2 + random.nextInt(2); - for (int i = 0; i < swaps && perturbed.size() > 1; i++) { - int idx1 = random.nextInt(perturbed.size()); - int idx2 = random.nextInt(perturbed.size()); - Collections.swap(perturbed, idx1, idx2); - } - - return perturbed; - } - - /** - * Get time slots ordered by optimization strategy. - */ - private List getTimeSlotsOrderedByStrategy(ScheduleConfiguration config, ScheduleState scheduleState) { - List timeSlots = new ArrayList<>(); - - // Generate all day/slot combinations - for (int day = 0; day < config.getNumDays(); day++) { - for (int slot = 0; slot < config.getSlotsPerDay(); slot++) { - timeSlots.add(new DaySlotPair(day, slot)); - } - } - - // Order based on strategy (deprecated strategies handled in ScheduleObjective) - switch (config.getOptimizationStrategy()) { - case MINIMIZE_DAYS: - // Already in order (day 0 slot 0, day 0 slot 1, ... day 1 slot 0, ...) - // This fills earlier days first - break; - - case STUDENT_FRIENDLY: - // Fill each day completely before moving to next day - // Within each day, prefer middle slots (avoid early morning) - // Priority: slots 1 and 2 (middle of day) over slots 0 (early) and 3 (late) - timeSlots.sort((p1, p2) -> { - // Primary: sort by day (fill Day 0 first, then Day 1, etc.) - int dayCompare = Integer.compare(p1.day, p2.day); - if (dayCompare != 0) - return dayCompare; - - // Secondary: within same day, prefer middle slots - // Slot priority order: 1 (best), 2 (good), 0 (early morning), 3 (late afternoon) - int[] slotPriority = { 2, 0, 1, 3 }; // Maps slot index to priority (lower is better) - int priority1 = p1.slot < slotPriority.length ? slotPriority[p1.slot] : p1.slot; - int priority2 = p2.slot < slotPriority.length ? slotPriority[p2.slot] : p2.slot; - return Integer.compare(priority1, priority2); - }); - break; - - default: - // DEFAULT or others: chronological order - break; - } - - return timeSlots; - } - - /** - * Get classrooms suitable for a course at a specific day and time slot, - * ordered according to optimization strategy. - */ - private List getSuitableClassroomsOrdered(Course course, - int day, - int timeSlotIndex, - ScheduleState scheduleState, - ScheduleConfiguration config) { - List suitable = new ArrayList<>(); - - for (Classroom classroom : scheduleState.getAvailableClassrooms()) { - // Check capacity - if (classroom.getCapacity() < course.getEnrolledStudentsCount()) { - continue; - } - - // Check if classroom is available at this time - boolean isAvailable = true; - for (ExamAssignment assignment : scheduleState.getAssignments().values()) { - if (assignment.isAssigned() && - assignment.getClassroomId().equals(classroom.getClassroomId()) && - assignment.getDay() == day && - assignment.getTimeSlotIndex() == timeSlotIndex) { - isAvailable = false; - break; - } - } - - if (isAvailable) { - suitable.add(classroom); - } - } - - // Order based on strategy (deprecated strategies handled in ScheduleObjective) - switch (config.getOptimizationStrategy()) { - case MINIMIZE_CLASSROOMS: - // Prefer classrooms that are already in use (reuse same classrooms) - suitable.sort((c1, c2) -> { - int usage1 = getClassroomUsageCount(c1.getClassroomId(), scheduleState); - int usage2 = getClassroomUsageCount(c2.getClassroomId(), scheduleState); - // Sort descending (most used first) - return Integer.compare(usage2, usage1); - }); - break; - - default: - // DEFAULT: Use round-robin to force distribution across classrooms - // Always prefer least-used classrooms to ensure multiple classrooms get used - suitable.sort((c1, c2) -> { - int usage1 = getClassroomUsageCount(c1.getClassroomId(), scheduleState); - int usage2 = getClassroomUsageCount(c2.getClassroomId(), scheduleState); - - // Primary: prefer least-used classrooms - int usageCompare = Integer.compare(usage1, usage2); - if (usageCompare != 0) - return usageCompare; - - // Tiebreaker: prefer smaller capacity (efficient space usage) - int capacityCompare = Integer.compare(c1.getCapacity(), c2.getCapacity()); - if (capacityCompare != 0) - return capacityCompare; - - // Final tiebreaker: classroom ID (deterministic) - return c1.getClassroomId().compareTo(c2.getClassroomId()); - }); - break; - } - - return suitable; - } - - /** - * Count how many times a classroom has been used in the current schedule. - */ - private int getClassroomUsageCount(String classroomId, ScheduleState scheduleState) { - int count = 0; - for (ExamAssignment assignment : scheduleState.getAssignments().values()) { - if (assignment.isAssigned() && assignment.getClassroomId().equals(classroomId)) { - count++; - } - } - return count; - } - - /** - * Helper class to represent a day/slot pair. - */ - private static class DaySlotPair { - final int day; - final int slot; - - DaySlotPair(int day, int slot) { - this.day = day; - this.slot = slot; - } + return violations; } /**