1
This commit is contained in:
@@ -126,7 +126,7 @@ exports.KeepOnline = async (req, res, next) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exports.GetVersion = (req, res) => {
|
exports.GetVersion = (req, res) => {
|
||||||
return res.status(200).send({ version: config.version });
|
return res.status(200).send({description:config.description, version:config.version, md5:config.md5, timestamp: Date.now()});
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----- verify user -----------
|
// ----- verify user -----------
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
version: "1.13",
|
version: "0.0.5",
|
||||||
|
description: "0.0.1",
|
||||||
|
md5: "36b441e48050bb919b5f0afcae3f076d",
|
||||||
|
|
||||||
port: 8080,
|
port: 8080,
|
||||||
port_https: 443,
|
port_https: 443,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const schedule = require('node-schedule');
|
const schedule = require('node-schedule');
|
||||||
const ladderModel = require('./ladder/ladder.model');
|
const ladderModel = require('../ladder/ladder.model');
|
||||||
|
|
||||||
const ExecuteJobs = async() =>
|
const ExecuteJobs = async() =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,10 +6,10 @@
|
|||||||
"Level": 1,
|
"Level": 1,
|
||||||
"BeginStar": 0,
|
"BeginStar": 0,
|
||||||
"RankDownStar": 0,
|
"RankDownStar": 0,
|
||||||
"MaxStar": 5,
|
"MaxStar": 2,
|
||||||
"WinGetStar": 1,
|
"WinGetStar": 1,
|
||||||
"ExtraGetStar": 0,
|
"ExtraGetStar": 1,
|
||||||
"LoseLostStar": 1,
|
"LoseLostStar": 0,
|
||||||
"LoseRankDown": 0,
|
"LoseRankDown": 0,
|
||||||
"RankScore": 0,
|
"RankScore": 0,
|
||||||
"AITimes": 30,
|
"AITimes": 30,
|
||||||
@@ -23,12 +23,12 @@
|
|||||||
"RankName": "Bronze",
|
"RankName": "Bronze",
|
||||||
"Level": 2,
|
"Level": 2,
|
||||||
"BeginStar": 0,
|
"BeginStar": 0,
|
||||||
"RankDownStar": 3,
|
"RankDownStar": 0,
|
||||||
"MaxStar": 5,
|
"MaxStar": 2,
|
||||||
"WinGetStar": 1,
|
"WinGetStar": 1,
|
||||||
"ExtraGetStar": 0,
|
"ExtraGetStar": 1,
|
||||||
"LoseLostStar": 1,
|
"LoseLostStar": 0,
|
||||||
"LoseRankDown": 1,
|
"LoseRankDown": 0,
|
||||||
"RankScore": 0,
|
"RankScore": 0,
|
||||||
"AITimes": 30,
|
"AITimes": 30,
|
||||||
"AIDeck": "bronze_ai",
|
"AIDeck": "bronze_ai",
|
||||||
@@ -37,34 +37,70 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 3,
|
"Id": 3,
|
||||||
"Rank": 2,
|
"Rank": 1,
|
||||||
"RankName": "Silver",
|
"RankName": "Bronze",
|
||||||
"Level": 3,
|
"Level": 3,
|
||||||
"BeginStar": 0,
|
"BeginStar": 0,
|
||||||
"RankDownStar": 3,
|
"RankDownStar": 0,
|
||||||
"MaxStar": 6,
|
"MaxStar": 2,
|
||||||
"WinGetStar": 1,
|
"WinGetStar": 1,
|
||||||
"ExtraGetStar": 1,
|
"ExtraGetStar": 1,
|
||||||
"LoseLostStar": 1,
|
"LoseLostStar": 0,
|
||||||
"LoseRankDown": 1,
|
"LoseRankDown": 0,
|
||||||
"RankScore": 0,
|
"RankScore": 0,
|
||||||
"AITimes": 30,
|
"AITimes": 30,
|
||||||
"AIDeck": "silver_ai",
|
"AIDeck": "bronze_ai",
|
||||||
"WaitTime": 15,
|
"WaitTime": 10,
|
||||||
"MaxWaitTime": 25
|
"MaxWaitTime": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 4,
|
"Id": 4,
|
||||||
"Rank": 2,
|
"Rank": 1,
|
||||||
"RankName": "Silver",
|
"RankName": "Bronze",
|
||||||
"Level": 4,
|
"Level": 4,
|
||||||
"BeginStar": 0,
|
"BeginStar": 0,
|
||||||
"RankDownStar": 3,
|
"RankDownStar": 0,
|
||||||
"MaxStar": 6,
|
"MaxStar": 2,
|
||||||
"WinGetStar": 1,
|
"WinGetStar": 1,
|
||||||
"ExtraGetStar": 1,
|
"ExtraGetStar": 1,
|
||||||
"LoseLostStar": 1,
|
"LoseLostStar": 0,
|
||||||
"LoseRankDown": 1,
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "bronze_ai",
|
||||||
|
"WaitTime": 10,
|
||||||
|
"MaxWaitTime": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 5,
|
||||||
|
"Rank": 1,
|
||||||
|
"RankName": "Bronze",
|
||||||
|
"Level": 5,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 0,
|
||||||
|
"MaxStar": 2,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 0,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "bronze_ai",
|
||||||
|
"WaitTime": 10,
|
||||||
|
"MaxWaitTime": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 6,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 6,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 3,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 0,
|
||||||
|
"LoseRankDown": 0,
|
||||||
"RankScore": 0,
|
"RankScore": 0,
|
||||||
"AITimes": 30,
|
"AITimes": 30,
|
||||||
"AIDeck": "silver_ai",
|
"AIDeck": "silver_ai",
|
||||||
@@ -72,21 +108,455 @@
|
|||||||
"MaxWaitTime": 25
|
"MaxWaitTime": 25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 5,
|
"Id": 7,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 7,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 3,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 0,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "silver_ai",
|
||||||
|
"WaitTime": 15,
|
||||||
|
"MaxWaitTime": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 8,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 8,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 3,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 0,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "silver_ai",
|
||||||
|
"WaitTime": 15,
|
||||||
|
"MaxWaitTime": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 9,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 9,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 3,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 0,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "silver_ai",
|
||||||
|
"WaitTime": 15,
|
||||||
|
"MaxWaitTime": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 10,
|
||||||
|
"Rank": 2,
|
||||||
|
"RankName": "Silver",
|
||||||
|
"Level": 10,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 3,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 0,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "silver_ai",
|
||||||
|
"WaitTime": 15,
|
||||||
|
"MaxWaitTime": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 11,
|
||||||
"Rank": 3,
|
"Rank": 3,
|
||||||
"RankName": "Gold",
|
"RankName": "Gold",
|
||||||
"Level": 5,
|
"Level": 11,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 4,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "gold_ai",
|
||||||
|
"WaitTime": 20,
|
||||||
|
"MaxWaitTime": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 12,
|
||||||
|
"Rank": 3,
|
||||||
|
"RankName": "Gold",
|
||||||
|
"Level": 12,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 4,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "gold_ai",
|
||||||
|
"WaitTime": 20,
|
||||||
|
"MaxWaitTime": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 13,
|
||||||
|
"Rank": 3,
|
||||||
|
"RankName": "Gold",
|
||||||
|
"Level": 13,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 4,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "gold_ai",
|
||||||
|
"WaitTime": 20,
|
||||||
|
"MaxWaitTime": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 14,
|
||||||
|
"Rank": 3,
|
||||||
|
"RankName": "Gold",
|
||||||
|
"Level": 14,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 4,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "gold_ai",
|
||||||
|
"WaitTime": 20,
|
||||||
|
"MaxWaitTime": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 15,
|
||||||
|
"Rank": 3,
|
||||||
|
"RankName": "Gold",
|
||||||
|
"Level": 15,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 2,
|
||||||
|
"MaxStar": 4,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 0,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "gold_ai",
|
||||||
|
"WaitTime": 20,
|
||||||
|
"MaxWaitTime": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 16,
|
||||||
|
"Rank": 4,
|
||||||
|
"RankName": "Platinum",
|
||||||
|
"Level": 16,
|
||||||
"BeginStar": 0,
|
"BeginStar": 0,
|
||||||
"RankDownStar": 3,
|
"RankDownStar": 3,
|
||||||
"MaxStar": 7,
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "platinum_ai",
|
||||||
|
"WaitTime": 25,
|
||||||
|
"MaxWaitTime": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 17,
|
||||||
|
"Rank": 4,
|
||||||
|
"RankName": "Platinum",
|
||||||
|
"Level": 17,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "platinum_ai",
|
||||||
|
"WaitTime": 25,
|
||||||
|
"MaxWaitTime": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 18,
|
||||||
|
"Rank": 4,
|
||||||
|
"RankName": "Platinum",
|
||||||
|
"Level": 18,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "platinum_ai",
|
||||||
|
"WaitTime": 25,
|
||||||
|
"MaxWaitTime": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 19,
|
||||||
|
"Rank": 4,
|
||||||
|
"RankName": "Platinum",
|
||||||
|
"Level": 19,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "platinum_ai",
|
||||||
|
"WaitTime": 25,
|
||||||
|
"MaxWaitTime": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 20,
|
||||||
|
"Rank": 4,
|
||||||
|
"RankName": "Platinum",
|
||||||
|
"Level": 20,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "platinum_ai",
|
||||||
|
"WaitTime": 25,
|
||||||
|
"MaxWaitTime": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 21,
|
||||||
|
"Rank": 5,
|
||||||
|
"RankName": "Diamond",
|
||||||
|
"Level": 21,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "diamond_ai",
|
||||||
|
"WaitTime": 30,
|
||||||
|
"MaxWaitTime": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 22,
|
||||||
|
"Rank": 5,
|
||||||
|
"RankName": "Diamond",
|
||||||
|
"Level": 22,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "diamond_ai",
|
||||||
|
"WaitTime": 30,
|
||||||
|
"MaxWaitTime": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 23,
|
||||||
|
"Rank": 5,
|
||||||
|
"RankName": "Diamond",
|
||||||
|
"Level": 23,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "diamond_ai",
|
||||||
|
"WaitTime": 30,
|
||||||
|
"MaxWaitTime": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 24,
|
||||||
|
"Rank": 5,
|
||||||
|
"RankName": "Diamond",
|
||||||
|
"Level": 24,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "diamond_ai",
|
||||||
|
"WaitTime": 30,
|
||||||
|
"MaxWaitTime": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 25,
|
||||||
|
"Rank": 5,
|
||||||
|
"RankName": "Diamond",
|
||||||
|
"Level": 25,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 0,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "diamond_ai",
|
||||||
|
"WaitTime": 30,
|
||||||
|
"MaxWaitTime": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 26,
|
||||||
|
"Rank": 6,
|
||||||
|
"RankName": "King",
|
||||||
|
"Level": 26,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
"WinGetStar": 1,
|
"WinGetStar": 1,
|
||||||
"ExtraGetStar": 1,
|
"ExtraGetStar": 1,
|
||||||
"LoseLostStar": 1,
|
"LoseLostStar": 1,
|
||||||
"LoseRankDown": 1,
|
"LoseRankDown": 1,
|
||||||
"RankScore": 1,
|
"RankScore": 1,
|
||||||
|
"InitialRankScore": 1100,
|
||||||
|
"WinScoreMin": 80,
|
||||||
|
"WinScoreMax": 150,
|
||||||
|
"LoseScore": 20,
|
||||||
"AITimes": 30,
|
"AITimes": 30,
|
||||||
"AIDeck": "gold_ai",
|
"AIDeck": "king_ai",
|
||||||
"WaitTime": 20,
|
"WaitTime": 35,
|
||||||
"MaxWaitTime": 30
|
"MaxWaitTime": 45
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 27,
|
||||||
|
"Rank": 6,
|
||||||
|
"RankName": "King",
|
||||||
|
"Level": 27,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 1,
|
||||||
|
"InitialRankScore": 1100,
|
||||||
|
"WinScoreMin": 80,
|
||||||
|
"WinScoreMax": 150,
|
||||||
|
"LoseScore": 20,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "king_ai",
|
||||||
|
"WaitTime": 35,
|
||||||
|
"MaxWaitTime": 45
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 28,
|
||||||
|
"Rank": 6,
|
||||||
|
"RankName": "King",
|
||||||
|
"Level": 28,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 1,
|
||||||
|
"InitialRankScore": 1100,
|
||||||
|
"WinScoreMin": 80,
|
||||||
|
"WinScoreMax": 150,
|
||||||
|
"LoseScore": 20,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "king_ai",
|
||||||
|
"WaitTime": 35,
|
||||||
|
"MaxWaitTime": 45
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 29,
|
||||||
|
"Rank": 6,
|
||||||
|
"RankName": "King",
|
||||||
|
"Level": 29,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 1,
|
||||||
|
"InitialRankScore": 1100,
|
||||||
|
"WinScoreMin": 80,
|
||||||
|
"WinScoreMax": 150,
|
||||||
|
"LoseScore": 20,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "king_ai",
|
||||||
|
"WaitTime": 35,
|
||||||
|
"MaxWaitTime": 45
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 30,
|
||||||
|
"Rank": 6,
|
||||||
|
"RankName": "King",
|
||||||
|
"Level": 30,
|
||||||
|
"BeginStar": 0,
|
||||||
|
"RankDownStar": 3,
|
||||||
|
"MaxStar": 5,
|
||||||
|
"WinGetStar": 1,
|
||||||
|
"ExtraGetStar": 1,
|
||||||
|
"LoseLostStar": 1,
|
||||||
|
"LoseRankDown": 1,
|
||||||
|
"RankScore": 1,
|
||||||
|
"InitialRankScore": 1100,
|
||||||
|
"WinScoreMin": 80,
|
||||||
|
"WinScoreMax": 150,
|
||||||
|
"LoseScore": 20,
|
||||||
|
"AITimes": 30,
|
||||||
|
"AIDeck": "king_ai",
|
||||||
|
"WaitTime": 35,
|
||||||
|
"MaxWaitTime": 45
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -11,6 +11,7 @@ const leaderboardSchema = new Schema({
|
|||||||
stars: { type: Number, default: 0 },
|
stars: { type: Number, default: 0 },
|
||||||
totalWins: { type: Number, default: 0 },
|
totalWins: { type: Number, default: 0 },
|
||||||
position: { type: Number, required: true },
|
position: { type: Number, required: true },
|
||||||
|
lastWinDeck: { type: Object, default: null }, // 添加最后获胜牌组信息
|
||||||
lastUpdated: { type: Date, default: Date.now }
|
lastUpdated: { type: Date, default: Date.now }
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ exports.generateLeaderboard = async () => {
|
|||||||
|
|
||||||
// Sort users based on ranking criteria:
|
// Sort users based on ranking criteria:
|
||||||
// 1. Rank level (higher is better)
|
// 1. Rank level (higher is better)
|
||||||
// 2. Rank score (for王者分数 mechanism)
|
// 2. Rank score (for King rank mechanism)
|
||||||
// 3. Stars
|
// 3. Stars
|
||||||
// 4. Total wins
|
// 4. Total wins
|
||||||
const sortedUsers = users.sort((a, b) => {
|
const sortedUsers = users.sort((a, b) => {
|
||||||
@@ -40,7 +41,7 @@ exports.generateLeaderboard = async () => {
|
|||||||
return configB.Level - configA.Level;
|
return configB.Level - configA.Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For players with rank score mechanism
|
// For players with rank score mechanism (King rank)
|
||||||
if (configA.RankScore === 1 && configB.RankScore === 1) {
|
if (configA.RankScore === 1 && configB.RankScore === 1) {
|
||||||
if (a.rankScore !== b.rankScore) {
|
if (a.rankScore !== b.rankScore) {
|
||||||
return b.rankScore - a.rankScore;
|
return b.rankScore - a.rankScore;
|
||||||
@@ -71,6 +72,7 @@ exports.generateLeaderboard = async () => {
|
|||||||
rankScore: player.rankScore,
|
rankScore: player.rankScore,
|
||||||
stars: player.stars,
|
stars: player.stars,
|
||||||
totalWins: player.totalWins,
|
totalWins: player.totalWins,
|
||||||
|
lastWinDeck: player.lastWinDeck, // 包含最后获胜牌组
|
||||||
position: i + 1
|
position: i + 1
|
||||||
});
|
});
|
||||||
leaderboardEntries.push(entry);
|
leaderboardEntries.push(entry);
|
||||||
@@ -115,5 +117,6 @@ exports.initializePlayerLadder = (player) => {
|
|||||||
player.rankScore = 0;
|
player.rankScore = 0;
|
||||||
player.winStreak = 0;
|
player.winStreak = 0;
|
||||||
player.totalWins = 0;
|
player.totalWins = 0;
|
||||||
|
player.lastWinDeck = null; // 初始化最后获胜牌组
|
||||||
return player;
|
return player;
|
||||||
};
|
};
|
||||||
@@ -31,7 +31,7 @@ class LadderService {
|
|||||||
const config = this.getRankConfig(player.rankId);
|
const config = this.getRankConfig(player.rankId);
|
||||||
|
|
||||||
if (config.RankScore === 1) {
|
if (config.RankScore === 1) {
|
||||||
// 王者分数 mechanism
|
// King rank score mechanism
|
||||||
this.updateRankScore(player, opponent, true);
|
this.updateRankScore(player, opponent, true);
|
||||||
} else {
|
} else {
|
||||||
// Star-based mechanism
|
// Star-based mechanism
|
||||||
@@ -49,7 +49,7 @@ class LadderService {
|
|||||||
const config = this.getRankConfig(player.rankId);
|
const config = this.getRankConfig(player.rankId);
|
||||||
|
|
||||||
if (config.RankScore === 1) {
|
if (config.RankScore === 1) {
|
||||||
// 王者分数 mechanism
|
// King rank score mechanism
|
||||||
this.updateRankScore(player, opponent, false);
|
this.updateRankScore(player, opponent, false);
|
||||||
} else {
|
} else {
|
||||||
// Star-based mechanism
|
// Star-based mechanism
|
||||||
@@ -64,8 +64,8 @@ class LadderService {
|
|||||||
updateStars(player, config, isWin) {
|
updateStars(player, config, isWin) {
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
let starsToAdd = config.WinGetStar;
|
let starsToAdd = config.WinGetStar;
|
||||||
// Add extra stars for win streak
|
// Add extra stars for win streak (3+ wins)
|
||||||
if (player.winStreak >= 3) {
|
if (player.winStreak >= 2) { // Streak starts at 2 (after 2 wins)
|
||||||
starsToAdd += config.ExtraGetStar;
|
starsToAdd += config.ExtraGetStar;
|
||||||
}
|
}
|
||||||
player.stars += starsToAdd;
|
player.stars += starsToAdd;
|
||||||
@@ -79,7 +79,7 @@ class LadderService {
|
|||||||
player.stars = Math.max(0, player.stars - 1);
|
player.stars = Math.max(0, player.stars - 1);
|
||||||
|
|
||||||
// Level down check
|
// Level down check
|
||||||
if (player.stars === 0) {
|
if (player.stars === 0 && config.LoseRankDown === 1) {
|
||||||
this.levelDown(player, config);
|
this.levelDown(player, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,18 +87,35 @@ class LadderService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateRankScore(player, opponent, isWin) {
|
updateRankScore(player, opponent, isWin) {
|
||||||
|
const config = this.getRankConfig(player.rankId);
|
||||||
|
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
let scoreToAdd = 20;
|
// 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 has a higher rank score, calculate bonus
|
||||||
if (opponent.rankScore > player.rankScore) {
|
if (opponent.rankScore > player.rankScore) {
|
||||||
const ratio = Math.min(opponent.rankScore / player.rankScore, 3);
|
// Calculate bonus based on rank difference (simplified)
|
||||||
scoreToAdd = Math.round(ratio * 20);
|
const ratio = Math.min((opponent.rankScore - player.rankScore) / 100, 1);
|
||||||
|
scoreToAdd = Math.round(config.WinScoreMin + ratio * (config.WinScoreMax - config.WinScoreMin));
|
||||||
}
|
}
|
||||||
|
|
||||||
player.rankScore += scoreToAdd;
|
player.rankScore += scoreToAdd;
|
||||||
} else {
|
} else {
|
||||||
// Deduct points on loss
|
// Deduct points on loss
|
||||||
|
const scoreToDeduct = config.LoseScore || 20;
|
||||||
if (player.rankScore > 0) {
|
if (player.rankScore > 0) {
|
||||||
player.rankScore = Math.max(0, player.rankScore - 20);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,6 +125,11 @@ class LadderService {
|
|||||||
if (nextConfig) {
|
if (nextConfig) {
|
||||||
player.rankId++;
|
player.rankId++;
|
||||||
player.stars = nextConfig.BeginStar;
|
player.stars = nextConfig.BeginStar;
|
||||||
|
|
||||||
|
// Initialize rank score for King rank
|
||||||
|
if (nextConfig.RankScore === 1) {
|
||||||
|
player.rankScore = nextConfig.InitialRankScore || 1100;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +137,14 @@ class LadderService {
|
|||||||
if (currentConfig.LoseRankDown === 1 && player.rankId > 1) {
|
if (currentConfig.LoseRankDown === 1 && player.rankId > 1) {
|
||||||
player.rankId--;
|
player.rankId--;
|
||||||
const prevConfig = this.getRankConfig(player.rankId);
|
const prevConfig = this.getRankConfig(player.rankId);
|
||||||
player.stars = prevConfig.RankDownStar;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
server.js
10
server.js
@@ -41,7 +41,7 @@ app.use(function (req, res, next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Parse JSON body
|
//Parse JSON body
|
||||||
app.use(express.json({ limit: "100kb" }));
|
app.use(express.json({ limit: "10kb" }));
|
||||||
|
|
||||||
//Log request
|
//Log request
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
@@ -96,6 +96,14 @@ ActivityRouter.route(app);
|
|||||||
const LadderRouter = require('./ladder/ladder.routes');
|
const LadderRouter = require('./ladder/ladder.routes');
|
||||||
LadderRouter.route(app);
|
LadderRouter.route(app);
|
||||||
|
|
||||||
|
// Task system routes
|
||||||
|
const TasksRouter = require('./tasks/tasks.routes');
|
||||||
|
TasksRouter.route(app);
|
||||||
|
|
||||||
|
// Initialize task system
|
||||||
|
const TasksModel = require('./tasks/tasks.model.js');
|
||||||
|
TasksModel.initializeTaskConfig('./tasks-config.json');
|
||||||
|
|
||||||
//Read SSL cert
|
//Read SSL cert
|
||||||
var ReadSSL = function()
|
var ReadSSL = function()
|
||||||
{
|
{
|
||||||
|
|||||||
119
tasks-api.md
Normal file
119
tasks-api.md
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# 任务系统接口文档
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
任务系统允许玩家完成各种游戏内任务以获得奖励。系统支持多种任务类型,包括日常任务、成就任务等。
|
||||||
|
|
||||||
|
## API端点
|
||||||
|
|
||||||
|
### 获取所有任务配置
|
||||||
|
```
|
||||||
|
GET /api/tasks
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "login_task_1",
|
||||||
|
"name": "每日登录",
|
||||||
|
"desc": "每日登录游戏",
|
||||||
|
"condition": 1,
|
||||||
|
"value1": 1,
|
||||||
|
"value2": "",
|
||||||
|
"value3": "",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [100],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "win_task_1",
|
||||||
|
"name": "胜利之路",
|
||||||
|
"desc": "获得3场对战胜利",
|
||||||
|
"condition": 3,
|
||||||
|
"value1": 3,
|
||||||
|
"value2": "",
|
||||||
|
"value3": "",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [200],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 获取玩家任务数据
|
||||||
|
```
|
||||||
|
GET /api/tasks/{userId}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"taskId": "login_task_1",
|
||||||
|
"assignedTime": 16409952000000000,
|
||||||
|
"expireTime": 16410816000000000,
|
||||||
|
"status": 1,
|
||||||
|
"progress": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastDailyTaskAssigned": 16409952000000000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 保存玩家任务数据
|
||||||
|
```
|
||||||
|
POST /api/tasks/{userId}
|
||||||
|
```
|
||||||
|
|
||||||
|
**请求体**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"taskId": "login_task_1",
|
||||||
|
"assignedTime": 16409952000000000,
|
||||||
|
"expireTime": 16410816000000000,
|
||||||
|
"status": 1,
|
||||||
|
"progress": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastDailyTaskAssigned": 16409952000000000
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"error": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 枚举值定义
|
||||||
|
|
||||||
|
### 任务条件类型 (TaskConditionType)
|
||||||
|
| 值 | 名称 | 描述 |
|
||||||
|
|---|------|------|
|
||||||
|
| 1 | LoginGame | 登入游戏 |
|
||||||
|
| 2 | PlayGames | 进行X场对战 |
|
||||||
|
| 3 | WinGames | 胜利X场 |
|
||||||
|
| 4 | DefeatHeroWithAttributes | 击败Y属性和Z属性的英雄X次 |
|
||||||
|
| 5 | SummonHeroWithAttributes | 召唤Y属性和Z属性的英雄X次 |
|
||||||
|
| 6 | UseHeroSkillWithAttributes | 使用Y属性和Z属性英雄的技能X次 |
|
||||||
|
|
||||||
|
### 任务奖励类型 (TaskRewardType)
|
||||||
|
| 值 | 名称 | 描述 |
|
||||||
|
|---|------|------|
|
||||||
|
| 0 | Coins | 金币 |
|
||||||
|
|
||||||
|
### 任务状态 (TaskStatus)
|
||||||
|
| 值 | 名称 | 描述 |
|
||||||
|
|---|------|------|
|
||||||
|
| 0 | Active | 激活 |
|
||||||
|
| 1 | Completed | 完成 |
|
||||||
|
| 2 | Expired | 过期 |
|
||||||
|
| 3 | Claimed | 已领取 |
|
||||||
80
tasks-config.json
Normal file
80
tasks-config.json
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "login_task_1",
|
||||||
|
"name": "每日登录",
|
||||||
|
"desc": "每日登录游戏",
|
||||||
|
"condition": 1,
|
||||||
|
"value1": 1,
|
||||||
|
"value2": "",
|
||||||
|
"value3": "",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [100],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "play_task_1",
|
||||||
|
"name": "参与对战",
|
||||||
|
"desc": "参与5场对战",
|
||||||
|
"condition": 2,
|
||||||
|
"value1": 5,
|
||||||
|
"value2": "",
|
||||||
|
"value3": "",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [150],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "win_task_1",
|
||||||
|
"name": "胜利之路",
|
||||||
|
"desc": "获得3场对战胜利",
|
||||||
|
"condition": 3,
|
||||||
|
"value1": 3,
|
||||||
|
"value2": "",
|
||||||
|
"value3": "",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [200],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "defeat_hero_task_1",
|
||||||
|
"name": "阵营克星",
|
||||||
|
"desc": "击败5个义勇军或帝国军英雄",
|
||||||
|
"condition": 4,
|
||||||
|
"value1": 5,
|
||||||
|
"value2": "YiYongJun",
|
||||||
|
"value3": "DiGuoJun",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [300],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "summon_hero_task_1",
|
||||||
|
"name": "召唤大师",
|
||||||
|
"desc": "召唤5个王国军或自由人英雄",
|
||||||
|
"condition": 5,
|
||||||
|
"value1": 5,
|
||||||
|
"value2": "WangGuoJun",
|
||||||
|
"value3": "ZiYouRen",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [250],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "skill_use_task_1",
|
||||||
|
"name": "技能专家",
|
||||||
|
"desc": "使用守郡或邪魔英雄的技能10次",
|
||||||
|
"condition": 6,
|
||||||
|
"value1": 10,
|
||||||
|
"value2": "ShouQun",
|
||||||
|
"value3": "XieMo",
|
||||||
|
"rewardTypes": [0],
|
||||||
|
"rewardNums": [350],
|
||||||
|
"isDailyTask": true,
|
||||||
|
"durationHours": 24
|
||||||
|
}
|
||||||
|
]
|
||||||
52
tasks/tasks.controller.js
Normal file
52
tasks/tasks.controller.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
const TasksModel = require("./tasks.model.js");
|
||||||
|
|
||||||
|
// Get all task configurations
|
||||||
|
exports.getAllTasks = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const tasks = await TasksModel.getAllTaskConfigs();
|
||||||
|
res.status(200).send(tasks);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get player tasks
|
||||||
|
exports.getPlayerTasks = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.params.userId;
|
||||||
|
if (!userId) {
|
||||||
|
return res.status(400).send({ error: "User ID is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const playerTasks = await TasksModel.getPlayerTasks(userId);
|
||||||
|
if (!playerTasks) {
|
||||||
|
return res.status(404).send({ error: "Player tasks not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send(playerTasks);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save player tasks
|
||||||
|
exports.savePlayerTasks = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const userId = req.params.userId;
|
||||||
|
if (!userId) {
|
||||||
|
return res.status(400).send({ error: "User ID is required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasksData = req.body;
|
||||||
|
tasksData.userId = userId;
|
||||||
|
|
||||||
|
const updatedTasks = await TasksModel.savePlayerTasks(tasksData);
|
||||||
|
if (!updatedTasks) {
|
||||||
|
return res.status(500).send({ error: "Failed to save player tasks" });
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).send({ success: true });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
};
|
||||||
94
tasks/tasks.model.js
Normal file
94
tasks/tasks.model.js
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
const mongoose = require("mongoose");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
// Task data structure based on the documentation
|
||||||
|
const playerTaskSchema = new Schema({
|
||||||
|
taskId: { type: String, required: true },
|
||||||
|
assignedTime: { type: Date, required: true },
|
||||||
|
expireTime: { type: Date, required: true },
|
||||||
|
status: { type: Number, required: true, default: 0 }, // 0: Active, 1: Completed, 2: Expired, 3: Claimed
|
||||||
|
progress: { type: Number, required: true, default: 0 }
|
||||||
|
});
|
||||||
|
|
||||||
|
const playerTaskDataSchema = new Schema({
|
||||||
|
userId: { type: String, required: true, index: true },
|
||||||
|
tasks: [playerTaskSchema],
|
||||||
|
lastDailyTaskAssigned: { type: Date, default: null }
|
||||||
|
});
|
||||||
|
|
||||||
|
playerTaskDataSchema.methods.toObj = function () {
|
||||||
|
var elem = this.toObject();
|
||||||
|
delete elem.__v;
|
||||||
|
delete elem._id;
|
||||||
|
return elem;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PlayerTaskData = mongoose.model("PlayerTaskData", playerTaskDataSchema);
|
||||||
|
exports.PlayerTaskData = PlayerTaskData;
|
||||||
|
|
||||||
|
// Task configuration storage
|
||||||
|
let taskConfigurations = [];
|
||||||
|
|
||||||
|
// Get all task configurations
|
||||||
|
exports.getAllTaskConfigs = async () => {
|
||||||
|
return taskConfigurations;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get task configuration by ID
|
||||||
|
exports.getTaskConfigById = async (taskId) => {
|
||||||
|
return taskConfigurations.find(task => task.id === taskId);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get player tasks
|
||||||
|
exports.getPlayerTasks = async (userId) => {
|
||||||
|
try {
|
||||||
|
let playerTaskData = await PlayerTaskData.findOne({ userId: userId });
|
||||||
|
if (!playerTaskData) {
|
||||||
|
playerTaskData = new PlayerTaskData({
|
||||||
|
userId: userId,
|
||||||
|
tasks: [],
|
||||||
|
lastDailyTaskAssigned: null
|
||||||
|
});
|
||||||
|
await playerTaskData.save();
|
||||||
|
}
|
||||||
|
return playerTaskData;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error getting player tasks:", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save player tasks
|
||||||
|
exports.savePlayerTasks = async (playerTaskData) => {
|
||||||
|
try {
|
||||||
|
const updated = await PlayerTaskData.findOneAndUpdate(
|
||||||
|
{ userId: playerTaskData.userId },
|
||||||
|
playerTaskData,
|
||||||
|
{ new: true, upsert: true }
|
||||||
|
);
|
||||||
|
return updated;
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error saving player tasks:", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize task configurations from file
|
||||||
|
exports.initializeTaskConfig = (configPath) => {
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(configPath)) {
|
||||||
|
const configFile = fs.readFileSync(configPath, 'utf8');
|
||||||
|
taskConfigurations = JSON.parse(configFile);
|
||||||
|
console.log(`Loaded ${taskConfigurations.length} task configurations`);
|
||||||
|
} else {
|
||||||
|
console.log("Task configuration file not found, using empty configuration");
|
||||||
|
taskConfigurations = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error initializing task configuration:", e);
|
||||||
|
taskConfigurations = [];
|
||||||
|
}
|
||||||
|
};
|
||||||
30
tasks/tasks.routes.js
Normal file
30
tasks/tasks.routes.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const TasksController = require('./tasks.controller.js');
|
||||||
|
const AuthTool = require('../authorization/auth.tool.js');
|
||||||
|
const config = require('../config.js');
|
||||||
|
|
||||||
|
const ADMIN = config.permissions.ADMIN; // Highest permission, can read and write all users
|
||||||
|
const SERVER = config.permissions.SERVER; // Middle permission, can read all users
|
||||||
|
const USER = config.permissions.USER; // Lowest permission, can only do things on same user
|
||||||
|
|
||||||
|
exports.route = (app) => {
|
||||||
|
// Get all task configurations
|
||||||
|
app.get('/api/tasks',
|
||||||
|
AuthTool.isValidJWT,
|
||||||
|
AuthTool.isPermissionLevel(SERVER),
|
||||||
|
TasksController.getAllTasks
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get player tasks
|
||||||
|
app.get('/api/tasks/:userId',
|
||||||
|
AuthTool.isValidJWT,
|
||||||
|
AuthTool.isSameUserOr(SERVER),
|
||||||
|
TasksController.getPlayerTasks
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save player tasks
|
||||||
|
app.post('/api/tasks/:userId',
|
||||||
|
AuthTool.isValidJWT,
|
||||||
|
AuthTool.isSameUserOr(SERVER),
|
||||||
|
TasksController.savePlayerTasks
|
||||||
|
);
|
||||||
|
};
|
||||||
111
tasks/tasks.tool.js
Normal file
111
tasks/tasks.tool.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
const TasksModel = require("./tasks.model.js");
|
||||||
|
|
||||||
|
// Task status constants
|
||||||
|
const TASK_STATUS = {
|
||||||
|
ACTIVE: 0,
|
||||||
|
COMPLETED: 1,
|
||||||
|
EXPIRED: 2,
|
||||||
|
CLAIMED: 3
|
||||||
|
};
|
||||||
|
|
||||||
|
// Task condition types
|
||||||
|
const TASK_CONDITION_TYPES = {
|
||||||
|
LOGIN_GAME: 1,
|
||||||
|
PLAY_GAMES: 2,
|
||||||
|
WIN_GAMES: 3,
|
||||||
|
DEFEAT_HERO_WITH_ATTRIBUTES: 4,
|
||||||
|
SUMMON_HERO_WITH_ATTRIBUTES: 5,
|
||||||
|
USE_HERO_SKILL_WITH_ATTRIBUTES: 6
|
||||||
|
};
|
||||||
|
|
||||||
|
// Task reward types
|
||||||
|
const TASK_REWARD_TYPES = {
|
||||||
|
COINS: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if a task is expired
|
||||||
|
exports.isTaskExpired = (task) => {
|
||||||
|
return new Date() > new Date(task.expireTime);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if a task is completed
|
||||||
|
exports.isTaskCompleted = (task) => {
|
||||||
|
return task.status === TASK_STATUS.COMPLETED;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if a task is claimed
|
||||||
|
exports.isTaskClaimed = (task) => {
|
||||||
|
return task.status === TASK_STATUS.CLAIMED;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a random task from the configuration
|
||||||
|
exports.getRandomTask = async () => {
|
||||||
|
const tasks = await TasksModel.getAllTaskConfigs();
|
||||||
|
if (tasks.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const randomIndex = Math.floor(Math.random() * tasks.length);
|
||||||
|
return tasks[randomIndex];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a new player task based on task configuration
|
||||||
|
exports.createPlayerTask = async (taskConfig) => {
|
||||||
|
const now = new Date();
|
||||||
|
const expireTime = new Date(now.getTime() + (taskConfig.durationHours * 60 * 60 * 1000));
|
||||||
|
|
||||||
|
return {
|
||||||
|
taskId: taskConfig.id,
|
||||||
|
assignedTime: now,
|
||||||
|
expireTime: expireTime,
|
||||||
|
status: TASK_STATUS.ACTIVE,
|
||||||
|
progress: 0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update task progress
|
||||||
|
exports.updateTaskProgress = async (playerTask, taskConfig, increment = 1) => {
|
||||||
|
// Check if task is already completed or claimed
|
||||||
|
if (playerTask.status === TASK_STATUS.COMPLETED || playerTask.status === TASK_STATUS.CLAIMED) {
|
||||||
|
return playerTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update progress
|
||||||
|
playerTask.progress += increment;
|
||||||
|
|
||||||
|
// Check if task is completed
|
||||||
|
if (playerTask.progress >= taskConfig.value1) {
|
||||||
|
playerTask.progress = taskConfig.value1; // Cap at the required value
|
||||||
|
playerTask.status = TASK_STATUS.COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return playerTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Give reward for completing a task
|
||||||
|
exports.giveTaskReward = async (userId, taskConfig) => {
|
||||||
|
// In a real implementation, this would integrate with the rewards system
|
||||||
|
// For now, we'll just log the reward information
|
||||||
|
console.log(`Giving reward to user ${userId} for task ${taskConfig.id}`);
|
||||||
|
|
||||||
|
for (let i = 0; i < taskConfig.rewardTypes.length; i++) {
|
||||||
|
const rewardType = taskConfig.rewardTypes[i];
|
||||||
|
const rewardNum = taskConfig.rewardNums[i];
|
||||||
|
|
||||||
|
switch (rewardType) {
|
||||||
|
case TASK_REWARD_TYPES.COINS:
|
||||||
|
console.log(`Rewarding ${rewardNum} coins to user ${userId}`);
|
||||||
|
// Here we would call the rewards system to give coins to the user
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`Unknown reward type: ${rewardType}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export constants
|
||||||
|
exports.TASK_STATUS = TASK_STATUS;
|
||||||
|
exports.TASK_CONDITION_TYPES = TASK_CONDITION_TYPES;
|
||||||
|
exports.TASK_REWARD_TYPES = TASK_REWARD_TYPES;
|
||||||
Reference in New Issue
Block a user