0

I am trying to make an elevator simulation because of an interesting problem I saw on CareerCup. My problem is that I want the elevator to "take time" to move from one floor to another. Right now it just instantly moves to the next floor in its "to visit" list. I'm not sure how to program it so that "pickup requests" can be coming in while the elevator is moving. I think this may require threading, and the time.sleep() function. How do I make one thread that makes random requests to the elevator, and another thread that has the elevator trying to meet all of the requests? This is what I have so far:

import time
from random import *
import math

class Elevator:
    def __init__(self, num_floors):
        self.going_up = False
        self.going_down = False
        self.docked = True
        self.curr_floor = 0
        self.num_floors = num_floors
        self.floors_to_visit = []
        self.people_waiting = []

    def print_curr_status(self):
        for i in range(self.num_floors):
            if i == self.curr_floor:
                print('.  []')
            else:
                print('.')
        print ("to_visit: ", self.floors_to_visit)

    def handle_call_request(self, person):
        if not self.going_up and not self.going_down:
            self.floors_to_visit = [person.curr_floor] + self.floors_to_visit
            self.going_up = True
            self.docked = False
            self.people_waiting.append(person)
        else:
            self.floors_to_visit.append(person.curr_floor)
            self.people_waiting.append(person)

    def handle_input_request(self, floor_num):
        self.floors_to_visit.append(floor_num)

    def go_to_next(self):
        if not self.floors_to_visit:
            self.print_curr_status()
            return
        self.curr_floor = self.floors_to_visit.pop(0)
        for i,person in enumerate(self.people_waiting):
            if person.curr_floor == self.curr_floor:
                person.riding = True
                person.press_floor_num()
                self.people_waiting.pop(i)
        return


class Person:
    def __init__(self, assigned_elevator, curr_floor):
        self.curr_floor = curr_floor
        self.desired_floor = math.floor(random() * 10)
        self.assigned_elevator = assigned_elevator
        self.riding = False

    def print_floor(self):
        print(self.desired_floor)

    def call_elevator(self):
        self.assigned_elevator.handle_call_request(self)

    def press_floor_num(self):
        self.assigned_elevator.handle_input_request(self.desired_floor)


my_elevator = Elevator(20)

while True:
    for i in range(3):
        some_person = Person(my_elevator, math.floor(random() * 10))
        some_person.call_elevator()
    my_elevator.go_to_next()
    my_elevator.print_curr_status()
    time.sleep(1)
Leedle
  • 55
  • 5

1 Answers1

0

No threding is neccessary. You can introduce 2 new variables: one keeping track on the time the elevator started and one for the time an elevator ride should take. Then just just check when the elevator has run long enough. You can do this calling the function time.time(); it'll return the time in seconds since January 1, 1970 (since you're only interested in the difference it doesn't matter; you just need a function that increment in time). Although, this function often can't give a more accurate time period than 1 second. If you feel it's to inaccurate on your machine then you could use datetime.

class Elevator:
    def __init__(self, num_floors):
        self.start_time = 0
        self.ride_duration = 1
        ...

    def call_elevator(self):
         self.start_time = time.time()
         self.assigned_elevator.handle_call_request(self)

    def go_to_next(self):
        if time.time() - self.start_time < self.ride_duration:
            return  # Do nothing.
        else:
            ...

You'll probably need to refactor the code to suit your needs and add some logic on what to do when the elevator is in use, etc.

Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50