Initial Commit
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.idea/*
|
||||||
|
build/*
|
||||||
|
*.iml
|
||||||
|
out/*
|
||||||
|
.gradle/*
|
||||||
|
target/*
|
13
LICENSE
Normal file
13
LICENSE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
Version 2, December 2004
|
||||||
|
|
||||||
|
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim or modified
|
||||||
|
copies of this license document, and changing it is allowed as long
|
||||||
|
as the name is changed.
|
||||||
|
|
||||||
|
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. You just DO WHAT THE FUCK YOU WANT TO.
|
39
README.md
Normal file
39
README.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
# Kata Tondeuse
|
||||||
|
|
||||||
|
Simulate the movement of Tondeuses (mowers) on a rectangular Pelouse (lawn), following a set of instructions.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Java 8 or later
|
||||||
|
- Maven
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Clone this repository
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/katatondeuse.git
|
||||||
|
cd katatondeuse
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Running the Application
|
||||||
|
|
||||||
|
To run the application:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn compile exec:java -Dexec.mainClass="com.qrouland.katatondeuse.Main" -Dexec.args="examples/input.txt"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
To run all tests :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn test
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the WTFPL - Do What The F*** You Want To Public License.
|
5
examples/input.txt
Normal file
5
examples/input.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
5 5
|
||||||
|
1 2 N
|
||||||
|
GAGAGAGAA
|
||||||
|
3 3 E
|
||||||
|
AADAADADDA
|
90
pom.xml
Normal file
90
pom.xml
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.qrouland.katatondeuse</groupId>
|
||||||
|
<artifactId>kata-tondeuse</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>Kata Tondeuse</name>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>WTFPL - Do What The F*** You Want To Public License</name>
|
||||||
|
<url>http://www.wtfpl.net/txt/copying/</url>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<mockito.version>2.26.0</mockito.version>
|
||||||
|
<junit.version>5.5.2</junit.version>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<javadoc.plugin.version>3.1.1</javadoc.plugin.version>
|
||||||
|
<source.plugin.version>3.2.0</source.plugin.version>
|
||||||
|
<surefire.plugin.version>2.22.2</surefire.plugin.version>
|
||||||
|
<org.apache.commons.version>3.14.0</org.apache.commons.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>${org.apache.commons.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>${source.plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${surefire.plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>16</source>
|
||||||
|
<target>16</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,87 @@
|
|||||||
|
package com.qrouland.katatondeuse;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class MainIntegrationTest {
|
||||||
|
private final PrintStream originalOut = System.out;
|
||||||
|
private final PrintStream originalErr = System.err;
|
||||||
|
private ByteArrayOutputStream outContent;
|
||||||
|
private ByteArrayOutputStream errContent;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUpStreams() {
|
||||||
|
outContent = new ByteArrayOutputStream();
|
||||||
|
errContent = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
System.setOut(new PrintStream(outContent));
|
||||||
|
System.setErr(new PrintStream(errContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void restoreStreams() {
|
||||||
|
System.setOut(originalOut);
|
||||||
|
System.setErr(originalErr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMain_ValidInputFile() throws IOException {
|
||||||
|
Path tempFile = Files.createTempFile("test-input", ".txt");
|
||||||
|
Files.writeString(tempFile,
|
||||||
|
"5 5\n" +
|
||||||
|
"1 2 N\n" +
|
||||||
|
"GAGAGAGAA\n" +
|
||||||
|
"3 3 E\n" +
|
||||||
|
"AADAADADDA\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
int code = Main.run(new String[]{tempFile.toString()});
|
||||||
|
|
||||||
|
String output = outContent.toString();
|
||||||
|
|
||||||
|
assertEquals(0, code);
|
||||||
|
assertTrue(output.contains("Pelouse 5 x 5"));
|
||||||
|
assertTrue(output.contains("Moved"));
|
||||||
|
|
||||||
|
Files.deleteIfExists(tempFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMain_MissingFileArg() {
|
||||||
|
int code = Main.run(new String[]{});
|
||||||
|
|
||||||
|
assertEquals(1, code);
|
||||||
|
String errorOutput = errContent.toString();
|
||||||
|
assertTrue(errorOutput.contains("Error: Missing input file argument."));
|
||||||
|
assertTrue(errorOutput.contains("Usage: java Main <inputfile>"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMain_NonexistentFile() {
|
||||||
|
int code = Main.run(new String[]{"nonexistent-file.txt"});
|
||||||
|
|
||||||
|
assertEquals(1, code);
|
||||||
|
String errorOutput = errContent.toString();
|
||||||
|
assertTrue(errorOutput.contains("File does not exist"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMain_withMalformedInputFile() throws IOException {
|
||||||
|
Path tempFile = Files.createTempFile("malformed-input", ".txt");
|
||||||
|
Files.writeString(tempFile,
|
||||||
|
"invalid pelouse line\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
int code = Main.run(new String[]{tempFile.toString()});
|
||||||
|
|
||||||
|
assertEquals(1, code);
|
||||||
|
String errorOutput = errContent.toString();
|
||||||
|
assertTrue(errorOutput.contains("Invalid Pelouse size format"));
|
||||||
|
|
||||||
|
Files.deleteIfExists(tempFile);
|
||||||
|
}
|
||||||
|
}
|
34
src/main/java/com/qrouland/katatondeuse/Main.java
Normal file
34
src/main/java/com/qrouland/katatondeuse/Main.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package com.qrouland.katatondeuse;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.controller.TontePelouseController;
|
||||||
|
import com.qrouland.katatondeuse.parser.FileInputParser;
|
||||||
|
import com.qrouland.katatondeuse.view.ConsolePelouseView;
|
||||||
|
import com.qrouland.katatondeuse.view.PelouseView;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
int exitCode = run(args);
|
||||||
|
System.exit(exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int run(String[] args) {
|
||||||
|
PelouseView view = new ConsolePelouseView();
|
||||||
|
try {
|
||||||
|
File inputFile = FileInputParser.parseInputFile(args);
|
||||||
|
TontePelouseController controller = new TontePelouseController(inputFile, view);
|
||||||
|
controller.run();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
view.displayError("Error: " + e.getMessage());
|
||||||
|
view.displayError("Usage: java Main <inputfile>");
|
||||||
|
return 1;
|
||||||
|
} catch (IOException e) {
|
||||||
|
view.displayError("Error reading file: " + e.getMessage());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Direction;
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
import com.qrouland.katatondeuse.parser.FileInputParser;
|
||||||
|
import com.qrouland.katatondeuse.view.PelouseView;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TontePelouseController {
|
||||||
|
private final File instructionsFile;
|
||||||
|
private final PelouseView pelouseView;
|
||||||
|
|
||||||
|
public TontePelouseController(File instructionsFile, PelouseView view) {
|
||||||
|
this.instructionsFile = instructionsFile;
|
||||||
|
this.pelouseView = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the tonte (mowing) simulation by reading instructions from the input file.
|
||||||
|
*
|
||||||
|
* @throws IOException an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public void run() throws IOException {
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(instructionsFile))) {
|
||||||
|
Pelouse pelouse = initPelouse(reader);
|
||||||
|
executeInstructions(reader, pelouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and executes the {@link Tondeuse} movement instructions from the reader.
|
||||||
|
*
|
||||||
|
* @param reader BufferedReader for reading lines from the instructions file.
|
||||||
|
* @param pelouse The {@link Pelouse} on which {@link Tondeuse} operate.
|
||||||
|
* @throws IOException an I/O error occurs.
|
||||||
|
*/
|
||||||
|
private void executeInstructions(BufferedReader reader, Pelouse pelouse) throws IOException {
|
||||||
|
String positionLine;
|
||||||
|
while ((positionLine = reader.readLine()) != null) {
|
||||||
|
String instructionsLine = reader.readLine();
|
||||||
|
ImmutablePair<Tondeuse, List<Direction>> instructions =
|
||||||
|
FileInputParser.parseTondeuseInstructions(positionLine, instructionsLine);
|
||||||
|
Tondeuse tondeuse = instructions.left;
|
||||||
|
List<Direction> directions = instructions.right;
|
||||||
|
|
||||||
|
pelouse.addTondeuse(tondeuse);
|
||||||
|
pelouseView.displayTondeuseAdd(tondeuse);
|
||||||
|
|
||||||
|
TonteTondeuseController controller = new TonteTondeuseController(tondeuse, pelouse, this.pelouseView);
|
||||||
|
controller.executeInstructions(directions);
|
||||||
|
pelouseView.displayPelouseState(pelouse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the first line of the input to initialize the .
|
||||||
|
*
|
||||||
|
* @param reader BufferedReader reading from the instructions file.
|
||||||
|
* @return The initialized {@link Pelouse}.
|
||||||
|
* @throws IOException an I/O error occurs.
|
||||||
|
*/
|
||||||
|
private Pelouse initPelouse(BufferedReader reader) throws IOException {
|
||||||
|
String firstLine = reader.readLine();
|
||||||
|
Pelouse pelouse = FileInputParser.parsePelouseDefinition(firstLine);
|
||||||
|
pelouseView.displayPelouseState(pelouse);
|
||||||
|
return pelouse;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementAhead;
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementLeft;
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementStrategy;
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementRight;
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import com.qrouland.katatondeuse.view.PelouseView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls a {@link Tondeuse} on {@link Pelouse}.
|
||||||
|
*/
|
||||||
|
public class TonteTondeuseController {
|
||||||
|
private final Pelouse pelouse;
|
||||||
|
private final Tondeuse tondeuse;
|
||||||
|
private final PelouseView pelouseView;
|
||||||
|
|
||||||
|
private static final Map<Direction, MovementStrategy> MOVEMENTS = Map.of(
|
||||||
|
Direction.D, new MovementRight(),
|
||||||
|
Direction.G, new MovementLeft(),
|
||||||
|
Direction.A, new MovementAhead()
|
||||||
|
);
|
||||||
|
|
||||||
|
public TonteTondeuseController(Tondeuse tondeuse, Pelouse pelouse, PelouseView view) {
|
||||||
|
this.pelouse = pelouse;
|
||||||
|
this.tondeuse = tondeuse;
|
||||||
|
this.pelouseView = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a list of instructions of movement directions.
|
||||||
|
*
|
||||||
|
* @param directions the list of movement directions (D, G, A).
|
||||||
|
*/
|
||||||
|
public void executeInstructions(List<Direction> directions) {
|
||||||
|
for (Direction direction : directions) {
|
||||||
|
Position initial_position = tondeuse.getPosition();
|
||||||
|
MovementStrategy movement = MOVEMENTS.get(direction);
|
||||||
|
movement.move(this.pelouse, this.tondeuse);
|
||||||
|
pelouseView.displayTondeuseMove(initial_position, tondeuse.getPosition(), movement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Orientation;
|
||||||
|
import com.qrouland.katatondeuse.model.Position;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
|
||||||
|
public class MovementAhead implements MovementStrategy {
|
||||||
|
/**
|
||||||
|
* Moves the {@link Tondeuse} one step ahead in the direction of its current orientation.
|
||||||
|
*
|
||||||
|
* @param pelouse The {@link Pelouse} on which the {@link Tondeuse} operates.
|
||||||
|
* @param tondeuse The {@link Tondeuse} to be moved.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void move(Pelouse pelouse, Tondeuse tondeuse) {
|
||||||
|
Position current = tondeuse.getPosition();
|
||||||
|
int x = current.getX();
|
||||||
|
int y = current.getY();
|
||||||
|
Orientation orientation = current.getOrientation();
|
||||||
|
|
||||||
|
switch (orientation) {
|
||||||
|
case N -> y += 1;
|
||||||
|
case S -> y -= 1;
|
||||||
|
case E -> x += 1;
|
||||||
|
case W -> x -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x >= 0 && x <= pelouse.getMaxX() && y >= 0 && y <= pelouse.getMaxY()) {
|
||||||
|
tondeuse.setPosition(new Position(x, y, orientation));
|
||||||
|
} else {
|
||||||
|
System.err.println("Move ignored: out of grid bounds.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Orientation;
|
||||||
|
import com.qrouland.katatondeuse.model.Position;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
|
||||||
|
public class MovementLeft implements MovementStrategy {
|
||||||
|
/**
|
||||||
|
* Rotates the {@link Tondeuse} 90 degrees to the left.
|
||||||
|
*
|
||||||
|
* @param pelouse The {@link Pelouse} on which the {@link Tondeuse} operates.
|
||||||
|
* @param tondeuse The {@link Tondeuse} to be moved.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void move(Pelouse pelouse, Tondeuse tondeuse) {
|
||||||
|
Position position = tondeuse.getPosition();
|
||||||
|
Orientation new_orientation = switch (position.getOrientation()) {
|
||||||
|
case N -> Orientation.W;
|
||||||
|
case W -> Orientation.S;
|
||||||
|
case S -> Orientation.E;
|
||||||
|
case E -> Orientation.N;
|
||||||
|
};
|
||||||
|
|
||||||
|
tondeuse.setPosition(new Position(position.getX(), position.getY(), new_orientation));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Orientation;
|
||||||
|
import com.qrouland.katatondeuse.model.Position;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
|
||||||
|
public class MovementRight implements MovementStrategy {
|
||||||
|
/**
|
||||||
|
* Rotates the {@link Tondeuse} 90 degrees to the right.
|
||||||
|
*
|
||||||
|
* @param pelouse The {@link Pelouse} on which the {@link Tondeuse} operates.
|
||||||
|
* @param tondeuse The {@link Tondeuse} to be moved.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void move(Pelouse pelouse, Tondeuse tondeuse) {
|
||||||
|
Position position = tondeuse.getPosition();
|
||||||
|
Orientation new_orientation = switch (position.getOrientation()) {
|
||||||
|
case N -> Orientation.E;
|
||||||
|
case E -> Orientation.S;
|
||||||
|
case S -> Orientation.W;
|
||||||
|
case W -> Orientation.N;
|
||||||
|
};
|
||||||
|
tondeuse.setPosition(new Position(position.getX(), position.getY(), new_orientation));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
|
||||||
|
public interface MovementStrategy {
|
||||||
|
/**
|
||||||
|
* Executes a movement of a {@link Tondeuse} on the {@link Pelouse}.
|
||||||
|
*
|
||||||
|
* @param pelouse The {@link Pelouse} on which the {@link Tondeuse} operates.
|
||||||
|
* @param tondeuse The {@link Tondeuse} to be moved.
|
||||||
|
*/
|
||||||
|
void move(Pelouse pelouse, Tondeuse tondeuse);
|
||||||
|
}
|
20
src/main/java/com/qrouland/katatondeuse/model/Direction.java
Normal file
20
src/main/java/com/qrouland/katatondeuse/model/Direction.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Three directions for moving a {@link Tondeuse} using a {@link com.qrouland.katatondeuse.controller.movement.MovementStrategy} .
|
||||||
|
*/
|
||||||
|
public enum Direction {
|
||||||
|
D, // Droite (droite)
|
||||||
|
G, // Gauche (left)
|
||||||
|
A; // Avance (ahead)
|
||||||
|
|
||||||
|
public static Direction fromChar(char c) {
|
||||||
|
return switch (c) {
|
||||||
|
case 'A' -> A;
|
||||||
|
case 'G' -> G;
|
||||||
|
case 'D' -> D;
|
||||||
|
default -> throw new IllegalArgumentException("Invalid direction character: " + c);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Four cardinal directions for orientations of the {@link Tondeuse}.
|
||||||
|
*/
|
||||||
|
public enum Orientation {
|
||||||
|
N, // North
|
||||||
|
E, // East
|
||||||
|
W, // West
|
||||||
|
S; // South
|
||||||
|
|
||||||
|
public static Orientation fromChar(char c) {
|
||||||
|
return switch (c) {
|
||||||
|
case 'N' -> N;
|
||||||
|
case 'E' -> E;
|
||||||
|
case 'S' -> S;
|
||||||
|
case 'W' -> W;
|
||||||
|
default -> throw new IllegalArgumentException("Invalid orientation character: " + c);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
47
src/main/java/com/qrouland/katatondeuse/model/Pelouse.java
Normal file
47
src/main/java/com/qrouland/katatondeuse/model/Pelouse.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a pelouse (lawn) on which {@link Tondeuse} (mowers) operate.
|
||||||
|
*/
|
||||||
|
public class Pelouse {
|
||||||
|
private final int maxX;
|
||||||
|
private final int maxY;
|
||||||
|
|
||||||
|
private final List<Tondeuse> tondeuses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Pelouse.
|
||||||
|
*
|
||||||
|
* @param maxX the max x coordinate.
|
||||||
|
* @param maxY the max x coordinate.
|
||||||
|
*/
|
||||||
|
public Pelouse(int maxX, int maxY) {
|
||||||
|
this.maxX = maxX;
|
||||||
|
this.maxY = maxY;
|
||||||
|
this.tondeuses = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxX() {
|
||||||
|
return maxX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxY() {
|
||||||
|
return maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Tondeuse> getTondeuses() {
|
||||||
|
return tondeuses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTondeuse(Tondeuse tondeuse) {
|
||||||
|
this.tondeuses.add(tondeuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Pelouse{maxX=%d, maxY=%d, tondeuses=%s}", maxX, maxY, tondeuses);
|
||||||
|
}
|
||||||
|
}
|
41
src/main/java/com/qrouland/katatondeuse/model/Position.java
Normal file
41
src/main/java/com/qrouland/katatondeuse/model/Position.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the position of a {@link Tondeuse} on a 2D grid (x,y) and its
|
||||||
|
* orientation (N, E, S, W).
|
||||||
|
*/
|
||||||
|
public class Position {
|
||||||
|
private final int x;
|
||||||
|
private final int y;
|
||||||
|
private final Orientation orientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Position.
|
||||||
|
*
|
||||||
|
* @param x the x coordinate.
|
||||||
|
* @param y the y coordinate.
|
||||||
|
* @param orientation the orientation (N, E, S, W).
|
||||||
|
*/
|
||||||
|
public Position(int x, int y, Orientation orientation) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.orientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Orientation getOrientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%d %d %s", x, y, orientation.toString());
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/com/qrouland/katatondeuse/model/Tondeuse.java
Normal file
30
src/main/java/com/qrouland/katatondeuse/model/Tondeuse.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Tondeuse (mower) with a current {@link Position} on a 2D grid.
|
||||||
|
*/
|
||||||
|
public class Tondeuse {
|
||||||
|
private Position position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Tondeuse at the given position.
|
||||||
|
*
|
||||||
|
* @param position the initial position of the Tondeuse.
|
||||||
|
*/
|
||||||
|
public Tondeuse(Position position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(Position position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Tondeuse { position = %s }", position.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.qrouland.katatondeuse.parser;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FileInputParser {
|
||||||
|
/**
|
||||||
|
* Parse instructions for a {@link Tondeuse} initial position and its movement instructions.
|
||||||
|
*
|
||||||
|
* @param positionLine string representing the {@link Tondeuse} initial position.
|
||||||
|
* @param instructionsLine string representing movement instructions.
|
||||||
|
* @return An ImmutablePair of {@link Tondeuse} and {@link Direction}.
|
||||||
|
*/
|
||||||
|
public static ImmutablePair<Tondeuse, List<Direction>> parseTondeuseInstructions(
|
||||||
|
String positionLine, String instructionsLine) {
|
||||||
|
if (!positionLine.matches("^\\d+ \\d+ [NESW]$")) {
|
||||||
|
throw new IllegalArgumentException("Invalid tondeuse position format : " + positionLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instructionsLine.matches("^[AGD]+$")) {
|
||||||
|
throw new IllegalArgumentException("Invalid tondeuse instruction format : " + instructionsLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = positionLine.split(" ");
|
||||||
|
int x = Integer.parseInt(parts[0]);
|
||||||
|
int y = Integer.parseInt(parts[1]);
|
||||||
|
Orientation orientation = Orientation.fromChar(parts[2].charAt(0));
|
||||||
|
|
||||||
|
List<Direction> directions = new ArrayList<>();
|
||||||
|
for (char c : instructionsLine.toCharArray()) {
|
||||||
|
directions.add(Direction.fromChar(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(x, y, orientation));
|
||||||
|
return new ImmutablePair<>(tondeuse, directions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a line to instantiate a {@link Pelouse}.
|
||||||
|
*
|
||||||
|
* @param line The line of the pelouse definition to parse.
|
||||||
|
* @return a Pelouse of the correct format.
|
||||||
|
*/
|
||||||
|
public static Pelouse parsePelouseDefinition(String line) {
|
||||||
|
String pattern = "^\\d+ \\d+$";
|
||||||
|
|
||||||
|
if (!line.matches(pattern)) {
|
||||||
|
throw new IllegalArgumentException("Invalid Pelouse size format: " + line);
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = line.split(" ");
|
||||||
|
int xMax = Integer.parseInt(parts[0]);
|
||||||
|
int yMax = Integer.parseInt(parts[1]);
|
||||||
|
|
||||||
|
return new Pelouse(xMax, yMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the input arguments to retrieve the input file.
|
||||||
|
*
|
||||||
|
* @param args cli args.
|
||||||
|
* @return a File object representing the input file.
|
||||||
|
* @throws IllegalArgumentException if no arguments provided or the file does not exist.
|
||||||
|
*/
|
||||||
|
public static File parseInputFile(String[] args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
throw new IllegalArgumentException("Missing input file argument.");
|
||||||
|
}
|
||||||
|
|
||||||
|
File inputFile = new File(args[0]);
|
||||||
|
|
||||||
|
if (!inputFile.exists()) {
|
||||||
|
throw new IllegalArgumentException("File does not exist: " + args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputFile;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.qrouland.katatondeuse.view;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementStrategy;
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Position;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
|
||||||
|
public class ConsolePelouseView implements PelouseView {
|
||||||
|
/**
|
||||||
|
* Displays the current state of the {@link Pelouse}, including the positions of all {@link Tondeuse}.
|
||||||
|
*
|
||||||
|
* @param pelouse The {@link Pelouse} to be displayed.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void displayPelouseState(Pelouse pelouse) {
|
||||||
|
System.out.printf("Pelouse %d x %d : ", pelouse.getMaxX(), pelouse.getMaxY());
|
||||||
|
for (int i = 0; i < pelouse.getTondeuses().size(); i++) {
|
||||||
|
Tondeuse tondeuse = pelouse.getTondeuses().get(i);
|
||||||
|
System.out.print(tondeuse.getPosition());
|
||||||
|
if (i < pelouse.getTondeuses().size() - 1) {
|
||||||
|
System.out.print(" | ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a message indicating a new {@link Tondeuse} has been added.
|
||||||
|
*
|
||||||
|
* @param tondeuse The {@link Tondeuse} that was added.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void displayTondeuseAdd(Tondeuse tondeuse) {
|
||||||
|
System.out.printf("Added : %s%n", tondeuse.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a message indicating a {@link Tondeuse} has moved from its origin to its destination.
|
||||||
|
*
|
||||||
|
* @param origin The original position of the {@link Tondeuse}.
|
||||||
|
* @param destination The new position of the {@link Tondeuse}.
|
||||||
|
* @param movement The {@link MovementStrategy} used for the movement.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void displayTondeuseMove(Position origin, Position destination, MovementStrategy movement) {
|
||||||
|
System.out.printf("Moved : %s to %s using %s%n", origin, destination, movement.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays an error message.
|
||||||
|
*
|
||||||
|
* @param message The error message.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void displayError(String message) {
|
||||||
|
System.err.println(message);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.qrouland.katatondeuse.view;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementStrategy;
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Position;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
|
||||||
|
public interface PelouseView {
|
||||||
|
/**
|
||||||
|
* Displays the current state of the {@link Pelouse}, including the positions of all {@link Tondeuse}.
|
||||||
|
*
|
||||||
|
* @param pelouse The {@link Pelouse} to be displayed.
|
||||||
|
*/
|
||||||
|
void displayPelouseState(Pelouse pelouse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a message indicating a new {@link Tondeuse} has been added.
|
||||||
|
*
|
||||||
|
* @param tondeuse The {@link Tondeuse} that was added.
|
||||||
|
*/
|
||||||
|
void displayTondeuseAdd(Tondeuse tondeuse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a message indicating a {@link Tondeuse} has moved from its origin {@link Position} to its destination {@link Position}.
|
||||||
|
*
|
||||||
|
* @param origin The original {@link Position} of the {@link Tondeuse}.
|
||||||
|
* @param destination The new {@link Position} of the {@link Tondeuse}.
|
||||||
|
* @param movement The {@link MovementStrategy} used for the movement.
|
||||||
|
*/
|
||||||
|
void displayTondeuseMove(Position origin, Position destination, MovementStrategy movement);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays an error message.
|
||||||
|
*
|
||||||
|
* @param message The error message.
|
||||||
|
*/
|
||||||
|
void displayError(String message);
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
import com.qrouland.katatondeuse.view.PelouseView;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TontePelouseControllerTest {
|
||||||
|
|
||||||
|
private PelouseView pelouseViewMock;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
pelouseViewMock = mock(PelouseView.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRun() throws IOException {
|
||||||
|
String fileContent = """
|
||||||
|
5 5
|
||||||
|
1 2 N
|
||||||
|
GAGAGAGAA
|
||||||
|
3 3 E
|
||||||
|
AADAADADDA
|
||||||
|
""";
|
||||||
|
|
||||||
|
File tempFile = File.createTempFile("testInstructions", ".txt");
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
|
||||||
|
try (BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))) {
|
||||||
|
writer.write(fileContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
TontePelouseController controller = new TontePelouseController(tempFile, pelouseViewMock);
|
||||||
|
controller.run();
|
||||||
|
|
||||||
|
verify(pelouseViewMock, atLeastOnce()).displayPelouseState(any(Pelouse.class));
|
||||||
|
verify(pelouseViewMock, atLeastOnce()).displayTondeuseAdd(any(Tondeuse.class));
|
||||||
|
|
||||||
|
ArgumentCaptor<Tondeuse> tondeuseCaptor = ArgumentCaptor.forClass(Tondeuse.class);
|
||||||
|
verify(pelouseViewMock, atLeastOnce()).displayTondeuseAdd(tondeuseCaptor.capture());
|
||||||
|
|
||||||
|
List<Tondeuse> addedTondeuses = tondeuseCaptor.getAllValues();
|
||||||
|
assertEquals(2, addedTondeuses.size());
|
||||||
|
|
||||||
|
assertEquals(1, addedTondeuses.get(0).getPosition().getX());
|
||||||
|
assertEquals(3, addedTondeuses.get(0).getPosition().getY());
|
||||||
|
assertEquals(com.qrouland.katatondeuse.model.Orientation.N, addedTondeuses.get(0).getPosition().getOrientation());
|
||||||
|
|
||||||
|
assertEquals(5, addedTondeuses.get(1).getPosition().getX());
|
||||||
|
assertEquals(1, addedTondeuses.get(1).getPosition().getY());
|
||||||
|
assertEquals(com.qrouland.katatondeuse.model.Orientation.E, addedTondeuses.get(1).getPosition().getOrientation());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementStrategy;
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import com.qrouland.katatondeuse.view.PelouseView;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TonteTondeuseControllerTest {
|
||||||
|
|
||||||
|
private Pelouse pelouse;
|
||||||
|
private Tondeuse tondeuse;
|
||||||
|
private PelouseView pelouseView;
|
||||||
|
private TonteTondeuseController controller;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
pelouse = new Pelouse(5, 5);
|
||||||
|
Position initialPosition = new Position(1, 2, Orientation.N);
|
||||||
|
tondeuse = new Tondeuse(initialPosition);
|
||||||
|
pelouseView = mock(PelouseView.class);
|
||||||
|
controller = new TonteTondeuseController(tondeuse, pelouse, pelouseView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExecuteInstructions() {
|
||||||
|
List<Direction> instructions = List.of(Direction.A, Direction.D, Direction.G);
|
||||||
|
|
||||||
|
controller.executeInstructions(instructions);
|
||||||
|
|
||||||
|
verify(pelouseView, times(3))
|
||||||
|
.displayTondeuseMove(any(Position.class), any(Position.class), any(MovementStrategy.class));
|
||||||
|
Position finalPosition = tondeuse.getPosition();
|
||||||
|
assertEquals("1 3 N", finalPosition.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
|
||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class MovementAheadTest {
|
||||||
|
private MovementAhead movementAhead;
|
||||||
|
private Pelouse pelouse;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
movementAhead = new MovementAhead();
|
||||||
|
pelouse = new Pelouse(5, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void moveNorth() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 2, Orientation.N));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(2, pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.N, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void moveSouth() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 2, Orientation.S));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(2, pos.getX());
|
||||||
|
assertEquals(1, pos.getY());
|
||||||
|
assertEquals(Orientation.S, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void moveEast() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 2, Orientation.E));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(3, pos.getX());
|
||||||
|
assertEquals(2, pos.getY());
|
||||||
|
assertEquals(Orientation.E, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void moveWest() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 2, Orientation.W));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(1, pos.getX());
|
||||||
|
assertEquals(2, pos.getY());
|
||||||
|
assertEquals(Orientation.W, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void move_OutOfBounds_MaxY() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(3, pelouse.getMaxY(), Orientation.N));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(3, pos.getX());
|
||||||
|
assertEquals(pelouse.getMaxY(), pos.getY());
|
||||||
|
assertEquals(Orientation.N, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void move_OutOfBounds_MaxX() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(pelouse.getMaxX(), 3, Orientation.E));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(pelouse.getMaxX(), pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.E, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void move_OutOfBounds_MinY() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(3, 0, Orientation.S));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(3, pos.getX());
|
||||||
|
assertEquals(0, pos.getY());
|
||||||
|
assertEquals(Orientation.S, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void mov_OutOfBounds_MinX() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(0, 3, Orientation.W));
|
||||||
|
movementAhead.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(0, pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.W, pos.getOrientation());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MovementLeftTest {
|
||||||
|
private MovementLeft movementLeft;
|
||||||
|
private Pelouse pelouse;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
movementLeft = new MovementLeft();
|
||||||
|
pelouse = new Pelouse(5, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnLeftFromNorth() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 3, Orientation.N));
|
||||||
|
movementLeft.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(2, pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.W, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnLeftFromWest() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 3, Orientation.W));
|
||||||
|
movementLeft.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(2, pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.S, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnLeftFromSouth() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 3, Orientation.S));
|
||||||
|
movementLeft.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(2, pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.E, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnLeftFromEast() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 3, Orientation.E));
|
||||||
|
movementLeft.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(2, pos.getX());
|
||||||
|
assertEquals(3, pos.getY());
|
||||||
|
assertEquals(Orientation.N, pos.getOrientation());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.qrouland.katatondeuse.controller.movement;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class MovementRightTest {
|
||||||
|
private MovementRight movementRight;
|
||||||
|
private Pelouse pelouse;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
movementRight = new MovementRight();
|
||||||
|
pelouse = new Pelouse(5, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnRightFromNorth() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(1, 1, Orientation.N));
|
||||||
|
movementRight.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(1, pos.getX());
|
||||||
|
assertEquals(1, pos.getY());
|
||||||
|
assertEquals(Orientation.E, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnRightFromEast() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(1, 1, Orientation.E));
|
||||||
|
movementRight.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(1, pos.getX());
|
||||||
|
assertEquals(1, pos.getY());
|
||||||
|
assertEquals(Orientation.S, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnRightFromSouth() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(1, 1, Orientation.S));
|
||||||
|
movementRight.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(1, pos.getX());
|
||||||
|
assertEquals(1, pos.getY());
|
||||||
|
assertEquals(Orientation.W, pos.getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTurnRightFromWest() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(1, 1, Orientation.W));
|
||||||
|
movementRight.move(pelouse, tondeuse);
|
||||||
|
|
||||||
|
Position pos = tondeuse.getPosition();
|
||||||
|
assertEquals(1, pos.getX());
|
||||||
|
assertEquals(1, pos.getY());
|
||||||
|
assertEquals(Orientation.N, pos.getOrientation());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class DirectionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromChar() {
|
||||||
|
assertEquals(Direction.A, Direction.fromChar('A'));
|
||||||
|
assertEquals(Direction.G, Direction.fromChar('G'));
|
||||||
|
assertEquals(Direction.D, Direction.fromChar('D'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromChar_invalidCharacter() {
|
||||||
|
Exception exception = assertThrows(IllegalArgumentException.class, () -> Direction.fromChar('X'));
|
||||||
|
assertEquals("Invalid direction character: X", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromChar_lowercaseInput() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Direction.fromChar('a'));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Direction.fromChar('g'));
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Direction.fromChar('d'));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class OrientationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromChar() {
|
||||||
|
assertEquals(Orientation.N, Orientation.fromChar('N'));
|
||||||
|
assertEquals(Orientation.E, Orientation.fromChar('E'));
|
||||||
|
assertEquals(Orientation.S, Orientation.fromChar('S'));
|
||||||
|
assertEquals(Orientation.W, Orientation.fromChar('W'));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromChar_invalidCharacter() {
|
||||||
|
Exception exception = assertThrows(IllegalArgumentException.class, () -> Orientation.fromChar('X'));
|
||||||
|
assertEquals("Invalid orientation character: X", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFromChar_lowercaseInput() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> Orientation.fromChar('n'));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class PelouseTest {
|
||||||
|
|
||||||
|
private Pelouse pelouse;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
pelouse = new Pelouse(5, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAddTondeuseAndGetTondeuses() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(1, 2, Orientation.N));
|
||||||
|
|
||||||
|
pelouse.addTondeuse(tondeuse);
|
||||||
|
List<Tondeuse> tondeuses = pelouse.getTondeuses();
|
||||||
|
|
||||||
|
assertEquals(1, tondeuses.size());
|
||||||
|
assertSame(tondeuse, tondeuses.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetTondeuses() {
|
||||||
|
assertTrue(pelouse.getTondeuses().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetMaxX_returnsCorrectValue() {
|
||||||
|
Pelouse pelouse = new Pelouse(10, 7);
|
||||||
|
|
||||||
|
assertEquals(10, pelouse.getMaxX());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetMaxY_returnsCorrectValue() {
|
||||||
|
Pelouse pelouse = new Pelouse(10, 7);
|
||||||
|
|
||||||
|
assertEquals(7, pelouse.getMaxY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testToString() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(3, 4, Orientation.E));
|
||||||
|
pelouse.addTondeuse(tondeuse);
|
||||||
|
|
||||||
|
String result = pelouse.toString();
|
||||||
|
|
||||||
|
assertTrue(result.contains("maxX=5"));
|
||||||
|
assertTrue(result.contains("maxY=5"));
|
||||||
|
assertTrue(result.contains("Tondeuse { position ="));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class PositionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPositionToString() {
|
||||||
|
Position position = new Position(0, 0, Orientation.S);
|
||||||
|
String expected = "0 0 S";
|
||||||
|
assertEquals(expected, position.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.qrouland.katatondeuse.model;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class TondeuseTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPositionGetter() {
|
||||||
|
Position position = new Position(1, 2, Orientation.N);
|
||||||
|
Tondeuse tondeuse = new Tondeuse(position);
|
||||||
|
|
||||||
|
assertEquals(position, tondeuse.getPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSetPosition() {
|
||||||
|
|
||||||
|
Position initialPosition = new Position(1, 2, Orientation.N);
|
||||||
|
Tondeuse tondeuse = new Tondeuse(initialPosition);
|
||||||
|
|
||||||
|
Position newPosition = new Position(3, 4, Orientation.E);
|
||||||
|
tondeuse.setPosition(newPosition);
|
||||||
|
|
||||||
|
assertEquals(newPosition, tondeuse.getPosition());
|
||||||
|
assertEquals(3, tondeuse.getPosition().getX());
|
||||||
|
assertEquals(4, tondeuse.getPosition().getY());
|
||||||
|
assertEquals(Orientation.E, tondeuse.getPosition().getOrientation());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testTondeuseToString() {
|
||||||
|
Position position = new Position(3, 4, Orientation.E);
|
||||||
|
Tondeuse tondeuse = new Tondeuse(position);
|
||||||
|
|
||||||
|
String expected = "Tondeuse { position = 3 4 E }";
|
||||||
|
assertEquals(expected, tondeuse.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.qrouland.katatondeuse;
|
||||||
|
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.model.Direction;
|
||||||
|
import com.qrouland.katatondeuse.model.Orientation;
|
||||||
|
import com.qrouland.katatondeuse.model.Pelouse;
|
||||||
|
import com.qrouland.katatondeuse.model.Tondeuse;
|
||||||
|
import com.qrouland.katatondeuse.parser.FileInputParser;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class FileInputParserTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParseTondeuseInstructions_validInput() {
|
||||||
|
String position = "1 2 N";
|
||||||
|
String instructions = "AGAD";
|
||||||
|
|
||||||
|
ImmutablePair<Tondeuse, List<Direction>> result = FileInputParser.parseTondeuseInstructions(position, instructions);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1, result.left.getPosition().getX());
|
||||||
|
assertEquals(2, result.left.getPosition().getY());
|
||||||
|
assertEquals(Orientation.N, result.left.getPosition().getOrientation());
|
||||||
|
|
||||||
|
assertEquals(List.of(Direction.A, Direction.G, Direction.A, Direction.D), result.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParseTondeuseInstructions_invalidPositionFormat() {
|
||||||
|
String invalidPosition = "1 N 2";
|
||||||
|
String instructions = "AGAD";
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
FileInputParser.parseTondeuseInstructions(invalidPosition, instructions));
|
||||||
|
assertEquals("Invalid tondeuse position format : " + invalidPosition, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParseTondeuseInstructions_invalidInstructionsFormat() {
|
||||||
|
String position = "1 2 N";
|
||||||
|
String invalidInstructions = "AGZRA";
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
FileInputParser.parseTondeuseInstructions(position, invalidInstructions));
|
||||||
|
|
||||||
|
assertEquals("Invalid tondeuse instruction format : " + invalidInstructions, exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParsePelouseDefinition_ValidInput() {
|
||||||
|
Pelouse pelouse = FileInputParser.parsePelouseDefinition("5 5");
|
||||||
|
|
||||||
|
assertNotNull(pelouse);
|
||||||
|
assertEquals(5, pelouse.getMaxX());
|
||||||
|
assertEquals(5, pelouse.getMaxY());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testParsePelouseDefinition_InvalidInput() {
|
||||||
|
String invalidLine = "5x5";
|
||||||
|
|
||||||
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () ->
|
||||||
|
FileInputParser.parsePelouseDefinition(invalidLine));
|
||||||
|
|
||||||
|
assertTrue(exception.getMessage().contains("Invalid Pelouse size format"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInputParserFile_ValidInputFile() throws IOException {
|
||||||
|
File tempFile = File.createTempFile("test", ".txt");
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
|
||||||
|
String[] args = { tempFile.getAbsolutePath() };
|
||||||
|
File result = FileInputParser.parseInputFile(args);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertTrue(result.exists());
|
||||||
|
assertEquals(tempFile.getAbsolutePath(), result.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFileInputParser_MissingArgument() {
|
||||||
|
String[] args = {};
|
||||||
|
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
FileInputParser.parseInputFile(args);
|
||||||
|
});
|
||||||
|
assertEquals("Missing input file argument.", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testFileInputParser_NonExistentFile() {
|
||||||
|
String[] args = { "nonexistentfile.txt" };
|
||||||
|
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
|
||||||
|
FileInputParser.parseInputFile(args);
|
||||||
|
});
|
||||||
|
assertEquals("File does not exist: nonexistentfile.txt", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.qrouland.katatondeuse.view;
|
||||||
|
|
||||||
|
import com.qrouland.katatondeuse.controller.movement.MovementAhead;
|
||||||
|
import com.qrouland.katatondeuse.model.*;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class ConsolePelouseViewTest {
|
||||||
|
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
|
||||||
|
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
|
||||||
|
private final PrintStream originalOut = System.out;
|
||||||
|
private final PrintStream originalErr = System.err;
|
||||||
|
|
||||||
|
private final ConsolePelouseView view = new ConsolePelouseView();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUpStreams() {
|
||||||
|
System.setOut(new PrintStream(outContent));
|
||||||
|
System.setErr(new PrintStream(errContent));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void restoreStreams() {
|
||||||
|
System.setOut(originalOut);
|
||||||
|
System.setErr(originalErr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDisplayPelouseState() {
|
||||||
|
Pelouse pelouse = new Pelouse(3, 3);
|
||||||
|
pelouse.addTondeuse(new Tondeuse(new Position(0, 0, Orientation.S)));
|
||||||
|
pelouse.addTondeuse(new Tondeuse(new Position(2, 2, Orientation.E)));
|
||||||
|
|
||||||
|
view.displayPelouseState(pelouse);
|
||||||
|
|
||||||
|
String output = outContent.toString().trim();
|
||||||
|
assertTrue(output.contains("Pelouse 3 x 3"));
|
||||||
|
assertTrue(output.contains("0 0 S | 2 2 E"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDisplayTondeuseAdd() {
|
||||||
|
Tondeuse tondeuse = new Tondeuse(new Position(2, 3, Orientation.E));
|
||||||
|
|
||||||
|
view.displayTondeuseAdd(tondeuse);
|
||||||
|
|
||||||
|
String output = outContent.toString().trim();
|
||||||
|
assertTrue(output.contains("Added"));
|
||||||
|
assertTrue(output.contains("2 3 E"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDisplayTondeuseMove() {
|
||||||
|
Position origin = new Position(1, 1, Orientation.N);
|
||||||
|
Position destination = new Position(1, 2, Orientation.N);
|
||||||
|
MovementAhead movement = new MovementAhead();
|
||||||
|
|
||||||
|
view.displayTondeuseMove(origin, destination, movement);
|
||||||
|
|
||||||
|
String output = outContent.toString().trim();
|
||||||
|
assertTrue(output.contains("Moved"));
|
||||||
|
assertTrue(output.contains("1 1 N"));
|
||||||
|
assertTrue(output.contains("1 2 N"));
|
||||||
|
assertTrue(output.contains("MovementAhead"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDisplayError() {
|
||||||
|
view.displayError("Test error message");
|
||||||
|
|
||||||
|
String output = errContent.toString().trim();
|
||||||
|
assertEquals("Test error message", output);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user