import type { RewardEventType } from "@/generated/prisma/client"; // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- export interface RewardEvent { type: RewardEventType; message: string; } interface RewardContext { isFirstSession: boolean; streakMilestone: boolean; streakDays: number; stageAdvanced: boolean; newStage: number; totalSessionsCompleted: number; } // --------------------------------------------------------------------------- // Reward messages // --------------------------------------------------------------------------- const FIRST_SESSION_MESSAGES = [ "第一次练习完成了。这条路始于足下,不在于终点。", "第一天。你不是只想了想,你做到了。这就是一切的区别。", "欢迎开始你的练习。门已经打开了。明天,再走进来。", ]; const STREAK_3_MESSAGES = [ "连续三天。一个模式正在形成。你的心智开始期待这一刻——习惯正在扎根。", "第三天。前两次靠的是意志力。今天,是势头的开始。", ]; const STREAK_7_MESSAGES = [ "七天。一整周都在为自己出现。大多数人从未走到这么远。你做到了。", "一周的每日练习。你的大脑正在实实在在地重塑。神经可塑性不是比喻——它正在发生。", ]; const STREAK_14_MESSAGES = [ "两周。研究表明形成习惯需要21天——你已经走了三分之二,感觉已经不一样了,不是吗?", "连续十四天。你不再在「尝试冥想」。你是一个在练习的人。身份已经转变。", ]; const STREAK_30_MESSAGES = [ "三十天。一个月的每日练习。无论你开始前是什么样子——焦虑、散乱、反应——你正在变成另一个人。一个能观察自己的心并做出选择的人。", "一个月。这不再是一个连续记录。这是一项练习。它是你的一部分。问题不再是「我今天要不要练习?」,而是「什么时候?」", ]; const STAGE_UP_MESSAGES: Record = { 1: [ "你已经进入基础阶段。基本功已经到位。现在开始深入——更长的练习,更细微的觉察。", "阶段提升:基础。你从尝试进入了训练。练习正在成为熟悉的领域。", ], 2: [ "成长阶段已到。你的坚持是稳固的,你的觉知正在敏锐。这就是练习开始改变你如何在这个世界上行走的地方。", "阶段提升:成长。你度过了笨拙的初学者阶段。你的练习现在有了质感和深度。", ], 3: [ "稳固阶段。十五次练习和强劲的坚持度。你的内心世界正在变得清晰可读。这就是情绪素养在行动。", "阶段提升:稳固。你的练习扎下了根。从每天的练习开始,逐渐成为一种存在方式。", ], 4: [ "进阶。这是稀有的领域。大多数人从未发展出这个层次的内心觉知。你的练习现在渗透到你做的每一件事中。", "阶段提升:进阶。你不只是在练习觉知——你在活出它。「练习」和「生活」之间的界限正在消融。", ], }; const GENERIC_COMPLETION_MESSAGES = [ "完成。你出现了,你练习了,你反思了。这就是全部——而你在做着。", "练习完成。留意你现在的感受和之前的区别。那个转变就是意义所在。", "又一次练习记录在册。不是每一次练习都会感觉深刻——但每一次练习都很重要。", "你今天完成了功课。不是明天,不是「等事情平静下来的时候」——是今天。这就是自律,自律就是自爱。", "练习结束。你未来的自己——那个更清晰、更平静、更有选择权的自己——在感谢你。", ]; // --------------------------------------------------------------------------- // Reward generation // --------------------------------------------------------------------------- function pick(arr: T[]): T { return arr[Math.floor(Math.random() * arr.length)]; } export function generateRewards(ctx: RewardContext): RewardEvent[] { const rewards: RewardEvent[] = []; // First session — highest priority reward if (ctx.isFirstSession) { rewards.push({ type: "first_session", message: pick(FIRST_SESSION_MESSAGES), }); // Also give a daily completion reward rewards.push({ type: "daily_completion", message: pick(GENERIC_COMPLETION_MESSAGES), }); return rewards; } // Always give daily completion rewards.push({ type: "daily_completion", message: pick(GENERIC_COMPLETION_MESSAGES), }); // Streak milestones (only one per session, highest applicable) if (ctx.streakMilestone) { if (ctx.streakDays === 30) { rewards.push({ type: "streak_30", message: pick(STREAK_30_MESSAGES) }); } else if (ctx.streakDays === 14) { rewards.push({ type: "streak_14", message: pick(STREAK_14_MESSAGES) }); } else if (ctx.streakDays === 7) { rewards.push({ type: "streak_7", message: pick(STREAK_7_MESSAGES) }); } else if (ctx.streakDays === 3) { rewards.push({ type: "streak_3", message: pick(STREAK_3_MESSAGES) }); } } // Stage advancement if (ctx.stageAdvanced && ctx.newStage > 0) { const messages = STAGE_UP_MESSAGES[ctx.newStage]; if (messages) { rewards.push({ type: "stage_up", message: pick(messages) }); } } return rewards; } // --------------------------------------------------------------------------- // Persist rewards to database // --------------------------------------------------------------------------- export async function persistRewards( userId: string, rewards: RewardEvent[], prisma: { rewardEvent: { create: (args: { data: any }) => Promise } } ): Promise { await Promise.all( rewards.map((r) => prisma.rewardEvent.create({ data: { userId, type: r.type, message: r.message, }, }) ) ); }