[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.datastruct.{Cell, FunctionArgs, SimulationBehaviours, Time}
|
||||||
import scim.lib.numberUtil._
|
import scim.lib.numberUtil._
|
||||||
|
import scim.lib.mapUtil._
|
||||||
import scim.lib.behaviourUtil._
|
import scim.lib.behaviourUtil._
|
||||||
import scim.lib.simInterfaces.SimulationBehaviour
|
import scim.lib.simInterfaces.SimulationBehaviour
|
||||||
|
|
||||||
@@ -10,30 +11,96 @@ import scala.util.Random
|
|||||||
package object behaviour {
|
package object behaviour {
|
||||||
|
|
||||||
val behaviours = SimulationBehaviours(Map[String, SimulationBehaviour](
|
val behaviours = SimulationBehaviours(Map[String, SimulationBehaviour](
|
||||||
|
"measureGeneric" -> measureGeneric,
|
||||||
"measureTemp" -> measureTemp,
|
"measureTemp" -> measureTemp,
|
||||||
"measureHumid" -> measureHumid,
|
"measureHumid" -> measureHumid,
|
||||||
"noOutput" -> noOutput,
|
"noOutput" -> noOutput,
|
||||||
|
"randomOutput" -> randomOutput,
|
||||||
|
"measureTempFault" -> measureTempFault,
|
||||||
"fluctuate" -> fluctuate,
|
"fluctuate" -> fluctuate,
|
||||||
"change" -> change,
|
"change" -> change,
|
||||||
"humidFromTemp" -> humidFromTemp
|
"humidFromTemp" -> humidFromTemp
|
||||||
))
|
))
|
||||||
|
|
||||||
|
def measureGeneric: SimulationBehaviour = {
|
||||||
|
sensorFactory(Vector(0, 1), 0.1, 0.1, 0.0)
|
||||||
|
}
|
||||||
|
|
||||||
def measureTemp: SimulationBehaviour = {
|
def measureTemp: SimulationBehaviour = {
|
||||||
sensorFactory(Vector(-50, 150), 0.1, 1.0, 0.0)
|
sensorFactory(Vector(-50, 150), 0.1, 1.0, 0.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
def measureHumid: SimulationBehaviour = {
|
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 = {
|
def noOutput: SimulationBehaviour = {
|
||||||
(_: Cell, _: Time, _: Option[Double], _: Option[FunctionArgs]) => { None }
|
(_: 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,
|
def sensorFactory(defaultRange: Vector[Double], defaultResolution: Double, defaultAccuracy: Double, defaultOffset: Double,
|
||||||
|
altFunction: Option[SimulationBehaviour] = None,
|
||||||
preFunction: Option[SimulationBehaviour] = None,
|
preFunction: Option[SimulationBehaviour] = None,
|
||||||
postFunction: Option[SimulationBehaviour] = None,
|
postFunction: Option[SimulationBehaviour] = None): SimulationBehaviour = {
|
||||||
altFunction: Option[SimulationBehaviour] = None): SimulationBehaviour = {
|
|
||||||
|
|
||||||
val genericSensor: SimulationBehaviour = (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]) => {
|
val genericSensor: SimulationBehaviour = (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]) => {
|
||||||
// can use altFunction to entirely disable normal behaviour (including pre/postFunction)
|
// can use altFunction to entirely disable normal behaviour (including pre/postFunction)
|
||||||
@@ -67,22 +134,43 @@ package object behaviour {
|
|||||||
genericSensor
|
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] = {
|
def fluctuate (cell: Cell, time: Time, inTruth: Option[Double], args: Option[FunctionArgs]): Option[Double] = {
|
||||||
if(inTruth.isEmpty) return None
|
if(inTruth.isEmpty) return None
|
||||||
val range: Double = args.getParam("range", 1.0)
|
val range: Double = args.getParam("range", 1.0)
|
||||||
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
||||||
val distOffset: Double = args.getParam("distOffset", 0)
|
val distOffset: Option[Double] = args.getParam[Double]("distOffset")
|
||||||
val offsetTimes: Vector[Int] = args.getParam("time", Vector(-1))
|
val offsetTimes: Option[Vector[Int]] = args.getParam[Vector[Int]]("time")
|
||||||
val offset = if(distOffset != 0 && offsetTimes.contains(time.time)) {
|
val offset = if(!distOffset.isEmpty && offsetTimes.get.contains(time.time)) {
|
||||||
val centerCell = Cell(center(0), center(1))
|
val centerCell = Cell(center(0), center(1))
|
||||||
centerCell.distance(cell) * distOffset
|
centerCell.distance(cell) * distOffset.get
|
||||||
} else { 0 }
|
} else { 0 }
|
||||||
|
|
||||||
val rng = new Random()
|
val rng = new Random()
|
||||||
val rngRange = rng.nextDouble() * range * (if (rng.nextBoolean()) -1 else 1)
|
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)
|
Some(inTruth.get + rngRange + offset)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -93,16 +181,16 @@ package object behaviour {
|
|||||||
val target: Double = args.getParam("target", inTruth.get + 5)
|
val target: Double = args.getParam("target", inTruth.get + 5)
|
||||||
val targetTime: Int = args.getParam("targetTime", time.time + 1)
|
val targetTime: Int = args.getParam("targetTime", time.time + 1)
|
||||||
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
val center: Vector[Int] = args.getParam("center", Vector(0, 0))
|
||||||
val distOffset: Double = args.getParam("distOffset", 0)
|
val distOffset: Option[Double] = args.getParam[Double]("distOffset")
|
||||||
val offsetTimes: Vector[Int] = args.getParam("time", Vector(-1))
|
val offsetTimes: Option[Vector[Int]] = args.getParam[Vector[Int]]("time")
|
||||||
// always calculate offset for target
|
// always calculate offset for target
|
||||||
val offset = if(distOffset != 0) {
|
val offset = if(!distOffset.isEmpty) {
|
||||||
val centerCell = Cell(center(0), center(1))
|
val centerCell = Cell(center(0), center(1))
|
||||||
centerCell.distance(cell) * distOffset
|
centerCell.distance(cell) * distOffset.get
|
||||||
} else { 0 }
|
} else { 0 }
|
||||||
|
|
||||||
// only change truth on offsetTimes
|
// 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 rng = new Random()
|
||||||
val rngRange = rng.nextDouble() * range * (if (rng.nextBoolean()) -1 else 1)
|
val rngRange = rng.nextDouble() * range * (if (rng.nextBoolean()) -1 else 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user