DP-Logopedicka-Platforma/js/managers/progressManager.js
2026-04-23 15:41:11 +02:00

740 lines
23 KiB
JavaScript

/**
* PROGRESS MANAGER
* Správa pokroku hráča, ukladanie a načítavanie dát
*/
class ProgressManager {
constructor() {
this.STORAGE_KEY = 'speechTherapyProgress';
this.progress = null;
this.init();
}
/**
* Inicializácia progress managera
*/
init() {
console.log('Inicializujem ProgressManager...');
this.loadProgress();
// Ak neexistuje pokrok, vytvor nový
if (!this.progress) {
this.createNewProgress();
}
console.log('ProgressManager inicializovaný');
}
/**
* Načítanie pokroku z localStorage
*/
loadProgress() {
try {
const savedData = localStorage.getItem(this.STORAGE_KEY);
if (savedData) {
this.progress = JSON.parse(savedData);
console.log('Pokrok načítaný z localStorage');
return true;
}
} catch (error) {
console.error('Chyba pri načítaní pokroku:', error);
}
return false;
}
/**
* Vytvorenie nového pokroku pre hráča
*/
createNewProgress() {
console.log('Vytváram nový pokrok pre hráča...');
this.progress = {
version: '1.0',
createdAt: new Date().toISOString(),
lastUpdated: new Date().toISOString(),
totalStars: 0,
totalCompletedLevels: 0,
totalPlayTime: 0, // v sekundách
worlds: {},
settings: {
soundEnabled: true,
musicEnabled: true,
difficulty: 'normal'
},
achievements: [],
statistics: {
totalWordsSpoken: 0,
correctPronunciations: 0,
incorrectPronunciations: 0,
gamesPlayed: 0,
favoriteGameType: null
}
};
// Inicializuj pokrok pre všetky svety
if (typeof getAllWorlds === 'function') {
const worlds = getAllWorlds();
worlds.forEach(world => {
this.progress.worlds[world.id] = {
isUnlocked: world.id === 'world_r', // Prvý svet je odomknutý
stars: 0,
completedLevels: 0,
totalLevels: world.totalLevels,
bestTime: null,
lastPlayed: null,
levels: {} // Pokrok jednotlivých levelov
};
// Inicializuj prázdny objekt pre levely - budú sa inicializovať dynamicky
this.progress.worlds[world.id].levels = {};
});
}
this.saveProgress();
console.log('Nový pokrok vytvorený a uložený');
}
/**
* Uloženie pokroku do localStorage
*/
saveProgress() {
try {
this.progress.lastUpdated = new Date().toISOString();
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.progress));
console.log('Pokrok uložený');
return true;
} catch (error) {
console.error('Chyba pri ukladaní pokroku:', error);
return false;
}
}
/**
* Získanie celkového pokroku
*/
getProgress() {
return this.progress;
}
/**
* Získanie pokroku konkrétneho sveta
*/
getWorldProgress(worldId) {
return this.progress.worlds[worldId] || null;
}
/**
* Získanie pokroku konkrétneho levelu (s automatickou inicializáciou)
*/
getLevelProgress(worldId, levelId) {
const worldProgress = this.getWorldProgress(worldId);
if (!worldProgress) return null;
// Ak level neexistuje v pokroku, inicializuj ho
if (!worldProgress.levels[levelId]) {
this.initializeLevelProgress(worldId, levelId);
}
return worldProgress.levels[levelId] || null;
}
/**
* Inicializácia pokroku pre konkrétny level
*/
initializeLevelProgress(worldId, levelId) {
console.log(`Inicializujem pokrok pre level ${levelId} v svete ${worldId}`);
const worldProgress = this.progress.worlds[worldId];
if (!worldProgress) {
console.error(`Svet ${worldId} neexistuje v pokroku`);
return false;
}
// Získaj konfiguráciu levelu
let levelConfig = null;
if (typeof getLevelConfig === 'function') {
levelConfig = getLevelConfig(levelId);
}
if (!levelConfig) {
console.error(`Konfigurácia levelu ${levelId} sa nenašla`);
return false;
}
// Vytvor pokrok pre level
worldProgress.levels[levelId] = {
isUnlocked: this.shouldLevelBeUnlocked(worldId, levelConfig),
stars: 0,
bestTime: null,
attempts: 0,
completed: false,
lastPlayed: null
};
this.saveProgress();
return true;
}
/**
* Kontrola, či má byť level odomknutý
*/
shouldLevelBeUnlocked(worldId, levelConfig) {
// Prvý level v prvom svete je vždy odomknutý
if (worldId === 'world_r' && levelConfig.levelNumber === 1) {
return true;
}
// Prvý level v každom svete je odomknutý ak je svet odomknutý
if (levelConfig.levelNumber === 1) {
return this.progress.worlds[worldId].isUnlocked;
}
// Ostatné levely sú zamknuté dokým sa nedokončí predchádzajúci
return false;
}
/**
* Inicializácia všetkých levelov pre svet (voliteľná funkcia)
*/
initializeAllLevelsForWorld(worldId) {
console.log(`Inicializujem všetky levely pre svet ${worldId}`);
if (typeof getWorldLevels === 'function') {
const levels = getWorldLevels(worldId);
levels.forEach(level => {
if (!this.progress.worlds[worldId].levels[level.id]) {
this.initializeLevelProgress(worldId, level.id);
}
});
}
}
/**
* Aktualizácia pokroku levelu
*/
updateLevelProgress(worldId, levelId, levelData) {
console.log(`Aktualizujem pokrok levelu ${levelId} v svete ${worldId}:`, levelData);
const worldProgress = this.progress.worlds[worldId];
if (!worldProgress) {
console.error(`Svet ${worldId} neexistuje v pokroku`);
return false;
}
// Ak level ešte neexistuje, inicializuj ho
if (!worldProgress.levels[levelId]) {
worldProgress.levels[levelId] = {
isUnlocked: false,
stars: 0,
bestTime: null,
attempts: 0,
completed: false,
lastPlayed: null,
totalPoints: 0,
maxPoints: 0,
percentage: 0
};
}
const levelProgress = worldProgress.levels[levelId];
// Aktualizuj dáta levelu - VYLEPŠENÉ UKLADANIE
if (levelData.stars !== undefined) {
// Ulož len ak sú hviezdy lepšie ako predtým
if (levelData.stars > levelProgress.stars) {
levelProgress.stars = levelData.stars;
console.log(`Nové hviezdy: ${levelData.stars} (predtým: ${levelProgress.stars})`);
}
}
if (levelData.time !== undefined) {
if (!levelProgress.bestTime || levelData.time < levelProgress.bestTime) {
levelProgress.bestTime = levelData.time;
console.log(`Nový najlepší čas: ${levelData.time}s`);
}
}
if (levelData.completed !== undefined) {
const wasCompleted = levelProgress.completed;
levelProgress.completed = levelData.completed;
if (levelData.completed && !wasCompleted) {
console.log(`Level ${levelId} dokončený prvýkrát!`);
}
}
// NOVÉ: Ulož dodatočné štatistiky
if (levelData.points !== undefined) {
levelProgress.totalPoints = Math.max(levelProgress.totalPoints, levelData.points);
}
if (levelData.maxPoints !== undefined) {
levelProgress.maxPoints = levelData.maxPoints;
}
if (levelData.percentage !== undefined) {
levelProgress.percentage = Math.max(levelProgress.percentage, levelData.percentage);
}
// Aktualizuj základné info
levelProgress.attempts++;
levelProgress.lastPlayed = new Date().toISOString();
// Aktualizuj štatistiky sveta
this.updateWorldStatistics(worldId);
// VYLEPŠENÉ: Skontroluj odomknutie ďalších levelov/svetov
this.checkUnlocks(worldId, levelId, levelData);
// Aktualizuj celkové štatistiky
this.updateOverallStatistics();
this.saveProgress();
return true;
}
/**
* Aktualizácia štatistík sveta
*/
updateWorldStatistics(worldId) {
const worldProgress = this.progress.worlds[worldId];
const levels = worldProgress.levels;
// Spočítaj hviezdy a dokončené levely
let totalStars = 0;
let completedLevels = 0;
Object.values(levels).forEach(level => {
totalStars += level.stars;
if (level.completed) {
completedLevels++;
}
});
worldProgress.stars = totalStars;
worldProgress.completedLevels = completedLevels;
worldProgress.lastPlayed = new Date().toISOString();
}
/**
* Aktualizácia celkových štatistík
*/
updateOverallStatistics() {
let totalStars = 0;
let totalCompletedLevels = 0;
Object.values(this.progress.worlds).forEach(world => {
totalStars += world.stars;
totalCompletedLevels += world.completedLevels;
});
this.progress.totalStars = totalStars;
this.progress.totalCompletedLevels = totalCompletedLevels;
}
/**
* Kontrola odomknutia nových levelov/svetov
*/
checkUnlocks(worldId, completedLevelId) {
console.log(`Kontrolujem odomknutia po dokončení ${completedLevelId}`);
const unlocked = {
levels: [],
worlds: []
};
// 1. Odomkni ďalší level v rovnakom svete (ak existuje)
const nextLevelUnlocked = this.unlockNextLevel(worldId, completedLevelId);
if (nextLevelUnlocked) {
unlocked.levels.push(nextLevelUnlocked);
}
// 2. Skontroluj odomknutie nových svetov
const newWorlds = this.checkWorldUnlocks();
unlocked.worlds.push(...newWorlds);
// 3. Informuj o odomknutom obsahu
if (unlocked.levels.length > 0 || unlocked.worlds.length > 0) {
this.showUnlockNotifications(unlocked);
}
return unlocked;
}
/**
* Odomknutie ďalšieho levelu v svete
*/
unlockNextLevel(worldId, currentLevelId) {
try {
// Získaj konfiguráciu aktuálneho levelu
if (typeof getLevelConfig !== 'function') {
console.warn('Funkcia getLevelConfig nie je dostupná');
return null;
}
const currentLevel = getLevelConfig(currentLevelId);
if (!currentLevel) {
console.warn(`Konfigurácia levelu ${currentLevelId} sa nenašla`);
return null;
}
// OPRAVENÉ: Použij správny formát ID podľa existujúcej konfigurácie
// Namiesto hardcoded formátu, nájdi všetky levely sveta a vybra ďalší
if (typeof getWorldLevels === 'function') {
const worldLevels = getWorldLevels(worldId);
// Nájdi index aktuálneho levelu
const currentIndex = worldLevels.findIndex(level => level.id === currentLevelId);
if (currentIndex === -1) {
console.warn(`Aktuálny level ${currentLevelId} sa nenašiel v zozname levelov`);
return null;
}
// Skontroluj či existuje ďalší level
if (currentIndex + 1 >= worldLevels.length) {
console.log(`Ďalší level neexistuje - koniec sveta ${worldId}`);
return null;
}
// Získaj ďalší level
const nextLevel = worldLevels[currentIndex + 1];
console.log(`Našiel som ďalší level: ${nextLevel.id} (${nextLevel.name})`);
// Získaj alebo vytvor pokrok ďalšieho levelu
const nextLevelProgress = this.getLevelProgress(worldId, nextLevel.id);
if (nextLevelProgress && !nextLevelProgress.isUnlocked) {
nextLevelProgress.isUnlocked = true;
console.log(`✅ Odomknutý ďalší level: ${nextLevel.name} (${nextLevel.id})`);
this.saveProgress();
return nextLevel;
} else if (nextLevelProgress && nextLevelProgress.isUnlocked) {
console.log(`Level ${nextLevel.id} je už odomknutý`);
return nextLevel;
}
}
return null;
} catch (error) {
console.error('Chyba pri odomykaní ďalšieho levelu:', error);
return null;
}
}
/**
* Kontrola odomknutia svetov
*/
checkWorldUnlocks() {
const unlockedWorlds = [];
try {
if (typeof getAllWorlds !== 'function') {
console.warn('Funkcia getAllWorlds nie je dostupná');
return unlockedWorlds;
}
const worlds = getAllWorlds();
worlds.forEach(world => {
// Preskočí svety, ktoré sú už odomknuté
if (this.progress.worlds[world.id].isUnlocked) {
return;
}
// Skontroluj podmienky odomknutia
if (world.unlockRequirement) {
const requiredWorldId = world.unlockRequirement.worldId;
const requiredStars = world.unlockRequirement.minStars || 0;
const requiredLevels = world.unlockRequirement.minCompletedLevels || 0;
const requiredWorldProgress = this.progress.worlds[requiredWorldId];
if (requiredWorldProgress) {
const hasEnoughStars = requiredWorldProgress.stars >= requiredStars;
const hasEnoughLevels = requiredWorldProgress.completedLevels >= requiredLevels;
if (hasEnoughStars && hasEnoughLevels) {
// Odomkni svet
this.progress.worlds[world.id].isUnlocked = true;
// Odomkni prvý level nového sveta
if (typeof getWorldLevels === 'function') {
const firstLevel = getWorldLevels(world.id)[0];
if (firstLevel) {
this.progress.worlds[world.id].levels[firstLevel.id] = {
isUnlocked: true,
stars: 0,
bestTime: null,
attempts: 0,
completed: false,
lastPlayed: null,
totalPoints: 0,
maxPoints: 0,
percentage: 0
};
}
}
console.log(`✅ Odomknutý nový svet: ${world.name} (${world.id})`);
unlockedWorlds.push(world);
} else {
console.log(`Svet ${world.id} ešte nie je odomknutý: potrebné ${requiredStars} hviezd (má ${requiredWorldProgress.stars}) a ${requiredLevels} levelov (má ${requiredWorldProgress.completedLevels})`);
}
}
}
});
if (unlockedWorlds.length > 0) {
this.saveProgress();
}
} catch (error) {
console.error('Chyba pri kontrole odomknutia svetov:', error);
}
return unlockedWorlds;
}
/**
* Zobrazenie notifikácie o odomknutí
*/
showUnlockNotification(type, item) {
const messages = {
'level': `🔓 Odomknutý nový level: ${item.name}!`,
'world': `🌟 Odomknutý nový svet: ${item.name}!`
};
const message = messages[type] || `Odomknuté: ${item.name}`;
console.log(message);
// Môžeš pridať toast notifikáciu, alert alebo upraviť UI
// Napríklad jednoduchý timeout alert:
setTimeout(() => {
if (typeof createUnlockToast === 'function') {
createUnlockToast(message, type);
} else {
// Fallback - console log (môže sa nahradiť lepším UI)
console.log(`UI Notifikácia: ${message}`);
}
}, 500);
}
/**
* Resetovanie pokroku (pre testovacie účely)
*/
resetProgress() {
console.log('Resetujem pokrok hráča...');
localStorage.removeItem(this.STORAGE_KEY);
this.createNewProgress();
}
/**
* Export pokroku (pre zálohovanie)
*/
exportProgress() {
return JSON.stringify(this.progress, null, 2);
}
/**
* Import pokroku (pre obnovenie zo zálohy)
*/
importProgress(progressData) {
try {
const imported = JSON.parse(progressData);
this.progress = imported;
this.saveProgress();
console.log('Pokrok úspešne importovaný');
return true;
} catch (error) {
console.error('Chyba pri importe pokroku:', error);
return false;
}
}
/**
* Získanie štatistík pre analýzu
*/
getStatistics() {
return {
totalStars: this.progress.totalStars,
totalCompletedLevels: this.progress.totalCompletedLevels,
totalPlayTime: this.progress.totalPlayTime,
worldsUnlocked: Object.values(this.progress.worlds).filter(w => w.isUnlocked).length,
averageStarsPerLevel: this.progress.totalCompletedLevels > 0
? (this.progress.totalStars / this.progress.totalCompletedLevels).toFixed(2)
: 0,
...this.progress.statistics
};
}
/**
* Zobrazenie notifikácií o odomknutí
*/
showUnlockNotifications(unlocked) {
console.log('🎉 === ODOMKNUTÝ NOVÝ OBSAH ===');
// Oznám odomknuté levely
unlocked.levels.forEach(level => {
console.log(`🔓 Nový level: ${level.name} (${level.id})`);
this.showUnlockNotification('level', level);
});
// Oznám odomknuté svety
unlocked.worlds.forEach(world => {
console.log(`🌟 Nový svet: ${world.name} (${world.id})`);
this.showUnlockNotification('world', world);
});
}
/**
* NOVÁ FUNKCIA: Získanie detailného pokroku sveta
*/
getDetailedWorldProgress(worldId) {
const worldProgress = this.getWorldProgress(worldId);
if (!worldProgress) return null;
const levels = worldProgress.levels;
const levelStats = {
total: 0,
completed: 0,
unlocked: 0,
locked: 0,
starsBreakdown: { 0: 0, 1: 0, 2: 0, 3: 0 }
};
Object.values(levels).forEach(level => {
levelStats.total++;
if (level.isUnlocked) levelStats.unlocked++;
else levelStats.locked++;
if (level.completed) levelStats.completed++;
levelStats.starsBreakdown[level.stars]++;
});
return {
...worldProgress,
levelStats,
completionPercentage: levelStats.total > 0 ?
Math.round((levelStats.completed / levelStats.total) * 100) : 0
};
}
/**
* NOVÁ FUNKCIA: Debug funkcie pre testovacie účely
*/
debugUnlockLevel(worldId, levelId) {
console.log(`Debug: Odomykam level ${levelId} v svete ${worldId}`);
const levelProgress = this.getLevelProgress(worldId, levelId);
if (levelProgress) {
levelProgress.isUnlocked = true;
this.saveProgress();
console.log(`✅ Level ${levelId} bol manuálne odomknutý`);
return true;
}
console.error(`❌ Level ${levelId} sa nenašiel`);
return false;
}
debugCompleteLevel(worldId, levelId, stars = 3) {
console.log(`Debug: Dokončujem level ${levelId} s ${stars} hviezdami`);
const success = this.updateLevelProgress(worldId, levelId, {
stars: stars,
completed: true,
time: 120, // 2 minúty
points: stars * 3,
maxPoints: 9,
percentage: (stars / 3) * 100
});
if (success) {
console.log(`✅ Level ${levelId} bol manuálne dokončený s ${stars} hviezdami`);
}
return success;
}
debugUnlockWorld(worldId) {
console.log(`Debug: Odomykam svet ${worldId}`);
if (this.progress.worlds[worldId]) {
this.progress.worlds[worldId].isUnlocked = true;
// Odomkni prvý level
if (typeof getWorldLevels === 'function') {
const firstLevel = getWorldLevels(worldId)[0];
if (firstLevel) {
this.debugUnlockLevel(worldId, firstLevel.id);
}
}
this.saveProgress();
console.log(`✅ Svet ${worldId} bol manuálne odomknutý`);
return true;
}
console.error(`❌ Svet ${worldId} sa nenašiel`);
return false;
}
/**
* NOVÁ FUNKCIA: Štatistiky pre debug a admin panel
*/
getProgressStatistics() {
const stats = this.getStatistics();
// Pridaj detailné štatistiky svetov
const worldStats = {};
Object.keys(this.progress.worlds).forEach(worldId => {
worldStats[worldId] = this.getDetailedWorldProgress(worldId);
});
return {
...stats,
worlds: worldStats,
lastUpdated: this.progress.lastUpdated,
createdAt: this.progress.createdAt
};
}
}
// Vytvor globálnu inštanciu
window.progressManager = new ProgressManager();
// Export pre Node.js (ak je potrebný)
if (typeof module !== 'undefined' && module.exports) {
module.exports = ProgressManager;
}