Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pick random value by weight php

Tags:

php

mysql

I'm about to create "lottary system."

Take a look at my table:

userid-lottaryid-amount
1 -------- 1 ----  1
2 -------- 1 ---- 10
3 -------- 1 ---- 15
4 -------- 1 ---- 20

I want to choose a winner. and another person for second place.

I just can't select a winner randomly because 4th user has 20 tickets and 1st user has only one. So I need to generate random results by weight in order to be more fair.

I found php function below but I couldn't figure out how to use it.

      function weighted_random_simple($values, $weights){ 
      $count = count($values); 
      $i = 0; 
      $n = 0; 
      $num = mt_rand(0, array_sum($weights)); 

      while($i < $count){
          $n += $weights[$i]; 
          if($n >= $num){
              break; 
          }
          $i++; 
      } 
      return $values[$i]; 

  }

    $values = array('1', '10', '20', '100');
    $weights = array(1, 10, 20, 100);

    echo weighted_random_simple($values, $weights);

I must fetch userid colomn as array to $values and amount colomn to $weights. But I couln't.

Here is my code so far:

    $query = $handler->prepare("SELECT 

      `cvu`.`lottaryid` as `lottaryid`, 
      `cvu`.`userid` as `userid`, 
      `cvu`.`amount` as `amount`, 

      `members`.`id` as `members_memberid`, 
      `members`.`username` as `username`

      FROM `lottariesandmembers` as `cvu`

      LEFT JOIN `members` as `members` ON `cvu`.`userid` = `members`.`id`  WHERE `cvu`.`lottaryid` = 2");
    $query->bindParam(':lottaryid', $lottaryid, PDO::PARAM_INT);
    $query->execute();



    while($r = $query->fetch()) {

        for ( $count=1 ; $count <= $r["amount"] ; $count++ ) {

            $abcprint = "$r[userid].$count - $r[username] - <br>";

            echo "$abcprint";

        }


    } 

This code I have, only lists users as many times as their amount. For example:

1.1 user1
2.1 user2
2.2 user2
2.3 user2
..
2.10 user2
3.1 user3
..
3.15 user3
4.1 user4
..
4.20 user4

and so on.. But I'm stuck how to pick a winner on that list.

I would like to merge those codes and create this little script, if you would like to help me.

I'm also open for brainstorm if you see the solution on the other way around.

like image 262
Rough Avatar asked Mar 14 '23 20:03

Rough


1 Answers

Instead of printing out the values as you are doing, you can just build a large array, and then choose a value randomly from that array.

while($r = $query->fetch()) {
    for ( $i=0; $i <= $r["amount"]; $i++ ) {
        // Add the user into the array as many times as they have tickets
        $tickets[] = $r['userid'];
    }
}

// select the first place winner
$first = $tickets[mt_rand(0, count($tickets) - 1)];

// remove the first place winner from the array
$tickets = array_values(array_filter($tickets, function($x) use ($first) { 
    return $x != $first; 
}));

// select the second place winner
$second = $tickets[mt_rand(0, count($tickets) - 1)];

I'm sure there is a more efficient way to do this using math, but I need to think about it a bit more...

like image 83
Don't Panic Avatar answered Mar 24 '23 07:03

Don't Panic