chore: formatting and use modern javadoc style

This commit is contained in:
js0ny 2025-10-18 21:43:31 +01:00
parent 79db47459a
commit c2a39936ec
3 changed files with 69 additions and 40 deletions

View file

@ -6,17 +6,21 @@ import java.util.Objects;
/** /**
* Represents the data transfer object for a region definition * Represents the data transfer object for a region definition
* <p> * <p>
* This record encapsulates the data for calculating if a coordinate is inside the region * This record encapsulates the data for calculating if a coordinate is inside
* the region
* <p> * <p>
* A built-in method <code>isClosedTo</code> is defined to check this DTO is valid or not in the mean of closing polygon * A built-in method {@code isClosedTo} is defined to check this DTO is valid or
* not in the mean of closing polygon
* *
* @param name The human-readable name for the region * @param name The human-readable name for the region
* @param vertices list of coordinates that forms a polygon as a region. * @param vertices list of coordinates that forms a polygon as a region.
* <p> * <p>
* In order to define a valid region, the last element of the list should be the same as the first, or * In order to define a valid region, the last element of the
* list should be the same as the first, or
* known as closed * known as closed
* @see RegionCheckRequestDto * @see RegionCheckRequestDto
* @see io.github.js0ny.ilp_coursework.service.GpsCalculationService#checkIsInRegion(LngLatDto, RegionDto) * @see io.github.js0ny.ilp_coursework.service.GpsCalculationService#checkIsInRegion(LngLatDto,
* RegionDto)
*/ */
public record RegionDto(String name, List<LngLatDto> vertices) { public record RegionDto(String name, List<LngLatDto> vertices) {
/** /**
@ -27,9 +31,11 @@ public record RegionDto(String name, List<LngLatDto> vertices) {
private static final int MINIMUM_VERTICES = 4; private static final int MINIMUM_VERTICES = 4;
/** /**
* Method to check if the region has a valid polygon by checking if the <code>vertices</code> forms a closed polygon * Method to check if the region has a valid polygon by checking if the
* {@code vertices} forms a closed polygon
* *
* @return {@code true} if the <code>vertices</code> are able to form a polygon and form a closed polygon * @return {@code true} if the {@code vertices} are able to form a polygon and
* form a closed polygon
*/ */
public boolean isClosed() { public boolean isClosed() {
if (vertices == null || vertices.size() < MINIMUM_VERTICES) { if (vertices == null || vertices.size() < MINIMUM_VERTICES) {

View file

@ -29,13 +29,17 @@ public class GpsCalculationService {
private static final double CLOSE_THRESHOLD = 0.00015; private static final double CLOSE_THRESHOLD = 0.00015;
/** /**
* Calculate the Euclidean distance between <code>position1</code> and <code>position2</code>, which are coordinates * Calculate the Euclidean distance between {@code position1} and
* {@code position2}, which are coordinates
* defined as {@link LngLatDto} * defined as {@link LngLatDto}
* *
* @param position1 The coordinate of the first position * @param position1 The coordinate of the first position
*
* @param position2 The coordinate of the second position * @param position2 The coordinate of the second position
* @return The Euclidean distance between <code>position1</code> and <code>position2</code> * @return The Euclidean distance between {@code position1} and
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getDistance(DistanceRequestDto) * {@code position2}
* @see
* io.github.js0ny.ilp_coursework.controller.ApiController#getDistance(DistanceRequestDto)
*/ */
public double calculateDistance(LngLatDto position1, LngLatDto position2) { public double calculateDistance(LngLatDto position1, LngLatDto position2) {
double lngDistance = position2.lng() - position1.lng(); double lngDistance = position2.lng() - position1.lng();
@ -45,13 +49,18 @@ public class GpsCalculationService {
} }
/** /**
* Check if <code>position1</code> and <code>position2</code> are close to each other, the threshold is < 0.00015 * Check if {@code position1} and
* {@code position2} are close to each other, the threshold is < 0.00015
*
* <p> * <p>
* Note that = 0.00015 will be counted as not close to and will return <code>false</code> * Note that = 0.00015 will be counted as not close to and will return {@code
* false}
* *
* @param position1 The coordinate of the first position * @param position1 The coordinate of the first position
*
* @param position2 The coordinate of the second position * @param position2 The coordinate of the second position
* @return True if <code>position1</code> and <code>position2</code> are close to each other * @return {@code true} if {@code position1} and
* {@code position2} are close to each other
* @see #CLOSE_THRESHOLD * @see #CLOSE_THRESHOLD
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getIsCloseTo(DistanceRequestDto) * @see io.github.js0ny.ilp_coursework.controller.ApiController#getIsCloseTo(DistanceRequestDto)
*/ */
@ -61,12 +70,14 @@ public class GpsCalculationService {
} }
/** /**
* Returns the next position moved from <code>start</code> in the direction with <code>angle</code>, with step size * Returns the next position moved from {@code start} in the direction with
* {@code angle}, with step size
* 0.00015 * 0.00015
* *
* @param start The coordinate of the original start point. * @param start The coordinate of the original start point.
*
* @param angle The direction to be moved in angle. * @param angle The direction to be moved in angle.
* @return The next position moved from <code>start</code> * @return The next position moved from {@code start}
* @see #STEP * @see #STEP
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getNextPosition(MovementRequestDto) * @see io.github.js0ny.ilp_coursework.controller.ApiController#getNextPosition(MovementRequestDto)
*/ */
@ -78,13 +89,14 @@ public class GpsCalculationService {
} }
/** /**
* Used to check if the given <code>position</code> * Used to check if the given {@code position}
* is inside the <code>region</code>, on edge and vertex is considered as inside. * is inside the {@code region}, on edge and vertex is considered as inside.
* *
* @param position The coordinate of the position. * @param position The coordinate of the position.
* @param region A {@link RegionDto} that contains name and a list of <code>LngLatDto</code> * @param region A {@link RegionDto} that contains name and a list of
* @return true if <code>position</code> is inside the <code>region</code>. * {@code LngLatDto}
* @throws IllegalArgumentException If <code>region</code> is not closed * @return {@code true} if {@code position} is inside the {@code region}.
* @throws IllegalArgumentException If {@code region} is not closed
* @see io.github.js0ny.ilp_coursework.controller.ApiController#getIsInRegion(RegionCheckRequestDto) * @see io.github.js0ny.ilp_coursework.controller.ApiController#getIsInRegion(RegionCheckRequestDto)
* @see RegionDto#isClosed() * @see RegionDto#isClosed()
*/ */
@ -95,16 +107,15 @@ public class GpsCalculationService {
return rayCasting(position, region.vertices()); return rayCasting(position, region.vertices());
} }
/** /**
* Helper function to <code>checkIsInRegion</code>, use of ray-casting algorithm * Helper function to {@code checkIsInRegion}, use of ray-casting algorithm
* to check if inside the polygon * to check if inside the polygon
* *
* @param point The point to check * @param point The point to check
* @param polygon The region that forms a polygon to check if <code>point</code> * @param polygon The region that forms a polygon to check if {@code point}
* sits inside. * sits inside.
* @return If the <code>point</code> sits inside the <code>polygon</code> then * @return If the {@code point} sits inside the {@code polygon} then
* return True * return {@code true}
* @see #isPointOnEdge(LngLatDto, LngLatDto, LngLatDto) * @see #isPointOnEdge(LngLatDto, LngLatDto, LngLatDto)
* @see #checkIsInRegion(LngLatDto, RegionDto) * @see #checkIsInRegion(LngLatDto, RegionDto)
*/ */
@ -138,7 +149,6 @@ public class GpsCalculationService {
double xIntersection = a.lng() + ((point.lat() - a.lat()) * (b.lng() - a.lng())) / (b.lat() - a.lat()); double xIntersection = a.lng() + ((point.lat() - a.lat()) * (b.lng() - a.lng())) / (b.lat() - a.lat());
if (xIntersection > point.lng()) { if (xIntersection > point.lng()) {
++intersections; ++intersections;
} }
@ -150,13 +160,15 @@ public class GpsCalculationService {
} }
/** /**
* Helper function from <code>rayCasting</code> that used to simply calculation <br> * Helper function from {@code rayCasting} that used to simply calculation <br>
* Used to check if point <code>p</code> is on the edge formed by <code>a</code> and <code>b</code> * Used to check if point {@code p} is on the edge formed by
* {@code a} and {@code b}
* *
* @param p point to be checked on the edge * @param p point to be checked on the edge
*
* @param a point that forms the edge * @param a point that forms the edge
* @param b point that forms the edge * @param b point that forms the edge
* @return boolean, if <code>p</code> is on <code>ab</code> then true * @return {@code true} if {@code p} is on {@code ab}
* @see #rayCasting(LngLatDto, List) * @see #rayCasting(LngLatDto, List)
*/ */
private boolean isPointOnEdge(LngLatDto p, LngLatDto a, LngLatDto b) { private boolean isPointOnEdge(LngLatDto p, LngLatDto a, LngLatDto b) {

View file

@ -13,7 +13,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.within; import static org.assertj.core.api.AssertionsForClassTypes.within;
public class GpsCalculationServiceTest { public class GpsCalculationServiceTest {
private static final double STEP = 0.00015; private static final double STEP = 0.00015;
@ -180,7 +179,8 @@ public class GpsCalculationServiceTest {
void nextPosition_shouldMoveWest_forAngle180() { void nextPosition_shouldMoveWest_forAngle180() {
var start = new LngLatDto(0.0, 0.0); var start = new LngLatDto(0.0, 0.0);
double angle = 180; double angle = 180;
// For 180 degrees, cos(180)=-1, sin(180)=0. Move happens entirely on negative lng axis. // For 180 degrees, cos(180)=-1, sin(180)=0. Move happens entirely on negative
// lng axis.
var expected = new LngLatDto(-STEP, 0.0); var expected = new LngLatDto(-STEP, 0.0);
var actual = service.nextPosition(start, angle); var actual = service.nextPosition(start, angle);
@ -194,7 +194,8 @@ public class GpsCalculationServiceTest {
void nextPosition_shouldMoveSouth_forAngle270() { void nextPosition_shouldMoveSouth_forAngle270() {
var start = new LngLatDto(0.0, 0.0); var start = new LngLatDto(0.0, 0.0);
double angle = 270; double angle = 270;
// For 270 degrees, cos(270)=0, sin(270)=-1. Move happens entirely on negative lat axis. // For 270 degrees, cos(270)=0, sin(270)=-1. Move happens entirely on negative
// lat axis.
var expected = new LngLatDto(0.0, -STEP); var expected = new LngLatDto(0.0, -STEP);
var actual = service.nextPosition(start, angle); var actual = service.nextPosition(start, angle);
@ -257,13 +258,17 @@ public class GpsCalculationServiceTest {
@DisplayName("Test for checkIsInRegion(LngLatDto, RegionDto) -> boolean") @DisplayName("Test for checkIsInRegion(LngLatDto, RegionDto) -> boolean")
class CheckIsInRegionTests { class CheckIsInRegionTests {
public static final RegionDto RECTANGLE_REGION = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(2.0, 0.0), new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, 0.0))); public static final RegionDto RECTANGLE_REGION = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0),
new LngLatDto(2.0, 0.0), new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, 0.0)));
@Test @Test
@DisplayName("General Case: Given Example for Testing") @DisplayName("General Case: Given Example for Testing")
void isInRegion_shouldReturnFalse_givenPolygonCentral() { void isInRegion_shouldReturnFalse_givenPolygonCentral() {
var position = new LngLatDto(1.234, 1.222); var position = new LngLatDto(1.234, 1.222);
var region = new RegionDto("central", List.of(new LngLatDto(-3.192473, 55.946233), new LngLatDto(-3.192473, 55.942617), new LngLatDto(-3.184319, 55.942617), new LngLatDto(-3.184319, 55.946233), new LngLatDto(-3.192473, 55.946233))); var region = new RegionDto("central",
List.of(new LngLatDto(-3.192473, 55.946233), new LngLatDto(-3.192473, 55.942617),
new LngLatDto(-3.184319, 55.942617), new LngLatDto(-3.184319, 55.946233),
new LngLatDto(-3.192473, 55.946233)));
boolean expected = false; boolean expected = false;
boolean actual = service.checkIsInRegion(position, region); boolean actual = service.checkIsInRegion(position, region);
assertThat(actual).isEqualTo(expected); assertThat(actual).isEqualTo(expected);
@ -291,7 +296,10 @@ public class GpsCalculationServiceTest {
@DisplayName("General Case: Simple Hexagon") @DisplayName("General Case: Simple Hexagon")
void isInRegion_shouldReturnTrue_forSimpleHexagon() { void isInRegion_shouldReturnTrue_forSimpleHexagon() {
var position = new LngLatDto(2.0, 2.0); var position = new LngLatDto(2.0, 2.0);
var region = new RegionDto("hexagon", List.of(new LngLatDto(1.0, 0.0), new LngLatDto(4.0, 0.0), new LngLatDto(5.0, 2.0), new LngLatDto(4.0, 4.0), new LngLatDto(1.0, 4.0), new LngLatDto(0.0, 2.0), new LngLatDto(1.0, 0.0))); var region = new RegionDto("hexagon",
List.of(new LngLatDto(1.0, 0.0), new LngLatDto(4.0, 0.0), new LngLatDto(5.0, 2.0),
new LngLatDto(4.0, 4.0), new LngLatDto(1.0, 4.0), new LngLatDto(0.0, 2.0),
new LngLatDto(1.0, 0.0)));
boolean expected = true; boolean expected = true;
boolean actual = service.checkIsInRegion(position, region); boolean actual = service.checkIsInRegion(position, region);
assertThat(actual).isEqualTo(expected); assertThat(actual).isEqualTo(expected);
@ -301,7 +309,8 @@ public class GpsCalculationServiceTest {
@DisplayName("Edge Case: Small Triangle") @DisplayName("Edge Case: Small Triangle")
void isInRegion_shouldReturnTrue_forSmallTriangle() { void isInRegion_shouldReturnTrue_forSmallTriangle() {
var position = new LngLatDto(0.00001, 0.00001); var position = new LngLatDto(0.00001, 0.00001);
var region = new RegionDto("triangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0), new LngLatDto(0.00005, 0.0001), new LngLatDto(0.0, 0.0))); var region = new RegionDto("triangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0),
new LngLatDto(0.00005, 0.0001), new LngLatDto(0.0, 0.0)));
boolean expected = true; boolean expected = true;
boolean actual = service.checkIsInRegion(position, region); boolean actual = service.checkIsInRegion(position, region);
assertThat(actual).isEqualTo(expected); assertThat(actual).isEqualTo(expected);
@ -356,7 +365,8 @@ public class GpsCalculationServiceTest {
@DisplayName("Edge Case: Region not forming polygon") @DisplayName("Edge Case: Region not forming polygon")
void isInRegion_shouldThrowExceptions_whenRegionNotFormingPolygon() { void isInRegion_shouldThrowExceptions_whenRegionNotFormingPolygon() {
var position = new LngLatDto(2.0, 2.0); var position = new LngLatDto(2.0, 2.0);
var region = new RegionDto("line", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0), new LngLatDto(0.0, 0.0))); var region = new RegionDto("line",
List.of(new LngLatDto(0.0, 0.0), new LngLatDto(0.0001, 0.0), new LngLatDto(0.0, 0.0)));
assertThatThrownBy(() -> { assertThatThrownBy(() -> {
service.checkIsInRegion(position, region); service.checkIsInRegion(position, region);
}).isInstanceOf(IllegalArgumentException.class).hasMessage("Region is not closed."); }).isInstanceOf(IllegalArgumentException.class).hasMessage("Region is not closed.");
@ -366,7 +376,8 @@ public class GpsCalculationServiceTest {
@DisplayName("Edge Case: Region is not closed") @DisplayName("Edge Case: Region is not closed")
void isInRegion_shouldThrowExceptions_whenRegionNotClose() { void isInRegion_shouldThrowExceptions_whenRegionNotClose() {
var position = new LngLatDto(2.0, 2.0); var position = new LngLatDto(2.0, 2.0);
var region = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(2.0, 0.0), new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, -1.0))); var region = new RegionDto("rectangle", List.of(new LngLatDto(0.0, 0.0), new LngLatDto(2.0, 0.0),
new LngLatDto(2.0, 2.0), new LngLatDto(0.0, 2.0), new LngLatDto(0.0, -1.0)));
assertThatThrownBy(() -> { assertThatThrownBy(() -> {
service.checkIsInRegion(position, region); service.checkIsInRegion(position, region);
}).isInstanceOf(IllegalArgumentException.class).hasMessage("Region is not closed."); }).isInstanceOf(IllegalArgumentException.class).hasMessage("Region is not closed.");