diff --git a/index.html b/index.html index edd0a52..07808d4 100644 --- a/index.html +++ b/index.html @@ -40,6 +40,9 @@ margin: 0 0.5em; display: inline; } + #opettajat > li > span { + margin-left: 0.5em; + } .piilotettu { display: none; } @@ -49,7 +52,7 @@ -
+
Luokat
@@ -57,6 +60,21 @@
+
+ Opettajat +
+
+ virhe + + + + + +
+
    +
    +
    + diff --git a/käyttöliittymä.js b/käyttöliittymä.js index c260b6d..6df350d 100644 --- a/käyttöliittymä.js +++ b/käyttöliittymä.js @@ -13,8 +13,52 @@ document.getElementById('lisää-luokka-aste').addEventListener('click', () => { piirräLuokat(); }); +document.getElementById('lisää-opettaja').addEventListener('submit', (tapahtuma) => { + tapahtuma.preventDefault(); + let virheElementti = document.getElementById('opettaja-virhe'); + let nimiElementti = document.getElementById('opettaja-nimi'); + let lyhenneElementti = document.getElementById('opettaja-lyhenne'); + + let nimi = nimiElementti.value; + let lyhenne = lyhenneElementti.value; + // Jos käyttäjä ei ole manuallisesti lisännyt lyhennettä, käytä + // automaattisesti luotua. + if (lyhenne === '') { + lyhenne = lyhenneElementti.placeholder; + } + + if (opettajat.lyhenne(lyhenne) === undefined) { + suorita(tapahtumaTyypit.lisääOpettaja, lyhenne, nimi); + nimiElementti.value = ''; + lyhenneElementti.value = ''; + lyhenneElementti.placeholder = ''; + virheElementti.classList.add('piilotettu'); + piirräOpettajat(); + } else { + virheElementti.firstChild.textContent = + `Jokaisella opettajalla tulee olla oma lyhenne. Lyhenne ${lyhenne} on jo käytössä opettajalla ${nimi}`; + virheElementti.classList.remove('piilotettu'); + } +}); + +document.getElementById('opettaja-nimi').addEventListener('input', () => { + let osat = document.getElementById('opettaja-nimi').value.split(' '); + let lyhenne = []; + for (let osa of osat) { + if (osa.length !== 0) { + // TODO: Toimii vain yhden koodipisteen pituisilla + // grafeemiklustereilla. + let koodi = osa.codePointAt(0); + lyhenne.push(String.fromCodePoint(koodi)); + } + } + lyhenne = lyhenne.join(''); + document.getElementById('opettaja-lyhenne').placeholder = lyhenne; +}); + function piirräKaikki() { piirräLuokat(); + piirräOpettajat(); } function piirräLuokat() { @@ -115,6 +159,41 @@ function luoLuokkaLista(aste) { return luokkaLista; } +function piirräOpettajat() { + let vanhaOpettajaLista = document.getElementById('opettajat'); + let opettajaLista = luoOpettajaLista(); + vanhaOpettajaLista.parentNode.replaceChild( + opettajaLista, + vanhaOpettajaLista + ); +} + +function luoOpettajaLista() { + let opettajaLista = document.createElement('ul'); + opettajaLista.id = 'opettajat'; + + for (let [lyhenne, nimi] of opettajat.opettajat()) { + opettajaLista.appendChild(luoOpettajaListassa(lyhenne, nimi)); + } + + return opettajaLista; +} + +function luoOpettajaListassa(lyhenne, nimi) { + let opettajaListassa = document.createElement('li'); + + opettajaListassa.appendChild(luoPainike('-', () => { + suorita(tapahtumaTyypit.poistaOpettaja, lyhenne); + piirräOpettajat(); + })); + + let opettajanNimi = document.createElement('span'); + opettajanNimi.appendChild(document.createTextNode(`${lyhenne} ${nimi}`)); + opettajaListassa.appendChild(opettajanNimi); + + return opettajaListassa; +} + function luoPainike(teksti, funktio) { let painike = document.createElement('input'); painike.type = 'button'; diff --git a/tietomalli.js b/tietomalli.js index 63d292b..db4a530 100644 --- a/tietomalli.js +++ b/tietomalli.js @@ -6,6 +6,9 @@ const tapahtumaTyypit = { lisääLuokka: 'lisääLuokka', poistaLuokka: 'poistaLuokka', + + lisääOpettaja: 'lisääOpettaja', + poistaOpettaja: 'poistaOpettaja', }; class Tapahtuma { @@ -16,13 +19,14 @@ class Tapahtuma { } let historia, tulevaisuus; -let luokkaAsteet; +let luokkaAsteet, opettajat; alustaMalli(); function alustaMalli() { historia = []; tulevaisuus = []; luokkaAsteet = new LuokkaAsteet(); + opettajat = new Opettajat(); } function suorita(tyyppi, ...argumentit) { @@ -40,6 +44,7 @@ function suorita(tyyppi, ...argumentit) { assertEq('muutaAste argumentit määrä', argumentit.length, 2); luokkaAsteet.muuta(...argumentit) break; + case tapahtumaTyypit.lisääLuokka: assertEq('lisääLuokka argumentit määrä', argumentit.length, 1); luokkaAsteet.asteet[argumentit[0]].lisää(); @@ -48,6 +53,16 @@ function suorita(tyyppi, ...argumentit) { assertEq('poistaLuokka argumentit määrä', argumentit.length, 1); luokkaAsteet.asteet[argumentit[0]].poista(); break; + + case tapahtumaTyypit.lisääOpettaja: + assertEq('lisääOpettaja argumentit määrä', argumentit.length, 2); + opettajat.lisää(argumentit[0], argumentit[1]); + break; + case tapahtumaTyypit.poistaOpettaja: + assertEq('poistaOpettaja argumentit määrä', argumentit.length, 1); + opettajat.poista(argumentit[0]); + break; + default: throw new Error(`tuntematon tapahtumatyyppi ${tyyppi}`); } @@ -89,10 +104,12 @@ testi('mallin alustaminen', () => { historia = undefined; tulevaisuus = undefined; luokkaAsteet = undefined; + opettajat = undefined; alustaMalli(); assertNe('historia', historia, undefined); assertNe('tulevaisuus', tulevaisuus, undefined); assertNe('luokkaAsteet', luokkaAsteet, undefined); + assertNe('opettajat', opettajat, undefined); }); testi('tapahtumahistoria', () => { @@ -184,3 +201,12 @@ testi('luokkien käsittely', () => { 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(), []); +}); diff --git a/tietotyypit.js b/tietotyypit.js index 2f0f9c5..7eb5e3f 100644 --- a/tietotyypit.js +++ b/tietotyypit.js @@ -70,6 +70,33 @@ class LuokkaAsteet { } } +class Opettajat { + #opettajat = new Map(); + + opettajat() { + let lista = Array.from(this.#opettajat.entries()); + lista.sort(); + return lista; + } + + lyhenne(lyhenne) { + return this.#opettajat.get(lyhenne); + } + + lisää(lyhenne, nimi) { + if (this.#opettajat.has(lyhenne)) { + throw new Error(`opettaja on jo olemassa lyhenteellä ${lyhenne}`); + } + this.#opettajat.set(lyhenne, nimi); + } + + poista(lyhenne) { + if (!this.#opettajat.delete(lyhenne)) { + throw new Error(`ei opettajaa lyhenteellä ${lyhenne}`); + } + } +} + testi('seuraava aste', () => { let luokkaAsteet = new LuokkaAsteet(); assertEq('aluksi', luokkaAsteet.seuraavaAste(), 1); @@ -138,3 +165,51 @@ testi('luokkien poistaminen', () => { }); assertEq('poistettua', aste.luokat(), ['A']); }); + +testi('opettajien lisääminen', () => { + let opettajat = new Opettajat(); + assertEq('aluksi', opettajat.opettajat(), []); + opettajat.lisää('MM', 'Maija Meikäläinen'); + opettajat.lisää('AS', 'Aili Savolainen'); + opettajat.lisää('KV', 'Kari Virtanen'); + assertThrow('sama lyhenne', 'opettaja on jo olemassa lyhenteellä MM', () => { + opettajat.lisää('MM', 'Matti Meikäläinen'); + }); + opettajat.lisää('MaM', 'Matti Meikäläinen'); + assertEq('lisättyä', opettajat.opettajat(), [ + ['AS', 'Aili Savolainen'], + ['KV', 'Kari Virtanen'], + ['MM', 'Maija Meikäläinen'], + ['MaM', 'Matti Meikäläinen'], + ]); +}); + +testi('opettajien poistaminen', () => { + let opettajat = new Opettajat(); + opettajat.lisää('MM', 'Maija Meikäläinen'); + opettajat.lisää('AS', 'Aili Savolainen'); + opettajat.lisää('KV', 'Kari Virtanen'); + opettajat.lisää('MaM', 'Matti Meikäläinen'); + opettajat.poista('MM'); + assertThrow('jo poistettu', 'ei opettajaa lyhenteellä MM', () => { + opettajat.poista('MM'); + }); + assertEq('poistettua', opettajat.opettajat(), [ + ['AS', 'Aili Savolainen'], + ['KV', 'Kari Virtanen'], + ['MaM', 'Matti Meikäläinen'], + ]); +}); + +testi('opettajien lyhenteen', () => { + let opettajat = new Opettajat(); + opettajat.lisää('MM', 'Maija Meikäläinen'); + opettajat.lisää('AS', 'Aili Savolainen'); + opettajat.lisää('KV', 'Kari Virtanen'); + opettajat.lisää('MaM', 'Matti Meikäläinen'); + assertEq('MM', opettajat.lyhenne('MM'), 'Maija Meikäläinen'); + assertEq('AS', opettajat.lyhenne('AS'), 'Aili Savolainen'); + assertEq('KV', opettajat.lyhenne('KV'), 'Kari Virtanen'); + assertEq('MaM', opettajat.lyhenne('MaM'), 'Matti Meikäläinen'); + assertEq('ZZ', opettajat.lyhenne('ZZ'), undefined); +});