<file_sep>class Rover {
  
  var maps: Maps?
  private var x: Int
  private var y: Int
  private var face: Direction

  init(x: Int, y: Int, face: Direction) {
    self.x = x
    self.y = y
    self.face = face
  }

  func operate(command: Command) {
    switch command {
    case .turnLeft:
      operateTurnLeftCommand()
    case .turnRight:
      operateTurnRightCommand()
    case .move:
      operateMoveCommand()
    }
  }

  func operateMoveCommand() {
    switch face {
    case .north:
      if y + 1 <= maps?.maxY ?? Int.max {
        y += 1
      }
    case .east:
      if x + 1 <= maps?.maxX ?? Int.max {
        x += 1
      }
    case .south:
      if y - 1 >= 0 {
        y -= 1
      }
    case .west:
      if x - 1 >= 0 {
        x -= 1
      }
    }
  }

  func operateTurnLeftCommand() {
    face = face.nextCounterclockwise
  }

  func operateTurnRightCommand() {
    face = face.nextClockwise
  }

  var position: Position {
    return Position(x: x, y: y, face: face)
  }

  enum Command: String {
    case turnLeft = "L"
    case turnRight = "R"
    case move = "M"
  }
}
<file_sep>struct Position: Equatable {

  let x: Int
  let y: Int
  let face: Direction
}
<file_sep>import XCTest
@testable import swift_marsrovertechchallenge

class RoverTests: XCTestCase {

  let dummyX = 1
  let dummyY = 2
  
  func testWhenTurnLeftDirectionShouldBeNextCounterclockwise() {
    let rover = Rover(x: dummyX, y: dummyY, face: .north)

    rover.operate(command: .turnLeft)
    let expectedFaceWest = Position(x: dummyX, y: dummyY, face: .west)
    XCTAssertEqual(expectedFaceWest, rover.position)

    rover.operate(command: .turnLeft)
    let expectedFaceSouth = Position(x: dummyX, y: dummyY, face: .south)
    XCTAssertEqual(expectedFaceSouth, rover.position)

    rover.operate(command: .turnLeft)
    let expectedFaceEast = Position(x: dummyX, y: dummyY, face: .east)
    XCTAssertEqual(expectedFaceEast, rover.position)

    rover.operate(command: .turnLeft)
    let expectedFaceNorth = Position(x: dummyX, y: dummyY, face: .north)
    XCTAssertEqual(expectedFaceNorth, rover.position)
  }

  func testWhenTurnRightDirectionShouldBeNextAfterClockwise() {
    let rover = Rover(x: dummyX, y: dummyY, face: .north)

    rover.operate(command: .turnRight)
    let expectedFaceWest = Position(x: dummyX, y: dummyY, face: .east)
    XCTAssertEqual(expectedFaceWest, rover.position)

    rover.operate(command: .turnRight)
    let expectedFaceSouth = Position(x: dummyX, y: dummyY, face: .south)
    XCTAssertEqual(expectedFaceSouth, rover.position)

    rover.operate(command: .turnRight)
    let expectedFaceEast = Position(x: dummyX, y: dummyY, face: .west)
    XCTAssertEqual(expectedFaceEast, rover.position)

    rover.operate(command: .turnRight)
    let expectedFaceNorth = Position(x: dummyX, y: dummyY, face: .north)
    XCTAssertEqual(expectedFaceNorth, rover.position)
  }

  func testWhenFaceNorthAndMoveShouldBeInNextPosition() {
    let rover = Rover(x: 1, y: 2, face: .north)
    rover.operate(command: .move)

    let expectedPosition = Position(x: 1, y: 3, face: .north)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenMoveShouldBeInTheSamePositionIfReachMaxY() {
    let rover = Rover(x: 1, y: 2, face: .north)
    let maps = Maps(maxX: 1, maxY: 2)
    rover.maps = maps
    rover.operate(command: .move)

    let expectedPosition = Position(x: 1, y: 2, face: .north)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenFaceEastAndMoveShouldBeInNextPosition() {
    let rover = Rover(x: 1, y: 2, face: .east)
    rover.operate(command: .move)

    let expectedPosition = Position(x: 2, y: 2, face: .east)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenMoveShouldBeInTheSamePositionIfReachMaxX() {
    let rover = Rover(x: 1, y: 2, face: .east)
    let maps = Maps(maxX: 1, maxY: 2)
    rover.maps = maps
    rover.operate(command: .move)

    let expectedPosition = Position(x: 1, y: 2, face: .east)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenFaceSouthAndMoveShouldBeInNextPosition() {
    let rover = Rover(x: 1, y: 2, face: .south)
    rover.operate(command: .move)

    let expectedPosition = Position(x: 1, y: 1, face: .south)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenMoveShouldBeInTheSamePositionIfReachMinY() {
    let rover = Rover(x: 1, y: 0, face: .south)
    let maps = Maps(maxX: dummyX, maxY: dummyY)
    rover.maps = maps
    rover.operate(command: .move)

    let expectedPosition = Position(x: 1, y: 0, face: .south)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenFaceWestAndMoveShouldBeInNextPosition() {
    let rover = Rover(x: 1, y: 2, face: .west)
    rover.operate(command: .move)

    let expectedPosition = Position(x: 0, y: 2, face: .west)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testWhenMoveShouldBeInTheSamePositionIfReachMinX() {
    let rover = Rover(x: 0, y: 2, face: .west)
    let maps = Maps(maxX: dummyX, maxY: dummyY)
    rover.maps = maps
    rover.operate(command: .move)

    let expectedPosition = Position(x: 0, y: 2, face: .west)
    XCTAssertEqual(expectedPosition, rover.position)
  }

  func testRawValueOfRoverCommandShouldBeIntegrity() {
    XCTAssertEqual("L", Rover.Command.turnLeft.rawValue)
    XCTAssertEqual("R", Rover.Command.turnRight.rawValue)
    XCTAssertEqual("M", Rover.Command.move.rawValue)
  }
}
<file_sep>struct Maps {

  let maxX: Int
  let maxY: Int
}
<file_sep>import XCTest
@testable import swift_marsrovertechchallenge

class DirectionTests: XCTestCase {

    func testDirectionRawValue() {
      XCTAssertEqual("N", Direction.north.rawValue)
      XCTAssertEqual("W", Direction.west.rawValue)
      XCTAssertEqual("S", Direction.south.rawValue)
      XCTAssertEqual("E", Direction.east.rawValue)
    }
}
<file_sep>https://code.google.com/archive/p/marsrovertechchallenge/
<file_sep>enum Direction: String {
  case north = "N"
  case west = "W"
  case south = "S"
  case east = "E"

  var nextClockwise: Direction {
    switch self {
    case .north:
      return .east
    case .east:
      return .south
    case .south:
      return .west
    case .west:
      return .north
    }
  }

  var nextCounterclockwise: Direction {
    switch self {
    case .north:
      return .west
    case .west:
      return .south
    case .south:
      return .east
    case .east:
      return .north
    }
  }
}
