lukujarjestaja/tietomalli.js

416 lines
16 KiB
JavaScript

'use strict';
const tapahtumaTyypit = {
lisääAste: 'lisääAste',
poistaAste: 'poistaAste',
muutaAste: 'muutaAste',
lisääLuokka: 'lisääLuokka',
poistaLuokka: 'poistaLuokka',
lisääOpettaja: 'lisääOpettaja',
poistaOpettaja: 'poistaOpettaja',
lisääTila: 'lisääTila',
poistaTila: 'poistaTila',
lisääTunti: 'lisääTunti',
poistaTunti: 'poistaTunti',
lisääTuntiLuokka: 'lisääTuntiLuokka',
poistaTuntiLuokka: 'poistaTuntiLuokka',
lisääTuntiOpettaja: 'lisääTuntiOpettaja',
poistaTuntiOpettaja: 'poistaTuntiOpettaja',
lisääTuntiTila: 'lisääTuntiTila',
poistaTuntiTila: 'poistaTuntiTila',
};
class Tapahtuma {
constructor(tyyppi, argumentit) {
this.tyyppi = tyyppi;
this.argumentit = argumentit;
}
}
let historia, tulevaisuus;
let luokkaAsteet, opettajat, tilat, tunnit;
alustaMalli();
function alustaMalli() {
historia = [];
tulevaisuus = [];
luokkaAsteet = new LuokkaAsteet();
opettajat = new Opettajat();
tilat = new Tilat();
tunnit = new Tunnit();
}
function suorita(tyyppi, ...argumentit) {
let paluuarvo = undefined;
switch (tyyppi) {
case tapahtumaTyypit.lisääAste:
assertRange('lisääAste argumentit', argumentit.length, 0, 1);
paluuarvo = luokkaAsteet.lisää(...argumentit)
break;
case tapahtumaTyypit.poistaAste:
assertEq('poistaAste argumentit', argumentit.length, 1);
let [poistettuAste] = argumentit;
luokkaAsteet.poista(poistettuAste);
// Poista poistettujen luokka-asteiden luokat tunneista
for (let [_, tunti] of tunnit.tunnit) {
for (let luokka of tunti.luokat.alkiot()) {
let luokanAste = parseInt(luokka[0]);
if (luokanAste === poistettuAste) {
tunti.luokat.poista(luokka);
}
}
}
break;
case tapahtumaTyypit.muutaAste:
assertEq('muutaAste argumentit', argumentit.length, 2);
let [vanhaAste, uusiAste] = argumentit;
luokkaAsteet.muuta(vanhaAste, uusiAste);
// Muuta muutetut luokka-asteet tunneissa
for (let [_, tunti] of tunnit.tunnit) {
for (let luokka of tunti.luokat.alkiot()) {
let luokanAste = parseInt(luokka[0]);
if (luokanAste === vanhaAste) {
let uusiLuokka = `${uusiAste}${luokka.slice(1)}`;
tunti.luokat.poista(luokka);
tunti.luokat.lisää(uusiLuokka);
}
}
}
break;
case tapahtumaTyypit.lisääLuokka:
assertEq('lisääLuokka argumentit', argumentit.length, 1);
luokkaAsteet.asteet[argumentit[0]].lisää();
break;
case tapahtumaTyypit.poistaLuokka:
assertEq('poistaLuokka argumentit', argumentit.length, 1);
let [aste] = argumentit;
luokkaAsteet.asteet[aste].poista();
// Poista luokka jota ei enää ole asteella tunneista
for (let [_, tunti] of tunnit.tunnit) {
for (let luokka of tunti.luokat.alkiot()) {
if (luokkaAsteet.luokat().indexOf(luokka) === -1) {
tunti.luokat.poista(luokka);
}
}
}
break;
case tapahtumaTyypit.lisääOpettaja:
assertEq('lisääOpettaja argumentit', argumentit.length, 2);
opettajat.lisää(...argumentit);
break;
case tapahtumaTyypit.poistaOpettaja:
assertEq('poistaOpettaja argumentit', argumentit.length, 1);
let [poistettuOpettaja] = argumentit;
opettajat.poista(poistettuOpettaja);
// Poista opettaja joita ei enää ole tunneista
for (let [_, tunti] of tunnit.tunnit) {
tunti.opettajaLyhenteet.poista(poistettuOpettaja);
}
break;
case tapahtumaTyypit.lisääTila:
assertEq('lisääTila argumentit', argumentit.length, 1);
paluuarvo = tilat.lisää(...argumentit);
break;
case tapahtumaTyypit.poistaTila:
assertEq('poistaTila argumentit', argumentit.length, 1);
let [poistettuTila] = argumentit;
tilat.poista(poistettuTila);
for (let [_, tunti] of tunnit.tunnit) {
tunti.tilat.poista(poistettuTila);
}
break;
case tapahtumaTyypit.lisääTunti:
assertEq('lisääTunti argumentit', argumentit.length, 4);
paluuarvo = tunnit.lisää(...argumentit);
break;
case tapahtumaTyypit.poistaTunti:
assertEq('poistaTunti argumentit', argumentit.length, 1);
tunnit.poista(...argumentit);
break;
case tapahtumaTyypit.lisääTuntiLuokka:
assertEq('lisääTuntiLuokka argumentit', argumentit.length, 2);
tunnit.tunnit.get(argumentit[0]).luokat.lisää(argumentit[1]);
break;
case tapahtumaTyypit.poistaTuntiLuokka:
assertEq('poistaTuntiLuokka argumentit', argumentit.length, 2);
tunnit.tunnit.get(argumentit[0]).luokat.poista(argumentit[1]);
break;
case tapahtumaTyypit.lisääTuntiOpettaja:
assertEq('lisääTuntiOpettaja argumentit', argumentit.length, 2);
tunnit.tunnit.get(argumentit[0]).opettajaLyhenteet.lisää(argumentit[1]);
break;
case tapahtumaTyypit.poistaTuntiOpettaja:
assertEq('poistaTuntiOpettajat argumentit', argumentit.length, 2);
tunnit.tunnit.get(argumentit[0]).opettajaLyhenteet.poista(argumentit[1]);
break;
case tapahtumaTyypit.lisääTuntiTila:
assertEq('lisääTuntiTila argumentit', argumentit.length, 2);
tunnit.tunnit.get(argumentit[0]).tilat.lisää(argumentit[1]);
break;
case tapahtumaTyypit.poistaTuntiTila:
assertEq('poistaTuntiTila argumentit', argumentit.length, 2);
tunnit.tunnit.get(argumentit[0]).tilat.poista(argumentit[1]);
break;
default:
throw new Error(`tuntematon tapahtumatyyppi ${tyyppi}`);
}
historia.push(new Tapahtuma(tyyppi, argumentit));
tulevaisuus = [];
return paluuarvo;
}
function kumoa() {
if (historia.length === 0) {
return;
}
// Kumoaminen tapahtuu ottamalla historia uusinta tapahtumaa lukuun
// ottamatta ja suorittamalla se siihen asti uudestaan tyhjältä mallilta
let kumottu = historia.pop();
let uusi_tulevaisuus = tulevaisuus.concat(kumottu);
let vanha_historia = historia;
alustaMalli();
for (let {tyyppi, argumentit} of vanha_historia) {
suorita(tyyppi, ...argumentit);
}
tulevaisuus = uusi_tulevaisuus;
}
function teeUudelleen() {
if (tulevaisuus.length === 0) {
return;
}
let {tyyppi, argumentit} = tulevaisuus.pop();
// Tulevaisuus tulee tallentaa, sillä suorita() tuhoaa sen
let uusi_tulevaisuus = tulevaisuus;
suorita(tyyppi, ...argumentit);
tulevaisuus = uusi_tulevaisuus;
}
testi('mallin alustaminen', () => {
historia = undefined;
tulevaisuus = undefined;
luokkaAsteet = undefined;
opettajat = undefined;
tilat = undefined;
tunnit = undefined;
alustaMalli();
assertNe('historia', historia, undefined);
assertNe('tulevaisuus', tulevaisuus, undefined);
assertNe('luokkaAsteet', luokkaAsteet, undefined);
assertNe('opettajat', opettajat, undefined);
assertNe('tilat', tilat, undefined);
assertNe('tunnit', tunnit, undefined);
});
testi('tapahtumahistoria', () => {
alustaMalli();
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.poistaAste, 1);
assertEq('historia.length', historia.length, 2);
assertEq('historia[0].tyyppi', historia[0].tyyppi, tapahtumaTyypit.lisääAste);
assertEq('historia[0].argumentit.length', historia[0].argumentit.length, 0);
assertEq('historia[1].tyyppi', historia[1].tyyppi, tapahtumaTyypit.poistaAste);
assertEq('historia[1].argumentit.length', historia[1].argumentit.length, 1);
assertEq('historia[1].argumentit[0]', historia[1].argumentit[0], 1);
assertThrow('poistaAste 1', 'luokka-astetta 1 ei ole olemassa', () => {
suorita(tapahtumaTyypit.poistaAste, 1);
});
assertEq('historia.length poikkeuksen jälkeen', historia.length, 2);
alustaMalli();
});
testi('kumoamiminen', () => {
alustaMalli();
kumoa();
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.lisääLuokka, 1);
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.lisääLuokka, 2);
suorita(tapahtumaTyypit.lisääLuokka, 1);
assertEq('aluksi 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B', 'C']);
assertEq('aluksi 2. aste', luokkaAsteet.asteet[2].luokat(), ['A', 'B']);
kumoa();
assertEq('kerran 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B']);
assertEq('kerran 2. aste', luokkaAsteet.asteet[2].luokat(), ['A', 'B']);
kumoa();
assertEq('kahdesti 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B']);
assertEq('kahdesti 2. aste', luokkaAsteet.asteet[2].luokat(), ['A']);
kumoa();
assertEq('kolmesti 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B']);
assertEq('kolmesti 2. aste', luokkaAsteet.asteet[2], undefined);
kumoa();
assertEq('neljästi 1. aste', luokkaAsteet.asteet[1].luokat(), ['A']);
kumoa();
assertEq('viidesti 1. aste', luokkaAsteet.asteet[1], undefined);
alustaMalli();
});
testi('uudelleen tekeminen', () => {
alustaMalli();
teeUudelleen();
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.lisääLuokka, 1);
suorita(tapahtumaTyypit.lisääLuokka, 2);
suorita(tapahtumaTyypit.lisääLuokka, 2);
kumoa();
kumoa();
kumoa();
assertEq('aluksi 1. aste', luokkaAsteet.asteet[1].luokat(), ['A']);
assertEq('aluksi 2. aste', luokkaAsteet.asteet[2].luokat(), ['A']);
teeUudelleen();
assertEq('kerran 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B']);
assertEq('kerran 2. aste', luokkaAsteet.asteet[2].luokat(), ['A']);
teeUudelleen();
assertEq('kahdesti 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B']);
assertEq('kahdesti 2. aste', luokkaAsteet.asteet[2].luokat(), ['A', 'B']);
suorita(tapahtumaTyypit.lisääLuokka, 1);
teeUudelleen();
assertEq('kolmesti 1. aste', luokkaAsteet.asteet[1].luokat(), ['A', 'B', 'C']);
assertEq('kolmesti 2. aste', luokkaAsteet.asteet[2].luokat(), ['A', 'B']);
alustaMalli();
});
testi('asteiden käsittely', () => {
alustaMalli();
assertEq('lisää', suorita(tapahtumaTyypit.lisääAste), 1);
suorita(tapahtumaTyypit.muutaAste, 1, 2);
assertEq('muutettua seuraava aste', luokkaAsteet.seuraavaAste(), 3);
suorita(tapahtumaTyypit.poistaAste, 2);
assertEq('lopuksi seuraava aste', luokkaAsteet.seuraavaAste(), 1);
alustaMalli();
});
testi('luokkien käsittely', () => {
alustaMalli();
suorita(tapahtumaTyypit.lisääAste);
assertEq('aluksi', luokkaAsteet.asteet[1].luokat(), ['A']);
suorita(tapahtumaTyypit.lisääLuokka, 1);
assertEq('lisättyä', luokkaAsteet.asteet[1].luokat(), ['A', 'B']);
suorita(tapahtumaTyypit.poistaLuokka, 1);
assertEq('poistettua', luokkaAsteet.asteet[1].luokat(), ['A']);
alustaMalli();
});
testi('opettajien käsittely', () => {
alustaMalli();
assertEq('aluksi', opettajat.opettajat(), []);
suorita(tapahtumaTyypit.lisääOpettaja, 'MM', 'Maija Meikäläinen');
assertEq('lisättyä', opettajat.opettajat(), [['MM', 'Maija Meikäläinen']]);
suorita(tapahtumaTyypit.poistaOpettaja, 'MM');
assertEq('poistettua', opettajat.opettajat(), []);
});
testi('tilojen käsittely', () => {
alustaMalli();
assertEq('aluksi', tilat.tilat(), []);
assertEq('1A', suorita(tapahtumaTyypit.lisääTila, '1A'), 0);
assertEq('lisättyä', tilat.tilat(), [[0, '1A']]);
suorita(tapahtumaTyypit.poistaTila, 0);
assertEq('poistettua', tilat.tilat(), []);
alustaMalli();
});
testi('tuntien käsittely', () => {
alustaMalli();
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.lisääAste);
suorita(tapahtumaTyypit.lisääAste, 5);
suorita(tapahtumaTyypit.lisääLuokka, 5);
suorita(tapahtumaTyypit.lisääOpettaja, 'KV', 'Kari Virtanen');
suorita(tapahtumaTyypit.lisääOpettaja, 'AS', 'Aili Savolainen');
suorita(tapahtumaTyypit.lisääOpettaja, 'MM', 'Maija Meikäläinen');
suorita(tapahtumaTyypit.lisääOpettaja, 'MaM', 'Matti Meikäläinen');
suorita(tapahtumaTyypit.lisääTila, '1A');
suorita(tapahtumaTyypit.lisääTila, '5B');
suorita(tapahtumaTyypit.lisääTila, 'Käsityöluokka');
suorita(tapahtumaTyypit.lisääTila, '5A');
assertEq('aluksi', tunnit.järjestyksessä(), []);
assertEq('historia',
suorita(tapahtumaTyypit.lisääTunti, ['Historia'], ['5B'], ['KV'], [1]),
0
);
assertEq('äidinkieli',
suorita(tapahtumaTyypit.lisääTunti, ['Äidinkieli'], ['1A'], ['AS'], [0]),
1
);
assertEq('kuvataide',
suorita(tapahtumaTyypit.lisääTunti, ['Kuvataide'], ['5A'], ['MM'], [2]),
2
);
assertEq('lisättyä pituus', tunnit.järjestyksessä().length, 3);
suorita(tapahtumaTyypit.poistaAste, 1);
assertEq('aste poistettua 0', tunnit.järjestyksessä()[0][1].luokat.alkiot(), ['5B']);
assertEq('aste poistettua 1', tunnit.järjestyksessä()[1][1].luokat.alkiot(), ['5A']);
assertEq('aste poistettua 2', tunnit.järjestyksessä()[2][1].luokat.alkiot(), []);
suorita(tapahtumaTyypit.muutaAste, 5, 6);
assertEq('aste muutettua 0', tunnit.järjestyksessä()[0][1].luokat.alkiot(), ['6B']);
assertEq('aste muutettua 1', tunnit.järjestyksessä()[1][1].luokat.alkiot(), ['6A']);
assertEq('aste muutettua 2', tunnit.järjestyksessä()[2][1].luokat.alkiot(), []);
suorita(tapahtumaTyypit.poistaLuokka, 6);
assertEq('luokka poistettua 0', tunnit.järjestyksessä()[0][1].luokat.alkiot(), []);
assertEq('luokka poistettua 1', tunnit.järjestyksessä()[1][1].luokat.alkiot(), ['6A']);
assertEq('luokka poistettua 1', tunnit.järjestyksessä()[2][1].luokat.alkiot(), []);
suorita(tapahtumaTyypit.poistaOpettaja, 'KV');
assertEq('opettaja poistettua 0', tunnit.järjestyksessä()[0][1].opettajaLyhenteet.alkiot(), []);
assertEq('opettaja poistettua 1', tunnit.järjestyksessä()[1][1].opettajaLyhenteet.alkiot(), ['MM']);
assertEq('opettaja poistettua 2', tunnit.järjestyksessä()[2][1].opettajaLyhenteet.alkiot(), ['AS']);
suorita(tapahtumaTyypit.poistaTila, 1);
assertEq('tila poistettua 0', tunnit.järjestyksessä()[0][1].tilat.alkiot(), []);
assertEq('tila poistettua 1', tunnit.järjestyksessä()[1][1].tilat.alkiot(), [2]);
assertEq('tila poistettua 2', tunnit.järjestyksessä()[2][1].tilat.alkiot(), [0]);
suorita(tapahtumaTyypit.lisääTuntiLuokka, 0, '2A');
assertEq('luokka lisättyä tunnille 0', tunnit.järjestyksessä()[0][1].luokat.alkiot(), ['2A']);
assertEq('luokka lisättyä tunnille 1', tunnit.järjestyksessä()[1][1].luokat.alkiot(), ['6A']);
assertEq('luokka lisättyä tunnille 2', tunnit.järjestyksessä()[2][1].luokat.alkiot(), []);
suorita(tapahtumaTyypit.poistaTuntiLuokka, 2, '6A');
assertEq('luokka poistettua tunnilta 0', tunnit.järjestyksessä()[0][1].luokat.alkiot(), ['2A']);
assertEq('luokka poistettua tunnilta 1', tunnit.järjestyksessä()[1][1].luokat.alkiot(), []);
assertEq('luokka poistettua tunnilta 2', tunnit.järjestyksessä()[2][1].luokat.alkiot(), []);
suorita(tapahtumaTyypit.lisääTuntiOpettaja, 0, 'MaM');
assertEq('opettaja lisättyä tunnille 0', tunnit.järjestyksessä()[0][1].opettajaLyhenteet.alkiot(), ['MaM']);
assertEq('opettaja lisättyä tunnille 1', tunnit.järjestyksessä()[1][1].opettajaLyhenteet.alkiot(), ['MM']);
assertEq('opettaja lisättyä tunnille 2', tunnit.järjestyksessä()[2][1].opettajaLyhenteet.alkiot(), ['AS']);
suorita(tapahtumaTyypit.poistaTuntiOpettaja, 2, 'MM');
assertEq('opettaja poistettua tunnilta 0', tunnit.järjestyksessä()[0][1].opettajaLyhenteet.alkiot(), ['MaM']);
assertEq('opettaja poistettua tunnilta 1', tunnit.järjestyksessä()[1][1].opettajaLyhenteet.alkiot(), []);
assertEq('opettaja poistettua tunnilta 2', tunnit.järjestyksessä()[2][1].opettajaLyhenteet.alkiot(), ['AS']);
suorita(tapahtumaTyypit.lisääTuntiTila, 0, 3);
assertEq('tila lisäätyä tunnille 0', tunnit.järjestyksessä()[0][1].tilat.alkiot(), [3]);
assertEq('tila lisäätyä tunnille 1', tunnit.järjestyksessä()[1][1].tilat.alkiot(), [2]);
assertEq('tila lisäätyä tunnille 2', tunnit.järjestyksessä()[2][1].tilat.alkiot(), [0]);
suorita(tapahtumaTyypit.poistaTuntiTila, 1, 0);
assertEq('tila poistettua tunnilta 0', tunnit.järjestyksessä()[0][1].tilat.alkiot(), [3]);
assertEq('tila poistettua tunnilta 1', tunnit.järjestyksessä()[1][1].tilat.alkiot(), [2]);
assertEq('tila poistettua tunnilta 2', tunnit.järjestyksessä()[2][1].tilat.alkiot(), []);
suorita(tapahtumaTyypit.poistaTunti, 0);
assertEq('poistettua pituus', tunnit.järjestyksessä().length, 2);
alustaMalli();
});