'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 = []; 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; } } 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); }); }); 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); }); }); testi('asteiden muuttaminen', () => { let luokkaAsteet = new LuokkaAsteet(); assertEq('lisääminen', luokkaAsteet.lisää(), 1); luokkaAsteet.muuta(1, 5); 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']); });