aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/features/texturepack/RarityMatcher.kt
blob: 1a0daacc20dd08ccbf036140affd57ae6aa4124c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

package moe.nea.firmament.features.texturepack

import com.google.gson.JsonElement
import io.github.moulberry.repo.data.Rarity
import moe.nea.firmament.util.useMatch

abstract class RarityMatcher {
    abstract fun match(rarity: Rarity): Boolean

    companion object {
        fun parse(jsonElement: JsonElement): RarityMatcher {
            val string = jsonElement.asString
            val range = parseRange(string)
            if (range != null) return range
            return Exact(Rarity.valueOf(string))
        }

        private val allRarities = Rarity.entries.joinToString("|", "(?:", ")")
        private val intervalSpec =
            "(?<beginningOpen>[\\[\\(])(?<beginning>$allRarities)?,(?<ending>$allRarities)?(?<endingOpen>[\\]\\)])"
                .toPattern()

        fun parseRange(string: String): RangeMatcher? {
            intervalSpec.useMatch<Nothing>(string) {
                // Open in the set-theory sense, meaning does not include its end.
                val beginningOpen = group("beginningOpen") == "("
                val endingOpen = group("endingOpen") == ")"
                val beginning = group("beginning")?.let(Rarity::valueOf)
                val ending = group("ending")?.let(Rarity::valueOf)
                return RangeMatcher(beginning, !beginningOpen, ending, !endingOpen)
            }
            return null
        }

    }

    data class Exact(val expected: Rarity) : RarityMatcher() {
        override fun match(rarity: Rarity): Boolean {
            return rarity == expected
        }
    }

    data class RangeMatcher(
        val beginning: Rarity?,
        val beginningInclusive: Boolean,
        val ending: Rarity?,
        val endingInclusive: Boolean,
    ) : RarityMatcher() {
        override fun match(rarity: Rarity): Boolean {
            if (beginning != null) {
                if (beginningInclusive) {
                    if (rarity < beginning) return false
                } else {
                    if (rarity <= beginning) return false
                }
            }
            if (ending != null) {
                if (endingInclusive) {
                    if (rarity > ending) return false
                } else {
                    if (rarity >= ending) return false
                }
            }
            return true
        }
    }

}