Kord/src/services/FeverService.ts

83 lines
2.4 KiB
TypeScript

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<void> {
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 };
}
}