Losowanie listy pojedynków w PHP

0

Witam mam problem potrzebuję pewien skrypt... Znam się trochę na PHP ale nie na tyle żeby go samemu napisać. Pisałem już na 2 innych forach i nikt nie był w stanie mimo prób stworzyć w pełni działającego skryptu. Problem wygląda następująco:

Posiadam tabelę w bazie danych o kolumnach: ID (AUTO), NAZWA (TEXT), KLUB (TEXT)
Jest to lista zawodników id no to wiadomo nazwa to imie i nazwisko i klub (nazwa jego klubu)
Chodzi o wylosowanie za pomocą PHP dla dowolnej liczby danych rozstawienia walk dla zawodników, z tym że jeżeli jest taka możliwość zawodnicy będący w tym samym klubie nie mogą ze sobą walczyć chyba, że nie ma innej możliwości. Np mamy 4 zawodników :

  1. Łukasz WKS
  2. Rafał ŁKS
  3. Marian WKS
  4. Piotrek ŁKS

Skrypt rozlosuje nam pary do walki:
1 - 4
2 -3

Gdyż jeśli to możliwe nie mogą walczyć zawodnicy z tego samego klubu ze sobą.

Mam nadzieję, że tu uzyskam pomoc i z góry za to dziękuje. :)

Pozdrawiam

0

Poniższa klasa zawiera dwie metody statyczne (DuelGenerator::generateDuels() oraz DuelGenerator::generateDuels2()), które mogą rozwiązać zadanie. Z tym że metoda DuelGenerator::generateDuels() jest częściowo wadliwa, ponieważ dla przykładowych danych z metody DuelGenerator::getData() nie zawsze zwróci 3 pary, czasem tylko 2. Natomiast druga metoda powinna działać poprawnie.

 
<?php
class DuelGenerator
{
    private static function getData()
    {
        /*
        $dbObj = new \PDO(
            'mysql:host='.$host.';dbname='.$dbName.';encoding=utf8', 
            $login, 
            $password
        );
        
        $stmt = $dbObj->prepare(
            'SELECT * FROM tabela'
        );
        $stmt->execute();
        $result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        return $result;
        */
        return array(
            array('id' => 1, 'nazwa' => 'Łukasz', 'klub' => 'WKS'),
            array('id' => 2, 'nazwa' => 'Rafał', 'klub' => 'ŁKS'),
            array('id' => 3, 'nazwa' => 'Marian', 'klub' => 'WKS'),
            array('id' => 4, 'nazwa' => 'Piotrek', 'klub' => 'ŁKS'),
            array('id' => 6, 'nazwa' => 'Marcin', 'klub' => 'MKS'),
            array('id' => 7, 'nazwa' => 'Witek', 'klub' => 'AAA')
        );
    }
    
    public static function generateDuels()
    {
        $users = self::getData();
        $pairs = array();
        $usersCount = count($users);
        while ($usersCount !== 0) 
        {
            $currentUserIndex = mt_rand(0, $usersCount - 1);
            $currentUser = $users[$currentUserIndex];
            $used = array();
            do
            {
                $oponnentIndex = mt_rand(0, $usersCount - 1);
                $opponent = $users[$oponnentIndex];
                if (!in_array($opponent['id'], $used))
                {
                    $used[] = $opponent['id'];
                }
            }
            while ($opponent['klub'] === $currentUser['klub'] && count($used) !== $usersCount);
            if ($opponent['klub'] !== $currentUser['klub'])
            {
                $pairs[$currentUser['id']] = $opponent['id'];
                unset($users[$currentUserIndex]);
                unset($users[$oponnentIndex]);
                $usersCount -= 2;
            }
            else 
            {
                unset($users[$currentUserIndex]);
                $usersCount--;
            }
            $users = array_values($users);
        }
        return $pairs;
    }
    
    public static $arrToSort;
    
    private static function shuffleAssoc($list) 
    { 
        if (!is_array($list)) 
        {
            return $list; 
        }
        
        $keys = array_keys($list); 
        shuffle($keys); 
        $random = array(); 
        foreach ($keys as $key) { 
            $random[$key] = $list[$key]; 
        }
        return $random; 
    }
    
    private static function cmp($a, $b)
    {
        if (self::$arrToSort[$a]['count'] === self::$arrToSort[$b]['count'])
        {
            return 0;
        }
        return (self::$arrToSort[$a]['count'] > self::$arrToSort[$b]['count']) ? -1 : 1; 
    }
    
    private static function groupData($users)
    {
        $groupedData = array();
        for ($i = 0, $ii = count($users); $i < $ii; $i++)
        {
            $currUser = $users[$i];
            if (!isset($groupedData[$currUser['klub']]))
            {
                $groupedData[$currUser['klub']] = array(
                    'index' => array($i),
                    'count' => 1
                );
            }
            else
            {
                $groupedData[$currUser['klub']]['index'][] = $i;
                $groupedData[$currUser['klub']]['count']++;
            }
        }
        self::$arrToSort = $groupedData;
        uksort($groupedData, "self::cmp");
        return $groupedData;
    }
    
    private static function removeFromGroupedData(array $groupedData, $club, $index)
    {
        unset($groupedData[$club]['index'][$index]);
        $groupedData[$club]['index'] = array_values($groupedData[$club]['index']);
        $groupedData[$club]['count']--;
        if ($groupedData[$club]['count'] == 0)
        {
            unset($groupedData[$club]);
        }
        return $groupedData;
    }
    
    public static function generateDuels2()
    {
        $users = self::getData();
        $groupedData = self::groupData($users);
        $pairs = array();
        $usersCount = count($users);
        while ($usersCount !== 0) 
        {
            reset($groupedData);
            $firstKey = key($groupedData);
            $indexInIndexArr = mt_rand(0, $groupedData[$firstKey]['count'] - 1);
            $currentUserIndex = $groupedData[$firstKey]['index'][$indexInIndexArr];
            $currentUser = $users[$currentUserIndex];
            $used = array();
            do
            {
                $oponnentIndex = mt_rand(0, $usersCount - 1);
                $opponent = $users[$oponnentIndex];
                if (!in_array($opponent['id'], $used))
                {
                    $used[] = $opponent['id'];
                }
            }
            while ($opponent['klub'] === $currentUser['klub'] && count($used) !== $usersCount);
            if ($opponent['klub'] !== $currentUser['klub'])
            {
                $pairs[$currentUser['id']] = $opponent['id'];
                unset($users[$currentUserIndex]);
                unset($users[$oponnentIndex]);
                $groupedData = self::removeFromGroupedData(
                    $groupedData, 
                    $opponent['klub'], 
                    array_search($oponnentIndex, $groupedData[$opponent['klub']]['index'])
                );
                $usersCount -= 2;
            }
            else 
            {
                unset($users[$currentUserIndex]);
                $usersCount--;
            }
            $groupedData = self::removeFromGroupedData($groupedData, $firstKey, $indexInIndexArr);
            $users = array_values($users);
            $groupedData = self::groupData($users);
        }
        return self::shuffleAssoc($pairs);
    }
}

$pairs = DuelGenerator::generateDuels2();
var_dump($pairs);

1 użytkowników online, w tym zalogowanych: 0, gości: 1