-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
9 changed files
with
1,882 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
/****************************************************************************************** | ||
* * | ||
* ██████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗███████╗ * | ||
* ██╔════╝╚██╗ ██╔╝ ██╔════╝██╔═══██╗██╔═══██╗██║ ██╔╝██║██╔════╝ * | ||
* ██║ ╚████╔╝█████╗██║ ██║ ██║██║ ██║█████╔╝ ██║█████╗ * | ||
* ██║ ╚██╔╝ ╚════╝██║ ██║ ██║██║ ██║██╔═██╗ ██║██╔══╝ * | ||
* ╚██████╗ ██║ ╚██████╗╚██████╔╝╚██████╔╝██║ ██╗██║███████╗ * | ||
* ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚══════╝ * | ||
* * | ||
* @project CyberCookie @creator EndeMythex @version 1.6.0 * | ||
*****************************************************************************************/ | ||
|
||
|
||
/* -------------------------------------------------------------------------- | ||
Setup / Import Resources | ||
-------------------------------------------------------------------------- */ | ||
|
||
import { db } from '../firebase/firebaseConfig.js'; | ||
|
||
import { | ||
collection, | ||
query, | ||
orderBy, | ||
limit, | ||
getDocs, | ||
setDoc, | ||
doc, | ||
onSnapshot | ||
} from "https://www.gstatic.com/firebasejs/10.12.5/firebase-firestore.js"; | ||
|
||
let previousScores = new Map(); | ||
let leaderboardUnsubscribe = null; // Pour stocker la fonction de désabonnement | ||
|
||
/* -------------------------------------------------------------------------- | ||
Update Leadboard | ||
-------------------------------------------------------------------------- */ | ||
|
||
export async function updateLeaderboard(userId, username, score) { | ||
try { | ||
await setDoc(doc(db, "leaderboard", userId), { | ||
username: username, | ||
score: score, | ||
lastUpdated: new Date().getTime() | ||
}); | ||
} catch (error) { | ||
console.error("Error updating leaderboard:", error); | ||
} | ||
} | ||
|
||
/* -------------------------------------------------------------------------- | ||
Load Leadboard | ||
-------------------------------------------------------------------------- */ | ||
|
||
export async function loadLeaderboard() { | ||
const leaderboardContent = document.getElementById('leaderboardContent'); | ||
|
||
try { | ||
const leaderboardQuery = query( | ||
collection(db, "leaderboard"), | ||
orderBy("score", "desc"), | ||
limit(7) | ||
); | ||
|
||
if (leaderboardUnsubscribe) { | ||
leaderboardUnsubscribe(); | ||
} | ||
|
||
leaderboardUnsubscribe = onSnapshot(leaderboardQuery, (querySnapshot) => { | ||
if (!leaderboardContent.querySelector('.leaderboard-list')) { | ||
const leaderboardList = document.createElement('div'); | ||
leaderboardList.className = 'leaderboard-list'; | ||
leaderboardContent.appendChild(leaderboardList); | ||
} | ||
|
||
const leaderboardList = leaderboardContent.querySelector('.leaderboard-list'); | ||
let rank = 1; | ||
const currentScores = new Map(); | ||
const entries = new Map(); | ||
|
||
// Première passe : créer ou mettre à jour les entrées | ||
querySnapshot.forEach((doc) => { | ||
const data = doc.data(); | ||
const userId = doc.id; | ||
currentScores.set(userId, data); | ||
|
||
let entry = leaderboardList.querySelector(`[data-user-id="${userId}"]`); | ||
|
||
if (!entry) { | ||
entry = document.createElement('div'); | ||
entry.className = 'leaderboard-entry'; | ||
entry.setAttribute('data-user-id', userId); | ||
} | ||
|
||
const previousData = previousScores.get(userId); | ||
if (!previousData || | ||
previousData.score !== data.score || | ||
previousData.username !== data.username) { | ||
|
||
entry.innerHTML = ` | ||
<span class="rank">#${rank}</span> | ||
<span class="username">${data.username || 'Anonymous'}</span> | ||
<span class="score">${formatNumber(data.score)}</span> | ||
`; | ||
|
||
entry.classList.add('updated'); | ||
setTimeout(() => entry.classList.remove('updated'), 500); | ||
} | ||
|
||
entries.set(userId, { entry, score: data.score }); | ||
rank++; | ||
}); | ||
|
||
// Deuxième passe : réorganiser les entrées dans le bon ordre | ||
leaderboardList.innerHTML = ''; // Vider la liste | ||
const sortedEntries = Array.from(entries.values()) | ||
.sort((a, b) => b.score - a.score); | ||
|
||
sortedEntries.forEach((item, index) => { | ||
const rankSpan = item.entry.querySelector('.rank'); | ||
if (rankSpan) { | ||
rankSpan.textContent = `#${index + 1}`; | ||
} | ||
leaderboardList.appendChild(item.entry); | ||
}); | ||
|
||
// Supprimer les entrées qui ne sont plus dans le top 10 | ||
const oldEntries = leaderboardList.querySelectorAll('.leaderboard-entry'); | ||
oldEntries.forEach(entry => { | ||
const userId = entry.getAttribute('data-user-id'); | ||
if (!currentScores.has(userId)) { | ||
entry.remove(); | ||
} | ||
}); | ||
|
||
previousScores = currentScores; | ||
|
||
if (rank === 1) { | ||
leaderboardList.innerHTML = ` | ||
<div class="leaderboard-empty">No scores yet. Be the first!</div> | ||
`; | ||
} | ||
}, (error) => { | ||
console.error("Error loading leaderboard:", error); | ||
if (!leaderboardContent.querySelector('.leaderboard-error')) { | ||
const errorMessage = document.createElement('div'); | ||
errorMessage.className = 'leaderboard-error'; | ||
errorMessage.textContent = 'Error loading leaderboard. Please try again later.'; | ||
leaderboardContent.appendChild(errorMessage); | ||
} | ||
}); | ||
|
||
} catch (error) { | ||
console.error("Error setting up leaderboard:", error); | ||
} | ||
} | ||
|
||
/* -------------------------------------------------------------------------- | ||
Format Number | ||
-------------------------------------------------------------------------- */ | ||
|
||
function formatNumber(num) { | ||
if (num >= 1000000) { | ||
return (num / 1000000).toFixed(1) + 'M'; | ||
} else if (num >= 1000) { | ||
return (num / 1000).toFixed(1) + 'K'; | ||
} | ||
return num.toString(); | ||
} | ||
|
||
/* -------------------------------------------------------------------------- | ||
Initialize Leaderboard | ||
-------------------------------------------------------------------------- */ | ||
|
||
export function initializeLeaderboard() { | ||
const leaderboardBtn = document.getElementById('leaderboardBtn'); | ||
const leaderboardContainer = document.getElementById('leaderboardContainer'); | ||
const settingsOptions = document.getElementById('settingsOptions'); | ||
const cookie = document.getElementById('cookie'); | ||
const discord = document.getElementById('discord'); | ||
const theme = document.getElementById('theme'); | ||
const extension = document.getElementById('extension'); | ||
const shop = document.getElementById('shop'); | ||
const settings = document.getElementById('settings'); | ||
|
||
leaderboardBtn.addEventListener('click', async function () { | ||
if (leaderboardContainer.style.display === "none") { | ||
leaderboardContainer.style.display = "block"; | ||
leaderboardBtn.textContent = "Home"; | ||
settingsOptions.style.display = "none"; | ||
cookie.style.display = 'none'; | ||
discord.style.display = 'none'; | ||
theme.style.display = 'none'; | ||
extension.style.display = 'none'; | ||
shop.style.display = 'none'; | ||
settings.style.display = 'none'; | ||
loadLeaderboard(); // Charger le leaderboard quand on l'affiche | ||
} else { | ||
leaderboardContainer.style.display = "none"; | ||
cookie.style.display = 'block'; | ||
leaderboardBtn.textContent = "LeadBoard"; | ||
theme.style.display = 'block'; | ||
discord.style.display = 'block'; | ||
extension.style.display = 'block'; | ||
shop.style.display = 'block'; | ||
settings.style.display = 'block'; | ||
// Désabonner quand on cache le leaderboard | ||
if (leaderboardUnsubscribe) { | ||
leaderboardUnsubscribe(); | ||
leaderboardUnsubscribe = null; | ||
} | ||
} | ||
}); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/****************************************************************************************** | ||
* * | ||
* ██████╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗███████╗ * | ||
* ██╔════╝╚██╗ ██╔╝ ██╔════╝██╔═══██╗██╔═══██╗██║ ██╔╝██║██╔════╝ * | ||
* ██║ ╚████╔╝█████╗██║ ██║ ██║██║ ██║█████╔╝ ██║█████╗ * | ||
* ██║ ╚██╔╝ ╚════╝██║ ██║ ██║██║ ██║██╔═██╗ ██║██╔══╝ * | ||
* ╚██████╗ ██║ ╚██████╗╚██████╔╝╚██████╔╝██║ ██╗██║███████╗ * | ||
* ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚══════╝ * | ||
* * | ||
* @project CyberCookie @creator EndeMythex @version 1.6.0 * | ||
*****************************************************************************************/ | ||
|
||
|
||
export class CookieEffectsManager { | ||
constructor() { | ||
this.canvas = document.createElement('canvas'); | ||
this.ctx = this.canvas.getContext('2d'); | ||
this.particles = []; | ||
this.cookieImage = new Image(); | ||
this.cookieImage.src = '/assets/icons/48x48cookie.png'; | ||
this.textParticles = []; | ||
this.ctx.font = '24px clockDigital'; | ||
|
||
// Configuration du canvas | ||
this.canvas.style.position = 'fixed'; | ||
this.canvas.style.top = '0'; | ||
this.canvas.style.left = '0'; | ||
this.canvas.style.pointerEvents = 'none'; | ||
this.canvas.style.zIndex = '10'; | ||
|
||
// Ajuster la taille du canvas | ||
this.resizeCanvas(); | ||
window.addEventListener('resize', () => this.resizeCanvas()); | ||
|
||
// Limiter le nombre maximum de particules | ||
this.MAX_PARTICLES = 50; | ||
this.MAX_TEXT_PARTICLES = 20; | ||
|
||
// Utiliser requestAnimationFrame avec throttling | ||
this.lastFrame = 0; | ||
this.FPS = 60; | ||
this.frameInterval = 1000 / this.FPS; | ||
|
||
// Démarrer l'animation | ||
this.animate(); | ||
} | ||
|
||
resizeCanvas() { | ||
this.canvas.width = window.innerWidth; | ||
this.canvas.height = window.innerHeight; | ||
} | ||
|
||
addParticle(x, y) { | ||
if (this.particles.length >= this.MAX_PARTICLES) { | ||
this.particles.shift(); // Supprimer la plus ancienne particule | ||
} | ||
const particle = { | ||
x, | ||
y, | ||
size: 48, | ||
speed: 2 + Math.random() * 2, | ||
opacity: 0.8, | ||
rotation: Math.random() * Math.PI * 2 | ||
}; | ||
this.particles.push(particle); | ||
} | ||
|
||
addTextParticle(x, y, text) { | ||
if (this.textParticles.length >= this.MAX_TEXT_PARTICLES) { | ||
this.textParticles.shift(); | ||
} | ||
const particle = { | ||
x, | ||
y, | ||
text, | ||
opacity: 1, | ||
speed: 1.5 | ||
}; | ||
this.textParticles.push(particle); | ||
} | ||
|
||
animate(timestamp) { | ||
// Limiter le FPS | ||
if (timestamp - this.lastFrame < this.frameInterval) { | ||
requestAnimationFrame((ts) => this.animate(ts)); | ||
return; | ||
} | ||
this.lastFrame = timestamp; | ||
|
||
// Optimiser le nettoyage du canvas | ||
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); | ||
|
||
// Batch rendering pour les cookies | ||
this.ctx.save(); | ||
for (let i = this.particles.length - 1; i >= 0; i--) { | ||
const particle = this.particles[i]; | ||
|
||
particle.y += particle.speed; | ||
particle.opacity -= 0.008; | ||
particle.rotation += 0.02; | ||
|
||
if (particle.opacity > 0) { | ||
this.ctx.globalAlpha = particle.opacity; | ||
this.ctx.translate(particle.x + particle.size/2, particle.y + particle.size/2); | ||
this.ctx.rotate(particle.rotation); | ||
this.ctx.drawImage( | ||
this.cookieImage, | ||
-particle.size/2, | ||
-particle.size/2, | ||
particle.size, | ||
particle.size | ||
); | ||
this.ctx.setTransform(1, 0, 0, 1, 0, 0); // Reset transform | ||
} else { | ||
this.particles.splice(i, 1); | ||
} | ||
} | ||
this.ctx.restore(); | ||
|
||
// Batch rendering pour le texte | ||
this.ctx.save(); | ||
this.ctx.font = '24px clockDigital'; | ||
for (let i = this.textParticles.length - 1; i >= 0; i--) { | ||
const particle = this.textParticles[i]; | ||
|
||
particle.y -= particle.speed; | ||
particle.opacity -= 0.02; | ||
|
||
if (particle.opacity > 0) { | ||
this.ctx.fillStyle = `rgba(255, 255, 255, ${particle.opacity})`; | ||
this.ctx.fillText(particle.text, particle.x, particle.y); | ||
} else { | ||
this.textParticles.splice(i, 1); | ||
} | ||
} | ||
this.ctx.restore(); | ||
|
||
requestAnimationFrame((ts) => this.animate(ts)); | ||
} | ||
|
||
init() { | ||
document.body.appendChild(this.canvas); | ||
} | ||
|
||
generateCookie(x, y) { | ||
if (x === undefined || y === undefined) { | ||
x = Math.random() * (window.innerWidth - 50); | ||
y = -50; | ||
} | ||
this.addParticle(x, y); | ||
} | ||
|
||
generateText(x, y, text) { | ||
this.addTextParticle(x, y, text); | ||
} | ||
} |
Oops, something went wrong.