const fs = require('fs'); const path = require('path'); // Load ladder configuration const ladderConfig = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ladder-config.json'))); class LadderService { constructor() { this.rankConfigs = new Map(); this.initConfig(); } initConfig() { ladderConfig.forEach(config => { this.rankConfigs.set(config.Id, config); }); } // Get rank configuration by ID getRankConfig(rankId) { return this.rankConfigs.get(rankId); } // Get all rank configurations getAllRankConfigs() { return Array.from(this.rankConfigs.values()); } // Handle player win async handleWin(player, opponent) { const config = this.getRankConfig(player.rankId); if (config.RankScore === 1) { // King rank score mechanism this.updateRankScore(player, opponent, true); } else { // Star-based mechanism this.updateStars(player, config, true); } player.totalWins++; player.winStreak++; return player; } // Handle player loss async handleLoss(player, opponent) { const config = this.getRankConfig(player.rankId); if (config.RankScore === 1) { // King rank score mechanism this.updateRankScore(player, opponent, false); } else { // Star-based mechanism this.updateStars(player, config, false); } player.winStreak = 0; return player; } updateStars(player, config, isWin) { if (isWin) { let starsToAdd = config.WinGetStar; // Add extra stars for win streak (3+ wins) if (player.winStreak >= 2) { // Streak starts at 2 (after 2 wins) starsToAdd += config.ExtraGetStar; } player.stars += starsToAdd; // Level up check if (player.stars > config.MaxStar) { this.levelUp(player); } } else { if (config.LoseLostStar === 1) { player.stars = Math.max(0, player.stars - 1); // Level down check if (player.stars === 0 && config.LoseRankDown === 1) { this.levelDown(player, config); } } } } updateRankScore(player, opponent, isWin) { const config = this.getRankConfig(player.rankId); if (isWin) { // Initialize rank score if not already set if (player.rankScore === 0) { player.rankScore = config.InitialRankScore || 1100; } // Calculate score to add based on opponent's rank let scoreToAdd = config.WinScoreMin || 80; // If opponent has a higher rank score, calculate bonus if (opponent.rankScore > player.rankScore) { // Calculate bonus based on rank difference (simplified) const ratio = Math.min((opponent.rankScore - player.rankScore) / 100, 1); scoreToAdd = Math.round(config.WinScoreMin + ratio * (config.WinScoreMax - config.WinScoreMin)); } player.rankScore += scoreToAdd; } else { // Deduct points on loss const scoreToDeduct = config.LoseScore || 20; if (player.rankScore > 0) { player.rankScore = Math.max(0, player.rankScore - scoreToDeduct); } // Check for level down if score is too low if (player.rankScore < 1000 && config.LoseRankDown === 1) { this.levelDown(player, config); } } } levelUp(player) { const nextConfig = this.getRankConfig(player.rankId + 1); if (nextConfig) { player.rankId++; player.stars = nextConfig.BeginStar; // Initialize rank score for King rank if (nextConfig.RankScore === 1) { player.rankScore = nextConfig.InitialRankScore || 1100; } } } levelDown(player, currentConfig) { if (currentConfig.LoseRankDown === 1 && player.rankId > 1) { player.rankId--; const prevConfig = this.getRankConfig(player.rankId); if (prevConfig.RankScore === 1) { // Stay in rank score system player.rankScore = Math.max(prevConfig.InitialRankScore || 1100, player.rankScore - (prevConfig.LoseScore || 20)); } else { // Back to star system player.stars = prevConfig.RankDownStar; player.rankScore = 0; } } } // Get player's rank display info getPlayerRankInfo(player) { const config = this.getRankConfig(player.rankId); if (config.RankScore === 1) { return { rankName: config.RankName, level: config.Level, score: player.rankScore, isRankScore: true }; } else { return { rankName: config.RankName, level: config.Level, stars: player.stars, maxStars: config.MaxStar, isRankScore: false }; } } } module.exports = new LadderService();