ruby_marks 0.0.1.dev

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ ruby_marks
2
+ ==========
3
+
4
+ Ruby Marks
@@ -0,0 +1,82 @@
1
+ #encoding: utf-8
2
+ module RubyMarks
3
+
4
+ class ClockMark
5
+
6
+ attr_accessor :document, :position, :coordinates
7
+
8
+ def initialize(params={})
9
+ params.each do |k, v|
10
+ self.send("#{k}=", v) if self.respond_to?("#{k}=")
11
+ end
12
+ @coordinates = {x1: 0, x2: 0, y1: 0, y2: 0}
13
+ self.calc_coordinates
14
+ end
15
+
16
+ def calc_coordinates
17
+ @coordinates.tap do |coordinates|
18
+ if self.document
19
+ x = position[:x]
20
+ y = position[:y]
21
+
22
+ coordinates[:x1] = x
23
+ loop do
24
+ coordinates[:x1] -= 1
25
+ color = self.document.file.pixel_color(coordinates[:x1], y)
26
+ color = RubyMarks::RGB.to_hex(color.red, color.green, color.blue)
27
+
28
+ break if color != "#000000" || coordinates[:x1] <= 0
29
+ end
30
+
31
+ coordinates[:x2] = x
32
+ loop do
33
+ coordinates[:x2] += 1
34
+ color = self.document.file.pixel_color(coordinates[:x2], y)
35
+ color = RubyMarks::RGB.to_hex(color.red, color.green, color.blue)
36
+
37
+ break if color != "#000000" || coordinates[:x2] >= self.document.file.page.width
38
+ end
39
+
40
+ coordinates[:y1] = y
41
+ loop do
42
+ coordinates[:y1] -= 1
43
+ color = self.document.file.pixel_color(x, coordinates[:y1])
44
+ color = RubyMarks::RGB.to_hex(color.red, color.green, color.blue)
45
+
46
+ break if color != "#000000" || coordinates[:y1] <= 0
47
+ end
48
+
49
+ coordinates[:y2] = y
50
+ loop do
51
+ coordinates[:y2] += 1
52
+ color = self.document.file.pixel_color(x, coordinates[:y2])
53
+ color = RubyMarks::RGB.to_hex(color.red, color.green, color.blue)
54
+
55
+ break if color != "#000000" || coordinates[:y2] >= self.document.file.page.height
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ def width
62
+ coordinates[:x2] - coordinates[:x1]
63
+ end
64
+
65
+ def height
66
+ coordinates[:y2] - coordinates[:y1]
67
+ end
68
+
69
+ def horizontal_middle_position
70
+ coordinates[:x1] + self.width / 2
71
+ end
72
+
73
+ def vertical_middle_position
74
+ coordinates[:y1] + self.height / 2
75
+ end
76
+
77
+ def to_s
78
+ self.coordinates
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,145 @@
1
+ #encoding: utf-8
2
+ module RubyMarks
3
+
4
+ # Represents a scanned document
5
+ class Document
6
+
7
+ attr_reader :file
8
+
9
+ attr_accessor :current_position, :clock_marks
10
+
11
+ def initialize(file)
12
+ @file = Magick::Image.read(file).first
13
+ @current_position = {x: 0, y: 0}
14
+ @clock_marks = []
15
+ end
16
+
17
+ def filename
18
+ @file.filename
19
+ end
20
+
21
+ def move_to(x, y)
22
+ @current_position = {x: @current_position[:x] + x, y: @current_position[:y] + y}
23
+ end
24
+
25
+ def marked?
26
+ if self.current_position
27
+ area_x = 8
28
+ area_y = 8
29
+
30
+ x_pos = current_position[:x]-area_x..current_position[:x]+area_x
31
+ y_pos = current_position[:y]-area_y..current_position[:y]+area_y
32
+
33
+ colors = []
34
+
35
+ y_pos.each do |y|
36
+ x_pos.each do |x|
37
+ color = @file.pixel_color(x, y)
38
+ color = RubyMarks::RGB.to_hex(color.red, color.green, color.blue)
39
+ color = (color == "#000000") ? "." : " "
40
+ colors << color
41
+ end
42
+ end
43
+ black_intensity = colors.count(".") * 100 / colors.size
44
+ return black_intensity >= 40 ? true : false
45
+ end
46
+ end
47
+
48
+ def unmarked?
49
+ !marked?
50
+ end
51
+
52
+ def scan
53
+ result = {}
54
+ result.tap do |result|
55
+ position_before = @current_position
56
+
57
+ scan_clock_marks unless clock_marks.any?
58
+ groups = [87, 310, 535, 760, 985]
59
+ marks = %w{A B C D E}
60
+ clock_marks.each_with_index do |clock_mark, index|
61
+ group_hash = {}
62
+ groups.each_with_index do |group, index|
63
+ @current_position = {x: clock_mark.coordinates[:x2], y: clock_mark.vertical_middle_position}
64
+ move_to(group, 0)
65
+ markeds = []
66
+ marks.each do |mark|
67
+ markeds << mark if marked?
68
+ move_to(25, 0)
69
+ end
70
+ group_hash["group_#{index+1}".to_sym] = markeds if markeds.any?
71
+ end
72
+ result["clock_#{index+1}".to_sym] = group_hash if group_hash.any?
73
+ end
74
+ @current_position = position_before
75
+ end
76
+ end
77
+
78
+ def flag_position
79
+ file = @file.dup
80
+
81
+ file.tap do |file|
82
+ if current_position
83
+ add_mark file
84
+ end
85
+ end
86
+ end
87
+
88
+ def flag_all_marks
89
+ file = @file.dup
90
+
91
+ file.tap do |file|
92
+ position_before = @current_position
93
+
94
+ scan_clock_marks unless clock_marks.any?
95
+ groups = [87, 310, 535, 760, 985]
96
+ marks = %w{A B C D E}
97
+ clock_marks.each do |clock_mark|
98
+ groups.each do |group|
99
+ @current_position = {x: clock_mark.coordinates[:x2], y: clock_mark.vertical_middle_position}
100
+ move_to(group, 0)
101
+ marks.each do |mark|
102
+ add_mark file
103
+ move_to(25, 0)
104
+ end
105
+ end
106
+ end
107
+
108
+ @current_position = position_before
109
+ end
110
+ end
111
+
112
+ def scan_clock_marks
113
+ @clock_marks = []
114
+ x = 62
115
+ in_clock = false
116
+ total_height = @file && @file.page.height || 0
117
+ @clock_marks.tap do |clock_marks|
118
+ total_height.times do |y|
119
+ clock = {}
120
+ color = @file.pixel_color(x, y)
121
+ color = RubyMarks::RGB.to_hex(color.red, color.green, color.blue)
122
+ if !in_clock && color == "#000000"
123
+ in_clock = true
124
+ clock_marks << RubyMarks::ClockMark.new(document: self, position: {x: x, y: y+3})
125
+ elsif in_clock && color != "#000000"
126
+ in_clock = false
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ private
133
+ def add_mark(file)
134
+ flag = Magick::Draw.new
135
+ file.annotate(flag, 0, 0, current_position[:x] - 12, current_position[:y] + 15, "+") do
136
+ self.pointsize = 41
137
+ self.stroke = '#000000'
138
+ self.fill = '#C00000'
139
+ self.font_weight = Magick::BoldWeight
140
+ end
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,21 @@
1
+ #encoding: utf-8
2
+ module RubyMarks
3
+
4
+ class RGB
5
+
6
+ def self.to_hex(red, green, blue)
7
+ red = get_hex_from_color(red)
8
+ green = get_hex_from_color(green)
9
+ blue = get_hex_from_color(blue)
10
+ "##{red}#{green}#{blue}".upcase
11
+ end
12
+
13
+ private
14
+ def self.get_hex_from_color(color)
15
+ color = color.to_s(16)[0..1]
16
+ color.size < 2 ? "0#{color}" : color
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,3 @@
1
+ module RubyMarks
2
+ VERSION = "0.0.1.dev".freeze
3
+ end
data/lib/ruby_marks.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'RMagick'
3
+ require 'ruby_marks/document'
4
+ require 'ruby_marks/clock_mark'
5
+ require 'ruby_marks/rgb'
6
+ require 'ruby_marks/version'
7
+
8
+
9
+ magick_version = `convert -version`
10
+
11
+ if magick_version =~ /Q16/
12
+ puts %{
13
+ *** IMPORTANT: You are running the ImageMagick under 16bits quantum depth. This configuration is used
14
+ in very specific cases and can cause RMagick work a bit slow. See more details in this forum post
15
+ http://rubyforge.org/forum/forum.php?thread_id=10975&forum_id=1618 ***
16
+ }
17
+ end
@@ -0,0 +1,38 @@
1
+ require "test_helper"
2
+
3
+ class RubyMarks::ClockMarkTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @file = 'assets/sheet_demo1.png'
7
+ @document = RubyMarks::Document.new(@file)
8
+ @positions = {}
9
+ @positions[:first_clock_position] = {x: 62, y: 794}
10
+ end
11
+
12
+ def test_should_get_clock_coordinates_by_a_given_position
13
+ clock = RubyMarks::ClockMark.new(document: @document, position: @positions[:first_clock_position])
14
+ expected_coordinates = {:x1=>48, :x2=>75, :y1=>790, :y2=>802}
15
+ assert_equal expected_coordinates, clock.calc_coordinates
16
+ end
17
+
18
+ def test_should_obtain_the_clock_mark_width
19
+ clock = RubyMarks::ClockMark.new(document: @document, position: @positions[:first_clock_position])
20
+ assert_equal 27, clock.width
21
+ end
22
+
23
+ def test_should_obtain_the_clock_mark_height
24
+ clock = RubyMarks::ClockMark.new(document: @document, position: @positions[:first_clock_position])
25
+ assert_equal 12, clock.height
26
+ end
27
+
28
+ def test_should_obtain_the_horizontal_middle_position
29
+ clock = RubyMarks::ClockMark.new(document: @document, position: @positions[:first_clock_position])
30
+ assert_equal 61, clock.horizontal_middle_position
31
+ end
32
+
33
+ def test_should_obtain_the_vertical_middle_position
34
+ clock = RubyMarks::ClockMark.new(document: @document, position: @positions[:first_clock_position])
35
+ assert_equal 796, clock.vertical_middle_position
36
+ end
37
+
38
+ end
@@ -0,0 +1,88 @@
1
+ require "test_helper"
2
+
3
+ class RubyMarks::DocumentTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @file = 'assets/sheet_demo1.png'
7
+ @document = RubyMarks::Document.new(@file)
8
+ @positions = {}
9
+ @positions[:marked_position] = {x: 161, y: 794}
10
+ @positions[:unmarked_position] = {x: 161, y: 994}
11
+ @positions[:first_clock_position] = {x: 62, y: 794}
12
+ end
13
+
14
+ def test_should_initialize_a_document_with_a_valid_file
15
+ assert_equal @file, @document.filename
16
+ end
17
+
18
+ def test_should_return_a_file_with_a_position_flagged
19
+ @document.current_position = @positions[:first_clock_position]
20
+ flagged_document = @document.flag_position
21
+ assert_equal Magick::Image, flagged_document.class
22
+
23
+ # temp_filename = "temp_sheet_demo1.png"
24
+ # File.delete(temp_filename) if File.exist?(temp_filename)
25
+ # flagged_document.write(temp_filename)
26
+ end
27
+
28
+ def test_should_recognize_marked_position
29
+ @document.current_position = @positions[:marked_position]
30
+ assert @document.marked?, "The position wasn't recognized as marked"
31
+ end
32
+
33
+ def test_should_recognize_not_marked_position
34
+ @document.current_position = @positions[:unmarked_position]
35
+ assert @document.unmarked?, "The position wasn't recognized as unmarked"
36
+ end
37
+
38
+ def test_should_recognize_the_document_clock_marks
39
+ @document.scan_clock_marks
40
+ assert_equal 20, @document.clock_marks.count
41
+ end
42
+
43
+ def test_should_return_the_document_with_all_marks_flagged
44
+ flagged_document = @document.flag_all_marks
45
+ assert_equal Magick::Image, flagged_document.class
46
+
47
+ # temp_filename = "temp_sheet_demo2.png"
48
+ # File.delete(temp_filename) if File.exist?(temp_filename)
49
+ # flagged_document.write(temp_filename)
50
+ end
51
+
52
+ def test_should_move_the_current_position_in_10_and_20_pixels
53
+ @document.current_position = @positions[:marked_position]
54
+ expected_position = {x: 171, y: 814}
55
+
56
+ assert_equal expected_position, @document.move_to(10, 20)
57
+ end
58
+
59
+ def test_should_scan_the_document_and_get_a_hash_of_marked_marks
60
+ expected_hash = {
61
+ clock_1: {
62
+ group_1: ['A'],
63
+ group_2: ['A']
64
+ },
65
+ clock_2: {
66
+ group_1: ['B'],
67
+ group_2: ['B']
68
+ },
69
+ clock_3: {
70
+ group_1: ['C'],
71
+ group_2: ['C'],
72
+ group_3: ['D']
73
+ },
74
+ clock_4: {
75
+ group_1: ['D'],
76
+ group_2: ['D'],
77
+ group_3: ['D']
78
+ },
79
+ clock_5: {
80
+ group_1: ['E'],
81
+ group_2: ['E']
82
+ }
83
+ }
84
+ p @document.scan
85
+ assert_equal expected_hash, @document.scan
86
+ end
87
+ end
88
+
@@ -0,0 +1,15 @@
1
+ require "test_helper"
2
+
3
+ class RubyMarks::RGBTest < Test::Unit::TestCase
4
+
5
+ def test_should_return_the_white_color_in_hexa_receiving_8bits
6
+ color = RubyMarks::RGB.to_hex(255, 255, 255)
7
+ assert_equal "#FFFFFF", color
8
+ end
9
+
10
+ def test_should_return_the_white_color_in_hexa_receiving_16bits
11
+ color = RubyMarks::RGB.to_hex(65535, 65535, 65535)
12
+ assert_equal "#FFFFFF", color
13
+ end
14
+
15
+ end
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'test/unit'
4
+ require 'ruby_marks'
5
+
6
+ $:.unshift File.expand_path("../../assets", __FILE__)
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby_marks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.dev
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - André Rodrigues
9
+ - Ronaldo Araujo
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-17 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rmagick
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ description: A simple ORM tool
32
+ email: andrerpbts@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - README.md
38
+ - lib/ruby_marks/clock_mark.rb
39
+ - lib/ruby_marks/document.rb
40
+ - lib/ruby_marks/rgb.rb
41
+ - lib/ruby_marks/version.rb
42
+ - lib/ruby_marks.rb
43
+ - test/ruby_marks/clock_mark_test.rb
44
+ - test/ruby_marks/document_test.rb
45
+ - test/ruby_marks/rgb_test.rb
46
+ - test/test_helper.rb
47
+ homepage: https://github.com/andrerpbts/ruby_marks.git
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>'
63
+ - !ruby/object:Gem::Version
64
+ version: 1.3.1
65
+ requirements: []
66
+ rubyforge_project: ruby_marks
67
+ rubygems_version: 1.8.24
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Ruby Marks ORM
71
+ test_files:
72
+ - test/ruby_marks/clock_mark_test.rb
73
+ - test/ruby_marks/document_test.rb
74
+ - test/ruby_marks/rgb_test.rb
75
+ - test/test_helper.rb