更新战令奖励统一
This commit is contained in:
parent
c36447a646
commit
91b07bc49d
13
assets/GameplayIntro/compressed.meta
Normal file
13
assets/GameplayIntro/compressed.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "1127eb1f-f9f7-4ef0-bb78-412c934aaee9",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ export function normalizePass(stage: any, rows: any[]): any {
|
|||
}
|
||||
return stage;
|
||||
}
|
||||
export function mergePassInfo(raw: any, extra: any, rows: any[], oldRows: any[] = rows): any {
|
||||
export function mergePassInfo(raw: any, extra: any, rows: any[]): any {
|
||||
if (!raw) return raw;
|
||||
for (const key of [1, 2]) {
|
||||
const old = raw[key];
|
||||
|
|
@ -45,17 +45,17 @@ export function mergePassInfo(raw: any, extra: any, rows: any[], oldRows: any[]
|
|||
for (let i = 0; i < Math.min(30, (old[lane] || []).length); i++) if (old[lane][i] === 0) raw[key][lane][i] = 0;
|
||||
}
|
||||
}
|
||||
raw[key] = normalizePass(raw[key], key === 1 ? oldRows : rows);
|
||||
raw[key] = normalizePass(raw[key], rows);
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
export function legacyPassInfo(pass: any, rows: any[], oldRows: any[] = rows): any {
|
||||
export function legacyPassInfo(pass: any, rows: any[]): any {
|
||||
const legacy: any = {};
|
||||
for (const key of [1, 2]) {
|
||||
const stage = pass[key];
|
||||
if (!stage || !Number(stage.time)) { legacy[key] = stage; continue; }
|
||||
const level = Math.max(1, Math.min(30, stage.progressLevel));
|
||||
const row = (key === 1 ? oldRows : rows)[stage.progressLevel - 1];
|
||||
const row = rows[stage.progressLevel - 1];
|
||||
const progress = stage.unlocked >= level ? OLD_TOKENS[level - 1] : Math.min(OLD_TOKENS[level - 1], Math.floor(stage.progress * OLD_TOKENS[level - 1] / Math.max(1, Number(row.token))));
|
||||
legacy[key] = { time: stage.time, activate: passTier(stage) > 0, progressLevel: level, progress,
|
||||
free: (stage.free || []).slice(0, 30), passCheck: (stage.passCheck || []).slice(0, 30) };
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ export class GameConfig {
|
|||
: this.defaultNewGuide;
|
||||
}
|
||||
static PASS_CHECK: any;
|
||||
static PASS_CHECK_OLD: any;
|
||||
private static defaultPassRate: any[] = [];
|
||||
private static newPlayerPassRate: any[] = [];
|
||||
static get PASS_RATE(): any[] {
|
||||
|
|
@ -773,7 +772,7 @@ export class GameConfig {
|
|||
vibrateOpen: true, //震动
|
||||
coinnum: 0, //每局的金币数
|
||||
paid_user: false, //是否是付费用户
|
||||
version: "1.0.75", //版本号
|
||||
version: "1.0.78", //版本号
|
||||
shushu_DistinctId: "", //数数访客ID
|
||||
shushu_AccountId: "", //数数账号ID
|
||||
uid: "", //用户和后端唯一id
|
||||
|
|
@ -882,14 +881,7 @@ export class GameConfig {
|
|||
return;
|
||||
}
|
||||
const newLevelData = res.json;
|
||||
cc.resources.load("Json/PASS_CHECK_OLD", (oldError: any, oldRes: cc.JsonAsset) => {
|
||||
if (oldError) {
|
||||
console.error("加载 PASS_CHECK_OLD.JSON 失败:", oldError);
|
||||
return;
|
||||
}
|
||||
this.PASS_CHECK_OLD = oldRes.json.Sheet1;
|
||||
this.PASS_CHECK = newLevelData.Sheet1;
|
||||
});
|
||||
// 可以根据需求对 newLevelData 进行处理
|
||||
// //console.log("PASS_CHECK.JSON 加载成功:", newLevelData);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1505,7 +1505,7 @@ export default class Utils {
|
|||
cc.fx.StorageMessage.setStorage('coin', { coin: cc.fx.GameConfig.GM_INFO.coin, timestamp: Date.now() });
|
||||
}
|
||||
static getPassCheckInfo(callBack) {
|
||||
if (!cc.fx.GameConfig.PASS_CHECK || !cc.fx.GameConfig.PASS_CHECK_OLD) {
|
||||
if (!cc.fx.GameConfig.PASS_CHECK) {
|
||||
if (callBack) callBack({ code: 0, msg: '战令配置尚未加载,请稍后重试' });
|
||||
return;
|
||||
}
|
||||
|
|
@ -1513,7 +1513,7 @@ export default class Utils {
|
|||
if (res.code !== 1) { if (callBack) callBack(res); return; }
|
||||
Utils.passRequest('read').then(extra => {
|
||||
const raw = typeof extra.data.legacy === 'string' ? JSON.parse(extra.data.legacy) : extra.data.legacy;
|
||||
const pass = mergePassInfo(raw, extra.data.extra, cc.fx.GameConfig.PASS_CHECK, cc.fx.GameConfig.PASS_CHECK_OLD);
|
||||
const pass = mergePassInfo(raw, extra.data.extra, cc.fx.GameConfig.PASS_CHECK);
|
||||
if (pass) { pass.revision = extra.data.revision; pass.upgradeReady = true; }
|
||||
for (const time of Object.keys(extra.data.extra || {})) for (const order of extra.data.extra[time].orders || []) Utils.applyPassGift(order);
|
||||
res.data.passCheck = JSON.stringify(pass);
|
||||
|
|
@ -1534,17 +1534,17 @@ export default class Utils {
|
|||
let pass = data;
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
const latest = await Utils.passRequest('read');
|
||||
const merged = mergePassInfo(JSON.parse(latest.data.legacy || 'null'), latest.data.extra, cc.fx.GameConfig.PASS_CHECK, cc.fx.GameConfig.PASS_CHECK_OLD);
|
||||
const merged = mergePassInfo(JSON.parse(latest.data.legacy || 'null'), latest.data.extra, cc.fx.GameConfig.PASS_CHECK);
|
||||
for (const key of [1, 2]) {
|
||||
if (!pass[key] || !Number(pass[key].time)) continue;
|
||||
pass[key] = normalizePass(pass[key], key === 1 ? cc.fx.GameConfig.PASS_CHECK_OLD : cc.fx.GameConfig.PASS_CHECK);
|
||||
pass[key] = normalizePass(pass[key], cc.fx.GameConfig.PASS_CHECK);
|
||||
const current = merged && [merged[1], merged[2]].find(s => String(s && s.time) === String(pass[key].time));
|
||||
if (current) {
|
||||
pass[key].experience = Math.max(pass[key].experience, current.experience);
|
||||
for (const lane of ['free', 'passCheck']) for (let i = 0; i < current[lane].length; i++) {
|
||||
if (current[lane][i] === 0) pass[key][lane][i] = 0;
|
||||
}
|
||||
pass[key] = normalizePass(pass[key], key === 1 ? cc.fx.GameConfig.PASS_CHECK_OLD : cc.fx.GameConfig.PASS_CHECK);
|
||||
pass[key] = normalizePass(pass[key], cc.fx.GameConfig.PASS_CHECK);
|
||||
}
|
||||
}
|
||||
try { return await Utils.passRequest('save', { ...Utils.passUpload(pass), revision: latest.data.revision }); }
|
||||
|
|
@ -1564,7 +1564,7 @@ export default class Utils {
|
|||
});
|
||||
}
|
||||
private static passUpload(pass: any): any {
|
||||
const legacy = legacyPassInfo(pass, cc.fx.GameConfig.PASS_CHECK, cc.fx.GameConfig.PASS_CHECK_OLD);
|
||||
const legacy = legacyPassInfo(pass, cc.fx.GameConfig.PASS_CHECK);
|
||||
for (const key of [1, 2]) if (pass[key] && Number(pass[key].time)) pass[key].legacyExperience = legacyExperience(legacy[key]);
|
||||
return { passCheck: JSON.stringify(pass), legacy: JSON.stringify(legacy) };
|
||||
}
|
||||
|
|
@ -1593,13 +1593,13 @@ export default class Utils {
|
|||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
const order = await Utils.passRequest('order', { outTradeNo });
|
||||
if (order.data.alreadyGranted) { Utils.applyPassGift(outTradeNo); return order; }
|
||||
const pass = mergePassInfo(JSON.parse(order.data.legacy || '{}'), order.data.extra, cc.fx.GameConfig.PASS_CHECK, cc.fx.GameConfig.PASS_CHECK_OLD);
|
||||
const pass = mergePassInfo(JSON.parse(order.data.legacy || '{}'), order.data.extra, cc.fx.GameConfig.PASS_CHECK);
|
||||
let key = [1, 2].find(k => String(pass[k] && pass[k].time) === order.data.passEnd);
|
||||
if (!key && order.data.extra[order.data.passEnd]) { key = 1; pass[1] = order.data.extra[order.data.passEnd]; }
|
||||
if (!key) throw { code: 410, msg: '订单所属期已过期,请联系客服' };
|
||||
pass[key].activate = true; pass[key].tier = order.data.targetTier;
|
||||
if (order.data.bonus) pass[key].experience += 20;
|
||||
pass[key] = normalizePass(pass[key], key === 1 ? cc.fx.GameConfig.PASS_CHECK_OLD : cc.fx.GameConfig.PASS_CHECK);
|
||||
pass[key] = normalizePass(pass[key], cc.fx.GameConfig.PASS_CHECK);
|
||||
// 沿用客户端计算后上传,赠金仅通过战令接口随本期发奖记录一起保存。
|
||||
const coinAmount = Math.floor(cc.fx.GameConfig.GM_INFO.coin) + (order.data.bonus ? 3000 : 0);
|
||||
const giftKey = (cc.fx.GameConfig.GM_INFO.uid || Utils.uid) + ':' + outTradeNo;
|
||||
|
|
|
|||
13
assets/gacha_bundle/compressed.meta
Normal file
13
assets/gacha_bundle/compressed.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "38f00c59-54ce-473c-a327-1fa1bfd7ec6a",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
13
assets/gacha_bundle/img/cat.meta
Normal file
13
assets/gacha_bundle/img/cat.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "f7a90a61-ed72-49b4-a293-49c19f2536d8",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
13
assets/libs/dn-sdk-minigame.meta
Normal file
13
assets/libs/dn-sdk-minigame.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "f8c7a430-1eda-4c66-9279-b4648f947b0b",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
13
assets/passCheck/script.meta
Normal file
13
assets/passCheck/script.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "49d2c552-72e4-4554-acbc-7df666efdc28",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
13
assets/propWindow/compressed.meta
Normal file
13
assets/propWindow/compressed.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "cd2cd7b6-cfeb-4a6e-b907-ea1efa59b0ad",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
13
assets/res/shop.meta
Normal file
13
assets/res/shop.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "d2d3e554-c6d3-44e5-8b43-a1570e9285b9",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
|
|
@ -101,8 +101,7 @@ export default class passCheck extends cc.Component {
|
|||
}
|
||||
onInit(passCheckInfo) {
|
||||
this.passData = passCheckInfo;
|
||||
const passCheckData = cc.fx.GameConfig.GM_INFO.getItemType == 2
|
||||
? cc.fx.GameConfig.PASS_CHECK : cc.fx.GameConfig.PASS_CHECK_OLD;
|
||||
const passCheckData = cc.fx.GameConfig.PASS_CHECK;
|
||||
|
||||
// let _playerPassLevel = cc.fx.GameConfig.GM_INFO.playerPassLevel
|
||||
// let getUserLevel = cc.fx.GameConfig.GM_INFO.level;
|
||||
|
|
|
|||
13
assets/win/compressed.meta
Normal file
13
assets/win/compressed.meta
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"ver": "1.1.3",
|
||||
"uuid": "28c4b382-8397-462d-98c6-a65c5a48b2c0",
|
||||
"importer": "folder",
|
||||
"isBundle": false,
|
||||
"bundleName": "",
|
||||
"priority": 1,
|
||||
"compressionType": {},
|
||||
"optimizeHotUpdate": {},
|
||||
"inlineSpriteFrames": {},
|
||||
"isRemoteBundle": {},
|
||||
"subMetas": {}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"last-module-event-record-time": 1790576651929,
|
||||
"last-module-event-record-time": 1791514028270,
|
||||
"group-list": [
|
||||
"default",
|
||||
"Map"
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ function animationFixture() {
|
|||
const storage = new Map(), actions = [], stopped = new Set();
|
||||
cc.fx.StorageMessage = { getStorage: key => storage.get(key), setStorage: (key, value) => storage.set(key, value) };
|
||||
cc.fx.GameConfig.GM_INFO = { uid: 'animation-player', getItemType: 2 };
|
||||
cc.fx.GameConfig.PASS_CHECK_OLD = JSON.parse(fs.readFileSync('assets/resources/Json/PASS_CHECK_OLD.json', 'utf8')).Sheet1;
|
||||
cc.Tween.stopAllByTarget = target => actions.filter(a => a.target === target).forEach(a => stopped.add(a));
|
||||
cc.tween = target => {
|
||||
const steps = [];
|
||||
|
|
@ -110,8 +109,7 @@ function animationFixture() {
|
|||
function show(level, partial = 0, options = {}) {
|
||||
const season = options.season || '2000000000000', tier = options.tier || 0;
|
||||
cc.fx.GameConfig.GM_INFO.getItemType = options.old ? 1 : 2;
|
||||
const config = options.old ? cc.fx.GameConfig.PASS_CHECK_OLD : rows;
|
||||
const stage = { time: season, experience: config.slice(0, level).reduce((sum, row) => sum + row.token, 0) + partial,
|
||||
const stage = { time: season, experience: rows.slice(0, level).reduce((sum, row) => sum + row.token, 0) + partial,
|
||||
free: Array(level).fill(0), passCheck: Array(level).fill(1), tier, activate: tier > 0 };
|
||||
const input = { 1: options.old ? stage : { time: '0' }, 2: options.old ? { time: '0' } : stage };
|
||||
const before = JSON.stringify(input);
|
||||
|
|
@ -224,7 +222,23 @@ test('battle pass level never exceeds unlocked tiers or the entitlement cap at a
|
|||
assert.equal(f.panel.currentLv.number, 6);
|
||||
}
|
||||
const empty = animationFixture(); empty.show(0, 0, { old: true, season: '1900000000000' });
|
||||
assert.equal(empty.panel.currentLv.number, 0);
|
||||
assert.equal(empty.panel.currentLv.number, 1);
|
||||
});
|
||||
|
||||
test('previous and current panels display the same new rewards beyond tier thirty', () => {
|
||||
for (const old of [false, true]) {
|
||||
const f = animationFixture();
|
||||
f.show(40, 0, { old, tier: 30 });
|
||||
assert.equal(f.panel.currentLv.number, 40);
|
||||
assert.equal(f.manager.listData.length, 45);
|
||||
for (const index of [0, 29, 34, 39]) {
|
||||
const reward = f.manager.listData[index];
|
||||
assert.equal(`${reward.ItemID1}:${reward.ItemNum1}`, rows[index].free);
|
||||
assert.equal(`${reward.ItemID2}:${reward.ItemNum2}`, rows[index].paid);
|
||||
assert.equal(reward.free, 0);
|
||||
assert.equal(reward.passCheck, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('battle pass periods and accounts cannot overwrite each other animation records', () => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ const vm = require('vm');
|
|||
const ts = require('typescript');
|
||||
const cp = require('node:child_process');
|
||||
const rows = JSON.parse(fs.readFileSync('assets/resources/Json/PASS_CHECK.json', 'utf8')).Sheet1;
|
||||
const oldRows = JSON.parse(fs.readFileSync('assets/resources/Json/PASS_CHECK_OLD.json', 'utf8')).Sheet1;
|
||||
const plain = value => JSON.parse(JSON.stringify(value));
|
||||
function load(path, deps = {}, globals = {}) {
|
||||
const exports = {};
|
||||
|
|
@ -32,7 +31,7 @@ function fixture(owned = 18) {
|
|||
const legacy = load('server/laf-cloud/functions/passCheck.ts', deps).default;
|
||||
const call = body => upgrade.default({ body: { uid: 'u', token: 't', ...body } });
|
||||
const old = body => legacy({ body: { uid: 'u', token: 't', ...body } });
|
||||
const cc = { fx: { GameConfig: { PASS_CHECK: rows, PASS_CHECK_OLD: oldRows, GM_INFO: { uid: 'u', coin: 100 } },
|
||||
const cc = { fx: { GameConfig: { PASS_CHECK: rows, GM_INFO: { uid: 'u', coin: 100 } },
|
||||
StorageMessage: { setStorage() {}, getStorage() {} } } };
|
||||
const context = { cc, ...model, Date, console, setTimeout, clearTimeout };
|
||||
const source = ts.createSourceFile('Utils.ts', fs.readFileSync('assets/Script/module/Pay/Utils.ts', 'utf8'), 99, true);
|
||||
|
|
@ -47,19 +46,19 @@ const save = (f, pass) => new Promise(resolve => f.Utils.setPassCheckInfo(resolv
|
|||
const xpAt = level => rows.slice(0, level).reduce((sum, row) => sum + row.token, 0);
|
||||
const at = (level, tier = 30) => model.normalizePass({ time: '100', experience: xpAt(level), tier, activate: tier > 0 }, rows);
|
||||
|
||||
test('previous season uses OLD experience and preserves claims through save and reload', async () => {
|
||||
test('previous season uses new experience and preserves claims through save and reload', async () => {
|
||||
const f = fixture(0);
|
||||
const previous = { time: String(f.start), progress: 2, progressLevel: 6, activate: false,
|
||||
const previous = { time: String(f.start), progress: 4, progressLevel: 6, activate: false,
|
||||
free: [0, 0, 0, 1, 0, 0, ...Array(24).fill(-1)], passCheck: [...Array(6).fill(1), ...Array(24).fill(-1)] };
|
||||
f.tables.users[0].passCheck = JSON.stringify({ 1: previous,
|
||||
2: { time: String(f.end), progress: 1, progressLevel: 1, activate: false, free: [1], passCheck: [1] } });
|
||||
const pass = JSON.parse((await read(f)).data.passCheck);
|
||||
assert.equal(pass[1].experience, 11);
|
||||
assert.equal(pass[1].experience, 12);
|
||||
assert.equal(pass[1].unlocked, 6);
|
||||
assert.equal(pass[1].progress, 2);
|
||||
assert.equal(pass[1].progress, 4);
|
||||
assert.equal(pass[2].experience, 0);
|
||||
assert.equal(pass[2].unlocked, 1);
|
||||
assert.deepEqual(plain(model.passBounds(pass[1], oldRows.length)), { generated: 30, content: 30 });
|
||||
assert.deepEqual(plain(model.passBounds(pass[1], rows.length)), { generated: 40, content: 36 });
|
||||
assert.equal(model.canClaimPass(pass[1], 3, true), true);
|
||||
assert.equal(model.canClaimPass(pass[1], 3, false), false);
|
||||
pass[1].free[3] = 0;
|
||||
|
|
@ -73,16 +72,36 @@ test('previous season uses OLD experience and preserves claims through save and
|
|||
assert.equal(legacy[1].progress, 2);
|
||||
});
|
||||
|
||||
test('previous partial progress projects with OLD costs and missing OLD cannot use new costs', async () => {
|
||||
const pass = { 1: model.normalizePass({ time: '100', experience: 10 }, oldRows) };
|
||||
const projected = model.legacyPassInfo(pass, rows, oldRows);
|
||||
test('previous partial progress uses new costs while preserving legacy projection', async () => {
|
||||
const pass = { 1: model.normalizePass({ time: '100', experience: 10 }, rows) };
|
||||
const projected = model.legacyPassInfo(pass, rows);
|
||||
assert.equal(projected[1].progressLevel, 6);
|
||||
assert.equal(projected[1].progress, 1);
|
||||
const f = fixture();
|
||||
delete f.cc.fx.GameConfig.PASS_CHECK_OLD;
|
||||
assert.equal((await read(f)).code, 1);
|
||||
delete f.cc.fx.GameConfig.PASS_CHECK;
|
||||
assert.equal((await read(f)).code, 0);
|
||||
});
|
||||
|
||||
test('current season moved to previous keeps new tiers and claims after save and reload', async () => {
|
||||
const f = fixture();
|
||||
await f.Utils.completePassOrder('paid');
|
||||
const pass = JSON.parse((await read(f)).data.passCheck);
|
||||
pass[2].experience = xpAt(40);
|
||||
pass[2].free[37] = 0;
|
||||
assert.equal((await save(f, pass)).code, 1);
|
||||
const rotated = JSON.parse((await read(f)).data.passCheck);
|
||||
rotated[1] = rotated[2];
|
||||
rotated[2] = { time: String(f.end + model.PASS_PERIOD), experience: 0, free: [], passCheck: [], activate: false };
|
||||
assert.equal((await save(f, rotated)).code, 1);
|
||||
const restored = JSON.parse((await read(f)).data.passCheck);
|
||||
assert.equal(restored[1].experience, xpAt(40));
|
||||
assert.equal(restored[1].unlocked, 40);
|
||||
assert.equal(restored[1].free[37], 0);
|
||||
assert.equal(model.canClaimPass(restored[1], 39, false), true);
|
||||
assert.equal(restored[2].unlocked, 1);
|
||||
});
|
||||
|
||||
test('authored levels and two reward columns remain finite and contiguous', () => {
|
||||
assert.ok(rows.length >= 40);
|
||||
rows.forEach((r, i) => { assert.equal(r.level, i + 1); assert.ok(r.token >= 0); assert.match(r.free, /^\d+:\d+$/); assert.match(r.paid, /^\d+:\d+$/); });
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user