14.2. 对域对象建模
红帽构建的 OptaPlanner 时间项目的目标是将每项分配给一个时间插槽和房间。要做到这一点,添加三个类: Timeslot
、init
on 和 Room,如下图所示:

timeslot
Timeslot
类代表当减少活动为过期的时间间隔时,例如,Monday 10:30 - 11:30
或 Tuesday 13:30 - 14:30
。在这个示例中,所有时间段都有相同的持续时间,在 lunch 或其他中断过程中没有时间插槽。
一个时间插槽没有日期,因为每周计划只重复一次。不需要 持续规划。timeslot 被称为 问题事实,因为公司不会更改 Timeslot
实例。此类类不需要任何特定于 OptaPlanner 的注解。
房间
Room
类代表更小活动的位置,例如 Room A
或 Room B
。在本例中,所有房间都没有容量限制,它们可以容纳所有定义。
空间
实例在竞争过程中不会改变,因此 Room
也是 问题事实。
lesson
在小时间中,由周一类代表,受一组参与者代表的规定,例如,A.Turing for 9th
rating 或 Chemistry by M.Curie 代表第 10 等级
。如果一个主题是按同一站组相同的每周的多次,则有多个仅可通过
id
区分的实例。例如,第 9 等级每周有六个数学。
在 OptaPlanner 期间,OptaPlanner 会更改周一类的 timeslot
和 room
字段,以将每个小时间分配给一个时间插槽和房间。因为 OptaPlanner 更改这些字段,因此
Apple
on 是一个 规划实体 :

上图中的大部分字段都包含输入数据,但 orange 字段除外。在输入数据中取消分配较少的 timeslot
和 room
字段,并在输出数据中分配(而非
)。OptaPlanner 在参与过程中会更改这些字段。此类字段称为 规划变量。为了使 OptaPlanner 能够识别它们,null
timeslot
和 room
字段都需要 @PlanningVariable
注释。它们包含类属性需要 @PlanningEntity
注释。
流程
创建
src/main/java/com/example/domain/Timeslot.java
类:package com.example.domain; import java.time.DayOfWeek; import java.time.LocalTime; public class Timeslot { private DayOfWeek dayOfWeek; private LocalTime startTime; private LocalTime endTime; private Timeslot() { } public Timeslot(DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) { this.dayOfWeek = dayOfWeek; this.startTime = startTime; this.endTime = endTime; } @Override public String toString() { return dayOfWeek + " " + startTime.toString(); } // ******************************** // Getters and setters // ******************************** public DayOfWeek getDayOfWeek() { return dayOfWeek; } public LocalTime getStartTime() { return startTime; } public LocalTime getEndTime() { return endTime; } }
请注意,
toString ()
方法保留输出短,因此更易于阅读 OptaPlanner 的DEBUG
或TRACE
日志,如稍后所示。创建
src/main/java/com/example/domain/Room.java
类:package com.example.domain; public class Room { private String name; private Room() { } public Room(String name) { this.name = name; } @Override public String toString() { return name; } // ******************************** // Getters and setters // ******************************** public String getName() { return name; } }
创建
src/main/java/com/example/domain/Lesson.java
类:package com.example.domain; import org.optaplanner.core.api.domain.entity.PlanningEntity; import org.optaplanner.core.api.domain.variable.PlanningVariable; @PlanningEntity public class Lesson { private Long id; private String subject; private String teacher; private String studentGroup; @PlanningVariable(valueRangeProviderRefs = "timeslotRange") private Timeslot timeslot; @PlanningVariable(valueRangeProviderRefs = "roomRange") private Room room; private Lesson() { } public Lesson(Long id, String subject, String teacher, String studentGroup) { this.id = id; this.subject = subject; this.teacher = teacher; this.studentGroup = studentGroup; } @Override public String toString() { return subject + "(" + id + ")"; } // ******************************** // Getters and setters // ******************************** 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; } }
bring
on
类有一个@PlanningEntity
注释,因此 OptaPlanner 知道该类在周五期间发生了变化,因为它包含一个或多个规划变量。timeslot
字段有一个@PlanningVariable
注释,因此 OptaPlanner 知道它可以更改其值。要查找分配给此字段的潜在Timeslot
实例,OptaPlanner 使用valueRangeProviderRefs
属性连接到提供List<Timeslot>
; 的值范围供应商。有关值范围供应商的详情,请查看 第 14.4 节 “在计划解决方案中收集域对象”。由于同样原因,
room
字段也有一个@PlanningVariable
注释。