During this lab session:
This activity helps students develop the following skills, values and attitudes: ability to analyze and synthesize, capacity for identifying and solving problems, and efficient use of computer systems.
This lab can be developed individually or in pairs.
Create a folder called command. Inside
this folder, create two files called:
control.rb and
test_control.rb.
Both Ruby source files must start with a comment containing the lab's title, date, and the authors' personal information. For example:
# Lab 4: Command Pattern # Date: 24-Sep-2009 # Authors: # 456654 Anthony Stark # 1160611 Thursday Rubinstein
This example was taken from [FREEMAN] pp. 191-223. You are required to write part of the software for the control remote shown in the following image, using the Command pattern.
You are given the following Ruby code (assume it is placed in
the control.rb source file):
class RemoteControlWithUndo
def initialize
@on_commands = []
@off_commands = []
no_command = NoCommand.new
7.times do
@on_commands << no_command
@off_commands << no_command
end
@undo_command = no_command
end
def set_command(slot, on_command, off_command)
@on_commands[slot] = on_command
@off_commands[slot] = off_command
end
def on_button_was_pushed(slot)
@on_commands[slot].execute
@undo_command = @on_commands[slot]
end
def off_button_was_pushed(slot)
@off_commands[slot].execute
@undo_command = @off_commands[slot]
end
def undo_button_was_pushed()
@undo_command.undo
end
def inspect
string_buff = ["\n------ Remote Control -------\n"]
@on_commands.zip(@off_commands).each_with_index do |commands, i|
on_command, off_command = commands
string_buff << "[slot #{i}] #{on_command.class} #{off_command.class}\n"
end
string_buff << "[undo] #{@undo_command.class}\n"
string_buff.join
end
end
class NoCommand
def execute
end
def undo
end
end
class Light
attr_reader :level
def initialize(location)
@location = location
@level = 0
end
def on
@level = 100
puts "Light is on"
end
def off
@level = 0
puts "Light is off"
end
def dim(level)
@level = level
if level == 0
off
else
puts "Light is dimmed to #{@level}%"
end
end
end
class CeilingFan
HIGH = 3
MEDIUM = 2
LOW = 1
OFF = 0
attr_reader :speed
def initialize (location)
@location = location
@speed = OFF
end
def high
@speed = HIGH;
puts "#{@location} ceiling fan is on high"
end
def medium
@speed = MEDIUM
puts "#{@location} ceiling fan is on medium"
end
def low
@speed = LOW
puts "#{@location} ceiling fan is on low"
end
def off
@speed = OFF
puts "#{@location} ceiling fan is off"
end
end
Write the following command classes placing them in the
control.rb source file:
LightOnCommand, LightOffCommand,
CeilingFanHighCommand,
CeilingFanMediumCommand, and
CeilingFanOffCommand. All these classes should have
these three methods: initialize,
execute and undo. Check the unit tests
in the next step to understand the expected behavior of each
method.
The following unit tests verify the correct behavior of your
classes. Place the test class in the
test_control.rb source file.
require 'test/unit'
require 'stringio'
require 'control'
class ControlTest < Test::Unit::TestCase
def setup
set_stdout
@rc = RemoteControlWithUndo.new
set_light
set_fan
end
def teardown
reset_stdout
end
def set_stdout
@out = StringIO.new
@old_stdout = $stdout
$stdout = @out
end
def reset_stdout
$stdout = @old_stdout
end
def set_light
light = Light.new("Living Room")
light_on = LightOnCommand.new(light)
light_off = LightOffCommand.new(light)
@rc.set_command(0, light_on, light_off)
end
def set_fan
fan = CeilingFan.new("Living Room")
fan_medium = CeilingFanMediumCommand.new(fan)
fan_high = CeilingFanHighCommand.new(fan)
fan_off = CeilingFanOffCommand.new(fan)
@rc.set_command(1, fan_medium, fan_off)
@rc.set_command(2, fan_high, fan_off)
end
def test_light
@rc.on_button_was_pushed(0)
@rc.off_button_was_pushed(0)
p @rc
@rc.undo_button_was_pushed
@rc.off_button_was_pushed(0)
@rc.on_button_was_pushed(0)
p @rc
@rc.undo_button_was_pushed
assert_equal "Light is on\n" \
"Light is off\n" \
"\n------ Remote Control -------\n" \
"[slot 0] LightOnCommand LightOffCommand\n" \
"[slot 1] CeilingFanMediumCommand CeilingFanOffCommand\n" \
"[slot 2] CeilingFanHighCommand CeilingFanOffCommand\n" \
"[slot 3] NoCommand NoCommand\n" \
"[slot 4] NoCommand NoCommand\n" \
"[slot 5] NoCommand NoCommand\n" \
"[slot 6] NoCommand NoCommand\n" \
"[undo] LightOffCommand\n\n" \
"Light is on\n" \
"Light is off\n" \
"Light is on\n" \
"\n------ Remote Control -------\n" \
"[slot 0] LightOnCommand LightOffCommand\n" \
"[slot 1] CeilingFanMediumCommand CeilingFanOffCommand\n" \
"[slot 2] CeilingFanHighCommand CeilingFanOffCommand\n" \
"[slot 3] NoCommand NoCommand\n" \
"[slot 4] NoCommand NoCommand\n" \
"[slot 5] NoCommand NoCommand\n" \
"[slot 6] NoCommand NoCommand\n" \
"[undo] LightOnCommand\n\n" \
"Light is off\n", @out.string
end
def test_fan
@rc.on_button_was_pushed(1)
@rc.off_button_was_pushed(1)
p @rc
@rc.undo_button_was_pushed
@rc.on_button_was_pushed(2)
p @rc
@rc.undo_button_was_pushed
assert_equal "Living Room ceiling fan is on medium\n" \
"Living Room ceiling fan is off\n" \
"\n------ Remote Control -------\n" \
"[slot 0] LightOnCommand LightOffCommand\n" \
"[slot 1] CeilingFanMediumCommand CeilingFanOffCommand\n" \
"[slot 2] CeilingFanHighCommand CeilingFanOffCommand\n" \
"[slot 3] NoCommand NoCommand\n" \
"[slot 4] NoCommand NoCommand\n" \
"[slot 5] NoCommand NoCommand\n" \
"[slot 6] NoCommand NoCommand\n" \
"[undo] CeilingFanOffCommand\n\n" \
"Living Room ceiling fan is on medium\n" \
"Living Room ceiling fan is on high\n" \
"\n------ Remote Control -------\n" \
"[slot 0] LightOnCommand LightOffCommand\n" \
"[slot 1] CeilingFanMediumCommand CeilingFanOffCommand\n" \
"[slot 2] CeilingFanHighCommand CeilingFanOffCommand\n" \
"[slot 3] NoCommand NoCommand\n" \
"[slot 4] NoCommand NoCommand\n" \
"[slot 5] NoCommand NoCommand\n" \
"[slot 6] NoCommand NoCommand\n" \
"[undo] CeilingFanHighCommand\n\n" \
"Living Room ceiling fan is on medium\n", @out.string
end
end
To hand in your lab work, follow these instructions:
command directory. Call this file
command.zip.
This activity will be evaluated using the following criteria:
| 100 | The code works as requested. |
|---|---|
| 60-90 | The code works, but has some flaws. |
| 20-50 | The code doesn't work, but it seams that some amount of time was spent on it. |
| DA | The program was plagiarized. |