Toteuta opettajat

This commit is contained in:
Juhani Krekelä 2023-08-07 18:51:11 +03:00
parent db99ada4dd
commit 80f235ad57
4 changed files with 200 additions and 2 deletions

View File

@ -40,6 +40,9 @@
margin: 0 0.5em;
display: inline;
}
#opettajat > li > span {
margin-left: 0.5em;
}
.piilotettu {
display: none;
}
@ -49,7 +52,7 @@
<input id="kumoa" type="button" value="Kumoa">
<input id="tee-uudelleen" type="button" value="Tee uudelleen">
<details class="ruutu" id="luokat" open>
<details class="ruutu" open>
<summary>Luokat</summary>
<div>
<input id="lisää-luokka-aste" type="button" value="+ Aste">
@ -57,6 +60,21 @@
</div>
</details>
<details class="ruutu" open>
<summary>Opettajat</summary>
<div>
<form id="lisää-opettaja">
<span class="virhe piilotettu" id="opettaja-virhe">virhe</span>
<label for="opettaja-nimi">Nimi</label>
<input id="opettaja-nimi" type="text" required>
<label for="opettaja-lyhenne">Lyhenne</label>
<input id="opettaja-lyhenne" type="text">
<input type="submit" value="+">
</form>
<ul id="opettajat"></ul>
</div>
</details>
<script src="testit.js"></script>
<script src="tietotyypit.js"></script>
<script src="tietomalli.js"></script>

View File

@ -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';

View File

@ -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(), []);
});

View File

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