-
Notifications
You must be signed in to change notification settings - Fork 0
/
elevator.js
161 lines (139 loc) · 3.05 KB
/
elevator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"use strict";
var events = require('events');
var debug = require('debug')('Elevator');
/**
* Elevator
* @constructor
*/
class Elevator extends events.EventEmitter {
constructor() {
super();
this.setMaxListeners(100);
this.floor = 0;
this.destination = 0;
this.direction = Elevator.STOPPED;
this.motor = undefined;
}
/**
* Starts the elevator.
*
* @private
*/
run() {
if (!this.motor) {
this.motor = setInterval(this.move.bind(this), Elevator.SPEED);
}
}
/**
* Stops the elevator by disbling the motor.
*
* @private
*/
idle() {
if (this.motor) {
clearInterval(this.motor);
this.motor = undefined;
this.emit('idle');
}
}
/**
* getFloor
*
* @return {integer} The floor that the elevator is currently positioned at.
*/
getFloor() {
return this.floor;
}
/**
* getDirection
*
* @return {integer} The direction that this elevator is currently travelling.
*/
getDirection() {
return this.direction;
}
/**
* getDestination
*
* @return {integer} The towards which this elevator will travel.
*/
getDestination() {
return this.destination;
}
/**
* Determine if the elevator is idle.
*
* @return {boolean}
*/
isIdle() {
return !Boolean(this.motor);
}
/**
* Sends the elevator to a given floor, specified as a parameter.
*
* @param {integer} The destination floor number to which the elevator should travel.
*/
goto(destination) {
debug('Setting destination to floor %d', destination);
this.destination = destination;
if (this.direction === Elevator.STOPPED) {
if (this.floor < this.destination) {
this.emit('load', this.floor, Elevator.UP);
} else if (this.floor > this.destination) {
this.emit('load', this.floor, Elevator.DOWN);
}
}
if (this.isIdle()) {
this.move();
}
}
/**
* Move one floor on every interval, determined by Elevator.SPEED.
*
* @private
*/
move() {
this.floor += this.direction;
if (this.direction !== Elevator.STOPPED) {
this.emit('move', this.floor, this.direction);
}
if (this.floor < this.destination) {
this.direction = Elevator.UP;
} else if (this.floor > this.destination) {
this.direction = Elevator.DOWN;
} else {
if (this.direction === Elevator.STOPPED) {
// We've been stopped for a cycle. We're now idle.
debug('Idle at floor %d.', this.floor);
this.idle();
} else {
this.direction = Elevator.STOPPED;
this.destination = undefined;
debug('Arrived at floor %d. Stopping.', this.floor);
this.emit('stop', this.floor); // Don't know where the controller will send us next.
}
}
if (this.direction !== Elevator.STOPPED && this.isIdle()) {
this.run();
}
}
/**
* Make a request for a particular floor.
*
* @param {Number} destination The destination floor.
*/
requestFloor(floor, direction) {
this.emit('floorRequest', floor, direction);
}
}
/**
* Elevator direction constants.
*/
Elevator.UP = 1;
Elevator.DOWN = -1;
Elevator.STOPPED = 0;
/**
* Speed of elevator actions, in milliseconds.
*/
Elevator.SPEED = 1000;
module.exports = Elevator;