Skip to content

Commit ea73753

Browse files
committed
feat: add int providers
1 parent e8b35e0 commit ea73753

3 files changed

Lines changed: 118 additions & 0 deletions

File tree

modules/value-providers/build.gradle.kts

Whitespace-only changes.
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package net.azisaba.serialization
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
import kotlin.math.PI
6+
import kotlin.math.cos
7+
import kotlin.math.ln
8+
import kotlin.math.sqrt
9+
import kotlin.random.Random
10+
11+
@Serializable
12+
sealed interface IntProvider {
13+
fun sample(random: Random): Int
14+
15+
@Serializable
16+
@SerialName("Constant")
17+
data class Constant(val value: Int) : IntProvider {
18+
override fun sample(random: Random): Int = value
19+
}
20+
21+
@Serializable
22+
@SerialName("Uniform")
23+
data class Uniform(val minInclusive: Int, val maxInclusive: Int) : IntProvider {
24+
init {
25+
require(maxInclusive >= minInclusive) {
26+
"maxInclusive must be greater than or equal to minInclusive: [$minInclusive, $maxInclusive]"
27+
}
28+
}
29+
30+
override fun sample(random: Random): Int = random.nextInt(minInclusive, maxInclusive + 1)
31+
}
32+
33+
@Serializable
34+
@SerialName("BiasedToBottom")
35+
data class BiasedToBottom(val minInclusive: Int, val maxInclusive: Int) : IntProvider {
36+
init {
37+
require(maxInclusive >= minInclusive) {
38+
"maxInclusive must be greater than or equal to minInclusive: [$minInclusive, $maxInclusive]"
39+
}
40+
}
41+
42+
override fun sample(random: Random): Int =
43+
minInclusive + random.nextInt(random.nextInt(maxInclusive - minInclusive + 1) + 1)
44+
}
45+
46+
@Serializable
47+
@SerialName("Clamped")
48+
data class Clamped(
49+
val source: IntProvider,
50+
val minInclusive: Int,
51+
val maxInclusive: Int,
52+
) : IntProvider {
53+
init {
54+
require(maxInclusive >= minInclusive) {
55+
"maxInclusive must be greater than or equal to minInclusive: [$minInclusive, $maxInclusive]"
56+
}
57+
}
58+
59+
override fun sample(random: Random): Int = source.sample(random).coerceIn(minInclusive, maxInclusive)
60+
}
61+
62+
@Serializable
63+
@SerialName("ClampedNormal")
64+
data class ClampedNormal(
65+
val mean: Float,
66+
val deviation: Float,
67+
val minInclusive: Int,
68+
val maxInclusive: Int,
69+
) : IntProvider {
70+
init {
71+
require(maxInclusive >= minInclusive) {
72+
"maxInclusive must be greater than or equal to minInclusive: [$minInclusive, $maxInclusive]"
73+
}
74+
}
75+
76+
override fun sample(random: Random): Int =
77+
(random.nextGaussian().toFloat() * deviation + mean)
78+
.coerceIn(minInclusive.toFloat(), maxInclusive.toFloat())
79+
.toInt()
80+
81+
private fun Random.nextGaussian(): Double {
82+
val u1 = nextDouble()
83+
val u2 = nextDouble()
84+
return sqrt(-2.0 * ln(u1)) * cos(2.0 * PI * u2)
85+
}
86+
}
87+
88+
@Serializable
89+
@SerialName("WeightedList")
90+
data class WeightedList(val distribution: List<Entry>) : IntProvider {
91+
init {
92+
require(distribution.isNotEmpty()) {
93+
"distribution must not be empty"
94+
}
95+
require(distribution.all { it.weight > 0 }) {
96+
"distribution weights must be greater than 0"
97+
}
98+
}
99+
100+
override fun sample(random: Random): Int {
101+
val totalWeight = distribution.sumOf(Entry::weight)
102+
val roll = random.nextInt(totalWeight)
103+
var accumulatedWeight = 0
104+
for (entry in distribution) {
105+
accumulatedWeight += entry.weight
106+
if (roll < accumulatedWeight) {
107+
return entry.provider.sample(random)
108+
}
109+
}
110+
111+
return distribution.last().provider.sample(random)
112+
}
113+
114+
@Serializable
115+
data class Entry(val provider: IntProvider, val weight: Int)
116+
}
117+
}

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ rootProject.name = "minecraft-serialization"
55

66
include("modules:adventure")
77
include("modules:joml")
8+
include("modules:value-providers")

0 commit comments

Comments
 (0)