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

General: Fix an issue with course deletion summary entries #9856

Merged
merged 12 commits into from
Jan 5, 2025
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ default Post findPostOrMessagePostByIdElseThrow(Long postId) throws EntityNotFou

List<Post> findAllByConversationId(Long conversationId);

List<Post> findAllByCourseId(Long courseId);
@Query("""
SELECT p
FROM Post p
LEFT JOIN p.conversation conversation
WHERE conversation.course.id = :courseId
""")
List<Post> findAllByCourseId(@Param("courseId") Long courseId);

List<Post> findByIdIn(List<Long> idList);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record CourseDeletionSummaryDTO(long numberOfBuilds, long numberOfCommunicationPosts, long numberOfAnswerPosts) {
public record CourseDeletionSummaryDTO(long numberOfBuilds, long numberOfCommunicationPosts, long numberOfAnswerPosts, long numberProgrammingExercises, long numberTextExercises,
long numberFileUploadExercises, long numberModelingExercises, long numberQuizExercises, long numberExams, long numberLectures) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
import de.tum.cit.aet.artemis.exam.repository.ExerciseGroupRepository;
import de.tum.cit.aet.artemis.exam.service.ExamDeletionService;
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.IncludedInOverallScore;
import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository;
import de.tum.cit.aet.artemis.exercise.repository.StudentParticipationRepository;
Expand Down Expand Up @@ -475,13 +476,26 @@ public Set<Course> findAllOnlineCoursesForPlatformForUser(String registrationId,
* @return the course deletion summary
*/
public CourseDeletionSummaryDTO getDeletionSummary(Course course) {
Long courseId = course.getId();

List<Long> programmingExerciseIds = course.getExercises().stream().map(Exercise::getId).toList();
long numberOfBuilds = buildJobRepository.countBuildJobsByExerciseIds(programmingExerciseIds);

List<Post> posts = postRepository.findAllByCourseId(course.getId());
List<Post> posts = postRepository.findAllByCourseId(courseId);
long numberOfCommunicationPosts = posts.size();
long numberOfAnswerPosts = answerPostRepository.countAnswerPostsByPostIdIn(posts.stream().map(Post::getId).toList());
ole-ve marked this conversation as resolved.
Show resolved Hide resolved
return new CourseDeletionSummaryDTO(numberOfBuilds, numberOfCommunicationPosts, numberOfAnswerPosts);
long numberLectures = lectureRepository.countByCourse_Id(courseId);
long numberExams = examRepository.countByCourse_Id(courseId);

Map<ExerciseType, Long> countByExerciseType = exerciseService.countByCourseIdGroupByType(courseId);
long numberProgrammingExercises = countByExerciseType.get(ExerciseType.PROGRAMMING);
long numberTextExercises = countByExerciseType.get(ExerciseType.TEXT);
long numberQuizExercises = countByExerciseType.get(ExerciseType.QUIZ);
long numberFileUploadExercises = countByExerciseType.get(ExerciseType.FILE_UPLOAD);
long numberModelingExercises = countByExerciseType.get(ExerciseType.MODELING);

ole-ve marked this conversation as resolved.
Show resolved Hide resolved
return new CourseDeletionSummaryDTO(numberOfBuilds, numberOfCommunicationPosts, numberOfAnswerPosts, numberProgrammingExercises, numberTextExercises,
numberFileUploadExercises, numberModelingExercises, numberQuizExercises, numberExams, numberLectures);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,8 @@ SELECT COUNT(studentExam)
""")
long countGeneratedStudentExamsByExamWithoutTestRuns(@Param("examId") long examId);

long countByCourse_Id(Long courseId);

/**
* Returns the title of the exam with the given id.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.tum.cit.aet.artemis.exercise.dto;

import java.util.Objects;

import de.tum.cit.aet.artemis.exercise.domain.Exercise;
import de.tum.cit.aet.artemis.exercise.domain.ExerciseType;

public record ExerciseTypeCountDTO(ExerciseType exerciseType, long count) {

public ExerciseTypeCountDTO(Class<?> exerciseType, Long count) {
this(ExerciseType.getExerciseTypeFromClass(exerciseType.asSubclass(Exercise.class)), Objects.requireNonNullElse(count, 0L));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import de.tum.cit.aet.artemis.core.repository.base.ArtemisJpaRepository;
import de.tum.cit.aet.artemis.exam.web.ExamResource;
import de.tum.cit.aet.artemis.exercise.domain.Exercise;
import de.tum.cit.aet.artemis.exercise.dto.ExerciseTypeCountDTO;
import de.tum.cit.aet.artemis.exercise.dto.ExerciseTypeMetricsEntry;

/**
Expand Down Expand Up @@ -627,4 +628,21 @@ SELECT count(e) > 0
AND e.exerciseGroup IS NOT NULL
""")
boolean isExamExercise(@Param("exerciseId") long exerciseId);

/**
* Returns a mapping from exercise type to count for a given course id. Note that there are way fewer courses
* than exercise, so loading the course and joining the course is way faster than vice versa.
*
* @param courseId the courseId to get the exerciseType->count mapping for
* @return a list of mappings from exercise type to count
*/
@Query("""
SELECT new de.tum.cit.aet.artemis.exercise.dto.ExerciseTypeCountDTO(TYPE(e), COUNT(e))
FROM Course c
JOIN c.exercises e
WHERE c.id = :courseId
AND TYPE(e) IN (ModelingExercise, TextExercise, ProgrammingExercise, QuizExercise, FileUploadExercise)
GROUP BY TYPE(e)
""")
List<ExerciseTypeCountDTO> countByCourseIdGroupedByType(@Param("courseId") long courseId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import static java.time.ZonedDateTime.now;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
Expand Down Expand Up @@ -63,9 +64,11 @@
import de.tum.cit.aet.artemis.exam.service.ExamLiveEventsService;
import de.tum.cit.aet.artemis.exercise.domain.Exercise;
import de.tum.cit.aet.artemis.exercise.domain.ExerciseMode;
import de.tum.cit.aet.artemis.exercise.domain.ExerciseType;
import de.tum.cit.aet.artemis.exercise.domain.Submission;
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.dto.ExerciseTypeCountDTO;
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.repository.SubmissionRepository;
Expand Down Expand Up @@ -829,4 +832,17 @@ public <T extends Exercise> T saveWithCompetencyLinks(T exercise, Function<T, T>
public void reconnectCompetencyExerciseLinks(Exercise exercise) {
exercise.getCompetencyLinks().forEach(link -> link.setExercise(exercise));
}

/**
* Returns a map from exercise type to count of exercise given a course id.
*
* @param courseId the course id
* @return the mapping from exercise type to course type. If a course has no exercises for a specific type, the map contains an entry for that type with value 0.
*/
public Map<ExerciseType, Long> countByCourseIdGroupByType(Long courseId) {
Map<ExerciseType, Long> exerciseTypeCountMap = exerciseRepository.countByCourseIdGroupedByType(courseId).stream()
.collect(Collectors.toMap(ExerciseTypeCountDTO::exerciseType, ExerciseTypeCountDTO::count));

return Arrays.stream(ExerciseType.values()).collect(Collectors.toMap(type -> type, type -> exerciseTypeCountMap.getOrDefault(type, 0L)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,6 @@ default Lecture findByIdWithLectureUnitsAndSlidesAndAttachmentsElseThrow(long le
GROUP BY l.course.id
""")
Set<CourseContentCount> countVisibleLectures(@Param("courseIds") Set<Long> courseIds, @Param("now") ZonedDateTime now);

long countByCourse_Id(Long courseId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,6 @@ export class CourseManagementTabBarComponent implements OnInit, OnDestroy, After
}

private getExistingSummaryEntries(): EntitySummary {
const numberRepositories =
this.course?.exercises
?.filter((exercise) => exercise.type === 'programming')
.map((exercise) => exercise?.numberOfParticipations ?? 0)
.reduce((repositorySum, numberOfParticipationsForRepository) => repositorySum + numberOfParticipationsForRepository, 0) ?? 0;

const numberOfExercisesPerType = new Map<ExerciseType, number>();
this.course?.exercises?.forEach((exercise) => {
if (exercise.type === undefined) {
Expand All @@ -219,23 +213,13 @@ export class CourseManagementTabBarComponent implements OnInit, OnDestroy, After
numberOfExercisesPerType.set(exercise.type, oldValue + 1);
});

const numberExams = this.course?.numberOfExams ?? 0;
const numberLectures = this.course?.lectures?.length ?? 0;
const numberStudents = this.course?.numberOfStudents ?? 0;
const numberTutors = this.course?.numberOfTeachingAssistants ?? 0;
const numberEditors = this.course?.numberOfEditors ?? 0;
const numberInstructors = this.course?.numberOfInstructors ?? 0;
const isTestCourse = this.course?.testCourse;

return {
'artemisApp.course.delete.summary.numberRepositories': numberRepositories,
'artemisApp.course.delete.summary.numberProgrammingExercises': numberOfExercisesPerType.get(ExerciseType.PROGRAMMING) ?? 0,
'artemisApp.course.delete.summary.numberModelingExercises': numberOfExercisesPerType.get(ExerciseType.MODELING) ?? 0,
'artemisApp.course.delete.summary.numberTextExercises': numberOfExercisesPerType.get(ExerciseType.TEXT) ?? 0,
'artemisApp.course.delete.summary.numberFileUploadExercises': numberOfExercisesPerType.get(ExerciseType.FILE_UPLOAD) ?? 0,
'artemisApp.course.delete.summary.numberQuizExercises': numberOfExercisesPerType.get(ExerciseType.QUIZ) ?? 0,
'artemisApp.course.delete.summary.numberExams': numberExams,
'artemisApp.course.delete.summary.numberLectures': numberLectures,
'artemisApp.course.delete.summary.numberStudents': numberStudents,
'artemisApp.course.delete.summary.numberTutors': numberTutors,
'artemisApp.course.delete.summary.numberEditors': numberEditors,
Expand All @@ -259,6 +243,13 @@ export class CourseManagementTabBarComponent implements OnInit, OnDestroy, After

return {
...this.getExistingSummaryEntries(),
'artemisApp.course.delete.summary.numberExams': summary.numberExams,
'artemisApp.course.delete.summary.numberLectures': summary.numberLectures,
'artemisApp.course.delete.summary.numberProgrammingExercises': summary.numberProgrammingExercises,
'artemisApp.course.delete.summary.numberTextExercises': summary.numberTextExercises,
'artemisApp.course.delete.summary.numberFileUploadExercises': summary.numberFileUploadExercises,
'artemisApp.course.delete.summary.numberQuizExercises': summary.numberQuizExercises,
'artemisApp.course.delete.summary.numberModelingExercises': summary.numberModelingExercises,
ole-ve marked this conversation as resolved.
Show resolved Hide resolved
'artemisApp.course.delete.summary.numberBuilds': summary.numberOfBuilds,
'artemisApp.course.delete.summary.numberCommunicationPosts': summary.numberOfCommunicationPosts,
'artemisApp.course.delete.summary.numberAnswerPosts': summary.numberOfAnswerPosts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@ export interface CourseDeletionSummaryDTO {
numberOfBuilds: number;
numberOfCommunicationPosts: number;
numberOfAnswerPosts: number;
numberProgrammingExercises: number;
numberTextExercises: number;
numberFileUploadExercises: number;
numberQuizExercises: number;
numberModelingExercises: number;
numberExams: number;
numberLectures: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,6 @@ private Post createMessageWithReactionForUser(String login, String messageText,
message.setAuthor(userUtilService.getUserByLogin(login));
message.setContent(messageText);
message.setCreationDate(ZonedDateTime.now());
message.setCourse(conversation.getCourse());
conversation.setCreator(message.getAuthor());
addReactionForUserToPost(login, message);
conversationRepository.save(conversation);
Expand Down
Loading