Skip to content

Commit

Permalink
Merge branch 'develop' into development/local-vc-ci-aux-repos
Browse files Browse the repository at this point in the history
  • Loading branch information
laurenzfb authored Sep 15, 2023
2 parents 4a37070 + 233dbd1 commit 1aa1e31
Show file tree
Hide file tree
Showing 42 changed files with 164 additions and 76 deletions.
10 changes: 10 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 @@ -131,6 +131,9 @@ public class Course extends DomainObject {
@JsonView(QuizView.Before.class)
private CourseInformationSharingConfiguration courseInformationSharingConfiguration = CourseInformationSharingConfiguration.COMMUNICATION_AND_MESSAGING; // default value

@Column(name = "info_sharing_messaging_code_of_conduct")
private String courseInformationSharingMessagingCodeOfConduct;

@Column(name = "max_complaints", nullable = false)
@JsonView(QuizView.Before.class)
private Integer maxComplaints = 3; // default value
Expand Down Expand Up @@ -1005,4 +1008,11 @@ public void setCourseInformationSharingConfiguration(CourseInformationSharingCon
this.courseInformationSharingConfiguration = courseInformationSharingConfiguration;
}

public String getCourseInformationSharingMessagingCodeOfConduct() {
return this.courseInformationSharingMessagingCodeOfConduct;
}

public void setCourseInformationSharingMessagingCodeOfConduct(String courseInformationSharingMessagingCodeOfConduct) {
this.courseInformationSharingMessagingCodeOfConduct = courseInformationSharingMessagingCodeOfConduct;
}
}
2 changes: 1 addition & 1 deletion src/main/java/de/tum/in/www1/artemis/domain/Exercise.java
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ public Submission findLatestSubmissionWithRatedResultWithCompletionDate(Particip
boolean isAssessmentOver = ignoreAssessmentDueDate || ExerciseDateService.isAfterAssessmentDueDate(this);
boolean isProgrammingExercise = participation.getExercise() instanceof ProgrammingExercise;
// Check that submission was submitted in time (rated). For non programming exercises we check if the assessment due date has passed (if set)
boolean ratedOrPractice = Boolean.TRUE.equals(result.isRated()) || participation.isTestRun();
boolean ratedOrPractice = Boolean.TRUE.equals(result.isRated()) || participation.isPracticeMode();
boolean noProgrammingAndAssessmentOver = !isProgrammingExercise && isAssessmentOver;
// For programming exercises we check that the assessment due date has passed (if set) for manual results otherwise we always show the automatic result
boolean programmingAfterAssessmentOrAutomatic = isProgrammingExercise && ((result.isManual() && isAssessmentOver) || result.isAutomatic());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,8 +673,8 @@ public Set<Result> findResultsFilteredForStudents(Participation participation) {
public List<StudentParticipation> findRelevantParticipation(List<StudentParticipation> participations) {
List<StudentParticipation> participationOfExercise = participations.stream()
.filter(participation -> participation.getExercise() != null && participation.getExercise().equals(this)).toList();
List<StudentParticipation> gradedParticipations = participationOfExercise.stream().filter(participation -> !participation.isTestRun()).toList();
List<StudentParticipation> practiceParticipations = participationOfExercise.stream().filter(Participation::isTestRun).toList();
List<StudentParticipation> gradedParticipations = participationOfExercise.stream().filter(participation -> !participation.isPracticeMode()).toList();
List<StudentParticipation> practiceParticipations = participationOfExercise.stream().filter(Participation::isPracticeMode).toList();

if (gradedParticipations.size() > 1) {
gradedParticipations = super.findRelevantParticipation(gradedParticipations);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/de/tum/in/www1/artemis/domain/Result.java
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public void setRatedIfNotAfterDueDate() {
if (submission.getType() == SubmissionType.INSTRUCTOR || submission.getType() == SubmissionType.TEST) {
this.rated = true;
}
else if (submission.getType() == SubmissionType.ILLEGAL || participation.isTestRun()) {
else if (submission.getType() == SubmissionType.ILLEGAL || participation.isPracticeMode()) {
this.rated = false;
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,25 @@ public void setTestRun(boolean testRun) {
this.testRun = testRun;
}

/**
* Same as {@link #isTestRun} since {@link Participation#testRun} is used to determine if a participation in a course exercise is used for practice purposes
*
* @return true if the participation is only used for practicing after the due date
*/
@JsonIgnore
public boolean isPracticeMode() {
return Boolean.TRUE.equals(testRun);
}

/**
* Same as {@link #setTestRun} since {@link Participation#testRun} is used to determine if a participation in a course exercise is used for practice purposes
*
* @param practiceMode sets the testRun flag to this value
*/
public void setPracticeMode(boolean practiceMode) {
this.testRun = practiceMode;
}

public Set<Result> getResults() {
return results;
}
Expand Down Expand Up @@ -282,7 +301,7 @@ private <T extends Submission> Optional<T> findLatestSubmission(boolean includeI
* @return the same string with "practice-" added to the front if this is a test run participation
*/
public String addPracticePrefixIfTestRun(String string) {
return (isTestRun() ? "practice-" : "") + string;
return (isPracticeMode() ? "practice-" : "") + string;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ public CourseForDashboardDTO getScoresAndParticipationResults(Course course, Gra
// TODO: Look into refactoring the fetchParticipationsWithSubmissionsAndResultsForCourses method in the CourseService to always initialize the participations (to an
// empty list if there aren't any). This way you don't need this very unintuitive check for the initialization state.
if (Hibernate.isInitialized(exercise.getStudentParticipations())) {
exercise.getStudentParticipations().stream().filter(participation -> !participation.isTestRun()).forEach(participation -> {
exercise.getStudentParticipations().stream().filter(participation -> !participation.isPracticeMode()).forEach(participation -> {
participation.setExercise(exercise);
gradedStudentParticipations.add(participation);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public StudentParticipation startExercise(Exercise exercise, Participant partici
public StudentParticipation startExerciseWithInitializationDate(Exercise exercise, Participant participant, boolean createInitialSubmission, ZonedDateTime initializationDate) {
// common for all exercises
Optional<StudentParticipation> optionalStudentParticipation = findOneByExerciseAndParticipantAnyState(exercise, participant);
if (optionalStudentParticipation.isPresent() && optionalStudentParticipation.get().isTestRun() && exercise.isCourseExercise()) {
if (optionalStudentParticipation.isPresent() && optionalStudentParticipation.get().isPracticeMode() && exercise.isCourseExercise()) {
// In case there is already a practice participation, set it to inactive
optionalStudentParticipation.get().setInitializationState(InitializationState.INACTIVE);
studentParticipationRepository.saveAndFlush(optionalStudentParticipation.get());
Expand Down Expand Up @@ -285,7 +285,7 @@ public StudentParticipation startPracticeMode(Exercise exercise, Participant par
participation.setInitializationState(InitializationState.UNINITIALIZED);
participation.setExercise(exercise);
participation.setParticipant(participant);
participation.setTestRun(true);
participation.setPracticeMode(true);
participation = studentParticipationRepository.saveAndFlush(participation);
}
else {
Expand Down Expand Up @@ -394,7 +394,7 @@ public ProgrammingExerciseStudentParticipation resumeProgrammingExercise(Program

// If a graded participation gets reset after the due date set the state back to finished. Otherwise, the participation is initialized
var dueDate = ExerciseDateService.getDueDate(participation);
if (!participation.isTestRun() && dueDate.isPresent() && ZonedDateTime.now().isAfter(dueDate.get())) {
if (!participation.isPracticeMode() && dueDate.isPresent() && ZonedDateTime.now().isAfter(dueDate.get())) {
participation.setInitializationState(InitializationState.FINISHED);
}
else {
Expand Down Expand Up @@ -646,7 +646,7 @@ public void cleanupBuildPlan(ProgrammingExerciseStudentParticipation participati

// If a graded participation gets cleaned up after the due date set the state back to finished. Otherwise, the participation is initialized
var dueDate = ExerciseDateService.getDueDate(participation);
if (!participation.isTestRun() && dueDate.isPresent() && ZonedDateTime.now().isAfter(dueDate.get())) {
if (!participation.isPracticeMode() && dueDate.isPresent() && ZonedDateTime.now().isAfter(dueDate.get())) {
participation.setInitializationState(InitializationState.FINISHED);
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ private Language getJPlagProgrammingLanguage(ProgrammingExercise programmingExer
public List<ProgrammingExerciseParticipation> filterStudentParticipationsForComparison(ProgrammingExercise programmingExercise, int minimumScore) {
var studentParticipations = studentParticipationRepository.findAllForPlagiarism(programmingExercise.getId());

return studentParticipations.parallelStream().filter(participation -> !participation.isTestRun())
return studentParticipations.parallelStream().filter(participation -> !participation.isPracticeMode())
.filter(participation -> participation instanceof ProgrammingExerciseParticipation).map(participation -> (ProgrammingExerciseParticipation) participation)
.filter(participation -> participation.getVcsRepositoryUrl() != null).filter(participation -> {
Submission submission = participation.findLatestSubmission().orElse(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,7 @@ private Path createZipForRepositoryWithParticipation(final ProgrammingExercise p
return null;
}

if (repositoryExportOptions.isExcludePracticeSubmissions() && participation.isTestRun()) {
if (repositoryExportOptions.isExcludePracticeSubmissions() && participation.isPracticeMode()) {
log.debug("Ignoring practice participation {}", participation);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,11 @@ private Result processNewProgrammingExerciseResult(final ProgrammingExercisePart
// test run repository).
// Student test exam participations will still be locked by this.
SubmissionPolicy submissionPolicy = programmingExerciseRepository.findWithSubmissionPolicyById(programmingExercise.getId()).orElseThrow().getSubmissionPolicy();
if (submissionPolicy instanceof LockRepositoryPolicy policy && !((ProgrammingExerciseStudentParticipation) participation).isTestRun()) {
if (submissionPolicy instanceof LockRepositoryPolicy policy && !((ProgrammingExerciseStudentParticipation) participation).isPracticeMode()) {
submissionPolicyService.handleLockRepositoryPolicy(processedResult, (Participation) participation, policy);
}

if (programmingSubmission.getLatestResult() != null && programmingSubmission.getLatestResult().isManual() && !((Participation) participation).isTestRun()) {
if (programmingSubmission.getLatestResult() != null && programmingSubmission.getLatestResult().isManual() && !((Participation) participation).isPracticeMode()) {
// Note: in this case, we do not want to save the processedResult, but we only want to update the latest semi-automatic one
Result updatedLatestSemiAutomaticResult = updateLatestSemiAutomaticResultWithNewAutomaticFeedback(programmingSubmission.getLatestResult().getId(), processedResult);
// Adding back dropped submission
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ private boolean isAllowedToSubmit(ProgrammingExerciseStudentParticipation partic

private boolean isAllowedToSubmitForCourseExercise(ProgrammingExerciseStudentParticipation participation, ProgrammingSubmission programmingSubmission) {
var dueDate = ExerciseDateService.getDueDate(participation);
if (dueDate.isEmpty() || participation.isTestRun()) {
// Without a due date or in the practice mode, the student can always submit
if (dueDate.isEmpty() || participation.isPracticeMode()) {
return true;
}
return dueDate.get().plusSeconds(PROGRAMMING_GRACE_PERIOD_SECONDS).isAfter(programmingSubmission.getSubmissionDate());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public ResponseEntity<ProgrammingExerciseStudentParticipation> resumeParticipati

// There is a second participation of that student in the exericse that is inactive/finished now
Optional<StudentParticipation> optionalOtherStudentParticipation = participationService.findOneByExerciseAndParticipantAnyStateAndTestRun(programmingExercise, user,
!participation.isTestRun());
!participation.isPracticeMode());
if (optionalOtherStudentParticipation.isPresent()) {
StudentParticipation otherParticipation = optionalOtherStudentParticipation.get();
if (participation.getInitializationState() == InitializationState.INACTIVE) {
Expand Down Expand Up @@ -371,7 +371,7 @@ public ResponseEntity<ProgrammingExerciseStudentParticipation> requestFeedback(@
private boolean isAllowedToParticipateInProgrammingExercise(ProgrammingExercise programmingExercise, @Nullable StudentParticipation participation) {
if (participation != null) {
// only regular participation before the due date; only practice run afterwards
return participation.isTestRun() == exerciseDateService.isAfterDueDate(participation);
return participation.isPracticeMode() == exerciseDateService.isAfterDueDate(participation);
}
else {
return programmingExercise.getDueDate() == null || now().isBefore(programmingExercise.getDueDate());
Expand Down Expand Up @@ -424,7 +424,7 @@ public ResponseEntity<Participation> updateParticipation(@PathVariable long exer
Optional<GradingScale> gradingScale = gradingScaleService.findGradingScaleByCourseId(participation.getExercise().getCourseViaExerciseGroupOrCourseMember().getId());

// Presentation Score is only valid for non practice participations
if (participation.isTestRun()) {
if (participation.isPracticeMode()) {
throw new BadRequestAlertException("Presentation score is not allowed for practice participations", ENTITY_NAME, "presentationScoreInvalid");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<changeSet author="zbil" id="20230907225501">
<addColumn tableName="course">
<column name="info_sharing_messaging_code_of_conduct" type="longtext"/>
</addColumn>
</changeSet>
</databaseChangeLog>
1 change: 1 addition & 0 deletions src/main/resources/config/liquibase/master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
<include file="classpath:config/liquibase/changelog/20230622000000_changelog.xml" relativeToChangelogFile="false"/>
<include file="classpath:config/liquibase/changelog/20230713113211_changelog.xml" relativeToChangelogFile="false"/>
<include file="classpath:config/liquibase/changelog/20230907114600_changelog.xml" relativeToChangelogFile="false"/>
<include file="classpath:config/liquibase/changelog/20230907225501_changelog.xml" relativeToChangelogFile="false"/>
<!-- NOTE: please use the format "YYYYMMDDhhmmss_changelog.xml", i.e. year month day hour minutes seconds and not something else! -->
<!-- we should also stay in a chronological order! -->
<!-- you can use the command 'date '+%Y%m%d%H%M%S'' to get the current date and time in the correct format -->
Expand Down
12 changes: 12 additions & 0 deletions src/main/webapp/app/course/manage/course-update.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,18 @@ <h5>
ngbTooltip="{{ 'artemisApp.course.courseCommunicationSetting.messagingEnabled.tooltip' | artemisTranslate }}"
></fa-icon>
</div>
<div class="form-group" *ngIf="messagingEnabled">
<label class="form-control-label" jhiTranslate="artemisApp.course.courseCommunicationSetting.messagingEnabled.codeOfConduct.label"
>Messaging Code of Conduct
</label>
<jhi-help-icon text="artemisApp.course.courseCommunicationSetting.messagingEnabled.codeOfConduct.tooltip"></jhi-help-icon>
<jhi-markdown-editor
class="markdown-editor"
[(markdown)]="course.courseInformationSharingMessagingCodeOfConduct"
(markdownChange)="updateCourseInformationSharingMessagingCodeOfConduct($event)"
>
</jhi-markdown-editor>
</div>
</div>
<div class="form-group" [jhiFeatureToggleHide]="FeatureToggle.LearningPaths">
<div class="form-check">
Expand Down
9 changes: 9 additions & 0 deletions src/main/webapp/app/course/manage/course-update.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export class CourseUpdateComponent implements OnInit {
editorGroupName: new FormControl(this.course.editorGroupName),
instructorGroupName: new FormControl(this.course.instructorGroupName),
description: new FormControl(this.course.description),
courseInformationSharingMessagingCodeOfConduct: new FormControl(this.course.courseInformationSharingMessagingCodeOfConduct),
organizations: new FormControl(this.courseOrganizations),
startDate: new FormControl(this.course.startDate),
endDate: new FormControl(this.course.endDate),
Expand Down Expand Up @@ -520,6 +521,14 @@ export class CourseUpdateComponent implements OnInit {
this.courseForm.controls['registrationConfirmationMessage'].setValue(message);
}

/**
* Updates courseInformationSharingMessagingCodeOfConduct on markdown change
* @param message new courseInformationSharingMessagingCodeOfConduct
*/
updateCourseInformationSharingMessagingCodeOfConduct(message: string) {
this.courseForm.controls['courseInformationSharingMessagingCodeOfConduct'].setValue(message);
}

/**
* Auxiliary method checking if online course is currently true
*/
Expand Down
1 change: 1 addition & 0 deletions src/main/webapp/app/entities/course.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export class Course implements BaseEntity {
public tutorialGroups?: TutorialGroup[];
public onlineCourseConfiguration?: OnlineCourseConfiguration;
public courseInformationSharingConfiguration?: CourseInformationSharingConfiguration;
public courseInformationSharingMessagingCodeOfConduct?: string;

// helper attributes
public isAtLeastTutor?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,22 @@ export class StudentParticipation extends Participation {
super(type ?? ParticipationType.STUDENT);
}
}

/**
* Checks if the participation is used for practicing in a course exercise. This is the case if testRun is set to true
* @param studentParticipation the participation to check
*/
export function isPracticeMode(studentParticipation: StudentParticipation | undefined): boolean | undefined {
return studentParticipation?.testRun;
}

/**
* Stores whether the participation is used for practicing in a course exercise.
* @param studentParticipation the participation that should store if it is used for practicing
* @param practiceMode true, if it is used for practicing
*/
export function setPracticeMode(studentParticipation: StudentParticipation | undefined, practiceMode: boolean) {
if (studentParticipation) {
studentParticipation.testRun = practiceMode;
}
}
Loading

0 comments on commit 1aa1e31

Please sign in to comment.