Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.acme.schooltimetabling.TimetableApp;
import org.acme.schooltimetabling.apiCalls.teacherEndpoint.TeacherRecord;
import org.acme.schooltimetabling.builders.teachers.TeacherBuilder;
import org.acme.schooltimetabling.builders.teachers.policies.DefaultTeachingPolicy;
import org.acme.schooltimetabling.builders.teachers.policies.FacultyPolicy;
import org.acme.schooltimetabling.constants.Constants;
import org.acme.schooltimetabling.constants.Days;
import org.acme.schooltimetabling.constants.Preference;
import org.acme.schooltimetabling.domain.teacher.Faculty;
import org.acme.schooltimetabling.domain.teacher.Teacher;
import org.acme.schooltimetabling.helperClasses.BitSetHelper;
import org.acme.schooltimetabling.helperClasses.Generators.TeacherGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class SurveyRecord {
Expand Down Expand Up @@ -51,7 +48,7 @@ public class SurveyRecord {
private int teacherFK;
@JsonProperty("teacher_detail")
private TeacherRecord teacherRecord;
/**All extra Json properties not captured by class members with the @JsonProperty tag will
/**All extra JSON properties not captured by class members with the @JsonProperty tag will
* be placed into this variable*/
private Map<String, Object> extraFields = new HashMap<>();

Expand All @@ -74,7 +71,6 @@ public boolean valid(){
* Only one Teacher(or Faculty) object will be if and only if this function is called. The class
* will hold on to the created object to prevent the teacher from existing multiple times.
* @return Teacher representation of the survey. In other words, they have their preferences set.
* @throws Exception
*/
public Teacher toTeacher(){
if(teacher_rep == null) teacher_rep = createTeacherRep();
Expand All @@ -100,10 +96,17 @@ else if(val.equalsIgnoreCase("acceptable")){
conflict.or(bsRep);
}
}
Teacher teacher = new Teacher(TeacherGenerator.getNextTeacherID(), Constants.TEACHER_NAME_TO_CANON.get(nonCanonName),
preferences, acceptable, conflict, Preference.parsePref((String) extraFields.get("gap")));
if(teacherRecord.isFaculty()) teacher = new Faculty(teacher);
return teacher;

TeacherBuilder builder = new TeacherBuilder(new DefaultTeachingPolicy());
if(teacherRecord.isFaculty()) builder.setPolicy(new FacultyPolicy());

return builder
.preference(preferences)
.acceptable(acceptable)
.conflict(conflict)
.canon(Constants.TEACHER_NAME_TO_CANON.get(nonCanonName))
.gapPref(Preference.parsePref((String) extraFields.get("gap")))
.build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package org.acme.schooltimetabling.builders.teachers;

import org.acme.schooltimetabling.builders.teachers.policies.TeachingPolicy;
import org.acme.schooltimetabling.constants.Preference;
import org.acme.schooltimetabling.domain.teacher.Faculty;
import org.acme.schooltimetabling.domain.teacher.Teacher;
import org.acme.schooltimetabling.helperClasses.Generators.TeacherGenerator;
import org.jspecify.annotations.NonNull;

import java.util.BitSet;

public class TeacherBuilder {
//we don't let them set the id; we will set it for them; not information they need to know
private BitSet preference = null;
private BitSet acceptable = null;
private BitSet conflict = null;
private String canon = null;
private Preference gapPref = null;
private TeachingPolicy policy;

public TeacherBuilder(TeachingPolicy teachingPolicy){
policy = teachingPolicy;
}

public TeacherBuilder setPolicy(@NonNull TeachingPolicy teachingPolicy){
policy = teachingPolicy;
return this;
}

public TeacherBuilder preference(@NonNull BitSet preference){
this.preference = (BitSet) preference.clone();
return this;
}

public TeacherBuilder acceptable(@NonNull BitSet acceptable){
this.acceptable = (BitSet) acceptable.clone();
return this;
}

public TeacherBuilder conflict(@NonNull BitSet conflict){
this.conflict = (BitSet) conflict.clone();
return this;
}

public TeacherBuilder canon(@NonNull String canon){
this.canon = canon;
return this;
}

public TeacherBuilder gapPref(@NonNull Preference gapPref){
this.gapPref = gapPref;
return this;
}

/**
* Note you must first set the <i>preference</i>, <i>acceptable</i>, and <i>conflict</i> <i>BitSets</i> must
* be set before calling this method.
* @param preschedule <i>BitSet</i> mask
*/
public TeacherBuilder preschedule(@NonNull BitSet preschedule){
this.preference.andNot(preschedule);
this.acceptable.andNot(preschedule);
this.conflict.or(preschedule);
return this;
}

/**
* clears the private fields containing the data passed to the {@link Faculty} or {@link Teacher} constructors
* by setting them to <i>null</i>.
*/
public TeacherBuilder clear(){
preference = null;
acceptable = null;
conflict = null;
canon = null;
gapPref = null;

return this;
}

public Teacher build(){
//validation
if(preference == null || acceptable == null || conflict == null || canon == null || gapPref == null){
throw new IllegalCallerException("When calling build() you must have a value set for preference, acceptable, " +
"conflict, canon name, and the gap preference");
}

BitSet preference = (BitSet) this.preference.clone();
BitSet acceptable = (BitSet) this.acceptable.clone();
BitSet conflict = (BitSet) this.conflict.clone();

//apply the policy for the instructor
policy.apply(preference, acceptable, conflict);

if(policy.isFaculty()){
return new Faculty(TeacherGenerator.getNextTeacherID(),
canon,
preference,
acceptable,
conflict,
gapPref);
}
else{
return new Teacher(TeacherGenerator.getNextTeacherID(),
canon,
preference,
acceptable,
conflict,
gapPref);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.acme.schooltimetabling.builders.teachers.policies;

import java.util.BitSet;

public class DefaultTeachingPolicy implements TeachingPolicy {
public DefaultTeachingPolicy(){}

@Override
public boolean isFaculty() {
return false;
}

@Override
public void apply(BitSet preference, BitSet acceptable, BitSet conflict) {
//no updates when using the default policy
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.acme.schooltimetabling.builders.teachers.policies;

import org.acme.schooltimetabling.constants.Constants;
import org.acme.schooltimetabling.constants.Days;
import org.acme.schooltimetabling.helperClasses.BitSetHelper;
import org.acme.schooltimetabling.helperClasses.ScheduleConfig;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.BitSet;
import java.util.EnumSet;
import java.util.List;

public class FacultyPolicy implements TeachingPolicy{
private static final BitSet DEFAULT_FACULTY_CONFLICT = buildDefaultFacultyConflict();

private final BitSet facultyConflict;

/**
* use this when creating schedules. Look at {@link this#buildDefaultFacultyConflict()} to inspect
* what the faculty conflict is.
*/
public FacultyPolicy(){
this.facultyConflict = (BitSet) DEFAULT_FACULTY_CONFLICT.clone();
}

/**
* This is meant to be used for testing purposes
* @param facultyConflict bitset which faculty can't be scheduled during
*/
public FacultyPolicy(BitSet facultyConflict){
this.facultyConflict = (BitSet) facultyConflict.clone();
}

@Override
public boolean isFaculty() {
return true;
}

@Override
public void apply(BitSet preference, BitSet acceptable, BitSet conflict) {
preference.andNot(facultyConflict);
acceptable.andNot(facultyConflict);
conflict.or(facultyConflict);
}

private static BitSet buildDefaultFacultyConflict() {
final int NUM_BLOCKS_FULL_HOUR = 2;
String department = ScheduleConfig.getDepartment().toLowerCase();
final DateTimeFormatter FORMATTER = Constants.TIME_FORMATTER;
List<LocalTime> facultyTimes;
EnumSet<Days> facultyDays;
BitSet facultyConflict = new BitSet();

if("csc".equals(department)){
facultyTimes = List.of(
LocalTime.parse("11:00AM", FORMATTER)
);
facultyDays = EnumSet.of(Days.TUESDAY);
}
else if("cpe".equals(department)){
/*CPE faculty times*/
facultyTimes = List.of(
LocalTime.parse("11:00AM", FORMATTER)
);
facultyDays = EnumSet.of(Days.WEDNESDAY);
}
else{
throw new RuntimeException(String.format("the department must be either 'cpe' or 'csc'. '%s' was found " +
"instead", department));
}


for(LocalTime localTime: facultyTimes) {
BitSet temp = BitSetHelper.timeSlotBitSet(localTime, NUM_BLOCKS_FULL_HOUR, facultyDays);
facultyConflict.or(temp);
}

return facultyConflict;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.acme.schooltimetabling.builders.teachers.policies;

import java.util.BitSet;

public interface TeachingPolicy {
void apply(BitSet preference, BitSet acceptable, BitSet conflict);
boolean isFaculty();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* 7AM-10PM for MTWRF
*/
public interface DefaultTime {
//these should all return copies of the bitsets for safety
BitSet getPreference();
BitSet getAcceptable();
BitSet getConflict();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import ai.timefold.solver.core.api.score.stream.ConstraintFactory;
import org.acme.schooltimetabling.TimetableApp;
import org.acme.schooltimetabling.builders.teachers.TeacherBuilder;
import org.acme.schooltimetabling.constants.Constants;
import org.acme.schooltimetabling.constants.Days;
import org.acme.schooltimetabling.constants.Preference;
Expand All @@ -18,8 +19,8 @@
import java.util.List;

/**
* The Faculty object represents a teacher that is a faculty member. It extends the Teacher object and overrides the
* {@link #getConflict()} getConflict}
* The Faculty object represents a teacher that is a faculty member. It extends the Teacher object.
* It no longer has any special behavior.
*/
public class Faculty extends Teacher{
private static final Logger LOGGER = LoggerFactory.getLogger(Faculty.class);
Expand All @@ -28,7 +29,10 @@ public class Faculty extends Teacher{
*/
private static final BitSet FACULTY_CONFLICT;

/*static block for setting up times faculty members can't be scheduled during*/
/*THIS IS NO LONGER USED BUT I'M LEAVING IT FOR NOW BECAUSE IT HAS TEST BEHAVIOR; THE FACULTY MASKING IS NOW
* DONE WHEN I CREATE THE FACULTY OBJECT; L
*
* static block for setting up times faculty members can't be scheduled during*/
static {
/*enter here the bitsets needed for faculty time*/
FACULTY_CONFLICT = new BitSet();
Expand Down Expand Up @@ -74,10 +78,16 @@ public class Faculty extends Teacher{

}

/**
* use {@link TeacherBuilder} instead if possible
*/
public Faculty(int id, String name, BitSet preferences, BitSet acceptable, BitSet conflict) {
super(id, name, preferences, acceptable, conflict);
}

/**
* use {@link TeacherBuilder} instead if possible
*/
public Faculty(int id, String name, BitSet preferences, BitSet acceptable, BitSet conflict, Preference gap) {
super(id, name, preferences, acceptable, conflict, gap);
}
Expand All @@ -86,21 +96,6 @@ public Faculty(Teacher teacher){
super(teacher);
}

/**
* Needs to be overridden, faculty can't be scheduled during a certain time. Faculty's {@link Teacher#conflict conflict BitSet}
* is combined with {@link Faculty#FACULTY_CONFLICT BitSet facutly restriction}. Needed for the
* {@link org.acme.schooltimetabling.solver.TimetableConstraintProvider#teacherLessonConflict teacherLessonConflict}
* constraint
* @return BitSet representing faculty's conflict preferences and faculty conflict
*/
@Override
public BitSet getConflict() {
BitSet conflict = super.getConflict();
BitSet facultyConflictCopy = conflict.get(0, conflict.size());
facultyConflictCopy.or(FACULTY_CONFLICT);
return facultyConflictCopy;
}

public static BitSet getFacultyConflict() {
return (BitSet) FACULTY_CONFLICT.clone();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.acme.schooltimetabling.domain.teacher;

import org.acme.schooltimetabling.builders.teachers.TeacherBuilder;
import org.acme.schooltimetabling.constants.Preference;

import java.util.BitSet;
Expand All @@ -16,11 +17,17 @@ public class Teacher {
public BitSet conflict;
private Preference gapPref;

/**
* use {@link TeacherBuilder} instead if possible
*/
public Teacher(int id, String name, BitSet preferences, BitSet acceptable, BitSet conflict, Preference gapPref){
this(id, name, preferences, acceptable, conflict);
this.gapPref = gapPref;
}

/**
* use {@link TeacherBuilder} instead if possible
*/
public Teacher(int id, String name, BitSet preferences, BitSet acceptable, BitSet conflict) {
this.id = id;
this.name = name;
Expand Down Expand Up @@ -59,4 +66,10 @@ public BitSet getConflict() {
}

public Preference getGapPref(){ return gapPref; }

public void preschedule(BitSet preschedule){
preferences.andNot(preschedule);
acceptable.andNot(preschedule);
conflict.or(preschedule);
}
}
Loading
Loading