• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Erstellung eines Spielplans

Steven20

Neues Mitglied
Hallo Leute,

also, ich habe ein Adminbereich wo ich Mannschaften für den Verein anlegen kann und dann für jede Mannschaft den Kader, die Tabelle, die Statistik und den Spielplan bearbeiten kann. Der Kader ist bereits fertig, nun möchte ich den Spielplan erstellen und da hänge ich. Jede angelegte Mannschaft (z. B. A-Jugend, B-Jugend, usw.) wird in der Datenbank gespeichert. Nun ist meine Frage, wo bzw. wie ich nun die Gegner für jede Mannschaft speichere. In der gleichen Tabelle wie die Mannschaften des Vereins oder eher eine eigene Tabelle mit der dazugehörigen TeamId zum zuweisen der Mannschaften? Habe schon eigene Versuche gestartet, aber bin damit nicht glücklich. Es soll auch möglich sein, dass einige Mannschaften Spielfrei haben. Wie kann man das am besten realisieren?

Dannke.
 
Für Spielpläne gibt es Vorlagen, sowas selbst berechnen zu wollen ist aufwändig. Anhand der Vorlagen werden dann die Spiele in eine Datenbank eingetragen, dann hast du den Spielplan.

Für die Spiele gibt es unterschiedliche Varianten, habe es so realisiert, dass ein Spiel ein Datenbankeintrag ist, das widerspricht zwar ein wenig der Normalisierung, weil in jedem Datensatz für zwei Teams die Daten vorhanden sind. Es läßt sich aber leichter abfragen.

Du brauchst also ein Tabelle mit den Spielen und z.b. folgenden Feldern:

id, spieltag, datum,
team1_id, tore_1, hz_1, ...
team2_id, tore_2, hz_2, ...

(hz = Halbzeit)

Die Abfragen können aber sehr komplex werden. Meine für die Abfrage der Tabelle sieht z.b. so aus (unvollständig, das sind nur die Felder die erzeugt werden):
Code:
    m.*,
    SUM( IF((m.id = s.team1 AND s.tore1 > s.tore2) OR (m.id = s.team2 AND s.tore1 < s.tore2), $pkt, 0))
    + SUM(IF(s.tore1 = s.tore2, 1, 0)) $pkt0 as pkt,
    SUM( IF((m.id = s.team1 AND s.tore1 < s.tore2) OR (m.id = s.team2 AND s.tore1 > s.tore2), $pkt, 0))
    + SUM(IF(s.tore1 = s.tore2, 1, 0)) $pkt0 as pkt2,
    ( SUM( IF((m.id = s.team1 AND s.tore1 > s.tore2) OR (m.id = s.team2 AND s.tore1 < s.tore2), $pkt, 0))
    + SUM(IF(s.tore1 = s.tore2, 1, 0)) ) / count(s.tore1) as p_s,
    SUM(IF((m.id = s.team1 AND s.tore1 > s.tore2) OR (m.id = s.team2 AND s.tore1 < s.tore2), 1, 0)) AS g,
    SUM(IF((m.id = s.team1 AND s.tore1 < s.tore2) OR (m.id = s.team2 AND s.tore1 > s.tore2), 1, 0)) AS v,
    SUM(IF(s.tore1 = s.tore2, 1, 0)) AS u,
    SUM(IF(m.id = s.team1, s.tore1, 0)) + SUM(IF(m.id = s.team2, s.tore2, 0)) AS tore1,
    (SUM(IF(m.id = s.team1, s.tore1, 0)) + SUM(IF(m.id = s.team2, s.tore2, 0))) / COUNT(s.tore1) AS t1_s,
    SUM(IF(m.id <> s.team1, s.tore1, 0)) + SUM(IF(m.id <> s.team2, s.tore2, 0)) AS tore2,
    (SUM(IF(m.id <> s.team1, s.tore1, 0)) + SUM(IF(m.id <> s.team2, s.tore2, 0))) / COUNT(s.tore1) AS t2_s,
    SUM(IF(m.id = s.team1, s.tore1, 0)) + SUM(IF(m.id = s.team2, s.tore2, 0)) -
    SUM(IF(m.id <> s.team1, s.tore1, 0)) - SUM(IF(m.id <> s.team2, s.tore2, 0)) AS diff,
    COUNT(s.tore1) AS spiele
 
Also ich will keinen Zufallsspielplan. Der Spielplan steht schon fest -> ist halt ne Vereinsseite, da steht der Spielplan ja schon vor der Saison fest. Was ich möchte is, dass ich einfach nur die Begegnungen eintragen muss.

Z. B.:
Spieltag | Datum | Zeit | Verein 1 gegen Verein 2 | Ergebnis

mein Problem ist einfach nur das Handling. Wie mache ich es am besten.

Mein Ansatz wären 2 Tabelllen.

1. Tabelle = Vereinsmannschaften (Die Mannschaften, die dem Verein angehören = A-Jugend, B-Jugend, C-Jugend, usw.) [ID, Name, Bezirk, etc.]
2. Tabelle = Gegner der Mannschaften (Alle Gegner der A-Jugend, Alle Gegner der B-Jugend, usw.) [ID, TeamId, Name, Spiele, Tore, Gegentore, etc.]
- TeamId = ID der Vereinsmannschaft.
Aus der 2. Tabelle würde ich dann auch die Ligatabelle generieren lassen. Zusätzlich müsste ja dann die Vereinsmannschaft mit in die 2. Tabelle um dann auch in der Ligatabelle zu erscheinen.

Ich hoffe ihr versteht was ich meine ;)

Würdet ihr es anders machen? Wenn ja, wie?
 
Ich würde es möglichst weit aufdröseln/normalisieren.

Entitäten:

- Verein, Mannschaft, Spiel, Spieltag, Liga, Saison, Altersstufe

Relationen:

  1. Ein Verein hat mehrere Mannschaft.
  2. Ein Spiel hat eine Heim- und eine Auswärtsmannschaft.
  3. Ein Spieltag hat mehrere Spiele.

Danach wird's kniffliger, weil Liga, Saison und Altersstufe hierarchisch mehr oder weniger auf einer Ebene liegen.

Ein Spieltag gehört einer Liga einer Saison einer Altersstufe an.

Bin mir nicht sicher, wie ich das abbilden würde.
 
- Round-robin tournament - Wikipedia, the free encyclopedia

Ich habe das mal in PHP implementiert. Kann ich nachher raussuchen, falls gewünscht.
Großartig.
Ich erstelle die Spielpläne immer mit der fertigen Tabellen, die ich irgendwo gefunden habe. Aber mit deinem Hinweis bin ich auf den Berger Algorithmus gestossen. Ich hab den mal umgesetzt, leider in Perl, da ich es für ein fertiges Perlskript brauche.
Code:
package RoundBerger;
sub new {
    my $self = bless {}, shift;
    $self->{_teams_} = shift || 0;
    $self->{_data_} = [];
    $self->{_onstart_} = sub {};
    $self->{_onend_} = sub {};
    $self->{_onrow_start_} = sub {};
    $self->{_onrow_end_} = sub {};
    $self->{_ongame_} = sub {};
    return $self;
}
# helper function
sub _x{
    my $self = shift;
    my $num = int($self->{_teams_} / 2);
    my $null;
    if($self->{_teams_} % 2) {
        $num++;
        $null++;
    }
    return ($num, $num *2, $null);    
}
# events
sub onstart{
    my $self = shift;
    $self->{_onstart_} = shift if ref $_[0] eq 'CODE';
}
sub onend{
    my $self = shift;
    $self->{_onend_} = shift if ref $_[0] eq 'CODE';
}
sub onrow_start{
    my $self = shift;
    $self->{_onrow_start_} = shift if ref $_[0] eq 'CODE';
}
sub onrow_end{
    my $self = shift;
    $self->{_onrow_end_} = shift if ref $_[0] eq 'CODE';
}
sub ongame{
    my $self = shift;
    $self->{_ongame_} = shift if ref $_[0] eq 'CODE';
}
# properties
sub num_games{
    my $self = shift;
    my $reverse = scalar @{$self->{_data_}} > $self->num_rounds;
    return ($self->{_teams_} / 2) * ($self->{_teams_} - 1) * ($reverse ? 2 : 1)
}
sub num_rounds{
    my $self = shift;
    return int($self->{_teams_} - 1 + .5)
}
sub num_teams{
    return shift->{_teams_};
}
sub round{
    my $self = shift;
    my $d = shift || 0;
    die "$d is out of range (0.." . $self->num_rounds.")." if($d < 0 or $d > $self->num_rounds);
    return $self->{_data_}->[$d];
}
# calculate berger tournament
sub berger{
    my $self = shift;
    my $rev = shift;
    my($num, $max, $null) = $self->_x();
    return unless($num);
    my @t;
    $t[0] = [grep $_, (1..$num)];
    $t[1] = [grep $_, reverse($num+1..$max)];
    my @arr;
    my $switch = 1;
    my $r = 0;
    for (1..$self->num_rounds) {
        my @tmp;
        my @tmp1;
        for my $c2(0..$num-1) {
            my $t1 = $t[0]->[$c2];
            my $t2 = $t[1]->[$c2];
            if($null && ($t1 == $max || $t2 == $max)){
                $null = $t1 == $max ? $t2 : $t1;
                next;
            }
            push @tmp, [$t1, $t2];
            push @tmp1, [$t2, $t1];
        }
        push @tmp, [$null] if $null;
        $arr[$r] = \@tmp;
        $arr[$r + $self->num_rounds] = \@tmp1 if $rev;
        ++$r;
        
        my $tmp0 = shift @{$t[$switch]};
        my $not = $switch ? 0 : 1;
         if(!$switch) {
             unshift @{$t[0]}, shift @{$t[1]};
         }else{
             push @{$t[1]}, pop @{$t[0]};
         }
         for(2..$num-$switch) {
             unshift @{$t[0]}, shift @{$t[1]};
             push @{$t[1]}, pop @{$t[0]};
        }
        
        unshift @{$t[$not]}, $tmp0;
        $switch = $not;
    }
    $self->{_data_} = \@arr;
    
}
sub out{
    my $self = shift;
    my $param = shift;
    my $data = $param->{sortByTeam} ? $self->sortByTeam() : $self->{_data_};
    $self->onstart($param->{onstart});
    $self->onend($param->{onend});
    $self->onrow_start($param->{onrow_start});
    $self->onrow_end($param->{onrow_end});
    $self->ongame($param->{ongame});
    
    $self->{_onstart_}->($self);
    my $r = 0;
    foreach my $rounds(@$data){
        $r++;
        $self->{_onrow_start_}->($self, $r);
        foreach my $round(@$rounds) {
            $self->{_ongame_}->($self, $round);
        }
        $self->{_onrow_end_}->($self, $r);
    }
    $self->{_onend_}->($self);
}
sub sortByTeam {
    my $self = shift;
    my($num, $max, $null) = $self->_x();
    # Ein zweidimensonales Array mit allen Spielen
    my $arr = [];
    # füllen mit einem defaultwert
    for my $c(0..$max-1) {
        $arr->[$c] = [];
        for (0..$max-1) {
            $arr->[$c]->[$_] = $c == $_ ? '*' : '-';
        }
    }
    my $r = 0;
    my $swap = scalar @{$self->{_data_}} < $max;
    foreach my $rounds(@{$self->{_data_}}){
        ++$r;
        foreach my $round(@$rounds) {
            next if ref $round ne 'ARRAY';
            my $idx_1 = $round->[0] -1;
            my $idx_2 = $round->[1]-1;
            if($swap && $idx_1 > $idx_2) {
                my $tmp = $idx_2;
                $idx_2 = $idx_1;
                $idx_1 = $tmp;
            }
            $arr->[$idx_1]->[$idx_2] = $r;
        }
    }
    return $arr;
}

Ein Beispiel:
Code:
#!/usr/bin/perl -w
use strict;
use RoundBerger;

my $num = $ARGV[0];
my $r = RoundBerger->new($num);
my $teams = [qw(a b c d e f g h i )];
unshift @$teams, 0; # index starts with 1
$r->berger();
$r->onrow_end(sub{ print "\n";});

$r->out({
    onrow_start => sub{ printf 'Runde %2s:', $_[1];},
    ongame => sub{ 
        printf  '[%2s-%2s]',team($_[1]->[0]), team($_[1]->[1]);
    },
    sortByTeam => 0
});
print "Kreuztabelle:\n";
$r->out({
    onrow_start => sub{ print 'Team: ', team($_[1]);},
    ongame => sub{ 
        printf '[%2s]',  $_[1];
    },
    onstart => sub {
        print "\nTeam: ";
        my $self = shift;
        printf ' %2s ', team($_) for(1..$self->num_teams) ;
        print "\n";
    },
    sortByTeam => 1
});

printf "games: %s\ndays: %s\n",  $r->num_games(), $r->num_rounds();
sub team {
    return $teams->[shift];
}

Ausgabe:
Code:
struppi@struppi-desktop:~/projekte/perl$ perl test.pl 8
Runde  1:[ a- h][ b- g][ c- f][ d- e]
Runde  2:[ h- e][ f- d][ g- c][ a- b]
Runde  3:[ b- h][ c- a][ d- g][ e- f]
Runde  4:[ h- f][ g- e][ a- d][ b- c]
Runde  5:[ c- h][ d- b][ e- a][ f- g]
Runde  6:[ h- g][ a- f][ b- e][ c- d]
Runde  7:[ d- h][ e- c][ f- b][ g- a]
Kreuztabelle:

Team:   a   b   c   d   e   f   g   h 
Team: a[ *][ 2][ 3][ 4][ 5][ 6][ 7][ 1]
Team: b[ -][ *][ 4][ 5][ 6][ 7][ 1][ 3]
Team: c[ -][ -][ *][ 6][ 7][ 1][ 2][ 5]
Team: d[ -][ -][ -][ *][ 1][ 2][ 3][ 7]
Team: e[ -][ -][ -][ -][ *][ 3][ 4][ 2]
Team: f[ -][ -][ -][ -][ -][ *][ 5][ 4]
Team: g[ -][ -][ -][ -][ -][ -][ *][ 6]
Team: h[ -][ -][ -][ -][ -][ -][ -][ *]
games: 28
days: 7
 
Zurück
Oben