mork 0.4.0 → 0.5.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.
- 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
|