Sequential Elevator (1)



package Elevator is

   procedure Controller;

   -- the range of the floors in the building
   NumberFloors : constant Integer := 5;
   type FloorNumber is new Integer range 1..NumberFloors;
   type FloorList is array(FloorNumber) of Boolean;

   -- the direction of moving
   type DirectionType is (up, down);

   -- just stubs for the calls made by the controller
   function GetActionId return Integer;
   function NewDestination return FloorNumber;
   function Approaching return FloorNumber;
   function GetCallFloor return FloorNumber;
   function StoppedAt return FloorNumber;
   function CarReady return FloorNumber;
   function CarReadyEmpty return FloorNumber;

   function IsDestination(Floor : FloorNumber) return Boolean;
   function IsInCallsup(Floor : FloorNumber) return Boolean;
   function IsInCallsdown(Floor : FloorNumber) return Boolean;
   function ThereAreRequestsAbove(Floor : FloorNumber) return Boolean;

   procedure CarStop;
   procedure CarContinue;
   procedure CarDoorOpen;
   procedure CarDoorClose;
   procedure CarMoveup;
   procedure CarMovedown;

end Elevator;




package body Elevator is

  procedure CarStop is
  begin
    null; --event[{ordered_to_stop}]
    null;
  end CarStop;

  procedure CarDoorOpen is
  begin
    null; -- event[{open_doors}]
    null;
  end CarDoorOpen;

  procedure CarDoorClose is
  begin
    null; -- event[{close_doors}]
    null;
  end CarDoorClose;

  procedure CarMoveup is
  begin
    null; --event[{ordered_to_move}]
    null; --event[{ordered_to_move_up}]
    null;
  end CarMoveup;

  procedure CarMovedown is
  begin
    null; --event[{ordered_to_move}]
    null; --event[{ordered_to_move_down}]
    null;
  end CarMovedown;

  procedure Controller is

    Callsup, Callsdown, Stops : FloorList;

    PeoplePresent : Boolean := False;
    DirectionUP : boolean;
    Signal : Integer;
    Floor : FloorNumber;
    Dummy : Boolean := False;

  begin

    DirectionUP := true; --event[{directionup=t}]
    loop
      -- obtain a random number that is supposed to model obtaining the
      -- code for a particular real-time event
      Signal := GetActionId;
      case Signal is
         when 1 =>
            -- someone pushed the call up button on one of the floors
            Floor := GetCallFloor;

            -- enter the floor in the list of calls up
            Callsup(Floor) := True;
         when 2 =>
            -- someone pushed the call up button on one of the floors
            Floor := GetCallFloor;

            -- enter the floor in the list of calls up
            Callsdown(Floor) := True;
         when 3 =>
            -- the car is approaching a certain floor
            Floor := Approaching; --event[{reporting_approach}]

            -- stop there only if this floor was requested as a destination
            -- by one of the people in the car or has a person waiting who
            -- is going in the direction the car is currently going
            if IsDestination(Floor) or
               ((DirectionUP) and then IsInCallsup(Floor)) or
               ((not DirectionUP) and then IsInCallsdown(Floor)) then
               CarStop;
               null;
            -- also stop if the floor is the top or first floor
            elsif ((DirectionUP) and then (Floor = FloorNumber'last)) or
                  ((not DirectionUP) and then (Floor = FloorNumber'first)) then
               CarStop;
               null;
            else
               CarContinue;
            end if;
         when 4 =>
            -- the car has stopped at a certain floor
            Floor := StoppedAt; --event[{not_moving}]

            -- open the doors
            CarDoorOpen;

            -- no more people should be waiting for this car on this floor
            if DirectionUP then
               Callsup(Floor) := False;
            else
               Callsdown(Floor) := False;
            end if;

            -- set the direction to up if the car is on the first floor and
            -- to down if it is on the top floor
            if Floor = FloorNumber'First then
               DirectionUP := true; --event[{directionup=t}]
               null;
            end if;

            if Floor = FloorNumber'Last then
               DirectionUP := false; --event[{directionup=f}]
               null;
            end if;
         when 5 =>
            -- the car is ready to move (people are not standing in the
            -- doors)
            Floor := CarReady;

            -- all people who wanted should have exited by now
            Stops(Floor) := False;

            -- close the doors
            CarDoorClose;

            -- move the car in the same direction unless there are no
            -- desired destinations in that direction
            if (DirectionUP) then
               null; --event[{directionupis=t}]
               if ThereAreRequestsAbove(Floor) then
                  CarMoveup;
               else
                  DirectionUP := false; --event[{directionup=f}]
                  CarMovedown;
               end if;
            else
               null; --event[{directionupis=f}]
               CarMovedown;
            end if;
         when 6 =>
            -- someone pushed a button while in the car
            Floor := NewDestination;
            Stops(Floor) := True;
         when 7 =>
            -- the car is open and empty
            Floor := CarReadyEmpty;

            -- clear all the stops now because there's nobody in the car
            for I in FloorNumber loop
               Stops(I) := False;
            end loop;

            -- this line is added only for the benefit of FLAVERS, in
            -- general the controller does not have to be terminating
            -- the exit from the loop may only occur here, when there are
            -- no people in the car and the doors are open
            exit when Dummy;

            CarDoorClose;

            -- of course it's unfair, but start moving to the first floor
            CarMovedown;
         when others =>
            null;
      end case;
    end loop;

    CarDoorClose;
  end Controller;

begin
  Controller;
end Elevator;