45 lines
2.8 KiB
TypeScript
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 };
|
|
}
|
|
}
|