MatchMaster/assets/coin_madness/CoinMadnessMockApi.ts

45 lines
2.8 KiB
TypeScript

/** Development-only fake service. Its balance never touches the player's wallet. */
export default class CoinMadnessMockApi {
private failNext = false;
constructor(private store: { read: () => any; write: (value: any) => void; level: () => number }, private now = () => Date.now()) {}
request(action: string, body: any = {}): any {
if (this.failNext) { this.failNext = false; return { code: 0, msg: '模拟接口失败,请重试' }; }
const now = this.now();
let state = this.store.read();
if (!state || action === 'reset') {
state = { config: { periodId: 'mock-' + now, title: '金币狂热 · 模拟版', startsAt: now,
endsAt: now + 7 * 86400000, priceCents: 99,
stages: [{ wins: 2, coins: 150 }, { wins: 3, coins: 200 }, { wins: 5, coins: 250 },
{ wins: 10, coins: 300 }, { wins: 15, coins: 400 }] },
paidAt: 0, stage: 0, totalWins: 0, baseline: 0, lastLevel: this.store.level(), settled: false, mockBalance: 1000 };
}
if (action === 'fail_next') this.failNext = true;
if (action === 'expire') state.config.endsAt = now;
const target = state.config.stages[state.stage];
const progress = Math.min(target ? target.wins : 0, state.totalWins - state.baseline);
let granted = 0;
if (now >= state.config.endsAt && !state.settled) {
if (state.paidAt && target && progress >= target.wins) { granted = target.coins; state.stage++; }
state.settled = true;
}
let msg = '';
if (action === 'purchase' || action === 'claim') {
if (body.periodId !== state.config.periodId) msg = '活动期次已变更,请刷新';
else if (now < state.config.startsAt || now >= state.config.endsAt) msg = '活动已结束或尚未开始';
else if (action === 'purchase' && !state.paidAt) {
state.paidAt = now; state.totalWins = 0; state.baseline = 0; state.lastLevel = this.store.level();
} else if (action === 'claim') {
if (!state.paidAt || body.stage !== state.stage || !target || progress < target.wins) msg = '当前奖励不可领取';
else { granted = target.coins; state.stage++; state.baseline = state.totalWins; }
}
}
if (action === 'simulate_win' && state.paidAt && !state.settled && now >= state.config.startsAt) state.totalWins++;
state.mockBalance += granted;
this.store.write(state);
const next = state.config.stages[state.stage];
const data = { available: true, serverNow: now, mockBalance: state.mockBalance, granted,
state: { ...state, progress: Math.min(next ? next.wins : 0, state.totalWins - state.baseline) } };
return msg ? { code: 0, msg, data } : { code: 1, data };
}
}