During this activity:
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 activity can be developed individually or in pairs.
This example was taken from [FREEMAN] pp. 191-223.
Create a folder called command
. Inside this folder, create two files called: control.rb
, and control_test.rb
.
Both Ruby source files must start with a comment containing title, date, and the authors' personal information. For example:
# Command Pattern # Date: 22-Feb-2017 # Authors: # A00456654 Thursday Rubinstein # A01160611 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
control_test.rb
source file.
# File: control_test.rb require 'minitest/autorun' require 'stringio' require 'control' class ControlTest < Minitest::Test 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
Create a compressed tarball file with the full contents of the 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
To deliver the command.tgz
file, please provide the following information:
Due date is Wednesday, February 22.