// VEHICLE STORAGE
// The default size for a vehicle container
define constant $default-capacity
= make(<size>, length: 350, width: 200, height: 100);
// This class represents a location where an aircraft could be stored
define abstract class <vehicle-storage> (<physical-object>)
slot storage-capacity :: <size> = $default-capacity,
init-keyword: capacity:;
each-subclass slot name-prefix :: <string> = "Storage", setter: #f;
slot identifier :: <string>, required-init-keyword: id:;
slot connected-to :: <simple-object-vector>;
end class <vehicle-storage>;
// By using the name-prefix each-subclass slot, we share one say method
// for all vehicle containers
define method say (storage :: <vehicle-storage>) => ()
format-out("%s %s", storage.name-prefix, storage.identifier);
end method say;
define method object-fits?
(object :: <physical-object>, container :: <vehicle-storage>)
=> (fits? :: <boolean>)
let object-size = object.physical-size;
let container-capacity = container.storage-capacity;
object-size.length < container-capacity.length
& object-size.height < container-capacity.height
& object-size.width < container-capacity.width;
end method object-fits?;
// Vehicle storage that can hold only one aircraft regardless of direction
// Direction in this context is either #"inbound" or #"outbound"
define abstract class <single-storage> (<vehicle-storage>)
slot vehicle-currently-occupying :: false-or(<aircraft>) = #f;
end class <single-storage>;
// Vehicle storage that can hold multiple aircraft, with distinct queues
// for each direction
define abstract class <multiple-storage> (<vehicle-storage>)
slot vehicles-by-direction :: <object-table> = make(<object-table>);
slot maxima-by-direction :: <object-table> = make(<object-table>);
keyword directions:;
keyword maxima:;
end class <multiple-storage>;
// In a real airport, there would be many paths an aircraft could take
// For our simple airport example, we define only the #"inbound" and
// #"outbound" paths
// The directions parameter is a sequence of these aircraft path names
// Multiple storage containers can limit the number of aircraft that
// they can hold for each path; this is the maxima parameter
// This initialize method creates a queue to hold aircraft for each
// direction, and stores the queue in a table indexed by direction
// This method also stores the maximum number of aircaft for that
// direction in a different table
define method initialize
(object :: <multiple-storage>, #key directions :: <sequence>,
maxima :: <sequence>)
next-method ();
for (direction in directions,
maximum in maxima)
object.vehicles-by-direction[direction] := make(<deque>);
object.maxima-by-direction[direction] := maximum;
end for;
end method initialize;
// From the preceding basic vehicle containers, we can build specific
// containers for each aircraft-transition location
define class <gate> (<single-storage>)
inherited slot name-prefix, init-value: "Gate";
end class <gate>;
// Given a zero-based terminal number, and a one-based gate number, create
// an return a string with a gate letter and a terminal number in it
define method generate-gate-id
(term :: <nonnegative-integer>, gate :: <positive-integer>)
=> (gate-id :: <string>)
format-to-string("%c%d", $letters[term], gate);
end method generate-gate-id;
// Gates-per-terminal is a vector; each element of the vector is the
// number of gates to create for the terminal at that index
// Returns a vector of all the gate instances
define method generate-gates
(gates-per-terminal :: <vector>, default-gate-capacity :: <size>)
=> (gates :: <vector>)
let result = make(<vector>, size: reduce1(\+, gates-per-terminal));
let result-index = 0;
for (term from 0 below gates-per-terminal.size)
for (gate from 1 to gates-per-terminal[term])
result[result-index]
:= make(<gate>, id: generate-gate-id(term, gate),
capacity: default-gate-capacity);
result-index := result-index + 1;
end for;
end for;
result;
end method generate-gates;
// This class represents the part of the airspace over a given airport
define class <sky> (<multiple-storage>)
// The airport over which this piece of sky is located
slot airport-below :: <airport>, required-init-keyword: airport:;
inherited slot name-prefix, init-value: "Sky";
required keyword inbound-aircraft:;
end class <sky>;
// When a sky instance is created, a sequence of inbound aircraft is
// provided
// This method initializes the direction slot of the aircraft to
// #"inbound", and places the aircraft in the inbound queue of the sky
// instance
define method initialize
(sky :: <sky>, #key inbound-aircraft :: <sequence>)
next-method(sky, directions: #[#"inbound", #"outbound"],
maxima: vector(inbound-aircraft.size,
inbound-aircraft.size));
let inbound-queue = sky.vehicles-by-direction [#"inbound"];
for (vehicle in inbound-aircraft)
vehicle.direction := #"inbound";
push-last(inbound-queue, vehicle);
end for;
// Connect the airport to the sky
sky.airport-below.sky-above := sky;
end method initialize;
// This class represents a strip of land where aircraft land and take off
define class <runway> (<single-storage>)
inherited slot name-prefix, init-value: "Runway";
end class <runway>;
// Taxiways connect runways and gates
define class <taxiway> (<multiple-storage>)
inherited slot name-prefix, init-value: "Taxiway";
end class <taxiway>;
|