import BaseService from './BaseService.js'; import TaxiGameState from '../models/taxi/taxiGameState.js'; import TaxiLevelStats from '../models/taxi/taxiLevelStats.js'; import User from '../models/community/user.js'; class TaxiService extends BaseService { constructor() { super(); } // Hilfsmethode: Konvertiere hashedId zu userId async getUserIdFromHashedId(hashedUserId) { const user = await User.findOne({ where: { hashedId: hashedUserId } }); if (!user) { throw new Error('User not found'); } return user.id; } // Spielstand abrufen async getGameState(hashedUserId) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); let gameState = await TaxiGameState.findOne({ where: { userId } }); if (!gameState) { // Erstelle neuen Spielstand gameState = await TaxiGameState.create({ userId, currentLevel: 1, totalScore: 0, totalMoney: 0, totalPassengersDelivered: 0, unlockedLevels: [1], achievements: [] }); } return { currentLevel: gameState.currentLevel, totalScore: gameState.totalScore, totalMoney: gameState.totalMoney, totalPassengersDelivered: gameState.totalPassengersDelivered, unlockedLevels: gameState.unlockedLevels, achievements: gameState.achievements }; } catch (error) { console.error('Error getting taxi game state:', error); throw error; } } // Spielstand speichern async saveGameState(hashedUserId, gameData) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const { level, score, money, passengersDelivered, fuel } = gameData; const [gameState, created] = await TaxiGameState.findOrCreate({ where: { userId }, defaults: { userId, currentLevel: level || 1, totalScore: score || 0, totalMoney: money || 0, totalPassengersDelivered: passengersDelivered || 0, unlockedLevels: [1], achievements: [] } }); if (!created) { // Aktualisiere bestehenden Spielstand await gameState.update({ currentLevel: Math.max(gameState.currentLevel, level || 1), totalScore: Math.max(gameState.totalScore, score || 0), totalMoney: Math.max(gameState.totalMoney, money || 0), totalPassengersDelivered: Math.max(gameState.totalPassengersDelivered, passengersDelivered || 0) }); } return { currentLevel: gameState.currentLevel, totalScore: gameState.totalScore, totalMoney: gameState.totalMoney, totalPassengersDelivered: gameState.totalPassengersDelivered, unlockedLevels: gameState.unlockedLevels, achievements: gameState.achievements }; } catch (error) { console.error('Error saving taxi game state:', error); throw error; } } // Level-Statistiken abrufen async getLevelStats(hashedUserId, level) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const stats = await TaxiLevelStats.findOne({ where: { userId, level } }); if (!stats) { return { level, bestScore: 0, bestMoney: 0, bestPassengersDelivered: 0, timesPlayed: 0, completed: false }; } return { level: stats.level, bestScore: stats.bestScore, bestMoney: stats.bestMoney, bestPassengersDelivered: stats.bestPassengersDelivered, timesPlayed: stats.timesPlayed, completed: stats.completed }; } catch (error) { console.error('Error getting level stats:', error); throw error; } } // Bestenliste abrufen async getLeaderboard(type = 'score', limit = 10) { try { let orderBy; switch (type) { case 'money': orderBy = [['totalMoney', 'DESC']]; break; case 'passengers': orderBy = [['totalPassengersDelivered', 'DESC']]; break; case 'level': orderBy = [['currentLevel', 'DESC']]; break; default: orderBy = [['totalScore', 'DESC']]; } const leaderboard = await TaxiGameState.findAll({ order: orderBy, limit: parseInt(limit), include: [{ model: User, attributes: ['username', 'id'] }] }); return leaderboard.map((entry, index) => ({ rank: index + 1, username: entry.User.username, userId: entry.User.id, score: entry.totalScore, money: entry.totalMoney, passengers: entry.totalPassengersDelivered, level: entry.currentLevel })); } catch (error) { console.error('Error getting leaderboard:', error); throw error; } } // Spiel beenden und Punkte verarbeiten async finishGame(hashedUserId, gameData) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const { finalScore, finalMoney, passengersDelivered, level } = gameData; // Aktualisiere Spielstand const gameState = await this.saveGameState(userId, { level, score: finalScore, money: finalMoney, passengersDelivered }); // Aktualisiere Level-Statistiken await this.updateLevelStats(hashedUserId, level, { score: finalScore, money: finalMoney, passengersDelivered }); // Prüfe auf neue freigeschaltete Level const newUnlockedLevels = await this.checkUnlockedLevels(hashedUserId, level); // Prüfe auf neue Erfolge const newAchievements = await this.checkAchievements(hashedUserId, gameState); return { gameState, newUnlockedLevels, newAchievements }; } catch (error) { console.error('Error finishing game:', error); throw error; } } // Level freischalten async unlockLevel(hashedUserId, level) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const gameState = await TaxiGameState.findOne({ where: { userId } }); if (!gameState) { throw new Error('Spielstand nicht gefunden'); } const unlockedLevels = [...gameState.unlockedLevels]; if (!unlockedLevels.includes(level)) { unlockedLevels.push(level); unlockedLevels.sort((a, b) => a - b); await gameState.update({ unlockedLevels }); } return { unlockedLevels }; } catch (error) { console.error('Error unlocking level:', error); throw error; } } // Spieler-Statistiken abrufen async getPlayerStats(hashedUserId) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const gameState = await this.getGameState(hashedUserId); const levelStats = await TaxiLevelStats.findAll({ where: { userId }, order: [['level', 'ASC']] }); const totalLevelsPlayed = levelStats.length; const completedLevels = levelStats.filter(stat => stat.completed).length; const totalPlayTime = levelStats.reduce((sum, stat) => sum + (stat.playTime || 0), 0); return { ...gameState, totalLevelsPlayed, completedLevels, totalPlayTime, levelStats: levelStats.map(stat => ({ level: stat.level, bestScore: stat.bestScore, bestMoney: stat.bestMoney, bestPassengersDelivered: stat.bestPassengersDelivered, timesPlayed: stat.timesPlayed, completed: stat.completed })) }; } catch (error) { console.error('Error getting player stats:', error); throw error; } } // Level zurücksetzen async resetLevel(hashedUserId, level) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); await TaxiLevelStats.destroy({ where: { userId, level } }); return { success: true }; } catch (error) { console.error('Error resetting level:', error); throw error; } } // Alle Spielstände zurücksetzen async resetAllProgress(hashedUserId) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); await TaxiGameState.destroy({ where: { userId } }); await TaxiLevelStats.destroy({ where: { userId } }); return { success: true }; } catch (error) { console.error('Error resetting all progress:', error); throw error; } } // Hilfsmethoden async updateLevelStats(hashedUserId, level, stats) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const { score, money, passengersDelivered } = stats; const [levelStat, created] = await TaxiLevelStats.findOrCreate({ where: { userId, level }, defaults: { userId, level, bestScore: score, bestMoney: money, bestPassengersDelivered: passengersDelivered, timesPlayed: 1, completed: true } }); if (!created) { const updates = { timesPlayed: levelStat.timesPlayed + 1, completed: true }; if (score > levelStat.bestScore) updates.bestScore = score; if (money > levelStat.bestMoney) updates.bestMoney = money; if (passengersDelivered > levelStat.bestPassengersDelivered) { updates.bestPassengersDelivered = passengersDelivered; } await levelStat.update(updates); } } catch (error) { console.error('Error updating level stats:', error); throw error; } } async checkUnlockedLevels(hashedUserId, currentLevel) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const gameState = await TaxiGameState.findOne({ where: { userId } }); if (!gameState) return []; const newUnlockedLevels = []; const nextLevel = currentLevel + 1; if (!gameState.unlockedLevels.includes(nextLevel)) { newUnlockedLevels.push(nextLevel); await this.unlockLevel(hashedUserId, nextLevel); } return newUnlockedLevels; } catch (error) { console.error('Error checking unlocked levels:', error); return []; } } async checkAchievements(hashedUserId, gameState) { try { const userId = await this.getUserIdFromHashedId(hashedUserId); const achievements = []; const currentAchievements = gameState.achievements || []; // Beispiel-Erfolge if (gameState.totalScore >= 1000 && !currentAchievements.includes('score_1000')) { achievements.push('score_1000'); } if (gameState.totalPassengersDelivered >= 50 && !currentAchievements.includes('passengers_50')) { achievements.push('passengers_50'); } if (gameState.currentLevel >= 10 && !currentAchievements.includes('level_10')) { achievements.push('level_10'); } if (achievements.length > 0) { const newAchievements = [...currentAchievements, ...achievements]; await TaxiGameState.update( { achievements: newAchievements }, { where: { userId } } ); } return achievements; } catch (error) { console.error('Error checking achievements:', error); return []; } } } export default TaxiService;