Skip to content

Commit

Permalink
Merge branch 'develop' into feature/programming-exercises/remove-test…
Browse files Browse the repository at this point in the history
…suites-workaround-jenkins
  • Loading branch information
b-fein authored Nov 27, 2024
2 parents 4e99ebf + 83ac531 commit 545dee6
Show file tree
Hide file tree
Showing 236 changed files with 5,765 additions and 1,207 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ Refer to [Using JHipster in production](http://www.jhipster.tech/production) for
The following command can automate the deployment to a server. The example shows the deployment to the main Artemis test server (which runs a virtual machine):

```shell
./artemis-server-cli deploy [email protected] -w build/libs/Artemis-7.7.2.war
./artemis-server-cli deploy [email protected] -w build/libs/Artemis-7.7.3.war
```

## Architecture
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ plugins {
}

group = "de.tum.cit.aet.artemis"
version = "7.7.2"
version = "7.7.3"
description = "Interactive Learning with Individual Feedback"

java {
Expand Down
Binary file modified docs/user/exams/student/access_exam.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/buttons/exam_hand_in_early.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/exams/student/buttons/save_exercise.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/exams/student/buttons/upload.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_bar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_modeling_exercises.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_navigation_sidebar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_overview.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_programming_exercises.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_quiz_exercises.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/exams/student/exam_text_exercises.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions docs/user/exams/students_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ Welcome Screen

Welcome Screen, waiting for exam start

This video offers a detailed guide on accessing your exams:

.. raw:: html

<iframe src="https://live.rbg.tum.de/w/artemisintro/52546?video_only=1&t=0" allowfullscreen="1" frameborder="0" width="600" height="350">
Watch this video on TUM-Live.
</iframe>

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.
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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

<iframe src="https://live.rbg.tum.de/w/artemisintro/53405?video_only=1&t=0" allowfullscreen="1" frameborder="0" width="600" height="350">
Watch this video on TUM-Live.
</iframe>

Example Solutions
^^^^^^^^^^^^^^^^^
- If the instructor sets the example solution publication date of the exam, the solutions will be available after that date.
Expand Down Expand Up @@ -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
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "artemis",
"version": "7.7.2",
"version": "7.7.3",
"description": "Interactive Learning with Individual Feedback",
"private": true,
"license": "MIT",
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/de/tum/cit/aet/artemis/assessment/domain/Result.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,12 @@ public class Result extends DomainObject implements Comparable<Result> {
@JsonView(QuizView.Before.class)
private List<Feedback> feedbacks = new ArrayList<>();

/**
* @deprecated: Will be removed for 8.0, please use submission.participation instead
*/
@ManyToOne
@JsonView(QuizView.Before.class)
@Deprecated(since = "7.7", forRemoval = true)
private Participation participation;

@ManyToOne(fetch = FetchType.LAZY)
Expand Down Expand Up @@ -385,15 +389,31 @@ private boolean feedbackTextHasChanged(String existingText, String newText) {
return !Objects.equals(existingText, newText);
}

/**
* @deprecated: Will be removed for 8.0, please use submission.participation instead
* @return the participation
*/
@Deprecated(since = "7.7", forRemoval = true)
public Participation getParticipation() {
return participation;
}

/**
* @deprecated: Will be removed for 8.0, please use submission.participation instead
* @param participation the participation to set
* @return the result
*/
@Deprecated(since = "7.7", forRemoval = true)
public Result participation(Participation participation) {
this.participation = participation;
return this;
}

/**
* @deprecated: Will be removed for 8.0, please use submission.participation instead
* @param participation the participation to set
*/
@Deprecated(since = "7.7", forRemoval = true)
public void setParticipation(Participation participation) {
this.participation = participation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -692,4 +692,15 @@ public void deleteLongFeedback(List<Feedback> feedbackList, Result result) {
List<Feedback> feedbacks = new ArrayList<>(feedbackList);
result.updateAllFeedbackItems(feedbacks, true);
}

/**
* Retrieves the number of students affected by a specific feedback detail text for a given exercise.
*
* @param exerciseId for which the affected student count is requested.
* @param detailText used to filter affected students.
* @return the total number of distinct students affected by the feedback detail text.
*/
public long getAffectedStudentCountByFeedbackDetailText(long exerciseId, String detailText) {
return studentParticipationRepository.countAffectedStudentsByFeedbackDetailText(exerciseId, detailText);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,4 +373,18 @@ public ResponseEntity<Page<FeedbackAffectedStudentDTO>> getAffectedStudentsWithF

return ResponseEntity.ok(participation);
}

/**
* GET /exercises/{exerciseId}/feedback-detail/affected-students : Retrieves the count of students affected by a specific feedback detail text.
*
* @param exerciseId The ID of the exercise for which affected students are counted.
* @param detailText The feedback detail text to filter by.
* @return A {@link ResponseEntity} containing the count of affected students.
*/
@GetMapping("exercises/{exerciseId}/feedback-detail/affected-students")
@EnforceAtLeastEditorInExercise
public ResponseEntity<Long> countAffectedStudentsByFeedbackDetailText(@PathVariable long exerciseId, @RequestParam("detailText") String detailText) {
long affectedStudentCount = resultService.getAffectedStudentCountByFeedbackDetailText(exerciseId, detailText);
return ResponseEntity.ok(affectedStudentCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -103,7 +100,6 @@ public CourseCompetencyService(CompetencyProgressRepository competencyProgressRe
this.standardizedCompetencyRepository = standardizedCompetencyRepository;
this.lectureUnitCompletionRepository = lectureUnitCompletionRepository;
this.learningObjectImportService = learningObjectImportService;
this.competencyLectureUnitLinkRepository = competencyLectureUnitLinkRepository;
this.courseRepository = courseRepository;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.tum.cit.aet.artemis.buildagent.dto;

import java.io.Serializable;
import java.time.ZonedDateTime;

import jakarta.validation.constraints.NotNull;

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record BuildLogDTO(@NotNull ZonedDateTime time, @NotNull String log) implements Serializable {

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
// in the future are migrated or cleared. Changes should be communicated in release notes as potentially breaking changes.
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
// TODO: this should be a record in the future
public class BuildResult extends AbstractBuildResultNotificationDTO implements Serializable {

private final String assignmentRepoBranchName;
Expand All @@ -41,7 +42,7 @@ public class BuildResult extends AbstractBuildResultNotificationDTO implements S

private final List<LocalCIJobDTO> jobs;

private List<BuildLogEntry> buildLogEntries = new ArrayList<>();
private List<BuildLogDTO> buildLogEntries = new ArrayList<>();

private final List<StaticCodeAnalysisReportDTO> staticCodeAnalysisReports;

Expand Down Expand Up @@ -123,15 +124,16 @@ public boolean hasLogs() {

@Override
public List<BuildLogEntry> extractBuildLogs() {
return buildLogEntries;
// convert the buildLogEntry DTOs to BuildLogEntry objects
return buildLogEntries.stream().map(log -> new BuildLogEntry(log.time(), log.log())).toList();
}

/**
* Setter for the buildLogEntries
*
* @param buildLogEntries the buildLogEntries to be set
*/
public void setBuildLogEntries(List<BuildLogEntry> buildLogEntries) {
public void setBuildLogEntries(List<BuildLogDTO> buildLogEntries) {
this.buildLogEntries = buildLogEntries;
hasLogs = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@

import com.fasterxml.jackson.annotation.JsonInclude;

import de.tum.cit.aet.artemis.programming.domain.build.BuildLogEntry;

// NOTE: this data structure is used in shared code between core and build agent nodes. Changing it requires that the shared data structures in Hazelcast (or potentially Redis)
// in the future are migrated or cleared. Changes should be communicated in release notes as potentially breaking changes.
@JsonInclude(JsonInclude.Include.NON_EMPTY)
// TODO: this data structure should not use BuildLogEntry because it's an entity class (and not a DTO)
public record ResultQueueItem(BuildResult buildResult, BuildJobQueueItem buildJobQueueItem, List<BuildLogEntry> buildLogs, Throwable exception) implements Serializable {
public record ResultQueueItem(BuildResult buildResult, BuildJobQueueItem buildJobQueueItem, List<BuildLogDTO> buildLogs, Throwable exception) implements Serializable {
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,14 @@ public static class MyPullImageResultCallback extends PullImageResultCallback {
@Override
public void onNext(PullResponseItem item) {
String msg = "~~~~~~~~~~~~~~~~~~~~ Pull image progress: " + item.getStatus() + " ~~~~~~~~~~~~~~~~~~~~";
log.info(msg);
buildLogsMap.appendBuildLogEntry(buildJobId, msg);
log.debug(msg);
super.onNext(item);
}

@Override
public void onComplete() {
String msg = "~~~~~~~~~~~~~~~~~~~~ Pull image complete ~~~~~~~~~~~~~~~~~~~~";
log.info(msg);
buildLogsMap.appendBuildLogEntry(buildJobId, msg);
log.debug(msg);
super.onComplete();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
import com.github.dockerjava.api.model.Frame;
import com.github.dockerjava.api.model.HostConfig;

import de.tum.cit.aet.artemis.buildagent.dto.BuildLogDTO;
import de.tum.cit.aet.artemis.core.exception.LocalCIException;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage;
import de.tum.cit.aet.artemis.programming.domain.build.BuildLogEntry;
import de.tum.cit.aet.artemis.programming.service.ci.ContinuousIntegrationService.RepositoryCheckoutPath;

/**
Expand Down Expand Up @@ -414,7 +414,7 @@ private void executeDockerCommand(String containerId, String buildJobId, boolean
@Override
public void onNext(Frame item) {
String text = new String(item.getPayload());
BuildLogEntry buildLogEntry = new BuildLogEntry(ZonedDateTime.now(), text);
BuildLogDTO buildLogEntry = new BuildLogDTO(ZonedDateTime.now(), text);
if (buildJobId != null) {
buildLogsMap.appendBuildLogEntry(buildJobId, buildLogEntry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ private BuildResult runScriptAndParseResults(BuildJobQueueItem buildJob, String
try {
buildResult = parseTestResults(testResultsTarInputStream, buildJob.buildConfig().branch(), assignmentRepoCommitHash, testRepoCommitHash, buildCompletedDate,
buildJob.id());
buildResult.setBuildLogEntries(buildLogsMap.getBuildLogs(buildJob.id()));
buildResult.setBuildLogEntries(buildLogsMap.getAndTruncateBuildLogs(buildJob.id()));
}
catch (IOException | IllegalStateException e) {
msg = "Error while parsing test results";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
import com.hazelcast.topic.ITopic;

import de.tum.cit.aet.artemis.buildagent.dto.BuildJobQueueItem;
import de.tum.cit.aet.artemis.buildagent.dto.BuildLogDTO;
import de.tum.cit.aet.artemis.buildagent.dto.BuildResult;
import de.tum.cit.aet.artemis.core.exception.LocalCIException;
import de.tum.cit.aet.artemis.programming.domain.build.BuildLogEntry;

/**
* This service is responsible for adding build jobs to the Integrated Code Lifecycle executor service.
Expand Down Expand Up @@ -171,7 +171,7 @@ public CompletableFuture<BuildResult> executeBuildJob(BuildJobQueueItem buildJob
finishCancelledBuildJob(buildJobItem.repositoryInfo().assignmentRepositoryUri(), buildJobItem.id(), containerName);
String msg = "Build job with id " + buildJobItem.id() + " was cancelled.";
String stackTrace = stackTraceToString(e);
buildLogsMap.appendBuildLogEntry(buildJobItem.id(), new BuildLogEntry(ZonedDateTime.now(), msg + "\n" + stackTrace));
buildLogsMap.appendBuildLogEntry(buildJobItem.id(), new BuildLogDTO(ZonedDateTime.now(), msg + "\n" + stackTrace));
throw new CompletionException(msg, e);
}
else {
Expand Down Expand Up @@ -232,7 +232,7 @@ private CompletableFuture<BuildResult> createCompletableFuture(Supplier<BuildRes
private void finishBuildJobExceptionally(String buildJobId, String containerName, Exception exception) {
String msg = "Error while executing build job " + buildJobId + ": " + exception.getMessage();
String stackTrace = stackTraceToString(exception);
buildLogsMap.appendBuildLogEntry(buildJobId, new BuildLogEntry(ZonedDateTime.now(), msg + "\n" + stackTrace));
buildLogsMap.appendBuildLogEntry(buildJobId, new BuildLogDTO(ZonedDateTime.now(), msg + "\n" + stackTrace));
log.error(msg);

log.info("Getting ID of running container {}", containerName);
Expand Down
Loading

0 comments on commit 545dee6

Please sign in to comment.