Created
August 26, 2016 13:11
-
-
Save waynejo/87047e595f64b548fc7e379b84e803b5 to your computer and use it in GitHub Desktop.
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
package lascala.turtle | |
import lascala.turtle.common.PenState.{Down, Up} | |
import lascala.turtle.common._ | |
object BasicFP { | |
case class TurtleState(position : Position, angle : Angle, color : PenColor, penState : PenState) | |
def initialTurtleState = TurtleState( | |
position = initialPosition, | |
angle = Angle(0.0), | |
color = initialColor, | |
penState = initialPenState | |
) | |
def move(log: String => Unit)(distance: Distance)(state:TurtleState):TurtleState = { | |
log(s"Move $distance%.1f") | |
val newPosition = Position(state.position.x, state.position.y).move(distance, state.angle) | |
if (state.penState == PenState.Down) { | |
common.dummyDrawLine(log, state.position, newPosition, state.color) | |
} | |
state.copy(position = newPosition) | |
} | |
def turn(log: String => Unit)(angle:Angle)(state:TurtleState) = { | |
log("Pen up") | |
// calculate new angle | |
val newAngle = ((state.angle.degree + angle.degree) % 360.0).degree | |
state.copy(angle = newAngle) | |
} | |
def penUp(log: String => Unit)(state:TurtleState) = { | |
log("Pen up") | |
state.copy(penState = Up) | |
} | |
def penDown(log: String => Unit)(state:TurtleState) = { | |
log("Pen down") | |
state.copy(penState = Down) | |
} | |
def setColor(log: String => Unit)(color:PenColor, state:TurtleState) = { | |
log(s"SetColor $color") | |
state.copy(color = color) | |
} | |
} |
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
package lascala.turtle | |
import lascala.turtle.BasicFP.TurtleState | |
import lascala.turtle.BasicOO.Turtle | |
import lascala.turtle.common._ | |
import utest._ | |
object BasicFPTest extends TestSuite { | |
import Functional._ | |
val tests = this { | |
'PenUp { | |
val turtle = BasicFP.initialTurtleState | |
assert(BasicFP.penUp(println)(turtle).penState == PenState.Up) | |
} | |
'PenDown { | |
val turtle = BasicFP.penUp(println)(BasicFP.initialTurtleState) | |
assert(BasicFP.penDown(println)(turtle).penState == PenState.Down) | |
} | |
'Move { | |
val turtle = BasicFP.initialTurtleState | |
val movedTurtle = BasicFP.move(println)(1.0)(turtle) | |
assert((movedTurtle.position.x - 1.0).abs < 0.000001) | |
assert((movedTurtle.position.y - 0.0).abs < 0.000001) | |
} | |
'Turn { | |
val turtle = BasicFP.initialTurtleState | |
val turnedTurtle = BasicFP.turn(println)(90.0.degree)(turtle) | |
assert((turnedTurtle.angle.degree - 90.0).abs < 0.000001) | |
} | |
'SetColor { | |
val turtle = BasicFP.initialTurtleState | |
val redTurtle = BasicFP.setColor(println)(PenColor.Red, turtle) | |
assert(redTurtle.color == PenColor.Red) | |
} | |
def log:(String)=>Unit = println | |
def move = BasicFP.move(log) _ | |
def turn = BasicFP.turn(log) _ | |
def penDown = BasicFP.penDown(log) _ | |
def penUp = BasicFP.penUp(log) _ | |
def setColor = BasicFP.setColor(log) _ | |
'DrawTriangle { | |
val turtle = BasicFP.initialTurtleState |> | |
move(100) |> | |
turn(120.0.degree) |> | |
move(100) |> | |
turn(120.0.degree) |> | |
move(100) |> | |
turn(120.0.degree) | |
assert((turtle.position.x - 0.0).abs < 0.000001) | |
assert((turtle.position.y - 0.0).abs < 0.000001) | |
assert((turtle.angle.degree - 0.0).abs < 0.000001) | |
} | |
'drawPolygon { | |
def drawPolygon(n:Int) = { | |
def angle = 360.0 / n.toDouble | |
def angleDegrees = angle.degree | |
// define a function that draws one side | |
def oneSide(state:TurtleState, sideNumber:Int) = state |> move(100.0) |> turn(angleDegrees) | |
(1 to n).foldLeft(BasicFP.initialTurtleState)(oneSide) | |
} | |
drawPolygon(5) | |
} | |
} | |
} |
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
package lascala.turtle | |
package object common { | |
type Distance = Double | |
case class Angle(degree: Double) { | |
def toRadian: Double = degree / 180 * math.Pi | |
} | |
implicit class AngleUnit(val angle: Double) extends AnyVal { | |
def degree: Angle = Angle(angle) | |
} | |
sealed trait PenState | |
object PenState { | |
case object Up extends PenState | |
case object Down extends PenState | |
} | |
sealed trait PenColor | |
object PenColor { | |
case object Black extends PenColor | |
case object Red extends PenColor | |
case object Blue extends PenColor | |
} | |
case class Position(x: Double, y: Double) { | |
def move(distance: Distance, angle: Angle): Position = | |
Position(x + distance * (math cos angle.toRadian), y + distance * (math sin angle.toRadian)) | |
override def toString(): String = f"($x%.1f, $y%.1f)" | |
} | |
implicit class DoubleRound2(val d: Double) extends AnyVal { | |
def round2: Double = (math rint d * 100) / 100.0 | |
} | |
val (initialPosition, initialColor, initialPenState) = (Position(0, 0), PenColor.Black, PenState.Down) | |
def dummyDrawLine(log: String => Unit, oldPos: Position, newPos: Position, color: PenColor): Unit = | |
log(s"...Draw line from $oldPos to $newPos using $color") | |
object Functional { | |
class PipedObject[T] private[Functional] (value:T) | |
{ | |
def |>[R] (f : T => R) = f(this.value) | |
} | |
implicit def toPiped[T] (value:T) = new PipedObject[T](value) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment