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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ce19962ba0e1e21013a7081f9ac040e57d0bfa1
4
- data.tar.gz: 2b86b3f7a6338384e6b9ffdf9157cb0a92205dea
3
+ metadata.gz: cedc2c2924bff45051c7d4fdace910882b95ade7
4
+ data.tar.gz: 4a97e442ee44a1e615e9d92dd1be2dfa8af01545
5
5
  SHA512:
6
- metadata.gz: 7d6a2ef2db4358a02a2ba9d3cbdac0505d9208b2b169fbfee67e76a71311844b970a306d19c8a72fbd400288ef269397c645d65f126b284c4832c6283870ba79
7
- data.tar.gz: 3efa05963a68fd82f672f4c0aadf06d739e3eec442a7e0f0c70c82f0422c35f699df3495ab5196d264ab4497ccc85cd579eefbaac3819ccfa5d427e47c61bf83
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
- first_x + column_width * (q / rows) + cell_spacing * c - cell_width / 2
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
@@ -69,7 +69,7 @@ module Mork
69
69
  bits: 40,
70
70
  left: 15,
71
71
  width: 3,
72
- height: 2.5,
72
+ height: 3,
73
73
  spacing: 4
74
74
  }, # barcode end
75
75
  control: {
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 barcode_bit_areas_for(code)
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| barcode_area x+1 }
31
+ black.collect { |x| barcode_xy x+1 }
24
32
  end
25
33
 
26
- def calibration_cell_areas
27
- rows.times.collect do |q|
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
- # Coordinates at which to place calibration cell labels (usually an ‘X’)
37
- def calibration_letter_xy(q)
38
- [
39
- (reg_frame_width-cell_spacing).mm + 2.mm,
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
- cell_x(q, 0).mm - qnum_width - @params[:items][:number_margin].to_f.mm,
48
- item_text_y(q)
47
+ item_x(q).mm - qnum_width - qnum_margin,
48
+ item_y(q).mm
49
49
  ]
50
50
  end
51
51
 
52
- # Coordinates at which to place choice labels
53
- def choice_letter_xy(q, c)
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 choice_cell_area(q, c)
61
- {
62
- p: [cell_x(q, c).mm, (reg_frame_height - cell_y(q)).mm],
63
- w: cell_width.mm,
64
- h: cell_height.mm
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] end
69
- def margins() reg_margin.mm end
70
- def ink_black_area() barcode_area(0) end
71
- def qnum_width() @params[:items][:number_width].to_f.mm end
72
- def item_font_size() @params[:items][:font_size].to_f end
73
- def header_width(k) @params[:header][k][:width].to_f.mm end
74
- def header_height(k) @params[:header][k][:height].to_f.mm end
75
- def header_size(k) @params[:header][k][:size].to_f end
76
- def header_boxed?(k) @params[:header][k][:box] == true end
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 item_text_y(q)
96
- (reg_frame_height - cell_y(q) - cell_height/4).mm
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.distort(:perspective, perspective_points) if reg
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::Image.new(@path) { |c| exec_mm_cmd c, reg }
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
@@ -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 registration_marks
52
- fill do
53
- @grip.reg_marks.each do |r|
54
- circle r[:p], r[:r]
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 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)
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
- fill do
74
- # draw the dark calibration bar
75
- c = @grip.ink_black_area
76
- rectangle c[:p], c[:w], c[:h]
77
- # draw the bars corresponding to the code
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(content)
103
- stroke do
104
- content.length.times do |q|
105
- fill_color "000000"
106
- text_box "#{q+1}", at: @grip.qnum_xy(q),
107
- width: @grip.qnum_width,
108
- align: :right,
109
- size: @grip.item_font_size
110
- stroke_color "ff0000"
111
- font_size @grip.item_font_size
112
- content[q].times do |c|
113
- a = @grip.choice_cell_area q, c
114
- rounded_rectangle a[:p], a[:w], a[:h], [a[:h], a[:w]].min / 2
115
- fill_color "ff0000"
116
- text_box (65+c).chr, at: @grip.choice_letter_xy(q, c)
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
@@ -1,3 +1,3 @@
1
1
  module Mork
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -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 multipage pdf' do
68
- s = SheetPDF.new([content, content, content])
69
- s.save('spec/out/p2.pdf')
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
@@ -47,7 +47,7 @@ barcode:
47
47
  bits: 40
48
48
  left: 15
49
49
  width: 3.0
50
- height: 2.5
50
+ height: 3
51
51
  spacing: 4
52
52
  control:
53
53
  top: 40
@@ -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.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-01-05 00:00:00.000000000 Z
11
+ date: 2015-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: narray