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
+
+
+
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);
+});