feat: add production campaigns, gameplay labs, and review documentation
This commit is contained in:
@@ -12,9 +12,9 @@ const storage=entries=>{
|
||||
return {getItem:key=>items.get(key)??null,setItem:(key,value)=>items.set(key,value)};
|
||||
};
|
||||
|
||||
test('three selectable editions retain their own level counts, order and chapters',()=>{
|
||||
test('five selectable editions retain their own level counts, order and chapters',()=>{
|
||||
assert.deepEqual(CAMPAIGN_VERSIONS.map(c=>[c.id,c.levels.length,c.chapterSize,c.chapters.length]),[
|
||||
['v0.1',24,8,3],['v0.2',48,6,8],['v0.3',48,6,8],
|
||||
['v0.1',24,8,3],['v0.2',48,6,8],['v0.3',48,6,8],['v0.4',20,5,4],['v0.5',1000,50,20],
|
||||
]);
|
||||
assert.equal(campaignVersion('v0.1').levels[0].name,'转一转,路就通了');
|
||||
assert.equal(campaignVersion('v0.1').levels.at(-1).name,'六角大满贯');
|
||||
@@ -34,8 +34,8 @@ test('browser archive module matches the exact historical JSON bytes and provena
|
||||
}
|
||||
});
|
||||
|
||||
test('all 72 historical layouts solve and replay with the current free rotation rules',()=>{
|
||||
for(const c of CAMPAIGN_VERSIONS.slice(0,2))for(const [i,level] of c.levels.entries()){
|
||||
test('all 120 earlier layouts solve and replay with the current free rotation rules',()=>{
|
||||
for(const c of CAMPAIGN_VERSIONS.slice(0,3))for(const [i,level] of c.levels.entries()){
|
||||
const label=`${c.id} level ${i+1}`;
|
||||
assert.deepEqual(validateLevel(level),[],label);
|
||||
const plan=solveRotations(level),game=new Game(level);
|
||||
@@ -51,12 +51,12 @@ test('all 72 historical layouts solve and replay with the current free rotation
|
||||
}
|
||||
});
|
||||
|
||||
test('new players default to v0.3 while an explicit version choice survives reload',()=>{
|
||||
const s=storage();assert.equal(selectedCampaign(s).id,'v0.3');
|
||||
test('new players default to v0.5 while an explicit version choice survives reload',()=>{
|
||||
const s=storage();assert.equal(selectedCampaign(s).id,'v0.5');
|
||||
assert.ok(writeCampaignProgress(s,campaignVersion('v0.1'),{current:23,completed:[0,22]}));
|
||||
assert.equal(selectedCampaign(s).id,'v0.1');
|
||||
assert.deepEqual(readCampaignProgress(s,selectedCampaign(s)),{current:23,completed:[0,22]});
|
||||
s.setItem(CAMPAIGN_SELECTION_KEY,'v9.9');assert.equal(selectedCampaign(s).id,'v0.3');
|
||||
s.setItem(CAMPAIGN_SELECTION_KEY,'v9.9');assert.equal(selectedCampaign(s).id,'v0.5');
|
||||
});
|
||||
|
||||
test('versions keep progress separate even when v0.2 and v0.3 reuse level IDs',()=>{
|
||||
@@ -77,7 +77,7 @@ test('each edition migrates only its own legacy slot without changing the old da
|
||||
'hex-trails-observe-v3-r2':JSON.stringify({current:6,completed:[6]}),
|
||||
};
|
||||
const s=storage(old);
|
||||
for(const [i,c] of CAMPAIGN_VERSIONS.entries()){
|
||||
for(const [i,c] of CAMPAIGN_VERSIONS.slice(0,3).entries()){
|
||||
const key=Object.keys(old)[i],expected=JSON.parse(old[key]);
|
||||
assert.deepEqual(readCampaignProgress(s,c),expected);
|
||||
writeCampaignProgress(s,c,{current:1,completed:[1]});
|
||||
@@ -98,8 +98,21 @@ test('invalid saves are bounded to each edition and do not resurrect legacy prog
|
||||
test('unavailable browser storage still permits loading a campaign',()=>{
|
||||
const denied={getItem(){throw new Error('denied');},setItem(){throw new Error('denied');}};
|
||||
for(const s of [undefined,denied]){
|
||||
assert.equal(selectedCampaign(s).id,'v0.3');
|
||||
assert.equal(selectedCampaign(s).id,'v0.5');
|
||||
assert.deepEqual(readCampaignProgress(s,campaignVersion('v0.1')),{current:0,completed:[]});
|
||||
assert.equal(writeCampaignProgress(s,campaignVersion('v0.1'),{current:1,completed:[0]}),false);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test('the production campaign starts independently and retains its thousandth level',()=>{
|
||||
const old=JSON.stringify({current:19,completed:[0,19]});
|
||||
const s=storage({[CAMPAIGN_SELECTION_KEY]:'v0.4',[campaignProgressKey('v0.4')]:old});
|
||||
const production=campaignVersion('v0.5');
|
||||
assert.equal(selectedCampaign(s).id,'v0.4');
|
||||
assert.deepEqual(readCampaignProgress(s,production),{current:0,completed:[]});
|
||||
writeCampaignProgress(s,production,{current:999,completed:[0,998,999]});
|
||||
assert.deepEqual(readCampaignProgress(s,production),{current:999,completed:[0,998,999]});
|
||||
assert.equal(s.getItem(campaignProgressKey('v0.4')),old);
|
||||
assert.equal(selectedCampaign(s).id,'v0.5');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user