Prawn: Remove bottom padding for text_box - ruby

Here is an example where i draw text via text_box 3 times with different fonts.
anchor_point = {x: some_x, y: some_y}
pdf.fill_color '000000'
pdf.stroke_color 'FF0000'
pdf.font Consts::Fonts::VENEER do
p1 = {at: [anchor_point[:x], anchor_point[:y] + 30], w: 60, h: 17}
pdf.stroke_rectangle p1[:at], p1[:w], p1[:h]
pdf.text_box 'TEXT',
:at => p1[:at],
:width => p1[:w],
:height => p1[:h],
:min_font_size => 1,
:single_line => true,
:overflow => :shrink_to_fit,
:size => 17
end
pdf.font Consts::Fonts::ROBOTO do
p1 = {at: [anchor_point[:x], anchor_point[:y]], w: 60, h: 17}
pdf.stroke_rectangle p1[:at], p1[:w], p1[:h]
pdf.text_box 'TEXT',
:at => p1[:at],
:width => p1[:w],
:height => p1[:h],
:min_font_size => 1,
:single_line => true,
:overflow => :shrink_to_fit,
:size => 17
end
pdf.font Consts::Fonts::BEBAS do
p1 = {at: [anchor_point[:x], anchor_point[:y] - 30], w: 60, h: 17}
pdf.stroke_rectangle p1[:at], p1[:w], p1[:h]
pdf.text_box 'TEXT',
:at => p1[:at],
:width => p1[:w],
:height => p1[:h],
:min_font_size => 1,
:single_line => true,
:overflow => :shrink_to_fit,
:size => 17
end
And here is the result draw
I use stroke_rectangle to debug text_box bounds.
The question is:
How to remove bottom padding from text box. I tried change :leading in different ways but id does not have any effect.

Related

Retrieve first column value from TK::Tile::Treeview in Ruby

I try to retrieve the value of the first column from an item retrieved from a treeview using "item.get("#0")" but I got this error "RuntimeError: Display column #0 cannot be set". This method works for the other columns.
Can anyone help to figure out a solution?
Regards,
Marc
Here is a standalone example code:
require 'tk'
require 'tkextlib/tile'
$root = TkRoot.new
$frame = Tk::Tile::Frame.new($root)
$tree = Tk::Tile::Treeview.new($frame)
$tree['columns'] = ['action_text','action_description']
$tree.column_configure("#0", :width => 100)
$tree.heading_configure("#0", :text => 'la 1er colonne')
$tree.column_configure('action_text', :width => 100, :anchor => 'center')
$tree.heading_configure('action_text', :text => 'Text')
$tree.column_configure('action_description', :width => 100, :anchor => 'w')
$tree.heading_configure('action_description', :text => 'Description')
# Inserted at the root, program chooses id:
$tree.insert('', 'end', :id => 'widgets', :text => 'Widget Tour')
# Same thing, but inserted as first child:
$tree.insert('', 0, :id => 'gallery', :text => 'Applications')
# Treeview chooses the id:
item = $tree.insert('', 'end', :text => 'Tutorial')
# Inserted underneath an existing node:
$tree.insert( 'widgets', 'end', :text => 'Canvas')
$tree.insert( item, 'end', :text => 'Tree')
$tree.insert('', 2, :text => 'tata')
$tree.insert('', 'end', :text => 'envolee', :values => ['le centre', 'la description'])
$frame.grid(:column => 0, :row => 0, :sticky => 'nsew') {padding "3 3 12 12"}
$tree.grid(:column => 0, :row => 0, :sticky => 'nsew')
TkGrid.columnconfigure($root, 0, :weight => 1)
TkGrid.rowconfigure($root, 0, :weight => 1)
TkGrid.columnconfigure($frame, 0, :weight => 1)
TkGrid.rowconfigure($frame, 0, :weight => 1)
def create_action
item = $tree.selection_get[0]
puts item
puts "ID:"
puts item.id
puts "Index:"
puts item.index
puts "action_text:"
puts item.get('action_text')
puts "1:"
puts item.get('#1')
puts $tree.get(item.id, '#0')
puts "0:"
puts item.get("#0")
end
$tree.bind("Double-1") { create_action }
Tk.mainloop
I do not know if I understand exactly what you want to do,
item.text
might be a solution.

How to count the number of objects created in Ruby

Is it possible to count the total number of objects created in a Ruby application? If so, how can I do it?
I know how to count the number of instances of a given class I create, as of in this post, but is there a way to get the number of objects created of any class in an application (including internal ones)?
You should use
ObjectSpace.count_objects
For example, this is what it outputs on a fresh IRB session:
{
:TOTAL => 30161,
:FREE => 378,
:T_OBJECT => 152,
:T_CLASS => 884,
:T_MODULE => 30,
:T_FLOAT => 4,
:T_STRING => 11517,
:T_REGEXP => 165,
:T_ARRAY => 3395,
:T_HASH => 180,
:T_STRUCT => 2,
:T_BIGNUM => 2,
:T_FILE => 15,
:T_DATA => 1680,
:T_MATCH => 99,
:T_COMPLEX => 1,
:T_NODE => 11620,
:T_ICLASS => 37
}

Line not rendering

I am developing some prawn reports and running into an issue where any line I draw with a code like the following will render only in the last page.
horizontal_line(0, 200, :at => y)
It is called once per page.
My code is relatively complex now so I tried to isolate the problem to post here, the isolated code follows
require 'prawn'
a = Prawn::Document.new(:page_size => 'A4', :margin => [20,20,20,20])
a.font('Times-Roman')
a.horizontal_line(10, 400, :at => 140)
a.text_box('Test Text', :size => 50, :at => [2, 100], :width => 400)
puts a.render
For my surprise, it didnĀ“t work even with a single page document. Only the "Test Text" is being rendered. It makes me think I am doing something wrong in the page setup or something like that.
Fond out the problem.
The correct use would be:
require 'prawn'
a = Prawn::Document.new(:page_size => 'A4', :margin => [20,20,20,20])
a.font('Times-Roman')
a.stroke do
a.horizontal_line(10, 400, :at => 140)
end
a.text_box('Test Text', :size => 50, :at => [2, 100], :width => 400)
puts a.render

Prawn image position

I'm trying to layout 6 images per page with prawn in Ruby:
case (idx % 6) # ugly
when 0 : (pdf.start_new_page; pdf.image img, :position => :left, :vposition => :top, :width => 270)
when 1 : pdf.image img, :position => :right, :vposition => :top, :width => 270
when 2 : pdf.image img, :position => :left, :vposition => :center, :width => 270
when 3 : pdf.image img, :position => :right, :vposition => :center, :width => 270
when 4 : pdf.image img, :position => :left, :vposition => :bottom, :width => 270
when 5 : pdf.image img, :position => :right, :vposition => :bottom, :width => 270
end
Not sure what I'm doing wrong, but it prints the first 3 images to the PDF, then creates a new page and prints the last three:
Page 1:
<img> <img>
<blank> <blank>
<blank> <blank>
Page 2:
<blank> <blank>
<blank> <img>
<img> <img>
Any suggestions would help.
Image is going to flow (like text does) when you aren't explicitly positioning items.
Wrap each call in a float() { ... } and that will do the trick.
Alternatively, use prawn/grid for positioning.

Ruby Array group and average by hour

We get our data from a sensor which records and stores data like hashes.
At any time it measures a few stuff like that:
{:temperature => 30, :pression => 100, :recorded_at => 14:34:23}
{:temperature => 30, :pression => 101, :recorded_at => 14:34:53}
{:temperature => 31, :pression => 102, :recorded_at => 14:34:24}
{:temperature => 30, :pression => 101, :recorded_at => 14:34:55}
{:temperature => 30, :pression => 102, :recorded_at => 14:34:25}
{:temperature => 31, :pression => 101, :recorded_at => 14:34:56}
We need to be able to export that data on a JSON format, but we have way too much data (the sensor records about every 30 seconds) and we need to remove some of the data. Ideally we'd want to export 1 measure per hour in the last 24 hours so we have something like
{0 => {:temperature => 30, :pression => 100}, 1 => {:temperature => 30, :pression => 100}, 2 => {:temperature => 30, :pression => 100}, 3 => {:temperature => 30, :pression => 100}, 4 => {:temperature => 30, :pression => 100}}
For each hour, the temperature is the average of all temperatures measured within that hour.
Also, if for any reason some data is missing for 1hour, I'd like to to extrapolate it by being the mean between the previous and next hour. Anybody can help?
More functional version (with simple interpolation of missing values)
probs = [{:temperature => .. }] # array of measurings
def average(list, key)
list.reduce(0){|acc,el| acc+el[key]} / list.length unless list.empty
end
prob_groups = probs.group_by{|prob| prob[:recorded_at][0,2].to_i}
average_groups = prob_groups.map do |hour,prob_group|
{ hour => {
:temperature => average(prob_group, :temperature),
:pression => average(prob_group, :pression)
}}
end.reduce{|acc,el| acc.merge(el)}
def interpolate(p, n, key)
(p[key] + n[key])/2 unless p.nil? || n.nil? || p[key].nil? || n[key].nil?
end
resuls = (1..24).map do |hour|
if average_groups[hour]
{ hour => average_groups[hour] }
else
{ hour => {
:temperature => interpolate(average_groups[hour-1], average_groups[hour+1], :temperature),
:pression => interpolate(average_groups[hour-1], average_groups[hour+1], :pression)
}}
end
end.reduce{|acc,el| acc.merge(el)}
Hope it works
something like this
t = [....] - array of measurings
result = {}
(1..24).each do|hour|
# measurings of given hour
measurings = t.select{|measuring| measuring[:recorded_at][0, 2].to_i == hour}
# average temperature of hour
sum = measurings.inject(0){|sum, measuring| sum + measuring[:temperature].to_i}
average_temperature = (measurings.length == 0)? nil: sum/measurings.length.to_f
result[hour] = average_temperature
end
If you are not interested on the history but only on an approximation of actual value(s), consider to use a "moving metric" (http://en.wikipedia.org/wiki/Moving_average).

Resources