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.
This commit is contained in:
svennickel
2026-09-07 13:30:21 +02:00
parent 09ae1c1609
commit 554ad25156
3 changed files with 123 additions and 306 deletions
@@ -4620,11 +4620,7 @@ function adminEditTeamspielmodus(): void
if ($punkte_vorsprung_doppel > 1 && $punkte_sieg_doppel < 0) if ($punkte_vorsprung_doppel > 1 && $punkte_sieg_doppel < 0)
$punkte_sieg_doppel = abs($punkte_sieg_doppel); $punkte_sieg_doppel = abs($punkte_sieg_doppel);
// Ohne Siegbedingung („Beliebig") gibt es nichts, worauf sich Vorsprung oder Deckelung // Ohne Siegbedingung („Beliebig") gibt es nichts, worauf sich Vorsprung oder Deckelung
// beziehen koennten. Dann bleiben beide auf ihren neutralen Werten, statt eine Regel zu // beziehen koennten.
// behaupten, die nirgends greift.
// Ohne geforderten Vorsprung endet ein Spiel EXAKT beim Siegwert — dann kann eine
// Grenze nie greifen, und sie zu speichern hiesse, eine Regel zu behaupten, die nichts
// tut (Sven 2026-09-01). Gilt auf jeder Ebene gleich.
if ($punkte_vorsprung_einzel <= 1) $punkte_deckel_einzel = 0; if ($punkte_vorsprung_einzel <= 1) $punkte_deckel_einzel = 0;
if ($punkte_vorsprung_doppel <= 1) $punkte_deckel_doppel = 0; if ($punkte_vorsprung_doppel <= 1) $punkte_deckel_doppel = 0;
if ($punkte_sieg_einzel == 0) { if ($punkte_sieg_einzel == 0) {
@@ -4707,20 +4703,10 @@ function adminEditTeamspielmodus(): void
$saetze_modus_einzel = 0; $saetze_modus_einzel = 0;
$saetze_modus_doppel = 0; $saetze_modus_doppel = 0;
} }
// Die Satzzahl wird ZUSAETZLICH nach punkte_sieg_* gespiegelt — dorthin, wo seit jeher // Die Satzzahl wird ZUSAETZLICH nach punkte_sieg_* gespiegelt, damit eine aeltere
// steht, bei wievielen Saetzen ein Spiel gewonnen ist. Eine aeltere Programmfassung // Programmfassung dieselbe wahre Aussage liest: N Gewinnsaetze als N, eine feste
// liest damit weiter dieselbe wahre Aussage, obwohl sie die neue Spalte nicht kennt. // Satzzahl als den Stand, bei dem sie entschieden ist. Umkehrung der Ueberfuehrung
// // in update.php, also verlustfrei.
// Gewinnsaetze sind diese Aussage unmittelbar: N Gewinnsaetze = „gewonnen bei N".
// Aber auch eine feste Satzzahl laesst sich vollstaendig so sagen, denn sie legt fest,
// welche Endstaende es gibt: bei 4 festen Saetzen sind 4:0, 3:1 und 2:2 moeglich, also
// „gewonnen bei 3, Unentschieden bei 2:2" — genau die Bedeutung des negativen
// Vorzeichens. Bei ungerader Satzzahl gibt es kein Unentschieden: 3 feste Saetze heissen
// „gewonnen bei 2". Das ist die Umkehrung der Ueberfuehrung (Datenbankversion 124) und
// deshalb verlustfrei in beide Richtungen.
//
// Fuer punkte_sieg_* = 0 („keine Siegbedingung") bleibt damit nur, was es auch bisher
// meinte: „Beliebig" — keine Angabe zur Satzzahl.
$sieg_aus_satzzahl = function ($modus) { $sieg_aus_satzzahl = function ($modus) {
if ($modus < 0) return -$modus; // N Gewinnsaetze if ($modus < 0) return -$modus; // N Gewinnsaetze
if ($modus == 0) return null; // keine Angabe if ($modus == 0) return null; // keine Angabe
@@ -4826,12 +4812,9 @@ function adminEditTeamspielmodus(): void
if (strlen($verknuepfungen) > 0) if (strlen($verknuepfungen) > 0)
$modus .= "|" . $verknuepfungen; $modus .= "|" . $verknuepfungen;
// Erst hier, weil das Ziel die Anzahl der Spiele braucht: Race setzt „ein Satz je // Erst hier, weil das Ziel die Anzahl der Spiele braucht: Race setzt „ein Satz je Spiel"
// Spiel" und „Spielergebnis als Spielpunkte" voraus, und das Ziel wird in die // und „Spielergebnis als Spielpunkte" voraus, und das Ziel wird in die Altfelder gespiegelt
// Altfelder gespiegelt — dieselbe wahre Aussage, die dort seit jeher steht („das Spiel // — dieselbe wahre Aussage, die dort seit jeher steht („das Spiel ist bei N Toren
// ist bei N Toren gewonnen"), damit eine aeltere Programmfassung nichts Falsches liest.
// Vorsprung und Grenze werden NICHT gespiegelt: sie gelten nur fuer das letzte Spiel,
// waehrend die Altfelder fuer alle gelten wuerden.
if ($zaehlweise == 1) { if ($zaehlweise == 1) {
$spiele_anzahl = count(array_filter(explode(",", explode("|", $modus)[0]), 'strlen')); $spiele_anzahl = count(array_filter(explode(",", explode("|", $modus)[0]), 'strlen'));
$race_ziel = $spiele_anzahl * $race_schritt; $race_ziel = $spiele_anzahl * $race_schritt;
@@ -11217,13 +11200,8 @@ function adminSaveBegegnungSpielplan(): void
} else { } else {
$spiel_heim_punkte_detailliert = $begegnung_input->get('spiel_' . $spiel_nr . '_heim_punkte_detailliert', array(), 'ARRAY'); $spiel_heim_punkte_detailliert = $begegnung_input->get('spiel_' . $spiel_nr . '_heim_punkte_detailliert', array(), 'ARRAY');
$spiel_gast_punkte_detailliert = $begegnung_input->get('spiel_' . $spiel_nr . '_gast_punkte_detailliert', array(), 'ARRAY'); $spiel_gast_punkte_detailliert = $begegnung_input->get('spiel_' . $spiel_nr . '_gast_punkte_detailliert', array(), 'ARRAY');
// Ein Formular mit Satzfeldern schickt sie fuer JEDES Spiel mit, auch fuer die, // Durchweg leere Satzfelder sind keine Aussage ueber Saetze, sondern „hier wurde
// in denen nichts steht. Durchweg leere Satzfelder sind aber keine Aussage ueber // nichts eingetragen" — sonst loescht blosses Oeffnen und Speichern den Altbestand.
// Saetze — sie sagen „hier wurde nichts eingetragen". Ohne diese Unterscheidung
// gewinnt die leere Satzangabe gegen ein vorhandenes Summenergebnis, und das
// blosse Oeffnen und Speichern einer alten Begegnung loescht sie: gemessen an
// einer Begegnung mit sieben gespeicherten Spielen, von denen nach dem Speichern
// eines uebrig war.
$satzfelder_leer = true; $satzfelder_leer = true;
foreach ($spiel_heim_punkte_detailliert as $wert) { foreach ($spiel_heim_punkte_detailliert as $wert) {
if ($wert !== '' && $wert !== null) { if ($wert !== '' && $wert !== null) {
@@ -11246,18 +11224,9 @@ function adminSaveBegegnungSpielplan(): void
if (empty($spiel_heim_punkte_detailliert)) { if (empty($spiel_heim_punkte_detailliert)) {
$spiel_heim_punkte = $begegnung_input->get('spiel_' . $spiel_nr . '_heim_punkte', 0, 'INT'); $spiel_heim_punkte = $begegnung_input->get('spiel_' . $spiel_nr . '_heim_punkte', 0, 'INT');
$spiel_gast_punkte = $begegnung_input->get('spiel_' . $spiel_nr . '_gast_punkte', 0, 'INT'); $spiel_gast_punkte = $begegnung_input->get('spiel_' . $spiel_nr . '_gast_punkte', 0, 'INT');
// Der gespiegelte Stand („3:1") steht seit jeher in ergebnis_detailliert, // Wo der Wettbewerb Ergebnisse JE SATZ fuehrt, bleibt ergebnis_detailliert bei einer
// wenn eine Meldung ohne Satzfelder kommt. Wo der Wettbewerb Ergebnisse JE // Meldung ohne Satzfelder LEER: das eine Paar bedeutet dort Saetze, und wer es als
// SATZ fuehrt, ist dieses eine Paar aber irrefuehrend: das Feld bedeutet // Tore liest, rechnet 1:0 statt 3:1. Der Satzstand steht in teamspiel_*_punkte.
// dort Saetze, und wer es so liest, sieht einen Satz mit drei Toren und
// rechnet daraus 1:0 statt 3:1 (genau der Fehler, der in unserer eigenen
// App steckte). Ein Altclient, der die Einstellung nicht kennt, meldet
// genau so — deshalb bleibt das Feld dann LEER: der Satzstand steht in
// teamspiel_*_punkte, und die Tore darin sind eben nicht bekannt.
//
// Erfundene Platzhalter („1:0" je gewonnenen Satz) waeren die Alternative
// und sind bewusst verworfen: gespeichert liesse sie niemand mehr von einer
// echten Meldung unterscheiden (Sven 2026-09-03).
$ergebnis_detailliert = ($spiel_heim_punkte == 0 && $spiel_gast_punkte == 0) $ergebnis_detailliert = ($spiel_heim_punkte == 0 && $spiel_gast_punkte == 0)
|| !empty($teamspiel_modus->satzergebnisse) || !empty($teamspiel_modus->satzergebnisse)
? '' ? ''
@@ -11317,15 +11286,8 @@ function adminSaveBegegnungSpielplan(): void
$spiel_gast_spieler_2_id = $t; $spiel_gast_spieler_2_id = $t;
} }
// Echte Satzergebnisse nicht durch ihren eigenen Spiegel ersetzen. // Echte Satzergebnisse nicht durch ihren eigenen Spiegel ersetzen: bringt ein Aufruf
// // keine Satzfelder mit und stehen im Bestand mehrere Paare, bleibt der Detailtext.
// Stellt jemand einen Wettbewerb von „Mehrere - mit Ergebnis je Satz" zurueck
// auf „nur der Satzstand", bietet das Formular danach nur noch die
// Summenfelder — und ein blosses Oeffnen und Speichern schriebe „3:1" ueber
// ein gespeichertes „6:3 3:6 6:3". Eng gefasst: nur wenn dieser Aufruf gar
// keine Satzfelder mitbringt, der Stand unveraendert bleibt und im Bestand
// mehr als ein Paar steht, bleibt der Detailtext, wie er ist (Sven
// 2026-09-01).
if (isset($spiel_heim_punkte_detailliert) && empty($spiel_heim_punkte_detailliert) if (isset($spiel_heim_punkte_detailliert) && empty($spiel_heim_punkte_detailliert)
&& isset($spiele_nummern[$spiel_nr])) { && isset($spiele_nummern[$spiel_nr])) {
$bestand = $spiele_nummern[$spiel_nr]; $bestand = $spiele_nummern[$spiel_nr];
@@ -11363,6 +11325,16 @@ function adminSaveBegegnungSpielplan(): void
$total_heim_punkte += $spiel_heim_punkte; $total_heim_punkte += $spiel_heim_punkte;
$total_gast_punkte += $spiel_gast_punkte; $total_gast_punkte += $spiel_gast_punkte;
// Gleichstand ist nicht immer ein Unentschieden. Wo eine Zahl von GEWINNSAETZEN
// gilt, hat ein Spiel mit gleichem Satzstand einfach noch keinen Sieger — es ist
// unfertig, und dafuer gibt es keinen Punkt. Ohne Angabe zur Satzzahl bleibt es
// beim bisherigen Verhalten.
$remis_moeglich = function ($saetze_modus) {
if ($saetze_modus == 0) return true; // keine Angabe
if ($saetze_modus < 0) return false; // Gewinnsaetze: am Ende steht keiner gleich
return $saetze_modus % 2 == 0; // feste Satzzahl: nur eine gerade endet remis
};
if ($spieltyp[0] != "D") { if ($spieltyp[0] != "D") {
if ($spielpunkte_wertung_einzel == 2) { if ($spielpunkte_wertung_einzel == 2) {
$spiel_heim_spielpunkte = $spiel_heim_punkte; $spiel_heim_spielpunkte = $spiel_heim_punkte;
@@ -11377,7 +11349,8 @@ function adminSaveBegegnungSpielplan(): void
} else if ($spiel_heim_punkte == 0 && $spiel_gast_punkte == 0) { } else if ($spiel_heim_punkte == 0 && $spiel_gast_punkte == 0) {
$spiel_heim_spielpunkte = 0; $spiel_heim_spielpunkte = 0;
$spiel_gast_spielpunkte = 0; $spiel_gast_spielpunkte = 0;
} else if ($spielpunkte_wertung_einzel != 3) { } else if ($spielpunkte_wertung_einzel != 3
&& $remis_moeglich($teamspiel_modus->saetze_modus_einzel)) {
$spiel_heim_spielpunkte = 1; $spiel_heim_spielpunkte = 1;
$spiel_gast_spielpunkte = 1; $spiel_gast_spielpunkte = 1;
} else { } else {
@@ -11399,7 +11372,8 @@ function adminSaveBegegnungSpielplan(): void
} else if ($spiel_heim_punkte == 0 && $spiel_gast_punkte == 0) { } else if ($spiel_heim_punkte == 0 && $spiel_gast_punkte == 0) {
$spiel_heim_spielpunkte = 0; $spiel_heim_spielpunkte = 0;
$spiel_gast_spielpunkte = 0; $spiel_gast_spielpunkte = 0;
} else if ($spielpunkte_wertung_doppel != 3) { } else if ($spielpunkte_wertung_doppel != 3
&& $remis_moeglich($teamspiel_modus->saetze_modus_doppel)) {
$spiel_heim_spielpunkte = 1; $spiel_heim_spielpunkte = 1;
$spiel_gast_spielpunkte = 1; $spiel_gast_spielpunkte = 1;
} else { } else {
@@ -5789,71 +5789,22 @@ function updateDatabase(): void
if ($datenbank_version < 122) { if ($datenbank_version < 122) {
// SIEGBEDINGUNGEN vollstaendig abbilden (Issue #304). // Siegbedingungen vollstaendig abbilden (Issue #304). Muss der LETZTE Block der
// Kette bleiben, sonst bleibt die kleinere Versionsnummer stehen.
// //
// Datenbankversion 122, nicht 121: 121 gehoert dem Hall-of-Fame-Zweig (PR #303, // Wertebereiche der neuen Spalten:
// Issue #300), der die Spalten teamspieler und nicht_ausgespielt bringt. Dieser // satz_sieg_* 0 = nicht hinterlegt; sonst Betrag = Siegwert, negativ
// Block muss der LETZTE der Kette bleiben. Die Reihenfolge ist nicht bloss Kosmetik: // erlaubt ein Remis ein Tor darunter (wie punkte_sieg_*)
// $datenbank_version wird einmal am Anfang gelesen, also laufen beide Bloecke im // saetze_modus_* 0 = wie bisher, N > 0 = feste Satzzahl, -N = N Gewinnsaetze
// selben Aufruf — aber jeder schreibt am Ende seine eigene Nummer, und die des // entscheidung_* 0 = keine Abweichung vom satz_*-Wert
// zuletzt gelaufenen bleibt stehen. Stuende dieser Block vor dem 121er, waere die // zaehlweise 0 = je Spiel, 1 = Race (Stand laeuft durch die Begegnung)
// gespeicherte Version danach 121, und beim naechsten Seitenaufruf liefe alles
// erneut.
// //
// Bisher sagte ein Mannschaftsspielmodus mit einer einzigen Zahl, wann ein Spiel // satzergebnisse ist eine EIGENE Spalte und kein dritter punktetyp-Wert: punktetyp
// endet: punkte_sieg_einzel/_doppel, deren Vorzeichen zusaetzlich ein // ist das Feld, aus dem fremde Anwendungen ablesen, ob die Punkte eines Spiels Tore
// Unentschieden zulaesst. Verbreitete Modi sind damit nicht darstellbar — „6 Tore, // oder Saetze sind, und kennt seit jeher zwei Werte.
// aber zwei Vorsprung, spaetestens bei 8" —, und wer nach Saetzen spielt, kann die
// Regel des einzelnen Satzes nirgends hinterlegen. Diese Ueberfuehrung ergaenzt
// deshalb drei Ebenen derselben Regel, die Satzzahl, die Angabe ob Saetze einzeln
// eingetragen werden, und eine Zaehlweise.
// //
// Alle Vorgabewerte beschreiben GENAU das heutige Verhalten, und keine bestehende // Alle Vorgabewerte beschreiben das heutige Verhalten; keine bestehende Spalte wird
// Spalte wird angetastet. Eine aeltere Programmfassung liest die neuen Spalten // angetastet.
// nicht und rechnet unveraendert weiter; ein Client, der nur die ueberlieferten
// Felder kennt, findet dort dieselbe Auskunft wie vorher.
//
// SPIELEBENE — punkte_vorsprung_* (wie viele klar voraus, 1 = ein Tor genuegt, also
// das heutige Verhalten) und punkte_deckel_* (Wert, bei dem das Spiel unabhaengig
// vom Vorsprung endet, 0 = keine Grenze).
//
// SATZEBENE — satz_sieg_* (0 = nicht hinterlegt, also der heutige Zustand; sonst
// dasselbe Vorzeichen wie punkte_sieg_*: Betrag = Siegwert, negativ erlaubt ein
// Remis ein Tor darunter), satz_vorsprung_*, satz_deckel_*. Die Regel INNERHALB
// eines Satzes hatte bisher keinen Platz: punkte_sieg_* misst dort, je nach
// punktetyp, entweder Tore („Einer") oder gewonnene Saetze („Mehrere").
//
// SATZZAHL — saetze_modus_*: 0 = wie bisher (allein punkte_sieg_* zaehlt Saetze,
// keine feste Zahl, kein Entscheidungssatz), N > 0 = feste Satzzahl N (alle werden
// gespielt), -N = N Gewinnsaetze (hoechstens 2N-1 Saetze, der letzte ist der
// Entscheidungssatz). Der Editor schreibt die Satzzahl ZUSAETZLICH nach
// punkte_sieg_* zurueck, damit eine aeltere Programmfassung dieselbe — wahre —
// Aussage liest wie bisher: N Gewinnsaetze als N, eine feste Satzzahl als den
// Stand, bei dem sie entschieden ist (4 feste Saetze = „gewonnen bei 3,
// Unentschieden bei 2:2" = -3; 3 feste Saetze = „gewonnen bei 2" = 2). Diese
// Spiegelung ist die Umkehrung der Ueberfuehrung unten und damit verlustfrei.
//
// ENTSCHEIDUNGSSATZ — entscheidung_*: abweichende Regel fuer den Satz, der bei N
// Gewinnsaetzen nach N-1 zu N-1 noch aussteht; sonst gilt satz_*.
// entscheidung_sieg_* = 0 heisst „keine Abweichung" und ist der Bestandswert.
//
// SATZERGEBNISSE — satzergebnisse: werden die Saetze eines Spiels mit ihrem
// jeweiligen Ergebnis eingetragen? Eine EIGENE Spalte und ausdruecklich kein
// dritter Wert in punktetyp: punktetyp ist das einzige Feld, aus dem eine fremde
// Anwendung ablesen muss, ob die Punkte eines Spiels Tore oder gewonnene Saetze
// sind, und es kennt seit jeher genau zwei Werte. Ein dritter haette jede Anwendung
// getroffen, die „1 = Saetze, sonst Tore" schreibt statt „0 = Tore, sonst Saetze" —
// beide Fassungen stehen im Sports Manager selbst, und mindestens ein Client
// (Kickern) ist von hier aus nicht mitzuziehen. So behaelt punktetyp seine
// Bedeutung: die Punkte SIND weiter die gewonnenen Saetze, die feinere Erfassung
// aendert daran nichts, und wer die neue Spalte nicht liest, verpasst das
// Zusaetzliche statt Falsches zu behaupten.
//
// ZAEHLWEISE — zaehlweise/race_*: im Race-Modus laeuft der Stand durch die ganze
// Begegnung, Spiel N endet also, wenn eine Seite N mal race_schritt erreicht.
// Eingetragen wird wie bisher die Differenz des einzelnen Spiels. race_vorsprung,
// race_deckel und race_remis gehoeren zum ZIEL, gelten also nur fuer das letzte
// Spiel der Folge. zaehlweise = 0 ist jeder Wettbewerb, der nichts anderes sagt.
$columns = $db->getTableColumns('#__sportsmanager_teamspiel_modus'); $columns = $db->getTableColumns('#__sportsmanager_teamspiel_modus');
if (!array_key_exists('satzergebnisse', $columns)) { if (!array_key_exists('satzergebnisse', $columns)) {
$query = "ALTER TABLE `#__sportsmanager_teamspiel_modus`" $query = "ALTER TABLE `#__sportsmanager_teamspiel_modus`"
@@ -5887,28 +5838,12 @@ function updateDatabase(): void
} }
} }
// Bestehende „Mehrere"-Modi in die Satzzahl ueberfuehren. // Bestehende „Mehrere"-Modi in die Satzzahl ueberfuehren — die Umkehrung der
// // Spiegelung, die der Editor beim Speichern vornimmt:
// * punkte_sieg_* = 1 ein Satz, und der wird gespielt. // punkte_sieg_* 1 -> ein fester Satz
// * punkte_sieg_* = N (ab 2) → N GEWINNSAETZE. Von den beiden Lesarten, die diese // N -> N Gewinnsaetze (haeufigere der beiden Lesarten)
// Zahl zulaesst (best of 2N-1 oder feste 2N-1 Saetze), ist das die weitaus // -N -> feste Satzzahl 2(N-1) (Remis setzt alle Saetze voraus)
// haeufigere; wessen Wettbewerb alle Saetze ausspielt, stellt eine Auswahl um. // 0 -> bleibt 0 („Beliebig")
// * punkte_sieg_* = -N → FESTE Satzzahl 2(N-1). Das Vorzeichen bedeutet „Remis bei
// N-1 zu N-1 moeglich", und ein Remis setzt voraus, dass alle Saetze gespielt
// werden: bei „Sieg 3, Remis 2:2" sind es vier.
// * 0 bleibt 0 und heisst „Beliebig": da war nie eine Regel.
//
// Auch ungewoehnliche Zahlen werden ueberfuehrt, nicht liegengelassen (Sven
// 2026-09-02). In „Mehrere" MISST punkte_sieg_* gewonnene Saetze — das ist die
// Bedeutung des Feldes, auch wenn ein Wettbewerb sie fuer Tore benutzt hat. Der
// Editor bietet solche Werte nicht zur Wahl an, zeigt den vorhandenen aber als
// eigenen Eintrag: sichtbar, unveraendert speicherbar, und einmal weggestellt
// nicht mehr einstellbar.
//
// Der Race-Modus wird NICHT automatisch erkannt; er ist aus Bestandsdaten nicht
// sicher abzuleiten und wird einmal von Hand gewaehlt.
//
// Nur dort, wo noch nichts gesetzt ist — ein zweiter Lauf aendert nichts.
$query = "UPDATE #__sportsmanager_teamspiel_modus" $query = "UPDATE #__sportsmanager_teamspiel_modus"
. "\n SET saetze_modus_einzel = CASE" . "\n SET saetze_modus_einzel = CASE"
. "\n WHEN punktetyp = 0 THEN 0" . "\n WHEN punktetyp = 0 THEN 0"
@@ -4665,27 +4665,15 @@ class HTML_sportsmanager_admin
$entscheidung_moeglich = $saetze_moeglich && ($row->saetze_modus_einzel ?? 0) < 0; $entscheidung_moeglich = $saetze_moeglich && ($row->saetze_modus_einzel ?? 0) < 0;
$entscheidung_moeglich_doppel = $doppel_separat && !empty($row) $entscheidung_moeglich_doppel = $doppel_separat && !empty($row)
&& $row->punktetyp != 0 && ($row->saetze_modus_doppel ?? 0) < 0; && $row->punktetyp != 0 && ($row->saetze_modus_doppel ?? 0) < 0;
// Wer die Satzzahl waehlt, legt damit die Siegbedingung des Spiels fest — Vorsprung // Wer die Satzzahl waehlt, legt damit die Siegbedingung des Spiels fest — Vorsprung und
// und Deckelung auf Spielebene haetten daneben nichts mehr zu sagen. // Deckelung auf Spielebene haetten daneben nichts mehr zu sagen.
// Bei „Mehrere" beantwortet die Satzzahl die Frage vollstaendig — „Spiel
// abgeschlossen bei" waere eine zweite Antwort auf dieselbe (Sven 2026-09-01).
// Die Auswahl bleibt im Dokument und sendet weiter ihren Wert, wird aber nicht
// mehr angeboten: ein Altwert ueberlebt dadurch unveraendert, ohne dass man ihn
// neu einstellen koennte.
$eigene_spielregel_verborgen = $saetze_moeglich; $eigene_spielregel_verborgen = $saetze_moeglich;
$eigene_spielregel_verborgen_doppel = $saetze_moeglich; $eigene_spielregel_verborgen_doppel = $saetze_moeglich;
// Im Race-Modus laeuft der Stand ueber die Begegnung durch; die Regeln des // Im Race-Modus laeuft der Stand ueber die Begegnung durch; die Regeln des
// einzelnen Spiels und des Satzes gibt es dort nicht. // einzelnen Spiels und des Satzes gibt es dort nicht.
$race_an = !empty($row) && ($row->zaehlweise ?? 0) != 0; $race_an = !empty($row) && ($row->zaehlweise ?? 0) != 0;
// Die Einheit der SPIELEBENE haengt an punktetyp: Tore bei „Einer", gewonnene // Die Einheit der Spielebene haengt an punktetyp: Tore bei „Einer", gewonnene
// Saetze bei „Mehrere". Bisher stand dort in beiden Faellen „Punkte" — und genau // Saetze bei „Mehrere". Vorher stand in beiden Faellen „Punkte".
// daran war eine Fehlkonfiguration nicht zu erkennen: „42 Punkte" liest sich
// plausibel, „42 Saetze" haette sofort auffallen lassen, dass hier Tore gemeint
// waren (Sven 2026-09-01).
//
// Beide Beschriftungen entstehen serverseitig und reisen als data-Attribut mit;
// beim Umschalten von punktetyp tauscht zeilen_anzeigen() sie ein. So bleibt jede
// Sprache uebersetzt, statt in JavaScript ein Wort zu raten.
$einheit_option = function ($wert, $gewaehlt, $tore, $saetze) use ($saetze_moeglich) { $einheit_option = function ($wert, $gewaehlt, $tore, $saetze) use ($saetze_moeglich) {
return "<option value=\"" . $wert . "\"" . ($gewaehlt ? " selected" : "") return "<option value=\"" . $wert . "\"" . ($gewaehlt ? " selected" : "")
. " data-tore=\"" . htmlentities_utf8($tore) . "\"" . " data-tore=\"" . htmlentities_utf8($tore) . "\""
@@ -4802,11 +4790,7 @@ class HTML_sportsmanager_admin
zeigen("row_saetze_modus_doppel", saetze && separat); zeigen("row_saetze_modus_doppel", saetze && separat);
zeigen("row_spielpunkte_wertung_doppel", !race && document.getElementById("row_spielpunkte_wertung_doppel") != null && document.adminForm.spielpunkte_wertung_doppel_separat.value == 1); zeigen("row_spielpunkte_wertung_doppel", !race && document.getElementById("row_spielpunkte_wertung_doppel") != null && document.adminForm.spielpunkte_wertung_doppel_separat.value == 1);
// Wer eine Satzzahl waehlt, hat die Siegbedingung des Spiels damit gesagt — // Wer eine Satzzahl waehlt, hat die Siegbedingung des Spiels damit gesagt —
// Vorsprung und Deckelung auf Spielebene haetten daneben nichts mehr zu // Vorsprung und Deckelung auf Spielebene haetten daneben nichts mehr zu melden.
// melden. Die Felder werden deshalb verborgen, nicht gesperrt: so senden
// sie weiter ihren urspruenglichen Wert, und ein Umweg ueber die Satzzahl
// und wieder zurueck auf „Beliebig" laesst eine ungewoehnliche
// Bestandszahl unberuehrt.
zeigen("row_punkte_sieg_einzel", !race && !saetze); zeigen("row_punkte_sieg_einzel", !race && !saetze);
zeigen("row_punkte_sieg_doppel", !race && !saetze && separat); zeigen("row_punkte_sieg_doppel", !race && !saetze && separat);
zeigen("row_punkte_vorsprung_einzel", !race && !saetze); zeigen("row_punkte_vorsprung_einzel", !race && !saetze);
@@ -4831,14 +4815,8 @@ class HTML_sportsmanager_admin
: '<?php echo Text::_('COM_SPORTSMANAGER_GAME_DOUBLES_SEPARATELY');?>'; : '<?php echo Text::_('COM_SPORTSMANAGER_GAME_DOUBLES_SEPARATELY');?>';
} }
// Spielfolge und Verknuepfungen: hinzufuegen und entfernen ohne Rueckfrage — es // Spielfolge und Verknuepfungen: hinzufuegen und entfernen ohne Rueckfrage — es ist
// ist nichts gespeichert, bis der Modus gespeichert wird (Sven 2026-09-01). // nichts gespeichert, bis der Modus gespeichert wird (Sven 2026-09-01).
//
// Alle Zeilen stehen im Dokument; sichtbar ist nur, was gebraucht wird.
// ENTFERNEN schiebt deshalb die Werte nach oben und blendet die letzte Zeile
// aus, statt eine Zeile herauszunehmen: das Speichern liest spiel_1, spiel_2 …
// der Reihe nach und bricht beim ersten leeren Paar ab — eine Luecke in der
// Mitte wuerde alles dahinter verschlucken.
function _zeilenZustand(praefix, anzahl) { function _zeilenZustand(praefix, anzahl) {
var letzte = 0; var letzte = 0;
for (var i = 1; i <= anzahl; i++) { for (var i = 1; i <= anzahl; i++) {
@@ -4938,14 +4916,9 @@ class HTML_sportsmanager_admin
<tr> <tr>
<td colspan="2" style="padding-bottom: 1em"> <td colspan="2" style="padding-bottom: 1em">
<?php <?php
// Die Begriffe stehen vor den Einstellungen, weil sie ineinander // Die Begriffe stehen vor den Einstellungen, weil
// stecken und die Gruppen unten genau dieser Leiter folgen. Ohne // sie ineinander stecken und die Gruppen unten
// sie ist „Spiel abgeschlossen bei" nicht von „Begegnung // genau dieser Leiter folgen.
// abgeschlossen bei" zu unterscheiden — und in „Mehrere" zaehlt
// das eine Saetze, das andere Spielpunkte.
//
// Absichtlich nicht durch htmlentities_utf8: der Text hebt die
// vier Begriffe selbst hervor.
?> ?>
<small class="sm_hinweis"><?php echo Text::_('COM_SPORTSMANAGER_MODE_GLOSSARY'); ?></small> <small class="sm_hinweis"><?php echo Text::_('COM_SPORTSMANAGER_MODE_GLOSSARY'); ?></small>
</td> </td>
@@ -4973,7 +4946,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="status" id="status" <select class="uk-select uk-form-width-large" name="status" id="status"
size="1"> size="1">
<?php <?php
$status = array(Text::_('COM_SPORTSMANAGER_NO'), Text::_('COM_SPORTSMANAGER_YES')); $status = array(Text::_('COM_SPORTSMANAGER_NO'), Text::_('COM_SPORTSMANAGER_YES'));
@@ -4995,7 +4968,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="zaehlweise" <select class="uk-select uk-form-width-large" name="zaehlweise"
id="zaehlweise" size="1" onChange="zeilen_anzeigen();"> id="zaehlweise" size="1" onChange="zeilen_anzeigen();">
<?php <?php
$zw = array(Text::_('COM_SPORTSMANAGER_COUNTING_PER_GAME'), Text::_('COM_SPORTSMANAGER_COUNTING_RACE')); $zw = array(Text::_('COM_SPORTSMANAGER_COUNTING_PER_GAME'), Text::_('COM_SPORTSMANAGER_COUNTING_RACE'));
@@ -5013,7 +4986,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="race_schritt" <select class="uk-select uk-form-width-large" name="race_schritt"
id="race_schritt" size="1" onChange="zeilen_anzeigen();"> id="race_schritt" size="1" onChange="zeilen_anzeigen();">
<?php <?php
// Sechs ist der Schritt, mit dem der Race-Modus gespielt wird; ohne // Sechs ist der Schritt, mit dem der Race-Modus gespielt wird; ohne
@@ -5058,7 +5031,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="race_vorsprung" <select class="uk-select uk-form-width-large" name="race_vorsprung"
id="race_vorsprung" size="1" onChange="zeilen_anzeigen();"> id="race_vorsprung" size="1" onChange="zeilen_anzeigen();">
<?php <?php
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
@@ -5074,7 +5047,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="race_deckel" <select class="uk-select uk-form-width-large" name="race_deckel"
id="race_deckel" size="1"> id="race_deckel" size="1">
<option value="0"<?php if (($row->race_deckel ?? 0) == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> <option value="0"<?php if (($row->race_deckel ?? 0) == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
<?php <?php
@@ -5091,7 +5064,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="race_remis" <select class="uk-select uk-form-width-large" name="race_remis"
id="race_remis" size="1"> id="race_remis" size="1">
<?php <?php
$rd = array(Text::_('COM_SPORTSMANAGER_RACE_DRAW_NO'), Text::_('COM_SPORTSMANAGER_RACE_DRAW_YES')); $rd = array(Text::_('COM_SPORTSMANAGER_RACE_DRAW_NO'), Text::_('COM_SPORTSMANAGER_RACE_DRAW_YES'));
@@ -5109,7 +5082,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="heimtausch" <select class="uk-select uk-form-width-large" name="heimtausch"
id="home_exchange" size="1"> id="home_exchange" size="1">
<?php <?php
$heimtausch = array(Text::_('COM_SPORTSMANAGER_NOT_ALLOWED'), Text::_('COM_SPORTSMANAGER_ALLOWED')); $heimtausch = array(Text::_('COM_SPORTSMANAGER_NOT_ALLOWED'), Text::_('COM_SPORTSMANAGER_ALLOWED'));
@@ -5127,7 +5100,7 @@ class HTML_sportsmanager_admin
: :
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="spielpunkte_wertung_einzel" id="points_valuation_single" name="spielpunkte_wertung_einzel" id="points_valuation_single"
size="1"> size="1">
<?php <?php
@@ -5156,7 +5129,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="spielpunkte_wertung_doppel" id="points_valuation_double" name="spielpunkte_wertung_doppel" id="points_valuation_double"
size="1"> size="1">
<?php <?php
@@ -5175,7 +5148,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="spielpunkte_bedingung" <select class="uk-select uk-form-width-large" name="spielpunkte_bedingung"
id="points_condition" id="points_condition"
size="1"> size="1">
<option <option
@@ -5203,7 +5176,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punktetyp" <select class="uk-select uk-form-width-large" name="punktetyp"
id="point_type" size="1" onChange="zeilen_anzeigen();"> id="point_type" size="1" onChange="zeilen_anzeigen();">
<?php <?php
// Drei Eintraege, zwei Felder: der dritte ist „Mehrere" samt der // Drei Eintraege, zwei Felder: der dritte ist „Mehrere" samt der
@@ -5250,7 +5223,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="saetze_modus_einzel" <select class="uk-select uk-form-width-large" name="saetze_modus_einzel"
id="saetze_modus_einzel" size="1" onChange="zeilen_anzeigen();"> id="saetze_modus_einzel" size="1" onChange="zeilen_anzeigen();">
<option value="0"<?php if ($row == null || ($row->saetze_modus_einzel ?? 0) == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option> <option value="0"<?php if ($row == null || ($row->saetze_modus_einzel ?? 0) == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option>
<?php <?php
@@ -5291,7 +5264,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="saetze_modus_doppel" <select class="uk-select uk-form-width-large" name="saetze_modus_doppel"
id="saetze_modus_doppel" size="1" onChange="zeilen_anzeigen();"> id="saetze_modus_doppel" size="1" onChange="zeilen_anzeigen();">
<option value="0"<?php if ($row == null || ($row->saetze_modus_doppel ?? 0) == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option> <option value="0"<?php if ($row == null || ($row->saetze_modus_doppel ?? 0) == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option>
<?php <?php
@@ -5331,7 +5304,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punkte_sieg_einzel" <select class="uk-select uk-form-width-large" name="punkte_sieg_einzel"
id="points_win_single" size="1"> id="points_win_single" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option>
@@ -5356,7 +5329,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punkte_sieg_doppel" <select class="uk-select uk-form-width-large" name="punkte_sieg_doppel"
id="points_win_double" size="1"> id="points_win_double" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option>
@@ -5381,7 +5354,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punkte_vorsprung_einzel" <select class="uk-select uk-form-width-large" name="punkte_vorsprung_einzel"
id="points_margin_single" size="1" onChange="zeilen_anzeigen();"> id="points_margin_single" size="1" onChange="zeilen_anzeigen();">
<?php <?php
// Ein Vorsprung von 1 ist das bisherige Verhalten und bleibt die Vorgabe. // Ein Vorsprung von 1 ist das bisherige Verhalten und bleibt die Vorgabe.
@@ -5401,7 +5374,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punkte_vorsprung_doppel" <select class="uk-select uk-form-width-large" name="punkte_vorsprung_doppel"
id="points_margin_double" size="1" onChange="zeilen_anzeigen();"> id="points_margin_double" size="1" onChange="zeilen_anzeigen();">
<?php <?php
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
@@ -5420,7 +5393,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punkte_deckel_einzel" <select class="uk-select uk-form-width-large" name="punkte_deckel_einzel"
id="points_cap_single" size="1"> id="points_cap_single" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
@@ -5443,7 +5416,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="punkte_deckel_doppel" <select class="uk-select uk-form-width-large" name="punkte_deckel_doppel"
id="points_cap_double" size="1"> id="points_cap_double" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
@@ -5469,7 +5442,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="satz_sieg_einzel" <select class="uk-select uk-form-width-large" name="satz_sieg_einzel"
id="satz_sieg_einzel" size="1"> id="satz_sieg_einzel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option>
@@ -5495,7 +5468,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="satz_sieg_doppel" <select class="uk-select uk-form-width-large" name="satz_sieg_doppel"
id="satz_sieg_doppel" size="1"> id="satz_sieg_doppel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_ANY'); ?></option>
@@ -5521,7 +5494,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="satz_vorsprung_einzel" <select class="uk-select uk-form-width-large" name="satz_vorsprung_einzel"
id="satz_vorsprung_einzel" size="1" onChange="zeilen_anzeigen();"> id="satz_vorsprung_einzel" size="1" onChange="zeilen_anzeigen();">
<?php <?php
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
@@ -5538,7 +5511,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="satz_vorsprung_doppel" <select class="uk-select uk-form-width-large" name="satz_vorsprung_doppel"
id="satz_vorsprung_doppel" size="1" onChange="zeilen_anzeigen();"> id="satz_vorsprung_doppel" size="1" onChange="zeilen_anzeigen();">
<?php <?php
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
@@ -5555,7 +5528,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="satz_deckel_einzel" <select class="uk-select uk-form-width-large" name="satz_deckel_einzel"
id="satz_deckel_einzel" size="1"> id="satz_deckel_einzel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
@@ -5574,7 +5547,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="satz_deckel_doppel" <select class="uk-select uk-form-width-large" name="satz_deckel_doppel"
id="satz_deckel_doppel" size="1"> id="satz_deckel_doppel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
@@ -5598,7 +5571,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="entscheidung_sieg_einzel" <select class="uk-select uk-form-width-large" name="entscheidung_sieg_einzel"
id="entscheidung_sieg_einzel" size="1"> id="entscheidung_sieg_einzel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_DECIDING_SET_SAME'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_DECIDING_SET_SAME'); ?></option>
@@ -5624,7 +5597,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="entscheidung_sieg_doppel" <select class="uk-select uk-form-width-large" name="entscheidung_sieg_doppel"
id="entscheidung_sieg_doppel" size="1"> id="entscheidung_sieg_doppel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_DECIDING_SET_SAME'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_DECIDING_SET_SAME'); ?></option>
@@ -5650,7 +5623,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="entscheidung_vorsprung_einzel" <select class="uk-select uk-form-width-large" name="entscheidung_vorsprung_einzel"
id="entscheidung_vorsprung_einzel" size="1" onChange="zeilen_anzeigen();"> id="entscheidung_vorsprung_einzel" size="1" onChange="zeilen_anzeigen();">
<?php <?php
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
@@ -5667,7 +5640,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="entscheidung_vorsprung_doppel" <select class="uk-select uk-form-width-large" name="entscheidung_vorsprung_doppel"
id="entscheidung_vorsprung_doppel" size="1" onChange="zeilen_anzeigen();"> id="entscheidung_vorsprung_doppel" size="1" onChange="zeilen_anzeigen();">
<?php <?php
for ($i = 1; $i <= 10; $i++) { for ($i = 1; $i <= 10; $i++) {
@@ -5684,7 +5657,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="entscheidung_deckel_einzel" <select class="uk-select uk-form-width-large" name="entscheidung_deckel_einzel"
id="entscheidung_deckel_einzel" size="1"> id="entscheidung_deckel_einzel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
@@ -5703,7 +5676,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="entscheidung_deckel_doppel" <select class="uk-select uk-form-width-large" name="entscheidung_deckel_doppel"
id="entscheidung_deckel_doppel" size="1"> id="entscheidung_deckel_doppel" size="1">
<option <option
value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option> value="0"><?php echo Text::_('COM_SPORTSMANAGER_GAME_CAP_NONE'); ?></option>
@@ -5727,7 +5700,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="spielernamen" <select class="uk-select uk-form-width-large" name="spielernamen"
id="player_names" size="1"> id="player_names" size="1">
<?php <?php
$typ = array(0 => Text::_('COM_SPORTSMANAGER_OPTIONAL'), 1 => Text::_('COM_SPORTSMANAGER_OPTIONAL_BUT_SAME_IN_DOUBLES'), 2 => Text::_('COM_SPORTSMANAGER_REQUIRED')); $typ = array(0 => Text::_('COM_SPORTSMANAGER_OPTIONAL'), 1 => Text::_('COM_SPORTSMANAGER_OPTIONAL_BUT_SAME_IN_DOUBLES'), 2 => Text::_('COM_SPORTSMANAGER_REQUIRED'));
@@ -5745,7 +5718,7 @@ class HTML_sportsmanager_admin
:</label> :</label>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" name="spiele_in_spielerstatistik" <select class="uk-select uk-form-width-large" name="spiele_in_spielerstatistik"
id="games_in_statistik" size="1"> id="games_in_statistik" size="1">
<option value="0"<?php if ($row == null || $row->spiele_in_spielerstatistik == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_GAMES_IN_STATISTIK_ALL'); ?></option> <option value="0"<?php if ($row == null || $row->spiele_in_spielerstatistik == 0) echo " selected"; ?>><?php echo Text::_('COM_SPORTSMANAGER_GAMES_IN_STATISTIK_ALL'); ?></option>
<?php <?php
@@ -5775,13 +5748,8 @@ class HTML_sportsmanager_admin
$modus = $row != null ? explode("|", $row->modus) : null; $modus = $row != null ? explode("|", $row->modus) : null;
$spiele = $modus != null && isset($modus[0]) ? explode(",", $modus[0]) : array(); $spiele = $modus != null && isset($modus[0]) ? explode(",", $modus[0]) : array();
// Nur die vorhandenen Zeilen zeigen, nicht alle 36 leeren. // Nur die vorhandenen Zeilen zeigen, nicht alle 36 leeren.
// // Sven 2026-09-01: „Vorschlag: Spiel hinzufügen und
// Sven 2026-09-01: „Vorschlag: Spiel hinzufügen und Verknüpfung hinzufügen // Verknüpfung hinzufügen anstelle leere Spiele und
// anstelle leere Spiele und Verknüpfungen gleich anzuzeigen." Die Zeilen
// bleiben alle im Dokument — verborgen —, damit die Feldnamen
// spiel_1..spiel_36 luecklos bleiben: das Speichern liest sie der Reihe nach
// und bricht beim ersten leeren Paar ab. Entfernen schiebt deshalb die
// Werte nach oben, statt eine Zeile herauszunehmen.
$spiele_gefuellt = 0; $spiele_gefuellt = 0;
foreach ($spiele as $eintrag) { foreach ($spiele as $eintrag) {
if (strlen(trim($eintrag)) > 0) $spiele_gefuellt++; if (strlen(trim($eintrag)) > 0) $spiele_gefuellt++;
@@ -5806,7 +5774,7 @@ class HTML_sportsmanager_admin
<table> <table>
<tr> <tr>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="spiel_<?php echo $spiel_nr; ?>_heim" size="1" name="spiel_<?php echo $spiel_nr; ?>_heim" size="1"
onChange="zeilen_anzeigen();" onChange="zeilen_anzeigen();"
aria-label="<?php echo Text::sprintf('COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_HOME', $spiel_nr); ?>"> aria-label="<?php echo Text::sprintf('COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_HOME', $spiel_nr); ?>">
@@ -5818,7 +5786,7 @@ class HTML_sportsmanager_admin
</select> </select>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="spiel_<?php echo $spiel_nr; ?>_gast" size="1" name="spiel_<?php echo $spiel_nr; ?>_gast" size="1"
onChange="zeilen_anzeigen();" onChange="zeilen_anzeigen();"
aria-label="<?php echo Text::sprintf('COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_GUEST', $spiel_nr); ?>"> aria-label="<?php echo Text::sprintf('COM_SPORTSMANAGER_ARIA_LABEL_GAME_NUMBER_GUEST', $spiel_nr); ?>">
@@ -5831,7 +5799,7 @@ class HTML_sportsmanager_admin
<label <label
for="match_<?php echo $spiel_nr; ?>_starting_team"><?php echo Text::_('COM_SPORTSMANAGER_EDITION'); ?> for="match_<?php echo $spiel_nr; ?>_starting_team"><?php echo Text::_('COM_SPORTSMANAGER_EDITION'); ?>
:</label> :</label>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="spiel_<?php echo $spiel_nr; ?>_auflage" name="spiel_<?php echo $spiel_nr; ?>_auflage"
id="match_<?php echo $spiel_nr; ?>_starting_team" id="match_<?php echo $spiel_nr; ?>_starting_team"
size="1"> size="1">
@@ -5887,7 +5855,7 @@ class HTML_sportsmanager_admin
<table> <table>
<tr> <tr>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="verknuepfung_<?php echo $verknuepfung_nr; ?>_doppel" name="verknuepfung_<?php echo $verknuepfung_nr; ?>_doppel"
size="1" size="1"
aria-label="<?php echo Text::_('COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_DOUBLE'); ?>"> aria-label="<?php echo Text::_('COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_DOUBLE'); ?>">
@@ -5900,7 +5868,7 @@ class HTML_sportsmanager_admin
</select> </select>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="verknuepfung_<?php echo $verknuepfung_nr; ?>_einzel1" name="verknuepfung_<?php echo $verknuepfung_nr; ?>_einzel1"
size="1" size="1"
aria-label="<?php echo Text::_('COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_SINGLE'); ?>"> aria-label="<?php echo Text::_('COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_SINGLE'); ?>">
@@ -5913,7 +5881,7 @@ class HTML_sportsmanager_admin
</select> </select>
</td> </td>
<td nowrap> <td nowrap>
<select class="uk-select uk-form-width-medium" <select class="uk-select uk-form-width-large"
name="verknuepfung_<?php echo $verknuepfung_nr; ?>_einzel2" name="verknuepfung_<?php echo $verknuepfung_nr; ?>_einzel2"
size="1" size="1"
aria-label="<?php echo Text::_('COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_SINGLE'); ?>"> aria-label="<?php echo Text::_('COM_SPORTSMANAGER_ARIA_LABEL_GAME_LINK_SINGLE'); ?>">
@@ -12693,15 +12661,9 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
</tr> </tr>
<?php <?php
} }
// Der Gesamtstand, wie er beim Speichern entsteht — nicht der gespeicherte. // Der Gesamtstand, wie er beim Speichern entsteht — nicht
// // der gespeicherte. Hier stand „Zwischenergebnis" mit dem
// Hier stand „Zwischenergebnis" mit dem Wert aus der Datenbank. Sven // Wert aus der Datenbank.
// 2026-09-02: „Sollte man das nicht schlicht entfernen und stattdessen gut
// sichtbar einen Gesamtstand hinschreiben, der in Echtzeit … berechnet zu dem
// was gerade eingetragen ist?" Genau das: die Zahl, auf die es hinausläuft,
// gehoert an die Stelle, an der man hinsieht — und der gespeicherte Stand
// steht ohnehin in der Begegnungsliste, aus der man hierher kam. Ein Hinweis
// darunter braucht es nicht: „Gesamtstand" samt Zahl sagt es selbst.
?> ?>
<tr> <tr>
<td nowrap colspan="2">&nbsp;</td> <td nowrap colspan="2">&nbsp;</td>
@@ -12776,13 +12738,9 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
$punkte_vorsprung_doppel = max(1, (int)($teamspiel_modus->punkte_vorsprung_doppel ?? 1)); $punkte_vorsprung_doppel = max(1, (int)($teamspiel_modus->punkte_vorsprung_doppel ?? 1));
$punkte_deckel_einzel = max(0, (int)($teamspiel_modus->punkte_deckel_einzel ?? 0)); $punkte_deckel_einzel = max(0, (int)($teamspiel_modus->punkte_deckel_einzel ?? 0));
$punkte_deckel_doppel = max(0, (int)($teamspiel_modus->punkte_deckel_doppel ?? 0)); $punkte_deckel_doppel = max(0, (int)($teamspiel_modus->punkte_deckel_doppel ?? 0));
// Zweite Ebene: die Regel im einzelnen Satz. Eingetragen werden einzelne Saetze // Zweite Ebene: die Regel im einzelnen Satz. Eingetragen
// nur bei „Mehrere mit Satzergebnissen" — nur dort greift sie also. // werden einzelne Saetze nur bei „Mehrere mit
// Eine Mannschaft ohne hinterlegte Spieler braucht keine Spielerauswahl: // Satzergebnissen" — nur dort greift sie also.
// das Feld haette nur den Leereintrag und behauptete eine Wahl, die es nicht
// gibt (Sven 2026-09-02). Gespeichert wird dann genau wie bei einer leeren
// Auswahl — der Server liest die fehlenden Felder mit Vorgabe 0, also
// „kein Spieler", und `$spieler_angegeben` bleibt falsch.
$heim_hat_spieler = !empty($heim_spieler); $heim_hat_spieler = !empty($heim_spieler);
$gast_hat_spieler = !empty($gast_spieler); $gast_hat_spieler = !empty($gast_spieler);
$satzweise = ($teamspiel_modus->satzergebnisse ?? 0) != 0; $satzweise = ($teamspiel_modus->satzergebnisse ?? 0) != 0;
@@ -12822,24 +12780,8 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
// punkte_gegner brauchen beide Ebenen — das Spiel und der Satz. // punkte_gegner brauchen beide Ebenen — das Spiel und der Satz.
if ($handheld != "yes" && ($race_an || $punkte_sieg_einzel != 0 || $punkte_sieg_doppel != 0 if ($handheld != "yes" && ($race_an || $punkte_sieg_einzel != 0 || $punkte_sieg_doppel != 0
|| ($satzweise && ($satz_sieg_einzel != 0 || $satz_sieg_doppel != 0)))) { || ($satzweise && ($satz_sieg_einzel != 0 || $satz_sieg_doppel != 0)))) {
// Der Gegenwert zu einem eingegebenen Stand — also die Ergaenzung, die das // Der Gegenwert zu einem eingegebenen Stand: was die andere Seite hoechstens haben
// Formular anbietet, wenn nur eine Seite eingetragen ist. // kann, wenn dieser Stand das Spiel beendet.
//
// Ergaenzt wird nur, was eindeutig ist: ein Stand UNTERHALB der Siegbedingung
// kann nicht der des Siegers sein, die andere Seite muss also gewonnen haben.
// Was dazu gehoert, ist `sieg`, bei Vorsprung entsprechend mehr, und nie mehr
// als die Deckelung — Beispiel Sieg 6, Vorsprung 2, Deckel 8: zu 5 gehoert 7,
// zu 4 die 6.
//
// Ein Stand, der selbst gewinnen KOENNTE, wird nicht ergaenzt: zu einer 6 bei
// Sieg 6 gehoert entweder 0..4 (dann hat sie gewonnen) oder 8 (dann verloren) —
// das ist geraten, nicht gefolgert. Leerer Rueckgabewert heisst „nichts
// eintragen"; die bisherige Fassung hatte dafuer eine eigene Abbruchbedingung
// auf Gleichheit mit der Siegbedingung.
//
// Das Unentschieden gilt nur OHNE Vorsprung: bei zwei Toren Vorsprung ist ein
// 5:5 bei „Sieg 6, Remis 5" kein Endstand, sondern ein laufendes Spiel. Der
// Editor speichert diese Kombination deshalb gar nicht mehr.
echo "function punkte_gegner(eingabe, sieg, vorsprung, deckel, unentschieden) {\n" echo "function punkte_gegner(eingabe, sieg, vorsprung, deckel, unentschieden) {\n"
. " var v = Number(eingabe);\n" . " var v = Number(eingabe);\n"
. " if (unentschieden != 0 && v == unentschieden)\n" . " if (unentschieden != 0 && v == unentschieden)\n"
@@ -12930,16 +12872,8 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
. "}\n"; . "}\n";
} }
} }
// Der Gesamtstand — und zwar DIE Zahl, die die Begegnung nach aussen // Der Gesamtstand: die Spielpunkte, wie sie Liste, Mannschaftsseite und Kopfzeile
// hat: die Spielpunkte. Liste, Mannschaftsseite und die Kopfzeile der // zeigen — gerechnet mit derselben Arithmetik wie beim Speichern.
// Begegnungsdetails zeigen alle heim_spielpunkte:gast_spielpunkte, also
// zeigt das Formular sie auch. Ich hatte hier zuerst die Summe der Tore
// gross und die Spielpunkte in Klammern — bei einem 5er-Spielplan stand da
// „6:4 (Spielpunkte 1:0)", wo die Begegnung 1:0 heisst (Sven 2026-09-02).
//
// Gerechnet wie der Server rechnet (admin.php,
// adminSaveBegegnungSpielplan): je Spiel aus der Wertung — Sieg 1/2/3,
// Unentschieden, oder das Ergebnis selbst.
echo "function gesamtstand_aktualisieren() {\n" echo "function gesamtstand_aktualisieren() {\n"
. " var sh = 0, sg = 0, h, g;\n"; . " var sh = 0, sg = 0, h, g;\n";
for ($i = 1; $i <= count($spieltypen); $i++) { for ($i = 1; $i <= count($spieltypen); $i++) {
@@ -12994,14 +12928,9 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
. " satzzeilen_anzeigen(nr);\n" . " satzzeilen_anzeigen(nr);\n"
. " gesamtstand_aktualisieren();\n" . " gesamtstand_aktualisieren();\n"
. "}\n" . "}\n"
// Gestaffelt zeigen: sichtbar ist die Mindestzahl, und dahinter genau // Gestaffelt zeigen: sichtbar ist die Mindestzahl,
// eine leere Zeile — nicht die volle Hoechstzahl. Sonst stuenden bei // und dahinter genau eine leere Zeile — nicht die
// sieben Spielen zu fuenf Saetzen siebzig Auswahlfelder da, von denen // volle Hoechstzahl.
// die meisten leer bleiben.
//
// Alle Zeilen bleiben im Dokument und werden mitgesendet; leere
// Satzpaare ueberspringt der Server ohnehin. Verborgen wird also nur,
// was man sieht, nicht was gespeichert wird.
. "function satzzeilen_anzeigen(nr) {\n" . "function satzzeilen_anzeigen(nr) {\n"
. " var min = satz_min_je_spiel[nr];\n" . " var min = satz_min_je_spiel[nr];\n"
. " if (min == null) return;\n" . " if (min == null) return;\n"
@@ -13325,15 +13254,9 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
</td> </td>
</tr> </tr>
<?php } else { <?php } else {
// „Mehrere (mit Satzergebnissen)": eingetragen werden die // „Mehrere (mit Satzergebnissen)":
// SAETZE, das Spielergebnis ergibt sich daraus. Genau so // eingetragen werden die SAETZE, das
// rechnet der Server ohnehin schon: liegen die // Spielergebnis ergibt sich daraus.
// *_detailliert-Felder vor, zaehlt adminSaveBegegnungSpielplan
// die gewonnenen Saetze selbst und laesst die Summenfelder
// links liegen. Die bleiben trotzdem im Formular — versteckt
// und mitgerechnet —, damit die Pruefungen
// (Spielpunkte-Bedingung, Spielernamen) unveraendert das
// lesen koennen, was sie immer gelesen haben.
$doppelspiel = $spieltypen[$spiel_nr - 1][0] == "D"; $doppelspiel = $spieltypen[$spiel_nr - 1][0] == "D";
$satz_sieg = $doppelspiel ? $satz_sieg_doppel : $satz_sieg_einzel; $satz_sieg = $doppelspiel ? $satz_sieg_doppel : $satz_sieg_einzel;
$satz_vorsprung = $doppelspiel ? $satz_vorsprung_doppel : $satz_vorsprung_einzel; $satz_vorsprung = $doppelspiel ? $satz_vorsprung_doppel : $satz_vorsprung_einzel;
@@ -13350,13 +13273,9 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
? (-2 * $saetze_wahl - 2) // 0-basiert: der (2N-1)-te Satz ? (-2 * $saetze_wahl - 2) // 0-basiert: der (2N-1)-te Satz
: -1; : -1;
// Vorbelegen nur, wenn die gespeicherten Saetze den // Vorbelegen nur, wenn die
// gespeicherten Spielstand auch ERGEBEN. Ein Wettbewerb, der // gespeicherten Saetze den
// von „Mehrere" auf „Mehrere mit Satzergebnissen" // gespeicherten Spielstand auch
// umgestellt wurde, hat in ergebnis_detailliert naemlich
// Altbestand stehen: dort spiegelt das Feld nur den
// Satzstand selbst („3:1"), es ist kein Satzergebnis. Wer
// das als ersten Satz anzeigt, erfindet ein Ergebnis.
$satz_werte = array(); $satz_werte = array();
if ($spiel != null && !empty($spiel->ergebnis_detailliert)) { if ($spiel != null && !empty($spiel->ergebnis_detailliert)) {
$gelesen = array(); $gelesen = array();
@@ -13380,12 +13299,9 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
$satz_werte = $gelesen; $satz_werte = $gelesen;
} }
// Wie viele Satzzeilen angeboten werden: die Deckelung des // Wie viele Satzzeilen angeboten
// SPIELS ist die Hoechstzahl der Saetze; fehlt sie, reicht // werden: die Deckelung des SPIELS ist
// „doppelte Siegbedingung minus eins" (best of). // die Hoechstzahl der Saetze; fehlt
// Wie viele Satzzeilen: die ausdrueckliche Wahl geht vor —
// feste Zahl N, oder 2N-1 bei N Gewinnsaetzen. Ohne Wahl wie
// bisher aus Deckelung bzw. Siegbedingung hergeleitet.
$satz_zeilen = $saetze_wahl > 0 $satz_zeilen = $saetze_wahl > 0
? $saetze_wahl ? $saetze_wahl
: ($saetze_wahl < 0 : ($saetze_wahl < 0
@@ -13395,16 +13311,8 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
: ($spiel_sieg != 0 ? 2 * $spiel_sieg - 1 : 5))); : ($spiel_sieg != 0 ? 2 * $spiel_sieg - 1 : 5)));
$satz_zeilen = min(15, max(1, $satz_zeilen)); $satz_zeilen = min(15, max(1, $satz_zeilen));
$satz_zeilen = max($satz_zeilen, count($satz_werte)); $satz_zeilen = max($satz_zeilen, count($satz_werte));
// Wie viele Zeilen von Anfang an SICHTBAR sind. Alle stehen im // Wie viele Zeilen sichtbar sind. Alle stehen im Dokument, weil das Speichern
// Dokument; gestaffelt gezeigt wird nur, wo eine Zeile ueber // spiel_1, spiel_2 ... der Reihe nach liest und beim ersten leeren Paar abbricht.
// bleiben KANN — bei einer festen Satzzahl werden alle
// gespielt, dort waere Verbergen eine Luege.
//
// Bei Gewinnsaetzen sind so viele noetig, wie zum Sieg
// gehoeren (drei bei „3 Gewinnsaetze"); die vierte und fuenfte
// erscheinen, sobald die dritte gefuellt ist. Ohne Angabe zur
// Satzzahl ist die Gesamtzahl ohnehin geraten — dann faengt es
// bei der Siegbedingung an, sonst bei einer Zeile.
$satz_min = $saetze_wahl > 0 $satz_min = $saetze_wahl > 0
? $satz_zeilen ? $satz_zeilen
: ($saetze_wahl < 0 : ($saetze_wahl < 0