83 lines
2.4 KiB
TypeScript
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 };
|
|
}
|
|
}
|