From 4e5ef0d040d81347d9ce80213bb7fd43c9429402 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 15 Jul 2019 16:40:47 -0400 Subject: [PATCH 1/9] Added voting endpoint. --- index.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/index.js b/index.js index 5c3220d..4492d42 100644 --- a/index.js +++ b/index.js @@ -106,6 +106,40 @@ app.get('/api/postVideoSponsorTimes', function (req, res) { }); }); +//voting endpoint +app.get('/api/voteOnSponsorTime', function (req, res) { + let UUID = req.query.UUID; + let userID = req.query.userID; + let type = req.query.type; + + if (UUID == undefined || userID == undefined || type == undefined) { + //invalid request + res.sendStatus(400); + return; + } + + //-1 for downvote, 1 for upvote. Maybe more depending on reputation in the future + let incrementAmount = 0; + + //don't use userID for now, and just add the vote + if (type == 1) { + //upvote + incrementAmount = 1; + } else if (type == 0) { + //downvote + incrementAmount = -1; + } else { + //unrecongnised type of vote + req.sendStatus(400); + return; + } + + db.prepare("UPDATE sponsorTimes SET votes = votes + ? WHERE UUID = ?").run(incrementAmount, UUID); + + //added to db + res.sendStatus(200); +}); + app.get('/database.db', function (req, res) { res.sendFile("./databases/sponsorTimes.db", { root: __dirname }); }); \ No newline at end of file From 22905b6acdd663bd9cf841f86488864af9b1eb63 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 15 Jul 2019 16:54:27 -0400 Subject: [PATCH 2/9] Made the server return a list of UUIDs along with the list of sponsor times. --- index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 4492d42..fe72a4b 100644 --- a/index.js +++ b/index.js @@ -33,8 +33,9 @@ app.get('/api/getVideoSponsorTimes', function (req, res) { let videoID = req.query.videoID; let sponsorTimes = []; + let UUIDs = [] - db.prepare("SELECT startTime, endTime FROM sponsorTimes WHERE videoID = ?").all(videoID, function(err, rows) { + db.prepare("SELECT startTime, endTime, UUID FROM sponsorTimes WHERE videoID = ?").all(videoID, function(err, rows) { if (err) console.log(err); for (let i = 0; i < rows.length; i++) { @@ -42,6 +43,8 @@ app.get('/api/getVideoSponsorTimes', function (req, res) { sponsorTimes[i][0] = rows[i].startTime; sponsorTimes[i][1] = rows[i].endTime; + + UUIDs[i] = rows[i].UUID; } if (sponsorTimes.length == 0) { @@ -49,7 +52,8 @@ app.get('/api/getVideoSponsorTimes', function (req, res) { } else { //send result res.send({ - sponsorTimes: sponsorTimes + sponsorTimes: sponsorTimes, + UUIDs: UUIDs }) } }); From 9ab902dc36858eca5cf4889b5324a7fdd04889ba Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 15 Jul 2019 22:18:35 -0400 Subject: [PATCH 3/9] Added new sqrt formula to decide which sponsor time to give out. --- index.js | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index fe72a4b..62e755f 100644 --- a/index.js +++ b/index.js @@ -33,20 +33,38 @@ app.get('/api/getVideoSponsorTimes', function (req, res) { let videoID = req.query.videoID; let sponsorTimes = []; - let UUIDs = [] + let votes = [] + let UUIDs = []; - db.prepare("SELECT startTime, endTime, UUID FROM sponsorTimes WHERE videoID = ?").all(videoID, function(err, rows) { + db.prepare("SELECT startTime, endTime, votes, UUID FROM sponsorTimes WHERE videoID = ?").all(videoID, function(err, rows) { if (err) console.log(err); for (let i = 0; i < rows.length; i++) { - sponsorTimes[i] = []; + //check if votes are above -2 + if (rows[i].votes < -2) { + //too untrustworthy, just ignore it + continue; + } + sponsorTimes.push([]); + + let index = sponsorTimes.length - 1; - sponsorTimes[i][0] = rows[i].startTime; - sponsorTimes[i][1] = rows[i].endTime; + sponsorTimes[index][0] = rows[i].startTime; + sponsorTimes[index][1] = rows[i].endTime; - UUIDs[i] = rows[i].UUID; + votes[index] = rows[i].votes; + UUIDs[index] = rows[i].UUID; } + if (sponsorTimes.length == 0) { + res.sendStatus(404); + return; + } + + organisedData = getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs); + sponsorTimes = organisedData.sponsorTimes; + UUIDs = organisedData.UUIDs; + if (sponsorTimes.length == 0) { res.sendStatus(404); } else { @@ -146,4 +164,113 @@ app.get('/api/voteOnSponsorTime', function (req, res) { app.get('/database.db', function (req, res) { res.sendFile("./databases/sponsorTimes.db", { root: __dirname }); -}); \ No newline at end of file +}); + + +//This function will find sponsor times that are contained inside of eachother, called similar sponsor times +//Only one similar time will be returned, randomly generated based on the sqrt of votes. +//This allows new less voted items to still sometimes appear to give them a chance at getting votes. +//Sponsor times with less than -2 votes are already ignored before this function is called +function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { + //list of sponsors that are contained inside eachother + let similarSponsors = []; + + for (let i = 0; i < sponsorTimes.length; i++) { + //see if the start time is located between the start and end time of the other sponsor time. + for (let j = 0; j < sponsorTimes.length; j++) { + if (sponsorTimes[j][0] > sponsorTimes[i][0] && sponsorTimes[j][0] < sponsorTimes[i][1]) { + //sponsor j is contained in sponsor i + similarSponsors.push([i, j]); + } + } + } + + let similarSponsorsGroups = []; + //once they have been added to a group, they don't need to be dealt with anymore + let dealtWithSimilarSponsors = []; + + //create lists of all the similar groups (if 1 and 2 are similar, and 2 and 3 are similar, the group is 1, 2, 3) + for (let i = 0; i < similarSponsors.length; i++) { + if (dealtWithSimilarSponsors.includes(i)) { + //dealt with already + continue; + } + + //this is the group of indexes that are similar + let group = similarSponsors[i]; + for (let j = 0; j < similarSponsors.length; j++) { + if (group.includes(similarSponsors[j][0]) || group.includes(similarSponsors[j][1])) { + //this is a similar group + group.push(similarSponsors[j][0]); + group.push(similarSponsors[j][1]); + dealtWithSimilarSponsors.push(j); + } + } + similarSponsorsGroups.push(group); + } + + //remove duplicate indexes in group arrays + for (let i = 0; i < similarSponsorsGroups.length; i++) { + uniqueArray = similarSponsorsGroups[i].filter(function(item, pos, self) { + return self.indexOf(item) == pos; + }); + + similarSponsorsGroups[i] = uniqueArray; + } + + let finalSponsorTimeIndexes = []; + //the sponsor times either chosen to be added to finalSponsorTimeIndexes or chosen not to be added + let finalSponsorTimeIndexesDealtWith = []; + + for (let i = 0; i < similarSponsorsGroups.length; i++) { + let sqrtVotesList = []; + let totalSqrtVotes = 0; + for (let j = 0; j < similarSponsorsGroups[i].length; j++) { + let sqrtVote = Math.sqrt(votes[similarSponsorsGroups[i][j]]); + sqrtVotesList.push(sqrtVote) + totalSqrtVotes += sqrtVote; + + //this index has now been deat with + finalSponsorTimeIndexesDealtWith.push(similarSponsorsGroups[i][j]); + } + + let randomNumber = Math.random(); + //this array will keep adding to this variable each time one sqrt vote has been dealt with + //this is the sum of all the sqrtVotes under this index + let currentVoteNumber = 0; + for (let j = 0; j < sqrtVotesList.length; j++) { + if (randomNumber > currentVoteNumber / totalSqrtVotes && randomNumber < (currentVoteNumber + sqrtVotesList[j]) / totalSqrtVotes) { + //this one was randomly generated + finalSponsorTimeIndexes.push(similarSponsorsGroups[i][j]); + break; + } + + //add on to the count + currentVoteNumber += sqrtVotesList[j]; + } + } + + //find the indexes never dealt with and add them + for (let i = 0; i < sponsorTimes.length; i++) { + if (!finalSponsorTimeIndexesDealtWith.includes(i)) { + finalSponsorTimeIndexes.push(i) + } + } + + //convert this to a final array to return + let finalSponsorTimes = []; + for (let i = 0; i < finalSponsorTimeIndexes.length; i++) { + finalSponsorTimes.push(sponsorTimes[finalSponsorTimeIndexes[i]]); + } + + //convert this to a final array of UUIDs as well + let finalUUIDs = []; + for (let i = 0; i < finalSponsorTimeIndexes.length; i++) { + finalUUIDs.push(UUIDs[finalSponsorTimeIndexes[i]]); + } + + return { + sponsorTimes: finalSponsorTimes, + UUIDs: finalUUIDs + }; +} \ No newline at end of file From ab3facdbcf831aeb104d152a55581148104ad18c Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 15 Jul 2019 22:25:22 -0400 Subject: [PATCH 4/9] Changed to point of convergence to 10. This can be changed if this service gets popular. --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 62e755f..0a5b501 100644 --- a/index.js +++ b/index.js @@ -226,7 +226,9 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { let sqrtVotesList = []; let totalSqrtVotes = 0; for (let j = 0; j < similarSponsorsGroups[i].length; j++) { - let sqrtVote = Math.sqrt(votes[similarSponsorsGroups[i][j]]); + //multiplying by 10 makes the 10 votes the point where it the votes start not mattering as much + //this can be changed if this system increases in popularity. + let sqrtVote = Math.sqrt(votes[similarSponsorsGroups[i][j]] * 10); sqrtVotesList.push(sqrtVote) totalSqrtVotes += sqrtVote; From a4affb9e4d85cb847e7492f496680b4e94551296 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 15 Jul 2019 22:32:08 -0400 Subject: [PATCH 5/9] Made it so that -2 to 0 votes has a chance in the randomizer. --- index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 0a5b501..cf96cce 100644 --- a/index.js +++ b/index.js @@ -226,9 +226,11 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { let sqrtVotesList = []; let totalSqrtVotes = 0; for (let j = 0; j < similarSponsorsGroups[i].length; j++) { - //multiplying by 10 makes the 10 votes the point where it the votes start not mattering as much + //multiplying by 10 makes around 13 votes the point where it the votes start not mattering as much (10 + 3) + //The 3 makes -2 the minimum votes before being ignored completely + //https://www.desmos.com/calculator/ljftxolg9j //this can be changed if this system increases in popularity. - let sqrtVote = Math.sqrt(votes[similarSponsorsGroups[i][j]] * 10); + let sqrtVote = Math.sqrt((votes[similarSponsorsGroups[i][j]] + 3) * 10); sqrtVotesList.push(sqrtVote) totalSqrtVotes += sqrtVote; From 5c24a6109c9784f4610c7861d6bf55c2d67c2989 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 16 Jul 2019 22:51:17 -0400 Subject: [PATCH 6/9] Moved weighted random into separate function. --- index.js | 81 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/index.js b/index.js index cf96cce..c21a89d 100644 --- a/index.js +++ b/index.js @@ -218,41 +218,11 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { similarSponsorsGroups[i] = uniqueArray; } - let finalSponsorTimeIndexes = []; + let weightedRandomIndexes = getWeightedRandom(similarSponsorsGroups, votes); + + let finalSponsorTimeIndexes = weightedRandomIndexes.finalIndexes; //the sponsor times either chosen to be added to finalSponsorTimeIndexes or chosen not to be added - let finalSponsorTimeIndexesDealtWith = []; - - for (let i = 0; i < similarSponsorsGroups.length; i++) { - let sqrtVotesList = []; - let totalSqrtVotes = 0; - for (let j = 0; j < similarSponsorsGroups[i].length; j++) { - //multiplying by 10 makes around 13 votes the point where it the votes start not mattering as much (10 + 3) - //The 3 makes -2 the minimum votes before being ignored completely - //https://www.desmos.com/calculator/ljftxolg9j - //this can be changed if this system increases in popularity. - let sqrtVote = Math.sqrt((votes[similarSponsorsGroups[i][j]] + 3) * 10); - sqrtVotesList.push(sqrtVote) - totalSqrtVotes += sqrtVote; - - //this index has now been deat with - finalSponsorTimeIndexesDealtWith.push(similarSponsorsGroups[i][j]); - } - - let randomNumber = Math.random(); - //this array will keep adding to this variable each time one sqrt vote has been dealt with - //this is the sum of all the sqrtVotes under this index - let currentVoteNumber = 0; - for (let j = 0; j < sqrtVotesList.length; j++) { - if (randomNumber > currentVoteNumber / totalSqrtVotes && randomNumber < (currentVoteNumber + sqrtVotesList[j]) / totalSqrtVotes) { - //this one was randomly generated - finalSponsorTimeIndexes.push(similarSponsorsGroups[i][j]); - break; - } - - //add on to the count - currentVoteNumber += sqrtVotesList[j]; - } - } + let finalSponsorTimeIndexesDealtWith = weightedRandomIndexes.indexesDealtWith; //find the indexes never dealt with and add them for (let i = 0; i < sponsorTimes.length; i++) { @@ -277,4 +247,47 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { sponsorTimes: finalSponsorTimes, UUIDs: finalUUIDs }; +} + +function getWeightedRandom(indexes, weights) { + let finalIndexes = []; + //the indexes either chosen to be added to final indexes or chosen not to be added + let indexesDealtWith = []; + + for (let i = 0; i < indexes.length; i++) { + let sqrtVotesList = []; + let totalSqrtVotes = 0; + for (let j = 0; j < indexes[i].length; j++) { + //multiplying by 10 makes around 13 votes the point where it the votes start not mattering as much (10 + 3) + //The 3 makes -2 the minimum votes before being ignored completely + //https://www.desmos.com/calculator/ljftxolg9j + //this can be changed if this system increases in popularity. + let sqrtVote = Math.sqrt((weights[indexes[i][j]] + 3) * 10); + sqrtVotesList.push(sqrtVote) + totalSqrtVotes += sqrtVote; + + //this index has now been deat with + indexesDealtWith.push(indexes[i][j]); + } + + let randomNumber = Math.random(); + //this array will keep adding to this variable each time one sqrt vote has been dealt with + //this is the sum of all the sqrtVotes under this index + let currentVoteNumber = 0; + for (let j = 0; j < sqrtVotesList.length; j++) { + if (randomNumber > currentVoteNumber / totalSqrtVotes && randomNumber < (currentVoteNumber + sqrtVotesList[j]) / totalSqrtVotes) { + //this one was randomly generated + finalIndexes.push(indexes[i][j]); + break; + } + + //add on to the count + currentVoteNumber += sqrtVotesList[j]; + } + } + + return { + finalIndexes: finalIndexes, + indexesDealtWith: indexesDealtWith + }; } \ No newline at end of file From 24ed3143ed5c915bdda1c33414b04df3da9252ce Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 17 Jul 2019 14:41:10 -0400 Subject: [PATCH 7/9] Uses weighted random to ensure a maximum of 4 sponsor times are returned --- index.js | 98 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/index.js b/index.js index c21a89d..8138a63 100644 --- a/index.js +++ b/index.js @@ -218,7 +218,7 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { similarSponsorsGroups[i] = uniqueArray; } - let weightedRandomIndexes = getWeightedRandom(similarSponsorsGroups, votes); + let weightedRandomIndexes = getWeightedRandomChoiceForArray(similarSponsorsGroups, votes); let finalSponsorTimeIndexes = weightedRandomIndexes.finalIndexes; //the sponsor times either chosen to be added to finalSponsorTimeIndexes or chosen not to be added @@ -231,6 +231,9 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { } } + //if there are too many indexes, find the best 4 + finalSponsorTimeIndexes = getWeightedRandomChoice(finalSponsorTimeIndexes, votes, 4).finalIndexes; + //convert this to a final array to return let finalSponsorTimes = []; for (let i = 0; i < finalSponsorTimeIndexes.length; i++) { @@ -249,40 +252,79 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { }; } -function getWeightedRandom(indexes, weights) { +//gets the getWeightedRandomChoice for each group in an array of groups +function getWeightedRandomChoiceForArray(indexGroups, weights) { let finalIndexes = []; //the indexes either chosen to be added to final indexes or chosen not to be added let indexesDealtWith = []; - for (let i = 0; i < indexes.length; i++) { - let sqrtVotesList = []; - let totalSqrtVotes = 0; - for (let j = 0; j < indexes[i].length; j++) { - //multiplying by 10 makes around 13 votes the point where it the votes start not mattering as much (10 + 3) - //The 3 makes -2 the minimum votes before being ignored completely - //https://www.desmos.com/calculator/ljftxolg9j - //this can be changed if this system increases in popularity. - let sqrtVote = Math.sqrt((weights[indexes[i][j]] + 3) * 10); - sqrtVotesList.push(sqrtVote) - totalSqrtVotes += sqrtVote; + for (let i = 0; i < indexGroups.length; i++) { + let randomChoice = getWeightedRandomChoice(indexGroups[i], weights, 1) + finalIndexes.push(randomChoice.finalIndexes); - //this index has now been deat with - indexesDealtWith.push(indexes[i][j]); + for (let j = 0; j < randomChoice.indexesDealtWith.length; j++) { + indexesDealtWith.push(randomChoice.indexesDealtWith[j]) + } + } + + return { + finalIndexes: finalIndexes, + indexesDealtWith: indexesDealtWith + }; +} + +//gets a weighted random choice from the indexes array based on the weights. +//amountOfChoices speicifies the amount of choices to return, 1 or more. +//choices are unique +function getWeightedRandomChoice(indexes, weights, amountOfChoices) { + if (amountOfChoices > indexes.length) { + //not possible, since all choices must be unique + return null; + } + + let finalIndexes = []; + let indexesDealtWith = []; + + let sqrtVotesList = []; + let totalSqrtVotes = 0; + for (let j = 0; j < indexes.length; j++) { + //multiplying by 10 makes around 13 votes the point where it the votes start not mattering as much (10 + 3) + //The 3 makes -2 the minimum votes before being ignored completely + //https://www.desmos.com/calculator/ljftxolg9j + //this can be changed if this system increases in popularity. + let sqrtVote = Math.sqrt((weights[indexes[j]] + 3) * 10); + sqrtVotesList.push(sqrtVote) + totalSqrtVotes += sqrtVote; + + //this index has now been deat with + indexesDealtWith.push(indexes[j]); + } + + //iterate and find amountOfChoices choices + let randomNumber = Math.random(); + //this array will keep adding to this variable each time one sqrt vote has been dealt with + //this is the sum of all the sqrtVotes under this index + let currentVoteNumber = 0; + for (let j = 0; j < sqrtVotesList.length; j++) { + if (randomNumber > currentVoteNumber / totalSqrtVotes && randomNumber < (currentVoteNumber + sqrtVotesList[j]) / totalSqrtVotes) { + //this one was randomly generated + finalIndexes.push(indexes[j]); + //remove that from original array, for next recursion pass if it happens + indexes.splice(j, 1); + break; } - let randomNumber = Math.random(); - //this array will keep adding to this variable each time one sqrt vote has been dealt with - //this is the sum of all the sqrtVotes under this index - let currentVoteNumber = 0; - for (let j = 0; j < sqrtVotesList.length; j++) { - if (randomNumber > currentVoteNumber / totalSqrtVotes && randomNumber < (currentVoteNumber + sqrtVotesList[j]) / totalSqrtVotes) { - //this one was randomly generated - finalIndexes.push(indexes[i][j]); - break; - } - - //add on to the count - currentVoteNumber += sqrtVotesList[j]; + //add on to the count + currentVoteNumber += sqrtVotesList[j]; + } + + //add on the other choices as well using recursion + if (amountOfChoices > 1) { + let otherChoices = getWeightedRandomChoice(indexes, weights, amountOfChoices - 1).finalIndexes; + console.log(otherChoices); + //add all these choices to the finalIndexes array being returned + for (let i = 0; i < otherChoices.length; i++) { + finalIndexes.push(otherChoices[i]); } } From 60c125f4ce425af04fc3c4797ccba838f3f7bbc6 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 17 Jul 2019 14:44:23 -0400 Subject: [PATCH 8/9] Made functions use more generic variable names. --- index.js | 70 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/index.js b/index.js index 8138a63..726a17f 100644 --- a/index.js +++ b/index.js @@ -220,9 +220,9 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { let weightedRandomIndexes = getWeightedRandomChoiceForArray(similarSponsorsGroups, votes); - let finalSponsorTimeIndexes = weightedRandomIndexes.finalIndexes; + let finalSponsorTimeIndexes = weightedRandomIndexes.finalChoices; //the sponsor times either chosen to be added to finalSponsorTimeIndexes or chosen not to be added - let finalSponsorTimeIndexesDealtWith = weightedRandomIndexes.indexesDealtWith; + let finalSponsorTimeIndexesDealtWith = weightedRandomIndexes.choicesDealtWith; //find the indexes never dealt with and add them for (let i = 0; i < sponsorTimes.length; i++) { @@ -232,7 +232,7 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { } //if there are too many indexes, find the best 4 - finalSponsorTimeIndexes = getWeightedRandomChoice(finalSponsorTimeIndexes, votes, 4).finalIndexes; + finalSponsorTimeIndexes = getWeightedRandomChoice(finalSponsorTimeIndexes, votes, 4).finalChoices; //convert this to a final array to return let finalSponsorTimes = []; @@ -253,51 +253,52 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { } //gets the getWeightedRandomChoice for each group in an array of groups -function getWeightedRandomChoiceForArray(indexGroups, weights) { - let finalIndexes = []; +function getWeightedRandomChoiceForArray(choiceGroups, weights) { + let finalChoices = []; //the indexes either chosen to be added to final indexes or chosen not to be added - let indexesDealtWith = []; + let choicesDealtWith = []; - for (let i = 0; i < indexGroups.length; i++) { - let randomChoice = getWeightedRandomChoice(indexGroups[i], weights, 1) - finalIndexes.push(randomChoice.finalIndexes); + for (let i = 0; i < choiceGroups.length; i++) { + let randomChoice = getWeightedRandomChoice(choiceGroups[i], weights, 1) + finalChoices.push(randomChoice.finalChoices); - for (let j = 0; j < randomChoice.indexesDealtWith.length; j++) { - indexesDealtWith.push(randomChoice.indexesDealtWith[j]) + for (let j = 0; j < randomChoice.choicesDealtWith.length; j++) { + choicesDealtWith.push(randomChoice.choicesDealtWith[j]) } } return { - finalIndexes: finalIndexes, - indexesDealtWith: indexesDealtWith + finalChoices: finalChoices, + choicesDealtWith: choicesDealtWith }; } //gets a weighted random choice from the indexes array based on the weights. //amountOfChoices speicifies the amount of choices to return, 1 or more. //choices are unique -function getWeightedRandomChoice(indexes, weights, amountOfChoices) { - if (amountOfChoices > indexes.length) { +function getWeightedRandomChoice(choices, weights, amountOfChoices) { + if (amountOfChoices > choices.length) { //not possible, since all choices must be unique return null; } - let finalIndexes = []; - let indexesDealtWith = []; + let finalChoices = []; + let choicesDealtWith = []; - let sqrtVotesList = []; - let totalSqrtVotes = 0; - for (let j = 0; j < indexes.length; j++) { + let sqrtWeightsList = []; + //the total of all the weights run through the cutom sqrt function + let totalSqrtWeights = 0; + for (let j = 0; j < choices.length; j++) { //multiplying by 10 makes around 13 votes the point where it the votes start not mattering as much (10 + 3) //The 3 makes -2 the minimum votes before being ignored completely //https://www.desmos.com/calculator/ljftxolg9j //this can be changed if this system increases in popularity. - let sqrtVote = Math.sqrt((weights[indexes[j]] + 3) * 10); - sqrtVotesList.push(sqrtVote) - totalSqrtVotes += sqrtVote; + let sqrtVote = Math.sqrt((weights[choices[j]] + 3) * 10); + sqrtWeightsList.push(sqrtVote) + totalSqrtWeights += sqrtVote; //this index has now been deat with - indexesDealtWith.push(indexes[j]); + choicesDealtWith.push(choices[j]); } //iterate and find amountOfChoices choices @@ -305,31 +306,30 @@ function getWeightedRandomChoice(indexes, weights, amountOfChoices) { //this array will keep adding to this variable each time one sqrt vote has been dealt with //this is the sum of all the sqrtVotes under this index let currentVoteNumber = 0; - for (let j = 0; j < sqrtVotesList.length; j++) { - if (randomNumber > currentVoteNumber / totalSqrtVotes && randomNumber < (currentVoteNumber + sqrtVotesList[j]) / totalSqrtVotes) { + for (let j = 0; j < sqrtWeightsList.length; j++) { + if (randomNumber > currentVoteNumber / totalSqrtWeights && randomNumber < (currentVoteNumber + sqrtWeightsList[j]) / totalSqrtWeights) { //this one was randomly generated - finalIndexes.push(indexes[j]); + finalChoices.push(choices[j]); //remove that from original array, for next recursion pass if it happens - indexes.splice(j, 1); + choices.splice(j, 1); break; } //add on to the count - currentVoteNumber += sqrtVotesList[j]; + currentVoteNumber += sqrtWeightsList[j]; } //add on the other choices as well using recursion if (amountOfChoices > 1) { - let otherChoices = getWeightedRandomChoice(indexes, weights, amountOfChoices - 1).finalIndexes; - console.log(otherChoices); - //add all these choices to the finalIndexes array being returned + let otherChoices = getWeightedRandomChoice(choices, weights, amountOfChoices - 1).finalChoices; + //add all these choices to the finalChoices array being returned for (let i = 0; i < otherChoices.length; i++) { - finalIndexes.push(otherChoices[i]); + finalChoices.push(otherChoices[i]); } } return { - finalIndexes: finalIndexes, - indexesDealtWith: indexesDealtWith + finalChoices: finalChoices, + choicesDealtWith: choicesDealtWith }; } \ No newline at end of file From 79fd1fe95e6a6b0dc7943516c6233e3b84ce5530 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Wed, 17 Jul 2019 15:46:38 -0400 Subject: [PATCH 9/9] Made it use the sum of votes from choiceGroups when deciding the top 4. --- index.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 726a17f..5c62dad 100644 --- a/index.js +++ b/index.js @@ -224,6 +224,15 @@ function getVoteOrganisedSponsorTimes(sponsorTimes, votes, UUIDs) { //the sponsor times either chosen to be added to finalSponsorTimeIndexes or chosen not to be added let finalSponsorTimeIndexesDealtWith = weightedRandomIndexes.choicesDealtWith; + let voteSums = weightedRandomIndexes.weightSums; + //convert these into the votes + for (let i = 0; i < voteSums.length; i++) { + if (voteSums[i] != undefined) { + //it should use the sum of votes, since anyone upvoting a similar sponsor is upvoting the existence of that sponsor. + votes[finalSponsorTimeIndexes[i]] = voteSums; + } + } + //find the indexes never dealt with and add them for (let i = 0; i < sponsorTimes.length; i++) { if (!finalSponsorTimeIndexesDealtWith.includes(i)) { @@ -257,8 +266,20 @@ function getWeightedRandomChoiceForArray(choiceGroups, weights) { let finalChoices = []; //the indexes either chosen to be added to final indexes or chosen not to be added let choicesDealtWith = []; + //for each choice group, what are the sums of the weights + let weightSums = []; for (let i = 0; i < choiceGroups.length; i++) { + //find weight sums for this group + weightSums.push(0); + for (let j = 0; j < choiceGroups[i].length; j++) { + //only if it is a positive vote, otherwise it is probably just a sponsor time with slightly wrong time + if (weights[choiceGroups[i][j]] > 0) { + weightSums[weightSums.length - 1] += weights[choiceGroups[i][j]]; + } + } + + //create a random choice for this group let randomChoice = getWeightedRandomChoice(choiceGroups[i], weights, 1) finalChoices.push(randomChoice.finalChoices); @@ -269,7 +290,8 @@ function getWeightedRandomChoiceForArray(choiceGroups, weights) { return { finalChoices: finalChoices, - choicesDealtWith: choicesDealtWith + choicesDealtWith: choicesDealtWith, + weightSums: weightSums }; }