WKVS v 1.0.0
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('wk_leitung');
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
require_once $baseDir . '/../scripts/delete_request_type_functions.php';
|
||||
|
||||
parse_input_to_delete();
|
||||
|
||||
verify_delete_csrf($_DELETE);
|
||||
|
||||
$programm_id = (int) ($_DELETE['programmId'] ?? 0);
|
||||
|
||||
if ($programm_id <= 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['success' => false, 'message' => 'Keine valide Programm-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
|
||||
$type = 'wkl';
|
||||
|
||||
$dbconnection = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($dbconnection['success'] !== true){
|
||||
echo 'Critical DB Error.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$programm_name = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_kategorien WHERE id = ? LIMIT 1", [$programm_id]) ?: null;
|
||||
|
||||
if ($programm_name === null) {
|
||||
echo json_encode(['success' => true, 'message' => 'Dieses Programm existiert nicht.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$personen = db_select($mysqli, $db_tabelle_teilnehmende, "id", '`programm` = ?', [$programm_name]);
|
||||
|
||||
if (count($personen) < 1) {
|
||||
echo json_encode(['success' => true, 'message' => 'Es existieren keine Personen mit diesem Programm.']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$personen_id_array = array_column($personen, 'id');
|
||||
|
||||
$parram_array = array_fill(0, count($personen_id_array), "?");
|
||||
$parram_string = implode(', ', $parram_array);
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$value_array = array_merge($personen_id_array, [$current_wk_id]);
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_wertungen WHERE `person_id` IN ($parram_string) AND `wk_id` = ?");
|
||||
|
||||
$types_string = str_repeat("i", count($personen_id_array)) . "i";
|
||||
$stmt->bind_param($types_string, ...$value_array);
|
||||
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
$stmt = $mysqli->prepare("DELETE FROM $db_tabelle_wertungen_log WHERE `person_id` IN ($parram_string) AND `wk_id` = ?");
|
||||
|
||||
$stmt->bind_param($types_string, ...$value_array);
|
||||
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'Noten gelöscht']);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$abt_id = intval($_POST['abteilungId'] ?? 1);
|
||||
|
||||
// Determine current year
|
||||
$current_year = date('Y');
|
||||
$monat = date('n');
|
||||
if ($monat > 6) $current_year++;
|
||||
|
||||
// Prepare SQL statement
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.id AS person_id
|
||||
FROM $db_tabelle_teilnehmende_gruppen tab
|
||||
INNER JOIN $db_tabelle_teilnehmende t ON tab.turnerin_id = t.id
|
||||
INNER JOIN $db_tabelle_gruppen ab ON ab.id = tab.abteilung_id
|
||||
WHERE ab.id = ?
|
||||
ORDER BY t.id ASC
|
||||
");
|
||||
|
||||
$stmt->bind_param('i', $abt_id);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$personen = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$indexedPersonen = array_column($personen, null, 'person_id');
|
||||
|
||||
// Close statement
|
||||
$stmt->close();
|
||||
|
||||
// 1. Get the IDs from the first query results
|
||||
$personenIds = array_column($personen, 'person_id');
|
||||
|
||||
if (empty($personenIds)) {
|
||||
echo json_encode(["success" => false, "message" => "Keine Notenänderungen vorhanden"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$placeholders = implode(',', array_fill(0, count($personenIds), '?'));
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$sqlNotenChanges = "DELETE FROM $db_tabelle_wertungen_log WHERE person_id IN ($placeholders) AND `wk_id` = ?";
|
||||
$stmtNotenChanges = $mysqli->prepare($sqlNotenChanges);
|
||||
|
||||
$paramsArray = array_merge($personenIds, [$current_wk_id]);
|
||||
|
||||
$types = str_repeat('i', count($personenIds)) . 's';
|
||||
|
||||
$stmtNotenChanges->bind_param($types, ...$paramsArray);
|
||||
|
||||
$stmtNotenChanges->execute();
|
||||
$stmtNotenChanges->close();
|
||||
|
||||
echo json_encode(["success" => true, "message" => "Notenänderung für Abteilung " . $abt_id . " gelöscht"]);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$mysqli->close();
|
||||
|
||||
if ($wkName === null) {
|
||||
echo json_encode(["success" => false, "message" => "Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$programm = trim($_POST['prog'] ?? '');
|
||||
|
||||
$current_year = date('Y');
|
||||
$monat = date('n');
|
||||
if ($monat > 6) $current_year++;
|
||||
|
||||
$dir = $baseDir . '/files/ranglisten/';
|
||||
$localPath = $dir . str_replace("/", "", str_replace(" ", "_", $wkName)) . "_Ergebnisse_" . str_replace("/", "", $programm) . "_" . $current_year . ".pdf";
|
||||
|
||||
if (!file_exists($localPath)) {
|
||||
echo json_encode(["success" => false, "message" => "Diese Rangliste existiert nicht."]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
unlink($localPath);
|
||||
|
||||
echo json_encode(["success" => true, "message" => "Rangliste gelöscht"]);
|
||||
http_response_code(200);
|
||||
@@ -0,0 +1,341 @@
|
||||
<?php
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// Validate editId from POST
|
||||
if (isset($_POST['editId'])) {
|
||||
$editId = intval($_POST['editId']);
|
||||
if ($editId === false || $editId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Falsche Personen ID']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$editId = filter_var($editId, FILTER_VALIDATE_INT);
|
||||
|
||||
if ($editId === false) {
|
||||
echo json_encode(['success' => true]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if (!($data['success'] ?? false)) {
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$is_payed = db_get_var($mysqli, "SELECT 1 FROM $db_tabelle_teilnehmende WHERE id = ? AND ((bezahltoverride = ?) OR (bezahlt = ? AND bezahltoverride = ?))", [$editId, 4, 4, 0]);
|
||||
|
||||
if ($is_payed != '1') {
|
||||
echo json_encode(['success'=> false, 'message'=> 'Startgebühr nicht bezahlt']);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$isAdmin = (($_SESSION['selectedFreigabeIdKampfrichter'] ?? '') === 'A') ? true : false;
|
||||
|
||||
$disciplines = db_select($mysqli, $db_tabelle_disziplinen, 'id', '', [], 'start_index ASC');
|
||||
|
||||
$disciplines = array_column($disciplines, "id");
|
||||
|
||||
$requested_discipline = trim($_POST['geraet'] ?? '');
|
||||
|
||||
$all_disciplines = false;
|
||||
|
||||
if ($isAdmin && $requested_discipline === 'A') {
|
||||
$all_disciplines = true;
|
||||
} else {
|
||||
$requested_discipline = (int) $requested_discipline;
|
||||
|
||||
if (!in_array($requested_discipline, $disciplines)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Falsche Geräte ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$discipline = $requested_discipline;
|
||||
}
|
||||
|
||||
if ($all_disciplines) {
|
||||
$stmt = $mysqli->prepare("SELECT t.`name`, t.`vorname`, t.`programm`, p.id as programm_id FROM $db_tabelle_teilnehmende t LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm WHERE t.id = ?");
|
||||
} else {
|
||||
|
||||
$disciplines = [$discipline];
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.name,
|
||||
t.vorname,
|
||||
t.programm,
|
||||
p.id as programm_id,
|
||||
agg.abteilung,
|
||||
agg.geraeteIndex,
|
||||
agg.startIndex
|
||||
FROM $db_tabelle_teilnehmende t
|
||||
LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
ta.turnerin_id,
|
||||
GROUP_CONCAT(DISTINCT a.name SEPARATOR ', ') AS abteilung,
|
||||
GROUP_CONCAT(DISTINCT g.start_index SEPARATOR ', ') AS geraeteIndex,
|
||||
ta.turnerin_index AS startIndex
|
||||
FROM $db_tabelle_teilnehmende_gruppen ta
|
||||
INNER JOIN $db_tabelle_gruppen a
|
||||
ON a.id = ta.abteilung_id
|
||||
LEFT JOIN $db_tabelle_disziplinen g
|
||||
ON g.id = ta.geraet_id
|
||||
GROUP BY ta.turnerin_id
|
||||
) agg ON agg.turnerin_id = t.id
|
||||
WHERE t.id = ?
|
||||
");
|
||||
|
||||
}
|
||||
$stmt->bind_param('i', $editId);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$dbresult = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if (!$dbresult || !is_array($dbresult) || count($dbresult) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Falsche Personen ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if ($all_disciplines) {
|
||||
$stmt = $mysqli->prepare("SELECT `note_bezeichnung_id`, `value`, `geraet_id`, `run_number` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `wk_id` = ?");
|
||||
|
||||
$stmt->bind_param('si', $editId, $current_wk_id);
|
||||
} else {
|
||||
$stmt = $mysqli->prepare("SELECT `note_bezeichnung_id`, `value`, `geraet_id`, `run_number` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `geraet_id` = ? AND `wk_id` = ?");
|
||||
|
||||
$stmt->bind_param('ssi', $editId, $discipline, $current_wk_id);
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$notenDB = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
|
||||
$indexedNotenDB = [];
|
||||
foreach ($notenDB as $sn) {
|
||||
$indexedNotenDB[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = $sn['value'];
|
||||
}
|
||||
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `id`, `default_value`, `nullstellen`, `pro_geraet`, `geraete_json`, `anzahl_laeufe_json` FROM $db_tabelle_wertungstypen");
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$notenConfig = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$displayIdNoteL = intval(db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['displayIdNoteL'])) ?? 0;
|
||||
$displayIdNoteR = intval(db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['displayIdNoteR'])) ?? 0;
|
||||
|
||||
if ($displayIdNoteL !== 0 && $displayIdNoteR !== 0) {
|
||||
$displayNoten = [$displayIdNoteR => 0, $displayIdNoteL => 0];
|
||||
}
|
||||
|
||||
|
||||
$noten = [];
|
||||
|
||||
$row = $dbresult[0];
|
||||
|
||||
$programm_id = $row['programm_id'];
|
||||
|
||||
foreach ($disciplines as $d) {
|
||||
foreach ($notenConfig as $snC) {
|
||||
$allowedGeraete = !empty($snC['geraete_json']) ? json_decode($snC['geraete_json'], true) : [];
|
||||
$isProGeraet = ($snC['pro_geraet'] === 1);
|
||||
|
||||
if (!$isProGeraet && !in_array($d, $allowedGeraete)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine number of runs for this program
|
||||
$anzRunsConfig = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];
|
||||
|
||||
$runs = $anzRunsConfig[$d][$programm_id] ?? $anzRunsConfig[$d]["all"] ?? $anzRunsConfig['default'] ?? 1;
|
||||
|
||||
if (isset($displayNoten) && array_key_exists($snC['id'], $displayNoten)) {
|
||||
$displayNoten[$snC['id']] = $runs;
|
||||
}
|
||||
|
||||
for ($r = 1; $r <= $runs; $r++) {
|
||||
$value = $indexedNotenDB[$d][$snC['id']][$r] ?? $snC['default_value'] ?? 0;
|
||||
$noten[$d][$r][$snC['id']] = number_format($value, $snC['nullstellen'] ?? 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$countBtn = 1;
|
||||
|
||||
if (isset($displayNoten)) {
|
||||
$countBtn = min($displayNoten);
|
||||
}
|
||||
|
||||
|
||||
$titel = $row['vorname'].' '.$row['name'].', '.$row['programm'];
|
||||
|
||||
if (!$all_disciplines) {
|
||||
|
||||
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.name,
|
||||
t.vorname,
|
||||
t.programm,
|
||||
t.id,
|
||||
agg.abteilung,
|
||||
agg.geraeteIndex,
|
||||
agg.startIndex
|
||||
FROM $db_tabelle_teilnehmende t
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
ta.turnerin_id,
|
||||
GROUP_CONCAT(DISTINCT a.name SEPARATOR ', ') AS abteilung,
|
||||
GROUP_CONCAT(DISTINCT g.start_index SEPARATOR ', ') AS geraeteIndex,
|
||||
ta.turnerin_index AS startIndex
|
||||
FROM $db_tabelle_teilnehmende_gruppen ta
|
||||
INNER JOIN $db_tabelle_gruppen a
|
||||
ON a.id = ta.abteilung_id
|
||||
LEFT JOIN $db_tabelle_disziplinen g
|
||||
ON g.id = ta.geraet_id
|
||||
GROUP BY ta.turnerin_id
|
||||
) agg ON agg.turnerin_id = t.id
|
||||
WHERE agg.abteilung = ? AND agg.geraeteIndex = ?
|
||||
ORDER BY t.id DESC
|
||||
");
|
||||
|
||||
|
||||
$bezahlt = 4;
|
||||
$bezahltoverride = 4;
|
||||
|
||||
$stmt->bind_param('ss', $row['abteilung'], $row['geraeteIndex']);
|
||||
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$entries = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if (!$entries || !is_array($entries) || count($entries) < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'No DB Result for next Turnerin']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
$maxstartindex = count($entries);
|
||||
|
||||
if ($maxstartindex < 1) {
|
||||
$maxstartindex = 1;
|
||||
}
|
||||
|
||||
$csti = (int)$row['startIndex'];
|
||||
$nsti = $csti + 1;
|
||||
|
||||
if ($nsti > $maxstartindex){
|
||||
$nsti -= $maxstartindex;
|
||||
}
|
||||
|
||||
$rohstartindex = intval($row['startIndex']);
|
||||
$varstartgeraet = intval($row['geraeteIndex']);
|
||||
|
||||
$aktsubabt = $_SESSION['currentsubabt'];
|
||||
|
||||
foreach ($disciplines as $index => $sdiscipline) {
|
||||
if (isset($sdiscipline) && $sdiscipline === $discipline) {
|
||||
$indexuser = $index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$calculedstartindex = $rohstartindex - $indexuser;
|
||||
|
||||
$calculedstartindex = $calculedstartindex >= 1 ? $calculedstartindex : $calculedstartindex + $maxstartindex;
|
||||
|
||||
|
||||
$nrow = null;
|
||||
|
||||
if ($calculedstartindex !== count($entries)){
|
||||
$nrow = null;
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry['startIndex'] == $nsti) {
|
||||
$nrow = $entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($nrow) {
|
||||
$nturnerin = [
|
||||
'name' => $nrow['vorname'].' '.$nrow['name'].', '.$nrow['programm'],
|
||||
'id' => $nrow['id']
|
||||
];
|
||||
} else {
|
||||
$nturnerin = [
|
||||
'name' => '--- nächste Gruppe ---',
|
||||
'id' => 0
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($isAdmin) {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'id' => $editId,
|
||||
'programm_id' => $programm_id,
|
||||
'titel' => $titel,
|
||||
'noten' => $noten,
|
||||
'countBtn' => $countBtn
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'id' => $editId,
|
||||
'programm_id' => $programm_id,
|
||||
'titel' => $titel,
|
||||
'noten' => $noten,
|
||||
'nturnerin' => $nturnerin,
|
||||
'countBtn' => $countBtn
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
<?php
|
||||
|
||||
use TCPDF;
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$wkName = ($wkName === null) ? 'Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen' : $wkName;
|
||||
|
||||
$normalFontSize = 11;
|
||||
$marginSide = 10;
|
||||
$marginTop = 10;
|
||||
$minMarginBottomTable = 20;
|
||||
$format = 'A4';
|
||||
$orientation = 'L';
|
||||
|
||||
$abt = intval($_POST['abteilungId'] ?? 1);
|
||||
|
||||
$now = trim($_POST['date'] ?? date('Y-m-d H:i:s'));
|
||||
|
||||
$geraete = db_select($mysqli, $db_tabelle_disziplinen, "*", '', [], "start_index ASC");
|
||||
|
||||
$IndexedGeraete = array_column($geraete, 'name', 'id');
|
||||
|
||||
$notenBezeichnungen = db_select($mysqli, $db_tabelle_wertungstypen, "`name`, `id`, `nullstellen`, `anzahl_laeufe_json`", '', [], "");
|
||||
|
||||
$IndexedNotenBezeichnungen = array_column($notenBezeichnungen, 'name', 'id');
|
||||
|
||||
$IndexedNotenNullstellen = array_column($notenBezeichnungen, 'nullstellen', 'id');
|
||||
|
||||
$IndexedNotenJsonGeraete = array_column($notenBezeichnungen, 'anzahl_laeufe_json', 'id');
|
||||
|
||||
$programme = db_select($mysqli, $db_tabelle_kategorien, "`programm`, `id`", '', [], "");
|
||||
|
||||
$indexedProgramme = array_column($programme, 'id', 'programm');
|
||||
|
||||
// Prepare SQL statement
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT
|
||||
t.id AS person_id,
|
||||
t.name,
|
||||
t.vorname,
|
||||
t.programm,
|
||||
t.verein,
|
||||
ab.id AS abteilung_id,
|
||||
tab.geraet_id AS start_geraet_id,
|
||||
tab.turnerin_index
|
||||
FROM $db_tabelle_teilnehmende_gruppen tab
|
||||
INNER JOIN $db_tabelle_teilnehmende t ON tab.turnerin_id = t.id
|
||||
INNER JOIN $db_tabelle_gruppen ab ON ab.id = tab.abteilung_id
|
||||
WHERE ab.id = ?
|
||||
ORDER BY t.id ASC
|
||||
");
|
||||
|
||||
$stmt->bind_param('i', $abt);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$personen = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$indexedPersonen = array_column($personen, null, 'person_id');
|
||||
|
||||
// Close statement
|
||||
$stmt->close();
|
||||
|
||||
// 1. Get the IDs from the first query results
|
||||
$personenIds = array_column($personen, 'person_id');
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if (!empty($personenIds)) {
|
||||
$placeholders = implode(',', array_fill(0, count($personenIds), '?'));
|
||||
|
||||
$sqlNotenChanges = "SELECT * FROM $db_tabelle_wertungen_log WHERE person_id IN ($placeholders) AND `wk_id` = ?";
|
||||
$stmtNotenChanges = $mysqli->prepare($sqlNotenChanges);
|
||||
|
||||
$paramsArray = array_merge($personenIds, [$current_wk_id]);
|
||||
|
||||
$types = str_repeat('i', count($personenIds)) . 's';
|
||||
|
||||
$stmtNotenChanges->bind_param($types, ...$paramsArray);
|
||||
|
||||
$stmtNotenChanges->execute();
|
||||
$notenChangesResult = $stmtNotenChanges->get_result();
|
||||
$notenChangesEntries = $notenChangesResult->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmtNotenChanges->close();
|
||||
} else {
|
||||
$notenChangesEntries = [];
|
||||
}
|
||||
|
||||
$kampfrichterIds = array_column($notenChangesEntries, 'edited_by');
|
||||
|
||||
if (!empty($kampfrichterIds)) {
|
||||
$placeholders = implode(',', array_fill(0, count($kampfrichterIds), '?'));
|
||||
|
||||
$sqlKampfrichter = "SELECT `id` AS `id_kampfrichter`, `name_person` AS `name_kampfrichter` FROM $db_tabelle_intern_benutzende WHERE id IN ($placeholders)";
|
||||
$stmtKampfrichter = $mysqli->prepare($sqlKampfrichter);
|
||||
|
||||
$types = str_repeat('i', count($kampfrichterIds));
|
||||
|
||||
$stmtKampfrichter->bind_param($types, ...$kampfrichterIds);
|
||||
|
||||
$stmtKampfrichter->execute();
|
||||
$kampfrichterResult = $stmtKampfrichter->get_result();
|
||||
$kampfrichter = $kampfrichterResult->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$indexedKampfrichter = array_column($kampfrichter, 'name_kampfrichter', 'id_kampfrichter');
|
||||
|
||||
$stmtKampfrichter->close();
|
||||
} else {
|
||||
$indexedKampfrichter = [];
|
||||
}
|
||||
|
||||
$entriesArray = [];
|
||||
|
||||
|
||||
|
||||
foreach ($notenChangesEntries as $snce) {
|
||||
|
||||
$programmId = $indexedProgramme[$indexedPersonen[$snce['person_id']]['programm']] ?? 0;
|
||||
|
||||
$runs = json_decode($IndexedNotenJsonGeraete[$snce['note_bezeichnung_id']], true) ?? [];
|
||||
|
||||
$countRuns = (int) $runs[$snce['geraet_id']][$programmId] ?? (int) $runs['default'] ?? 1;
|
||||
|
||||
$notenTextRaw = $IndexedNotenBezeichnungen[$snce['note_bezeichnung_id']] ?? 'Unbekannter Notenname';
|
||||
|
||||
$notenText = ($countRuns > 1) ? $notenTextRaw . ' (R' . ($snce['run_number'] ?? 1 ). ')' : $notenTextRaw;
|
||||
|
||||
$nullstellen = (int) $IndexedNotenNullstellen[$snce['note_bezeichnung_id']] ?? 2;
|
||||
$value = ($snce['old_value'] !== null) ? number_format((float) $snce['old_value'], $nullstellen) . ' ' . json_decode('"\u2192"') . ' ' . number_format((float) $snce['new_value'], $nullstellen) : number_format((float) $snce['new_value'], $nullstellen);
|
||||
|
||||
$entriesArray[$snce['geraet_id']][$indexedPersonen[$snce['person_id']]['start_geraet_id']][] = [
|
||||
'name' => ($indexedPersonen[$snce['person_id']]['name'] ?? 'Unbekannter Nachname') . ', ' . ($indexedPersonen[$snce['person_id']]['vorname'] ?? 'Unbekannter Vorname'),
|
||||
'programm' => $indexedPersonen[$snce['person_id']]['programm'] ?? 'Unbekanntes Programm',
|
||||
'verein' => $indexedPersonen[$snce['person_id']]['verein'] ?? 'Unbekannter Verein',
|
||||
'note' => $notenText,
|
||||
'value' => $value,
|
||||
'kampfrichter' => $indexedKampfrichter[$snce['edited_by']] ?? 'Unbekannter Kampfrichter',
|
||||
'timestamp' => new DateTime($snce['timestamp'])->format('d.m.Y H:i:s') ?? '---'
|
||||
];
|
||||
}
|
||||
|
||||
// Load TCPDF
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
/*
|
||||
// Optional: load custom font
|
||||
$fontfile = $baseDir . '/wp-content/uploads/fonts/Inter-Regular.ttf'; // adjust path
|
||||
if (file_exists($fontfile)) {
|
||||
$fontname = TCPDF_FONTS::addTTFfont($fontfile, 'TrueTypeUnicode', '', 32);
|
||||
}
|
||||
*/
|
||||
class ProtokollPDF extends TCPDF
|
||||
{
|
||||
public $current_year;
|
||||
public $subAbt;
|
||||
public $abt;
|
||||
public $columns;
|
||||
public $discipline;
|
||||
public $wkName;
|
||||
public $marginSide;
|
||||
public $marginTop;
|
||||
public $pdfHeight;
|
||||
public $pdfWidth;
|
||||
public $headerType;
|
||||
public $now;
|
||||
// Page header
|
||||
|
||||
public $headerBottomY = 0;
|
||||
|
||||
|
||||
public function Header()
|
||||
{
|
||||
$this->SetFillColor(255, 255, 255);
|
||||
|
||||
$this->Rect(0, 0, $this->pdfWidth, $this->pdfHeight, 'F');
|
||||
|
||||
$arrayTitles = [];
|
||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
||||
$this->SetY($this->marginTop);
|
||||
$this->SetX(($this->marginSide ?? 10));
|
||||
$this->SetFont('freesans', '', 20);
|
||||
|
||||
if ($this->headerType === 'bigHeader') {
|
||||
|
||||
$this->Cell(0, 0, 'Protokoll ' . $this->wkName . ' ' . $this->current_year, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$preimageX = $this->GetX();
|
||||
$preimageY = $this->GetY();
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->SetY($preimageY + 5);
|
||||
$this->SetX($this->marginSide ?? 10); // Force back to left margin
|
||||
$this->SetFont('freesans', '', 11);
|
||||
$this->Cell(0, 6, 'Gereat: ' . $this->discipline, 0, 1, 'L');
|
||||
$this->Cell(0, 6, 'Abteilung: ' . $this->abt, 0, 1, 'L');
|
||||
$this->Cell(0, 6, 'Gruppe: ' . $this->subAbt, 0, 1, 'L');
|
||||
|
||||
$this->Ln(5);
|
||||
|
||||
} else {
|
||||
|
||||
$this->Cell(10, 0, 'Protokoll ' . $this->wkName . ' ' . $this->current_year, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$this->SetFont('freesans', '', 11);
|
||||
$info = "Gerät: {$this->discipline} | Abt: {$this->abt} | Gruppe: {$this->subAbt}";
|
||||
$this->Cell(10, 6, $info, 0, 1, 'L'); // Align all info to the right while title is on the left
|
||||
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->Ln(18);
|
||||
}
|
||||
|
||||
$columns = $this->columns;
|
||||
$startY = $this->GetY();
|
||||
$this->SetFont('', 'B');
|
||||
|
||||
$this->SetX($this->marginSide ?? 10);
|
||||
|
||||
foreach ($columns as $col) {
|
||||
|
||||
$title = $col['header'];
|
||||
|
||||
if (($col['rotate'] ?? false)) {
|
||||
$x = $this->GetX();
|
||||
$y = $this->GetY() + 7;
|
||||
|
||||
$this->StartTransform();
|
||||
$this->Rotate(45, $x, $y);
|
||||
|
||||
$lineY = $startY + 7;
|
||||
if (($col['id'] ?? '') === 'gesamt') {
|
||||
$this->SetLineWidth(0.6);
|
||||
} else {
|
||||
$this->SetLineWidth(0.2);
|
||||
}
|
||||
|
||||
$this->Line($x, $lineY, $x + ($col['width_header'] ?? 0), $lineY);
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->Cell($col['width_header'] ?? 0, 7, $title ?? '', 0, 0, 'C');
|
||||
$this->StopTransform();
|
||||
$this->SetX($x + ($col['max_width'] ?? 0));
|
||||
} else {
|
||||
$this->Cell($col['max_width'] ?? 0, 7, $title ?? '', 0, 0, $col['align'] ?? 'L');
|
||||
}
|
||||
}
|
||||
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
}
|
||||
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line($this->marginSide ?? 10, $this->headerBottomY, $this->pdfWidth - ($this->marginSide ?? 10), $this->headerBottomY);
|
||||
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX(0);
|
||||
|
||||
$this->SetFillColor(255, 255, 255); // white
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX($this->pdfWidth - ($this->marginSide ?? 10));
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(-15);
|
||||
$this->SetFont('freesans', 'I', 8);
|
||||
|
||||
// 1. Page Number - Centered
|
||||
$this->Cell(0, 10, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), 0, false, 'C');
|
||||
|
||||
// 2. Timestamp - Force to Left
|
||||
$this->SetX($this->getMargins()['left']); // Reset to left margin
|
||||
$this->Cell(0, 10, 'Zeitstempel: ' . $this->now, 0, false, 'L');
|
||||
|
||||
// 3. Host - Force to Right (Cell with width 0 and align 'R' handles this)
|
||||
$this->SetX($this->getMargins()['left']); // Reset again so 'R' alignment works from the start
|
||||
$this->Cell(0, 10, $_SERVER['HTTP_HOST'], 0, 0, 'R', false, 'https://'.$_SERVER['HTTP_HOST']);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf = new ProtokollPDF($orientation, 'mm', $format, true, 'UTF-8', false);
|
||||
|
||||
$pdfHeight = $pdf->getPageHeight();
|
||||
$pdfWidth = $pdf->getPageWidth();
|
||||
|
||||
$pdf->current_year = $current_year;
|
||||
$pdf->wkName = $wkName;
|
||||
$pdf->abt = $abt;
|
||||
$pdf->marginSide = $marginSide;
|
||||
$pdf->marginTop = $marginTop;
|
||||
$pdf->pdfHeight = $pdfHeight;
|
||||
$pdf->pdfWidth = $pdfWidth;
|
||||
$pdf->now = $now;
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor($wkName);
|
||||
$pdf->SetTitle($wkName . "_Protokoll_" . $abt . "_" . $current_year . ".pdf");
|
||||
|
||||
$pdf->SetAutoPageBreak(FALSE);
|
||||
|
||||
|
||||
$pdf->SetFont('freesans', '', 11);
|
||||
|
||||
// Define columns dynamically
|
||||
$columns = [
|
||||
['id' => 'name', 'header' => 'Name Person', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'name'],
|
||||
['id' => 'programm', 'header' => 'Programm', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'programm'],
|
||||
['id' => 'verein', 'header' => 'Verein', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'verein'],
|
||||
['id' => 'note', 'header' => 'Note', 'align' => 'C', 'flex' => false, 'type' => 'field', 'field' => 'note'],
|
||||
['id' => 'value', 'header' => 'Wert', 'align' => 'C', 'flex' => false, 'type' => 'field', 'field' => 'value'],
|
||||
['id' => 'kr', 'header' => 'Kampfrichter/in', 'align' => 'C', 'flex' => true, 'type' => 'field', 'field' => 'kampfrichter'],
|
||||
['id' => 'timestamp', 'header' => 'Zeitstempel', 'align' => 'C', 'flex' => false, 'type' => 'field', 'field' => 'timestamp'],
|
||||
];
|
||||
|
||||
|
||||
$padding = 4;
|
||||
|
||||
unset($col);
|
||||
|
||||
// 1. Calculate initial max widths based on headers
|
||||
foreach ($columns as &$col) {
|
||||
$col['width_header'] = $pdf->GetStringWidth($col['header']) + ($padding * 2);
|
||||
if ($col['type'] !== 'note') {
|
||||
$col['max_width'] = $col['width_header'];
|
||||
} else {
|
||||
$col['max_width'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entriesArray as $geratId => $singleGeraet) {
|
||||
|
||||
$pdf->discipline = $IndexedGeraete[$geratId] ?? 'Unbekanntes Gerät';
|
||||
|
||||
foreach ($singleGeraet as $geratIdStart => $singleStartGeraet) {
|
||||
|
||||
$pdf->subAbt = $geratIdStart;
|
||||
|
||||
$tcolumns = $columns;
|
||||
|
||||
foreach ($singleStartGeraet as $se) {
|
||||
foreach ($tcolumns as &$col) {
|
||||
$text = '';
|
||||
if (isset($se[$col['field']])) {
|
||||
$text = $se[$col['field']];
|
||||
}
|
||||
$width = $pdf->GetStringWidth($text) + ($padding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
// 4. Distribute Flexible Widths
|
||||
$tablew = $pdfWidth - (2 * $marginSide); // total table width (A4 landscape in mm minus margins)
|
||||
$fixedWidth = 0;
|
||||
$flexCols = [];
|
||||
|
||||
foreach ($tcolumns as $col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$flexCols[] = $col['id'];
|
||||
$fixedWidth += $col['max_width'];
|
||||
} else {
|
||||
$fixedWidth += $col['max_width'];
|
||||
}
|
||||
}
|
||||
|
||||
$effTableWidth = $tablew - $fixedWidth;
|
||||
|
||||
if (!empty($flexCols) && $effTableWidth > 0) {
|
||||
$flexTotalInitial = 0;
|
||||
foreach ($tcolumns as $col) {
|
||||
if ($col['flex'] ?? false) $flexTotalInitial += $col['max_width'];
|
||||
}
|
||||
|
||||
foreach ($tcolumns as &$col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$col['max_width'] += ($col['max_width'] / $flexTotalInitial) * $effTableWidth;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
$pdf->columns = $tcolumns;
|
||||
|
||||
$pdf->headerType = 'bigHeader';
|
||||
$pdf->AddPage();
|
||||
$pdf->headerType = '';
|
||||
|
||||
// After AddPage(), the header has been drawn
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
|
||||
// Now adjust your margins if needed
|
||||
$pdf->SetMargins($marginSide, $margin_top, $marginSide); // +5 mm padding below header
|
||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
||||
|
||||
$pdf->SetFont('', '');
|
||||
$rIndex = 0;
|
||||
|
||||
foreach ($singleStartGeraet as $r) {
|
||||
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
|
||||
if ($rIndex % 2 == 0) {
|
||||
$pdf->SetFillColor(255, 255, 255);
|
||||
} else {
|
||||
$pdf->SetFillColor(240, 240, 240);
|
||||
}
|
||||
|
||||
$rowHeight = 10;
|
||||
|
||||
foreach ($tcolumns as $col) {
|
||||
|
||||
if ($pdf->getY() + $rowHeight > $pdfHeight - $minMarginBottomTable) {
|
||||
$pdf->addPage();
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
$pdf->setY($margin_top);
|
||||
}
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
}
|
||||
|
||||
$startX = $pdf->GetX();
|
||||
$startY = $pdf->GetY();
|
||||
|
||||
$text = strip_tags($r[$col['field']]);
|
||||
|
||||
if ($col['type'] === 'field') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $text, 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->SetY($startY + $rowHeight); // Move Y manually instead of Ln() to account for rowHeight
|
||||
$rIndex++;
|
||||
}
|
||||
$textanzEintaege = (count($singleStartGeraet) > 1) ? 'Einträge': 'Eintrag';
|
||||
|
||||
$pdf->SetFont('', '', 7);
|
||||
|
||||
$pdf->Cell(20, 6, count($singleStartGeraet).' '.$textanzEintaege, 0, 0, 'L');
|
||||
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->Output($wkName . "_Protokoll_" . $abt . "_" . $current_year . ".pdf", 'I');
|
||||
exit;
|
||||
@@ -0,0 +1,750 @@
|
||||
<?php
|
||||
|
||||
use TCPDF;
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
|
||||
$wkName = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);
|
||||
|
||||
$wkName = ($wkName === null) ? 'Keinen Wettkampfname angegeben. Setzen unter: /intern/wk-leitung/einstellungen' : $wkName;
|
||||
|
||||
$normalFontSize = 11;
|
||||
$marginSide = 10;
|
||||
$marginTop = 10;
|
||||
$minMarginBottomTable = 20;
|
||||
$format = 'A4';
|
||||
$orientation = 'L';
|
||||
|
||||
$programm = trim($_POST['prog'] ?? 'P6A');
|
||||
$buttontype = trim($_POST['type'] ?? 'downloadRangliste');
|
||||
|
||||
$allowedOperations = ['downloadRangliste', 'updateServerRangliste'];
|
||||
|
||||
if (!in_array($buttontype, $allowedOperations)) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => false, "message" => "Invalide Operation"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$upperprogramm = strtoupper($programm);
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `id`, `name` FROM $db_tabelle_disziplinen ORDER BY start_index ASC");
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$geraete = $result->fetch_all(MYSQLI_ASSOC);
|
||||
$disciplines = array_map(
|
||||
'strtolower',
|
||||
array_column($geraete, 'name')
|
||||
);
|
||||
|
||||
$stmt->close();
|
||||
|
||||
// Determine current year
|
||||
$current_year = date('Y');
|
||||
$monat = date('n');
|
||||
if ($monat > 6) $current_year++;
|
||||
|
||||
// Prepare SQL statement
|
||||
$stmt = $mysqli->prepare("
|
||||
SELECT * FROM $db_tabelle_teilnehmende
|
||||
WHERE LOWER(programm) = LOWER(?)
|
||||
AND (bezahltoverride = ? OR (bezahlt = ? OR bezahltoverride = ?))
|
||||
ORDER BY rang ASC
|
||||
");
|
||||
$bezahlt1 = '4';
|
||||
$bezahlt2 = '4';
|
||||
$bezahlt3 = '0';
|
||||
$stmt->bind_param('ssss', $programm, $bezahlt1, $bezahlt2, $bezahlt3);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$personen = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
|
||||
// Close statement
|
||||
$stmt->close();
|
||||
|
||||
$programmId = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE LOWER(`programm`) = LOWER(?)", [$programm]);
|
||||
$cache = require $baseDir . '/../scripts/cache/noten-config-calculating-cache.php';
|
||||
$ascArrayAnzahlLaeufeJSON = $cache['anzahl_laeufe_json'];
|
||||
|
||||
// 1. Get the IDs from the first query results
|
||||
$turnerinnenIds = array_column($personen, 'id');
|
||||
|
||||
$rangNote = intval(db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['rangNote']));
|
||||
|
||||
if ($rangNote === 0) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => false, "message" => "Keine Note für Rangvergabe ausgewählt"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if (!empty($turnerinnenIds)) {
|
||||
// 2. Create a string of placeholders: ?,?,?
|
||||
$placeholders = implode(',', array_fill(0, count($turnerinnenIds), '?'));
|
||||
|
||||
// 3. Prepare the IN statement
|
||||
$sqlNoten = "SELECT * FROM $db_tabelle_wertungen WHERE person_id IN ($placeholders) AND `wk_id` = ?";
|
||||
$stmtNoten = $mysqli->prepare($sqlNoten);
|
||||
|
||||
// --- FIX STARTS HERE ---
|
||||
|
||||
// 1. Combine all values into one flat array for binding
|
||||
$paramsArray = array_merge($turnerinnenIds, [$current_wk_id]);
|
||||
|
||||
// 2. Build the types string
|
||||
// 'i' for every ID, plus 'i' (or 's') for the year
|
||||
$types = str_repeat('i', count($turnerinnenIds)) . 's';
|
||||
|
||||
// 3. Unpack the combined array into the bind_param function
|
||||
$stmtNoten->bind_param($types, ...$paramsArray);
|
||||
|
||||
// --- FIX ENDS HERE ---
|
||||
|
||||
$stmtNoten->execute();
|
||||
$notenResult = $stmtNoten->get_result();
|
||||
$notenEntries = $notenResult->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$stmtNoten->close(); // Close inside the IF to avoid errors if IDs were empty
|
||||
} else {
|
||||
$notenEntries = [];
|
||||
}
|
||||
|
||||
$indexedNotenEntries = [];
|
||||
foreach ($notenEntries as $sn) {
|
||||
if (!isset($indexedNotenEntries[$sn['person_id']][$sn['note_bezeichnung_id']][$sn['geraet_id']])) {
|
||||
$indexedNotenEntries[$sn['person_id']][$sn['note_bezeichnung_id']][$sn['geraet_id']] = [];
|
||||
}
|
||||
$indexedNotenEntries[$sn['person_id']][$sn['note_bezeichnung_id']][$sn['geraet_id']][$sn['run_number']] = $sn['value'];
|
||||
}
|
||||
|
||||
$orderBestRang = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['orderBestRang']);
|
||||
|
||||
$okValuesOrderBestRang = ["ASC", "DESC"];
|
||||
|
||||
if (!in_array($orderBestRang, $okValuesOrderBestRang)) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => false, "message" => "Invalide Sortierung der Ränge"]);
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$alleNoten = db_select($mysqli, $db_tabelle_wertungstypen, "id, default_value, nullstellen, pro_geraet, geraete_json, zeige_auf_rangliste, groesse_auf_rangliste, name", "zeige_auf_rangliste = ? OR id = ?", ['1', $rangNote]);
|
||||
|
||||
$displayedNoten = [];
|
||||
|
||||
$alleNotenIndexed = array_column($alleNoten, null, 'id');
|
||||
|
||||
foreach ($alleNotenIndexed as $key => $sN) {
|
||||
if (intval($sN['zeige_auf_rangliste']) === 1) {
|
||||
$displayedNoten[$key] = $sN;
|
||||
}
|
||||
}
|
||||
|
||||
$ascArrayDefaultValues = array_column($alleNoten, 'default_value', 'id');
|
||||
$ascArrayGeraeteJSON = array_column($alleNoten, 'geraete_json', 'id');
|
||||
|
||||
foreach ($ascArrayGeraeteJSON as $key => $saagj) {
|
||||
$ascArrayGeraeteJSON[$key] = json_decode($saagj, true) ?? [];
|
||||
}
|
||||
|
||||
// 1. Initialize the structure for every person
|
||||
$indexedNotenArray = [];
|
||||
$sortArray = [];
|
||||
|
||||
$notenGeraeteArray = array_merge($geraete, array(array("id" => 0)));
|
||||
|
||||
foreach ($personen as $sp) {
|
||||
$pId = $sp['id'];
|
||||
foreach ($displayedNoten as $an) {
|
||||
$nId = $an['id'];
|
||||
$isProGeraet = (intval($an['pro_geraet']) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$nId] ?? [];
|
||||
|
||||
foreach ($notenGeraeteArray as $g) {
|
||||
$gId = $g['id'];
|
||||
|
||||
if ($isProGeraet) {
|
||||
if ($gId === 0) continue;
|
||||
} else {
|
||||
if (!in_array($gId, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$indexedNotenArray[$pId][$gId][$nId] = $indexedNotenEntries[$pId][$nId][$gId] ?? [$an['default_value']];
|
||||
}
|
||||
|
||||
if (intval($nId) === $rangNote) {
|
||||
$val = $indexedNotenArray[$pId][0][$nId] ?? [$an['default_value']];
|
||||
$sortArray[$pId] = is_array($val) ? end($val) : $val; // fallback to the last run for sorting if needed, or total should just be one run
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$wkWebpageDomain = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['linkWebseite']);
|
||||
|
||||
// Load TCPDF
|
||||
require $baseDir . '/../composer/vendor/autoload.php';
|
||||
|
||||
// Optional: load custom font
|
||||
$fontfile = $baseDir . '/wp-content/uploads/fonts/Inter-Regular.ttf'; // adjust path
|
||||
if (file_exists($fontfile)) {
|
||||
$fontname = TCPDF_FONTS::addTTFfont($fontfile, 'TrueTypeUnicode', '', 32);
|
||||
}
|
||||
|
||||
class RanglistePDF extends TCPDF
|
||||
{
|
||||
public $current_year;
|
||||
public $programm;
|
||||
public $upperprogramm;
|
||||
public $columns;
|
||||
public $disciplines;
|
||||
public $wkName;
|
||||
public $marginSide;
|
||||
public $marginTop;
|
||||
public $pdfHeight;
|
||||
public $pdfWidth;
|
||||
public $wkWebpageDomain;
|
||||
// Page header
|
||||
|
||||
public $headerBottomY = 0;
|
||||
|
||||
public function Header()
|
||||
{
|
||||
$this->SetFillColor(255, 255, 255);
|
||||
|
||||
$this->Rect(0, 0, $this->pdfWidth, $this->pdfHeight, 'F');
|
||||
|
||||
$arrayTitles = [];
|
||||
$image_file = $_SERVER['DOCUMENT_ROOT'] . '/intern/img/logo-normal.png';
|
||||
$this->SetY($this->marginTop);
|
||||
$this->SetX(($this->marginSide ?? 10));
|
||||
$this->SetFont('freesans', '', 20);
|
||||
$this->Cell(0, 0, 'Rangliste ' . $this->wkName . ' ' . $this->current_year, 0, 1, 'L', 0, '', 0, false, 'T', 'M');
|
||||
$preimageX = $this->GetX();
|
||||
$preimageY = $this->GetY();
|
||||
$this->Image($image_file, $this->pdfWidth - 10 - $this->marginSide, $this->marginTop, '', 10, 'png', '', 'T');
|
||||
|
||||
$this->SetY($preimageY);
|
||||
$this->SetX($this->marginSide ?? 10); // Force back to left margin
|
||||
$this->SetFont('freesans', '', 11);
|
||||
$this->Cell(0, 10, 'Programm: ' . $this->upperprogramm, 0, 1, 'L');
|
||||
|
||||
$this->Ln(5);
|
||||
|
||||
$columns = $this->columns;
|
||||
$startY = $this->GetY();
|
||||
$this->SetFont('', 'B');
|
||||
|
||||
$this->SetX($this->marginSide ?? 10);
|
||||
|
||||
foreach ($columns as $col) {
|
||||
$isDuplicate = in_array($col['header'], $arrayTitles);
|
||||
|
||||
$title = $isDuplicate ? '' : $col['header'];
|
||||
|
||||
if (!$isDuplicate) {
|
||||
$arrayTitles[] = $col['header'];
|
||||
}
|
||||
|
||||
if (($col['rotate'] ?? false) && !$isDuplicate) {
|
||||
$x = $this->GetX();
|
||||
$y = $this->GetY() + 7;
|
||||
|
||||
$this->StartTransform();
|
||||
$this->Rotate(45, $x, $y);
|
||||
|
||||
$lineY = $startY + 7;
|
||||
if (($col['id'] ?? '') === 'gesamt') {
|
||||
$this->SetLineWidth(0.6);
|
||||
} else {
|
||||
$this->SetLineWidth(0.2);
|
||||
}
|
||||
|
||||
$this->Line($x, $lineY, $x + ($col['width_header'] ?? 0), $lineY);
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->Cell($col['width_header'] ?? 0, 7, $title ?? '', 0, 0, 'C');
|
||||
$this->StopTransform();
|
||||
$this->SetX($x + ($col['max_width'] ?? 0));
|
||||
} else {
|
||||
$this->Cell($col['max_width'] ?? 0, 7, $title ?? '', 0, 0, $col['align'] ?? 'L');
|
||||
}
|
||||
}
|
||||
|
||||
$this->Ln();
|
||||
$this->headerBottomY = $this->GetY();
|
||||
}
|
||||
|
||||
|
||||
// Page footer
|
||||
public function Footer()
|
||||
{
|
||||
$this->SetLineWidth(0.6);
|
||||
$this->Line($this->marginSide ?? 10, $this->headerBottomY, $this->pdfWidth - ($this->marginSide ?? 10), $this->headerBottomY);
|
||||
|
||||
$this->SetLineWidth(0.2);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX(0);
|
||||
|
||||
$this->SetFillColor(255, 255, 255); // white
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(0);
|
||||
$this->SetX($this->pdfWidth - ($this->marginSide ?? 10));
|
||||
|
||||
$this->Cell(($this->marginSide ?? 10), $this->pdfHeight, '', 0, 0, 'L', true);
|
||||
|
||||
$this->SetY(-15);
|
||||
$this->SetFont('freesans', 'I', 8);
|
||||
$this->Cell(0, 10, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
|
||||
$this->SetFont('', '');
|
||||
$this->Cell(0, 10, ($this->wkWebpageDomain ?? $_SERVER['HTTP_HOST']), 0, 0, 'R', false, 'https://' . ($this->wkWebpageDomain ?? $_SERVER['HTTP_HOST']), 0, false, 'T', 'M');
|
||||
}
|
||||
}
|
||||
|
||||
$pdf = new RanglistePDF($orientation, 'mm', $format, true, 'UTF-8', false);
|
||||
|
||||
$pdfHeight = $pdf->getPageHeight();
|
||||
$pdfWidth = $pdf->getPageWidth();
|
||||
|
||||
$pdf->current_year = $current_year;
|
||||
$pdf->wkName = $wkName;
|
||||
$pdf->wkWebpageDomain = $wkWebpageDomain;
|
||||
$pdf->programm = $programm;
|
||||
$pdf->upperprogramm = $upperprogramm;
|
||||
$pdf->marginSide = $marginSide;
|
||||
$pdf->marginTop = $marginTop;
|
||||
$pdf->pdfHeight = $pdfHeight;
|
||||
$pdf->pdfWidth = $pdfWidth;
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor($wkName);
|
||||
$pdf->SetTitle($wkName . "_Ergebnisse_" . $programm . "_" . $current_year . ".pdf");
|
||||
|
||||
$pdf->SetAutoPageBreak(FALSE);
|
||||
|
||||
|
||||
$pdf->SetFont('freesans', '', 11);
|
||||
|
||||
// Define columns dynamically
|
||||
$columns = [
|
||||
['id' => 'rang', 'header' => 'Rang', 'align' => 'C', 'flex' => false, 'type' => 'rank'],
|
||||
['id' => 'name', 'header' => 'Name', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'name'],
|
||||
['id' => 'vorname', 'header' => 'Vorname', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'vorname'],
|
||||
['id' => 'geburtsdatum', 'header' => 'Jg.', 'align' => 'C', 'flex' => false, 'type' => 'year', 'field' => 'geburtsdatum'],
|
||||
['id' => 'verein', 'header' => 'Verein', 'align' => 'L', 'flex' => true, 'type' => 'field', 'field' => 'verein'],
|
||||
];
|
||||
|
||||
// Add notes dynamically per device
|
||||
foreach ($geraete as $g) {
|
||||
foreach ($displayedNoten as $noteDef) {
|
||||
$neni = $noteDef['id'];
|
||||
$isProGeraet = (intval($noteDef['pro_geraet']) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
|
||||
if ($isProGeraet || in_array($g['id'], $allowedGeraete)) {
|
||||
$columns[] = [
|
||||
'id' => 'note_' . $g['id'] . '_' . $neni,
|
||||
'header' => $g['name'],
|
||||
'align' => 'C',
|
||||
'flex' => false,
|
||||
'rotate' => true,
|
||||
'type' => 'note',
|
||||
'geraet_id' => $g['id'],
|
||||
'note_bezeichnung_id' => $neni,
|
||||
'nullstellen' => $noteDef['nullstellen'] ?? 2,
|
||||
'font_size' => intval($noteDef['groesse_auf_rangliste']) ?? 0
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Gesamt (Total) column
|
||||
$columns[] = [
|
||||
'id' => 'gesamt',
|
||||
'header' => $alleNotenIndexed[$rangNote]['name'] ?? 'Total',
|
||||
'align' => 'C',
|
||||
'flex' => false,
|
||||
'rotate' => true,
|
||||
'type' => 'note',
|
||||
'geraet_id' => 0,
|
||||
'note_bezeichnung_id' => $rangNote,
|
||||
'nullstellen' => $alleNotenIndexed[$rangNote]['nullstellen'] ?? 2,
|
||||
'font_size' => intval($alleNotenIndexed[$rangNote]['groesse_auf_rangliste']) ?? 0
|
||||
];
|
||||
|
||||
|
||||
|
||||
$padding = 4;
|
||||
|
||||
unset($col);
|
||||
|
||||
// 1. Calculate initial max widths based on headers
|
||||
foreach ($columns as &$col) {
|
||||
$col['width_header'] = $pdf->GetStringWidth($col['header']) + ($padding * 2);
|
||||
if ($col['type'] !== 'note') {
|
||||
$col['max_width'] = $col['width_header'];
|
||||
} else {
|
||||
$col['max_width'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fill missing defaults and update max widths based on data
|
||||
foreach ($personen as $sp) {
|
||||
$pId = $sp['id'];
|
||||
foreach ($indexedNotenArray[$pId] as $sG => $currentNoten) {
|
||||
foreach ($displayedNoten as $noteDef) {
|
||||
$neni = $noteDef['id'];
|
||||
if (isset($currentNoten[$neni])) {
|
||||
$runs = $currentNoten[$neni];
|
||||
if (is_array($runs)) {
|
||||
$runsConfig = $ascArrayAnzahlLaeufeJSON[$neni] ?? [];
|
||||
$runsCount = $runsConfig[$sG][$programmId] ?? $runsConfig[$sG]['all'] ?? $runsConfig["default"] ?? 1;
|
||||
$defaultValue = $ascArrayDefaultValues[$neni] ?? 0;
|
||||
|
||||
for ($r = 1; $r <= $runsCount - 1; $r++) {
|
||||
if (!isset($runs[$r])) {
|
||||
$runs[$r] = $defaultValue;
|
||||
}
|
||||
}
|
||||
$indexedNotenArray[$pId][$sG][$neni] = $runs;
|
||||
|
||||
ksort($runs);
|
||||
$maxLenStr = "";
|
||||
foreach ($runs as $rVal) {
|
||||
$str = number_format((float)$rVal, $noteDef['nullstellen']);
|
||||
// Approximate max width by string length, GetStringWidth will do the real check later
|
||||
if (strlen($str) > strlen($maxLenStr)) {
|
||||
$maxLenStr = $str;
|
||||
}
|
||||
}
|
||||
$val = $maxLenStr;
|
||||
} else {
|
||||
$val = number_format((float)$runs, $noteDef['nullstellen']);
|
||||
}
|
||||
} else {
|
||||
// Logic for "Pro Gerät" vs "Specific/Total"
|
||||
$isProGeraet = (intval($noteDef['pro_geraet']) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
|
||||
if ($isProGeraet) {
|
||||
if ($sG === 0) continue;
|
||||
} else {
|
||||
if (!in_array($sG, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$defaultValue = $ascArrayDefaultValues[$neni] ?? 0;
|
||||
|
||||
$runsConfig = $ascArrayAnzahlLaeufeJSON[$neni] ?? [];
|
||||
$runsCount = $runsConfig[$sG][$programmId] ?? $runsConfig[$sG]['all'] ?? $runsConfig["default"] ?? 1;
|
||||
|
||||
$valArray = [];
|
||||
$maxLenStr = "";
|
||||
for ($r = 1; $r <= $runsCount - 1; $r++) {
|
||||
$valArray[$r] = $defaultValue;
|
||||
$str = number_format((float)$defaultValue, $noteDef['nullstellen']);
|
||||
if (strlen($str) > strlen($maxLenStr)) {
|
||||
$maxLenStr = $str;
|
||||
}
|
||||
}
|
||||
|
||||
$val = $maxLenStr;
|
||||
$indexedNotenArray[$pId][$sG][$neni] = $valArray;
|
||||
|
||||
if ($neni === $rangNote && $sG === 0) {
|
||||
$sortArray[$pId] = $defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Update column width if this note is displayed
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['type'] === 'note' && $col['geraet_id'] == $sG && $col['note_bezeichnung_id'] == $neni) {
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
$cpadding = $padding;
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
$cpadding = ($col['font_size'] / $normalFontSize) * $padding;
|
||||
}
|
||||
|
||||
$width = $pdf->GetStringWidth($val) + ($cpadding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
}
|
||||
|
||||
// Also update widths for static fields
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['type'] === 'field' || $col['type'] === 'year' || $col['type'] === 'rank') {
|
||||
$text = '';
|
||||
if ($col['type'] === 'rank') {
|
||||
$text = '999'; // Placeholder for rank width
|
||||
} elseif ($col['type'] === 'year') {
|
||||
$text = '0000';
|
||||
} elseif (isset($sp[$col['field']])) {
|
||||
$text = $sp[$col['field']];
|
||||
}
|
||||
$width = $pdf->GetStringWidth($text) + ($padding * 2);
|
||||
if ($width > $col['max_width']) {
|
||||
$col['max_width'] = $width;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
function calculateRanks(array $scoreArray, $direction = 'DESC') {
|
||||
// 1. Sort the scores while preserving keys
|
||||
if ($direction === 'DESC') {
|
||||
arsort($scoreArray); // High scores first
|
||||
} else {
|
||||
asort($scoreArray); // Low scores first
|
||||
}
|
||||
|
||||
$ranks = [];
|
||||
$currentRank = 0;
|
||||
$lastScore = null;
|
||||
$skipped = 0;
|
||||
|
||||
foreach ($scoreArray as $pId => $score) {
|
||||
if ($score !== $lastScore) {
|
||||
$currentRank += ($skipped + 1);
|
||||
$skipped = 0;
|
||||
} else {
|
||||
$skipped++;
|
||||
}
|
||||
|
||||
$ranks[$pId] = $currentRank;
|
||||
$lastScore = $score;
|
||||
}
|
||||
return $ranks;
|
||||
}
|
||||
|
||||
|
||||
// 3. Finalize Ranks
|
||||
$ranks = calculateRanks($sortArray, $orderBestRang);
|
||||
|
||||
// 4. Distribute Flexible Widths
|
||||
$tablew = $pdfWidth - (2 * $marginSide); // total table width (A4 landscape in mm minus margins)
|
||||
$fixedWidth = 0;
|
||||
$flexCols = [];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$flexCols[] = $col['id'];
|
||||
$fixedWidth += $col['max_width'];
|
||||
} else {
|
||||
$fixedWidth += $col['max_width'];
|
||||
}
|
||||
}
|
||||
|
||||
$effTableWidth = $tablew - $fixedWidth;
|
||||
|
||||
|
||||
if (!empty($flexCols) && $effTableWidth > 0) {
|
||||
$flexTotalInitial = 0;
|
||||
foreach ($columns as $col) {
|
||||
if ($col['flex'] ?? false) $flexTotalInitial += $col['max_width'];
|
||||
}
|
||||
|
||||
foreach ($columns as &$col) {
|
||||
if ($col['flex'] ?? false) {
|
||||
$col['max_width'] += ($col['max_width'] / $flexTotalInitial) * $effTableWidth;
|
||||
}
|
||||
}
|
||||
unset($col);
|
||||
}
|
||||
|
||||
$pdf->columns = $columns;
|
||||
$pdf->disciplines = $disciplines;
|
||||
|
||||
$pdf->AddPage();
|
||||
|
||||
// After AddPage(), the header has been drawn
|
||||
$margin_top = $pdf->headerBottomY;
|
||||
|
||||
// Now adjust your margins if needed
|
||||
$pdf->SetMargins($marginSide, $margin_top, $marginSide); // +5 mm padding below header
|
||||
$pdf->SetY($margin_top); // Move cursor below header manually
|
||||
|
||||
$pdf->SetFont('', '');
|
||||
$rIndex = 0;
|
||||
|
||||
usort($personen, function($a, $b) use ($ranks) {
|
||||
$rankA = $ranks[$a['id']];
|
||||
$rankB = $ranks[$b['id']];
|
||||
|
||||
return $rankA <=> $rankB;
|
||||
});
|
||||
|
||||
foreach ($personen as $r) {
|
||||
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
|
||||
$rang = $ranks[$r['id']];
|
||||
|
||||
if ($rang == 1) {
|
||||
$pdf->SetFillColor(255, 235, 128);
|
||||
} elseif($rang == 2) {
|
||||
$pdf->SetFillColor(224, 224, 224);
|
||||
} elseif($rang == 3) {
|
||||
$pdf->SetFillColor(230, 191, 153);
|
||||
} elseif ($rIndex % 2 == 0) {
|
||||
$pdf->SetFillColor(255, 255, 255); // white
|
||||
} else {
|
||||
$pdf->SetFillColor(240, 240, 240); // light gray
|
||||
}
|
||||
|
||||
|
||||
// Determine row height based on max runs
|
||||
$maxRuns = 1;
|
||||
foreach ($columns as $col) {
|
||||
if ($col['type'] === 'note') {
|
||||
$runs = $indexedNotenArray[$r['id']][$col['geraet_id']][$col['note_bezeichnung_id']] ?? [];
|
||||
if (is_array($runs) && count($runs) > $maxRuns) {
|
||||
$maxRuns = count($runs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Base height is 8, add extra height for additional runs. Let's say 4mm per additional line.
|
||||
// But to keep it centered properly, we will use MultiCell with valign='M' (Middle).
|
||||
$rowHeight = max(8, $maxRuns * 5 + 3); // 5mm per line
|
||||
|
||||
if ($pdf->getY() + $rowHeight >= $pdfHeight - $minMarginBottomTable) {
|
||||
$pdf->addPage();
|
||||
$pdf->setX($marginSide);
|
||||
}
|
||||
|
||||
foreach ($columns as $col) {
|
||||
|
||||
$customFontSize = (isset($col['font_size']) && $col['font_size'] != 0);
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $col['font_size']);
|
||||
}
|
||||
|
||||
$startX = $pdf->GetX();
|
||||
$startY = $pdf->GetY();
|
||||
|
||||
if ($col['id'] === 'rang') {
|
||||
$pdf->SetFont('', 'B');
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $rang, 'B', 'C', true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
$pdf->SetFont('', '');
|
||||
} elseif ($col['type'] === 'field') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, $r[$col['field']], 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
} elseif ($col['type'] === 'year') {
|
||||
$pdf->MultiCell($col['max_width'], $rowHeight, (new DateTime($r[$col['field']]))->format("Y"), 'B', $col['align'], true, 0, $startX, $startY, true, 0, false, true, $rowHeight, 'M');
|
||||
} elseif ($col['type'] === 'note') {
|
||||
$runs = $indexedNotenArray[$r['id']][$col['geraet_id']][$col['note_bezeichnung_id']] ?? [];
|
||||
if (!is_array($runs)) {
|
||||
$runs = [$runs];
|
||||
} else {
|
||||
ksort($runs);
|
||||
}
|
||||
|
||||
$numRuns = max(count($runs), 1);
|
||||
$lineHeight = $rowHeight / $numRuns;
|
||||
|
||||
$pdf->SetXY($startX, $startY);
|
||||
$pdf->Cell($col['max_width'], $rowHeight, '', 0, 0, '', true);
|
||||
|
||||
$runIndex = 0;
|
||||
foreach (array_values($runs) as $rnVal) {
|
||||
$formatted = number_format((float)$rnVal, $col['nullstellen'] ?? 0);
|
||||
$currentY = $startY + ($runIndex * $lineHeight);
|
||||
|
||||
$pdf->SetXY($startX, $currentY);
|
||||
|
||||
$pdf->Cell($col['max_width'], $lineHeight, $formatted, 0, 0, $col['align'], false);
|
||||
$runIndex++;
|
||||
}
|
||||
|
||||
// Draw the bottom border for the entire row height
|
||||
$pdf->Line($startX, $startY + $rowHeight, $startX + $col['max_width'], $startY + $rowHeight);
|
||||
|
||||
// Reset pointer for the next column
|
||||
$pdf->SetXY($startX + $col['max_width'], $startY);
|
||||
|
||||
if ($col['id'] === 'gesamt') {
|
||||
// Draw the heavy separator line on the left side of the "Gesamt" column
|
||||
$pdf->SetLineWidth(0.6);
|
||||
$pdf->Line($startX, $startY, $startX, $startY + $rowHeight);
|
||||
$pdf->SetLineWidth(0.2);
|
||||
}
|
||||
}
|
||||
|
||||
if ($customFontSize) {
|
||||
$pdf->SetFont('', '', $normalFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->SetY($startY + $rowHeight); // Move Y manually instead of Ln() to account for rowHeight
|
||||
$rIndex++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$pdf->SetFont('', '', 7);
|
||||
$textanzturnerinnen = (count($personen) > 1) ? 'Turnerinnen': 'Turnerin';
|
||||
$pdf->Cell(20, 6, count($personen).' '.$textanzturnerinnen, 0, 0, 'L');
|
||||
|
||||
if ($buttontype === 'downloadRangliste') {
|
||||
$pdf->Output($wkName . "_Ergebnisse_" . $programm . "_" . $current_year . ".pdf", 'I');
|
||||
exit;
|
||||
} elseif ($buttontype === 'updateServerRangliste') {
|
||||
$dir = $baseDir . '/files/ranglisten/';
|
||||
if (!file_exists($dir)) mkdir($dir, 0755, true);
|
||||
$localPath = $dir . str_replace("/", "", str_replace(" ", "_", $wkName)) . "_Ergebnisse_" . str_replace("/", "", $programm) . "_" . $current_year . ".pdf";
|
||||
if (file_exists($localPath)) unlink($localPath);
|
||||
$pdf->Output($localPath, 'F');
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(["success" => true, "message" => "PDF wurde aktualisiert"]);
|
||||
exit;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
// ---------- Get and sanitize input ----------
|
||||
$personId = intval($_POST['personId'] ?? 0);
|
||||
$gereatId = intval($_POST['geraetId'] ?? 0);
|
||||
|
||||
if ($gereatId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Gerät angegeben']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($personId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ---------- Step 2: Get values from DB ----------
|
||||
|
||||
$sqlQuery = "SELECT
|
||||
paf.`audiofile_id`,
|
||||
af.`file_path`,
|
||||
af.`file_name`,
|
||||
tu.`name`,
|
||||
tu.`vorname`
|
||||
FROM $db_tabelle_teilnehmende_audiofiles paf
|
||||
INNER JOIN $db_tabelle_audiofiles af
|
||||
ON paf.`audiofile_id` = af.`id`
|
||||
LEFT JOIN $db_tabelle_teilnehmende tu
|
||||
ON paf.`person_id` = tu.`id`
|
||||
WHERE paf.`person_id` = ?
|
||||
AND paf.`geraet_id` = ?
|
||||
";
|
||||
|
||||
$stmt = $mysqli->prepare($sqlQuery);
|
||||
|
||||
$stmt->bind_param('ii', $personId, $gereatId);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
if (count($rows) !== 1 || !isset($rows[0]['file_path']) || $rows[0]['file_path'] === null) {
|
||||
echo json_encode(['success' => false, 'message' => 'Keine Musik']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $rows[0];
|
||||
|
||||
$folder = realpath($baseDir . '/externe-geraete/json');
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'audio-id-'. $gereatId .'.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if (!is_file($filepath)){
|
||||
file_put_contents($filepath, []);
|
||||
}
|
||||
|
||||
|
||||
$json = [
|
||||
"audio_path" => $row['file_path'],
|
||||
"audio_name" => $row['file_name'],
|
||||
"start" => true,
|
||||
"person" => [
|
||||
"name" => $row['name'],
|
||||
"vorname" => $row['vorname']
|
||||
]
|
||||
];
|
||||
|
||||
$jsonData = json_encode($json);
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Audio JSON updated successfully'
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$gereatId = intval($_POST['geraetId'] ?? 0);
|
||||
|
||||
if ($gereatId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Gerät angegeben']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$folder = realpath($baseDir . '/externe-geraete/json');
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'audio-id-'. $gereatId .'.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!is_file($filepath)){
|
||||
file_put_contents($filepath, []);
|
||||
}
|
||||
|
||||
$json = [
|
||||
"start" => false
|
||||
];
|
||||
|
||||
$jsonData = json_encode($json);
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file: ' . $filepath
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON updated successfully for '.$discipline,
|
||||
'disable_musik_button' => true
|
||||
]);
|
||||
exit;
|
||||
@@ -0,0 +1,315 @@
|
||||
<?php
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$person_id = isset($_POST['personId']) ? intval($_POST['personId']) : 0;
|
||||
$field_type_id = intval($_POST['fieldTypeId'] ?? 0);
|
||||
$gereat_id = intval($_POST['gereatId'] ?? 0);
|
||||
$jahr = isset($_POST['jahr']) ? intval($_POST['jahr']) : 0;
|
||||
$run_number = isset($_POST['run']) ? intval($_POST['run']) : 1;
|
||||
|
||||
if (!isset($_POST['value'])) {
|
||||
echo json_encode(['success' => false, 'message' => 'Kein Value angegeben']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$valueNoteUpdate = floatval($_POST['value']);
|
||||
|
||||
if ($person_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Personen-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($jahr < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalides Jahr']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($gereat_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Geraet-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geratExistiert = db_get_var($mysqli, "SELECT 1 FROM $db_tabelle_disziplinen WHERE id = ? LIMIT 1", [$gereat_id]);
|
||||
|
||||
if (!$geratExistiert) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Geraet-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($field_type_id < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Notentyp-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$noteConfig = db_select($mysqli, $db_tabelle_wertungstypen, "*", "id = ?", [$field_type_id]);
|
||||
|
||||
if (count($noteConfig) !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalide Notentyp-ID']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$singleNoteConfig = $noteConfig[0];
|
||||
|
||||
if ($singleNoteConfig['max_value'] !== null && $valueNoteUpdate > $singleNoteConfig['max_value']) {
|
||||
echo json_encode(['success' => false, 'message' => "Wert zu hoch (max " . $singleNoteConfig['max_value'].")"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($singleNoteConfig['min_value'] !== null && $valueNoteUpdate < $singleNoteConfig['min_value']){
|
||||
echo json_encode(['success' => false, 'message' => "Wert zu niedrig (min " . $singleNoteConfig['min_value'].")"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
$oldNote = db_get_var($mysqli, "SELECT `value` FROM $db_tabelle_wertungen WHERE `person_id` = ? AND `note_bezeichnung_id` = ? AND `geraet_id` = ? AND `wk_id` = ? AND `run_number` = ?", [$person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number]);
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_wertungen (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$stmt->bind_param("siiiii", $valueNoteUpdate, $person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$userId = (int) $_SESSION['user_id_kampfrichter'];
|
||||
|
||||
$sql = "INSERT INTO $db_tabelle_wertungen_log (`new_value`, `old_value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`, `edited_by`)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
|
||||
$stmt->bind_param("ssiiiiii", $valueNoteUpdate, $oldNote, $person_id, $field_type_id, $gereat_id, $current_wk_id, $run_number, $userId);
|
||||
|
||||
$stmt->execute();
|
||||
|
||||
$stmt->close();
|
||||
|
||||
if ($singleNoteConfig['berechnung_json'] === null) {
|
||||
echo json_encode(['success' => true, 'message' => "Wert aktualisiert"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . "/../scripts/string-calculator/string-calculator-functions.php";
|
||||
|
||||
$updateNoten = [];
|
||||
|
||||
$notenRechner = new NotenRechner();
|
||||
|
||||
try {
|
||||
$abhaenigeRechnungen = json_decode($singleNoteConfig['berechnung_json']);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => true, 'message' => "Wert aktualisiert, fehler bei der Berechnung der weiteren Werte"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geraete = db_select($mysqli, $db_tabelle_disziplinen, "id");
|
||||
|
||||
$programmName = db_get_var($mysqli, "SELECT `programm` FROM $db_tabelle_teilnehmende WHERE `id` = ?", [$person_id]);
|
||||
|
||||
$programmId = db_get_var($mysqli, "SELECT `id` FROM $db_tabelle_kategorien WHERE `programm` = ?", [$programmName]);
|
||||
|
||||
// We load the configuration native cached array
|
||||
$cache = require $baseDir . '/../scripts/cache/noten-config-calculating-cache.php';
|
||||
|
||||
$noten = db_select($mysqli, $db_tabelle_wertungen, "`value`, `note_bezeichnung_id`, `geraet_id`, `run_number`", "`person_id` = ? AND `wk_id` = ? AND `value` IS NOT NULL", [$person_id, $current_wk_id]);
|
||||
|
||||
$ascArrayDefaultValues = $cache['default_values'];
|
||||
$ascArrayProGeraet = $cache['pro_geraet'];
|
||||
$ascArrayGeraeteJSON = $cache['geraete_json'];
|
||||
$ascArrayAnzahlLaeufeJSON = $cache['anzahl_laeufe_json'];
|
||||
$ascArrayRechnungen = $cache['rechnungen'];
|
||||
$indexedNullstellen = $cache['nullstellen'];
|
||||
|
||||
$mRunFunctions = [];
|
||||
|
||||
foreach ($abhaenigeRechnungen as $saRechnung) {
|
||||
$sRechnung = $ascArrayRechnungen[$saRechnung[0]] ?? 0;
|
||||
//var_dump($sRechnung);
|
||||
$mRunCalc = $notenRechner->checkRunFunctions($sRechnung) ?? false;
|
||||
|
||||
if ($mRunCalc) {
|
||||
$mRunFunctions[] = $saRechnung[0];
|
||||
}
|
||||
}
|
||||
|
||||
$indexedNotenArray = [];
|
||||
|
||||
foreach ($geraete as $g) {
|
||||
$indexedNotenArray[$g['id']] = [];
|
||||
}
|
||||
|
||||
$indexedNotenArray[0] = [];
|
||||
|
||||
foreach ($noten as $sn) {
|
||||
$indexedNotenArray[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = ["value" => $sn['value'], "type" => "note"];
|
||||
}
|
||||
|
||||
$requiredNoteIds = [];
|
||||
$requiredNoteIds[$field_type_id] = true;
|
||||
|
||||
foreach ($abhaenigeRechnungen as $saRechnung) {
|
||||
// Only load dependencies for the specifically connected calculations
|
||||
$sRechnungStr = $ascArrayRechnungen[$saRechnung[0]] ?? '';
|
||||
if ($sRechnungStr !== '') {
|
||||
$ids = $notenRechner->getBenoetigteIdsComplex($sRechnungStr);
|
||||
foreach ($ids as $idConfig) {
|
||||
$requiredNoteIds[(int)$idConfig['noteId']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$alleNotenIds = array_keys($requiredNoteIds);
|
||||
|
||||
if (count($mRunFunctions) > 0) {
|
||||
foreach ($indexedNotenArray as $sG => $siNA) {
|
||||
foreach ($alleNotenIds as $neni) {
|
||||
if (!isset($ascArrayDefaultValues[$neni])) continue;
|
||||
|
||||
$isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
|
||||
if ($isProGeraet === 1 && (int)$sG === 0) continue;
|
||||
|
||||
if ($isProGeraet !== 1) {
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$runs = $ascArrayAnzahlLaeufeJSON[$neni][$sG][$programmId] ?? $ascArrayAnzahlLaeufeJSON[$neni][$sG]['all'] ?? $ascArrayAnzahlLaeufeJSON[$neni]["default"] ?? 1;
|
||||
|
||||
for ($r = 1; $r <= $runs; $r++) {
|
||||
if (!isset($indexedNotenArray[$sG][$neni][$r])) {
|
||||
$indexedNotenArray[$sG][$neni][$r] = ["value" => $ascArrayDefaultValues[$neni], "type" => "default_value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($indexedNotenArray as $sG => $siNA) {
|
||||
foreach ($alleNotenIds as $neni) {
|
||||
if (isset($indexedNotenArray[$sG][$neni][$run_number])) continue;
|
||||
if (!isset($ascArrayDefaultValues[$neni])) continue;
|
||||
|
||||
$isProGeraet = (int)($ascArrayProGeraet[$neni] ?? 0);
|
||||
if ($isProGeraet === 1 && (int)$sG === 0) continue;
|
||||
|
||||
if ($isProGeraet !== 1) {
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$neni] ?? [];
|
||||
if (!is_array($allowedGeraete) || !in_array($sG, $allowedGeraete)) continue;
|
||||
}
|
||||
|
||||
$indexedNotenArray[$sG][$neni][$run_number] = ["value" => $ascArrayDefaultValues[$neni], "type" => "default_value"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to save the IDs that were actually recalculated
|
||||
$idsToSave = [];
|
||||
|
||||
foreach ($abhaenigeRechnungen as $sRechnung) {
|
||||
$targetNoteId = $sRechnung[0];
|
||||
$rechnungType = $sRechnung[1];
|
||||
$targetRun = $sRechnung[2][0] ?? 'A';
|
||||
|
||||
// 1. Initial Filter
|
||||
if ($rechnungType !== "A" && intval($rechnungType) !== $gereat_id) continue;
|
||||
|
||||
$rechnung = $ascArrayRechnungen[$targetNoteId] ?? null;
|
||||
if ($rechnung === null) {
|
||||
echo json_encode(['success' => true, 'message' => "Fehler: Rechnung $targetNoteId nicht gefunden"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2. Determine Target Device ID
|
||||
$isProGeraet = (intval($ascArrayProGeraet[$targetNoteId] ?? 0) === 1);
|
||||
$allowedGeraete = $ascArrayGeraeteJSON[$targetNoteId] ?? [];
|
||||
|
||||
if ($rechnungType === "A" || $isProGeraet || in_array($gereat_id, $allowedGeraete)) {
|
||||
$targetGeraetKey = $gereat_id;
|
||||
} else {
|
||||
$targetGeraetKey = 0;
|
||||
}
|
||||
|
||||
// 3. Calculation Logic
|
||||
$runsConfig = $ascArrayAnzahlLaeufeJSON[$targetNoteId] ?? [];
|
||||
$runs = $runsConfig[$targetGeraetKey][$programmId] ?? $runsConfig[$targetGeraetKey]["all"] ?? $runsConfig["default"] ?? 1;
|
||||
|
||||
$acrun = min($runs, $run_number);
|
||||
|
||||
if (in_array($targetNoteId, $mRunFunctions)) {
|
||||
$calcResult = $notenRechner->berechneStringComplexRun($rechnung, $indexedNotenArray, $targetGeraetKey, $programmId, $ascArrayAnzahlLaeufeJSON);
|
||||
} else {
|
||||
$calcResult = $notenRechner->berechneStringComplex($rechnung, $indexedNotenArray, $targetGeraetKey, $acrun);
|
||||
}
|
||||
|
||||
if (!($calcResult['success'] ?? false)) {
|
||||
echo json_encode(['success' => true, 'message' => "Rechenfehler in $targetNoteId: " . ($calcResult['value'] ?? '')]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$acTargetRun = ($targetRun === "A") ? $acrun : intval($targetRun);
|
||||
|
||||
|
||||
// 4. Update State
|
||||
$val = $calcResult['value'];
|
||||
$indexedNotenArray[$targetGeraetKey][$targetNoteId][$acTargetRun] = ["value" => $val, "type" => "berechnet"];
|
||||
$updatedValues[$targetGeraetKey][$targetNoteId][$acTargetRun] = $val;
|
||||
}
|
||||
|
||||
// Prepare the statement once
|
||||
$sql = "INSERT INTO $db_tabelle_wertungen (`value`, `person_id`, `note_bezeichnung_id`, `geraet_id`, `wk_id`, `run_number`)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)";
|
||||
|
||||
$stmt = $mysqli->prepare($sql);
|
||||
$formatedNoten = [];
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
foreach ($updatedValues as $gereat => $notenArray) {
|
||||
foreach ($notenArray as $note => $runArray) {
|
||||
foreach ($runArray as $run => $value) {
|
||||
$stmt->bind_param("siiiii", $value, $person_id, $note, $gereat, $current_wk_id, $run);
|
||||
$stmt->execute();
|
||||
$formatedNoten[$gereat][$note][$run] = number_format($value ,$indexedNullstellen[$note] ?? 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mysqli->commit();
|
||||
|
||||
$formatedNoten[$gereat_id][$field_type_id][$run_number] = number_format($valueNoteUpdate ,$indexedNullstellen[$field_type_id] ?? 2);
|
||||
|
||||
$stmt->close();
|
||||
$mysqli->close();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => "Wert aktualisiert, alle Berechnungen durchgeführt",
|
||||
"noten" => $formatedNoten
|
||||
]);
|
||||
@@ -0,0 +1,297 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($baseDir)) {
|
||||
$baseDir = $_SERVER['DOCUMENT_ROOT'];
|
||||
}
|
||||
|
||||
require_once $baseDir . '/../scripts/session_functions.php';
|
||||
|
||||
ini_wkvs_session();
|
||||
|
||||
check_user_permission('kampfrichter');
|
||||
|
||||
verify_csrf();
|
||||
|
||||
// ---------- Get and sanitize input ----------
|
||||
$id = intval($_POST['personId'] ?? 0);
|
||||
$initNoteRun = intval($_POST['run'] ?? 0);
|
||||
$geraetId = intval($_POST['geraetId'] ?? 0);
|
||||
$dataType = intval($_POST['dataType'] ?? 0);
|
||||
$jahr = isset($_POST['jahr']) ? preg_replace('/[^0-9]/', '', $_POST['jahr']) : '';
|
||||
$anfrageType = $_POST['type'] ?? '';
|
||||
|
||||
$allowedTypes = ["neu", "start", "result"];
|
||||
|
||||
if (!in_array($anfrageType, $allowedTypes)) {
|
||||
echo json_encode(['success' => false, 'message' => "Operation nicht gestattet."]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($anfrageType !== "start" && ($id < 1 || intval($jahr) < 1)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Personen ID ist nicht valide.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($geraetId < 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$type = 'kr';
|
||||
|
||||
$data = require $baseDir . '/../scripts/db/db-verbindung-script.php';
|
||||
|
||||
if ($data['success'] === false){
|
||||
echo json_encode(['success' => false, 'message' => $data['message']]);
|
||||
exit;
|
||||
}
|
||||
|
||||
require $baseDir . '/../scripts/db/db-functions.php';
|
||||
require $baseDir . '/../scripts/db/db-tables.php';
|
||||
|
||||
$stmt = $mysqli->prepare("SELECT `name` FROM $db_tabelle_disziplinen WHERE `id` = ? LIMIT 1");
|
||||
$stmt->bind_param("s", $geraetId);
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = $stmt->get_result();
|
||||
|
||||
if ($result->num_rows === 0) {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid discipline']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$geraetData = $result->fetch_assoc();
|
||||
$geraetName = $geraetData['name'];
|
||||
|
||||
$stmt->close();
|
||||
|
||||
$folder = realpath($baseDir . '/externe-geraete/json');
|
||||
|
||||
if ($folder === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Could not find displays folder.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$filename = 'display-id-' . $geraetId . '.json';
|
||||
$filepath = $folder . '/' . $filename;
|
||||
|
||||
if (!is_writable($folder)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Folder not writable']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$jsonString = file_get_contents($filepath);
|
||||
|
||||
// decode JSON, fallback to empty array if invalid
|
||||
$oldjson = json_decode($jsonString, true) ?? [];
|
||||
|
||||
switch ($anfrageType) {
|
||||
case "neu":
|
||||
$stmt = $mysqli->prepare("SELECT `id`, `name`, `vorname`, `programm`, `verein` FROM `$db_tabelle_teilnehmende` WHERE id = ? LIMIT 1");
|
||||
$stmt->bind_param("i", $id);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->get_result();
|
||||
$rows = $result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
if (!$rows || !is_array($rows) || count($rows) !== 1) {
|
||||
echo json_encode(['success' => false, 'message' => 'Row fetch failed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$row = $rows[0];
|
||||
|
||||
|
||||
$data = ["noteLinks" => '',
|
||||
"noteRechts" => '',
|
||||
"id" => $id,
|
||||
"name" => $row['name'],
|
||||
"vorname" => $row['vorname'],
|
||||
"programm" => $row['programm'],
|
||||
"verein" => $row['verein'],
|
||||
"start" => false
|
||||
];
|
||||
|
||||
$arrayData = $data;
|
||||
break;
|
||||
case "start":
|
||||
if (!array_key_exists("id", $oldjson) || intval($oldjson["id"]) !== $id || !array_key_exists("start", $oldjson)) {
|
||||
echo json_encode(['success' => false, 'message' => 'Person nicht auf Display!']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$oldjson["start"] = (bool) $dataType;
|
||||
|
||||
$arrayData = $oldjson;
|
||||
break;
|
||||
case "result":
|
||||
// 1. Get IDs and filter out empty values
|
||||
$noteLinksId = db_get_variable($mysqli, $db_tabelle_var, ['displayIdNoteL']);
|
||||
$noteRechtsId = db_get_variable($mysqli, $db_tabelle_var, ['displayIdNoteR']);
|
||||
|
||||
$programm_id = db_get_var($mysqli, "SELECT p.`id` FROM $db_tabelle_teilnehmende t INNER JOIN $db_tabelle_kategorien p ON p.`programm` = t.`programm` WHERE t.`id` = ?", [$id]) ?? null;
|
||||
|
||||
$display_cache = require $baseDir . '/../scripts/cache/display-dependencies.php';
|
||||
|
||||
$this_display_cache = $display_cache[$programm_id][$geraetId][$initNoteRun];
|
||||
|
||||
$sql_where_values = $this_display_cache['values'];
|
||||
|
||||
$sql_where_string = $this_display_cache['SQL'];
|
||||
|
||||
$intersect_noten = $this_display_cache['intersect_noten'];
|
||||
|
||||
$rankLiveArray = [];
|
||||
|
||||
$current_wk_id = (int) db_get_variable($mysqli, $db_tabelle_var, ['current_wk_id']) ?: 0;
|
||||
|
||||
if (!empty($sql_where_values) && $sql_where_string !== '') {
|
||||
|
||||
$notenDB = db_select($mysqli, $db_tabelle_wertungen, '`value`, `note_bezeichnung_id`, `geraet_id`, `run_number`', "`person_id` = ? AND `wk_id` = ? AND ($sql_where_string)", array_merge([$id, $current_wk_id], $sql_where_values));
|
||||
|
||||
$indexedNotenDB = [];
|
||||
|
||||
foreach ($notenDB as $sn) {
|
||||
$indexedNotenDB[$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = $sn;
|
||||
}
|
||||
}
|
||||
|
||||
$mysqli->begin_transaction();
|
||||
|
||||
|
||||
try {
|
||||
$stmt = $mysqli->prepare("INSERT INTO $db_tabelle_wertungen (`person_id`, `note_bezeichnung_id`, `wk_id`, `geraet_id`, `run_number`, `is_public`, `public_value`) VALUES (?, ?, ?, ?, ?, 1, ?) ON DUPLICATE KEY UPDATE `public_value` = VALUES(`public_value`), `is_public` = 1");
|
||||
|
||||
foreach ($intersect_noten as $s_note) {
|
||||
$n_id = $s_note['n_id'];
|
||||
$g_id = $s_note['g_id'];
|
||||
$run = $s_note['r'];
|
||||
|
||||
$value = $indexedNotenDB[$g_id][$n_id][$run]['value'] ?? $notenConfig['default_values'][$n_id] ?? 0;
|
||||
$rankLiveArray[$g_id][$run][$n_id] = number_format($value, $notenConfig['nullstellen'][$n_id] ?? 2);
|
||||
|
||||
$stmt->bind_param("iiiiid", $id, $n_id, $current_wk_id, $g_id, $run, $value);
|
||||
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$mysqli->commit();
|
||||
$stmt->close();
|
||||
} catch (Exception $e) {
|
||||
$mysqli->rollback();
|
||||
echo json_encode(['success' => false, 'message' => 'DB Transaction failed Error: ' . $e->getMessage()]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Create an array of IDs that actually exist
|
||||
$validIds = array_filter([$noteLinksId, $noteRechtsId]);
|
||||
|
||||
$noten = [];
|
||||
$notenConfig = [];
|
||||
|
||||
if (!empty($validIds)) {
|
||||
// 2. Fetch Noten (Only if we have IDs to look for)
|
||||
$placeholders = implode(',', array_fill(0, count($validIds), '?'));
|
||||
|
||||
$sqlNoten = "SELECT `value`, `note_bezeichnung_id` FROM $db_tabelle_wertungen
|
||||
WHERE person_id = ? AND `wk_id` = ? AND `geraet_id` = ? AND run_number = ?
|
||||
AND `note_bezeichnung_id` IN ($placeholders)";
|
||||
|
||||
$stmt = $mysqli->prepare($sqlNoten);
|
||||
// Combine standard params with our dynamic ID list
|
||||
$params = array_merge([$id, $current_wk_id, $geraetId, $initNoteRun], $validIds);
|
||||
$types = str_repeat('s', count($params));
|
||||
$stmt->bind_param($types, ...$params);
|
||||
$stmt->execute();
|
||||
$notenDB = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$noten = array_column($notenDB, 'value', 'note_bezeichnung_id');
|
||||
$stmt->close();
|
||||
|
||||
// 3. Fetch Config
|
||||
$sqlConfig = "SELECT `id`, `default_value`, `nullstellen`, `display_string`
|
||||
FROM $db_tabelle_wertungstypen WHERE `id` IN ($placeholders)";
|
||||
|
||||
$stmt = $mysqli->prepare($sqlConfig);
|
||||
$typesConfig = str_repeat('s', count($validIds));
|
||||
$stmt->bind_param($typesConfig, ...$validIds);
|
||||
$stmt->execute();
|
||||
$notenConfigDB = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
|
||||
$notenConfig = array_column($notenConfigDB, null, 'id');
|
||||
$stmt->close();
|
||||
}
|
||||
|
||||
// 4. Helper function to safely format the output without crashing
|
||||
$formatNote = function($id) use ($noten, $notenConfig) {
|
||||
if (!$id || !isset($notenConfig[$id])) {
|
||||
return ""; // Return empty string if ID is not set or not found in DB
|
||||
}
|
||||
|
||||
$conf = $notenConfig[$id];
|
||||
$val = $noten[$id] ?? $conf['default_value'] ?? 0;
|
||||
$prec = $conf['nullstellen'] ?? 2;
|
||||
|
||||
$display_schema = $conf['display_string'] ?? '${note}';
|
||||
|
||||
$formatted_note = number_format((float)$val, (int)$prec, '.', '');
|
||||
|
||||
$result = str_ireplace('${note}', $formatted_note, $display_schema);
|
||||
|
||||
if ($result === $display_schema) {
|
||||
return $formatted_note;
|
||||
}
|
||||
|
||||
return $result;
|
||||
};
|
||||
|
||||
// 5. Assign to JSON
|
||||
$oldjson["noteLinks"] = $formatNote($noteLinksId);
|
||||
$oldjson["noteRechts"] = $formatNote($noteRechtsId);
|
||||
|
||||
$arrayData = $oldjson;
|
||||
|
||||
break;
|
||||
default:
|
||||
http_response_code(400);
|
||||
exit;
|
||||
}
|
||||
|
||||
$jsonData = json_encode($arrayData);
|
||||
|
||||
// Write file
|
||||
if (file_put_contents($filepath, $jsonData) === false) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to write JSON file'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($anfrageType === "result") {
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON updated successfully for ' . $geraetName,
|
||||
'data' => $arrayData,
|
||||
'rankLive' => $rankLiveArray,
|
||||
'nameGeraet' => strtolower($geraetName)
|
||||
]);
|
||||
} else {
|
||||
// ---------- Return JSON ----------
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'JSON updated successfully for ' . $geraetName,
|
||||
'data' => $arrayData,
|
||||
'nameGeraet' => strtolower($geraetName)
|
||||
]);
|
||||
}
|
||||
exit;
|
||||
Reference in New Issue
Block a user