From 952797f54143624782bd033f78574d606584fa2d Mon Sep 17 00:00:00 2001 From: Travis Wyatt Date: Tue, 7 Jan 2025 10:49:57 -0800 Subject: [PATCH] Provide `LocalDate` interpolator --- interpolate/api/interpolate.api | 1 + interpolate/api/interpolate.klib.api | 1 + .../src/commonMain/kotlin/Interpolator.kt | 6 ++++++ .../commonMain/kotlin/LinearInterpolator.kt | 18 ++++++++++++++++++ scale/api/scale.api | 4 ++++ scale/api/scale.klib.api | 4 ++++ scale/src/commonMain/kotlin/ContinuousScale.kt | 15 +++++++++++++++ 7 files changed, 49 insertions(+) diff --git a/interpolate/api/interpolate.api b/interpolate/api/interpolate.api index 2b3f2bd5..871897cc 100644 --- a/interpolate/api/interpolate.api +++ b/interpolate/api/interpolate.api @@ -14,6 +14,7 @@ public final class com/juul/krayon/interpolate/InterpolatorKt { public static final fun interpolator (FF)Lcom/juul/krayon/interpolate/BidirectionalInterpolator; public static final fun interpolator (II)Lcom/juul/krayon/interpolate/BidirectionalInterpolator; public static final fun interpolator (Lkotlinx/datetime/Instant;Lkotlinx/datetime/Instant;)Lcom/juul/krayon/interpolate/BidirectionalInterpolator; + public static final fun interpolator (Lkotlinx/datetime/LocalDate;Lkotlinx/datetime/LocalDate;)Lcom/juul/krayon/interpolate/BidirectionalInterpolator; public static final fun interpolator (Lkotlinx/datetime/LocalDateTime;Lkotlinx/datetime/LocalDateTime;)Lcom/juul/krayon/interpolate/BidirectionalInterpolator; public static final fun interpolator-h4DbW5E (II)Lcom/juul/krayon/interpolate/Interpolator; } diff --git a/interpolate/api/interpolate.klib.api b/interpolate/api/interpolate.klib.api index c66b4b1a..1e7d892e 100644 --- a/interpolate/api/interpolate.klib.api +++ b/interpolate/api/interpolate.klib.api @@ -22,4 +22,5 @@ final fun com.juul.krayon.interpolate/interpolator(kotlin/Double, kotlin/Double) final fun com.juul.krayon.interpolate/interpolator(kotlin/Float, kotlin/Float): com.juul.krayon.interpolate/BidirectionalInterpolator // com.juul.krayon.interpolate/interpolator|interpolator(kotlin.Float;kotlin.Float){}[0] final fun com.juul.krayon.interpolate/interpolator(kotlin/Int, kotlin/Int): com.juul.krayon.interpolate/BidirectionalInterpolator // com.juul.krayon.interpolate/interpolator|interpolator(kotlin.Int;kotlin.Int){}[0] final fun com.juul.krayon.interpolate/interpolator(kotlinx.datetime/Instant, kotlinx.datetime/Instant): com.juul.krayon.interpolate/BidirectionalInterpolator // com.juul.krayon.interpolate/interpolator|interpolator(kotlinx.datetime.Instant;kotlinx.datetime.Instant){}[0] +final fun com.juul.krayon.interpolate/interpolator(kotlinx.datetime/LocalDate, kotlinx.datetime/LocalDate): com.juul.krayon.interpolate/BidirectionalInterpolator // com.juul.krayon.interpolate/interpolator|interpolator(kotlinx.datetime.LocalDate;kotlinx.datetime.LocalDate){}[0] final fun com.juul.krayon.interpolate/interpolator(kotlinx.datetime/LocalDateTime, kotlinx.datetime/LocalDateTime): com.juul.krayon.interpolate/BidirectionalInterpolator // com.juul.krayon.interpolate/interpolator|interpolator(kotlinx.datetime.LocalDateTime;kotlinx.datetime.LocalDateTime){}[0] diff --git a/interpolate/src/commonMain/kotlin/Interpolator.kt b/interpolate/src/commonMain/kotlin/Interpolator.kt index f8c21c8d..62478795 100644 --- a/interpolate/src/commonMain/kotlin/Interpolator.kt +++ b/interpolate/src/commonMain/kotlin/Interpolator.kt @@ -2,6 +2,7 @@ package com.juul.krayon.interpolate import com.juul.krayon.color.Color import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime public interface Interpolator { @@ -28,6 +29,11 @@ public fun interpolator( stop: Instant, ): BidirectionalInterpolator = LinearInstantInterpolator(start, stop) +public fun interpolator( + start: LocalDate, + stop: LocalDate, +): BidirectionalInterpolator = LinearLocalDateInterpolator(start, stop) + public fun interpolator( start: LocalDateTime, stop: LocalDateTime, diff --git a/interpolate/src/commonMain/kotlin/LinearInterpolator.kt b/interpolate/src/commonMain/kotlin/LinearInterpolator.kt index 670e3d75..5f47540c 100644 --- a/interpolate/src/commonMain/kotlin/LinearInterpolator.kt +++ b/interpolate/src/commonMain/kotlin/LinearInterpolator.kt @@ -4,8 +4,12 @@ import com.juul.krayon.color.Color import com.juul.krayon.color.lerp import com.juul.krayon.time.minus import com.juul.krayon.time.plus +import kotlinx.datetime.DatePeriod import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.plus +import kotlin.math.roundToInt internal class LinearIntInterpolator( private val start: Int, @@ -51,6 +55,20 @@ internal class LinearInstantInterpolator( override fun invert(value: Instant): Float = ((value - start) / range).toFloat() } +internal class LinearLocalDateInterpolator( + private val start: LocalDate, + stop: LocalDate, +) : BidirectionalInterpolator { + + private val range = stop.toEpochDays() - start.toEpochDays() + + override fun interpolate(fraction: Float): LocalDate = + start + DatePeriod(days = (range * fraction).roundToInt()) + + override fun invert(value: LocalDate): Float = + (value.toEpochDays() - start.toEpochDays()).toFloat() / range +} + internal class LinearLocalDateTimeInterpolator( private val start: LocalDateTime, stop: LocalDateTime, diff --git a/scale/api/scale.api b/scale/api/scale.api index 2c70b095..1b41f91d 100644 --- a/scale/api/scale.api +++ b/scale/api/scale.api @@ -12,22 +12,26 @@ public final class com/juul/krayon/scale/ContinuousScaleKt { public static final fun domain (Lcom/juul/krayon/scale/ContinuousScale;[F)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domain (Lcom/juul/krayon/scale/ContinuousScale;[I)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domain (Lcom/juul/krayon/scale/ContinuousScale;[Lkotlinx/datetime/Instant;)Lcom/juul/krayon/scale/ContinuousScale; + public static final fun domain (Lcom/juul/krayon/scale/ContinuousScale;[Lkotlinx/datetime/LocalDate;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domain (Lcom/juul/krayon/scale/ContinuousScale;[Lkotlinx/datetime/LocalDateTime;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domainDouble (Lcom/juul/krayon/scale/ContinuousScale;Ljava/lang/Iterable;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domainFloat (Lcom/juul/krayon/scale/ContinuousScale;Ljava/lang/Iterable;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domainInstant (Lcom/juul/krayon/scale/ContinuousScale;Ljava/lang/Iterable;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domainInt (Lcom/juul/krayon/scale/ContinuousScale;Ljava/lang/Iterable;)Lcom/juul/krayon/scale/ContinuousScale; + public static final fun domainLocalDate (Lcom/juul/krayon/scale/ContinuousScale;Ljava/lang/Iterable;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun domainLocalDateTime (Lcom/juul/krayon/scale/ContinuousScale;Ljava/lang/Iterable;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun range (Lcom/juul/krayon/scale/ContinuousScale;[D)Lcom/juul/krayon/scale/ContinuousScale; public static final fun range (Lcom/juul/krayon/scale/ContinuousScale;[F)Lcom/juul/krayon/scale/ContinuousScale; public static final fun range (Lcom/juul/krayon/scale/ContinuousScale;[I)Lcom/juul/krayon/scale/ContinuousScale; public static final fun range (Lcom/juul/krayon/scale/ContinuousScale;[Lkotlinx/datetime/Instant;)Lcom/juul/krayon/scale/ContinuousScale; + public static final fun range (Lcom/juul/krayon/scale/ContinuousScale;[Lkotlinx/datetime/LocalDate;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun range (Lcom/juul/krayon/scale/ContinuousScale;[Lkotlinx/datetime/LocalDateTime;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun rangeColor (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun rangeDouble (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun rangeFloat (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun rangeInstant (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun rangeInt (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; + public static final fun rangeLocalDate (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun rangeLocalDateTime (Lcom/juul/krayon/scale/ContinuousScale;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static final fun scale (Ljava/util/List;Ljava/util/List;)Lcom/juul/krayon/scale/ContinuousScale; public static synthetic fun scale$default (Ljava/util/List;Ljava/util/List;ILjava/lang/Object;)Lcom/juul/krayon/scale/ContinuousScale; diff --git a/scale/api/scale.klib.api b/scale/api/scale.klib.api index 4576fb6c..60d4a183 100644 --- a/scale/api/scale.klib.api +++ b/scale/api/scale.klib.api @@ -46,8 +46,10 @@ final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.j final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin.collections/Iterable): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.collections.Iterable){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin.collections/Iterable): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.collections.Iterable){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin.collections/Iterable): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.collections.Iterable){0§}[0] +final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin.collections/Iterable): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.collections.Iterable){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin.collections/Iterable): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.collections.Iterable){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin/Array...): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.Array...){0§}[0] +final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin/Array...): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.Array...){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin/Array...): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.Array...){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin/DoubleArray...): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.DoubleArray...){0§}[0] final fun <#A: kotlin/Any?> (com.juul.krayon.scale/ContinuousScale<*, #A>).com.juul.krayon.scale/domain(kotlin/FloatArray...): com.juul.krayon.scale/ContinuousScale // com.juul.krayon.scale/domain|domain@com.juul.krayon.scale.ContinuousScale<*,0:0>(kotlin.FloatArray...){0§}[0] @@ -57,8 +59,10 @@ final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin.collections/List): com.juul.krayon.scale/ContinuousScale<#A, kotlin/Float> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.collections.List){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin.collections/List): com.juul.krayon.scale/ContinuousScale<#A, kotlin/Int> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.collections.List){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin.collections/List): com.juul.krayon.scale/ContinuousScale<#A, kotlinx.datetime/Instant> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.collections.List){0§>}[0] +final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin.collections/List): com.juul.krayon.scale/ContinuousScale<#A, kotlinx.datetime/LocalDate> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.collections.List){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin.collections/List): com.juul.krayon.scale/ContinuousScale<#A, kotlinx.datetime/LocalDateTime> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.collections.List){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin/Array...): com.juul.krayon.scale/ContinuousScale<#A, kotlinx.datetime/Instant> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.Array...){0§>}[0] +final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin/Array...): com.juul.krayon.scale/ContinuousScale<#A, kotlinx.datetime/LocalDate> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.Array...){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin/Array...): com.juul.krayon.scale/ContinuousScale<#A, kotlinx.datetime/LocalDateTime> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.Array...){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin/DoubleArray...): com.juul.krayon.scale/ContinuousScale<#A, kotlin/Double> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.DoubleArray...){0§>}[0] final fun <#A: kotlin/Comparable<#A>> (com.juul.krayon.scale/ContinuousScale<#A, *>).com.juul.krayon.scale/range(kotlin/FloatArray...): com.juul.krayon.scale/ContinuousScale<#A, kotlin/Float> // com.juul.krayon.scale/range|range@com.juul.krayon.scale.ContinuousScale<0:0,*>(kotlin.FloatArray...){0§>}[0] diff --git a/scale/src/commonMain/kotlin/ContinuousScale.kt b/scale/src/commonMain/kotlin/ContinuousScale.kt index dfbc53aa..030aac7e 100644 --- a/scale/src/commonMain/kotlin/ContinuousScale.kt +++ b/scale/src/commonMain/kotlin/ContinuousScale.kt @@ -5,6 +5,7 @@ import com.juul.krayon.interpolate.Interpolator import com.juul.krayon.interpolate.Inverter import com.juul.krayon.interpolate.interpolator import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import kotlin.jvm.JvmName @@ -34,6 +35,8 @@ public fun ContinuousScale<*, R>.domain(vararg domain: Double): ContinuousSc public fun ContinuousScale<*, R>.domain(vararg domain: Instant): ContinuousScale = domain(domain.toList()) +public fun ContinuousScale<*, R>.domain(vararg domain: LocalDate): ContinuousScale = domain(domain.toList()) + public fun ContinuousScale<*, R>.domain(vararg domain: LocalDateTime): ContinuousScale = domain(domain.toList()) // List domains @@ -51,6 +54,11 @@ public fun ContinuousScale<*, R>.domain( domain: Iterable, ): ContinuousScale = domain(domain.toList(), ::interpolator) +@JvmName("domainLocalDate") +public fun ContinuousScale<*, R>.domain( + domain: Iterable, +): ContinuousScale = domain(domain.toList(), ::interpolator) + @JvmName("domainLocalDateTime") public fun ContinuousScale<*, R>.domain( domain: Iterable, @@ -65,6 +73,8 @@ public fun > ContinuousScale.range(vararg range: Double) public fun > ContinuousScale.range(vararg range: Instant): ContinuousScale = range(range.toList()) +public fun > ContinuousScale.range(vararg range: LocalDate): ContinuousScale = range(range.toList()) + public fun > ContinuousScale.range(vararg range: LocalDateTime): ContinuousScale = range( range.toList(), ) @@ -85,6 +95,11 @@ public fun > ContinuousScale.range(range: List): @JvmName("rangeInstant") public fun > ContinuousScale.range(range: List): ContinuousScale = range(range, ::interpolator) +@JvmName("rangeLocalDate") +public fun > ContinuousScale.range( + range: List, +): ContinuousScale = range(range, ::interpolator) + @JvmName("rangeLocalDateTime") public fun > ContinuousScale.range( range: List,