Model the domain objects
Your goal is to assign each lesson to a time slot and a room. You will create these classes:
Timeslot
The Timeslot
class represents a time interval when lessons are taught,
for example, Monday 10:30 - 11:30
or Tuesday 13:30 - 14:30
.
For simplicity’s sake, all time slots have the same duration
and there are no time slots during lunch or other breaks.
A time slot has no date, because a high school schedule just repeats every week. So there is no need for continuous planning.
Create the src/main/java/org/acme/schooltimetabling/domain/Timeslot.java
class:
package org.acme.schooltimetabling.domain;
import java.time.DayOfWeek;
import java.time.LocalTime;
public class Timeslot {
private DayOfWeek dayOfWeek;
private LocalTime startTime;
private LocalTime endTime;
public Timeslot() {
}
public Timeslot(DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) {
this.dayOfWeek = dayOfWeek;
this.startTime = startTime;
this.endTime = endTime;
}
public DayOfWeek getDayOfWeek() {
return dayOfWeek;
}
public LocalTime getStartTime() {
return startTime;
}
public LocalTime getEndTime() {
return endTime;
}
@Override
public String toString() {
return dayOfWeek + " " + startTime;
}
}
Because no Timeslot
instances change during solving, a Timeslot
is called a problem fact.
Such classes do not require any Timefold specific annotations.
Notice the toString()
method keeps the output short,
so it is easier to read Timefold’s DEBUG
or TRACE
log, as shown later.
Room
The Room
class represents a location where lessons are taught,
for example, Room A
or Room B
.
For simplicity’s sake, all rooms are without capacity limits
and they can accommodate all lessons.
Create the src/main/java/org/acme/schooltimetabling/domain/Room.java
class:
package org.acme.schooltimetabling.domain;
public class Room {
private String name;
public Room() {
}
public Room(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
Room
instances do not change during solving, so Room
is also a problem fact.
Lesson
During a lesson, represented by the Lesson
class,
a teacher teaches a subject to a group of students,
for example, Math by A.Turing for 9th grade
or Chemistry by M.Curie for 10th grade
.
If a subject is taught multiple times per week by the same teacher to the same student group,
there are multiple Lesson
instances that are only distinguishable by id
.
For example, the 9th grade has six math lessons a week.
During solving, Timefold changes the timeslot
and room
fields of the Lesson
class,
to assign each lesson to a time slot and a room.
Because Timefold changes these fields, Lesson
is a planning entity:
Most of the fields in the previous diagram contain input data, except for the orange fields:
A lesson’s timeslot
and room
fields are unassigned (null
) in the input data
and assigned (not null
) in the output data.
Timefold changes these fields during solving.
Such fields are called planning variables.
In order for Timefold to recognize them,
both the timeslot
and room
fields require an @PlanningVariable
annotation.
Their containing class, Lesson
, requires an @PlanningEntity
annotation.
Create the src/main/java/org/acme/schooltimetabling/domain/Lesson.java
class:
package org.acme.schooltimetabling.domain;
import ai.timefold.solver.core.api.domain.entity.PlanningEntity;
import ai.timefold.solver.core.api.domain.lookup.PlanningId;
import ai.timefold.solver.core.api.domain.variable.PlanningVariable;
@PlanningEntity
public class Lesson {
@PlanningId
private Long id;
private String subject;
private String teacher;
private String studentGroup;
@PlanningVariable
private Timeslot timeslot;
@PlanningVariable
private Room room;
public Lesson() {
}
public Lesson(Long id, String subject, String teacher, String studentGroup) {
this.id = id;
this.subject = subject;
this.teacher = teacher;
this.studentGroup = studentGroup;
}
public Long getId() {
return id;
}
public String getSubject() {
return subject;
}
public String getTeacher() {
return teacher;
}
public String getStudentGroup() {
return studentGroup;
}
public Timeslot getTimeslot() {
return timeslot;
}
public void setTimeslot(Timeslot timeslot) {
this.timeslot = timeslot;
}
public Room getRoom() {
return room;
}
public void setRoom(Room room) {
this.room = room;
}
@Override
public String toString() {
return subject + "(" + id + ")";
}
}
The Lesson
class has an @PlanningEntity
annotation,
so Timefold knows that this class changes during solving
because it contains one or more planning variables.
The timeslot
field has an @PlanningVariable
annotation,
so Timefold knows that it can change its value.
In order to find potential Timeslot
instances to assign to this field,
Timefold uses the variable type to connect to a value range provider
that provides a List<Timeslot>
to pick from.
The room
field also has an @PlanningVariable
annotation, for the same reasons.
Determining the |