Structure: - control-plane/: Registries, SIMCO directives, CI/CD templates - projects/: Gamilit, ERP-Suite, Trading-Platform, Betting-Analytics - shared/: Libs catalog, knowledge-base Key features: - Centralized port, domain, database, and service registries - 23 SIMCO directives + 6 fundamental principles - NEXUS agent profiles with delegation rules - Validation scripts for workspace integrity - Dockerfiles for all services - Path aliases for quick reference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
23 KiB
RF-GAM-004: Economía de ML Coins (Maya Learning Coins)
📋 Metadata
| Campo | Valor |
|---|---|
| ID | RF-GAM-004 |
| Módulo | 02 - Gamificación |
| Título | Economía de ML Coins (Maya Learning Coins) |
| Prioridad | Alta |
| Estado | ✅ Implementado |
| Versión | 2.1 (DB-099: tenant_id support) |
| Fecha Creación | 2025-11-08 |
| Última Actualización | 2025-11-11 (DB-099) |
| Autor | Database Team |
| Stakeholders | Product Owner, UX Team, Backend Team, Frontend Team, Game Designer |
🔗 Referencias
Implementación DDL
🗄️ Tablas Relacionadas:
-
gamification_system.user_stats- Ubicación:
apps/database/ddl/schemas/gamification_system/tables/user_stats.sql - Propósito: Almacena balance actual de ML Coins y totales históricos
- Columnas clave:
ml_coins(INTEGER): Balance actual de ML Coinsml_coins_earned_total(INTEGER): Total histórico ganadoml_coins_spent_total(INTEGER): Total histórico gastado
- Ubicación:
-
gamification_system.ml_coins_transactions- Ubicación:
apps/database/ddl/schemas/gamification_system/tables/05-ml_coins_transactions.sql - Propósito: Registro completo de todas las transacciones de ML Coins
- Columnas clave:
id(UUID): ID único de transacciónuser_id(UUID): Usuario que realiza la transaccióntenant_id(UUID): ✨ NUEVO DB-099 - ID del tenant (multi-tenancy support)amount(INTEGER): Monto de la transacción (con multiplicador aplicado)balance_before(INTEGER): Balance antes de la transacciónbalance_after(INTEGER): Balance después de la transaccióntransaction_type(ENUM): Tipo de transacción (14 tipos)multiplier(NUMERIC): Multiplicador aplicado (ej: 1.25x por rango)metadata(JSONB): Información adicional (base_amount, rank, etc.)created_at(TIMESTAMPTZ): Timestamp de la transacción
- Ubicación:
🗄️ ENUM Canónico:
- Ubicación:
apps/database/ddl/schemas/gamification_system/enums/transaction_type.sql - Tipo:
gamification_system.transaction_type - Valores: 14 tipos (7 earned, 3 spent, 4 admin)
🗄️ Funciones SQL:
award_ml_coins(user_id, amount, transaction_type, description, reference_id, reference_type)- Ubicación:
apps/database/ddl/schemas/gamification_system/functions/award_ml_coins.sql - Propósito: Otorgar ML Coins al usuario aplicando multiplicador de rango
- Validaciones:
- Obtiene rango actual del usuario
- Aplica multiplicador según rango Maya (1.00x - 2.00x)
- Actualiza balance con
FOR UPDATE(previene race conditions) - Registra transacción con metadata completa
- Ubicación:
Especificación Técnica
📘 Documento ET Relacionado:
- ET-GAM-004: Tipos Compartidos de Gamificación
- ET-GAM-003: Rangos Maya - Multiplicadores de rango
- ET-GAM-002: Sistema de Comodines - Gastos de ML Coins
Documentos Relacionados
- RF-GAM-002: Sistema de Comodines - Principal uso de ML Coins
- RF-GAM-003: Rangos Maya - Multiplicadores por rango
- RF-GAM-001: Sistema de Achievements - Fuente de ML Coins
📖 Descripción General
Propósito
El sistema de ML Coins (Maya Learning Coins) es la moneda virtual principal de la plataforma Gamilit. Proporciona:
- Motivación económica: Los estudiantes ganan coins por actividades de aprendizaje
- Sistema de recompensas: Progresión tangible y medible
- Economía de recursos escasos: Decisiones estratégicas sobre cómo gastar coins
- Gamificación profunda: Feedback inmediato por logros
Contexto
Los ML Coins son el núcleo del sistema de gamificación de Gamilit:
- Se ganan completando ejercicios, módulos, achievements, rachas, etc.
- Se multiplican según el rango Maya del usuario (1.00x - 2.00x)
- Se gastan en comodines (power-ups), pistas, reintentos
- Se rastrean con historial completo de transacciones
🎯 Objetivos del Sistema
Objetivos Primarios
-
Incentivar el aprendizaje activo
- Recompensar inmediatamente actividades educativas
- Crear ciclo de feedback positivo
- Motivar a completar contenido
-
Promover progresión y maestría
- Mayores recompensas por contenido difícil
- Multiplicadores por rango premian veteranos
- Balance entre nuevos y experimentados
-
Habilitar toma de decisiones estratégicas
- Recursos escasos requieren planificación
- Decisión: ¿guardar o gastar?
- Enseña administración de recursos
Objetivos Secundarios
-
Crear economía sostenible
- Balance entre earning y spending
- Prevenir inflación de coins
- Evitar acumulación excesiva
-
Facilitar análisis y métricas
- Trackear engagement por tipo de actividad
- Identificar usuarios en riesgo
- Optimizar recompensas basado en datos
📊 Flujos de ML Coins
1. Earning (Ganancia de Coins)
1.1 Por Actividad Educativa
Ejercicios Completados (earned_exercise)
- Monto base: 5-50 ML Coins (según dificultad)
- Multiplicador: Según rango Maya (1.00x - 2.00x)
- Trigger: Al completar ejercicio exitosamente
- Ejemplo:
- Estudiante Ajaw (1.00x) completa ejercicio medio (20 coins)
- Recibe: 20 * 1.00 = 20 ML Coins
- Estudiante K'uk'ulkan (2.00x) completa mismo ejercicio
- Recibe: 20 * 2.00 = 40 ML Coins
Módulos Completados (earned_module)
- Monto base: 100-300 ML Coins (según módulo)
- Multiplicador: Según rango Maya
- Trigger: Al completar 100% de ejercicios del módulo
- Ejemplo:
- Módulo "Comprensión Literal" = 150 coins base
- Nacom (1.25x): 150 * 1.25 = 188 ML Coins
Achievements Desbloqueados (earned_achievement)
- Monto base: 50-500 ML Coins (según rareza)
- Común: 50 coins
- Raro: 100 coins
- Épico: 250 coins
- Legendario: 500 coins
- Multiplicador: Según rango Maya
- Trigger: Al cumplir condiciones del achievement
1.2 Por Progresión y Engagement
Subida de Rango (earned_rank)
- Monto: 100-1000 ML Coins (según rango alcanzado) ✅ IMPLEMENTADO
- Ajaw → Nacom: 100 coins (al alcanzar 500 XP)
- Nacom → Ah K'in: 250 coins (al alcanzar 1,000 XP)
- Ah K'in → Halach Uinic: 500 coins (al alcanzar 1,500 XP)
- Halach Uinic → K'uk'ulkan: 1,000 coins (al alcanzar 2,250 XP)
- Multiplicador: NO aplica (recompensa fija)
- Trigger: Al alcanzar XP requerido para nuevo rango
Racha de Días (earned_streak)
- Monto: 10-100 ML Coins (según días consecutivos)
- 3 días: 10 coins
- 7 días: 25 coins
- 14 días: 50 coins
- 30 días: 100 coins
- Multiplicador: Según rango Maya
- Trigger: Al mantener racha activa
Login Diario (earned_daily)
- Monto: 50 ML Coins
- Multiplicador: Según rango Maya
- Trigger: Primer login del día
- Límite: 1 vez por día
Bonus Especial (earned_bonus)
- Monto: Variable (definido por evento)
- Multiplicador: Según rango Maya
- Trigger: Eventos especiales, promociones, desafíos
- Ejemplo: "Semana de la Lectura" +200 coins por completar módulo
2. Spending (Gasto de Coins)
2.1 Comodines (Power-ups)
Pistas Contextuales (spent_powerup - pistas)
- Costo: -15 ML Coins
- Beneficio: Muestra 2-3 pistas sobre respuesta correcta
- Límite: 3 por ejercicio
- Uso estratégico: Para ejercicios difíciles sin perder intento
Visión Lectora (spent_powerup - vision_lectora)
- Costo: -25 ML Coins
- Beneficio: Resalta pasajes clave del texto
- Límite: 1 por ejercicio
- Uso estratégico: Para textos largos y complejos
Segunda Oportunidad (spent_powerup - segunda_oportunidad)
- Costo: -40 ML Coins
- Beneficio: Permite reintento sin penalización de XP
- Límite: 1 por ejercicio
- Uso estratégico: Para ejercicios críticos
2.2 Ayudas Adicionales
Pista Simple (spent_hint)
- Costo: -10 ML Coins
- Beneficio: Pista contextual individual
- Límite: Ilimitado (costoso)
Reintento de Ejercicio (spent_retry)
- Costo: -20 ML Coins
- Beneficio: Reiniciar ejercicio fallado
- Límite: Ilimitado
3. Administrativo y Sistema
Ajuste Manual (admin_adjustment)
- Monto: Variable (+ o -)
- Propósito: Correcciones, compensaciones, regalos
- Autorización: Solo administradores
- Ejemplo: Compensar bug que afectó a usuarios
Reembolso (refund)
- Monto: Positivo (devolución)
- Propósito: Devolver coins por compra errónea o bug
- Trigger: Solicitud de usuario o detección automática
Bonus General (bonus)
- Monto: Positivo
- Propósito: Bonos del sistema no categorizados
- Ejemplo: Recompensa por participar en beta testing
Bonus de Bienvenida (welcome_bonus)
- Monto: +100 ML Coins
- Propósito: Dar capital inicial a nuevos usuarios
- Trigger: Registro de nueva cuenta (una sola vez)
🔢 Economía y Balance
Multiplicadores por Rango Maya
⚠️ NOTA IMPORTANTE (2025-11-19): Los multiplicadores ML Coins descritos aquí están PENDIENTES DE IMPLEMENTACIÓN.
| Rango | Nivel | Multiplicador ML Coins (Documentado) | Multiplicador XP (Implementado) | Estado |
|---|---|---|---|---|
| Ajaw | 1 | 1.00x | 1.00x | ✅ XP: Implementado |
| Nacom | 2 | 1.25x (+25%) | 1.10x (+10%) | ❌ ML: No implementado |
| Ah K'in | 3 | 1.50x (+50%) | 1.15x (+15%) | ❌ ML: No implementado |
| Halach Uinic | 4 | 1.75x (+75%) | 1.20x (+20%) | ❌ ML: No implementado |
| K'uk'ulkan | 5 | 2.00x (+100%) | 1.25x (+25%) | ❌ ML: No implementado |
Estado Actual:
- ✅ Multiplicadores XP: Implementados y funcionales (1.00x - 1.25x)
- ❌ Multiplicadores ML Coins: Documentados pero NO implementados en DB v2.0
- ✅ Bonus ML Coins (único por promoción): Implementados (100-1000 ML)
Funcionalidad NO Implementada:
-- ❌ Esta columna NO existe en la tabla maya_ranks:
ml_coins_multiplier NUMERIC(3,2)
-- ✅ Lo que SÍ existe:
ml_coins_bonus INTEGER -- Bonus único al promover
xp_multiplier NUMERIC(3,2) -- Multiplicador XP
Decisión Pendiente: Product Owner debe decidir si implementar multiplicadores ML Coins o simplificar economía manteniendo solo bonus únicos.
Ver:
- ET-GAM-003: Rangos Maya para multiplicadores XP implementados
- docs/04-fase-backlog/FUNCIONALIDADES-GAMIFICACION-PENDIENTES.md para análisis detallado
Earning vs Spending Estimado
Earning Típico (Usuario Activo - Ajaw 1.00x):
- 10 ejercicios/día: 10 * 20 = 200 coins
- 1 módulo/semana: 150 coins
- 1 achievement/semana: 100 coins
- Login diario: 50 coins
- Total semanal: ~1,300 ML Coins
Spending Típico:
- 3 pistas/semana: 3 * 15 = 45 coins
- 1 visión lectora/semana: 25 coins
- 1 segunda oportunidad/semana: 40 coins
- Total semanal: ~110 ML Coins
Balance: +1,190 ML Coins/semana (positivo, permite acumulación)
Objetivo: Usuarios deben poder acumular coins pero sentir que son valiosos (no triviales).
📐 Reglas de Negocio
Regla 1: No Negativos
Descripción: El balance de ML Coins de un usuario nunca puede ser negativo.
Implementación:
- CHECK constraint en tabla
user_stats:ml_coins >= 0 - Validación en función
spend_ml_coins()antes de restar - Frontend previene compra si balance insuficiente
Ejemplo:
Usuario tiene: 25 ML Coins
Quiere comprar: Segunda Oportunidad (40 coins)
Resultado: ❌ Transacción rechazada "Balance insuficiente"
Regla 2: Multiplicador se Aplica Solo a Earning
Descripción: El multiplicador de rango Maya se aplica solo a coins ganados, no a gastos.
Implementación:
- Función
award_ml_coins()aplica multiplicador - Función
spend_ml_coins()usa monto exacto (sin multiplicador)
Ejemplo:
K'uk'ulkan (2.00x) gana 100 coins → Recibe 200 coins
K'uk'ulkan gasta en pista (15 coins) → Paga exactamente 15 coins
Regla 3: Transacciones Atómicas
Descripción: Cada transacción de ML Coins debe ser atómica (todo o nada).
Implementación:
- Uso de
FOR UPDATEpara bloquear fila durante transacción - Rollback automático si falla cualquier paso
- Registro de transacción solo si update exitoso
Regla 4: Auditoría Completa
Descripción: Todas las transacciones deben quedar registradas permanentemente.
Implementación:
- Tabla
ml_coins_transactionssin DELETE - Metadata JSONB con detalles (base_amount, rank, multiplier)
- Columnas
balance_beforeybalance_afterpara auditoría
Regla 5: Redondeo hacia Abajo
Descripción: Montos con decimales se redondean hacia abajo (FLOOR).
Implementación:
v_final_amount := FLOOR(p_amount * v_multiplier);
Ejemplo:
Base: 33 coins
Multiplicador Nacom: 1.25x
Cálculo: 33 * 1.25 = 41.25
Resultado: FLOOR(41.25) = 41 coins
🎮 Casos de Uso
Caso de Uso 1: Estudiante Completa Ejercicio
Actor: Estudiante (usuario autenticado)
Precondiciones:
- Usuario tiene cuenta activa
- Usuario tiene rango Maya asignado
- Ejercicio disponible y no completado previamente
Flujo Principal:
- Usuario resuelve ejercicio correctamente
- Sistema obtiene rango Maya del usuario
- Sistema calcula monto base según dificultad del ejercicio
- Sistema aplica multiplicador de rango
- Sistema llama
award_ml_coins() - Se actualiza balance en
user_stats - Se registra transacción en
ml_coins_transactions - Frontend muestra notificación: "+20 ML Coins 🪙"
Postcondiciones:
- Balance de ML Coins incrementado
- Transacción registrada con tipo
earned_exercise - Totales históricos actualizados
Caso de Uso 2: Estudiante Compra Comodín
Actor: Estudiante
Precondiciones:
- Usuario tiene balance suficiente de ML Coins
- Comodín disponible para compra
Flujo Principal:
- Usuario hace clic en "Comprar Pistas (15 coins)"
- Frontend verifica balance >= 15
- Sistema llama
purchase_comodin(user_id, 'pistas', quantity) - Función SQL:
- Verifica balance con
FOR UPDATE - Resta 15 ML Coins del balance
- Incrementa inventario de comodines
- Registra transacción tipo
spent_powerup
- Verifica balance con
- Frontend actualiza UI con nuevo balance e inventario
Flujo Alternativo: Balance insuficiente
- Frontend muestra error: "ML Coins insuficientes. Necesitas 15, tienes 10"
- Sugerencia: "Completa más ejercicios para ganar ML Coins"
Caso de Uso 3: Usuario Sube de Rango
Actor: Sistema (automático)
Precondiciones:
- Usuario alcanzó XP requerido para nuevo rango
Flujo Principal:
- Función
check_rank_promotion()detecta promoción - Sistema actualiza
user_rankscon nuevo rango - Sistema otorga bonus de rango:
award_ml_coins(user_id, 250, 'earned_rank', 'Promoción a Ah K''in') - Se registra transacción (sin multiplicador - monto fijo)
- Frontend muestra celebración: "¡Felicidades! +250 ML Coins por alcanzar Ah K'in"
📊 Métricas y KPIs
Métricas de Usuario
-
Balance Actual
- Columna:
user_stats.ml_coins - Propósito: Mostrar en UI, validar compras
- Columna:
-
Total Ganado Histórico
- Columna:
user_stats.ml_coins_earned_total - Propósito: Leaderboards, achievements
- Columna:
-
Total Gastado Histórico
- Columna:
user_stats.ml_coins_spent_total - Propósito: Análisis de engagement, patrones de gasto
- Columna:
Métricas del Sistema
-
ML Coins en Circulación
SELECT SUM(ml_coins) FROM gamification_system.user_stats;- Propósito: Monitorear inflación, salud económica
-
Earning por Tipo de Transacción
SELECT transaction_type, SUM(amount) FROM ml_coins_transactions WHERE transaction_type LIKE 'earned_%' GROUP BY transaction_type;- Propósito: Identificar fuentes principales de coins
-
Spending por Tipo
SELECT transaction_type, SUM(ABS(amount)) FROM ml_coins_transactions WHERE transaction_type LIKE 'spent_%' GROUP BY transaction_type;- Propósito: Entender cómo usuarios gastan coins
-
Ratio Earning/Spending
SELECT SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END) as total_earned, SUM(CASE WHEN amount < 0 THEN ABS(amount) ELSE 0 END) as total_spent, (SUM(CASE WHEN amount > 0 THEN amount ELSE 0 END)::FLOAT / NULLIF(SUM(CASE WHEN amount < 0 THEN ABS(amount) ELSE 0 END), 0)) as ratio FROM ml_coins_transactions;- Target: Ratio ~5-10x (usuarios ganan mucho más de lo que gastan)
- Alert: Si ratio < 3x → usuarios gastando demasiado
- Alert: Si ratio > 20x → coins no tienen valor percibido
🔒 Seguridad y Prevención de Fraude
1. Race Conditions
Problema: Dos transacciones simultáneas pueden causar balance incorrecto.
Solución: Row-level locking con FOR UPDATE
SELECT ml_coins INTO v_current_balance
FROM gamification_system.user_stats
WHERE user_id = p_user_id
FOR UPDATE;
2. Balance Negativo
Problema: Bugs o exploits podrían permitir balance negativo.
Solución:
- CHECK constraint:
ml_coins >= 0 - Validación en aplicación antes de gastar
- Transacción atómica (rollback si falla)
3. Duplicación de Recompensas
Problema: Usuario podría reclamar misma recompensa múltiples veces.
Solución:
- Idempotency keys en
reference_id - Validación de ejercicio ya completado
- Achievement solo se otorga una vez (validación en trigger)
4. Admin Abuse
Problema: Admin malintencionado otorga coins ilimitados.
Solución:
- Audit logging en
ml_coins_transactions - Alertas automáticas para transacciones admin > 1000 coins
- Revisión periódica de transacciones tipo
admin_adjustment
🧪 Casos de Prueba
Test 1: Award con Multiplicador Ajaw (1.00x)
Input:
award_ml_coins(
user_id = 'test-user-1',
amount = 100,
transaction_type = 'earned_exercise',
description = 'Test'
);
Condiciones:
- Usuario tiene rango Ajaw (1.00x)
- Balance inicial: 0
Output Esperado:
- Balance final: 100 ML Coins
ml_coins_earned_total: 100- Transacción registrada con
amount = 100,multiplier = 1.00
Test 2: Award con Multiplicador K'uk'ulkan (2.00x)
Input:
award_ml_coins(
user_id = 'test-user-2',
amount = 100,
transaction_type = 'earned_module',
description = 'Test'
);
Condiciones:
- Usuario tiene rango K'uk'ulkan (2.00x)
- Balance inicial: 50
Output Esperado:
- Balance final: 50 + 200 = 250 ML Coins
ml_coins_earned_total: 200- Transacción con
amount = 200,multiplier = 2.00 - Metadata JSONB:
{ "base_amount": 100, "rank": "K'uk'ulkan", "multiplier": 2.00, "final_amount": 200 }
Test 3: Spend - Balance Suficiente
Input:
spend_ml_coins(
user_id = 'test-user-3',
amount = 15,
transaction_type = 'spent_hint',
description = 'Compra de pista'
);
Condiciones:
- Balance inicial: 100
Output Esperado:
- Balance final: 85 ML Coins
ml_coins_spent_total: 15- Transacción con
amount = -15(negativo)
Test 4: Spend - Balance Insuficiente
Input:
spend_ml_coins(
user_id = 'test-user-4',
amount = 50,
transaction_type = 'spent_powerup',
description = 'Compra de comodín'
);
Condiciones:
- Balance inicial: 20
Output Esperado:
- Error: "Insufficient ML Coins balance"
- Balance sin cambios: 20
- No se crea transacción
📚 Referencias Técnicas
Base de Datos
- Tabla principal:
gamification_system.user_stats - Tabla de transacciones:
gamification_system.ml_coins_transactions - ENUM:
gamification_system.transaction_type - Función de award:
gamification_system.award_ml_coins() - Tests:
apps/database/ddl/schemas/gamification_system/functions/tests/test_award_ml_coins.sql
Backend (NestJS)
- Service:
apps/backend/src/modules/gamification/services/ml-coins.service.ts - Entity:
apps/backend/src/modules/gamification/entities/ml-coins-transaction.entity.ts - Controller:
apps/backend/src/modules/gamification/controllers/ml-coins.controller.ts - DTOs:
apps/backend/src/modules/gamification/dto/ml-coins/
Frontend (React)
- Store:
apps/frontend/src/features/gamification/economy/store/economyStore.ts - Components:
apps/frontend/src/features/gamification/economy/components/ - Hooks:
apps/frontend/src/features/gamification/economy/hooks/useTransactions.ts - API:
apps/frontend/src/features/gamification/api/gamificationAPI.ts
🔄 Versionado
Versión 2.0 (2025-11-08) - ACTUAL
Cambios:
- ✅ Migrado
transaction_typede 10 valores legacy a 14 valores oficiales - ✅ Agregados:
earned_module,earned_streak,earned_daily,earned_bonus,spent_powerup,spent_retry,bonus,welcome_bonus - ✅ Consolidado multiplicadores de rango Maya (1.00x - 2.00x)
- ✅ Documentación completa creada
Versión 1.0 (2025-10-27) - LEGACY
Características originales:
- 10 tipos de transacciones
- Función
award_ml_coins()básica sin multiplicadores - Sin documentación formal
✅ Criterios de Aceptación
- ✅ Usuario puede ganar ML Coins por actividades educativas
- ✅ Multiplicador de rango Maya se aplica correctamente
- ✅ Usuario puede gastar ML Coins en comodines y ayudas
- ✅ Balance nunca puede ser negativo
- ✅ Todas las transacciones quedan registradas
- ✅ Metadata JSONB contiene información completa
- ✅ Frontend muestra balance actualizado en tiempo real
- ✅ Tests SQL pasan al 100%
Creado: 2025-11-08 Aprobado por: Database Team Próxima revisión: 2025-12-01