-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make lottery less random #79
Comments
Your proposed solution to use weighted random selection with weights adjusted based on previous selections seems reasonable. It would allow for more even distribution of selections among participants over time and prevent certain participants from being picked too frequently or too infrequently. As for the implementation, you could create an object to store the current weights for each participant and initialize them with proportional weights based on the number of participants. For example, if you have 15 participants, each would have an initial weight of 1/15. Then, when a participant is chosen, their weight would be cut by 3/4 and their weight would be evenly distributed to the other participants, meaning each of the remaining participants would receive an additional weight of 3/(4*(n-1)), where n is the number of participants remaining after removing the selected participant. When a new participant joins, you would adjust the weights again to allow the newcomer a starting proportional weight. Here's some sample code that implements this approach: const participants = ['Alice', 'Bob', 'Charlie', 'Dave', 'Eve', 'Frank', 'Grace', 'Heidi', 'Ivan', 'Judy', 'Kathy', 'Larry', 'Mallory', 'Nancy', 'Oscar'];
const weights = {};
let remainingParticipants = [...participants];
// Initialize weights with proportional values
remainingParticipants.forEach(p => {
weights[p] = 1 / participants.length;
});
// Function to select a participant
function selectParticipant() {
if (remainingParticipants.length === 0) {
console.log('No participants remaining!');
return null;
}
// Calculate cumulative weights
const cumWeights = {};
let cumWeight = 0;
remainingParticipants.forEach(p => {
cumWeight += weights[p];
cumWeights[p] = cumWeight;
});
// Generate random number in range [0,1)
const rand = Math.random();
// Select participant with corresponding cumulative weight
const selectedParticipant = remainingParticipants.find(p => cumWeights[p] > rand * cumWeight);
// Update weights
remainingParticipants = remainingParticipants.filter(p => p !== selectedParticipant);
const remainingWeight = 3 / (4 * remainingParticipants.length);
remainingParticipants.forEach(p => {
weights[p] += remainingWeight;
});
weights[selectedParticipant] *= 1 / 4;
return selectedParticipant;
} |
A request for a less random picker was brought up after some people out of a group of 15 participants have yet to be picked in the past two months.
Describe the solution you'd like
Have a new list of
weights
per participant. the weights can start proportionally and when a person is chosen, their weight is cut by 3/4 and their weight is evenly distributed to the other participants. When a new participant joins, weights are adjusted to allow the newcomer a starting proportional weight.Describe alternatives you've considered
to start - make sure a person isn't chosen twice in a row by filtering out the previous winners. https://github.com/alwaysbegrowing/telegram-standup-bot/blob/805c853ca284219e69f2780a04c7493ee854210e/pages/api/lib/_lottery.ts#L18
Additional context
Maybe something like this? https://www.npmjs.com/package/random-weighted-choice where everyone but the winner's weight is increased by 1? and newcomer weight is the average of all weights?
The text was updated successfully, but these errors were encountered: