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
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
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
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
@@ -31,6 +31,13 @@ public enum ShopItem {
BG_GRID(LookSlot.PAGE_BACKGROUND, 450),
BG_WAVES(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_STARFIELD(LookSlot.BANNER_BACKGROUND, 300),
BN_PIXELS(LookSlot.BANNER_BACKGROUND, 300),
@@ -39,6 +46,13 @@ public enum ShopItem {
BN_GRID(LookSlot.BANNER_BACKGROUND, 300),
BN_WAVES(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_RETRO_CRT(LookSlot.SKIN, 700),
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);
}
}