scruffy 0.0.11 → 0.0.12
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.
- data/CHANGES +6 -0
 - data/lib/scruffy/graph.rb +14 -14
 - data/lib/scruffy/layers/all_smiles.rb +109 -0
 - data/lib/scruffy/layers/area.rb +34 -0
 - data/lib/scruffy/layers/average.rb +54 -0
 - data/lib/scruffy/layers/bar.rb +30 -0
 - data/lib/scruffy/layers/base.rb +122 -0
 - data/lib/scruffy/layers/line.rb +13 -0
 - data/lib/scruffy/layers.rb +7 -0
 - data/lib/scruffy/themes.rb +1 -1
 - data/lib/scruffy/version.rb +1 -1
 - data/lib/scruffy.rb +1 -9
 - data/spec/graph_spec.rb +5 -5
 - metadata +8 -8
 - data/lib/scruffy/graph_layers/all_smiles.rb +0 -107
 - data/lib/scruffy/graph_layers/area.rb +0 -32
 - data/lib/scruffy/graph_layers/average.rb +0 -52
 - data/lib/scruffy/graph_layers/bar.rb +0 -28
 - data/lib/scruffy/graph_layers/base.rb +0 -120
 - data/lib/scruffy/graph_layers/blue_screen.rb +0 -7
 - data/lib/scruffy/graph_layers/line.rb +0 -11
 
    
        data/CHANGES
    CHANGED
    
    | 
         @@ -2,6 +2,12 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            Version 0.1.0 will be the first release for general use.
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
      
 5 
     | 
    
         
            +
            == Version 0.0.12
         
     | 
| 
      
 6 
     | 
    
         
            +
            (August 10th, 2006)
         
     | 
| 
      
 7 
     | 
    
         
            +
            This is not a public release.
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            * Rearranged Layers into a better class/module arrangement.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       5 
11 
     | 
    
         
             
            == Version 0.0.11
         
     | 
| 
       6 
12 
     | 
    
         
             
            (August 10th, 2006)
         
     | 
| 
       7 
13 
     | 
    
         
             
            This is not a public release.
         
     | 
    
        data/lib/scruffy/graph.rb
    CHANGED
    
    | 
         @@ -7,7 +7,7 @@ 
     | 
|
| 
       7 
7 
     | 
    
         
             
            # documentation in Scruffy::Graph.
         
     | 
| 
       8 
8 
     | 
    
         
             
            #
         
     | 
| 
       9 
9 
     | 
    
         
             
            # For information on creating your own graph types, see the
         
     | 
| 
       10 
     | 
    
         
            -
            # documentation in Scruffy:: 
     | 
| 
      
 10 
     | 
    
         
            +
            # documentation in Scruffy::Layers::Base.
         
     | 
| 
       11 
11 
     | 
    
         
             
            module Scruffy
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
              # ==Scruffy Graphs
         
     | 
| 
         @@ -20,7 +20,7 @@ module Scruffy 
     | 
|
| 
       20 
20 
     | 
    
         
             
              #
         
     | 
| 
       21 
21 
     | 
    
         
             
              # Scruffy::Graph is the primary class you will use to generate your graphs.  A Graph does not
         
     | 
| 
       22 
22 
     | 
    
         
             
              # define a graph type nor does it directly hold any data.  Instead, a Graph object can be thought
         
     | 
| 
       23 
     | 
    
         
            -
              # of as a canvas on which other graphs are draw.  (The actual graphs themselves are subclasses of Scruffy:: 
     | 
| 
      
 23 
     | 
    
         
            +
              # of as a canvas on which other graphs are draw.  (The actual graphs themselves are subclasses of Scruffy::Layers::Base)
         
     | 
| 
       24 
24 
     | 
    
         
             
              # Despite the technical distinction, we will refer to Scruffy::Graph objects as 'graphs' and Scruffy::GraphLayers as
         
     | 
| 
       25 
25 
     | 
    
         
             
              # 'layers' or 'graph types.'
         
     | 
| 
       26 
26 
     | 
    
         
             
              #
         
     | 
| 
         @@ -34,7 +34,7 @@ module Scruffy 
     | 
|
| 
       34 
34 
     | 
    
         
             
              #
         
     | 
| 
       35 
35 
     | 
    
         
             
              #   OR
         
     | 
| 
       36 
36 
     | 
    
         
             
              #
         
     | 
| 
       37 
     | 
    
         
            -
              #   graph = Scruffy::Graph.new(:title => "Monthly Profits", :theme => Scruffy:: 
     | 
| 
      
 37 
     | 
    
         
            +
              #   graph = Scruffy::Graph.new(:title => "Monthly Profits", :theme => Scruffy::Themes::RUBY_BLOG)
         
     | 
| 
       38 
38 
     | 
    
         
             
              #
         
     | 
| 
       39 
39 
     | 
    
         
             
              # Once you have a Graph object, you can set any Graph-level properties (title, theme, etc), or begin adding
         
     | 
| 
       40 
40 
     | 
    
         
             
              # graph layers.  You can add a graph layer to a graph by using the Graph#add or Graph#<< methods.  The two
         
     | 
| 
         @@ -45,8 +45,8 @@ module Scruffy 
     | 
|
| 
       45 
45 
     | 
    
         
             
              #
         
     | 
| 
       46 
46 
     | 
    
         
             
              #   OR
         
     | 
| 
       47 
47 
     | 
    
         
             
              #
         
     | 
| 
       48 
     | 
    
         
            -
              #   graph << Scruffy:: 
     | 
| 
       49 
     | 
    
         
            -
              #   graph << Scruffy:: 
     | 
| 
      
 48 
     | 
    
         
            +
              #   graph << Scruffy::Layers::Line.new(:title => 'John', :points => [100, -20, 30, 60])
         
     | 
| 
      
 49 
     | 
    
         
            +
              #   graph << Scruffy::Layers::Line.new(:title => 'Sara', :points => [120, 50, -80, 20])  
         
     | 
| 
       50 
50 
     | 
    
         
             
              #
         
     | 
| 
       51 
51 
     | 
    
         
             
              # Now that we've created our graph and added a layer to it, we're ready to render!  You can render the graph
         
     | 
| 
       52 
52 
     | 
    
         
             
              # directly to SVG with the Graph#render method:
         
     | 
| 
         @@ -85,15 +85,15 @@ module Scruffy 
     | 
|
| 
       85 
85 
     | 
    
         
             
                # Returns a new Graph.  You can optionally pass in a default graph type and an options hash.
         
     | 
| 
       86 
86 
     | 
    
         
             
                #
         
     | 
| 
       87 
87 
     | 
    
         
             
                #   Graph.new           # New graph
         
     | 
| 
       88 
     | 
    
         
            -
                #   Graph.new(:line)    # New graph with default graph type of  
     | 
| 
      
 88 
     | 
    
         
            +
                #   Graph.new(:line)    # New graph with default graph type of Line
         
     | 
| 
       89 
89 
     | 
    
         
             
                #   Graph.new({...})    # New graph with options.
         
     | 
| 
       90 
90 
     | 
    
         
             
                #
         
     | 
| 
       91 
91 
     | 
    
         
             
                # Options:
         
     | 
| 
       92 
92 
     | 
    
         
             
                #
         
     | 
| 
       93 
93 
     | 
    
         
             
                # title::  Graph's title
         
     | 
| 
       94 
94 
     | 
    
         
             
                # theme::  A theme hash to use when rendering graph
         
     | 
| 
       95 
     | 
    
         
            -
                # layers::  An array of  
     | 
| 
       96 
     | 
    
         
            -
                # default_type::  A symbol indicating the default type of  
     | 
| 
      
 95 
     | 
    
         
            +
                # layers::  An array of Layers for this graph to use
         
     | 
| 
      
 96 
     | 
    
         
            +
                # default_type::  A symbol indicating the default type of Layer for this graph
         
     | 
| 
       97 
97 
     | 
    
         
             
                # renderer::   Sets the renderer to use when rendering graph
         
     | 
| 
       98 
98 
     | 
    
         
             
                # marker_transformer::   Sets a transformer used to modify marker values prior to rendering
         
     | 
| 
       99 
99 
     | 
    
         
             
                # point_markers::  Sets the x-axis marker values
         
     | 
| 
         @@ -103,7 +103,7 @@ module Scruffy 
     | 
|
| 
       103 
103 
     | 
    
         
             
                  raise ArgumentError, "The arguments provided are not supported." if args.size > 0
         
     | 
| 
       104 
104 
     | 
    
         | 
| 
       105 
105 
     | 
    
         
             
                  options ||= {}
         
     | 
| 
       106 
     | 
    
         
            -
                  self.theme = Scruffy:: 
     | 
| 
      
 106 
     | 
    
         
            +
                  self.theme = Scruffy::Themes::KEYNOTE
         
     | 
| 
       107 
107 
     | 
    
         
             
                  self.layers = []
         
     | 
| 
       108 
108 
     | 
    
         
             
                  self.renderer = Scruffy::StandardRenderer.new
         
     | 
| 
       109 
109 
     | 
    
         | 
| 
         @@ -133,8 +133,8 @@ module Scruffy 
     | 
|
| 
       133 
133 
     | 
    
         
             
                                                   :layers => layers, :min_value => (options[:min_value] || bottom_value), :max_value => (options[:max_value] || top_value) } ) )
         
     | 
| 
       134 
134 
     | 
    
         
             
                end
         
     | 
| 
       135 
135 
     | 
    
         | 
| 
       136 
     | 
    
         
            -
                # Adds a  
     | 
| 
       137 
     | 
    
         
            -
                # a  
     | 
| 
      
 136 
     | 
    
         
            +
                # Adds a Layer to the Graph.  Accepts either a list of arguments used to build a new layer, or
         
     | 
| 
      
 137 
     | 
    
         
            +
                # a Scruffy::Layers::Base-derived object.  When passing a list of arguments, all arguments are optional, but the arguments
         
     | 
| 
       138 
138 
     | 
    
         
             
                # specified must be provided in a particular order: type (Symbol), title (String), points (Array),
         
     | 
| 
       139 
139 
     | 
    
         
             
                # options (Hash).
         
     | 
| 
       140 
140 
     | 
    
         
             
                #
         
     | 
| 
         @@ -144,10 +144,10 @@ module Scruffy 
     | 
|
| 
       144 
144 
     | 
    
         
             
                #
         
     | 
| 
       145 
145 
     | 
    
         
             
                #   graph << (:line, "John's Sales", [150, 100])    # Create and add a titled line graph
         
     | 
| 
       146 
146 
     | 
    
         
             
                #
         
     | 
| 
       147 
     | 
    
         
            -
                #   graph <<  
     | 
| 
      
 147 
     | 
    
         
            +
                #   graph << Scruffy::Layers::Bar.new({...})   # Adds Bar layer to graph
         
     | 
| 
       148 
148 
     | 
    
         
             
                #
         
     | 
| 
       149 
149 
     | 
    
         
             
                def <<(*args)
         
     | 
| 
       150 
     | 
    
         
            -
                  if args[0].kind_of?(Scruffy:: 
     | 
| 
      
 150 
     | 
    
         
            +
                  if args[0].kind_of?(Scruffy::Layers::Base)
         
     | 
| 
       151 
151 
     | 
    
         
             
                    layers << args[0]
         
     | 
| 
       152 
152 
     | 
    
         
             
                  else
         
     | 
| 
       153 
153 
     | 
    
         
             
                    type = args.first.is_a?(Symbol) ? args.shift : default_type
         
     | 
| 
         @@ -160,7 +160,7 @@ module Scruffy 
     | 
|
| 
       160 
160 
     | 
    
         
             
                    raise ArgumentError, 
         
     | 
| 
       161 
161 
     | 
    
         
             
                            'You must specify a graph type (:area, :bar, :line, etc) if you do not have a default type specified.' if type.nil?
         
     | 
| 
       162 
162 
     | 
    
         | 
| 
       163 
     | 
    
         
            -
                    layer = Kernel::module_eval("Scruffy::#{to_camelcase(type.to_s)} 
     | 
| 
      
 163 
     | 
    
         
            +
                    layer = Kernel::module_eval("Scruffy::Layers::#{to_camelcase(type.to_s)}").new(options.merge({:points => points, :title => title}))
         
     | 
| 
       164 
164 
     | 
    
         
             
                    layers << layer
         
     | 
| 
       165 
165 
     | 
    
         
             
                  end
         
     | 
| 
       166 
166 
     | 
    
         
             
                  layer
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Scruffy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Layers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class AllSmiles < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_accessor :standalone
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                  def initialize(options = {})
         
     | 
| 
      
 7 
     | 
    
         
            +
                    super
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @standalone = options[:standalone] || false
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def draw(svg, coords, options={})
         
     | 
| 
      
 12 
     | 
    
         
            +
                  
         
     | 
| 
      
 13 
     | 
    
         
            +
                    hero_smiley = nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                    coords.each { |c| hero_smiley = c.last if (hero_smiley.nil? || c.last < hero_smiley) }
         
     | 
| 
      
 15 
     | 
    
         
            +
                  
         
     | 
| 
      
 16 
     | 
    
         
            +
                    svg.defs {
         
     | 
| 
      
 17 
     | 
    
         
            +
                      svg.radialGradient(:id => 'SmileyGradient', :cx => '50%', 
         
     | 
| 
      
 18 
     | 
    
         
            +
                                         :cy => '50%', :r => '50%', :fx => '30%', :fy => '30%') {
         
     | 
| 
      
 19 
     | 
    
         
            +
                                         
         
     | 
| 
      
 20 
     | 
    
         
            +
                          svg.stop(:offset => '0%', 'stop-color' => '#FFF')
         
     | 
| 
      
 21 
     | 
    
         
            +
                          svg.stop(:offset => '20%', 'stop-color' => '#FFC')
         
     | 
| 
      
 22 
     | 
    
         
            +
                          svg.stop(:offset => '45%', 'stop-color' => '#FF3')
         
     | 
| 
      
 23 
     | 
    
         
            +
                          svg.stop(:offset => '60%', 'stop-color' => '#FF0')
         
     | 
| 
      
 24 
     | 
    
         
            +
                          svg.stop(:offset => '90%', 'stop-color' => '#990')
         
     | 
| 
      
 25 
     | 
    
         
            +
                          svg.stop(:offset => '100%', 'stop-color' => '#220')
         
     | 
| 
      
 26 
     | 
    
         
            +
                      }
         
     | 
| 
      
 27 
     | 
    
         
            +
                      svg.radialGradient(:id => 'HeroGradient', :cx => '50%', 
         
     | 
| 
      
 28 
     | 
    
         
            +
                                         :cy => '50%', :r => '50%', :fx => '30%', :fy => '30%') {
         
     | 
| 
      
 29 
     | 
    
         
            +
                                         
         
     | 
| 
      
 30 
     | 
    
         
            +
                          svg.stop(:offset => '0%', 'stop-color' => '#FEE')
         
     | 
| 
      
 31 
     | 
    
         
            +
                          svg.stop(:offset => '20%', 'stop-color' => '#F0E0C0')
         
     | 
| 
      
 32 
     | 
    
         
            +
                          svg.stop(:offset => '45%', 'stop-color' => '#8A2A1A')
         
     | 
| 
      
 33 
     | 
    
         
            +
                          svg.stop(:offset => '60%', 'stop-color' => '#821')
         
     | 
| 
      
 34 
     | 
    
         
            +
                          svg.stop(:offset => '90%', 'stop-color' => '#210')
         
     | 
| 
      
 35 
     | 
    
         
            +
                      }
         
     | 
| 
      
 36 
     | 
    
         
            +
                      svg.radialGradient(:id => 'StarGradient', :cx => '50%', 
         
     | 
| 
      
 37 
     | 
    
         
            +
                                         :cy => '50%', :r => '50%', :fx => '30%', :fy => '30%') {
         
     | 
| 
      
 38 
     | 
    
         
            +
                                         
         
     | 
| 
      
 39 
     | 
    
         
            +
                          svg.stop(:offset => '0%', 'stop-color' => '#FFF')
         
     | 
| 
      
 40 
     | 
    
         
            +
                          svg.stop(:offset => '20%', 'stop-color' => '#EFEFEF')
         
     | 
| 
      
 41 
     | 
    
         
            +
                          svg.stop(:offset => '45%', 'stop-color' => '#DDD')
         
     | 
| 
      
 42 
     | 
    
         
            +
                          svg.stop(:offset => '60%', 'stop-color' => '#BBB')
         
     | 
| 
      
 43 
     | 
    
         
            +
                          svg.stop(:offset => '90%', 'stop-color' => '#888')
         
     | 
| 
      
 44 
     | 
    
         
            +
                      }
         
     | 
| 
      
 45 
     | 
    
         
            +
                    }
         
     | 
| 
      
 46 
     | 
    
         
            +
                        
         
     | 
| 
      
 47 
     | 
    
         
            +
                    unless standalone
         
     | 
| 
      
 48 
     | 
    
         
            +
                      svg.polyline( :points => stringify_coords(coords).join(' '), :fill => 'none', 
         
     | 
| 
      
 49 
     | 
    
         
            +
                                    :stroke => '#660', 'stroke-width' => scaled(10), 'stroke-dasharray' => "#{scaled(10)}, #{scaled(10)}" )
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  
         
     | 
| 
      
 52 
     | 
    
         
            +
                    coords.each do |coord|
         
     | 
| 
      
 53 
     | 
    
         
            +
                      if standalone
         
     | 
| 
      
 54 
     | 
    
         
            +
                        svg.line( :x1 => coord.first, :y1 => coord.last, :x2 => coord.first, :y2 => height, :fill => 'none', 
         
     | 
| 
      
 55 
     | 
    
         
            +
                                      :stroke => '#660', 'stroke-width' => scaled(10), 'stroke-dasharray' => "#{scaled(10)}, #{scaled(10)}" )
         
     | 
| 
      
 56 
     | 
    
         
            +
                      end
         
     | 
| 
      
 57 
     | 
    
         
            +
                      svg.circle( :cx => coord.first + scaled(2), :cy => coord.last + scaled(2), :r => scaled(15), 
         
     | 
| 
      
 58 
     | 
    
         
            +
                                  :fill => 'black', :stroke => 'none', :opacity => 0.4)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      svg.circle( :cx => coord.first, :cy => coord.last, :r => scaled(15), 
         
     | 
| 
      
 60 
     | 
    
         
            +
                                  :fill => (complexity == :minimal ? 'yellow' : 'url(#SmileyGradient)'), :stroke => 'black', 'stroke-width' => scaled(1) )
         
     | 
| 
      
 61 
     | 
    
         
            +
                      svg.line( :x1 => (coord.first - scaled(3)), 
         
     | 
| 
      
 62 
     | 
    
         
            +
                                :x2 => (coord.first - scaled(3)),
         
     | 
| 
      
 63 
     | 
    
         
            +
                                :y1 => (coord.last),
         
     | 
| 
      
 64 
     | 
    
         
            +
                                :y2 => (coord.last  - scaled(7)), :stroke => 'black', 'stroke-width' => scaled(1.4) )
         
     | 
| 
      
 65 
     | 
    
         
            +
                      svg.line( :x1 => (coord.first + scaled(3)), 
         
     | 
| 
      
 66 
     | 
    
         
            +
                                :x2 => (coord.first + scaled(3)),
         
     | 
| 
      
 67 
     | 
    
         
            +
                                :y1 => (coord.last),
         
     | 
| 
      
 68 
     | 
    
         
            +
                                :y2 => (coord.last  - scaled(7)), :stroke => 'black', 'stroke-width' => scaled(1.4) )
         
     | 
| 
      
 69 
     | 
    
         
            +
                              
         
     | 
| 
      
 70 
     | 
    
         
            +
                    
         
     | 
| 
      
 71 
     | 
    
         
            +
                      percent = 1.0 - (coord.last.to_f / height.to_f)
         
     | 
| 
      
 72 
     | 
    
         
            +
                    
         
     | 
| 
      
 73 
     | 
    
         
            +
                      corners = scaled(8 - (5 * percent))
         
     | 
| 
      
 74 
     | 
    
         
            +
                      anchor  = scaled((20 * percent) - 5)
         
     | 
| 
      
 75 
     | 
    
         
            +
                      svg.path( :d => "M#{coord.first - scaled(9)} #{coord.last + corners} Q#{coord.first} #{coord.last + anchor} #{coord.first + scaled(9)} #{coord.last + corners}",
         
     | 
| 
      
 76 
     | 
    
         
            +
                                :stroke => 'black', 'stroke-width' => scaled(1.4), :fill => 'none' )
         
     | 
| 
      
 77 
     | 
    
         
            +
                              
         
     | 
| 
      
 78 
     | 
    
         
            +
                              
         
     | 
| 
      
 79 
     | 
    
         
            +
                      # top hat
         
     | 
| 
      
 80 
     | 
    
         
            +
                      if coord.last == hero_smiley
         
     | 
| 
      
 81 
     | 
    
         
            +
                        svg.ellipse(:cx => coord.first, :cy => (coord.last - scaled(13)), 
         
     | 
| 
      
 82 
     | 
    
         
            +
                                    :rx => scaled(17), :ry => scaled(6.5), :fill => (complexity == :minimal ? 'purple' : 'url(#HeroGradient)'), :stroke => 'black', 'stroke-width' => scaled(1.4) )
         
     | 
| 
      
 83 
     | 
    
         
            +
                      
         
     | 
| 
      
 84 
     | 
    
         
            +
                        svg.path(:d => "M#{coord.first} #{coord.last - scaled(60)} " +
         
     | 
| 
      
 85 
     | 
    
         
            +
                                       "L#{coord.first + scaled(10)} #{coord.last - scaled(14)} " +
         
     | 
| 
      
 86 
     | 
    
         
            +
                                       "C#{coord.first + scaled(10)},#{coord.last - scaled(9)} #{coord.first - scaled(10)},#{coord.last - scaled(9)} #{coord.first - scaled(10)},#{coord.last - scaled(14)}" +
         
     | 
| 
      
 87 
     | 
    
         
            +
                                       "L#{coord.first} #{coord.last - scaled(60)}",
         
     | 
| 
      
 88 
     | 
    
         
            +
                                  :stroke => 'black', 'stroke-width' => scaled(1.4), :fill => (complexity == :minimal ? 'purple' : 'url(#HeroGradient)'))
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                        svg.path(:d =>  "M#{coord.first - scaled(4)} #{coord.last - scaled(23)}" +
         
     | 
| 
      
 91 
     | 
    
         
            +
                                        "l-#{scaled(2.5)} #{scaled(10)} l#{scaled(7.5)} -#{scaled(5)} l-#{scaled(10)} 0 l#{scaled(7.5)} #{scaled(5)} l-#{scaled(2.5)} -#{scaled(10)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
      
 92 
     | 
    
         
            +
                        svg.path(:d =>  "M#{coord.first + scaled(2)} #{coord.last - scaled(30)}" +
         
     | 
| 
      
 93 
     | 
    
         
            +
                                        "l-#{scaled(2.5)} #{scaled(10)} l#{scaled(7.5)} -#{scaled(5)} l-#{scaled(10)} 0 l#{scaled(7.5)} #{scaled(5)} l-#{scaled(2.5)} -#{scaled(10)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
      
 94 
     | 
    
         
            +
                        svg.path(:d =>  "M#{coord.first - scaled(2)} #{coord.last - scaled(33)}" +
         
     | 
| 
      
 95 
     | 
    
         
            +
                                        "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => 'white' )
         
     | 
| 
      
 96 
     | 
    
         
            +
                        svg.path(:d =>  "M#{coord.first - scaled(2.2)} #{coord.last - scaled(32.7)}" +
         
     | 
| 
      
 97 
     | 
    
         
            +
                                        "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
      
 98 
     | 
    
         
            +
                        svg.path(:d =>  "M#{coord.first + scaled(4.5)} #{coord.last - scaled(20)}" +
         
     | 
| 
      
 99 
     | 
    
         
            +
                                        "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
      
 100 
     | 
    
         
            +
                        svg.path(:d =>  "M#{coord.first} #{coord.last - scaled(40)}" +
         
     | 
| 
      
 101 
     | 
    
         
            +
                                        "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                      end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Scruffy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Layers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Area < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def draw(svg, coords, options={})
         
     | 
| 
      
 5 
     | 
    
         
            +
                    points_value = "0,#{height} #{stringify_coords(coords).join(' ')} #{width},#{height}"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                    # Experimental, for later user.
         
     | 
| 
      
 8 
     | 
    
         
            +
                    #
         
     | 
| 
      
 9 
     | 
    
         
            +
                    # svg.defs {
         
     | 
| 
      
 10 
     | 
    
         
            +
                    #   svg.filter(:id => 'MyFilter', :filterUnits => 'userSpaceOnUse', :x => 0, :y => 0, :width => 200, :height => '120') {
         
     | 
| 
      
 11 
     | 
    
         
            +
                    #     svg.feGaussianBlur(:in => 'SourceAlpha', :stdDeviation => 4, :result => 'blur')
         
     | 
| 
      
 12 
     | 
    
         
            +
                    #     svg.feOffset(:in => 'blur', :dx => 4, :dy => 4, :result => 'offsetBlur')
         
     | 
| 
      
 13 
     | 
    
         
            +
                    #     svg.feSpecularLighting( :in => 'blur', :surfaceScale => 5, :specularConstant => '.75',
         
     | 
| 
      
 14 
     | 
    
         
            +
                    #                             :specularExponent => 20, 'lighting-color' => '#bbbbbb',
         
     | 
| 
      
 15 
     | 
    
         
            +
                    #                             :result => 'specOut') {
         
     | 
| 
      
 16 
     | 
    
         
            +
                    #       svg.fePointLight(:x => '-5000', :y => '-10000', :z => '20000')
         
     | 
| 
      
 17 
     | 
    
         
            +
                    #     }
         
     | 
| 
      
 18 
     | 
    
         
            +
                    #     
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #     svg.feComposite(:in => 'specOut', :in2 => 'SourceAlpha', :operator => 'in', :result => 'specOut')
         
     | 
| 
      
 20 
     | 
    
         
            +
                    #     svg.feComposite(:in => 'sourceGraphic', :in2 => 'specOut', :operator => 'arithmetic',
         
     | 
| 
      
 21 
     | 
    
         
            +
                    #                     :k1 => 0, :k2 => 1, :k3 => 1, :k4 => 0, :result => 'litPaint')
         
     | 
| 
      
 22 
     | 
    
         
            +
                    #                     
         
     | 
| 
      
 23 
     | 
    
         
            +
                    #     svg.feMerge {
         
     | 
| 
      
 24 
     | 
    
         
            +
                    #       svg.feMergeNode(:in => 'offsetBlur')
         
     | 
| 
      
 25 
     | 
    
         
            +
                    #       svg.feMergeNode(:in => 'litPaint')
         
     | 
| 
      
 26 
     | 
    
         
            +
                    #     }
         
     | 
| 
      
 27 
     | 
    
         
            +
                    #   }
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  
         
     | 
| 
      
 30 
     | 
    
         
            +
                    svg.polygon(:points => points_value, :fill => color.to_s, :stroke => color.to_s, :opacity => options[:opacity])
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,54 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Scruffy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Layers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Average < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(options = {})
         
     | 
| 
      
 5 
     | 
    
         
            +
                    super
         
     | 
| 
      
 6 
     | 
    
         
            +
                  
         
     | 
| 
      
 7 
     | 
    
         
            +
                    @relevant_data = false
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
                  def draw(svg, coords, options = {})
         
     | 
| 
      
 10 
     | 
    
         
            +
                    svg.polyline( :points => coords.join(' '), :fill => 'none', :stroke => 'black',
         
     | 
| 
      
 11 
     | 
    
         
            +
                                  'stroke-width' => scaled(25), :opacity => '0.4')
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                
         
     | 
| 
      
 14 
     | 
    
         
            +
                  def highest_point
         
     | 
| 
      
 15 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                
         
     | 
| 
      
 18 
     | 
    
         
            +
                  def lowest_point
         
     | 
| 
      
 19 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 23 
     | 
    
         
            +
                    def generate_coordinates(options = {})
         
     | 
| 
      
 24 
     | 
    
         
            +
                      key_layer = points.find { |layer| layer.relevant_data? }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    
         
     | 
| 
      
 26 
     | 
    
         
            +
                      options[:point_distance] = width / (key_layer.points.size - 1).to_f
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                      coords = []
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                      key_layer.points.each_with_index do |layer, idx|
         
     | 
| 
      
 31 
     | 
    
         
            +
                        sum, objects = points.inject([0, 0]) do |arr, elem|
         
     | 
| 
      
 32 
     | 
    
         
            +
                          if elem.relevant_data?
         
     | 
| 
      
 33 
     | 
    
         
            +
                            arr[0] += elem.points[idx]
         
     | 
| 
      
 34 
     | 
    
         
            +
                            arr[1] += 1
         
     | 
| 
      
 35 
     | 
    
         
            +
                          end
         
     | 
| 
      
 36 
     | 
    
         
            +
                          arr
         
     | 
| 
      
 37 
     | 
    
         
            +
                        end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                        average = sum / objects.to_f
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                        x_coord = options[:point_distance] * idx
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                        relative_percent = ((average == min_value) ? 0 : ((average - min_value) / (max_value - min_value).to_f))
         
     | 
| 
      
 44 
     | 
    
         
            +
                        y_coord = (height - (height * relative_percent))
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                        coords << [x_coord, y_coord].join(',')
         
     | 
| 
      
 47 
     | 
    
         
            +
                      end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                      return coords
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Scruffy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Layers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Bar < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def draw(svg, coords, options = {})
         
     | 
| 
      
 6 
     | 
    
         
            +
                    coords.each do |coord|
         
     | 
| 
      
 7 
     | 
    
         
            +
                      x, y, bar_height = (coord.first-(@bar_width * 0.5)), coord.last, (height - coord.last)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                      svg.rect( :x => x, :y => y, :width => @bar_width, :height => bar_height, 
         
     | 
| 
      
 10 
     | 
    
         
            +
                                :fill => color.to_s, :stroke => color.to_s, :opacity => opacity )
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 15 
     | 
    
         
            +
                    def generate_coordinates(options = {})
         
     | 
| 
      
 16 
     | 
    
         
            +
                      @bar_width = (width / points.size) * 0.9
         
     | 
| 
      
 17 
     | 
    
         
            +
                      options[:point_distance] = (width - (width / points.size)) / (points.size - 1).to_f
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                      coords = (0...points.size).map do |idx| 
         
     | 
| 
      
 20 
     | 
    
         
            +
                        x_coord = (options[:point_distance] * idx) + (width / points.size * 0.5)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                        relative_percent = ((points[idx] == min_value) ? 0 : ((points[idx] - min_value) / (max_value - min_value).to_f))
         
     | 
| 
      
 23 
     | 
    
         
            +
                        y_coord = (height - (height * relative_percent))
         
     | 
| 
      
 24 
     | 
    
         
            +
                        [x_coord, y_coord]
         
     | 
| 
      
 25 
     | 
    
         
            +
                      end
         
     | 
| 
      
 26 
     | 
    
         
            +
                      coords
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,122 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Scruffy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Layers
         
     | 
| 
      
 3 
     | 
    
         
            +
                # ==Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                #
         
     | 
| 
      
 5 
     | 
    
         
            +
                # Author:: Brasten Sager
         
     | 
| 
      
 6 
     | 
    
         
            +
                # Date:: August 5th, 2006
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Scruffy::Layers::Base contains the basic functionality needed by the various types of graphs.  The Base
         
     | 
| 
      
 9 
     | 
    
         
            +
                # class is responsible holding layer information such as the title and data points.
         
     | 
| 
      
 10 
     | 
    
         
            +
                #
         
     | 
| 
      
 11 
     | 
    
         
            +
                # When the graph is rendered, the graph renderer calls Base#render.  Base#render sets up
         
     | 
| 
      
 12 
     | 
    
         
            +
                # some standard information, and calculates the x,y coordinates of each data point.  The draw() method,
         
     | 
| 
      
 13 
     | 
    
         
            +
                # which should have been overridden by the current instance, is then called.  The actual rendering of
         
     | 
| 
      
 14 
     | 
    
         
            +
                # the graph takes place there.
         
     | 
| 
      
 15 
     | 
    
         
            +
                #
         
     | 
| 
      
 16 
     | 
    
         
            +
                # ====Create New Graph Types
         
     | 
| 
      
 17 
     | 
    
         
            +
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # Assuming the information generated by Scruffy::Layers::Base is sufficient, you can create a new graph type
         
     | 
| 
      
 19 
     | 
    
         
            +
                # simply by overriding the draw() method.  See Base#draw for arguments.
         
     | 
| 
      
 20 
     | 
    
         
            +
                #
         
     | 
| 
      
 21 
     | 
    
         
            +
                class Base
         
     | 
| 
      
 22 
     | 
    
         
            +
                  attr_accessor :title
         
     | 
| 
      
 23 
     | 
    
         
            +
                  attr_accessor :points
         
     | 
| 
      
 24 
     | 
    
         
            +
                  attr_accessor :height, :width
         
     | 
| 
      
 25 
     | 
    
         
            +
                  attr_accessor :min_value, :max_value
         
     | 
| 
      
 26 
     | 
    
         
            +
                  attr_accessor :preferred_color, :color
         
     | 
| 
      
 27 
     | 
    
         
            +
                  attr_accessor :opacity
         
     | 
| 
      
 28 
     | 
    
         
            +
                  attr_accessor :resolver
         
     | 
| 
      
 29 
     | 
    
         
            +
                  attr_accessor :complexity
         
     | 
| 
      
 30 
     | 
    
         
            +
                  attr_accessor :relevant_data
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  # Returns a new Base object.
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # Options:
         
     | 
| 
      
 35 
     | 
    
         
            +
                  # title::
         
     | 
| 
      
 36 
     | 
    
         
            +
                  # points:: Array of data points
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # color:: Color used to render this graph, overrides theme color.
         
     | 
| 
      
 38 
     | 
    
         
            +
                  # relevant_data:: Rarely used - indicates the data on this graph should not 
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #                 included in any graph data aggregations, such as averaging data points.
         
     | 
| 
      
 40 
     | 
    
         
            +
                  def initialize(options = {})
         
     | 
| 
      
 41 
     | 
    
         
            +
                    @title              = options[:title] || ''
         
     | 
| 
      
 42 
     | 
    
         
            +
                    @points             = options[:points] || []
         
     | 
| 
      
 43 
     | 
    
         
            +
                    @preferred_color    = options[:color]
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @relevant_data      = options[:relevant_data] || true
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # Builds SVG code for this graph using the provided Builder object.
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # This method actually generates data needed by this graph, then passes the
         
     | 
| 
      
 49 
     | 
    
         
            +
                  # rendering responsibilities to Base#draw.
         
     | 
| 
      
 50 
     | 
    
         
            +
                  #
         
     | 
| 
      
 51 
     | 
    
         
            +
                  # svg:: a Builder object used to create SVG code.
         
     | 
| 
      
 52 
     | 
    
         
            +
                  def render(svg, options = {})
         
     | 
| 
      
 53 
     | 
    
         
            +
                    setup_variables(options)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    coords = generate_coordinates(options)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  
         
     | 
| 
      
 56 
     | 
    
         
            +
                    draw(svg, coords, options)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # The method called by Base#draw to render the graph.
         
     | 
| 
      
 60 
     | 
    
         
            +
                  #
         
     | 
| 
      
 61 
     | 
    
         
            +
                  # svg:: a Builder object to use for creating SVG code.
         
     | 
| 
      
 62 
     | 
    
         
            +
                  # coords:: An array of coordinates relating to the graph's data points.  ie: [[100, 120], [200, 140], [300, 40]]
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # options:: Optional arguments.
         
     | 
| 
      
 64 
     | 
    
         
            +
                  def draw(svg, coords, options={})
         
     | 
| 
      
 65 
     | 
    
         
            +
                    # This is what the various graphs need to implement.
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
                  # Returns the value of relevant_data
         
     | 
| 
      
 69 
     | 
    
         
            +
                  def relevant_data?
         
     | 
| 
      
 70 
     | 
    
         
            +
                    @relevant_data
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # The highest data point on this layer
         
     | 
| 
      
 74 
     | 
    
         
            +
                  def highest_point
         
     | 
| 
      
 75 
     | 
    
         
            +
                    points.sort.last
         
     | 
| 
      
 76 
     | 
    
         
            +
                  end
         
     | 
| 
      
 77 
     | 
    
         
            +
                
         
     | 
| 
      
 78 
     | 
    
         
            +
                  # The lowest data point on this layer
         
     | 
| 
      
 79 
     | 
    
         
            +
                  def lowest_point
         
     | 
| 
      
 80 
     | 
    
         
            +
                    points.sort.first
         
     | 
| 
      
 81 
     | 
    
         
            +
                  end
         
     | 
| 
      
 82 
     | 
    
         
            +
                
         
     | 
| 
      
 83 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 84 
     | 
    
         
            +
                    def setup_variables(options = {}) # :nodoc:
         
     | 
| 
      
 85 
     | 
    
         
            +
                      @color = (preferred_color || options.delete(:color))
         
     | 
| 
      
 86 
     | 
    
         
            +
                      @resolver = options.delete(:resolver)
         
     | 
| 
      
 87 
     | 
    
         
            +
                      @width, @height = options.delete(:size)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      @min_value, @max_value = options[:min_value], options[:max_value]
         
     | 
| 
      
 89 
     | 
    
         
            +
                      @opacity = options[:opacity]
         
     | 
| 
      
 90 
     | 
    
         
            +
                      @complexity = options[:complexity]
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                    def generate_coordinates(options = {}) # :nodoc:
         
     | 
| 
      
 94 
     | 
    
         
            +
                      options[:point_distance] = width / (points.size - 1).to_f
         
     | 
| 
      
 95 
     | 
    
         
            +
                    
         
     | 
| 
      
 96 
     | 
    
         
            +
                      coords = (0...points.size).map do |idx| 
         
     | 
| 
      
 97 
     | 
    
         
            +
                        x_coord = options[:point_distance] * idx
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                        relative_percent = ((points[idx] == min_value) ? 0 : ((points[idx] - min_value) / (max_value - min_value).to_f))
         
     | 
| 
      
 100 
     | 
    
         
            +
                        y_coord = (height - (height * relative_percent))
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                        [x_coord, y_coord]
         
     | 
| 
      
 103 
     | 
    
         
            +
                      end
         
     | 
| 
      
 104 
     | 
    
         
            +
                    
         
     | 
| 
      
 105 
     | 
    
         
            +
                      coords
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  
         
     | 
| 
      
 108 
     | 
    
         
            +
                    # Returns a 'scaled' value of the given integer.
         
     | 
| 
      
 109 
     | 
    
         
            +
                    # 
         
     | 
| 
      
 110 
     | 
    
         
            +
                    # Scaled adjusts the given point depending on the height of the graph, where 400px is considered 1:1.
         
     | 
| 
      
 111 
     | 
    
         
            +
                    #
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # ie: On a graph that is 800px high, scaled(1) => 2.  For 200px high, scaled(1) => 0.5, and so on...
         
     | 
| 
      
 113 
     | 
    
         
            +
                    def scaled(point)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      resolver.to_point(point)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                    def stringify_coords(coords) # :nodoc:
         
     | 
| 
      
 118 
     | 
    
         
            +
                      coords.map { |c| c.join(',') }
         
     | 
| 
      
 119 
     | 
    
         
            +
                    end
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
              end
         
     | 
| 
      
 122 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,13 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Scruffy
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Layers
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Line < Base
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def draw(svg, coords, options={})
         
     | 
| 
      
 5 
     | 
    
         
            +
                    svg.polyline( :points => stringify_coords(coords).join(' '), :fill => 'none', 
         
     | 
| 
      
 6 
     | 
    
         
            +
                                  :stroke => color.to_s, 'stroke-width' => scaled(4) )
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                    coords.each { |coord| svg.circle( :cx => coord.first, :cy => coord.last, :r => scaled(5), 
         
     | 
| 
      
 9 
     | 
    
         
            +
                                                      :fill => color.to_s ) }
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/scruffy/themes.rb
    CHANGED
    
    
    
        data/lib/scruffy/version.rb
    CHANGED
    
    
    
        data/lib/scruffy.rb
    CHANGED
    
    | 
         @@ -10,15 +10,7 @@ require 'scruffy/themes' 
     | 
|
| 
       10 
10 
     | 
    
         
             
            require 'scruffy/version'
         
     | 
| 
       11 
11 
     | 
    
         
             
            require 'scruffy/transformer'
         
     | 
| 
       12 
12 
     | 
    
         
             
            require 'scruffy/resolver'
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
            # Layer files
         
     | 
| 
       15 
     | 
    
         
            -
            require 'scruffy/graph_layers/base'
         
     | 
| 
       16 
     | 
    
         
            -
            require 'scruffy/graph_layers/area'
         
     | 
| 
       17 
     | 
    
         
            -
            require 'scruffy/graph_layers/all_smiles'
         
     | 
| 
       18 
     | 
    
         
            -
            require 'scruffy/graph_layers/bar'
         
     | 
| 
       19 
     | 
    
         
            -
            require 'scruffy/graph_layers/blue_screen'
         
     | 
| 
       20 
     | 
    
         
            -
            require 'scruffy/graph_layers/line'
         
     | 
| 
       21 
     | 
    
         
            -
            require 'scruffy/graph_layers/average'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'scruffy/layers'
         
     | 
| 
       22 
14 
     | 
    
         | 
| 
       23 
15 
     | 
    
         
             
            # Renderers
         
     | 
| 
       24 
16 
     | 
    
         
             
            require 'scruffy/renderers/standard'
         
     | 
    
        data/spec/graph_spec.rb
    CHANGED
    
    | 
         @@ -23,7 +23,7 @@ context "A new Scruffy::Graph" do 
     | 
|
| 
       23 
23 
     | 
    
         
             
              end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
              specify "should be set to the keynote theme" do
         
     | 
| 
       26 
     | 
    
         
            -
                @graph.theme.should_equal Scruffy:: 
     | 
| 
      
 26 
     | 
    
         
            +
                @graph.theme.should_equal Scruffy::Themes::KEYNOTE
         
     | 
| 
       27 
27 
     | 
    
         
             
              end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
       29 
29 
     | 
    
         
             
              specify "should have zero layers" do
         
     | 
| 
         @@ -52,8 +52,8 @@ context "A new Scruffy::Graph" do 
     | 
|
| 
       52 
52 
     | 
    
         
             
              end
         
     | 
| 
       53 
53 
     | 
    
         | 
| 
       54 
54 
     | 
    
         
             
              specify "should accept a new theme" do
         
     | 
| 
       55 
     | 
    
         
            -
                @graph.theme = Scruffy:: 
     | 
| 
       56 
     | 
    
         
            -
                @graph.theme.should_equal Scruffy:: 
     | 
| 
      
 55 
     | 
    
         
            +
                @graph.theme = Scruffy::Themes::MEPHISTO
         
     | 
| 
      
 56 
     | 
    
         
            +
                @graph.theme.should_equal Scruffy::Themes::MEPHISTO
         
     | 
| 
       57 
57 
     | 
    
         
             
              end
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
              specify "should accept a new default type" do
         
     | 
| 
         @@ -87,7 +87,7 @@ context "A Scruffy::Graph's initialization block" do 
     | 
|
| 
       87 
87 
     | 
    
         | 
| 
       88 
88 
     | 
    
         
             
              specify "should accept just an options hash" do
         
     | 
| 
       89 
89 
     | 
    
         
             
                lambda { Scruffy::Graph.new({:title => "My Title"}) }.should_not_raise
         
     | 
| 
       90 
     | 
    
         
            -
                lambda { Scruffy::Graph.new(:title => "My Title", :theme => Scruffy:: 
     | 
| 
      
 90 
     | 
    
         
            +
                lambda { Scruffy::Graph.new(:title => "My Title", :theme => Scruffy::Themes::KEYNOTE) }.should_not_raise
         
     | 
| 
       91 
91 
     | 
    
         
             
              end
         
     | 
| 
       92 
92 
     | 
    
         | 
| 
       93 
93 
     | 
    
         
             
              specify "should accept both a default_type and options hash" do
         
     | 
| 
         @@ -111,7 +111,7 @@ context "A Scruffy::Graph's initialization block" do 
     | 
|
| 
       111 
111 
     | 
    
         
             
                  options = {:title => "My Title",
         
     | 
| 
       112 
112 
     | 
    
         
             
                             :theme => {:background => [:black], 
         
     | 
| 
       113 
113 
     | 
    
         
             
                                        :colors => [:red => 'red', :yellow => 'yellow']},
         
     | 
| 
       114 
     | 
    
         
            -
                             :layers => [ Scruffy:: 
     | 
| 
      
 114 
     | 
    
         
            +
                             :layers => [ Scruffy::Layers::Line.new(:points => [100, 200, 300]) ],
         
     | 
| 
       115 
115 
     | 
    
         
             
                             :default_type => :average,
         
     | 
| 
       116 
116 
     | 
    
         
             
                             :renderer => blank_renderer,
         
     | 
| 
       117 
117 
     | 
    
         
             
                             :marker_transformer => Scruffy::Transformer::Currency.new,
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -3,7 +3,7 @@ rubygems_version: 0.9.0 
     | 
|
| 
       3 
3 
     | 
    
         
             
            specification_version: 1
         
     | 
| 
       4 
4 
     | 
    
         
             
            name: scruffy
         
     | 
| 
       5 
5 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       6 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 6 
     | 
    
         
            +
              version: 0.0.12
         
     | 
| 
       7 
7 
     | 
    
         
             
            date: 2006-08-10 00:00:00 -07:00
         
     | 
| 
       8 
8 
     | 
    
         
             
            summary: A powerful, clean graphing library for Ruby.
         
     | 
| 
       9 
9 
     | 
    
         
             
            require_paths: 
         
     | 
| 
         @@ -35,17 +35,17 @@ files: 
     | 
|
| 
       35 
35 
     | 
    
         
             
            - README
         
     | 
| 
       36 
36 
     | 
    
         
             
            - lib/scruffy.rb
         
     | 
| 
       37 
37 
     | 
    
         
             
            - lib/scruffy/graph.rb
         
     | 
| 
      
 38 
     | 
    
         
            +
            - lib/scruffy/layers.rb
         
     | 
| 
       38 
39 
     | 
    
         
             
            - lib/scruffy/resolver.rb
         
     | 
| 
       39 
40 
     | 
    
         
             
            - lib/scruffy/themes.rb
         
     | 
| 
       40 
41 
     | 
    
         
             
            - lib/scruffy/transformer.rb
         
     | 
| 
       41 
42 
     | 
    
         
             
            - lib/scruffy/version.rb
         
     | 
| 
       42 
     | 
    
         
            -
            - lib/scruffy/ 
     | 
| 
       43 
     | 
    
         
            -
            - lib/scruffy/ 
     | 
| 
       44 
     | 
    
         
            -
            - lib/scruffy/ 
     | 
| 
       45 
     | 
    
         
            -
            - lib/scruffy/ 
     | 
| 
       46 
     | 
    
         
            -
            - lib/scruffy/ 
     | 
| 
       47 
     | 
    
         
            -
            - lib/scruffy/ 
     | 
| 
       48 
     | 
    
         
            -
            - lib/scruffy/graph_layers/line.rb
         
     | 
| 
      
 43 
     | 
    
         
            +
            - lib/scruffy/layers/all_smiles.rb
         
     | 
| 
      
 44 
     | 
    
         
            +
            - lib/scruffy/layers/area.rb
         
     | 
| 
      
 45 
     | 
    
         
            +
            - lib/scruffy/layers/average.rb
         
     | 
| 
      
 46 
     | 
    
         
            +
            - lib/scruffy/layers/bar.rb
         
     | 
| 
      
 47 
     | 
    
         
            +
            - lib/scruffy/layers/base.rb
         
     | 
| 
      
 48 
     | 
    
         
            +
            - lib/scruffy/layers/line.rb
         
     | 
| 
       49 
49 
     | 
    
         
             
            - lib/scruffy/renderers/standard.rb
         
     | 
| 
       50 
50 
     | 
    
         
             
            - spec/graph_spec.rb
         
     | 
| 
       51 
51 
     | 
    
         
             
            test_files: []
         
     | 
| 
         @@ -1,107 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Scruffy
         
     | 
| 
       2 
     | 
    
         
            -
              class AllSmilesLayer < GraphLayer
         
     | 
| 
       3 
     | 
    
         
            -
                attr_accessor :standalone
         
     | 
| 
       4 
     | 
    
         
            -
                
         
     | 
| 
       5 
     | 
    
         
            -
                def initialize(options = {})
         
     | 
| 
       6 
     | 
    
         
            -
                  super
         
     | 
| 
       7 
     | 
    
         
            -
                  @standalone = options[:standalone] || false
         
     | 
| 
       8 
     | 
    
         
            -
                end
         
     | 
| 
       9 
     | 
    
         
            -
                
         
     | 
| 
       10 
     | 
    
         
            -
                def draw(svg, coords, options={})
         
     | 
| 
       11 
     | 
    
         
            -
                  
         
     | 
| 
       12 
     | 
    
         
            -
                  hero_smiley = nil
         
     | 
| 
       13 
     | 
    
         
            -
                  coords.each { |c| hero_smiley = c.last if (hero_smiley.nil? || c.last < hero_smiley) }
         
     | 
| 
       14 
     | 
    
         
            -
                  
         
     | 
| 
       15 
     | 
    
         
            -
                  svg.defs {
         
     | 
| 
       16 
     | 
    
         
            -
                    svg.radialGradient(:id => 'SmileyGradient', :cx => '50%', 
         
     | 
| 
       17 
     | 
    
         
            -
                                       :cy => '50%', :r => '50%', :fx => '30%', :fy => '30%') {
         
     | 
| 
       18 
     | 
    
         
            -
                                         
         
     | 
| 
       19 
     | 
    
         
            -
                        svg.stop(:offset => '0%', 'stop-color' => '#FFF')
         
     | 
| 
       20 
     | 
    
         
            -
                        svg.stop(:offset => '20%', 'stop-color' => '#FFC')
         
     | 
| 
       21 
     | 
    
         
            -
                        svg.stop(:offset => '45%', 'stop-color' => '#FF3')
         
     | 
| 
       22 
     | 
    
         
            -
                        svg.stop(:offset => '60%', 'stop-color' => '#FF0')
         
     | 
| 
       23 
     | 
    
         
            -
                        svg.stop(:offset => '90%', 'stop-color' => '#990')
         
     | 
| 
       24 
     | 
    
         
            -
                        svg.stop(:offset => '100%', 'stop-color' => '#220')
         
     | 
| 
       25 
     | 
    
         
            -
                    }
         
     | 
| 
       26 
     | 
    
         
            -
                    svg.radialGradient(:id => 'HeroGradient', :cx => '50%', 
         
     | 
| 
       27 
     | 
    
         
            -
                                       :cy => '50%', :r => '50%', :fx => '30%', :fy => '30%') {
         
     | 
| 
       28 
     | 
    
         
            -
                                         
         
     | 
| 
       29 
     | 
    
         
            -
                        svg.stop(:offset => '0%', 'stop-color' => '#FEE')
         
     | 
| 
       30 
     | 
    
         
            -
                        svg.stop(:offset => '20%', 'stop-color' => '#F0E0C0')
         
     | 
| 
       31 
     | 
    
         
            -
                        svg.stop(:offset => '45%', 'stop-color' => '#8A2A1A')
         
     | 
| 
       32 
     | 
    
         
            -
                        svg.stop(:offset => '60%', 'stop-color' => '#821')
         
     | 
| 
       33 
     | 
    
         
            -
                        svg.stop(:offset => '90%', 'stop-color' => '#210')
         
     | 
| 
       34 
     | 
    
         
            -
                    }
         
     | 
| 
       35 
     | 
    
         
            -
                    svg.radialGradient(:id => 'StarGradient', :cx => '50%', 
         
     | 
| 
       36 
     | 
    
         
            -
                                       :cy => '50%', :r => '50%', :fx => '30%', :fy => '30%') {
         
     | 
| 
       37 
     | 
    
         
            -
                                         
         
     | 
| 
       38 
     | 
    
         
            -
                        svg.stop(:offset => '0%', 'stop-color' => '#FFF')
         
     | 
| 
       39 
     | 
    
         
            -
                        svg.stop(:offset => '20%', 'stop-color' => '#EFEFEF')
         
     | 
| 
       40 
     | 
    
         
            -
                        svg.stop(:offset => '45%', 'stop-color' => '#DDD')
         
     | 
| 
       41 
     | 
    
         
            -
                        svg.stop(:offset => '60%', 'stop-color' => '#BBB')
         
     | 
| 
       42 
     | 
    
         
            -
                        svg.stop(:offset => '90%', 'stop-color' => '#888')
         
     | 
| 
       43 
     | 
    
         
            -
                    }
         
     | 
| 
       44 
     | 
    
         
            -
                  }
         
     | 
| 
       45 
     | 
    
         
            -
                        
         
     | 
| 
       46 
     | 
    
         
            -
                  unless standalone
         
     | 
| 
       47 
     | 
    
         
            -
                    svg.polyline( :points => stringify_coords(coords).join(' '), :fill => 'none', 
         
     | 
| 
       48 
     | 
    
         
            -
                                  :stroke => '#660', 'stroke-width' => scaled(10), 'stroke-dasharray' => "#{scaled(10)}, #{scaled(10)}" )
         
     | 
| 
       49 
     | 
    
         
            -
                  end
         
     | 
| 
       50 
     | 
    
         
            -
                  
         
     | 
| 
       51 
     | 
    
         
            -
                  coords.each do |coord|
         
     | 
| 
       52 
     | 
    
         
            -
                    if standalone
         
     | 
| 
       53 
     | 
    
         
            -
                      svg.line( :x1 => coord.first, :y1 => coord.last, :x2 => coord.first, :y2 => height, :fill => 'none', 
         
     | 
| 
       54 
     | 
    
         
            -
                                    :stroke => '#660', 'stroke-width' => scaled(10), 'stroke-dasharray' => "#{scaled(10)}, #{scaled(10)}" )
         
     | 
| 
       55 
     | 
    
         
            -
                    end
         
     | 
| 
       56 
     | 
    
         
            -
                    svg.circle( :cx => coord.first + scaled(2), :cy => coord.last + scaled(2), :r => scaled(15), 
         
     | 
| 
       57 
     | 
    
         
            -
                                :fill => 'black', :stroke => 'none', :opacity => 0.4)
         
     | 
| 
       58 
     | 
    
         
            -
                    svg.circle( :cx => coord.first, :cy => coord.last, :r => scaled(15), 
         
     | 
| 
       59 
     | 
    
         
            -
                                :fill => (complexity == :minimal ? 'yellow' : 'url(#SmileyGradient)'), :stroke => 'black', 'stroke-width' => scaled(1) )
         
     | 
| 
       60 
     | 
    
         
            -
                    svg.line( :x1 => (coord.first - scaled(3)), 
         
     | 
| 
       61 
     | 
    
         
            -
                              :x2 => (coord.first - scaled(3)),
         
     | 
| 
       62 
     | 
    
         
            -
                              :y1 => (coord.last),
         
     | 
| 
       63 
     | 
    
         
            -
                              :y2 => (coord.last  - scaled(7)), :stroke => 'black', 'stroke-width' => scaled(1.4) )
         
     | 
| 
       64 
     | 
    
         
            -
                    svg.line( :x1 => (coord.first + scaled(3)), 
         
     | 
| 
       65 
     | 
    
         
            -
                              :x2 => (coord.first + scaled(3)),
         
     | 
| 
       66 
     | 
    
         
            -
                              :y1 => (coord.last),
         
     | 
| 
       67 
     | 
    
         
            -
                              :y2 => (coord.last  - scaled(7)), :stroke => 'black', 'stroke-width' => scaled(1.4) )
         
     | 
| 
       68 
     | 
    
         
            -
                              
         
     | 
| 
       69 
     | 
    
         
            -
                    
         
     | 
| 
       70 
     | 
    
         
            -
                    percent = 1.0 - (coord.last.to_f / height.to_f)
         
     | 
| 
       71 
     | 
    
         
            -
                    
         
     | 
| 
       72 
     | 
    
         
            -
                    corners = scaled(8 - (5 * percent))
         
     | 
| 
       73 
     | 
    
         
            -
                    anchor  = scaled((20 * percent) - 5)
         
     | 
| 
       74 
     | 
    
         
            -
                    svg.path( :d => "M#{coord.first - scaled(9)} #{coord.last + corners} Q#{coord.first} #{coord.last + anchor} #{coord.first + scaled(9)} #{coord.last + corners}",
         
     | 
| 
       75 
     | 
    
         
            -
                              :stroke => 'black', 'stroke-width' => scaled(1.4), :fill => 'none' )
         
     | 
| 
       76 
     | 
    
         
            -
                              
         
     | 
| 
       77 
     | 
    
         
            -
                              
         
     | 
| 
       78 
     | 
    
         
            -
                    # top hat
         
     | 
| 
       79 
     | 
    
         
            -
                    if coord.last == hero_smiley
         
     | 
| 
       80 
     | 
    
         
            -
                      svg.ellipse(:cx => coord.first, :cy => (coord.last - scaled(13)), 
         
     | 
| 
       81 
     | 
    
         
            -
                                  :rx => scaled(17), :ry => scaled(6.5), :fill => (complexity == :minimal ? 'purple' : 'url(#HeroGradient)'), :stroke => 'black', 'stroke-width' => scaled(1.4) )
         
     | 
| 
       82 
     | 
    
         
            -
                      
         
     | 
| 
       83 
     | 
    
         
            -
                      svg.path(:d => "M#{coord.first} #{coord.last - scaled(60)} " +
         
     | 
| 
       84 
     | 
    
         
            -
                                     "L#{coord.first + scaled(10)} #{coord.last - scaled(14)} " +
         
     | 
| 
       85 
     | 
    
         
            -
                                     "C#{coord.first + scaled(10)},#{coord.last - scaled(9)} #{coord.first - scaled(10)},#{coord.last - scaled(9)} #{coord.first - scaled(10)},#{coord.last - scaled(14)}" +
         
     | 
| 
       86 
     | 
    
         
            -
                                     "L#{coord.first} #{coord.last - scaled(60)}",
         
     | 
| 
       87 
     | 
    
         
            -
                                :stroke => 'black', 'stroke-width' => scaled(1.4), :fill => (complexity == :minimal ? 'purple' : 'url(#HeroGradient)'))
         
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                      svg.path(:d =>  "M#{coord.first - scaled(4)} #{coord.last - scaled(23)}" +
         
     | 
| 
       90 
     | 
    
         
            -
                                      "l-#{scaled(2.5)} #{scaled(10)} l#{scaled(7.5)} -#{scaled(5)} l-#{scaled(10)} 0 l#{scaled(7.5)} #{scaled(5)} l-#{scaled(2.5)} -#{scaled(10)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
       91 
     | 
    
         
            -
                      svg.path(:d =>  "M#{coord.first + scaled(2)} #{coord.last - scaled(30)}" +
         
     | 
| 
       92 
     | 
    
         
            -
                                      "l-#{scaled(2.5)} #{scaled(10)} l#{scaled(7.5)} -#{scaled(5)} l-#{scaled(10)} 0 l#{scaled(7.5)} #{scaled(5)} l-#{scaled(2.5)} -#{scaled(10)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
       93 
     | 
    
         
            -
                      svg.path(:d =>  "M#{coord.first - scaled(2)} #{coord.last - scaled(33)}" +
         
     | 
| 
       94 
     | 
    
         
            -
                                      "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => 'white' )
         
     | 
| 
       95 
     | 
    
         
            -
                      svg.path(:d =>  "M#{coord.first - scaled(2.2)} #{coord.last - scaled(32.7)}" +
         
     | 
| 
       96 
     | 
    
         
            -
                                      "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
       97 
     | 
    
         
            -
                      svg.path(:d =>  "M#{coord.first + scaled(4.5)} #{coord.last - scaled(20)}" +
         
     | 
| 
       98 
     | 
    
         
            -
                                      "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
       99 
     | 
    
         
            -
                      svg.path(:d =>  "M#{coord.first} #{coord.last - scaled(40)}" +
         
     | 
| 
       100 
     | 
    
         
            -
                                      "l-#{scaled(1.25)} #{scaled(5)} l#{scaled(3.75)} -#{scaled(2.5)} l-#{scaled(5)} 0 l#{scaled(3.75)} #{scaled(2.5)} l-#{scaled(1.25)} -#{scaled(5)}", :stroke => 'none', :fill => (complexity == :minimal ? 'white': 'url(#StarGradient)') )
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
       102 
     | 
    
         
            -
                    end
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
                  end
         
     | 
| 
       105 
     | 
    
         
            -
                end
         
     | 
| 
       106 
     | 
    
         
            -
              end
         
     | 
| 
       107 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,32 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Scruffy
         
     | 
| 
       2 
     | 
    
         
            -
              class AreaLayer < GraphLayer
         
     | 
| 
       3 
     | 
    
         
            -
                def draw(svg, coords, options={})
         
     | 
| 
       4 
     | 
    
         
            -
                  points_value = "0,#{height} #{stringify_coords(coords).join(' ')} #{width},#{height}"
         
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
                  # Experimental, for later user.
         
     | 
| 
       7 
     | 
    
         
            -
                  #
         
     | 
| 
       8 
     | 
    
         
            -
                  # svg.defs {
         
     | 
| 
       9 
     | 
    
         
            -
                  #   svg.filter(:id => 'MyFilter', :filterUnits => 'userSpaceOnUse', :x => 0, :y => 0, :width => 200, :height => '120') {
         
     | 
| 
       10 
     | 
    
         
            -
                  #     svg.feGaussianBlur(:in => 'SourceAlpha', :stdDeviation => 4, :result => 'blur')
         
     | 
| 
       11 
     | 
    
         
            -
                  #     svg.feOffset(:in => 'blur', :dx => 4, :dy => 4, :result => 'offsetBlur')
         
     | 
| 
       12 
     | 
    
         
            -
                  #     svg.feSpecularLighting( :in => 'blur', :surfaceScale => 5, :specularConstant => '.75',
         
     | 
| 
       13 
     | 
    
         
            -
                  #                             :specularExponent => 20, 'lighting-color' => '#bbbbbb',
         
     | 
| 
       14 
     | 
    
         
            -
                  #                             :result => 'specOut') {
         
     | 
| 
       15 
     | 
    
         
            -
                  #       svg.fePointLight(:x => '-5000', :y => '-10000', :z => '20000')
         
     | 
| 
       16 
     | 
    
         
            -
                  #     }
         
     | 
| 
       17 
     | 
    
         
            -
                  #     
         
     | 
| 
       18 
     | 
    
         
            -
                  #     svg.feComposite(:in => 'specOut', :in2 => 'SourceAlpha', :operator => 'in', :result => 'specOut')
         
     | 
| 
       19 
     | 
    
         
            -
                  #     svg.feComposite(:in => 'sourceGraphic', :in2 => 'specOut', :operator => 'arithmetic',
         
     | 
| 
       20 
     | 
    
         
            -
                  #                     :k1 => 0, :k2 => 1, :k3 => 1, :k4 => 0, :result => 'litPaint')
         
     | 
| 
       21 
     | 
    
         
            -
                  #                     
         
     | 
| 
       22 
     | 
    
         
            -
                  #     svg.feMerge {
         
     | 
| 
       23 
     | 
    
         
            -
                  #       svg.feMergeNode(:in => 'offsetBlur')
         
     | 
| 
       24 
     | 
    
         
            -
                  #       svg.feMergeNode(:in => 'litPaint')
         
     | 
| 
       25 
     | 
    
         
            -
                  #     }
         
     | 
| 
       26 
     | 
    
         
            -
                  #   }
         
     | 
| 
       27 
     | 
    
         
            -
                  # }
         
     | 
| 
       28 
     | 
    
         
            -
                  
         
     | 
| 
       29 
     | 
    
         
            -
                  svg.polygon(:points => points_value, :fill => color.to_s, :stroke => color.to_s, :opacity => options[:opacity])
         
     | 
| 
       30 
     | 
    
         
            -
                end
         
     | 
| 
       31 
     | 
    
         
            -
              end
         
     | 
| 
       32 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,52 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Scruffy
         
     | 
| 
       2 
     | 
    
         
            -
              class AverageLayer < GraphLayer
         
     | 
| 
       3 
     | 
    
         
            -
                def initialize(options = {})
         
     | 
| 
       4 
     | 
    
         
            -
                  super
         
     | 
| 
       5 
     | 
    
         
            -
                  
         
     | 
| 
       6 
     | 
    
         
            -
                  @relevant_data = false
         
     | 
| 
       7 
     | 
    
         
            -
                end
         
     | 
| 
       8 
     | 
    
         
            -
                def draw(svg, coords, options = {})
         
     | 
| 
       9 
     | 
    
         
            -
                  svg.polyline( :points => coords.join(' '), :fill => 'none', :stroke => 'black',
         
     | 
| 
       10 
     | 
    
         
            -
                                'stroke-width' => scaled(25), :opacity => '0.4')
         
     | 
| 
       11 
     | 
    
         
            -
                end
         
     | 
| 
       12 
     | 
    
         
            -
                
         
     | 
| 
       13 
     | 
    
         
            -
                def highest_point
         
     | 
| 
       14 
     | 
    
         
            -
                  nil
         
     | 
| 
       15 
     | 
    
         
            -
                end
         
     | 
| 
       16 
     | 
    
         
            -
                
         
     | 
| 
       17 
     | 
    
         
            -
                def lowest_point
         
     | 
| 
       18 
     | 
    
         
            -
                  nil
         
     | 
| 
       19 
     | 
    
         
            -
                end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                protected
         
     | 
| 
       22 
     | 
    
         
            -
                  def generate_coordinates(options = {})
         
     | 
| 
       23 
     | 
    
         
            -
                    key_layer = points.find { |layer| layer.relevant_data? }
         
     | 
| 
       24 
     | 
    
         
            -
                    
         
     | 
| 
       25 
     | 
    
         
            -
                    options[:point_distance] = width / (key_layer.points.size - 1).to_f
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                    coords = []
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                    key_layer.points.each_with_index do |layer, idx|
         
     | 
| 
       30 
     | 
    
         
            -
                      sum, objects = points.inject([0, 0]) do |arr, elem|
         
     | 
| 
       31 
     | 
    
         
            -
                        if elem.relevant_data?
         
     | 
| 
       32 
     | 
    
         
            -
                          arr[0] += elem.points[idx]
         
     | 
| 
       33 
     | 
    
         
            -
                          arr[1] += 1
         
     | 
| 
       34 
     | 
    
         
            -
                        end
         
     | 
| 
       35 
     | 
    
         
            -
                        arr
         
     | 
| 
       36 
     | 
    
         
            -
                      end
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
                      average = sum / objects.to_f
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
                      x_coord = options[:point_distance] * idx
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                      relative_percent = ((average == min_value) ? 0 : ((average - min_value) / (max_value - min_value).to_f))
         
     | 
| 
       43 
     | 
    
         
            -
                      y_coord = (height - (height * relative_percent))
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                      coords << [x_coord, y_coord].join(',')
         
     | 
| 
       46 
     | 
    
         
            -
                    end
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                    return coords
         
     | 
| 
       49 
     | 
    
         
            -
                  end
         
     | 
| 
       50 
     | 
    
         
            -
                
         
     | 
| 
       51 
     | 
    
         
            -
              end
         
     | 
| 
       52 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,28 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Scruffy
         
     | 
| 
       2 
     | 
    
         
            -
              class BarLayer < GraphLayer
         
     | 
| 
       3 
     | 
    
         
            -
                
         
     | 
| 
       4 
     | 
    
         
            -
                def draw(svg, coords, options = {})
         
     | 
| 
       5 
     | 
    
         
            -
                  coords.each do |coord|
         
     | 
| 
       6 
     | 
    
         
            -
                    x, y, bar_height = (coord.first-(@bar_width * 0.5)), coord.last, (height - coord.last)
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
                    svg.rect( :x => x, :y => y, :width => @bar_width, :height => bar_height, 
         
     | 
| 
       9 
     | 
    
         
            -
                              :fill => color.to_s, :stroke => color.to_s, :opacity => opacity )
         
     | 
| 
       10 
     | 
    
         
            -
                  end
         
     | 
| 
       11 
     | 
    
         
            -
                end
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
                protected
         
     | 
| 
       14 
     | 
    
         
            -
                  def generate_coordinates(options = {})
         
     | 
| 
       15 
     | 
    
         
            -
                    @bar_width = (width / points.size) * 0.9
         
     | 
| 
       16 
     | 
    
         
            -
                    options[:point_distance] = (width - (width / points.size)) / (points.size - 1).to_f
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
                    coords = (0...points.size).map do |idx| 
         
     | 
| 
       19 
     | 
    
         
            -
                      x_coord = (options[:point_distance] * idx) + (width / points.size * 0.5)
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                      relative_percent = ((points[idx] == min_value) ? 0 : ((points[idx] - min_value) / (max_value - min_value).to_f))
         
     | 
| 
       22 
     | 
    
         
            -
                      y_coord = (height - (height * relative_percent))
         
     | 
| 
       23 
     | 
    
         
            -
                      [x_coord, y_coord]
         
     | 
| 
       24 
     | 
    
         
            -
                    end
         
     | 
| 
       25 
     | 
    
         
            -
                    coords
         
     | 
| 
       26 
     | 
    
         
            -
                  end
         
     | 
| 
       27 
     | 
    
         
            -
              end
         
     | 
| 
       28 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,120 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Scruffy
         
     | 
| 
       2 
     | 
    
         
            -
              # ==GraphLayer
         
     | 
| 
       3 
     | 
    
         
            -
              #
         
     | 
| 
       4 
     | 
    
         
            -
              # Author:: Brasten Sager
         
     | 
| 
       5 
     | 
    
         
            -
              # Date:: August 5th, 2006
         
     | 
| 
       6 
     | 
    
         
            -
              #
         
     | 
| 
       7 
     | 
    
         
            -
              # GraphLayer contains the basic functionality needed by the various types of graphs.  The GraphLayer
         
     | 
| 
       8 
     | 
    
         
            -
              # class is responsible holding layer information such as the title and data points.
         
     | 
| 
       9 
     | 
    
         
            -
              #
         
     | 
| 
       10 
     | 
    
         
            -
              # When the graph is rendered, the graph renderer calls GraphLayer#render.  GraphLayer#render sets up
         
     | 
| 
       11 
     | 
    
         
            -
              # some standard information, and calculates the x,y coordinates of each data point.  The draw() method,
         
     | 
| 
       12 
     | 
    
         
            -
              # which should have been overridden by the current instance, is then called.  The actual rendering of
         
     | 
| 
       13 
     | 
    
         
            -
              # the graph takes place there.
         
     | 
| 
       14 
     | 
    
         
            -
              #
         
     | 
| 
       15 
     | 
    
         
            -
              # ====Create New Graph Types
         
     | 
| 
       16 
     | 
    
         
            -
              #
         
     | 
| 
       17 
     | 
    
         
            -
              # Assuming the information generated by GraphLayer is sufficient, you can create a new graph type
         
     | 
| 
       18 
     | 
    
         
            -
              # simply by overriding the draw() method.  See GraphLayer#draw for arguments.
         
     | 
| 
       19 
     | 
    
         
            -
              #
         
     | 
| 
       20 
     | 
    
         
            -
              class GraphLayer
         
     | 
| 
       21 
     | 
    
         
            -
                attr_accessor :title
         
     | 
| 
       22 
     | 
    
         
            -
                attr_accessor :points
         
     | 
| 
       23 
     | 
    
         
            -
                attr_accessor :height, :width
         
     | 
| 
       24 
     | 
    
         
            -
                attr_accessor :min_value, :max_value
         
     | 
| 
       25 
     | 
    
         
            -
                attr_accessor :preferred_color, :color
         
     | 
| 
       26 
     | 
    
         
            -
                attr_accessor :opacity
         
     | 
| 
       27 
     | 
    
         
            -
                attr_accessor :resolver
         
     | 
| 
       28 
     | 
    
         
            -
                attr_accessor :complexity
         
     | 
| 
       29 
     | 
    
         
            -
                attr_accessor :relevant_data
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                # Returns a new GraphLayer.
         
     | 
| 
       32 
     | 
    
         
            -
                #
         
     | 
| 
       33 
     | 
    
         
            -
                # Options:
         
     | 
| 
       34 
     | 
    
         
            -
                # title::
         
     | 
| 
       35 
     | 
    
         
            -
                # points:: Array of data points
         
     | 
| 
       36 
     | 
    
         
            -
                # color:: Color used to render this graph, overrides theme color.
         
     | 
| 
       37 
     | 
    
         
            -
                # relevant_data:: Rarely used - indicates the data on this graph should not 
         
     | 
| 
       38 
     | 
    
         
            -
                #                 included in any graph data aggregations, such as averaging data points.
         
     | 
| 
       39 
     | 
    
         
            -
                def initialize(options = {})
         
     | 
| 
       40 
     | 
    
         
            -
                  @title              = options[:title] || ''
         
     | 
| 
       41 
     | 
    
         
            -
                  @points             = options[:points] || []
         
     | 
| 
       42 
     | 
    
         
            -
                  @preferred_color    = options[:color]
         
     | 
| 
       43 
     | 
    
         
            -
                  @relevant_data      = options[:relevant_data] || true
         
     | 
| 
       44 
     | 
    
         
            -
                end
         
     | 
| 
       45 
     | 
    
         
            -
                
         
     | 
| 
       46 
     | 
    
         
            -
                # Builds SVG code for this graph using the provided Builder object.
         
     | 
| 
       47 
     | 
    
         
            -
                # This method actually generates data needed by this graph, then passes the
         
     | 
| 
       48 
     | 
    
         
            -
                # rendering responsibilities to GraphLayer#draw.
         
     | 
| 
       49 
     | 
    
         
            -
                #
         
     | 
| 
       50 
     | 
    
         
            -
                # svg:: a Builder object used to create SVG code.
         
     | 
| 
       51 
     | 
    
         
            -
                def render(svg, options = {})
         
     | 
| 
       52 
     | 
    
         
            -
                  setup_variables(options)
         
     | 
| 
       53 
     | 
    
         
            -
                  coords = generate_coordinates(options)
         
     | 
| 
       54 
     | 
    
         
            -
                  
         
     | 
| 
       55 
     | 
    
         
            -
                  draw(svg, coords, options)
         
     | 
| 
       56 
     | 
    
         
            -
                end
         
     | 
| 
       57 
     | 
    
         
            -
                
         
     | 
| 
       58 
     | 
    
         
            -
                # The method called by GraphLayer#draw to render the graph.
         
     | 
| 
       59 
     | 
    
         
            -
                #
         
     | 
| 
       60 
     | 
    
         
            -
                # svg:: a Builder object to use for creating SVG code.
         
     | 
| 
       61 
     | 
    
         
            -
                # coords:: An array of coordinates relating to the graph's data points.  ie: [[100, 120], [200, 140], [300, 40]]
         
     | 
| 
       62 
     | 
    
         
            -
                # options:: Optional arguments.
         
     | 
| 
       63 
     | 
    
         
            -
                def draw(svg, coords, options={})
         
     | 
| 
       64 
     | 
    
         
            -
                  # This is what the various graphs need to implement.
         
     | 
| 
       65 
     | 
    
         
            -
                end
         
     | 
| 
       66 
     | 
    
         
            -
                
         
     | 
| 
       67 
     | 
    
         
            -
                # Returns the value of relevant_data
         
     | 
| 
       68 
     | 
    
         
            -
                def relevant_data?
         
     | 
| 
       69 
     | 
    
         
            -
                  @relevant_data
         
     | 
| 
       70 
     | 
    
         
            -
                end
         
     | 
| 
       71 
     | 
    
         
            -
                
         
     | 
| 
       72 
     | 
    
         
            -
                # The highest data point on this GraphLayer
         
     | 
| 
       73 
     | 
    
         
            -
                def highest_point
         
     | 
| 
       74 
     | 
    
         
            -
                  points.sort.last
         
     | 
| 
       75 
     | 
    
         
            -
                end
         
     | 
| 
       76 
     | 
    
         
            -
                
         
     | 
| 
       77 
     | 
    
         
            -
                # The lowest data point on this GraphLayer
         
     | 
| 
       78 
     | 
    
         
            -
                def lowest_point
         
     | 
| 
       79 
     | 
    
         
            -
                  points.sort.first
         
     | 
| 
       80 
     | 
    
         
            -
                end
         
     | 
| 
       81 
     | 
    
         
            -
                
         
     | 
| 
       82 
     | 
    
         
            -
                protected
         
     | 
| 
       83 
     | 
    
         
            -
                  def setup_variables(options = {}) # :nodoc:
         
     | 
| 
       84 
     | 
    
         
            -
                    @color = (preferred_color || options.delete(:color))
         
     | 
| 
       85 
     | 
    
         
            -
                    @resolver = options.delete(:resolver)
         
     | 
| 
       86 
     | 
    
         
            -
                    @width, @height = options.delete(:size)
         
     | 
| 
       87 
     | 
    
         
            -
                    @min_value, @max_value = options[:min_value], options[:max_value]
         
     | 
| 
       88 
     | 
    
         
            -
                    @opacity = options[:opacity]
         
     | 
| 
       89 
     | 
    
         
            -
                    @complexity = options[:complexity]
         
     | 
| 
       90 
     | 
    
         
            -
                  end
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                  def generate_coordinates(options = {}) # :nodoc:
         
     | 
| 
       93 
     | 
    
         
            -
                    options[:point_distance] = width / (points.size - 1).to_f
         
     | 
| 
       94 
     | 
    
         
            -
                    
         
     | 
| 
       95 
     | 
    
         
            -
                    coords = (0...points.size).map do |idx| 
         
     | 
| 
       96 
     | 
    
         
            -
                      x_coord = options[:point_distance] * idx
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                      relative_percent = ((points[idx] == min_value) ? 0 : ((points[idx] - min_value) / (max_value - min_value).to_f))
         
     | 
| 
       99 
     | 
    
         
            -
                      y_coord = (height - (height * relative_percent))
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                      [x_coord, y_coord]
         
     | 
| 
       102 
     | 
    
         
            -
                    end
         
     | 
| 
       103 
     | 
    
         
            -
                    
         
     | 
| 
       104 
     | 
    
         
            -
                    coords
         
     | 
| 
       105 
     | 
    
         
            -
                  end
         
     | 
| 
       106 
     | 
    
         
            -
                  
         
     | 
| 
       107 
     | 
    
         
            -
                  # Returns a 'scaled' value of the given integer.
         
     | 
| 
       108 
     | 
    
         
            -
                  # 
         
     | 
| 
       109 
     | 
    
         
            -
                  # Scaled adjusts the given point depending on the height of the graph, where 400px is considered 1:1.
         
     | 
| 
       110 
     | 
    
         
            -
                  #
         
     | 
| 
       111 
     | 
    
         
            -
                  # ie: On a graph that is 800px high, scaled(1) => 2.  For 200px high, scaled(1) => 0.5, and so on...
         
     | 
| 
       112 
     | 
    
         
            -
                  def scaled(point)
         
     | 
| 
       113 
     | 
    
         
            -
                    resolver.to_point(point)
         
     | 
| 
       114 
     | 
    
         
            -
                  end
         
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
                  def stringify_coords(coords) # :nodoc:
         
     | 
| 
       117 
     | 
    
         
            -
                    coords.map { |c| c.join(',') }
         
     | 
| 
       118 
     | 
    
         
            -
                  end
         
     | 
| 
       119 
     | 
    
         
            -
              end
         
     | 
| 
       120 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,11 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            module Scruffy
         
     | 
| 
       2 
     | 
    
         
            -
              class LineLayer < GraphLayer
         
     | 
| 
       3 
     | 
    
         
            -
                def draw(svg, coords, options={})
         
     | 
| 
       4 
     | 
    
         
            -
                  svg.polyline( :points => stringify_coords(coords).join(' '), :fill => 'none', 
         
     | 
| 
       5 
     | 
    
         
            -
                                :stroke => color.to_s, 'stroke-width' => scaled(4) )
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
                  coords.each { |coord| svg.circle( :cx => coord.first, :cy => coord.last, :r => scaled(5), 
         
     | 
| 
       8 
     | 
    
         
            -
                                                    :fill => color.to_s ) }
         
     | 
| 
       9 
     | 
    
         
            -
                end
         
     | 
| 
       10 
     | 
    
         
            -
              end
         
     | 
| 
       11 
     | 
    
         
            -
            end
         
     |