chore(purity): Update to ensure new collections/sequences functions are ok

This commit is contained in:
yairm210 2025-07-22 16:06:55 +03:00
parent 4e766464a7
commit 1620a4c231
5 changed files with 13 additions and 9 deletions

View File

@ -37,7 +37,7 @@ plugins {
// This is *with* gradle 8.2 downloaded according the project specs, no idea what that's about // This is *with* gradle 8.2 downloaded according the project specs, no idea what that's about
kotlin("multiplatform") version "1.9.24" kotlin("multiplatform") version "1.9.24"
kotlin("plugin.serialization") version "1.9.24" kotlin("plugin.serialization") version "1.9.24"
id("io.github.yairm210.purity-plugin") version "0.0.27" apply(false) id("io.github.yairm210.purity-plugin") version "0.0.33" apply(false)
} }
allprojects { allprojects {
@ -174,7 +174,7 @@ project(":core") {
"implementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") "implementation"("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
"implementation"("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion") "implementation"("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
"implementation"("io.github.yairm210:purity-annotations:0.0.25") "implementation"("io.github.yairm210:purity-annotations:0.0.32")
"implementation"("io.ktor:ktor-client-core:$ktorVersion") "implementation"("io.ktor:ktor-client-core:$ktorVersion")
"implementation"("io.ktor:ktor-client-cio:$ktorVersion") "implementation"("io.ktor:ktor-client-cio:$ktorVersion")

View File

@ -36,7 +36,6 @@ import com.unciv.models.Counter
import com.unciv.models.metadata.GameParameters import com.unciv.models.metadata.GameParameters
import com.unciv.models.ruleset.Building import com.unciv.models.ruleset.Building
import com.unciv.models.ruleset.Policy import com.unciv.models.ruleset.Policy
import com.unciv.models.ruleset.Victory
import com.unciv.models.ruleset.nation.CityStateType import com.unciv.models.ruleset.nation.CityStateType
import com.unciv.models.ruleset.nation.Difficulty import com.unciv.models.ruleset.nation.Difficulty
import com.unciv.models.ruleset.nation.Nation import com.unciv.models.ruleset.nation.Nation
@ -56,6 +55,7 @@ import com.unciv.models.translations.tr
import com.unciv.ui.components.extensions.toPercent import com.unciv.ui.components.extensions.toPercent
import com.unciv.ui.screens.victoryscreen.RankingType import com.unciv.ui.screens.victoryscreen.RankingType
import org.jetbrains.annotations.VisibleForTesting import org.jetbrains.annotations.VisibleForTesting
import yairm210.purity.annotations.LocalState
import yairm210.purity.annotations.Readonly import yairm210.purity.annotations.Readonly
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -472,7 +472,9 @@ class Civilization : IsPartOfGameInfoSerialization {
* Returns a dictionary of ALL resource names, and the amount that the civ has of each * Returns a dictionary of ALL resource names, and the amount that the civ has of each
* Stockpiled resources return the stockpiled amount * Stockpiled resources return the stockpiled amount
*/ */
@Readonly @Suppress("purity")
fun getCivResourcesByName(): HashMap<String, Int> { fun getCivResourcesByName(): HashMap<String, Int> {
@LocalState
val hashMap = HashMap<String, Int>(gameInfo.ruleset.tileResources.size) val hashMap = HashMap<String, Int>(gameInfo.ruleset.tileResources.size)
for (resource in gameInfo.ruleset.tileResources.keys) hashMap[resource] = 0 for (resource in gameInfo.ruleset.tileResources.keys) hashMap[resource] = 0
for (entry in getCivResourceSupply()) for (entry in getCivResourceSupply())
@ -486,6 +488,7 @@ class Civilization : IsPartOfGameInfoSerialization {
/** Gets the number of resources available to this city /** Gets the number of resources available to this city
* Does not include city-wide resources * Does not include city-wide resources
* Returns 0 for undefined resources */ * Returns 0 for undefined resources */
@Readonly
fun getResourceAmount(resourceName: String): Int { fun getResourceAmount(resourceName: String): Int {
return getCivResourcesByName()[resourceName] ?: 0 return getCivResourcesByName()[resourceName] ?: 0
} }
@ -745,6 +748,7 @@ class Civilization : IsPartOfGameInfoSerialization {
@Readonly @Readonly
fun calculateScoreBreakdown(): HashMap<String,Double> { fun calculateScoreBreakdown(): HashMap<String,Double> {
@LocalState
val scoreBreakdown = hashMapOf<String,Double>() val scoreBreakdown = hashMapOf<String,Double>()
// 1276 is the number of tiles in a medium sized map. The original uses 4160 for this, // 1276 is the number of tiles in a medium sized map. The original uses 4160 for this,
// but they have bigger maps // but they have bigger maps

View File

@ -3,6 +3,7 @@ package com.unciv.models
import com.badlogic.gdx.utils.Json import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.JsonValue import com.badlogic.gdx.utils.JsonValue
import com.unciv.logic.IsPartOfGameInfoSerialization import com.unciv.logic.IsPartOfGameInfoSerialization
import yairm210.purity.annotations.LocalState
import yairm210.purity.annotations.Readonly import yairm210.purity.annotations.Readonly
/** /**
@ -51,6 +52,7 @@ open class Counter<K>(
@Readonly @Readonly
/** Creates a new instance (does not modify) */ /** Creates a new instance (does not modify) */
operator fun times(amount: Int): Counter<K> { operator fun times(amount: Int): Counter<K> {
@LocalState
val newCounter = Counter<K>() val newCounter = Counter<K>()
for (key in keys) newCounter[key] = this[key] * amount for (key in keys) newCounter[key] = this[key] * amount
return newCounter return newCounter

View File

@ -162,7 +162,7 @@ class Terrain : RulesetStatsObject() {
/** Terrain filter matching is "pure" - input always returns same output, and it's called a bajillion times */ /** Terrain filter matching is "pure" - input always returns same output, and it's called a bajillion times */
val cachedMatchesFilterResult = HashMap<String, Boolean>() val cachedMatchesFilterResult = HashMap<String, Boolean>()
@Readonly @Readonly @Suppress("purity")
fun matchesFilter(filter: String, state: GameContext? = null, multiFilter: Boolean = true): Boolean { fun matchesFilter(filter: String, state: GameContext? = null, multiFilter: Boolean = true): Boolean {
return if (multiFilter) MultiFilter.multiFilter(filter, { return if (multiFilter) MultiFilter.multiFilter(filter, {
cachedMatchesFilterResult.getOrPut(it) { matchesSingleFilter(it) } || cachedMatchesFilterResult.getOrPut(it) { matchesSingleFilter(it) } ||

View File

@ -229,6 +229,7 @@ enum class Countables(
private val engine = Expressions() private val engine = Expressions()
override val matchesWithRuleset: Boolean = true override val matchesWithRuleset: Boolean = true
@Suppress("purity")
override fun matches(parameterText: String, ruleset: Ruleset) = override fun matches(parameterText: String, ruleset: Ruleset) =
engine.matches(parameterText, ruleset) engine.matches(parameterText, ruleset)
override fun eval(parameterText: String, gameContext: GameContext): Int? = override fun eval(parameterText: String, gameContext: GameContext): Int? =
@ -258,7 +259,6 @@ enum class Countables(
open val noPlaceholders = !text.contains('[') open val noPlaceholders = !text.contains('[')
// Leave these in place only for the really simple cases // Leave these in place only for the really simple cases
@Readonly
open fun matches(parameterText: String) = if (noPlaceholders) parameterText == text open fun matches(parameterText: String) = if (noPlaceholders) parameterText == text
else parameterText.equalsPlaceholderText(placeholderText) else parameterText.equalsPlaceholderText(placeholderText)
@ -268,9 +268,7 @@ enum class Countables(
/** This indicates whether a parameter *is of this countable type*, not *whether its parameters are correct* /** This indicates whether a parameter *is of this countable type*, not *whether its parameters are correct*
* E.g. "[fakeBuilding] Buildings" is obviously a countable of type "[buildingFilter] Buildings", therefore matches will return true. * E.g. "[fakeBuilding] Buildings" is obviously a countable of type "[buildingFilter] Buildings", therefore matches will return true.
* But it has another problem, which is that the building filter is bad, so its getErrorSeverity will return "ruleset specific" */ * But it has another problem, which is that the building filter is bad, so its getErrorSeverity will return "ruleset specific" */
@Readonly
open fun matches(parameterText: String, ruleset: Ruleset): Boolean = false open fun matches(parameterText: String, ruleset: Ruleset): Boolean = false
@Readonly
abstract fun eval(parameterText: String, gameContext: GameContext): Int? abstract fun eval(parameterText: String, gameContext: GameContext): Int?
open val documentationHeader get() = open val documentationHeader get() =
@ -293,7 +291,7 @@ enum class Countables(
getErrorSeverity(parameterText.getPlaceholderParameters().first(), ruleset) getErrorSeverity(parameterText.getPlaceholderParameters().first(), ruleset)
companion object { companion object {
@Readonly @Readonly @Suppress("purity")
fun getMatching(parameterText: String, ruleset: Ruleset?) = Countables.entries fun getMatching(parameterText: String, ruleset: Ruleset?) = Countables.entries
.firstOrNull { .firstOrNull {
if (it.matchesWithRuleset) if (it.matchesWithRuleset)
@ -301,7 +299,7 @@ enum class Countables(
else it.matches(parameterText) else it.matches(parameterText)
} }
@Readonly @Readonly @Suppress("purity")
fun getCountableAmount(parameterText: String, gameContext: GameContext): Int? { fun getCountableAmount(parameterText: String, gameContext: GameContext): Int? {
val ruleset = gameContext.gameInfo?.ruleset val ruleset = gameContext.gameInfo?.ruleset
val countable = getMatching(parameterText, ruleset) ?: return null val countable = getMatching(parameterText, ruleset) ?: return null