Skip to content

Commit 9a77d3f

Browse files
committed
feat: add OneOf API
1 parent a28c7fa commit 9a77d3f

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

modules/core/src/main/kotlin/net/azisaba/data/NumberProvider.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ package net.azisaba.data
33
import kotlin.random.Random
44

55
interface NumberProvider<T : Number> {
6-
fun sample(random: Random): T
6+
fun sample(random: Random = Random.Default): T
77
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package net.azisaba.data
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
import kotlin.random.Random
6+
7+
@Serializable
8+
sealed interface OneOf<T : Any> {
9+
fun choice(random: Random = Random.Default): T
10+
11+
@Serializable
12+
@SerialName("Fixed")
13+
data class Fixed<T : Any>(val value: T) : OneOf<T> {
14+
override fun choice(random: Random): T = value
15+
}
16+
17+
@Serializable
18+
@SerialName("Uniform")
19+
data class Uniform<T : Any>(val values: List<T>) : OneOf<T> {
20+
init {
21+
require(values.isNotEmpty()) { "values must not be empty" }
22+
}
23+
24+
override fun choice(random: Random): T = values[random.nextInt(values.size)]
25+
}
26+
27+
@Serializable
28+
@SerialName("Weighted")
29+
data class Weighted<T : Any>(val entries: List<Entry<T>>) : OneOf<T> {
30+
private val totalWeight: Int = entries.sumOf(Entry<T>::weight)
31+
32+
init {
33+
require(entries.isNotEmpty()) { "entries must not be empty" }
34+
require(totalWeight > 0) { "total weight must be greater than 0" }
35+
}
36+
37+
override fun choice(random: Random): T {
38+
var r = random.nextInt(totalWeight)
39+
40+
for (entry in entries) {
41+
if (r < entry.weight) {
42+
return entry.value
43+
}
44+
r -= entry.weight
45+
}
46+
47+
return entries.last().value
48+
}
49+
50+
@Serializable
51+
data class Entry<T : Any>(val value: T, val weight: Int) {
52+
init {
53+
require(weight > 0) { "weight must be greater than 0" }
54+
}
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)