17.4.1 The container protocol and implementation
The |
|---|
module: airport
// The following generic functions constitute the essential protocol for
// interaction between containers and vehicles
// Returns true if container is available for aircraft in direction
define generic available? (vehicle, container, direction);
// Moves vehicle into container in the given direction
define generic move-in-vehicle (vehicle, container, direction);
// Moves vehicle out of container in the given direction
define generic move-out-vehicle (vehicle, container, direction);
// Returns the aircraft next in line to move out of container in direction
define generic next-out (container, direction);
// Returns the class of the next container to move vehicle into,
// and how long it will take to get there
define generic next-landing-step (container, vehicle);
// A single storage container is available if the aircraft fits into the
// the container, and there is not already a vehicle in the container
define method available?
(vehicle :: <aircraft>, container :: <single-storage>,
direction :: <symbol>)
=> (container-available? :: <boolean>)
object-fits?(vehicle, container)
& ~ (container.vehicle-currently-occupying);
end method available?;
// A multiple storage container is available if the aircraft fits into
// the container, and there are not too many aircraft already queued in
// the container for the specified direction
define method available?
(vehicle :: <aircraft>, container :: <multiple-storage>,
direction :: <symbol>)
=> (container-available? :: <boolean>)
object-fits?(vehicle, container)
& size(container.vehicles-by-direction[direction])
< container.maxima-by-direction[direction];
end method available?;
// Avoids jamming the runway with inbound traffic, which would prevent
// outbound aircraft from taking off
// The runway is clear to inbound traffic only if there is space in the
// next container inbound from the runway
define method available?
(vehicle :: <aircraft>, container :: <runway>,
direction :: <symbol>)
=> (container-available? :: <boolean>)
next-method()
& select (direction)
#"outbound" => #t;
#"inbound"
=> let (class) = next-landing-step(container, vehicle);
if (class)
find-available-connection(container, class, vehicle) ~== #f;
end if;
end select;
end method available?;
// A slot is used to keep track of which aircraft is in a single
// storage container
define method move-in-vehicle
(vehicle :: <aircraft>, container :: <single-storage>,
direction :: <symbol>)
=> ()
container.vehicle-currently-occupying := vehicle;
values();
end method move-in-vehicle;
// A deque is used to keep track of which aircraft are traveling in a
// particular direction in a multiple storage container
define method move-in-vehicle
(vehicle :: <aircraft>, container :: <multiple-storage>,
direction :: <symbol>)
=> ()
let vehicles = container.vehicles-by-direction[direction];
push-last(vehicles, vehicle);
values();
end method move-in-vehicle;
// When an aircraft reaches the gate, it begins its outbound journey
define method move-in-vehicle
(vehicle :: <aircraft>, container :: <gate>,
direction :: <symbol>)
=> ()
next-method();
vehicle.direction := #"outbound";
values();
end method move-in-vehicle;
define method move-out-vehicle
(vehicle :: <aircraft>, container :: <single-storage>,
direction :: <symbol>)
=> ()
container.vehicle-currently-occupying := #f;
values();
end method move-out-vehicle;
define method move-out-vehicle
(vehicle :: <aircraft>,
container :: <multiple-storage>, direction :: <symbol>)
=> ()
let vehicles = container.vehicles-by-direction[direction];
// Assumes that aircraft always exit container in order, and
// that this aircraft is next
pop(vehicles);
values();
end method move-out-vehicle;
// Determines what vehicle, if any, could move to the next container
// If there is such a vehicle, then this method returns the vehicle,
// the next container in the direction of travel,
// and the time that it would take to make that transition
define method next-out
(container :: <vehicle-storage>, direction :: <symbol>)
=> (next-vehicle :: false-or(<vehicle>),
next-storage :: false-or(<vehicle-storage>),
time-to-execute :: false-or(<time-offset>));
let next-vehicle = next-out-internal(container, direction);
if (next-vehicle)
let (class, time) = next-landing-step(container, next-vehicle);
if (class)
let next-container
= find-available-connection(container, class, next-vehicle);
if (next-container)
values(next-vehicle, next-container, time);
end if;
end if;
end if;
end method next-out;
// This method is just a helper method for the next-out method
// We need different methods based on the class of container
define method next-out-internal
(container :: <single-storage>, desired-direction :: <symbol>)
=> (vehicle :: false-or(<aircraft>))
let vehicle = container.vehicle-currently-occupying;
if (vehicle & vehicle.direction == desired-direction) vehicle; end;
end method next-out-internal;
define method next-out-internal
(container :: <multiple-storage>, desired-direction :: <symbol>)
=> (vehicle :: false-or(<aircraft>))
let vehicle-queue = container.vehicles-by-direction[desired-direction];
if (vehicle-queue.size > 0) vehicle-queue[0]; end;
end method next-out-internal;
// The following methods return the class of the next container to which a
// vehicle can move from a particular container
// They also return an estimate of how long that transition will take
define method next-landing-step
(storage :: <sky>, aircraft :: <aircraft>)
=> (next-class :: false-or(<class>), duration :: false-or(<time-offset>))
if (aircraft.direction == #"inbound")
values(<runway>, flying-time(aircraft, storage.airport-below));
end if;
end method next-landing-step;
define method next-landing-step
(storage :: <runway>, aircraft :: <aircraft>)
=> (next-class :: <class>, duration :: <time-offset>)
select (aircraft.direction)
#"inbound" => values(<taxiway>, brake-time(aircraft, storage));
#"outbound" => values(<sky>, takeoff-time(aircraft, storage));
end select;
end method next-landing-step;
define method next-landing-step
(storage :: <taxiway>, aircraft :: <aircraft>)
=> (next-class :: <class>, duration :: <time-offset>)
select (aircraft.direction)
#"inbound" => values(<gate>, gate-time(aircraft, storage));
#"outbound" => values(<runway>, runway-time(aircraft, storage));
end select;
end method next-landing-step;
define method next-landing-step
(storage :: <gate>, aircraft :: <aircraft>)
=> (next-class :: <class>, duration :: <time-offset>)
values(<taxiway>, gate-turnaround(aircraft, storage));
end method next-landing-step;
|




