bitmap_cmd_editor 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +3 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/Rakefile +35 -0
- data/bin/bitmap_cmd_editor +10 -0
- data/bitmap_cmd_editor.gemspec +33 -0
- data/features/clear_table.feature +23 -0
- data/features/colours_pixel.feature +30 -0
- data/features/command_bitmap_cmd_editor.feature +48 -0
- data/features/create_bitmap.feature +29 -0
- data/features/draw_horinzontal_segment.feature +33 -0
- data/features/draw_vertical_segment.feature +33 -0
- data/features/fill_region.feature +44 -0
- data/features/show_content.feature +40 -0
- data/features/step_definitions/clear_table_step.rb +4 -0
- data/features/step_definitions/colours_pixel_step.rb +10 -0
- data/features/step_definitions/create_bitmap_step.rb +19 -0
- data/features/support/env.rb +2 -0
- data/lib/bitmap_cmd_editor.rb +3 -0
- data/lib/bitmap_cmd_editor/bitmap.rb +195 -0
- data/lib/bitmap_cmd_editor/client.rb +34 -0
- data/lib/bitmap_cmd_editor/exceptions.rb +17 -0
- data/lib/bitmap_cmd_editor/validators/clear_image_validator.rb +20 -0
- data/lib/bitmap_cmd_editor/validators/colour_pixel_validator.rb +34 -0
- data/lib/bitmap_cmd_editor/validators/command_validator.rb +21 -0
- data/lib/bitmap_cmd_editor/validators/create_image_validator.rb +34 -0
- data/lib/bitmap_cmd_editor/validators/error_message.rb +38 -0
- data/lib/bitmap_cmd_editor/validators/fill_region_validator.rb +34 -0
- data/lib/bitmap_cmd_editor/validators/horizontal_line_validator.rb +38 -0
- data/lib/bitmap_cmd_editor/validators/print_table_validator.rb +20 -0
- data/lib/bitmap_cmd_editor/validators/validator_herlper.rb +33 -0
- data/lib/bitmap_cmd_editor/validators/vertical_line_validator.rb +38 -0
- data/lib/bitmap_cmd_editor/version.rb +27 -0
- metadata +237 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
Feature: Show Content
|
2
|
+
S - Show the contents of the current image
|
3
|
+
|
4
|
+
Scenario: Showing Table
|
5
|
+
Given I run `bitmap_cmd_editor` interactively
|
6
|
+
And I type "I 5 6"
|
7
|
+
And I type "L 4 1 E"
|
8
|
+
And I type "L 3 2 E"
|
9
|
+
And I type "L 4 2 E"
|
10
|
+
And I type "L 3 3 E"
|
11
|
+
And I type "L 2 5 E"
|
12
|
+
And I type "F 4 2 H"
|
13
|
+
When I type "S"
|
14
|
+
And I type "X"
|
15
|
+
Then it should pass with:
|
16
|
+
"""
|
17
|
+
Welcome to the Bitmap Command Editor
|
18
|
+
------------------------------------
|
19
|
+
|
20
|
+
Available Commands:
|
21
|
+
-------------------
|
22
|
+
|
23
|
+
I M N - Create a new M x N image with all pixels coloured white (O).
|
24
|
+
C - Clears the table, setting all pixels to white (O).
|
25
|
+
L X Y C - Colours the pixel (X,Y) with colour C.
|
26
|
+
V X Y1 Y2 C - Draw a vertical segment of colour C in column X between rows Y1 and Y2 (inclusive).
|
27
|
+
H X1 X2 Y C - Draw a horizontal segment of colour C in row Y between columns X1 and X2 (inclusive).
|
28
|
+
F X Y C - Fill the region R with the colour C. R is defined as: Pixel (X,Y) belongs to R. Any other pixel which is the same colour as (X,Y) and shares a common side with any pixel in R also belongs to this region.
|
29
|
+
S - Show the contents of the current image
|
30
|
+
X - Terminate the session
|
31
|
+
|
32
|
+
O O O H O
|
33
|
+
O O H H O
|
34
|
+
O O H O O
|
35
|
+
O O O O O
|
36
|
+
O E O O O
|
37
|
+
O O O O O
|
38
|
+
|
39
|
+
End the Session...
|
40
|
+
"""
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Given(/^a bitmap was created typing the command "([^"]*)"$/) do |command|
|
2
|
+
steps %{
|
3
|
+
Given a bitmap created
|
4
|
+
And The user type "#{command}"
|
5
|
+
}
|
6
|
+
end
|
7
|
+
|
8
|
+
When(/^The user tries to colour "([^"]*)"$/) do |command|
|
9
|
+
@command = @bitmap.process_command(command)
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Given(/^a bitmap created$/) do
|
2
|
+
@bitmap = Bitmap.new
|
3
|
+
end
|
4
|
+
|
5
|
+
When(/^The user type "([^"]*)"$/) do |command|
|
6
|
+
@bitmap.process_command(command)
|
7
|
+
end
|
8
|
+
|
9
|
+
Then(/^this bitmap should be created$/) do |table|
|
10
|
+
expected_table=table.raw
|
11
|
+
expect(@bitmap.table).to match_array(expected_table)
|
12
|
+
end
|
13
|
+
When(/^The user attempts to create "([^"]*)"$/) do |command|
|
14
|
+
@command = @bitmap.process_command(command)
|
15
|
+
end
|
16
|
+
|
17
|
+
Then(/^He should see the message "([^"]*)"$/) do |message|
|
18
|
+
expect(@command).to include(message)
|
19
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
module BitmapCmdEditor
|
2
|
+
# @author Diego Hernán Piccinini Lagos
|
3
|
+
# It's the main object is instantiated empty when the application start
|
4
|
+
class Bitmap
|
5
|
+
|
6
|
+
attr_reader :table, :columns, :rows
|
7
|
+
|
8
|
+
# @param (see CommandValidator#initialize)
|
9
|
+
def initialize
|
10
|
+
@table=[]
|
11
|
+
@columns = 0
|
12
|
+
@rows = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
# process the operations commands availables view the constant COMMANDS, X is excluded because it is a
|
16
|
+
# system command not a bitmap command
|
17
|
+
# @param input [String] the command typed for example: I 5 6
|
18
|
+
# @return CommandValidator.validate response [Symbol|String] could be :valid or Error Message string
|
19
|
+
def process_command(input)
|
20
|
+
|
21
|
+
validator=Validators::CommandValidator.validate(input)
|
22
|
+
if validator == :valid
|
23
|
+
args = input.split(' ')
|
24
|
+
case args[0]
|
25
|
+
when 'I'
|
26
|
+
create_image(args)
|
27
|
+
when 'C'
|
28
|
+
clear_image(args)
|
29
|
+
when 'L'
|
30
|
+
colours_pixel(args)
|
31
|
+
when 'V'
|
32
|
+
draw_vertical_line(args)
|
33
|
+
when 'H'
|
34
|
+
draw_horizontal_line(args)
|
35
|
+
when 'F'
|
36
|
+
fill_region(args)
|
37
|
+
when 'S'
|
38
|
+
print_table(args)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
validator
|
42
|
+
end
|
43
|
+
end
|
44
|
+
private
|
45
|
+
|
46
|
+
# For create image table map for M columns and N rows with the command I M N
|
47
|
+
# @param args [String] the command typed for example: I 5 6
|
48
|
+
# @return CreateImageValidator.validate response [Symbol|String] could be :valid or Error Message string
|
49
|
+
def create_image(args)
|
50
|
+
validator=Validators::CreateImageValidator.validate(args)
|
51
|
+
if validator == :valid
|
52
|
+
@columns=Integer(args[1])
|
53
|
+
@rows = Integer(args[2])
|
54
|
+
@table = fill_table(@columns,@rows)
|
55
|
+
end
|
56
|
+
validator
|
57
|
+
end
|
58
|
+
|
59
|
+
# clear the image with the command C all values will be O
|
60
|
+
# @param args [String] in this case is C
|
61
|
+
# @return CreateImageValidator.validate response [Symbol|String] could be :valid or Error Message string
|
62
|
+
def clear_image(args)
|
63
|
+
validator=Validators::ClearImageValidator.validate(args)
|
64
|
+
if validator == :valid
|
65
|
+
@table = fill_table(@columns,@rows)
|
66
|
+
end
|
67
|
+
validator
|
68
|
+
end
|
69
|
+
|
70
|
+
# to fill a coordinate with specific colour with command L M N C
|
71
|
+
# @param args [String] in this case the command is for example L 4 2 A
|
72
|
+
# @return ColourPixelValidator.validate response [Symbol|String] could be :valid or Error Message string
|
73
|
+
def colours_pixel(args)
|
74
|
+
validator=Validators::ColourPixelValidator.validate(args, @columns, @rows)
|
75
|
+
if validator == :valid
|
76
|
+
column=Integer(args[1]) - 1
|
77
|
+
row = Integer(args[2]) - 1
|
78
|
+
@table[row][column]=args[3]
|
79
|
+
end
|
80
|
+
validator
|
81
|
+
end
|
82
|
+
|
83
|
+
# to create a fill all table coordinates with a colour
|
84
|
+
# @param columns [Integer]
|
85
|
+
# @param rows [Integer]
|
86
|
+
# @param colour [String]
|
87
|
+
# @return table 2 dimensions [Array] pixels coordinates rows and coloumns with colour
|
88
|
+
def fill_table(columns, rows, colour = 'O')
|
89
|
+
table = []
|
90
|
+
rows.times do |row|
|
91
|
+
table[row] =Array.new(columns,colour)
|
92
|
+
end
|
93
|
+
table
|
94
|
+
end
|
95
|
+
|
96
|
+
# to draw a vertical line
|
97
|
+
# @param args [String] in this case the command is for example V 2 1 4 W
|
98
|
+
# @return VerticalLineValidator.validate response [Symbol|String] could be :valid or Error Message string
|
99
|
+
def draw_vertical_line(args)
|
100
|
+
validator=Validators::VerticalLineValidator.validate(args, @columns, @rows)
|
101
|
+
if validator == :valid
|
102
|
+
column=Integer(args[1]) - 1
|
103
|
+
row_start = Integer(args[2]) - 1
|
104
|
+
row_end = Integer(args[3]) - 1
|
105
|
+
(row_start..row_end).each do |row|
|
106
|
+
@table[row][column]=args[4]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
validator
|
110
|
+
end
|
111
|
+
|
112
|
+
# to draw a horinzontal line
|
113
|
+
# @param args [String] in this case the command is for example H 2 1 4 C
|
114
|
+
# @return VerticalLineValidator.validate response [Symbol|String] could be :valid or Error Message string
|
115
|
+
def draw_horizontal_line(args)
|
116
|
+
validator=Validators::HorizontalLineValidator.validate(args, @columns, @rows)
|
117
|
+
if validator == :valid
|
118
|
+
column_start=Integer(args[1]) - 1
|
119
|
+
column_end = Integer(args[2]) - 1
|
120
|
+
row = Integer(args[3]) - 1
|
121
|
+
(column_start..column_end).each do |column|
|
122
|
+
@table[row][column]=args[4]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
validator
|
126
|
+
end
|
127
|
+
|
128
|
+
# to fill a region with specific colour with command F M N C
|
129
|
+
# @param args [String] in this case the command is for example F 4 2 A
|
130
|
+
# @return FillRegionValidator.validate response [Symbol|String] could be :valid or Error Message string
|
131
|
+
def fill_region(args)
|
132
|
+
validator=Validators::FillRegionValidator.validate(args, @columns, @rows)
|
133
|
+
if validator == :valid
|
134
|
+
column=Integer(args[1]) - 1
|
135
|
+
row = Integer(args[2]) - 1
|
136
|
+
searched = []
|
137
|
+
same_region = [[row , column]]
|
138
|
+
begin
|
139
|
+
same_region, searched = get_region(same_region,searched)
|
140
|
+
end while not (same_region - searched).empty?
|
141
|
+
|
142
|
+
same_region.each do |fill_coordinate|
|
143
|
+
r=fill_coordinate[0]
|
144
|
+
c=fill_coordinate[1]
|
145
|
+
@table[r][c]=args[3]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
validator
|
149
|
+
end
|
150
|
+
|
151
|
+
# search the same colour adjacent pixels
|
152
|
+
# @param same_region [Array] the region has finded
|
153
|
+
# @param searched [Array] the pixels that it has a previous search
|
154
|
+
def get_region(same_region, searched)
|
155
|
+
|
156
|
+
diff = same_region - searched
|
157
|
+
# search only the points not searched before
|
158
|
+
diff.each do |find_center|
|
159
|
+
row= find_center[0]
|
160
|
+
column = find_center[1]
|
161
|
+
if row> (BitmapCmdEditor::MIN_ROWS - 1)
|
162
|
+
same_region.push [row - 1 , column] if @table[row - 1][column] == @table[row][column]
|
163
|
+
end
|
164
|
+
if row< (@rows -1)
|
165
|
+
same_region.push [row + 1 , column] if @table[row + 1][column] == @table[row][column]
|
166
|
+
end
|
167
|
+
if column> (BitmapCmdEditor::MIN_COLUMNS - 1 )
|
168
|
+
same_region.push [row , column - 1] if @table[row][column - 1] == @table[row][column]
|
169
|
+
end
|
170
|
+
if column< (@columns - 1)
|
171
|
+
same_region.push [row , column + 1] if @table[row][column + 1] == @table[row][column]
|
172
|
+
end
|
173
|
+
searched.push find_center
|
174
|
+
end
|
175
|
+
same_region = same_region.uniq
|
176
|
+
searched = searched.uniq
|
177
|
+
[same_region , searched]
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
# print the table with the command S
|
182
|
+
# @param args [String] in this case is S
|
183
|
+
# @return PrintTableValidator.validate response [Symbol|String] could be :valid or Error Message string
|
184
|
+
def print_table(args)
|
185
|
+
validator=Validators::PrintTableValidator.validate(args)
|
186
|
+
if validator == :valid
|
187
|
+
puts "\n"
|
188
|
+
@table.each do |row|
|
189
|
+
puts row.join(' ')
|
190
|
+
end
|
191
|
+
end
|
192
|
+
validator
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'readline'
|
2
|
+
|
3
|
+
module BitmapCmdEditor
|
4
|
+
# @author Diego Hernán Piccinini Lagos
|
5
|
+
# This class handle the the interactive loop until X + Enter to exit
|
6
|
+
|
7
|
+
class Client
|
8
|
+
class << self
|
9
|
+
# getting commands in a loop
|
10
|
+
def get_commands
|
11
|
+
begin
|
12
|
+
puts WELCOME_MESSAGE
|
13
|
+
bitmap = Bitmap.new
|
14
|
+
loop do
|
15
|
+
input = Readline.readline("> ")
|
16
|
+
input.strip!
|
17
|
+
|
18
|
+
# the command X must not be processed it's only to exit
|
19
|
+
if input=='X'
|
20
|
+
puts "\nEnd the Session..."
|
21
|
+
break
|
22
|
+
else
|
23
|
+
process=bitmap.process_command(input)
|
24
|
+
puts process unless process==:valid
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
rescue => err
|
29
|
+
puts err.message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module BitmapCmdEditor
|
2
|
+
# @author Diego Hernán Piccinini Lagos
|
3
|
+
class NotImplementedCommand < NotImplementedError; end
|
4
|
+
class CreateImageArgumentError < ArgumentError; end
|
5
|
+
class MoreColumnsThanAllowed < RangeError; end
|
6
|
+
class MoreRowsThanAllowed < RangeError; end
|
7
|
+
class LessColumnsThanAllowed < RangeError; end
|
8
|
+
class LessRowsThanAllowed < RangeError; end
|
9
|
+
class OutOfRange < RangeError; end
|
10
|
+
class ClearImageArgumentError < ArgumentError; end
|
11
|
+
class ColourPixelArgumentError < ArgumentError; end
|
12
|
+
class HorizontalLineArgumentError < ArgumentError; end
|
13
|
+
class VerticalLineArgumentError < ArgumentError; end
|
14
|
+
class FillRegionArgumentError < ArgumentError; end
|
15
|
+
class PrintTableArgumentError < ArgumentError; end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module BitmapCmdEditor
|
2
|
+
module Validators
|
3
|
+
# @author Diego Hernán Piccinini Lagos
|
4
|
+
# To validate a new bitmap image table created
|
5
|
+
class ClearImageValidator
|
6
|
+
class << self
|
7
|
+
# @param args [Array] the command 0=> 'C'
|
8
|
+
def validate(args)
|
9
|
+
begin
|
10
|
+
raise ClearImageArgumentError.new(
|
11
|
+
ErrorMessage.new(:clear_image_wrongs_arguments).show_content) unless args.count == 1
|
12
|
+
:valid
|
13
|
+
rescue => err
|
14
|
+
err.message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module BitmapCmdEditor
|
2
|
+
module Validators
|
3
|
+
# @author Diego Hernán Piccinini Lagos
|
4
|
+
class ColourPixelValidator
|
5
|
+
class << self
|
6
|
+
# @param args [Array] the command 0=> 'L' and 1=> columns 2 =>rows 3 => colour
|
7
|
+
# @param bitmap_columns [Integer] number of columns of the image created
|
8
|
+
# @param bitmap_rows [Integer] number of rows of the image created
|
9
|
+
def validate(args, bitmap_columns, bitmap_rows)
|
10
|
+
begin
|
11
|
+
raise ColourPixelArgumentError.new(
|
12
|
+
ErrorMessage.new(:command_wrong_arguments, {:arguments => 3}).show_content) unless args.count == 4
|
13
|
+
|
14
|
+
begin
|
15
|
+
columns= Integer(args[1])
|
16
|
+
rows= Integer(args[2])
|
17
|
+
rescue => err
|
18
|
+
raise TypeError.new(ErrorMessage.new(:coordinates_are_not_integer).show_content)
|
19
|
+
end
|
20
|
+
ValidatorHelper.out_of_range('columns',BitmapCmdEditor::MIN_COLUMNS,bitmap_columns,columns)
|
21
|
+
|
22
|
+
ValidatorHelper.out_of_range('rows',BitmapCmdEditor::MIN_ROWS,bitmap_rows,rows)
|
23
|
+
|
24
|
+
raise TypeError.new(ErrorMessage.new(:the_colour_is_invalid).show_content) unless ('A'..'Z').include?args[3]
|
25
|
+
|
26
|
+
:valid
|
27
|
+
rescue => err
|
28
|
+
err.message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module BitmapCmdEditor
|
2
|
+
module Validators
|
3
|
+
# @author Diego Hernán Piccinini Lagos
|
4
|
+
# To validate the command and show the user a help message
|
5
|
+
class CommandValidator
|
6
|
+
class << self
|
7
|
+
# @param input [String] the input command string
|
8
|
+
def validate(input)
|
9
|
+
begin
|
10
|
+
args=input.split(' ')
|
11
|
+
raise NotImplementedCommand.new(ErrorMessage.new(:command_not_exist).show_content) unless BitmapCmdEditor::COMMANDS.include?(args[0])
|
12
|
+
:valid
|
13
|
+
rescue NotImplementedCommand => err
|
14
|
+
err.message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module BitmapCmdEditor
|
2
|
+
module Validators
|
3
|
+
# @author Diego Hernán Piccinini Lagos
|
4
|
+
# To validate a new bitmap image table created
|
5
|
+
class CreateImageValidator
|
6
|
+
class << self
|
7
|
+
# @param args [Array] the command 0=> 'I' and 1=> columns 2 =>rows
|
8
|
+
def validate(args)
|
9
|
+
begin
|
10
|
+
raise CreateImageArgumentError.new(
|
11
|
+
ErrorMessage.new(:command_wrong_arguments, {:arguments => 2}).show_content) unless args.count == 3
|
12
|
+
begin
|
13
|
+
columns= Integer(args[1])
|
14
|
+
rows= Integer(args[2])
|
15
|
+
rescue => err
|
16
|
+
raise TypeError.new(ErrorMessage.new(:coordinates_are_not_integer).show_content)
|
17
|
+
end
|
18
|
+
ValidatorHelper.more_than_max('columns',BitmapCmdEditor::MAX_COLUMNS,columns)
|
19
|
+
|
20
|
+
ValidatorHelper.more_than_max('rows',BitmapCmdEditor::MAX_ROWS,rows)
|
21
|
+
|
22
|
+
ValidatorHelper.less_than_min('columns',BitmapCmdEditor::MIN_COLUMNS,columns)
|
23
|
+
|
24
|
+
ValidatorHelper.less_than_min('rows',BitmapCmdEditor::MIN_ROWS,rows)
|
25
|
+
|
26
|
+
:valid
|
27
|
+
rescue => err
|
28
|
+
err.message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|