lukujarjestaja/tietotyypit.js

231 lines
6.2 KiB
JavaScript

'use strict';
class LuokkaAste {
#luokat = 1;
luokat() {
// Tee lista, jossa on #luokat ensimmäistä isoa kirjainta
let luokat = [];
for (let i = 0; i < this.#luokat; i++) {
luokat.push(String.fromCharCode(65 + i));
}
return luokat;
}
lisää() {
this.#luokat++;
}
poista() {
if (this.#luokat <= 1) {
throw new Error('viimeistä luokkaa ei voi poistaa asteelta');
}
this.#luokat--;
}
}
class LuokkaAsteet {
asteet = [];
luokat() {
let luokat = [];
for (let aste = 0; aste < this.asteet.length; aste++) {
if (this.asteet[aste] !== undefined) {
for (let luokka of this.asteet[aste].luokat()) {
luokat.push(`${aste}${luokka}`);
}
}
}
return luokat;
}
seuraavaAste() {
// Seuraava aste on yksi suurinta listassa jo olevaa astetta isompi, tai
// 1 jos listassa ei vielä ole asteita
let aste = 1;
for (let i = 0; i < this.asteet.length; i++) {
if (this.asteet[i] !== undefined) {
aste = i + 1;
}
}
return aste;
}
lisää(aste) {
aste ??= this.seuraavaAste()
if (this.asteet[aste] !== undefined) {
throw new Error(`luokka-aste ${aste} on jo olemassa`);
}
let asteObjekti = new LuokkaAste();
this.asteet[aste] = asteObjekti;
return aste;
}
poista(aste) {
if (this.asteet[aste] === undefined) {
throw new Error(`luokka-astetta ${aste} ei ole olemassa`);
}
this.asteet[aste] = undefined;
}
muuta(vanha, uusi) {
if (vanha === uusi) {
return;
}
// Heitä poikkeus jo ennen poistoa, jotta asteet-taulukkoon ei tule
// mitään muutoksia poikkeustilanteessa
if (this.asteet[uusi] !== undefined) {
throw new Error(`luokka-aste ${uusi} on jo olemassa`);
}
let aste = this.asteet[vanha];
this.poista(vanha);
this.asteet[uusi] = aste;
}
}
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);
luokkaAsteet.lisää();
assertEq('asteen 1 jälkeen', luokkaAsteet.seuraavaAste(), 2);
luokkaAsteet.lisää(3);
assertEq('asteiden 1 ja 3 jälkeen', luokkaAsteet.seuraavaAste(), 4);
luokkaAsteet.lisää();
assertEq('asteiden 1, 3, 4 jälkeen', luokkaAsteet.seuraavaAste(), 5);
luokkaAsteet.poista(4);
luokkaAsteet.poista(3);
assertEq('asteet 3 ja 4 poistettua', luokkaAsteet.seuraavaAste(), 2);
luokkaAsteet.muuta(1, 5);
assertEq('aste 1 muutettua 5:ksi', luokkaAsteet.seuraavaAste(), 6);
});
testi('asteiden lisääminen', () => {
let luokkaAsteet = new LuokkaAsteet();
assertEq('1. aste', luokkaAsteet.lisää(), 1);
assertEq('2. aste', luokkaAsteet.lisää(), 2);
assertEq('3. aste', luokkaAsteet.lisää(3), 3);
assertThrow('3. aste uudelleen', 'luokka-aste 3 on jo olemassa', () => {
luokkaAsteet.lisää(3);
});
assertEq('lisättyä', luokkaAsteet.luokat(), ['1A', '2A', '3A']);
});
testi('asteiden poistaminen', () => {
let luokkaAsteet = new LuokkaAsteet();
luokkaAsteet.lisää();
luokkaAsteet.lisää();
luokkaAsteet.poista(1);
luokkaAsteet.poista(2);
assertThrow('3. asteen poisto', 'luokka-astetta 3 ei ole olemassa', () => {
luokkaAsteet.poista(3);
});
assertEq('poistettua', luokkaAsteet.luokat(), []);
});
testi('asteiden muuttaminen', () => {
let luokkaAsteet = new LuokkaAsteet();
assertEq('lisääminen', luokkaAsteet.lisää(), 1);
luokkaAsteet.muuta(1, 5);
assertEq('muutettua', luokkaAsteet.luokat(), ['5A']);
assertThrow('poisto', 'luokka-astetta 1 ei ole olemassa', () => {
luokkaAsteet.poista(1);
});
luokkaAsteet.poista(5);
});
testi('luokkien lisääminen', () => {
let luokkaAsteet = new LuokkaAsteet();
let aste = luokkaAsteet.asteet[luokkaAsteet.lisää()];
assertEq('aluksi', aste.luokat(), ['A']);
aste.lisää();
aste.lisää();
assertEq('lisättyä', aste.luokat(), ['A', 'B', 'C']);
});
testi('luokkien poistaminen', () => {
let luokkaAsteet = new LuokkaAsteet();
let aste = luokkaAsteet.asteet[luokkaAsteet.lisää()];
aste.lisää();
aste.lisää();
aste.poista();
aste.poista();
assertThrow('viimeisen poisto', 'viimeistä luokkaa ei voi poistaa asteelta', () => {
aste.poista();
});
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);
});