fancadescala/graph/src/main/scala/tf/bug/fancadegraph/Level.scala

93 lines
2.9 KiB
Scala

package tf.bug.fancadegraph
import cats.data._
import polymorphic._
import scalax.collection.Graph
import scalax.collection.GraphEdge.DiHyperEdge
import tf.bug.{fancadescodec => fansc}
case class Level(
blocks: Set[Block],
wires: Graph[Pin, DiHyperEdge]
) {
def boundary =
blocks.foldLeft(fansc.Boundary(0, 0, 0)) {
case (fansc.Boundary(lr, du, nf), block) =>
val tlr = block.position.lr + Exists.unwrap(block.template).definition.width
val tdu = block.position.du + Exists.unwrap(block.template).definition.height
val tnf = block.position.nf + Exists.unwrap(block.template).definition.depth
fansc.Boundary(lr.max(tlr), du.max(tdu), nf.max(tnf))
}
}
object Level {
def validate(level: Level): Chain[String] = {
???
}
def encode(level: Level): tf.bug.fancadescodec.Entry = {
val boundary = level.boundary
val objs: Vector[fansc.Obj] = {
val initialVector = Vector.fill(boundary.sizeNF, boundary.sizeDU, boundary.sizeLR)(fansc.Obj.empty)
level.blocks.foldLeft(initialVector) {
case (ew, nb) =>
val fansc.Position(sx, sy, sz) = nb.position
val nbd = Exists.unwrap(nb.template).definition
(0 until nbd.depth).foldLeft(ew) {
case (zw, z) =>
(0 until nbd.height).foldLeft(zw) {
case (yw, y) =>
(0 until nbd.width).foldLeft(yw) {
case (xw, x) =>
val objInd = x + (y * nbd.width) + (z * nbd.width * nbd.height)
xw.updated(sz + z, xw(sz + z).updated(sy + y, xw(sz + z)(sy + y).updated(sx + x, nbd.ids(objInd))))
}
}
}
}
}.flatten.flatten
val metadatas = level.blocks.toVector.map(_.metadata).flatten
val wires = level.wires.edges.toVector.map(_.edge).flatMap {
edge =>
val from = edge.nodeSeq.head
edge.nodeSeq.tail.map { to =>
if(from.definition.dataType == PinType.Pull) {
fansc.Wire(
to.basePosition,
from.basePosition,
to.definition.voxel,
from.definition.voxel
)
} else {
fansc.Wire(
from.basePosition,
to.basePosition,
from.definition.voxel,
to.definition.voxel
)
}
}
}
fansc.Entry(
Some(0x03), // TODO
"hello", // TODO
None, // TODO
Some(fansc.World(
boundary,
objs
)),
Some(metadatas),
Some(wires)
)
}
def toScodec(ours: Level): ValidatedNec[String, tf.bug.fancadescodec.Entry] = {
NonEmptyChain.fromChain(validate(ours))
.fold[ValidatedNec[String, tf.bug.fancadescodec.Entry]](
Validated.Valid(encode(ours))
)(Validated.Invalid(_))
}
}