From 3da9b43ff60629861e1924634ac772244bd80e07 Mon Sep 17 00:00:00 2001 From: toffe Date: Sat, 20 Sep 2025 18:51:00 +0200 Subject: [PATCH] init --- README.MD | 154 ++++++ chat.json | 41 ++ claude.json | 162 ++++++ employee-scheduling-screenshot.png | Bin 0 -> 107543 bytes gemini.json | 60 +++ gpt.json | 54 ++ pom.xml | 245 +++++++++ sample.json | 1 + solution.json | 1 + .../employeescheduling/domain/Employee.java | 91 ++++ .../domain/EmployeeSchedule.java | 72 +++ .../acme/employeescheduling/domain/Shift.java | 133 +++++ .../rest/DemoDataGenerator.java | 240 +++++++++ .../rest/EmployeeScheduleDemoResource.java | 51 ++ .../rest/EmployeeScheduleResource.java | 201 +++++++ .../EmployeeScheduleSolverException.java | 30 ++ ...EmployeeScheduleSolverExceptionMapper.java | 19 + .../rest/exception/ErrorInfo.java | 4 + .../EmployeeSchedulingConstraintProvider.java | 123 +++++ src/main/resources/META-INF/resources/app.js | 496 ++++++++++++++++++ .../resources/META-INF/resources/index.html | 161 ++++++ src/main/resources/application.properties | 43 ++ target/build-metrics.json | 1 + target/classes/META-INF/resources/app.js | 496 ++++++++++++++++++ target/classes/META-INF/resources/index.html | 161 ++++++ target/classes/application.properties | 43 ++ .../employeescheduling/domain/Employee.class | Bin 0 -> 2989 bytes .../domain/EmployeeSchedule.class | Bin 0 -> 3117 bytes .../employeescheduling/domain/Shift.class | Bin 0 -> 5338 bytes .../DemoDataGenerator$CountDistribution.class | Bin 0 -> 1800 bytes .../rest/DemoDataGenerator$DemoData.class | Bin 0 -> 3166 bytes ...DemoDataGenerator$DemoDataParameters.class | Bin 0 -> 4019 bytes .../rest/DemoDataGenerator.class | Bin 0 -> 12097 bytes .../rest/EmployeeScheduleDemoResource.class | Bin 0 -> 2774 bytes .../rest/EmployeeScheduleResource$Job.class | Bin 0 -> 2386 bytes .../rest/EmployeeScheduleResource.class | Bin 0 -> 11485 bytes .../EmployeeScheduleSolverException.class | Bin 0 -> 1287 bytes ...mployeeScheduleSolverExceptionMapper.class | Bin 0 -> 2045 bytes .../rest/exception/ErrorInfo.class | Bin 0 -> 1652 bytes ...EmployeeSchedulingConstraintProvider.class | Bin 0 -> 11101 bytes target/employee-scheduling-dev.jar | Bin 0 -> 5389 bytes .../compile/default-compile/createdFiles.lst | 14 + .../compile/default-compile/inputFiles.lst | 10 + .../compile/null/createdFiles.lst | 0 .../compile/null/inputFiles.lst | 10 + .../testCompile/null/createdFiles.lst | 4 + .../testCompile/null/inputFiles.lst | 4 + target/quarkus/bootstrap/dev-app-model.dat | Bin 0 -> 104224 bytes .../rest/EmployeeScheduleResourceTest.class | Bin 0 -> 5746 bytes .../EmployeeSchedulingEnvironmentTest.class | Bin 0 -> 4232 bytes .../rest/EmployeeSchedulingResourceIT.class | Bin 0 -> 4809 bytes ...oyeeSchedulingConstraintProviderTest.class | Bin 0 -> 8144 bytes vi | 162 ++++++ 53 files changed, 3287 insertions(+) create mode 100644 README.MD create mode 100644 chat.json create mode 100644 claude.json create mode 100644 employee-scheduling-screenshot.png create mode 100644 gemini.json create mode 100644 gpt.json create mode 100644 pom.xml create mode 100644 sample.json create mode 100644 solution.json create mode 100644 src/main/java/org/acme/employeescheduling/domain/Employee.java create mode 100644 src/main/java/org/acme/employeescheduling/domain/EmployeeSchedule.java create mode 100644 src/main/java/org/acme/employeescheduling/domain/Shift.java create mode 100644 src/main/java/org/acme/employeescheduling/rest/DemoDataGenerator.java create mode 100644 src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.java create mode 100644 src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java create mode 100644 src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.java create mode 100644 src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.java create mode 100644 src/main/java/org/acme/employeescheduling/rest/exception/ErrorInfo.java create mode 100644 src/main/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.java create mode 100644 src/main/resources/META-INF/resources/app.js create mode 100644 src/main/resources/META-INF/resources/index.html create mode 100644 src/main/resources/application.properties create mode 100644 target/build-metrics.json create mode 100644 target/classes/META-INF/resources/app.js create mode 100644 target/classes/META-INF/resources/index.html create mode 100644 target/classes/application.properties create mode 100644 target/classes/org/acme/employeescheduling/domain/Employee.class create mode 100644 target/classes/org/acme/employeescheduling/domain/EmployeeSchedule.class create mode 100644 target/classes/org/acme/employeescheduling/domain/Shift.class create mode 100644 target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$CountDistribution.class create mode 100644 target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$DemoData.class create mode 100644 target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$DemoDataParameters.class create mode 100644 target/classes/org/acme/employeescheduling/rest/DemoDataGenerator.class create mode 100644 target/classes/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.class create mode 100644 target/classes/org/acme/employeescheduling/rest/EmployeeScheduleResource$Job.class create mode 100644 target/classes/org/acme/employeescheduling/rest/EmployeeScheduleResource.class create mode 100644 target/classes/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.class create mode 100644 target/classes/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.class create mode 100644 target/classes/org/acme/employeescheduling/rest/exception/ErrorInfo.class create mode 100644 target/classes/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.class create mode 100644 target/employee-scheduling-dev.jar create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/compile/null/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/compile/null/inputFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/testCompile/null/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/testCompile/null/inputFiles.lst create mode 100644 target/quarkus/bootstrap/dev-app-model.dat create mode 100644 target/test-classes/org/acme/employeescheduling/rest/EmployeeScheduleResourceTest.class create mode 100644 target/test-classes/org/acme/employeescheduling/rest/EmployeeSchedulingEnvironmentTest.class create mode 100644 target/test-classes/org/acme/employeescheduling/rest/EmployeeSchedulingResourceIT.class create mode 100644 target/test-classes/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProviderTest.class create mode 100644 vi diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..4137008 --- /dev/null +++ b/README.MD @@ -0,0 +1,154 @@ +# Employee Scheduling (Java, Quarkus, Maven) + +Schedule shifts to employees, accounting for employee availability and shift skill requirements. + +![Employee Scheduling Screenshot](./employee-scheduling-screenshot.png) + +- [Run the application](#run-the-application) +- [Run the application with Timefold Solver Enterprise Edition](#run-the-application-with-timefold-solver-enterprise-edition) +- [Run the packaged application](#run-the-packaged-application) +- [Run the application in a container](#run-the-application-in-a-container) +- [Run it native](#run-it-native) + +> [!TIP] +> [Check out our off-the-shelf model for Employee Shift Scheduling](https://app.timefold.ai/models/employee-scheduling/v1). This model supports many additional constraints such as skills, pairing employees, fairness and more. + +## Prerequisites + +1. Install Java and Maven, for example with [Sdkman](https://sdkman.io): + + ```sh + $ sdk install java + $ sdk install maven + ``` + +## Run the application + +1. Git clone the timefold-quickstarts repo and navigate to this directory: + + ```sh + $ git clone https://github.com/TimefoldAI/timefold-quickstarts.git + ... + $ cd timefold-quickstarts/java/employee-scheduling + ``` + +2. Start the application with Maven: + + ```sh + $ mvn quarkus:dev + ``` + +3. Visit [http://localhost:8080](http://localhost:8080) in your browser. + +4. Click on the **Solve** button. + +Then try _live coding_: + +- Make some changes in the source code. +- Refresh your browser (F5). + +Notice that those changes are immediately in effect. + +## Run the application with Timefold Solver Enterprise Edition + +For high-scalability use cases, switch to [Timefold Solver Enterprise Edition](https://docs.timefold.ai/timefold-solver/latest/enterprise-edition/enterprise-edition), our commercial offering. +[Contact Timefold](https://timefold.ai/contact) to obtain the credentials required to access our private Enterprise Maven repository. + +1. Create `.m2/settings.xml` in your home directory with the following content: + + ```xml + + ... + + + + timefold-solver-enterprise + my_username + my_password + + + ... + + ``` + + See [Settings Reference](https://maven.apache.org/settings.html) for more information on Maven settings. + +2. Start the application with Maven: + + ```sh + $ mvn clean quarkus:dev -Denterprise + ``` + +3. Visit [http://localhost:8080](http://localhost:8080) in your browser. + +4. Click on the **Solve** button. + +Then try _live coding_: + +- Make some changes in the source code. +- Refresh your browser (F5). + +Notice that those changes are immediately in effect. + +## Run the packaged application + +When you're done iterating in `quarkus:dev` mode, package the application to run as a conventional jar file. + +1. Compile it with Maven: + + ```sh + $ mvn package + ``` + +2. Run it: + + ```sh + $ java -jar ./target/quarkus-app/quarkus-run.jar + ``` + + > **Note** + > To run it on port 8081 instead, add `-Dquarkus.http.port=8081`. + +3. Visit [http://localhost:8080](http://localhost:8080) in your browser. + +4. Click on the **Solve** button. + +## Run the application in a container + +1. Build a container image: + + ```sh + $ mvn package -Dcontainer + ``` + +2. Run a container: + + ```sh + $ docker run -p 8080:8080 $USER/employee-scheduling:1.0-SNAPSHOT + ``` + +## Run it native + +To increase startup performance for serverless deployments, build the application as a native executable: + +1. [Install GraalVM and `gu` install the native-image tool](https://quarkus.io/guides/building-native-image#configuring-graalvm). + +2. Compile it natively. This takes a few minutes: + + ```sh + $ mvn package -Dnative -DskipTests + ``` + +3. Run the native executable: + + ```sh + $ ./target/*-runner + ``` + +4. Visit [http://localhost:8080](http://localhost:8080) in your browser. + +5. Click on the **Solve** button. + +## More information + +Visit [timefold.ai](https://timefold.ai). diff --git a/chat.json b/chat.json new file mode 100644 index 0000000..4ebbc99 --- /dev/null +++ b/chat.json @@ -0,0 +1,41 @@ +{ + "employees": [ + { + "name": "Employee1", + "skills": ["Skill1", "Skill2"], + "unavailableDates": ["2025-01-01", "2025-01-02"], + "undesiredDates": ["2025-01-03"], + "desiredDates": ["2025-01-04"] + }, + { + "name": "Employee2", + "skills": ["Skill2", "Skill3"], + "unavailableDates": ["2025-01-02"], + "undesiredDates": ["2025-01-05"], + "desiredDates": ["2025-01-06"] + } + ], + "shifts": [ + { + "id": "Shift1", + "start": "2025-01-01T08:00:00", + "end": "2025-01-01T16:00:00", + "location": "Location1", + "requiredSkill": "Skill1", + "employee": { + "name": "Employee1" + } + }, + { + "id": "Shift2", + "start": "2025-01-02T08:00:00", + "end": "2025-01-02T16:00:00", + "location": "Location2", + "requiredSkill": "Skill2", + "employee": { + "name": "Employee2" + } + } + ] +} + diff --git a/claude.json b/claude.json new file mode 100644 index 0000000..18e541f --- /dev/null +++ b/claude.json @@ -0,0 +1,162 @@ +{ + "employees": [ + { + "name": "Marie Dupont", + "skills": ["INFIRMIER", "PRELEVEMENT"], + "unavailableDates": ["2024-12-25", "2024-12-26"], + "undesiredDates": ["2024-12-24", "2024-12-31"], + "desiredDates": ["2024-12-20", "2024-12-21"] + }, + { + "name": "Pierre Martin", + "skills": ["MEDECIN", "SUPERVISION"], + "unavailableDates": ["2024-12-30"], + "undesiredDates": ["2024-12-29"], + "desiredDates": ["2024-12-22", "2024-12-23"] + }, + { + "name": "Sophie Bernard", + "skills": ["INFIRMIER", "ACCUEIL"], + "unavailableDates": [], + "undesiredDates": ["2024-12-25"], + "desiredDates": ["2024-12-24", "2024-12-28"] + }, + { + "name": "Jean Leroy", + "skills": ["PRELEVEMENT", "TRANSPORT"], + "unavailableDates": ["2024-12-24", "2024-12-25"], + "undesiredDates": [], + "desiredDates": ["2024-12-27", "2024-12-30"] + }, + { + "name": "Anne Moreau", + "skills": ["MEDECIN", "INFIRMIER"], + "unavailableDates": ["2024-12-26"], + "undesiredDates": ["2024-12-31"], + "desiredDates": ["2024-12-21", "2024-12-29"] + }, + { + "name": "Luc Petit", + "skills": ["ACCUEIL", "TRANSPORT"], + "unavailableDates": [], + "undesiredDates": ["2024-12-20"], + "desiredDates": ["2024-12-25", "2024-12-26"] + } + ], + "shifts": [ + { + "id": "shift_001", + "start": "2024-12-20T08:00:00", + "end": "2024-12-20T16:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "INFIRMIER", + "employee": null + }, + { + "id": "shift_002", + "start": "2024-12-20T14:00:00", + "end": "2024-12-20T22:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "PRELEVEMENT", + "employee": null + }, + { + "id": "shift_003", + "start": "2024-12-21T06:00:00", + "end": "2024-12-21T14:00:00", + "location": "Hôpital Purpan", + "requiredSkill": "MEDECIN", + "employee": null + }, + { + "id": "shift_004", + "start": "2024-12-21T08:00:00", + "end": "2024-12-21T12:00:00", + "location": "Centre de collecte - Colomiers", + "requiredSkill": "ACCUEIL", + "employee": null + }, + { + "id": "shift_005", + "start": "2024-12-22T09:00:00", + "end": "2024-12-22T17:00:00", + "location": "Centre de collecte - Blagnac", + "requiredSkill": "INFIRMIER", + "employee": null + }, + { + "id": "shift_006", + "start": "2024-12-22T13:00:00", + "end": "2024-12-22T18:00:00", + "location": "Transport mobile", + "requiredSkill": "TRANSPORT", + "employee": null + }, + { + "id": "shift_007", + "start": "2024-12-23T07:00:00", + "end": "2024-12-23T15:00:00", + "location": "Hôpital Rangueil", + "requiredSkill": "MEDECIN", + "employee": null + }, + { + "id": "shift_008", + "start": "2024-12-23T10:00:00", + "end": "2024-12-23T16:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "PRELEVEMENT", + "employee": null + }, + { + "id": "shift_009", + "start": "2024-12-24T08:00:00", + "end": "2024-12-24T14:00:00", + "location": "Centre de collecte - Colomiers", + "requiredSkill": "INFIRMIER", + "employee": null + }, + { + "id": "shift_010", + "start": "2024-12-27T09:00:00", + "end": "2024-12-27T17:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "SUPERVISION", + "employee": null + }, + { + "id": "shift_011", + "start": "2024-12-28T08:00:00", + "end": "2024-12-28T16:00:00", + "location": "Centre de collecte - Blagnac", + "requiredSkill": "ACCUEIL", + "employee": null + }, + { + "id": "shift_012", + "start": "2024-12-29T06:00:00", + "end": "2024-12-29T14:00:00", + "location": "Hôpital Purpan", + "requiredSkill": "MEDECIN", + "employee": null + }, + { + "id": "shift_013", + "start": "2024-12-30T10:00:00", + "end": "2024-12-30T18:00:00", + "location": "Transport mobile", + "requiredSkill": "TRANSPORT", + "employee": null + }, + { + "id": "shift_014", + "start": "2024-12-31T08:00:00", + "end": "2024-12-31T16:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "INFIRMIER", + "employee": null + } + ], + "score": null, + "solverStatus": null +} diff --git a/employee-scheduling-screenshot.png b/employee-scheduling-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..af99511d7288c38e086c723bc25dd526dd4560e7 GIT binary patch literal 107543 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 + + 4.0.0 + + org.acme + employee-scheduling + 1.0-SNAPSHOT + + + 17 + UTF-8 + + 3.26.2 + 1.26.0 + + 3.14.0 + 3.3.1 + 3.5.3 + + + + + + io.quarkus + quarkus-bom + ${version.io.quarkus} + pom + import + + + ai.timefold.solver + timefold-solver-bom + ${version.ai.timefold.solver} + pom + import + + + + + + + io.quarkus + quarkus-rest + + + io.quarkus + quarkus-rest-jackson + + + io.quarkus + quarkus-smallrye-openapi + + + ai.timefold.solver + timefold-solver-quarkus + + + ai.timefold.solver + timefold-solver-quarkus-jackson + + + + + io.quarkus + quarkus-web-dependency-locator + + + ai.timefold.solver + timefold-solver-webui + runtime + + + org.webjars + bootstrap + 5.2.3 + runtime + + + org.webjars + jquery + 3.6.4 + runtime + + + org.webjars + font-awesome + 5.15.1 + runtime + + + org.webjars.npm + js-joda + 1.11.0 + runtime + + + + + ai.timefold.solver + timefold-solver-test + test + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + org.awaitility + awaitility + test + + + org.assertj + assertj-core + 3.27.4 + test + + + + + + + maven-resources-plugin + ${version.resources.plugin} + + + maven-compiler-plugin + ${version.compiler.plugin} + + + io.quarkus + quarkus-maven-plugin + ${version.io.quarkus} + + + + build + + + + + + maven-surefire-plugin + ${version.surefire.plugin} + + + + + + + native + + + native + + + + + + maven-failsafe-plugin + ${version.surefire.plugin} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + + + + + + + + + true + + native + + + + container + + + container + + + + + io.quarkus + quarkus-container-image-jib + + + + true + + + + enterprise + + + enterprise + + + + + timefold-solver-enterprise + Timefold Solver Enterprise Edition + https://timefold.jfrog.io/artifactory/releases/ + + + + + + ai.timefold.solver.enterprise + timefold-solver-enterprise-bom + ${version.ai.timefold.solver} + pom + import + + + + + + ai.timefold.solver.enterprise + timefold-solver-enterprise-quarkus + + + + enterprise + + + + + diff --git a/sample.json b/sample.json new file mode 100644 index 0000000..107741e --- /dev/null +++ b/sample.json @@ -0,0 +1 @@ +{"employees":[{"name":"Elsa Green","skills":["Cardiology","Nurse"],"unavailableDates":["2025-09-30"],"undesiredDates":["2025-09-25"],"desiredDates":[]},{"name":"Elsa Li","skills":["Doctor","Anaesthetics"],"unavailableDates":[],"undesiredDates":["2025-09-22"],"desiredDates":["2025-09-29"]},{"name":"Elsa Watt","skills":["Anaesthetics","Nurse"],"unavailableDates":["2025-10-05"],"undesiredDates":[],"desiredDates":["2025-09-26"]},{"name":"Amy Smith","skills":["Anaesthetics","Nurse"],"unavailableDates":["2025-09-24","2025-10-03"],"undesiredDates":[],"desiredDates":["2025-09-23","2025-10-01"]},{"name":"Hugo King","skills":["Doctor","Cardiology"],"unavailableDates":[],"undesiredDates":[],"desiredDates":[]},{"name":"Amy King","skills":["Cardiology","Nurse"],"unavailableDates":["2025-09-25"],"undesiredDates":[],"desiredDates":[]},{"name":"Dan Poe","skills":["Cardiology","Anaesthetics","Nurse"],"unavailableDates":["2025-10-02"],"undesiredDates":["2025-09-28"],"desiredDates":[]},{"name":"Hugo Watt","skills":["Doctor","Cardiology"],"unavailableDates":[],"undesiredDates":["2025-10-01"],"desiredDates":[]},{"name":"Carl King","skills":["Cardiology","Nurse"],"unavailableDates":[],"undesiredDates":[],"desiredDates":[]},{"name":"Gus Watt","skills":["Anaesthetics","Nurse"],"unavailableDates":["2025-10-04"],"undesiredDates":[],"desiredDates":[]},{"name":"Jay Watt","skills":["Doctor","Cardiology"],"unavailableDates":[],"undesiredDates":["2025-09-28"],"desiredDates":["2025-10-05"]},{"name":"Elsa King","skills":["Doctor","Cardiology","Anaesthetics"],"unavailableDates":[],"undesiredDates":["2025-09-23","2025-10-05"],"desiredDates":[]},{"name":"Dan King","skills":["Cardiology","Nurse"],"unavailableDates":[],"undesiredDates":[],"desiredDates":["2025-09-30"]},{"name":"Carl Green","skills":["Cardiology","Nurse"],"unavailableDates":[],"undesiredDates":["2025-09-24"],"desiredDates":["2025-09-27"]},{"name":"Jay Poe","skills":["Doctor","Anaesthetics"],"unavailableDates":["2025-09-25"],"undesiredDates":["2025-09-27","2025-09-30"],"desiredDates":[]}],"shifts":[{"id":"0","start":"2025-09-22T06:00:00","end":"2025-09-22T14:00:00","location":"Ambulatory care","requiredSkill":"Doctor","employee":null},{"id":"1","start":"2025-09-22T14:00:00","end":"2025-09-22T22:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"2","start":"2025-09-22T14:00:00","end":"2025-09-22T22:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"3","start":"2025-09-22T06:00:00","end":"2025-09-22T14:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"4","start":"2025-09-22T14:00:00","end":"2025-09-22T22:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"5","start":"2025-09-22T22:00:00","end":"2025-09-23T06:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"6","start":"2025-09-22T06:00:00","end":"2025-09-22T14:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"7","start":"2025-09-22T09:00:00","end":"2025-09-22T17:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"8","start":"2025-09-22T14:00:00","end":"2025-09-22T22:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"9","start":"2025-09-22T22:00:00","end":"2025-09-23T06:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"10","start":"2025-09-23T06:00:00","end":"2025-09-23T14:00:00","location":"Ambulatory care","requiredSkill":"Doctor","employee":null},{"id":"11","start":"2025-09-23T14:00:00","end":"2025-09-23T22:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"12","start":"2025-09-23T06:00:00","end":"2025-09-23T14:00:00","location":"Critical care","requiredSkill":"Nurse","employee":null},{"id":"13","start":"2025-09-23T14:00:00","end":"2025-09-23T22:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"14","start":"2025-09-23T22:00:00","end":"2025-09-24T06:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"15","start":"2025-09-23T06:00:00","end":"2025-09-23T14:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"16","start":"2025-09-23T09:00:00","end":"2025-09-23T17:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"17","start":"2025-09-23T14:00:00","end":"2025-09-23T22:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"18","start":"2025-09-23T22:00:00","end":"2025-09-24T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"19","start":"2025-09-24T06:00:00","end":"2025-09-24T14:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"20","start":"2025-09-24T14:00:00","end":"2025-09-24T22:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"21","start":"2025-09-24T06:00:00","end":"2025-09-24T14:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"22","start":"2025-09-24T14:00:00","end":"2025-09-24T22:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"23","start":"2025-09-24T22:00:00","end":"2025-09-25T06:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"24","start":"2025-09-24T06:00:00","end":"2025-09-24T14:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"25","start":"2025-09-24T09:00:00","end":"2025-09-24T17:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"26","start":"2025-09-24T14:00:00","end":"2025-09-24T22:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"27","start":"2025-09-24T22:00:00","end":"2025-09-25T06:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"28","start":"2025-09-25T06:00:00","end":"2025-09-25T14:00:00","location":"Ambulatory care","requiredSkill":"Doctor","employee":null},{"id":"29","start":"2025-09-25T14:00:00","end":"2025-09-25T22:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"30","start":"2025-09-25T06:00:00","end":"2025-09-25T14:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"31","start":"2025-09-25T14:00:00","end":"2025-09-25T22:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"32","start":"2025-09-25T22:00:00","end":"2025-09-26T06:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"33","start":"2025-09-25T06:00:00","end":"2025-09-25T14:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"34","start":"2025-09-25T09:00:00","end":"2025-09-25T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"35","start":"2025-09-25T09:00:00","end":"2025-09-25T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"36","start":"2025-09-25T14:00:00","end":"2025-09-25T22:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"37","start":"2025-09-25T22:00:00","end":"2025-09-26T06:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"38","start":"2025-09-26T06:00:00","end":"2025-09-26T14:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"39","start":"2025-09-26T14:00:00","end":"2025-09-26T22:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"40","start":"2025-09-26T06:00:00","end":"2025-09-26T14:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"41","start":"2025-09-26T06:00:00","end":"2025-09-26T14:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"42","start":"2025-09-26T14:00:00","end":"2025-09-26T22:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"43","start":"2025-09-26T22:00:00","end":"2025-09-27T06:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"44","start":"2025-09-26T06:00:00","end":"2025-09-26T14:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"45","start":"2025-09-26T09:00:00","end":"2025-09-26T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"46","start":"2025-09-26T14:00:00","end":"2025-09-26T22:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"47","start":"2025-09-26T22:00:00","end":"2025-09-27T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"48","start":"2025-09-27T06:00:00","end":"2025-09-27T14:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"49","start":"2025-09-27T14:00:00","end":"2025-09-27T22:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"50","start":"2025-09-27T06:00:00","end":"2025-09-27T14:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"51","start":"2025-09-27T14:00:00","end":"2025-09-27T22:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"52","start":"2025-09-27T22:00:00","end":"2025-09-28T06:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"53","start":"2025-09-27T06:00:00","end":"2025-09-27T14:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"54","start":"2025-09-27T09:00:00","end":"2025-09-27T17:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"55","start":"2025-09-27T14:00:00","end":"2025-09-27T22:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"56","start":"2025-09-27T22:00:00","end":"2025-09-28T06:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"57","start":"2025-09-28T06:00:00","end":"2025-09-28T14:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"58","start":"2025-09-28T14:00:00","end":"2025-09-28T22:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"59","start":"2025-09-28T06:00:00","end":"2025-09-28T14:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"60","start":"2025-09-28T06:00:00","end":"2025-09-28T14:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"61","start":"2025-09-28T14:00:00","end":"2025-09-28T22:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"62","start":"2025-09-28T22:00:00","end":"2025-09-29T06:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"63","start":"2025-09-28T06:00:00","end":"2025-09-28T14:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"64","start":"2025-09-28T09:00:00","end":"2025-09-28T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"65","start":"2025-09-28T14:00:00","end":"2025-09-28T22:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"66","start":"2025-09-28T22:00:00","end":"2025-09-29T06:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"67","start":"2025-09-29T06:00:00","end":"2025-09-29T14:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"68","start":"2025-09-29T14:00:00","end":"2025-09-29T22:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"69","start":"2025-09-29T06:00:00","end":"2025-09-29T14:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"70","start":"2025-09-29T14:00:00","end":"2025-09-29T22:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"71","start":"2025-09-29T22:00:00","end":"2025-09-30T06:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"72","start":"2025-09-29T06:00:00","end":"2025-09-29T14:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"73","start":"2025-09-29T09:00:00","end":"2025-09-29T17:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"74","start":"2025-09-29T14:00:00","end":"2025-09-29T22:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"75","start":"2025-09-29T22:00:00","end":"2025-09-30T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"76","start":"2025-09-30T06:00:00","end":"2025-09-30T14:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"77","start":"2025-09-30T14:00:00","end":"2025-09-30T22:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"78","start":"2025-09-30T06:00:00","end":"2025-09-30T14:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"79","start":"2025-09-30T14:00:00","end":"2025-09-30T22:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"80","start":"2025-09-30T22:00:00","end":"2025-10-01T06:00:00","location":"Critical care","requiredSkill":"Nurse","employee":null},{"id":"81","start":"2025-09-30T06:00:00","end":"2025-09-30T14:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"82","start":"2025-09-30T09:00:00","end":"2025-09-30T17:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"83","start":"2025-09-30T14:00:00","end":"2025-09-30T22:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"84","start":"2025-09-30T22:00:00","end":"2025-10-01T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"85","start":"2025-10-01T06:00:00","end":"2025-10-01T14:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"86","start":"2025-10-01T14:00:00","end":"2025-10-01T22:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"87","start":"2025-10-01T06:00:00","end":"2025-10-01T14:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"88","start":"2025-10-01T06:00:00","end":"2025-10-01T14:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"89","start":"2025-10-01T14:00:00","end":"2025-10-01T22:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"90","start":"2025-10-01T22:00:00","end":"2025-10-02T06:00:00","location":"Critical care","requiredSkill":"Doctor","employee":null},{"id":"91","start":"2025-10-01T06:00:00","end":"2025-10-01T14:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"92","start":"2025-10-01T09:00:00","end":"2025-10-01T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"93","start":"2025-10-01T14:00:00","end":"2025-10-01T22:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"94","start":"2025-10-01T22:00:00","end":"2025-10-02T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"95","start":"2025-10-02T06:00:00","end":"2025-10-02T14:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"96","start":"2025-10-02T14:00:00","end":"2025-10-02T22:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"97","start":"2025-10-02T06:00:00","end":"2025-10-02T14:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"98","start":"2025-10-02T14:00:00","end":"2025-10-02T22:00:00","location":"Critical care","requiredSkill":"Nurse","employee":null},{"id":"99","start":"2025-10-02T22:00:00","end":"2025-10-03T06:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"100","start":"2025-10-02T06:00:00","end":"2025-10-02T14:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"101","start":"2025-10-02T09:00:00","end":"2025-10-02T17:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"102","start":"2025-10-02T14:00:00","end":"2025-10-02T22:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"103","start":"2025-10-02T22:00:00","end":"2025-10-03T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"104","start":"2025-10-03T06:00:00","end":"2025-10-03T14:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"105","start":"2025-10-03T14:00:00","end":"2025-10-03T22:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"106","start":"2025-10-03T06:00:00","end":"2025-10-03T14:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"107","start":"2025-10-03T14:00:00","end":"2025-10-03T22:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"108","start":"2025-10-03T14:00:00","end":"2025-10-03T22:00:00","location":"Critical care","requiredSkill":"Nurse","employee":null},{"id":"109","start":"2025-10-03T22:00:00","end":"2025-10-04T06:00:00","location":"Critical care","requiredSkill":"Nurse","employee":null},{"id":"110","start":"2025-10-03T06:00:00","end":"2025-10-03T14:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"111","start":"2025-10-03T09:00:00","end":"2025-10-03T17:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"112","start":"2025-10-03T14:00:00","end":"2025-10-03T22:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"113","start":"2025-10-03T22:00:00","end":"2025-10-04T06:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"114","start":"2025-10-04T06:00:00","end":"2025-10-04T14:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"115","start":"2025-10-04T14:00:00","end":"2025-10-04T22:00:00","location":"Ambulatory care","requiredSkill":"Cardiology","employee":null},{"id":"116","start":"2025-10-04T06:00:00","end":"2025-10-04T14:00:00","location":"Critical care","requiredSkill":"Nurse","employee":null},{"id":"117","start":"2025-10-04T14:00:00","end":"2025-10-04T22:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"118","start":"2025-10-04T22:00:00","end":"2025-10-05T06:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"119","start":"2025-10-04T06:00:00","end":"2025-10-04T14:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"120","start":"2025-10-04T09:00:00","end":"2025-10-04T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"121","start":"2025-10-04T14:00:00","end":"2025-10-04T22:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"122","start":"2025-10-04T22:00:00","end":"2025-10-05T06:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null},{"id":"123","start":"2025-10-05T06:00:00","end":"2025-10-05T14:00:00","location":"Ambulatory care","requiredSkill":"Anaesthetics","employee":null},{"id":"124","start":"2025-10-05T14:00:00","end":"2025-10-05T22:00:00","location":"Ambulatory care","requiredSkill":"Nurse","employee":null},{"id":"125","start":"2025-10-05T14:00:00","end":"2025-10-05T22:00:00","location":"Ambulatory care","requiredSkill":"Doctor","employee":null},{"id":"126","start":"2025-10-05T06:00:00","end":"2025-10-05T14:00:00","location":"Critical care","requiredSkill":"Anaesthetics","employee":null},{"id":"127","start":"2025-10-05T14:00:00","end":"2025-10-05T22:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"128","start":"2025-10-05T22:00:00","end":"2025-10-06T06:00:00","location":"Critical care","requiredSkill":"Cardiology","employee":null},{"id":"129","start":"2025-10-05T06:00:00","end":"2025-10-05T14:00:00","location":"Pediatric care","requiredSkill":"Cardiology","employee":null},{"id":"130","start":"2025-10-05T09:00:00","end":"2025-10-05T17:00:00","location":"Pediatric care","requiredSkill":"Nurse","employee":null},{"id":"131","start":"2025-10-05T14:00:00","end":"2025-10-05T22:00:00","location":"Pediatric care","requiredSkill":"Doctor","employee":null},{"id":"132","start":"2025-10-05T22:00:00","end":"2025-10-06T06:00:00","location":"Pediatric care","requiredSkill":"Anaesthetics","employee":null}],"score":null,"solverStatus":null} \ No newline at end of file diff --git a/solution.json b/solution.json new file mode 100644 index 0000000..bf2dd3b --- /dev/null +++ b/solution.json @@ -0,0 +1 @@ +{"employees":[{"name":"Marie Dupont","skills":["PRELEVEMENT","INFIRMIER"],"unavailableDates":["2024-12-26","2024-12-25"],"undesiredDates":["2024-12-31","2024-12-24"],"desiredDates":["2024-12-21","2024-12-20"]},{"name":"Pierre Martin","skills":["MEDECIN","SUPERVISION"],"unavailableDates":["2024-12-30"],"undesiredDates":["2024-12-29"],"desiredDates":["2024-12-23","2024-12-22"]},{"name":"Sophie Bernard","skills":["ACCUEIL","INFIRMIER"],"unavailableDates":[],"undesiredDates":["2024-12-25"],"desiredDates":["2024-12-28","2024-12-24"]},{"name":"Jean Leroy","skills":["PRELEVEMENT","TRANSPORT"],"unavailableDates":["2024-12-25","2024-12-24"],"undesiredDates":[],"desiredDates":["2024-12-30","2024-12-27"]},{"name":"Anne Moreau","skills":["MEDECIN","INFIRMIER"],"unavailableDates":["2024-12-26"],"undesiredDates":["2024-12-31"],"desiredDates":["2024-12-29","2024-12-21"]},{"name":"Luc Petit","skills":["TRANSPORT","ACCUEIL"],"unavailableDates":[],"undesiredDates":["2024-12-20"],"desiredDates":["2024-12-26","2024-12-25"]}],"shifts":[{"id":"shift_001","start":"2024-12-20T08:00:00","end":"2024-12-20T16:00:00","location":"Centre de collecte - Toulouse","requiredSkill":"INFIRMIER","employee":{"name":"Marie Dupont","skills":["PRELEVEMENT","INFIRMIER"],"unavailableDates":["2024-12-26","2024-12-25"],"undesiredDates":["2024-12-31","2024-12-24"],"desiredDates":["2024-12-21","2024-12-20"]}},{"id":"shift_002","start":"2024-12-20T14:00:00","end":"2024-12-20T22:00:00","location":"Centre de collecte - Toulouse","requiredSkill":"PRELEVEMENT","employee":{"name":"Jean Leroy","skills":["PRELEVEMENT","TRANSPORT"],"unavailableDates":["2024-12-25","2024-12-24"],"undesiredDates":[],"desiredDates":["2024-12-30","2024-12-27"]}},{"id":"shift_003","start":"2024-12-21T06:00:00","end":"2024-12-21T14:00:00","location":"Hôpital Purpan","requiredSkill":"MEDECIN","employee":{"name":"Anne Moreau","skills":["MEDECIN","INFIRMIER"],"unavailableDates":["2024-12-26"],"undesiredDates":["2024-12-31"],"desiredDates":["2024-12-29","2024-12-21"]}},{"id":"shift_004","start":"2024-12-21T08:00:00","end":"2024-12-21T12:00:00","location":"Centre de collecte - Colomiers","requiredSkill":"ACCUEIL","employee":{"name":"Luc Petit","skills":["TRANSPORT","ACCUEIL"],"unavailableDates":[],"undesiredDates":["2024-12-20"],"desiredDates":["2024-12-26","2024-12-25"]}},{"id":"shift_005","start":"2024-12-22T09:00:00","end":"2024-12-22T17:00:00","location":"Centre de collecte - Blagnac","requiredSkill":"INFIRMIER","employee":{"name":"Marie Dupont","skills":["PRELEVEMENT","INFIRMIER"],"unavailableDates":["2024-12-26","2024-12-25"],"undesiredDates":["2024-12-31","2024-12-24"],"desiredDates":["2024-12-21","2024-12-20"]}},{"id":"shift_006","start":"2024-12-22T13:00:00","end":"2024-12-22T18:00:00","location":"Transport mobile","requiredSkill":"TRANSPORT","employee":{"name":"Luc Petit","skills":["TRANSPORT","ACCUEIL"],"unavailableDates":[],"undesiredDates":["2024-12-20"],"desiredDates":["2024-12-26","2024-12-25"]}},{"id":"shift_007","start":"2024-12-23T07:00:00","end":"2024-12-23T15:00:00","location":"Hôpital Rangueil","requiredSkill":"MEDECIN","employee":{"name":"Pierre Martin","skills":["MEDECIN","SUPERVISION"],"unavailableDates":["2024-12-30"],"undesiredDates":["2024-12-29"],"desiredDates":["2024-12-23","2024-12-22"]}},{"id":"shift_008","start":"2024-12-23T10:00:00","end":"2024-12-23T16:00:00","location":"Centre de collecte - Toulouse","requiredSkill":"PRELEVEMENT","employee":{"name":"Jean Leroy","skills":["PRELEVEMENT","TRANSPORT"],"unavailableDates":["2024-12-25","2024-12-24"],"undesiredDates":[],"desiredDates":["2024-12-30","2024-12-27"]}},{"id":"shift_009","start":"2024-12-24T08:00:00","end":"2024-12-24T14:00:00","location":"Centre de collecte - Colomiers","requiredSkill":"INFIRMIER","employee":{"name":"Sophie Bernard","skills":["ACCUEIL","INFIRMIER"],"unavailableDates":[],"undesiredDates":["2024-12-25"],"desiredDates":["2024-12-28","2024-12-24"]}},{"id":"shift_010","start":"2024-12-27T09:00:00","end":"2024-12-27T17:00:00","location":"Centre de collecte - Toulouse","requiredSkill":"SUPERVISION","employee":{"name":"Pierre Martin","skills":["MEDECIN","SUPERVISION"],"unavailableDates":["2024-12-30"],"undesiredDates":["2024-12-29"],"desiredDates":["2024-12-23","2024-12-22"]}},{"id":"shift_011","start":"2024-12-28T08:00:00","end":"2024-12-28T16:00:00","location":"Centre de collecte - Blagnac","requiredSkill":"ACCUEIL","employee":{"name":"Sophie Bernard","skills":["ACCUEIL","INFIRMIER"],"unavailableDates":[],"undesiredDates":["2024-12-25"],"desiredDates":["2024-12-28","2024-12-24"]}},{"id":"shift_012","start":"2024-12-29T06:00:00","end":"2024-12-29T14:00:00","location":"Hôpital Purpan","requiredSkill":"MEDECIN","employee":{"name":"Anne Moreau","skills":["MEDECIN","INFIRMIER"],"unavailableDates":["2024-12-26"],"undesiredDates":["2024-12-31"],"desiredDates":["2024-12-29","2024-12-21"]}},{"id":"shift_013","start":"2024-12-30T10:00:00","end":"2024-12-30T18:00:00","location":"Transport mobile","requiredSkill":"TRANSPORT","employee":{"name":"Jean Leroy","skills":["PRELEVEMENT","TRANSPORT"],"unavailableDates":["2024-12-25","2024-12-24"],"undesiredDates":[],"desiredDates":["2024-12-30","2024-12-27"]}},{"id":"shift_014","start":"2024-12-31T08:00:00","end":"2024-12-31T16:00:00","location":"Centre de collecte - Toulouse","requiredSkill":"INFIRMIER","employee":{"name":"Sophie Bernard","skills":["ACCUEIL","INFIRMIER"],"unavailableDates":[],"undesiredDates":["2024-12-25"],"desiredDates":["2024-12-28","2024-12-24"]}}],"score":"0hard/3238.84530soft","solverStatus":"NOT_SOLVING"} \ No newline at end of file diff --git a/src/main/java/org/acme/employeescheduling/domain/Employee.java b/src/main/java/org/acme/employeescheduling/domain/Employee.java new file mode 100644 index 0000000..0f2ff5d --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/domain/Employee.java @@ -0,0 +1,91 @@ +package org.acme.employeescheduling.domain; + +import java.time.LocalDate; +import java.util.Objects; +import java.util.Set; + +import ai.timefold.solver.core.api.domain.lookup.PlanningId; + +public class Employee { + @PlanningId + private String name; + private Set skills; + + private Set unavailableDates; + private Set undesiredDates; + private Set desiredDates; + + public Employee() { + + } + + public Employee(String name, Set skills, + Set unavailableDates, Set undesiredDates, Set desiredDates) { + this.name = name; + this.skills = skills; + this.unavailableDates = unavailableDates; + this.undesiredDates = undesiredDates; + this.desiredDates = desiredDates; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getSkills() { + return skills; + } + + public void setSkills(Set skills) { + this.skills = skills; + } + + public Set getUnavailableDates() { + return unavailableDates; + } + + public void setUnavailableDates(Set unavailableDates) { + this.unavailableDates = unavailableDates; + } + + public Set getUndesiredDates() { + return undesiredDates; + } + + public void setUndesiredDates(Set undesiredDates) { + this.undesiredDates = undesiredDates; + } + + public Set getDesiredDates() { + return desiredDates; + } + + public void setDesiredDates(Set desiredDates) { + this.desiredDates = desiredDates; + } + + @Override + public String toString() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Employee employee)) { + return false; + } + return Objects.equals(getName(), employee.getName()); + } + + @Override + public int hashCode() { + return getName().hashCode(); + } +} diff --git a/src/main/java/org/acme/employeescheduling/domain/EmployeeSchedule.java b/src/main/java/org/acme/employeescheduling/domain/EmployeeSchedule.java new file mode 100644 index 0000000..dc3ed1e --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/domain/EmployeeSchedule.java @@ -0,0 +1,72 @@ +package org.acme.employeescheduling.domain; + +import java.util.List; + +import ai.timefold.solver.core.api.domain.solution.PlanningEntityCollectionProperty; +import ai.timefold.solver.core.api.domain.solution.PlanningScore; +import ai.timefold.solver.core.api.domain.solution.PlanningSolution; +import ai.timefold.solver.core.api.domain.solution.ProblemFactCollectionProperty; +import ai.timefold.solver.core.api.domain.valuerange.ValueRangeProvider; +import ai.timefold.solver.core.api.score.buildin.hardsoftbigdecimal.HardSoftBigDecimalScore; +import ai.timefold.solver.core.api.solver.SolverStatus; + +@PlanningSolution +public class EmployeeSchedule { + + @ProblemFactCollectionProperty + @ValueRangeProvider + private List employees; + + @PlanningEntityCollectionProperty + private List shifts; + + @PlanningScore + private HardSoftBigDecimalScore score; + + private SolverStatus solverStatus; + + // No-arg constructor required for Timefold + public EmployeeSchedule() {} + + public EmployeeSchedule(List employees, List shifts) { + this.employees = employees; + this.shifts = shifts; + } + + public EmployeeSchedule(HardSoftBigDecimalScore score, SolverStatus solverStatus) { + this.score = score; + this.solverStatus = solverStatus; + } + + public List getEmployees() { + return employees; + } + + public void setEmployees(List employees) { + this.employees = employees; + } + + public List getShifts() { + return shifts; + } + + public void setShifts(List shifts) { + this.shifts = shifts; + } + + public HardSoftBigDecimalScore getScore() { + return score; + } + + public void setScore(HardSoftBigDecimalScore score) { + this.score = score; + } + + public SolverStatus getSolverStatus() { + return solverStatus; + } + + public void setSolverStatus(SolverStatus solverStatus) { + this.solverStatus = solverStatus; + } +} diff --git a/src/main/java/org/acme/employeescheduling/domain/Shift.java b/src/main/java/org/acme/employeescheduling/domain/Shift.java new file mode 100644 index 0000000..74cb018 --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/domain/Shift.java @@ -0,0 +1,133 @@ +package org.acme.employeescheduling.domain; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; +import java.util.Objects; + +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 Shift { + @PlanningId + private String id; + + private LocalDateTime start; + private LocalDateTime end; + + private String location; + private String requiredSkill; + + @PlanningVariable + private Employee employee; + + public Shift() { + } + + public Shift(LocalDateTime start, LocalDateTime end, String location, String requiredSkill) { + this(start, end, location, requiredSkill, null); + } + + public Shift(LocalDateTime start, LocalDateTime end, String location, String requiredSkill, Employee employee) { + this(null, start, end, location, requiredSkill, employee); + } + + public Shift(String id, LocalDateTime start, LocalDateTime end, String location, String requiredSkill, Employee employee) { + this.id = id; + this.start = start; + this.end = end; + this.location = location; + this.requiredSkill = requiredSkill; + this.employee = employee; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public LocalDateTime getStart() { + return start; + } + + public void setStart(LocalDateTime start) { + this.start = start; + } + + public LocalDateTime getEnd() { + return end; + } + + public void setEnd(LocalDateTime end) { + this.end = end; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getRequiredSkill() { + return requiredSkill; + } + + public void setRequiredSkill(String requiredSkill) { + this.requiredSkill = requiredSkill; + } + + public Employee getEmployee() { + return employee; + } + + public void setEmployee(Employee employee) { + this.employee = employee; + } + + public boolean isOverlappingWithDate(LocalDate date) { + return getStart().toLocalDate().equals(date) || getEnd().toLocalDate().equals(date); + } + + public int getOverlappingDurationInMinutes(LocalDate date) { + LocalDateTime startDateTime = LocalDateTime.of(date, LocalTime.MIN); + LocalDateTime endDateTime = LocalDateTime.of(date, LocalTime.MAX); + return getOverlappingDurationInMinutes(startDateTime, endDateTime, getStart(), getEnd()); + } + + private int getOverlappingDurationInMinutes(LocalDateTime firstStartDateTime, LocalDateTime firstEndDateTime, + LocalDateTime secondStartDateTime, LocalDateTime secondEndDateTime) { + LocalDateTime maxStartTime = firstStartDateTime.isAfter(secondStartDateTime) ? firstStartDateTime : secondStartDateTime; + LocalDateTime minEndTime = firstEndDateTime.isBefore(secondEndDateTime) ? firstEndDateTime : secondEndDateTime; + long minutes = maxStartTime.until(minEndTime, ChronoUnit.MINUTES); + return minutes > 0 ? (int) minutes : 0; + } + + @Override + public String toString() { + return location + " " + start + "-" + end; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Shift shift)) { + return false; + } + return Objects.equals(getId(), shift.getId()); + } + + @Override + public int hashCode() { + return getId().hashCode(); + } +} diff --git a/src/main/java/org/acme/employeescheduling/rest/DemoDataGenerator.java b/src/main/java/org/acme/employeescheduling/rest/DemoDataGenerator.java new file mode 100644 index 0000000..5230bfe --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/rest/DemoDataGenerator.java @@ -0,0 +1,240 @@ +package org.acme.employeescheduling.rest; + +import java.time.DayOfWeek; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import jakarta.enterprise.context.ApplicationScoped; + +import org.acme.employeescheduling.domain.Employee; +import org.acme.employeescheduling.domain.EmployeeSchedule; +import org.acme.employeescheduling.domain.Shift; + +@ApplicationScoped +public class DemoDataGenerator { + public enum DemoData { + SMALL(new DemoDataParameters( + List.of("Ambulatory care", "Critical care", "Pediatric care"), + List.of("Doctor", "Nurse"), + List.of("Anaesthetics", "Cardiology"), + 14, + 15, + List.of(new CountDistribution(1, 3), + new CountDistribution(2, 1) + ), + List.of(new CountDistribution(1, 0.9), + new CountDistribution(2, 0.1) + ), + List.of(new CountDistribution(1, 4), + new CountDistribution(2, 3), + new CountDistribution(3, 2), + new CountDistribution(4, 1) + ), + 0 + )), + LARGE(new DemoDataParameters( + List.of("Ambulatory care", + "Neurology", + "Critical care", + "Pediatric care", + "Surgery", + "Radiology", + "Outpatient"), + List.of("Doctor", "Nurse"), + List.of("Anaesthetics", "Cardiology", "Radiology"), + 28, + 50, + List.of(new CountDistribution(1, 3), + new CountDistribution(2, 1) + ), + List.of(new CountDistribution(1, 0.5), + new CountDistribution(2, 0.3), + new CountDistribution(3, 0.2) + ), + List.of(new CountDistribution(5, 4), + new CountDistribution(10, 3), + new CountDistribution(15, 2), + new CountDistribution(20, 1) + ), + 0 + )); + + private final DemoDataParameters parameters; + + DemoData(DemoDataParameters parameters) { + this.parameters = parameters; + } + + public DemoDataParameters getParameters() { + return parameters; + } + } + + public record CountDistribution(int count, double weight) {} + + public record DemoDataParameters(List locations, + List requiredSkills, + List optionalSkills, + int daysInSchedule, + int employeeCount, + List optionalSkillDistribution, + List shiftCountDistribution, + List availabilityCountDistribution, + int randomSeed) {} + + private static final String[] FIRST_NAMES = { "Amy", "Beth", "Carl", "Dan", "Elsa", "Flo", "Gus", "Hugo", "Ivy", "Jay" }; + private static final String[] LAST_NAMES = { "Cole", "Fox", "Green", "Jones", "King", "Li", "Poe", "Rye", "Smith", "Watt" }; + private static final Duration SHIFT_LENGTH = Duration.ofHours(8); + private static final LocalTime MORNING_SHIFT_START_TIME = LocalTime.of(6, 0); + private static final LocalTime DAY_SHIFT_START_TIME = LocalTime.of(9, 0); + private static final LocalTime AFTERNOON_SHIFT_START_TIME = LocalTime.of(14, 0); + private static final LocalTime NIGHT_SHIFT_START_TIME = LocalTime.of(22, 0); + + static final LocalTime[][] SHIFT_START_TIMES_COMBOS = { + { MORNING_SHIFT_START_TIME, AFTERNOON_SHIFT_START_TIME }, + { MORNING_SHIFT_START_TIME, AFTERNOON_SHIFT_START_TIME, NIGHT_SHIFT_START_TIME }, + { MORNING_SHIFT_START_TIME, DAY_SHIFT_START_TIME, AFTERNOON_SHIFT_START_TIME, NIGHT_SHIFT_START_TIME }, + }; + + Map> locationToShiftStartTimeListMap = new HashMap<>(); + + public EmployeeSchedule generateDemoData(DemoData demoData) { + return generateDemoData(demoData.getParameters()); + } + + public EmployeeSchedule generateDemoData(DemoDataParameters parameters) { + EmployeeSchedule employeeSchedule = new EmployeeSchedule(); + + LocalDate startDate = LocalDate.now().with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY)); + + Random random = new Random(parameters.randomSeed); + + int shiftTemplateIndex = 0; + for (String location : parameters.locations) { + locationToShiftStartTimeListMap.put(location, List.of(SHIFT_START_TIMES_COMBOS[shiftTemplateIndex])); + shiftTemplateIndex = (shiftTemplateIndex + 1) % SHIFT_START_TIMES_COMBOS.length; + } + + List namePermutations = joinAllCombinations(FIRST_NAMES, LAST_NAMES); + Collections.shuffle(namePermutations, random); + + List employees = new ArrayList<>(); + for (int i = 0; i < parameters.employeeCount; i++) { + Set skills = pickSubset(parameters.optionalSkills, random, parameters.optionalSkillDistribution); + skills.add(pickRandom(parameters.requiredSkills, random)); + Employee employee = new Employee(namePermutations.get(i), skills, new LinkedHashSet<>(), new LinkedHashSet<>(), new LinkedHashSet<>()); + employees.add(employee); + } + employeeSchedule.setEmployees(employees); + + List shifts = new LinkedList<>(); + for (int i = 0; i < parameters.daysInSchedule; i++) { + Set employeesWithAvailabilitiesOnDay = pickSubset(employees, random, + parameters.availabilityCountDistribution); + LocalDate date = startDate.plusDays(i); + for (Employee employee : employeesWithAvailabilitiesOnDay) { + switch (random.nextInt(3)) { + case 0 -> employee.getUnavailableDates().add(date); + case 1 -> employee.getUndesiredDates().add(date); + case 2 -> employee.getDesiredDates().add(date); + } + } + shifts.addAll(generateShiftsForDay(parameters, date, random)); + } + AtomicInteger countShift = new AtomicInteger(); + shifts.forEach(s -> s.setId(Integer.toString(countShift.getAndIncrement()))); + employeeSchedule.setShifts(shifts); + + return employeeSchedule; + } + + private List generateShiftsForDay(DemoDataParameters parameters, LocalDate date, Random random) { + List shifts = new LinkedList<>(); + for (String location : parameters.locations) { + List shiftStartTimes = locationToShiftStartTimeListMap.get(location); + for (LocalTime shiftStartTime : shiftStartTimes) { + LocalDateTime shiftStartDateTime = date.atTime(shiftStartTime); + LocalDateTime shiftEndDateTime = shiftStartDateTime.plus(SHIFT_LENGTH); + shifts.addAll(generateShiftForTimeslot(parameters, shiftStartDateTime, shiftEndDateTime, location, random)); + } + } + return shifts; + } + + private List generateShiftForTimeslot(DemoDataParameters parameters, + LocalDateTime timeslotStart, LocalDateTime timeslotEnd, String location, + Random random) { + var shiftCount = pickCount(random, parameters.shiftCountDistribution); + + List shifts = new LinkedList<>(); + for (int i = 0; i < shiftCount; i++) { + String requiredSkill; + if (random.nextBoolean()) { + requiredSkill = pickRandom(parameters.requiredSkills, random); + } else { + requiredSkill = pickRandom(parameters.optionalSkills, random); + } + shifts.add(new Shift(timeslotStart, timeslotEnd, location, requiredSkill)); + } + return shifts; + } + + private T pickRandom(List source, Random random) { + return source.get(random.nextInt(source.size())); + } + + private int pickCount(Random random, List countDistribution) { + double probabilitySum = 0; + for (var possibility : countDistribution) { + probabilitySum += possibility.weight; + } + var choice = random.nextDouble(probabilitySum); + int numOfItems = 0; + while (choice >= countDistribution.get(numOfItems).weight) { + choice -= countDistribution.get(numOfItems).weight; + numOfItems++; + } + return countDistribution.get(numOfItems).count; + } + + private Set pickSubset(List sourceSet, Random random, List countDistribution) { + var count = pickCount(random, countDistribution); + List items = new ArrayList<>(sourceSet); + Collections.shuffle(items, random); + return new HashSet<>(items.subList(0, count)); + } + + private List joinAllCombinations(String[]... partArrays) { + int size = 1; + for (String[] partArray : partArrays) { + size *= partArray.length; + } + List out = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + StringBuilder item = new StringBuilder(); + int sizePerIncrement = 1; + for (String[] partArray : partArrays) { + item.append(' '); + item.append(partArray[(i / sizePerIncrement) % partArray.length]); + sizePerIncrement *= partArray.length; + } + item.delete(0, 1); + out.add(item.toString()); + } + return out; + } +} diff --git a/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.java b/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.java new file mode 100644 index 0000000..c036401 --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.java @@ -0,0 +1,51 @@ +package org.acme.employeescheduling.rest; + +import jakarta.inject.Inject; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.acme.employeescheduling.domain.EmployeeSchedule; +import org.acme.employeescheduling.rest.DemoDataGenerator.DemoData; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; + +@Tag(name = "Demo data", description = "Timefold-provided demo employee schedule data.") +@Path("demo-data") +public class EmployeeScheduleDemoResource { + + private final DemoDataGenerator dataGenerator; + + @Inject + public EmployeeScheduleDemoResource(DemoDataGenerator dataGenerator) { + this.dataGenerator = dataGenerator; + } + + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "List of demo data represented as IDs.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = DemoData.class, type = SchemaType.ARRAY))) }) + @Operation(summary = "List demo data.") + @GET + public DemoData[] list() { + return DemoData.values(); + } + + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "Unsolved demo schedule.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EmployeeSchedule.class)))}) + @Operation(summary = "Find an unsolved demo schedule by ID.") + @GET + @Path("/{demoDataId}") + public Response generate(@PathParam("demoDataId") DemoData demoData) { + return Response.ok(dataGenerator.generateDemoData(demoData)).build(); + } +} diff --git a/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java b/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java new file mode 100644 index 0000000..2ab429f --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java @@ -0,0 +1,201 @@ +package org.acme.employeescheduling.rest; + +import java.util.Collection; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import ai.timefold.solver.core.api.score.analysis.ScoreAnalysis; +import ai.timefold.solver.core.api.score.buildin.hardsoftbigdecimal.HardSoftBigDecimalScore; +import ai.timefold.solver.core.api.solver.ScoreAnalysisFetchPolicy; +import ai.timefold.solver.core.api.solver.SolutionManager; +import ai.timefold.solver.core.api.solver.SolverManager; +import ai.timefold.solver.core.api.solver.SolverStatus; + +import org.acme.employeescheduling.domain.EmployeeSchedule; +import org.acme.employeescheduling.rest.exception.EmployeeScheduleSolverException; +import org.acme.employeescheduling.rest.exception.ErrorInfo; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Tag(name = "Employee Schedules", description = "Employee Schedules service for assigning employees to shifts.") +@Path("schedules") +public class EmployeeScheduleResource { + + private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeScheduleResource.class); + + 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, + SolutionManager solutionManager) { + this.solverManager = solverManager; + this.solutionManager = solutionManager; + } + + @Operation(summary = "List the job IDs of all submitted schedules.") + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "List of all job IDs.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(type = SchemaType.ARRAY, implementation = String.class))) }) + @GET + @Produces(MediaType.APPLICATION_JSON) + public Collection list() { + return jobIdToJob.keySet(); + } + + @Operation(summary = "Submit a schedule to start solving as soon as CPU resources are available.") + @APIResponses(value = { + @APIResponse(responseCode = "202", + description = "The job ID. Use that ID to get the solution with the other methods.", + content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(implementation = String.class))) }) + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces(MediaType.TEXT_PLAIN) + public String solve(EmployeeSchedule problem) { + String jobId = UUID.randomUUID().toString(); + jobIdToJob.put(jobId, Job.ofSchedule(problem)); + solverManager.solveBuilder() + .withProblemId(jobId) + .withProblemFinder(jobId_ -> jobIdToJob.get(jobId).schedule) + .withBestSolutionConsumer(solution -> jobIdToJob.put(jobId, Job.ofSchedule(solution))) + .withExceptionHandler((jobId_, exception) -> { + jobIdToJob.put(jobId, Job.ofException(exception)); + LOGGER.error("Failed solving jobId ({}).", jobId, exception); + }) + .run(); + return jobId; + } + + @Operation(summary = "Submit a schedule to analyze its score.") + @APIResponses(value = { + @APIResponse(responseCode = "202", + description = "Resulting score analysis, optionally without constraint matches.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ScoreAnalysis.class))) }) + @PUT + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces(MediaType.APPLICATION_JSON) + @Path("analyze") + public ScoreAnalysis analyze(EmployeeSchedule problem, + @QueryParam("fetchPolicy") ScoreAnalysisFetchPolicy fetchPolicy) { + return fetchPolicy == null ? solutionManager.analyze(problem) : solutionManager.analyze(problem, fetchPolicy); + } + + @Operation( + summary = "Get the solution and score for a given job ID. This is the best solution so far, as it might still be running or not even started.") + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "The best solution of the schedule so far.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EmployeeSchedule.class))), + @APIResponse(responseCode = "404", description = "No schedule found.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ErrorInfo.class))), + @APIResponse(responseCode = "500", description = "Exception during solving a schedule.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ErrorInfo.class))) + }) + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{jobId}") + public EmployeeSchedule getEmployeeSchedule( + @Parameter(description = "The job ID returned by the POST method.") @PathParam("jobId") String jobId) { + EmployeeSchedule schedule = getEmployeeScheduleAndCheckForExceptions(jobId); + SolverStatus solverStatus = solverManager.getSolverStatus(jobId); + schedule.setSolverStatus(solverStatus); + return schedule; + } + + private EmployeeSchedule getEmployeeScheduleAndCheckForExceptions(String jobId) { + Job job = jobIdToJob.get(jobId); + if (job == null) { + throw new EmployeeScheduleSolverException(jobId, Response.Status.NOT_FOUND, "No schedule found."); + } + if (job.exception != null) { + throw new EmployeeScheduleSolverException(jobId, job.exception); + } + return job.schedule; + } + + @Operation( + summary = "Terminate solving for a given job ID. Returns the best solution of the schedule so far, as it might still be running or not even started.") + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "The best solution of the schedule so far.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EmployeeSchedule.class))), + @APIResponse(responseCode = "404", description = "No schedule found.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ErrorInfo.class))), + @APIResponse(responseCode = "500", description = "Exception during solving a schedule.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ErrorInfo.class))) + }) + @DELETE + @Produces(MediaType.APPLICATION_JSON) + @Path("{jobId}") + public EmployeeSchedule terminateSolving( + @Parameter(description = "The job ID returned by the POST method.") @PathParam("jobId") String jobId) { + // TODO: Replace with .terminateEarlyAndWait(... [, timeout]); see https://github.com/TimefoldAI/timefold-solver/issues/77 + solverManager.terminateEarly(jobId); + return getEmployeeSchedule(jobId); + } + + @Operation( + summary = "Get the schedule status and score for a given job ID.") + @APIResponses(value = { + @APIResponse(responseCode = "200", description = "The schedule status and the best score so far.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = EmployeeSchedule.class))), + @APIResponse(responseCode = "404", description = "No schedule found.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ErrorInfo.class))), + @APIResponse(responseCode = "500", description = "Exception during solving a schedule.", + content = @Content(mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = ErrorInfo.class))) + }) + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{jobId}/status") + public EmployeeSchedule getStatus( + @Parameter(description = "The job ID returned by the POST method.") @PathParam("jobId") String jobId) { + EmployeeSchedule schedule = getEmployeeScheduleAndCheckForExceptions(jobId); + SolverStatus solverStatus = solverManager.getSolverStatus(jobId); + return new EmployeeSchedule(schedule.getScore(), solverStatus); + } + + private record Job(EmployeeSchedule schedule, Throwable exception) { + + static Job ofSchedule(EmployeeSchedule schedule) { + return new Job(schedule, null); + } + + static Job ofException(Throwable error) { + return new Job(null, error); + } + } +} diff --git a/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.java b/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.java new file mode 100644 index 0000000..b2fc316 --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.java @@ -0,0 +1,30 @@ +package org.acme.employeescheduling.rest.exception; + +import jakarta.ws.rs.core.Response; + +public class EmployeeScheduleSolverException extends RuntimeException { + + private final String jobId; + + private final Response.Status status; + + public EmployeeScheduleSolverException(String jobId, Response.Status status, String message) { + super(message); + this.jobId = jobId; + this.status = status; + } + + public EmployeeScheduleSolverException(String jobId, Throwable cause) { + super(cause.getMessage(), cause); + this.jobId = jobId; + this.status = Response.Status.INTERNAL_SERVER_ERROR; + } + + public String getJobId() { + return jobId; + } + + public Response.Status getStatus() { + return status; + } +} diff --git a/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.java b/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.java new file mode 100644 index 0000000..481079e --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.java @@ -0,0 +1,19 @@ +package org.acme.employeescheduling.rest.exception; + +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; + +@Provider +public class EmployeeScheduleSolverExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(EmployeeScheduleSolverException exception) { + return Response + .status(exception.getStatus()) + .type(MediaType.APPLICATION_JSON) + .entity(new ErrorInfo(exception.getJobId(), exception.getMessage())) + .build(); + } +} diff --git a/src/main/java/org/acme/employeescheduling/rest/exception/ErrorInfo.java b/src/main/java/org/acme/employeescheduling/rest/exception/ErrorInfo.java new file mode 100644 index 0000000..5ab81f4 --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/rest/exception/ErrorInfo.java @@ -0,0 +1,4 @@ +package org.acme.employeescheduling.rest.exception; + +public record ErrorInfo(String jobId, String message) { +} diff --git a/src/main/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.java b/src/main/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.java new file mode 100644 index 0000000..63a2071 --- /dev/null +++ b/src/main/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.java @@ -0,0 +1,123 @@ +package org.acme.employeescheduling.solver; + +import static ai.timefold.solver.core.api.score.stream.Joiners.equal; +import static ai.timefold.solver.core.api.score.stream.Joiners.lessThanOrEqual; +import static ai.timefold.solver.core.api.score.stream.Joiners.overlapping; + +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.function.Function; + +import ai.timefold.solver.core.api.score.buildin.hardsoftbigdecimal.HardSoftBigDecimalScore; +import ai.timefold.solver.core.api.score.stream.Constraint; +import ai.timefold.solver.core.api.score.stream.ConstraintCollectors; +import ai.timefold.solver.core.api.score.stream.ConstraintFactory; +import ai.timefold.solver.core.api.score.stream.ConstraintProvider; +import ai.timefold.solver.core.api.score.stream.common.LoadBalance; + +import org.acme.employeescheduling.domain.Employee; +import org.acme.employeescheduling.domain.Shift; + +public class EmployeeSchedulingConstraintProvider implements ConstraintProvider { + + private static int getMinuteOverlap(Shift shift1, Shift shift2) { + // The overlap of two timeslot occurs in the range common to both timeslots. + // Both timeslots are active after the higher of their two start times, + // and before the lower of their two end times. + LocalDateTime shift1Start = shift1.getStart(); + LocalDateTime shift1End = shift1.getEnd(); + LocalDateTime shift2Start = shift2.getStart(); + LocalDateTime shift2End = shift2.getEnd(); + return (int) Duration.between((shift1Start.isAfter(shift2Start)) ? shift1Start : shift2Start, + (shift1End.isBefore(shift2End)) ? shift1End : shift2End).toMinutes(); + } + + @Override + public Constraint[] defineConstraints(ConstraintFactory constraintFactory) { + return new Constraint[] { + // Hard constraints + requiredSkill(constraintFactory), + noOverlappingShifts(constraintFactory), + atLeast10HoursBetweenTwoShifts(constraintFactory), + oneShiftPerDay(constraintFactory), + unavailableEmployee(constraintFactory), + // Soft constraints + undesiredDayForEmployee(constraintFactory), + desiredDayForEmployee(constraintFactory), + balanceEmployeeShiftAssignments(constraintFactory) + }; + } + + Constraint requiredSkill(ConstraintFactory constraintFactory) { + return constraintFactory.forEach(Shift.class) + .filter(shift -> !shift.getEmployee().getSkills().contains(shift.getRequiredSkill())) + .penalize(HardSoftBigDecimalScore.ONE_HARD) + .asConstraint("Missing required skill"); + } + + Constraint noOverlappingShifts(ConstraintFactory constraintFactory) { + return constraintFactory.forEachUniquePair(Shift.class, equal(Shift::getEmployee), + overlapping(Shift::getStart, Shift::getEnd)) + .penalize(HardSoftBigDecimalScore.ONE_HARD, + EmployeeSchedulingConstraintProvider::getMinuteOverlap) + .asConstraint("Overlapping shift"); + } + + Constraint atLeast10HoursBetweenTwoShifts(ConstraintFactory constraintFactory) { + return constraintFactory.forEach(Shift.class) + .join(Shift.class, equal(Shift::getEmployee), lessThanOrEqual(Shift::getEnd, Shift::getStart)) + .filter((firstShift, + secondShift) -> Duration.between(firstShift.getEnd(), secondShift.getStart()).toHours() < 10) + .penalize(HardSoftBigDecimalScore.ONE_HARD, + (firstShift, secondShift) -> { + int breakLength = (int) Duration.between(firstShift.getEnd(), secondShift.getStart()).toMinutes(); + return (10 * 60) - breakLength; + }) + .asConstraint("At least 10 hours between 2 shifts"); + } + + Constraint oneShiftPerDay(ConstraintFactory constraintFactory) { + return constraintFactory.forEachUniquePair(Shift.class, equal(Shift::getEmployee), + equal(shift -> shift.getStart().toLocalDate())) + .penalize(HardSoftBigDecimalScore.ONE_HARD) + .asConstraint("Max one shift per day"); + } + + Constraint unavailableEmployee(ConstraintFactory constraintFactory) { + return constraintFactory.forEach(Shift.class) + .join(Employee.class, equal(Shift::getEmployee, Function.identity())) + .flattenLast(Employee::getUnavailableDates) + .filter(Shift::isOverlappingWithDate) + .penalize(HardSoftBigDecimalScore.ONE_HARD, Shift::getOverlappingDurationInMinutes) + .asConstraint("Unavailable employee"); + } + + Constraint undesiredDayForEmployee(ConstraintFactory constraintFactory) { + return constraintFactory.forEach(Shift.class) + .join(Employee.class, equal(Shift::getEmployee, Function.identity())) + .flattenLast(Employee::getUndesiredDates) + .filter(Shift::isOverlappingWithDate) + .penalize(HardSoftBigDecimalScore.ONE_SOFT, Shift::getOverlappingDurationInMinutes) + .asConstraint("Undesired day for employee"); + } + + Constraint desiredDayForEmployee(ConstraintFactory constraintFactory) { + return constraintFactory.forEach(Shift.class) + .join(Employee.class, equal(Shift::getEmployee, Function.identity())) + .flattenLast(Employee::getDesiredDates) + .filter(Shift::isOverlappingWithDate) + .reward(HardSoftBigDecimalScore.ONE_SOFT, Shift::getOverlappingDurationInMinutes) + .asConstraint("Desired day for employee"); + } + + Constraint balanceEmployeeShiftAssignments(ConstraintFactory constraintFactory) { + return constraintFactory.forEach(Shift.class) + .groupBy(Shift::getEmployee, ConstraintCollectors.count()) + .complement(Employee.class, e -> 0) // Include all employees which are not assigned to any shift.c + .groupBy(ConstraintCollectors.loadBalance((employee, shiftCount) -> employee, + (employee, shiftCount) -> shiftCount)) + .penalizeBigDecimal(HardSoftBigDecimalScore.ONE_SOFT, LoadBalance::unfairness) + .asConstraint("Balance employee shift assignments"); + } + +} diff --git a/src/main/resources/META-INF/resources/app.js b/src/main/resources/META-INF/resources/app.js new file mode 100644 index 0000000..eca3308 --- /dev/null +++ b/src/main/resources/META-INF/resources/app.js @@ -0,0 +1,496 @@ +let autoRefreshIntervalId = null; +const zoomMin = 2 * 1000 * 60 * 60 * 24 // 2 day in milliseconds +const zoomMax = 4 * 7 * 1000 * 60 * 60 * 24 // 4 weeks in milliseconds + +const UNAVAILABLE_COLOR = '#ef2929' // Tango Scarlet Red +const UNDESIRED_COLOR = '#f57900' // Tango Orange +const DESIRED_COLOR = '#73d216' // Tango Chameleon + +let demoDataId = null; +let scheduleId = null; +let loadedSchedule = null; + +const byEmployeePanel = document.getElementById("byEmployeePanel"); +const byEmployeeTimelineOptions = { + timeAxis: {scale: "hour", step: 6}, + orientation: {axis: "top"}, + stack: false, + xss: {disabled: true}, // Items are XSS safe through JQuery + zoomMin: zoomMin, + zoomMax: zoomMax, +}; +let byEmployeeGroupDataSet = new vis.DataSet(); +let byEmployeeItemDataSet = new vis.DataSet(); +let byEmployeeTimeline = new vis.Timeline(byEmployeePanel, byEmployeeItemDataSet, byEmployeeGroupDataSet, byEmployeeTimelineOptions); + +const byLocationPanel = document.getElementById("byLocationPanel"); +const byLocationTimelineOptions = { + timeAxis: {scale: "hour", step: 6}, + orientation: {axis: "top"}, + xss: {disabled: true}, // Items are XSS safe through JQuery + zoomMin: zoomMin, + zoomMax: zoomMax, +}; +let byLocationGroupDataSet = new vis.DataSet(); +let byLocationItemDataSet = new vis.DataSet(); +let byLocationTimeline = new vis.Timeline(byLocationPanel, byLocationItemDataSet, byLocationGroupDataSet, byLocationTimelineOptions); + +let windowStart = JSJoda.LocalDate.now().toString(); +let windowEnd = JSJoda.LocalDate.parse(windowStart).plusDays(7).toString(); + +$(document).ready(function () { + replaceQuickstartTimefoldAutoHeaderFooter(); + + $("#solveButton").click(function () { + solve(); + }); + $("#stopSolvingButton").click(function () { + stopSolving(); + }); + $("#analyzeButton").click(function () { + analyze(); + }); + // HACK to allow vis-timeline to work within Bootstrap tabs + $("#byEmployeeTab").on('shown.bs.tab', function (event) { + byEmployeeTimeline.redraw(); + }) + $("#byLocationTab").on('shown.bs.tab', function (event) { + byLocationTimeline.redraw(); + }) + + setupAjax(); + fetchDemoData(); +}); + +function setupAjax() { + $.ajaxSetup({ + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json,text/plain', // plain text is required by solve() returning UUID of the solver job + } + }); + // Extend jQuery to support $.put() and $.delete() + jQuery.each(["put", "delete"], function (i, method) { + jQuery[method] = function (url, data, callback, type) { + if (jQuery.isFunction(data)) { + type = type || callback; + callback = data; + data = undefined; + } + return jQuery.ajax({ + url: url, + type: method, + dataType: type, + data: data, + success: callback + }); + }; + }); +} + +function fetchDemoData() { + $.get("/demo-data", function (data) { + data.forEach(item => { + $("#testDataButton").append($('' + item + '')); + $("#" + item + "TestData").click(function () { + switchDataDropDownItemActive(item); + scheduleId = null; + demoDataId = item; + + refreshSchedule(); + }); + }); + demoDataId = data[0]; + switchDataDropDownItemActive(demoDataId); + refreshSchedule(); + }).fail(function (xhr, ajaxOptions, thrownError) { + // disable this page as there is no data + let $demo = $("#demo"); + $demo.empty(); + $demo.html("

No test data available

") + }); +} + +function switchDataDropDownItemActive(newItem) { + activeCssClass = "active"; + $("#testDataButton > a." + activeCssClass).removeClass(activeCssClass); + $("#" + newItem + "TestData").addClass(activeCssClass); +} + +function getShiftColor(shift, employee) { + const shiftStart = JSJoda.LocalDateTime.parse(shift.start); + const shiftStartDateString = shiftStart.toLocalDate().toString(); + const shiftEnd = JSJoda.LocalDateTime.parse(shift.end); + const shiftEndDateString = shiftEnd.toLocalDate().toString(); + if (employee.unavailableDates.includes(shiftStartDateString) || + // The contains() check is ignored for a shift end at midnight (00:00:00). + (shiftEnd.isAfter(shiftStart.toLocalDate().plusDays(1).atStartOfDay()) && + employee.unavailableDates.includes(shiftEndDateString))) { + return UNAVAILABLE_COLOR + } else if (employee.undesiredDates.includes(shiftStartDateString) || + // The contains() check is ignored for a shift end at midnight (00:00:00). + (shiftEnd.isAfter(shiftStart.toLocalDate().plusDays(1).atStartOfDay()) && + employee.undesiredDates.includes(shiftEndDateString))) { + return UNDESIRED_COLOR + } else if (employee.desiredDates.includes(shiftStartDateString) || + // The contains() check is ignored for a shift end at midnight (00:00:00). + (shiftEnd.isAfter(shiftStart.toLocalDate().plusDays(1).atStartOfDay()) && + employee.desiredDates.includes(shiftEndDateString))) { + return DESIRED_COLOR + } else { + return " #729fcf"; // Tango Sky Blue + } +} + +function refreshSchedule() { + let path = "/schedules/" + scheduleId; + if (scheduleId === null) { + if (demoDataId === null) { + alert("Please select a test data set."); + return; + } + + path = "/demo-data/" + demoDataId; + } + $.getJSON(path, function (schedule) { + loadedSchedule = schedule; + renderSchedule(schedule); + }) + .fail(function (xhr, ajaxOptions, thrownError) { + showError("Getting the schedule has failed.", xhr); + refreshSolvingButtons(false); + }); +} + +function renderSchedule(schedule) { + refreshSolvingButtons(schedule.solverStatus != null && schedule.solverStatus !== "NOT_SOLVING"); + $("#score").text("Score: " + (schedule.score == null ? "?" : schedule.score)); + + const unassignedShifts = $("#unassignedShifts"); + const groups = []; + + // Show only first 7 days of draft + const scheduleStart = schedule.shifts.map(shift => JSJoda.LocalDateTime.parse(shift.start).toLocalDate()).sort()[0].toString(); + const scheduleEnd = JSJoda.LocalDate.parse(scheduleStart).plusDays(7).toString(); + + windowStart = scheduleStart; + windowEnd = scheduleEnd; + + unassignedShifts.children().remove(); + let unassignedShiftsCount = 0; + byEmployeeGroupDataSet.clear(); + byLocationGroupDataSet.clear(); + + byEmployeeItemDataSet.clear(); + byLocationItemDataSet.clear(); + + + schedule.employees.forEach((employee, index) => { + const employeeGroupElement = $('
') + .append($(`
)`) + .append(employee.name)) + .append($('
') + .append($(employee.skills.map(skill => `${skill}`).join('')))); + byEmployeeGroupDataSet.add({id: employee.name, content: employeeGroupElement.html()}); + + employee.unavailableDates.forEach((rawDate, dateIndex) => { + const date = JSJoda.LocalDate.parse(rawDate) + const start = date.atStartOfDay().toString(); + const end = date.plusDays(1).atStartOfDay().toString(); + const byEmployeeShiftElement = $(`
`) + .append($(`
`).text("Unavailable")); + byEmployeeItemDataSet.add({ + id: "employee-" + index + "-unavailability-" + dateIndex, group: employee.name, + content: byEmployeeShiftElement.html(), + start: start, end: end, + type: "background", + style: "opacity: 0.5; background-color: " + UNAVAILABLE_COLOR, + }); + }); + employee.undesiredDates.forEach((rawDate, dateIndex) => { + const date = JSJoda.LocalDate.parse(rawDate) + const start = date.atStartOfDay().toString(); + const end = date.plusDays(1).atStartOfDay().toString(); + const byEmployeeShiftElement = $(`
`) + .append($(`
`).text("Undesired")); + byEmployeeItemDataSet.add({ + id: "employee-" + index + "-undesired-" + dateIndex, group: employee.name, + content: byEmployeeShiftElement.html(), + start: start, end: end, + type: "background", + style: "opacity: 0.5; background-color: " + UNDESIRED_COLOR, + }); + }); + employee.desiredDates.forEach((rawDate, dateIndex) => { + const date = JSJoda.LocalDate.parse(rawDate) + const start = date.atStartOfDay().toString(); + const end = date.plusDays(1).atStartOfDay().toString(); + const byEmployeeShiftElement = $(`
`) + .append($(`
`).text("Desired")); + byEmployeeItemDataSet.add({ + id: "employee-" + index + "-desired-" + dateIndex, group: employee.name, + content: byEmployeeShiftElement.html(), + start: start, end: end, + type: "background", + style: "opacity: 0.5; background-color: " + DESIRED_COLOR, + }); + }); + }); + + schedule.shifts.forEach((shift, index) => { + if (groups.indexOf(shift.location) === -1) { + groups.push(shift.location); + byLocationGroupDataSet.add({ + id: shift.location, + content: shift.location, + }); + } + + if (shift.employee == null) { + unassignedShiftsCount++; + + const byLocationShiftElement = $('
') + .append($(`
)`) + .append("Unassigned")) + .append($('
') + .append($(`${shift.requiredSkill}`))); + + byLocationItemDataSet.add({ + id: 'shift-' + index, group: shift.location, + content: byLocationShiftElement.html(), + start: shift.start, end: shift.end, + style: "background-color: #EF292999" + }); + } else { + const skillColor = (shift.employee.skills.indexOf(shift.requiredSkill) === -1 ? '#ef2929' : '#8ae234'); + const byEmployeeShiftElement = $('
') + .append($(`
)`) + .append(shift.location)) + .append($('
') + .append($(`${shift.requiredSkill}`))); + const byLocationShiftElement = $('
') + .append($(`
)`) + .append(shift.employee.name)) + .append($('
') + .append($(`${shift.requiredSkill}`))); + + const shiftColor = getShiftColor(shift, shift.employee); + byEmployeeItemDataSet.add({ + id: 'shift-' + index, group: shift.employee.name, + content: byEmployeeShiftElement.html(), + start: shift.start, end: shift.end, + style: "background-color: " + shiftColor + }); + byLocationItemDataSet.add({ + id: 'shift-' + index, group: shift.location, + content: byLocationShiftElement.html(), + start: shift.start, end: shift.end, + style: "background-color: " + shiftColor + }); + } + }); + + + if (unassignedShiftsCount === 0) { + unassignedShifts.append($(`

`).text(`There are no unassigned shifts.`)); + } else { + unassignedShifts.append($(`

`).text(`There are ${unassignedShiftsCount} unassigned shifts.`)); + } + byEmployeeTimeline.setWindow(scheduleStart, scheduleEnd); + byLocationTimeline.setWindow(scheduleStart, scheduleEnd); +} + +function solve() { + $.post("/schedules", JSON.stringify(loadedSchedule), function (data) { + scheduleId = data; + refreshSolvingButtons(true); + }).fail(function (xhr, ajaxOptions, thrownError) { + showError("Start solving failed.", xhr); + refreshSolvingButtons(false); + }, + "text"); +} + +function analyze() { + new bootstrap.Modal("#scoreAnalysisModal").show() + const scoreAnalysisModalContent = $("#scoreAnalysisModalContent"); + scoreAnalysisModalContent.children().remove(); + if (loadedSchedule.score == null) { + scoreAnalysisModalContent.text("No score to analyze yet, please first press the 'solve' button."); + } else { + $('#scoreAnalysisScoreLabel').text(`(${loadedSchedule.score})`); + $.put("/schedules/analyze", JSON.stringify(loadedSchedule), function (scoreAnalysis) { + let constraints = scoreAnalysis.constraints; + constraints.sort((a, b) => { + let aComponents = getScoreComponents(a.score), bComponents = getScoreComponents(b.score); + if (aComponents.hard < 0 && bComponents.hard > 0) return -1; + if (aComponents.hard > 0 && bComponents.soft < 0) return 1; + if (Math.abs(aComponents.hard) > Math.abs(bComponents.hard)) { + return -1; + } else { + if (aComponents.medium < 0 && bComponents.medium > 0) return -1; + if (aComponents.medium > 0 && bComponents.medium < 0) return 1; + if (Math.abs(aComponents.medium) > Math.abs(bComponents.medium)) { + return -1; + } else { + if (aComponents.soft < 0 && bComponents.soft > 0) return -1; + if (aComponents.soft > 0 && bComponents.soft < 0) return 1; + + return Math.abs(bComponents.soft) - Math.abs(aComponents.soft); + } + } + }); + constraints.map((e) => { + let components = getScoreComponents(e.weight); + e.type = components.hard != 0 ? 'hard' : (components.medium != 0 ? 'medium' : 'soft'); + e.weight = components[e.type]; + let scores = getScoreComponents(e.score); + e.implicitScore = scores.hard != 0 ? scores.hard : (scores.medium != 0 ? scores.medium : scores.soft); + }); + scoreAnalysis.constraints = constraints; + + scoreAnalysisModalContent.children().remove(); + scoreAnalysisModalContent.text(""); + + const analysisTable = $(``).css({textAlign: 'center'}); + const analysisTHead = $(``).append($(``) + .append($(``)) + .append($(``).css({textAlign: 'left'})) + .append($(``)) + .append($(``)) + .append($(``)) + .append($(``)) + .append($(``))); + analysisTable.append(analysisTHead); + const analysisTBody = $(``) + $.each(scoreAnalysis.constraints, (index, constraintAnalysis) => { + let icon = constraintAnalysis.type == "hard" && constraintAnalysis.implicitScore < 0 ? '' : ''; + if (!icon) icon = constraintAnalysis.matches.length == 0 ? '' : ''; + + let row = $(``); + row.append($(`
ConstraintType# MatchesWeightScore
`).html(icon)) + .append($(``).text(constraintAnalysis.name).css({textAlign: 'left'})) + .append($(``).text(constraintAnalysis.type)) + .append($(``).html(`${constraintAnalysis.matches.length}`)) + .append($(``).text(constraintAnalysis.weight)) + .append($(``).text(constraintAnalysis.implicitScore)); + analysisTBody.append(row); + row.append($(``)); + }); + analysisTable.append(analysisTBody); + scoreAnalysisModalContent.append(analysisTable); + }).fail(function (xhr, ajaxOptions, thrownError) { + showError("Analyze failed.", xhr); + }, "text"); + } +} + +function getScoreComponents(score) { + let components = {hard: 0, medium: 0, soft: 0}; + + $.each([...score.matchAll(/(-?\d*(\.\d+)?)(hard|medium|soft)/g)], (i, parts) => { + components[parts[3]] = parseFloat(parts[1], 10); + }); + + return components; +} + +function refreshSolvingButtons(solving) { + if (solving) { + $("#solveButton").hide(); + $("#stopSolvingButton").show(); + if (autoRefreshIntervalId == null) { + autoRefreshIntervalId = setInterval(refreshSchedule, 2000); + } + } else { + $("#solveButton").show(); + $("#stopSolvingButton").hide(); + if (autoRefreshIntervalId != null) { + clearInterval(autoRefreshIntervalId); + autoRefreshIntervalId = null; + } + } +} + +function refreshSolvingButtons(solving) { + if (solving) { + $("#solveButton").hide(); + $("#stopSolvingButton").show(); + if (autoRefreshIntervalId == null) { + autoRefreshIntervalId = setInterval(refreshSchedule, 2000); + } + } else { + $("#solveButton").show(); + $("#stopSolvingButton").hide(); + if (autoRefreshIntervalId != null) { + clearInterval(autoRefreshIntervalId); + autoRefreshIntervalId = null; + } + } +} + +function stopSolving() { + $.delete(`/schedules/${scheduleId}`, function () { + refreshSolvingButtons(false); + refreshSchedule(); + }).fail(function (xhr, ajaxOptions, thrownError) { + showError("Stop solving failed.", xhr); + }); +} + +function replaceQuickstartTimefoldAutoHeaderFooter() { + const timefoldHeader = $("header#timefold-auto-header"); + if (timefoldHeader != null) { + timefoldHeader.addClass("bg-black") + timefoldHeader.append( + $(`
+ +
`)); + } + + const timefoldFooter = $("footer#timefold-auto-footer"); + if (timefoldFooter != null) { + timefoldFooter.append( + $(``)); + } +} diff --git a/src/main/resources/META-INF/resources/index.html b/src/main/resources/META-INF/resources/index.html new file mode 100644 index 0000000..7c1b361 --- /dev/null +++ b/src/main/resources/META-INF/resources/index.html @@ -0,0 +1,161 @@ + + + + + Employee scheduling - Timefold Solver on Quarkus + + + + + + + + + + +
+ +
+
+
+
+
+
+

Employee scheduling solver

+

Generate the optimal schedule for your employees.

+ +
+ + + + Score: ? + + +
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+

REST API Guide

+ +

Employee Scheduling solver integration via cURL

+ +

1. Download demo data

+
+            
+            curl -X GET -H 'Accept:application/json' http://localhost:8080/demo-data/SMALL -o sample.json
+    
+ +

2. Post the sample data for solving

+

The POST operation returns a jobId that should be used in subsequent commands.

+
+            
+            curl -X POST -H 'Content-Type:application/json' http://localhost:8080/schedules -d@sample.json
+    
+ +

3. Get the current status and score

+
+            
+            curl -X GET -H 'Accept:application/json' http://localhost:8080/schedules/{jobId}/status
+    
+ +

4. Get the complete solution

+
+            
+            curl -X GET -H 'Accept:application/json' http://localhost:8080/schedules/{jobId}
+    
+ +

5. Fetch the analysis of the solution

+
+            
+            curl -X PUT -H 'Content-Type:application/json' http://localhost:8080/schedules/analyze -d@solution.json
+    
+ +

5. Terminate solving early

+
+            
+            curl -X DELETE -H 'Accept:application/json' http://localhost:8080/schedules/{id}
+    
+
+ +
+

REST API Reference

+
+ + +
+
+
+
+ + + + + + + + + + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..2e80d17 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,43 @@ +######################## +# Timefold Solver properties +######################## + +# The solver runs for 30 seconds. To run for 5 minutes use "5m" and for 2 hours use "2h". +quarkus.timefold.solver.termination.spent-limit=30s + +# To change how many solvers to run in parallel +# timefold.solver-manager.parallel-solver-count=4 + +# Temporary comment this out to detect bugs in your code (lowers performance) +# quarkus.timefold.solver.environment-mode=FULL_ASSERT + +# Temporary comment this out to return a feasible solution as soon as possible +# quarkus.timefold.solver.termination.best-score-limit=0hard/*soft + +# To see what Timefold is doing, turn on DEBUG or TRACE logging. +quarkus.log.category."ai.timefold.solver".level=INFO +%test.quarkus.log.category."ai.timefold.solver".level=INFO +%prod.quarkus.log.category."ai.timefold.solver".level=INFO + +# XML file for power tweaking, defaults to solverConfig.xml (directly under src/main/resources) +# quarkus.timefold.solver-config-xml=org/.../maintenanceScheduleSolverConfig.xml + +######################## +# Timefold Solver Enterprise properties +######################## + +# To run increase CPU cores usage per solver +%enterprise.quarkus.timefold.solver.move-thread-count=AUTO + +######################## +# Native build properties +######################## + +# Enable Swagger UI also in the native mode +quarkus.swagger-ui.always-include=true + +######################## +# Test overrides +######################## + +%test.quarkus.timefold.solver.termination.spent-limit=10s diff --git a/target/build-metrics.json b/target/build-metrics.json new file mode 100644 index 0000000..db0681a --- /dev/null +++ b/target/build-metrics.json @@ -0,0 +1 @@ +{"duration":1238,"records":[{"duration":413,"stepId":"io.quarkus.deployment.index.ApplicationArchiveBuildStep#build","started":"16:23:20.294","dependents":[374,275,273,307,276,436,337,272,418],"id":271,"thread":"build-42"},{"duration":291,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#build","started":"16:23:20.832","dependents":[439],"id":403,"thread":"build-6"},{"duration":171,"stepId":"io.quarkus.deployment.console.ConsoleProcessor#setupConsole","started":"16:23:20.193","dependents":[269,273,268,267],"id":266,"thread":"build-2"},{"duration":155,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#generateConfigClass","started":"16:23:20.193","dependents":[],"id":265,"thread":"build-38"},{"duration":152,"stepId":"io.quarkus.swaggerui.deployment.SwaggerUiProcessor#getSwaggerUiFinalDestination","started":"16:23:20.257","dependents":[405],"id":270,"thread":"build-32"},{"duration":140,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#createDevUILog","started":"16:23:20.197","dependents":[439,263,433],"id":258,"thread":"build-50"},{"duration":125,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#bodyHandler","started":"16:23:20.202","dependents":[439,433],"id":256,"thread":"build-27"},{"duration":111,"stepId":"io.quarkus.deployment.steps.BannerProcessor#recordBanner","started":"16:23:20.199","dependents":[439,332],"id":253,"thread":"build-51"},{"duration":107,"stepId":"io.quarkus.deployment.steps.MainClassBuildStep#build","started":"16:23:21.289","dependents":[],"id":439,"thread":"build-6"},{"duration":105,"stepId":"io.quarkus.arc.deployment.ArcProcessor#generateResources","started":"16:23:20.975","dependents":[389,438,418],"id":388,"thread":"build-2"},{"duration":99,"stepId":"io.quarkus.deployment.steps.ConfigDescriptionBuildStep#createConfigDescriptions","started":"16:23:20.193","dependents":[260,262,254],"id":244,"thread":"build-42"},{"duration":98,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#setupBlockingOperationSupport","started":"16:23:20.165","dependents":[439],"id":221,"thread":"build-3"},{"duration":92,"stepId":"io.quarkus.arc.deployment.ArcProcessor#registerBeans","started":"16:23:20.839","dependents":[365,354,356,359,355,368,360,357,370,362,366,363,361,415,358,367],"id":353,"thread":"build-62"},{"duration":91,"stepId":"io.quarkus.devui.deployment.menu.DependenciesProcessor#createAppDeps","started":"16:23:20.213","dependents":[404],"id":250,"thread":"build-39"},{"duration":91,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#dontPropagateCdiContext","started":"16:23:20.193","dependents":[439,242],"id":240,"thread":"build-11"},{"duration":89,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#getAllExtensions","started":"16:23:21.018","dependents":[402,401,404,405,406],"id":400,"thread":"build-90"},{"duration":88,"stepId":"io.quarkus.deployment.steps.ApplicationIndexBuildStep#build","started":"16:23:20.205","dependents":[271,252,360,357,352,408],"id":245,"thread":"build-60"},{"duration":88,"stepId":"io.quarkus.webdependency.locator.deployment.WebDependencyLocatorProcessor#findWebDependenciesAndCreateHandler","started":"16:23:20.206","dependents":[249,439,430,431],"id":247,"thread":"build-62"},{"duration":86,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#createBuildTimeConstJsTemplate","started":"16:23:21.128","dependents":[428,427],"id":426,"thread":"build-6"},{"duration":85,"stepId":"io.quarkus.jackson.deployment.JacksonProcessor#generateCustomizer","started":"16:23:20.719","dependents":[337],"id":336,"thread":"build-62"},{"duration":84,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#logConsoleCommand","started":"16:23:20.166","dependents":[412],"id":202,"thread":"build-8"},{"duration":84,"stepId":"io.quarkus.deployment.dev.io.NioThreadPoolDevModeProcessor#setupTCCL","started":"16:23:20.184","dependents":[439],"id":226,"thread":"build-33"},{"duration":82,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#createVertxThreadFactory","started":"16:23:20.193","dependents":[243,439],"id":236,"thread":"build-41"},{"duration":78,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#fileHandling","started":"16:23:20.189","dependents":[417,415],"id":224,"thread":"build-40"},{"duration":74,"stepId":"io.quarkus.smallrye.context.deployment.SmallRyeContextPropagationProcessor#buildStatic","started":"16:23:20.195","dependents":[439],"id":229,"thread":"build-21"},{"duration":74,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#configureLogging","started":"16:23:20.195","dependents":[439],"id":231,"thread":"build-34"},{"duration":73,"stepId":"io.quarkus.devui.deployment.menu.DevServicesProcessor#createDevServicesPages","started":"16:23:20.196","dependents":[404,264],"id":230,"thread":"build-14"},{"duration":72,"stepId":"io.quarkus.vertx.http.deployment.console.ConsoleProcessor#setupConsole","started":"16:23:20.196","dependents":[434],"id":227,"thread":"build-47"},{"duration":72,"stepId":"io.quarkus.deployment.steps.ReflectiveHierarchyStep#ignoreJavaClassWarnings","started":"16:23:20.190","dependents":[416],"id":217,"thread":"build-35"},{"duration":71,"stepId":"io.quarkus.mutiny.deployment.MutinyProcessor#buildTimeInit","started":"16:23:20.176","dependents":[439],"id":196,"thread":"build-16"},{"duration":71,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#resetMapper","started":"16:23:20.198","dependents":[439],"id":232,"thread":"build-44"},{"duration":70,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#registerFormAuthMechanism","started":"16:23:20.193","dependents":[439,368,366,367],"id":220,"thread":"build-17"},{"duration":70,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#beanDefiningAnnotations","started":"16:23:20.174","dependents":[352,337,228],"id":190,"thread":"build-9"},{"duration":69,"stepId":"io.quarkus.devui.deployment.build.BuildMetricsDevUIProcessor#create","started":"16:23:20.186","dependents":[439],"id":206,"thread":"build-32"},{"duration":69,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#ioThreadDetector","started":"16:23:20.201","dependents":[439,239],"id":233,"thread":"build-53"},{"duration":65,"stepId":"io.quarkus.devui.deployment.menu.ConfigurationProcessor#registerBuildTimeActions","started":"16:23:20.169","dependents":[439,368,366,264,367],"id":186,"thread":"build-7"},{"duration":65,"stepId":"io.quarkus.deployment.steps.DevServicesConfigBuildStep#setup","started":"16:23:20.190","dependents":[260,384,262,254,270,434],"id":207,"thread":"build-22"},{"duration":65,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#recordAndRegisterBuildTimeBeans","started":"16:23:20.720","dependents":[416,368,366,334,352,337,373,335,367,379,418],"id":333,"thread":"build-20"},{"duration":64,"stepId":"io.quarkus.devui.deployment.menu.BuildMetricsProcessor#create","started":"16:23:20.166","dependents":[439],"id":182,"thread":"build-12"},{"duration":63,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#eventLoopCount","started":"16:23:20.195","dependents":[437,439],"id":212,"thread":"build-37"},{"duration":63,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#releaseConfigOnShutdown","started":"16:23:20.170","dependents":[439],"id":183,"thread":"build-15"},{"duration":60,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#initBasicAuth","started":"16:23:20.202","dependents":[439,351,368,366,349,367],"id":218,"thread":"build-54"},{"duration":56,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#jsonDefault","started":"16:23:20.188","dependents":[408],"id":191,"thread":"build-28"},{"duration":56,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#cors","started":"16:23:20.207","dependents":[439,433,424],"id":222,"thread":"build-66"},{"duration":56,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#setupEndpoints","started":"16:23:21.087","dependents":[439,416,409,415,438,418,411,419],"id":408,"thread":"build-82"},{"duration":56,"stepId":"io.quarkus.netty.deployment.NettyProcessor#build","started":"16:23:20.204","dependents":[234,438],"id":214,"thread":"build-4"},{"duration":56,"stepId":"io.quarkus.virtual.threads.deployment.VirtualThreadsProcessor#setup","started":"16:23:20.207","dependents":[439,368,366,352,337,367],"id":219,"thread":"build-65"},{"duration":56,"stepId":"io.quarkus.netty.deployment.NettyProcessor#eagerlyInitClass","started":"16:23:20.190","dependents":[439],"id":194,"thread":"build-24"},{"duration":55,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#reportDeprecatedMappingProperties","started":"16:23:20.202","dependents":[439],"id":210,"thread":"build-36"},{"duration":55,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#currentContextFactory","started":"16:23:20.193","dependents":[439,389],"id":199,"thread":"build-6"},{"duration":54,"stepId":"io.quarkus.devui.deployment.menu.WorkspaceProcessor#locateWorkspaceItems","started":"16:23:20.194","dependents":[237],"id":200,"thread":"build-5"},{"duration":52,"stepId":"io.quarkus.webdependency.locator.deployment.devui.WebDependencyLocatorDevModeApiProcessor#findWebDependenciesAssets","started":"16:23:20.209","dependents":[249],"id":215,"thread":"build-30"},{"duration":51,"stepId":"io.quarkus.vertx.http.deployment.GeneratedStaticResourcesProcessor#process","started":"16:23:20.197","dependents":[439,430,431,436],"id":197,"thread":"build-49"},{"duration":51,"stepId":"io.quarkus.devui.deployment.menu.MCPProcessor#registerDevUiHandlers","started":"16:23:20.195","dependents":[439,430,431],"id":195,"thread":"build-46"},{"duration":50,"stepId":"io.quarkus.devui.deployment.menu.ExtensionsProcessor#createBuildTimeActions","started":"16:23:20.199","dependents":[264],"id":198,"thread":"build-52"},{"duration":49,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#registerRPCService","started":"16:23:20.204","dependents":[235,300,241],"id":203,"thread":"build-18"},{"duration":49,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setupLoggingStaticInit","started":"16:23:20.205","dependents":[439],"id":204,"thread":"build-56"},{"duration":48,"stepId":"io.quarkus.deployment.steps.DevModeBuildStep#watchChanges","started":"16:23:20.206","dependents":[238],"id":205,"thread":"build-63"},{"duration":48,"stepId":"io.quarkus.devui.deployment.ide.IdeProcessor#createOpenInIDEService","started":"16:23:20.197","dependents":[439,430,431,264],"id":193,"thread":"build-48"},{"duration":47,"stepId":"io.quarkus.vertx.http.deployment.console.ConsoleProcessor#config","started":"16:23:20.307","dependents":[412],"id":262,"thread":"build-8"},{"duration":45,"stepId":"io.quarkus.deployment.steps.ClassPathSystemPropBuildStep#set","started":"16:23:20.212","dependents":[439],"id":209,"thread":"build-59"},{"duration":45,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#createHttpAuthenticationHandler","started":"16:23:20.222","dependents":[439,225,396],"id":223,"thread":"build-31"},{"duration":44,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#checkForBuildTimeConfigChange","started":"16:23:20.206","dependents":[439],"id":201,"thread":"build-61"},{"duration":44,"stepId":"io.quarkus.devui.deployment.menu.ConfigurationProcessor#registerConfigs","started":"16:23:20.294","dependents":[439],"id":260,"thread":"build-61"},{"duration":44,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#build_ab8f5337a8a378f6d88c5272f38f49e13900f727","started":"16:23:20.293","dependents":[437,439,393,368,431,366,364,259,433,434,261,367],"id":257,"thread":"build-6"},{"duration":41,"stepId":"io.quarkus.deployment.steps.PreloadClassesBuildStep#preInit","started":"16:23:20.186","dependents":[439],"id":181,"thread":"build-23"},{"duration":40,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setupLoggingRuntimeInit","started":"16:23:20.721","dependents":[435,439,438],"id":332,"thread":"build-44"},{"duration":39,"stepId":"io.quarkus.vertx.http.deployment.GeneratedStaticResourcesProcessor#produceResources","started":"16:23:20.197","dependents":[216],"id":188,"thread":"build-19"},{"duration":38,"stepId":"io.quarkus.deployment.pkg.steps.JarResultBuildStep#outputTarget","started":"16:23:20.195","dependents":[273,189,187,403],"id":184,"thread":"build-45"},{"duration":37,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#checkMixingStacks","started":"16:23:20.222","dependents":[434],"id":213,"thread":"build-20"},{"duration":37,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#registerDevUiHandlers","started":"16:23:21.243","dependents":[439,430,431],"id":429,"thread":"build-2"},{"duration":36,"stepId":"io.quarkus.deployment.SslProcessor#setupNativeSsl","started":"16:23:20.197","dependents":[234],"id":185,"thread":"build-29"},{"duration":34,"stepId":"io.quarkus.vertx.http.deployment.ManagementInterfaceSecurityProcessor#createManagementAuthMechHandler","started":"16:23:20.222","dependents":[439,395,211],"id":208,"thread":"build-10"},{"duration":31,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#additionalBean","started":"16:23:20.254","dependents":[275,352,337],"id":241,"thread":"build-61"},{"duration":29,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#generateMappings","started":"16:23:20.723","dependents":[356,376,358,438,379],"id":330,"thread":"build-60"},{"duration":29,"stepId":"io.quarkus.smallrye.context.deployment.SmallRyeContextPropagationProcessor#build","started":"16:23:20.294","dependents":[439,368,366,367],"id":255,"thread":"build-44"},{"duration":29,"stepId":"io.quarkus.deployment.steps.RuntimeConfigSetupBuildStep#setupRuntimeConfig","started":"16:23:20.161","dependents":[369,231,257,375,434,349,253,243,240,437,232,242,261,218,422,365,197,407,220,431,212,334,433,396,421,332,432,435,439,393,222,258,236,424,335,395,256,398],"id":126,"thread":"build-2"},{"duration":28,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#createIndexHtmlTemplate","started":"16:23:21.214","dependents":[428],"id":427,"thread":"build-2"},{"duration":26,"stepId":"io.quarkus.arc.deployment.ArcProcessor#buildCompatibleExtensions","started":"16:23:20.166","dependents":[352,337],"id":132,"thread":"build-6"},{"duration":23,"stepId":"io.quarkus.arc.deployment.ArcProcessor#validate","started":"16:23:20.949","dependents":[374,385,388,375,377,381,376,378,379,418],"id":373,"thread":"build-60"},{"duration":23,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#addRoutingCtxToSecurityEventsForCdiBeans","started":"16:23:20.222","dependents":[439],"id":192,"thread":"build-25"},{"duration":22,"stepId":"io.quarkus.devui.deployment.menu.WorkspaceProcessor#createBuildTimeActions","started":"16:23:20.254","dependents":[264],"id":237,"thread":"build-6"},{"duration":22,"stepId":"io.quarkus.vertx.http.deployment.webjar.WebJarProcessor#processWebJarDevMode","started":"16:23:21.109","dependents":[439,407,406],"id":405,"thread":"build-57"},{"duration":21,"stepId":"io.quarkus.arc.deployment.devui.JsonRpcMethodsProcessor#jsonRpcMethods","started":"16:23:20.254","dependents":[342],"id":235,"thread":"build-8"},{"duration":21,"stepId":"io.quarkus.deployment.dev.HotDeploymentWatchedFileBuildStep#setupWatchedFileHotDeployment","started":"16:23:20.255","dependents":[434],"id":238,"thread":"build-56"},{"duration":21,"stepId":"io.quarkus.deployment.console.ConsoleProcessor#helpCommand","started":"16:23:20.168","dependents":[412],"id":122,"thread":"build-10"},{"duration":20,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#autoAddScope","started":"16:23:20.186","dependents":[343],"id":163,"thread":"build-25"},{"duration":19,"stepId":"io.quarkus.vertx.http.deployment.StaticResourcesProcessor#collectStaticResources","started":"16:23:20.243","dependents":[393],"id":216,"thread":"build-12"},{"duration":19,"stepId":"io.quarkus.arc.deployment.LoggingBeanSupportProcessor#discoveredComponents","started":"16:23:20.175","dependents":[352,337,228],"id":145,"thread":"build-20"},{"duration":18,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#createBuildTimeData","started":"16:23:21.109","dependents":[426,427],"id":404,"thread":"build-90"},{"duration":18,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#handleCustomAnnotatedMethods","started":"16:23:20.730","dependents":[331,352,337,329],"id":328,"thread":"build-56"},{"duration":18,"stepId":"io.quarkus.deployment.recording.substitutions.AdditionalSubstitutionsBuildStep#additionalSubstitutions","started":"16:23:20.190","dependents":[439],"id":166,"thread":"build-39"},{"duration":18,"stepId":"io.quarkus.devui.deployment.menu.ConfigurationProcessor#createConfigurationPages","started":"16:23:20.312","dependents":[404],"id":254,"thread":"build-20"},{"duration":18,"stepId":"io.quarkus.arc.deployment.devui.ArcDevModeApiProcessor#collectBeanInfo","started":"16:23:20.973","dependents":[386],"id":385,"thread":"build-40"},{"duration":18,"stepId":"io.quarkus.arc.deployment.ShutdownBuildSteps#addScope","started":"16:23:20.189","dependents":[343],"id":167,"thread":"build-30"},{"duration":17,"stepId":"io.quarkus.arc.deployment.BeanArchiveProcessor#build","started":"16:23:20.805","dependents":[346,399,339,352,345,362,341,338,363,347,415,340,408,343],"id":337,"thread":"build-6"},{"duration":17,"stepId":"io.quarkus.arc.deployment.StartupBuildSteps#addScope","started":"16:23:20.190","dependents":[343],"id":164,"thread":"build-31"},{"duration":16,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#buildTimeRunTimeConfig","started":"16:23:20.195","dependents":[384,438],"id":171,"thread":"build-10"},{"duration":16,"stepId":"io.quarkus.deployment.ide.IdeProcessor#detectRunningIdeProcesses","started":"16:23:20.175","dependents":[136],"id":131,"thread":"build-19"},{"duration":16,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#registerMetrics","started":"16:23:20.197","dependents":[439,332],"id":172,"thread":"build-20"},{"duration":16,"stepId":"io.quarkus.deployment.console.ConsoleProcessor#quitCommand","started":"16:23:20.173","dependents":[412],"id":120,"thread":"build-5"},{"duration":16,"stepId":"io.quarkus.arc.deployment.devui.ArcDevUIProcessor#registerMonitoringComponents","started":"16:23:20.252","dependents":[352,337],"id":228,"thread":"build-15"},{"duration":15,"stepId":"io.quarkus.deployment.steps.CapabilityAggregationStep#provideCapabilities","started":"16:23:20.205","dependents":[175],"id":174,"thread":"build-58"},{"duration":14,"stepId":"io.quarkus.devui.deployment.menu.WorkspaceProcessor#createDefaultWorkspaceActions","started":"16:23:20.184","dependents":[237],"id":155,"thread":"build-18"},{"duration":14,"stepId":"io.quarkus.deployment.recording.AnnotationProxyBuildStep#build","started":"16:23:20.307","dependents":[364],"id":252,"thread":"build-53"},{"duration":14,"stepId":"io.quarkus.deployment.steps.CompiledJavaVersionBuildStep#compiledJavaVersion","started":"16:23:20.204","dependents":[408],"id":173,"thread":"build-57"},{"duration":14,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#setupDeployment","started":"16:23:21.158","dependents":[422,439,430,431,423,433,424,421,438,420],"id":419,"thread":"build-2"},{"duration":13,"stepId":"io.quarkus.deployment.steps.ClassTransformingBuildStep#handleClassTransformation","started":"16:23:21.147","dependents":[],"id":418,"thread":"build-83"},{"duration":13,"stepId":"io.quarkus.arc.deployment.ArcProcessor#setupExecutor","started":"16:23:20.302","dependents":[439],"id":251,"thread":"build-56"},{"duration":13,"stepId":"io.quarkus.arc.deployment.ArcProcessor#initialize","started":"16:23:20.825","dependents":[385,363,353],"id":352,"thread":"build-20"},{"duration":12,"stepId":"io.quarkus.deployment.steps.ApplicationInfoBuildStep#create","started":"16:23:20.195","dependents":[439],"id":162,"thread":"build-43"},{"duration":12,"stepId":"io.quarkus.mutiny.deployment.MutinyDevUIProcessor#createCard","started":"16:23:20.186","dependents":[400,387],"id":156,"thread":"build-36"},{"duration":11,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#resolveRolesAllowedConfigExpressions","started":"16:23:20.719","dependents":[439,368,375,366,367],"id":313,"thread":"build-50"},{"duration":11,"stepId":"io.quarkus.arc.deployment.SplitPackageProcessor#splitPackageDetection","started":"16:23:20.708","dependents":[388],"id":276,"thread":"build-8"},{"duration":11,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#serverSerializers","started":"16:23:21.146","dependents":[439,438,419],"id":417,"thread":"build-82"},{"duration":11,"stepId":"io.quarkus.deployment.ExtensionLoader#config","started":"16:23:20.180","dependents":[134,269,231,141,266,136,240,245,157,426,376,171,427,271,139,220,225,334,135,265,152,276,236,160,270,138,395,199,386,244,369,306,308,381,345,434,228,419,243,437,140,154,143,330,144,365,197,223,200,385,146,162,212,396,352,184,432,148,150,439,307,230,151,158,258,172,320,337,344,408,403,153,274,208,402,351,257,360,389,357,349,185,253,232,404,242,261,234,379,215,297,198,431,433,332,211,233,418,159,429,424,335,256,210,161,273,384,247,350,218,203,422,214,407,204,388,333,165,201,205,303,189,219,421,192,435,393,222,168,405,342,398],"id":130,"thread":"build-26"},{"duration":11,"stepId":"io.quarkus.arc.deployment.devui.ArcDevUIProcessor#pages","started":"16:23:20.995","dependents":[400,387],"id":386,"thread":"build-68"},{"duration":10,"stepId":"io.quarkus.vertx.deployment.VertxJsonProcessor#registerJacksonSerDeser","started":"16:23:20.169","dependents":[336],"id":54,"thread":"build-14"},{"duration":10,"stepId":"io.quarkus.deployment.steps.CombinedIndexBuildStep#build","started":"16:23:20.708","dependents":[283,336,300,286,314,311,289,288,410,290,315,305,358,323,297,332,321,277,301,293,313,278,331,306,356,308,294,339,285,291,292,317,384,287,330,279,333,319,281,352,303,295,284,307,416,282,347,280,328,342],"id":275,"thread":"build-32"},{"duration":10,"stepId":"io.quarkus.deployment.steps.ReflectiveHierarchyStep#build","started":"16:23:21.144","dependents":[438],"id":416,"thread":"build-90"},{"duration":9,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#overrideContextInternalInterfaceToAddSafeGuards","started":"16:23:20.187","dependents":[418],"id":149,"thread":"build-29"},{"duration":9,"stepId":"io.quarkus.deployment.steps.NativeImageConfigBuildStep#build","started":"16:23:20.261","dependents":[439],"id":234,"thread":"build-20"},{"duration":8,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#findAllJsonRPCMethods","started":"16:23:20.718","dependents":[426,397],"id":300,"thread":"build-6"},{"duration":8,"stepId":"io.quarkus.arc.deployment.SyntheticBeansProcessor#initRuntime","started":"16:23:20.939","dependents":[369,439,370,434],"id":368,"thread":"build-60"},{"duration":8,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#indexDependencyBuildItem","started":"16:23:20.193","dependents":[271],"id":160,"thread":"build-4"},{"duration":7,"stepId":"io.quarkus.deployment.steps.MainClassBuildStep#mainClassBuildStep","started":"16:23:20.722","dependents":[418],"id":307,"thread":"build-15"},{"duration":7,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#watchSolverConfigXml","started":"16:23:20.192","dependents":[238],"id":157,"thread":"build-27"},{"duration":7,"stepId":"io.quarkus.arc.deployment.ArcProcessor#quarkusMain","started":"16:23:20.165","dependents":[352,337,228],"id":34,"thread":"build-9"},{"duration":7,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#registerAuthMechanismSelectionInterceptor","started":"16:23:20.721","dependents":[439,360,320,305],"id":303,"thread":"build-34"},{"duration":6,"stepId":"io.quarkus.arc.deployment.ArcProcessor#loggerProducer","started":"16:23:20.177","dependents":[352,337],"id":79,"thread":"build-4"},{"duration":6,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setupStackTraceFormatter","started":"16:23:20.708","dependents":[274,433,332],"id":273,"thread":"build-38"},{"duration":6,"stepId":"io.quarkus.deployment.steps.BlockingOperationControlBuildStep#blockingOP","started":"16:23:20.270","dependents":[439],"id":239,"thread":"build-44"},{"duration":6,"stepId":"io.quarkus.deployment.dev.testing.TestTracingProcessor#testConsoleCommand","started":"16:23:20.721","dependents":[412],"id":301,"thread":"build-27"},{"duration":6,"stepId":"io.quarkus.arc.deployment.ConfigStaticInitBuildSteps#registerBeans","started":"16:23:20.186","dependents":[352,337],"id":133,"thread":"build-21"},{"duration":6,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#addAutoFilters","started":"16:23:20.826","dependents":[403],"id":351,"thread":"build-62"},{"duration":6,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#responseHeaderSupport","started":"16:23:20.179","dependents":[408],"id":97,"thread":"build-28"},{"duration":6,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#generateBuilders","started":"16:23:20.975","dependents":[438],"id":384,"thread":"build-56"},{"duration":6,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#additionalBean","started":"16:23:20.177","dependents":[352,337],"id":78,"thread":"build-17"},{"duration":6,"stepId":"io.quarkus.credentials.deployment.CredentialsProcessor#unremoveable","started":"16:23:20.177","dependents":[373,379],"id":77,"thread":"build-21"},{"duration":5,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#registerAnnotatedUserDefinedRuntimeFilters","started":"16:23:20.826","dependents":[439,368,366,367,438],"id":350,"thread":"build-6"},{"duration":5,"stepId":"io.quarkus.arc.deployment.HotDeploymentConfigBuildStep#startup","started":"16:23:20.179","dependents":[95],"id":92,"thread":"build-27"},{"duration":5,"stepId":"io.quarkus.vertx.http.deployment.GeneratedStaticResourcesProcessor#devMode","started":"16:23:20.186","dependents":[238,197,188],"id":128,"thread":"build-34"},{"duration":5,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#securityContextOverrideHandler","started":"16:23:20.190","dependents":[419],"id":147,"thread":"build-14"},{"duration":5,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#shouldNotRemoveHttpServerOptionsCustomizers","started":"16:23:20.179","dependents":[373,379],"id":87,"thread":"build-23"},{"duration":5,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#gatherMvnpmJars","started":"16:23:20.203","dependents":[429,427],"id":169,"thread":"build-55"},{"duration":5,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setUpDefaultLogCleanupFilters","started":"16:23:20.179","dependents":[384],"id":93,"thread":"build-24"},{"duration":5,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#runtimeOverrideConfig","started":"16:23:20.179","dependents":[384],"id":91,"thread":"build-25"},{"duration":5,"stepId":"io.quarkus.resteasy.reactive.server.deployment.devui.ResteasyReactiveDevUIProcessor#createJsonRPCService","started":"16:23:20.188","dependents":[235,300,241],"id":142,"thread":"build-37"},{"duration":4,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#contextInjection","started":"16:23:20.187","dependents":[352,337,373,344,343,379],"id":129,"thread":"build-4"},{"duration":4,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#scanResources","started":"16:23:20.723","dependents":[326,309,346,399,352,318,304,419,325,410,328,327,408,312,322,310],"id":302,"thread":"build-66"},{"duration":4,"stepId":"io.quarkus.resteasy.reactive.server.deployment.devui.ResteasyReactiveDevUIProcessor#createPages","started":"16:23:20.178","dependents":[400,387],"id":71,"thread":"build-11"},{"duration":4,"stepId":"io.quarkus.netty.deployment.NettyProcessor#setNettyMachineId","started":"16:23:20.187","dependents":[439],"id":127,"thread":"build-13"},{"duration":4,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#asyncSupport","started":"16:23:20.179","dependents":[408],"id":82,"thread":"build-13"},{"duration":4,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#responseStatusSupport","started":"16:23:20.177","dependents":[408],"id":67,"thread":"build-22"},{"duration":4,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#filterMultipleVertxInstancesWarning","started":"16:23:20.173","dependents":[93,332],"id":49,"thread":"build-13"},{"duration":4,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#createJsonRpcRouter","started":"16:23:21.086","dependents":[439],"id":397,"thread":"build-7"},{"duration":4,"stepId":"io.quarkus.deployment.steps.ThreadPoolSetup#createExecutor","started":"16:23:20.289","dependents":[255,248,439,251,257,433,246],"id":243,"thread":"build-61"},{"duration":4,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#unknownConfigFiles","started":"16:23:20.708","dependents":[439],"id":272,"thread":"build-6"},{"duration":4,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForExceptionMappers","started":"16:23:20.748","dependents":[352,337,438,419],"id":331,"thread":"build-6"},{"duration":4,"stepId":"io.quarkus.arc.deployment.CommandLineArgumentsProcessor#commandLineArgs","started":"16:23:20.189","dependents":[368,366,352,337,367],"id":137,"thread":"build-38"},{"duration":4,"stepId":"io.quarkus.vertx.http.deployment.devmode.NotFoundProcessor#routeNotFound","started":"16:23:21.283","dependents":[439],"id":436,"thread":"build-6"},{"duration":4,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setUpDefaultLevels","started":"16:23:20.175","dependents":[384,332],"id":53,"thread":"build-18"},{"duration":3,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#preinitializeRouter","started":"16:23:20.338","dependents":[439,368,431,366,367],"id":261,"thread":"build-44"},{"duration":3,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#setupEndpoints","started":"16:23:21.089","dependents":[417,415,414,438],"id":399,"thread":"build-83"},{"duration":3,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#scanForParameterContainers","started":"16:23:20.729","dependents":[325],"id":323,"thread":"build-42"},{"duration":3,"stepId":"io.quarkus.deployment.dev.testing.TestTracingProcessor#startTesting","started":"16:23:20.364","dependents":[434,332],"id":269,"thread":"build-38"},{"duration":3,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#handleApplication","started":"16:23:20.725","dependents":[331,323,319,314,399,329,311,419,321,317,417,315,408,438],"id":306,"thread":"build-40"},{"duration":3,"stepId":"io.quarkus.arc.deployment.staticmethods.InterceptedStaticMethodsProcessor#collectInterceptedStaticMethods","started":"16:23:20.932","dependents":[394,363,373,379],"id":362,"thread":"build-40"},{"duration":3,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#smallryeOpenApiIndex","started":"16:23:20.823","dependents":[351,350,348,403,349],"id":347,"thread":"build-56"},{"duration":3,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#finalizeRouter","started":"16:23:21.283","dependents":[435,439,434],"id":433,"thread":"build-2"},{"duration":3,"stepId":"io.quarkus.webdependency.locator.deployment.devui.WebDependencyLocatorDevUIProcessor#createPages","started":"16:23:20.295","dependents":[400,387],"id":249,"thread":"build-60"},{"duration":3,"stepId":"io.quarkus.jackson.deployment.JacksonProcessor#jacksonSupport","started":"16:23:20.721","dependents":[439,368,366,367],"id":297,"thread":"build-2"},{"duration":3,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#additionalReflection","started":"16:23:21.146","dependents":[438],"id":415,"thread":"build-57"},{"duration":2,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#processFooterLogs","started":"16:23:20.342","dependents":[400,264,387],"id":263,"thread":"build-6"},{"duration":2,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#recordAndRegisterDevUIBean","started":"16:23:20.785","dependents":[439,368,366,367],"id":334,"thread":"build-44"},{"duration":2,"stepId":"io.quarkus.netty.deployment.NettyProcessor#registerQualifiers","started":"16:23:20.186","dependents":[352,337],"id":116,"thread":"build-31"},{"duration":2,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#registerAutoSecurityFilter","started":"16:23:20.827","dependents":[439,368,366,367],"id":349,"thread":"build-44"},{"duration":2,"stepId":"io.quarkus.vertx.http.deployment.devmode.ArcDevProcessor#registerRoutes","started":"16:23:20.973","dependents":[388,439,430,431,436],"id":381,"thread":"build-42"},{"duration":2,"stepId":"io.quarkus.arc.deployment.ArcProcessor#marker","started":"16:23:20.187","dependents":[271],"id":117,"thread":"build-30"},{"duration":2,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#initializeHttpSecurity","started":"16:23:21.088","dependents":[439,433,398,432],"id":396,"thread":"build-2"},{"duration":2,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#buildResourceInterceptors","started":"16:23:20.748","dependents":[346,352,337,415,408,419],"id":329,"thread":"build-40"},{"duration":2,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#ifBuildProperty","started":"16:23:20.720","dependents":[306,299,298],"id":293,"thread":"build-32"},{"duration":2,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#beans","started":"16:23:20.172","dependents":[352,337],"id":42,"thread":"build-17"},{"duration":2,"stepId":"io.quarkus.jackson.deployment.JacksonProcessor#unremovable","started":"16:23:20.718","dependents":[352,337,373,379],"id":286,"thread":"build-38"},{"duration":2,"stepId":"io.quarkus.arc.deployment.ArcProcessor#notifyBeanContainerListeners","started":"16:23:21.083","dependents":[439,391],"id":390,"thread":"build-81"},{"duration":2,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#recordAndRegisterRuntimeBeans","started":"16:23:20.785","dependents":[439,368,366,367],"id":335,"thread":"build-6"},{"duration":2,"stepId":"io.quarkus.vertx.http.deployment.StaticResourcesProcessor#runtimeInit","started":"16:23:21.087","dependents":[439,433],"id":393,"thread":"build-56"},{"duration":2,"stepId":"io.quarkus.deployment.steps.DevServicesConfigBuildStep#deprecated","started":"16:23:20.188","dependents":[207],"id":125,"thread":"build-11"},{"duration":2,"stepId":"io.quarkus.arc.deployment.SyntheticBeansProcessor#initStatic","started":"16:23:20.939","dependents":[439,370],"id":367,"thread":"build-51"},{"duration":2,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#vertxIntegration","started":"16:23:20.165","dependents":[417,415,414],"id":21,"thread":"build-4"},{"duration":2,"stepId":"io.quarkus.smallrye.openapi.deployment.devui.OpenApiDevUIProcessor#pages","started":"16:23:20.198","dependents":[400,387],"id":158,"thread":"build-13"},{"duration":2,"stepId":"io.quarkus.arc.deployment.ConfigStaticInitBuildSteps#transformConfigProducer","started":"16:23:20.183","dependents":[352],"id":101,"thread":"build-17"},{"duration":2,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#registerConfigClasses","started":"16:23:20.974","dependents":[439],"id":383,"thread":"build-34"},{"duration":2,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#collectEventConsumers","started":"16:23:20.932","dependents":[364,370],"id":361,"thread":"build-34"},{"duration":2,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#transformEndpoints","started":"16:23:20.823","dependents":[352],"id":346,"thread":"build-62"},{"duration":2,"stepId":"io.quarkus.devui.deployment.logstream.LogStreamProcessor#registerBuildTimeActions","started":"16:23:20.181","dependents":[264],"id":75,"thread":"build-30"},{"duration":2,"stepId":"io.quarkus.arc.deployment.ArcProcessor#exposeCustomScopeNames","started":"16:23:20.187","dependents":[167,164,357,352,337,345,343,228],"id":118,"thread":"build-27"},{"duration":2,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#registerSafeDuplicatedContextInterceptor","started":"16:23:20.187","dependents":[352,337],"id":119,"thread":"build-24"},{"duration":2,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#mapPageBuildTimeData","started":"16:23:21.018","dependents":[426],"id":387,"thread":"build-82"},{"duration":2,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#additionalAsyncTypeMethodScanners","started":"16:23:20.161","dependents":[408],"id":7,"thread":"build-4"},{"duration":2,"stepId":"io.quarkus.arc.deployment.devui.ArcDevUIProcessor#createJsonRPCService","started":"16:23:20.182","dependents":[235,300,241],"id":90,"thread":"build-29"},{"duration":2,"stepId":"io.quarkus.arc.deployment.ArcProcessor#initializeContainer","started":"16:23:21.080","dependents":[439,390],"id":389,"thread":"build-80"},{"duration":2,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#build","started":"16:23:20.934","dependents":[365,439,434],"id":364,"thread":"build-60"},{"duration":1,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveDevModeProcessor#openCommand","started":"16:23:21.144","dependents":[412],"id":411,"thread":"build-57"},{"duration":1,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#registerOpenApiSchemaClassesForReflection","started":"16:23:20.828","dependents":[416,438],"id":348,"thread":"build-51"},{"duration":1,"stepId":"io.quarkus.deployment.JniProcessor#setupJni","started":"16:23:20.206","dependents":[234],"id":165,"thread":"build-59"},{"duration":1,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#additionalBeans","started":"16:23:20.731","dependents":[352,337,438],"id":324,"thread":"build-6"},{"duration":1,"stepId":"io.quarkus.devui.deployment.menu.ContinuousTestingProcessor#createJsonRPCService","started":"16:23:20.162","dependents":[235,300,241],"id":2,"thread":"build-5"},{"duration":1,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#configFiles","started":"16:23:20.234","dependents":[238],"id":189,"thread":"build-15"},{"duration":1,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#unremovableBeans","started":"16:23:20.163","dependents":[373,379],"id":9,"thread":"build-6"},{"duration":1,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#additionalProviders","started":"16:23:21.145","dependents":[417,415,414],"id":413,"thread":"build-83"},{"duration":1,"stepId":"io.quarkus.arc.deployment.ArcProcessor#registerSyntheticObservers","started":"16:23:20.947","dependents":[388,372,373,371,438,379],"id":370,"thread":"build-40"},{"duration":1,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#build_9d6b7122fb368970c50c3a870d1f672392cd8afb","started":"16:23:20.180","dependents":[234,438],"id":66,"thread":"build-14"},{"duration":1,"stepId":"io.quarkus.vertx.http.deployment.ManagementInterfaceSecurityProcessor#setupAuthenticationMechanisms","started":"16:23:20.257","dependents":[439,433,352,337],"id":211,"thread":"build-22"},{"duration":1,"stepId":"io.quarkus.vertx.deployment.EventConsumerMethodsProcessor#eventConsumerMethods","started":"16:23:20.161","dependents":[342],"id":1,"thread":"build-3"},{"duration":1,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#compressionSupport","started":"16:23:20.195","dependents":[408],"id":152,"thread":"build-19"},{"duration":1,"stepId":"io.quarkus.devui.deployment.menu.ContinuousTestingProcessor#continuousTestingState","started":"16:23:21.087","dependents":[439],"id":392,"thread":"build-78"},{"duration":1,"stepId":"io.quarkus.arc.deployment.AutoProducerMethodsProcessor#annotationTransformer","started":"16:23:20.823","dependents":[352],"id":345,"thread":"build-20"},{"duration":1,"stepId":"io.quarkus.netty.deployment.NettyProcessor#cleanupUnsafeLog","started":"16:23:20.168","dependents":[93,332],"id":27,"thread":"build-13"},{"duration":1,"stepId":"io.quarkus.arc.deployment.ArcProcessor#unremovableAsyncObserverExceptionHandlers","started":"16:23:20.167","dependents":[373,379],"id":22,"thread":"build-11"},{"duration":1,"stepId":"io.quarkus.arc.deployment.AutoAddScopeProcessor#annotationTransformer","started":"16:23:20.823","dependents":[352,373,379],"id":343,"thread":"build-51"},{"duration":1,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#detectBasicAuthImplicitlyRequired","started":"16:23:20.933","dependents":[439],"id":360,"thread":"build-60"},{"duration":1,"stepId":"io.quarkus.devui.deployment.logstream.LogStreamProcessor#handler","started":"16:23:20.714","dependents":[439,332],"id":274,"thread":"build-6"},{"duration":1,"stepId":"io.quarkus.devui.deployment.menu.ContinuousTestingProcessor#createContinuousTestingPages","started":"16:23:20.171","dependents":[404],"id":32,"thread":"build-16"},{"duration":1,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#handler","started":"16:23:21.173","dependents":[439,436,425],"id":424,"thread":"build-90"},{"duration":1,"stepId":"io.quarkus.swaggerui.deployment.SwaggerUiProcessor#feature","started":"16:23:20.194","dependents":[439],"id":146,"thread":"build-44"},{"duration":1,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#initializeRouter","started":"16:23:21.281","dependents":[439,436,433,432],"id":431,"thread":"build-90"},{"duration":1,"stepId":"io.quarkus.devui.deployment.menu.ContinuousTestingProcessor#registerBuildTimeActions","started":"16:23:20.185","dependents":[264],"id":102,"thread":"build-35"},{"duration":1,"stepId":"io.quarkus.arc.deployment.ReflectiveBeanClassesProcessor#implicitReflectiveBeanClasses","started":"16:23:20.933","dependents":[388],"id":359,"thread":"build-51"},{"duration":1,"stepId":"io.quarkus.arc.deployment.staticmethods.InterceptedStaticMethodsProcessor#callInitializer","started":"16:23:21.088","dependents":[439],"id":394,"thread":"build-81"},{"duration":1,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#setMtlsCertificateRoleProperties","started":"16:23:21.090","dependents":[439],"id":398,"thread":"build-57"},{"duration":1,"stepId":"io.quarkus.deployment.steps.RegisterForReflectionBuildStep#build","started":"16:23:20.720","dependents":[416,438],"id":288,"thread":"build-8"},{"duration":1,"stepId":"io.quarkus.deployment.steps.ShutdownListenerBuildStep#setupShutdown","started":"16:23:21.287","dependents":[439],"id":435,"thread":"build-83"},{"duration":1,"stepId":"io.quarkus.deployment.dev.testing.TestTracingProcessor#handle","started":"16:23:20.171","dependents":[93,332],"id":36,"thread":"build-4"},{"duration":1,"stepId":"io.quarkus.arc.deployment.WrongAnnotationUsageProcessor#detect","started":"16:23:20.932","dependents":[388],"id":357,"thread":"build-42"},{"duration":1,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#registerConfigMappingsBean","started":"16:23:20.932","dependents":[370],"id":358,"thread":"build-2"},{"duration":1,"stepId":"io.quarkus.swaggerui.deployment.SwaggerUiProcessor#registerSwaggerUiHandler","started":"16:23:21.132","dependents":[439,430,431],"id":407,"thread":"build-90"},{"duration":1,"stepId":"io.quarkus.tls.deployment.CertificatesProcessor#initializeCertificate","started":"16:23:20.937","dependents":[439,368,366,396,433,367],"id":365,"thread":"build-34"},{"duration":1,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setupLogFilters","started":"16:23:20.162","dependents":[93,332],"id":3,"thread":"build-6"},{"duration":1,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#securityExceptionMappers","started":"16:23:20.167","dependents":[331],"id":25,"thread":"build-7"},{"duration":1,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#openSocket","started":"16:23:21.287","dependents":[439,438],"id":437,"thread":"build-2"},{"duration":1,"stepId":"io.quarkus.arc.deployment.AutoInjectFieldProcessor#annotationTransformer","started":"16:23:20.824","dependents":[352],"id":344,"thread":"build-6"},{"duration":1,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#createVertxContextHandlers","started":"16:23:20.285","dependents":[243,439,246],"id":242,"thread":"build-44"},{"duration":1,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#logging","started":"16:23:20.170","dependents":[53],"id":33,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#integrateEagerSecurity","started":"16:23:20.729","dependents":[408],"id":308,"thread":"build-56"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#deprioritizeLegacyProviders","started":"16:23:20.166","dependents":[417],"id":16,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#unlessBuildProperty","started":"16:23:20.722","dependents":[306,299,298],"id":289,"thread":"build-66"},{"duration":0,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#registerVerticleClasses","started":"16:23:20.722","dependents":[438],"id":291,"thread":"build-56"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.DependenciesProcessor#createBuildTimeActions","started":"16:23:20.209","dependents":[264],"id":170,"thread":"build-64"},{"duration":0,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#findEnablementStereotypes","started":"16:23:20.720","dependents":[283,293,289,292],"id":280,"thread":"build-33"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#handleJsonAnnotations","started":"16:23:21.144","dependents":[413,439,438],"id":410,"thread":"build-82"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#addDefaultAuthFailureHandler","started":"16:23:21.173","dependents":[439,433,424],"id":423,"thread":"build-2"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#runtimeConfiguration","started":"16:23:21.172","dependents":[422,439],"id":421,"thread":"build-83"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#gatherAuthorizationPolicyInstances","started":"16:23:20.719","dependents":[296,308],"id":278,"thread":"build-20"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#produceEagerSecurityInterceptorStorage","started":"16:23:20.732","dependents":[439,368,366,367],"id":320,"thread":"build-34"},{"duration":0,"stepId":"io.quarkus.deployment.console.ConsoleProcessor#installCliCommands","started":"16:23:21.145","dependents":[434],"id":412,"thread":"build-82"},{"duration":0,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#cleanupVertxWarnings","started":"16:23:20.165","dependents":[93,332],"id":12,"thread":"build-8"},{"duration":0,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#buildExclusions","started":"16:23:20.725","dependents":[347],"id":298,"thread":"build-42"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#additionalBeans","started":"16:23:20.176","dependents":[352,337],"id":48,"thread":"build-21"},{"duration":0,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#closeBuildTimeLogging","started":"16:23:20.181","dependents":[434],"id":68,"thread":"build-33"},{"duration":0,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#setupConfigOverride","started":"16:23:20.187","dependents":[],"id":106,"thread":"build-17"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#convertRoutes","started":"16:23:21.175","dependents":[430,431],"id":425,"thread":"build-2"},{"duration":0,"stepId":"io.quarkus.deployment.SecureRandomProcessor#registerReflectiveMethods","started":"16:23:20.173","dependents":[438],"id":40,"thread":"build-4"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForParamConverters_dcdfdd2a310a09abe5ee3f0ed2b2bc49f36f3d07","started":"16:23:20.730","dependents":[352,337,408,438,419],"id":316,"thread":"build-50"},{"duration":0,"stepId":"io.quarkus.deployment.console.ConsoleProcessor#setupExceptionHandler","started":"16:23:20.364","dependents":[273],"id":267,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.deployment.steps.ProfileBuildStep#defaultProfile","started":"16:23:20.189","dependents":[384],"id":121,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#requestScopedResources","started":"16:23:20.732","dependents":[352],"id":322,"thread":"build-40"},{"duration":0,"stepId":"io.quarkus.deployment.CollectionClassProcessor#setupCollectionClasses","started":"16:23:20.171","dependents":[438],"id":30,"thread":"build-13"},{"duration":0,"stepId":"io.quarkus.deployment.steps.CurateOutcomeBuildStep#removeResources","started":"16:23:20.209","dependents":[418],"id":168,"thread":"build-31"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#validateConfigMappingsInjectionPoints","started":"16:23:20.973","dependents":[384,383],"id":379,"thread":"build-20"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#vetoMPConfigProperties","started":"16:23:20.165","dependents":[352],"id":14,"thread":"build-7"},{"duration":0,"stepId":"io.quarkus.smallrye.context.deployment.SmallRyeContextPropagationProcessor#registerBean","started":"16:23:20.183","dependents":[352,337],"id":74,"thread":"build-33"},{"duration":0,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#mapDeploymentMethods","started":"16:23:20.344","dependents":[300,397],"id":264,"thread":"build-8"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.EndpointsProcessor#createEndpointsPage","started":"16:23:20.221","dependents":[404],"id":178,"thread":"build-43"},{"duration":0,"stepId":"io.quarkus.deployment.ide.IdeProcessor#effectiveIde","started":"16:23:20.192","dependents":[273,404,267,193],"id":136,"thread":"build-19"},{"duration":0,"stepId":"io.quarkus.deployment.steps.AdditionalClassLoaderResourcesBuildStep#appendAdditionalClassloaderResources","started":"16:23:20.180","dependents":[275],"id":57,"thread":"build-29"},{"duration":0,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#createKnownInternalImportMap","started":"16:23:20.197","dependents":[158,270,427],"id":154,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.common.deployment.JaxrsMethodsProcessor#jaxrsMethods","started":"16:23:20.823","dependents":[342],"id":340,"thread":"build-42"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ShutdownBuildSteps#registerShutdownObservers","started":"16:23:20.949","dependents":[373],"id":371,"thread":"build-60"},{"duration":0,"stepId":"io.quarkus.deployment.index.ApplicationArchiveBuildStep#addConfiguredIndexedDependencies","started":"16:23:20.193","dependents":[271],"id":140,"thread":"build-21"},{"duration":0,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setMinLevelForInitialConfigurator","started":"16:23:20.193","dependents":[439],"id":143,"thread":"build-43"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ArcProcessor#quarkusApplication","started":"16:23:20.721","dependents":[352,337],"id":284,"thread":"build-21"},{"duration":0,"stepId":"io.quarkus.deployment.execannotations.ExecutionModelAnnotationsProcessor#check","started":"16:23:20.824","dependents":[],"id":342,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.arc.deployment.init.InitializationTaskProcessor#startApplicationInitializer","started":"16:23:20.947","dependents":[439],"id":369,"thread":"build-51"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#unremovableBeans","started":"16:23:20.734","dependents":[373,379],"id":327,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setProperty","started":"16:23:20.185","dependents":[439],"id":94,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#perClassExceptionMapperSupport","started":"16:23:20.730","dependents":[352],"id":309,"thread":"build-27"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#applicationSpecificUnwrappedExceptions","started":"16:23:20.720","dependents":[331],"id":281,"thread":"build-41"},{"duration":0,"stepId":"io.quarkus.arc.deployment.AutoInjectFieldProcessor#autoInjectQualifiers","started":"16:23:20.823","dependents":[344,343],"id":338,"thread":"build-40"},{"duration":0,"stepId":"io.quarkus.deployment.logging.LoggingResourceProcessor#setUpDarkeningDefault","started":"16:23:20.188","dependents":[384],"id":113,"thread":"build-39"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForFeatures","started":"16:23:20.731","dependents":[324,419],"id":319,"thread":"build-2"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#addAllWriteableMarker","started":"16:23:21.147","dependents":[418],"id":414,"thread":"build-7"},{"duration":0,"stepId":"io.quarkus.deployment.logging.LoggingWithPanacheProcessor#process","started":"16:23:20.721","dependents":[418],"id":282,"thread":"build-47"},{"duration":0,"stepId":"io.quarkus.devui.deployment.ReportIssuesProcessor#registerJsonRpcService","started":"16:23:20.167","dependents":[235,300,241],"id":19,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.webdependency.locator.deployment.WebDependencyLocatorProcessor#findRelevantFiles","started":"16:23:20.195","dependents":[238,197,188],"id":148,"thread":"build-20"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#setupAuthenticationMechanisms","started":"16:23:20.267","dependents":[439,351,433,352,337,424,349],"id":225,"thread":"build-66"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#recordableConstructor","started":"16:23:20.183","dependents":[439],"id":76,"thread":"build-14"},{"duration":0,"stepId":"io.quarkus.deployment.console.ConsoleProcessor#missingDevUIMessageHandler","started":"16:23:20.364","dependents":[434],"id":268,"thread":"build-8"},{"duration":0,"stepId":"io.quarkus.deployment.dev.testing.TestTracingProcessor#sharedStateListener","started":"16:23:20.173","dependents":[269],"id":39,"thread":"build-11"},{"duration":0,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#makeSolverFactoryUnremovableInDevMode","started":"16:23:20.192","dependents":[373,379],"id":135,"thread":"build-41"},{"duration":0,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#preventLoggerContention","started":"16:23:20.173","dependents":[53],"id":38,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.deployment.ForkJoinPoolProcessor#setProperty","started":"16:23:20.184","dependents":[439],"id":86,"thread":"build-30"},{"duration":0,"stepId":"io.quarkus.mutiny.deployment.MutinyProcessor#runtimeInit","started":"16:23:20.293","dependents":[439],"id":246,"thread":"build-41"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.StaticResourcesProcessor#indexHtmlFile","started":"16:23:20.190","dependents":[238],"id":124,"thread":"build-22"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#generateCustomProducer","started":"16:23:20.734","dependents":[352,337],"id":326,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#initializeRolesAllowedConfigExp","started":"16:23:20.973","dependents":[439],"id":375,"thread":"build-34"},{"duration":0,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#loadAllBuildTimeTemplates","started":"16:23:21.243","dependents":[429],"id":428,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#featureAndCapability","started":"16:23:20.179","dependents":[439,175],"id":52,"thread":"build-26"},{"duration":0,"stepId":"io.quarkus.arc.deployment.SyntheticBeansProcessor#initRegular","started":"16:23:20.939","dependents":[370],"id":366,"thread":"build-40"},{"duration":0,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#unlessBuildProfile","started":"16:23:20.720","dependents":[306,299,298],"id":283,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.smallrye.openapi.deployment.devui.OpenApiDevUIProcessor#createJsonRPCService","started":"16:23:20.187","dependents":[235,300,241],"id":105,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.MCPProcessor#createMCPPage","started":"16:23:20.176","dependents":[400,387],"id":47,"thread":"build-17"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#initMtlsClientAuth","started":"16:23:20.202","dependents":[352,337],"id":161,"thread":"build-18"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForDynamicFeatures","started":"16:23:20.730","dependents":[324,419],"id":315,"thread":"build-8"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#config","started":"16:23:20.164","dependents":[384],"id":6,"thread":"build-8"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ArcProcessor#registerContextPropagation","started":"16:23:20.193","dependents":[229],"id":141,"thread":"build-13"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#generateAuthorizationPolicyStorage","started":"16:23:20.724","dependents":[337],"id":296,"thread":"build-61"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ArcProcessor#feature","started":"16:23:20.180","dependents":[439],"id":60,"thread":"build-30"},{"duration":0,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#registerVerticleClasses","started":"16:23:20.720","dependents":[438],"id":285,"thread":"build-53"},{"duration":0,"stepId":"io.quarkus.arc.deployment.LookupConditionsProcessor#suppressConditionsGenerators","started":"16:23:20.823","dependents":[352],"id":341,"thread":"build-60"},{"duration":0,"stepId":"io.quarkus.swaggerui.deployment.SwaggerUiProcessor#brandingFiles","started":"16:23:20.180","dependents":[238],"id":61,"thread":"build-18"},{"duration":0,"stepId":"io.quarkus.webdependency.locator.deployment.WebDependencyLocatorProcessor#feature","started":"16:23:20.166","dependents":[439],"id":17,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#validateStaticInitConfigProperty","started":"16:23:20.974","dependents":[439,438],"id":380,"thread":"build-2"},{"duration":0,"stepId":"io.quarkus.deployment.pkg.steps.FileSystemResourcesBuildStep#notNormalMode","started":"16:23:20.235","dependents":[],"id":187,"thread":"build-12"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#generateConfigProperties","started":"16:23:20.719","dependents":[356,376,358,438,379],"id":279,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#aggregateParameterContainers","started":"16:23:20.733","dependents":[326,346,327,408],"id":325,"thread":"build-40"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ExecutorServiceProcessor#executorServiceBean","started":"16:23:20.296","dependents":[368,366,367],"id":248,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#buildSetup","started":"16:23:20.163","dependents":[439],"id":4,"thread":"build-7"},{"duration":0,"stepId":"io.quarkus.arc.deployment.LifecycleEventsBuildStep#startupEvent","started":"16:23:21.287","dependents":[437,439],"id":434,"thread":"build-90"},{"duration":0,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#logCleanup","started":"16:23:20.175","dependents":[93,332],"id":44,"thread":"build-16"},{"duration":0,"stepId":"io.quarkus.deployment.ConstructorPropertiesProcessor#build","started":"16:23:20.724","dependents":[438],"id":295,"thread":"build-14"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#initFormAuth","started":"16:23:21.284","dependents":[439,434],"id":432,"thread":"build-83"},{"duration":0,"stepId":"io.quarkus.arc.deployment.StartupBuildSteps#unremovableBeans","started":"16:23:20.184","dependents":[373,379],"id":81,"thread":"build-21"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.BuildMetricsProcessor#createJsonRPCService","started":"16:23:20.180","dependents":[235,300,241],"id":59,"thread":"build-31"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#pathInterfaceImpls","started":"16:23:20.731","dependents":[352,337],"id":318,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#validateRuntimeConfigProperty","started":"16:23:20.976","dependents":[439,438],"id":382,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#configureHandlers","started":"16:23:21.173","dependents":[439],"id":422,"thread":"build-90"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.BuildMetricsProcessor#createBuildMetricsPages","started":"16:23:20.188","dependents":[404],"id":110,"thread":"build-22"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForInterceptors","started":"16:23:20.732","dependents":[329],"id":321,"thread":"build-51"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#cacheControlSupport","started":"16:23:20.187","dependents":[408],"id":108,"thread":"build-14"},{"duration":0,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#registerBean","started":"16:23:20.170","dependents":[352,337],"id":29,"thread":"build-16"},{"duration":0,"stepId":"io.quarkus.deployment.ExtensionLoader#booleanSupplierFactory","started":"16:23:20.184","dependents":[174],"id":83,"thread":"build-34"},{"duration":0,"stepId":"io.quarkus.netty.deployment.NettyProcessor#registerEventLoopBeans","started":"16:23:20.338","dependents":[439,368,366,367],"id":259,"thread":"build-27"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#feature","started":"16:23:20.169","dependents":[439],"id":24,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.devmode.NotFoundProcessor#resourceNotFoundDataAvailable","started":"16:23:20.183","dependents":[352,337],"id":80,"thread":"build-32"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.MCPProcessor#createMCPJsonRPCService","started":"16:23:20.182","dependents":[235,300,241],"id":73,"thread":"build-31"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#registerSecurityBeans","started":"16:23:20.222","dependents":[352,337],"id":179,"thread":"build-55"},{"duration":0,"stepId":"io.quarkus.devui.deployment.welcome.WelcomeProcessor#createWelcomePages","started":"16:23:21.108","dependents":[404],"id":401,"thread":"build-57"},{"duration":0,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#suppressNonRuntimeConfigChanged","started":"16:23:20.186","dependents":[201],"id":99,"thread":"build-22"},{"duration":0,"stepId":"io.quarkus.devui.deployment.BuildTimeContentProcessor#createRelocationMap","started":"16:23:20.188","dependents":[427],"id":111,"thread":"build-17"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#makeRequiredBeansUnremovable","started":"16:23:20.221","dependents":[373,379],"id":176,"thread":"build-13"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.ExtensionsProcessor#createExtensionsPages","started":"16:23:21.109","dependents":[404],"id":402,"thread":"build-83"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveVertxWebSocketIntegrationProcessor#scanner","started":"16:23:20.164","dependents":[408],"id":8,"thread":"build-9"},{"duration":0,"stepId":"io.quarkus.arc.deployment.UnremovableAnnotationsProcessor#unremovableBeans","started":"16:23:20.187","dependents":[373,379],"id":107,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#searchForProviders","started":"16:23:20.226","dependents":[271],"id":180,"thread":"build-64"},{"duration":0,"stepId":"io.quarkus.devui.deployment.logstream.LogStreamProcessor#additionalBean","started":"16:23:20.189","dependents":[352,337],"id":115,"thread":"build-35"},{"duration":0,"stepId":"io.quarkus.jackson.deployment.JacksonProcessor#register","started":"16:23:20.722","dependents":[416,352,337,438],"id":294,"thread":"build-51"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#exceptionMappers","started":"16:23:20.187","dependents":[331],"id":109,"thread":"build-35"},{"duration":0,"stepId":"io.quarkus.deployment.execannotations.ExecutionModelAnnotationsProcessor#devuiJsonRpcServices","started":"16:23:20.186","dependents":[342],"id":98,"thread":"build-28"},{"duration":0,"stepId":"io.quarkus.jackson.deployment.JacksonProcessor#supportMixins","started":"16:23:20.721","dependents":[439,368,366,367,438],"id":287,"thread":"build-39"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#handleClassLevelExceptionMappers","started":"16:23:20.728","dependents":[408,438],"id":304,"thread":"build-56"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#registerHttpAuthMechanismAnnotations","started":"16:23:20.165","dependents":[303],"id":13,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.deployment.steps.MainClassBuildStep#applicationReflection","started":"16:23:20.184","dependents":[438],"id":85,"thread":"build-31"},{"duration":0,"stepId":"io.quarkus.arc.deployment.TestsAsBeansProcessor#testAnnotations","started":"16:23:20.186","dependents":[352,337,228],"id":100,"thread":"build-14"},{"duration":0,"stepId":"io.quarkus.deployment.steps.MainClassBuildStep#setupVersionField","started":"16:23:20.165","dependents":[438],"id":10,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.ReadmeProcessor#createJsonRPCServiceForCache","started":"16:23:20.180","dependents":[235,300,241],"id":56,"thread":"build-18"},{"duration":0,"stepId":"io.quarkus.devui.deployment.logstream.LogStreamProcessor#createJsonRPCService","started":"16:23:20.167","dependents":[235,300,241],"id":20,"thread":"build-10"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#resourceIndex","started":"16:23:20.721","dependents":[409,337,302],"id":290,"thread":"build-42"},{"duration":0,"stepId":"io.quarkus.netty.deployment.NettyProcessor#limitArenaSize","started":"16:23:20.196","dependents":[439],"id":150,"thread":"build-47"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ArcProcessor#validateAsyncObserverExceptionHandlers","started":"16:23:20.973","dependents":[388],"id":377,"thread":"build-2"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ObservabilityProcessor#preAuthFailureFilter","started":"16:23:21.172","dependents":[439,423,433,424],"id":420,"thread":"build-90"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.ManagementInterfaceSecurityProcessor#initializeAuthMechanismHandler","started":"16:23:21.089","dependents":[439,433],"id":395,"thread":"build-57"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#setMinimalNettyMaxOrderSize","started":"16:23:20.174","dependents":[214,150],"id":43,"thread":"build-16"},{"duration":0,"stepId":"io.quarkus.arc.deployment.TestsAsBeansProcessor#testClassBeans","started":"16:23:20.186","dependents":[352,337],"id":103,"thread":"build-13"},{"duration":0,"stepId":"io.quarkus.deployment.steps.ConfigGenerationBuildStep#watchConfigFiles","started":"16:23:20.183","dependents":[238],"id":88,"thread":"build-4"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#httpRoot","started":"16:23:20.196","dependents":[227,436,429,433,425,403,411],"id":151,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.deployment.ide.IdeProcessor#detectIdeFiles","started":"16:23:20.188","dependents":[136],"id":114,"thread":"build-22"},{"duration":0,"stepId":"io.quarkus.deployment.steps.PreloadClassesBuildStep#registerPreInitClasses","started":"16:23:20.166","dependents":[],"id":15,"thread":"build-7"},{"duration":0,"stepId":"io.quarkus.smallrye.context.deployment.SmallRyeContextPropagationProcessor#createSynthBeansForConfiguredInjectionPoints","started":"16:23:20.932","dependents":[439,368,366,367],"id":354,"thread":"build-20"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.EndpointsProcessor#createJsonRPCService","started":"16:23:20.173","dependents":[235,300,241],"id":41,"thread":"build-20"},{"duration":0,"stepId":"io.quarkus.tls.deployment.CertificatesProcessor#unremovableBeans","started":"16:23:20.181","dependents":[373,379],"id":65,"thread":"build-29"},{"duration":0,"stepId":"io.quarkus.devui.deployment.DevUIProcessor#createAllRoutes","started":"16:23:21.132","dependents":[429],"id":406,"thread":"build-83"},{"duration":0,"stepId":"io.quarkus.smallrye.context.deployment.SmallRyeContextPropagationProcessor#transformInjectionPoint","started":"16:23:20.180","dependents":[352],"id":62,"thread":"build-31"},{"duration":0,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#registerReflectivelyAccessedMethods","started":"16:23:20.172","dependents":[438],"id":37,"thread":"build-18"},{"duration":0,"stepId":"io.quarkus.deployment.steps.BannerProcessor#watchBannerChanges","started":"16:23:20.192","dependents":[238],"id":134,"thread":"build-4"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#additionalBeans","started":"16:23:20.188","dependents":[352,337],"id":112,"thread":"build-17"},{"duration":0,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#feature","started":"16:23:20.193","dependents":[439],"id":138,"thread":"build-21"},{"duration":0,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#contributeClassesToIndex","started":"16:23:20.181","dependents":[275],"id":63,"thread":"build-31"},{"duration":0,"stepId":"io.quarkus.vertx.deployment.EventBusCodecProcessor#registerCodecs","started":"16:23:20.823","dependents":[364,438],"id":339,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.BuildMetricsProcessor#additionalBeans","started":"16:23:20.182","dependents":[352,337],"id":72,"thread":"build-32"},{"duration":0,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#ifBuildProfile","started":"16:23:20.722","dependents":[306,299,298],"id":292,"thread":"build-40"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.WorkspaceProcessor#createWorkspacePage","started":"16:23:20.180","dependents":[404],"id":55,"thread":"build-18"},{"duration":0,"stepId":"io.quarkus.deployment.dev.ConfigureDisableInstrumentationBuildStep#configure","started":"16:23:20.185","dependents":[434],"id":95,"thread":"build-24"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#registerCustomConfigBeanTypes","started":"16:23:20.932","dependents":[368,366,367,438],"id":355,"thread":"build-56"},{"duration":0,"stepId":"io.quarkus.arc.deployment.BuildTimeEnabledProcessor#conditionTransformer","started":"16:23:20.726","dependents":[352],"id":299,"thread":"build-56"},{"duration":0,"stepId":"ai.timefold.solver.quarkus.jackson.deployment.TimefoldJacksonProcessor#registerTimefoldJacksonModule","started":"16:23:20.163","dependents":[336],"id":5,"thread":"build-3"},{"duration":0,"stepId":"io.quarkus.deployment.steps.CurateOutcomeBuildStep#curateOutcome","started":"16:23:20.202","dependents":[213,400,273,300,169,294,173,174,245,426,401,247,404,170,215,271,250,264,175,387,418,209,237,168,405],"id":159,"thread":"build-13"},{"duration":0,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#doNotRemoveVertxOptionsCustomizers","started":"16:23:20.168","dependents":[373,379],"id":23,"thread":"build-4"},{"duration":0,"stepId":"io.quarkus.devui.deployment.build.BuildMetricsDevUIProcessor#createJsonRPCService","started":"16:23:20.186","dependents":[235,300,241],"id":104,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.arc.deployment.StartupBuildSteps#registerStartupObservers","started":"16:23:20.949","dependents":[373],"id":372,"thread":"build-51"},{"duration":0,"stepId":"io.quarkus.vertx.deployment.VertxProcessor#reinitializeClassesForNetty","started":"16:23:20.176","dependents":[234],"id":46,"thread":"build-4"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.ReadmeProcessor#createReadmePage","started":"16:23:20.190","dependents":[404],"id":123,"thread":"build-27"},{"duration":0,"stepId":"io.quarkus.deployment.pkg.steps.NativeImageBuildStep#ignoreBuildPropertyChanges","started":"16:23:20.182","dependents":[201],"id":69,"thread":"build-22"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#customExceptionMappers","started":"16:23:20.182","dependents":[328],"id":70,"thread":"build-18"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ArcProcessor#launchMode","started":"16:23:20.184","dependents":[352,337],"id":89,"thread":"build-14"},{"duration":0,"stepId":"ai.timefold.solver.quarkus.jackson.deployment.TimefoldJacksonProcessor#feature","started":"16:23:20.172","dependents":[439],"id":35,"thread":"build-19"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ObserverValidationProcessor#validateApplicationObserver","started":"16:23:20.973","dependents":[388],"id":374,"thread":"build-51"},{"duration":0,"stepId":"io.quarkus.deployment.steps.CapabilityAggregationStep#aggregateCapabilities","started":"16:23:20.220","dependents":[331,177,213,400,208,308,286,180,179,288,419,437,420,296,223,225,352,303,264,176,192,268,416,237,348,313,278,408,178,403,398,216],"id":175,"thread":"build-57"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#validateConfigPropertiesInjectionPoints","started":"16:23:20.973","dependents":[383],"id":376,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForContextResolvers","started":"16:23:20.729","dependents":[413,352,337,438,419],"id":311,"thread":"build-14"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#unremovableContextMethodParams","started":"16:23:20.730","dependents":[373,379],"id":310,"thread":"build-39"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#scanForParamConverters_59e3169e3a646b7fcf3083416f558434b73816c5","started":"16:23:20.730","dependents":[316],"id":314,"thread":"build-61"},{"duration":0,"stepId":"io.quarkus.netty.deployment.NettyProcessor#disableFinalizers","started":"16:23:20.185","dependents":[439],"id":96,"thread":"build-35"},{"duration":0,"stepId":"io.quarkus.arc.deployment.HotDeploymentConfigBuildStep#configFile","started":"16:23:20.169","dependents":[238],"id":28,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.deployment.dev.IsolatedDevModeMain$AddApplicationClassPredicateBuildStep$1@136b2771","started":"16:23:20.181","dependents":[352,408],"id":64,"thread":"build-32"},{"duration":0,"stepId":"io.quarkus.devui.deployment.build.BuildMetricsDevUIProcessor#additionalBeans","started":"16:23:20.184","dependents":[352,337],"id":84,"thread":"build-22"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#notFoundRoutes","started":"16:23:21.281","dependents":[436],"id":430,"thread":"build-6"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveCDIProcessor#subResourcesAsBeans","started":"16:23:20.730","dependents":[352,337,373,379],"id":312,"thread":"build-15"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.VertxHttpProcessor#frameworkRoot","started":"16:23:20.194","dependents":[407,227,431,195,381,433,425,193,154,426,158,404,429,270,424,178,411,427],"id":144,"thread":"build-13"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#handleFieldSecurity","started":"16:23:21.144","dependents":[410],"id":409,"thread":"build-83"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#providersFromClasspath","started":"16:23:20.177","dependents":[417,415,414],"id":50,"thread":"build-11"},{"duration":0,"stepId":"io.quarkus.jackson.deployment.JacksonProcessor#autoRegisterModules","started":"16:23:20.719","dependents":[336],"id":277,"thread":"build-61"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProcessor#reflection","started":"16:23:20.171","dependents":[438],"id":31,"thread":"build-17"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#configPropertyInjectionPoints","started":"16:23:20.973","dependents":[380,382,438],"id":378,"thread":"build-56"},{"duration":0,"stepId":"io.quarkus.netty.deployment.NettyProcessor#cleanupMacDNSInLog","started":"16:23:20.166","dependents":[93,332],"id":18,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ConfigBuildStep#registerConfigPropertiesBean","started":"16:23:20.932","dependents":[370],"id":356,"thread":"build-44"},{"duration":0,"stepId":"io.quarkus.vertx.core.deployment.VertxCoreProcessor#filterNettyHostsFileParsingWarn","started":"16:23:20.175","dependents":[93,332],"id":45,"thread":"build-21"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ShutdownBuildSteps#unremovableBeans","started":"16:23:20.165","dependents":[373,379],"id":11,"thread":"build-10"},{"duration":0,"stepId":"io.quarkus.arc.deployment.staticmethods.InterceptedStaticMethodsProcessor#processInterceptedStaticMethods","started":"16:23:20.935","dependents":[438,418],"id":363,"thread":"build-34"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ObservabilityProcessor#methodScanner","started":"16:23:20.222","dependents":[408],"id":177,"thread":"build-58"},{"duration":0,"stepId":"io.quarkus.smallrye.openapi.deployment.SmallRyeOpenApiProcessor#addAutoOpenApiEndpointFilter","started":"16:23:20.197","dependents":[403],"id":153,"thread":"build-44"},{"duration":0,"stepId":"ai.timefold.solver.quarkus.deployment.TimefoldProcessor#registerDevUICard","started":"16:23:20.193","dependents":[400,387],"id":139,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.arc.deployment.ArcProcessor#signalBeanContainerReady","started":"16:23:21.086","dependents":[394,396,399,433,434,392,419,439,393,436,429,417,397,408,395],"id":391,"thread":"build-80"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveScanningProcessor#defaultUnwrappedExceptions","started":"16:23:20.168","dependents":[331],"id":26,"thread":"build-5"},{"duration":0,"stepId":"io.quarkus.vertx.http.deployment.HttpSecurityProcessor#collectInterceptedMethods","started":"16:23:20.728","dependents":[308,320],"id":305,"thread":"build-42"},{"duration":0,"stepId":"io.quarkus.devui.deployment.menu.ConfigurationProcessor#registerJsonRpcService","started":"16:23:20.178","dependents":[235,300,241],"id":51,"thread":"build-23"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.common.deployment.ResteasyReactiveCommonProcessor#scanForIOInterceptors","started":"16:23:20.731","dependents":[329],"id":317,"thread":"build-32"},{"duration":0,"stepId":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveProcessor#registerCustomExceptionMappers","started":"16:23:20.180","dependents":[328],"id":58,"thread":"build-30"},{"duration":0,"stepId":"io.quarkus.deployment.steps.ReflectionDiagnosticProcessor#writeReflectionData","started":"16:23:21.289","dependents":[],"id":438,"thread":"build-83"}],"started":"2025-09-20T16:23:20.16","items":[{"count":1146,"class":"io.quarkus.deployment.builditem.ConfigDescriptionBuildItem"},{"count":625,"class":"io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem"},{"count":395,"class":"io.quarkus.deployment.builditem.GeneratedClassBuildItem"},{"count":153,"class":"io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem"},{"count":94,"class":"io.quarkus.hibernate.validator.spi.AdditionalConstrainedClassBuildItem"},{"count":64,"class":"io.quarkus.deployment.builditem.MainBytecodeRecorderBuildItem"},{"count":49,"class":"io.quarkus.arc.deployment.AdditionalBeanBuildItem"},{"count":44,"class":"io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyBuildItem"},{"count":40,"class":"io.quarkus.vertx.http.deployment.RouteBuildItem"},{"count":38,"class":"io.quarkus.deployment.builditem.StaticBytecodeRecorderBuildItem"},{"count":29,"class":"io.quarkus.deployment.builditem.ConfigClassBuildItem"},{"count":28,"class":"io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem"},{"count":24,"class":"io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem"},{"count":18,"class":"io.quarkus.arc.deployment.SyntheticBeanBuildItem"},{"count":17,"class":"io.quarkus.deployment.builditem.BytecodeTransformerBuildItem"},{"count":16,"class":"io.quarkus.deployment.builditem.AdditionalIndexedClassesBuildItem"},{"count":15,"class":"io.quarkus.devui.spi.JsonRPCProvidersBuildItem"},{"count":14,"class":"io.quarkus.arc.deployment.UnremovableBeanBuildItem"},{"count":14,"class":"io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem"},{"count":13,"class":"io.quarkus.deployment.builditem.CapabilityBuildItem"},{"count":10,"class":"io.quarkus.deployment.builditem.SuppressNonRuntimeConfigChangedWarningBuildItem"},{"count":10,"class":"io.quarkus.deployment.builditem.FeatureBuildItem"},{"count":10,"class":"io.quarkus.deployment.builditem.nativeimage.RuntimeReinitializedClassBuildItem"},{"count":9,"class":"io.quarkus.vertx.http.deployment.webjar.WebJarBuildItem"},{"count":9,"class":"io.quarkus.devui.deployment.InternalPageBuildItem"},{"count":9,"class":"io.quarkus.devui.spi.buildtime.BuildTimeActionBuildItem"},{"count":8,"class":"io.quarkus.devui.deployment.DevUIWebJarBuildItem"},{"count":8,"class":"io.quarkus.devui.deployment.DevUIRoutesBuildItem"},{"count":8,"class":"io.quarkus.arc.deployment.AnnotationsTransformerBuildItem"},{"count":8,"class":"io.quarkus.deployment.logging.LogCleanupFilterBuildItem"},{"count":7,"class":"io.quarkus.resteasy.reactive.spi.ExceptionMapperBuildItem"},{"count":7,"class":"io.quarkus.vertx.http.deployment.devmode.NotFoundPageDisplayableEndpointBuildItem"},{"count":7,"class":"io.quarkus.resteasy.reactive.spi.MessageBodyWriterBuildItem"},{"count":6,"class":"io.quarkus.deployment.builditem.SystemPropertyBuildItem"},{"count":6,"class":"io.quarkus.deployment.builditem.ConsoleCommandBuildItem"},{"count":6,"class":"io.quarkus.deployment.builditem.nativeimage.NativeImageSystemPropertyBuildItem"},{"count":6,"class":"io.quarkus.devui.spi.page.CardPageBuildItem"},{"count":6,"class":"io.quarkus.resteasy.reactive.server.spi.MethodScannerBuildItem"},{"count":5,"class":"io.quarkus.arc.deployment.BeanDefiningAnnotationBuildItem"},{"count":5,"class":"io.quarkus.arc.deployment.GeneratedBeanBuildItem"},{"count":4,"class":"io.quarkus.jackson.spi.ClassPathJacksonModuleBuildItem"},{"count":4,"class":"io.quarkus.deployment.builditem.nativeimage.ReflectiveFieldBuildItem"},{"count":4,"class":"io.quarkus.resteasy.reactive.spi.MessageBodyWriterOverrideBuildItem"},{"count":4,"class":"io.quarkus.resteasy.reactive.spi.MessageBodyReaderBuildItem"},{"count":4,"class":"io.quarkus.deployment.execannotations.ExecutionModelAnnotationsAllowedBuildItem"},{"count":4,"class":"io.quarkus.vertx.http.deployment.spi.RouteBuildItem"},{"count":4,"class":"io.quarkus.devui.deployment.BuildTimeConstBuildItem"},{"count":4,"class":"io.quarkus.resteasy.reactive.spi.MessageBodyReaderOverrideBuildItem"},{"count":4,"class":"io.quarkus.deployment.builditem.AdditionalApplicationArchiveMarkerBuildItem"},{"count":3,"class":"io.quarkus.vertx.http.deployment.HttpAuthMechanismAnnotationBuildItem"},{"count":3,"class":"io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem"},{"count":3,"class":"io.quarkus.deployment.builditem.nativeimage.NativeImageConfigBuildItem"},{"count":3,"class":"io.quarkus.deployment.builditem.ServiceStartBuildItem"},{"count":3,"class":"io.quarkus.vertx.http.deployment.FilterBuildItem"},{"count":3,"class":"io.quarkus.arc.deployment.AutoAddScopeBuildItem"},{"count":3,"class":"io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem"},{"count":3,"class":"io.quarkus.resteasy.reactive.spi.CustomExceptionMapperBuildItem"},{"count":3,"class":"io.quarkus.deployment.builditem.GeneratedResourceBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.ShutdownListenerBuildItem"},{"count":2,"class":"io.quarkus.resteasy.reactive.common.deployment.ResourceInterceptorsContributorBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.ObjectSubstitutionBuildItem"},{"count":2,"class":"io.quarkus.devui.spi.buildtime.QuteTemplateBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.StaticInitConfigBuilderBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.RecordableConstructorBuildItem"},{"count":2,"class":"io.quarkus.webdependency.locator.deployment.devui.WebDependencyLibrariesBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.BytecodeRecorderObjectLoaderBuildItem"},{"count":2,"class":"io.quarkus.devui.spi.buildtime.StaticContentBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.LogCategoryBuildItem"},{"count":2,"class":"io.quarkus.deployment.dev.testing.TestListenerBuildItem"},{"count":2,"class":"io.quarkus.resteasy.reactive.server.spi.UnwrappedExceptionBuildItem"},{"count":2,"class":"io.quarkus.deployment.builditem.ConfigMappingBuildItem"},{"count":2,"class":"io.quarkus.devui.deployment.InternalImportMapBuildItem"},{"count":2,"class":"io.quarkus.arc.deployment.AutoInjectAnnotationBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.AnnotationProxyBuildItem"},{"count":1,"class":"io.quarkus.devui.deployment.MvnpmBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.spi.StaticResourcesBuildItem"},{"count":1,"class":"io.quarkus.deployment.console.ConsoleInstalledBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.SynthesisFinishedBuildItem"},{"count":1,"class":"io.quarkus.vertx.core.deployment.EventLoopCountBuildItem"},{"count":1,"class":"io.quarkus.vertx.core.deployment.CoreVertxBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ContextResolversBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.nativeimage.ReflectiveHierarchyIgnoreWarningBuildItem"},{"count":1,"class":"io.quarkus.vertx.deployment.LocalCodecSelectorTypesBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.InitialRouterBuildItem"},{"count":1,"class":"io.quarkus.smallrye.openapi.deployment.spi.OpenApiDocumentBuildItem"},{"count":1,"class":"io.quarkus.swaggerui.deployment.SwaggerUiBuildItem"},{"count":1,"class":"io.quarkus.deployment.dev.ExceptionNotificationBuildItem"},{"count":1,"class":"io.quarkus.deployment.pkg.builditem.CompiledJavaVersionBuildItem"},{"count":1,"class":"io.quarkus.devui.spi.workspace.WorkspaceBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.ValidationPhaseBuildItem"},{"count":1,"class":"io.quarkus.netty.deployment.EventLoopSupplierBuildItem"},{"count":1,"class":"io.quarkus.deployment.BooleanSupplierFactoryBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ParamConverterProvidersBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.spi.HandlerConfigurationProviderBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.DevServicesLauncherConfigResultBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ThreadFactoryBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ApplicationIndexBuildItem"},{"count":1,"class":"io.quarkus.deployment.logging.LoggingSetupBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.ArcContainerBuildItem"},{"count":1,"class":"io.quarkus.devui.deployment.JsonRPCRuntimeMethodsBuildItem"},{"count":1,"class":"io.quarkus.smallrye.context.deployment.spi.ThreadContextProviderBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ApplicationClassNameBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.StreamingLogHandlerBuildItem"},{"count":1,"class":"io.quarkus.deployment.dev.DisableInstrumentationForIndexPredicateBuildItem"},{"count":1,"class":"io.quarkus.devui.spi.page.UnlistedPageBuildItem"},{"count":1,"class":"io.quarkus.deployment.logging.LoggingDecorateBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.spi.GlobalHandlerCustomizerBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.CurrentContextFactoryBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.ParameterContainersBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.GeneratedRuntimeSystemPropertyBuildItem"},{"count":1,"class":"io.quarkus.smallrye.openapi.deployment.spi.AddToOpenAPIDefinitionBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ConfigurationBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.ApplicationResultBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.BodyHandlerBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BuildExclusionsBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.LogCategoryMinLevelDefaultsBuildItem"},{"count":1,"class":"ai.timefold.solver.quarkus.deployment.SolverConfigBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.IOThreadDetectorBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.InvokerFactoryBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.SslNativeConfigBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.ServerDefaultProducesHandlerBuildItem"},{"count":1,"class":"io.quarkus.deployment.ide.IdeRunningProcessBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.TransformedClassesBuildItem"},{"count":1,"class":"io.quarkus.netty.deployment.EventLoopGroupBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.devui.ArcBeanInfoBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem$BeanConfiguratorBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BeanDiscoveryFinishedBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.RunTimeConfigurationProxyBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.ResourceInterceptorsBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.DefaultRouteBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.VertxDevUILogBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BuildCompatibleExtensionsBuildItem"},{"count":1,"class":"io.quarkus.devui.deployment.ThemeVarsBuildItem"},{"count":1,"class":"io.quarkus.devui.spi.page.FooterPageBuildItem"},{"count":1,"class":"io.quarkus.smallrye.context.deployment.ContextPropagationInitializedBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ExceptionMappersBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.InterceptorResolverBuildItem"},{"count":1,"class":"io.quarkus.devui.spi.page.SettingPageBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.IndexDependencyBuildItem"},{"count":1,"class":"io.quarkus.devui.spi.workspace.WorkspaceActionBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BeanArchiveIndexBuildItem"},{"count":1,"class":"io.quarkus.jackson.spi.JacksonModuleBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ConsoleFormatterBannerBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.SuppressConditionGeneratorBuildItem"},{"count":1,"class":"io.quarkus.tls.deployment.spi.TlsRegistryBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BuildTimeEnabledStereotypesBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ApplicationArchivesBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ContextHandlerBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.TransformedAnnotationsBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveResourceMethodEntriesBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.GeneratedFileSystemResourceHandledBuildItem"},{"count":1,"class":"io.quarkus.deployment.pkg.builditem.OutputTargetBuildItem"},{"count":1,"class":"io.quarkus.vertx.core.deployment.IgnoredContextLocalDataKeysBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.PreBeanContainerBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.InjectionPointTransformerBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.webjar.WebJarResultsBuildItem"},{"count":1,"class":"io.quarkus.netty.deployment.MinNettyAllocatorMaxOrderBuildItem"},{"count":1,"class":"io.quarkus.smallrye.openapi.deployment.OpenApiFilteredIndexViewBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.VertxWebRouterBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.CombinedIndexBuildItem"},{"count":1,"class":"io.quarkus.deployment.Capabilities"},{"count":1,"class":"io.quarkus.devui.deployment.ExtensionsBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ExecutorBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.SetupEndpointsResultBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveDeploymentInfoBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.ObserverRegistrationPhaseBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.ResourceScanningResultBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ServerSerialisersBuildItem"},{"count":1,"class":"io.quarkus.vertx.deployment.VertxBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.ResteasyReactiveDeploymentBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.BeanContainerBuildItem"},{"count":1,"class":"io.quarkus.devui.spi.buildtime.FooterLogBuildItem"},{"count":1,"class":"io.quarkus.deployment.ide.EffectiveIdeBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.JaxRsResourceIndexBuildItem"},{"count":1,"class":"io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem"},{"count":1,"class":"io.quarkus.vertx.http.deployment.HttpRootPathBuildItem"},{"count":1,"class":"io.quarkus.devui.deployment.DeploymentMethodBuildItem"},{"count":1,"class":"io.quarkus.deployment.steps.CapabilityAggregationStep$CapabilitiesConfiguredInDescriptorsBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ApplicationStartBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.ConfigPropertyBuildItem"},{"count":1,"class":"io.quarkus.devui.deployment.RelocationImportMapBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.common.deployment.AggregatedParameterContainersBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.ContextRegistrationPhaseBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.CustomScopeAnnotationsBuildItem"},{"count":1,"class":"io.quarkus.resteasy.reactive.server.deployment.BuiltInReaderOverrideBuildItem"},{"count":1,"class":"io.quarkus.arc.deployment.CompletedApplicationClassPredicateBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.ApplicationInfoBuildItem"},{"count":1,"class":"io.quarkus.deployment.ide.IdeFileBuildItem"},{"count":1,"class":"io.quarkus.deployment.builditem.MainClassBuildItem"}],"itemsCount":3198,"buildTarget":"employee-scheduling-1.0-SNAPSHOT"} \ No newline at end of file diff --git a/target/classes/META-INF/resources/app.js b/target/classes/META-INF/resources/app.js new file mode 100644 index 0000000..eca3308 --- /dev/null +++ b/target/classes/META-INF/resources/app.js @@ -0,0 +1,496 @@ +let autoRefreshIntervalId = null; +const zoomMin = 2 * 1000 * 60 * 60 * 24 // 2 day in milliseconds +const zoomMax = 4 * 7 * 1000 * 60 * 60 * 24 // 4 weeks in milliseconds + +const UNAVAILABLE_COLOR = '#ef2929' // Tango Scarlet Red +const UNDESIRED_COLOR = '#f57900' // Tango Orange +const DESIRED_COLOR = '#73d216' // Tango Chameleon + +let demoDataId = null; +let scheduleId = null; +let loadedSchedule = null; + +const byEmployeePanel = document.getElementById("byEmployeePanel"); +const byEmployeeTimelineOptions = { + timeAxis: {scale: "hour", step: 6}, + orientation: {axis: "top"}, + stack: false, + xss: {disabled: true}, // Items are XSS safe through JQuery + zoomMin: zoomMin, + zoomMax: zoomMax, +}; +let byEmployeeGroupDataSet = new vis.DataSet(); +let byEmployeeItemDataSet = new vis.DataSet(); +let byEmployeeTimeline = new vis.Timeline(byEmployeePanel, byEmployeeItemDataSet, byEmployeeGroupDataSet, byEmployeeTimelineOptions); + +const byLocationPanel = document.getElementById("byLocationPanel"); +const byLocationTimelineOptions = { + timeAxis: {scale: "hour", step: 6}, + orientation: {axis: "top"}, + xss: {disabled: true}, // Items are XSS safe through JQuery + zoomMin: zoomMin, + zoomMax: zoomMax, +}; +let byLocationGroupDataSet = new vis.DataSet(); +let byLocationItemDataSet = new vis.DataSet(); +let byLocationTimeline = new vis.Timeline(byLocationPanel, byLocationItemDataSet, byLocationGroupDataSet, byLocationTimelineOptions); + +let windowStart = JSJoda.LocalDate.now().toString(); +let windowEnd = JSJoda.LocalDate.parse(windowStart).plusDays(7).toString(); + +$(document).ready(function () { + replaceQuickstartTimefoldAutoHeaderFooter(); + + $("#solveButton").click(function () { + solve(); + }); + $("#stopSolvingButton").click(function () { + stopSolving(); + }); + $("#analyzeButton").click(function () { + analyze(); + }); + // HACK to allow vis-timeline to work within Bootstrap tabs + $("#byEmployeeTab").on('shown.bs.tab', function (event) { + byEmployeeTimeline.redraw(); + }) + $("#byLocationTab").on('shown.bs.tab', function (event) { + byLocationTimeline.redraw(); + }) + + setupAjax(); + fetchDemoData(); +}); + +function setupAjax() { + $.ajaxSetup({ + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json,text/plain', // plain text is required by solve() returning UUID of the solver job + } + }); + // Extend jQuery to support $.put() and $.delete() + jQuery.each(["put", "delete"], function (i, method) { + jQuery[method] = function (url, data, callback, type) { + if (jQuery.isFunction(data)) { + type = type || callback; + callback = data; + data = undefined; + } + return jQuery.ajax({ + url: url, + type: method, + dataType: type, + data: data, + success: callback + }); + }; + }); +} + +function fetchDemoData() { + $.get("/demo-data", function (data) { + data.forEach(item => { + $("#testDataButton").append($('' + item + '')); + $("#" + item + "TestData").click(function () { + switchDataDropDownItemActive(item); + scheduleId = null; + demoDataId = item; + + refreshSchedule(); + }); + }); + demoDataId = data[0]; + switchDataDropDownItemActive(demoDataId); + refreshSchedule(); + }).fail(function (xhr, ajaxOptions, thrownError) { + // disable this page as there is no data + let $demo = $("#demo"); + $demo.empty(); + $demo.html("

No test data available

") + }); +} + +function switchDataDropDownItemActive(newItem) { + activeCssClass = "active"; + $("#testDataButton > a." + activeCssClass).removeClass(activeCssClass); + $("#" + newItem + "TestData").addClass(activeCssClass); +} + +function getShiftColor(shift, employee) { + const shiftStart = JSJoda.LocalDateTime.parse(shift.start); + const shiftStartDateString = shiftStart.toLocalDate().toString(); + const shiftEnd = JSJoda.LocalDateTime.parse(shift.end); + const shiftEndDateString = shiftEnd.toLocalDate().toString(); + if (employee.unavailableDates.includes(shiftStartDateString) || + // The contains() check is ignored for a shift end at midnight (00:00:00). + (shiftEnd.isAfter(shiftStart.toLocalDate().plusDays(1).atStartOfDay()) && + employee.unavailableDates.includes(shiftEndDateString))) { + return UNAVAILABLE_COLOR + } else if (employee.undesiredDates.includes(shiftStartDateString) || + // The contains() check is ignored for a shift end at midnight (00:00:00). + (shiftEnd.isAfter(shiftStart.toLocalDate().plusDays(1).atStartOfDay()) && + employee.undesiredDates.includes(shiftEndDateString))) { + return UNDESIRED_COLOR + } else if (employee.desiredDates.includes(shiftStartDateString) || + // The contains() check is ignored for a shift end at midnight (00:00:00). + (shiftEnd.isAfter(shiftStart.toLocalDate().plusDays(1).atStartOfDay()) && + employee.desiredDates.includes(shiftEndDateString))) { + return DESIRED_COLOR + } else { + return " #729fcf"; // Tango Sky Blue + } +} + +function refreshSchedule() { + let path = "/schedules/" + scheduleId; + if (scheduleId === null) { + if (demoDataId === null) { + alert("Please select a test data set."); + return; + } + + path = "/demo-data/" + demoDataId; + } + $.getJSON(path, function (schedule) { + loadedSchedule = schedule; + renderSchedule(schedule); + }) + .fail(function (xhr, ajaxOptions, thrownError) { + showError("Getting the schedule has failed.", xhr); + refreshSolvingButtons(false); + }); +} + +function renderSchedule(schedule) { + refreshSolvingButtons(schedule.solverStatus != null && schedule.solverStatus !== "NOT_SOLVING"); + $("#score").text("Score: " + (schedule.score == null ? "?" : schedule.score)); + + const unassignedShifts = $("#unassignedShifts"); + const groups = []; + + // Show only first 7 days of draft + const scheduleStart = schedule.shifts.map(shift => JSJoda.LocalDateTime.parse(shift.start).toLocalDate()).sort()[0].toString(); + const scheduleEnd = JSJoda.LocalDate.parse(scheduleStart).plusDays(7).toString(); + + windowStart = scheduleStart; + windowEnd = scheduleEnd; + + unassignedShifts.children().remove(); + let unassignedShiftsCount = 0; + byEmployeeGroupDataSet.clear(); + byLocationGroupDataSet.clear(); + + byEmployeeItemDataSet.clear(); + byLocationItemDataSet.clear(); + + + schedule.employees.forEach((employee, index) => { + const employeeGroupElement = $('
') + .append($(`
)`) + .append(employee.name)) + .append($('
') + .append($(employee.skills.map(skill => `${skill}`).join('')))); + byEmployeeGroupDataSet.add({id: employee.name, content: employeeGroupElement.html()}); + + employee.unavailableDates.forEach((rawDate, dateIndex) => { + const date = JSJoda.LocalDate.parse(rawDate) + const start = date.atStartOfDay().toString(); + const end = date.plusDays(1).atStartOfDay().toString(); + const byEmployeeShiftElement = $(`
`) + .append($(`
`).text("Unavailable")); + byEmployeeItemDataSet.add({ + id: "employee-" + index + "-unavailability-" + dateIndex, group: employee.name, + content: byEmployeeShiftElement.html(), + start: start, end: end, + type: "background", + style: "opacity: 0.5; background-color: " + UNAVAILABLE_COLOR, + }); + }); + employee.undesiredDates.forEach((rawDate, dateIndex) => { + const date = JSJoda.LocalDate.parse(rawDate) + const start = date.atStartOfDay().toString(); + const end = date.plusDays(1).atStartOfDay().toString(); + const byEmployeeShiftElement = $(`
`) + .append($(`
`).text("Undesired")); + byEmployeeItemDataSet.add({ + id: "employee-" + index + "-undesired-" + dateIndex, group: employee.name, + content: byEmployeeShiftElement.html(), + start: start, end: end, + type: "background", + style: "opacity: 0.5; background-color: " + UNDESIRED_COLOR, + }); + }); + employee.desiredDates.forEach((rawDate, dateIndex) => { + const date = JSJoda.LocalDate.parse(rawDate) + const start = date.atStartOfDay().toString(); + const end = date.plusDays(1).atStartOfDay().toString(); + const byEmployeeShiftElement = $(`
`) + .append($(`
`).text("Desired")); + byEmployeeItemDataSet.add({ + id: "employee-" + index + "-desired-" + dateIndex, group: employee.name, + content: byEmployeeShiftElement.html(), + start: start, end: end, + type: "background", + style: "opacity: 0.5; background-color: " + DESIRED_COLOR, + }); + }); + }); + + schedule.shifts.forEach((shift, index) => { + if (groups.indexOf(shift.location) === -1) { + groups.push(shift.location); + byLocationGroupDataSet.add({ + id: shift.location, + content: shift.location, + }); + } + + if (shift.employee == null) { + unassignedShiftsCount++; + + const byLocationShiftElement = $('
') + .append($(`
)`) + .append("Unassigned")) + .append($('
') + .append($(`${shift.requiredSkill}`))); + + byLocationItemDataSet.add({ + id: 'shift-' + index, group: shift.location, + content: byLocationShiftElement.html(), + start: shift.start, end: shift.end, + style: "background-color: #EF292999" + }); + } else { + const skillColor = (shift.employee.skills.indexOf(shift.requiredSkill) === -1 ? '#ef2929' : '#8ae234'); + const byEmployeeShiftElement = $('
') + .append($(`
)`) + .append(shift.location)) + .append($('
') + .append($(`${shift.requiredSkill}`))); + const byLocationShiftElement = $('
') + .append($(`
)`) + .append(shift.employee.name)) + .append($('
') + .append($(`${shift.requiredSkill}`))); + + const shiftColor = getShiftColor(shift, shift.employee); + byEmployeeItemDataSet.add({ + id: 'shift-' + index, group: shift.employee.name, + content: byEmployeeShiftElement.html(), + start: shift.start, end: shift.end, + style: "background-color: " + shiftColor + }); + byLocationItemDataSet.add({ + id: 'shift-' + index, group: shift.location, + content: byLocationShiftElement.html(), + start: shift.start, end: shift.end, + style: "background-color: " + shiftColor + }); + } + }); + + + if (unassignedShiftsCount === 0) { + unassignedShifts.append($(`

`).text(`There are no unassigned shifts.`)); + } else { + unassignedShifts.append($(`

`).text(`There are ${unassignedShiftsCount} unassigned shifts.`)); + } + byEmployeeTimeline.setWindow(scheduleStart, scheduleEnd); + byLocationTimeline.setWindow(scheduleStart, scheduleEnd); +} + +function solve() { + $.post("/schedules", JSON.stringify(loadedSchedule), function (data) { + scheduleId = data; + refreshSolvingButtons(true); + }).fail(function (xhr, ajaxOptions, thrownError) { + showError("Start solving failed.", xhr); + refreshSolvingButtons(false); + }, + "text"); +} + +function analyze() { + new bootstrap.Modal("#scoreAnalysisModal").show() + const scoreAnalysisModalContent = $("#scoreAnalysisModalContent"); + scoreAnalysisModalContent.children().remove(); + if (loadedSchedule.score == null) { + scoreAnalysisModalContent.text("No score to analyze yet, please first press the 'solve' button."); + } else { + $('#scoreAnalysisScoreLabel').text(`(${loadedSchedule.score})`); + $.put("/schedules/analyze", JSON.stringify(loadedSchedule), function (scoreAnalysis) { + let constraints = scoreAnalysis.constraints; + constraints.sort((a, b) => { + let aComponents = getScoreComponents(a.score), bComponents = getScoreComponents(b.score); + if (aComponents.hard < 0 && bComponents.hard > 0) return -1; + if (aComponents.hard > 0 && bComponents.soft < 0) return 1; + if (Math.abs(aComponents.hard) > Math.abs(bComponents.hard)) { + return -1; + } else { + if (aComponents.medium < 0 && bComponents.medium > 0) return -1; + if (aComponents.medium > 0 && bComponents.medium < 0) return 1; + if (Math.abs(aComponents.medium) > Math.abs(bComponents.medium)) { + return -1; + } else { + if (aComponents.soft < 0 && bComponents.soft > 0) return -1; + if (aComponents.soft > 0 && bComponents.soft < 0) return 1; + + return Math.abs(bComponents.soft) - Math.abs(aComponents.soft); + } + } + }); + constraints.map((e) => { + let components = getScoreComponents(e.weight); + e.type = components.hard != 0 ? 'hard' : (components.medium != 0 ? 'medium' : 'soft'); + e.weight = components[e.type]; + let scores = getScoreComponents(e.score); + e.implicitScore = scores.hard != 0 ? scores.hard : (scores.medium != 0 ? scores.medium : scores.soft); + }); + scoreAnalysis.constraints = constraints; + + scoreAnalysisModalContent.children().remove(); + scoreAnalysisModalContent.text(""); + + const analysisTable = $(``).css({textAlign: 'center'}); + const analysisTHead = $(``).append($(``) + .append($(``)) + .append($(``).css({textAlign: 'left'})) + .append($(``)) + .append($(``)) + .append($(``)) + .append($(``)) + .append($(``))); + analysisTable.append(analysisTHead); + const analysisTBody = $(``) + $.each(scoreAnalysis.constraints, (index, constraintAnalysis) => { + let icon = constraintAnalysis.type == "hard" && constraintAnalysis.implicitScore < 0 ? '' : ''; + if (!icon) icon = constraintAnalysis.matches.length == 0 ? '' : ''; + + let row = $(``); + row.append($(`
ConstraintType# MatchesWeightScore
`).html(icon)) + .append($(``).text(constraintAnalysis.name).css({textAlign: 'left'})) + .append($(``).text(constraintAnalysis.type)) + .append($(``).html(`${constraintAnalysis.matches.length}`)) + .append($(``).text(constraintAnalysis.weight)) + .append($(``).text(constraintAnalysis.implicitScore)); + analysisTBody.append(row); + row.append($(``)); + }); + analysisTable.append(analysisTBody); + scoreAnalysisModalContent.append(analysisTable); + }).fail(function (xhr, ajaxOptions, thrownError) { + showError("Analyze failed.", xhr); + }, "text"); + } +} + +function getScoreComponents(score) { + let components = {hard: 0, medium: 0, soft: 0}; + + $.each([...score.matchAll(/(-?\d*(\.\d+)?)(hard|medium|soft)/g)], (i, parts) => { + components[parts[3]] = parseFloat(parts[1], 10); + }); + + return components; +} + +function refreshSolvingButtons(solving) { + if (solving) { + $("#solveButton").hide(); + $("#stopSolvingButton").show(); + if (autoRefreshIntervalId == null) { + autoRefreshIntervalId = setInterval(refreshSchedule, 2000); + } + } else { + $("#solveButton").show(); + $("#stopSolvingButton").hide(); + if (autoRefreshIntervalId != null) { + clearInterval(autoRefreshIntervalId); + autoRefreshIntervalId = null; + } + } +} + +function refreshSolvingButtons(solving) { + if (solving) { + $("#solveButton").hide(); + $("#stopSolvingButton").show(); + if (autoRefreshIntervalId == null) { + autoRefreshIntervalId = setInterval(refreshSchedule, 2000); + } + } else { + $("#solveButton").show(); + $("#stopSolvingButton").hide(); + if (autoRefreshIntervalId != null) { + clearInterval(autoRefreshIntervalId); + autoRefreshIntervalId = null; + } + } +} + +function stopSolving() { + $.delete(`/schedules/${scheduleId}`, function () { + refreshSolvingButtons(false); + refreshSchedule(); + }).fail(function (xhr, ajaxOptions, thrownError) { + showError("Stop solving failed.", xhr); + }); +} + +function replaceQuickstartTimefoldAutoHeaderFooter() { + const timefoldHeader = $("header#timefold-auto-header"); + if (timefoldHeader != null) { + timefoldHeader.addClass("bg-black") + timefoldHeader.append( + $(`
+ +
`)); + } + + const timefoldFooter = $("footer#timefold-auto-footer"); + if (timefoldFooter != null) { + timefoldFooter.append( + $(``)); + } +} diff --git a/target/classes/META-INF/resources/index.html b/target/classes/META-INF/resources/index.html new file mode 100644 index 0000000..7c1b361 --- /dev/null +++ b/target/classes/META-INF/resources/index.html @@ -0,0 +1,161 @@ + + + + + Employee scheduling - Timefold Solver on Quarkus + + + + + + + + + + +
+ +
+
+
+
+
+
+

Employee scheduling solver

+

Generate the optimal schedule for your employees.

+ +
+ + + + Score: ? + + +
+ +
+
+
+
+
+
+
+
+
+
+
+ +
+

REST API Guide

+ +

Employee Scheduling solver integration via cURL

+ +

1. Download demo data

+
+            
+            curl -X GET -H 'Accept:application/json' http://localhost:8080/demo-data/SMALL -o sample.json
+    
+ +

2. Post the sample data for solving

+

The POST operation returns a jobId that should be used in subsequent commands.

+
+            
+            curl -X POST -H 'Content-Type:application/json' http://localhost:8080/schedules -d@sample.json
+    
+ +

3. Get the current status and score

+
+            
+            curl -X GET -H 'Accept:application/json' http://localhost:8080/schedules/{jobId}/status
+    
+ +

4. Get the complete solution

+
+            
+            curl -X GET -H 'Accept:application/json' http://localhost:8080/schedules/{jobId}
+    
+ +

5. Fetch the analysis of the solution

+
+            
+            curl -X PUT -H 'Content-Type:application/json' http://localhost:8080/schedules/analyze -d@solution.json
+    
+ +

5. Terminate solving early

+
+            
+            curl -X DELETE -H 'Accept:application/json' http://localhost:8080/schedules/{id}
+    
+
+ +
+

REST API Reference

+
+ + +
+
+
+
+ + + + + + + + + + diff --git a/target/classes/application.properties b/target/classes/application.properties new file mode 100644 index 0000000..2e80d17 --- /dev/null +++ b/target/classes/application.properties @@ -0,0 +1,43 @@ +######################## +# Timefold Solver properties +######################## + +# The solver runs for 30 seconds. To run for 5 minutes use "5m" and for 2 hours use "2h". +quarkus.timefold.solver.termination.spent-limit=30s + +# To change how many solvers to run in parallel +# timefold.solver-manager.parallel-solver-count=4 + +# Temporary comment this out to detect bugs in your code (lowers performance) +# quarkus.timefold.solver.environment-mode=FULL_ASSERT + +# Temporary comment this out to return a feasible solution as soon as possible +# quarkus.timefold.solver.termination.best-score-limit=0hard/*soft + +# To see what Timefold is doing, turn on DEBUG or TRACE logging. +quarkus.log.category."ai.timefold.solver".level=INFO +%test.quarkus.log.category."ai.timefold.solver".level=INFO +%prod.quarkus.log.category."ai.timefold.solver".level=INFO + +# XML file for power tweaking, defaults to solverConfig.xml (directly under src/main/resources) +# quarkus.timefold.solver-config-xml=org/.../maintenanceScheduleSolverConfig.xml + +######################## +# Timefold Solver Enterprise properties +######################## + +# To run increase CPU cores usage per solver +%enterprise.quarkus.timefold.solver.move-thread-count=AUTO + +######################## +# Native build properties +######################## + +# Enable Swagger UI also in the native mode +quarkus.swagger-ui.always-include=true + +######################## +# Test overrides +######################## + +%test.quarkus.timefold.solver.termination.spent-limit=10s diff --git a/target/classes/org/acme/employeescheduling/domain/Employee.class b/target/classes/org/acme/employeescheduling/domain/Employee.class new file mode 100644 index 0000000000000000000000000000000000000000..070353fb6ca4a1c200207c05471495c94d55c4fa GIT binary patch literal 2989 zcmb`JTW=dx5Xb)~@hz?s$4Qz?Z=^IyeMz#Vlu}3ll4{l{Ow{0iVUcG4KY zU=pzm;z%frKGmP;T3xsHwVl1EM%7VBteTeTtSJoU3%f%|VJL}o24|2_DA~<@O|Lc# z&1f9e?dOKksva1%cHN|bn%&S%OWW{w6k?X%Fcikhubot!CRJC&>_`S#jM880(5%;6 z3RzFD?U;3~VmPkSSO(*wG}^WZYS#6=y0NZ1MoTQ5&0tbCN7`1+Xqio;*4>)UU`Dnw z!HqQEIiJA=TvSNz8_u?iH<2&&1E%o?W|O#_!JD|EkaHt&$-FcXH(`9))`k0OKJdP` zz0$u@c#_6E7LvG{K^}#k)O%S`NFC^{gL`(3Nn`Ri6=oi_EyrvayJpK|G#|@}NezhJuHH0d?k~oi z1CxO)mH$Ik(aFPLzJ1DGKtKK6N;-YFu&XfH%lG`K!}#4lI*ZI%uSZ{{FJb?umPCF6LxfSv! zaP*~+28hycpb+i9?|nhYxd_2d!8O-v?^>36>w!kYmPM`Jm6T(5ZgbBW_Cqg6%U+8Atzz1DPLXNqT1RKXYl#BjK z7Lp`Sf0+y-O=7vLzf65EnKz;2W5TCIrg2mpD(KUCz4}COxfgpb0-vh4=72_rf5(QtaVboQk-aa9#-X#s9N=*h)HzHA|!l-vnMZF)58n}*L z0jv{s;{;T%e*{ryLZ~18yGyeffvWh2>|@3)h5i*QRPN_ovGfh%u@|M^kop>DO0SUG z`WErQ7sZ!2x5(emxb%X0UO$;6I>4m-<3mc=7>mdCCy=>g-^+hpI8>YwXgv^ji& zPw97>RqgGTxu52L>5)I7l5D~JXrbVfUFRs*J|zS%F(=-G?cno3WT|eK+;X+H{|1Xb BE9n3L literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/domain/EmployeeSchedule.class b/target/classes/org/acme/employeescheduling/domain/EmployeeSchedule.class new file mode 100644 index 0000000000000000000000000000000000000000..aacd7c2a87b796b2c6fb571cf7cc4c4148840bba GIT binary patch literal 3117 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 fv-%zeA>1fdeGk1yDNtOWTGSz z6F&F@{87f)yMxw%M3a7Kc6V;(nR(`|KYtzn0Pq6&9z@WkA*v&WZifC{zR!&sw|9*9 zqAZ;XL-&GZTizl=S30wqKpY7TJvw@!GnmrZF?hKy3{h{?szY(@@xF?;-ylmQ@X}O+bm71OTqj$5hhZyS>_h;$OtD2fz|JX;!#b|uDtWAOx0;s~!BFUw$AWTjO~)v%6I1cA z$!jjdc8B2G_`EIcin5o>Y*Cui1v9hB5DmB_i{3Np=Cw`kSn3@L zqh8gb(3U%sYHG1n;ZsZ5MD9t5Ru#^k9y*N`&Suf|S}@YMH1NLuWT=EO3LqjL~Zq zU5L_|%zg*UjvhhFrjO8fNTLYFLv`Q-Cg?sv%A|^$xJ9SBDQM>36nF%;>7Iy?SbYQr zXn#$Tg7P#+r&86j$0WyBx}NnAplP9p0a`{==a>%xpa02x6n8@N1#+hH5zkH^W8`o4 z!-38z!8q8%+SBy2o~`QOBneLC!(z| literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$DemoData.class b/target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$DemoData.class new file mode 100644 index 0000000000000000000000000000000000000000..aca24c441c07b2f33a2afcae7495feb6b1a4ccfb GIT binary patch literal 3166 zcmb_f-B%k$6#otRTDF0tYf4Ln(jv79wT-18+6G9F&_YcUO4?Xjt7i#ASWI?tvx_2r z)JGpY$5;IWeDfToT2PLjzUt8jkN<#wfUmxKytCPmw6%()^N^XnbLZaQ{hY~9e|`4@ zfDwEcKpR8CFiUZ@SmAMASuPu^oL7sBeBLf=dMR%5sufT3ijh_=^%B>)sal3PP^Ywm z!5f4RegY_#e0cv-Dh6HSD?Ws*x1%^HLNNB+Seo<WAy)7sq!56?Y3==H`u^~>vQHIc1WzH^(yjeY5R82177(>Un zsaaZ4ExV)`Id+=QYbrUZ=+O4yIGzjOL=Yztue;s0v~oP7RV{`#gFHUj>?Su}O)h^d z#SOx?II{Z`c|UCw38sY8loDCnta1V3tUz#%;oOdN{e$Ee8G>WFN~N^O$>yqr3lzO^ z)tuLivQb(MV3;Aj3x|&zwr-`#8>Ti#rWm?EB~fM5kdZ)2_$(`@a!L4iA&3$d zMU!?KA~mH{G}c<1rjo47@{Swx)S*KeP3Kv=GRMtp>Rg#9SDW3m-D7uAP4!DH!JuRe zYE1>z)PxRKkyoc~EA|=}fUAx!L2FSXgWL03Nmnh~B)-ehCzeyxE=$~Mv{i;Fx~N(( zu_20#m4=IS*E_e4CmJg-zWr5wNbhqqpA^Cxu4|NS0dU zq*1j3c$Z=5|Jz4>c1ou=igWdHiicEJMPaKi8@4m-eWZh?PEjUDD9yd8Zt<=GXr|W) zQ513Q0^x(=EkfUZqH9Yx(cm>Dc@tzHI51#l2y{(Jz^y+^59LPw!tJ#Rah>*IL*Q$-{9BieHdEa5m$retBDKCqWay# zF$Wm1*Y`cxtY;mb{H%AKn&6{8kziw`c8q<5eWVfW{1%;3j(E1vKdTHV&nnSP3@Xnn zLz_6Gyr7(?Dcl(jZ6Pu1jbLO0NwM^WXhB;p`K3BJg7gC$7aJS(qy7jcU232v<+5i3 zS2i$x7leYqA|r^ HlDq!~zGz|% literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$DemoDataParameters.class b/target/classes/org/acme/employeescheduling/rest/DemoDataGenerator$DemoDataParameters.class new file mode 100644 index 0000000000000000000000000000000000000000..ac72abc132987c5ac3a81f64109824dd13d8207d GIT binary patch literal 4019 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 literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/rest/EmployeeScheduleResource$Job.class b/target/classes/org/acme/employeescheduling/rest/EmployeeScheduleResource$Job.class new file mode 100644 index 0000000000000000000000000000000000000000..cfa9eca1d161b99f311de4fddf13c21eb56fbc48 GIT binary patch literal 2386 zcmbtVTTc@~6#k}Ab}0*ms(1%f)V8SghN$JDAPQR42q96Qw(VdS+MPPPMg31cXd)rO zL=zu;@JAWX>@IeZvKo2lTu#sV&UL>1@pJ17fC)TGAci&#?FQoLVCY>n*Uenjv|r_( z@sf~bhK_N|w%kdEwsdB>6FNFIBn))HV3-i{Rn9Ecc#hZVRq>8%A#gk_Aa!%il@gw61@za{B4QXT}#*uhYHO^ zmMT)bF^g56Pmp#>WqN>NA^l$tTjFMxQ&i1E2KsTBl5)kOE2#nui_uR0TA_R<%eDa9j;H7;Z(y5;-L_ z_uI7BJ1vCkxYDfqBjY4Ha65rK#x+bBn8XyrV6zsoVY?RbpkI@~ggB|Vjl%FTTvp3o z7i&D{E6$mAxyqg4f)HzsdOlR*;LV35f#K4-I=@G3E3LXKWY}b;YC29>5MaFA4HEXg zgKC1#>bOfC-{$E2Z+=ZOX!Pr5Fy?KWOV1^zx70?guHga0*=A)TGSxuSHV~~!E%D2O z%f#L>qNo^B>gz+Nlp=oGm7GYO)*-qr(B4LSGP?R`8wJ?sKjUJ&$Db3eIG~~cJj@0 zV)$A?)H>40v_fDM@GgY!I}oy7zJ2te83_=s(5}MOvRgO^{273sr5}J6WZ6d_j|(l# zj{xugh`+V@04@gRc%IWO)m>Z)H${|>~npP)r$5f5M( zwL>L8MDD}J-Tz`7$5k)WYt%#4u~CfC-a{vUvi!Na>B)#tsLwj?U>Y;HN3s;@>0~oY Lg}jeBJjBsoMBiW7 literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/rest/EmployeeScheduleResource.class b/target/classes/org/acme/employeescheduling/rest/EmployeeScheduleResource.class new file mode 100644 index 0000000000000000000000000000000000000000..0ccf75aeb37619e9f7e89b9740cc1761cb13851a GIT binary patch literal 11485 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 PzGJ&ox4K^)#;*SbIi2mU literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.class b/target/classes/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.class new file mode 100644 index 0000000000000000000000000000000000000000..de97bf51274fe69744e5387615785e6843c09dda GIT binary patch literal 1287 zcmb_b(M}UV6g^W~mez%0p%o}9VntXAqtB?(keYzCCR@TQ4%IGMHpoIu+-Fd%|yXyX!}8 zN7g<%@+@)#pJDQu>$}klhT?jCkk^bt*KhA^9A+_vtbv?~TQC{+gRsqo(~(?u&b;80 zl*&1gt*%GeJd`Tp^13yz^)i}ChHM7jxeSM(GpE7vUW=h{6IjE}n8;(67^+A_UBytL zybmIb1iw%`RNM(d$!)350$<5WGtSz{p@2C9^CpTYG0Y9_bZ`;|7vk8H47s+9-b$rJ zn}YfEjhh6tgbP}~MFwkxGD8*pzOh_oEE~9M;-03yI-W2Izt=dZ*^O8Aqh`%Mtl393 z+kR&=ycrEUR)HaE{V_76cY_vPHeYvr+30qTWq6QiQK$!w@D4@j>bQ59j!s-syk7r* z^WI@FI@g+K9MM%or#M7*pd-T+4QM}cN0zq9Y#G+#QH@oA2HXs~p(9_rdfJsSPTbZW zVKDc6UxvG$P)aHToT2=W@sTeRR(L>OP0_JbM_Y_aizmiq`j@#8M+(}TsVrc|!0a?ru>O8%iVvM_zRQGX9ecTe(@R)EJ)=}!A zaauK}jP(u1XWAr}nv4$@;)Z6D&}+!BL03z}87`jwyLfp-aSEF;L={`K=BP~>+j#PF F@ei@$EkghR literal 0 HcmV?d00001 diff --git a/target/classes/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.class b/target/classes/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.class new file mode 100644 index 0000000000000000000000000000000000000000..48aa4e5998b7b7672dcaffe6f250920d9cebe851 GIT binary patch literal 2045 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 literal 0 HcmV?d00001 diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..04ac5e6 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,14 @@ +org/acme/employeescheduling/domain/EmployeeSchedule.class +org/acme/employeescheduling/rest/DemoDataGenerator$CountDistribution.class +org/acme/employeescheduling/rest/DemoDataGenerator$DemoDataParameters.class +org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.class +org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.class +org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.class +org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.class +org/acme/employeescheduling/rest/EmployeeScheduleResource$Job.class +org/acme/employeescheduling/rest/EmployeeScheduleResource.class +org/acme/employeescheduling/rest/DemoDataGenerator.class +org/acme/employeescheduling/domain/Shift.class +org/acme/employeescheduling/domain/Employee.class +org/acme/employeescheduling/rest/exception/ErrorInfo.class +org/acme/employeescheduling/rest/DemoDataGenerator$DemoData.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..df48964 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,10 @@ +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/domain/Employee.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/domain/EmployeeSchedule.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/domain/Shift.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/DemoDataGenerator.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/rest/exception/ErrorInfo.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/main/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.java diff --git a/target/maven-status/maven-compiler-plugin/compile/null/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/null/createdFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/target/maven-status/maven-compiler-plugin/compile/null/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/null/inputFiles.lst new file mode 100644 index 0000000..55f3d04 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/compile/null/inputFiles.lst @@ -0,0 +1,10 @@ +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/domain/Employee.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/domain/EmployeeSchedule.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/domain/Shift.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/rest/DemoDataGenerator.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleDemoResource.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/rest/EmployeeScheduleResource.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverException.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/rest/exception/EmployeeScheduleSolverExceptionMapper.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/rest/exception/ErrorInfo.java +/home/virt/timefold-quickstarts/java/collect-sang/src/main/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProvider.java diff --git a/target/maven-status/maven-compiler-plugin/testCompile/null/createdFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/null/createdFiles.lst new file mode 100644 index 0000000..7d6a317 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/testCompile/null/createdFiles.lst @@ -0,0 +1,4 @@ +org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProviderTest.class +org/acme/employeescheduling/rest/EmployeeScheduleResourceTest.class +org/acme/employeescheduling/rest/EmployeeSchedulingEnvironmentTest.class +org/acme/employeescheduling/rest/EmployeeSchedulingResourceIT.class diff --git a/target/maven-status/maven-compiler-plugin/testCompile/null/inputFiles.lst b/target/maven-status/maven-compiler-plugin/testCompile/null/inputFiles.lst new file mode 100644 index 0000000..c6fe8c2 --- /dev/null +++ b/target/maven-status/maven-compiler-plugin/testCompile/null/inputFiles.lst @@ -0,0 +1,4 @@ +/home/virt/timefold-quickstarts/java/employee-scheduling/src/test/java/org/acme/employeescheduling/rest/EmployeeScheduleResourceTest.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/test/java/org/acme/employeescheduling/rest/EmployeeSchedulingEnvironmentTest.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/test/java/org/acme/employeescheduling/rest/EmployeeSchedulingResourceIT.java +/home/virt/timefold-quickstarts/java/employee-scheduling/src/test/java/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProviderTest.java diff --git a/target/quarkus/bootstrap/dev-app-model.dat b/target/quarkus/bootstrap/dev-app-model.dat new file mode 100644 index 0000000000000000000000000000000000000000..ff441c972e975c5d970df2460811b1504d9ff5d2 GIT binary patch literal 104224 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 Pus*0*8X{&vwEq7A6j@6~ literal 0 HcmV?d00001 diff --git a/target/test-classes/org/acme/employeescheduling/rest/EmployeeScheduleResourceTest.class b/target/test-classes/org/acme/employeescheduling/rest/EmployeeScheduleResourceTest.class new file mode 100644 index 0000000000000000000000000000000000000000..8df3bc6846f61d898ed6d4ba41bca74263625bfd GIT binary patch literal 5746 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 literal 0 HcmV?d00001 diff --git a/target/test-classes/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProviderTest.class b/target/test-classes/org/acme/employeescheduling/solver/EmployeeSchedulingConstraintProviderTest.class new file mode 100644 index 0000000000000000000000000000000000000000..6338494f0c31ce5fe27a63ab7f7f0656055a0289 GIT binary patch literal 8144 zcmcgxX?Ppe6+KU0WXqGpRyGm`2#^Gu7(@bLsY0mj*u=q3LS!5a6n89-mSTVQdvE5w z`|iExzI)G;-u&Z)5ska}%wB=2n%dT!=ivbS2uj_i3!GKsytK88SPAYH9yNWRhP55# zn2A|_%vNv+<_MfQkzGkMHmD^$yCR;&ji!;b613S`moNwQ9xc(XC23JG>b>aD5_+$$ zB?L}uRrQdi4`{t+tS98kv^YPc#`RD#Y9_Q0rD^IwC?hw$JRBru)e7d}P=OLP9*+$P z9FgO*-jorwbkhhm=*@07T!F(e-;W~{9Eqa@!Uv#%K!8rrdxzTlRGQf5B4WdsZ|mC0 zn;RjVF>SQbQB_(K_G6(y%|!6HVHfGsd#y4YEg+UibZZqHgT(?M}mla7LkfT0IA z>Vujg&{=a{meNk{2p<6a^~t1`u(7XTnp)w<=?cD&dVz-hR@@UQP#)I|HKt#rB?XFW zR@Zivp^?1?&FYhRs!1lPW`U!!!Srm(%}`}n#b8?+gg|u}&g2P6N67r8B|NY4r!0WA zSm(!C3f3dS)L@IS17c+=VTY4|-|SswrV`X>HZ{r$jr0^I!?ieDK?gR_0?TaEjTBRd zotRfkFLf$77v~97c-A#AK@``tIGOGT3NDaAJ)^$4y=ncLwQJX8od_BAKUAQ~3Bk;S zbnK@sDGoqGuOAx~^g*Yp8B20b5f4f{mP)Qvhp6AYTzhgRGN<`aofaRE;td6+lwB?* z*e;REZB~!~g_X!7xkO-QmWMov_Tfz_81!bIAo09V;z?I5%Y$dWsLe$eDH%Z9*mY!CFaTsKk_nwmGFIv>v>d6b0MX3l{K6MIx^)+Kt!riB-xkjKfB%OcdO zo1x7qHPN3+hHR?nxbQ6Jk?Xz62Gg`84~@66h?zafX{Fc`z_Zxv$8!pv#|r{S+Nr?i z5V|pF_LKRj1Km9;SE#*e)G`zFWW_-C=|09%YZX<7+h4&W8M z>c?ve9>MDZXB?!=B9N@fm*VW}zyueAW(TzVJgd-Ry5miOXKN-r#ru#j!r#3Ggyd}r z$sZKFBk`DSm}^HT5zcu}&Us(K2Xf9~c{4@(7SqW&oc>2S{UZfi@j6GJ$kC??hV9X3 za`d@^ZT9F(Ir>V$b}3kCF$^uy7*okylYV?7uyC9ckb89e_$#%Vcq&V&bIvfIRLDn4 z>Bn5jhuE7d*^b@vren9fy4Wq*p52nvv4y-}s4{Nw$fqX*av zu@&;kF*_l)vg5;p{4ZYvv+xlAE6xP`77ud-9*0uSl8gV&cT&My_rTv7EFVFI5Mn2) zT94U|8M~=1cHuA|O7_CnS+qFPS-b}eI)jUbQ8SFXU?{j`@lKo&*@csQ2<*c0BG_^o zf=foQax#+6$S0}XmXtAN5z49J0#srlY1tw)q6VvYQ#_ZRx)yb~f!DuV=m%-)EXN$z z)Jj~5NAVcVPy6q2&HwgCM)k!@%*}0f;<*7+t|p>UL+Vn?YqMJqMhCsW_3J zaV$d*PC^W);zES+0+!=doQ}81pQociRHI28jb1@N}6$G2TAc%TFaCY7xcqSbL zzAv31@SR*Z2sZ7{f$d^O8taED(U)~v_e*eHe!;$TCN0>Lkj}dkrJ1UI5S)|DGeYZT zpnnGj^6H(PY4*z<*?vBVr^Ci>QlV_1nxVXrq1?w%)^R?wS095pjsc`#;CI-J7a7=Z zuyVh{n*DF2n5!&tB(^Y@T_}2Su^8g#6qn)>aTR_nUdH9(JzOe2#uegoTpKb8Wy0QfaysmNwdt_;Rp$-+t?95A+uYo@%nkct#D`&xP?zj_W!G<(Z?|Gy zRx_#y z`t_sb449W43@{4_nLL<<1r-LffQ(6k zc|XB?fM7mIFdrhA4-?Es2LQoH7EmT1m|Q#hWR4KbT?BJC!Q4YI z_Y%zK2<8g}^Lc{#BH?<8V7^Q+e@`%9A(*cc%-0C!8wB&s{Q`5l2j&JR&Egx6U5wzm zQ83D}n_zEnVa(i*>YU3^QC3k;PZ}o+=Y@&uZ%o6SUO&#gWAyq={g$;botrZ$(NQhq z_!a!*7_4xWco*~WKEH7KfZyGGh$ehQ=YN8W@G&mKr?{GKe;i+s*MG@3pY!)Ce9d2Z z>#{jLzHw7wC8ao=em(&k%jwHlThq7KOXY2VKanc`w*H+lb6nTWtBH1ABtB_@rJy+#4Bfd!!Bu}u;-z*WOTWCdG~!Tx z6R?Btd}Ocpv6X6#u-(PKRlK(Erg|?j(%x`;Z+X3Uz21jj?_;m`C$IMfdw-_1040Bo Jzu<3}^FO)vW?29L literal 0 HcmV?d00001 diff --git a/vi b/vi new file mode 100644 index 0000000..18e541f --- /dev/null +++ b/vi @@ -0,0 +1,162 @@ +{ + "employees": [ + { + "name": "Marie Dupont", + "skills": ["INFIRMIER", "PRELEVEMENT"], + "unavailableDates": ["2024-12-25", "2024-12-26"], + "undesiredDates": ["2024-12-24", "2024-12-31"], + "desiredDates": ["2024-12-20", "2024-12-21"] + }, + { + "name": "Pierre Martin", + "skills": ["MEDECIN", "SUPERVISION"], + "unavailableDates": ["2024-12-30"], + "undesiredDates": ["2024-12-29"], + "desiredDates": ["2024-12-22", "2024-12-23"] + }, + { + "name": "Sophie Bernard", + "skills": ["INFIRMIER", "ACCUEIL"], + "unavailableDates": [], + "undesiredDates": ["2024-12-25"], + "desiredDates": ["2024-12-24", "2024-12-28"] + }, + { + "name": "Jean Leroy", + "skills": ["PRELEVEMENT", "TRANSPORT"], + "unavailableDates": ["2024-12-24", "2024-12-25"], + "undesiredDates": [], + "desiredDates": ["2024-12-27", "2024-12-30"] + }, + { + "name": "Anne Moreau", + "skills": ["MEDECIN", "INFIRMIER"], + "unavailableDates": ["2024-12-26"], + "undesiredDates": ["2024-12-31"], + "desiredDates": ["2024-12-21", "2024-12-29"] + }, + { + "name": "Luc Petit", + "skills": ["ACCUEIL", "TRANSPORT"], + "unavailableDates": [], + "undesiredDates": ["2024-12-20"], + "desiredDates": ["2024-12-25", "2024-12-26"] + } + ], + "shifts": [ + { + "id": "shift_001", + "start": "2024-12-20T08:00:00", + "end": "2024-12-20T16:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "INFIRMIER", + "employee": null + }, + { + "id": "shift_002", + "start": "2024-12-20T14:00:00", + "end": "2024-12-20T22:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "PRELEVEMENT", + "employee": null + }, + { + "id": "shift_003", + "start": "2024-12-21T06:00:00", + "end": "2024-12-21T14:00:00", + "location": "Hôpital Purpan", + "requiredSkill": "MEDECIN", + "employee": null + }, + { + "id": "shift_004", + "start": "2024-12-21T08:00:00", + "end": "2024-12-21T12:00:00", + "location": "Centre de collecte - Colomiers", + "requiredSkill": "ACCUEIL", + "employee": null + }, + { + "id": "shift_005", + "start": "2024-12-22T09:00:00", + "end": "2024-12-22T17:00:00", + "location": "Centre de collecte - Blagnac", + "requiredSkill": "INFIRMIER", + "employee": null + }, + { + "id": "shift_006", + "start": "2024-12-22T13:00:00", + "end": "2024-12-22T18:00:00", + "location": "Transport mobile", + "requiredSkill": "TRANSPORT", + "employee": null + }, + { + "id": "shift_007", + "start": "2024-12-23T07:00:00", + "end": "2024-12-23T15:00:00", + "location": "Hôpital Rangueil", + "requiredSkill": "MEDECIN", + "employee": null + }, + { + "id": "shift_008", + "start": "2024-12-23T10:00:00", + "end": "2024-12-23T16:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "PRELEVEMENT", + "employee": null + }, + { + "id": "shift_009", + "start": "2024-12-24T08:00:00", + "end": "2024-12-24T14:00:00", + "location": "Centre de collecte - Colomiers", + "requiredSkill": "INFIRMIER", + "employee": null + }, + { + "id": "shift_010", + "start": "2024-12-27T09:00:00", + "end": "2024-12-27T17:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "SUPERVISION", + "employee": null + }, + { + "id": "shift_011", + "start": "2024-12-28T08:00:00", + "end": "2024-12-28T16:00:00", + "location": "Centre de collecte - Blagnac", + "requiredSkill": "ACCUEIL", + "employee": null + }, + { + "id": "shift_012", + "start": "2024-12-29T06:00:00", + "end": "2024-12-29T14:00:00", + "location": "Hôpital Purpan", + "requiredSkill": "MEDECIN", + "employee": null + }, + { + "id": "shift_013", + "start": "2024-12-30T10:00:00", + "end": "2024-12-30T18:00:00", + "location": "Transport mobile", + "requiredSkill": "TRANSPORT", + "employee": null + }, + { + "id": "shift_014", + "start": "2024-12-31T08:00:00", + "end": "2024-12-31T16:00:00", + "location": "Centre de collecte - Toulouse", + "requiredSkill": "INFIRMIER", + "employee": null + } + ], + "score": null, + "solverStatus": null +}