diff --git a/index.js b/index.js index e644058..f3792fa 100644 --- a/index.js +++ b/index.js @@ -190,6 +190,40 @@ const balanceArrays = (a1, a2) => { return [modArr1, modArr2]; }; +const storeFk = async (idArr) => { + // store fk history to avoid repeats + if (!idArr || typeof idArr !== "object") + return console.error("Cannot store fk history"); + if (!fs.existsSync("fk.json")) { + fs.writeFileSync("fk.json", "[]"); + } + let fkHistory = JSON.parse(fs.readFileSync("fk.json")); + + // add to history + fkHistory.push(idArr); + if (fkHistory.length > 10) fkHistory.shift(); + try { + fs.writeFileSync("fk.json", JSON.stringify(fkHistory)); + } catch (error) { + console.error(error); + } + return; +}; + +const getPastFk = async () => { + // get 3 most recent sets of fks to avoid repeats + if (!fs.existsSync("fk.json")) { + fs.writeFileSync("fk.json", "[]"); + } + let fkHistory = JSON.parse(fs.readFileSync("fk.json")); + let recentFk = fkHistory.slice(-3); + + if (!recentFk || typeof recentFk !== "object") + console.error("Invalid fk history"); + if (recentFk.length === 0) return [[], [], []]; + return recentFk; +}; + client.on("ready", () => { console.log(`Logged in as ${client.user.tag}!`); console.log( @@ -312,10 +346,6 @@ client.on("interactionCreate", async (interaction) => { (channel) => channel.name === "red" || channel.id === RED_ID ); if (!red) return console.error("Can't find channel 'red'!"); - const addup = interaction.guild.channels.cache.find( - (channel) => channel.name === "add-up" || channel.id === ADDUP_ID - ); - if (!addup) return console.error("Can't find channel 'add-up'!"); const picking = interaction.guild.channels.cache.find( (channel) => channel.name === "picking" || channel.id === PICKING_ID ); @@ -323,20 +353,14 @@ client.on("interactionCreate", async (interaction) => { // get members in voice channel let members = blu.members.concat(red.members); - //if (command !== "resetteams") members = members.concat(addup.members); if (members.size === 0) { - return await interaction.followUp( - `Found no members in ${ - command === "resetteams" ? "blu" : "addup, blu," - } or red` - ); + return await interaction.followUp("Found no members in blu or red"); } - // move members to addup - let idx = 0, - eCount = 0; + let eCount = 0; - const moveToAddup = async (member) => { + // move members to picking + const moveToPicking = async (member) => { try { await member.voice.setChannel(picking); } catch (error) { @@ -345,19 +369,19 @@ client.on("interactionCreate", async (interaction) => { } }; - const moveAllToAddup = async () => { + const moveAllToPicking = async () => { return Promise.all( Array.from(members, async ([memberId, member]) => { - await moveToAddup(member); + await moveToPicking(member); }) ); }; - moveAllToAddup().then(() => + moveAllToPicking().then(() => interaction.followUp( - `Moved members in ${ - command === "resetteams" ? "blu" : "addup, blu," - } and red${eCount > 0 ? ` (error moving ${eCount} members)` : ""}` + `Moved members in blu and red${ + eCount > 0 ? ` (error moving ${eCount} members)` : "" + }` ) ); } @@ -379,6 +403,7 @@ client.on("interactionCreate", async (interaction) => { const pickingPlayers = []; addup.members.forEach((member) => addupPlayers.push(member)); picking.members.forEach((member) => pickingPlayers.push(member)); + if (pickingPlayers.length < addupPlayers.length) { // move all addup into empty picking addup.members.forEach((member) => { @@ -388,20 +413,58 @@ client.on("interactionCreate", async (interaction) => { "Found too few players in picking to fatkid, moved all addup players to picking instead" ); } - let fatkids = []; + + const targetPlayerCount = 3; + if (pickingPlayers.length + addupPlayers.length < targetPlayerCount) { + return await interaction.followUp( + `Can't find enough total players, expected ${targetPlayerCount} (found ${ + pickingPlayers.length + addupPlayers.length + })` + ); + } + + // set up past fk protection + let fatkids = [], + recentFkSets = [], + protectedFk = [], + protectedStr = "", + fkAttempts = 0; + try { + recentFkSets = await getPastFk(); + protectedFk = recentFkSets.flat(); + } catch (error) { + console.error(error); + await interaction.followUp( + "Failed to get history, fk protection may not be applied" + ); + } // select excess players to be sat out - while (pickingPlayers.length + addupPlayers.length > 18) { + while (pickingPlayers.length + addupPlayers.length > targetPlayerCount) { if (pickingPlayers.length === 0) { return await interaction.followUp( "Error: ran out of players in picking to fatkid" ); } + // remove earliest fk sets as attempts become unreasonably high + if (fkAttempts === 100 || fkAttempts === 250 || fkAttempts === 500) { + console.log(`Shifting fk history ${fkAttempts}`); + recentFkSets.shift(); + protectedFk = recentFkSets.flat(); + } + fkAttempts++; const idx = Math.floor(Math.random() * pickingPlayers.length); let fk = await pickingPlayers.splice(idx, 1)[0]; - console.log(fk); + if (protectedFk.includes(fk.id)) { + protectedStr += `${fk.id}, `; + pickingPlayers.push(fk); + continue; + } fatkids.push(fk); } + if (protectedStr.length > 0) { + console.log(`Protected fks: ${protectedStr}`); + } let errCount = 0; @@ -415,9 +478,12 @@ client.on("interactionCreate", async (interaction) => { } } + let fkIds = []; + // move players from picking to fatkid for (const fk of fatkids) { try { + fkIds.push(fk.id); await fk.voice.setChannel(addup); } catch (error) { console.error(error); @@ -425,14 +491,25 @@ client.on("interactionCreate", async (interaction) => { } } + // store fatkid history + try { + storeFk(fkIds); + } catch (error) { + console.error(error); + } + interaction.followUp( `Sat out ${fatkids.length} players${ errCount > 0 ? ` (error moving ${errCount} members)` : "" + }${ + fkAttempts > 100 + ? ` (fk protection sets ignored: ${3 - recentFkSets.length}/3)` + : "" }` ); } - if (command === "testfk") { + /*if (command === "testfk") { // debug fk // pull users in addup into picking, then randomly select other users in picking to be sat out until there are 18 in picking await interaction.reply("Randomly choosing fatkids from picking..."); @@ -504,7 +581,7 @@ client.on("interactionCreate", async (interaction) => { errCount > 0 ? ` (error moving ${errCount} members)` : "" }` ); - } + }*/ if (command === "fklist" || command === "listfk") { // moves players in picking to fatkid channel, for use in captain pugs