From 1c7fc7e570f6f3c3bf4d2256eee2a3609092adf3 Mon Sep 17 00:00:00 2001 From: jbion Date: Tue, 19 Feb 2019 22:23:49 +0100 Subject: Refactor resources API --- .../game/data/serializers/ResourcesSerializer.kt | 2 +- .../sevenwonders/game/resources/Resources.kt | 65 ++++++++++------------ 2 files changed, 29 insertions(+), 38 deletions(-) (limited to 'game-engine/src') diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt index fcf66d79..c988b097 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt @@ -23,6 +23,6 @@ internal class ResourcesSerializer : JsonSerializer, JsonDeserializer @Throws(JsonParseException::class) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Resources { val s = json.asString - return s.toCharArray().map { ResourceType.fromSymbol(it) }.toResources() + return s.toCharArray().map { ResourceType.fromSymbol(it) to 1 }.toResources() } } diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt index 476ffea8..d662cf1b 100644 --- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt +++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt @@ -1,34 +1,29 @@ package org.luxons.sevenwonders.game.resources -import java.util.NoSuchElementException - fun emptyResources(): Resources = MutableResources() -fun resourcesOf(singleResource: ResourceType): Resources = MutableResources(mutableMapOf(singleResource to 1)) +fun resourcesOf(singleResource: ResourceType): Resources = mapOf(singleResource to 1).toMutableResources() + +fun resourcesOf(vararg resources: ResourceType): Resources = resources.map { it to 1 }.toMutableResources() + +fun resourcesOf(vararg resources: Pair): Resources = mutableResourcesOf(*resources) -fun resourcesOf(vararg resources: ResourceType): Resources = - resources.fold(MutableResources()) { rs, r -> rs.add(r, 1); rs } +fun Iterable>.toResources(): Resources = toMutableResources() -fun resourcesOf(resources: Iterable): Resources = - resources.fold(MutableResources()) { rs, r -> rs.add(r, 1); rs } +fun Map.toResources(): Resources = toMutableResources() -fun resourcesOf(vararg resources: Pair): Resources = - resources.fold(MutableResources()) { rs, (type, qty) -> rs.add(type, qty); rs } +fun Iterable.merge(): Resources = fold(MutableResources()) { r1, r2 -> r1.add(r2); r1 } internal fun mutableResourcesOf() = MutableResources() -internal fun mutableResourcesOf(vararg resources: Pair) = - resources.fold(MutableResources()) { rs, (type, qty) -> rs.add(type, qty); rs } +internal fun mutableResourcesOf(vararg resources: Pair) = resources.asIterable().toMutableResources() -fun Iterable.toResources(): Resources = resourcesOf(this) +internal fun Iterable>.toMutableResources(): MutableResources = + fold(MutableResources()) { mr, (type, qty) -> mr.add(type, qty); mr } -fun Iterable.merge(): Resources = fold(MutableResources()) { r1, r2 -> r1.add(r2); r1 } +internal fun Map.toMutableResources(): MutableResources = MutableResources(toMutableMap()) -internal fun Resources.toMutableResources(): MutableResources { - val resources = MutableResources() - resources.add(this) - return resources -} +internal fun Resources.toMutableResources(): MutableResources = quantities.toMutableResources() interface Resources { @@ -43,26 +38,21 @@ interface Resources { fun containsAll(resources: Resources): Boolean = resources.quantities.all { it.value <= this[it.key] } - operator fun plus(resources: Resources): Resources { - val new = MutableResources() - new.add(this) - new.add(resources) - return new - } + operator fun plus(resources: Resources): Resources = + ResourceType.values().map { it to this[it] + resources[it] }.toResources() - operator fun minus(resources: Resources): Resources { - val diff = MutableResources() - quantities.forEach { type, count -> - val remainder = count - resources[type] - diff.quantities[type] = Math.max(0, remainder) - } - return diff - } + /** + * Returns new resources containing these resources minus the given [resources]. If the given resources contain + * more than these resources contain for a resource type, then the resulting resources will contain none of that + * type. + */ + operator fun minus(resources: Resources): Resources = + quantities.mapValues { (type, q) -> Math.max(0, q - resources[type]) }.toResources() fun toList(): List = quantities.flatMap { (type, quantity) -> List(quantity) { type } } } -data class MutableResources( +class MutableResources( override val quantities: MutableMap = mutableMapOf() ) : Resources { @@ -77,9 +67,10 @@ data class MutableResources( throw NoSuchElementException("Can't remove $quantity resources of type $type") } quantities.computeIfPresent(type) { _, oldQty -> oldQty - quantity } - // to ensure equals() work properly - if (quantities[type] == 0) { - quantities.remove(type) - } } + + override fun equals(other: Any?): Boolean = + other is Resources && quantities.filterValues { it > 0 } == other.quantities.filterValues { it > 0 } + + override fun hashCode(): Int = quantities.filterValues { it > 0 }.hashCode() } -- cgit