Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
184 commits
Select commit Hold shift + click to select a range
eb54ed9
Fixed minor spelling mistake in comment
SamuelRoettgermann Jun 16, 2025
e3437d6
renamed warning and tooltip
SamuelRoettgermann Jun 16, 2025
d60eb17
changed the minimum valid value from 0 to 1
SamuelRoettgermann Jun 16, 2025
da3b4c8
deprecated an outdated validator
SamuelRoettgermann Jun 22, 2025
6732bf0
added tooltip for the number of exercises in exam
SamuelRoettgermann Jun 22, 2025
0bfaf7e
improved the deprecation message
SamuelRoettgermann Jun 22, 2025
8f1a3a6
add test for the min adjustment
SamuelRoettgermann Jun 22, 2025
f2efca0
initial setup
SamuelRoettgermann Jun 23, 2025
f021a56
URL is openable and calls correct REST endpoint, however not yet navi…
SamuelRoettgermann Jun 23, 2025
5a1cafb
added exam room button to admin dropdown
SamuelRoettgermann Jul 5, 2025
dca8ba1
created domain objects and liquibase changelog
SamuelRoettgermann Jul 7, 2025
a86f864
implemented the domain objects, defined the DB changes, and added two…
SamuelRoettgermann Jul 7, 2025
d8a6a90
added documentation for the entities
SamuelRoettgermann Jul 7, 2025
fa8356d
init setup of the exam room repository
SamuelRoettgermann Jul 7, 2025
d6a952c
added JSON include only non-empty for entities
SamuelRoettgermann Jul 7, 2025
7076ed7
changed coordinate types to float and added exam-room-id column to th…
SamuelRoettgermann Jul 7, 2025
2ec994b
follow up update on the liquibase column addition
SamuelRoettgermann Jul 7, 2025
da24105
added 2 more columns to ExamRoom to be able to store all possible nam…
SamuelRoettgermann Jul 7, 2025
b28dc45
added a few fields to the tables, and unfinished version of room parsing
SamuelRoettgermann Jul 11, 2025
cda2bb1
JSON serialization issue fixed -> Uploading rooms works, however room…
SamuelRoettgermann Jul 14, 2025
fdf6dc4
several logger limitations to make it more readable
SamuelRoettgermann Jul 19, 2025
f4988ca
fixed serialization issues, was more verbose in Java code
SamuelRoettgermann Jul 19, 2025
b64f67b
room parsing with capacity per layout instead of per room works, stil…
SamuelRoettgermann Jul 19, 2025
5ef3e88
liquibase changes according to the domain changes
SamuelRoettgermann Jul 19, 2025
7ec543c
parsing works, old & unused entries still need to be deleted, backend…
SamuelRoettgermann Jul 20, 2025
d067a1d
display the update information returned from the backend
SamuelRoettgermann Jul 20, 2025
efcecd3
added a new table exam_room_assignment, added planned seat entity to …
SamuelRoettgermann Jul 20, 2025
7491679
fixed auto-generated queries
SamuelRoettgermann Jul 21, 2025
a05b723
added a query to find all outdated exam rooms
SamuelRoettgermann Jul 21, 2025
915ae79
added backend code to return an exam room admin overview, aswell as f…
SamuelRoettgermann Jul 21, 2025
124a2ab
more of less logging
SamuelRoettgermann Jul 21, 2025
76c20f2
added exam room overview information and deletion button to admin ove…
SamuelRoettgermann Jul 21, 2025
3edb5bc
made the ExamSeat a JSON field in ExamRoom, rewrote a bunch of stuff …
SamuelRoettgermann Jul 21, 2025
720441f
converted ExamSeat from an entity to a DTO, added backend functionali…
SamuelRoettgermann Jul 27, 2025
03de792
removed examSeatEntity and examRoomEntity from ExamUser cause it's ju…
SamuelRoettgermann Jul 27, 2025
0d7eda1
fixed bugs arised from removing the examRoom reference from ExamUser,…
SamuelRoettgermann Jul 27, 2025
44f0e2e
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Jul 27, 2025
2c8a0a3
added capacity calculations, various cleanups, mental breakdown over …
SamuelRoettgermann Jul 28, 2025
6ec0c1f
various beautifications, now uses actual jhi-translate strings, still…
SamuelRoettgermann Jul 28, 2025
656116b
removed unrequired routing file
SamuelRoettgermann Aug 1, 2025
dc00bd4
added translations for English and German
SamuelRoettgermann Aug 1, 2025
a363397
added sorting functionality, moved functionality from template to com…
SamuelRoettgermann Aug 1, 2025
889a328
irrelevant
SamuelRoettgermann Aug 1, 2025
b6c9ab7
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Aug 2, 2025
8ed8f44
updated Liquibase changes to new date
SamuelRoettgermann Aug 2, 2025
7003ad3
removed custom Sass file
SamuelRoettgermann Aug 2, 2025
e2f3476
removed outdated client tests
SamuelRoettgermann Aug 3, 2025
3736c70
massively reduced the number of WriteableSignals, simplified logic to…
SamuelRoettgermann Aug 3, 2025
cf22303
added missing translations
SamuelRoettgermann Aug 3, 2025
85e2ed2
documented the backend code
SamuelRoettgermann Aug 3, 2025
44f715e
fixed client errors
SamuelRoettgermann Aug 3, 2025
9fa408b
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Aug 3, 2025
9392878
improved type-hint for string
SamuelRoettgermann Aug 3, 2025
a9c207a
added JSDoc to the TS code
SamuelRoettgermann Aug 3, 2025
16c4886
moved logic out of the template
SamuelRoettgermann Aug 3, 2025
28cb949
massively reduced DB calls
SamuelRoettgermann Aug 3, 2025
466afc6
moved a DTO-related enum from domain into DTO folder
SamuelRoettgermann Aug 3, 2025
a27a5e2
added a bit more documentation to the liquibase changelog
SamuelRoettgermann Aug 3, 2025
4cb0821
delete broken testing file
SamuelRoettgermann Aug 3, 2025
1d80bfc
clarified a comment
SamuelRoettgermann Aug 3, 2025
cab4585
fixed a wrong JavaDoc
SamuelRoettgermann Aug 3, 2025
8b8bf1b
fixed a display issue
SamuelRoettgermann Aug 3, 2025
25c587e
implemented all review suggestions from Lukas and CodeRabbit, and all…
SamuelRoettgermann Aug 8, 2025
7b2e245
prevent parallel uploads
SamuelRoettgermann Aug 8, 2025
5a40386
implemented Lukas suggestion to use Jackson for help with parsing the…
SamuelRoettgermann Aug 8, 2025
30ac592
reduced number of DB calls, added filename to the file-upload-button,…
SamuelRoettgermann Aug 9, 2025
ff90af4
fixed more coderabbit suggestions
SamuelRoettgermann Aug 9, 2025
c5cd592
fixed an error from a newly added test, that my code violated
SamuelRoettgermann Aug 9, 2025
d510ccc
fixed 2 more points of Lukas
SamuelRoettgermann Aug 9, 2025
0fd9652
one more coderabbit suggestion for protecting against foreign user input
SamuelRoettgermann Aug 9, 2025
9731204
fixed another issue because I used the wrong @NotNull annotation
SamuelRoettgermann Aug 9, 2025
a229956
changed translation for the safe delete button
SamuelRoettgermann Aug 10, 2025
0ffdb2a
made function names more intuitive, improved & fixed some JavaDoc
SamuelRoettgermann Aug 10, 2025
786a311
adapted recommended liquibase changes
SamuelRoettgermann Aug 11, 2025
b28ecd0
removed accidental changes, presumably from a develop merge
SamuelRoettgermann Aug 12, 2025
1f5299d
removed Getters and Setters markers
SamuelRoettgermann Aug 12, 2025
5c54d33
removed dangling JavaDoc comments, renamed fields to be more descript…
SamuelRoettgermann Aug 12, 2025
b4327fc
removed redundant code
SamuelRoettgermann Aug 12, 2025
5a1e408
removed redundant data sent via DTO, moved the calculations to the cl…
SamuelRoettgermann Aug 12, 2025
70969d1
made the delete not delete as a batch anymore to prevent potential da…
SamuelRoettgermann Aug 12, 2025
32ffad1
renamed idx to index
SamuelRoettgermann Aug 12, 2025
bb5f9d3
parsing seats and layouts now more often raise an exception rather th…
SamuelRoettgermann Aug 13, 2025
e2cfd5d
moved HTTP calls in a .service.ts file
SamuelRoettgermann Aug 13, 2025
54653f8
added NotNull to all DTOs; made capacity non-nullable
SamuelRoettgermann Aug 13, 2025
135c3f8
made ExamSeatDTOs coordinates double instead of float
SamuelRoettgermann Aug 14, 2025
f20e8e3
made examRoom load lazy in LayoutStrategy
SamuelRoettgermann Aug 14, 2025
d6a6e15
added Bean JSON validation to LayoutStrategy#parametersJson
SamuelRoettgermann Aug 14, 2025
2d30981
removed impossible to hit exception from catch clause
SamuelRoettgermann Aug 14, 2025
08f459b
pedantic import error
SamuelRoettgermann Aug 14, 2025
709b274
unified some duplicated duration formatting code
SamuelRoettgermann Aug 15, 2025
11e289a
removed the conirm/alert calls and instead use DeleteDialogService fo…
SamuelRoettgermann Aug 15, 2025
121fbee
code cleanup, using regular artemis alerts now instead of custom erro…
SamuelRoettgermann Aug 15, 2025
436474c
remove code nesting by using guard clauses
SamuelRoettgermann Aug 15, 2025
a819759
added text to empty error message for getting an error while getting …
SamuelRoettgermann Aug 15, 2025
3233321
now TS also uses the correct translation key
SamuelRoettgermann Aug 15, 2025
b821ba6
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Aug 15, 2025
f8c24a9
some CodeRabbit nitpicks
SamuelRoettgermann Aug 15, 2025
f790aae
partial recovery of test code, lost about 3 days worth of work due to…
SamuelRoettgermann Aug 24, 2025
3b9d5fd
Merge remote-tracking branch 'refs/remotes/origin/feature/exam-mode/a…
SamuelRoettgermann Aug 24, 2025
ae67da4
re-finished the service tests
SamuelRoettgermann Aug 24, 2025
3cf548f
integration tests
SamuelRoettgermann Aug 25, 2025
ff44bd5
fixed integration tests
SamuelRoettgermann Aug 25, 2025
1fb6e40
added a few more integration tests
SamuelRoettgermann Aug 25, 2025
6a402ca
finished backend tests, except for minor bugs
SamuelRoettgermann Aug 28, 2025
30d24c2
fixed all integration tests
SamuelRoettgermann Aug 28, 2025
6355bac
fixed code structural tests, code rabbit suggestion for using Void.cl…
SamuelRoettgermann Aug 28, 2025
49dbbf1
resolved merge conflict
SamuelRoettgermann Aug 29, 2025
efed2bc
added frontend tests
SamuelRoettgermann Aug 30, 2025
de448f4
added more frontend tests to increase coverage
SamuelRoettgermann Aug 30, 2025
681e033
fixed compilation failures due to new checkstyles
SamuelRoettgermann Aug 30, 2025
b9c7729
fixed client compilation issues, hopefully I didn
SamuelRoettgermann Aug 30, 2025
8fe63e7
of course I missed one case
SamuelRoettgermann Aug 30, 2025
c77c5b7
bunch of CodeRabbit suggestions
SamuelRoettgermann Aug 30, 2025
065f8ed
added file too big error in backend
SamuelRoettgermann Aug 30, 2025
1b3e19f
fixed chronological order in master.xml
SamuelRoettgermann Aug 30, 2025
d09220b
fixed typo in master.xml
SamuelRoettgermann Aug 30, 2025
6f98903
applied CodeRabbit suggestion
SamuelRoettgermann Aug 30, 2025
85a3465
applied CodeRabbit nitpick comment to get rid off an injected, but ne…
SamuelRoettgermann Aug 30, 2025
172d3d3
talked with CodeRabbit and now use a more specific, albeit sometimes …
SamuelRoettgermann Aug 30, 2025
9c3a39c
applied more CodeRabbit suggestions
SamuelRoettgermann Aug 30, 2025
b5caf15
applied some CodeRabbit nitpick comments
SamuelRoettgermann Aug 30, 2025
142cf31
more CodeRabbit fixes
SamuelRoettgermann Aug 30, 2025
4cc239a
fixed wrong reading of seat condition flags, and IO exception
SamuelRoettgermann Aug 31, 2025
8d004b1
first round of Tobias change requests
SamuelRoettgermann Sep 6, 2025
b0d15d0
rest of Tobi's change requests + CodeRabbit change requests
SamuelRoettgermann Sep 6, 2025
571cd49
fixed a few last compilation errors and finally found and fixed a nas…
SamuelRoettgermann Sep 6, 2025
1ac17d7
CodeRabbit suggestions
SamuelRoettgermann Sep 6, 2025
67a160a
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Sep 6, 2025
327a7a3
improved comment clarity even more
SamuelRoettgermann Sep 6, 2025
87aa963
improved documentation and usability
SamuelRoettgermann Sep 6, 2025
4baac6e
added tests for new pipe to meet coverage threshold
SamuelRoettgermann Sep 6, 2025
052b774
removed a test that worked locally but failed for type safety things …
SamuelRoettgermann Sep 6, 2025
32c2ef3
initial commit
SamuelRoettgermann Sep 8, 2025
771647f
applied Tobi's last fixes
SamuelRoettgermann Sep 8, 2025
0fa2580
still missing 2 german and all english translations, added transient …
SamuelRoettgermann Sep 9, 2025
28b0627
removed some unnecessary String.valueOf wrappers
SamuelRoettgermann Sep 10, 2025
fd6b28a
removed formatting disabled blocks
SamuelRoettgermann Sep 10, 2025
24ee19f
removed all <p></p> instances for spacing from the template
SamuelRoettgermann Sep 10, 2025
2e0aac8
code rabbit language fix, and also removed unused translation strings
SamuelRoettgermann Sep 10, 2025
1459597
fixed a bug Marlon found on Chrome and Safari; fixed a bug with displ…
SamuelRoettgermann Sep 10, 2025
2c51429
added padding to the upload and deletion card titles
SamuelRoettgermann Sep 10, 2025
404b792
Merge branch 'feature/exam-mode/add-room-data-insertion-admin-panel' …
SamuelRoettgermann Sep 11, 2025
aa0f040
added REST endpoint for simple distributions, only to the default dis…
SamuelRoettgermann Sep 11, 2025
be6f573
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Sep 12, 2025
6d2dbd9
minor code beautification
SamuelRoettgermann Sep 12, 2025
9de7f05
added fixed selection support; made the fixed selection fail-early i.…
SamuelRoettgermann Sep 12, 2025
ff5c4b9
re-added accidently deleted repository function
SamuelRoettgermann Sep 12, 2025
b84ba36
improved error message a bit; still need to add translation keys
SamuelRoettgermann Sep 12, 2025
8d9ac66
added the room ID to the admin overview page
SamuelRoettgermann Sep 12, 2025
76eb651
simplified & optimized a query
SamuelRoettgermann Sep 12, 2025
8c10817
fixed bug showing all exam rooms rather than just the newest one
SamuelRoettgermann Sep 12, 2025
916933c
minor formatting fix
SamuelRoettgermann Sep 12, 2025
0bc9f62
added i18n translations, and removed some unnecessary logging
SamuelRoettgermann Sep 12, 2025
180a86b
reset the planned room and seat fields on exam room deletion
SamuelRoettgermann Sep 12, 2025
3fb7858
code cleanup, and fixed a bug where it deleted old exam room assignme…
SamuelRoettgermann Sep 12, 2025
6175031
removed transient fields that were not yet used, but a good chunk of …
SamuelRoettgermann Sep 12, 2025
8afac7d
minor code cleanup and performance optimization; also made the JavaDo…
SamuelRoettgermann Sep 12, 2025
362b56e
added default capacity display to the admin overview
SamuelRoettgermann Sep 12, 2025
11236a7
fixed tests related to the realistic exam room zip file scenario
SamuelRoettgermann Sep 12, 2025
0e2021d
fixed some examRepositoryArchitectureTests
SamuelRoettgermann Sep 13, 2025
d884e13
this PR fixes the examRepositoryArchitectureTest; the previous commit…
SamuelRoettgermann Sep 13, 2025
484ad2c
a lot of code rabbit suggestions and nitpicks
SamuelRoettgermann Sep 13, 2025
69bf6f2
one additional coderabbit suggestion to make a query more in-line wit…
SamuelRoettgermann Sep 13, 2025
342b6a0
batch save instead of individual saves
SamuelRoettgermann Sep 14, 2025
edabd3e
more CodeRabbit nitpicks
SamuelRoettgermann Sep 14, 2025
2dee634
Tobi's fixes
SamuelRoettgermann Sep 15, 2025
5efcd60
CodeRabbit query re-reversal
SamuelRoettgermann Sep 15, 2025
c7ff242
last of Tobi's suggestion to move code into new service & resource
SamuelRoettgermann Sep 15, 2025
9e36dfc
more CodeRabbit suggestions
SamuelRoettgermann Sep 15, 2025
4704f32
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Sep 15, 2025
c01bc32
fixed query for Postgres (json type doesnt have a comparison and DIST…
SamuelRoettgermann Sep 15, 2025
c593a6b
Review suggestions
SamuelRoettgermann Sep 17, 2025
3ce8a0c
one code rabbit suggestion and minor spelling changes
SamuelRoettgermann Sep 21, 2025
e2067cc
code rabbit suggestion for a key-bug fiX
SamuelRoettgermann Sep 22, 2025
c8a4988
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Sep 22, 2025
250e897
fixed a JavaDoc
SamuelRoettgermann Sep 22, 2025
79e252b
applied Tobi's change
SamuelRoettgermann Sep 24, 2025
203fa00
Merge remote-tracking branch 'refs/remotes/origin/feature/exam-mode/s…
SamuelRoettgermann Sep 24, 2025
23942e9
removed the 'delete all exam rooms including the newest version' feature
SamuelRoettgermann Oct 1, 2025
f71e17d
removed global reset of exam users
SamuelRoettgermann Oct 2, 2025
21b93a6
Merge branch 'chore/exam-mode/remove-delete-all-rooms-functionality' …
SamuelRoettgermann Oct 2, 2025
1672f55
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Oct 3, 2025
1a18996
adapted programming branch coverage by -0.04
SamuelRoettgermann Oct 3, 2025
3da297d
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Oct 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record ExamRoomDTO(@NotNull String roomNumber, @NotNull String name, @NotNull String building, int numberOfSeats, @NotNull Set<ExamRoomLayoutStrategyDTO> layoutStrategies) {
public record ExamRoomDTO(long id, @NotNull String roomNumber, @NotNull String name, @NotNull String building, int numberOfSeats,
@NotNull Set<ExamRoomLayoutStrategyDTO> layoutStrategies) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.tum.cit.aet.artemis.exam.repository;

import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import de.tum.cit.aet.artemis.core.repository.base.ArtemisJpaRepository;
import de.tum.cit.aet.artemis.exam.config.ExamEnabled;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoomExamAssignment;

/**
* Spring Data JPA repository for the {@link de.tum.cit.aet.artemis.exam.domain.room.ExamRoomExamAssignment} entity.
*/
@Conditional(ExamEnabled.class)
@Lazy
@Repository
public interface ExamRoomExamAssignmentRepository extends ArtemisJpaRepository<ExamRoomExamAssignment, Long> {

@Transactional
@Modifying
void deleteAllByExamId(long examId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

Expand Down Expand Up @@ -49,7 +50,32 @@ HAVING COUNT(*) > 1
ON examRoom.roomNumber = latestRoom.roomNumber
AND examRoom.name = latestRoom.name
AND examRoom.createdDate < latestRoom.maxCreatedDate
WHERE examRoom.id NOT IN ( SELECT DISTINCT erea.examRoom.id FROM ExamRoomExamAssignment erea )
WHERE NOT EXISTS (
SELECT 1
FROM ExamRoomExamAssignment erea
WHERE erea.examRoom.id = examRoom.id
)
""")
Set<Long> findAllIdsOfOutdatedAndUnusedExamRooms();

/**
* Returns IDs of the current (latest) version of each unique exam room (roomNumber, name).
*
* @return All IDs of the current exam rooms
*/
@Query("""
SELECT id
FROM (
SELECT er.id AS id, er.roomNumber AS roomNumber, er.name AS name, er.createdDate AS createdDate, ROW_NUMBER() OVER (
PARTITION BY er.roomNumber, er.name
ORDER BY er.createdDate DESC, er.id DESC
) AS rowNumber
FROM ExamRoom er
)
WHERE rowNumber = 1
""")
Set<Long> findAllIdsOfCurrentExamRooms();

@EntityGraph(type = EntityGraph.EntityGraphType.LOAD, attributePaths = { "layoutStrategies" })
Set<ExamRoom> findAllWithEagerLayoutStrategiesByIdIn(Set<Long> ids);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package de.tum.cit.aet.artemis.exam.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.validation.constraints.NotEmpty;

import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
import de.tum.cit.aet.artemis.exam.config.ExamEnabled;
import de.tum.cit.aet.artemis.exam.domain.Exam;
import de.tum.cit.aet.artemis.exam.domain.ExamUser;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoom;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoomExamAssignment;
import de.tum.cit.aet.artemis.exam.dto.room.ExamSeatDTO;
import de.tum.cit.aet.artemis.exam.repository.ExamRepository;
import de.tum.cit.aet.artemis.exam.repository.ExamRoomExamAssignmentRepository;
import de.tum.cit.aet.artemis.exam.repository.ExamRoomRepository;
import de.tum.cit.aet.artemis.exam.repository.ExamUserRepository;

/**
* Service Implementation for managing distributions of exam users to exam rooms in an exam.
*/
@Conditional(ExamEnabled.class)
@Lazy
@Service
public class ExamRoomDistributionService {

private static final String ENTITY_NAME = "examRoomDistributionService";

private final ExamRepository examRepository;

private final ExamRoomRepository examRoomRepository;

private final ExamRoomService examRoomService;

private final ExamRoomExamAssignmentRepository examRoomExamAssignmentRepository;

private final ExamUserRepository examUserRepository;

public ExamRoomDistributionService(ExamRepository examRepository, ExamRoomRepository examRoomRepository, ExamRoomService examRoomService,
ExamRoomExamAssignmentRepository examRoomExamAssignmentRepository, ExamUserRepository examUserRepository) {
this.examRepository = examRepository;
this.examRoomRepository = examRoomRepository;
this.examRoomService = examRoomService;
this.examRoomExamAssignmentRepository = examRoomExamAssignmentRepository;
this.examUserRepository = examUserRepository;
}

/**
* Distribute all students who are registered for a given exam across a selection of rooms.
* Existing planned seats and room assignments are replaced.
*
* @param examId The exam
* @param examRoomIds The ids of the rooms to distribute to
* @implNote Currently only the "default" layout strategy is used.
*/
public void distributeRegisteredStudents(long examId, @NotEmpty Set<Long> examRoomIds) {
final Exam exam = examRepository.findByIdWithExamUsersElseThrow(examId);
final Set<ExamRoom> examRoomsForExam = examRoomRepository.findAllWithEagerLayoutStrategiesByIdIn(examRoomIds);

final int numberOfUsableSeats = examRoomsForExam.stream().mapToInt(examRoom -> examRoomService.getDefaultLayoutStrategyOrElseThrow(examRoom).getCapacity()).sum();
final int numberOfExamUsers = exam.getExamUsers().size();

if (numberOfUsableSeats < numberOfExamUsers) {
throw new BadRequestAlertException("Not enough seats available in the selected rooms", ENTITY_NAME, "notEnoughExamSeats",
Map.of("numberOfUsableSeats", numberOfUsableSeats, "numberOfExamUsers", numberOfExamUsers));
}

examRoomExamAssignmentRepository.deleteAllByExamId(examId);
List<ExamRoomExamAssignment> examRoomExamAssignments = new ArrayList<>();
for (ExamRoom examRoom : examRoomsForExam) {
var examRoomExamAssignment = new ExamRoomExamAssignment();
examRoomExamAssignment.setExamRoom(examRoom);
examRoomExamAssignment.setExam(exam);
examRoomExamAssignments.add(examRoomExamAssignment);
}
examRoomExamAssignmentRepository.saveAll(examRoomExamAssignments);

distributeExamUsersToUsableSeatsInRooms(exam, examRoomsForExam);
}

private void distributeExamUsersToUsableSeatsInRooms(Exam exam, Set<ExamRoom> examRoomsForExam) {
Map<String, List<ExamSeatDTO>> roomNumberToUsableSeatsDefaultLayout = new HashMap<>();
for (ExamRoom examRoom : examRoomsForExam) {
roomNumberToUsableSeatsDefaultLayout.put(examRoom.getRoomNumber(), examRoomService.getDefaultUsableSeats(examRoom));
}

setPlannedRoomAndPlannedSeatForExamUsersRandomly(exam, roomNumberToUsableSeatsDefaultLayout);

examUserRepository.saveAll(exam.getExamUsers());
examRepository.save(exam);
}

private void setPlannedRoomAndPlannedSeatForExamUsersRandomly(Exam exam, Map<String, List<ExamSeatDTO>> roomNumberToUsableSeats) {
Iterator<ExamUser> examUsersIterator = exam.getExamUsers().iterator();

for (var roomNumberToUsableSeatsEntry : roomNumberToUsableSeats.entrySet()) {
final String roomNumber = roomNumberToUsableSeatsEntry.getKey();
final List<ExamSeatDTO> usableSeatsForThisRoom = roomNumberToUsableSeatsEntry.getValue();

for (ExamSeatDTO seat : usableSeatsForThisRoom) {
if (!examUsersIterator.hasNext()) {
return;
}

ExamUser nextExamUser = examUsersIterator.next();
nextExamUser.setPlannedRoom(roomNumber);
nextExamUser.setPlannedSeat(seat.name());
exam.addExamUser(nextExamUser);
}
}
}
}
Loading
Loading