{ "version": 3, "sources": ["../../../../server/chat-plugins/scavengers.ts"], "sourcesContent": ["/**\r\n * Scavengers Plugin\r\n * Pokemon Showdown - http://pokemonshowdown.com/\r\n *\r\n * This is a game plugin to host scavenger games specifically in the Scavengers room,\r\n * where the players will race answer several hints.\r\n *\r\n * @license MIT license\r\n */\r\n\r\nimport {FS, Utils} from '../../lib';\r\nimport {ScavMods, TwistEvent} from './scavenger-games';\r\nimport {ChatHandler} from '../chat';\r\n\r\ntype GameTypes = 'official' | 'regular' | 'mini' | 'unrated' | 'practice' | 'recycled';\r\n\r\nexport interface QueuedHunt {\r\n\thosts: {id: string, name: string, noUpdate?: boolean}[];\r\n\tquestions: (string | string[])[];\r\n\tstaffHostId: string;\r\n\tstaffHostName: string;\r\n\tgameType: GameTypes;\r\n}\r\nexport interface FakeUser {\r\n\tname: string;\r\n\tid: string;\r\n\tnoUpdate?: boolean;\r\n}\r\ninterface ModEvent {\r\n\tpriority: number;\r\n\texec: TwistEvent;\r\n}\r\n\r\nconst RATED_TYPES = ['official', 'regular', 'mini'];\r\nconst DEFAULT_POINTS: {[k: string]: number[]} = {\r\n\tofficial: [20, 15, 10, 5, 1],\r\n};\r\nconst DEFAULT_BLITZ_POINTS: {[k: string]: number} = {\r\n\tofficial: 10,\r\n};\r\nconst DEFAULT_HOST_POINTS = 4;\r\nconst DEFAULT_TIMER_DURATION = 120;\r\n\r\nconst DATA_FILE = 'config/chat-plugins/ScavMods.json';\r\nconst HOST_DATA_FILE = 'config/chat-plugins/scavhostdata.json';\r\nconst PLAYER_DATA_FILE = 'config/chat-plugins/scavplayerdata.json';\r\nconst DATABASE_FILE = 'config/chat-plugins/scavhunts.json';\r\n\r\nconst ACCIDENTAL_LEAKS = /^((?:\\s)?(?:\\/{2,}|[^\\w/]+)|\\s\\/)?(?:\\s)?(?:s\\W?cavenge|s\\W?cav(?:engers)? guess|d\\W?t|d\\W?ata|d\\W?etails|g\\W?(?:uess)?|v)\\b/i;\r\n\r\nconst FILTER_LENIENCY = 7;\r\n\r\nconst HISTORY_PERIOD = 6; // months\r\n\r\nconst databaseContentsJSON = FS(DATABASE_FILE).readIfExistsSync();\r\nconst scavengersData = databaseContentsJSON ? JSON.parse(databaseContentsJSON) : {recycledHunts: []};\r\n\r\nconst SCAVENGER_ROOMID = 'scavengers';\r\nfunction getScavsRoom(room?: Room) {\r\n\tif (!room) return Rooms.get(SCAVENGER_ROOMID);\r\n\tif (room.roomid === SCAVENGER_ROOMID) return room;\r\n\tif (room.parent?.roomid === SCAVENGER_ROOMID) return room.parent;\r\n\treturn null;\r\n}\r\n\r\nclass Ladder {\r\n\tfile: string;\r\n\tdata: {[userid: string]: AnyObject};\r\n\tconstructor(file: string) {\r\n\t\tthis.file = file;\r\n\t\tthis.data = {};\r\n\r\n\t\tthis.load();\r\n\t}\r\n\r\n\tload() {\r\n\t\tconst json = FS(this.file).readIfExistsSync();\r\n\t\tif (json) this.data = JSON.parse(json);\r\n\t}\r\n\r\n\taddPoints(name: string, aspect: string, points: number, noUpdate?: boolean) {\r\n\t\tconst userid = toID(name);\r\n\r\n\t\tif (!userid || userid === 'constructor' || !points) return this;\r\n\t\tif (!this.data[userid]) this.data[userid] = {name: name};\r\n\r\n\t\tif (!this.data[userid][aspect]) this.data[userid][aspect] = 0;\r\n\t\tthis.data[userid][aspect] += points;\r\n\r\n\t\tif (!noUpdate) this.data[userid].name = name; // always keep the last used name\r\n\r\n\t\treturn this; // allow chaining\r\n\t}\r\n\r\n\treset() {\r\n\t\tthis.data = {};\r\n\t\treturn this; // allow chaining\r\n\t}\r\n\r\n\twrite() {\r\n\t\tFS(this.file).writeUpdate(() => JSON.stringify(this.data));\r\n\t}\r\n\r\n\tvisualize(sortBy: string): Promise<({rank: number} & AnyObject)[]>;\r\n\tvisualize(sortBy: string, userid: ID): Promise<({rank: number} & AnyObject) | undefined>;\r\n\tvisualize(sortBy: string, userid?: ID) {\r\n\t\t// return a promise for async sorting - make this less exploitable\r\n\t\treturn new Promise((resolve, reject) => {\r\n\t\t\tlet lowestScore = Infinity;\r\n\t\t\tlet lastPlacement = 1;\r\n\r\n\t\t\tconst ladder = Utils.sortBy(\r\n\t\t\t\tObject.entries(this.data).filter(([u, bit]) => sortBy in bit),\r\n\t\t\t\t([u, bit]) => -bit[sortBy]\r\n\t\t\t).map(([u, chunk], i) => {\r\n\t\t\t\tif (chunk[sortBy] !== lowestScore) {\r\n\t\t\t\t\tlowestScore = chunk[sortBy];\r\n\t\t\t\t\tlastPlacement = i + 1;\r\n\t\t\t\t}\r\n\t\t\t\treturn {\r\n\t\t\t\t\trank: lastPlacement,\r\n\t\t\t\t\t...chunk,\r\n\t\t\t\t} as {rank: number} & AnyObject;\r\n\t\t\t}); // identify ties\r\n\t\t\tif (userid) {\r\n\t\t\t\tconst rank = ladder.find(entry => toID(entry.name) === userid);\r\n\t\t\t\tresolve(rank);\r\n\t\t\t} else {\r\n\t\t\t\tresolve(ladder);\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n}\r\n\r\nclass PlayerLadder extends Ladder {\r\n\tconstructor(file: string) {\r\n\t\tsuper(file);\r\n\t}\r\n\r\n\taddPoints(name: string, aspect: string, points: number, noUpdate?: boolean) {\r\n\t\tif (!aspect.startsWith('cumulative-')) {\r\n\t\t\tthis.addPoints(name, `cumulative-${aspect}`, points, noUpdate);\r\n\t\t}\r\n\t\tconst userid = toID(name);\r\n\r\n\t\tif (!userid || userid === 'constructor' || !points) return this;\r\n\t\tif (!this.data[userid]) this.data[userid] = {name: name};\r\n\r\n\t\tif (!this.data[userid][aspect]) this.data[userid][aspect] = 0;\r\n\t\tthis.data[userid][aspect] += points;\r\n\r\n\t\tif (!noUpdate) this.data[userid].name = name; // always keep the last used name\r\n\r\n\t\treturn this; // allow chaining\r\n\t}\r\n\r\n\t// add the different keys to the history - async for larger leaderboards\r\n\t// FIXME: this is not what \"async\" means\r\n\tsoftReset() {\r\n\t\treturn new Promise((resolve, reject) => {\r\n\t\t\tfor (const u in this.data) {\r\n\t\t\t\tconst userData = this.data[u];\r\n\t\t\t\tfor (const a in userData) {\r\n\t\t\t\t\tif (/^(?:cumulative|history)-/i.test(a) || a === 'name') continue; // cumulative does not need to be soft reset\r\n\t\t\t\t\tconst historyKey = 'history-' + a;\r\n\r\n\t\t\t\t\tif (!userData[historyKey]) userData[historyKey] = [];\r\n\r\n\t\t\t\t\tuserData[historyKey].unshift(userData[a]);\r\n\t\t\t\t\tuserData[historyKey] = userData[historyKey].slice(0, HISTORY_PERIOD);\r\n\r\n\t\t\t\t\tuserData[a] = 0; // set it back to 0\r\n\t\t\t\t\t// clean up if history is all 0's\r\n\t\t\t\t\tif (!userData[historyKey].some((p: any) => !!p)) {\r\n\t\t\t\t\t\tdelete userData[a];\r\n\t\t\t\t\t\tdelete userData[historyKey];\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tresolve();\r\n\t\t});\r\n\t}\r\n\r\n\thardReset() {\r\n\t\tthis.data = {};\r\n\t\treturn this; // allow chaining\r\n\t}\r\n}\r\n\r\n// initialize roomsettings\r\nconst LeaderboardRoom = getScavsRoom();\r\n\r\nconst Leaderboard = LeaderboardRoom?.scavLeaderboard?.scavsLeaderboard || new Ladder(DATA_FILE);\r\nconst HostLeaderboard = LeaderboardRoom?.scavLeaderboard?.scavsHostLeaderboard || new PlayerLadder(HOST_DATA_FILE);\r\nconst PlayerLeaderboard = LeaderboardRoom?.scavLeaderboard?.scavsPlayerLeaderboard ||\r\n\tnew PlayerLadder(PLAYER_DATA_FILE);\r\n\r\nif (LeaderboardRoom) {\r\n\tif (!LeaderboardRoom.scavLeaderboard) LeaderboardRoom.scavLeaderboard = {};\r\n\t// bind ladders to scavenger room to persist through restarts\r\n\tLeaderboardRoom.scavLeaderboard.scavsLeaderboard = Leaderboard;\r\n\tLeaderboardRoom.scavLeaderboard.scavsHostLeaderboard = HostLeaderboard;\r\n\tLeaderboardRoom.scavLeaderboard.scavsPlayerLeaderboard = PlayerLeaderboard;\r\n}\r\n\r\nfunction formatQueue(queue: QueuedHunt[] | undefined, viewer: User, room: Room, broadcasting?: boolean) {\r\n\tconst showStaff = viewer.can('mute', null, room) && !broadcasting;\r\n\tconst queueDisabled = room.settings.scavSettings?.scavQueueDisabled;\r\n\tconst timerDuration = room.settings.scavSettings?.defaultScavTimer || DEFAULT_TIMER_DURATION;\r\n\tlet buffer;\r\n\tif (queue?.length) {\r\n\t\tbuffer = queue.map((item, index) => {\r\n\t\t\tconst removeButton = ``;\r\n\t\t\tconst startButton = ``;\r\n\t\t\tconst unratedText = item.gameType === 'unrated' ?\r\n\t\t\t\t'[Unrated] ' :\r\n\t\t\t\t'';\r\n\t\t\tconst hosts = Utils.escapeHTML(Chat.toListString(item.hosts.map(h => h.name)));\r\n\t\t\tconst queuedBy = item.hosts.every(h => h.id !== item.staffHostId) ? ` / ${item.staffHostId}` : '';\r\n\t\t\tlet questions;\r\n\t\t\tif (!broadcasting && (item.hosts.some(h => h.id === viewer.id) || viewer.id === item.staffHostId)) {\r\n\t\t\t\tquestions = item.questions.map(\r\n\t\t\t\t\t(q, i) => {\r\n\t\t\t\t\t\tif (i % 2) {\r\n\t\t\t\t\t\t\tq = q as string[];\r\n\t\t\t\t\t\t\treturn Utils.html`[${q.join(' / ')}]
`;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tq = q as string;\r\n\t\t\t\t\t\t\treturn Utils.escapeHTML(q);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t).join(\" \");\r\n\t\t\t} else {\r\n\t\t\t\tquestions = `[${item.questions.length / 2} hidden questions]`;\r\n\t\t\t}\r\n\t\t\treturn `${removeButton}${startButton} ${unratedText}${hosts}${queuedBy}${questions}`;\r\n\t\t}).join(\"\");\r\n\t} else {\r\n\t\tbuffer = `The scavenger queue is currently empty.`;\r\n\t}\r\n\tlet template = `
${showStaff ? buffer : buffer.replace(/.+?<\\/button>/gi, '')}
ByQuestions
`;\r\n\tif (showStaff) {\r\n\t\ttemplate += `
Auto Timer Duration: ${timerDuration} minutesAuto Dequeue:  
`;\r\n\t}\r\n\treturn template;\r\n}\r\n\r\nclass ScavengerHuntDatabase {\r\n\tstatic getRecycledHuntFromDatabase() {\r\n\t\t// Return a random hunt from the database.\r\n\t\treturn scavengersData.recycledHunts[Math.floor(Math.random() * scavengersData.recycledHunts.length)];\r\n\t}\r\n\r\n\tstatic addRecycledHuntToDatabase(hosts: FakeUser[], params: (string | string[])[]) {\r\n\t\tconst huntSchema: {hosts: FakeUser[], questions: AnyObject[]} = {\r\n\t\t\thosts: hosts,\r\n\t\t\tquestions: [],\r\n\t\t};\r\n\r\n\t\tlet questionSchema: {text: string, answers: string[], hints?: string[]} = {\r\n\t\t\ttext: '',\r\n\t\t\tanswers: [],\r\n\t\t\thints: [],\r\n\t\t};\r\n\r\n\t\tfor (let i = 0; i < params.length; ++i) {\r\n\t\t\tif (i % 2 === 0) {\r\n\t\t\t\tconst questionText = params[i] as string;\r\n\t\t\t\tquestionSchema.text = questionText;\r\n\t\t\t} else {\r\n\t\t\t\tconst answerText = params[i] as string[];\r\n\t\t\t\tquestionSchema.answers = answerText;\r\n\t\t\t\thuntSchema.questions.push(questionSchema);\r\n\t\t\t\tquestionSchema = {\r\n\t\t\t\t\ttext: '',\r\n\t\t\t\t\tanswers: [],\r\n\t\t\t\t\thints: [],\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tscavengersData.recycledHunts.push(huntSchema);\r\n\t\tthis.updateDatabaseOnDisk();\r\n\t}\r\n\r\n\tstatic removeRecycledHuntFromDatabase(index: number) {\r\n\t\tscavengersData.recycledHunts.splice(index - 1, 1);\r\n\t\tthis.updateDatabaseOnDisk();\r\n\t}\r\n\r\n\tstatic addHintToRecycledHunt(huntNumber: number, questionNumber: number, hint: string) {\r\n\t\tscavengersData.recycledHunts[huntNumber - 1].questions[questionNumber - 1].hints.push(hint);\r\n\t\tthis.updateDatabaseOnDisk();\r\n\t}\r\n\r\n\tstatic removeHintToRecycledHunt(huntNumber: number, questionNumber: number, hintNumber: number) {\r\n\t\tscavengersData.recycledHunts[huntNumber - 1].questions[questionNumber - 1].hints.splice(hintNumber - 1);\r\n\t\tthis.updateDatabaseOnDisk();\r\n\t}\r\n\r\n\tstatic updateDatabaseOnDisk() {\r\n\t\tFS(DATABASE_FILE).writeUpdate(() => JSON.stringify(scavengersData));\r\n\t}\r\n\r\n\tstatic isEmpty() {\r\n\t\treturn scavengersData.recycledHunts.length === 0;\r\n\t}\r\n\r\n\tstatic hasHunt(hunt_number: number) {\r\n\t\treturn !isNaN(hunt_number) && hunt_number > 0 && hunt_number <= scavengersData.recycledHunts.length;\r\n\t}\r\n\r\n\tstatic getFullTextOfHunt(hunt: {hosts: FakeUser[], questions: {text: string, answers: string[], hints?: string[]}[]}) {\r\n\t\treturn `${hunt.hosts.map(host => host.name).join(',')} | ${hunt.questions.map(question => `${question.text} | ${question.answers.join(';')}`).join(' | ')}`;\r\n\t}\r\n}\r\nexport class ScavengerHunt extends Rooms.RoomGame {\r\n\tgameType: GameTypes;\r\n\tjoinedIps: string[];\r\n\tstartTime: number;\r\n\tquestions: {hint: string, answer: string[], spoilers: string[]}[];\r\n\tcompleted: AnyObject[];\r\n\tleftHunt: {[userid: string]: 1 | undefined};\r\n\thosts: FakeUser[];\r\n\tmodsList: string[];\r\n\tmods: {[k: string]: ModEvent[]};\r\n\tstaffHostId: string;\r\n\tstaffHostName: string;\r\n\tgameid: ID;\r\n\tscavGame: true;\r\n\ttimerEnd: number | null;\r\n\ttimer: NodeJS.Timer | null;\r\n\r\n\treadonly checkChat = true;\r\n\r\n\t[k: string]: any; // for purposes of adding new temporary properties for the purpose of twists.\r\n\tconstructor(\r\n\t\troom: Room,\r\n\t\tstaffHost: User | FakeUser,\r\n\t\thosts: FakeUser[],\r\n\t\tgameType: GameTypes,\r\n\t\tquestions: (string | string[])[],\r\n\t\tmod?: string | string[]\r\n\t) {\r\n\t\tsuper(room);\r\n\r\n\t\tthis.allowRenames = true;\r\n\t\tthis.gameType = gameType;\r\n\t\tthis.playerCap = Infinity;\r\n\r\n\t\tthis.joinedIps = [];\r\n\r\n\t\tthis.startTime = Date.now();\r\n\t\tthis.questions = [];\r\n\t\tthis.completed = [];\r\n\r\n\t\tthis.leftHunt = {};\r\n\r\n\t\tthis.hosts = hosts;\r\n\r\n\t\tthis.modsList = [];\r\n\t\tthis.mods = {};\r\n\r\n\t\tthis.timer = null;\r\n\t\tthis.timerEnd = null;\r\n\r\n\t\tthis.staffHostId = staffHost.id;\r\n\t\tthis.staffHostName = staffHost.name;\r\n\t\tthis.cacheUserIps(staffHost); // store it in case of host subbing\r\n\r\n\t\tthis.gameid = 'scavengerhunt' as ID;\r\n\t\tthis.title = 'Scavenger Hunt';\r\n\t\tthis.scavGame = true;\r\n\r\n\t\tif (this.room.scavgame) {\r\n\t\t\tthis.loadMods(this.room.scavgame.mod);\r\n\t\t}\r\n\t\tif (mod) {\r\n\t\t\tthis.loadMods(mod);\r\n\t\t} else if (this.gameType === 'official' && this.room.settings.scavSettings?.officialtwist) {\r\n\t\t\tthis.loadMod(this.room.settings.scavSettings?.officialtwist);\r\n\t\t}\r\n\r\n\t\tthis.runEvent('Load');\r\n\t\tthis.onLoad(questions);\r\n\t\tthis.runEvent('AfterLoad');\r\n\t}\r\n\r\n\tloadMods(modInformation: any) {\r\n\t\tif (Array.isArray(modInformation)) {\r\n\t\t\tfor (const mod of modInformation) {\r\n\t\t\t\tthis.loadMod(mod);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis.loadMod(modInformation);\r\n\t\t}\r\n\t}\r\n\r\n\tloadMod(modData: string | ID | AnyObject) {\r\n\t\tlet twist;\r\n\t\tif (typeof modData === 'string') {\r\n\t\t\tconst modId = toID(modData) as string;\r\n\t\t\tif (!ScavMods.twists[modId]) return this.announce(`Invalid mod. Starting the hunt without the mod ${modId}.`);\r\n\r\n\t\t\ttwist = ScavMods.twists[modId];\r\n\t\t} else {\r\n\t\t\ttwist = modData;\r\n\t\t}\r\n\t\tthis.modsList.push(twist.id);\r\n\t\tfor (const key in twist) {\r\n\t\t\tif (!key.startsWith('on')) continue;\r\n\t\t\tconst priority = twist[key + 'Priority'] || 0;\r\n\t\t\tif (!this.mods[key]) this.mods[key] = [];\r\n\t\t\tthis.mods[key].push({exec: twist[key], priority});\r\n\t\t}\r\n\t\tif (twist.isGameMode) {\r\n\t\t\tthis.announce(`This hunt is part of an ongoing ${twist.name}.`);\r\n\t\t} else {\r\n\t\t\tthis.announce(`This hunt uses the twist ${twist.name}.`);\r\n\t\t}\r\n\t}\r\n\r\n\t// alert new users that are joining the room about the current hunt.\r\n\tonConnect(user: User, connection: Connection) {\r\n\t\t// send the fact that a hunt is currently going on.\r\n\t\tconnection.sendTo(this.room, this.getCreationMessage());\r\n\t\tthis.runEvent('Connect', user, connection);\r\n\t}\r\n\r\n\tgetCreationMessage(newHunt?: boolean): string {\r\n\t\tconst message = this.runEvent('CreateCallback');\r\n\t\tif (message) return message;\r\n\r\n\t\tconst hosts = Utils.escapeHTML(Chat.toListString(this.hosts.map(h => h.name)));\r\n\t\tconst staffHost = this.hosts.some(h => h.id === this.staffHostId) ?\r\n\t\t\t`` :\r\n\t\t\tUtils.html` by ${this.staffHostName}`;\r\n\r\n\t\tconst article = ['official', 'unrated'].includes(this.gameType) && !newHunt ? 'An' : 'A';\r\n\t\tconst huntType = `${article} ${newHunt ? 'new ' : ''}${this.gameType}`;\r\n\r\n\t\treturn `|raw|
${huntType} scavenger hunt by ${hosts} has been started${staffHost}.` +\r\n\t\t\t`
` +\r\n\t\t\t`Hint #1: ${Chat.formatText(this.questions[0].hint)}` +\r\n\t\t\t`
` +\r\n\t\t\t`(To answer, use /scavenge ANSWER)
`;\r\n\t}\r\n\r\n\tjoinGame(user: User) {\r\n\t\tif (this.hosts.some(h => h.id === user.id) || user.id === this.staffHostId) {\r\n\t\t\treturn user.sendTo(\r\n\t\t\t\tthis.room,\r\n\t\t\t\t\"You cannot join your own hunt! If you wish to view your questions, use /viewhunt instead!\"\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (!Config.noipchecks && user.ips.some(ip => this.joinedIps.includes(ip))) {\r\n\t\t\treturn user.sendTo(this.room, \"You already have one alt in the hunt.\");\r\n\t\t}\r\n\t\tif (this.runEvent('Join', user)) return false;\r\n\t\tif (this.addPlayer(user)) {\r\n\t\t\tthis.cacheUserIps(user);\r\n\t\t\tdelete this.leftHunt[user.id];\r\n\t\t\tuser.sendTo(this.room, \"You joined the scavenger hunt! Use the command /scavenge to answer.\");\r\n\t\t\tthis.onSendQuestion(user);\r\n\t\t\treturn true;\r\n\t\t}\r\n\t\tuser.sendTo(this.room, \"You have already joined the hunt.\");\r\n\t\treturn false;\r\n\t}\r\n\r\n\tcacheUserIps(user: User | FakeUser) {\r\n\t\t// limit to 1 IP in every game.\r\n\t\tif (!('ips' in user)) return; // ghost user object cached from queue\r\n\t\tfor (const ip of user.ips) {\r\n\t\t\tthis.joinedIps.push(ip);\r\n\t\t}\r\n\t}\r\n\r\n\tleaveGame(user: User) {\r\n\t\tconst player = this.playerTable[user.id];\r\n\r\n\t\tif (!player) return user.sendTo(this.room, \"You have not joined the scavenger hunt.\");\r\n\t\tif (player.completed) return user.sendTo(this.room, \"You have already completed this scavenger hunt.\");\r\n\t\tthis.runEvent('Leave', player);\r\n\t\tthis.joinedIps = this.joinedIps.filter(ip => !player.joinIps.includes(ip));\r\n\t\tthis.removePlayer(user);\r\n\t\tthis.leftHunt[user.id] = 1;\r\n\t\tuser.sendTo(this.room, \"You have left the scavenger hunt.\");\r\n\t}\r\n\r\n\t// overwrite the default makePlayer so it makes a ScavengerHuntPlayer instead.\r\n\tmakePlayer(user: User) {\r\n\t\treturn new ScavengerHuntPlayer(user, this);\r\n\t}\r\n\r\n\tonLoad(q: (string | string[])[]) {\r\n\t\tfor (let i = 0; i < q.length; i += 2) {\r\n\t\t\tconst hint = q[i] as string;\r\n\t\t\tconst answer = q[i + 1] as string[];\r\n\r\n\t\t\tthis.questions.push({hint: hint, answer: answer, spoilers: []});\r\n\t\t}\r\n\r\n\t\tconst message = this.getCreationMessage(true);\r\n\t\tthis.room.add(message).update();\r\n\t}\r\n\r\n\t// returns whether or not the next action should be stopped\r\n\trunEvent(event_id: string, ...args: any[]) {\r\n\t\tconst events = this.mods['on' + event_id];\r\n\t\tif (!events) return;\r\n\r\n\t\tUtils.sortBy(events, event => -event.priority);\r\n\t\tlet result = undefined;\r\n\r\n\t\tfor (const event of events) {\r\n\t\t\tconst subResult = event.exec.call(this, ...args) as any;\r\n\t\t\tif (subResult === true) return true;\r\n\t\t\tresult = subResult;\r\n\t\t}\r\n\r\n\t\treturn result === false ? true : result;\r\n\t}\r\n\r\n\tonEditQuestion(questionNumber: number, question_answer: string, value: string) {\r\n\t\tif (question_answer === 'question') question_answer = 'hint';\r\n\t\tif (!['hint', 'answer'].includes(question_answer)) return false;\r\n\r\n\t\tlet answer: string[] = [];\r\n\t\tif (question_answer === 'answer') {\r\n\t\t\tanswer = value.split(';').map(p => p.trim());\r\n\t\t}\r\n\r\n\t\tif (!questionNumber || questionNumber < 1 || questionNumber > this.questions.length || (!answer && !value)) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tquestionNumber--; // indexOf starts at 0\r\n\r\n\t\tif (question_answer === 'answer') {\r\n\t\t\tthis.questions[questionNumber].answer = answer;\r\n\t\t} else {\r\n\t\t\tthis.questions[questionNumber].hint = value;\r\n\t\t}\r\n\r\n\t\tthis.announce(`The ${question_answer} for question ${questionNumber + 1} has been edited.`);\r\n\t\tif (question_answer === 'hint') {\r\n\t\t\tfor (const p in this.playerTable) {\r\n\t\t\t\tthis.playerTable[p].onNotifyChange(questionNumber);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tsetTimer(minutes: number) {\r\n\t\tif (this.timer) {\r\n\t\t\tclearTimeout(this.timer);\r\n\t\t\tthis.timer = null;\r\n\t\t\tthis.timerEnd = null;\r\n\t\t}\r\n\r\n\t\tif (minutes === 0) {\r\n\t\t\treturn 'off';\r\n\t\t}\r\n\t\tif (minutes > 24 * 60) { // 24 hours\r\n\t\t\tthrow new Chat.ErrorMessage(`Time limit must be under 24 hours (you asked for ${Chat.toDurationString(minutes * 60000)}).`);\r\n\t\t}\r\n\t\tif (minutes && minutes > 0) {\r\n\t\t\tthis.timer = setTimeout(() => this.onEnd(), minutes * 60000);\r\n\t\t\tthis.timerEnd = Date.now() + minutes * 60000;\r\n\t\t}\r\n\r\n\t\treturn minutes;\r\n\t}\r\n\r\n\tchoose(user: User, originalValue: string) {\r\n\t\tif (!(user.id in this.playerTable)) {\r\n\t\t\tif (!this.joinGame(user)) return false;\r\n\t\t}\r\n\t\tconst value = toID(originalValue);\r\n\r\n\t\tconst player = this.playerTable[user.id];\r\n\r\n\t\tif (this.runEvent('AnySubmit', player, value, originalValue)) return;\r\n\t\tif (player.completed) return false;\r\n\r\n\t\tthis.validatePlayer(player);\r\n\t\tplayer.lastGuess = Date.now();\r\n\r\n\t\tif (this.runEvent('Submit', player, value, originalValue)) return false;\r\n\r\n\t\tif (player.verifyAnswer(value)) {\r\n\t\t\tif (this.runEvent('CorrectAnswer', player, value)) return;\r\n\t\t\tplayer.sendRoom(\"Congratulations! You have gotten the correct answer.\");\r\n\t\t\tplayer.currentQuestion++;\r\n\t\t\tif (player.currentQuestion === this.questions.length) {\r\n\t\t\t\tthis.onComplete(player);\r\n\t\t\t} else {\r\n\t\t\t\tthis.onSendQuestion(user);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.runEvent('IncorrectAnswer', player, value)) return;\r\n\t\t\tthrow new Chat.ErrorMessage(\"That is not the answer - try again!\");\r\n\t\t}\r\n\t}\r\n\r\n\tgetQuestion(question: number, showHints?: boolean) {\r\n\t\tconst current = {\r\n\t\t\tquestion: this.questions[question - 1],\r\n\t\t\tnumber: question,\r\n\t\t};\r\n\t\tconst finalHint = current.number === this.questions.length ? \"Final \" : \"\";\r\n\r\n\t\treturn `|raw|
` +\r\n\t\t\t`` +\r\n\t\t\t`` +\r\n\t\t\t`
${finalHint}Hint #${current.number}:${\r\n\t\t\t\tChat.formatText(current.question.hint) +\r\n\t\t\t\t(showHints && current.question.spoilers.length ?\r\n\t\t\t\t\t`
Extra Hints:${\r\n\t\t\t\t\t\tcurrent.question.spoilers.map(p => `- ${p}`).join('
')\r\n\t\t\t\t\t}
` :\r\n\t\t\t\t\t``)\r\n\t\t\t}
`;\r\n\t}\r\n\r\n\tonSendQuestion(user: User | ScavengerHuntPlayer, showHints?: boolean) {\r\n\t\tif (!(user.id in this.playerTable) || this.hosts.some(h => h.id === user.id)) return false;\r\n\r\n\t\tconst player = this.playerTable[user.id];\r\n\t\tif (player.completed) return false;\r\n\r\n\t\tif (this.runEvent('SendQuestion', player, showHints)) return;\r\n\r\n\t\tconst questionDisplay = this.getQuestion(player.getCurrentQuestion().number, showHints);\r\n\r\n\t\tplayer.sendRoom(questionDisplay);\r\n\t\treturn true;\r\n\t}\r\n\r\n\tonViewHunt(user: User) {\r\n\t\tif (this.runEvent('ViewHunt', user)) return;\r\n\r\n\t\tlet qLimit = 1;\r\n\t\tif (this.hosts.some(h => h.id === user.id) || user.id === this.staffHostId)\t{\r\n\t\t\tqLimit = this.questions.length + 1;\r\n\t\t} else if (user.id in this.playerTable) {\r\n\t\t\tconst player = this.playerTable[user.id];\r\n\t\t\tqLimit = player.currentQuestion + 1;\r\n\t\t}\r\n\r\n\t\tuser.sendTo(\r\n\t\t\tthis.room,\r\n\t\t\t`|raw|
` +\r\n\t\t\t`` +\r\n\t\t\tthis.questions.slice(0, qLimit).map((q, i) => (\r\n\t\t\t\t``\r\n\t\t\t)).join(\"\") +\r\n\t\t\t`
#HintAnswer
${\r\n\t\t\t\t\ti + 1\r\n\t\t\t\t}${\r\n\t\t\t\t\tChat.formatText(q.hint) +\r\n\t\t\t\t\t(q.spoilers.length ?\r\n\t\t\t\t\t\t`
Extra Hints:${\r\n\t\t\t\t\t\t\tq.spoilers.map(s => `- ${s}`).join('
')\r\n\t\t\t\t\t\t}
` :\r\n\t\t\t\t\t\t``)\r\n\t\t\t\t}
${\r\n\t\t\t\t\ti + 1 >= qLimit ?\r\n\t\t\t\t\t\t`` :\r\n\t\t\t\t\t\tUtils.escapeHTMLForceWrap(q.answer.join(' ; '))\r\n\t\t\t\t}
`\r\n\t\t);\r\n\t}\r\n\r\n\tonComplete(player: ScavengerHuntPlayer) {\r\n\t\tif (player.completed) return false;\r\n\r\n\t\tconst now = Date.now();\r\n\t\tconst time = Chat.toDurationString(now - this.startTime, {hhmmss: true});\r\n\t\tconst canBlitz = this.completed.length < 3;\r\n\r\n\t\tconst blitz = now - this.startTime <= 60000 && canBlitz &&\r\n\t\t\t(this.room.settings.scavSettings?.blitzPoints?.[this.gameType] || DEFAULT_BLITZ_POINTS[this.gameType]);\r\n\r\n\t\tplayer.completed = true;\r\n\t\tlet result = this.runEvent('Complete', player, time, blitz);\r\n\t\tif (result === true) return;\r\n\t\tresult = result || {name: player.name, time: time, blitz: blitz};\r\n\t\tthis.completed.push(result);\r\n\t\tconst place = Utils.formatOrder(this.completed.length);\r\n\r\n\t\tconst completionMessage = this.runEvent('ConfirmCompletion', player, time, blitz, place, result);\r\n\t\tthis.announce(\r\n\t\t\tcompletionMessage ||\r\n\t\t\tUtils.html`${result.name} has finished the hunt in ${place} place! (${time}${(blitz ? \" - BLITZ\" : \"\")})`\r\n\t\t);\r\n\r\n\t\tplayer.destroy(); // remove from user.games;\r\n\t}\r\n\r\n\tonShowEndBoard(endedBy?: User) {\r\n\t\tconst sliceIndex = this.gameType === 'official' ? 5 : 3;\r\n\t\tconst hosts = Chat.toListString(this.hosts.map(h => `${Utils.escapeHTML(h.name)}`));\r\n\r\n\t\tthis.announce(\r\n\t\t\t`The ${this.gameType ? `${this.gameType} ` : \"\"}scavenger hunt by ${hosts} was ended ${(endedBy ? \"by \" + Utils.escapeHTML(endedBy.name) : \"automatically\")}.
` +\r\n\t\t\t`${this.completed.slice(0, sliceIndex).map((p, i) => `${Utils.formatOrder(i + 1)} place: ${Utils.escapeHTML(p.name)} [${p.time}].
`).join(\"\")}` +\r\n\t\t\t`${this.completed.length > sliceIndex ? `Consolation Prize: ${this.completed.slice(sliceIndex).map(e => `${Utils.escapeHTML(e.name)} [${e.time}]`).join(', ')}
` : ''}
` +\r\n\t\t\t`
Solution:
` +\r\n\t\t\t`${this.questions.map((q, i) => `${i + 1}) ${Chat.formatText(q.hint)} [${Utils.escapeHTML(q.answer.join(' / '))}]`).join(\"
\")}` +\r\n\t\t\t`
`\r\n\t\t);\r\n\t}\r\n\r\n\tonEnd(reset?: boolean, endedBy?: User) {\r\n\t\tif (!endedBy && (this.preCompleted ? this.preCompleted.length : this.completed.length) === 0) {\r\n\t\t\treset = true;\r\n\t\t}\r\n\r\n\t\tthis.runEvent('End', reset);\r\n\t\tif (!ScavengerHuntDatabase.isEmpty() && this.room.settings.scavSettings?.addRecycledHuntsToQueueAutomatically) {\r\n\t\t\tif (!this.room.settings.scavQueue) this.room.settings.scavQueue = [];\r\n\r\n\t\t\tconst next = ScavengerHuntDatabase.getRecycledHuntFromDatabase();\r\n\t\t\tconst correctlyFormattedQuestions = next.questions.flatMap((question: AnyObject) => [question.text, question.answers]);\r\n\t\t\tthis.room.settings.scavQueue.push({\r\n\t\t\t\thosts: next.hosts,\r\n\t\t\t\tquestions: correctlyFormattedQuestions,\r\n\t\t\t\tstaffHostId: 'scavengermanager',\r\n\t\t\t\tstaffHostName: 'Scavenger Manager',\r\n\t\t\t\tgameType: 'unrated',\r\n\t\t\t});\r\n\t\t}\r\n\t\tif (!reset) {\r\n\t\t\t// Display the finishers' board\r\n\t\t\tif (!this.runEvent('ShowEndBoard', endedBy)) this.onShowEndBoard(endedBy);\r\n\r\n\t\t\t// give points for winning and blitzes in official games\r\n\t\t\tif (!this.runEvent('GivePoints')) {\r\n\t\t\t\tconst winPoints = this.room.settings.scavSettings?.winPoints?.[this.gameType] ||\r\n\t\t\t\t\tDEFAULT_POINTS[this.gameType];\r\n\t\t\t\tconst blitzPoints = this.room.settings.scavSettings?.blitzPoints?.[this.gameType] ||\r\n\t\t\t\t\tDEFAULT_BLITZ_POINTS[this.gameType];\r\n\t\t\t\t// only regular hunts give host points\r\n\t\t\t\tlet hostPoints;\r\n\t\t\t\tif (this.gameType === 'regular') {\r\n\t\t\t\t\thostPoints = this.room.settings.scavSettings?.hostPoints ?\r\n\t\t\t\t\t\tthis.room.settings.scavSettings?.hostPoints :\r\n\t\t\t\t\t\tDEFAULT_HOST_POINTS;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlet didSomething = false;\r\n\t\t\t\tif (winPoints || blitzPoints) {\r\n\t\t\t\t\tfor (const [i, completed] of this.completed.entries()) {\r\n\t\t\t\t\t\tif (!completed.blitz && i >= winPoints.length) break; // there won't be any more need to keep going\r\n\t\t\t\t\t\tconst name = completed.name;\r\n\t\t\t\t\t\tif (winPoints[i]) Leaderboard.addPoints(name, 'points', winPoints[i]);\r\n\t\t\t\t\t\tif (blitzPoints && completed.blitz) Leaderboard.addPoints(name, 'points', blitzPoints);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdidSomething = true;\r\n\t\t\t\t}\r\n\t\t\t\tif (hostPoints) {\r\n\t\t\t\t\tif (this.hosts.length === 1) {\r\n\t\t\t\t\t\tLeaderboard.addPoints(this.hosts[0].name, 'points', hostPoints, this.hosts[0].noUpdate);\r\n\t\t\t\t\t\tdidSomething = true;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthis.room.sendMods('|notify|A scavenger hunt with multiple hosts needs points!');\r\n\t\t\t\t\t\tthis.room.sendMods('(A scavenger hunt with multiple hosts has ended.)');\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (didSomething) Leaderboard.write();\r\n\t\t\t}\r\n\r\n\t\t\tthis.onTallyLeaderboard();\r\n\r\n\t\t\tthis.tryRunQueue(this.room.roomid);\r\n\t\t} else if (endedBy) {\r\n\t\t\tthis.announce(`The scavenger hunt has been reset by ${endedBy.name}.`);\r\n\t\t} else {\r\n\t\t\tthis.announce(\"The hunt has been reset automatically, due to the lack of finishers.\");\r\n\t\t\tthis.tryRunQueue(this.room.roomid);\r\n\t\t}\r\n\t\tthis.runEvent('AfterEnd', reset);\r\n\t\tthis.destroy();\r\n\t}\r\n\r\n\tonTallyLeaderboard() {\r\n\t\t// update player leaderboard with the statistics\r\n\t\tfor (const p in this.playerTable) {\r\n\t\t\tconst player = this.playerTable[p];\r\n\t\t\tPlayerLeaderboard.addPoints(player.name, 'join', 1);\r\n\t\t\tif (player.completed) PlayerLeaderboard.addPoints(player.name, 'finish', 1);\r\n\t\t}\r\n\t\tfor (const id in this.leftHunt) {\r\n\t\t\tif (id in this.playerTable) continue; // this should never happen, but just in case;\r\n\r\n\t\t\tPlayerLeaderboard.addPoints(id, 'join', 1, true);\r\n\t\t}\r\n\t\tif (this.gameType !== 'practice') {\r\n\t\t\tfor (const host of this.hosts) {\r\n\t\t\t\tHostLeaderboard.addPoints(host.name, 'points', 1, host.noUpdate).write();\r\n\t\t\t}\r\n\t\t}\r\n\t\tPlayerLeaderboard.write();\r\n\t}\r\n\r\n\ttryRunQueue(roomid: RoomID) {\r\n\t\tif (this.room.scavgame || this.room.settings.scavSettings?.scavQueueDisabled) {\r\n\t\t\treturn; // don't run the queue for child games\r\n\t\t}\r\n\t\t// prepare the next queue'd game\r\n\t\tif (this.room.settings.scavQueue && this.room.settings.scavQueue.length) {\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tconst room = Rooms.get(roomid) as ChatRoom;\r\n\t\t\t\tif (!room || room.game || !room.settings.scavQueue?.length || room.settings.scavSettings?.scavQueueDisabled) return;\r\n\r\n\t\t\t\tconst next = room.settings.scavQueue.shift()!;\r\n\t\t\t\tconst duration = room.settings.scavSettings?.defaultScavTimer || DEFAULT_TIMER_DURATION;\r\n\t\t\t\troom.game = new ScavengerHunt(\r\n\t\t\t\t\troom,\r\n\t\t\t\t\t{id: next.staffHostId, name: next.staffHostName},\r\n\t\t\t\t\tnext.hosts,\r\n\t\t\t\t\tnext.gameType,\r\n\t\t\t\t\tnext.questions\r\n\t\t\t\t);\r\n\t\t\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\t\t\tif (game) {\r\n\t\t\t\t\tgame.setTimer(duration); // auto timer for queue'd games.\r\n\t\t\t\t\troom.add(`|c|~|[ScavengerManager] A scavenger hunt by ${Chat.toListString(next.hosts.map(h => h.name))} has been automatically started. It will automatically end in ${duration} minutes.`).update(); // highlight the users with \"hunt by\"\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// update the saved queue.\r\n\t\t\t\troom.saveSettings();\r\n\t\t\t}, 2 * 60000); // 2 minute cooldown\r\n\t\t}\r\n\t}\r\n\r\n\t// modify destroy to get rid of any timers in the current roomgame.\r\n\tdestroy() {\r\n\t\tif (this.timer) {\r\n\t\t\tclearTimeout(this.timer);\r\n\t\t}\r\n\t\tfor (const i in this.playerTable) {\r\n\t\t\tthis.playerTable[i].destroy();\r\n\t\t}\r\n\t\t// destroy this game\r\n\t\tthis.room.game = null;\r\n\t}\r\n\r\n\tannounce(msg: string) {\r\n\t\tthis.room.add(`|raw|
${msg}
`).update();\r\n\t}\r\n\r\n\tvalidatePlayer(player: ScavengerHuntPlayer) {\r\n\t\tif (player.infracted) return false;\r\n\t\tif (this.hosts.some(h => h.id === player.id) || player.id === this.staffHostId) {\r\n\t\t\t// someone joining on an alt then going back to their original userid\r\n\t\t\tplayer.sendRoom(\"You have been caught for doing your own hunt; staff has been notified.\");\r\n\r\n\t\t\t// notify staff\r\n\t\t\tconst staffMsg = `(${player.name} has been caught trying to do their own hunt.)`;\r\n\t\t\tthis.room.sendMods(staffMsg);\r\n\t\t\tthis.room.roomlog(staffMsg);\r\n\t\t\tthis.room.modlog({\r\n\t\t\t\taction: 'SCAV CHEATER',\r\n\t\t\t\tuserid: player.id,\r\n\t\t\t\tnote: 'caught trying to do their own hunt',\r\n\t\t\t});\r\n\r\n\t\t\tPlayerLeaderboard.addPoints(player.name, 'infraction', 1);\r\n\t\t\tplayer.infracted = true;\r\n\t\t}\r\n\r\n\t\tconst uniqueConnections = this.getUniqueConnections(player.id);\r\n\t\tif (uniqueConnections > 1 && this.room.settings.scavSettings?.scavmod?.ipcheck) {\r\n\t\t\t// multiple users on one alt\r\n\t\t\tplayer.sendRoom(\"You have been caught for attempting a hunt with multiple connections on your account. Staff has been notified.\");\r\n\r\n\t\t\t// notify staff\r\n\t\t\tconst staffMsg = `(${player.name} has been caught attempting a hunt with ${uniqueConnections} connections on the account. The user has also been given 1 infraction point on the player leaderboard.)`;\r\n\r\n\t\t\tthis.room.sendMods(staffMsg);\r\n\t\t\tthis.room.roomlog(staffMsg);\r\n\t\t\tthis.room.modlog({\r\n\t\t\t\taction: 'SCAV CHEATER',\r\n\t\t\t\tuserid: player.id,\r\n\t\t\t\tnote: `caught attempting a hunt with ${uniqueConnections} connections on the account; has also been given 1 infraction point on the player leaderboard`,\r\n\t\t\t});\r\n\r\n\t\t\tPlayerLeaderboard.addPoints(player.name, 'infraction', 1);\r\n\t\t\tplayer.infracted = true;\r\n\t\t}\r\n\t}\r\n\r\n\teliminate(userid: string) {\r\n\t\tif (!(userid in this.playerTable)) return false;\r\n\t\tconst player = this.playerTable[userid];\r\n\r\n\t\t// do not remove players that have completed - they should still get to see the answers\r\n\t\tif (player.completed) return true;\r\n\r\n\t\tplayer.destroy();\r\n\t\tdelete this.playerTable[userid];\r\n\t\treturn true;\r\n\t}\r\n\r\n\tonUpdateConnection() {}\r\n\r\n\tonChatMessage(msg: string) {\r\n\t\tlet msgId = toID(msg) as string;\r\n\r\n\t\t// identify if there is a bot/dt command that failed\r\n\t\t// remove it and then match the rest of the post for leaks.\r\n\t\tconst commandMatch = ACCIDENTAL_LEAKS.exec(msg);\r\n\t\tif (commandMatch) msgId = msgId.slice(toID(commandMatch[0]).length);\r\n\r\n\t\tconst filtered = this.questions.some(q => q.answer.some(a => {\r\n\t\t\ta = toID(a);\r\n\t\t\tconst md = Math.ceil((a.length - 5) / FILTER_LENIENCY);\r\n\t\t\tif (Utils.levenshtein(msgId, a, md) <= md) return true;\r\n\t\t\treturn false;\r\n\t\t}));\r\n\r\n\t\tif (filtered) return \"Please do not leak the answer. Use /scavenge [guess] to submit your guess instead.\";\r\n\t\treturn;\r\n\t}\r\n\r\n\thasFinished(user: User) {\r\n\t\treturn this.playerTable[user.id] && this.playerTable[user.id].completed;\r\n\t}\r\n\r\n\tgetUniqueConnections(userid: string) {\r\n\t\tconst user = Users.get(userid);\r\n\t\tif (!user) return 1;\r\n\r\n\t\tconst ips = user.connections.map(c => c.ip);\r\n\t\treturn ips.filter((ip, index) => ips.indexOf(ip) === index).length;\r\n\t}\r\n\r\n\tstatic parseHosts(hostArray: string[], room: Room, allowOffline?: boolean) {\r\n\t\tconst hosts = [];\r\n\t\tfor (const u of hostArray) {\r\n\t\t\tconst id = toID(u);\r\n\t\t\tconst user = Users.getExact(id);\r\n\t\t\tif (!allowOffline && (!user?.connected || !(user.id in room.users))) continue;\r\n\r\n\t\t\tif (!user) {\r\n\t\t\t\t// simply stick the ID's in there - don't keep any benign symbols passed by the hunt maker\r\n\t\t\t\thosts.push({name: id, id: id, noUpdate: true});\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\thosts.push({id: '' + user.id, name: '' + user.name});\r\n\t\t}\r\n\t\treturn hosts;\r\n\t}\r\n\r\n\tstatic parseQuestions(questionArray: string[]): AnyObject {\r\n\t\tif (questionArray.length % 2 === 1) return {err: \"Your final question is missing an answer\"};\r\n\t\tif (questionArray.length < 6) return {err: \"You must have at least 3 hints and answers\"};\r\n\r\n\t\tconst formattedQuestions = [];\r\n\r\n\t\tfor (let [i, question] of questionArray.entries()) {\r\n\t\t\tif (i % 2) {\r\n\t\t\t\tconst answers = question.split(';').map(p => p.trim());\r\n\t\t\t\tformattedQuestions[i] = answers;\r\n\t\t\t\tif (!answers.length || answers.some(a => !toID(a))) {\r\n\t\t\t\t\treturn {err: \"Empty answer - only alphanumeric characters will count in answers.\"};\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tquestion = question.trim();\r\n\t\t\t\tformattedQuestions[i] = question;\r\n\t\t\t\tif (!question) return {err: \"Empty question.\"};\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn {result: formattedQuestions};\r\n\t}\r\n}\r\n\r\nexport class ScavengerHuntPlayer extends Rooms.RoomGamePlayer {\r\n\tlastGuess: number;\r\n\tcompleted: boolean;\r\n\tjoinIps: string[];\r\n\tcurrentQuestion: number;\r\n\r\n\t[k: string]: any; // for purposes of adding new temporary properties for the purpose of twists.\r\n\tconstructor(user: User, game: ScavengerHunt) {\r\n\t\tsuper(user, game);\r\n\r\n\t\tthis.joinIps = user.ips.slice();\r\n\r\n\t\tthis.currentQuestion = 0;\r\n\t\tthis.completed = false;\r\n\t\tthis.lastGuess = 0;\r\n\t}\r\n\r\n\tgetCurrentQuestion() {\r\n\t\treturn {\r\n\t\t\tquestion: this.game.questions[this.currentQuestion],\r\n\t\t\tnumber: this.currentQuestion + 1,\r\n\t\t};\r\n\t}\r\n\r\n\tverifyAnswer(value: string) {\r\n\t\tconst answer = this.getCurrentQuestion().question.answer;\r\n\t\tvalue = toID(value);\r\n\r\n\t\treturn answer.some((a: string) => toID(a) === value);\r\n\t}\r\n\r\n\tonNotifyChange(num: number) {\r\n\t\tthis.game.runEvent('NotifyChange', this, num);\r\n\t\tif (num === this.currentQuestion) {\r\n\t\t\tthis.sendRoom(`|raw|The hint has been changed to: ${Chat.formatText(this.game.questions[num].hint)}`);\r\n\t\t}\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tconst user = Users.getExact(this.id);\r\n\t\tif (user) {\r\n\t\t\tuser.games.delete(this.game.roomid);\r\n\t\t\tuser.updateSearch();\r\n\t\t}\r\n\t}\r\n}\r\n\r\nconst ScavengerCommands: Chat.ChatCommands = {\r\n\t/**\r\n\t * Player commands\r\n\t */\r\n\t\"\"() {\r\n\t\treturn this.parse(\"/join scavengers\");\r\n\t},\r\n\r\n\tguess(target, room, user) {\r\n\t\treturn this.parse(`/choose ${target}`);\r\n\t},\r\n\r\n\tjoin(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(\"There is no scavenger hunt currently running.\");\r\n\t\tthis.checkChat();\r\n\r\n\t\tgame.joinGame(user);\r\n\t},\r\n\r\n\tleave(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(\"There is no scavenger hunt currently running.\");\r\n\t\tgame.leaveGame(user);\r\n\t},\r\n\r\n\t/**\r\n\t * Scavenger Games\r\n\t * --------------\r\n\t * Individual game commands for each Scavenger Game\r\n\t */\r\n\tgame: 'games',\r\n\tgames: {\r\n\t\t/**\r\n\t\t * General game commands\r\n\t\t */\r\n\t\tcreate: 'start',\r\n\t\tnew: 'start',\r\n\t\tstart(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\tif (room.scavgame) return this.errorReply('There is already a scavenger game running.');\r\n\t\t\tif (room.getGame(ScavengerHunt)) {\r\n\t\t\t\treturn this.errorReply('You cannot start a scavenger game where there is already a scavenger hunt in the room.');\r\n\t\t\t}\r\n\r\n\t\t\ttarget = toID(target);\r\n\t\t\tconst game = ScavMods.LoadGame(room, target);\r\n\r\n\t\t\tif (!game) return this.errorReply('Invalid game mode.');\r\n\r\n\t\t\troom.scavgame = game;\r\n\r\n\t\t\tthis.privateModAction(`A ${game.name} has been created by ${user.name}.`);\r\n\t\t\tthis.modlog('SCAVENGER', null, 'ended the scavenger game');\r\n\r\n\t\t\tgame.announce(`A game of ${game.name} has been started!`);\r\n\t\t},\r\n\r\n\t\tend(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\tif (!room.scavgame) return this.errorReply(`There is no scavenger game currently running.`);\r\n\r\n\t\t\tthis.privateModAction(`The ${room.scavgame.name} has been forcibly ended by ${user.name}.`);\r\n\t\t\tthis.modlog('SCAVENGER', null, 'ended the scavenger game');\r\n\t\t\troom.scavgame.announce(`The ${room.scavgame.name} has been forcibly ended.`);\r\n\t\t\troom.scavgame.destroy(true);\r\n\t\t},\r\n\r\n\t\tkick(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\tif (!room.scavgame) return this.errorReply(`There is no scavenger game currently running.`);\r\n\r\n\t\t\tconst targetId = toID(target);\r\n\t\t\tif (targetId === 'constructor' || !targetId) return this.errorReply(\"Invalid player.\");\r\n\r\n\t\t\tconst success = room.scavgame.eliminate(targetId);\r\n\t\t\tif (success) {\r\n\t\t\t\tthis.addModAction(`User '${targetId}' has been kicked from the ${room.scavgame.name}.`);\r\n\t\t\t\tthis.modlog('SCAVENGERS', target, `kicked from the ${room.scavgame.name}`);\r\n\t\t\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\t\t\tif (game) {\r\n\t\t\t\t\tgame.eliminate(targetId); // remove player from current hunt as well.\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthis.errorReply(`Unable to kick user '${targetId}'.`);\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tpoints: 'leaderboard',\r\n\t\tscore: 'leaderboard',\r\n\t\tscoreboard: 'leaderboard',\r\n\t\tasync leaderboard(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tif (!room.scavgame) return this.errorReply(`There is no scavenger game currently running.`);\r\n\t\t\tif (!room.scavgame.leaderboard) return this.errorReply(\"This scavenger game does not have a leaderboard.\");\r\n\t\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\t\tconst html = await room.scavgame.leaderboard.htmlLadder();\r\n\t\t\tthis.sendReply(`|raw|${html}`);\r\n\t\t},\r\n\r\n\t\tasync rank(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tif (!room.scavgame) return this.errorReply(`There is no scavenger game currently running.`);\r\n\t\t\tif (!room.scavgame.leaderboard) return this.errorReply(\"This scavenger game does not have a leaderboard.\");\r\n\t\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\t\tconst targetId = toID(target) || user.id;\r\n\r\n\t\t\tconst rank = await room.scavgame.leaderboard.visualize('points', targetId) as AnyObject;\r\n\r\n\t\t\tif (!rank) {\r\n\t\t\t\tthis.sendReplyBox(`User '${targetId}' does not have any points on the scavenger games leaderboard.`);\r\n\t\t\t} else {\r\n\t\t\t\tthis.sendReplyBox(Utils.html`User '${rank.name}' is #${rank.rank} on the scavenger games leaderboard with ${rank.points} points.`);\r\n\t\t\t}\r\n\t\t},\r\n\t},\r\n\tteamscavs: {\r\n\t\taddteam: 'createteam',\r\n\t\tcreateteam(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\t// if (room.getGame(ScavengerHunt)) return this.errorReply('Teams cannot be modified after the hunt starts.');\r\n\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\r\n\t\t\tlet [teamName, leader] = target.split(',');\r\n\t\t\tteamName = teamName.trim();\r\n\t\t\tif (game.teams[teamName]) return this.errorReply(`The team ${teamName} already exists.`);\r\n\r\n\t\t\tconst leaderUser = Users.get(leader);\r\n\t\t\tif (!leaderUser) return this.errorReply('The user you specified is currently not online');\r\n\t\t\tif (game.getPlayerTeam(leaderUser)) return this.errorReply('The user is already a member of another team.');\r\n\r\n\t\t\tgame.teams[teamName] = {name: teamName, answers: [], players: [leaderUser.id], question: 1, completed: false};\r\n\t\t\tgame.announce(Utils.html`A new team \"${teamName}\" has been created with ${leaderUser.name} as the leader.`);\r\n\t\t},\r\n\r\n\t\tdeleteteam: 'removeteam',\r\n\t\tremoveteam(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\t// if (room.getGame(ScavengerHunt)) return this.errorReply('Teams cannot be modified after the hunt starts.');\r\n\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\r\n\t\t\tif (!game.teams[target]) return this.errorReply(`The team ${target} does not exist.`);\r\n\r\n\t\t\tdelete game.teams[target];\r\n\t\t\tgame.announce(Utils.html`The team \"${target}\" has been removed.`);\r\n\t\t},\r\n\r\n\t\taddplayer(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\t\t\t// if (room.getGame(ScavengerHunt)) return this.errorReply('Teams cannot be modified after the hunt starts.');\r\n\r\n\t\t\tlet userTeam;\r\n\r\n\t\t\tfor (const teamID in game.teams) {\r\n\t\t\t\tconst team = game.teams[teamID];\r\n\t\t\t\tif (team.players[0] === user.id) {\r\n\t\t\t\t\tuserTeam = team;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (!userTeam) return this.errorReply('You must be the leader of a team to add people into the team.');\r\n\r\n\t\t\tconst targetUsers = target.split(',').map(id => Users.getExact(id)).filter(u => u?.connected) as User[];\r\n\t\t\tif (!targetUsers.length) return this.errorReply('Please select a user that is currently online.');\r\n\r\n\t\t\tconst errors = [];\r\n\t\t\tfor (const targetUser of targetUsers) {\r\n\t\t\t\tif (game.getPlayerTeam(targetUser)) errors.push(`${targetUser.name} is already in a team.`);\r\n\t\t\t}\r\n\t\t\tif (errors.length) return this.sendReplyBox(errors.join('
'));\r\n\r\n\t\t\tconst playerIDs = targetUsers.map(u => u.id);\r\n\t\t\tuserTeam.players.push(...playerIDs);\r\n\r\n\t\t\tfor (const targetUser of targetUsers) {\r\n\t\t\t\ttargetUser.sendTo(room, `You have joined ${userTeam.name}.`);\r\n\t\t\t}\r\n\t\t\tgame.announce(Utils.html`${Chat.toListString(targetUsers.map(u => u.name))} ${targetUsers.length > 1 ? 'have' : 'has'} been added into ${userTeam.name}.`);\r\n\t\t},\r\n\r\n\t\teditplayers(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\t\t\tthis.checkCan('mute', null, room);\r\n\t\t\t// if (room.getGame(ScavengerHunt)) return this.errorReply('Teams cannot be modified after the hunt starts.');\r\n\r\n\t\t\tconst parts = target.split(',');\r\n\t\t\tconst teamName = parts[0].trim();\r\n\t\t\tconst playerchanges = parts.slice(1);\r\n\r\n\t\t\tconst team = game.teams[teamName];\r\n\r\n\t\t\tif (!team) return this.errorReply('Invalid team.');\r\n\r\n\t\t\tfor (const entry of playerchanges) {\r\n\t\t\t\tconst userid = toID(entry);\r\n\t\t\t\tif (entry.trim().startsWith('-')) {\r\n\t\t\t\t\t// remove from the team\r\n\t\t\t\t\tif (!team.players.includes(userid)) {\r\n\t\t\t\t\t\tthis.errorReply(`User \"${userid}\" is not in team \"${team.name}.\"`);\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t} else if (team.players[0] === userid) {\r\n\t\t\t\t\t\tthis.errorReply(`You cannot remove \"${userid}\", who is the leader of \"${team.name}\".`);\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tteam.players = team.players.filter((u: string) => u !== userid);\r\n\t\t\t\t\tgame.announce(`${userid} was removed from \"${team.name}.\"`);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tconst targetUser = Users.getExact(userid);\r\n\t\t\t\t\tif (!targetUser?.connected) {\r\n\t\t\t\t\t\tthis.errorReply(`User \"${userid}\" is not currently online.`);\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tconst targetUserTeam = game.getPlayerTeam(targetUser);\r\n\t\t\t\t\tif (team.players.includes(userid)) {\r\n\t\t\t\t\t\tthis.errorReply(`User \"${userid}\" is already part of \"${team.name}.\"`);\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t} else if (targetUserTeam) {\r\n\t\t\t\t\t\tthis.errorReply(`User \"${userid}\" is already part of another team - \"${targetUserTeam.name}\".`);\r\n\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tteam.players.push(userid);\r\n\t\t\t\t\tgame.announce(`${targetUser.name} was added to \"${team.name}.\"`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tteams(target, room, user) {\r\n\t\t\tif (!this.runBroadcast()) return false;\r\n\t\t\troom = this.requireRoom();\r\n\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\r\n\t\t\tconst display = [];\r\n\t\t\tfor (const teamID in game.teams) {\r\n\t\t\t\tconst team = game.teams[teamID];\r\n\t\t\t\tdisplay.push(Utils.html`${team.name} - ${team.players[0]}${team.players.length > 1 ? ', ' + team.players.slice(1).join(', ') : ''}`);\r\n\t\t\t}\r\n\r\n\t\t\tthis.sendReplyBox(display.join('
'));\r\n\t\t},\r\n\r\n\t\tguesses(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\r\n\t\t\tconst team = game.getPlayerTeam(user);\r\n\t\t\tif (!team) return this.errorReply('You are not currently part of this Team Scavs game.');\r\n\r\n\t\t\tthis.sendReplyBox(Utils.html`Question #${team.question} guesses: ${team.answers.sort().join(', ')}`);\r\n\t\t},\r\n\r\n\t\tchat: 'note',\r\n\t\tnote(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tconst game = room.scavgame;\r\n\t\t\tif (!game || game.id !== 'teamscavs') return this.errorReply('There is currently no game of Team Scavs going on.');\r\n\r\n\t\t\tconst team = game.getPlayerTeam(user);\r\n\t\t\tif (!team) return this.errorReply('You are not currently part of this Team Scavs game.');\r\n\r\n\t\t\tif (!target) return this.errorReply('Please include a message as the note.');\r\n\r\n\t\t\tgame.teamAnnounce(user, Utils.html` Note from ${user.name}: ${target}`);\r\n\t\t},\r\n\t},\r\n\tteamscavshelp: [\r\n\t\t'/tscav createteam [team name], [leader name] - creates a new team for the current Team Scavs game. (Requires: % @ * # &)',\r\n\t\t'/tscav deleteteam [team name] - deletes an existing team for the current Team Scavs game. (Requires: % @ * # &)',\r\n\t\t'/tscav addplayer [user] - allows a team leader to add a player onto their team.',\r\n\t\t'/tscav editplayers [team name], [added user | -removed user], [...] (use - preceding a user\\'s name to remove a user) - Edits the players within an existing team. (Requires: % @ * # &)',\r\n\t\t'/tscav teams - views the list of teams and the players on each team.',\r\n\t\t'/tscav guesses - views the list of guesses already submitted by your team for the current question.',\r\n\t\t'/tscav chat [message] - adds a message that can be seen by all of your teammates in the Team Scavs game.',\r\n\t],\r\n\r\n\t/**\r\n\t * Creation / Moderation commands\r\n\t */\r\n\tcreatetwist: 'create',\r\n\tcreatetwistofficial: 'create',\r\n\tcreatetwistmini: 'create',\r\n\tcreatetwistpractice: 'create',\r\n\tcreatetwistunrated: 'create',\r\n\tcreatepractice: 'create',\r\n\tcreateofficial: 'create',\r\n\tcreateunrated: 'create',\r\n\tcreatemini: 'create',\r\n\tforcecreate: 'create',\r\n\tforcecreateunrated: 'create',\r\n\tcreaterecycled: 'create',\r\n\tcreate(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"Scavenger hunts can only be created in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tif (room.game) return this.errorReply(`There is already a game in this room - ${room.game.title}.`);\r\n\t\tlet gameType = 'regular' as GameTypes;\r\n\t\tif (cmd.includes('practice')) {\r\n\t\t\tgameType = 'practice';\r\n\t\t} else if (cmd.includes('official')) {\r\n\t\t\tgameType = 'official';\r\n\t\t} else if (cmd.includes('mini')) {\r\n\t\t\tgameType = 'mini';\r\n\t\t} else if (cmd.includes('unrated')) {\r\n\t\t\tgameType = 'unrated';\r\n\t\t} else if (cmd.includes('recycled')) {\r\n\t\t\tgameType = 'recycled';\r\n\t\t}\r\n\r\n\t\tlet mod;\r\n\t\tlet questions = target;\r\n\r\n\t\tif (cmd.includes('twist')) {\r\n\t\t\tconst twistparts = target.split('|');\r\n\t\t\tquestions = twistparts.slice(1).join('|');\r\n\t\t\tmod = twistparts[0].split(',');\r\n\t\t}\r\n\r\n\t\t// mini and officials can be started anytime\r\n\t\tif (\r\n\t\t\t!cmd.includes('force') && ['regular', 'unrated', 'recycled'].includes(gameType) && !mod &&\r\n\t\t\troom.settings.scavQueue && room.settings.scavQueue.length && !room.scavgame\r\n\t\t) {\r\n\t\t\treturn this.errorReply(`There are currently hunts in the queue! If you would like to start the hunt anyways, use /forcestart${gameType === 'regular' ? 'hunt' : gameType}.`);\r\n\t\t}\r\n\r\n\t\tif (gameType === 'recycled') {\r\n\t\t\tif (ScavengerHuntDatabase.isEmpty()) {\r\n\t\t\t\treturn this.errorReply(\"There are no hunts in the database.\");\r\n\t\t\t}\r\n\r\n\t\t\tlet hunt;\r\n\t\t\tif (questions) {\r\n\t\t\t\tconst huntNumber = parseInt(questions);\r\n\t\t\t\tif (!ScavengerHuntDatabase.hasHunt(huntNumber)) return this.errorReply(\"You specified an invalid hunt number.\");\r\n\t\t\t\thunt = scavengersData.recycledHunts[huntNumber - 1];\r\n\t\t\t} else {\r\n\t\t\t\thunt = ScavengerHuntDatabase.getRecycledHuntFromDatabase();\r\n\t\t\t}\r\n\r\n\t\t\tquestions = ScavengerHuntDatabase.getFullTextOfHunt(hunt);\r\n\t\t}\r\n\r\n\t\tlet [hostsArray, ...params] = questions.split('|');\r\n\t\t// A recycled hunt should list both its original creator and the staff who started it as its host.\r\n\t\tif (gameType === 'recycled') {\r\n\t\t\thostsArray += `,${user.name}`;\r\n\t\t}\r\n\t\tconst hosts = ScavengerHunt.parseHosts(\r\n\t\t\thostsArray.split(/[,;]/),\r\n\t\t\troom,\r\n\t\t\tgameType === 'official' || gameType === 'recycled'\r\n\t\t);\r\n\t\tif (!hosts.length) {\r\n\t\t\treturn this.errorReply(\"The user(s) you specified as the host is not online, or is not in the room.\");\r\n\t\t}\r\n\r\n\t\tconst res = ScavengerHunt.parseQuestions(params);\r\n\t\tif (res.err) return this.errorReply(res.err);\r\n\r\n\t\troom.game = new ScavengerHunt(room, user, hosts, gameType, res.result, mod);\r\n\r\n\t\tthis.privateModAction(`A new scavenger hunt was created by ${user.name}.`);\r\n\t\tthis.modlog('SCAV NEW', null, `${gameType.toUpperCase()}: creators - ${hosts.map(h => h.id)}`);\r\n\t},\r\n\r\n\tstatus(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tconst elapsedMsg = Chat.toDurationString(Date.now() - game.startTime, {hhmmss: true});\r\n\t\tconst gameTypeMsg = game.gameType ? `${game.gameType} ` : '';\r\n\t\tconst hostersMsg = Utils.escapeHTML(Chat.toListString(game.hosts.map(h => h.name)));\r\n\t\tconst hostMsg = game.hosts.some(h => h.id === game.staffHostId) ?\r\n\t\t\t'' : Utils.html` (started by - ${game.staffHostName})`;\r\n\t\tconst finishers = Utils.html`${game.completed.map(u => u.name).join(', ')}`;\r\n\t\tlet buffer = `
The current ${gameTypeMsg}scavenger hunt by ${hostersMsg}${hostMsg} has been up for: ${elapsedMsg}
${!game.timerEnd ? 'The timer is currently off.' : `The hunt ends in: ${Chat.toDurationString(game.timerEnd - Date.now(), {hhmmss: true})}`}
Completed (${game.completed.length}): ${finishers}
`;\r\n\t\tif (game.modsList.includes('timetrial')) {\r\n\t\t\tconst finisher = game.completed.find(player => player.id === user.id);\r\n\t\t\tconst timeTrialMsg = finisher ?\r\n\t\t\t\t`You finished the hunt in: ${finisher.time}.` :\r\n\t\t\t\t(game.startTimes?.[user.id] ?\r\n\t\t\t\t\t`You joined the hunt ${Chat.toDurationString(Date.now() - game.startTimes[user.id], {hhmmss: true})} ago.` :\r\n\t\t\t\t\t'You have not joined the hunt.');\r\n\t\t\tbuffer = `
The current ${gameTypeMsg}scavenger hunt by ${hostersMsg}${hostMsg} has been up for: ${elapsedMsg}
${timeTrialMsg}
${!game.timerEnd ? 'The timer is currently off.' : `The hunt ends in: ${Chat.toDurationString(game.timerEnd - Date.now(), {hhmmss: true})}`}
Completed (${game.completed.length}): ${finishers}
`;\r\n\t\t}\r\n\r\n\t\tif (game.hosts.some(h => h.id === user.id) || game.staffHostId === user.id) {\r\n\t\t\tlet str = `
`;\r\n\t\t\tfor (let i = 0; i < game.questions.length; i++) {\r\n\t\t\t\tconst questionNum = i + 1;\r\n\t\t\t\tconst players = Object.values(game.playerTable).filter(player => player.currentQuestion === i && !player.completed);\r\n\t\t\t\tif (!players.length) {\r\n\t\t\t\t\tstr += ``;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tstr += `
QuestionUsers on this Question
${questionNum}None
${questionNum}`;\r\n\t\t\t\t\tstr += players.map(\r\n\t\t\t\t\t\tpl => pl.lastGuess > Date.now() - 1000 * 300 ?\r\n\t\t\t\t\t\t\tUtils.html`${pl.name}` :\r\n\t\t\t\t\t\t\tUtils.escapeHTML(pl.name)\r\n\t\t\t\t\t).join(\", \");\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tconst completed: AnyObject[] = game.preCompleted ? game.preCompleted : game.completed;\r\n\t\t\tstr += Utils.html`
Completed${completed.length ? completed.map(pl => pl.name).join(\", \") : 'None'}`;\r\n\t\t\treturn this.sendReply(`|raw|${str}
${buffer}`);\r\n\t\t}\r\n\t\tthis.sendReply(`|raw|${buffer}`);\r\n\t},\r\n\r\n\thint(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\t\tif (!game.onSendQuestion(user, true)) this.errorReply(\"You are not currently participating in the hunt.\");\r\n\t},\r\n\r\n\ttimer(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tconst minutes = (toID(target) === 'off' ? 0 : parseFloat(target));\r\n\t\tif (isNaN(minutes) || minutes < 0 || (minutes * 60 * 1000) > Chat.MAX_TIMEOUT_DURATION) {\r\n\t\t\tthrow new Chat.ErrorMessage(`You must specify a timer length that is a postive number.`);\r\n\t\t}\r\n\r\n\t\tconst result = game.setTimer(minutes);\r\n\t\tconst message = `The scavenger timer has been ${(result === 'off' ? \"turned off\" : `set to ${result} minutes`)}`;\r\n\r\n\t\troom.add(message + '.');\r\n\t\tthis.privateModAction(`${message} by ${user.name}.`);\r\n\t\tthis.modlog('SCAV TIMER', null, (result === 'off' ? 'OFF' : `${result} minutes`));\r\n\t},\r\n\r\n\tinherit(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tif (game.staffHostId === user.id) return this.errorReply('You already have staff permissions for this hunt.');\r\n\r\n\t\tgame.staffHostId = '' + user.id;\r\n\t\tgame.staffHostName = '' + user.name;\r\n\r\n\t\t// clear user's game progress and prevent user from ever entering again\r\n\t\tgame.eliminate(user.id);\r\n\t\tgame.cacheUserIps(user);\r\n\r\n\t\tthis.privateModAction(`${user.name} has inherited staff permissions for the current hunt.`);\r\n\t\tthis.modlog('SCAV INHERIT');\r\n\t},\r\n\r\n\treset(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tgame.onEnd(true, user);\r\n\t\tthis.privateModAction(`${user.name} has reset the scavenger hunt.`);\r\n\t\tthis.modlog('SCAV RESET');\r\n\t},\r\n\r\n\tresettoqueue(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tconst hunt: QueuedHunt = {\r\n\t\t\thosts: game.hosts,\r\n\t\t\tquestions: [],\r\n\t\t\tstaffHostId: game.staffHostId,\r\n\t\t\tstaffHostName: game.StaffHostName,\r\n\t\t\tgameType: game.gameType,\r\n\t\t};\r\n\t\tfor (const entry of game.questions) {\r\n\t\t\thunt.questions.push(...[entry.hint, entry.answer]);\r\n\t\t}\r\n\t\tif (!room.settings.scavQueue) room.settings.scavQueue = [];\r\n\t\troom.settings.scavQueue.push(hunt);\r\n\r\n\t\tgame.onEnd(true, user);\r\n\t\tthis.privateModAction(`${user.name} has reset the scavenger hunt, and placed it in the queue.`);\r\n\t\tthis.modlog('SCAV RESETTOQUEUE');\r\n\t},\r\n\r\n\tforceend: 'end',\r\n\tend(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tif (!room.game && room.scavgame) return this.parse('/scav games end');\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tconst completed = game.preCompleted ? game.preCompleted : game.completed;\r\n\r\n\t\tif (!this.cmd.includes('force')) {\r\n\t\t\tif (!completed.length) {\r\n\t\t\t\treturn this.errorReply('No one has finished the hunt yet. Use /forceendhunt if you want to end the hunt and reveal the answers.');\r\n\t\t\t}\r\n\t\t} else if (completed.length) {\r\n\t\t\treturn this.errorReply(`This hunt has ${Chat.count(completed, \"finishers\")}; use /endhunt`);\r\n\t\t}\r\n\r\n\t\tgame.onEnd(false, user);\r\n\t\tthis.privateModAction(`${user.name} has ended the scavenger hunt.`);\r\n\t\tthis.modlog('SCAV END');\r\n\t},\r\n\r\n\tviewhunt(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tif (!('onViewHunt' in game)) return this.errorReply('There is currently no hunt to be viewed.');\r\n\r\n\t\tgame.onViewHunt(user);\r\n\t},\r\n\r\n\tedithunt(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\t\tif (\r\n\t\t\t(!game.hosts.some(h => h.id === user.id) || !user.can('show', null, room)) &&\r\n\t\t\tgame.staffHostId !== user.id\r\n\t\t) {\r\n\t\t\treturn this.errorReply(\"You cannot edit the hints and answers if you are not the host.\");\r\n\t\t}\r\n\r\n\t\tconst [question, type, ...value] = target.split(',');\r\n\t\tif (!game.onEditQuestion(parseInt(question), toID(type), value.join(',').trim())) {\r\n\t\t\treturn this.sendReply(\"/scavengers edithunt [question number], [hint | answer], [value] - edits the current scavenger hunt.\");\r\n\t\t}\r\n\t},\r\n\r\n\taddhint: 'spoiler',\r\n\tspoiler(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\t\tif (\r\n\t\t\t(!game.hosts.some(h => h.id === user.id) || !user.can('show', null, room)) &&\r\n\t\t\tgame.staffHostId !== user.id\r\n\t\t) {\r\n\t\t\treturn this.errorReply(\"You cannot add more hints if you are not the host.\");\r\n\t\t}\r\n\t\tconst parts = target.split(',');\r\n\t\tconst question = parseInt(parts[0]) - 1;\r\n\t\tconst hint = parts.slice(1).join(',');\r\n\r\n\t\tif (!game.questions[question]) return this.errorReply(`Invalid question number.`);\r\n\t\tif (!hint) return this.errorReply('The hint cannot be left empty.');\r\n\t\tgame.questions[question].spoilers.push(hint);\r\n\r\n\t\troom.addByUser(user, `Question #${question + 1} hint - spoiler: ${hint}`);\r\n\t\tconst playersOnQ = game.players.filter(player => player.currentQuestion === question && !player.completed);\r\n\t\tconst notif = `|notify|Scavenger hint for Q${question + 1}`;\r\n\t\tfor (const player of playersOnQ) {\r\n\t\t\tconst playerObj = Users.get(player.id);\r\n\t\t\tif (!playerObj?.connected) continue;\r\n\t\t\troom.sendUser(playerObj, notif);\r\n\t\t}\r\n\t},\r\n\r\n\tdeletehint: 'removehint',\r\n\tremovehint(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\t\tif (\r\n\t\t\t(!game.hosts.some(h => h.id === user.id) || !user.can('show', null, room)) &&\r\n\t\t\tgame.staffHostId !== user.id\r\n\t\t) {\r\n\t\t\treturn this.errorReply(\"You cannot remove hints if you are not the host.\");\r\n\t\t}\r\n\r\n\t\tconst parts = target.split(',');\r\n\t\tconst question = parseInt(parts[0]) - 1;\r\n\t\tconst hint = parseInt(parts[1]) - 1;\r\n\r\n\r\n\t\tif (!game.questions[question]) return this.errorReply(`Invalid question number.`);\r\n\t\tif (!game.questions[question].spoilers[hint]) return this.errorReply('Invalid hint number.');\r\n\t\tgame.questions[question].spoilers.splice(hint, 1);\r\n\r\n\t\treturn this.sendReply(\"Hint has been removed.\");\r\n\t},\r\n\r\n\tmodifyhint: 'edithint',\r\n\tedithint(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\t\tif (\r\n\t\t\t(!game.hosts.some(h => h.id === user.id) || !user.can('show', null, room)) &&\r\n\t\t\tgame.staffHostId !== user.id\r\n\t\t) {\r\n\t\t\treturn this.errorReply(\"You cannot edit hints if you are not the host.\");\r\n\t\t}\r\n\r\n\t\tconst parts = target.split(',');\r\n\t\tconst question = parseInt(parts[0]) - 1;\r\n\t\tconst hint = parseInt(parts[1]) - 1;\r\n\t\tconst value = parts.slice(2).join(',');\r\n\r\n\t\tif (!game.questions[question]) return this.errorReply(`Invalid question number.`);\r\n\t\tif (!game.questions[question].spoilers[hint]) return this.errorReply('Invalid hint number.');\r\n\t\tif (!value) return this.errorReply('The hint cannot be left empty.');\r\n\t\tgame.questions[question].spoilers[hint] = value;\r\n\r\n\t\troom.addByUser(user, `Question #${question + 1} hint - spoiler: ${value}`);\r\n\t\tconst playersOnQ = game.players.filter(player => player.currentQuestion === question && !player.completed);\r\n\t\tconst notif = `|notify|Scavenger hint for Q${question + 1}`;\r\n\t\tfor (const player of playersOnQ) {\r\n\t\t\tconst playerObj = Users.get(player.id);\r\n\t\t\tif (!playerObj?.connected) continue;\r\n\t\t\troom.sendUser(playerObj, notif);\r\n\t\t}\r\n\t\treturn this.sendReply(\"Hint has been modified.\");\r\n\t},\r\n\r\n\tkick(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst game = room.getGame(ScavengerHunt);\r\n\t\tif (!game) return this.errorReply(`There is no scavenger hunt currently running.`);\r\n\r\n\t\tconst targetId = toID(target);\r\n\t\tif (targetId === 'constructor' || !targetId) return this.errorReply(\"Invalid player.\");\r\n\r\n\t\tconst success = game.eliminate(targetId);\r\n\t\tif (success) {\r\n\t\t\tthis.modlog('SCAV KICK', targetId);\r\n\t\t\treturn this.privateModAction(`${user.name} has kicked '${targetId}' from the scavenger hunt.`);\r\n\t\t}\r\n\t\tthis.errorReply(`Unable to kick '${targetId}' from the scavenger hunt.`);\r\n\t},\r\n\r\n\t/**\r\n\t * Hunt queuing\r\n\t */\r\n\tqueueunrated: 'queue',\r\n\tqueuerated: 'queue',\r\n\tqueuerecycled: 'queue',\r\n\tqueue(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tif (!target && this.cmd !== 'queuerecycled') {\r\n\t\t\tif (this.cmd === 'queue') {\r\n\t\t\t\tthis.runBroadcast();\r\n\t\t\t\tconst commandHandler = ScavengerCommands.viewqueue as ChatHandler;\r\n\t\t\t\tcommandHandler.call(this, target, room, user, this.connection, this.cmd, this.message);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\treturn this.parse('/scavhelp staff');\r\n\t\t}\r\n\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tif (this.cmd === 'queuerecycled') {\r\n\t\t\tif (ScavengerHuntDatabase.isEmpty()) {\r\n\t\t\t\treturn this.errorReply(`There are no hunts in the database.`);\r\n\t\t\t}\r\n\t\t\tif (!room.settings.scavQueue) {\r\n\t\t\t\troom.settings.scavQueue = [];\r\n\t\t\t}\r\n\r\n\t\t\tlet next;\r\n\t\t\tif (target) {\r\n\t\t\t\tconst huntNumber = parseInt(target);\r\n\t\t\t\tif (!ScavengerHuntDatabase.hasHunt(huntNumber)) return this.errorReply(\"You specified an invalid hunt number.\");\r\n\t\t\t\tnext = scavengersData.recycledHunts[huntNumber - 1];\r\n\t\t\t} else {\r\n\t\t\t\tnext = ScavengerHuntDatabase.getRecycledHuntFromDatabase();\r\n\t\t\t}\r\n\t\t\tconst correctlyFormattedQuestions = next.questions.flatMap((question: AnyObject) => [question.text, question.answers]);\r\n\t\t\troom.settings.scavQueue.push({\r\n\t\t\t\thosts: next.hosts,\r\n\t\t\t\tquestions: correctlyFormattedQuestions,\r\n\t\t\t\tstaffHostId: 'scavengermanager',\r\n\t\t\t\tstaffHostName: 'Scavenger Manager',\r\n\t\t\t\tgameType: 'unrated',\r\n\t\t\t});\r\n\t\t} else {\r\n\t\t\tconst [hostsArray, ...params] = target.split('|');\r\n\t\t\tconst hosts = ScavengerHunt.parseHosts(hostsArray.split(/[,;]/), room);\r\n\t\t\tif (!hosts.length) {\r\n\t\t\t\treturn this.errorReply(\"The user(s) you specified as the host is not online, or is not in the room.\");\r\n\t\t\t}\r\n\r\n\t\t\tconst results = ScavengerHunt.parseQuestions(params);\r\n\t\t\tif (results.err) return this.errorReply(results.err);\r\n\r\n\t\t\tif (!room.settings.scavQueue) room.settings.scavQueue = [];\r\n\r\n\t\t\troom.settings.scavQueue.push({\r\n\t\t\t\thosts: hosts,\r\n\t\t\t\tquestions: results.result,\r\n\t\t\t\tstaffHostId: user.id,\r\n\t\t\t\tstaffHostName: user.name,\r\n\t\t\t\tgameType: (this.cmd.includes('unrated') ? 'unrated' : 'regular'),\r\n\t\t\t});\r\n\t\t}\r\n\t\tthis.privateModAction(`${user.name} has added a scavenger hunt to the queue.`);\r\n\r\n\t\troom.saveSettings();\r\n\t},\r\n\r\n\tdequeue(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tconst id = parseInt(target);\r\n\r\n\t\t// this command should be using the display to manage anyways, so no error message is needed\r\n\t\tif (!room.settings.scavQueue || isNaN(id) || id < 0 || id >= room.settings.scavQueue.length) return false;\r\n\r\n\t\tconst removed = room.settings.scavQueue.splice(id, 1)[0];\r\n\t\tthis.privateModAction(`${user.name} has removed a scavenger hunt created by [${removed.hosts.map(u => u.id).join(\", \")}] from the queue.`);\r\n\t\tthis.sendReply(`|uhtmlchange|scav-queue|${formatQueue(room.settings.scavQueue, user, room)}`);\r\n\r\n\t\troom.saveSettings();\r\n\t},\r\n\r\n\tviewqueue(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\tthis.sendReply(`|uhtml|scav-queue|${formatQueue(room.settings.scavQueue, user, room, this.broadcasting)}`);\r\n\t},\r\n\r\n\tnext(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tif (!room.settings.scavQueue?.length) {\r\n\t\t\treturn this.errorReply(\"The scavenger hunt queue is currently empty.\");\r\n\t\t}\r\n\t\tif (room.game) return this.errorReply(`There is already a game in this room - ${room.game.title}.`);\r\n\r\n\t\tconst huntId = parseInt(target) || 0;\r\n\r\n\t\tif (!room.settings.scavQueue[huntId]) return false; // no need for an error reply - this is done via UI anyways\r\n\r\n\t\tconst next = room.settings.scavQueue.splice(huntId, 1)[0];\r\n\t\troom.game = new ScavengerHunt(\r\n\t\t\troom,\r\n\t\t\t{id: next.staffHostId, name: next.staffHostName},\r\n\t\t\tnext.hosts,\r\n\t\t\tnext.gameType,\r\n\t\t\tnext.questions\r\n\t\t);\r\n\r\n\t\tif (huntId) this.sendReply(`|uhtmlchange|scav-queue|${formatQueue(room.settings.scavQueue, user, room)}`);\r\n\t\tthis.modlog('SCAV NEW', null, `from queue: creators - ${next.hosts.map(h => h.id)}`);\r\n\r\n\t\t// update the saved queue.\r\n\t\troom.saveSettings();\r\n\t},\r\n\r\n\tenablequeue: 'disablequeue',\r\n\tdisablequeue(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\r\n\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\tconst state = this.cmd === 'disablequeue';\r\n\t\tif ((room.settings.scavSettings.scavQueueDisabled || false) === state) {\r\n\t\t\treturn this.errorReply(`The queue is already ${state ? 'disabled' : 'enabled'}.`);\r\n\t\t}\r\n\r\n\t\troom.settings.scavSettings.scavQueueDisabled = state;\r\n\t\troom.saveSettings();\r\n\r\n\t\tthis.sendReply(`|uhtmlchange|scav-queue|${formatQueue(room.settings.scavQueue, user, room)}`);\r\n\t\tthis.privateModAction(`The queue has been ${state ? 'disabled' : 'enabled'} by ${user.name}.`);\r\n\t\tthis.modlog('SCAV QUEUE', null, (state ? 'disabled' : 'enabled'));\r\n\t},\r\n\r\n\tdefaulttimer(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('declare', null, room);\r\n\r\n\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\tif (!target) {\r\n\t\t\tconst duration_string = room.settings.scavSettings.defaultScavTimer || DEFAULT_TIMER_DURATION;\r\n\t\t\treturn this.sendReply(`The default scavenger timer is currently set at: ${duration_string} minutes.`);\r\n\t\t}\r\n\t\tconst duration = parseInt(target);\r\n\r\n\t\tif (!duration || duration < 0) {\r\n\t\t\treturn this.errorReply('The default timer must be an integer greater than zero, in minutes.');\r\n\t\t}\r\n\r\n\t\troom.settings.scavSettings.defaultScavTimer = duration;\r\n\t\troom.saveSettings();\r\n\t\tthis.privateModAction(`The default scavenger timer has been set to ${duration} minutes by ${user.name}.`);\r\n\t\tthis.modlog('SCAV DEFAULT TIMER', null, `${duration} minutes`);\r\n\t},\r\n\r\n\t/**\r\n\t * Leaderboard Commands\r\n\t */\r\n\taddpoints(target, room, user) {\r\n\t\troom = this.requireRoom('scavengers' as RoomID);\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tconst parts = target.split(',');\r\n\t\tconst targetId = toID(parts[0]);\r\n\t\tconst points = parseInt(parts[1]);\r\n\r\n\t\tif (!targetId || targetId === 'constructor' || targetId.length > 18) return this.errorReply(\"Invalid username.\");\r\n\t\tif (!points || points < 0 || points > 1000) return this.errorReply(\"Points must be an integer between 1 and 1000.\");\r\n\r\n\t\tLeaderboard.addPoints(targetId, 'points', points, true).write();\r\n\r\n\t\tthis.privateModAction(`${targetId} was given ${points} points on the current scavengers ladder by ${user.name}.`);\r\n\t\tthis.modlog('SCAV ADDPOINTS', targetId, '' + points);\r\n\t},\r\n\r\n\tremovepoints(target, room, user) {\r\n\t\troom = this.requireRoom('scavengers' as RoomID);\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tconst parts = target.split(',');\r\n\t\tconst targetId = toID(parts[0]);\r\n\t\tconst points = parseInt(parts[1]);\r\n\r\n\t\tif (!targetId || targetId === 'constructor' || targetId.length > 18) return this.errorReply(\"Invalid username.\");\r\n\t\tif (!points || points < 0 || points > 1000) return this.errorReply(\"Points must be an integer between 1 and 1000.\");\r\n\r\n\t\tLeaderboard.addPoints(targetId, 'points', -points, true).write();\r\n\r\n\t\tthis.privateModAction(`${user.name} has taken ${points} points from ${targetId} on the current scavengers ladder.`);\r\n\t\tthis.modlog('SCAV REMOVEPOINTS', targetId, '' + points);\r\n\t},\r\n\r\n\tresetladder(target, room, user) {\r\n\t\troom = this.requireRoom('scavengers' as RoomID);\r\n\t\tthis.checkCan('declare', null, room);\r\n\r\n\t\tLeaderboard.reset().write();\r\n\r\n\t\tthis.privateModAction(`${user.name} has reset the current scavengers ladder.`);\r\n\t\tthis.modlog('SCAV RESETLADDER');\r\n\t},\r\n\ttop: 'ladder',\r\n\tasync ladder(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\tconst isChange = (!this.broadcasting && target);\r\n\t\tconst hideStaff = (!this.broadcasting && this.meansNo(target));\r\n\r\n\t\tconst ladder = await Leaderboard.visualize('points') as AnyObject[];\r\n\t\tthis.sendReply(\r\n\t\t\t`|uhtml${isChange ? 'change' : ''}|scavladder|
${ladder.map(entry => {\r\n\t\t\t\tconst roomRank = room!.auth.getDirect(toID(entry.name));\r\n\t\t\t\tconst isStaff = Users.Auth.atLeast(roomRank, '+');\r\n\t\t\t\tif (isStaff && hideStaff) return '';\r\n\t\t\t\treturn ``;\r\n\t\t\t}).join('')}
RankNamePoints
${entry.rank}${(isStaff ? `${Utils.escapeHTML(entry.name)}` : (entry.rank <= 5 ? `${Utils.escapeHTML(entry.name)}` : Utils.escapeHTML(entry.name)))}${entry.points}
` +\r\n\t\t\t`
`\r\n\t\t);\r\n\t},\r\n\r\n\tasync rank(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\tconst targetId = toID(target) || user.id;\r\n\r\n\t\tconst rank = await Leaderboard.visualize('points', targetId) as AnyObject;\r\n\t\tif (!rank) {\r\n\t\t\tthis.sendReplyBox(`User '${targetId}' does not have any points on the scavengers leaderboard.`);\r\n\t\t} else {\r\n\t\t\tthis.sendReplyBox(Utils.html`User '${rank.name}' is #${rank.rank} on the scavengers leaderboard with ${rank.points} points.`);\r\n\t\t}\r\n\t},\r\n\r\n\t/**\r\n\t * Leaderboard Point Distribution Editing\r\n\t */\r\n\tsetblitz(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst scavsRoom = getScavsRoom(room);\r\n\t\tif (!scavsRoom) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room); // perms for viewing only\r\n\r\n\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\tif (!target) {\r\n\t\t\tconst points = [];\r\n\t\t\tconst source = Object.entries(Object.assign(DEFAULT_BLITZ_POINTS, room.settings.scavSettings.blitzPoints || {}));\r\n\t\t\tfor (const entry of source) {\r\n\t\t\t\tpoints.push(`${entry[0]}: ${entry[1]}`);\r\n\t\t\t}\r\n\t\t\treturn this.sendReplyBox(`The points rewarded for winning hunts within a minute is:
${points.join('
')}`);\r\n\t\t}\r\n\r\n\t\tthis.checkCan('declare', null, room); // perms for editing\r\n\r\n\t\tconst parts = target.split(',');\r\n\t\tconst blitzPoints = parseInt(parts[1]);\r\n\t\tconst gameType = toID(parts[0]) as GameTypes;\r\n\t\tif (!RATED_TYPES.includes(gameType)) return this.errorReply(`You cannot set blitz points for ${gameType} hunts.`);\r\n\r\n\t\tif (isNaN(blitzPoints) || blitzPoints < 0 || blitzPoints > 1000) {\r\n\t\t\treturn this.errorReply(\"The points value awarded for blitz must be an integer bewteen 0 and 1000.\");\r\n\t\t}\r\n\t\tif (!room.settings.scavSettings.blitzPoints) room.settings.scavSettings.blitzPoints = {};\r\n\t\troom.settings.scavSettings.blitzPoints[gameType] = blitzPoints;\r\n\r\n\t\troom.saveSettings();\r\n\t\tthis.privateModAction(`${user.name} has set the points awarded for blitz for ${gameType} hunts to ${blitzPoints}.`);\r\n\t\tthis.modlog('SCAV BLITZ', null, `${gameType}: ${blitzPoints}`);\r\n\r\n\t\t// double modnote in scavs room if it is a subroomgroupchat\r\n\t\tif (room.parent && !room.persist && scavsRoom) {\r\n\t\t\tscavsRoom.modlog({\r\n\t\t\t\taction: 'SCAV BLITZ',\r\n\t\t\t\tloggedBy: user.id,\r\n\t\t\t\tnote: `${gameType}: ${blitzPoints}`,\r\n\t\t\t});\r\n\t\t\tscavsRoom.sendMods(`(${user.name} has set the points awarded for blitz for ${gameType} hunts to ${blitzPoints} in <<${room.roomid}>>.)`);\r\n\t\t\tscavsRoom.roomlog(`(${user.name} has set the points awarded for blitz for ${gameType} hunts to ${blitzPoints} in <<${room.roomid}>>.)`);\r\n\t\t}\r\n\t},\r\n\r\n\tsethostpoints(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst scavsRoom = getScavsRoom(room);\r\n\t\tif (!scavsRoom) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room); // perms for viewing only\r\n\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\tif (!target) {\r\n\t\t\tconst pointSetting = Object.hasOwnProperty.call(room.settings.scavSettings, 'hostPoints') ?\r\n\t\t\t\troom.settings.scavSettings.hostPoints : DEFAULT_HOST_POINTS;\r\n\t\t\treturn this.sendReply(`The points rewarded for hosting a regular hunt is ${pointSetting}.`);\r\n\t\t}\r\n\r\n\t\tthis.checkCan('declare', null, room); // perms for editting\r\n\t\tconst points = parseInt(target);\r\n\t\tif (isNaN(points)) return this.errorReply(`${target} is not a valid number of points.`);\r\n\r\n\t\troom.settings.scavSettings.hostPoints = points;\r\n\t\troom.saveSettings();\r\n\t\tthis.privateModAction(`${user.name} has set the points awarded for hosting regular scavenger hunts to ${points}`);\r\n\t\tthis.modlog('SCAV SETHOSTPOINTS', null, `${points}`);\r\n\r\n\t\t// double modnote in scavs room if it is a subroomgroupchat\r\n\t\tif (room.parent && !room.persist) {\r\n\t\t\tscavsRoom.modlog({\r\n\t\t\t\taction: 'SCAV SETHOSTPOINTS',\r\n\t\t\t\tloggedBy: user.id,\r\n\t\t\t\tnote: `${points} [room: ${room.roomid}]`,\r\n\t\t\t});\r\n\t\t\tscavsRoom.sendMods(`(${user.name} has set the points awarded for hosting regular scavenger hunts to - ${points} in <<${room.roomid}>>)`);\r\n\t\t\tscavsRoom.roomlog(`(${user.name} has set the points awarded for hosting regular scavenger hunts to - ${points} in <<${room.roomid}>>)`);\r\n\t\t}\r\n\t},\r\n\tsetpoints(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst scavsRoom = getScavsRoom(room);\r\n\t\tif (!scavsRoom) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room); // perms for viewing only\r\n\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\tif (!target) {\r\n\t\t\tconst points = [];\r\n\t\t\tconst source = Object.entries({\r\n\t\t\t\t...DEFAULT_POINTS,\r\n\t\t\t\t...(room.settings.scavSettings.winPoints as typeof DEFAULT_POINTS || {}),\r\n\t\t\t});\r\n\r\n\t\t\tfor (const entry of source) {\r\n\t\t\t\tpoints.push(`${entry[0]}: ${entry[1].map((p: number, i: number) => `(${(i + 1)}) ${p}`).join(', ')}`);\r\n\t\t\t}\r\n\t\t\treturn this.sendReplyBox(`The points rewarded for winning hunts is:
${points.join('
')}`);\r\n\t\t}\r\n\r\n\t\tthis.checkCan('declare', null, room); // perms for editting\r\n\r\n\t\tlet [type, ...pointsSet] = target.split(',');\r\n\t\ttype = toID(type) as GameTypes;\r\n\t\tif (!RATED_TYPES.includes(type)) return this.errorReply(`You cannot set win points for ${type} hunts.`);\r\n\t\tconst winPoints = pointsSet.map(p => parseInt(p));\r\n\r\n\t\tif (winPoints.some(p => isNaN(p) || p < 0 || p > 1000) || !winPoints.length) {\r\n\t\t\treturn this.errorReply(\"The points value awarded for winning a scavenger hunt must be an integer between 0 and 1000.\");\r\n\t\t}\r\n\r\n\t\tif (!room.settings.scavSettings.winPoints) room.settings.scavSettings.winPoints = {};\r\n\t\troom.settings.scavSettings.winPoints[type] = winPoints;\r\n\r\n\t\troom.saveSettings();\r\n\t\tconst pointsDisplay = winPoints.map((p, i) => `(${(i + 1)}) ${p}`).join(', ');\r\n\t\tthis.privateModAction(`${user.name} has set the points awarded for winning ${type} scavenger hunts to - ${pointsDisplay}`);\r\n\t\tthis.modlog('SCAV SETPOINTS', null, `${type}: ${pointsDisplay}`);\r\n\r\n\t\t// double modnote in scavs room if it is a subroomgroupchat\r\n\t\tif (room.parent && !room.persist) {\r\n\t\t\tscavsRoom.modlog({\r\n\t\t\t\taction: 'SCAV SETPOINTS',\r\n\t\t\t\tloggedBy: user.id,\r\n\t\t\t\tnote: `${pointsDisplay} [room: ${room.roomid}]`,\r\n\t\t\t});\r\n\t\t\tscavsRoom.sendMods(`(${user.name} has set the points awarded for winning ${type} scavenger hunts to - ${pointsDisplay} in <<${room.roomid}>>)`);\r\n\t\t\tscavsRoom.roomlog(`(${user.name} has set the points awarded for winning ${type} scavenger hunts to - ${pointsDisplay} in <<${room.roomid}>>)`);\r\n\t\t}\r\n\t},\r\n\r\n\tresettwist: 'settwist',\r\n\tsettwist(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tconst scavsRoom = getScavsRoom(room);\r\n\t\tif (!scavsRoom) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tif (this.cmd.includes('reset')) target = 'RESET';\r\n\r\n\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\tif (!target) {\r\n\t\t\tconst twist = room.settings.scavSettings.officialtwist || 'none';\r\n\t\t\treturn this.sendReplyBox(`The current official twist is: ${twist}`);\r\n\t\t}\r\n\t\tthis.checkCan('declare', null, room);\r\n\t\tif (target === 'RESET') {\r\n\t\t\troom.settings.scavSettings.officialtwist = null;\r\n\t\t} else {\r\n\t\t\tconst twist = toID(target);\r\n\t\t\tif (!ScavMods.twists[twist] || twist === 'constructor') return this.errorReply('Invalid twist.');\r\n\r\n\t\t\troom.settings.scavSettings.officialtwist = twist;\r\n\t\t\troom.saveSettings();\r\n\t\t}\r\n\r\n\t\tif (room.settings.scavSettings.officialtwist) {\r\n\t\t\tthis.privateModAction(`${user.name} has set the official twist to ${room.settings.scavSettings.officialtwist}`);\r\n\t\t} else {\r\n\t\t\tthis.privateModAction(`${user.name} has removed the official twist.`);\r\n\t\t}\r\n\t\tthis.modlog('SCAV TWIST', null, room.settings.scavSettings.officialtwist);\r\n\r\n\t\t// double modnote in scavs room if it is a subroomgroupchat\r\n\t\tif (room.parent && !room.persist) {\r\n\t\t\tif (room.settings.scavSettings.officialtwist) {\r\n\t\t\t\tscavsRoom.modlog({\r\n\t\t\t\t\taction: 'SCAV TWIST',\r\n\t\t\t\t\tloggedBy: user.id,\r\n\t\t\t\t\tnote: `${room.settings.scavSettings.officialtwist} [room: ${room.roomid}]`,\r\n\t\t\t\t});\r\n\t\t\t\tscavsRoom.sendMods(`(${user.name} has set the official twist to - ${room.settings.scavSettings.officialtwist} in <<${room.roomid}>>)`);\r\n\t\t\t\tscavsRoom.roomlog(`(${user.name} has set the official twist to - ${room.settings.scavSettings.officialtwist} in <<${room.roomid}>>)`);\r\n\t\t\t} else {\r\n\t\t\t\tscavsRoom.sendMods(`(${user.name} has reset the official twist in <<${room.roomid}>>)`);\r\n\t\t\t\tscavsRoom.roomlog(`(${user.name} has reset the official twist in <<${room.roomid}>>)`);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\ttwists(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\tlet buffer = ``;\r\n\t\tbuffer += Object.values(ScavMods.twists).map(twist => (\r\n\t\t\tUtils.html``\r\n\t\t)).join('');\r\n\t\tbuffer += `
TwistDescription
${twist.name}${twist.desc}
`;\r\n\r\n\t\tthis.sendReply(`|raw|
${buffer}
`);\r\n\t},\r\n\r\n\t/**\r\n\t * Scavenger statistic tracking\r\n\t */\r\n\thuntcount: 'huntlogs',\r\n\tasync huntlogs(target, room, user) {\r\n\t\troom = this.requireRoom('scavengers' as RoomID);\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tif (target === 'RESET') {\r\n\t\t\tthis.checkCan('declare', null, room);\r\n\t\t\tawait HostLeaderboard.softReset();\r\n\t\t\tHostLeaderboard.write();\r\n\t\t\tthis.privateModAction(`${user.name} has reset the host log leaderboard into the next month.`);\r\n\t\t\tthis.modlog('SCAV HUNTLOGS', null, 'RESET');\r\n\t\t\treturn;\r\n\t\t} else if (target === 'HARD RESET') {\r\n\t\t\tthis.checkCan('declare', null, room);\r\n\t\t\tHostLeaderboard.hardReset().write();\r\n\t\t\tthis.privateModAction(`${user.name} has hard reset the host log leaderboard.`);\r\n\t\t\tthis.modlog('SCAV HUNTLOGS', null, 'HARD RESET');\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet [sortMethod, isUhtmlChange] = target.split(',');\r\n\r\n\t\tconst sortingFields = ['points', 'cumulative-points'];\r\n\r\n\t\tif (!sortingFields.includes(sortMethod)) sortMethod = 'points'; // default sort method\r\n\r\n\t\tconst data = await HostLeaderboard.visualize(sortMethod) as AnyObject[];\r\n\t\tthis.sendReply(\r\n\t\t\t`|${isUhtmlChange ? 'uhtmlchange' : 'uhtml'}|scav-huntlogs|
${\r\n\t\t\t\tdata.map(entry => {\r\n\t\t\t\t\tconst auth = room!.auth.get(toID(entry.name)).trim();\r\n\t\t\t\t\tconst color = auth ? 'inherit' : 'gray';\r\n\t\t\t\t\treturn `` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t``;\r\n\t\t\t\t}).join('')\r\n\t\t\t}
RankNameHunts CreatedTotal Hunts CreatedHistory
${entry.rank}${auth || ' '}${Utils.escapeHTML(entry.name)}${(entry.points || 0)}${(entry['cumulative-points'] || 0)}${entry['history-points'] ? `{ ${entry['history-points'].join(', ')} }` : ''}
${\r\n\t\t\t\tsortingFields.map(\r\n\t\t\t\t\tf => ``\r\n\t\t\t\t).join(' ')\r\n\t\t\t}
`\r\n\t\t);\r\n\t},\r\n\r\n\tasync playlogs(target, room, user) {\r\n\t\troom = this.requireRoom('scavengers' as RoomID);\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tif (target === 'RESET') {\r\n\t\t\tthis.checkCan('declare', null, room);\r\n\t\t\tawait PlayerLeaderboard.softReset();\r\n\t\t\tPlayerLeaderboard.write();\r\n\t\t\tthis.privateModAction(`${user.name} has reset the player log leaderboard into the next month.`);\r\n\t\t\tthis.modlog('SCAV PLAYLOGS', null, 'RESET');\r\n\t\t\treturn;\r\n\t\t} else if (target === 'HARD RESET') {\r\n\t\t\tthis.checkCan('declare', null, room);\r\n\t\t\tPlayerLeaderboard.hardReset().write();\r\n\t\t\tthis.privateModAction(`${user.name} has hard reset the player log leaderboard.`);\r\n\t\t\tthis.modlog('SCAV PLAYLOGS', null, 'HARD RESET');\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet [sortMethod, isUhtmlChange] = target.split(',');\r\n\r\n\t\tconst sortingFields = ['join', 'cumulative-join', 'finish', 'cumulative-finish', 'infraction', 'cumulative-infraction'];\r\n\r\n\t\tif (!sortingFields.includes(sortMethod)) sortMethod = 'finish'; // default sort method\r\n\r\n\t\tconst data = await PlayerLeaderboard.visualize(sortMethod) as AnyObject[];\r\n\t\tconst formattedData = data.map(d => {\r\n\t\t\t// always have at least one for join to get a value of 0 if both are 0 or non-existent\r\n\t\t\td.ratio = (((d.finish || 0) / (d.join || 1)) * 100).toFixed(2);\r\n\t\t\td['cumulative-ratio'] = (((d['cumulative-finish'] || 0) / (d['cumulative-join'] || 1)) * 100).toFixed(2);\r\n\t\t\treturn d;\r\n\t\t});\r\n\r\n\t\tthis.sendReply(\r\n\t\t\t`|${isUhtmlChange ? 'uhtmlchange' : 'uhtml'}|scav-playlogs|
${\r\n\t\t\t\tformattedData.map(entry => {\r\n\t\t\t\t\tconst auth = room!.auth.get(toID(entry.name)).trim();\r\n\t\t\t\t\tconst color = auth ? 'inherit' : 'gray';\r\n\r\n\t\t\t\t\treturn `` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t`` +\r\n\t\t\t\t\t\t``;\r\n\t\t\t\t}).join('')\r\n\t\t\t}
RankNameFinished HuntsJoined HuntsRatioInfractions
${entry.rank}${auth || ' '}${Utils.escapeHTML(entry.name)}${(entry.finish || 0)} (${(entry['cumulative-finish'] || 0)})${(entry['history-finish'] ? `
(History: ${entry['history-finish'].join(', ')})` : '')}
${(entry.join || 0)} (${(entry['cumulative-join'] || 0)})${(entry['history-join'] ? `
(History: ${entry['history-join'].join(', ')})` : '')}
${entry.ratio}%
(${(entry['cumulative-ratio'] || \"0.00\")}%)
${(entry.infraction || 0)} (${(entry['cumulative-infraction'] || 0)})${(entry['history-infraction'] ? `
(History: ${entry['history-infraction'].join(', ')})` : '')}
${\r\n\t\t\t\tsortingFields.map(\r\n\t\t\t\t\tf => ``\r\n\t\t\t\t).join(' ')\r\n\t\t\t}
`\r\n\t\t);\r\n\t},\r\n\r\n\tuninfract: \"infract\",\r\n\tinfract(target, room, user) {\r\n\t\troom = this.requireRoom('scavengers' as RoomID);\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tconst targetId = toID(target);\r\n\t\tif (!targetId) return this.errorReply(`Please include the name of the user to ${this.cmd}.`);\r\n\t\tconst change = this.cmd === 'infract' ? 1 : -1;\r\n\r\n\t\tPlayerLeaderboard.addPoints(targetId, 'infraction', change, true).write();\r\n\r\n\t\tthis.privateModAction(`${user.name} has ${(change > 0 ? 'given' : 'taken')} one infraction point ${(change > 0 ? 'to' : 'from')} '${targetId}'.`);\r\n\t\tthis.modlog(`SCAV ${this.cmd.toUpperCase()}`, user);\r\n\t},\r\n\r\n\tmodsettings: {\r\n\t\t'': 'update',\r\n\t\t'update'(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tif (!getScavsRoom(room)) return false;\r\n\t\t\tthis.checkCan('declare', null, room);\r\n\t\t\tconst settings = room.settings.scavSettings?.scavmod || {};\r\n\r\n\t\t\tthis.sendReply(`|uhtml${this.cmd === 'update' ? 'change' : ''}|scav-modsettings|
Scavenger Moderation Settings:

` +\r\n\t\t\t\t` Multiple connection verification: ${settings.ipcheck ? 'ON' : 'OFF'}` +\r\n\t\t\t\t`
`);\r\n\t\t},\r\n\r\n\t\t'ipcheck'(target, room, user) {\r\n\t\t\troom = this.requireRoom();\r\n\t\t\tif (!getScavsRoom(room)) return false;\r\n\t\t\tthis.checkCan('declare', null, room);\r\n\r\n\t\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\t\tconst settings = room.settings.scavSettings.scavmod || {};\r\n\t\t\ttarget = toID(target);\r\n\r\n\t\t\tconst setting: {[k: string]: boolean} = {\r\n\t\t\t\t'on': true,\r\n\t\t\t\t'off': false,\r\n\t\t\t\t'toggle': !settings.ipcheck,\r\n\t\t\t};\r\n\r\n\t\t\tif (!(target in setting)) return this.sendReply('Invalid setting - ON, OFF, TOGGLE');\r\n\r\n\t\t\tsettings.ipcheck = setting[target];\r\n\t\t\troom.settings.scavSettings.scavmod = settings;\r\n\r\n\t\t\troom.saveSettings();\r\n\r\n\t\t\tthis.privateModAction(`${user.name} has set multiple connections verification to ${setting[target] ? 'ON' : 'OFF'}.`);\r\n\t\t\tthis.modlog('SCAV MODSETTINGS IPCHECK', null, setting[target] ? 'ON' : 'OFF');\r\n\r\n\t\t\treturn this.parse('/scav modsettings update');\r\n\t\t},\r\n\t},\r\n\r\n\t/**\r\n\t * Database Commands\r\n\t */\r\n\trecycledhunts(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tif (!getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"Scavenger Hunts can only be added to the database in the scavengers room.\");\r\n\t\t}\r\n\r\n\t\tlet cmd;\r\n\t\t[cmd, target] = Utils.splitFirst(target, ' ');\r\n\t\tcmd = toID(cmd);\r\n\r\n\t\tif (!['addhunt', 'list', 'removehunt', 'addhint', 'removehint', 'autostart'].includes(cmd)) {\r\n\t\t\treturn this.parse(`/recycledhuntshelp`);\r\n\t\t}\r\n\r\n\t\tif (cmd === 'addhunt') {\r\n\t\t\tif (!target) return this.errorReply(`Usage: ${cmd} Hunt Text`);\r\n\r\n\t\t\tconst [hostsArray, ...questions] = target.split('|');\r\n\t\t\tconst hosts = ScavengerHunt.parseHosts(hostsArray.split(/[,;]/), room, true);\r\n\t\t\tif (!hosts.length) {\r\n\t\t\t\treturn this.errorReply(\"You need to specify a host.\");\r\n\t\t\t}\r\n\r\n\t\t\tconst result = ScavengerHunt.parseQuestions(questions);\r\n\t\t\tif (result.err) return this.errorReply(result.err);\r\n\r\n\t\t\tScavengerHuntDatabase.addRecycledHuntToDatabase(hosts, result.result);\r\n\t\t\treturn this.privateModAction(`A recycled hunt has been added to the database.`);\r\n\t\t}\r\n\r\n\t\t// The rest of the commands depend on there already being hunts in the database.\r\n\t\tif (ScavengerHuntDatabase.isEmpty()) return this.errorReply(\"There are no hunts in the database.\");\r\n\r\n\r\n\t\tif (cmd === 'list') {\r\n\t\t\treturn this.parse(`/join view-recycledHunts-${room}`);\r\n\t\t}\r\n\r\n\t\tconst params = target.split(',').map(param => param.trim()).filter(param => param !== '');\r\n\r\n\t\tconst usageMessages: {[k: string]: string} = {\r\n\t\t\t'removehunt': 'Usage: removehunt hunt_number',\r\n\t\t\t'addhint': 'Usage: addhint hunt number, question number, hint text',\r\n\t\t\t'removehint': 'Usage: removehint hunt number, question number, hint text',\r\n\t\t\t'autostart': 'Usage: autostart on/off',\r\n\t\t};\r\n\t\tif (!params) return this.errorReply(usageMessages[cmd]);\r\n\r\n\t\tconst numberOfRequiredParameters: {[k: string]: number} = {\r\n\t\t\t'removehunt': 1,\r\n\t\t\t'addhint': 3,\r\n\t\t\t'removehint': 3,\r\n\t\t\t'autostart': 1,\r\n\t\t};\r\n\t\tif (params.length < numberOfRequiredParameters[cmd]) return this.errorReply(usageMessages[cmd]);\r\n\r\n\t\tconst [huntNumber, questionNumber, hintNumber] = params.map((param) => parseInt(param));\r\n\t\tconst cmdsNeedingHuntNumber = ['removehunt', 'removehint', 'addhint'];\r\n\t\tif (cmdsNeedingHuntNumber.includes(cmd)) {\r\n\t\t\tif (!ScavengerHuntDatabase.hasHunt(huntNumber)) return this.errorReply(\"You specified an invalid hunt number.\");\r\n\t\t}\r\n\r\n\t\tconst cmdsNeedingQuestionNumber = ['addhint', 'removehint'];\r\n\t\tif (cmdsNeedingQuestionNumber.includes(cmd)) {\r\n\t\t\tif (\r\n\t\t\t\tisNaN(questionNumber) ||\r\n\t\t\t\tquestionNumber <= 0 ||\r\n\t\t\t\tquestionNumber > scavengersData.recycledHunts[huntNumber - 1].questions.length\r\n\t\t\t) {\r\n\t\t\t\treturn this.errorReply(\"You specified an invalid question number.\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst cmdsNeedingHintNumber = ['removehint'];\r\n\t\tif (cmdsNeedingHintNumber.includes(cmd)) {\r\n\t\t\tconst numQuestions = scavengersData.recycledHunts[huntNumber - 1].questions.length;\r\n\t\t\tif (isNaN(questionNumber) || questionNumber <= 0 || questionNumber > numQuestions) {\r\n\t\t\t\treturn this.errorReply(\"You specified an invalid hint number.\");\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (cmd === 'removehunt') {\r\n\t\t\tScavengerHuntDatabase.removeRecycledHuntFromDatabase(huntNumber);\r\n\t\t\treturn this.privateModAction(`Recycled hunt #${huntNumber} was removed from the database.`);\r\n\t\t} else if (cmd === 'addhint') {\r\n\t\t\tconst hintText = params[2];\r\n\t\t\tScavengerHuntDatabase.addHintToRecycledHunt(huntNumber, questionNumber, hintText);\r\n\t\t\treturn this.privateModAction(`Hint added to Recycled hunt #${huntNumber} question #${questionNumber}: ${hintText}.`);\r\n\t\t} else if (cmd === 'removehint') {\r\n\t\t\tScavengerHuntDatabase.removeHintToRecycledHunt(huntNumber, questionNumber, hintNumber);\r\n\t\t\treturn this.privateModAction(`Hint #${hintNumber} was removed from Recycled hunt #${huntNumber} question #${questionNumber}.`);\r\n\t\t} else if (cmd === 'autostart') {\r\n\t\t\tif (!room.settings.scavSettings) room.settings.scavSettings = {};\r\n\t\t\tif (params[0] !== 'on' && params[0] !== 'off') return this.errorReply(usageMessages[cmd]);\r\n\t\t\tif ((params[0] === 'on') === !!room.settings.scavSettings.addRecycledHuntsToQueueAutomatically) {\r\n\t\t\t\treturn this.errorReply(`Autostarting recycled hunts is already ${room.settings.scavSettings.addRecycledHuntsToQueueAutomatically ? 'on' : 'off'}.`);\r\n\t\t\t}\r\n\t\t\troom.settings.scavSettings.addRecycledHuntsToQueueAutomatically =\r\n\t\t\t\t!room.settings.scavSettings.addRecycledHuntsToQueueAutomatically;\r\n\t\t\tthis.privateModAction(`Automatically adding recycled hunts to the queue is now ${room.settings.scavSettings.addRecycledHuntsToQueueAutomatically ? 'on' : 'off'}`);\r\n\t\t\tif (params[0] === 'on') {\r\n\t\t\t\treturn this.parse(\"/scav queuerecycled\");\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\trecycledhuntshelp() {\r\n\t\tif (!this.runBroadcast()) return;\r\n\t\tthis.sendReplyBox([\r\n\t\t\t\"Help for Recycled Hunts\",\r\n\t\t\t\"- addhunt <Hunt Text>: Adds a hunt to the database of recycled hunts.\",\r\n\t\t\t\"- removehunt<Hunt Number>: Removes a hunt form the database of recycled hunts.\",\r\n\t\t\t\"- list: Shows a list of hunts in the database along with their questions and hints.\",\r\n\t\t\t\"- addhint <Hunt Number, Question Number, Hint Text>: Adds a hint to the specified question in the specified hunt.\",\r\n\t\t\t\"- removehint <Hunt Number, Question Number, Hint Number>: Removes the specified hint from the specified question in the specified hunt.\",\r\n\t\t\t\"- autostart <on/off>: Sets whether or not recycled hunts are automatically added to the queue when a hunt ends.\",\r\n\t\t].join('
'));\r\n\t},\r\n};\r\n\r\nexport const pages: Chat.PageTable = {\r\n\trecycledHunts(query, user, connection) {\r\n\t\tthis.title = 'Recycled Hunts';\r\n\t\tconst room = this.requireRoom();\r\n\r\n\t\tlet buf = \"\";\r\n\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\r\n\t\tif (!room.persist) return;\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tbuf += `

List of recycled Scavenger hunts

`;\r\n\t\tbuf += `
    `;\r\n\t\tfor (const hunt of scavengersData.recycledHunts) {\r\n\t\t\tbuf += `
  1. `;\r\n\t\t\tbuf += `

    By ${hunt.hosts.map((host: AnyObject) => host.name).join(', ')}

    `;\r\n\t\t\tfor (const question of hunt.questions) {\r\n\t\t\t\tbuf += `
    `;\r\n\t\t\t\tbuf += `${question.text}`;\r\n\t\t\t\tbuf += `
    `;\r\n\t\t\t\tbuf += `
    Answers:
    `;\r\n\t\t\t\tfor (const answer of question.answers) {\r\n\t\t\t\t\tbuf += `
    ${answer}
    `;\r\n\t\t\t\t}\r\n\t\t\t\tbuf += `
    `;\r\n\r\n\t\t\t\tif (question.hints.length) {\r\n\t\t\t\t\tbuf += `
    `;\r\n\t\t\t\t\tbuf += `
    Hints:
    `;\r\n\t\t\t\t\tfor (const hint of question.hints) {\r\n\t\t\t\t\t\tbuf += `
    ${hint}
    `;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbuf += `
    `;\r\n\t\t\t\t}\r\n\t\t\t\tbuf += `
    `;\r\n\t\t\t}\r\n\t\t\tbuf += `
  2. `;\r\n\t\t}\r\n\t\tbuf += `
`;\r\n\t\tbuf += `
`;\r\n\t\treturn buf;\r\n\t},\r\n};\r\n\r\nexport const commands: Chat.ChatCommands = {\r\n\t// general\r\n\tscav: 'scavengers',\r\n\tscavengers: ScavengerCommands,\r\n\ttscav: 'teamscavs',\r\n\tteamscavs: ScavengerCommands.teamscavs,\r\n\tteamscavshelp: ScavengerCommands.teamscavshelp,\r\n\r\n\t// old game aliases\r\n\tscavenge: ScavengerCommands.guess,\r\n\tstartpracticehunt: 'starthunt',\r\n\tstartofficialhunt: 'starthunt',\r\n\tstartminihunt: 'starthunt',\r\n\tstartunratedhunt: 'starthunt',\r\n\tstartrecycledhunt: 'starthunt',\r\n\tstarttwisthunt: 'starthunt',\r\n\tstarttwistofficial: 'starthunt',\r\n\tstarttwistpractice: 'starthunt',\r\n\tstarttwistmini: 'starthunt',\r\n\tstarttwistunrated: 'starthunt',\r\n\r\n\tforcestarthunt: 'starthunt',\r\n\tforcestartunrated: 'starthunt',\r\n\tforcestartpractice: 'starthunt',\r\n\r\n\tstarthunt: ScavengerCommands.create,\r\n\tjoinhunt: ScavengerCommands.join,\r\n\tleavehunt: ScavengerCommands.leave,\r\n\tresethunt: ScavengerCommands.reset,\r\n\tresethunttoqueue: ScavengerCommands.resettoqueue,\r\n\tforceendhunt: 'endhunt',\r\n\tendhunt: ScavengerCommands.end,\r\n\tedithunt: ScavengerCommands.edithunt,\r\n\tviewhunt: ScavengerCommands.viewhunt,\r\n\tinherithunt: ScavengerCommands.inherit,\r\n\tscavengerstatus: ScavengerCommands.status,\r\n\tscavengerhint: ScavengerCommands.hint,\r\n\r\n\tnexthunt: ScavengerCommands.next,\r\n\r\n\t// point aliases\r\n\tscavaddpoints: 'scavengeraddpoints',\r\n\tscavengersaddpoints: ScavengerCommands.addpoints,\r\n\r\n\tscavrmpoints: 'scavengersremovepoints',\r\n\tscavengersrmpoints: 'scavengersremovepoints',\r\n\tscavremovepoints: 'scavengersremovepoints',\r\n\tscavengersremovepoints: ScavengerCommands.addpoints,\r\n\r\n\tscavresetlb: 'scavengersresetlb',\r\n\tscavengersresetlb: ScavengerCommands.resetladder,\r\n\r\n\trecycledhunts: ScavengerCommands.recycledhunts,\r\n\trecycledhuntshelp: ScavengerCommands.recycledhuntshelp,\r\n\r\n\tscavrank: ScavengerCommands.rank,\r\n\tscavladder: 'scavtop',\r\n\tscavtop: ScavengerCommands.ladder,\r\n\tscavengerhelp: 'scavengershelp',\r\n\tscavhelp: 'scavengershelp',\r\n\tscavengershelp(target, room, user) {\r\n\t\tif (!room || !getScavsRoom(room)) {\r\n\t\t\treturn this.errorReply(\"This command can only be used in the scavengers room.\");\r\n\t\t}\r\n\t\tif (!this.runBroadcast()) return false;\r\n\r\n\t\tconst userCommands = [\r\n\t\t\t\"Player commands:\",\r\n\t\t\t\"- /scavengers: Join the scavengers room.\",\r\n\t\t\t\"- /joinhunt: Join the current scavenger hunt.\",\r\n\t\t\t\"- /leavehunt: Leave the current scavenger hunt. Also resets your progress.\",\r\n\t\t\t\"- /viewhunt: Show the ongoing hunt up to where you solved it.\",\r\n\t\t\t\"- /scavenge [guess]: Submit your answer to the current hint.\",\r\n\t\t\t\"- /scavengerstatus (or /scav status): Check your status in the current hunt.\",\r\n\t\t\t\"- /scavengers queue (or /scav queue): Showcase the hunts currently in queue, with the answers hidden for any hunt that is not yours.\",\r\n\t\t\t\"- /scavengerhint (or /scav hint): View your latest hint in the current game.\",\r\n\t\t\t\"- /scavladder (or /scav top): View the current scavengers leaderboard.\",\r\n\t\t\t\"- /scavrank [user]: View the rank of the user on the current scavenger leaderboard. Defaults to the user if no name is provided.\",\r\n\t\t\t\"For a more in-depth overview, use /scavhelp staff.\",\r\n\t\t].join('
');\r\n\t\tconst staffCommands = [\r\n\t\t\t\"Staff and auth commands:\",\r\n\t\t\t\"As a room voice (+), you can use the following Scavengers commands, on top of the regular commands (see /scavhelp):\",\r\n\t\t\t\"- /scav edithunt [question number], [hint | answer], [value]: Edit the ongoing scavenger hunt. Only the host(s) can edit the hunt.\",\r\n\t\t\t\"- /scav addhint [question number], [value]: Add a hint to a question in the ongoing scavenger hunt. Only the host(s) can add a hint.\",\r\n\t\t\t\"- /scav edithint [question number], [hint number], [value]: Edit a hint to a question in the ongoing scavenger hunt. Only the host(s) can edit a hint.\",\r\n\t\t\t\"- /scav removehint [question number], [hint number] (or /scav deletehint): Remove a hint from a question in the current scavenger hunt. Only the host(s) can remove a hint.\",\r\n\t\t\t\"- /teamscavshelp: Explains the team scavs plugin.\",\r\n\t\t\t\"
As a room driver (%), you can also use the following Scavengers commands:\",\r\n\t\t\t\"- /scav queue (unrated) [host(s)] | [hint] | [answer] | [hint] | [answer] | [hint] | [answer] | ...: Queue a scavenger hunt to be started after the current hunt is finished.\",\r\n\t\t\t\"- /start(official/practice/mini/unrated)hunt [host] | [hint] | [answer] | [hint] | [answer] | [hint] |
[answer] | ...: Create a new (official/practice/mini/unrated) scavenger hunt and start it immediately.\",\r\n\t\t\t\"- /scav viewqueue (or /scav queue): Look at the list of queued scavenger hunts. Now also includes the option to remove hunts from the queue.\",\r\n\t\t\t\"- /resethunt: Reset the current scavenger hunt without revealing the hints and answers, nor giving out points.\",\r\n\t\t\t\"- /resethunttoqueue: Reset the ongoing scavenger hunt without revealing the hints and answers, nor giving out points. Then, add it directly to the queue.\",\r\n\t\t\t\"- /scav timer [minutes]: Set a timer to automatically end the current hunt. Setting [minutes] to 0 turns off the timer.\",\r\n\t\t\t\"- /endhunt: End the current scavenger hunt immediately and announce the winners and the answers.\",\r\n\t\t\t\"- /nexthunt: Start the next hunt in the queue.\",\r\n\t\t\t\"- /viewhunt: View the ongoing scavenger hunt. As a host, you can also view the hunt in its entirety.\",\r\n\t\t\t\"- /inherithunt: Become the staff host, gaining staff permissions to the current hunt.\",\r\n\t\t\t\"- /scav games create [game mode]: start a game of the given mode.\",\r\n\t\t\t\"    Game modes include: Jump Start, Point Rally, KO games, Scav games and team scavs.\",\r\n\t\t\t\"- /scav games end: End the game of the given type.\",\r\n\t\t\t\"- /starttwist(hunt / practice / official / mini /unrated) [twist] | [host] | [hint] | [answer] | [hint] | [answer] | [hint] | [answer] | \u2026 : Create and start a new scavenger hunt that uses a specified twist mode. This can be used inside a scavenger game mode.\",\r\n\t\t\t\"- /scav twists: Show a list of all the twists that are available on the server.\",\r\n\t\t\t\"- /scav settwist: View the current default official hunt twist that is in use.\",\r\n\t\t\t\"- /scav setpoints: Show the current point distribution for officials, minis and regular hunts.\",\r\n\t\t\t\"- /scav setblitz: Show the current points awarded for Blitzing an official, mini or regular hunt.\",\r\n\t\t\t\"- /scav defaulttimer: Show the default timer applied to hunts started automatically from the queue.\",\r\n\t\t\t\"- /scav addpoints [user], [amount]: Give the user the specified amount of points towards the current ladder.\",\r\n\t\t\t\"- /scav removepoints [user], [amount]: Remove the specified amount of points from the user towards the current ladder.\",\r\n\t\t\t\"- /recycledhunts: Modify the database of recycled hunts and enable/disable autoqueing them.\",\r\n\t\t\t\"- /scav queuerecycled [number]: Queue a recycled hunt from the database. If [number] is left blank, then a random hunt is queued.\",\r\n\t\t\t\"- /recycledhuntshelp: give more info about the recycled hunts.\",\r\n\t\t\t\"
As a room owner (#), you can also use the following scavengers commands:\",\r\n\t\t\t\"- /scav resetladder: Reset the current scavenger leaderboard.\",\r\n\t\t\t\"- /scav setpoints [1st place], [2nd place], [3rd place], [4th place], [5th place], ...: Set the point values for wins of officials, minis and regular hunts.\",\r\n\t\t\t\"- /scav defaulttimer [value]: Set the default timer applied to automatically started hunts from the queue.\",\r\n\t\t\t\"- /scav setblitz [value] ...: Set the blitz award to the given value.\",\r\n\t\t\t\"- /scav settwist [twist name]: Set the default twist mode for all official hunts.\",\r\n\t\t\t\"- /scav resettwist: Reset the default twist mode for all official hunts to nothing.\",\r\n\t\t\t\"- /scav modsettings: Allow or disallow miscellaneous room settings\",\r\n\t\t].join('
');\r\n\r\n\t\tconst gamesCommands = [\r\n\t\t\t\"Game commands:\",\r\n\t\t\t\"- /scav game create [kogames | pointrally | scavengergames | jumpstart | teamscavs]: Start a new scripted scavenger game. (Requires: % @ * # &)\",\r\n\t\t\t\"- /scav game end: End the current scavenger game. (Requires: % @ * # &)\",\r\n\t\t\t\"- /scav game kick [user]: Kick the user from the current scavenger game. (Requires: % @ * # &)\",\r\n\t\t\t\"- /scav game score: Show the current scoreboard for any game with a leaderboard.\",\r\n\t\t\t\"- /scav game rank [user]: Show a user's rank in the current scavenger game leaderboard.\",\r\n\t\t].join('
');\r\n\r\n\t\ttarget = toID(target);\r\n\r\n\t\tconst display = target === 'all' ?\r\n\t\t\t`${userCommands}

${staffCommands}

${gamesCommands}` :\r\n\t\t\t(\r\n\t\t\t\ttarget === 'staff' || target === 'auth' ? staffCommands :\r\n\t\t\t\ttarget === 'games' || target === 'game' ? gamesCommands : userCommands\r\n\t\t\t);\r\n\r\n\t\tthis.sendReplyBox(display);\r\n\t},\r\n};\r\n"], "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,iBAAwB;AACxB,6BAAmC;AAXnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCA,MAAM,cAAc,CAAC,YAAY,WAAW,MAAM;AAClD,MAAM,iBAA0C;AAAA,EAC/C,UAAU,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC;AAC5B;AACA,MAAM,uBAA8C;AAAA,EACnD,UAAU;AACX;AACA,MAAM,sBAAsB;AAC5B,MAAM,yBAAyB;AAE/B,MAAM,YAAY;AAClB,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,gBAAgB;AAEtB,MAAM,mBAAmB;AAEzB,MAAM,kBAAkB;AAExB,MAAM,iBAAiB;AAEvB,MAAM,2BAAuB,eAAG,aAAa,EAAE,iBAAiB;AAChE,MAAM,iBAAiB,uBAAuB,KAAK,MAAM,oBAAoB,IAAI,EAAC,eAAe,CAAC,EAAC;AAEnG,MAAM,mBAAmB;AACzB,SAAS,aAAa,MAAa;AAClC,MAAI,CAAC;AAAM,WAAO,MAAM,IAAI,gBAAgB;AAC5C,MAAI,KAAK,WAAW;AAAkB,WAAO;AAC7C,MAAI,KAAK,QAAQ,WAAW;AAAkB,WAAO,KAAK;AAC1D,SAAO;AACR;AAEA,MAAM,OAAO;AAAA,EAGZ,YAAY,MAAc;AACzB,SAAK,OAAO;AACZ,SAAK,OAAO,CAAC;AAEb,SAAK,KAAK;AAAA,EACX;AAAA,EAEA,OAAO;AACN,UAAM,WAAO,eAAG,KAAK,IAAI,EAAE,iBAAiB;AAC5C,QAAI;AAAM,WAAK,OAAO,KAAK,MAAM,IAAI;AAAA,EACtC;AAAA,EAEA,UAAU,MAAc,QAAgB,QAAgB,UAAoB;AAC3E,UAAM,SAAS,KAAK,IAAI;AAExB,QAAI,CAAC,UAAU,WAAW,iBAAiB,CAAC;AAAQ,aAAO;AAC3D,QAAI,CAAC,KAAK,KAAK,MAAM;AAAG,WAAK,KAAK,MAAM,IAAI,EAAC,KAAU;AAEvD,QAAI,CAAC,KAAK,KAAK,MAAM,EAAE,MAAM;AAAG,WAAK,KAAK,MAAM,EAAE,MAAM,IAAI;AAC5D,SAAK,KAAK,MAAM,EAAE,MAAM,KAAK;AAE7B,QAAI,CAAC;AAAU,WAAK,KAAK,MAAM,EAAE,OAAO;AAExC,WAAO;AAAA,EACR;AAAA,EAEA,QAAQ;AACP,SAAK,OAAO,CAAC;AACb,WAAO;AAAA,EACR;AAAA,EAEA,QAAQ;AACP,uBAAG,KAAK,IAAI,EAAE,YAAY,MAAM,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA,EAC1D;AAAA,EAIA,UAAU,QAAgB,QAAa;AAEtC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACvC,UAAI,cAAc;AAClB,UAAI,gBAAgB;AAEpB,YAAM,SAAS,iBAAM;AAAA,QACpB,OAAO,QAAQ,KAAK,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,GAAG,MAAM,UAAU,GAAG;AAAA,QAC5D,CAAC,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,MAAM;AAAA,MAC1B,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,MAAM;AACxB,YAAI,MAAM,MAAM,MAAM,aAAa;AAClC,wBAAc,MAAM,MAAM;AAC1B,0BAAgB,IAAI;AAAA,QACrB;AACA,eAAO;AAAA,UACN,MAAM;AAAA,UACN,GAAG;AAAA,QACJ;AAAA,MACD,CAAC;AACD,UAAI,QAAQ;AACX,cAAM,OAAO,OAAO,KAAK,WAAS,KAAK,MAAM,IAAI,MAAM,MAAM;AAC7D,gBAAQ,IAAI;AAAA,MACb,OAAO;AACN,gBAAQ,MAAM;AAAA,MACf;AAAA,IACD,CAAC;AAAA,EACF;AACD;AAEA,MAAM,qBAAqB,OAAO;AAAA,EACjC,YAAY,MAAc;AACzB,UAAM,IAAI;AAAA,EACX;AAAA,EAEA,UAAU,MAAc,QAAgB,QAAgB,UAAoB;AAC3E,QAAI,CAAC,OAAO,WAAW,aAAa,GAAG;AACtC,WAAK,UAAU,MAAM,cAAc,UAAU,QAAQ,QAAQ;AAAA,IAC9D;AACA,UAAM,SAAS,KAAK,IAAI;AAExB,QAAI,CAAC,UAAU,WAAW,iBAAiB,CAAC;AAAQ,aAAO;AAC3D,QAAI,CAAC,KAAK,KAAK,MAAM;AAAG,WAAK,KAAK,MAAM,IAAI,EAAC,KAAU;AAEvD,QAAI,CAAC,KAAK,KAAK,MAAM,EAAE,MAAM;AAAG,WAAK,KAAK,MAAM,EAAE,MAAM,IAAI;AAC5D,SAAK,KAAK,MAAM,EAAE,MAAM,KAAK;AAE7B,QAAI,CAAC;AAAU,WAAK,KAAK,MAAM,EAAE,OAAO;AAExC,WAAO;AAAA,EACR;AAAA;AAAA;AAAA,EAIA,YAAY;AACX,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC7C,iBAAW,KAAK,KAAK,MAAM;AAC1B,cAAM,WAAW,KAAK,KAAK,CAAC;AAC5B,mBAAW,KAAK,UAAU;AACzB,cAAI,4BAA4B,KAAK,CAAC,KAAK,MAAM;AAAQ;AACzD,gBAAM,aAAa,aAAa;AAEhC,cAAI,CAAC,SAAS,UAAU;AAAG,qBAAS,UAAU,IAAI,CAAC;AAEnD,mBAAS,UAAU,EAAE,QAAQ,SAAS,CAAC,CAAC;AACxC,mBAAS,UAAU,IAAI,SAAS,UAAU,EAAE,MAAM,GAAG,cAAc;AAEnE,mBAAS,CAAC,IAAI;AAEd,cAAI,CAAC,SAAS,UAAU,EAAE,KAAK,CAAC,MAAW,CAAC,CAAC,CAAC,GAAG;AAChD,mBAAO,SAAS,CAAC;AACjB,mBAAO,SAAS,UAAU;AAAA,UAC3B;AAAA,QACD;AAAA,MACD;AACA,cAAQ;AAAA,IACT,CAAC;AAAA,EACF;AAAA,EAEA,YAAY;AACX,SAAK,OAAO,CAAC;AACb,WAAO;AAAA,EACR;AACD;AAGA,MAAM,kBAAkB,aAAa;AAErC,MAAM,cAAc,iBAAiB,iBAAiB,oBAAoB,IAAI,OAAO,SAAS;AAC9F,MAAM,kBAAkB,iBAAiB,iBAAiB,wBAAwB,IAAI,aAAa,cAAc;AACjH,MAAM,oBAAoB,iBAAiB,iBAAiB,0BAC3D,IAAI,aAAa,gBAAgB;AAElC,IAAI,iBAAiB;AACpB,MAAI,CAAC,gBAAgB;AAAiB,oBAAgB,kBAAkB,CAAC;AAEzE,kBAAgB,gBAAgB,mBAAmB;AACnD,kBAAgB,gBAAgB,uBAAuB;AACvD,kBAAgB,gBAAgB,yBAAyB;AAC1D;AAEA,SAAS,YAAY,OAAiC,QAAc,MAAY,cAAwB;AACvG,QAAM,YAAY,OAAO,IAAI,QAAQ,MAAM,IAAI,KAAK,CAAC;AACrD,QAAM,gBAAgB,KAAK,SAAS,cAAc;AAClD,QAAM,gBAAgB,KAAK,SAAS,cAAc,oBAAoB;AACtE,MAAI;AACJ,MAAI,OAAO,QAAQ;AAClB,aAAS,MAAM,IAAI,CAAC,MAAM,UAAU;AACnC,YAAM,eAAe,4CAA4C;AACjE,YAAM,cAAc,yCAAyC;AAC7D,YAAM,cAAc,KAAK,aAAa,YACrC,oEACA;AACD,YAAM,QAAQ,iBAAM,WAAW,KAAK,aAAa,KAAK,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC,CAAC;AAC7E,YAAM,WAAW,KAAK,MAAM,MAAM,OAAK,EAAE,OAAO,KAAK,WAAW,IAAI,MAAM,KAAK,gBAAgB;AAC/F,UAAI;AACJ,UAAI,CAAC,iBAAiB,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,OAAO,EAAE,KAAK,OAAO,OAAO,KAAK,cAAc;AAClG,oBAAY,KAAK,UAAU;AAAA,UAC1B,CAAC,GAAG,MAAM;AACT,gBAAI,IAAI,GAAG;AACV,kBAAI;AACJ,qBAAO,iBAAM,uCAAuC,EAAE,KAAK,KAAK;AAAA,YACjE,OAAO;AACN,kBAAI;AACJ,qBAAO,iBAAM,WAAW,CAAC;AAAA,YAC1B;AAAA,UACD;AAAA,QACD,EAAE,KAAK,GAAG;AAAA,MACX,OAAO;AACN,oBAAY,IAAI,KAAK,UAAU,SAAS;AAAA,MACzC;AACA,aAAO,WAAW,eAAe,oBAAoB,cAAc,QAAQ,oBAAoB;AAAA,IAChG,CAAC,EAAE,KAAK,EAAE;AAAA,EACX,OAAO;AACN,aAAS;AAAA,EACV;AACA,MAAI,WAAW,wFAAwF,YAAY,SAAS,OAAO,QAAQ,8BAA8B,EAAE;AAC3K,MAAI,WAAW;AACd,gBAAY,qFAAqF,oEAAoE,CAAC,gBACrK,6CACA,4IAA4I,gBAC5I,4CACA;AAAA,EACF;AACA,SAAO;AACR;AAEA,MAAM,sBAAsB;AAAA,EAC3B,OAAO,8BAA8B;AAEpC,WAAO,eAAe,cAAc,KAAK,MAAM,KAAK,OAAO,IAAI,eAAe,cAAc,MAAM,CAAC;AAAA,EACpG;AAAA,EAEA,OAAO,0BAA0B,OAAmB,QAA+B;AAClF,UAAM,aAA0D;AAAA,MAC/D;AAAA,MACA,WAAW,CAAC;AAAA,IACb;AAEA,QAAI,iBAAsE;AAAA,MACzE,MAAM;AAAA,MACN,SAAS,CAAC;AAAA,MACV,OAAO,CAAC;AAAA,IACT;AAEA,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,EAAE,GAAG;AACvC,UAAI,IAAI,MAAM,GAAG;AAChB,cAAM,eAAe,OAAO,CAAC;AAC7B,uBAAe,OAAO;AAAA,MACvB,OAAO;AACN,cAAM,aAAa,OAAO,CAAC;AAC3B,uBAAe,UAAU;AACzB,mBAAW,UAAU,KAAK,cAAc;AACxC,yBAAiB;AAAA,UAChB,MAAM;AAAA,UACN,SAAS,CAAC;AAAA,UACV,OAAO,CAAC;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAEA,mBAAe,cAAc,KAAK,UAAU;AAC5C,SAAK,qBAAqB;AAAA,EAC3B;AAAA,EAEA,OAAO,+BAA+B,OAAe;AACpD,mBAAe,cAAc,OAAO,QAAQ,GAAG,CAAC;AAChD,SAAK,qBAAqB;AAAA,EAC3B;AAAA,EAEA,OAAO,sBAAsB,YAAoB,gBAAwB,MAAc;AACtF,mBAAe,cAAc,aAAa,CAAC,EAAE,UAAU,iBAAiB,CAAC,EAAE,MAAM,KAAK,IAAI;AAC1F,SAAK,qBAAqB;AAAA,EAC3B;AAAA,EAEA,OAAO,yBAAyB,YAAoB,gBAAwB,YAAoB;AAC/F,mBAAe,cAAc,aAAa,CAAC,EAAE,UAAU,iBAAiB,CAAC,EAAE,MAAM,OAAO,aAAa,CAAC;AACtG,SAAK,qBAAqB;AAAA,EAC3B;AAAA,EAEA,OAAO,uBAAuB;AAC7B,uBAAG,aAAa,EAAE,YAAY,MAAM,KAAK,UAAU,cAAc,CAAC;AAAA,EACnE;AAAA,EAEA,OAAO,UAAU;AAChB,WAAO,eAAe,cAAc,WAAW;AAAA,EAChD;AAAA,EAEA,OAAO,QAAQ,aAAqB;AACnC,WAAO,CAAC,MAAM,WAAW,KAAK,cAAc,KAAK,eAAe,eAAe,cAAc;AAAA,EAC9F;AAAA,EAEA,OAAO,kBAAkB,MAA6F;AACrH,WAAO,GAAG,KAAK,MAAM,IAAI,UAAQ,KAAK,IAAI,EAAE,KAAK,GAAG,OAAO,KAAK,UAAU,IAAI,cAAY,GAAG,SAAS,UAAU,SAAS,QAAQ,KAAK,GAAG,GAAG,EAAE,KAAK,KAAK;AAAA,EACzJ;AACD;AACO,MAAM,sBAAsB,MAAM,SAA8B;AAAA;AAAA,EAoBtE,YACC,MACA,WACA,OACA,UACA,WACA,KACC;AACD,UAAM,IAAI;AAXX,SAAS,YAAY;AAapB,SAAK,eAAe;AACpB,SAAK,WAAW;AAChB,SAAK,YAAY;AAEjB,SAAK,YAAY,CAAC;AAElB,SAAK,YAAY,KAAK,IAAI;AAC1B,SAAK,YAAY,CAAC;AAClB,SAAK,YAAY,CAAC;AAElB,SAAK,WAAW,CAAC;AAEjB,SAAK,QAAQ;AAEb,SAAK,WAAW,CAAC;AACjB,SAAK,OAAO,CAAC;AAEb,SAAK,QAAQ;AACb,SAAK,WAAW;AAEhB,SAAK,cAAc,UAAU;AAC7B,SAAK,gBAAgB,UAAU;AAC/B,SAAK,aAAa,SAAS;AAE3B,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,WAAW;AAEhB,QAAI,KAAK,KAAK,UAAU;AACvB,WAAK,SAAS,KAAK,KAAK,SAAS,GAAG;AAAA,IACrC;AACA,QAAI,KAAK;AACR,WAAK,SAAS,GAAG;AAAA,IAClB,WAAW,KAAK,aAAa,cAAc,KAAK,KAAK,SAAS,cAAc,eAAe;AAC1F,WAAK,QAAQ,KAAK,KAAK,SAAS,cAAc,aAAa;AAAA,IAC5D;AAEA,SAAK,SAAS,MAAM;AACpB,SAAK,OAAO,SAAS;AACrB,SAAK,SAAS,WAAW;AAAA,EAC1B;AAAA,EAEA,SAAS,gBAAqB;AAC7B,QAAI,MAAM,QAAQ,cAAc,GAAG;AAClC,iBAAW,OAAO,gBAAgB;AACjC,aAAK,QAAQ,GAAG;AAAA,MACjB;AAAA,IACD,OAAO;AACN,WAAK,QAAQ,cAAc;AAAA,IAC5B;AAAA,EACD;AAAA,EAEA,QAAQ,SAAkC;AACzC,QAAI;AACJ,QAAI,OAAO,YAAY,UAAU;AAChC,YAAM,QAAQ,KAAK,OAAO;AAC1B,UAAI,CAAC,gCAAS,OAAO,KAAK;AAAG,eAAO,KAAK,SAAS,kDAAkD,QAAQ;AAE5G,cAAQ,gCAAS,OAAO,KAAK;AAAA,IAC9B,OAAO;AACN,cAAQ;AAAA,IACT;AACA,SAAK,SAAS,KAAK,MAAM,EAAE;AAC3B,eAAW,OAAO,OAAO;AACxB,UAAI,CAAC,IAAI,WAAW,IAAI;AAAG;AAC3B,YAAM,WAAW,MAAM,MAAM,UAAU,KAAK;AAC5C,UAAI,CAAC,KAAK,KAAK,GAAG;AAAG,aAAK,KAAK,GAAG,IAAI,CAAC;AACvC,WAAK,KAAK,GAAG,EAAE,KAAK,EAAC,MAAM,MAAM,GAAG,GAAG,SAAQ,CAAC;AAAA,IACjD;AACA,QAAI,MAAM,YAAY;AACrB,WAAK,SAAS,mCAAmC,MAAM,OAAO;AAAA,IAC/D,OAAO;AACN,WAAK,SAAS,4BAA4B,MAAM,OAAO;AAAA,IACxD;AAAA,EACD;AAAA;AAAA,EAGA,UAAU,MAAY,YAAwB;AAE7C,eAAW,OAAO,KAAK,MAAM,KAAK,mBAAmB,CAAC;AACtD,SAAK,SAAS,WAAW,MAAM,UAAU;AAAA,EAC1C;AAAA,EAEA,mBAAmB,SAA2B;AAC7C,UAAM,UAAU,KAAK,SAAS,gBAAgB;AAC9C,QAAI;AAAS,aAAO;AAEpB,UAAM,QAAQ,iBAAM,WAAW,KAAK,aAAa,KAAK,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC,CAAC;AAC7E,UAAM,YAAY,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,WAAW,IAC/D,KACA,iBAAM,eAAe,KAAK;AAE3B,UAAM,UAAU,CAAC,YAAY,SAAS,EAAE,SAAS,KAAK,QAAQ,KAAK,CAAC,UAAU,OAAO;AACrF,UAAM,WAAW,GAAG,WAAW,UAAU,SAAS,KAAK,KAAK;AAE5D,WAAO,4CAA4C,kCAAkC,8BAA8B,kHAErF,KAAK,WAAW,KAAK,UAAU,CAAC,EAAE,IAAI;AAAA,EAGrE;AAAA,EAEA,SAAS,MAAY;AACpB,QAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK,OAAO,KAAK,aAAa;AAC3E,aAAO,KAAK;AAAA,QACX,KAAK;AAAA,QACL;AAAA,MACD;AAAA,IACD;AACA,QAAI,CAAC,OAAO,cAAc,KAAK,IAAI,KAAK,QAAM,KAAK,UAAU,SAAS,EAAE,CAAC,GAAG;AAC3E,aAAO,KAAK,OAAO,KAAK,MAAM,uCAAuC;AAAA,IACtE;AACA,QAAI,KAAK,SAAS,QAAQ,IAAI;AAAG,aAAO;AACxC,QAAI,KAAK,UAAU,IAAI,GAAG;AACzB,WAAK,aAAa,IAAI;AACtB,aAAO,KAAK,SAAS,KAAK,EAAE;AAC5B,WAAK,OAAO,KAAK,MAAM,qEAAqE;AAC5F,WAAK,eAAe,IAAI;AACxB,aAAO;AAAA,IACR;AACA,SAAK,OAAO,KAAK,MAAM,mCAAmC;AAC1D,WAAO;AAAA,EACR;AAAA,EAEA,aAAa,MAAuB;AAEnC,QAAI,EAAE,SAAS;AAAO;AACtB,eAAW,MAAM,KAAK,KAAK;AAC1B,WAAK,UAAU,KAAK,EAAE;AAAA,IACvB;AAAA,EACD;AAAA,EAEA,UAAU,MAAY;AACrB,UAAM,SAAS,KAAK,YAAY,KAAK,EAAE;AAEvC,QAAI,CAAC;AAAQ,aAAO,KAAK,OAAO,KAAK,MAAM,yCAAyC;AACpF,QAAI,OAAO;AAAW,aAAO,KAAK,OAAO,KAAK,MAAM,iDAAiD;AACrG,SAAK,SAAS,SAAS,MAAM;AAC7B,SAAK,YAAY,KAAK,UAAU,OAAO,QAAM,CAAC,OAAO,QAAQ,SAAS,EAAE,CAAC;AACzE,SAAK,aAAa,IAAI;AACtB,SAAK,SAAS,KAAK,EAAE,IAAI;AACzB,SAAK,OAAO,KAAK,MAAM,mCAAmC;AAAA,EAC3D;AAAA;AAAA,EAGA,WAAW,MAAY;AACtB,WAAO,IAAI,oBAAoB,MAAM,IAAI;AAAA,EAC1C;AAAA,EAEA,OAAO,GAA0B;AAChC,aAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK,GAAG;AACrC,YAAM,OAAO,EAAE,CAAC;AAChB,YAAM,SAAS,EAAE,IAAI,CAAC;AAEtB,WAAK,UAAU,KAAK,EAAC,MAAY,QAAgB,UAAU,CAAC,EAAC,CAAC;AAAA,IAC/D;AAEA,UAAM,UAAU,KAAK,mBAAmB,IAAI;AAC5C,SAAK,KAAK,IAAI,OAAO,EAAE,OAAO;AAAA,EAC/B;AAAA;AAAA,EAGA,SAAS,aAAqB,MAAa;AAC1C,UAAM,SAAS,KAAK,KAAK,OAAO,QAAQ;AACxC,QAAI,CAAC;AAAQ;AAEb,qBAAM,OAAO,QAAQ,WAAS,CAAC,MAAM,QAAQ;AAC7C,QAAI,SAAS;AAEb,eAAW,SAAS,QAAQ;AAC3B,YAAM,YAAY,MAAM,KAAK,KAAK,MAAM,GAAG,IAAI;AAC/C,UAAI,cAAc;AAAM,eAAO;AAC/B,eAAS;AAAA,IACV;AAEA,WAAO,WAAW,QAAQ,OAAO;AAAA,EAClC;AAAA,EAEA,eAAe,gBAAwB,iBAAyB,OAAe;AAC9E,QAAI,oBAAoB;AAAY,wBAAkB;AACtD,QAAI,CAAC,CAAC,QAAQ,QAAQ,EAAE,SAAS,eAAe;AAAG,aAAO;AAE1D,QAAI,SAAmB,CAAC;AACxB,QAAI,oBAAoB,UAAU;AACjC,eAAS,MAAM,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AAAA,IAC5C;AAEA,QAAI,CAAC,kBAAkB,iBAAiB,KAAK,iBAAiB,KAAK,UAAU,UAAW,CAAC,UAAU,CAAC,OAAQ;AAC3G,aAAO;AAAA,IACR;AAEA;AAEA,QAAI,oBAAoB,UAAU;AACjC,WAAK,UAAU,cAAc,EAAE,SAAS;AAAA,IACzC,OAAO;AACN,WAAK,UAAU,cAAc,EAAE,OAAO;AAAA,IACvC;AAEA,SAAK,SAAS,OAAO,gCAAgC,iBAAiB,oBAAoB;AAC1F,QAAI,oBAAoB,QAAQ;AAC/B,iBAAW,KAAK,KAAK,aAAa;AACjC,aAAK,YAAY,CAAC,EAAE,eAAe,cAAc;AAAA,MAClD;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,SAAS,SAAiB;AACzB,QAAI,KAAK,OAAO;AACf,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AACb,WAAK,WAAW;AAAA,IACjB;AAEA,QAAI,YAAY,GAAG;AAClB,aAAO;AAAA,IACR;AACA,QAAI,UAAU,KAAK,IAAI;AACtB,YAAM,IAAI,KAAK,aAAa,oDAAoD,KAAK,iBAAiB,UAAU,GAAK,KAAK;AAAA,IAC3H;AACA,QAAI,WAAW,UAAU,GAAG;AAC3B,WAAK,QAAQ,WAAW,MAAM,KAAK,MAAM,GAAG,UAAU,GAAK;AAC3D,WAAK,WAAW,KAAK,IAAI,IAAI,UAAU;AAAA,IACxC;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,MAAY,eAAuB;AACzC,QAAI,EAAE,KAAK,MAAM,KAAK,cAAc;AACnC,UAAI,CAAC,KAAK,SAAS,IAAI;AAAG,eAAO;AAAA,IAClC;AACA,UAAM,QAAQ,KAAK,aAAa;AAEhC,UAAM,SAAS,KAAK,YAAY,KAAK,EAAE;AAEvC,QAAI,KAAK,SAAS,aAAa,QAAQ,OAAO,aAAa;AAAG;AAC9D,QAAI,OAAO;AAAW,aAAO;AAE7B,SAAK,eAAe,MAAM;AAC1B,WAAO,YAAY,KAAK,IAAI;AAE5B,QAAI,KAAK,SAAS,UAAU,QAAQ,OAAO,aAAa;AAAG,aAAO;AAElE,QAAI,OAAO,aAAa,KAAK,GAAG;AAC/B,UAAI,KAAK,SAAS,iBAAiB,QAAQ,KAAK;AAAG;AACnD,aAAO,SAAS,sDAAsD;AACtE,aAAO;AACP,UAAI,OAAO,oBAAoB,KAAK,UAAU,QAAQ;AACrD,aAAK,WAAW,MAAM;AAAA,MACvB,OAAO;AACN,aAAK,eAAe,IAAI;AAAA,MACzB;AAAA,IACD,OAAO;AACN,UAAI,KAAK,SAAS,mBAAmB,QAAQ,KAAK;AAAG;AACrD,YAAM,IAAI,KAAK,aAAa,qCAAqC;AAAA,IAClE;AAAA,EACD;AAAA,EAEA,YAAY,UAAkB,WAAqB;AAClD,UAAM,UAAU;AAAA,MACf,UAAU,KAAK,UAAU,WAAW,CAAC;AAAA,MACrC,QAAQ;AAAA,IACT;AACA,UAAM,YAAY,QAAQ,WAAW,KAAK,UAAU,SAAS,WAAW;AAExE,WAAO,+EACqC,kBAAkB,QAAQ,4BAEpE,KAAK,WAAW,QAAQ,SAAS,IAAI,KACpC,aAAa,QAAQ,SAAS,SAAS,SACvC,2CACC,QAAQ,SAAS,SAAS,IAAI,OAAK,KAAK,GAAG,EAAE,KAAK,QAAQ,gBAE3D;AAAA,EAGJ;AAAA,EAEA,eAAe,MAAkC,WAAqB;AACrE,QAAI,EAAE,KAAK,MAAM,KAAK,gBAAgB,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE;AAAG,aAAO;AAErF,UAAM,SAAS,KAAK,YAAY,KAAK,EAAE;AACvC,QAAI,OAAO;AAAW,aAAO;AAE7B,QAAI,KAAK,SAAS,gBAAgB,QAAQ,SAAS;AAAG;AAEtD,UAAM,kBAAkB,KAAK,YAAY,OAAO,mBAAmB,EAAE,QAAQ,SAAS;AAEtF,WAAO,SAAS,eAAe;AAC/B,WAAO;AAAA,EACR;AAAA,EAEA,WAAW,MAAY;AACtB,QAAI,KAAK,SAAS,YAAY,IAAI;AAAG;AAErC,QAAI,SAAS;AACb,QAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK,OAAO,KAAK,aAAa;AAC3E,eAAS,KAAK,UAAU,SAAS;AAAA,IAClC,WAAW,KAAK,MAAM,KAAK,aAAa;AACvC,YAAM,SAAS,KAAK,YAAY,KAAK,EAAE;AACvC,eAAS,OAAO,kBAAkB;AAAA,IACnC;AAEA,SAAK;AAAA,MACJ,KAAK;AAAA,MACL,4HAEA,KAAK,UAAU,MAAM,GAAG,MAAM,EAAE,IAAI,CAAC,GAAG,MACvC,WACC,IAAI,aAEJ,KAAK,WAAW,EAAE,IAAI,KACrB,EAAE,SAAS,SACX,2CACC,EAAE,SAAS,IAAI,OAAK,KAAK,GAAG,EAAE,KAAK,QAAQ,gBAE5C,eAED,IAAI,KAAK,SACR,KACA,iBAAM,oBAAoB,EAAE,OAAO,KAAK,KAAK,CAAC,aAEhD,EAAE,KAAK,EAAE,IACV;AAAA,IACD;AAAA,EACD;AAAA,EAEA,WAAW,QAA6B;AACvC,QAAI,OAAO;AAAW,aAAO;AAE7B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,OAAO,KAAK,iBAAiB,MAAM,KAAK,WAAW,EAAC,QAAQ,KAAI,CAAC;AACvE,UAAM,WAAW,KAAK,UAAU,SAAS;AAEzC,UAAM,QAAQ,MAAM,KAAK,aAAa,OAAS,aAC7C,KAAK,KAAK,SAAS,cAAc,cAAc,KAAK,QAAQ,KAAK,qBAAqB,KAAK,QAAQ;AAErG,WAAO,YAAY;AACnB,QAAI,SAAS,KAAK,SAAS,YAAY,QAAQ,MAAM,KAAK;AAC1D,QAAI,WAAW;AAAM;AACrB,aAAS,UAAU,EAAC,MAAM,OAAO,MAAM,MAAY,MAAY;AAC/D,SAAK,UAAU,KAAK,MAAM;AAC1B,UAAM,QAAQ,iBAAM,YAAY,KAAK,UAAU,MAAM;AAErD,UAAM,oBAAoB,KAAK,SAAS,qBAAqB,QAAQ,MAAM,OAAO,OAAO,MAAM;AAC/F,SAAK;AAAA,MACJ,qBACA,iBAAM,WAAW,OAAO,sCAAsC,iBAAiB,OAAQ,QAAQ,aAAa;AAAA,IAC7G;AAEA,WAAO,QAAQ;AAAA,EAChB;AAAA,EAEA,eAAe,SAAgB;AAC9B,UAAM,aAAa,KAAK,aAAa,aAAa,IAAI;AACtD,UAAM,QAAQ,KAAK,aAAa,KAAK,MAAM,IAAI,OAAK,OAAO,iBAAM,WAAW,EAAE,IAAI,QAAQ,CAAC;AAE3F,SAAK;AAAA,MACJ,OAAO,KAAK,WAAW,GAAG,KAAK,cAAc,uBAAuB,mBAAoB,UAAU,QAAQ,iBAAM,WAAW,QAAQ,IAAI,IAAI,yBACxI,KAAK,UAAU,MAAM,GAAG,UAAU,EAAE,IAAI,CAAC,GAAG,MAAM,GAAG,iBAAM,YAAY,IAAI,CAAC,gBAAgB,iBAAM,WAAW,EAAE,IAAI,4CAA4C,EAAE,qBAAqB,EAAE,KAAK,EAAE,IAC/L,KAAK,UAAU,SAAS,aAAa,sBAAsB,KAAK,UAAU,MAAM,UAAU,EAAE,IAAI,OAAK,OAAO,iBAAM,WAAW,EAAE,IAAI,4CAA4C,EAAE,cAAc,EAAE,KAAK,IAAI,YAAY,gFAEtN,KAAK,UAAU,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,MAAM,KAAK,WAAW,EAAE,IAAI,0CAA0C,iBAAM,WAAW,EAAE,OAAO,KAAK,KAAK,CAAC,gBAAgB,EAAE,KAAK,QAAQ;AAAA,IAElL;AAAA,EACD;AAAA,EAEA,MAAM,OAAiB,SAAgB;AACtC,QAAI,CAAC,YAAY,KAAK,eAAe,KAAK,aAAa,SAAS,KAAK,UAAU,YAAY,GAAG;AAC7F,cAAQ;AAAA,IACT;AAEA,SAAK,SAAS,OAAO,KAAK;AAC1B,QAAI,CAAC,sBAAsB,QAAQ,KAAK,KAAK,KAAK,SAAS,cAAc,sCAAsC;AAC9G,UAAI,CAAC,KAAK,KAAK,SAAS;AAAW,aAAK,KAAK,SAAS,YAAY,CAAC;AAEnE,YAAM,OAAO,sBAAsB,4BAA4B;AAC/D,YAAM,8BAA8B,KAAK,UAAU,QAAQ,CAAC,aAAwB,CAAC,SAAS,MAAM,SAAS,OAAO,CAAC;AACrH,WAAK,KAAK,SAAS,UAAU,KAAK;AAAA,QACjC,OAAO,KAAK;AAAA,QACZ,WAAW;AAAA,QACX,aAAa;AAAA,QACb,eAAe;AAAA,QACf,UAAU;AAAA,MACX,CAAC;AAAA,IACF;AACA,QAAI,CAAC,OAAO;AAEX,UAAI,CAAC,KAAK,SAAS,gBAAgB,OAAO;AAAG,aAAK,eAAe,OAAO;AAGxE,UAAI,CAAC,KAAK,SAAS,YAAY,GAAG;AACjC,cAAM,YAAY,KAAK,KAAK,SAAS,cAAc,YAAY,KAAK,QAAQ,KAC3E,eAAe,KAAK,QAAQ;AAC7B,cAAM,cAAc,KAAK,KAAK,SAAS,cAAc,cAAc,KAAK,QAAQ,KAC/E,qBAAqB,KAAK,QAAQ;AAEnC,YAAI;AACJ,YAAI,KAAK,aAAa,WAAW;AAChC,uBAAa,KAAK,KAAK,SAAS,cAAc,aAC7C,KAAK,KAAK,SAAS,cAAc,aACjC;AAAA,QACF;AAEA,YAAI,eAAe;AACnB,YAAI,aAAa,aAAa;AAC7B,qBAAW,CAAC,GAAG,SAAS,KAAK,KAAK,UAAU,QAAQ,GAAG;AACtD,gBAAI,CAAC,UAAU,SAAS,KAAK,UAAU;AAAQ;AAC/C,kBAAM,OAAO,UAAU;AACvB,gBAAI,UAAU,CAAC;AAAG,0BAAY,UAAU,MAAM,UAAU,UAAU,CAAC,CAAC;AACpE,gBAAI,eAAe,UAAU;AAAO,0BAAY,UAAU,MAAM,UAAU,WAAW;AAAA,UACtF;AACA,yBAAe;AAAA,QAChB;AACA,YAAI,YAAY;AACf,cAAI,KAAK,MAAM,WAAW,GAAG;AAC5B,wBAAY,UAAU,KAAK,MAAM,CAAC,EAAE,MAAM,UAAU,YAAY,KAAK,MAAM,CAAC,EAAE,QAAQ;AACtF,2BAAe;AAAA,UAChB,OAAO;AACN,iBAAK,KAAK,SAAS,4DAA4D;AAC/E,iBAAK,KAAK,SAAS,mDAAmD;AAAA,UACvE;AAAA,QACD;AACA,YAAI;AAAc,sBAAY,MAAM;AAAA,MACrC;AAEA,WAAK,mBAAmB;AAExB,WAAK,YAAY,KAAK,KAAK,MAAM;AAAA,IAClC,WAAW,SAAS;AACnB,WAAK,SAAS,wCAAwC,QAAQ,OAAO;AAAA,IACtE,OAAO;AACN,WAAK,SAAS,sEAAsE;AACpF,WAAK,YAAY,KAAK,KAAK,MAAM;AAAA,IAClC;AACA,SAAK,SAAS,YAAY,KAAK;AAC/B,SAAK,QAAQ;AAAA,EACd;AAAA,EAEA,qBAAqB;AAEpB,eAAW,KAAK,KAAK,aAAa;AACjC,YAAM,SAAS,KAAK,YAAY,CAAC;AACjC,wBAAkB,UAAU,OAAO,MAAM,QAAQ,CAAC;AAClD,UAAI,OAAO;AAAW,0BAAkB,UAAU,OAAO,MAAM,UAAU,CAAC;AAAA,IAC3E;AACA,eAAW,MAAM,KAAK,UAAU;AAC/B,UAAI,MAAM,KAAK;AAAa;AAE5B,wBAAkB,UAAU,IAAI,QAAQ,GAAG,IAAI;AAAA,IAChD;AACA,QAAI,KAAK,aAAa,YAAY;AACjC,iBAAW,QAAQ,KAAK,OAAO;AAC9B,wBAAgB,UAAU,KAAK,MAAM,UAAU,GAAG,KAAK,QAAQ,EAAE,MAAM;AAAA,MACxE;AAAA,IACD;AACA,sBAAkB,MAAM;AAAA,EACzB;AAAA,EAEA,YAAY,QAAgB;AAC3B,QAAI,KAAK,KAAK,YAAY,KAAK,KAAK,SAAS,cAAc,mBAAmB;AAC7E;AAAA,IACD;AAEA,QAAI,KAAK,KAAK,SAAS,aAAa,KAAK,KAAK,SAAS,UAAU,QAAQ;AACxE,iBAAW,MAAM;AAChB,cAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,YAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,SAAS,WAAW,UAAU,KAAK,SAAS,cAAc;AAAmB;AAE7G,cAAM,OAAO,KAAK,SAAS,UAAU,MAAM;AAC3C,cAAM,WAAW,KAAK,SAAS,cAAc,oBAAoB;AACjE,aAAK,OAAO,IAAI;AAAA,UACf;AAAA,UACA,EAAC,IAAI,KAAK,aAAa,MAAM,KAAK,cAAa;AAAA,UAC/C,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACN;AACA,cAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,YAAI,MAAM;AACT,eAAK,SAAS,QAAQ;AACtB,eAAK,IAAI,+CAA+C,KAAK,aAAa,KAAK,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC,kEAAkE,mBAAmB,EAAE,OAAO;AAAA,QACpM;AAGA,aAAK,aAAa;AAAA,MACnB,GAAG,IAAI,GAAK;AAAA,IACb;AAAA,EACD;AAAA;AAAA,EAGA,UAAU;AACT,QAAI,KAAK,OAAO;AACf,mBAAa,KAAK,KAAK;AAAA,IACxB;AACA,eAAW,KAAK,KAAK,aAAa;AACjC,WAAK,YAAY,CAAC,EAAE,QAAQ;AAAA,IAC7B;AAEA,SAAK,KAAK,OAAO;AAAA,EAClB;AAAA,EAEA,SAAS,KAAa;AACrB,SAAK,KAAK,IAAI,4CAA4C,oBAAoB,EAAE,OAAO;AAAA,EACxF;AAAA,EAEA,eAAe,QAA6B;AAC3C,QAAI,OAAO;AAAW,aAAO;AAC7B,QAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,OAAO,EAAE,KAAK,OAAO,OAAO,KAAK,aAAa;AAE/E,aAAO,SAAS,wEAAwE;AAGxF,YAAM,WAAW,IAAI,OAAO;AAC5B,WAAK,KAAK,SAAS,QAAQ;AAC3B,WAAK,KAAK,QAAQ,QAAQ;AAC1B,WAAK,KAAK,OAAO;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ,OAAO;AAAA,QACf,MAAM;AAAA,MACP,CAAC;AAED,wBAAkB,UAAU,OAAO,MAAM,cAAc,CAAC;AACxD,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,oBAAoB,KAAK,qBAAqB,OAAO,EAAE;AAC7D,QAAI,oBAAoB,KAAK,KAAK,KAAK,SAAS,cAAc,SAAS,SAAS;AAE/E,aAAO,SAAS,iHAAiH;AAGjI,YAAM,WAAW,IAAI,OAAO,+CAA+C;AAE3E,WAAK,KAAK,SAAS,QAAQ;AAC3B,WAAK,KAAK,QAAQ,QAAQ;AAC1B,WAAK,KAAK,OAAO;AAAA,QAChB,QAAQ;AAAA,QACR,QAAQ,OAAO;AAAA,QACf,MAAM,iCAAiC;AAAA,MACxC,CAAC;AAED,wBAAkB,UAAU,OAAO,MAAM,cAAc,CAAC;AACxD,aAAO,YAAY;AAAA,IACpB;AAAA,EACD;AAAA,EAEA,UAAU,QAAgB;AACzB,QAAI,EAAE,UAAU,KAAK;AAAc,aAAO;AAC1C,UAAM,SAAS,KAAK,YAAY,MAAM;AAGtC,QAAI,OAAO;AAAW,aAAO;AAE7B,WAAO,QAAQ;AACf,WAAO,KAAK,YAAY,MAAM;AAC9B,WAAO;AAAA,EACR;AAAA,EAEA,qBAAqB;AAAA,EAAC;AAAA,EAEtB,cAAc,KAAa;AAC1B,QAAI,QAAQ,KAAK,GAAG;AAIpB,UAAM,eAAe,iBAAiB,KAAK,GAAG;AAC9C,QAAI;AAAc,cAAQ,MAAM,MAAM,KAAK,aAAa,CAAC,CAAC,EAAE,MAAM;AAElE,UAAM,WAAW,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,KAAK,OAAK;AAC5D,UAAI,KAAK,CAAC;AACV,YAAM,KAAK,KAAK,MAAM,EAAE,SAAS,KAAK,eAAe;AACrD,UAAI,iBAAM,YAAY,OAAO,GAAG,EAAE,KAAK;AAAI,eAAO;AAClD,aAAO;AAAA,IACR,CAAC,CAAC;AAEF,QAAI;AAAU,aAAO;AACrB;AAAA,EACD;AAAA,EAEA,YAAY,MAAY;AACvB,WAAO,KAAK,YAAY,KAAK,EAAE,KAAK,KAAK,YAAY,KAAK,EAAE,EAAE;AAAA,EAC/D;AAAA,EAEA,qBAAqB,QAAgB;AACpC,UAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,QAAI,CAAC;AAAM,aAAO;AAElB,UAAM,MAAM,KAAK,YAAY,IAAI,OAAK,EAAE,EAAE;AAC1C,WAAO,IAAI,OAAO,CAAC,IAAI,UAAU,IAAI,QAAQ,EAAE,MAAM,KAAK,EAAE;AAAA,EAC7D;AAAA,EAEA,OAAO,WAAW,WAAqB,MAAY,cAAwB;AAC1E,UAAM,QAAQ,CAAC;AACf,eAAW,KAAK,WAAW;AAC1B,YAAM,KAAK,KAAK,CAAC;AACjB,YAAM,OAAO,MAAM,SAAS,EAAE;AAC9B,UAAI,CAAC,iBAAiB,CAAC,MAAM,aAAa,EAAE,KAAK,MAAM,KAAK;AAAS;AAErE,UAAI,CAAC,MAAM;AAEV,cAAM,KAAK,EAAC,MAAM,IAAI,IAAQ,UAAU,KAAI,CAAC;AAC7C;AAAA,MACD;AAEA,YAAM,KAAK,EAAC,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,KAAK,KAAI,CAAC;AAAA,IACpD;AACA,WAAO;AAAA,EACR;AAAA,EAEA,OAAO,eAAe,eAAoC;AACzD,QAAI,cAAc,SAAS,MAAM;AAAG,aAAO,EAAC,KAAK,2CAA0C;AAC3F,QAAI,cAAc,SAAS;AAAG,aAAO,EAAC,KAAK,6CAA4C;AAEvF,UAAM,qBAAqB,CAAC;AAE5B,aAAS,CAAC,GAAG,QAAQ,KAAK,cAAc,QAAQ,GAAG;AAClD,UAAI,IAAI,GAAG;AACV,cAAM,UAAU,SAAS,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACrD,2BAAmB,CAAC,IAAI;AACxB,YAAI,CAAC,QAAQ,UAAU,QAAQ,KAAK,OAAK,CAAC,KAAK,CAAC,CAAC,GAAG;AACnD,iBAAO,EAAC,KAAK,qEAAoE;AAAA,QAClF;AAAA,MACD,OAAO;AACN,mBAAW,SAAS,KAAK;AACzB,2BAAmB,CAAC,IAAI;AACxB,YAAI,CAAC;AAAU,iBAAO,EAAC,KAAK,kBAAiB;AAAA,MAC9C;AAAA,IACD;AAEA,WAAO,EAAC,QAAQ,mBAAkB;AAAA,EACnC;AACD;AAEO,MAAM,4BAA4B,MAAM,eAA8B;AAAA;AAAA,EAO5E,YAAY,MAAY,MAAqB;AAC5C,UAAM,MAAM,IAAI;AAEhB,SAAK,UAAU,KAAK,IAAI,MAAM;AAE9B,SAAK,kBAAkB;AACvB,SAAK,YAAY;AACjB,SAAK,YAAY;AAAA,EAClB;AAAA,EAEA,qBAAqB;AACpB,WAAO;AAAA,MACN,UAAU,KAAK,KAAK,UAAU,KAAK,eAAe;AAAA,MAClD,QAAQ,KAAK,kBAAkB;AAAA,IAChC;AAAA,EACD;AAAA,EAEA,aAAa,OAAe;AAC3B,UAAM,SAAS,KAAK,mBAAmB,EAAE,SAAS;AAClD,YAAQ,KAAK,KAAK;AAElB,WAAO,OAAO,KAAK,CAAC,MAAc,KAAK,CAAC,MAAM,KAAK;AAAA,EACpD;AAAA,EAEA,eAAe,KAAa;AAC3B,SAAK,KAAK,SAAS,gBAAgB,MAAM,GAAG;AAC5C,QAAI,QAAQ,KAAK,iBAAiB;AACjC,WAAK,SAAS,uDAAuD,KAAK,WAAW,KAAK,KAAK,UAAU,GAAG,EAAE,IAAI,GAAG;AAAA,IACtH;AAAA,EACD;AAAA,EAEA,UAAU;AACT,UAAM,OAAO,MAAM,SAAS,KAAK,EAAE;AACnC,QAAI,MAAM;AACT,WAAK,MAAM,OAAO,KAAK,KAAK,MAAM;AAClC,WAAK,aAAa;AAAA,IACnB;AAAA,EACD;AACD;AAEA,MAAM,oBAAuC;AAAA;AAAA;AAAA;AAAA,EAI5C,KAAK;AACJ,WAAO,KAAK,MAAM,kBAAkB;AAAA,EACrC;AAAA,EAEA,MAAM,QAAQ,MAAM,MAAM;AACzB,WAAO,KAAK,MAAM,WAAW,QAAQ;AAAA,EACtC;AAAA,EAEA,KAAK,QAAQ,MAAM,MAAM;AACxB,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,SAAK,UAAU;AAEf,SAAK,SAAS,IAAI;AAAA,EACnB;AAAA,EAEA,MAAM,QAAQ,MAAM,MAAM;AACzB,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,SAAK,UAAU,IAAI;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM;AAAA,EACN,OAAO;AAAA;AAAA;AAAA;AAAA,IAIN,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM,QAAQ,MAAM,MAAM;AACzB,aAAO,KAAK,YAAY;AACxB,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAI,KAAK;AAAU,eAAO,KAAK,WAAW,4CAA4C;AACtF,UAAI,KAAK,QAAQ,aAAa,GAAG;AAChC,eAAO,KAAK,WAAW,wFAAwF;AAAA,MAChH;AAEA,eAAS,KAAK,MAAM;AACpB,YAAM,OAAO,gCAAS,SAAS,MAAM,MAAM;AAE3C,UAAI,CAAC;AAAM,eAAO,KAAK,WAAW,oBAAoB;AAEtD,WAAK,WAAW;AAEhB,WAAK,iBAAiB,KAAK,KAAK,4BAA4B,KAAK,OAAO;AACxE,WAAK,OAAO,aAAa,MAAM,0BAA0B;AAEzD,WAAK,SAAS,aAAa,KAAK,wBAAwB;AAAA,IACzD;AAAA,IAEA,IAAI,QAAQ,MAAM,MAAM;AACvB,aAAO,KAAK,YAAY;AACxB,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAI,CAAC,KAAK;AAAU,eAAO,KAAK,WAAW,+CAA+C;AAE1F,WAAK,iBAAiB,OAAO,KAAK,SAAS,mCAAmC,KAAK,OAAO;AAC1F,WAAK,OAAO,aAAa,MAAM,0BAA0B;AACzD,WAAK,SAAS,SAAS,OAAO,KAAK,SAAS,+BAA+B;AAC3E,WAAK,SAAS,QAAQ,IAAI;AAAA,IAC3B;AAAA,IAEA,KAAK,QAAQ,MAAM,MAAM;AACxB,aAAO,KAAK,YAAY;AACxB,WAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAI,CAAC,KAAK;AAAU,eAAO,KAAK,WAAW,+CAA+C;AAE1F,YAAM,WAAW,KAAK,MAAM;AAC5B,UAAI,aAAa,iBAAiB,CAAC;AAAU,eAAO,KAAK,WAAW,iBAAiB;AAErF,YAAM,UAAU,KAAK,SAAS,UAAU,QAAQ;AAChD,UAAI,SAAS;AACZ,aAAK,aAAa,SAAS,sCAAsC,KAAK,SAAS,OAAO;AACtF,aAAK,OAAO,cAAc,QAAQ,mBAAmB,KAAK,SAAS,MAAM;AACzE,cAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,YAAI,MAAM;AACT,eAAK,UAAU,QAAQ;AAAA,QACxB;AAAA,MACD,OAAO;AACN,aAAK,WAAW,wBAAwB,YAAY;AAAA,MACrD;AAAA,IACD;AAAA,IAEA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,MAAM,YAAY,QAAQ,MAAM,MAAM;AACrC,aAAO,KAAK,YAAY;AACxB,UAAI,CAAC,KAAK;AAAU,eAAO,KAAK,WAAW,+CAA+C;AAC1F,UAAI,CAAC,KAAK,SAAS;AAAa,eAAO,KAAK,WAAW,kDAAkD;AACzG,UAAI,CAAC,KAAK,aAAa;AAAG,eAAO;AAEjC,YAAM,OAAO,MAAM,KAAK,SAAS,YAAY,WAAW;AACxD,WAAK,UAAU,QAAQ,MAAM;AAAA,IAC9B;AAAA,IAEA,MAAM,KAAK,QAAQ,MAAM,MAAM;AAC9B,aAAO,KAAK,YAAY;AACxB,UAAI,CAAC,KAAK;AAAU,eAAO,KAAK,WAAW,+CAA+C;AAC1F,UAAI,CAAC,KAAK,SAAS;AAAa,eAAO,KAAK,WAAW,kDAAkD;AACzG,UAAI,CAAC,KAAK,aAAa;AAAG,eAAO;AAEjC,YAAM,WAAW,KAAK,MAAM,KAAK,KAAK;AAEtC,YAAM,OAAO,MAAM,KAAK,SAAS,YAAY,UAAU,UAAU,QAAQ;AAEzE,UAAI,CAAC,MAAM;AACV,aAAK,aAAa,SAAS,wEAAwE;AAAA,MACpG,OAAO;AACN,aAAK,aAAa,iBAAM,aAAa,KAAK,aAAa,KAAK,gDAAgD,KAAK,gBAAgB;AAAA,MAClI;AAAA,IACD;AAAA,EACD;AAAA,EACA,WAAW;AAAA,IACV,SAAS;AAAA,IACT,WAAW,QAAQ,MAAM,MAAM;AAC9B,aAAO,KAAK,YAAY;AACxB,WAAK,SAAS,QAAQ,MAAM,IAAI;AAGhC,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AAEjH,UAAI,CAAC,UAAU,MAAM,IAAI,OAAO,MAAM,GAAG;AACzC,iBAAW,SAAS,KAAK;AACzB,UAAI,KAAK,MAAM,QAAQ;AAAG,eAAO,KAAK,WAAW,YAAY,0BAA0B;AAEvF,YAAM,aAAa,MAAM,IAAI,MAAM;AACnC,UAAI,CAAC;AAAY,eAAO,KAAK,WAAW,gDAAgD;AACxF,UAAI,KAAK,cAAc,UAAU;AAAG,eAAO,KAAK,WAAW,+CAA+C;AAE1G,WAAK,MAAM,QAAQ,IAAI,EAAC,MAAM,UAAU,SAAS,CAAC,GAAG,SAAS,CAAC,WAAW,EAAE,GAAG,UAAU,GAAG,WAAW,MAAK;AAC5G,WAAK,SAAS,iBAAM,mBAAmB,mCAAmC,WAAW,qBAAqB;AAAA,IAC3G;AAAA,IAEA,YAAY;AAAA,IACZ,WAAW,QAAQ,MAAM,MAAM;AAC9B,aAAO,KAAK,YAAY;AACxB,WAAK,SAAS,QAAQ,MAAM,IAAI;AAGhC,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AAEjH,UAAI,CAAC,KAAK,MAAM,MAAM;AAAG,eAAO,KAAK,WAAW,YAAY,wBAAwB;AAEpF,aAAO,KAAK,MAAM,MAAM;AACxB,WAAK,SAAS,iBAAM,iBAAiB,2BAA2B;AAAA,IACjE;AAAA,IAEA,UAAU,QAAQ,MAAM,MAAM;AAC7B,aAAO,KAAK,YAAY;AACxB,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AAGjH,UAAI;AAEJ,iBAAW,UAAU,KAAK,OAAO;AAChC,cAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,YAAI,KAAK,QAAQ,CAAC,MAAM,KAAK,IAAI;AAChC,qBAAW;AACX;AAAA,QACD;AAAA,MACD;AACA,UAAI,CAAC;AAAU,eAAO,KAAK,WAAW,+DAA+D;AAErG,YAAM,cAAc,OAAO,MAAM,GAAG,EAAE,IAAI,QAAM,MAAM,SAAS,EAAE,CAAC,EAAE,OAAO,OAAK,GAAG,SAAS;AAC5F,UAAI,CAAC,YAAY;AAAQ,eAAO,KAAK,WAAW,gDAAgD;AAEhG,YAAM,SAAS,CAAC;AAChB,iBAAW,cAAc,aAAa;AACrC,YAAI,KAAK,cAAc,UAAU;AAAG,iBAAO,KAAK,GAAG,WAAW,4BAA4B;AAAA,MAC3F;AACA,UAAI,OAAO;AAAQ,eAAO,KAAK,aAAa,OAAO,KAAK,QAAQ,CAAC;AAEjE,YAAM,YAAY,YAAY,IAAI,OAAK,EAAE,EAAE;AAC3C,eAAS,QAAQ,KAAK,GAAG,SAAS;AAElC,iBAAW,cAAc,aAAa;AACrC,mBAAW,OAAO,MAAM,mBAAmB,SAAS,OAAO;AAAA,MAC5D;AACA,WAAK,SAAS,iBAAM,OAAO,KAAK,aAAa,YAAY,IAAI,OAAK,EAAE,IAAI,CAAC,KAAK,YAAY,SAAS,IAAI,SAAS,yBAAyB,SAAS,OAAO;AAAA,IAC1J;AAAA,IAEA,YAAY,QAAQ,MAAM,MAAM;AAC/B,aAAO,KAAK,YAAY;AACxB,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AACjH,WAAK,SAAS,QAAQ,MAAM,IAAI;AAGhC,YAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,YAAM,WAAW,MAAM,CAAC,EAAE,KAAK;AAC/B,YAAM,gBAAgB,MAAM,MAAM,CAAC;AAEnC,YAAM,OAAO,KAAK,MAAM,QAAQ;AAEhC,UAAI,CAAC;AAAM,eAAO,KAAK,WAAW,eAAe;AAEjD,iBAAW,SAAS,eAAe;AAClC,cAAM,SAAS,KAAK,KAAK;AACzB,YAAI,MAAM,KAAK,EAAE,WAAW,GAAG,GAAG;AAEjC,cAAI,CAAC,KAAK,QAAQ,SAAS,MAAM,GAAG;AACnC,iBAAK,WAAW,SAAS,2BAA2B,KAAK,QAAQ;AACjE;AAAA,UACD,WAAW,KAAK,QAAQ,CAAC,MAAM,QAAQ;AACtC,iBAAK,WAAW,sBAAsB,kCAAkC,KAAK,QAAQ;AACrF;AAAA,UACD;AACA,eAAK,UAAU,KAAK,QAAQ,OAAO,CAAC,MAAc,MAAM,MAAM;AAC9D,eAAK,SAAS,GAAG,4BAA4B,KAAK,QAAQ;AAAA,QAC3D,OAAO;AACN,gBAAM,aAAa,MAAM,SAAS,MAAM;AACxC,cAAI,CAAC,YAAY,WAAW;AAC3B,iBAAK,WAAW,SAAS,kCAAkC;AAC3D;AAAA,UACD;AAEA,gBAAM,iBAAiB,KAAK,cAAc,UAAU;AACpD,cAAI,KAAK,QAAQ,SAAS,MAAM,GAAG;AAClC,iBAAK,WAAW,SAAS,+BAA+B,KAAK,QAAQ;AACrE;AAAA,UACD,WAAW,gBAAgB;AAC1B,iBAAK,WAAW,SAAS,8CAA8C,eAAe,QAAQ;AAC9F;AAAA,UACD;AACA,eAAK,QAAQ,KAAK,MAAM;AACxB,eAAK,SAAS,GAAG,WAAW,sBAAsB,KAAK,QAAQ;AAAA,QAChE;AAAA,MACD;AAAA,IACD;AAAA,IAEA,MAAM,QAAQ,MAAM,MAAM;AACzB,UAAI,CAAC,KAAK,aAAa;AAAG,eAAO;AACjC,aAAO,KAAK,YAAY;AAExB,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AAEjH,YAAM,UAAU,CAAC;AACjB,iBAAW,UAAU,KAAK,OAAO;AAChC,cAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,gBAAQ,KAAK,iBAAM,eAAe,KAAK,2BAA2B,KAAK,QAAQ,CAAC,aAAa,KAAK,QAAQ,SAAS,IAAI,OAAO,KAAK,QAAQ,MAAM,CAAC,EAAE,KAAK,IAAI,IAAI,IAAI;AAAA,MACtK;AAEA,WAAK,aAAa,QAAQ,KAAK,QAAQ,CAAC;AAAA,IACzC;AAAA,IAEA,QAAQ,QAAQ,MAAM,MAAM;AAC3B,aAAO,KAAK,YAAY;AACxB,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AAEjH,YAAM,OAAO,KAAK,cAAc,IAAI;AACpC,UAAI,CAAC;AAAM,eAAO,KAAK,WAAW,qDAAqD;AAEvF,WAAK,aAAa,iBAAM,yBAAyB,KAAK,8BAA8B,KAAK,QAAQ,KAAK,EAAE,KAAK,IAAI,GAAG;AAAA,IACrH;AAAA,IAEA,MAAM;AAAA,IACN,KAAK,QAAQ,MAAM,MAAM;AACxB,aAAO,KAAK,YAAY;AACxB,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,QAAQ,KAAK,OAAO;AAAa,eAAO,KAAK,WAAW,oDAAoD;AAEjH,YAAM,OAAO,KAAK,cAAc,IAAI;AACpC,UAAI,CAAC;AAAM,eAAO,KAAK,WAAW,qDAAqD;AAEvF,UAAI,CAAC;AAAQ,eAAO,KAAK,WAAW,uCAAuC;AAE3E,WAAK,aAAa,MAAM,iBAAM,0BAA0B,KAAK,kBAAkB,QAAQ;AAAA,IACxF;AAAA,EACD;AAAA,EACA,eAAe;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,OAAO,QAAQ,MAAM,MAAM,YAAY,KAAK;AAC3C,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,6DAA6D;AAAA,IACrF;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,QAAI,KAAK;AAAM,aAAO,KAAK,WAAW,0CAA0C,KAAK,KAAK,QAAQ;AAClG,QAAI,WAAW;AACf,QAAI,IAAI,SAAS,UAAU,GAAG;AAC7B,iBAAW;AAAA,IACZ,WAAW,IAAI,SAAS,UAAU,GAAG;AACpC,iBAAW;AAAA,IACZ,WAAW,IAAI,SAAS,MAAM,GAAG;AAChC,iBAAW;AAAA,IACZ,WAAW,IAAI,SAAS,SAAS,GAAG;AACnC,iBAAW;AAAA,IACZ,WAAW,IAAI,SAAS,UAAU,GAAG;AACpC,iBAAW;AAAA,IACZ;AAEA,QAAI;AACJ,QAAI,YAAY;AAEhB,QAAI,IAAI,SAAS,OAAO,GAAG;AAC1B,YAAM,aAAa,OAAO,MAAM,GAAG;AACnC,kBAAY,WAAW,MAAM,CAAC,EAAE,KAAK,GAAG;AACxC,YAAM,WAAW,CAAC,EAAE,MAAM,GAAG;AAAA,IAC9B;AAGA,QACC,CAAC,IAAI,SAAS,OAAO,KAAK,CAAC,WAAW,WAAW,UAAU,EAAE,SAAS,QAAQ,KAAK,CAAC,OACpF,KAAK,SAAS,aAAa,KAAK,SAAS,UAAU,UAAU,CAAC,KAAK,UAClE;AACD,aAAO,KAAK,WAAW,uGAAuG,aAAa,YAAY,SAAS,WAAW;AAAA,IAC5K;AAEA,QAAI,aAAa,YAAY;AAC5B,UAAI,sBAAsB,QAAQ,GAAG;AACpC,eAAO,KAAK,WAAW,qCAAqC;AAAA,MAC7D;AAEA,UAAI;AACJ,UAAI,WAAW;AACd,cAAM,aAAa,SAAS,SAAS;AACrC,YAAI,CAAC,sBAAsB,QAAQ,UAAU;AAAG,iBAAO,KAAK,WAAW,uCAAuC;AAC9G,eAAO,eAAe,cAAc,aAAa,CAAC;AAAA,MACnD,OAAO;AACN,eAAO,sBAAsB,4BAA4B;AAAA,MAC1D;AAEA,kBAAY,sBAAsB,kBAAkB,IAAI;AAAA,IACzD;AAEA,QAAI,CAAC,YAAY,GAAG,MAAM,IAAI,UAAU,MAAM,GAAG;AAEjD,QAAI,aAAa,YAAY;AAC5B,oBAAc,IAAI,KAAK;AAAA,IACxB;AACA,UAAM,QAAQ,cAAc;AAAA,MAC3B,WAAW,MAAM,MAAM;AAAA,MACvB;AAAA,MACA,aAAa,cAAc,aAAa;AAAA,IACzC;AACA,QAAI,CAAC,MAAM,QAAQ;AAClB,aAAO,KAAK,WAAW,6EAA6E;AAAA,IACrG;AAEA,UAAM,MAAM,cAAc,eAAe,MAAM;AAC/C,QAAI,IAAI;AAAK,aAAO,KAAK,WAAW,IAAI,GAAG;AAE3C,SAAK,OAAO,IAAI,cAAc,MAAM,MAAM,OAAO,UAAU,IAAI,QAAQ,GAAG;AAE1E,SAAK,iBAAiB,uCAAuC,KAAK,OAAO;AACzE,SAAK,OAAO,YAAY,MAAM,GAAG,SAAS,YAAY,iBAAiB,MAAM,IAAI,OAAK,EAAE,EAAE,GAAG;AAAA,EAC9F;AAAA,EAEA,OAAO,QAAQ,MAAM,MAAM;AAC1B,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,UAAM,aAAa,KAAK,iBAAiB,KAAK,IAAI,IAAI,KAAK,WAAW,EAAC,QAAQ,KAAI,CAAC;AACpF,UAAM,cAAc,KAAK,WAAW,OAAO,KAAK,mBAAmB;AACnE,UAAM,aAAa,iBAAM,WAAW,KAAK,aAAa,KAAK,MAAM,IAAI,OAAK,EAAE,IAAI,CAAC,CAAC;AAClF,UAAM,UAAU,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,WAAW,IAC7D,KAAK,iBAAM,sBAAsB,KAAK;AACvC,UAAM,YAAY,iBAAM,OAAO,KAAK,UAAU,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI;AACxE,QAAI,SAAS,6DAA6D,oCAAoC,aAAa,iCAAiC,mBAAmB,CAAC,KAAK,WAAW,gCAAgC,qBAAqB,KAAK,iBAAiB,KAAK,WAAW,KAAK,IAAI,GAAG,EAAC,QAAQ,KAAI,CAAC,uBAAuB,KAAK,UAAU,YAAY;AACvW,QAAI,KAAK,SAAS,SAAS,WAAW,GAAG;AACxC,YAAM,WAAW,KAAK,UAAU,KAAK,YAAU,OAAO,OAAO,KAAK,EAAE;AACpE,YAAM,eAAe,WACpB,6BAA6B,SAAS,UACrC,KAAK,aAAa,KAAK,EAAE,IACzB,uBAAuB,KAAK,iBAAiB,KAAK,IAAI,IAAI,KAAK,WAAW,KAAK,EAAE,GAAG,EAAC,QAAQ,KAAI,CAAC,WAClG;AACF,eAAS,6DAA6D,oCAAoC,aAAa,iCAAiC,mBAAmB,qBAAqB,CAAC,KAAK,WAAW,gCAAgC,qBAAqB,KAAK,iBAAiB,KAAK,WAAW,KAAK,IAAI,GAAG,EAAC,QAAQ,KAAI,CAAC,uBAAuB,KAAK,UAAU,YAAY;AAAA,IACzX;AAEA,QAAI,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK,gBAAgB,KAAK,IAAI;AAC3E,UAAI,MAAM;AACV,eAAS,IAAI,GAAG,IAAI,KAAK,UAAU,QAAQ,KAAK;AAC/C,cAAM,cAAc,IAAI;AACxB,cAAM,UAAU,OAAO,OAAO,KAAK,WAAW,EAAE,OAAO,YAAU,OAAO,oBAAoB,KAAK,CAAC,OAAO,SAAS;AAClH,YAAI,CAAC,QAAQ,QAAQ;AACpB,iBAAO,WAAW;AAAA,QACnB,OAAO;AACN,iBAAO,WAAW;AAClB,iBAAO,QAAQ;AAAA,YACd,QAAM,GAAG,YAAY,KAAK,IAAI,IAAI,MAAO,MACxC,iBAAM,eAAe,GAAG,kBACxB,iBAAM,WAAW,GAAG,IAAI;AAAA,UAC1B,EAAE,KAAK,IAAI;AAAA,QACZ;AAAA,MACD;AACA,YAAM,YAAyB,KAAK,eAAe,KAAK,eAAe,KAAK;AAC5E,aAAO,iBAAM,iCAAiC,UAAU,SAAS,UAAU,IAAI,QAAM,GAAG,IAAI,EAAE,KAAK,IAAI,IAAI;AAC3G,aAAO,KAAK,UAAU,QAAQ,oBAAoB,QAAQ;AAAA,IAC3D;AACA,SAAK,UAAU,QAAQ,QAAQ;AAAA,EAChC;AAAA,EAEA,KAAK,QAAQ,MAAM,MAAM;AACxB,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,QAAI,CAAC,KAAK,eAAe,MAAM,IAAI;AAAG,WAAK,WAAW,kDAAkD;AAAA,EACzG;AAAA,EAEA,MAAM,QAAQ,MAAM,MAAM;AACzB,WAAO,KAAK,YAAY;AACxB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,UAAM,UAAW,KAAK,MAAM,MAAM,QAAQ,IAAI,WAAW,MAAM;AAC/D,QAAI,MAAM,OAAO,KAAK,UAAU,KAAM,UAAU,KAAK,MAAQ,KAAK,sBAAsB;AACvF,YAAM,IAAI,KAAK,aAAa,2DAA2D;AAAA,IACxF;AAEA,UAAM,SAAS,KAAK,SAAS,OAAO;AACpC,UAAM,UAAU,gCAAiC,WAAW,QAAQ,eAAe,UAAU;AAE7F,SAAK,IAAI,UAAU,GAAG;AACtB,SAAK,iBAAiB,GAAG,cAAc,KAAK,OAAO;AACnD,SAAK,OAAO,cAAc,MAAO,WAAW,QAAQ,QAAQ,GAAG,gBAAiB;AAAA,EACjF;AAAA,EAEA,QAAQ,QAAQ,MAAM,MAAM;AAC3B,WAAO,KAAK,YAAY;AACxB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,QAAI,KAAK,gBAAgB,KAAK;AAAI,aAAO,KAAK,WAAW,mDAAmD;AAE5G,SAAK,cAAc,KAAK,KAAK;AAC7B,SAAK,gBAAgB,KAAK,KAAK;AAG/B,SAAK,UAAU,KAAK,EAAE;AACtB,SAAK,aAAa,IAAI;AAEtB,SAAK,iBAAiB,GAAG,KAAK,4DAA4D;AAC1F,SAAK,OAAO,cAAc;AAAA,EAC3B;AAAA,EAEA,MAAM,QAAQ,MAAM,MAAM;AACzB,WAAO,KAAK,YAAY;AACxB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,SAAK,MAAM,MAAM,IAAI;AACrB,SAAK,iBAAiB,GAAG,KAAK,oCAAoC;AAClE,SAAK,OAAO,YAAY;AAAA,EACzB;AAAA,EAEA,aAAa,QAAQ,MAAM,MAAM;AAChC,WAAO,KAAK,YAAY;AACxB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,UAAM,OAAmB;AAAA,MACxB,OAAO,KAAK;AAAA,MACZ,WAAW,CAAC;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,eAAe,KAAK;AAAA,MACpB,UAAU,KAAK;AAAA,IAChB;AACA,eAAW,SAAS,KAAK,WAAW;AACnC,WAAK,UAAU,KAAK,GAAG,CAAC,MAAM,MAAM,MAAM,MAAM,CAAC;AAAA,IAClD;AACA,QAAI,CAAC,KAAK,SAAS;AAAW,WAAK,SAAS,YAAY,CAAC;AACzD,SAAK,SAAS,UAAU,KAAK,IAAI;AAEjC,SAAK,MAAM,MAAM,IAAI;AACrB,SAAK,iBAAiB,GAAG,KAAK,gEAAgE;AAC9F,SAAK,OAAO,mBAAmB;AAAA,EAChC;AAAA,EAEA,UAAU;AAAA,EACV,IAAI,QAAQ,MAAM,MAAM;AACvB,WAAO,KAAK,YAAY;AACxB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,QAAI,CAAC,KAAK,QAAQ,KAAK;AAAU,aAAO,KAAK,MAAM,iBAAiB;AACpE,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,UAAM,YAAY,KAAK,eAAe,KAAK,eAAe,KAAK;AAE/D,QAAI,CAAC,KAAK,IAAI,SAAS,OAAO,GAAG;AAChC,UAAI,CAAC,UAAU,QAAQ;AACtB,eAAO,KAAK,WAAW,0GAA0G;AAAA,MAClI;AAAA,IACD,WAAW,UAAU,QAAQ;AAC5B,aAAO,KAAK,WAAW,iBAAiB,KAAK,MAAM,WAAW,WAAW,iBAAiB;AAAA,IAC3F;AAEA,SAAK,MAAM,OAAO,IAAI;AACtB,SAAK,iBAAiB,GAAG,KAAK,oCAAoC;AAClE,SAAK,OAAO,UAAU;AAAA,EACvB;AAAA,EAEA,SAAS,QAAQ,MAAM,MAAM;AAC5B,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,QAAI,EAAE,gBAAgB;AAAO,aAAO,KAAK,WAAW,0CAA0C;AAE9F,SAAK,WAAW,IAAI;AAAA,EACrB;AAAA,EAEA,SAAS,QAAQ,MAAM,MAAM;AAC5B,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,SACE,CAAC,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,MAAM,IAAI,MACxE,KAAK,gBAAgB,KAAK,IACzB;AACD,aAAO,KAAK,WAAW,gEAAgE;AAAA,IACxF;AAEA,UAAM,CAAC,UAAU,MAAM,GAAG,KAAK,IAAI,OAAO,MAAM,GAAG;AACnD,QAAI,CAAC,KAAK,eAAe,SAAS,QAAQ,GAAG,KAAK,IAAI,GAAG,MAAM,KAAK,GAAG,EAAE,KAAK,CAAC,GAAG;AACjF,aAAO,KAAK,UAAU,sGAAsG;AAAA,IAC7H;AAAA,EACD;AAAA,EAEA,SAAS;AAAA,EACT,QAAQ,QAAQ,MAAM,MAAM;AAC3B,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,SACE,CAAC,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,MAAM,IAAI,MACxE,KAAK,gBAAgB,KAAK,IACzB;AACD,aAAO,KAAK,WAAW,oDAAoD;AAAA,IAC5E;AACA,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,WAAW,SAAS,MAAM,CAAC,CAAC,IAAI;AACtC,UAAM,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAEpC,QAAI,CAAC,KAAK,UAAU,QAAQ;AAAG,aAAO,KAAK,WAAW,0BAA0B;AAChF,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,gCAAgC;AAClE,SAAK,UAAU,QAAQ,EAAE,SAAS,KAAK,IAAI;AAE3C,SAAK,UAAU,MAAM,aAAa,WAAW,qBAAqB,MAAM;AACxE,UAAM,aAAa,KAAK,QAAQ,OAAO,YAAU,OAAO,oBAAoB,YAAY,CAAC,OAAO,SAAS;AACzG,UAAM,QAAQ,+BAA+B,WAAW;AACxD,eAAW,UAAU,YAAY;AAChC,YAAM,YAAY,MAAM,IAAI,OAAO,EAAE;AACrC,UAAI,CAAC,WAAW;AAAW;AAC3B,WAAK,SAAS,WAAW,KAAK;AAAA,IAC/B;AAAA,EACD;AAAA,EAEA,YAAY;AAAA,EACZ,WAAW,QAAQ,MAAM,MAAM;AAC9B,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,SACE,CAAC,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,MAAM,IAAI,MACxE,KAAK,gBAAgB,KAAK,IACzB;AACD,aAAO,KAAK,WAAW,kDAAkD;AAAA,IAC1E;AAEA,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,WAAW,SAAS,MAAM,CAAC,CAAC,IAAI;AACtC,UAAM,OAAO,SAAS,MAAM,CAAC,CAAC,IAAI;AAGlC,QAAI,CAAC,KAAK,UAAU,QAAQ;AAAG,aAAO,KAAK,WAAW,0BAA0B;AAChF,QAAI,CAAC,KAAK,UAAU,QAAQ,EAAE,SAAS,IAAI;AAAG,aAAO,KAAK,WAAW,sBAAsB;AAC3F,SAAK,UAAU,QAAQ,EAAE,SAAS,OAAO,MAAM,CAAC;AAEhD,WAAO,KAAK,UAAU,wBAAwB;AAAA,EAC/C;AAAA,EAEA,YAAY;AAAA,EACZ,SAAS,QAAQ,MAAM,MAAM;AAC5B,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AACjF,SACE,CAAC,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,QAAQ,MAAM,IAAI,MACxE,KAAK,gBAAgB,KAAK,IACzB;AACD,aAAO,KAAK,WAAW,gDAAgD;AAAA,IACxE;AAEA,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,WAAW,SAAS,MAAM,CAAC,CAAC,IAAI;AACtC,UAAM,OAAO,SAAS,MAAM,CAAC,CAAC,IAAI;AAClC,UAAM,QAAQ,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAErC,QAAI,CAAC,KAAK,UAAU,QAAQ;AAAG,aAAO,KAAK,WAAW,0BAA0B;AAChF,QAAI,CAAC,KAAK,UAAU,QAAQ,EAAE,SAAS,IAAI;AAAG,aAAO,KAAK,WAAW,sBAAsB;AAC3F,QAAI,CAAC;AAAO,aAAO,KAAK,WAAW,gCAAgC;AACnE,SAAK,UAAU,QAAQ,EAAE,SAAS,IAAI,IAAI;AAE1C,SAAK,UAAU,MAAM,aAAa,WAAW,qBAAqB,OAAO;AACzE,UAAM,aAAa,KAAK,QAAQ,OAAO,YAAU,OAAO,oBAAoB,YAAY,CAAC,OAAO,SAAS;AACzG,UAAM,QAAQ,+BAA+B,WAAW;AACxD,eAAW,UAAU,YAAY;AAChC,YAAM,YAAY,MAAM,IAAI,OAAO,EAAE;AACrC,UAAI,CAAC,WAAW;AAAW;AAC3B,WAAK,SAAS,WAAW,KAAK;AAAA,IAC/B;AACA,WAAO,KAAK,UAAU,yBAAyB;AAAA,EAChD;AAAA,EAEA,KAAK,QAAQ,MAAM,MAAM;AACxB,WAAO,KAAK,YAAY;AACxB,UAAM,OAAO,KAAK,QAAQ,aAAa;AACvC,QAAI,CAAC;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAEjF,UAAM,WAAW,KAAK,MAAM;AAC5B,QAAI,aAAa,iBAAiB,CAAC;AAAU,aAAO,KAAK,WAAW,iBAAiB;AAErF,UAAM,UAAU,KAAK,UAAU,QAAQ;AACvC,QAAI,SAAS;AACZ,WAAK,OAAO,aAAa,QAAQ;AACjC,aAAO,KAAK,iBAAiB,GAAG,KAAK,oBAAoB,oCAAoC;AAAA,IAC9F;AACA,SAAK,WAAW,mBAAmB,oCAAoC;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,MAAM,QAAQ,MAAM,MAAM;AACzB,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,QAAI,CAAC,UAAU,KAAK,QAAQ,iBAAiB;AAC5C,UAAI,KAAK,QAAQ,SAAS;AACzB,aAAK,aAAa;AAClB,cAAM,iBAAiB,kBAAkB;AACzC,uBAAe,KAAK,MAAM,QAAQ,MAAM,MAAM,KAAK,YAAY,KAAK,KAAK,KAAK,OAAO;AACrF;AAAA,MACD;AACA,aAAO,KAAK,MAAM,iBAAiB;AAAA,IACpC;AAEA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,QAAI,KAAK,QAAQ,iBAAiB;AACjC,UAAI,sBAAsB,QAAQ,GAAG;AACpC,eAAO,KAAK,WAAW,qCAAqC;AAAA,MAC7D;AACA,UAAI,CAAC,KAAK,SAAS,WAAW;AAC7B,aAAK,SAAS,YAAY,CAAC;AAAA,MAC5B;AAEA,UAAI;AACJ,UAAI,QAAQ;AACX,cAAM,aAAa,SAAS,MAAM;AAClC,YAAI,CAAC,sBAAsB,QAAQ,UAAU;AAAG,iBAAO,KAAK,WAAW,uCAAuC;AAC9G,eAAO,eAAe,cAAc,aAAa,CAAC;AAAA,MACnD,OAAO;AACN,eAAO,sBAAsB,4BAA4B;AAAA,MAC1D;AACA,YAAM,8BAA8B,KAAK,UAAU,QAAQ,CAAC,aAAwB,CAAC,SAAS,MAAM,SAAS,OAAO,CAAC;AACrH,WAAK,SAAS,UAAU,KAAK;AAAA,QAC5B,OAAO,KAAK;AAAA,QACZ,WAAW;AAAA,QACX,aAAa;AAAA,QACb,eAAe;AAAA,QACf,UAAU;AAAA,MACX,CAAC;AAAA,IACF,OAAO;AACN,YAAM,CAAC,YAAY,GAAG,MAAM,IAAI,OAAO,MAAM,GAAG;AAChD,YAAM,QAAQ,cAAc,WAAW,WAAW,MAAM,MAAM,GAAG,IAAI;AACrE,UAAI,CAAC,MAAM,QAAQ;AAClB,eAAO,KAAK,WAAW,6EAA6E;AAAA,MACrG;AAEA,YAAM,UAAU,cAAc,eAAe,MAAM;AACnD,UAAI,QAAQ;AAAK,eAAO,KAAK,WAAW,QAAQ,GAAG;AAEnD,UAAI,CAAC,KAAK,SAAS;AAAW,aAAK,SAAS,YAAY,CAAC;AAEzD,WAAK,SAAS,UAAU,KAAK;AAAA,QAC5B;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB,aAAa,KAAK;AAAA,QAClB,eAAe,KAAK;AAAA,QACpB,UAAW,KAAK,IAAI,SAAS,SAAS,IAAI,YAAY;AAAA,MACvD,CAAC;AAAA,IACF;AACA,SAAK,iBAAiB,GAAG,KAAK,+CAA+C;AAE7E,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,QAAQ,QAAQ,MAAM,MAAM;AAC3B,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,UAAM,KAAK,SAAS,MAAM;AAG1B,QAAI,CAAC,KAAK,SAAS,aAAa,MAAM,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,SAAS,UAAU;AAAQ,aAAO;AAEpG,UAAM,UAAU,KAAK,SAAS,UAAU,OAAO,IAAI,CAAC,EAAE,CAAC;AACvD,SAAK,iBAAiB,GAAG,KAAK,iDAAiD,QAAQ,MAAM,IAAI,OAAK,EAAE,EAAE,EAAE,KAAK,IAAI,oBAAoB;AACzI,SAAK,UAAU,2BAA2B,YAAY,KAAK,SAAS,WAAW,MAAM,IAAI,GAAG;AAE5F,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,UAAU,QAAQ,MAAM,MAAM;AAC7B,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,QAAI,CAAC,KAAK,aAAa;AAAG,aAAO;AAEjC,SAAK,UAAU,qBAAqB,YAAY,KAAK,SAAS,WAAW,MAAM,MAAM,KAAK,YAAY,GAAG;AAAA,EAC1G;AAAA,EAEA,KAAK,QAAQ,MAAM,MAAM;AACxB,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,QAAI,CAAC,KAAK,SAAS,WAAW,QAAQ;AACrC,aAAO,KAAK,WAAW,8CAA8C;AAAA,IACtE;AACA,QAAI,KAAK;AAAM,aAAO,KAAK,WAAW,0CAA0C,KAAK,KAAK,QAAQ;AAElG,UAAM,SAAS,SAAS,MAAM,KAAK;AAEnC,QAAI,CAAC,KAAK,SAAS,UAAU,MAAM;AAAG,aAAO;AAE7C,UAAM,OAAO,KAAK,SAAS,UAAU,OAAO,QAAQ,CAAC,EAAE,CAAC;AACxD,SAAK,OAAO,IAAI;AAAA,MACf;AAAA,MACA,EAAC,IAAI,KAAK,aAAa,MAAM,KAAK,cAAa;AAAA,MAC/C,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACN;AAEA,QAAI;AAAQ,WAAK,UAAU,2BAA2B,YAAY,KAAK,SAAS,WAAW,MAAM,IAAI,GAAG;AACxG,SAAK,OAAO,YAAY,MAAM,0BAA0B,KAAK,MAAM,IAAI,OAAK,EAAE,EAAE,GAAG;AAGnF,SAAK,aAAa;AAAA,EACnB;AAAA,EAEA,aAAa;AAAA,EACb,aAAa,QAAQ,MAAM,MAAM;AAChC,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAGhC,QAAI,CAAC,KAAK,SAAS;AAAc,WAAK,SAAS,eAAe,CAAC;AAC/D,UAAM,QAAQ,KAAK,QAAQ;AAC3B,SAAK,KAAK,SAAS,aAAa,qBAAqB,WAAW,OAAO;AACtE,aAAO,KAAK,WAAW,wBAAwB,QAAQ,aAAa,YAAY;AAAA,IACjF;AAEA,SAAK,SAAS,aAAa,oBAAoB;AAC/C,SAAK,aAAa;AAElB,SAAK,UAAU,2BAA2B,YAAY,KAAK,SAAS,WAAW,MAAM,IAAI,GAAG;AAC5F,SAAK,iBAAiB,sBAAsB,QAAQ,aAAa,gBAAgB,KAAK,OAAO;AAC7F,SAAK,OAAO,cAAc,MAAO,QAAQ,aAAa,SAAU;AAAA,EACjE;AAAA,EAEA,aAAa,QAAQ,MAAM,MAAM;AAChC,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,WAAW,MAAM,IAAI;AAEnC,QAAI,CAAC,KAAK,SAAS;AAAc,WAAK,SAAS,eAAe,CAAC;AAC/D,QAAI,CAAC,QAAQ;AACZ,YAAM,kBAAkB,KAAK,SAAS,aAAa,oBAAoB;AACvE,aAAO,KAAK,UAAU,oDAAoD,0BAA0B;AAAA,IACrG;AACA,UAAM,WAAW,SAAS,MAAM;AAEhC,QAAI,CAAC,YAAY,WAAW,GAAG;AAC9B,aAAO,KAAK,WAAW,qEAAqE;AAAA,IAC7F;AAEA,SAAK,SAAS,aAAa,mBAAmB;AAC9C,SAAK,aAAa;AAClB,SAAK,iBAAiB,+CAA+C,uBAAuB,KAAK,OAAO;AACxG,SAAK,OAAO,sBAAsB,MAAM,GAAG,kBAAkB;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,QAAQ,MAAM,MAAM;AAC7B,WAAO,KAAK,YAAY,YAAsB;AAC9C,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,WAAW,KAAK,MAAM,CAAC,CAAC;AAC9B,UAAM,SAAS,SAAS,MAAM,CAAC,CAAC;AAEhC,QAAI,CAAC,YAAY,aAAa,iBAAiB,SAAS,SAAS;AAAI,aAAO,KAAK,WAAW,mBAAmB;AAC/G,QAAI,CAAC,UAAU,SAAS,KAAK,SAAS;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAElH,gBAAY,UAAU,UAAU,UAAU,QAAQ,IAAI,EAAE,MAAM;AAE9D,SAAK,iBAAiB,GAAG,sBAAsB,qDAAqD,KAAK,OAAO;AAChH,SAAK,OAAO,kBAAkB,UAAU,KAAK,MAAM;AAAA,EACpD;AAAA,EAEA,aAAa,QAAQ,MAAM,MAAM;AAChC,WAAO,KAAK,YAAY,YAAsB;AAC9C,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,WAAW,KAAK,MAAM,CAAC,CAAC;AAC9B,UAAM,SAAS,SAAS,MAAM,CAAC,CAAC;AAEhC,QAAI,CAAC,YAAY,aAAa,iBAAiB,SAAS,SAAS;AAAI,aAAO,KAAK,WAAW,mBAAmB;AAC/G,QAAI,CAAC,UAAU,SAAS,KAAK,SAAS;AAAM,aAAO,KAAK,WAAW,+CAA+C;AAElH,gBAAY,UAAU,UAAU,UAAU,CAAC,QAAQ,IAAI,EAAE,MAAM;AAE/D,SAAK,iBAAiB,GAAG,KAAK,kBAAkB,sBAAsB,4CAA4C;AAClH,SAAK,OAAO,qBAAqB,UAAU,KAAK,MAAM;AAAA,EACvD;AAAA,EAEA,YAAY,QAAQ,MAAM,MAAM;AAC/B,WAAO,KAAK,YAAY,YAAsB;AAC9C,SAAK,SAAS,WAAW,MAAM,IAAI;AAEnC,gBAAY,MAAM,EAAE,MAAM;AAE1B,SAAK,iBAAiB,GAAG,KAAK,+CAA+C;AAC7E,SAAK,OAAO,kBAAkB;AAAA,EAC/B;AAAA,EACA,KAAK;AAAA,EACL,MAAM,OAAO,QAAQ,MAAM,MAAM;AAChC,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,QAAI,CAAC,KAAK,aAAa;AAAG,aAAO;AAEjC,UAAM,WAAY,CAAC,KAAK,gBAAgB;AACxC,UAAM,YAAa,CAAC,KAAK,gBAAgB,KAAK,QAAQ,MAAM;AAE5D,UAAM,SAAS,MAAM,YAAY,UAAU,QAAQ;AACnD,SAAK;AAAA,MACJ,SAAS,WAAW,WAAW,iKAAiK,OAAO,IAAI,WAAS;AACnN,cAAM,WAAW,KAAM,KAAK,UAAU,KAAK,MAAM,IAAI,CAAC;AACtD,cAAM,UAAU,MAAM,KAAK,QAAQ,UAAU,GAAG;AAChD,YAAI,WAAW;AAAW,iBAAO;AACjC,eAAO,WAAW,MAAM,gBAAiB,UAAU,OAAO,iBAAM,WAAW,MAAM,IAAI,WAAY,MAAM,QAAQ,IAAI,WAAW,iBAAM,WAAW,MAAM,IAAI,eAAe,iBAAM,WAAW,MAAM,IAAI,aAAe,MAAM;AAAA,MACzN,CAAC,EAAE,KAAK,EAAE,sGAC6E,YACtF,QACA,SAAS,YACT,SACA;AAAA,IACF;AAAA,EACD;AAAA,EAEA,MAAM,KAAK,QAAQ,MAAM,MAAM;AAC9B,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,QAAI,CAAC,KAAK,aAAa;AAAG,aAAO;AAEjC,UAAM,WAAW,KAAK,MAAM,KAAK,KAAK;AAEtC,UAAM,OAAO,MAAM,YAAY,UAAU,UAAU,QAAQ;AAC3D,QAAI,CAAC,MAAM;AACV,WAAK,aAAa,SAAS,mEAAmE;AAAA,IAC/F,OAAO;AACN,WAAK,aAAa,iBAAM,aAAa,KAAK,aAAa,KAAK,2CAA2C,KAAK,gBAAgB;AAAA,IAC7H;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,QAAQ,MAAM,MAAM;AAC5B,WAAO,KAAK,YAAY;AACxB,UAAM,YAAY,aAAa,IAAI;AACnC,QAAI,CAAC,WAAW;AACf,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,QAAI,CAAC,KAAK,SAAS;AAAc,WAAK,SAAS,eAAe,CAAC;AAC/D,QAAI,CAAC,QAAQ;AACZ,YAAM,SAAS,CAAC;AAChB,YAAM,SAAS,OAAO,QAAQ,OAAO,OAAO,sBAAsB,KAAK,SAAS,aAAa,eAAe,CAAC,CAAC,CAAC;AAC/G,iBAAW,SAAS,QAAQ;AAC3B,eAAO,KAAK,GAAG,MAAM,CAAC,MAAM,MAAM,CAAC,GAAG;AAAA,MACvC;AACA,aAAO,KAAK,aAAa,kEAAkE,OAAO,KAAK,QAAQ,GAAG;AAAA,IACnH;AAEA,SAAK,SAAS,WAAW,MAAM,IAAI;AAEnC,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,cAAc,SAAS,MAAM,CAAC,CAAC;AACrC,UAAM,WAAW,KAAK,MAAM,CAAC,CAAC;AAC9B,QAAI,CAAC,YAAY,SAAS,QAAQ;AAAG,aAAO,KAAK,WAAW,mCAAmC,iBAAiB;AAEhH,QAAI,MAAM,WAAW,KAAK,cAAc,KAAK,cAAc,KAAM;AAChE,aAAO,KAAK,WAAW,2EAA2E;AAAA,IACnG;AACA,QAAI,CAAC,KAAK,SAAS,aAAa;AAAa,WAAK,SAAS,aAAa,cAAc,CAAC;AACvF,SAAK,SAAS,aAAa,YAAY,QAAQ,IAAI;AAEnD,SAAK,aAAa;AAClB,SAAK,iBAAiB,GAAG,KAAK,iDAAiD,qBAAqB,cAAc;AAClH,SAAK,OAAO,cAAc,MAAM,GAAG,aAAa,aAAa;AAG7D,QAAI,KAAK,UAAU,CAAC,KAAK,WAAW,WAAW;AAC9C,gBAAU,OAAO;AAAA,QAChB,QAAQ;AAAA,QACR,UAAU,KAAK;AAAA,QACf,MAAM,GAAG,aAAa;AAAA,MACvB,CAAC;AACD,gBAAU,SAAS,IAAI,KAAK,iDAAiD,qBAAqB,oBAAoB,KAAK,YAAY;AACvI,gBAAU,QAAQ,IAAI,KAAK,iDAAiD,qBAAqB,oBAAoB,KAAK,YAAY;AAAA,IACvI;AAAA,EACD;AAAA,EAEA,cAAc,QAAQ,MAAM,MAAM;AACjC,WAAO,KAAK,YAAY;AACxB,UAAM,YAAY,aAAa,IAAI;AACnC,QAAI,CAAC,WAAW;AACf,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,QAAI,CAAC,KAAK,SAAS;AAAc,WAAK,SAAS,eAAe,CAAC;AAC/D,QAAI,CAAC,QAAQ;AACZ,YAAM,eAAe,OAAO,eAAe,KAAK,KAAK,SAAS,cAAc,YAAY,IACvF,KAAK,SAAS,aAAa,aAAa;AACzC,aAAO,KAAK,UAAU,qDAAqD,eAAe;AAAA,IAC3F;AAEA,SAAK,SAAS,WAAW,MAAM,IAAI;AACnC,UAAM,SAAS,SAAS,MAAM;AAC9B,QAAI,MAAM,MAAM;AAAG,aAAO,KAAK,WAAW,GAAG,yCAAyC;AAEtF,SAAK,SAAS,aAAa,aAAa;AACxC,SAAK,aAAa;AAClB,SAAK,iBAAiB,GAAG,KAAK,0EAA0E,QAAQ;AAChH,SAAK,OAAO,sBAAsB,MAAM,GAAG,QAAQ;AAGnD,QAAI,KAAK,UAAU,CAAC,KAAK,SAAS;AACjC,gBAAU,OAAO;AAAA,QAChB,QAAQ;AAAA,QACR,UAAU,KAAK;AAAA,QACf,MAAM,GAAG,iBAAiB,KAAK;AAAA,MAChC,CAAC;AACD,gBAAU,SAAS,IAAI,KAAK,4EAA4E,eAAe,KAAK,WAAW;AACvI,gBAAU,QAAQ,IAAI,KAAK,4EAA4E,eAAe,KAAK,WAAW;AAAA,IACvI;AAAA,EACD;AAAA,EACA,UAAU,QAAQ,MAAM,MAAM;AAC7B,WAAO,KAAK,YAAY;AACxB,UAAM,YAAY,aAAa,IAAI;AACnC,QAAI,CAAC,WAAW;AACf,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,QAAI,CAAC,KAAK,SAAS;AAAc,WAAK,SAAS,eAAe,CAAC;AAC/D,QAAI,CAAC,QAAQ;AACZ,YAAM,SAAS,CAAC;AAChB,YAAM,SAAS,OAAO,QAAQ;AAAA,QAC7B,GAAG;AAAA,QACH,GAAI,KAAK,SAAS,aAAa,aAAsC,CAAC;AAAA,MACvE,CAAC;AAED,iBAAW,SAAS,QAAQ;AAC3B,eAAO,KAAK,GAAG,MAAM,CAAC,MAAM,MAAM,CAAC,EAAE,IAAI,CAAC,GAAW,MAAc,IAAK,IAAI,MAAO,GAAG,EAAE,KAAK,IAAI,GAAG;AAAA,MACrG;AACA,aAAO,KAAK,aAAa,kDAAkD,OAAO,KAAK,QAAQ,GAAG;AAAA,IACnG;AAEA,SAAK,SAAS,WAAW,MAAM,IAAI;AAEnC,QAAI,CAAC,MAAM,GAAG,SAAS,IAAI,OAAO,MAAM,GAAG;AAC3C,WAAO,KAAK,IAAI;AAChB,QAAI,CAAC,YAAY,SAAS,IAAI;AAAG,aAAO,KAAK,WAAW,iCAAiC,aAAa;AACtG,UAAM,YAAY,UAAU,IAAI,OAAK,SAAS,CAAC,CAAC;AAEhD,QAAI,UAAU,KAAK,OAAK,MAAM,CAAC,KAAK,IAAI,KAAK,IAAI,GAAI,KAAK,CAAC,UAAU,QAAQ;AAC5E,aAAO,KAAK,WAAW,8FAA8F;AAAA,IACtH;AAEA,QAAI,CAAC,KAAK,SAAS,aAAa;AAAW,WAAK,SAAS,aAAa,YAAY,CAAC;AACnF,SAAK,SAAS,aAAa,UAAU,IAAI,IAAI;AAE7C,SAAK,aAAa;AAClB,UAAM,gBAAgB,UAAU,IAAI,CAAC,GAAG,MAAM,IAAK,IAAI,MAAO,GAAG,EAAE,KAAK,IAAI;AAC5E,SAAK,iBAAiB,GAAG,KAAK,+CAA+C,6BAA6B,eAAe;AACzH,SAAK,OAAO,kBAAkB,MAAM,GAAG,SAAS,eAAe;AAG/D,QAAI,KAAK,UAAU,CAAC,KAAK,SAAS;AACjC,gBAAU,OAAO;AAAA,QAChB,QAAQ;AAAA,QACR,UAAU,KAAK;AAAA,QACf,MAAM,GAAG,wBAAwB,KAAK;AAAA,MACvC,CAAC;AACD,gBAAU,SAAS,IAAI,KAAK,+CAA+C,6BAA6B,sBAAsB,KAAK,WAAW;AAC9I,gBAAU,QAAQ,IAAI,KAAK,+CAA+C,6BAA6B,sBAAsB,KAAK,WAAW;AAAA,IAC9I;AAAA,EACD;AAAA,EAEA,YAAY;AAAA,EACZ,SAAS,QAAQ,MAAM,MAAM;AAC5B,WAAO,KAAK,YAAY;AACxB,UAAM,YAAY,aAAa,IAAI;AACnC,QAAI,CAAC,WAAW;AACf,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,QAAI,KAAK,IAAI,SAAS,OAAO;AAAG,eAAS;AAEzC,QAAI,CAAC,KAAK,SAAS;AAAc,WAAK,SAAS,eAAe,CAAC;AAC/D,QAAI,CAAC,QAAQ;AACZ,YAAM,QAAQ,KAAK,SAAS,aAAa,iBAAiB;AAC1D,aAAO,KAAK,aAAa,kCAAkC,OAAO;AAAA,IACnE;AACA,SAAK,SAAS,WAAW,MAAM,IAAI;AACnC,QAAI,WAAW,SAAS;AACvB,WAAK,SAAS,aAAa,gBAAgB;AAAA,IAC5C,OAAO;AACN,YAAM,QAAQ,KAAK,MAAM;AACzB,UAAI,CAAC,gCAAS,OAAO,KAAK,KAAK,UAAU;AAAe,eAAO,KAAK,WAAW,gBAAgB;AAE/F,WAAK,SAAS,aAAa,gBAAgB;AAC3C,WAAK,aAAa;AAAA,IACnB;AAEA,QAAI,KAAK,SAAS,aAAa,eAAe;AAC7C,WAAK,iBAAiB,GAAG,KAAK,sCAAsC,KAAK,SAAS,aAAa,eAAe;AAAA,IAC/G,OAAO;AACN,WAAK,iBAAiB,GAAG,KAAK,sCAAsC;AAAA,IACrE;AACA,SAAK,OAAO,cAAc,MAAM,KAAK,SAAS,aAAa,aAAa;AAGxE,QAAI,KAAK,UAAU,CAAC,KAAK,SAAS;AACjC,UAAI,KAAK,SAAS,aAAa,eAAe;AAC7C,kBAAU,OAAO;AAAA,UAChB,QAAQ;AAAA,UACR,UAAU,KAAK;AAAA,UACf,MAAM,GAAG,KAAK,SAAS,aAAa,wBAAwB,KAAK;AAAA,QAClE,CAAC;AACD,kBAAU,SAAS,IAAI,KAAK,wCAAwC,KAAK,SAAS,aAAa,sBAAsB,KAAK,WAAW;AACrI,kBAAU,QAAQ,IAAI,KAAK,yCAAyC,KAAK,SAAS,aAAa,sBAAsB,KAAK,WAAW;AAAA,MACtI,OAAO;AACN,kBAAU,SAAS,IAAI,KAAK,0CAA0C,KAAK,WAAW;AACtF,kBAAU,QAAQ,IAAI,KAAK,0CAA0C,KAAK,WAAW;AAAA,MACtF;AAAA,IACD;AAAA,EACD;AAAA,EAEA,OAAO,QAAQ,MAAM,MAAM;AAC1B,WAAO,KAAK,YAAY;AACxB,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,QAAI,CAAC,KAAK,aAAa;AAAG,aAAO;AAEjC,QAAI,SAAS;AACb,cAAU,OAAO,OAAO,gCAAS,MAAM,EAAE,IAAI,WAC5C,iBAAM,qCAAqC,MAAM,sCAAsC,MAAM,gBAC7F,EAAE,KAAK,EAAE;AACV,cAAU;AAEV,SAAK,UAAU,4CAA4C,cAAc;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AAAA,EACX,MAAM,SAAS,QAAQ,MAAM,MAAM;AAClC,WAAO,KAAK,YAAY,YAAsB;AAC9C,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,QAAI,WAAW,SAAS;AACvB,WAAK,SAAS,WAAW,MAAM,IAAI;AACnC,YAAM,gBAAgB,UAAU;AAChC,sBAAgB,MAAM;AACtB,WAAK,iBAAiB,GAAG,KAAK,8DAA8D;AAC5F,WAAK,OAAO,iBAAiB,MAAM,OAAO;AAC1C;AAAA,IACD,WAAW,WAAW,cAAc;AACnC,WAAK,SAAS,WAAW,MAAM,IAAI;AACnC,sBAAgB,UAAU,EAAE,MAAM;AAClC,WAAK,iBAAiB,GAAG,KAAK,+CAA+C;AAC7E,WAAK,OAAO,iBAAiB,MAAM,YAAY;AAC/C;AAAA,IACD;AAEA,QAAI,CAAC,YAAY,aAAa,IAAI,OAAO,MAAM,GAAG;AAElD,UAAM,gBAAgB,CAAC,UAAU,mBAAmB;AAEpD,QAAI,CAAC,cAAc,SAAS,UAAU;AAAG,mBAAa;AAEtD,UAAM,OAAO,MAAM,gBAAgB,UAAU,UAAU;AACvD,SAAK;AAAA,MACJ,IAAI,gBAAgB,gBAAgB,4NACnC,KAAK,IAAI,WAAS;AACjB,cAAM,OAAO,KAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC,EAAE,KAAK;AACnD,cAAM,QAAQ,OAAO,YAAY;AACjC,eAAO,WAAW,MAAM,oCAAoC,UAAU,QAAQ,kBAAkB,iBAAM,WAAW,MAAM,IAAI,wCACvF,MAAM,UAAU,wCAChB,MAAM,mBAAmB,KAAK,uCAChC,MAAM,gBAAgB,IAAI,+BAA+B,MAAM,gBAAgB,EAAE,KAAK,IAAI,eAAe;AAAA,MAE5I,CAAC,EAAE,KAAK,EAAE,kDAEV,cAAc;AAAA,QACb,OAAK,wBAAwB,MAAM,aAAa,cAAc,yCAAyC,SAAS;AAAA,MACjH,EAAE,KAAK,GAAG;AAAA,IAEZ;AAAA,EACD;AAAA,EAEA,MAAM,SAAS,QAAQ,MAAM,MAAM;AAClC,WAAO,KAAK,YAAY,YAAsB;AAC9C,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,QAAI,WAAW,SAAS;AACvB,WAAK,SAAS,WAAW,MAAM,IAAI;AACnC,YAAM,kBAAkB,UAAU;AAClC,wBAAkB,MAAM;AACxB,WAAK,iBAAiB,GAAG,KAAK,gEAAgE;AAC9F,WAAK,OAAO,iBAAiB,MAAM,OAAO;AAC1C;AAAA,IACD,WAAW,WAAW,cAAc;AACnC,WAAK,SAAS,WAAW,MAAM,IAAI;AACnC,wBAAkB,UAAU,EAAE,MAAM;AACpC,WAAK,iBAAiB,GAAG,KAAK,iDAAiD;AAC/E,WAAK,OAAO,iBAAiB,MAAM,YAAY;AAC/C;AAAA,IACD;AAEA,QAAI,CAAC,YAAY,aAAa,IAAI,OAAO,MAAM,GAAG;AAElD,UAAM,gBAAgB,CAAC,QAAQ,mBAAmB,UAAU,qBAAqB,cAAc,uBAAuB;AAEtH,QAAI,CAAC,cAAc,SAAS,UAAU;AAAG,mBAAa;AAEtD,UAAM,OAAO,MAAM,kBAAkB,UAAU,UAAU;AACzD,UAAM,gBAAgB,KAAK,IAAI,OAAK;AAEnC,QAAE,UAAW,EAAE,UAAU,MAAM,EAAE,QAAQ,KAAM,KAAK,QAAQ,CAAC;AAC7D,QAAE,kBAAkB,MAAO,EAAE,mBAAmB,KAAK,MAAM,EAAE,iBAAiB,KAAK,KAAM,KAAK,QAAQ,CAAC;AACvG,aAAO;AAAA,IACR,CAAC;AAED,SAAK;AAAA,MACJ,IAAI,gBAAgB,gBAAgB,wOACnC,cAAc,IAAI,WAAS;AAC1B,cAAM,OAAO,KAAM,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC,EAAE,KAAK;AACnD,cAAM,QAAQ,OAAO,YAAY;AAEjC,eAAO,WAAW,MAAM,oCAAoC,UAAU,QAAQ,kBAAkB,iBAAM,WAAW,MAAM,IAAI,wCACvF,MAAM,UAAU,gCAAkC,MAAM,mBAAmB,KAAK,YAAc,MAAM,gBAAgB,IAAI,6CAA6C,MAAM,gBAAgB,EAAE,KAAK,IAAI,cAAc,yCACpN,MAAM,QAAQ,gCAAkC,MAAM,iBAAiB,KAAK,YAAc,MAAM,cAAc,IAAI,6CAA6C,MAAM,cAAc,EAAE,KAAK,IAAI,cAAc,yCAC7M,MAAM,0CAA2C,MAAM,kBAAkB,KAAK,sDAC7E,MAAM,cAAc,gCAAkC,MAAM,uBAAuB,KAAK,YAAc,MAAM,oBAAoB,IAAI,6CAA6C,MAAM,oBAAoB,EAAE,KAAK,IAAI,cAAc;AAAA,MAEzQ,CAAC,EAAE,KAAK,EAAE,kDAEV,cAAc;AAAA,QACb,OAAK,wBAAwB,MAAM,aAAa,cAAc,yCAAyC,SAAS;AAAA,MACjH,EAAE,KAAK,GAAG;AAAA,IAEZ;AAAA,EACD;AAAA,EAEA,WAAW;AAAA,EACX,QAAQ,QAAQ,MAAM,MAAM;AAC3B,WAAO,KAAK,YAAY,YAAsB;AAC9C,SAAK,SAAS,QAAQ,MAAM,IAAI;AAEhC,UAAM,WAAW,KAAK,MAAM;AAC5B,QAAI,CAAC;AAAU,aAAO,KAAK,WAAW,0CAA0C,KAAK,MAAM;AAC3F,UAAM,SAAS,KAAK,QAAQ,YAAY,IAAI;AAE5C,sBAAkB,UAAU,UAAU,cAAc,QAAQ,IAAI,EAAE,MAAM;AAExE,SAAK,iBAAiB,GAAG,KAAK,YAAa,SAAS,IAAI,UAAU,gCAAkC,SAAS,IAAI,OAAO,WAAY,YAAY;AAChJ,SAAK,OAAO,QAAQ,KAAK,IAAI,YAAY,KAAK,IAAI;AAAA,EACnD;AAAA,EAEA,aAAa;AAAA,IACZ,IAAI;AAAA,IACJ,SAAS,QAAQ,MAAM,MAAM;AAC5B,aAAO,KAAK,YAAY;AACxB,UAAI,CAAC,aAAa,IAAI;AAAG,eAAO;AAChC,WAAK,SAAS,WAAW,MAAM,IAAI;AACnC,YAAM,WAAW,KAAK,SAAS,cAAc,WAAW,CAAC;AAEzD,WAAK,UAAU,SAAS,KAAK,QAAQ,WAAW,WAAW,2OAC+E,SAAS,UAAU,OAAO,aAC3J;AAAA,IACV;AAAA,IAEA,UAAU,QAAQ,MAAM,MAAM;AAC7B,aAAO,KAAK,YAAY;AACxB,UAAI,CAAC,aAAa,IAAI;AAAG,eAAO;AAChC,WAAK,SAAS,WAAW,MAAM,IAAI;AAEnC,UAAI,CAAC,KAAK,SAAS;AAAc,aAAK,SAAS,eAAe,CAAC;AAC/D,YAAM,WAAW,KAAK,SAAS,aAAa,WAAW,CAAC;AACxD,eAAS,KAAK,MAAM;AAEpB,YAAM,UAAkC;AAAA,QACvC,MAAM;AAAA,QACN,OAAO;AAAA,QACP,UAAU,CAAC,SAAS;AAAA,MACrB;AAEA,UAAI,EAAE,UAAU;AAAU,eAAO,KAAK,UAAU,mCAAmC;AAEnF,eAAS,UAAU,QAAQ,MAAM;AACjC,WAAK,SAAS,aAAa,UAAU;AAErC,WAAK,aAAa;AAElB,WAAK,iBAAiB,GAAG,KAAK,qDAAqD,QAAQ,MAAM,IAAI,OAAO,QAAQ;AACpH,WAAK,OAAO,4BAA4B,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK;AAE5E,aAAO,KAAK,MAAM,0BAA0B;AAAA,IAC7C;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAAQ,MAAM,MAAM;AACjC,WAAO,KAAK,YAAY;AACxB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,QAAI,CAAC,aAAa,IAAI,GAAG;AACxB,aAAO,KAAK,WAAW,2EAA2E;AAAA,IACnG;AAEA,QAAI;AACJ,KAAC,KAAK,MAAM,IAAI,iBAAM,WAAW,QAAQ,GAAG;AAC5C,UAAM,KAAK,GAAG;AAEd,QAAI,CAAC,CAAC,WAAW,QAAQ,cAAc,WAAW,cAAc,WAAW,EAAE,SAAS,GAAG,GAAG;AAC3F,aAAO,KAAK,MAAM,oBAAoB;AAAA,IACvC;AAEA,QAAI,QAAQ,WAAW;AACtB,UAAI,CAAC;AAAQ,eAAO,KAAK,WAAW,UAAU,eAAe;AAE7D,YAAM,CAAC,YAAY,GAAG,SAAS,IAAI,OAAO,MAAM,GAAG;AACnD,YAAM,QAAQ,cAAc,WAAW,WAAW,MAAM,MAAM,GAAG,MAAM,IAAI;AAC3E,UAAI,CAAC,MAAM,QAAQ;AAClB,eAAO,KAAK,WAAW,6BAA6B;AAAA,MACrD;AAEA,YAAM,SAAS,cAAc,eAAe,SAAS;AACrD,UAAI,OAAO;AAAK,eAAO,KAAK,WAAW,OAAO,GAAG;AAEjD,4BAAsB,0BAA0B,OAAO,OAAO,MAAM;AACpE,aAAO,KAAK,iBAAiB,iDAAiD;AAAA,IAC/E;AAGA,QAAI,sBAAsB,QAAQ;AAAG,aAAO,KAAK,WAAW,qCAAqC;AAGjG,QAAI,QAAQ,QAAQ;AACnB,aAAO,KAAK,MAAM,4BAA4B,MAAM;AAAA,IACrD;AAEA,UAAM,SAAS,OAAO,MAAM,GAAG,EAAE,IAAI,WAAS,MAAM,KAAK,CAAC,EAAE,OAAO,WAAS,UAAU,EAAE;AAExF,UAAM,gBAAuC;AAAA,MAC5C,cAAc;AAAA,MACd,WAAW;AAAA,MACX,cAAc;AAAA,MACd,aAAa;AAAA,IACd;AACA,QAAI,CAAC;AAAQ,aAAO,KAAK,WAAW,cAAc,GAAG,CAAC;AAEtD,UAAM,6BAAoD;AAAA,MACzD,cAAc;AAAA,MACd,WAAW;AAAA,MACX,cAAc;AAAA,MACd,aAAa;AAAA,IACd;AACA,QAAI,OAAO,SAAS,2BAA2B,GAAG;AAAG,aAAO,KAAK,WAAW,cAAc,GAAG,CAAC;AAE9F,UAAM,CAAC,YAAY,gBAAgB,UAAU,IAAI,OAAO,IAAI,CAAC,UAAU,SAAS,KAAK,CAAC;AACtF,UAAM,wBAAwB,CAAC,cAAc,cAAc,SAAS;AACpE,QAAI,sBAAsB,SAAS,GAAG,GAAG;AACxC,UAAI,CAAC,sBAAsB,QAAQ,UAAU;AAAG,eAAO,KAAK,WAAW,uCAAuC;AAAA,IAC/G;AAEA,UAAM,4BAA4B,CAAC,WAAW,YAAY;AAC1D,QAAI,0BAA0B,SAAS,GAAG,GAAG;AAC5C,UACC,MAAM,cAAc,KACpB,kBAAkB,KAClB,iBAAiB,eAAe,cAAc,aAAa,CAAC,EAAE,UAAU,QACvE;AACD,eAAO,KAAK,WAAW,2CAA2C;AAAA,MACnE;AAAA,IACD;AAEA,UAAM,wBAAwB,CAAC,YAAY;AAC3C,QAAI,sBAAsB,SAAS,GAAG,GAAG;AACxC,YAAM,eAAe,eAAe,cAAc,aAAa,CAAC,EAAE,UAAU;AAC5E,UAAI,MAAM,cAAc,KAAK,kBAAkB,KAAK,iBAAiB,cAAc;AAClF,eAAO,KAAK,WAAW,uCAAuC;AAAA,MAC/D;AAAA,IACD;AAEA,QAAI,QAAQ,cAAc;AACzB,4BAAsB,+BAA+B,UAAU;AAC/D,aAAO,KAAK,iBAAiB,kBAAkB,2CAA2C;AAAA,IAC3F,WAAW,QAAQ,WAAW;AAC7B,YAAM,WAAW,OAAO,CAAC;AACzB,4BAAsB,sBAAsB,YAAY,gBAAgB,QAAQ;AAChF,aAAO,KAAK,iBAAiB,gCAAgC,wBAAwB,mBAAmB,WAAW;AAAA,IACpH,WAAW,QAAQ,cAAc;AAChC,4BAAsB,yBAAyB,YAAY,gBAAgB,UAAU;AACrF,aAAO,KAAK,iBAAiB,SAAS,8CAA8C,wBAAwB,iBAAiB;AAAA,IAC9H,WAAW,QAAQ,aAAa;AAC/B,UAAI,CAAC,KAAK,SAAS;AAAc,aAAK,SAAS,eAAe,CAAC;AAC/D,UAAI,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,MAAM;AAAO,eAAO,KAAK,WAAW,cAAc,GAAG,CAAC;AACxF,UAAK,OAAO,CAAC,MAAM,SAAU,CAAC,CAAC,KAAK,SAAS,aAAa,sCAAsC;AAC/F,eAAO,KAAK,WAAW,0CAA0C,KAAK,SAAS,aAAa,uCAAuC,OAAO,QAAQ;AAAA,MACnJ;AACA,WAAK,SAAS,aAAa,uCAC1B,CAAC,KAAK,SAAS,aAAa;AAC7B,WAAK,iBAAiB,2DAA2D,KAAK,SAAS,aAAa,uCAAuC,OAAO,OAAO;AACjK,UAAI,OAAO,CAAC,MAAM,MAAM;AACvB,eAAO,KAAK,MAAM,qBAAqB;AAAA,MACxC;AAAA,IACD;AAAA,EACD;AAAA,EAEA,oBAAoB;AACnB,QAAI,CAAC,KAAK,aAAa;AAAG;AAC1B,SAAK,aAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,EAAE,KAAK,OAAO,CAAC;AAAA,EAChB;AACD;AAEO,MAAM,QAAwB;AAAA,EACpC,cAAc,OAAO,MAAM,YAAY;AACtC,SAAK,QAAQ;AACb,UAAM,OAAO,KAAK,YAAY;AAE9B,QAAI,MAAM;AACV,QAAI,CAAC,KAAK;AAAO,aAAO,MAAM;AAC9B,QAAI,CAAC,KAAK;AAAS;AACnB,SAAK,SAAS,QAAQ,MAAM,IAAI;AAChC,WAAO;AACP,WAAO;AACP,eAAW,QAAQ,eAAe,eAAe;AAChD,aAAO;AACP,aAAO,UAAU,KAAK,MAAM,IAAI,CAAC,SAAoB,KAAK,IAAI,EAAE,KAAK,IAAI;AACzE,iBAAW,YAAY,KAAK,WAAW;AACtC,eAAO;AACP,eAAO,YAAY,SAAS;AAC5B,eAAO;AACP,eAAO;AACP,mBAAW,UAAU,SAAS,SAAS;AACtC,iBAAO,OAAO;AAAA,QACf;AACA,eAAO;AAEP,YAAI,SAAS,MAAM,QAAQ;AAC1B,iBAAO;AACP,iBAAO;AACP,qBAAW,QAAQ,SAAS,OAAO;AAClC,mBAAO,OAAO;AAAA,UACf;AACA,iBAAO;AAAA,QACR;AACA,eAAO;AAAA,MACR;AACA,aAAO;AAAA,IACR;AACA,WAAO;AACP,WAAO;AACP,WAAO;AAAA,EACR;AACD;AAEO,MAAM,WAA8B;AAAA;AAAA,EAE1C,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW,kBAAkB;AAAA,EAC7B,eAAe,kBAAkB;AAAA;AAAA,EAGjC,UAAU,kBAAkB;AAAA,EAC5B,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EAEnB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EAEpB,WAAW,kBAAkB;AAAA,EAC7B,UAAU,kBAAkB;AAAA,EAC5B,WAAW,kBAAkB;AAAA,EAC7B,WAAW,kBAAkB;AAAA,EAC7B,kBAAkB,kBAAkB;AAAA,EACpC,cAAc;AAAA,EACd,SAAS,kBAAkB;AAAA,EAC3B,UAAU,kBAAkB;AAAA,EAC5B,UAAU,kBAAkB;AAAA,EAC5B,aAAa,kBAAkB;AAAA,EAC/B,iBAAiB,kBAAkB;AAAA,EACnC,eAAe,kBAAkB;AAAA,EAEjC,UAAU,kBAAkB;AAAA;AAAA,EAG5B,eAAe;AAAA,EACf,qBAAqB,kBAAkB;AAAA,EAEvC,cAAc;AAAA,EACd,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,wBAAwB,kBAAkB;AAAA,EAE1C,aAAa;AAAA,EACb,mBAAmB,kBAAkB;AAAA,EAErC,eAAe,kBAAkB;AAAA,EACjC,mBAAmB,kBAAkB;AAAA,EAErC,UAAU,kBAAkB;AAAA,EAC5B,YAAY;AAAA,EACZ,SAAS,kBAAkB;AAAA,EAC3B,eAAe;AAAA,EACf,UAAU;AAAA,EACV,eAAe,QAAQ,MAAM,MAAM;AAClC,QAAI,CAAC,QAAQ,CAAC,aAAa,IAAI,GAAG;AACjC,aAAO,KAAK,WAAW,uDAAuD;AAAA,IAC/E;AACA,QAAI,CAAC,KAAK,aAAa;AAAG,aAAO;AAEjC,UAAM,eAAe;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,EAAE,KAAK,QAAQ;AACf,UAAM,gBAAgB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,EAAE,KAAK,QAAQ;AAEf,UAAM,gBAAgB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD,EAAE,KAAK,QAAQ;AAEf,aAAS,KAAK,MAAM;AAEpB,UAAM,UAAU,WAAW,QAC1B,GAAG,2BAA2B,4BAA4B,kBAEzD,WAAW,WAAW,WAAW,SAAS,gBAC1C,WAAW,WAAW,WAAW,SAAS,gBAAgB;AAG5D,SAAK,aAAa,OAAO;AAAA,EAC1B;AACD;", "names": [] }