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.
IMPORTANT NOTE: The lab activities can be developed individually or in pairs. The lab report must be developed individually.
This example was taken from [FREEMAN] pp. 191-223.
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 5: Command Pattern # Date: 22-Feb-2012 # Authors: # 456654 Thursday Rubinstein # 1160611 Anthony Stark
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. Place it in the control.rb source file and study it carefully.
# File: control.rb
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
# Access these constants from outside this class as CeilingFan::HIGH,
# CeilingFan::MEDIUM, and so on.
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.
# File: test_control.rb
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 individual lab work, follow these instructions.
lab5_report_A0MMMMMMM.txt, where A0MMMMMMM is your student ID. From your AsciiDoc source, generate the corresponding HTML file. That file should be called lab5_report_A0MMMMMMM.html. Place these two files in the command directory.
command directory. Call this file command.tgz. From a terminal, you can use the following command to create this file (make sure to run it at the same level where the command folder resides):
tar czf command.tgz command
Due date is Tuesday, February 28.
This activity will be evaluated using the following criteria:
| 50% | Implementation of functional requirements. |
|---|---|
| 50% | Lab report. |
| DA | The program and/or report was plagiarized. |