From 9b2be5df2218b585f42ba86b6aff1def22723f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Petrovick=C3=BD?= Date: Wed, 18 Feb 2026 14:06:37 +0100 Subject: [PATCH 1/2] refactor: remove SolverManager's ProblemId generic --- .../rest/BedSchedulingResource.java | 24 +++++++++---------- .../rest/ConferenceSchedulingResource.java | 24 +++++++++---------- .../rest/EmployeeScheduleResource.java | 4 ++-- .../facilitylocation/rest/SolverResource.java | 4 ++-- .../solver/SolverManagerTest.java | 2 +- .../rest/FlightCrewSchedulingResource.java | 24 +++++++++---------- .../rest/PackagingScheduleResource.java | 4 ++-- .../rest/MaintenanceScheduleResource.java | 4 ++-- .../rest/MeetingSchedulingResource.java | 24 +++++++++---------- .../rest/OrderPickingSolverResource.java | 4 ++-- .../rest/ProjectJobSchedulingResource.java | 24 +++++++++---------- .../rest/TimetableResource.java | 4 ++-- .../rest/SportsLeagueSchedulingResource.java | 24 +++++++++---------- .../rest/TimetableController.java | 4 ++-- .../rest/TaskAssigningResource.java | 24 +++++++++---------- .../rest/TournamentSchedulingResource.java | 24 +++++++++---------- .../rest/VehicleRoutePlanResource.java | 4 ++-- .../rest/TimetableResource.kt | 12 +++++----- 18 files changed, 119 insertions(+), 119 deletions(-) diff --git a/java/bed-allocation/src/main/java/org/acme/bedallocation/rest/BedSchedulingResource.java b/java/bed-allocation/src/main/java/org/acme/bedallocation/rest/BedSchedulingResource.java index 0bc711c417..413c19dbaf 100644 --- a/java/bed-allocation/src/main/java/org/acme/bedallocation/rest/BedSchedulingResource.java +++ b/java/bed-allocation/src/main/java/org/acme/bedallocation/rest/BedSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.bedallocation.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Bed Scheduling", description = "Bed Scheduling service assigning beds for patient stays.") @Path("schedules") @@ -48,7 +48,7 @@ public class BedSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(BedSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public BedSchedulingResource() { } @Inject - public BedSchedulingResource(SolverManager solverManager, + public BedSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -92,7 +92,7 @@ public String solve(BedPlan problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/conference-scheduling/src/main/java/org/acme/conferencescheduling/rest/ConferenceSchedulingResource.java b/java/conference-scheduling/src/main/java/org/acme/conferencescheduling/rest/ConferenceSchedulingResource.java index 2b55eee5db..0a6261960b 100644 --- a/java/conference-scheduling/src/main/java/org/acme/conferencescheduling/rest/ConferenceSchedulingResource.java +++ b/java/conference-scheduling/src/main/java/org/acme/conferencescheduling/rest/ConferenceSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.conferencescheduling.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Conference Scheduling", description = "Conference Scheduling service assigning rooms and timeslots for conference talks.") @Path("schedules") @@ -48,7 +48,7 @@ public class ConferenceSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(ConferenceSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public ConferenceSchedulingResource() { } @Inject - public ConferenceSchedulingResource(SolverManager solverManager, + public ConferenceSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -92,7 +92,7 @@ public String solve(ConferenceSchedule problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java b/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java index f990ea09fd..f6b76e9aab 100644 --- a/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java +++ b/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java @@ -43,14 +43,14 @@ public class EmployeeScheduleResource { private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeScheduleResource.class); - SolverManager solverManager; + SolverManager solverManager; SolutionManager solutionManager; // TODO: Without any "time to live", the map may eventually grow out of memory. private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @Inject - public EmployeeScheduleResource(SolverManager solverManager, + public EmployeeScheduleResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; diff --git a/java/facility-location/src/main/java/org/acme/facilitylocation/rest/SolverResource.java b/java/facility-location/src/main/java/org/acme/facilitylocation/rest/SolverResource.java index 738c9edabe..f2f781454d 100644 --- a/java/facility-location/src/main/java/org/acme/facilitylocation/rest/SolverResource.java +++ b/java/facility-location/src/main/java/org/acme/facilitylocation/rest/SolverResource.java @@ -27,11 +27,11 @@ public class SolverResource { private final AtomicReference solverError = new AtomicReference<>(); private final FacilityLocationProblemRepository repository; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; public SolverResource(FacilityLocationProblemRepository repository, - SolverManager solverManager, + SolverManager solverManager, SolutionManager solutionManager) { this.repository = repository; this.solverManager = solverManager; diff --git a/java/facility-location/src/test/java/org/acme/facilitylocation/solver/SolverManagerTest.java b/java/facility-location/src/test/java/org/acme/facilitylocation/solver/SolverManagerTest.java index 59cdbc11fc..9e16020d9f 100644 --- a/java/facility-location/src/test/java/org/acme/facilitylocation/solver/SolverManagerTest.java +++ b/java/facility-location/src/test/java/org/acme/facilitylocation/solver/SolverManagerTest.java @@ -19,7 +19,7 @@ class SolverManagerTest { @Inject - SolverManager solverManager; + SolverManager solverManager; @Test void solve() throws ExecutionException, InterruptedException { diff --git a/java/flight-crew-scheduling/src/main/java/org/acme/flighcrewscheduling/rest/FlightCrewSchedulingResource.java b/java/flight-crew-scheduling/src/main/java/org/acme/flighcrewscheduling/rest/FlightCrewSchedulingResource.java index bbce0c5875..e5f29dbaf3 100644 --- a/java/flight-crew-scheduling/src/main/java/org/acme/flighcrewscheduling/rest/FlightCrewSchedulingResource.java +++ b/java/flight-crew-scheduling/src/main/java/org/acme/flighcrewscheduling/rest/FlightCrewSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.flighcrewscheduling.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Flight Crew Scheduling", description = "Flight Crew Scheduling service assigning crew for flights.") @Path("schedules") @@ -48,7 +48,7 @@ public class FlightCrewSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(FlightCrewSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public FlightCrewSchedulingResource() { } @Inject - public FlightCrewSchedulingResource(SolverManager solverManager, + public FlightCrewSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -92,7 +92,7 @@ public String solve(FlightCrewSchedule problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/food-packaging/src/main/java/org/acme/foodpackaging/rest/PackagingScheduleResource.java b/java/food-packaging/src/main/java/org/acme/foodpackaging/rest/PackagingScheduleResource.java index c1ca98f5b5..4545b1c1c5 100644 --- a/java/food-packaging/src/main/java/org/acme/foodpackaging/rest/PackagingScheduleResource.java +++ b/java/food-packaging/src/main/java/org/acme/foodpackaging/rest/PackagingScheduleResource.java @@ -25,13 +25,13 @@ public class PackagingScheduleResource { private PackagingScheduleRepository repository; - private SolverManager solverManager; + private SolverManager solverManager; private SolutionManager solutionManager; @Inject public PackagingScheduleResource(PackagingScheduleRepository repository, - SolverManager solverManager, + SolverManager solverManager, SolutionManager solutionManager) { this.repository = repository; this.solverManager = solverManager; diff --git a/java/maintenance-scheduling/src/main/java/org/acme/maintenancescheduling/rest/MaintenanceScheduleResource.java b/java/maintenance-scheduling/src/main/java/org/acme/maintenancescheduling/rest/MaintenanceScheduleResource.java index 4f85f546c1..0883de5bfa 100644 --- a/java/maintenance-scheduling/src/main/java/org/acme/maintenancescheduling/rest/MaintenanceScheduleResource.java +++ b/java/maintenance-scheduling/src/main/java/org/acme/maintenancescheduling/rest/MaintenanceScheduleResource.java @@ -43,14 +43,14 @@ public class MaintenanceScheduleResource { public static final String SINGLETON_SCHEDULE_ID = "1"; - SolverManager solverManager; + SolverManager solverManager; SolutionManager solutionManager; // TODO: Without any "time to live", the map may eventually grow out of memory. private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @Inject - public MaintenanceScheduleResource(SolverManager solverManager, + public MaintenanceScheduleResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; diff --git a/java/meeting-scheduling/src/main/java/org/acme/meetingschedule/rest/MeetingSchedulingResource.java b/java/meeting-scheduling/src/main/java/org/acme/meetingschedule/rest/MeetingSchedulingResource.java index ced9c0895d..dd48292afa 100644 --- a/java/meeting-scheduling/src/main/java/org/acme/meetingschedule/rest/MeetingSchedulingResource.java +++ b/java/meeting-scheduling/src/main/java/org/acme/meetingschedule/rest/MeetingSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.meetingschedule.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Meeting Scheduling", description = "Meetings Scheduling service assigning timeslots and rooms for meetings.") @Path("schedules") @@ -48,7 +48,7 @@ public class MeetingSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(MeetingSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public MeetingSchedulingResource() { } @Inject - public MeetingSchedulingResource(SolverManager solverManager, + public MeetingSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -92,7 +92,7 @@ public String solve(MeetingSchedule problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/order-picking/src/main/java/org/acme/orderpicking/rest/OrderPickingSolverResource.java b/java/order-picking/src/main/java/org/acme/orderpicking/rest/OrderPickingSolverResource.java index 7a18ae1319..25526d6546 100644 --- a/java/order-picking/src/main/java/org/acme/orderpicking/rest/OrderPickingSolverResource.java +++ b/java/order-picking/src/main/java/org/acme/orderpicking/rest/OrderPickingSolverResource.java @@ -28,12 +28,12 @@ public class OrderPickingSolverResource { private static final String PROBLEM_ID = "1"; private final AtomicBoolean solverWasNeverStarted = new AtomicBoolean(true); - private SolverManager solverManager; + private SolverManager solverManager; private SolutionManager solutionManager; private OrderPickingRepository orderPickingRepository; @Inject - public OrderPickingSolverResource(SolverManager solverManager, + public OrderPickingSolverResource(SolverManager solverManager, SolutionManager solutionManager, OrderPickingRepository orderPickingRepository) { this.solverManager = solverManager; diff --git a/java/project-job-scheduling/src/main/java/org/acme/projectjobschedule/rest/ProjectJobSchedulingResource.java b/java/project-job-scheduling/src/main/java/org/acme/projectjobschedule/rest/ProjectJobSchedulingResource.java index e13452509e..0f083f7b4b 100644 --- a/java/project-job-scheduling/src/main/java/org/acme/projectjobschedule/rest/ProjectJobSchedulingResource.java +++ b/java/project-job-scheduling/src/main/java/org/acme/projectjobschedule/rest/ProjectJobSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.projectjobschedule.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Project Job Scheduling", description = "Project Job Scheduling service assigning jobs for execution.") @Path("schedules") @@ -48,7 +48,7 @@ public class ProjectJobSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(ProjectJobSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public ProjectJobSchedulingResource() { } @Inject - public ProjectJobSchedulingResource(SolverManager solverManager, + public ProjectJobSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -94,7 +94,7 @@ public String solve(ProjectJobSchedule problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/school-timetabling/src/main/java/org/acme/schooltimetabling/rest/TimetableResource.java b/java/school-timetabling/src/main/java/org/acme/schooltimetabling/rest/TimetableResource.java index a7660c3539..6a0148c52f 100644 --- a/java/school-timetabling/src/main/java/org/acme/schooltimetabling/rest/TimetableResource.java +++ b/java/school-timetabling/src/main/java/org/acme/schooltimetabling/rest/TimetableResource.java @@ -43,7 +43,7 @@ public class TimetableResource { private static final Logger LOGGER = LoggerFactory.getLogger(TimetableResource.class); - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; // TODO: Without any "time to live", the map may eventually grow out of memory. @@ -56,7 +56,7 @@ public TimetableResource() { } @Inject - public TimetableResource(SolverManager solverManager, + public TimetableResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; diff --git a/java/sports-league-scheduling/src/main/java/org/acme/sportsleagueschedule/rest/SportsLeagueSchedulingResource.java b/java/sports-league-scheduling/src/main/java/org/acme/sportsleagueschedule/rest/SportsLeagueSchedulingResource.java index 91a082fe3f..cab8b94bef 100644 --- a/java/sports-league-scheduling/src/main/java/org/acme/sportsleagueschedule/rest/SportsLeagueSchedulingResource.java +++ b/java/sports-league-scheduling/src/main/java/org/acme/sportsleagueschedule/rest/SportsLeagueSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.sportsleagueschedule.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Sports League Scheduling", description = "Sports League Scheduling service assigning rounds for league matches.") @Path("schedules") @@ -48,7 +48,7 @@ public class SportsLeagueSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(SportsLeagueSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public SportsLeagueSchedulingResource() { } @Inject - public SportsLeagueSchedulingResource(SolverManager solverManager, + public SportsLeagueSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -92,7 +92,7 @@ public String solve(LeagueSchedule problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/spring-boot-integration/src/main/java/org/acme/schooltimetabling/rest/TimetableController.java b/java/spring-boot-integration/src/main/java/org/acme/schooltimetabling/rest/TimetableController.java index a9cfeaa43d..74cf692f33 100644 --- a/java/spring-boot-integration/src/main/java/org/acme/schooltimetabling/rest/TimetableController.java +++ b/java/spring-boot-integration/src/main/java/org/acme/schooltimetabling/rest/TimetableController.java @@ -49,13 +49,13 @@ public class TimetableController { private static final Logger LOGGER = LoggerFactory.getLogger(TimetableController.class); - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; // TODO: Without any "time to live", the map may eventually grow out of memory. private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); - public TimetableController(SolverManager solverManager, + public TimetableController(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; diff --git a/java/task-assigning/src/main/java/org/acme/taskassigning/rest/TaskAssigningResource.java b/java/task-assigning/src/main/java/org/acme/taskassigning/rest/TaskAssigningResource.java index 0b19eaa301..4a8ab24fc9 100644 --- a/java/task-assigning/src/main/java/org/acme/taskassigning/rest/TaskAssigningResource.java +++ b/java/task-assigning/src/main/java/org/acme/taskassigning/rest/TaskAssigningResource.java @@ -1,7 +1,15 @@ package org.acme.taskassigning.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Flight Crew Scheduling", description = "Task assigning service assigning tasks to employees.") @Path("schedules") @@ -48,7 +48,7 @@ public class TaskAssigningResource { private static final Logger LOGGER = LoggerFactory.getLogger(TaskAssigningResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -58,7 +58,7 @@ public TaskAssigningResource() { } @Inject - public TaskAssigningResource(SolverManager solverManager, + public TaskAssigningResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -91,7 +91,7 @@ public String solve(TaskAssigningSolution problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/tournament-scheduling/src/main/java/org/acme/tournamentschedule/rest/TournamentSchedulingResource.java b/java/tournament-scheduling/src/main/java/org/acme/tournamentschedule/rest/TournamentSchedulingResource.java index 61f673a76a..3a24721104 100644 --- a/java/tournament-scheduling/src/main/java/org/acme/tournamentschedule/rest/TournamentSchedulingResource.java +++ b/java/tournament-scheduling/src/main/java/org/acme/tournamentschedule/rest/TournamentSchedulingResource.java @@ -1,7 +1,15 @@ package org.acme.tournamentschedule.rest; -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import ai.timefold.solver.core.api.score.HardSoftScore; +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; import ai.timefold.solver.core.api.solver.SolutionManager; import ai.timefold.solver.core.api.solver.SolverManager; @@ -32,14 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - @Tag(name = "Tournament Scheduling", description = "Tournament Scheduling service assigning teams to tournament matches.") @Path("schedules") @@ -48,7 +48,7 @@ public class TournamentSchedulingResource { private static final Logger LOGGER = LoggerFactory.getLogger(TournamentSchedulingResource.class); private static final int MAX_JOBS_CACHE_SIZE = 2; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; private final ConcurrentMap jobIdToJob = new ConcurrentHashMap<>(); @@ -59,7 +59,7 @@ public TournamentSchedulingResource() { } @Inject - public TournamentSchedulingResource(SolverManager solverManager, + public TournamentSchedulingResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; @@ -92,7 +92,7 @@ public String solve(TournamentSchedule problem) { .withProblemFinder(id -> jobIdToJob.get(jobId).schedule) .withBestSolutionEventConsumer(event -> jobIdToJob.put(jobId, Job.ofSchedule(event.solution()))) .withExceptionHandler((id, exception) -> { - jobIdToJob.put(id, Job.ofException(exception)); + jobIdToJob.put((String) id, Job.ofException(exception)); LOGGER.error("Failed solving jobId ({}).", id, exception); }) .run(); diff --git a/java/vehicle-routing/src/main/java/org/acme/vehiclerouting/rest/VehicleRoutePlanResource.java b/java/vehicle-routing/src/main/java/org/acme/vehiclerouting/rest/VehicleRoutePlanResource.java index 74630ec14d..54ba0864b9 100644 --- a/java/vehicle-routing/src/main/java/org/acme/vehiclerouting/rest/VehicleRoutePlanResource.java +++ b/java/vehicle-routing/src/main/java/org/acme/vehiclerouting/rest/VehicleRoutePlanResource.java @@ -52,7 +52,7 @@ public class VehicleRoutePlanResource { private static final Logger LOGGER = LoggerFactory.getLogger(VehicleRoutePlanResource.class); private static final int MAX_RECOMMENDED_ASSIGNMENT_LIST_SIZE = 5; - private final SolverManager solverManager; + private final SolverManager solverManager; private final SolutionManager solutionManager; @@ -66,7 +66,7 @@ public VehicleRoutePlanResource() { } @Inject - public VehicleRoutePlanResource(SolverManager solverManager, + public VehicleRoutePlanResource(SolverManager solverManager, SolutionManager solutionManager) { this.solverManager = solverManager; this.solutionManager = solutionManager; diff --git a/kotlin/school-timetabling/src/main/kotlin/org/acme/kotlin/schooltimetabling/rest/TimetableResource.kt b/kotlin/school-timetabling/src/main/kotlin/org/acme/kotlin/schooltimetabling/rest/TimetableResource.kt index bf2a36e14f..e9d6d53510 100644 --- a/kotlin/school-timetabling/src/main/kotlin/org/acme/kotlin/schooltimetabling/rest/TimetableResource.kt +++ b/kotlin/school-timetabling/src/main/kotlin/org/acme/kotlin/schooltimetabling/rest/TimetableResource.kt @@ -1,7 +1,7 @@ package org.acme.kotlin.schooltimetabling.rest -import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis import ai.timefold.solver.core.api.score.HardSoftScore +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy import ai.timefold.solver.core.api.solver.SolutionManager import ai.timefold.solver.core.api.solver.SolverManager @@ -43,7 +43,7 @@ class TimetableResource { private val LOGGER: Logger = LoggerFactory.getLogger(TimetableResource::class.java) - private final var solverManager: SolverManager? + private final var solverManager: SolverManager? private final var solutionManager: SolutionManager? @@ -58,7 +58,7 @@ class TimetableResource { @Inject constructor( - solverManager: SolverManager, solutionManager: SolutionManager + solverManager: SolverManager, solutionManager: SolutionManager ) { this.solverManager = solverManager this.solutionManager = solutionManager @@ -99,13 +99,13 @@ class TimetableResource { jobIdToJob[jobId] = Job.ofTimetable(problem) solverManager!!.solveBuilder() .withProblemId(jobId) - .withProblemFinder(Function { _: String? -> - jobIdToJob[jobId]!!.timetable + .withProblemFinder(Function { _: Any -> + jobIdToJob[jobId]!!.timetable!! }) .withBestSolutionEventConsumer { event: NewBestSolutionEvent -> jobIdToJob[jobId] = Job.ofTimetable(event.solution()) } - .withExceptionHandler(BiConsumer { _: String?, exception: Throwable? -> + .withExceptionHandler(BiConsumer { _: Any?, exception: Throwable? -> jobIdToJob[jobId] = Job.ofException(exception) LOGGER.error("Failed solving jobId ({}).", jobId, exception) }) From 87c6a9dd980cd7ed25a3989aeb7b02c5ccf7f271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Petrovick=C3=BD?= Date: Thu, 19 Feb 2026 13:59:37 +0100 Subject: [PATCH 2/2] refactor: validate constraint name --- .../acme/taskassigning/domain/Employee.java | 4 ++-- .../org/acme/taskassigning/domain/Task.java | 20 +++++++++---------- .../acme/taskassigning/domain/TaskType.java | 6 +++--- .../TaskAssigningConstraintProvider.java | 2 +- .../TaskAssigningConstraintProviderTest.java | 12 +++++------ 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Employee.java b/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Employee.java index b89e05dc74..38ac1de636 100644 --- a/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Employee.java +++ b/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Employee.java @@ -102,8 +102,8 @@ public Affinity getAffinity(Customer customer) { } @JsonIgnore - public Integer getEndTime() { - return tasks.isEmpty() ? 0 : tasks.get(tasks.size() - 1).getEndTime(); + public long getEndTime() { + return tasks.isEmpty() ? 0L : tasks.get(tasks.size() - 1).getEndTime(); } @Override diff --git a/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Task.java b/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Task.java index 42dadcc90e..5eb355968d 100644 --- a/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Task.java +++ b/java/task-assigning/src/main/java/org/acme/taskassigning/domain/Task.java @@ -20,7 +20,7 @@ public class Task { private TaskType taskType; private int indexInTaskType; private Customer customer; - private int minStartTime; + private long minStartTime; private Priority priority; // Shadow variables @@ -32,7 +32,7 @@ public class Task { private Task previousTask; // Not ignored, used in the UI. @ShadowVariable(supplierName = "startTimeSupplier") - private Integer startTime; // In minutes + private Long startTime; // In minutes public Task() { } @@ -88,11 +88,11 @@ public void setCustomer(Customer customer) { this.customer = customer; } - public int getMinStartTime() { + public long getMinStartTime() { return minStartTime; } - public void setMinStartTime(int minStartTime) { + public void setMinStartTime(long minStartTime) { this.minStartTime = minStartTime; } @@ -120,11 +120,11 @@ public void setPreviousTask(Task previousTask) { this.previousTask = previousTask; } - public Integer getStartTime() { + public Long getStartTime() { return startTime; } - public void setStartTime(Integer startTime) { + public void setStartTime(Long startTime) { this.startTime = startTime; } @@ -134,11 +134,11 @@ public void setStartTime(Integer startTime) { @SuppressWarnings("unused") @ShadowSources({"employee", "previousTask.startTime"}) - public Integer startTimeSupplier() { + public Long startTimeSupplier() { if (employee == null) { return null; } else if (previousTask == null) { - return minStartTime; + return (long) minStartTime; } else { var previousEndTime = previousTask.getEndTime(); return Math.max(previousEndTime, minStartTime); @@ -160,7 +160,7 @@ public int getMissingSkillCount() { } @JsonIgnore - public int getDuration() { + public long getDuration() { Affinity affinity = getAffinity(); return taskType.getBaseDuration() * affinity.getDurationMultiplier(); } @@ -171,7 +171,7 @@ public Affinity getAffinity() { } @JsonIgnore - public Integer getEndTime() { + public Long getEndTime() { if (startTime == null) { return null; } diff --git a/java/task-assigning/src/main/java/org/acme/taskassigning/domain/TaskType.java b/java/task-assigning/src/main/java/org/acme/taskassigning/domain/TaskType.java index 304cf6886f..da875e0c60 100644 --- a/java/task-assigning/src/main/java/org/acme/taskassigning/domain/TaskType.java +++ b/java/task-assigning/src/main/java/org/acme/taskassigning/domain/TaskType.java @@ -11,7 +11,7 @@ public class TaskType { private String code; private String title; - private int baseDuration; // In minutes + private long baseDuration; // In minutes private List requiredSkills; public TaskType() { @@ -47,11 +47,11 @@ public void setTitle(String title) { this.title = title; } - public int getBaseDuration() { + public long getBaseDuration() { return baseDuration; } - public void setBaseDuration(int baseDuration) { + public void setBaseDuration(long baseDuration) { this.baseDuration = baseDuration; } diff --git a/java/task-assigning/src/main/java/org/acme/taskassigning/solver/TaskAssigningConstraintProvider.java b/java/task-assigning/src/main/java/org/acme/taskassigning/solver/TaskAssigningConstraintProvider.java index 7316cb11ea..6e251da2db 100644 --- a/java/task-assigning/src/main/java/org/acme/taskassigning/solver/TaskAssigningConstraintProvider.java +++ b/java/task-assigning/src/main/java/org/acme/taskassigning/solver/TaskAssigningConstraintProvider.java @@ -52,7 +52,7 @@ protected Constraint minimizeMakespan(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Employee.class) .penalize(BendableScore.ofSoft(BENDABLE_SCORE_HARD_LEVELS_SIZE, BENDABLE_SCORE_SOFT_LEVELS_SIZE, 1, 1), employee -> employee.getEndTime() * employee.getEndTime()) - .asConstraint("Minimize makespan, latest ending employee first"); + .asConstraint("Minimize makespan - latest ending employee first"); } protected Constraint criticalPriorityTaskEndTime(ConstraintFactory constraintFactory) { diff --git a/java/task-assigning/src/test/java/org/acme/taskassigning/solver/TaskAssigningConstraintProviderTest.java b/java/task-assigning/src/test/java/org/acme/taskassigning/solver/TaskAssigningConstraintProviderTest.java index a1a01f93ac..d06c0d32b1 100644 --- a/java/task-assigning/src/test/java/org/acme/taskassigning/solver/TaskAssigningConstraintProviderTest.java +++ b/java/task-assigning/src/test/java/org/acme/taskassigning/solver/TaskAssigningConstraintProviderTest.java @@ -70,7 +70,7 @@ void criticalPriorityTaskEndTime() { // Task 1 TaskType type1 = new TaskType("1", "1", 10); Task task1 = new Task("1", type1, 1, customer, employee, 1, Priority.CRITICAL); - task1.setStartTime(1); + task1.setStartTime(1L); // Task 2 TaskType type2 = new TaskType("1", "1", 20); Task task2 = new Task("2", type2, 1, customer, employee, 2, Priority.MINOR); @@ -90,15 +90,15 @@ void minimizeMakespan() { // Task 1 TaskType type1 = new TaskType("1", "1", 10); Task task1 = new Task("1", type1, 1, customer, employee1, 1, Priority.CRITICAL); - task1.setStartTime(1); + task1.setStartTime(1L); // Task 2 TaskType type2 = new TaskType("2", "1", 20); Task task2 = new Task("2", type2, 1, customer, employee1, 2, Priority.MINOR); - task2.setStartTime(2); + task2.setStartTime(2L); // Task 3 TaskType invalidType2 = new TaskType("3", "3", 1); Task task3 = new Task("3", invalidType2, 1, customer, employee2, 1, Priority.CRITICAL); - task3.setStartTime(3); + task3.setStartTime(3L); employee1.setTasks(List.of(task1, task2)); employee2.setTasks(List.of(task3)); @@ -116,7 +116,7 @@ void majorPriorityTaskEndTime() { // Task 1 TaskType type1 = new TaskType("1", "1", 10); Task task1 = new Task("1", type1, 1, customer, employee, 1, Priority.MAJOR); - task1.setStartTime(1); + task1.setStartTime(1L); // Task 2 TaskType type2 = new TaskType("1", "1", 20); Task task2 = new Task("2", type2, 1, customer, employee, 2, Priority.MINOR); @@ -134,7 +134,7 @@ void minorPriorityTaskEndTime() { // Task 1 TaskType type1 = new TaskType("1", "1", 10); Task task1 = new Task("1", type1, 1, customer, employee, 1, Priority.MINOR); - task1.setStartTime(1); + task1.setStartTime(1L); // Task 2 TaskType type2 = new TaskType("1", "1", 20); Task task2 = new Task("2", type2, 1, customer, employee, 2, Priority.MAJOR);