Diverse änderungen am Push system
This commit is contained in:
@@ -89,7 +89,17 @@ class AchievementSystem {
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`📋 ${result.rows.length} Achievements für Spieler ${playerId} geladen`);
|
||||
// Count unique achievements and duplicates
|
||||
const uniqueAchievements = new Set(result.rows.map(row => row.achievement_id));
|
||||
const totalCount = result.rows.length;
|
||||
const uniqueCount = uniqueAchievements.size;
|
||||
const duplicateCount = totalCount - uniqueCount;
|
||||
|
||||
if (duplicateCount > 0) {
|
||||
console.log(`📋 ${totalCount} Achievements für Spieler ${playerId} geladen (${uniqueCount} eindeutige, ${duplicateCount} doppelt)`);
|
||||
} else {
|
||||
console.log(`📋 ${totalCount} Achievements für Spieler ${playerId} geladen`);
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`❌ Fehler beim Laden der Spieler-Achievements für ${playerId}:`, error);
|
||||
@@ -535,106 +545,138 @@ class AchievementSystem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft Tageskönig Achievement
|
||||
* Prüft Tageskönig Achievement pro Standort
|
||||
*/
|
||||
async checkDailyBest(playerId, currentDate, newAchievements) {
|
||||
const achievement = Array.from(this.achievements.values())
|
||||
.find(a => a.category === 'best_time' && a.condition_type === 'daily_best');
|
||||
.find(a => a.category === 'time' && a.condition_type === 'best_time_daily_location');
|
||||
|
||||
if (!achievement) return;
|
||||
|
||||
// Prüfe ob das Achievement heute bereits vergeben wurde
|
||||
const alreadyEarnedToday = await pool.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM player_achievements pa
|
||||
WHERE pa.player_id = $1
|
||||
AND pa.achievement_id = $2
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') = CURRENT_DATE
|
||||
`, [playerId, achievement.id]);
|
||||
|
||||
if (parseInt(alreadyEarnedToday.rows[0].count) > 0) return;
|
||||
|
||||
// Hole beste Zeit des Spielers heute
|
||||
const playerResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
// Hole alle Standorte, an denen der Spieler heute gespielt hat
|
||||
const locationsResult = await pool.query(`
|
||||
SELECT DISTINCT t.location_id, l.name as location_name
|
||||
FROM times t
|
||||
INNER JOIN locations l ON t.location_id = l.id
|
||||
WHERE t.player_id = $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') = $2
|
||||
`, [playerId, currentDate]);
|
||||
|
||||
// Hole beste Zeit des Tages
|
||||
const dailyResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE DATE(t.created_at AT TIME ZONE 'Europe/Berlin') = $1
|
||||
`, [currentDate]);
|
||||
for (const location of locationsResult.rows) {
|
||||
// Prüfe ob das Achievement heute bereits für diesen Standort vergeben wurde
|
||||
const alreadyEarnedToday = await pool.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM player_achievements pa
|
||||
WHERE pa.player_id = $1
|
||||
AND pa.achievement_id = $2
|
||||
AND pa.location_id = $3
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') = CURRENT_DATE
|
||||
`, [playerId, achievement.id, location.location_id]);
|
||||
|
||||
if (parseInt(alreadyEarnedToday.rows[0].count) > 0) continue;
|
||||
|
||||
const playerBest = playerResult.rows[0].best_time;
|
||||
const dailyBest = dailyResult.rows[0].best_time;
|
||||
// Hole beste Zeit des Spielers heute an diesem Standort
|
||||
const playerResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE t.player_id = $1
|
||||
AND t.location_id = $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') = $3
|
||||
`, [playerId, location.location_id, currentDate]);
|
||||
|
||||
if (playerBest && dailyBest && playerBest === dailyBest) {
|
||||
await this.awardAchievement(playerId, achievement, 1, newAchievements);
|
||||
// Hole beste Zeit des Tages an diesem Standort
|
||||
const dailyResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE t.location_id = $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') = $2
|
||||
`, [location.location_id, currentDate]);
|
||||
|
||||
const playerBest = playerResult.rows[0].best_time;
|
||||
const dailyBest = dailyResult.rows[0].best_time;
|
||||
|
||||
if (playerBest && dailyBest && playerBest === dailyBest) {
|
||||
await this.awardAchievement(playerId, achievement, 1, newAchievements, location.location_id);
|
||||
console.log(`🏆 Tageskönig Achievement vergeben für Standort: ${location.location_name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft Wochenchampion Achievement
|
||||
* Prüft Wochenchampion Achievement pro Standort
|
||||
*/
|
||||
async checkWeeklyBest(playerId, currentDate, newAchievements) {
|
||||
const achievement = Array.from(this.achievements.values())
|
||||
.find(a => a.category === 'best_time' && a.condition_type === 'weekly_best');
|
||||
.find(a => a.category === 'time' && a.condition_type === 'best_time_weekly_location');
|
||||
|
||||
if (!achievement) return;
|
||||
|
||||
// Prüfe ob das Achievement diese Woche bereits vergeben wurde
|
||||
// Berechne Woche
|
||||
const currentDateObj = new Date(currentDate);
|
||||
const dayOfWeek = currentDateObj.getDay();
|
||||
const weekStart = new Date(currentDateObj);
|
||||
weekStart.setDate(currentDateObj.getDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1));
|
||||
const weekStartStr = weekStart.toISOString().split('T')[0];
|
||||
|
||||
const alreadyEarnedThisWeek = await pool.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM player_achievements pa
|
||||
WHERE pa.player_id = $1
|
||||
AND pa.achievement_id = $2
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') >= $3
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') <= $4
|
||||
`, [playerId, achievement.id, weekStartStr, currentDate]);
|
||||
|
||||
if (parseInt(alreadyEarnedThisWeek.rows[0].count) > 0) return;
|
||||
|
||||
// Hole beste Zeit des Spielers diese Woche
|
||||
const playerResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
// Hole alle Standorte, an denen der Spieler diese Woche gespielt hat
|
||||
const locationsResult = await pool.query(`
|
||||
SELECT DISTINCT t.location_id, l.name as location_name
|
||||
FROM times t
|
||||
INNER JOIN locations l ON t.location_id = l.id
|
||||
WHERE t.player_id = $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $3
|
||||
`, [playerId, weekStartStr, currentDate]);
|
||||
|
||||
// Hole beste Zeit der Woche
|
||||
const weeklyResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $2
|
||||
`, [weekStartStr, currentDate]);
|
||||
for (const location of locationsResult.rows) {
|
||||
// Prüfe ob das Achievement diese Woche bereits für diesen Standort vergeben wurde
|
||||
const alreadyEarnedThisWeek = await pool.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM player_achievements pa
|
||||
WHERE pa.player_id = $1
|
||||
AND pa.achievement_id = $2
|
||||
AND pa.location_id = $3
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') >= $4
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') <= $5
|
||||
`, [playerId, achievement.id, location.location_id, weekStartStr, currentDate]);
|
||||
|
||||
if (parseInt(alreadyEarnedThisWeek.rows[0].count) > 0) continue;
|
||||
|
||||
const playerBest = playerResult.rows[0].best_time;
|
||||
const weeklyBest = weeklyResult.rows[0].best_time;
|
||||
// Hole beste Zeit des Spielers diese Woche an diesem Standort
|
||||
const playerResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE t.player_id = $1
|
||||
AND t.location_id = $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $3
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $4
|
||||
`, [playerId, location.location_id, weekStartStr, currentDate]);
|
||||
|
||||
if (playerBest && weeklyBest && playerBest === weeklyBest) {
|
||||
await this.awardAchievement(playerId, achievement, 1, newAchievements);
|
||||
// Hole beste Zeit der Woche an diesem Standort
|
||||
const weeklyResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE t.location_id = $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $3
|
||||
`, [location.location_id, weekStartStr, currentDate]);
|
||||
|
||||
const playerBest = playerResult.rows[0].best_time;
|
||||
const weeklyBest = weeklyResult.rows[0].best_time;
|
||||
|
||||
if (playerBest && weeklyBest && playerBest === weeklyBest) {
|
||||
await this.awardAchievement(playerId, achievement, 1, newAchievements, location.location_id);
|
||||
console.log(`🏆 Wochenchampion Achievement vergeben für Standort: ${location.location_name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft Monatsmeister Achievement
|
||||
* Prüft Monatsmeister Achievement pro Standort
|
||||
*/
|
||||
async checkMonthlyBest(playerId, currentDate, newAchievements) {
|
||||
const achievement = Array.from(this.achievements.values())
|
||||
.find(a => a.category === 'best_time' && a.condition_type === 'monthly_best');
|
||||
.find(a => a.category === 'time' && a.condition_type === 'best_time_monthly_location');
|
||||
|
||||
if (!achievement) return;
|
||||
|
||||
@@ -642,41 +684,57 @@ class AchievementSystem {
|
||||
const currentDateObj = new Date(currentDate);
|
||||
const monthStart = new Date(currentDateObj.getFullYear(), currentDateObj.getMonth(), 1);
|
||||
const monthStartStr = monthStart.toISOString().split('T')[0];
|
||||
|
||||
// Prüfe ob das Achievement diesen Monat bereits vergeben wurde
|
||||
const alreadyEarnedThisMonth = await pool.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM player_achievements pa
|
||||
WHERE pa.player_id = $1
|
||||
AND pa.achievement_id = $2
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') >= $3
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') <= $4
|
||||
`, [playerId, achievement.id, monthStartStr, currentDate]);
|
||||
|
||||
if (parseInt(alreadyEarnedThisMonth.rows[0].count) > 0) return;
|
||||
|
||||
// Hole beste Zeit des Spielers diesen Monat
|
||||
const playerResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
// Hole alle Standorte, an denen der Spieler diesen Monat gespielt hat
|
||||
const locationsResult = await pool.query(`
|
||||
SELECT DISTINCT t.location_id, l.name as location_name
|
||||
FROM times t
|
||||
INNER JOIN locations l ON t.location_id = l.id
|
||||
WHERE t.player_id = $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $3
|
||||
`, [playerId, monthStartStr, currentDate]);
|
||||
|
||||
// Hole beste Zeit des Monats
|
||||
const monthlyResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $2
|
||||
`, [monthStartStr, currentDate]);
|
||||
for (const location of locationsResult.rows) {
|
||||
// Prüfe ob das Achievement diesen Monat bereits für diesen Standort vergeben wurde
|
||||
const alreadyEarnedThisMonth = await pool.query(`
|
||||
SELECT COUNT(*) as count
|
||||
FROM player_achievements pa
|
||||
WHERE pa.player_id = $1
|
||||
AND pa.achievement_id = $2
|
||||
AND pa.location_id = $3
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') >= $4
|
||||
AND DATE(pa.earned_at AT TIME ZONE 'Europe/Berlin') <= $5
|
||||
`, [playerId, achievement.id, location.location_id, monthStartStr, currentDate]);
|
||||
|
||||
if (parseInt(alreadyEarnedThisMonth.rows[0].count) > 0) continue;
|
||||
|
||||
const playerBest = playerResult.rows[0].best_time;
|
||||
const monthlyBest = monthlyResult.rows[0].best_time;
|
||||
// Hole beste Zeit des Spielers diesen Monat an diesem Standort
|
||||
const playerResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE t.player_id = $1
|
||||
AND t.location_id = $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $3
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $4
|
||||
`, [playerId, location.location_id, monthStartStr, currentDate]);
|
||||
|
||||
if (playerBest && monthlyBest && playerBest === monthlyBest) {
|
||||
await this.awardAchievement(playerId, achievement, 1, newAchievements);
|
||||
// Hole beste Zeit des Monats an diesem Standort
|
||||
const monthlyResult = await pool.query(`
|
||||
SELECT MIN(recorded_time) as best_time
|
||||
FROM times t
|
||||
WHERE t.location_id = $1
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') >= $2
|
||||
AND DATE(t.created_at AT TIME ZONE 'Europe/Berlin') <= $3
|
||||
`, [location.location_id, monthStartStr, currentDate]);
|
||||
|
||||
const playerBest = playerResult.rows[0].best_time;
|
||||
const monthlyBest = monthlyResult.rows[0].best_time;
|
||||
|
||||
if (playerBest && monthlyBest && playerBest === monthlyBest) {
|
||||
await this.awardAchievement(playerId, achievement, 1, newAchievements, location.location_id);
|
||||
console.log(`🏆 Monatsmeister Achievement vergeben für Standort: ${location.location_name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -684,12 +742,12 @@ class AchievementSystem {
|
||||
* Vergibt ein Achievement an einen Spieler
|
||||
* Erstellt immer einen neuen Eintrag (keine Updates mehr)
|
||||
*/
|
||||
async awardAchievement(playerId, achievement, progress, newAchievements) {
|
||||
async awardAchievement(playerId, achievement, progress, newAchievements, locationId = null) {
|
||||
try {
|
||||
await pool.query(`
|
||||
INSERT INTO player_achievements (player_id, achievement_id, progress, is_completed, earned_at)
|
||||
VALUES ($1, $2, $3, true, NOW())
|
||||
`, [playerId, achievement.id, progress]);
|
||||
INSERT INTO player_achievements (player_id, achievement_id, progress, is_completed, earned_at, location_id)
|
||||
VALUES ($1, $2, $3, true, NOW(), $4)
|
||||
`, [playerId, achievement.id, progress, locationId]);
|
||||
|
||||
newAchievements.push({
|
||||
id: achievement.id,
|
||||
@@ -697,10 +755,12 @@ class AchievementSystem {
|
||||
description: achievement.description,
|
||||
icon: achievement.icon,
|
||||
points: achievement.points,
|
||||
progress: progress
|
||||
progress: progress,
|
||||
locationId: locationId
|
||||
});
|
||||
|
||||
console.log(`🏆 Achievement vergeben: ${achievement.icon} ${achievement.name} (+${achievement.points} Punkte)`);
|
||||
const locationText = locationId ? ` (Standort: ${locationId})` : '';
|
||||
console.log(`🏆 Achievement vergeben: ${achievement.icon} ${achievement.name} (+${achievement.points} Punkte)${locationText}`);
|
||||
} catch (error) {
|
||||
console.error(`❌ Fehler beim Vergeben des Achievements ${achievement.name}:`, error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user