feat(economy): implement streak and stats commands with detailed user feedback
This commit is contained in:
@@ -614,4 +614,645 @@ Tu bot tiene una **base excelente y muy completa**. Las sugerencias principales
|
||||
3. **Más visual:** DisplayComponents en todos lados
|
||||
4. **Más feedback:** Stats, logs, notificaciones
|
||||
|
||||
Ahora voy a crear el **comando de tienda completo con DisplayComponents** 🚀
|
||||
---
|
||||
|
||||
## 🛠️ Comandos Sugeridos para Implementar
|
||||
|
||||
### Comandos de Sistema de Logros
|
||||
```typescript
|
||||
// src/commands/messages/game/logros.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'logros',
|
||||
aliases: ['achievements', 'logro'],
|
||||
description: 'Ver tus logros y progreso',
|
||||
usage: 'logros [@usuario]',
|
||||
// ... implementación
|
||||
};
|
||||
|
||||
// src/commands/messages/admin/logro-crear.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'logro-crear',
|
||||
description: 'Crear un nuevo logro',
|
||||
usage: 'logro-crear <key>',
|
||||
// Usar editor interactivo similar a areaCreate.ts
|
||||
};
|
||||
```
|
||||
|
||||
### Comandos de Misiones
|
||||
```typescript
|
||||
// src/commands/messages/game/misiones.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'misiones',
|
||||
aliases: ['quests', 'mision'],
|
||||
description: 'Ver misiones disponibles y tu progreso',
|
||||
usage: 'misiones [categoria]',
|
||||
// Usar DisplayComponents para mostrar misiones visuales
|
||||
};
|
||||
|
||||
// src/commands/messages/game/mision-reclamar.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'mision-reclamar',
|
||||
aliases: ['claim-quest'],
|
||||
description: 'Reclamar recompensa de misión completada',
|
||||
usage: 'mision-reclamar <questId>',
|
||||
};
|
||||
```
|
||||
|
||||
### Comandos de Estadísticas
|
||||
```typescript
|
||||
// src/commands/messages/game/stats.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'stats',
|
||||
aliases: ['estadisticas', 'statistics'],
|
||||
description: 'Ver estadísticas detalladas de un jugador',
|
||||
usage: 'stats [@usuario]',
|
||||
// Mostrar con DisplayComponents estilo tarjeta
|
||||
};
|
||||
|
||||
// src/commands/messages/game/ranking-stats.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'ranking-stats',
|
||||
aliases: ['top-stats'],
|
||||
description: 'Ver ranking de jugadores por estadísticas',
|
||||
usage: 'ranking-stats [categoria]',
|
||||
// Categorías: minas, pesca, combate, monedas, etc.
|
||||
};
|
||||
```
|
||||
|
||||
### Comandos de Tienda Mejorada
|
||||
```typescript
|
||||
// src/commands/messages/game/tienda.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'tienda',
|
||||
aliases: ['shop', 'store'],
|
||||
description: 'Ver la tienda del servidor con interfaz visual',
|
||||
usage: 'tienda [categoria] [pagina]',
|
||||
// Usar DisplayComponents con:
|
||||
// - Categorías en botones
|
||||
// - Paginación
|
||||
// - Botones de compra rápida
|
||||
// - Preview de items con stats
|
||||
};
|
||||
```
|
||||
|
||||
### Comandos de Rachas
|
||||
```typescript
|
||||
// src/commands/messages/game/racha.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'racha',
|
||||
aliases: ['streak', 'daily'],
|
||||
description: 'Ver tu racha diaria y reclamar recompensa',
|
||||
usage: 'racha',
|
||||
// Auto-incrementa si jugaste hoy
|
||||
// Muestra recompensa del día
|
||||
};
|
||||
```
|
||||
|
||||
### Comandos de Cooldowns
|
||||
```typescript
|
||||
// src/commands/messages/game/cooldowns.ts
|
||||
export const command: CommandMessage = {
|
||||
name: 'cooldowns',
|
||||
aliases: ['cds', 'tiempos'],
|
||||
description: 'Ver todos tus cooldowns activos',
|
||||
usage: 'cooldowns',
|
||||
// Lista todos los cooldowns con tiempo restante
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Servicios a Crear
|
||||
|
||||
### 1. Achievement Service
|
||||
```typescript
|
||||
// src/game/achievements/service.ts
|
||||
|
||||
export async function checkAchievements(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
trigger: string
|
||||
) {
|
||||
// Verificar logros desbloqueables basados en el trigger
|
||||
// Triggers: "mine", "fish", "combat", "craft", etc.
|
||||
// Retornar array de logros nuevos desbloqueados
|
||||
}
|
||||
|
||||
export async function unlockAchievement(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
achievementKey: string
|
||||
) {
|
||||
// Desbloquear logro
|
||||
// Dar recompensas
|
||||
// Crear notificación
|
||||
}
|
||||
|
||||
export async function getAchievementProgress(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
achievementKey: string
|
||||
) {
|
||||
// Calcular progreso actual del logro
|
||||
// Retornar porcentaje y valores
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Quest Service
|
||||
```typescript
|
||||
// src/game/quests/service.ts
|
||||
|
||||
export async function generateDailyQuests(guildId: string) {
|
||||
// Generar misiones diarias aleatorias
|
||||
// Llamar cada día a medianoche
|
||||
}
|
||||
|
||||
export async function updateQuestProgress(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
questType: string,
|
||||
increment: number = 1
|
||||
) {
|
||||
// Actualizar progreso de misiones activas
|
||||
// Completar automáticamente si alcanza el objetivo
|
||||
}
|
||||
|
||||
export async function claimQuestReward(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
questId: string
|
||||
) {
|
||||
// Verificar que esté completada
|
||||
// Dar recompensas
|
||||
// Marcar como reclamada
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Stats Service
|
||||
```typescript
|
||||
// src/game/stats/service.ts
|
||||
|
||||
export async function updateStats(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
updates: Partial<PlayerStats>
|
||||
) {
|
||||
// Actualizar stats del jugador
|
||||
// Verificar récords
|
||||
// Llamar desde otros servicios
|
||||
}
|
||||
|
||||
export async function getLeaderboard(
|
||||
guildId: string,
|
||||
category: string,
|
||||
limit: number = 10
|
||||
) {
|
||||
// Obtener top jugadores en una categoría
|
||||
// Categorías: totalMines, mobsDefeated, coinsEarned, etc.
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Streak Service
|
||||
```typescript
|
||||
// src/game/streaks/service.ts
|
||||
|
||||
export async function updateStreak(
|
||||
userId: string,
|
||||
guildId: string
|
||||
) {
|
||||
// Actualizar racha diaria
|
||||
// Resetear si pasó más de 1 día
|
||||
// Retornar recompensa del día
|
||||
}
|
||||
|
||||
export async function getStreakReward(day: number) {
|
||||
// Calcular recompensa según el día de racha
|
||||
// Escalar recompensas por día
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Mejoras al Código Existente
|
||||
|
||||
### 1. Centralizar Manejo de Recompensas
|
||||
```typescript
|
||||
// src/game/rewards/service.ts
|
||||
|
||||
export interface Reward {
|
||||
coins?: number;
|
||||
items?: Array<{ key: string; quantity: number }>;
|
||||
xp?: number;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export async function giveRewards(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
rewards: Reward,
|
||||
source: string // "achievement", "quest", "streak", etc.
|
||||
) {
|
||||
const results = [];
|
||||
|
||||
if (rewards.coins) {
|
||||
await adjustCoins(userId, guildId, rewards.coins);
|
||||
results.push(`💰 ${rewards.coins} monedas`);
|
||||
}
|
||||
|
||||
if (rewards.items) {
|
||||
for (const item of rewards.items) {
|
||||
await addItemByKey(userId, guildId, item.key, item.quantity);
|
||||
results.push(`📦 ${item.quantity}x ${item.key}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Log para auditoría
|
||||
await prisma.auditLog.create({
|
||||
data: {
|
||||
userId,
|
||||
guildId,
|
||||
action: 'reward_given',
|
||||
target: source,
|
||||
details: rewards
|
||||
}
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Mejorar Sistema de Notificaciones
|
||||
```typescript
|
||||
// src/core/lib/notifications.ts
|
||||
|
||||
export async function notifyAchievement(
|
||||
user: User,
|
||||
guild: Guild,
|
||||
achievement: Achievement
|
||||
) {
|
||||
// Enviar DM al usuario
|
||||
// O mensaje en canal específico
|
||||
// Con DisplayComponents mostrando el logro
|
||||
}
|
||||
|
||||
export async function notifyQuestComplete(
|
||||
user: User,
|
||||
guild: Guild,
|
||||
quest: Quest
|
||||
) {
|
||||
// Notificar que puede reclamar recompensa
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Helpers para DisplayComponents
|
||||
```typescript
|
||||
// src/core/lib/display-helpers.ts
|
||||
|
||||
export function createItemCard(item: EconomyItem): DisplayComponent {
|
||||
return {
|
||||
type: 'container',
|
||||
layout: 'vertical',
|
||||
components: [
|
||||
{
|
||||
type: 'image',
|
||||
url: item.iconUrl || 'default-item.png',
|
||||
alt: item.name
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
content: `**${item.name}**\n${item.description}`,
|
||||
style: 'bold'
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
content: `💰 ${item.basePrice} monedas`,
|
||||
style: 'muted'
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
export function createProgressBar(
|
||||
current: number,
|
||||
total: number,
|
||||
width: number = 10
|
||||
): string {
|
||||
const filled = Math.floor((current / total) * width);
|
||||
const empty = width - filled;
|
||||
return '█'.repeat(filled) + '░'.repeat(empty) + ` ${current}/${total}`;
|
||||
}
|
||||
|
||||
export function createStatCard(
|
||||
title: string,
|
||||
stats: Record<string, number>
|
||||
): DisplayComponent {
|
||||
return {
|
||||
type: 'embed',
|
||||
title: title,
|
||||
fields: Object.entries(stats).map(([key, value]) => ({
|
||||
name: key,
|
||||
value: value.toString(),
|
||||
inline: true
|
||||
}))
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Integración con Sistema Existente
|
||||
|
||||
### Hooks en Comandos Existentes
|
||||
|
||||
Añadir estas llamadas a los comandos que ya tienes:
|
||||
|
||||
```typescript
|
||||
// En src/commands/messages/game/mina.ts
|
||||
import { updateStats } from '../../../game/stats/service';
|
||||
import { updateQuestProgress } from '../../../game/quests/service';
|
||||
import { checkAchievements } from '../../../game/achievements/service';
|
||||
|
||||
// Después de minar exitosamente:
|
||||
await updateStats(userId, guildId, { minesCompleted: 1 });
|
||||
await updateQuestProgress(userId, guildId, 'mine', 1);
|
||||
const newAchievements = await checkAchievements(userId, guildId, 'mine');
|
||||
|
||||
// Similar en pescar.ts, pelear.ts, craftear.ts, etc.
|
||||
```
|
||||
|
||||
### Cron Jobs para Sistema de Misiones
|
||||
|
||||
```typescript
|
||||
// src/core/cron/daily-reset.ts
|
||||
import cron from 'node-cron';
|
||||
|
||||
export function setupDailyReset() {
|
||||
// Ejecutar cada día a medianoche (hora del servidor)
|
||||
cron.schedule('0 0 * * *', async () => {
|
||||
const guilds = await prisma.guild.findMany();
|
||||
|
||||
for (const guild of guilds) {
|
||||
// Generar nuevas misiones diarias
|
||||
await generateDailyQuests(guild.id);
|
||||
|
||||
// Limpiar misiones expiradas
|
||||
await cleanExpiredQuests(guild.id);
|
||||
|
||||
// Actualizar rachas
|
||||
// (se actualizan automáticamente al usar comandos)
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Métricas y Analytics
|
||||
|
||||
### Tracking de Uso
|
||||
```typescript
|
||||
// src/core/analytics/tracker.ts
|
||||
|
||||
export async function trackCommand(
|
||||
userId: string,
|
||||
guildId: string,
|
||||
commandName: string
|
||||
) {
|
||||
await prisma.auditLog.create({
|
||||
data: {
|
||||
userId,
|
||||
guildId,
|
||||
action: 'command_used',
|
||||
target: commandName,
|
||||
details: { timestamp: new Date() }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function getCommandStats(guildId: string, days: number = 7) {
|
||||
// Obtener comandos más usados
|
||||
// Usuarios más activos
|
||||
// Horas pico de uso
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Plan de Implementación Sugerido
|
||||
|
||||
### Fase 1: Engagement Básico (Sprint 1-2)
|
||||
1. ✅ Implementar `PlayerStats` y servicio
|
||||
2. ✅ Añadir tracking en comandos existentes
|
||||
3. ✅ Crear comando `!stats`
|
||||
4. ✅ Crear comando `!cooldowns`
|
||||
|
||||
### Fase 2: Sistema de Logros (Sprint 3-4)
|
||||
1. ✅ Implementar Achievement Service
|
||||
2. ✅ Crear logros básicos (10-15)
|
||||
3. ✅ Integrar checks en comandos
|
||||
4. ✅ Crear comando `!logros`
|
||||
5. ✅ Sistema de notificaciones
|
||||
|
||||
### Fase 3: Misiones Diarias (Sprint 5-6)
|
||||
1. ✅ Implementar Quest System
|
||||
2. ✅ Crear misiones diarias/semanales
|
||||
3. ✅ Cron job para reset diario
|
||||
4. ✅ Comandos de misiones
|
||||
5. ✅ UI con DisplayComponents
|
||||
|
||||
### Fase 4: Rachas y Recompensas (Sprint 7)
|
||||
1. ✅ Implementar Streak System
|
||||
2. ✅ Comando `!racha` con recompensas
|
||||
3. ✅ Integrar con sistema de recompensas
|
||||
|
||||
### Fase 5: Tienda Mejorada (Sprint 8)
|
||||
1. ✅ Refactorizar comando tienda
|
||||
2. ✅ DisplayComponents avanzados
|
||||
3. ✅ Categorías y filtros
|
||||
4. ✅ Compra rápida con botones
|
||||
|
||||
### Fase 6: Rankings y Social (Sprint 9-10)
|
||||
1. ✅ Rankings por categorías
|
||||
2. ✅ Leaderboards globales
|
||||
3. ✅ Sistema de menciones/comparación
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Ejemplos Visuales de DisplayComponents
|
||||
|
||||
### Logro Desbloqueado
|
||||
```typescript
|
||||
{
|
||||
type: 'embed',
|
||||
color: 0xFFD700, // Dorado
|
||||
title: '🏆 ¡Logro Desbloqueado!',
|
||||
description: '**Primera Mina**\nHas minado por primera vez',
|
||||
thumbnail: 'achievement-first-mine.png',
|
||||
fields: [
|
||||
{
|
||||
name: '💰 Recompensa',
|
||||
value: '500 monedas',
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: '📊 Progreso',
|
||||
value: '1/100 logros',
|
||||
inline: true
|
||||
}
|
||||
],
|
||||
footer: 'Usa !logros para ver todos tus logros'
|
||||
}
|
||||
```
|
||||
|
||||
### Misión Completada
|
||||
```typescript
|
||||
{
|
||||
type: 'embed',
|
||||
color: 0x00FF00, // Verde
|
||||
title: '✅ Misión Completada!',
|
||||
description: '**Minero Diario**\nMina 10 veces',
|
||||
fields: [
|
||||
{
|
||||
name: '📦 Recompensas',
|
||||
value: '• 1000 monedas\n• 3x Pico de Hierro\n• 50 XP',
|
||||
inline: false
|
||||
}
|
||||
],
|
||||
components: [
|
||||
{
|
||||
type: 'button',
|
||||
label: 'Reclamar',
|
||||
style: 'success',
|
||||
customId: 'claim_quest_123'
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Stats del Jugador
|
||||
```typescript
|
||||
{
|
||||
type: 'embed',
|
||||
color: 0x5865F2, // Discord Blurple
|
||||
title: '📊 Estadísticas de @Usuario',
|
||||
thumbnail: 'user-avatar.png',
|
||||
fields: [
|
||||
{ name: '⛏️ Minas', value: '234', inline: true },
|
||||
{ name: '🎣 Pesca', value: '156', inline: true },
|
||||
{ name: '⚔️ Combates', value: '89', inline: true },
|
||||
{ name: '💰 Monedas Ganadas', value: '456,789', inline: true },
|
||||
{ name: '🛠️ Items Crafteados', value: '67', inline: true },
|
||||
{ name: '👾 Mobs Derrotados', value: '423', inline: true },
|
||||
{ name: '🏆 Logros', value: '23/100', inline: true },
|
||||
{ name: '🔥 Racha Actual', value: '12 días', inline: true },
|
||||
{ name: '⭐ Nivel', value: '15', inline: true }
|
||||
],
|
||||
footer: 'Jugando desde: 15 Ene 2024'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Tips de Optimización
|
||||
|
||||
### 1. Caché para Queries Frecuentes
|
||||
```typescript
|
||||
import { Cache } from 'node-cache';
|
||||
|
||||
const leaderboardCache = new Cache({ stdTTL: 300 }); // 5 minutos
|
||||
|
||||
export async function getCachedLeaderboard(guildId: string, category: string) {
|
||||
const cacheKey = `leaderboard:${guildId}:${category}`;
|
||||
|
||||
let data = leaderboardCache.get(cacheKey);
|
||||
if (data) return data;
|
||||
|
||||
data = await getLeaderboard(guildId, category);
|
||||
leaderboardCache.set(cacheKey, data);
|
||||
|
||||
return data;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Batch Updates para Stats
|
||||
```typescript
|
||||
// En lugar de actualizar cada stat individualmente
|
||||
// Acumular y hacer update único al final del comando
|
||||
|
||||
const statsUpdates = {
|
||||
minesCompleted: 1,
|
||||
totalCoinsEarned: reward
|
||||
};
|
||||
|
||||
await updateStats(userId, guildId, statsUpdates);
|
||||
```
|
||||
|
||||
### 3. Índices en Prisma
|
||||
Ya los tienes definidos, asegúrate de que estén aplicados:
|
||||
```bash
|
||||
npx prisma migrate dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Checklist de Implementación
|
||||
|
||||
### Antes de Empezar
|
||||
- [ ] Backup de la base de datos
|
||||
- [ ] Branch nueva en Git
|
||||
- [ ] Revisar modelos de Prisma actuales
|
||||
- [ ] Planificar migraciones
|
||||
|
||||
### Durante Implementación
|
||||
- [ ] Tests unitarios para servicios nuevos
|
||||
- [ ] Documentar APIs internas
|
||||
- [ ] Validación de inputs
|
||||
- [ ] Manejo de errores
|
||||
- [ ] Logs apropiados
|
||||
|
||||
### Después de Implementar
|
||||
- [ ] Pruebas en servidor de desarrollo
|
||||
- [ ] Code review
|
||||
- [ ] Actualizar documentación de usuario
|
||||
- [ ] Deploy gradual
|
||||
- [ ] Monitorear métricas
|
||||
|
||||
---
|
||||
|
||||
## 📚 Recursos Adicionales
|
||||
|
||||
### Documentación Útil
|
||||
- [Discord.js Guide](https://discordjs.guide/)
|
||||
- [Prisma Docs](https://www.prisma.io/docs)
|
||||
- [Discord Interactions](https://discord.com/developers/docs/interactions/overview)
|
||||
|
||||
### Herramientas Recomendadas
|
||||
- **Bull/BullMQ**: Para cron jobs y queues
|
||||
- **node-cache**: Para caché en memoria
|
||||
- **zod**: Para validación de schemas
|
||||
- **winston**: Para logging avanzado
|
||||
|
||||
---
|
||||
|
||||
## ✨ Conclusión Final
|
||||
|
||||
Tu proyecto **Amayo** es impresionante y tiene todos los componentes base necesarios. Con estas mejoras sugeridas, puedes convertirlo en un bot de economía y RPG de nivel profesional que mantenga a los usuarios enganchados por meses.
|
||||
|
||||
Las prioridades recomendadas son:
|
||||
|
||||
**Inmediato (Semana 1-2):**
|
||||
- Sistema de Stats completo
|
||||
- Comando cooldowns
|
||||
- Mejorar comando tienda
|
||||
|
||||
**Corto Plazo (Mes 1):**
|
||||
- Sistema de logros básico
|
||||
- Misiones diarias
|
||||
- Sistema de rachas
|
||||
|
||||
**Mediano Plazo (Mes 2-3):**
|
||||
- Sistema de clanes
|
||||
- Eventos temporales
|
||||
- Trading entre jugadores
|
||||
|
||||
¡Mucho éxito con el desarrollo! 🚀
|
||||
|
||||
Reference in New Issue
Block a user