PlaguPoster/ratings/selector/src/commonMain/kotlin/models/RatingConfig.kt

106 lines
3.4 KiB
Kotlin
Raw Normal View History

2022-09-06 17:56:58 +00:00
package dev.inmo.plaguposter.ratings.selector.models
import dev.inmo.micro_utils.pagination.FirstPagePagination
import dev.inmo.micro_utils.pagination.Pagination
import dev.inmo.plaguposter.posts.models.PostId
import dev.inmo.plaguposter.ratings.models.Rating
import dev.inmo.plaguposter.ratings.repo.RatingsRepo
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.random.Random
@Serializable
data class RatingConfig(
val min: Rating?,
val max: Rating?,
2022-09-09 11:27:11 +00:00
val prefer: Prefer,
val otherwise: RatingConfig? = null
2022-09-06 17:56:58 +00:00
) {
suspend fun select(repo: RatingsRepo, exclude: List<PostId>): PostId? {
var reversed: Boolean = false
var count: Int? = null
when (prefer) {
Prefer.Max -> {
reversed = true
count = 1
}
Prefer.Min -> {
reversed = false
count = 1
}
Prefer.Random -> {
reversed = false
count = null
}
}
val posts = when(min) {
null -> {
when (max) {
null -> {
repo.keys(
count ?.let { Pagination(0, it) } ?: FirstPagePagination(repo.count().toInt()),
reversed
).results.filterNot {
it in exclude
}
}
else -> {
repo.getPostsWithRatingLessEq(max, exclude = exclude).keys
}
}
}
else -> {
when (max) {
null -> {
repo.getPostsWithRatingGreaterEq(min, exclude = exclude).keys
}
else -> {
repo.getPosts(min .. max, reversed, count, exclude = exclude).keys
}
}
}
}
return when (prefer) {
Prefer.Max,
Prefer.Min -> posts.firstOrNull()
Prefer.Random -> posts.randomOrNull()
2022-09-09 11:27:11 +00:00
} ?: otherwise ?.select(repo, exclude)
2022-09-06 17:56:58 +00:00
}
@Serializable(Prefer.Serializer::class)
sealed interface Prefer {
val type: String
@Serializable(Serializer::class)
object Max : Prefer { override val type: String = "max" }
@Serializable(Serializer::class)
object Min : Prefer { override val type: String = "min" }
@Serializable(Serializer::class)
object Random : Prefer { override val type: String = "random" }
object Serializer : KSerializer<Prefer> {
override val descriptor: SerialDescriptor = String.serializer().descriptor
override fun deserialize(decoder: Decoder): Prefer {
val identifier = decoder.decodeString().lowercase()
return values.first { it.type.lowercase() == identifier }
}
override fun serialize(encoder: Encoder, value: Prefer) {
encoder.encodeString(value.type.lowercase())
}
}
companion object {
val values = arrayOf(Max, Min, Random)
}
}
}