Project: Build a Library project (LEARN INTERMEDIATE JAVASCRIPT)

The following is the solution of the Build a Library project:

class Media {
  constructor(title) {
    this._title = title;
    this._isCheckedOut = false;
    this._ratings = [];
  }

  get title() {
    return this._title;
  }

  get isCheckedOut() {
    return this._isCheckedOut;
  }

  get ratings() {
    return this._ratings;
  }

  set isCheckedOut(isCheckedOut) {
    this._isCheckedOut = isCheckedOut;
  }

  toggleCheckOutStatus() {
    if (this._isCheckedOut) {
      this._isCheckedOut = false;
    } else {
      this._isCheckedOut = true;
    }
  }

  getAverageRating() {
    return Math.round(
      this._ratings.reduce((currentSum, rating) => currentSum + rating, 0) /
        this._ratings.length
    );
  }

  addRating(rating) {
    this._ratings.push(rating);
  }
}

class Book extends Media {
  constructor(author, title, pages) {
    super(title);
    this._author = author;
    this._pages = pages;
  }

  get author() {
    return this._author;
  }

  get pages() {
    return this._pages;
  }
}

class CD extends Media {
  constructor(title, songs, duration) {
    super(title);
    this._songs = songs;
    this._duration = duration;
  }

  get songs() {
    return this._songs;
  }

  get duration() {
    return this._duration;
  }

  shuffle() {
    const index = [];
    const shuffledSongs = [];
    while (index.length < this._songs.length) {
      let i = Math.floor(Math.random() * this._songs.length);
      !index.includes(i) ? index.push(i) : null;
    }

    for (let i = 0; i < index.length; i++) {
      shuffledSongs[i] = this._songs[index[i]];

    }

    return shuffledSongs;

  }
}

class Catalog {
  constructor() {
    this._media = [];
  }

  get media() {
    return this._media;
  }

  addMedia(media) {
    this._media.push(media);
  }

  findMediaByTitle(title) {
    return this._media.find(media => media.title === title);

  }

  removeMediaByTitle(title) {
    const remove = this._media.findIndex(media => media.title === title);
    this._media.splice(remove, 1);
  }
}


class Movie extends Media {
  constructor(director, title, runTime) {
    super(title);
    this._director = director;
    this._runTime = runTime;
  }

  get director() {
    return this._director;
  }

  get runTime() {
    return this.runTime;
  }
}