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 creating and updating prerequisite competencies #8765

Merged
Show file tree
Hide file tree
Changes from 101 commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
afd2fdf
Add database migration and basic entities
rstief May 24, 2024
656eddd
Make changeset more readable, add comments and fix small MySQL bug
rstief May 24, 2024
0d29b03
Remove all occurrences of prerequisites in the server code
rstief May 24, 2024
fc7eb1e
Add Repository, Service and DTOs
rstief May 24, 2024
a69a1af
Add Prerequisite Endpoints, Change Authorization to @EnforceAtLeastRo…
rstief May 24, 2024
ab982ac
Move prerequisites to own resource, add prerequisite import endpoint
rstief May 26, 2024
3a18271
Remove unused methods from old competency import
rstief May 26, 2024
490109e
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief May 26, 2024
0fd62e2
Fix import
rstief May 26, 2024
4cac566
Add server tests
rstief May 27, 2024
e9829b2
Improve import, add test for update prerequisite
rstief May 28, 2024
a95a08e
Change competency model to be an interface
rstief May 28, 2024
1d37566
Adjust client code to support new prerequisites
rstief May 28, 2024
91e2b40
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief May 28, 2024
dce5b56
Add javadoc
rstief May 29, 2024
da250f4
Add client code
rstief May 29, 2024
1c0361c
fix changelog
rstief May 29, 2024
47e0e5e
server style, fix tests
rstief May 29, 2024
15a716d
Improve client tests
rstief May 29, 2024
2fb88c6
Fix server tests
rstief May 29, 2024
14b8516
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief May 29, 2024
cb49122
Remove todo comments
rstief May 29, 2024
ebdd8e9
Remove create/update (will be re-added in follow-up PR)
rstief May 29, 2024
5b9af2d
Revert "Remove create/update (will be re-added in follow-up PR)"
rstief May 29, 2024
8d940ae
Rename competency-import-course.component to avoid confusion with new…
rstief May 29, 2024
43f281d
Add client test or new import component
rstief May 29, 2024
4f0cfae
Remove unused tests
rstief May 30, 2024
1b12dfd
Fix recursive query
rstief May 30, 2024
5152638
Fix another server test
rstief May 30, 2024
6c0db66
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief May 30, 2024
42219b9
Add client tests
rstief May 31, 2024
27ccdfa
Fix server warnings
rstief May 31, 2024
47f45d4
Fix server warnings (part2)
rstief May 31, 2024
940798f
Fix client tests
rstief May 31, 2024
960225e
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief May 31, 2024
d1cf05f
Add tests for endpoints
rstief May 31, 2024
d42aadb
Remove unused code
rstief May 31, 2024
a1a27ce
Remove more unused code
rstief May 31, 2024
97a8bed
Add server tests
rstief May 31, 2024
a999120
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief May 31, 2024
109cafb
Revert "Remove more unused code"
rstief May 31, 2024
b253e26
Revert "Remove unused code"
rstief May 31, 2024
ea33478
Update src/main/java/de/tum/in/www1/artemis/web/rest/competency/Prere…
rstief Jun 2, 2024
36536e7
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 2, 2024
cac153a
Add JsonInclude Annotation
rstief Jun 2, 2024
f799758
Fix search empty search table translation
rstief Jun 2, 2024
8d632da
Apply suggestions from code review (german translations)
rstief Jun 2, 2024
19e438f
Revert rename competency -> course_competency, reduce size of discrim…
rstief Jun 3, 2024
a397eaf
Apply suggestions from code review
rstief Jun 3, 2024
1fc7c51
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 3, 2024
e750006
Update src/main/webapp/app/course/competencies/prerequisite.service.ts
rstief Jun 3, 2024
02f3bde
Update src/main/webapp/app/course/competencies/prerequisite.service.ts
rstief Jun 3, 2024
c9fcb1b
Fix server test
rstief Jun 4, 2024
f743a71
Disallow import of competencies that have already been imported as pr…
rstief Jun 4, 2024
5c03d8b
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 4, 2024
00a1c19
Fix tests
rstief Jun 4, 2024
dcb3381
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 4, 2024
a03649d
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 5, 2024
a2b7851
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 5, 2024
3f0b74e
Fix merge problems
rstief Jun 5, 2024
f3d9dbd
Fix merge problems
rstief Jun 5, 2024
e19d069
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 5, 2024
fd67e8e
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 7, 2024
e3f4af0
Improve client coverage
rstief Jun 7, 2024
0437d5a
Further improve client coverage
rstief Jun 7, 2024
eb06aa9
First version of create/edit
rstief Jun 5, 2024
8aae933
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 7, 2024
9239893
fix infinite loading bug
rstief Jun 7, 2024
ae95526
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 7, 2024
37f84a6
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 7, 2024
f673cfa
Add missing import
rstief Jun 7, 2024
5b0f950
Merge remote-tracking branch 'origin/chore/adaptive-learning/add-prer…
rstief Jun 7, 2024
e6ad0d6
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 7, 2024
3610a14
Code Review Suggestions
rstief Jun 8, 2024
986aaae
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 8, 2024
448dfba
Add more client tests ^^
rstief Jun 8, 2024
be0a43d
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 8, 2024
661caf0
Finish create/edit components
rstief Jun 9, 2024
bc0c1c8
Adjust competency management
rstief Jun 9, 2024
8024cf3
remove TODO
rstief Jun 9, 2024
c99c65b
Add server test
rstief Jun 9, 2024
56bcd93
Add client tests
rstief Jun 9, 2024
0ec391c
Add more client tests
rstief Jun 9, 2024
da86acb
Add more client tests
rstief Jun 9, 2024
d36f06f
Fix server tests
rstief Jun 9, 2024
3b2e7eb
Fix server test
rstief Jun 9, 2024
e16ea1e
Fix server test
rstief Jun 9, 2024
36ea9b2
Add another client test
rstief Jun 9, 2024
44357dd
Fix a translation
rstief Jun 9, 2024
9d65c34
Add navbar translation
rstief Jun 9, 2024
decf056
Update src/main/webapp/i18n/en/competency.json
rstief Jun 10, 2024
a7c9019
Fix navigation bug
rstief Jun 10, 2024
18e193a
Merge remote-tracking branch 'origin/feature/adaptive-learning/allow-…
rstief Jun 10, 2024
70ca81a
Add javadocs, extract DTO
rstief Jun 11, 2024
797fb81
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 11, 2024
a5b4a09
Update src/main/webapp/app/course/competencies/import-competencies/im…
rstief Jun 11, 2024
3a5c295
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 12, 2024
ce368bb
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 17, 2024
0be9ecf
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 17, 2024
e8f0e17
Merge branch 'develop' into chore/adaptive-learning/add-prerequisite-…
rstief Jun 22, 2024
86c0b7f
Merge branch 'chore/adaptive-learning/add-prerequisite-entities' into…
rstief Jun 22, 2024
c4bdb06
Merge branch 'develop' into feature/adaptive-learning/allow-creating-…
rstief Jun 22, 2024
5f4ea0c
Update src/test/java/de/tum/in/www1/artemis/competency/PrerequisiteUt…
rstief Jun 22, 2024
02a1970
Fix style issues
rstief Jun 22, 2024
a0c2742
Apply suggestions from code review
rstief Jun 23, 2024
d3453ae
Update src/test/javascript/spec/component/competencies/competency-for…
rstief Jun 23, 2024
53832f0
Update src/test/javascript/spec/component/competencies/competency-for…
rstief Jun 23, 2024
89a1742
Merge branch 'develop' into feature/adaptive-learning/allow-creating-…
rstief Jun 23, 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
24 changes: 7 additions & 17 deletions src/main/java/de/tum/in/www1/artemis/domain/Course.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import de.tum.in.www1.artemis.domain.competency.Competency;
import de.tum.in.www1.artemis.domain.competency.LearningPath;
import de.tum.in.www1.artemis.domain.competency.Prerequisite;
import de.tum.in.www1.artemis.domain.enumeration.CourseInformationSharingConfiguration;
import de.tum.in.www1.artemis.domain.enumeration.Language;
import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage;
Expand Down Expand Up @@ -248,11 +249,10 @@ public class Course extends DomainObject {
@JsonIgnoreProperties("course")
private Set<Organization> organizations = new HashSet<>();

@ManyToMany
@JoinTable(name = "competency_course", joinColumns = @JoinColumn(name = "course_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "competency_id", referencedColumnName = "id"))
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@JsonIgnoreProperties("consecutiveCourses")
private Set<Competency> prerequisites = new HashSet<>();
@OneToMany(mappedBy = "course", cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonIgnoreProperties("course")
@OrderBy("title")
private Set<Prerequisite> prerequisites = new HashSet<>();

@OneToOne(cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
@JoinColumn(name = "tutorial_groups_configuration_id")
Expand Down Expand Up @@ -700,24 +700,14 @@ public void setOrganizations(Set<Organization> organizations) {
this.organizations = organizations;
}

public Set<Competency> getPrerequisites() {
public Set<Prerequisite> getPrerequisites() {
return prerequisites;
}

public void setPrerequisites(Set<Competency> prerequisites) {
public void setPrerequisites(Set<Prerequisite> prerequisites) {
this.prerequisites = prerequisites;
}

public void addPrerequisite(Competency competency) {
this.prerequisites.add(competency);
competency.getConsecutiveCourses().add(this);
}

public void removePrerequisite(Competency competency) {
this.prerequisites.remove(competency);
competency.getConsecutiveCourses().remove(this);
}

@Override
public String toString() {
return "Course{" + "id=" + getId() + ", title='" + getTitle() + "'" + ", description='" + getDescription() + "'" + ", shortName='" + getShortName() + "'"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

import de.tum.in.www1.artemis.domain.DomainObject;

/**
* BaseCompetency is an abstract class that contains basic information shared between all competency types.
* It is extended by {@link CourseCompetency} and {@link StandardizedCompetency}
*/
@MappedSuperclass
public abstract class BaseCompetency extends DomainObject {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,31 @@
import java.util.Set;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table;

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

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import de.tum.in.www1.artemis.domain.Course;
import de.tum.in.www1.artemis.domain.Exercise;
import de.tum.in.www1.artemis.domain.lecture.ExerciseUnit;
import de.tum.in.www1.artemis.domain.lecture.LectureUnit;

@Entity
@Table(name = "competency")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Competency extends BaseCompetency {

@JsonIgnore
public static final int DEFAULT_MASTERY_THRESHOLD = 50;

@Column(name = "soft_due_date")
private ZonedDateTime softDueDate;

@Column(name = "mastery_threshold")
private Integer masteryThreshold;

@Column(name = "optional")
private boolean optional;
@DiscriminatorValue("C")
public class Competency extends CourseCompetency {

// TODO: move properties (linkedStandardizedCompetency, exercises, lectureUnits, userProgress, learningPaths) to CourseCompetency when refactoring
@ManyToOne
@JoinColumn(name = "course_id")
@JsonIgnoreProperties({ "competencies", "prerequisites" })
private Course course;
@JoinColumn(name = "linked_standardized_competency_id")
@JsonIgnoreProperties({ "competencies" })
private StandardizedCompetency linkedStandardizedCompetency;

@ManyToMany(mappedBy = "competencies")
@JsonIgnoreProperties({ "competencies", "course" })
Expand All @@ -58,15 +39,6 @@ public class Competency extends BaseCompetency {
@JsonIgnoreProperties("competencies")
private Set<LectureUnit> lectureUnits = new HashSet<>();

/**
* A set of courses for which this competency is a prerequisite for.
*/
@ManyToMany
@JoinTable(name = "competency_course", joinColumns = @JoinColumn(name = "competency_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "course_id", referencedColumnName = "id"))
@JsonIgnoreProperties({ "competencies", "prerequisites" })
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Course> consecutiveCourses = new HashSet<>();

@OneToMany(mappedBy = "competency", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, orphanRemoval = true)
@JsonIgnoreProperties({ "user", "competency" })
private Set<CompetencyProgress> userProgress = new HashSet<>();
Expand All @@ -75,54 +47,22 @@ public class Competency extends BaseCompetency {
@JsonIgnoreProperties({ "competencies", "course" })
private Set<LearningPath> learningPaths = new HashSet<>();

@ManyToOne
@JoinColumn(name = "linked_standardized_competency_id")
@JsonIgnoreProperties({ "competencies" })
private StandardizedCompetency linkedStandardizedCompetency;

@OneToMany(mappedBy = "competency", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private Set<CompetencyJol> competencyJols = new HashSet<>();

public Competency() {
}

public Competency(String title, String description, ZonedDateTime softDueDate, Integer masteryThreshold, CompetencyTaxonomy taxonomy, boolean optional) {
super(title, description, taxonomy);
this.softDueDate = softDueDate;
this.masteryThreshold = masteryThreshold;
this.optional = optional;
}

public ZonedDateTime getSoftDueDate() {
return softDueDate;
}

public void setSoftDueDate(ZonedDateTime dueDate) {
this.softDueDate = dueDate;
}

public int getMasteryThreshold() {
return masteryThreshold == null ? 100 : this.masteryThreshold;
}

public void setMasteryThreshold(Integer masteryThreshold) {
this.masteryThreshold = masteryThreshold;
super(title, description, softDueDate, masteryThreshold, taxonomy, optional);
}

public boolean isOptional() {
return optional;
}

public void setOptional(boolean optional) {
this.optional = optional;
}

public Course getCourse() {
return course;
public StandardizedCompetency getLinkedStandardizedCompetency() {
return linkedStandardizedCompetency;
}

public void setCourse(Course course) {
this.course = course;
public void setLinkedStandardizedCompetency(StandardizedCompetency linkedStandardizedCompetency) {
this.linkedStandardizedCompetency = linkedStandardizedCompetency;
}

public Set<Exercise> getExercises() {
Expand Down Expand Up @@ -163,7 +103,7 @@ public void addLectureUnit(LectureUnit lectureUnit) {

/**
* Removes the lecture unit from the competency (bidirectional)
* Note: ExerciseUnits are not accepted, should be set via the connected exercise (see {@link #removeExercise(Exercise)})
* Note: ExerciseUnits are not accepted, should be set via the connected exercise
*
* @param lectureUnit The lecture unit to remove
*/
Expand All @@ -176,10 +116,6 @@ public void removeLectureUnit(LectureUnit lectureUnit) {
lectureUnit.getCompetencies().remove(this);
}

public Set<Course> getConsecutiveCourses() {
return consecutiveCourses;
}

public Set<CompetencyProgress> getUserProgress() {
return userProgress;
}
Expand All @@ -196,14 +132,6 @@ public void setLearningPaths(Set<LearningPath> learningPaths) {
this.learningPaths = learningPaths;
}

public StandardizedCompetency getLinkedStandardizedCompetency() {
return linkedStandardizedCompetency;
}

public void setLinkedStandardizedCompetency(StandardizedCompetency linkedStandardizedCompetency) {
this.linkedStandardizedCompetency = linkedStandardizedCompetency;
}

/**
* Ensure that exercise units are connected to competencies through the corresponding exercise
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package de.tum.in.www1.artemis.domain.competency;

import java.time.ZonedDateTime;

import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorType;
import jakarta.persistence.Entity;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;

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

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import de.tum.in.www1.artemis.domain.Course;

/**
* CourseCompetency is an abstract class for all competency types that are part of a course.
* It is extended by {@link Competency} and {@link Prerequisite}
*/
@Entity
@Table(name = "competency")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public abstract class CourseCompetency extends BaseCompetency {

@JsonIgnore
public static final int DEFAULT_MASTERY_THRESHOLD = 100;

@JsonIgnore
public static final int MAX_TITLE_LENGTH = 255;

@Column(name = "soft_due_date")
private ZonedDateTime softDueDate;

@Column(name = "mastery_threshold")
private int masteryThreshold;

@Column(name = "optional")
private boolean optional;

@ManyToOne
@JoinColumn(name = "course_id")
@JsonIgnoreProperties({ "competencies", "prerequisites" })
private Course course;

@ManyToOne
@JoinColumn(name = "linked_course_competency_id")
@JsonIgnoreProperties({ "competencies" })
private CourseCompetency linkedCourseCompetency;

public CourseCompetency() {
}

public CourseCompetency(String title, String description, ZonedDateTime softDueDate, Integer masteryThreshold, CompetencyTaxonomy taxonomy, boolean optional) {
super(title, description, taxonomy);
this.softDueDate = softDueDate;
this.masteryThreshold = masteryThreshold;
this.optional = optional;
}

public ZonedDateTime getSoftDueDate() {
return softDueDate;
}

public void setSoftDueDate(ZonedDateTime softDueDate) {
this.softDueDate = softDueDate;
}

public int getMasteryThreshold() {
return masteryThreshold;
}

public void setMasteryThreshold(int masteryThreshold) {
this.masteryThreshold = masteryThreshold;
}

public boolean isOptional() {
return optional;
}

public void setOptional(boolean optional) {
this.optional = optional;
}

@ManyToOne
public Course getCourse() {
return course;
}

public void setCourse(Course course) {
this.course = course;
}

public CourseCompetency getLinkedCourseCompetency() {
return linkedCourseCompetency;
}

public void setLinkedCourseCompetency(CourseCompetency linkedCourseCompetency) {
this.linkedCourseCompetency = linkedCourseCompetency;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package de.tum.in.www1.artemis.domain.competency;

import java.time.ZonedDateTime;

import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Entity;

/**
* A competency that students are expected to have mastered before participating in a course.
*/
@Entity
@DiscriminatorValue("P")
public class Prerequisite extends CourseCompetency {

public Prerequisite(String title, String description, ZonedDateTime softDueDate, Integer masteryThreshold, CompetencyTaxonomy taxonomy, boolean optional) {
super(title, description, softDueDate, masteryThreshold, taxonomy, optional);
}

public Prerequisite() {
}
}
Loading
Loading