From c7b7d726d98d37c29b63921d8a4eb25618a05691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Tue, 8 Aug 2023 19:08:44 +0300 Subject: [PATCH] Toteuta tunnit ilman usean luokan tai opettajan tukea --- käyttöliittymä.js | 68 ++++++++++++++++++++++--- tietomalli.js | 127 +++++++++++++++++++++++++++++++++++++++++++--- tietotyypit.js | 106 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+), 12 deletions(-) diff --git a/käyttöliittymä.js b/käyttöliittymä.js index 20aafc5..0cdac3b 100644 --- a/käyttöliittymä.js +++ b/käyttöliittymä.js @@ -10,7 +10,7 @@ document.getElementById('tee-uudelleen').addEventListener('click', () => { document.getElementById('lisää-luokka-aste').addEventListener('click', () => { suorita(tapahtumaTyypit.lisääAste); - piirräLuokat(); + piirräKaikki(); }); document.getElementById('lisää-opettaja').addEventListener('submit', (tapahtuma) => { @@ -34,7 +34,7 @@ document.getElementById('lisää-opettaja').addEventListener('submit', (tapahtum lyhenneElementti.value = ''; lyhenneElementti.placeholder = ''; virheElementti.classList.add('piilotettu'); - piirräOpettajat(); + piirräKaikki(); } else if (toinenNimi === nimi) { virheElementti.firstChild.textContent = `Opettaja ${nimi} on jo listassa`; @@ -61,9 +61,31 @@ document.getElementById('opettaja-nimi').addEventListener('input', () => { document.getElementById('opettaja-lyhenne').placeholder = lyhenne; }); +document.getElementById('lisää-tunti').addEventListener('submit', (tapahtuma) => { + tapahtuma.preventDefault(); + let nimiElementti = document.getElementById('tunti-nimi'); + let luokkaElementti = document.getElementById('tunti-luokka'); + let opettajaElementti = document.getElementById('tunti-opettaja'); + let kertaaViikossaElementti = document.getElementById('tunti-kertaa-viikossa'); + + let nimi = nimiElementti.value; + let luokka = luokkaElementti.value; + let opettajaLyhenne = opettajaElementti.value; + let kertaaViikossa = parseInt(kertaaViikossaElementti.value); + suorita(tapahtumaTyypit.lisääTunti, nimi, luokka, opettajaLyhenne, kertaaViikossa); + + nimiElementti.value = ''; + luokkaElementti.value = ''; + opettajaElementti.value = ''; + kertaaViikossaElementti.value = 1; + + piirräKaikki(); +}); + function piirräKaikki() { piirräLuokat(); piirräOpettajat(); + piirräTunnit(); } function piirräLuokat() { @@ -82,6 +104,7 @@ function piirräLuokat() { valinta.appendChild(document.createTextNode(luokka)); tuntiLuokkaValinta.appendChild(valinta); } + tuntiLuokkaValinta.value = ''; vanhaTuntiLuokkaValinta.parentNode.replaceChild( tuntiLuokkaValinta, vanhaTuntiLuokkaValinta @@ -108,7 +131,7 @@ function luoLuokkaAsteListassa(aste) { luokkaAsteListassa.appendChild(luoPainike('+', () => { suorita(tapahtumaTyypit.lisääLuokka, aste); - piirräLuokat(); + piirräKaikki(); })); luokkaAsteListassa.appendChild(luoPainike('-', () => { if (luokkaAsteet.asteet[aste].luokat().length > 1) { @@ -116,7 +139,7 @@ function luoLuokkaAsteListassa(aste) { } else { suorita(tapahtumaTyypit.poistaAste, aste); } - piirräLuokat(); + piirräKaikki(); })); luokkaAsteListassa.appendChild(luoLuokkaLista(aste)); @@ -146,7 +169,7 @@ function luoLuokkaAsteListassa(aste) { let uusiAste = parseInt(asteValitsin.value); if (luokkaAsteet.asteet[uusiAste] === undefined || aste === uusiAste) { suorita(tapahtumaTyypit.muutaAste, aste, uusiAste); - piirräLuokat(); + piirräKaikki(); } else { muokkausVirhe.firstChild.textContent = `Luokka-aste ${uusiAste} on jo olemassa.`; @@ -194,6 +217,7 @@ function piirräOpettajat() { valinta.value = lyhenne; tuntiOpettajaValinta.appendChild(valinta); } + tuntiOpettajaValinta.value = ''; vanhaTuntiOpettajaValinta.parentNode.replaceChild( tuntiOpettajaValinta, vanhaTuntiOpettajaValinta @@ -216,7 +240,7 @@ function luoOpettajaListassa(lyhenne, nimi) { opettajaListassa.appendChild(luoPainike('-', () => { suorita(tapahtumaTyypit.poistaOpettaja, lyhenne); - piirräOpettajat(); + piirräKaikki(); })); let opettajanNimi = document.createElement('span'); @@ -226,6 +250,38 @@ function luoOpettajaListassa(lyhenne, nimi) { return opettajaListassa; } +function piirräTunnit() { + let vanhaTuntiLista = document.getElementById('tunnit'); + let tuntiLista = luoTuntiLista(); + vanhaTuntiLista.parentNode.replaceChild( + tuntiLista, + vanhaTuntiLista + ); +} + +function luoTuntiLista() { + let tuntiLista = document.createElement('ul'); + tuntiLista.id = 'tunnit'; + + for (let [_, tunti] of tunnit.järjestyksessä()) { + let tuntiListassa = document.createElement('li'); + let nimi = tunti.nimi; + let luokat = tunti.luokat.join(', '); + let opettajat = tunti.opettajaLyhenteet.join(', '); + let kertaaViikossa = tunti.kertaaViikossa; + let teksti; + if (kertaaViikossa === 1) { + teksti = `${nimi} ${luokat} ${opettajat}`; + } else { + teksti = `${nimi} ${luokat} ${opettajat} ×${kertaaViikossa}`; + } + tuntiListassa.appendChild(document.createTextNode(teksti)); + tuntiLista.appendChild(tuntiListassa); + } + + return tuntiLista; +} + function luoPainike(teksti, funktio) { let painike = document.createElement('input'); painike.type = 'button'; diff --git a/tietomalli.js b/tietomalli.js index db4a530..a2e0c54 100644 --- a/tietomalli.js +++ b/tietomalli.js @@ -9,6 +9,9 @@ const tapahtumaTyypit = { lisääOpettaja: 'lisääOpettaja', poistaOpettaja: 'poistaOpettaja', + + lisääTunti: 'lisääTunti', + poistaTunti: 'poistaTunti', }; class Tapahtuma { @@ -19,7 +22,7 @@ class Tapahtuma { } let historia, tulevaisuus; -let luokkaAsteet, opettajat; +let luokkaAsteet, opettajat, tunnit; alustaMalli(); function alustaMalli() { @@ -27,6 +30,7 @@ function alustaMalli() { tulevaisuus = []; luokkaAsteet = new LuokkaAsteet(); opettajat = new Opettajat(); + tunnit = new Tunnit(); } function suorita(tyyppi, ...argumentit) { @@ -38,11 +42,38 @@ function suorita(tyyppi, ...argumentit) { break; case tapahtumaTyypit.poistaAste: assertEq('poistaAste argumentit määrä', argumentit.length, 1); - paluuarvo = luokkaAsteet.poista(...argumentit) + let [poistettuAste] = argumentit; + luokkaAsteet.poista(poistettuAste); + // Poista poistettujen luokka-asteiden luokat tunneista + for (let [id, tunti] of tunnit.tunnit) { + let luokat = []; + for (let luokka of tunti.luokat) { + let luokanAste = parseInt(luokka[0]); + if (luokanAste !== poistettuAste) { + luokat.push(luokka); + } + } + tunnit.tunnit.get(id).luokat = luokat; + } break; case tapahtumaTyypit.muutaAste: assertEq('muutaAste argumentit määrä', argumentit.length, 2); - luokkaAsteet.muuta(...argumentit) + let [vanhaAste, uusiAste] = argumentit; + luokkaAsteet.muuta(vanhaAste, uusiAste); + // Muuta muutetut luokka-asteet tunneissa + for (let [id, tunti] of tunnit.tunnit) { + let luokat = []; + for (let luokka of tunti.luokat) { + let luokanAste = parseInt(luokka[0]); + if (luokanAste === vanhaAste) { + let luokanLuokka = luokka.slice(1); + luokat.push(`${uusiAste}${luokanLuokka}`); + } else { + luokat.push(luokka); + } + } + tunnit.tunnit.get(id).luokat = luokat; + } break; case tapahtumaTyypit.lisääLuokka: @@ -51,16 +82,47 @@ function suorita(tyyppi, ...argumentit) { break; case tapahtumaTyypit.poistaLuokka: assertEq('poistaLuokka argumentit määrä', argumentit.length, 1); - luokkaAsteet.asteet[argumentit[0]].poista(); + let [aste] = argumentit; + luokkaAsteet.asteet[aste].poista(); + // Poista luokka jota ei enää ole asteella tunneista + for (let [id, tunti] of tunnit.tunnit) { + let luokat = []; + for (let luokka of tunti.luokat) { + if (luokkaAsteet.luokat().indexOf(luokka) !== -1) { + luokat.push(luokka); + } + } + tunnit.tunnit.get(id).luokat = luokat; + } break; case tapahtumaTyypit.lisääOpettaja: assertEq('lisääOpettaja argumentit määrä', argumentit.length, 2); - opettajat.lisää(argumentit[0], argumentit[1]); + opettajat.lisää(...argumentit); break; case tapahtumaTyypit.poistaOpettaja: assertEq('poistaOpettaja argumentit määrä', argumentit.length, 1); - opettajat.poista(argumentit[0]); + let [poistettuOpettaja] = argumentit; + opettajat.poista(poistettuOpettaja); + // Poista opettaja joita ei enää ole tunneista + for (let [id, tunti] of tunnit.tunnit) { + let opettajaLyhenteet = []; + for (let opettajaLyhenne of tunti.opettajaLyhenteet) { + if (opettajaLyhenne !== poistettuOpettaja) { + opettajaLyhenteet.push(opettajaLyhenne); + } + } + tunnit.tunnit.get(id).opettajaLyhenteet = opettajaLyhenteet; + } + break; + + case tapahtumaTyypit.lisääTunti: + assertEq('lisääTunti argumentit määrä', argumentit.length, 4); + paluuarvo = tunnit.lisää(...argumentit); + break; + case tapahtumaTyypit.poistaTunti: + assertEq('poistaTunti argumentit määrä', argumentit.length, 1); + tunnit.poista(...argumentit); break; default: @@ -105,11 +167,13 @@ testi('mallin alustaminen', () => { tulevaisuus = undefined; luokkaAsteet = undefined; opettajat = undefined; + tunnit = undefined; alustaMalli(); assertNe('historia', historia, undefined); assertNe('tulevaisuus', tulevaisuus, undefined); assertNe('luokkaAsteet', luokkaAsteet, undefined); assertNe('opettajat', opettajat, undefined); + assertNe('tunnit', tunnit, undefined); }); testi('tapahtumahistoria', () => { @@ -210,3 +274,54 @@ testi('opettajien käsittely', () => { suorita(tapahtumaTyypit.poistaOpettaja, 'MM'); assertEq('poistettua', opettajat.opettajat(), []); }); + +testi('tuntien käsittely', () => { + alustaMalli(); + 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'); + 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', 3), + 1 + ); + assertEq('kuvataide', + suorita(tapahtumaTyypit.lisääTunti, 'Kuvataide', '5A', 'MM', 1), + 2 + ); + assertEq('lisättyä pituus', tunnit.järjestyksessä().length, 3); + + suorita(tapahtumaTyypit.poistaAste, 1); + assertEq('aste poistettua 0', tunnit.järjestyksessä()[0][1].luokat, ['5B']); + assertEq('aste poistettua 1', tunnit.järjestyksessä()[1][1].luokat, ['5A']); + assertEq('aste poistettua 2', tunnit.järjestyksessä()[2][1].luokat, []); + + suorita(tapahtumaTyypit.muutaAste, 5, 6); + assertEq('aste muutettua 0', tunnit.järjestyksessä()[0][1].luokat, ['6B']); + assertEq('aste muutettua 1', tunnit.järjestyksessä()[1][1].luokat, ['6A']); + assertEq('aste muutettua 2', tunnit.järjestyksessä()[2][1].luokat, []); + + suorita(tapahtumaTyypit.poistaLuokka, 6); + assertEq('luokka poistettua 0', tunnit.järjestyksessä()[0][1].luokat, []); + assertEq('luokka poistettua 1', tunnit.järjestyksessä()[1][1].luokat, ['6A']); + assertEq('luokka poistettua 1', tunnit.järjestyksessä()[2][1].luokat, []); + + suorita(tapahtumaTyypit.poistaOpettaja, 'KV'); + assertEq('opettaja poistettua 0', tunnit.järjestyksessä()[0][1].opettajaLyhenteet, []); + assertEq('opettaja poistettua 1', tunnit.järjestyksessä()[1][1].opettajaLyhenteet, ['MM']); + assertEq('opettaja poistettua 2', tunnit.järjestyksessä()[2][1].opettajaLyhenteet, ['AS']); + + suorita(tapahtumaTyypit.poistaTunti, 0); + assertEq('poistettua pituus', tunnit.järjestyksessä().length, 2); + + alustaMalli(); + // TODO: Luokkien ja opettajien listojen päivitys +}); diff --git a/tietotyypit.js b/tietotyypit.js index 92caef7..5df1971 100644 --- a/tietotyypit.js +++ b/tietotyypit.js @@ -109,6 +109,71 @@ class Opettajat { } } +class Tunti { + constructor(nimi, luokat, opettajaLyhenteet, kertaaViikossa) { + this.nimi = nimi; + this.luokat = luokat; + this.opettajaLyhenteet = opettajaLyhenteet; + this.kertaaViikossa = kertaaViikossa; + } +} + +class Tunnit { + tunnit = new Map(); + #seuraavaId = 0; + + lisää(nimi, luokka, opettajaLyhenne, kertaaViikossa) { + let id = this.#seuraavaId++; + this.tunnit.set( + id, + new Tunti(nimi, [luokka], [opettajaLyhenne], kertaaViikossa) + ); + return id; + } + + poista(id) { + if (!this.tunnit.delete(id)) { + throw new Error(`ei tuntia ID:llä ${id}`); + } + } + + järjestyksessä() { + let tunnit = []; + for (let [id, tunti] of this.tunnit) { + tunnit.push([id, tunti]); + } + tunnit.sort((a, b) => { + let tulos = vertaa(a[1].nimi, b[1].nimi); + // TODO: Korjaa niin, että osaa verrata okein listoja + if (tulos === 0) { + tulos = vertaa(a[1].luokat, b[1].luokat); + } + // TODO: Korjaa niin, että osaa verrata okein listoja + if (tulos === 0) { + tulos = vertaa(a[1].opettajaLyhenteet, b[1].opettajaLyhenteet); + } + if (tulos === 0) { + tulos = vertaa(a[1].kertaaViikossa, b[1].kertaaViikossa); + } + if (tulos === 0) { + tulos = vertaa(a[0], b[0]); + } + return tulos; + }); + return tunnit; + } +} + +function vertaa(a, b) { + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } +} + testi('seuraava aste', () => { let luokkaAsteet = new LuokkaAsteet(); assertEq('aluksi', luokkaAsteet.seuraavaAste(), 1); @@ -228,3 +293,44 @@ testi('opettajien lyhenteen', () => { assertEq('MaM', opettajat.lyhenne('MaM'), 'Matti Meikäläinen'); assertEq('ZZ', opettajat.lyhenne('ZZ'), undefined); }); + +testi('tuntien lisääminen', () => { + let tunnit = new Tunnit(); + assertEq('historia', tunnit.lisää('Historia', '5B', 'KV', 1), 0); + assertEq('äidinkieli', tunnit.lisää('Äidinkieli', '1A', 'AS', 3), 1); + assertEq('historia nimi', tunnit.tunnit.get(0).nimi, 'Historia'); + assertEq('historia luokat', tunnit.tunnit.get(0).luokat, ['5B']); + assertEq('historia opettajat', tunnit.tunnit.get(0).opettajaLyhenteet, ['KV']); + assertEq('historia viikossa', tunnit.tunnit.get(0).kertaaViikossa, 1); + assertEq('äidinkieli nimi', tunnit.tunnit.get(1).nimi, 'Äidinkieli'); + assertEq('äidinkieli luokat', tunnit.tunnit.get(1).luokat, ['1A']); + assertEq('äidinkieli opettajat', tunnit.tunnit.get(1).opettajaLyhenteet, ['AS']); + assertEq('äidinkieli viikossa', tunnit.tunnit.get(1).kertaaViikossa, 3); +}); + +testi('tuntien poistaminen', () => { + let tunnit = new Tunnit(); + tunnit.lisää('Historia', '5B', 'KV', 1); + tunnit.lisää('Äidinkieli', '1B', 'AS', 3); + tunnit.poista(0); + tunnit.poista(1); + assertThrow('jo poistettu', 'ei tuntia ID:llä 1', () => { + tunnit.poista(1); + }); + assertEq('kuvataide', tunnit.lisää('Kuvataide', '6A', 'MM', 1), 2); +}); + +testi('tuntien järjestys', () => { + let tunnit = new Tunnit(); + tunnit.lisää('Historia', '5B', 'KV', 1); + tunnit.lisää('Äidinkieli', '1B', 'AS', 3); + assertEq('aluksi', tunnit.järjestyksessä()[0][1].nimi, 'Historia'); + tunnit.tunnit.get(1).nimi = 'Historia'; + assertEq('sama nimi', tunnit.järjestyksessä()[0][1].luokat, ['1B']); + tunnit.tunnit.get(0).luokat = ['1B']; + assertEq('sama luokka', tunnit.järjestyksessä()[0][1].opettajaLyhenteet, ['AS']); + tunnit.tunnit.get(0).opettajaLyhenteet = ['AS']; + assertEq('sama opettaja', tunnit.järjestyksessä()[0][1].kertaaViikossa, 1); + tunnit.tunnit.get(1).kertaaViikossa = 1; + assertEq('yhtä monta kertaa viikossa', tunnit.järjestyksessä()[0][0], 0); +});