feat(rewards): add 14 new shop items with twin backgrounds
Build, Test & Push Core Service / quality-check (push) Successful in 1m14s
Build, Test & Push Core Service / docker (push) Successful in 1m23s

Each page background gets a matching banner background. Tests verify
pairing, price constraints, and code length limits
This commit is contained in:
lobo committed 2026-10-03 17:31:19 +02:00
1 parent 8eab98df74
commit 74cc8297ce
3 files changed
+48 -1

No files matched your search

+1 -1
View File
@@ -65,7 +65,7 @@ To Be Played is split into three repositories:
snapshots, once per user, kind and game (`ref`). Rules and numbers: `RewardRules`; a Steam finish needs playtime and one snapshots, once per user, kind and game (`ref`). Rules and numbers: `RewardRules`; a Steam finish needs playtime and one
proof of fresh play (ending achievement or playtime around the finish, or half of the IGDB time played since the finish; old history pays nothing). The month bonus needs a finished game in that month. Games added by hand pay 15 for proof of fresh play (ending achievement or playtime around the finish, or half of the IGDB time played since the finish; old history pays nothing). The month bonus needs a finished game in that month. Games added by hand pay 15 for
a finish, at most 3 per ISO week. The settle takes a per-user advisory lock. V26 also pays a one-time starter grant a finish, at most 3 per ISO week. The settle takes a per-user advisory lock. V26 also pays a one-time starter grant
for finishes from before the status log. Shop: a whitelist of 43 looks (`ShopItem`; 31 buyable and 12 unlock-only) in eight slots, including animated completed effects, page backgrounds, for finishes from before the status log. Shop: a whitelist of 57 looks (`ShopItem`; 45 buyable and 12 unlock-only) in eight slots, including animated completed effects, page backgrounds (CSS, SVG and two canvas engines in the Frontend),
banner backgrounds (V27 widens `reward_equipped.slot`) and three buyable skins (full themes, slot `SKIN`). The unlock-only banner backgrounds (V27 widens `reward_equipped.slot`) and three buyable skins (full themes, slot `SKIN`). The unlock-only
items (price 0, never sold): the settle books an `UNLOCK` row (ref = item code, 0 points) once a items (price 0, never sold): the settle books an `UNLOCK` row (ref = item code, 0 points) once a
track reaches the item's target, retroactively and never lost. The five tracks (`Unlocks`): games finished track reaches the item's target, retroactively and never lost. The five tracks (`Unlocks`): games finished
@@ -31,6 +31,13 @@ public enum ShopItem {
BG_GRID(LookSlot.PAGE_BACKGROUND, 450), BG_GRID(LookSlot.PAGE_BACKGROUND, 450),
BG_WAVES(LookSlot.PAGE_BACKGROUND, 400), BG_WAVES(LookSlot.PAGE_BACKGROUND, 400),
BG_BOKEH(LookSlot.PAGE_BACKGROUND, 400), BG_BOKEH(LookSlot.PAGE_BACKGROUND, 400),
BG_SYNTHWAVE(LookSlot.PAGE_BACKGROUND, 450),
BG_FIREFLIES(LookSlot.PAGE_BACKGROUND, 400),
BG_SNOW(LookSlot.PAGE_BACKGROUND, 400),
BG_SAKURA(LookSlot.PAGE_BACKGROUND, 400),
BG_NEBULA(LookSlot.PAGE_BACKGROUND, 450),
BG_MATRIX(LookSlot.PAGE_BACKGROUND, 500),
BG_CONSTELLATION(LookSlot.PAGE_BACKGROUND, 500),
BN_TRIANGLES(LookSlot.BANNER_BACKGROUND, 300), BN_TRIANGLES(LookSlot.BANNER_BACKGROUND, 300),
BN_STARFIELD(LookSlot.BANNER_BACKGROUND, 300), BN_STARFIELD(LookSlot.BANNER_BACKGROUND, 300),
BN_PIXELS(LookSlot.BANNER_BACKGROUND, 300), BN_PIXELS(LookSlot.BANNER_BACKGROUND, 300),
@@ -39,6 +46,13 @@ public enum ShopItem {
BN_GRID(LookSlot.BANNER_BACKGROUND, 300), BN_GRID(LookSlot.BANNER_BACKGROUND, 300),
BN_WAVES(LookSlot.BANNER_BACKGROUND, 300), BN_WAVES(LookSlot.BANNER_BACKGROUND, 300),
BN_BOKEH(LookSlot.BANNER_BACKGROUND, 300), BN_BOKEH(LookSlot.BANNER_BACKGROUND, 300),
BN_SYNTHWAVE(LookSlot.BANNER_BACKGROUND, 300),
BN_FIREFLIES(LookSlot.BANNER_BACKGROUND, 300),
BN_SNOW(LookSlot.BANNER_BACKGROUND, 300),
BN_SAKURA(LookSlot.BANNER_BACKGROUND, 300),
BN_NEBULA(LookSlot.BANNER_BACKGROUND, 300),
BN_MATRIX(LookSlot.BANNER_BACKGROUND, 300),
BN_CONSTELLATION(LookSlot.BANNER_BACKGROUND, 300),
SKIN_PASTEL(LookSlot.SKIN, 600), SKIN_PASTEL(LookSlot.SKIN, 600),
SKIN_RETRO_CRT(LookSlot.SKIN, 700), SKIN_RETRO_CRT(LookSlot.SKIN, 700),
SKIN_CYBERPUNK(LookSlot.SKIN, 800), SKIN_CYBERPUNK(LookSlot.SKIN, 800),
@@ -0,0 +1,33 @@
package core_service.modules.rewards.domain;
import core_service.shared.test.AbstractUnitTest;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static org.assertj.core.api.Assertions.assertThat;
class ShopItemTest extends AbstractUnitTest {
@Test
void everyPageBackgroundHasABannerTwin() {
for (ShopItem item : ShopItem.values()) {
if (!item.name().startsWith("BG_")) continue;
ShopItem twin = ShopItem.valueOf("BN_" + item.name().substring(3));
assertThat(item.slot()).isEqualTo(LookSlot.PAGE_BACKGROUND);
assertThat(twin.slot()).isEqualTo(LookSlot.BANNER_BACKGROUND);
}
}
@Test
void buyableBannerBackgroundsCost300() {
assertThat(Arrays.stream(ShopItem.values())
.filter(item -> item.name().startsWith("BN_") && !item.unlockOnly())
.map(ShopItem::price)).containsOnly(300);
}
@Test
void codesFitTheColumn() {
assertThat(Arrays.stream(ShopItem.values()).map(Enum::name)).allMatch(name -> name.length() <= 32);
}
}