const mongoose = require('mongoose'); const Schema = mongoose.Schema; const ladderService = require('./ladder.service'); const leaderboardSchema = new Schema({ playerId: { type: String, index: true, required: true }, username: { type: String, required: true }, avatar: { type: String, default: "" }, rankId: { type: Number, default: 1 }, rankScore: { type: Number, default: 0 }, stars: { type: Number, default: 0 }, totalWins: { type: Number, default: 0 }, position: { type: Number, required: true }, lastUpdated: { type: Date, default: Date.now } }); const Leaderboard = mongoose.model('Leaderboard', leaderboardSchema); // Leaderboard functions exports.generateLeaderboard = async () => { try { // Clear current leaderboard await Leaderboard.deleteMany({}); // Get all users const User = mongoose.model('Users'); const users = await User.find({}); // Sort users based on ranking criteria: // 1. Rank level (higher is better) // 2. Rank score (for็Ž‹่€…ๅˆ†ๆ•ฐ mechanism) // 3. Stars // 4. Total wins const sortedUsers = users.sort((a, b) => { const configA = ladderService.getRankConfig(a.rankId); const configB = ladderService.getRankConfig(b.rankId); // Compare rank levels if (configA.Level !== configB.Level) { return configB.Level - configA.Level; } // For players with rank score mechanism if (configA.RankScore === 1 && configB.RankScore === 1) { if (a.rankScore !== b.rankScore) { return b.rankScore - a.rankScore; } } // Compare stars if (a.stars !== b.stars) { return b.stars - a.stars; } // Compare total wins return b.totalWins - a.totalWins; }); // Take top 100 players const topPlayers = sortedUsers.slice(0, 100); // Create leaderboard entries const leaderboardEntries = []; for (let i = 0; i < topPlayers.length; i++) { const player = topPlayers[i]; const entry = new Leaderboard({ playerId: player._id, username: player.username, avatar: player.avatar, rankId: player.rankId, rankScore: player.rankScore, stars: player.stars, totalWins: player.totalWins, position: i + 1 }); leaderboardEntries.push(entry); } // Save all entries if (leaderboardEntries.length > 0) { await Leaderboard.insertMany(leaderboardEntries); } return leaderboardEntries; } catch (error) { console.error('Error generating leaderboard:', error); return []; } }; exports.getLeaderboard = async () => { try { const leaderboard = await Leaderboard.find({}).sort({ position: 1 }); return leaderboard; } catch (error) { console.error('Error getting leaderboard:', error); return []; } }; exports.getPlayerPosition = async (playerId) => { try { const entry = await Leaderboard.findOne({ playerId: playerId }); return entry ? entry.position : null; } catch (error) { console.error('Error getting player position:', error); return null; } }; // Initialize the ladder for a new player exports.initializePlayerLadder = (player) => { player.rankId = 1; player.stars = 0; player.rankScore = 0; player.winStreak = 0; player.totalWins = 0; return player; };