[add] added missing block parsing

- added mergeMaps function to library
 - added block function to Cell class
This commit is contained in:
2020-01-29 01:19:11 -06:00
parent 05a3a88f83
commit 8f47875cd7
4 changed files with 56 additions and 8 deletions

View File

@@ -39,11 +39,10 @@ sensors:
# all cells are declared to output the gt # all cells are declared to output the gt
# of baseline for each into the console # of baseline for each into the console
- group: baseline - group: baseline
cells: blocks:
- [0, 0, 0] - start: [0, 0]
- [1, 1, 0] end: [6, 6]
- [2, 2, 0] count: 0
- [3, 3, 0]
groundtruths: groundtruths:
- group: baseline - group: baseline

View File

@@ -89,7 +89,9 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
private def parseSensor(sensor: Map[String, Any]): Unit = { private def parseSensor(sensor: Map[String, Any]): Unit = {
val groupString = sensor("group").asInstanceOf[String] val groupString = sensor("group").asInstanceOf[String]
val parentString: Option[String] = if(sensor.contains("parent")) Some(sensor("parent").asInstanceOf[String]) else None val parentString: Option[String] = if(sensor.contains("parent")) Some(sensor("parent").asInstanceOf[String]) else None
val cells: Map[Cell, SensorCount] = parseCells(sensor("cells").asInstanceOf[Vector[Any]]) val cellsParsed: Map[Cell, SensorCount] = if(sensor.contains("cells")) parseCells(sensor("cells").asInstanceOf[Vector[Any]]) else Map()
val blocksParsed: Map[Cell, SensorCount] = if(sensor.contains("blocks")) parseBlocks(sensor("blocks").asInstanceOf[Vector[Any]]) else Map()
val cells = mergeMaps[Cell, SensorCount](blocksParsed, cellsParsed, (a: SensorCount, b: SensorCount) => a.add(b), SensorCount(0))
val group = Group(groupString, parentString) val group = Group(groupString, parentString)
if(!groups.contains(groupString)) { if(!groups.contains(groupString)) {
groups(groupString) = group groups(groupString) = group
@@ -113,18 +115,41 @@ class SimulationConfigParser(input: Map[String, Any], simulationBehaviours: Simu
} }
private def parseCells(cells: Vector[Any]): Map[Cell, SensorCount] = { private def parseCells(cells: Vector[Any]): Map[Cell, SensorCount] = {
val parseCell: Any => (Cell, SensorCount) = (cell: Any) => cell match { val parseCell: Any => (Cell, SensorCount) = (inCell: Any) => inCell match {
case cell: Vector[_] => val cellVector = cell.asInstanceOf[Vector[Int]] case cell: Vector[_] => val cellVector = cell.asInstanceOf[Vector[Int]]
(Cell(cellVector(0), cellVector(1)), SensorCount(cellVector(2))) (Cell(cellVector(0), cellVector(1)), SensorCount(cellVector(2)))
case cell: Map[_, _] => val cellMap = cell.asInstanceOf[Map[String, Int]] case cell: Map[_, _] => val cellMap = cell.asInstanceOf[Map[String, Int]]
(Cell(cellMap("x"), cellMap("y")), SensorCount(cellMap("count"))) (Cell(cellMap("x"), cellMap("y")), SensorCount(cellMap("count")))
case _ => throw new Exception("Invalid Cell: " + cell.toString) case _ => throw new Exception("Invalid Cell: " + inCell.toString)
} }
// traversableToMap iterates over the vector while parseCell returns a key value // traversableToMap iterates over the vector while parseCell returns a key value
// pair for each element which than gets added to the returned map // pair for each element which than gets added to the returned map
traversableToMap[Cell, SensorCount](cells, parseCell) traversableToMap[Cell, SensorCount](cells, parseCell)
} }
private def parseBlocks(blocks: Vector[Any]): Map[Cell, SensorCount] = {
val parseBlock: Any => Map[Cell, SensorCount] = (inBlock: Any) => inBlock match {
case block: Map[_, _] => {
val blockMap = block.asInstanceOf[Map[String, Any]]
val start = blockMap("start").asInstanceOf[Vector[Int]]
val end = blockMap("end").asInstanceOf[Vector[Int]]
val count = blockMap("count").asInstanceOf[Int]
val blockCells = Cell(start(0), start(1)).block(Cell(end(0), end(1)))
val countPerCell: Int = count / blockCells.length
var countRest: Int = count % blockCells.length
val result: Vector[(Cell, SensorCount)] = blockCells.map(cell => {
val sensorCount = SensorCount(countPerCell + (if(countRest > 0) 1 else 0))
if(countRest > 0) countRest -= 1
cell -> sensorCount
})
result.toMap
}
case _ => throw new Exception("Invalid Block: " + inBlock.toString)
}
mergeMaps[Cell, SensorCount](blocks.map(parseBlock), (a: SensorCount, b: SensorCount) => a.add(b), SensorCount(0))
}
// don't add tickfacor here, this is done in parseTruth with config.time() // don't add tickfacor here, this is done in parseTruth with config.time()
private def parseTimeLineElement(timeLineElement: Any): (Int, Option[Int]) = { private def parseTimeLineElement(timeLineElement: Any): (Int, Option[Int]) = {
timeLineElement match { timeLineElement match {

View File

@@ -126,6 +126,18 @@ case class Cell(x: Int, y: Int) {
def distance(otherCell: Cell): Double = { def distance(otherCell: Cell): Double = {
Math.sqrt(Math.pow(x - otherCell.x, 2) + Math.pow(y - otherCell.y, 2)) Math.sqrt(Math.pow(x - otherCell.x, 2) + Math.pow(y - otherCell.y, 2))
} }
def block(otherCell: Cell): Vector[Cell] = {
val bottomLeft = Cell(math.min(x, otherCell.x), math.min(y, otherCell.y))
val topRight = Cell(math.max(x, otherCell.x), math.max(y, otherCell.y))
// add + 1 as topright is included in the block
val xCount = topRight.x - bottomLeft.x + 1
val yCount = topRight.y - bottomLeft.y + 1
Vector.tabulate(yCount)(yCoord => {
Vector.tabulate(xCount)(xCoord => {
Cell(xCoord + bottomLeft.x, yCoord + bottomLeft.y)
})
}).flatten
}
} }
case class Group(name: String, sensorParent: Option[String] = None){ case class Group(name: String, sensorParent: Option[String] = None){
// the sensorParent serves as indicator for the parser that a ground truth is not required // the sensorParent serves as indicator for the parser that a ground truth is not required

View File

@@ -152,6 +152,18 @@ package object mapUtil {
} }
} }
def mergeMaps[A, B](mapA: Map[A, B], mapB: Map[A, B], add: (B, B) => B, default: B): Map[A, B] = {
mapA ++ mapB.map(e => e._1 -> add(e._2, mapA.getOrElse(e._1, default)))
}
def mergeMaps[A, B](vector: Vector[Map[A, B]], add: (B, B) => B, default: B): Map[A, B] = {
if(vector.length > 1) {
mergeMaps(vector.head, mergeMaps(vector.tail, add, default), add, default)
} else {
vector.head
}
}
def traversableToMap[A, B](traversable: Traversable[Any], getTuple: (Any) => (A, B) = (e: Any) => e.asInstanceOf[(A, B)]._1 -> e.asInstanceOf[(A, B)]._2): Map[A, B] = { def traversableToMap[A, B](traversable: Traversable[Any], getTuple: (Any) => (A, B) = (e: Any) => e.asInstanceOf[(A, B)]._1 -> e.asInstanceOf[(A, B)]._2): Map[A, B] = {
// Traversable[Tuple[A, B]] can be converted via .map // Traversable[Tuple[A, B]] can be converted via .map
// .foldLeft used in favor of .map().toMap as the latter needs two traversals // .foldLeft used in favor of .map().toMap as the latter needs two traversals