mork 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mork/grid.rb +9 -1
- data/lib/mork/grid_const.rb +1 -1
- data/lib/mork/grid_omr.rb +0 -1
- data/lib/mork/grid_pdf.rb +53 -43
- data/lib/mork/mimage.rb +6 -15
- data/lib/mork/sheet_pdf.rb +96 -52
- data/lib/mork/version.rb +1 -1
- data/spec/mork/sheet_pdf_spec.rb +10 -3
- data/spec/samples/grid160.yml +1 -1
- data/spec/samples/layout.yml +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cedc2c2924bff45051c7d4fdace910882b95ade7
|
4
|
+
data.tar.gz: 4a97e442ee44a1e615e9d92dd1be2dfa8af01545
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77283aab2e31e1189a7579f49b6a535b374381254df3b75a4ded1eb2ea871ba11987b441237afef320e59a5fd605a8b9a1863b80c27547221064696f52a75642
|
7
|
+
data.tar.gz: b2ea3c69c2fd974d4d047af7ad2aec052dcd34046ca06a5ad20666dd31df1485dd906b52164929ae8c826c857783f7ac25f0aa84da5ea6f2f1266e6548f7226e
|
data/lib/mork/grid.rb
CHANGED
@@ -39,6 +39,10 @@ module Mork
|
|
39
39
|
columns * rows
|
40
40
|
end
|
41
41
|
|
42
|
+
def max_choices_per_question
|
43
|
+
@params[:items][:max_cells].to_i
|
44
|
+
end
|
45
|
+
|
42
46
|
def barcode_bits
|
43
47
|
@params[:barcode][:bits].to_i
|
44
48
|
end
|
@@ -68,7 +72,11 @@ module Mork
|
|
68
72
|
# the distance from the registration frame to the left edge
|
69
73
|
# of the c-th choice cell of the q-th question
|
70
74
|
def cell_x(q,c)
|
71
|
-
|
75
|
+
item_x(q) + cell_spacing * c
|
76
|
+
end
|
77
|
+
|
78
|
+
def item_x(q)
|
79
|
+
first_x + column_width * (q / rows) - cell_width / 2
|
72
80
|
end
|
73
81
|
|
74
82
|
def cal_cell_x
|
data/lib/mork/grid_const.rb
CHANGED
data/lib/mork/grid_omr.rb
CHANGED
@@ -73,7 +73,6 @@ module Mork
|
|
73
73
|
# areas on the sheet that are certainly white/black
|
74
74
|
def paper_white_area() barcode_bit_area -1 end
|
75
75
|
def ink_black_area() barcode_bit_area 0 end
|
76
|
-
def max_choices_per_question() @params[:items][:max_cells].to_i end
|
77
76
|
def rm_max_search_area_side() (ppu_x * page_width / 4).round end
|
78
77
|
|
79
78
|
private
|
data/lib/mork/grid_pdf.rb
CHANGED
@@ -18,62 +18,66 @@ module Mork
|
|
18
18
|
]
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def barcode_width
|
22
|
+
super.mm
|
23
|
+
end
|
24
|
+
|
25
|
+
def barcode_height
|
26
|
+
super.mm
|
27
|
+
end
|
28
|
+
|
29
|
+
def barcode_xy_for(code)
|
22
30
|
black = barcode_bits.times.reject { |x| (code>>x)[0]==0 }
|
23
|
-
black.collect { |x|
|
31
|
+
black.collect { |x| barcode_xy x+1 }
|
24
32
|
end
|
25
33
|
|
26
|
-
def
|
27
|
-
|
28
|
-
{
|
29
|
-
p: [(reg_frame_width-cell_spacing).mm, (reg_frame_height - cell_y(q)).mm],
|
30
|
-
w: cell_width.mm,
|
31
|
-
h: cell_height.mm
|
32
|
-
}
|
33
|
-
end
|
34
|
+
def ink_black_xy
|
35
|
+
barcode_xy 0
|
34
36
|
end
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
item_text_y(q)
|
41
|
-
]
|
38
|
+
def calibration_cells_xy
|
39
|
+
rows.times.collect do |q|
|
40
|
+
[(reg_frame_width-cell_spacing).mm, item_y(q).mm]
|
41
|
+
end
|
42
42
|
end
|
43
43
|
|
44
44
|
# Coordinates at which to place item numbers
|
45
45
|
def qnum_xy(q)
|
46
46
|
[
|
47
|
-
|
48
|
-
|
47
|
+
item_x(q).mm - qnum_width - qnum_margin,
|
48
|
+
item_y(q).mm
|
49
49
|
]
|
50
50
|
end
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
[
|
55
|
-
cell_x(q, c).mm + 2.mm,
|
56
|
-
item_text_y(q)
|
57
|
-
]
|
52
|
+
def width_of_cell
|
53
|
+
cell_width.mm
|
58
54
|
end
|
59
55
|
|
60
|
-
def
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
56
|
+
def height_of_cell
|
57
|
+
cell_height.mm
|
58
|
+
end
|
59
|
+
|
60
|
+
def choice_spacing
|
61
|
+
cell_spacing.mm
|
62
|
+
end
|
63
|
+
|
64
|
+
def item_xy(q)
|
65
|
+
[item_x(q).mm, item_y(q).mm]
|
66
|
+
end
|
67
|
+
|
68
|
+
def cround
|
69
|
+
@cround ||= [width_of_cell, height_of_cell].min / 2
|
66
70
|
end
|
67
71
|
|
68
|
-
def page_size() [page_width.mm, page_height.mm]
|
69
|
-
def margins() reg_margin.mm
|
70
|
-
def
|
71
|
-
def qnum_width() @params[:items][:number_width].to_f.mm
|
72
|
-
def item_font_size() @params[:items][:font_size].to_f
|
73
|
-
def header_width(k) @params[:header][k][:width].to_f.mm
|
74
|
-
def header_height(k) @params[:header][k][:height].to_f.mm
|
75
|
-
def header_size(k) @params[:header][k][:size].to_f
|
76
|
-
def header_boxed?(k) @params[:header][k][:box] == true
|
72
|
+
def page_size() [page_width.mm, page_height.mm] end
|
73
|
+
def margins() reg_margin.mm end
|
74
|
+
def qnum_margin() @params[:items][:number_margin].to_f.mm end
|
75
|
+
def qnum_width() @params[:items][:number_width].to_f.mm end
|
76
|
+
def item_font_size() @params[:items][:font_size].to_f end
|
77
|
+
def header_width(k) @params[:header][k][:width].to_f.mm end
|
78
|
+
def header_height(k) @params[:header][k][:height].to_f.mm end
|
79
|
+
def header_size(k) @params[:header][k][:size].to_f end
|
80
|
+
def header_boxed?(k) @params[:header][k][:box] == true end
|
77
81
|
|
78
82
|
def header_xy(k)
|
79
83
|
[
|
@@ -88,12 +92,18 @@ module Mork
|
|
88
92
|
header_height(k) - 1.mm
|
89
93
|
]
|
90
94
|
end
|
91
|
-
|
92
95
|
|
93
96
|
private
|
94
|
-
|
95
|
-
def
|
96
|
-
|
97
|
+
|
98
|
+
def item_y(q)
|
99
|
+
reg_frame_height - cell_y(q)
|
100
|
+
end
|
101
|
+
|
102
|
+
def barcode_xy(i)
|
103
|
+
[
|
104
|
+
barcode_bit_x(i).mm,
|
105
|
+
barcode_height
|
106
|
+
]
|
97
107
|
end
|
98
108
|
|
99
109
|
def barcode_area(i)
|
data/lib/mork/mimage.rb
CHANGED
@@ -142,22 +142,16 @@ module Mork
|
|
142
142
|
# if the 2nd arg is false, then stretching is not applied
|
143
143
|
def write(fname=nil, reg=true)
|
144
144
|
if fname
|
145
|
-
# img = MiniMagick::Image.open @path
|
146
|
-
# img.combine_options {|c| exec_mm_cmd c, reg }
|
147
|
-
# begin
|
148
|
-
# img.write fname
|
149
|
-
# @write = :ok
|
150
|
-
# rescue Exception
|
151
|
-
# @write = :fail
|
152
|
-
# end
|
153
145
|
MiniMagick::Tool::Convert.new(false) do |img|
|
154
146
|
img << @path
|
155
|
-
img
|
156
|
-
@cmd.each { |cmd| img.send *cmd }
|
147
|
+
exec_mm_cmd img, reg
|
157
148
|
img << fname
|
158
149
|
end
|
159
150
|
else
|
160
|
-
MiniMagick::
|
151
|
+
MiniMagick::Tool::Mogrify.new(false) do |img|
|
152
|
+
img << @path
|
153
|
+
exec_mm_cmd img, reg
|
154
|
+
end
|
161
155
|
end
|
162
156
|
end
|
163
157
|
|
@@ -166,10 +160,7 @@ module Mork
|
|
166
160
|
# ============================================================#
|
167
161
|
def exec_mm_cmd(c, reg)
|
168
162
|
c.distort(:perspective, perspective_points) if reg
|
169
|
-
|
170
|
-
@cmd.each do |cmd|
|
171
|
-
c.send *cmd
|
172
|
-
end
|
163
|
+
@cmd.each { |cmd| c.send *cmd }
|
173
164
|
end
|
174
165
|
|
175
166
|
def img_size
|
data/lib/mork/sheet_pdf.rb
CHANGED
@@ -2,6 +2,9 @@ require 'mork/grid_pdf'
|
|
2
2
|
require 'prawn'
|
3
3
|
|
4
4
|
module Mork
|
5
|
+
|
6
|
+
#TODO: read the prawn manual, we should probably use views
|
7
|
+
|
5
8
|
class SheetPDF < Prawn::Document
|
6
9
|
def initialize(content, grip=GridPDF.new)
|
7
10
|
@grip = case grip
|
@@ -26,21 +29,6 @@ module Mork
|
|
26
29
|
|
27
30
|
private
|
28
31
|
|
29
|
-
def process
|
30
|
-
# for each response sheet
|
31
|
-
@content.each_with_index do |content, i|
|
32
|
-
start_new_page if i>0
|
33
|
-
fill_color "000000"
|
34
|
-
stroke_color "000000"
|
35
|
-
line_width 0.3
|
36
|
-
registration_marks
|
37
|
-
barcode content[:barcode]
|
38
|
-
header content[:header]
|
39
|
-
questions_and_choices content[:choices]
|
40
|
-
calibration_cells
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
32
|
def my_page_params
|
45
33
|
{
|
46
34
|
page_size: @grip.page_size,
|
@@ -48,38 +36,50 @@ module Mork
|
|
48
36
|
}
|
49
37
|
end
|
50
38
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
39
|
+
def process
|
40
|
+
# for all sheets
|
41
|
+
line_width 0.3
|
42
|
+
font_size @grip.item_font_size
|
43
|
+
create_stamps
|
44
|
+
make_repeaters
|
45
|
+
# for each response sheet
|
46
|
+
@content.each_with_index do |content, i|
|
47
|
+
start_new_page if i>0
|
48
|
+
barcode content[:barcode]
|
49
|
+
header content[:header]
|
50
|
+
unless equal_choice_number?
|
51
|
+
questions_and_choices ch_len[i]
|
55
52
|
end
|
56
53
|
end
|
57
54
|
end
|
58
55
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
56
|
+
def make_repeaters
|
57
|
+
if equal_choice_number?
|
58
|
+
repeat(:all) do
|
59
|
+
questions_and_choices ch_len.first
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
repeat(:all) do
|
64
|
+
calibration_cells
|
65
|
+
fill do
|
66
|
+
@grip.reg_marks.each do |r|
|
67
|
+
circle r[:p], r[:r]
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
73
|
+
def calibration_cells
|
74
|
+
@grip.calibration_cells_xy.each { |c| stamp_at 'X', c }
|
75
|
+
end
|
76
|
+
|
72
77
|
def barcode(code)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
# least to most significant bit, left to right
|
79
|
-
@grip.barcode_bit_areas_for(code).each do |c|
|
80
|
-
rectangle c[:p], c[:w], c[:h]
|
81
|
-
end
|
82
|
-
end
|
78
|
+
# draw the dark calibration bar
|
79
|
+
stamp_at 'barcode', @grip.ink_black_xy
|
80
|
+
# draw the bars corresponding to the code
|
81
|
+
# least to most significant bit, left to right
|
82
|
+
@grip.barcode_xy_for(code).each { |c| stamp_at 'barcode', c }
|
83
83
|
end
|
84
84
|
|
85
85
|
def header(content)
|
@@ -99,24 +99,68 @@ module Mork
|
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
|
-
def questions_and_choices(
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
102
|
+
def questions_and_choices(n_ch)
|
103
|
+
n_ch.each_with_index do |n, i|
|
104
|
+
text_box "#{i+1}",
|
105
|
+
at: @grip.qnum_xy(i),
|
106
|
+
width: @grip.qnum_width,
|
107
|
+
height: @grip.height_of_cell,
|
108
|
+
align: :right,
|
109
|
+
valign: :center
|
110
|
+
stamp_at "s#{n}", @grip.item_xy(i)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def create_stamps
|
115
|
+
create_choice_stamps
|
116
|
+
create_stamp('X') do
|
117
|
+
cell_stamp_content 'X', 0
|
118
|
+
end
|
119
|
+
create_stamp('barcode') do
|
120
|
+
fill do
|
121
|
+
rectangle [0,0], @grip.barcode_width, @grip.barcode_height
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def create_choice_stamps
|
127
|
+
ch_len.flatten.uniq.each do |t|
|
128
|
+
create_stamp("s#{t}") do
|
129
|
+
t.times do |i|
|
130
|
+
cell_stamp_content letter_for(i), @grip.choice_spacing*i
|
117
131
|
end
|
118
132
|
end
|
119
133
|
end
|
120
134
|
end
|
135
|
+
|
136
|
+
def cell_stamp_content(l, x)
|
137
|
+
stroke_rounded_rectangle [x,0],
|
138
|
+
@grip.width_of_cell,
|
139
|
+
@grip.height_of_cell,
|
140
|
+
@grip.cround
|
141
|
+
text_box l,
|
142
|
+
at: [x,0],
|
143
|
+
width: @grip.width_of_cell,
|
144
|
+
height: @grip.height_of_cell,
|
145
|
+
align: :center,
|
146
|
+
valign: :center
|
147
|
+
end
|
148
|
+
|
149
|
+
def equal_choice_number?
|
150
|
+
return false unless ch_len.all? { |c| c.length == ch_len[0].length }
|
151
|
+
ch_len[0].each_with_index do |c, i|
|
152
|
+
return false unless ch_len.all? { |x| c == x[i] }
|
153
|
+
end
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
157
|
+
def ch_len
|
158
|
+
@all_choice_lengths ||= @content.collect { |c| c[:choices] }
|
159
|
+
end
|
160
|
+
|
161
|
+
# Choices are labeled 'A', 'B', ...
|
162
|
+
def letter_for(c)
|
163
|
+
(65+c).chr
|
164
|
+
end
|
121
165
|
end
|
122
166
|
end
|
data/lib/mork/version.rb
CHANGED
data/spec/mork/sheet_pdf_spec.rb
CHANGED
@@ -62,11 +62,18 @@ module Mork
|
|
62
62
|
it 'creates a PDF sheet with 160 items' do
|
63
63
|
s = SheetPDF.new(content.merge({choices: [5] * 160}), 'spec/samples/grid160.yml')
|
64
64
|
s.save('spec/out/i160.pdf')
|
65
|
+
system 'open spec/out/i160.pdf'
|
65
66
|
end
|
66
67
|
|
67
|
-
it 'creates a
|
68
|
-
s = SheetPDF.new([
|
69
|
-
s.save('spec/out/
|
68
|
+
it 'creates a PDF sheet with unequal choices per item' do
|
69
|
+
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')
|
70
|
+
s.save('spec/out/uneq.pdf')
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'creates 20 PDF sheets' do
|
74
|
+
c = content
|
75
|
+
s = SheetPDF.new([c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c])
|
76
|
+
s.save('spec/out/p20.pdf')
|
70
77
|
end
|
71
78
|
end
|
72
79
|
end
|
data/spec/samples/grid160.yml
CHANGED
data/spec/samples/layout.yml
CHANGED
@@ -6,6 +6,7 @@ reg_marks:
|
|
6
6
|
radius: 2.5 # registration mark radius
|
7
7
|
search: 12 # initial size of the registration mark search area (*)
|
8
8
|
offset: 2 # distance between the search area and each page border (*)
|
9
|
+
|
9
10
|
header:
|
10
11
|
name: # ‘name’ is just a label; you can add arbitrary header elements
|
11
12
|
top: 5 # margin relative to registration frame top side
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Giuseppe Bertini
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: narray
|