mork 0.0.9 → 0.0.10
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 +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
|
+
|