workinggggg!!!!!!!

- fix map tiles proto colours KTable
- test and tidy up Colour/ColourHex
- reset event-server application
This commit is contained in:
Adam 2022-02-08 11:51:16 +01:00
parent bdb2d9577f
commit 5a59b3bd6d
13 changed files with 211 additions and 97 deletions

View file

@ -1,6 +1,7 @@
package dev.adamko.kafkatorio.events.schema.converters
import dev.adamko.kafkatorio.events.schema.Colour
import dev.adamko.kafkatorio.events.schema.ColourHex
import kotlin.math.roundToInt
@ -15,39 +16,12 @@ fun Colour.isHexadecimal(): Boolean {
/** True if all values are between `[0..1]`. */
fun Colour.isPercentage(): Boolean = !isHexadecimal()
fun Colour.toHexadecimal() = if (isPercentage()) {
Colour(
(red * 255).coerceIn(0f..255f),
(green * 255).coerceIn(0f..255f),
(blue * 255).coerceIn(0f..255f),
(alpha * 255).coerceIn(0f..255f),
)
} else {
Colour(
red.coerceIn(0f..255f),
green.coerceIn(0f..255f),
blue.coerceIn(0f..255f),
alpha.coerceIn(0f..255f),
)
}
fun Colour.toPercentage() = if (isPercentage()) {
this
} else {
Colour(
(red / 255).coerceIn(0f..1f),
(green / 255).coerceIn(0f..1f),
(blue / 255).coerceIn(0f..1f),
(alpha / 255).coerceIn(0f..1f),
)
}
fun Colour.toHexString(includeAlpha: Boolean = false): String {
val hexConverter: Float.() -> String = if (isHexadecimal()) {
Float::decimalToHex
} else {
Float::percentageToHex
val hexConverter: Float.() -> String = when {
isHexadecimal() -> Float::hexadecimalToString
else -> Float::percentageToHexadecimalString
}
val length = if (includeAlpha) 9 else 7
@ -62,8 +36,51 @@ fun Colour.toHexString(includeAlpha: Boolean = false): String {
}
}
fun Float.decimalToHex(): String =
fun Float.hexadecimalToString(): String =
roundToInt().toString(16).padStart(2, ' ')
fun Float.percentageToHex(): String =
fun Float.percentageToHexadecimalString(): String =
times(255).roundToInt().toString(16).padStart(2, ' ')
private val ubyteMaxFloat = UByte.MAX_VALUE.toFloat()
private val ubyteMinFloat = UByte.MIN_VALUE.toFloat()
private val ubyteRangeFloat = ubyteMinFloat..ubyteMaxFloat
private fun Float.toColourHex() = (this * ubyteMaxFloat)
.coerceIn(ubyteRangeFloat)
.toUInt()
.toUByte()
private fun Float.coerceToColourHex() = coerceIn(ubyteRangeFloat)
.toUInt()
.toUByte()
fun Colour.toHex(): ColourHex {
val converter: Float.() -> UByte = when {
isPercentage() -> Float::toColourHex
else -> Float::coerceToColourHex
}
return ColourHex(
red.converter(),
green.converter(),
blue.converter(),
alpha.converter(),
)
}
private fun UByte.toPercentileFloat() = (this.toFloat() / ubyteMaxFloat).coerceIn(0f..1f)
fun ColourHex.toPercentile(): Colour {
return Colour(
red.toPercentileFloat(),
green.toPercentileFloat(),
blue.toPercentileFloat(),
alpha.toPercentileFloat(),
)
}

View file

@ -1,7 +1,6 @@
package dev.adamko.kafkatorio.events.schema.converters
import dev.adamko.kafkatorio.events.schema.MAP_CHUNK_SIZE
import dev.adamko.kafkatorio.events.schema.MapBoundingBox
import dev.adamko.kafkatorio.events.schema.MapChunkPosition
import dev.adamko.kafkatorio.events.schema.MapEntityPosition
import dev.adamko.kafkatorio.events.schema.MapTilePosition
@ -17,7 +16,7 @@ operator fun MapTilePosition.plus(addend: Int) =
MapTilePosition(x + addend, y + addend)
fun MapTilePosition.toMapChunkPosition( chunkSize: Int = MAP_CHUNK_SIZE) =
fun MapTilePosition.toMapChunkPosition(chunkSize: Int = MAP_CHUNK_SIZE) =
MapChunkPosition(
floor(x.toDouble() / chunkSize.toDouble()).toInt(),
floor(y.toDouble() / chunkSize.toDouble()).toInt(),
@ -27,7 +26,7 @@ fun MapTilePosition.toMapChunkPosition( chunkSize: Int = MAP_CHUNK_SIZE) =
fun MapEntityPosition.toMapTilePosition() =
MapChunkPosition(floor(x).toInt(), floor(y).toInt())
fun MapEntityPosition.toMapChunkPosition( chunkSize: Int = MAP_CHUNK_SIZE) =
fun MapEntityPosition.toMapChunkPosition(chunkSize: Int = MAP_CHUNK_SIZE) =
MapChunkPosition(
floor(x / chunkSize.toDouble()).toInt(),
floor(y / chunkSize.toDouble()).toInt(),
@ -44,8 +43,8 @@ operator fun MapChunkPosition.minus(subtrahend: Int) =
MapChunkPosition(x - subtrahend, y - subtrahend)
fun MapChunkPosition.leftTopTile( chunkSize: Int = MAP_CHUNK_SIZE): MapTilePosition =
MapTilePosition(
fun MapChunkPosition.leftTopTile(chunkSize: Int = MAP_CHUNK_SIZE): MapTilePosition =
MapTilePosition(
x * chunkSize,
y * chunkSize,
)

View file

@ -1,6 +1,5 @@
package dev.adamko.kafkatorio.events.schema
import dev.adamko.kafkatorio.events.schema.converters.toHexadecimal
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.Serializable
@ -69,20 +68,10 @@ data class Colour(
val blue: Float = 0f,
@EncodeDefault
val alpha: Float = 1f,
) {
fun toHex() = toHexadecimal().let {
ColourHex(
it.red.toUInt().toUByte(),
it.green.toUInt().toUByte(),
it.blue.toUInt().toUByte(),
it.alpha.toUInt().toUByte(),
)
}
}
)
/** Size-efficient version of [Colour] */
/** Size-efficient version of [Colour] (`4*4` bytes vs `4*1` bytes) */
@Serializable
data class ColourHex(
@EncodeDefault

View file

@ -0,0 +1,86 @@
package dev.adamko.kafkatorio.events.schema
import dev.adamko.kafkatorio.events.schema.converters.toHex
import dev.adamko.kafkatorio.events.schema.converters.toPercentile
import io.kotest.assertions.withClue
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.floats.shouldBeWithinPercentageOf
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.property.checkAll
import kotlinx.serialization.decodeFromString
class ColourHexTest : BehaviorSpec({
Given("colour json") {
//Language=JSON
val colourJson = """
{
"red": 0.1,
"green": 0.4,
"blue": 0.7,
"alpha": 0.6
}
""".trimIndent()
val colour: Colour = jsonMapperKafkatorio.decodeFromString(colourJson)
Then("expect colour is decoded") {
colour shouldBe Colour(
0.1f,
0.4f,
0.7f,
0.6f,
)
}
Then("expect Colour can be converted to ColourHex and back") {
val colourHex = colour.toHex()
colourHex shouldBe ColourHex(
25u,
102u,
178u,
153u,
)
colourHex.toPercentile() should { back ->
withClue(back) {
val tolerance = 2.6 // 2.6%, because 255/100 = 2.55
withClue("red") { back.red.shouldBeWithinPercentageOf(0.1f, tolerance) }
withClue("green") { back.green.shouldBeWithinPercentageOf(0.4f, tolerance) }
withClue("blue") { back.blue.shouldBeWithinPercentageOf(0.7f, tolerance) }
withClue("alpha") { back.alpha.shouldBeWithinPercentageOf(0.6f, tolerance) }
}
}
}
}
Given("any colour json") {
Then("expect can always convert") {
checkAll<UByte, UByte, UByte, UByte> { r, g, b, a ->
//Language=JSON
val colourJson = """
{
"red": ${r.toFloat() / UByte.MAX_VALUE.toFloat()},
"green": ${g.toFloat() / UByte.MAX_VALUE.toFloat()},
"blue": ${b.toFloat() / UByte.MAX_VALUE.toFloat()},
"alpha": ${a.toFloat() / UByte.MAX_VALUE.toFloat()}
}
""".trimIndent()
val colour: Colour = jsonMapperKafkatorio.decodeFromString(colourJson)
val colourHex = colour.toHex()
colourHex shouldBe ColourHex(r, g, b, a)
}
}
}
})