110 lines
2.5 KiB
TypeScript
110 lines
2.5 KiB
TypeScript
import { getUserIdFromSession } from '../../utils/auth';
|
|
import { REWARDS } from '../../utils/economy';
|
|
import { PrismaClient } from '@prisma/client';
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
interface DailyVisitResponse {
|
|
message: string;
|
|
reward: {
|
|
coins: number;
|
|
streakBonus: boolean;
|
|
};
|
|
updatedCoins: number;
|
|
}
|
|
|
|
/**
|
|
* Creates a Date object for the start of a given day in UTC.
|
|
*/
|
|
function getStartOfDay(date: Date): Date {
|
|
const startOfDay = new Date(date);
|
|
startOfDay.setUTCHours(0, 0, 0, 0);
|
|
return startOfDay;
|
|
}
|
|
|
|
export default defineEventHandler(async (event): Promise<DailyVisitResponse> => {
|
|
const userId = await getUserIdFromSession(event);
|
|
const today = getStartOfDay(new Date());
|
|
|
|
// 1. Check if the user has already claimed the reward today
|
|
const existingVisit = await prisma.dailyVisit.findUnique({
|
|
where: {
|
|
userId_date: {
|
|
userId,
|
|
date: today,
|
|
},
|
|
},
|
|
});
|
|
|
|
if (existingVisit) {
|
|
throw createError({
|
|
statusCode: 409,
|
|
statusMessage: 'Daily visit reward has already been claimed today.',
|
|
});
|
|
}
|
|
|
|
// 2. Check for a 5-day consecutive streak (i.e., visits on the 4 previous days)
|
|
const previousDates = Array.from({ length: 4 }, (_, i) => {
|
|
const d = new Date(today);
|
|
d.setUTCDate(d.getUTCDate() - (i + 1));
|
|
return d;
|
|
});
|
|
|
|
const priorVisitsCount = await prisma.dailyVisit.count({
|
|
where: {
|
|
userId,
|
|
date: {
|
|
in: previousDates,
|
|
},
|
|
},
|
|
});
|
|
|
|
const hasStreak = priorVisitsCount === 4;
|
|
|
|
// 3. Calculate rewards and update the database in a transaction
|
|
let totalReward = REWARDS.QUESTS.DAILY_VISIT.BASE.coins;
|
|
let message = 'Daily visit claimed!';
|
|
if (hasStreak) {
|
|
totalReward += REWARDS.QUESTS.DAILY_VISIT.STREAK_BONUS.coins;
|
|
message = 'Daily visit and streak bonus claimed!';
|
|
}
|
|
|
|
const village = await prisma.village.findUnique({ where: { userId } });
|
|
|
|
const [, updatedUser] = await prisma.$transaction([
|
|
prisma.dailyVisit.create({
|
|
data: {
|
|
userId,
|
|
date: today,
|
|
},
|
|
}),
|
|
prisma.user.update({
|
|
where: { id: userId },
|
|
data: {
|
|
coins: {
|
|
increment: totalReward,
|
|
},
|
|
},
|
|
}),
|
|
...(village ? [prisma.villageEvent.create({
|
|
data: {
|
|
villageId: village.id,
|
|
type: 'QUEST_DAILY_VISIT',
|
|
message,
|
|
coins: totalReward,
|
|
exp: 0,
|
|
}
|
|
})] : []),
|
|
]);
|
|
|
|
// 4. Return the response
|
|
return {
|
|
message,
|
|
reward: {
|
|
coins: totalReward,
|
|
streakBonus: hasStreak,
|
|
},
|
|
updatedCoins: updatedUser.coins,
|
|
};
|
|
});
|