summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/build.gradle2
-rw-r--r--backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt4
-rw-r--r--backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt29
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt13
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt4
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializer.kt9
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt2
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculator.kt59
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Production.kt66
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransaction.kt15
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt39
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Resources.kt95
-rw-r--r--game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt20
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt13
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/boards/BoardTest.kt4
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/CardTest.kt4
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt40
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializerTest.kt2
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializerTest.kt6
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializerTest.kt47
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/effects/ProductionIncreaseTest.kt10
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt46
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt145
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt24
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt483
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt36
-rw-r--r--game-engine/src/test/kotlin/org/luxons/sevenwonders/game/test/TestUtils.kt23
27 files changed, 544 insertions, 696 deletions
diff --git a/backend/build.gradle b/backend/build.gradle
index 6c733559..af5ed8e2 100644
--- a/backend/build.gradle
+++ b/backend/build.gradle
@@ -65,7 +65,7 @@ dependencies {
annotationProcessor 'org.hildan.livedoc:livedoc-javadoc-processor:4.3.2'
testCompile 'org.springframework.boot:spring-boot-starter-test'
- testCompile 'org.hildan.jackstomp:jackstomp:1.1.0'
+ testCompile 'org.hildan.jackstomp:jackstomp:2.0.0'
checkstyleConfig 'org.hildan.checkstyle:checkstyle-config:2.1.0'
}
diff --git a/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt b/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt
index bebb3233..743e3d1a 100644
--- a/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt
+++ b/backend/src/main/kotlin/org/luxons/sevenwonders/config/WebSocketConfig.kt
@@ -10,6 +10,8 @@ import org.springframework.web.socket.config.annotation.StompEndpointRegistry
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
import org.springframework.web.socket.server.support.DefaultHandshakeHandler
+const val SEVEN_WONDERS_WS_ENDPOINT = "/seven-wonders-websocket"
+
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig @Autowired constructor(private val topicSubscriptionInterceptor: TopicSubscriptionInterceptor) :
@@ -25,7 +27,7 @@ class WebSocketConfig @Autowired constructor(private val topicSubscriptionInterc
}
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
- registry.addEndpoint("/seven-wonders-websocket")
+ registry.addEndpoint(SEVEN_WONDERS_WS_ENDPOINT)
.setHandshakeHandler(handshakeHandler())
.setAllowedOrigins("http://localhost:3000") // to allow frontend server proxy requests in dev mode
.withSockJS()
diff --git a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt
index d98e932e..472e5529 100644
--- a/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt
+++ b/backend/src/test/kotlin/org/luxons/sevenwonders/test/api/SevenWondersClient.kt
@@ -1,25 +1,36 @@
package org.luxons.sevenwonders.test.api
+import com.fasterxml.jackson.databind.module.SimpleModule
+import org.hildan.jackstomp.JackstompClient
+import org.luxons.sevenwonders.config.SEVEN_WONDERS_WS_ENDPOINT
+import org.luxons.sevenwonders.game.resources.MutableResources
+import org.luxons.sevenwonders.game.resources.Resources
+import org.springframework.messaging.converter.MappingJackson2MessageConverter
import java.util.concurrent.ExecutionException
import java.util.concurrent.TimeoutException
-import org.hildan.jackstomp.JackstompClient
-import org.hildan.jackstomp.JackstompSession
+class SevenWondersClient {
+
+ private val client: JackstompClient
-class SevenWondersClient @JvmOverloads constructor(private val client: JackstompClient = JackstompClient()) {
+ init {
+ val customMappingsModule = SimpleModule("ConcreteResourcesDeserializationModule")
+ customMappingsModule.addAbstractTypeMapping(Resources::class.java, MutableResources::class.java)
+
+ val mappingJackson2MessageConverter = MappingJackson2MessageConverter()
+ mappingJackson2MessageConverter.objectMapper.registerModule(customMappingsModule)
+
+ client = JackstompClient()
+ client.webSocketClient.messageConverter = mappingJackson2MessageConverter
+ }
@Throws(InterruptedException::class, ExecutionException::class, TimeoutException::class)
fun connect(serverUrl: String): SevenWondersSession {
- val session = client.connect(serverUrl + WEBSOCKET_ENDPOINT)
+ val session = client.syncConnect(serverUrl + SEVEN_WONDERS_WS_ENDPOINT)
return SevenWondersSession(session)
}
fun stop() {
client.stop()
}
-
- companion object {
-
- private val WEBSOCKET_ENDPOINT = "/seven-wonders-websocket"
- }
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt
index 6a38965f..ad50a1c6 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/cards/Requirements.kt
@@ -4,11 +4,14 @@ import org.luxons.sevenwonders.game.Player
import org.luxons.sevenwonders.game.boards.Board
import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.resources.Resources
-import org.luxons.sevenwonders.game.resources.bestPrice
+import org.luxons.sevenwonders.game.resources.asResources
+import org.luxons.sevenwonders.game.resources.bestSolution
+import org.luxons.sevenwonders.game.resources.emptyResources
+import org.luxons.sevenwonders.game.resources.execute
data class Requirements internal constructor(
val gold: Int = 0,
- val resources: Resources = Resources()
+ val resources: Resources = emptyResources()
) {
/**
* Returns whether the given [board] meets these requirements on its own.
@@ -52,8 +55,8 @@ data class Requirements internal constructor(
if (producesRequiredResources(board)) {
return true
}
- val bestPrice = bestPrice(resources, player)
- return bestPrice != null && bestPrice <= board.gold - gold
+ val solution = bestSolution(resources, player)
+ return !solution.possibleTransactions.isEmpty() && solution.price <= board.gold - gold
}
private fun hasRequiredGold(board: Board): Boolean {
@@ -71,7 +74,7 @@ data class Requirements internal constructor(
private fun producesRequiredResourcesWithHelp(board: Board, transactions: ResourceTransactions): Boolean {
val totalBoughtResources = transactions.asResources()
- val remainingResources = this.resources.minus(totalBoughtResources)
+ val remainingResources = resources - totalBoughtResources
return board.production.contains(remainingResources)
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt
index 06b46bb2..b766dd31 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializer.kt
@@ -15,10 +15,10 @@ import java.lang.reflect.Type
internal class ProductionSerializer : JsonSerializer<Production>, JsonDeserializer<Production> {
override fun serialize(production: Production, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
- val fixedResources = production.fixedResources
+ val fixedResources = production.getFixedResources()
val choices = production.getAlternativeResources()
return when {
- fixedResources.isEmpty -> serializeAsChoice(choices, context)
+ fixedResources.isEmpty() -> serializeAsChoice(choices, context)
choices.isEmpty() -> serializeAsResources(fixedResources, context)
else -> throw IllegalArgumentException("Cannot serialize a production with mixed fixed resources and choices")
}
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 c6c6a962..fcf66d79 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
@@ -10,22 +10,19 @@ import com.google.gson.JsonSerializationContext
import com.google.gson.JsonSerializer
import org.luxons.sevenwonders.game.resources.ResourceType
import org.luxons.sevenwonders.game.resources.Resources
+import org.luxons.sevenwonders.game.resources.toResources
import java.lang.reflect.Type
internal class ResourcesSerializer : JsonSerializer<Resources>, JsonDeserializer<Resources> {
override fun serialize(resources: Resources, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
- val s = resources.asList().map { it.symbol }.joinToString("")
+ val s = resources.toList().map { it.symbol }.joinToString("")
return if (s.isEmpty()) JsonNull.INSTANCE else JsonPrimitive(s)
}
@Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Resources {
val s = json.asString
- val resources = Resources()
- for (c in s.toCharArray()) {
- resources.add(ResourceType.fromSymbol(c), 1)
- }
- return resources
+ return s.toCharArray().map { ResourceType.fromSymbol(it) }.toResources()
}
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
index ce50e3e0..ed982abb 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/moves/Move.kt
@@ -14,7 +14,7 @@ abstract class Move internal constructor(
val type: MoveType = move.type
// TODO restore visibility to public
- internal val transactions: ResourceTransactions = ResourceTransactions(move.transactions)
+ internal val transactions: ResourceTransactions = move.transactions
internal abstract fun place(discardedCards: MutableList<Card>, settings: Settings)
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculator.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculator.kt
index 3b86fd97..4159cea3 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculator.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculator.kt
@@ -4,20 +4,10 @@ import org.luxons.sevenwonders.game.Player
import java.util.ArrayList
import java.util.EnumSet
-internal fun bestPrice(resources: Resources, player: Player): Int? {
- return bestSolution(resources, player)?.price
-}
-
-internal fun bestTransaction(resources: Resources, player: Player): ResourceTransactions? {
- return bestSolution(resources, player)?.transactions
-}
+internal fun bestSolution(resources: Resources, player: Player): TransactionPlan =
+ BestPriceCalculator(resources, player).computeBestSolution()
-internal fun bestSolution(resources: Resources, player: Player): TransactionPlan? {
- val calculator = BestPriceCalculator(resources, player)
- return calculator.computeBestSolution()
-}
-
-internal data class TransactionPlan(val price: Int, val transactions: ResourceTransactions)
+internal data class TransactionPlan(val price: Int, val possibleTransactions: Set<ResourceTransactions>)
private class ResourcePool(
val provider: Provider?,
@@ -30,16 +20,16 @@ private class ResourcePool(
private class BestPriceCalculator(resourcesToPay: Resources, player: Player) {
private val pools: List<ResourcePool>
- private val resourcesLeftToPay: Resources
- private val boughtResources: ResourceTransactions = ResourceTransactions()
+ private val resourcesLeftToPay: MutableResources
+ private val boughtResources: MutableMap<Provider, MutableResources> = HashMap()
private var pricePaid: Int = 0
- var bestSolution: ResourceTransactions? = null
- var bestPrice: Int = Integer.MAX_VALUE
+ private var bestSolutions: MutableSet<ResourceTransactions> = mutableSetOf()
+ private var bestPrice: Int = Integer.MAX_VALUE
init {
val board = player.board
- this.resourcesLeftToPay = resourcesToPay.minus(board.production.fixedResources)
+ this.resourcesLeftToPay = resourcesToPay.minus(board.production.getFixedResources()).toMutableResources()
this.pools = createResourcePools(player)
}
@@ -56,24 +46,25 @@ private class BestPriceCalculator(resourcesToPay: Resources, player: Player) {
for (provider in providers) {
val providerBoard = player.getBoard(provider.boardPosition)
- val pool = ResourcePool(provider, rules, providerBoard.publicProduction.asChoices().map { it.toMutableSet() }.toSet())
+ val choices = providerBoard.publicProduction.asChoices().map { it.toMutableSet() }.toSet()
+ val pool = ResourcePool(provider, rules, choices)
pools.add(pool)
}
return pools
}
- fun computeBestSolution(): TransactionPlan? {
+ fun computeBestSolution(): TransactionPlan {
computePossibilities()
- return if (bestSolution == null) null else TransactionPlan(bestPrice, bestSolution!!)
+ return TransactionPlan(bestPrice, bestSolutions)
}
private fun computePossibilities() {
- if (resourcesLeftToPay.isEmpty) {
+ if (resourcesLeftToPay.isEmpty()) {
updateBestSolutionIfNeeded()
return
}
for (type in ResourceType.values()) {
- if (resourcesLeftToPay.getQuantity(type) > 0) {
+ if (resourcesLeftToPay[type] > 0) {
for (pool in pools) {
if (pool.provider == null) {
computeSelfPossibilities(type, pool)
@@ -94,14 +85,22 @@ private class BestPriceCalculator(resourcesToPay: Resources, player: Player) {
private fun computeNeighbourPossibilities(pool: ResourcePool, type: ResourceType, provider: Provider) {
val cost = pool.getCost(type)
resourcesLeftToPay.remove(type, 1)
- boughtResources.add(provider, Resources(type))
- pricePaid += cost
+ buyOne(provider, type, cost)
computePossibilitiesWhenUsing(type, pool)
- pricePaid -= cost
- boughtResources.remove(provider, Resources(type))
+ unbuyOne(provider, type, cost)
resourcesLeftToPay.add(type, 1)
}
+ fun buyOne(provider: Provider, type: ResourceType, cost: Int) {
+ boughtResources.getOrPut(provider) { MutableResources() }.add(type, 1)
+ pricePaid += cost
+ }
+
+ fun unbuyOne(provider: Provider, type: ResourceType, cost: Int) {
+ pricePaid -= cost
+ boughtResources.get(provider)!!.remove(type, 1)
+ }
+
private fun computePossibilitiesWhenUsing(type: ResourceType, pool: ResourcePool) {
for (choice in pool.choices) {
if (choice.contains(type)) {
@@ -114,9 +113,13 @@ private class BestPriceCalculator(resourcesToPay: Resources, player: Player) {
}
private fun updateBestSolutionIfNeeded() {
+ if (pricePaid > bestPrice) return
+
if (pricePaid < bestPrice) {
bestPrice = pricePaid
- bestSolution = ResourceTransactions(boughtResources.asList())
+ bestSolutions.clear()
}
+ // avoid mutating the resources from the transactions
+ bestSolutions.add(boughtResources.mapValues { MutableResources(HashMap(it.value.quantities)) }.toTransactions())
}
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Production.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Production.kt
index 2dd6d60f..0b069677 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Production.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/Production.kt
@@ -3,35 +3,30 @@ package org.luxons.sevenwonders.game.resources
import java.util.Arrays
import java.util.EnumSet
-class Production internal constructor() {
-
- val fixedResources = Resources()
+data class Production internal constructor(
+ private val fixedResources: MutableResources = mutableResourcesOf(),
private val alternativeResources: MutableSet<Set<ResourceType>> = mutableSetOf()
+) {
+ fun getFixedResources(): Resources = fixedResources
- fun getAlternativeResources(): Set<Set<ResourceType>> {
- return alternativeResources
- }
+ fun getAlternativeResources(): Set<Set<ResourceType>> = alternativeResources
- fun addFixedResource(type: ResourceType, quantity: Int) {
- fixedResources.add(type, quantity)
- }
+ fun addFixedResource(type: ResourceType, quantity: Int) = fixedResources.add(type, quantity)
fun addChoice(vararg options: ResourceType) {
val optionSet = EnumSet.copyOf(Arrays.asList(*options))
alternativeResources.add(optionSet)
}
- fun addAll(resources: Resources) {
- fixedResources.addAll(resources)
- }
+ fun addAll(resources: Resources) = fixedResources.add(resources)
fun addAll(production: Production) {
- fixedResources.addAll(production.fixedResources)
+ fixedResources.add(production.fixedResources)
alternativeResources.addAll(production.getAlternativeResources())
}
internal fun asChoices(): Set<Set<ResourceType>> {
- val fixedAsChoices = fixedResources.asList().map{ EnumSet.of(it) }.toSet()
+ val fixedAsChoices = fixedResources.toList().map { EnumSet.of(it) }.toSet()
return fixedAsChoices + alternativeResources
}
@@ -42,20 +37,22 @@ class Production internal constructor() {
return containedInAlternatives(resources - fixedResources)
}
- private fun containedInAlternatives(resources: Resources): Boolean {
- return containedInAlternatives(resources, alternativeResources)
- }
+ private fun containedInAlternatives(resources: Resources): Boolean =
+ containedInAlternatives(resources.toMutableResources(), alternativeResources)
- private fun containedInAlternatives(resources: Resources, alternatives: MutableSet<Set<ResourceType>>): Boolean {
- if (resources.isEmpty) {
+ private fun containedInAlternatives(
+ resources: MutableResources,
+ alternatives: MutableSet<Set<ResourceType>>
+ ): Boolean {
+ if (resources.isEmpty()) {
return true
}
for (type in ResourceType.values()) {
- if (resources.getQuantity(type) <= 0) {
+ if (resources[type] <= 0) {
continue
}
- val candidate = findFirstAlternativeContaining(alternatives, type)
- ?: return false // no alternative produces the resource of this entry
+ // return if no alternative produces the resource of this entry
+ val candidate = alternatives.firstOrNull { a -> a.contains(type) } ?: return false
resources.remove(type, 1)
alternatives.remove(candidate)
val remainingAreContainedToo = containedInAlternatives(resources, alternatives)
@@ -67,29 +64,4 @@ class Production internal constructor() {
}
return false
}
-
- private fun findFirstAlternativeContaining(
- alternatives: Set<Set<ResourceType>>,
- type: ResourceType
- ): Set<ResourceType>? {
- return alternatives.stream().filter { a -> a.contains(type) }.findAny().orElse(null)
- }
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as Production
-
- if (fixedResources != other.fixedResources) return false
- if (alternativeResources != other.alternativeResources) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = fixedResources.hashCode()
- result = 31 * result + alternativeResources.hashCode()
- return result
- }
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransaction.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransaction.kt
deleted file mode 100644
index 30f4d014..00000000
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransaction.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.luxons.sevenwonders.game.resources
-
-import org.luxons.sevenwonders.game.Player
-
-data class ResourceTransaction(val provider: Provider, val resources: Resources) {
-
- internal fun execute(player: Player) {
- val board = player.board
- val price = board.tradingRules.computeCost(this)
- board.removeGold(price)
- val providerPosition = provider.boardPosition
- val providerBoard = player.getBoard(providerPosition)
- providerBoard.addGold(price)
- }
-}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
index 52d10064..c7ab3636 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactions.kt
@@ -2,36 +2,25 @@ package org.luxons.sevenwonders.game.resources
import org.luxons.sevenwonders.game.Player
-internal data class ResourceTransactions(private val resourcesByProvider: MutableMap<Provider, Resources> = mutableMapOf()) {
+typealias ResourceTransactions = Collection<ResourceTransaction>
- constructor(transactions: Collection<ResourceTransaction>) : this() {
- transactions.forEach { t -> add(t.provider, t.resources) }
- }
+fun noTransactions(): ResourceTransactions = emptyList()
- fun add(provider: Provider, resources: Resources) {
- resourcesByProvider.merge(provider, resources) { old, new -> old + new }
- }
+fun Map<Provider, Resources>.toTransactions() =
+ filter { (_, res) -> !res.isEmpty() }.map { (p, res) -> ResourceTransaction(p, res) }
- fun remove(provider: Provider, resources: Resources) {
- resourcesByProvider.compute(provider) { _, prevResources ->
- if (prevResources == null) {
- throw IllegalStateException("Cannot remove resources from resource transactions")
- }
- prevResources.minus(resources)
- }
- }
+fun ResourceTransactions.asResources(): Resources = map { it.resources }.merge()
- fun execute(player: Player) {
- asList().forEach { it.execute(player) }
- }
+internal fun ResourceTransactions.execute(player: Player) = forEach { it.execute(player) }
- fun asList(): List<ResourceTransaction> {
- return resourcesByProvider
- .filter { (_, resources) -> !resources.isEmpty }
- .map { (provider, resources) -> ResourceTransaction(provider, resources) }
- }
+data class ResourceTransaction(val provider: Provider, val resources: Resources) {
- fun asResources(): Resources {
- return resourcesByProvider.values.fold(Resources(), Resources::plus)
+ internal fun execute(player: Player) {
+ val board = player.board
+ val price = board.tradingRules.computeCost(this)
+ board.removeGold(price)
+ val providerPosition = provider.boardPosition
+ val providerBoard = player.getBoard(providerPosition)
+ providerBoard.addGold(price)
}
}
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 96ad0b20..15673bd2 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
@@ -2,71 +2,84 @@ package org.luxons.sevenwonders.game.resources
import java.util.NoSuchElementException
-class Resources(quantities: Map<ResourceType, Int> = emptyMap()) {
+fun emptyResources(): Resources = MutableResources()
- private val quantities: MutableMap<ResourceType, Int> = quantities.toMutableMap()
+fun resourcesOf(singleResource: ResourceType): Resources = MutableResources(mutableMapOf(singleResource to 1))
- constructor(singleResource: ResourceType): this(mapOf(singleResource to 1))
+fun resourcesOf(vararg resources: ResourceType): Resources =
+ resources.fold(MutableResources()) { rs, r -> rs.add(r, 1); rs }
- val isEmpty: Boolean
- get() = size() == 0
+fun resourcesOf(resources: Iterable<ResourceType>): Resources =
+ resources.fold(MutableResources()) { rs, r -> rs.add(r, 1); rs }
- fun add(type: ResourceType, quantity: Int) {
- quantities.merge(type, quantity) { x, y -> x + y }
- }
+fun resourcesOf(vararg resources: Pair<ResourceType, Int>): Resources =
+ resources.fold(MutableResources()) { rs, (type, qty) -> rs.add(type, qty); rs }
- fun remove(type: ResourceType, quantity: Int) {
- if (getQuantity(type) < quantity) {
- throw NoSuchElementException("Can't remove $quantity resources of type $type")
- }
- quantities.computeIfPresent(type) { _, oldQty -> oldQty - quantity }
- }
+internal fun mutableResourcesOf() = MutableResources()
- fun addAll(resources: Resources) {
- resources.quantities.forEach { type, quantity -> this.add(type, quantity) }
- }
+internal fun mutableResourcesOf(vararg resources: Pair<ResourceType, Int>) =
+ resources.fold(MutableResources()) { rs, (type, qty) -> rs.add(type, qty); rs }
+
+fun Iterable<ResourceType>.toResources(): Resources = resourcesOf(this)
+
+fun Iterable<Resources>.merge(): Resources = fold(MutableResources()) { r1, r2 -> r1.add(r2); r1}
+
+internal fun Resources.toMutableResources(): MutableResources {
+ val resources = MutableResources()
+ resources.add(this)
+ return resources
+}
- fun getQuantity(type: ResourceType): Int = quantities[type] ?: 0
+interface Resources {
- fun asList(): List<ResourceType> = quantities.flatMap { e -> List(e.value) { e.key } }
+ val quantities: Map<ResourceType, Int>
- fun containsAll(resources: Resources): Boolean = resources.quantities.all { it.value <= this.getQuantity(it.key) }
+ val size: Int
+ get() = quantities.map { it.value }.sum()
+
+ fun isEmpty(): Boolean = size == 0
+
+ operator fun get(key: ResourceType): Int = quantities.getOrDefault(key, 0)
+
+ fun containsAll(resources: Resources): Boolean = resources.quantities.all { it.value <= this[it.key] }
operator fun plus(resources: Resources): Resources {
- val new = Resources(this.quantities)
- new.addAll(resources)
+ val new = MutableResources()
+ new.add(this)
+ new.add(resources)
return new
}
- /**
- * Creates a new [Resources] object containing these resources minus the given resources.
- *
- * @param resources
- * the resources to subtract from these resources
- *
- * @return a new [Resources] object containing these resources minus the given resources.
- */
operator fun minus(resources: Resources): Resources {
- val diff = Resources()
+ val diff = MutableResources()
quantities.forEach { type, count ->
- val remainder = count - resources.getQuantity(type)
+ val remainder = count - resources[type]
diff.quantities[type] = Math.max(0, remainder)
}
return diff
}
- fun size(): Int = quantities.values.sum()
+ fun toList(): List<ResourceType> = quantities.flatMap { (type, quantity) -> List(quantity) { type } }
+}
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
+data class MutableResources(
+ override val quantities: MutableMap<ResourceType, Int> = mutableMapOf()
+) : Resources {
- other as Resources
+ fun add(type: ResourceType, quantity: Int) {
+ quantities.merge(type, quantity) { x, y -> x + y }
+ }
- if (quantities != other.quantities) return false
+ fun add(resources: Resources) = resources.quantities.forEach { type, quantity -> this.add(type, quantity) }
- return true
+ fun remove(type: ResourceType, quantity: Int) {
+ if (this[type] < quantity) {
+ 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 hashCode(): Int = quantities.hashCode()
}
diff --git a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt
index dc0dc489..3b3c81ea 100644
--- a/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt
+++ b/game-engine/src/main/kotlin/org/luxons/sevenwonders/game/resources/TradingRules.kt
@@ -15,22 +15,10 @@ class TradingRules internal constructor(private val defaultCost: Int) {
costs.computeIfAbsent(type) { mutableMapOf() }[provider] = cost
}
- internal fun computeCost(transactions: ResourceTransactions): Int {
- return transactions.asList().map { this.computeCost(it) }.sum()
- }
+ internal fun computeCost(transactions: ResourceTransactions): Int = transactions.map { computeCost(it) }.sum()
- internal fun computeCost(transaction: ResourceTransaction): Int {
- val resources = transaction.resources
- val provider = transaction.provider
- return computeCost(resources, provider)
- }
+ internal fun computeCost(transact: ResourceTransaction) = computeCost(transact.resources, transact.provider)
- private fun computeCost(resources: Resources, provider: Provider): Int {
- var total = 0
- for (type in ResourceType.values()) {
- val count = resources.getQuantity(type)
- total += getCost(type, provider) * count
- }
- return total
- }
+ private fun computeCost(resources: Resources, provider: Provider): Int =
+ resources.quantities.map { (type, qty) -> getCost(type, provider) * qty }.sum()
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt
index 5f76b42e..fb232d9e 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/GameTest.kt
@@ -11,7 +11,9 @@ import org.luxons.sevenwonders.game.data.GameDefinitionLoader
import org.luxons.sevenwonders.game.data.LAST_AGE
import org.luxons.sevenwonders.game.moves.MoveType
import org.luxons.sevenwonders.game.resources.ResourceTransaction
-import org.luxons.sevenwonders.game.resources.bestTransaction
+import org.luxons.sevenwonders.game.resources.ResourceTransactions
+import org.luxons.sevenwonders.game.resources.Resources
+import org.luxons.sevenwonders.game.resources.bestSolution
import org.luxons.sevenwonders.game.test.testCustomizableSettings
import java.util.HashMap
@@ -78,16 +80,19 @@ class GameTest {
return PlayerMove(MoveType.DISCARD, firstCardInHand.card.name)
}
- private fun findResourcesToBuyFor(handCard: HandCard, turnInfo: PlayerTurnInfo): List<ResourceTransaction> {
+ private fun findResourcesToBuyFor(handCard: HandCard, turnInfo: PlayerTurnInfo): Collection<ResourceTransaction> {
if (handCard.isFree) {
return emptyList()
}
val requiredResources = handCard.card.requirements.resources
val table = turnInfo.table
val playerIndex = turnInfo.playerIndex
- val transactions = bestTransaction(requiredResources, PlayerContext(playerIndex, table, listOf()))
// we're supposed to have a best transaction plan because the card is playable
- return transactions!!.asList()
+ return bestTransaction(requiredResources, PlayerContext(playerIndex, table, listOf()))
+ }
+
+ private fun bestTransaction(resources: Resources, player: Player): ResourceTransactions {
+ return bestSolution(resources, player).possibleTransactions.first()
}
private fun createPickGuildMove(turnInfo: PlayerTurnInfo): PlayerMove {
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/boards/BoardTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/boards/BoardTest.kt
index 68799145..0f2a3e0c 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/boards/BoardTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/boards/BoardTest.kt
@@ -18,9 +18,9 @@ import org.luxons.sevenwonders.game.effects.RawPointsIncrease
import org.luxons.sevenwonders.game.effects.SpecialAbility
import org.luxons.sevenwonders.game.effects.SpecialAbilityActivation
import org.luxons.sevenwonders.game.resources.ResourceType
+import org.luxons.sevenwonders.game.resources.resourcesOf
import org.luxons.sevenwonders.game.score.ScoreCategory
import org.luxons.sevenwonders.game.test.addCards
-import org.luxons.sevenwonders.game.test.createResources
import org.luxons.sevenwonders.game.test.getDifferentColorFrom
import org.luxons.sevenwonders.game.test.playCardWithEffect
import org.luxons.sevenwonders.game.test.singleBoardPlayer
@@ -47,7 +47,7 @@ class BoardTest {
@Theory
fun initialProduction_containsInitialResource(type: ResourceType) {
val board = Board(testWonder(type), 0, Settings(5))
- val resources = createResources(type)
+ val resources = resourcesOf(type)
assertTrue(board.production.contains(resources))
assertTrue(board.publicProduction.contains(resources))
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/CardTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/CardTest.kt
index e9f95b55..b8be570f 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/CardTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/CardTest.kt
@@ -8,8 +8,8 @@ import org.luxons.sevenwonders.game.api.Table
import org.luxons.sevenwonders.game.boards.Board
import org.luxons.sevenwonders.game.effects.ProductionIncrease
import org.luxons.sevenwonders.game.resources.Production
-import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.resources.ResourceType
+import org.luxons.sevenwonders.game.resources.noTransactions
import org.luxons.sevenwonders.game.test.testCard
import org.luxons.sevenwonders.game.wonders.Wonder
@@ -36,7 +36,7 @@ class CardTest {
table.getBoard(0).gold = 3
table.getBoard(1).gold = 3
table.getBoard(2).gold = 3
- treeFarmCard.applyTo(SimplePlayer(0, table), ResourceTransactions())
+ treeFarmCard.applyTo(SimplePlayer(0, table), noTransactions())
assertEquals(2, table.getBoard(0).gold.toLong())
assertEquals(3, table.getBoard(1).gold.toLong())
assertEquals(3, table.getBoard(2).gold.toLong())
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt
index 95a5e174..a26034f2 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/cards/RequirementsTest.kt
@@ -10,9 +10,9 @@ import org.junit.runner.RunWith
import org.luxons.sevenwonders.game.SimplePlayer
import org.luxons.sevenwonders.game.api.Table
import org.luxons.sevenwonders.game.resources.Provider
-import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.resources.ResourceType
-import org.luxons.sevenwonders.game.resources.Resources
+import org.luxons.sevenwonders.game.resources.emptyResources
+import org.luxons.sevenwonders.game.resources.noTransactions
import org.luxons.sevenwonders.game.test.createRequirements
import org.luxons.sevenwonders.game.test.createTransactions
import org.luxons.sevenwonders.game.test.singleBoardPlayer
@@ -25,14 +25,14 @@ class RequirementsTest {
@Test
fun getResources_emptyAfterInit() {
val (_, resources) = Requirements()
- assertTrue(resources.isEmpty)
+ assertTrue(resources.isEmpty())
}
@Test
fun setResources_success() {
- val resources = Resources()
- val (_, resources1) = Requirements(0, resources)
- assertSame(resources, resources1)
+ val resources = emptyResources()
+ val requirements = Requirements(0, resources)
+ assertSame(resources, requirements.resources)
}
@Theory
@@ -43,7 +43,7 @@ class RequirementsTest {
val player = singleBoardPlayer(board)
assertEquals(boardGold >= requiredGold, requirements.areMetWithoutNeighboursBy(board))
- assertEquals(boardGold >= requiredGold, requirements.areMetWithHelpBy(board, ResourceTransactions()))
+ assertEquals(boardGold >= requiredGold, requirements.areMetWithHelpBy(board, noTransactions()))
assertEquals(boardGold >= requiredGold, requirements.areMetBy(player))
}
@@ -55,10 +55,7 @@ class RequirementsTest {
val player = singleBoardPlayer(board)
assertEquals(initialResource == requiredResource, requirements.areMetWithoutNeighboursBy(board))
- assertEquals(
- initialResource == requiredResource,
- requirements.areMetWithHelpBy(board, ResourceTransactions())
- )
+ assertEquals(initialResource == requiredResource, requirements.areMetWithHelpBy(board, noTransactions()))
if (initialResource == requiredResource) {
assertTrue(requirements.areMetBy(player))
@@ -67,7 +64,8 @@ class RequirementsTest {
@Theory
fun resourceRequirement_ownProduction(
- initialResource: ResourceType, producedResource: ResourceType,
+ initialResource: ResourceType,
+ producedResource: ResourceType,
requiredResource: ResourceType
) {
assumeTrue(initialResource != requiredResource)
@@ -79,10 +77,7 @@ class RequirementsTest {
val player = singleBoardPlayer(board)
assertEquals(producedResource == requiredResource, requirements.areMetWithoutNeighboursBy(board))
- assertEquals(
- producedResource == requiredResource,
- requirements.areMetWithHelpBy(board, ResourceTransactions())
- )
+ assertEquals(producedResource == requiredResource, requirements.areMetWithHelpBy(board, noTransactions()))
if (producedResource == requiredResource) {
assertTrue(requirements.areMetBy(player))
@@ -91,7 +86,8 @@ class RequirementsTest {
@Theory
fun resourceRequirement_boughtResource(
- initialResource: ResourceType, boughtResource: ResourceType,
+ initialResource: ResourceType,
+ boughtResource: ResourceType,
requiredResource: ResourceType
) {
assumeTrue(initialResource != requiredResource)
@@ -108,10 +104,7 @@ class RequirementsTest {
assertFalse(requirements.areMetWithoutNeighboursBy(board))
assertEquals(boughtResource == requiredResource, requirements.areMetWithHelpBy(board, resources))
-
- if (boughtResource == requiredResource) {
- assertTrue(requirements.areMetBy(player))
- }
+ assertEquals(boughtResource == requiredResource, requirements.areMetBy(player))
}
@Theory
@@ -125,10 +118,7 @@ class RequirementsTest {
val table = Table(Arrays.asList(board, neighbourBoard))
val player = SimplePlayer(0, table)
- val transactions = createTransactions(
- Provider.RIGHT_PLAYER,
- requiredResource
- )
+ val transactions = createTransactions(Provider.RIGHT_PLAYER, requiredResource)
assertFalse(requirements.areMetWithoutNeighboursBy(board))
assertTrue(requirements.areMetWithHelpBy(board, transactions))
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializerTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializerTest.kt
index 5b0a47ab..1b87e593 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializerTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionIncreaseSerializerTest.kt
@@ -8,6 +8,7 @@ import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
import org.luxons.sevenwonders.game.effects.ProductionIncrease
+import org.luxons.sevenwonders.game.resources.MutableResources
import org.luxons.sevenwonders.game.resources.Production
import org.luxons.sevenwonders.game.resources.ResourceType
import org.luxons.sevenwonders.game.resources.Resources
@@ -22,6 +23,7 @@ class ProductionIncreaseSerializerTest {
}.type
gson = GsonBuilder().registerTypeAdapter(Resources::class.java, ResourcesSerializer())
+ .registerTypeAdapter(MutableResources::class.java, ResourcesSerializer())
.registerTypeAdapter(ResourceType::class.java, ResourceTypeSerializer())
.registerTypeAdapter(resourceTypeList, ResourceTypesSerializer())
.registerTypeAdapter(Production::class.java, ProductionSerializer())
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializerTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializerTest.kt
index f74e21c5..66d4013a 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializerTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ProductionSerializerTest.kt
@@ -7,6 +7,7 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
+import org.luxons.sevenwonders.game.resources.MutableResources
import org.luxons.sevenwonders.game.resources.Production
import org.luxons.sevenwonders.game.resources.ResourceType
import org.luxons.sevenwonders.game.resources.Resources
@@ -17,10 +18,9 @@ class ProductionSerializerTest {
@Before
fun setUp() {
- val resourceTypeList = object : TypeToken<List<ResourceType>>() {
-
- }.type
+ val resourceTypeList = object : TypeToken<List<ResourceType>>() {}.type
gson = GsonBuilder().registerTypeAdapter(Resources::class.java, ResourcesSerializer())
+ .registerTypeAdapter(MutableResources::class.java, ResourcesSerializer())
.registerTypeAdapter(ResourceType::class.java, ResourceTypeSerializer())
.registerTypeAdapter(resourceTypeList, ResourceTypesSerializer())
.registerTypeAdapter(Production::class.java, ProductionSerializer())
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializerTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializerTest.kt
index 500c2666..426e0f0e 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializerTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/data/serializers/ResourcesSerializerTest.kt
@@ -6,8 +6,11 @@ import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Test
-import org.luxons.sevenwonders.game.resources.ResourceType
+import org.luxons.sevenwonders.game.resources.MutableResources
+import org.luxons.sevenwonders.game.resources.ResourceType.*
import org.luxons.sevenwonders.game.resources.Resources
+import org.luxons.sevenwonders.game.resources.emptyResources
+import org.luxons.sevenwonders.game.resources.resourcesOf
class ResourcesSerializerTest {
@@ -15,7 +18,10 @@ class ResourcesSerializerTest {
@Before
fun setUp() {
- gson = GsonBuilder().registerTypeAdapter(Resources::class.java, ResourcesSerializer()).create()
+ gson = GsonBuilder()
+ .registerTypeAdapter(Resources::class.java, ResourcesSerializer())
+ .registerTypeAdapter(MutableResources::class.java, ResourcesSerializer())
+ .create()
}
@Test
@@ -25,40 +31,31 @@ class ResourcesSerializerTest {
@Test
fun serialize_emptyResourcesToNull() {
- val resources = Resources()
+ val resources = emptyResources()
assertEquals("null", gson!!.toJson(resources))
}
@Test
fun serialize_singleType() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 1)
+ val resources = resourcesOf(WOOD)
assertEquals("\"W\"", gson!!.toJson(resources))
}
@Test
fun serialize_multipleTimesSameType() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 3)
+ val resources = resourcesOf(WOOD to 3)
assertEquals("\"WWW\"", gson!!.toJson(resources))
}
@Test
fun serialize_mixedTypes() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 1)
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 1)
+ val resources = resourcesOf(WOOD, STONE, CLAY)
assertEquals("\"WSC\"", gson!!.toJson(resources))
}
@Test
fun serialize_mixedTypes_unordered() {
- val resources = Resources()
- resources.add(ResourceType.CLAY, 1)
- resources.add(ResourceType.WOOD, 2)
- resources.add(ResourceType.CLAY, 1)
- resources.add(ResourceType.STONE, 1)
+ val resources = resourcesOf(CLAY to 1, WOOD to 2, CLAY to 1, STONE to 1)
assertEquals("\"CCWWS\"", gson!!.toJson(resources))
}
@@ -69,39 +66,31 @@ class ResourcesSerializerTest {
@Test
fun deserialize_emptyList() {
- val resources = Resources()
+ val resources = emptyResources()
assertEquals(resources, gson!!.fromJson("\"\"", Resources::class.java))
}
@Test
fun deserialize_singleType() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 1)
+ val resources = resourcesOf(WOOD)
assertEquals(resources, gson!!.fromJson("\"W\"", Resources::class.java))
}
@Test
fun deserialize_multipleTimesSameType() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 3)
+ val resources = resourcesOf(WOOD to 3)
assertEquals(resources, gson!!.fromJson("\"WWW\"", Resources::class.java))
}
@Test
fun deserialize_mixedTypes() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 1)
- resources.add(ResourceType.CLAY, 1)
- resources.add(ResourceType.STONE, 1)
+ val resources = resourcesOf(WOOD, CLAY, STONE)
assertEquals(resources, gson!!.fromJson("\"WCS\"", Resources::class.java))
}
@Test
fun deserialize_mixedTypes_unordered() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 1)
- resources.add(ResourceType.CLAY, 2)
- resources.add(ResourceType.STONE, 3)
+ val resources = resourcesOf(WOOD to 1, CLAY to 2, STONE to 3)
assertEquals(resources, gson!!.fromJson("\"SCWCSS\"", Resources::class.java))
}
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/effects/ProductionIncreaseTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/effects/ProductionIncreaseTest.kt
index 9d5be34f..7973131c 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/effects/ProductionIncreaseTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/effects/ProductionIncreaseTest.kt
@@ -7,7 +7,7 @@ import org.junit.experimental.theories.Theory
import org.junit.runner.RunWith
import org.luxons.sevenwonders.game.SimplePlayer
import org.luxons.sevenwonders.game.resources.ResourceType
-import org.luxons.sevenwonders.game.test.createResources
+import org.luxons.sevenwonders.game.resources.resourcesOf
import org.luxons.sevenwonders.game.test.fixedProduction
import org.luxons.sevenwonders.game.test.testBoard
import org.luxons.sevenwonders.game.test.testTable
@@ -26,11 +26,11 @@ class ProductionIncreaseTest {
effect.applyTo(board)
- val resources = createResources(initialType, addedType)
+ val resources = resourcesOf(initialType, addedType)
assertTrue(board.production.contains(resources))
assertFalse(board.publicProduction.contains(resources))
- val moreResources = createResources(initialType, addedType, extraType)
+ val moreResources = resourcesOf(initialType, addedType, extraType)
assertFalse(board.production.contains(moreResources))
assertFalse(board.publicProduction.contains(moreResources))
}
@@ -46,11 +46,11 @@ class ProductionIncreaseTest {
effect.applyTo(board)
- val resources = createResources(initialType, addedType)
+ val resources = resourcesOf(initialType, addedType)
assertTrue(board.production.contains(resources))
assertTrue(board.publicProduction.contains(resources))
- val moreResources = createResources(initialType, addedType, extraType)
+ val moreResources = resourcesOf(initialType, addedType, extraType)
assertFalse(board.production.contains(moreResources))
assertFalse(board.publicProduction.contains(moreResources))
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt
index ca279d97..67537644 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/BestPriceCalculatorTest.kt
@@ -7,7 +7,6 @@ import org.luxons.sevenwonders.game.api.Table
import org.luxons.sevenwonders.game.resources.Provider.LEFT_PLAYER
import org.luxons.sevenwonders.game.resources.Provider.RIGHT_PLAYER
import org.luxons.sevenwonders.game.resources.ResourceType.*
-import org.luxons.sevenwonders.game.test.createResources
import org.luxons.sevenwonders.game.test.createTransaction
import org.luxons.sevenwonders.game.test.createTransactions
import org.luxons.sevenwonders.game.test.testBoard
@@ -16,13 +15,16 @@ import java.util.Arrays
class BestPriceCalculatorTest {
+ private fun solutions(price: Int, vararg resourceTransactions: ResourceTransactions) =
+ TransactionPlan(price, setOf(*resourceTransactions))
+
@Test
fun bestPrice_0forEmptyResources() {
val table = testTable(3)
val player0 = SimplePlayer(0, table)
- val emptyResources = Resources()
- val emptyTransactions = ResourceTransactions()
- assertEquals(TransactionPlan(0, emptyTransactions), bestSolution(emptyResources, player0))
+ val emptyResources = emptyResources()
+ val emptyTransactions = noTransactions()
+ assertEquals(solutions(0, emptyTransactions), bestSolution(emptyResources, player0))
}
@Test
@@ -31,12 +33,12 @@ class BestPriceCalculatorTest {
val main = testBoard(STONE)
val right = testBoard(WOOD)
val table = Table(Arrays.asList(main, right, left))
-
+
val player0 = SimplePlayer(0, table)
val player1 = SimplePlayer(1, table)
val player2 = SimplePlayer(2, table)
- val resources = createResources(STONE, STONE)
+ val resources = resourcesOf(STONE, STONE)
val stoneLeftSingle = createTransaction(LEFT_PLAYER, STONE)
val stoneRightSingle = createTransaction(RIGHT_PLAYER, STONE)
@@ -45,9 +47,9 @@ class BestPriceCalculatorTest {
val stoneRight = createTransactions(stoneRightSingle)
val stoneLeftAndRight = createTransactions(stoneLeftSingle, stoneRightSingle)
- assertEquals(TransactionPlan(2, stoneLeft), bestSolution(resources, player0))
- assertEquals(TransactionPlan(4, stoneLeftAndRight), bestSolution(resources, player1))
- assertEquals(TransactionPlan(2, stoneRight), bestSolution(resources, player2))
+ assertEquals(solutions(2, stoneLeft), bestSolution(resources, player0))
+ assertEquals(solutions(4, stoneLeftAndRight), bestSolution(resources, player1))
+ assertEquals(solutions(2, stoneRight), bestSolution(resources, player2))
}
@Test
@@ -65,15 +67,15 @@ class BestPriceCalculatorTest {
val player2 = SimplePlayer(2, table)
val player3 = SimplePlayer(3, table)
- val resources = createResources(WOOD)
+ val resources = resourcesOf(WOOD)
val woodLeft = createTransactions(LEFT_PLAYER, WOOD)
val woodRight = createTransactions(RIGHT_PLAYER, WOOD)
- assertEquals(TransactionPlan(1, woodRight), bestSolution(resources, player0))
- assertEquals(TransactionPlan(0, ResourceTransactions()), bestSolution(resources, player1))
- assertEquals(TransactionPlan(2, woodLeft), bestSolution(resources, player2))
- assertEquals(TransactionPlan(0, ResourceTransactions()), bestSolution(resources, player3))
+ assertEquals(solutions(1, woodRight), bestSolution(resources, player0))
+ assertEquals(solutions(0, noTransactions()), bestSolution(resources, player1))
+ assertEquals(solutions(2, woodLeft, woodRight), bestSolution(resources, player2))
+ assertEquals(solutions(0, noTransactions()), bestSolution(resources, player3))
}
@Test
@@ -93,12 +95,12 @@ class BestPriceCalculatorTest {
val player1 = SimplePlayer(1, table)
val player2 = SimplePlayer(2, table)
- val resources = createResources(WOOD)
+ val resources = resourcesOf(WOOD)
val woodRight = createTransactions(RIGHT_PLAYER, WOOD)
- assertEquals(TransactionPlan(1, woodRight), bestSolution(resources, player0))
- assertEquals(TransactionPlan(0, ResourceTransactions()), bestSolution(resources, player1))
- assertEquals(TransactionPlan(0, ResourceTransactions()), bestSolution(resources, player2))
+ assertEquals(solutions(1, woodRight), bestSolution(resources, player0))
+ assertEquals(solutions(0, noTransactions()), bestSolution(resources, player1))
+ assertEquals(solutions(0, noTransactions()), bestSolution(resources, player2))
}
@Test
@@ -121,12 +123,12 @@ class BestPriceCalculatorTest {
val player1 = SimplePlayer(1, table)
val player2 = SimplePlayer(2, table)
- val resources = createResources(ORE, CLAY)
+ val resources = resourcesOf(ORE, CLAY)
val oreAndClayLeft = createTransactions(LEFT_PLAYER, ORE, CLAY)
val clayRight = createTransactions(RIGHT_PLAYER, CLAY)
- assertEquals(TransactionPlan(1, clayRight), bestSolution(resources, player0))
- assertEquals(TransactionPlan(0, ResourceTransactions()), bestSolution(resources, player1))
- assertEquals(TransactionPlan(4, oreAndClayLeft), bestSolution(resources, player2))
+ assertEquals(solutions(1, clayRight), bestSolution(resources, player0))
+ assertEquals(solutions(0, noTransactions()), bestSolution(resources, player1))
+ assertEquals(solutions(4, oreAndClayLeft), bestSolution(resources, player2))
}
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt
index 92623a2b..79be288f 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ProductionTest.kt
@@ -3,38 +3,27 @@ package org.luxons.sevenwonders.game.resources
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
+import org.luxons.sevenwonders.game.resources.ResourceType.*
import java.util.EnumSet
import java.util.HashSet
class ProductionTest {
- private var emptyResources: Resources = Resources()
- private var resources1Wood: Resources = Resources()
- private var resources1Stone: Resources = Resources()
- private var resources1Stone1Wood: Resources = Resources()
- private var resources2Stones: Resources = Resources()
- private var resources2Stones3Clay: Resources = Resources()
+ private lateinit var emptyResources: Resources
+ private lateinit var resources1Wood: Resources
+ private lateinit var resources1Stone: Resources
+ private lateinit var resources1Stone1Wood: Resources
+ private lateinit var resources2Stones: Resources
+ private lateinit var resources2Stones3Clay: Resources
@Before
fun init() {
- emptyResources = Resources()
-
- resources1Wood = Resources()
- resources1Wood.add(ResourceType.WOOD, 1)
-
- resources1Stone = Resources()
- resources1Stone.add(ResourceType.STONE, 1)
-
- resources1Stone1Wood = Resources()
- resources1Stone1Wood.add(ResourceType.STONE, 1)
- resources1Stone1Wood.add(ResourceType.WOOD, 1)
-
- resources2Stones = Resources()
- resources2Stones.add(ResourceType.STONE, 2)
-
- resources2Stones3Clay = Resources()
- resources2Stones3Clay.add(ResourceType.STONE, 2)
- resources2Stones3Clay.add(ResourceType.CLAY, 3)
+ emptyResources = emptyResources()
+ resources1Wood = resourcesOf(WOOD)
+ resources1Stone = resourcesOf(STONE)
+ resources1Stone1Wood = resourcesOf(STONE to 1, WOOD to 1)
+ resources2Stones = resourcesOf(STONE to 2)
+ resources2Stones3Clay = resourcesOf(STONE to 2, CLAY to 3)
}
@Test
@@ -52,67 +41,67 @@ class ProductionTest {
@Test
fun contains_singleFixedResource_notEnough() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 1)
+ production.addFixedResource(STONE, 1)
assertFalse(production.contains(resources2Stones))
}
@Test
fun contains_singleFixedResource_justEnough() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 2)
+ production.addFixedResource(STONE, 2)
assertTrue(production.contains(resources2Stones))
}
@Test
fun contains_singleFixedResource_moreThanEnough() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 3)
+ production.addFixedResource(STONE, 3)
assertTrue(production.contains(resources2Stones))
}
@Test
fun contains_singleFixedResource_moreThanEnough_amongOthers() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 3)
- production.addFixedResource(ResourceType.CLAY, 2)
+ production.addFixedResource(STONE, 3)
+ production.addFixedResource(CLAY, 2)
assertTrue(production.contains(resources2Stones))
}
@Test
fun contains_multipleFixedResources_notEnoughOfOne() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 3)
- production.addFixedResource(ResourceType.CLAY, 1)
+ production.addFixedResource(STONE, 3)
+ production.addFixedResource(CLAY, 1)
assertFalse(production.contains(resources2Stones3Clay))
}
@Test
fun contains_multipleFixedResources_notEnoughOfBoth() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 1)
- production.addFixedResource(ResourceType.CLAY, 1)
+ production.addFixedResource(STONE, 1)
+ production.addFixedResource(CLAY, 1)
assertFalse(production.contains(resources2Stones3Clay))
}
@Test
fun contains_multipleFixedResources_moreThanEnough() {
val production = Production()
- production.addFixedResource(ResourceType.STONE, 3)
- production.addFixedResource(ResourceType.CLAY, 5)
+ production.addFixedResource(STONE, 3)
+ production.addFixedResource(CLAY, 5)
assertTrue(production.contains(resources2Stones3Clay))
}
@Test
fun contains_singleChoice_containsEmpty() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.CLAY)
+ production.addChoice(STONE, CLAY)
assertTrue(production.contains(emptyResources))
}
@Test
fun contains_singleChoice_enough() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addChoice(STONE, WOOD)
assertTrue(production.contains(resources1Wood))
assertTrue(production.contains(resources1Stone))
}
@@ -120,42 +109,42 @@ class ProductionTest {
@Test
fun contains_multipleChoices_notBoth() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.CLAY)
- production.addChoice(ResourceType.STONE, ResourceType.CLAY)
- production.addChoice(ResourceType.STONE, ResourceType.CLAY)
+ production.addChoice(STONE, CLAY)
+ production.addChoice(STONE, CLAY)
+ production.addChoice(STONE, CLAY)
assertFalse(production.contains(resources2Stones3Clay))
}
@Test
fun contains_multipleChoices_enough() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.ORE)
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addChoice(STONE, ORE)
+ production.addChoice(STONE, WOOD)
assertTrue(production.contains(resources1Stone1Wood))
}
@Test
fun contains_multipleChoices_enoughReverseOrder() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
- production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ production.addChoice(STONE, WOOD)
+ production.addChoice(STONE, ORE)
assertTrue(production.contains(resources1Stone1Wood))
}
@Test
fun contains_multipleChoices_moreThanEnough() {
val production = Production()
- production.addChoice(ResourceType.LOOM, ResourceType.GLASS, ResourceType.PAPYRUS)
- production.addChoice(ResourceType.STONE, ResourceType.ORE)
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addChoice(LOOM, GLASS, PAPYRUS)
+ production.addChoice(STONE, ORE)
+ production.addChoice(STONE, WOOD)
assertTrue(production.contains(resources1Stone1Wood))
}
@Test
fun contains_mixedFixedAndChoice_enough() {
val production = Production()
- production.addFixedResource(ResourceType.WOOD, 1)
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addFixedResource(WOOD, 1)
+ production.addChoice(STONE, WOOD)
assertTrue(production.contains(resources1Stone1Wood))
}
@@ -194,8 +183,8 @@ class ProductionTest {
@Test
fun addAll_production_multipleChoices() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
- production.addChoice(ResourceType.STONE, ResourceType.ORE)
+ production.addChoice(STONE, WOOD)
+ production.addChoice(STONE, ORE)
val production2 = Production()
production2.addAll(production)
@@ -205,8 +194,8 @@ class ProductionTest {
@Test
fun addAll_production_mixedFixedResourcesAndChoices() {
val production = Production()
- production.addFixedResource(ResourceType.WOOD, 1)
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
+ production.addFixedResource(WOOD, 1)
+ production.addChoice(STONE, WOOD)
val production2 = Production()
production2.addAll(production)
@@ -223,22 +212,22 @@ class ProductionTest {
@Test
fun asChoices_onlyChoices() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.WOOD)
- production.addChoice(ResourceType.STONE, ResourceType.ORE)
- production.addChoice(ResourceType.CLAY, ResourceType.LOOM, ResourceType.GLASS)
+ production.addChoice(STONE, WOOD)
+ production.addChoice(STONE, ORE)
+ production.addChoice(CLAY, LOOM, GLASS)
assertEquals(production.getAlternativeResources(), production.asChoices())
}
@Test
fun asChoices_onlyFixed() {
val production = Production()
- production.addFixedResource(ResourceType.WOOD, 1)
- production.addFixedResource(ResourceType.CLAY, 2)
+ production.addFixedResource(WOOD, 1)
+ production.addFixedResource(CLAY, 2)
val expected = HashSet<Set<ResourceType>>()
- expected.add(EnumSet.of(ResourceType.WOOD))
- expected.add(EnumSet.of(ResourceType.CLAY))
- expected.add(EnumSet.of(ResourceType.CLAY))
+ expected.add(EnumSet.of(WOOD))
+ expected.add(EnumSet.of(CLAY))
+ expected.add(EnumSet.of(CLAY))
assertEquals(expected, production.asChoices())
}
@@ -246,17 +235,17 @@ class ProductionTest {
@Test
fun asChoices_mixed() {
val production = Production()
- production.addChoice(ResourceType.STONE, ResourceType.ORE)
- production.addChoice(ResourceType.CLAY, ResourceType.LOOM, ResourceType.GLASS)
- production.addFixedResource(ResourceType.WOOD, 1)
- production.addFixedResource(ResourceType.CLAY, 2)
+ production.addChoice(STONE, ORE)
+ production.addChoice(CLAY, LOOM, GLASS)
+ production.addFixedResource(WOOD, 1)
+ production.addFixedResource(CLAY, 2)
val expected = HashSet<Set<ResourceType>>()
- expected.add(EnumSet.of(ResourceType.STONE, ResourceType.ORE))
- expected.add(EnumSet.of(ResourceType.CLAY, ResourceType.LOOM, ResourceType.GLASS))
- expected.add(EnumSet.of(ResourceType.WOOD))
- expected.add(EnumSet.of(ResourceType.CLAY))
- expected.add(EnumSet.of(ResourceType.CLAY))
+ expected.add(EnumSet.of(STONE, ORE))
+ expected.add(EnumSet.of(CLAY, LOOM, GLASS))
+ expected.add(EnumSet.of(WOOD))
+ expected.add(EnumSet.of(CLAY))
+ expected.add(EnumSet.of(CLAY))
assertEquals(expected, production.asChoices())
}
@@ -272,11 +261,11 @@ class ProductionTest {
val production1 = Production()
val production2 = Production()
assertTrue(production1 == production2)
- production1.addFixedResource(ResourceType.GLASS, 1)
- production2.addFixedResource(ResourceType.GLASS, 1)
+ production1.addFixedResource(GLASS, 1)
+ production2.addFixedResource(GLASS, 1)
assertTrue(production1 == production2)
- production1.addChoice(ResourceType.ORE, ResourceType.WOOD)
- production2.addChoice(ResourceType.ORE, ResourceType.WOOD)
+ production1.addChoice(ORE, WOOD)
+ production2.addChoice(ORE, WOOD)
assertTrue(production1 == production2)
}
@@ -285,11 +274,11 @@ class ProductionTest {
val production1 = Production()
val production2 = Production()
assertEquals(production1.hashCode().toLong(), production2.hashCode().toLong())
- production1.addFixedResource(ResourceType.GLASS, 1)
- production2.addFixedResource(ResourceType.GLASS, 1)
+ production1.addFixedResource(GLASS, 1)
+ production2.addFixedResource(GLASS, 1)
assertEquals(production1.hashCode().toLong(), production2.hashCode().toLong())
- production1.addChoice(ResourceType.ORE, ResourceType.WOOD)
- production2.addChoice(ResourceType.ORE, ResourceType.WOOD)
+ production1.addChoice(ORE, WOOD)
+ production2.addChoice(ORE, WOOD)
assertEquals(production1.hashCode().toLong(), production2.hashCode().toLong())
}
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt
index 26ab16fa..172df278 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourceTransactionsTest.kt
@@ -2,31 +2,25 @@ package org.luxons.sevenwonders.game.resources
import org.junit.Assert.assertEquals
import org.junit.Test
+import org.luxons.sevenwonders.game.resources.ResourceType.CLAY
+import org.luxons.sevenwonders.game.resources.ResourceType.WOOD
import org.luxons.sevenwonders.game.test.createTransaction
+import org.luxons.sevenwonders.game.test.of
class ResourceTransactionsTest {
@Test
fun toTransactions() {
- val transactionList = listOf(
- createTransaction(Provider.LEFT_PLAYER, ResourceType.WOOD),
- createTransaction(Provider.LEFT_PLAYER, ResourceType.CLAY),
- createTransaction(Provider.RIGHT_PLAYER, ResourceType.WOOD)
+ val transactionMap = mapOf(
+ Provider.LEFT_PLAYER to (1 of WOOD) + (1 of CLAY),
+ Provider.RIGHT_PLAYER to (1 of WOOD)
)
- val transactions = ResourceTransactions(transactionList)
-
val expectedNormalized = setOf(
- createTransaction(Provider.LEFT_PLAYER, ResourceType.WOOD, ResourceType.CLAY),
- createTransaction(Provider.RIGHT_PLAYER, ResourceType.WOOD)
+ createTransaction(Provider.LEFT_PLAYER, WOOD, CLAY),
+ createTransaction(Provider.RIGHT_PLAYER, WOOD)
)
- assertEquals(expectedNormalized, transactions.asList().toSet())
- }
-
- @Test(expected = IllegalStateException::class)
- fun remove_failsIfNoResourceForThatProvider() {
- val transactions = ResourceTransactions()
- transactions.remove(Provider.LEFT_PLAYER, Resources(ResourceType.WOOD))
+ assertEquals(expectedNormalized, transactionMap.toTransactions().toSet())
}
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt
index a6ffb6c6..9fa0bc55 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/ResourcesTest.kt
@@ -4,6 +4,7 @@ import org.junit.Assert.*
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
+import org.luxons.sevenwonders.game.resources.ResourceType.*
import java.util.NoSuchElementException
class ResourcesTest {
@@ -14,503 +15,417 @@ class ResourcesTest {
@Test
fun init_shouldBeEmpty() {
- val resources = Resources()
- for (resourceType in ResourceType.values()) {
- assertEquals(0, resources.getQuantity(resourceType).toLong())
+ val resources = emptyResources()
+ for (resourceType in values()) {
+ assertEquals(0, resources[resourceType])
}
- assertEquals(0, resources.size().toLong())
- assertTrue(resources.isEmpty)
+ assertEquals(0, resources.size)
+ assertTrue(resources.isEmpty())
}
@Test
fun add_zero() {
- val resources = Resources()
- resources.add(ResourceType.CLAY, 0)
- assertEquals(0, resources.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, resources.size().toLong())
- assertTrue(resources.isEmpty)
+ val resources = mutableResourcesOf()
+ resources.add(CLAY, 0)
+ assertEquals(0, resources[CLAY])
+ assertEquals(0, resources.size)
+ assertTrue(resources.isEmpty())
}
@Test
fun add_simple() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 3)
- assertEquals(3, resources.getQuantity(ResourceType.WOOD).toLong())
- assertEquals(3, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ val resources = mutableResourcesOf()
+ resources.add(WOOD, 3)
+ assertEquals(3, resources[WOOD])
+ assertEquals(3, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun add_multipleCallsStacked() {
- val resources = Resources()
- resources.add(ResourceType.ORE, 3)
- resources.add(ResourceType.ORE, 2)
- assertEquals(5, resources.getQuantity(ResourceType.ORE).toLong())
- assertEquals(5, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ val resources = mutableResourcesOf()
+ resources.add(ORE, 3)
+ resources.add(ORE, 2)
+ assertEquals(5, resources[ORE])
+ assertEquals(5, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun add_interlaced() {
- val resources = Resources()
- resources.add(ResourceType.GLASS, 3)
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.WOOD, 4)
- resources.add(ResourceType.GLASS, 2)
- assertEquals(5, resources.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(10, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ val resources = mutableResourcesOf()
+ resources.add(GLASS, 3)
+ resources.add(STONE, 1)
+ resources.add(WOOD, 4)
+ resources.add(GLASS, 2)
+ assertEquals(5, resources[GLASS])
+ assertEquals(10, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun plus_zero() {
- val resources = Resources(mapOf(ResourceType.CLAY to 2))
- val resourcesPlusZero = resources + Resources()
- val zeroPlusResources = Resources() + resources
+ val resources = resourcesOf(CLAY to 2)
+ val resourcesPlusZero = resources + emptyResources()
+ val zeroPlusResources = emptyResources() + resources
- assertEquals(2, resourcesPlusZero.getQuantity(ResourceType.CLAY))
- assertEquals(2, resourcesPlusZero.size())
- assertEquals(2, zeroPlusResources.getQuantity(ResourceType.CLAY))
- assertEquals(2, zeroPlusResources.size())
+ assertEquals(2, resourcesPlusZero[CLAY])
+ assertEquals(2, resourcesPlusZero.size)
+ assertEquals(2, zeroPlusResources[CLAY])
+ assertEquals(2, zeroPlusResources.size)
}
@Test
fun plus_sameResource() {
- val resources1 = Resources(mapOf(ResourceType.WOOD to 1))
- val resources2 = Resources(mapOf(ResourceType.WOOD to 3))
+ val resources1 = resourcesOf(WOOD to 1)
+ val resources2 = resourcesOf(WOOD to 3)
val sum = resources1 + resources2
- assertEquals(4, sum.getQuantity(ResourceType.WOOD).toLong())
- assertEquals(4, sum.size())
+ assertEquals(1, resources1.size)
+ assertEquals(3, resources2.size)
+ assertEquals(4, sum[WOOD])
+ assertEquals(4, sum.size)
}
@Test
- fun plus_differentResources() {
- val resources1 = Resources(mapOf(ResourceType.WOOD to 1))
- val resources2 = Resources(mapOf(ResourceType.ORE to 3))
+ fun plus_differentemptyResources() {
+ val resources1 = resourcesOf(WOOD to 1)
+ val resources2 = resourcesOf(ORE to 3)
val sum = resources1 + resources2
- assertEquals(1, sum.getQuantity(ResourceType.WOOD).toLong())
- assertEquals(3, sum.getQuantity(ResourceType.ORE).toLong())
- assertEquals(4, sum.size())
+ assertEquals(1, resources1.size)
+ assertEquals(3, resources2.size)
+ assertEquals(1, sum[WOOD])
+ assertEquals(3, sum[ORE])
+ assertEquals(4, sum.size)
}
@Test
- fun plus_overlappingResources() {
- val resources1 = Resources(mapOf(ResourceType.WOOD to 1))
- val resources2 = Resources(mapOf(ResourceType.WOOD to 2, ResourceType.ORE to 4))
+ fun plus_overlappingemptyResources() {
+ val resources1 = resourcesOf(WOOD to 1)
+ val resources2 = resourcesOf(WOOD to 2, ORE to 4)
val sum = resources1 + resources2
- assertEquals(3, sum.getQuantity(ResourceType.WOOD).toLong())
- assertEquals(4, sum.getQuantity(ResourceType.ORE).toLong())
- assertEquals(7, sum.size())
+ assertEquals(1, resources1.size)
+ assertEquals(6, resources2.size)
+ assertEquals(3, sum[WOOD])
+ assertEquals(4, sum[ORE])
+ assertEquals(7, sum.size)
}
@Test
fun remove_some() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 3)
- resources.remove(ResourceType.WOOD, 2)
- assertEquals(1, resources.getQuantity(ResourceType.WOOD).toLong())
- assertEquals(1, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ val resources = mutableResourcesOf(WOOD to 3)
+ resources.remove(WOOD, 2)
+ assertEquals(1, resources[WOOD])
+ assertEquals(1, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun remove_all() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 3)
- resources.remove(ResourceType.WOOD, 3)
- assertEquals(0, resources.getQuantity(ResourceType.WOOD).toLong())
- assertEquals(0, resources.size().toLong())
- assertTrue(resources.isEmpty)
+ val resources = mutableResourcesOf(WOOD to 3)
+ resources.remove(WOOD, 3)
+ assertEquals(0, resources[WOOD])
+ assertEquals(0, resources.size)
+ assertTrue(resources.isEmpty())
}
@Test
fun remove_tooMany() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 2)
+ val resources = mutableResourcesOf(WOOD to 2)
thrown.expect(NoSuchElementException::class.java)
- resources.remove(ResourceType.WOOD, 3)
+ resources.remove(WOOD, 3)
}
@Test
fun addAll_empty() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
+ val resources = mutableResourcesOf(STONE to 1, CLAY to 3)
- val emptyResources = Resources()
+ val emptyResources = emptyResources()
- resources.addAll(emptyResources)
- assertEquals(1, resources.getQuantity(ResourceType.STONE).toLong())
- assertEquals(3, resources.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
- assertEquals(4, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ resources.add(emptyResources)
+ assertEquals(1, resources[STONE])
+ assertEquals(3, resources[CLAY])
+ assertEquals(0, resources[ORE])
+ assertEquals(0, resources[GLASS])
+ assertEquals(0, resources[LOOM])
+ assertEquals(4, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun addAll_zeros() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
+ val resources = mutableResourcesOf(STONE to 1, CLAY to 3)
- val emptyResources = Resources()
- emptyResources.add(ResourceType.STONE, 0)
- emptyResources.add(ResourceType.CLAY, 0)
+ val emptyResources = resourcesOf(STONE to 0, CLAY to 0)
- resources.addAll(emptyResources)
- assertEquals(1, resources.getQuantity(ResourceType.STONE).toLong())
- assertEquals(3, resources.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
- assertEquals(4, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ resources.add(emptyResources)
+ assertEquals(1, resources[STONE])
+ assertEquals(3, resources[CLAY])
+ assertEquals(0, resources[ORE])
+ assertEquals(0, resources[GLASS])
+ assertEquals(0, resources[LOOM])
+ assertEquals(4, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun addAll_same() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
+ val resources = mutableResourcesOf(STONE to 1, CLAY to 3)
+ val resources2 = resourcesOf(STONE to 2, CLAY to 6)
- val resources2 = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 6)
-
- resources.addAll(resources2)
- assertEquals(3, resources.getQuantity(ResourceType.STONE).toLong())
- assertEquals(9, resources.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
- assertEquals(12, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ resources.add(resources2)
+ assertEquals(3, resources[STONE])
+ assertEquals(9, resources[CLAY])
+ assertEquals(0, resources[ORE])
+ assertEquals(0, resources[GLASS])
+ assertEquals(0, resources[LOOM])
+ assertEquals(12, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun addAll_overlap() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
-
- val resources2 = Resources()
- resources.add(ResourceType.CLAY, 6)
- resources.add(ResourceType.ORE, 4)
+ val resources = mutableResourcesOf(STONE to 1, CLAY to 3)
+ val resources2 = resourcesOf(CLAY to 6, ORE to 4)
- resources.addAll(resources2)
- assertEquals(1, resources.getQuantity(ResourceType.STONE).toLong())
- assertEquals(9, resources.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(4, resources.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, resources.getQuantity(ResourceType.LOOM).toLong())
- assertEquals(14, resources.size().toLong())
- assertFalse(resources.isEmpty)
+ resources.add(resources2)
+ assertEquals(1, resources[STONE])
+ assertEquals(9, resources[CLAY])
+ assertEquals(4, resources[ORE])
+ assertEquals(0, resources[GLASS])
+ assertEquals(0, resources[LOOM])
+ assertEquals(14, resources.size)
+ assertFalse(resources.isEmpty())
}
@Test
fun contains_emptyContainsEmpty() {
- val emptyResources = Resources()
- val emptyResources2 = Resources()
+ val emptyResources = emptyResources()
+ val emptyResources2 = emptyResources()
assertTrue(emptyResources.containsAll(emptyResources2))
}
@Test
fun contains_singleTypeContainsEmpty() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
-
- val emptyResources = Resources()
+ val resources = resourcesOf(STONE to 1)
+ val emptyResources = emptyResources()
assertTrue(resources.containsAll(emptyResources))
}
@Test
fun contains_multipleTypesContainsEmpty() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
-
- val emptyResources = Resources()
+ val resources = resourcesOf(STONE to 1, CLAY to 3)
+ val emptyResources = emptyResources()
assertTrue(resources.containsAll(emptyResources))
}
@Test
fun contains_self() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 1, CLAY to 3)
assertTrue(resources.containsAll(resources))
}
@Test
fun contains_allOfEachType() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
-
- val resources2 = Resources()
- resources2.add(ResourceType.STONE, 1)
- resources2.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 1, CLAY to 3)
+ val resources2 = resourcesOf(STONE to 1, CLAY to 3)
assertTrue(resources.containsAll(resources2))
}
@Test
fun contains_someOfEachType() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.STONE, 1)
- resources2.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 2, CLAY to 4)
+ val resources2 = resourcesOf(STONE to 1, CLAY to 3)
assertTrue(resources.containsAll(resources2))
}
@Test
fun contains_someOfSomeTypes() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 2, CLAY to 4)
+ val resources2 = resourcesOf(CLAY to 3)
assertTrue(resources.containsAll(resources2))
}
@Test
fun contains_allOfSomeTypes() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.CLAY, 4)
+ val resources = resourcesOf(STONE to 2, CLAY to 4)
+ val resources2 = resourcesOf(CLAY to 4)
assertTrue(resources.containsAll(resources2))
}
@Test
fun minus_empty() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
-
- val emptyResources = Resources()
+ val resources = resourcesOf(STONE to 1, CLAY to 3)
+ val emptyResources = emptyResources()
val diff = resources.minus(emptyResources)
- assertEquals(1, diff.getQuantity(ResourceType.STONE).toLong())
- assertEquals(3, diff.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(1, diff[STONE])
+ assertEquals(3, diff[CLAY])
+ assertEquals(0, diff[ORE])
+ assertEquals(0, diff[GLASS])
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_self() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 1, CLAY to 3)
val diff = resources.minus(resources)
- assertEquals(0, diff.getQuantity(ResourceType.STONE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(0, diff[STONE])
+ assertEquals(0, diff[CLAY])
+ assertEquals(0, diff[ORE])
+ assertEquals(0, diff[GLASS])
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_allOfEachType() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 1)
- resources.add(ResourceType.CLAY, 3)
-
- val resources2 = Resources()
- resources2.add(ResourceType.STONE, 1)
- resources2.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 1, CLAY to 3)
+ val resources2 = resourcesOf(STONE to 1, CLAY to 3)
val diff = resources.minus(resources2)
- assertEquals(0, diff.getQuantity(ResourceType.STONE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(0, diff[STONE])
+ assertEquals(0, diff[CLAY])
+ assertEquals(0, diff[ORE])
+ assertEquals(0, diff[GLASS])
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_someOfEachType() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.STONE, 1)
- resources2.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 2, CLAY to 4)
+ val resources2 = resourcesOf(STONE to 1, CLAY to 3)
val diff = resources.minus(resources2)
- assertEquals(1, diff.getQuantity(ResourceType.STONE).toLong())
- assertEquals(1, diff.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(1, diff[STONE])
+ assertEquals(1, diff[CLAY])
+ assertEquals(0, diff[ORE])
+ assertEquals(0, diff[GLASS])
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_someOfSomeTypes() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.CLAY, 3)
+ val resources = resourcesOf(STONE to 2, CLAY to 4)
+ val resources2 = resourcesOf(CLAY to 3)
val diff = resources.minus(resources2)
- assertEquals(2, diff.getQuantity(ResourceType.STONE).toLong())
- assertEquals(1, diff.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(2, diff[STONE])
+ assertEquals(1, diff[CLAY])
+ assertEquals(0, diff[ORE])
+ assertEquals(0, diff[GLASS])
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_allOfSomeTypes() {
- val resources = Resources()
- resources.add(ResourceType.STONE, 2)
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.CLAY, 4)
+ val resources = resourcesOf(STONE to 2, CLAY to 4)
+ val resources2 = resourcesOf(CLAY to 4)
val diff = resources.minus(resources2)
- assertEquals(2, diff.getQuantity(ResourceType.STONE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.ORE).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.GLASS).toLong())
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(2, diff[STONE])
+ assertEquals(0, diff[CLAY])
+ assertEquals(0, diff[ORE])
+ assertEquals(0, diff[GLASS])
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_tooMuchOfExistingType() {
- val resources = Resources()
- resources.add(ResourceType.CLAY, 4)
-
- val resources2 = Resources()
- resources2.add(ResourceType.CLAY, 5)
+ val resources = resourcesOf(CLAY to 4)
+ val resources2 = resourcesOf(CLAY to 5)
val diff = resources.minus(resources2)
- assertEquals(0, diff.getQuantity(ResourceType.CLAY).toLong())
+ assertEquals(0, diff[CLAY])
}
@Test
fun minus_someOfAnAbsentType() {
- val resources = Resources()
-
- val resources2 = Resources()
- resources2.add(ResourceType.LOOM, 5)
+ val resources = emptyResources()
+ val resources2 = resourcesOf(LOOM to 5)
val diff = resources.minus(resources2)
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(0, diff[LOOM])
}
@Test
fun minus_someOfATypeWithZero() {
- val resources = Resources()
- resources.add(ResourceType.LOOM, 0)
-
- val resources2 = Resources()
- resources2.add(ResourceType.LOOM, 5)
+ val resources = resourcesOf(LOOM to 0)
+ val resources2 = resourcesOf(LOOM to 5)
val diff = resources.minus(resources2)
- assertEquals(0, diff.getQuantity(ResourceType.LOOM).toLong())
+ assertEquals(0, diff[LOOM])
}
@Test
fun isEmpty_noElement() {
- val resources = Resources()
- assertTrue(resources.isEmpty)
+ val resources = emptyResources()
+ assertTrue(resources.isEmpty())
}
@Test
fun isEmpty_singleZeroElement() {
- val resources = Resources()
- resources.add(ResourceType.LOOM, 0)
- assertTrue(resources.isEmpty)
+ val resources = resourcesOf(LOOM to 0)
+ assertTrue(resources.isEmpty())
}
@Test
fun isEmpty_multipleZeroElements() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 0)
- resources.add(ResourceType.ORE, 0)
- resources.add(ResourceType.LOOM, 0)
- assertTrue(resources.isEmpty)
+ val resources = resourcesOf(WOOD to 0, ORE to 0, LOOM to 0)
+ assertTrue(resources.isEmpty())
}
@Test
fun isEmpty_singleElementMoreThanZero() {
- val resources = Resources()
- resources.add(ResourceType.LOOM, 3)
- assertFalse(resources.isEmpty)
+ val resources = resourcesOf(LOOM to 3)
+ assertFalse(resources.isEmpty())
}
@Test
fun isEmpty_mixedZeroAndNonZeroElements() {
- val resources = Resources()
- resources.add(ResourceType.WOOD, 0)
- resources.add(ResourceType.LOOM, 3)
- assertFalse(resources.isEmpty)
+ val resources = resourcesOf(WOOD to 0, LOOM to 3)
+ assertFalse(resources.isEmpty())
}
@Test
fun isEmpty_mixedZeroAndNonZeroElements_reverseOrder() {
- val resources = Resources()
- resources.add(ResourceType.ORE, 3)
- resources.add(ResourceType.PAPYRUS, 0)
- assertFalse(resources.isEmpty)
- }
-
- @Test
- fun equals_falseWhenNull() {
- val resources = Resources()
- resources.add(ResourceType.GLASS, 1)
-
- assertFalse(resources == null)
+ val resources = resourcesOf(ORE to 3, PAPYRUS to 0)
+ assertFalse(resources.isEmpty())
}
@Test
fun equals_trueWhenSame() {
- val resources = Resources()
+ val resources = emptyResources()
assertEquals(resources, resources)
}
@Test
fun equals_trueWhenSameContent() {
- val resources1 = Resources()
- val resources2 = Resources()
+ val resources1 = mutableResourcesOf()
+ val resources2 = mutableResourcesOf()
assertTrue(resources1 == resources2)
- resources1.add(ResourceType.GLASS, 1)
- resources2.add(ResourceType.GLASS, 1)
+ resources1.add(GLASS, 1)
+ resources2.add(GLASS, 1)
assertTrue(resources1 == resources2)
}
@Test
fun hashCode_sameWhenSameContent() {
- val resources1 = Resources()
- val resources2 = Resources()
- assertEquals(resources1.hashCode().toLong(), resources2.hashCode().toLong())
- resources1.add(ResourceType.GLASS, 1)
- resources2.add(ResourceType.GLASS, 1)
- assertEquals(resources1.hashCode().toLong(), resources2.hashCode().toLong())
+ val resources1 = mutableResourcesOf()
+ val resources2 = mutableResourcesOf()
+ assertEquals(resources1.hashCode(), resources2.hashCode())
+ resources1.add(GLASS, 1)
+ resources2.add(GLASS, 1)
+ assertEquals(resources1.hashCode(), resources2.hashCode())
}
}
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt
index 859c997a..ac3f72de 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/resources/TradingRulesTest.kt
@@ -1,15 +1,14 @@
package org.luxons.sevenwonders.game.resources
-import java.util.ArrayList
-
+import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeTrue
import org.junit.experimental.theories.DataPoints
import org.junit.experimental.theories.Theories
import org.junit.experimental.theories.Theory
import org.junit.runner.RunWith
-import org.luxons.sevenwonders.game.test.*
-
-import org.junit.Assert.assertEquals
-import org.junit.Assume.assumeTrue
+import org.luxons.sevenwonders.game.test.createTransaction
+import org.luxons.sevenwonders.game.test.createTransactions
+import java.util.ArrayList
@RunWith(Theories::class)
class TradingRulesTest {
@@ -32,7 +31,7 @@ class TradingRulesTest {
@Theory
fun computeCost_zeroForNoResources(defaultCost: Int) {
val rules = TradingRules(defaultCost)
- assertEquals(0, rules.computeCost(ResourceTransactions()).toLong())
+ assertEquals(0, rules.computeCost(noTransactions()).toLong())
}
@Theory
@@ -59,9 +58,11 @@ class TradingRulesTest {
@Theory
fun computeCost_defaultCostWhenOverrideOnOtherProviderOrType(
- defaultCost: Int, overriddenCost: Int,
+ defaultCost: Int,
+ overriddenCost: Int,
overriddenProvider: Provider,
- overriddenType: ResourceType, provider: Provider,
+ overriddenType: ResourceType,
+ provider: Provider,
type: ResourceType
) {
assumeTrue(overriddenProvider != provider || overriddenType != type)
@@ -73,8 +74,10 @@ class TradingRulesTest {
@Theory
fun computeCost_oneDefaultAndOneOverriddenType(
- defaultCost: Int, overriddenCost: Int,
- overriddenType: ResourceType, provider: Provider,
+ defaultCost: Int,
+ overriddenCost: Int,
+ overriddenType: ResourceType,
+ provider: Provider,
type: ResourceType
) {
assumeTrue(overriddenType != type)
@@ -86,8 +89,10 @@ class TradingRulesTest {
@Theory
fun computeCost_oneDefaultAndOneOverriddenProvider(
- defaultCost: Int, overriddenCost: Int,
- overriddenProvider: Provider, provider: Provider,
+ defaultCost: Int,
+ overriddenCost: Int,
+ overriddenProvider: Provider,
+ provider: Provider,
type: ResourceType
) {
assumeTrue(overriddenProvider != provider)
@@ -98,10 +103,7 @@ class TradingRulesTest {
boughtResources.add(createTransaction(provider, type))
boughtResources.add(createTransaction(overriddenProvider, type))
- assertEquals(
- (defaultCost + overriddenCost).toLong(),
- rules.computeCost(ResourceTransactions(boughtResources)).toLong()
- )
+ assertEquals(defaultCost + overriddenCost, rules.computeCost(boughtResources))
}
companion object {
diff --git a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/test/TestUtils.kt b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/test/TestUtils.kt
index bf718d32..1a360a77 100644
--- a/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/test/TestUtils.kt
+++ b/game-engine/src/test/kotlin/org/luxons/sevenwonders/game/test/TestUtils.kt
@@ -24,6 +24,8 @@ import org.luxons.sevenwonders.game.resources.ResourceTransaction
import org.luxons.sevenwonders.game.resources.ResourceTransactions
import org.luxons.sevenwonders.game.resources.ResourceType
import org.luxons.sevenwonders.game.resources.Resources
+import org.luxons.sevenwonders.game.resources.noTransactions
+import org.luxons.sevenwonders.game.resources.resourcesOf
import org.luxons.sevenwonders.game.wonders.Wonder
import org.luxons.sevenwonders.game.wonders.WonderStage
import java.util.Arrays
@@ -90,34 +92,29 @@ private fun createWonderStage(vararg effects: Effect): WonderStage {
fun fixedProduction(vararg producedTypes: ResourceType): Production {
val production = Production()
- val fixedProducedResources = production.fixedResources
- fixedProducedResources.addAll(createResources(*producedTypes))
+ production.addAll(resourcesOf(*producedTypes))
return production
}
-fun createResources(vararg types: ResourceType): Resources {
- val resources = Resources()
- for (producedType in types) {
- resources.add(producedType, 1)
- }
- return resources
+infix fun Int.of(type: ResourceType): Resources {
+ return resourcesOf(type to this)
}
internal fun createTransactions(provider: Provider, vararg resources: ResourceType): ResourceTransactions {
val transaction = createTransaction(provider, *resources)
- return ResourceTransactions(listOf(transaction))
+ return listOf(transaction)
}
internal fun createTransactions(vararg transactions: ResourceTransaction): ResourceTransactions {
- return ResourceTransactions(Arrays.asList(*transactions))
+ return transactions.toList()
}
fun createTransaction(provider: Provider, vararg resources: ResourceType): ResourceTransaction {
- return ResourceTransaction(provider, createResources(*resources))
+ return ResourceTransaction(provider, resourcesOf(*resources))
}
fun createRequirements(vararg types: ResourceType): Requirements {
- val resources = createResources(*types)
+ val resources = resourcesOf(*types)
return Requirements(resources = resources)
}
@@ -209,7 +206,7 @@ fun createScience(compasses: Int, wheels: Int, tablets: Int, jokers: Int): Scien
internal fun playCardWithEffect(player: Player, color: Color, effect: Effect) {
val card = testCard(color, effect)
player.board.addCard(card)
- card.applyTo(player, ResourceTransactions())
+ card.applyTo(player, noTransactions())
}
internal fun createMove(context: PlayerContext, card: Card, type: MoveType, vararg transactions: ResourceTransaction): Move {
bgstack15