Skip to content
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
36b6b0d
try to improve database performance
krusche Aug 10, 2025
dd9e7e1
additional performance improvements
krusche Aug 10, 2025
c218720
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 11, 2025
8cda8d9
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 12, 2025
a5d66cb
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 14, 2025
f683494
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 16, 2025
7ecb3ee
Merge branch 'develop' into chore/improve-management-stats-performance
krusche Aug 26, 2025
1b3e6d0
Merge branch 'develop' into chore/improve-management-stats-performance
tobias-lippert Aug 26, 2025
e46a314
cleanup and add logging
tobias-lippert Aug 26, 2025
037fdf6
speedup active students query
tobias-lippert Aug 26, 2025
0072bd8
fix bug assessments over 100%
tobias-lippert Sep 1, 2025
53efabc
add exercise id to result
tobias-lippert Sep 2, 2025
ec9675b
set exercise id for programming exercise results
tobias-lippert Sep 2, 2025
9ee9a88
add changelog to master.xml
tobias-lippert Sep 2, 2025
81e8529
adjust query to new table layout
tobias-lippert Sep 4, 2025
4940811
adapt query
tobias-lippert Sep 5, 2025
bac732d
Revert "speedup active students query"
tobias-lippert Sep 5, 2025
fc8ee50
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Sep 21, 2025
5a47625
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 4, 2025
d4fd6b6
migration
tobias-lippert Oct 4, 2025
a89f982
adapt queries
tobias-lippert Oct 4, 2025
b697052
fix architecture tests
tobias-lippert Oct 5, 2025
8c7abfa
fix course tests
tobias-lippert Oct 5, 2025
4fb8942
switch to liquibase migration
tobias-lippert Oct 6, 2025
0bdaf62
try to fix migration
tobias-lippert Oct 6, 2025
43eddf0
fix db migration
tobias-lippert Oct 7, 2025
2670a00
add rollback
tobias-lippert Oct 7, 2025
3f9ce53
fix server style, guard against some empty clauses and introduce help…
tobias-lippert Oct 7, 2025
b56d1d7
fix server style again
tobias-lippert Oct 7, 2025
b36c0a8
down to 511 test failures
tobias-lippert Oct 8, 2025
ae3bf01
down to 57 test failures
tobias-lippert Oct 8, 2025
cc4f177
down to 45 test failures
tobias-lippert Oct 8, 2025
9a809ef
fix remaining tests
tobias-lippert Oct 8, 2025
a7a00de
rabbit
tobias-lippert Oct 8, 2025
cf1f2e5
code review
tobias-lippert Oct 10, 2025
612b115
fix javadoc
tobias-lippert Oct 10, 2025
8994631
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 12, 2025
1736988
remove newline at the end of runconfig
tobias-lippert Oct 12, 2025
a31473d
fix indentation
tobias-lippert Oct 14, 2025
74f9984
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 15, 2025
7ce07eb
Merge branch 'develop' into chore/further-management-stats-improvement
tobias-lippert Oct 15, 2025
901c7e3
Merge branch 'develop' into chore/further-management-stats-improvement
krusche Oct 18, 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
2 changes: 1 addition & 1 deletion .idea/runConfigurations/Artemis_BuildAgent__Prod_.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ public class Result extends DomainObject implements Comparable<Result> {
@JsonIgnore
private Instant lastModifiedDate;

@Column(name = "exercise_id", nullable = false)
private long exerciseId;

public ZonedDateTime getCompletionDate() {
return completionDate;
}
Expand Down Expand Up @@ -169,10 +172,23 @@ public Result score(Double score) {
return this;
}

public Result exerciseId(long exerciseId) {
this.exerciseId = exerciseId;
return this;
}

public Instant getLastModifiedDate() {
return lastModifiedDate;
}

public long getExerciseId() {
return exerciseId;
}

public void setExerciseId(long exerciseId) {
this.exerciseId = exerciseId;
}

/**
* Sets the score to the specified score rounded to 4 decimal places.
* If you are handling student results that potentially need rounding, use {@link Result#setScore(Double score, Course course)} instead!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,13 @@ public interface ComplaintRepository extends ArtemisJpaRepository<Complaint, Lon
""")
Optional<Complaint> findByIdWithEagerAssessor(@Param("complaintId") Long complaintId);

/**
* This magic method counts the number of complaints by complaint type associated to a course id
*
* @param courseId - the id of the course we want to filter by
* @param complaintType - type of complaint we want to filter by
* @return number of more feedback requests associated to course courseId
*/
long countByResult_Submission_Participation_Exercise_Course_IdAndComplaintType(Long courseId, ComplaintType complaintType);

/**
* This magic method counts the number of complaints by complaint type associated to an exam id
*
* @param examId - the id of the exam we want to filter by
* @param complaintType - type of complaint we want to filter by
* @return number of complaints associated to course examId
*/
long countByResult_Submission_Participation_Exercise_ExerciseGroup_Exam_IdAndComplaintType(Long examId, ComplaintType complaintType);
@Query("""
SELECT COUNT(c)
FROM Complaint c
WHERE c.result.exerciseId IN :exerciseIds
AND c.complaintType = :complaintType
""")
long countByExerciseIdsAndComplaintType(@Param("exerciseIds") Set<Long> exerciseIds, @Param("complaintType") ComplaintType complaintType);

@Query("""
SELECT c
Expand Down Expand Up @@ -142,7 +132,7 @@ SELECT COUNT(c)
@Query("""
SELECT COUNT(c)
FROM Complaint c
WHERE c.result.submission.participation.exercise.id = :exerciseId
WHERE c.result.exerciseId = :exerciseId
AND c.complaintType = :complaintType
""")
long countComplaintsByExerciseIdAndComplaintType(@Param("exerciseId") Long exerciseId, @Param("complaintType") ComplaintType complaintType);
Expand All @@ -156,13 +146,13 @@ SELECT COUNT(c)
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
c.result.submission.participation.exercise.id,
c.result.exerciseId,
COUNT(DISTINCT c)
)
FROM Complaint c
WHERE c.result.submission.participation.exercise.id IN :exerciseIds
WHERE c.result.exerciseId IN :exerciseIds
AND c.complaintType = :complaintType
GROUP BY c.result.submission.participation.exercise.id
GROUP BY c.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintType(@Param("exerciseIds") Set<Long> exerciseIds, @Param("complaintType") ComplaintType complaintType);

Expand All @@ -175,14 +165,14 @@ SELECT COUNT(c)
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
c.result.submission.participation.exercise.id,
c.result.exerciseId,
COUNT(DISTINCT c)
)
FROM Complaint c
WHERE c.result.submission.participation.exercise.id IN :exerciseIds
WHERE c.result.exerciseId IN :exerciseIds
AND c.complaintType = :complaintType
AND c.result.submission.participation.testRun = FALSE
GROUP BY c.result.submission.participation.exercise.id
GROUP BY c.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintTypeIgnoreTestRuns(@Param("exerciseIds") Set<Long> exerciseIds,
@Param("complaintType") ComplaintType complaintType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,22 @@ public interface ComplaintResponseRepository extends ArtemisJpaRepository<Compla
/**
* This magic method counts the number of complaints responses by complaint type associated to a course id
*
* @param courseId - the id of the course we want to filter by
* @param complaintType - complaint type we want to filter by
* @return number of complaints response associated to course courseId
*/
long countByComplaint_Result_Submission_Participation_Exercise_Course_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(Long courseId, ComplaintType complaintType);

/**
* This magic method counts the number of complaints responses by complaint type associated to an exam id
* @param exerciseIds - of the exercises we want to filter by
* @return number of complaints response associated to the given exercise ids
*
* @param examId - the id of the exam we want to filter by
* @param complaintType - complaint type we want to filter by
* @return number of complaints response associated to exam examId
*/
long countByComplaint_Result_Submission_Participation_Exercise_ExerciseGroup_Exam_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(Long examId,
ComplaintType complaintType);

@Query("""
SELECT COUNT(DISTINCT cr)
FROM ComplaintResponse cr
JOIN cr.complaint c
JOIN c.result r
WHERE r.exerciseId IN :exerciseIds
AND cr.submittedTime IS NOT NULL
AND c.complaintType = :complaintType
""")
long countComplaintResponsesForExerciseIdsAndComplaintType(@Param("exerciseIds") Set<Long> exerciseIds, @Param("complaintType") ComplaintType complaintType);

/**
* This magic method counts the number of complaints responses by complaint type associated to an exercise id
Expand All @@ -55,7 +56,7 @@ long countByComplaint_Result_Submission_Participation_Exercise_ExerciseGroup_Exa
@Query("""
SELECT COUNT(DISTINCT cr)
FROM ComplaintResponse cr
WHERE cr.complaint.result.submission.participation.exercise.id = :exerciseId
WHERE cr.complaint.result.exerciseId = :exerciseId
AND cr.complaint.complaintType = :complaintType
AND cr.submittedTime IS NOT NULL
""")
Expand All @@ -70,15 +71,15 @@ SELECT COUNT(DISTINCT cr)
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
cr.complaint.result.submission.participation.exercise.id,
cr.complaint.result.exerciseId,
COUNT(DISTINCT cr)
)
FROM ComplaintResponse cr
WHERE cr.complaint.result.submission.participation.exercise.id IN :exerciseIds
WHERE cr.complaint.result.exerciseId IN :exerciseIds
AND cr.submittedTime IS NOT NULL
AND cr.complaint.complaintType = :complaintType
AND cr.complaint.result.submission.participation.testRun = FALSE
GROUP BY cr.complaint.result.submission.participation.exercise.id
GROUP BY cr.complaint.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintComplaintTypeIgnoreTestRuns(@Param("exerciseIds") Set<Long> exerciseIds,
@Param("complaintType") ComplaintType complaintType);
Expand All @@ -92,14 +93,14 @@ List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintComplaintTypeI
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.assessment.dto.dashboard.ExerciseMapEntryDTO(
cr.complaint.result.submission.participation.exercise.id,
cr.complaint.result.exerciseId,
COUNT(DISTINCT cr)
)
FROM ComplaintResponse cr
WHERE cr.complaint.result.submission.participation.exercise.id IN :exerciseIds
WHERE cr.complaint.result.exerciseId IN :exerciseIds
AND cr.submittedTime IS NOT NULL
AND cr.complaint.complaintType = :complaintType
GROUP BY cr.complaint.result.submission.participation.exercise.id
GROUP BY cr.complaint.result.exerciseId
""")
List<ExerciseMapEntryDTO> countComplaintsByExerciseIdsAndComplaintComplaintType(@Param("exerciseIds") Set<Long> exerciseIds,
@Param("complaintType") ComplaintType complaintType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ public interface ResultRepository extends ArtemisJpaRepository<Result, Long> {

@Query("""
SELECT r
FROM Result r
LEFT JOIN FETCH r.assessor
WHERE r.id = :resultId
FROM Result r
LEFT JOIN FETCH r.assessor
WHERE r.id = :resultId
""")
Optional<Result> findByIdWithEagerAssessor(@Param("resultId") long resultId);

Expand Down Expand Up @@ -220,7 +220,7 @@ SELECT COUNT(r)
WHERE r.completionDate IS NOT NULL
AND r.assessor IS NOT NULL
AND p.testRun = FALSE
AND p.exercise.id IN :exerciseIds
AND r.exerciseId IN :exerciseIds
""")
long countAssessmentsForExerciseIdsIgnoreTestRuns(@Param("exerciseIds") Set<Long> exerciseIdsWithManualAssessment);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,17 @@ private Result submitManualAssessment(long resultId, Exercise exercise) {
* @param feedbackList the assessment as a feedback list that should be added to the result of the corresponding submission
* @param resultId id of the result we want to save the feedbackList to, null if no result exists
* @param assessmentNoteText the text of the assessment note of the result
* @param exerciseId the id of the exercise the assessment belongs to
* @return the saved result
*/
public Result saveManualAssessment(final Submission submission, final List<Feedback> feedbackList, Long resultId, String assessmentNoteText) {
public Result saveManualAssessment(final Submission submission, final List<Feedback> feedbackList, Long resultId, String assessmentNoteText, long exerciseId) {
Result result = null;
if (resultId != null) {
result = resultRepository.findWithEagerSubmissionAndFeedbackAndTestCasesAndAssessmentNoteById(resultId).orElse(null);
}

if (result == null) {
result = submissionService.saveNewEmptyResult(submission);
result = submissionService.saveNewEmptyResult(submission, exerciseId);
}

// important to not lose complaint information when overriding an assessment
Expand Down Expand Up @@ -325,7 +326,7 @@ public Result saveManualAssessment(final Submission submission, final List<Feedb
*/
public Result saveAndSubmitManualAssessment(final Exercise exercise, final Submission submission, final List<Feedback> feedbackList, Long resultId, String assessmentNoteText,
boolean submit) {
Result result = saveManualAssessment(submission, feedbackList, resultId, assessmentNoteText);
Result result = saveManualAssessment(submission, feedbackList, resultId, assessmentNoteText, exercise.getId());
if (!submit) {
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,34 +174,56 @@ else if (participant instanceof Team) {
}
}

public long countComplaintsByCourseId(long courseId) {
return complaintRepository.countByResult_Submission_Participation_Exercise_Course_IdAndComplaintType(courseId, ComplaintType.COMPLAINT);
/**
* Counts the number of complaints for the given exercise ids
*
* @param exerciseIds the ids of the exercises
* @return the number of complaints
*/
public long countComplaintsByExerciseIds(Set<Long> exerciseIds) {
if (exerciseIds == null || exerciseIds.isEmpty()) {
return 0L;
}
return complaintRepository.countByExerciseIdsAndComplaintType(exerciseIds, ComplaintType.COMPLAINT);
}

public long countMoreFeedbackRequestsByCourseId(long courseId) {
return complaintRepository.countByResult_Submission_Participation_Exercise_Course_IdAndComplaintType(courseId, ComplaintType.MORE_FEEDBACK);
/**
* Counts the number of more feedback requests for the given exercise ids
*
* @param exerciseIds the ids of the exercises
* @return the number of more feedback requests
*/
public long countMoreFeedbackRequestsByExerciseIds(Set<Long> exerciseIds) {
if (exerciseIds == null || exerciseIds.isEmpty()) {
return 0L;
}
return complaintRepository.countByExerciseIdsAndComplaintType(exerciseIds, ComplaintType.MORE_FEEDBACK);
}

/**
* Counts the number of responses to complaints for the given course id
* Counts the number of responses to complaints for the given exercise ids
*
* @param courseId the id of the course
* @param exerciseIds the ids of the exercises
* @return the number of responses
*/
public long countComplaintResponsesByCourseId(long courseId) {
return complaintResponseRepository.countByComplaint_Result_Submission_Participation_Exercise_Course_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(courseId,
ComplaintType.COMPLAINT);
public long countComplaintResponsesByExerciseIds(Set<Long> exerciseIds) {
if (exerciseIds == null || exerciseIds.isEmpty()) {
return 0L;
}
return complaintResponseRepository.countComplaintResponsesForExerciseIdsAndComplaintType(exerciseIds, ComplaintType.COMPLAINT);
}

/**
* Counts the number of responses to feedback requests for the given course id
* Counts the number of responses to feedback requests for the given exercise ids
*
* @param courseId the id of the course
* @param exerciseIds the ids of the exercises
* @return the number of responses
*/
public long countMoreFeedbackRequestResponsesByCourseId(long courseId) {
return complaintResponseRepository.countByComplaint_Result_Submission_Participation_Exercise_Course_Id_AndComplaint_ComplaintType_AndSubmittedTimeIsNotNull(courseId,
ComplaintType.MORE_FEEDBACK);
public long countMoreFeedbackRequestResponsesByExerciseIds(Set<Long> exerciseIds) {
if (exerciseIds == null || exerciseIds.isEmpty()) {
return 0L;
}
return complaintResponseRepository.countComplaintResponsesForExerciseIdsAndComplaintType(exerciseIds, ComplaintType.MORE_FEEDBACK);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ protected Result saveExampleAssessment(long exampleSubmissionId, List<Feedback>
// as parameter resultId is not set, we use the latest Result, if no latest Result exists, we use null
Result result;
if (submission.getLatestResult() == null) {
result = assessmentService.saveManualAssessment(submission, feedbacks, null, null);
result = assessmentService.saveManualAssessment(submission, feedbacks, null, null, exercise.getId());
}
else {
result = assessmentService.saveManualAssessment(submission, feedbacks, submission.getLatestResult().getId(), null);
result = assessmentService.saveManualAssessment(submission, feedbacks, submission.getLatestResult().getId(), null, exercise.getId());
}
return resultRepository.submitResult(result, exercise);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ public StatisticsEntry(String date, String username) {
this.username = username;
}

public StatisticsEntry(int year, int month, int day, String username) {
this.date = String.format("%04d-%02d-%02d", year, month, day);
this.amount = 1L;
this.username = username;
}

// empty constructor
public StatisticsEntry() {
this.amount = 0L;
Expand Down
Loading
Loading