package eu.ztsh.garmin.data class GarminMapper { companion object { fun map(lanes: Lanes): IntArray { return intArrayOf(0x02, lanes.lanes.lanes.sumOf { it.value }, lanes.outlines.lanes.sumOf { it.value }) } fun map(direction: Direction): IntArray { return toDirectionArray(direction.angle, direction.out, direction.roundabout) } fun map(distance: Distance): IntArray { return setDistance(distance.distance, distance.unit) } fun map(speed: Speed): IntArray { return setSpeed(speed.speed, speed.limit, speed.limit > 0 && speed.speed > speed.limit) } fun setTime(hours: Int, minutes: Int, traffic: Boolean = false, flag: Boolean = false): IntArray { val trafficChar = asChar(traffic) val flagChar = asChar(flag) return if (hours > 99) { intArrayOf( 0x05, trafficChar, asDigit(hours / 1000), asDigit(hours / 100), 0x00, asDigit(hours / 10), asDigit(hours), 0xff, flagChar ) } else { intArrayOf( 0x05, trafficChar, asDigit(hours / 10), asDigit(hours), 0xff, asDigit(minutes / 10), asDigit(minutes), 0x00, flagChar ) } } fun speedControl(state: Boolean): IntArray { return intArrayOf(0x04, if (state) 0x01 else 0x02) } fun cleanDistance(): IntArray { return intArrayOf(0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) } private fun toDirectionArray( angle: OutAngle, out: OutType = OutType.Lane, roundabout: OutAngle = OutAngle.AsDirection ): IntArray { val param1: Int = when (angle) { OutAngle.LeftDown -> 0x10 OutAngle.RightDown -> 0x20 else -> out.value } val param2: Int = if (out == OutType.RightRoundabout || out == OutType.LeftRoundabout ) { if (roundabout == OutAngle.AsDirection) angle.value else roundabout.value } else { 0x00 } val param3: Int = if (angle == OutAngle.LeftDown || angle == OutAngle.RightDown) 0x00 else angle.value return intArrayOf(0x01, param1, param2, param3) } private fun setDistance(distance: Double, unit: Unit = Unit.Any): IntArray { val isDecimal = (distance * 10).toInt() != (distance.toInt() * 10) val distanceValue = if (isDecimal) distance * 10 else distance return intArrayOf( 0x03, asDigit(distanceValue / 1000), // position 1 asDigit(distanceValue / 100), // position 2 asDigit(distanceValue / 10), // position 3 if (isDecimal) 0xff else 0x00, // comma asDigit(distanceValue), // position 4 unit.value // unit ) } private fun setSpeed( speed: Int, limit: Int = 0, limitWarning: Boolean = false, acc: Boolean = false ): IntArray { // TODO: car connection val accChar = asChar(acc) val limitWarningChar = asChar(limitWarning) return if (limit > 0) { intArrayOf( 0x06, asDigit(speed / 100), asDigit(speed / 10), asDigit(speed), 0xff, asDigit(limit / 100), asDigit(limit / 10), asDigit(limit), limitWarningChar, accChar ) } else { intArrayOf( 0x06, 0x00, 0x00, 0x00, 0x00, asDigit(speed / 100), asDigit(speed / 10), asDigit(speed), limitWarningChar, accChar ) } } private fun asDigit(n: Double): Int { return asDigit(n.toInt()) } private fun asDigit(n: Int): Int { if (n == 0) { return 0 } val m = n % 10 return if (m == 0) 10 else m } private fun asChar(boolean: Boolean): Int { return if (boolean) 0xff else 0x00 } } }