[add][mod] added missing behaviours from example and some more factories
- measureGeneric, randomOutput, measureTempFault - randomOutputFactory, sensorModifierFactory - [mod] optional args fomr FunctionArgs now use Option[A]
This commit is contained in:
@@ -2,6 +2,7 @@ package scim.components
|
||||
|
||||
import scim.datastruct.{Cell, FunctionArgs, SimulationBehaviours, Time}
|
||||
import scim.lib.numberUtil._
|
||||
import scim.lib.mapUtil._
|
||||
import scim.lib.behaviourUtil._
|
||||
import scim.lib.simInterfaces.SimulationBehaviour
|
||||
|
||||
@@ -10,30 +11,96 @@ import scala.util.Random
|
||||
package object behaviour {
|
||||
|
||||
val behaviours = SimulationBehaviours(Map[String, SimulationBehaviour](
|
||||
"measureGeneric" -> measureGeneric,
|
||||
"measureTemp" -> measureTemp,
|
||||
"measureHumid" -> measureHumid,
|
||||
"noOutput" -> noOutput,
|
||||
"randomOutput" -> randomOutput,
|
||||
"measureTempFault" -> measureTempFault,
|
||||
"fluctuate" -> fluctuate,
|
||||
"change" -> change,
|
||||
"humidFromTemp" -> humidFromTemp
|
||||
))
|
||||
|
||||
def measureGeneric: SimulationBehaviour = {
|
||||
sensorFactory(Vector(0, 1), 0.1, 0.1, 0.0)
|
||||
}
|
||||
|
||||
def measureTemp: SimulationBehaviour = {
|
||||
sensorFactory(Vector(-50, 150), 0.1, 1.0, 0.0)
|
||||
}
|
||||
|
||||
def measureHumid: SimulationBehaviour = {
|
||||
sensorFactory(Vector(0, 100), 1.0, 2.0, 0.0)
|
||||
sensorFactory(Vector(5, 100), 1.0, 2.0, 0.0)
|
||||
}
|
||||
|
||||
def measureTempFault: SimulationBehaviour = {
|
||||
sensorModifierFactory("accuracy", Vector(-10, 10), 5, 15.0, 20.0, measureTemp)
|
||||
}
|
||||
|
||||
def noOutput: SimulationBehaviour = {
|
||||
(_: Cell, _: Time, _: Option[Double], _: Option[FunctionArgs]) => { None }
|
||||
}
|
||||
|
||||
def randomOutput: SimulationBehaviour = {
|
||||
randomOutputFactory(Vector(-50, 50))
|
||||
}
|
||||
|
||||
def randomOutputFactory(defaultRange: Vector[Double]) : SimulationBehaviour = {
|
||||
(_: Cell, _: Time, _: Option[Double], args: Option[FunctionArgs]) => {
|
||||
val range: Vector[Double] = args.getParam("range", defaultRange)
|
||||
val rng = new Random()
|
||||
val start = range(0).intValue()
|
||||
val end = range(1).intValue()
|
||||
val rngRange = start + rng.nextInt((end - start) + 1)
|
||||
Some((rngRange.doubleValue() + rng.nextDouble() * (if (rng.nextBoolean()) -1 else 1)).range(range(0), range(1)))
|
||||
}
|
||||
}
|
||||
|
||||
def sensorModifierFactory(defaultMod: String, modRange: Vector[Double], modResolution: Double, modAccuracy: Double, modOffset: Double,
|
||||
behaviour: SimulationBehaviour): SimulationBehaviour = {
|
||||
def modifyArgs(args: Option[FunctionArgs]): Option[FunctionArgs] = {
|
||||
val modifier: Option[Map[String, Any]] = args.getParam("modifier")
|
||||
if (!modifier.isEmpty) {
|
||||
val modType = modifier.get.getKeyOrElse[String]("type", defaultMod)
|
||||
// TODO: use interface to replace args
|
||||
val newArgs = modType match {
|
||||
case "range" => args.get.args + ("range" -> modifier.get.getKeyOrElse[Vector[Double]]("value", modRange))
|
||||
case "resolution" => args.get.args + ("resolution" -> modifier.get.getKeyOrElse[Double]("value", modResolution))
|
||||
case "accuracy" => args.get.args + ("accuracy" -> modifier.get.getKeyOrElse[Double]("value", modAccuracy))
|
||||
case "offset" => args.get.args + ("offset" -> modifier.get.getKeyOrElse[Double]("value", modOffset))
|
||||
}
|
||||
Some(FunctionArgs(newArgs))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
val modifierWrapper: SimulationBehaviour = (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]) => {
|
||||
val modifier: Option[Map[String, Any]] = args.getParam("modifier")
|
||||
if (!modifier.isEmpty) {
|
||||
val x = modifier.get.getKey[Int]("x")
|
||||
val y = modifier.get.getKey[Int]("y")
|
||||
val timeMod = modifier.get.getKey[Int]("time")
|
||||
(timeMod, x, y) match {
|
||||
case (timeFault, None, None) if (!timeFault.isEmpty && timeFault.get == time.time) => behaviour(cell, time, inTruth, modifyArgs(args))
|
||||
case (None, xVal, yVal) if (!xVal.isEmpty && !yVal.isEmpty && Cell(xVal.get, yVal.get) == cell) => behaviour(cell, time, inTruth, modifyArgs(args))
|
||||
case (timeFault, xVal, yVal) if (!timeFault.isEmpty && timeFault.get == time.time && !xVal.isEmpty && !yVal.isEmpty && Cell(xVal.get, yVal.get) == cell) =>
|
||||
behaviour(cell, time, inTruth, modifyArgs(args))
|
||||
case _ => behaviour(cell, time, inTruth, args)
|
||||
}
|
||||
} else {
|
||||
behaviour(cell, time, inTruth, args)
|
||||
}
|
||||
}
|
||||
|
||||
modifierWrapper
|
||||
}
|
||||
|
||||
def sensorFactory(defaultRange: Vector[Double], defaultResolution: Double, defaultAccuracy: Double, defaultOffset: Double,
|
||||
altFunction: Option[SimulationBehaviour] = None,
|
||||
preFunction: Option[SimulationBehaviour] = None,
|
||||
postFunction: Option[SimulationBehaviour] = None,
|
||||
altFunction: Option[SimulationBehaviour] = None): SimulationBehaviour = {
|
||||
postFunction: Option[SimulationBehaviour] = None): SimulationBehaviour = {
|
||||
|
||||
val genericSensor: SimulationBehaviour = (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]) => {
|
||||
// can use altFunction to entirely disable normal behaviour (including pre/postFunction)
|
||||
@@ -67,22 +134,43 @@ package object behaviour {
|
||||
genericSensor
|
||||
}
|
||||
|
||||
def sensorFactoryBehaviour(default: SimulationBehaviour,
|
||||
altFunction: Option[SimulationBehaviour] = None,
|
||||
preFunction: Option[SimulationBehaviour] = None,
|
||||
postFunction: Option[SimulationBehaviour] = None): SimulationBehaviour = {
|
||||
|
||||
val genericSensor: SimulationBehaviour = (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]) => {
|
||||
val altResult = if (!altFunction.isEmpty) altFunction.get(cell, time, inTruth, args) else None
|
||||
if (!altResult.isEmpty) {
|
||||
altResult
|
||||
} else {
|
||||
val preResult = if (!preFunction.isEmpty) preFunction.get(cell, time, inTruth, args) else inTruth
|
||||
if (preResult.isEmpty) {
|
||||
None
|
||||
} else {
|
||||
val result = default(cell, time, inTruth, args)
|
||||
if (!postFunction.isEmpty) postFunction.get(cell, time, result, args) else result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genericSensor
|
||||
}
|
||||
|
||||
def fluctuate (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]): Option[Double] = {
|
||||
if(inTruth.isEmpty) return None
|
||||
val range: Double = args.getParam("range", 1.0)
|
||||
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
||||
val distOffset: Double = args.getParam("distOffset", 0)
|
||||
val offsetTimes: Vector[Int] = args.getParam("time", Vector(-1))
|
||||
val offset = if(distOffset != 0 && offsetTimes.contains(time.time)) {
|
||||
val distOffset: Option[Double] = args.getParam[Double]("distOffset")
|
||||
val offsetTimes: Option[Vector[Int]] = args.getParam[Vector[Int]]("time")
|
||||
val offset = if(!distOffset.isEmpty && offsetTimes.get.contains(time.time)) {
|
||||
val centerCell = Cell(center(0), center(1))
|
||||
centerCell.distance(cell) * distOffset
|
||||
centerCell.distance(cell) * distOffset.get
|
||||
} else { 0 }
|
||||
|
||||
val rng = new Random()
|
||||
val rngRange = rng.nextDouble() * range * (if (rng.nextBoolean()) -1 else 1)
|
||||
|
||||
//if(time.time == 0 || time.time == 11) println("\nXXX: " + cell + " :: " + inTruth.get + " :OFF: " + offset + " :RES: " + (inTruth.get + rngRange + offset))
|
||||
|
||||
Some(inTruth.get + rngRange + offset)
|
||||
|
||||
}
|
||||
@@ -93,16 +181,16 @@ package object behaviour {
|
||||
val target: Double = args.getParam("target", inTruth.get + 5)
|
||||
val targetTime: Int = args.getParam("targetTime", time.time + 1)
|
||||
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
||||
val distOffset: Double = args.getParam("distOffset", 0)
|
||||
val offsetTimes: Vector[Int] = args.getParam("time", Vector(-1))
|
||||
val distOffset: Option[Double] = args.getParam[Double]("distOffset")
|
||||
val offsetTimes: Option[Vector[Int]] = args.getParam[Vector[Int]]("time")
|
||||
// always calculate offset for target
|
||||
val offset = if(distOffset != 0) {
|
||||
val offset = if(!distOffset.isEmpty) {
|
||||
val centerCell = Cell(center(0), center(1))
|
||||
centerCell.distance(cell) * distOffset
|
||||
centerCell.distance(cell) * distOffset.get
|
||||
} else { 0 }
|
||||
|
||||
// only change truth on offsetTimes
|
||||
val truth = if(offsetTimes.contains(time.time)) inTruth.get + offset else inTruth.get
|
||||
val truth = if(!offsetTimes.isEmpty && offsetTimes.get.contains(time.time)) inTruth.get + offset else inTruth.get
|
||||
|
||||
val rng = new Random()
|
||||
val rngRange = rng.nextDouble() * range * (if (rng.nextBoolean()) -1 else 1)
|
||||
|
||||
Reference in New Issue
Block a user