import Match3Campaign from '../models/match3/campaign.js'; import Match3Level from '../models/match3/level.js'; import Match3Objective from '../models/match3/objective.js'; import Match3UserProgress from '../models/match3/userProgress.js'; import Match3UserLevelProgress from '../models/match3/userLevelProgress.js'; class Match3Service { /** * Lädt alle aktiven Kampagnen */ async getActiveCampaigns() { try { const campaigns = await Match3Campaign.findAll({ where: { isActive: true }, include: [ { model: Match3Level, as: 'levels', where: { isActive: true }, required: false, include: [ { model: Match3Objective, as: 'objectives', required: false, order: [['order', 'ASC']] } ], order: [['order', 'ASC']] } ], order: [['order', 'ASC']] }); return campaigns; } catch (error) { console.error('Error loading active campaigns:', error); throw error; } } /** * Lädt eine spezifische Kampagne mit allen Leveln */ async getCampaign(campaignId) { try { const campaign = await Match3Campaign.findByPk(campaignId, { include: [ { model: Match3Level, as: 'levels', where: { isActive: true }, required: false, include: [ { model: Match3Objective, as: 'objectives', required: false, order: [['order', 'ASC']] } ], order: [['order', 'ASC']] } ] }); return campaign; } catch (error) { console.error('Error loading campaign:', error); throw error; } } /** * Lädt den Benutzerfortschritt für eine Kampagne */ async getUserProgress(userId, campaignId) { try { let userProgress = await Match3UserProgress.findOne({ where: { userId, campaignId }, include: [ { model: Match3UserLevelProgress, as: 'levelProgress', include: [ { model: Match3Level, as: 'level' } ] } ] }); if (!userProgress) { // Erstelle neuen Fortschritt wenn noch nicht vorhanden userProgress = await Match3UserProgress.create({ userId, campaignId, totalScore: 0, totalStars: 0, levelsCompleted: 0, currentLevel: 1, isCompleted: false }); } else { // Validiere und korrigiere bestehende currentLevel-Werte if (userProgress.currentLevel < 1 || userProgress.currentLevel > 1000) { console.warn(`Invalid currentLevel detected for user ${userId}: ${userProgress.currentLevel}, correcting to ${userProgress.levelsCompleted + 1}`); // Korrigiere den ungültigen Wert await userProgress.update({ currentLevel: userProgress.levelsCompleted + 1 }); // Lade den aktualisierten Datensatz userProgress = await Match3UserProgress.findByPk(userProgress.id, { include: [ { model: Match3UserLevelProgress, as: 'levelProgress', include: [ { model: Match3Level, as: 'level' } ] } ] }); } } return userProgress; } catch (error) { console.error('Error loading user progress:', error); throw error; } } /** * Aktualisiert den Level-Fortschritt eines Benutzers */ async updateLevelProgress(userId, campaignId, levelId, levelData) { try { // Lade oder erstelle Benutzerfortschritt let userProgress = await Match3UserProgress.findOne({ where: { userId, campaignId } }); if (!userProgress) { userProgress = await Match3UserProgress.create({ userId, campaignId, totalScore: 0, totalStars: 0, levelsCompleted: 0, currentLevel: 1, isCompleted: false }); } // Lade oder erstelle Level-Fortschritt let levelProgress = await Match3UserLevelProgress.findOne({ where: { userProgressId: userProgress.id, levelId } }); if (!levelProgress) { levelProgress = await Match3UserLevelProgress.create({ userProgressId: userProgress.id, levelId, score: 0, moves: 0, time: 0, stars: 0, isCompleted: false, attempts: 0 }); } // Aktualisiere Level-Fortschritt const updateData = { score: Math.max(levelProgress.bestScore, levelData.score), moves: levelData.moves, time: levelData.time || 0, stars: Math.max(levelProgress.stars, levelData.stars), isCompleted: levelData.isCompleted || false, attempts: levelProgress.attempts + 1 }; if (levelData.isCompleted) { updateData.completedAt = new Date(); } await levelProgress.update(updateData); // Aktualisiere Bestwerte if (levelData.score > levelProgress.bestScore) { await levelProgress.update({ bestScore: levelData.score }); } if (levelData.moves < levelProgress.bestMoves || levelProgress.bestMoves === 0) { await levelProgress.update({ bestMoves: levelData.moves }); } if (levelData.time < levelProgress.bestTime || levelProgress.bestTime === 0) { await levelProgress.update({ bestTime: levelData.time }); } // Aktualisiere Kampagnen-Fortschritt if (levelData.isCompleted) { const totalScore = await Match3UserLevelProgress.sum('score', { where: { userProgressId: userProgress.id, isCompleted: true } }); const totalStars = await Match3UserLevelProgress.sum('stars', { where: { userProgressId: userProgress.id, isCompleted: true } }); const levelsCompleted = await Match3UserLevelProgress.count({ where: { userProgressId: userProgress.id, isCompleted: true } }); // Korrigiere currentLevel: Es sollte immer levelsCompleted + 1 sein const correctCurrentLevel = levelsCompleted + 1; await userProgress.update({ totalScore, totalStars, levelsCompleted, currentLevel: correctCurrentLevel, // Verwende den korrigierten Wert lastPlayed: new Date() }); // Prüfe ob Kampagne abgeschlossen ist const totalLevels = await Match3Level.count({ where: { campaignId, isActive: true } }); if (levelsCompleted >= totalLevels) { await userProgress.update({ isCompleted: true }); } } return { userProgress, levelProgress }; } catch (error) { console.error('Error updating level progress:', error); throw error; } } /** * Lädt die Bestenliste für eine Kampagne */ async getLeaderboard(campaignId, limit = 10) { try { const leaderboard = await Match3UserProgress.findAll({ where: { campaignId }, include: [ { model: Match3UserLevelProgress, as: 'levelProgress', where: { isCompleted: true }, required: false } ], order: [ ['totalScore', 'DESC'], ['totalStars', 'DESC'], ['levelsCompleted', 'DESC'] ], limit }); return leaderboard; } catch (error) { console.error('Error loading leaderboard:', error); throw error; } } /** * Lädt Statistiken für einen Benutzer */ async getUserStats(userId) { try { const stats = await Match3UserProgress.findAll({ where: { userId }, include: [ { model: Match3Campaign, as: 'campaign' }, { model: Match3UserLevelProgress, as: 'levelProgress', include: [ { model: Match3Level, as: 'level' } ] } ] }); return stats; } catch (error) { console.error('Error loading user stats:', error); throw error; } } } export default new Match3Service();