Random number in a range of numbers with pre-defined probabilities

0

I need to create a kind of roulette where a random prize comes out, taking into account:

  • the type of prize, for example 5 different prizes better than others
  • The better the lower the odds of getting out
  • the stock of the prizes, take into account if the prize is still in stock

I was thinking of organizing values like this:

var premios = [
        { 'tipo': 'premio1', 'stock': 40, 'probabilidade': 0.5 },
        { 'tipo': 'premio2', 'stock': 40, 'probabilidade': 0.5 },
        { 'tipo': 'premio3', 'stock': 30, 'probabilidade': 0.4 },
        { 'tipo': 'premio4', 'stock': 10, 'probabilidade': 0.2 },
        { 'tipo': 'premio5', 'stock': 5, 'probabilidade': 0.1 }
    ];

I've been experimenting with several things, I think I got close to a solution but it's not working at 100%, the odds are not right. I'm a little lost, can anyone help?

function RandomProb () {
    var s = 0,
        pcnt = premios.length, 
        num = Math.floor(Math.random() * (1000 - 1 + 1)) + 1;

    for (var i = 0; i < pcnt; ++i) {

        range = premios[i].probabilidade * 1000;

        if (num < 1000-range && premios[i].stock) {
            premios[i].stock--; 
            return premios[i].tipo;
        }
    }
};
    
asked by anonymous 14.09.2016 / 14:01

1 answer

1

After much discussion and thanks to the help of the comments I managed to reach a functional solution:

var premios = [
        { 'tipo': 'premio1', 'stock': 50, 'probabilidade': 5 },
        { 'tipo': 'premio2', 'stock': 40, 'probabilidade': 4 },
        { 'tipo': 'premio3', 'stock': 30, 'probabilidade': 3 },
        { 'tipo': 'premio4', 'stock': 20, 'probabilidade': 2 },
        { 'tipo': 'premio5', 'stock': 10, 'probabilidade': 1 }
    ];


function RandomProb () {

    var aSorteio = [];

    premios = $.grep(premios, function(e){ 
        return e.stock > 0; 
    });

    premios.forEach(function (p,i) { 
            var r = Math.floor(p.probabilidade/1);
            for (var i = 0; i < r; i++) { 
                aSorteio.push(i);
            }
    });

    var g = Math.floor(Math.random() * aSorteio.length),
    p = aSorteio[g];
    if(premios[p]!=undefined){ 
        premios[p].stock--;
        return premios[p].tipo;
    }
};

Then, I noticed that it is not necessary to have the probability value since at the end of the stock the premium will no longer exit. So the final solution looks like this:

var premios = [
        { 'tipo': 'premio1', 'stock': 50 },
        { 'tipo': 'premio2', 'stock': 40 },
        { 'tipo': 'premio3', 'stock': 30 },
        { 'tipo': 'premio4', 'stock': 20 },
        { 'tipo': 'premio5', 'stock': 10 }
    ];


function RandomProb () {

    premios = $.grep(premios, function(e){ 
        return e.stock > 0; 
    });

    var p = Math.floor(Math.random() * premios.length);

    if(premios[p]!=undefined){ 
        premios[p].stock--;
        return premios[p].tipo;
    }
};
    
14.09.2016 / 19:26