import { JavaObject, cast_java_lang_Object } from '../../java/lang/JavaObject'; import { KursblockungDynFachart, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynFachart } from '../../core/kursblockung/KursblockungDynFachart'; import { KursblockungInput, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInput } from '../../core/data/kursblockung/KursblockungInput'; import { HashMap, cast_java_util_HashMap } from '../../java/util/HashMap'; import { KursblockungInputRegel, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputRegel } from '../../core/data/kursblockung/KursblockungInputRegel'; import { KursblockungDynSchiene, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynSchiene } from '../../core/kursblockung/KursblockungDynSchiene'; import { KursblockungDynKurs, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs } from '../../core/kursblockung/KursblockungDynKurs'; import { KursblockungInputFach, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputFach } from '../../core/data/kursblockung/KursblockungInputFach'; import { JavaString, cast_java_lang_String } from '../../java/lang/JavaString'; import { Logger, cast_de_nrw_schule_svws_logger_Logger } from '../../logger/Logger'; import { LogLevel, cast_de_nrw_schule_svws_logger_LogLevel } from '../../logger/LogLevel'; import { System, cast_java_lang_System } from '../../java/lang/System'; import { NullPointerException, cast_java_lang_NullPointerException } from '../../java/lang/NullPointerException'; import { Vector, cast_java_util_Vector } from '../../java/util/Vector'; import { HashSet, cast_java_util_HashSet } from '../../java/util/HashSet'; import { KursblockungDynStatistik, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynStatistik } from '../../core/kursblockung/KursblockungDynStatistik'; import { KursblockungInputSchueler, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputSchueler } from '../../core/data/kursblockung/KursblockungInputSchueler'; import { LinkedCollection, cast_de_nrw_schule_svws_core_adt_collection_LinkedCollection } from '../../core/adt/collection/LinkedCollection'; import { KursblockungInputKurs, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputKurs } from '../../core/data/kursblockung/KursblockungInputKurs'; import { JavaInteger, cast_java_lang_Integer } from '../../java/lang/JavaInteger'; import { KursblockungOutput, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungOutput } from '../../core/data/kursblockung/KursblockungOutput'; import { JavaLong, cast_java_lang_Long } from '../../java/lang/JavaLong'; import { KursblockungInputKursart, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputKursart } from '../../core/data/kursblockung/KursblockungInputKursart'; import { KursblockungInputFachwahl, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputFachwahl } from '../../core/data/kursblockung/KursblockungInputFachwahl'; import { KursblockungDynSchueler, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynSchueler } from '../../core/kursblockung/KursblockungDynSchueler'; export class KursblockungDynDaten extends JavaObject { private readonly logger : Logger; private readonly regelMap : HashMap>; private maxTimeMillis : number = 0; private schienenArr : Array; private kursArr : Array; private kursArrFrei : Array; private readonly kursMap : HashMap; private fachartArr : Array; private readonly fachartMap : HashMap>; private schuelerArr : Array; private readonly schuelerMap : HashMap; private readonly statistik : KursblockungDynStatistik; /** * 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). */ public constructor(pLogger : Logger, pInput : KursblockungInput) { super(); this.logger = pLogger; this.regelMap = new 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(); this.fachartArr = Array(0).fill(null); this.fachartMap = new HashMap(); this.schuelerArr = Array(0).fill(null); this.schuelerMap = new HashMap(); this.statistik = new 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. */ private schritt01FehlerBeiReferenzen(pInput : KursblockungInput) : boolean { 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 : number = 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 : HashSet = new HashSet(); for (let i : number = 0; i < pInput.faecher.size(); i++){ let iFach : KursblockungInputFach | null = 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 : HashSet = new HashSet(); for (let i : number = 0; i < pInput.kursarten.size(); i++){ let iKursart : KursblockungInputKursart | null = 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 : HashSet = new HashSet(); for (let i : number = 0; i < pInput.kurse.size(); i++){ let iKurs : KursblockungInputKurs | null = 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 : number = 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 : HashSet = new HashSet(); for (let i : number = 0; i < pInput.schueler.size(); i++){ let schueler : KursblockungInputSchueler | null = 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 : number = 0; i < pInput.fachwahlen.size(); i++){ let iFachwahl : KursblockungInputFachwahl | null = pInput.fachwahlen.get(i); let schuelerID : number = 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 : number = 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 : number = 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 : number = 0; i < pInput.kurse.size(); i++){ let iKurs : KursblockungInputKurs = pInput.kurse.get(i); let fachID : number = 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 : number = 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 : number = 0; i < pInput.regeln.size(); i++){ let iRegel : KursblockungInputRegel = pInput.regeln.get(i); let regelID : number = 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 : number = 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 : number = iRegel.daten[1].valueOf(); let bis : number = 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 : number = 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 : number = 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; } private schritt02FehlerBeiRegelGruppierung(vRegeln : Vector) : boolean { for (let i : number = 0; i < vRegeln.size(); i++){ let regel : KursblockungInputRegel = vRegeln.get(i); let regelID : number = regel.id; let list : LinkedCollection | null = this.regelMap.get(regelID); if (list === null) { list = new LinkedCollection(); this.regelMap.put(regelID, list); } list.addLast(regel); } return false; } private schritt03FehlerBeiFachartenErstellung(pInput : KursblockungInput) : boolean { let mapFach : HashMap = new HashMap(); for (let iFach of pInput.faecher) { mapFach.put(iFach.id, iFach.representation); } let mapKursart : HashMap = new HashMap(); for (let iKursart of pInput.kursarten) { mapKursart.put(iKursart.id, iKursart.representation); } let mapSchueler : HashMap = new HashMap(); for (let iSchueler of pInput.schueler) { mapSchueler.put(iSchueler.id, iSchueler.representation); } let nFacharten : number = 0; let nKurse : number = pInput.kurse.size(); for (let i : number = 0; i < nKurse; i++){ let iKurs : KursblockungInputKurs = pInput.kurse.get(i); let fachID : number = iKurs.fach; let kursartID : number = iKurs.kursart; let kursartMap : HashMap | null = this.fachartMap.get(fachID); if (kursartMap === null) { kursartMap = new HashMap(); this.fachartMap.put(fachID, kursartMap); } let dynFachart : KursblockungDynFachart | null = kursartMap.get(kursartID); if (dynFachart === null) { let strFach : String | null = mapFach.get(fachID); let strKursart : String | null = mapKursart.get(kursartID); if ((strFach === null) || (strKursart === null)) throw new NullPointerException() let representation : String = strFach.valueOf() + ";" + strKursart.valueOf(); dynFachart = new KursblockungDynFachart(nFacharten, representation, this.statistik); kursartMap.put(kursartID, dynFachart); nFacharten++; } dynFachart.aktionMaxKurseErhoehen(); } for (let i : number = 0; i < pInput.fachwahlen.size(); i++){ let iFachwahl : KursblockungInputFachwahl = pInput.fachwahlen.get(i); let schuelerID : number = iFachwahl.schueler; let fachID : number = iFachwahl.fach; let kursartID : number = iFachwahl.kursart; let kursartMap : HashMap | null = this.fachartMap.get(fachID); if (kursartMap === null) { kursartMap = new HashMap(); this.fachartMap.put(fachID, kursartMap); } let dynFachart : KursblockungDynFachart | null = kursartMap.get(kursartID); if (dynFachart === null) { let strFach : String | null = mapFach.get(fachID); let strKursart : String | null = mapKursart.get(kursartID); let strSchueler : String | null = mapSchueler.get(schuelerID); if ((strFach === null) || (strKursart === null) || (strSchueler === null)) throw new NullPointerException() let representation : String = strFach.valueOf() + ";" + strKursart.valueOf(); dynFachart = new KursblockungDynFachart(nFacharten, representation, this.statistik); kursartMap.put(kursartID, dynFachart); nFacharten++; this.logger.logLn(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 : number = 0; for (let i : number = 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; } private schritt04FehlerBeiSchuelerErstellung(pInput : KursblockungInput) : boolean { let vSchueler : Vector = pInput.schueler; let nSchueler : number = vSchueler.size(); this.schuelerArr = Array(nSchueler).fill(null); for (let i : number = 0; i < nSchueler; i++){ let iSchueler : KursblockungInputSchueler = vSchueler.get(i); let schueler : KursblockungDynSchueler = new KursblockungDynSchueler(iSchueler, this.statistik, pInput.maxSchienen); this.schuelerArr[i] = schueler; this.schuelerMap.put(iSchueler.id, schueler); } return false; } private schritt05FehlerBeiSchuelerFachwahlenErstellung(vFachwahlen : Vector, susArr : Array) : boolean { let mapSchuelerFA : HashMap> = new HashMap(); let mapSchuelerID : HashMap> = new HashMap(); for (let i : number = 0; i < susArr.length; i++){ mapSchuelerFA.put(susArr[i], new LinkedCollection()); mapSchuelerID.put(susArr[i], new LinkedCollection()); } let nFachwahlen : number = vFachwahlen.size(); for (let i : number = 0; i < nFachwahlen; i++){ let iFachwahl : KursblockungInputFachwahl = vFachwahlen.get(i); let susID : number = iFachwahl.schueler; let fachID : number = iFachwahl.fach; let kursartID : number = iFachwahl.kursart; let schueler : KursblockungDynSchueler | null = this.schuelerMap.get(susID); let kursartMap : HashMap | null = this.fachartMap.get(fachID); let dynFachart : KursblockungDynFachart | null = kursartMap === null ? null : kursartMap.get(kursartID); let dynFacharten : LinkedCollection | null = mapSchuelerFA.get(schueler); if (dynFacharten === null) throw new NullPointerException() dynFacharten.addLast(dynFachart); let fachwahlIDs : LinkedCollection | null = mapSchuelerID.get(schueler); if (fachwahlIDs === null) throw new NullPointerException() fachwahlIDs.addLast(iFachwahl.id); } for (let nr : number = 0; nr < susArr.length; nr++){ let schueler : KursblockungDynSchueler = susArr[nr]; let listFA : LinkedCollection | null = mapSchuelerFA.get(schueler); let listID : LinkedCollection | null = mapSchuelerID.get(schueler); if ((listFA === null) || (listID === null)) throw new NullPointerException() let nWahlen : number = listFA.size(); let arrFA : Array = Array(nWahlen).fill(null); let arrID : Array = Array(nWahlen).fill(0); for (let i : number = 0; i < nWahlen; i++){ arrFA[i] = listFA.removeFirst(); arrID[i] = listID.removeFirst().valueOf(); } schueler.aktionSetzeFachartenUndIDs(arrFA, arrID); } return false; } private schritt06FehlerBeiStatistikErstellung(fachartArr : Array, susArr : Array) : boolean { let nFacharten : number = fachartArr.length; let bewertungMatrixFachart : Array> = [...Array(nFacharten)].map(e => Array(nFacharten).fill(0)); for (let i : number = 0; i < susArr.length; i++){ let fa : Array = susArr[i].gibFacharten(); for (let i1 : number = 0; i1 < fa.length; i1++){ let nr1 : number = fa[i1].gibNr(); for (let i2 : number = i1 + 1; i2 < fa.length; i2++){ let nr2 : number = fa[i2].gibNr(); bewertungMatrixFachart[nr1][nr2]++; bewertungMatrixFachart[nr2][nr1]++; } } } for (let i1 : number = 0; i1 < nFacharten; i1++){ let kursAnz1 : number = fachartArr[i1].gibKurseMax(); let nr1 : number = fachartArr[i1].gibNr(); for (let i2 : number = 0; i2 < nFacharten; i2++){ let kursAnz2 : number = fachartArr[i2].gibKurseMax(); let nr2 : number = fachartArr[i2].gibNr(); if ((kursAnz1 === 0) || (kursAnz2 === 0)) { bewertungMatrixFachart[nr1][nr2] = 0; } else { let faktor : number = Math.trunc(1000 / (kursAnz1 + kursAnz2 - 1)); bewertungMatrixFachart[nr1][nr2] *= faktor; } } bewertungMatrixFachart[nr1][nr1] += 100000; } this.statistik.aktionInitialisiere(bewertungMatrixFachart, susArr.length, fachartArr.length); return false; } private schritt07FehlerBeiSchienenErzeugung(pSchienen : number) : boolean { this.schienenArr = Array(pSchienen).fill(null); for (let nr : number = 0; nr < pSchienen; nr++){ this.schienenArr[nr] = new KursblockungDynSchiene(this.logger, nr, this.statistik); } return false; } private schritt08FehlerBeiKursErstellung(pInput : KursblockungInput) : boolean { let vKurse : Vector = pInput.kurse; let nKurse : number = vKurse.size(); let nSchienen : number = this.schienenArr.length; let mapKursSchieneFrei : HashMap> = new HashMap(); let mapKursSchieneLage : HashMap> = new HashMap(); for (let i : number = 0; i < nKurse; i++){ let kursID : number = vKurse.get(i).id; let schieneFrei : LinkedCollection = new LinkedCollection(); mapKursSchieneLage.put(kursID, new LinkedCollection()); mapKursSchieneFrei.put(kursID, schieneFrei); let perm : Array = Array(nSchienen).fill(0); for (let j : number = 0; j < nSchienen; j++){ perm[j] = j; } for (let j1 : number = 0; j1 < nSchienen; j1++){ let j2 : number = (Math.random() * nSchienen) as number; let s1 : number = perm[j1]; let s2 : number = perm[j2]; perm[j1] = s2; perm[j2] = s1; } for (let j : number = 0; j < nSchienen; j++){ schieneFrei.addLast(this.schienenArr[perm[j]]); } } let regelID1 : number = 1; let regelnTyp1 : LinkedCollection | null = this.regelMap.get(regelID1); if (regelnTyp1 !== null) { for (let regel1 of regelnTyp1) { let kursart : number = regel1.daten[0].valueOf(); let von : number = regel1.daten[1].valueOf(); let bis : number = regel1.daten[2].valueOf(); for (let i : number = 0; i < pInput.kurse.size(); i++){ let kurs : KursblockungInputKurs = pInput.kurse.get(i); if (kurs.kursart === kursart) { for (let schiene : number = von; schiene <= bis; schiene++){ let schieneFrei : LinkedCollection | null = mapKursSchieneFrei.get(kurs.id); if (schieneFrei === null) throw new NullPointerException() schieneFrei.remove(this.schienenArr[schiene]); } } } } } let regelID3 : number = 3; let regelnTyp3 : LinkedCollection | null = this.regelMap.get(regelID3); if (regelnTyp3 !== null) { for (let regel3 of regelnTyp3) { let kursID : number = regel3.daten[0].valueOf(); let schiene : number = regel3.daten[1].valueOf(); let schieneFrei : LinkedCollection | null = mapKursSchieneFrei.get(kursID); if (schieneFrei === null) throw new NullPointerException() schieneFrei.remove(this.schienenArr[schiene]); } } let regelID2 : number = 2; let regelnTyp2 : LinkedCollection | null = this.regelMap.get(regelID2); if (regelnTyp2 !== null) { for (let regel2 of regelnTyp2) { let kursID : number = regel2.daten[0].valueOf(); let schiene : number = regel2.daten[1].valueOf(); let schieneFrei : LinkedCollection | null = mapKursSchieneFrei.get(kursID); let schieneLage : LinkedCollection | null = mapKursSchieneLage.get(kursID); if ((schieneFrei === null) || (schieneLage === null)) throw new NullPointerException() if (schieneLage.contains(this.schienenArr[schiene])) { continue; } if (!schieneFrei.contains(this.schienenArr[schiene])) { let kurs : KursblockungDynKurs | null = this.kursMap.get(kursID); if (kurs === null) throw new 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 : number = 0; i < nKurse; i++){ let iKurs : KursblockungInputKurs = vKurse.get(i); let representation : String = iKurs.representation; let fach : number = iKurs.fach; let kursart : number = iKurs.kursart; let schienen : number = iKurs.schienen; if (schienen <= 0) { this.logger.logLn(LogLevel.ERROR, "Kurs \'" + representation.valueOf() + "\' belegt nur " + schienen + " Schienen, das ist zu wenig."); return true; } if (schienen > this.schienenArr.length) { this.logger.logLn(LogLevel.ERROR, "Es gibt " + this.schienenArr.length + " Schienen, aber der Kurs \'" + representation.valueOf() + "\' möchte " + schienen + " Schienen belegt."); return true; } let listLage : LinkedCollection | null = mapKursSchieneLage.get(iKurs.id); if (listLage === null) throw new NullPointerException() let pSchienenLageFixiert : number = listLage.size(); if (pSchienenLageFixiert > iKurs.schienen) { this.logger.logLn(LogLevel.ERROR, "Kurs \'" + representation.valueOf() + "\' fixert " + pSchienenLageFixiert + " Schienen, das ist mehr als seine Schienenanzahl " + iKurs.schienen + " ."); return true; } let listFrei : LinkedCollection | null = mapKursSchieneFrei.get(iKurs.id); if (listFrei === null) throw new NullPointerException() while (listLage.size() < iKurs.schienen) { if (listFrei.isEmpty()) { this.logger.logLn(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 = Array(listLage.size()).fill(null); for (let j : number = 0; j < pSchienenLage.length; j++){ pSchienenLage[j] = listLage.removeFirst(); } let pSchienenFrei : Array = Array(listFrei.size()).fill(null); for (let j : number = 0; j < pSchienenFrei.length; j++){ pSchienenFrei[j] = listFrei.removeFirst(); } let kursartMap : HashMap | null = this.fachartMap.get(fach); let dynFachart : KursblockungDynFachart | null = kursartMap === null ? null : kursartMap.get(kursart); if (dynFachart === null) throw new NullPointerException() let kurs : KursblockungDynKurs = new KursblockungDynKurs(pSchienenLage, pSchienenLageFixiert, pSchienenFrei, iKurs, dynFachart, this.logger); this.kursArr[i] = kurs; this.kursMap.put(iKurs.id, kurs); } return false; } private schritt09FehlerBeiKursFreiErstellung(pInput : KursblockungInput) : boolean { let nKursFrei : number = 0; for (let i : number = 0; i < this.kursArr.length; i++){ if (this.kursArr[i].gibHatFreiheitsgrade()) { nKursFrei++; } } this.kursArrFrei = Array(nKursFrei).fill(null); for (let i : number = 0, j : number = 0; i < this.kursArr.length; i++){ if (this.kursArr[i].gibHatFreiheitsgrade()) { this.kursArrFrei[j] = this.kursArr[i]; j++; } } return false; } private schritt10FehlerBeiFachartKursArrayErstellung(pInput : KursblockungInput) : boolean { let nFacharten : number = this.fachartArr.length; let mapFachartList : HashMap> = new HashMap(); for (let i : number = 0; i < nFacharten; i++){ mapFachartList.put(i, new LinkedCollection()); } for (let i : number = 0; i < this.kursArr.length; i++){ let kurs : KursblockungDynKurs = this.kursArr[i]; let fachartNr : number = kurs.gibFachart().gibNr(); let fachartKurse : LinkedCollection | null = mapFachartList.get(fachartNr); if (fachartKurse === null) throw new NullPointerException() fachartKurse.addLast(kurs); } for (let nr : number = 0; nr < nFacharten; nr++){ let list : LinkedCollection | null = mapFachartList.get(nr); if (list === null) throw new NullPointerException() let kursArr : Array = Array(list.size()).fill(null); for (let i : number = 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. */ private fehler(fehlermeldung : String) : void { 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.ERROR, fehlermeldung); } /** * Liefert das Logger-Objekt für Benutzerhinweise, Warnungen und Fehler. * * @return Das Logger-Objekt für Benutzerhinweise, Warnungen und Fehler. */ gibLogger() : Logger { 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() : KursblockungDynStatistik { 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() : number { 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() : number { 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() : KursblockungOutput { let out : KursblockungOutput = new KursblockungOutput(); for (let i : number = 0; i < this.kursArr.length; i++) this.kursArr[i].aktionOutputErzeugen(out.kursZuSchiene); for (let i : number = 0; i < this.schuelerArr.length; i++) this.schuelerArr[i].aktionOutputsErzeugen(out.fachwahlenZuKurs); return out; } /** * Liefert alle Kurse. * * @return Array aller Kurse. */ gibKurseAlle() : Array { return this.kursArr; } /** * Liefert alle Kurse deren Lage nicht komplett fixiert ist. * * @return Array aller Kurse, deren Schienenlage noch veränderbar ist. */ gibKurseDieFreiSind() : Array { 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() : number { 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() : number { 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 : boolean) : Array { if (pNurMultiKurse) { let list : LinkedCollection = new LinkedCollection(); for (let schueler of this.schuelerArr) { if (schueler.gibHatMultikurs()) { list.addLast(schueler); } } let temp : Array = Array(list.size()).fill(null); for (let i : number = 0; i < temp.length; i++){ temp[i] = list.removeFirst(); } return temp; } return this.schuelerArr; } /** * Entfernt alle SuS aus ihren Kursen. */ aktionSchuelerAusAllenKursenEntfernen() : void { for (let i : number = 0; i < this.schuelerArr.length; i++){ this.schuelerArr[i].aktionKurseAlleEntfernen(); } } /** * Debug Ausgaben. Nur für Testzwecke. */ debug() : void { console.log(JSON.stringify("########## Schienen ##########")); for (let i : number = 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 : number = 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 : number = 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 : number = 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() : void { 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() : void { 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() : void { 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() : void { 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() : number { 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() : number { return this.statistik.gibBewertung_NW_KD_JetztK(); } /** * Verteilte alle Kurse auf ihre Schienen zufällig. Kurse die keinen * Freiheitsgrad haben, werden dabei ignoriert. */ aktionKurseFreieZufaelligVerteilen() : void { for (let kurs of this.kursArrFrei) { kurs.aktionZufaelligVerteilen(); } } /** * Verteilt einen Kurs zufällig. Kurse die keinen Freiheitsgrad haben, werden * dabei ignoriert. */ aktionKursFreienEinenZufaelligVerteilen() : void { if (this.kursArrFrei.length === 0) { return; } let index : number = (Math.random() * this.kursArrFrei.length) as number; let kurs : KursblockungDynKurs = 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() : number { return this.statistik.gibBewertung_NW_KD_JetztS(); } isTranspiledInstanceOf(name : string): boolean { return ['de.nrw.schule.svws.core.kursblockung.KursblockungDynDaten'].includes(name); } } export function cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynDaten(obj : unknown) : KursblockungDynDaten { return obj as KursblockungDynDaten; }