Start over, using new fancadegraph project
This commit is contained in:
parent
d4389b6f50
commit
4ab4b5ad68
15 changed files with 102 additions and 231 deletions
|
@ -9,6 +9,8 @@ lazy val core = (project in file("core")).settings(
|
||||||
"org.typelevel" %% "cats-core" % "2.1.1",
|
"org.typelevel" %% "cats-core" % "2.1.1",
|
||||||
"org.typelevel" %% "cats-effect" % "2.1.2",
|
"org.typelevel" %% "cats-effect" % "2.1.2",
|
||||||
"io.chrisdavenport" %% "fuuid" % "0.3.0",
|
"io.chrisdavenport" %% "fuuid" % "0.3.0",
|
||||||
|
"tf.bug" %% "fancadescodec" % "0.1.1",
|
||||||
|
"tf.bug" %% "fancadegraph" % "0.1.0",
|
||||||
),
|
),
|
||||||
addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full),
|
addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package tf.bug.fancadetagless
|
|
||||||
|
|
||||||
import cats.effect.Sync
|
|
||||||
import cats.implicits._
|
|
||||||
import io.chrisdavenport.fuuid.FUUID
|
|
||||||
|
|
||||||
case class Block(uuid: FUUID, make: Make, pins: Set[Pin])
|
|
||||||
|
|
||||||
object Block {
|
|
||||||
|
|
||||||
def fromMake[F[_]](make: Make)(implicit s: Sync[F]): F[Block] = {
|
|
||||||
val uuid = FUUID.randomFUUID[F]
|
|
||||||
val pins = make.pins.traverse[F, Pin] { case (tpe, dir) => Pin.fromMake(tpe, dir) }
|
|
||||||
(uuid, pins).mapN {
|
|
||||||
case (u, v) => Block(u, make, v.toSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
case class Constraint()
|
|
@ -1,41 +0,0 @@
|
||||||
package tf.bug.fancadetagless
|
|
||||||
|
|
||||||
import cats.effect.Sync
|
|
||||||
import shapeless._
|
|
||||||
|
|
||||||
trait Encoding[A] {
|
|
||||||
|
|
||||||
def pins: Vector[PinType]
|
|
||||||
|
|
||||||
def encodeConstant(a: A): Vector[Make]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object Encoding extends ProductTypeClassCompanion[Encoding] {
|
|
||||||
|
|
||||||
object typeClass extends ProductTypeClass[Encoding] {
|
|
||||||
|
|
||||||
override def product[H, T <: HList](ch: Encoding[H], ct: Encoding[T]): Encoding[H :: T] = new Encoding[H :: T] {
|
|
||||||
override def pins: Vector[PinType] = ch.pins ++ ct.pins
|
|
||||||
override def encodeConstant(a: H :: T): Vector[Make] = ch.encodeConstant(a.head) ++ ct.encodeConstant(a.tail)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def emptyProduct: Encoding[HNil] = new Encoding[HNil] {
|
|
||||||
override def pins: Vector[PinType] = Vector.empty
|
|
||||||
override def encodeConstant(a: HNil): Vector[Make] = Vector.empty
|
|
||||||
}
|
|
||||||
|
|
||||||
override def project[F, G](instance: => Encoding[G], to: F => G, from: G => F): Encoding[F] = new Encoding[F] {
|
|
||||||
override def pins: Vector[PinType] = instance.pins
|
|
||||||
override def encodeConstant(a: F): Vector[Make] = instance.encodeConstant(to(a))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
implicit val floatEncoding: Encoding[Float] = new Encoding[Float] {
|
|
||||||
override def pins: Vector[PinType] = Vector(PinType.Number)
|
|
||||||
override def encodeConstant(a: Float): Vector[Make] =
|
|
||||||
Vector(Make.Builtin(s"Value[Number]($a)", pins.map((_, PinDirection.Outward))))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
80
core/src/main/scala/tf/bug/fancadetagless/Fanscript.scala
Normal file
80
core/src/main/scala/tf/bug/fancadetagless/Fanscript.scala
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
import tf.bug.fancadetagless.Fanscript.{Position, ScreenSize}
|
||||||
|
|
||||||
|
trait Fanscript[F[_]] {
|
||||||
|
|
||||||
|
def lift(value: Float): F[Float]
|
||||||
|
def lift(value: Vector3): F[Vector3]
|
||||||
|
def lift(value: Rotation): F[Rotation]
|
||||||
|
def lift(value: Boolean): F[Boolean]
|
||||||
|
|
||||||
|
def win(stop: Boolean): F[Unit]
|
||||||
|
def lose(stop: Boolean): F[Unit]
|
||||||
|
def setScore(score: F[Float]): F[Unit]
|
||||||
|
def setCamera(position: F[Vector3], rotation: F[Rotation], distance: F[Float]): F[Unit]
|
||||||
|
def setLight(position: F[Vector3], rotation: F[Rotation]): F[Unit]
|
||||||
|
def screenSize: F[Fanscript.ScreenSize]
|
||||||
|
def accelerometer: F[Vector3]
|
||||||
|
|
||||||
|
def getPosition(obj: F[Obj]): F[Fanscript.Position]
|
||||||
|
def setPosition(obj: F[Obj], position: F[Vector3], rotation: F[Rotation]): F[Unit]
|
||||||
|
def raycast(from: F[Vector3], to: F[Vector3]): F[Fanscript.Raycast]
|
||||||
|
def getSize(obj: F[Obj]): F[Fanscript.Size]
|
||||||
|
def setVisible(obj: F[Obj], visible: F[Boolean]): F[Unit]
|
||||||
|
def createObj(original: F[Obj]): F[Obj]
|
||||||
|
def destroyObj(obj: F[Obj]): F[Obj]
|
||||||
|
|
||||||
|
def playSound(loop: Boolean, sound: Nothing)(volume: F[Float], pitch: F[Float]): F[Float]
|
||||||
|
def stopSound(channel: F[Float]): F[Unit]
|
||||||
|
def volumePitch(channel: F[Float], volume: F[Float], pitch: F[Float]): F[Unit]
|
||||||
|
|
||||||
|
def addForce(obj: F[Obj], force: F[Vector3], applyAt: F[Vector3], torque: F[Vector3]): F[Unit]
|
||||||
|
def getVelocity(obj: F[Obj]): F[Fanscript.Velocity]
|
||||||
|
def setVelocity(obj: F[Obj], velocity: F[Vector3], spin: F[Vector3]): F[Unit]
|
||||||
|
def setLocked(obj: F[Obj], position: F[Vector3], rotation: F[Vector3]): F[Unit]
|
||||||
|
def setMass(obj: F[Obj], mass: F[Float]): F[Unit]
|
||||||
|
def setFriction(obj: F[Obj], friction: F[Float]): F[Unit]
|
||||||
|
def setBounciness(obj: F[Obj], bounciness: F[Float]): F[Unit]
|
||||||
|
def setGravity(gravity: F[Vector3]): F[Unit]
|
||||||
|
def addConstraint(base: F[Obj], part: F[Obj], pivot: F[Vector3]): F[Constraint]
|
||||||
|
def linearLimits(constraint: F[Constraint], lower: F[Vector3], upper: F[Vector3]): F[Unit]
|
||||||
|
def angularLimits(constraint: F[Constraint], lower: F[Vector3], upper: F[Vector3]): F[Unit]
|
||||||
|
def linearSpring(constraint: F[Constraint], stiffness: F[Vector3], damping: F[Vector3]): F[Unit]
|
||||||
|
def angularSpring(constraint: F[Constraint], stiffness: F[Vector3], damping: F[Vector3]): F[Unit]
|
||||||
|
def linearMotor(constraint: F[Constraint], speed: F[Vector3], force: F[Vector3]): F[Unit]
|
||||||
|
def angularMotor(constraint: F[Constraint], speed: F[Vector3], force: F[Vector3]): F[Unit]
|
||||||
|
|
||||||
|
def ifElse(cond: F[Boolean])(ifTrue: F[Unit])(ifFalse: F[Unit]): F[Unit]
|
||||||
|
def onPlay(onPlay: F[Unit]): F[Unit]
|
||||||
|
def onBoxArt(onBoxArt: F[Unit]): F[Unit]
|
||||||
|
def onTouch(onTouch: F[Fanscript.Touch] => F[Unit]): F[Unit]
|
||||||
|
|
||||||
|
def screenSizeWidth(screenSize: F[ScreenSize]): F[Float]
|
||||||
|
def screenSizeHeight(screenSize: F[ScreenSize]): F[Float]
|
||||||
|
|
||||||
|
def positionPosition(position: F[Position]): F[Vector3]
|
||||||
|
def positionRotation(position: F[Position]): F[Rotation]
|
||||||
|
|
||||||
|
def raycastHit(raycast: F[Fanscript.Raycast]): F[Boolean]
|
||||||
|
def raycastPosition(raycast: F[Fanscript.Raycast]): F[Vector3]
|
||||||
|
def raycastObj(raycast: F[Fanscript.Raycast]): F[Obj]
|
||||||
|
|
||||||
|
def sizeMin(size: F[Fanscript.Size]): F[Vector3]
|
||||||
|
def sizeMax(size: F[Fanscript.Size]): F[Vector3]
|
||||||
|
|
||||||
|
def velocityVelocity(velocity: F[Fanscript.Velocity]): F[Vector3]
|
||||||
|
def velocitySpin(velocity: F[Fanscript.Velocity]): F[Vector3]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object Fanscript {
|
||||||
|
|
||||||
|
case class ScreenSize(width: Float, height: Float)
|
||||||
|
case class Position(position: Vector3, rotation: Rotation)
|
||||||
|
case class Raycast(hit: Boolean, position: Vector3, obj: Obj)
|
||||||
|
case class Size(min: Vector3, max: Vector3)
|
||||||
|
case class Velocity(velocity: Vector3, spin: Vector3)
|
||||||
|
case class Touch(screenX: Float, screenY: Float)
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
package tf.bug.fancadetagless
|
|
||||||
|
|
||||||
sealed trait Make {
|
|
||||||
def pins: Vector[(PinType, PinDirection)]
|
|
||||||
}
|
|
||||||
object Make {
|
|
||||||
case class Builtin(name: String, pins: Vector[(PinType, PinDirection)]) extends Make
|
|
||||||
case class Custom(world: World, pins: Vector[(PinType, PinDirection)]) extends Make
|
|
||||||
}
|
|
3
core/src/main/scala/tf/bug/fancadetagless/Obj.scala
Normal file
3
core/src/main/scala/tf/bug/fancadetagless/Obj.scala
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
case class Obj() // FIXME
|
|
@ -1,29 +0,0 @@
|
||||||
package tf.bug.fancadetagless
|
|
||||||
|
|
||||||
import cats.effect.Sync
|
|
||||||
import cats.implicits._
|
|
||||||
import io.chrisdavenport.fuuid.FUUID
|
|
||||||
|
|
||||||
case class Pin(uuid: FUUID, tpe: PinType, dir: PinDirection)
|
|
||||||
object Pin {
|
|
||||||
|
|
||||||
def fromMake[F[_]](tpe: PinType, dir: PinDirection)(implicit s: Sync[F]): F[Pin] = {
|
|
||||||
val uuid: F[FUUID] = FUUID.randomFUUID[F]
|
|
||||||
uuid.map(Pin(_, tpe, dir))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait PinType
|
|
||||||
object PinType {
|
|
||||||
case object Pull extends PinType
|
|
||||||
case object Number extends PinType
|
|
||||||
case object Truth extends PinType
|
|
||||||
case class Quoted[T <: PinType](v: T) extends PinType
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait PinDirection
|
|
||||||
object PinDirection {
|
|
||||||
case object Inward extends PinDirection
|
|
||||||
case object Outward extends PinDirection
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
package tf.bug.fancadetagless
|
|
||||||
|
|
||||||
case class Pins[A](pins: Vector[Pin])(implicit enc: Encoding[A])
|
|
7
core/src/main/scala/tf/bug/fancadetagless/Rotation.scala
Normal file
7
core/src/main/scala/tf/bug/fancadetagless/Rotation.scala
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
case class Rotation(
|
||||||
|
pitch: Float,
|
||||||
|
yaw: Float,
|
||||||
|
roll: Float
|
||||||
|
)
|
7
core/src/main/scala/tf/bug/fancadetagless/Vector3.scala
Normal file
7
core/src/main/scala/tf/bug/fancadetagless/Vector3.scala
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
case class Vector3(
|
||||||
|
x: Float,
|
||||||
|
y: Float,
|
||||||
|
z: Float
|
||||||
|
)
|
|
@ -1,6 +0,0 @@
|
||||||
package tf.bug.fancadetagless
|
|
||||||
|
|
||||||
import scalax.collection.Graph
|
|
||||||
import scalax.collection.GraphEdge.DiHyperEdge
|
|
||||||
|
|
||||||
case class World(blocks: Set[Block], connections: Graph[Pin, DiHyperEdge])
|
|
|
@ -1,42 +0,0 @@
|
||||||
package tf.bug
|
|
||||||
|
|
||||||
import cats.data.StateT
|
|
||||||
import cats.effect.Sync
|
|
||||||
import cats.implicits._
|
|
||||||
import io.chrisdavenport.fuuid.FUUID
|
|
||||||
import scalax.collection.GraphEdge.DiHyperEdge
|
|
||||||
|
|
||||||
package object fancadetagless {
|
|
||||||
|
|
||||||
type FancadeT[F[_], A] = StateT[F, World, Pins[A]]
|
|
||||||
object FancadeT {
|
|
||||||
def make[F[_]](make: Make)(implicit s: Sync[F]): FancadeT[F, Unit] = {
|
|
||||||
val block = Block.fromMake[F](make)
|
|
||||||
StateT.apply { w =>
|
|
||||||
block.map { b =>
|
|
||||||
(w.copy(w.blocks + b), Pins(b.pins.toVector))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def constant[F[_], A](a: A)(implicit encoding: Encoding[A], s: Sync[F]): FancadeT[F, A] = {
|
|
||||||
val makes = encoding.encodeConstant(a)
|
|
||||||
val blocks = makes.traverse[F, Block](Block.fromMake[F])
|
|
||||||
StateT.apply { world =>
|
|
||||||
for {
|
|
||||||
b <- blocks
|
|
||||||
s = b.toSet
|
|
||||||
nw = world.copy(blocks = world.blocks ++ s)
|
|
||||||
} yield (nw, Pins(b.flatMap(_.pins)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def connect[F[_]](from: Pin, to: Pin)(implicit s: Sync[F]): FancadeT[F, Unit] = {
|
|
||||||
StateT.apply { w =>
|
|
||||||
val newConn = DiHyperEdge(from, to)
|
|
||||||
s.pure(w.copy(connections = w.connections incl newConn), Pins(Vector.empty))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
package tf.bug.fancadetagless.test
|
|
||||||
|
|
||||||
import cats.effect.Sync
|
|
||||||
import tf.bug.fancadetagless.{FancadeT, Make, PinDirection, PinType, Pins}
|
|
||||||
|
|
||||||
trait Calc[W[_]] {
|
|
||||||
|
|
||||||
def lift(f: Float): W[Float]
|
|
||||||
|
|
||||||
def add(a: W[Float], b: W[Float]): W[Float]
|
|
||||||
def sub(a: W[Float], b: W[Float]): W[Float]
|
|
||||||
def mul(a: W[Float], b: W[Float]): W[Float]
|
|
||||||
def div(a: W[Float], b: W[Float]): W[Float]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
object Calc {
|
|
||||||
|
|
||||||
trait Program[R] {
|
|
||||||
def apply[F[_]](int: Calc[F]): F[R]
|
|
||||||
}
|
|
||||||
|
|
||||||
case class FancadeCalc[F[_]]()(implicit s: Sync[F]) extends Calc[FancadeT[F, *]] {
|
|
||||||
|
|
||||||
override def lift(f: Float): FancadeT[F, Float] = FancadeT.constant(f)
|
|
||||||
|
|
||||||
override def add(a: FancadeT[F, Float], b: FancadeT[F, Float]): FancadeT[F, Float] =
|
|
||||||
for {
|
|
||||||
addBlock <- FancadeT.make(Make.Builtin("Add[Number]", Vector(
|
|
||||||
(PinType.Number, PinDirection.Inward),
|
|
||||||
(PinType.Number, PinDirection.Inward),
|
|
||||||
(PinType.Number, PinDirection.Outward)
|
|
||||||
)))
|
|
||||||
ab <- a
|
|
||||||
bb <- b
|
|
||||||
_ <- FancadeT.connect(ab.pins.head, addBlock.pins(0))
|
|
||||||
_ <- FancadeT.connect(bb.pins.head, addBlock.pins(1))
|
|
||||||
} yield Pins(addBlock.pins.drop(2))
|
|
||||||
|
|
||||||
override def sub(a: FancadeT[F, Float], b: FancadeT[F, Float]): FancadeT[F, Float] = ???
|
|
||||||
|
|
||||||
override def mul(a: FancadeT[F, Float], b: FancadeT[F, Float]): FancadeT[F, Float] = ???
|
|
||||||
|
|
||||||
override def div(a: FancadeT[F, Float], b: FancadeT[F, Float]): FancadeT[F, Float] =
|
|
||||||
for {
|
|
||||||
addBlock <- FancadeT.make(Make.Builtin("Divide[Number]", Vector(
|
|
||||||
(PinType.Number, PinDirection.Inward),
|
|
||||||
(PinType.Number, PinDirection.Inward),
|
|
||||||
(PinType.Number, PinDirection.Outward)
|
|
||||||
)))
|
|
||||||
ab <- a
|
|
||||||
bb <- b
|
|
||||||
_ <- FancadeT.connect(ab.pins.head, addBlock.pins(0))
|
|
||||||
_ <- FancadeT.connect(bb.pins.head, addBlock.pins(1))
|
|
||||||
} yield Pins(addBlock.pins.drop(2))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package tf.bug.fancadetagless.test
|
|
||||||
|
|
||||||
import cats.effect.{ExitCode, IO, IOApp}
|
|
||||||
import cats.implicits._
|
|
||||||
import scalax.collection.Graph
|
|
||||||
import tf.bug.fancadetagless.World
|
|
||||||
|
|
||||||
object Main extends IOApp {
|
|
||||||
override def run(args: List[String]): IO[ExitCode] = {
|
|
||||||
object TwoPlusThreeOverFour extends Calc.Program[Float] {
|
|
||||||
override def apply[F[_]](int: Calc[F]): F[Float] =
|
|
||||||
int.div(
|
|
||||||
int.add(
|
|
||||||
int.lift(2.0f),
|
|
||||||
int.lift(3.0f)
|
|
||||||
),
|
|
||||||
int.lift(4.0f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val ft = TwoPlusThreeOverFour(Calc.FancadeCalc[IO])
|
|
||||||
ft.runS(World(Set.empty, Graph.empty)).flatMap(w => IO(println(w))).as(ExitCode.Success)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue