mork 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +1 -2
- data/Guardfile +10 -0
- data/config/grids.yml +42 -0
- data/lib/mork.rb +8 -4
- data/lib/mork/grid.rb +307 -0
- data/lib/mork/grid_const.rb +14 -0
- data/lib/mork/mimage.rb +86 -0
- data/lib/mork/mimage_list.rb +29 -0
- data/lib/mork/npatch.rb +51 -0
- data/lib/mork/report.rb +39 -0
- data/lib/mork/sheet.rb +144 -0
- data/lib/mork/sheet_pdf.rb +97 -0
- data/lib/mork/version.rb +1 -1
- data/mork.gemspec +9 -2
- data/spec/mork/grid_spec.rb +85 -0
- data/spec/mork/mimage_list_spec.rb +37 -0
- data/spec/mork/mimage_spec.rb +48 -0
- data/spec/mork/npatch_spec.rb +52 -0
- data/spec/mork/report_spec.rb +13 -0
- data/spec/mork/sheet_pdf_spec.rb +34 -0
- data/spec/mork/sheet_spec.rb +149 -0
- data/spec/samples/code_sample.pdf +85 -0
- data/spec/samples/code_sample.png +0 -0
- data/spec/samples/code_zero.pdf +79 -0
- data/spec/samples/info.yml +53 -0
- data/spec/samples/reg_mark.jpg +0 -0
- data/spec/samples/sample.pages +0 -0
- data/spec/samples/sample01.jpg +0 -0
- data/spec/samples/two_pages.pdf +0 -0
- data/spec/spec_helper.rb +34 -0
- metadata +199 -31
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe MimageList do
|
5
|
+
before(:all) do
|
6
|
+
tpg = sample_img(:two_pages)
|
7
|
+
@mlist = MimageList.new(tpg.filename)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".new" do
|
11
|
+
it "should raise an error unless called with a string" do
|
12
|
+
lambda {
|
13
|
+
MimageList.new(666)
|
14
|
+
}.should raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "[]" do
|
19
|
+
it "should return the 1st mimage in the stack" do
|
20
|
+
@mlist[0].should be_a(Mimage)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return the last mimage in the stack" do
|
24
|
+
@mlist[1].should be_a(Mimage)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "each" do
|
29
|
+
it "should loop over all images" do
|
30
|
+
@mlist.each do |m|
|
31
|
+
puts m.inspect
|
32
|
+
m.should be_a(Mimage)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe Mimage do
|
5
|
+
let(:smp) { sample_img(:sample01) }
|
6
|
+
let(:mim) { Mimage.new(smp.filename) }
|
7
|
+
|
8
|
+
describe ".new" do
|
9
|
+
it "should create a Mimage from a string pointing to an existing bitmap file" do
|
10
|
+
mim.should be_a(Mimage)
|
11
|
+
end
|
12
|
+
it "should create a Mimage from an existing Magick::ImageList object" do
|
13
|
+
i = Magick::ImageList.new smp.filename
|
14
|
+
Mimage.new(i).should be_a(Mimage)
|
15
|
+
end
|
16
|
+
it "should create a Mimage from an existing Magick::Image object" do
|
17
|
+
i = Magick::ImageList.new smp.filename
|
18
|
+
Mimage.new(i.first).should be_a(Mimage)
|
19
|
+
end
|
20
|
+
it "should raise an error if called with a fixnum" do
|
21
|
+
lambda { Mimage.new 1 }.should raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#crop" do
|
26
|
+
it "should return a Mimage" do
|
27
|
+
mim.crop({x: 0, y: 0, w: 10, h: 10}).should be_a(Mimage)
|
28
|
+
end
|
29
|
+
it "should return a Mimage of the correct width" do
|
30
|
+
i = mim.crop({x: 0, y: 0, w: 20, h: 10})
|
31
|
+
i.width.should == 20
|
32
|
+
end
|
33
|
+
it "should return a Mimage of the correct height" do
|
34
|
+
i = mim.crop({x: 0, y: 0, w: 10, h: 10})
|
35
|
+
i.height.should == 10
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#crop!" do
|
40
|
+
it "should reduce the Mimage to the correct width" do
|
41
|
+
mim.crop!({x: 0, y: 0, w: 20, h: 10}).width.should == 20
|
42
|
+
end
|
43
|
+
it "should reduce the Mimage to the correct height" do
|
44
|
+
mim.crop!({x: 0, y: 0, w: 20, h: 10}).height.should == 10
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe NPatch do
|
5
|
+
let(:rgm) { sample_img(:reg_mark) }
|
6
|
+
let(:mim) { Mimage.new(rgm.filename) }
|
7
|
+
|
8
|
+
describe ".new" do
|
9
|
+
it "should create an NPatch" do
|
10
|
+
NPatch.new(mim).should be_an(NPatch)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#dark_centroid" do
|
15
|
+
it "should return the correct X" do
|
16
|
+
x, y = NPatch.new(mim).dark_centroid
|
17
|
+
x.should == rgm.info["centroid_x"]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the correct Y" do
|
21
|
+
x, y = NPatch.new(mim).dark_centroid
|
22
|
+
y.should == rgm.info["centroid_y"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# describe "#dark_centroid_on" do
|
29
|
+
# it "returns the actual xy offset of the tl registration mark" do
|
30
|
+
# x, y = mim.dark_centroid_on({x: 0, y: 0, w: 180, h: 180})
|
31
|
+
# x.should be_within(2).of(smp.reg_marks["tl_x"])
|
32
|
+
# y.should be_within(2).of(smp.reg_marks["tl_y"])
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# it "returns the actual xy offset of the tr registration mark" do
|
36
|
+
# x, y = mim.dark_centroid_on({x: smp.width-180, y: 0, w: 180, h: 180})
|
37
|
+
# x.should be_within(2).of(smp.reg_marks["tr_x"])
|
38
|
+
# y.should be_within(2).of(smp.reg_marks["tr_y"])
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# it "returns the actual xy offset of the br registration mark" do
|
42
|
+
# x, y = mim.dark_centroid_on({x: smp.width-180, y: smp.height-180, w: 180, h: 180})
|
43
|
+
# x.should be_within(2).of(smp.reg_marks["br_x"])
|
44
|
+
# y.should be_within(2).of(smp.reg_marks["br_y"])
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# it "returns the actual xy offset of the bl registration mark" do
|
48
|
+
# x, y = mim.dark_centroid_on({x: 0, y: smp.height-180, w: 180, h: 180})
|
49
|
+
# x.should be_within(2).of(smp.reg_marks["bl_x"])
|
50
|
+
# y.should be_within(2).of(smp.reg_marks["bl_y"])
|
51
|
+
# end
|
52
|
+
# end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe SheetPDF do
|
5
|
+
it "should create a basic pdf" do
|
6
|
+
info = {
|
7
|
+
code: 18446744073709551615,
|
8
|
+
choices: [5] * 100,
|
9
|
+
header: {
|
10
|
+
name: "Bertini Giuseppe VR123456",
|
11
|
+
title: "Esame di Fondamenti Morfologici e Funzionali della Vita",
|
12
|
+
code: "119.27",
|
13
|
+
date: "18 gennaio 2013"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
s = SheetPDF.new(Grid.new(:default), info)
|
17
|
+
s.save("tmp/f1.pdf")
|
18
|
+
|
19
|
+
info = {
|
20
|
+
code: 283764283738,
|
21
|
+
choices: [5] * 100,
|
22
|
+
header: {
|
23
|
+
name: "Francesco Gagliardi VR765432",
|
24
|
+
title: "Esame di Fondamenti Morfologici e Funzionali della Vita",
|
25
|
+
code: "119.28",
|
26
|
+
date: "18 gennaio 2013"
|
27
|
+
}
|
28
|
+
}
|
29
|
+
s = SheetPDF.new(Grid.new(:default), info)
|
30
|
+
s.save("tmp/f2.pdf")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Mork
|
4
|
+
describe Sheet do
|
5
|
+
context "describing marked choices" do
|
6
|
+
before(:all) do
|
7
|
+
fn = sample_img(:sample01).filename
|
8
|
+
@sheet = Sheet.new(fn, Grid.new)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#marked?" do
|
12
|
+
it "should return true for a darkened choice" do
|
13
|
+
@sheet.marked?(0,0).should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return false for a blank choice" do
|
17
|
+
@sheet.marked?(0,1).should be_false
|
18
|
+
end
|
19
|
+
|
20
|
+
it "prints the average whiteness of the first 40 sets of choices" do
|
21
|
+
40.times do |q|
|
22
|
+
t = (0..4).collect do |c|
|
23
|
+
@sheet.send(:shade_of, q, c).round
|
24
|
+
end
|
25
|
+
puts "#{q+1}: #{t.join(" ")}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#mark_array" do
|
31
|
+
it "should return an array of marked choices for each of the first 5 questions" do
|
32
|
+
@sheet.mark_array(5).should == [[0], [1], [2], [3], [4]]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return an array of marked choices for the specified question set" do
|
36
|
+
@sheet.mark_array([0, 1, 15, 16, 31]).should == [[0], [1], [0], [1], []]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should return an array of @grid.max_questions length if called without arguments" do
|
40
|
+
@sheet.mark_array.length.should == 160
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#mark_logical_array" do
|
45
|
+
it "should return an array of booleans for each of the first questions" do
|
46
|
+
@sheet.mark_logical_array(5).should == [
|
47
|
+
[true, false, false, false, false],
|
48
|
+
[false, true, false, false, false],
|
49
|
+
[false, false, true, false, false],
|
50
|
+
[false, false, false, true, false],
|
51
|
+
[false, false, false, false, true],
|
52
|
+
]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
context "describing sheet codes" do
|
57
|
+
before(:all) do
|
58
|
+
@smp = sample_img(:code_sample)
|
59
|
+
@cshe = Sheet.new(@smp.filename, Grid.new)
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#dark_code_bit_shade" do
|
63
|
+
it "should be less than a certain amount" do
|
64
|
+
v = @cshe.dark_code_bit_shade
|
65
|
+
v.should < @cshe.send(:dark_threshold)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#light_code_bit_shade" do
|
70
|
+
it "should be more than a certain amount" do
|
71
|
+
v = @cshe.light_code_bit_shade
|
72
|
+
v.should > @cshe.send(:dark_threshold)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#code_string" do
|
78
|
+
it "should read the bit string" do
|
79
|
+
@cshe.code_string.should == @smp.code_string
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#code" do
|
84
|
+
it "should read the bit string and return the integer code" do
|
85
|
+
@cshe.code.should == @smp.code_int
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
context "highlighting stuff" do
|
91
|
+
it "should highlight all high bits in red" do
|
92
|
+
smp = sample_img(:code_sample)
|
93
|
+
s = Sheet.new(smp.filename, Grid.new)
|
94
|
+
CODE_BITS.times do |i|
|
95
|
+
if smp.code_int[i] == 1
|
96
|
+
s.highlight_code_bit i
|
97
|
+
end
|
98
|
+
end
|
99
|
+
s.write "tmp/bits.pdf"
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should highlight the dark calibration bit" do
|
103
|
+
fn = sample_img(:code_sample).filename
|
104
|
+
s = Sheet.new(fn, Grid.new)
|
105
|
+
s.highlight_dark_calibration_bit
|
106
|
+
s.write "tmp/dark_bit.pdf"
|
107
|
+
end
|
108
|
+
it "should highlight the light calibration bit" do
|
109
|
+
fn = sample_img(:code_sample).filename
|
110
|
+
s = Sheet.new(fn, Grid.new)
|
111
|
+
s.highlight_light_calibration_bit
|
112
|
+
s.write "tmp/light_bit.pdf"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "multi-page pdf" do
|
117
|
+
before(:all) do
|
118
|
+
@smp = sample_img(:two_pages)
|
119
|
+
@mlist = MimageList.new(@smp.filename)
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "reading the codes" do
|
123
|
+
it "should read the right code for the first page" do
|
124
|
+
s = Sheet.new(@mlist[0], Grid.new)
|
125
|
+
s.code.should == 18446744073709551615
|
126
|
+
end
|
127
|
+
it "should read the right code for the second page" do
|
128
|
+
s = Sheet.new(@mlist[1], Grid.new)
|
129
|
+
s.code.should == 283764283738
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "getting the answers" do
|
134
|
+
it "should read the correct choices for the first page" do
|
135
|
+
s = Sheet.new(@mlist[0], Grid.new)
|
136
|
+
s.marked?( 0, 0).should be_true
|
137
|
+
s.marked?( 0, 1).should be_false
|
138
|
+
s.marked?(15, 3).should be_false
|
139
|
+
s.marked?(15, 4).should be_true
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should read the correct choices for the second page" do
|
143
|
+
s = Sheet.new(@mlist[1], Grid.new)
|
144
|
+
s.mark_array(15).should == [[0], [1], [2], [3], [4], [0], [1], [2, 3], [4], [1, 2, 3], [0], [1], [2], [3], [4]]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
%PDF-1.3
|
2
|
+
%����
|
3
|
+
1 0 obj
|
4
|
+
<< /Creator <feff0050007200610077006e>
|
5
|
+
/Producer <feff0050007200610077006e>
|
6
|
+
>>
|
7
|
+
endobj
|
8
|
+
2 0 obj
|
9
|
+
<< /Type /Catalog
|
10
|
+
/Pages 3 0 R
|
11
|
+
>>
|
12
|
+
endobj
|
13
|
+
3 0 obj
|
14
|
+
<< /Type /Pages
|
15
|
+
/Count 1
|
16
|
+
/Kids [5 0 R]
|
17
|
+
>>
|
18
|
+
endobj
|
19
|
+
4 0 obj
|
20
|
+
<< /Length 1109
|
21
|
+
>>
|
22
|
+
stream
|
23
|
+
q
|
24
|
+
28.346 21.260 m
|
25
|
+
28.346 25.174 25.174 28.346 21.260 28.346 c
|
26
|
+
17.346 28.346 14.173 25.174 14.173 21.260 c
|
27
|
+
14.173 17.346 17.346 14.173 21.260 14.173 c
|
28
|
+
25.174 14.173 28.346 17.346 28.346 21.260 c
|
29
|
+
21.260 21.260 m
|
30
|
+
28.346 820.630 m
|
31
|
+
28.346 824.544 25.174 827.717 21.260 827.717 c
|
32
|
+
17.346 827.717 14.173 824.544 14.173 820.630 c
|
33
|
+
14.173 816.716 17.346 813.543 21.260 813.543 c
|
34
|
+
25.174 813.543 28.346 816.716 28.346 820.630 c
|
35
|
+
21.260 820.630 m
|
36
|
+
581.102 820.630 m
|
37
|
+
581.102 824.544 577.930 827.717 574.016 827.717 c
|
38
|
+
570.102 827.717 566.929 824.544 566.929 820.630 c
|
39
|
+
566.929 816.716 570.102 813.543 574.016 813.543 c
|
40
|
+
577.930 813.543 581.102 816.716 581.102 820.630 c
|
41
|
+
574.016 820.630 m
|
42
|
+
581.102 21.260 m
|
43
|
+
581.102 25.174 577.930 28.346 574.016 28.346 c
|
44
|
+
570.102 28.346 566.929 25.174 566.929 21.260 c
|
45
|
+
566.929 17.346 570.102 14.173 574.016 14.173 c
|
46
|
+
577.930 14.173 581.102 17.346 581.102 21.260 c
|
47
|
+
574.016 21.260 m
|
48
|
+
f
|
49
|
+
42.520 14.173 5.669 14.173 re
|
50
|
+
49.606 14.173 5.669 14.173 re
|
51
|
+
77.953 14.173 5.669 14.173 re
|
52
|
+
92.126 14.173 5.669 14.173 re
|
53
|
+
120.472 14.173 5.669 14.173 re
|
54
|
+
127.559 14.173 5.669 14.173 re
|
55
|
+
134.646 14.173 5.669 14.173 re
|
56
|
+
f
|
57
|
+
Q
|
58
|
+
|
59
|
+
endstream
|
60
|
+
endobj
|
61
|
+
5 0 obj
|
62
|
+
<< /Type /Page
|
63
|
+
/Parent 3 0 R
|
64
|
+
/MediaBox [0 0 595.2755905511815 841.889763779528]
|
65
|
+
/Contents 4 0 R
|
66
|
+
/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
|
67
|
+
>>
|
68
|
+
>>
|
69
|
+
endobj
|
70
|
+
xref
|
71
|
+
0 6
|
72
|
+
0000000000 65535 f
|
73
|
+
0000000015 00000 n
|
74
|
+
0000000109 00000 n
|
75
|
+
0000000158 00000 n
|
76
|
+
0000000215 00000 n
|
77
|
+
0000001376 00000 n
|
78
|
+
trailer
|
79
|
+
<< /Size 6
|
80
|
+
/Root 2 0 R
|
81
|
+
/Info 1 0 R
|
82
|
+
>>
|
83
|
+
startxref
|
84
|
+
1553
|
85
|
+
%%EOF
|
Binary file
|
@@ -0,0 +1,79 @@
|
|
1
|
+
%PDF-1.3
|
2
|
+
%����
|
3
|
+
1 0 obj
|
4
|
+
<< /Creator <feff0050007200610077006e>
|
5
|
+
/Producer <feff0050007200610077006e>
|
6
|
+
>>
|
7
|
+
endobj
|
8
|
+
2 0 obj
|
9
|
+
<< /Type /Catalog
|
10
|
+
/Pages 3 0 R
|
11
|
+
>>
|
12
|
+
endobj
|
13
|
+
3 0 obj
|
14
|
+
<< /Type /Pages
|
15
|
+
/Count 1
|
16
|
+
/Kids [5 0 R]
|
17
|
+
>>
|
18
|
+
endobj
|
19
|
+
4 0 obj
|
20
|
+
<< /Length 926
|
21
|
+
>>
|
22
|
+
stream
|
23
|
+
q
|
24
|
+
28.346 21.260 m
|
25
|
+
28.346 25.174 25.174 28.346 21.260 28.346 c
|
26
|
+
17.346 28.346 14.173 25.174 14.173 21.260 c
|
27
|
+
14.173 17.346 17.346 14.173 21.260 14.173 c
|
28
|
+
25.174 14.173 28.346 17.346 28.346 21.260 c
|
29
|
+
21.260 21.260 m
|
30
|
+
28.346 820.630 m
|
31
|
+
28.346 824.544 25.174 827.717 21.260 827.717 c
|
32
|
+
17.346 827.717 14.173 824.544 14.173 820.630 c
|
33
|
+
14.173 816.716 17.346 813.543 21.260 813.543 c
|
34
|
+
25.174 813.543 28.346 816.716 28.346 820.630 c
|
35
|
+
21.260 820.630 m
|
36
|
+
581.102 820.630 m
|
37
|
+
581.102 824.544 577.930 827.717 574.016 827.717 c
|
38
|
+
570.102 827.717 566.929 824.544 566.929 820.630 c
|
39
|
+
566.929 816.716 570.102 813.543 574.016 813.543 c
|
40
|
+
577.930 813.543 581.102 816.716 581.102 820.630 c
|
41
|
+
574.016 820.630 m
|
42
|
+
581.102 21.260 m
|
43
|
+
581.102 25.174 577.930 28.346 574.016 28.346 c
|
44
|
+
570.102 28.346 566.929 25.174 566.929 21.260 c
|
45
|
+
566.929 17.346 570.102 14.173 574.016 14.173 c
|
46
|
+
577.930 14.173 581.102 17.346 581.102 21.260 c
|
47
|
+
574.016 21.260 m
|
48
|
+
f
|
49
|
+
42.520 14.173 5.669 14.173 re
|
50
|
+
f
|
51
|
+
Q
|
52
|
+
|
53
|
+
endstream
|
54
|
+
endobj
|
55
|
+
5 0 obj
|
56
|
+
<< /Type /Page
|
57
|
+
/Parent 3 0 R
|
58
|
+
/MediaBox [0 0 595.2755905511815 841.889763779528]
|
59
|
+
/Contents 4 0 R
|
60
|
+
/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
|
61
|
+
>>
|
62
|
+
>>
|
63
|
+
endobj
|
64
|
+
xref
|
65
|
+
0 6
|
66
|
+
0000000000 65535 f
|
67
|
+
0000000015 00000 n
|
68
|
+
0000000109 00000 n
|
69
|
+
0000000158 00000 n
|
70
|
+
0000000215 00000 n
|
71
|
+
0000001192 00000 n
|
72
|
+
trailer
|
73
|
+
<< /Size 6
|
74
|
+
/Root 2 0 R
|
75
|
+
/Info 1 0 R
|
76
|
+
>>
|
77
|
+
startxref
|
78
|
+
1369
|
79
|
+
%%EOF
|