Dziennik krok 6: nowy widok, ten sam model

Projekt: dziennik ocen krok po kroku - JavaScript od podstaw: konsola (JavaScript)

Zysk z rozdzielenia modelu i widoku: nowy sposób pokazania danych nie wymaga zmian w klasie. Funkcja `table` rysuje tabelę z wyrównanymi kolumnami (`padEnd` dopełnia napis spacjami z prawej, `padStart` z lewej, więc liczby stoją równo pod sobą), korzystając z tych samych metod `gradesBy` i `best`. Klasa `Gradebook` jest identyczna jak w poprzednim kroku.

const DATA = `Ola;matematyka;5
Jan;matematyka;3
Ola;polski;4
Ala;fizyka;7
Ewa;matematyka;6
Jan;polski;2
Kuba;matematyka
Ewa;polski;5
Ola;matematyka;6
Ola;polski;cztery
Jan;matematyka;4`;
class Gradebook {
  #records = [];

  static parseLine(line) {
    const parts = line.split(';');
    if (parts.length !== 3) throw new Error('oczekiwano 3 pól');
    const [name, subject, gradeText] = parts.map(p => p.trim());
    if (name === '' || subject === '') throw new Error('puste imię lub przedmiot');
    const grade = Number(gradeText);
    if (!Number.isInteger(grade) || grade < 1 || grade > 6) {
      throw new Error(`ocena spoza skali 1-6: "${gradeText}"`);
    }
    return { name, subject, grade };
  }

  static average(grades) {
    return grades.reduce((a, b) => a + b, 0) / grades.length;
  }

  add(record) {
    this.#records.push(record);
  }

  load(text) {
    const errors = [];
    text.split('\n').forEach((line, i) => {
      try {
        this.add(Gradebook.parseLine(line));
      } catch (e) {
        errors.push(`wiersz ${i + 1}: ${e.message}`);
      }
    });
    return errors;
  }

  gradesBy(key) {
    const groups = {};
    for (const r of this.#records) {
      if (!(r[key] in groups)) groups[r[key]] = [];
      groups[r[key]].push(r.grade);
    }
    return groups;
  }

  best() {
    let best = null;
    for (const [name, grades] of Object.entries(this.gradesBy('name'))) {
      const avg = Gradebook.average(grades);
      if (best === null || avg > best.avg) best = { name, avg };
    }
    return best;
  }

  get records() {
    return [...this.#records];
  }
}
function table(book) {
  console.log('Uczeń'.padEnd(6) + 'Oceny'.padEnd(10) + 'Średnia'.padStart(8));
  for (const [name, grades] of Object.entries(book.gradesBy('name'))) {
    const avg = Gradebook.average(grades).toFixed(2);
    console.log(name.padEnd(6) + grades.join(' ').padEnd(10) + avg.padStart(8));
  }
  console.log('-'.repeat(24));
  const best = book.best();
  console.log(`Najlepsza średnia: ${best.name} (${best.avg.toFixed(2)})`);
}
const book = new Gradebook();
const errors = book.load(DATA);
table(book);
console.log(`Pominięte wiersze: ${errors.length}`);

Ładowanie interaktywnego edytora... Jeśli się nie pojawi, włącz JavaScript.

Wszystkie lekcje kursu JavaScript od podstaw: konsola·Zaloguj się, aby zapisać postęp na koncie.