import { prisma } from '../database'; import { logger } from '../utils/logger'; import { ActivityTrackerService } from './ActivityTrackerService'; export class FeverService { private static BONUS_RATE = 0.1; // +10% 성공률 /** * 봇 시작 시 피버 스케줄러를 가동합니다. (1시간마다 체크) */ public static startScheduler() { // 1시간마다 전 서버의 피버 상태를 갱신하거나 분석을 시도하는 스케줄러 (간단히 setInterval) setInterval(async () => { try { const guilds = await prisma.guildConfig.findMany({ select: { guildId: true } }); for (const guild of guilds) { await this.updateFeverState(guild.guildId); } } catch (err) { logger.error('Fever scheduler error:', err); } }, 1000 * 60 * 60); // 1 hour } /** * 개별 서버의 피버 상태를 분석하고 갱신합니다. */ public static async updateFeverState(guildId: string): Promise { const peakHour = await ActivityTrackerService.getPeakHour(guildId); if (peakHour === null) return; const now = new Date(); const currentHour = now.getUTCHours(); // 현재 시간이 피크 시간대라면 피버 활성화 (1시간) const isActive = currentHour === peakHour; const expiresAt = isActive ? new Date(now.getTime() + 1000 * 60 * 60) : null; await prisma.feverState.upsert({ where: { guildId }, update: { isActive, peakHour, expiresAt, bonusRate: this.BONUS_RATE, }, create: { guildId, isActive, peakHour, expiresAt, bonusRate: this.BONUS_RATE, } }); if (isActive) { logger.info(`[Fever] Activated for guild ${guildId} (Peak Hour: ${peakHour})`); } } /** * 현재 피버 보너스 정보를 조회합니다. */ public static async getFeverBonus(guildId: string): Promise<{ active: boolean; bonusRate: number }> { const fever = await prisma.feverState.findUnique({ where: { guildId } }); if (!fever || !fever.isActive || !fever.expiresAt) { return { active: false, bonusRate: 0 }; } // 만료 체크 if (new Date() > fever.expiresAt) { await prisma.feverState.update({ where: { guildId }, data: { isActive: false } }); return { active: false, bonusRate: 0 }; } return { active: true, bonusRate: fever.bonusRate }; } }