refactor: read onboarding AB assignments within server functions
This commit is contained in:
parent
365b224a47
commit
c3894186c9
|
|
@ -1,5 +1,4 @@
|
|||
import cloud from '@lafjs/cloud'
|
||||
import Utils from "@/Utils";
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
const db = cloud.database();
|
||||
|
|
@ -47,7 +46,14 @@ export function getChinaDateKey(now = Date.now()) {
|
|||
}
|
||||
|
||||
export function getUserSignInTriggerLevel(user: any, config: SignInActivityConfig): number {
|
||||
return Utils.isNewPlayerB(user) ? 15 : Number(config.triggerLevel);
|
||||
let assignments = user?.abTests;
|
||||
if (typeof assignments === "string") {
|
||||
try { assignments = JSON.parse(assignments); } catch { assignments = null; }
|
||||
}
|
||||
const assignment = assignments?.layer_1;
|
||||
const isNewPlayerB = !!assignment && assignment.name === "new1_50" && assignment.enabled !== false
|
||||
&& ["B", "2"].includes(String(assignment.group).toUpperCase());
|
||||
return isNewPlayerB ? 15 : Number(config.triggerLevel);
|
||||
}
|
||||
|
||||
export function getUserSignInLevel(user: any) {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
import cloud from '@lafjs/cloud';
|
||||
const db = cloud.database();
|
||||
export default class Utils {
|
||||
static isNewPlayerB(user: any): boolean {
|
||||
let assignments = user?.abTests;
|
||||
if (typeof assignments === "string") {
|
||||
try { assignments = JSON.parse(assignments); } catch { return false; }
|
||||
}
|
||||
const assignment = assignments?.layer_1;
|
||||
return !!assignment && assignment.name === "new1_50" && assignment.enabled !== false
|
||||
&& ["B", "2"].includes(String(assignment.group).toUpperCase());
|
||||
}
|
||||
|
||||
static checkToken(token, token1) {
|
||||
if (token == token1) {
|
||||
//console.error("校验成功")
|
||||
|
|
|
|||
|
|
@ -53,7 +53,14 @@ export default async function (ctx: FunctionContext) {
|
|||
return;
|
||||
}
|
||||
// B组前15关只推进主线;补报跨过15关时也只计算门槛之后的胜利。
|
||||
const careerCount = Utils.isNewPlayerB(res1.data)
|
||||
let assignments = res1.data?.abTests;
|
||||
if (typeof assignments === "string") {
|
||||
try { assignments = JSON.parse(assignments); } catch { assignments = null; }
|
||||
}
|
||||
const assignment = assignments?.layer_1;
|
||||
const isNewPlayerB = !!assignment && assignment.name === "new1_50" && assignment.enabled !== false
|
||||
&& ["B", "2"].includes(String(assignment.group).toUpperCase());
|
||||
const careerCount = isNewPlayerB
|
||||
? Math.max(levelAmount - 15, 0) - Math.max(oldlevelAmount - 15, 0)
|
||||
: count;
|
||||
let add = oldAdd + careerCount;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ function withNewPlayerConfig(config) {
|
|||
return config;
|
||||
}
|
||||
|
||||
const ServerUtils = loadMembers('server/laf-cloud/functions/Utils.ts', ['isNewPlayerB']);
|
||||
const ServerUtils = loadMembers('server/laf-cloud/functions/Utils.ts', ['checkToken']);
|
||||
function loadModule(file, deps = {}, globals = {}) {
|
||||
const exports = {};
|
||||
const code = ts.transpileModule(fs.readFileSync(file, 'utf8'), {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ const config = (level = 0, group = 'B') => withNewPlayerConfig({ GM_INFO: {
|
|||
const json = file => JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
|
||||
test('front and back agree on B/2; A, missing, disabled and unrelated experiments keep defaults', () => {
|
||||
const service = loadModule('server/laf-cloud/functions/SignInActivity.ts', {
|
||||
'@lafjs/cloud': { default: { database: () => ({}) } }, crypto: require('node:crypto'),
|
||||
});
|
||||
for (const [raw, expected] of [
|
||||
[assignment('B'), true], [assignment(2), true], [assignment('2'), true],
|
||||
[assignment('A'), false], [assignment(1), false], [assignment('1'), false],
|
||||
|
|
@ -21,10 +24,10 @@ test('front and back agree on B/2; A, missing, disabled and unrelated experiment
|
|||
]) {
|
||||
const c = config(); c.GM_INFO.abTestAssignments = raw;
|
||||
assert.equal(c.isNewPlayerB(), expected);
|
||||
assert.equal(ServerUtils.isNewPlayerB({ abTests: raw }), expected);
|
||||
assert.equal(ServerUtils.isNewPlayerB({ abTests: JSON.stringify(raw) }), expected);
|
||||
assert.equal(service.getUserSignInTriggerLevel({ abTests: raw }, { triggerLevel: 23 }), expected ? 15 : 23);
|
||||
assert.equal(service.getUserSignInTriggerLevel({ abTests: JSON.stringify(raw) }, { triggerLevel: 23 }), expected ? 15 : 23);
|
||||
}
|
||||
assert.equal(ServerUtils.isNewPlayerB({ abTests: 'invalid' }), false);
|
||||
assert.equal(service.getUserSignInTriggerLevel({ abTests: 'invalid' }, { triggerLevel: 23 }), 23);
|
||||
});
|
||||
|
||||
test('B mainline switches at 50/51; A, help and endless keep Json', async () => {
|
||||
|
|
@ -144,11 +147,19 @@ test('front-end Career is hidden without counting through 15 and reused node app
|
|||
});
|
||||
|
||||
test('server counts only victories after 15, including batches crossing the boundary', async () => {
|
||||
for (const [group, oldLevel, level, expected] of [
|
||||
const cases = [
|
||||
['B', 0, 1, 0], ['B', 14, 15, 0], ['B', 15, 16, 1], ['B', 13, 18, 3],
|
||||
['B', 15, 20, 5], ['B', 18, 18, 0], ['B', 50, 51, 1], ['A', 14, 15, 1], [0, 0, 1, 1],
|
||||
]) {
|
||||
const user = { _id: 'user', levelAmount: oldLevel, addLevel: 0, abTests: assignment(group), film: 100, isWhite: true, address: '浙江' };
|
||||
[2, 14, 15, 0], ['2', 15, 16, 1],
|
||||
].map(([group, oldLevel, level, expected]) => [assignment(group), oldLevel, level, expected]);
|
||||
cases.push(
|
||||
[JSON.stringify(assignment('B')), 14, 15, 0], [JSON.stringify(assignment('A')), 14, 15, 1],
|
||||
[undefined, 14, 15, 1], ['invalid', 14, 15, 1],
|
||||
[{ layer_1: { name: 'another', group: 'B' } }, 14, 15, 1],
|
||||
[{ layer_1: { name: 'new1_50', group: 'B', enabled: false } }, 14, 15, 1],
|
||||
);
|
||||
for (const [abTests, oldLevel, level, expected] of cases) {
|
||||
const user = { _id: 'user', levelAmount: oldLevel, addLevel: 0, abTests, film: 100, isWhite: true, address: '浙江' };
|
||||
let update;
|
||||
const cloud = { database: () => ({ collection: () => ({ where: () => ({ getOne: async () => ({ data: user }),
|
||||
update: async payload => { update = payload; return { updated: 1 }; } }) }) }) };
|
||||
|
|
@ -158,7 +169,7 @@ test('server counts only victories after 15, including batches crossing the boun
|
|||
}, { process: { env: { SRANK_ID: 'rank' } } }).default;
|
||||
const result = await api({ body: { uid: 'user', action: 'save', levelAmount: level }, headers: {} });
|
||||
assert.equal(result.code, 1);
|
||||
assert.equal(update.addLevel, expected, `${group}: ${oldLevel} -> ${level}`);
|
||||
assert.equal(update.addLevel, expected, `${JSON.stringify(abTests)}: ${oldLevel} -> ${level}`);
|
||||
assert.equal(update.film, 100 + level - oldLevel, 'film still follows all cleared levels');
|
||||
assert.equal(update.levelAmount, level);
|
||||
}
|
||||
|
|
@ -166,7 +177,7 @@ test('server counts only victories after 15, including batches crossing the boun
|
|||
|
||||
test('seven-day activity uses B=15 while other players keep the configured trigger', () => {
|
||||
const service = loadModule('server/laf-cloud/functions/SignInActivity.ts', {
|
||||
'@lafjs/cloud': { default: { database: () => ({}) } }, '@/Utils': { default: ServerUtils }, crypto: require('node:crypto'),
|
||||
'@lafjs/cloud': { default: { database: () => ({}) } }, crypto: require('node:crypto'),
|
||||
});
|
||||
for (const group of ['A', 'B', 0, '2']) {
|
||||
assert.equal(service.getUserSignInTriggerLevel({ abTests: assignment(group) }, { triggerLevel: 23 }), ['B', '2'].includes(group) ? 15 : 23);
|
||||
|
|
@ -179,7 +190,7 @@ test('B seven-day activity activates at cleared level 15 and retains the origina
|
|||
get: async () => ({ data: [activity] }), update: async () => ({ updated: 1 }),
|
||||
}) }) }) };
|
||||
const service = loadModule('server/laf-cloud/functions/SignInActivity.ts', {
|
||||
'@lafjs/cloud': { default: cloud }, '@/Utils': { default: ServerUtils }, crypto: require('node:crypto'),
|
||||
'@lafjs/cloud': { default: cloud }, crypto: require('node:crypto'),
|
||||
});
|
||||
for (const [group, level, expected] of [['B', 14, false], ['B', 15, true], ['A', 15, false], ['A', 23, true]]) {
|
||||
const result = await service.activateSignInActivity({ _id: 'player', levelAmount: level, abTests: assignment(group) });
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user