{ "version": 3, "sources": ["../../../../server/chat-plugins/battlesearch.ts"], "sourcesContent": ["/**\r\n * Battle search - handles searching battle logs.\r\n */\r\nimport {FS, Utils, ProcessManager, Repl} from '../../lib';\r\n\r\nimport {checkRipgrepAvailability, Config} from '../config-loader';\r\n\r\nimport * as path from 'path';\r\nimport * as child_process from 'child_process';\r\n\r\nconst BATTLESEARCH_PROCESS_TIMEOUT = 3 * 60 * 60 * 1000; // 3 hours\r\n\r\ninterface BattleOutcome {\r\n\tlost: string;\r\n\twon: string;\r\n\tturns: string;\r\n}\r\n\r\ninterface BattleSearchResults {\r\n\ttotalBattles: number;\r\n\t/** Total battle outcomes. Null when only searching for one userid.*/\r\n\ttotalOutcomes: BattleOutcome[] | null;\r\n\ttotalWins: {[k: string]: number};\r\n\ttotalLosses: {[k: string]: number};\r\n\ttotalTies: number;\r\n\ttimesBattled: {[k: string]: number};\r\n}\r\n\r\nconst MAX_BATTLESEARCH_PROCESSES = 1;\r\nexport async function runBattleSearch(userids: ID[], month: string, tierid: ID, turnLimit?: number) {\r\n\tconst useRipgrep = await checkRipgrepAvailability();\r\n\tconst pathString = `logs/${month}/${tierid}/`;\r\n\tconst results: {[k: string]: BattleSearchResults} = {};\r\n\tlet files = [];\r\n\ttry {\r\n\t\tfiles = await FS(pathString).readdir();\r\n\t} catch (err: any) {\r\n\t\tif (err.code === 'ENOENT') {\r\n\t\t\treturn results;\r\n\t\t}\r\n\t\tthrow err;\r\n\t}\r\n\tconst [userid] = userids;\r\n\tfiles = files.filter(item => item.startsWith(month)).map(item => `logs/${month}/${tierid}/${item}`);\r\n\r\n\tif (useRipgrep) {\r\n\t\t// Matches non-word (including _ which counts as a word) characters between letters/numbers\r\n\t\t// in a user's name so the userid can case-insensitively be matched to the name.\r\n\t\tconst regexString = userids.map(id => `(?=.*?(\"p(1|2)\":\"${[...id].join('[^a-zA-Z0-9]*')}[^a-zA-Z0-9]*\"))`).join('');\r\n\t\tlet output;\r\n\t\ttry {\r\n\t\t\toutput = await ProcessManager.exec(['rg', '-i', regexString, '--no-line-number', '-P', '-tjson', ...files]);\r\n\t\t} catch {\r\n\t\t\treturn results;\r\n\t\t}\r\n\t\tfor (const line of output.stdout.split('\\n').reverse()) {\r\n\t\t\tconst [file, raw] = Utils.splitFirst(line, ':');\r\n\t\t\tif (!raw || !line) continue;\r\n\t\t\tconst data = JSON.parse(raw);\r\n\t\t\tconst day = file.split('/')[3];\r\n\t\t\tif (!results[day]) {\r\n\t\t\t\tresults[day] = {\r\n\t\t\t\t\ttotalBattles: 0,\r\n\t\t\t\t\ttotalWins: {},\r\n\t\t\t\t\ttotalOutcomes: userids.length > 1 ? [] : null,\r\n\t\t\t\t\ttotalLosses: {},\r\n\t\t\t\t\ttotalTies: 0,\r\n\t\t\t\t\ttimesBattled: {},\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t\tconst p1id = toID(data.p1);\r\n\t\t\tconst p2id = toID(data.p2);\r\n\r\n\t\t\tif (userids.length > 1) {\r\n\t\t\t\t// looking for specific userids, only register ones where those users are players\r\n\t\t\t\tif (userids.filter(item => [p1id, p2id].includes(item)).length < userids.length) continue;\r\n\t\t\t} else {\r\n\t\t\t\tif (!(p1id === userid || p2id === userid)) continue;\r\n\t\t\t}\r\n\r\n\t\t\tif (turnLimit && data.turns > turnLimit) continue;\r\n\t\t\tif (!results[day]) {\r\n\t\t\t\tresults[day] = {\r\n\t\t\t\t\ttotalBattles: 0,\r\n\t\t\t\t\ttotalWins: {},\r\n\t\t\t\t\ttotalOutcomes: userids.length > 1 ? [] : null,\r\n\t\t\t\t\ttotalLosses: {},\r\n\t\t\t\t\ttotalTies: 0,\r\n\t\t\t\t\ttimesBattled: {},\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t\tresults[day].totalBattles++;\r\n\t\t\tconst winnerid = toID(data.winner);\r\n\t\t\tconst loser = winnerid === p1id ? p2id : p1id;\r\n\t\t\tif (userids.includes(winnerid)) {\r\n\t\t\t\tif (!results[day].totalWins[winnerid]) results[day].totalWins[winnerid] = 0;\r\n\t\t\t\tresults[day].totalWins[winnerid]++;\r\n\t\t\t} else if (data.winner) {\r\n\t\t\t\tif (!results[day].totalLosses[loser]) results[day].totalLosses[loser] = 0;\r\n\t\t\t\tresults[day].totalLosses[loser]++;\r\n\t\t\t} else {\r\n\t\t\t\tresults[day].totalTies++;\r\n\t\t\t}\r\n\t\t\t// explicitly state 0 of stats if none\r\n\t\t\tfor (const id of userids) {\r\n\t\t\t\tif (!results[day].totalLosses[id]) results[day].totalLosses[id] = 0;\r\n\t\t\t\tif (!results[day].totalWins[id]) results[day].totalWins[id] = 0;\r\n\t\t\t}\r\n\r\n\t\t\tconst outcomes = results[day].totalOutcomes;\r\n\t\t\tif (outcomes) {\r\n\t\t\t\toutcomes.push({won: winnerid, lost: loser, turns: data.turns});\r\n\t\t\t}\r\n\t\t\t// we only want foe data for single-userid searches\r\n\t\t\tconst foe = userids.length > 1 ? null : userid === toID(data.p1) ? toID(data.p2) : toID(data.p1);\r\n\t\t\tif (foe) {\r\n\t\t\t\tif (!results[day].timesBattled[foe]) results[day].timesBattled[foe] = 0;\r\n\t\t\t\tresults[day].timesBattled[foe]++;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn results;\r\n\t}\r\n\tfor (const file of files) {\r\n\t\tconst subFiles = FS(`${file}`).readdirSync();\r\n\t\tconst day = file.split('/')[3];\r\n\t\tfor (const dayFile of subFiles) {\r\n\t\t\tconst json = FS(`${file}/${dayFile}`).readIfExistsSync();\r\n\t\t\tconst data = JSON.parse(json);\r\n\t\t\tconst p1id = toID(data.p1);\r\n\t\t\tconst p2id = toID(data.p2);\r\n\t\t\tif (userids.length > 1) {\r\n\t\t\t\t// looking for specific userids, only register ones where those users are players\r\n\t\t\t\tif (userids.filter(item => item === p1id || item === p2id).length < userids.length) continue;\r\n\t\t\t} else {\r\n\t\t\t\tif (!(p1id === userid || p2id === userid)) continue;\r\n\t\t\t}\r\n\t\t\tif (turnLimit && data.turns > turnLimit) continue;\r\n\t\t\tif (!results[day]) {\r\n\t\t\t\tresults[day] = {\r\n\t\t\t\t\ttotalBattles: 0,\r\n\t\t\t\t\ttotalWins: {},\r\n\t\t\t\t\ttotalOutcomes: [],\r\n\t\t\t\t\ttotalLosses: {},\r\n\t\t\t\t\ttotalTies: 0,\r\n\t\t\t\t\ttimesBattled: {},\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t\tresults[day].totalBattles++;\r\n\t\t\tconst winnerid = toID(data.winner);\r\n\t\t\tconst loser = winnerid === p1id ? p2id : p1id;\r\n\t\t\tif (userids.includes(winnerid)) {\r\n\t\t\t\tif (!results[day].totalWins[winnerid]) results[day].totalWins[winnerid] = 0;\r\n\t\t\t\tresults[day].totalWins[winnerid]++;\r\n\t\t\t} else if (data.winner) {\r\n\t\t\t\tif (!results[day].totalLosses[loser]) results[day].totalLosses[loser] = 0;\r\n\t\t\t\tresults[day].totalLosses[loser]++;\r\n\t\t\t} else {\r\n\t\t\t\tresults[day].totalTies++;\r\n\t\t\t}\r\n\t\t\t// explicitly state 0 of stats if none\r\n\t\t\tfor (const id of userids) {\r\n\t\t\t\tif (!results[day].totalLosses[id]) results[day].totalLosses[id] = 0;\r\n\t\t\t\tif (!results[day].totalWins[id]) results[day].totalWins[id] = 0;\r\n\t\t\t}\r\n\r\n\t\t\tconst outcomes = results[day].totalOutcomes;\r\n\t\t\tif (outcomes) {\r\n\t\t\t\toutcomes.push({won: winnerid, lost: loser, turns: data.turns});\r\n\t\t\t}\r\n\r\n\t\t\t// we don't want foe data if we're searching for 2 userids\r\n\t\t\tconst foe = userids.length > 1 ? null : userid === p1id ? p2id : p1id;\r\n\t\t\tif (foe) {\r\n\t\t\t\tif (!results[day].timesBattled[foe]) results[day].timesBattled[foe] = 0;\r\n\t\t\t\tresults[day].timesBattled[foe]++;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn results;\r\n}\r\n\r\nfunction buildResults(\r\n\tdata: {[k: string]: BattleSearchResults}, userids: ID[],\r\n\tmonth: string, tierid: ID, turnLimit?: number\r\n) {\r\n\tlet buf = `>view-battlesearch-${userids.join('-')}--${turnLimit}--${month}--${tierid}--confirm\\n|init|html\\n|title|[Battle Search][${userids.join('-')}][${tierid}][${month}]\\n`;\r\n\tbuf += `|pagehtml|

`;\r\n\tbuf += `${tierid} battles on ${month} where `;\r\n\tbuf += userids.length > 1 ? `the users ${userids.join(', ')} were players` : `the user ${userids[0]} was a player`;\r\n\tbuf += turnLimit ? ` and the battle lasted less than ${turnLimit} turn${Chat.plural(turnLimit)}` : '';\r\n\tbuf += `:

  • `;\r\n\tbuf += `

  • `;\r\n\tif (userids.length > 1) {\r\n\t\tconst outcomes: BattleOutcome[] = [];\r\n\t\tfor (const day in data) {\r\n\t\t\tconst curOutcomes = data[day].totalOutcomes;\r\n\t\t\tif (curOutcomes) outcomes.push(...curOutcomes);\r\n\t\t}\r\n\t\tbuf += `

    Full summary

    `;\r\n\t\tbuf += ``;\r\n\t\tfor (const battle of outcomes) {\r\n\t\t\tconst {won, lost, turns} = battle;\r\n\t\t\tbuf += ``;\r\n\t\t}\r\n\t}\r\n\tbuf += `
    WonLostTurns
    ${won}${lost}${turns}

    `;\r\n\tfor (const day in data) {\r\n\t\tconst dayStats = data[day];\r\n\t\tbuf += `

    `;\r\n\t\tconst {totalWins, totalLosses} = dayStats;\r\n\t\tbuf += ``;\r\n\t\tbuf += ``;\r\n\t\tfor (const id in totalWins) {\r\n\t\t\t// hide userids if we're only searching for 1\r\n\t\t\tbuf += ``;\r\n\t\t}\r\n\t\tfor (const id in totalLosses) {\r\n\t\t\tbuf += ``;\r\n\t\t}\r\n\t\tif (userids.length < 2) {\r\n\t\t\tbuf += ``;\r\n\t\t\tconst [userid] = userids;\r\n\t\t\tfor (const foe in dayStats.timesBattled) {\r\n\t\t\t\tbuf += ``;\r\n\t\t\t}\r\n\t\t}\r\n\t\tbuf += `


    `;\r\n\t}\r\n\tbuf += `

    ${day}

    `;\r\n\t\tbuf += `
    CategoryNumber
    Total Battles${dayStats.totalBattles}
    Total Wins${userids.length > 1 ? ` (${id}) ` : ''}${totalWins[id]}
    Total Losses${userids.length > 1 ? ` (${id}) ` : ''}${totalLosses[id]}
    OpponentTimes Battled
    `;\r\n\t\t\t\tbuf += `${foe}`;\r\n\t\t\t\tbuf += `${dayStats.timesBattled[foe]}

    `;\r\n\treturn buf;\r\n}\r\n\r\nasync function rustBattleSearch(\r\n\tcontext: Chat.PageContext, targetUser: string, daysString: string, format: ID\r\n) {\r\n\tconst days = parseInt(daysString);\r\n\tif (days < 1 || days > 15) {\r\n\t\tthrow new Chat.ErrorMessage(`Days must be between 1 and 15. To search longer ranges, use psbattletools manually on sim3.`);\r\n\t}\r\n\tif (!targetUser) {\r\n\t\tthrow new Chat.ErrorMessage(`No user specified.`);\r\n\t}\r\n\tconst {connection, user} = context;\r\n\tconst currentDayOfMonth = (new Date()).getDate();\r\n\tif (days < 1 || days > 15) {\r\n\t\treturn context.errorReply(`Days must be between 1 and 15. To search longer ranges, use psbattletools manually on sim3.`);\r\n\t}\r\n\r\n\ttry {\r\n\t\tawait ProcessManager.exec(`psbattletools --version`, {\r\n\t\t\tenv: {PATH: `${process.env.PATH}:${process.env.HOME}/.cargo/bin`},\r\n\t\t});\r\n\t} catch (e) {\r\n\t\treturn context.errorReply(\r\n\t\t\t`You must install psbattletools to use the alternate battlesearch.`\r\n\t\t);\r\n\t}\r\n\tif (user.lastCommand !== '/battlesearch' && [30, 31, 1].includes(currentDayOfMonth)) {\r\n\t\tconst buf = [`Warning: Usage stats may be running currently.`];\r\n\t\tbuf.push(`Battlesearch can interfere with usage stats processing due to high computational load.`);\r\n\t\tbuf.push(`Please exercise caution.`);\r\n\t\tbuf.push(`Type the command again to confirm.`);\r\n\t\tuser.lastCommand = '/battlesearch';\r\n\t\tthrow new Chat.ErrorMessage(buf.join('
    '));\r\n\t}\r\n\tuser.lastCommand = '';\r\n\r\n\tconst directories = [];\r\n\tfor (let daysAgo = 0; daysAgo < days; daysAgo++) {\r\n\t\tconst date = new Date(Date.now() - 24 * 60 * 60 * 1000 * daysAgo);\r\n\t\tconst year = date.getFullYear();\r\n\t\tconst month = (date.getMonth() + 1).toString().padStart(2, '0');\r\n\t\tconst day = date.getDate().toString().padStart(2, '0');\r\n\r\n\t\tdirectories.push(\r\n\t\t\tFS(path.join('logs', `${year}-${month}`, format, `${year}-${month}-${day}`)).path\r\n\t\t);\r\n\t}\r\n\r\n\t// TODO: implement flag?\r\n\tlet buf = `>view-battlesearch-${toID(targetUser)}\\n|init|html\\n|title|[Battlesearch] ${targetUser} in ${format}\\n`;\r\n\tbuf += `|pagehtml|

    Battlesearch for ${targetUser} in ${format} in the last ${days} days

    `;\r\n\tbuf += `
    `;\r\n\tbuf += `

    Searching...

    `;\r\n\tbuf += `
    `;\r\n\tconnection.send(buf);\r\n\r\n\tconst search = child_process.spawn(\r\n\t\t'psbattletools',\r\n\t\t['--threads', '3', 'search', targetUser, ...directories],\r\n\t\t{env: {PATH: `${process.env.PATH}:${process.env.HOME}/.cargo/bin`}}\r\n\t);\r\n\tsearch.stdout.on('data', data => {\r\n\t\tbuf = buf.replace('', `${Chat.formatText(data.toString()).replace(/\\n/g, '
    ')}`);\r\n\t\tconnection.send(buf);\r\n\t});\r\n\tsearch.on('close', () => {\r\n\t\tbuf = buf.replace('Searching...', 'Done!');\r\n\t\tconnection.send(buf);\r\n\t});\r\n}\r\n\r\nasync function fsBattleSearch(\r\n\tconnection: Connection, userids: string[], month: string,\r\n\ttierid: ID, turnLimit?: number\r\n) {\r\n\tuserids = userids.map(toID);\r\n\tconst user = connection.user;\r\n\tif (!user.can('forcewin')) return connection.popup(`/battlesearch - Access Denied`);\r\n\r\n\tconst response = await PM.query({userids, turnLimit, month, tierid});\r\n\tconnection.send(buildResults(response, userids as ID[], month, tierid, turnLimit));\r\n}\r\n\r\nexport const pages: Chat.PageTable = {\r\n\tasync battlesearch(args, user, connection) {\r\n\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\r\n\t\tthis.checkCan('forcewin');\r\n\t\tif (Config.nobattlesearch === true) {\r\n\t\t\treturn this.errorReply(`Battlesearch has been temporarily disabled due to load issues.`);\r\n\t\t}\r\n\t\tif (Config.nobattlesearch === 'psbattletools') {\r\n\t\t\treturn rustBattleSearch(this, args[0], args[1], toID(args[2]));\r\n\t\t}\r\n\t\tconst [ids, rawLimit, month, formatid, confirmation] = Utils.splitFirst(this.pageid.slice(18), '--', 5);\r\n\t\tlet turnLimit: number | undefined = parseInt(rawLimit);\r\n\t\tif (isNaN(turnLimit)) turnLimit = undefined;\r\n\t\tconst userids = ids.split('-');\r\n\t\tif (!ids || turnLimit && turnLimit < 1) {\r\n\t\t\treturn user.popup(`Some arguments are missing or invalid for battlesearch. Use /battlesearch to start over.`);\r\n\t\t}\r\n\t\tthis.title = `[Battle Search][${userids.join(', ')}]`;\r\n\t\tlet buf = `

    Battle Search

    Userid${Chat.plural(userids)}: ${userids.join(', ')}

    `;\r\n\t\tif (turnLimit) {\r\n\t\t\tbuf += `Maximum Turns: ${turnLimit}`;\r\n\t\t}\r\n\t\tbuf += `

    `;\r\n\r\n\t\tconst months = Utils.sortBy(\r\n\t\t\t(await FS('logs/').readdir()).filter(f => f.length === 7 && f.includes('-')),\r\n\t\t\tname => ({reverse: name})\r\n\t\t);\r\n\t\tif (!month) {\r\n\t\t\tbuf += `

    Please select a month:

    `;\r\n\t\t} else {\r\n\t\t\tif (!months.includes(month)) {\r\n\t\t\t\treturn `${buf}Invalid month selected. `;\r\n\t\t\t}\r\n\t\t\tbuf += `

    `;\r\n\t\t}\r\n\r\n\t\tconst tierid = toID(formatid);\r\n\t\tconst tiers = Utils.sortBy(await FS(`logs/${month}/`).readdir(), tier => [\r\n\t\t\t// First sort by gen with the latest being first\r\n\t\t\ttier.startsWith('gen') ? -parseInt(tier.charAt(3)) : -6,\r\n\t\t\t// Then sort alphabetically\r\n\t\t\ttier,\r\n\t\t]).map(tier => {\r\n\t\t\t// Use the official tier name\r\n\t\t\tconst format = Dex.formats.get(tier);\r\n\t\t\tif (format?.exists) tier = format.name;\r\n\t\t\t// Otherwise format as best as possible\r\n\t\t\tif (tier.startsWith('gen')) {\r\n\t\t\t\treturn `[Gen ${tier.substring(3, 4)}] ${tier.substring(4)}`;\r\n\t\t\t}\r\n\t\t\treturn tier;\r\n\t\t});\r\n\t\tif (!tierid) {\r\n\t\t\tbuf += `

    Please select the tier to search:

    `;\r\n\t\t} else {\r\n\t\t\tif (!tiers.map(toID).includes(tierid)) {\r\n\t\t\t\treturn `${buf}Invalid tier selected. `;\r\n\t\t\t}\r\n\t\t\tthis.title += `[${tierid}]`;\r\n\t\t\tbuf += `

    `;\r\n\t\t}\r\n\r\n\t\tconst [userid] = userids;\r\n\t\tif (toID(confirmation) !== 'confirm') {\r\n\t\t\tbuf += `

    Are you sure you want to run a battle search for for ${tierid} battles on ${month} `;\r\n\t\t\tbuf += `where the ${userids.length > 1 ? `user(s) ${userids.join(', ')} were players` : `the user ${userid} was a player`}`;\r\n\t\t\tif (turnLimit) buf += ` and the battle lasted less than ${turnLimit} turn${Chat.plural(turnLimit)}`;\r\n\t\t\tbuf += `?

    `;\r\n\t\t\treturn `${buf}`;\r\n\t\t}\r\n\r\n\t\t// Run search\r\n\t\tvoid fsBattleSearch(connection, userids, month, tierid, turnLimit);\r\n\t\treturn (\r\n\t\t\t`

    Battle Search

    ` +\r\n\t\t\t`Searching for ${tierid} battles on ${month} where the ` +\r\n\t\t\t`${userids.length > 1 ? `user(s) ${userids.join(', ')} were players` : `the user ${userid} was a player`} ` +\r\n\t\t\t(turnLimit ? `and the battle lasted less than ${turnLimit} turn${Chat.plural(turnLimit)}.` : '') +\r\n\t\t\t`

    Loading... (this will take a while)

    `\r\n\t\t);\r\n\t},\r\n};\r\n\r\nexport const commands: Chat.ChatCommands = {\r\n\tbattlesearch(target, room, user, connection) {\r\n\t\tif (!target.trim()) return this.parse('/help battlesearch');\r\n\t\tthis.checkCan('forcewin');\r\n\r\n\t\tconst parts = target.split(',');\r\n\t\tlet turnLimit;\r\n\t\tconst ids = [];\r\n\t\tfor (const part of parts) {\r\n\t\t\tif (part.startsWith('limit=')) {\r\n\t\t\t\tconst n = parseInt(part.slice('limit='.length).trim());\r\n\t\t\t\tif (isNaN(n)) {\r\n\t\t\t\t\treturn this.errorReply(`Invalid limit: ${part.slice('limit='.length)}`);\r\n\t\t\t\t}\r\n\t\t\t\tturnLimit = n;\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\t\t\tids.push(part);\r\n\t\t}\r\n\t\t// Selection on month, tier, and date will be handled in the HTML room\r\n\t\treturn this.parse(`/join view-battlesearch-${ids.map(toID).join('-')}--${turnLimit || \"\"}`);\r\n\t},\r\n\tbattlesearchhelp() {\r\n\t\tif (Config.nobattlesearch === 'psbattletools') {\r\n\t\t\t// use the psbattletools battlesearch command instead\r\n\t\t\treturn this.parse('/help rustbattlesearch');\r\n\t\t}\r\n\r\n\t\tthis.runBroadcast();\r\n\t\treturn this.sendReply(\r\n\t\t\t'/battlesearch [args] - Searches rated battle history for the provided [args] and returns information on battles between the userids given.\\n' +\r\n\t\t\t`If a number is provided in the [args], it is assumed to be a turn limit, else they're assumed to be userids. Requires &`\r\n\t\t);\r\n\t},\r\n\trustbattlesearchhelp: [\r\n\t\t`/battlesearch , , - Searches for battles played by in the past days. Requires: &`,\r\n\t],\r\n};\r\n\r\n/*********************************************************\r\n * Process manager\r\n *********************************************************/\r\n\r\nexport const PM = new ProcessManager.QueryProcessManager(module, async data => {\r\n\tconst {userids, turnLimit, month, tierid} = data;\r\n\tconst start = Date.now();\r\n\ttry {\r\n\t\tconst result = await runBattleSearch(userids, month, tierid, turnLimit);\r\n\t\tconst elapsedTime = Date.now() - start;\r\n\t\tif (elapsedTime > 10 * 60 * 1000) {\r\n\t\t\tMonitor.slow(`[Slow battlesearch query] ${elapsedTime}ms: ${JSON.stringify(data)}`);\r\n\t\t}\r\n\t\treturn result;\r\n\t} catch (err) {\r\n\t\tMonitor.crashlog(err, 'A battle search query', {\r\n\t\t\tuserids,\r\n\t\t\tturnLimit,\r\n\t\t\tmonth,\r\n\t\t\ttierid,\r\n\t\t});\r\n\t}\r\n\treturn null;\r\n}, BATTLESEARCH_PROCESS_TIMEOUT, message => {\r\n\tif (message.startsWith('SLOW\\n')) {\r\n\t\tMonitor.slow(message.slice(5));\r\n\t}\r\n});\r\n\r\nif (!PM.isParentProcess) {\r\n\t// This is a child process!\r\n\tglobal.Config = require('../config-loader').Config;\r\n\tglobal.Monitor = {\r\n\t\tcrashlog(error: Error, source = 'A battle search process', details: AnyObject | null = null) {\r\n\t\t\tconst repr = JSON.stringify([error.name, error.message, source, details]);\r\n\t\t\tprocess.send!(`THROW\\n@!!@${repr}\\n${error.stack}`);\r\n\t\t},\r\n\t\tslow(text: string) {\r\n\t\t\tprocess.send!(`CALLBACK\\nSLOW\\n${text}`);\r\n\t\t},\r\n\t};\r\n\tprocess.on('uncaughtException', err => {\r\n\t\tif (Config.crashguard) {\r\n\t\t\tMonitor.crashlog(err, 'A battle search child process');\r\n\t\t}\r\n\t});\r\n\tglobal.Dex = require('../../sim/dex').Dex;\r\n\tglobal.toID = Dex.toID;\r\n\t// eslint-disable-next-line no-eval\r\n\tRepl.start('battlesearch', cmd => eval(cmd));\r\n} else {\r\n\tPM.spawn(MAX_BATTLESEARCH_PROCESSES);\r\n}\r\n"], "mappings": "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", "names": ["buf"] }