Bereinigen und Entfernen von nicht mehr benötigten TinyMCE-Dateien und -Plugins; Aktualisierung der Internationalisierung für Deutsch und Englisch in den Falukant- und Navigationsmodulen; Verbesserung der Statusleiste und Router-Implementierung.

This commit is contained in:
Torsten Schulz (local)
2025-08-21 16:10:21 +02:00
parent 53c748a074
commit 3eb7ae4e93
170 changed files with 3850 additions and 7924 deletions

View File

@@ -0,0 +1,313 @@
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();