<button data-floor='404' class='btn'>404</button>
$btn-size:160px;

.btn {
  border: 1px solid;
  outline: none;
  text-align: center;
  color: #626262;
  width: $btn-size;
  height: $btn-size;
  border-radius: 9999em;
  cursor: pointer;
  font-size: 3.5em;
}

body{
  height: 100vh;
  display: grid;
  button{
    margin: auto;
  }
}
View Compiled
class Building{
  private readonly _groundFloor:number = 0;
  private readonly _floors:number = 404;
  private readonly _wallHeight:number = 300;//cm
  
  get groundFloor(){
    return this._groundFloor;
  }
  get floors(){
    return this._floors;
  }
  get wallHeight(){
    return this._wallHeight;
  }
  get buildingHeight(){
    return this._floors * this._wallHeight;
  }
}

class People{
  private readonly _avgWeight:number = 88.9041;//kg
  get avgWeight(){
    return this.avgWeight;
  }
}

class Elevator{
  constructor(
    private hostBuilding:Building
  ){
    const building = this.hostBuilding;
    this._queue = new Map();
    for(let floor = building.groundFloor; floor < building.floors; floor++){
      const isCurrentFloor = floor === building.groundFloor;
      this._queue.set(floor, isCurrentFloor);
    }
  }
  private readonly _maxWeight:number = 977.9451;
  private readonly _doorSpeed = 3.5;//s
  private readonly _doorWait = 3; ///
  private _onFloor = this.hostBuilding.groundFloor;
  private _queue:Map<number, number>;//order, floor
  private _queueOrder = 0;
  private _badMusic = new Howl({
    src: ["https://s3-eu-west-1.amazonaws.com/adamcyclonestest/Elevator-music.mp3"]
  });
  
  private arivalRutine(next){
    
    
    this.anounce(this._speach.anounceFloor(next.ariveAtFloor));
    this.anounce(this._speach.doors.opening);
    let track;
    setTimeout(()=>{
      track = this._badMusic.play();
      this._badMusic.fade(0, 1, 2000, track);
    }, this.doorSpeed);
    
    
    setTimeout(()=>{
      this.anounce(this._speach.doors.closing);
      
      //this._badMusic.pause();
    }, this.doorWait + this.doorSpeed);
    
    setTimeout(()=>{
      this.anounce(this._speach.lift[next.going]);
      this._badMusic.fade(1, 0, 4000, track);
    }, this.doorWait + this.doorSpeed + this.doorSpeed);
    
  }
  
  private readonly _speach = Object.freeze({
    doors:{
      closing: new SpeechSynthesisUtterance("Doors closing"),
      opening: new SpeechSynthesisUtterance("Doors opening"), 
    },
    lift:{
      down: new SpeechSynthesisUtterance("Lift going down"),
      up: new SpeechSynthesisUtterance("Lift going up"),
    },
    anounceFloor:(floor)=>{
      return new SpeechSynthesisUtterance(`Floor ${floor}`);
    },
    doesNotCompute:(g, topFloor)=>`Elevator cannot fly or travel underground. only floors ${g} - ${topFloor} are accessible`
  })
  
  public anounce(anouncement){
    window.speechSynthesis.speak(anouncement);
  }
  
  get maxWeight(){
    return this._maxWeight;
  }
  get doorSpeed(){
    return this._doorSpeed * 1000;
  }
  get doorWait(){
    return this._doorWait * 1000;
  }
  get onFloor(){
    return this._onFloor;
  }
  get queue(){
    return this._queue;
  }
  get speach(){
    return this._speach;
  }
  
  set floor(n:number){
    const g = this.hostBuilding.groundFloor;
    const topFloor = this.hostBuilding.floors;
    this._queueOrder++
    if(n >= g && n <= topFloor){
        this._onFloor = n;
        this._queue.set(this._queueOrder, n);
    }
    else{
      this._speach.anounce(this._speach.doesNotCompute)
      throw new Error(this._speach.doesNotCompute)
    }
  }
  
}


const someOffice = new Building();

const elevatorOne = new Elevator( someOffice );



Mousetrap.bind(["1","2","3","4","5","6","7","8","9","0"], e => {
  elevatorOne.floor = e.key;
  elevatorOne.arivalRutine({
    going: "up",
    ariveAtFloor: elevatorOne.onFloor
  })
});

const callButton = document.querySelector('[data-floor]');

callButton.addEventListener('click', (e)=>{
  elevatorOne.floor = e.target.dataset.floor;
  elevatorOne.arivalRutine({
    going: "up",
    ariveAtFloor: elevatorOne.onFloor
  })
})
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/mousetrap/1.6.2/mousetrap.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/howler/2.0.15/howler.min.js