Skip to content

Commit

Permalink
Athena: Allow feedback suggestion module selection on exercise level (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
maximiliansoelch authored Mar 9, 2024
1 parent ca88f95 commit 562fed0
Show file tree
Hide file tree
Showing 57 changed files with 1,200 additions and 171 deletions.
11 changes: 11 additions & 0 deletions src/main/java/de/tum/in/www1/artemis/domain/Course.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ public class Course extends DomainObject {
@JsonView(QuizView.Before.class)
private Integer accuracyOfScores = 1; // default value

@Column(name = "restricted_athena_modules_access", nullable = false)
private boolean restrictedAthenaModulesAccess = false; // default is false

/**
* Note: Currently just used in the scope of the tutorial groups feature
*/
Expand Down Expand Up @@ -791,6 +794,14 @@ public void setAccuracyOfScores(Integer accuracyOfScores) {
this.accuracyOfScores = accuracyOfScores;
}

public boolean getRestrictedAthenaModulesAccess() {
return restrictedAthenaModulesAccess;
}

public void setRestrictedAthenaModulesAccess(boolean restrictedAthenaModulesAccess) {
this.restrictedAthenaModulesAccess = restrictedAthenaModulesAccess;
}

public Set<TutorialGroup> getTutorialGroups() {
return tutorialGroups;
}
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/de/tum/in/www1/artemis/domain/Exercise.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ public abstract class Exercise extends BaseExercise implements LearningObject {
@Column(name = "second_correction_enabled")
private Boolean secondCorrectionEnabled = false;

@Column(name = "feedback_suggestions_enabled") // enables Athena
private Boolean feedbackSuggestionsEnabled = false;
@Column(name = "feedback_suggestion_module") // Athena module name (Athena enabled) or null
private String feedbackSuggestionModule;

@ManyToOne
@JsonView(QuizView.Before.class)
Expand Down Expand Up @@ -782,12 +782,16 @@ public void setSecondCorrectionEnabled(boolean secondCorrectionEnabled) {
this.secondCorrectionEnabled = secondCorrectionEnabled;
}

public boolean getFeedbackSuggestionsEnabled() {
return Boolean.TRUE.equals(feedbackSuggestionsEnabled);
public String getFeedbackSuggestionModule() {
return feedbackSuggestionModule;
}

public void setFeedbackSuggestionsEnabled(boolean feedbackSuggestionsEnabled) {
this.feedbackSuggestionsEnabled = feedbackSuggestionsEnabled;
public void setFeedbackSuggestionModule(String feedbackSuggestionModule) {
this.feedbackSuggestionModule = feedbackSuggestionModule;
}

public boolean areFeedbackSuggestionsEnabled() {
return feedbackSuggestionModule != null;
}

public Set<GradingCriterion> getGradingCriteria() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import de.tum.in.www1.artemis.domain.Exercise;
import de.tum.in.www1.artemis.domain.metrics.ExerciseTypeMetricsEntry;
Expand Down Expand Up @@ -576,23 +578,39 @@ default boolean toggleSecondCorrection(Exercise exercise) {
Set<Exercise> getAllExercisesUserParticipatedInWithEagerParticipationsSubmissionsResultsFeedbacksTestCasesByUserId(@Param("userId") long userId);

/**
* Finds all exercises filtered by feedback suggestions and due date.
* Finds all exercises filtered by feedback suggestion modules not null and due date.
*
* @param feedbackSuggestionsEnabled - filter by feedback suggestions enabled
* @param dueDate - filter by due date
* @param dueDate - filter by due date
* @return Set of Exercises
*/
Set<Exercise> findByFeedbackSuggestionsEnabledAndDueDateIsAfter(boolean feedbackSuggestionsEnabled, ZonedDateTime dueDate);
Set<Exercise> findByFeedbackSuggestionModuleNotNullAndDueDateIsAfter(ZonedDateTime dueDate);

/**
* Find all exercises feedback suggestions (Athena) and with *Due Date* in the future.
*
* @return Set of Exercises
*/
default Set<Exercise> findAllFeedbackSuggestionsEnabledExercisesWithFutureDueDate() {
return findByFeedbackSuggestionsEnabledAndDueDateIsAfter(true, ZonedDateTime.now());
return findByFeedbackSuggestionModuleNotNullAndDueDateIsAfter(ZonedDateTime.now());
}

/**
* Revokes the access by setting all exercises that currently utilize a restricted module to null.
*
* @param courseId The course for which the access should be revoked
* @param restrictedFeedbackSuggestionModule Collection of restricted modules
*/
@Transactional // ok because of modifying query
@Modifying
@Query("""
UPDATE Exercise e
SET e.feedbackSuggestionModule = NULL
WHERE e.course.id = :courseId
AND e.feedbackSuggestionModule IN :restrictedFeedbackSuggestionModule
""")
void revokeAccessToRestrictedFeedbackSuggestionModulesByCourseId(@Param("courseId") Long courseId,
@Param("restrictedFeedbackSuggestionModule") Collection<String> restrictedFeedbackSuggestionModule);

/**
* For an explanation, see {@link de.tum.in.www1.artemis.web.rest.ExamResource#getAllExercisesWithPotentialPlagiarismForExam(long,long)}
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public Optional<Submission> getNextAssessableSubmission(Exercise exercise, boole
*/
public <S extends Submission> Optional<S> getAthenaSubmissionToAssess(Exercise exercise, boolean skipAssessmentQueue, boolean examMode, int correctionRound,
Function<Long, Optional<S>> findSubmissionById) {
if (exercise.getFeedbackSuggestionsEnabled() && athenaSubmissionSelectionService.isPresent() && !skipAssessmentQueue && correctionRound == 0) {
if (exercise.areFeedbackSuggestionsEnabled() && athenaSubmissionSelectionService.isPresent() && !skipAssessmentQueue && correctionRound == 0) {
var assessableSubmissions = getAssessableSubmissions(exercise, examMode, correctionRound);
var athenaSubmissionId = athenaSubmissionSelectionService.get().getProposedSubmissionId(exercise, assessableSubmissions.stream().map(Submission::getId).toList());
if (athenaSubmissionId.isPresent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public TextExercise importTextExercise(final TextExercise templateExercise, Text
TextExercise newExercise = copyTextExerciseBasis(importedExercise, gradingInstructionCopyTracker);
if (newExercise.isExamExercise()) {
// Disable feedback suggestions on exam exercises (currently not supported)
newExercise.setFeedbackSuggestionsEnabled(false);
newExercise.setFeedbackSuggestionModule(null);
}

TextExercise newTextExercise = textExerciseRepository.save(newExercise);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ public class AthenaFeedbackSendingService {

private final AthenaConnector<RequestDTO, ResponseDTO> connector;

private final AthenaModuleUrlHelper athenaModuleUrlHelper;
private final AthenaModuleService athenaModuleService;

private final AthenaDTOConverter athenaDTOConverter;

/**
* Creates a new service to send feedback to the Athena service
*/
public AthenaFeedbackSendingService(@Qualifier("athenaRestTemplate") RestTemplate athenaRestTemplate, AthenaModuleUrlHelper athenaModuleUrlHelper,
public AthenaFeedbackSendingService(@Qualifier("athenaRestTemplate") RestTemplate athenaRestTemplate, AthenaModuleService athenaModuleService,
AthenaDTOConverter athenaDTOConverter) {
connector = new AthenaConnector<>(athenaRestTemplate, ResponseDTO.class);
this.athenaModuleUrlHelper = athenaModuleUrlHelper;
this.athenaModuleService = athenaModuleService;
this.athenaDTOConverter = athenaDTOConverter;
}

Expand Down Expand Up @@ -72,7 +72,7 @@ public void sendFeedback(Exercise exercise, Submission submission, List<Feedback
*/
@Async
public void sendFeedback(Exercise exercise, Submission submission, List<Feedback> feedbacks, int maxRetries) {
if (!exercise.getFeedbackSuggestionsEnabled()) {
if (!exercise.areFeedbackSuggestionsEnabled()) {
throw new IllegalArgumentException("The exercise does not have feedback suggestions enabled.");
}

Expand All @@ -89,7 +89,7 @@ public void sendFeedback(Exercise exercise, Submission submission, List<Feedback
// Only send manual feedback from tutors to Athena
final RequestDTO request = new RequestDTO(athenaDTOConverter.ofExercise(exercise), athenaDTOConverter.ofSubmission(exercise.getId(), submission),
feedbacks.stream().filter(Feedback::isManualFeedback).map((feedback) -> athenaDTOConverter.ofFeedback(exercise, submission.getId(), feedback)).toList());
ResponseDTO response = connector.invokeWithRetry(athenaModuleUrlHelper.getAthenaModuleUrl(exercise.getExerciseType()) + "/feedbacks", request, maxRetries);
ResponseDTO response = connector.invokeWithRetry(athenaModuleService.getAthenaModuleUrl(exercise) + "/feedbacks", request, maxRetries);
log.info("Athena responded to feedback: {}", response.data);
}
catch (NetworkingException networkingException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ public class AthenaFeedbackSuggestionsService {

private final AthenaConnector<RequestDTO, ResponseDTOProgramming> programmingAthenaConnector;

private final AthenaModuleUrlHelper athenaModuleUrlHelper;
private final AthenaModuleService athenaModuleService;

private final AthenaDTOConverter athenaDTOConverter;

/**
* Creates a new AthenaFeedbackSuggestionsService to receive feedback suggestions from the Athena service.
*/
public AthenaFeedbackSuggestionsService(@Qualifier("athenaRestTemplate") RestTemplate athenaRestTemplate, AthenaModuleUrlHelper athenaModuleUrlHelper,
public AthenaFeedbackSuggestionsService(@Qualifier("athenaRestTemplate") RestTemplate athenaRestTemplate, AthenaModuleService athenaModuleService,
AthenaDTOConverter athenaDTOConverter) {
textAthenaConnector = new AthenaConnector<>(athenaRestTemplate, ResponseDTOText.class);
programmingAthenaConnector = new AthenaConnector<>(athenaRestTemplate, ResponseDTOProgramming.class);
this.athenaDTOConverter = athenaDTOConverter;
this.athenaModuleUrlHelper = athenaModuleUrlHelper;
this.athenaModuleService = athenaModuleService;
}

private record RequestDTO(ExerciseDTO exercise, SubmissionDTO submission) {
Expand Down Expand Up @@ -70,7 +70,7 @@ public List<TextFeedbackDTO> getTextFeedbackSuggestions(TextExercise exercise, T
}

final RequestDTO request = new RequestDTO(athenaDTOConverter.ofExercise(exercise), athenaDTOConverter.ofSubmission(exercise.getId(), submission));
ResponseDTOText response = textAthenaConnector.invokeWithRetry(athenaModuleUrlHelper.getAthenaModuleUrl(exercise.getExerciseType()) + "/feedback_suggestions", request, 0);
ResponseDTOText response = textAthenaConnector.invokeWithRetry(athenaModuleService.getAthenaModuleUrl(exercise) + "/feedback_suggestions", request, 0);
log.info("Athena responded to feedback suggestions request: {}", response.data);
return response.data.stream().toList();
}
Expand All @@ -86,8 +86,7 @@ public List<ProgrammingFeedbackDTO> getProgrammingFeedbackSuggestions(Programmin
log.debug("Start Athena Feedback Suggestions Service for Exercise '{}' (#{}).", exercise.getTitle(), exercise.getId());

final RequestDTO request = new RequestDTO(athenaDTOConverter.ofExercise(exercise), athenaDTOConverter.ofSubmission(exercise.getId(), submission));
ResponseDTOProgramming response = programmingAthenaConnector.invokeWithRetry(athenaModuleUrlHelper.getAthenaModuleUrl(exercise.getExerciseType()) + "/feedback_suggestions",
request, 0);
ResponseDTOProgramming response = programmingAthenaConnector.invokeWithRetry(athenaModuleService.getAthenaModuleUrl(exercise) + "/feedback_suggestions", request, 0);
log.info("Athena responded to feedback suggestions request: {}", response.data);
return response.data.stream().toList();
}
Expand Down
Loading

0 comments on commit 562fed0

Please sign in to comment.