bitmapped 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +4 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/ChangeLog.rdoc +4 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +20 -0
- data/README.md +65 -0
- data/Rakefile +42 -0
- data/bin/bitmapped +11 -0
- data/bitmapped.gemspec +23 -0
- data/lib/bitmapped/bitmap.rb +122 -0
- data/lib/bitmapped/cli.rb +28 -0
- data/lib/bitmapped/exceptions.rb +4 -0
- data/lib/bitmapped/validators/validate_column_row_input.rb +21 -0
- data/lib/bitmapped/validators/validate_fill_input.rb +24 -0
- data/lib/bitmapped/validators/validate_segment_input.rb +24 -0
- data/lib/bitmapped/validators/validation_helper.rb +18 -0
- data/lib/bitmapped/version.rb +4 -0
- data/lib/bitmapped.rb +1 -0
- data/spec/bitmap_spec.rb +210 -0
- data/spec/bitmapped_spec.rb +8 -0
- data/spec/exceptions_spec.rb +20 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/validators/validate_column_row_input_spec.rb +28 -0
- data/spec/validators/validate_fill_input_spec.rb +28 -0
- data/spec/validators/validate_helper_spec.rb +28 -0
- data/spec/validators/validate_segment_input_spec.rb +28 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 99702c03528a066944f878c4b91150111a57109c
|
4
|
+
data.tar.gz: bb7495610f144df0ed5ebbbf4073846add4a7984
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 310a13fb27eb9a4124623c7088e2de83bf4e323fe414e2721c35bff6ddaa6e9067e95bb48296b6562410816eca7ad31455ab5ece03416b9a58262bad8ae604c1
|
7
|
+
data.tar.gz: 84f16acd5af696546e80aba724afa45d966dc0e1f7aed02643cf158c94b54d63b20acbfb21f98605fa868dc208eb6728b4d1283f86bca1ec9d16d853461daf42
|
data/.document
ADDED
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/.travis.yml
ADDED
data/ChangeLog.rdoc
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2015 Ashley Connor
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# bitmapped
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/github/ashleyconnor/bitmapped/badges/gpa.svg)](https://codeclimate.com/github/ashleyconnor/bitmapped) [![Build Status](https://travis-ci.org/ashleyconnor/bitmapped.svg)](https://travis-ci.org/ashleyconnor/bitmapped)
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
Bitmapped is an command-line editor which allows you to create and edit bitmap-like text images.
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
Bitmapped accepts various commands to create and edit bitmap-like text images:
|
12
|
+
|
13
|
+
| Command | Description | Key | Parameters |
|
14
|
+
|---------------------|------------------------------------------------------------|-----|----------------------------------------|
|
15
|
+
| Initiate Bitmap | Initiates a Bitmap of the given size | I | Columns:Int, Rows:Int |
|
16
|
+
| Clear | Clears the Bitmap setting all cells to "0" | C | |
|
17
|
+
| Color Cell | Colors the cell at the given co-ordinates | L | Column:Int, Row:Int, Color:String |
|
18
|
+
| Vertically Line | Colors multiple cells on specified column between rows X Y | V | Column:Int, Row:X, Row:Y, Color:String |
|
19
|
+
| Horizontal Line | Colors multiple cells on specified row between rows X Y | H | Row:X, Row:Y, Row:Int, Color:String |
|
20
|
+
| Fill (Paint Bucket) | Fills a given cell and surrounding cells of the same color | F | Column:Int, Row:Int, Color:String |
|
21
|
+
| Exit | Exits the program | X | |
|
22
|
+
|
23
|
+
|
24
|
+
## Examples
|
25
|
+
bundle exec bitmapped
|
26
|
+
> I 5 6
|
27
|
+
> L 2 3 A
|
28
|
+
> S
|
29
|
+
+---+---+---+---+---+
|
30
|
+
| 0 | 0 | 0 | 0 | 0 |
|
31
|
+
| 0 | 0 | 0 | 0 | 0 |
|
32
|
+
| 0 | 0 | 0 | 0 | 0 |
|
33
|
+
| 0 | 0 | 0 | 0 | 0 |
|
34
|
+
| 0 | 0 | 0 | 0 | 0 |
|
35
|
+
| 0 | 0 | 0 | 0 | 0 |
|
36
|
+
+---+---+---+---+---+
|
37
|
+
> F 3 3 J
|
38
|
+
> V 2 3 4 W
|
39
|
+
> H 3 4 2 Z
|
40
|
+
> S
|
41
|
+
+---+---+---+---+---+
|
42
|
+
| J | J | J | J | J |
|
43
|
+
| J | J | Z | Z | J |
|
44
|
+
| J | W | J | J | J |
|
45
|
+
| J | W | J | J | J |
|
46
|
+
| J | J | J | J | J |
|
47
|
+
| J | J | J | J | J |
|
48
|
+
+---+---+---+---+---+
|
49
|
+
|
50
|
+
## Requirements
|
51
|
+
Ruby 2.0+
|
52
|
+
## Install
|
53
|
+
|
54
|
+
$ gem install bitmapped
|
55
|
+
|
56
|
+
## TODO
|
57
|
+
|
58
|
+
* Custom commands
|
59
|
+
* Refactor Bitmap commands into objects with tests
|
60
|
+
|
61
|
+
### Copyright
|
62
|
+
|
63
|
+
Copyright (c) 2015 **Ashley Connor**
|
64
|
+
|
65
|
+
See LICENSE.txt for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn e.message
|
9
|
+
warn "Run `gem install bundler` to install Bundler."
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
Bundler.setup(:development)
|
15
|
+
rescue Bundler::BundlerError => e
|
16
|
+
warn e.message
|
17
|
+
warn "Run `bundle install` to install missing gems."
|
18
|
+
exit e.status_code
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake'
|
22
|
+
|
23
|
+
require 'rubygems/tasks'
|
24
|
+
Gem::Tasks.new
|
25
|
+
|
26
|
+
require 'rdoc/task'
|
27
|
+
RDoc::Task.new do |rdoc|
|
28
|
+
rdoc.title = "bitmapped"
|
29
|
+
end
|
30
|
+
task :doc => :rdoc
|
31
|
+
|
32
|
+
begin
|
33
|
+
require 'rspec/core/rake_task'
|
34
|
+
RSpec::Core::RakeTask.new
|
35
|
+
rescue LoadError
|
36
|
+
task :spec do
|
37
|
+
abort "Please run `gem install rspec` to install RSpec."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :spec
|
42
|
+
task :default => :spec
|
data/bin/bitmapped
ADDED
data/bitmapped.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path('../lib/bitmapped/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "bitmapped"
|
7
|
+
gem.version = Bitmapped::VERSION
|
8
|
+
gem.platform = Gem::Platform::RUBY
|
9
|
+
gem.summary = %q{Bitmap CLI program}
|
10
|
+
gem.description = %q{Bitmap CLI program}
|
11
|
+
gem.license = "MIT"
|
12
|
+
gem.authors = ["Ashley Connor"]
|
13
|
+
gem.email = "ashconnor@me.com"
|
14
|
+
gem.homepage = "https://rubygems.org/gems/bitmapped"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ['lib']
|
20
|
+
|
21
|
+
gem.required_ruby_version = ">= 2.0.0"
|
22
|
+
gem.add_runtime_dependency 'terminal-table', '~> 1.4', '>= 1.4.5'
|
23
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
Dir[File.join(File.dirname(__FILE__), 'validators', '*.rb')].each {|file| require file }
|
2
|
+
|
3
|
+
require 'terminal-table'
|
4
|
+
require 'bitmapped/exceptions'
|
5
|
+
|
6
|
+
module Bitmapped
|
7
|
+
class Bitmap
|
8
|
+
|
9
|
+
attr_accessor :pixels, :table, :rows, :columns
|
10
|
+
|
11
|
+
def command(input)
|
12
|
+
begin
|
13
|
+
case input.shift
|
14
|
+
when "I"
|
15
|
+
self.columns, self.rows = Validators::ValidateColumnRowInput.parse_and_validate(input)
|
16
|
+
self.pixels = populate_pixels(self.columns, self.rows)
|
17
|
+
when "X"
|
18
|
+
raise Interrupt
|
19
|
+
when bitmap_available("C")
|
20
|
+
self.pixels = populate_pixels(self.columns, self.rows)
|
21
|
+
when bitmap_available("L")
|
22
|
+
column, row, color = Validators::ValidateFillInput.parse_and_validate(input)
|
23
|
+
color_command(column, row, color)
|
24
|
+
when bitmap_available("V")
|
25
|
+
column, start, finish, color = Validators::ValidateSegmentInput.parse_and_validate(input)
|
26
|
+
vertical_command(column, start, finish, color)
|
27
|
+
when bitmap_available("H")
|
28
|
+
start, finish, row, color = Validators::ValidateSegmentInput.parse_and_validate(input)
|
29
|
+
horizontal_command(start, finish, row, color)
|
30
|
+
when bitmap_available("F")
|
31
|
+
column, row, color = Validators::ValidateFillInput.parse_and_validate(input)
|
32
|
+
fill_command(column, row, color)
|
33
|
+
when bitmap_available("S")
|
34
|
+
formatted_table
|
35
|
+
when "C", "L", "V", "H", "F", "S"
|
36
|
+
"Bitmap has not been initialised, run command 'I' with valid arguments"
|
37
|
+
else
|
38
|
+
"Invalid Command"
|
39
|
+
end
|
40
|
+
rescue ParsingError => e
|
41
|
+
"Invalid parameters"
|
42
|
+
rescue InvalidCoordinatesError => e
|
43
|
+
"Invalid co-ordinates"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
def populate_pixels(x, y)
|
49
|
+
Array.new(self.rows) { Array.new(self.columns) { "0" } }
|
50
|
+
end
|
51
|
+
|
52
|
+
def bitmap_available(command)
|
53
|
+
lambda { |option| option == command && self.pixels }
|
54
|
+
end
|
55
|
+
|
56
|
+
def formatted_table
|
57
|
+
self.table ||= Terminal::Table.new
|
58
|
+
self.table.rows = self.pixels
|
59
|
+
self.table
|
60
|
+
# self.pixels.each { |row| puts row.join("") } # no fancy table
|
61
|
+
end
|
62
|
+
|
63
|
+
def color_command(x, y, color)
|
64
|
+
x, y = coordinates_to_array_indexes(x, y)
|
65
|
+
self.pixels[y][x] = color
|
66
|
+
end
|
67
|
+
|
68
|
+
def vertical_command(column, x, y, color)
|
69
|
+
raise InvalidCoordinatesError unless (0 < column && column <= self.columns)
|
70
|
+
x, y = coordinates_to_array_indexes(x, y)
|
71
|
+
column = column - 1
|
72
|
+
self.pixels[x..y].each { |row| row[column] = color }
|
73
|
+
end
|
74
|
+
|
75
|
+
def horizontal_command(x, y, row, color)
|
76
|
+
raise InvalidCoordinatesError unless (0 < row && row <= self.rows)
|
77
|
+
x, y = coordinates_to_array_indexes(x, y)
|
78
|
+
row = row - 1
|
79
|
+
self.pixels[row][x..y] = Array.new((x..y).size, color)
|
80
|
+
end
|
81
|
+
|
82
|
+
def fill_command(x, y, replacement_color)
|
83
|
+
x, y = coordinates_to_array_indexes(x, y)
|
84
|
+
target_color = self.pixels[x][y]
|
85
|
+
queue = [[x,y]]
|
86
|
+
|
87
|
+
until queue.empty?
|
88
|
+
x, y = queue.pop
|
89
|
+
next if (!valid_cooridinates(x+1, y+1) || self.pixels[x][y] != target_color)
|
90
|
+
self.pixels[x][y] = replacement_color
|
91
|
+
queue << [x+1, y] # east
|
92
|
+
queue << [x-1, y] # west
|
93
|
+
queue << [x, y+1] # south
|
94
|
+
queue << [x, y-1] # north
|
95
|
+
|
96
|
+
# and if we are doing 8-direction flood-fill...
|
97
|
+
# queue << [x+1, y-1] # north-east
|
98
|
+
# queue << [x-1, y-1] # north-west
|
99
|
+
# queue << [x+1, y+1] # south-east
|
100
|
+
# queue << [x-1, y+1] # south-west
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def valid_cooridinates(x, y)
|
105
|
+
if (0 <= x && x <= self.columns) && (0 <= y && y <= self.rows)
|
106
|
+
true
|
107
|
+
else
|
108
|
+
false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def coordinates_to_array_indexes(x, y)
|
113
|
+
x = x.to_i - 1
|
114
|
+
y = y.to_i - 1
|
115
|
+
if valid_cooridinates(x, y)
|
116
|
+
[x, y]
|
117
|
+
else
|
118
|
+
raise InvalidCoordinatesError
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'bitmapped/bitmap'
|
2
|
+
|
3
|
+
require 'readline'
|
4
|
+
|
5
|
+
module Bitmapped
|
6
|
+
class Cli
|
7
|
+
class << self
|
8
|
+
def start
|
9
|
+
begin
|
10
|
+
bitmap = Bitmap.new
|
11
|
+
puts "Bitmapped Command Centre (Ctrl+C to exit):"
|
12
|
+
|
13
|
+
loop do
|
14
|
+
input = split_input(Readline.readline("> "))
|
15
|
+
puts bitmap.command(input)
|
16
|
+
end
|
17
|
+
rescue Interrupt => interrupt
|
18
|
+
puts "\nExiting..."
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def split_input(input)
|
24
|
+
input.strip.split(' ')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bitmapped/exceptions'
|
2
|
+
|
3
|
+
module Bitmapped
|
4
|
+
module Validators
|
5
|
+
class ValidateColumnRowInput
|
6
|
+
class << self
|
7
|
+
def parse_and_validate(input)
|
8
|
+
begin
|
9
|
+
raise ArgumentError unless input.size == 2
|
10
|
+
|
11
|
+
columns = Integer(input[0])
|
12
|
+
rows = Integer(input[1])
|
13
|
+
[columns, rows]
|
14
|
+
rescue ArgumentError => ae
|
15
|
+
raise ParsingError
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bitmapped/exceptions'
|
2
|
+
require 'bitmapped/validators/validation_helper'
|
3
|
+
|
4
|
+
module Bitmapped
|
5
|
+
module Validators
|
6
|
+
class ValidateFillInput
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def parse_and_validate(input)
|
10
|
+
begin
|
11
|
+
raise ArgumentError unless input.size == 3
|
12
|
+
|
13
|
+
columns = Integer(input[0])
|
14
|
+
rows = Integer(input[1])
|
15
|
+
color = ValidationHelper.parse_color(input[2].strip)
|
16
|
+
[columns, rows, color]
|
17
|
+
rescue ArgumentError => ae
|
18
|
+
raise ParsingError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bitmapped/exceptions'
|
2
|
+
require 'bitmapped/validators/validation_helper'
|
3
|
+
|
4
|
+
module Bitmapped
|
5
|
+
module Validators
|
6
|
+
class ValidateSegmentInput
|
7
|
+
class << self
|
8
|
+
def parse_and_validate(input)
|
9
|
+
begin
|
10
|
+
raise ArgumentError unless input.size == 4
|
11
|
+
|
12
|
+
segement_a = Integer(input[0])
|
13
|
+
segement_b = Integer(input[1])
|
14
|
+
segement_c = Integer(input[2])
|
15
|
+
color = ValidationHelper.parse_color(input[3].strip)
|
16
|
+
[segement_a, segement_b, segement_c, color]
|
17
|
+
rescue ArgumentError => ae
|
18
|
+
raise ParsingError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bitmapped/exceptions'
|
2
|
+
|
3
|
+
module Bitmapped
|
4
|
+
module Validators
|
5
|
+
module ValidationHelper
|
6
|
+
class << self
|
7
|
+
def parse_color(color)
|
8
|
+
color = color.strip
|
9
|
+
if [*'A'..'Z'].include?(color)
|
10
|
+
color
|
11
|
+
else
|
12
|
+
raise ParsingError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/bitmapped.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bitmapped/version'
|
data/spec/bitmap_spec.rb
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bitmapped/bitmap'
|
4
|
+
|
5
|
+
describe Bitmap do
|
6
|
+
|
7
|
+
subject { Bitmap.new }
|
8
|
+
|
9
|
+
shared_examples_for "a command requiring an initialised bitmap" do |arg|
|
10
|
+
it "returns an error message" do
|
11
|
+
expect(subject.command([arg])).to eq("Bitmap has not been initialised, run command 'I' with valid arguments")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe 'the I command' do
|
16
|
+
it 'initializes a grid of that size' do
|
17
|
+
args = ["I", "2", "3"]
|
18
|
+
pixels = [["0", "0"],
|
19
|
+
["0", "0"],
|
20
|
+
["0", "0"]]
|
21
|
+
|
22
|
+
subject.command(args)
|
23
|
+
|
24
|
+
expect(subject.columns).to eq(2)
|
25
|
+
expect(subject.rows).to eq(3)
|
26
|
+
expect(subject.pixels).to eq(pixels)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'overwrites the old bitmap given the I command again' do
|
30
|
+
first_args = ["I", "2", "3"]
|
31
|
+
second_args = ["I", "3", "2"]
|
32
|
+
pixels = [["0", "0", "0"],
|
33
|
+
["0", "0", "0"]]
|
34
|
+
|
35
|
+
subject.command(first_args)
|
36
|
+
subject.command(second_args)
|
37
|
+
|
38
|
+
expect(subject.columns).to eq(3)
|
39
|
+
expect(subject.rows).to eq(2)
|
40
|
+
expect(subject.pixels).to eq(pixels)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'the X command' do
|
45
|
+
it 'raises an Interrupt exception' do
|
46
|
+
expect{ subject.command(["X"]) } .to raise_error(Interrupt)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'the C command' do
|
51
|
+
it_should_behave_like "a command requiring an initialised bitmap", "C"
|
52
|
+
|
53
|
+
context 'when the bitmap is initialised' do
|
54
|
+
it 'replaces all of the bitmap colors with "0"' do
|
55
|
+
setup_pixels(subject, 3, 2, "X")
|
56
|
+
subject.command(["C"])
|
57
|
+
|
58
|
+
expect(subject.pixels).to eq([["0", "0", "0"],
|
59
|
+
["0", "0", "0"]])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'the L command' do
|
65
|
+
it_should_behave_like "a command requiring an initialised bitmap", "L"
|
66
|
+
|
67
|
+
context 'when the bitmap is initialised' do
|
68
|
+
before(:example) do
|
69
|
+
setup_pixels(subject, 3, 2)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'replaces the color at those coordinates' do
|
73
|
+
subject.command(["L", "1", "2", "Z"])
|
74
|
+
subject.command(["L", "2", "1", "Z"])
|
75
|
+
|
76
|
+
expect(subject.pixels).to eq([["0", "Z", "0"],
|
77
|
+
["Z", "0", "0"]])
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns an error when the coordinates are not valid' do
|
81
|
+
expect(subject.command(["L", "4", "4", "Z"])).to eq("Invalid co-ordinates")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'the V command' do
|
87
|
+
it_should_behave_like "a command requiring an initialised bitmap", "V"
|
88
|
+
|
89
|
+
context 'when the bitmap is initialised' do
|
90
|
+
before(:example) do
|
91
|
+
setup_pixels(subject, 4, 4)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should draw a vertical color segment between the 2 rows' do
|
95
|
+
subject.command(["V", "3", "2", "4", "X"])
|
96
|
+
subject.command(["V", "1", "1", "3", "Z"])
|
97
|
+
|
98
|
+
expect(subject.pixels).to eq([["Z","0","0","0"],
|
99
|
+
["Z","0","X","0"],
|
100
|
+
["Z","0","X","0"],
|
101
|
+
["0","0","X","0"]]
|
102
|
+
)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns an error when the coordinates are invalid' do
|
106
|
+
[["V", "10", "1", "3", "Z"], ["V", "1", "10", "3", "Z"], ["V", "1", "1", "10", "Z"]].each do |args|
|
107
|
+
expect(subject.command(args)).to eq("Invalid co-ordinates")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'returns an error when the parameters are invalid' do
|
112
|
+
[["V", "10", "3", "Z"], ["V", "Z", "10", "3", "3"], ["V", "1", "1", "10", "1"]].each do |args|
|
113
|
+
expect(subject.command(args)).to eq("Invalid parameters")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe 'the H command' do
|
120
|
+
it_should_behave_like "a command requiring an initialised bitmap", "H"
|
121
|
+
|
122
|
+
context 'when the bitmap is initialised' do
|
123
|
+
before(:example) do
|
124
|
+
setup_pixels(subject, 4, 4)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should draw a horizontal color segment between the 2 columns' do
|
128
|
+
subject.command(["H", "2", "4", "2", "X"])
|
129
|
+
subject.command(["H", "1", "4", "4", "Z"])
|
130
|
+
|
131
|
+
expect(subject.pixels).to eq([["0","0","0","0"],
|
132
|
+
["0","X","X","X"],
|
133
|
+
["0","0","0","0"],
|
134
|
+
["Z","Z","Z","Z"]]
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'returns an error when the coordinates are invalid' do
|
139
|
+
[["H", "10", "1", "3", "Z"], ["H", "1", "10", "3", "Z"], ["H", "1", "1", "10", "Z"]].each do |args|
|
140
|
+
expect(subject.command(args)).to eq("Invalid co-ordinates")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'returns an error when the parameters are invalid' do
|
145
|
+
[["H", "10", "3", "Z"], ["H", "Z", "10", "3", "3"], ["H", "1", "1", "10", "1", "Z"]].each do |args|
|
146
|
+
expect(subject.command(args)).to eq("Invalid parameters")
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe 'the F command' do
|
153
|
+
it_should_behave_like "a command requiring an initialised bitmap", "F"
|
154
|
+
|
155
|
+
context 'when the bitmap is initialised' do
|
156
|
+
|
157
|
+
before(:example) do
|
158
|
+
setup_pixels(subject, 4, 4)
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should fill region on the bitmap with the color given' do
|
162
|
+
subject.command(["F", "3", "3", "J"])
|
163
|
+
expect(subject.pixels).to eq([["J","J","J","J"],
|
164
|
+
["J","J","J","J"],
|
165
|
+
["J","J","J","J"],
|
166
|
+
["J","J","J","J"]])
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
describe 'the S command' do
|
172
|
+
it_should_behave_like "a command requiring an initialised bitmap", "S"
|
173
|
+
|
174
|
+
context 'when the bitmap is initialised' do
|
175
|
+
before(:example) do
|
176
|
+
setup_pixels(subject, 4, 4)
|
177
|
+
end
|
178
|
+
|
179
|
+
let(:formatted_table) { %{+---+---+---+---+
|
180
|
+
| 0 | 0 | 0 | 0 |
|
181
|
+
| 0 | 0 | 0 | 0 |
|
182
|
+
| 0 | 0 | 0 | 0 |
|
183
|
+
| 0 | 0 | 0 | 0 |
|
184
|
+
+---+---+---+---+}.gsub(/[^\S\n]{2,}/, '')}
|
185
|
+
|
186
|
+
let(:filled_formatted_table) {%{+---+---+---+---+
|
187
|
+
| J | J | J | J |
|
188
|
+
| J | J | J | J |
|
189
|
+
| J | J | J | J |
|
190
|
+
| J | J | J | J |
|
191
|
+
+---+---+---+---+}.gsub(/[^\S\n]{2,}/, '')}
|
192
|
+
|
193
|
+
it 'should output a formatted table' do
|
194
|
+
expect(subject.command(["S"]).to_s).to eq(formatted_table)
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'should output a correctly formatted table after fill command' do
|
198
|
+
subject.command(["F", "3", "3", "J"])
|
199
|
+
|
200
|
+
expect(subject.command(["S"]).to_s).to eq(filled_formatted_table)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def setup_pixels(subject, columns, rows, color="0")
|
206
|
+
subject.columns = columns
|
207
|
+
subject.rows = rows
|
208
|
+
subject.pixels = Array.new(rows) { Array.new(columns) { color } }
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bitmapped/exceptions'
|
4
|
+
|
5
|
+
describe ParsingError do
|
6
|
+
subject { ParsingError }
|
7
|
+
|
8
|
+
it 'inherits from StandardError' do
|
9
|
+
expect(subject.superclass).to eq(StandardError)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe InvalidCoordinatesError do
|
14
|
+
subject { InvalidCoordinatesError }
|
15
|
+
|
16
|
+
it 'inherits from StandardError' do
|
17
|
+
expect(subject.superclass).to eq(StandardError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bitmapped/exceptions'
|
4
|
+
|
5
|
+
describe Validators::ValidateColumnRowInput do
|
6
|
+
context 'given valid input' do
|
7
|
+
|
8
|
+
let(:valid_inputs) { [["2", "2"], ["2", "3"], ["10", "99"]] }
|
9
|
+
let(:outputs) { [[2, 2], [2, 3], [10, 99]] }
|
10
|
+
|
11
|
+
it 'should return an array of parsed values' do
|
12
|
+
valid_inputs.each_with_index do |input, index|
|
13
|
+
expect(Validators::ValidateColumnRowInput.parse_and_validate(input)).to eq(outputs[index])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given invalid input' do
|
19
|
+
|
20
|
+
let(:invalid_inputs) { [["A", "2"], ["2", "Z"], ["99"]] }
|
21
|
+
|
22
|
+
it 'should return an error' do
|
23
|
+
invalid_inputs.each do |input|
|
24
|
+
expect{Validators::ValidateColumnRowInput.parse_and_validate(input)}.to raise_error(ParsingError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bitmapped/exceptions'
|
4
|
+
|
5
|
+
describe Validators::ValidateFillInput do
|
6
|
+
context 'given valid input' do
|
7
|
+
|
8
|
+
let(:valid_inputs) { [["2", "2", "C"], ["2", "3", "X"], ["10", "99", "Y"]] }
|
9
|
+
let(:outputs) { [[2, 2, "C"], [2, 3, "X"], [10, 99, "Y"]] }
|
10
|
+
|
11
|
+
it 'should return an array of parsed values' do
|
12
|
+
valid_inputs.each_with_index do |input, index|
|
13
|
+
expect(Validators::ValidateFillInput.parse_and_validate(input)).to eq(outputs[index])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given invalid input' do
|
19
|
+
|
20
|
+
let(:invalid_inputs) { [["A", "2", "2"], ["2", "Z", "A"], ["99", "Z"]] }
|
21
|
+
|
22
|
+
it 'should return an error' do
|
23
|
+
invalid_inputs.each do |input|
|
24
|
+
expect{Validators::ValidateFillInput.parse_and_validate(input)}.to raise_error(ParsingError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bitmapped/exceptions'
|
4
|
+
|
5
|
+
describe Validators::ValidationHelper do
|
6
|
+
context 'given valid input' do
|
7
|
+
|
8
|
+
let(:valid_inputs) { [" A", "B", "C "] }
|
9
|
+
let(:outputs) { ["A", "B", "C"] }
|
10
|
+
|
11
|
+
it 'should return an array of parsed values' do
|
12
|
+
valid_inputs.each_with_index do |input, index|
|
13
|
+
expect(Validators::ValidationHelper.parse_color(input)).to eq(outputs[index])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given invalid input' do
|
19
|
+
|
20
|
+
let(:invalid_inputs) { ["2", "!", "a"] }
|
21
|
+
|
22
|
+
it 'should return an error' do
|
23
|
+
invalid_inputs.each do |input|
|
24
|
+
expect{Validators::ValidationHelper.parse_color(input)}.to raise_error(ParsingError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'bitmapped/exceptions'
|
4
|
+
|
5
|
+
describe Validators::ValidateSegmentInput do
|
6
|
+
context 'given valid input' do
|
7
|
+
|
8
|
+
let(:valid_inputs) { [["2", "2", "2", "C"], ["2", "3", "3", "X"], ["10", "99", "1000", "Y"]] }
|
9
|
+
let(:outputs) { [[2, 2, 2, "C"], [2, 3, 3, "X"], [10, 99, 1000, "Y"]] }
|
10
|
+
|
11
|
+
it 'should return an array of parsed values' do
|
12
|
+
valid_inputs.each_with_index do |input, index|
|
13
|
+
expect(Validators::ValidateSegmentInput.parse_and_validate(input)).to eq(outputs[index])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'given invalid input' do
|
19
|
+
|
20
|
+
let(:invalid_inputs) { [["A", "2", "2", "2"], ["2", "2", "2", "2"], ["99", "50","Z"]] }
|
21
|
+
|
22
|
+
it 'should return an error' do
|
23
|
+
invalid_inputs.each do |input|
|
24
|
+
expect{Validators::ValidateSegmentInput.parse_and_validate(input)}.to raise_error(ParsingError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bitmapped
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ashley Connor
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: terminal-table
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.4.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.4'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.4.5
|
33
|
+
description: Bitmap CLI program
|
34
|
+
email: ashconnor@me.com
|
35
|
+
executables:
|
36
|
+
- bitmapped
|
37
|
+
extensions: []
|
38
|
+
extra_rdoc_files: []
|
39
|
+
files:
|
40
|
+
- ".document"
|
41
|
+
- ".gitignore"
|
42
|
+
- ".rspec"
|
43
|
+
- ".travis.yml"
|
44
|
+
- ChangeLog.rdoc
|
45
|
+
- Gemfile
|
46
|
+
- LICENSE.txt
|
47
|
+
- README.md
|
48
|
+
- Rakefile
|
49
|
+
- bin/bitmapped
|
50
|
+
- bitmapped.gemspec
|
51
|
+
- lib/bitmapped.rb
|
52
|
+
- lib/bitmapped/bitmap.rb
|
53
|
+
- lib/bitmapped/cli.rb
|
54
|
+
- lib/bitmapped/exceptions.rb
|
55
|
+
- lib/bitmapped/validators/validate_column_row_input.rb
|
56
|
+
- lib/bitmapped/validators/validate_fill_input.rb
|
57
|
+
- lib/bitmapped/validators/validate_segment_input.rb
|
58
|
+
- lib/bitmapped/validators/validation_helper.rb
|
59
|
+
- lib/bitmapped/version.rb
|
60
|
+
- spec/bitmap_spec.rb
|
61
|
+
- spec/bitmapped_spec.rb
|
62
|
+
- spec/exceptions_spec.rb
|
63
|
+
- spec/spec_helper.rb
|
64
|
+
- spec/validators/validate_column_row_input_spec.rb
|
65
|
+
- spec/validators/validate_fill_input_spec.rb
|
66
|
+
- spec/validators/validate_helper_spec.rb
|
67
|
+
- spec/validators/validate_segment_input_spec.rb
|
68
|
+
homepage: https://rubygems.org/gems/bitmapped
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 2.0.0
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.2.2
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Bitmap CLI program
|
92
|
+
test_files:
|
93
|
+
- spec/bitmap_spec.rb
|
94
|
+
- spec/bitmapped_spec.rb
|
95
|
+
- spec/exceptions_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
- spec/validators/validate_column_row_input_spec.rb
|
98
|
+
- spec/validators/validate_fill_input_spec.rb
|
99
|
+
- spec/validators/validate_helper_spec.rb
|
100
|
+
- spec/validators/validate_segment_input_spec.rb
|