Search in sources :

Example 6 with TimeTable

use of org.acme.schooltimetabling.domain.TimeTable in project optaplanner-quickstarts by kiegroup.

the class TimeTableResourceTest method solveAndRetrieve.

@Test
@Timeout(60L)
void solveAndRetrieve() throws JsonProcessingException {
    timeTableResource.solve();
    await().timeout(AWAIT_TIMEOUT).until(solverRequestSink::received, messages -> messages.size() == 1);
    Message<String> solverRequestMessage = solverRequestSink.received().get(0);
    SolverRequest solverRequest = objectMapper.readValue(solverRequestMessage.getPayload(), SolverRequest.class);
    // Assign one lesson to simulate solving.
    TimeTable requestTimeTable = solverRequest.getTimeTable();
    Lesson firstLesson = requestTimeTable.getLessonList().get(0);
    firstLesson.setRoom(requestTimeTable.getRoomList().get(0));
    firstLesson.setTimeslot(requestTimeTable.getTimeslotList().get(0));
    SolverResponse solverResponse = new SolverResponse(solverRequest.getProblemId(), requestTimeTable);
    solverResponseSource.send(objectMapper.writeValueAsString(solverResponse));
    // Wait until the client receives the message and saves the new timetable to a database.
    await().timeout(AWAIT_TIMEOUT).until(timeTableResource::getTimeTable, timeTable -> timeTable.getLessonList().get(0).getRoom() != null);
    Lesson solvedFirstLesson = timeTableResource.getTimeTable().getLessonList().get(0);
    assertThat(solvedFirstLesson.getRoom()).isNotNull();
    assertThat(solvedFirstLesson.getTimeslot()).isNotNull();
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) SolverResponse(org.acme.schooltimetabling.message.SolverResponse) Lesson(org.acme.schooltimetabling.domain.Lesson) QuarkusTest(io.quarkus.test.junit.QuarkusTest) Test(org.junit.jupiter.api.Test) Timeout(org.junit.jupiter.api.Timeout)

Example 7 with TimeTable

use of org.acme.schooltimetabling.domain.TimeTable in project optaplanner-quickstarts by kiegroup.

the class TimeTableMessagingHandler method solve.

@Incoming(SOLVER_REQUEST_CHANNEL)
public CompletionStage<Void> solve(Message<String> solverRequestMessage) {
    return CompletableFuture.runAsync(() -> {
        SolverRequest solverRequest;
        try {
            solverRequest = objectMapper.readValue(solverRequestMessage.getPayload(), SolverRequest.class);
        } catch (Throwable throwable) {
            LOGGER.warn("Unable to deserialize solver request from JSON.", throwable);
            /* Usually a bad request, which should be immediately rejected. No error response can be sent back
                   as the problemId is unknown. Such a NACKed message is redirected to the DLQ (Dead letter queue).
                   Catching the Throwable to make sure no unchecked exceptions are missed. */
            solverRequestMessage.nack(throwable);
            return;
        }
        TimeTable solution;
        try {
            solution = solver.solve(solverRequest.getTimeTable());
            replySuccess(solverRequestMessage, solverRequest.getProblemId(), solution);
        } catch (Throwable throwable) {
            LOGGER.warn("Error during processing a solver request ({}).", solverRequest.getProblemId(), throwable);
            replyFailure(solverRequestMessage, solverRequest.getProblemId(), throwable);
        }
    });
}
Also used : SolverRequest(org.acme.schooltimetabling.message.SolverRequest) TimeTable(org.acme.schooltimetabling.domain.TimeTable) Incoming(org.eclipse.microprofile.reactive.messaging.Incoming)

Example 8 with TimeTable

use of org.acme.schooltimetabling.domain.TimeTable in project optaplanner-quickstarts by kiegroup.

the class TimeTableApp method printTimetable.

private static void printTimetable(TimeTable timeTable) {
    LOGGER.info("");
    List<Room> roomList = timeTable.getRoomList();
    List<Lesson> lessonList = timeTable.getLessonList();
    Map<Timeslot, Map<Room, List<Lesson>>> lessonMap = lessonList.stream().filter(lesson -> lesson.getTimeslot() != null && lesson.getRoom() != null).collect(Collectors.groupingBy(Lesson::getTimeslot, Collectors.groupingBy(Lesson::getRoom)));
    LOGGER.info("|            | " + roomList.stream().map(room -> String.format("%-10s", room.getName())).collect(Collectors.joining(" | ")) + " |");
    LOGGER.info("|" + "------------|".repeat(roomList.size() + 1));
    for (Timeslot timeslot : timeTable.getTimeslotList()) {
        List<List<Lesson>> cellList = roomList.stream().map(room -> {
            Map<Room, List<Lesson>> byRoomMap = lessonMap.get(timeslot);
            if (byRoomMap == null) {
                return Collections.<Lesson>emptyList();
            }
            List<Lesson> cellLessonList = byRoomMap.get(room);
            if (cellLessonList == null) {
                return Collections.<Lesson>emptyList();
            }
            return cellLessonList;
        }).collect(Collectors.toList());
        LOGGER.info("| " + String.format("%-10s", timeslot.getDayOfWeek().toString().substring(0, 3) + " " + timeslot.getStartTime()) + " | " + cellList.stream().map(cellLessonList -> String.format("%-10s", cellLessonList.stream().map(Lesson::getSubject).collect(Collectors.joining(", ")))).collect(Collectors.joining(" | ")) + " |");
        LOGGER.info("|            | " + cellList.stream().map(cellLessonList -> String.format("%-10s", cellLessonList.stream().map(Lesson::getTeacher).collect(Collectors.joining(", ")))).collect(Collectors.joining(" | ")) + " |");
        LOGGER.info("|            | " + cellList.stream().map(cellLessonList -> String.format("%-10s", cellLessonList.stream().map(Lesson::getStudentGroup).collect(Collectors.joining(", ")))).collect(Collectors.joining(" | ")) + " |");
        LOGGER.info("|" + "------------|".repeat(roomList.size() + 1));
    }
    List<Lesson> unassignedLessons = lessonList.stream().filter(lesson -> lesson.getTimeslot() == null || lesson.getRoom() == null).collect(Collectors.toList());
    if (!unassignedLessons.isEmpty()) {
        LOGGER.info("");
        LOGGER.info("Unassigned lessons");
        for (Lesson lesson : unassignedLessons) {
            LOGGER.info("  " + lesson.getSubject() + " - " + lesson.getTeacher() + " - " + lesson.getStudentGroup());
        }
    }
}
Also used : SolverConfig(org.optaplanner.core.config.solver.SolverConfig) Solver(org.optaplanner.core.api.solver.Solver) Logger(org.slf4j.Logger) TimeTableConstraintProvider(org.acme.schooltimetabling.solver.TimeTableConstraintProvider) LoggerFactory(org.slf4j.LoggerFactory) SolverFactory(org.optaplanner.core.api.solver.SolverFactory) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) TimeTable(org.acme.schooltimetabling.domain.TimeTable) List(java.util.List) Lesson(org.acme.schooltimetabling.domain.Lesson) DayOfWeek(java.time.DayOfWeek) Duration(java.time.Duration) Map(java.util.Map) LocalTime(java.time.LocalTime) Collections(java.util.Collections) Room(org.acme.schooltimetabling.domain.Room) Timeslot(org.acme.schooltimetabling.domain.Timeslot) ArrayList(java.util.ArrayList) List(java.util.List) Room(org.acme.schooltimetabling.domain.Room) Lesson(org.acme.schooltimetabling.domain.Lesson) Timeslot(org.acme.schooltimetabling.domain.Timeslot) Map(java.util.Map)

Example 9 with TimeTable

use of org.acme.schooltimetabling.domain.TimeTable in project optaplanner-quickstarts by kiegroup.

the class TimeTableApp method main.

public static void main(String[] args) {
    SolverFactory<TimeTable> solverFactory = SolverFactory.create(new SolverConfig().withSolutionClass(TimeTable.class).withEntityClasses(Lesson.class).withConstraintProviderClass(TimeTableConstraintProvider.class).withTerminationSpentLimit(Duration.ofSeconds(5)));
    // Load the problem
    TimeTable problem = generateDemoData();
    // Solve the problem
    Solver<TimeTable> solver = solverFactory.buildSolver();
    TimeTable solution = solver.solve(problem);
    // Visualize the solution
    printTimetable(solution);
}
Also used : TimeTable(org.acme.schooltimetabling.domain.TimeTable) Lesson(org.acme.schooltimetabling.domain.Lesson) SolverConfig(org.optaplanner.core.config.solver.SolverConfig)

Example 10 with TimeTable

use of org.acme.schooltimetabling.domain.TimeTable in project optaplanner-quickstarts by kiegroup.

the class TimeTableController method getTimeTable.

// To try, GET http://localhost:8080/timeTable
@GetMapping()
public TimeTable getTimeTable() {
    // Get the solver status before loading the solution
    // to avoid the race condition that the solver terminates between them
    SolverStatus solverStatus = getSolverStatus();
    TimeTable solution = timeTableRepository.findById(TimeTableRepository.SINGLETON_TIME_TABLE_ID);
    // Sets the score
    scoreManager.updateScore(solution);
    solution.setSolverStatus(solverStatus);
    return solution;
}
Also used : TimeTable(org.acme.schooltimetabling.domain.TimeTable) SolverStatus(org.optaplanner.core.api.solver.SolverStatus) GetMapping(org.springframework.web.bind.annotation.GetMapping)

Aggregations

TimeTable (org.acme.schooltimetabling.domain.TimeTable)15 Lesson (org.acme.schooltimetabling.domain.Lesson)9 Room (org.acme.schooltimetabling.domain.Room)5 Timeslot (org.acme.schooltimetabling.domain.Timeslot)5 SolverRequest (org.acme.schooltimetabling.message.SolverRequest)5 Test (org.junit.jupiter.api.Test)5 Timeout (org.junit.jupiter.api.Timeout)5 QuarkusTest (io.quarkus.test.junit.QuarkusTest)4 SolverResponse (org.acme.schooltimetabling.message.SolverResponse)4 ArrayList (java.util.ArrayList)2 Incoming (org.eclipse.microprofile.reactive.messaging.Incoming)2 SolverStatus (org.optaplanner.core.api.solver.SolverStatus)2 SolverConfig (org.optaplanner.core.config.solver.SolverConfig)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 DayOfWeek (java.time.DayOfWeek)1 Duration (java.time.Duration)1 LocalTime (java.time.LocalTime)1 Collections (java.util.Collections)1 List (java.util.List)1 Map (java.util.Map)1