CREATE VIEW roadtokona.view_result_normalized AS
SELECT
+ fk_race,
+ fk_division,
race_date,
race_location,
division_gender,
FROM
roadtokona.result re
JOIN roadtokona.race ra ON (re.fk_race = ra.race_id)
-JOIN roadtokona.division di ON (re.fk_division = di.division_id);
+JOIN roadtokona.division di ON (re.fk_division = di.division_id)
+ORDER BY
+ result_normalized;
CREATE VIEW roadtokona.view_division_factor AS
SELECT
- division_gender,
- division_age,
- factor_value
+ factor_value,
+ division_gender || division_age
FROM
roadtokona.factor fa
JOIN roadtokona.division di ON (fa.fk_division = di.division_id);
+CREATE VIEW roadtokona.view_division AS
+SELECT
+ division_gender || division_age as agegroup,
+ division_gender || division_age
+FROM
+ roadtokona.factor fa
+JOIN roadtokona.division di ON (fa.fk_division = di.division_id);
+
+CREATE VIEW roadtokona.view_division_winner AS
+SELECT
+ min(result_finish) as finish_winner,
+ fk_division,
+ fk_race
+FROM
+ roadtokona.result
+GROUP BY
+ fk_division,
+ fk_race;
+
+CREATE VIEW roadtokona.view_race AS
+SELECT
+ race_id,
+ race_location || ' (' || to_char(race_date, 'DD.MM.YYYY') || ')'
+FROM
+ roadtokona.race
+ORDER BY
+ race_date;
+
+CREATE VIEW roadtokona.view_result_normalized_rolldown AS
+SELECT
+ roadtokona.view_result_normalized.*
+FROM
+ roadtokona.view_result_normalized
+WHERE NOT EXISTS (
+ SELECT 1
+ FROM roadtokona.view_division_winner
+ WHERE roadtokona.view_result_normalized.result_finish = roadtokona.view_division_winner.finish_winner
+ AND roadtokona.view_result_normalized.fk_division = roadtokona.view_division_winner.fk_division
+ AND roadtokona.view_result_normalized.fk_race = roadtokona.view_division_winner.fk_race
+)
+ORDER BY
+ result_normalized;
+
+
insert into roadtokona.division values
(default, 'M', 18),
(default, 'F', 18),
--ALTER TABLE roadtokona.result OWNER TO laktatnebel;
--ALTER TABLE roadtokona.view_result_normalized OWNER TO laktatnebel;
---GRANT ALL ON SCHEMA roadtokona TO oleb;
+ALTER SCHEMA roadtokona OWNER TO oleb;
+
+ALTER TABLE roadtokona.division OWNER TO oleb;
+ALTER TABLE roadtokona.race OWNER TO oleb;
+ALTER TABLE roadtokona.factor OWNER TO oleb;
+ALTER TABLE roadtokona.result OWNER TO oleb;
+ALTER TABLE roadtokona.view_result_normalized OWNER TO oleb;
+ALTER TABLE roadtokona.view_division OWNER TO oleb;
+ALTER TABLE roadtokona.view_division_factor OWNER TO oleb;
+ALTER TABLE roadtokona.view_race OWNER TO oleb;
+ALTER TABLE roadtokona.view_division_winner OWNER TO oleb;
+ALTER TABLE roadtokona.view_result_normalized_rolldown OWNER TO oleb;
+
+GRANT ALL ON SCHEMA roadtokona TO oleb;
--- /dev/null
+
+<?php require_once '../roadtokona_glob_vars.php'; ?>
+<?php require_once 'lib/database_functions.php'; ?>
+<?php
+header('Content-Type: application/json');
+
+$str_connection = "host=".HOST." port=5432 dbname=".DB." user=".USER." password=".PASS." ";
+
+$race_id = $_GET['rid'] ?? '';
+
+try {
+ // PostgreSQL Verbindung
+ $db = pg_connect($str_connection);
+ if (!$db) {
+ throw new Exception('Verbindung zur Datenbank fehlgeschlagen');
+ }
+
+ // Nur erlaubte Spalten selektieren (Security!)
+ //$query = "SELECT $columns FROM $source LIMIT 100";
+
+ // Query ausführen
+ $result = pg_query($db, str_replace($race_id, "FK_RACE", $selectFromViewResultNormalizedRolldown));
+ if (!$result) {
+ throw new Exception('Datenbankabfrage fehlgeschlagen');
+ }
+
+ // Daten sammeln
+ $data = [];
+ while ($row = pg_fetch_assoc($result)) {
+ $data[] = $row;
+ }
+
+ // Ressourcen freigeben
+ pg_free_result($result);
+ pg_close($db);
+
+ echo json_encode($data);
+
+} catch (Exception $e) {
+ http_response_code(500);
+ echo json_encode([
+ 'error' => 'Serverfehler',
+ 'message' => $e->getMessage()
+ ]);
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php\r
+putenv("PGGSSENCMODE=disable");\r
+putenv("LC_ALL=C");\r
+?>\r
+<?php require_once '../roadtokona_glob_vars.php'; ?>\r
+<?php require_once 'lib/database_functions.php'; ?>\r
+<?php require_once 'lib/gui_functions.php'; ?>\r
+<?php require_once 'lib/util_functions.php'; ?>\r
+<?php
+$page = 'index.php';\r
+\r
+$j=0;\r
+\r
+$connect_dbms_handle = getDBConnection();\r
+\r
+$current_user=1;\r
+\r
+?>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="de">\r
+\r
+<head>\r
+<meta http-equiv="content-type" content="text/html; charset=UTF-8" />\r
+<meta http-equiv="expires" content="0" /> \r
+\r
+<title>roadtokona.triathlon-coaching.com</title>\r
+\r
+<link rel="stylesheet" href="stylesheet/roadtokona.css" type="text/css" media="screen, projection\" />\r
+</head>\r
+\r
+<body>\r
+<header>\r
+<h1>#roadtokona</h1>\r
+</header>\r
+\r
+<main>\r
+<h2>Was ist neu?</h2>\r
+<p>Der Weg nach Kona ist anders geworden. Laut IRONMAN Cooperation fairer, aber definitiv weniger transparent.</p>\r
+<p>Bislang reichte ein bestimmter Platz in deienr Altersklasse für einen Slot, oder man konnte auf das Roll-down-verfahren hoffen und nachrücken.<br />\r
+Das war auch für den Support / Coach einfach: Am Live-Tracker war der aktuelle Stand der Dinge jederzeit ersichtlich.<br />"Platz 5 ist 2 Minuten vor Dir, gib Gas!" - diese Rufe hört man nun selten.</p>\r
+<p>Jetzt werden alle Zeiten im Ziel erst mit einem für jede Altersklasse spezifischen Faktor multipliziert und daraus eine Liste mit "normalisierten Zeiten" generiert.<br />Anhand derer werden dann die begehrten Slots vergeben.</p>\r
+<p>Ganz einfach, oder? Profis und PC/HC haben eigene Verfahren und die Ersten der jeweiligen Altersklassen sind auf jeden Fall qualifiziert.</p></section>\r
+\r
+\r
+<h2>Faktoren</h2>\r
+<p>Diese Faktoren hat die IRONMAN Cooperation veröffentlicht.<br />\r
+Da diese auf echten Ergebnissen beruhen, können sie sich jede Sasion auch ändern - ich werde hier immer nur die allerneusten Werte verwenden.</p>\r
+<div class="factors-container">\r
+<div><p>\r
+<?php\r
+$dataDivisionFactor = getData($connect_dbms_handle, $selectFromViewDivisionFactor);\r
+foreach ($dataDivisionFactor as $data) {\r
+ //print_r($d);\r
+ echo $data[1]." - ".$data[0];\r
+ if ($data[1] == "M85" ) {\r
+ echo "\n</p></div>\n<div><p>\n";\r
+// echo "<br />";\r
+ } else {\r
+ echo "<br />\n";\r
+ }\r
+}\r
+?>\r
+* Mangels Daten in den Klassen F80 und älter gibt es dafür keine Faktoren.\r
+</p></div></div>\r
+\r
+<h2>Wie kann ich meine Zeit umrechnen?</h2>\r
+<form id="calculator">\r
+<fieldset>\r
+<legend>Rechner</legend>\r
+Deine Zeit:\r
+<?php\r
+makeSelect("yourhour", null, "yourhour", null, 0, 0, 24, -1, false, 1, null, null, null, false, false, 1);\r
+echo "h ";\r
+makeSelect("yourminute", null, "yourminute", null, 2, 0, 60, -1, false, 1, null, null, null, false, false, 1);\r
+echo "min ";\r
+makeSelect("yoursecond", null, "yoursecond", null, 3, 0, 60, -1, false, 1, null, null, null, false, false, 1);\r
+echo "sec ";\r
+?>\r
+<br />Deine Altersklasse:\r
+<?php\r
+makeSelect("yourag", $dataDivisionFactor, "yourag", null, 4, 0, 0, -1, false, 1, null, null, null, false, false, 1);\r
+?>\r
+<div>\r
+<p id="result">Ergebnis: 00:00:00</p>\r
+</div>\r
+</fieldset>\r
+</form>\r
+\r
+<h2>Wie schnell hätte ich sein müssen?</h2>\r
+<p>Das ist die Gretchenfrage. :-) Da die Slotvergabe nach dem neuen System erst ab dem 16. August 2025 greift, sind die Ergebnisse aller anderen Wettkämpfe davor nur bedingt aussagekräftig.<br />\r
+Aber Du kannst ja gucken, welche Zeit in welcher Klasse zu welcher Platzierung in der "normalisierten Liste" gereicht hätte.<br />Die Schlüsse daraus kannst Du ja selber ziehen ;-)</p>\r
+<p>Du kannst den Wettkampf auswählen und bekommst die Rolldown-Liste. Das heißt die Liste ohne Profis, PC/HC und Ersten der jeweiligen Altersklasse.<br />\r
+Wenn es beispielsweise 75 Slots für die begehrte Insel gibt, sind davon schon maximal 26 durch die Ersten belegt. Bleiben noch 49.</p>\r
+<form id="raceselector">\r
+<fieldset>\r
+<legend>Wettkampfauswahl</legend>\r
+wähle aus: <?php\r
+$dataRaces = getData($connect_dbms_handle, $selectFromViewRaces);\r
+makeSelect("race", $dataRaces, "race", null, 5, 0, 0, -1, false, 1, null, null, null, false, false, 1);\r
+?>\r
+<br />... und markiere eine Altersklasse:\r
+<?php\r
+$dataDivision = getData($connect_dbms_handle, $selectFromViewDivision);\r
+makeSelect("ag", $dataDivision, "ag", null, 6, 0, 0, -1, false, 1, null, null, null, false, false, 1);\r
+?>\r
+<div>\r
+ <p id="results">Bitte Wettkampf auswählen.</p>\r
+</div>\r
+</fieldset>\r
+</form>\r
+\r
+</main>\r
+\r
+<footer>\r
+<a href="https://www.triathlon-coaching.com">Impressum, Datenschutz, Copyright, Kontakt ...</a>\r
+</footer>\r
+\r
+<script src="js/roadtokona.js"></script>\r
+</body>\r
+</html>\r
+<?php
+closeDBConnection ( $connect_dbms_handle );
+?>
--- /dev/null
+/**
+ *
+ */
+
+document.addEventListener('DOMContentLoaded', function() {
+ // Elemente auswählen
+ const hoursSelect = document.getElementById('yourhour');
+ const minutesSelect = document.getElementById('yourminute');
+ const secondsSelect = document.getElementById('yoursecond');
+ const factorSelect = document.getElementById('yourag');
+ const resultParagraph = document.getElementById('result');
+
+ // Event-Listener für alle Auswahllisten
+ [hoursSelect, minutesSelect, secondsSelect, factorSelect].forEach(select => {
+ select.addEventListener('change', calculateResult);
+ });
+
+ // Funktion zur Formatierung der Zeit im hh:mm:ss Format
+ function formatTime(totalSeconds) {
+ // Sicherstellen, dass wir mit einer ganzen Zahl arbeiten
+ totalSeconds = Math.round(totalSeconds);
+
+ // Stunden, Minuten und Sekunden berechnen
+ const hours = Math.floor(totalSeconds / 3600);
+ const remainingSeconds = totalSeconds % 3600;
+ const minutes = Math.floor(remainingSeconds / 60);
+ const seconds = remainingSeconds % 60;
+
+ // Führende Nullen hinzufügen
+ const pad = num => num.toString().padStart(2, '0');
+
+ return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
+ }
+
+ // Funktion zur Berechnung des Ergebnisses
+ function calculateResult() {
+ // Werte auslesen
+ const hours = parseInt(hoursSelect.value) || 0;
+ const minutes = parseInt(minutesSelect.value) || 0;
+ const seconds = parseInt(secondsSelect.value) || 0;
+ const factor = parseFloat(factorSelect.value) || 1;
+
+ // Gesamtzeit in Sekunden berechnen
+ const totalSeconds = hours * 3600 + minutes * 60 + seconds;
+
+ // Ergebnis berechnen
+ const result = totalSeconds * factor;
+
+ // Ergebnis formatieren und anzeigen
+ resultParagraph.textContent = `Ergebnis: ${formatTime(result)}`;
+ }
+
+ // Initiale Berechnung
+ calculateResult();
+ });
+
+
+
+document.getElementById('race').addEventListener('change', function() {
+ const selection = this.value;
+ const resultsDiv = document.getElementById('results');
+
+ if (!selection) {
+ resultsDiv.innerHTML = '<p>Bitte Wettkampf auswählen.</p>';
+ return;
+ }
+
+ resultsDiv.innerHTML = '<p class="loading">Daten werden geladen...</p>';
+
+ // AJAX-Anfrage an den Server
+ fetch(`getRaceData.php?rid=${encodeURIComponent(selection)}`)
+ .then(response => {
+ if (!response.ok) {
+ throw new Error(`Serverfehler: ${response.status}`);
+ }
+ return response.json();
+ })
+ .then(data => {
+ if (!data || data.length === 0) {
+ resultsDiv.innerHTML = '<p>Keine Daten gefunden.</p>';
+ return;
+ }
+
+ // Tabelle erstellen
+ let html = '<p class="cta">OMG - ist das flott!<br /><a href="https://www.triathlon-coaching.com">Brauchst Du einen Coach?</a></p>'
+ html += '<table id="resultlist"><thead><tr><th>#</th>';
+
+ // Spaltenüberschriften
+ const columns = Object.keys(data[0]);
+ columns.forEach(col => {
+ html += `<th>${col}</th>`;
+ });
+ html += '</tr></thead><tbody>';
+
+ ct=0;
+ // Datenzeilen
+ data.forEach(row => {
+ ct++;
+ html += '<tr>';
+ html += '<td>'+ct+'</td>';
+ columns.forEach(col => {
+ html += `<td>${row[col] ?? ''}</td>`;
+ });
+ html += '</tr>';
+ });
+
+ html += '</tbody></table>';
+ resultsDiv.innerHTML = html;
+ // Nachdem die Tabelle geladen wurde, den Event-Listener für die Altersklassenauswahl setzen
+ setupAgeGroupHighlighting();
+ })
+ .catch(error => {
+ resultsDiv.innerHTML = `<p class="error">Fehler beim Laden der Daten: ${error.message}</p>`;
+ console.error('Fehler:', error);
+ });
+});
+
+
+
+
+// Funktion für die Markierung der Altersklassen
+function setupAgeGroupHighlighting() {
+ const auswahl = document.getElementById('ag');
+ const tabelle = document.getElementById('resultlist');
+
+ // Event-Listener entfernen, falls bereits vorhanden
+ auswahl.removeEventListener('change', handleAgeGroupSelection);
+
+ // Neuen Event-Listener hinzufügen
+ auswahl.addEventListener('change', handleAgeGroupSelection);
+}
+
+// Handler für die Altersklassenauswahl
+function handleAgeGroupSelection() {
+ const tabelle = document.getElementById('resultlist');
+ if (!tabelle) return;
+
+ // Zuerst alle Markierungen entfernen
+ const bereitsMarkiert = tabelle.querySelectorAll('.highlight');
+ bereitsMarkiert.forEach(element => {
+ element.classList.remove('highlight');
+ });
+
+ // Wenn eine Option ausgewählt wurde (nicht die leere Standardoption)
+ if (this.value) {
+ const selectedText = this.options[this.selectedIndex].text;
+ console.log('selectedText:', selectedText);
+
+ const zellen = tabelle.querySelectorAll('td');
+ zellen.forEach(zelle => {
+ if (zelle.textContent === selectedText) {
+ zelle.closest('tr').classList.add('highlight');
+ }
+ });
+ }
+}
+
+// Initialen Event-Listener setzen (falls Tabelle bereits existiert)
+document.addEventListener('DOMContentLoaded', function() {
+ // Prüfen, ob die Tabelle bereits existiert (z.B. bei Seitenrefresh)
+ if (document.getElementById('resultlist')) {
+ setupAgeGroupHighlighting();
+ }
+});
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("db/database_functions_pgsql.php");
+
+require ("db/database_functions_select.php");
+
+
+$selectFromViewRaces = "SELECT * FROM ".SCHEMA.".view_race;";
+
+$selectFromViewDivision = "SELECT * FROM ".SCHEMA.".view_division;";
+
+$selectFromViewDivisionFactor = "SELECT * FROM ".SCHEMA.".view_division_factor;";
+
+$selectFromViewResultNormalizedRolldown = "SELECT division_gender || division_age AS \"Agegroup\", result_finish AS \"Finish Time\", factor_value AS \"Faktor\", result_normalized AS \"Rolldown Time\" FROM ".SCHEMA.".view_result_normalized_rolldown WHERE fk_race=FK_RACE;";
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/**
+ * Mit PostgresSQL verbinden */
+function getDBConnection() {
+
+ $str_connection = "host=".HOST." port=5432 dbname=".DB." user=".USER." password=".PASS." ";
+ //echo $str_connection;
+ // mit DB verbinden
+ //$connect_dbms_handle = new PDO("pgsql:dbname=".DB, USER, PASS);
+ $connect_dbms_handle = @pg_connect($str_connection) or die('Verbindungsaufbau fehlgeschlagen: ' . pg_last_error());
+
+ if ($connect_dbms_handle) {
+ return $connect_dbms_handle;
+ } else {
+ echo "Datenbankabfrage fehlgeschlagen!";
+ echo pg_last_error($connect_dbms_handle);
+ return false;
+ }
+}
+
+/**
+ * PostgresSQL-Verbindung schliessen */
+function closeDBConnection($ref_connection) {
+ @pg_close($ref_connection) or die('Verbindungsclose fehlgeschlagen: ');
+ //echo pg_last_error($ref_connection);
+}
+
+
+// SQL an DB absetzen
+// Parameter: Tablle, Feld(er), Wert(e)
+// Rückgabewert: boolean
+function getBooleanData ($dbms_connection, $db_query) {
+ // Variablen
+ $return_bool_value = false ;
+
+ // DB Abfage starten
+ //echo $db_query;
+ $res_sql_result = pg_query ($dbms_connection, $db_query);
+ // Gültigkeit der DB Abfage testen
+ if ($res_sql_result) {
+ //echo "<li>".$res_sql_result;
+ $return_bool_value = true;
+ } else {
+ return "Datenbankabfrage fehlgeschlagen!";
+ }
+
+ return $return_bool_value;
+}
+
+
+// SQL an DB absetzen
+// Parameter: Tablle, Feld(er), Wert(e)
+// Rückgabewert: Array
+function getData ($dbms_connection, $db_query) {
+ $return_arr_data = array(); // Rückgabewert als Array
+ //echo "\n<p> SQL:<br>".$ref_str_db_query."</p>";
+
+ // DB Abfage starten
+ //echo $db_query;
+ $res_sql_result = pg_query ($dbms_connection, $db_query);
+ // Gültigkeit der DB Abfage testen
+ if ($res_sql_result) {
+ //echo "<p>".$res_sql_result."</p>";
+ while ($arr_sql_data = pg_fetch_row($res_sql_result)) {
+ //echo debugPrint($arr_sql_data);
+ array_push ($return_arr_data, $arr_sql_data);
+ }
+ //var_dump( $return_arr_data);
+ } else {
+ return "Datenbankabfrage fehlgeschlagen!";
+ }
+
+ return $return_arr_data;
+}
+
+
+// SQL an DB absetzen
+// Parameter: Tablle, Feld(er), Wert(e)
+// Rückgabewert: Array
+function getDataReturnID ($dbms_connection, $db_query) {
+ $return_arr_data = array(); // Rückgabewert als Array
+ //echo "\n<p> SQL:<br>".$ref_str_db_query."</p>";
+
+ // DB Abfage starten
+ //echo $db_query;
+ $res_sql_result = pg_query ($dbms_connection, $db_query);
+ // Gültigkeit der DB Abfage testen
+ if ($res_sql_result) {
+ //echo "<p>".$res_sql_result."</p>";
+ while ($arr_sql_data = pg_fetch_row($res_sql_result)) {
+ //echo debugPrint($arr_sql_data);
+ array_push ($return_arr_data, $arr_sql_data);
+ }
+ //var_dump( $return_arr_data);
+ } else {
+ return "Datenbankabfrage fehlgeschlagen!";
+ }
+
+ return $return_arr_data[0][0];
+}
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+function generateSelect ($selectedFields, $table) {
+ $select_str = "SELECT ";
+
+ if (is_array($selectedFields)) {
+ //print_r($selectedFields);
+ $anzFields = count($selectedFields);
+ for ($i = 0 ; $i < $anzFields; $i++) {
+ $select_str .= $selectedFields[$i];
+ if ($i < $anzFields-1) {
+ $select_str .= ", ";
+ }
+ }
+ } else {
+ $select_str .= "*";
+ }
+
+ $select_str .= " FROM ".$table;
+
+ $select_str .= ";";
+
+ //echo $select_str;
+ return $select_str;
+}
+
+
+function generateSelectWhereOrder ($selectedFields, $table, $whereClause, $orderClause) {
+ $select_str = "SELECT ";
+
+ if (is_array($selectedFields)) {
+ //print_r($selectedFields);
+ $anzFields = count($selectedFields);
+ for ($i = 0 ; $i < $anzFields; $i++) {
+ $select_str .= $selectedFields[$i];
+ if ($i < $anzFields-1) {
+ $select_str .= ", ";
+ }
+ }
+ } else {
+ $select_str .= "*";
+ }
+
+ $select_str .= " FROM ".$table;
+
+ if ($whereClause != null) {
+ $select_str .= " WHERE ";
+
+ //print_r($whereClause);
+ $anzWheres = count($whereClause);
+ for ($i = 0 ; $i < $anzWheres; $i++) {
+ $select_str .= $whereClause[$i];
+ if ($i < $anzWheres-1) {
+ $select_str .= " AND ";
+ }
+ }
+ }
+
+ if ($orderClause != null) {
+ $select_str .= " ORDER BY ";
+
+ //print_r($orderClause);
+ $anzOrders = count($orderClause);
+ for ($i = 0 ; $i < $anzOrders; $i++) {
+ $select_str .= $orderClause[$i];
+ if ($i < $anzOrders-1) {
+ $select_str .= ", ";
+ }
+ }
+ }
+
+ $select_str .= ";";
+
+ //echo $select_str;
+ return $select_str;
+}
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+/** $ref_select_name Name des <select>
+ * $ref_value_array Daten-Array; null möglich
+ * $ref_id Id des <select>
+ * $ref_class Class des <select>; null möglich
+ * $ref_tabindex Tabindex in der <form>
+
+ * $ref_start Start-Index statt Datenarray falls Datenarray null
+ * $ref_end End-Index statt Datenarray falls Datenarray null
+ * $ref_int_preselect Index vorausgewähltes Element; default -1
+ * $ref_multiple Mehrfachauswahl <select multiple>; default false
+ * $ref_int_size Für mehrzeilige Mehrfachauswahl > 1;
+ * $ref_javascript Javascript; null möglich
+
+ * $ref_mandantory Pflichtfeldmarkierung; null möglich
+ * $ref_labeltitle <label>-Text; null möglich
+ * $ref_p_flag true, wenn alles in <p> soll
+ * $ref_newline_flag true, wenn <label> ueber <select> stehen soll
+ * $ref_intend Anz. Tabs einrücken
+ * */
+function makeSelect($ref_select_name, $ref_value_array, $ref_id, $ref_class, $ref_tabindex, $ref_start, $ref_end, $ref_int_preselect, $ref_multiple, $ref_int_size, $ref_javascript, $ref_mandantory, $ref_labeltitle, $ref_p_flag, $ref_newline_flag, $ref_intend) {
+
+ $intend = make_intend_str($ref_intend);
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "<p>\n";
+ }
+
+ echo $intend."\t";
+
+ if ($ref_mandantory) {
+ echo "* ";
+ }
+
+ if ($ref_labeltitle != null) {
+ echo "<label for=\"".$ref_select_name."\">".$ref_labeltitle."</label>";
+ if ($ref_newline_flag) {
+ echo "<br />";
+ }
+ echo "\n";
+ }
+
+ $str_id = $ref_id == null ? " " : " id=\"".$ref_id."\" ";
+ $str_class = $ref_class == null ? " " : " class=\"".$ref_class."\" ";
+ $str_tabindex = $ref_tabindex == null ? " " : " tabindex=\"".$ref_tabindex."\" ";
+ $str_javascript = $ref_javascript == null ? " " : " onchange=\"".$ref_javascript."\" ";
+
+ echo $intend."\t";
+
+ echo "<select ".$str_id.$str_class.$str_tabindex.$str_javascript."name=\"".$ref_select_name."\" size=\"".$ref_int_size."\" "." ";
+ if ($ref_multiple == true) {
+ echo "multiple=\"multiple\" ";
+ }
+ echo ">\n";
+
+ if ($ref_value_array != null) {
+
+ // Flag: True, falls das Datenarray multidimensional ist. Dann wird das Attribut value in <option> mit dem wert aus dem Unterarray gefüllt, ansonsten wird der Schleifenindex verwendet.
+ $multiDimensionalArrayFlag = is_array($ref_value_array[0]);
+
+ for ($i=0; $i<count($ref_value_array); $i++) {
+ echo $intend;
+ echo "\t\t<option value=\"".($multiDimensionalArrayFlag ? $ref_value_array[$i][0] : $i)."\"";
+ if (($multiDimensionalArrayFlag ? $ref_value_array[$i][0] : ($i+1)) == $ref_int_preselect) { // $i-1 deshalb, weil das Array mit dem 0-ten Element beginnt, der Value aber mit 1 anfängt
+ echo " selected";
+ }
+ echo ">".($multiDimensionalArrayFlag ? $ref_value_array[$i][1] : $ref_value_array[$i])."</option>\n";
+ }
+ } else {
+ for ($i=$ref_start; $i<(1+$ref_end); $i++) {
+ echo $intend;
+ echo "\t\t<option value=\"".$i."\"";
+ if ($i == $ref_int_preselect) {
+ echo " selected";
+ }
+ echo ">".$i."</option>\n";
+ }
+ }
+
+ echo $intend."\t";
+ echo "</select>\n";
+
+ if ($ref_p_flag) {
+ echo $intend;
+ echo "</p>\n";
+ }
+}
+
+
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("gui/gui_functions_select.php");
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+function debugPrint($param) {
+ echo "<p>";
+ if (is_array($param)) {
+ if ($asList) {
+ debugPrintAsList($param);
+ } else {
+ echo "_";
+ foreach ($param as $p) {
+ echo $p."_";
+ }
+ }
+ } else {
+ echo $param;
+ }
+ echo "</p>\n";
+}
+
+function debugPrintAsList($param) {
+ echo "<ol>\n";
+ foreach ($param as $p) {
+ echo "<li>".$p."_</li>\n";
+ }
+ echo "</ol>\n";
+}
+
+function coordinates ($ref_longitude, $ref_latitude) {
+ $return_geo = array("","");
+
+ $return_geo[0] = $ref_longitude[0] + $ref_longitude[1]/60 + $ref_longitude[2]/3600;
+ $return_geo[1] = $ref_latitude[0] + $ref_latitude[1]/60 + $ref_latitude[2]/3600;
+
+ return $return_geo;
+}
+
+function find_pos_in_array($ref_array, $ref_value) {
+ $pos = -1;
+
+ for ($i=0; $i<count($ref_array); $i++) {
+ if ($ref_array[$i] == $ref_value) {
+ $pos = $i;
+ }
+ }
+
+ return $pos;
+}
+
+function make_intend($ref_count) {
+ for ($i=0; $i<$ref_count; $i++) {
+ echo "\t";
+ }
+}
+
+function make_intend_str($ref_count) {
+ $intend = "";
+ for ($i=0; $i<$ref_count; $i++) {
+ $intend .= "\t";
+ }
+ return $intend;
+}
+
+
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+require ("util/util_functions.php");
+
+
+?>
\ No newline at end of file
--- /dev/null
+
+BODY {
+ font-size: 100.01%;
+ font-family: Verdana, sans-serif;
+ padding: 0;
+ margin: 0;
+}
+
+TABLE, TH, TD {
+ border: none;
+}
+
+TH, TD {
+ padding: 5px;
+ text-align: right;
+}
+
+H1 {
+ font-size: 1.5em;
+ margin: 0 0 0.5em 1em;
+ color: rgb(0, 121, 138);
+}
+
+H2 {
+ font-size: 1.25em;
+ margin: 1em 0 0.5em 1em;
+ color: rgb(0, 121, 138);
+}
+
+P {
+ margin: 0 2em;
+}
+
+P.cta,
+P.cta A {
+ margin: 0 2em;
+ color: rgb(166, 12, 36);
+ font-weight: 600;
+}
+
+FORM, SELECT, OPTION {
+ font-size: 1.150em;
+}
+
+SELECT, OPTION {
+ background-color: rgb(243, 173, 0);
+}
+
+FORM {
+ margin: 0 2em;
+ background-color: rgb(173, 218, 213);
+}
+
+LEGEND {
+ font-weight: bold;
+}
+
+.factors-container {
+ display: flex;
+ gap: 1rem;
+ margin: 0 2em;
+ margin-top: 1rem;
+ /*--font-size: 250%;*/
+}
+
+.factors-container div {
+ flex: 1;
+ padding: 1rem;
+ border: 1px solid #000;
+ background-color: rgb(226, 239, 243);
+}
+
+/* Mobile: Untereinander */
+@media (max-width: 480px) {
+ .factors-container {
+ flex-direction: column;
+ gap: 1rem;
+ }
+}
+
+#results,
+#result {
+ border: 1px solid #000;
+ background-color: rgb(226, 239, 243);
+ margin-top: 1rem;
+}
+
+.highlight {
+ background-color: yellow;
+ font-weight: bold;
+}
+
+FOOTER {
+ margin: 1rem 0 1em 1em;
+}
+
+A {
+ color: #000;
+}
+
+@keyframes pulse {
+ 0% { transform: scale(1); }
+ 50% { transform: scale(1.05); }
+ 100% { transform: scale(1); }
+}