Compare commits

..
Author SHA1 Message Date
svennickel 983083d761 Zeilenenden von tools.php wiederherstellen (CRLF) 2026-09-11 07:14:05 +02:00
svennickel 2a0ccfd98f Die Frage "liegt ein Ergebnis vor?" an einer Stelle beantworten
Die Bedingung stand doppelt als Closure in sportsmanager.php und ein drittes
und viertes Mal punktebasiert in den Ansichten, wo eine Begegnung mit
ausschliesslich unentschiedenen Saetzen als "_:_" erschien, obwohl die
Tabelle sie zaehlt.
2026-09-10 09:52:25 +02:00
svennickel 668f917a25 Ticker: Tore zeigen, und ein 0:0-Satzstand ist ein Ergebnis
Meldung von Sven (DTFB-IT): "Im Live-Ticker werden Tore nicht gezeigt."
Dazu gemessen: view_ticker.php enthielt keinen einzigen Zugriff auf die
Tore-Spalten, und die Spielzeile blendete das Ergebnis aus, sobald der
Satzstand 0:0 war ("5:5 5:5" -> leere Zelle, obwohl eingetragen).

- Spielzeile im Matchdetail: das Ergebnis erscheint auch bei Satzstand 0:0,
  sofern ein Satzergebnis vorliegt (ergebnis_detailliert); darunter stehen
  die Tore des Spiels aus teamspiel_heim_tore/teamspiel_gast_tore, klein und
  nur, wenn sie bekannt sind und nicht ohnehin dem Punktestand entsprechen
  (bei punktetyp 0 sind Punkte = Tore, dort bleibt die Zeile unveraendert).
- Matchdetail-Kopf: die Gesamttore der Begegnung stehen in der Datumszeile
  ("... - Tore 47:42"), gleiche Bekanntheits-Regel; der feste 78px-Zaehler
  (resultat_holder) bleibt unangetastet und zeigt statt "--|--" den Stand,
  sobald ein Ergebnis vorliegt (heim_tore bekannt), auch bei Spielpunkten 0:0
  (Wertung "je Satz, Sieg 1": alle Spiele remis).
- Status einer Begegnung (finished/upcoming) in Liste und Turnierbaum:
  bekannte Tore zaehlen als beendet, nicht nur Spielpunkte != 0.
- Die Ticker-Abfragen (Liste und Timestamp-Erkennung) behandeln eine
  Begegnung mit Punkten 0:0, aber bekannten Toren als ausgetragen -- sie
  erscheint unter den beendeten Spielen und sortiert sich dort ein, statt
  als "anstehend" zu gelten. Fuer Bestandsdaten ohne Tore-Spaltenwerte
  (NULL) aendert sich an Filterung und Sortierung nichts.
2026-09-10 07:28:52 +02:00
svennickel ab6b91f2b5 Remis-Saetze mitfuehren: neue Spalten, an denselben Stellen geschrieben wie die Tore
Meldung von Sven (DTFB-IT): "In der Tabelle sind Saetze falsch." Die
Satz-Spalte der Tabelle summiert teamspiel_*_punkte, und die zaehlen nur
ENTSCHIEDENE Saetze -- unentschiedene Saetze verschwanden spurlos. Aus
"6:4 5:5 2:6 6:3" wurden 2:2 Saetze, das 5:5 fehlte in jeder Summe.

Vorbild ist die Spielerstatistik, die mit saetze_unentschieden genau dieses
Feld schon fuehrt. Neue NULL-bare Spalten, NULL heisst unbekannt (Bestand vor
der Erfassung von Satzergebnissen), nie wird 0 unterstellt:

- teamspiel.teamspiel_saetze_remis: unentschiedene Saetze des Spiels, eine
  Zahl, fuer beide Seiten gleich
- begegnung.saetze_remis: Summe ueber die Spiele; NULL, sobald ein Spiel
  unbekannt ist (gleiche Regel wie bei den Toren)
- team.saetze_remis: Summe ueber die ausgetragenen Begegnungen, in
  teamstatistikAktualisieren mitberechnet

Berechnet wird der Wert in tools.php (saetzeRemisFuerSpiel, analog zu
toreFuerSpiel: nur bei punktetyp 1 mit Satzergebnissen bekannt, sonst NULL)
und an denselben beiden Stellen geschrieben wie die Tore: Speicherschleife
adminSaveBegegnungSpielplan() und begegnungenAktualisieren().

Migration: #306 ist nicht ausgeliefert, Datenbankversion 123 gehoert bereits
zu diesem Zweig -- die neuen Spalten erweitern deshalb den bestehenden
<123-Block in database/update.php (mit eigenen Spalten-Guards, damit eine
Instanz, die den bisherigen 123er-Stand schon traegt, nur das Fehlende
nachzieht) und die CREATEs in script.php.

Anzeige: im Je-Satz-Modus weist die Satz-Spalte der Tabelle die Remis-Saetze
kompakt mit aus ("6:5 (4)"), mit erklaerendem title (neuer Sprachschluessel
COM_SPORTSMANAGER_SETS_DRAWN); die Spaltenzahl waechst nicht. Ausserhalb des
Je-Satz-Modus bleibt team.saetze_remis NULL und die Anzeige unveraendert.
getTabelleSpieltag liefert den Wert je Spieltag ueber ein Subselect, das nur
im Je-Satz-Zweig erzeugt wird; die JSON-Ansicht reicht die Teamobjekte
unveraendert durch und traegt den Wert damit automatisch.
2026-09-10 07:26:31 +02:00
svennickel 7b8fbe6f45 Ein 5:5 ist eingetragen: das Signal "Ergebnis liegt vor" vom Punktestand loesen
Meldung von Sven (DTFB-IT): "Ist irgendwo zwischendurch ein 5:5 werden alle
Ergebnisse und Paarungen beim Speichern ab dort geloescht." Seine Vermutung
traf zu: teamspiel_*_punkte zaehlt nur ENTSCHIEDENE Saetze, und punkte == 0:0
gilt an mehreren Stellen als "nichts eingetragen". Wo Unentschieden normal
sind (Je-Satz-Modus, Satzergebnis-Erfassung), kollidiert das.

Gemessen an PRUEF Liga G (Modus 21, je Satz): eingetragen Spiel 1
"6:4 5:5 2:6 6:3", Spiel 2 "5:5 5:5", Spiel 3 "4:4 6:2 5:5 2:6" -- gespeichert
wurde nur Spiel 1. Spiel 2 ergibt Punkte 0:0, damit war die Behalte-Bedingung
(admin.php) und die do-while-Bedingung falsch, die Schleife endete, und
DELETE ... WHERE teamspiel_nummer >= $spiel_nr nahm Spiel 2 UND Spiel 3 mit.
Die falschen Gesamttore aus der Meldung sind eine Folge derselben Loeschung;
ohne komplett unentschiedenes Spiel stimmen sie exakt (47:42 = Handrechnung).

Ausserdem gemessen: eine Begegnung, deren Spiele ALLE unentschieden enden
(Begegnungspunkte 0:0), verschwand komplett aus der Tabelle -- die Mannschaft
zeigte danach "0 Siege, 0 Unentschieden, 1 Niederlage", Spielpunkte und Tore
der Begegnung fehlten. Grund: die Tabellenabfragen filtern Begegnungen mit
(heim_punkte != 0 OR gast_punkte != 0).

Behebung: ueberall dort, wo punkte != 0 als "es liegt ein Ergebnis vor"
dient, gilt zusaetzlich "ein Satzergebnis liegt vor" -- das Kriterium wird
erweitert, nie verengt:

- Speicherschleife adminSaveBegegnungSpielplan(): Behalte-Bedingung und
  do-while zusaetzlich !empty($ergebnis_detailliert). Auf teamspiel-Ebene ist
  ergebnis_detailliert das unmittelbare Zeugnis der Eingabe; es ist genau dann
  gefuellt, wenn Satzergebnisse eingetragen wurden.
- Wiederherstellungs-Block fuer Zwischenergebnisse: Punkte werden nur noch
  zurueckgeholt, wenn NEBEN 0:0 auch kein Satzergebnis gesendet wurde -- ein
  live eingetragenes "5:5 5:5" ist eine Eingabe, keine Luecke.
- Tabellenabfragen (getTabelleSpieltag, teamstatistikAktualisieren samt
  Buchholz-Paarungen): ausgetragen ist eine Begegnung mit punkte != 0 ODER
  heim_tore IS NOT NULL. Auf Begegnungsebene gibt es kein ergebnis_detailliert;
  heim_tore (Datenbankversion 123) wird beim Speichern genau dann gesetzt, wenn
  Satzergebnisse vorliegen, und ist damit dort das eindeutige Signal.
- Spieltag-Ermittlung (tabelle(), teamstatistikAktualisieren): ein Spieltag
  mit heim_spielpunkte 0:0 (Wertung "je Satz, Sieg 1": alle Spiele remis)
  zaehlt ueber NOT ISNULL(heim_tore) trotzdem als ausgetragen.

Bestandsmodi aendern sich nicht: ausserhalb der Satzergebnis-Erfassung ist
bei "nicht eingetragen" auch kein Satzergebnis vorhanden (ergebnis_detailliert
leer, heim_tore NULL), das erweiterte Kriterium bleibt dort wirkungslos. Die
SQL-Zusaetze sind an $je_satz gebunden bzw. haengen an Spalten, die in
Bestandsdaten NULL sind; die von getTabelleSpieltag erzeugten Abfragen bleiben
fuer Nicht-Je-Satz-Modi byteidentisch (Query-Log-Vergleich wie bei 49ce079).
2026-09-10 07:23:35 +02:00
svennickel cc07d7d53a Kein Satzstand je Spiel, wo je Satz gewertet wird
Sven 2026-09-09 mit Bildschirmfoto des Begegnungsformulars: „Bei dem Modus ‚für
jeden Satz einzeln' erscheint mir die Anzeige der Satzergebnisse bei den Spielen
nicht sinnvoll beim Bearbeiten der Begegnung. Zeige diese da nicht an."

Zu Recht: die Zeile „Saetze: 2:1" unter einem Spiel beantwortet dort eine Frage,
die in diesem Modus niemand stellt. Gewertet wird jeder Satz einzeln — der
Satzstand des Spiels entscheidet nichts mehr, und daneben steht bereits der
Gesamtstand, der die tatsaechlich vergebenen Spielpunkte zeigt.

Die Zeile entfaellt deshalb je Spiel, dessen Wertung „je Satz" ist (Einzel und
Doppel getrennt betrachtet, weil beide eine eigene Wertung haben koennen).

Die beiden VERBORGENEN Felder darunter bleiben in jedem Fall stehen: sie tragen
`spiel_N_heim_punkte`/`_gast_punkte` zum Server, und das Satz-JavaScript
beschreibt sie weiter. Nur die sichtbare Zeile faellt weg; das JS, das sie
fuellt, prueft ohnehin auf Vorhandensein (`if (anzeige != null)`) und laeuft
unveraendert.

Gemessen am Testserver:
  Liga G (je Satz):        0 Satzstand-Anzeigen, 6 verborgene Punktefelder
  Liga F (Satzdetail, aber
         Wertung je Spiel): 3 Anzeigen, 3 span-Elemente, 6 Punktefelder
2026-09-09 22:57:17 +02:00
svennickel 1a111b792f Je Satz in allen drei Punkteskalen, systematisch kodiert
Sven 2026-09-09: „Bei ‚Spielpunkt' ‚Für jeden Satz einzeln': hier wuerde ich
analog zu den Auswahlen oben ergaenzend noch ‚Sieg: 1 Punkt' und ‚Sieg: 3 Punkte,
Unentschieden: 1 Punkt' noch mit vorsehen wollen in geeigneter Reihenfolge." Und:
„solange es kompatibel zu dem Stand vor #304/#306 ist" — der Wert des Modus war
also frei gestaltbar.

Statt weitere Einzelwerte anzuhaengen (4, dann 5, dann 6) traegt der Wert die
Bedeutung jetzt selbst:

    Wert % 10  = die Punkteskala   (0 = Sieg 2/Remis 1, 1 = Sieg 3/Remis 1,
                                    2 = ohne Umrechnung, 3 = Sieg 1)
    Wert >= 10 = je SATZ statt je Spiel

    je Spiel:  3   0   1   2        je Satz:  13  10  11
                                              ^^  ^^  ^^ dieselbe Skala, +10

Die ueberlieferten Werte 0 bis 3 behalten damit ihre Bedeutung unveraendert —
das ist die geforderte Kompatibilitaet zum Stand vor #304. Und jede der drei
Rechenstellen leitet Siegwert und Remiswert aus demselben Grundwert ab, statt
einen Sonderfall je Wert zu fuehren: aus einer Fallunterscheidung mit vier
Zweigen wurden zwei Zeilen.

Der Entwicklungswert 4 (nur in #306, nie ausgeliefert) entfaellt ersatzlos; er
existierte allein auf dem Testserver und ist dort auf 10 gesetzt. Deshalb auch
keine Migration dafuer — in keiner Installation steht er.

Der Server nimmt nur noch die sieben gueltigen Werte an; alles andere faellt auf
0 zurueck. Fehlt die Satzerfassung, faellt eine Je-Satz-Wertung auf IHRE EIGENE
Skala je Spiel zurueck (13 -> 3, nicht mehr pauschal auf 0): die gewaehlte
Punkteskala ist eine andere Aussage als die Bezugsebene und bleibt erhalten.

VERIFIZIERT, alles gemessen statt angenommen:

1. Bestand unveraendert: Ausgangsstand gesichert, alle sieben Pruefmodi ueber die
   echten Formulare neu gespeichert, 784-Zeilen-Dump aller wertungsrelevanten
   Tabellen — IDENTISCH. Am Ende, nach dem Durchlauf aller drei neuen Skalen und
   Ruecksetzen auf 10, erneut identisch.
2. Spielpunkte je Skala gegen eine UNABHAENGIGE Nachrechnung in Python (parst
   ergebnis_detailliert selbst, kein PHP beteiligt): 8 Spiele + 3 Begegnungen,
   je Skala 0 Abweichungen. Darunter der Faelligkeitsfall, dass „Sieg 1 Punkt"
   fuer Unentschieden NICHTS gibt (Spiel mit 1 Sieg, 1 Niederlage, 2 Remis:
   1:1 statt 2:2) und der Rueckfall ohne Satzdetails (Skala x Satzsiege).
3. Spielerstatistik je Skala gegen dieselbe Art Nachrechnung: 7 Spieler, je
   Skala 0 Abweichungen. Siege/Unentschieden/Niederlagen sind ueber alle Skalen
   gleich (die Skala aendert nur Spielpunkte, nicht wer einen Satz gewann), die
   Spielpunkte skalieren mit 1/2/3.
4. Das erzeugte JavaScript traegt je Skala die passenden Faktoren
   (1*/0*, 2*/1*, 3*/1*) — aus der gerenderten Seite gelesen.
5. Die Auswahl zeigt drei Je-Satz-Eintraege in derselben Reihenfolge wie oben
   (Sieg 1, Sieg 2/Remis 1, Sieg 3/Remis 1); ohne Satzerfassung bleibt die ganze
   Gruppe verborgen.

Der Warnhinweis spricht nicht mehr von „2 Punkten je gewonnenem Satz", sondern
vom vollen Siegwert — mit drei Skalen waere die Zahl falsch gewesen.
2026-09-09 22:52:18 +02:00
svennickel fa63e1e2d6 Spielpunkte-Auswahl gruppieren, und die Hinweise brechen wieder um
Sven 2026-09-09 mit zwei Bildschirmfotos: „Benenne die Optionen geeignet,
geeignet angeordnet und gut unterscheidbar." Und: „Und brich die Beschreibungen
geeignet um."

1. DIE BESCHREIBUNGEN — ein Schaden, den 7f1bedc (Kommentare entfernen)
   angerichtet hat. Der Kommentar ueber der CSS-Regel .sm_hinweis war
   mehrzeilig; entfernt wurde nur seine ERSTE Zeile, weil nur die mit „/*"
   begann. Zurueck blieben vier Prosazeilen und ein verwaistes „*/" direkt hinter
   <style>. Der Browser liest das als Selektor und verwirft die ganze Regel — also
   fehlten `white-space: normal` und `max-width: 42em`, und jede Beschreibung lief
   in einer Zeile aus dem Bild. Genau das zeigt Svens Bildschirmfoto.

   Der Rest ist entfernt, die Regel gilt wieder. Gegengeprueft: im ganzen Zweig
   gibt es kein zweites unbalanciertes Kommentarzeichen (Klammerbilanz ueber alle
   sechs geaenderten Dateien; die uebrigen Treffer sind einzeilige Kommentare).

2. DIE AUSWAHL. Die neue Wertung stand am Ende und las sich fast wortgleich wie
   die zweite („Sieg: 2 Punkte, Unentschieden: 1 Punkt – je Satz" gegen „Sieg: 2
   Punkte, Unentschieden: 1 Punkt"). Jetzt zwei Gruppen:

     Fuer das ganze Spiel
        Sieg: 1 Punkt
        Sieg: 2 Punkte, Unentschieden: 1 Punkt
        Sieg: 3 Punkte, Unentschieden: 1 Punkt
        Ohne Umrechnung – Saetze sind die Spielpunkte
     Fuer jeden Satz einzeln
        Je Satz: Sieg 2 Punkte, Unentschieden 1 Punkt

   Das Unterscheidende steht ZUSAETZLICH im Eintrag selbst („Je Satz:" vorn), weil
   eine Gruppenueberschrift nur im aufgeklappten Zustand sichtbar ist — zugeklappt
   zeigt das Feld allein den Eintrag, und der muss fuer sich sprechen.

   Das Feld heisst nicht mehr „Spielpunkte pro Spiel", sondern „Spielpunkte": mit
   einer Wertung je Satz war die alte Beschriftung ihrem eigenen Inhalt
   widersprochen.

3. Beide Auswahlfelder (Einzel und Doppel) entstehen jetzt aus EINER Funktion.
   Vorher stand die Schleife zweimal da — dieselbe Bauart, die beim Remis-Vorfall
   auseinandergelaufen ist.

Gemessen am Testserver: Modus 21 (je Satz) zeigt beide Gruppen mit dem richtigen
gewaehlten Eintrag; Modus 15 („Mehrere" ohne Satzerfassung) und 16 („Einer")
zeigen die Je-Satz-Gruppe VERBORGEN. Die .sm_hinweis-Regel kommt wieder
unversehrt im Quelltext der Seite an.
2026-09-09 21:59:07 +02:00
svennickel 111fdeb306 Spielerstatistik im Je-Satz-Modus: jeder Satz zaehlt wie ein Spiel
Der STFV will in der Spielerstatistik jeden Satz als Spiel gezaehlt sehen.
spielerstatistikAktualisieren() holt dafuer im Veranstaltungs-Zweig
zusaetzlich ergebnis_detailliert und die beiden Wertungs-Spalten (der Join
auf teamspiel_modus existiert schon), bestimmt je Zeile Einzel oder Doppel
wie begegnungenAktualisieren ueber ISNULL(spieler_2_id) und zaehlt bei
Wertung 4 Siege/Unentschieden/Niederlagen und die Satz-Spalten je SATZ aus
runden_detailliert_auswertung — die angezeigte Spielezahl ist s+u+n und
wird damit von selbst zur Satzzahl. spg/spv bleiben die (im 4er-Modus
bereits satzbasierten) Spielpunkte; pg/pv bleiben die Punktesummen, also
Saetze — ihre Einheiten-Beschriftung haengt an punktetyp und bliebe bei
einer Tore-Umwidmung falsch. Ohne gespeicherte Satzergebnisse (App-Meldung
nur mit Satzstand) zaehlt das Spiel wie bisher als EIN Spiel aus dem
Punktevergleich — deterministisch, keine erfundenen Saetze.

Die S/U/N-Zaehlung und die Satz-Spalten laufen jetzt ueber dieselben drei
Zaehler (heim/unentschieden/gast je Zeile): fuer jede Wertung ausser 4
tragen sie exakt die alten 1-aus-3-Werte, das Ergebnis ist wertgleich zum
bisherigen if/else — bewiesen ueber die Messlatte, nicht nur hergeleitet:
11 Modi + 11 Begegnungen unveraendert gespeichert, voller Datenbank-Dump
(784 Zeilen) und Frontend-Dump (26987 Zeilen) vor/nach dem Wechsel — die
EINZIGEN Unterschiede sind die 7 bestenliste_punkte-Zeilen der
Je-Satz-Prueflige G, und dort nur s/u/n und sg/su/sv; spg/spv und pg/pv
jeder Zeile sind unveraendert. Alle sieben Bestands-Bestenlisten
(einschliesslich der Liga 'Mehrere mit Ergebnis je Satz' bei Wertung
Sieg 2/Remis 1, die weiter je SPIEL zaehlt) sind identisch.

Handrechnung dokumentiert an Spieler 115 der Prueflige G: Einzel
'6:4 4:4 2:6 6:3' (2/1/1), Doppel '4:4 4:4 6:2 2:6' (1/2/1), Doppel
'6:4 6:4 0:6 4:6' als Gast (2/0/2), dazu die Fallback-Begegnung ohne
Satzdetails als eine Niederlage (0/0/1): zusammen 5 Siege, 3 Unentschieden,
5 Niederlagen = 13 'Spiele' (Saetze), Spielpunkte 15:15, Punkte 6:6 —
exakt die gespeicherte Zeile.
2026-09-09 19:23:31 +02:00
svennickel 49ce079900 Tabellensortierung im Je-Satz-Modus: Begegnungspunkte, Spielpunkte, TORE
Im Je-Satz-Modus ist die Satzdifferenz nach der Spielpunkte-Differenz
vollstaendig redundant (Spielpunkte-Differenz = 2 x Satzdifferenz) — die
naechste Stufe, die wirklich trennt, sind die Tore (#306-Konzept, Abschnitt
0 und 3). Die Sortierung haengt am MODUS, nicht an neuen tabellenwertung-
Werten: so wirkt die Tore-Stufe automatisch in Differenz-, Quotienten-,
Buchholz- und Direktvergleichs-Varianten, ohne die Auswahlliste zu
verdoppeln. getTabelleSpieltag(), teamstatistikAktualisieren() und
getTabelleDirekterVergleich() ermitteln die Wertung des Modus jeweils per
eigenem kleinen SELECT und schieben bei Wertung 4 die Stufe tore_differenz
DESC (bzw. tore_quotient) ZWISCHEN Spielpunkte und Punkte; die Satz-Stufe
bleibt als letzter Tie-Break dahinter — sie schadet nie, und solange Tore
noch NULL sind, ordnet die Tabelle exakt wie bisher. Die Summen entstehen
als SUM ueber CASE je Begegnung ohne COALESCE: NULL traegt nichts bei,
unbekannt wird niemals 0:0. Die Platzvergabe (geteilte Plaetze) beachtet
die Tore an beiden Stellen (teamstatistik und HTML-Tabelle) mit — ohne das
teilten sich zwei nur durch Tore getrennte Teams Platz 1, gemessen am
Zwischenstand dieses Schrittes.

Die HTML-Tabelle zeigt die neue Stufe: im Je-Satz-Modus steht zwischen der
Saetze- und der Spiele-Spalte eine Tore-Spalte (Differenz bzw. Quotient,
absolut als Tooltip/Beiwert, "-" wo Tore unbekannt sind). Die JSON-Ansicht
bekommt die tore_*-Felder additiv ueber die ohnehin rohen Team-Zeilen.

Fuer alle anderen Modi entsteht BYTEIDENTISCHES SQL — nicht behauptet,
sondern geloggt: beide Fassungen im Testserver mit einem Query-Log
instrumentiert, 18 getTabelleSpieltag-Aufrufe (9 Ligen x 2 Spieltage) und
19 teamstatistik-Laeufe verglichen. Saemtliche Unterschiede betreffen
ausschliesslich die Je-Satz-Liga (2 Zusatzspalten, 2 Subselects, eine
ORDER-Stufe); jede Query einer Nicht-4-Liga ist Byte fuer Byte gleich.
Dazu dieselbe Messlatte wie bisher: 11 Modi + 11 Begegnungen unveraendert
gespeichert, Datenbank-Dump (778 Zeilen): 0 Unterschiede; Frontend-Dump
(9 Ligen x 3 Ansichten + 8 Statistiken): jede Abweichung ist eine
HINZUGEKOMMENE Zeile der Tore-Spalte der Je-Satz-Liga, keine einzige
bestehende Zeile geaendert oder entfernt.

Und der Fall, fuer den die Stufe da ist, ist konstruiert und gemessen
(Prueflige H): eine Remis-Begegnung, beide Teams mit Begegnungspunkten 1,
Spielpunkte-Differenz 0 und Satz-Differenz 0, aber Toren 35:34 gegen 34:35.
Alte Kette: beide Platz 1, alphabetisch sortiert (Adler vor Zebras). Neue
Kette: Zebras (+1 Tore) Platz 1, Adler (-1) Platz 2 — in team.platz wie in
der angezeigten Tabelle.
2026-09-09 19:21:15 +02:00
svennickel 64588f71ac Wertung 4: Sieg 2 / Unentschieden 1 — je SATZ (der STFV-Modus)
Der STFV wertet jeden gewonnenen Satz mit 2 Spielpunkten und jedes
Satz-Unentschieden mit 1 Punkt je Seite. Das ist ein neuer Wert der
bestehenden Stellschraube spielpunkte_wertung_* (tinyint, Wert 4), keine
neue Spalte und keine Kombinatorik (#306-Konzept, Abschnitt 1). Nach aussen
bleibt der Modus punktetyp 1 + satzergebnisse 1 — die Punkte eines Spiels
SIND weiter die gewonnenen Saetze, punktetyp behaelt seine zwei Werte.

Die Regel sitzt in spielpunkteFuerSpiel(): 2·gewonnene + 1·unentschiedene
Saetze je Seite aus ergebnis_detailliert; ohne Detail (App-Meldung nur mit
Satzstand) deterministisch 2·punkte — Satzsiege sind bekannt, Remis nicht.
Beide PHP-Rechenwege bekommen dadurch denselben neuen Fall geschenkt.

Das Formular bietet die Option nur an, wo sie rechenbar ist: sichtbar
allein bei "Mehrere - mit Ergebnis je Satz" (data-satzdetails-Option,
zeilen_anzeigen() blendet sie sonst aus und stellt die Auswahl zurueck).
Der Server verlaesst sich darauf nicht: kommt Wertung 4 ohne punktetyp 1 +
satzergebnisse 1 an, faellt sie auf 0 zurueck (Sieg 2/Remis 1 je Spiel, die
naechstliegende Je-Spiel-Regel) — die Spielform dominiert, wie im
Bestandscode. Race schliesst 4 automatisch aus, weil Race Wertung 2
erzwingt. Gemessen an drei ueber das echte Formular geposteten Modi:
Einer+4 -> 0, Mehrere-ohne-Satzerfassung+4 -> 0, Race+4 -> 2. Und der
Warnhinweis beim Speichern mit Bestandsergebnissen nennt jetzt auch den
STFV-Altbestandsfall: wo unter "Mehrere" in Wahrheit Tore in den
Punkte-Feldern stehen, zaehlt nach dem Wechsel jedes Tor wie ein gewonnener
Satz doppelt — umgerechnet wird nichts.

Die DRITTE Rechenstelle rechnet mit — die Lehre aus dem Remis-Vorfall
(Formular 7:3, Server 6:2): das erzeugte Formular-JavaScript bekommt EINE
gemeinsame Satzsummen-Hilfsfunktion (satz_summen liest die
_punkte_detailliert-Felder und ueberspringt 0:0-Saetze wie die
Satz-Zaehlschleife des Servers), und BEIDE Verbraucher benutzen sie:
gesamtstand_aktualisieren() und spielpunkte_bedingung(). Aus den
spiel_N_*_punkte-Feldern duerfen beide im 4er-Modus nicht mehr rechnen —
dort stehen Saetze, eine Je-Spiel-Wertung waere falsch.

End-to-end gemessen an der neuen Prueflige G (Modus ueber das echte
Formular angelegt: 3 Spiele E/E/D, 4 feste Saetze, Wertung je Satz;
punkte_sieg wird -3 gespiegelt):

  - Begegnung 117 mit Satz-Remis in allen drei Spielen ("6:4 4:4 2:6 6:3",
    "1:6 2:6 6:6 0:6", "4:4 4:4 6:2 2:6"): gespeichert 5:3, 1:7, 4:4 —
    Begegnung 10:14 Spielpunkte, 3:5 Saetze, 43:57 Tore. Handrechnung
    identisch.
  - JS-Paritaet nicht nur gelesen, sondern gerechnet: das vom PHP erzeugte
    JavaScript aus der gerenderten Seite in node gegen dieselben Feldwerte
    laufen lassen — gesamtstand_aktualisieren liefert 10:14,
    spielpunkte_bedingung summiert 10/14, satz_summen je Spiel
    [2,1,1] [0,1,3] [1,2,1]; die Datenbank derselben Begegnung sagt 10:14.
  - Fallback gemessen (Begegnung 119, Meldung wie ein Altclient nur mit
    Satzstand 2:1 und 1:1): Spielpunkte 4:2 und 2:2 (= 2·punkte),
    ergebnis_detailliert bleibt leer, Tore bleiben NULL.
  - Bestandsmodi unveraendert: dieselbe Messlatte wie bei den beiden
    Schritten zuvor (10 Modi + 10 Begegnungen unveraendert gespeichert,
    756 Zeilen Datenbank-Dump, 30995 Zeilen Frontend-HTML): VOLLSTAENDIG
    identisch.

Neue Sprachschluessel DE/EN: die Option ("Sieg: 2 Punkte, Unentschieden:
1 Punkt - je Satz") und der erweiterte Warnhinweis.
2026-09-09 19:09:12 +02:00
svennickel 79f3abc01a Torsummen als eigene Spalten, NULL heisst unbekannt (Datenbankversion 123)
Die STFV-Tabellensortierung braucht als letzte inhaltliche Stufe die Tore — und
die stehen bisher ausschliesslich im tinytext ergebnis_detailliert, wo kein SQL
sie lesen kann (#306-Konzept, Abschnitt 2). Also neue, durchweg NULL-bare
Spalten: teamspiel_heim_tore/gast_tore, begegnung.heim_tore/gast_tore und
team.tore_gewonnen/verloren/differenz/quotient (Typen nach punkte_*-Vorbild).

toreFuerSpiel() in tools.php ist die einzige Rechenstelle: bei punktetyp 0 sind
die Punkte die Tore; wo Satzergebnisse gefuehrt werden (satzergebnisse 1),
werden sie aus ergebnis_detailliert summiert (runden_detailliert_auswertung);
sonst NULL — unter "Mehrere" ohne Satzerfassung spiegelt das Detail nur den
Satzstand, eine Torzahl steht dort nicht und stand dort nie. Geschrieben wird
an denselben zwei Stellen wie die Spielpunkte (Spielbericht speichern und
begegnungenAktualisieren), immer paarweise gesetzt oder paarweise NULL; das
Loeschen des Spielberichts nullt die Begegnungssummen mit. team.tore_* rechnet
teamstatistikAktualisieren immer mit — als SUM ueber CASE je Begegnung, OHNE
COALESCE: eine Begegnung mit unbekannten Toren traegt nichts bei, unbekannt
wird niemals als 0:0 gewertet. Gemessen an Prueflige F: ein geleertes
ergebnis_detailliert macht Spiel, Begegnung und die Differenz beider Teams
NULL (135/147 -> 85/98), die Wiederherstellung stellt exakt den alten Stand her.

KEIN Backfill in der Migration: updateDatabase() ruft begegnungenAktualisieren()
nicht auf, und ein Update soll gespeicherte Werte nicht anfassen. Gemessen: nach
Einspielen und einem Seitenaufruf steht die Version auf 123, alle 455 + 116 + 32
Tore-Felder sind NULL. Befuellt wird beim naechsten Speichern eines Berichts
bzw. komplett beim Speichern des Modus — gemessen ueber alle acht Ligen:
Einer/Race tragen Tore = Punkte (Damenbundesliga 42:31 -> 42:31), Satzerfassung
summiert die Saetze ("5:3 4:4 2:6 6:1" -> 17:14, Begegnung 50:49), "Mehrere"
ohne Satzerfassung bleibt ehrlich NULL (PRUEF Liga A, 30 Spiele, 0 Tore-Werte).

Beide Pflegeorte: Migration <123 in database/update.php (getTableColumns-Guard
je Tabelle, Versionsschreiben am Ende) UND die CREATEs in script.php samt
datenbank_version 123. Gemessen per probe_-Tabellen aus den Neuinstallations-
CREATEs gegen die migrierten Tabellen (information_schema: Name, Position, Typ,
Nullable, Default): alle drei Tabellen spaltenidentisch.

Bestand unberuehrt, gemessen mit derselben Messlatte wie beim Refactoring:
alle zehn Modi und dieselben zehn Begegnungen unveraendert erneut gespeichert,
danach Datenbank-Dump der Bestandsspalten (756 Zeilen) und Frontend-Dump
(30995 Zeilen HTML) gegen den Lauf mit dem alten Code verglichen:
VOLLSTAENDIG identisch.
2026-09-09 18:56:02 +02:00
svennickel e1a0637795 Spielpunkte-Regel an eine Stelle: spielpunkteFuerSpiel() in tools.php
Vorarbeit fuer die STFV-Satzwertung (#304/#306-Konzept, Abschnitt 6): die
Spielpunkte-Kaskade stand woertlich doppelt im PHP — einmal beim Speichern des
Spielberichts (admin.php, Rechenweg A), einmal in begegnungenAktualisieren()
(sportsmanager.php, Rechenweg B). Der Remis-Vorfall (35384a5, 5d1df85) ist genau
aus dieser Doppelung entstanden. Bevor eine vierte Wertung dazukommt, wird die
Regel EINE Funktion: spielpunkteFuerSpiel(wertung, heim, gast) in tools.php,
beide Wege rufen sie nur noch auf. Reine Umformung, keine Verhaltensaenderung;
die dritte Rechenstelle (das erzeugte Formular-JavaScript) bleibt in diesem
Schritt unangetastet.

Gemessen, nicht nur begruendet — vorab wurden vier weitere Prueflige angelegt,
damit ALLE Wertungen und Spielformen unter der Messlatte liegen (C = Sieg 3/
Remis 1, D = Sieg 1, E = Race mit 9:9-Abbruch, F = Mehrere mit Ergebnis je Satz
samt Satz-Remis; dazu die bestehenden A = Gewinnsaetze, B = Einer sowie
Damenbundesliga und Testliga). Ablauf identisch vor und nach der Umformung:
alle zehn Modi unveraendert durchs Formular gespeichert (Rechenweg B ueber alle
116 Begegnungen), dazu zehn Begegnungen quer durch alle Ligen unveraendert
durchs Spielbericht-Formular (Rechenweg A). Danach verglichen:

  - Datenbank-Dump (116 Begegnungen, 455 teamspiel-Zeilen, 32 Team-Zeilen,
    138 bestenliste_punkte-Zeilen, 756 Zeilen gesamt): VOLLSTAENDIG identisch.
  - Frontend-Dump (8 Ligen je 3 Spieltagsansichten + 7 Spielerstatistiken,
    30995 Zeilen HTML): VOLLSTAENDIG identisch.
2026-09-09 18:46:01 +02:00
svennickel 5d1df8579d Gleicher Satzstand bleibt ein Unentschieden — die Sonderregel kommt weg
Sven beim Testen von Begegnung 93 (2:2 im Doppel, Modus 3 Gewinnsaetze,
Wertung Sieg 2/Remis 1): das Formular rechnete 7:3 vor, gespeichert wurde 6:2.
„Und das ist meinem Verstaendnis nach doch auch das richtige Ergebnis?" — ja.

Zwei Fehler in einem:

1. Die Spielpunkte werden an DREI Stellen berechnet, nicht an zweien: zusaetzlich
   zu admin.php und begegnungenAktualisieren() rechnet das Formular selbst per
   JavaScript mit (view_admin.php, spielpunkte_bedingung()). 554ad25/35384a5
   hatten die Remis-Sonderregel in die ersten beiden eingebaut, die dritte lief
   nach der alten Regel weiter — daher 7:3 gegen 6:2.

2. Die Sonderregel selbst war falsch. „Unentschieden nur, wo der Satzmodus es
   zulaesst" war eine Ableitung aus 554ad25, keine Anforderung. Die Wertung
   sagt ausdruecklich „Sieg 2 Punkte, Unentschieden 1 Punkt" — das ist eine
   Anweisung fuer den gleichen Stand, und eine Zahl von Gewinnsaetzen sagt nur,
   WANN ein Spiel endet, nicht dass ein gleicher Stand wertlos ist. Spiele
   enden faktisch gleich (Abbruch, Zeitlimit, Absprache); ein 0:0 an der Stelle
   verliert dieselbe Information, die es schuetzen wollte.

Also: remisMoeglich() samt beiden Verwendungen entfernt, alle drei Wege rechnen
wieder die langjaehrige Regel. Gemessen auf zwei Pruefligen (je 6 Begegnungen,
30 Spiele, 4 Gleichstaende ungleich 0:0): die auf demselben Datenbestand neu
berechneten Tabellen sind zwischen dem Stand vor diesem PR und danach
VOLLSTAENDIG identisch — keine einzige Zahl weicht ab. Begegnung 93 zeigt im
Formular, auf der Seite und in der Datenbank uebereinstimmend 7:3.
2026-09-08 18:31:24 +02:00
svennickel 7f1bedc41e Kommentare aus dem Quelltext entfernen
Aus dem Review: „Der Quelltext ist absolut ueberkommentiert." Nach dem Kuerzen
in 554ad25 jetzt vollstaendig — 294 Kommentarzeilen aus fuenf Dateien.

Nachgewiesen unveraendert: der Diff ohne Kommentar- und Leerzeilen gegen
5aee028 ist vor und nach dieser Aenderung derselbe (gleiche Pruefsumme). Es ist
also ausschliesslich Kommentar entfernt worden, keine Zeile Programmtext.

Entfernt wurden nur die von diesem Zweig HINZUGEFUEGTEN Kommentare; jeder
Kommentar, der im alten Stand schon stand, bleibt unangetastet (auch dort, wo
Formularzeilen verschoben wurden).
2026-09-08 18:17:24 +02:00
svennickel 35384a5c43 Die Remis-Regel galt nur auf einem der beiden Rechenwege
Sven 2026-09-08: „Teste fuer alle Modus, ob Siege, Unentschieden und
Niederlagen weiter korrekt berechnet werden pro Spiel fuer saemtliche
Modusszenarien."

Beim Testen ueber die volle Matrix (4 Spielpunkte-Wertungen x 7 Satzmodi x 4
Spielstaende = 112 Szenarien) kam ein Fehler DIESES Zweigs heraus: die
Spielpunkte werden an ZWEI Stellen berechnet, und 09ae1c1/554ad25 hatte die
Remis-Pruefung nur in eine davon eingebaut.

  Weg A  admin.php, Spielbericht speichern        — MIT Pruefung
  Weg B  sportsmanager.php, begegnungenAktualisieren() bei Modus-/
         Wettbewerbsaenderung                     — OHNE Pruefung

Dasselbe Spiel bekam damit verschiedene Spielpunkte, je nachdem, welcher Weg es
zuletzt angefasst hatte: Speichern ergab 0:0, ein Moduswechsel schrieb 1:1
zurueck. Betroffen sind Gleichstaende ungleich 0:0 in Wettbewerben, deren
Satzmodus kein Remis zulaesst (ein fester Satz, ungerade Satzzahl,
Gewinnsaetze) bei Wertung „Sieg 2/Remis 1" oder „Sieg 3/Remis 1" — 8 der 112
Szenarien. Gemessen, nicht geschaetzt.

Die Regel steht jetzt als remisMoeglich() auf Dateiebene und wird von beiden
Wegen aufgerufen, statt als Closure in einem der beiden Loops zu leben.
Matrix danach: 0 Widersprueche.

NICHT betroffen und mitgeprueft:
- Siege/Unentschieden/Niederlagen je Spiel sind in ALLEN 112 Szenarien
  unveraendert. Sie kommen in der Spielerstatistik aus dem Vergleich der
  PUNKTE (sportsmanager.php:6338), nicht aus den Spielpunkten, und an den
  Punkten aendert dieser Zweig nichts.
- Race bleibt unberuehrt: die Race-Normalisierung setzt die Wertung auf 2
  („ohne Umrechnung"), und dort gibt es keinen Remis-Zweig.
- spielerstatistikAktualisieren() selbst ist unveraendert (nur die
  Einheiten-Beschriftung kam hinzu).
2026-09-08 17:46:38 +02:00
svennickel 2c4b3e0908 Spielpunkte-Wertung neben die Einheit, die sie uebernimmt
Sven 2026-09-08: „hier wuerde ich die Option direkt unter ‚Saetze pro Spiel'
ziehen und abhaengig von der Einstellung bei ‚Saetze pro Spiel' benennen".

Die vierte Wertung („ohne Umrechnung") uebernimmt das Spielergebnis als
Spielpunkte — welche Zahl das ist, sagt aber ein ANDERES Feld: Tore bei
„Einer", Saetze bei „Mehrere". Sie stand bisher zwei Gruppen weiter oben unter
„Begegnung", also getrennt von der Angabe, die ihre Bedeutung festlegt.

- „Spielpunkte pro Spiel" (Einzel + Doppel) sitzt jetzt direkt unter „Saetze
  pro Spiel" in der Gruppe „Spiel" — wo sie hingehoert: es ist eine Angabe zum
  einzelnen Spiel, nicht zur Begegnung. „Begegnung abgeschlossen bei" bleibt in
  der Gruppe „Begegnung".
- Der Eintrag heisst jetzt nach der gewaehlten Einheit: „Ohne Umrechnung –
  Saetze sind die Spielpunkte" bzw. „… Tore sind die Spielpunkte". Ueber
  dasselbe data-tore/data-saetze-Verfahren, das die Siegbedingungen schon
  benutzen; umgeschaltet in zeilen_anzeigen(), also auch beim Wechseln ohne
  Neuladen. Der alte Sammeltext bleibt als Rueckfall stehen.
- Am lokalen Testserver gerendert und geprueft: Reihenfolge stimmt, beide
  Texte kommen uebersetzt an.
- Nebenbei: der Kommentar nannte Datenbankversion 126, tatsaechlich ist es 122.
2026-09-08 16:08:44 +02:00
svennickel 84211e9f9e Ergebnisanzeige, Spielerstatistik, und die Spielfolge bleibt schmal
Drei weitere Punkte aus dem Review.

1. ERGEBNISANZEIGE BEI SAETZEN. Im Spielbericht stand je Spiel NUR ergebnis_detailliert. Bei
reinem „Mehrere" ist das derselbe Satzstand — bei Erfassung je Satz sind es die Saetze, und
dann fehlte, wer das Spiel gewonnen hat. Gemessen: die Zeilen lasen „6:3 | 3:6" ohne jede
Angabe des Standes. Jetzt steht der Stand davor und die Saetze in Klammern dahinter:
„1:1 (6:3 | 3:6)", „2:1 (6:3 | 3:6 | 6:4)". Wo beides dasselbe ist („Einer", oder „Mehrere"
ohne Satzerfassung), bleibt es einzeilig — gegengeprueft an einer Begegnung aus der
Einer-Zeit: unveraendert „6:3", nichts doppelt. Ein nicht gespieltes Spiel bleibt leer und
zeigt kein „0:0".

2. SPIELERSTATISTIK. Die Spalten „T +/-" summieren teamspiel_*_punkte, zaehlen also je
punktetyp Tore oder gewonnene Saetze — hiessen aber immer „Tore". Anders als in der Tabelle
gibt es hier nicht einen Modus: eine Bestenliste kann mehrere Wettbewerbe umfassen, sogar
Individualwettbewerbe. spielerstatistikEinheit() liest deshalb den punktetyp der speisenden
Wettbewerbe; sind sie einig, steht die richtige Einheit, sonst „Punkte" — statt eine zu
behaupten, die nicht fuer alle Zeilen gilt. Neuer Schluessel COM_SPORTSMANAGER_SETS_SHORTCUT
in beiden Sprachen. Alle drei Faelle gemessen: nur „Mehrere" -> „S +/-" mit „Saetze",
gemischt -> „P +/-" mit „Punkte", zurueck -> wieder „S".

Und der Tooltip der Tabellenspalte hiess COM_SPORTSMANAGER_DIFFERENCE = „Differenz Tore",
widersprach also der neuen Beschriftung „Saetze". Er nennt jetzt nur die Rechenart
(„Differenz"), wie sein Geschwister „Verhaeltnis" schon immer; die Einheit steht in der
Spalte. Einzige Verwendungsstelle.

3. SPIELFOLGE. Die sechs Auswahlfelder der Spielfolge und der Verknuepfungen stehen wieder
auf medium — sie tragen kurze Werte und sollten nicht mitwachsen. Breit bleiben nur die 33
Felder der Einstellungen, wo die langen Beschriftungen stehen.
2026-09-07 18:01:58 +02:00
svennickel 099174c0ef Tabellenspalte richtig benennen: bei „Mehrere" sind es Saetze, keine Tore
Aus dem Review: „Die Summe der Tore ist auch falsch." Sie ist es nicht — sie ist falsch
BESCHRIFTET. Unter punktetyp „Mehrere" ist begegnung.heim_punkte seit immer die Summe der
Satzstaende, und die Tabellenspalte heisst „Tore". Bisher fiel das nicht auf, weil die Tore
gar nicht bekannt waren; mit der Erfassung je Satz sind sie es, und die Spalte behauptet
etwas, was sie nicht zeigt.

Die Absicht war schon da: tabelleAnzeigen() fragt `punktetyp != 2 ? Tore : Saetze` — nur
kennt punktetyp ausschliesslich 0 und 1, die Bedingung war also nie wahr. Jetzt
`punktetyp == 0 ? Tore : Saetze`, an beiden Spaltenkoepfen (Absolut und Differenz/Verhaeltnis).

Gemessen an zwei Wettbewerben derselben Installation: bei punktetyp 1 stehen jetzt „Saetze
Absolut" und „Saetze", bei punktetyp 0 unveraendert dreimal „Tore". Keine Zahl aendert
sich, kein Sortierschluessel, keine Bestandsdaten.

Die Alternative — die echten Tore summieren, wo Satzergebnisse geführt werden — waere ein
Eingriff in Bestandsstaende und in die Tabellensortierung und gehoert in einen eigenen PR
mit Migration (Sven 2026-09-07).
2026-09-07 13:52:35 +02:00
svennickel 554ad25156 Review: Unentschieden nur, wo es moeglich ist; Kommentare gekuerzt; Felder breiter
Drei Punkte aus dem Review.

1. UNENTSCHIEDEN, WO ES KEINES GIBT. Gemeldet: „2 Punkte pro Spiel und 1 Punkt
unentschieden ausgewaehlt, es kommt aber nur 1 Punkt pro Spiel." Nachgestellt an einer
Begegnung mit vier Spielen (Modus: Mehrere, Ergebnis je Satz, 3 Gewinnsaetze, Wertung
„Sieg 2, Remis 1"): Spiel 1 mit 6:3 3:6 steht 1:1 nach Saetzen und bekam 1:1 Spielpunkte.

Bei einer Zahl von GEWINNSAETZEN ist ein gleicher Satzstand aber kein Unentschieden,
sondern ein unfertiges Spiel — dafuer gibt es keinen Punkt. Die Rechnung fragt jetzt, ob
der Modus ueberhaupt ein Remis zulaesst: bei Gewinnsaetzen nein, bei fester Satzzahl nur
bei gerader Zahl, ohne Angabe wie bisher. Gemessen an derselben Meldung: Spiel 1 jetzt
0:0, die Begegnung 6:0 statt 7:1; die Spiele 2 bis 4 unveraendert 2:0.

Die Rechnung selbst ist Altbestand und von diesem PR nicht angefasst — erst die neue
Satzzahl liefert die Information, mit der sie unterscheiden kann.

2. KOMMENTARE. Zu Recht beanstandet. Was Sprachmechanik erklaert oder den Code
nacherzaehlt, ist raus; was eine Entscheidung oder einen Messwert festhaelt, bleibt in
hoechstens drei Zeilen. Die Herleitung gehoert in den PR-Text, nicht in die Datei.
update.php von 87 auf 22 Kommentarzeilen (57 % auf 25 % der Aenderung), ueber alle Dateien
von 459 auf 267.

3. AUSWAHLFELDER. Die 39 Auswahlfelder des Modus-Formulars stehen von medium (200 px) auf
large (500 px). Bei 200 px brach eine Beschriftung wie „Ohne Umrechnung - Tore bzw. Saetze
sind die Spielpunkte" ab. Nur dieses Formular, keine andere Ansicht.

Danach geprueft: sechs Ansichten HTTP 200 ohne PHP-Meldung, php -l sauber, dieselbe Meldung
mit dem erwarteten Ergebnis.
2026-09-07 13:30:21 +02:00
svennickel 09ae1c1609 Siegbedingungen vollstaendig abbilden, samt Race-Modus (#304)
Vorsprung und Deckelung je Spiel, dieselbe Regel eine Ebene tiefer fuer den
einzelnen Satz, eine Auswahl der Satzzahl (feste Zahl oder Gewinnsaetze) samt
optional abweichender Regel fuer den Entscheidungssatz, eine Auswahl
"Mehrere - mit Ergebnis je Satz" mit Satzzeilen im Begegnungsformular — und
eine Zaehlweise "Race-Modus", in der der Stand ueber die ganze Begegnung
durchlaeuft.

Die Regel beschreibt den Wettbewerb, sie lehnt keine Eingabe ab: ein 8:6 dort,
wo ein Spiel bei 6 endet, hat oft einen Grund, den keine Regel kennt, und ueber
die Richtigkeit wachen beide Mannschaften. Ihr Nutzen liegt darin, dass eine
auswertende Anwendung endlich erkennen kann, ob ein Spiel entschieden ist.

RACE-MODUS. Das Spiel N endet, wenn der LAUFENDE Stand einer Seite N mal den
Schritt erreicht; eingetragen wird wie bisher die DIFFERENZ dieses Spiels, und
der Begegnungsstand bleibt ihre Summe. Gemessen an 91 Bundesliga-Begegnungen:
6:5 5:7 7:5 4:7 8:2 6:9 6:5 summiert sich auf 42:40, und laufend gelesen trifft
jedes Spiel seine Etappe (6, 12, 18, 24, 30, 36, 42). Die Ergaenzung im Formular
rechnet deshalb mit laufenden Staenden und zieht ab, was schon auf dem Konto
steht.

Im Formular steht statt des gespeicherten "Zwischenergebnis" jetzt der
GESAMTSTAND, gross und in Echtzeit: die Spielpunkte, gerechnet aus den
eingetragenen Spielen mit derselben Arithmetik, die der Server beim Speichern
anwendet. Es ist DIE Zahl, die die Begegnung nach aussen hat — Liste,
Mannschaftsseite und die Kopfzeile der Begegnungsdetails zeigen alle
heim_spielpunkte:gast_spielpunkte. Gemessen an einem 5er-Spielplan mit "Sieg: 1
Punkt": ein eingetragenes 6:4 ergibt "1:0", genau wie die Details. Die Torsumme
gehoert dagegen in die Tabellenspalte "Tore" und nicht in den Kopf einer
Begegnung. Die Zeile steht als letzte des Kopfes, unter dem Kommentar, mit
demselben senkrechten Abstand, den die Spiele untereinander haben — und ohne
erklaerenden Zusatz: "Gesamtstand" samt Zahl sagt es selbst.

Das Ziel wird nicht eingegeben, sondern folgt aus der Spielfolge. Dort steht
deshalb die Rechenvorschrift ("Anzahl der Spiele aus der Spielfolge x Schritt je
Spiel") und die konkrete Zahl erst ab zwei Spielen ("derzeit 7 Spiele x 6 = 42
Tore"): bei einem einzigen — dem Anfangszustand — waere "1 Spiele x 6 = 6 Tore"
nicht nur ungrammatisch, sondern eine Auskunft ueber einen Zustand, den niemand
gemeint hat. Mindestvorsprung, Grenze und ein moegliches
Unentschieden gelten nur fuer das letzte Spiel. Die Zaehlweise setzt
"Spielergebnis als Spielpunkte" und einen Satz je Spiel voraus und setzt beides
mit; das Ziel wird zusaetzlich nach punkte_sieg_* gespiegelt (mit Vorzeichen
fuer das Unentschieden), damit eine aeltere Programmfassung dieselbe wahre
Aussage liest. Vorrunde und Hauptrunde sind zwei Mannschaftsspielplaene. Die Zaehlweise steht als
erste Zeile ihrer Gruppe: was sie ausblendet, liegt darunter — Felder ueber einer
Auswahl verschwinden zu lassen, liest sich als Fehler.

Damit die Einstellungen ueberhaupt auseinanderzuhalten sind, steht dem Editor
eine kurze Begriffsleiter voran: Begegnung, Spiel, Satz, Tor. Sie stecken
ineinander, und die Gruppen darunter folgen genau dieser Reihenfolge. Drei
weitere Hinweiszeilen sagen, was "Ergebnis je Satz" bedeutet, wozu die Angaben
gut sind und wie der Race-Modus zaehlt.

Die vierte Spielpunkte-Wertung hiess "Keine" und sagte damit das Gegenteil
dessen, was sie tut: gewertet wird alles, nur ohne Umrechnung — das Ergebnis
des Spiels IST sein Spielpunktestand. Sie heisst jetzt "Ohne Umrechnung - Tore
bzw. Saetze sind die Spielpunkte"; die drei uebrigen beginnen mit "Sieg:", also
sagt schon der Satzanfang, dass es hier nicht um einen Sieg-Wert geht.

Die Hinweiszeilen brechen ausdruecklich um und haben ein Mass (max-width): die
Zellen dieses Formulars tragen alle `nowrap`, was fuer Beschriftungen und
Auswahlfelder richtig ist und fuer Prosa falsch — die Hinweise zogen die Tabelle
sonst beliebig breit. Wo ein Hinweis steht, ist die Beschriftung oben
ausgerichtet: sonst stand sie auf halber Hoehe des Absatzes statt neben dem
Auswahlfeld, zu dem sie gehoert.

Die Satzebene fuehrt dasselbe Vorzeichen wie die Spielebene: der Betrag ist der
Siegwert, ein negatives Vorzeichen erlaubt zusaetzlich ein Unentschieden ein Tor
darunter. Ohne diese Faelle waere ein Satz, der remis endet, gar nicht
hinterlegbar gewesen.

Bestehende "Mehrere"-Modi werden in die Satzzahl UEBERFUEHRT, und zwar restlos: 1 wird ein fester Satz, ein positiver Wert N werden N
Gewinnsaetze, ein negativer wird die feste Satzzahl 2(|N|-1) — denn ein Remis
setzt voraus, dass alle Saetze gespielt werden. Auch Werte jenseits der neuen
Auswahl werden ueberfuehrt statt als "Beliebig" liegen zu bleiben, denn sie sind
nicht unsinnig, nur ungewoehnlich: ein gespeichertes "Spiel gewonnen bei 42
Saetzen" bleibt nach der Ueberfuehrung dieselbe wahre Aussage, nur an der
richtigen Stelle. Das Formular zeigt einen solchen Wert als EIGENEN,
vorgewaehlten Eintrag der Auswahl ("42 Gewinnsaetze"), speichert ihn unveraendert
wieder und bietet ihn, einmal weggestellt, nicht mehr an. Sonst haette dort eine
Zeile ohne Auswahlfeld gestanden — die Beschriftung "Spiel abgeschlossen bei:"
und rechts daneben nichts — oder die Zahl waere beim ersten Speichern
verschwunden. Gemessen an drei Bestandswerten: 42 wird -42 und uebersteht Anzeige
und Speichern unveraendert, -9 wird die feste Satzzahl 16, und nach dem Wechsel
auf "3 Gewinnsaetze" hat die Auswahl 18 statt 19 Eintraege. Der Race-Modus wird
NICHT automatisch erkannt; er ist aus Bestandsdaten nicht sicher abzuleiten und
wird einmal von Hand gewaehlt.

Dass die Ueberfuehrung nichts verschiebt, ist gemessen und nicht bloss
begruendet: dieselbe Datenbank einmal unter der alten Fassung mit altem Schema
und einmal unter dieser, je sieben Begegnungen unveraendert neu gespeichert und
dann Tabellen, Uebersicht, Spielerstatistik und drei Begegnungsdetails
verglichen — 7942 Zeilen HTML und 436 Datenzeilen aus begegnung und teamspiel,
kein einziger Unterschied. Darunter der Bestandsmodus mit punkte_sieg 42, den
die Ueberfuehrung anfasst.

Umgekehrt spiegelt der Editor die Satzzahl VOLLSTAENDIG nach punkte_sieg_*
zurueck, nicht nur bei Gewinnsaetzen: eine feste Satzzahl sagt genau, welche
Endstaende es gibt, und damit auch, bei welchem Stand das Spiel entschieden ist —
4 feste Saetze heissen "gewonnen bei 3, Unentschieden bei 2:2" (-3), 3 feste
Saetze "gewonnen bei 2" (2). Das ist die Umkehrung der Ueberfuehrung und deshalb
verlustfrei. Zuvor blieb punkte_sieg_* bei fester Satzzahl leer, mit der
Begruendung, sie sei keine Siegbedingung — richtig gedacht, aber praktisch falsch:
ein Client, der nur die alten Felder kennt, haette nach einmaligem Oeffnen und
Speichern eines Bestandsmodus "Beliebig" gelesen, wo vorher eine Zahl stand. Und
es gibt einen solchen Client, den wir nicht mitziehen koennen (Kickern). Gemessen:
feste Satzzahl 4 -> -3, 3 -> 2, 6 -> -4, 1 -> 1, und Gewinnsaetze unveraendert
3 -> 3, 2 -> 2.

Die Einheit der Spielebene folgt punktetyp: Tore bei "Einer", Saetze bei
"Mehrere". Bisher stand dort in beiden Faellen "Punkte" — und genau daran war
eine Fehlkonfiguration nicht zu erkennen. Am echten TFVB-Spielplan 2026 sah man
es doppelt: "Spiel abgeschlossen bei 5 Punkte" direkt ueber "Mindestvorsprung 2
Tore", dieselbe Einheit in zwei Woertern. Innerhalb eines Satzes wird ohnehin
durchgaengig von Toren gesprochen.

Und "Spiele in Spielerstatistik" waehlt "Alle Spiele" jetzt ausdruecklich vor,
statt sich darauf zu verlassen, dass es die erste Option ist. Aus "Vorsprung" wird "Mindestvorsprung" (und
der Wert 1 heisst "Keiner"), aus "Deckelung" wird "Spaetestens gewonnen bei".

Die Einstellungen sind in fuenf Gruppen geordnet, vom Grossen ins Kleine:
Allgemein, Begegnung, Spiel, Satz, Spieler und Statistik. Dafuer wechseln drei
bestehende Zeilen den Platz — "Aktiv" nach oben zu "Bezeichnung",
"Spielernamen" hinunter zu "Spiele in Spielerstatistik", und die Gruppe
"Begegnung" vor die Gruppe "Spiel"; sonst ist nichts verschoben. Der Knopf
"Doppel getrennt einstellen" bekommt eine eigene Zeile, weil er auch die
Satzregel schaltet. Eine Gruppe ohne sichtbare Zeile zeigt keine Ueberschrift.

Die Spielfolge zeigt nur noch die Zeilen, die es gibt: Spiel 1 steht fest, weitere
kommen ueber "Spiel hinzufuegen", jede weitere traegt ein Kreuz zum Entfernen — ohne
Rueckfrage, denn gespeichert ist bis zum Speichern nichts. Verknuepfungen fangen bei
null an. Alle Zeilen bleiben im Dokument und werden beim Entfernen nach oben geschoben,
weil das Speichern spiel_1, spiel_2 … der Reihe nach liest und beim ersten leeren Paar
abbricht. Das Ziel des Race-Modus rechnet dabei mit: es haengt an der Zahl der Spiele,
und die aendert sich hier.

Bei "Mehrere" beantwortet die Satzzahl die Frage vollstaendig — "Spiel abgeschlossen
bei" wird dort deshalb gar nicht mehr angeboten. Es geht dabei nichts verloren, weil
jeder Bestandswert in die Satzzahl uebergeht (siehe oben) und ein Wert jenseits der
Auswahl dort als eigener Eintrag steht.

Ohne geforderten Mindestvorsprung endet ein Spiel exakt beim Siegwert — eine Grenze
kann dann nie greifen. "Spaetestens gewonnen bei" wird deshalb ueberall nur noch
angeboten, wo ein Vorsprung verlangt ist, und beim Speichern auf null gesetzt.

Die Spielfolge steht schon in derselben Spalte unter den Einstellungen und bekommt
deshalb nur ihre Ueberschrift — als sechste Gruppe. Und "Spiele in Spielerstatistik"
stellte nackte Zahlen neben "Alle Spiele"; sie sagen jetzt, was sie zaehlen ("nur die
ersten 3 Spiele").

Beim WECHSEL der Satzart wird nichts umgerechnet — aus sechs Toren wuerden sechs
Saetze, und umgekehrt; aus "drei gewonnene Saetze" folgt keine Torzahl, es ist also gar
nicht rekonstruierbar. Stattdessen zwei Massnahmen. Erstens fragt der Editor nach, wenn
"Saetze pro Spiel" geaendert wird und unter dem Spielplan schon Ergebnisse stehen.
Zweitens ueberleben echte Satzergebnisse den Weg zurueck von "mit Ergebnis je Satz" auf
"nur der Satzstand": bringt ein Aufruf keine Satzfelder mit, bleibt der Stand
unveraendert und stehen im Bestand mehr als ein Paar, bleibt ergebnis_detailliert, wie
es ist — sonst haette blosses Oeffnen und Speichern "6:3 3:6 6:3 3:6 8:6" durch "3:2"
ersetzt. Wird der Stand geaendert, wird der Detailtext wie bisher neu geschrieben.

RUECKWAERTSKOMPATIBEL, und zwar geprueft und nicht bloss behauptet.

EINE Datenbankversion, 122, nicht sechs (Sven 2026-09-03): alle Spalten in einem
ALTER, die Ueberfuehrung dahinter, ein Zaehler hoch. 121 gehoert dem
Hall-of-Fame-Zweig (PR #303 / Issue #300), auf dem dieser Stand aufsetzt; dieser
Block muss deshalb der LETZTE der Kette bleiben — $datenbank_version wird einmal
gelesen, beide Bloecke laufen also im selben Aufruf, aber die Nummer des zuletzt
gelaufenen bleibt stehen. Gemessen gegen eine Datenbank, die #303 schon hinter sich
hat: 121 -> 122, unsere 24 Spalten dazu, die drei Hall-of-Fame-Spalten unberuehrt,
der Bestandsmodus mit punkte_sieg 42 als saetze_modus -42 ueberfuehrt. Die Zwischenstufen waren nur
die Reihenfolge, in der ich gebaut habe — kein Bestand hat sie je gesehen, und
sechs Schritte, die immer zusammen laufen, sind sechs Gelegenheiten, auf halbem
Weg stehenzubleiben. Gemessen an einer Datenbank auf Stand 120: ein Aufruf, 120
-> 122, 13 Spalten -> 37, der Bestandsmodus mit punkte_sieg 42 als saetze_modus
-42 ueberfuehrt; ein zweiter Lauf tut nichts (die Spaltenpruefung und das WHERE
der Ueberfuehrung sehen beide, dass es schon geschehen ist).

Ein Client, der nur die ueberlieferten Felder liest, soll weiterarbeiten wie
bisher — es gibt mindestens einen, den wir von hier aus nicht mitziehen koennen
(Kickern). Dafuer zaehlt nicht, was hinzukommt, sondern was sich an dem aendert,
was er schon liest. Neue Spalten sind harmlos: die Modus-Zeile geht als ganzes
Objekt in die JSON-Ansicht, unbekannte Schluessel ignoriert jeder Client. Die
Ueberfuehrung selbst fasst kein altes Feld an. Bleiben zwei Stellen, und beide
sind versorgt.

Erstens der Wertebereich von punktetyp. "Mehrere - mit Ergebnis je Satz" war
zuerst ein dritter Wert 2 — und punktetyp ist genau das Feld, an dem eine fremde
Anwendung ablesen muss, ob die Punkte eines Spiels Tore oder gewonnene Saetze
sind. Wer "1 = Saetze, sonst Tore" schreibt statt "0 = Tore, sonst Saetze",
haette bei einem Satzstand 3:2 "3:2 Tore" gelesen; beide Fassungen stehen im
Sports Manager selbst. Die Angabe bekommt deshalb eine EIGENE Spalte
(satzergebnisse), punktetyp behaelt seine zwei Werte und seine Bedeutung. Ein
Altclient liest weiter "Mehrere" und rechnet richtig — die Punkte SIND die
gewonnenen Saetze, daran aendert die feinere Erfassung nichts; er verpasst nur
das Zusaetzliche. Die Auswahl im Editor hat weiter drei Eintraege, der dritte
schreibt punktetyp 1 samt satzergebnisse 1.

Zweitens: der Server verlangt die Satzergebnisse NICHT, auch wo sie eingestellt
sind. Er fragt beim Speichern ueberhaupt nicht nach dem Modus — kommt kein
Satzfeld mit, gilt der Summenwert, wie immer. Gemessen an einem Spielplan mit
"3 Gewinnsaetze" und Satzerfassung, gemeldet wie ein Altclient nach
SetsMode.setsOnly (nur spiel_N_*_punkte, keine Satzfelder): Spiel 1 als 3:1
gespeichert, Spielpunkte 1:0, ergebnis_detailliert "3:1" — genau die Zeile, die
das eigene Formular unter "Mehrere" auch schreibt. Dieselbe Begegnung nimmt
gemischt beides auf: Spiel 1 als Satzstand, Spiel 2 als "6:3 3:6 6:4". Meldet der
Altclient danach beide Spiele erneut als Satzstand, ueberleben die Satzergebnisse
von Spiel 2 unveraendert; dasselbe beim Oeffnen und Speichern im Verbandsformular,
das fuer diesen Modus nur Satzzeilen zeigt — es belegt sie fuer Spiel 1 bewusst
nicht vor (aus "3:1" folgt kein erster Satz) und schickt den gespeicherten Stand
im versteckten Summenfeld mit. Nur wenn der Altclient das Spiel AENDERT, weicht
der Detailtext dem neuen Stand ("2:0") — er beschrieb dann ein anderes Ergebnis.

Und wo Satzergebnisse gefuehrt werden, bleibt ergebnis_detailliert bei einer Meldung
ohne Satzfelder LEER, statt wie sonst den Stand zu spiegeln. Dieses eine Paar bedeutet
dort naemlich etwas anderes als sonst: das Feld fuehrt Saetze, also liest man „3:1" als
einen Satz mit drei Toren und rechnet daraus 1:0 statt 3:1 — in unserer eigenen App
steckte genau dieser Fehler. Leer ist die Wahrheit: der Satzstand steht in
teamspiel_*_punkte, die Tore darin sind nicht bekannt, und die Anzeige laesst die
Detailspalte dann weg statt denselben Wert zweimal zu zeigen. Erfundene Platzhalter
(„1:0" je gewonnenen Satz) waeren die Alternative und sind verworfen: gespeichert liesse
sie niemand mehr von einer echten Meldung unterscheiden (Sven 2026-09-03). Es ist die
einzige Stelle, an der das Speichern nach dem Modus fragt. Gemessen: dieselbe
Altclient-Meldung schreibt unter „Mehrere" weiter „4:2" und unter „Mehrere - mit
Ergebnis je Satz" nichts; echte Satzergebnisse daneben bleiben unberuehrt, auch nach
erneuter Summenmeldung und nach Oeffnen und Speichern im Formular.

Der Race-Modus braucht dafuer nichts: fuer einen Altclient sieht ein
Race-Spielplan aus wie punktetyp 0, "Ergebnis als Spielpunkte" und punkte_sieg =
Ziel — also genau so, wie ein solcher Spielplan heute schon eingestellt ist. Er
verliert nichts und gewinnt nichts.

Die Spielerauswahl erscheint nur noch fuer eine Mannschaft, die auch Spieler
hinterlegt hat — sonst stand dort ein Feld mit nichts als dem Leereintrag und
behauptete eine Wahl, die es nicht gibt. Gespeichert wird dann genau wie bei
einer leeren Auswahl: der Server liest die fehlenden Felder mit Vorgabe 0, also
"kein Spieler". Die Absende-Pruefung wird SEITENWEISE erzeugt und liest nur, was
es gibt; ohne Kader auf beiden Seiten bleibt von ihr "return true" uebrig. Sonst
haette eine Forderung nach Namen, die niemand erfuellen kann, das Melden
verhindert statt es zu ordnen. Gemessen an drei Faellen: beide Kader (12 Felder
je Seite), nur der Heimkader (12 zu 0, und die Pruefung liest nur heim), keiner
(0 Felder, Pruefung ohne Feldzugriff, ein 5:3 speichert mit vier Spieler-IDs 0
und Begegnungsstand 5:3 bei Spielpunkten 1:0) — der letzte Fall ausdruecklich
mit "Spielernamen: Pflicht".

Nebenbei behoben:
- Durchweg leere Satzfelder gewannen gegen ein vorhandenes Summenergebnis; das
  blosse Oeffnen und Speichern loeschte damit Altbestand (gemessen: von sieben
  gespeicherten Spielen blieb eines uebrig).
- "Doppel separat" wurde allein aus punkte_sieg_* abgeleitet; abweichende
  Doppelwerte in den neuen Feldern waeren verborgen und beim naechsten
  Speichern ueberschrieben worden.
- Zwei hartkodierte deutsche Zeichenketten im uebersetzten Formular nutzen
  jetzt ihre vorhandenen Sprachschluessel.
- COM_SPORTSMANAGER_SETS fuehrte den Umlaut als HTML-Entitaet und wurde in zwei
  Auswahlfeldern erneut maskiert ("S&amp;auml;tze"); jetzt literal.
2026-09-06 21:23:49 +02:00
svennickel 5aee02830d Merge pull request #305 from Deutscher-Tischfussballbund/sportsmanager2-issue289
Zusatzinfo-Feld für Spielorte
2026-09-06 21:16:49 +02:00
Jürgen MeyerandClaude Sonnet 5 cb2e614604 Zusatzinfo-Feld für Spielort im Admin-Formular ergänzt und Frontend-Anzeige der Heimspielstätte um Weitere Infos, Ruhetag und Training erweitert.
Adresse der Heimspielstätte verlinkt jetzt zusätzlich auf Google Maps.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 17:50:42 +02:00
svennickel 5d126b0d28 Merge pull request #303 from Deutscher-Tischfussballbund/sportsmanager2-issue300
Überarbeitung Hall of Fame
2026-09-04 23:24:10 +02:00
Jürgen Meyer 69cf0e46ab Datenbankvorbereitung für issue 289 2026-09-04 11:34:07 +02:00
Jürgen Meyer df794966df Hall of Fame: Jahres-/Id-Filter korrigiert, inaktive Vereine bei Namens-Links berücksichtigt
- halloffame_id: Bereichssuche (z.B. "1-5") ist nicht mehr möglich, nur noch einzelne Werte.
- jahr: Bereichs- und Einzelwerte werden auf 1900..aktuelles Jahr+5 begrenzt; liegt bei einem Bereich der 2. Wert unter dem 1., werden die Werte vertauscht statt den Bereich zu verwerfen.
- halloffameNameLink verlinkt bei Vereinen jetzt nur noch, wenn der Verein nicht ausgetreten ist (analog zur bestehenden Spieler-Aktiv-Prüfung).
2026-09-04 08:35:27 +02:00
Jürgen MeyerandClaude Sonnet 5 12da0a9c00 Überarbeitung Hall of Fame
## Neue Frontend-Darstellungen (gruppierung)
- gruppierung=jahr - Jahresrückblick: eine Tabelle je Jahr mit allen Disziplinen, inkl. mehrerer Plätze, Team-Mitspielern und Spalten-/Zeilen-Layout wie auf der Detailseite.
- gruppierung=summe - Ranking über alle Disziplinen hinweg: ein Eintrag je Spieler/Team mit mindestens einem 1. Platz, inkl. Titelanzahl und Auflistung aller Titel (Disziplin, Jahre).
- gruppierung=summedisziplin - wie summe, aber eine eigene Rangliste je Disziplin.

## Neue/erweiterte Steuerungsparameter
- platzierung (inspalten/inzeilen), plaetzezeigen, sortierung (kontextabhängig: Jahresreihenfolge oder anzahl/name in den Summen-Ansichten).
- anzahltitel - Mindestanzahl an Titeln für die Summen-Ansichten.
- halloffame_id und jahr als Filter für alle Hall-of-Fame-Seiten, mit Komma- und Bereichs-Syntax (2006-2010,2015).
- Titel fällt auf den Joomla-Menütitel zurück, wenn kein eigener Titel im Menüpunkt gesetzt ist.
- Überschrift semantisch als h1 statt div.

## Mannschaftsspieler-Feld
- Neues Datenbankfeld teamspieler (TEXT) an #__sportsmanager_mitglied_von_halloffame, Eingabe im Backend als Textarea (nur bei Mannschaftsdisziplinen).
- Anzeige im Frontend bei platzierung=inzeilen oder wenn nur ein Platz gezeigt wird, sofern mindestens ein Eintrag >= 3 Zeichen vorhanden ist.

## Verlinkung & Bilder
- Spieler-, Vereins- und Mannschaftsnamen sind jetzt überall anklickbar (Detailseite, Jahresübersicht, Summen-Ansichten) und führen zur jeweiligen Profilseite - inaktive Spieler (ohne aktuellen Verein) bleiben unverlinkt.
- Dummybilder: neues geschlechtsneutrales Bild (spieler-n.png) für Spieler ohne Datenbank-ID; deren Geschlecht wird zusätzlich anhand der übrigen Spieler mit ID derselben Disziplin geschätzt, bevor auf das neutrale Bild zurückgefallen wird.
- Fehlt der Name zu einer Platzierung, wird in der Spaltenansicht nur das Bild weggelassen, in der Zeilenansicht die komplette Zeile.

## Neues Feld "nicht_ausgespielt"
- Neue Spalte nicht_ausgespielt (BOOL) hinter jahr an #__sportsmanager_mitglied_von_halloffame (Teil von Datenbank-Version 121).
- Admin-Formular: Checkbox neben dem Jahr-Feld; bei Aktivierung werden alle anderen Felder deaktiviert, beim Speichern werden Platz 2/3 gelöscht und Platz 1 auf reines nicht_ausgespielt=1 ohne Team-/Spielerdaten gesetzt.
- Frontend-Detailseite und Backend-Jahresliste zeigen bei solchen Einträgen "Nicht ausgespielt" statt Team-/Spielername an.
- Jahresübersicht und beide Summen-Ansichten überspringen solche Einträge vollständig.

## Vereins-Dropdown im Backend gruppiert
- Die Vereinsliste im Auswahlfeld (Plätze 1-3) ist jetzt in zwei optgroup-Blöcke aufgeteilt: "Aktive Vereine" / "Inaktive Vereine" (neue Sprachkonstanten COM_SPORTSMANAGER_ACTIVE_CLUBS / COM_SPORTSMANAGER_INACTIVE_CLUBS). Innerhalb jeder Gruppe bleibt die alphabetische Sortierung erhalten.

## Routing-Fix
- task=team_details und task=verein_details funktionierten nur, wenn der aktuelle Menüpunkt bereits auf content=teams bzw. content=vereine stand (z. B. beim Verlinken von der Hall-of-Fame-Seite aus nicht). Beide Tasks laufen jetzt wie spieler_details über eine content-unabhängige Route.

## Performance
- Options-Liste für Vereins-/Spieler-Dropdowns im Backend-Formular wurde bis zu 6x komplett neu gerendert (3 Plätze x 2 Spieler bzw. 3x Vereinsliste). Jetzt wird sie nur noch 1x aufgebaut, in einem <template>-Element abgelegt und per JavaScript in die <select>-Felder befüllt.
- Team-ID-Auflösung für Mannschaften ohne Vereinszuordnung läuft jetzt über eine einmalig geladene Liste statt einer Datenbankabfrage pro Zeile.

## Bugfixes
- halloffameTeamIdFuerTeamname() erwartete einen nicht-nullbaren string und stürzte bei nicht_ausgespielt-Einträgen (teamname = NULL) mit einem TypeError ab. Parameter ist jetzt nullable, leerer/NULL-Teamname liefert direkt null zurück.
- Bei Einzel-Disziplinen wurden Jahre in den Summen-Ansichten doppelt gezählt, wenn in der Datenbank (z. B. aus Altdaten) noch ein spieler2_id hinterlegt war; wird jetzt nur noch bei echten Doppel-Disziplinen berücksichtigt.

## Migration
- Datenbank-Version 121: neues Feld teamspieler, neue Spalte nicht_ausgespielt, Bereitstellung des neutralen Dummybilds für Bestandsinstallationen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 11:33:38 +02:00
svennickel ca827a049f Merge pull request #302 from Deutscher-Tischfussballbund/sportsmanager2-issue301
Export von kompletten Ligen im json-Format
2026-08-30 15:16:26 +02:00
svennickel 70fb4d97b7 Merge pull request #299 from Deutscher-Tischfussballbund/sportsmanager2-issue298
Zusätzliche Link-Parameter für Menüeinträge "Allgemeine Inhalte"
2026-08-30 13:43:04 +02:00
Jürgen Meyer d39dc45cec Änderungsvorschläge abgearbeitet. 2026-08-30 11:57:17 +02:00
Jürgen Meyer c290986bac Änderung wie Vorgeschlagen übernommen. 2026-08-30 10:15:48 +02:00
Jürgen Meyer 9541bc0652 Export von kompletten Ligen im json-Format 2026-08-28 15:52:39 +02:00
jmeyer26 50e6872214 Merge pull request #288 from Deutscher-Tischfussballbund/claude/season-selection-url-persist-6yz518
Persist season selection in URL instead of cookie-only
2026-08-28 12:33:47 +02:00
Jürgen Meyer a953ebf130 Zusätzliche Link-Parameter für Menüeinträge "Allgemeine Inhalte" 2026-08-27 15:03:45 +02:00
MarvinF e8051bbcf6 Merge pull request #297 from Deutscher-Tischfussballbund/sportsmanager2-issue296
Mail sending silently fails
2026-08-25 22:51:32 +02:00
Jürgen Meyer a01efae2e9 Exception Fehler bei E-Mail Versand 2026-08-25 20:05:50 +02:00
MarvinF 04e4ea6cdf Merge pull request #295 from Deutscher-Tischfussballbund/294-fix-string-comparison-spielpunkte-bedingung
Match report: goals compared as strings – winner swapped for two-digit results
2026-08-25 12:40:01 +02:00
svennickel f787681fec fix: compare goals numerically in spielpunkte_bedingung()
Refs #294
2026-08-24 23:10:16 +02:00
MarvinF 541af8fb7f Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-07-16 23:16:50 +02:00
MarvinF cc92b938be Merge pull request #291 from Deutscher-Tischfussballbund/sportsmanager2-issue290
Bei Teilnehmerzahl 1 oder weniger eines Ranglistenturnieres werden oh…
2026-07-16 23:14:36 +02:00
Jürgen Meyer 4c21d66fbe Bei Teilnehmerzahl 1 oder weniger eines Ranglistenturnieres werden ohne weitere Berechnung 0 Punkte vergeben. 2026-07-16 14:27:34 +02:00
MarvinF afb89dba6e Rename dev_preview to dev_preview.yml 2026-06-16 21:07:55 +02:00
MarvinF c4d599834a Create dev_preview 2026-06-16 21:06:47 +02:00
Claude dcea759ab2 Persist season selection in URL instead of cookie-only
Season filter dropdowns in all frontend views (Mannschaftswettbewerbe,
Turniere, Teams, Spielerstatistiken, Individualwettbewerbe, Ranglisten)
now navigate via JS URL update (window.location with searchParams) instead
of submitting a POST form. This puts filter_saison_id in the URL, making
season-filtered views bookmarkable and shareable.

The PHP backend already reads filter_saison_id from $_REQUEST (covers GET),
and the cookie is still set as fallback for links that don't carry the param.

For veranstaltungHeaderAlone (single competition detail view), the JS also
resets task=veranstaltungen and removes veranstaltungid on season change,
matching the previous form-based behaviour of navigating back to the list.

https://claude.ai/code/session_01VyKCAgyEfixxR6RhAkBSEL
2026-06-13 08:31:37 +00:00
MarvinF 19037d0729 Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-05-13 00:06:44 +02:00
MarvinF bfc65d6030 Merge pull request #284 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-05-13 00:05:08 +02:00
MarvinF 2a307b0987 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-05-13 00:03:28 +02:00
MarvinF e8e6f7046d Merge pull request #283 from Deutscher-Tischfussballbund/sportsmanager2-issue282
add club mailing functionality to admin area
2026-05-13 00:02:35 +02:00
Marvin Flock 20ab5a44a9 fix: add table headers 2026-05-13 00:00:34 +02:00
Jürgen Meyer a5357e4a51 mailto Funktion bei Mannschaften in admin-Bereich Veranstaltung 2026-04-28 11:46:22 +02:00
Jürgen Meyer 68e16a3adb mailto Funktion bei Vereine in admin-Bereich 2026-04-28 09:45:29 +02:00
MarvinF 7d47b3ed24 Merge pull request #281 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2026-04-14 19:10:16 +02:00
MarvinF cfc821f8ff Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-04-14 19:09:46 +02:00
MarvinF 582829331c Merge pull request #280 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-04-14 19:08:39 +02:00
MarvinF d8ccd08843 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-04-14 19:08:15 +02:00
MarvinF 57e92da771 Merge pull request #279 from Deutscher-Tischfussballbund/sportsmanager2-issue274-neu
Enhancing Playerstatistics (Performance Index, Club Membership and more)
2026-04-14 19:06:45 +02:00
Marvin Flock 7f85888a26 fix: add table fix 2026-04-14 19:02:38 +02:00
Marvin Flock 13ad52f221 fix: add small fixes 2026-04-14 18:50:05 +02:00
Jürgen Meyer a44564a40e Anzeige naegative Satzpunkte in Ligatabelle 2026-04-09 11:11:37 +02:00
Jürgen Meyer ee4e817ad4 Aktualisierung Spielerstatistiken 2026-04-06 08:10:55 +02:00
jmeyer26 8a7ff6c234 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue274-neu 2026-04-06 07:41:01 +02:00
Jürgen Meyer 8fb4ed1cdd Filter Mannschaften in Spielerstatistik 2026-04-06 07:33:33 +02:00
Jürgen Meyer a2243d9ccf Teams und Filter Spiele in Wertung hinzugefügt. 2026-04-06 05:53:13 +02:00
MarvinF 308fbae4e5 Merge pull request #277 from Deutscher-Tischfussballbund/sportsmanager2-issue275
Display Teamlogo in Hall of Fame
2026-04-05 19:10:55 +02:00
MarvinF d6d2a04ceb Merge branch 'sportsmanager2-dev' into sportsmanager2-issue275 2026-04-05 19:10:32 +02:00
MarvinF d7d6751b70 Merge pull request #278 from Deutscher-Tischfussballbund/sportsmanager2-issue276
Optimization of direct comparison
2026-04-05 19:07:34 +02:00
Jürgen Meyer b112b4dc31 Effizienzindex und Punkteschnitt zu Spielerstatistoken hinzugefügt. 2026-04-04 12:42:07 +02:00
jmeyer26 ac416c1822 Fehler Vergleich Satzpunkte korrigiert 2026-04-03 07:37:32 +02:00
Jürgen Meyer c92774b27d Spielerstatistik Race Permormance Index hinzugefügt 2026-04-02 18:48:43 +02:00
Jürgen Meyer b33a7e6a25 Unnötige Variablen gelöscht 2026-04-02 11:59:39 +02:00
Jürgen Meyer f86815dae5 Auswahl Direkter Vergleich nach Punkte, Satzpunkte, Tore 2026-04-02 11:56:51 +02:00
Jürgen Meyer 43a03bbb09 Hall of Fame - Zuordnung Mannschaftswappen über Teamname 2026-04-01 15:51:23 +02:00
MarvinF f430c7d35d Merge pull request #273 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2026-03-24 17:17:57 +01:00
MarvinF 73c352f6cf Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-03-24 17:16:00 +01:00
MarvinF c8c19ef8e0 Merge pull request #272 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-03-24 17:13:22 +01:00
MarvinF cb0db3833c Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-03-24 17:12:24 +01:00
MarvinF 29e7ea7ffa Merge pull request #271 from Deutscher-Tischfussballbund/fix/common-update
fix: refactor the update php to allow different databases
2026-03-24 17:10:46 +01:00
MarvinF 426a582844 Merge pull request #270 from Deutscher-Tischfussballbund/sportsmanager2-issue269
Fixes for Direct Compare, Player Statistics, Home field right
2026-03-24 02:12:16 +01:00
Marvin Flock c1763536c9 fix: refactor the update php to allow different databases 2026-03-24 01:38:18 +01:00
Jürgen Meyer 507861fd56 Neuberechung Quote in Spielerstatistik 2026-03-23 13:33:45 +01:00
Jürgen Meyer 168ad7dab4 Terminänderung funktionierte nicht mehr bei Tausch Heimrecht. 2026-03-23 12:08:11 +01:00
Jürgen Meyer c8483b077e Weiter Optimierung 2026-03-17 13:08:02 +01:00
Jürgen Meyer c23ed24962 Kleine Optimierung 2026-03-17 13:05:59 +01:00
Jürgen Meyer f70048f90f Fehlerkorrektur Direkter Vergleich 2026-03-17 12:47:43 +01:00
MarvinF 572ccee6fd Merge pull request #267 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2026-03-10 00:13:41 +01:00
MarvinF fa03965b17 Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-03-10 00:13:14 +01:00
MarvinF 0376b46470 Merge pull request #266 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-03-10 00:11:00 +01:00
MarvinF c8f419e00a Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-03-10 00:10:35 +01:00
MarvinF 116e4929b2 Merge pull request #265 from Deutscher-Tischfussballbund/sportsmanager2-issue261-issue262
Optimizations for Hall of fame, gameplans, associations, game postponement and more
2026-03-10 00:09:13 +01:00
MarvinF aed4d19c47 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue261-issue262 2026-03-10 00:08:54 +01:00
Jürgen Meyer 2faa38e2b8 Hilfsausgabe gelöscht 2026-03-09 07:44:59 +01:00
Jürgen Meyer dc0fcea945 Beanstandung Copilot abgearbeitet 5 2026-03-09 07:43:20 +01:00
Jürgen Meyer e139ac4fc2 Beanstandung Copilot abgearbeitet 4 2026-03-08 23:59:38 +01:00
jmeyer26andCopilot 5919994a3e Update src/structure/components/com_sportsmanager/admin.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-08 23:02:02 +01:00
jmeyer26andCopilot eccecedf95 Update src/structure/language/de-DE/de-DE.com_sportsmanager.ini
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-08 22:58:31 +01:00
Jürgen Meyer 9ed58f2916 Beanstandung Copilot abgearbeitet 2 2026-03-08 22:43:05 +01:00
Jürgen Meyer 1a9188c07b Beanstandung Copilot abgearbeitet 1 2026-03-08 21:46:09 +01:00
Jürgen Meyer 9435515088 Beim Löschen von Spieler bzw. Vereine werden die entsprechenden ids in Hall of Fame und Verbandsorgane gelöscht 2026-03-08 20:43:10 +01:00
Jürgen Meyer 4ada3a3b77 Bemerkungen angepasst 2026-03-08 12:23:39 +01:00
Jürgen Meyer 8391bf9df1 Automatische Spielberichtskorrektur bei doppelter Spielnummer 2026-03-08 12:19:10 +01:00
Jürgen Meyer bac4c0ada4 Funktion Spielbericht löschen hinzugefügt. 2026-03-08 09:23:27 +01:00
MarvinF ba50b0d6a4 Merge pull request #264 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2026-03-07 01:12:47 +01:00
MarvinF e4c4694dcb Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-03-07 01:12:18 +01:00
MarvinF e5de0030f2 Merge pull request #263 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-03-07 01:10:38 +01:00
MarvinF 8d364e0bfd Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-03-07 01:10:17 +01:00
Jürgen Meyer eed02e396d Evtl. vorhandene Ordnungsstrafen werden beim Löschen eines Spieles mitgelöscht. 2026-03-06 20:16:54 +01:00
Jürgen Meyer 40be14ad75 Heimrechttausch: Sicherheitsabfrage und speichern in Historie 2026-03-06 15:10:01 +01:00
Jürgen Meyer 54965f9ef2 Scrollbalken bei Ordnungsstrafen, Verbandsorgane und Hall of Fame 2026-03-06 10:43:46 +01:00
jmeyer26 8780229435 Merge pull request #260 from Deutscher-Tischfussballbund/sportsmanager2-250
Hall of Fame hinzugefügt
2026-03-02 19:51:09 +01:00
Jürgen Meyer a856a979aa Hall of Fame hinzugefügt 2026-03-02 19:49:22 +01:00
Jürgen Meyer 578fb76ead Klammer in update.php fehlte nach resolve conflicts 2026-02-25 11:00:02 +01:00
jmeyer26 b199b73d6f Merge pull request #258 from Deutscher-Tischfussballbund/sportsmanager2-issue070
Sportsmanager2 issue070
2026-02-25 09:42:22 +01:00
jmeyer26 0d61e9a823 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue070 2026-02-25 09:40:39 +01:00
jmeyer26 299b0bef4e Merge pull request #257 from Deutscher-Tischfussballbund/sportsmanager2-explicit-penalties
Explicit penalties for league teams
2026-02-25 09:30:49 +01:00
Jürgen Meyer 57c158a770 Kleine Korrekturen 2026-02-24 18:49:29 +01:00
Wieland Hagen 84d07aecb1 Explicit penalties for league teams (3): add moderator_user_id 2026-02-23 16:18:35 +01:00
Wieland Hagen 5bd0735708 Explicit penalties for league teams (2): resolved issues in PR 2026-02-23 15:43:29 +01:00
Jürgen Meyer 69e2032916 Letzte Änderung 2026-02-13 11:00:11 +01:00
jmeyer26andCopilot e5aede7cac Update src/structure/components/com_sportsmanager/admin.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 10:35:07 +01:00
jmeyer26andCopilot 7f8f842796 Update src/structure/components/com_sportsmanager/admin.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 08:53:21 +01:00
jmeyer26andCopilot 112511aa12 Update src/structure/components/com_sportsmanager/sportsmanager.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 08:49:51 +01:00
jmeyer26andCopilot eacb0dc165 Update src/structure/components/com_sportsmanager/views/sportsmanager/view.html.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 08:47:22 +01:00
Jürgen Meyer 67f5f38d1a Vorschläge des Copiloten umgesetzt 2026-02-13 08:10:35 +01:00
jmeyer26andCopilot f65ec6be88 Update src/structure/components/com_sportsmanager/database/update.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 06:54:41 +01:00
jmeyer26andCopilot 427bd545af Update src/structure/script.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 06:54:20 +01:00
jmeyer26andCopilot 986cd6d99e Update src/structure/components/com_sportsmanager/admin.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-13 06:42:58 +01:00
Jürgen Meyer 66baeb0f77 update.php und script.php erweitert 2026-02-12 17:04:26 +01:00
Jürgen Meyer 46474c6c40 Verteilerliste erweitert 2026-02-12 15:58:23 +01:00
Jürgen Meyer a583131162 Exportfunktion und ein paar Korrekturen 2026-02-12 15:06:38 +01:00
Jürgen Meyer cb8b6ebe06 Einige Optimierungen 2026-02-12 11:33:29 +01:00
Jürgen Meyer d41376494f Bilder hinzugefügt und ein paar Optimierungen 2026-02-11 17:03:02 +01:00
Jürgen Meyer d462137424 Frontend für Verbandsorgane erstellt. 2026-02-11 13:58:12 +01:00
Jürgen Meyer 3cb3fa2b28 Formulare für Mitglieder Verbandsorgane erstellt. 2026-02-10 16:23:57 +01:00
Jürgen Meyer 10807c7ea8 Organisation hinzugefügt und kleine Korrekturen. 2026-02-10 10:00:46 +01:00
Jürgen Meyer e469e70b97 Formulare für Tabelle Verbandsorgane erstellt 2026-02-09 17:20:45 +01:00
Wieland Hagen 522369bb14 Explicit penalties for league teams 2026-02-09 11:09:02 +01:00
MarvinF 91caf76a71 Merge pull request #256 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2026-02-03 19:27:41 +01:00
MarvinF 12037f9bac Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-02-03 19:27:10 +01:00
MarvinF b1af98df54 Merge pull request #255 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-02-03 19:25:43 +01:00
MarvinF fe885160d9 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-02-03 19:25:22 +01:00
MarvinF 308bbd4d76 Update build_release.yml
remove teams notification
2026-02-03 19:23:19 +01:00
MarvinF 89bbba9c1c Merge pull request #254 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod merge
2026-02-03 19:17:18 +01:00
MarvinF aa07d51cd3 Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-02-03 19:09:48 +01:00
MarvinF 5ca5015eb4 Merge pull request #253 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2026-02-03 19:09:10 +01:00
MarvinF a0ef2bda54 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-02-03 19:08:43 +01:00
MarvinF 3300a66c19 Merge pull request #249 from Deutscher-Tischfussballbund/sportsmanager2-issue244
Sportsmanager2 issue244
2026-02-03 19:02:44 +01:00
MarvinF cd60c9f42a Merge branch 'sportsmanager2-dev' into sportsmanager2-issue244 2026-02-03 19:02:23 +01:00
MarvinF 692fd0a676 Merge pull request #248 from Deutscher-Tischfussballbund/sportsmanager2-issue247
remove delimiter on csv-export
2026-02-02 18:56:41 +01:00
MarvinF b8e21aa8ee Merge branch 'sportsmanager2-dev' into sportsmanager2-issue247 2026-02-02 18:56:04 +01:00
MarvinF 1d66905488 Merge pull request #251 from Deutscher-Tischfussballbund/Sportsmanager2-issue250
fix error "spiel_nr on null" in team tournament encounter
2026-02-02 17:00:30 +01:00
Jürgen Meyer 991d0501df Tipp des Copiloten benutzt :) 2026-01-31 19:04:08 +01:00
Jürgen Meyer c5ffbed4da Fehler bei Begegnung hinzufügen gefixt. 2026-01-31 18:49:25 +01:00
Jürgen Meyer 33c94ae907 Rechtschreibkorrketur 2026-01-28 18:04:26 +01:00
jmeyer26andCopilot 8890ca35d2 Update src/structure/components/com_sportsmanager/views/sportsmanager/view.html.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 17:59:23 +01:00
jmeyer26andCopilot 50d332cd45 Update src/structure/language/en-GB/en-GB.com_sportsmanager.ini
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 17:58:09 +01:00
jmeyer26andCopilot 90cf2cc4ca Update src/structure/language/de-DE/de-DE.com_sportsmanager.ini
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 17:01:07 +01:00
jmeyer26andCopilot ea0515e827 Update src/structure/language/en-GB/en-GB.com_sportsmanager.ini
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-28 17:00:52 +01:00
Jürgen Meyer a868d56450 Spielerstatus im Verein in Spielerdetails 2026-01-28 16:51:52 +01:00
Jürgen Meyer eaaa75d584 Checkbox Lizenznummer erhalten entfernt. 2026-01-28 12:10:42 +01:00
Jürgen Meyer 1479fc7e20 Importfunktion angepasst 2026-01-27 18:27:28 +01:00
Jürgen Meyer 70563bc8e4 Formulare für Spielerimport angepasst. 2026-01-27 14:57:43 +01:00
Jürgen Meyer 218436c065 CSV Export Funktion mittels KI komplett neu erstellt. 2026-01-27 13:02:51 +01:00
Jürgen Meyer c21d20e532 Bei csv-Export wird Semikolon im Text durch Komma ersetzt (bei Export von Ligabetrieb, Ordnungsstrafen und Spielverlegungen) 2026-01-27 07:00:54 +01:00
MarvinF 8b22eb886d Merge pull request #246 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2026-01-26 17:59:27 +01:00
MarvinF ae05c42209 Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2026-01-26 17:59:03 +01:00
MarvinF 3bc1324b4b Merge pull request #245 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2026-01-26 17:57:36 +01:00
MarvinF 23ceb2e272 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2026-01-26 17:56:42 +01:00
MarvinF 5b26295ebf Merge pull request #243 from Deutscher-Tischfussballbund/sportsmanager2-issue242
Sportsmanager2 issue242
2026-01-26 17:51:55 +01:00
Jürgen Meyer 9d3cd6b959 Telefonnummer Spielort in Team Details 2026-01-26 11:28:21 +01:00
Jürgen Meyer 6b7c5e7a3b Export Teamdaten implementiert. 2026-01-22 14:45:37 +01:00
Jürgen Meyer ab6f776b96 Tabellen Spielorte, Teams um die Felder telefon, EMail, Ruhetage und Trainingstage erweitert. 2026-01-22 11:31:27 +01:00
jmeyer26 8fed3c217f Merge pull request #241 from Deutscher-Tischfussballbund/sportsmanager2-issue240
Sportsmanager2 issue240
2026-01-22 09:18:25 +01:00
jmeyer26 633ec1f1cb Merge pull request #238 from Deutscher-Tischfussballbund/sportsmanager2-issue234
Sportsmanager2 issue234
2026-01-22 09:17:18 +01:00
Jürgen Meyer 41e229340d Formulare optimiert 2026-01-14 18:22:02 +01:00
Jürgen Meyer 379427d4c4 json Import implementiert. csv-Import um Lizenznummer erweitert. 2026-01-13 19:42:08 +01:00
Jürgen Meyer a2808b7db0 Erst mal ein bisschen aufgeräumt 2026-01-13 11:17:32 +01:00
Jürgen Meyer c3cec6c93c SQL-Anweisungen übersichtlicher gestaltet. 2026-01-06 16:53:19 +01:00
Jürgen Meyer 9913279519 Benutzerrechte für OS und SV angepasst 2026-01-06 13:10:40 +01:00
Jürgen Meyer 0c78ed8b63 Fehler bei Insert Antragsteller korrigiert 2026-01-04 13:29:29 +01:00
Jürgen Meyer 4a448cb61d Letzter Feinschliff 2026-01-04 12:14:21 +01:00
Jürgen Meyer 825ff04a89 script.php angepasst und noch ein paar kleine Korrekturen 2026-01-03 17:45:35 +01:00
Jürgen Meyer 8b7ca05fc1 Mailen von Spielverlegung und Export von Spielverlegungen 2026-01-02 23:12:45 +01:00
Jürgen Meyer 76f0ef5f55 Anlegen und Löschen von Spielverlegungen 2026-01-01 18:31:09 +01:00
Jürgen Meyer f76f1185f5 Abfragen optimiert 2025-12-30 18:53:44 +01:00
Jürgen Meyer 7253426b51 Menüstruktur für admin Spielverlegungen erstellt 2025-12-29 17:45:21 +01:00
Jürgen Meyer 4686f5d8db Liste Spielverlegungen in Frontend 2025-12-29 12:44:50 +01:00
Jürgen Meyer db80f584cd Verschiebereln erweitert. Kategoriefilter optimiert. 2025-12-25 13:20:54 +01:00
MarvinF 275693ecb3 Merge pull request #232 from Deutscher-Tischfussballbund/sportsmanager-issue069
implemented disciplinary penalties for clubs
2025-12-23 13:25:33 +01:00
MarvinF fb3c088835 Merge branch 'sportsmanager2-dev' into sportsmanager-issue069 2025-12-23 13:23:00 +01:00
jmeyer26andMarvinF ddca0066bf Update src/structure/components/com_sportsmanager/admin.php
Co-authored-by: MarvinF <B3r@users.noreply.github.com>
2025-12-23 13:00:55 +01:00
MarvinF bc56e30682 Merge pull request #237 from Deutscher-Tischfussballbund/sportsmanager-issue236
Wrong winner when doing draw for cup
2025-12-23 12:39:19 +01:00
Jürgen Meyer 2fe9acb01c Änderungen gecheckt, Absender in joomlamail hinzugefügt. 2025-12-22 10:16:09 +01:00
Jürgen Meyer de3705ca65 Änderungen nach Kommentaren 2025-12-22 09:19:19 +01:00
Marvin Flock 947a150b06 fix: apply minor fixes to deprecated config and redundant variable assignment 2025-12-22 00:09:50 +01:00
Jürgen Meyer c8199abee1 Bei Pokalauslosung werden jetzt die richtigen Sieger erkannt 2025-12-21 18:35:44 +01:00
Jürgen Meyer 6c1a6aa0de Änderungen nach Kommentar vorgenommen 2025-12-21 05:21:36 +01:00
Marvin Flock 626b9c503a Merge branch 'sportsmanager2-dev' into sportsmanager-issue069
# Conflicts:
#	src/structure/components/com_sportsmanager/database/update.php
2025-12-20 17:21:54 +01:00
Jürgen Meyer 964ab1ca8b E-Mail über joomla. Status Überarbeitung. 2025-12-20 10:03:05 +01:00
Jürgen Meyer 783cffaf2b Kommemtar entfernt 2025-12-12 15:48:20 +01:00
Jürgen Meyer 12cb9a0e67 Fehler bei Export korrigiert. 2025-12-12 15:29:20 +01:00
Jürgen Meyer 49c8037dbf Export Ordnungsstrafen. Unnötige Tags entfernt. 2025-12-12 12:11:24 +01:00
Jürgen Meyer e7dbfa6402 Ordnungsstrafen implementiert 2025-12-11 17:52:36 +01:00
MarvinF b21e11be59 Merge pull request #231 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-12-09 19:11:57 +01:00
MarvinF f119316561 Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2025-12-09 19:11:36 +01:00
MarvinF 06070a1d47 Merge pull request #230 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2025-12-09 19:11:01 +01:00
MarvinF 5bf3fa3501 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2025-12-09 19:10:17 +01:00
MarvinF a2cdc68578 Merge pull request #229 from Deutscher-Tischfussballbund/sportsmanager-issue225
administrators can't see player profiles of inactive players
2025-12-09 19:09:12 +01:00
MarvinF b34aa63872 Merge pull request #228 from Deutscher-Tischfussballbund/sportsmanager-issue227
Saving a tournament will overwrite the dates of its disciplines
2025-12-09 19:07:57 +01:00
Jürgen Meyer ddb7e3a1bd Korreketur datenbank-version 2025-12-09 05:46:28 +01:00
Jürgen Meyer e3fb99000c Korrektur Fehler beim Speichern Datum Disziplin 2025-12-09 05:43:23 +01:00
Jürgen Meyer 9cd84108e4 Spielerstatistik in adminSpieler um Vereinlose Spieler erweitert 2025-12-04 15:19:00 +01:00
Jürgen Meyer 3b721e3c82 Formular Spieler verschönert. 2025-12-04 14:08:14 +01:00
Jürgen Meyer fec866fa5d Profil von inaktiven Spieler kann mit bestimmten Rechten wieder angezeigt werden. 2025-12-04 13:31:33 +01:00
Marvin Flock d17280edb1 chore!: remove malicious fs package 2025-11-27 10:12:47 +01:00
MarvinF 287dcb0074 Merge pull request #224 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-11-17 17:16:48 +01:00
MarvinF 2e596dfcaa Merge branch 'sportsmanager2-prod' into sportsmanager2-stage 2025-11-17 17:16:28 +01:00
MarvinF 6c96125da4 Merge pull request #223 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2025-11-17 17:15:39 +01:00
MarvinF 01c7e5bb63 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2025-11-17 17:15:00 +01:00
MarvinF 0116fd0860 Merge pull request #222 from Deutscher-Tischfussballbund/sportsmanager2-v230
Small design fixes
2025-11-16 20:17:39 +01:00
Jürgen Meyer ec61daa5c7 Kleine kosmetsiche Korrekturen 2025-11-15 11:28:53 +01:00
MarvinF e692edcb99 Merge pull request #220 from Deutscher-Tischfussballbund/sportsmanager2-issue217
Sportsmanager2 issue217
2025-11-14 11:25:37 +01:00
Marvin Flock c1196c9fd9 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue217
# Conflicts:
#	src/structure/components/com_sportsmanager/database/update.php
2025-11-14 11:25:01 +01:00
MarvinF 4cc403536e Merge pull request #219 from Deutscher-Tischfussballbund/sportsmanager2-issue192
Playoffs optimization: KO games with game number and matchday title
2025-11-14 11:20:19 +01:00
Jürgen Meyer 1032af51f5 Kleine Korrektur 2025-11-14 07:28:36 +01:00
Jürgen Meyer 33d748303d Bei eintägiger Veranstaltung wird Datum in Formular Disziplin versteckt 2025-11-14 07:18:06 +01:00
Jürgen Meyer 331d4cfd85 Kleine Korrektur 2025-11-14 06:38:07 +01:00
Jürgen Meyer 6b1aa25c1b Comments in Review abgearbeitet 2025-11-14 06:33:11 +01:00
MarvinF 6b9f81f1c7 Merge pull request #221 from Deutscher-Tischfussballbund/sportsmanager2-issue218
MonsterDYP imports throw error
2025-11-13 21:52:06 +01:00
Jürgen Meyer e498981bc4 Datumsabgleich zwischen Turnier und Turnierdisziplin optimiert. 2025-11-13 17:13:43 +01:00
Jürgen Meyer 54d73a61e0 Hilfsausgabe gelöscht 2025-11-13 10:55:15 +01:00
Jürgen Meyer bd491add2e Unterdrückung der Speicherung von Turnierspielen bei Monstr-DYP 2025-11-13 10:51:11 +01:00
Jürgen Meyer 30c8ba9bfa Erweiterter Export für STFV 2025-11-12 11:56:35 +01:00
Jürgen Meyer 555f1de1b5 Verbandskürzel zu Einstellungen hinzugefügt 2025-11-12 11:17:21 +01:00
Jürgen Meyer a823e029d0 Live-Ticker angepasst 2025-11-10 16:32:19 +01:00
Jürgen Meyer 5627282a53 Vorbelegung Spielnummer entfernt. 2025-11-10 15:39:11 +01:00
Jürgen Meyer d73d081780 Ansicht Begegnungen im Frontend überarbeitet 2025-11-05 16:44:32 +01:00
Jürgen Meyer e3bd06257d Kleinen Programmierfehler beseitigt. 2025-11-05 12:43:32 +01:00
Jürgen Meyer 2a87c93c17 Anischt Begegnungen im admin-Bereich überarbeitet 2025-11-05 12:36:29 +01:00
Jürgen Meyer 5fafcace6b Überarbeitung Teamsport Spieltag erzeugen 2025-11-04 21:30:58 +01:00
MarvinF 12fd3a3ff0 Merge pull request #215 from Deutscher-Tischfussballbund/sportsmanager2-issue214
Add background color on hover for tournament trees
2025-11-04 18:47:30 +01:00
Jürgen Meyer 885d6a3191 Überarbeitung Begegnung hinzufügen bzw. editieren 2025-11-04 18:39:08 +01:00
MarvinF c50833ebe4 Merge pull request #216 from Deutscher-Tischfussballbund/sportsmanager2-issue213
Anzahl Kategorein auf 100 erhöht.
2025-11-04 00:05:18 +01:00
Jürgen Meyer 8242bd09cc Anzahl Kategorien Spielerstatistiken auf 100 erhöht 2025-11-03 15:32:14 +01:00
Jürgen Meyer 3886cc88d3 Anzahl Sortierreihenfolge Team Veranstaltungen auf 100 gesetzt. 2025-11-03 12:25:34 +01:00
Jürgen Meyer 96eff9f189 Anzahl Kategorein auf 100 erhöht. 2025-11-03 12:18:31 +01:00
Jürgen Meyer 1c2a0abcc2 Hintergrundfarbe bei Mouseover in Turnierbaum 2025-11-03 11:42:34 +01:00
MarvinF 24f4195403 Merge pull request #212 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-10-14 20:25:23 +02:00
MarvinF c1b7cb1e8c Merge pull request #211 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2025-10-14 20:23:35 +02:00
MarvinF 878cacd8cd Merge pull request #210 from Deutscher-Tischfussballbund/sportsmanager2-issue207
Sportsmanager2 issue207
2025-10-13 15:51:55 +02:00
MarvinF 5f830602ef Merge pull request #209 from Deutscher-Tischfussballbund/sportsmanager2-issue208
Vereinszuordnung Spieler korrigiert.
2025-10-12 23:31:46 +02:00
Jürgen Meyer eef105895b Spieleliste in Verein Details auskommentiert 2025-10-10 11:56:01 +02:00
Jürgen Meyer c0bdbb4bde Fehlerhaften Link Sortierung Vereine korrigiert. 2025-10-10 10:36:24 +02:00
Jürgen Meyer d05f3c5d7f Vereinszuordnung Spieler korrigiert. 2025-10-09 13:14:13 +02:00
MarvinF 0c334d897d Merge pull request #204 from Deutscher-Tischfussballbund/sportsmanager2-stage
downward merge stage to dev
2025-10-06 23:18:12 +02:00
MarvinF 79efed156b Merge pull request #203 from Deutscher-Tischfussballbund/sportsmanager2-prod
downward merge prod to stage
2025-10-06 23:17:24 +02:00
MarvinF 7984ea73aa Merge pull request #202 from Deutscher-Tischfussballbund/sportsmanager2-issue201
Zeileneinrückung in view.html.php korrigiert
2025-09-28 03:31:42 +02:00
Jürgen Meyer 7d07aee916 Zeileneinrückung in view.html.php korrigiert 2025-09-27 12:19:59 +02:00
MarvinF 43acc01861 Merge pull request #200 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-09-26 17:01:25 +02:00
MarvinF fa374986ca Merge pull request #199 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2025-09-26 17:00:10 +02:00
MarvinF aa68992d45 Merge pull request #197 from Deutscher-Tischfussballbund/fix/ranking_bug
website freezing up indefinitely
2025-09-26 16:52:53 +02:00
MarvinF 0d4381fc7f Merge pull request #84 from Deutscher-Tischfussballbund/feature/auto-email-missing-results
email reminder for tournament results
2025-09-26 16:51:54 +02:00
Marvin Flock 9b4eb13d52 feat: prevent email flood on new created tournaments when email reminder are turned on in later stages 2025-09-25 23:43:11 +02:00
Marvin Flock cfe4f871f7 Merge branch 'sportsmanager2-dev' into feature/auto-email-missing-results
# Conflicts:
#	src/structure/components/com_sportsmanager/database/update.php
#	src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php
2025-09-25 18:16:42 +02:00
Marvin Flock bbe786a075 fix: update regarding code review 2025-09-25 18:13:58 +02:00
Marvin Flock 64ce39a59f feat: add email reminder functionality 2025-09-25 02:53:50 +02:00
Jürgen Meyer d0258d967d Optimierung Inserts fuer Aktualisierung Ranglisten 2025-09-24 09:44:11 +02:00
MarvinF bf99d459fb Merge pull request #189 from Deutscher-Tischfussballbund/fix/183_long-discipline-names-break-layout
Long list of disciplines break tournament view
2025-09-23 20:18:30 +02:00
MarvinF bc91be9382 Merge pull request #195 from Deutscher-Tischfussballbund/sportsmanager2-issue193
change styling/sizing of tables
2025-09-23 20:14:24 +02:00
MarvinF 5c09a35485 Merge pull request #196 from Deutscher-Tischfussballbund/sportsmanager2-issue194
date formats break in group game import
2025-09-23 20:12:18 +02:00
MarvinF f14d5a1e8c Merge pull request #191 from Deutscher-Tischfussballbund/sportsmanager2-issue190
some live results will show up twice
2025-09-23 20:04:18 +02:00
MarvinF 26fd06afef Update view.html.php 2025-09-23 19:48:03 +02:00
Marvin Flock 1f147081e1 fix: add removed part back to sportsmanager 2025-09-23 18:18:24 +02:00
Jürgen Meyer 4f89abc630 Leerzeilen in Importdatei werden ignoriert. 2025-09-22 11:34:27 +02:00
Jürgen Meyer d84c2eefcf Kleine Korrektur 2025-09-22 06:37:27 +02:00
Jürgen Meyer ba73036b02 Import Gruppenspiele optimiert (issue #194) 2025-09-22 06:32:08 +02:00
Jürgen Meyer 29a108d88c Style Manuelle Tabelle an andere Tabellen angepasst (issue #193) 2025-09-22 04:52:40 +02:00
Jürgen Meyer 11e42c2374 tfvhh durch #_ ersetzt 2025-09-18 17:10:24 +02:00
Jürgen Meyer 56776c01f0 Doppelte Live-Ergebnisse eines Spiels (issue #190) 2025-09-18 16:54:22 +02:00
Marvin Flock 6187456e31 Merge branch 'sportsmanager2-dev' into feature/auto-email-missing-results
# Conflicts:
#	src/structure/components/com_sportsmanager/sportsmanager.php
2025-09-17 21:42:29 +02:00
Marvin Flock 49e3bde816 fix: display disciplines under each other in admin and public tournament view 2025-09-17 21:23:51 +02:00
MarvinF 15347b3ab7 Merge pull request #181 from Deutscher-Tischfussballbund/sportsmanager2-issue180
Überarbeitung Pokalauslosung (issue #180)
2025-09-17 20:37:19 +02:00
MarvinF 3363ec1a77 Merge pull request #182 from Deutscher-Tischfussballbund/sportsmanager2-issue178
Überarbeitung Anzeige Vereinsliste in Frontend (issue #178)
2025-09-17 20:36:49 +02:00
MarvinF 751c1919d4 Merge pull request #188 from Deutscher-Tischfussballbund/sportsmanager2-issue179
Initialisierung neuer Einstellungen (issue #179)
2025-09-17 20:36:08 +02:00
Jürgen Meyer 9babcec39e Passive und inaktive Spieler werden im oeffentlichen Bereich nicht mehr gezeigt (issue #150) 2025-09-17 19:17:30 +02:00
Jürgen Meyer e8c4ab2d1d Korrektur Dropdown Spielorte 2025-09-17 10:41:59 +02:00
Jürgen Meyer 53ff7ab566 Initialisierung neuer Einstellungen 2025-09-17 08:54:22 +02:00
Jürgen Meyer ac8bafaa9e Label für show_member_count angepasst 2025-09-17 08:08:36 +02:00
MarvinF 4f6edb0acb Merge pull request #187 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-09-16 20:37:44 +02:00
MarvinF 822708356b Merge pull request #186 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2025-09-16 20:36:49 +02:00
MarvinF 7c302d4ded Merge pull request #185 from Deutscher-Tischfussballbund/fix/live-encounters
live encounters missing in live ticker
2025-09-16 20:35:45 +02:00
Marvin Flock 1e63f2b542 fix: add live encounters to live ticker 2025-09-16 19:50:34 +02:00
Jürgen Meyer 1d9aa13300 Überarbeitung Anzeige Vereinsliste in Frontend (issue #178) 2025-09-12 10:56:25 +02:00
Jürgen Meyer ea85f102a5 Änderungen nach issue #180 2025-09-11 10:22:52 +02:00
MarvinF ebfd6ee4e9 Merge pull request #177 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-09-04 22:24:49 +02:00
MarvinF a503325ca4 Merge pull request #176 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2025-09-04 22:23:53 +02:00
MarvinF 218dc138fb Update build_release.yml 2025-09-04 22:22:18 +02:00
MarvinF eed53841cf Merge pull request #175 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-09-04 22:05:16 +02:00
MarvinF dbc79096d4 Merge pull request #174 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2025-09-04 22:04:25 +02:00
Marvin Flock 3e93e27f72 chore: add notification to teams 2025-09-04 22:02:39 +02:00
MarvinF 8c022f831a Merge pull request #173 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-09-04 21:56:02 +02:00
MarvinF 2ab429f949 Merge pull request #172 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2025-09-04 21:55:00 +02:00
MarvinF 6e53017158 Create teams_integration.yml 2025-09-04 21:40:02 +02:00
MarvinF 8764b0a337 Merge pull request #171 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod
2025-09-04 21:13:28 +02:00
MarvinF 07611a0087 Merge pull request #170 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage
2025-09-04 21:11:56 +02:00
MarvinF bc57da1eff Merge pull request #169 from Deutscher-Tischfussballbund/sportsmanager2-issue165
issue #165 gefixt. Tabelle wird falsch gespeichert bei Direkter Vergl…
2025-09-04 21:08:11 +02:00
MarvinF 1c380928f0 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue165 2025-09-04 21:07:37 +02:00
Jürgen Meyer 1ddcfd87db issue #165 gefixt. Tabelle wird falsch gespeichert bei Direkter Vergleich. 2025-09-03 02:51:40 +02:00
Marvin Flock cb1493954f chore: update release date in manifest file on release build 2025-09-02 23:36:20 +02:00
MarvinF 9637f2a92a Merge pull request #168 from Deutscher-Tischfussballbund/sportsmanager2-issue166
issue #166 gefixt (Filter Land in Termine)
2025-09-02 23:21:33 +02:00
MarvinF a977343544 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue166 2025-09-02 23:19:17 +02:00
MarvinF 1f5593d3e8 Merge pull request #167 from Deutscher-Tischfussballbund/sportsmanager2-issue164
Issue #164 - Fehler Export Spielberichte
2025-09-02 23:15:54 +02:00
Jürgen Meyer fff5f97971 issue #166 gefixt (Filter Land in Termine) 2025-09-02 16:01:09 +02:00
Jürgen Meyer 546b9c3af9 Issue #164 - Fehler Export Spielberichte 2025-09-02 13:23:54 +02:00
MarvinF 4ad93a8cf6 Merge pull request #162 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage 2 prod pr
2025-09-02 01:48:44 +02:00
MarvinF 1b5e070026 Merge pull request #161 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev 2 stage pr
2025-09-02 01:47:42 +02:00
MarvinF 114eba3a9c Merge pull request #160 from Deutscher-Tischfussballbund/temp_releasenotes
resize parameters of images are not working
2025-09-02 01:45:51 +02:00
Marvin Flock 9fb592ccbc chore: dummy commit for release notes 2025-09-02 01:44:07 +02:00
MarvinF f76ab18d4b Merge pull request #159 from Deutscher-Tischfussballbund/temp_releasenotes
optimize club details page for mobile
2025-09-02 01:43:08 +02:00
Marvin Flock 02e27d7747 chore: dummy commit for release notes 2025-09-02 01:41:00 +02:00
MarvinF 5375950049 Merge pull request #158 from Deutscher-Tischfussballbund/temp_releasenotes
locations can be reused for event creation
2025-09-02 01:39:52 +02:00
Marvin Flock 050b246fef chore: dummy commit for release notes 2025-09-02 01:38:18 +02:00
MarvinF 55b8cc52c7 Merge pull request #157 from Deutscher-Tischfussballbund/temp_releasenotes
improved the list of clubs with sorting and more configuration options
2025-09-02 01:37:19 +02:00
Marvin Flock aad70e5ab2 chore: dummy commit for release notes 2025-09-02 01:32:45 +02:00
MarvinF 37a98edbad Merge pull request #156 from Deutscher-Tischfussballbund/temp_releasenotes
while generating group games, the second encounter for two teams was ordered the same (home/guest) as the first encounter
2025-09-02 01:28:06 +02:00
Marvin Flock 228f68f90c chore: dummy commit for release notes 2025-09-02 01:22:03 +02:00
MarvinF 4f9df2ce89 Merge pull request #155 from Deutscher-Tischfussballbund/temp_releasenotes
team dropdown while generating group games shows a team twice
2025-09-02 01:20:56 +02:00
Marvin Flock 1a364a4e30 chore: dummy commit for release notes 2025-09-02 01:16:26 +02:00
MarvinF f3bf69c9ca Merge pull request #154 from Deutscher-Tischfussballbund/temp_releasenotes
When using direct comparison, if there are no encounters yet, an error is thrown
2025-09-02 01:13:58 +02:00
Marvin Flock cc81b97569 chore: dummy commit for release notes 2025-09-02 01:09:54 +02:00
MarvinF aaa5aaac1d Merge pull request #153 from Deutscher-Tischfussballbund/temp_releasenotes
Import options improvement: calendar week, matchday title, match number
2025-09-02 01:08:09 +02:00
Marvin Flock f9f9e58881 chore: dummy commit for release notes 2025-09-02 01:04:53 +02:00
MarvinF 671dfb7e8d Merge pull request #145 from Deutscher-Tischfussballbund/sportsmanager2-issue052
Änderungen für issue #52, issue #131 und issue #143
2025-09-02 00:23:13 +02:00
Marvin Flock 3ae15e2e70 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue052
# Conflicts:
#	src/structure/components/com_sportsmanager/admin.php
#	src/structure/components/com_sportsmanager/database/update.php
#	src/structure/components/com_sportsmanager/views/sportsmanager/view.html.php
#	src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php
#	src/structure/language/de-DE/de-DE.com_sportsmanager.ini
#	src/structure/language/en-GB/en-GB.com_sportsmanager.ini
#	src/structure/script.php
2025-09-02 00:21:11 +02:00
MarvinF ee0c19efe3 Merge pull request #147 from Deutscher-Tischfussballbund/sportsmanager2-issue125
Änderungen für issue #125, issue #116 und issue #117
2025-09-02 00:06:41 +02:00
MarvinF 87c9ec82fd Merge branch 'sportsmanager2-dev' into sportsmanager2-issue125 2025-09-02 00:06:05 +02:00
Jürgen Meyer 71d8460cd6 Entscheidung ob Verband angezeigt wird liegt allein bei Web Admin. 2025-09-01 20:56:57 +02:00
Jürgen Meyer d97713e73d Fehler bei Erstellung Spieleplen mit 4 Mannschaften mit Setzliste behoben. 2025-09-01 20:34:14 +02:00
Marvin Flock b16638ed47 fix: code review changes 2025-09-01 18:02:20 +02:00
MarvinF b511badad2 Merge pull request #144 from Deutscher-Tischfussballbund/fix/bayern-missing-argument
missing parameter in player details with ELO runs into error
2025-08-30 13:18:19 +02:00
Jürgen Meyer 42ff1155f3 Probleme mit Sonderzeichen in Turnierbaum gefixt. 2025-08-29 16:28:06 +02:00
Jürgen Meyer 17a9bfdd2e issue #151 2025-08-29 12:00:08 +02:00
Jürgen Meyer 3aa20036dc Issue #152 Heimrechtwechsel in Rückrunde 2025-08-29 11:22:13 +02:00
Jürgen Meyer fc1ce3bdd6 Alle offenen Mängel beseitigt. 2025-08-29 10:34:31 +02:00
Marvin Flock cf52c718e8 chore: some review fixes 2025-08-28 22:24:13 +02:00
Marvin Flock 8b29c8eba6 chore: some review fixes 2025-08-28 22:19:11 +02:00
Marvin Flock e9460ef8cc Merge branch 'sportsmanager2-dev' into sportsmanager2-issue052
# Conflicts:
#	src/structure/components/com_sportsmanager/admin.php
#	src/structure/components/com_sportsmanager/sportsmanager.php
#	src/structure/components/com_sportsmanager/views/sportsmanager/view_admin.php
2025-08-28 21:58:43 +02:00
Marvin Flock 3ac38abb92 chore: some review fixes 2025-08-28 21:42:52 +02:00
Marvin Flock 19ff8ebd08 chore: some review fixes 2025-08-28 21:20:20 +02:00
Marvin Flock 3ab2ae9206 chore: some review fixes 2025-08-28 21:18:23 +02:00
Marvin Flock 4820f82253 chore: some review fixes 2025-08-28 21:16:34 +02:00
Marvin Flock 0a06321a72 chore: remove unused style tag 2025-08-28 20:31:42 +02:00
Marvin Flock 60232d95b3 chore: remove empty class attributes, fix label for input 2025-08-28 20:18:52 +02:00
Marvin Flock f27b87a0d8 chore: add return types to methods 2025-08-28 20:01:58 +02:00
Jürgen Meyer bc6c44e82a Eingeschränkte Spieler erscheinen jetzt auch in Vereinsdetails. 2025-08-27 06:41:25 +02:00
Jürgen Meyer 01ac642de5 Passive Vereinsmitglieder werden in Vereinsdetails nicht mehr angezeigt. 2025-08-26 06:27:43 +02:00
Jürgen Meyer 825a072ace Änderungen zu issue #149 (Resize in yoothemeBild) 2025-08-19 10:07:12 +02:00
Jürgen Meyer 1aa9b924d7 Noch ein paar kleine Änderungen 2025-08-17 18:11:46 +02:00
Jürgen Meyer 4a96d9f0a9 Fehler in script.php und update.php behoben 2025-08-16 18:05:35 +02:00
Jürgen Meyer 7a59020e64 Änderungen für issue #125, issue #116 und issue #117 2025-08-16 17:48:14 +02:00
Jürgen Meyer 3f816235c8 Änderungen für issue #52, issue #131 und issue #143 2025-08-15 13:54:04 +02:00
Marvin Flock 4f264ed72d fix: add previously deleted parameter back into sprintf again with reference to $spieler 2025-08-14 22:34:33 +02:00
MarvinF a6f302cb63 Merge pull request #142 from Deutscher-Tischfussballbund/chore/automatic-version-update-in-manifest-xml
chore: update manifest xml sportsmanager version with pipeline
2025-08-12 20:44:48 +02:00
Marvin Flock 22c50e688a chore: update manifest xml sportsmanager version with pipeline 2025-08-12 01:44:13 +02:00
MarvinF fbd7e05abb Merge pull request #141 from Deutscher-Tischfussballbund/chore/add-release-process-to-readme
chore: update readme with more details to release process
2025-08-12 01:18:15 +02:00
MarvinF a36edeedca Merge branch 'sportsmanager2-dev' into chore/add-release-process-to-readme 2025-08-12 01:17:56 +02:00
Marvin Flock ea9fd038f3 chore: update readme with more details to release process 2025-08-12 01:17:00 +02:00
MarvinF e55d925034 Merge pull request #140 from Deutscher-Tischfussballbund/chore/add-release-process-to-readme
chore: add release process to readme
2025-08-12 01:14:05 +02:00
Marvin Flock 48d0bca1c6 chore: add release process to readme 2025-08-12 01:12:57 +02:00
MarvinF ba9c84dfe7 Merge pull request #139 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod merge
2025-08-12 00:31:56 +02:00
MarvinF f424dfe024 Merge pull request #138 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2025-08-12 00:31:06 +02:00
MarvinF f382c3a208 Merge pull request #137 from Deutscher-Tischfussballbund/chore/version
chore: read correct tag version
2025-08-12 00:30:13 +02:00
Marvin Flock 2d7fb27ee1 chore: read correct tag version 2025-08-12 00:03:51 +02:00
MarvinF 93769df3ac Merge pull request #136 from Deutscher-Tischfussballbund/sportsmanager2-stage
Sportsmanager2 stage
2025-08-11 23:55:48 +02:00
MarvinF ee6d559a7f Merge pull request #135 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2025-08-11 23:54:51 +02:00
MarvinF 6e9b2c4f5e Merge pull request #134 from Deutscher-Tischfussballbund/chore/version
chore: debug tag versions
2025-08-11 23:53:51 +02:00
Marvin Flock f713362c3e chore: debug tag versions 2025-08-11 23:51:45 +02:00
MarvinF 71dd59c3d8 Merge pull request #133 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod merge
2025-08-11 23:23:53 +02:00
MarvinF 9594ec84e2 Merge pull request #132 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage merge
2025-08-11 23:22:20 +02:00
MarvinF 79adb9efd2 Merge pull request #123 from Deutscher-Tischfussballbund/sportsmanager2-issue121
Sportsmanager2 issue121
2025-08-11 23:16:22 +02:00
MarvinF 7d7f162dde Merge branch 'sportsmanager2-dev' into sportsmanager2-issue121 2025-08-11 23:14:29 +02:00
MarvinF 1538738722 Merge pull request #124 from Deutscher-Tischfussballbund/feature/issue-85-query-performance-improv
Refactor: remove execute() on reading queries
2025-08-11 23:11:44 +02:00
Jürgen Meyer eb4bcf38d9 Änderungen nach review 2025-08-11 18:31:07 +02:00
Marvin Flock 0d8e61b3ca Merge branch 'sportsmanager2-dev' into feature/issue-85-query-performance-improv
# Conflicts:
#	src/structure/components/com_sportsmanager/admin.php
#	src/structure/components/com_sportsmanager/sportsmanager.php
2025-08-11 18:30:06 +02:00
MarvinF 3f26a340dc Merge pull request #112 from Deutscher-Tischfussballbund/fix/issue-6-sql-syntax-error
Issue 6: fix sql syntax error
2025-08-11 17:59:14 +02:00
MarvinF 87d9449417 Merge branch 'sportsmanager2-dev' into fix/issue-6-sql-syntax-error 2025-08-11 17:58:53 +02:00
MarvinF e0575dc125 Merge pull request #113 from Deutscher-Tischfussballbund/sportsmanager2-issue059
Sportsmanager2 issue059
2025-08-11 17:58:26 +02:00
MarvinF b1f67d1d13 Merge pull request #127 from Deutscher-Tischfussballbund/chore/version-from-tags
chore: create version in sportsmanager from git tag
2025-08-11 17:43:27 +02:00
Marvin Flock f119cae584 chore: restore breaks in switch statement 2025-08-11 00:19:43 +02:00
jmeyer26 18d346a4e9 Merge pull request #115 from Deutscher-Tischfussballbund/sportsmanager2-issue068
Sportsmanager2 issue068
2025-08-05 21:39:20 +02:00
Marvin Flock e81600dd86 Merge branch 'sportsmanager2-dev' into sportsmanager2-issue068 2025-08-05 21:30:57 +02:00
Marvin Flock ff7314cf3f chore: create version in sportsmanager from git tag 2025-08-05 21:21:11 +02:00
Jürgen Meyer 1fe9d4bc5f Änderung nach Review durchgeführt. 2025-08-05 20:45:33 +02:00
Marvin Flock 5e3996dd5e fix: add missing line breaks 2025-08-04 18:21:47 +02:00
Marvin Flock 9861f59662 refactor: remove execute() on reading queries 2025-08-04 00:00:42 +02:00
Jürgen Meyer 9f6c026b2b Verschachtelte Tabelle entfernt. Redundante if-Anweisungen entfernt. 2025-08-01 19:34:53 +02:00
Jürgen Meyer 850fd2c079 Einige Optimierungen durchgeführt. 2025-08-01 16:02:32 +02:00
MarvinF 762bf50f62 Merge pull request #111 from Deutscher-Tischfussballbund/fix/issue45-duplicate-license-on-ranking-duplication
Fix: duplicate Ranglisten should also duplicate license checkbox values of the duplicate source rangliste
2025-08-01 01:31:39 +02:00
MarvinF 19fc2c8800 Merge branch 'sportsmanager2-dev' into fix/issue45-duplicate-license-on-ranking-duplication 2025-08-01 01:30:28 +02:00
MarvinF be1b66eb8e Merge pull request #122 from Deutscher-Tischfussballbund/fix/explode-lizenzen
Fix: refresh rankings even when there are no licenses set
2025-07-31 17:05:32 +02:00
Marvin Flock cf14997acb fix: explode of licenses only if licenses are given 2025-07-31 16:59:12 +02:00
Jürgen Meyer 0d3e54a544 Mannschaftsdetails und Spielerdetails für Mobil angepasst 2025-07-31 12:01:52 +02:00
MarvinF 7b1cc50943 Merge pull request #120 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage -> Prod merge
2025-07-29 18:30:28 +02:00
MarvinF 133a983685 Merge pull request #119 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev -> Stage merge
2025-07-29 18:28:39 +02:00
MarvinF 20b956b239 Merge pull request #118 from Deutscher-Tischfussballbund/feature/refactor-readme
refactor: remove test from readme
2025-07-29 18:21:05 +02:00
Marvin Flock fedb300d8f refactor: remove test from readme 2025-07-29 18:19:01 +02:00
MarvinF 07121c2233 Merge pull request #114 from Deutscher-Tischfussballbund/fix/issue-108-yootheme-path-fix
fix: add base url to yootheme images
2025-07-29 18:01:16 +02:00
MarvinF 8dab7fa74f Merge branch 'sportsmanager2-dev' into fix/issue-108-yootheme-path-fix 2025-07-29 17:59:55 +02:00
Jürgen Meyer 3e577f6be1 Kein Aufruf Korrekturschleife, wenn kein Array Korrektur vorhanden. 2025-07-24 16:29:13 +02:00
Jürgen Meyer 2b6563dae0 Möglichkeit Direkter Vergleich in Teamsport (issue #68) 2025-07-23 09:40:05 +02:00
jmeyer26 1bd53893a8 Merge pull request #83 from Deutscher-Tischfussballbund/sportsmanager2-juergen
Fix: #74 Player picture improvements & remove 'Ranglisten' YooTheme Lazyloading optimizations
2025-07-22 05:49:22 +02:00
Jürgen Meyer acfcbb1010 Funktion yoothemeBild in rangliste wird wieder aufgerufen. 2025-07-22 05:46:23 +02:00
Marvin Flock a6aee26211 fix: add base url to yootheme images 2025-07-21 20:17:20 +02:00
MarvinF b24203ccb9 Merge pull request #109 from Deutscher-Tischfussballbund/sportsmanager2-issue108
Mannschaftsbilder in Teamsport zu klein gefixt (issue #108)
2025-07-21 19:43:44 +02:00
Jürgen Meyer 2ff39cf086 Fehler Versatz Header Tabelle wenn Bilder fehlen gefixt. 2025-07-16 10:34:40 +02:00
Jürgen Meyer 8479691824 Optimierung Ablöschung temporärer Import-Daten 2025-07-14 17:01:21 +02:00
Jürgen Meyer ca4ce6060e Überprüfung Format Spielernummer bei Import (issue #59) 2025-07-14 08:23:34 +02:00
Jürgen Meyer 0729291afc Fehler Anführungszeichen korrigiert. 2025-07-13 23:34:51 +02:00
Marvin Flock b57c7c148d fix: abort when id is null 2025-07-13 23:17:00 +02:00
Marvin Flock b17fcffdd5 fix: replace http:// with https:// 2025-07-13 22:06:50 +02:00
Marvin Flock 97c6d9ee03 fix: duplicate licence fields when duplicating ranking 2025-07-13 21:37:28 +02:00
Jürgen Meyer f3c2040632 Mannschaftsbilder in Teamsport zu klein gefixt (issue #108) 2025-07-02 08:19:44 +02:00
Jürgen Meyer 1235edde82 Letzte Änderung wegen Konflikten rückgängig gemacht. 2025-07-01 12:37:41 +02:00
Jürgen Meyer 763fd7d386 Tabellenformatierung angepasst (issue #108) 2025-07-01 12:31:03 +02:00
MarvinF 77e2c6e910 Merge pull request #77 from Deutscher-Tischfussballbund/issues/43
fix: #43 - remove css3.js reference
2025-06-30 18:57:43 +02:00
MarvinF a2aee3b135 Merge pull request #82 from Deutscher-Tischfussballbund/issues/73_missing-dropdown-in-league
fix: add season dropdown to events, even if there is just one event
2025-06-30 18:57:10 +02:00
MarvinF 9a7f8acc3b Merge pull request #107 from Deutscher-Tischfussballbund/fix/64_division_by_zero
Fix: add division by zero check, return zero instead of exception
2025-06-30 18:55:47 +02:00
Jürgen Meyer 9091b22859 Konfilkt mit README.md 2025-06-30 00:52:54 +02:00
Jürgen Meyer 839b27756a Konflikt mit README.md 2025-06-30 00:50:03 +02:00
Jürgen Meyer 0d0ee08199 Weitere Optimierungen der Tabellen Rangliste, Turnierergebnisse und Spielerstatistik 2025-06-30 00:16:05 +02:00
Jürgen Meyer 6609a4ca78 Änderungen nach Kommentaren in PR83 überarbeitet. 2025-06-29 19:00:59 +02:00
Marvin Flock 4ecf48d02e fix: add division by zero check, return zero instead of exception 2025-06-29 16:44:18 +02:00
MarvinF 40633f864a Merge pull request #106 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod pr
2025-06-25 17:23:09 +02:00
MarvinF 8e6aa127c6 Merge pull request #105 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage pr
2025-06-25 17:21:52 +02:00
MarvinF 9289843cb1 Update README.md 2025-06-25 17:19:33 +02:00
MarvinF 7a70500175 Merge pull request #76 from Deutscher-Tischfussballbund/php-debugging
feat: add debugging for php in docker
2025-06-25 17:14:02 +02:00
MarvinF 31b8e5251e Update release-drafter_extension.yml 2025-06-25 01:22:57 +02:00
MarvinF 455f845ab0 Update build_release.yml 2025-06-25 01:21:52 +02:00
MarvinF f55d89827a Merge pull request #103 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod pr
2025-06-25 01:00:10 +02:00
MarvinF 874e06e061 Merge pull request #102 from Deutscher-Tischfussballbund/sportsmanager2-dev
dev to stage pr
2025-06-25 00:59:11 +02:00
MarvinF 83b8e1c25f Create release-drafter_github.yml 2025-06-25 00:52:06 +02:00
MarvinF 3c9fac7e1a Rename release-drafter.yml to release-drafter_extension.yml 2025-06-25 00:50:45 +02:00
MarvinF 4ec02e5f02 Update build_release.yml 2025-06-25 00:49:57 +02:00
MarvinF 4d1573729d Merge pull request #101 from Deutscher-Tischfussballbund/sportsmanager2-stage
stage to prod PR
2025-06-25 00:36:39 +02:00
MarvinF 6da371569a Merge pull request #100 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev to Stage PR
2025-06-25 00:35:48 +02:00
MarvinF fdede4a4a7 Delete .github/release-drafter_github.yml 2025-06-25 00:31:36 +02:00
MarvinF 7ced30cf5b Rename release-drafter_extension.yml to release-drafter.yml 2025-06-25 00:31:08 +02:00
MarvinF 934b5b4971 Update build_release.yml 2025-06-25 00:30:35 +02:00
MarvinF 085e5a8aeb Merge pull request #99 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage to Prod PR
2025-06-24 23:29:31 +02:00
MarvinF 53ada7c6b0 Merge pull request #98 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev to Stage PR
2025-06-24 23:28:19 +02:00
MarvinF 29dbfaeea4 Update build_release.yml 2025-06-24 23:25:58 +02:00
MarvinF 95e02435fd Merge pull request #97 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage to Prod PR
2025-06-24 23:06:32 +02:00
MarvinF 32eacde07d Merge pull request #96 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev to Stage PR
2025-06-24 23:05:43 +02:00
MarvinF 2b19aee00f Update release-drafter_extension.yml 2025-06-24 23:04:06 +02:00
MarvinF 8b6ad5103c Update release-drafter_github.yml 2025-06-24 23:03:51 +02:00
MarvinF 743f2b4013 Update release-drafter_github.yml 2025-06-24 22:53:45 +02:00
MarvinF 2d2a124239 Update release-drafter_extension.yml 2025-06-24 22:53:23 +02:00
MarvinF d1e0dec74a Update autolabel.yaml 2025-06-24 22:52:56 +02:00
MarvinF c4c3ea88fc Merge pull request #95 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage to Prod PR
2025-06-24 22:42:28 +02:00
MarvinF 761e04b6f2 Merge pull request #94 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev to Stage PR
2025-06-24 22:41:27 +02:00
MarvinF 089796d201 Create autolabel.yaml 2025-06-24 22:37:05 +02:00
MarvinF e2b6f48498 Update release-drafter_github.yml 2025-06-24 22:33:49 +02:00
MarvinF 3422813152 Update release-drafter_github.yml 2025-06-24 22:32:31 +02:00
MarvinF 67b46f121a Update release-drafter_extension.yml 2025-06-24 22:31:47 +02:00
MarvinF 6c3c9badfd Create release-drafter_github.yml 2025-06-24 22:06:27 +02:00
MarvinF e05d107af3 Rename release-drafter.yml to release-drafter_extension.yml 2025-06-24 22:05:51 +02:00
MarvinF 2f94c29c7e Update build_release.yml 2025-06-24 22:05:24 +02:00
MarvinF b656cb5df3 Merge pull request #93 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage to prod PR
2025-06-24 21:49:28 +02:00
MarvinF af97c59960 Merge pull request #92 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev to Stage PR
2025-06-24 21:48:48 +02:00
MarvinF ebb3580fad Update build_release.yml 2025-06-24 21:47:56 +02:00
MarvinF 4a313d5914 Merge pull request #91 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage to prod PR
2025-06-24 21:23:42 +02:00
MarvinF 771856b842 Merge pull request #90 from Deutscher-Tischfussballbund/sportsmanager2-dev
Dev to Stage PR
2025-06-24 21:22:59 +02:00
MarvinF 0c4d0820d1 Update build_release.yml 2025-06-24 21:22:00 +02:00
MarvinF 8a0ad8d8e9 Merge pull request #89 from Deutscher-Tischfussballbund/sportsmanager2-stage
Stage 2 Prod PR
2025-06-24 21:06:54 +02:00
MarvinF 03a448f4cc Merge pull request #88 from Deutscher-Tischfussballbund/sportsmanager2-dev
stage PR
2025-06-24 21:05:39 +02:00
MarvinF 9d75619c2c Update release-drafter.yml 2025-06-24 20:28:20 +02:00
MarvinF a1890c51c0 feat: add release notes to extension installation 2025-06-24 20:20:28 +02:00
Marvin Flock 51ee656f66 feat: add release notes to extension installation 2025-06-24 20:16:51 +02:00
MarvinF 6d9df0e769 Create release-drafter.yml 2025-06-24 20:11:53 +02:00
MarvinF a74bcb0ee8 Update build_release.yml 2025-06-24 20:10:53 +02:00
MarvinF 6399eab0af Update build_release.yml 2025-06-24 19:33:06 +02:00
MarvinF 9cde84a1d0 Update build_snapshot.yml 2025-06-24 19:32:50 +02:00
MarvinF 76738ec307 Update build_snapshot.yml 2025-06-24 19:30:36 +02:00
MarvinF 59e1a4571b Create prod release pipeline 2025-06-24 19:29:17 +02:00
Tim 7952c95217 Merge branch 'sportsmanager2-dev' into php-debugging 2025-06-24 18:58:07 +02:00
Tim 56679669c0 feat: extend tournament result upload window to 14 days for uploaders 2025-06-24 13:58:02 +00:00
Tim 1e8a7a3ae0 chore: add migration script for tournament reminder fields 2025-06-24 13:53:11 +00:00
Tim 269af499c8 feat: add auto-email reminder script for missing tournament results 2025-06-24 13:48:13 +00:00
Jürgen Meyer 56d8be9a55 Hilfskommentare in Programm zu issue #74 rausgelöscht. 2025-06-24 13:52:32 +02:00
Jürgen Meyer 29f0e6842b issue #74 Player image size (Details siehe issue #74) 2025-06-24 13:29:20 +02:00
Marvin Flock 22e96bf49d fix: add season dropdown to events, even if there is just one event 2025-06-23 21:12:43 +02:00
MarvinF 1e4e34ef71 Merge pull request #65 from Deutscher-Tischfussballbund/tfvb_league_admin_infos
Tfvb league admin infos
2025-06-22 21:27:50 +02:00
DTFB-PaulF d98f7da7b9 Merge pull request #78 from Deutscher-Tischfussballbund/feature-test-paul-jürgen
Test2
2025-06-19 19:24:28 +02:00
Jürgen Meyer 94e768ef51 Test2 2025-06-19 19:19:21 +02:00
Marvin Flock 36dbfdb7c4 fix: check for null since str_starts_with is typed 2025-06-17 22:01:07 +02:00
Marvin Flock 5cfd8f3c1a fix: remove non existent css reference 2025-06-17 22:00:08 +02:00
Marvin Flock 1d7369e456 Merge branch 'sportsmanager2-stage' into sportsmanager2-dev 2025-06-17 21:36:16 +02:00
Marvin Flock de467c0d4a feat: add debugging for php in docker 2025-06-17 21:29:15 +02:00
Tim 0225e49beb Updated/added envs in README.md
Updated/added environments
2025-06-17 00:08:32 +02:00
Jürgen Meyer e1ecec502b Überarbeitung Startseite: 2025-06-15 16:22:58 +02:00
Jürgen Meyer 000731a289 In Kategorieliste Verbandsorgane hinzugefügt. 2025-06-13 11:40:01 +02:00
Wieland Hagen 385bef0752 Admin League Team View: add tooltip 2025-06-12 17:55:05 +02:00
Jürgen Meyer 902ae55a9a Formular Veranstaltung übersichtlicher gestaltet 2025-06-12 17:04:20 +02:00
Jürgen Meyer feb08ff903 Falsche Versionsnr in script.php. Style von Formular Export Spielberichte optimiert. 2025-06-12 10:50:57 +02:00
Jürgen Meyer a922b11b6d Korrektur der Farben in Formular Gruppenspiele erzeugen (issue #71) 2025-06-11 14:52:22 +02:00
Marvin Flock 254d556899 Merge branch 'dev' into sportsmanager2-dev 2025-06-10 17:41:28 +02:00
MarvinF 6793c53002 Update build_snapshot.yml 2025-06-09 16:58:45 +02:00
MarvinF 8b671fd005 Update build_snapshot.yml 2025-06-09 16:44:51 +02:00
MarvinF 37ad8dd24c Create build_snapshot.yml 2025-06-09 16:44:50 +02:00
Marvin Flock 35f128d949 change: update Readme for deployment trigger 2025-06-04 17:38:46 +02:00
Marvin Flock 825e643959 change: update Readme for deployment trigger 2025-06-02 23:36:49 +02:00
Helmut Poppen eb6b81b3dd Changed DisplayController from UTF8-BOM to UTF8 2025-05-20 10:34:30 +02:00
Marvin Flock 8638311065 fix: send mails only when at least one email address is given 2025-05-13 22:55:45 +02:00
Marvin Flock 67c91c65ab chore: deployment hook test 2025-05-13 20:04:26 +02:00
Marvin Flock 365e7f00fd fix: put namespaces as first line after php opening tag 2025-05-13 19:50:01 +02:00
Marvin Flock d54e248d02 fix: put namespaces as first line after php opening tag 2025-05-13 19:45:38 +02:00
Helmut Poppen ec54893106 Deployment Hook Test 2025-05-13 11:14:51 +02:00
Helmut Poppen fe7c45a635 Deployment Hook Test 2025-05-13 11:12:27 +02:00
Wieland Hagen 2dddfa473a Admin League Games View: display "+0d" for 0 day shifts, fix SQL query 2025-05-11 21:26:22 +02:00
DTFB-PaulF c59728c5a8 Merge pull request #67 from Deutscher-Tischfussballbund/bug/propose_date_not_working
fix: change reading of value fields by using brackets
2025-05-07 09:40:02 +02:00
Marvin Flock 8f3c1bcef9 fix: change reading of value fields by using brackets 2025-05-06 22:02:44 +02:00
MarvinF 45558f3228 Merge pull request #66 from Deutscher-Tischfussballbund/bug/mail_duplication
mail duplication
2025-05-05 22:47:19 +02:00
Marvin Flock a1ae678f6d fix: replace sendMail loop with bcc loop in order to send one mail instead of way too many 2025-05-04 22:38:33 +02:00
Wieland Hagen 82c0f3a58b Admin League Games View: show various additional information
- mark teams which have requested a game shift
- display amount of time that a game has been shifted
- display time that has passed between game and result proposal, and result proposal and result validation
- mark games with incomplete player data
2025-05-04 21:04:36 +02:00
Wieland Hagen a6fe497cad Admin League Team View: show number of shifts that each team is responsible for 2025-05-04 20:59:06 +02:00
Marvin Flock e3283af13f fix: change line order for <br> to only appear when actual url is filled 2025-05-03 17:09:19 +02:00
Jürgen Meyer e205382f52 Eingabeformular Spielbericht optimiert 2025-04-30 16:49:31 +02:00
Jürgen Meyer a235ee9abc Bugfixes: Groesse Passbild Spieler 2, Kategorien ueber 30 2025-04-29 15:41:40 +02:00
Jürgen Meyer 6a4748e4d6 Dropdownliste Liga erweitert und Bugs bei Export gefixt. 2025-04-29 08:42:32 +02:00
Marvin Flock a32cbdcb35 chore: change bind mounts to named volumes to increase performance significantly 2025-04-25 00:48:18 +02:00
Marvin Flock 5c026641c7 fix: use UserFactoryInterface and align input 2025-04-24 20:15:31 +02:00
Marvin Flock 43ebed6b39 fix: use correct dependency injection for json to work 2025-04-23 20:31:09 +02:00
Marvin Flock c7e9f664e2 fix: remove ignore flag from adding licence fields, implement proper check for fields 2025-04-23 17:48:42 +02:00
Marvin Flock 10032fd6a9 fix: add ignore to license db fields, if already existing ignore errors 2025-04-23 16:38:43 +02:00
Marvin Flock ddec58e302 fix: resolve merge conflicts 2025-04-23 12:32:31 +02:00
Marvin Flock 047e6c46af fix: remove duplicated styling 2025-04-22 20:21:40 +02:00
Marvin Flock 9f215b9dfa fix: use correct mailer interface for sending mails 2025-04-22 19:50:34 +02:00
Marvin Flock cc2a411480 chore: remove unused imports 2025-04-22 19:24:09 +02:00
Marvin Flock c246328540 fix: revert removal of distribution methods 2025-04-22 19:16:56 +02:00
Marvin Flock 021283fe7e fix: folder and file handling by using native php methods 2025-04-22 17:39:15 +02:00
Marvin Flock bf25471571 fix: start image url with slash 2025-04-22 17:04:44 +02:00
Marvin Flock 8d50de12d7 chore: update copyright text 2025-04-22 16:46:55 +02:00
Marvin Flock dbdf7be51a fix: resolve merge conflicts of joomla_6 branch 2025-04-21 22:07:45 +02:00
MarvinF d5eee17e8f Merge pull request #55 from Deutscher-Tischfussballbund/mimetypes
fix: add more mimetypes
2025-04-21 18:05:53 +02:00
MarvinF 82a7bbe63c Merge pull request #60 from Deutscher-Tischfussballbund/birthdate_validation
Birthdate validation
2025-04-21 18:05:07 +02:00
MarvinF 7435db170c Merge pull request #63 from Deutscher-Tischfussballbund/bug/login-error
Fix Login Error
2025-04-21 17:56:57 +02:00
Jürgen Meyer fe453a8454 Export Funktion für Spielberichte, Spieler in Teams und Spielplan 2025-04-19 12:30:40 +02:00
arnef fc37696779 fix query limit method to use setLimit() 2025-04-17 21:53:27 +02:00
Marvin Flock d0ada72b68 fix: remove birthday from player, replace with birthyear where necessary 2025-04-17 20:02:02 +02:00
Jürgen Meyer e3167e7175 Termine kopieren.
Fehler beim Logging Termin löschen gefixt.
2025-04-17 10:34:02 +02:00
Jürgen Meyer 541a20c694 Termine Relative Links auch in E-Mail Versand Änderung 2025-04-16 17:52:07 +02:00
Jürgen Meyer 5d3f26dfee In Termine Ergebnisse auch als relativer Link möglich 2025-04-16 13:04:49 +02:00
Marvin Flock c59a0be5ec feat: enable logging into own log file com_sportsmanager.php 2025-04-09 15:59:16 +02:00
Marvin Flock fea9f4089c fix: remove tick 2025-04-09 15:48:31 +02:00
Marvin Flock cac8f33aa7 fix: add more specific error message to no access method 2025-04-09 15:38:21 +02:00
Marvin Flock 543aceaeab fix: remove initial validation
feat:  remove birthday and birthmonth
2025-04-02 19:22:27 +02:00
Marvin Flock 1d2e3bb52f feat: add required to firstname and lastname player fields 2025-04-02 19:21:18 +02:00
Helmut Poppen 98f8b5904c Webhook Test 2025-03-31 20:31:13 +02:00
Helmut Poppen cfdbeb7ecb Webhook Test 2025-03-31 19:50:31 +02:00
Helmut Poppen 57fcd04ff7 Webhook Test 2025-03-31 19:42:56 +02:00
Helmut Poppen 993490e4bf Webhook Test 2025-03-31 19:39:58 +02:00
Helmut Poppen 448fbfd19a Webhook Test 2025-03-31 19:36:34 +02:00
Jürgen Meyer 9e1df7c03d Merge branch 'sportsmanager-2-stfv' of github.com:Deutscher-Tischfussballbund/com_sportsmanager into sportsmanager-2-stfv 2025-03-31 18:12:30 +02:00
Helmut Poppen d06a4b433a Test Webhook 2 2025-03-31 17:15:38 +02:00
Helmut Poppen 16bc0d3188 Test Webhook 2025-03-31 17:12:51 +02:00
Jürgen Meyer 65152e51d3 Doppel 7 und 8 für Dropdown Mannschaftsspielpläne hinzugefügt. 2025-03-31 09:58:53 +02:00
Marvin Flock a589ca8337 fix: remove duplicate language keys, change some of the language keys 2025-03-28 20:55:41 +01:00
Marvin Flock 067e67e08b chore: outsource more image methods into own file 2025-03-28 14:32:53 +01:00
Marvin Flock 0f4a3242b1 fix: add labels, init variables, replace deprecated joomla 3 classes, add return types, removed commented code, removed unused parameters 2025-03-28 14:31:33 +01:00
Marvin Flock 1af673df17 chore: update readme 2025-03-28 14:24:29 +01:00
Marvin Flock 31a3eeef12 chore: replace database.php by splitting into init and update 2025-03-28 14:24:02 +01:00
Marvin Flock 4ca16747af chore: update project structure with basic mvc approach 2025-03-28 14:23:12 +01:00
Marvin Flock 563e0e6294 chore: Update copyright 2025-03-18 20:35:00 +01:00
Marvin Flock 5d85be8937 fix: implement some minor fixes 2025-03-18 20:34:09 +01:00
Marvin Flock 1eed53ae9c fix: add missing php ini to docker compose 2025-03-18 20:29:33 +01:00
Marvin Flock fcc6c7e538 feat: add birthday validation 2025-03-18 20:29:05 +01:00
Marvin Flock eeb423fcbc chore: remove variable assignment in if statements 2025-03-18 20:27:40 +01:00
MarvinF 0c9a94a07f Merge pull request #56 from Deutscher-Tischfussballbund/license_fixes
fix: minor fixes regarding licenses including database fields for license
2025-03-18 12:57:08 +01:00
Helmut Poppen 9e730ad179 First version of match import 2025-03-17 22:14:37 +01:00
Marvin Flock 4ba20a793d Merge branch 'sportsmanager2' into license_fixes
# Conflicts:
#	src/structure/script.php
2025-03-12 17:37:29 +01:00
Marvin Flock e725f0fcea fix: add missing license fields to install.php, change order of fields 2025-03-12 17:29:22 +01:00
MarvinF e8af5349e6 Merge pull request #57 from Deutscher-Tischfussballbund/testsetup_fixes
test setup fixes
2025-03-12 14:08:47 +01:00
Marvin Flock 870b15d947 chore: update meta data 2025-03-12 13:24:56 +01:00
Marvin Flock eb751f28fc chore: add test setup to readme 2025-03-11 21:16:07 +01:00
Marvin Flock 0d59ed7003 fix: change pathes of kickboilerplate to sportsmanager to allow builds again 2025-03-11 21:15:44 +01:00
Marvin Flock 57048d3a3f chore: update sportsmanager.xml 2025-03-11 21:14:49 +01:00
Marvin Flock 6645678ed2 fix: outsource bildKopierenAngepasst method to be reused from within script.php
chore: move and rename install.php to root path and rename to script.php
2025-03-11 21:11:22 +01:00
Marvin Flock 621f7d3d64 fix: update docker-compose.yml for joomla 5.2.4 2025-03-11 21:07:18 +01:00
Marvin Flock b9a7a6f222 chore: remove unused files 2025-03-11 21:06:15 +01:00
Marvin Flock e5f3d15ac1 fix: add missing license fields to database update 2025-03-10 19:38:42 +01:00
Marvin Flock b776cea826 fix: cut bytestring into numeric part 2025-03-10 19:38:10 +01:00
Marvin Flock d4c7bbc183 fix: replace is_array check with actual array 2025-03-10 19:37:10 +01:00
StefanE ee4799c287 Remove wrong comma in query build 2025-03-04 00:00:40 +01:00
Paul Fleischanderl fbdcfacb21 sportsmanager 2.0 changes merge result 2025-02-28 17:13:35 +01:00
Marvin Flock f0e7a20e6b fix: add more mimetypes 2025-02-11 11:47:13 +01:00
DTFB-PaulF 5a25f6d398 Merge pull request #53 from Deutscher-Tischfussballbund/dev
paul: bugfix player import no update for spieler_nr
2024-11-17 13:10:24 +01:00
Helmut Poppen 322906ff70 Merge branch 'dev' into production
# Conflicts:
#	src/structure/language/de-DE/de-DE.com_sportsmanager.ini
2024-11-15 13:19:57 +01:00
Stefan Wendhausen 935f8ef7d8 Update de-DE.com_sportsmanager.ini
Test action
2024-08-06 20:45:55 +02:00
Stefan Wendhausen 92785965b2 Create kickernprod.yml 2024-08-06 20:28:34 +02:00
Stefan Wendhausen 405f030364 Create dtfbprod.yml 2024-08-06 20:27:39 +02:00
Helmut Poppen a9b088dcda Merge pull request #44 from Deutscher-Tischfussballbund/dev
Fixed table width for Turnierergebnisse
2023-07-01 13:11:20 +02:00
Tim 5c089a4325 Merge pull request #41 from Deutscher-Tischfussballbund/dev
Release Jan 2023
2023-01-16 15:19:27 +01:00
66 changed files with 67856 additions and 59676 deletions
+25
View File
@@ -0,0 +1,25 @@
name-template: "Release $COMPLETE"
tag-template: "v$COMPLETE"
draft: false
exclude:
pulls: true
exclude-labels:
- changelog-ignore
categories:
- title: "Features"
labels: ["feature", "enhancement"]
- title: "Fixes"
labels: ["bug"]
- title: "Maintenance"
labels: ["chore", "refactor"]
change-template: "- $TITLE [#$NUMBER]"
template: |
# Release $RESOLVED_VERSION
## Changes
$CHANGES
+23
View File
@@ -0,0 +1,23 @@
name-template: "Release $COMPLETE"
tag-template: "v$COMPLETE"
draft: false
exclude:
pulls: true
exclude-labels:
- changelog-ignore
categories:
- title: "Features"
labels: ["feature", "enhancement"]
- title: "Fixes"
labels: ["bug"]
- title: "Maintenance"
labels: ["chore", "refactor"]
change-template: "- $TITLE [#$NUMBER]"
template: |
## Changes
$CHANGES
+25
View File
@@ -0,0 +1,25 @@
name: Auto-label PRs
on:
pull_request:
types: [opened, reopened, synchronize, edited]
jobs:
label-changelog-ignore:
runs-on: ubuntu-latest
steps:
- name: Label PRs
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const base = context.payload.pull_request.base.ref;
const head = context.payload.pull_request.head.ref;
if ((base === 'sportsmanager2-prod' && head === 'sportsmanager2-stage') || (base === 'sportsmanager2-stage' && head === 'sportsmanager2-dev')) {
await github.rest.issues.addLabels({
...context.repo,
issue_number: context.payload.pull_request.number,
labels: ['changelog-ignore']
});
}
+100
View File
@@ -0,0 +1,100 @@
# This workflow will run release using node and then publish a package to GitHub Packages when a release is created
# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
name: Sportsmanager Release
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+' # run only on version tags like v1.0.0
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: sportsmanager2-prod
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install npm dependencies
run: npm ci
- name: Get version from git tag
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
- name: Set DATE
run: echo "DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Update version.php
run: |
echo "<?php" > src/structure/components/com_sportsmanager/util/version.php
echo "defined('_JEXEC') or die;" >> src/structure/components/com_sportsmanager/util/version.php
echo "return [" >> src/structure/components/com_sportsmanager/util/version.php
echo " 'version' => '${{ env.VERSION }}'," >> src/structure/components/com_sportsmanager/util/version.php
echo " 'date' => '$(date +%F)'," >> src/structure/components/com_sportsmanager/util/version.php
echo "];" >> src/structure/components/com_sportsmanager/util/version.php
echo "Updating version to $VERSION in sportsmanager.xml"
sed -i "s#<version>.*</version>#<version>$VERSION</version>#" src/structure/sportsmanager.xml
echo "Updating Date to $DATE in sportsmanager.xml"
sed -i "s#<creationDate>.*</creationDate>#<creationDate>$DATE</creationDate>#" src/structure/sportsmanager.xml
- name: Generate release notes
id: release_notes_extension
uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter_extension.yml
version: ${{ github.ref_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Save release notes to file
run: |
echo "${{ steps.release_notes_extension.outputs.body }}" > RELEASE_NOTES.md
- name: Run build script
run: npm run release
- name: Generate release notes
id: release_notes_github
uses: release-drafter/release-drafter@v6
with:
config-name: release-drafter_github.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Save release notes to file
run: |
echo "${{ steps.release_notes_github.outputs.body }}" > RELEASE_NOTES.md
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: "${{ github.ref_name }}"
name: "Release ${{ github.ref_name }}"
files: package/packages/com_sportsmanager.zip
body_path: "RELEASE_NOTES.md"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Delete draft release via API # workaround: remove leftover draft by release-drafter
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
drafts=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$REPO/releases | jq '.[] | select(.draft == true)')
if [ -n "$drafts" ]; then
id=$(echo "$drafts" | jq -r '.id')
curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/repos/$REPO/releases/$id
echo "Deleted draft release with ID: $id"
else
echo "No draft releases found"
fi
+2 -2
View File
@@ -6,7 +6,7 @@ name: Snapshot Release
on: on:
push: push:
tags: tags:
- 'v*-snapshot' # run only on version tags like v1.0.0-snapshot - 'v[0-9]+.[0-9]+.[0-9]+-snapshot' # run only on version tags like v1.0.0-snapshot
# - 'v*' # Run only on version tags like v1.0.0 # - 'v*' # Run only on version tags like v1.0.0
jobs: jobs:
build: build:
@@ -33,7 +33,7 @@ jobs:
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
prerelease: true prerelease: true
name: SNAPSHOT name: "Snapshot ${{ github.ref_name }}"
files: package/packages/com_sportsmanager.zip files: package/packages/com_sportsmanager.zip
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+84
View File
@@ -0,0 +1,84 @@
# Builds the codebase and publishes a rolling dev-preview release (no version bump).
# The release uses a fixed tag "dev-preview" so each run replaces the previous one.
name: Sportsmanager Dev Preview
on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to build'
required: true
default: 'sportsmanager2-prod'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ inputs.branch }}
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install npm dependencies
run: npm ci
- name: Run build script
run: npm run release
- name: Delete existing dev-preview release (if any)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
release_id=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO/releases/tags/dev-preview" \
| jq -r '.id // empty')
if [ -n "$release_id" ]; then
curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO/releases/$release_id"
echo "Deleted existing dev-preview release (ID: $release_id)"
else
echo "No existing dev-preview release found"
fi
- name: Delete existing dev-preview tag (if any)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
run: |
status=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO/git/refs/tags/dev-preview")
if [ "$status" = "200" ]; then
curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO/git/refs/tags/dev-preview"
echo "Deleted existing dev-preview tag"
else
echo "No existing dev-preview tag found"
fi
- name: Publish dev-preview release
uses: softprops/action-gh-release@v2
with:
tag_name: dev-preview
name: "Dev Preview (${{ github.run_number }})"
body: |
Automated dev preview build from branch `${{ inputs.branch }}`.
Commit: ${{ github.sha }}
Run: ${{ github.run_number }}
> This is a temporary preview release and will be replaced on the next run.
files: package/packages/com_sportsmanager.zip
draft: false
prerelease: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+23
View File
@@ -0,0 +1,23 @@
name: Deploy production branch to dtfb.de
on:
push:
branches: ['production']
paths: ['src/structure/**']
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: rsync deployments
uses: burnett01/rsync-deployments@7.0.1
with:
switches: -avzr
path: src/structure/
remote_path: ${{ secrets.DTFB_PROD_PATH }}
remote_host: ${{ secrets.DTFB_PROD_HOST }}
remote_port: ${{ secrets.DTFB_PROD_PORT }}
remote_user: ${{ secrets.DTFB_PROD_USER }}
remote_key: ${{ secrets.DTFB_PROD_KEY }}
+23
View File
@@ -0,0 +1,23 @@
name: Deploy production branch to kickern-hamburg.de
on:
push:
branches: ['production']
paths: ['src/structure/**']
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: rsync deployments
uses: burnett01/rsync-deployments@7.0.1
with:
switches: -avzr
path: src/structure/
remote_path: ${{ secrets.KICKERN_PROD_PATH }}
remote_host: ${{ secrets.KICKERN_PROD_HOST }}
remote_port: ${{ secrets.KICKERN_PROD_PORT }}
remote_user: ${{ secrets.KICKERN_PROD_USER }}
remote_key: ${{ secrets.KICKERN_PROD_KEY }}
+1 -1
View File
@@ -1,6 +1,6 @@
### WebStorm/IntelliJ ### ### WebStorm/IntelliJ ###
/.idea /.idea
.DS_Store
# Dependency directories # Dependency directories
/node_modules /node_modules
+101 -7
View File
@@ -1,13 +1,107 @@
# SportsManager # SportsManager
## Deploy status ## DEV/STAGE environments
### DEV environment | LV | HOSTER | DOMAIN | BRANCH |
[![buddy pipeline](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/173/badge.svg?token=de39e4e4c47351d592b59a5d1e26a41cf5196861f67d4499bbab990600468001 "buddy pipeline")](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/173) [Preview: sportsmanager.s10.kicktemp.dev](https://sportsmanager.s10.kicktemp.dev) | ------ | -------- | ------------------------------------------------------------ | -------------------- |
| DTFB | Kicktemp | [stage.dtfb.de](https://stage.dtfb.de) | dev |
| TFVHH | Kicktemp | [stage.kickern-hamburg.de](https://stage.kickern-hamburg.de) | dev |
| STFVH | DTFB | [stage.stfv.de](https://stage.stfv.de/) | sportsmanager2-stage |
| MTFV | DTFB | [stage.mtfv.de](https://stage.mtfv.de/) | ? |
| TFVSH | DTFB | [relaunch.tfvsh.de](https://relaunch.tfvsh.de) | ? |
[![buddy pipeline](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/204/badge.svg?token=de39e4e4c47351d592b59a5d1e26a41cf5196861f67d4499bbab990600468001 "buddy pipeline")](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/204) [Preview: stage.kickern-hamburg.de](https://stage.kickern-hamburg.de)
### PROD environment ## PROD environments
[![buddy pipeline](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/218/badge.svg?token=de39e4e4c47351d592b59a5d1e26a41cf5196861f67d4499bbab990600468001 "buddy pipeline")](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/218) [Preview: dtfb.de](https://dtfb.de)
[![buddy pipeline](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/219/badge.svg?token=de39e4e4c47351d592b59a5d1e26a41cf5196861f67d4499bbab990600468001 "buddy pipeline")](https://buddy.kicktemp.com/kicktemp/com-sportsmanager/pipelines/pipeline/219) [Preview: kickern-hamburg.de](https://kickern-hamburg.de) | LV | HOSTER | DOMAIN | BRANCH |
| ------ | -------- | ------------------------------------------------ | ------------------- |
| DTFB | Kicktemp | [dtfb.de](https://dtfb.de) | production |
| TFVHH | Kicktemp | [kickern-hamburg.de](https://kickern-hamburg.de) | production |
| MTFV | DTFB | [mtfv.de](https://mtfv.de/) | sportsmanager2-prod |
| TFVSH | DTFB | [tfvsh.de](https://tfvsh.de/) | sportsmanager2-prod |
| STFVH | DTFB | [stfv.de](https://stfv.de/) | sportsmanager2-prod |
## Test setup
### Installation
To start joomla and the database, run
```shell
docker-compose up -d
```
### Release creation
To create a release execute
```shell
npm run release
```
### Deployment
Deployment can only be done manually right now (sad)
To do this go to
[Testserver Extension Installer Site](http://localhost:8080/administrator/index.php?option=com_installer&view=install)
and upload the zip file found in `./package/packages`
### Development Tools
If you are using Intellij, there is a plugin named Joomla! which helps with resolving
joomla specific database prefixes like #__
To set it up, insert into the configuration popup which follows after you enable the framework support:
Joomla install path: `./data/joomla_data`
JConfig: `./data/joomla_data/configuration.php`
> This works only with mounted volumes. However, mounted volumes will slow down the joomla instance significantly.
> The current setup does not use mounted volumes.
> An alternative would be to download joomla and use that installation
### Debugging (with Docker/Intellij)
1. Start Docker Container (see above)
2. Create a terminal for that container
```shell
docker exec -it <container_name> bash
```
3. install xdebug within the container since joomla does not come with xdebug preinstalled
```shell
pecl install xdebug
```
4. restart the container
5. In Intellij Go to [File | Settings | Languages & Frameworks | PHP | Servers](jetbrains://idea/settings?name=Languages+%26+Frameworks--PHP--Servers) and setup your server
| | |
|----------|-----------|
| name | anything |
| host | localhost |
| port | 8080 |
| debugger | xdebug |
use the path mapping and map the repo structure to the container content
| File/Directory | path on server |
|------------------------------------------------------------------|----------------------------------------|
| \<path>/com_sportsmanager/src/structure/administrator/components | /var/www/html/administrator/components |
| \<path>/com_sportsmanager/src/structure/components | /var/www/html/components |
7. Click on "Start Listening for PHP Debug Connections" in the top row of intellij
8. (Not sure if optional) Install a browser extension by Jetbrains
https://chromewebstore.google.com/detail/xdebug-helper-by-jetbrain/aoelhdemabeimdhedkidlnbkfhnhgnhm
### How to release
Hint: for technical details regarding the release process have a look into .github/...
To create a release these steps need to be followed
1. make sure all needed code changes are merged from dev -> stage -> prod, since releases may only be build on prod branch
2. give pull requests meaningful names and label them enhancement/bug/chore since labels and names are used for release note generation
Hint: if a specific pull request should be ignored, add the label changelog-ignore
3. tag a commit (recommended is the latest merge on prod). The pipeline is listening for any tag fitting `v[0-9]+.[0-9]+.[0-9]+`
```shell
git tag -a v1.2.3 1a2b3c4 -m "Release version 1.2.3"
```
4. push the tag
```shell
git push origin --tags
```
5. the tag push will trigger the pipeline, and it will create the release and store in GitHub
A release can be created again anytime by deleting the release from GitHub, deleting the tag (from GitHub and additionally from git)
and repeating step 3 and 4
Further: merges from dev to stage and from stage to prod can only be done by creating pull requests. These pull requests will be automatically labeled as changelog-ignore
+2
View File
@@ -0,0 +1,2 @@
This is no official release!
The Release and the release notes will be generated by github actions
+37 -24
View File
@@ -1,30 +1,43 @@
version: '2'
services: services:
mariadb: joomla:
image: docker.io/bitnami/mariadb:10.3 image: joomla:5.2.4
restart: always
ports:
- '8080:80'
environment:
JOOMLA_DB_HOST: db
JOOMLA_DB_USER: joomla
JOOMLA_DB_PASSWORD: examplepass
JOOMLA_DB_NAME: joomla_db
JOOMLA_SITE_NAME: Sportsmanager Testserver
JOOMLA_ADMIN_USER: Joomla Hero
JOOMLA_ADMIN_USERNAME: joomla
JOOMLA_ADMIN_PASSWORD: joomla@secured
JOOMLA_ADMIN_EMAIL: joomla@example.com
volumes:
- joomla_data:/var/www/html
- './docker/php.ini:/usr/local/etc/php/php.ini'
networks:
- joomla_network
db:
image: mysql:8.0
restart: always
ports: ports:
- '3306:3306' - '3306:3306'
environment: environment:
# ALLOW_EMPTY_PASSWORD is recommended only for development. MYSQL_DATABASE: joomla_db
- ALLOW_EMPTY_PASSWORD=yes MYSQL_USER: joomla
- MARIADB_USER=bn_joomla MYSQL_PASSWORD: examplepass
- MARIADB_DATABASE=bitnami_joomla MYSQL_RANDOM_ROOT_PASSWORD: '1'
TZ: Europe/Berlin
volumes: volumes:
- './data/mariadb_data:/bitnami/mariadb' - joomla_database:/var/lib/mysql
joomla: networks:
image: docker.io/bitnami/joomla:3 - joomla_network
ports:
- '80:8080' networks:
- '443:8443' joomla_network:
environment:
- JOOMLA_DATABASE_HOST=mariadb
- JOOMLA_DATABASE_PORT_NUMBER=3306
- JOOMLA_DATABASE_USER=bn_joomla
- JOOMLA_DATABASE_NAME=bitnami_joomla
# ALLOW_EMPTY_PASSWORD is recommended only for development.
- ALLOW_EMPTY_PASSWORD=yes
volumes: volumes:
- './data/joomla_data:/bitnami/joomla' joomla_data:
- './docker/php.ini:/opt/bitnami/php/etc/php.ini:ro' joomla_database:
depends_on:
- mariadb
+77 -130
View File
@@ -9,15 +9,15 @@
; PHP attempts to find and load this configuration from a number of locations. ; PHP attempts to find and load this configuration from a number of locations.
; The following is a summary of its search order: ; The following is a summary of its search order:
; 1. SAPI module specific location. ; 1. SAPI module specific location.
; 2. The PHPRC environment variable. (As of PHP 5.2.0) ; 2. The PHPRC environment variable.
; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) ; 3. A number of predefined registry keys on Windows
; 4. Current working directory (except CLI) ; 4. Current working directory (except CLI)
; 5. The web server's directory (for SAPI modules), or directory of PHP ; 5. The web server's directory (for SAPI modules), or directory of PHP
; (otherwise in Windows) ; (otherwise in Windows)
; 6. The directory from the --with-config-file-path compile time option, or the ; 6. The directory from the --with-config-file-path compile time option, or the
; Windows directory (usually C:\windows) ; Windows directory (usually C:\windows)
; See the PHP docs for more specific information. ; See the PHP docs for more specific information.
; http://php.net/configuration.file ; https://php.net/configuration.file
; The syntax of the file is extremely simple. Whitespace and lines ; The syntax of the file is extremely simple. Whitespace and lines
; beginning with a semicolon are silently ignored (as you probably guessed). ; beginning with a semicolon are silently ignored (as you probably guessed).
@@ -31,7 +31,7 @@
; special sections cannot be overridden by user-defined INI files or ; special sections cannot be overridden by user-defined INI files or
; at runtime. Currently, [PATH=] and [HOST=] sections only work under ; at runtime. Currently, [PATH=] and [HOST=] sections only work under
; CGI/FastCGI. ; CGI/FastCGI.
; http://php.net/ini.sections ; https://php.net/ini.sections
; Directives are specified using the following syntax: ; Directives are specified using the following syntax:
; directive = value ; directive = value
@@ -75,7 +75,7 @@
; php.ini-production contains settings which hold security, performance and ; php.ini-production contains settings which hold security, performance and
; best practices at its core. But please be aware, these settings may break ; best practices at its core. But please be aware, these settings may break
; compatibility with older or less security conscience applications. We ; compatibility with older or less security-conscious applications. We
; recommending using the production ini in production and testing environments. ; recommending using the production ini in production and testing environments.
; php.ini-development is very similar to its production variant, except it is ; php.ini-development is very similar to its production variant, except it is
@@ -756,7 +756,7 @@ user_dir =
; Directory in which the loadable extensions (modules) reside. ; Directory in which the loadable extensions (modules) reside.
; http://php.net/extension-dir ; http://php.net/extension-dir
extension_dir = /opt/bitnami/php/lib/php/extensions ;extension_dir = /usr/local/lib/php/extensions
; On windows: ; On windows:
;extension_dir = "ext" ;extension_dir = "ext"
@@ -839,7 +839,7 @@ file_uploads = On
; Temporary directory for HTTP uploaded files (will use system default if not ; Temporary directory for HTTP uploaded files (will use system default if not
; specified). ; specified).
; http://php.net/upload-tmp-dir ; http://php.net/upload-tmp-dir
upload_tmp_dir = /opt/bitnami/php/tmp upload_tmp_dir = /tmp
; Maximum allowed size for uploaded files. ; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize ; http://php.net/upload-max-filesize
@@ -1318,7 +1318,7 @@ session.save_handler = files
; ;
; The path can be defined as: ; The path can be defined as:
; ;
session.save_path = /opt/bitnami/php/var/run/session session.save_path = /tmp/session
; ;
; where N is an integer. Instead of storing all the session files in ; where N is an integer. Instead of storing all the session files in
; /path, what this will do is use subdirectories N-levels deep, and ; /path, what this will do is use subdirectories N-levels deep, and
@@ -1334,12 +1334,10 @@ session.save_path = /opt/bitnami/php/var/run/session
; The file storage module creates files using mode 600 by default. ; The file storage module creates files using mode 600 by default.
; You can change that by using ; You can change that by using
; ;
session.save_path = /opt/bitnami/php/var/run/session
; ;
; where MODE is the octal representation of the mode. Note that this ; where MODE is the octal representation of the mode. Note that this
; does not overwrite the process's umask. ; does not overwrite the process's umask.
; http://php.net/session.save-path ; http://php.net/session.save-path
session.save_path = /opt/bitnami/php/var/run/session
; Whether to use strict session mode. ; Whether to use strict session mode.
; Strict session mode does not accept an uninitialized session ID, and ; Strict session mode does not accept an uninitialized session ID, and
@@ -1539,18 +1537,18 @@ session.sid_bits_per_character = 5
; Default Value: "1%" ; Default Value: "1%"
; Development Value: "1%" ; Development Value: "1%"
; Production Value: "1%" ; Production Value: "1%"
; http://php.net/session.upload-progress.freq ; https://php.net/session.upload-progress.freq
;session.upload_progress.freq = "1%" ;session.upload_progress.freq = "1%"
; The minimum delay between updates, in seconds ; The minimum delay between updates, in seconds
; Default Value: 1 ; Default Value: 1
; Development Value: 1 ; Development Value: 1
; Production Value: 1 ; Production Value: 1
; http://php.net/session.upload-progress.min-freq ; https://php.net/session.upload-progress.min-freq
;session.upload_progress.min_freq = "1" ;session.upload_progress.min_freq = "1"
; Only write session data when session data is changed. Enabled by default. ; Only write session data when session data is changed. Enabled by default.
; http://php.net/session.lazy-write ; https://php.net/session.lazy-write
;session.lazy_write = On ;session.lazy_write = On
[Assertion] [Assertion]
@@ -1558,67 +1556,47 @@ session.sid_bits_per_character = 5
; -1: Do not compile at all ; -1: Do not compile at all
; 0: Jump over assertion at run-time ; 0: Jump over assertion at run-time
; 1: Execute assertions ; 1: Execute assertions
; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) ; Changing from or to a negative value is only possible in php.ini!
; (For turning assertions on and off at run-time, toggle zend.assertions between the values 1 and 0)
; Default Value: 1 ; Default Value: 1
; Development Value: 1 ; Development Value: 1
; Production Value: -1 ; Production Value: -1
; http://php.net/zend.assertions ; https://php.net/zend.assertions
zend.assertions = -1 zend.assertions = -1
; Assert(expr); active by default.
; http://php.net/assert.active
;assert.active = On
; Throw an AssertionError on failed assertions
; http://php.net/assert.exception
;assert.exception = On
; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active)
; http://php.net/assert.warning
;assert.warning = On
; Don't bail out by default.
; http://php.net/assert.bail
;assert.bail = Off
; User-function to be called if an assertion fails.
; http://php.net/assert.callback
;assert.callback = 0
; Eval the expression with current error_reporting(). Set to true if you want
; error_reporting(0) around the eval().
; http://php.net/assert.quiet-eval
;assert.quiet_eval = 0
[COM] [COM]
; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs ; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs
; http://php.net/com.typelib-file ; https://php.net/com.typelib-file
;com.typelib_file = ;com.typelib_file =
; allow Distributed-COM calls ; allow Distributed-COM calls
; http://php.net/com.allow-dcom ; https://php.net/com.allow-dcom
;com.allow_dcom = true ;com.allow_dcom = true
; autoregister constants of a component's typlib on com_load() ; autoregister constants of a component's typelib on com_load()
; http://php.net/com.autoregister-typelib ; https://php.net/com.autoregister-typelib
;com.autoregister_typelib = true ;com.autoregister_typelib = true
; register constants casesensitive ; register constants casesensitive
; http://php.net/com.autoregister-casesensitive ; https://php.net/com.autoregister-casesensitive
;com.autoregister_casesensitive = false ;com.autoregister_casesensitive = false
; show warnings on duplicate constant registrations ; show warnings on duplicate constant registrations
; http://php.net/com.autoregister-verbose ; https://php.net/com.autoregister-verbose
;com.autoregister_verbose = true ;com.autoregister_verbose = true
; The default character set code-page to use when passing strings to and from COM objects. ; The default character set code-page to use when passing strings to and from COM objects.
; Default: system ANSI code page ; Default: system ANSI code page
;com.code_page= ;com.code_page=
; The version of the .NET framework to use. The value of the setting are the first three parts
; of the framework's version number, separated by dots, and prefixed with "v", e.g. "v4.0.30319".
;com.dotnet_version=
[mbstring] [mbstring]
; language for internal character representation. ; language for internal character representation.
; This affects mb_send_mail() and mbstring.detect_order. ; This affects mb_send_mail() and mbstring.detect_order.
; http://php.net/mbstring.language ; https://php.net/mbstring.language
;mbstring.language = Japanese ;mbstring.language = Japanese
; Use of this INI entry is deprecated, use global internal_encoding instead. ; Use of this INI entry is deprecated, use global internal_encoding instead.
@@ -1633,7 +1611,7 @@ zend.assertions = -1
; mbstring.encoding_translation = On is needed to use this setting. ; mbstring.encoding_translation = On is needed to use this setting.
; If empty, default_charset or input_encoding or mbstring.input is used. ; If empty, default_charset or input_encoding or mbstring.input is used.
; The precedence is: default_charset < input_encoding < mbstring.http_input ; The precedence is: default_charset < input_encoding < mbstring.http_input
; http://php.net/mbstring.http-input ; https://php.net/mbstring.http-input
;mbstring.http_input = ;mbstring.http_input =
; Use of this INI entry is deprecated, use global output_encoding instead. ; Use of this INI entry is deprecated, use global output_encoding instead.
@@ -1643,7 +1621,7 @@ zend.assertions = -1
; The precedence is: default_charset < output_encoding < mbstring.http_output ; The precedence is: default_charset < output_encoding < mbstring.http_output
; To use an output encoding conversion, mbstring's output handler must be set ; To use an output encoding conversion, mbstring's output handler must be set
; otherwise output encoding conversion cannot be performed. ; otherwise output encoding conversion cannot be performed.
; http://php.net/mbstring.http-output ; https://php.net/mbstring.http-output
;mbstring.http_output = ;mbstring.http_output =
; enable automatic encoding translation according to ; enable automatic encoding translation according to
@@ -1651,54 +1629,40 @@ zend.assertions = -1
; converted to internal encoding by setting this to On. ; converted to internal encoding by setting this to On.
; Note: Do _not_ use automatic encoding translation for ; Note: Do _not_ use automatic encoding translation for
; portable libs/applications. ; portable libs/applications.
; http://php.net/mbstring.encoding-translation ; https://php.net/mbstring.encoding-translation
;mbstring.encoding_translation = Off ;mbstring.encoding_translation = Off
; automatic encoding detection order. ; automatic encoding detection order.
; "auto" detect order is changed according to mbstring.language ; "auto" detect order is changed according to mbstring.language
; http://php.net/mbstring.detect-order ; https://php.net/mbstring.detect-order
;mbstring.detect_order = auto ;mbstring.detect_order = auto
; substitute_character used when character cannot be converted ; substitute_character used when character cannot be converted
; one from another ; one from another
; http://php.net/mbstring.substitute-character ; https://php.net/mbstring.substitute-character
;mbstring.substitute_character = none ;mbstring.substitute_character = none
; overload(replace) single byte functions by mbstring functions. ; Enable strict encoding detection.
; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), ;mbstring.strict_detection = Off
; etc. Possible values are 0,1,2,4 or combination of them.
; For example, 7 for overload everything.
; 0: No overload
; 1: Overload mail() function
; 2: Overload str*() functions
; 4: Overload ereg*() functions
; http://php.net/mbstring.func-overload
;mbstring.func_overload = 0
; enable strict encoding detection.
; Default: Off
;mbstring.strict_detection = On
; This directive specifies the regex pattern of content types for which mb_output_handler() ; This directive specifies the regex pattern of content types for which mb_output_handler()
; is activated. ; is activated.
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) ; Default: mbstring.http_output_conv_mimetypes=^(text/|application/xhtml\+xml)
;mbstring.http_output_conv_mimetype= ;mbstring.http_output_conv_mimetypes=
; This directive specifies maximum stack depth for mbstring regular expressions. It is similar ; This directive specifies maximum stack depth for mbstring regular expressions. It is similar
; to the pcre.recursion_limit for PCRE. ; to the pcre.recursion_limit for PCRE.
; Default: 100000
;mbstring.regex_stack_limit=100000 ;mbstring.regex_stack_limit=100000
; This directive specifies maximum retry count for mbstring regular expressions. It is similar ; This directive specifies maximum retry count for mbstring regular expressions. It is similar
; to the pcre.backtrack_limit for PCRE. ; to the pcre.backtrack_limit for PCRE.
; Default: 1000000
;mbstring.regex_retry_limit=1000000 ;mbstring.regex_retry_limit=1000000
[gd] [gd]
; Tell the jpeg decode to ignore warnings and try to create ; Tell the jpeg decode to ignore warnings and try to create
; a gd image. The warning will then be displayed as notices ; a gd image. The warning will then be displayed as notices
; disabled by default ; disabled by default
; http://php.net/gd.jpeg-ignore-warning ; https://php.net/gd.jpeg-ignore-warning
;gd.jpeg_ignore_warning = 1 ;gd.jpeg_ignore_warning = 1
[exif] [exif]
@@ -1706,48 +1670,48 @@ zend.assertions = -1
; With mbstring support this will automatically be converted into the encoding ; With mbstring support this will automatically be converted into the encoding
; given by corresponding encode setting. When empty mbstring.internal_encoding ; given by corresponding encode setting. When empty mbstring.internal_encoding
; is used. For the decode settings you can distinguish between motorola and ; is used. For the decode settings you can distinguish between motorola and
; intel byte order. A decode setting cannot be empty. ; intel byte order. A decode setting must not be empty.
; http://php.net/exif.encode-unicode ; https://php.net/exif.encode-unicode
;exif.encode_unicode = ISO-8859-15 ;exif.encode_unicode = ISO-8859-15
; http://php.net/exif.decode-unicode-motorola ; https://php.net/exif.decode-unicode-motorola
;exif.decode_unicode_motorola = UCS-2BE ;exif.decode_unicode_motorola = UCS-2BE
; http://php.net/exif.decode-unicode-intel ; https://php.net/exif.decode-unicode-intel
;exif.decode_unicode_intel = UCS-2LE ;exif.decode_unicode_intel = UCS-2LE
; http://php.net/exif.encode-jis ; https://php.net/exif.encode-jis
;exif.encode_jis = ;exif.encode_jis =
; http://php.net/exif.decode-jis-motorola ; https://php.net/exif.decode-jis-motorola
;exif.decode_jis_motorola = JIS ;exif.decode_jis_motorola = JIS
; http://php.net/exif.decode-jis-intel ; https://php.net/exif.decode-jis-intel
;exif.decode_jis_intel = JIS ;exif.decode_jis_intel = JIS
[Tidy] [Tidy]
; The path to a default tidy configuration file to use when using tidy ; The path to a default tidy configuration file to use when using tidy
; http://php.net/tidy.default-config ; https://php.net/tidy.default-config
;tidy.default_config = /usr/local/lib/php/default.tcfg ;tidy.default_config = /usr/local/lib/php/default.tcfg
; Should tidy clean and repair output automatically? ; Should tidy clean and repair output automatically?
; WARNING: Do not use this option if you are generating non-html content ; WARNING: Do not use this option if you are generating non-html content
; such as dynamic images ; such as dynamic images
; http://php.net/tidy.clean-output ; https://php.net/tidy.clean-output
tidy.clean_output = Off tidy.clean_output = Off
[soap] [soap]
; Enables or disables WSDL caching feature. ; Enables or disables WSDL caching feature.
; http://php.net/soap.wsdl-cache-enabled ; https://php.net/soap.wsdl-cache-enabled
soap.wsdl_cache_enabled=1 soap.wsdl_cache_enabled=1
; Sets the directory name where SOAP extension will put cache files. ; Sets the directory name where SOAP extension will put cache files.
; http://php.net/soap.wsdl-cache-dir ; https://php.net/soap.wsdl-cache-dir
soap.wsdl_cache_dir="/tmp" soap.wsdl_cache_dir="/tmp"
; (time to live) Sets the number of second while cached file will be used ; (time to live) Sets the number of second while cached file will be used
; instead of original one. ; instead of original one.
; http://php.net/soap.wsdl-cache-ttl ; https://php.net/soap.wsdl-cache-ttl
soap.wsdl_cache_ttl=86400 soap.wsdl_cache_ttl=86400
; Sets the size of the cache limit. (Max. number of WSDL files to cache) ; Sets the size of the cache limit. (Max. number of WSDL files to cache)
@@ -1806,6 +1770,11 @@ opcache.revalidate_freq = 60
; size of the optimized code. ; size of the optimized code.
;opcache.save_comments=1 ;opcache.save_comments=1
; If enabled, compilation warnings (including notices and deprecations) will
; be recorded and replayed each time a file is included. Otherwise, compilation
; warnings will only be emitted when the file is first cached.
;opcache.record_warnings=0
; Allow file existence override (file_exists, etc.) performance feature. ; Allow file existence override (file_exists, etc.) performance feature.
;opcache.enable_file_override=0 ;opcache.enable_file_override=0
@@ -1827,10 +1796,6 @@ opcache.revalidate_freq = 60
; are cached. ; are cached.
;opcache.max_file_size=0 ;opcache.max_file_size=0
; Check the cache checksum each N requests.
; The default value of "0" means that the checks are disabled.
;opcache.consistency_checks=0
; How long to wait (in seconds) for a scheduled restart to begin if the cache ; How long to wait (in seconds) for a scheduled restart to begin if the cache
; is not being accessed. ; is not being accessed.
;opcache.force_restart_timeout=180 ;opcache.force_restart_timeout=180
@@ -1868,7 +1833,16 @@ opcache.revalidate_freq = 60
; Enables and sets the second level cache directory. ; Enables and sets the second level cache directory.
; It should improve performance when SHM memory is full, at server restart or ; It should improve performance when SHM memory is full, at server restart or
; SHM reset. The default "" disables file based caching. ; SHM reset. The default "" disables file based caching.
opcache.file_cache = /opt/bitnami/php/var/run/opcache_file opcache.file_cache = /tmp/opcache_file
; Enables or disables read-only mode for the second level cache directory.
; It should improve performance for read-only containers,
; when the cache is pre-warmed and packaged alongside the application.
; Best used with `opcache.validate_timestamps=0`, `opcache.enable_file_override=1`
; and `opcache.file_cache_consistency_checks=0`.
; Note: A cache generated with a different build of PHP, a different file path,
; or different settings (including which extensions are loaded), may be ignored.
;opcache.file_cache_read_only=0
; Enables or disables opcode caching in shared memory. ; Enables or disables opcode caching in shared memory.
;opcache.file_cache_only=0 ;opcache.file_cache_only=0
@@ -1882,8 +1856,13 @@ opcache.file_cache = /opt/bitnami/php/var/run/opcache_file
;opcache.file_cache_fallback=1 ;opcache.file_cache_fallback=1
; Enables or disables copying of PHP code (text segment) into HUGE PAGES. ; Enables or disables copying of PHP code (text segment) into HUGE PAGES.
; This should improve performance, but requires appropriate OS configuration. ; Under certain circumstances (if only a single global PHP process is
;opcache.huge_code_pages=1 ; started from which all others fork), this can increase performance
; by a tiny amount because TLB misses are reduced. On the other hand, this
; delays PHP startup, increases memory usage and degrades performance
; under memory pressure - use with care.
; Requires appropriate OS configuration.
;opcache.huge_code_pages=0
; Validate cached file permissions. ; Validate cached file permissions.
;opcache.validate_permission=0 ;opcache.validate_permission=0
@@ -1897,12 +1876,12 @@ opcache.file_cache = /opt/bitnami/php/var/run/opcache_file
; Specifies a PHP script that is going to be compiled and executed at server ; Specifies a PHP script that is going to be compiled and executed at server
; start-up. ; start-up.
; http://php.net/opcache.preload ; https://php.net/opcache.preload
;opcache.preload= ;opcache.preload=
; Preloading code as root is not allowed for security reasons. This directive ; Preloading code as root is not allowed for security reasons. This directive
; facilitates to let the preloading to be run as another user. ; facilitates to let the preloading to be run as another user.
; http://php.net/opcache.preload_user ; https://php.net/opcache.preload_user
;opcache.preload_user= ;opcache.preload_user=
; Prevents caching files that are less than this number of seconds old. It ; Prevents caching files that are less than this number of seconds old. It
@@ -1945,44 +1924,12 @@ opcache.file_cache = /opt/bitnami/php/var/run/opcache_file
; List of headers files to preload, wildcard patterns allowed. ; List of headers files to preload, wildcard patterns allowed.
;ffi.preload= ;ffi.preload=
zend_extension = opcache
opcache.fast_shutdown = 1
;extension = pdo_dblib
;extension = apcu
;extension = mcrypt
;extension = imagick
;extension = memcached
;extension = maxminddb
;extension = mongodb
;[XDebug] zend_extension=xdebug.so
zend_extension = xdebug
xdebug.mode=debug xdebug.mode=debug
;xdebug.client_host = 127.0.0.1
;xdebug.client_port = 9000
;xdebug.output_dir = /tmp
;xdebug.remote_handler = dbgp
;xdebug.remote_port=9000
;xdebug.remote_host=10.254.254.254
;xdebug.remote_autostart=1
;xdebug.remote_enable=1
;xdebug.default_enable=0
;xdebug.remote_host=host.docker.internal
;xdebug.remote_port=9000
;xdebug.remote_connect_back=0
;xdebug.profiler_enable=0
;xdebug.remote_log="/tmp/xdebug.log"
xdebug.mode=debug
xdebug.client_port=9000
xdebug.client_host=host.docker.internal
xdebug.remote_handler=dbgp
;xdebug.remote_host=host.docker.internal
;xdebug.remote_port=9000
xdebug.start_with_request=yes xdebug.start_with_request=yes
xdebug.discover_client_host=0 xdebug.client_host=host.docker.internal
xdebug.idekey=PHPSTORM xdebug.client_port=9003
xdebug.show_error_trace = 1 xdebug.log=/tmp/xdebug.log
xdebug.max_nesting_level=250 xdebug.discover_client_host=false
xdebug.var_display_max_depth=10 xdebug.log_level=7
;xdebug.log=/tmp/xdebug.log
+33 -17
View File
@@ -43,7 +43,7 @@ export const config = {
watch: ['src/structure/**/*.{php,html,xml,ini,less,json,js,css}'], watch: ['src/structure/**/*.{php,html,xml,ini,less,json,js,css}'],
}, },
copyrelease: { copyrelease: {
src: ['src/structure/**/**', 'src/structure/**/.*', '!src/structure/**/*.{php,html,xml,ini,less,json,js,css}', '!src/structure/**/.*.{php,html,xml,ini,less,json,js,css}'], src: ['RELEASE_NOTES.md','src/structure/**/**', 'src/structure/**/.*', '!src/structure/**/*.{php,html,xml,ini,less,json,js,css}', '!src/structure/**/.*.{php,html,xml,ini,less,json,js,css}'],
replacesrc: ['src/structure/**/**.{php,html,xml,ini,less,json,js,css}', 'src/structure/**/.*.{php,html,xml,ini,less,json,js,css}'], replacesrc: ['src/structure/**/**.{php,html,xml,ini,less,json,js,css}', 'src/structure/**/.*.{php,html,xml,ini,less,json,js,css}'],
dest: 'releasefiles/' dest: 'releasefiles/'
}, },
@@ -56,28 +56,44 @@ export const config = {
}, },
packagefiles: [ packagefiles: [
{ {
src: './releasefiles/components/com_kickboilerplate/**/**', src: './releasefiles/components/com_sportsmanager/**/**',
dest: 'sourcefiles/com_kickboilerplate/site' dest: 'sourcefiles/com_sportsmanager/site'
}, },
{ {
src: './releasefiles/administrator/components/com_kickboilerplate/**/**', src: './releasefiles/language/**/**',
dest: 'sourcefiles/com_kickboilerplate/admin' dest: 'sourcefiles/com_sportsmanager/site/language'
}, },
{ {
src: './releasefiles/administrator/components/com_kickboilerplate/kickboilerplate.xml', src: './releasefiles/administrator/components/com_sportsmanager/**/**',
dest: 'sourcefiles/com_kickboilerplate/' dest: 'sourcefiles/com_sportsmanager/admin'
}, },
{ {
src: './releasefiles/administrator/components/com_kickboilerplate/script.php', src: './releasefiles/administrator/language/**/**',
dest: 'sourcefiles/com_kickboilerplate/' dest: 'sourcefiles/com_sportsmanager/admin/language'
}, },
{ {
src: './releasefiles/media/com_kickboilerplate/**/**', src: './releasefiles/administrator/services/**/**',
dest: 'sourcefiles/com_kickboilerplate/media' dest: 'sourcefiles/com_sportsmanager/admin/services'
}, },
{ {
src: './releasefiles/plugins/system/kickboilerplate/**/**', src: './releasefiles/sportsmanager.xml',
dest: 'sourcefiles/plg_system_kickboilerplate' dest: 'sourcefiles/com_sportsmanager/'
},
{
src: './releasefiles/script.php',
dest: 'sourcefiles/com_sportsmanager/'
},
{
src: './releasefiles/media/com_sportsmanager/**/**',
dest: 'sourcefiles/com_sportsmanager/media'
},
{
src: './releasefiles/plugins/system/kickyootheme/**/**',
dest: 'sourcefiles/plg_system_kickyootheme'
},
{
src: './releasefiles/RELEASE_NOTES.md',
dest: 'sourcefiles/com_sportsmanager/admin/'
} }
], ],
package: [ package: [
@@ -100,7 +116,7 @@ export const config = {
archiver: [ archiver: [
{ {
destination : 'package/packages/', destination : 'package/packages/',
name: 'plg_system_kickboilerplate', name: 'plg_system_kickyootheme',
suffixversion: false, suffixversion: false,
types: [ types: [
{ {
@@ -112,14 +128,14 @@ export const config = {
} }
], ],
folders: [ folders: [
'sourcefiles/plg_system_kickboilerplate' 'sourcefiles/plg_system_kickyootheme'
], ],
files: [ files: [
] ]
}, },
{ {
destination : 'package/packages/', destination : 'package/packages/',
name: 'com_kickboilerplate', name: 'com_sportsmanager',
suffixversion: false, suffixversion: false,
types: [ types: [
{ {
@@ -131,7 +147,7 @@ export const config = {
} }
], ],
folders: [ folders: [
'sourcefiles/com_kickboilerplate' 'sourcefiles/com_sportsmanager'
], ],
files: [ files: [
] ]
+3555 -1917
View File
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -1,7 +1,7 @@
{ {
"name": "sportsmanager", "name": "sportsmanager",
"description": "", "description": "",
"version": "0.0.1", "version": "2.0.0",
"scripts": { "scripts": {
"boilerplate": "cross-env NODE_ENV=development gulp boilerplate", "boilerplate": "cross-env NODE_ENV=development gulp boilerplate",
"build": "cross-env NODE_ENV=production gulp build", "build": "cross-env NODE_ENV=production gulp build",
@@ -16,7 +16,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/nielsnuebel/com_sportsmanager.git" "url": "https://github.com/Deutscher-Tischfussballbund/com_sportsmanager.git"
}, },
"keywords": [], "keywords": [],
"author": { "author": {
@@ -122,7 +122,6 @@
"browser-sync": "^2.26.12", "browser-sync": "^2.26.12",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"cross-env": "^7.0.2", "cross-env": "^7.0.2",
"fs": "0.0.1-security",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-changed": "^4.0.2", "gulp-changed": "^4.0.2",
"gulp-clean": "^0.4.0", "gulp-clean": "^0.4.0",
@@ -1,23 +0,0 @@
<?php
// no direct access
defined('_JEXEC') or die('Restricted access');
// Require the base controller
require_once (JPATH_COMPONENT.DS.'controller.php');
// Require specific controller if requested
//if($controller = JRequest::getVar('controller')) {
// require_once (JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php');
//}
// Create the controller
//$classname = 'AutosController'.$controller;
//$controller = new $classname( );
// Perform the Request task
//$controller->execute( JRequest::getVar('task'));
// Redirect if set by the controller
//$controller->redirect();
?>
@@ -1,31 +0,0 @@
<?php
/*
* Sports Manager (C) 2006-2020, Sven Nickel
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla controller library
jimport('joomla.application.component.controller');
/**
* General Controller of SportsManager component
*/
class SportsManagerController extends JControllerLegacy
{
/**
* display task
*
* @return void
*/
function display($cachable = false, $urlparams = false)
{
// set default view if not set
$input = JFactory::getApplication()->input;
$input->set('view', $input->getCmd('view', 'SportsManager'));
// call parent behavior
parent::display($cachable);
}
}
@@ -0,0 +1,61 @@
<?php
/**
* @package Joomla.Administrator
* @subpackage com_inlinecontact
*
* @copyright (C) Alexander Niklaus. All rights reserved.
* @license GNU General Public License version 2 or later
* @link https://an-software.net
*/
defined('_JEXEC') or die;
use Dtfb\Component\com_sportsmanager\Administrator\Extension\SportsmanagerComponent;
use Joomla\CMS\Dispatcher\ComponentDispatcherFactoryInterface;
use Joomla\CMS\Extension\ComponentInterface;
use Joomla\CMS\Extension\Service\Provider\ComponentDispatcherFactory;
use Joomla\CMS\Extension\Service\Provider\MVCFactory;
use Joomla\CMS\Log\Log;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
/**
* The contact service provider.
*
* @since 1.0.0
*/
return new class implements ServiceProviderInterface {
/**
* Registers the service provider with a DI container.
*
* @param Container $container The DI container.
*
* @return void
*
* @since 1.0.0
*/
public function register(Container $container): void
{
Log::addLogger(
[
'text_file' => 'com_sportsmanager.php',
],
Log::ALL,
['com_sportsmanager']
);
$container->registerServiceProvider(new MVCFactory('\\Dtfb\\Component\\com_sportsmanager'));
$container->registerServiceProvider(new ComponentDispatcherFactory('\\Dtfb\\Component\\com_sportsmanager'));
$container->set(
ComponentInterface::class,
function (Container $container) {
$component = new SportsmanagerComponent($container->get(ComponentDispatcherFactoryInterface::class));
$component->setMVCFactory($container->get(MVCFactoryInterface::class));
return $component;
}
);
}
};
@@ -1,19 +0,0 @@
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import joomla controller library
jimport('joomla.application.component.controller');
// Get an instance of the controller prefixed by HelloWorld
$controller = JControllerLegacy::getInstance('SportsManager');
// Get the task
$jinput = JFactory::getApplication()->input;
$task = $jinput->get('task', "", 'STR' );
// Perform the Request task
$controller->execute($task);
// Redirect if set by the controller
$controller->redirect();
@@ -0,0 +1,19 @@
<?php
namespace Dtfb\Component\com_sportsmanager\Administrator\Controller;
/*
* Sports Manager (C) 2006-2020, Sven Nickel
*/
// No direct access to this file
use Joomla\CMS\MVC\Controller\BaseController;
defined('_JEXEC') or die('Restricted access');
/**
* General Controller of SportsManager component
* @since 1.0.0
*/
class DisplayController extends BaseController
{
protected $default_view = 'sportsmanager';
}
@@ -0,0 +1,14 @@
<?php
namespace Dtfb\Component\com_sportsmanager\Administrator\Extension;
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Extension\MVCComponent;
use function defined;
/**
* Component class for com_sportsmanager
*
* @since 2.0.0
*/
class SportsmanagerComponent extends MVCComponent {}
@@ -0,0 +1,40 @@
<?php
namespace Dtfb\Component\com_sportsmanager\Administrator\View\Sportsmanager;
/*
* Sports Manager (C) 2006-2020, Sven Nickel
*/
// No direct access to this file
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
use Joomla\CMS\Toolbar\ToolbarHelper;
defined('_JEXEC') or die('Restricted access');
/**
* SportsManager View
* @since 1.0.0
*/
class HtmlView extends BaseHtmlView
{
function display($tpl = null): void
{
ToolbarHelper::title(Text::_('COM_SPORTSMANAGER'));
?>
<h3><?php echo Text::_('COM_SPORTSMANAGER'); ?> &#8211; Created by Sven Nickel | Maintained by DTFB</h3>
<?php
$notesPath = JPATH_COMPONENT_ADMINISTRATOR . '/RELEASE_NOTES.md';
if (file_exists($notesPath)) {
$notes = file_get_contents($notesPath);
echo '<div style="padding:1em;"><h3>Release Notes</h3><pre>' .
htmlspecialchars($notes) . '</pre></div>';
}
// Display the template
parent::display($tpl);
}
}
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
@@ -1 +0,0 @@
<html><body bgcolor="#FFFFFF"></body></html>
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
@@ -1 +0,0 @@
<html><body bgcolor="#FFFFFF"></body></html>
@@ -1,49 +0,0 @@
<?php
/*
* Sports Manager (C) 2006-2020, Sven Nickel
*/
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla view library
jimport('joomla.application.component.view');
/**
* SportsManager View
*/
class SportsManagerViewSportsManager extends JViewLegacy
{
/**
* SportsManager view display method
* @return void
*/
function display($tpl = null)
{
JToolbarHelper::title(JText::_('COM_SPORTSMANAGER'));
?>
<h2><?php echo JText::_('COM_SPORTSMANAGER'); ?> Copyright &copy; 2006 &#8211; 2014 Sven Nickel</h2>
<?php
/*
// Get data from the model
$items = $this->get('Items');
$pagination = $this->get('Pagination');
// Check for errors.
if (count($errors = $this->get('Errors')))
{
JError::raiseError(500, implode('<br />', $errors));
return false;
}
// Assign data to the view
$this->items = $items;
$this->pagination = $pagination;
*/
// Display the template
parent::display($tpl);
}
}
@@ -21,12 +21,17 @@ COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TEAMS_JOINT="Mannschaften in gem
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CLUBS="Vereine" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CLUBS="Vereine"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_VENUES="Spielorte" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_VENUES="Spielorte"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_APPOINTMENTS="Termine" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_APPOINTMENTS="Termine"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_MATCH_RESCHEDULING="Spielverlegungen"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_ASSOCIATION_BODIES="Verbandsorgane"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_HALL_OF_FAME="Hall Of Fame"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE="Titel" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE="Titel"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE_DESC="Titel, der im Fenster oben angezeigt wird" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE_DESC="Titel, der im Fenster oben angezeigt wird"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION="Beschreibung" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION="Beschreibung"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION_DESC="Beschreibung, die unterhalb des Titels angezeigt wird (WICHTIG: Werden HTML-Tags verwendet, müssen auch Umlaute in HTML-Code angeben werden)" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION_DESC="Beschreibung, die unterhalb des Titels angezeigt wird (WICHTIG: Werden HTML-Tags verwendet, müssen auch Umlaute in HTML-Code angeben werden)"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES="Kategorien" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES="Kategorien"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES_DESC="Eine optionale Auswahl an durch Kommata getrennte Kategorienummern" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES_DESC="Eine optionale Auswahl von Kategorienummern durch Kommata oder Spiegelstrich getrennt"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_EXTRA_PARAMS="Zusätzliche Parameter"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_EXTRA_PARAMS_DESC="Optionale zusätzliche Parameter für den Link in der Form Name1=Wert1&Name2=Wert2, die bei Aufruf dieses Menüpunkts wie GET-Parameter zur Verfügung stehen"
COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_TITLE="Layout: Elo-Rangliste" COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_TITLE="Layout: Elo-Rangliste"
COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_DESC="Auflistung der Spieler sortiert nach Elo-Wertung" COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_DESC="Auflistung der Spieler sortiert nach Elo-Wertung"
COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_OPTION_ELO_RANKING="Elo-Rangliste" COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_OPTION_ELO_RANKING="Elo-Rangliste"
@@ -21,12 +21,17 @@ COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TEAMS_JOINT="Teams in joint list
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CLUBS="Clubs" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CLUBS="Clubs"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_VENUES="Venues" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_VENUES="Venues"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_APPOINTMENTS="Appointments" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_APPOINTMENTS="Appointments"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_MATCH_RESCHEDULING="Match reschedulings"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_ASSOCIATION_BODIES="Association bodies"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_HALL_OF_FAME="Hall of fame"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE="Title" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE="Title"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE_DESC="Title which will be shows on top" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_TITLE_DESC="Title which will be shows on top"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION="Description" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION="Description"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION_DESC="Description that will be shows below the titel (IMPORTANT: if html tags are used, special characters must be maskeraded)" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_DESCRIPTION_DESC="Description that will be shows below the titel (IMPORTANT: if html tags are used, special characters must be maskeraded)"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES="Categories" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES="Categories"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES_DESC="An optional selection of category numbers seperated by commas" COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES_DESC="An optional selection of category numbers seperated by commas or bullet point"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_EXTRA_PARAMS="Additional parameters"
COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_EXTRA_PARAMS_DESC="Optional additional parameters for the link in the form name1=value1&name2=value2, made available as GET parameters whenever this menu item is called"
COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_TITLE="Layout: elo ranking" COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_TITLE="Layout: elo ranking"
COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_DESC="Listing of players sorted by elo rating" COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_DESC="Listing of players sorted by elo rating"
COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_OPTION_ELO_RANKING="Elo ranking" COM_SPORTSMANAGER_LAYOUT_ELO_RANKING_OPTION_ELO_RANKING="Elo ranking"
File diff suppressed because it is too large Load Diff
@@ -2,35 +2,49 @@
/* /*
* Sports Manager API Extension * Sports Manager API Extension
*/ */
defined('_JEXEC') or die();
$secret = JFactory::$config['secret']; use JetBrains\PhpStorm\NoReturn;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Factory;
use Joomla\CMS\User\UserFactoryInterface;
use Joomla\Registry\Registry;
function abortWithError($error) { defined("_JEXEC") or die();
require_once JPATH_SITE . '/components/com_sportsmanager/database/init.php';
Factory::getContainer()->set(Registry::class, function () {
return new Registry();
});
$secret = Factory::getContainer()->get(Registry::class)->get("secret");
#[NoReturn] function abortWithError($error): void
{
if (isJson()) { if (isJson()) {
header('content-type: application/json'); header("content-type: application/json");
die(json_encode(['error' => $error])); die(json_encode(["error" => $error]));
} else { } else {
die($error); die($error);
} }
} }
function isJson() { function isJson(): bool
$jinput = JFactory::getApplication()->input; {
$jInput = Factory::getContainer()->get(SiteApplication::class)->input;
return $jinput->get('format') === 'json'; return $jInput->get('format') === 'json';
} }
function notifyChange($data) { function notifyChange($data): void
{
try { try {
$db = &getDatabase(); $db = getDatabase();
$query = "SELECT wert from #__sportsmanager_einstellungen WHERE name='api_push_key'"; $query = "SELECT wert from #__sportsmanager_einstellungen WHERE name='api_push_key'";
$db->setQuery($query); $push_key = loadResult($db, $query);
$push_key = $db->loadResult();
$push_server = !empty($push_key) && isset(_payload($push_key)->aud) ? _payload($push_key)->aud : ''; $push_server = !empty($push_key) && isset(_payload($push_key)->aud) ? _payload($push_key)->aud : '';
if ($push_server != '' && $push_key != '') { if ($push_server != '' && $push_key != '') {
$url = $push_server . (substr($push_server, -1) == '/' ? '' : '/') . 'v1/notifications/send'; $url = $push_server . (str_ends_with($push_server, '/') ? '' : '/') . 'v1/notifications/send';
$key = 'key=' . $push_key; $key = 'key=' . $push_key;
$ch = curl_init($url); $ch = curl_init($url);
@@ -46,7 +60,7 @@ function notifyChange($data) {
CURLOPT_POSTFIELDS => json_encode($data), CURLOPT_POSTFIELDS => json_encode($data),
)); ));
$resp = curl_exec($ch); $resp = curl_exec($ch);
if ($resp == FALSE) { if (!$resp) {
error_log("failed to send notification"); error_log("failed to send notification");
} }
} }
@@ -55,7 +69,8 @@ function notifyChange($data) {
} }
} }
function begegnungChanged($begegnung, $begegnung_vorher, $modus, $heim_team, $gast_team, $spiele) { function begegnungChanged($begegnung, $begegnung_vorher, $modus, $heim_team, $gast_team, $spiele): void
{
notifyChange(['payload' => [ notifyChange(['payload' => [
'begegnung' => $begegnung, 'begegnung' => $begegnung,
'begegnung_vorher' => $begegnung_vorher, 'begegnung_vorher' => $begegnung_vorher,
@@ -66,7 +81,8 @@ function begegnungChanged($begegnung, $begegnung_vorher, $modus, $heim_team, $ga
], 'type' => 'FIXTURE_RESULT_CHANGED']); ], 'type' => 'FIXTURE_RESULT_CHANGED']);
} }
function begegnungTischChanged($begegnung, $heim_team, $gast_team) { function begegnungTischChanged($begegnung, $heim_team, $gast_team): void
{
notifyChange(['payload' => [ notifyChange(['payload' => [
'begegnung' => $begegnung, 'begegnung' => $begegnung,
'heim_team' => $heim_team, 'heim_team' => $heim_team,
@@ -74,7 +90,8 @@ function begegnungTischChanged($begegnung, $heim_team, $gast_team) {
], 'type' => 'TABLE_CHANGED']); ], 'type' => 'TABLE_CHANGED']);
} }
function begegnungVerlegenNotify($begegnung, $users, $vorschlagendes_team_id, $heim_team, $gast_team) { function begegnungVerlegenNotify($begegnung, $users, $vorschlagendes_team_id, $heim_team, $gast_team): void
{
notifyChange([ notifyChange([
'payload' => [ 'payload' => [
'begegnung' => $begegnung, 'begegnung' => $begegnung,
@@ -92,7 +109,8 @@ function begegnungVerlegenNotify($begegnung, $users, $vorschlagendes_team_id, $h
* @reponse body * @reponse body
* { data: { token: "reqest_token", access_for_team: ["team_id_1", "team_id_2"]}, expires: 1520013747000} * { data: { token: "reqest_token", access_for_team: ["team_id_1", "team_id_2"]}, expires: 1520013747000}
*/ */
function userToken() { #[NoReturn] function userToken(): void
{
global $secret; global $secret;
if (!isJson()) { if (!isJson()) {
abortWithError("JSON Request only"); abortWithError("JSON Request only");
@@ -100,33 +118,38 @@ function userToken() {
if (isExternalDatabase()) { if (isExternalDatabase()) {
abortWithError("Local Database only"); abortWithError("Local Database only");
} }
$jinput = JFactory::getApplication()->input->json; $container = Factory::getContainer();
$access_key = $jinput->getString('access_key'); $jInput = $container->get(SiteApplication::class)->input->json;
$access_key = $jInput->getString('access_key');
$user_id = _payload($access_key)->sub; $user_id = _payload($access_key)->sub;
$user = JFactory::getUser($user_id); $user = $container->get(UserFactoryInterface::class)->loadUserById($user_id);
if (!jwt_validate($access_key, $secret . $user->password)) { if (!jwt_validate($access_key, $secret . $user->password)) {
abortWithError('Access Key is invalid'); abortWithError('Access Key is invalid');
} }
try {
$expires = new DateTime(); $expires = new DateTime();
$expires->modify('+16 hours'); $expires->modify('+16 hours');
$db = &getDatabase(); $db = getDatabase();
$query = "SELECT berechtigt_team_id from #__sportsmanager_berechtigt_fuer_team where berechtigt_user_id = $user_id"; $query = "SELECT berechtigt_team_id from #__sportsmanager_berechtigt_fuer_team where berechtigt_user_id = $user_id";
$db->setQuery($query); $team_id = loadObjectList($db, $query);
if (!$db->execute()) {
abortWithError($db->stderr(true));
}
$team_id = $db->loadObjectList();
JSON_sportsmanager::JSON([ JSON_sportsmanager::JSON([
'token' => jwt_token([ 'token' => jwt_token([
'sub' => $user_id, 'sub' => $user_id,
'exp' => $expires->getTimestamp(), 'exp' => $expires->getTimestamp(),
], $secret), ], $secret),
'access_for_teams' => array_map(function($item) { return $item->berechtigt_team_id; }, $team_id), 'access_for_teams' => array_map(function ($item) {
return $item->berechtigt_team_id;
}, $team_id),
'expires' => $expires->getTimestamp() * 1000, // 'expires' => $expires->getTimestamp() * 1000, //
]); ]);
} catch (Exception $ex) {
error_log($ex);
}
} }
/* /*
@@ -134,7 +157,8 @@ function userToken() {
* @response body * @response body
* { data: { token: "api_acccess_token" }} * { data: { token: "api_acccess_token" }}
*/ */
function userAuth() { #[NoReturn] function userAuth(): void
{
global $secret; global $secret;
if (!isJson()) { if (!isJson()) {
die(); die();
@@ -142,18 +166,19 @@ function userAuth() {
if (isExternalDatabase()) { if (isExternalDatabase()) {
abortWithError("Local Database only"); abortWithError("Local Database only");
} }
$jinput = JFactory::getApplication()->input->json; $container = Factory::getContainer();
$username = $jinput->getString('username'); $jInput = $container->get(SiteApplication::class)->input->json;
$password = $jinput->getString('password'); $username = $jInput->getString('username');
$password = $jInput->getString('password');
$db = &getDatabase(); $db = getDatabase();
$query = $db->getQuery(true); $query = $db->getQuery(true);
$query->select('id')->from('#__users')->where('username = "' . $username . '"')->limit(1); $query->select('id')->from('#__users')->where('username = "' . $username . '"')->setLimit(1);
$db->setQuery($query); $user_id = loadResult($db, $query);
$user_id = $db->loadResult(); $user = $container->get(UserFactoryInterface::class)->loadUserById($user_id);
$user = JFactory::getUser($user_id);
if (JUserHelper::verifyPassword($password, $user->password, $user->id)) { //TODO: pw verification modernising: use php native methods, however this also needs new pw hashing. maybe force a pw reset on all accounts
if (password_verify($password, $user->password)) {
JSON_sportsmanager::JSON([ JSON_sportsmanager::JSON([
'token' => jwt_token([ 'token' => jwt_token([
@@ -161,24 +186,27 @@ function userAuth() {
'iat' => (new DateTime())->getTimestamp(), 'iat' => (new DateTime())->getTimestamp(),
], $secret . $user->password) ], $secret . $user->password)
]); ]);
return;
} }
abortWithError('Wrong credentials'); abortWithError('Wrong credentials');
} }
function getUserID() { function getUserID(): int
{
global $secret; global $secret;
$token = JFactory::getApplication()->input->server->getString('HTTP_SECRET', NULL); $container = Factory::getContainer();
$input = $container->get(SiteApplication::class)->input;
$token = $input->server->getString('HTTP_SECRET', NULL);
return $token != NULL && jwt_validate($token, $secret) && isset(_payload($token)->sub) return $token != NULL && jwt_validate($token, $secret) && isset(_payload($token)->sub)
? (int)_payload($token)->sub ? (int)_payload($token)->sub
: 0; : 0;
} }
function getColorOfImage($image) { function getColorOfImage($image)
{
if ($image != NULL) { if ($image != NULL) {
if (strpos($image, '.png') !== false) { if (str_contains($image, '.png')) {
$img = imagecreatefrompng($image); $img = imagecreatefrompng($image);
} else { } else {
$img = imagecreatefromjpeg($image); $img = imagecreatefromjpeg($image);
@@ -210,7 +238,8 @@ function getColorOfImage($image) {
return NULL; return NULL;
} }
function colorKey($rgb) { function colorKey($rgb): string
{
$r = (int)($rgb['red'] / 100); $r = (int)($rgb['red'] / 100);
$g = (int)($rgb['green'] / 100); $g = (int)($rgb['green'] / 100);
@@ -219,7 +248,8 @@ function colorKey($rgb) {
return $r . '-' . $g . '-' . $b; return $r . '-' . $g . '-' . $b;
} }
function hex($rgb) { function hex($rgb): ?string
{
$r = $rgb['red']; $r = $rgb['red'];
$g = $rgb['green']; $g = $rgb['green'];
$b = $rgb['blue']; $b = $rgb['blue'];
@@ -244,14 +274,16 @@ function hex($rgb) {
/* /*
* sign string with secret * sign string with secret
*/ */
function _sign($data, $secret, $algo = 'sha256') { function _sign($data, $secret): string
{
return base64_encode(hash_hmac('sha256', $data, $secret)); return base64_encode(hash_hmac('sha256', $data, $secret));
} }
/* /*
* get payload from jwt token * get payload from jwt token
*/ */
function _payload($token) { function _payload($token)
{
$jwt = explode('.', $token); $jwt = explode('.', $token);
return json_decode(base64_decode($jwt[0])); return json_decode(base64_decode($jwt[0]));
} }
@@ -259,7 +291,8 @@ function _payload($token) {
/* /*
* headless signed jwt token * headless signed jwt token
*/ */
function jwt_token($payload, $secret) { function jwt_token($payload, $secret): string
{
$data = base64_encode(json_encode($payload)); $data = base64_encode(json_encode($payload));
return $data . '.' . _sign($data, $secret); return $data . '.' . _sign($data, $secret);
@@ -268,7 +301,8 @@ function jwt_token($payload, $secret) {
/* /*
* validate token * validate token
*/ */
function jwt_validate($token, $secret) { function jwt_validate($token, $secret): bool
{
$jwt = explode('.', $token); $jwt = explode('.', $token);
if (sizeof($jwt) == 2 && $jwt[1] == _sign($jwt[0], $secret)) { if (sizeof($jwt) == 2 && $jwt[1] == _sign($jwt[0], $secret)) {
if (isset(_payload($token)->exp)) { if (isset(_payload($token)->exp)) {
@@ -1,24 +0,0 @@
<?php
/*
* Sports Manager (C) 2006-2020, Sven Nickel
*/
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die();
jimport('joomla.application.component.controller');
/**
* Auto Component Controller
*/
class SportsManagerController extends JControllerLegacy
{
function display()
{
// Setzt einen Standard view
if ( ! JRequest::getCmd( 'view' ) ) {
JRequest::setVar('view', 'categories' );
}
parent::display();
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,117 @@
<?php
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\Database\DatabaseInterface;
use Joomla\Database\Mysql\MysqlDriver;
use Joomla\Database\Mysqli\MysqliDriver;
require_once JPATH_SITE . '/components/com_sportsmanager/database/util.php';
function initDatabase(): void
{
global $sportsmanager_database_local;
global $sportsmanager_database_external;
global $sportsmanager_joomla_path;
global $sportsmanager_joomla_url;
$sportsmanager_database_local = NULL;
$sportsmanager_database_external = NULL;
$sportsmanager_joomla_path = JPATH_ROOT;
$sportsmanager_joomla_url = Uri::base();
$sportsmanager_database_local = Factory::getContainer()->get(DatabaseInterface::class);
$query = "SELECT * FROM #__sportsmanager_einstellungen";
$rows = loadObjectList($sportsmanager_database_local, $query);
$database_driver = "mysql";
$database_host = "";
$database_user = "";
$database_password = "";
$database_database = "";
$database_prefix = "jos_";
$joomla_path = "";
$joomla_url = "";
foreach ($rows as $row) {
$name = mb_strtolower($row->name);
if ($name == "database_driver")
$database_driver = $row->wert;
else if ($name == "database_host")
$database_host = $row->wert;
else if ($name == "database_user")
$database_user = $row->wert;
else if ($name == "database_password")
$database_password = $row->wert;
else if ($name == "database_database")
$database_database = $row->wert;
else if ($name == "database_prefix")
$database_prefix = $row->wert;
else if ($name == "joomla_path")
$joomla_path = $row->wert;
else if ($name == "joomla_url")
$joomla_url = $row->wert;
}
if (!empty($database_driver) && !empty($database_host) && !empty($database_user) && !empty($database_database) && !empty($database_prefix) && !empty($joomla_path) && !empty($joomla_url)) {
$option = array(); //prevent problems
$option['driver'] = $database_driver; // Database driver name
$option['host'] = $database_host; // Database host name
$option['user'] = $database_user; // User for database authentication
$option['password'] = $database_password; // Password for database authentication
$option['database'] = $database_database; // Database name
$option['prefix'] = $database_prefix; // Database prefix (may be empty)
$sportsmanager_database_external = match ($option['driver']) {
'mysql' => new MysqlDriver($option),
'mysqli' => new MysqliDriver($option),
default => NULL,
};
if ($sportsmanager_database_external === NULL) {
echo "<strong>" . Text::_('COM_SPORTSMANAGER_CONNECTION_EXTERNAL_DB_FAILURE') . "</strong><br><br>";
} else {
try {
if (!$sportsmanager_database_external->execute()) {
echo "<strong>" . Text::_('COM_SPORTSMANAGER_EXTERNAL_DB_NO_SM_TABLES') . "</strong><br><br>";
$sportsmanager_database_external = NULL;
} else {
$query = "SELECT wert FROM #__sportsmanager_einstellungen WHERE name = 'datenbank_version'";
$db_version = loadResult($sportsmanager_database_external, $query);
if ($db_version < 38) {
echo "<strong>" . Text::_('COM_SPORTSMANAGER_EXTERNAL_DB_NO_SM_VERSION') . "</strong><br><br>";
$sportsmanager_database_external = NULL;
} else if (!is_dir($joomla_path . DIRECTORY_SEPARATOR . "images" . DIRECTORY_SEPARATOR . "sportsmanager")) {
echo "<strong>" . Text::_('COM_SPORTSMANAGER_EXTERNAL_NO_IMAGES_FOLDER') . " '/images/sportsmanager'!</strong><br><br>";
$sportsmanager_database_external = NULL;
} else {
$sportsmanager_joomla_path = $joomla_path;
$sportsmanager_joomla_url = $joomla_url;
}
}
} catch (Exception $e) {
error_log($e->getMessage());
}
}
}
}
function isExternalDatabase(): bool
{
global $sportsmanager_database_external;
return $sportsmanager_database_external != NULL;
}
function getDatabase($forceLocalDB = FALSE)
{
global $sportsmanager_database_local;
global $sportsmanager_database_external;
if ($forceLocalDB || $sportsmanager_database_external == NULL)
$db = $sportsmanager_database_local;
else
$db = $sportsmanager_database_external;
return $db;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,47 @@
<?php
use Joomla\CMS\Log\Log;
/**
* @param $db
* @param $query
* @return mixed
* @since 2.0.5
*/
function loadObjectList($db, $query): mixed
{
try {
$db->setQuery($query);
$objList = $db->loadObjectList();
} catch (RuntimeException $e) {
Log::add("Database error: " . $e->getMessage(), Log::ERROR, "com_sportsmanager");
if(isJson()) {
abortWithError($e->getMessage());
} else {
throw $e;
}
}
return $objList;
}
/**
* @param $db
* @param $query
* @return mixed
* @since 2.0.5
*/
function loadResult($db, $query): mixed
{
try {
$db->setQuery($query);
$result = $db->loadResult();
} catch (RuntimeException $e) {
Log::add("Database error: " . $e->getMessage(), Log::ERROR, "com_sportsmanager");
if(isJson()) {
abortWithError($e->getMessage());
} else {
throw $e;
}
}
return $result;
}
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,45 @@
<?php
namespace Dtfb\Component\com_sportsmanager\Site\Controller;
/*
* Sports Manager (C) 2006-2020, Sven Nickel
*/
// Check to ensure this file is included in Joomla!
defined('_JEXEC') or die();
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Controller\BaseController;
/**
* @package SportsManager.Site
* @subpackage com_sportsmanager
*
* @copyright Copyright (C) 2020 John Smith. All rights reserved.
* @license GNU General Public License version 3; see LICENSE
*/
/**
* Class DisplayController
* @since 2.0.0
* The DisplayController class handles the display of views in the application.
* It extends the BaseController class.
*/
class DisplayController extends BaseController {
/**
* Displays the view for the given URL parameters.
*
* @param bool $cachable Whether the view can be cached or not. Default is false.
* @param array $urlparams The URL parameters to be passed to the view. Default is an empty array.
* @param array|null $safeurlparams An associative array of 'safe' URL parameters and their variable types.
*
* @return void
* @throws Exception
* @since 2.0.0
*/
public function display($cachable = false, $urlparams = array(), array $safeurlparams = null): void
{
require_once JPATH_SITE . '/components/com_sportsmanager/sportsmanager.php';
}
}
@@ -4,49 +4,75 @@
*/ */
// kein direkter Zugriff // kein direkter Zugriff
use JetBrains\PhpStorm\NoReturn;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Factory;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Version;
defined('_JEXEC') or die('Restricted access'); defined('_JEXEC') or die('Restricted access');
require_once (JPATH_COMPONENT.DIRECTORY_SEPARATOR.'mathparser.php'); require_once JPATH_SITE . '/components/com_sportsmanager/mathparser.php';
require_once JPATH_SITE . '/components/com_sportsmanager/database/init.php';
/** @noinspection PhpUnused */
function mathParserVerteilung($rohpunkte, $platz, $teilnehmer, $multiplikator) { function mathParserVerteilung($rohpunkte, $platz, $teilnehmer, $multiplikator) {
if ($teilnehmer <= 1){
return 0;
}
return max(round($multiplikator * round(((($rohpunkte - 1) * (-log($platz / $teilnehmer) * (1 - ($platz / $teilnehmer)))) / (-log(1 / $teilnehmer) * (1 - (1 / $teilnehmer)))) + 1)), 1); return max(round($multiplikator * round(((($rohpunkte - 1) * (-log($platz / $teilnehmer) * (1 - ($platz / $teilnehmer)))) / (-log(1 / $teilnehmer) * (1 - (1 / $teilnehmer)))) + 1)), 1);
} }
/** @noinspection PhpUnused */
function mathParserVerteilungR($rohpunkte, $platz, $teilnehmer, $multiplikator) { function mathParserVerteilungR($rohpunkte, $platz, $teilnehmer, $multiplikator) {
if ($teilnehmer <= 1){
return 0;
}
return max(round(((($multiplikator * $rohpunkte - 1) * (-log($platz / $teilnehmer) * (1 - ($platz / $teilnehmer)))) / (-log(1 / $teilnehmer) * (1 - (1 / $teilnehmer)))) + 1), 1); return max(round(((($multiplikator * $rohpunkte - 1) * (-log($platz / $teilnehmer) * (1 - ($platz / $teilnehmer)))) / (-log(1 / $teilnehmer) * (1 - (1 / $teilnehmer)))) + 1), 1);
} }
class MathParserSM extends MathParser { class MathParserSM extends MathParser
{
// Verteilung nach Klostermann/Wahle // Verteilung nach Klostermann/Wahle
public function __construct() { public function __construct()
MathParser::__construct(); {
$this->createFunc("ROUND", round, 1); parent::__construct();
$this->createFunc("VERTEILUNG", mathParserVerteilung, 4); try {
$this->createFunc("VERTEILUNGR", mathParserVerteilungR, 4); $this->createFunc("ROUND", 'round', 1);
$this->createFunc("VERTEILUNG", 'mathParserVerteilung', 4);
$this->createFunc("VERTEILUNGR", 'mathParserVerteilungR', 4);
} catch (Exception $e) {
Log::add('an error occurred: ' . $e->getMessage(), Log::ERROR, 'com_sportsmanager');
throw new RuntimeException('An error occurred.', 500);
}
} }
} }
function keinZugriff($login = FALSE) { #[NoReturn] function keinZugriff($login = FALSE): void
{
if (isJson()) { if (isJson()) {
abortWithError(401 . ' Unauthorized'); abortWithError(401 . ' Unauthorized');
} }
if (!$login || JFactory::getUser()->id) { if (!$login || Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id) {
JError::raiseError(500, JText::_('JERROR_ALERTNOAUTHOR')); Log::add('Unauthorized user with id ' . Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id, Log::WARNING, 'com_sportsmanager');
jexit(); throw new RuntimeException('Not authorized!', 401);
} }
$version = new JVersion; $version = new Version();
$joomla = $version->getShortVersion(); $joomla = $version->getShortVersion();
$u =& JFactory::getURI(); $u = Uri::getInstance();
$redirectUrl = urlencode(base64_encode($u->toString())); $redirectUrl = urlencode(base64_encode($u->toString()));
$redirectUrl = '&return=' . $redirectUrl; $redirectUrl = '&return=' . $redirectUrl;
$joomlaLoginUrl = 'index.php?option=' . (substr($joomla, 0, 3) != '1.5' ? 'com_users' : 'com_user') . '&view=login'; $joomlaLoginUrl = 'index.php?option=' . (!str_starts_with($joomla, '1.5') ? 'com_users' : 'com_user') . '&view=login';
$finalUrl = $joomlaLoginUrl . $redirectUrl; $finalUrl = $joomlaLoginUrl . $redirectUrl;
$app = &JFactory::getApplication(); $app = Factory::getContainer()->get(SiteApplication::class);
$app->redirect(JRoute::_($finalUrl)); $app->redirect(Route::_($finalUrl));
jexit(); jexit();
} }
function bereinigterDateiname($dateiname) { function bereinigterDateiname($dateiname): array|string
{
$_convertTable = array( $_convertTable = array(
'&amp;' => 'and', '@' => 'at', '©' => 'c', '®' => 'r', 'À' => 'a', '&amp;' => 'and', '@' => 'at', '©' => 'c', '®' => 'r', 'À' => 'a',
'Á' => 'a', 'Â' => 'a', 'Ä' => 'a', 'Å' => 'a', 'Æ' => 'ae', 'Ç' => 'c', 'Á' => 'a', 'Â' => 'a', 'Ä' => 'a', 'Å' => 'a', 'Æ' => 'ae', 'Ç' => 'c',
@@ -109,27 +135,30 @@ function bereinigterDateiname($dateiname) {
return str_replace($bad, "", strtr($dateiname, $_convertTable)); return str_replace($bad, "", strtr($dateiname, $_convertTable));
} }
function setMinMemoryLimit($memDestSize) { function setMinMemoryLimit($memDestSize): void
{
if (getBytes(ini_get('memory_limit')) < getBytes($memDestSize)) if (getBytes(ini_get('memory_limit')) < getBytes($memDestSize))
ini_set('memory_limit', $memDestSize); ini_set('memory_limit', $memDestSize);
} }
function getBytes($val) { function getBytes($val): int|string
{
$val = trim($val); $val = trim($val);
$last = strtolower($val{strlen($val)-1}); $numeric = substr($val, 0, strlen($val) - 1);
$last = strtolower($val[strlen($val) - 1]);
switch ($last) { switch ($last) {
// The 'G' modifier is available since PHP 5.1.0 // The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm': case 'm':
$val *= 1024; case 'g':
case 'k': case 'k':
$val *= 1024; $numeric *= 1024;
break;
} }
return $val; return $numeric;
} }
function encrypt($str, $key){ function encrypt($str, $key): string
{
$result = ""; $result = "";
for ($i = 0; $i < strlen($str); $i++) { for ($i = 0; $i < strlen($str); $i++) {
$char = substr($str, $i, 1); $char = substr($str, $i, 1);
@@ -140,7 +169,8 @@ function encrypt($str, $key){
return base64_encode($result); return base64_encode($result);
} }
function decrypt($str, $key){ function decrypt($str, $key): string
{
$str = base64_decode($str); $str = base64_decode($str);
$result = ""; $result = "";
for ($i = 0; $i < strlen($str); $i++) { for ($i = 0; $i < strlen($str); $i++) {
@@ -152,53 +182,294 @@ function decrypt($str, $key){
return $result; return $result;
} }
function individualwettbewerbFilter($prefix) { function individualwettbewerbFilter($prefix): string
$db =& getDatabase(); {
$user_id = isExternalDatabase() ? 0 : JFactory::getUser()->id; $user_id = isExternalDatabase() ? 0 : Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id;
return " " . $prefix . " (SELECT berechtigt_individualwettbewerb_id FROM #__sportsmanager_berechtigt_fuer_individualwettbewerb INNER JOIN #__sportsmanager_individualwettbewerb ON individualwettbewerb_id = berechtigt_individualwettbewerb_id WHERE berechtigt_user_id = $user_id) "; return " " . $prefix . " (SELECT berechtigt_individualwettbewerb_id FROM #__sportsmanager_berechtigt_fuer_individualwettbewerb INNER JOIN #__sportsmanager_individualwettbewerb ON individualwettbewerb_id = berechtigt_individualwettbewerb_id WHERE berechtigt_user_id = $user_id) ";
} }
function kategorieFilter($prefix, $suffix = "") { function kategorieFilter($prefix, $suffix = ""): string
{
global $params; global $params;
$kategorien = explode(",", $params->get('kategorien')); $kategorien = explode(",", $params->get('kategorien'));
$filter = ""; $result = [];
foreach ($kategorien as $s) {
$kategorie = intval(trim($s)); foreach ($kategorien as $item) {
if ($kategorie == 0) $item = trim($item);
if ($item === '') continue;
// Prüfen, ob es ein Bereich ist
if (strpos($item, '-') !== false) {
$rangeParts = explode('-', $item);
// genau 2 Teile für einen gültigen Bereich
if (count($rangeParts) !== 2) continue;
$start = intval(trim($rangeParts[0]));
$end = intval(trim($rangeParts[1]));
if ($start <= 0 || $end <= 0 || $start > $end) continue;
for ($i = $start; $i <= $end; $i++) {
$result[$i] = true; // Duplikate vermeiden
}
} else {
$num = intval($item);
if ($num > 0) {
$result[$num] = true;
}
}
}
if (empty($result)) {
return "";
}
$filter = array_keys($result);
sort($filter, SORT_NUMERIC);
return " $prefix (" . implode(", ", $filter) . ") $suffix";
}
function idListeParameterFilter(string $parameterName, string $prefix, string $suffix = ""): string
{
$jInput = Factory::getContainer()->get(SiteApplication::class)->input;
$werte = $jInput->get($parameterName, '', 'STRING');
$result = [];
foreach (explode(",", $werte) as $item) {
$item = trim($item);
if ($item === '') continue;
$num = intval($item);
if ($num > 0) {
$result[$num] = true; // Duplikate vermeiden
}
}
if (empty($result)) {
return "";
}
$filter = array_keys($result);
sort($filter, SORT_NUMERIC);
return " $prefix (" . implode(", ", $filter) . ") $suffix";
}
function halloffameIdFilter($prefix): string
{
// Keine Bereichssuche bei der Halloffame-Id, nur einzelne Werte
return idListeParameterFilter('halloffame_id', $prefix);
}
function halloffameJahrFilter($prefix): string
{
$minJahr = 1900;
$maxJahr = (int) date('Y') + 5;
$jInput = Factory::getContainer()->get(SiteApplication::class)->input;
$werte = $jInput->get('jahr', '', 'STRING');
$result = [];
foreach (explode(",", $werte) as $item) {
$item = trim($item);
if ($item === '') continue;
// Prüfen, ob es ein Bereich ist
if (strpos($item, '-') !== false) {
$rangeParts = explode('-', $item);
// genau 2 Teile für einen gültigen Bereich
if (count($rangeParts) !== 2) continue;
$start = intval(trim($rangeParts[0]));
$end = intval(trim($rangeParts[1]));
if ($start <= 0 || $end <= 0) continue;
// Werte vertauschen, falls der 2. Wert kleiner als der 1. ist
if ($end < $start) {
[$start, $end] = [$end, $start];
}
// Bereich auf 1900 .. aktuelles Jahr+5 begrenzen
$start = max($start, $minJahr);
$end = min($end, $maxJahr);
if ($start > $end) continue;
for ($i = $start; $i <= $end; $i++) {
$result[$i] = true; // Duplikate vermeiden
}
} else {
$num = intval($item);
if ($num <= 0) continue;
// Einzelwert auf 1900 .. aktuelles Jahr+5 begrenzen
$num = max($minJahr, min($maxJahr, $num));
$result[$num] = true;
}
}
if (empty($result)) {
return "";
}
$filter = array_keys($result);
sort($filter, SORT_NUMERIC);
return " $prefix (" . implode(", ", $filter) . ")";
}
function halloffameAlleTeams($db): array
{
return loadObjectList($db, "SELECT team_id, teamname FROM #__sportsmanager_team ORDER BY team_id DESC");
}
function halloffameTeamIdFuerTeamname(array $alleTeams, ?string $teamname)
{
if (empty($teamname))
return null;
foreach ($alleTeams as $team) {
if (str_starts_with($team->teamname, $teamname))
return $team->team_id;
}
return null;
}
function halloffameAlleSpielerInfo($db): array
{
// "Aktiv" = hat einen aktuellen Verein; ohne aktuellen Verein liefert spieler_details ohnehin keine Daten
$rows = loadObjectList($db, "SELECT spieler_id, geschlecht, aktueller_verein_id FROM #__sportsmanager_spieler");
$result = [];
foreach ($rows as $row) {
$result[$row->spieler_id] = (object) [
'geschlecht' => $row->geschlecht,
'aktiv' => !empty($row->aktueller_verein_id),
];
}
return $result;
}
function halloffameSpielerAktiv(array $alleSpielerInfo, $spieler_id): bool
{
return empty($spieler_id) || !isset($alleSpielerInfo[$spieler_id]) || $alleSpielerInfo[$spieler_id]->aktiv;
}
function halloffameSpielerBildId(array $alleSpielerInfo, $spieler_id)
{
return halloffameSpielerAktiv($alleSpielerInfo, $spieler_id) ? $spieler_id : '';
}
function halloffameSpielerBildAlternativ(array $alleSpielerInfo, $spieler_id, string $geschaetztesGeschlecht = ''): string
{
if (!empty($spieler_id) && isset($alleSpielerInfo[$spieler_id]))
return $alleSpielerInfo[$spieler_id]->geschlecht == 'M' ? 'm' : 'w';
if ($geschaetztesGeschlecht === 'M')
return 'm';
if ($geschaetztesGeschlecht === 'W')
return 'w';
return 'n';
}
function halloffameGeschlechtZaehlen(object $ziel, array $alleSpielerInfo, $spieler1_id, $spieler2_id): void
{
foreach ([$spieler1_id, $spieler2_id] as $id) {
if (empty($id) || !isset($alleSpielerInfo[$id]))
continue; continue;
if (!empty($filter)) if ($alleSpielerInfo[$id]->geschlecht == 'M')
$filter .= ", "; $ziel->anzahl_m++;
$filter .= $kategorie; else
$ziel->anzahl_w++;
} }
return empty($filter) ? "" : (" " . $prefix . " (" . $filter . ") " . $suffix);
} }
function turnierFilter($prefix) { function halloffameGeschaetztesGeschlecht($anzahl_m, $anzahl_w): string
$db =& getDatabase(); {
$user_id = isExternalDatabase() ? 0 : JFactory::getUser()->id; if ($anzahl_m > $anzahl_w)
return " " . $prefix . " (SELECT berechtigt_turnier_id FROM #__sportsmanager_berechtigt_fuer_turnier WHERE berechtigt_user_id = $user_id AND DATEDIFF(letzter_tag, NOW()) >= -14) "; return 'M';
if ($anzahl_w > $anzahl_m)
return 'W';
return '';
} }
function vereinFilter($prefix) { function halloffameAlleVereineInfo($db): array
$db =& getDatabase(); {
$user_id = isExternalDatabase() ? 0 : JFactory::getUser()->id; $rows = loadObjectList($db, "SELECT verein_id, ausgetreten FROM #__sportsmanager_verein");
$result = [];
foreach ($rows as $row) {
$result[$row->verein_id] = (object) [
'aktiv' => empty($row->ausgetreten),
];
}
return $result;
}
function halloffameVereinAktiv(array $alleVereineInfo, $verein_id): bool
{
return empty($verein_id) || !isset($alleVereineInfo[$verein_id]) || $alleVereineInfo[$verein_id]->aktiv;
}
function halloffameNameLink(string $bild_type, $id, array $alleSpielerInfo, array $alleVereineInfo, string $nameHtml): string
{
if (empty($id))
return $nameHtml;
if ($bild_type === 'spieler' && !halloffameSpielerAktiv($alleSpielerInfo, $id))
return $nameHtml;
if ($bild_type === 'vereine' && !halloffameVereinAktiv($alleVereineInfo, $id))
return $nameHtml;
$tasks = ['spieler' => 'spieler_details', 'vereine' => 'verein_details', 'mannschaften' => 'team_details'];
if (!isset($tasks[$bild_type]))
return $nameHtml;
return '<a href="' . SportsManagerURL('&task=' . $tasks[$bild_type] . '&id=' . $id) . '">' . $nameHtml . '</a>';
}
function halloffameTitel(): string
{
global $params;
$titel = trim((string) $params->get('titel', ''));
if ($titel !== '')
return $titel;
$menu = Factory::getContainer()->get(SiteApplication::class)->getMenu()->getActive();
if ($menu !== null && trim((string) $menu->title) !== '')
return $menu->title;
return '';
}
function turnierFilter($prefix): string
{
$user_id = isExternalDatabase() ? 0 : Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id;
return " " . $prefix . " (SELECT berechtigt_turnier_id FROM #__sportsmanager_berechtigt_fuer_turnier WHERE berechtigt_user_id = $user_id AND DATEDIFF(letzter_tag, NOW()) >= -21) ";
}
function vereinFilter($prefix): string
{
$user_id = isExternalDatabase() ? 0 : Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id;
return " " . $prefix . " (SELECT berechtigt_verein_id FROM #__sportsmanager_berechtigt_fuer_verein INNER JOIN #__sportsmanager_verein ON berechtigt_verein_id = verein_id WHERE berechtigt_user_id = $user_id AND NOT ausgetreten) "; return " " . $prefix . " (SELECT berechtigt_verein_id FROM #__sportsmanager_berechtigt_fuer_verein INNER JOIN #__sportsmanager_verein ON berechtigt_verein_id = verein_id WHERE berechtigt_user_id = $user_id AND NOT ausgetreten) ";
} }
function veranstalterFilter($prefix) { function veranstalterFilter($prefix): string
$db =& getDatabase(); {
$user_id = isExternalDatabase() ? 0 : JFactory::getUser()->id; $user_id = isExternalDatabase() ? 0 : Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id;
return " " . $prefix . " (SELECT berechtigt_veranstalter_id FROM #__sportsmanager_berechtigt_fuer_veranstalter WHERE berechtigt_user_id = $user_id) "; return " " . $prefix . " (SELECT berechtigt_veranstalter_id FROM #__sportsmanager_berechtigt_fuer_veranstalter WHERE berechtigt_user_id = $user_id) ";
} }
function veranstaltungFilter($prefix) { function veranstaltungFilter($prefix): string
$db =& getDatabase(); {
$user_id = isExternalDatabase() ? 0 : JFactory::getUser()->id; $user_id = isExternalDatabase() ? 0 : Factory::getContainer()->get(SiteApplication::class)->getIdentity()->id;
return " " . $prefix . " (SELECT berechtigt_veranstaltung_id FROM #__sportsmanager_berechtigt_fuer_veranstaltung INNER JOIN #__sportsmanager_veranstaltung ON veranstaltung_id = berechtigt_veranstaltung_id WHERE berechtigt_user_id = $user_id AND DATEDIFF(letzter_tag, NOW()) >= -14) "; return " " . $prefix . " (SELECT berechtigt_veranstaltung_id FROM #__sportsmanager_berechtigt_fuer_veranstaltung INNER JOIN #__sportsmanager_veranstaltung ON veranstaltung_id = berechtigt_veranstaltung_id WHERE berechtigt_user_id = $user_id AND DATEDIFF(letzter_tag, NOW()) >= -21) ";
} }
// Berechnet Datum zum Montag der ersten Kalenderwoche eines Jahres // Berechnet Datum zum Montag der ersten Kalenderwoche eines Jahres
function firstkw($jahr) { function firstkw($jahr): bool|int
{
$erster = mktime(0, 0, 0, 1, 1, $jahr); $erster = mktime(0, 0, 0, 1, 1, $jahr);
$wtag = date('w', $erster); $wtag = date('w', $erster);
if ($wtag <= 4) { if ($wtag <= 4) {
@@ -206,8 +477,7 @@ function firstkw($jahr) {
* Donnerstag oder kleiner: auf den Montag zurückrechnen. * Donnerstag oder kleiner: auf den Montag zurückrechnen.
*/ */
$montag = mktime(0, 0, 0, 1, 1 - ($wtag - 1), $jahr); $montag = mktime(0, 0, 0, 1, 1 - ($wtag - 1), $jahr);
} } else {
else {
/** /**
* auf den Montag nach vorne rechnen. * auf den Montag nach vorne rechnen.
*/ */
@@ -217,32 +487,34 @@ function firstkw($jahr) {
} }
// Berechnet Wochentag über Kalenderwoche, Jahr und Wochentag (0 = Montag, ..., 6 = Sonntag) // Berechnet Wochentag über Kalenderwoche, Jahr und Wochentag (0 = Montag, ..., 6 = Sonntag)
function mondaykw($kw, $jahr, $weekday) { function mondaykw($kw, $jahr, $weekday): bool|int
{
$firstmonday = firstkw($jahr); $firstmonday = firstkw($jahr);
$mon_monat = date('m', $firstmonday); $mon_monat = date('m', $firstmonday);
$mon_jahr = date('Y', $firstmonday); $mon_jahr = date('Y', $firstmonday);
$mon_tage = date('d',$firstmonday); $mon_tage = (int)date('d', $firstmonday);
$tage = ($kw - 1) * 7; $tage = ($kw - 1) * 7;
$daykw = mktime(0,0,0,$mon_monat,$mon_tage+$tage+$weekday,$mon_jahr); return mktime(0, 0, 0, $mon_monat, $mon_tage + $tage + $weekday, $mon_jahr);
return $daykw;
} }
// Berechnet Termin am Wochentag (0 = Montag, ..., 6 = Sonntag) in Kalenderwoche zum Datum // Berechnet Termin am Wochentag (0 = Montag, ..., 6 = Sonntag) in Kalenderwoche zum Datum
function geaenderterWochentag($datum, $wochentag) { function geaenderterWochentag($datum, $wochentag): bool|int
{
$wtag = date('w', $datum); $wtag = date('w', $datum);
if ($wtag == 0) // Sonntag if ($wtag == 0) // Sonntag
$wtag = 7; $wtag = 7;
$mon_monat = date('m', $datum); $mon_monat = date('m', $datum);
$mon_jahr = date('Y', $datum); $mon_jahr = date('Y', $datum);
$mon_tage = date('d', $datum); $mon_tage = (int)date('d', $datum);
return mktime(0, 0, 0, $mon_monat, $mon_tage + 1 - $wtag + $wochentag, $mon_jahr); return mktime(0, 0, 0, $mon_monat, $mon_tage + 1 - $wtag + $wochentag, $mon_jahr);
} }
function normalisiertesDatum($datum) { function normalisiertesDatum($datum): ?string
{
if ($datum == NULL) if ($datum == NULL)
return NULL; return NULL;
if (strpos($datum, "-") !== false) if (str_contains($datum, "-"))
$trennzeichen = "-"; $trennzeichen = "-";
else else
$trennzeichen = "."; $trennzeichen = ".";
@@ -256,37 +528,35 @@ function normalisiertesDatum($datum) {
$jahr = intval(substr($s, 0, 4)); $jahr = intval(substr($s, 0, 4));
$monat = intval(substr($s, 4, 2)); $monat = intval(substr($s, 4, 2));
$tag = intval(substr($s, 6, 2)); $tag = intval(substr($s, 6, 2));
} } else if ($n == 3) {
else if ($n == 3) {
if ($trennzeichen != ".") { if ($trennzeichen != ".") {
$jahr = intval($t[0]); $jahr = intval($t[0]);
if (strlen($t[0]) <= 2) if (strlen($t[0]) <= 2)
$jahr += 1900; $jahr += 1900;
$monat = intval($t[1]); $monat = intval($t[1]);
$tag = intval($t[2]); $tag = intval($t[2]);
} } else {
else {
$tag = intval($t[0]); $tag = intval($t[0]);
$monat = intval($t[1]); $monat = intval($t[1]);
$jahr = intval($t[2]); $jahr = intval($t[2]);
if (strlen($t[2]) <= 2) if (strlen($t[2]) <= 2)
$jahr += 1900; $jahr += 1900;
} }
} } else
else
return NULL; return NULL;
if (!checkdate($monat, $tag, $jahr)) if (!checkdate($monat, $tag, $jahr))
return NULL; return NULL;
return sprintf("%04d-%02d-%02d", $jahr, $monat, $tag);; return sprintf("%04d-%02d-%02d", $jahr, $monat, $tag);
} }
function normalisierteUhrzeit($uhrzeit) { function normalisierteUhrzeit($uhrzeit): ?string
{
if ($uhrzeit == NULL) if ($uhrzeit == NULL)
return NULL; return NULL;
if (strpos($uhrzeit, "-") !== FALSE) if (str_contains($uhrzeit, "-"))
$trennzeichen = "-"; $trennzeichen = "-";
else else
$trennzeichen = ":"; $trennzeichen = ":";
@@ -301,22 +571,21 @@ function normalisierteUhrzeit($uhrzeit) {
$stunden = intval(substr($s, 0, 2)); $stunden = intval(substr($s, 0, 2));
$minuten = intval(substr($s, 2, 2)); $minuten = intval(substr($s, 2, 2));
$sekunden = $len != 6 ? 0 : intval(substr($s, 4, 2)); $sekunden = $len != 6 ? 0 : intval(substr($s, 4, 2));
} } else if ($n == 2 || $n == 3) {
else if ($n == 2 || $n == 3) {
$stunden = intval($t[0]); $stunden = intval($t[0]);
$minuten = intval($t[1]); $minuten = intval($t[1]);
$sekunden = $n != 3 ? 0 : intval($t[2]); $sekunden = $n != 3 ? 0 : intval($t[2]);
} } else
else
return NULL; return NULL;
if ($stunden < 0 || $stunden > 23 || $minuten < 0 || $minuten > 59 || $sekunden < 0 || $sekunden > 59) if ($stunden < 0 || $stunden > 23 || $minuten < 0 || $minuten > 59 || $sekunden < 0 || $sekunden > 59)
return NULL; return NULL;
return sprintf("%02d:%02d:%02d", $stunden, $minuten, $sekunden);; return sprintf("%02d:%02d:%02d", $stunden, $minuten, $sekunden);
} }
function runden_detailliert_invers($runden) { function runden_detailliert_invers($runden): ?string
{
if ($runden == null) if ($runden == null)
return null; return null;
$runden_invers = ""; $runden_invers = "";
@@ -330,7 +599,8 @@ function runden_detailliert_invers($runden) {
return $runden_invers; return $runden_invers;
} }
function runden_detailliert_auswertung($runden) { function runden_detailliert_auswertung($runden): array
{
$ergebnis = 0; $ergebnis = 0;
$heim_saetze = 0; $heim_saetze = 0;
$unentschieden_saetze = 0; $unentschieden_saetze = 0;
@@ -358,9 +628,69 @@ function runden_detailliert_auswertung($runden) {
return array($ergebnis, $heim_saetze, $unentschieden_saetze, $gast_saetze, $heim_punkte, $gast_punkte); return array($ergebnis, $heim_saetze, $unentschieden_saetze, $gast_saetze, $heim_punkte, $gast_punkte);
} }
function spielpunkteFuerSpiel($wertung, $heim_punkte, $gast_punkte, $ergebnis_detailliert = null): array
{
if ($wertung == 2)
return array($heim_punkte, $gast_punkte);
$je_satz = $wertung >= 10;
$grund = $wertung % 10;
$sieg = $grund == 0 ? 2 : ($grund == 1 ? 3 : 1);
$remis = $grund == 3 ? 0 : 1;
if ($je_satz) {
if (empty($ergebnis_detailliert))
return array($sieg * (int)$heim_punkte, $sieg * (int)$gast_punkte);
$auswertung = runden_detailliert_auswertung($ergebnis_detailliert);
return array($sieg * $auswertung[1] + $remis * $auswertung[2],
$sieg * $auswertung[3] + $remis * $auswertung[2]);
}
if ($heim_punkte > $gast_punkte)
return array($sieg, 0);
if ($heim_punkte < $gast_punkte)
return array(0, $sieg);
if ($heim_punkte == 0 && $gast_punkte == 0)
return array(0, 0);
return array($remis, $remis);
}
function toreFuerSpiel($punktetyp, $satzergebnisse, $heim_punkte, $gast_punkte, $ergebnis_detailliert): array
{
if ($punktetyp == 0)
return array((int)$heim_punkte, (int)$gast_punkte);
if (!empty($satzergebnisse) && !empty($ergebnis_detailliert)) {
$auswertung = runden_detailliert_auswertung($ergebnis_detailliert);
return array($auswertung[4], $auswertung[5]);
}
return array(null, null);
}
function jeSatzWertung($wertung_einzel, $wertung_doppel): bool
{
return $wertung_einzel >= 10 || $wertung_doppel >= 10;
}
function ausgetragenBedingung($je_satz, $alias): string
{
return "($alias.heim_punkte != 0 OR $alias.gast_punkte != 0"
. ($je_satz ? " OR NOT ISNULL($alias.heim_tore)" : "") . ")";
}
function ergebnisVorhanden($je_satz, $heim_punkte, $gast_punkte, $heim_tore): bool
{
return $heim_punkte != null || $gast_punkte != null || ($je_satz && $heim_tore !== null);
}
function saetzeRemisFuerSpiel($punktetyp, $satzergebnisse, $ergebnis_detailliert): ?int
{
if ($punktetyp == 0 || empty($satzergebnisse) || empty($ergebnis_detailliert))
return null;
$auswertung = runden_detailliert_auswertung($ergebnis_detailliert);
return $auswertung[2];
}
// pass two file names // pass two file names
// returns TRUE if files are the same, FALSE otherwise // returns TRUE if files are the same, FALSE otherwise
function files_identical($fn1, $fn2) { function files_identical($fn1, $fn2): bool
{
if (!is_file($fn1) || !is_file($fn2)) if (!is_file($fn1) || !is_file($fn2))
return FALSE; return FALSE;
@@ -390,4 +720,4 @@ function files_identical($fn1, $fn2) {
return $same; return $same;
} }
?>
@@ -0,0 +1,125 @@
<?php
use Joomla\CMS\Factory;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Mail\MailerFactoryInterface;
use Joomla\CMS\Application\SiteApplication;
/**
* @since 2.2
* @throws Exception
*/
function sentEmailReminders(): void
{
$app = Factory::getContainer()->get(SiteApplication::class);
$db = getDatabase();
$query = $db->getQuery(true)
->select('wert')
->from('#__sportsmanager_einstellungen')
->where('name = ' . $db->quote('enable_email_reminders'));
$row = loadResult($db, $query);
if (!$row) {
return; // quit when email reminders are disabled
}
$query = $db->getQuery(true)
->select('tournament.turnier_id, tournament.turnierbezeichnung, tournament.letzter_tag, tournament.reminder_count, GROUP_CONCAT(user.email SEPARATOR ", ") as emails')
->from($db->quoteName('#__sportsmanager_turnier', 'tournament'))
->join('INNER', $db->quoteName('#__sportsmanager_berechtigt_fuer_turnier', 'entitled') . ' ON tournament.turnier_id = entitled.berechtigt_turnier_id')
->join('INNER', $db->quoteName('#__users', 'user') . ' ON entitled.berechtigt_user_id = user.id')
->where('tournament.reminder_count < 3')
->group('tournament.turnier_id, tournament.turnierbezeichnung');
$rows = loadObjectList($db, $query);
if(!empty($rows)) {
$mailFrom = $app->getCfg('mailfrom');
$fromName = $app->getCfg('fromname');
$mailer = Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer();
$mailer->setSender($mailFrom, $fromName);
foreach ($rows as $row) {
$currentReminder = $row->reminder_count + 1;
if (hasResultsAlready($db, $row)) {
updateDBReminders($db, $row, 3); // do not sent any more reminders
continue;
}
if (!isset($row->emails) || $row->emails == "" || $row->emails == NULL) {
Log::add('can\'t sent ' . $currentReminder .'. email reminder for tournament ' . $row->turnierbezeichnung . ': no recipient set', Log::WARNING, 'com_sportsmanager');
continue;
}
$now = new DateTime();
$last_day = new DateTime($row->letzter_tag);
$last_day->modify('+1 day'); // start to count at the end of the day, not at the beginning
$diff = $now->getTimestamp() - $last_day->getTimestamp();
$reminderDelays = [
1 => 24*60*60, // 24h
2 => 3*24*60*60, // 3d
3 => 13*24*60*60 // 13d
];
foreach ($reminderDelays as $count => $delay) {
if ($diff >= $delay && $row->reminder_count < $count) {
$subject = ($row->reminder_count == 2 ? "Letzte " : "") . "Erinnerung: " . $row->turnierbezeichnung . " Ergebnisse einreichen!";
$body = "Hi,"
. "\n\nDies ist die " . $currentReminder . ". " . ($row->reminder_count == 2 ? "*und damit letzte* " : "") . "Erinnerung die Turnierergebnisse einzureichen."
. "\n\nTurnier: " . $row->turnierbezeichnung
. "\nTurnierende: " . FormatiertesDatum($row->letzter_tag, false, false)
. "\n\nLaut Turnierordnung müssen die Ergebnisse spätestens 24 Stunden nach Turnierende eingetragen werden. Bitte reich die Ergebnisse umgehend nach."
. "\n\nDu erhältst diese Mail, weil du als Berechtigter für das Turnier eingetragen wurdest. Falls du nicht der Veranstalter bist, leite diese Email bitte entsprechend weiter."
. "\n\nHochladen der Ergebnisse über " . SportsManagerURL('&task=admin_turnierdisziplinen&turnierid=' . $row->turnier_id, -1) . ".";
$mailer->setSubject($subject);
$mailer->setBody($body);
$emailArray = explode(", ", $row->emails);
foreach ($emailArray as $email) {
$mailer->addBcc($email);
}
$mailer->send();
updateDBReminders($db, $currentReminder, $row->turnier_id);
}
}
}
}
}
function updateDBReminders($db, $reminder, $tournamentId): void
{
$query = $db->getQuery(true)
->update($db->quoteName('#__sportsmanager_turnier'))
->set($db->quoteName('reminder_count') . ' = ' . $db->quote($reminder))
->where($db->quoteName('turnier_id') . ' = ' . $db->quote($tournamentId));
$db->setQuery($query);
$db->execute();
}
/**
* checks if a tournament has at least one result entry for a discipline
* @param $db
* @param $row mixed tournament entry
* @return bool true if at least one result is given, else false
* @since 2.2
*/
function hasResultsAlready($db, mixed $row): bool
{
$subQuery = $db->getQuery(true)
->select($db->quoteName('turnierdisziplin_id'))
->from($db->quoteName('#__sportsmanager_turnierdisziplin'))
->where($db->quoteName('turnier_id') . ' = ' . $db->quote($row->turnier_id));
$query = $db->getQuery(true)
->select('COUNT(*) AS count')
->from($db->quoteName('#__sportsmanager_turniermeldung', 'tm'))
->where($db->quoteName('tm.turnierdisziplin_id') . ' IN (' . $subQuery . ')');
$result = loadResult($db, $query);
return $result && $result[0]->count > 0;
}
@@ -0,0 +1,475 @@
<?php
use JetBrains\PhpStorm\NoReturn;
use Joomla\CMS\Application\SiteApplication;
use Joomla\CMS\Factory;
use Joomla\CMS\Uri\Uri;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Folder;
require_once JPATH_SITE . '/components/com_sportsmanager/database/util.php';
const SPORTSMANAGER_JOOMLA_PATH = JPATH_ROOT;
define("SPORTSMANAGER_JOOMLA_URL", Uri::base());
function bildKopierenAngepasst($quelle, $ziel, $ziel_breite, $ziel_hoehe, $zuschneiden): bool
{
$len = strlen($ziel);
if ($len < 4 || $ziel[$len - 4] != ".")
return false;
$ext = strtolower(substr($ziel, $len - 3));
if ($ext != "jpg" && $ext != "png")
return false;
$quelle_image = $ext == "png" ? imagecreatefrompng($quelle) : imagecreatefromjpeg($quelle);
if ($quelle_image === false)
return false;
$quelle_breite = imagesx($quelle_image);
$quelle_hoehe = imagesy($quelle_image);
if ($quelle_breite == $ziel_breite && $quelle_hoehe == $ziel_hoehe)
return File::copy($quelle, $ziel);
$ziel_image = imagecreatetruecolor($ziel_breite, $ziel_hoehe);
$hintergrund = $ext == "png" ? imagecolorallocatealpha($ziel_image, 0, 0, 0, 127) : imagecolorallocate($ziel_image, 64, 64, 64);
imagefill($ziel_image, 0, 0, $hintergrund);
$quelle_proportionen = $quelle_breite / $quelle_hoehe;
$ziel_proportionen = $ziel_breite / $ziel_hoehe;
if ($zuschneiden) {
if ($ziel_proportionen >= $quelle_proportionen) {
$quelle_teilhoehe = round($quelle_breite / $ziel_proportionen);
if (!imagecopyresampled($ziel_image, $quelle_image, 0, 0, 0, round(($quelle_hoehe - $quelle_teilhoehe) / 2), $ziel_breite, $ziel_hoehe, $quelle_breite, $quelle_teilhoehe))
return false;
} else {
$quelle_teilbreite = round($quelle_hoehe * $ziel_proportionen);
if (!imagecopyresampled($ziel_image, $quelle_image, 0, 0, round(($quelle_breite - $quelle_teilbreite) / 2), 0, $ziel_breite, $ziel_hoehe, $quelle_teilbreite, $quelle_hoehe))
return false;
}
} else {
if ($ziel_proportionen >= $quelle_proportionen) {
$ziel_teilbreite = round($ziel_hoehe * $quelle_proportionen);
if (!imagecopyresampled($ziel_image, $quelle_image, round(($ziel_breite - $ziel_teilbreite) / 2), 0, 0, 0, $ziel_teilbreite, $ziel_hoehe, $quelle_breite, $quelle_hoehe))
return false;
} else {
$ziel_teilhoehe = round($ziel_breite / $quelle_proportionen);
if (!imagecopyresampled($ziel_image, $quelle_image, 0, round(($ziel_hoehe - $ziel_teilhoehe) / 2), 0, 0, $ziel_breite, $ziel_teilhoehe, $quelle_breite, $quelle_hoehe))
return false;
}
}
ob_start();
if ($ext == "png") {
imagesavealpha($ziel_image, true);
if (!imagepng($ziel_image))
return false;
} else {
if (!imagejpeg($ziel_image))
return false;
}
$output = ob_get_contents();
ob_end_clean();
File::write($ziel, $output);
return true;
}
#[NoReturn] function bildAnpassen($typ, $id = 0): void
{
$jInput = Factory::getContainer()->get(SiteApplication::class)->input;
if (empty($id))
$id = $jInput->get('id', 0, 'INT');
$fixed_width = $jInput->get('w', 0, 'INT');
$fixed_height = $jInput->get('h', 0, 'INT');
$max_width = $jInput->get('mw', 0, 'INT');
$max_height = $jInput->get('mh', 0, 'INT');
$no_cache = $jInput->get('nc', 0, 'INT');
$pfad = SPORTSMANAGER_JOOMLA_PATH . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ . DIRECTORY_SEPARATOR . $id . '.';
if (file_exists($pfad . 'png') && is_file($pfad . 'png'))
$ext = "png";
else if (file_exists($pfad . 'png') && is_file($pfad . 'png'))
$ext = "jpg";
else {
ob_end_clean(); // Wegen UTF-8-Zeichen, die in der ausgabe vorhanden sind
header('HTTP/1.1 404 Not Found');
die();
}
$filemtime = filemtime($pfad . $ext);
$last_modified = gmdate('D, d M Y H:i:s', $filemtime) . " GMT";
$etag = md5($id . '.' . $ext . $filemtime);
// Prüfung, ob die im Browsercache vorhandene Datei der hiesigen entspricht
if ($_SERVER['HTTP_IF_NONE_MATCH'] == '"' . $etag . '"' || $last_modified == $_SERVER['HTTP_IF_MODIFIED_SINCE']) {
ob_end_clean(); // Wegen UTF-8-Zeichen, die in der ausgabe vorhanden sind
header('HTTP/1.1 304 Not Modified');
if ($no_cache)
header("Cache-Control: must-revalidate"); // Bewirkt, dass der Browser jedesmal die Datei neu prüft
else
header("Cache-Control: max-age=2592000"); // Bewirkt, dass nach dreißig Tagen die Datei vom Browser auf eine Aktualisierung geprüft wird.
header("Last-Modified: " . $last_modified);
header('ETag: "' . $etag . '"');
die();
}
$image = $ext == "png" ? imagecreatefrompng($pfad . $ext) : imagecreatefromjpeg($pfad . $ext);
if ($image === false) {
ob_end_clean(); // Wegen UTF-8-Zeichen, die in der ausgabe vorhanden sind
header('HTTP/1.1 404 Not Found');
die();
}
ob_end_clean(); // Wegen UTF-8-Zeichen, die in der ausgabe vorhanden sind
header("Content-type: image/" . ($ext == "png" ? "png" : "jpeg"));
if ($no_cache)
header("Cache-Control: must-revalidate"); // Bewirkt, dass der Browser jedesmal die Datei neu prüft
else
header("Cache-Control: max-age=2592000"); // Bewirkt, dass nach dreißig Tagen die Datei vom Browser auf eine Aktualisierung geprüft wird.
header("Last-Modified: " . $last_modified);
header('ETag: "' . $etag . '"');
$width = imagesx($image);
$height = imagesy($image);
if (($fixed_width == 0 || $width == $fixed_width) && ($fixed_height == 0 || $height == $fixed_height) && ($fixed_width != 0 || $max_width == 0 || $width <= $max_width) && ($fixed_height != 0 || $max_height == 0 || $height <= $max_height)) {
if ($ext == "png") {
imagesavealpha($image, true);
imagepng($image);
} else
imagejpeg($image);
die();
}
$new_width = $width;
$new_height = $height;
if ($max_height > 0 && $new_height > $max_height) {
$new_width = max(round($new_width * $max_height / $new_height), 1);
$new_height = $max_height;
}
if ($max_width > 0 && $new_width > $max_width) {
$new_height = max(round($new_height * $max_width / $new_width), 1);
$new_width = $max_width;
}
if ($max_width > 0 && (($max_width - $new_width) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_width += 1;
if ($max_height > 0 && (($max_height - $new_height) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_height += 1;
$image_resized = imagecreatetruecolor(max($fixed_width, $new_width), max($fixed_height, $new_height));
$color = $ext == "png" ? imagecolorallocatealpha($image_resized, 0, 0, 0, 127) : imagecolorallocate($image_resized, 64, 64, 64);
imagefill($image_resized, 0, 0, $color);
imagecopyresampled($image_resized, $image, round((imagesx($image_resized) - $new_width) / 2), round((imagesy($image_resized) - $new_height) / 2), 0, 0, $new_width, $new_height, $width, $height);
if ($ext == "png") {
imagesavealpha($image_resized, true);
imagepng($image_resized);
} else
imagejpeg($image_resized);
die();
}
function bildLoeschen($typ, $id): void
{
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$bilder_pfad = SPORTSMANAGER_JOOMLA_PATH . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ;
$pfad = $bilder_pfad . '/' . $typ_prefix . $id . ".";
if (!is_file($pfad . 'png') && !is_file($pfad . 'jpg'))
return;
$alte_bilder = Folder::files($bilder_pfad, '^' . $typ_prefix . $id . '\.|^' . $typ_prefix . 'I' . $id . 'T');
foreach ($alte_bilder as $fn)
File::delete($bilder_pfad . DIRECTORY_SEPARATOR . $fn);
}
function bildIdentisch($typ1, $id1, $typ2, $id2): bool
{
$typ1_exploded = explode("/", $typ1);
$typ1 = $typ1_exploded[0];
$typ1_prefix = count($typ1_exploded) > 1 ? $typ1_exploded[1] : "";
$bilder_pfad1 = SPORTSMANAGER_JOOMLA_PATH . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ1;
$pfad1 = $bilder_pfad1 . '/' . $typ1_prefix . $id1 . ".";
if (is_file($pfad1 . "png"))
$ext = "png";
else if (is_file($pfad1 . "jpg"))
$ext = "jpg";
else
$ext = "";
$pfad1 .= $ext;
$typ2_exploded = explode("/", $typ2);
$typ2 = $typ2_exploded[0];
$typ2_prefix = count($typ2_exploded) > 1 ? $typ2_exploded[1] : "";
$bilder_pfad2 = SPORTSMANAGER_JOOMLA_PATH . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ2;
$pfad2 = $bilder_pfad2 . '/' . $typ2_prefix . $id2 . "." . $ext;
return files_identical($pfad1, $pfad2);
}
function teamImage($teamId, $vereinId, $width = 240, $height = 240): ?string
{
$url = bildURL("mannschaften", $teamId, 0, 0, $width, $height);
if ($url == null) {
$url = bildURL("vereine", $vereinId, 0, 0, $width, $height);
}
return $url;
}
function playerImage($playerId, $gender, $width = 180, $height = 240): ?string
{
$url = bildURL("spieler", $playerId, $width, $height, 0,0, $gender == 'M' ? 'm' : 'w');
if ($url == null) {
$url = bildURL("mannschaftsmitglieder", $playerId, $width, $height);
}
return $url;
}
#[NoReturn] function spielerbild(): void
{
$db = getDatabase();
$jInput = Factory::getContainer()->get(SiteApplication::class)->input;
$spielernr = $db->escape(trim($jInput->get('spielernr', '', 'RAW')));
$lizenznr = $db->escape(trim($jInput->get('lizenznr', '', 'RAW')));
if (empty($spielernr) && empty($lizenznr)) {
ob_end_clean(); // Wegen UTF-8-Zeichen, die in der ausgabe vorhanden sind
header('HTTP/1.1 404 Not Found');
die();
}
$query = "SELECT spieler_id"
. "\n FROM #__sportsmanager_spieler"
. "\n WHERE NOT ISNULL(aktueller_verein_id) AND NOT bild_ausblenden" . (!empty($spielernr) ? " AND spielernr = '$spielernr'" : " AND lizenznr = '$lizenznr'")
. "\n ORDER BY spieler_id DESC";
$rows = loadObjectList($db, $query);
if (count($rows) < 1) {
ob_end_clean(); // Wegen UTF-8-Zeichen, die in der ausgabe vorhanden sind
header('HTTP/1.1 404 Not Found');
die();
}
$id = $rows[0]->spieler_id;
bildAnpassen("spieler", $id);
}
function bildURL($typ, $id, $fixed_width = 0, $fixed_height = 0, $max_width = 0, $max_height = 0, $alternativ = ""): ?string
{
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$time = filemtime($pfad . $ext);
if ($fixed_width > 0 && $fixed_height > 0) {
$pfad_angepasst = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $fixed_width . "H" . $fixed_height . "." . $ext;
if (is_file($pfad_angepasst)) {
return SPORTSMANAGER_JOOMLA_URL . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst);
}
}
$size = getimagesize($pfad . $ext);
$width = $size[0];
$height = $size[1];
$max_width = $fixed_width > 0 ? $fixed_width : $max_width;
$max_height = $fixed_height > 0 ? $fixed_height : $max_height;
if (($fixed_width == 0 || $width == $fixed_width) && ($fixed_height == 0 || $height == $fixed_height) && ($fixed_width != 0 || $max_width == 0 || $width <= $max_width) && ($fixed_height != 0 || $max_height == 0 || $height <= $max_height)) {
$pfad_angepasst = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $width . "H" . $height . "." . $ext;
if (!is_file($pfad_angepasst)) {
if (!copy($pfad . $ext, $pfad_angepasst))
return null;
}
return SPORTSMANAGER_JOOMLA_URL . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst);
}
$new_width = $width;
$new_height = $height;
if ($max_height > 0 && $new_height > $max_height) {
$new_width = max(round($new_width * $max_height / $new_height), 1);
$new_height = $max_height;
}
if ($max_width > 0 && $new_width > $max_width) {
$new_height = max(round($new_height * $max_width / $new_width), 1);
$new_width = $max_width;
}
if ($max_width > 0 && (($max_width - $new_width) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_width += 1;
if ($max_height > 0 && (($max_height - $new_height) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_height += 1;
$pfad_angepasst = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . max($fixed_width, $new_width) . "H" . max($fixed_height, $new_height) . "." . $ext;
if (!is_file($pfad_angepasst)) {
$image = $ext == "png" ? imagecreatefrompng($pfad . $ext) : imagecreatefromjpeg($pfad . $ext);
if ($image === false)
return null;
$image_resized = imagecreatetruecolor(max($fixed_width, $new_width), max($fixed_height, $new_height));
$color = $ext == "png" ? imagecolorallocatealpha($image_resized, 0, 0, 0, 127) : imagecolorallocate($image_resized, 64, 64, 64);
imagefill($image_resized, 0, 0, $color);
imagecopyresampled($image_resized, $image, round((imagesx($image_resized) - $new_width) / 2), round((imagesy($image_resized) - $new_height) / 2), 0, 0, $new_width, $new_height, $width, $height);
if ($ext == "png") {
imagesavealpha($image_resized, true);
imagepng($image_resized, $pfad_angepasst);
}
else
imagejpeg($image_resized, $pfad_angepasst);
}
return SPORTSMANAGER_JOOMLA_URL . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst);
}
/*
* #resize=250
#resize=250,250,blue
#resize=250,250,blue
#resize=250,250&sizes=60%,80%,200%
#resize=250,250,cover&sizes=60%,80%,200%
#resize=250,250,fill&sizes=60%,80%,200%
#crop=250,250,center,top
#crop=250,250
#crop=250,250,center,bottom
#crop=250,250,left
#crop=250,250,right
*/
function yoothemeBild($typ, $id, $alternativ, $zusatz = ""): ?string
{
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$bildpfad = SPORTSMANAGER_JOOMLA_URL . "images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . "." . $ext;
return '<img class="el-image" data-src="' . $bildpfad . '" ' . $zusatz . ' uk-img />';
}
function bildHTML($typ, $id, $fixed_width = 0, $fixed_height = 0, $max_width = 0, $max_height = 0, $zusatz = "", $alternativ = ""): ?string
{
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$time = filemtime($pfad . $ext);
if ($fixed_width > 0 && $fixed_height > 0) {
$pfad_angepasst = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $fixed_width . "H" . $fixed_height . "." . $ext;
if (is_file($pfad_angepasst)) {
return '<img src="' . SPORTSMANAGER_JOOMLA_URL . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst) . '" width="' . $fixed_width . '" height="' . $fixed_height . '" ' . $zusatz . ' />';
}
}
$size = getimagesize($pfad . $ext);
$width = $size[0];
$height = $size[1];
$max_width = $fixed_width > 0 ? $fixed_width : $max_width;
$max_height = $fixed_height > 0 ? $fixed_height : $max_height;
if (($fixed_width == 0 || $width == $fixed_width) && ($fixed_height == 0 || $height == $fixed_height) && ($fixed_width != 0 || $max_width == 0 || $width <= $max_width) && ($fixed_height != 0 || $max_height == 0 || $height <= $max_height)) {
$pfad_angepasst = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $width . "H" . $height . "." . $ext;
if (!is_file($pfad_angepasst)) {
if (!copy($pfad . $ext, $pfad_angepasst))
return null;
}
return '<img src="' . SPORTSMANAGER_JOOMLA_URL . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst) . '" width="' . $width . '" height="' . $height . '" ' . $zusatz . ' />';
}
$new_width = $width;
$new_height = $height;
if ($max_height > 0 && $new_height > $max_height) {
$new_width = max(round($new_width * $max_height / $new_height), 1);
$new_height = $max_height;
}
if ($max_width > 0 && $new_width > $max_width) {
$new_height = max(round($new_height * $max_width / $new_width), 1);
$new_width = $max_width;
}
if ($max_width > 0 && (($max_width - $new_width) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_width += 1;
if ($max_height > 0 && (($max_height - $new_height) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_height += 1;
$pfad_angepasst = SPORTSMANAGER_JOOMLA_PATH . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . max($fixed_width, $new_width) . "H" . max($fixed_height, $new_height) . "." . $ext;
if (!is_file($pfad_angepasst)) {
$image = $ext == "png" ? imagecreatefrompng($pfad . $ext) : imagecreatefromjpeg($pfad . $ext);
if ($image === false)
return null;
$image_resized = imagecreatetruecolor(max($fixed_width, $new_width), max($fixed_height, $new_height));
$color = $ext == "png" ? imagecolorallocatealpha($image_resized, 0, 0, 0, 127) : imagecolorallocate($image_resized, 64, 64, 64);
imagefill($image_resized, 0, 0, $color);
imagecopyresampled($image_resized, $image, round((imagesx($image_resized) - $new_width) / 2), round((imagesy($image_resized) - $new_height) / 2), 0, 0, $new_width, $new_height, $width, $height);
if ($ext == "png") {
imagesavealpha($image_resized, true);
imagepng($image_resized, $pfad_angepasst);
}
else
imagejpeg($image_resized, $pfad_angepasst);
}
return '<img src="' . SPORTSMANAGER_JOOMLA_URL . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst) . '" width="' . max($fixed_width, $new_width) . '" height="' . max($fixed_height, $new_height) . '" ' . $zusatz . ' />';
}
@@ -0,0 +1,6 @@
<?php // do not change this file, this is automatically updated while building releases, see .github/workflows/build_release.yml
defined('_JEXEC') or die;
return [
'version' => 'DEV',
'date' => '2025-08-05',
];
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
@@ -24,6 +24,9 @@
<option value="vereine"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CLUBS]]></option> <option value="vereine"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CLUBS]]></option>
<option value="spielorte"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_VENUES]]></option> <option value="spielorte"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_VENUES]]></option>
<option value="termine"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_APPOINTMENTS]]></option> <option value="termine"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_APPOINTMENTS]]></option>
<option value="spielverlegungen"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_MATCH_RESCHEDULING]]></option>
<option value="verbandsorgane"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_ASSOCIATION_BODIES]]></option>
<option value="hall_of_fame"><![CDATA[COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_HALL_OF_FAME]]></option>
</field> </field>
<field name="titel" <field name="titel"
type="text" type="text"
@@ -42,6 +45,11 @@
default="" default=""
label="COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES" label="COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES"
description="COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES_DESC" /> description="COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_CATEGORIES_DESC" />
<field name="zusatzparameter"
type="text"
default=""
label="COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_EXTRA_PARAMS"
description="COM_SPORTSMANAGER_LAYOUT_GENERAL_CONTENT_OPTION_EXTRA_PARAMS_DESC" />
</fieldset> </fieldset>
</fields> </fields>
</metadata> </metadata>
@@ -1,5 +0,0 @@
[.ShellClassInfo]
InfoTip=Dieser Ordner wird online freigegeben.
IconFile=C:\Program Files (x86)\Google\Drive\googledrivesync.exe
IconIndex=16
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,18 @@
<?php <?php
use JetBrains\PhpStorm\NoReturn;
defined('_JEXEC') or die('Restricted access'); defined('_JEXEC') or die('Restricted access');
require_once(JPATH_COMPONENT . DIRECTORY_SEPARATOR . 'views/sportsmanager/view_tools.php'); require_once JPATH_SITE . '/components/com_sportsmanager/views/sportsmanager/view_tools.php';
require_once JPATH_SITE . '/components/com_sportsmanager/util/image.php';
class JSON_sportsmanager { class JSON_sportsmanager
{
static function mannschaften($veranstaltung, $rows) { static function mannschaften($veranstaltung, $rows): array
{
$teams = []; $teams = [];
foreach ($rows as $team) { foreach ($rows as $team) {
$team->teambild = teamImage($team->team_id, $team->verein_id); $team->teambild = teamImage($team->team_id, $team->verein_id);
@@ -22,7 +28,8 @@ class JSON_sportsmanager {
]; ];
} }
static function tabelleAnzeigen($veranstaltung, $modus, $teams, $spieltag, $spieltage, $alleine_angezeigt, $praesentation) { static function tabelleAnzeigen($modus, $teams): array
{
foreach ($teams as $team) { foreach ($teams as $team) {
$team->teambild = teamImage($team->team_id, $team->verein_id); $team->teambild = teamImage($team->team_id, $team->verein_id);
} }
@@ -33,7 +40,8 @@ class JSON_sportsmanager {
]; ];
} }
static function tabelleEigeneAnzeigen($veranstaltung, $modus, $teams, $alleine_angezeigt, $praesentation) { static function tabelleEigeneAnzeigen($modus, $teams): array
{
foreach ($teams as $team) { foreach ($teams as $team) {
$team->teambild = teamImage($team->team_id, $team->verein_id); $team->teambild = teamImage($team->team_id, $team->verein_id);
} }
@@ -43,7 +51,8 @@ class JSON_sportsmanager {
]; ];
} }
static function _getPlayerDetails($game, $home_player_map, $away_player_map) { static function _getPlayerDetails($game, $home_player_map, $away_player_map): void
{
// TODO dynamisch machen // TODO dynamisch machen
$game->heim_spieler_1_vorname = isset($home_player_map[$game->heim_spieler_1_id]) $game->heim_spieler_1_vorname = isset($home_player_map[$game->heim_spieler_1_id])
? $home_player_map[$game->heim_spieler_1_id]->vorname ? $home_player_map[$game->heim_spieler_1_id]->vorname
@@ -87,7 +96,8 @@ class JSON_sportsmanager {
} }
static function adminEditBegegnungSpielplan($bestaetigen, $veranstaltung, $begegnung, $heim_team, $gast_team, $spiele, $heim_spieler, $gast_spieler, $teamspiel_modus, $encrypted_pin, $count_verlegen_aktionen, $erneut_oeffnen, $aus_uebersicht) { static function adminEditBegegnungSpielplan($bestaetigen, $veranstaltung, $begegnung, $heim_team, $gast_team, $spiele, $heim_spieler, $gast_spieler, $teamspiel_modus): array
{
$heim_team->teambild = teamImage($heim_team->team_id, $heim_team->verein_id); $heim_team->teambild = teamImage($heim_team->team_id, $heim_team->verein_id);
$gast_team->teambild = teamImage($gast_team->team_id, $gast_team->verein_id); $gast_team->teambild = teamImage($gast_team->team_id, $gast_team->verein_id);
$heim_spieler_map = []; $heim_spieler_map = [];
@@ -119,7 +129,8 @@ class JSON_sportsmanager {
]; ];
} }
static function mannschaftDetails($veranstaltung, $team, $mitglieder, $mailverteiler, $mitglieder_statistiken, $teamansprechpartner, $begegnungen, $vorheriges_team_id, $naechstes_team_id, $team_moderator, $details_anzeigen, $ansprechpartner_anzeigen, $weitere_veranstaltungen, $veranstaltungsbezeichnungen, $spielberechtigungen, $ansicht_vereinigt, $ist_vergangen) { static function mannschaftDetails($veranstaltung, $team, $mitglieder, $teamansprechpartner, $begegnungen, $ansprechpartner_anzeigen, $veranstaltungsbezeichnungen): array
{
global $sportsmanager_joomla_path; global $sportsmanager_joomla_path;
global $sportsmanager_joomla_url; global $sportsmanager_joomla_url;
@@ -156,25 +167,27 @@ class JSON_sportsmanager {
]; ];
} }
static function JSON($data, $meta = NULL) { #[NoReturn] static function JSON($data, $meta = NULL): void
{
$response = [ $response = [
'data' => $data 'data' => $data
]; ];
if ($meta != NULL) { if ($meta != NULL) {
$response['meta'] = $meta; $response['meta'] = $meta;
} }
header('Content-Type: application/json; charset=utf-8', true); header('Content-Type: application/json; charset=utf-8');
echo json_encode($response); echo json_encode($response);
jexit(); jexit();
} }
static function spielerstatistik($spielerstatistik, $spielerstatistik_punkte, $allein_angezeigt, $filter_saison_id, $vorherige_spielerstatistik_id, $naechste_spielerstatistik_id, $details_anzeigen) { #[NoReturn] static function spielerstatistik($spielerstatistik_punkte): void
{
$rank = 1; $rank = 1;
foreach ($spielerstatistik_punkte as $s) { foreach ($spielerstatistik_punkte as $s) {
$s->spieler_bild = playerImage($s->spieler_id, $s->geschlecht); $s->spieler_bild = playerImage($s->spieler_id, $s->geschlecht);
$s->spieler_2_bild = playerImage($s->spieler_2_id, $s->geschlecht_2); $s->spieler_2_bild = playerImage($s->spieler_2_id, $s->geschlecht_2);
$s->quote = ($s->spielpunkte_gewonnen > 0 || $s->spielpunkte_verloren > 0) $s->quote = ($s->spielpunkte_gewonnen > 0 || $s->spielpunkte_verloren > 0)
? round($s->spielpunkte_gewonnen * 100 / ($s->spielpunkte_gewonnen + $s->spielpunkte_verloren), 0) . '%' ? round($s->spielpunkte_gewonnen * 100 / ($s->spielpunkte_gewonnen + $s->spielpunkte_verloren)) . '%'
: '-'; : '-';
$s->rank = '' . $rank; $s->rank = '' . $rank;
$rank++; $rank++;
@@ -182,7 +195,9 @@ class JSON_sportsmanager {
self::JSON($spielerstatistik_punkte); self::JSON($spielerstatistik_punkte);
} }
static function spielerDetails($spieler, $vereine, $veranstalter, $spieler_elo_verlauf_einzel, $spieler_elo_verlauf_doppel, $spielerNamen, $teamNamen, $veranstaltungBezeichnungen, $turnierdisziplinBezeichnungen, $individualwettbewerbBezeichnungen, $ranglistenplatzierungen, $turnierplatzierungen, $teams, $sortierung, $vorheriger_spieler_id, $naechster_spieler_id, $elo_detailliert, $statistik, $beginn, $kategorie, $einstufungen, $filter, $veranstaltungid, $veranstalterid, $einstufungid, $unabhaengige_ansicht, $details_anzeigen) { #[NoReturn] static function spielerDetails($spieler, $vereine, $veranstalter, $spieler_elo_verlauf_einzel, $spieler_elo_verlauf_doppel, $spielerNamen, $teamNamen, $veranstaltungBezeichnungen, $turnierdisziplinBezeichnungen, $individualwettbewerbBezeichnungen, $ranglistenplatzierungen, $turnierplatzierungen, $teams, $elo_detailliert, $statistik, $einstufungen): void
{
if (count($vereine) == 0){die;}
$letzte_einzel = []; $letzte_einzel = [];
$spieler->bild = playerImage($spieler->spieler_id, $spieler->geschlecht); $spieler->bild = playerImage($spieler->spieler_id, $spieler->geschlecht);
for ($i = sizeof($spieler_elo_verlauf_einzel) - 1; $i >= max(sizeof($spieler_elo_verlauf_einzel) - 10, 0); $i--) { for ($i = sizeof($spieler_elo_verlauf_einzel) - 1; $i >= max(sizeof($spieler_elo_verlauf_einzel) - 10, 0); $i--) {
@@ -285,13 +300,14 @@ class JSON_sportsmanager {
]); ]);
} }
static function begegnungVerlegen($veranstaltung, $begegnung, $heim_team, $gast_team, $verlegen_aktionen, $berechtigt_fuer_akzeptieren, $aus_uebersicht, $vorschlagendes_team_id) { #[NoReturn] static function begegnungVerlegen($veranstaltung, $verlegen_aktionen, $berechtigt_fuer_akzeptieren, $vorschlagendes_team_id): void
{
$letzte_aktionen = array(); $letzte_aktionen = array();
foreach ($verlegen_aktionen as $aktion) { foreach ($verlegen_aktionen as $aktion) {
if ($aktion->aktion == 1 || $aktion->aktion == 5 || $aktion == 10) { if ($aktion->aktion == 1 || $aktion->aktion == 5 || $aktion == 10) {
break; break;
} }
array_push($letzte_aktionen, $aktion); $letzte_aktionen[] = $aktion;
} }
$termine = array(); $termine = array();
if (count($letzte_aktionen) > 0) { if (count($letzte_aktionen) > 0) {
@@ -300,7 +316,7 @@ class JSON_sportsmanager {
if ($aktion->eingetragen != $eingetragen || $aktion->aktion != 0 || $aktion->zeitpunkt == NULL) { if ($aktion->eingetragen != $eingetragen || $aktion->aktion != 0 || $aktion->zeitpunkt == NULL) {
break; break;
} }
array_push($termine, $aktion); $termine[] = $aktion;
} }
} }
@@ -328,7 +344,7 @@ class JSON_sportsmanager {
'termine' => $response, 'termine' => $response,
'berechtigt_anfordern' => $berechtigt_anfordern, 'berechtigt_anfordern' => $berechtigt_anfordern,
'berechtigt_ablehnen' => $berechtigt_ablehnen, 'berechtigt_ablehnen' => $berechtigt_ablehnen,
'berechtigt_akzeptieren' => $berechtigt_fuer_akzeptieren ? TRUE : FALSE, 'berechtigt_akzeptieren' => (bool)$berechtigt_fuer_akzeptieren,
'termine_minimal' => $veranstaltung->termine_minimal, 'termine_minimal' => $veranstaltung->termine_minimal,
'termine_maximal' => $veranstaltung->termine_maximal, 'termine_maximal' => $veranstaltung->termine_maximal,
]); ]);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -3,29 +3,32 @@
* Sports Manager (C) 2006-2020, Sven Nickel * Sports Manager (C) 2006-2020, Sven Nickel
*/ */
// kein direkter Zugriff use Joomla\Filesystem\Folder;
defined('_JEXEC') or die('Restricted access'); use Joomla\CMS\Router\Route;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
function htmlentities_utf8($s) { // kein direkter Zugriff
defined("_JEXEC") or die("Restricted access");
function htmlentities_utf8($s): string
{
return htmlentities($s, ENT_QUOTES, "UTF-8"); return htmlentities($s, ENT_QUOTES, "UTF-8");
} }
function htmlentities_noquotes_utf8($s) { function addOnLoad($function): void
return htmlentities($s, ENT_NOQUOTES, "UTF-8"); {
}
function addOnLoad($function) {
?> ?>
<script language="JavaScript"> <script language="JavaScript">
function addLoadEvent(func) { function addLoadEvent(func) {
var oldonload = window.onload; const oldOnload = window.onload;
if (typeof window.onload != 'function') { if (typeof window.onload != 'function') {
window.onload = func; window.onload = func;
} }
else { else {
window.onload = function () { window.onload = function () {
if (oldonload) { if (oldOnload) {
oldonload(); oldOnload();
} }
func(); func();
} }
@@ -37,57 +40,87 @@ function addOnLoad($function) {
<?php <?php
} }
function SportsManagerURL($weitereParameter = null, $ssl = 0) { function SportsManagerURL($weitereParameter = "", $ssl = 0): ?string
return JRoute::_('index.php' . ($weitereParameter != null ? ("?" . ltrim($weitereParameter, "&")) : ""), false, $ssl); {
$urlPath = handleFilter($weitereParameter);
$joomlaBaseUrl = Uri::getInstance()->toString([
"scheme",
"host",
"port",
"path",
]);
if (str_contains($joomlaBaseUrl, "?")) {
// Base URL already contains a query string, append with '&'
$finalUrl = $joomlaBaseUrl . "&" . ltrim($urlPath, "&");
} else {
// Base URL does not contain a query string, append with '?'
$finalUrl = $joomlaBaseUrl . "?" . ltrim($urlPath, "&");
} }
function NichtLeererString($s, $ersatz = "Keiner") { return Route::_($finalUrl, false, $ssl);
}
function handleFilter($urlPart)
{
// Check if both '&filter=' and '#' are present in the URL part
if (
str_contains($urlPart, "&filter=") &&
str_contains($urlPart, "#")
) {
// Split the string by '#' to remove the hash part
$parts = explode("#", $urlPart, 2);
$query = $parts[0];
// Parse the query string into an associative array
parse_str($query, $queryParams);
// Remove the 'filter' parameter if it exists
unset($queryParams["filter"]);
// Rebuild the query string without the 'filter' parameter
return http_build_query($queryParams);
} else {
// Return the original URL part if either '&filter=' or '#' is not present
return $urlPart;
}
}
function NichtLeererString($s, $ersatz = "Keiner")
{
return !empty($s) ? $s : $ersatz; return !empty($s) ? $s : $ersatz;
} }
function hervorheben($titel) { function hervorheben($titel) {
if (empty($titel)) if (empty($titel)) {
return $titel; return $titel;
return $titel . ' *';
} }
function Laenderkennungen() { return $titel . " *";
$kennungen = array("AUT", "BEL", "BUL", "CZE", "DEN", "FRA", "GBR", "GER", "LUX", "NED", "SUI", "USA");
return $kennungen;
} }
function rundenstufe($stufe) { function Laenderkennungen(): array
switch ($stufe) { {
case 0: return array("AUT", "BEL", "BUL", "CZE", "DEN", "FRA", "GBR", "GER", "LUX", "NED", "SUI", "USA");
$bezeichnung = JText::_('COM_SPORTSMANAGER_FINAL_RANKS'); }
break;
case 1:
$bezeichnung = JText::_('COM_SPORTSMANAGER_MAIN_ROUND');
break;
case 2:
$bezeichnung = JText::_('COM_SPORTSMANAGER_ADDITIONAL_ROUND');
break;
case 3:
$bezeichnung = JText::_('COM_SPORTSMANAGER_2ND_ADDITIONAL_ROUND');
break;
case 10:
$bezeichnung = JText::_('COM_SPORTSMANAGER_PRELIMINARY_ROUND');
break;
case 20:
$bezeichnung = JText::_('COM_SPORTSMANAGER_REGISTRATIONS');
break;
default:
$bezeichnung = "";
} // switch
return $bezeichnung; function rundenstufe($stufe): string
{
return match ($stufe) {
0 => Text::_("COM_SPORTSMANAGER_FINAL_RANKS"),
1 => Text::_("COM_SPORTSMANAGER_MAIN_ROUND"),
2 => Text::_("COM_SPORTSMANAGER_ADDITIONAL_ROUND"),
3 => Text::_("COM_SPORTSMANAGER_2ND_ADDITIONAL_ROUND"),
10 => Text::_("COM_SPORTSMANAGER_PRELIMINARY_ROUND"),
20 => Text::_("COM_SPORTSMANAGER_REGISTRATIONS"),
default => "",
};
} }
function StringsZusammenfassen($titel1, $titel2, $ersatz = null, $separator = " / ") { function StringsZusammenfassen($titel1, $titel2, $ersatz = null, $separator = " / ") {
if ($ersatz == null) if ($ersatz == null) {
$ersatz = JText::_('COM_SPORTSMANAGER_NONE'); $ersatz = Text::_("COM_SPORTSMANAGER_NONE");
}
$t1 = NichtLeererString($titel1, $ersatz); $t1 = NichtLeererString($titel1, $ersatz);
$t2 = NichtLeererString($titel2, $ersatz); $t2 = NichtLeererString($titel2, $ersatz);
@@ -97,65 +130,59 @@ function StringsZusammenfassen($titel1, $titel2, $ersatz = null, $separator = "
function Rundenbezeichnung($runde, $spieltag = false, $bezeichnung_verstecken = false, $kurzform = false) { function Rundenbezeichnung($runde, $spieltag = false, $bezeichnung_verstecken = false, $kurzform = false) {
if ($kurzform) { if ($kurzform) {
if ($runde >= 20000) if ($runde >= 20000)
return JText::sprintf('COM_SPORTSMANAGER_PLACE_FROM_TO_SHORTCUT', 99 - $runde % 100, 99 - floor(($runde - 20000) / 100) + 99 - ($runde % 100)); return Text::sprintf("COM_SPORTSMANAGER_PLACE_FROM_TO_SHORTCUT", 99 - $runde % 100, 99 - floor(($runde - 20000) / 100) + 99 - ($runde % 100));
switch ($runde) { return match ($runde) {
case 0: 0 => $spieltag
return $spieltag ? JText::_('COM_SPORTSMANAGER_MATCH_DAY_NONE') : JText::_('COM_SPORTSMANAGER_ROUND_NONE'); ? Text::_("COM_SPORTSMANAGER_MATCH_DAY_NONE")
case 19999: : Text::_("COM_SPORTSMANAGER_ROUND_NONE"),
return JText::_('COM_SPORTSMANAGER_FINAL_SHORTCUT'); 19999 => Text::_("COM_SPORTSMANAGER_FINAL_SHORTCUT"),
case 19998: 19998 => Text::_("COM_SPORTSMANAGER_3RD_PLACE_SHORTCUT"),
return JText::_('COM_SPORTSMANAGER_3RD_PLACE_SHORTCUT'); 19997 => Text::_("COM_SPORTSMANAGER_HALF_FINAL_SHORTCUT"),
case 19997: 19996 => Text::_("COM_SPORTSMANAGER_QUARTER_FINAL_SHORTCUT"),
return JText::_('COM_SPORTSMANAGER_HALF_FINAL_SHORTCUT'); 19995 => Text::_("COM_SPORTSMANAGER_ROUND_OF_16_SHORTCUT"),
case 19996: 19994 => Text::_("COM_SPORTSMANAGER_ROUND_OF_32_SHORTCUT"),
return JText::_('COM_SPORTSMANAGER_QUARTER_FINAL_SHORTCUT'); 19993 => Text::_("COM_SPORTSMANAGER_ROUND_OF_64_SHORTCUT"),
case 19995: 19992 => Text::_("COM_SPORTSMANAGER_ROUND_OF_128_SHORTCUT"),
return JText::_('COM_SPORTSMANAGER_ROUND_OF_16_SHORTCUT'); default => $bezeichnung_verstecken ? $runde : Text::sprintf($spieltag ? "COM_SPORTSMANAGER_MATCH_DAY_NR_SHORTCUT" : "COM_SPORTSMANAGER_ROUND_NR_SHORTCUT", $runde),
case 19994: };
return JText::_('COM_SPORTSMANAGER_ROUND_OF_32_SHORTCUT');
case 19993:
return JText::_('COM_SPORTSMANAGER_ROUND_OF_64_SHORTCUT');
case 19992:
return JText::_('COM_SPORTSMANAGER_ROUND_OF_128_SHORTCUT');
}
return $bezeichnung_verstecken ? $runde : JText::sprintf($spieltag ? 'COM_SPORTSMANAGER_MATCH_DAY_NR_SHORTCUT' : 'COM_SPORTSMANAGER_ROUND_NR_SHORTCUT', $runde);
} }
else { else {
if ($runde >= 20000) if ($runde >= 20000)
return JText::sprintf('COM_SPORTSMANAGER_PLACE_FROM_TO', 99 - $runde % 100, 99 - floor(($runde - 20000) / 100) + 99 - ($runde % 100)); return Text::sprintf("COM_SPORTSMANAGER_PLACE_FROM_TO", 99 - $runde % 100, 99 - floor(($runde - 20000) / 100) + 99 - ($runde % 100));
switch ($runde) { return match ($runde) {
case 0: 0 => $spieltag
return $spieltag ? JText::_('COM_SPORTSMANAGER_MATCH_DAY_NONE') : JText::_('COM_SPORTSMANAGER_ROUND_NONE'); ? Text::_("COM_SPORTSMANAGER_MATCH_DAY_NONE")
case 19999: : Text::_("COM_SPORTSMANAGER_ROUND_NONE"),
return JText::_('COM_SPORTSMANAGER_FINAL'); 19999 => Text::_("COM_SPORTSMANAGER_FINAL"),
case 19998: 19998 => Text::_("COM_SPORTSMANAGER_3RD_PLACE"),
return JText::_('COM_SPORTSMANAGER_3RD_PLACE'); 19997 => Text::_("COM_SPORTSMANAGER_HALF_FINAL"),
case 19997: 19996 => Text::_("COM_SPORTSMANAGER_QUARTER_FINAL"),
return JText::_('COM_SPORTSMANAGER_HALF_FINAL'); 19995 => Text::_("COM_SPORTSMANAGER_ROUND_OF_16"),
case 19996: 19994 => Text::_("COM_SPORTSMANAGER_ROUND_OF_32"),
return JText::_('COM_SPORTSMANAGER_QUARTER_FINAL'); 19993 => Text::_("COM_SPORTSMANAGER_ROUND_OF_64"),
case 19995: 19992 => Text::_("COM_SPORTSMANAGER_ROUND_OF_128"),
return JText::_('COM_SPORTSMANAGER_ROUND_OF_16'); default => $bezeichnung_verstecken
case 19994: ? $runde
return JText::_('COM_SPORTSMANAGER_ROUND_OF_32'); : Text::sprintf(
case 19993: $spieltag
return JText::_('COM_SPORTSMANAGER_ROUND_OF_64'); ? "COM_SPORTSMANAGER_MATCH_DAY_NR"
case 19992: : "COM_SPORTSMANAGER_ROUND_NR",
return JText::_('COM_SPORTSMANAGER_ROUND_OF_128'); $runde
} ),
};
return $bezeichnung_verstecken ? $runde : JText::sprintf($spieltag ? 'COM_SPORTSMANAGER_MATCH_DAY_NR' : 'COM_SPORTSMANAGER_ROUND_NR', $runde);
} }
} }
function FormatiertesDatum($s, $zeit_anzeigen = true, $wochentag_anzeigen = true) { function FormatiertesDatum($s, $zeit_anzeigen = true, $wochentag_anzeigen = true): string
{
if ($s != null && strlen($s) > 0) { if ($s != null && strlen($s) > 0) {
$ts = getdate(strtotime($s)); $ts = getdate(strtotime($s));
if ($wochentag_anzeigen) { if ($wochentag_anzeigen) {
$wochentage = array(JText::_('COM_SPORTSMANAGER_DAY_0_SHORTCUT'), JText::_('COM_SPORTSMANAGER_DAY_1_SHORTCUT'), JText::_('COM_SPORTSMANAGER_DAY_2_SHORTCUT'), JText::_('COM_SPORTSMANAGER_DAY_3_SHORTCUT'), JText::_('COM_SPORTSMANAGER_DAY_4_SHORTCUT'), JText::_('COM_SPORTSMANAGER_DAY_5_SHORTCUT'), JText::_('COM_SPORTSMANAGER_DAY_6_SHORTCUT')); $wochentage = array(Text::_("COM_SPORTSMANAGER_DAY_0_SHORTCUT"), Text::_("COM_SPORTSMANAGER_DAY_1_SHORTCUT"), Text::_("COM_SPORTSMANAGER_DAY_2_SHORTCUT"), Text::_("COM_SPORTSMANAGER_DAY_3_SHORTCUT"), Text::_("COM_SPORTSMANAGER_DAY_4_SHORTCUT"), Text::_("COM_SPORTSMANAGER_DAY_5_SHORTCUT"), Text::_("COM_SPORTSMANAGER_DAY_6_SHORTCUT"));
if ($zeit_anzeigen) if ($zeit_anzeigen)
return sprintf("%s, %02d.%02d.%04d %02d:%02d", $wochentage[$ts["wday"]], $ts["mday"], $ts["mon"], $ts["year"], $ts["hours"], $ts["minutes"]); return sprintf("%s, %02d.%02d.%04d %02d:%02d", $wochentage[$ts["wday"]], $ts["mday"], $ts["mon"], $ts["year"], $ts["hours"], $ts["minutes"]);
@@ -167,10 +194,11 @@ function FormatiertesDatum($s, $zeit_anzeigen = true, $wochentag_anzeigen = true
return sprintf("%02d.%02d.%04d", $ts["mday"], $ts["mon"], $ts["year"]); return sprintf("%02d.%02d.%04d", $ts["mday"], $ts["mon"], $ts["year"]);
} }
return JText::_('COM_SPORTSMANAGER_DATE_NONE'); return Text::_("COM_SPORTSMANAGER_DATE_NONE");
} }
function FormatierterTermin($erster_tag, $letzter_tag, $jahr_anzeigen = false, $filter_jahr = null) { function FormatierterTermin($erster_tag, $letzter_tag, $jahr_anzeigen = false, $filter_jahr = null): string
{
$erster_ts = getdate(strtotime($erster_tag)); $erster_ts = getdate(strtotime($erster_tag));
$letzter_ts = getdate(strtotime($letzter_tag)); $letzter_ts = getdate(strtotime($letzter_tag));
if (!empty($filter_jahr)) if (!empty($filter_jahr))
@@ -188,401 +216,12 @@ function FormatierterTermin($erster_tag, $letzter_tag, $jahr_anzeigen = false, $
return $erster_termin . "-" . $letzter_termin; return $erster_termin . "-" . $letzter_termin;
} }
function bildLoeschen($typ, $id) { function terminDokumentname($id): bool|string
global $sportsmanager_joomla_path;
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$bilder_pfad = $sportsmanager_joomla_path . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ;
$pfad = $bilder_pfad . '/' . $typ_prefix . $id . ".";
if (!is_file($pfad . 'png') && !is_file($pfad . 'jpg'))
return;
$alte_bilder = JFolder::files($bilder_pfad, '^' . $typ_prefix . $id . '\.|^' . $typ_prefix . 'I' . $id . 'T');
foreach ($alte_bilder as $fn)
JFile::delete($bilder_pfad . DIRECTORY_SEPARATOR . $fn);
}
function bildIdentisch($typ1, $id1, $typ2, $id2) {
global $sportsmanager_joomla_path;
$typ1_exploded = explode("/", $typ1);
$typ1 = $typ1_exploded[0];
$typ1_prefix = count($typ1_exploded) > 1 ? $typ1_exploded[1] : "";
$bilder_pfad1 = $sportsmanager_joomla_path . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ1;
$pfad1 = $bilder_pfad1 . '/' . $typ1_prefix . $id1 . ".";
if (is_file($pfad1 . "png"))
$ext = "png";
else if (is_file($pfad1 . "jpg"))
$ext = "jpg";
else
$ext = "";
$pfad1 .= $ext;
$typ2_exploded = explode("/", $typ2);
$typ2 = $typ2_exploded[0];
$typ2_prefix = count($typ2_exploded) > 1 ? $typ2_exploded[1] : "";
$bilder_pfad2 = $sportsmanager_joomla_path . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . 'sportsmanager' . DIRECTORY_SEPARATOR . $typ2;
$pfad2 = $bilder_pfad2 . '/' . $typ2_prefix . $id2 . "." . $ext;
return files_identical($pfad1, $pfad2);
}
function teamImage($teamId, $vereinId, $width = 240, $height = 240) {
$url = bildURL("mannschaften", $teamId, 0, 0, $width, $height);
if ($url == null) {
$url = bildURL("vereine", $vereinId, 0, 0, $width, $height);
}
return $url;
}
function playerImage($playerId, $gender, $width = 180, $height = 240) {
$url = bildURL("spieler", $playerId, $width, $height, 0,0,'', $gender == 'M' ? 'm' : 'w');
if ($url == null) {
$url = bildURL("mannschaftsmitglieder", $playerId, $width, $height, 0,0,'');
}
return $url;
}
function bildURL($typ, $id, $fixed_width = 0, $fixed_height = 0, $max_width = 0, $max_height = 0, $zusatz = "", $alternativ = "") {
global $sportsmanager_joomla_path;
global $sportsmanager_joomla_url;
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$time = filemtime($pfad . $ext);
if ($fixed_width > 0 && $fixed_height > 0) {
$pfad_angepasst = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $fixed_width . "H" . $fixed_height . "." . $ext;
if (is_file($pfad_angepasst)) {
return $sportsmanager_joomla_url . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst);
}
}
$size = getimagesize($pfad . $ext);
$width = $size[0];
$height = $size[1];
$max_width = $fixed_width > 0 ? $fixed_width : $max_width;
$max_height = $fixed_height > 0 ? $fixed_height : $max_height;
if (($fixed_width == 0 || $width == $fixed_width) && ($fixed_height == 0 || $height == $fixed_height) && ($fixed_width != 0 || $max_width == 0 || $width <= $max_width) && ($fixed_height != 0 || $max_height == 0 || $height <= $max_height)) {
$pfad_angepasst = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $width . "H" . $height . "." . $ext;
if (!is_file($pfad_angepasst)) {
if (!copy($pfad . $ext, $pfad_angepasst))
return null;
}
return $sportsmanager_joomla_url . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst);
}
$new_width = $width;
$new_height = $height;
if ($max_height > 0 && $new_height > $max_height) {
$new_width = max(round($new_width * $max_height / $new_height), 1);
$new_height = $max_height;
}
if ($max_width > 0 && $new_width > $max_width) {
$new_height = max(round($new_height * $max_width / $new_width), 1);
$new_width = $max_width;
}
if ($max_width > 0 && (($max_width - $new_width) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_width += 1;
if ($max_height > 0 && (($max_height - $new_height) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_height += 1;
$pfad_angepasst = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . max($fixed_width, $new_width) . "H" . max($fixed_height, $new_height) . "." . $ext;
if (!is_file($pfad_angepasst)) {
$image = $ext == "png" ? imagecreatefrompng($pfad . $ext) : imagecreatefromjpeg($pfad . $ext);
if ($image === false)
return null;
$image_resized = imagecreatetruecolor(max($fixed_width, $new_width), max($fixed_height, $new_height));
$color = $ext == "png" ? imagecolorallocatealpha($image_resized, 0, 0, 0, 127) : imagecolorallocate($image_resized, 64, 64, 64);
imagefill($image_resized, 0, 0, $color);
imagecopyresampled($image_resized, $image, round((imagesx($image_resized) - $new_width) / 2), round((imagesy($image_resized) - $new_height) / 2), 0, 0, $new_width, $new_height, $width, $height);
if ($ext == "png") {
imagesavealpha($image_resized, true);
imagepng($image_resized, $pfad_angepasst);
}
else
imagejpeg($image_resized, $pfad_angepasst);
}
return $sportsmanager_joomla_url . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst);
}
/*
* #resize=250
#resize=250,250,blue
#resize=250,250,blue
#resize=250,250&sizes=60%,80%,200%
#resize=250,250,cover&sizes=60%,80%,200%
#resize=250,250,fill&sizes=60%,80%,200%
#crop=250,250,center,top
#crop=250,250
#crop=250,250,center,bottom
#crop=250,250,left
#crop=250,250,right
*/
function yoothemeBild($typ, $id, $resize = '', $zusatz = "", $alternativ)
{ {
global $sportsmanager_joomla_path; global $sportsmanager_joomla_path;
global $sportsmanager_joomla_url;
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$time = filemtime($pfad . $ext);
$bildpfad = "images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . "." . $ext;
return '<img class="el-image" data-src="' . $bildpfad . $resize . '" ' . $zusatz . ' uk-img />';
}
/*
Quick and dirty DTFL Logo Bilder
*/
function logoBilder($typ, $id, $resize = '', $zusatz = "", $alternativ)
{
global $sportsmanager_joomla_path;
global $sportsmanager_joomla_url;
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$time = filemtime($pfad . $ext);
$bildpfad = "images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . "." . $ext;
return '<img class="el-image" data-src="' . $bildpfad . $resize . '" ' . $zusatz . ' uk-img />';
}
function bildHTML($typ, $id, $fixed_width = 0, $fixed_height = 0, $max_width = 0, $max_height = 0, $zusatz = "", $alternativ = "") {
global $sportsmanager_joomla_path;
global $sportsmanager_joomla_url;
$typ_exploded = explode("/", $typ);
$typ = $typ_exploded[0];
$typ_prefix = count($typ_exploded) > 1 ? $typ_exploded[1] : "";
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else if (!empty($alternativ)) {
$id = $alternativ;
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . $id . ".";
if (is_file($pfad . "png"))
$ext = "png";
else if (is_file($pfad . "jpg"))
$ext = "jpg";
else
return null;
}
else
return null;
$time = filemtime($pfad . $ext);
if ($fixed_width > 0 && $fixed_height > 0) {
$pfad_angepasst = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $fixed_width . "H" . $fixed_height . "." . $ext;
if (is_file($pfad_angepasst)) {
return '<img src="' . $sportsmanager_joomla_url . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst) . '" width="' . $fixed_width . '" height="' . $fixed_height . '" ' . $zusatz . ' />';
}
}
$size = getimagesize($pfad . $ext);
$width = $size[0];
$height = $size[1];
$max_width = $fixed_width > 0 ? $fixed_width : $max_width;
$max_height = $fixed_height > 0 ? $fixed_height : $max_height;
if (($fixed_width == 0 || $width == $fixed_width) && ($fixed_height == 0 || $height == $fixed_height) && ($fixed_width != 0 || $max_width == 0 || $width <= $max_width) && ($fixed_height != 0 || $max_height == 0 || $height <= $max_height)) {
$pfad_angepasst = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . $width . "H" . $height . "." . $ext;
if (!is_file($pfad_angepasst)) {
if (!copy($pfad . $ext, $pfad_angepasst))
return null;
}
return '<img src="' . $sportsmanager_joomla_url . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst) . '" width="' . $width . '" height="' . $height . '" ' . $zusatz . ' />';
}
$new_width = $width;
$new_height = $height;
if ($max_height > 0 && $new_height > $max_height) {
$new_width = max(round($new_width * $max_height / $new_height), 1);
$new_height = $max_height;
}
if ($max_width > 0 && $new_width > $max_width) {
$new_height = max(round($new_height * $max_width / $new_width), 1);
$new_width = $max_width;
}
if ($max_width > 0 && (($max_width - $new_width) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_width += 1;
if ($max_height > 0 && (($max_height - $new_height) % 2) == 1) // Toleranz bei nur 1 Pixel Unterschied
$new_height += 1;
$pfad_angepasst = $sportsmanager_joomla_path . "/images/sportsmanager/" . $typ . "/" . $typ_prefix . "I" . $id . "T" . $time . "W" . max($fixed_width, $new_width) . "H" . max($fixed_height, $new_height) . "." . $ext;
if (!is_file($pfad_angepasst)) {
$image = $ext == "png" ? imagecreatefrompng($pfad . $ext) : imagecreatefromjpeg($pfad . $ext);
if ($image === false)
return null;
$image_resized = imagecreatetruecolor(max($fixed_width, $new_width), max($fixed_height, $new_height));
$color = $ext == "png" ? imagecolorallocatealpha($image_resized, 0, 0, 0, 127) : imagecolorallocate($image_resized, 64, 64, 64);
imagefill($image_resized, 0, 0, $color);
imagecopyresampled($image_resized, $image, round((imagesx($image_resized) - $new_width) / 2), round((imagesy($image_resized) - $new_height) / 2), 0, 0, $new_width, $new_height, $width, $height);
if ($ext == "png") {
imagesavealpha($image_resized, true);
imagepng($image_resized, $pfad_angepasst);
}
else
imagejpeg($image_resized, $pfad_angepasst);
}
return '<img src="' . $sportsmanager_joomla_url . 'images/sportsmanager/' . $typ . '/' . basename($pfad_angepasst) . '" width="' . max($fixed_width, $new_width) . '" height="' . max($fixed_height, $new_height) . '" ' . $zusatz . ' />';
}
function terminDokumentname($id) {
global $sportsmanager_joomla_path;
$pfad = $sportsmanager_joomla_path . "/images/sportsmanager/termine"; $pfad = $sportsmanager_joomla_path . "/images/sportsmanager/termine";
$dokumente = JFolder::files($pfad, '^' . $id . ' '); $dokumente = Folder::files($pfad, '^' . $id . ' ');
return !empty($dokumente) ? substr($dokumente[0], strlen((string) $id) + 1) : false; return !empty($dokumente) ? substr($dokumente[0], strlen((string) $id) + 1) : false;
} }
function lightBoxJSShow($lightbox_class = "lightbox") {
return "show" . $lightbox_class . "();";
}
function lightBoxJSHide($lightbox_class = "lightbox") {
return "hide" . $lightbox_class . "();";
}
function lightBoxClassHide($lightbox_class = "lightbox") {
return $lightbox_class . "_close";
}
function lightBoxHeader($lightbox_class = "lightbox") {
?>
<style type="text/css">
div<?php echo "#" . $lightbox_class; ?> {
position: fixed;
left: 50px;
right: 50px;
top: 50px;
bottom: 50px;
border: 1px solid #999999;
overflow: scroll;
background-color: #e4e4e4;
padding: 20px;
display: none;
visibility: hidden;
}
div<?php echo "#" . $lightbox_class . "_close"; ?> {
position: fixed;
right: 0px;
top: 0px;
bottom: 0px;
left: 0px;
overflow: hidden;
display: none;
visibility: hidden;
background-color: rgba(0, 0, 0, 0.8);
}
</style>
<script type="text/javascript">
//<!--
function show<?php echo $lightbox_class; ?>() {
document.getElementById("<?php echo $lightbox_class; ?>").style.display = "inline";
document.getElementById("<?php echo $lightbox_class; ?>").style.visibility = "visible";
document.getElementById("<?php echo $lightbox_class . "_close"; ?>").style.display = "inline";
document.getElementById("<?php echo $lightbox_class . "_close"; ?>").style.visibility = "visible";
}
function hide<?php echo $lightbox_class; ?>() {
document.getElementById("<?php echo $lightbox_class; ?>").style.display = "none";
document.getElementById("<?php echo $lightbox_class; ?>").style.visibility = "hidden";
document.getElementById("<?php echo $lightbox_class . "_close"; ?>").style.display = "none";
document.getElementById("<?php echo $lightbox_class . "_close"; ?>").style.visibility = "hidden";
}
//-->
</script>
<?php
}
@@ -1,4 +1,4 @@
; Sports Manager (C) 2006-2020, Sven Nickel (Test) ; Sports Manager (C) 2006-2020, Sven Nickel (Test)
COM_SPORTSMANAGER="Sports Manager" COM_SPORTSMANAGER="Sports Manager"
COM_SPORTSMANAGER_PLAYERS="Spieler" COM_SPORTSMANAGER_PLAYERS="Spieler"
COM_SPORTSMANAGER_CLUBS="Vereine" COM_SPORTSMANAGER_CLUBS="Vereine"
@@ -21,6 +21,7 @@ COM_SPORTSMANAGER_LOCATIONS="Spielorte"
COM_SPORTSMANAGER_SEASONS="Saisons" COM_SPORTSMANAGER_SEASONS="Saisons"
COM_SPORTSMANAGER_TEAM_PLANS="Mannschaftsspielpl&auml;ne" COM_SPORTSMANAGER_TEAM_PLANS="Mannschaftsspielpl&auml;ne"
COM_SPORTSMANAGER_TEAM_NAME="Mannschaftsname" COM_SPORTSMANAGER_TEAM_NAME="Mannschaftsname"
COM_SPORTSMANAGER_TEAM_NAME_SHORT="Mannschaftsname kurz (max 24)"
COM_SPORTSMANAGER_TEAM_NAME2="Vereinsname" COM_SPORTSMANAGER_TEAM_NAME2="Vereinsname"
COM_SPORTSMANAGER_TEAM_SEAT="Vereinssitz" COM_SPORTSMANAGER_TEAM_SEAT="Vereinssitz"
COM_SPORTSMANAGER_POSTPONE_RULES="Verschieberegeln" COM_SPORTSMANAGER_POSTPONE_RULES="Verschieberegeln"
@@ -38,6 +39,8 @@ COM_SPORTSMANAGER_ORGANISATION="Organisation"
COM_SPORTSMANAGER_TEAM_MEMBERS="Mannschaftsmitglieder" COM_SPORTSMANAGER_TEAM_MEMBERS="Mannschaftsmitglieder"
COM_SPORTSMANAGER_TEAM_MEMBERS2=Vereinsmitglieder COM_SPORTSMANAGER_TEAM_MEMBERS2=Vereinsmitglieder
COM_SPORTSMANAGER_MEMBERS="Mitglieder" COM_SPORTSMANAGER_MEMBERS="Mitglieder"
COM_SPORTSMANAGER_MEMBER="Mitglied"
COM_SPORTSMANAGER_ACTIVE_MEMBERS="Aktive Mitglieder"
COM_SPORTSMANAGER_TEAMS="Mannschaften" COM_SPORTSMANAGER_TEAMS="Mannschaften"
COM_SPORTSMANAGER_CURRENT_TEAMS="Aktuelle Mannschaften" COM_SPORTSMANAGER_CURRENT_TEAMS="Aktuelle Mannschaften"
COM_SPORTSMANAGER_PREVIOUS_TEAMS="Fr&uuml;here Mannschaften" COM_SPORTSMANAGER_PREVIOUS_TEAMS="Fr&uuml;here Mannschaften"
@@ -74,13 +77,13 @@ COM_SPORTSMANAGER_GAME="Spiel"
COM_SPORTSMANAGER_GAMES="Spiele" COM_SPORTSMANAGER_GAMES="Spiele"
COM_SPORTSMANAGER_GAMES_SHORTCUT="S" COM_SPORTSMANAGER_GAMES_SHORTCUT="S"
COM_SPORTSMANAGER_ADD_PLAYER_STATISTICS="Spielerstatistik hinzuf&uuml;gen" COM_SPORTSMANAGER_ADD_PLAYER_STATISTICS="Spielerstatistik hinzuf&uuml;gen"
COM_SPORTSMANAGER_PLAYER_STATISTICS="Spielerstatistik" COM_SPORTSMANAGER_PLAYER_STATISTIC="Spielerstatistik"
COM_SPORTSMANAGER_COMPETITION="Wettbewerb" COM_SPORTSMANAGER_COMPETITION="Wettbewerb"
COM_SPORTSMANAGER_COMPETITIONS="Wettbewerbe" COM_SPORTSMANAGER_COMPETITIONS="Wettbewerbe"
COM_SPORTSMANAGER_IN_COMPETITIONS="in Wettbewerb" COM_SPORTSMANAGER_IN_COMPETITIONS="in Wettbewerb"
COM_SPORTSMANAGER_COMPETITIONS_SHORTCUT="W" COM_SPORTSMANAGER_COMPETITIONS_SHORTCUT="W"
COM_SPORTSMANAGER_DUPLICATE="Duplizieren" COM_SPORTSMANAGER_DUPLICATE="Duplizieren"
COM_SPORTSMANAGER_CONFIRM_REMOVE_RANKING="Willst du die Spielerstatistik wirklich entfernen?" COM_SPORTSMANAGER_CONFIRM_REMOVE_PLAYER_STATISTICS="Willst du die Spielerstatistik wirklich entfernen?"
COM_SPORTSMANAGER_LIVE_TICKER="Live-Ticker" COM_SPORTSMANAGER_LIVE_TICKER="Live-Ticker"
COM_SPORTSMANAGER_PLACE="Platz" COM_SPORTSMANAGER_PLACE="Platz"
COM_SPORTSMANAGER_TEAM="Mannschaft" COM_SPORTSMANAGER_TEAM="Mannschaft"
@@ -129,10 +132,13 @@ COM_SPORTSMANAGER_QUARTER_FINAL_SHORTCUT="1/4"
COM_SPORTSMANAGER_ROUND_OF_16="Achtelfinale" COM_SPORTSMANAGER_ROUND_OF_16="Achtelfinale"
COM_SPORTSMANAGER_ROUND_OF_16_SHORTCUT="1/8" COM_SPORTSMANAGER_ROUND_OF_16_SHORTCUT="1/8"
COM_SPORTSMANAGER_ROUND_OF_32="Sechzehntelfinale" COM_SPORTSMANAGER_ROUND_OF_32="Sechzehntelfinale"
COM_SPORTSMANAGER_ROUND_OF_32_ALT="16-tel-Finale"
COM_SPORTSMANAGER_ROUND_OF_32_SHORTCUT="1/16" COM_SPORTSMANAGER_ROUND_OF_32_SHORTCUT="1/16"
COM_SPORTSMANAGER_ROUND_OF_64="Zweiunddreißigstelfinale" COM_SPORTSMANAGER_ROUND_OF_64="Zweiunddreißigstelfinale"
COM_SPORTSMANAGER_ROUND_OF_64_ALT="32-tel-Finale"
COM_SPORTSMANAGER_ROUND_OF_64_SHORTCUT="1/32" COM_SPORTSMANAGER_ROUND_OF_64_SHORTCUT="1/32"
COM_SPORTSMANAGER_ROUND_OF_128="Vierundsechzigstelfinale" COM_SPORTSMANAGER_ROUND_OF_128="Vierundsechzigstelfinale"
COM_SPORTSMANAGER_ROUND_OF_128_ALT="64-tel-Finale"
COM_SPORTSMANAGER_ROUND_OF_128_SHORTCUT="1/64" COM_SPORTSMANAGER_ROUND_OF_128_SHORTCUT="1/64"
COM_SPORTSMANAGER_DAY_0_SHORTCUT="So." COM_SPORTSMANAGER_DAY_0_SHORTCUT="So."
COM_SPORTSMANAGER_DAY_1_SHORTCUT="Mo." COM_SPORTSMANAGER_DAY_1_SHORTCUT="Mo."
@@ -151,9 +157,12 @@ COM_SPORTSMANAGER_DEFEAT="Niederlage"
COM_SPORTSMANAGER_DEFEATS="Niederlagen" COM_SPORTSMANAGER_DEFEATS="Niederlagen"
COM_SPORTSMANAGER_DEFEATS_SHORTCUT="N" COM_SPORTSMANAGER_DEFEATS_SHORTCUT="N"
COM_SPORTSMANAGER_GOALS="Tore" COM_SPORTSMANAGER_GOALS="Tore"
COM_SPORTSMANAGER_SETS="S&auml;tze" COM_SPORTSMANAGER_GOALS_SHORTCUT="T"
COM_SPORTSMANAGER_SETS="Sätze"
COM_SPORTSMANAGER_SETS_DRAWN="Unentschiedene Sätze: %d"
COM_SPORTSMANAGER_POINT="Punkt" COM_SPORTSMANAGER_POINT="Punkt"
COM_SPORTSMANAGER_POINTS="Punkte" COM_SPORTSMANAGER_POINTS="Punkte"
COM_SPORTSMANAGER_SETS_SHORTCUT="S"
COM_SPORTSMANAGER_POINTS_SHORTCUT="P" COM_SPORTSMANAGER_POINTS_SHORTCUT="P"
COM_SPORTSMANAGER_ONE_POINT="1 Punkt" COM_SPORTSMANAGER_ONE_POINT="1 Punkt"
COM_SPORTSMANAGER_NUMBER_POINTS="%d Punkte" COM_SPORTSMANAGER_NUMBER_POINTS="%d Punkte"
@@ -164,8 +173,8 @@ COM_SPORTSMANAGER_GAME_POINTS_SHORTCUT="SP"
COM_SPORTSMANAGER_SUFFIX_ONE_TEAM=" (eine Mannschaft)" COM_SPORTSMANAGER_SUFFIX_ONE_TEAM=" (eine Mannschaft)"
COM_SPORTSMANAGER_SUFFIX_TEAMS_TOGETHER=" (Mannschaften zusammen)" COM_SPORTSMANAGER_SUFFIX_TEAMS_TOGETHER=" (Mannschaften zusammen)"
COM_SPORTSMANAGER_DIFFERENCE="Differenz" COM_SPORTSMANAGER_DIFFERENCE="Differenz"
COM_SPORTSMANAGER_DIFFERENCE_IN_POINTS="Punktedifferenz" COM_SPORTSMANAGER_DIFFERENCE_IN_POINTS="Differenz Spielpunkte"
COM_SPORTSMANAGER_POINTS_RATIO="Punkteverh&auml;ltnis" COM_SPORTSMANAGER_POINTS_RATIO="Verh&auml;ltnis Spielpunkte"
COM_SPORTSMANAGER_SCHEDULE_DATE="Zeitpunkt" COM_SPORTSMANAGER_SCHEDULE_DATE="Zeitpunkt"
COM_SPORTSMANAGER_TEAM_HOME="Heim" COM_SPORTSMANAGER_TEAM_HOME="Heim"
COM_SPORTSMANAGER_TEAM_VISITOR="Gast" COM_SPORTSMANAGER_TEAM_VISITOR="Gast"
@@ -259,6 +268,7 @@ COM_SPORTSMANAGER_IN="in"
COM_SPORTSMANAGER_NATIONAL="Nationale" COM_SPORTSMANAGER_NATIONAL="Nationale"
COM_SPORTSMANAGER_INTERNATIONAL="Internationale" COM_SPORTSMANAGER_INTERNATIONAL="Internationale"
COM_SPORTSMANAGER_PLAYER_NUMBER_SHORT="Spielernr." COM_SPORTSMANAGER_PLAYER_NUMBER_SHORT="Spielernr."
COM_SPORTSMANAGER_ASSOCIATION_SHORT_NAME="Verbands-Kürzel"
COM_SPORTSMANAGER_BASIC_PLAYER_NUMBER_SHORT="Basis-Spielernr." COM_SPORTSMANAGER_BASIC_PLAYER_NUMBER_SHORT="Basis-Spielernr."
COM_SPORTSMANAGER_MESSAGES="Meldungen" COM_SPORTSMANAGER_MESSAGES="Meldungen"
COM_SPORTSMANAGER_TOURNAMENT_PLACEMENT="Turnierplatzierungen" COM_SPORTSMANAGER_TOURNAMENT_PLACEMENT="Turnierplatzierungen"
@@ -289,11 +299,9 @@ COM_SPORTSMANAGER_REQUEST_MESSAGE_PLURAL="Es m&uuml;ssen mindestens %d Termine v
COM_SPORTSMANAGER_REJECT_SHIFT="Verschiebung ablehnen" COM_SPORTSMANAGER_REJECT_SHIFT="Verschiebung ablehnen"
COM_SPORTSMANAGER_TO="bis" COM_SPORTSMANAGER_TO="bis"
COM_SPORTSMANAGER_PLAYER_STATISTICS="Spielerstatistiken" COM_SPORTSMANAGER_PLAYER_STATISTICS="Spielerstatistiken"
COM_SPORTSMANAGER_PERFORMANCE_INDEX="Leistungsindex"
COM_SPORTSMANAGER_PERFORMANCE_INDEX_SHORTCUT="LI"
COM_SPORTSMANAGER_WON="gewonnen" COM_SPORTSMANAGER_WON="gewonnen"
COM_SPORTSMANAGER_LOST="verloren" COM_SPORTSMANAGER_LOST="verloren"
COM_SPORTSMANAGER_RATE="Quote" COM_SPORTSMANAGER_RATE="Siegquote"
COM_SPORTSMANAGER_RATE_SHORTCUT="Q" COM_SPORTSMANAGER_RATE_SHORTCUT="Q"
COM_SPORTSMANAGER_NO_CLUB="Kein Verein" COM_SPORTSMANAGER_NO_CLUB="Kein Verein"
COM_SPORTSMANAGER_RATING="Wertung" COM_SPORTSMANAGER_RATING="Wertung"
@@ -311,6 +319,11 @@ COM_SPORTSMANAGER_FOR_OTHER_CONTACT="F&uuml;r andere Ansprechpartner"
COM_SPORTSMANAGER_DATES_REGISTERED_USERS="Termine beantragten durch angemeldete Benutzer" COM_SPORTSMANAGER_DATES_REGISTERED_USERS="Termine beantragten durch angemeldete Benutzer"
COM_SPORTSMANAGER_VIEW_ELO_RATING="Elo-Wertung anzeigen" COM_SPORTSMANAGER_VIEW_ELO_RATING="Elo-Wertung anzeigen"
COM_SPORTSMANAGER_VIEW_SPORTSMANAGER_LIZENZ="Lizenz anzeigen" COM_SPORTSMANAGER_VIEW_SPORTSMANAGER_LIZENZ="Lizenz anzeigen"
COM_SPORTSMANAGER_VIEW_LEAST_MEMBER_COUNT="Mindest Mitgliederzahl zeigen (Vereine)"
COM_SPORTSMANAGER_SHOW_ORGANISATION="Spalte Verband zeigen (Vereine)"
COM_SPORTSMANAGER_SHOW_MEMBER_COUNT="Spalte Mitglieder Zeigen (Vereine)"
COM_SPORTSMANAGER_SHOW_TOURNAMENT_BRACKET="Turnierbaum anzeigen"
COM_SPORTSMANAGER_USE_DISCIPLINARY_FINE="Ordnungsstrafen verwenden"
COM_SPORTSMANAGER_PLAYER_DETAILS="Spielerdetails" COM_SPORTSMANAGER_PLAYER_DETAILS="Spielerdetails"
COM_SPORTSMANAGER_PLAYER_LIST_DETAILS="Spielerliste/-details" COM_SPORTSMANAGER_PLAYER_LIST_DETAILS="Spielerliste/-details"
COM_SPORTSMANAGER_PLAYER_EDIT="Spielerdaten durch Organisations-/Vereinsansprechpartner bearbeiten" COM_SPORTSMANAGER_PLAYER_EDIT="Spielerdaten durch Organisations-/Vereinsansprechpartner bearbeiten"
@@ -353,6 +366,7 @@ COM_SPORTSMANAGER_STATISTIK="Statistik"
COM_SPORTSMANAGER_PLAYERS_ACTIVE="Spieler aktiv" COM_SPORTSMANAGER_PLAYERS_ACTIVE="Spieler aktiv"
COM_SPORTSMANAGER_RESTRICTED_PLAYERS="Spieler eingeschr&auml;nkt" COM_SPORTSMANAGER_RESTRICTED_PLAYERS="Spieler eingeschr&auml;nkt"
COM_SPORTSMANAGER_PLAYER_PASSIV="Spieler passiv" COM_SPORTSMANAGER_PLAYER_PASSIV="Spieler passiv"
COM_SPORTSMANAGER_PLAYER_UNATTACHED="Spieler vereinslos"
COM_SPORTSMANAGER_MEN_ACTIVE="Herren aktiv" COM_SPORTSMANAGER_MEN_ACTIVE="Herren aktiv"
COM_SPORTSMANAGER_WOMEN_ACTIVE="Damen aktiv" COM_SPORTSMANAGER_WOMEN_ACTIVE="Damen aktiv"
COM_SPORTSMANAGER_JUNIOR_ACTIVE="Junioren aktiv" COM_SPORTSMANAGER_JUNIOR_ACTIVE="Junioren aktiv"
@@ -380,8 +394,11 @@ COM_SPORTSMANAGER_MEMBER_STATUS="Mitgliedsstatus"
COM_SPORTSMANAGER_ACTIVE="Aktiv" COM_SPORTSMANAGER_ACTIVE="Aktiv"
COM_SPORTSMANAGER_RESTRICTED="Eingeschränkt" COM_SPORTSMANAGER_RESTRICTED="Eingeschränkt"
COM_SPORTSMANAGER_BEATEN="Ausgetreten" COM_SPORTSMANAGER_BEATEN="Ausgetreten"
COM_SPORTSMANAGER_HIDE="Verstecken"
COM_SPORTSMANAGER_PASSIVE="Passiv" COM_SPORTSMANAGER_PASSIVE="Passiv"
COM_SPORTSMANAGER_BEATEN_CLUB="Verein ausgetreten" COM_SPORTSMANAGER_BEATEN_CLUB="Verein ausgetreten"
COM_SPORTSMANAGER_ACTIVE_CLUBS="Aktive Vereine"
COM_SPORTSMANAGER_INACTIVE_CLUBS="Inaktive Vereine"
COM_SPORTSMANAGER_SINGLE_SEED="Elo-Startwert Einzel" COM_SPORTSMANAGER_SINGLE_SEED="Elo-Startwert Einzel"
COM_SPORTSMANAGER_DOUBLE_SEED="Elo-Startwert Doppel" COM_SPORTSMANAGER_DOUBLE_SEED="Elo-Startwert Doppel"
COM_SPORTSMANAGER_PLAYER_EXPORT="Spieler: Exportieren" COM_SPORTSMANAGER_PLAYER_EXPORT="Spieler: Exportieren"
@@ -402,10 +419,11 @@ COM_SPORTSMANAGER_EXPORT="Exportieren"
COM_SPORTSMANAGER_INTERNATIONAL_PLAYERS="Spieler (international)" COM_SPORTSMANAGER_INTERNATIONAL_PLAYERS="Spieler (international)"
COM_SPORTSMANAGER_COUNTRY_CODE="Landeskennung" COM_SPORTSMANAGER_COUNTRY_CODE="Landeskennung"
COM_SPORTSMANAGER_IMPORT="Importieren" COM_SPORTSMANAGER_IMPORT="Importieren"
COM_SPORTSMANAGER_IMPORT_MESSAGE="Im Import sind ausschlie&szlig;lich Spielerdaten zum Verein %s enthalten. Soll ausschlie&szlig;lich der Spielerbestand des einen Vereins aktualisiert werden, muss der zugeh&ouml;rige Verein unten ausgew&auml;hlt werden. Beinhaltet der Import den gesamten Spielerbestand einer Organisation, muss die zugeh&ouml;rige Organisation gew&auml;hlt werden." COM_SPORTSMANAGER_IMPORT_MESSAGE="Im Import sind ausschlie&szlig;lich Spielerdaten zum Verein %s enthalten. Soll ausschlie&szlig;lich der Spielerbestand des einen Vereins aktualisiert werden, muss der zugeh&ouml;rige Verein unten ausgew&auml;hlt werden. Beinhaltet der Import den gesamten Spielerbestand einer Organisation, muss die zugeh&ouml;rige Organisation gew&auml;hlt werden.<br />Bei schon vorhandener Lizenznummer wird die Lizenznummer und das Geburtsjahr nicht &uuml;berschrieben!"
COM_SPORTSMANAGER_CHECK="Pr&uuml;fen" COM_SPORTSMANAGER_CHECK="Pr&uuml;fen"
COM_SPORTSMANAGER_IMPORT_CONFLICTS_MESSAGE="Im Import sind Konflikte enthalten, die im Vorfeld manuell beseitigt werden müssen." COM_SPORTSMANAGER_IMPORT_CONFLICTS_MESSAGE="Im Import sind Fehler oder Konflikte enthalten, die im Vorfeld manuell beseitigt werden müssen."
COM_SPORTSMANAGER_IMPORT_DUPLICATE_MESSAGE="Versuch, Spielernr. auf eine bereits für einen anderen Spieler vergebene Spielernr. zu ändern" COM_SPORTSMANAGER_IMPORT_DUPLICATE_MESSAGE="Versuch, Spielernr. auf eine bereits für einen anderen Spieler vergebene Spielernr. zu ändern"
COM_SPORTSMANAGER_IMPORT_WRONG_FORMAT_PLAYERNUMBER="Eine oder mehrere Spielernummer enthalten ein ung&uuml;ltiges Format"
COM_SPORTSMANAGER_NAME2="Name" COM_SPORTSMANAGER_NAME2="Name"
COM_SPORTSMANAGER_DATA_IMPORT_ABORT_MESSAGE="Der Import wird abgebrochen, da Konflikte bei den zu importierenden Spielerdaten bestehen. Bitte kontaktiere einen Moderator und sende dabei die Importdatei mit!" COM_SPORTSMANAGER_DATA_IMPORT_ABORT_MESSAGE="Der Import wird abgebrochen, da Konflikte bei den zu importierenden Spielerdaten bestehen. Bitte kontaktiere einen Moderator und sende dabei die Importdatei mit!"
COM_SPORTSMANAGER_DATA_IMPORT_NO_CONFLICTS="Es bestehen keine Konflikte bei den zu importierenden Spielerdaten." COM_SPORTSMANAGER_DATA_IMPORT_NO_CONFLICTS="Es bestehen keine Konflikte bei den zu importierenden Spielerdaten."
@@ -474,18 +492,25 @@ COM_SPORTSMANAGER_GAME_DOUBLES2="Doppel-Spiel"
COM_SPORTSMANAGER_GAME_DOUBLES_IDENTICAL="Doppel-Spiel identisch" COM_SPORTSMANAGER_GAME_DOUBLES_IDENTICAL="Doppel-Spiel identisch"
COM_SPORTSMANAGER_GAME_DOUBLES_SEPARATELY="Doppel-Spiel separat" COM_SPORTSMANAGER_GAME_DOUBLES_SEPARATELY="Doppel-Spiel separat"
COM_SPORTSMANAGER_ONE="Einer" COM_SPORTSMANAGER_ONE="Einer"
COM_SPORTSMANAGER_MULTIPLE="Mehrere" COM_SPORTSMANAGER_MULTIPLE="Mehrere nur der Satzstand"
COM_SPORTSMANAGER_HOME_EXCHANGE="Heimtausch" COM_SPORTSMANAGER_HOME_EXCHANGE="Heimtausch"
COM_SPORTSMANAGER_NOT_ALLOWED="Nicht zulässig" COM_SPORTSMANAGER_NOT_ALLOWED="Nicht zulässig"
COM_SPORTSMANAGER_ALLOWED="Zulässig" COM_SPORTSMANAGER_ALLOWED="Zulässig"
COM_SPORTSMANAGER_PLAYER_NAME="Spielername" COM_SPORTSMANAGER_PLAYER_NAME="Spielername"
COM_SPORTSMANAGER_PLAYERS_SEARCH_SPECIAL="(Spezialsuche)" COM_SPORTSMANAGER_PLAYERS_SEARCH_SPECIAL="(Spezialsuche)"
COM_SPORTSMANAGER_ADD_SEASON="Saison hinzuf&uuml;gen" COM_SPORTSMANAGER_ADD_SEASON="Saison hinzuf&uuml;gen"
COM_SPORTSMANAGER_GAME_POINTS_GAME="Spielpunkte pro Spiel" COM_SPORTSMANAGER_GAME_POINTS_GAME="Spielpunkte"
COM_SPORTSMANAGER_WIN_1_POINT="Sieg: 1 Punkt" COM_SPORTSMANAGER_WIN_1_POINT="Sieg: 1 Punkt"
COM_SPORTSMANAGER_WIN_2_POINTS="Sieg: 2 Punkte, Unentschieden: 1 Punkt" COM_SPORTSMANAGER_WIN_2_POINTS="Sieg: 2 Punkte, Unentschieden: 1 Punkt"
COM_SPORTSMANAGER_WIN_1_POINT_PER_SET="Je Satz: Sieg 1 Punkt"
COM_SPORTSMANAGER_WIN_2_POINTS_PER_SET="Je Satz: Sieg 2 Punkte, Unentschieden 1 Punkt"
COM_SPORTSMANAGER_WIN_3_POINTS_PER_SET="Je Satz: Sieg 3 Punkte, Unentschieden 1 Punkt"
COM_SPORTSMANAGER_GAME_POINTS_FOR_GAME="Für das ganze Spiel"
COM_SPORTSMANAGER_GAME_POINTS_FOR_SET="Für jeden Satz einzeln"
COM_SPORTSMANAGER_WIN_3_POINTS="Sieg: 3 Punkte, Unentschieden: 1 Punkt" COM_SPORTSMANAGER_WIN_3_POINTS="Sieg: 3 Punkte, Unentschieden: 1 Punkt"
COM_SPORTSMANAGER_MEETING_CONCLUDED_AT="Begegnung abgeschlossen bei" COM_SPORTSMANAGER_MEETING_CONCLUDED_AT="Begegnung abgeschlossen bei"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK="Spiele in Spielerstatistik"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK_ALL="Alle Spiele"
COM_SPORTSMANAGER_GENERALLY="Allgemein" COM_SPORTSMANAGER_GENERALLY="Allgemein"
COM_SPORTSMANAGER_TYPE="Typ" COM_SPORTSMANAGER_TYPE="Typ"
COM_SPORTSMANAGER_ELO_MIN="Elo min." COM_SPORTSMANAGER_ELO_MIN="Elo min."
@@ -502,7 +527,6 @@ COM_SPORTSMANAGER_ADD_POINTS_TABLE="Punktetabelle hinzuf&uuml;gen"
COM_SPORTSMANAGER_ADD_FUNCTION="Funktion hinzuf&uuml;gen" COM_SPORTSMANAGER_ADD_FUNCTION="Funktion hinzuf&uuml;gen"
COM_SPORTSMANAGER_PARTICIPANT="Teilnehmer" COM_SPORTSMANAGER_PARTICIPANT="Teilnehmer"
COM_SPORTSMANAGER_FUNCTION="Funktion" COM_SPORTSMANAGER_FUNCTION="Funktion"
COM_SPORTSMANAGER_MULTIPLIER="Multiplikator"
COM_SPORTSMANAGER_MAXIMUM="maximal" COM_SPORTSMANAGER_MAXIMUM="maximal"
COM_SPORTSMANAGER_CONTRACTION="K&uuml;rzel" COM_SPORTSMANAGER_CONTRACTION="K&uuml;rzel"
COM_SPORTSMANAGER_ELIGIBLE_ORGANIZERS="Berechtigte f&uuml;r Veranstalter" COM_SPORTSMANAGER_ELIGIBLE_ORGANIZERS="Berechtigte f&uuml;r Veranstalter"
@@ -536,9 +560,23 @@ COM_SPORTSMANAGER_FULL_RATING="Volle Wertung"
COM_SPORTSMANAGER_NO_RATING="Keine Wertung" COM_SPORTSMANAGER_NO_RATING="Keine Wertung"
COM_SPORTSMANAGER_TEAM_COMPETITIONS="Mannschaftswettbewerbe" COM_SPORTSMANAGER_TEAM_COMPETITIONS="Mannschaftswettbewerbe"
COM_SPORTSMANAGER_TABLE_SUMMARY="Tabellenwertung" COM_SPORTSMANAGER_TABLE_SUMMARY="Tabellenwertung"
COM_SPORTSMANAGER_HEAD_TO_HEAD_RECORD="Direkter Vergleich"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_NOT="deaktiviert"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_POINTS="bei gleicher Punktzahl"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_SETS="bei gleicher Punktzahl, Satzpunkte"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_GOALS="bei gleicher Punktzahl, Satzpunkte, Tore"
COM_SPORTSMANAGER_POINTS_WON_LOST_DIFFERENCE="Spielpunkte gewonnen, Spielpunkte verloren, Punktedifferenz" COM_SPORTSMANAGER_POINTS_WON_LOST_DIFFERENCE="Spielpunkte gewonnen, Spielpunkte verloren, Punktedifferenz"
COM_SPORTSMANAGER_PERFORMANCE_INDEX="Leistungsindex (SP+ * SP+ * 100) / (SP+ + SP-), Spielpunkte gewonnen, ..." COM_SPORTSMANAGER_PERFORMANCE_INDEX0="Spielpunkte gewonnen, Spielpunkte verloren, Punktedifferenz"
COM_SPORTSMANAGER_PERFORMANCE_INDEX1="Leistungsindex (SP+ * SP+ * 100) / (SP+ + SP-), Spielpunkte gewonnen, ..."
COM_SPORTSMANAGER_PERFORMANCE_INDEX2="Leistungsindex (S * P+ * 10) / (P+ + P-), Spielpunkte gewonnen, ..." COM_SPORTSMANAGER_PERFORMANCE_INDEX2="Leistungsindex (S * P+ * 10) / (P+ + P-), Spielpunkte gewonnen, ..."
COM_SPORTSMANAGER_PERFORMANCE_INDEX3="Race Performance Index (Siege*2 + Unentschieden + Tordifferenz)"
COM_SPORTSMANAGER_PERFORMANCE_INDEX4="Effizienzindex (T+ / (T+ + T-))"
COM_SPORTSMANAGER_PERFORMANCE_INDEX5="Punkteschnitt (P+ / Anzahl Sätze)"
COM_SPORTSMANAGER_PERFORMANCE_SHORT1="LI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT2="LI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT3="RPI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT4="EI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT5="AVG"
COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS="Einzelstatistik aus allen Spielen" COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS="Einzelstatistik aus allen Spielen"
COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_SINGLES="Einzelstatistik aus Einzel-Spielen" COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_SINGLES="Einzelstatistik aus Einzel-Spielen"
COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_DOUBLES="Einzelstatistik aus Doppel-Spielen" COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_DOUBLES="Einzelstatistik aus Doppel-Spielen"
@@ -562,7 +600,7 @@ COM_SPORTSMANAGER_PRIVATE_PLAYER_DATA="Private Spielerdaten in Vereins- und Mann
COM_SPORTSMANAGER_ASSOCIATIONS_MEMBERSHIPS_MANAGE="Vereine und Mitgliedschaften verwalten" COM_SPORTSMANAGER_ASSOCIATIONS_MEMBERSHIPS_MANAGE="Vereine und Mitgliedschaften verwalten"
COM_SPORTSMANAGER_MANAGE_CLASSIFICATIONS="Einstufungen verwalten" COM_SPORTSMANAGER_MANAGE_CLASSIFICATIONS="Einstufungen verwalten"
COM_SPORTSMANAGER_MANAGE_TEAM_PLANS="Mannschaftsspielpläne verwalten" COM_SPORTSMANAGER_MANAGE_TEAM_PLANS="Mannschaftsspielpläne verwalten"
COM_SPORTSMANAGER_MANAGE_RULES_POSTPONEMENT="Verschieberegeln verwalten" COM_SPORTSMANAGER_MANAGE_RULES_POSTPONEMENT="Spielverlegungen/Verschieberegeln verwalten"
COM_SPORTSMANAGER_MANAGE_VENUES="Spielorte verwalten" COM_SPORTSMANAGER_MANAGE_VENUES="Spielorte verwalten"
COM_SPORTSMANAGER_MANAGE_TEAM_COMPETITIONS="Mannschaftswettbewerbe verwalten" COM_SPORTSMANAGER_MANAGE_TEAM_COMPETITIONS="Mannschaftswettbewerbe verwalten"
COM_SPORTSMANAGER_MANAGE_PLAYER_STATISTICS="Spielerstastistiken verwalten" COM_SPORTSMANAGER_MANAGE_PLAYER_STATISTICS="Spielerstastistiken verwalten"
@@ -604,7 +642,10 @@ COM_SPORTSMANAGER_ONLY_DETAILED_RATING_POINT_DIFFERENCE="Nur Detailwertung nach
COM_SPORTSMANAGER_ONLY_DETAILED_POINTS_AFTER_POINTSRATE="Nur Detailwertung nach Punktequote" COM_SPORTSMANAGER_ONLY_DETAILED_POINTS_AFTER_POINTSRATE="Nur Detailwertung nach Punktequote"
COM_SPORTSMANAGER_KO_SIMPLE_FULL="K.O. (einfach oder vollstaendige Ausspielung aller Plaetze)" COM_SPORTSMANAGER_KO_SIMPLE_FULL="K.O. (einfach oder vollstaendige Ausspielung aller Plaetze)"
COM_SPORTSMANAGER_MANUAL_PRO_TEAMS="Manuell (pro Mannschaft)" COM_SPORTSMANAGER_MANUAL_PRO_TEAMS="Manuell (pro Mannschaft)"
COM_SPORTSMANAGER_CUP_DRAW_EVERY_ROUND="Pokal: Jede Runde wird neu gelost"
COM_SPORTSMANAGER_CUP_USING_SEEDING_LIST="Pokal: Losen einer Setzliste"
COM_SPORTSMANAGER_SUBDIVISION="Unterteilung" COM_SPORTSMANAGER_SUBDIVISION="Unterteilung"
COM_SPORTSMANAGER_SHOW_MATCHDAY_TITLE="Titel von Spieltag zeigen"
COM_SPORTSMANAGER_ELO_RATING="ELO-Wertung" COM_SPORTSMANAGER_ELO_RATING="ELO-Wertung"
COM_SPORTSMANAGER_ELIGIBLE_FOR_EVENT="Berechtigte f&uuml;r Veranstaltung" COM_SPORTSMANAGER_ELIGIBLE_FOR_EVENT="Berechtigte f&uuml;r Veranstaltung"
COM_SPORTSMANAGER_TITLE_LOGO="Titel-Logo" COM_SPORTSMANAGER_TITLE_LOGO="Titel-Logo"
@@ -632,6 +673,9 @@ COM_SPORTSMANAGER_GAMEDAY="Spieltag"
COM_SPORTSMANAGER_GAMEDAYS="Spieltage" COM_SPORTSMANAGER_GAMEDAYS="Spieltage"
COM_SPORTSMANAGER_ROUND="Runde" COM_SPORTSMANAGER_ROUND="Runde"
COM_SPORTSMANAGER_ROUNDS="Runden" COM_SPORTSMANAGER_ROUNDS="Runden"
COM_SPORTSMANAGER_ROUND_TITLE="Runde Bezeichnung"
COM_SPORTSMANAGER_DRAW_FOR_HOME="Heimrecht auslosen"
COM_SPORTSMANAGER_MATCH_PLACE3="Spiel um Platz 3"
COM_SPORTSMANAGER_MONTH="Monat" COM_SPORTSMANAGER_MONTH="Monat"
COM_SPORTSMANAGER_MONTHS="Monate" COM_SPORTSMANAGER_MONTHS="Monate"
COM_SPORTSMANAGER_PLAYER_FROM_TEAM="Spieler von Mannschaft" COM_SPORTSMANAGER_PLAYER_FROM_TEAM="Spieler von Mannschaft"
@@ -647,8 +691,14 @@ COM_SPORTSMANAGER_SO_FAR="bisher"
COM_SPORTSMANAGER_PLACEMENT_AREA="Platzierungsbereich" COM_SPORTSMANAGER_PLACEMENT_AREA="Platzierungsbereich"
COM_SPORTSMANAGER_IMAGE_WITHIN_TEAM="Bild innerhalb Mannschaft" COM_SPORTSMANAGER_IMAGE_WITHIN_TEAM="Bild innerhalb Mannschaft"
COM_SPORTSMANAGER_ADD_MEETING="Begegnung hinzuf&uuml;gen" COM_SPORTSMANAGER_ADD_MEETING="Begegnung hinzuf&uuml;gen"
COM_SPORTSMANAGER_GAMEDAY_GENERATION="Spieltag erzeugen"
COM_SPORTSMANAGER_ROUND_GENERATION="Runde erzeugen" COM_SPORTSMANAGER_ROUND_GENERATION="Runde erzeugen"
COM_SPORTSMANAGER_CUP_ROUND_GENERATION="Pokalrunde auslosen"
COM_SPORTSMANAGER_GENERATE_GROUP_GAME="Gruppenspiele erzeugen" COM_SPORTSMANAGER_GENERATE_GROUP_GAME="Gruppenspiele erzeugen"
COM_SPORTSMANAGER_IMPORT_GROUP_GAME="Gruppenspiele importieren"
COM_SPORTSMANAGER_IMPORT_GROUP_GAME2="Gruppenspiele: Importieren"
COM_SPORTSMANAGER_IMPORT_GROUP_GAME_IMPORTED="Begegnungen wurden importiert"
COM_SPORTSMANAGER_IMPORT_GROUP_GAME_CREATED="Begegnungen wurden erstellt"
COM_SPORTSMANAGER_REMOVE_ALL_ENCOUNTERS="Willst du wirklich alle Begegnungen entfernen?" COM_SPORTSMANAGER_REMOVE_ALL_ENCOUNTERS="Willst du wirklich alle Begegnungen entfernen?"
COM_SPORTSMANAGER_REMOVE_ALL_MATCHES="Alle Begegnungen entfernen" COM_SPORTSMANAGER_REMOVE_ALL_MATCHES="Alle Begegnungen entfernen"
COM_SPORTSMANAGER_HOME_TEAM="Heimteam" COM_SPORTSMANAGER_HOME_TEAM="Heimteam"
@@ -694,6 +744,7 @@ COM_SPORTSMANAGER_NUMBER_DAYS="%d Tage"
COM_SPORTSMANAGER_CALENDAR_WEEK="Kalenderwoche" COM_SPORTSMANAGER_CALENDAR_WEEK="Kalenderwoche"
COM_SPORTSMANAGER_CALENDAR_WEEK_SHORTCUT="KW" COM_SPORTSMANAGER_CALENDAR_WEEK_SHORTCUT="KW"
COM_SPORTSMANAGER_PAIRING="Paarung" COM_SPORTSMANAGER_PAIRING="Paarung"
COM_SPORTSMANAGER_SETTING="Setzen"
COM_SPORTSMANAGER_PAIRINGS="Paarungen" COM_SPORTSMANAGER_PAIRINGS="Paarungen"
COM_SPORTSMANAGER_INTERMITTENT="Aussetzend" COM_SPORTSMANAGER_INTERMITTENT="Aussetzend"
COM_SPORTSMANAGER_MAXIMUM_SETS="S&auml;tze maximal" COM_SPORTSMANAGER_MAXIMUM_SETS="S&auml;tze maximal"
@@ -770,6 +821,7 @@ COM_SPORTSMANAGER_FEDERAL_STATES="Bundesl&auml;nder"
COM_SPORTSMANAGER_STATES="L&auml;nder" COM_SPORTSMANAGER_STATES="L&auml;nder"
COM_SPORTSMANAGER_YEAR="Jahr" COM_SPORTSMANAGER_YEAR="Jahr"
COM_SPORTSMANAGER_ADDITION="Zusatz" COM_SPORTSMANAGER_ADDITION="Zusatz"
COM_SPORTSMANAGER_LOCATION="Ort"
COM_SPORTSMANAGER_STATE="Land" COM_SPORTSMANAGER_STATE="Land"
COM_SPORTSMANAGER_FEDERAL_="Bundes-" COM_SPORTSMANAGER_FEDERAL_="Bundes-"
COM_SPORTSMANAGER_INFO="Info" COM_SPORTSMANAGER_INFO="Info"
@@ -783,7 +835,6 @@ COM_SPORTSMANAGER_APPLIED_FOR="Beantragt"
COM_SPORTSMANAGER_DECLINED="Abgelehnt" COM_SPORTSMANAGER_DECLINED="Abgelehnt"
COM_SPORTSMANAGER_DATE_DETAILS="Termin: Details" COM_SPORTSMANAGER_DATE_DETAILS="Termin: Details"
COM_SPORTSMANAGER_ADDITIONS="Zus&auml;tze" COM_SPORTSMANAGER_ADDITIONS="Zus&auml;tze"
COM_SPORTSMANAGER_ADDITIONAL_INFORMATION="Weitere Informationen"
COM_SPORTSMANAGER_PUBLIC_EMAIL="E-Mail &ouml;ffentlich" COM_SPORTSMANAGER_PUBLIC_EMAIL="E-Mail &ouml;ffentlich"
COM_SPORTSMANAGER_EMAIL_WITH_CHANGES="E-Mail bei &Auml;nderungen" COM_SPORTSMANAGER_EMAIL_WITH_CHANGES="E-Mail bei &Auml;nderungen"
COM_SPORTSMANAGER_ACTION_TYPE="Aktionstyp" COM_SPORTSMANAGER_ACTION_TYPE="Aktionstyp"
@@ -827,7 +878,6 @@ COM_SPORTSMANAGER_REMOVE_STATE_REALLY="Willst du das Land wirklich entfernen?"
COM_SPORTSMANAGER_DATES_STATE="Termine Land" COM_SPORTSMANAGER_DATES_STATE="Termine Land"
COM_SPORTSMANAGER_RENAME_APPOINTMENTS_STATE="Termine mit dem bisherigen Land umbenennen" COM_SPORTSMANAGER_RENAME_APPOINTMENTS_STATE="Termine mit dem bisherigen Land umbenennen"
COM_SPORTSMANAGER_FINAL_RANKING="FINAL RANKING" COM_SPORTSMANAGER_FINAL_RANKING="FINAL RANKING"
COM_SPORTSMANAGER_HOME_TEAM2="Heimmanschaft"
COM_SPORTSMANAGER_RESULTS2="Resultat" COM_SPORTSMANAGER_RESULTS2="Resultat"
COM_SPORTSMANAGER_NO_GAMES="Keine Spiele" COM_SPORTSMANAGER_NO_GAMES="Keine Spiele"
COM_SPORTSMANAGER_END_GAME="Endspiel" COM_SPORTSMANAGER_END_GAME="Endspiel"
@@ -860,6 +910,9 @@ COM_SPORTSMANAGER_INITIAL_APPOINTMENT_SUGGESTIONS="Initiale Terminvorschl&auml;g
COM_SPORTSMANAGER_REQUESTING_TEAM="Beantragende Mannschaft" COM_SPORTSMANAGER_REQUESTING_TEAM="Beantragende Mannschaft"
COM_SPORTSMANAGER_OPPONENT_TEAM="Gegnerische Mannschaft" COM_SPORTSMANAGER_OPPONENT_TEAM="Gegnerische Mannschaft"
COM_SPORTSMANAGER_AGAINST_PROPOSALS_ALLOWED="Gegensvorschl&auml;ge zul&auml;ssig" COM_SPORTSMANAGER_AGAINST_PROPOSALS_ALLOWED="Gegensvorschl&auml;ge zul&auml;ssig"
COM_SPORTSMANAGER_REASON_REQUIRED="Begr&uuml;ndung erforderlich"
COM_SPORTSMANAGER_CLUB_ENTITLEMENT="Berechtigung Vereine"
COM_SPORTSMANAGER_ASSOCIATION_ENTITLEMENT="Berechtigung Verband"
COM_SPORTSMANAGER_LEAD_TIME="Vorlaufzeit" COM_SPORTSMANAGER_LEAD_TIME="Vorlaufzeit"
COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MINIMAL="Terminvorschl&auml;ge minimal" COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MINIMAL="Terminvorschl&auml;ge minimal"
COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MAXIMUM="Terminvorschl&auml;ge maximal" COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MAXIMUM="Terminvorschl&auml;ge maximal"
@@ -869,6 +922,11 @@ COM_SPORTSMANAGER_OPTIONAL_BUT_SAME_IN_DOUBLES="Optional, aber im Doppel keiner
COM_SPORTSMANAGER_REQUIRED="Erforderlich" COM_SPORTSMANAGER_REQUIRED="Erforderlich"
COM_SPORTSMANAGER_RESULT_ONLY="Nur Ergebnis" COM_SPORTSMANAGER_RESULT_ONLY="Nur Ergebnis"
COM_SPORTSMANAGER_GAME_NUMBER="Spiel %d" COM_SPORTSMANAGER_GAME_NUMBER="Spiel %d"
COM_SPORTSMANAGER_LABEL_GAME_NUMBER="Spiel Nr"
COM_SPORTSMANAGER_LABEL_GAME_TITLE="Spieltag Titel"
COM_SPORTSMANAGER_EXPLICIT_PENALTIES="Explizite Strafen"
COM_SPORTSMANAGER_EXPLICIT_PENALTIES_EMAIL_SUBJECT="%s: Strafpunkte erhalten"
COM_SPORTSMANAGER_EXPLICIT_PENALTIES_EMAIL_BODY="%s wurden %f Strafpunkte zugeteilt mit der Begründung: %s"
COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_SUBJECT="%s vs %s: Spieltermin verlegen" COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_SUBJECT="%s vs %s: Spieltermin verlegen"
COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_BODY="Zur Begegnung %s gegen %s am %s in %s wird von %s der Spieltermin verschoben.\n\nAlternative Termine:\n\n" COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_BODY="Zur Begegnung %s gegen %s am %s in %s wird von %s der Spieltermin verschoben.\n\nAlternative Termine:\n\n"
COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_REQUESTED_BODY="Zur Begegnung %s gegen %s am %s in %s wird von %s der Spieltermin verschoben.\n\nBitte alternative Termine vorschlagen unter %s" COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_REQUESTED_BODY="Zur Begegnung %s gegen %s am %s in %s wird von %s der Spieltermin verschoben.\n\nBitte alternative Termine vorschlagen unter %s"
@@ -925,3 +983,203 @@ COM_SPORTSMANAGER_RANK="Rang"
; SPIELER BEARBEITEN ; SPIELER BEARBEITEN
COM_SPORTSMANAGER_LIZENZ="Lizenz" COM_SPORTSMANAGER_LIZENZ="Lizenz"
COM_SPORTSMANAGER_ARIA_LABEL_MATCHDAY_SELECT="Wähle einen Spieltag"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_DAY="Wähle den Tag des Begegnungsvorschlags"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_MONTH="Wähle den Monat des Begegnungsvorschlags"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_YEAR="Wähle das Jahr des Begegnungsvorschlags"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_HOUR="Wähle die Stunde des Begegnungsvorschlags"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_MINUTE="Wähle die Minute des Begegnungsvorschlags"
COM_SPORTSMANAGER_ARIA_LABEL_SPECIAL_FILTER="Erweiterter Filter"
COM_SPORTSMANAGER_ARIA_LABEL_PLACE="Ort"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_CLUB="Wähle berechtigten Verein"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_START_MONTH="Monat des Turnierbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_START_YEAR="Jahr des Turnierbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_END_MONTH="Monat des Turnierendes"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_END_YEAR="Jahr des Turnierendes"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_USER="Wähle berechtigten Anwender"
COM_SPORTSMANAGER_ARIA_LABEL_POINTS_GUEST="Punkte Gast"
COM_SPORTSMANAGER_ARIA_LABEL_POINTS_HOME="Punkte Heim"
COM_SPORTSMANAGER_ARIA_LABEL_PLAYER_GUEST="Spieler Gast"
COM_SPORTSMANAGER_ARIA_LABEL_PLAYER_HOME="Spieler Heim"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_MONTH="Wähle den Monat"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_YEAR="Wähle das Jahr"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_HOUR="Wähle eine Stunde"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_MINUTE="Wähle eine Minute"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_GUEST="Spiel Gast"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_HOME="Spiel Heim"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_DOUBLE="Verknüpfung Doppel"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_SINGLE="Verknüpfung Einzel"
COM_SPORTSMANAGER_ARIA_LABEL_PLACEMENT_MIN="Platzierung Min."
COM_SPORTSMANAGER_ARIA_LABEL_PLACEMENT_MAX="Platzierung Max."
COM_SPORTSMANAGER_ARIA_LABEL_PARTICIPANT_MIN="Teilnehmer Min."
COM_SPORTSMANAGER_ARIA_LABEL_PARTICIPANT_MAX="Teilnehmer Max."
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_START_MONTH="Monat des Ranglistenbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_START_YEAR="Jahr des Ranglistenbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_END_MONTH="Monat des Ranglistenendes"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_END_YEAR="Jahr des Ranglistenendes"
COM_SPORTSMANAGER_ARIA_LABEL_MAXIMUM_EVALUATED_COUNT="Maximal gewertete Teilnahmen"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_START_MONTH="Monat des Statistikbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_START_YEAR="Jahr des Statistikbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_END_MONTH="Monat des Statistikendes"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_END_YEAR="Jahr des Statistikendes"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_ORGANIZER="Wähle berechtigten Veranstalter"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_START_MONTH="Monat des Veranstaltungsbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_START_YEAR="Jahr des Veranstaltungsbeginns"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_END_MONTH="Monat des Veranstaltungsendes"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_END_YEAR="Jahr des Veranstaltungsendes"
COM_SPORTSMANAGER_ARIA_LABEL_FIRST_ROUND="Erste Runde"
COM_SPORTSMANAGER_ARIA_LABEL_FIRST_ROUND_TYPE="Erste Runde Typ"
COM_SPORTSMANAGER_ARIA_LABEL_FIRST_ROUND_PLACE="Erste Runde Platzierung"
COM_SPORTSMANAGER_ARIA_LABEL_LAST_ROUND="Letzte Runde"
COM_SPORTSMANAGER_ARIA_LABEL_LAST_ROUND_TYPE="Letzte Runde Typ"
COM_SPORTSMANAGER_ARIA_LABEL_LAST_ROUND_PLACE="Letzte Runde Platzierung"
COM_SPORTSMANAGER_ARIA_LABEL_ROUND_TYPE="Rundentyp"
COM_SPORTSMANAGER_ARIA_LABEL_ROUND_PLACE="Rundenplatzierung"
COM_SPORTSMANAGER_HOME_POINTS="Heim Punkte"
COM_SPORTSMANAGER_GUEST_POINTS="Gast Punkte"
COM_SPORTSMANAGER_ARIA_LABEL_ENCOUNTER_YEAR="Jahr der Begegnung"
COM_SPORTSMANAGER_ARIA_LABEL_PAIRING_TEAM="Team für Paarung"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_COMPETITION="Wähle berechtigten Anwender"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_EVALUATION="Ranking Wertung"
COM_SPORTSMANAGER_ARIA_LABEL_LASTNAME="Nachname"
COM_SPORTSMANAGER_ARIA_LABEL_FIRSTNAME="Vorname"
COM_SPORTSMANAGER_ARIA_LABEL_CLUB="Verein"
COM_SPORTSMANAGER_NUM_REQUESTED_SHIFTS="Verschiebungen"
COM_SPORTSMANAGER_NUM_REQUESTED_SHFITS_TOOLTIP="Spielverschiebungen durch diese Mannschaft"
COM_SPORTSMANAGER_GAME_RESULT_DELAYS="Verzögerung"
COM_SPORTSMANAGER_USE_EMAIL_REMINDERS="Verwende Email Erinnerungen"
COM_SPORTSMANAGER_RULEBOOKS="Regelwerke"
COM_SPORTSMANAGER_RULEBOOK="Regelwerk"
COM_SPORTSMANAGER_RULE_SHORT="SPO"
COM_SPORTSMANAGER_FEE_SHORT="GO"
COM_SPORTSMANAGER_RULE_LONG="Paragraph SPO"
COM_SPORTSMANAGER_FEE_LONG="Paragraph GO"
COM_SPORTSMANAGER_SELECT="Auswahl"
COM_SPORTSMANAGER_NO_SELECT="keine Auswahl"
COM_SPORTSMANAGER_REALLY_REMOVE_RULEBOOK="Willst Du dieses Regelwerk wirklich entfernen?"
COM_SPORTSMANAGER_ADD_RULEBOOK="Regelwerk hinzuf&uuml;gen"
COM_SPORTSMANAGER_DISCIPLINARY_FINES="Ordnungsstrafen"
COM_SPORTSMANAGER_DISCIPLINARY_FINE="Ordnungsstrafe"
COM_SPORTSMANAGER_ISSUE_DISCIPLINARY_FINES="Ordnungsstrafe ausstellen"
COM_SPORTSMANAGER_EDIT_DISCIPLINARY_FINE="Ordnungsstrafe bearbeiten"
COM_SPORTSMANAGER_SEND_DISCIPLINARY_FINE="Ordnungsstrafe versenden"
COM_SPORTSMANAGER_REALLY_REMOVE_DISCIPLINARY_FINES="Willst Du diese Ordnungsstrafe wirklich entfernen?"
COM_SPORTSMANAGER_VIOLATIONS="Verst&ouml;&szlig;e"
COM_SPORTSMANAGER_VIOLATION="Versto&szlig;"
COM_SPORTSMANAGER_ADD_VIOLATION="Versto&szlig; hinzuf&uuml;gen"
COM_SPORTSMANAGER_REALLY_REMOVE_VIOLATION="Willst Du diesen Versto&szlig; wirklich entfernen?"
COM_SPORTSMANAGER_VIOLATION_TEXT="Text"
COM_SPORTSMANAGER_VIOLATION_ADD_TEXT="Zusatztext"
COM_SPORTSMANAGER_FEE="Geb&uuml;hr"
COM_SPORTSMANAGER_ADD_FEE="Zusatzgeb&uuml;hr"
COM_SPORTSMANAGER_SELECTABLE="Ausw&auml;hlbar"
COM_SPORTSMANAGER_TEMPLATE="Vorlage"
COM_SPORTSMANAGER_EMAIL_SUBJECT="Betreff"
COM_SPORTSMANAGER_EMAIL_MESSAGE="Nachricht"
COM_SPORTSMANAGER_EMAIL_TO="An"
COM_SPORTSMANAGER_EMAIL_SEND="E-Mail senden"
COM_SPORTSMANAGER_EMAIL_TEXT_TEMPLATE="Textvorlage"
COM_SPORTSMANAGER_ISSUER="Aussteller"
COM_SPORTSMANAGER_ISSUE_DATE="Ausstelldatum"
COM_SPORTSMANAGER_SENDER="Sender"
COM_SPORTSMANAGER_BILL_ISSUER="Rechnung erstellt"
COM_SPORTSMANAGER_MULTIPLIER="Multiplikator"
COM_SPORTSMANAGER_ADDITIONAL_INFORMATION="Weitere Angaben"
COM_SPORTSMANAGER_EMAIL_WAS_SEND="Die E-Mail wurde erfolgreich versendet"
COM_SPORTSMANAGER_EMAIL_WAS_NOT_SEND="Die E-Mail wurde nicht versendet"
COM_SPORTSMANAGER_OLD_DATE="Alter Termin"
COM_SPORTSMANAGER_NEW_DATE="Neuer Termin"
COM_SPORTSMANAGER_REASON_GAME_APPOINTMENT="Verlegungsgrund"
COM_SPORTSMANAGER_MATCH_RESCHEDULINGS="Spielverlegungen"
COM_SPORTSMANAGER_MATCH_RESCHEDULING="Spielverlegung"
COM_SPORTSMANAGER_MATCH_SWAPPING_HELP="Bei Heimrechttausch gleichen Termin eintragen"
COM_SPORTSMANAGER_NOT_VALID_TIME="Ung&uuml;ltige Uhrzeit"
COM_SPORTSMANAGER_REALLY_MATCH_RESCHEDULING="Willst Du diesen Spielverlegung wirklich entfernen?"
COM_SPORTSMANAGER_REST_DAYS="Ruhetage"
COM_SPORTSMANAGER_ADDITIONAL_INFO="Zusatzinfo"
COM_SPORTSMANAGER_TRAINING_DAYS="Trainingstage"
COM_SPORTSMANAGER_NOT_ACTUALIZED_DATA="Nicht aktualisierte Daten"
COM_SPORTSMANAGER_ASSOCIATION_BODIES="Verbandsorgane"
COM_SPORTSMANAGER_ASSOCIATION_BODY="Verbandsorgan"
COM_SPORTSMANAGER_ADD_ASSOCIATION_BODY="Verbandsorgan hinzuf&uuml;gen"
COM_SPORTSMANAGER_REALLY_REMOVE_ASSOCIATION_BODY="Willst Du dieses Verbandsorgan wirklich entfernen?"
COM_SPORTSMANAGER_INVALID_ASSOCIATION_BODY_NAME="Ung&uuml;ltiger Name f&uuml;r Verbandsorgan!"
COM_SPORTSMANAGER_NAME_NOT_COMPLETE="Der Name ist nicht komplett ausgef&uuml;llt"
COM_SPORTSMANAGER_ADDITIONAL_INFO="Zusatzinfo"
COM_SPORTSMANAGER_USE_HTML="Hier sollte HTML-formatierter Text verwendet werden"
COM_SPORTSMANAGER_REALLY_REMOVE_ASSOCIATION_BODY_MEMBER="M&ouml;chtest du dieses Mitglied des Verbandsorgans wirklich entfernen?"
COM_SPORTSMANAGER_HELP_EDIT_ASSOCIATION_BODY_MEMBER="Wird ein Name aus der Spielerliste ausgew&auml;hlt, werden Nachname und Vorname &uuml;bernommen.<br>Telefon, Mobil, E-Mail werden aus der Spielerliste &uuml;bernommen, wenn sie hier nicht ausgef&uuml;llt sind."
COM_SPORTSMANAGER_HALL_OF_FAME="Hall of Fame"
COM_SPORTSMANAGER_ADD_HALL_OF_FAME="Hall of Fame hinzuf&uuml;gen"
COM_SPORTSMANAGER_INVALID_HALL_OF_FAME_NAME="Invalider Name f&uuml;r Hall of Fame"
COM_SPORTSMANAGER_REALLY_REMOVE_HALL_OF_FAME="Willst Du wirklich diese Hall of Fame mit allen Mitgliedern l&ouml;schen?"
COM_SPORTSMANAGER_MATCH_TYPE="Spielform"
COM_SPORTSMANAGER_REALLY_REMOVE_HALL_OF_FAME_YEAR="Willst Du wirklich dieses Hall of Fame Jahr l&ouml;schen?"
COM_SPORTSMANAGER_YEARS="Jahre"
COM_SPORTSMANAGER_ADD_HALL_OF_FAME_YEAR="Hall of Fame Jahr hinzuf&uuml;gen"
COM_SPORTSMANAGER_HALL_OF_FAME_TITLE_COUNT="Anzahl"
COM_SPORTSMANAGER_HALL_OF_FAME_TITLES="Titel"
COM_SPORTSMANAGER_HALL_OF_FAME_TEAM_PLAYERS="Mannschaftsspieler"
COM_SPORTSMANAGER_HALL_OF_FAME_NOT_HELD="Nicht ausgespielt"
COM_SPORTSMANAGER_NO_ENTRY="kein Eintrag"
COM_SPORTSMANAGER_REALLY_SWAP_MATCH="Willst Du wirklich das Heimrecht tauschen?"
COM_SPORTSMANAGER_SWAP_MATCH="Heimrechttausch"
COM_SPORTSMANAGER_REALLY_DELETE_MATCH_REPORT="Der Spielbericht wird zusammen mit allen historischen Eintr&auml;gen gel&ouml;scht. Willst du den Spielbericht wirklich l&ouml;schen?"
COM_SPORTSMANAGER_MATCH_REPORT_DELETED="Spielbericht gel&ouml;scht"
COM_SPORTSMANAGER_MATCH_REPORT_WAS_DELETED="Der Spielbericht wurde erfolgreich gel&ouml;scht!"
COM_SPORTSMANAGER_MATCH_REPORT_CORRECTED="Spielberichtskorrektur"
COM_SPORTSMANAGER_MIN_MATCHES="Mindestzahl Spiele"
COM_SPORTSMANAGER_SELECT_ALL="Alle"
COM_SPORTSMANAGER_MAIL_SEND_ERROR="Die Benachrichtigungs-E-Mail zum Ergebnis konnte nicht versendet werden."
COM_SPORTSMANAGER_TERMIN_MAIL_SEND_ERROR="Mindestens eine Benachrichtigungs-E-Mail zum Termin konnte nicht versendet werden."
COM_SPORTSMANAGER_GAME_MARGIN="Mindestvorsprung"
COM_SPORTSMANAGER_GAME_CAP="Spätestens gewonnen bei"
COM_SPORTSMANAGER_GAME_CAP_NONE="Keine Begrenzung"
COM_SPORTSMANAGER_NO_MARGIN="Keiner"
COM_SPORTSMANAGER_ONE_GOAL="1 Tor"
COM_SPORTSMANAGER_NUMBER_GOALS="%d Tore"
COM_SPORTSMANAGER_MULTIPLE_WITH_SETS="Mehrere mit Ergebnis je Satz"
COM_SPORTSMANAGER_SET_NUMBER="Satz %d"
COM_SPORTSMANAGER_SET_COUNT="Sätze je Spiel"
COM_SPORTSMANAGER_GROUP_GENERAL="Allgemein"
COM_SPORTSMANAGER_GROUP_GAME="Spiel"
COM_SPORTSMANAGER_GROUP_SET="Satz"
COM_SPORTSMANAGER_GROUP_MATCH="Begegnung"
COM_SPORTSMANAGER_GROUP_PLAYERS="Spieler und Statistik"
COM_SPORTSMANAGER_DOUBLES_SETTINGS="Doppel-Spiele"
COM_SPORTSMANAGER_ONE_FIXED_SET="1 Satz (wird gespielt)"
COM_SPORTSMANAGER_NUMBER_FIXED_SETS="%d Sätze (alle werden gespielt)"
COM_SPORTSMANAGER_NUMBER_WINNING_SETS="%d Gewinnsätze"
COM_SPORTSMANAGER_DECIDING_SET="Entscheidungssatz"
COM_SPORTSMANAGER_DECIDING_SET_SAME="Wie die übrigen Sätze"
COM_SPORTSMANAGER_SETS_PER_GAME_HELP="Mit „Ergebnis je Satz" werden die Tore der einzelnen Sätze mit erfasst und stehen im Spielbericht; ohne bleibt nur der Satzstand."
COM_SPORTSMANAGER_SET_COUNT_HELP="Die Angaben beschreiben den Wettbewerb; sie lehnen keine Eingabe ab. Auswertungen und Apps erkennen daran, ob ein Spiel noch läuft oder schon entschieden ist."
COM_SPORTSMANAGER_MODE_GLOSSARY="Eine <strong>Begegnung</strong> ist die Partie zweier Mannschaften. Sie besteht aus mehreren <strong>Spielen</strong>: Einzel und Doppel, in der Reihenfolge der Spielfolge. Jedes Spiel bringt Spielpunkte für die Begegnung. Ein <strong>Spiel</strong> besteht aus einem Satz („Einer") oder aus mehreren. In einem <strong>Satz</strong> fallen <strong>Tore</strong>. Die Einstellungen unten sind in dieser Reihenfolge geordnet: von der Begegnung über das Spiel zum Satz."
COM_SPORTSMANAGER_RESULT_AS_GAME_POINTS="Ohne Umrechnung Tore bzw. Sätze sind die Spielpunkte"
COM_SPORTSMANAGER_RESULT_AS_GAME_POINTS_GOALS="Ohne Umrechnung Tore sind die Spielpunkte"
COM_SPORTSMANAGER_RESULT_AS_GAME_POINTS_SETS="Ohne Umrechnung Sätze sind die Spielpunkte"
COM_SPORTSMANAGER_COUNTING="Zählweise"
COM_SPORTSMANAGER_COUNTING_PER_GAME="Je Spiel jedes Spiel beginnt bei 0:0"
COM_SPORTSMANAGER_COUNTING_RACE="Race-Modus die Tore addieren sich über alle Spiele"
COM_SPORTSMANAGER_RACE_STEP="Schritt je Spiel"
COM_SPORTSMANAGER_RACE_TARGET="Ziel"
COM_SPORTSMANAGER_RACE_TARGET_FORMULA="Anzahl der Spiele aus der Spielfolge × Schritt je Spiel"
COM_SPORTSMANAGER_RACE_TARGET_CURRENT="derzeit %1$d Spiele × %2$d = %3$d Tore"
COM_SPORTSMANAGER_RACE_MARGIN="Mindestvorsprung am Ziel"
COM_SPORTSMANAGER_RACE_CAP="Spätestens gewonnen bei"
COM_SPORTSMANAGER_RACE_DRAW="Unentschieden am Ziel"
COM_SPORTSMANAGER_RACE_DRAW_NO="Nein"
COM_SPORTSMANAGER_RACE_DRAW_YES="Ja bei einem Tor unter dem Ziel"
COM_SPORTSMANAGER_RACE_HELP="Der Stand läuft über die ganze Begegnung durch: Spiel 1 endet beim Schritt, Spiel 2 beim doppelten Schritt, und so fort bis zum Ziel. Mindestvorsprung und Grenze gelten nur für das letzte Spiel. Der Race-Modus setzt „Spielergebnis als Spielpunkte" und einen Satz je Spiel voraus beides wird mitgesetzt."
COM_SPORTSMANAGER_ADD_GAME="Spiel hinzufügen"
COM_SPORTSMANAGER_ADD_LINK="Verknüpfung hinzufügen"
COM_SPORTSMANAGER_REMOVE_GAME="Dieses Spiel entfernen"
COM_SPORTSMANAGER_REMOVE_LINK="Diese Verknüpfung entfernen"
COM_SPORTSMANAGER_LINK_NUMBER="Verknüpfung Nr. %d"
COM_SPORTSMANAGER_GROUP_SEQUENCE="Spielfolge"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK_FIRST_ONE="nur das erste Spiel"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK_FIRST="nur die ersten %d Spiele"
COM_SPORTSMANAGER_POINT_TYPE_CHANGED_WARNING="Für diesen Mannschaftsspielplan sind bereits Ergebnisse eingetragen. Die gespeicherten Zahlen werden NICHT umgerechnet sie bedeuten danach etwas anderes (Tore statt Sätze bzw. umgekehrt). Trotzdem speichern?"
COM_SPORTSMANAGER_PER_SET_VALUATION_CHANGED_WARNING="Für diesen Mannschaftsspielplan sind bereits Ergebnisse eingetragen. Beim Wechsel der Wertung „je Satz" wird nichts umgerechnet: Spiele ohne gespeicherte Satzergebnisse werden mit dem vollen Siegwert je gewonnenem Satz gewertet, ihre Satz-Unentschieden gehen verloren. Und wo unter „Mehrere" in Wahrheit Tore in den Punkte-Feldern stehen (statt Sätzen), zählt ab jetzt jedes Tor wie ein gewonnener Satz doppelt. Trotzdem speichern?"
COM_SPORTSMANAGER_RACE_RUNNING="Stand"
COM_SPORTSMANAGER_TOTAL_SCORE="Gesamtstand"
@@ -1,4 +1,4 @@
; Sports Manager (C) 2006-2020, Sven Nickel ; Sports Manager (C) 2006-2020, Sven Nickel
COM_SPORTSMANAGER="Sports Manager" COM_SPORTSMANAGER="Sports Manager"
COM_SPORTSMANAGER_PLAYERS="Players" COM_SPORTSMANAGER_PLAYERS="Players"
COM_SPORTSMANAGER_CLUBS="Clubs" COM_SPORTSMANAGER_CLUBS="Clubs"
@@ -21,6 +21,7 @@ COM_SPORTSMANAGER_LOCATIONS="Locations"
COM_SPORTSMANAGER_SEASONS="Seasons" COM_SPORTSMANAGER_SEASONS="Seasons"
COM_SPORTSMANAGER_TEAM_PLANS="Team plans" COM_SPORTSMANAGER_TEAM_PLANS="Team plans"
COM_SPORTSMANAGER_TEAM_NAME="Team name" COM_SPORTSMANAGER_TEAM_NAME="Team name"
COM_SPORTSMANAGER_TEAM_NAME_SHORT="Team name short (max 24)"
COM_SPORTSMANAGER_TEAM_NAME2="Club name" COM_SPORTSMANAGER_TEAM_NAME2="Club name"
COM_SPORTSMANAGER_TEAM_SEAT="Club location" COM_SPORTSMANAGER_TEAM_SEAT="Club location"
COM_SPORTSMANAGER_POSTPONE_RULES="Postpone rules" COM_SPORTSMANAGER_POSTPONE_RULES="Postpone rules"
@@ -38,6 +39,8 @@ COM_SPORTSMANAGER_ORGANISATION="Organisation"
COM_SPORTSMANAGER_TEAM_MEMBERS="Team members" COM_SPORTSMANAGER_TEAM_MEMBERS="Team members"
COM_SPORTSMANAGER_TEAM_MEMBERS2="Club members" COM_SPORTSMANAGER_TEAM_MEMBERS2="Club members"
COM_SPORTSMANAGER_MEMBERS="Members" COM_SPORTSMANAGER_MEMBERS="Members"
COM_SPORTSMANAGER_MEMBER="Member"
COM_SPORTSMANAGER_ACTIVE_MEMBERS="Active members"
COM_SPORTSMANAGER_TEAMS="Teams" COM_SPORTSMANAGER_TEAMS="Teams"
COM_SPORTSMANAGER_CURRENT_TEAMS="Current teams" COM_SPORTSMANAGER_CURRENT_TEAMS="Current teams"
COM_SPORTSMANAGER_PREVIOUS_TEAMS="Previous teams" COM_SPORTSMANAGER_PREVIOUS_TEAMS="Previous teams"
@@ -74,13 +77,13 @@ COM_SPORTSMANAGER_GAME="Game"
COM_SPORTSMANAGER_GAMES="Games" COM_SPORTSMANAGER_GAMES="Games"
COM_SPORTSMANAGER_GAMES_SHORTCUT="G" COM_SPORTSMANAGER_GAMES_SHORTCUT="G"
COM_SPORTSMANAGER_ADD_PLAYER_STATISTICS="Add player statistics" COM_SPORTSMANAGER_ADD_PLAYER_STATISTICS="Add player statistics"
COM_SPORTSMANAGER_PLAYER_STATISTICS="Player statistics" COM_SPORTSMANAGER_PLAYER_STATISTIC="Player statistics"
COM_SPORTSMANAGER_COMPETITION="Competition" COM_SPORTSMANAGER_COMPETITION="Competition"
COM_SPORTSMANAGER_COMPETITIONS="Competitions" COM_SPORTSMANAGER_COMPETITIONS="Competitions"
COM_SPORTSMANAGER_IN_COMPETITIONS="in competition" COM_SPORTSMANAGER_IN_COMPETITIONS="in competition"
COM_SPORTSMANAGER_COMPETITIONS_SHORTCUT="C" COM_SPORTSMANAGER_COMPETITIONS_SHORTCUT="C"
COM_SPORTSMANAGER_DUPLICATE="Duplicate" COM_SPORTSMANAGER_DUPLICATE="Duplicate"
COM_SPORTSMANAGER_CONFIRM_REMOVE_RANKING="Do you really want to remove the player statistics?" COM_SPORTSMANAGER_CONFIRM_REMOVE_PLAYER_STATISTICS="Do you really want to remove the player statistics?"
COM_SPORTSMANAGER_LIVE_TICKER="Live ticker" COM_SPORTSMANAGER_LIVE_TICKER="Live ticker"
COM_SPORTSMANAGER_PLACE="Place" COM_SPORTSMANAGER_PLACE="Place"
COM_SPORTSMANAGER_TEAM="Team" COM_SPORTSMANAGER_TEAM="Team"
@@ -128,11 +131,14 @@ COM_SPORTSMANAGER_QUARTER_FINAL="Quarter final"
COM_SPORTSMANAGER_QUARTER_FINAL_SHORTCUT="1/4" COM_SPORTSMANAGER_QUARTER_FINAL_SHORTCUT="1/4"
COM_SPORTSMANAGER_ROUND_OF_16="Round of sixteen" COM_SPORTSMANAGER_ROUND_OF_16="Round of sixteen"
COM_SPORTSMANAGER_ROUND_OF_16_SHORTCUT="1/8" COM_SPORTSMANAGER_ROUND_OF_16_SHORTCUT="1/8"
COM_SPORTSMANAGER_ROUND_OF_32="Round of thiry-two" COM_SPORTSMANAGER_ROUND_OF_32="Round of thirty-two"
COM_SPORTSMANAGER_ROUND_OF_32_ALT="Round of thirty-two"
COM_SPORTSMANAGER_ROUND_OF_32_SHORTCUT="1/16" COM_SPORTSMANAGER_ROUND_OF_32_SHORTCUT="1/16"
COM_SPORTSMANAGER_ROUND_OF_64="Round of sixty-four" COM_SPORTSMANAGER_ROUND_OF_64="Round of sixty-four"
COM_SPORTSMANAGER_ROUND_OF_64_ALT="Round of sixty-four"
COM_SPORTSMANAGER_ROUND_OF_64_SHORTCUT="1/32" COM_SPORTSMANAGER_ROUND_OF_64_SHORTCUT="1/32"
COM_SPORTSMANAGER_ROUND_OF_128="Round of 128" COM_SPORTSMANAGER_ROUND_OF_128="Round of 128"
COM_SPORTSMANAGER_ROUND_OF_128_ALT="Round of 128"
COM_SPORTSMANAGER_ROUND_OF_128_SHORTCUT="1/64" COM_SPORTSMANAGER_ROUND_OF_128_SHORTCUT="1/64"
COM_SPORTSMANAGER_DAY_0_SHORTCUT="Su." COM_SPORTSMANAGER_DAY_0_SHORTCUT="Su."
COM_SPORTSMANAGER_DAY_1_SHORTCUT="Mo." COM_SPORTSMANAGER_DAY_1_SHORTCUT="Mo."
@@ -151,9 +157,12 @@ COM_SPORTSMANAGER_DEFEAT="Defeat"
COM_SPORTSMANAGER_DEFEATS="Defeats" COM_SPORTSMANAGER_DEFEATS="Defeats"
COM_SPORTSMANAGER_DEFEATS_SHORTCUT="F" COM_SPORTSMANAGER_DEFEATS_SHORTCUT="F"
COM_SPORTSMANAGER_GOALS="Goals" COM_SPORTSMANAGER_GOALS="Goals"
COM_SPORTSMANAGER_GOALS_SHORTCUT="G"
COM_SPORTSMANAGER_SETS="Sets" COM_SPORTSMANAGER_SETS="Sets"
COM_SPORTSMANAGER_SETS_DRAWN="Drawn sets: %d"
COM_SPORTSMANAGER_POINT="Point" COM_SPORTSMANAGER_POINT="Point"
COM_SPORTSMANAGER_POINTS="Points" COM_SPORTSMANAGER_POINTS="Points"
COM_SPORTSMANAGER_SETS_SHORTCUT="S"
COM_SPORTSMANAGER_POINTS_SHORTCUT="P" COM_SPORTSMANAGER_POINTS_SHORTCUT="P"
COM_SPORTSMANAGER_ONE_POINT="1 point" COM_SPORTSMANAGER_ONE_POINT="1 point"
COM_SPORTSMANAGER_NUMBER_POINTS="%d points" COM_SPORTSMANAGER_NUMBER_POINTS="%d points"
@@ -164,8 +173,8 @@ COM_SPORTSMANAGER_GAME_POINTS_SHORTCUT="GP"
COM_SPORTSMANAGER_SUFFIX_ONE_TEAM=" (one team)" COM_SPORTSMANAGER_SUFFIX_ONE_TEAM=" (one team)"
COM_SPORTSMANAGER_SUFFIX_TEAMS_TOGETHER=" (teams together)" COM_SPORTSMANAGER_SUFFIX_TEAMS_TOGETHER=" (teams together)"
COM_SPORTSMANAGER_DIFFERENCE="Difference" COM_SPORTSMANAGER_DIFFERENCE="Difference"
COM_SPORTSMANAGER_DIFFERENCE_IN_POINTS="Difference in points" COM_SPORTSMANAGER_DIFFERENCE_IN_POINTS="Difference in game points"
COM_SPORTSMANAGER_POINTS_RATIO="Points ratio" COM_SPORTSMANAGER_POINTS_RATIO="Game points ratio"
COM_SPORTSMANAGER_SCHEDULE_DATE="Appointment date" COM_SPORTSMANAGER_SCHEDULE_DATE="Appointment date"
COM_SPORTSMANAGER_TEAM_HOME="Home" COM_SPORTSMANAGER_TEAM_HOME="Home"
COM_SPORTSMANAGER_TEAM_VISITOR="Visitor" COM_SPORTSMANAGER_TEAM_VISITOR="Visitor"
@@ -259,6 +268,7 @@ COM_SPORTSMANAGER_IN="in"
COM_SPORTSMANAGER_NATIONAL="National" COM_SPORTSMANAGER_NATIONAL="National"
COM_SPORTSMANAGER_INTERNATIONAL="International" COM_SPORTSMANAGER_INTERNATIONAL="International"
COM_SPORTSMANAGER_PLAYER_NUMBER_SHORT="Player number" COM_SPORTSMANAGER_PLAYER_NUMBER_SHORT="Player number"
COM_SPORTSMANAGER_ASSOCIATION_SHORT_NAME="Association short name"
COM_SPORTSMANAGER_BASIC_PLAYER_NUMBER_SHORT="Player number base" COM_SPORTSMANAGER_BASIC_PLAYER_NUMBER_SHORT="Player number base"
COM_SPORTSMANAGER_MESSAGES="Registrations" COM_SPORTSMANAGER_MESSAGES="Registrations"
COM_SPORTSMANAGER_TOURNAMENT_PLACEMENT="Tournament placements" COM_SPORTSMANAGER_TOURNAMENT_PLACEMENT="Tournament placements"
@@ -289,11 +299,9 @@ COM_SPORTSMANAGER_REQUEST_MESSAGE_PLURAL="At least %d dates must be given comple
COM_SPORTSMANAGER_REJECT_SHIFT="Reject shift" COM_SPORTSMANAGER_REJECT_SHIFT="Reject shift"
COM_SPORTSMANAGER_TO="until" COM_SPORTSMANAGER_TO="until"
COM_SPORTSMANAGER_PLAYER_STATISTICS="Player statistics" COM_SPORTSMANAGER_PLAYER_STATISTICS="Player statistics"
COM_SPORTSMANAGER_PERFORMANCE_INDEX="Performance index"
COM_SPORTSMANAGER_PERFORMANCE_INDEX_SHORTCUT="PI"
COM_SPORTSMANAGER_WON="won" COM_SPORTSMANAGER_WON="won"
COM_SPORTSMANAGER_LOST="lost" COM_SPORTSMANAGER_LOST="lost"
COM_SPORTSMANAGER_RATE="Rate" COM_SPORTSMANAGER_RATE="Winning rate"
COM_SPORTSMANAGER_RATE_SHORTCUT="R" COM_SPORTSMANAGER_RATE_SHORTCUT="R"
COM_SPORTSMANAGER_NO_CLUB="No club" COM_SPORTSMANAGER_NO_CLUB="No club"
COM_SPORTSMANAGER_RATING="Rating" COM_SPORTSMANAGER_RATING="Rating"
@@ -311,6 +319,11 @@ COM_SPORTSMANAGER_FOR_OTHER_CONTACT="For other contact"
COM_SPORTSMANAGER_DATES_REGISTERED_USERS="Apply dates by registered users" COM_SPORTSMANAGER_DATES_REGISTERED_USERS="Apply dates by registered users"
COM_SPORTSMANAGER_VIEW_ELO_RATING="View Elo rating" COM_SPORTSMANAGER_VIEW_ELO_RATING="View Elo rating"
COM_SPORTSMANAGER_VIEW_SPORTSMANAGER_LIZENZ="Show License" COM_SPORTSMANAGER_VIEW_SPORTSMANAGER_LIZENZ="Show License"
COM_SPORTSMANAGER_VIEW_LEAST_MEMBER_COUNT="Show least member count (teams)"
COM_SPORTSMANAGER_SHOW_ORGANISATION="Show organisation (teams)"
COM_SPORTSMANAGER_SHOW_MEMBER_COUNT="Show member column (teams)"
COM_SPORTSMANAGER_SHOW_TOURNAMENT_BRACKET="Show Tournament Bracket"
COM_SPORTSMANAGER_USE_DISCIPLINARY_FINE="Use disciplinary fine"
COM_SPORTSMANAGER_PLAYER_DETAILS="Player details" COM_SPORTSMANAGER_PLAYER_DETAILS="Player details"
COM_SPORTSMANAGER_PLAYER_LIST_DETAILS="Player list details" COM_SPORTSMANAGER_PLAYER_LIST_DETAILS="Player list details"
COM_SPORTSMANAGER_PLAYER_EDIT="Edit player data by organisation/club contacts" COM_SPORTSMANAGER_PLAYER_EDIT="Edit player data by organisation/club contacts"
@@ -351,8 +364,9 @@ COM_SPORTSMANAGER_PLAYERS_EXPORT_SPORT_SOFTWARE="Export players (Sport Software)
COM_SPORTSMANAGER_CLEANUP_INACTIVE_PLAYERS="Cleanup inactive players" COM_SPORTSMANAGER_CLEANUP_INACTIVE_PLAYERS="Cleanup inactive players"
COM_SPORTSMANAGER_STATISTIK="Statistics" COM_SPORTSMANAGER_STATISTIK="Statistics"
COM_SPORTSMANAGER_PLAYERS_ACTIVE="Players active" COM_SPORTSMANAGER_PLAYERS_ACTIVE="Players active"
COM_SPORTSMANAGER_RESTRICTED_PLAYERS="Players restrited" COM_SPORTSMANAGER_RESTRICTED_PLAYERS="Players restricted"
COM_SPORTSMANAGER_PLAYER_PASSIV="Players passive" COM_SPORTSMANAGER_PLAYER_PASSIV="Players passive"
COM_SPORTSMANAGER_PLAYER_UNATTACHED="Players unattached"
COM_SPORTSMANAGER_MEN_ACTIVE="Male active" COM_SPORTSMANAGER_MEN_ACTIVE="Male active"
COM_SPORTSMANAGER_WOMEN_ACTIVE="Female active" COM_SPORTSMANAGER_WOMEN_ACTIVE="Female active"
COM_SPORTSMANAGER_JUNIOR_ACTIVE="Juniors active" COM_SPORTSMANAGER_JUNIOR_ACTIVE="Juniors active"
@@ -362,7 +376,7 @@ COM_SPORTSMANAGER_IDENTICAL_NAME="Identical name"
COM_SPORTSMANAGER_IDENTICAL_NAME_BIRTHYEAR="Identical name and birth year" COM_SPORTSMANAGER_IDENTICAL_NAME_BIRTHYEAR="Identical name and birth year"
COM_SPORTSMANAGER_NO_PLAYERS="No player number" COM_SPORTSMANAGER_NO_PLAYERS="No player number"
COM_SPORTSMANAGER_LAST_FIRST_NAME="Last name, first name" COM_SPORTSMANAGER_LAST_FIRST_NAME="Last name, first name"
COM_SPORTSMANAGER_BIRTHYEAR="birthyear" COM_SPORTSMANAGER_BIRTHYEAR="Birthyear"
COM_SPORTSMANAGER_NAT="Nat. #" COM_SPORTSMANAGER_NAT="Nat. #"
COM_SPORTSMANAGER_INT="Intern. #" COM_SPORTSMANAGER_INT="Intern. #"
COM_SPORTSMANAGER_REMOVE_MESSAGE="Do you really want to remove the player?" COM_SPORTSMANAGER_REMOVE_MESSAGE="Do you really want to remove the player?"
@@ -380,8 +394,11 @@ COM_SPORTSMANAGER_MEMBER_STATUS="Member status"
COM_SPORTSMANAGER_ACTIVE="Active" COM_SPORTSMANAGER_ACTIVE="Active"
COM_SPORTSMANAGER_RESTRICTED="Restricted" COM_SPORTSMANAGER_RESTRICTED="Restricted"
COM_SPORTSMANAGER_BEATEN="Excreted" COM_SPORTSMANAGER_BEATEN="Excreted"
COM_SPORTSMANAGER_HIDE="Hide"
COM_SPORTSMANAGER_PASSIVE="Passive" COM_SPORTSMANAGER_PASSIVE="Passive"
COM_SPORTSMANAGER_BEATEN_CLUB="Club excreted" COM_SPORTSMANAGER_BEATEN_CLUB="Club excreted"
COM_SPORTSMANAGER_ACTIVE_CLUBS="Active clubs"
COM_SPORTSMANAGER_INACTIVE_CLUBS="Inactive clubs"
COM_SPORTSMANAGER_SINGLE_SEED="Elo starting value singles" COM_SPORTSMANAGER_SINGLE_SEED="Elo starting value singles"
COM_SPORTSMANAGER_DOUBLE_SEED="Elo starting value doubles" COM_SPORTSMANAGER_DOUBLE_SEED="Elo starting value doubles"
COM_SPORTSMANAGER_PLAYER_EXPORT="Players: Export" COM_SPORTSMANAGER_PLAYER_EXPORT="Players: Export"
@@ -402,10 +419,11 @@ COM_SPORTSMANAGER_EXPORT="Export"
COM_SPORTSMANAGER_INTERNATIONAL_PLAYERS="Players (international)" COM_SPORTSMANAGER_INTERNATIONAL_PLAYERS="Players (international)"
COM_SPORTSMANAGER_COUNTRY_CODE="Country code" COM_SPORTSMANAGER_COUNTRY_CODE="Country code"
COM_SPORTSMANAGER_IMPORT="Import" COM_SPORTSMANAGER_IMPORT="Import"
COM_SPORTSMANAGER_IMPORT_MESSAGE="In the import there are only player information about club %s present. Shall only the members of that one club be updated, the associated club has to be selected down here. If the import contains all members of the organisation then the organisation must be selected." COM_SPORTSMANAGER_IMPORT_MESSAGE="In the import there are only player information about club %s present. Shall only the members of that one club be updated, the associated club has to be selected down here. If the import contains all members of the organisation then the organisation must be selected.<br />If a license number already exists, the license number and the year of birth will not be overwritten."
COM_SPORTSMANAGER_CHECK="Check" COM_SPORTSMANAGER_CHECK="Check"
COM_SPORTSMANAGER_IMPORT_CONFLICTS_MESSAGE="There are conflicts in the import which have to be fixed manually first." COM_SPORTSMANAGER_IMPORT_CONFLICTS_MESSAGE="There are faults or conflicts in the import which have to be fixed manually first."
COM_SPORTSMANAGER_IMPORT_DUPLICATE_MESSAGE="Attempt to change player number into one that is already assigned to another player." COM_SPORTSMANAGER_IMPORT_DUPLICATE_MESSAGE="Attempt to change player number into one that is already assigned to another player."
COM_SPORTSMANAGER_IMPORT_WRONG_FORMAT_PLAYERNUMBER="One or more player numbers contain an invalid format"
COM_SPORTSMANAGER_NAME2="Name" COM_SPORTSMANAGER_NAME2="Name"
COM_SPORTSMANAGER_DATA_IMPORT_ABORT_MESSAGE="The import has been aborted because there are conflicts in the containing player information. Please contact a moderator and attach the import!" COM_SPORTSMANAGER_DATA_IMPORT_ABORT_MESSAGE="The import has been aborted because there are conflicts in the containing player information. Please contact a moderator and attach the import!"
COM_SPORTSMANAGER_DATA_IMPORT_NO_CONFLICTS="There are conflicts in the containing player information." COM_SPORTSMANAGER_DATA_IMPORT_NO_CONFLICTS="There are conflicts in the containing player information."
@@ -444,7 +462,7 @@ COM_SPORTSMANAGER_NOTE="Note"
COM_SPORTSMANAGER_WANT_REALLY_REMOVE="Do you really want to remove the club?" COM_SPORTSMANAGER_WANT_REALLY_REMOVE="Do you really want to remove the club?"
COM_SPORTSMANAGER_ADD="Add" COM_SPORTSMANAGER_ADD="Add"
COM_SPORTSMANAGER_REMOVE_ACCOUNT="Remove account" COM_SPORTSMANAGER_REMOVE_ACCOUNT="Remove account"
COM_SPORTSMANAGER_DISTRICT="Ristrict" COM_SPORTSMANAGER_DISTRICT="District"
COM_SPORTSMANAGER_ELIGIBLE_FOR_TEAM="Eligible for team" COM_SPORTSMANAGER_ELIGIBLE_FOR_TEAM="Eligible for team"
COM_SPORTSMANAGER_ELIGIBLE_FOR_CLUB="Eligible for club" COM_SPORTSMANAGER_ELIGIBLE_FOR_CLUB="Eligible for club"
COM_SPORTSMANAGER_SAVED_CLUB="Club to maintain" COM_SPORTSMANAGER_SAVED_CLUB="Club to maintain"
@@ -474,18 +492,25 @@ COM_SPORTSMANAGER_GAME_DOUBLES2="Double games"
COM_SPORTSMANAGER_GAME_DOUBLES_IDENTICAL="Doubles game identical" COM_SPORTSMANAGER_GAME_DOUBLES_IDENTICAL="Doubles game identical"
COM_SPORTSMANAGER_GAME_DOUBLES_SEPARATELY="Doubles game seperately" COM_SPORTSMANAGER_GAME_DOUBLES_SEPARATELY="Doubles game seperately"
COM_SPORTSMANAGER_ONE="One" COM_SPORTSMANAGER_ONE="One"
COM_SPORTSMANAGER_MULTIPLE="Multiple" COM_SPORTSMANAGER_MULTIPLE="Multiple set score only"
COM_SPORTSMANAGER_HOME_EXCHANGE="Home exchange" COM_SPORTSMANAGER_HOME_EXCHANGE="Home exchange"
COM_SPORTSMANAGER_NOT_ALLOWED="Not allowed" COM_SPORTSMANAGER_NOT_ALLOWED="Not allowed"
COM_SPORTSMANAGER_ALLOWED="Allowed" COM_SPORTSMANAGER_ALLOWED="Allowed"
COM_SPORTSMANAGER_PLAYER_NAME="Player name" COM_SPORTSMANAGER_PLAYER_NAME="Player name"
COM_SPORTSMANAGER_PLAYERS_SEARCH_SPECIAL="(Special search)" COM_SPORTSMANAGER_PLAYERS_SEARCH_SPECIAL="(Special search)"
COM_SPORTSMANAGER_ADD_SEASON="Add season" COM_SPORTSMANAGER_ADD_SEASON="Add season"
COM_SPORTSMANAGER_GAME_POINTS_GAME="Game points per game" COM_SPORTSMANAGER_GAME_POINTS_GAME="Game points"
COM_SPORTSMANAGER_WIN_1_POINT="Win: 1 point" COM_SPORTSMANAGER_WIN_1_POINT="Win: 1 point"
COM_SPORTSMANAGER_WIN_2_POINTS="Win: 2 points, draw: 1 point" COM_SPORTSMANAGER_WIN_2_POINTS="Win: 2 points, draw: 1 point"
COM_SPORTSMANAGER_WIN_1_POINT_PER_SET="Per set: win 1 point"
COM_SPORTSMANAGER_WIN_2_POINTS_PER_SET="Per set: win 2 points, draw 1 point"
COM_SPORTSMANAGER_WIN_3_POINTS_PER_SET="Per set: win 3 points, draw 1 point"
COM_SPORTSMANAGER_GAME_POINTS_FOR_GAME="For the whole game"
COM_SPORTSMANAGER_GAME_POINTS_FOR_SET="For each set separately"
COM_SPORTSMANAGER_WIN_3_POINTS="Win: 3 points, draw: 1 point" COM_SPORTSMANAGER_WIN_3_POINTS="Win: 3 points, draw: 1 point"
COM_SPORTSMANAGER_MEETING_CONCLUDED_AT="Match won at" COM_SPORTSMANAGER_MEETING_CONCLUDED_AT="Match won at"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK="Games in player statistics"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK_ALL="All games"
COM_SPORTSMANAGER_GENERALLY="Generally" COM_SPORTSMANAGER_GENERALLY="Generally"
COM_SPORTSMANAGER_TYPE="Type" COM_SPORTSMANAGER_TYPE="Type"
COM_SPORTSMANAGER_ELO_MIN="Elo min." COM_SPORTSMANAGER_ELO_MIN="Elo min."
@@ -502,7 +527,6 @@ COM_SPORTSMANAGER_ADD_POINTS_TABLE="Add points table"
COM_SPORTSMANAGER_ADD_FUNCTION="Add function" COM_SPORTSMANAGER_ADD_FUNCTION="Add function"
COM_SPORTSMANAGER_PARTICIPANT="Participants" COM_SPORTSMANAGER_PARTICIPANT="Participants"
COM_SPORTSMANAGER_FUNCTION="Function" COM_SPORTSMANAGER_FUNCTION="Function"
COM_SPORTSMANAGER_MULTIPLIER="Multiplier"
COM_SPORTSMANAGER_MAXIMUM="maximum" COM_SPORTSMANAGER_MAXIMUM="maximum"
COM_SPORTSMANAGER_CONTRACTION="Contraction" COM_SPORTSMANAGER_CONTRACTION="Contraction"
COM_SPORTSMANAGER_ELIGIBLE_ORGANIZERS="Eligible for organisation" COM_SPORTSMANAGER_ELIGIBLE_ORGANIZERS="Eligible for organisation"
@@ -536,9 +560,23 @@ COM_SPORTSMANAGER_FULL_RATING="Full rating"
COM_SPORTSMANAGER_NO_RATING="No rating" COM_SPORTSMANAGER_NO_RATING="No rating"
COM_SPORTSMANAGER_TEAM_COMPETITIONS="Team competitions" COM_SPORTSMANAGER_TEAM_COMPETITIONS="Team competitions"
COM_SPORTSMANAGER_TABLE_SUMMARY="Table rating" COM_SPORTSMANAGER_TABLE_SUMMARY="Table rating"
COM_SPORTSMANAGER_HEAD_TO_HEAD_RECORD="Head-to-head record"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_NOT="Off"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_POINTS="Tie: pts"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_SETS="Tie: pts, set points"
COM_SPORTSMANAGER_HEAD_TO_HEAD_OPT_GOALS="Tie: pts, set points, goals"
COM_SPORTSMANAGER_POINTS_WON_LOST_DIFFERENCE="Game points won, game points lost, point difference" COM_SPORTSMANAGER_POINTS_WON_LOST_DIFFERENCE="Game points won, game points lost, point difference"
COM_SPORTSMANAGER_PERFORMANCE_INDEX="Performance index (GP+ * GP+ * 100) / (GP+ + GP-), game points won, ..." COM_SPORTSMANAGER_PERFORMANCE_INDEX0="Game points won, game points lost, point difference"
COM_SPORTSMANAGER_PERFORMANCE_INDEX1="Performance index (GP+ * GP+ * 100) / (GP+ + GP-), game points won, ..."
COM_SPORTSMANAGER_PERFORMANCE_INDEX2="Performance index (games * P+ * 10) / (P+ + P-), game points won, ..." COM_SPORTSMANAGER_PERFORMANCE_INDEX2="Performance index (games * P+ * 10) / (P+ + P-), game points won, ..."
COM_SPORTSMANAGER_PERFORMANCE_INDEX3="Race Performance Index (victories*2 + draws + goal difference)"
COM_SPORTSMANAGER_PERFORMANCE_INDEX4="Efficency index (G+ / (G+ + G-))"
COM_SPORTSMANAGER_PERFORMANCE_INDEX5="Set point average (P+ / count sets)"
COM_SPORTSMANAGER_PERFORMANCE_SHORT1="LI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT2="LI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT3="RPI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT4="EI"
COM_SPORTSMANAGER_PERFORMANCE_SHORT5="AVG"
COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS="Individual statistics of all games" COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS="Individual statistics of all games"
COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_SINGLES="Individual statistics of singles games" COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_SINGLES="Individual statistics of singles games"
COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_DOUBLES="Individual statistics of doubles games" COM_SPORTSMANAGER_INDIVIDUAL_STATISTICS_DOUBLES="Individual statistics of doubles games"
@@ -562,7 +600,7 @@ COM_SPORTSMANAGER_PRIVATE_PLAYER_DATA="View privat player information in club an
COM_SPORTSMANAGER_ASSOCIATIONS_MEMBERSHIPS_MANAGE="Manage clubs and memberships" COM_SPORTSMANAGER_ASSOCIATIONS_MEMBERSHIPS_MANAGE="Manage clubs and memberships"
COM_SPORTSMANAGER_MANAGE_CLASSIFICATIONS="Manage classifications" COM_SPORTSMANAGER_MANAGE_CLASSIFICATIONS="Manage classifications"
COM_SPORTSMANAGER_MANAGE_TEAM_PLANS="Manage team plans" COM_SPORTSMANAGER_MANAGE_TEAM_PLANS="Manage team plans"
COM_SPORTSMANAGER_MANAGE_RULES_POSTPONEMENT="Manage postpone rules" COM_SPORTSMANAGER_MANAGE_RULES_POSTPONEMENT="Manage match rescheduling/postpone rules"
COM_SPORTSMANAGER_MANAGE_VENUES="Manage venues" COM_SPORTSMANAGER_MANAGE_VENUES="Manage venues"
COM_SPORTSMANAGER_MANAGE_TEAM_COMPETITIONS="Manage team competitions" COM_SPORTSMANAGER_MANAGE_TEAM_COMPETITIONS="Manage team competitions"
COM_SPORTSMANAGER_MANAGE_PLAYER_STATISTICS="Manage player statitics" COM_SPORTSMANAGER_MANAGE_PLAYER_STATISTICS="Manage player statitics"
@@ -604,7 +642,10 @@ COM_SPORTSMANAGER_ONLY_DETAILED_RATING_POINT_DIFFERENCE="Only detailed ranking b
COM_SPORTSMANAGER_ONLY_DETAILED_POINTS_AFTER_POINTSRATE="Only detailed ranking by points rate" COM_SPORTSMANAGER_ONLY_DETAILED_POINTS_AFTER_POINTSRATE="Only detailed ranking by points rate"
COM_SPORTSMANAGER_KO_SIMPLE_FULL="K.O. (singles or full playout of all places)" COM_SPORTSMANAGER_KO_SIMPLE_FULL="K.O. (singles or full playout of all places)"
COM_SPORTSMANAGER_MANUAL_PRO_TEAMS="Manual (per team)" COM_SPORTSMANAGER_MANUAL_PRO_TEAMS="Manual (per team)"
COM_SPORTSMANAGER_CUP_DRAW_EVERY_ROUND="Cup: draw every round"
COM_SPORTSMANAGER_CUP_USING_SEEDING_LIST="Cup: draw seeding list"
COM_SPORTSMANAGER_SUBDIVISION="Subdivision" COM_SPORTSMANAGER_SUBDIVISION="Subdivision"
COM_SPORTSMANAGER_SHOW_MATCHDAY_TITLE="Show title matchday"
COM_SPORTSMANAGER_ELO_RATING="Elo rating" COM_SPORTSMANAGER_ELO_RATING="Elo rating"
COM_SPORTSMANAGER_ELIGIBLE_FOR_EVENT="Eligibles for competition" COM_SPORTSMANAGER_ELIGIBLE_FOR_EVENT="Eligibles for competition"
COM_SPORTSMANAGER_TITLE_LOGO="Title logo" COM_SPORTSMANAGER_TITLE_LOGO="Title logo"
@@ -632,6 +673,9 @@ COM_SPORTSMANAGER_GAMEDAY="Gameday"
COM_SPORTSMANAGER_GAMEDAYS="Gamedays" COM_SPORTSMANAGER_GAMEDAYS="Gamedays"
COM_SPORTSMANAGER_ROUND="Round" COM_SPORTSMANAGER_ROUND="Round"
COM_SPORTSMANAGER_ROUNDS="Rounds" COM_SPORTSMANAGER_ROUNDS="Rounds"
COM_SPORTSMANAGER_ROUND_TITLE="Round Title"
COM_SPORTSMANAGER_DRAW_FOR_HOME="Draw for home"
COM_SPORTSMANAGER_MATCH_PLACE3="Match for place 3"
COM_SPORTSMANAGER_MONTH="Month" COM_SPORTSMANAGER_MONTH="Month"
COM_SPORTSMANAGER_MONTHS="Months" COM_SPORTSMANAGER_MONTHS="Months"
COM_SPORTSMANAGER_PLAYER_FROM_TEAM="Player of team" COM_SPORTSMANAGER_PLAYER_FROM_TEAM="Player of team"
@@ -647,8 +691,14 @@ COM_SPORTSMANAGER_SO_FAR="so far"
COM_SPORTSMANAGER_PLACEMENT_AREA="Placement area" COM_SPORTSMANAGER_PLACEMENT_AREA="Placement area"
COM_SPORTSMANAGER_IMAGE_WITHIN_TEAM="Image within team" COM_SPORTSMANAGER_IMAGE_WITHIN_TEAM="Image within team"
COM_SPORTSMANAGER_ADD_MEETING="Add match" COM_SPORTSMANAGER_ADD_MEETING="Add match"
COM_SPORTSMANAGER_GAMEDAY_GENERATION="Generate gameday"
COM_SPORTSMANAGER_ROUND_GENERATION="Generate round" COM_SPORTSMANAGER_ROUND_GENERATION="Generate round"
COM_SPORTSMANAGER_CUP_ROUND_GENERATION="Generate cup round"
COM_SPORTSMANAGER_GENERATE_GROUP_GAME="Generate group games" COM_SPORTSMANAGER_GENERATE_GROUP_GAME="Generate group games"
COM_SPORTSMANAGER_Import_GROUP_GAME="Import group games"
COM_SPORTSMANAGER_Import_GROUP_GAME2="Group games: Import"
COM_SPORTSMANAGER_IMPORT_GROUP_GAME_IMPORTED="matches were imported"
COM_SPORTSMANAGER_IMPORT_GROUP_GAME_CREATED="matches were created"
COM_SPORTSMANAGER_REMOVE_ALL_ENCOUNTERS="Do you really want to remove all matches?" COM_SPORTSMANAGER_REMOVE_ALL_ENCOUNTERS="Do you really want to remove all matches?"
COM_SPORTSMANAGER_REMOVE_ALL_MATCHES="Remove all matches" COM_SPORTSMANAGER_REMOVE_ALL_MATCHES="Remove all matches"
COM_SPORTSMANAGER_HOME_TEAM="Home team" COM_SPORTSMANAGER_HOME_TEAM="Home team"
@@ -694,6 +744,7 @@ COM_SPORTSMANAGER_NUMBER_DAYS="%d days"
COM_SPORTSMANAGER_CALENDAR_WEEK="Calendar week" COM_SPORTSMANAGER_CALENDAR_WEEK="Calendar week"
COM_SPORTSMANAGER_CALENDAR_WEEK_SHORTCUT="CW" COM_SPORTSMANAGER_CALENDAR_WEEK_SHORTCUT="CW"
COM_SPORTSMANAGER_PAIRING="Fixture" COM_SPORTSMANAGER_PAIRING="Fixture"
COM_SPORTSMANAGER_SETTING="Setting"
COM_SPORTSMANAGER_PAIRINGS="Fixtures" COM_SPORTSMANAGER_PAIRINGS="Fixtures"
COM_SPORTSMANAGER_INTERMITTENT="Skipping" COM_SPORTSMANAGER_INTERMITTENT="Skipping"
COM_SPORTSMANAGER_MAXIMUM_SETS="Maximum sets" COM_SPORTSMANAGER_MAXIMUM_SETS="Maximum sets"
@@ -770,6 +821,7 @@ COM_SPORTSMANAGER_FEDERAL_STATES="State"
COM_SPORTSMANAGER_STATES="Countries" COM_SPORTSMANAGER_STATES="Countries"
COM_SPORTSMANAGER_YEAR="Year" COM_SPORTSMANAGER_YEAR="Year"
COM_SPORTSMANAGER_ADDITION="Addition" COM_SPORTSMANAGER_ADDITION="Addition"
COM_SPORTSMANAGER_LOCATION="Location"
COM_SPORTSMANAGER_STATE="Germany" COM_SPORTSMANAGER_STATE="Germany"
COM_SPORTSMANAGER_FEDERAL_="Federal " COM_SPORTSMANAGER_FEDERAL_="Federal "
COM_SPORTSMANAGER_INFO="Info" COM_SPORTSMANAGER_INFO="Info"
@@ -783,7 +835,6 @@ COM_SPORTSMANAGER_APPLIED_FOR="Applied"
COM_SPORTSMANAGER_DECLINED="Declined" COM_SPORTSMANAGER_DECLINED="Declined"
COM_SPORTSMANAGER_DATE_DETAILS="Event: Details" COM_SPORTSMANAGER_DATE_DETAILS="Event: Details"
COM_SPORTSMANAGER_ADDITIONS="Additions" COM_SPORTSMANAGER_ADDITIONS="Additions"
COM_SPORTSMANAGER_ADDITIONAL_INFORMATION="Additional information"
COM_SPORTSMANAGER_PUBLIC_EMAIL="E-mail public" COM_SPORTSMANAGER_PUBLIC_EMAIL="E-mail public"
COM_SPORTSMANAGER_EMAIL_WITH_CHANGES="E-mail for changes" COM_SPORTSMANAGER_EMAIL_WITH_CHANGES="E-mail for changes"
COM_SPORTSMANAGER_ACTION_TYPE="Action type" COM_SPORTSMANAGER_ACTION_TYPE="Action type"
@@ -827,7 +878,6 @@ COM_SPORTSMANAGER_REMOVE_STATE_REALLY="Do you really want to remove the country?
COM_SPORTSMANAGER_DATES_STATE="Appointments country" COM_SPORTSMANAGER_DATES_STATE="Appointments country"
COM_SPORTSMANAGER_RENAME_APPOINTMENTS_STATE="Rename appointments with the preset country" COM_SPORTSMANAGER_RENAME_APPOINTMENTS_STATE="Rename appointments with the preset country"
COM_SPORTSMANAGER_FINAL_RANKING="FINAL RANKING" COM_SPORTSMANAGER_FINAL_RANKING="FINAL RANKING"
COM_SPORTSMANAGER_HOME_TEAM2="Home team"
COM_SPORTSMANAGER_RESULTS2="Result" COM_SPORTSMANAGER_RESULTS2="Result"
COM_SPORTSMANAGER_NO_GAMES="No games" COM_SPORTSMANAGER_NO_GAMES="No games"
COM_SPORTSMANAGER_END_GAME="Final" COM_SPORTSMANAGER_END_GAME="Final"
@@ -860,6 +910,9 @@ COM_SPORTSMANAGER_INITIAL_APPOINTMENT_SUGGESTIONS="Initial appointment suggestio
COM_SPORTSMANAGER_REQUESTING_TEAM="Requesting team" COM_SPORTSMANAGER_REQUESTING_TEAM="Requesting team"
COM_SPORTSMANAGER_OPPONENT_TEAM="Opponent team" COM_SPORTSMANAGER_OPPONENT_TEAM="Opponent team"
COM_SPORTSMANAGER_AGAINST_PROPOSALS_ALLOWED="Against proposals allowed" COM_SPORTSMANAGER_AGAINST_PROPOSALS_ALLOWED="Against proposals allowed"
COM_SPORTSMANAGER_REASON_REQUIRED="Reason required"
COM_SPORTSMANAGER_CLUB_ENTITLEMENT="Club entitlement"
COM_SPORTSMANAGER_ASSOCIATION_ENTITLEMENT="Association_entitlement"
COM_SPORTSMANAGER_LEAD_TIME="Lead time" COM_SPORTSMANAGER_LEAD_TIME="Lead time"
COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MINIMAL="Appointment proposals minimal" COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MINIMAL="Appointment proposals minimal"
COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MAXIMUM="Appointment proposals maximum" COM_SPORTSMANAGER_APPOINTMENT_PROPOSALS_MAXIMUM="Appointment proposals maximum"
@@ -869,6 +922,11 @@ COM_SPORTSMANAGER_OPTIONAL_BUT_SAME_IN_DOUBLES="Optional but both or none in dou
COM_SPORTSMANAGER_REQUIRED="Required" COM_SPORTSMANAGER_REQUIRED="Required"
COM_SPORTSMANAGER_RESULT_ONLY="Result only" COM_SPORTSMANAGER_RESULT_ONLY="Result only"
COM_SPORTSMANAGER_GAME_NUMBER="Game %d" COM_SPORTSMANAGER_GAME_NUMBER="Game %d"
COM_SPORTSMANAGER_LABEL_GAME_NUMBER="Game nr"
COM_SPORTSMANAGER_LABEL_GAME_TITLE="Gameday title"
COM_SPORTSMANAGER_EXPLICIT_PENALTIES="Explicit Penalties"
COM_SPORTSMANAGER_EXPLICIT_PENALTIES_EMAIL_SUBJECT="%s: received penalty"
COM_SPORTSMANAGER_EXPLICIT_PENALTIES_EMAIL_BODY="%s received a penalty of %f points based on the following justification: %s"
COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_SUBJECT="%s vs %s: Shift game appointment" COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_SUBJECT="%s vs %s: Shift game appointment"
COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_BODY="For match %s versus %s on %s in %s the game appointment is shifted by %s.\n\nAlternative appointments:\n\n" COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_BODY="For match %s versus %s on %s in %s the game appointment is shifted by %s.\n\nAlternative appointments:\n\n"
COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_REQUESTED_BODY="For match %s on %s in %s the game appointment is shifted by %s.\n\nPlease propose alternative appointments under %s" COM_SPORTSMANAGER_EMAIL_SHIFT_GAME_APPOINTMENT_REQUESTED_BODY="For match %s on %s in %s the game appointment is shifted by %s.\n\nPlease propose alternative appointments under %s"
@@ -921,3 +979,207 @@ COM_SPORTSMANAGER_NON_SMOKING_PROTECTION_MARK_NO=" (Kein Nichtraucherschutz)"
COM_SPORTSMANAGER_POINTS_TABLE="Points table" COM_SPORTSMANAGER_POINTS_TABLE="Points table"
COM_SPORTSMANAGER_EVALUATION="Auswertung" COM_SPORTSMANAGER_EVALUATION="Auswertung"
COM_SPORTSMANAGER_FUNCTION_DESCRIPTION="Variables: n = number of participants, p = place, m = multiplier of rating and in doubles possibly additionally reduced rating<br />Functions: +, -, *, /, round(x), pow(x), if(a > b, x, y), min(x, y), max(x, y), log(x), ln(x), logn(b, x)<br />VerteilungR(r, p, n, m) := max(round((((m * r - 1) * (-log(p / n) * (1 - (p / n)))) / (-log(1 / n) * (1 - (1 / n)))) + 1), 1)<br />Verteilung(r, p, n, m) := max(round(m * round((((r - 1) * (-log(p / n) * (1 - (p / n)))) / (-log(1 / n) * (1 - (1 / n)))) + 1)), 1)<br /><br />The functions VerteilungR() and Verteilung() distribute points for place 1 (r) descending to the individual places (p) of the number of participants (n).<br />VerteilungR() applies the multiplier (m) to the points for 1st place and then distributes down to 1 point for the last place.<br />Verteilung() applies the multiplier (m) to the points after the calculation, i.e. the last place receives 1 * m points." COM_SPORTSMANAGER_FUNCTION_DESCRIPTION="Variables: n = number of participants, p = place, m = multiplier of rating and in doubles possibly additionally reduced rating<br />Functions: +, -, *, /, round(x), pow(x), if(a > b, x, y), min(x, y), max(x, y), log(x), ln(x), logn(b, x)<br />VerteilungR(r, p, n, m) := max(round((((m * r - 1) * (-log(p / n) * (1 - (p / n)))) / (-log(1 / n) * (1 - (1 / n)))) + 1), 1)<br />Verteilung(r, p, n, m) := max(round(m * round((((r - 1) * (-log(p / n) * (1 - (p / n)))) / (-log(1 / n) * (1 - (1 / n)))) + 1)), 1)<br /><br />The functions VerteilungR() and Verteilung() distribute points for place 1 (r) descending to the individual places (p) of the number of participants (n).<br />VerteilungR() applies the multiplier (m) to the points for 1st place and then distributes down to 1 point for the last place.<br />Verteilung() applies the multiplier (m) to the points after the calculation, i.e. the last place receives 1 * m points."
COM_SPORTSMANAGER_RANK="Rank"
; Edit Player
COM_SPORTSMANAGER_LIZENZ="License"
COM_SPORTSMANAGER_ARIA_LABEL_MATCHDAY_SELECT="Choose a match day"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_DAY="Choose the day of the match proposal"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_MONTH="Choose the month of the match proposal"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_YEAR="Choose the year of the match proposal"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_HOUR="Choose the hour of the match proposal"
COM_SPORTSMANAGER_ARIA_LABEL_PROPOSAL_MINUTE="Choose the minute of the match proposal"
COM_SPORTSMANAGER_ARIA_LABEL_SPECIAL_FILTER="Advanced Filter"
COM_SPORTSMANAGER_ARIA_LABEL_PLACE="Location"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_CLUB="Choose eligible club"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_START_MONTH="Month of tournament start"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_START_YEAR="Year of tournament start"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_END_MONTH="Month of tournament end"
COM_SPORTSMANAGER_ARIA_LABEL_TOURNAMENT_END_YEAR="Year of tournament end"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_USER="Choose eligible user"
COM_SPORTSMANAGER_ARIA_LABEL_POINTS_GUEST="Points away"
COM_SPORTSMANAGER_ARIA_LABEL_POINTS_HOME="Points home"
COM_SPORTSMANAGER_ARIA_LABEL_PLAYER_GUEST="Player away"
COM_SPORTSMANAGER_ARIA_LABEL_PLAYER_HOME="Player home"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_MONTH="Choose a Month"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_YEAR="Choose a Year"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_HOUR="Choose an Hour"
COM_SPORTSMANAGER_ARIA_LABEL_SCHEDULE_DATE_MINUTE="Choose a Minute"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_GUEST="Game away"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_HOME="Game home"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_DOUBLE="Game link double"
COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_SINGLE="Game link single"
COM_SPORTSMANAGER_ARIA_LABEL_PLACEMENT_MIN="Placement min."
COM_SPORTSMANAGER_ARIA_LABEL_PLACEMENT_MAX="Placement max."
COM_SPORTSMANAGER_ARIA_LABEL_PARTICIPANT_MIN="Participant min."
COM_SPORTSMANAGER_ARIA_LABEL_PARTICIPANT_MAX="Participant max."
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_START_MONTH="Month of ranking start"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_START_YEAR="Year of ranking start"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_END_MONTH="Month of ranking end"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_END_YEAR="Year of ranking end"
COM_SPORTSMANAGER_ARIA_LABEL_MAXIMUM_EVALUATED_COUNT="Maximum number of evaluated participations"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_START_MONTH="Month of statistics start"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_START_YEAR="Year of statistics start"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_END_MONTH="Month of statistics end"
COM_SPORTSMANAGER_ARIA_LABEL_STATISTICS_END_YEAR="Year of statistics end"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_ORGANIZER="Choose eligible organizer"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_START_MONTH="Month of event start"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_START_YEAR="Year of event start"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_END_MONTH="Month of event end"
COM_SPORTSMANAGER_ARIA_LABEL_EVENT_END_YEAR="Year of event end"
COM_SPORTSMANAGER_ARIA_LABEL_FIRST_ROUND="First round"
COM_SPORTSMANAGER_ARIA_LABEL_FIRST_ROUND_TYPE="First round type"
COM_SPORTSMANAGER_ARIA_LABEL_FIRST_ROUND_PLACE="First round place"
COM_SPORTSMANAGER_ARIA_LABEL_LAST_ROUND="Last round"
COM_SPORTSMANAGER_ARIA_LABEL_LAST_ROUND_TYPE="Last round type"
COM_SPORTSMANAGER_ARIA_LABEL_LAST_ROUND_PLACE="Last round place"
COM_SPORTSMANAGER_ARIA_LABEL_ROUND_TYPE="round type"
COM_SPORTSMANAGER_ARIA_LABEL_ROUND_PLACE="round place"
COM_SPORTSMANAGER_HOME_POINTS="Home points"
COM_SPORTSMANAGER_GUEST_POINTS="Guest points"
COM_SPORTSMANAGER_ARIA_LABEL_ENCOUNTER_YEAR="Year of encounter"
COM_SPORTSMANAGER_ARIA_LABEL_PAIRING_TEAM="Team for fixture"
COM_SPORTSMANAGER_ARIA_LABEL_ELIGIBLE_COMPETITION="Choose eligible user"
COM_SPORTSMANAGER_ARIA_LABEL_RANKING_EVALUATION="Ranking evaluation"
COM_SPORTSMANAGER_ARIA_LABEL_LASTNAME="Lastname"
COM_SPORTSMANAGER_ARIA_LABEL_FIRSTNAME="Firstname"
COM_SPORTSMANAGER_ARIA_LABEL_CLUB="Club"
COM_SPORTSMANAGER_NUM_REQUESTED_SHIFTS="Shifts"
COM_SPORTSMANAGER_NUM_REQUESTED_SHFITS_TOOLTIP="Game shifts caused by this team"
COM_SPORTSMANAGER_GAME_RESULT_DELAYS="Delay"
COM_SPORTSMANAGER_USE_EMAIL_REMINDERS="Use email reminders"
COM_SPORTSMANAGER_RULEBOOKS="Rulebooks"
COM_SPORTSMANAGER_RULEBOOK="Rulebook"
COM_SPORTSMANAGER_RULE_SHORT="Rule"
COM_SPORTSMANAGER_FEE_SHORT="Section fees"
COM_SPORTSMANAGER_RULE_LONG="Section rules"
COM_SPORTSMANAGER_FEE_LONG="Fee"
COM_SPORTSMANAGER_SELECT="Select"
COM_SPORTSMANAGER_NO_SELECT="No selection"
COM_SPORTSMANAGER_REALLY_REMOVE_RULEBOOK="Do you really want to remove this rulebook?"
COM_SPORTSMANAGER_ADD_RULEBOOK="Add rulebook"
COM_SPORTSMANAGER_DISCIPLINARY_FINES="Disciplinary fines"
COM_SPORTSMANAGER_ISSUE_DISCIPLINARY_FINES="Issue disciplinary fines"
COM_SPORTSMANAGER_ISSUE_DISCIPLINARY_FINE="Issue disciplinary fine"
COM_SPORTSMANAGER_EDIT_DISCIPLINARY_FINE="Edit issue disciplinary fine"
COM_SPORTSMANAGER_SEND_DISCIPLINARY_FINE="Send issue disciplinary fine"
COM_SPORTSMANAGER_REALLY_REMOVE_DISCIPLINARY_FINES="Do you really want to remove this Issue disciplinary fine?"
COM_SPORTSMANAGER_VIOLATIONS="Violations"
COM_SPORTSMANAGER_VIOLATION="Violation"
COM_SPORTSMANAGER_ADD_VIOLATION="Add violation"
COM_SPORTSMANAGER_REALLY_REMOVE_VIOLATION="Do you really want to remove this violation?"
COM_SPORTSMANAGER_VIOLATION_TEXT="Text"
COM_SPORTSMANAGER_VIOLATION_ADD_TEXT="Additional text"
COM_SPORTSMANAGER_FEE="Fee"
COM_SPORTSMANAGER_ADD_FEE="Additional Fee"
COM_SPORTSMANAGER_SELECTABLE="Selectable"
COM_SPORTSMANAGER_TEMPLATE="Template"
COM_SPORTSMANAGER_EMAIL_SUBJECT="Subject"
COM_SPORTSMANAGER_EMAIL_MESSAGE="Message"
COM_SPORTSMANAGER_EMAIL_TO="to"
COM_SPORTSMANAGER_EMAIL_SEND="Send E-Mail"
COM_SPORTSMANAGER_EMAIL_TEXT_TEMPLATE="Text template"
COM_SPORTSMANAGER_ISSUER="Issuer"
COM_SPORTSMANAGER_SENDER="Sender"
COM_SPORTSMANAGER_ISSUE_DATE="Issue date"
COM_SPORTSMANAGER_BILL_ISSUER="Bill issuer"
COM_SPORTSMANAGER_MULTIPLIER="Multiplier"
COM_SPORTSMANAGER_ADDITIONAL_INFORMATION="Additional information"
COM_SPORTSMANAGER_EMAIL_WAS_SEND="E-Mail was succesfully sent"
COM_SPORTSMANAGER_EMAIL_WAS_NOT_SEND="E-Mail was not sent"
COM_SPORTSMANAGER_OLD_DATE="Old Date"
COM_SPORTSMANAGER_NEW_DATE="New Date"
COM_SPORTSMANAGER_REASON_GAME_APPOINTMENT="Appointment reason"
COM_SPORTSMANAGER_MATCH_RESCHEDULINGS="Match reschedulings"
COM_SPORTSMANAGER_MATCH_RESCHEDULING="Match rescheduling"
COM_SPORTSMANAGER_MATCH_SWAPPING_HELP="If home advantage is swapped, enter the same date"
COM_SPORTSMANAGER_NOT_VALID_TIME="Not valid time"
COM_SPORTSMANAGER_REALLY_MATCH_RESCHEDULING="Do you really want to remove this match rescheduling?"
COM_SPORTSMANAGER_REST_DAYS="Rest days"
COM_SPORTSMANAGER_ADDITIONAL_INFO="Additional info"
COM_SPORTSMANAGER_TRAINING_DAYS="Training days"
COM_SPORTSMANAGER_NOT_ACTUALIZED_DATA="Data not updated"
COM_SPORTSMANAGER_ASSOCIATION_BODIES="Association bodies"
COM_SPORTSMANAGER_ASSOCIATION_BODY="Association body"
COM_SPORTSMANAGER_ADD_ASSOCIATION_BODY="Add association body"
COM_SPORTSMANAGER_REALLY_REMOVE_ASSOCIATION_BODY="Do you really want to remove this association body?"
COM_SPORTSMANAGER_INVALID_ASSOCIATION_BODY_NAME="Invalid association body name"
COM_SPORTSMANAGER_NAME_NOT_COMPLETE="The name is not completely filled in"
COM_SPORTSMANAGER_ADDITIONAL_INFO="Additional information"
COM_SPORTSMANAGER_USE_HTML="HTML-formatted text should be used here."
COM_SPORTSMANAGER_REALLY_REMOVE_ASSOCIATION_BODY_MEMBER="Do you really want to remove this association body member?"
COM_SPORTSMANAGER_HELP_EDIT_ASSOCIATION_BODY_MEMBER="Selecting a name from the player list will fill in the first and last name.<br>Phone, mobile, and email are filled from the player list if left blank here."
COM_SPORTSMANAGER_HALL_OF_FAME="Hall of Fame"
COM_SPORTSMANAGER_ADD_HALL_OF_FAME="Add Hall of Fame"
COM_SPORTSMANAGER_INVALID_HALL_OF_FAME_NAME="Invalid Hall of Fame name"
COM_SPORTSMANAGER_REALLY_REMOVE_HALL_OF_FAME="Are you sure you want to delete this Hall of Fame including all its members?"
COM_SPORTSMANAGER_MATCH_TYPE="Game Type"
COM_SPORTSMANAGER_REALLY_REMOVE_HALL_OF_FAME_YEAR="Are you sure you want to delete this Hall of Fame year?"
COM_SPORTSMANAGER_YEARS="Years"
COM_SPORTSMANAGER_ADD_HALL_OF_FAME_YEAR="Add Hall of Fame Year"
COM_SPORTSMANAGER_HALL_OF_FAME_TITLE_COUNT="Number"
COM_SPORTSMANAGER_HALL_OF_FAME_TITLES="Titles"
COM_SPORTSMANAGER_HALL_OF_FAME_TEAM_PLAYERS="Team Players"
COM_SPORTSMANAGER_HALL_OF_FAME_NOT_HELD="Not held"
COM_SPORTSMANAGER_NO_ENTRY="no entry"
COM_SPORTSMANAGER_REALLY_SWAP_MATCH="Do you really want to swap the home advantage?"
COM_SPORTSMANAGER_SWAP_MATCH="Swap home advantage"
COM_SPORTSMANAGER_REALLY_DELETE_MATCH_REPORT="The match report and all its history will be deleted. Are you sure you want to delete the match report?"
COM_SPORTSMANAGER_MATCH_REPORT_DELETED="Match report deleted"
COM_SPORTSMANAGER_MATCH_REPORT_WAS_DELETED="The match report has been successfully deleted!"
COM_SPORTSMANAGER_MATCH_REPORT_CORRECTED="Match report corrected"
COM_SPORTSMANAGER_MIN_MATCHES="Min count matches"
COM_SPORTSMANAGER_SELECT_ALL="All"
COM_SPORTSMANAGER_MAIL_SEND_ERROR="The notification e-mail for the result could not be sent."
COM_SPORTSMANAGER_TERMIN_MAIL_SEND_ERROR="At least one notification e-mail for the appointment could not be sent."
COM_SPORTSMANAGER_GAME_MARGIN="Minimum margin"
COM_SPORTSMANAGER_GAME_CAP="Won at the latest at"
COM_SPORTSMANAGER_GAME_CAP_NONE="No limit"
COM_SPORTSMANAGER_NO_MARGIN="None"
COM_SPORTSMANAGER_ONE_GOAL="1 goal"
COM_SPORTSMANAGER_NUMBER_GOALS="%d goals"
COM_SPORTSMANAGER_MULTIPLE_WITH_SETS="Multiple with each set's result"
COM_SPORTSMANAGER_SET_NUMBER="Set %d"
COM_SPORTSMANAGER_SET_COUNT="Sets per game"
COM_SPORTSMANAGER_GROUP_GENERAL="General"
COM_SPORTSMANAGER_GROUP_GAME="Game"
COM_SPORTSMANAGER_GROUP_SET="Set"
COM_SPORTSMANAGER_GROUP_MATCH="Match"
COM_SPORTSMANAGER_GROUP_PLAYERS="Players and statistics"
COM_SPORTSMANAGER_DOUBLES_SETTINGS="Doubles games"
COM_SPORTSMANAGER_ONE_FIXED_SET="1 set (played out)"
COM_SPORTSMANAGER_NUMBER_FIXED_SETS="%d sets (all played out)"
COM_SPORTSMANAGER_NUMBER_WINNING_SETS="Best of %d wins"
COM_SPORTSMANAGER_DECIDING_SET="Deciding set"
COM_SPORTSMANAGER_DECIDING_SET_SAME="As the other sets"
COM_SPORTSMANAGER_SETS_PER_GAME_HELP="With “each sets result” the goals of the individual sets are recorded too and appear in the match report; without it only the set score remains."
COM_SPORTSMANAGER_SET_COUNT_HELP="These settings describe the competition; they never reject an entry. Evaluations and apps use them to tell a game still running from one already decided."
COM_SPORTSMANAGER_MODE_GLOSSARY="A <strong>match</strong> is the fixture between two teams. It consists of several <strong>games</strong> singles and doubles in the order of the game sequence and each game yields game points for the match. A <strong>game</strong> consists of one set (“One”) or of several. Within a <strong>set</strong>, <strong>goals</strong> are scored. The settings below follow that order: from the match through the game down to the set."
COM_SPORTSMANAGER_RESULT_AS_GAME_POINTS="Without conversion goals or sets are the game points"
COM_SPORTSMANAGER_RESULT_AS_GAME_POINTS_GOALS="Without conversion goals are the game points"
COM_SPORTSMANAGER_RESULT_AS_GAME_POINTS_SETS="Without conversion sets are the game points"
COM_SPORTSMANAGER_COUNTING="Counting"
COM_SPORTSMANAGER_COUNTING_PER_GAME="Per game every game starts at 0:0"
COM_SPORTSMANAGER_COUNTING_RACE="Race goals add up across all games"
COM_SPORTSMANAGER_RACE_STEP="Step per game"
COM_SPORTSMANAGER_RACE_TARGET="Target"
COM_SPORTSMANAGER_RACE_TARGET_FORMULA="Number of games in the sequence × step per game"
COM_SPORTSMANAGER_RACE_TARGET_CURRENT="currently %1$d games × %2$d = %3$d goals"
COM_SPORTSMANAGER_RACE_MARGIN="Minimum margin at the target"
COM_SPORTSMANAGER_RACE_CAP="Won at the latest at"
COM_SPORTSMANAGER_RACE_DRAW="Draw at the target"
COM_SPORTSMANAGER_RACE_DRAW_NO="No"
COM_SPORTSMANAGER_RACE_DRAW_YES="Yes one goal below the target"
COM_SPORTSMANAGER_RACE_HELP="The score runs through the whole match: game 1 ends at the step, game 2 at twice the step, and so on up to the target. Minimum margin and limit apply to the last game only. Race requires “game result as game points” and one set per game both are set along with it."
COM_SPORTSMANAGER_ADD_GAME="Add a game"
COM_SPORTSMANAGER_ADD_LINK="Add a link"
COM_SPORTSMANAGER_REMOVE_GAME="Remove this game"
COM_SPORTSMANAGER_REMOVE_LINK="Remove this link"
COM_SPORTSMANAGER_LINK_NUMBER="Link no. %d"
COM_SPORTSMANAGER_GROUP_SEQUENCE="Game sequence"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK_FIRST_ONE="the first game only"
COM_SPORTSMANAGER_GAMES_IN_STATISTIK_FIRST="the first %d games only"
COM_SPORTSMANAGER_POINT_TYPE_CHANGED_WARNING="Results have already been entered for this team schedule. The stored numbers are NOT converted afterwards they mean something else (goals instead of sets, or the other way round). Save anyway?"
COM_SPORTSMANAGER_PER_SET_VALUATION_CHANGED_WARNING="Results have already been entered for this team schedule. Switching the per-set valuation converts nothing: games without stored set results are valued at the full win value per set won, and their drawn sets are lost. And where a 'multiple sets' schedule in fact holds goals in its points fields (instead of sets), every goal will from now on count double, like a set won. Save anyway?"
COM_SPORTSMANAGER_RACE_RUNNING="Score"
COM_SPORTSMANAGER_TOTAL_SCORE="Total score"
@@ -1,26 +1,27 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/component-install.dtd"> <extension type="component" version="5.0" method="upgrade">
<extension type="component" version="3.0" method="upgrade">
<name>Sports manager</name> <name>Sports manager</name>
<creationDate>2020-09-30</creationDate> <creationDate>2025-03-12</creationDate>
<author>Sven Nickel</author> <author>Deutscher Tischfußball Verband</author>
<authorEmail>sven.nickel@gmail.com</authorEmail> <authorEmail>it@dtfb.de</authorEmail>
<copyright>All rights reserved</copyright> <copyright>All rights reserved</copyright>
<license>GNU/GPL</license> <license>GNU/GPL</license>
<version>1.7.1</version> <version>DEV</version>
<description>Verwaltung von Spielern und Vereinen in Mannschafts- und Individualwettbewerben</description> <description>Verwaltung von Spielern und Vereinen in Mannschafts- und Individualwettbewerben</description>
<namespace path="src">Dtfb\Component\com_sportsmanager</namespace>
<files folder="site"> <files folder="site">
<filename>index.html</filename> <filename>index.html</filename>
<filename>admin.php</filename> <filename>admin.php</filename>
<filename>api.php</filename> <filename>api.php</filename>
<filename>controller.php</filename>
<filename>database.php</filename>
<filename>sportsmanager.php</filename> <filename>sportsmanager.php</filename>
<filename>mathparser.php</filename> <filename>mathparser.php</filename>
<filename>tools.php</filename> <filename>tools.php</filename>
<filename>js/jquery.min.js</filename> <filename>js/jquery.min.js</filename>
<folder>database</folder>
<folder>images</folder> <folder>images</folder>
<folder>models</folder> <folder>models</folder>
<folder>src</folder>
<folder>util</folder>
<folder>views</folder> <folder>views</folder>
</files> </files>
<languages folder="site"> <languages folder="site">
@@ -31,14 +32,15 @@
<language tag="nl-NL">language/nl-NL/nl-NL.com_sportsmanager.ini <language tag="nl-NL">language/nl-NL/nl-NL.com_sportsmanager.ini
</language> </language>
</languages> </languages>
<scriptfile>install.php</scriptfile> <scriptfile>script.php</scriptfile>
<administration> <administration>
<files folder="admin"> <files folder="admin">
<filename>access.xml</filename> <filename>access.xml</filename>
<filename>sportsmanager.php</filename>
<filename>controller.php</filename>
<filename>index.html</filename> <filename>index.html</filename>
<folder>views</folder> <filename>RELEASE_NOTES.md</filename>
<folder>services</folder>
<folder>src</folder>
<folder>tmpl</folder>
</files> </files>
<languages folder="admin"> <languages folder="admin">
<language tag="en-GB">language/en-GB/en-GB.com_sportsmanager.ini <language tag="en-GB">language/en-GB/en-GB.com_sportsmanager.ini