Skip to content
Open
145 changes: 145 additions & 0 deletions docs/user_stories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# User story 1
As an air traffic controller
So I can get passengers to a destination
I want to instruct a plane to land at an airport

# Nouns
air traffic controller, passengers, destination, plane, airport

# Verbs
get, instruct, land

# Functional representation
Objects:
- plane
- airport

Messages:
- land

# Diagram
Airport <--land--> Plane


##################################
# User story 2
As an air traffic controller
So I can get passengers on the way to their destination
I want to instruct a plane to take off from an airport and confirm that it is no longer in the airport

# Nouns
air traffic controller, passengers, destination, plane, airport

# Verbs
get, instruct, take off, confirm

# Functional representation
Objects:
- Airport
- Plane

Messages:
- take_off
- left_airport?

# Diagrams
Airport <--take_off--> Plane

Plane <--left_airport?--> true


##################################
# User story 3
As an air traffic controller
To ensure safety
I want to prevent landing when the airport is full

# Nouns
air traffic controller, safety, airport, full

# Verbs
ensure, prevent, landing

# Functional representation
Objects:
- Airport
- Plane

Messages:
- landing
- full?

# Diagrams
Airport <--landing--> Plane

Airport <--full?--> true/false


##################################
# User story 4
As the system designer
So that the software can be used for many different airports
I would like a default airport capacity that can be overridden as appropriate

# Functional representation
Objects:
- Airport

Messages:
- set_capacity

Airport <--set_capacity--> num


##################################
# User story 5
As an air traffic controller
To ensure safety
I want to prevent takeoff when weather is stormy

# Functional representation
Objects:
- Airport
- Weather
- Plane

Messages:
- prevent_take_off

# Diagrams
Airport <--take_off--> Plane
Weather <--stormy?--> ture/false


##################################
# User story 6
As an air traffic controller
To ensure safety
I want to prevent landing when weather is stormy

# Functional representation
Objects:
- Airport
- Weather
- Plane

Messages:
- prevent_landing

# Diagrams
Airport <--land--> Plane
Weather <--stormy?--> true/false


##################################

# Edge cases
- planes can only take off from airports they are in;
# done
- planes that are already flying cannot take off and/or be in an airport;
(when plane lands left_airport? should be false)
# done
- planes that are landed cannot land again and must be in an airport
# done

##################################
42 changes: 42 additions & 0 deletions lib/airport.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require_relative 'plane'
require_relative 'weather'

class Airport

DEFAULT_CAPACITY = 5

attr_reader :planes, :capacity

def initialize(capacity=DEFAULT_CAPACITY)
@planes = []
@capacity = capacity
end

def land(plane)
fail 'Airport full' if full?
fail 'Landing not allowed due to adverse weather' if stormy?
fail 'Plane already landed' if @planes.include?(plane)
plane.allowed_land
@planes << plane
plane
end

def take_off(plane)
fail 'Plane not in the airport' unless @planes.include?(plane)
fail 'Take-off not allowed due to adverse weather' if stormy?
plane.allowed_take_off
@planes.delete(plane)
end

private

def full?
@planes.length >= @capacity
end

def stormy?
weather = Weather.stormy?
weather
end

end
19 changes: 19 additions & 0 deletions lib/plane.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Plane

def initialize
@left_airport = true
end

def allowed_take_off
@left_airport = true
end

def left_airport?
@left_airport
end

def allowed_land
@left_airport = false
end

end
10 changes: 10 additions & 0 deletions lib/weather.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Weather

WEATHER = [:sunny, :rainy, :stormy, :windy]

def self.stormy?
current_weather = WEATHER.sample
current_weather == :stormy
end

end
133 changes: 133 additions & 0 deletions spec/airport_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
require './lib/airport'
require './lib/weather'

describe Airport do

# Capacity
describe '#capacity' do

it 'has a default value' do
expect(subject.capacity).to eq Airport::DEFAULT_CAPACITY
end

it 'can be set to a specific value' do
airport = Airport.new(10)
expect(airport.capacity).to eq 10
end

end

# Lands a plane
describe '#land' do

it 'airport responds to the method' do
expect(subject).to respond_to :land
end

it 'accepts one argument' do
expect(subject).to respond_to(:land).with(1).argument
end

it 'lands a plane' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = double (:plane)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding doubles to the top of the Airport spec would dry code a bit

allow(plane).to receive(:allowed_land)
expect(subject.land(plane)).to eq plane
end

it 'rasies an error when airport is full' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = double (:plane)
allow(plane).to receive(:allowed_land)
subject.capacity.times {subject.land(Plane.new)}
expect {subject.land(plane)}.to raise_error 'Airport full'
end

it 'raises an error when the weather is stormy' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(true)

plane = double (:plane)
allow(plane).to receive(:allowed_land)
expect{ subject.land(plane) }.to raise_error 'Landing not allowed due to adverse weather'
end

it 'raises an error when the plane has already landed' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = double (:plane)
allow(plane).to receive(:allowed_land)
subject.land(plane)
expect{ subject.land(plane) }.to raise_error 'Plane already landed'
end

it 'changes left_airport? to false' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = Plane.new
expect(subject.land(plane)).not_to be_left_airport
end

end

# Takes off a plane
describe '#take_off' do

it 'airport responds to the method' do
expect(subject).to respond_to :take_off
end

it 'accepts one argument' do
expect(subject).to respond_to(:take_off).with(1).argument
end

it 'raises an error when the weather is stormy' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = double (:plane)
allow(plane).to receive_messages(:allowed_land => nil, :allowed_take_off => nil)
subject.land(plane)

allow(weather).to receive(:stormy?).and_return(true)
expect{ subject.take_off(plane) }.to raise_error 'Take-off not allowed due to adverse weather'
end

it 'takes-off the plane when the weather is NOT stormy' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = double (:plane)
allow(plane).to receive_messages(:allowed_land => nil, :allowed_take_off => nil)
subject.land(plane)
expect(subject.take_off(plane)).to eq plane
end

it 'confirms the plane has left_airport?' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = Plane.new
subject.land(plane)
#expect(plane.left_airport?).to eq true
expect(subject.take_off(plane)).to be_left_airport
end

it 'raises an error when the plane is not in the airport' do
weather = class_double('Weather').as_stubbed_const
allow(weather).to receive(:stormy?).and_return(false)

plane = double (:plane)
allow(plane).to receive_messages(:allowed_land => nil, :allowed_take_off => nil)
expect{subject.take_off(plane)}.to raise_error 'Plane not in the airport'
end

end

end
27 changes: 27 additions & 0 deletions spec/plane_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require 'plane'

describe Plane do

it 'responds to allowed_take_off method' do
expect(subject).to respond_to :allowed_take_off
end

it 'responds to _left_airport? method' do
expect(subject).to respond_to :left_airport?
end

it 'after allowed_take_off returns true for left_airport?' do
subject.allowed_take_off
expect(subject).to be_left_airport
end

it 'responds to allowed_land method' do
expect(subject).to respond_to :allowed_land
end

it 'after allowed_land returns false for left_airport' do
subject.allowed_land
expect(subject).not_to be_left_airport
end

end
Loading