mork 0.8.1 → 0.9.0

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.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/README.md +107 -35
  4. data/lib/mork/coord.rb +1 -1
  5. data/lib/mork/extensions.rb +3 -0
  6. data/lib/mork/grid.rb +13 -6
  7. data/lib/mork/grid_const.rb +11 -9
  8. data/lib/mork/grid_omr.rb +15 -5
  9. data/lib/mork/grid_pdf.rb +1 -0
  10. data/lib/mork/magicko.rb +46 -28
  11. data/lib/mork/mimage.rb +113 -52
  12. data/lib/mork/mimage_list.rb +6 -5
  13. data/lib/mork/npatch.rb +16 -18
  14. data/lib/mork/sheet_omr.rb +210 -125
  15. data/lib/mork/sheet_pdf.rb +15 -8
  16. data/lib/mork/version.rb +1 -1
  17. data/mork.gemspec +2 -0
  18. data/mork.sublime-project +1 -1
  19. data/spec/mork/extensions_spec.rb +3 -3
  20. data/spec/mork/grid_omr_spec.rb +2 -1
  21. data/spec/mork/grid_spec.rb +34 -35
  22. data/spec/mork/magicko_spec.rb +2 -2
  23. data/spec/mork/mimage_spec.rb +22 -63
  24. data/spec/mork/sheet_omr_spec.rb +96 -201
  25. data/spec/mork/sheet_pdf_spec.rb +9 -10
  26. data/spec/out/{.gitignore → barcode/.gitignore} +0 -0
  27. data/spec/out/highlight/.gitignore +4 -0
  28. data/spec/out/mark/.gitignore +4 -0
  29. data/spec/out/outline/.gitignore +4 -0
  30. data/spec/out/pdf/.gitignore +4 -0
  31. data/spec/out/registration/.gitignore +4 -0
  32. data/spec/out/text/.gitignore +4 -0
  33. data/spec/samples/angolo.jpg +0 -0
  34. data/spec/samples/angolo2.jpg +0 -0
  35. data/spec/samples/angolo3.jpg +0 -0
  36. data/spec/samples/boxy.yml +0 -0
  37. data/spec/samples/grid.yml +0 -0
  38. data/spec/samples/grid160.yml +0 -0
  39. data/spec/samples/grid_omr_layout.yml +56 -0
  40. data/spec/samples/info.yml +15 -39
  41. data/spec/samples/jdoe/JohnDoe1.jpeg +0 -0
  42. data/spec/samples/jdoe/JohnDoe2.jpeg +0 -0
  43. data/spec/samples/jdoe/JohnDoe3.jpeg +0 -0
  44. data/spec/samples/jdoe/layout.yml +58 -0
  45. data/spec/samples/layout.yml +2 -2
  46. data/spec/samples/lucrezia/border1.pdf +0 -0
  47. data/spec/samples/lucrezia/border2.pdf +0 -0
  48. data/spec/samples/lucrezia/bw1.pdf +0 -0
  49. data/spec/samples/lucrezia/bw2.pdf +0 -0
  50. data/spec/samples/lucrezia/gray1.pdf +0 -0
  51. data/spec/samples/lucrezia/gray2.pdf +0 -0
  52. data/spec/samples/{syst/IMG_20150104_0004.jpg → marisol/marisol1.jpg} +0 -0
  53. data/spec/samples/{syst/IMG_20150104_0009.jpg → marisol/marisol2.jpg} +0 -0
  54. data/spec/samples/{syst/IMG_20150104_0011.jpg → marisol/marisol3.jpg} +0 -0
  55. data/spec/samples/reg_mark.jpg +0 -0
  56. data/spec/samples/rm00.jpeg +0 -0
  57. data/spec/samples/rm01.jpeg +0 -0
  58. data/spec/samples/rm02.jpeg +0 -0
  59. data/spec/samples/rm03.jpeg +0 -0
  60. data/spec/samples/rm04.jpeg +0 -0
  61. data/spec/samples/rm05.jpeg +0 -0
  62. data/spec/samples/syst/barr0.jpg +0 -0
  63. data/spec/samples/syst/barr1.jpg +0 -0
  64. data/spec/samples/syst/barr2.jpg +0 -0
  65. data/spec/samples/syst/bell0.jpg +0 -0
  66. data/spec/samples/syst/bell1.jpg +0 -0
  67. data/spec/samples/syst/bell2.jpg +0 -0
  68. data/spec/samples/syst/bila0.jpg +0 -0
  69. data/spec/samples/syst/bila1.jpg +0 -0
  70. data/spec/samples/syst/bila2.jpg +0 -0
  71. data/spec/samples/syst/bila3.jpg +0 -0
  72. data/spec/samples/syst/bila4.jpg +0 -0
  73. data/spec/samples/syst/bone0.jpg +0 -0
  74. data/spec/samples/syst/bone1.jpg +0 -0
  75. data/spec/samples/syst/bone2.jpg +0 -0
  76. data/spec/samples/syst/cost0.jpg +0 -0
  77. data/spec/samples/syst/cost1.jpg +0 -0
  78. data/spec/samples/syst/cost2.jpg +0 -0
  79. data/spec/samples/syst/cost3.jpg +0 -0
  80. data/spec/samples/syst/cost4.jpg +0 -0
  81. data/spec/samples/syst/dald0.jpg +0 -0
  82. data/spec/samples/syst/dald1.jpg +0 -0
  83. data/spec/samples/syst/dald2.jpg +0 -0
  84. data/spec/samples/syst/dald3.jpg +0 -0
  85. data/spec/samples/syst/dald4.jpg +0 -0
  86. data/spec/samples/syst/dign0.jpg +0 -0
  87. data/spec/samples/syst/dign1.jpg +0 -0
  88. data/spec/samples/syst/dign2.jpg +0 -0
  89. data/spec/samples/syst/dive0.jpg +0 -0
  90. data/spec/samples/syst/dive1.jpg +0 -0
  91. data/spec/samples/syst/dive2.jpg +0 -0
  92. data/spec/samples/syst/histo.m +0 -0
  93. data/spec/samples/{syst_grid.yml → syst/layout.yml} +0 -0
  94. data/spec/spec_helper.rb +29 -29
  95. metadata +49 -62
  96. data/auto.txt +0 -0
  97. data/spec/samples/out-1.jpg +0 -0
  98. data/spec/samples/qzc013.jpg +0 -0
  99. data/spec/samples/sample02.jpg +0 -0
  100. data/spec/samples/sample_gray.jpg +0 -0
  101. data/spec/samples/sheet.jpg +0 -0
  102. data/spec/samples/sheet666.jpg +0 -0
  103. data/spec/samples/slanted.jpg +0 -0
  104. data/spec/samples/slanted.yml +0 -54
  105. data/spec/samples/syst/IMG_20150104_0004.txt +0 -4955
  106. data/spec/samples/syst/IMG_20150104_0009.txt +0 -4955
  107. data/spec/samples/syst/IMG_20150104_0011.txt +0 -4955
  108. data/spec/samples/syst/SCN_0001.jpg +0 -0
  109. data/spec/samples/syst/SCN_0001.txt +0 -4955
  110. data/spec/samples/syst/barr0.txt +0 -4955
  111. data/spec/samples/syst/barr1.txt +0 -4955
  112. data/spec/samples/syst/barr2.txt +0 -4955
  113. data/spec/samples/syst/bell0.txt +0 -4955
  114. data/spec/samples/syst/bell1.txt +0 -4955
  115. data/spec/samples/syst/bell2.txt +0 -4955
  116. data/spec/samples/syst/bila0.txt +0 -4955
  117. data/spec/samples/syst/bila1.txt +0 -4955
  118. data/spec/samples/syst/bila2.txt +0 -4955
  119. data/spec/samples/syst/bila3.txt +0 -4955
  120. data/spec/samples/syst/bila4.txt +0 -4955
  121. data/spec/samples/syst/bone0.txt +0 -4955
  122. data/spec/samples/syst/bone1.txt +0 -4955
  123. data/spec/samples/syst/bone2.txt +0 -4955
  124. data/spec/samples/syst/cost0.txt +0 -4955
  125. data/spec/samples/syst/cost1.txt +0 -4955
  126. data/spec/samples/syst/cost2.txt +0 -4955
  127. data/spec/samples/syst/cost3.txt +0 -4955
  128. data/spec/samples/syst/cost4.txt +0 -4955
  129. data/spec/samples/syst/dald0.txt +0 -4955
  130. data/spec/samples/syst/dald1.txt +0 -4955
  131. data/spec/samples/syst/dald2.txt +0 -4955
  132. data/spec/samples/syst/dald3.txt +0 -4955
  133. data/spec/samples/syst/dald4.txt +0 -4955
  134. data/spec/samples/syst/dign0.txt +0 -4955
  135. data/spec/samples/syst/dign1.txt +0 -4955
  136. data/spec/samples/syst/dign2.txt +0 -4955
  137. data/spec/samples/syst/dive0.txt +0 -4955
  138. data/spec/samples/syst/dive1.txt +0 -4955
  139. data/spec/samples/syst/dive2.txt +0 -4955
  140. data/spec/samples/syst/out0000.jpg +0 -0
  141. data/spec/samples/syst/out0000.txt +0 -4955
  142. data/spec/samples/syst/out0001.jpg +0 -0
  143. data/spec/samples/syst/out0001.txt +0 -4955
  144. data/spec/samples/syst/out0002.jpg +0 -0
  145. data/spec/samples/syst/out0002.txt +0 -4955
  146. data/spec/samples/syst/qzc013.jpg +0 -0
  147. data/spec/samples/syst/qzc013.txt +0 -4955
  148. data/spec/samples/syst/sample_gray.jpg +0 -0
  149. data/spec/samples/syst/sample_gray.txt +0 -4955
  150. data/spec/samples/two_pages.pdf +0 -0
@@ -4,81 +4,40 @@ module Mork
4
4
  describe Mimage do
5
5
  let(:qna) { [5] * 100 }
6
6
 
7
- context 'new age on slanted' do
8
- let(:img) { sample_img 'slanted' }
9
- let(:mim) { Mimage.new img.filename, qna, GridOMR.new(img.grid_file) }
7
+ context 'John Doe' do
8
+ let(:img) { sample_img 'jdoe1' }
9
+ let(:fn) { File.basename(img.image_path) }
10
+ let(:mim) { Mimage.new img.image_path, [img.nchoices]*img.nitems, GridOMR.new(img.grid_path) }
10
11
  describe 'basics' do
11
12
  it 'should be valid' do
12
- mim.highlight_rm_centers
13
- mim.highlight_rm_areas
14
- mim.write 'spec/out/slanted.jpg', false
15
13
  expect(mim.valid?).to be_truthy
16
14
  end
17
15
 
18
16
  it 'should return the correct regmark coordinates' do
19
17
  [:tl, :tr, :br, :bl].each do |corner|
20
18
  crn = mim.rm[corner]
21
- expect(crn[:x]).to be_within(2).of(img.info[corner.to_s][0])
22
-
23
- end
24
- end
25
- end
26
- end
27
-
28
- context 'problematic sheets' do
29
- let(:mim) { Mimage.new 'spec/samples/out-1.jpg', qna, GridOMR.new('spec/samples/grid.yml') }
30
- let(:bila) { Mimage.new 'spec/samples/syst/bila0.jpg', qna, GridOMR.new('spec/samples/grid.yml') }
31
-
32
- it 'writes all cell values to a text file', exclude: true do
33
- d=Dir['spec/samples/syst/*.jpg']
34
- d.each do |f|
35
- fn = File.basename f, '.jpg'
36
- m = Mimage.new "spec/samples/syst/#{fn}.jpg", qna, GridOMR.new('spec/samples/grid.yml')
37
- puts fn
38
- File.open("spec/samples/syst/#{fn}.txt",'w') do |f|
39
- f.puts "ink:#{m.send :ink_black}"
40
- f.puts "drk:#{m.send :darkest_cell_mean}"
41
- f.puts "pap:#{m.send :paper_white}"
42
- f.puts "cal:#{m.send :cal_cell_mean}"
43
- f.puts "cho:#{m.send :choice_threshold}"
44
- 100.times do |q|
45
- 5.times do |c|
46
- f.puts m.send('choice_cell_averages')[q, c]
47
- end
48
- end
19
+ expect(crn[:x]).to be_within(2).of(img.send(corner)[0])
20
+ expect(crn[:x]).to be_within(2).of(img.send(corner)[0])
49
21
  end
50
22
  end
51
- end
52
- end
53
-
54
- context 'Old specs' do
55
- let(:sgi) { sample_img 'sample-gray' }
56
- let(:sg) { Mimage.new sgi.filename, qna, GridOMR.new(sgi.grid_file) }
57
-
58
- describe 'basics' do
59
- it 'returns the pixels as an array' do
60
- expect(sg.send :reg_pixels).to be_a NPatch
61
- end
62
-
63
- it 'returns the correct number of pixels' do
64
- expect(sg.send(:reg_pixels).length).to eq sgi.width * sgi.height
65
- end
66
-
67
- it 'returns the stretched array' do
68
- expect(sg.send(:reg_pixels).length).to eq sgi.width * sgi.height
69
- end
70
- end
71
23
 
72
- describe 'inspecting' do
73
- xit 'writes out average whiteness of choice cells' do
74
- qz = sample_img 'silvia'
75
- s = Mimage.new qz.filename, [5] * 5, GridOMR.new(qz.grid_file)
76
- File.open('spec/out/choices.txt', 'w') do |f|
77
- 5.times do |q|
78
- t = (0..4).collect do |c|
79
- s.send(:shade_of, q, c).round
24
+ xit 'writes all cell values to a text file' do
25
+ d=Dir['spec/samples/syst/*.jpg']
26
+ d.each do |f|
27
+ fname = File.basename f, '.jpg'
28
+ m = Mimage.new "spec/samples/syst/#{fname}.jpg", qna, GridOMR.new('spec/samples/grid.yml')
29
+ puts fname
30
+ File.open("spec/out/text/#{fname}.txt",'w') do |f|
31
+ f.puts "ink:#{m.send :ink_black}"
32
+ f.puts "drk:#{m.send :darkest_cell_mean}"
33
+ f.puts "pap:#{m.send :paper_white}"
34
+ f.puts "cal:#{m.send :cal_cell_mean}"
35
+ f.puts "cho:#{m.send :choice_threshold}"
36
+ 100.times do |q|
37
+ 5.times do |c|
38
+ f.puts m.send('choice_cell_averages')[q, c]
39
+ end
80
40
  end
81
- f.puts "#{q+1}: #{t.join(' ')}"
82
41
  end
83
42
  end
84
43
  end
@@ -3,258 +3,153 @@ require 'fileutils'
3
3
 
4
4
  module Mork
5
5
  describe SheetOMR do
6
- context 'basic object generation' do
7
- let(:img) { sample_img 'slanted' }
8
- let(:omr) { SheetOMR.new img.filename, [5] * 120, img.grid_file }
6
+ context 'with a valid response sheet' do
7
+ let(:img) { sample_img 'jdoe1' }
8
+ let(:fn) { File.basename(img.image_path) }
9
+ let(:omr) { SheetOMR.new img.image_path, choices: [img.nchoices]*img.nitems, layout: img.grid_path }
9
10
  describe '#new' do
10
- it 'raises an error if the provided path is invalid' do
11
- expect { SheetOMR.new 'non_existing_file.jpg'}.to raise_error IOError
12
- end
13
-
14
11
  it 'creates a SheetOMR object' do
15
12
  expect(omr).to be_a SheetOMR
16
13
  end
17
14
 
18
- it 'registers correctly' do
19
- expect(omr.valid?).to be_truthy
20
- end
21
-
22
- it 'writes out the registration' do
23
- omr.write_registration 'spec/out/slanted2.jpg'
15
+ it 'raises an error if the provided path is invalid' do
16
+ expect { SheetOMR.new 'non_existing_file.jpg'}.to raise_error IOError
24
17
  end
25
18
  end
26
- end
27
- # context 'problematic' do
28
- # let(:shinfo) { sample_img 'bianchi' }
29
- # let(:sheet) { SheetOMR.new shinfo.filename, shinfo.grid_file }
30
- #
31
- # it 'has a status' do
32
- # sheet.status.should == {:tl=>:ok, :tr=>:ok, :br=>:ok, :bl=>:ok, :write=>nil}
33
- # end
34
- #
35
- # it 'has a barcode' do
36
- # sheet.barcode.should == shinfo.barcode_int
37
- # end
38
- #
39
- # it 'writes the registered and marked image' do
40
- # sheet.cross_marked
41
- # sheet.write 'spec/out/bianchi.jpg'
42
- # sheet.status[:write].should == :fail
43
- # end
44
- #
45
- # it 'writes the registration areas' do
46
- # sheet.highlight_registration
47
- # sheet.write_raw 'spec/out/reg_bianchi.jpg'
48
- # end
49
- #
50
- # end
51
- #
52
- context 'slanted' do
53
- let(:sh) { sample_img 'slanted' }
54
- let(:sheet) { SheetOMR.new sh.filename, [5]*120, sh.grid_file }
55
-
56
- it 'gets in trouble' do
57
- sheet.write_registration 'spec/out/laurout.jpg'
58
- end
59
-
60
- it 'gets more in trouble' do
61
- sheet.highlight_marked
62
- sheet.write 'spec/out/lauraout2.jpg'
63
- end
64
-
65
- it 'should be valid' do
66
- expect(sheet.valid?).to be_truthy
67
- end
68
- end
69
-
70
- context 'highlighting' do
71
- # since these specs change the @crop, they must be run in isolation
72
- # with the SheetOMR rebuilt each time, even though it is time consuming!
73
- let(:shinfo) { sample_img 'sample-gray' }
74
- let(:sheet) { SheetOMR.new shinfo.filename, [5]*120, shinfo.grid_file }
75
-
76
- it 'writes the sheet with registrations highlighted' do
77
- sheet.write_registration 'spec/out/sample_gray_registered.jpg'
78
- end
79
-
80
- it 'highlights all choice cells' do
81
- sheet.highlight_all_choices
82
- sheet.write 'spec/out/all_highlights.jpg'
83
- end
84
-
85
- it 'highlights marked cells' do
86
- sheet.highlight_marked
87
- sheet.write 'spec/out/marked_highlights.jpg'
88
- end
89
-
90
- it 'crossed marked cells' do
91
- sheet.cross_marked
92
- sheet.write 'spec/out/marked_crosses.jpg'
93
- end
94
19
 
95
- it 'outlines some responses' do
96
- sheet.outline [[1],[1],[2],[2],[3,4],[],[0,1,2,3,4], [],[1],[2],[2],[3,4],[],[0,1,2,3,4]]
97
- sheet.write 'spec/out/outlines.jpg'
20
+ describe '#valid?' do
21
+ it 'registers correctly' do
22
+ expect(omr.valid?).to be_truthy
23
+ end
98
24
  end
99
25
 
100
- it 'cross some responses' do
101
- sheet.cross [[1],[1],[2],[2],[3,4],[],[0,1,2,3,4], [],[1],[2],[2],[3,4],[],[0,1,2,3,4]]
102
- sheet.write 'spec/out/crosses.jpg'
26
+ describe '#status' do
27
+ it 'returns the registration status for each of the four corners' do
28
+ expect(omr.status).to eq({ tl: :ok, tr: :ok, br: :ok, bl: :ok })
29
+ end
103
30
  end
104
31
 
105
- it 'outlines some responses in-place (rewriting the source image)' do
106
- FileUtils.cp shinfo.filename, 'spec/out/inplace.jpg'
107
- tsheet = SheetOMR.new 'spec/out/inplace.jpg', [5]*100, shinfo.grid_file
108
- tsheet.outline [[1],[1],[2],[2],[3,4],[],[0,1,2,3,4], [],[1],[2],[2],[3,4],[],[0,1,2,3,4]]
109
- tsheet.write
32
+ describe '#barcode' do
33
+ it 'returns the integer form of the barcode' do
34
+ expect(omr.barcode).to eq img.barcode_int
35
+ end
110
36
  end
111
37
 
112
- it 'highlights marked cells and outline correct responses' do
113
- sheet.highlight_marked
114
- sheet.outline [[1],[1],[2],[2],[3,4],[],[0,1,2,3,4], [],[1],[2],[2],[3,4],[],[0,1,2,3,4]]
115
- sheet.write 'spec/out/marks_and_outs.jpg'
38
+ describe '#barcode_string' do
39
+ it 'returns the binary string version of the barcode' do
40
+ expect(omr.barcode_string).to eq img.barcode_str
41
+ end
116
42
  end
117
43
 
118
- it 'highlights marked cells of a problematic one' do
119
- si = sample_img 'silvia'
120
- s = SheetOMR.new si.filename, [5]*100, si.grid_file
121
- s.highlight_marked
122
- s.write 'spec/out/problem.jpg'
44
+ describe '#marked?' do
45
+ it 'returns true if the given cell was marked, false otherwise' do
46
+ expect(omr.marked? 0, 0).to be_truthy
47
+ expect(omr.marked? 0, 1).to be_falsy
48
+ expect(omr.marked? 119, 4).to be_truthy
49
+ expect(omr.marked? 119, 3).to be_falsy
50
+ end
123
51
  end
124
52
 
125
- it 'highlights the barcode' do
126
- si = sample_img 'sample-gray'
127
- s = SheetOMR.new si.filename, [5]*100, si.grid_file
128
- s.highlight_barcode
129
- s.write 'spec/out/code_bits.jpg'
53
+ describe '#marked_choices' do
54
+ it 'returns an array of marked choices as position indices' do
55
+ expect(omr.marked_choices).to eq standard_mark_array(24)
56
+ end
130
57
  end
131
- end
132
58
 
133
- context 'marking a nicely printed and scanned sheet' do
134
- before(:all) do
135
- @shinfo = sample_img 'sample-gray'
136
- @sheet = SheetOMR.new @shinfo.filename, [5]*120, @shinfo.grid_file
137
- end
59
+ describe '#marked_choices' do
60
+ it 'returns an array of marked choices as position indexes' do
61
+ expect(omr.marked_choices ).to eq standard_mark_array(24)
62
+ end
138
63
 
139
- describe '#valid?' do
140
- it 'returns true' do
141
- @sheet.valid?.should be_truthy
64
+ let(:om2) { SheetOMR.new img.image_path, choices: [5, 4, 3, 2, 1], layout: img.grid_path }
65
+ it 'returns marked choices only for existing choice cells' do
66
+ expect(om2.marked_choices).to eq [[0], [1], [2], [], []]
142
67
  end
143
68
  end
144
69
 
145
- describe '#marked?' do
146
- it 'returns true for some darkened choices' do
147
- expect(@sheet.marked?(0,0)).to be_truthy
148
- expect(@sheet.marked?(1,1)).to be_truthy
149
- expect(@sheet.marked?(2,2)).to be_truthy
70
+ describe '#marked_logicals' do
71
+ it 'returns an array of logicals for the marked choices' do
72
+ expect(omr.marked_logicals).to eq standard_mark_logical_array(24)
150
73
  end
74
+ end
151
75
 
152
- it 'return false for some blank choices' do
153
- expect(@sheet.marked?(0,1)).to be_falsy
154
- expect(@sheet.marked?(1,0)).to be_falsy
155
- expect(@sheet.marked?(2,3)).to be_falsy
76
+ describe '#marked_letters' do
77
+ it 'returns an array of characters for the marked choices' do
78
+ expect(omr.marked_letters).to eq standard_mark_char_array(24)
156
79
  end
80
+ end
157
81
 
158
- it 'writes out markedness' do
159
- mf = File.open('spec/out/marked.txt', 'w')
160
- 120.times do |q|
161
- x = 5.times.collect do |c|
162
- @sheet.marked?(q,c) ? '1' : '0'
163
- end
164
- mf.puts x.join(' ')
82
+ it 'writes out markedness' do
83
+ mf = File.open('spec/out/text/marked.txt', 'w')
84
+ img.nitems.times do |q|
85
+ x = 5.times.collect do |c|
86
+ omr.marked?(q,c) ? '1' : '0'
165
87
  end
166
- mf.close
88
+ mf.puts x.join(' ')
167
89
  end
90
+ mf.close
168
91
  end
169
92
 
170
- describe '#mark_array' do
171
- it 'should return an array of marked choices for each of the first 5 questions' do
172
- @sheet.mark_array(5).should == [[0], [1], [2], [3], [4]]
173
- end
174
-
175
- it 'should return an array of marked choices for the specified question set' do
176
- @sheet.mark_array([0, 1, 13, 16, 31, 104, 21]).should == [[0], [1], [3,4], [2], [1], [], [0,1,2,3,4]]
93
+ context 'creating overlays' do
94
+ it 'registration highlighted' do
95
+ omr.save_registration "spec/out/registration/#{fn}"
177
96
  end
178
97
 
179
- it 'should return an array of @grid.max_questions length if called without arguments' do
180
- @sheet.mark_array.length.should == 120
98
+ it 'highlights all choice cells' do
99
+ omr.overlay :highlight, :all
100
+ omr.save "spec/out/highlight/#{fn}"
181
101
  end
182
- end
183
102
 
184
- describe '#mark_logical_array' do
185
- it 'should return an array of booleans for each of the first questions' do
186
- @sheet.mark_logical_array(5).should == [
187
- [true, false, false, false, false],
188
- [false, true, false, false, false],
189
- [false, false, true, false, false],
190
- [false, false, false, true, false],
191
- [false, false, false, false, true],
192
- ]
103
+ it 'highlights marked cells' do
104
+ omr.overlay :highlight, :marked
105
+ omr.save "spec/out/highlight/marked-#{fn}"
193
106
  end
194
- end
195
107
 
196
- describe 'barcodes' do
197
- it 'should read the bit string as all ones' do
198
- @sheet.barcode_string.should == '1111111111111111111111111111111111111111'
199
- @sheet.barcode.should == 1099511627775
108
+ it 'checks marked cells' do
109
+ omr.overlay :check, :marked
110
+ omr.save "spec/out/mark/#{fn}"
200
111
  end
201
112
 
202
- it 'should read another bit string' do
203
- barcode_string = '0000000000000000000000000010000110100000'
204
- s2 = SheetOMR.new('spec/samples/sample02.jpg', [5]*100)
205
- s2.barcode_string.should == barcode_string
206
- s2.barcode.should == 8608
113
+ it 'outlines and crosses marked cells' do
114
+ omr.overlay :outline, standard_mark_array(24)
115
+ omr.overlay :check
116
+ omr.save "spec/out/outline/#{fn}"
207
117
  end
208
118
 
209
- it 'should read the 666 bit string' do
210
- sh = sample_img 'code666'
211
- s2 = SheetOMR.new sh.filename, [5]*100, sh.grid_file
212
- s2.barcode.should == sh.barcode_int
119
+ it 'highlights the barcode' do
120
+ omr.overlay :outline, :barcode
121
+ omr.save "spec/out/barcode/#{fn}"
213
122
  end
214
123
  end
215
-
216
- end
217
-
218
- context 'marking a problematic sheet' do
219
- let(:sheet) { SheetOMR.new 'spec/samples/out-1.jpg', [5]*100, 'spec/samples/grid.yml' }
220
-
221
- it 'highlights the registration' do
222
- sheet.write_registration 'spec/out/problematic.jpg'
223
- end
224
-
225
- it 'highlights the barcode' do
226
- sheet.highlight_barcode
227
- sheet.write 'spec/out/barcode.jpg'
228
- end
229
124
  end
230
125
 
231
- context 'systematic tests' do
126
+ context 'systematic tests', exclude: true do
232
127
  let(:bila) { 'CCEBEBCEEACCDCABDBEBCADEADDCCCACCACDBBDAECDDABDEEBCEEDCBAAADEEEEDCADEABCBDECCCCDDDCABBECAADADBBEEABA'.split '' }
233
- let(:bila0) { SheetOMR.new 'spec/samples/syst/bila0.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
234
- let(:bila1) { SheetOMR.new 'spec/samples/syst/bila1.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
235
- let(:bila2) { SheetOMR.new 'spec/samples/syst/bila2.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
236
- let(:bila3) { SheetOMR.new 'spec/samples/syst/bila3.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
237
- let(:bila4) { SheetOMR.new 'spec/samples/syst/bila4.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
128
+ let(:bila0) { SheetOMR.new 'spec/samples/syst/bila0.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
129
+ let(:bila1) { SheetOMR.new 'spec/samples/syst/bila1.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
130
+ let(:bila2) { SheetOMR.new 'spec/samples/syst/bila2.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
131
+ let(:bila3) { SheetOMR.new 'spec/samples/syst/bila3.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
132
+ let(:bila4) { SheetOMR.new 'spec/samples/syst/bila4.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
238
133
  let(:dald) { 'DDDBECAAADBAEEEAEEEBAACAEDBDECDBDCDCDDEDCCDCDBDCADEEDBCCBEBBAADDCDBBECBBBDEABADABADADBABAEABACBDADDA'.split '' }
239
- let(:dald0) { SheetOMR.new 'spec/samples/syst/dald0.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
240
- let(:dald1) { SheetOMR.new 'spec/samples/syst/dald1.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
241
- let(:dald2) { SheetOMR.new 'spec/samples/syst/dald2.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
242
- let(:dald3) { SheetOMR.new 'spec/samples/syst/dald3.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
243
- let(:dald4) { SheetOMR.new 'spec/samples/syst/dald4.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
134
+ let(:dald0) { SheetOMR.new 'spec/samples/syst/dald0.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
135
+ let(:dald1) { SheetOMR.new 'spec/samples/syst/dald1.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
136
+ let(:dald2) { SheetOMR.new 'spec/samples/syst/dald2.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
137
+ let(:dald3) { SheetOMR.new 'spec/samples/syst/dald3.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
138
+ let(:dald4) { SheetOMR.new 'spec/samples/syst/dald4.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
244
139
  let(:cost) { 'ABBDDBAEAEBAADEAAECBCDBBDABABADEECCACBCAEDDAEBEABBCDABECAACEEEBADECBBEAADBBBEABDAEBDEEABBABEBEDDAEEC'.split '' }
245
- let(:cost0) { SheetOMR.new 'spec/samples/syst/cost0.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
246
- let(:cost1) { SheetOMR.new 'spec/samples/syst/cost1.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
247
- let(:cost2) { SheetOMR.new 'spec/samples/syst/cost2.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
248
- let(:cost3) { SheetOMR.new 'spec/samples/syst/cost3.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
249
- let(:cost4) { SheetOMR.new 'spec/samples/syst/cost4.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
140
+ let(:cost0) { SheetOMR.new 'spec/samples/syst/cost0.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
141
+ let(:cost1) { SheetOMR.new 'spec/samples/syst/cost1.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
142
+ let(:cost2) { SheetOMR.new 'spec/samples/syst/cost2.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
143
+ let(:cost3) { SheetOMR.new 'spec/samples/syst/cost3.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
144
+ let(:cost4) { SheetOMR.new 'spec/samples/syst/cost4.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
250
145
  let(:bone) { 'CECBBABAECADEDCACBBDEECBADBECDCEDECABCAADCBDEDACAEEDCCADBEDCEBCCBBDCCACDEDDAAECEBDBADCBAAEBAEDABCBDC'.split '' }
251
- let(:bone0) { SheetOMR.new 'spec/samples/syst/bone0.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
252
- let(:bone1) { SheetOMR.new 'spec/samples/syst/bone1.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
253
- let(:bone2) { SheetOMR.new 'spec/samples/syst/bone2.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
146
+ let(:bone0) { SheetOMR.new 'spec/samples/syst/bone0.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
147
+ let(:bone1) { SheetOMR.new 'spec/samples/syst/bone1.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
148
+ let(:bone2) { SheetOMR.new 'spec/samples/syst/bone2.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
254
149
  let(:barr) { 'ACECAAADDBCECCCDBEBECDEDAECEDDEEDCDEADDCCBCCCBBEACBCAEDEEDDDABBBBABEBDCEADEEDEBCBADBCEDCDBACEBCBDCDA'.split '' }
255
- let(:barr0) { SheetOMR.new 'spec/samples/syst/barr0.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
256
- let(:barr1) { SheetOMR.new 'spec/samples/syst/barr1.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
257
- let(:barr2) { SheetOMR.new 'spec/samples/syst/barr2.jpg', [5]*100, 'spec/samples/syst_grid.yml'}
150
+ let(:barr0) { SheetOMR.new 'spec/samples/syst/barr0.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
151
+ let(:barr1) { SheetOMR.new 'spec/samples/syst/barr1.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
152
+ let(:barr2) { SheetOMR.new 'spec/samples/syst/barr2.jpg', choices: [5]*100, layout: 'spec/samples/syst/layout.yml'}
258
153
 
259
154
  it 'checks bila' do
260
155
  expect(bila0.mark_char_array.flatten).to eq(bila)
@@ -40,8 +40,8 @@ module Mork
40
40
  end
41
41
 
42
42
  it 'creates a basic PDF sheet' do
43
- s = SheetPDF.new(content, 'spec/samples/layout.yml')
44
- s.save('spec/out/sheet.pdf')
43
+ s = SheetPDF.new(content)
44
+ s.save('spec/out/pdf/sheet.pdf')
45
45
  end
46
46
 
47
47
  it 'creates a boxed PDF sheet' do
@@ -52,39 +52,38 @@ module Mork
52
52
  signature: 'Signature'
53
53
  }
54
54
  s = SheetPDF.new(content.merge({header: h}), 'spec/samples/boxy.yml')
55
- s.save('spec/out/boxy.pdf')
55
+ s.save('spec/out/pdf/boxy.pdf')
56
56
  end
57
57
 
58
58
  it 'creates a basic PDF sheet with a code of 15' do
59
59
  s = SheetPDF.new(content.merge({barcode: 15}))
60
- s.save('spec/out/sheet16.pdf')
60
+ s.save('spec/out/pdf/sheet16.pdf')
61
61
  end
62
62
 
63
63
  it 'creates a basic PDF sheet with a code of 666666666666' do
64
64
  s = SheetPDF.new(content.merge({barcode: 666666666666}))
65
- s.save('spec/out/sheet666.pdf')
65
+ s.save('spec/out/pdf/sheet666.pdf')
66
66
  end
67
67
 
68
68
  it 'creates a PDF sheet with the maximum possible barcode' do
69
69
  s = SheetPDF.new(content.merge({barcode: 1099511627775}))
70
- s.save('spec/out/maxcode.pdf')
70
+ s.save('spec/out/pdf/maxcode.pdf')
71
71
  end
72
72
 
73
73
  it 'creates a PDF sheet with 160 items' do
74
74
  s = SheetPDF.new(content.merge({choices: [5] * 160}), 'spec/samples/grid160.yml')
75
- s.save('spec/out/i160.pdf')
76
- # system 'open spec/out/i160.pdf'
75
+ s.save('spec/out/pdf/i160.pdf')
77
76
  end
78
77
 
79
78
  it 'creates a PDF sheet with unequal choices per item' do
80
79
  s = SheetPDF.new(content.merge({choices: [5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]}), 'spec/samples/layout.yml')
81
- s.save('spec/out/uneq.pdf')
80
+ s.save('spec/out/pdf/uneq.pdf')
82
81
  end
83
82
 
84
83
  it 'creates 20 PDF sheets' do
85
84
  c = content
86
85
  s = SheetPDF.new([c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c])
87
- s.save('spec/out/p20.pdf')
86
+ s.save('spec/out/pdf/p20.pdf')
88
87
  end
89
88
  end
90
89
  end
File without changes
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
@@ -0,0 +1,4 @@
1
+ # Ignore everything in this directory
2
+ *
3
+ # Except this file
4
+ !.gitignore
File without changes
Binary file
Binary file
File without changes
File without changes
File without changes
@@ -0,0 +1,56 @@
1
+ page_size: # all measurements in mm
2
+ width: 210 # width of the paper sheet
3
+ height: 297 # height of the paper sheet
4
+ reg_marks:
5
+ margin: 10 # distance from each page border to registration mark center
6
+ radius: 2.5 # registration mark radius
7
+ offset: 2 # distance between the search area and each page border (*)
8
+ crop: 20
9
+ blur: 2
10
+ dilate: 5
11
+ header:
12
+ name: # ‘name’ is just a label; you can add arbitrary header elements
13
+ top: 5 # margin relative to registration frame top side
14
+ left: 15 # margin relative to registration frame left side
15
+ width: 170 # text will be fitted to this width
16
+ height: 7 # text will be fitted to this height
17
+ size: 14 # font size
18
+ title:
19
+ top: 15
20
+ left: 15
21
+ width: 180
22
+ height: 12
23
+ size: 12
24
+ code:
25
+ top: 5
26
+ left: 165
27
+ width: 20
28
+ height: 10
29
+ size: 14
30
+ signature:
31
+ top: 30
32
+ left: 7.5
33
+ width: 120
34
+ height: 15
35
+ size: 7
36
+ box: true # header element will be enclosed in a box
37
+ items:
38
+ top: 55.5 # response area margin, relative to reg frame
39
+ left: 10.5 # response area margin, relative to reg frame
40
+ rows: 30 # number of items per column
41
+ columns: 4 # number of columns
42
+ column_width: 44 #
43
+ x_spacing: 7 # horizontal distance between ajacent cell centers
44
+ y_spacing: 7 # vertical distance between ajacent cell centers
45
+ cell_width: 6 # width of each choice and calibration cell
46
+ cell_height: 5 # height of each choice and calibration cell
47
+ max_cells: 5 # maximum number of choices per item
48
+ font_size: 9 # size of both the item number and choice cell letter
49
+ number_width: 8 #
50
+ number_margin: 2 # margin between
51
+ barcode:
52
+ bits: 40 # the maximum sheet identifier is 2 to the power or bits
53
+ left: 15 # distance between registration frame side and the first barcode bit
54
+ width: 3 # width of each barcode bit
55
+ height: 2.5 # height of each barcode bit from the registration frame bottom side
56
+ spacing: 4 # horizontal distance between adjacent barcode bit centers