Pokemon_server / dist /server /ladders-remote.js.map
Jofthomas's picture
Jofthomas HF staff
Upload 4781 files
5c2ed06 verified
{
"version": 3,
"sources": ["../../server/ladders-remote.ts"],
"sourcesContent": ["/**\n * Main server ladder library\n * Pokemon Showdown - http://pokemonshowdown.com/\n *\n * This file handles ladders for the main server on\n * play.pokemonshowdown.com.\n *\n * Ladders for all other servers is handled by ladders.ts.\n *\n * Matchmaking is currently still implemented in rooms.ts.\n *\n * @license MIT\n */\nimport { Utils } from '../lib';\n\nexport class LadderStore {\n\tformatid: string;\n\tstatic readonly formatsListPrefix = '';\n\n\tconstructor(formatid: string) {\n\t\tthis.formatid = formatid;\n\t}\n\n\t/**\n\t * Returns [formatid, html], where html is an the HTML source of a\n\t * ladder toplist, to be displayed directly in the ladder tab of the\n\t * client.\n\t */\n\t// This requires to be `async` because it must conform with the `LadderStore` interface\n\t// eslint-disable-next-line @typescript-eslint/require-await\n\tasync getTop(prefix?: string): Promise<[string, string] | null> {\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns a Promise for the Elo rating of a user\n\t */\n\tasync getRating(userid: string) {\n\t\tconst formatid = this.formatid;\n\t\tconst user = Users.getExact(userid);\n\t\tif (user?.mmrCache[formatid]) {\n\t\t\treturn user.mmrCache[formatid];\n\t\t}\n\t\tconst [data] = await LoginServer.request('mmr', {\n\t\t\tformat: formatid,\n\t\t\tuser: userid,\n\t\t});\n\t\tlet mmr = NaN;\n\t\tif (data && !data.errorip) {\n\t\t\tmmr = Number(data);\n\t\t}\n\t\tif (isNaN(mmr)) return 1000;\n\n\t\tif (user && user.id === userid) {\n\t\t\tuser.mmrCache[formatid] = mmr;\n\t\t}\n\t\treturn mmr;\n\t}\n\n\t/**\n\t * Update the Elo rating for two players after a battle, and display\n\t * the results in the passed room.\n\t */\n\tasync updateRating(p1name: string, p2name: string, p1score: number, room: AnyObject): Promise<[\n\t\tnumber, AnyObject | undefined | null, AnyObject | undefined | null,\n\t]> {\n\t\tif (Ladders.disabled) {\n\t\t\troom.addRaw(`Ratings not updated. The ladders are currently disabled.`).update();\n\t\t\treturn [p1score, null, null];\n\t\t}\n\n\t\tconst formatid = this.formatid;\n\t\tconst p1 = Users.getExact(p1name);\n\t\tconst p2 = Users.getExact(p2name);\n\t\tconst p1id = toID(p1name);\n\t\tconst p2id = toID(p2name);\n\n\t\tconst ladderUpdatePromise = LoginServer.request('ladderupdate', {\n\t\t\tp1: p1name,\n\t\t\tp2: p2name,\n\t\t\tscore: p1score,\n\t\t\tformat: formatid,\n\t\t});\n\n\t\t// calculate new Elo scores and display to room while loginserver updates the ladder\n\t\tconst [p1OldElo, p2OldElo] = (await Promise.all([this.getRating(p1id), this.getRating(p2id)])).map(Math.round);\n\t\tconst p1NewElo = Math.round(this.calculateElo(p1OldElo, p1score, p2OldElo));\n\t\tconst p2NewElo = Math.round(this.calculateElo(p2OldElo, 1 - p1score, p1OldElo));\n\n\t\tconst p1Act = (p1score > 0.9 ? `winning` : (p1score < 0.1 ? `losing` : `tying`));\n\t\tlet p1Reasons = `${p1NewElo - p1OldElo} for ${p1Act}`;\n\t\tif (!p1Reasons.startsWith('-')) p1Reasons = '+' + p1Reasons;\n\t\troom.addRaw(Utils.html`${p1name}'s rating: ${p1OldElo} &rarr; <strong>${p1NewElo}</strong><br />(${p1Reasons})`);\n\n\t\tconst p2Act = (p1score > 0.9 || p1score < 0 ? `losing` : (p1score < 0.1 ? `winning` : `tying`));\n\t\tlet p2Reasons = `${p2NewElo - p2OldElo} for ${p2Act}`;\n\t\tif (!p2Reasons.startsWith('-'))\tp2Reasons = '+' + p2Reasons;\n\t\troom.addRaw(Utils.html`${p2name}'s rating: ${p2OldElo} &rarr; <strong>${p2NewElo}</strong><br />(${p2Reasons})`);\n\n\t\troom.rated = Math.min(p1NewElo, p2NewElo);\n\n\t\tif (p1) p1.mmrCache[formatid] = +p1NewElo;\n\t\tif (p2) p2.mmrCache[formatid] = +p2NewElo;\n\n\t\troom.update();\n\n\t\tconst [data, error] = await ladderUpdatePromise;\n\n\t\tlet problem = false;\n\t\tif (error) {\n\t\t\tif (error.message !== 'stream interrupt') {\n\t\t\t\troom.add(`||Ladder isn't responding, score probably updated but might not have (${error.message}).`);\n\t\t\t\tproblem = true;\n\t\t\t}\n\t\t} else if (!room.battle) {\n\t\t\tproblem = true;\n\t\t} else if (!data) {\n\t\t\troom.add(`|error|Unexpected response ${data} from ladder server.`);\n\t\t\troom.update();\n\t\t\tproblem = true;\n\t\t} else if (data.errorip) {\n\t\t\troom.add(`|error|This server's request IP ${data.errorip} is not a registered server.`);\n\t\t\troom.add(`|error|You should be using ladders.js and not ladders-remote.js for ladder tracking.`);\n\t\t\troom.update();\n\t\t\tproblem = true;\n\t\t}\n\n\t\tif (problem) {\n\t\t\t// We used to clear mmrCache for the format to get the users updated rating next search\n\t\t\t// we now no longer do that because that results in the user getting paired with other users as though they have 1000 elo\n\t\t\t// if the next query times out, which happens very frequently. This results in a lot of confusion, so we're just\n\t\t\t// going to not clear this cache. If the user gets the proper rating later - great. If they don't,\n\t\t\t// this will ensure they still get matched up in a much more accurate fashion.\n\t\t\treturn [p1score, null, null];\n\t\t}\n\n\t\treturn [p1score, data?.p1rating, data?.p2rating];\n\t}\n\n\t/**\n\t * Returns a Promise for an array of strings of <tr>s for ladder ratings of the user\n\t */\n\t// This requires to be `async` because it must conform with the `LadderStore` interface\n\t// eslint-disable-next-line @typescript-eslint/require-await\n\tstatic async visualizeAll(username: string) {\n\t\treturn [`<tr><td><strong>Please use the official client at play.pokemonshowdown.com</strong></td></tr>`];\n\t}\n\t/**\n\t * Calculates Elo based on a match result\n\t */\n\tcalculateElo(oldElo: number, score: number, foeElo: number): number {\n\t\t// see lib/ntbb-ladder.lib.php in the pokemon-showdown-client repo for the login server implementation\n\t\t// *intentionally* different from calculation in ladders-local, due to the high activity on the main server\n\n\t\t// The K factor determines how much your Elo changes when you win or\n\t\t// lose games. Larger K means more change.\n\t\t// In the \"original\" Elo, K is constant, but it's common for K to\n\t\t// get smaller as your rating goes up\n\t\tlet K = 50;\n\n\t\t// dynamic K-scaling (optional)\n\t\tif (oldElo < 1100) {\n\t\t\tif (score < 0.5) {\n\t\t\t\tK = 20 + (oldElo - 1000) * 30 / 100;\n\t\t\t} else if (score > 0.5) {\n\t\t\t\tK = 80 - (oldElo - 1000) * 30 / 100;\n\t\t\t}\n\t\t} else if (oldElo > 1300) {\n\t\t\tK = 40;\n\t\t}\n\n\t\t// main Elo formula\n\t\tconst E = 1 / (1 + 10 ** ((foeElo - oldElo) / 400));\n\n\t\tconst newElo = oldElo + K * (score - E);\n\n\t\treturn Math.max(newElo, 1000);\n\t}\n}\n"],
"mappings": "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",
"names": []
}