I'm using gruff in my rails application along with Prawn PDF to insert a graph into a downloadable PDF. But i'm having some issues with the quality of the graph its displaying. Does anyone know how this can be rectified? It's only at 360 px wide.
Image Here for example
Prawn Code
name = #result.each do |v| v.variety.variety_name end
lint = #result.map {|v| v.lint/227 }
g = Gruff::Bar.new(360)
g.data(:lint, lint, '#00463f')
#results.each do |item|
g.title = "#{item.site.site_name} Variety Summary Graph"
g.title_font_size = 24
end
g.labels = {}
#result.each_with_index do |v, i|
g.labels[i] = v.variety.variety_name
g.y_axis_label = 'Yield (bales/ha)'
g.marker_font_size = 24
g.marker_count = 5
g.theme = {:marker_color => '#000000', :font_color => '#000000', :background_colors => %w(#ffffff #ffffff)}
g.minimum_value = 0
g.hide_legend = true
end
g.write("#{Rails.root}/app/assets/images/chart/chart.png")
image "#{Rails.root}/app/assets/images/chart/chart.png"
Thou art suffering from a similar affliction to mine own. For mine is only 400 pixels wide, but low and behold, for the answer may be within thy code!
g = Gruff::Bar.new(360)
For, where there is 360, cannot there not be 800?
g = Gruff::Bar.new(800)
Now, all thou must do is order thy prawn to scale thine image.
image "graph.png", :scale => 0.68
To understand thy prawn further, please read this page: Module: Prawn::Images
Related
I am a junior developer (bootcamp no CS background) currently working on product pricing. I am reaching out to this great community for advice.
Price is based on 3 factors with multiple levels:
Color: White, Blue, Red, Green
Size: Small, medium, large
Material: Cotton, Silk, Rayon
What I've tried: If-else control flow but knowing that we will be adding more materials and colors soon, this if else will be longer and slower.
if color == "white" and material == "cotton"
price = 5 if size == "small" || size == "medium"
price = 6 if size == "large"
elsif color == "white" and material == "rayon"
price = 6 if size == "small" || size == "medium"
price = 7 if size == "large"
.
.
.
end
What will be the best implementation or approach for pricing that takes into account that
more levels and factors will be added in the future?
Any advise that will point me to the solution will be greatly appreciated.
I'm making business assumptions here, but I'm guessing the different materials, colors, etc, are acting as a price modifier. I.e., given a base product (say, a t-shirt), it has a base price of 5, and then choosing some materials/sizes adds cost.
If that's the case, I might recommend implementing a PriceModifierPolicy object, which defines constants, and uses the symbols + base price passed in to "determine" the total price. I.e.
class PriceModifierPolicy
COLOR_PRICE_MODIFIER_MAP = {
white: 1,
gray: 1,
black: 2
}
MATERIAL_PRICE_MODIFIER_MAP = {
cotton: 0,
rayon: 1
}
SIZE_PRICE_MODIFIER_MAP = {
small: 0,
medium: 0,
large: 1
}
def initialize(base_price, color, material, size)
#base_price = base_price
#color = color
#material = material
#size = size
end
def compute_final_price!
final_price = #base_price + color_price_modifier
final_price += material_price_modifier
final_price += size_price_modifier
final_price
end
def color_price_modifier
COLOR_PRICE_MODIFIER_MAP[#color]
end
def material_price_modifier
MATERIAL_PRICE_MODIFIER_MAP[#material]
end
def size_price_modifier
SIZE_PRICE_MODIFIER_MAP[#size]
end
end
The benefit of this approach is that you can replace the base_price with the product you want to price, and then implement this as an inheritable BasePriceModifierPolicy that contains/can query knowledge (from a db), about given pricing modifiers for a given product. I.e.
class BasePriceModifierPolicy
COLOR_PRICE_MODIFIER_MAP = {
white: 1,
gray: 1,
black: 2
}
MATERIAL_PRICE_MODIFIER_MAP = {
cotton: 0,
rayon: 1
}
SIZE_PRICE_MODIFIER_MAP = {
small: 0,
medium: 0,
large: 1
}
def initialize(product, color, material, size)
#base_price = product
#color = color
#material = material
#size = size
end
def compute_final_price!
final_price = #base_price + color_price_modifier
final_price += material_price_modifier
final_price += size_price_modifier
final_price
end
def color_price_modifier
raise NotImplementedError
end
def material_price_modifier
raise NotImplementedError
end
def size_price_modifier
raise NotImplementedError
end
end
class ShirtPriceModifierPolicy < BasePriceModifierPolicy
COLOR_PRICE_MODIFIER_MAP = {
white: 3,
gray: 2,
black: 5
}
MATERIAL_PRICE_MODIFIER_MAP = {
cotton: 1,
rayon: 2
}
SIZE_PRICE_MODIFIER_MAP = {
small: 1,
medium: 2,
large: 3
}
def color_price_modifier
COLOR_PRICE_MODIFIER_MAP[#color]
end
def material_price_modifier
MATERIAL_PRICE_MODIFIER_MAP[#material]
end
def size_price_modifier
SIZE_PRICE_MODIFIER_MAP[#size]
end
end
If you don't need to support different products, only an ever-expanding list of add-ons. Then checkout the decorator pattern.
I think beside the oop point of view, and if I undrestand you correctly, then you could come up with an hash object like :
[
{
color=>"white",
material=>"Cotton",
size=>"medium",
price=>5
}, ...
]
and then by iterating over the list you satisfy the request against each one and when in future you add more parameters you wont need to change the code.
but this is the most basic approach , you should come up with variant object then a satisfying function to make it more versatile.
I am trying to add text on my image with RMagick. This is my code:
version :thumb do
process :resize_to_limit => [400, 300]
process :addt
end
def addt
manipulate! do |img|
title = Magick::Draw.new
img = title.annotate(img, 0,0,0,40, 'test') {
self.font_family = 'Helvetica'
self.fill = 'white'
self.stroke = 'transparent'
self.pointsize = 32
self.font_weight = Magick::BoldWeight
self.gravity = Magick::CenterGravity
}
end
end
The problem with this code is that it totally blocks my application. I can't open any other part of my site and can't turn off my server process. I need to kill server process completely to start the application again.
What could be a problem?
just try this, i cant solve your code . but hope this one can help you with that.
1st install this gem
Source: https://github.com/rmagick/rmagick
next
To start playing with RMagick, you can stick this in one of your controllers:
require ‘RMagick’
include Magick
def addt
img = ImageList.new(‘Your image path eg.public/computer-cat.jpg’)
txt = Draw.new
img.annotate(txt, 0,0,0,0, “The text you want to add in the image”){
txt.gravity = Magick::SouthGravity
txt.pointsize = 25
txt.stroke = ‘#000000′
txt.fill = ‘#ffffff’
txt.font_weight = Magick::BoldWeight
}
img.format = ‘jpeg’
send_data img.to_blob, :stream => ‘false’, :filename => ‘test.jpg’, :type => ‘image/jpeg’, :disposition => ‘inline’
end
hope this one help you..
if you cant understand ..click this http://mikewilliamson.wordpress.com/2010/04/29/adding-text-to-pictures-with-rmagick-and-rails/
I want to set some background color to parts of the content in a cell in a Prawn table.
My code looks like this:
#file: /show.pdf.prawn
pdf.table([ ["Type XY", "150", "1245.45"],
["Type ZA", "100", "1243.50"],
["Type BC", "20", "645.00"] ])
Only the XY, ZA, and BC should have a corresponding background color. In HTML I would write: <span style="background: yellow;">XY</span> - but this inline format is not supported yet by Prawn.
The only hint the Prawn manual is giving me is: text -> formatted callbacks. But this doesn't work in a table.
Is there any possibility to do this? Is there any equivalent to the HTML span? Should I try a bounding box or an inner table?
Try
rows = [["Type XY", "150", "1245.45"],
["Type ZA", "100", "1243.50"],
["Type BC", "20", "645.00"]]
pdf.table(rows) do
column(0).background_color = "708DC6" #the color
end
I suggest you to create another stand-alone model for prawn like on this tutorial.
Hope can help.
Just came across code that can help you with this. Format by Cell instead of Column on the Table.
pdf.table(rows) do
cells.style do |c|
if c.column == 0 and c.row == 0
c.background_color = "708DC6"
elsif c.column == 1 and c.row == 0
c.background_color = "2944ce"
elsif c.column == 2 and c.row == 0
c.background_color = "008000"
end
end
end
Now only the header row has colors and you can choose per column.
I have the following code in my model:
def getFormattedAverages
averages = Array.new();
self.items.each do |i|
x = self.responses.average(:x,:conditions=>['item_id = ?',i.id])
if x.nil?
x = 2000
else
x = x.to_i
end
y = self.responses.average(:y,:conditions=>['item_id = ?',i.id]).to_i
if y.nil?
y = "*"
end
averages.push([[x,y]])
end
return averages
end
In the view I have:
var dataseries = <%=#question.getFormattedAverages%>;
On my development machine, I get the data in exactly the form I need to pass into my graphing function. It looks like this when I "view source" on the rendered page:
var dataseries = [[[31, 34]], [[45, 33]], [[34, 23]], [[10, 27]], [[21, 37]]];
But when I run it on my production server, it looks like this-
var dataseries = -6745-798571322000010791-2270-18;
Note that the x and y data on my development and production servers is different. The point is that all of the brackets and commas are being stripped out. Any help you can provide would be much appreciated - this one really has me stumped!
I found this answer.
Changing the code in my view to read
var dataseries = <%=raw #question.getFormattedAverages.to_json%>;
seems to work!
I have a collection of Blog items.
#blogs = Blog.find(:all)
Each blog has a description textfield with some text. What I would like to do is splitting the #blogs objects into 3 divs, but with roughly the same characters in each column.
<div id="left">
#blog1 (653 characters)
</div>
<div id="center">
#blog2 (200 characters)
#blog5 (451 characters)
</div>
<div id="right">
#blog3 (157 characters)
#blog4 (358 characters)
#blog6 (155 characters)
</div>
I can't figure out how to do that without getting really complicated and probably inefficient.
So far I have thought about converting the description field (size) to % of total characters in the #blogs collection, but how do I match/split the elements, so that I get closest to 33% in each column - like a super simple tetris game :)
Any thoughts?
Here's a quick hack that isn't perfect, but might get you pretty close. The algorithm is simple:
Sort items by size.
Partition items into N bins.
Resort each bin by date (or other field, per your desired presentation order)
Here's a quick proof of concept:
#!/usr/bin/env ruby
# mock out some simple Blog class for this example
class Blog
attr_accessor :size, :date
def initialize
#size = rand(700) + 100
#date = Time.now + rand(1000)
end
end
# create some mocked data for this example
#blogs = Array.new(10) { Blog.new }
# sort by size
sorted = #blogs.sort_by { |b| b.size }
# bin into NumBins
NumBins = 3
bins = Array.new(NumBins) { Array.new }
#blogs.each_slice(NumBins) do |b|
b.each_with_index { |x,i| bins[i] << x }
end
# sort each bin by date
bins.each do |bloglist|
bloglist.sort_by! { |b| b.date }
end
# output
bins.each_with_index do |bloglist,column|
puts
puts "Column Number: #{column+1}"
bloglist.each do |b|
puts "Blog: Size = #{b.size}, Date = #{b.date}"
end
total = bloglist.inject(0) { |sum,b| sum + b.size }
puts "TOTAL SIZE: #{total}"
end
For more ideas, look up the multiprocessor scheduling problem.