diff options
author | Joffrey Bion <joffrey.bion@booking.com> | 2020-05-28 13:03:36 +0200 |
---|---|---|
committer | Joffrey Bion <joffrey.bion@booking.com> | 2020-05-28 13:34:57 +0200 |
commit | 4178ba9700ffd6619f995482a369bd5133276e2e (patch) | |
tree | 497223513f61a7162d78213e1c9fe7de16064e25 | |
parent | Clarify message for unavailable resources (diff) | |
download | seven-wonders-4178ba9700ffd6619f995482a369bd5133276e2e.tar.gz seven-wonders-4178ba9700ffd6619f995482a369bd5133276e2e.tar.bz2 seven-wonders-4178ba9700ffd6619f995482a369bd5133276e2e.zip |
Fix production alternative duplicates
Having twice the same choice wasn't supported so far.
This can happen with Alexandria's bonuses (4 primary resources, or 3 secondary)
associated to the yellow Market/Caravansery cards.
Resolves:
https://github.com/joffrey-bion/seven-wonders/issues/19
7 files changed, 47 insertions, 17 deletions
diff --git a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt index 68a85898..333883b6 100644 --- a/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt +++ b/sw-common-model/src/commonMain/kotlin/org/luxons/sevenwonders/model/boards/Boards.kt @@ -29,7 +29,7 @@ data class Requirements( @Serializable data class Production( val fixedResources: List<CountedResource>, - val alternativeResources: Set<Set<ResourceType>> + val alternativeResources: List<Set<ResourceType>> ) @Serializable diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/converters/Boards.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/converters/Boards.kt index 7ff870cf..0d8369ac 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/converters/Boards.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/converters/Boards.kt @@ -73,7 +73,7 @@ internal fun InternalWonderStage.toApiWonderStage(isLastBuiltStage: Boolean, las internal fun InternalProduction.toApiProduction(): ApiProduction = ApiProduction( fixedResources = getFixedResources().toCountedResourcesList(), - alternativeResources = getAlternativeResources() + alternativeResources = getAlternativeResources().sortedBy { it.size } ) internal fun InternalRequirements.toApiRequirements(): ApiRequirements = diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt index 467b0912..c98f20a8 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt @@ -24,14 +24,14 @@ internal class ProductionSerializer : JsonSerializer<Production>, JsonDeserializ } } - private fun serializeAsChoice(choices: Set<Set<ResourceType>>, context: JsonSerializationContext): JsonElement { + private fun serializeAsChoice(choices: List<Set<ResourceType>>, context: JsonSerializationContext): JsonElement { if (choices.isEmpty()) { return JsonNull.INSTANCE } if (choices.size > 1) { throw IllegalArgumentException("Cannot serialize a production with more than one choice") } - val str = choices.flatten().map { it.symbol }.joinToString("/") + val str = choices[0].map { it.symbol }.joinToString("/") return context.serialize(str) } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/BestPriceCalculator.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/BestPriceCalculator.kt index 85b07a80..dd2d2cae 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/BestPriceCalculator.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/BestPriceCalculator.kt @@ -15,7 +15,7 @@ data class TransactionPlan(val price: Int, val possibleTransactions: Set<Resourc private class ResourcePool( val provider: Provider?, private val rules: TradingRules, - choices: Set<Set<ResourceType>> + choices: List<Set<ResourceType>> ) { val choices: Set<MutableSet<ResourceType>> = choices.mapTo(HashSet()) { it.toMutableSet() } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt index 46ec66f7..4f9bbe90 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt @@ -5,11 +5,12 @@ import java.util.EnumSet data class Production internal constructor( private val fixedResources: MutableResources = mutableResourcesOf(), - private val alternativeResources: MutableSet<Set<ResourceType>> = mutableSetOf() + // cannot be a Set because the same choices can be there multiple times + private val alternativeResources: MutableList<Set<ResourceType>> = mutableListOf() ) { fun getFixedResources(): Resources = fixedResources - fun getAlternativeResources(): Set<Set<ResourceType>> = alternativeResources + fun getAlternativeResources(): List<Set<ResourceType>> = alternativeResources fun addFixedResource(type: ResourceType, quantity: Int) = fixedResources.add(type, quantity) @@ -25,8 +26,8 @@ data class Production internal constructor( alternativeResources.addAll(production.getAlternativeResources()) } - internal fun asChoices(): Set<Set<ResourceType>> { - val fixedAsChoices = fixedResources.toList().mapTo(HashSet()) { EnumSet.of(it) } + internal fun asChoices(): List<Set<ResourceType>> { + val fixedAsChoices = fixedResources.toList().map { EnumSet.of(it) } return fixedAsChoices + alternativeResources } @@ -42,7 +43,7 @@ data class Production internal constructor( private fun containedInAlternatives( resources: MutableResources, - alternatives: MutableSet<Set<ResourceType>> + alternatives: MutableList<Set<ResourceType>> ): Boolean { if (resources.isEmpty()) { return true diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/ProductionTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/ProductionTest.kt index c449c784..9bc04142 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/ProductionTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/resources/ProductionTest.kt @@ -11,7 +11,6 @@ import org.luxons.sevenwonders.model.resources.ResourceType.PAPYRUS import org.luxons.sevenwonders.model.resources.ResourceType.STONE import org.luxons.sevenwonders.model.resources.ResourceType.WOOD import java.util.EnumSet -import java.util.HashSet import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue @@ -228,12 +227,22 @@ class ProductionTest { } @Test + fun asChoices_withDuplicateChoices() { + val production = Production() + production.addChoice(STONE, WOOD) + production.addChoice(STONE, ORE) + production.addChoice(STONE, ORE) + production.addChoice(CLAY, LOOM, GLASS) + assertEquals(production.getAlternativeResources(), production.asChoices()) + } + + @Test fun asChoices_onlyFixed() { val production = Production() production.addFixedResource(WOOD, 1) production.addFixedResource(CLAY, 2) - val expected = HashSet<Set<ResourceType>>() + val expected = mutableListOf<Set<ResourceType>>() expected.add(EnumSet.of(WOOD)) expected.add(EnumSet.of(CLAY)) expected.add(EnumSet.of(CLAY)) @@ -249,12 +258,32 @@ class ProductionTest { production.addFixedResource(WOOD, 1) production.addFixedResource(CLAY, 2) - val expected = HashSet<Set<ResourceType>>() + val expected = mutableListOf<Set<ResourceType>>() + expected.add(EnumSet.of(WOOD)) + expected.add(EnumSet.of(CLAY)) + expected.add(EnumSet.of(CLAY)) expected.add(EnumSet.of(STONE, ORE)) expected.add(EnumSet.of(CLAY, LOOM, GLASS)) + + assertEquals(expected, production.asChoices()) + } + + @Test + fun asChoices_mixed_withDuplicates() { + val production = Production() + production.addChoice(STONE, ORE) + production.addChoice(CLAY, LOOM, GLASS) + production.addChoice(STONE, ORE) + production.addFixedResource(WOOD, 1) + production.addFixedResource(CLAY, 2) + + val expected = mutableListOf<Set<ResourceType>>() expected.add(EnumSet.of(WOOD)) expected.add(EnumSet.of(CLAY)) expected.add(EnumSet.of(CLAY)) + expected.add(EnumSet.of(STONE, ORE)) + expected.add(EnumSet.of(CLAY, LOOM, GLASS)) + expected.add(EnumSet.of(STONE, ORE)) assertEquals(expected, production.asChoices()) } @@ -269,13 +298,13 @@ class ProductionTest { fun equals_trueWhenSameContent() { val production1 = Production() val production2 = Production() - assertTrue(production1 == production2) + assertEquals(production1, production2) production1.addFixedResource(GLASS, 1) production2.addFixedResource(GLASS, 1) - assertTrue(production1 == production2) + assertEquals(production1, production2) production1.addChoice(ORE, WOOD) production2.addChoice(ORE, WOOD) - assertTrue(production1 == production2) + assertEquals(production1, production2) } @Test diff --git a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt index d3243906..a3e4cd11 100644 --- a/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt +++ b/sw-ui/src/main/kotlin/org/luxons/sevenwonders/ui/components/game/ProductionBar.kt @@ -62,7 +62,7 @@ private fun RBuilder.fixedResources(resources: List<CountedResource>) { } } -private fun RBuilder.alternativeResources(resources: Set<Set<ResourceType>>) { +private fun RBuilder.alternativeResources(resources: List<Set<ResourceType>>) { styledDiv { css { margin = "auto" |