Note that there are some explanatory texts on larger screens.

plurals
  1. POPHP Random numbers with weights on two levels
    primarykey
    data
    text
    <p>I have growing number of so called Battles grouped in different Ranks. I want to randomize the battles shown to the user. The show rate to be defined by the Rank at first place (higher rank - more impressions) and the second level is to get a random battle from the collection in this rank. Every battle in the rank has it's own number of impressions.</p> <p>In $battles I get the battles from the DB and i perform some calculations to define the show rate and the impressions that each rank should get.</p> <pre><code>foreach ($battles as $el =&gt; &amp;$values) { $values['show_rate'] = $values['rank'] * 100 / $totals['sum_of_ranks']; $values['dedicated_impressions'] = $totals['total_battle_impressions'] * $values['show_rate'] / 100; $values['impressions_left'] = $values['dedicated_impressions'] - $values['sum_of_impressions']; } </code></pre> <p>This is the result of the previous cycle. In the key <code>battle_ids</code> i have the ids of the battles in this rank, in <code>battle_impressions</code> i have the impressions of the same battles ordered in the same way.</p> <pre><code> $battles = array( 0 =&gt; array( 'battles_in_rank' =&gt; '1', 'battle_ids' =&gt; array( 0 =&gt; '28', ), 'battle_impressions' =&gt; array( 0 =&gt; '3', ), 'sum_of_impressions' =&gt; '3', 'rank' =&gt; '0', 'show_rate' =&gt; 0, 'dedicated_impressions' =&gt; 0, 'impressions_left' =&gt; -3, ), 1 =&gt; array( 'battles_in_rank' =&gt; '4', 'battle_ids' =&gt; array( 0 =&gt; '27', 1 =&gt; '19', 2 =&gt; '18', 3 =&gt; '17', ), 'battle_impressions' =&gt; array( 0 =&gt; '0', 1 =&gt; '0', 2 =&gt; '0', 3 =&gt; '0', ), 'sum_of_impressions' =&gt; '0', 'rank' =&gt; '1', 'show_rate' =&gt; 6.6666666666667, 'dedicated_impressions' =&gt; 230.53333333333, 'impressions_left' =&gt; 230.53333333333, ), 2 =&gt; array( 'battles_in_rank' =&gt; '2', 'battle_ids' =&gt; array( 0 =&gt; '7', 1 =&gt; '3', ), 'battle_impressions' =&gt; array( 0 =&gt; '0', 1 =&gt; '3', ), 'sum_of_impressions' =&gt; '3', 'rank' =&gt; '3', 'show_rate' =&gt; 20, 'dedicated_impressions' =&gt; 691.6, 'impressions_left' =&gt; 688.6, ), 3 =&gt; array( 'battles_in_rank' =&gt; '2', 'battle_ids' =&gt; array( 0 =&gt; '12', 1 =&gt; '5', ), 'battle_impressions' =&gt; array( 0 =&gt; '17', 1 =&gt; '1', ), 'sum_of_impressions' =&gt; '18', 'rank' =&gt; '4', 'show_rate' =&gt; 26.666666666667, 'dedicated_impressions' =&gt; 922.13333333333, 'impressions_left' =&gt; 904.13333333333, ), 4 =&gt; array( 'battles_in_rank' =&gt; '1', 'battle_ids' =&gt; array( 0 =&gt; '2', ), 'battle_impressions' =&gt; array( 0 =&gt; '3434', ), 'sum_of_impressions' =&gt; '3434', 'rank' =&gt; '7', 'show_rate' =&gt; 46.666666666667, 'dedicated_impressions' =&gt; 1613.7333333333, 'impressions_left' =&gt; -1820.2666666667, ), ); </code></pre> <p>After i get all this information i perform a clean up to get nice result for random function.</p> <pre><code>$elements = array(); $weights = array(); foreach ($battles as $el =&gt; &amp;$values) { $elements[] = array($values['battle_ids'], $values['battle_impressions']); $weights[] = $values['show_rate']; } </code></pre> <p>Here is the random function that i have at the moment:</p> <pre><code>public function getRandom($values, $weights) { $pos = mt_rand(1, array_sum($weights)); $em = 0; foreach ($values as $k =&gt; $v) { $em += $weights[$k]; if ($em &gt;= $pos) { if (is_array($v)) { return $this-&gt;getRandom($v[0], $v[1]); } else { return $v; } } } } </code></pre> <p>And i call it like that to get one random battle id.</p> <pre><code>$this-&gt;getRandom($elements, $weights); </code></pre> <p>What i need is having 5 or 10 unique random IDs.</p> <p>It works but this function gives me only one random element of each call, and when i call it several times i get the same id very often, like 6 out of 10 times.</p> <p>For example if i need 5 random battles i have to call the function in a cycle with 20-30 iterations to get 5 unique random battles. If the battles in the higher ranks are over it should fill the array with battles in lower ranks, so i always end up with 5 battles (or 10). </p> <p>The second level of randomization should be the battles in one rank, weighted by their impressions. That's why the random function is recursive.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload