123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- 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 { KursblockungDynStatistik, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynStatistik } from '../../core/kursblockung/KursblockungDynStatistik';
- import { KursblockungStatic, cast_de_nrw_schule_svws_core_kursblockung_KursblockungStatic } from '../../core/kursblockung/KursblockungStatic';
- import { KursblockungMatrix, cast_de_nrw_schule_svws_core_kursblockung_KursblockungMatrix } from '../../core/kursblockung/KursblockungMatrix';
- import { KursblockungInputSchueler, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungInputSchueler } from '../../core/data/kursblockung/KursblockungInputSchueler';
- import { KursblockungDynKurs, cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynKurs } from '../../core/kursblockung/KursblockungDynKurs';
- import { JavaString, cast_java_lang_String } from '../../java/lang/JavaString';
- import { Vector, cast_java_util_Vector } from '../../java/util/Vector';
- import { System, cast_java_lang_System } from '../../java/lang/System';
- import { KursblockungOutputFachwahlZuKurs, cast_de_nrw_schule_svws_core_data_kursblockung_KursblockungOutputFachwahlZuKurs } from '../../core/data/kursblockung/KursblockungOutputFachwahlZuKurs';
- export class KursblockungDynSchueler extends JavaObject {
- private readonly representation : String;
- private fachartArr : Array<KursblockungDynFachart>;
- private fachartZuGUI : Array<number>;
- private fachartZuKurs : Array<KursblockungDynKurs | null>;
- private fachartZuKursSaveS : Array<KursblockungDynKurs | null>;
- private fachartZuKursSaveK : Array<KursblockungDynKurs | null>;
- private readonly statistik : KursblockungDynStatistik;
- private nichtwahlen : number = 0;
- private readonly schieneBelegt : Array<boolean>;
- private static dummy : KursblockungMatrix = new KursblockungMatrix(0, 0);
- private matrix : KursblockungMatrix;
- /**
- * Im Konstruktor wird {@code pSchueler} in ein Objekt dieser Klasse
- * umgewandelt.
- *
- * @param pStatistik Referenz um die Nichtwahlen mitzuteilen.
- * @param pSchueler Die Schüler-Daten von der GUI/DB.
- * @param pSchienenAnzahl Wir benötigt, um {@link #schieneBelegt} zu
- * initialisieren.
- */
- constructor(pSchueler : KursblockungInputSchueler, pStatistik : KursblockungDynStatistik, pSchienenAnzahl : number) {
- super();
- this.representation = pSchueler.representation;
- this.statistik = pStatistik;
- this.fachartArr = Array(0).fill(null);
- this.fachartZuGUI = Array(0).fill(0);
- this.fachartZuKurs = Array(0).fill(null);
- this.fachartZuKursSaveS = Array(0).fill(null);
- this.fachartZuKursSaveK = Array(0).fill(null);
- this.nichtwahlen = 0;
- this.schieneBelegt = Array(pSchienenAnzahl).fill(false);
- this.matrix = KursblockungDynSchueler.dummy;
- }
- public toString() : String {
- return this.representation;
- }
- /**
- * Eine String-Darstellung des Schülers. Beinhaltet meistens den Vornamen, den
- * Nachnamen, das Geburtsdatum und das Geschlecht.
- *
- * @return Eine String-Darstellung des Schülers.
- */
- gibRepresentation() : String {
- return this.representation;
- }
- /**
- * Liefert die aktuelle Anzahl an Nichtwahlen.
- *
- * @return Die aktuelle Anzahl an Nichtwahlen.
- */
- gibNichtwahlen() : number {
- return this.nichtwahlen;
- }
- /**
- * Liefert ein Array aller Facherten (= Fachwahlen) des Schülers.
- *
- * @return Ein Array aller Facherten (= Fachwahlen) des Schülers.
- */
- gibFacharten() : Array<KursblockungDynFachart> {
- return this.fachartArr;
- }
- /**
- * Setzt alle Facharten (=Fachwahlen) des Schülers.
- *
- * @param pFacharten Die Facharten des Schülers.
- * @param pIDs Die zur Fachwahl zugehörige ID der GUI bzw. Datenbank.
- */
- aktionSetzeFachartenUndIDs(pFacharten : Array<KursblockungDynFachart>, pIDs : Array<number>) : void {
- let nFacharten : number = pFacharten.length;
- this.fachartArr = pFacharten;
- this.fachartZuGUI = pIDs;
- this.fachartZuKurs = Array(nFacharten).fill(null);
- this.fachartZuKursSaveS = Array(nFacharten).fill(null);
- this.fachartZuKursSaveK = Array(nFacharten).fill(null);
- this.statistik.aktionNichtwahlenVeraendern(nFacharten);
- this.nichtwahlen = nFacharten;
- for (let i : number = 1; i < nFacharten; i++){
- for (let j : number = i; j >= 1; j--){
- let anzL : number = this.fachartArr[j - 1].gibKurseMax();
- let anzR : number = this.fachartArr[j].gibKurseMax();
- if (anzL > anzR) {
- let fL : KursblockungDynFachart = this.fachartArr[j - 1];
- let fR : KursblockungDynFachart = this.fachartArr[j];
- let valL : number = this.fachartZuGUI[j - 1];
- let valR : number = this.fachartZuGUI[j];
- this.fachartArr[j - 1] = fR;
- this.fachartArr[j] = fL;
- this.fachartZuGUI[j - 1] = valR;
- this.fachartZuGUI[j] = valL;
- }
- }
- }
- this.matrix = new KursblockungMatrix(nFacharten, this.schieneBelegt.length);
- }
- /**
- * Speichert die aktuell belegten Kurse im Zustand S.
- */
- aktionZustandSpeichernS() : void {
- System.arraycopy(this.fachartZuKurs, 0, this.fachartZuKursSaveS, 0, this.fachartZuKurs.length);
- }
- /**
- * Speichert die aktuell belegten Kurse im Zustand K.
- */
- aktionZustandSpeichernK() : void {
- System.arraycopy(this.fachartZuKurs, 0, this.fachartZuKursSaveK, 0, this.fachartZuKurs.length);
- }
- /**
- * Entfernt zunächst den Schüler aus seinen aktuellen Kursen und setzt ihn dann
- * in die Kurse, die zuvor im Zustand S gespeichert wurden.
- */
- aktionZustandLadenS() : void {
- this.aktionWaehleKurse(this.fachartZuKursSaveS);
- }
- /**
- * Entfernt zunächst den Schüler aus seinen aktuellen Kursen und setzt ihn dann
- * in die Kurse, die zuvor im Zustand K gespeichert wurden.
- */
- aktionZustandLadenK() : void {
- this.aktionWaehleKurse(this.fachartZuKursSaveK);
- }
- private aktionWaehleKurse(wahl : Array<KursblockungDynKurs | null>) : void {
- this.aktionKurseAlleEntfernen();
- for (let i : number = 0; i < this.fachartZuKurs.length; i++){
- let kurs : KursblockungDynKurs | null = wahl[i];
- if (kurs !== null) {
- this.aktionKursHinzufuegen(i, kurs);
- }
- }
- }
- /**
- * Entfernt den Schüler aus seinen aktuell zugeordneten Kursen.
- */
- aktionKurseAlleEntfernen() : void {
- for (let i : number = 0; i < this.fachartArr.length; i++){
- let kurs : KursblockungDynKurs | null = this.fachartZuKurs[i];
- if (kurs !== null) {
- this.aktionKursEntfernen(i, kurs);
- }
- }
- }
- /**
- * Geht die Facharten durch (Facharten mit einer kleineren Kursanzahl zuerst)
- * und geht dann pro Fachart alle Kurse durch (Kurse mit kleinerer Schüleranzahl
- * zuerst). Falls der Kurs wählbar ist, wird der Schüler hinzugefügt und es geht
- * weiter mit der nächsten Fachart. Ein Kurs ist wählbar, wenn nicht bereits ein
- * Kurs zugeordnet wurde und die Schienen in den der Kurs sind frei sind.<br>
- *
- * Falls der Paramter {@code pNurMultikurse} TRUE ist, dann werden nur
- * Multikurse verteilt.
- *
- * @param pNurMultikurse Falls TRUE ist, dann werden nur Multikurse verteilt.
- */
- aktionKurseZufaelligVerteilen(pNurMultikurse : boolean) : void {
- let perm : Array<number> = KursblockungStatic.gibPermutation(this.fachartArr.length);
- for (let p : number = 0; p < this.fachartArr.length; p++){
- let i : number = perm[p];
- if (this.fachartZuKurs[i] !== null) {
- continue;
- }
- let fachart : KursblockungDynFachart = this.fachartArr[i];
- if (pNurMultikurse) {
- if (!fachart.gibHatMultikurs()) {
- continue;
- }
- }
- let kurse : Array<KursblockungDynKurs> = fachart.gibKurse();
- let perm2 : Array<number> = KursblockungStatic.gibPermutation(kurse.length);
- for (let p2 : number = 0; p2 < perm2.length; p2++){
- let i2 : number = p2;
- let kurs : KursblockungDynKurs = kurse[i2];
- let waehlbar : boolean = true;
- for (let nr of kurs.gibSchienenLage()) {
- if (this.schieneBelegt[nr]) {
- waehlbar = false;
- }
- }
- if (waehlbar) {
- this.aktionKursHinzufuegen(i, kurs);
- break;
- }
- }
- }
- }
- /**
- * Verteilt alle Kurse die über genau 1 Schiene gehen mit Hilfe eines Matching
- * Algorithmus.
- */
- aktionKurseMitBipartiteMatchingVerteilen() : void {
- let data : Array<Array<number>> = this.matrix.getMatrix();
- for (let r : number = 0; r < this.fachartArr.length; r++){
- for (let c : number = 0; c < this.schieneBelegt.length; c++){
- data[r][c] = 0;
- }
- if (this.fachartZuKurs[r] !== null) {
- continue;
- }
- if (this.fachartArr[r].gibHatMultikurs()) {
- continue;
- }
- for (let kurs of this.fachartArr[r].gibKurse()) {
- for (let nr of kurs.gibSchienenLage()) {
- if (!this.schieneBelegt[nr]) {
- data[r][nr] = 1;
- }
- }
- }
- }
- let r2c : Array<number> = this.matrix.gibMaximalesBipartitesMatching(true);
- for (let r : number = 0; r < this.fachartArr.length; r++){
- if (this.fachartZuKurs[r] !== null) {
- continue;
- }
- let c : number = r2c[r];
- if (c === -1) {
- continue;
- }
- let kursGefunden : KursblockungDynKurs | null = null;
- for (let kurs of this.fachartArr[r].gibKurse()) {
- for (let nr of kurs.gibSchienenLage()) {
- if ((nr === c) && (kursGefunden === null)) {
- kursGefunden = kurs;
- }
- }
- }
- if (kursGefunden !== null)
- this.aktionKursHinzufuegen(r, kursGefunden);
- }
- }
- /**
- * Erzeugt pro Fachwahl ein Objekt des Typs
- * {@link KursblockungOutputFachwahlZuKurs} und fügt es dem Vector
- * {@code vFachwahlZuKurs} hinzu. Die GUI kann daraus die
- * Schüler-Zu-Kurs-Zuordnungen rekonstruiern.
- *
- * @param vFachwahlZuKurs Fügt diesem Vector pro Fachwahl ein Objekt des Typs
- * {@link KursblockungOutputFachwahlZuKurs} hinzu.
- */
- aktionOutputsErzeugen(vFachwahlZuKurs : Vector<KursblockungOutputFachwahlZuKurs>) : void {
- for (let i : number = 0; i < this.fachartArr.length; i++){
- let fachwahlZuKurs : KursblockungOutputFachwahlZuKurs = new KursblockungOutputFachwahlZuKurs();
- fachwahlZuKurs.fachwahl = this.fachartZuGUI[i];
- let tmpKurs : KursblockungDynKurs | null = this.fachartZuKurs[i];
- fachwahlZuKurs.kurs = (tmpKurs === null) ? -1 : tmpKurs.gibID();
- vFachwahlZuKurs.add(fachwahlZuKurs);
- }
- }
- /**
- * Liefert TRUE, falls der Schüler mindestens einen Multikurs hat. Ein Multikurs
- * ist ein Kurs, der über mehr als eine Schiene geht.
- *
- * @return TRUE, falls der Schüler mindestens einen Multikurs hat.
- */
- gibHatMultikurs() : boolean {
- for (let fachart of this.fachartArr) {
- if (fachart.gibHatMultikurs()) {
- return true;
- }
- }
- return false;
- }
- private aktionKursHinzufuegen(fachartIndex : number, kurs : KursblockungDynKurs) : void {
- kurs.aktionSchuelerHinzufügen();
- this.statistik.aktionNichtwahlenVeraendern(-1);
- this.nichtwahlen--;
- for (let nr of kurs.gibSchienenLage()) {
- if (this.schieneBelegt[nr]) {
- console.log(JSON.stringify("FEHLER: Schienen-Doppelbelegung! " + this.representation.valueOf()));
- }
- this.schieneBelegt[nr] = true;
- }
- this.fachartZuKurs[fachartIndex] = kurs;
- }
- private aktionKursEntfernen(fachartIndex : number, kurs : KursblockungDynKurs) : void {
- kurs.aktionSchuelerEntfernen();
- this.statistik.aktionNichtwahlenVeraendern(+1);
- this.nichtwahlen++;
- for (let nr of kurs.gibSchienenLage()) {
- if (!this.schieneBelegt[nr]) {
- console.log(JSON.stringify("FEHLER: Kurs ist gar nicht in Schiene ! " + this.representation.valueOf()));
- }
- this.schieneBelegt[nr] = false;
- }
- this.fachartZuKurs[fachartIndex] = null;
- }
- isTranspiledInstanceOf(name : string): boolean {
- return ['de.nrw.schule.svws.core.kursblockung.KursblockungDynSchueler'].includes(name);
- }
- }
- export function cast_de_nrw_schule_svws_core_kursblockung_KursblockungDynSchueler(obj : unknown) : KursblockungDynSchueler {
- return obj as KursblockungDynSchueler;
- }
|