diff options
17 files changed, 26 insertions, 25 deletions
diff --git a/api/src/main/java/market/guess/api/MarketStateDTO.java b/api/src/main/java/market/guess/api/MarketStateDTO.java index 1f7e79b..da2fff0 100644 --- a/api/src/main/java/market/guess/api/MarketStateDTO.java +++ b/api/src/main/java/market/guess/api/MarketStateDTO.java | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | package market.guess.api; | 1 | package market.guess.api; |
| 2 | 2 | ||
| 3 | import java.util.List; | 3 | import java.util.List; |
| 4 | import market.guess.model.event.MechanismType; | ||
| 4 | 5 | ||
| 5 | public record MarketStateDTO( | 6 | public record MarketStateDTO( |
| 6 | String eventKey, | 7 | String eventKey, |
diff --git a/api/src/main/java/market/guess/api/CommissionTiming.java b/api/src/main/java/market/guess/model/event/CommissionTiming.java index 29861e3..fff8b6b 100644 --- a/api/src/main/java/market/guess/api/CommissionTiming.java +++ b/api/src/main/java/market/guess/model/event/CommissionTiming.java | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | package market.guess.api; | 1 | package market.guess.model.event; |
| 2 | 2 | ||
| 3 | public enum CommissionTiming { | 3 | public enum CommissionTiming { |
| 4 | ON_CLOSE, | 4 | ON_CLOSE, |
diff --git a/api/src/main/java/market/guess/model/event/EventSummaryDTO.java b/api/src/main/java/market/guess/model/event/EventSummaryDTO.java index 1595f81..42762c2 100644 --- a/api/src/main/java/market/guess/model/event/EventSummaryDTO.java +++ b/api/src/main/java/market/guess/model/event/EventSummaryDTO.java | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | package market.guess.model.event; | 1 | package market.guess.model.event; |
| 2 | 2 | ||
| 3 | import java.util.List; | 3 | import java.util.List; |
| 4 | import market.guess.api.CommissionTiming; | ||
| 5 | import market.guess.api.MechanismType; | ||
| 6 | 4 | ||
| 7 | public record EventSummaryDTO( | 5 | public record EventSummaryDTO( |
| 8 | String key, | 6 | String key, |
diff --git a/api/src/main/java/market/guess/api/MechanismType.java b/api/src/main/java/market/guess/model/event/MechanismType.java index f478041..6063881 100644 --- a/api/src/main/java/market/guess/api/MechanismType.java +++ b/api/src/main/java/market/guess/model/event/MechanismType.java | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | package market.guess.api; | 1 | package market.guess.model.event; |
| 2 | 2 | ||
| 3 | public enum MechanismType { | 3 | public enum MechanismType { |
| 4 | LMSR, | 4 | LMSR, |
diff --git a/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/EventDeserializer.java b/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/EventDeserializer.java index 69a8447..e40d633 100644 --- a/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/EventDeserializer.java +++ b/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/EventDeserializer.java | |||
| @@ -7,7 +7,7 @@ import com.google.gson.JsonParseException; | |||
| 7 | import com.google.gson.reflect.TypeToken; | 7 | import com.google.gson.reflect.TypeToken; |
| 8 | import java.lang.reflect.Type; | 8 | import java.lang.reflect.Type; |
| 9 | import java.util.List; | 9 | import java.util.List; |
| 10 | import market.guess.api.CommissionTiming; | 10 | import market.guess.model.event.CommissionTiming; |
| 11 | import market.guess.model.event.EventStatus; | 11 | import market.guess.model.event.EventStatus; |
| 12 | import market.guess.service.domain.Event; | 12 | import market.guess.service.domain.Event; |
| 13 | import market.guess.service.domain.Market; | 13 | import market.guess.service.domain.Market; |
| @@ -45,7 +45,9 @@ public final class EventDeserializer implements JsonDeserializer<Event> { | |||
| 45 | obj.get("runningId").getAsInt(), | 45 | obj.get("runningId").getAsInt(), |
| 46 | trades, | 46 | trades, |
| 47 | context.deserialize(obj.get("state"), EventStatus.class), | 47 | context.deserialize(obj.get("state"), EventStatus.class), |
| 48 | winningOptionKey == null || winningOptionKey.isJsonNull() ? null : winningOptionKey.getAsString(), | 48 | winningOptionKey == null || winningOptionKey.isJsonNull() |
| 49 | ? null | ||
| 50 | : winningOptionKey.getAsString(), | ||
| 49 | obj.get("settlementCommission").getAsBigDecimal()); | 51 | obj.get("settlementCommission").getAsBigDecimal()); |
| 50 | } | 52 | } |
| 51 | } | 53 | } |
diff --git a/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/TradingMechanismAdapter.java b/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/TradingMechanismAdapter.java index ac3da8b..1fa2b9a 100644 --- a/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/TradingMechanismAdapter.java +++ b/service/src/main/java/market/guess/service/catalog/infrastructure/adapter/TradingMechanismAdapter.java | |||
| @@ -7,14 +7,14 @@ import com.google.gson.JsonParseException; | |||
| 7 | import com.google.gson.JsonSerializationContext; | 7 | import com.google.gson.JsonSerializationContext; |
| 8 | import com.google.gson.JsonSerializer; | 8 | import com.google.gson.JsonSerializer; |
| 9 | import java.lang.reflect.Type; | 9 | import java.lang.reflect.Type; |
| 10 | import market.guess.api.MechanismType; | 10 | import market.guess.model.event.MechanismType; |
| 11 | import market.guess.service.mechanism.LmsrTradingMechanism; | 11 | import market.guess.service.mechanism.LmsrTradingMechanism; |
| 12 | import market.guess.service.mechanism.OrderBookTradingMechanism; | 12 | import market.guess.service.mechanism.OrderBookTradingMechanism; |
| 13 | import market.guess.service.mechanism.TradingMechanism; | 13 | import market.guess.service.mechanism.TradingMechanism; |
| 14 | 14 | ||
| 15 | /** | 15 | /** |
| 16 | * TradingMechanism is a sealed interface, so Gson can't tell which implementation to build from | 16 | * TradingMechanism is a sealed interface, so Gson can't tell which implementation to build from the |
| 17 | * the JSON alone; this tags the JSON with a type discriminator and dispatches on it. | 17 | * JSON alone; this tags the JSON with a type discriminator and dispatches on it. |
| 18 | */ | 18 | */ |
| 19 | public final class TradingMechanismAdapter | 19 | public final class TradingMechanismAdapter |
| 20 | implements JsonSerializer<TradingMechanism>, JsonDeserializer<TradingMechanism> { | 20 | implements JsonSerializer<TradingMechanism>, JsonDeserializer<TradingMechanism> { |
diff --git a/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v1/EventMapperV1.java b/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v1/EventMapperV1.java index b9c43bb..fa1c5ab 100644 --- a/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v1/EventMapperV1.java +++ b/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v1/EventMapperV1.java | |||
| @@ -2,7 +2,7 @@ package market.guess.service.catalog.infrastructure.mapper.v1; | |||
| 2 | 2 | ||
| 3 | import java.util.ArrayList; | 3 | import java.util.ArrayList; |
| 4 | import java.util.List; | 4 | import java.util.List; |
| 5 | import market.guess.api.CommissionTiming; | 5 | import market.guess.model.event.CommissionTiming; |
| 6 | import market.guess.model.event.EventStatus; | 6 | import market.guess.model.event.EventStatus; |
| 7 | import market.guess.service.catalog.infrastructure.mapper.Mapper; | 7 | import market.guess.service.catalog.infrastructure.mapper.Mapper; |
| 8 | import market.guess.service.catalog.model.v1.GMEvent; | 8 | import market.guess.service.catalog.model.v1.GMEvent; |
diff --git a/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v2/EventMapperV2.java b/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v2/EventMapperV2.java index 82455f1..bcdce94 100644 --- a/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v2/EventMapperV2.java +++ b/service/src/main/java/market/guess/service/catalog/infrastructure/mapper/v2/EventMapperV2.java | |||
| @@ -2,7 +2,7 @@ package market.guess.service.catalog.infrastructure.mapper.v2; | |||
| 2 | 2 | ||
| 3 | import java.util.ArrayList; | 3 | import java.util.ArrayList; |
| 4 | import java.util.List; | 4 | import java.util.List; |
| 5 | import market.guess.api.CommissionTiming; | 5 | import market.guess.model.event.CommissionTiming; |
| 6 | import market.guess.model.event.EventStatus; | 6 | import market.guess.model.event.EventStatus; |
| 7 | import market.guess.service.catalog.infrastructure.mapper.Mapper; | 7 | import market.guess.service.catalog.infrastructure.mapper.Mapper; |
| 8 | import market.guess.service.catalog.model.v2.GMEvent; | 8 | import market.guess.service.catalog.model.v2.GMEvent; |
diff --git a/service/src/main/java/market/guess/service/domain/Event.java b/service/src/main/java/market/guess/service/domain/Event.java index e1b366e..1e17457 100644 --- a/service/src/main/java/market/guess/service/domain/Event.java +++ b/service/src/main/java/market/guess/service/domain/Event.java | |||
| @@ -4,10 +4,10 @@ import java.math.BigDecimal; | |||
| 4 | import java.time.Instant; | 4 | import java.time.Instant; |
| 5 | import java.util.ArrayList; | 5 | import java.util.ArrayList; |
| 6 | import java.util.List; | 6 | import java.util.List; |
| 7 | import market.guess.api.CommissionTiming; | ||
| 8 | import market.guess.api.MarketDTO; | 7 | import market.guess.api.MarketDTO; |
| 9 | import market.guess.api.MarketStateDTO; | 8 | import market.guess.api.MarketStateDTO; |
| 10 | import market.guess.api.TradeRowDTO; | 9 | import market.guess.api.TradeRowDTO; |
| 10 | import market.guess.model.event.CommissionTiming; | ||
| 11 | import market.guess.model.event.EventStatus; | 11 | import market.guess.model.event.EventStatus; |
| 12 | import market.guess.model.event.EventSummaryDTO; | 12 | import market.guess.model.event.EventSummaryDTO; |
| 13 | import market.guess.model.ledger.LedgerType; | 13 | import market.guess.model.ledger.LedgerType; |
diff --git a/service/src/main/java/market/guess/service/fulfillment/LocalFulfillmentContext.java b/service/src/main/java/market/guess/service/fulfillment/LocalFulfillmentContext.java index cbbfafd..d1006bc 100644 --- a/service/src/main/java/market/guess/service/fulfillment/LocalFulfillmentContext.java +++ b/service/src/main/java/market/guess/service/fulfillment/LocalFulfillmentContext.java | |||
| @@ -3,7 +3,7 @@ package market.guess.service.fulfillment; | |||
| 3 | import java.math.BigDecimal; | 3 | import java.math.BigDecimal; |
| 4 | import java.util.ArrayList; | 4 | import java.util.ArrayList; |
| 5 | import java.util.List; | 5 | import java.util.List; |
| 6 | import market.guess.api.CommissionTiming; | 6 | import market.guess.model.event.CommissionTiming; |
| 7 | import market.guess.model.ledger.LedgerType; | 7 | import market.guess.model.ledger.LedgerType; |
| 8 | import market.guess.service.domain.Order; | 8 | import market.guess.service.domain.Order; |
| 9 | import market.guess.service.domain.Trade; | 9 | import market.guess.service.domain.Trade; |
diff --git a/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java b/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java index 981e733..c133ac7 100644 --- a/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java +++ b/service/src/main/java/market/guess/service/mechanism/LmsrTradingMechanism.java | |||
| @@ -5,7 +5,7 @@ import java.time.Clock; | |||
| 5 | import java.time.Instant; | 5 | import java.time.Instant; |
| 6 | import java.util.Arrays; | 6 | import java.util.Arrays; |
| 7 | import java.util.List; | 7 | import java.util.List; |
| 8 | import market.guess.api.MechanismType; | 8 | import market.guess.model.event.MechanismType; |
| 9 | import market.guess.service.domain.Event; | 9 | import market.guess.service.domain.Event; |
| 10 | import market.guess.service.domain.Market; | 10 | import market.guess.service.domain.Market; |
| 11 | import market.guess.service.domain.Trade; | 11 | import market.guess.service.domain.Trade; |
diff --git a/service/src/main/java/market/guess/service/mechanism/OrderBookTradingMechanism.java b/service/src/main/java/market/guess/service/mechanism/OrderBookTradingMechanism.java index fd03750..ba88d06 100644 --- a/service/src/main/java/market/guess/service/mechanism/OrderBookTradingMechanism.java +++ b/service/src/main/java/market/guess/service/mechanism/OrderBookTradingMechanism.java | |||
| @@ -5,7 +5,7 @@ import java.math.RoundingMode; | |||
| 5 | import java.time.Instant; | 5 | import java.time.Instant; |
| 6 | import java.util.ArrayList; | 6 | import java.util.ArrayList; |
| 7 | import java.util.List; | 7 | import java.util.List; |
| 8 | import market.guess.api.MechanismType; | 8 | import market.guess.model.event.MechanismType; |
| 9 | import market.guess.service.domain.Event; | 9 | import market.guess.service.domain.Event; |
| 10 | import market.guess.service.domain.Market; | 10 | import market.guess.service.domain.Market; |
| 11 | import market.guess.service.domain.Trade; | 11 | import market.guess.service.domain.Trade; |
diff --git a/service/src/main/java/market/guess/service/mechanism/TradingMechanism.java b/service/src/main/java/market/guess/service/mechanism/TradingMechanism.java index 30d076d..90e696d 100644 --- a/service/src/main/java/market/guess/service/mechanism/TradingMechanism.java +++ b/service/src/main/java/market/guess/service/mechanism/TradingMechanism.java | |||
| @@ -3,7 +3,7 @@ package market.guess.service.mechanism; | |||
| 3 | import java.math.BigDecimal; | 3 | import java.math.BigDecimal; |
| 4 | import java.time.Instant; | 4 | import java.time.Instant; |
| 5 | import java.util.List; | 5 | import java.util.List; |
| 6 | import market.guess.api.MechanismType; | 6 | import market.guess.model.event.MechanismType; |
| 7 | import market.guess.service.domain.Event; | 7 | import market.guess.service.domain.Event; |
| 8 | import market.guess.service.domain.Market; | 8 | import market.guess.service.domain.Market; |
| 9 | import market.guess.service.domain.Trade; | 9 | import market.guess.service.domain.Trade; |
diff --git a/service/src/main/java/market/guess/service/settlement/LocalSettlementContext.java b/service/src/main/java/market/guess/service/settlement/LocalSettlementContext.java index f6e9b67..d970b03 100644 --- a/service/src/main/java/market/guess/service/settlement/LocalSettlementContext.java +++ b/service/src/main/java/market/guess/service/settlement/LocalSettlementContext.java | |||
| @@ -2,7 +2,7 @@ package market.guess.service.settlement; | |||
| 2 | 2 | ||
| 3 | import java.math.BigDecimal; | 3 | import java.math.BigDecimal; |
| 4 | import java.util.HashMap; | 4 | import java.util.HashMap; |
| 5 | import market.guess.api.CommissionTiming; | 5 | import market.guess.model.event.CommissionTiming; |
| 6 | import market.guess.model.event.EventStatus; | 6 | import market.guess.model.event.EventStatus; |
| 7 | import market.guess.model.ledger.LedgerType; | 7 | import market.guess.model.ledger.LedgerType; |
| 8 | import market.guess.service.domain.Event; | 8 | import market.guess.service.domain.Event; |
| @@ -20,6 +20,7 @@ public final class LocalSettlementContext implements SettlementContext { | |||
| 20 | public BigDecimal settle(Event event, String winningOptionKey) { | 20 | public BigDecimal settle(Event event, String winningOptionKey) { |
| 21 | event.setWinningOptionKey(winningOptionKey); | 21 | event.setWinningOptionKey(winningOptionKey); |
| 22 | 22 | ||
| 23 | // TODO: abstract the commission charge away | ||
| 23 | var chargeCommission = event.getCommissionTiming() == CommissionTiming.ON_CLOSE; | 24 | var chargeCommission = event.getCommissionTiming() == CommissionTiming.ON_CLOSE; |
| 24 | var rate = BigDecimal.valueOf(event.getCommissionPercent()).divide(BigDecimal.valueOf(100)); | 25 | var rate = BigDecimal.valueOf(event.getCommissionPercent()).divide(BigDecimal.valueOf(100)); |
| 25 | var winningOption = event.getOption(winningOptionKey); | 26 | var winningOption = event.getOption(winningOptionKey); |
| @@ -40,8 +41,7 @@ public final class LocalSettlementContext implements SettlementContext { | |||
| 40 | var net = gross.subtract(commission); | 41 | var net = gross.subtract(commission); |
| 41 | 42 | ||
| 42 | ledger.credit(entry.getKey(), LedgerType.PAYOUT, net, "Payout: " + winningOption.getName()); | 43 | ledger.credit(entry.getKey(), LedgerType.PAYOUT, net, "Payout: " + winningOption.getName()); |
| 43 | ledger.debit( | 44 | ledger.debit(event.getLedger(), LedgerType.PAYOUT, net, "Payout: " + winningOption.getName()); |
| 44 | event.getLedger(), LedgerType.PAYOUT, net, "Payout: " + winningOption.getName()); | ||
| 45 | event.addSettlementCommission(commission); | 45 | event.addSettlementCommission(commission); |
| 46 | totalPayout = totalPayout.add(net); | 46 | totalPayout = totalPayout.add(net); |
| 47 | } | 47 | } |
diff --git a/service/src/test/java/market/guess/service/Ex1FullTest.java b/service/src/test/java/market/guess/service/Ex1FullTest.java index 6718142..38d21c2 100644 --- a/service/src/test/java/market/guess/service/Ex1FullTest.java +++ b/service/src/test/java/market/guess/service/Ex1FullTest.java | |||
| @@ -7,7 +7,7 @@ import java.nio.file.Files; | |||
| 7 | import java.nio.file.Path; | 7 | import java.nio.file.Path; |
| 8 | import java.time.Instant; | 8 | import java.time.Instant; |
| 9 | import java.util.List; | 9 | import java.util.List; |
| 10 | import market.guess.api.CommissionTiming; | 10 | import market.guess.model.event.CommissionTiming; |
| 11 | import market.guess.model.event.EventStatus; | 11 | import market.guess.model.event.EventStatus; |
| 12 | import market.guess.service.catalog.LocalCatalogContext; | 12 | import market.guess.service.catalog.LocalCatalogContext; |
| 13 | import market.guess.service.catalog.infrastructure.MarketContext; | 13 | import market.guess.service.catalog.infrastructure.MarketContext; |
| @@ -18,9 +18,7 @@ import market.guess.service.catalog.infrastructure.repository.InMemoryEventRepos | |||
| 18 | import market.guess.service.catalog.infrastructure.repository.InMemoryUserRepository; | 18 | import market.guess.service.catalog.infrastructure.repository.InMemoryUserRepository; |
| 19 | import market.guess.service.domain.Event; | 19 | import market.guess.service.domain.Event; |
| 20 | import market.guess.service.domain.Market; | 20 | import market.guess.service.domain.Market; |
| 21 | import market.guess.service.domain.User; | ||
| 22 | import market.guess.service.fulfillment.LocalFulfillmentContext; | 21 | import market.guess.service.fulfillment.LocalFulfillmentContext; |
| 23 | import market.guess.service.helpers.BigDecimalOptions; | ||
| 24 | import market.guess.service.ledger.LedgerContext; | 22 | import market.guess.service.ledger.LedgerContext; |
| 25 | import market.guess.service.matching.LocalMatchingEngine; | 23 | import market.guess.service.matching.LocalMatchingEngine; |
| 26 | import market.guess.service.mechanism.LmsrTradingMechanism; | 24 | import market.guess.service.mechanism.LmsrTradingMechanism; |
diff --git a/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java index bdd3eb1..642ad78 100644 --- a/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java +++ b/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | package market.guess.ui.console.command; | 1 | package market.guess.ui.console.command; |
| 2 | 2 | ||
| 3 | import market.guess.api.CatalogContext; | 3 | import market.guess.api.CatalogContext; |
| 4 | import market.guess.model.event.CommissionTiming; | ||
| 4 | import market.guess.model.event.EventStatus; | 5 | import market.guess.model.event.EventStatus; |
| 5 | import market.guess.ui.console.io.InputProcessor; | 6 | import market.guess.ui.console.io.InputProcessor; |
| 6 | 7 | ||
| @@ -65,7 +66,7 @@ public final class EventDetailsMenuCommand implements MenuCommand { | |||
| 65 | "Commission: %d%% (%s)" | 66 | "Commission: %d%% (%s)" |
| 66 | .formatted( | 67 | .formatted( |
| 67 | event.summary().commissionPercent(), | 68 | event.summary().commissionPercent(), |
| 68 | event.summary().commissionTiming() == market.guess.api.CommissionTiming.ON_CLOSE | 69 | event.summary().commissionTiming() == CommissionTiming.ON_CLOSE |
| 69 | ? "on-close" | 70 | ? "on-close" |
| 70 | : "on-purchase")); | 71 | : "on-purchase")); |
| 71 | io.println("Status: %s".formatted(event.summary().status())); | 72 | io.println("Status: %s".formatted(event.summary().status())); |
diff --git a/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java index 01e93bd..3dfe662 100644 --- a/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java +++ b/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | package market.guess.ui.console.command; | 1 | package market.guess.ui.console.command; |
| 2 | 2 | ||
| 3 | import market.guess.api.CatalogContext; | 3 | import market.guess.api.CatalogContext; |
| 4 | import market.guess.api.CommissionTiming; | 4 | import market.guess.model.event.CommissionTiming; |
| 5 | import market.guess.ui.console.io.InputProcessor; | 5 | import market.guess.ui.console.io.InputProcessor; |
| 6 | 6 | ||
| 7 | public final class ListEventsMenuCommand implements MenuCommand { | 7 | public final class ListEventsMenuCommand implements MenuCommand { |
| @@ -41,7 +41,8 @@ public final class ListEventsMenuCommand implements MenuCommand { | |||
| 41 | 41 | ||
| 42 | for (var event : events) { | 42 | for (var event : events) { |
| 43 | io.newLine(); | 43 | io.newLine(); |
| 44 | io.println(" [%d] %s (ID: %d)".formatted(event.displayId(), event.name(), event.displayId())); | 44 | io.println( |
| 45 | " [%d] %s (ID: %d)".formatted(event.displayId(), event.name(), event.displayId())); | ||
| 45 | io.println(" Description: %s".formatted(event.description())); | 46 | io.println(" Description: %s".formatted(event.description())); |
| 46 | io.println( | 47 | io.println( |
| 47 | " Commission: %d%% (%s)" | 48 | " Commission: %d%% (%s)" |