1   package elevator;
2   
3   /*
4    * Copyright (C) 2000 by ETHZ/INF/CS
5    * All rights reserved
6    * 
7    * @version $Id$
8    * @author Roger Karrer
9    */
10  
11  import java.util.Enumeration;
12  import java.util.Vector;
13  
14  // class that implements the elevator threads
15  class Lift extends Thread {
16  
17      // used for assigning unique ids to the elevators
18      private static int count = 0;
19  
20      public static final int IDLE = 0;
21      public static final int UP = 1;
22      public static final int DOWN = 2;
23  
24      private int travelDir; // one of IDLE, UP, or DOWN
25      private int currentFloor;
26      // holds the number of people who want to get off on each floor
27      private int[] peopleFor; 
28      // Values in pickupOn can be IDLE, UP, DOWN, and UP|DOWN, which indicate
29      // which calls the elevator should respond to on each floor.  IDLE means
30      // don't pick up on that floor
31      private int[] pickupOn;
32      private int firstFloor, lastFloor;
33      // reference to the shared control object
34      private Controls controls;
35  
36      // Create a new elevator that can travel from floor 1 to floor numFloors.
37      // The elevator starts on floor 1, and is initially idle with no passengers.
38      // c is a reference to the shared control object
39      // The thread starts itself
40      public Lift(int numFloors, Controls c) {
41          super("Lift " + count++);
42          controls = c;
43          firstFloor = 1;
44          lastFloor = numFloors;
45          travelDir = IDLE;
46          currentFloor = firstFloor;
47          pickupOn = new int[numFloors+1];
48          peopleFor = new int[numFloors+1];
49          for (int i = 0; i <= numFloors; i++) {
50              pickupOn[i] = IDLE;
51              peopleFor[i] = 0;
52          }
53          start();
54      }
55  
56      // Body of the thread.  If the elevator is idle, it checks for calls
57      // every tenth of a second.  If it is moving, it takes 1 second to
58      // move between floors.
59      public void run() {
60          int numIterations = 100;
61          int i = 0;
62          while(i < numIterations) {
63              if (travelDir == IDLE) {
64                  try { sleep(100); } catch(InterruptedException e) {}
65                  doIdle();
66              }
67              else {
68                  try { sleep(1000); } catch(InterruptedException e) {}
69                  doMoving();
70              }
71              i++;
72          }
73      }
74  
75      // IDLE
76      // First check to see if there is an up or down call on what ever floor
77      // the elevator is idle on.  If there isn't one, then check the other floors.
78      private void doIdle() {
79          boolean foundFloor = false;
80          int targetFloor = -1;
81      
82          if (controls.claimUp(getName(), currentFloor)) {
83              // System.out.println("Lift::doIdle - could claim upcall on current floor"); // CARE
84              foundFloor = true;
85              targetFloor = currentFloor;
86              travelDir = UP;
87              addPeople(controls.getUpPeople(currentFloor));
88          }
89          else if (controls.claimDown(getName(), currentFloor)) {
90              // System.out.println("Lift::doIdle - could claim downcall on current floor"); // CARE
91              foundFloor = true;
92              targetFloor = currentFloor;
93              travelDir = DOWN;
94              addPeople(controls.getDownPeople(currentFloor));
95          }
96  
97          // System.out.println("Lift::doIdle - lookuing for calls on other floors"); // CARE
98          for (int floor = firstFloor; !foundFloor && floor <= lastFloor; floor++) {
99              // System.out.println("Lift::doIdle - checking floor " + floor); // CARE
100             if (controls.claimUp(getName(), floor)) {
101                 // System.out.println("Lift::doIdle - success with claimUp " + floor); // CARE
102                 foundFloor = true;
103                 targetFloor = floor;
104                 pickupOn[floor] |= UP;
105                 travelDir = (targetFloor > currentFloor) ? UP : DOWN;
106             }
107             else if (controls.claimDown(getName(), floor)) {
108                 // System.out.println("Lift::doIdle - success with claimDown " + floor); // CARE
109                 foundFloor = true;
110                 targetFloor = floor;
111                 pickupOn[floor] |= DOWN;
112                 travelDir = (targetFloor > currentFloor) ? UP : DOWN;
113             }
114         }
115     
116         if (foundFloor) {
117             System.out.println(getName() + " is now moving " +
118                     ((travelDir==UP)?"UP":"DOWN"));
119         }
120     }
121 
122     // MOVING
123     // First change floor (up or down as appropriate)
124     // Drop off passengers if we have to
125     // Then pick up passengers if we have to
126     private void doMoving() {
127         currentFloor += (travelDir == UP) ? 1 : -1;
128         int oldDir = travelDir;
129 
130         if (travelDir == UP && currentFloor == lastFloor) travelDir = DOWN;
131         if (travelDir == DOWN && currentFloor == firstFloor) travelDir = UP;
132         System.out.println(getName() + " now on " + currentFloor);
133 
134         if (peopleFor[currentFloor] > 0) {
135             System.out.println(getName() + " delivering " +
136                     peopleFor[currentFloor] + " passengers on " +
137                     currentFloor);
138             peopleFor[currentFloor] = 0;
139         }
140     
141         // Pickup people who want to go up if:
142         //   1) we previous claimed an up call on this floor, or
143         //   2) we are travelling up and there is an unclaimed up call on this
144         //      floor
145         if (((pickupOn[currentFloor] & UP) != 0) ||
146                 (travelDir == UP && controls.claimUp(getName(), currentFloor))) {
147             addPeople(controls.getUpPeople(currentFloor));
148             pickupOn[currentFloor] &= ~UP;
149         }
150 
151         // Pickup people who want to go down if:
152         //   1) we previous claimed an down call on this floor, or
153         //   2) we are travelling down and there is an unclaimed down call on this
154         //      floor
155         if (((pickupOn[currentFloor] & DOWN) != 0) ||
156                 (travelDir == DOWN && controls.claimDown(getName(), currentFloor))) {
157             addPeople(controls.getDownPeople(currentFloor));
158             pickupOn[currentFloor] &= ~DOWN;
159         }
160 
161         if (travelDir == UP) {
162             // If we are travelling up, and there are people who want to get off
163             // on a floor above this one, continue to go up.
164             if (stopsAbove()) ;
165             else {
166                 // If we are travelling up, but no one wants to get off above this
167                 // floor, but they do want to get off below this one, start
168                 // moving down
169                 if (stopsBelow()) travelDir = DOWN;
170                     // Otherwise, no one is the elevator, so become idle
171                 else travelDir = IDLE;
172             }
173         }
174         else {
175             // If we are travelling down, and there are people who want to get off
176             // on a floor below this one, continue to go down.
177             if (stopsBelow()) ;
178             else {
179                 // If we are travelling down, but no one wants to get off below this
180                 // floor, but they do want to get off above this one, start
181                 // moving up
182                 if (stopsAbove()) travelDir = UP;
183                     // Otherwise, no one is the elevator, so become idle
184                 else travelDir = IDLE;
185             }
186         }
187 
188         // Print out are new direction
189         if (oldDir != travelDir) {
190             System.out.print(getName());
191             if (travelDir == IDLE) System.out.println(" becoming IDLE");
192             else if (travelDir == UP) System.out.println(" changing to UP");
193             else if (travelDir == DOWN) System.out.println(" changing to DOWN");
194         }
195     }
196 
197     // Returns true if there are passengers in the elevator who want to stop
198     // on a floor above currentFloor, or we claimed a call on a floor below
199     // currentFloor
200     private boolean stopsAbove() {
201         boolean above = false;
202         for (int i = currentFloor + 1; !above && i <= lastFloor; i++)
203             above = (pickupOn[i] != IDLE) || (peopleFor[i] != 0);
204         return above;
205     }
206 
207     // Returns true if there are passengers in the elevator who want to stop
208     // on a floor below currentFloor, or we claiemda call on a floor above
209     // currentFloor
210     private boolean stopsBelow() {
211         boolean below = false;
212         for (int i = currentFloor - 1; !below && (i >= firstFloor); i--)
213             below = (pickupOn[i] != IDLE) || (peopleFor[i] != 0);
214         return below;
215     }
216 
217     // Updates peopleFor based on the Vector of destination floors received
218     // from the control object
219     private void addPeople(Vector people) {
220         System.out.println(getName() + " picking up " + people.size() +
221                 " passengers on " + currentFloor);
222         for (Enumeration e = people.elements(); e.hasMoreElements(); ) {
223             int toFloor = ((Integer) e.nextElement()).intValue();
224             peopleFor[toFloor] += 1;
225         }
226     }
227 }
228 
229 
230 
231 
232     
233     
234