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

chore: automatic data #449

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
293 changes: 293 additions & 0 deletions server/src/test/java/de/uftos/utils/DataGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
package de.uftos.utils;

import de.uftos.dto.requestdtos.LessonsCountRequestDto;
import io.restassured.http.ContentType;
import io.restassured.path.json.JsonPath;
import java.util.Map.Entry;
import org.json.JSONException;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer;

Check warning on line 12 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L12 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Wrong lexicographical order for 'org.junit.jupiter.api.MethodOrderer' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:12:1: warning: Wrong lexicographical order for 'org.junit.jupiter.api.MethodOrderer' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)
import java.util.*;

Check warning on line 13 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L13 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Wrong lexicographical order for 'java.util.*' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:13:1: warning: Wrong lexicographical order for 'java.util.*' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)

Check warning on line 13 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L13 <com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck>

Using the '.*' form of import should be avoided - java.util.*.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:13:17: warning: Using the '.*' form of import should be avoided - java.util.*. (com.puppycrawl.tools.checkstyle.checks.imports.AvoidStarImportCheck)
import java.util.stream.Collectors;

Check warning on line 14 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L14 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Wrong lexicographical order for 'java.util.stream.Collectors' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:14:1: warning: Wrong lexicographical order for 'java.util.stream.Collectors' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)
import java.util.stream.IntStream;

Check warning on line 15 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L15 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Wrong lexicographical order for 'java.util.stream.IntStream' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:15:1: warning: Wrong lexicographical order for 'java.util.stream.IntStream' import. Should be before 'org.junit.jupiter.api.TestMethodOrder'. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)

import static io.restassured.RestAssured.given;

Check warning on line 17 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L17 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Import statement for 'io.restassured.RestAssured.given' is in the wrong order. Should be in the 'STATIC' group, expecting not assigned imports on this line.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:17:1: warning: Import statement for 'io.restassured.RestAssured.given' is in the wrong order. Should be in the 'STATIC' group, expecting not assigned imports on this line. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)
import static org.hamcrest.Matchers.equalTo;

Check warning on line 18 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L18 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Import statement for 'org.hamcrest.Matchers.equalTo' is in the wrong order. Should be in the 'STATIC' group, expecting not assigned imports on this line.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:18:1: warning: Import statement for 'org.hamcrest.Matchers.equalTo' is in the wrong order. Should be in the 'STATIC' group, expecting not assigned imports on this line. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)
import static org.hamcrest.Matchers.notNullValue;

Check warning on line 19 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L19 <com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck>

Import statement for 'org.hamcrest.Matchers.notNullValue' is in the wrong order. Should be in the 'STATIC' group, expecting not assigned imports on this line.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:19:1: warning: Import statement for 'org.hamcrest.Matchers.notNullValue' is in the wrong order. Should be in the 'STATIC' group, expecting not assigned imports on this line. (com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck)

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)

Check warning on line 21 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L21 <com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocTypeCheck>

Missing a Javadoc comment.
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:21:1: warning: Missing a Javadoc comment. (com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocTypeCheck)
@Disabled("This class is only used to generate data on demand.")
public class DataGenerator {

private static final List<String> firstNames = List.of("John", "Jane", "Michael", "Sarah", "David", "Emily", "Robert", "Laura", "Daniel", "Sophia");

Check warning on line 25 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L25 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>

Line is longer than 120 characters (found 150).
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:25:0: warning: Line is longer than 120 characters (found 150). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)
private static final List<String> lastNames = List.of("Smith", "Johnson", "Brown", "Williams", "Jones", "Garcia", "Miller", "Davis", "Martinez", "Lopez");

Check warning on line 26 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L26 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>

Line is longer than 120 characters (found 156).
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:26:0: warning: Line is longer than 120 characters (found 156). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)
private static final List<String> subjects = List.of("Math", "English", "History", "Science", "Art", "Physical Education");

Check warning on line 27 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L27 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>

Line is longer than 120 characters (found 125).
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:27:0: warning: Line is longer than 120 characters (found 125). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)
private static final List<String> colors = List.of("#FF5733", "#33FF57", "#3357FF", "#F333FF", "#FF3333");

private static List<String> tags = new ArrayList<>();
private static List<String> students = new ArrayList<>();
private static List<String> teachers = new ArrayList<>();
private static List<String> rooms = new ArrayList<>();
private static List<String> studentGroups = new ArrayList<>();
private static List<String> grades = new ArrayList<>();
private static List<String> subjectIds = new ArrayList<>();
private static final Map<String, String> gradeMap = new HashMap<>();
private static final Map<String, String> gradeCurriculumMap = new HashMap<>();

private static final Random random = new Random();

// Helper methods to get random names
private static String getRandomFirstName() {
return firstNames.get(random.nextInt(firstNames.size()));
}

private static String getRandomLastName() {
return lastNames.get(random.nextInt(lastNames.size()));
}

// Helper method to get random tag
private static List<String> getRandomTag() {
if (tags.isEmpty() || random.nextFloat() > 0.2) {
return Collections.emptyList();
}
return List.of(tags.get(random.nextInt(tags.size())));
}

@Test
@Order(1)
public void createTags() throws JSONException {
List<String> tagNames = List.of("blind", "deaf", "wheelchair");

for (String tagName : tagNames) {
String tagId = given().contentType(ContentType.JSON)
.body(JsonGenerator.generateTagJson(tagName))
.when()
.post("/tags")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("name", equalTo(tagName))
.log().ifValidationFails()
.extract()
.body().jsonPath().getString("id");
tags.add(tagId);
}
}

@Test
@Order(2)
public void createSubjects() throws JSONException {
for (String subjectName : subjects) {
String color = colors.get(random.nextInt(colors.size()));
String subjectId = given().contentType(ContentType.JSON)
.body(JsonGenerator.generateSubjectJson(subjectName, color))
.when()
.post("/subjects")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("name", equalTo(subjectName))
.log().ifValidationFails()
.extract()
.body().jsonPath().getString("id");
subjectIds.add(subjectId);
}
}

@Test
@Order(3)
public void createGrades() throws JSONException {
for (int i = 5; i <= 10; i++) {
String gradeName = i + "th Grade";

// Create grade and extract curriculumId
String response = given().contentType(ContentType.JSON)
.body(JsonGenerator.generateGradeJson(gradeName, null, new ArrayList<>(), new ArrayList<>()))
.when()
.post("/grades")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("name", equalTo(gradeName))
.log().ifValidationFails()
.extract()
.body().asString();

String gradeId = JsonPath.from(response).getString("id");
String curriculumId = JsonPath.from(response).getString("curriculumId");

// Save gradeId and curriculumId in the map
gradeCurriculumMap.put(gradeId, curriculumId);
gradeMap.put(gradeId, gradeName);
grades.add(gradeId);
}
}

@Test
@Order(4)
public void createStudents() throws JSONException {
for (int i = 1; i <= 50; i++) {
String firstName = getRandomFirstName();
String lastName = getRandomLastName();
List<String> studentTags = getRandomTag();

String studentId = given().contentType(ContentType.JSON)
.body(
JsonGenerator.generateStudentJson(firstName, lastName, new ArrayList<>(), studentTags))
.when()
.post("/students")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("firstName", equalTo(firstName))
.body("lastName", equalTo(lastName))
.log().ifValidationFails()
.extract()
.body().jsonPath().getString("id");
students.add(studentId);
}
}

@Test
@Order(5)
public void createStudentGroups() throws JSONException {
for (int i = 1; i <= 10; i++) {
String assignedGradeId = grades.get(random.nextInt(grades.size()));
String assignedGradeName = gradeMap.get(assignedGradeId); // Get the gradeName from the map

// Assign 1 or 2 unique subjects
Set<String> assignedSubjects = new HashSet<>();
while (assignedSubjects.size() < random.nextInt(2) + 1) {
assignedSubjects.add(subjectIds.get(random.nextInt(subjectIds.size())));
}

String groupName = assignedSubjects.stream()
.map(subjectId -> subjects.get(subjectIds.indexOf(subjectId)))
.collect(Collectors.joining(", ")) + " for " + assignedGradeName; // Use gradeName in group name

List<String> groupTags = getRandomTag();

// First, create the group without students
String groupId = given().contentType(ContentType.JSON)
.body(JsonGenerator.generateStudentGroupJson(groupName, new ArrayList<>(), List.of(assignedGradeId), groupTags, new ArrayList<>(assignedSubjects)))

Check warning on line 175 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L175 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>

Line is longer than 120 characters (found 157).
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:175:0: warning: Line is longer than 120 characters (found 157). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)
.when()
.post("/student-groups")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("name", equalTo(groupName))
.log().ifValidationFails()
.extract()
.body().jsonPath().getString("id");

studentGroups.add(groupId);

// Then, assign students to the group
List<String> groupStudents = IntStream.range(0, 5)
.mapToObj(index -> students.get(random.nextInt(students.size())))
.collect(Collectors.toList());

given().contentType(ContentType.JSON)
.body(groupStudents)
.when()
.post("/student-groups/" + groupId + "/students")
.then()
.statusCode(200)
.body("id", equalTo(groupId))
.log().ifValidationFails();
}
}

@Test
@Order(6)
public void createTeachers() throws JSONException {
for (int i = 1; i <= 20; i++) {
String firstName = getRandomFirstName();
String lastName = getRandomLastName();
String acronym = firstName.charAt(0) + "" + lastName.charAt(0);
List<String> teacherTags = getRandomTag();

// Assign 2 or 3 random subjects to each teacher
Set<String> assignedSubjects = new HashSet<>();
while (assignedSubjects.size() < random.nextInt(2) + 2) {
assignedSubjects.add(subjectIds.get(random.nextInt(subjectIds.size())));
}

String teacherId = given().contentType(ContentType.JSON)
.body(JsonGenerator.generateTeacherJson(firstName, lastName, acronym, new ArrayList<>(assignedSubjects), teacherTags))

Check warning on line 220 in server/src/test/java/de/uftos/utils/DataGenerator.java

View workflow job for this annotation

GitHub Actions / checkstyle

[checkstyle] server/src/test/java/de/uftos/utils/DataGenerator.java#L220 <com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck>

Line is longer than 120 characters (found 128).
Raw output
/github/workspace/./server/src/test/java/de/uftos/utils/DataGenerator.java:220:0: warning: Line is longer than 120 characters (found 128). (com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck)
.when()
.post("/teachers")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("firstName", equalTo(firstName))
.body("lastName", equalTo(lastName))
.log().ifValidationFails()
.extract()
.body().jsonPath().getString("id");

teachers.add(teacherId);
}
}

@Test
@Order(7)
public void createRooms() throws JSONException {
for (int i = 1; i <= 10; i++) {
String roomName = "Room " + i;
String buildingName = "Building A";
int capacity = 30 + random.nextInt(20);
List<String> roomTags = getRandomTag();

String roomId = given().contentType(ContentType.JSON)
.body(JsonGenerator.generateRoomJson(roomName, buildingName, capacity, roomTags))
.when()
.post("/rooms")
.then()
.statusCode(200)
.body("id", notNullValue())
.body("name", equalTo(roomName))
.log().ifValidationFails()
.extract()
.body().jsonPath().getString("id");
rooms.add(roomId);
}
}

/*
This doesn't currently work, idk why.
{
"timestamp": "2024-09-05T10:54:08.090+00:00",
"status": 404,
"error": "Not Found",
"message": "No static resource curriculum.",
"path": "/curriculum/"
}

@Test
@Order(8)
public void updateCurricula() throws JSONException {
for (Entry<String, String> idEntry : gradeCurriculumMap.entrySet()) {
String gradeId = idEntry.getKey();
String curriculumId = idEntry.getValue();

// Generate lesson counts for each subject
List<LessonsCountRequestDto> lessonCounts = subjects.stream()
.map(subject -> new LessonsCountRequestDto(subjectIds.get(subjects.indexOf(subject)), random.nextInt(3) + 1))
.collect(Collectors.toList());

String curriculumName = gradeMap.get(gradeId);
given().contentType(ContentType.JSON)
.when()
.body(JsonGenerator.generateCurriculumJson(gradeId, curriculumName, lessonCounts))
.put("/curriculum/" + curriculumId)
.then()
.log().everything()
.statusCode(200);
}
}
*/
}
80 changes: 80 additions & 0 deletions server/ucdl/ucdl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
newConstraint:
description: "Ein neuer Constraint, der immer zu false auswertet."
default_type: HARD_PENALIZE
parameter:
definition: >-
if (false) {
return true
}
return false

teacherCollision:
description: "Lehrer {teacher} kann nicht mehrere Unterrichtseinheiten zeitgleich unterrichten."
default_type: HARD_PENALIZE
parameter:
teacher: Teacher
definition: >-
exists (lesson1 : teacher.lessons) {
exists (lesson2 : teacher.lessons) {
lesson1 != lesson2 && lesson1.timeslot == lesson2.timeslot && lesson1.teacher == lesson2.teacher
}
}

studentCollision:
description: "Schüler {student} kann nicht an mehreren Unterrichtseinheiten zeitgleich teilnehmen."
default_type: HARD_PENALIZE
parameter:
student: Student
definition: >-
exists (lesson1 : student.studentGroups.lessons) {
exists (lesson2 : student.studentGroups.lessons) {
lesson1 != lesson2 && lesson1.timeslot == lesson2.timeslot && lesson1.teacher == lesson2.teacher
}
}

roomCollision:
description: "In Raum {room} können nicht mehrere Unterrichtseinheiten zeitgleich unterrichtet werden."
default_type: HARD_PENALIZE
parameter:
room: Room
definition: >-
exists (lesson1 : room.lessons) {
exists (lesson2 : room.lessons) {
lesson1 != lesson2 && lesson1.timeslot == lesson2.timeslot && lesson1.teacher == lesson2.teacher
}
}

workingHours:
description: "Lehrer {teacher} arbeitet zum Zeitpunkt {timeslot}."
default_type: SOFT_PENALIZE
parameter:
teacher: Teacher
timeslot: Timeslot
definition: >-
if (timeslot in teacher.lessons.timeslot) {
return true
}
return false

teacherTeachesGroup:
description: "Lehrer {teacher} unterrichtet Schülergruppe {group} in Fach {subject}."
default_type: SOFT_PENALIZE
parameter:
teacher: Teacher
group: Student-Group
subject: Subject
definition: >-
forall (lesson : group.lessons[this.subject == subject]) {
lesson.teacher == teacher
}

subjectRoom:
description: "Fach {subject} kann nur in Räumen mit Tag {tag} unterrichtet werden."
default_type: SOFT_PENALIZE
parameter:
subject: Subject
tag: Tag
definition: >-
forall (room : subject.lessons.room) {
tag in room.tags
}
Loading