From c23f3aa3f1128fab012474e60dd6c986cd433266 Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Thu, 8 Aug 2024 19:55:49 -0400 Subject: [PATCH 1/8] feat: add helpers to run banner auctions --- .../topsort/analytics/banners/BannerConfig.kt | 82 +++++++++++++++++ .../analytics/banners/BannerResponse.kt | 18 ++++ .../java/com/topsort/analytics/banners/run.kt | 87 +++++++++++++++++++ .../model/auctions/AuctionResponse.kt | 57 +++++++++--- 4 files changed, 230 insertions(+), 14 deletions(-) create mode 100644 TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt create mode 100644 TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt create mode 100644 TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt new file mode 100644 index 0000000..1feb79e --- /dev/null +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt @@ -0,0 +1,82 @@ +package com.topsort.analytics.banners + +/** + * Class that handles different type of Banner configurations + */ +sealed class BannerConfig private constructor() { + + /** + * Banner configuration for landing page banners + * + * @property slotId id of the banner slot + * @property ids ids of the entities that are competing for the banner + * @property device can be "desktop" or "mobile" + * @property geoTargeting optional location for geo-targeted banners + */ + data class LandingPage( + val slotId: String, + val ids: List, + val device: String? = null, + val geoTargeting: String? = null + ) : BannerConfig() + + /** + * Banner configuration for single category banners + * + * @property slotId id of the banner slot + * @property category category for the banner + * @property device can be "desktop" or "mobile" + * @property geoTargeting optional location for geo-targeted banners + */ + data class CategorySingle( + val slotId: String, + val category: String, + val device: String? = null, + val geoTargeting: String? = null + ) : BannerConfig() + + /** + * Banner config for multiple category banners + * + * @property slotId id of the banner slot + * @property categories list of categories for the competing banners + * @property device can be "desktop" or "mobile" + * @property geoTargeting optional location for geo-targeted banners + */ + data class CategoryMultiple( + val slotId: String, + val categories: List, + val device: String? = null, + val geoTargeting: String? = null, + ) : BannerConfig() + + /** + * Banner configuration for category disjunctions banners + * + * @property slotId id of the banner slot + * @property disjunctions category disjunctions for the competing banners + * @property device can be "desktop" or "mobile" + * @property geoTargeting optional location for geo-targeted banners + */ + data class CategoryDisjunctions( + val slotId: String, + val disjunctions: List>, + val device: String? = null, + val geoTargeting: String? = null, + ) : BannerConfig() + + /** + * Banner configuration for keyword banners + * + * @property slotId id of the banner slot + * @property keyword keyword for the competing banners + * @property device can be "desktop" or "mobile" + * @property geoTargeting optional location for geo-targeted banners + */ + data class Keyword( + val slotId: String, + val keyword: String, + val device: String? = null, + val geoTargeting: String? = null, + ) : BannerConfig() +} \ No newline at end of file diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt new file mode 100644 index 0000000..096c020 --- /dev/null +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt @@ -0,0 +1,18 @@ +package com.topsort.analytics.banners + +import com.topsort.analytics.model.auctions.EntityType + +/** + * Response for a single slot banner auction + * + * @property id id of the winning entity + * @property type type of the winning entity + * @property url url of the banner to show + * @property resolvedBidId id for tracking the auction result on events + */ +data class BannerResponse( + val id: String, + val type: EntityType, + val url: String, + val resolvedBidId: String, +) {} \ No newline at end of file diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt new file mode 100644 index 0000000..8570923 --- /dev/null +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt @@ -0,0 +1,87 @@ +package com.topsort.analytics.banners + +import com.topsort.analytics.model.auctions.Auction +import com.topsort.analytics.model.auctions.AuctionRequest +import com.topsort.analytics.service.TopsortAuctionsHttpService + +/** + * Run a banner auction with a single slot + * + * @param config the banner configuration that specifies which kind of banner auction to run + * @return A BannerResponse if the auction successfully returned a winner or null if not. + */ +fun runBannerAuction(config: BannerConfig): BannerResponse? { + val auction = buildBannerAuction(config) + val request = AuctionRequest(listOf(auction)) + val response = TopsortAuctionsHttpService.runAuctions(request) + if ((response?.results?.isNotEmpty() == true)) { + if (response.results[0].winners.isNotEmpty()) { + val winner = response.results[0].winners[0] + return BannerResponse( + id = winner.id, + url = winner.asset!!.url, + type = winner.type, + resolvedBidId = winner.resolvedBidId + ) + } + } + return null +} + +/** + * Builds a low-leve Auction object to be run with TopsortAuctionHttpService. + * + * Generally, you shouldn't be calling this function yourself and you should use runBannerAuction instead. + * + * @param config the banner configuration that specifies which kind of banner auction to run + * @return an Auction object + */ +fun buildBannerAuction(config: BannerConfig): Auction { + when (config) { + is BannerConfig.LandingPage -> { + return Auction.Factory.buildBannerAuctionLandingPage( + 1, + config.slotId, + config.ids, + config.device, + config.geoTargeting + ) + } + + is BannerConfig.CategorySingle -> { + return Auction.Factory.buildBannerAuctionCategorySingle( + 1, + config.slotId, + config.category, + config.device, + config.geoTargeting + ) + } + + is BannerConfig.CategoryMultiple -> { + return Auction.Factory.buildBannerAuctionCategoryMultiple( + 1, + config.slotId, + config.categories, + config.device, + config.geoTargeting + ) + } + + is BannerConfig.CategoryDisjunctions -> { + return Auction.Factory.buildBannerAuctionCategoryDisjunctions( + 1, config.slotId, config.disjunctions, config.device, config.geoTargeting + ) + } + + is BannerConfig.Keyword -> { + return Auction.Factory.buildBannerAuctionKeywords( + 1, + config.slotId, + config.keyword, + config.device, + config.geoTargeting + ) + } + } +} \ No newline at end of file diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt index 3f34d01..fafbe9e 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt @@ -3,11 +3,11 @@ package com.topsort.analytics.model.auctions import org.json.JSONObject data class AuctionResponse private constructor( - val results : List? = null, + val results: List, ) { companion object { fun fromJson(json: String?): AuctionResponse? { - if(json == null) return null + if (json == null) return null val array = JSONObject(json).getJSONArray("results") val results = (0 until array.length()).map { AuctionResponseItem.fromJsonObject(array.getJSONObject(it)) @@ -20,11 +20,11 @@ data class AuctionResponse private constructor( } data class AuctionResponseItem( - val resultType : String, - val winners : List? = null, + val resultType: String, + val winners: List, val error: Boolean, ) { - companion object{ + companion object { fun fromJsonObject(json: JSONObject): AuctionResponseItem { val array = json.getJSONArray("winners") val winners = (0 until array.length()).map { @@ -40,20 +40,49 @@ data class AuctionResponse private constructor( } data class AuctionWinnerItem( - val rank : Int, - val type : String, - val id : String, + val rank: Int, + val type: EntityType, + val id: String, val resolvedBidId: String, - ){ - companion object{ + val asset: Asset? = null, + ) { + companion object { fun fromJsonObject(json: JSONObject): AuctionWinnerItem { return AuctionWinnerItem( - rank = json.getInt("rank"), - type = json.getString("type"), - id = json.getString("id"), - resolvedBidId = json.getString("resolvedBidId"), + rank = json.getInt("rank"), + type = EntityType.fromValue(json.getString("type")), + id = json.getString("id"), + resolvedBidId = json.getString("resolvedBidId"), + asset = Asset.fromJsonObject(json), ) } } } + + data class Asset(val url: String) { + companion object { + fun fromJsonObject(json: JSONObject): Asset? { + val asset = json.optJSONObject("asset") ?: return null + val url = asset.getString("url") + return Asset(url = url) + } + } + } +} + +enum class EntityType { + PRODUCT, + VENDOR, + BRAND, + URL; + + companion object { + fun fromValue(value: String): EntityType = when (value) { + "product" -> PRODUCT + "vendor" -> VENDOR + "brand" -> BRAND + "url" -> URL + else -> throw IllegalArgumentException() + } + } } From 9627f0ffb50252c1ffd816028b780edced39f520 Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Thu, 8 Aug 2024 20:01:58 -0400 Subject: [PATCH 2/8] add exception reason --- .../com/topsort/analytics/model/auctions/AuctionResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt index fafbe9e..892a7f3 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt @@ -82,7 +82,7 @@ enum class EntityType { "vendor" -> VENDOR "brand" -> BRAND "url" -> URL - else -> throw IllegalArgumentException() + else -> throw IllegalArgumentException("not valid entity type: $value") } } } From 84a7c0b01593609b7bae5a11a8875f49f9d3607d Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Thu, 8 Aug 2024 20:03:11 -0400 Subject: [PATCH 3/8] remove empty body --- .../main/java/com/topsort/analytics/banners/BannerResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt index 096c020..4f75eb6 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerResponse.kt @@ -15,4 +15,4 @@ data class BannerResponse( val type: EntityType, val url: String, val resolvedBidId: String, -) {} \ No newline at end of file +) \ No newline at end of file From 10e3966ac739a6666b77c4915e3971fab5170b05 Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Fri, 9 Aug 2024 12:47:46 -0400 Subject: [PATCH 4/8] use device as en enum and default to mobile --- .../topsort/analytics/banners/BannerConfig.kt | 22 +++--- .../analytics/model/auctions/Auction.kt | 68 +++++++++---------- .../model/auctions/AuctionResponse.kt | 16 ----- .../analytics/model/auctions/Device.kt | 6 ++ .../analytics/model/auctions/EntityType.kt | 18 +++++ 5 files changed, 70 insertions(+), 60 deletions(-) create mode 100644 TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt create mode 100644 TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/EntityType.kt diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt index 1feb79e..681722e 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt @@ -1,5 +1,7 @@ package com.topsort.analytics.banners +import com.topsort.analytics.model.auctions.Device + /** * Class that handles different type of Banner configurations */ @@ -10,13 +12,13 @@ sealed class BannerConfig private constructor() { * * @property slotId id of the banner slot * @property ids ids of the entities that are competing for the banner - * @property device can be "desktop" or "mobile" + * @property device target device for the banner * @property geoTargeting optional location for geo-targeted banners */ data class LandingPage( val slotId: String, val ids: List, - val device: String? = null, + val device: Device = Device.MOBILE, val geoTargeting: String? = null ) : BannerConfig() @@ -25,13 +27,13 @@ sealed class BannerConfig private constructor() { * * @property slotId id of the banner slot * @property category category for the banner - * @property device can be "desktop" or "mobile" + * @property device target device for the banner * @property geoTargeting optional location for geo-targeted banners */ data class CategorySingle( val slotId: String, val category: String, - val device: String? = null, + val device: Device = Device.MOBILE, val geoTargeting: String? = null ) : BannerConfig() @@ -40,13 +42,13 @@ sealed class BannerConfig private constructor() { * * @property slotId id of the banner slot * @property categories list of categories for the competing banners - * @property device can be "desktop" or "mobile" + * @property device target device for the banner * @property geoTargeting optional location for geo-targeted banners */ data class CategoryMultiple( val slotId: String, val categories: List, - val device: String? = null, + val device: Device = Device.MOBILE, val geoTargeting: String? = null, ) : BannerConfig() @@ -55,13 +57,13 @@ sealed class BannerConfig private constructor() { * * @property slotId id of the banner slot * @property disjunctions category disjunctions for the competing banners - * @property device can be "desktop" or "mobile" + * @property device target device for the banner * @property geoTargeting optional location for geo-targeted banners */ data class CategoryDisjunctions( val slotId: String, val disjunctions: List>, - val device: String? = null, + val device: Device = Device.MOBILE, val geoTargeting: String? = null, ) : BannerConfig() @@ -70,13 +72,13 @@ sealed class BannerConfig private constructor() { * * @property slotId id of the banner slot * @property keyword keyword for the competing banners - * @property device can be "desktop" or "mobile" + * @property device target device for the banner * @property geoTargeting optional location for geo-targeted banners */ data class Keyword( val slotId: String, val keyword: String, - val device: String? = null, + val device: Device = Device.MOBILE, val geoTargeting: String? = null, ) : BannerConfig() } \ No newline at end of file diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt index 59af3af..0a27762 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt @@ -1,6 +1,6 @@ package com.topsort.analytics.model.auctions -data class Auction private constructor ( +data class Auction private constructor( val type: String, val slots: Int, val products: Products? = null, @@ -8,17 +8,17 @@ data class Auction private constructor ( val searchQuery: String? = null, val geoTargeting: GeoTargeting? = null, val slotId: String? = null, - val device: String? = null, + val device: Device? = null, ) { - object Factory{ + object Factory { @JvmOverloads fun buildSponsoredListingAuctionProductIds( - slots : Int, + slots: Int, ids: List, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "listings", slots = slots, @@ -29,10 +29,10 @@ data class Auction private constructor ( @JvmOverloads fun buildSponsoredListingAuctionCategorySingle( - slots : Int, + slots: Int, category: String, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "listings", slots = slots, @@ -43,10 +43,10 @@ data class Auction private constructor ( @JvmOverloads fun buildSponsoredListingAuctionCategoryMultiple( - slots : Int, + slots: Int, categories: List, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "listings", slots = slots, @@ -57,10 +57,10 @@ data class Auction private constructor ( @JvmOverloads fun buildSponsoredListingAuctionCategoryDisjunctions( - slots : Int, + slots: Int, disjunctions: List>, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "listings", slots = slots, @@ -71,10 +71,10 @@ data class Auction private constructor ( @JvmOverloads fun buildSponsoredListingAuctionKeyword( - slots : Int, + slots: Int, keyword: String, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "listings", slots = slots, @@ -85,12 +85,12 @@ data class Auction private constructor ( @JvmOverloads fun buildBannerAuctionLandingPage( - slots : Int, - slotId : String, + slots: Int, + slotId: String, ids: List, - device: String? = null, + device: Device = Device.MOBILE, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "banners", slots = slots, @@ -103,12 +103,12 @@ data class Auction private constructor ( @JvmOverloads fun buildBannerAuctionCategorySingle( - slots : Int, - slotId : String, + slots: Int, + slotId: String, category: String, - device: String? = null, + device: Device = Device.MOBILE, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "banners", slots = slots, @@ -121,12 +121,12 @@ data class Auction private constructor ( @JvmOverloads fun buildBannerAuctionCategoryMultiple( - slots : Int, - slotId : String, + slots: Int, + slotId: String, categories: List, - device: String? = null, + device: Device = Device.MOBILE, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "banners", slots = slots, @@ -139,12 +139,12 @@ data class Auction private constructor ( @JvmOverloads fun buildBannerAuctionCategoryDisjunctions( - slots : Int, - slotId : String, + slots: Int, + slotId: String, disjunctions: List>, - device: String? = null, + device: Device = Device.MOBILE, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "banners", slots = slots, @@ -157,12 +157,12 @@ data class Auction private constructor ( @JvmOverloads fun buildBannerAuctionKeywords( - slots : Int, - slotId : String, + slots: Int, + slotId: String, keyword: String, - device: String? = null, + device: Device = Device.MOBILE, geoTargeting: String? = null, - ) : Auction { + ): Auction { return Auction( type = "banners", slots = slots, @@ -174,7 +174,7 @@ data class Auction private constructor ( } } - data class Products ( + data class Products( val ids: List, ) diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt index 892a7f3..cdc3c9e 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/AuctionResponse.kt @@ -70,19 +70,3 @@ data class AuctionResponse private constructor( } } -enum class EntityType { - PRODUCT, - VENDOR, - BRAND, - URL; - - companion object { - fun fromValue(value: String): EntityType = when (value) { - "product" -> PRODUCT - "vendor" -> VENDOR - "brand" -> BRAND - "url" -> URL - else -> throw IllegalArgumentException("not valid entity type: $value") - } - } -} diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt new file mode 100644 index 0000000..97ef8c3 --- /dev/null +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt @@ -0,0 +1,6 @@ +package com.topsort.analytics.model.auctions + +enum class Device { + DESKTOP, + MOBILE +} \ No newline at end of file diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/EntityType.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/EntityType.kt new file mode 100644 index 0000000..2161bfc --- /dev/null +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/EntityType.kt @@ -0,0 +1,18 @@ +package com.topsort.analytics.model.auctions + +enum class EntityType { + PRODUCT, + VENDOR, + BRAND, + URL; + + companion object { + fun fromValue(value: String): EntityType = when (value) { + "product" -> PRODUCT + "vendor" -> VENDOR + "brand" -> BRAND + "url" -> URL + else -> throw IllegalArgumentException("not valid entity type: $value") + } + } +} From 2e06e97678fa1b09c9d462a9089dc11b93538a6c Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Mon, 12 Aug 2024 19:23:21 -0400 Subject: [PATCH 5/8] add tests --- .../java/com/topsort/analytics/banners/run.kt | 2 +- .../com/topsort/analytics/banners/runTest.kt | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 TopsortAnalytics/src/test/java/com/topsort/analytics/banners/runTest.kt diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt index 8570923..fa0fc06 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/run.kt @@ -29,7 +29,7 @@ fun runBannerAuction(config: BannerConfig): BannerResponse? { } /** - * Builds a low-leve Auction object to be run with TopsortAuctionHttpService. + * Builds a low-level Auction object to be run with TopsortAuctionHttpService. * * Generally, you shouldn't be calling this function yourself and you should use runBannerAuction instead. * diff --git a/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/runTest.kt b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/runTest.kt new file mode 100644 index 0000000..5f3176a --- /dev/null +++ b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/runTest.kt @@ -0,0 +1,56 @@ +package com.topsort.analytics.banners + +import org.assertj.core.api.Assertions.assertThat +import org.json.JSONObject +import org.junit.Test + +internal class RunTest { + @Test + fun buildLandingPageBanner() { + val slot = "slot" + val ids = listOf("id1", "id2") + val bannerConfig = BannerConfig.LandingPage(slotId = slot, ids = ids) + val bannerAuction = buildBannerAuction(bannerConfig); + val json = JSONObject.wrap(bannerAuction)!!.toString() + val expectedJson = + "{\"slots\":1,\"slotId\":\"$slot\",\"type\":\"banners\",\"device\":\"mobile\",\"products\":{\"ids\":[\"${ids[0]}\",\"${ids[1]}\"]}}" + assertThat(json).isEqualTo(expectedJson) + } + + @Test + fun buildSingleCategoryBanner() { + val slot = "slot" + val category = "category" + val bannerConfig = BannerConfig.CategorySingle(slotId = slot, category = category) + val bannerAuction = buildBannerAuction(bannerConfig); + val json = JSONObject.wrap(bannerAuction)!!.toString() + val expectedJson = + "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"id\":\"$category\"},\"type\":\"banners\",\"device\":\"mobile\"}}" + assertThat(json).isEqualTo(expectedJson) + } + + @Test + fun buildMultipleCategoryBanner() { + val slot = "slot" + val categories = listOf("cat1", "cat2") + val bannerConfig = BannerConfig.CategoryMultiple(slotId = slot, categories = categories) + val bannerAuction = buildBannerAuction(bannerConfig); + val json = JSONObject.wrap(bannerAuction)!!.toString() + val expectedJson = + "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"ids\":[\"${categories[0]}\",\"${categories[1]}\"]},\"type\":\"banners\",\"device\":\"mobile\"}}" + assertThat(json).isEqualTo(expectedJson) + } + + @Test + fun buildDisjuctionsCategoryBanner() { + val slot = "slot" + val disjunctions = listOf(listOf("cat1", "cat2"), listOf("cat3")) + val bannerConfig = + BannerConfig.CategoryDisjunctions(slotId = slot, disjunctions = disjunctions) + val bannerAuction = buildBannerAuction(bannerConfig); + val json = JSONObject.wrap(bannerAuction)!!.toString() + val expectedJson = + "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"disjunctions\":[[\"${disjunctions[0][0]}\",\"${disjunctions[0][1]}\"],[\"${disjunctions[1][0]}\"]]},\"type\":\"banners\",\"device\":\"mobile\"}}" + assertThat(json).isEqualTo(expectedJson) + } +} \ No newline at end of file From cbbd05b0da6a0a8dac734279ba6b3ca28a7a7081 Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Mon, 12 Aug 2024 19:25:06 -0400 Subject: [PATCH 6/8] rename test file --- .../java/com/topsort/analytics/banners/{runTest.kt => RunTest.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename TopsortAnalytics/src/test/java/com/topsort/analytics/banners/{runTest.kt => RunTest.kt} (100%) diff --git a/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/runTest.kt b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt similarity index 100% rename from TopsortAnalytics/src/test/java/com/topsort/analytics/banners/runTest.kt rename to TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt From ec95e0499e8f4e6dbbc35ab067604c8f032595ff Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Tue, 13 Aug 2024 11:18:44 -0400 Subject: [PATCH 7/8] use lowercase for device fields and fix tests --- .../java/com/topsort/analytics/banners/BannerConfig.kt | 10 +++++----- .../com/topsort/analytics/model/auctions/Auction.kt | 10 +++++----- .../com/topsort/analytics/model/auctions/Device.kt | 5 +++-- .../test/java/com/topsort/analytics/banners/RunTest.kt | 6 +++--- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt index 681722e..4170c1d 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/banners/BannerConfig.kt @@ -18,7 +18,7 @@ sealed class BannerConfig private constructor() { data class LandingPage( val slotId: String, val ids: List, - val device: Device = Device.MOBILE, + val device: Device = Device.mobile, val geoTargeting: String? = null ) : BannerConfig() @@ -33,7 +33,7 @@ sealed class BannerConfig private constructor() { data class CategorySingle( val slotId: String, val category: String, - val device: Device = Device.MOBILE, + val device: Device = Device.mobile, val geoTargeting: String? = null ) : BannerConfig() @@ -48,7 +48,7 @@ sealed class BannerConfig private constructor() { data class CategoryMultiple( val slotId: String, val categories: List, - val device: Device = Device.MOBILE, + val device: Device = Device.mobile, val geoTargeting: String? = null, ) : BannerConfig() @@ -63,7 +63,7 @@ sealed class BannerConfig private constructor() { data class CategoryDisjunctions( val slotId: String, val disjunctions: List>, - val device: Device = Device.MOBILE, + val device: Device = Device.mobile, val geoTargeting: String? = null, ) : BannerConfig() @@ -78,7 +78,7 @@ sealed class BannerConfig private constructor() { data class Keyword( val slotId: String, val keyword: String, - val device: Device = Device.MOBILE, + val device: Device = Device.mobile, val geoTargeting: String? = null, ) : BannerConfig() } \ No newline at end of file diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt index 0a27762..7babc7f 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Auction.kt @@ -88,7 +88,7 @@ data class Auction private constructor( slots: Int, slotId: String, ids: List, - device: Device = Device.MOBILE, + device: Device = Device.mobile, geoTargeting: String? = null, ): Auction { return Auction( @@ -106,7 +106,7 @@ data class Auction private constructor( slots: Int, slotId: String, category: String, - device: Device = Device.MOBILE, + device: Device = Device.mobile, geoTargeting: String? = null, ): Auction { return Auction( @@ -124,7 +124,7 @@ data class Auction private constructor( slots: Int, slotId: String, categories: List, - device: Device = Device.MOBILE, + device: Device = Device.mobile, geoTargeting: String? = null, ): Auction { return Auction( @@ -142,7 +142,7 @@ data class Auction private constructor( slots: Int, slotId: String, disjunctions: List>, - device: Device = Device.MOBILE, + device: Device = Device.mobile, geoTargeting: String? = null, ): Auction { return Auction( @@ -160,7 +160,7 @@ data class Auction private constructor( slots: Int, slotId: String, keyword: String, - device: Device = Device.MOBILE, + device: Device = Device.mobile, geoTargeting: String? = null, ): Auction { return Auction( diff --git a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt index 97ef8c3..e80aec8 100644 --- a/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt +++ b/TopsortAnalytics/src/main/java/com/topsort/analytics/model/auctions/Device.kt @@ -1,6 +1,7 @@ package com.topsort.analytics.model.auctions +@Suppress("EnumNaming") enum class Device { - DESKTOP, - MOBILE + desktop, + mobile } \ No newline at end of file diff --git a/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt index 5f3176a..74131aa 100644 --- a/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt +++ b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt @@ -25,7 +25,7 @@ internal class RunTest { val bannerAuction = buildBannerAuction(bannerConfig); val json = JSONObject.wrap(bannerAuction)!!.toString() val expectedJson = - "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"id\":\"$category\"},\"type\":\"banners\",\"device\":\"mobile\"}}" + "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"id\":\"$category\"},\"type\":\"banners\",\"device\":\"mobile\"}" assertThat(json).isEqualTo(expectedJson) } @@ -37,7 +37,7 @@ internal class RunTest { val bannerAuction = buildBannerAuction(bannerConfig); val json = JSONObject.wrap(bannerAuction)!!.toString() val expectedJson = - "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"ids\":[\"${categories[0]}\",\"${categories[1]}\"]},\"type\":\"banners\",\"device\":\"mobile\"}}" + "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"ids\":[\"${categories[0]}\",\"${categories[1]}\"]},\"type\":\"banners\",\"device\":\"mobile\"}" assertThat(json).isEqualTo(expectedJson) } @@ -50,7 +50,7 @@ internal class RunTest { val bannerAuction = buildBannerAuction(bannerConfig); val json = JSONObject.wrap(bannerAuction)!!.toString() val expectedJson = - "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"disjunctions\":[[\"${disjunctions[0][0]}\",\"${disjunctions[0][1]}\"],[\"${disjunctions[1][0]}\"]]},\"type\":\"banners\",\"device\":\"mobile\"}}" + "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"disjunctions\":[[\"${disjunctions[0][0]}\",\"${disjunctions[0][1]}\"],[\"${disjunctions[1][0]}\"]]},\"type\":\"banners\",\"device\":\"mobile\"}" assertThat(json).isEqualTo(expectedJson) } } \ No newline at end of file From 814895f9524d5fe1eb4433a574b6d32bf4f3b610 Mon Sep 17 00:00:00 2001 From: Felipe Contreras-Salinas Date: Tue, 13 Aug 2024 11:28:56 -0400 Subject: [PATCH 8/8] fix tests --- .../src/test/java/com/topsort/analytics/banners/RunTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt index 74131aa..28b013e 100644 --- a/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt +++ b/TopsortAnalytics/src/test/java/com/topsort/analytics/banners/RunTest.kt @@ -25,7 +25,7 @@ internal class RunTest { val bannerAuction = buildBannerAuction(bannerConfig); val json = JSONObject.wrap(bannerAuction)!!.toString() val expectedJson = - "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"id\":\"$category\"},\"type\":\"banners\",\"device\":\"mobile\"}" + "{\"slots\":1,\"slotId\":\"$slot\",\"type\":\"banners\",\"category\":{\"id\":\"$category\"},\"device\":\"mobile\"}" assertThat(json).isEqualTo(expectedJson) } @@ -37,7 +37,7 @@ internal class RunTest { val bannerAuction = buildBannerAuction(bannerConfig); val json = JSONObject.wrap(bannerAuction)!!.toString() val expectedJson = - "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"ids\":[\"${categories[0]}\",\"${categories[1]}\"]},\"type\":\"banners\",\"device\":\"mobile\"}" + "{\"slots\":1,\"slotId\":\"$slot\",\"type\":\"banners\",\"category\":{\"ids\":[\"${categories[0]}\",\"${categories[1]}\"]},\"device\":\"mobile\"}" assertThat(json).isEqualTo(expectedJson) } @@ -50,7 +50,7 @@ internal class RunTest { val bannerAuction = buildBannerAuction(bannerConfig); val json = JSONObject.wrap(bannerAuction)!!.toString() val expectedJson = - "{\"slots\":1,\"slotId\":\"$slot\",\"category\":{\"disjunctions\":[[\"${disjunctions[0][0]}\",\"${disjunctions[0][1]}\"],[\"${disjunctions[1][0]}\"]]},\"type\":\"banners\",\"device\":\"mobile\"}" + "{\"slots\":1,\"slotId\":\"$slot\",\"type\":\"banners\",\"category\":{\"disjunctions\":[[\"${disjunctions[0][0]}\",\"${disjunctions[0][1]}\"],[\"${disjunctions[1][0]}\"]]},\"device\":\"mobile\"}" assertThat(json).isEqualTo(expectedJson) } } \ No newline at end of file