119 lines
3.3 KiB
JavaScript
119 lines
3.3 KiB
JavaScript
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;
|
|
}; |