commit #21
This commit is contained in:
parent
74f113e670
commit
926a52e34e
14 changed files with 105 additions and 99 deletions
|
@ -9,7 +9,6 @@ import de.moritzruth.theaterdsl.dmx.EnttecOpenDmxUsb
|
|||
import de.moritzruth.theaterdsl.show.createShow
|
||||
import de.moritzruth.theaterdsl.show.runShow
|
||||
|
||||
@Suppress("DuplicatedCode")
|
||||
val show = createShow {
|
||||
firstAct()
|
||||
secondAct()
|
||||
|
|
|
@ -4,6 +4,7 @@ import de.moritzruth.lampenfieber.device.devices
|
|||
import de.moritzruth.theaterdsl.dmx.EnttecOpenDmxUsb
|
||||
import de.moritzruth.theaterdsl.dmx.PerDeviceDmxDataWriter
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
|
||||
suspend fun main() {
|
||||
EnttecOpenDmxUsb.start()
|
||||
|
@ -23,6 +24,6 @@ suspend fun main() {
|
|||
awaitCancellation()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
suspend fun test() = coroutineScope {
|
||||
|
||||
}
|
|
@ -353,6 +353,7 @@ fun ShowBuilderContext.fourthAct() = act("Vierter Akt") {
|
|||
step(StepCue.MusicEnd) {
|
||||
actors {
|
||||
-"Paula"
|
||||
-"David"
|
||||
-"Theaterlehrer"
|
||||
-"Sven"
|
||||
-"Heike"
|
||||
|
@ -403,10 +404,6 @@ fun ShowBuilderContext.fourthAct() = act("Vierter Akt") {
|
|||
|
||||
scene("10") {
|
||||
step(StepCue.Text("Kai", "Hilfe, los, runter!")) {
|
||||
actors {
|
||||
+"Paula / steht bei Markierung"
|
||||
}
|
||||
|
||||
curtainState = CurtainState.OPEN
|
||||
|
||||
onRun {
|
||||
|
@ -415,6 +412,10 @@ fun ShowBuilderContext.fourthAct() = act("Vierter Akt") {
|
|||
}
|
||||
|
||||
step(StepCue.Curtain(CurtainState.OPEN, false)) {
|
||||
actors {
|
||||
+"Paula / steht bei Markierung"
|
||||
}
|
||||
|
||||
onRun {
|
||||
Tops.both.forEach { it.brightness.fade(50.percent, 1.5.seconds) }
|
||||
bar.color.static(Color.WHITE)
|
||||
|
|
|
@ -19,33 +19,32 @@ interface DynamicValue<T> {
|
|||
}
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
abstract class FloatDV<T>(private val initialStaticValue: Float) : DynamicValue<T> {
|
||||
abstract class DoubleDV<T>(private val initialStaticValue: Double) : DynamicValue<T> {
|
||||
private sealed interface State {
|
||||
data class Static(val value: Float) : State
|
||||
data class Static(val value: Double) : State
|
||||
|
||||
data class Fade(val start: Float, val end: Float, val duration: Duration) : State {
|
||||
data class Fade(val start: Double, val end: Double, val duration: Duration) : State {
|
||||
val delta = end - start
|
||||
}
|
||||
|
||||
data class Sine(
|
||||
val offset: Double,
|
||||
val minimum: Float,
|
||||
val maximum: Float,
|
||||
val period: Duration
|
||||
val minimum: Double,
|
||||
val maximum: Double,
|
||||
val b: Double,
|
||||
val c: Double
|
||||
) : State {
|
||||
companion object {
|
||||
fun calculateA(minimum: Float, maximum: Float) = (maximum - minimum) * 0.5
|
||||
fun calculateX(progress: Double, offset: Double) = 2 * PI * progress - offset
|
||||
fun calculateD(minimum: Float) = 0.5 + minimum
|
||||
fun calculateB(period: Duration) = period.inWholeMilliseconds / (2 * PI)
|
||||
fun calculateX(elapsedTime: Duration, b: Double, c: Double) = b * elapsedTime.inWholeMilliseconds + c
|
||||
}
|
||||
}
|
||||
|
||||
data class Step(val steps: ImmutableList<Float>, val interval: Duration, val startIndex: Int) : State
|
||||
data class PulseOnce(val rampUpDuration: Duration, val rampDownDuration: Duration, val peakValue: Float, val start: Float, val end: Float) : State
|
||||
data class Step(val steps: ImmutableList<Double>, val interval: Duration, val startIndex: Int) : State
|
||||
data class PulseOnce(val rampUpDuration: Duration, val rampDownDuration: Duration, val peakValue: Double, val start: Double, val end: Double) : State
|
||||
}
|
||||
|
||||
protected abstract fun toDomain(value: Float): T
|
||||
protected abstract fun fromDomain(value: T): Float
|
||||
protected abstract fun toDomain(value: Double): T
|
||||
protected abstract fun fromDomain(value: T): Double
|
||||
protected abstract val minimumValue: T
|
||||
protected abstract val maximumValue: T
|
||||
|
||||
|
@ -63,15 +62,12 @@ abstract class FloatDV<T>(private val initialStaticValue: Float) : DynamicValue<
|
|||
override fun getCurrentValue(): T {
|
||||
val elapsedTime = stateChangeMark.elapsedNow()
|
||||
|
||||
val float = when (val s = state) {
|
||||
val double = when (val s = state) {
|
||||
is State.Static -> s.value
|
||||
is State.Fade -> (min(elapsedTime / s.duration, 1.0) * s.delta + s.start).toFloat()
|
||||
is State.Fade -> (min(elapsedTime / s.duration, 1.0) * s.delta + s.start)
|
||||
is State.Sine -> {
|
||||
val a = State.Sine.calculateA(s.minimum, s.maximum)
|
||||
val x = State.Sine.calculateX(elapsedTime / s.period, s.offset)
|
||||
val d = State.Sine.calculateD(s.minimum)
|
||||
|
||||
(a * sin(x) + d).toFloat()
|
||||
val fromZeroToOne = (sin(State.Sine.calculateX(elapsedTime, s.b, s.c)) + 1) / 2
|
||||
(fromZeroToOne * (s.maximum - s.minimum) + s.minimum)
|
||||
}
|
||||
|
||||
is State.Step -> {
|
||||
|
@ -83,16 +79,16 @@ abstract class FloatDV<T>(private val initialStaticValue: Float) : DynamicValue<
|
|||
if (elapsedTime <= s.rampUpDuration) {
|
||||
val progress = elapsedTime / s.rampUpDuration
|
||||
val delta = s.peakValue - s.start
|
||||
(progress * delta + s.start).toFloat()
|
||||
(progress * delta + s.start)
|
||||
} else {
|
||||
val progress = min(elapsedTime / s.rampDownDuration, 1.0)
|
||||
val delta = s.peakValue - s.end
|
||||
(s.peakValue - progress * delta).toFloat()
|
||||
(s.peakValue - progress * delta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toDomain(float)
|
||||
return toDomain(double)
|
||||
}
|
||||
|
||||
fun static(value: T) {
|
||||
|
@ -108,9 +104,14 @@ abstract class FloatDV<T>(private val initialStaticValue: Float) : DynamicValue<
|
|||
}
|
||||
|
||||
fun sine(period: Duration, minimum: T = minimumValue, maximum: T = maximumValue, start: T = getCurrentValue()) {
|
||||
val coercedStart = fromDomain(start).coerceIn(fromDomain(minimum), fromDomain(maximum))
|
||||
val offset = asin((coercedStart - State.Sine.calculateD(fromDomain(minimum))) / State.Sine.calculateA(fromDomain(minimum), fromDomain(maximum)))
|
||||
state = State.Sine(offset, fromDomain(minimum), fromDomain(maximum), period)
|
||||
val b = State.Sine.calculateB(period)
|
||||
val doubleMinimum = fromDomain(minimum)
|
||||
val doubleMaximum = fromDomain(maximum)
|
||||
val delta = doubleMaximum - doubleMinimum
|
||||
|
||||
val coercedStart = fromDomain(start).coerceIn(doubleMinimum, fromDomain(maximum))
|
||||
val c = asin(2 * ((coercedStart - doubleMinimum) / delta) - 1)
|
||||
state = State.Sine(fromDomain(minimum), fromDomain(maximum), b, c)
|
||||
}
|
||||
|
||||
fun steps(steps: List<T>, interval: Duration, startIndex: Int = 0) {
|
||||
|
@ -132,16 +133,16 @@ abstract class FloatDV<T>(private val initialStaticValue: Float) : DynamicValue<
|
|||
}
|
||||
}
|
||||
|
||||
class PercentageDV(initialStaticValue: Percentage = 0.percent) : FloatDV<Percentage>(initialStaticValue.value) {
|
||||
override fun fromDomain(value: Percentage): Float = value.value
|
||||
override fun toDomain(value: Float): Percentage = Percentage(value)
|
||||
class PercentageDV(initialStaticValue: Percentage = 0.percent) : DoubleDV<Percentage>(initialStaticValue.value) {
|
||||
override fun fromDomain(value: Percentage): Double = value.value
|
||||
override fun toDomain(value: Double): Percentage = Percentage(value)
|
||||
override val minimumValue: Percentage = 0.percent
|
||||
override val maximumValue: Percentage = 100.percent
|
||||
}
|
||||
|
||||
class AngleDV(initialStaticValue: Angle = 0.degrees) : FloatDV<Angle>(initialStaticValue.degrees) {
|
||||
override fun fromDomain(value: Angle): Float = value.degrees
|
||||
override fun toDomain(value: Float): Angle = Angle(value)
|
||||
class AngleDV(initialStaticValue: Angle = 0.degrees) : DoubleDV<Angle>(initialStaticValue.degrees) {
|
||||
override fun fromDomain(value: Angle): Double = value.degrees
|
||||
override fun toDomain(value: Double): Angle = Angle(value)
|
||||
override val minimumValue: Angle = 0.degrees
|
||||
override val maximumValue: Angle = 360.degrees
|
||||
}
|
||||
|
@ -199,9 +200,9 @@ class ColorDV(private val initialStaticValue: Color = Color.WHITE) : DynamicValu
|
|||
val progress = min(elapsedTime / s.duration, 1.0)
|
||||
|
||||
Color(
|
||||
hue = Angle((s.start.hue.degrees + s.deltaHue * progress).toFloat()),
|
||||
saturation = Percentage((s.start.saturation.value + s.deltaSaturation * progress).toFloat()),
|
||||
brightness = Percentage((s.start.brightness.value + s.deltaBrightness * progress).toFloat())
|
||||
hue = Angle((s.start.hue.degrees + s.deltaHue * progress)),
|
||||
saturation = Percentage((s.start.saturation.value + s.deltaSaturation * progress)),
|
||||
brightness = Percentage((s.start.brightness.value + s.deltaBrightness * progress))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -209,11 +210,11 @@ class ColorDV(private val initialStaticValue: Color = Color.WHITE) : DynamicValu
|
|||
val startRandom = Random((elapsedTime / s.interval).toInt() - 1)
|
||||
val endRandom = Random((elapsedTime / s.interval).toInt())
|
||||
val progress = (elapsedTime / s.interval).mod(1.0)
|
||||
val startHue = s.hue.degrees - s.deviation.degrees + startRandom.nextFloat() * s.deviation.degrees * 2
|
||||
val endHue = s.hue.degrees - s.deviation.degrees + endRandom.nextFloat() * s.deviation.degrees * 2
|
||||
val startHue = s.hue.degrees - s.deviation.degrees + startRandom.nextDouble() * s.deviation.degrees * 2
|
||||
val endHue = s.hue.degrees - s.deviation.degrees + endRandom.nextDouble() * s.deviation.degrees * 2
|
||||
val delta = endHue - startHue
|
||||
|
||||
Color(hue = Angle((progress * delta).toFloat()))
|
||||
Color(hue = Angle((progress * delta)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ interface DmxDataWriter {
|
|||
/**
|
||||
* @param startAtOne Whether the written value is in `1..255` or in `0..255`.
|
||||
*/
|
||||
fun writeInRange(range: ClosedFloatingPointRange<Float>, value: Float, startAtOne: Boolean = false) =
|
||||
fun writeInRange(range: ClosedFloatingPointRange<Double>, value: Double, startAtOne: Boolean = false) =
|
||||
writeRaw(Percentage((value - range.start) / (range.endInclusive - range.start)).roundToDmxValue(startAtOne))
|
||||
|
||||
fun writeHighByte(value: UShort) = writeRaw(DmxValue(value.toUInt().shr(8).toUByte()))
|
||||
|
|
|
@ -16,5 +16,5 @@ value class DmxValue(val value: UByte) : Comparable<UByte> {
|
|||
* @param startAtOne Whether the output range is `1..255` or `0..255`.
|
||||
*/
|
||||
fun Percentage.roundToDmxValue(startAtOne: Boolean = false): DmxValue =
|
||||
if (startAtOne) DmxValue(((value * (DmxValue.VALUE_RANGE.last.toFloat() - 1f)).roundToInt() + 1).toUByte())
|
||||
else DmxValue((value * DmxValue.VALUE_RANGE.last.toFloat()).roundToInt().toUByte())
|
||||
if (startAtOne) DmxValue(((value * (DmxValue.VALUE_RANGE.last.toDouble() - 1f)).roundToInt() + 1).toUByte())
|
||||
else DmxValue((value * DmxValue.VALUE_RANGE.last.toDouble()).roundToInt().toUByte())
|
|
@ -88,7 +88,7 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
|||
|
||||
var leftSpotTarget: String?
|
||||
var rightSpotTarget: String?
|
||||
var curtainState = CurtainState.CLOSED
|
||||
var curtainState_ = CurtainState.CLOSED
|
||||
|
||||
object : ActBuilderContext {
|
||||
override fun scene(@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") sceneName: String, build: SceneBuilderContext.() -> Unit) {
|
||||
|
@ -111,7 +111,11 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
|||
override val props = PropsBuilderMap(changedProps)
|
||||
override var rightSpotTarget: String? = null
|
||||
override var leftSpotTarget: String? = null
|
||||
override var curtainState: CurtainState by ::curtainState
|
||||
override var curtainState: CurtainState
|
||||
get() = curtainState_
|
||||
set(value) {
|
||||
curtainState_ = value
|
||||
}
|
||||
|
||||
override fun actors(build: ActorsBuildContext.() -> Unit) {
|
||||
ActorsBuildContext(actorEntrances, actorExits).build()
|
||||
|
@ -155,7 +159,7 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
|||
logger.warn("These actors cannot enter because they are already on the stage: ${addedActorsAlreadyOnStage.joinToString()}")
|
||||
}
|
||||
|
||||
actorsOnStage.removeAll(actorExitsNames)
|
||||
actorsOnStage.removeAll(actorExitsNames.toSet())
|
||||
actorsOnStage.addAll(actorEntrancesNames)
|
||||
|
||||
changedProps.forEach { (k, v) -> props[k] = v }
|
||||
|
@ -171,7 +175,7 @@ private fun buildAct(actIndex: Int, actName: String, build: ActBuilderContext.()
|
|||
changedProps.isNotEmpty(),
|
||||
leftSpotTarget,
|
||||
rightSpotTarget,
|
||||
curtainState,
|
||||
curtainState_,
|
||||
runner
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package de.moritzruth.theaterdsl.value
|
||||
|
||||
@JvmInline
|
||||
value class Angle(val degrees: Float) : Comparable<Angle> {
|
||||
value class Angle(val degrees: Double) : Comparable<Angle> {
|
||||
override fun toString(): String = "${degrees}°"
|
||||
|
||||
override fun compareTo(other: Angle): Int = degrees.compareTo(other.degrees)
|
||||
|
||||
fun inSingleRotation(): Angle = Angle(
|
||||
if (degrees == 360f || degrees == -360f) degrees
|
||||
if (degrees == 360.0 || degrees == -360.0) degrees
|
||||
else degrees.mod(360f)
|
||||
)
|
||||
|
||||
|
@ -17,18 +17,18 @@ value class Angle(val degrees: Float) : Comparable<Angle> {
|
|||
): ClosedFloatingPointRange<Angle> {
|
||||
override fun lessThanOrEquals(a: Angle, b: Angle): Boolean = a.degrees <= b.degrees
|
||||
|
||||
fun asFloatRange(): ClosedFloatingPointRange<Float> = start.degrees..endInclusive.degrees
|
||||
fun asDoubleRange(): ClosedFloatingPointRange<Double> = start.degrees..endInclusive.degrees
|
||||
|
||||
companion object {
|
||||
val FULL_ROTATION: Range = Range(Angle(0f), Angle(360f))
|
||||
val FULL_ROTATION: Range = Range(Angle(0.0), Angle(360.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline val Int.degrees: Angle
|
||||
get() = Angle(this.toFloat())
|
||||
get() = Angle(this.toDouble())
|
||||
|
||||
inline val Double.degrees: Angle
|
||||
get() = Angle(this.toFloat())
|
||||
get() = Angle(this)
|
||||
|
||||
fun Float.asAngle(): Angle = Angle(this)
|
||||
fun Double.asAngle(): Angle = Angle(this)
|
||||
|
|
|
@ -13,44 +13,44 @@ data class Color(
|
|||
val x = c * (1 - abs(h.mod(2f) - 1))
|
||||
val m = brightness.value - c
|
||||
|
||||
val r: Float
|
||||
val g: Float
|
||||
val b: Float
|
||||
val r: Double
|
||||
val g: Double
|
||||
val b: Double
|
||||
|
||||
when {
|
||||
h < 1 -> {
|
||||
r = c
|
||||
g = x
|
||||
b = 0f
|
||||
b = 0.0
|
||||
}
|
||||
|
||||
h < 2 -> {
|
||||
r = x
|
||||
g = c
|
||||
b = 0f
|
||||
b = 0.0
|
||||
}
|
||||
|
||||
h < 3 -> {
|
||||
r = 0f
|
||||
r = 0.0
|
||||
g = c
|
||||
b = x
|
||||
}
|
||||
|
||||
h < 4 -> {
|
||||
r = 0f
|
||||
r = 0.0
|
||||
g = x
|
||||
b = c
|
||||
}
|
||||
|
||||
h < 5 -> {
|
||||
r = x
|
||||
g = 0f
|
||||
g = 0.0
|
||||
b = c
|
||||
}
|
||||
|
||||
else /* h < 6 */ -> {
|
||||
r = c
|
||||
g = 0f
|
||||
g = 0.0
|
||||
b = x
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package de.moritzruth.theaterdsl.value
|
||||
|
||||
@JvmInline
|
||||
value class Frequency(val hertz: Float) : Comparable<Frequency> {
|
||||
value class Frequency(val hertz: Double) : Comparable<Frequency> {
|
||||
companion object {
|
||||
val ZERO: Frequency = Frequency(0f)
|
||||
val INFINITY: Frequency = Frequency(Float.POSITIVE_INFINITY)
|
||||
val ZERO: Frequency = Frequency(0.0)
|
||||
val INFINITY: Frequency = Frequency(Double.POSITIVE_INFINITY)
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -21,7 +21,7 @@ value class Frequency(val hertz: Float) : Comparable<Frequency> {
|
|||
) : ClosedFloatingPointRange<Frequency> {
|
||||
override fun lessThanOrEquals(a: Frequency, b: Frequency): Boolean = a.hertz <= b.hertz
|
||||
|
||||
fun asFloatRange(): ClosedFloatingPointRange<Float> = start.hertz..endInclusive.hertz
|
||||
fun asDoubleRange(): ClosedFloatingPointRange<Double> = start.hertz..endInclusive.hertz
|
||||
|
||||
override fun toString(): String = "$start..$endInclusive"
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@ import kotlin.math.pow
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
val IntProgression.delta: Int get() = last - first
|
||||
val ClosedFloatingPointRange<Float>.delta: Float get() = endInclusive - start
|
||||
val ClosedFloatingPointRange<Double>.delta: Double get() = endInclusive - start
|
||||
|
||||
fun Int.transfer(from: IntRange, to: IntRange): Int =
|
||||
((this - from.first) / from.delta) * to.delta + to.first
|
||||
|
||||
fun Float.transfer(from: ClosedFloatingPointRange<Float>, to: ClosedFloatingPointRange<Float>): Float =
|
||||
fun Double.transfer(from: ClosedFloatingPointRange<Double>, to: ClosedFloatingPointRange<Double>): Double =
|
||||
((this - from.start) / from.delta) * to.delta + to.start
|
||||
|
||||
fun Float.toString(decimalPlaces: Int): String {
|
||||
fun Double.toString(decimalPlaces: Int): String {
|
||||
val s = (this * (10f.pow(decimalPlaces))).roundToInt().toString().padStart(decimalPlaces + 1, '0')
|
||||
return s.dropLast(decimalPlaces) + "." + s.takeLast(decimalPlaces)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
package de.moritzruth.theaterdsl.value
|
||||
|
||||
@JvmInline
|
||||
value class Percentage(val value: Float) : Comparable<Percentage> {
|
||||
value class Percentage(val value: Double) : Comparable<Percentage> {
|
||||
companion object {
|
||||
val VALUE_RANGE: ClosedFloatingPointRange<Float> = 0f..1f
|
||||
val VALUE_RANGE: ClosedFloatingPointRange<Double> = 0.0..1.0
|
||||
}
|
||||
|
||||
init {
|
||||
require(value in VALUE_RANGE) { "value ($value) must be in 0..1" }
|
||||
}
|
||||
|
||||
fun ofRange(range: ClosedFloatingPointRange<Float>): Float = value.transfer(VALUE_RANGE, range)
|
||||
fun ofRange(range: ClosedFloatingPointRange<Double>): Double = value.transfer(VALUE_RANGE, range)
|
||||
|
||||
override fun compareTo(other: Percentage): Int = value.compareTo(other.value)
|
||||
|
||||
|
@ -22,7 +22,7 @@ value class Percentage(val value: Float) : Comparable<Percentage> {
|
|||
) : ClosedFloatingPointRange<Percentage> {
|
||||
override fun lessThanOrEquals(a: Percentage, b: Percentage): Boolean = a.value <= b.value
|
||||
|
||||
fun asFloatRange(): ClosedFloatingPointRange<Float> = start.value..endInclusive.value
|
||||
fun asDoubleRange(): ClosedFloatingPointRange<Double> = start.value..endInclusive.value
|
||||
|
||||
companion object {
|
||||
val FULL: Range = Range(VALUE_RANGE.start.asPercentage(), VALUE_RANGE.endInclusive.asPercentage())
|
||||
|
@ -32,16 +32,16 @@ value class Percentage(val value: Float) : Comparable<Percentage> {
|
|||
|
||||
inline val Int.percent: Percentage
|
||||
get() = try {
|
||||
Percentage(this / 100f)
|
||||
Percentage(this / 100.0)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw IllegalArgumentException("must be in 0..100")
|
||||
}
|
||||
|
||||
inline val Double.percent: Percentage
|
||||
get() = try {
|
||||
Percentage(this.toFloat() / 100f)
|
||||
Percentage(this / 100f)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
throw IllegalArgumentException("must be in 0..100")
|
||||
}
|
||||
|
||||
fun Float.asPercentage(): Percentage = Percentage(this)
|
||||
fun Double.asPercentage(): Percentage = Percentage(this)
|
||||
|
|
|
@ -3,31 +3,31 @@ package de.moritzruth.theaterdsl.value
|
|||
import kotlinx.collections.immutable.ImmutableSet
|
||||
import kotlin.math.abs
|
||||
|
||||
data class FloatRangesAndValues(val ranges: ImmutableSet<ClosedFloatingPointRange<Float>>, val values: ImmutableSet<Float>) {
|
||||
data class DoubleRangesAndValues(val ranges: ImmutableSet<ClosedFloatingPointRange<Double>>, val values: ImmutableSet<Double>) {
|
||||
init {
|
||||
require(ranges.isNotEmpty() || values.isNotEmpty()) { "at least one range or value is required" }
|
||||
}
|
||||
|
||||
val highest: Float
|
||||
val highestBeforeInfinity: Float
|
||||
val lowest: Float
|
||||
val lowestAfterInfinity: Float
|
||||
val highest: Double
|
||||
val highestBeforeInfinity: Double
|
||||
val lowest: Double
|
||||
val lowestAfterInfinity: Double
|
||||
|
||||
init {
|
||||
var l = Float.POSITIVE_INFINITY
|
||||
var lai = Float.POSITIVE_INFINITY
|
||||
var h = Float.NEGATIVE_INFINITY
|
||||
var hbi = Float.NEGATIVE_INFINITY
|
||||
var l = Double.POSITIVE_INFINITY
|
||||
var lai = Double.POSITIVE_INFINITY
|
||||
var h = Double.NEGATIVE_INFINITY
|
||||
var hbi = Double.NEGATIVE_INFINITY
|
||||
|
||||
for (v in values + ranges.flatMap { listOf(it.start, it.endInclusive) }) {
|
||||
if (v < lai) {
|
||||
l = v
|
||||
if (v != Float.NEGATIVE_INFINITY) lai = v
|
||||
if (v != Double.NEGATIVE_INFINITY) lai = v
|
||||
}
|
||||
|
||||
if (v > hbi) {
|
||||
h = v
|
||||
if (v != Float.POSITIVE_INFINITY) hbi = v
|
||||
if (v != Double.POSITIVE_INFINITY) hbi = v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,12 +37,12 @@ data class FloatRangesAndValues(val ranges: ImmutableSet<ClosedFloatingPointRang
|
|||
lowestAfterInfinity = lai
|
||||
}
|
||||
|
||||
fun getNearestTo(value: Float): Float {
|
||||
var nearestValue = 0f
|
||||
var nearestDistance = 0f
|
||||
fun getNearestTo(value: Double): Double {
|
||||
var nearestValue = 0.0
|
||||
var nearestDistance = 0.0
|
||||
var isFirst = true
|
||||
|
||||
fun update(v: Float) {
|
||||
fun update(v: Double) {
|
||||
if (isFirst) {
|
||||
nearestValue = v
|
||||
nearestDistance = v - value
|
||||
|
@ -71,5 +71,5 @@ data class FloatRangesAndValues(val ranges: ImmutableSet<ClosedFloatingPointRang
|
|||
return nearestValue
|
||||
}
|
||||
|
||||
operator fun contains(value: Float): Boolean = getNearestTo(value) == value
|
||||
operator fun contains(value: Double): Boolean = getNearestTo(value) == value
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package de.moritzruth.theaterdsl.value
|
||||
|
||||
@JvmInline
|
||||
value class Temperature(val kelvin: Float) : Comparable<Temperature> {
|
||||
value class Temperature(val kelvin: Double) : Comparable<Temperature> {
|
||||
override fun toString(): String = "${kelvin}K"
|
||||
|
||||
override fun compareTo(other: Temperature): Int = kelvin.compareTo(other.kelvin)
|
||||
|
|
Loading…
Add table
Reference in a new issue