Auslesen von Werten aus SQL-DB & Kombination per Zufallsprinzip

Hallöchen :-)

Mal wieder VIELEN DANK! Jetzt ist jedes Match einmalig :-)
Aber die Sache scheint doch schwieriger zu sein, als wir dachten ...

Denn nun nimmt er ein beliebiges Match und packt es nach und nach ins array ... und genau SO schreibt er es dann auch rein ... Schwierigkeit hierbei ... jetzt kommt es auch vor, dass ein team mehrmals pro spieltag spielt, weil den matches keine spieltagsid zugeordnet ist ... Kann man das relativ einfach realisieren?

Ich probier schonmal ein wenig rum, ob mir was einfällt .. wäre natürlich klasse, wenn dir irgendwas noch schnelleres einfällt :-)
 
Also was ich jetzt versucht habe ist eine foreach schleife einzubauen, in der letzten for-schleife .. also dort, wo die Spieltage durchgegangen werden ... Leider finde ich keine Möglichkeit das array "$matchSqls" nach bestimmten Teams, an bestimmten Spieltagen zu durchsuchen ... da ja immer nur ein kompletter String für den mySQL Befehl gespeichert wird ...

Gibts da evt eine Möglichkeit? Weil dann würde es ja einwandfrei funktionieren .. so könnte ich gucken, ob eine der beiden Teams in dem Array mit dem Spieltag schon vorhanden ist und die Teams in diesem Fall wieder ins Array tun, und dann die nächsten Teams holen, solange bis eben alle 8 Teams pro Spieltag übrig sind ... Naja ...

Aber irgendwie finde ich keinen Befehl, um das so zu realisieren ...

Würde es überhaupt über den Weg klappen?
 
Ist nicht ganz einfach. Ich hab das mal eingebaut und dabei folgendes festgestellt.
Code:
Tag: 1
Spiel 0: Team5::Team7
Spiel 1: Team6::Team2
Spiel 2: Team4::Team3
Spiel 3: Team8::Team1
=====================================================
Tag: 2
Spiel 0: Team4::Team8
Spiel 1: Team1::Team6
Spiel 2: Team2::Team3
<br />
<b>Warning</b>:  shuffle() expects parameter 1 to be array, null given in <b>C:\xampp\htdocs\test\test.php</b> on line <b>70</b><br />
Wenn wir das jetzt analysieren, sehen wir das am 2ten Tag der Matsch 5::7 noch übrig bleibt. Dieser ist aber schon am ersten Tag eingetragen.

Irgendwie muss da ein anderer Algorithmus her
 
gefällt mir noch nicht besonders. hoffentlich kennt jemand noch einen besseren Ansatz.

Beim testen habe ich festgestellt, dass es nicht viele Versuche braucht um ein kompletes Set hinzukriegen. Also versucht es dieser Code einfach solange bis es geht.

Ich poste heir mal mein Testscript. Die DB-Dinges sind ausgeblendet. Die Datei ist so direkt aufrufbar und lauffähig.

PHP:
<?php
//Testdaten
$teams[] = ('Team1');
$teams[] = ('Team2');
$teams[] = ('Team3');
$teams[] = ('Team4');
$teams[] = ('Team5');
$teams[] = ('Team6');
$teams[] = ('Team7');
$teams[] = ('Team8');


//Settings
$saisonid = 1;
$ligaid = 1;
$anzSpielTage = 7;
$anzSpielePerTag = 4;

//Array mit allen Teams erstellen
$sql = "select * from team where ligaid = {$ligaid}";
//TODO: beim gebrauch mit der DB bei den folgenden 4 Zeilen die // entfernen 
//$result = mysql_query($sql);
//while($team = mysql_fetch_array($result)){
//    $teams[] = $team['vereinsname'];
//}

/**
 * Funktion um den Cach-Wert eines Matches zu generieren
 * @param $team1    String  Name des Heimteams
 * @param $team2    String  Name des Auswertsteams
 * @return          String  Cach-Wert team###team
 */
function createMatchCachEntry($team1,$team2){
    return MIN($team1,$team2).'###'.MAX($team1,$team2);
}

/**
 * Funktion um matches auszufiltern, von denen an diesem Tag bereits ein Team gespielt hat
 * @param $key      int     IndexKey des Matches
 * @return          Boolean
 */
function dayFilter($key){
    global $dayCache;
    global $matches;
    return !(in_array($matches[$key][0], $dayCache) || in_array($matches[$key][1], $dayCache)); 
}

//alle möglichen Matches definieren
$cachMatches = array();
foreach($teams as $team1){
    foreach($teams as $team2){
        //Prüfen dass die Manschaft nicht gegen sich selber spielt und dass der Match noch nicht exisitiert
        if($team1 != $team2 && !in_array(createMatchCachEntry($team1,$team2), $cachMatches)){
            $cachMatches[] = createMatchCachEntry($team1,$team2);
            $matches[] = array(min($team1, $team2), max($team1, $team2));
        }
    }
}

//Schleife die solange durchgeht, bis ein vollständiges Set erstellt werden konnte
do{
echo "#### Durchgang ".++$cnt." ####<br />\n",
    $notValidSetFlag = false;
    $matchSqls = array();
    //Index der mathces erstellen
    $index = array_keys($matches);
    //Jeden Spieltag durchgehen
    for($spieltag = 1; $spieltag <= $anzSpielTage; $spieltag++){
        //TeamCach für den Tag
        $dayCache = array();
        //Kopie des Restindex erstellen
        $dayIindex = $index;
        //Die Matchs mischen
        shuffle($dayIindex);
        //Anazahl Spiele pro Tag oder Anzahl üpbrige Matches durchgehen
echo "Tag: {$spieltag}<br />\n";
        for($i=0; $i < min($anzSpielePerTag, count($index)); $i++){
            //Den obersten Match aus der Leiste nehmen
            $key = array_shift($dayIindex);
            //prüfen ob ein key ausgelesen werden konnt
            //Ansonsten abbrechen und neu beginnen 
            if(is_null($key)){
echo "#### break #### -> Neu starten ################################<br />\n";
                $notValidSetFlag=true;
                break 2;        
            }
            
            //Match aus dem Index austragen
            unset($index[array_search($key, $index)]);       
            //Mischen wer die Heimmanschaft ist
            $match = $matches[$key];
            shuffle($match);
            //SQL-Insert-Teil zusammensetzen
            $matchSqls[] = "('{$spieltag}','{$saisonid}','{$ligaid}','{$match[0]}','{$match[1]}')";
            
            //Teams in den Tagescahce eintragen
            $dayCache[] = $match[0];
            $dayCache[] = $match[1];
            //Indexe ausfiltern, so dass nur noch die Indexe der Matches vorhanden sind, die
            //noch heute noch nicht gespielt haben
            $dayIindex = array_filter($dayIindex, 'dayFilter');
echo "Spiel {$i}: {$match[0]}::{$match[1]}<br />\n";
        }
echo "<hr />\n";    
        //Wenn alle Matches eingeteilt sind, alles abbrechen
        if(count($index)==0){ break 2; }
    }
}while($notValidSetFlag);

//Die Matches mit einem einzigen DB-Zugriff eintragen
//TODO: beim gebrauch mit der DB bei der folgenden Zeile die // entfernen 
$sql = "INSERT INTO spieltage (spieltag,saisonid,ligaid,hteam,ateam) VALUES ".implode(',', $matchSqls);
//mysql_query($sql);

?>

Das Resultat sieht dann ungefähr so aus, wobei nur der letzte Versuch in die DB eingetragen würde
Code:
#### Durchgang 1 ####
Tag: 1
Spiel 0: Team4::Team8
Spiel 1: Team3::Team5
Spiel 2: Team1::Team7
Spiel 3: Team2::Team6
Tag: 2
Spiel 0: Team3::Team6
Spiel 1: Team5::Team1
Spiel 2: Team2::Team7
#### break #### -> Neu starten ################################
#### Durchgang 2 ####
Tag: 1
Spiel 0: Team8::Team3
Spiel 1: Team2::Team4
Spiel 2: Team5::Team1
Spiel 3: Team6::Team7
Tag: 2
Spiel 0: Team8::Team2
Spiel 1: Team1::Team3
Spiel 2: Team6::Team4
Spiel 3: Team5::Team7
Tag: 3
Spiel 0: Team4::Team7
Spiel 1: Team2::Team3
Spiel 2: Team8::Team1
Spiel 3: Team6::Team5
Tag: 4
Spiel 0: Team8::Team4
Spiel 1: Team7::Team1
Spiel 2: Team6::Team2
Spiel 3: Team5::Team3
Tag: 5
Spiel 0: Team8::Team6
Spiel 1: Team7::Team3
Spiel 2: Team2::Team1
Spiel 3: Team5::Team4
Tag: 6
Spiel 0: Team4::Team3
Spiel 1: Team8::Team5
Spiel 2: Team7::Team2
Spiel 3: Team1::Team6
Tag: 7
Spiel 0: Team8::Team7
Spiel 1: Team4::Team1
 
Ahoi!

Vielen Dank schonmal ... gibt es nen Grund, weshalb am letzten Spieltag nur 2 Spiele sind? Ist mir gerade nicht ersichtlich, endet bei mir im Test aber auch mit nur 2 Spielen am letzten Spieltag.

LG
 
Weil da noch ein Fehler drinne steckt.
PHP:
...
        for($i=0; $i < min($anzSpielePerTag, count($index)); $i++){
            ...
In der For-Schleife reduzieren wir den $index. am letzten Tag kommt somit der count($index) unter 4 und schneidet uns darum die letzten 2 Spiele ab. Der ganze min() Teil ist eigentlich da um zu verhindern, dass wenn [Anzahl Matches]/[Anzahl Matches pro Tag] nicht aufgeht, am letzten Tag entsprechend weniger Spiele stattfinden.
Wir müssen also lediglich diese berechnung vor der Schleife machen
PHP:
...
        $maxSpieleParDay = min($anzSpielePerTag, count($index));
        for($i=0; $i < $maxSpieleParDay; $i++){
            ...
 
Achso ... Okay :-) Kleiner Code-Schnipsel, den ich wohl nicht so ganz realisiert habe. Werde mir das mal verinnerlichen. Es funktioniert auf jeden Fall! :-)

Vielen Dank!

Thema gelöst!
 
Zurück