diff --git a/.run/Rover [check].run.xml b/.run/Rover [check].run.xml new file mode 100644 index 0000000..f18c25b --- /dev/null +++ b/.run/Rover [check].run.xml @@ -0,0 +1,24 @@ + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/.run/Rover [detekt ktlintCheck].run.xml b/.run/Rover [detekt ktlintCheck].run.xml new file mode 100644 index 0000000..8d0aa2c --- /dev/null +++ b/.run/Rover [detekt ktlintCheck].run.xml @@ -0,0 +1,25 @@ + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/.run/Rover [test].run.xml b/.run/Rover [test].run.xml new file mode 100644 index 0000000..2ca8fb6 --- /dev/null +++ b/.run/Rover [test].run.xml @@ -0,0 +1,24 @@ + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/02_OrangeBelt.v.2.1.pdf b/02_OrangeBelt.v.2.1.pdf new file mode 100644 index 0000000..4ebcbfb Binary files /dev/null and b/02_OrangeBelt.v.2.1.pdf differ diff --git a/README.md b/README.md index 71122aa..75bfc1e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ -# Rover +# ๐Ÿ›ฐ๏ธ Mars Rover ![Build](https://github.com/appsoluut/dojo-mars-rover/actions/workflows/ci.yml/badge.svg) [![codecov](https://codecov.io/gh/appsoluut/dojo-mars-rover/branch/main/graph/badge.svg)](https://codecov.io/gh/appsoluut/dojo-mars-rover) [![DeepSource](https://app.deepsource.com/gh/appsoluut/dojo-mars-rover.svg/?label=code+coverage&show_trend=true&token=UmCazOJ6A2-UkVOMKafStlYo)](https://app.deepsource.com/gh/appsoluut/dojo-mars-rover/) [![DeepSource](https://app.deepsource.com/gh/appsoluut/dojo-mars-rover.svg/?label=active+issues&show_trend=true&token=UmCazOJ6A2-UkVOMKafStlYo)](https://app.deepsource.com/gh/appsoluut/dojo-mars-rover/) [![DeepSource](https://app.deepsource.com/gh/appsoluut/dojo-mars-rover.svg/?label=resolved+issues&show_trend=true&token=UmCazOJ6A2-UkVOMKafStlYo)](https://app.deepsource.com/gh/appsoluut/dojo-mars-rover/) -A Kotlin project bootstrapped with **Gradle**, **Detekt**, **Ktlint**, **JUnit**, and **JaCoCo**. - ## ๐Ÿš€ Features - ๐Ÿ”ง Gradle wrapper included @@ -26,11 +24,98 @@ cd Rover # Run Detekt and Ktlint checks ./gradlew detekt ktlintCheck - -# Run -./gradlew run ``` -# License +## Problem -MIT - feel free to use and modify. +NASA is landing a robotic rover on a rectangular plateau on Mars. +This plateau must be explored systematically so that the roverโ€™s on-board cameras can survey the terrain and send images back to Earth. + +A roverโ€™s position is represented by: +- Two integers (**X**, **Y**) indicating its coordinates, and +- A letter indicating its current heading: + - **N** (North) + - **E** (East) + - **S** (South) + - **W** (West) + +The plateau is divided into a grid, and the rover moves across it based on simple navigation commands. + +For example, a position of `0 0 N` means the rover is at the bottom-left corner, facing North. + +--- + +## Instructions + +NASA can send the following commands to the rover: + +- `L` โž” Turn 90 degrees **left** without moving from the current spot. +- `R` โž” Turn 90 degrees **right** without moving from the current spot. +- `M` โž” Move **forward** one grid point in the direction it is facing. + +> **Important**: +> Moving North from `(x, y)` goes to `(x, y+1)`. +> Moving East from `(x, y)` goes to `(x+1, y)`, and so on. + +--- + +## Input + +The input consists of: + +1. **First parameter**: The roverโ€™s **starting position**: two integers and a letter (e.g., `1 2 N`). + +2. **Second parameter**: A string of **movement instructions** (e.g., `LMLMLMLMM`). + +The rover processes all instructions in sequence. + +--- + +## Output + +After executing all the commands, the rover reports its **final coordinates and heading**. + +--- + +## Example + +| Starting Position | Instructions | Expected Output | +|:------------------|:-------------|:----------------| +| 1 2 N | | 1 2 N | +| 1 2 N | L | 1 2 W | +| 1 2 W | L | 1 2 S | +| 1 2 S | L | 1 2 E | +| 1 2 E | L | 1 2 N | +| 1 2 N | R | 1 2 E | +| 1 2 E | R | 1 2 S | +| 1 2 S | R | 1 2 W | +| 1 2 W | R | 1 2 N | +| 1 2 N | M | 1 3 N | +| 1 2 E | M | 2 2 E | +| 1 2 S | M | 1 1 S | +| 1 2 W | M | 0 2 W | +| 1 2 N | LMLMLMLMM | 1 3 N | +| 3 3 E | MMRMMRMRRM | 5 1 E | + +--- + +# ๐ŸŽฏ Your Mission + +You have been given a **working but fragile** codebase that controls a **single** rover. + +Your goal: +- **Refactor** the code to make it clean, expressive, and easy to maintain. +- Prepare the code for **future enhancements**. +- Eliminate technical debt, improve readability, and structure it to allow **easily adding new features** later. + +> ๐Ÿง  **Hint**: +> Future missions may require **handling multiple rovers** at once. +> Your design should naturally evolve toward making this possible. + +โœ… **Do not change the existing behavior.** +โœ… **All existing tests must continue to pass.** + +--- + +# ๐ŸŒŸ Good luck, engineer of Mars! +Craft code that's ready for exploration... and evolution! ๐Ÿš€ diff --git a/TECHDEBT.md b/TECHDEBT.md new file mode 100644 index 0000000..2693455 --- /dev/null +++ b/TECHDEBT.md @@ -0,0 +1,5 @@ +# TODO +- [ ] Make ktlint pass checks + +# RPP +- [ ] ... \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index a7dc9fd..f24e667 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } application { - mainClass.set("MainKt") + mainClass.set("RoverKt") } repositories { diff --git a/src/main/kotlin/Main.kt b/src/main/kotlin/Main.kt deleted file mode 100644 index 5dbce6a..0000000 --- a/src/main/kotlin/Main.kt +++ /dev/null @@ -1,3 +0,0 @@ -fun main() { - println("Hello, Kotlin CI/CD world!") -} diff --git a/src/main/kotlin/Rover.kt b/src/main/kotlin/Rover.kt new file mode 100644 index 0000000..15fc851 --- /dev/null +++ b/src/main/kotlin/Rover.kt @@ -0,0 +1,43 @@ +package org.example + +class Rover { + constructor(p: String) { + val s = p.split(' ') + if (s.size >= 3) { + rs.xx = s[0].toInt() + rs.yy = s[1].toInt() + rs.dd = s[2][0] + } + } + + fun go(cms: String) { + for (c in cms) { + when (c) { + 'L' -> { when (rs.dd) { 'E' -> rs.dd = 'N' 'N' -> rs.dd = 'W' 'W' -> rs.dd = 'S' 'S' -> rs.dd = 'E'}} + 'R' -> { when (rs.dd) { 'E' -> rs.dd = 'S' 'S' -> rs.dd = 'W' 'W' -> rs.dd = 'N' 'N' -> rs.dd = 'E'}} + 'M' -> { when (rs.dd) { 'E' -> rs.xx++ 'S' -> rs.yy-- 'W' -> rs.xx-- 'N' -> rs.yy++}} + } + } + } + + fun g(z: Char) { + go(z.toString()) + } + + val xyd: String + get() = "${rs.xx} ${rs.yy} ${rs.dd}" + + fun pos(): String { + return xyd + } + + constructor() : this("") + + private var rs = RoverState() +} + +class RoverState { + var xx: Int = 0 + var yy: Int = 0 + var dd: Char = 'N' +} diff --git a/src/test/kotlin/MainTest.kt b/src/test/kotlin/MainTest.kt deleted file mode 100644 index 3f2d238..0000000 --- a/src/test/kotlin/MainTest.kt +++ /dev/null @@ -1,10 +0,0 @@ -import kotlin.test.Test -import kotlin.test.assertEquals - -class MainTest { - @Test - fun testExample() { - val result = 2 + 2 - assertEquals(4, result) - } -} diff --git a/src/test/kotlin/MarsRoverTests.kt b/src/test/kotlin/MarsRoverTests.kt new file mode 100644 index 0000000..811074f --- /dev/null +++ b/src/test/kotlin/MarsRoverTests.kt @@ -0,0 +1,30 @@ +import org.example.Rover +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource + +class MarsRoverTests { + @ParameterizedTest + @CsvSource( + "1 2 N, ' ', 1 2 N", + "1 2 N, L, 1 2 W", + "1 2 W, L, 1 2 S", + "1 2 S, L, 1 2 E", + "1 2 E, L, 1 2 N", + "1 2 N, R, 1 2 E", + "1 2 E, R, 1 2 S", + "1 2 S, R, 1 2 W", + "1 2 W, R, 1 2 N", + "1 2 N, M, 1 3 N", + "1 2 E, M, 2 2 E", + "1 2 S, M, 1 1 S", + "1 2 W, M, 0 2 W", + "1 2 N, LMLMLMLMM, 1 3 N", + "3 3 E, MMRMMRMRRM, 5 1 E" + ) + fun `execute commands`(startingPosition: String, instructions: String, expectedOutput: String) { + val rover = Rover(startingPosition) + rover.go(instructions) + assertEquals(expectedOutput, rover.pos()) + } +} \ No newline at end of file