Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Introduce plagiarism module API #10296

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
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 @@ -42,10 +42,10 @@
import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository;
import de.tum.cit.aet.artemis.exercise.repository.StudentParticipationRepository;
import de.tum.cit.aet.artemis.exercise.service.ExerciseDateService;
import de.tum.cit.aet.artemis.plagiarism.api.PlagiarismCaseApi;
import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismCase;
import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismMapping;
import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismVerdict;
import de.tum.cit.aet.artemis.plagiarism.repository.PlagiarismCaseRepository;
import de.tum.cit.aet.artemis.plagiarism.service.PlagiarismCaseService.PlagiarismMapping;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;

/**
Expand All @@ -62,15 +62,15 @@ public class CourseScoreCalculationService {

private final ExerciseRepository exerciseRepository;

private final PlagiarismCaseRepository plagiarismCaseRepository;
private final Optional<PlagiarismCaseApi> plagiarismCaseApi;

private final PresentationPointsCalculationService presentationPointsCalculationService;

public CourseScoreCalculationService(StudentParticipationRepository studentParticipationRepository, ExerciseRepository exerciseRepository,
PlagiarismCaseRepository plagiarismCaseRepository, PresentationPointsCalculationService presentationPointsCalculationService) {
Optional<PlagiarismCaseApi> plagiarismCaseApi, PresentationPointsCalculationService presentationPointsCalculationService) {
this.studentParticipationRepository = studentParticipationRepository;
this.exerciseRepository = exerciseRepository;
this.plagiarismCaseRepository = plagiarismCaseRepository;
this.plagiarismCaseApi = plagiarismCaseApi;
this.presentationPointsCalculationService = presentationPointsCalculationService;
}

Expand Down Expand Up @@ -151,7 +151,7 @@ public Map<Long, BonusSourceResultDTO> calculateCourseScoresForExamBonusSource(C
if (!participations.isEmpty()) {
studentIdToParticipations.addAll(studentId, participations);
}
plagiarismCases = plagiarismCaseRepository.findByCourseIdAndStudentId(courseId, studentId);
plagiarismCases = plagiarismCaseApi.map(api -> api.findByCourseIdAndStudentId(courseId, studentId)).orElse(List.of());
}
else {
// Get all participations for the course.
Expand All @@ -167,7 +167,7 @@ public Map<Long, BonusSourceResultDTO> calculateCourseScoresForExamBonusSource(C
}
}
}
plagiarismCases = plagiarismCaseRepository.findByCourseId(courseId);
plagiarismCases = plagiarismCaseApi.map(api -> api.findByCourseId(courseId)).orElse(List.of());
}

return studentIdToParticipations.entrySet().parallelStream().collect(Collectors.toMap(Map.Entry::getKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
import de.tum.cit.aet.artemis.exam.domain.Exam;
import de.tum.cit.aet.artemis.exam.repository.ExamRepository;
import de.tum.cit.aet.artemis.exercise.repository.StudentParticipationRepository;
import de.tum.cit.aet.artemis.plagiarism.api.PlagiarismCaseApi;
import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismVerdict;
import de.tum.cit.aet.artemis.plagiarism.repository.PlagiarismCaseRepository;

/**
* REST controller for managing grade steps of a grading scale
Expand All @@ -58,20 +58,20 @@ public class GradeStepResource {

private final UserRepository userRepository;

private final PlagiarismCaseRepository plagiarismCaseRepository;
private final Optional<PlagiarismCaseApi> plagiarismCaseApi;

private final StudentParticipationRepository studentParticipationRepository;

public GradeStepResource(GradingScaleRepository gradingScaleRepository, GradeStepRepository gradeStepRepository, AuthorizationCheckService authCheckService,
CourseRepository courseRepository, ExamRepository examRepository, UserRepository userRepository, PlagiarismCaseRepository plagiarismCaseRepository,
CourseRepository courseRepository, ExamRepository examRepository, UserRepository userRepository, Optional<PlagiarismCaseApi> plagiarismCaseApi,
StudentParticipationRepository studentParticipationRepository) {
this.gradingScaleRepository = gradingScaleRepository;
this.gradeStepRepository = gradeStepRepository;
this.authCheckService = authCheckService;
this.courseRepository = courseRepository;
this.examRepository = examRepository;
this.userRepository = userRepository;
this.plagiarismCaseRepository = plagiarismCaseRepository;
this.plagiarismCaseApi = plagiarismCaseApi;
this.studentParticipationRepository = studentParticipationRepository;
}

Expand Down Expand Up @@ -189,7 +189,7 @@ public ResponseEntity<GradeDTO> getGradeStepByPercentageForCourse(@PathVariable
gradeStep = new GradeStep();
gradeStep.setGradeName(gradingScale.getNoParticipationGradeOrDefault());
}
else if (plagiarismCaseRepository.findByCourseIdAndStudentId(courseId, user.getId()).stream()
else if (plagiarismCaseApi.isPresent() && plagiarismCaseApi.get().findByCourseIdAndStudentId(courseId, user.getId()).stream()
.anyMatch(plagiarismCase -> PlagiarismVerdict.PLAGIARISM.equals(plagiarismCase.getVerdict()))) {
gradeStep = new GradeStep();
gradeStep.setGradeName(gradingScale.getPlagiarismGradeOrDefault());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise;
import de.tum.cit.aet.artemis.modeling.repository.ModelingExerciseRepository;
import de.tum.cit.aet.artemis.modeling.service.ModelingExerciseImportService;
import de.tum.cit.aet.artemis.plagiarism.service.PlagiarismDetectionConfigHelper;
import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismDetectionConfigHelper;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;
import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseRepository;
import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseTaskRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public void preparePostForBroadcast(Post post) {
* @param course course the answer post belongs to
* @param notification notification for the update (can be null)
*/
protected void preparePostAndBroadcast(AnswerPost updatedAnswerPost, Course course, Notification notification) {
public void preparePostAndBroadcast(AnswerPost updatedAnswerPost, Course course, Notification notification) {
// we need to explicitly (and newly) add the updated answer post to the answers of the broadcast post to share up-to-date information
Post updatedPost = updatedAnswerPost.getPost();
// remove and add operations on sets identify an AnswerPost by its id; to update a certain property of an existing answer post,
Expand All @@ -127,7 +127,7 @@ protected void preparePostAndBroadcast(AnswerPost updatedAnswerPost, Course cour
* @param recipients the recipients for this broadcast, can be null
* @param mentionedUsers the users mentioned in the message, can be null
*/
protected void broadcastForPost(PostDTO postDTO, Long courseId, Set<ConversationNotificationRecipientSummary> recipients, Set<User> mentionedUsers) {
public void broadcastForPost(PostDTO postDTO, Long courseId, Set<ConversationNotificationRecipientSummary> recipients, Set<User> mentionedUsers) {
// reduce the payload of the websocket message: this is important to avoid overloading the involved subsystems
Conversation postConversation = postDTO.post().getConversation();
if (postConversation != null) {
Expand Down Expand Up @@ -197,7 +197,7 @@ protected Course preCheckUserAndCourseForMessaging(User user, Long courseId) {
return course;
}

protected void preCheckUserAndCourseForCommunicationOrMessaging(User user, Course course) {
public void preCheckUserAndCourseForCommunicationOrMessaging(User user, Course course) {
authorizationCheckService.checkHasAtLeastRoleInCourseElseThrow(Role.STUDENT, course, user);

if (course.getCourseInformationSharingConfiguration() == CourseInformationSharingConfiguration.DISABLED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
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;
import de.tum.cit.aet.artemis.core.exception.ApiNotPresentException;
import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
import de.tum.cit.aet.artemis.core.repository.CourseRepository;
import de.tum.cit.aet.artemis.core.repository.UserRepository;
import de.tum.cit.aet.artemis.plagiarism.service.PlagiarismAnswerPostService;
import de.tum.cit.aet.artemis.plagiarism.service.PlagiarismPostService;
import de.tum.cit.aet.artemis.plagiarism.api.PlagiarismPostApi;

@Profile(PROFILE_CORE)
@Service
Expand All @@ -41,24 +41,20 @@ public class ReactionService {

private final ReactionRepository reactionRepository;

private final PlagiarismPostService plagiarismPostService;

private final PlagiarismAnswerPostService plagiarismAnswerPostService;
private final Optional<PlagiarismPostApi> plagiarismPostApi;

private final ConversationService conversationService;

private final PostRepository postRepository;

private final AnswerPostRepository answerPostRepository;

public ReactionService(UserRepository userRepository, CourseRepository courseRepository, ReactionRepository reactionRepository, PlagiarismPostService plagiarismPostService,
PlagiarismAnswerPostService plagiarismAnswerPostService, ConversationService conversationService, PostRepository postRepository,
AnswerPostRepository answerPostRepository) {
public ReactionService(UserRepository userRepository, CourseRepository courseRepository, ReactionRepository reactionRepository, Optional<PlagiarismPostApi> plagiarismPostApi,
ConversationService conversationService, PostRepository postRepository, AnswerPostRepository answerPostRepository) {
this.userRepository = userRepository;
this.courseRepository = courseRepository;
this.reactionRepository = reactionRepository;
this.plagiarismPostService = plagiarismPostService;
this.plagiarismAnswerPostService = plagiarismAnswerPostService;
this.plagiarismPostApi = plagiarismPostApi;
this.conversationService = conversationService;
this.postRepository = postRepository;
this.answerPostRepository = answerPostRepository;
Expand Down Expand Up @@ -138,15 +134,18 @@ public void deleteReactionById(Long reactionId, Long courseId) {
updatedPost.removeAnswerPost(updatedAnswerPost);
updatedPost.addAnswerPost(updatedAnswerPost);
}
plagiarismPostService.preparePostForBroadcast(updatedPost);
plagiarismPostService.broadcastForPost(new PostDTO(updatedPost, MetisCrudAction.UPDATE), course.getId(), null, null);

PlagiarismPostApi api = plagiarismPostApi.orElseThrow(() -> new ApiNotPresentException(PlagiarismPostApi.class, PROFILE_CORE));
api.preparePostForBroadcast(updatedPost);
api.broadcastForPost(new PostDTO(updatedPost, MetisCrudAction.UPDATE), course.getId(), null, null);
reactionRepository.deleteById(reactionId);
}

private void mayInteractWithConversationElseThrow(User user, Post post, Course course) {
if (post.getConversation() != null) {
PlagiarismPostApi api = plagiarismPostApi.orElseThrow(() -> new ApiNotPresentException(PlagiarismPostApi.class, PROFILE_CORE));
conversationService.isMemberOrCreateForCourseWideElseThrow(post.getConversation().getId(), user, Optional.empty());
plagiarismPostService.preCheckUserAndCourseForCommunicationOrMessaging(user, course);
api.preCheckUserAndCourseForCommunicationOrMessaging(user, course);
}
}

Expand All @@ -160,8 +159,9 @@ private void mayInteractWithConversationElseThrow(User user, Post post, Course c
* @return saved reaction
*/
private Reaction createReactionForAnswer(Reaction reaction, AnswerPost posting, User user, Course course) {
PlagiarismPostApi api = plagiarismPostApi.orElseThrow(() -> new ApiNotPresentException(PlagiarismPostApi.class, PROFILE_CORE));
Reaction savedReaction;
AnswerPost answerPost = plagiarismAnswerPostService.findAnswerPostOrAnswerMessageById(posting.getId());
AnswerPost answerPost = api.findAnswerPostOrAnswerMessageById(posting.getId());
mayInteractWithConversationElseThrow(user, answerPost.getPost(), course);
reaction.setAnswerPost(answerPost);
// save reaction
Expand All @@ -172,7 +172,7 @@ private Reaction createReactionForAnswer(Reaction reaction, AnswerPost posting,
AnswerPost updatedAnswerPost = answerPostRepository.save(answerPost);
updatedAnswerPost.getPost().setConversation(answerPost.getPost().getConversation());

plagiarismAnswerPostService.preparePostAndBroadcast(answerPost, course, null);
api.preparePostAndBroadcast(answerPost, course, null);
return savedReaction;
}

Expand All @@ -186,8 +186,10 @@ private Reaction createReactionForAnswer(Reaction reaction, AnswerPost posting,
* @return saved reaction
*/
private Reaction createReactionForPost(Reaction reaction, Post posting, User user, Course course) {
PlagiarismPostApi api = plagiarismPostApi.orElseThrow(() -> new ApiNotPresentException(PlagiarismPostApi.class, PROFILE_CORE));

Reaction savedReaction;
Post post = plagiarismPostService.findPostOrMessagePostById(posting.getId());
Post post = api.findPostOrMessagePostById(posting.getId());
mayInteractWithConversationElseThrow(user, post, course);
reaction.setPost(post);
// save reaction
Expand All @@ -202,8 +204,8 @@ private Reaction createReactionForPost(Reaction reaction, Post posting, User use
Post updatedPost = postRepository.save(post);
updatedPost.setConversation(post.getConversation());

plagiarismPostService.preparePostForBroadcast(post);
plagiarismPostService.broadcastForPost(new PostDTO(post, MetisCrudAction.UPDATE), course.getId(), null, null);
api.preparePostForBroadcast(post);
api.broadcastForPost(new PostDTO(post, MetisCrudAction.UPDATE), course.getId(), null, null);
return savedReaction;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@
import de.tum.cit.aet.artemis.lecture.domain.Lecture;
import de.tum.cit.aet.artemis.lecture.repository.LectureRepository;
import de.tum.cit.aet.artemis.lecture.service.LectureService;
import de.tum.cit.aet.artemis.plagiarism.api.PlagiarismCaseApi;
import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismCase;
import de.tum.cit.aet.artemis.plagiarism.repository.PlagiarismCaseRepository;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;
import de.tum.cit.aet.artemis.programming.repository.BuildJobRepository;
import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseRepository;
Expand Down Expand Up @@ -197,7 +197,7 @@ public class CourseService {

private final TutorialGroupRepository tutorialGroupRepository;

private final PlagiarismCaseRepository plagiarismCaseRepository;
private final Optional<PlagiarismCaseApi> plagiarismCaseApi;

private final ConversationRepository conversationRepository;

Expand Down Expand Up @@ -230,7 +230,7 @@ public CourseService(CourseRepository courseRepository, ExerciseService exercise
ComplaintService complaintService, ComplaintRepository complaintRepository, ResultRepository resultRepository, ComplaintResponseRepository complaintResponseRepository,
SubmissionRepository submissionRepository, ProgrammingExerciseRepository programmingExerciseRepository, ExerciseRepository exerciseRepository,
ParticipantScoreRepository participantScoreRepository, PresentationPointsCalculationService presentationPointsCalculationService,
TutorialGroupRepository tutorialGroupRepository, PlagiarismCaseRepository plagiarismCaseRepository, ConversationRepository conversationRepository,
TutorialGroupRepository tutorialGroupRepository, Optional<PlagiarismCaseApi> plagiarismCaseApi, ConversationRepository conversationRepository,
Optional<LearningPathApi> learningPathApi, Optional<IrisSettingsService> irisSettingsService, LectureRepository lectureRepository,
TutorialGroupNotificationRepository tutorialGroupNotificationRepository, TutorialGroupChannelManagementService tutorialGroupChannelManagementService,
Optional<PrerequisitesApi> prerequisitesApi, Optional<CompetencyRelationApi> competencyRelationApi, PostRepository postRepository,
Expand Down Expand Up @@ -266,7 +266,7 @@ public CourseService(CourseRepository courseRepository, ExerciseService exercise
this.participantScoreRepository = participantScoreRepository;
this.presentationPointsCalculationService = presentationPointsCalculationService;
this.tutorialGroupRepository = tutorialGroupRepository;
this.plagiarismCaseRepository = plagiarismCaseRepository;
this.plagiarismCaseApi = plagiarismCaseApi;
this.conversationRepository = conversationRepository;
this.learningPathApi = learningPathApi;
this.irisSettingsService = irisSettingsService;
Expand Down Expand Up @@ -337,8 +337,13 @@ public void fetchParticipationsWithSubmissionsAndResultsForCourses(Collection<Co
* @param userId the user for which the plagiarism cases should be fetched.
*/
public void fetchPlagiarismCasesForCourseExercises(Set<Exercise> exercises, Long userId) {
if (plagiarismCaseApi.isEmpty()) {
return;
}

PlagiarismCaseApi api = plagiarismCaseApi.get();
Set<Long> exerciseIds = exercises.stream().map(Exercise::getId).collect(Collectors.toSet());
List<PlagiarismCase> plagiarismCasesOfUserInCourseExercises = plagiarismCaseRepository.findByStudentIdAndExerciseIds(userId, exerciseIds);
List<PlagiarismCase> plagiarismCasesOfUserInCourseExercises = api.findByStudentIdAndExerciseIds(userId, exerciseIds);
for (Exercise exercise : exercises) {
// Add plagiarism cases to each exercise.
Set<PlagiarismCase> plagiarismCasesForExercise = plagiarismCasesOfUserInCourseExercises.stream()
Expand Down
Loading
Loading