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.
This commit is contained in:
svennickel
2026-09-09 22:52:18 +02:00
parent fa63e1e2d6
commit 1a111b792f
7 changed files with 744 additions and 721 deletions
@@ -4724,10 +4724,16 @@ function adminEditTeamspielmodus(): void
$spielpunkte_wertung_einzel = $jInput->get('spielpunkte_wertung_einzel', 0, 'INT');
$spielpunkte_wertung_doppel_separat = $jInput->get('spielpunkte_wertung_doppel_separat', 0, 'INT');
$spielpunkte_wertung_doppel = $spielpunkte_wertung_doppel_separat ? $jInput->get('spielpunkte_wertung_doppel', 0, 'INT') : $spielpunkte_wertung_einzel;
if ($spielpunkte_wertung_einzel == 4 && ($punktetyp != 1 || $satzergebnisse != 1))
$spielpunkte_wertung_einzel = 0;
if ($spielpunkte_wertung_doppel == 4 && ($punktetyp != 1 || $satzergebnisse != 1))
$spielpunkte_wertung_doppel = 0;
$spielpunkte_wertung_pruefen = function ($wertung) use ($punktetyp, $satzergebnisse) {
$erlaubt = array(0, 1, 2, 3, 10, 11, 13);
if (!in_array($wertung, $erlaubt))
$wertung = 0;
if ($wertung >= 10 && ($punktetyp != 1 || $satzergebnisse != 1))
$wertung = $wertung % 10;
return $wertung;
};
$spielpunkte_wertung_einzel = $spielpunkte_wertung_pruefen($spielpunkte_wertung_einzel);
$spielpunkte_wertung_doppel = $spielpunkte_wertung_pruefen($spielpunkte_wertung_doppel);
$spielpunkte_bedingung = $jInput->get('spielpunkte_bedingung', 0, 'INT');
$spielernamen = $jInput->get('spielernamen', 0, 'INT');
@@ -1854,7 +1854,7 @@ function getTabelleDirekterVergleich($teams,$veranstaltung,$spieltag)
. "\n WHERE teamspiel_modus_id = " . (int)($veranstaltung->modus_id ?? 0);
$wertungen = loadObjectList($db, $query);
$je_satz = count($wertungen) > 0
&& ($wertungen[0]->spielpunkte_wertung_einzel == 4 || $wertungen[0]->spielpunkte_wertung_doppel == 4);
&& ($wertungen[0]->spielpunkte_wertung_einzel >= 10 || $wertungen[0]->spielpunkte_wertung_doppel >= 10);
$gesamtpunkte = 1000;
$anzahl_spiele = 1000;
@@ -2002,7 +2002,7 @@ function getTabelleSpieltag($veranstaltung,$spieltag,$mannschaften = "",$offset_
. "\n WHERE teamspiel_modus_id = " . (int)($veranstaltung->modus_id ?? 0);
$wertungen = loadObjectList($db, $query);
$je_satz = count($wertungen) > 0
&& ($wertungen[0]->spielpunkte_wertung_einzel == 4 || $wertungen[0]->spielpunkte_wertung_doppel == 4);
&& ($wertungen[0]->spielpunkte_wertung_einzel >= 10 || $wertungen[0]->spielpunkte_wertung_doppel >= 10);
$query = "SELECT verein_id, teamname, zusatzpunkte,"
. "\n werte.*,"
@@ -5625,7 +5625,7 @@ function teamstatistikAktualisieren($geaenderte_veranstaltung_id = 0, $geaendert
. "\n WHERE teamspiel_modus_id = " . (int)($veranstaltung->modus_id ?? 0);
$wertungen = loadObjectList($db, $query);
$je_satz = count($wertungen) > 0
&& ($wertungen[0]->spielpunkte_wertung_einzel == 4 || $wertungen[0]->spielpunkte_wertung_doppel == 4);
&& ($wertungen[0]->spielpunkte_wertung_einzel >= 10 || $wertungen[0]->spielpunkte_wertung_doppel >= 10);
$query = "UPDATE #__sportsmanager_team"
. "\n LEFT JOIN"
@@ -6352,7 +6352,7 @@ function spielerstatistikAktualisieren($geaenderte_spielerstatistik_id = 0, $gea
$ergebnis = $heim_punkte > $gast_punkte ? 1 : ($heim_punkte < $gast_punkte ? 2 : 0);
$wertung = $begegnung->heim_spieler_2_id === NULL && $begegnung->gast_spieler_2_id === NULL
? $begegnung->spielpunkte_wertung_einzel : $begegnung->spielpunkte_wertung_doppel;
if ($wertung == 4 && !empty($begegnung->ergebnis_detailliert)) {
if ($wertung >= 10 && !empty($begegnung->ergebnis_detailliert)) {
$auswertung = runden_detailliert_auswertung($begegnung->ergebnis_detailliert);
$heim_saetze = $auswertung[1];
$unentschieden_saetze = $auswertung[2];
@@ -632,20 +632,24 @@ function spielpunkteFuerSpiel($wertung, $heim_punkte, $gast_punkte, $ergebnis_de
{
if ($wertung == 2)
return array($heim_punkte, $gast_punkte);
if ($wertung == 4) {
$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(2 * (int)$heim_punkte, 2 * (int)$gast_punkte);
return array($sieg * (int)$heim_punkte, $sieg * (int)$gast_punkte);
$auswertung = runden_detailliert_auswertung($ergebnis_detailliert);
return array(2 * $auswertung[1] + $auswertung[2], 2 * $auswertung[3] + $auswertung[2]);
return array($sieg * $auswertung[1] + $remis * $auswertung[2],
$sieg * $auswertung[3] + $remis * $auswertung[2]);
}
$sieg = $wertung == 0 ? 2 : ($wertung == 1 ? 3 : 1);
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) || $wertung == 3)
if ($heim_punkte == 0 && $gast_punkte == 0)
return array(0, 0);
return array(1, 1);
return array($remis, $remis);
}
function toreFuerSpiel($punktetyp, $satzergebnisse, $heim_punkte, $gast_punkte, $ergebnis_detailliert): array
@@ -1708,7 +1708,7 @@ if (count($spiele) > 0) {
static function tabelleAnzeigen($veranstaltung, $modus, $teams, $spieltag, $spieltage, $alleine_angezeigt, int $praesentation = 0): void
{
global $params;
$je_satz = !empty($modus) && ($modus->spielpunkte_wertung_einzel == 4 || $modus->spielpunkte_wertung_doppel == 4);
$je_satz = !empty($modus) && ($modus->spielpunkte_wertung_einzel >= 10 || $modus->spielpunkte_wertung_doppel >= 10);
if (count($teams) > 0) {
if ($alleine_angezeigt && $veranstaltung->tabellenwertung >= -1 && $veranstaltung->tabellenwertung <= 11 && count($spieltage) > 1) {
?>
@@ -4860,7 +4860,7 @@ class HTML_sportsmanager_admin
var _punktetyp_vorher = <?php echo !empty($row->satzergebnisse) ? 2 : (int)($row->punktetyp ?? 0); ?>;
var _hat_ergebnisse = <?php echo !empty($row->hat_ergebnisse) ? 'true' : 'false'; ?>;
var _wertung4_vorher = <?php echo !empty($row) && ($row->spielpunkte_wertung_einzel == 4 || $row->spielpunkte_wertung_doppel == 4) ? 'true' : 'false'; ?>;
var _wertung4_vorher = <?php echo !empty($row) && ($row->spielpunkte_wertung_einzel >= 10 || $row->spielpunkte_wertung_doppel >= 10) ? 'true' : 'false'; ?>;
function punktetyp_geprueft() {
if (!_hat_ergebnisse) return true;
@@ -4868,8 +4868,8 @@ class HTML_sportsmanager_admin
&& !confirm(<?php echo json_encode(Text::_('COM_SPORTSMANAGER_POINT_TYPE_CHANGED_WARNING')); ?>))
return false;
var separat = document.adminForm.spielpunkte_wertung_doppel_separat.value == 1;
var wertung4 = document.adminForm.spielpunkte_wertung_einzel.value == 4
|| (separat && document.adminForm.spielpunkte_wertung_doppel.value == 4);
var wertung4 = Number(document.adminForm.spielpunkte_wertung_einzel.value) >= 10
|| (separat && Number(document.adminForm.spielpunkte_wertung_doppel.value) >= 10);
if (wertung4 !== _wertung4_vorher)
return confirm(<?php echo json_encode(Text::_('COM_SPORTSMANAGER_PER_SET_VALUATION_CHANGED_WARNING')); ?>);
return true;
@@ -5136,7 +5136,9 @@ class HTML_sportsmanager_admin
}
$html .= '</optgroup>';
$html .= '<optgroup data-satzdetails="1" label="' . htmlspecialchars(Text::_('COM_SPORTSMANAGER_GAME_POINTS_FOR_SET'), ENT_QUOTES) . '"' . $verborgen . '>';
$html .= '<option value="4" data-satzdetails="1"' . $verborgen . $gewaehlt(4) . '>' . htmlentities_utf8(Text::_('COM_SPORTSMANAGER_WIN_2_POINTS_PER_SET')) . '</option>';
foreach (array(13 => 'COM_SPORTSMANAGER_WIN_1_POINT_PER_SET', 10 => 'COM_SPORTSMANAGER_WIN_2_POINTS_PER_SET', 11 => 'COM_SPORTSMANAGER_WIN_3_POINTS_PER_SET') as $wert => $schluessel) {
$html .= '<option value="' . $wert . '" data-satzdetails="1"' . $verborgen . $gewaehlt($wert) . '>' . htmlentities_utf8(Text::_($schluessel)) . '</option>';
}
$html .= '</optgroup>';
return $html;
};
@@ -12752,7 +12754,7 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
. "}\n";
}
}
if ($spielpunkte_wertung_einzel == 4 || $spielpunkte_wertung_doppel == 4) {
if ($spielpunkte_wertung_einzel >= 10 || $spielpunkte_wertung_doppel >= 10) {
echo "function satz_summen(nr) {\n"
. " var heim = document.getElementsByName('spiel_' + nr + '_heim_punkte_detailliert[]');\n"
. " var gast = document.getElementsByName('spiel_' + nr + '_gast_punkte_detailliert[]');\n"
@@ -12773,10 +12775,13 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
for ($i = 1; $i <= count($spieltypen); $i++) {
$d = $spieltypen[$i - 1][0] == "D";
$w = $d ? $spielpunkte_wertung_doppel : $spielpunkte_wertung_einzel;
if ($w == 4) {
if ($w >= 10) {
$g = $w % 10;
$sieg = $g == 0 ? 2 : ($g == 1 ? 3 : 1);
$remis = $g == 3 ? 0 : 1;
echo " satzstand = satz_summen(" . $i . ");\n"
. " sh += 2 * satzstand[0] + satzstand[1];\n"
. " sg += 2 * satzstand[2] + satzstand[1];\n";
. " sh += " . $sieg . " * satzstand[0] + " . $remis . " * satzstand[1];\n"
. " sg += " . $sieg . " * satzstand[2] + " . $remis . " * satzstand[1];\n";
continue;
}
echo " h = document.adminForm['spiel_" . $i . "_heim_punkte'];\n"
@@ -12927,10 +12932,10 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
echo "function spielpunkte_bedingung() {\n"
. " var spielpunkte_heim = 0;\n"
. " var spielpunkte_gast = 0;\n"
. " var spielpunkte_sieg_einzel = " . ($spielpunkte_wertung_einzel == 0 ? 2 : ($spielpunkte_wertung_einzel == 1 ? 3 : 1)) . ";\n"
. " var spielpunkte_sieg_doppel = " . ($spielpunkte_wertung_doppel == 0 ? 2 : ($spielpunkte_wertung_doppel == 1 ? 3 : 1)) . ";\n"
. " var spielpunkte_unentschieden_einzel = " . ($spielpunkte_wertung_einzel <= 1 ? 1 : 0) . ";\n"
. " var spielpunkte_unentschieden_doppel = " . ($spielpunkte_wertung_doppel <= 1 ? 1 : 0) . ";\n"
. " var spielpunkte_sieg_einzel = " . ($spielpunkte_wertung_einzel % 10 == 0 ? 2 : ($spielpunkte_wertung_einzel % 10 == 1 ? 3 : 1)) . ";\n"
. " var spielpunkte_sieg_doppel = " . ($spielpunkte_wertung_doppel % 10 == 0 ? 2 : ($spielpunkte_wertung_doppel % 10 == 1 ? 3 : 1)) . ";\n"
. " var spielpunkte_unentschieden_einzel = " . ($spielpunkte_wertung_einzel % 10 <= 1 ? 1 : 0) . ";\n"
. " var spielpunkte_unentschieden_doppel = " . ($spielpunkte_wertung_doppel % 10 <= 1 ? 1 : 0) . ";\n"
. " var punkte_heim;\n"
. " var punkte_gast;\n"
. " var satzstand;\n";
@@ -12939,10 +12944,14 @@ static function adminVerbandsorganMitglieder($rows,$verbandsorgan): void
$spiel_einzel = $spieltypen[$i - 1][0] != "D";
if (($spiel_einzel && $spielpunkte_wertung_einzel == 2) || (!$spiel_einzel && $spielpunkte_wertung_doppel == 2))
continue;
if (($spiel_einzel ? $spielpunkte_wertung_einzel : $spielpunkte_wertung_doppel) == 4) {
$w_spiel = $spiel_einzel ? $spielpunkte_wertung_einzel : $spielpunkte_wertung_doppel;
if ($w_spiel >= 10) {
$g = $w_spiel % 10;
$sieg = $g == 0 ? 2 : ($g == 1 ? 3 : 1);
$remis = $g == 3 ? 0 : 1;
echo " satzstand = satz_summen(" . $i . ");\n"
. " spielpunkte_heim += 2 * satzstand[0] + satzstand[1];\n"
. " spielpunkte_gast += 2 * satzstand[2] + satzstand[1];\n";
. " spielpunkte_heim += " . $sieg . " * satzstand[0] + " . $remis . " * satzstand[1];\n"
. " spielpunkte_gast += " . $sieg . " * satzstand[2] + " . $remis . " * satzstand[1];\n";
continue;
}
// Number(): .value ist eine Zeichenkette, "10" > "9" wäre sonst unwahr
@@ -501,7 +501,9 @@ COM_SPORTSMANAGER_ADD_SEASON="Saison hinzuf&uuml;gen"
COM_SPORTSMANAGER_GAME_POINTS_GAME="Spielpunkte"
COM_SPORTSMANAGER_WIN_1_POINT="Sieg: 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"
@@ -1177,6 +1179,6 @@ 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 2 Punkten 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_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"
@@ -501,7 +501,9 @@ COM_SPORTSMANAGER_ADD_SEASON="Add season"
COM_SPORTSMANAGER_GAME_POINTS_GAME="Game points"
COM_SPORTSMANAGER_WIN_1_POINT="Win: 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"
@@ -1177,6 +1179,6 @@ 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 2 points 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_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"