diff options
29 files changed, 925 insertions, 1227 deletions
diff --git a/sw-engine/build.gradle.kts b/sw-engine/build.gradle.kts index e39d7fd2..ca2d6fec 100644 --- a/sw-engine/build.gradle.kts +++ b/sw-engine/build.gradle.kts @@ -1,10 +1,11 @@ plugins { kotlin("jvm") + kotlin("plugin.serialization") } dependencies { implementation(project(":sw-common-model")) - implementation("com.github.salomonbrys.kotson:kotson:2.5.0") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1") testImplementation(kotlin("test")) testImplementation(kotlin("test-junit")) } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/cards/Requirements.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/cards/Requirements.kt index b78a5057..1d03aa76 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/cards/Requirements.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/cards/Requirements.kt @@ -1,11 +1,13 @@ package org.luxons.sevenwonders.engine.cards +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.Player import org.luxons.sevenwonders.engine.boards.Board import org.luxons.sevenwonders.engine.resources.* import org.luxons.sevenwonders.model.resources.ResourceTransactions import org.luxons.sevenwonders.model.resources.bestPrice +@Serializable data class Requirements internal constructor( val gold: Int = 0, val resources: Resources = emptyResources(), diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/GameDefinition.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/GameDefinition.kt index 07c101e6..64d6be3b 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/GameDefinition.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/GameDefinition.kt @@ -1,34 +1,20 @@ package org.luxons.sevenwonders.engine.data -import com.github.salomonbrys.kotson.typeToken -import com.google.gson.Gson -import com.google.gson.GsonBuilder +import kotlinx.serialization.Serializable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json import org.luxons.sevenwonders.engine.Game import org.luxons.sevenwonders.engine.boards.Board import org.luxons.sevenwonders.engine.data.definitions.DecksDefinition import org.luxons.sevenwonders.engine.data.definitions.WonderDefinition -import org.luxons.sevenwonders.engine.data.serializers.NumericEffectSerializer -import org.luxons.sevenwonders.engine.data.serializers.ProductionIncreaseSerializer -import org.luxons.sevenwonders.engine.data.serializers.ProductionSerializer -import org.luxons.sevenwonders.engine.data.serializers.ResourceTypeSerializer -import org.luxons.sevenwonders.engine.data.serializers.ResourceTypesSerializer -import org.luxons.sevenwonders.engine.data.serializers.ResourcesSerializer -import org.luxons.sevenwonders.engine.data.serializers.ScienceProgressSerializer -import org.luxons.sevenwonders.engine.effects.GoldIncrease -import org.luxons.sevenwonders.engine.effects.MilitaryReinforcements -import org.luxons.sevenwonders.engine.effects.ProductionIncrease -import org.luxons.sevenwonders.engine.effects.RawPointsIncrease -import org.luxons.sevenwonders.engine.effects.ScienceProgress -import org.luxons.sevenwonders.engine.resources.Production -import org.luxons.sevenwonders.engine.resources.Resources import org.luxons.sevenwonders.model.Age import org.luxons.sevenwonders.model.Settings -import org.luxons.sevenwonders.model.resources.ResourceType import org.luxons.sevenwonders.model.wonders.AssignedWonder import org.luxons.sevenwonders.model.wonders.PreGameWonder internal const val LAST_AGE: Age = 3 +@Serializable internal data class GlobalRules( val minPlayers: Int, val maxPlayers: Int, @@ -63,36 +49,18 @@ class GameDefinition internal constructor( companion object { fun load(): GameDefinition { - val gson: Gson = createGson() - val rules = loadJson("global_rules.json", GlobalRules::class.java, gson) - val wonders = loadJson("wonders.json", Array<WonderDefinition>::class.java, gson) - val decksDefinition = loadJson("cards.json", DecksDefinition::class.java, gson) + val rules = loadJson<GlobalRules>("global_rules.json") + val wonders = loadJson<Array<WonderDefinition>>("wonders.json") + val decksDefinition = loadJson<DecksDefinition>("cards.json") return GameDefinition(rules, wonders.toList(), decksDefinition) } } } -private fun <T> loadJson(filename: String, clazz: Class<T>, gson: Gson): T { +private inline fun <reified T> loadJson(filename: String): T { val packageAsPath = GameDefinition::class.java.`package`.name.replace('.', '/') val resourcePath = "/$packageAsPath/$filename" val resource = GameDefinition::class.java.getResource(resourcePath) val json = resource.readText() - return gson.fromJson(json, clazz) + return Json.decodeFromString(json) } - -private fun createGson(): Gson { - return GsonBuilder().disableHtmlEscaping() - .registerTypeAdapter<Resources>(ResourcesSerializer()) - .registerTypeAdapter<ResourceType>(ResourceTypeSerializer()) - .registerTypeAdapter<List<ResourceType>>(ResourceTypesSerializer()) - .registerTypeAdapter<Production>(ProductionSerializer()) - .registerTypeAdapter<ProductionIncrease>(ProductionIncreaseSerializer()) - .registerTypeAdapter<MilitaryReinforcements>(NumericEffectSerializer()) - .registerTypeAdapter<RawPointsIncrease>(NumericEffectSerializer()) - .registerTypeAdapter<GoldIncrease>(NumericEffectSerializer()) - .registerTypeAdapter<ScienceProgress>(ScienceProgressSerializer()) - .create() -} - -private inline fun <reified T : Any> GsonBuilder.registerTypeAdapter(typeAdapter: Any): GsonBuilder = - this.registerTypeAdapter(typeToken<T>(), typeAdapter) diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/CardDefinition.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/CardDefinition.kt index cc42641a..0b9fbb7d 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/CardDefinition.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/CardDefinition.kt @@ -1,21 +1,23 @@ package org.luxons.sevenwonders.engine.data.definitions +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.cards.Card import org.luxons.sevenwonders.engine.cards.Requirements import org.luxons.sevenwonders.model.cards.CardBack import org.luxons.sevenwonders.model.cards.Color +@Serializable internal class CardDefinition( private val name: String, private val color: Color, - private val requirements: Requirements?, private val effect: EffectsDefinition, - private val chainParent: String?, - private val chainChildren: List<String>?, + private val requirements: Requirements? = null, + private val chainParent: String? = null, + private val chainChildren: List<String>? = null, + private val countPerNbPlayer: Map<Int, Int>? = null, private val image: String, - private val countPerNbPlayer: Map<Int, Int>, ) { - fun create(back: CardBack, nbPlayers: Int): List<Card> = List(countPerNbPlayer[nbPlayers] ?: 0) { create(back) } + fun create(back: CardBack, nbPlayers: Int): List<Card> = List(countPerNbPlayer!![nbPlayers] ?: 0) { create(back) } fun create(back: CardBack): Card { val reqs = requirements ?: Requirements() diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/DecksDefinition.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/DecksDefinition.kt index f3dc42f4..ed2b1214 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/DecksDefinition.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/DecksDefinition.kt @@ -1,17 +1,20 @@ package org.luxons.sevenwonders.engine.data.definitions +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.cards.Card import org.luxons.sevenwonders.engine.cards.Decks import org.luxons.sevenwonders.model.cards.CardBack import kotlin.random.Random +@Serializable internal class DeckDefinition( val cards: List<CardDefinition>, val backImage: String, ) { - fun create(nbPlayers: Int): List<Card> = cards.flatMap { it.create(CardBack(backImage), nbPlayers) } + fun prepareFor(nbPlayers: Int): List<Card> = cards.flatMap { it.create(CardBack(backImage), nbPlayers) } } +@Serializable internal class DecksDefinition( private val age1: DeckDefinition, private val age2: DeckDefinition, @@ -20,9 +23,9 @@ internal class DecksDefinition( ) { fun prepareDecks(nbPlayers: Int, random: Random) = Decks( mapOf( - 1 to age1.create(nbPlayers).shuffled(random), - 2 to age2.create(nbPlayers).shuffled(random), - 3 to (age3.create(nbPlayers) + pickGuildCards(nbPlayers, random)).shuffled(random), + 1 to age1.prepareFor(nbPlayers).shuffled(random), + 2 to age2.prepareFor(nbPlayers).shuffled(random), + 3 to (age3.prepareFor(nbPlayers) + pickGuildCards(nbPlayers, random)).shuffled(random), ), ) diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/EffectsDefinition.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/EffectsDefinition.kt index 86829eca..efd92c90 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/EffectsDefinition.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/EffectsDefinition.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.engine.data.definitions +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.effects.BonusPerBoardElement import org.luxons.sevenwonders.engine.effects.Discount import org.luxons.sevenwonders.engine.effects.Effect @@ -11,24 +12,25 @@ import org.luxons.sevenwonders.engine.effects.ScienceProgress import org.luxons.sevenwonders.engine.effects.SpecialAbility import org.luxons.sevenwonders.engine.effects.SpecialAbilityActivation +@Serializable internal class EffectsDefinition( - private val gold: GoldIncrease? = null, - private val military: MilitaryReinforcements? = null, + private val gold: Int? = null, + private val military: Int? = null, private val science: ScienceProgress? = null, private val discount: Discount? = null, private val perBoardElement: BonusPerBoardElement? = null, private val production: ProductionIncrease? = null, - private val points: RawPointsIncrease? = null, + private val points: Int? = null, private val action: SpecialAbility? = null, ) { fun create(): List<Effect> = mutableListOf<Effect>().apply { - gold?.let { add(it) } - military?.let { add(it) } + gold?.let { add(GoldIncrease(it)) } + military?.let { add(MilitaryReinforcements(it)) } science?.let { add(it) } discount?.let { add(it) } perBoardElement?.let { add(it) } production?.let { add(it) } - points?.let { add(it) } + points?.let { add(RawPointsIncrease(it)) } action?.let { add(SpecialAbilityActivation(it)) } } } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/WonderDefinition.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/WonderDefinition.kt index 2a59f6dc..3d9956bc 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/WonderDefinition.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/definitions/WonderDefinition.kt @@ -1,12 +1,15 @@ package org.luxons.sevenwonders.engine.data.definitions +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.cards.Requirements +import org.luxons.sevenwonders.engine.data.serializers.ResourceTypeSerializer import org.luxons.sevenwonders.engine.wonders.Wonder import org.luxons.sevenwonders.engine.wonders.WonderStage import org.luxons.sevenwonders.model.resources.ResourceType import org.luxons.sevenwonders.model.wonders.WonderName import org.luxons.sevenwonders.model.wonders.WonderSide +@Serializable internal class WonderDefinition( val name: WonderName, val sides: Map<WonderSide, WonderSideDefinition>, @@ -14,7 +17,9 @@ internal class WonderDefinition( fun create(wonderSide: WonderSide): Wonder = sides[wonderSide]!!.createWonder(name) } +@Serializable internal class WonderSideDefinition( + @Serializable(with = ResourceTypeSerializer::class) private val initialResource: ResourceType, private val stages: List<WonderStageDefinition>, val image: String, @@ -22,6 +27,7 @@ internal class WonderSideDefinition( fun createWonder(name: String): Wonder = Wonder(name, initialResource, stages.map { it.create() }, image) } +@Serializable internal class WonderStageDefinition( private val requirements: Requirements, private val effects: EffectsDefinition, diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/NumericEffectSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/NumericEffectSerializer.kt deleted file mode 100644 index a149e8a0..00000000 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/NumericEffectSerializer.kt +++ /dev/null @@ -1,38 +0,0 @@ -package org.luxons.sevenwonders.engine.data.serializers - -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonParseException -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer -import org.luxons.sevenwonders.engine.effects.Effect -import org.luxons.sevenwonders.engine.effects.GoldIncrease -import org.luxons.sevenwonders.engine.effects.MilitaryReinforcements -import org.luxons.sevenwonders.engine.effects.RawPointsIncrease -import java.lang.reflect.Type - -internal class NumericEffectSerializer : JsonSerializer<Effect>, JsonDeserializer<Effect> { - - override fun serialize(effect: Effect, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - val value: Int = when (effect) { - is MilitaryReinforcements -> effect.count - is GoldIncrease -> effect.amount - is RawPointsIncrease -> effect.points - else -> throw IllegalArgumentException("Unknown numeric effect " + effect.javaClass.name) - } - return JsonPrimitive(value) - } - - @Throws(JsonParseException::class) - override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Effect { - val value = json.asInt - return when (typeOfT) { - MilitaryReinforcements::class.java -> MilitaryReinforcements(value) - GoldIncrease::class.java -> GoldIncrease(value) - RawPointsIncrease::class.java -> RawPointsIncrease(value) - else -> throw IllegalArgumentException("Unknown numeric effet " + typeOfT.typeName) - } - } -} diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionIncreaseSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionIncreaseSerializer.kt deleted file mode 100644 index dc340578..00000000 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionIncreaseSerializer.kt +++ /dev/null @@ -1,47 +0,0 @@ -package org.luxons.sevenwonders.engine.data.serializers - -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonParseException -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer -import org.luxons.sevenwonders.engine.effects.ProductionIncrease -import org.luxons.sevenwonders.engine.resources.Production -import java.lang.reflect.Type - -internal class ProductionIncreaseSerializer : JsonSerializer<ProductionIncrease>, JsonDeserializer<ProductionIncrease> { - - override fun serialize( - productionIncrease: ProductionIncrease, - typeOfSrc: Type, - context: JsonSerializationContext, - ): JsonElement { - val production = productionIncrease.production - val json = context.serialize(production) - return if (!json.isJsonNull && !productionIncrease.isSellable) JsonPrimitive("(${json.asString})") else json - } - - @Throws(JsonParseException::class) - override fun deserialize( - json: JsonElement, - typeOfT: Type, - context: JsonDeserializationContext, - ): ProductionIncrease { - var prodJson = json - - var resourcesStr = prodJson.asString - val isSellable = !resourcesStr.startsWith("(") - if (!isSellable) { - resourcesStr = unwrapBrackets(resourcesStr) - prodJson = JsonPrimitive(resourcesStr) - } - val production = context.deserialize<Production>(prodJson, Production::class.java) - return ProductionIncrease(production, isSellable) - } - - private fun unwrapBrackets(str: String): String { - return str.substring(1, str.length - 1) - } -} diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt index c98f20a8..48efaedb 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializer.kt @@ -1,53 +1,47 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonNull -import com.google.gson.JsonParseException -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import org.luxons.sevenwonders.engine.resources.Production -import org.luxons.sevenwonders.engine.resources.Resources import org.luxons.sevenwonders.model.resources.ResourceType -import java.lang.reflect.Type -internal class ProductionSerializer : JsonSerializer<Production>, JsonDeserializer<Production> { +internal object ProductionSerializer : KSerializer<Production> { - override fun serialize(production: Production, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - val fixedResources = production.getFixedResources() - val choices = production.getAlternativeResources() - return when { - fixedResources.isEmpty() -> serializeAsChoice(choices, context) - choices.isEmpty() -> serializeAsResources(fixedResources, context) + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Production", PrimitiveKind.STRING) + + @OptIn(ExperimentalSerializationApi::class) + override fun serialize(encoder: Encoder, value: Production) { + val fixedResources = value.getFixedResources() + val choices = value.getAlternativeResources() + when { + fixedResources.isEmpty() -> choices.toChoiceString()?.let { encoder.encodeString(it) } ?: encoder.encodeNull() + choices.isEmpty() -> encoder.encodeSerializableValue(ResourcesSerializer, fixedResources) else -> throw IllegalArgumentException("Cannot serialize a production with mixed fixed resources and choices") } } - private fun serializeAsChoice(choices: List<Set<ResourceType>>, context: JsonSerializationContext): JsonElement { - if (choices.isEmpty()) { - return JsonNull.INSTANCE + private fun List<Set<ResourceType>>.toChoiceString(): String? { + if (isEmpty()) { + return null } - if (choices.size > 1) { + if (size > 1) { throw IllegalArgumentException("Cannot serialize a production with more than one choice") } - val str = choices[0].map { it.symbol }.joinToString("/") - return context.serialize(str) - } - - private fun serializeAsResources(fixedResources: Resources, context: JsonSerializationContext): JsonElement { - return context.serialize(fixedResources) + return this[0].map { it.symbol }.joinToString("/") } - @Throws(JsonParseException::class) - override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Production { - val resourcesStr = json.asString + override fun deserialize(decoder: Decoder): Production { + val resourcesStr = decoder.decodeString() val production = Production() if (resourcesStr.contains("/")) { production.addChoice(*createChoice(resourcesStr)) } else { - val fixedResources = context.deserialize<Resources>(json, Resources::class.java) - production.addAll(fixedResources) + production.addAll(ResourcesSerializer.deserializeString(resourcesStr)) } return production } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializer.kt index b308fd24..ccbb9560 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializer.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializer.kt @@ -1,26 +1,20 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonParseException -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import org.luxons.sevenwonders.model.resources.ResourceType -import java.lang.reflect.Type -internal class ResourceTypeSerializer : JsonSerializer<ResourceType>, JsonDeserializer<ResourceType> { +internal object ResourceTypeSerializer : KSerializer<ResourceType> { - override fun serialize(type: ResourceType, typeOfSrc: Type, context: JsonSerializationContext): JsonElement = - JsonPrimitive(type.symbol) + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ResourceType", PrimitiveKind.STRING) - @Throws(JsonParseException::class) - override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ResourceType { - val str = json.asString - if (str.isEmpty()) { - throw IllegalArgumentException("Empty string is not a valid resource level") - } - return ResourceType.fromSymbol(str[0]) + override fun serialize(encoder: Encoder, value: ResourceType) { + encoder.encodeString(value.symbol.toString()) } + + override fun deserialize(decoder: Decoder): ResourceType = ResourceType.fromSymbol(decoder.decodeString()) } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializer.kt index ebbee8fd..8bd35f52 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializer.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializer.kt @@ -1,30 +1,21 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonParseException -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import org.luxons.sevenwonders.model.resources.ResourceType -import java.lang.reflect.Type -internal class ResourceTypesSerializer : JsonSerializer<List<ResourceType>>, JsonDeserializer<List<ResourceType>> { +internal object ResourceTypesSerializer : KSerializer<List<ResourceType>> { - override fun serialize( - resources: List<ResourceType>, - typeOfSrc: Type, - context: JsonSerializationContext, - ): JsonElement { - val s = resources.map { it.symbol }.joinToString("") - return JsonPrimitive(s) + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ResourceTypeList", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: List<ResourceType>) { + encoder.encodeString(value.map { it.symbol }.joinToString("")) } - @Throws(JsonParseException::class) - override fun deserialize( - json: JsonElement, - typeOfT: Type, - context: JsonDeserializationContext, - ): List<ResourceType> = json.asString.map { ResourceType.fromSymbol(it) } + override fun deserialize(decoder: Decoder): List<ResourceType> = + decoder.decodeString().map { ResourceType.fromSymbol(it) } } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializer.kt index 4226411d..cf31c380 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializer.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializer.kt @@ -1,26 +1,27 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonNull -import com.google.gson.JsonParseException -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import org.luxons.sevenwonders.engine.resources.Resources import org.luxons.sevenwonders.engine.resources.toResources import org.luxons.sevenwonders.model.resources.ResourceType -import java.lang.reflect.Type -internal class ResourcesSerializer : JsonSerializer<Resources>, JsonDeserializer<Resources> { +internal object ResourcesSerializer : KSerializer<Resources> { - override fun serialize(resources: Resources, typeOfSrc: Type, context: JsonSerializationContext): JsonElement { - val s = resources.toList().map { it.symbol }.joinToString("") - return if (s.isEmpty()) JsonNull.INSTANCE else JsonPrimitive(s) + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Resources", PrimitiveKind.STRING) + + @OptIn(ExperimentalSerializationApi::class) + override fun serialize(encoder: Encoder, value: Resources) { + val s = value.toList().map { it.symbol }.joinToString("") + if (s.isEmpty()) encoder.encodeNull() else encoder.encodeString(s) } - @Throws(JsonParseException::class) - override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Resources = - json.asString.map { ResourceType.fromSymbol(it) to 1 }.toResources() + override fun deserialize(decoder: Decoder): Resources = deserializeString(decoder.decodeString()) + + fun deserializeString(symbols: String): Resources = symbols.map { ResourceType.fromSymbol(it) to 1 }.toResources() } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializer.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializer.kt index 1193c94b..b4493c70 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializer.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializer.kt @@ -1,55 +1,48 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer -import com.google.gson.JsonElement -import com.google.gson.JsonNull -import com.google.gson.JsonParseException -import com.google.gson.JsonPrimitive -import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.serializer import org.luxons.sevenwonders.engine.boards.Science import org.luxons.sevenwonders.engine.boards.ScienceType import org.luxons.sevenwonders.engine.effects.ScienceProgress -import java.lang.reflect.Type -internal class ScienceProgressSerializer : JsonSerializer<ScienceProgress>, JsonDeserializer<ScienceProgress> { +internal object ScienceProgressSerializer : KSerializer<ScienceProgress> { - override fun serialize( - scienceProgress: ScienceProgress, - typeOfSrc: Type, - context: JsonSerializationContext, - ): JsonElement { - val science = scienceProgress.science + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ScienceProgress", PrimitiveKind.STRING) - if (science.size() > 1) { + @OptIn(ExperimentalSerializationApi::class) + override fun serialize(encoder: Encoder, value: ScienceProgress) { + if (value.science.size() > 1) { throw UnsupportedOperationException("Cannot serialize science containing more than one element") } - + if (value.science.jokers == 1) { + encoder.encodeString("any") + return + } for (type in ScienceType.values()) { - val quantity = science.getQuantity(type) + val quantity = value.science.getQuantity(type) if (quantity == 1) { - return context.serialize(type) + encoder.encodeSerializableValue(serializer(), type) + return } } - - return if (science.jokers == 1) JsonPrimitive("any") else JsonNull.INSTANCE + encoder.encodeNull() } - @Throws(JsonParseException::class) - override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ScienceProgress { - val s = json.asString + override fun deserialize(decoder: Decoder): ScienceProgress { + val s = decoder.decodeString() val science = Science() if ("any" == s) { science.addJoker(1) } else { - science.add(deserializeScienceType(json, context), 1) + science.add(ScienceType.valueOf(s), 1) } return ScienceProgress(science) } - - private fun deserializeScienceType(json: JsonElement, context: JsonDeserializationContext): ScienceType { - return context.deserialize<ScienceType>(json, ScienceType::class.java) - ?: throw IllegalArgumentException("Invalid science level " + json.asString) - } } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/BonusPerBoardElement.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/BonusPerBoardElement.kt index 41dbd937..6f1cee51 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/BonusPerBoardElement.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/BonusPerBoardElement.kt @@ -1,5 +1,6 @@ package org.luxons.sevenwonders.engine.effects +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.Player import org.luxons.sevenwonders.engine.boards.Board import org.luxons.sevenwonders.model.boards.RelativeBoardPosition @@ -11,6 +12,7 @@ enum class BoardElementType { DEFEAT_TOKEN, } +@Serializable internal data class BonusPerBoardElement( val boards: List<RelativeBoardPosition>, val type: BoardElementType, diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/Discount.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/Discount.kt index 83a45e28..f74f79c8 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/Discount.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/Discount.kt @@ -1,10 +1,14 @@ package org.luxons.sevenwonders.engine.effects +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.boards.Board +import org.luxons.sevenwonders.engine.data.serializers.ResourceTypesSerializer import org.luxons.sevenwonders.model.resources.Provider import org.luxons.sevenwonders.model.resources.ResourceType +@Serializable internal data class Discount( + @Serializable(with = ResourceTypesSerializer::class) val resourceTypes: List<ResourceType> = emptyList(), val providers: List<Provider> = emptyList(), val discountedPrice: Int = 1, diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ProductionIncrease.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ProductionIncrease.kt index 6458ad20..006d7516 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ProductionIncrease.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ProductionIncrease.kt @@ -1,14 +1,19 @@ package org.luxons.sevenwonders.engine.effects +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.boards.Board import org.luxons.sevenwonders.engine.resources.Production -internal data class ProductionIncrease(val production: Production, val isSellable: Boolean) : InstantOwnBoardEffect() { +@Serializable +internal data class ProductionIncrease( + val resources: Production, + val isSellable: Boolean +) : InstantOwnBoardEffect() { public override fun applyTo(board: Board) { - board.production.addAll(production) + board.production.addAll(resources) if (isSellable) { - board.publicProduction.addAll(production) + board.publicProduction.addAll(resources) } } } diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ScienceProgress.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ScienceProgress.kt index 4ea8626f..50a670bb 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ScienceProgress.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/effects/ScienceProgress.kt @@ -1,8 +1,11 @@ package org.luxons.sevenwonders.engine.effects +import kotlinx.serialization.Serializable import org.luxons.sevenwonders.engine.boards.Board import org.luxons.sevenwonders.engine.boards.Science +import org.luxons.sevenwonders.engine.data.serializers.ScienceProgressSerializer +@Serializable(with = ScienceProgressSerializer::class) internal class ScienceProgress(val science: Science) : InstantOwnBoardEffect() { public override fun applyTo(board: Board) = board.science.addAll(science) diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt index 3eb59bd5..ad11faab 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Production.kt @@ -1,8 +1,11 @@ package org.luxons.sevenwonders.engine.resources +import kotlinx.serialization.Serializable +import org.luxons.sevenwonders.engine.data.serializers.ProductionSerializer import org.luxons.sevenwonders.model.resources.ResourceType import java.util.EnumSet +@Serializable(with = ProductionSerializer::class) data class Production internal constructor( private val fixedResources: MutableResources = mutableResourcesOf(), // cannot be a Set because the same choices can be there multiple times diff --git a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Resources.kt b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Resources.kt index b2dfc964..53556a3d 100644 --- a/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Resources.kt +++ b/sw-engine/src/main/kotlin/org/luxons/sevenwonders/engine/resources/Resources.kt @@ -1,5 +1,7 @@ package org.luxons.sevenwonders.engine.resources +import kotlinx.serialization.Serializable +import org.luxons.sevenwonders.engine.data.serializers.ResourcesSerializer import org.luxons.sevenwonders.model.resources.ResourceType fun emptyResources(): Resources = MutableResources() @@ -34,6 +36,7 @@ internal fun Map<ResourceType, Int>.toMutableResources(): MutableResources = Mut internal fun Resources.toMutableResources(): MutableResources = quantities.toMutableResources() +@Serializable(with = ResourcesSerializer::class) interface Resources { val quantities: Map<ResourceType, Int> diff --git a/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/cards.json b/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/cards.json index 32a3a4c2..9577a4f6 100644 --- a/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/cards.json +++ b/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/cards.json @@ -5,7 +5,10 @@ "name": "Clay Pit", "color": "BROWN", "effect": { - "production": "O/C" + "production": { + "resources": "O/C", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -18,11 +21,15 @@ "7": 1 }, "image": "claypit.png" - }, { + }, + { "name": "Clay Pool", "color": "BROWN", "effect": { - "production": "C" + "production": { + "resources": "C", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -32,11 +39,15 @@ "7": 2 }, "image": "claypool.png" - }, { + }, + { "name": "Excavation", "color": "BROWN", "effect": { - "production": "S/C" + "production": { + "resources": "S/C", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -49,11 +60,15 @@ "7": 1 }, "image": "excavation.png" - }, { + }, + { "name": "Forest Cave", "color": "BROWN", "effect": { - "production": "W/O" + "production": { + "resources": "W/O", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -66,11 +81,15 @@ "7": 1 }, "image": "forestcave.png" - }, { + }, + { "name": "Lumber Yard", "color": "BROWN", "effect": { - "production": "W" + "production": { + "resources": "W", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -80,11 +99,15 @@ "7": 2 }, "image": "lumberyard.png" - }, { + }, + { "name": "Mine", "color": "BROWN", "effect": { - "production": "S/O" + "production": { + "resources": "S/O", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -97,11 +120,15 @@ "7": 1 }, "image": "mine.png" - }, { + }, + { "name": "Ore Vein", "color": "BROWN", "effect": { - "production": "O" + "production": { + "resources": "O", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -111,11 +138,15 @@ "7": 2 }, "image": "orevein.png" - }, { + }, + { "name": "Stone Pit", "color": "BROWN", "effect": { - "production": "S" + "production": { + "resources": "S", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -125,11 +156,15 @@ "7": 2 }, "image": "stonepit.png" - }, { + }, + { "name": "Timber Yard", "color": "BROWN", "effect": { - "production": "W/S" + "production": { + "resources": "W/S", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -142,11 +177,15 @@ "7": 1 }, "image": "timberyard.png" - }, { + }, + { "name": "Tree Farm", "color": "BROWN", "effect": { - "production": "W/C" + "production": { + "resources": "W/C", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -159,11 +198,15 @@ "7": 1 }, "image": "treefarm.png" - }, { + }, + { "name": "Glassworks", "color": "GREY", "effect": { - "production": "G" + "production": { + "resources": "G", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -173,11 +216,15 @@ "7": 2 }, "image": "glassworks.png" - }, { + }, + { "name": "Loom", "color": "GREY", "effect": { - "production": "L" + "production": { + "resources": "L", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -187,11 +234,15 @@ "7": 2 }, "image": "loom.png" - }, { + }, + { "name": "Press", "color": "GREY", "effect": { - "production": "P" + "production": { + "resources": "P", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -201,7 +252,8 @@ "7": 2 }, "image": "press.png" - }, { + }, + { "name": "East Trading Post", "color": "YELLOW", "effect": { @@ -224,16 +276,17 @@ "7": 2 }, "image": "easttradingpost.png" - }, { + }, + { "name": "Marketplace", "color": "YELLOW", "effect": { "discount": { "resourceTypes": "LGP", "providers": [ - "LEFT_PLAYER", "RIGHT_PLAYER" - ], - "discountedPrice": 1 + "LEFT_PLAYER", + "RIGHT_PLAYER" + ] } }, "chainChildren": [ @@ -247,7 +300,8 @@ "7": 2 }, "image": "marketplace.png" - }, { + }, + { "name": "Tavern", "color": "YELLOW", "effect": { @@ -261,7 +315,8 @@ "7": 3 }, "image": "tavern.png" - }, { + }, + { "name": "West Trading Post", "color": "YELLOW", "effect": { @@ -284,7 +339,8 @@ "7": 2 }, "image": "westtradingpost.png" - }, { + }, + { "name": "Altar", "color": "BLUE", "effect": { @@ -301,7 +357,8 @@ "7": 2 }, "image": "altar.png" - }, { + }, + { "name": "Baths", "color": "BLUE", "effect": { @@ -321,7 +378,8 @@ "7": 2 }, "image": "baths.png" - }, { + }, + { "name": "Pawnshop", "color": "BLUE", "effect": { @@ -335,7 +393,8 @@ "7": 2 }, "image": "pawnshop.png" - }, { + }, + { "name": "Theater", "color": "BLUE", "effect": { @@ -352,7 +411,8 @@ "7": 2 }, "image": "theater.png" - }, { + }, + { "name": "Apothecary", "color": "GREEN", "effect": { @@ -362,7 +422,8 @@ "resources": "L" }, "chainChildren": [ - "Stables", "Dispensary" + "Stables", + "Dispensary" ], "countPerNbPlayer": { "3": 1, @@ -372,7 +433,8 @@ "7": 2 }, "image": "apothecary.png" - }, { + }, + { "name": "Scriptorium", "color": "GREEN", "effect": { @@ -382,7 +444,8 @@ "resources": "P" }, "chainChildren": [ - "Courthouse", "Library" + "Courthouse", + "Library" ], "countPerNbPlayer": { "3": 1, @@ -392,7 +455,8 @@ "7": 2 }, "image": "scriptorium.png" - }, { + }, + { "name": "Workshop", "color": "GREEN", "effect": { @@ -402,7 +466,8 @@ "resources": "G" }, "chainChildren": [ - "Archery Range", "Laboratory" + "Archery Range", + "Laboratory" ], "countPerNbPlayer": { "3": 1, @@ -412,7 +477,8 @@ "7": 2 }, "image": "workshop.png" - }, { + }, + { "name": "Barracks", "color": "RED", "effect": { @@ -429,7 +495,8 @@ "7": 2 }, "image": "barracks.png" - }, { + }, + { "name": "Guard Tower", "color": "RED", "effect": { @@ -446,7 +513,8 @@ "7": 2 }, "image": "guardtower.png" - }, { + }, + { "name": "Stockade", "color": "RED", "effect": { @@ -473,7 +541,10 @@ "name": "Brickyard", "color": "BROWN", "effect": { - "production": "CC" + "production": { + "resources": "CC", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -486,11 +557,15 @@ "7": 2 }, "image": "brickyard.png" - }, { + }, + { "name": "Foundry", "color": "BROWN", "effect": { - "production": "OO" + "production": { + "resources": "OO", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -503,11 +578,15 @@ "7": 2 }, "image": "foundry.png" - }, { + }, + { "name": "Quarry", "color": "BROWN", "effect": { - "production": "SS" + "production": { + "resources": "SS", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -520,11 +599,15 @@ "7": 2 }, "image": "quarry.png" - }, { + }, + { "name": "Sawmill", "color": "BROWN", "effect": { - "production": "WW" + "production": { + "resources": "WW", + "isSellable": true + } }, "requirements": { "gold": 1 @@ -537,11 +620,15 @@ "7": 2 }, "image": "sawmill.png" - }, { + }, + { "name": "Glassworks", "color": "GREY", "effect": { - "production": "G" + "production": { + "resources": "G", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -551,11 +638,15 @@ "7": 2 }, "image": "glassworks.png" - }, { + }, + { "name": "Loom", "color": "GREY", "effect": { - "production": "L" + "production": { + "resources": "L", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -565,11 +656,15 @@ "7": 2 }, "image": "loom.png" - }, { + }, + { "name": "Press", "color": "GREY", "effect": { - "production": "P" + "production": { + "resources": "P", + "isSellable": true + } }, "countPerNbPlayer": { "3": 1, @@ -579,13 +674,16 @@ "7": 2 }, "image": "press.png" - }, { + }, + { "name": "Bazar", "color": "YELLOW", "effect": { "perBoardElement": { "boards": [ - "SELF", "LEFT", "RIGHT" + "SELF", + "LEFT", + "RIGHT" ], "gold": 2, "type": "CARD", @@ -602,11 +700,15 @@ "7": 2 }, "image": "bazar.png" - }, { + }, + { "name": "Caravansery", "color": "YELLOW", "effect": { - "production": "(W/S/O/C)" + "production": { + "resources": "W/S/O/C", + "isSellable": false + } }, "requirements": { "resources": "WW" @@ -623,11 +725,15 @@ "7": 3 }, "image": "caravansery.png" - }, { + }, + { "name": "Forum", "color": "YELLOW", "effect": { - "production": "(G/P/L)" + "production": { + "resources": "G/P/L", + "isSellable": false + } }, "requirements": { "resources": "CC" @@ -644,13 +750,16 @@ "7": 3 }, "image": "forum.png" - }, { + }, + { "name": "Vineyard", "color": "YELLOW", "effect": { "perBoardElement": { "boards": [ - "SELF", "LEFT", "RIGHT" + "SELF", + "LEFT", + "RIGHT" ], "gold": 1, "type": "CARD", @@ -667,7 +776,8 @@ "7": 2 }, "image": "vineyard.png" - }, { + }, + { "name": "Aqueduct", "color": "BLUE", "effect": { @@ -685,7 +795,8 @@ "7": 2 }, "image": "aqueduct.png" - }, { + }, + { "name": "Courthouse", "color": "BLUE", "effect": { @@ -703,7 +814,8 @@ "7": 2 }, "image": "courthouse.png" - }, { + }, + { "name": "Statue", "color": "BLUE", "effect": { @@ -724,7 +836,8 @@ "7": 2 }, "image": "statue.png" - }, { + }, + { "name": "Temple", "color": "BLUE", "effect": { @@ -745,7 +858,8 @@ "7": 2 }, "image": "temple.png" - }, { + }, + { "name": "Dispensary", "color": "GREEN", "effect": { @@ -756,7 +870,8 @@ }, "chainParent": "Apothecary", "chainChildren": [ - "Arena", "Lodge" + "Arena", + "Lodge" ], "countPerNbPlayer": { "3": 1, @@ -766,7 +881,8 @@ "7": 2 }, "image": "dispensary.png" - }, { + }, + { "name": "Laboratory", "color": "GREEN", "effect": { @@ -777,7 +893,8 @@ }, "chainParent": "Workshop", "chainChildren": [ - "Siege Workshop", "Observatory" + "Siege Workshop", + "Observatory" ], "countPerNbPlayer": { "3": 1, @@ -787,7 +904,8 @@ "7": 2 }, "image": "laboratory.png" - }, { + }, + { "name": "Library", "color": "GREEN", "effect": { @@ -798,7 +916,8 @@ }, "chainParent": "Scriptorium", "chainChildren": [ - "Senate", "University" + "Senate", + "University" ], "countPerNbPlayer": { "3": 1, @@ -808,7 +927,8 @@ "7": 2 }, "image": "library.png" - }, { + }, + { "name": "School", "color": "GREEN", "effect": { @@ -818,7 +938,8 @@ "resources": "WP" }, "chainChildren": [ - "Academy", "Study" + "Academy", + "Study" ], "countPerNbPlayer": { "3": 1, @@ -828,7 +949,8 @@ "7": 2 }, "image": "school.png" - }, { + }, + { "name": "Archery Range", "color": "RED", "effect": { @@ -846,7 +968,8 @@ "7": 2 }, "image": "archeryrange.png" - }, { + }, + { "name": "Stables", "color": "RED", "effect": { @@ -864,7 +987,8 @@ "7": 2 }, "image": "stables.png" - }, { + }, + { "name": "Training Ground", "color": "RED", "effect": { @@ -884,7 +1008,8 @@ "7": 3 }, "image": "trainingground.png" - }, { + }, + { "name": "Walls", "color": "RED", "effect": { @@ -918,9 +1043,9 @@ "boards": [ "SELF" ], + "type": "BUILT_WONDER_STAGES", "gold": 3, - "points": 1, - "type": "BUILT_WONDER_STAGES" + "points": 1 } }, "requirements": { @@ -935,7 +1060,8 @@ "7": 3 }, "image": "arena.png" - }, { + }, + { "name": "Chamber of Commerce", "color": "YELLOW", "effect": { @@ -943,9 +1069,9 @@ "boards": [ "SELF" ], + "type": "CARD", "gold": 2, "points": 2, - "type": "CARD", "colors": [ "GREY" ] @@ -962,7 +1088,8 @@ "7": 2 }, "image": "chamberofcommerce.png" - }, { + }, + { "name": "Haven", "color": "YELLOW", "effect": { @@ -970,9 +1097,9 @@ "boards": [ "SELF" ], + "type": "CARD", "gold": 1, "points": 1, - "type": "CARD", "colors": [ "BROWN" ] @@ -990,7 +1117,8 @@ "7": 2 }, "image": "haven.png" - }, { + }, + { "name": "Lighthouse", "color": "YELLOW", "effect": { @@ -998,9 +1126,9 @@ "boards": [ "SELF" ], + "type": "CARD", "gold": 1, "points": 1, - "type": "CARD", "colors": [ "GREY" ] @@ -1018,7 +1146,8 @@ "7": 2 }, "image": "lighthouse.png" - }, { + }, + { "name": "Gardens", "color": "BLUE", "effect": { @@ -1036,7 +1165,8 @@ "7": 2 }, "image": "gardens.png" - }, { + }, + { "name": "Palace", "color": "BLUE", "effect": { @@ -1053,7 +1183,8 @@ "7": 2 }, "image": "palace.png" - }, { + }, + { "name": "Pantheon", "color": "BLUE", "effect": { @@ -1071,7 +1202,8 @@ "7": 2 }, "image": "pantheon.png" - }, { + }, + { "name": "Senate", "color": "BLUE", "effect": { @@ -1089,7 +1221,8 @@ "7": 2 }, "image": "senate.png" - }, { + }, + { "name": "Town Hall", "color": "BLUE", "effect": { @@ -1106,7 +1239,8 @@ "7": 3 }, "image": "townhall.png" - }, { + }, + { "name": "Academy", "color": "GREEN", "effect": { @@ -1124,7 +1258,8 @@ "7": 2 }, "image": "academy.png" - }, { + }, + { "name": "Lodge", "color": "GREEN", "effect": { @@ -1142,7 +1277,8 @@ "7": 2 }, "image": "lodge.png" - }, { + }, + { "name": "Observatory", "color": "GREEN", "effect": { @@ -1160,7 +1296,8 @@ "7": 2 }, "image": "observatory.png" - }, { + }, + { "name": "Study", "color": "GREEN", "effect": { @@ -1178,7 +1315,8 @@ "7": 2 }, "image": "study.png" - }, { + }, + { "name": "University", "color": "GREEN", "effect": { @@ -1196,7 +1334,8 @@ "7": 2 }, "image": "university.png" - }, { + }, + { "name": "Arsenal", "color": "RED", "effect": { @@ -1213,7 +1352,8 @@ "7": 3 }, "image": "arsenal.png" - }, { + }, + { "name": "Circus", "color": "RED", "effect": { @@ -1231,7 +1371,8 @@ "7": 3 }, "image": "circus.png" - }, { + }, + { "name": "Fortifications", "color": "RED", "effect": { @@ -1249,7 +1390,8 @@ "7": 2 }, "image": "fortifications.png" - }, { + }, + { "name": "Siege Workshop", "color": "RED", "effect": { @@ -1278,28 +1420,30 @@ "effect": { "perBoardElement": { "boards": [ - "LEFT", "SELF", "RIGHT" + "LEFT", + "SELF", + "RIGHT" ], - "gold": 0, - "points": 1, - "type": "BUILT_WONDER_STAGES" + "type": "BUILT_WONDER_STAGES", + "points": 1 } }, "requirements": { "resources": "SSCCG" }, "image": "buildersguild.png" - }, { + }, + { "name": "Craftsmens Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 2, "type": "CARD", + "points": 2, "colors": [ "GREY" ] @@ -1309,17 +1453,18 @@ "resources": "SSOO" }, "image": "craftsmensguild.png" - }, { + }, + { "name": "Magistrates Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 1, "type": "CARD", + "points": 1, "colors": [ "BLUE" ] @@ -1329,17 +1474,18 @@ "resources": "WWWSL" }, "image": "magistratesguild.png" - }, { + }, + { "name": "Philosophers Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 1, "type": "CARD", + "points": 1, "colors": [ "GREEN" ] @@ -1349,7 +1495,8 @@ "resources": "CCCPL" }, "image": "philosophersguild.png" - }, { + }, + { "name": "Scientists Guild", "color": "PURPLE", "effect": { @@ -1359,7 +1506,8 @@ "resources": "WWOOP" }, "image": "scientistsguild.png" - }, { + }, + { "name": "Shipowners Guild", "color": "PURPLE", "effect": { @@ -1367,11 +1515,12 @@ "boards": [ "SELF" ], - "gold": 0, - "points": 1, "type": "CARD", + "points": 1, "colors": [ - "BROWN", "GREY", "PURPLE" + "BROWN", + "GREY", + "PURPLE" ] } }, @@ -1379,17 +1528,18 @@ "resources": "WWWGP" }, "image": "shipownersguild.png" - }, { + }, + { "name": "Spies Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 1, "type": "CARD", + "points": 1, "colors": [ "RED" ] @@ -1399,34 +1549,36 @@ "resources": "CCCG" }, "image": "spiesguild.png" - }, { + }, + { "name": "Strategists Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 1, - "type": "DEFEAT_TOKEN" + "type": "DEFEAT_TOKEN", + "points": 1 } }, "requirements": { "resources": "SOOL" }, "image": "strategistsguild.png" - }, { + }, + { "name": "Traders Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 1, "type": "CARD", + "points": 1, "colors": [ "YELLOW" ] @@ -1436,17 +1588,18 @@ "resources": "GPL" }, "image": "tradersguild.png" - }, { + }, + { "name": "Workers Guild", "color": "PURPLE", "effect": { "perBoardElement": { "boards": [ - "LEFT", "RIGHT" + "LEFT", + "RIGHT" ], - "gold": 0, - "points": 1, "type": "CARD", + "points": 1, "colors": [ "BROWN" ] @@ -1458,4 +1611,4 @@ "image": "workersguild.png" } ] -} +}
\ No newline at end of file diff --git a/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/wonders.json b/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/wonders.json index 9049ca5e..1088a339 100644 --- a/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/wonders.json +++ b/sw-engine/src/main/resources/org/luxons/sevenwonders/engine/data/wonders.json @@ -12,14 +12,19 @@ "effects": { "points": 3 } - }, { + }, + { "requirements": { "resources": "OO" }, "effects": { - "production": "(W/S/O/C)" + "production": { + "resources": "W/S/O/C", + "isSellable": false + } } - }, { + }, + { "requirements": { "resources": "GG" }, @@ -38,16 +43,24 @@ "resources": "CC" }, "effects": { - "production": "(W/S/O/C)" + "production": { + "resources": "W/S/O/C", + "isSellable": false + } } - }, { + }, + { "requirements": { "resources": "WW" }, "effects": { - "production": "(G/P/L)" + "production": { + "resources": "G/P/L", + "isSellable": false + } } - }, { + }, + { "requirements": { "resources": "SSS" }, @@ -59,380 +72,411 @@ "image": "alexandriaB.png" } } - }, { - "name": "Babylon", - "sides": { - "A": { - "initialResource": "C", - "stages": [ - { - "requirements": { - "resources": "CC" - }, - "effects": { - "points": 3 - } - }, { - "requirements": { - "resources": "WWW" - }, - "effects": { - "science": "any" - } - }, { - "requirements": { - "resources": "CCCC" + }, + { + "name": "Babylon", + "sides": { + "A": { + "initialResource": "C", + "stages": [ + { + "requirements": { + "resources": "CC" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 7 - } - } - ], - "image": "babylonA.png" - }, - "B": { - "initialResource": "C", - "stages": [ - { - "requirements": { - "resources": "CL" + { + "requirements": { + "resources": "WWW" + }, + "effects": { + "science": "any" + } }, - "effects": { - "points": 3 + { + "requirements": { + "resources": "CCCC" + }, + "effects": { + "points": 7 + } } - }, { - "requirements": { - "resources": "WWG" + ], + "image": "babylonA.png" + }, + "B": { + "initialResource": "C", + "stages": [ + { + "requirements": { + "resources": "CL" + }, + "effects": { + "points": 3 + } }, - "effects": { - "action": "PLAY_LAST_CARD" - } - }, { - "requirements": { - "resources": "CCCP" + { + "requirements": { + "resources": "WWG" + }, + "effects": { + "action": "PLAY_LAST_CARD" + } }, - "effects": { - "science": "any" + { + "requirements": { + "resources": "CCCP" + }, + "effects": { + "science": "any" + } } - } - ], - "image": "babylonB.png" + ], + "image": "babylonB.png" + } } - } -}, { - "name": "Ephesos", - "sides": { - "A": { - "initialResource": "P", - "stages": [ - { - "requirements": { - "resources": "SS" - }, - "effects": { - "points": 3 - } - }, { - "requirements": { - "resources": "WW" - }, - "effects": { - "gold": 9 - } - }, { - "requirements": { - "resources": "PP" + }, + { + "name": "Ephesos", + "sides": { + "A": { + "initialResource": "P", + "stages": [ + { + "requirements": { + "resources": "SS" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 7 - } - } - ], - "image": "ephesosA.png" - }, - "B": { - "initialResource": "P", - "stages": [ - { - "requirements": { - "resources": "SS" + { + "requirements": { + "resources": "WW" + }, + "effects": { + "gold": 9 + } }, - "effects": { - "gold": 4, - "points": 2 + { + "requirements": { + "resources": "PP" + }, + "effects": { + "points": 7 + } } - }, { - "requirements": { - "resources": "WW" + ], + "image": "ephesosA.png" + }, + "B": { + "initialResource": "P", + "stages": [ + { + "requirements": { + "resources": "SS" + }, + "effects": { + "gold": 4, + "points": 2 + } }, - "effects": { - "gold": 4, - "points": 3 - } - }, { - "requirements": { - "resources": "GPL" + { + "requirements": { + "resources": "WW" + }, + "effects": { + "gold": 4, + "points": 3 + } }, - "effects": { - "gold": 4, - "points": 5 + { + "requirements": { + "resources": "GPL" + }, + "effects": { + "gold": 4, + "points": 5 + } } - } - ], - "image": "ephesosB.png" + ], + "image": "ephesosB.png" + } } - } -}, { - "name": "Gizah", - "sides": { - "A": { - "initialResource": "S", - "stages": [ - { - "requirements": { - "resources": "SS" - }, - "effects": { - "points": 3 - } - }, { - "requirements": { - "resources": "WWW" - }, - "effects": { - "points": 5 - } - }, { - "requirements": { - "resources": "SSSS" + }, + { + "name": "Gizah", + "sides": { + "A": { + "initialResource": "S", + "stages": [ + { + "requirements": { + "resources": "SS" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 7 - } - } - ], - "image": "gizahA.png" - }, - "B": { - "initialResource": "S", - "stages": [ - { - "requirements": { - "resources": "WW" + { + "requirements": { + "resources": "WWW" + }, + "effects": { + "points": 5 + } }, - "effects": { - "points": 3 + { + "requirements": { + "resources": "SSSS" + }, + "effects": { + "points": 7 + } } - }, { - "requirements": { - "resources": "SSS" + ], + "image": "gizahA.png" + }, + "B": { + "initialResource": "S", + "stages": [ + { + "requirements": { + "resources": "WW" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 5 - } - }, { - "requirements": { - "resources": "CCC" + { + "requirements": { + "resources": "SSS" + }, + "effects": { + "points": 5 + } }, - "effects": { - "points": 5 - } - }, { - "requirements": { - "resources": "SSSSP" + { + "requirements": { + "resources": "CCC" + }, + "effects": { + "points": 5 + } }, - "effects": { - "points": 7 + { + "requirements": { + "resources": "SSSSP" + }, + "effects": { + "points": 7 + } } - } - ], - "image": "gizahB.png" + ], + "image": "gizahB.png" + } } - } -}, { - "name": "Halikarnassus", - "sides": { - "A": { - "initialResource": "L", - "stages": [ - { - "requirements": { - "resources": "CC" - }, - "effects": { - "points": 3 - } - }, { - "requirements": { - "resources": "OOO" - }, - "effects": { - "action": "PLAY_DISCARDED" - } - }, { - "requirements": { - "resources": "LL" + }, + { + "name": "Halikarnassus", + "sides": { + "A": { + "initialResource": "L", + "stages": [ + { + "requirements": { + "resources": "CC" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 7 - } - } - ], - "image": "halikarnassusA.png" - }, - "B": { - "initialResource": "L", - "stages": [ - { - "requirements": { - "resources": "OO" + { + "requirements": { + "resources": "OOO" + }, + "effects": { + "action": "PLAY_DISCARDED" + } }, - "effects": { - "points": 2, - "action": "PLAY_DISCARDED" + { + "requirements": { + "resources": "LL" + }, + "effects": { + "points": 7 + } } - }, { - "requirements": { - "resources": "CCC" + ], + "image": "halikarnassusA.png" + }, + "B": { + "initialResource": "L", + "stages": [ + { + "requirements": { + "resources": "OO" + }, + "effects": { + "points": 2, + "action": "PLAY_DISCARDED" + } }, - "effects": { - "points": 1, - "action": "PLAY_DISCARDED" - } - }, { - "requirements": { - "resources": "GPL" + { + "requirements": { + "resources": "CCC" + }, + "effects": { + "points": 1, + "action": "PLAY_DISCARDED" + } }, - "effects": { - "action": "PLAY_DISCARDED" + { + "requirements": { + "resources": "GPL" + }, + "effects": { + "action": "PLAY_DISCARDED" + } } - } - ], - "image": "halikarnassusB.png" + ], + "image": "halikarnassusB.png" + } } - } -}, { - "name": "Olympia", - "sides": { - "A": { - "initialResource": "W", - "stages": [ - { - "requirements": { - "resources": "WW" - }, - "effects": { - "points": 3 - } - }, { - "requirements": { - "resources": "SS" - }, - "effects": { - "action": "ONE_FREE_PER_AGE" - } - }, { - "requirements": { - "resources": "OO" + }, + { + "name": "Olympia", + "sides": { + "A": { + "initialResource": "W", + "stages": [ + { + "requirements": { + "resources": "WW" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 7 - } - } - ], - "image": "olympiaA.png" - }, - "B": { - "initialResource": "W", - "stages": [ - { - "requirements": { - "resources": "WW" + { + "requirements": { + "resources": "SS" + }, + "effects": { + "action": "ONE_FREE_PER_AGE" + } }, - "effects": { - "discount": { - "resourceTypes": "WSOC", - "providers": [ - "LEFT_PLAYER", "RIGHT_PLAYER" - ], - "discountedPrice": 1 + { + "requirements": { + "resources": "OO" + }, + "effects": { + "points": 7 } } - }, { - "requirements": { - "resources": "SS" + ], + "image": "olympiaA.png" + }, + "B": { + "initialResource": "W", + "stages": [ + { + "requirements": { + "resources": "WW" + }, + "effects": { + "discount": { + "resourceTypes": "WSOC", + "providers": [ + "LEFT_PLAYER", + "RIGHT_PLAYER" + ], + "discountedPrice": 1 + } + } }, - "effects": { - "points": 5 - } - }, { - "requirements": { - "resources": "OOL" + { + "requirements": { + "resources": "SS" + }, + "effects": { + "points": 5 + } }, - "effects": { - "action": "COPY_GUILD" + { + "requirements": { + "resources": "OOL" + }, + "effects": { + "action": "COPY_GUILD" + } } - } - ], - "image": "olympiaB.png" + ], + "image": "olympiaB.png" + } } - } -}, { - "name": "Rhodos", - "sides": { - "A": { - "initialResource": "O", - "stages": [ - { - "requirements": { - "resources": "WW" - }, - "effects": { - "points": 3 - } - }, { - "requirements": { - "resources": "CCC" - }, - "effects": { - "military": 2 - } - }, { - "requirements": { - "resources": "OOOO" + }, + { + "name": "Rhodos", + "sides": { + "A": { + "initialResource": "O", + "stages": [ + { + "requirements": { + "resources": "WW" + }, + "effects": { + "points": 3 + } }, - "effects": { - "points": 7 - } - } - ], - "image": "rhodosA.png" - }, - "B": { - "initialResource": "O", - "stages": [ - { - "requirements": { - "resources": "SSS" + { + "requirements": { + "resources": "CCC" + }, + "effects": { + "military": 2 + } }, - "effects": { - "gold": 3, - "military": 1, - "points": 3 + { + "requirements": { + "resources": "OOOO" + }, + "effects": { + "points": 7 + } } - }, { - "requirements": { - "resources": "OOOO" + ], + "image": "rhodosA.png" + }, + "B": { + "initialResource": "O", + "stages": [ + { + "requirements": { + "resources": "SSS" + }, + "effects": { + "gold": 3, + "military": 1, + "points": 3 + } }, - "effects": { - "gold": 4, - "military": 1, - "points": 4 + { + "requirements": { + "resources": "OOOO" + }, + "effects": { + "gold": 4, + "military": 1, + "points": 4 + } } - } - ], - "image": "rhodosB.png" + ], + "image": "rhodosB.png" + } } } -} ] diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/NumericEffectSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/NumericEffectSerializerTest.kt deleted file mode 100644 index 520db340..00000000 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/NumericEffectSerializerTest.kt +++ /dev/null @@ -1,148 +0,0 @@ -package org.luxons.sevenwonders.engine.data.serializers - -import com.github.salomonbrys.kotson.fromJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import org.junit.Before -import org.junit.Test -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.engine.effects.GoldIncrease -import org.luxons.sevenwonders.engine.effects.MilitaryReinforcements -import org.luxons.sevenwonders.engine.effects.ProductionIncrease -import org.luxons.sevenwonders.engine.effects.RawPointsIncrease -import org.luxons.sevenwonders.engine.resources.Production -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -@RunWith(Theories::class) -class NumericEffectSerializerTest { - - private lateinit var gson: Gson - - @Before - fun setUp() { - gson = GsonBuilder().registerTypeAdapter(MilitaryReinforcements::class.java, NumericEffectSerializer()) - .registerTypeAdapter(RawPointsIncrease::class.java, NumericEffectSerializer()) - .registerTypeAdapter(GoldIncrease::class.java, NumericEffectSerializer()) - // ProductionIncrease is not a numeric effect, it is here for negative testing purpose - .registerTypeAdapter(ProductionIncrease::class.java, NumericEffectSerializer()) - .create() - } - - @Test - fun serialize_militaryReinforcements_null() { - assertEquals("null", gson.toJson(null, MilitaryReinforcements::class.java)) - } - - @Test - fun serialize_rawPointsIncrease_null() { - assertEquals("null", gson.toJson(null, RawPointsIncrease::class.java)) - } - - @Test - fun serialize_goldIncrease_null() { - assertEquals("null", gson.toJson(null, GoldIncrease::class.java)) - } - - @Test - fun serialize_failOnUnknownType() { - assertFailsWith<IllegalArgumentException> { - gson.toJson(ProductionIncrease(Production(), false)) - } - } - - @Theory - fun serialize_militaryReinforcements(count: Int) { - val reinforcements = MilitaryReinforcements(count) - assertEquals(count.toString(), gson.toJson(reinforcements)) - } - - @Theory - fun serialize_rawPointsIncrease(count: Int) { - val points = RawPointsIncrease(count) - assertEquals(count.toString(), gson.toJson(points)) - } - - @Theory - fun serialize_goldIncrease(count: Int) { - val goldIncrease = GoldIncrease(count) - assertEquals(count.toString(), gson.toJson(goldIncrease)) - } - - @Theory - fun deserialize_militaryReinforcements(count: Int) { - val reinforcements = MilitaryReinforcements(count) - assertEquals(reinforcements, gson.fromJson<MilitaryReinforcements>(count.toString())) - } - - @Theory - fun deserialize_rawPointsIncrease(count: Int) { - val points = RawPointsIncrease(count) - assertEquals(points, gson.fromJson<RawPointsIncrease>(count.toString())) - } - - @Theory - fun deserialize_goldIncrease(count: Int) { - val goldIncrease = GoldIncrease(count) - assertEquals(goldIncrease, gson.fromJson<GoldIncrease>(count.toString())) - } - - @Test - fun deserialize_militaryReinforcements_failOnEmptyString() { - assertFailsWith<NumberFormatException> { - gson.fromJson<MilitaryReinforcements>("\"\"") - } - } - - @Test - fun deserialize_rawPointsIncrease_failOnEmptyString() { - assertFailsWith<NumberFormatException> { - gson.fromJson<RawPointsIncrease>("\"\"") - } - } - - @Test - fun deserialize_goldIncrease_failOnEmptyString() { - assertFailsWith<NumberFormatException> { - gson.fromJson<GoldIncrease>("\"\"") - } - } - - @Test - fun deserialize_militaryReinforcements_failOnNonNumericString() { - assertFailsWith<NumberFormatException> { - gson.fromJson<MilitaryReinforcements>("\"abc\"") - } - } - - @Test - fun deserialize_rawPointsIncrease_failOnNonNumericString() { - assertFailsWith<NumberFormatException> { - gson.fromJson<RawPointsIncrease>("\"abc\"") - } - } - - @Test - fun deserialize_goldIncrease_failOnNonNumericString() { - assertFailsWith<NumberFormatException> { - gson.fromJson<GoldIncrease>("\"abc\"") - } - } - - @Test - fun deserialize_failOnUnknownType() { - assertFailsWith<IllegalArgumentException> { - gson.fromJson<ProductionIncrease>("\"2\"") - } - } - - companion object { - - @JvmStatic - @DataPoints - fun dataPoints(): IntArray = intArrayOf(-2, -1, 0, 1, 2, 5) - } -} diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionIncreaseSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionIncreaseSerializerTest.kt deleted file mode 100644 index 664ccedc..00000000 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionIncreaseSerializerTest.kt +++ /dev/null @@ -1,192 +0,0 @@ -package org.luxons.sevenwonders.engine.data.serializers - -import com.github.salomonbrys.kotson.fromJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import com.google.gson.reflect.TypeToken -import org.junit.Before -import org.junit.Test -import org.luxons.sevenwonders.engine.effects.ProductionIncrease -import org.luxons.sevenwonders.engine.resources.MutableResources -import org.luxons.sevenwonders.engine.resources.Production -import org.luxons.sevenwonders.engine.resources.Resources -import org.luxons.sevenwonders.model.resources.ResourceType -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertNull - -class ProductionIncreaseSerializerTest { - - private lateinit var gson: Gson - - @Before - fun setUp() { - 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()) - .registerTypeAdapter(ProductionIncrease::class.java, ProductionIncreaseSerializer()) - .create() - } - - private fun create(sellable: Boolean, wood: Int, stone: Int, clay: Int): ProductionIncrease { - val production = Production() - if (wood > 0) { - production.addFixedResource(ResourceType.WOOD, wood) - } - if (stone > 0) { - production.addFixedResource(ResourceType.STONE, stone) - } - if (clay > 0) { - production.addFixedResource(ResourceType.CLAY, clay) - } - return ProductionIncrease(production, sellable) - } - - private fun createChoice(sellable: Boolean, vararg types: ResourceType): ProductionIncrease { - val production = Production() - production.addChoice(*types) - return ProductionIncrease(production, sellable) - } - - @Test - fun serialize_nullAsNull() { - assertEquals("null", gson.toJson(null, ProductionIncrease::class.java)) - } - - @Test - fun serialize_emptyProdIncreaseAsNull() { - val prodIncrease = ProductionIncrease(Production(), false) - assertEquals("null", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_singleType() { - val prodIncrease = create(true, 1, 0, 0) - assertEquals("\"W\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_mixedTypes() { - val prodIncrease = create(true, 1, 1, 1) - assertEquals("\"WSC\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_mixedTypes_notSellable() { - val prodIncrease = create(false, 1, 1, 1) - assertEquals("\"(WSC)\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_choice2() { - val prodIncrease = createChoice(true, ResourceType.WOOD, ResourceType.CLAY) - assertEquals("\"W/C\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_choice3() { - val prodIncrease = createChoice(true, ResourceType.WOOD, ResourceType.ORE, ResourceType.CLAY) - assertEquals("\"W/O/C\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_choice3_notSellable() { - val prodIncrease = createChoice(false, ResourceType.WOOD, ResourceType.ORE, ResourceType.CLAY) - assertEquals("\"(W/O/C)\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_choice2_unordered() { - val prodIncrease = createChoice(true, ResourceType.CLAY, ResourceType.WOOD) - assertEquals("\"W/C\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_choice3_unordered() { - val prodIncrease = createChoice(true, ResourceType.WOOD, ResourceType.CLAY, ResourceType.ORE) - assertEquals("\"W/O/C\"", gson.toJson(prodIncrease)) - } - - @Test - fun serialize_failIfMultipleChoices() { - val prodIncrease = createChoice(true, ResourceType.WOOD, ResourceType.CLAY) - prodIncrease.production.addChoice(ResourceType.ORE, ResourceType.GLASS) - assertFailsWith<IllegalArgumentException> { - gson.toJson(prodIncrease) - } - } - - @Test - fun serialize_failIfMixedFixedAndChoices() { - val prodIncrease = create(true, 1, 0, 0) - prodIncrease.production.addChoice(ResourceType.WOOD, ResourceType.CLAY) - assertFailsWith<IllegalArgumentException> { - gson.toJson(prodIncrease) - } - } - - @Test - fun deserialize_nullFromNull() { - assertNull(gson.fromJson("null", ProductionIncrease::class.java)) - } - - @Test - fun deserialize_emptyList() { - val prodIncrease = ProductionIncrease(Production(), true) - assertEquals(prodIncrease, gson.fromJson("\"\"")) - } - - @Test - fun deserialize_failOnGarbageString() { - assertFailsWith(IllegalArgumentException::class) { - gson.fromJson<ProductionIncrease>("\"this is garbage\"") - } - } - - @Test - fun deserialize_failOnGarbageStringWithSlashes() { - assertFailsWith(IllegalArgumentException::class) { - gson.fromJson<ProductionIncrease>("\"this/is/garbage\"") - } - } - - @Test - fun deserialize_singleType() { - val prodIncrease = create(true, 1, 0, 0) - assertEquals(prodIncrease, gson.fromJson("\"W\"")) - } - - @Test - fun deserialize_multipleTimesSameType_notSellable() { - val prodIncrease = create(false, 3, 0, 0) - assertEquals(prodIncrease, gson.fromJson("\"(WWW)\"")) - } - - @Test - fun deserialize_mixedTypes() { - val prodIncrease = create(true, 1, 1, 1) - assertEquals(prodIncrease, gson.fromJson("\"WCS\"")) - } - - @Test - fun deserialize_choice2() { - val prodIncrease = createChoice(true, ResourceType.WOOD, ResourceType.CLAY) - assertEquals(prodIncrease, gson.fromJson("\"W/C\"")) - } - - @Test - fun deserialize_choice3_notSellable() { - val prodIncrease = createChoice(false, ResourceType.WOOD, ResourceType.ORE, ResourceType.CLAY) - assertEquals(prodIncrease, gson.fromJson("\"(W/O/C)\"")) - } - - @Test - fun deserialize_failOnMultipleResourcesInChoice() { - assertFailsWith(IllegalArgumentException::class) { - gson.fromJson<ProductionIncrease>("\"W/SS/C\"") - } - } -} diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializerTest.kt index 314bc43c..25e9d68c 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializerTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ProductionSerializerTest.kt @@ -1,14 +1,11 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.github.salomonbrys.kotson.fromJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import com.google.gson.reflect.TypeToken -import org.junit.Before +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import org.junit.Test -import org.luxons.sevenwonders.engine.resources.MutableResources import org.luxons.sevenwonders.engine.resources.Production -import org.luxons.sevenwonders.engine.resources.Resources import org.luxons.sevenwonders.model.resources.ResourceType import kotlin.test.assertEquals import kotlin.test.assertFailsWith @@ -16,19 +13,6 @@ import kotlin.test.assertNull class ProductionSerializerTest { - private lateinit var gson: Gson - - @Before - fun setUp() { - 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()) - .create() - } - private fun create(wood: Int, stone: Int, clay: Int): Production { val production = Production() if (wood > 0) { @@ -51,61 +35,61 @@ class ProductionSerializerTest { @Test fun serialize_nullAsNull() { - assertEquals("null", gson.toJson(null, Production::class.java)) + assertEquals("null", Json.encodeToString(Production.serializer().nullable, null)) } @Test fun serialize_emptyProdIncreaseAsNull() { val prodIncrease = Production() - assertEquals("null", gson.toJson(prodIncrease)) + assertEquals("null", Json.encodeToString(prodIncrease)) } @Test fun serialize_singleType() { val prodIncrease = create(1, 0, 0) - assertEquals("\"W\"", gson.toJson(prodIncrease)) + assertEquals("\"W\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_multipleTimesSameType() { val prodIncrease = create(3, 0, 0) - assertEquals("\"WWW\"", gson.toJson(prodIncrease)) + assertEquals("\"WWW\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_mixedTypes() { val prodIncrease = create(1, 1, 1) - assertEquals("\"WSC\"", gson.toJson(prodIncrease)) + assertEquals("\"WSC\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_mixedTypesMultiple() { val prodIncrease = create(2, 1, 2) - assertEquals("\"WWSCC\"", gson.toJson(prodIncrease)) + assertEquals("\"WWSCC\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_choice2() { val prodIncrease = createChoice(ResourceType.WOOD, ResourceType.CLAY) - assertEquals("\"W/C\"", gson.toJson(prodIncrease)) + assertEquals("\"W/C\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_choice3() { val prodIncrease = createChoice(ResourceType.WOOD, ResourceType.ORE, ResourceType.CLAY) - assertEquals("\"W/O/C\"", gson.toJson(prodIncrease)) + assertEquals("\"W/O/C\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_choice2_unordered() { val prodIncrease = createChoice(ResourceType.CLAY, ResourceType.WOOD) - assertEquals("\"W/C\"", gson.toJson(prodIncrease)) + assertEquals("\"W/C\"", Json.encodeToString(prodIncrease)) } @Test fun serialize_choice3_unordered() { val prodIncrease = createChoice(ResourceType.WOOD, ResourceType.CLAY, ResourceType.ORE) - assertEquals("\"W/O/C\"", gson.toJson(prodIncrease)) + assertEquals("\"W/O/C\"", Json.encodeToString(prodIncrease)) } @Test @@ -113,7 +97,7 @@ class ProductionSerializerTest { val production = createChoice(ResourceType.WOOD, ResourceType.CLAY) production.addChoice(ResourceType.ORE, ResourceType.GLASS) assertFailsWith<IllegalArgumentException> { - gson.toJson(production) + Json.encodeToString(production) } } @@ -122,87 +106,86 @@ class ProductionSerializerTest { val production = create(1, 0, 0) production.addChoice(ResourceType.WOOD, ResourceType.CLAY) assertFailsWith<IllegalArgumentException> { - gson.toJson(production) + Json.encodeToString(production) } } @Test fun deserialize_nullFromNull() { - assertNull(gson.fromJson("null", Production::class.java)) + assertNull(Json.decodeFromString<Production?>("null")) } @Test fun deserialize_emptyList() { - val prodIncrease = Production() - assertEquals(prodIncrease, gson.fromJson("\"\"")) + assertEquals(Production(), Json.decodeFromString("\"\"")) } @Test fun deserialize_failOnGarbageString() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<Production>("\"this is garbage\"") + Json.decodeFromString<Production>("\"this is garbage\"") } } @Test fun deserialize_failOnGarbageStringWithSlashes() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<Production>("\"this/is/garbage\"") + Json.decodeFromString<Production>("\"this/is/garbage\"") } } @Test fun deserialize_singleType() { val prodIncrease = create(1, 0, 0) - assertEquals(prodIncrease, gson.fromJson("\"W\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"W\"")) } @Test fun deserialize_multipleTimesSameType() { val prodIncrease = create(3, 0, 0) - assertEquals(prodIncrease, gson.fromJson("\"WWW\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"WWW\"")) } @Test fun deserialize_mixedTypes() { val prodIncrease = create(1, 1, 1) - assertEquals(prodIncrease, gson.fromJson("\"WCS\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"WCS\"")) } @Test fun deserialize_mixedTypes_unordered() { val prodIncrease = create(1, 3, 2) - assertEquals(prodIncrease, gson.fromJson("\"SCWCSS\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"SCWCSS\"")) } @Test fun deserialize_choice2() { val prodIncrease = createChoice(ResourceType.WOOD, ResourceType.CLAY) - assertEquals(prodIncrease, gson.fromJson("\"W/C\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"W/C\"")) } @Test fun deserialize_choice3() { val prodIncrease = createChoice(ResourceType.WOOD, ResourceType.ORE, ResourceType.CLAY) - assertEquals(prodIncrease, gson.fromJson("\"W/O/C\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"W/O/C\"")) } @Test fun deserialize_choice2_unordered() { val prodIncrease = createChoice(ResourceType.CLAY, ResourceType.WOOD) - assertEquals(prodIncrease, gson.fromJson("\"W/C\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"W/C\"")) } @Test fun deserialize_choice3_unordered() { val prodIncrease = createChoice(ResourceType.WOOD, ResourceType.CLAY, ResourceType.ORE) - assertEquals(prodIncrease, gson.fromJson("\"W/O/C\"")) + assertEquals(prodIncrease, Json.decodeFromString("\"W/O/C\"")) } @Test fun deserialize_failOnMultipleResourcesInChoice() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<Production>("\"W/SS/C\"") + Json.decodeFromString<Production>("\"W/SS/C\"") } } } diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializerTest.kt index e256efc3..3956ff0c 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializerTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypeSerializerTest.kt @@ -1,9 +1,7 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.github.salomonbrys.kotson.fromJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import org.junit.Before +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.json.Json import org.junit.Test import org.luxons.sevenwonders.model.resources.ResourceType import kotlin.test.assertEquals @@ -12,45 +10,38 @@ import kotlin.test.assertNull class ResourceTypeSerializerTest { - private lateinit var gson: Gson - - @Before - fun setUp() { - gson = GsonBuilder().registerTypeAdapter(ResourceType::class.java, ResourceTypeSerializer()).create() - } - @Test fun serialize_useSymbolForEachType() { ResourceType.values().forEach { type -> - val expectedJson = "\"" + type.symbol + "\"" - assertEquals(expectedJson, gson.toJson(type)) + val expectedjson = "\"" + type.symbol + "\"" + assertEquals(expectedjson, Json.encodeToString(ResourceTypeSerializer, type)) } } @Test fun deserialize_useSymbolForEachType() { ResourceType.values().forEach { type -> - val typeInJson = "\"" + type.symbol + "\"" - assertEquals(type, gson.fromJson(typeInJson)) + val typeInjson = "\"" + type.symbol + "\"" + assertEquals(type, Json.decodeFromString(ResourceTypeSerializer, typeInjson)) } } @Test fun deserialize_nullFromNull() { - assertNull(gson.fromJson("null", ResourceType::class.java)) + assertNull(Json.decodeFromString(ResourceTypeSerializer.nullable, "null")) } @Test fun deserialize_failsOnEmptyString() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<ResourceType>("\"\"") + Json.decodeFromString(ResourceTypeSerializer, "\"\"") } } @Test fun deserialize_failsOnGarbageString() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<ResourceType>("\"thisisgarbage\"") + Json.decodeFromString(ResourceTypeSerializer, "\"thisisgarbage\"") } } } diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializerTest.kt index 8c2ce2fc..b7ea6c9e 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializerTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourceTypesSerializerTest.kt @@ -1,11 +1,7 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.github.salomonbrys.kotson.fromJson -import com.github.salomonbrys.kotson.typeToken -import com.github.salomonbrys.kotson.typedToJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import org.junit.Before +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.json.Json import org.junit.Test import org.luxons.sevenwonders.model.resources.ResourceType import kotlin.test.assertEquals @@ -13,68 +9,61 @@ import kotlin.test.assertNull class ResourceTypesSerializerTest { - private lateinit var gson: Gson - - @Before - fun setUp() { - gson = GsonBuilder().registerTypeAdapter(typeToken<List<ResourceType>>(), ResourceTypesSerializer()).create() - } - @Test fun serialize_null() { - assertEquals("null", gson.toJson(null, typeToken<List<ResourceType>>())) + assertEquals("null", Json.encodeToString(ResourceTypesSerializer.nullable, null)) } @Test fun serialize_emptyList() { val types = emptyList<ResourceType>() - assertEquals("\"\"", gson.typedToJson(types)) + assertEquals("\"\"", Json.encodeToString(ResourceTypesSerializer, types)) } @Test fun serialize_singleType() { val types = listOf(ResourceType.WOOD) - assertEquals("\"W\"", gson.typedToJson(types)) + assertEquals("\"W\"", Json.encodeToString(ResourceTypesSerializer, types)) } @Test fun serialize_multipleTimesSameType() { val types = List(3) { ResourceType.WOOD } - assertEquals("\"WWW\"", gson.typedToJson(types)) + assertEquals("\"WWW\"", Json.encodeToString(ResourceTypesSerializer, types)) } @Test fun serialize_mixedTypes() { val types = listOf(ResourceType.WOOD, ResourceType.CLAY, ResourceType.STONE) - assertEquals("\"WCS\"", gson.typedToJson(types)) + assertEquals("\"WCS\"", Json.encodeToString(ResourceTypesSerializer, types)) } @Test fun deserialize_null() { - assertNull(gson.fromJson("null", typeToken<List<ResourceType>>())) + assertNull(Json.decodeFromString(ResourceTypesSerializer.nullable, "null")) } @Test fun deserialize_emptyList() { val types = emptyList<ResourceType>() - assertEquals(types, gson.fromJson("\"\"")) + assertEquals(types, Json.decodeFromString(ResourceTypesSerializer, "\"\"")) } @Test fun deserialize_singleType() { val types = listOf(ResourceType.WOOD) - assertEquals(types, gson.fromJson("\"W\"")) + assertEquals(types, Json.decodeFromString(ResourceTypesSerializer, "\"W\"")) } @Test fun deserialize_multipleTimesSameType() { val types = List(3) { ResourceType.WOOD } - assertEquals(types, gson.fromJson("\"WWW\"")) + assertEquals(types, Json.decodeFromString(ResourceTypesSerializer, "\"WWW\"")) } @Test fun deserialize_mixedTypes() { val types = listOf(ResourceType.WOOD, ResourceType.CLAY, ResourceType.STONE) - assertEquals(types, gson.fromJson("\"WCS\"")) + assertEquals(types, Json.decodeFromString(ResourceTypesSerializer, "\"WCS\"")) } } diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializerTest.kt index bc5808a0..614babe4 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializerTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ResourcesSerializerTest.kt @@ -1,99 +1,93 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.github.salomonbrys.kotson.fromJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import org.junit.Before +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule import org.junit.Test -import org.luxons.sevenwonders.engine.resources.MutableResources import org.luxons.sevenwonders.engine.resources.Resources import org.luxons.sevenwonders.engine.resources.emptyResources import org.luxons.sevenwonders.engine.resources.resourcesOf -import org.luxons.sevenwonders.model.resources.ResourceType.CLAY -import org.luxons.sevenwonders.model.resources.ResourceType.STONE -import org.luxons.sevenwonders.model.resources.ResourceType.WOOD +import org.luxons.sevenwonders.model.resources.ResourceType.* import kotlin.test.assertEquals import kotlin.test.assertNull class ResourcesSerializerTest { - private lateinit var gson: Gson - - @Before - fun setUp() { - gson = GsonBuilder() // - .registerTypeAdapter(Resources::class.java, ResourcesSerializer()) - .registerTypeAdapter(MutableResources::class.java, ResourcesSerializer()) - .create() + private val json: Json = Json { + serializersModule = SerializersModule { + contextual(Resources::class, ResourcesSerializer) + } } @Test fun serialize_null() { - assertEquals("null", gson.toJson(null, Resources::class.java)) + assertEquals("null", json.encodeToString(ResourcesSerializer.nullable, null)) } @Test fun serialize_emptyResourcesToNull() { val resources = emptyResources() - assertEquals("null", gson.toJson(resources)) + assertEquals("null", json.encodeToString(resources)) } @Test fun serialize_singleType() { val resources = resourcesOf(WOOD) - assertEquals("\"W\"", gson.toJson(resources)) + assertEquals("\"W\"", json.encodeToString(resources)) } @Test fun serialize_multipleTimesSameType() { val resources = resourcesOf(WOOD to 3) - assertEquals("\"WWW\"", gson.toJson(resources)) + assertEquals("\"WWW\"", json.encodeToString(resources)) } @Test fun serialize_mixedTypes() { val resources = resourcesOf(WOOD, STONE, CLAY) - assertEquals("\"WSC\"", gson.toJson(resources)) + assertEquals("\"WSC\"", json.encodeToString(resources)) } @Test fun serialize_mixedTypes_unordered() { val resources = resourcesOf(CLAY to 1, WOOD to 2, CLAY to 1, STONE to 1) - assertEquals("\"CCWWS\"", gson.toJson(resources)) + assertEquals("\"CCWWS\"", json.encodeToString(resources)) } @Test fun deserialize_null() { - assertNull(gson.fromJson("null", Resources::class.java)) + assertNull(json.decodeFromString<Resources?>("null")) } @Test fun deserialize_emptyList() { val resources = emptyResources() - assertEquals(resources, gson.fromJson("\"\"")) + assertEquals(resources, json.decodeFromString("\"\"")) } @Test fun deserialize_singleType() { val resources = resourcesOf(WOOD) - assertEquals(resources, gson.fromJson("\"W\"")) + assertEquals(resources, json.decodeFromString("\"W\"")) } @Test fun deserialize_multipleTimesSameType() { val resources = resourcesOf(WOOD to 3) - assertEquals(resources, gson.fromJson("\"WWW\"")) + assertEquals(resources, json.decodeFromString("\"WWW\"")) } @Test fun deserialize_mixedTypes() { val resources = resourcesOf(WOOD, CLAY, STONE) - assertEquals(resources, gson.fromJson("\"WCS\"")) + assertEquals(resources, json.decodeFromString("\"WCS\"")) } @Test fun deserialize_mixedTypes_unordered() { val resources = resourcesOf(WOOD to 1, CLAY to 2, STONE to 3) - assertEquals(resources, gson.fromJson("\"SCWCSS\"")) + assertEquals(resources, json.decodeFromString("\"SCWCSS\"")) } } diff --git a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializerTest.kt b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializerTest.kt index 19b1e572..1519ec7e 100644 --- a/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializerTest.kt +++ b/sw-engine/src/test/kotlin/org/luxons/sevenwonders/engine/data/serializers/ScienceProgressSerializerTest.kt @@ -1,9 +1,8 @@ package org.luxons.sevenwonders.engine.data.serializers -import com.github.salomonbrys.kotson.fromJson -import com.google.gson.Gson -import com.google.gson.GsonBuilder -import org.junit.Before +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import org.junit.Test import org.luxons.sevenwonders.engine.boards.ScienceType import org.luxons.sevenwonders.engine.effects.ScienceProgress @@ -19,45 +18,38 @@ private const val JOKER_STR = "\"any\"" class ScienceProgressSerializerTest { - private lateinit var gson: Gson - - @Before - fun setUp() { - gson = GsonBuilder().registerTypeAdapter(ScienceProgress::class.java, ScienceProgressSerializer()).create() - } - @Test fun serialize_emptyToNull() { val progress = createScienceProgress(0, 0, 0, 0) - val json = gson.toJson(progress) + val json = Json.encodeToString(progress) assertEquals("null", json) } @Test fun serialize_oneCompass() { val progress = createScienceProgress(1, 0, 0, 0) - val json = gson.toJson(progress) + val json = Json.encodeToString(progress) assertEquals(COMPASS_STR, json) } @Test fun serialize_oneWheel() { val progress = createScienceProgress(0, 1, 0, 0) - val json = gson.toJson(progress) + val json = Json.encodeToString(progress) assertEquals(WHEEL_STR, json) } @Test fun serialize_oneTablet() { val progress = createScienceProgress(0, 0, 1, 0) - val json = gson.toJson(progress) + val json = Json.encodeToString(progress) assertEquals(TABLET_STR, json) } @Test fun serialize_oneJoker() { val progress = createScienceProgress(0, 0, 0, 1) - val json = gson.toJson(progress) + val json = Json.encodeToString(progress) assertEquals(JOKER_STR, json) } @@ -65,7 +57,7 @@ class ScienceProgressSerializerTest { fun serialize_failOnMultipleCompasses() { assertFailsWith<UnsupportedOperationException> { val progress = createScienceProgress(2, 0, 0, 0) - gson.toJson(progress) + Json.encodeToString(progress) } } @@ -73,7 +65,7 @@ class ScienceProgressSerializerTest { fun serialize_failOnMultipleWheels() { assertFailsWith<UnsupportedOperationException> { val progress = createScienceProgress(0, 2, 0, 0) - gson.toJson(progress) + Json.encodeToString(progress) } } @@ -81,7 +73,7 @@ class ScienceProgressSerializerTest { fun serialize_failOnMultipleTablets() { assertFailsWith<UnsupportedOperationException> { val progress = createScienceProgress(0, 0, 2, 0) - gson.toJson(progress) + Json.encodeToString(progress) } } @@ -89,7 +81,7 @@ class ScienceProgressSerializerTest { fun serialize_failOnMultipleJokers() { assertFailsWith<UnsupportedOperationException> { val progress = createScienceProgress(0, 0, 0, 2) - gson.toJson(progress) + Json.encodeToString(progress) } } @@ -97,27 +89,27 @@ class ScienceProgressSerializerTest { fun serialize_failOnMixedElements() { assertFailsWith<UnsupportedOperationException> { val progress = createScienceProgress(1, 1, 0, 0) - gson.toJson(progress) + Json.encodeToString(progress) } } @Test fun deserialize_failOnEmptyString() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<ScienceProgress>("\"\"") + Json.decodeFromString<ScienceProgress>("\"\"") } } @Test fun deserialize_failOnGarbageString() { assertFailsWith<IllegalArgumentException> { - gson.fromJson<ScienceProgress>("thisisgarbage") + Json.decodeFromString<ScienceProgress>("thisisgarbage") } } @Test fun deserialize_compass() { - val progress = gson.fromJson<ScienceProgress>(COMPASS_STR) + val progress = Json.decodeFromString<ScienceProgress>(COMPASS_STR) assertNotNull(progress.science) assertEquals(1, progress.science.getQuantity(ScienceType.COMPASS)) assertEquals(0, progress.science.getQuantity(ScienceType.WHEEL)) @@ -127,7 +119,7 @@ class ScienceProgressSerializerTest { @Test fun deserialize_wheel() { - val progress = gson.fromJson<ScienceProgress>(WHEEL_STR) + val progress = Json.decodeFromString<ScienceProgress>(WHEEL_STR) assertNotNull(progress.science) assertEquals(0, progress.science.getQuantity(ScienceType.COMPASS)) assertEquals(1, progress.science.getQuantity(ScienceType.WHEEL)) @@ -137,7 +129,7 @@ class ScienceProgressSerializerTest { @Test fun deserialize_tablet() { - val progress = gson.fromJson<ScienceProgress>(TABLET_STR) + val progress = Json.decodeFromString<ScienceProgress>(TABLET_STR) assertNotNull(progress.science) assertEquals(0, progress.science.getQuantity(ScienceType.COMPASS)) assertEquals(0, progress.science.getQuantity(ScienceType.WHEEL)) @@ -147,7 +139,7 @@ class ScienceProgressSerializerTest { @Test fun deserialize_joker() { - val progress = gson.fromJson<ScienceProgress>(JOKER_STR) + val progress = Json.decodeFromString<ScienceProgress>(JOKER_STR) assertNotNull(progress.science) assertEquals(0, progress.science.getQuantity(ScienceType.COMPASS)) assertEquals(0, progress.science.getQuantity(ScienceType.WHEEL)) |