mork 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -1
- data/.ruby-version +1 -1
- data/README.md +130 -24
- data/lib/mork/extensions.rb +26 -0
- data/lib/mork/grid.rb +47 -325
- data/lib/mork/grid_const.rb +33 -35
- data/lib/mork/grid_omr.rb +94 -0
- data/lib/mork/grid_pdf.rb +107 -0
- data/lib/mork/mimage.rb +14 -2
- data/lib/mork/npatch.rb +0 -1
- data/lib/mork/{sheet.rb → sheet_omr.rb} +87 -89
- data/lib/mork/sheet_pdf.rb +60 -66
- data/lib/mork/version.rb +1 -1
- data/lib/mork.rb +2 -6
- data/spec/mork/extensions_spec.rb +10 -0
- data/spec/mork/grid_omr_spec.rb +122 -0
- data/spec/mork/grid_spec.rb +22 -138
- data/spec/mork/sheet_omr_spec.rb +165 -0
- data/spec/mork/sheet_pdf_spec.rb +53 -43
- data/spec/samples/grid01.yml +3 -4
- data/spec/samples/grid02.yml +57 -0
- data/spec/samples/grid160.yml +57 -0
- data/spec/samples/grid_omr_01.yml +28 -0
- data/spec/samples/sample_color.pdf +0 -0
- data/spec/samples/sample_gray.jpg +0 -0
- data/spec/samples/sheet666.jpg +0 -0
- data/spec/samples/sheet666.pdf +12566 -0
- data/spec/spec_helper.rb +3 -20
- metadata +50 -28
- data/spec/mork/sheet_spec.rb +0 -178
data/lib/mork/sheet_pdf.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
+
require 'mork/grid_pdf'
|
1
2
|
require 'prawn'
|
2
3
|
|
3
4
|
module Mork
|
4
5
|
class SheetPDF < Prawn::Document
|
5
|
-
def initialize(content,
|
6
|
-
@
|
7
|
-
when
|
8
|
-
when
|
9
|
-
else raise
|
6
|
+
def initialize(content, grip=GridPDF.new)
|
7
|
+
@grip = case grip
|
8
|
+
when String, Hash; GridPDF.new grip
|
9
|
+
when Mork::GridPDF; grip
|
10
|
+
else raise 'Invalid initialization parameter'
|
10
11
|
end
|
11
12
|
super my_page_params
|
12
13
|
# @content should be an array of hashes, one per page;
|
@@ -33,76 +34,66 @@ module Mork
|
|
33
34
|
stroke_color "000000"
|
34
35
|
line_width 0.3
|
35
36
|
registration_marks
|
36
|
-
|
37
|
+
barcode content[:barcode]
|
37
38
|
header content[:header]
|
38
|
-
control content[:control] if content[:control]
|
39
39
|
questions_and_choices content[:choices]
|
40
|
+
calibration_cells
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
44
|
def my_page_params
|
44
45
|
{
|
45
|
-
page_size: @
|
46
|
-
margin:
|
46
|
+
page_size: @grip.page_size,
|
47
|
+
margin: @grip.margins
|
47
48
|
}
|
48
49
|
end
|
49
50
|
|
50
51
|
def registration_marks
|
51
52
|
fill do
|
52
|
-
@
|
53
|
+
@grip.reg_marks.each do |r|
|
53
54
|
circle r[:p], r[:r]
|
54
55
|
end
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
+
def calibration_cells
|
60
|
+
font_size @grip.item_font_size do
|
61
|
+
stroke do
|
62
|
+
stroke_color "ff0000"
|
63
|
+
@grip.calibration_cell_areas.each_with_index do |a, i|
|
64
|
+
rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
|
65
|
+
fill_color "ff0000"
|
66
|
+
text_box 'X', at: @grip.calibration_letter_xy(i)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def barcode(code)
|
59
73
|
fill do
|
60
74
|
# draw the dark calibration bar
|
61
|
-
c = @
|
75
|
+
c = @grip.ink_black_area
|
62
76
|
rectangle c[:p], c[:w], c[:h]
|
63
77
|
# draw the bars corresponding to the code
|
64
78
|
# least to most significant bit, left to right
|
65
|
-
@
|
79
|
+
@grip.barcode_bit_areas_for(code).each do |c|
|
66
80
|
rectangle c[:p], c[:w], c[:h]
|
67
81
|
end
|
68
82
|
end
|
69
83
|
end
|
70
84
|
|
71
|
-
def control(content)
|
72
|
-
font_size @grid.pdf_control_size do
|
73
|
-
text_box content[:string], at: @grid.pdf_control_xy,
|
74
|
-
width: @grid.pdf_control_width,
|
75
|
-
align: :right
|
76
|
-
stroke do
|
77
|
-
font_size
|
78
|
-
stroke_color "ff0000"
|
79
|
-
# dark
|
80
|
-
a = @grid.pdf_ctrl_area_dark
|
81
|
-
rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
|
82
|
-
fill_color "ff0000"
|
83
|
-
draw_text content[:labels][0], at: @grid.pdf_dark_control_letter_xy
|
84
|
-
# light
|
85
|
-
a = @grid.pdf_ctrl_area_light
|
86
|
-
rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
|
87
|
-
fill_color "ff0000"
|
88
|
-
draw_text content[:labels][1], at: @grid.pdf_light_control_letter_xy
|
89
|
-
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
85
|
def header(content)
|
95
86
|
content.each do |k,v|
|
96
|
-
font_size @
|
97
|
-
if @
|
98
|
-
bounding_box @
|
87
|
+
font_size @grip.header_size(k) do
|
88
|
+
if @grip.header_boxed?(k)
|
89
|
+
bounding_box @grip.header_xy(k), width: @grip.header_width(k), height: @grip.header_height(k) do
|
99
90
|
stroke_bounds
|
100
|
-
bounding_box @
|
91
|
+
bounding_box @grip.header_padding(k), width: @grip.header_width(k) do
|
101
92
|
text v
|
102
93
|
end
|
103
94
|
end
|
104
95
|
else
|
105
|
-
text_box v, at: @
|
96
|
+
text_box v, at: @grip.header_xy(k), width: @grip.header_width(k)
|
106
97
|
end
|
107
98
|
end
|
108
99
|
end
|
@@ -112,40 +103,43 @@ module Mork
|
|
112
103
|
stroke do
|
113
104
|
content.length.times do |q|
|
114
105
|
fill_color "000000"
|
115
|
-
text_box "#{q+1}", at: @
|
116
|
-
width: @
|
106
|
+
text_box "#{q+1}", at: @grip.qnum_xy(q),
|
107
|
+
width: @grip.qnum_width,
|
117
108
|
align: :right,
|
118
|
-
size: @
|
109
|
+
size: @grip.item_font_size
|
119
110
|
stroke_color "ff0000"
|
120
|
-
font_size @
|
111
|
+
font_size @grip.item_font_size
|
121
112
|
content[q].times do |c|
|
122
|
-
a = @
|
113
|
+
a = @grip.choice_cell_area q, c
|
123
114
|
rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
|
124
115
|
fill_color "ff0000"
|
125
|
-
|
116
|
+
text_box (65+c).chr, at: @grip.choice_letter_xy(q, c)
|
126
117
|
end
|
127
118
|
end
|
128
119
|
end
|
129
120
|
end
|
130
|
-
|
131
|
-
# def nquestions
|
132
|
-
# @content[:choices].length
|
133
|
-
# end
|
134
|
-
#
|
135
|
-
# def nchoices(i)
|
136
|
-
# @content[:choices][i]
|
137
|
-
# end
|
138
121
|
end
|
139
122
|
end
|
140
123
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
124
|
+
# def control(content)
|
125
|
+
# font_size @grip.control_size do
|
126
|
+
# text_box content[:string], at: @grip.control_xy,
|
127
|
+
# width: @grip.control_width,
|
128
|
+
# align: :right
|
129
|
+
# stroke do
|
130
|
+
# stroke_color "ff0000"
|
131
|
+
# # dark
|
132
|
+
# a = @grip.ctrl_area_dark
|
133
|
+
# rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
|
134
|
+
# fill_color "ff0000"
|
135
|
+
# draw_text content[:labels][0], at: @grip.dark_control_letter_xy
|
136
|
+
# # light
|
137
|
+
# a = @grip.ctrl_area_light
|
138
|
+
# rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
|
139
|
+
# fill_color "ff0000"
|
140
|
+
# draw_text content[:labels][1], at: @grip.light_control_letter_xy
|
141
|
+
#
|
142
|
+
# end
|
143
|
+
# end
|
144
|
+
# end
|
145
|
+
#
|
data/lib/mork/version.rb
CHANGED
data/lib/mork.rb
CHANGED
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe GridOMR do
|
5
|
+
let(:grom) { GridOMR.new 1601, 2281, 'spec/samples/grid_omr_01.yml' }
|
6
|
+
|
7
|
+
describe '#choice_cell_area' do
|
8
|
+
it 'returns the coordinates of the first choice cell' do
|
9
|
+
grom.choice_cell_area(0,0).should == {x: 63, y: 436, w: 51, h: 41}
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'returns the coordinates of the last choice cell' do
|
13
|
+
grom.choice_cell_area(119,4).should == {x: 1411, y: 2108, w: 51, h: 41}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#barcode_bit_area' do
|
18
|
+
# it 'returns the coordinates of the first barcode bit area' do
|
19
|
+
# grom.barcode_bit_area(0).should == {x: 160, y: 2260, w: 25, h: 21}
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# it 'returns the coordinates of the last barcode bit area' do
|
23
|
+
# grom.barcode_bit_area(39).should == {x: 1475, y: 2260, w: 25, h: 21}
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# it 'fails if an invalid barcode bit is requested' do
|
27
|
+
# lambda { grom.barcode_bit_area(40) }.should raise_error
|
28
|
+
# end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#rm_search_area' do
|
32
|
+
context 'on the first iteration' do
|
33
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tl reg_mark corner' do
|
34
|
+
c = grom.rm_search_area :tl, 0
|
35
|
+
c.should == {x: 15, y: 15, w: 91, h: 92}
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tr reg_mark corner' do
|
39
|
+
c = grom.rm_search_area :tr, 0
|
40
|
+
c.should == { x: 1494, y: 15, w: 91, h: 92 }
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :br reg_mark corner' do
|
44
|
+
c = grom.rm_search_area :br, 0
|
45
|
+
c.should == { x: 1494, y: 2173, w: 91, h: 92 }
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :bl reg_mark corner' do
|
49
|
+
c = grom.rm_search_area :bl, 0
|
50
|
+
c.should == { x: 15, y: 2173, w: 91, h: 92 }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'on the third iteration' do
|
55
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tl reg_mark corner' do
|
56
|
+
c = grom.rm_search_area :tl, 2
|
57
|
+
c.should == { x: 15, y: 15, w: 130, h: 131 }
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tr reg_mark corner' do
|
61
|
+
c = grom.rm_search_area :tr, 2
|
62
|
+
c.should == { x: 1456, y: 15, w: 130, h: 131 }
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :br reg_mark corner' do
|
66
|
+
c = grom.rm_search_area :br, 2
|
67
|
+
c.should == { x: 1456, y: 2135, w: 130, h: 131 }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :bl reg_mark corner' do
|
71
|
+
c = grom.rm_search_area :bl, 2
|
72
|
+
c.should == { x: 15, y: 2135, w: 130, h: 131 }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#rm_edgy_x' do
|
78
|
+
it 'returns the minimum acceptable number of pixels from the regmark center to the edge of the rm_search_area' do
|
79
|
+
grom.rm_edgy_x.should == 24
|
80
|
+
end
|
81
|
+
it 'returns an integer' do
|
82
|
+
grom.rm_edgy_x.should be_a Fixnum
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#rm_edgy_y' do
|
87
|
+
it 'returns the minimum acceptable number of pixels from the regmark center to the edge of the rm_search_area' do
|
88
|
+
grom.rm_edgy_y.should == 24
|
89
|
+
end
|
90
|
+
it 'returns an integer' do
|
91
|
+
grom.rm_edgy_y.should be_a Fixnum
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#rm_max_search_area_side' do
|
96
|
+
it 'returns the maximum extent of the regmark search area, 1/4 of the raw image horizontal pixels' do
|
97
|
+
grom.rm_max_search_area_side.should == 400
|
98
|
+
end
|
99
|
+
it 'returns an integer' do
|
100
|
+
grom.rm_max_search_area_side.should be_a Fixnum
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#max_choices_per_question' do
|
105
|
+
it 'returns the maximum number of choice cells per question' do
|
106
|
+
grom.max_choices_per_question.should == 5
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe '#paper_white_area' do
|
111
|
+
it 'returns the coordinates of the white area used for barcode calibration' do
|
112
|
+
grom.paper_white_area.should == {x: 93, y: 2260, w: 25, h: 21}
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '#ink_black_area' do
|
117
|
+
it 'returns the coordinates of the barcode calibration bar' do
|
118
|
+
grom.ink_black_area.should == {x: 126, y: 2260, w: 25, h: 21}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/spec/mork/grid_spec.rb
CHANGED
@@ -2,10 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Mork
|
4
4
|
describe Grid do
|
5
|
+
context 'init params' do
|
6
|
+
it 'does not work with an integer' do
|
7
|
+
expect {Grid.new 1}.to raise_error
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
context 'default grid' do
|
6
12
|
before(:all) do
|
7
|
-
@grid = Grid.new
|
8
|
-
@grid.set_page_size 1601, 2281 # the size of sample01.jpg
|
13
|
+
@grid = Grid.new 'spec/samples/grid_omr_01.yml'
|
9
14
|
end
|
10
15
|
|
11
16
|
describe '#max_questions' do
|
@@ -14,144 +19,11 @@ module Mork
|
|
14
19
|
end
|
15
20
|
end
|
16
21
|
|
17
|
-
describe '#
|
18
|
-
it 'returns the
|
19
|
-
@grid.
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe '#code_bits' do
|
24
|
-
it 'returns the number of bits used to define the form code' do
|
25
|
-
@grid.code_bits.should == 40
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'returns an integer' do
|
29
|
-
@grid.code_bits.should be_a Fixnum
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#rm_search_area' do
|
34
|
-
context 'on the first iteration' do
|
35
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tl reg_mark corner' do
|
36
|
-
c = @grid.rm_search_area :tl, 0
|
37
|
-
c.should == {:x=>15, :y=>15, :w=>76, :h=>77}
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tr reg_mark corner' do
|
41
|
-
c = @grid.rm_search_area :tr, 0
|
42
|
-
c.should == { x: 1510, y: 15, w: 76, h: 77 }
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :br reg_mark corner' do
|
46
|
-
c = @grid.rm_search_area :br, 0
|
47
|
-
c.should == { x: 1510, y: 2189, w: 76, h: 77 }
|
48
|
-
end
|
49
|
-
|
50
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :bl reg_mark corner' do
|
51
|
-
c = @grid.rm_search_area :bl, 0
|
52
|
-
c.should == { x: 15, y: 2189, w: 76, h: 77 }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'on the third iteration' do
|
57
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tl reg_mark corner' do
|
58
|
-
c = @grid.rm_search_area :tl, 2
|
59
|
-
c.should == { x: 15, y: 15, w: 114, h: 115 }
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :tr reg_mark corner' do
|
63
|
-
c = @grid.rm_search_area :tr, 2
|
64
|
-
c.should == { x: 1471, y: 15, w: 114, h: 115 }
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :br reg_mark corner' do
|
68
|
-
c = @grid.rm_search_area :br, 2
|
69
|
-
c.should == { x: 1471, y: 2150, w: 114, h: 115 }
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'returns an {:x, :y, :w, :h} hash of coordinates in pixels for the :bl reg_mark corner' do
|
73
|
-
c = @grid.rm_search_area :bl, 2
|
74
|
-
c.should == { x: 15, y: 2150, w: 114, h: 115 }
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '#rm_edgy_x' do
|
80
|
-
it 'returns the minimum acceptable number of pixels from the regmark center to the edge of the rm_search_area' do
|
81
|
-
@grid.rm_edgy_x.should == 24
|
82
|
-
end
|
83
|
-
it 'returns an integer' do
|
84
|
-
@grid.rm_edgy_x.should be_a Fixnum
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe '#rm_edgy_y' do
|
89
|
-
it 'returns the minimum acceptable number of pixels from the regmark center to the edge of the rm_search_area' do
|
90
|
-
@grid.rm_edgy_y.should == 24
|
91
|
-
end
|
92
|
-
it 'returns an integer' do
|
93
|
-
@grid.rm_edgy_y.should be_a Fixnum
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe '#rm_max_search_area_side' do
|
98
|
-
it 'returns the maximum extent of the regmark search area, 1/4 of the raw image horizontal pixels' do
|
99
|
-
@grid.rm_max_search_area_side.should == 400
|
100
|
-
end
|
101
|
-
it 'returns an integer' do
|
102
|
-
@grid.rm_max_search_area_side.should be_a Fixnum
|
22
|
+
describe '#barcode_bits' do
|
23
|
+
it 'returns the number of bits used to define the form barcode' do
|
24
|
+
@grid.send(:barcode_bits).should == 40
|
103
25
|
end
|
104
26
|
end
|
105
|
-
|
106
|
-
describe '#choice_cell_area' do
|
107
|
-
it 'returns the coordinates of the first choice cell' do
|
108
|
-
@grid.choice_cell_area(0,0).should == {x: 63, y: 436, w: 51, h: 41}
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'returns the coordinates of the last choice cell' do
|
112
|
-
@grid.choice_cell_area(119,4).should == {x: 1538, y: 2108, w: 51, h: 41}
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
describe '#ctrl_area_dark' do
|
117
|
-
it 'returns the coordinates of the control cell used to set the darkened threshold' do
|
118
|
-
@grid.ctrl_area_dark.should == {:x=>1479, :y=>329, :w=>51, :h=>41}
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
describe '#ctrl_area_light' do
|
123
|
-
it 'returns the coordinates of the control cell used to set the darkened threshold' do
|
124
|
-
@grid.ctrl_area_light.should == {:x=>1538, :y=>329, :w=>51, :h=>41}
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
describe '#cal_area_white' do
|
129
|
-
it 'returns the coordinates of the white area used for code calibration' do
|
130
|
-
@grid.cal_area_white.should == {:x=>93, :y=>2260, :w=>25, :h=>21}
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe '#cal_area_black' do
|
135
|
-
it 'returns the coordinates of the code calibration bar' do
|
136
|
-
@grid.cal_area_black.should == {:x=>126, :y=>2260, :w=>25, :h=>21}
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe '#code_bit_area' do
|
141
|
-
it 'returns the coordinates of the first code bit area' do
|
142
|
-
@grid.code_bit_area(0).should == {:x=>160, :y=>2260, :w=>25, :h=>21}
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'returns the coordinates of the last code bit area' do
|
146
|
-
@grid.code_bit_area(39).should == {:x=>1475, :y=>2260, :w=>25, :h=>21}
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'fails if an invalid code bit is requested' do
|
150
|
-
lambda { @grid.code_bit_area(40) }.should raise_error
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
|
155
27
|
end
|
156
28
|
|
157
29
|
|
@@ -220,3 +92,15 @@ end
|
|
220
92
|
# c[:y].should be_within(4).of(3120)
|
221
93
|
# end
|
222
94
|
# end
|
95
|
+
|
96
|
+
# describe '#ctrl_area_dark' do
|
97
|
+
# it 'returns the coordinates of the control cell used to set the darkened threshold' do
|
98
|
+
# @grid.ctrl_area_dark.should == {:x=>1479, :y=>329, :w=>51, :h=>41}
|
99
|
+
# end
|
100
|
+
# end
|
101
|
+
#
|
102
|
+
# describe '#ctrl_area_light' do
|
103
|
+
# it 'returns the coordinates of the control cell used to set the darkened threshold' do
|
104
|
+
# @grid.ctrl_area_light.should == {:x=>1538, :y=>329, :w=>51, :h=>41}
|
105
|
+
# end
|
106
|
+
# end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe SheetOMR do
|
5
|
+
context 'highlighting' do
|
6
|
+
# since these specs change the @crop, they must be run in isolation
|
7
|
+
# with the SheetOMR rebuilt each time, even though it is time consuming!
|
8
|
+
let(:sheet) { SheetOMR.new 'spec/samples/sample_gray.jpg', 'spec/samples/grid_omr_01.yml' }
|
9
|
+
|
10
|
+
it 'highlights the registration areas and frame' do
|
11
|
+
sheet.highlight_reg_area
|
12
|
+
sheet.write_raw 'tmp/reg_areas.jpg'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should highlight all areas' do
|
16
|
+
sheet.highlight_all
|
17
|
+
sheet.write 'tmp/all_highlights.jpg'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should highlight marked cells and outline correct responses' do
|
21
|
+
sheet.highlight_marked
|
22
|
+
sheet.outline [[1],[1],[2],[2],[3,4],[],[0,1,2,3,4]]
|
23
|
+
sheet.write 'tmp/marked_highlights.jpg'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'marking a nicely printed and scanned sheet' do
|
28
|
+
before(:all) do
|
29
|
+
@sheet = SheetOMR.new('spec/samples/sample_gray.jpg', 'spec/samples/grid_omr_01.yml')
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#valid?' do
|
33
|
+
it 'returns true' do
|
34
|
+
@sheet.valid?.should be_truthy
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#marked?' do
|
39
|
+
it 'returns true for some darkened choices' do
|
40
|
+
expect(@sheet.marked?(0,0)).to be_truthy
|
41
|
+
expect(@sheet.marked?(1,1)).to be_truthy
|
42
|
+
expect(@sheet.marked?(2,2)).to be_truthy
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'return false for some blank choices' do
|
46
|
+
expect(@sheet.marked?(0,1)).to be_falsy
|
47
|
+
expect(@sheet.marked?(1,0)).to be_falsy
|
48
|
+
expect(@sheet.marked?(2,3)).to be_falsy
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'writes out average whiteness of choice cells' do
|
52
|
+
puts "Choice threshold: #{@sheet.send :choice_threshold}"
|
53
|
+
File.open('tmp/choices.txt', 'w') do |f|
|
54
|
+
120.times do |q|
|
55
|
+
t = (0..4).collect do |c|
|
56
|
+
@sheet.send(:shade_of, q, c).round
|
57
|
+
end
|
58
|
+
f.puts "#{q+1}: #{t.join(' ')}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
mf = File.open('tmp/marked.txt', 'w')
|
63
|
+
uf = File.open('tmp/unmarked.txt', 'w')
|
64
|
+
120.times do |q|
|
65
|
+
5.times do |c|
|
66
|
+
shade = @sheet.send(:shade_of, q, c)
|
67
|
+
@sheet.marked?(q,c) ? mf.puts(shade) : uf.puts(shade)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
mf.close
|
71
|
+
uf.close
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#mark_array' do
|
76
|
+
it 'should return an array of marked choices for each of the first 5 questions' do
|
77
|
+
@sheet.mark_array(5).should == [[0], [1], [2], [3], [4]]
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should return an array of marked choices for the specified question set' do
|
81
|
+
@sheet.mark_array([0, 1, 13, 16, 31, 104, 21]).should == [[0], [1], [3,4], [2], [1], [], [0,1,2,3,4]]
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should return an array of @grid.max_questions length if called without arguments' do
|
85
|
+
@sheet.mark_array.length.should == 120
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#mark_logical_array' do
|
90
|
+
it 'should return an array of booleans for each of the first questions' do
|
91
|
+
@sheet.mark_logical_array(5).should == [
|
92
|
+
[true, false, false, false, false],
|
93
|
+
[false, true, false, false, false],
|
94
|
+
[false, false, true, false, false],
|
95
|
+
[false, false, false, true, false],
|
96
|
+
[false, false, false, false, true],
|
97
|
+
]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe 'barcodes' do
|
102
|
+
it 'should read the bit string as all ones' do
|
103
|
+
@sheet.barcode_string.should == '1111111111111111111111111111111111111111'
|
104
|
+
@sheet.barcode.should == 1099511627775
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should read another bit string' do
|
108
|
+
barcode_string = '0000000000000000000000000010000110100000'
|
109
|
+
s2 = SheetOMR.new('spec/samples/sample02.jpg')
|
110
|
+
s2.barcode_string.should == barcode_string
|
111
|
+
s2.barcode.should == 8608
|
112
|
+
s2.highlight_barcode
|
113
|
+
s2.write 'tmp/code_bits.jpg'
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should read the 666 bit string' do
|
117
|
+
s2 = SheetOMR.new('spec/samples/sheet666.jpg')
|
118
|
+
s2.barcode.should == 666666666666
|
119
|
+
s2.highlight_barcode
|
120
|
+
s2.write 'tmp/code_bits666.jpg'
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'a faded, b&w, distorted sheet' do
|
127
|
+
it 'should return the correct barcode' do
|
128
|
+
SheetOMR.new('spec/samples/sample03.jpg').barcode.should == 8608
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# context "multi-page pdf" do
|
133
|
+
# before(:all) do
|
134
|
+
# @mlist = MimageList.new('spec/samples/two_pages.pdf')
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# describe "reading the codes" do
|
138
|
+
# it "should read the right code for the first page" do
|
139
|
+
# s = SheetOMR.new(@mlist[0], Grid.new)
|
140
|
+
# s.code.should == 18446744073709551615
|
141
|
+
# end
|
142
|
+
# it "should read the right code for the second page" do
|
143
|
+
# s = SheetOMR.new(@mlist[1], Grid.new)
|
144
|
+
# s.code.should == 283764283738
|
145
|
+
# end
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# describe "getting the answers" do
|
149
|
+
# it "should read the correct choices for the first page" do
|
150
|
+
# s = SheetOMR.new(@mlist[0], Grid.new)
|
151
|
+
# s.marked?( 0, 0).should be_truthy
|
152
|
+
# s.marked?( 0, 1).should be_falsy
|
153
|
+
# s.marked?(15, 3).should be_falsy
|
154
|
+
# s.marked?(15, 4).should be_truthy
|
155
|
+
# end
|
156
|
+
#
|
157
|
+
# it "should read the correct choices for the second page" do
|
158
|
+
# s = SheetOMR.new(@mlist[1], Grid.new)
|
159
|
+
# s.mark_array(15).should == [[0], [1], [2], [3], [4], [0], [1], [2, 3], [4], [1, 2, 3], [0], [1], [2], [3], [4]]
|
160
|
+
# end
|
161
|
+
# end
|
162
|
+
# end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|