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(_)) } }