-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Fix checkstyle * Add dependency to fopbot * Custom world implementation * Interface for creating problem solver * Simple maze solver algorithm * Visualizer for maze * Add default constructors * Json Junit Test Support * Snapshot dependency * Improve code namings * numberOfSteps should also contain the direction as input * Add color to start and end point * Add support for serialization * Utilities for adding criterions and reflection stuff * Reflection stuff * H1 | DirectionVector Tests * H2 | World Tests * H3 | MazeSolverRecursive Tests * H4 | MazeSolverIterative Tests * Finialize rubrics * Remove obsolete test cases * documentation * Remove obsolete code * Change x to dx * Remove obsolete comments * Remove obsolete comments * Remove obsolete code * Remove obsolete code * Remove helper function since they have the same signature as the main function * Add requirements check * Fix nextStep input must be not the rotated vector. The rotation will be checked in the method (#4) * Add dependency to fopbot * Custom world implementation * Simple maze solver algorithm * Improve code namings * Add color to start and end point * Fix failing tests due to missing exclusion * Bump tudalgo fixing spoon type error --------- Co-authored-by: zentox <[email protected]>
- Loading branch information
Showing
58 changed files
with
4,761 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
package h06; | ||
|
||
import h06.world.DirectionVector; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junitpioneer.jupiter.json.JsonClasspathSource; | ||
import org.junitpioneer.jupiter.json.Property; | ||
import org.sourcegrade.jagr.api.rubric.TestForSubmission; | ||
import org.tudalgo.algoutils.tutor.general.assertions.Context; | ||
import org.tudalgo.algoutils.tutor.general.reflections.BasicMethodLink; | ||
import org.tudalgo.algoutils.tutor.general.reflections.MethodLink; | ||
import org.tudalgo.algoutils.tutor.general.reflections.TypeLink; | ||
import spoon.reflect.code.CtConditional; | ||
import spoon.reflect.code.CtIf; | ||
import spoon.reflect.code.CtReturn; | ||
import spoon.reflect.declaration.CtElement; | ||
|
||
import java.util.List; | ||
|
||
import static h06.TutorUtils.getMethodLink; | ||
import static h06.TutorUtils.getTypeLink; | ||
import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertEquals; | ||
import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertFalse; | ||
import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertTrue; | ||
import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.contextBuilder; | ||
|
||
/** | ||
* Defines unit tests for {@link DirectionVector}. | ||
* | ||
* @author Nhan Huynh | ||
*/ | ||
@DisplayName("H1 | DirectionVector") | ||
@TestForSubmission | ||
public class H1_DirectionVectorTest { | ||
|
||
/** | ||
* Defines unit tests for the method {@link DirectionVector#rotate270()}. | ||
*/ | ||
@DisplayName("H1.1 | rotate270()") | ||
@Nested | ||
public class Rotate270Test { | ||
|
||
/** | ||
* Tests whether the input vector is rotated correctly. | ||
* | ||
* @param input the input vector | ||
* @param expected the expected vector | ||
*/ | ||
@ParameterizedTest(name = "Input: {0}") | ||
@DisplayName("01 | Methode rotate270() gibt in allen Fällen den korrekten Vektor zurück.") | ||
@JsonClasspathSource(value = { | ||
"DirectionVector/rotate270/up.json", | ||
"DirectionVector/rotate270/right.json", | ||
"DirectionVector/rotate270/down.json", | ||
"DirectionVector/rotate270/left.json", | ||
}) | ||
public void testRotate270( | ||
@Property("input") DirectionVector input, | ||
@Property("expected") DirectionVector expected | ||
) { | ||
TypeLink type = getTypeLink(Package.WORLD, DirectionVector.class); | ||
MethodLink method = getMethodLink(Package.WORLD, DirectionVector.class, "rotate270"); | ||
DirectionVector actual = input.rotate270(); | ||
Context context = contextBuilder().subject(method) | ||
.add("Input", input) | ||
.add("Expected", expected) | ||
.add("Actual", actual) | ||
.build(); | ||
assertEquals( | ||
expected, actual, context, | ||
result -> "DirectionVector#rotate270() should return %s, but was %s.".formatted(expected, result) | ||
); | ||
} | ||
|
||
@DisplayName("02 | Verbindliche Anforderungen") | ||
@Test | ||
public void testRequirements() { | ||
TypeLink type = getTypeLink(Package.WORLD, DirectionVector.class); | ||
BasicMethodLink method = ((BasicMethodLink) getMethodLink(Package.WORLD, DirectionVector.class, "rotate270")); | ||
Context context = contextBuilder().subject(method).build(); | ||
|
||
List<CtReturn<?>> returns = method.getCtElement().filterChildren(it -> it instanceof CtReturn<?>) | ||
.list(); | ||
boolean found = false; | ||
for (CtReturn<?> ret : returns) { | ||
if (ret.getReturnedExpression() instanceof CtConditional<?> expression) { | ||
found = true; | ||
break; | ||
} | ||
} | ||
assertTrue(found, context, | ||
result -> "DirectionVector#rotate270() should contain exactly one conditional statement, but found %s" | ||
.formatted(returns.stream().map(CtReturn::getReturnedExpression).toList())); | ||
} | ||
} | ||
|
||
/** | ||
* Defines unit tests for the method {@link DirectionVector#rotate90()}. | ||
*/ | ||
@DisplayName("H1.2 | rotate90()") | ||
@Nested | ||
public class Rotate90Test { | ||
|
||
/** | ||
* Tests whether the input vector is rotated correctly. | ||
* | ||
* @param input the input vector | ||
* @param expected the expected vector | ||
*/ | ||
@ParameterizedTest(name = "Input: {0}") | ||
@DisplayName("03 | Methode rotate90() gibt in allen Fällen den korrekten Vektor zurück.") | ||
@JsonClasspathSource(value = { | ||
"DirectionVector/rotate90/up.json", | ||
"DirectionVector/rotate90/right.json", | ||
"DirectionVector/rotate90/down.json", | ||
"DirectionVector/rotate90/left.json", | ||
}) | ||
public void testRotate90( | ||
@Property("input") DirectionVector input, | ||
@Property("expected") DirectionVector expected | ||
) { | ||
MethodLink method = getMethodLink(Package.WORLD, DirectionVector.class, "rotate90"); | ||
DirectionVector actual = input.rotate90(); | ||
Context context = contextBuilder().subject(method) | ||
.add("Input", input) | ||
.add("Expected", expected) | ||
.add("Actual", actual) | ||
.build(); | ||
assertEquals( | ||
expected, actual, context, | ||
result -> "DirectionVector#rotate90() should return %s, but was %s.".formatted(expected, actual) | ||
); | ||
} | ||
|
||
@DisplayName("04 | Verbindliche Anforderungen") | ||
@Test | ||
public void testRequirements() { | ||
TypeLink type = getTypeLink(Package.WORLD, DirectionVector.class); | ||
BasicMethodLink method = ((BasicMethodLink) getMethodLink(Package.WORLD, DirectionVector.class, "rotate90")); | ||
Context context = contextBuilder().subject(method).build(); | ||
|
||
List<CtElement> elements = method.getCtElement().filterChildren(it -> it instanceof CtIf).list(); | ||
|
||
assertFalse(elements.isEmpty(), context, | ||
result -> "DirectionVector#rotate90() should contain exactly one if-else statement, but found %s" | ||
.formatted(elements)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
package h06; | ||
|
||
import h06.world.DirectionVector; | ||
import h06.world.World; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junitpioneer.jupiter.json.JsonClasspathSource; | ||
import org.junitpioneer.jupiter.json.Property; | ||
import org.sourcegrade.jagr.api.rubric.TestForSubmission; | ||
import org.tudalgo.algoutils.tutor.general.assertions.Context; | ||
import org.tudalgo.algoutils.tutor.general.match.BasicReflectionMatchers; | ||
import org.tudalgo.algoutils.tutor.general.reflections.BasicTypeLink; | ||
import org.tudalgo.algoutils.tutor.general.reflections.MethodLink; | ||
|
||
import java.awt.Point; | ||
|
||
import static h06.TutorUtils.buildWorldContext; | ||
import static h06.TutorUtils.getMethodLink; | ||
import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.assertEquals; | ||
import static org.tudalgo.algoutils.tutor.general.assertions.Assertions2.contextBuilder; | ||
|
||
/** | ||
* Defines unit tests for {@link World}. | ||
* | ||
* @see H1_DirectionVectorTest | ||
*/ | ||
@DisplayName("H2 | World") | ||
@TestForSubmission | ||
public class H2_WorldTest { | ||
|
||
/** | ||
* Returns the method {@link World#isBlocked(Point, DirectionVector)} used for context information. | ||
* | ||
* @return the method {@link World#isBlocked(Point, DirectionVector)} used for context information | ||
*/ | ||
private MethodLink getMethod() { | ||
return getMethodLink( | ||
Package.WORLD, | ||
World.class, | ||
"isBlocked", | ||
BasicReflectionMatchers.sameTypes(BasicTypeLink.of(Point.class), BasicTypeLink.of(DirectionVector.class)) | ||
); | ||
} | ||
|
||
/** | ||
* Tests whether {@link World#isBlocked(Point, DirectionVector)} returns the expected value. | ||
* | ||
* @param properties the properties of the world | ||
* @param p the point to test | ||
* @param d the direction vector to test | ||
* @param expected the expected value | ||
*/ | ||
private void assertIsBlocked(WorldProperties properties, Point p, DirectionVector d, boolean expected) { | ||
MethodLink method = getMethod(); | ||
|
||
World world = properties.createWorld(); | ||
boolean actual = world.isBlocked(p, d); | ||
|
||
Context context = contextBuilder().subject(method) | ||
.add(buildWorldContext(properties)) | ||
.build(); | ||
|
||
assertEquals( | ||
expected, actual, context, | ||
result -> "World#isBlocked(%s, %s) should return %s, but was %s.".formatted(p, d, expected, result) | ||
); | ||
} | ||
|
||
|
||
/** | ||
* Tests whether {@link World#isBlocked(Point, DirectionVector)} returns the correct value for points outside | ||
* the world. | ||
* | ||
* @param properties the properties of the world | ||
* @param p the point to test | ||
* @param d the direction vector to test | ||
*/ | ||
@ParameterizedTest(name = "Koordinate: {1}, Richtung: {2}") | ||
@DisplayName("05 | isBlocked(Point, DirectionVector) gibt für Koordinaten außerhalb der Welt false true.") | ||
@JsonClasspathSource(value = { | ||
"World/isBlocked/outside_1.json", | ||
"World/isBlocked/outside_2.json", | ||
"World/isBlocked/outside_3.json", | ||
"World/isBlocked/outside_4.json", | ||
"World/isBlocked/outside_5.json", | ||
}) | ||
public void testIsBlockedOutside( | ||
@Property("properties") WorldProperties properties, | ||
@Property("p") Point p, | ||
@Property("d") DirectionVector d) { | ||
assertIsBlocked(properties, p, d, true); | ||
} | ||
|
||
/** | ||
* Tests whether {@link World#isBlocked(Point, DirectionVector)} returns the correct value for points inside | ||
* the world. (Only direction left and up). | ||
* | ||
* @param properties the properties of the world | ||
* @param p the point to test | ||
* @param d the direction vector to test | ||
* @param expected the expected value | ||
*/ | ||
@ParameterizedTest(name = "Koordinate: {1}, Richtung: {2}") | ||
@DisplayName("06 | isBlocked(Point, DirectionVector) gibt für Koordinaten innerhalb der Welt mit " | ||
+ "Richtungsvektor links und oben korrekte Werte zurück.") | ||
@JsonClasspathSource(value = { | ||
"World/isBlocked/leftup_1.json", | ||
"World/isBlocked/leftup_2.json", | ||
"World/isBlocked/leftup_3.json", | ||
"World/isBlocked/leftup_4.json", | ||
"World/isBlocked/leftup_5.json", | ||
}) | ||
public void testIsBlockedRightAndDown( | ||
@Property("properties") WorldProperties properties, | ||
@Property("p") Point p, | ||
@Property("d") DirectionVector d, | ||
@Property("expected") boolean expected) { | ||
assertIsBlocked(properties, p, d, expected); | ||
} | ||
|
||
/** | ||
* Tests whether {@link World#isBlocked(Point, DirectionVector)} returns the correct value for points inside | ||
* the world. (Only direction right and down). | ||
* | ||
* @param properties the properties of the world | ||
* @param p the point to test | ||
* @param d the direction vector to test | ||
* @param expected the expected value | ||
*/ | ||
@ParameterizedTest(name = "Koordinate: {1}, Richtung: {2}") | ||
@DisplayName("07 | isBlocked(Point, DirectionVector) gibt für Koordinaten innerhalb der Welt mit " | ||
+ "Richtungsvektor rechts und unten korrekte Werte zurück.") | ||
@JsonClasspathSource(value = { | ||
"World/isBlocked/rightdown_1.json", | ||
"World/isBlocked/rightdown_2.json", | ||
"World/isBlocked/rightdown_3.json", | ||
"World/isBlocked/rightdown_4.json", | ||
}) | ||
public void testIsBlockedLeftAndUp( | ||
@Property("properties") WorldProperties properties, | ||
@Property("p") Point p, | ||
@Property("d") DirectionVector d, | ||
@Property("expected") boolean expected) { | ||
assertIsBlocked(properties, p, d, expected); | ||
} | ||
|
||
@ParameterizedTest(name = "Koordinate: {1}, Richtung: {2}") | ||
@DisplayName("08 | isBlocked(Point, DirectionVector) ruft die Methode isBlocked(int, int, boolean) mit der " | ||
+ "richtigen Wand Orientierung auf.") | ||
@JsonClasspathSource(value = { | ||
"World/isBlocked/orientation_left.json", | ||
"World/isBlocked/orientation_right.json", | ||
"World/isBlocked/orientation_up.json", | ||
"World/isBlocked/orientation_down.json", | ||
}) | ||
public void testOrientation( | ||
@Property("properties") WorldProperties properties, | ||
@Property("p") Point p, | ||
@Property("d") DirectionVector d, | ||
@Property("expected") boolean expected) { | ||
MethodLink method = getMethod(); | ||
|
||
World world = properties.createWorld(); | ||
boolean actual = world.isBlocked(p, d); | ||
|
||
Context context = contextBuilder().subject(method) | ||
.add(buildWorldContext(properties)) | ||
.build(); | ||
|
||
assertEquals( | ||
expected, actual, context, | ||
result -> "World#isBlocked(%s, %s) should call World#isBlocked(int, int, boolean) with".formatted(p, d) | ||
+ "the orientation %s, but was %s.".formatted(expected, actual) | ||
); | ||
} | ||
|
||
/** | ||
* Tests whether {@link World#isBlocked(Point, DirectionVector)} calls the method | ||
* {@link World#isBlocked(int, int, boolean)} with the correct wall orientation. | ||
*/ | ||
private static class OrientationWorld extends World { | ||
|
||
/** | ||
* Creates a new world with the given width and height. | ||
* | ||
* @param width the width of the world | ||
* @param height the height of the world | ||
*/ | ||
public OrientationWorld(int width, int height) { | ||
super(width, height); | ||
} | ||
|
||
@Override | ||
public boolean isBlocked(int x, int y, boolean horizontal) { | ||
return horizontal; | ||
} | ||
} | ||
} |
Oops, something went wrong.