Files
tcg-server/ladder/ladder.service.js
yaoyanwei e26f405ea8 1
2025-09-08 16:43:50 +08:00

173 lines
4.6 KiB
JavaScript

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();