Advertisement
Guest User

99 Bottles of Beer

a guest
Feb 2nd, 2017
255
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module.exports = class BeerWall {
  2.   static sing(starting = 99, ending = 0) {
  3.     this.validate(starting, ending);
  4.  
  5.     return [...this.recite(starting, ending)].join('\n\n');
  6.   }
  7.  
  8.   static *recite(starting, ending) {
  9.     const wall = new BeerWall(starting);
  10.  
  11.     while ((yield* wall) > ending) {}
  12.   }
  13.  
  14.   static verse(bottles) {
  15.     return new BeerWall(bottles).verse();
  16.   }
  17.  
  18.   static validate() {
  19.     if (typeof arguments[0] !== 'number' || typeof arguments[1] !== 'number') {
  20.       throw new TypeError('Invalid type: starting and ending must be numbers');
  21.     }
  22.  
  23.     if (arguments[0] > 99 || arguments[0] < 0) {
  24.       throw new RangeError('Invalid starting');
  25.     }
  26.  
  27.     if (arguments[1] > 99 || arguments[1] < 0) {
  28.       throw new RangeError('Invalid ending');
  29.     }
  30.  
  31.     if (arguments[0] < arguments[1]) {
  32.       throw new RangeError('starting must be greater or equal to ending');
  33.     }
  34.   }
  35.  
  36.   constructor(bottles) {
  37.     this.bottles = bottles;
  38.   }
  39.  
  40.   *[Symbol.iterator]() {
  41.     const current = this.bottles;
  42.  
  43.     yield this.verse();
  44.  
  45.     return current;
  46.   }
  47.  
  48.   verse() {
  49.     return (
  50.       `${this.Quantity} ${this.container} of beer on the wall, ` +
  51.       `${this.quantity} ${this.container} of beer.\n` +
  52.       `${this.action()}, ` +
  53.       `${this.quantity} ${this.container} of beer on the wall.`
  54.     );
  55.   }
  56.  
  57.   get Quantity() {
  58.     const quantity = this.quantity;
  59.  
  60.     return quantity.charAt(0).toUpperCase() + quantity.substr(1);
  61.   }
  62.  
  63.   get quantity() {
  64.     switch (this.bottles) {
  65.     case 0:
  66.       return 'no more';
  67.     default:
  68.       return this.bottles.toString();
  69.     }
  70.   }
  71.  
  72.   get container() {
  73.     switch (this.bottles) {
  74.     case 1:
  75.       return 'bottle';
  76.     default:
  77.       return 'bottles';
  78.     }
  79.   }
  80.  
  81.   get pronoun() {
  82.     switch (this.bottles) {
  83.     case 1:
  84.       return 'it';
  85.     default:
  86.       return 'one';
  87.     }
  88.   }
  89.  
  90.   action() {
  91.     const pronoun = this.pronoun;
  92.     const bottles = this.bottles--;
  93.  
  94.     if (bottles === 0) {
  95.       this.bottles = 99;
  96.     }
  97.  
  98.     switch (bottles) {
  99.     case 0:
  100.       return 'Go to the store and buy some more';
  101.     default:
  102.       return `Take ${pronoun} down and pass it around`;
  103.     }
  104.   }
  105. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement