Skip to content

A solution #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 49 additions & 6 deletions elevator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
UP = 1
DOWN = 2
DESTINATION = 4
FLOOR_COUNT = 6

class ElevatorLogic(object):
Expand All @@ -20,6 +21,50 @@ def __init__(self):
# Feel free to add any instance variables you want.
self.destination_floor = None
self.callbacks = None
self.state = [0] * (FLOOR_COUNT + 1) # UP/DOWN/DESTINATION bitmask per floor (1-based)
self.trend = None # current trend (UP/DOWN/None)

def find(self, start, stop, step, trend):
for floor in range(start, stop, step):
if self.state[floor] & (trend | DESTINATION):
return floor
return None

def update_state(self, floor, set_mask, unset_mask=0):
# set/unset state bitmask for given floor
self.state[floor] = (self.state[floor] | set_mask) & ~unset_mask
# find the next potential up/down stops
# (closest stop in same direction or farthest stop in opposite direction)
count = len(self.state)
curr = self.callbacks.current_floor
next_up = self.find(curr + 1, count, 1, UP) or self.find(count - 1, curr, -1, DOWN)
next_down = self.find(curr - 1, 0, -1, DOWN) or self.find(1, curr, 1, UP)
# select the destination floor (taking current trend into account)
# and set new trend if there is none
if next_up and (self.trend == UP or not next_down):
self.destination_floor = next_up
self.trend = self.trend or UP
elif next_down and (self.trend == DOWN or not next_up):
self.destination_floor = next_down
self.trend = self.trend or DOWN
else:
self.destination_floor = None

def prepare_for_departure(self):
curr = self.callbacks.current_floor
# change trend direction if we were called here to go to opposite direction
opposite_trend = self.trend == UP and DOWN or self.trend == DOWN and UP or None
if self.state[curr] & ~DESTINATION == opposite_trend:
self.trend = opposite_trend
# clear (ignore) destinations that are not in current trend direction
for f in range(1, len(self.state)):
if self.trend == UP and f <= curr or self.trend == DOWN and f >= curr:
self.state[f] &= ~DESTINATION
# clear used state of current floor and update destination using updated trend
self.update_state(curr, 0, self.trend or 0)
# update trend according to actual destination
dest = self.destination_floor or curr
self.trend = dest > curr and UP or dest < curr and DOWN or None

def on_called(self, floor, direction):
"""
Expand All @@ -30,7 +75,7 @@ def on_called(self, floor, direction):
floor: the floor that the elevator is being called to
direction: the direction the caller wants to go, up or down
"""
self.destination_floor = floor
self.update_state(floor, direction)

def on_floor_selected(self, floor):
"""
Expand All @@ -40,7 +85,7 @@ def on_floor_selected(self, floor):

floor: the floor that was requested
"""
self.destination_floor = floor
self.update_state(floor, DESTINATION)

def on_floor_changed(self):
"""
Expand All @@ -56,7 +101,5 @@ def on_ready(self):
Maybe passengers have embarked and disembarked. The doors are closed,
time to actually move, if necessary.
"""
if self.destination_floor > self.callbacks.current_floor:
self.callbacks.motor_direction = UP
elif self.destination_floor < self.callbacks.current_floor:
self.callbacks.motor_direction = DOWN
self.prepare_for_departure()
self.callbacks.motor_direction = self.trend