Last active
September 22, 2024 16:10
-
-
Save TheNerdMan/2f50288de5c9a9fdccb303f54bef826a to your computer and use it in GitHub Desktop.
A command night bot to output a random value but weight those values so some are rarer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @author=TheNerdMan */ | |
/** | |
* Creates an array of shape [{outputStr: string, weight: number}] | |
* | |
* @param stringArray An array of strings, strings should be formated as such "\<String To Ouput\>, \<weight\>" | |
* an example is ["Foo, 0.5", "Bar, 0.25", "FooBar, 0.25"]. | |
* | |
* Weights must add up to 1.0. | |
*/ | |
function getWeights(stringArray /*: string[]*/) { | |
var recordArray = stringArray.map((c) => { | |
return { outputStr: c.split(",")[0]?.trim(), weight: c.split(",")[1]?.trim() } | |
}); | |
validateWeights(recordArray); | |
return recordArray; | |
} | |
/** | |
* Makes sure weights add up to 1, throws a js error if not. | |
* | |
* @param mappedArray An array of shape [{outputStr: string, weight: number}], | |
*/ | |
function validateWeights(mappedArray /*: [{outputStr: string, weight: number}]*/) { | |
// validate weights add up to 1.0 | |
var weightSum = mappedArray | |
.map((c) => parseFloat(c.weight)) | |
.reduce((a, b) => a + b, 0) | |
weightSum = parseFloat(weightSum.toFixed(1)); | |
// throw error if weights don't add up to 1.0 | |
if (weightSum !== 1.0) throw new Error("Weights must add up to 1.0"); | |
} | |
/** | |
* Creates a "flat" array of ints that map to a index of a value from the weighted array. | |
* | |
* @param mappedArray An array of shape [{outputStr: string, weight: number}] | |
* @example | |
* [{ outputStr: "Foo", weight: 0.5 }, { outputStr: "Bar", weight: 0.25 }, { outputStr: "FooBar", weight: 0.25 }] | |
* outputs | |
* [1,1,1,1,2,2,3,3] | |
*/ | |
function createFlatWeightedArray(mappedArray /*: [{outputStr: string, weight: number}]*/) { | |
// create a "flat" array of ints that map to a index of a value from the weighted array. | |
var flatWeightArray = []; | |
mappedArray.forEach((c) => { | |
var weight = parseFloat(c.weight); | |
var weightCount = Math.floor(weight * 10); | |
for (var i = 0; i < weightCount; i++) { | |
flatWeightArray.push(mappedArray.indexOf(c)); | |
} | |
}); | |
return flatWeightArray; | |
} | |
/** | |
* Gets the list from paste bin using api.allorigins.win to get around cors errors. | |
* If that service goes down then uh oh | |
*/ | |
function retrieveListFromPasteBin(url /*: string*/) { | |
const request = new XMLHttpRequest(); | |
request.open("GET", `https://api.allorigins.win/raw?url=${encodeURIComponent(url)}`, false); // `false` makes the request synchronous | |
request.send(null); | |
if (request.status === 200) { | |
console.log(request.responseText); | |
return request.responseText; | |
} | |
throw new Error(`Request Error: ${request.status}`); | |
} | |
function main(pasteBinUrl /*: string*/) { | |
if (!pasteBinUrl) throw new Error("Paste Bin Url missing"); | |
// get the text | |
var pasteBinText = retrieveListFromPasteBin(pasteBinUrl); | |
// Remove line endings | |
var rawArray = pasteBinText.replace(/(\r\n|\n|\r)/gm, "").split(";"); | |
// Drop the last item if user has put ; on every line | |
if (!rawArray[rawArray.length - 1]) rawArray.pop(); | |
// Get the weights in a nice object | |
var weightedArray = getWeights(rawArray); | |
// now we do some maths to create an array of numbers, counting up to the amount of items we have | |
// but we add more numbers to make choosing a random number weighted to users needs. | |
// e.g. | |
// [{ outputStr: "Foo", weight: 0.5 }, { outputStr: "Bar", weight: 0.25 }, { outputStr: "FooBar", weight: 0.25 }] | |
// becomes | |
// [1,1,1,1,2,2,3,3] | |
var flatWeightArray = createFlatWeightedArray(weightedArray); | |
// now pick from that array, the answer will map to a value in the weighted array; | |
var weightedRandomIndex = flatWeightArray[Math.floor(Math.random() * flatWeightArray.length)] | |
var result = weightedArray[weightedRandomIndex]; | |
return result.outputStr; | |
} | |
main(q) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment