408 lines
11 KiB
JavaScript
Executable File
408 lines
11 KiB
JavaScript
Executable File
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;
|