diff --git a/docs/user/exams/student/access_exam.png b/docs/user/exams/student/access_exam.png
index 76a0dddd02f3..a3579e5fc874 100644
Binary files a/docs/user/exams/student/access_exam.png and b/docs/user/exams/student/access_exam.png differ
diff --git a/docs/user/exams/student/buttons/exam_hand_in_early.png b/docs/user/exams/student/buttons/exam_hand_in_early.png
index d443c4116554..266d30608fbf 100644
Binary files a/docs/user/exams/student/buttons/exam_hand_in_early.png and b/docs/user/exams/student/buttons/exam_hand_in_early.png differ
diff --git a/docs/user/exams/student/buttons/save_exercise.png b/docs/user/exams/student/buttons/save_exercise.png
new file mode 100644
index 000000000000..7e16a5f622b5
Binary files /dev/null and b/docs/user/exams/student/buttons/save_exercise.png differ
diff --git a/docs/user/exams/student/buttons/upload.png b/docs/user/exams/student/buttons/upload.png
new file mode 100644
index 000000000000..cbe7b44079f7
Binary files /dev/null and b/docs/user/exams/student/buttons/upload.png differ
diff --git a/docs/user/exams/student/exam_bar.png b/docs/user/exams/student/exam_bar.png
index d1a4728bcc57..02914123a784 100644
Binary files a/docs/user/exams/student/exam_bar.png and b/docs/user/exams/student/exam_bar.png differ
diff --git a/docs/user/exams/student/exam_modeling_exercises.png b/docs/user/exams/student/exam_modeling_exercises.png
index 037cb07283aa..8fdd0912935e 100644
Binary files a/docs/user/exams/student/exam_modeling_exercises.png and b/docs/user/exams/student/exam_modeling_exercises.png differ
diff --git a/docs/user/exams/student/exam_navigation_sidebar.png b/docs/user/exams/student/exam_navigation_sidebar.png
index e8455e426df5..f6a45add9523 100644
Binary files a/docs/user/exams/student/exam_navigation_sidebar.png and b/docs/user/exams/student/exam_navigation_sidebar.png differ
diff --git a/docs/user/exams/student/exam_overview.png b/docs/user/exams/student/exam_overview.png
index eab66ecf60a7..84a85532187c 100644
Binary files a/docs/user/exams/student/exam_overview.png and b/docs/user/exams/student/exam_overview.png differ
diff --git a/docs/user/exams/student/exam_programming_exercises.png b/docs/user/exams/student/exam_programming_exercises.png
index b2018403e57a..1956f4fd173d 100644
Binary files a/docs/user/exams/student/exam_programming_exercises.png and b/docs/user/exams/student/exam_programming_exercises.png differ
diff --git a/docs/user/exams/student/exam_quiz_exercises.png b/docs/user/exams/student/exam_quiz_exercises.png
index 32c8d3634610..0c4bed59d3f6 100644
Binary files a/docs/user/exams/student/exam_quiz_exercises.png and b/docs/user/exams/student/exam_quiz_exercises.png differ
diff --git a/docs/user/exams/student/exam_text_exercises.png b/docs/user/exams/student/exam_text_exercises.png
index f81591045eb6..d79126ed398f 100644
Binary files a/docs/user/exams/student/exam_text_exercises.png and b/docs/user/exams/student/exam_text_exercises.png differ
diff --git a/docs/user/exams/students_guide.rst b/docs/user/exams/students_guide.rst
index b38278b75d22..f56f5fa94894 100644
--- a/docs/user/exams/students_guide.rst
+++ b/docs/user/exams/students_guide.rst
@@ -105,6 +105,14 @@ Welcome Screen
Welcome Screen, waiting for exam start
+This video offers a detailed guide on accessing your exams:
+
+.. raw:: html
+
+
+
Exam Conduction
^^^^^^^^^^^^^^^
- Once the exam working time starts and you have confirmed your participation, the *Exercise Overview* screen will appear. This screen lists all exercises that are part of your exam with their respective amount of points, title and exercise type. The status column indicates the status of each exercise and whether you have a submission in them or not.
@@ -132,6 +140,14 @@ Exam Conduction
Exam Navigation Sidebar
+- You have two options to save your changes for an exercise:
+
+ 1. Click the |save_exercise| button to manually save and submit your changes.
+ 2. Select an exercise in the navigation sidebar (either the current one or a different exercise), which will automatically save and submit your changes.
+
+ .. warning::
+ The |save_exercise| button is only available for text, modeling, and quiz exercises. For file upload exercises, you need to manually click the |upload| button, and for programming exercises, you need to manually click the |submit| button to save and submit your changes.
+
- On the header, you will find the exam bar that includes the remaining time and the |exam_hand_in_early| button. If you click this button, you will be sent to the exam `End Screen`_.
- The *time left* until the end of the exam is also shown next to the button.
@@ -373,6 +389,14 @@ Summary
Complaining about the Assessment of a Text Exercise
+This video offers a detailed guide on participating in your exams:
+
+.. raw:: html
+
+
+
Example Solutions
^^^^^^^^^^^^^^^^^
- If the instructor sets the example solution publication date of the exam, the solutions will be available after that date.
@@ -470,3 +494,5 @@ Grades
.. |exam_no_results_found| image:: student/buttons/exam_no_results_found.png
.. |exam_hand_in_early| image:: student/buttons/exam_hand_in_early.png
.. |saved_exercises| image:: student/buttons/saved_exercises.png
+.. |upload| image:: student/buttons/upload.png
+.. |save_exercise| image:: student/buttons/save_exercise.png
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
index 705c162c6341..3b0a4bc083c9 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
@@ -51,8 +51,7 @@ public CompetencyService(CompetencyRepository competencyRepository, Authorizatio
LearningObjectImportService learningObjectImportService, CompetencyLectureUnitLinkRepository competencyLectureUnitLinkRepository, CourseRepository courseRepository,
CompetencyExerciseLinkRepository competencyExerciseLinkRepository) {
super(competencyProgressRepository, courseCompetencyRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService,
- learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService,
- competencyLectureUnitLinkRepository, courseRepository);
+ learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService, courseRepository);
this.competencyRepository = competencyRepository;
this.competencyExerciseLinkRepository = competencyExerciseLinkRepository;
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
index cbe33e70b710..88cad15f1000 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
@@ -30,7 +30,6 @@
import de.tum.cit.aet.artemis.atlas.dto.CompetencyRelationDTO;
import de.tum.cit.aet.artemis.atlas.dto.CompetencyWithTailRelationDTO;
import de.tum.cit.aet.artemis.atlas.dto.UpdateCourseCompetencyRelationDTO;
-import de.tum.cit.aet.artemis.atlas.repository.CompetencyLectureUnitLinkRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyProgressRepository;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyRelationRepository;
import de.tum.cit.aet.artemis.atlas.repository.CourseCompetencyRepository;
@@ -83,15 +82,13 @@ public class CourseCompetencyService {
private final LearningObjectImportService learningObjectImportService;
- private final CompetencyLectureUnitLinkRepository competencyLectureUnitLinkRepository;
-
private final CourseRepository courseRepository;
public CourseCompetencyService(CompetencyProgressRepository competencyProgressRepository, CourseCompetencyRepository courseCompetencyRepository,
CompetencyRelationRepository competencyRelationRepository, CompetencyProgressService competencyProgressService, ExerciseService exerciseService,
LectureUnitService lectureUnitService, LearningPathService learningPathService, AuthorizationCheckService authCheckService,
StandardizedCompetencyRepository standardizedCompetencyRepository, LectureUnitCompletionRepository lectureUnitCompletionRepository,
- LearningObjectImportService learningObjectImportService, CompetencyLectureUnitLinkRepository competencyLectureUnitLinkRepository, CourseRepository courseRepository) {
+ LearningObjectImportService learningObjectImportService, CourseRepository courseRepository) {
this.competencyProgressRepository = competencyProgressRepository;
this.courseCompetencyRepository = courseCompetencyRepository;
this.competencyRelationRepository = competencyRelationRepository;
@@ -103,7 +100,6 @@ public CourseCompetencyService(CompetencyProgressRepository competencyProgressRe
this.standardizedCompetencyRepository = standardizedCompetencyRepository;
this.lectureUnitCompletionRepository = lectureUnitCompletionRepository;
this.learningObjectImportService = learningObjectImportService;
- this.competencyLectureUnitLinkRepository = competencyLectureUnitLinkRepository;
this.courseRepository = courseRepository;
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
index eb66a98d641f..96a68280f334 100644
--- a/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
@@ -43,8 +43,7 @@ public PrerequisiteService(PrerequisiteRepository prerequisiteRepository, Author
StandardizedCompetencyRepository standardizedCompetencyRepository, CourseCompetencyRepository courseCompetencyRepository, ExerciseService exerciseService,
LearningObjectImportService learningObjectImportService, CompetencyLectureUnitLinkRepository competencyLectureUnitLinkRepository, CourseRepository courseRepository) {
super(competencyProgressRepository, courseCompetencyRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService,
- learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService,
- competencyLectureUnitLinkRepository, courseRepository);
+ learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService, courseRepository);
this.prerequisiteRepository = prerequisiteRepository;
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/repository/ConversationMessageRepository.java b/src/main/java/de/tum/cit/aet/artemis/communication/repository/ConversationMessageRepository.java
index 21b3dfac0b81..2952c5213432 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/repository/ConversationMessageRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/repository/ConversationMessageRepository.java
@@ -137,21 +137,4 @@ default Post findMessagePostByIdElseThrow(Long postId) throws EntityNotFoundExce
WHERE p.id = :postId AND answer.author = cp.user
""")
Set findUsersWhoRepliedInMessage(@Param("postId") Long postId);
-
- /**
- * Finds tags of course-wide messages
- *
- * @param courseId the course
- * @return list of tags
- */
- // TODO: unused, delete
- @Query("""
- SELECT DISTINCT tag
- FROM Post post
- LEFT JOIN post.tags tag
- LEFT JOIN Channel channel ON channel.id = post.conversation.id
- WHERE channel.course.id = :courseId
- AND channel.isCourseWide = TRUE
- """)
- List findPostTagsForCourse(@Param("courseId") Long courseId);
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/service/ConversationMessagingService.java b/src/main/java/de/tum/cit/aet/artemis/communication/service/ConversationMessagingService.java
index 0020deca7faf..a54058431b76 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/service/ConversationMessagingService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/service/ConversationMessagingService.java
@@ -3,8 +3,6 @@
import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;
import java.time.ZonedDateTime;
-import java.util.Comparator;
-import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -24,8 +22,6 @@
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
-import com.google.common.collect.Lists;
-
import de.tum.cit.aet.artemis.communication.domain.ConversationNotificationRecipientSummary;
import de.tum.cit.aet.artemis.communication.domain.CreatedConversationMessage;
import de.tum.cit.aet.artemis.communication.domain.DisplayPriority;
@@ -49,7 +45,6 @@
import de.tum.cit.aet.artemis.communication.service.conversation.auth.ChannelAuthorizationService;
import de.tum.cit.aet.artemis.communication.service.notifications.ConversationNotificationService;
import de.tum.cit.aet.artemis.communication.service.notifications.GroupNotificationService;
-import de.tum.cit.aet.artemis.communication.service.similarity.PostSimilarityComparisonStrategy;
import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.core.domain.User;
import de.tum.cit.aet.artemis.core.exception.AccessForbiddenException;
@@ -66,8 +61,6 @@
@Service
public class ConversationMessagingService extends PostingService {
- private static final int TOP_K_SIMILARITY_RESULTS = 5;
-
private static final Logger log = LoggerFactory.getLogger(ConversationMessagingService.class);
private final ConversationService conversationService;
@@ -82,14 +75,11 @@ public class ConversationMessagingService extends PostingService {
private final SingleUserNotificationRepository singleUserNotificationRepository;
- private final PostSimilarityComparisonStrategy postContentCompareStrategy;
-
protected ConversationMessagingService(CourseRepository courseRepository, ExerciseRepository exerciseRepository, LectureRepository lectureRepository,
ConversationMessageRepository conversationMessageRepository, AuthorizationCheckService authorizationCheckService, WebsocketMessagingService websocketMessagingService,
UserRepository userRepository, ConversationService conversationService, ConversationParticipantRepository conversationParticipantRepository,
ConversationNotificationService conversationNotificationService, ChannelAuthorizationService channelAuthorizationService,
- GroupNotificationService groupNotificationService, SingleUserNotificationRepository singleUserNotificationRepository,
- PostSimilarityComparisonStrategy postContentCompareStrategy) {
+ GroupNotificationService groupNotificationService, SingleUserNotificationRepository singleUserNotificationRepository) {
super(courseRepository, userRepository, exerciseRepository, lectureRepository, authorizationCheckService, websocketMessagingService, conversationParticipantRepository);
this.conversationService = conversationService;
this.conversationMessageRepository = conversationMessageRepository;
@@ -97,7 +87,6 @@ protected ConversationMessagingService(CourseRepository courseRepository, Exerci
this.channelAuthorizationService = channelAuthorizationService;
this.groupNotificationService = groupNotificationService;
this.singleUserNotificationRepository = singleUserNotificationRepository;
- this.postContentCompareStrategy = postContentCompareStrategy;
}
/**
@@ -433,41 +422,6 @@ private Conversation mayUpdateOrDeleteMessageElseThrow(Post existingMessagePost,
}
}
- /**
- * Calculates k similar posts based on the underlying content comparison strategy
- *
- * @param courseId id of the course in which similar posts are searched for
- * @param post post that is to be created and check for similar posts beforehand
- * @return list of similar posts
- */
- // TODO: unused, remove
- public List getSimilarPosts(Long courseId, Post post) {
- PostContextFilterDTO postContextFilter = new PostContextFilterDTO(courseId, null, null, null, null, false, false, false, null, null);
- List coursePosts = this.getCourseWideMessages(Pageable.unpaged(), postContextFilter, userRepository.getUser(), courseId).stream()
- .sorted(Comparator.comparing(coursePost -> postContentCompareStrategy.performSimilarityCheck(post, coursePost))).toList();
-
- // sort course posts by calculated similarity scores
- setAuthorRoleOfPostings(coursePosts, courseId);
- return Lists.reverse(coursePosts).stream().limit(TOP_K_SIMILARITY_RESULTS).toList();
- }
-
- /**
- * Checks course and user validity,
- * retrieves all tags for posts in a certain course
- *
- * @param courseId id of the course the tags belongs to
- * @return tags of all posts that belong to the course
- */
- // TODO: unused, delete
- public List getAllCourseTags(Long courseId) {
- final User user = userRepository.getUserWithGroupsAndAuthorities();
- final Course course = courseRepository.findByIdElseThrow(courseId);
-
- // checks
- preCheckUserAndCourseForCommunicationOrMessaging(user, course);
- return conversationMessageRepository.findPostTagsForCourse(courseId);
- }
-
@Override
public String getEntityName() {
return METIS_POST_ENTITY_NAME;
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/service/similarity/PostSimilarityComparisonStrategy.java b/src/main/java/de/tum/cit/aet/artemis/communication/service/similarity/PostSimilarityComparisonStrategy.java
deleted file mode 100644
index 93ca9de0c9f9..000000000000
--- a/src/main/java/de/tum/cit/aet/artemis/communication/service/similarity/PostSimilarityComparisonStrategy.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package de.tum.cit.aet.artemis.communication.service.similarity;
-
-import de.tum.cit.aet.artemis.communication.domain.Post;
-
-/**
- * This interface offers a method that performs a similarity check on two posts that are compared to each other.
- * Every strategy that implements this interface has to provide this method in order to be applicable as post similarity comparison strategy, that can be interchanged easily.
- */
-public interface PostSimilarityComparisonStrategy {
-
- /**
- * Method implemented by every strategy; compares two posts using any suitable algorithm to determine similarity
- *
- * @param post1 first post object that is compared against
- * @param post2 second post object that is compared against
- * @return the calculated similarity score
- */
- Double performSimilarityCheck(Post post1, Post post2);
-}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/service/similarity/TitleJaccardSimilarityCompareStrategy.java b/src/main/java/de/tum/cit/aet/artemis/communication/service/similarity/TitleJaccardSimilarityCompareStrategy.java
deleted file mode 100644
index 53e7285cd41b..000000000000
--- a/src/main/java/de/tum/cit/aet/artemis/communication/service/similarity/TitleJaccardSimilarityCompareStrategy.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package de.tum.cit.aet.artemis.communication.service.similarity;
-
-import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;
-
-import org.apache.commons.text.similarity.JaccardSimilarity;
-import org.springframework.context.annotation.Primary;
-import org.springframework.context.annotation.Profile;
-import org.springframework.stereotype.Component;
-
-import de.tum.cit.aet.artemis.communication.domain.Post;
-
-/**
- * Implementation of a PostSimilarityComparisonStrategy to be used when searching for duplicates during post creation.
- * Jaccard Similarity is a common proximity measurement used to compute the similarity between two objects, such as two text documents;
- * In the context of post comparison, the TitleJaccardSimilarityCompareStrategy determines the similarity between two titles (i.e. document) using the number of terms used in both
- * documents.
- * We use the JaccardSimilarity implementation provided by the org.apache.commons.text.similarity package.
- */
-@Profile(PROFILE_CORE)
-@Primary
-@Component
-public class TitleJaccardSimilarityCompareStrategy implements PostSimilarityComparisonStrategy {
-
- @Override
- public Double performSimilarityCheck(Post post1, Post post2) {
- JaccardSimilarity jaccardSimilarity = new JaccardSimilarity();
- Double similarityScore = 0.0;
-
- // we only compute a similarity score if the title of both posts are defined
- if (post1.getTitle() != null && post2.getTitle() != null) {
- similarityScore = jaccardSimilarity.apply(post1.getTitle().toLowerCase(), post2.getTitle().toLowerCase());
- }
- return similarityScore;
- }
-}
diff --git a/src/main/java/de/tum/cit/aet/artemis/communication/web/ConversationMessageResource.java b/src/main/java/de/tum/cit/aet/artemis/communication/web/ConversationMessageResource.java
index 5031332a8862..bfa04d53cc5f 100644
--- a/src/main/java/de/tum/cit/aet/artemis/communication/web/ConversationMessageResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/communication/web/ConversationMessageResource.java
@@ -201,34 +201,4 @@ public ResponseEntity updateDisplayPriority(@PathVariable Long courseId, @
Post postWithUpdatedDisplayPriority = conversationMessagingService.changeDisplayPriority(courseId, postId, displayPriority);
return ResponseEntity.ok().body(postWithUpdatedDisplayPriority);
}
-
- /**
- * POST /courses/{courseId}/messages/similarity-check : trigger a similarity check for post to be created
- *
- * @param courseId id of the course the post should be published in
- * @param post post to create
- * @return ResponseEntity with status 200 (OK)
- */
- @PostMapping("courses/{courseId}/messages/similarity-check")
- @EnforceAtLeastStudent
- // TODO: unused, remove
- public ResponseEntity> computeSimilarityScoresWitCoursePosts(@PathVariable Long courseId, @RequestBody Post post) {
- List similarPosts = conversationMessagingService.getSimilarPosts(courseId, post);
- return ResponseEntity.ok().body(similarPosts);
- }
-
- /**
- * GET /courses/{courseId}/posts/tags : Get all tags for posts in a certain course
- *
- * @param courseId id of the course the post belongs to
- * @return the ResponseEntity with status 200 (OK) and with body all tags for posts in that course,
- * or 400 (Bad Request) if the checks on user or course validity fail
- */
- @GetMapping("courses/{courseId}/messages/tags")
- // TODO: unused, delete
- @EnforceAtLeastStudent
- public ResponseEntity> getAllPostTagsForCourse(@PathVariable Long courseId) {
- List tags = conversationMessagingService.getAllCourseTags(courseId);
- return new ResponseEntity<>(tags, null, HttpStatus.OK);
- }
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java b/src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java
index a89a6f6ef207..2ed93c8d8926 100644
--- a/src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/core/service/cleanup/DataCleanupService.java
@@ -13,7 +13,6 @@
import de.tum.cit.aet.artemis.assessment.repository.cleanup.FeedbackCleanupRepository;
import de.tum.cit.aet.artemis.assessment.repository.cleanup.LongFeedbackTextCleanupRepository;
-import de.tum.cit.aet.artemis.assessment.repository.cleanup.ParticipantScoreCleanupRepository;
import de.tum.cit.aet.artemis.assessment.repository.cleanup.PlagiarismComparisonCleanupRepository;
import de.tum.cit.aet.artemis.assessment.repository.cleanup.RatingCleanupRepository;
import de.tum.cit.aet.artemis.assessment.repository.cleanup.ResultCleanupRepository;
@@ -49,13 +48,10 @@ public class DataCleanupService {
private final TeamScoreCleanupRepository teamScoreCleanupRepository;
- private final ParticipantScoreCleanupRepository participantScoreCleanupRepository;
-
public DataCleanupService(CleanupJobExecutionRepository cleanupJobExecutionRepository, PlagiarismComparisonCleanupRepository plagiarismComparisonCleanupRepository,
ResultCleanupRepository resultCleanupRepository, RatingCleanupRepository ratingCleanupRepository, FeedbackCleanupRepository feedbackCleanupRepository,
TextBlockCleanupRepository textBlockCleanupRepository, LongFeedbackTextCleanupRepository longFeedbackTextCleanupRepository,
- StudentScoreCleanupRepository studentScoreCleanupRepository, TeamScoreCleanupRepository teamScoreCleanupRepository,
- ParticipantScoreCleanupRepository participantScoreCleanupRepository) {
+ StudentScoreCleanupRepository studentScoreCleanupRepository, TeamScoreCleanupRepository teamScoreCleanupRepository) {
this.resultCleanupRepository = resultCleanupRepository;
this.ratingCleanupRepository = ratingCleanupRepository;
this.feedbackCleanupRepository = feedbackCleanupRepository;
@@ -65,7 +61,6 @@ public DataCleanupService(CleanupJobExecutionRepository cleanupJobExecutionRepos
this.teamScoreCleanupRepository = teamScoreCleanupRepository;
this.cleanupJobExecutionRepository = cleanupJobExecutionRepository;
this.plagiarismComparisonCleanupRepository = plagiarismComparisonCleanupRepository;
- this.participantScoreCleanupRepository = participantScoreCleanupRepository;
}
// TODO: offer the possibility to delete old submission versions
diff --git a/src/main/java/de/tum/cit/aet/artemis/exam/service/ExamLiveEventsService.java b/src/main/java/de/tum/cit/aet/artemis/exam/service/ExamLiveEventsService.java
index fa48e0c1a09c..31ee3dbf9e80 100644
--- a/src/main/java/de/tum/cit/aet/artemis/exam/service/ExamLiveEventsService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/exam/service/ExamLiveEventsService.java
@@ -8,7 +8,6 @@
import de.tum.cit.aet.artemis.communication.service.WebsocketMessagingService;
import de.tum.cit.aet.artemis.core.domain.User;
-import de.tum.cit.aet.artemis.core.repository.UserRepository;
import de.tum.cit.aet.artemis.exam.domain.Exam;
import de.tum.cit.aet.artemis.exam.domain.StudentExam;
import de.tum.cit.aet.artemis.exam.domain.event.ExamAttendanceCheckEvent;
@@ -55,14 +54,11 @@ public class ExamLiveEventsService {
private final StudentExamRepository studentExamRepository;
- private final UserRepository userRepository;
-
- public ExamLiveEventsService(WebsocketMessagingService websocketMessagingService, ExamLiveEventRepository examLiveEventRepository, StudentExamRepository studentExamRepository,
- UserRepository userRepository) {
+ public ExamLiveEventsService(WebsocketMessagingService websocketMessagingService, ExamLiveEventRepository examLiveEventRepository,
+ StudentExamRepository studentExamRepository) {
this.websocketMessagingService = websocketMessagingService;
this.examLiveEventRepository = examLiveEventRepository;
this.studentExamRepository = studentExamRepository;
- this.userRepository = userRepository;
}
/**
diff --git a/src/main/java/de/tum/cit/aet/artemis/exercise/repository/StudentParticipationRepository.java b/src/main/java/de/tum/cit/aet/artemis/exercise/repository/StudentParticipationRepository.java
index 1101f94d4708..bb775298efb5 100644
--- a/src/main/java/de/tum/cit/aet/artemis/exercise/repository/StudentParticipationRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/exercise/repository/StudentParticipationRepository.java
@@ -59,7 +59,8 @@ public interface StudentParticipationRepository extends ArtemisJpaRepository findByCourseIdWithEagerRatedResults(@Param("courseId") long courseId);
@@ -69,8 +70,10 @@ public interface StudentParticipationRepository extends ArtemisJpaRepository findByCourseIdAndStudentIdWithEagerRatedResults(@Param("courseId") long courseId, @Param("studentId") long studentId);
@@ -79,7 +82,8 @@ SELECT COUNT(p.id) > 0
FROM StudentParticipation p
LEFT JOIN p.team.students ts
WHERE p.exercise.course.id = :courseId
- AND (p.student.id = :studentId OR ts.id = :studentId)
+ AND (p.student.id = :studentId
+ OR ts.id = :studentId)
""")
boolean existsByCourseIdAndStudentId(@Param("courseId") long courseId, @Param("studentId") long studentId);
@@ -91,7 +95,8 @@ SELECT COUNT(p.id) > 0
WHERE p.testRun = FALSE
AND p.exercise.exerciseGroup.exam.id = :examId
AND r.rated = TRUE
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
List findByExamIdWithEagerLegalSubmissionsRatedResults(@Param("examId") long examId);
@@ -125,7 +130,8 @@ SELECT COUNT(p.id) > 0
LEFT JOIN FETCH p.submissions s
WHERE p.exercise.id = :exerciseId
AND p.student.login = :username
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
Optional findWithEagerLegalSubmissionsByExerciseIdAndStudentLogin(@Param("exerciseId") long exerciseId, @Param("username") String username);
@@ -135,7 +141,8 @@ SELECT COUNT(p.id) > 0
LEFT JOIN FETCH p.submissions s
WHERE p.exercise.id = :exerciseId
AND p.student.login = :username
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
AND p.testRun = :testRun
""")
Optional findWithEagerLegalSubmissionsByExerciseIdAndStudentLoginAndTestRun(@Param("exerciseId") long exerciseId, @Param("username") String username,
@@ -157,7 +164,8 @@ Optional findWithEagerLegalSubmissionsByExerciseIdAndStude
LEFT JOIN FETCH t.students
WHERE p.exercise.id = :exerciseId
AND p.team.id = :teamId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
Optional findWithEagerLegalSubmissionsAndTeamStudentsByExerciseIdAndTeamId(@Param("exerciseId") long exerciseId, @Param("teamId") long teamId);
@@ -175,8 +183,9 @@ SELECT COUNT(p) > 0
FROM StudentParticipation p
LEFT JOIN p.team.students u
LEFT JOIN p.student s
- WHERE p.id = :participationId AND
- (s.login = :login OR u.login = :login)
+ WHERE p.id = :participationId
+ AND (s.login = :login
+ OR u.login = :login)
""")
boolean existsByIdAndParticipatingStudentLogin(@Param("participationId") long participationId, @Param("login") String login);
@@ -187,7 +196,8 @@ SELECT COUNT(p) > 0
LEFT JOIN FETCH s.results
WHERE p.exercise.id = :exerciseId
AND p.testRun = :testRun
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
List findByExerciseIdAndTestRunWithEagerLegalSubmissionsResult(@Param("exerciseId") long exerciseId, @Param("testRun") boolean testRun);
@@ -235,7 +245,10 @@ Optional findByExerciseIdAndStudentIdAndTestRunWithEagerSu
LEFT JOIN FETCH r.assessmentNote
WHERE p.exercise.id = :exerciseId
AND (
- r.id = (SELECT MAX(p_r.id) FROM p.results p_r)
+ r.id = (
+ SELECT MAX(p_r.id)
+ FROM p.results p_r
+ )
OR r.assessmentType <> de.tum.cit.aet.artemis.assessment.domain.AssessmentType.AUTOMATIC
OR r IS NULL
)
@@ -260,29 +273,16 @@ Optional findByExerciseIdAndStudentIdAndTestRunWithEagerSu
LEFT JOIN FETCH t.students
WHERE p.exercise.id = :exerciseId
AND (
- r.id = (SELECT MAX(p_r.id) FROM p.results p_r)
+ r.id = (
+ SELECT MAX(p_r.id)
+ FROM p.results p_r
+ )
OR r.assessmentType <> de.tum.cit.aet.artemis.assessment.domain.AssessmentType.AUTOMATIC
OR r IS NULL
)
""")
Set findByExerciseIdWithLatestAndManualResultsWithTeamInformation(@Param("exerciseId") long exerciseId);
- @Query("""
- SELECT DISTINCT p
- FROM StudentParticipation p
- LEFT JOIN FETCH p.results r
- LEFT JOIN FETCH r.submission s
- LEFT JOIN FETCH p.submissions
- LEFT JOIN FETCH r.assessmentNote
- WHERE p.exercise.id = :exerciseId
- AND (
- r.id = (SELECT MAX(p_r.id) FROM p.results p_r WHERE p_r.rated = TRUE)
- OR r.assessmentType <> de.tum.cit.aet.artemis.assessment.domain.AssessmentType.AUTOMATIC
- OR r IS NULL
- )
- """)
- Set findByExerciseIdWithLatestAndManualRatedResultsAndAssessmentNote(@Param("exerciseId") long exerciseId);
-
@Query("""
SELECT DISTINCT p
FROM StudentParticipation p
@@ -292,7 +292,11 @@ Optional findByExerciseIdAndStudentIdAndTestRunWithEagerSu
AND p.testRun = :testRun
AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
AND r.assessmentType <> de.tum.cit.aet.artemis.assessment.domain.AssessmentType.AUTOMATIC
- AND r.id = (SELECT MAX(r2.id) FROM p.results r2 WHERE r2.completionDate IS NOT NULL)
+ AND r.id = (
+ SELECT MAX(r2.id)
+ FROM p.results r2
+ WHERE r2.completionDate IS NOT NULL
+ )
""")
Set findByExerciseIdAndTestRunWithEagerLegalSubmissionsAndLatestResultWithCompletionDate(@Param("exerciseId") long exerciseId,
@Param("testRun") boolean testRun);
@@ -343,16 +347,14 @@ default List findByExerciseIdWithLatestAutomaticResultAndF
LEFT JOIN FETCH f.testCase
LEFT JOIN FETCH r.submission s
WHERE p.id = :participationId
- AND (r.id = (
+ AND r.id = (
SELECT MAX(pr.id)
FROM p.results pr
LEFT JOIN pr.submission prs
WHERE pr.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.AUTOMATIC
- AND (
- prs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
- OR prs.type IS NULL
- )
- ))
+ AND (prs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR prs.type IS NULL)
+ )
""")
Optional findByIdWithLatestAutomaticResultAndFeedbacksAndTestCases(@Param("participationId") long participationId);
@@ -366,10 +368,8 @@ SELECT MAX(pr.id)
LEFT JOIN FETCH r.submission s
WHERE p.exercise.id = :exerciseId
AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
- AND (
- r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.MANUAL
- OR r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.SEMI_AUTOMATIC
- )
+ AND (r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.MANUAL
+ OR r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.SEMI_AUTOMATIC)
""")
List findByExerciseIdWithManualResultAndFeedbacksAndTestCases(@Param("exerciseId") long exerciseId);
@@ -385,11 +385,10 @@ default List findByExerciseIdWithManualResultAndFeedbacksA
LEFT JOIN FETCH f.testCase
LEFT JOIN FETCH r.submission s
WHERE p.id = :participationId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
- AND (
- r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.MANUAL
- OR r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.SEMI_AUTOMATIC
- )
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
+ AND (r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.MANUAL
+ OR r.assessmentType = de.tum.cit.aet.artemis.assessment.domain.AssessmentType.SEMI_AUTOMATIC)
""")
Optional findByIdWithManualResultAndFeedbacks(@Param("participationId") long participationId);
@@ -399,7 +398,8 @@ default List findByExerciseIdWithManualResultAndFeedbacksA
LEFT JOIN FETCH p.submissions s
WHERE p.exercise.id = :exerciseId
AND p.student.id = :studentId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
List findByExerciseIdAndStudentIdWithEagerLegalSubmissions(@Param("exerciseId") long exerciseId, @Param("studentId") long studentId);
@@ -427,7 +427,8 @@ default List findByExerciseIdWithManualResultAndFeedbacksA
LEFT JOIN FETCH p.submissions s
WHERE p.exercise.id = :exerciseId
AND p.team.id = :teamId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
List findByExerciseIdAndTeamIdWithEagerLegalSubmissions(@Param("exerciseId") long exerciseId, @Param("teamId") long teamId);
@@ -451,8 +452,10 @@ default List findByExerciseIdWithManualResultAndFeedbacksA
LEFT JOIN FETCH t.students
WHERE p.exercise.id = :exerciseId
AND p.team.id = :teamId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
- AND (rs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR rs.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
+ AND (rs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR rs.type IS NULL)
""")
List findByExerciseIdAndTeamIdWithEagerResultsAndLegalSubmissionsAndTeamStudents(@Param("exerciseId") long exerciseId, @Param("teamId") long teamId);
@@ -471,7 +474,8 @@ SELECT MAX(pr.id)
LEFT JOIN pr.submission prs
WHERE prs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
OR prs.type IS NULL
- ) OR r.id IS NULL)
+ )
+ OR r.id IS NULL)
""")
Optional findByExerciseIdAndStudentIdAndTestRunWithLatestResult(@Param("exerciseId") long exerciseId, @Param("studentId") long studentId,
@Param("testRun") boolean testRun);
@@ -524,7 +528,10 @@ WHERE prs.assessmentType IN (
)
)
AND submission.submitted = TRUE
- AND submission.id = (SELECT MAX(s.id) FROM p.submissions s)
+ AND submission.id = (
+ SELECT MAX(s.id)
+ FROM p.submissions s
+ )
""")
List findByExerciseIdWithLatestSubmissionWithoutManualResultsAndIgnoreTestRunParticipation(@Param("exerciseId") long exerciseId,
@Param("correctionRound") long correctionRound);
@@ -548,7 +555,10 @@ WHERE prs.assessmentType IN (
de.tum.cit.aet.artemis.assessment.domain.AssessmentType.SEMI_AUTOMATIC
)
) AND s.submitted = TRUE
- AND s.id = (SELECT MAX(s.id) FROM p.submissions s)
+ AND s.id = (
+ SELECT MAX(s.id)
+ FROM p.submissions s
+ )
""")
List findByExerciseIdWithLatestSubmissionWithoutManualResultsWithPassedIndividualDueDateIgnoreTestRuns(@Param("exerciseId") long exerciseId,
@Param("now") ZonedDateTime now);
@@ -558,7 +568,8 @@ List findByExerciseIdWithLatestSubmissionWithoutManualResu
FROM Participation p
LEFT JOIN FETCH p.submissions s
WHERE p.id = :participationId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
Optional findWithEagerLegalSubmissionsById(@Param("participationId") long participationId);
@@ -593,8 +604,10 @@ List findByExerciseIdWithLatestSubmissionWithoutManualResu
LEFT JOIN FETCH p.team t
LEFT JOIN FETCH t.students
WHERE p.id = :participationId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
- AND (rs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR rs.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
+ AND (rs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR rs.type IS NULL)
""")
Optional findWithEagerLegalSubmissionsResultsFeedbacksById(@Param("participationId") long participationId);
@@ -617,10 +630,9 @@ List findByExerciseIdWithLatestSubmissionWithoutManualResu
FROM StudentParticipation p
JOIN Result r ON r.participation.id = p.id
WHERE p.exercise.id = :exerciseId
- AND (
- p.student.firstName LIKE %:partialStudentName%
- OR p.student.lastName LIKE %:partialStudentName%
- ) AND r.completionDate IS NOT NULL
+ AND (p.student.firstName LIKE %:partialStudentName%
+ OR p.student.lastName LIKE %:partialStudentName%)
+ AND r.completionDate IS NOT NULL
""")
List findIdsByExerciseIdAndStudentName(@Param("exerciseId") long exerciseId, @Param("partialStudentName") String partialStudentName, Pageable pageable);
@@ -632,10 +644,9 @@ SELECT COUNT(p)
FROM StudentParticipation p
JOIN Result r ON r.participation.id = p.id
WHERE p.exercise.id = :exerciseId
- AND (
- p.student.firstName LIKE %:partialStudentName%
- OR p.student.lastName LIKE %:partialStudentName%
- ) AND r.completionDate IS NOT NULL
+ AND (p.student.firstName LIKE %:partialStudentName%
+ OR p.student.lastName LIKE %:partialStudentName%)
+ AND r.completionDate IS NOT NULL
""")
long countByExerciseIdAndStudentName(@Param("exerciseId") long exerciseId, @Param("partialStudentName") String partialStudentName);
@@ -666,8 +677,10 @@ default Page findAllWithEagerSubmissionsAndResultsByExerci
LEFT JOIN FETCH p.submissions s
LEFT JOIN FETCH s.results sr
WHERE p.exercise.id = :exerciseId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
- AND (rs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR rs.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
+ AND (rs.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR rs.type IS NULL)
""")
List findAllWithEagerLegalSubmissionsAndEagerResultsByExerciseId(@Param("exerciseId") long exerciseId);
@@ -697,12 +710,17 @@ default Page findAllWithEagerSubmissionsAndResultsByExerci
LEFT JOIN FETCH p.team
WHERE p.exercise.id = :exerciseId
AND p.testRun = FALSE
- AND s.id = (SELECT MAX(s2.id)
- FROM p.submissions s2
- WHERE s2.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s2.type IS NULL)
- AND r.id = (SELECT MAX(r2.id)
- FROM s.results r2
- WHERE r2.rated = TRUE)
+ AND s.id = (
+ SELECT MAX(s2.id)
+ FROM p.submissions s2
+ WHERE s2.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s2.type IS NULL
+ )
+ AND r.id = (
+ SELECT MAX(r2.id)
+ FROM s.results r2
+ WHERE r2.rated = TRUE
+ )
""")
List findAllForPlagiarism(@Param("exerciseId") long exerciseId);
@@ -713,7 +731,8 @@ default Page findAllWithEagerSubmissionsAndResultsByExerci
LEFT JOIN FETCH s.results r
WHERE p.student.id = :studentId
AND p.exercise IN :exercises
- AND (p.testRun = FALSE OR :includeTestRuns = TRUE)
+ AND (p.testRun = FALSE
+ OR :includeTestRuns = TRUE)
""")
Set findByStudentIdAndIndividualExercisesWithEagerSubmissionsResult(@Param("studentId") long studentId,
@Param("exercises") Collection exercises, @Param("includeTestRuns") boolean includeTestRuns);
@@ -786,7 +805,8 @@ List findTestRunParticipationsByStudentIdAndIndividualExer
LEFT JOIN FETCH t.students teamStudent
WHERE teamStudent.id = :studentId
AND p.exercise IN :exercises
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
Set findByStudentIdAndTeamExercisesWithEagerLegalSubmissionsResult(@Param("studentId") long studentId,
@Param("exercises") Collection exercises);
@@ -799,7 +819,8 @@ Set findByStudentIdAndTeamExercisesWithEagerLegalSubmissio
LEFT JOIN FETCH p.team t
WHERE p.exercise.course.id = :courseId
AND t.shortName = :teamShortName
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
""")
List findAllByCourseIdAndTeamShortNameWithEagerLegalSubmissionsResult(@Param("courseId") long courseId, @Param("teamShortName") String teamShortName);
@@ -831,7 +852,8 @@ SELECT p.id, COUNT(s)
LEFT JOIN p.submissions s
WHERE p.team.shortName = :teamShortName
AND p.exercise.course.id = :courseId
- AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL OR s.type IS NULL)
+ AND (s.type <> de.tum.cit.aet.artemis.exercise.domain.SubmissionType.ILLEGAL
+ OR s.type IS NULL)
GROUP BY p.id
""")
List countLegalSubmissionsPerParticipationByCourseIdAndTeamShortName(@Param("courseId") long courseId, @Param("teamShortName") String teamShortName);
@@ -850,7 +872,8 @@ AND EXISTS (
FROM p.submissions s1
WHERE s1.participation.id = p.id
AND s1.submitted = TRUE
- AND (r.assessor = :assessor OR r.assessor.id IS NULL)
+ AND (r.assessor = :assessor
+ OR r.assessor.id IS NULL)
)
""")
List findAllByParticipationExerciseIdAndResultAssessorAndCorrectionRoundIgnoreTestRuns(@Param("exerciseId") long exerciseId,
diff --git a/src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseDeletionService.java b/src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseDeletionService.java
index 6739cfc0c714..36b7e99fedd0 100644
--- a/src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseDeletionService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/exercise/service/ExerciseDeletionService.java
@@ -17,7 +17,6 @@
import de.tum.cit.aet.artemis.assessment.repository.TutorParticipationRepository;
import de.tum.cit.aet.artemis.assessment.service.ExampleSubmissionService;
import de.tum.cit.aet.artemis.atlas.domain.competency.CompetencyExerciseLink;
-import de.tum.cit.aet.artemis.atlas.repository.CompetencyExerciseLinkRepository;
import de.tum.cit.aet.artemis.atlas.service.competency.CompetencyProgressService;
import de.tum.cit.aet.artemis.communication.domain.conversation.Channel;
import de.tum.cit.aet.artemis.communication.repository.conversation.ChannelRepository;
@@ -81,8 +80,6 @@ public class ExerciseDeletionService {
private final CompetencyProgressService competencyProgressService;
- private final CompetencyExerciseLinkRepository competencyExerciseLinkRepository;
-
private final Optional irisSettingsService;
public ExerciseDeletionService(ExerciseRepository exerciseRepository, ExerciseUnitRepository exerciseUnitRepository, ParticipationService participationService,
@@ -90,7 +87,7 @@ public ExerciseDeletionService(ExerciseRepository exerciseRepository, ExerciseUn
TutorParticipationRepository tutorParticipationRepository, ExampleSubmissionService exampleSubmissionService, StudentExamRepository studentExamRepository,
LectureUnitService lectureUnitService, PlagiarismResultRepository plagiarismResultRepository, TextExerciseService textExerciseService,
ChannelRepository channelRepository, ChannelService channelService, CompetencyProgressService competencyProgressService,
- CompetencyExerciseLinkRepository competencyExerciseLinkRepository, Optional irisSettingsService) {
+ Optional irisSettingsService) {
this.exerciseRepository = exerciseRepository;
this.participationService = participationService;
this.programmingExerciseService = programmingExerciseService;
@@ -106,7 +103,6 @@ public ExerciseDeletionService(ExerciseRepository exerciseRepository, ExerciseUn
this.channelRepository = channelRepository;
this.channelService = channelService;
this.competencyProgressService = competencyProgressService;
- this.competencyExerciseLinkRepository = competencyExerciseLinkRepository;
this.irisSettingsService = irisSettingsService;
}
diff --git a/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java b/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java
index 4d549bb3fe66..05e3166ff171 100644
--- a/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/exercise/web/ParticipationResource.java
@@ -66,7 +66,6 @@
import de.tum.cit.aet.artemis.core.service.messaging.InstanceMessageSendService;
import de.tum.cit.aet.artemis.core.util.HeaderUtil;
import de.tum.cit.aet.artemis.exercise.domain.Exercise;
-import de.tum.cit.aet.artemis.exercise.domain.ExerciseType;
import de.tum.cit.aet.artemis.exercise.domain.InitializationState;
import de.tum.cit.aet.artemis.exercise.domain.Submission;
import de.tum.cit.aet.artemis.exercise.domain.SubmissionType;
@@ -595,9 +594,7 @@ public ResponseEntity> updateParticipationDueDates(@P
}
private Set findParticipationWithLatestResults(Exercise exercise) {
- if (exercise.getExerciseType() == ExerciseType.QUIZ) {
- return studentParticipationRepository.findByExerciseIdWithLatestAndManualRatedResultsAndAssessmentNote(exercise.getId());
- }
+ // TODO: we should reduce the amount of data fetched here and sent to the client: double check which data is actually required in the exercise scores page
if (exercise.isTeamMode()) {
// For team exercises the students need to be eagerly fetched
return studentParticipationRepository.findByExerciseIdWithLatestAndManualResultsWithTeamInformation(exercise.getId());
diff --git a/src/main/java/de/tum/cit/aet/artemis/iris/web/IrisExerciseChatSessionResource.java b/src/main/java/de/tum/cit/aet/artemis/iris/web/IrisExerciseChatSessionResource.java
index 9e736ce8c358..3f2a0bdb6ab7 100644
--- a/src/main/java/de/tum/cit/aet/artemis/iris/web/IrisExerciseChatSessionResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/iris/web/IrisExerciseChatSessionResource.java
@@ -101,7 +101,7 @@ public ResponseEntity getCurrentSessionOrCreateIfNotExi
@EnforceAtLeastStudentInExercise
public ResponseEntity> getAllSessions(@PathVariable Long exerciseId) {
var exercise = exerciseRepository.findByIdElseThrow(exerciseId);
- ProgrammingExercise programmingExercise = validateExercise(exercise);
+ validateExercise(exercise);
irisSettingsService.isEnabledForElseThrow(IrisSubSettingsType.CHAT, exercise);
var user = userRepository.getUserWithGroupsAndAuthorities();
diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java b/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java
index cc1f57c533fa..c88024f0835b 100644
--- a/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingExerciseStudentParticipationRepository.java
@@ -136,8 +136,8 @@ Optional findWithSubmissionsAndEagerStu
@EntityGraph(type = LOAD, attributePaths = { "submissions", "team.students" })
List findWithSubmissionsById(long participationId);
- @EntityGraph(type = LOAD, attributePaths = { "submissions" })
- List findWithSubmissionsByExerciseId(long exerciseId);
+ @EntityGraph(type = LOAD, attributePaths = { "submissions.results" })
+ List findWithSubmissionsAndResultsByExerciseId(long exerciseId);
@EntityGraph(type = LOAD, attributePaths = { "submissions", "team.students" })
List findWithSubmissionsAndTeamStudentsByExerciseId(long exerciseId);
diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java b/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java
index ffe438217b64..90d514ca4b68 100644
--- a/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java
+++ b/src/main/java/de/tum/cit/aet/artemis/programming/repository/ProgrammingSubmissionRepository.java
@@ -50,7 +50,8 @@ default ProgrammingSubmission findFirstByParticipationIdAndCommitHashOrderByIdDe
@Query(value = """
SELECT new de.tum.cit.aet.artemis.programming.dto.ProgrammingSubmissionIdAndSubmissionDateDTO(ps.id, ps.submissionDate)
FROM ProgrammingSubmission ps
- WHERE ps.participation.id = :participationId ORDER BY ps.submissionDate DESC
+ WHERE ps.participation.id = :participationId
+ ORDER BY ps.submissionDate DESC
""")
List findFirstIdByParticipationIdOrderBySubmissionDateDesc(@Param("participationId") long participationId, Pageable pageable);
@@ -72,8 +73,8 @@ default Optional findFirstByParticipationIdWithResultsOrd
if (result.isEmpty()) {
return Optional.empty();
}
- long id = result.getFirst().programmingSubmissionId();
- return findProgrammingSubmissionWithResultsById(id);
+ long submissionId = result.getFirst().programmingSubmissionId();
+ return findProgrammingSubmissionWithResultsById(submissionId);
}
@Query("""
@@ -104,8 +105,7 @@ default Optional findFirstByParticipationIdWithResultsOrd
* @return ProgrammingSubmission list (can be empty!)
*/
default List findGradedByParticipationIdWithResultsOrderBySubmissionDateDesc(long participationId, Pageable pageable) {
- List ids = findSubmissionIdsAndDatesByParticipationId(participationId, pageable).stream().map(ProgrammingSubmissionIdAndSubmissionDateDTO::programmingSubmissionId)
- .toList();
+ var ids = findSubmissionIdsAndDatesByParticipationId(participationId, pageable).stream().map(ProgrammingSubmissionIdAndSubmissionDateDTO::programmingSubmissionId).toList();
if (ids.isEmpty()) {
return Collections.emptyList();
diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java
index db9cebb2eb6c..bbcdc1d5624b 100644
--- a/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/ParticipationVcsAccessTokenService.java
@@ -9,7 +9,9 @@
import de.tum.cit.aet.artemis.core.domain.User;
import de.tum.cit.aet.artemis.core.exception.AccessForbiddenException;
+import de.tum.cit.aet.artemis.exercise.domain.Team;
import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation;
+import de.tum.cit.aet.artemis.exercise.repository.TeamRepository;
import de.tum.cit.aet.artemis.programming.domain.ParticipationVCSAccessToken;
import de.tum.cit.aet.artemis.programming.repository.ParticipationVCSAccessTokenRepository;
import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseStudentParticipationRepository;
@@ -25,10 +27,13 @@ public class ParticipationVcsAccessTokenService {
private final ProgrammingExerciseStudentParticipationRepository programmingExerciseStudentParticipationRepository;
+ private final TeamRepository teamRepository;
+
public ParticipationVcsAccessTokenService(ParticipationVCSAccessTokenRepository participationVCSAccessTokenRepository,
- ProgrammingExerciseStudentParticipationRepository programmingExerciseStudentParticipationRepository) {
+ ProgrammingExerciseStudentParticipationRepository programmingExerciseStudentParticipationRepository, TeamRepository teamRepository) {
this.participationVcsAccessTokenRepository = participationVCSAccessTokenRepository;
this.programmingExerciseStudentParticipationRepository = programmingExerciseStudentParticipationRepository;
+ this.teamRepository = teamRepository;
}
/**
@@ -55,6 +60,7 @@ public ParticipationVCSAccessToken createParticipationVCSAccessToken(User user,
*/
public ParticipationVCSAccessToken findByUserAndParticipationIdOrElseThrow(User user, long participationId) {
var participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(participationId);
+ loadTeamStudentsForTeamExercise(participation);
if (participation.isOwnedBy(user)) {
return participationVcsAccessTokenRepository.findByUserIdAndParticipationIdOrElseThrow(user.getId(), participationId);
}
@@ -73,6 +79,7 @@ public ParticipationVCSAccessToken findByUserAndParticipationIdOrElseThrow(User
public ParticipationVCSAccessToken createVcsAccessTokenForUserAndParticipationIdOrElseThrow(User user, long participationId) {
participationVcsAccessTokenRepository.findByUserIdAndParticipationIdAndThrowIfExists(user.getId(), participationId);
var participation = programmingExerciseStudentParticipationRepository.findByIdElseThrow(participationId);
+ loadTeamStudentsForTeamExercise(participation);
if (participation.isOwnedBy(user)) {
return createParticipationVCSAccessToken(user, participation);
}
@@ -81,6 +88,19 @@ public ParticipationVCSAccessToken createVcsAccessTokenForUserAndParticipationId
}
}
+ /**
+ * Loads the team students of a participation's team, if it has a team
+ *
+ * @param participation the participation which team's students are not loaded yet
+ */
+ private void loadTeamStudentsForTeamExercise(StudentParticipation participation) {
+ if (participation.getTeam().isPresent()) {
+ Team team = participation.getTeam().get();
+ Team teamWithStudents = teamRepository.findWithStudentsByIdElseThrow(team.getId());
+ participation.getTeam().get().setStudents(teamWithStudents.getStudents());
+ }
+ }
+
/**
* Deletes the token connected to a participation
*
diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingSubmissionService.java b/src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingSubmissionService.java
index 58665d8beae4..9de4485f16b2 100644
--- a/src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingSubmissionService.java
+++ b/src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingSubmissionService.java
@@ -6,6 +6,7 @@
import java.time.ZonedDateTime;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -341,14 +342,16 @@ public Optional getLatestPendingSubmission(Long participa
* @return a Map of {[participationId]: ProgrammingSubmission | null}. Will contain an entry for every student participation of the exercise and a submission object if a
* pending submission exists or null if not.
*/
- public Map> getLatestPendingSubmissionsForProgrammingExercise(Long programmingExerciseId) {
- List participations = programmingExerciseStudentParticipationRepository.findWithSubmissionsByExerciseId(programmingExerciseId);
- // TODO: find the latest pending submission directly using Java (the submissions are available now) and not with additional db queries
- return participations.stream().collect(Collectors.toMap(Participation::getId, p -> findLatestPendingSubmissionForParticipation(p.getId())));
- }
-
- private Optional findLatestPendingSubmissionForParticipation(final long participationId) {
- return findLatestPendingSubmissionForParticipation(participationId, false);
+ public Map> getLatestPendingSubmissionsForProgrammingExercise(Long programmingExerciseId) {
+ var participations = programmingExerciseStudentParticipationRepository.findWithSubmissionsAndResultsByExerciseId(programmingExerciseId);
+ return participations.stream().collect(Collectors.toMap(Participation::getId, p -> {
+ var latestSubmission = p.getSubmissions().stream().max(Comparator.comparing(Submission::getSubmissionDate));
+ if (latestSubmission.isEmpty() || latestSubmission.get().getLatestResult() != null) {
+ // This is not an error case, it is very likely that there is no pending submission for a participation.
+ return Optional.empty();
+ }
+ return latestSubmission;
+ }));
}
private Optional findLatestPendingSubmissionForParticipation(final long participationId, final boolean isGraded) {
diff --git a/src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java b/src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java
index be1c99c67be6..2566e1a87fb8 100644
--- a/src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java
+++ b/src/main/java/de/tum/cit/aet/artemis/programming/web/ProgrammingExerciseParticipationResource.java
@@ -37,6 +37,7 @@
import de.tum.cit.aet.artemis.core.service.AuthorizationCheckService;
import de.tum.cit.aet.artemis.exam.repository.StudentExamRepository;
import de.tum.cit.aet.artemis.exam.service.ExamService;
+import de.tum.cit.aet.artemis.exercise.domain.Submission;
import de.tum.cit.aet.artemis.exercise.domain.participation.Participation;
import de.tum.cit.aet.artemis.exercise.repository.ParticipationRepository;
import de.tum.cit.aet.artemis.exercise.service.ParticipationAuthorizationCheckService;
@@ -230,17 +231,17 @@ public ResponseEntity getLatestPendingSubmission(@PathVar
*/
@GetMapping("programming-exercises/{exerciseId}/latest-pending-submissions")
@EnforceAtLeastTutor
- public ResponseEntity