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

Adaptive learning: Allow editors to edit the competency link weight #9564

Merged
merged 50 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9713857
First refactoring
JohannesStoehr Oct 18, 2024
73f9597
Fix most tests
JohannesStoehr Oct 18, 2024
4c367aa
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 19, 2024
a700139
Try around
JohannesStoehr Oct 19, 2024
4d68a02
Revert LoggingAspect
JohannesStoehr Oct 19, 2024
99d0c85
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 20, 2024
8c3dc7c
Fix more tests
JohannesStoehr Oct 20, 2024
b029f0f
Merge branch 'refs/heads/develop' into feature/adaptive-learning/comp…
JohannesStoehr Oct 21, 2024
8d63e74
Fix more tests
JohannesStoehr Oct 21, 2024
3145850
Fix more tests
JohannesStoehr Oct 21, 2024
ff64ccc
Fix more tests
JohannesStoehr Oct 21, 2024
fe7318a
Fix exercise creation
JohannesStoehr Oct 21, 2024
4458e47
Fix exercise update server
JohannesStoehr Oct 21, 2024
bfa4f28
Fix exercise import
JohannesStoehr Oct 21, 2024
9f070ac
Done
JohannesStoehr Oct 22, 2024
b52d014
Fix tests
JohannesStoehr Oct 22, 2024
7bead56
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 22, 2024
dcd99c3
Fix last things
JohannesStoehr Oct 22, 2024
c87a614
Remove log
JohannesStoehr Oct 22, 2024
c7dbf9d
Allow user editing
JohannesStoehr Oct 22, 2024
f285a0d
Patrik
JohannesStoehr Oct 22, 2024
583ee8a
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 22, 2024
038d66c
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 23, 2024
2d3cade
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 23, 2024
1d2d45a
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 24, 2024
43b5e39
Use variables
JohannesStoehr Oct 24, 2024
b4f1334
Use SCREAMING_SNAKE_CASE
JohannesStoehr Oct 24, 2024
40d3d87
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 24, 2024
45103b8
Merge remote-tracking branch 'origin/feature/adaptive-learning/compet…
JohannesStoehr Oct 24, 2024
30f9583
Make Flo happy
JohannesStoehr Oct 25, 2024
009c6ec
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 25, 2024
ad560fd
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 25, 2024
7c0d345
Make Flo happy transitively
JohannesStoehr Oct 25, 2024
9efb40f
Fix and combine test
JohannesStoehr Oct 25, 2024
597ea81
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 25, 2024
7534972
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 25, 2024
c0d5076
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 25, 2024
c4f30cf
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 26, 2024
7a0eace
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 26, 2024
b1f9e9d
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 27, 2024
b2cf54d
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 27, 2024
276989e
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 27, 2024
674a52d
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 28, 2024
19c6044
Increase test coverage
JohannesStoehr Oct 28, 2024
f543026
Fix constructor order
JohannesStoehr Oct 28, 2024
b83e2cf
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 28, 2024
eca4ef4
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 30, 2024
e1bb388
Fix merge conflict
JohannesStoehr Oct 30, 2024
b492936
Merge branch 'feature/adaptive-learning/competency-link-weight' into …
JohannesStoehr Oct 30, 2024
bf92aac
Merge branch 'develop' into feature/adaptive-learning/competency-link…
JohannesStoehr Oct 30, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.Optional;
import java.util.Set;

import de.tum.cit.aet.artemis.atlas.domain.competency.CourseCompetency;
import de.tum.cit.aet.artemis.atlas.domain.competency.CompetencyLearningObjectLink;
import de.tum.cit.aet.artemis.core.domain.User;

public interface LearningObject {
Expand All @@ -19,7 +19,7 @@ public interface LearningObject {

Long getId();

Set<CourseCompetency> getCompetencies();
Set<? extends CompetencyLearningObjectLink> getCompetencyLinks();

boolean isVisibleToStudents();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package de.tum.cit.aet.artemis.atlas.domain.competency;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MapsId;
import jakarta.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import com.fasterxml.jackson.annotation.JsonIgnore;

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

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "competency_exercise")
public class CompetencyExerciseLink extends CompetencyLearningObjectLink {

@EmbeddedId
@JsonIgnore
protected CompetencyExerciseId id = new CompetencyExerciseId();

@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@MapsId("exerciseId")
private Exercise exercise;

public CompetencyExerciseLink(CourseCompetency competency, Exercise exercise, double weight) {
super(competency, weight);
this.exercise = exercise;
}

public CompetencyExerciseLink() {
// Empty constructor for Spring
}

public Exercise getExercise() {
return exercise;
}

public void setExercise(Exercise exercise) {
this.exercise = exercise;
}

public CompetencyExerciseId getId() {
return id;
}

@Override
public String toString() {
return "CompetencyExerciseLink{" + "exercise=" + exercise + ", id=" + id + ", competency=" + competency + ", weight=" + weight + '}';
}

@Embeddable
public static class CompetencyExerciseId implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

private long exerciseId;

private long competencyId;

public CompetencyExerciseId() {
// Empty constructor for Spring
}

public CompetencyExerciseId(long exerciseId, long competencyId) {
this.exerciseId = exerciseId;
this.competencyId = competencyId;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CompetencyExerciseId that)) {
return false;
}
return exerciseId == that.exerciseId && competencyId == that.competencyId;
}

@Override
public int hashCode() {
return Objects.hash(exerciseId, competencyId);
}

@Override
public String toString() {
return "CompetencyExerciseId{" + "exerciseId=" + exerciseId + ", competencyId=" + competencyId + '}';
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package de.tum.cit.aet.artemis.atlas.domain.competency;

import java.io.Serializable;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.MapsId;

@MappedSuperclass
public abstract class CompetencyLearningObjectLink implements Serializable {

@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@MapsId("competencyId")
protected CourseCompetency competency;

@Column(name = "link_weight")
protected double weight;

public CompetencyLearningObjectLink(CourseCompetency competency, double weight) {
this.competency = competency;
this.weight = weight;
}

public CompetencyLearningObjectLink() {
// Empty constructor for Spring
}

public CourseCompetency getCompetency() {
return competency;
}

public void setCompetency(CourseCompetency competency) {
this.competency = competency;
}

public double getWeight() {
return weight;
}

public void setWeight(double weight) {
this.weight = weight;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package de.tum.cit.aet.artemis.atlas.domain.competency;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MapsId;
import jakarta.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import com.fasterxml.jackson.annotation.JsonIgnore;

import de.tum.cit.aet.artemis.lecture.domain.LectureUnit;

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "competency_lecture_unit")
public class CompetencyLectureUnitLink extends CompetencyLearningObjectLink {

@EmbeddedId
@JsonIgnore
protected CompetencyLectureUnitId id = new CompetencyLectureUnitId();

@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
@MapsId("lectureUnitId")
private LectureUnit lectureUnit;

public CompetencyLectureUnitLink(CourseCompetency competency, LectureUnit lectureUnit, double weight) {
super(competency, weight);
this.lectureUnit = lectureUnit;
}

public CompetencyLectureUnitLink() {
// Empty constructor for Spring
}

public LectureUnit getLectureUnit() {
return lectureUnit;
}

public void setLectureUnit(LectureUnit lectureUnit) {
this.lectureUnit = lectureUnit;
}

public CompetencyLectureUnitId getId() {
return id;
}

@Override
public String toString() {
return "CompetencyLectureUnitLink{" + "lectureUnit=" + lectureUnit + ", id=" + id + ", competency=" + competency + ", weight=" + weight + '}';
}

@Embeddable
public static class CompetencyLectureUnitId implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

private long lectureUnitId;

private long competencyId;

public CompetencyLectureUnitId() {
// Empty constructor for Spring
}

public CompetencyLectureUnitId(long lectureUnitId, long competencyId) {
this.lectureUnitId = lectureUnitId;
this.competencyId = competencyId;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CompetencyLectureUnitId that)) {
return false;
}
return lectureUnitId == that.lectureUnitId && competencyId == that.competencyId;
}

@Override
public int hashCode() {
return Objects.hash(lectureUnitId, competencyId);
}

@Override
public String toString() {
return "CompetencyLectureUnitId{" + "lectureUnitId=" + lectureUnitId + ", competencyId=" + competencyId + '}';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.exercise.domain.Exercise;
import de.tum.cit.aet.artemis.lecture.domain.ExerciseUnit;
import de.tum.cit.aet.artemis.lecture.domain.LectureUnit;

/**
* CourseCompetency is an abstract class for all competency types that are part of a course.
Expand Down Expand Up @@ -71,13 +69,13 @@ public abstract class CourseCompetency extends BaseCompetency {
@JsonIgnoreProperties({ "competencies" })
private StandardizedCompetency linkedStandardizedCompetency;

@ManyToMany(mappedBy = "competencies")
@JsonIgnoreProperties({ "competencies", "course" })
private Set<Exercise> exercises = new HashSet<>();
@OneToMany(mappedBy = "competency", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnoreProperties("competency")
private Set<CompetencyExerciseLink> exerciseLinks = new HashSet<>();

@ManyToMany(mappedBy = "competencies")
@JsonIgnoreProperties("competencies")
private Set<LectureUnit> lectureUnits = new HashSet<>();
@OneToMany(mappedBy = "competency", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnoreProperties("competency")
private Set<CompetencyLectureUnitLink> lectureUnitLinks = new HashSet<>();

@OneToMany(mappedBy = "competency", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
@JsonIgnoreProperties({ "user", "competency" })
Expand Down Expand Up @@ -161,55 +159,20 @@ public void setLinkedStandardizedCompetency(StandardizedCompetency linkedStandar
this.linkedStandardizedCompetency = linkedStandardizedCompetency;
}

public Set<Exercise> getExercises() {
return exercises;
}

public void setExercises(Set<Exercise> exercises) {
this.exercises = exercises;
public Set<CompetencyExerciseLink> getExerciseLinks() {
return exerciseLinks;
}

public void addExercise(Exercise exercise) {
this.exercises.add(exercise);
exercise.getCompetencies().add(this);
public void setExerciseLinks(Set<CompetencyExerciseLink> exerciseLinks) {
this.exerciseLinks = exerciseLinks;
}

public Set<LectureUnit> getLectureUnits() {
return lectureUnits;
public Set<CompetencyLectureUnitLink> getLectureUnitLinks() {
return lectureUnitLinks;
}

public void setLectureUnits(Set<LectureUnit> lectureUnits) {
this.lectureUnits = lectureUnits;
}

/**
* Adds the lecture unit to the competency (bidirectional)
* Note: ExerciseUnits are not accepted, should be set via the connected exercise (see {@link #addExercise(Exercise)})
*
* @param lectureUnit The lecture unit to add
*/
public void addLectureUnit(LectureUnit lectureUnit) {
if (lectureUnit instanceof ExerciseUnit) {
// The competencies of ExerciseUnits are taken from the corresponding exercise
throw new IllegalArgumentException("ExerciseUnits can not be connected to competencies");
}
this.lectureUnits.add(lectureUnit);
lectureUnit.getCompetencies().add(this);
}

/**
* Removes the lecture unit from the competency (bidirectional)
* Note: ExerciseUnits are not accepted, should be set via the connected exercise
*
* @param lectureUnit The lecture unit to remove
*/
public void removeLectureUnit(LectureUnit lectureUnit) {
if (lectureUnit instanceof ExerciseUnit) {
// The competencies of ExerciseUnits are taken from the corresponding exercise
throw new IllegalArgumentException("ExerciseUnits can not be disconnected from competencies");
}
this.lectureUnits.remove(lectureUnit);
lectureUnit.getCompetencies().remove(this);
public void setLectureUnitLinks(Set<CompetencyLectureUnitLink> lectureUnitLinks) {
this.lectureUnitLinks = lectureUnitLinks;
}

public Set<CompetencyProgress> getUserProgress() {
Expand All @@ -234,6 +197,6 @@ public void setLearningPaths(Set<LearningPath> learningPaths) {
@PrePersist
@PreUpdate
public void prePersistOrUpdate() {
this.lectureUnits.removeIf(lectureUnit -> lectureUnit instanceof ExerciseUnit);
this.lectureUnitLinks.removeIf(lectureUnit -> lectureUnit.getLectureUnit() instanceof ExerciseUnit);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.tum.cit.aet.artemis.atlas.repository;

import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Repository;

import de.tum.cit.aet.artemis.atlas.domain.competency.CompetencyExerciseLink;
import de.tum.cit.aet.artemis.core.repository.base.ArtemisJpaRepository;

@Profile(PROFILE_CORE)
@Repository
public interface CompetencyExerciseLinkRepository extends ArtemisJpaRepository<CompetencyExerciseLink, Long> {

}
Loading
Loading