feat: add gift zone city team and mashup mode
This commit is contained in:
@@ -129,18 +129,24 @@ test('content system summarizes MVP gift albums and per-city progress', () => {
|
||||
cityId: 'beijing',
|
||||
acquiredDate: '2026-03-29T00:00:00.000Z',
|
||||
})
|
||||
playerState.collectedCats.push('beijing')
|
||||
|
||||
const albums = contentSystem.getGiftAlbums(playerState)
|
||||
const magnetEntries = contentSystem.getGiftAlbumEntries('magnets', playerState)
|
||||
const stampEntries = contentSystem.getGiftAlbumEntries('stamps', playerState)
|
||||
const catEntries = contentSystem.getGiftAlbumEntries('cats', playerState)
|
||||
|
||||
assert.deepEqual(albums.map((album) => album.id), ['magnets', 'stamps'])
|
||||
assert.deepEqual(albums.map((album) => album.collectedCount), [1, 1])
|
||||
assert.deepEqual(albums.map((album) => album.totalCount), [36, 6])
|
||||
assert.deepEqual(albums.map((album) => album.id), ['magnets', 'stamps', 'cats'])
|
||||
assert.deepEqual(albums.map((album) => album.collectedCount), [1, 1, 1])
|
||||
assert.deepEqual(albums.map((album) => album.totalCount), [36, 6, 6])
|
||||
assert.equal(magnetEntries[0].cityId, 'beijing')
|
||||
assert.equal(magnetEntries[0].collectedCount, 1)
|
||||
assert.equal(magnetEntries[0].totalCount, 6)
|
||||
assert.equal(stampEntries[0].cityId, 'beijing')
|
||||
assert.equal(stampEntries[0].isCollected, true)
|
||||
assert.equal(stampEntries[1].isCollected, false)
|
||||
assert.equal(catEntries[0].cityId, 'beijing')
|
||||
assert.equal(catEntries[0].catName, '京京')
|
||||
assert.equal(catEntries[0].isCollected, true)
|
||||
assert.equal(catEntries[1].isCollected, false)
|
||||
})
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
classifyDeadlock,
|
||||
evaluateBoard,
|
||||
generateBoard,
|
||||
generateMashupBoard,
|
||||
} from '../js/gameplay/difficulty/index.js'
|
||||
|
||||
test('generateBoard is deterministic for the same city, level, and seed', () => {
|
||||
@@ -72,3 +73,23 @@ test('classifyDeadlock identifies a hard deadlock when slot is full and no match
|
||||
|
||||
assert.equal(result.type, 'hard')
|
||||
})
|
||||
|
||||
test('generateMashupBoard is deterministic and mixes unlocked city content', () => {
|
||||
const contentSystem = createContentSystem()
|
||||
|
||||
const first = generateMashupBoard({
|
||||
cityIds: ['beijing', 'tokyo'],
|
||||
seed: 33001,
|
||||
contentSystem,
|
||||
})
|
||||
const second = generateMashupBoard({
|
||||
cityIds: ['beijing', 'tokyo'],
|
||||
seed: 33001,
|
||||
contentSystem,
|
||||
})
|
||||
|
||||
assert.deepEqual(first.pieces, second.pieces)
|
||||
assert.deepEqual(first.overlapGraph, second.overlapGraph)
|
||||
assert.deepEqual(first.sourceCityIds, ['beijing', 'tokyo'])
|
||||
assert.ok(new Set(first.elementDefinitions.map((entry) => entry.sourceCityId)).size >= 2)
|
||||
})
|
||||
|
||||
@@ -118,7 +118,125 @@ test('scene store opens the gift zone and switches between MVP tabs', () => {
|
||||
assert.equal(switched, true)
|
||||
assert.equal(sceneStore.getScene().selectedTab, 'stamps')
|
||||
|
||||
const switchedToCats = sceneStore.selectGiftTab('cats')
|
||||
|
||||
assert.equal(switchedToCats, true)
|
||||
assert.equal(sceneStore.getScene().selectedTab, 'cats')
|
||||
|
||||
sceneStore.goBack()
|
||||
|
||||
assert.equal(sceneStore.getScene().type, 'home-select')
|
||||
})
|
||||
|
||||
test('scene store opens city team selection and locks the first chosen team', () => {
|
||||
const contentSystem = createContentSystem()
|
||||
const playerState = createDefaultPlayerState()
|
||||
const sceneStore = createSceneStore({
|
||||
contentSystem,
|
||||
playerState,
|
||||
now: () => new Date('2026-03-29T08:00:00.000Z').getTime(),
|
||||
})
|
||||
|
||||
const opened = sceneStore.openCityTeamSelect()
|
||||
|
||||
assert.equal(opened, true)
|
||||
assert.equal(sceneStore.getScene().type, 'city-team-select')
|
||||
assert.deepEqual(sceneStore.getScene().options.map((entry) => entry.cityId), ['beijing'])
|
||||
|
||||
const selected = sceneStore.chooseCityTeam('beijing')
|
||||
|
||||
assert.equal(selected, true)
|
||||
assert.deepEqual(playerState.cityTeam, {
|
||||
teamCityId: 'beijing',
|
||||
joinedDate: '2026-03-29T08:00:00.000Z',
|
||||
lastSwitchDate: null,
|
||||
})
|
||||
assert.equal(sceneStore.getScene().type, 'home-select')
|
||||
|
||||
sceneStore.openCityTeamSelect()
|
||||
const reselected = sceneStore.chooseCityTeam('beijing')
|
||||
|
||||
assert.equal(reselected, false)
|
||||
assert.equal(playerState.cityTeam.teamCityId, 'beijing')
|
||||
})
|
||||
|
||||
test('scene store opens mashup gameplay after two completed cities', () => {
|
||||
const contentSystem = createContentSystem()
|
||||
const playerState = createDefaultPlayerState()
|
||||
const sceneStore = createSceneStore({
|
||||
contentSystem,
|
||||
playerState,
|
||||
now: () => 33001,
|
||||
})
|
||||
|
||||
playerState.unlockedCities.push('tokyo')
|
||||
playerState.levelProgress.beijing = {
|
||||
1: { completed: true, stars: 3 },
|
||||
2: { completed: true, stars: 3 },
|
||||
3: { completed: true, stars: 3 },
|
||||
4: { completed: true, stars: 3 },
|
||||
5: { completed: true, stars: 3 },
|
||||
6: { completed: true, stars: 3 },
|
||||
}
|
||||
playerState.levelProgress.tokyo = {
|
||||
1: { completed: true, stars: 3 },
|
||||
2: { completed: true, stars: 3 },
|
||||
3: { completed: true, stars: 3 },
|
||||
4: { completed: true, stars: 3 },
|
||||
5: { completed: true, stars: 3 },
|
||||
6: { completed: true, stars: 3 },
|
||||
}
|
||||
|
||||
const opened = sceneStore.openHomeTile('mashup')
|
||||
|
||||
assert.deepEqual(opened, { opened: true })
|
||||
assert.equal(sceneStore.getScene().type, 'gameplay')
|
||||
assert.equal(sceneStore.getScene().mode, 'mashup')
|
||||
assert.deepEqual(sceneStore.getScene().sourceCityIds, ['beijing', 'tokyo'])
|
||||
})
|
||||
|
||||
test('scene store awards a deterministic local mashup reward', () => {
|
||||
const contentSystem = createContentSystem()
|
||||
const playerState = createDefaultPlayerState()
|
||||
const sceneStore = createSceneStore({
|
||||
contentSystem,
|
||||
playerState,
|
||||
now: () => 33001,
|
||||
})
|
||||
|
||||
playerState.unlockedCities.push('tokyo')
|
||||
playerState.levelProgress.beijing = {
|
||||
1: { completed: true, stars: 3 },
|
||||
2: { completed: true, stars: 3 },
|
||||
3: { completed: true, stars: 3 },
|
||||
4: { completed: true, stars: 3 },
|
||||
5: { completed: true, stars: 3 },
|
||||
6: { completed: true, stars: 3 },
|
||||
}
|
||||
playerState.levelProgress.tokyo = {
|
||||
1: { completed: true, stars: 3 },
|
||||
2: { completed: true, stars: 3 },
|
||||
3: { completed: true, stars: 3 },
|
||||
4: { completed: true, stars: 3 },
|
||||
5: { completed: true, stars: 3 },
|
||||
6: { completed: true, stars: 3 },
|
||||
}
|
||||
|
||||
sceneStore.openHomeTile('mashup')
|
||||
const reward = sceneStore.completeGameplayVictory()
|
||||
|
||||
assert.deepEqual(reward, {
|
||||
type: 'magnet',
|
||||
magnetId: 'magnet_beijing_2',
|
||||
cityId: 'beijing',
|
||||
levelId: 2,
|
||||
})
|
||||
assert.deepEqual(playerState.collectedMagnets, [
|
||||
{
|
||||
magnetId: 'magnet_beijing_2',
|
||||
cityId: 'beijing',
|
||||
levelId: 2,
|
||||
acquiredDate: '1970-01-01T00:00:33.001Z',
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user