"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynDaten = exports.KursblockungDynDaten = void 0;
const JavaObject_1 = require("../../java/lang/JavaObject");
const KursblockungDynFachart_1 = require("../../core/kursblockung/KursblockungDynFachart");
const HashMap_1 = require("../../java/util/HashMap");
const KursblockungDynSchiene_1 = require("../../core/kursblockung/KursblockungDynSchiene");
const KursblockungDynKurs_1 = require("../../core/kursblockung/KursblockungDynKurs");
const LogLevel_1 = require("../../logger/LogLevel");
const NullPointerException_1 = require("../../java/lang/NullPointerException");
const HashSet_1 = require("../../java/util/HashSet");
const KursblockungDynStatistik_1 = require("../../core/kursblockung/KursblockungDynStatistik");
const LinkedCollection_1 = require("../../core/adt/collection/LinkedCollection");
const KursblockungOutput_1 = require("../../core/data/kursblockung/KursblockungOutput");
const KursblockungDynSchueler_1 = require("../../core/kursblockung/KursblockungDynSchueler");
class KursblockungDynDaten extends JavaObject_1.JavaObject {
    logger;
    regelMap;
    maxTimeMillis = 0;
    schienenArr;
    kursArr;
    kursArrFrei;
    kursMap;
    fachartArr;
    fachartMap;
    schuelerArr;
    schuelerMap;
    statistik;
    /**
     * Der Konstruktor der Klasse liest alle Daten von {@link KursblockungInput} ein
     * und baut die relevanten Datenstrukturen auf.
     *
     * @param pLogger Logger für Benutzerhinweise, Warnungen und Fehler.
     * @param pInput  Die Eingabedaten (Schnittstelle zur GUI).
     */
    constructor(pLogger, pInput) {
        super();
        this.logger = pLogger;
        this.regelMap = new HashMap_1.HashMap();
        this.maxTimeMillis = pInput.maxTimeMillis;
        this.schienenArr = Array(0).fill(null);
        this.kursArr = Array(0).fill(null);
        this.kursArrFrei = Array(0).fill(null);
        this.kursMap = new HashMap_1.HashMap();
        this.fachartArr = Array(0).fill(null);
        this.fachartMap = new HashMap_1.HashMap();
        this.schuelerArr = Array(0).fill(null);
        this.schuelerMap = new HashMap_1.HashMap();
        this.statistik = new KursblockungDynStatistik_1.KursblockungDynStatistik();
        if (this.schritt01FehlerBeiReferenzen(pInput)) {
            return;
        }
        if (this.schritt02FehlerBeiRegelGruppierung(pInput.regeln)) {
            return;
        }
        if (this.schritt03FehlerBeiFachartenErstellung(pInput)) {
            return;
        }
        if (this.schritt04FehlerBeiSchuelerErstellung(pInput)) {
            return;
        }
        if (this.schritt05FehlerBeiSchuelerFachwahlenErstellung(pInput.fachwahlen, this.schuelerArr)) {
            return;
        }
        if (this.schritt06FehlerBeiStatistikErstellung(this.fachartArr, this.schuelerArr)) {
            return;
        }
        if (this.schritt07FehlerBeiSchienenErzeugung(pInput.maxSchienen)) {
            return;
        }
        if (this.schritt08FehlerBeiKursErstellung(pInput)) {
            return;
        }
        if (this.schritt09FehlerBeiKursFreiErstellung(pInput)) {
            return;
        }
        if (this.schritt10FehlerBeiFachartKursArrayErstellung(pInput)) {
            return;
        }
    }
    /**
     * Überprüft alle Referenzen in {@link KursblockungInput} und auch die
     * referentielle Integrität.
     *
     * @param pInput Das {@link KursblockungInput}-Objekt von der GUI.
     * @return {@code true}, falls kein Fehler gefunden wurde.
     */
    schritt01FehlerBeiReferenzen(pInput) {
        if (pInput === null) {
            this.fehler("KursblockungInput == null");
            return true;
        }
        if (pInput.fachwahlen === null) {
            this.fehler("KursblockungInput.fachwahlen == null");
            return true;
        }
        if (pInput.fachwahlen.size() === 0) {
            this.fehler("Die Blockung hat 0 Fachwahlen.");
            return true;
        }
        for (let i = 0; i < pInput.fachwahlen.size(); i++) {
            if (pInput.fachwahlen.get(i) === null) {
                this.fehler("KursblockungInput.fachwahlen.get(" + i + ") == null");
                return true;
            }
        }
        if (pInput.faecher === null) {
            this.fehler("KursblockungInput.faecher == null");
            return true;
        }
        if (pInput.faecher.size() === 0) {
            this.fehler("Die Blockung hat 0 Fächer.");
            return true;
        }
        let setFaecher = new HashSet_1.HashSet();
        for (let i = 0; i < pInput.faecher.size(); i++) {
            let iFach = pInput.faecher.get(i);
            if (iFach === null) {
                this.fehler("KursblockungInput.faecher.get(" + i + ") == null");
                return true;
            }
            setFaecher.add(iFach.id);
        }
        if (pInput.kursarten === null) {
            this.fehler("KursblockungInput.kursarten == null");
            return true;
        }
        if (pInput.kursarten.size() === 0) {
            this.fehler("Die Blockung hat 0 Kursarten.");
            return true;
        }
        let setKursarten = new HashSet_1.HashSet();
        for (let i = 0; i < pInput.kursarten.size(); i++) {
            let iKursart = pInput.kursarten.get(i);
            if (iKursart === null) {
                this.fehler("KursblockungInput.kursarten.get(" + i + ") == null");
                return true;
            }
            setKursarten.add(iKursart.id);
        }
        if (pInput.kurse === null) {
            this.fehler("KursblockungInput.kurse == null");
            return true;
        }
        if (pInput.kurse.size() === 0) {
            this.fehler("Die Blockung hat 0 Kurse.");
            return true;
        }
        let setKurse = new HashSet_1.HashSet();
        for (let i = 0; i < pInput.kurse.size(); i++) {
            let iKurs = pInput.kurse.get(i);
            if (iKurs === null) {
                this.fehler("KursblockungInput.kurse.get(" + i + ") == null");
                return true;
            }
            setKurse.add(iKurs.id);
        }
        if (pInput.regeln === null) {
            this.fehler("KursblockungInput.regeln == null");
            return true;
        }
        for (let i = 0; i < pInput.regeln.size(); i++) {
            if (pInput.regeln.get(i) === null) {
                this.fehler("KursblockungInput.regeln.get(" + i + ") == null");
                return true;
            }
            if (pInput.regeln.get(i).daten === null) {
                this.fehler("KursblockungInput.regeln.get(" + i + ").daten == null");
                return true;
            }
        }
        if (pInput.schueler === null) {
            this.fehler("KursblockungInput.schueler == null");
            return true;
        }
        if (pInput.schueler.size() === 0) {
            this.fehler("Die Blockung hat 0 Schüler.");
            return true;
        }
        let setSchueler = new HashSet_1.HashSet();
        for (let i = 0; i < pInput.schueler.size(); i++) {
            let schueler = pInput.schueler.get(i);
            if (schueler === null) {
                this.fehler("KursblockungInput.schueler.get(" + i + ") == null");
                return true;
            }
            setSchueler.add(schueler.id);
        }
        if (pInput.input < 0) {
            this.fehler("KursblockungInput.input < 0, das ist bei einer Datenbank-ID unüblich.");
            return true;
        }
        for (let i = 0; i < pInput.fachwahlen.size(); i++) {
            let iFachwahl = pInput.fachwahlen.get(i);
            let schuelerID = iFachwahl.schueler;
            if (!setSchueler.contains(schuelerID)) {
                this.fehler("KursblockungInput.fachwahlen.get(" + i + ") referenziert Schüler-ID (" + schuelerID + "), die zuvor nicht definiert wurde.");
                return true;
            }
            let fachID = iFachwahl.fach;
            if (!setFaecher.contains(fachID)) {
                this.fehler("KursblockungInput.fachwahlen.get(" + i + ") referenziert Fach-ID (" + fachID + "), die zuvor nicht definiert wurde.");
                return true;
            }
            let kursartID = iFachwahl.kursart;
            if (!setKursarten.contains(kursartID)) {
                this.fehler("KursblockungInput.fachwahlen.get(" + i + ") referenziert Kursart-ID (" + kursartID + "), die zuvor nicht definiert wurde.");
                return true;
            }
        }
        for (let i = 0; i < pInput.kurse.size(); i++) {
            let iKurs = pInput.kurse.get(i);
            let fachID = iKurs.fach;
            if (!setFaecher.contains(fachID)) {
                this.fehler("KursblockungInput.kurse.get(" + i + ") referenziert Fach-ID (" + fachID + "), die zuvor nicht definiert wurde.");
                return true;
            }
            let kursartID = iKurs.kursart;
            if (!setKursarten.contains(kursartID)) {
                this.fehler("KursblockungInput.kurse.get(" + i + ") referenziert Kursart-ID (" + kursartID + "), die zuvor nicht definiert wurde.");
                return true;
            }
        }
        for (let i = 0; i < pInput.regeln.size(); i++) {
            let iRegel = pInput.regeln.get(i);
            let regelID = iRegel.id;
            if ((regelID < 1) || (regelID > 3)) {
                this.fehler("KursblockungInput.regeln.get(" + i + ") hat unbekannte Regel-ID (" + regelID + ").");
                return true;
            }
            if (regelID === 1) {
                let kursartID = iRegel.daten[0].valueOf();
                if (!setKursarten.contains(kursartID)) {
                    this.fehler("KursblockungInput.regeln.get(" + i + ") mit regel.id (" + regelID + ") referenziert unbekannte Kursart-ID (" + kursartID + ").");
                    return true;
                }
                let von = iRegel.daten[1].valueOf();
                let bis = iRegel.daten[2].valueOf();
                if (!((von >= 0) && (von <= bis) && (bis < pInput.maxSchienen))) {
                    this.fehler("KursblockungInput.regeln.get(" + i + ") mit regel.id (" + regelID + ") Schiene \'von\' (" + von + ") \'bis\' (" + bis + ") nicht logisch.");
                    return true;
                }
            }
            if (regelID === 2) {
                let kursID = iRegel.daten[0].valueOf();
                if (!setKurse.contains(kursID)) {
                    this.fehler("KursblockungInput.regeln.get(" + i + ") mit regel.id (" + regelID + ") referenziert unbekannte Kurs-ID (" + kursID + ").");
                    return true;
                }
            }
            if (regelID === 3) {
                let kursID = iRegel.daten[0].valueOf();
                if (!setKurse.contains(kursID)) {
                    this.fehler("KursblockungInput.regeln.get(" + i + ") mit regel.id (" + regelID + ") referenziert unbekannte Kurs-ID (" + kursID + ").");
                    return true;
                }
            }
        }
        return false;
    }
    schritt02FehlerBeiRegelGruppierung(vRegeln) {
        for (let i = 0; i < vRegeln.size(); i++) {
            let regel = vRegeln.get(i);
            let regelID = regel.id;
            let list = this.regelMap.get(regelID);
            if (list === null) {
                list = new LinkedCollection_1.LinkedCollection();
                this.regelMap.put(regelID, list);
            }
            list.addLast(regel);
        }
        return false;
    }
    schritt03FehlerBeiFachartenErstellung(pInput) {
        let mapFach = new HashMap_1.HashMap();
        for (let iFach of pInput.faecher) {
            mapFach.put(iFach.id, iFach.representation);
        }
        let mapKursart = new HashMap_1.HashMap();
        for (let iKursart of pInput.kursarten) {
            mapKursart.put(iKursart.id, iKursart.representation);
        }
        let mapSchueler = new HashMap_1.HashMap();
        for (let iSchueler of pInput.schueler) {
            mapSchueler.put(iSchueler.id, iSchueler.representation);
        }
        let nFacharten = 0;
        let nKurse = pInput.kurse.size();
        for (let i = 0; i < nKurse; i++) {
            let iKurs = pInput.kurse.get(i);
            let fachID = iKurs.fach;
            let kursartID = iKurs.kursart;
            let kursartMap = this.fachartMap.get(fachID);
            if (kursartMap === null) {
                kursartMap = new HashMap_1.HashMap();
                this.fachartMap.put(fachID, kursartMap);
            }
            let dynFachart = kursartMap.get(kursartID);
            if (dynFachart === null) {
                let strFach = mapFach.get(fachID);
                let strKursart = mapKursart.get(kursartID);
                if ((strFach === null) || (strKursart === null))
                    throw new NullPointerException_1.NullPointerException();
                let representation = strFach.valueOf() + ";" + strKursart.valueOf();
                dynFachart = new KursblockungDynFachart_1.KursblockungDynFachart(nFacharten, representation, this.statistik);
                kursartMap.put(kursartID, dynFachart);
                nFacharten++;
            }
            dynFachart.aktionMaxKurseErhoehen();
        }
        for (let i = 0; i < pInput.fachwahlen.size(); i++) {
            let iFachwahl = pInput.fachwahlen.get(i);
            let schuelerID = iFachwahl.schueler;
            let fachID = iFachwahl.fach;
            let kursartID = iFachwahl.kursart;
            let kursartMap = this.fachartMap.get(fachID);
            if (kursartMap === null) {
                kursartMap = new HashMap_1.HashMap();
                this.fachartMap.put(fachID, kursartMap);
            }
            let dynFachart = kursartMap.get(kursartID);
            if (dynFachart === null) {
                let strFach = mapFach.get(fachID);
                let strKursart = mapKursart.get(kursartID);
                let strSchueler = mapSchueler.get(schuelerID);
                if ((strFach === null) || (strKursart === null) || (strSchueler === null))
                    throw new NullPointerException_1.NullPointerException();
                let representation = strFach.valueOf() + ";" + strKursart.valueOf();
                dynFachart = new KursblockungDynFachart_1.KursblockungDynFachart(nFacharten, representation, this.statistik);
                kursartMap.put(kursartID, dynFachart);
                nFacharten++;
                this.logger.logLn(LogLevel_1.LogLevel.APP, "Schüler " + strSchueler.valueOf() + " wählt \'" + representation.valueOf() + "\', ohne das ein Kurs existiert!");
            }
            dynFachart.aktionMaxSchuelerErhoehen();
        }
        if (nFacharten === 0) {
            this.fehler("Die Blockung hat 0 Facharten.");
            return true;
        }
        this.fachartArr = Array(nFacharten).fill(null);
        for (let map of this.fachartMap.values()) {
            for (let fachart of map.values()) {
                this.fachartArr[fachart.gibNr()] = fachart;
            }
        }
        let kursSumme = 0;
        for (let i = 0; i < this.fachartArr.length; i++) {
            kursSumme += this.fachartArr[i].gibKurseMax();
        }
        if (kursSumme !== nKurse) {
            this.fehler("Summe aller auf die Facharten verteilten Kurse ist ungleich der Gesamtkursanzahl.");
            return true;
        }
        return false;
    }
    schritt04FehlerBeiSchuelerErstellung(pInput) {
        let vSchueler = pInput.schueler;
        let nSchueler = vSchueler.size();
        this.schuelerArr = Array(nSchueler).fill(null);
        for (let i = 0; i < nSchueler; i++) {
            let iSchueler = vSchueler.get(i);
            let schueler = new KursblockungDynSchueler_1.KursblockungDynSchueler(iSchueler, this.statistik, pInput.maxSchienen);
            this.schuelerArr[i] = schueler;
            this.schuelerMap.put(iSchueler.id, schueler);
        }
        return false;
    }
    schritt05FehlerBeiSchuelerFachwahlenErstellung(vFachwahlen, susArr) {
        let mapSchuelerFA = new HashMap_1.HashMap();
        let mapSchuelerID = new HashMap_1.HashMap();
        for (let i = 0; i < susArr.length; i++) {
            mapSchuelerFA.put(susArr[i], new LinkedCollection_1.LinkedCollection());
            mapSchuelerID.put(susArr[i], new LinkedCollection_1.LinkedCollection());
        }
        let nFachwahlen = vFachwahlen.size();
        for (let i = 0; i < nFachwahlen; i++) {
            let iFachwahl = vFachwahlen.get(i);
            let susID = iFachwahl.schueler;
            let fachID = iFachwahl.fach;
            let kursartID = iFachwahl.kursart;
            let schueler = this.schuelerMap.get(susID);
            let kursartMap = this.fachartMap.get(fachID);
            let dynFachart = kursartMap === null ? null : kursartMap.get(kursartID);
            let dynFacharten = mapSchuelerFA.get(schueler);
            if (dynFacharten === null)
                throw new NullPointerException_1.NullPointerException();
            dynFacharten.addLast(dynFachart);
            let fachwahlIDs = mapSchuelerID.get(schueler);
            if (fachwahlIDs === null)
                throw new NullPointerException_1.NullPointerException();
            fachwahlIDs.addLast(iFachwahl.id);
        }
        for (let nr = 0; nr < susArr.length; nr++) {
            let schueler = susArr[nr];
            let listFA = mapSchuelerFA.get(schueler);
            let listID = mapSchuelerID.get(schueler);
            if ((listFA === null) || (listID === null))
                throw new NullPointerException_1.NullPointerException();
            let nWahlen = listFA.size();
            let arrFA = Array(nWahlen).fill(null);
            let arrID = Array(nWahlen).fill(0);
            for (let i = 0; i < nWahlen; i++) {
                arrFA[i] = listFA.removeFirst();
                arrID[i] = listID.removeFirst().valueOf();
            }
            schueler.aktionSetzeFachartenUndIDs(arrFA, arrID);
        }
        return false;
    }
    schritt06FehlerBeiStatistikErstellung(fachartArr, susArr) {
        let nFacharten = fachartArr.length;
        let bewertungMatrixFachart = [...Array(nFacharten)].map(e => Array(nFacharten).fill(0));
        for (let i = 0; i < susArr.length; i++) {
            let fa = susArr[i].gibFacharten();
            for (let i1 = 0; i1 < fa.length; i1++) {
                let nr1 = fa[i1].gibNr();
                for (let i2 = i1 + 1; i2 < fa.length; i2++) {
                    let nr2 = fa[i2].gibNr();
                    bewertungMatrixFachart[nr1][nr2]++;
                    bewertungMatrixFachart[nr2][nr1]++;
                }
            }
        }
        for (let i1 = 0; i1 < nFacharten; i1++) {
            let kursAnz1 = fachartArr[i1].gibKurseMax();
            let nr1 = fachartArr[i1].gibNr();
            for (let i2 = 0; i2 < nFacharten; i2++) {
                let kursAnz2 = fachartArr[i2].gibKurseMax();
                let nr2 = fachartArr[i2].gibNr();
                if ((kursAnz1 === 0) || (kursAnz2 === 0)) {
                    bewertungMatrixFachart[nr1][nr2] = 0;
                }
                else {
                    let faktor = Math.trunc(1000 / (kursAnz1 + kursAnz2 - 1));
                    bewertungMatrixFachart[nr1][nr2] *= faktor;
                }
            }
            bewertungMatrixFachart[nr1][nr1] += 100000;
        }
        this.statistik.aktionInitialisiere(bewertungMatrixFachart, susArr.length, fachartArr.length);
        return false;
    }
    schritt07FehlerBeiSchienenErzeugung(pSchienen) {
        this.schienenArr = Array(pSchienen).fill(null);
        for (let nr = 0; nr < pSchienen; nr++) {
            this.schienenArr[nr] = new KursblockungDynSchiene_1.KursblockungDynSchiene(this.logger, nr, this.statistik);
        }
        return false;
    }
    schritt08FehlerBeiKursErstellung(pInput) {
        let vKurse = pInput.kurse;
        let nKurse = vKurse.size();
        let nSchienen = this.schienenArr.length;
        let mapKursSchieneFrei = new HashMap_1.HashMap();
        let mapKursSchieneLage = new HashMap_1.HashMap();
        for (let i = 0; i < nKurse; i++) {
            let kursID = vKurse.get(i).id;
            let schieneFrei = new LinkedCollection_1.LinkedCollection();
            mapKursSchieneLage.put(kursID, new LinkedCollection_1.LinkedCollection());
            mapKursSchieneFrei.put(kursID, schieneFrei);
            let perm = Array(nSchienen).fill(0);
            for (let j = 0; j < nSchienen; j++) {
                perm[j] = j;
            }
            for (let j1 = 0; j1 < nSchienen; j1++) {
                let j2 = (Math.random() * nSchienen);
                let s1 = perm[j1];
                let s2 = perm[j2];
                perm[j1] = s2;
                perm[j2] = s1;
            }
            for (let j = 0; j < nSchienen; j++) {
                schieneFrei.addLast(this.schienenArr[perm[j]]);
            }
        }
        let regelID1 = 1;
        let regelnTyp1 = this.regelMap.get(regelID1);
        if (regelnTyp1 !== null) {
            for (let regel1 of regelnTyp1) {
                let kursart = regel1.daten[0].valueOf();
                let von = regel1.daten[1].valueOf();
                let bis = regel1.daten[2].valueOf();
                for (let i = 0; i < pInput.kurse.size(); i++) {
                    let kurs = pInput.kurse.get(i);
                    if (kurs.kursart === kursart) {
                        for (let schiene = von; schiene <= bis; schiene++) {
                            let schieneFrei = mapKursSchieneFrei.get(kurs.id);
                            if (schieneFrei === null)
                                throw new NullPointerException_1.NullPointerException();
                            schieneFrei.remove(this.schienenArr[schiene]);
                        }
                    }
                }
            }
        }
        let regelID3 = 3;
        let regelnTyp3 = this.regelMap.get(regelID3);
        if (regelnTyp3 !== null) {
            for (let regel3 of regelnTyp3) {
                let kursID = regel3.daten[0].valueOf();
                let schiene = regel3.daten[1].valueOf();
                let schieneFrei = mapKursSchieneFrei.get(kursID);
                if (schieneFrei === null)
                    throw new NullPointerException_1.NullPointerException();
                schieneFrei.remove(this.schienenArr[schiene]);
            }
        }
        let regelID2 = 2;
        let regelnTyp2 = this.regelMap.get(regelID2);
        if (regelnTyp2 !== null) {
            for (let regel2 of regelnTyp2) {
                let kursID = regel2.daten[0].valueOf();
                let schiene = regel2.daten[1].valueOf();
                let schieneFrei = mapKursSchieneFrei.get(kursID);
                let schieneLage = mapKursSchieneLage.get(kursID);
                if ((schieneFrei === null) || (schieneLage === null))
                    throw new NullPointerException_1.NullPointerException();
                if (schieneLage.contains(this.schienenArr[schiene])) {
                    continue;
                }
                if (!schieneFrei.contains(this.schienenArr[schiene])) {
                    let kurs = this.kursMap.get(kursID);
                    if (kurs === null)
                        throw new NullPointerException_1.NullPointerException();
                    this.fehler("Regel 2: Kurs (" + kurs.gibRepresentation().valueOf() + ") Schiene (" + schiene + ") fixieren, sie ist aber bereits gesperrt.");
                    return true;
                }
                schieneFrei.remove(this.schienenArr[schiene]);
                schieneLage.addLast(this.schienenArr[schiene]);
            }
        }
        this.kursArr = Array(nKurse).fill(null);
        for (let i = 0; i < nKurse; i++) {
            let iKurs = vKurse.get(i);
            let representation = iKurs.representation;
            let fach = iKurs.fach;
            let kursart = iKurs.kursart;
            let schienen = iKurs.schienen;
            if (schienen <= 0) {
                this.logger.logLn(LogLevel_1.LogLevel.ERROR, "Kurs \'" + representation.valueOf() + "\' belegt nur " + schienen + " Schienen, das ist zu wenig.");
                return true;
            }
            if (schienen > this.schienenArr.length) {
                this.logger.logLn(LogLevel_1.LogLevel.ERROR, "Es gibt " + this.schienenArr.length + " Schienen, aber der Kurs \'" + representation.valueOf() + "\' möchte " + schienen + " Schienen belegt.");
                return true;
            }
            let listLage = mapKursSchieneLage.get(iKurs.id);
            if (listLage === null)
                throw new NullPointerException_1.NullPointerException();
            let pSchienenLageFixiert = listLage.size();
            if (pSchienenLageFixiert > iKurs.schienen) {
                this.logger.logLn(LogLevel_1.LogLevel.ERROR, "Kurs \'" + representation.valueOf() + "\' fixert " + pSchienenLageFixiert + " Schienen, das ist mehr als seine Schienenanzahl " + iKurs.schienen + " .");
                return true;
            }
            let listFrei = mapKursSchieneFrei.get(iKurs.id);
            if (listFrei === null)
                throw new NullPointerException_1.NullPointerException();
            while (listLage.size() < iKurs.schienen) {
                if (listFrei.isEmpty()) {
                    this.logger.logLn(LogLevel_1.LogLevel.ERROR, "Kurs \'" + representation.valueOf() + "\' hat zu viele Schienen gesperrt, so dass seine seine Schienenanzahl keinen Platz mehr hat .");
                    return true;
                }
                listLage.addLast(listFrei.pollFirst());
            }
            let pSchienenLage = Array(listLage.size()).fill(null);
            for (let j = 0; j < pSchienenLage.length; j++) {
                pSchienenLage[j] = listLage.removeFirst();
            }
            let pSchienenFrei = Array(listFrei.size()).fill(null);
            for (let j = 0; j < pSchienenFrei.length; j++) {
                pSchienenFrei[j] = listFrei.removeFirst();
            }
            let kursartMap = this.fachartMap.get(fach);
            let dynFachart = kursartMap === null ? null : kursartMap.get(kursart);
            if (dynFachart === null)
                throw new NullPointerException_1.NullPointerException();
            let kurs = new KursblockungDynKurs_1.KursblockungDynKurs(pSchienenLage, pSchienenLageFixiert, pSchienenFrei, iKurs, dynFachart, this.logger);
            this.kursArr[i] = kurs;
            this.kursMap.put(iKurs.id, kurs);
        }
        return false;
    }
    schritt09FehlerBeiKursFreiErstellung(pInput) {
        let nKursFrei = 0;
        for (let i = 0; i < this.kursArr.length; i++) {
            if (this.kursArr[i].gibHatFreiheitsgrade()) {
                nKursFrei++;
            }
        }
        this.kursArrFrei = Array(nKursFrei).fill(null);
        for (let i = 0, j = 0; i < this.kursArr.length; i++) {
            if (this.kursArr[i].gibHatFreiheitsgrade()) {
                this.kursArrFrei[j] = this.kursArr[i];
                j++;
            }
        }
        return false;
    }
    schritt10FehlerBeiFachartKursArrayErstellung(pInput) {
        let nFacharten = this.fachartArr.length;
        let mapFachartList = new HashMap_1.HashMap();
        for (let i = 0; i < nFacharten; i++) {
            mapFachartList.put(i, new LinkedCollection_1.LinkedCollection());
        }
        for (let i = 0; i < this.kursArr.length; i++) {
            let kurs = this.kursArr[i];
            let fachartNr = kurs.gibFachart().gibNr();
            let fachartKurse = mapFachartList.get(fachartNr);
            if (fachartKurse === null)
                throw new NullPointerException_1.NullPointerException();
            fachartKurse.addLast(kurs);
        }
        for (let nr = 0; nr < nFacharten; nr++) {
            let list = mapFachartList.get(nr);
            if (list === null)
                throw new NullPointerException_1.NullPointerException();
            let kursArr = Array(list.size()).fill(null);
            for (let i = 0; i < kursArr.length; i++) {
                kursArr[i] = list.removeFirst();
            }
            this.fachartArr[nr].aktionSetKurse(kursArr);
        }
        return false;
    }
    /**
     * Leert die Datenstruktur und teilt dem Logger einen Fehler mit.
     *
     * @param fehlermeldung Die Fehlermeldung.
     */
    fehler(fehlermeldung) {
        this.regelMap.clear();
        this.maxTimeMillis = 0;
        this.schienenArr = Array(0).fill(null);
        this.fachartArr = Array(0).fill(null);
        this.fachartMap.clear();
        this.kursArr = Array(0).fill(null);
        this.kursArrFrei = Array(0).fill(null);
        this.kursMap.clear();
        this.schuelerArr = Array(0).fill(null);
        this.schuelerMap.clear();
        this.statistik.clear();
        this.logger.logLn(LogLevel_1.LogLevel.ERROR, fehlermeldung);
    }
    /**
     * Liefert das Logger-Objekt für Benutzerhinweise, Warnungen und Fehler.
     *
     * @return Das Logger-Objekt für Benutzerhinweise, Warnungen und Fehler.
     */
    gibLogger() {
        return this.logger;
    }
    /**
     * Liefert das Statistik-Objekt (für Anfragen zu Nichtwahlen, Kursdifferenzen,
     * etc.).
     *
     * @return Das Statistik-Objekt (für Anfragen zu Nichtwahlen, Kursdifferenzen,
     *         etc.).
     */
    gibStatistik() {
        return this.statistik;
    }
    /**
     * Liefert die maximale Blockungszeit in Millisekunden. Entweder handelt es sich
     * um einen Standardwert oder der Wert wurde im Konstruktor als Regel übergeben.
     *
     * @return Liefert die maximale Blockungszeit in Millisekunden.
     */
    gibBlockungszeitMillis() {
        return this.maxTimeMillis;
    }
    /**
     * Liefert die maximal erlaubte Anzahl an Schienen. Entweder handelt es sich um
     * einen Standardwert oder der Wert wurde im Konstruktor als Regel übergeben.
     *
     * @return Liefert die maximal erlaubte Anzahl an Schienen.
     */
    gibSchienenAnzahl() {
        return this.schienenArr.length;
    }
    /**
     * Erzeugt ein Objekt {@link KursblockungOutput}. Dieses Objekt beinhaltet alle
     * Informationen aus denen die GUI die Kurs-Zu-Schiene und die
     * SuS-Zu-Kurs-Zuordnungen rekonstruieren kann.
     *
     * @return Das Blockungsergebnis für die GUI.
     */
    gibErzeugtesKursblockungOutput() {
        let out = new KursblockungOutput_1.KursblockungOutput();
        for (let i = 0; i < this.kursArr.length; i++)
            this.kursArr[i].aktionOutputErzeugen(out.kursZuSchiene);
        for (let i = 0; i < this.schuelerArr.length; i++)
            this.schuelerArr[i].aktionOutputsErzeugen(out.fachwahlenZuKurs);
        return out;
    }
    /**
     * Liefert alle Kurse.
     *
     * @return Array aller Kurse.
     */
    gibKurseAlle() {
        return this.kursArr;
    }
    /**
     * Liefert alle Kurse deren Lage nicht komplett fixiert ist.
     *
     * @return Array aller Kurse, deren Schienenlage noch veränderbar ist.
     */
    gibKurseDieFreiSind() {
        return this.kursArrFrei;
    }
    /**
     * Liefert die Anzahl alle Kurse deren Lage nicht komplett fixiert ist.
     *
     * @return Anzahl aller Kurse, deren Schienenlage noch veränderbar ist.
     */
    gibKurseDieFreiSindAnzahl() {
        return this.kursArrFrei.length;
    }
    /**
     * Liefert einen Long-Wert, der einer Bewertung der Fachwahlmatrix entspricht.
     * Je kleiner der Wert, desto besser ist die Bewertung.
     *
     * @return Long-Wert, der einer Bewertung der Fachwahlmatrix entspricht.
     */
    gibBewertungFachartPaar() {
        return this.statistik.gibBewertungFachartPaar();
    }
    /**
     * Liefert ein Array aller Schülerinnen und Schüler. Falls der Parameter
     * {@code pNurMultiKurse} TRUE ist, dann werden nur SuS mit mindestens einem
     * Multikurs ausgewählt.
     *
     * @param pNurMultiKurse Falls TRUE, dann werden nur SuS mit mindestens einem
     *                       Multikurs ausgewählt.
     *
     * @return Ein Array aller Schülerinnen und Schüler.
     */
    gibSchuelerArray(pNurMultiKurse) {
        if (pNurMultiKurse) {
            let list = new LinkedCollection_1.LinkedCollection();
            for (let schueler of this.schuelerArr) {
                if (schueler.gibHatMultikurs()) {
                    list.addLast(schueler);
                }
            }
            let temp = Array(list.size()).fill(null);
            for (let i = 0; i < temp.length; i++) {
                temp[i] = list.removeFirst();
            }
            return temp;
        }
        return this.schuelerArr;
    }
    /**
     * Entfernt alle SuS aus ihren Kursen.
     */
    aktionSchuelerAusAllenKursenEntfernen() {
        for (let i = 0; i < this.schuelerArr.length; i++) {
            this.schuelerArr[i].aktionKurseAlleEntfernen();
        }
    }
    /**
     * Debug Ausgaben. Nur für Testzwecke.
     */
    debug() {
        console.log(JSON.stringify("########## Schienen ##########"));
        for (let i = 0; i < this.schienenArr.length; i++) {
            console.log(JSON.stringify("Schiene " + (i + 1)));
            this.schienenArr[i].debug(false);
        }
        console.log(JSON.stringify("########## Facharten ##########"));
        for (let i = 0; i < this.fachartArr.length; i++) {
            console.log(JSON.stringify("Fachart " + this.fachartArr[i] + " --> " + this.fachartArr[i].gibKursdifferenz()));
            this.fachartArr[i].debug();
        }
        console.log(JSON.stringify("########## Schienen (nur Multikurse) ##########"));
        for (let i = 0; i < this.schienenArr.length; i++) {
            console.log(JSON.stringify("Schiene " + (i + 1)));
            this.schienenArr[i].debug(true);
        }
        console.log(JSON.stringify("########## Facharten (nur Multikurse) ##########"));
        for (let i = 0; i < this.fachartArr.length; i++) {
            if (!this.fachartArr[i].gibHatMultikurs()) {
                continue;
            }
            console.log(JSON.stringify("Fachart " + this.fachartArr[i] + " --> " + this.fachartArr[i].gibKursdifferenz()));
            this.fachartArr[i].debug();
        }
        this.statistik.debug();
    }
    /**
     * Speichert die Bewertung, die Kursverteilung und die Schülerverteilung im
     * Zustand S.
     */
    aktionZustandSpeichernS() {
        this.statistik.aktionBewertungSpeichernS();
        for (let kurs of this.kursArr) {
            kurs.aktionZustandSpeichernS();
        }
        for (let schueler of this.schuelerArr) {
            schueler.aktionZustandSpeichernS();
        }
    }
    /**
     * Speichert die Bewertung, die Kursverteilung und die Schülerverteilung im
     * Zustand K.
     */
    aktionZustandSpeichernK() {
        this.statistik.aktionBewertungSpeichernK();
        for (let kurs of this.kursArr) {
            kurs.aktionZustandSpeichernK();
        }
        for (let schueler of this.schuelerArr) {
            schueler.aktionZustandSpeichernK();
        }
    }
    /**
     * Lädt den zuvor gespeicherten Zustand S (Kursverteilung und
     * Schülerverteilung).
     */
    aktionZustandLadenS() {
        for (let schueler of this.schuelerArr) {
            schueler.aktionKurseAlleEntfernen();
        }
        for (let kurs of this.kursArr) {
            kurs.aktionZustandLadenS();
        }
        for (let schueler of this.schuelerArr) {
            schueler.aktionZustandLadenS();
        }
    }
    /**
     * Lädt den zuvor gespeicherten Zustand Z (Kursverteilung und
     * Schülerverteilung).
     */
    aktionZustandLadenK() {
        for (let schueler of this.schuelerArr) {
            schueler.aktionKurseAlleEntfernen();
        }
        for (let kurs of this.kursArr) {
            kurs.aktionZustandLadenK();
        }
        for (let schueler of this.schuelerArr) {
            schueler.aktionZustandLadenK();
        }
    }
    /**
     * Liefert den Wert {@code -1, 0 oder +1}, falls die Bewertung (Nichtwahlen,
     * Kursdiffenzen) des Zustandes S sich verschlechtert (-1), sich verbessert (+1)
     * hat oder gleichgeblieben (0) ist.
     *
     * @return {@code -1, 0 oder +1}, falls die Bewertung (Nichtwahlen,
     *         Kursdiffenzen) des Zustandes S sich verschlechtert (-1), sich
     *         verbessert (+1) hat oder gleichgeblieben (0) ist.
     */
    gibBewertungJetztBesserAlsS() {
        return this.statistik.gibBewertung_NW_KD_JetztS();
    }
    /**
     * Liefert den Wert {@code -1, 0 oder +1}, falls die Bewertung (Nichtwahlen,
     * Kursdiffenzen) des Zustandes K sich verschlechtert (-1), sich verbessert (+1)
     * hat oder gleichgeblieben (0) ist.
     *
     * @return {@code -1, 0 oder +1}, falls die Bewertung (Nichtwahlen,
     *         Kursdiffenzen) des Zustandes K sich verschlechtert (-1), sich
     *         verbessert (+1) hat oder gleichgeblieben (0) ist.
     */
    gibBewertungJetztBesserAlsK() {
        return this.statistik.gibBewertung_NW_KD_JetztK();
    }
    /**
     * Verteilte alle Kurse auf ihre Schienen zufällig. Kurse die keinen
     * Freiheitsgrad haben, werden dabei ignoriert.
     */
    aktionKurseFreieZufaelligVerteilen() {
        for (let kurs of this.kursArrFrei) {
            kurs.aktionZufaelligVerteilen();
        }
    }
    /**
     * Verteilt einen Kurs zufällig. Kurse die keinen Freiheitsgrad haben, werden
     * dabei ignoriert.
     */
    aktionKursFreienEinenZufaelligVerteilen() {
        if (this.kursArrFrei.length === 0) {
            return;
        }
        let index = (Math.random() * this.kursArrFrei.length);
        let kurs = this.kursArrFrei[index];
        kurs.aktionZufaelligVerteilen();
    }
    /**
     * Liefert den Wert {@code -1, 0 oder +1}, falls die Bewertung (Nichtwahlen,
     * Kursdiffenzen) des Zustandes S sich verschlechtert (-1), sich verbessert (+1)
     * hat oder gleichgeblieben (0) ist.
     *
     * @return {@code -1, 0 oder +1}, falls die Bewertung (Nichtwahlen,
     *         Kursdiffenzen) des Zustandes K sich verschlechtert (-1), sich
     *         verbessert (+1) hat oder gleichgeblieben (0) ist.
     */
    gibBewertung_NW_KD_JetztS() {
        return this.statistik.gibBewertung_NW_KD_JetztS();
    }
    isTranspiledInstanceOf(name) {
        return ['de.nrw.schule.svws.core.kursblockung.KursblockungDynDaten'].includes(name);
    }
}
exports.KursblockungDynDaten = KursblockungDynDaten;
function cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynDaten(obj) {
    return obj;
}
exports.cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynDaten = cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynDaten;
//# sourceMappingURL=KursblockungDynDaten.js.map