= Model the domain objects
:imagesdir: ../..

Your goal is to assign each lesson to a time slot and a room.
You will create these classes:

image::quickstart/school-timetabling/schoolTimetablingClassDiagramPure.png[]

== 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 xref:repeated-planning/repeated-planning.adoc#continuousPlanning[continuous planning].

Create the `src/main/java/org/acme/schooltimetabling/domain/Timeslot.java` class:

[source,java]
----
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 OptaPlanner specific annotations.

Notice the `toString()` method keeps the output short,
so it is easier to read OptaPlanner'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:

[source,java]
----
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, OptaPlanner changes the `timeslot` and `room` fields of the `Lesson` class,
to assign each lesson to a time slot and a room.
Because OptaPlanner changes these fields, `Lesson` is a _planning entity_:

image::quickstart/school-timetabling/schoolTimetablingClassDiagramAnnotated.png[]

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.
OptaPlanner changes these fields during solving.
Such fields are called planning variables.
In order for OptaPlanner 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:

[source,java]
----
package org.acme.schooltimetabling.domain;

import org.optaplanner.core.api.domain.entity.PlanningEntity;
import org.optaplanner.core.api.domain.lookup.PlanningId;
import org.optaplanner.core.api.domain.variable.PlanningVariable;

@PlanningEntity
public class Lesson {

    @PlanningId
    private Long id;

    private String subject;
    private String teacher;
    private String studentGroup;

    @PlanningVariable(valueRangeProviderRefs = "timeslotRange")
    private Timeslot timeslot;
    @PlanningVariable(valueRangeProviderRefs = "roomRange")
    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 OptaPlanner knows that this class changes during solving
because it contains one or more planning variables.

The `timeslot` field has an `@PlanningVariable` annotation,
so OptaPlanner knows that it can change its value.
In order to find potential `Timeslot` instances to assign to this field,
OptaPlanner uses the `valueRangeProviderRefs` property to connect to a value range provider
(explained later) that provides a `List<Timeslot>` to pick from.

The `room` field also has an `@PlanningVariable` annotation, for the same reasons.

[NOTE]
====
Determining the `@PlanningVariable` fields for an arbitrary constraint solving use case
is often challenging the first time.
Read xref:design-patterns/design-patterns.adoc#domainModelingGuide[the domain modeling guidelines] to avoid common pitfalls.
====
