Skip to content

Commit

Permalink
Student Scheduling: Curriculum Reservation/Restriction
Browse files Browse the repository at this point in the history
- added ability to have multiple majors
- added ability to match on student minors
  - when a reservation has both majors and minors, a student must have a least one matching minor OR major
  • Loading branch information
tomas-muller committed Jan 13, 2021
1 parent 54ad167 commit 505be75
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 15 deletions.
20 changes: 15 additions & 5 deletions src/org/cpsolver/studentsct/StudentSectioningXMLLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,13 @@ protected Reservation loadReservation(Element reservationEl, Offering offering,
course, studentIds);
}
} else if ("curriculum".equals(reservationEl.attributeValue("type")) || "curriculum-override".equals(reservationEl.attributeValue("type"))) {
List<String> acadAreas = new ArrayList<String>();
for (Iterator<?> k = reservationEl.elementIterator("area"); k.hasNext(); ) {
Element areaEl = (Element)k.next();
acadAreas.add(areaEl.attributeValue("code"));
}
if (acadAreas.isEmpty() && reservationEl.attributeValue("area") != null)
acadAreas.add(reservationEl.attributeValue("area"));
List<String> classifications = new ArrayList<String>();
for (Iterator<?> k = reservationEl.elementIterator("classification"); k.hasNext(); ) {
Element clasfEl = (Element)k.next();
Expand All @@ -596,18 +603,21 @@ protected Reservation loadReservation(Element reservationEl, Offering offering,
Element majorEl = (Element)k.next();
majors.add(majorEl.attributeValue("code"));
}
List<String> minors = new ArrayList<String>();
for (Iterator<?> k = reservationEl.elementIterator("minor"); k.hasNext(); ) {
Element minorEl = (Element)k.next();
minors.add(minorEl.attributeValue("code"));
}
if ("curriculum".equals(reservationEl.attributeValue("type")))
r = new CurriculumReservation(Long.valueOf(reservationEl.attributeValue("id")),
Double.parseDouble(reservationEl.attributeValue("limit", "-1")),
offering,
reservationEl.attributeValue("area"),
classifications, majors);
acadAreas, classifications, majors, minors);
else
r = new CurriculumOverride(Long.valueOf(reservationEl.attributeValue("id")),
Double.parseDouble(reservationEl.attributeValue("limit", "-1")),
offering,
reservationEl.attributeValue("area"),
classifications, majors);
acadAreas, classifications, majors, minors);
} else if ("course".equals(reservationEl.attributeValue("type"))) {
long courseId = Long.parseLong(reservationEl.attributeValue("course"));
for (Course course: offering.getCourses()) {
Expand Down Expand Up @@ -969,7 +979,7 @@ protected Student loadStudent(Element studentEl, Map<Long, Offering> offeringTab
new Unavailability(student, section, "true".equals(requestEl.attributeValue("allowOverlap")));
} else if ("acm".equals(requestEl.getName())) {
if (requestEl.attributeValue("minor") != null)
student.getAreaClassificationMajors().add(new AreaClassificationMajor(requestEl.attributeValue("area"), requestEl.attributeValue("classification"), requestEl.attributeValue("minor")));
student.getAreaClassificationMinors().add(new AreaClassificationMajor(requestEl.attributeValue("area"), requestEl.attributeValue("classification"), requestEl.attributeValue("minor")));
else
student.getAreaClassificationMajors().add(new AreaClassificationMajor(requestEl.attributeValue("area"), requestEl.attributeValue("classification"), requestEl.attributeValue("major")));
} else if ("group".equals(requestEl.getName())) {
Expand Down
9 changes: 8 additions & 1 deletion src/org/cpsolver/studentsct/StudentSectioningXMLSaver.java
Original file line number Diff line number Diff line change
Expand Up @@ -531,11 +531,18 @@ protected void saveReservation(Element reservationEl, Reservation reservation) {
CurriculumReservation cr = (CurriculumReservation)reservation;
if (cr.getReservationLimit() >= 0.0)
reservationEl.addAttribute("limit", String.valueOf(cr.getReservationLimit()));
reservationEl.addAttribute("area", cr.getAcademicArea());
if (cr.getAcademicAreas().size() == 1)
reservationEl.addAttribute("area", cr.getAcademicAreas().iterator().next());
else {
for (String area: cr.getAcademicAreas())
reservationEl.addElement("area").addAttribute("code", area);
}
for (String clasf: cr.getClassifications())
reservationEl.addElement("classification").addAttribute("code", clasf);
for (String major: cr.getMajors())
reservationEl.addElement("major").addAttribute("code", major);
for (String minor: cr.getMinors())
reservationEl.addElement("minor").addAttribute("code", minor);
} else if (reservation instanceof CourseReservation) {
reservationEl.addAttribute("type", "course");
CourseReservation cr = (CourseReservation)reservation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public class CurriculumOverride extends CurriculumReservation {
*/
public static final boolean DEFAULT_ALLOW_OVERLAP = false;

public CurriculumOverride(long id, double limit, Offering offering, Collection<String> acadAreas, Collection<String> classifications, Collection<String> majors, Collection<String> minors) {
super(id, limit, offering, acadAreas, classifications, majors, minors, DEFAULT_PRIORITY, DEFAULT_MUST_BE_USED, DEFAULT_CAN_ASSIGN_OVER_LIMIT, DEFAULT_ALLOW_OVERLAP);
}
@Deprecated
public CurriculumOverride(long id, double limit, Offering offering, String acadArea, Collection<String> classifications, Collection<String> majors) {
super(id, limit, offering, acadArea, classifications, majors, DEFAULT_PRIORITY, DEFAULT_MUST_BE_USED, DEFAULT_CAN_ASSIGN_OVER_LIMIT, DEFAULT_ALLOW_OVERLAP);
}
Expand Down
97 changes: 88 additions & 9 deletions src/org/cpsolver/studentsct/reservation/CurriculumReservation.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@
*/
public class CurriculumReservation extends Reservation {
private double iLimit;
private String iAcadArea;
private Set<String> iAcadAreas = new HashSet<String>();
private Set<String> iClassifications = new HashSet<String>();
private Set<String> iMajors = new HashSet<String>();
private Set<String> iMinors = new HashSet<String>();

/**
* Reservation priority (lower than individual and group reservations)
Expand All @@ -58,6 +59,29 @@ public class CurriculumReservation extends Reservation {
*/
public static final boolean DEFAULT_ALLOW_OVERLAP = false;

/**
* Constructor
* @param id unique id
* @param limit reservation limit (-1 for unlimited)
* @param offering instructional offering on which the reservation is set
* @param acadAreas one or more academic areas
* @param classifications zero or more classifications (classifications must match if not empty)
* @param majors zero or more majors (majors must match if not empty)
* @param minors zero or more majors (minors must match if not empty)
*/
public CurriculumReservation(long id, double limit, Offering offering, Collection<String> acadAreas, Collection<String> classifications, Collection<String> majors, Collection<String> minors) {
super(id, offering, DEFAULT_PRIORITY, DEFAULT_MUST_BE_USED, DEFAULT_CAN_ASSIGN_OVER_LIMIT, DEFAULT_ALLOW_OVERLAP);
iLimit = limit;
if (acadAreas != null)
iAcadAreas.addAll(acadAreas);
if (classifications != null)
iClassifications.addAll(classifications);
if (majors != null)
iMajors.addAll(majors);
if (minors != null)
iMinors.addAll(minors);
}

/**
* Constructor
* @param id unique id
Expand All @@ -67,16 +91,45 @@ public class CurriculumReservation extends Reservation {
* @param classifications zero or more classifications (classifications must match if not empty)
* @param majors zero or more majors (majors must match if not empty)
*/
@Deprecated
public CurriculumReservation(long id, double limit, Offering offering, String acadArea, Collection<String> classifications, Collection<String> majors) {
super(id, offering, DEFAULT_PRIORITY, DEFAULT_MUST_BE_USED, DEFAULT_CAN_ASSIGN_OVER_LIMIT, DEFAULT_ALLOW_OVERLAP);
iLimit = limit;
iAcadArea = acadArea;
iAcadAreas.add(acadArea);
if (classifications != null)
iClassifications.addAll(classifications);
if (majors != null)
iMajors.addAll(majors);
}

/**
* Constructor
* @param id unique id
* @param limit reservation limit (-1 for unlimited)
* @param offering instructional offering on which the reservation is set
* @param acadAreas one or more academic areas
* @param classifications zero or more classifications (classifications must match if not empty)
* @param majors zero or more majors (majors must match if not empty)
* @param minors zero or more majors (minors must match if not empty)
* @param priority reservation priority
* @param mustBeUsed must this reservation be used
* @param canAssignOverLimit can assign over class / configuration / course limit
* @param allowOverlap does this reservation allow for overlaps
*/
protected CurriculumReservation(long id, double limit, Offering offering, Collection<String> acadAreas, Collection<String> classifications, Collection<String> majors, Collection<String> minors,
int priority, boolean mustBeUsed, boolean canAssignOverLimit, boolean allowOverlap) {
super(id, offering, priority, mustBeUsed, canAssignOverLimit, allowOverlap);
iLimit = limit;
if (acadAreas != null)
iAcadAreas.addAll(acadAreas);
if (classifications != null)
iClassifications.addAll(classifications);
if (majors != null)
iMajors.addAll(majors);
if (minors != null)
iMinors.addAll(minors);
}

/**
* Constructor
* @param id unique id
Expand All @@ -90,11 +143,12 @@ public CurriculumReservation(long id, double limit, Offering offering, String ac
* @param canAssignOverLimit can assign over class / configuration / course limit
* @param allowOverlap does this reservation allow for overlaps
*/
@Deprecated
protected CurriculumReservation(long id, double limit, Offering offering, String acadArea, Collection<String> classifications, Collection<String> majors,
int priority, boolean mustBeUsed, boolean canAssignOverLimit, boolean allowOverlap) {
super(id, offering, priority, mustBeUsed, canAssignOverLimit, allowOverlap);
iLimit = limit;
iAcadArea = acadArea;
iAcadAreas.add(acadArea);
if (classifications != null)
iClassifications.addAll(classifications);
if (majors != null)
Expand All @@ -118,12 +172,22 @@ public void setReservationLimit(double limit) {
}


/**
* Academic areas
* @return selected academic areas
*/
public Set<String> getAcademicAreas() {
return iAcadAreas;
}

/**
* Academic area
* @return selected academic area
*/
@Deprecated
public String getAcademicArea() {
return iAcadArea;
if (getAcademicAreas().isEmpty()) return "";
return getAcademicAreas().iterator().next();
}

/**
Expand All @@ -134,6 +198,14 @@ public Set<String> getMajors() {
return iMajors;
}

/**
* Minors
* @return selected minors
*/
public Set<String> getMinors() {
return iMinors;
}

/**
* Academic classifications
* @return selected academic classifications
Expand All @@ -147,11 +219,18 @@ public Set<String> getClassifications() {
*/
@Override
public boolean isApplicable(Student student) {
for (AreaClassificationMajor acm: student.getAreaClassificationMajors())
if (getAcademicArea().equals(acm.getArea()) &&
(getClassifications().isEmpty() || getClassifications().contains(acm.getClassification())) &&
(getMajors().isEmpty() || getMajors().contains(acm.getMajor())))
return true;
if (!getMajors().isEmpty() || getMinors().isEmpty())
for (AreaClassificationMajor acm: student.getAreaClassificationMajors())
if (getAcademicAreas().contains(acm.getArea()) &&
(getClassifications().isEmpty() || getClassifications().contains(acm.getClassification())) &&
(getMajors().isEmpty() || getMajors().contains(acm.getMajor())))
return true;
if (!getMinors().isEmpty())
for (AreaClassificationMajor acm: student.getAreaClassificationMinors())
if (getAcademicAreas().contains(acm.getArea()) &&
(getClassifications().isEmpty() || getClassifications().contains(acm.getClassification())) &&
(getMinors().contains(acm.getMajor())))
return true;
return false;
}

Expand Down

0 comments on commit 505be75

Please sign in to comment.