88 lines
2.8 KiB
Scala
88 lines
2.8 KiB
Scala
|
package tf.bug.fancadegraph
|
||
|
|
||
|
import cats.data._
|
||
|
import scalax.collection.Graph
|
||
|
import scalax.collection.GraphEdge.DiHyperEdge
|
||
|
import tf.bug.{fancadescodec => fansc}
|
||
|
|
||
|
case class Level(
|
||
|
blocks: Set[Block[_]],
|
||
|
wires: Graph[Pin, DiHyperEdge]
|
||
|
)
|
||
|
|
||
|
object Level {
|
||
|
|
||
|
def validate(level: Level): Chain[String] = {
|
||
|
???
|
||
|
}
|
||
|
|
||
|
def encode(level: Level): tf.bug.fancadescodec.Entry = {
|
||
|
val boundary = level.blocks.foldLeft(fansc.Boundary(0, 0, 0)) {
|
||
|
case (fansc.Boundary(lr, du, nf), block) =>
|
||
|
val tlr = block.position.lr + block.definition.width
|
||
|
val tdu = block.position.du + block.definition.height
|
||
|
val tnf = block.position.nf + block.definition.depth
|
||
|
fansc.Boundary(lr.max(tlr), du.max(tdu), nf.max(tnf))
|
||
|
}
|
||
|
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
|
||
|
(0 until nb.definition.depth).foldLeft(ew) {
|
||
|
case (zw, z) =>
|
||
|
(0 until nb.definition.height).foldLeft(zw) {
|
||
|
case (yw, y) =>
|
||
|
(0 until nb.definition.width).foldLeft(yw) {
|
||
|
case (xw, x) =>
|
||
|
val objInd = x + (y * nb.definition.width) + (z * nb.definition.width * nb.definition.height)
|
||
|
xw.updated(sz + z, xw(sz + z).updated(sy + y, xw(sz + z)(sy + y).updated(sx + x, nb.definition.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.owner.position,
|
||
|
from.owner.position,
|
||
|
to.definition.voxel,
|
||
|
from.definition.voxel
|
||
|
)
|
||
|
} else {
|
||
|
fansc.Wire(
|
||
|
from.owner.position,
|
||
|
to.owner.position,
|
||
|
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(_))
|
||
|
}
|
||
|
|
||
|
}
|