增加天梯排行榜
This commit is contained in:
24
jobs/jobs.js
24
jobs/jobs.js
@@ -1,21 +1,39 @@
|
|||||||
const schedule = require('node-schedule');
|
const schedule = require('node-schedule');
|
||||||
|
const ladderModel = require('./ladder/ladder.model');
|
||||||
|
|
||||||
const ExecuteJobs = async() =>
|
const ExecuteJobs = async() =>
|
||||||
{
|
{
|
||||||
//console.log('Run Hourly Jobs.....');
|
//console.log('Run Hourly Jobs.....');
|
||||||
|
|
||||||
//Add custom hourly jobs here
|
//Add custom hourly jobs here
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute leaderboard refresh at specified times: 00:00, 12:00, 18:00, 22:00
|
||||||
|
const RefreshLeaderboard = async() => {
|
||||||
|
console.log('Refreshing leaderboard...');
|
||||||
|
try {
|
||||||
|
await ladderModel.generateLeaderboard();
|
||||||
|
console.log('Leaderboard refreshed successfully');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error refreshing leaderboard:', error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.InitJobs = function()
|
exports.InitJobs = function()
|
||||||
{
|
{
|
||||||
|
// Hourly jobs
|
||||||
schedule.scheduleJob('* 1 * * *', function(){ // this for one hour
|
schedule.scheduleJob('* 1 * * *', function(){ // this for one hour
|
||||||
ExecuteJobs();
|
ExecuteJobs();
|
||||||
});
|
});
|
||||||
|
|
||||||
//Test run when starting
|
// Leaderboard refresh jobs at 00:00, 12:00, 18:00, 22:00
|
||||||
|
schedule.scheduleJob('0 0 * * *', async function() {
|
||||||
|
const hours = new Date().getHours();
|
||||||
|
if (hours === 0 || hours === 12 || hours === 18 || hours === 22) {
|
||||||
|
await RefreshLeaderboard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Test run when starting
|
||||||
ExecuteJobs();
|
ExecuteJobs();
|
||||||
}
|
}
|
||||||
92
ladder-config.json
Normal file
92
ladder-config.json
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"Id": 1,
|
||||||
|
"Rank": 1,
|
||||||
|
"RankName": "Bronze",
|
||||||
|
"Level": 1,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 0,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 0,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "bronze_ai",
|
||||||
|
"WaitTime": 10,
|
||||||
|
"MaxWaitTime": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2,
|
||||||
|
"Rank": 1,
|
||||||
|
"RankName": "Bronze",
|
||||||
|
"Level": 2,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 0,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "bronze_ai",
|
||||||
|
"WaitTime": 10,
|
||||||
|
"MaxWaitTime": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 3,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 6,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "silver_ai",
|
||||||
|
"WaitTime": 15,
|
||||||
|
"MaxWaitTime": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 4,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 6,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "silver_ai",
|
||||||
|
"WaitTime": 15,
|
||||||
|
"MaxWaitTime": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 5,
|
||||||
|
"Rank": 3,
|
||||||
|
"RankName": "Gold",
|
||||||
|
"Level": 5,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 7,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 1,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "gold_ai",
|
||||||
|
"WaitTime": 20,
|
||||||
|
"MaxWaitTime": 30
|
||||||
|
}
|
||||||
|
]
|
||||||
55
ladder/ladder.controller.js
Normal file
55
ladder/ladder.controller.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
const ladderModel = require('./ladder.model');
|
||||||
|
const ladderService = require('./ladder.service');
|
||||||
|
const { UserModel } = require('../users/users.model');
|
||||||
|
|
||||||
|
// Get leaderboard
|
||||||
|
exports.getLeaderboard = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const leaderboard = await ladderModel.getLeaderboard();
|
||||||
|
res.status(200).send(leaderboard);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting leaderboard:', error);
|
||||||
|
res.status(500).send({ error: 'Failed to get leaderboard' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get player's position in leaderboard
|
||||||
|
exports.getPlayerPosition = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { playerId } = req.params;
|
||||||
|
const position = await ladderModel.getPlayerPosition(playerId);
|
||||||
|
res.status(200).send({ position });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting player position:', error);
|
||||||
|
res.status(500).send({ error: 'Failed to get player position' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get player's rank info
|
||||||
|
exports.getPlayerRankInfo = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { playerId } = req.params;
|
||||||
|
const player = await UserModel.getById(playerId);
|
||||||
|
|
||||||
|
if (!player) {
|
||||||
|
return res.status(404).send({ error: 'Player not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const rankInfo = ladderService.getPlayerRankInfo(player);
|
||||||
|
res.status(200).send(rankInfo);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting player rank info:', error);
|
||||||
|
res.status(500).send({ error: 'Failed to get player rank info' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all rank configurations
|
||||||
|
exports.getRankConfigurations = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const configs = ladderService.getAllRankConfigs();
|
||||||
|
res.status(200).send(configs);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error getting rank configurations:', error);
|
||||||
|
res.status(500).send({ error: 'Failed to get rank configurations' });
|
||||||
|
}
|
||||||
|
};
|
||||||
119
ladder/ladder.model.js
Normal file
119
ladder/ladder.model.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
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;
|
||||||
|
};
|
||||||
15
ladder/ladder.routes.js
Normal file
15
ladder/ladder.routes.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const ladderController = require('./ladder.controller');
|
||||||
|
|
||||||
|
exports.route = (app) => {
|
||||||
|
// Get leaderboard
|
||||||
|
app.get('/ladder/leaderboard', ladderController.getLeaderboard);
|
||||||
|
|
||||||
|
// Get player position in leaderboard
|
||||||
|
app.get('/ladder/position/:playerId', ladderController.getPlayerPosition);
|
||||||
|
|
||||||
|
// Get player rank info
|
||||||
|
app.get('/ladder/rank/:playerId', ladderController.getPlayerRankInfo);
|
||||||
|
|
||||||
|
// Get all rank configurations
|
||||||
|
app.get('/ladder/config', ladderController.getRankConfigurations);
|
||||||
|
};
|
||||||
144
ladder/ladder.service.js
Normal file
144
ladder/ladder.service.js
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
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) {
|
||||||
|
// 王者分数 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) {
|
||||||
|
// 王者分数 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
|
||||||
|
if (player.winStreak >= 3) {
|
||||||
|
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) {
|
||||||
|
this.levelDown(player, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRankScore(player, opponent, isWin) {
|
||||||
|
if (isWin) {
|
||||||
|
let scoreToAdd = 20;
|
||||||
|
// If opponent has a higher rank score, calculate bonus
|
||||||
|
if (opponent.rankScore > player.rankScore) {
|
||||||
|
const ratio = Math.min(opponent.rankScore / player.rankScore, 3);
|
||||||
|
scoreToAdd = Math.round(ratio * 20);
|
||||||
|
}
|
||||||
|
player.rankScore += scoreToAdd;
|
||||||
|
} else {
|
||||||
|
// Deduct points on loss
|
||||||
|
if (player.rankScore > 0) {
|
||||||
|
player.rankScore = Math.max(0, player.rankScore - 20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
levelUp(player) {
|
||||||
|
const nextConfig = this.getRankConfig(player.rankId + 1);
|
||||||
|
if (nextConfig) {
|
||||||
|
player.rankId++;
|
||||||
|
player.stars = nextConfig.BeginStar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
levelDown(player, currentConfig) {
|
||||||
|
if (currentConfig.LoseRankDown === 1 && player.rankId > 1) {
|
||||||
|
player.rankId--;
|
||||||
|
const prevConfig = this.getRankConfig(player.rankId);
|
||||||
|
player.stars = prevConfig.RankDownStar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
const UserTool = require('../users/users.tool');
|
const UserTool = require('../users/users.tool');
|
||||||
const config = require('../config.js');
|
const config = require('../config.js');
|
||||||
|
const ladderService = require('../ladder/ladder.service');
|
||||||
|
const ladderModel = require('../ladder/ladder.model');
|
||||||
|
|
||||||
var MatchTool = {};
|
var MatchTool = {};
|
||||||
|
|
||||||
@@ -26,6 +27,10 @@ MatchTool.GetPlayerData = (player) =>
|
|||||||
var data = {};
|
var data = {};
|
||||||
data.username = player.username;
|
data.username = player.username;
|
||||||
data.elo = player.elo;
|
data.elo = player.elo;
|
||||||
|
// Add ladder info to player data
|
||||||
|
data.rankId = player.rankId;
|
||||||
|
data.stars = player.stars;
|
||||||
|
data.rankScore = player.rankScore;
|
||||||
data.reward = {};
|
data.reward = {};
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -52,17 +57,37 @@ MatchTool.GainMatchReward = async(player, opponent, winner_username) => {
|
|||||||
else if (lost)
|
else if (lost)
|
||||||
player.defeats += 1;
|
player.defeats += 1;
|
||||||
|
|
||||||
|
// Handle ladder system
|
||||||
|
if (won) {
|
||||||
|
await ladderService.handleWin(player, opponent);
|
||||||
|
} else if (lost) {
|
||||||
|
await ladderService.handleLoss(player, opponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save last win deck for leaderboard
|
||||||
|
if (won && player.decks && player.decks.length > 0) {
|
||||||
|
// For simplicity, we'll use the first deck as the last win deck
|
||||||
|
// In a real implementation, this would be the actual deck used in the match
|
||||||
|
player.lastWinDeck = player.decks[0];
|
||||||
|
}
|
||||||
|
|
||||||
//Calculate elo
|
//Calculate elo
|
||||||
var match_count = player.matches || 0;
|
var match_count = player.matches || 0;
|
||||||
var match_progress = Math.min(Math.max(match_count / config.elo_ini_match, 0.0), 1.0);
|
var match_progress = Math.min(Math.max(match_count / config.elo_ini_match, 0.0), 1.0);
|
||||||
var new_elo = MatchTool.calculateELO(player_elo, opponent_elo, match_progress, won, lost);
|
var new_elo = MatchTool.calculateELO(player_elo, opponent_elo, match_progress, won, lost);
|
||||||
player.elo = new_elo;
|
player.elo = new_elo;
|
||||||
player.save();
|
|
||||||
|
// Save player changes
|
||||||
|
await player.save();
|
||||||
|
|
||||||
var reward = {
|
var reward = {
|
||||||
elo: player.elo,
|
elo: player.elo,
|
||||||
xp: xp,
|
xp: xp,
|
||||||
coins: coins
|
coins: coins,
|
||||||
|
// Add ladder info to reward
|
||||||
|
rankId: player.rankId,
|
||||||
|
stars: player.stars,
|
||||||
|
rankScore: player.rankScore
|
||||||
};
|
};
|
||||||
|
|
||||||
return reward;
|
return reward;
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ MarketRouter.route(app);
|
|||||||
const ActivityRouter = require("./activity/activity.routes");
|
const ActivityRouter = require("./activity/activity.routes");
|
||||||
ActivityRouter.route(app);
|
ActivityRouter.route(app);
|
||||||
|
|
||||||
|
// Ladder system routes
|
||||||
|
const LadderRouter = require('./ladder/ladder.routes');
|
||||||
|
LadderRouter.route(app);
|
||||||
|
|
||||||
//Read SSL cert
|
//Read SSL cert
|
||||||
var ReadSSL = function()
|
var ReadSSL = function()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const Validator = require('../tools/validator.tool');
|
|||||||
const AuthTool = require('../authorization/auth.tool');
|
const AuthTool = require('../authorization/auth.tool');
|
||||||
const Email = require('../tools/email.tool');
|
const Email = require('../tools/email.tool');
|
||||||
const config = require('../config');
|
const config = require('../config');
|
||||||
|
const ladderModel = require('../ladder/ladder.model');
|
||||||
|
|
||||||
//Register new user
|
//Register new user
|
||||||
exports.RegisterUser = async (req, res, next) => {
|
exports.RegisterUser = async (req, res, next) => {
|
||||||
@@ -62,6 +63,9 @@ exports.RegisterUser = async (req, res, next) => {
|
|||||||
user.elo = config.start_elo;
|
user.elo = config.start_elo;
|
||||||
user.xp = 0;
|
user.xp = 0;
|
||||||
|
|
||||||
|
// Initialize ladder data
|
||||||
|
user = ladderModel.initializePlayerLadder(user);
|
||||||
|
|
||||||
user.account_create_time = new Date();
|
user.account_create_time = new Date();
|
||||||
user.last_login_time = new Date();
|
user.last_login_time = new Date();
|
||||||
user.last_online_time = new Date();
|
user.last_online_time = new Date();
|
||||||
@@ -389,8 +393,7 @@ exports.SendEmail = async (req, res) =>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
// reward is an object containing rewards to give
|
// reward is an object containing rewards to give
|
||||||
exports.GiveReward = async(req, res) =>
|
exports.GiveReward = async(req, res) =>{
|
||||||
{
|
|
||||||
var userId = req.params.userId;
|
var userId = req.params.userId;
|
||||||
var reward = req.body.reward;
|
var reward = req.body.reward;
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ const userSchema = new Schema({
|
|||||||
victories: {type: Number, default: 0},
|
victories: {type: Number, default: 0},
|
||||||
defeats: {type: Number, default: 0},
|
defeats: {type: Number, default: 0},
|
||||||
|
|
||||||
|
// Ladder system fields
|
||||||
|
rankId: {type: Number, default: 1}, // Current rank ID
|
||||||
|
stars: {type: Number, default: 0}, // Current stars
|
||||||
|
rankScore: {type: Number, default: 0}, // Rank score for王者分数 mechanism
|
||||||
|
winStreak: {type: Number, default: 0}, // Win streak counter
|
||||||
|
totalWins: {type: Number, default: 0}, // Total wins for leaderboard
|
||||||
|
lastWinDeck: {type: Object, default: null}, // Last winning deck for leaderboard
|
||||||
|
|
||||||
cards: [{ tid: String, variant: String, quantity: Number, _id: false }],
|
cards: [{ tid: String, variant: String, quantity: Number, _id: false }],
|
||||||
packs: [{ tid: String, quantity: Number, _id: false }],
|
packs: [{ tid: String, quantity: Number, _id: false }],
|
||||||
decks: [{ type: Object, _id: false }],
|
decks: [{ type: Object, _id: false }],
|
||||||
|
|||||||
Reference in New Issue
Block a user