skip to Main Content

I am trying to create a fantasy cricket team of 11 players from a large list of players.

For the team, I have basic minimum and maximum requirements for each type of player. I have assigned values like this:

$min_wicket_keeper = 1;
$min_batsman = 3;
$min_all_rounders = 1;
$min_bowlers = 2;

$max_wicket_keeper = 3;
$max_batsman = 5;
$max_all_rounders = 5;
$max_bowlers = 4;

I have total players like this:

$total_wicket_keepers = 2;
$total_batsman = 6;
$total_all_rounders = 5;
$total_bowlers = 5;

You can see I have total 18 players. Now I want to create a team of 11 players assigning random type players — keep in mind the minimum and maximum requirements of players.

Example 1

$wicket_keeper_limit = 1;
$batsman_limit = 4;
$all_rounder_limit = 4;
$bowler_limit = 2;
//so total 11

Example 2

$wicket_keeper_limit = 2;
$batsman_limit = 3;
$all_rounder_limit = 3;
$bowler_limit = 3;
//so total 11

I want a random number assigned for each type but total should be 11 and should not below minimum requirements and should not greater then total available players for each type followed by maximum limit.

I have tried code like this

$min_wicket_keeper = 1;
$min_batsman = 3;
$min_all_rounders = 1;
$min_bowlers = 2;

$max_wicket_keeper = 3;
$max_batsman = 5;
$max_all_rounders = 5;
$max_bowlers = 4;

$total_wicket_keepers = 2;
$total_batsman = 6;
$total_all_rounders = 5;
$total_bowlers = 5;


$total_players_match = $total_wicket_keepers+$total_batsman+$total_all_rounders+$total_bowlers;

echo $total_players_match;

if ($total_players_match > 11) {
    $remain_players = 11;
    if ($total_wicket_keepers > $min_wicket_keeper) {
        $wicket_keeper_limit = rand($min_wicket_keeper,$total_wicket_keepers);
        $remain_players = $remain_players-$wicket_keeper_limit;
    } else {
        $wicket_keeper_limit = $total_wicket_keepers;
        $remain_players = $remain_players-$wicket_keeper_limit;
    }
        
    echo "WK: ".$wicket_keeper_limit." REMAIN: ".$remain_players."<br>";
        
    if ($total_batsman>$min_batsman) {
        $batsman_limit = rand($min_batsman,$total_batsman);
        $remain_players = $remain_players-$batsman_limit;
            
        if ($remain_players > ($total_bowlers + $total_all_rounders)) {
            $batsman_limit = ($min_batsman + $remain_players) - ($total_bowlers+$total_all_rounders);
            $remain_players = $remain_players-$batsman_limit;
        }
            
    } else {
        $batsman_limit = $total_batsman;
        $remain_players = $remain_players-$batsman_limit;
    }
        
    echo "BT: " . $batsman_limit . " REMAIN: " . $remain_players . "<br>";
        
    if ($total_bowlers > $min_bowlers) {
        $bowler_limit = rand($min_bowlers, $total_bowlers);
        $remain_players = $remain_players - $bowler_limit;
            
        if ($remain_players > $total_all_rounders) {
            $bowler_limit = $total_bowlers;
            $remain_players = $remain_players - $bowler_limit;
        }

    } else {
            $bowler_limit = $total_bowlers;
        $remain_players = $remain_players - $bowler_limit;
    }
        
    echo "BOL:" . $bowler_limit . " REMAIN:" . $remain_players . "<br>";
        
    $all_rounder_limit = $remain_players;
        
    echo "ALL: " . $all_rounder_limit . " REMAIN: " . $remain_players . "<br>";
        
} else {
    $wicket_keeper_limit = $total_wicket_keepers;
    $batsman_limit = $total_batsman;
    $all_rounder_limit = $total_all_rounders;
    $bowler_limit = $total_bowlers;
}
    
echo "WK:" . $wicket_keeper_limit . "<br>";
    echo "BT:" . $batsman_limit . "<br>";
    echo "BO:" . $bowler_limit . "<br>";
    echo "AL:" . $all_rounder_limit . "<br>";

but it’s failing to follow my minimum and maximum requirements. Sometimes I am getting bowler as 0 and sometimes I am getting all rounder as high as 6.

This is Online Fiddle Link

Edit: According to comments, I should clear that, I will generate multiple teams with put above code in while loops, Like 50 teams which will have different/random players in each type like some team have 5 batsman, some team will have only 3 batsman.

When I will get above code working, I will later get players from my database according to limit, I have got for each type.

2

Answers


  1. I’m sorry but your code to me was too much to handle. Based on your conditions I wrote following code:

    <?php
    // Remapped your variables because it was too much
    $constraints = [
        'wicket_keeper' => ['min' => 1, 'max' => 3],
        'batsman'       => ['min' => 3, 'max' => 5],
        'all_rounders'  => ['min' => 1, 'max' => 5],
        'bowlers'       => ['min' => 2, 'max' => 4],
    ];
    
    // These are the current values to assign
    $values = [
        'wicket_keeper' => 2,
        'batsman'       => 6,
        'all_rounders'  => 5,
        'bowlers'       => 5,
    ];
    
    // The first problem is that the maximums should be adjusted to the values we have
    foreach ($values as $key => $value) {
        if ($value < $constraints[$key]['max']){
            $constraints[$key]['max'] = $value;
        }
    }
    
    // Vice versa we need to do this for the minimums
    // I now did this manually, but I think you get the point
    $result = [
        'wicket_keeper' => 1,
        'batsman'       => 3,
        'all_rounders'  => 1,
        'bowlers'       => 2,
    ];
    
    // We keep track of possible options
    $options = array_keys($result);
    
    // Init
    $totalPlayers = 0;
    $max = 0;
    
    // This is minus 7 because of your minimum requirements, also done manually
    // But of course you can calculate this as well.
    $teamLimit = 11 - 7;
    while($totalPlayers < $teamLimit) {
            // Pick a random type
            $random = rand(0, count($options) - 1);
    
            // Get key
            $key = $options[$random];
    
            // Add one player to the random type
            $result[$key] += 1;
            $totalPlayers++;
    
            // Check if max is reached
            // If so, remove it from possible options
            if ($result[$key] >= $constraints[$key]['max']){
                unset($options[$key]);
            }
    }
    
    var_dump($result);
    

    I hope the comments are clear enough.

    Live example

    Login or Signup to reply.
  2. You might build this script as a single function/method or better would be to practice the single-responsibility principle and have multiple functions/methods which perform exactly one task. To avoid expanding the snippet too much, I’ll only show my advice as a multi-responsibility function.

    • Pass in your team creation settings.
    • Implement logical guard conditions to alert you when settings prevent populating a full team.
    • Apply the maximum limitations on your total player pool.
    • As a shortcut, seed your team with all designated minimum values.
    • Randomly select one position at a time in a loop and "consume" that position in the pool so that a position can never be over-drawn from the pool.
    • When the team is full or the pool is empty, kill the loop.
    • Return the populated team or alert the user if the team couldn’t be fully populated.

    Code: (Demo)

    function randomizeTeam(
        int $teamSize,
        array $positionPool,
        array $positionMins = [],
        array $positionMaxs = []
    ): array {
        // guard conditions
        foreach ($positionMins as $pos => $min) {
            if (!key_exists($pos, $positionPool) || $positionPool[$pos] < $min) {
                throw new Exception('Position pool cannot accommodate minimum required positions');
            }
        }
    
        // input preparation
        foreach ($positionMaxs as $pos => $max) {
            if (key_exists($pos, $positionPool) && $positionPool[$pos] > $max) {
                $positionPool[$pos] = $max;
            }
        }
        
        // seed team
        $team = [];
        $sum = 0;
        foreach ($positionPool as $pos => &$pool) {
            $team[$pos] = $positionMins[$pos] ?? 0;
            $pool -= $team[$pos];
            if (!$pool) {
                unset($positionPool[$pos]); // remove exhausted pool
            }
            $sum += $team[$pos];
        }
        
        // add random positions
        while ($sum < $teamSize && $positionPool) {
            $pos = array_rand($positionPool);
            ++$team[$pos];
            --$positionPool[$pos];
            if (!$positionPool[$pos]) {
                unset($positionPool[$pos]); // remove exhausted pool
            }
            ++$sum;
        }
    
        // another guard condition
        if (array_sum($team) < $teamSize) {
            throw new Exception('Position pool was exhausted before filling team');
        }
    
        return $team;
    }
    
    var_export(
        randomizeTeam(
            11,
            [
                'wicket_keeper' => 2,
                'batsman'       => 6,
                'all_rounders'  => 5,
                'bowlers'       => 5,
            ],
            [
                'wicket_keeper' => 1,
                'batsman'       => 3,
                'all_rounders'  => 1,
                'bowlers'       => 2,
            ],
            [
                'wicket_keeper' => 3,
                'batsman'       => 5,
                'all_rounders'  => 5,
                'bowlers'       => 4,
            ]
        )
    );
    

    Potential output:

    array (
      'wicket_keeper' => 2,
      'batsman' => 4,
      'all_rounders' => 2,
      'bowlers' => 3,
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search