Verbands-Lehrgangswächter

Zeigt eine Liste aller verfügbaren Lehrgänge an und zeigt an, wie viele Lehrgänge hierzu offen sind.

// ==UserScript==
// @name        Verbands-Lehrgangswächter
// @namespace   lukas2013.leitstellenspiel.de
// @version     2024.09.09_10
// @license     BSD-3-Clause
// @author      lukas2013
// @description Zeigt eine Liste aller verfügbaren Lehrgänge an und zeigt an, wie viele Lehrgänge hierzu offen sind.
// @match       https://www.leitstellenspiel.de/schoolings*
// @match       https://polizei.leitstellenspiel.de/schoolings*
// @icon        https://www.leitstellenspiel.de/favicon.ico
// @run-at      document-idle
// @grant       none
// ==/UserScript==

(function () {
    const predefinedSchoolings = [
        // Feuerwehr
        "Feuerwehr - GW-Messtechnik Lehrgang",
        "Feuerwehr - GW-Gefahrgut Lehrgang",
        "Feuerwehr - Höhenrettung Lehrgang",
        "Feuerwehr - ELW 2 Lehrgang",
        "Feuerwehr - Wechsellader Lehrgang",
        "Feuerwehr - Dekon-P Lehrgang",
        "Feuerwehr - Feuerwehrkran Lehrgang",
        "Feuerwehr - GW-Wasserrettung Lehrgang",
        "Feuerwehr - GW-Taucher Lehrgang",
        "Feuerwehr - Notarzt-Ausbildung",
        "Feuerwehr - Flugfeldlöschfahrzeug-Ausbildung",
        "Feuerwehr - Rettungstreppen-Ausbildung",
        "Feuerwehr - Werkfeuerwehr-Ausbildung",
        "Feuerwehr - Intensivpflege",
        "Feuerwehr - NEA200 Fortbildung",
        "Feuerwehr - Drohnen-Schulung",
        "Feuerwehr - Feuerwehr-Verpflegungseinheit",
        "Feuerwehr - Verpflegungshelfer",
        // Polizei
        "Polizei - Zugführer (leBefKw)",
        "Polizei - Hundertschaftsführer (FüKW)",
        "Polizei - Polizeihubschrauber",
        "Polizei - Wasserwerfer",
        "Polizei - SEK",
        "Polizei - MEK",
        "Polizei - Hundeführer (Schutzhund)",
        "Polizei - Motorradstaffel",
        "Polizei - Brandbekämpfung",
        "Polizei - Kriminalpolizei",
        "Polizei - Dienstgruppenleitung",
        "Polizei - Reiterstaffel",
        "Polizei - Windenoperator",
        // Rettungsdienst
        "Rettungsdienst - Notarzt-Ausbildung",
        "Rettungsdienst - LNA-Ausbildung",
        "Rettungsdienst - OrgL-Ausbildung",
        "Rettungsdienst - SEG - Einsatzleitung",
        "Rettungsdienst - SEG - GW-San",
        "Rettungsdienst - GW-Wasserrettung Lehrgang",
        "Rettungsdienst - GW-Taucher Lehrgang",
        "Rettungsdienst - Rettungshundeführer",
        "Rettungsdienst - Intensivpflege",
        "Rettungsdienst - Drohnenoperator",
        "Rettungsdienst - Betreuungsdienst",
        "Rettungsdienst - Verpflegungshelfer",
        "Rettungsdienst - Höhenretter",
        "Rettungsdienst - Windenoperator",
        "Rettungsdienst - Einsatzleiter Bergrettung",
        // THW
        "THW - Zugtrupp",
        "THW - Fachgruppe Räumen",
        "THW - Fachgruppe Wassergefahren",
        "THW - Fachgruppe Bergungstaucher",
        "THW - Fachgruppe Rettungshundeführer",
        "THW - Fachgruppe Wasserschaden/Pumpen",
        "THW - Fachgruppe Schwere Bergung",
        "THW - Fachgruppe Elektroversorgung",
        "THW - Trupp Unbemannte Luftfahrtsysteme",
        "THW - Fachzug Führung und Kommunikation"
    ];

    function logDebug(message, data) {
        console.log("[DEBUG] " + message, data);
    }

    function getSchoolingsFromTable() {
        const schoolings = {};
        const table = document.getElementById("schooling_opened_table");

        if (table) {
            const rows = table.querySelectorAll("tbody tr");

            rows.forEach(row => {
                const nameCell = row.querySelector("td:nth-child(1) a");
                const availableCell = row.querySelector("td:nth-child(2)");

                if (nameCell && availableCell) {
                    const name = nameCell.textContent.trim();
                    const available = parseInt(availableCell.textContent.trim(), 10);

                    // Wenn der Lehrgang schon existiert, füge die Anzahl verfügbarer Plätze hinzu
                    if (!schoolings[name]) {
                        schoolings[name] = { count: 0, totalAvailable: 0 };
                    }
                    schoolings[name].count += 1;
                    schoolings[name].totalAvailable += available;

                    logDebug("Lehrgang gefunden: ", { name, available });
                }
            });
        } else {
            logDebug("Tabelle nicht gefunden", null);
        }

        logDebug("Parsed Schoolings", schoolings);
        return schoolings;
    }

    function createTable(schoolings) {
        logDebug("Erstelle Tabelle mit folgenden Lehrgängen: ", schoolings);
        const table = document.createElement("table");
        table.style.width = "100%";
        table.style.borderCollapse = "collapse";

        // Kopfzeile erstellen
        const header = table.createTHead();
        const headerRow = header.insertRow();
        const nameHeader = document.createElement("th");
        nameHeader.innerText = "Lehrgang";
        nameHeader.style.border = "1px solid black";
        nameHeader.style.padding = "2px";
        const availableHeader = document.createElement("th");
        availableHeader.innerText = "Offene Lehrgänge (Verfügbare Plätze)";
        availableHeader.style.border = "1px solid black";
        availableHeader.style.padding = "2px";
        headerRow.appendChild(nameHeader);
        headerRow.appendChild(availableHeader);

        // Tabellenkörper erstellen und Daten hinzufügen
        const tbody = table.createTBody();

        // Kombiniere die dynamisch gefundenen und vordefinierten Lehrgänge, ohne doppelte Einträge
        const allSchoolings = { ...schoolings };
        predefinedSchoolings.forEach(schooling => {
            if (!allSchoolings[schooling]) {
                allSchoolings[schooling] = { count: 0, totalAvailable: 0 };
            }
        });

        // Sortiere die kombinierten Lehrgänge alphabetisch
        const sortedSchoolings = Object.keys(allSchoolings).sort();

        // Iteriere über alle kombinierten Lehrgänge und füge diese hinzu
        sortedSchoolings.forEach(schooling => {
            const row = tbody.insertRow();
            const nameCell = row.insertCell();
            nameCell.innerText = schooling;
            nameCell.style.border = "1px solid black";
            nameCell.style.padding = "2px";

            const availableCell = row.insertCell();
            const { count, totalAvailable } = allSchoolings[schooling];
            availableCell.innerHTML = `${count} (${totalAvailable})`;
            availableCell.style.border = "1px solid black";
            availableCell.style.padding = "2px";

            // Wenn der Lehrgang keine offenen Lehrgänge hat, färbe die Zeile gelb und mache die Zahl fett
            if (count === 0 && totalAvailable === 0) {
                row.style.backgroundColor = "lightyellow";
                availableCell.innerHTML = `<strong>${count} (${totalAvailable})</strong>`;
                logDebug(`Lehrgang "${schooling}" hat keine offenen Lehrgänge und wird gelb eingefärbt.`, null);
            } else if (count < 4) {
                row.style.backgroundColor = "#ddd199";
                logDebug(`Lehrgang "${schooling}" hat weniger als 4 offene Lehrgänge und wird in #ddd199 eingefärbt.`, null);
            } else if (!predefinedSchoolings.includes(schooling)) {
                row.style.backgroundColor = "red";
                logDebug(`Lehrgang "${schooling}" ist nicht in den vordefinierten Lehrgängen enthalten und wird rot eingefärbt.`, null);
            }
        });

        return table;
    }

    function addStats() {
        logDebug("Starte das Hinzufügen der Statistiken...", null);
        const statsDiv = document.createElement("div");
        statsDiv.id = "schooling-stats";

        // Holen der Daten aus der Tabelle
        const schoolings = getSchoolingsFromTable();

        // Erstellen der Tabelle mit den Lehrgangsinformationen
        const table = createTable(schoolings);
        statsDiv.appendChild(table);

        const clearDiv = document.querySelector("div.clear");
        if (clearDiv) {
            // Tabelle nach dem "clear"-Div einfügen
            clearDiv.parentNode.insertBefore(statsDiv, clearDiv.nextSibling);
            logDebug("Statistik nach dem clear-Element eingefügt.", statsDiv);
        } else {
            logDebug("clear-Element nicht gefunden", null);
            const container = document.getElementById("iframe-inside-container");
            if (container) {
                container.insertBefore(statsDiv, container.firstChild);
                logDebug("Statistik wurde dem Container hinzugefügt.", statsDiv);
            } else {
                logDebug("Container nicht gefunden", null);
            }
        }
    }

    function main() {
        logDebug("Skript gestartet", null);
        addStats();
    }

    main();
})();