metric_fu 1.1.6 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY CHANGED
@@ -1,3 +1,14 @@
1
+ === MetricFu 1.2.0 / 2010-01-09
2
+
3
+ * ftools isn't supported by 1.9 so moved to fileutils.
4
+ * Added support for Google Charts thanks to Carl Youngblood.
5
+ * Stopped relying on Github gems as they will be going away.
6
+
7
+ === MetricFu 1.1.6 / 2009-12-14
8
+
9
+ * Now compatible with Reek 1.2x thanks to Kevin Rutherford
10
+ * Fixed problem with deleted files still showing up in Flog reports thanks to Dan Mayer
11
+
1
12
  === MetricFu 1.1.5 / 2009-8-13
2
13
 
3
14
  * Previous Ruby 1.9 fix was not quite fix-y enough
@@ -139,8 +139,7 @@ module MetricFu
139
139
  def cycle(first_value, second_value, iteration)
140
140
  return first_value if iteration % 2 == 0
141
141
  return second_value
142
- end
143
-
142
+ end
144
143
 
145
144
  end
146
145
  end
@@ -9,6 +9,7 @@ module MetricFu
9
9
  :roodi, :saikuro, :rcov]
10
10
 
11
11
  AVAILABLE_GRAPHS = [:flog, :flay, :reek, :roodi, :rcov]
12
+ AVAILABLE_GRAPH_ENGINES = [:gchart, :bluff]
12
13
 
13
14
  # The @@configuration class variable holds a global type configuration
14
15
  # object for any parts of the system to use.
@@ -133,18 +134,7 @@ module MetricFu
133
134
 
134
135
  @file_globs_to_ignore = []
135
136
 
136
- @graph_theme = { :colors => %w(orange purple green white red blue pink yellow),
137
- :marker_color => 'blue',
138
- :background_colors => %w(white white)}
139
-
140
- relative_font_path = [File.dirname(__FILE__), '..', '..', 'vendor', '_fonts', 'monaco.ttf']
141
- @graph_font = File.expand_path(File.join(relative_font_path))
142
- @graph_size = "1000x400"
143
- @graph_title_font_size = 12
144
- @graph_legend_box_size = 12
145
- @graph_legend_font_size = 10
146
- @graph_marker_font_size = 10
147
-
137
+ @graph_engine = :bluff # can be :bluff or :gchart
148
138
  end
149
139
 
150
140
  # Perform a simple check to try and guess if we're running
data/lib/base/graph.rb CHANGED
@@ -12,8 +12,8 @@ module MetricFu
12
12
  self.clazz = []
13
13
  end
14
14
 
15
- def add(graph_type)
16
- grapher_name = graph_type.to_s.capitalize + "Grapher"
15
+ def add(graph_type, graph_engine)
16
+ grapher_name = graph_type.to_s.capitalize + graph_engine.to_s.capitalize + "Grapher"
17
17
  self.clazz.push MetricFu.const_get(grapher_name).new
18
18
  end
19
19
 
@@ -24,10 +24,11 @@ module MetricFu
24
24
  Dir[File.join(MetricFu.data_directory, '*.yml')].sort.each do |metric_file|
25
25
  puts "Generating graphs for #{metric_file}"
26
26
  date = metric_file.split('/')[3].split('.')[0]
27
+ y, m, d = date[0..3].to_i, date[4..5].to_i, date[6..7].to_i
27
28
  metrics = YAML::load(File.open(metric_file))
28
29
 
29
30
  self.clazz.each do |grapher|
30
- grapher.get_metrics(metrics, date)
31
+ grapher.get_metrics(metrics, "#{m}/#{d}")
31
32
  end
32
33
  end
33
34
  self.clazz.each do |grapher|
@@ -0,0 +1,85 @@
1
+ require 'activesupport'
2
+
3
+ module MetricFu
4
+ class Grapher
5
+ BLUFF_GRAPH_SIZE = "1000x600"
6
+ BLUFF_DEFAULT_OPTIONS = <<-EOS
7
+ var g = new Bluff.Line('graph', "#{BLUFF_GRAPH_SIZE}");
8
+ g.theme_37signals();
9
+ g.title_font_size = "24px"
10
+ g.legend_font_size = "12px"
11
+ g.marker_font_size = "10px"
12
+ EOS
13
+ end
14
+
15
+ class FlayBluffGrapher < FlayGrapher
16
+ def graph!
17
+ content = <<-EOS
18
+ #{BLUFF_DEFAULT_OPTIONS}
19
+ g.title = 'Flay: duplication';
20
+ g.data('flay', [#{@flay_score.join(',')}]);
21
+ g.labels = #{@labels.to_json};
22
+ g.draw();
23
+ EOS
24
+ File.open(File.join(MetricFu.output_directory, 'flay.js'), 'w') {|f| f << content }
25
+ end
26
+ end
27
+
28
+ class FlogBluffGrapher < FlogGrapher
29
+ def graph!
30
+ content = <<-EOS
31
+ #{BLUFF_DEFAULT_OPTIONS}
32
+ g.title = 'Flog: code complexity';
33
+ g.data('average', [#{@flog_average.join(',')}]);
34
+ g.data('top 5% average', [#{@top_five_percent_average.join(',')}])
35
+ g.labels = #{@labels.to_json};
36
+ g.draw();
37
+ EOS
38
+ File.open(File.join(MetricFu.output_directory, 'flog.js'), 'w') {|f| f << content }
39
+ end
40
+ end
41
+
42
+ class RcovBluffGrapher < RcovGrapher
43
+ def graph!
44
+ content = <<-EOS
45
+ #{BLUFF_DEFAULT_OPTIONS}
46
+ g.title = 'Rcov: code coverage';
47
+ g.data('rcov', [#{@rcov_percent.join(',')}]);
48
+ g.labels = #{@labels.to_json};
49
+ g.draw();
50
+ EOS
51
+ File.open(File.join(MetricFu.output_directory, 'rcov.js'), 'w') {|f| f << content }
52
+ end
53
+ end
54
+
55
+ class ReekBluffGrapher < ReekGrapher
56
+ def graph!
57
+ legend = @reek_count.keys.sort
58
+ data = ""
59
+ legend.each do |name|
60
+ data += "g.data('#{name}', [#{@reek_count[name].join(',')}])\n"
61
+ end
62
+ content = <<-EOS
63
+ #{BLUFF_DEFAULT_OPTIONS}
64
+ g.title = 'Reek: code smells';
65
+ #{data}
66
+ g.labels = #{@labels.to_json};
67
+ g.draw();
68
+ EOS
69
+ File.open(File.join(MetricFu.output_directory, 'reek.js'), 'w') {|f| f << content }
70
+ end
71
+ end
72
+
73
+ class RoodiBluffGrapher < RoodiGrapher
74
+ def graph!
75
+ content = <<-EOS
76
+ #{BLUFF_DEFAULT_OPTIONS}
77
+ g.title = 'Roodi: design problems';
78
+ g.data('roodi', [#{@roodi_count.join(',')}]);
79
+ g.labels = #{@labels.to_json};
80
+ g.draw();
81
+ EOS
82
+ File.open(File.join(MetricFu.output_directory, 'roodi.js'), 'w') {|f| f << content }
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,119 @@
1
+ module MetricFu
2
+ module GchartGrapher
3
+ COLORS = %w{009999 FF7400 A60000 008500 E6399B 344AD7 00B860 D5CCB9}
4
+ GCHART_GRAPH_SIZE = "1000x300" # maximum permitted image size is 300000 pixels
5
+
6
+ NUMBER_OF_TICKS = 6
7
+ def determine_y_axis_scale(values)
8
+ values.collect! {|val| val || 0.0 }
9
+ if values.empty?
10
+ @max_value = 10
11
+ @yaxis = [0, 2, 4, 6, 8, 10]
12
+ else
13
+ @max_value = values.max + Integer(0.1 * values.max)
14
+ portion_size = (@max_value / (NUMBER_OF_TICKS - 1).to_f).ceil
15
+ @yaxis = []
16
+ NUMBER_OF_TICKS.times {|n| @yaxis << Integer(portion_size * n) }
17
+ @max_value = @yaxis.last
18
+ end
19
+ end
20
+ end
21
+
22
+ class Grapher
23
+ include MetricFu::GchartGrapher
24
+
25
+ def self.require_graphing_gem
26
+ require 'gchart'
27
+ rescue LoadError
28
+ puts "#"*99 + "\n" +
29
+ "If you want to use google charts for graphing, you'll need to install the googlecharts rubygem." +
30
+ "\n" + "#"*99
31
+ end
32
+ end
33
+
34
+ class FlayGchartGrapher < FlayGrapher
35
+ def graph!
36
+ determine_y_axis_scale(@flay_score)
37
+ url = Gchart.line(
38
+ :size => GCHART_GRAPH_SIZE,
39
+ :title => URI.escape("Flay: duplication"),
40
+ :data => @flay_score,
41
+ :max_value => @max_value,
42
+ :axis_with_labels => 'x,y',
43
+ :axis_labels => [@labels.values, @yaxis],
44
+ :format => 'file',
45
+ :filename => File.join(MetricFu.output_directory, 'flay.png'))
46
+ end
47
+ end
48
+
49
+ class FlogGchartGrapher < FlogGrapher
50
+ def graph!
51
+ determine_y_axis_scale(@top_five_percent_average + @flog_average)
52
+ url = Gchart.line(
53
+ :size => GCHART_GRAPH_SIZE,
54
+ :title => URI.escape("Flog: code complexity"),
55
+ :data => [@flog_average, @top_five_percent_average],
56
+ :stacked => false,
57
+ :bar_colors => COLORS[0..1],
58
+ :legend => ['average', 'top 5%25 average'],
59
+ :max_value => @max_value,
60
+ :axis_with_labels => 'x,y',
61
+ :axis_labels => [@labels.values, @yaxis],
62
+ :format => 'file',
63
+ :filename => File.join(MetricFu.output_directory, 'flog.png'))
64
+ end
65
+ end
66
+
67
+ class RcovGchartGrapher < RcovGrapher
68
+ def graph!
69
+ determine_y_axis_scale(self.rcov_percent)
70
+ url = Gchart.line(
71
+ :size => GCHART_GRAPH_SIZE,
72
+ :title => URI.escape("Rcov: code coverage"),
73
+ :data => self.rcov_percent,
74
+ :max_value => 101,
75
+ :axis_with_labels => 'x,y',
76
+ :axis_labels => [self.labels.values, [0,20,40,60,80,100]],
77
+ :format => 'file',
78
+ :filename => File.join(MetricFu.output_directory, 'rcov.png')
79
+ )
80
+ end
81
+ end
82
+
83
+ class ReekGchartGrapher < ReekGrapher
84
+ def graph!
85
+ determine_y_axis_scale(@reek_count.values.flatten.uniq)
86
+ values = []
87
+ legend = @reek_count.keys.sort
88
+ legend.collect {|k| values << @reek_count[k]}
89
+
90
+ url = Gchart.line(
91
+ :size => GCHART_GRAPH_SIZE,
92
+ :title => URI.escape("Reek: code smells"),
93
+ :data => values,
94
+ :stacked => false,
95
+ :bar_colors => COLORS,
96
+ :legend => legend,
97
+ :max_value => @max_value,
98
+ :axis_with_labels => 'x,y',
99
+ :axis_labels => [@labels.values, @yaxis],
100
+ :format => 'file',
101
+ :filename => File.join(MetricFu.output_directory, 'reek.png'))
102
+ end
103
+ end
104
+
105
+ class RoodiGchartGrapher < RoodiGrapher
106
+ def graph!
107
+ determine_y_axis_scale(@roodi_count)
108
+ url = Gchart.line(
109
+ :size => GCHART_GRAPH_SIZE,
110
+ :title => URI.escape("Roodi: potential design problems"),
111
+ :data => @roodi_count,
112
+ :max_value => @max_value,
113
+ :axis_with_labels => 'x,y',
114
+ :axis_labels => [@labels.values, @yaxis],
115
+ :format => 'file',
116
+ :filename => File.join(MetricFu.output_directory, 'roodi.png'))
117
+ end
118
+ end
119
+ end
@@ -1,4 +1,3 @@
1
-
2
1
  module MetricFu
3
2
 
4
3
  class FlayGrapher < Grapher
@@ -7,27 +6,13 @@ module MetricFu
7
6
 
8
7
  def initialize
9
8
  super
10
- self.flay_score = []
11
- self.labels = {}
9
+ @flay_score = []
10
+ @labels = {}
12
11
  end
13
12
 
14
13
  def get_metrics(metrics, date)
15
- self.flay_score.push(metrics[:flay][:total_score].to_i)
16
- self.labels.update( { self.labels.size => date })
17
- end
18
-
19
- def graph!
20
- g = Gruff::Line.new(MetricFu.graph_size)
21
- g.title = "Flay: duplication"
22
- g.theme = MetricFu.graph_theme
23
- g.font = MetricFu.graph_font
24
- g.data('flay', self.flay_score)
25
- g.labels = self.labels
26
- g.title_font_size = MetricFu.graph_title_font_size
27
- g.legend_box_size = MetricFu.graph_legend_box_size
28
- g.legend_font_size = MetricFu.graph_legend_font_size
29
- g.marker_font_size = MetricFu.graph_marker_font_size
30
- g.write(File.join(MetricFu.output_directory, 'flay.png'))
14
+ @flay_score.push(metrics[:flay][:total_score].to_i)
15
+ @labels.update( { @labels.size => date })
31
16
  end
32
17
 
33
18
  end
@@ -6,30 +6,15 @@ module MetricFu
6
6
 
7
7
  def initialize
8
8
  super
9
- self.flog_average = []
10
- self.labels = {}
11
- self.top_five_percent_average =[]
9
+ @flog_average = []
10
+ @labels = {}
11
+ @top_five_percent_average =[]
12
12
  end
13
13
 
14
14
  def get_metrics(metrics, date)
15
- self.top_five_percent_average.push(calc_top_five_percent_average(metrics))
16
- self.flog_average.push(metrics[:flog][:average])
17
- self.labels.update( { self.labels.size => date })
18
- end
19
-
20
- def graph!
21
- g = Gruff::Line.new(MetricFu.graph_size)
22
- g.title = "Flog: code complexity"
23
- g.theme = MetricFu.graph_theme
24
- g.font = MetricFu.graph_font
25
- g.data('top five percent average', self.top_five_percent_average)
26
- g.data('flog average', self.flog_average)
27
- g.labels = self.labels
28
- g.title_font_size = MetricFu.graph_title_font_size
29
- g.legend_box_size = MetricFu.graph_legend_box_size
30
- g.legend_font_size = MetricFu.graph_legend_font_size
31
- g.marker_font_size = MetricFu.graph_marker_font_size
32
- g.write(File.join(MetricFu.output_directory, 'flog.png'))
15
+ @top_five_percent_average.push(calc_top_five_percent_average(metrics))
16
+ @flog_average.push(metrics[:flog][:average])
17
+ @labels.update( { @labels.size => date })
33
18
  end
34
19
 
35
20
  private
@@ -37,13 +22,17 @@ module MetricFu
37
22
  def calc_top_five_percent_average(metrics)
38
23
  methods = metrics[:flog][:pages].inject([]) {|methods, page| methods << page[:scanned_methods]}
39
24
  methods.flatten!
40
-
41
25
  methods = methods.sort_by {|method| method[:score]}.reverse
42
26
 
43
27
  number_of_methods_that_is_five_percent = (methods.size * 0.05).ceil
44
28
 
45
- total_for_five_percent = methods[0...number_of_methods_that_is_five_percent].inject(0) {|total, method| total += method[:score]}
46
- total_for_five_percent / number_of_methods_that_is_five_percent.to_f
29
+ total_for_five_percent =
30
+ methods[0...number_of_methods_that_is_five_percent].inject(0) {|total, method| total += method[:score] }
31
+ if number_of_methods_that_is_five_percent == 0
32
+ 0.0
33
+ else
34
+ total_for_five_percent / number_of_methods_that_is_five_percent.to_f
35
+ end
47
36
  end
48
37
 
49
38
  end
@@ -1,19 +1,11 @@
1
1
  module MetricFu
2
2
  class Grapher
3
3
  def initialize
4
- self.class.require_gruff
4
+ self.class.require_graphing_gem
5
5
  end
6
6
 
7
- def self.require_gruff
8
- require 'gruff'
9
- rescue LoadError
10
- puts "#"*99 + "\n" +
11
- "If you want to use metric_fu's graphing features then you'll need to install the gems " +
12
- "'topfunky-gruff' (or 'umang-gruff' if you use 1.9x) and 'rmagick' (and rmagick requires ImageMagick). "+
13
- "If you don't want to deal with that, then make sure you set config.graphs = [] (see the metric_fu's homepage for more details) "+
14
- "to indicate that you don't want graphing." +
15
- "\n" + "#"*99
16
- raise
7
+ def self.require_graphing_gem
8
+ # to be overridden by charting engines
17
9
  end
18
10
  end
19
11
  end
@@ -15,20 +15,6 @@ module MetricFu
15
15
  self.labels.update( { self.labels.size => date })
16
16
  end
17
17
 
18
- def graph!
19
- g = Gruff::Line.new(MetricFu.graph_size)
20
- g.title = "Rcov: code coverage"
21
- g.theme = MetricFu.graph_theme
22
- g.font = MetricFu.graph_font
23
- g.data('rcov', self.rcov_percent)
24
- g.labels = self.labels
25
- g.title_font_size = MetricFu.graph_title_font_size
26
- g.legend_box_size = MetricFu.graph_legend_box_size
27
- g.legend_font_size = MetricFu.graph_legend_font_size
28
- g.marker_font_size = MetricFu.graph_marker_font_size
29
- g.write(File.join(MetricFu.output_directory, 'rcov.png'))
30
- end
31
-
32
18
  end
33
19
 
34
20
  end
@@ -6,39 +6,27 @@ module MetricFu
6
6
 
7
7
  def initialize
8
8
  super
9
- self.reek_count = {}
10
- self.labels= {}
9
+ @reek_count = {}
10
+ @labels = {}
11
11
  end
12
12
 
13
13
  def get_metrics(metrics, date)
14
- counter = self.labels.size
15
- self.labels.update( { counter => date })
14
+ counter = @labels.size
15
+ @labels.update( { @labels.size => date })
16
16
 
17
17
  metrics[:reek][:matches].each do |reek_chunk|
18
18
  reek_chunk[:code_smells].each do |code_smell|
19
19
  # speaking of code smell...
20
- self.reek_count[code_smell[:type]] = [] if self.reek_count[code_smell[:type]].nil?
21
- self.reek_count[code_smell[:type]][counter].nil? ? self.reek_count[code_smell[:type]][counter] = 1 : self.reek_count[code_smell[:type]][counter] += 1
20
+ @reek_count[code_smell[:type]] = [] if @reek_count[code_smell[:type]].nil?
21
+ if @reek_count[code_smell[:type]][counter].nil?
22
+ @reek_count[code_smell[:type]][counter] = 1
23
+ else
24
+ @reek_count[code_smell[:type]][counter] += 1
25
+ end
22
26
  end
23
27
  end
24
28
  end
25
29
 
26
- def graph!
27
- g = Gruff::Line.new(MetricFu.graph_size)
28
- g.title = "Reek: code smells"
29
- g.theme = MetricFu.graph_theme
30
- g.font = MetricFu.graph_font
31
- self.reek_count.each_pair do |type, count|
32
- g.data(type, count)
33
- end
34
- g.labels = self.labels
35
- g.title_font_size = MetricFu.graph_title_font_size
36
- g.legend_box_size = MetricFu.graph_legend_box_size
37
- g.legend_font_size = MetricFu.graph_legend_font_size
38
- g.marker_font_size = MetricFu.graph_marker_font_size
39
- g.write(File.join(MetricFu.output_directory, 'reek.png'))
40
- end
41
-
42
30
  end
43
31
 
44
32
  end
@@ -6,27 +6,13 @@ module MetricFu
6
6
 
7
7
  def initialize
8
8
  super
9
- self.roodi_count = []
10
- self.labels = {}
9
+ @roodi_count = []
10
+ @labels = {}
11
11
  end
12
12
 
13
13
  def get_metrics(metrics, date)
14
- self.roodi_count.push(metrics[:roodi][:problems].size)
15
- self.labels.update( { self.labels.size => date })
16
- end
17
-
18
- def graph!
19
- g = Gruff::Line.new(MetricFu.graph_size)
20
- g.title = "Roodi: design problems"
21
- g.theme = MetricFu.graph_theme
22
- g.font = MetricFu.graph_font
23
- g.data('roodi', self.roodi_count)
24
- g.labels = self.labels
25
- g.title_font_size = MetricFu.graph_title_font_size
26
- g.legend_box_size = MetricFu.graph_legend_box_size
27
- g.legend_font_size = MetricFu.graph_legend_font_size
28
- g.marker_font_size = MetricFu.graph_marker_font_size
29
- g.write(File.join(MetricFu.output_directory, 'roodi.png'))
14
+ @roodi_count.push(metrics[:roodi][:problems].size)
15
+ @labels.update( { @labels.size => date })
30
16
  end
31
17
 
32
18
  end
data/lib/metric_fu.rb CHANGED
@@ -5,9 +5,9 @@ module MetricFu
5
5
  LIB_ROOT = File.dirname(__FILE__)
6
6
  end
7
7
  base_dir = File.join(MetricFu::LIB_ROOT, 'base')
8
- generator_dir = File.join(MetricFu::LIB_ROOT, 'generators')
9
- template_dir = File.join(MetricFu::LIB_ROOT, 'templates')
10
- graph_dir = File.join(MetricFu::LIB_ROOT, 'graphs')
8
+ generator_dir = File.join(MetricFu::LIB_ROOT, 'generators')
9
+ template_dir = File.join(MetricFu::LIB_ROOT, 'templates')
10
+ graph_dir = File.join(MetricFu::LIB_ROOT, 'graphs')
11
11
 
12
12
  # We need to require these two things first because our other classes
13
13
  # depend on them.
@@ -27,4 +27,5 @@ Dir[File.join(generator_dir, '*.rb')].each {|l| require l }
27
27
  Dir[File.join(template_dir, 'standard/*.rb')].each {|l| require l}
28
28
  Dir[File.join(template_dir, 'awesome/*.rb')].each {|l| require l}
29
29
  require graph_dir + "/grapher"
30
- Dir[File.join(graph_dir, '*.rb')].each {|l| require l}
30
+ Dir[File.join(graph_dir, '*.rb')].each {|l| require l}
31
+ Dir[File.join(graph_dir, 'engines', '*.rb')].each {|l| require l}
@@ -1,9 +1,16 @@
1
+ require 'fileutils'
2
+
1
3
  class AwesomeTemplate < MetricFu::Template
2
4
 
3
5
  def write
4
6
  # Getting rid of the crap before and after the project name from integrity
5
7
  @name = File.basename(Dir.pwd).gsub(/^\w+-|-\w+$/, "")
6
8
 
9
+ # Copy Bluff javascripts to output directory
10
+ Dir[File.join(this_directory, '..', 'javascripts', '*')].each do |f|
11
+ FileUtils.copy(f, File.join(MetricFu.output_directory, File.basename(f)))
12
+ end
13
+
7
14
  report.each_pair do |section, contents|
8
15
  if template_exists?(section)
9
16
  create_instance_var(section, contents)
@@ -2,7 +2,13 @@
2
2
 
3
3
  <p><a href='http://ruby.sadi.st/Flay.html'>Flay</a> analyzes ruby code for structural similarities.</p>
4
4
 
5
- <img src="flay.png?<%= Time.now %>">
5
+ <% graph_name = 'flay' %>
6
+ <% if MetricFu.configuration.graph_engine == :gchart %>
7
+ <img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
8
+ <% else %>
9
+ <canvas id="graph"></canvas>
10
+ <script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
11
+ <% end %>
6
12
 
7
13
  <h4>Total Score (lower is better): <%= @flay[:total_score] %></h4>
8
14
 
@@ -1,7 +1,13 @@
1
1
  <h3>Flog Results</h3>
2
2
  <p><a href='http://ruby.sadi.st/Flog.html'>Flog</a> measures code complexity.</p>
3
3
 
4
- <img src="flog.png?<%= Time.now %>">
4
+ <% graph_name = 'flog' %>
5
+ <% if MetricFu.configuration.graph_engine == :gchart %>
6
+ <img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
7
+ <% else %>
8
+ <canvas id="graph"></canvas>
9
+ <script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
10
+ <% end %>
5
11
 
6
12
  <h2>Total Flog score for all methods: <%= @flog[:total]%></h2>
7
13
  <h2>Average Flog score for all methods: <%= @flog[:average]%></h2>
@@ -11,6 +11,9 @@
11
11
  <%= inline_css("css/default.css") %>
12
12
  </style>
13
13
  <link REL="SHORTCUT ICON" HREF="/favicon.ico">
14
+ <script language="javascript" src="js-class.js" type="text/javascript"></script>
15
+ <script language="javascript" src="bluff-min.js" type="text/javascript"></script>
16
+ <script language="javascript" src="excanvas.js" type="text/javascript"></script>
14
17
  </head>
15
18
  <body>
16
19
  <div id='header'>
@@ -2,7 +2,13 @@
2
2
 
3
3
  <p>C0 code coverage information.</p>
4
4
 
5
- <img src="rcov.png?<%= Time.now %>">
5
+ <% graph_name = 'rcov' %>
6
+ <% if MetricFu.configuration.graph_engine == :gchart %>
7
+ <img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
8
+ <% else %>
9
+ <canvas id="graph"></canvas>
10
+ <script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
11
+ <% end %>
6
12
 
7
13
  <p>Total Coverage: <%= @rcov.delete(:global_percent_run) %>% </p>
8
14
  <table>
@@ -2,7 +2,13 @@
2
2
 
3
3
  <p><a href="http://reek.rubyforge.org/">Reek</a> detects common code smells in ruby code.</p>
4
4
 
5
- <img src="reek.png?<%= Time.now %>">
5
+ <% graph_name = 'reek' %>
6
+ <% if MetricFu.configuration.graph_engine == :gchart %>
7
+ <img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
8
+ <% else %>
9
+ <canvas id="graph"></canvas>
10
+ <script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
11
+ <% end %>
6
12
 
7
13
  <table>
8
14
  <tr>
@@ -2,7 +2,13 @@
2
2
 
3
3
  <p><a href="http://roodi.rubyforge.org/">Roodi</a> parses your Ruby code and warns you about design issues you have based on the checks that is has configured.</p>
4
4
 
5
- <img src="roodi.png?<%= Time.now %>">
5
+ <% graph_name = 'roodi' %>
6
+ <% if MetricFu.configuration.graph_engine == :gchart %>
7
+ <img src="<%= graph_name %>.png?<%= Time.now.to_i %>" />
8
+ <% else %>
9
+ <canvas id="graph"></canvas>
10
+ <script language="javascript" src="<%= graph_name %>.js?<%= Time.now.to_i %>" type="text/javascript"></script>
11
+ <% end %>
6
12
 
7
13
  <table>
8
14
  <tr>
@@ -0,0 +1 @@
1
+ Bluff={VERSION:'0.3.4',array:function(c){if(c.length===undefined)return[c];var d=[],f=c.length;while(f--)d[f]=c[f];return d},each:function(c,d,f){for(var g=0,h=c.length;g<h;g++){d.call(f||null,c[g],g)}},reverse_each:function(c,d,f){var g=c.length;while(g--)d.call(f||null,c[g],g)},sum:function(c){var d=0,f=c.length;while(f--)d+=c[f];return d},Mini:{}};Bluff.Base=new JS.Class({extend:{DEBUG:false,DATA_LABEL_INDEX:0,DATA_VALUES_INDEX:1,DATA_COLOR_INDEX:2,LEGEND_MARGIN:10,TITLE_MARGIN:10,LABEL_MARGIN:10,DEFAULT_TARGET_WIDTH:800},top_margin:null,bottom_margin:null,right_margin:null,left_margin:null,labels:null,center_labels_over_point:null,has_left_labels:null,x_axis_label:null,y_axis_label:null,y_axis_increment:null,colors:null,title:null,font:null,font_color:null,hide_line_markers:null,hide_legend:null,hide_title:null,hide_line_numbers:null,no_data_message:null,title_font_size:null,legend_font_size:null,marker_font_size:null,marker_color:null,marker_count:null,minimum_value:null,maximum_value:null,sort:null,additional_line_values:null,stacked:null,legend_box_size:null,initialize:function(c,d){this._0=new Bluff.Renderer(c);d=d||this.klass.DEFAULT_TARGET_WIDTH;this.top_margin=this.bottom_margin=this.left_margin=this.right_margin=20;var f;if(typeof d!='number'){f=d.split('x');this._j=parseFloat(f[0]);this._x=parseFloat(f[1])}else{this._j=parseFloat(d);this._x=this._j*0.75}this.initialize_ivars();this._15();this.theme_keynote()},initialize_ivars:function(){this._b=800;this._J=800*(this._x/this._j);this._5=0;this.marker_count=null;this.maximum_value=this.minimum_value=null;this._9=false;this._2=[];this.labels={};this._y={};this.sort=true;this.title=null;this._c=this._j/this._b;this.marker_font_size=21.0;this.legend_font_size=20.0;this.title_font_size=36.0;this.legend_box_size=20.0;this.no_data_message="No Data";this.hide_line_markers=this.hide_legend=this.hide_title=this.hide_line_numbers=false;this.center_labels_over_point=true;this.has_left_labels=false;this.additional_line_values=[];this._1l=[];this._k={};this.x_axis_label=this.y_axis_label=null;this.y_axis_increment=null;this.stacked=null;this._a=null},set_margins:function(c){this.top_margin=this.left_margin=this.right_margin=this.bottom_margin=c},set_font:function(c){this.font=c;this._0.font=this.font},add_color:function(c){this.colors.push(c)},replace_colors:function(c){this.colors=c||[]},set_theme:function(c){this._15();this._k={colors:['black','white'],additional_line_colors:[],marker_color:'white',font_color:'black',background_colors:null,background_image:null};for(var d in c)this._k[d]=c[d];this.colors=this._k.colors;this.marker_color=this._k.marker_color;this.font_color=this._k.font_color||this.marker_color;this._1l=this._k.additional_line_colors;this._R()},theme_keynote:function(){this._S='#6886B4';this._T='#FDD84E';this._n='#72AE6E';this._z='#D1695E';this._U='#8A6EAF';this._A='#EFAA43';this._B='white';this.colors=[this._T,this._S,this._n,this._z,this._U,this._A,this._B];this.set_theme({colors:this.colors,marker_color:'white',font_color:'white',background_colors:['black','#4a465a']})},theme_37signals:function(){this._n='#339933';this._U='#cc99cc';this._S='#336699';this._T='#FFF804';this._z='#ff0000';this._A='#cf5910';this._C='black';this.colors=[this._T,this._S,this._n,this._z,this._U,this._A,this._C];this.set_theme({colors:this.colors,marker_color:'black',font_color:'black',background_colors:['#d1edf5','white']})},theme_rails_keynote:function(){this._n='#00ff00';this._V='#333333';this._A='#ff5d00';this._z='#f61100';this._B='white';this._W='#999999';this._C='black';this.colors=[this._n,this._V,this._A,this._z,this._B,this._W,this._C];this.set_theme({colors:this.colors,marker_color:'white',font_color:'white',background_colors:['#0083a3','#0083a3']})},theme_odeo:function(){this._V='#202020';this._B='white';this._1m='#a21764';this._n='#8ab438';this._W='#999999';this._1n='#3a5b87';this._C='black';this.colors=[this._V,this._B,this._1n,this._1m,this._n,this._W,this._C];this.set_theme({colors:this.colors,marker_color:'white',font_color:'white',background_colors:['#ff47a4','#ff1f81']})},theme_pastel:function(){this.colors=['#a9dada','#aedaa9','#daaea9','#dadaa9','#a9a9da','#daaeda','#dadada'];this.set_theme({colors:this.colors,marker_color:'#aea9a9',font_color:'black',background_colors:'white'})},theme_greyscale:function(){this.colors=['#282828','#383838','#686868','#989898','#c8c8c8','#e8e8e8'];this.set_theme({colors:this.colors,marker_color:'#aea9a9',font_color:'black',background_colors:'white'})},data:function(f,g,h){g=(g===undefined)?[]:g;h=h||null;g=Bluff.array(g);this._2.push([f,g,(h||this._1o())]);this._5=(g.length>this._5)?g.length:this._5;Bluff.each(g,function(c,d){if(c===undefined)return;if(this.maximum_value===null&&this.minimum_value===null)this.maximum_value=this.minimum_value=c;this.maximum_value=this._16(c)?c:this.maximum_value;if(this.maximum_value>0)this._9=true;this.minimum_value=this._1p(c)?c:this.minimum_value;if(this.minimum_value<0)this._9=true},this)},draw:function(){if(this.stacked)this._1q();this._1r();this._s(function(){this._0.rectangle(this.left_margin,this.top_margin,this._b-this.right_margin,this._J-this.bottom_margin);this._0.rectangle(this._1,this._7,this._o,this._i)})},clear:function(){this._R()},_1r:function(){if(!this._9)return this._1s();this._X();this._1t();if(this.sort)this._1u();this._1v();this._Y();this._1w();this._1x()},_X:function(g){if(this._a===null||g===true){this._a=[];if(!this._9)return;this._17();Bluff.each(this._2,function(d){var f=[];Bluff.each(d[this.klass.DATA_VALUES_INDEX],function(c){if(c===null||c===undefined)f.push(null);else f.push((c-this.minimum_value)/this._e)},this);this._a.push([d[this.klass.DATA_LABEL_INDEX],f,d[this.klass.DATA_COLOR_INDEX]])},this)}},_17:function(){this._e=this.maximum_value-this.minimum_value;this._e=this._e>0?this._e:1},_1t:function(){this._K=this.hide_line_markers?0:this._D(this.marker_font_size);this._18=this.hide_title?0:this._D(this.title_font_size);this._19=this.hide_legend?0:this._D(this.legend_font_size);var c,d,f,g,h,i,j;if(this.hide_line_markers){this._1=this.left_margin;this._Z=this.right_margin;this._1a=this.bottom_margin}else{d=0;if(this.has_left_labels){c='';for(j in this.labels){c=c.length>this.labels[j].length?c:this.labels[j]}d=this._L(this.marker_font_size,c)*1.25}else{d=this._L(this.marker_font_size,this._1b(this.maximum_value))}f=this.hide_line_numbers&&!this.has_left_labels?0:d+this.klass.LABEL_MARGIN*2;this._1=this.left_margin+f+(this.y_axis_label===null?0.0:this._K+this.klass.LABEL_MARGIN*2);g=-Infinity;for(j in this.labels)g=g>Number(j)?g:Number(j);g=Math.round(g);h=(g>=(this._5-1)&&this.center_labels_over_point)?this._L(this.marker_font_size,this.labels[g])/2:0.0;this._Z=this.right_margin+h;this._1a=this.bottom_margin+this._K+this.klass.LABEL_MARGIN}this._o=this._b-this._Z;this._6=this._b-this._1-this._Z;this._7=this.top_margin+(this.hide_title?this.klass.TITLE_MARGIN:this._18+this.klass.TITLE_MARGIN*2)+(this.hide_legend?this.klass.LEGEND_MARGIN:this._19+this.klass.LEGEND_MARGIN*2);i=(this.x_axis_label===null)?0.0:this._K+this.klass.LABEL_MARGIN;this._i=this._J-this._1a-i;this._4=this._i-this._7},_1w:function(){if(this.x_axis_label){var c=this._i+this.klass.LABEL_MARGIN*2+this._K;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._f(this.marker_font_size);this._0.gravity='north';this._0.annotate_scaled(this._b,1.0,0.0,c,this.x_axis_label,this._c);this._s(function(){this._0.line(0.0,c,this._b,c)})}},_Y:function(){if(this.hide_line_markers)return;if(this.y_axis_increment===null){if(this.marker_count===null){Bluff.each([3,4,5,6,7],function(c){if(!this.marker_count&&this._e%c==0)this.marker_count=c},this);this.marker_count=this.marker_count||4}this._10=(this._e>0)?this._1c(this._e/this.marker_count):1}else{this.maximum_value=Math.max(Math.ceil(this.maximum_value),this.y_axis_increment);this.minimum_value=Math.floor(this.minimum_value);this._17();this._X(true);this.marker_count=Math.round(this._e/this.y_axis_increment);this._10=this.y_axis_increment}this._1y=this._4/(this._e/this._10);var d,f,g,h;for(d=0,f=this.marker_count;d<=f;d++){g=this._7+this._4-d*this._1y;this._0.stroke=this.marker_color;this._0.stroke_width=1;this._0.line(this._1,g,this._o,g);h=d*this._10+this.minimum_value;if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._f(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(this._1-this.klass.LABEL_MARGIN,1.0,0.0,g,this._1b(h),this._c)}}},_1d:function(c){return(this._b-c)/2},_1v:function(){if(this.hide_legend)return;this._t=[];for(var i=0,j=this._2.length;i<j;i++)this._t.push(this._2[i][this.klass.DATA_LABEL_INDEX]);var k=this.legend_box_size;if(this.font)this._0.font=this.font;this._0.pointsize=this.legend_font_size;var l=[[]];Bluff.each(this._t,function(c){var d=l.length-1;var f=this._0.get_type_metrics(c);var g=f.width+k*2.7;l[d].push(g);if(Bluff.sum(l[d])>(this._b*0.9))l.push([l[d].pop()])},this);var o=this._1d(Bluff.sum(l[0]));var n=this.hide_title?this.top_margin+this.klass.LEGEND_MARGIN:this.top_margin+this.klass.TITLE_MARGIN+this._18+this.klass.LEGEND_MARGIN;this._s(function(){this._0.stroke_width=1;this._0.line(0,n,this._b,n)});Bluff.each(this._t,function(c,d){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._f(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='normal';this._0.gravity='west';this._0.annotate_scaled(this._b,1.0,o+(k*1.7),n,c,this._c);this._0.stroke='transparent';this._0.fill=this._2[d][this.klass.DATA_COLOR_INDEX];this._0.rectangle(o,n-k/2.0,o+k,n+k/2.0);this._0.pointsize=this.legend_font_size;var f=this._0.get_type_metrics(c);var g=f.width+(k*2.7),h;l[0].shift();if(l[0].length==0){this._s(function(){this._0.line(0.0,n,this._b,n)});l.shift();if(l.length>0)o=this._1d(Bluff.sum(l[0]));h=Math.max(this._19,k)+this.klass.LEGEND_MARGIN;if(l.length>0){n+=h;this._7+=h;this._4=this._i-this._7}}else{o+=g}},this);this._l=0},_1x:function(){if(this.hide_title||!this.title)return;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._f(this.title_font_size);this._0.font_weight='bold';this._0.gravity='north';this._0.annotate_scaled(this._b,1.0,0,this.top_margin,this.title,this._c)},_d:function(c,d){if(this.hide_line_markers)return;var f;if(this.labels[d]&&!this._y[d]){f=this._i+this.klass.LABEL_MARGIN;this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._f(this.marker_font_size);this._0.gravity='north';this._0.annotate_scaled(1.0,1.0,c,f,this.labels[d],this._c);this._y[d]=true;this._s(function(){this._0.stroke_width=1;this._0.line(0.0,f,this._b,f)})}},_1s:function(){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._f(80);this._0.gravity='center';this._0.annotate_scaled(this._b,this._J/2,0,10,this.no_data_message,this._c)},_R:function(){var c=this._k.background_colors;switch(true){case c instanceof Array:this._1z.apply(this,c);break;case typeof c=='string':this._1A(c);break;default:this._1B(this._k.background_image);break}},_1A:function(c){this._0.render_solid_background(this._j,this._x,c)},_1z:function(c,d){this._0.render_gradiated_background(this._j,this._x,c,d)},_1B:function(c){},_15:function(){this._l=0;this._y={};this._k={};this._0.scale(this._c,this._c)},_1T:function(c){return this._c*c},_f:function(c){var d=c*this._c;return d},_M:function(c,d){return(c>d)?d:c},_16:function(c,d){return c>this.maximum_value},_1p:function(c,d){return c<this.minimum_value},_1e:function(c,d){return c},_1U:function(c,d){return c},_1c:function(c){if(c==0)return 1.0;var d=1.0;while(c<10){c*=10;d/=10}while(c>100){c/=10;d*=10}return Math.floor(c)*d},_1u:function(){var f=this._1C,g=this.klass.DATA_VALUES_INDEX;this._a.sort(function(c,d){return f(d[g])-f(c[g])})},_1C:function(d){var f=0;Bluff.each(d,function(c){f+=c});return f},_1q:function(){var g=[],h=this._5;while(h--)g[h]=0;Bluff.each(this._2,function(f){Bluff.each(f[this.klass.DATA_VALUES_INDEX],function(c,d){g[d]+=c},this);f[this.klass.DATA_VALUES_INDEX]=Bluff.array(g)},this)},_s:function(c){if(this.klass.DEBUG){this._0.fill='transparent';this._0.stroke='turquoise';c.call(this)}},_1o:function(){if(this._l==0){this._l+=1;return this.colors[0]}else{if(this._l<this.colors.length){this._l+=1;return this.colors[this._l-1]}else{this._l=0;return this.colors[this.colors.length-1]}}},_1b:function(c){if(this._e%this.marker_count==0||this.y_axis_increment!==null){return String(Math.round(c))}if(this._e>10)return String(Math.floor(c));else if(this._e>=3)return String(Math.floor(c*100)/100);else return String(c)},_D:function(c){return this._0.caps_height(c)},_L:function(c,d){return this._0.text_width(c,d)}});Bluff.Area=new JS.Class(Bluff.Base,{draw:function(){this.callSuper();if(!this._9)return;this._N=this._6/(this._5-1);this._0.stroke='transparent';Bluff.each(this._a,function(h){var i=[];var j=0.0,k=0.0;Bluff.each(h[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._N*d);var g=this._7+(this._4-c*this._4);if(j>0&&k>0){i.push(f);i.push(g)}else{i.push(this._1);i.push(this._i-1);i.push(f);i.push(g)}this._d(f,d);j=f;k=g},this);i.push(this._o);i.push(this._i-1);i.push(this._1);i.push(this._i-1);this._0.fill=h[this.klass.DATA_COLOR_INDEX];this._0.polyline(i)},this)}});Bluff.BarConversion=new JS.Class({mode:null,zero:null,graph_top:null,graph_height:null,minimum_value:null,spread:null,getLeftYRightYscaled:function(c,d){var f;switch(this.mode){case 1:d[0]=this.graph_top+this.graph_height*(1-c)+1;d[1]=this.graph_top+this.graph_height-1;break;case 2:d[0]=this.graph_top+1;d[1]=this.graph_top+this.graph_height*(1-c)-1;break;case 3:f=c-this.minimum_value/this.spread;if(c>=this.zero){d[0]=this.graph_top+this.graph_height*(1-(f-this.zero))+1;d[1]=this.graph_top+this.graph_height*(1-this.zero)-1}else{d[0]=this.graph_top+this.graph_height*(1-(f-this.zero))+1;d[1]=this.graph_top+this.graph_height*(1-this.zero)-1}break;default:d[0]=0.0;d[1]=0.0}}});Bluff.Bar=new JS.Class(Bluff.Base,{draw:function(){var c=0,d;for(d in this.labels)c+=1;this.center_labels_over_point=(c>this._5);this.callSuper();if(!this._9)return;this._1D()},_1D:function(){var l=0.9;this._8=this._6/(this._5*this._2.length);var o=(this._8*(1-l))/2;this._0.stroke_opacity=0.0;var n=new Bluff.BarConversion();n.graph_height=this._4;n.graph_top=this._7;if(this.minimum_value>=0){n.mode=1}else{if(this.maximum_value<=0){n.mode=2}else{n.mode=3;n.spread=this._e;n.minimum_value=this.minimum_value;n.zero=-this.minimum_value/this._e}}Bluff.each(this._a,function(j,k){Bluff.each(j[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._8*(k+d+((this._2.length-1)*d)))+o;var g=f+this._8*l;var h=[];n.getLeftYRightYscaled(c,h);this._0.fill=j[this.klass.DATA_COLOR_INDEX];this._0.stroke='transparent';this._0.rectangle(f,h[0],g,h[1]);var i=this._1+(this._2.length*this._8*d)+(this._2.length*this._8/2.0)+o;this._d(i-(this.center_labels_over_point?this._8/2.0:0.0),d)},this)},this);if(this.center_labels_over_point)this._d(this._o,this._5)}});Bluff.Line=new JS.Class(Bluff.Base,{baseline_value:null,baseline_color:null,hide_dots:null,hide_lines:null,initialize:function(c){if(arguments.length>3)throw'Wrong number of arguments';if(arguments.length==1||(typeof arguments[1]!='number'&&typeof arguments[1]!='string'))this.callSuper(c,null);else this.callSuper();this.hide_dots=this.hide_lines=false;this.baseline_color='red';this.baseline_value=null},draw:function(){this.callSuper();if(!this._9)return;this.x_increment=(this._5>1)?(this._6/(this._5-1)):this._6;var l;if(this._O!==undefined){l=this._7+(this._4-this._O*this._4);this._0.push();this._0.stroke=this.baseline_color;this._0.stroke_width=3.0;this._0.line(this._1,l,this._1+this._6,l);this._0.pop()}Bluff.each(this._a,function(i){var j=null,k=null;Bluff.each(i[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this.x_increment*d);if(c===undefined)return;this._d(f,d);var g=this._7+(this._4-c*this._4);this._0.stroke=i[this.klass.DATA_COLOR_INDEX];this._0.fill=i[this.klass.DATA_COLOR_INDEX];this._0.stroke_opacity=1.0;this._0.stroke_width=this._M(this._j/(this._a[0][1].length*6),3.0);if(!this.hide_lines&&j!==null&&k!==null)this._0.line(j,k,f,g);var h=this._M(this._j/(this._a[0][1].length*2),7.0);if(!this.hide_dots)this._0.circle(f,g,f-h,g);j=f;k=g},this)},this)},_X:function(){this.maximum_value=Math.max(this.maximum_value,this.baseline_value);this.callSuper();if(this.baseline_value!==null)this._O=this.baseline_value/this.maximum_value}});Bluff.Net=new JS.Class(Bluff.Base,{hide_dots:null,initialize:function(){this.callSuper();this.hide_dots=false},draw:function(){this.callSuper();if(!this._9)return;this._u=this._4/2.0;this._v=this._1+(this._6/2.0);this._w=this._7+(this._4/2.0)-10;this._N=this._6/(this._5-1);var s=this._M(this._j/(this._a[0][this.klass.DATA_VALUES_INDEX].length*2.5),7.0);this._0.stroke_opacity=1.0;this._0.stroke_width=this._M(this._j/(this._a[0][this.klass.DATA_VALUES_INDEX].length*4),3.0);var q;if(this._O!==undefined){q=this._7+(this._4-this._O*this._4);this._0.push();this._0.stroke_color=this.baseline_color;this._0.fill_opacity=0.0;this._0.stroke_width=5;this._0.line(this._1,q,this._1+this._6,q);this._0.pop()}Bluff.each(this._a,function(m){var p=null,r=null;Bluff.each(m[this.klass.DATA_VALUES_INDEX],function(c,d){if(c===undefined)return;var f=d*Math.PI*2/this._5,g=c*this._u,h=this._v+Math.sin(f)*g,i=this._w-Math.cos(f)*g,j=(d+1<m[this.klass.DATA_VALUES_INDEX].length)?d+1:0,k=j*Math.PI*2/this._5,l=m[this.klass.DATA_VALUES_INDEX][j]*this._u,o=this._v+Math.sin(k)*l,n=this._w-Math.cos(k)*l;this._0.stroke=m[this.klass.DATA_COLOR_INDEX];this._0.fill=m[this.klass.DATA_COLOR_INDEX];this._0.line(h,i,o,n);if(!this.hide_dots)this._0.circle(h,i,h-s,i)},this)},this)},_Y:function(){if(this.hide_line_markers)return;this._u=this._4/2.0;this._v=this._1+(this._6/2.0);this._w=this._7+(this._4/2.0)-10;var c,d;for(var f=0,g=this._5;f<g;f++){c=f*Math.PI*2/this._5;this._0.stroke=this.marker_color;this._0.stroke_width=1;this._0.line(this._v,this._w,this._v+Math.sin(c)*this._u,this._w-Math.cos(c)*this._u);d=labels[f]?labels[f]:'000';this._d(this._v,this._w,c*360/(2*Math.PI),this._u,d)}},_d:function(c,d,f,g,h){var i=1.1,j=c,k=d,l=f*Math.PI/180,o=j+(g*i*Math.sin(l)),n=k-(g*i*Math.cos(l));this._0.fill=this.marker_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._f(20);this._0.stroke='transparent';this._0.font_weight='bold';var m=l/(2*Math.PI);switch(true){case m>=0.96||m<0.04:this._0.gravity='south';break;case m>=0.04&&m<0.21:this._0.gravity='west';break;case m>=0.21&&m<0.29:this._0.gravity='west';break;case m>=0.29&&m<0.46:this._0.gravity='west';break;case m>=0.46&&m<0.54:this._0.gravity='north';break;case m>=0.54&&m<0.71:this._0.gravity='east';break;case m>=0.71&&m<0.79:this._0.gravity='east';break;case m>=0.79&&m<0.96:this._0.gravity='east';break}this._0.annotate_scaled(0,0,o,n,h,this._c)}});Bluff.Pie=new JS.Class(Bluff.Base,{extend:{TEXT_OFFSET_PERCENTAGE:0.15},zero_degreee:null,initialize_ivars:function(){this.callSuper();this.zero_degree=0.0},draw:function(){this.hide_line_markers=true;this.callSuper();if(!this._9)return;var i=this._4,j=(Math.min(this._6,this._4)/2)*0.8,k=this._1+(this._6-i)/2,l=this._1+(this._6/2),o=this._7+(this._4/2)-10,n=this._1E(),m=this.zero_degree,p=this.klass.DATA_VALUES_INDEX;if(this.sort)this._2.sort(function(a,b){return a[p][0]-b[p][0]});Bluff.each(this._2,function(c,d){if(c[this.klass.DATA_VALUES_INDEX][0]>0){this._0.fill=c[this.klass.DATA_COLOR_INDEX];var f=(c[this.klass.DATA_VALUES_INDEX][0]/n)*360;this._0.circle(l,o,l+j,o,m,m+f+0.5);var g=m+((m+f)-m)/2;var h=Math.round((c[this.klass.DATA_VALUES_INDEX][0]/n)*100.0)+'%';this._d(l,o,g,j+(j*this.klass.TEXT_OFFSET_PERCENTAGE),h);m+=f}},this)},_d:function(c,d,f,g,h){var i=20.0,j=c,k=d,l=g+i,o=l*0.15,n=j+((l+o)*Math.cos(f*Math.PI/180)),m=k+(l*Math.sin(f*Math.PI/180));this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._f(this.marker_font_size);this._0.font_weight='bold';this._0.gravity='center';this._0.annotate_scaled(0,0,n,m,h,this._c)},_1E:function(){var d=0;Bluff.each(this._2,function(c){d+=c[this.klass.DATA_VALUES_INDEX][0]},this);return d}});Bluff.SideBar=new JS.Class(Bluff.Base,{draw:function(){this.has_left_labels=true;this.callSuper();if(!this._9)return;var p=0.9;this._E=this._4/this._5;this._8=this._E*p/this._a.length;this._0.stroke_opacity=0.0;var r=[],s=this._5;while(s--)r[s]=0;var q=[],u=this._5;while(u--)q[u]=this._1;var t=(this._E*(1-p))/2;Bluff.each(this._a,function(n,m){Bluff.each(n[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._6-c*this._6-r[d]),g=this._1+this._6-r[d],h=g-f,i=q[d]-1,j=this._7+(this._E*d)+(this._8*m)+t,k=i+h,l=j+this._8;r[d]+=(c*this._6);this._0.stroke='transparent';this._0.fill=n[this.klass.DATA_COLOR_INDEX];this._0.rectangle(i,j,k,l);var o=this._7+(this._E*d+this._E/2)+t;this._d(o,d)},this)},this)},_Y:function(){if(this.hide_line_markers)return;this._0.stroke_width=1;var c=5;var d=this._1c(this.maximum_value/c),f,g,h,i;for(var j=0;j<=c;j++){f=(this._o-this._1)/c;g=this._o-(f*j)-1;h=j-c;i=Math.abs(h)*d;this._0.stroke=this.marker_color;this._0.line(g,this._i,g,this._7);if(!this.hide_line_numbers){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.pointsize=this._f(this.marker_font_size);this._0.gravity='center';this._0.annotate_scaled(0,0,g,this._i+(this.klass.LABEL_MARGIN*2.0),i,this._c)}}},_d:function(c,d){if(this.labels[d]&&!this._y[d]){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.stroke='transparent';this._0.font_weight='normal';this._0.pointsize=this._f(this.marker_font_size);this._0.gravity='east';this._0.annotate_scaled(1,1,this._1-this.klass.LABEL_MARGIN*2.0,c,this.labels[d],this._c);this._y[d]=true}}});Bluff.Spider=new JS.Class(Bluff.Base,{hide_text:null,hide_axes:null,transparent_background:null,initialize:function(c,d,f){this.callSuper(c,f);this._1F=d;this.hide_legend=true},draw:function(){this.hide_line_markers=true;this.callSuper();if(!this._9)return;var c=this._4,d=this._4/2.0,f=this._1+(this._6-c)/2.0,g=this._1+(this._6/2.0),h=this._7+(this._4/2.0)-25;this._1G=d/this._1F;var i=this._1H(),j=0.0,k=(2*Math.PI)/this._2.length,l=0.0;if(!this.hide_axes)this._1I(g,h,d,k);this._1J(g,h,k)},_1f:function(c){return c*this._1G},_d:function(c,d,f,g,h){var i=50,j=c,k=d+0,l=j+((g+i)*Math.cos(f)),o=k+((g+i)*Math.sin(f));this._0.fill=this.marker_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._f(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='bold';this._0.gravity='center';this._0.annotate_scaled(0,0,l,o,h,this._c)},_1I:function(g,h,i,j,k){if(this.hide_axes)return;var l=0.0;Bluff.each(this._2,function(c){this._0.stroke=k||c[this.klass.DATA_COLOR_INDEX];this._0.stroke_width=5.0;var d=i*Math.cos(l);var f=i*Math.sin(l);this._0.line(g,h,g+d,h+f);if(!this.hide_text)this._d(g,h,l,i,c[this.klass.DATA_LABEL_INDEX]);l+=j},this)},_1J:function(d,f,g,h){var i=[],j=0.0;Bluff.each(this._2,function(c){i.push(d+this._1f(c[this.klass.DATA_VALUES_INDEX][0])*Math.cos(j));i.push(f+this._1f(c[this.klass.DATA_VALUES_INDEX][0])*Math.sin(j));j+=g},this);this._0.stroke_width=1.0;this._0.stroke=h||this.marker_color;this._0.fill=h||this.marker_color;this._0.fill_opacity=0.4;this._0.polyline(i)},_1H:function(){var d=0.0;Bluff.each(this._2,function(c){d+=c[this.klass.DATA_VALUES_INDEX][0]},this);return d}});Bluff.Base.StackedMixin=new JS.Module({_11:function(){var g={};Bluff.each(this._2,function(f){Bluff.each(f[this.klass.DATA_VALUES_INDEX],function(c,d){if(!g[d])g[d]=0.0;g[d]+=c},this)},this);for(var h in g){if(g[h]>this.maximum_value)this.maximum_value=g[h]}this.minimum_value=0}});Bluff.StackedArea=new JS.Class(Bluff.Base,{include:Bluff.Base.StackedMixin,last_series_goes_on_bottom:null,draw:function(){this._11();this.callSuper();if(!this._9)return;this._N=this._6/(this._5-1);this._0.stroke='transparent';var o=[],n=this._5;while(n--)o.push(0);var m=null;var p=this.last_series_goes_on_bottom?'reverse_each':'each';Bluff[p](this._a,function(h){var i=m;m=[];Bluff.each(h[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._N*d);var g=this._7+(this._4-c*this._4-o[d]);o[d]+=(c*this._4);m.push(f);m.push(g);this._d(f,d)},this);var j,k,l;if(i){j=Bluff.array(m);for(k=i.length/2-1;k>=0;k--){j.push(i[2*k]);j.push(i[2*k+1])}j.push(m[0]);j.push(m[1])}else{j=Bluff.array(m);j.push(this._o);j.push(this._i-1);j.push(this._1);j.push(this._i-1);j.push(m[0]);j.push(m[1])}this._0.fill=h[this.klass.DATA_COLOR_INDEX];this._0.polyline(j)},this)}});Bluff.StackedBar=new JS.Class(Bluff.Base,{include:Bluff.Base.StackedMixin,draw:function(){this._11();this.callSuper();if(!this._9)return;var o=0.9;this._8=this._6/this._5;var n=(this._8*(1-o))/2;var m=[],p=this._5;while(p--)m.push(0);Bluff.each(this._a,function(k,l){Bluff.each(k[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._8*d)+(this._8*o/2.0)+n;this._d(f,d);if(c==0)return;var g=this._1+(this._8*d)+n;var h=this._7+(this._4-c*this._4-m[d])+1;var i=g+this._8*o;var j=this._7+this._4-m[d]-1;m[d]+=(c*this._4);this._0.fill=k[this.klass.DATA_COLOR_INDEX];this._0.rectangle(g,h,i,j)},this)},this)}});Bluff.AccumulatorBar=new JS.Class(Bluff.StackedBar,{draw:function(){if(this._2.length!=1)throw'Incorrect number of datasets exception';var g=[];var h=0;var i=[];Bluff.each(this._2[0][this.klass.DATA_VALUES_INDEX],function(d){var f=-Infinity;Bluff.each(i,function(c){f=Math.max(f,c)});i.push((h>0)?(d+f):d);g.push(i[h]-d);h+=1},this);this.data("Accumulator",g);this.callSuper()}});Bluff.SideStackedBar=new JS.Class(Bluff.SideBar,{include:Bluff.Base.StackedMixin,draw:function(){this.has_left_labels=true;this._11();this.callSuper();if(!this._9)return;var p=0.9;this._8=this._4/this._5;var r=[],s=this._5,q=[],u=this._5,t=(this._8*(1-p))/2;while(s--)r.push(0);while(u--)q.push(this._1);Bluff.each(this._a,function(n,m){this._0.fill=n[this.klass.DATA_COLOR_INDEX];Bluff.each(n[this.klass.DATA_VALUES_INDEX],function(c,d){var f=this._1+(this._6-c*this._6-r[d])+1;var g=this._1+this._6-r[d]-1;var h=g-f;var i=q[d],j=this._7+(this._8*d)+t,k=i+h,l=j+this._8*p;q[d]+=h;r[d]+=(c*this._6-2);this._0.rectangle(i,j,k,l);var o=this._7+(this._8*d)+(this._8*p/2.0)+t;this._d(o,d)},this)},this)},_16:function(c,d){d=d||0;return this._1e(c,d)>this.maximum_value},_1e:function(d,f){var g=0;Bluff.each(this._2,function(c){g+=c[this.klass.DATA_VALUES_INDEX][f]},this);return g}});Bluff.Mini.Legend=new JS.Module({_12:function(){this._1K=this._J;this._x+=this._2.length*this._D(this._f(this.legend_font_size))*1.7;this._R()},_13:function(){this._t=[];Bluff.each(this._2,function(c){this._t.push(c[this.klass.DATA_LABEL_INDEX])},this);var f=40.0,g=10.0,h=100.0,i=40.0;if(this.font)this._0.font=this.font;this._0.pointsize=this.legend_font_size;var j=h,k=this._1K+i;this._s(function(){this._0.line(0.0,k,this._b,k)});Bluff.each(this._t,function(c,d){this._0.fill=this.font_color;if(this.font)this._0.font=this.font;this._0.pointsize=this._f(this.legend_font_size);this._0.stroke='transparent';this._0.font_weight='normal';this._0.gravity='west';this._0.annotate_scaled(this._b,1.0,j+(f*1.7),k,this._1L(c),this._c);this._0.stroke='transparent';this._0.fill=this._2[d][this.klass.DATA_COLOR_INDEX];this._0.rectangle(j,k-f/2.0,j+f,k+f/2.0);k+=this._D(this.legend_font_size)*1.7},this);this._l=0},_1L:function(c){var d=String(c);while(this._L(this._f(this.legend_font_size),d)>(this._j-this.legend_left_margin-this.right_margin)&&(d.length>1))d=d.substr(0,d.length-1);return d+(d.length<String(c).length?"…":'')}});Bluff.Mini.Bar=new JS.Class(Bluff.Bar,{include:Bluff.Mini.Legend,draw:function(){this.hide_legend=true;this.hide_title=true;this.hide_line_numbers=true;this.marker_font_size=50.0;this.minimum_value=0.0;this.legend_font_size=60.0;this._12();this.callSuper();this._13()}});Bluff.Mini.Pie=new JS.Class(Bluff.Pie,{include:Bluff.Mini.Legend,initialize_ivars:function(){this.callSuper();this.hide_legend=true;this.hide_title=true;this.hide_line_numbers=true;this.marker_font_size=60.0;this.legend_font_size=60.0},draw:function(){this._12();this.callSuper();this._13()}});Bluff.Mini.SideBar=new JS.Class(Bluff.SideBar,{include:Bluff.Mini.Legend,initialize_ivars:function(){this.callSuper();this.hide_legend=true;this.hide_title=true;this.hide_line_numbers=true;this.marker_font_size=50.0;this.legend_font_size=50.0},draw:function(){this._12();this.callSuper();this._13()}});Bluff.Renderer=new JS.Class({extend:{WRAPPER_CLASS:'bluff-wrapper',TEXT_CLASS:'bluff-text'},font:'Arial, Helvetica, Verdana, sans-serif',gravity:'north',initialize:function(c){this._p=document.getElementById(c);this._3=this._p.getContext('2d')},scale:function(c,d){this._g=c;this._h=d||c},caps_height:function(c){var d=this._P(c,'X'),f=this._F(d).height;this._Q(d);return f},text_width:function(c,d){var f=this._P(c,d);var g=this._F(f).width;this._Q(f);return g},get_type_metrics:function(c){var d=this._P(this.pointsize,c);var f=this._F(d);this._Q(d);return f},clear:function(c,d){this._p.width=c;this._p.height=d;this._3.clearRect(0,0,c,d);var f=this._1g(),g=f.childNodes,h=g.length;f.style.width=c+'px';f.style.height=d+'px';while(h--){if(g[h]&&g[h].className==this.klass.TEXT_CLASS)this._Q(g[h])}},push:function(){this._3.save()},pop:function(){this._3.restore()},render_gradiated_background:function(c,d,f,g){this.clear(c,d);var h=this._3.createLinearGradient(0,0,0,d);h.addColorStop(0,f);h.addColorStop(1,g);this._3.fillStyle=h;this._3.fillRect(0,0,c,d)},render_solid_background:function(c,d,f){this.clear(c,d);this._3.fillStyle=f;this._3.fillRect(0,0,c,d)},annotate_scaled:function(c,d,f,g,h,i){var j=(c*i)>=1?(c*i):1;var k=(d*i)>=1?(d*i):1;var h=this._P(this.pointsize,h);h.style.color=this.fill;h.style.fontWeight=this.font_weight;h.style.textAlign='center';h.style.left=(this._g*f+this._1M(h,j))+'px';h.style.top=(this._h*g+this._1N(h,k))+'px'},circle:function(c,d,f,g,h,i){var j=Math.sqrt(Math.pow(f-c,2)+Math.pow(g-d,2));this._3.fillStyle=this.fill;this._3.beginPath();var k=(h||0)*Math.PI/180;var l=(i||360)*Math.PI/180;if(h!==undefined&&i!==undefined){this._3.moveTo(this._g*(c+j*Math.cos(l)),this._h*(d+j*Math.sin(l)));this._3.lineTo(this._g*c,this._h*d);this._3.lineTo(this._g*(c+j*Math.cos(k)),this._h*(d+j*Math.sin(k)))}this._3.arc(this._g*c,this._h*d,this._g*j,k,l,false);this._3.fill()},line:function(c,d,f,g){this._3.strokeStyle=this.stroke;this._3.lineWidth=this.stroke_width;this._3.beginPath();this._3.moveTo(this._g*c,this._h*d);this._3.lineTo(this._g*f,this._h*g);this._3.stroke()},polyline:function(c){this._3.fillStyle=this.fill;this._3.globalAlpha=this.fill_opacity||1;try{this._3.strokeStyle=this.stroke}catch(e){}var d=c.shift(),f=c.shift();this._3.beginPath();this._3.moveTo(this._g*d,this._h*f);while(c.length>0){d=c.shift();f=c.shift();this._3.lineTo(this._g*d,this._h*f)}this._3.fill()},rectangle:function(c,d,f,g){var h;if(c>f){h=c;c=f;f=h}if(d>g){h=d;d=g;g=h}try{this._3.fillStyle=this.fill;this._3.fillRect(this._g*c,this._h*d,this._g*(f-c),this._h*(g-d))}catch(e){}try{this._3.strokeStyle=this.stroke;if(this.stroke!='transparent')this._3.strokeRect(this._g*c,this._h*d,this._g*(f-c),this._h*(g-d))}catch(e){}},_1M:function(c,d){var f=this._F(c).width;switch(this.gravity){case'west':return 0;case'east':return d-f;case'north':case'south':case'center':return(d-f)/2}},_1N:function(c,d){var f=this._F(c).height;switch(this.gravity){case'north':return 0;case'south':return d-f;case'west':case'east':case'center':return(d-f)/2}},_1g:function(){var c=this._p.parentNode;if(c.className==this.klass.WRAPPER_CLASS)return c;c=document.createElement('div');c.className=this.klass.WRAPPER_CLASS;c.style.position='relative';c.style.border='none';c.style.padding='0 0 0 0';this._p.parentNode.insertBefore(c,this._p);c.appendChild(this._p);return c},_P:function(c,d){var f=this._1O(d);f.style.fontFamily=this.font;f.style.fontSize=(typeof c=='number')?c+'px':c;return f},_1O:function(c){var d=document.createElement('div');d.className=this.klass.TEXT_CLASS;d.style.position='absolute';d.appendChild(document.createTextNode(c));this._1g().appendChild(d);return d},_Q:function(c){c.parentNode.removeChild(c)},_F:function(c){var d=c.style.display;return(d&&d!='none')?{width:c.offsetWidth,height:c.offsetHeight}:{width:c.clientWidth,height:c.clientHeight}}});Bluff.TableReader=new JS.Class({NUMBER_FORMAT:/\-?(0|[1-9]\d*)(\.\d+)?(e[\+\-]?\d+)?/i,initialize:function(c,d){this._1P=(typeof c=='string')?document.getElementById(c):c;this._1h=!!d},get_data:function(){if(!this._2)this._1i();return this._2},get_labels:function(){if(!this._14)this._1i();return this._14},get_title:function(){return this._1Q},get_series:function(c){if(this._2[c])return this._2[c];return this._2[c]={points:[]}},_1i:function(){this._G=this._m=0;this._H=this._I=0;this._2=[];this._14={};this._q=[];this._r=[];this._1j(this._1P);if((this._q.length>1&&this._r.length==1)||this._q.length<this._r.length){if(!this._1h)this._1k()}else{if(this._1h)this._1k()}Bluff.each(this._r,function(c,d){this.get_series(d-this._I).name=c},this);Bluff.each(this._q,function(c,d){this._14[d-this._H]=c},this)},_1j:function(c){this._1R(c);var d,f=c.childNodes,g=f.length;for(d=0;d<g;d++)this._1j(f[d])},_1R:function(c){if(!c.tagName)return;var d=this._1S(c.innerHTML),f,g;switch(c.tagName.toUpperCase()){case'TR':if(!this._9)this._H=this._G;this._G+=1;this._m=0;break;case'TD':if(!this._9)this._I=this._m;this._m+=1;d=parseFloat(d.match(this.NUMBER_FORMAT)[0]);if(typeof d=='number'){this._9=true;f=this._m-this._I-1;g=this._G-this._H-1;this.get_series(f).points[g]=parseFloat(d)}break;case'TH':this._m+=1;if(this._m==1&&this._G==1)this._q[0]=this._r[0]=d;else if(c.scope=="row"||this._m==1)this._q[this._G-1]=d;else this._r[this._m-1]=d;break;case'CAPTION':this._1Q=d;break}},_1k:function(){var h=this._2,i;this._2=[];Bluff.each(h,function(f,g){Bluff.each(f.points,function(c,d){this.get_series(d).points[g]=c},this)},this);i=this._q;this._q=this._r;this._r=i;i=this._H;this._H=this._I;this._I=i},_1S:function(c){return c.replace(/<\/?[^>]+>/gi,'')},extend:{Mixin:new JS.Module({data_from_table:function(d,f){var g=new Bluff.TableReader(d,f),h=g.get_data();Bluff.each(h,function(c){this.data(c.name,c.points)},this);this.labels=g.get_labels();this.title=g.get_title()||this.title}})}});Bluff.Base.include(Bluff.TableReader.Mixin);
@@ -0,0 +1,19 @@
1
+ if(!window.CanvasRenderingContext2D){(function(){var I=Math,i=I.round,L=I.sin,M=I.cos,m=10,A=m/2,Q={init:function(a){var b=a||document;if(/MSIE/.test(navigator.userAgent)&&!window.opera){var c=this;b.attachEvent("onreadystatechange",function(){c.r(b)})}},r:function(a){if(a.readyState=="complete"){if(!a.namespaces["s"]){a.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml")}var b=a.createStyleSheet();b.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}";
2
+ var c=a.getElementsByTagName("canvas");for(var d=0;d<c.length;d++){if(!c[d].getContext){this.initElement(c[d])}}}},q:function(a){var b=a.outerHTML,c=a.ownerDocument.createElement(b);if(b.slice(-2)!="/>"){var d="/"+a.tagName,e;while((e=a.nextSibling)&&e.tagName!=d){e.removeNode()}if(e){e.removeNode()}}a.parentNode.replaceChild(c,a);return c},initElement:function(a){a=this.q(a);a.getContext=function(){if(this.l){return this.l}return this.l=new K(this)};a.attachEvent("onpropertychange",V);a.attachEvent("onresize",
3
+ W);var b=a.attributes;if(b.width&&b.width.specified){a.style.width=b.width.nodeValue+"px"}else{a.width=a.clientWidth}if(b.height&&b.height.specified){a.style.height=b.height.nodeValue+"px"}else{a.height=a.clientHeight}return a}};function V(a){var b=a.srcElement;switch(a.propertyName){case "width":b.style.width=b.attributes.width.nodeValue+"px";b.getContext().clearRect();break;case "height":b.style.height=b.attributes.height.nodeValue+"px";b.getContext().clearRect();break}}function W(a){var b=a.srcElement;
4
+ if(b.firstChild){b.firstChild.style.width=b.clientWidth+"px";b.firstChild.style.height=b.clientHeight+"px"}}Q.init();var R=[];for(var E=0;E<16;E++){for(var F=0;F<16;F++){R[E*16+F]=E.toString(16)+F.toString(16)}}function J(){return[[1,0,0],[0,1,0],[0,0,1]]}function G(a,b){var c=J();for(var d=0;d<3;d++){for(var e=0;e<3;e++){var g=0;for(var h=0;h<3;h++){g+=a[d][h]*b[h][e]}c[d][e]=g}}return c}function N(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=
5
+ a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX=a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.d=a.d;b.e=a.e}function O(a){var b,c=1;a=String(a);if(a.substring(0,3)=="rgb"){var d=a.indexOf("(",3),e=a.indexOf(")",d+1),g=a.substring(d+1,e).split(",");b="#";for(var h=0;h<3;h++){b+=R[Number(g[h])]}if(g.length==4&&a.substr(3,1)=="a"){c=g[3]}}else{b=a}return[b,c]}function S(a){switch(a){case "butt":return"flat";case "round":return"round";
6
+ case "square":default:return"square"}}function K(a){this.a=J();this.m=[];this.k=[];this.c=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=m*1;this.globalAlpha=1;this.canvas=a;var b=a.ownerDocument.createElement("div");b.style.width=a.clientWidth+"px";b.style.height=a.clientHeight+"px";b.style.overflow="hidden";b.style.position="absolute";a.appendChild(b);this.j=b;this.d=1;this.e=1}var j=K.prototype;j.clearRect=function(){this.j.innerHTML=
7
+ "";this.c=[]};j.beginPath=function(){this.c=[]};j.moveTo=function(a,b){this.c.push({type:"moveTo",x:a,y:b});this.f=a;this.g=b};j.lineTo=function(a,b){this.c.push({type:"lineTo",x:a,y:b});this.f=a;this.g=b};j.bezierCurveTo=function(a,b,c,d,e,g){this.c.push({type:"bezierCurveTo",cp1x:a,cp1y:b,cp2x:c,cp2y:d,x:e,y:g});this.f=e;this.g=g};j.quadraticCurveTo=function(a,b,c,d){var e=this.f+0.6666666666666666*(a-this.f),g=this.g+0.6666666666666666*(b-this.g),h=e+(c-this.f)/3,l=g+(d-this.g)/3;this.bezierCurveTo(e,
8
+ g,h,l,c,d)};j.arc=function(a,b,c,d,e,g){c*=m;var h=g?"at":"wa",l=a+M(d)*c-A,n=b+L(d)*c-A,o=a+M(e)*c-A,f=b+L(e)*c-A;if(l==o&&!g){l+=0.125}this.c.push({type:h,x:a,y:b,radius:c,xStart:l,yStart:n,xEnd:o,yEnd:f})};j.rect=function(a,b,c,d){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath()};j.strokeRect=function(a,b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.stroke()};j.fillRect=function(a,
9
+ b,c,d){this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+d);this.lineTo(a,b+d);this.closePath();this.fill()};j.createLinearGradient=function(a,b,c,d){var e=new H("gradient");return e};j.createRadialGradient=function(a,b,c,d,e,g){var h=new H("gradientradial");h.n=c;h.o=g;h.i.x=a;h.i.y=b;return h};j.drawImage=function(a,b){var c,d,e,g,h,l,n,o,f=a.runtimeStyle.width,k=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var q=a.width,r=a.height;a.runtimeStyle.width=
10
+ f;a.runtimeStyle.height=k;if(arguments.length==3){c=arguments[1];d=arguments[2];h=(l=0);n=(e=q);o=(g=r)}else if(arguments.length==5){c=arguments[1];d=arguments[2];e=arguments[3];g=arguments[4];h=(l=0);n=q;o=r}else if(arguments.length==9){h=arguments[1];l=arguments[2];n=arguments[3];o=arguments[4];c=arguments[5];d=arguments[6];e=arguments[7];g=arguments[8]}else{throw"Invalid number of arguments";}var s=this.b(c,d),t=[],v=10,w=10;t.push(" <g_vml_:group",' coordsize="',m*v,",",m*w,'"',' coordorigin="0,0"',
11
+ ' style="width:',v,";height:",w,";position:absolute;");if(this.a[0][0]!=1||this.a[0][1]){var x=[];x.push("M11='",this.a[0][0],"',","M12='",this.a[1][0],"',","M21='",this.a[0][1],"',","M22='",this.a[1][1],"',","Dx='",i(s.x/m),"',","Dy='",i(s.y/m),"'");var p=s,y=this.b(c+e,d),z=this.b(c,d+g),B=this.b(c+e,d+g);p.x=Math.max(p.x,y.x,z.x,B.x);p.y=Math.max(p.y,y.y,z.y,B.y);t.push("padding:0 ",i(p.x/m),"px ",i(p.y/m),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",x.join(""),", sizingmethod='clip');")}else{t.push("top:",
12
+ i(s.y/m),"px;left:",i(s.x/m),"px;")}t.push(' ">','<g_vml_:image src="',a.src,'"',' style="width:',m*e,";"," height:",m*g,';"',' cropleft="',h/q,'"',' croptop="',l/r,'"',' cropright="',(q-h-n)/q,'"',' cropbottom="',(r-l-o)/r,'"'," />","</g_vml_:group>");this.j.insertAdjacentHTML("BeforeEnd",t.join(""))};j.stroke=function(a){var b=[],c=O(a?this.fillStyle:this.strokeStyle),d=c[0],e=c[1]*this.globalAlpha,g=10,h=10;b.push("<g_vml_:shape",' fillcolor="',d,'"',' filled="',Boolean(a),'"',' style="position:absolute;width:',
13
+ g,";height:",h,';"',' coordorigin="0 0" coordsize="',m*g," ",m*h,'"',' stroked="',!a,'"',' strokeweight="',this.lineWidth,'"',' strokecolor="',d,'"',' path="');var l={x:null,y:null},n={x:null,y:null};for(var o=0;o<this.c.length;o++){var f=this.c[o];if(f.type=="moveTo"){b.push(" m ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="lineTo"){b.push(" l ");var k=this.b(f.x,f.y);b.push(i(k.x),",",i(k.y))}else if(f.type=="close"){b.push(" x ")}else if(f.type=="bezierCurveTo"){b.push(" c ");
14
+ var k=this.b(f.x,f.y),q=this.b(f.cp1x,f.cp1y),r=this.b(f.cp2x,f.cp2y);b.push(i(q.x),",",i(q.y),",",i(r.x),",",i(r.y),",",i(k.x),",",i(k.y))}else if(f.type=="at"||f.type=="wa"){b.push(" ",f.type," ");var k=this.b(f.x,f.y),s=this.b(f.xStart,f.yStart),t=this.b(f.xEnd,f.yEnd);b.push(i(k.x-this.d*f.radius),",",i(k.y-this.e*f.radius)," ",i(k.x+this.d*f.radius),",",i(k.y+this.e*f.radius)," ",i(s.x),",",i(s.y)," ",i(t.x),",",i(t.y))}if(k){if(l.x==null||k.x<l.x){l.x=k.x}if(n.x==null||k.x>n.x){n.x=k.x}if(l.y==
15
+ null||k.y<l.y){l.y=k.y}if(n.y==null||k.y>n.y){n.y=k.y}}}b.push(' ">');if(typeof this.fillStyle=="object"){var v={x:"50%",y:"50%"},w=n.x-l.x,x=n.y-l.y,p=w>x?w:x;v.x=i(this.fillStyle.i.x/w*100+50)+"%";v.y=i(this.fillStyle.i.y/x*100+50)+"%";var y=[];if(this.fillStyle.p=="gradientradial"){var z=this.fillStyle.n/p*100,B=this.fillStyle.o/p*100-z}else{var z=0,B=100}var C={offset:null,color:null},D={offset:null,color:null};this.fillStyle.h.sort(function(T,U){return T.offset-U.offset});for(var o=0;o<this.fillStyle.h.length;o++){var u=
16
+ this.fillStyle.h[o];y.push(u.offset*B+z,"% ",u.color,",");if(u.offset>C.offset||C.offset==null){C.offset=u.offset;C.color=u.color}if(u.offset<D.offset||D.offset==null){D.offset=u.offset;D.color=u.color}}y.pop();b.push("<g_vml_:fill",' color="',D.color,'"',' color2="',C.color,'"',' type="',this.fillStyle.p,'"',' focusposition="',v.x,", ",v.y,'"',' colors="',y.join(""),'"',' opacity="',e,'" />')}else if(a){b.push('<g_vml_:fill color="',d,'" opacity="',e,'" />')}else{b.push("<g_vml_:stroke",' opacity="',
17
+ e,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',S(this.lineCap),'"',' weight="',this.lineWidth,'px"',' color="',d,'" />')}b.push("</g_vml_:shape>");this.j.insertAdjacentHTML("beforeEnd",b.join(""));this.c=[]};j.fill=function(){this.stroke(true)};j.closePath=function(){this.c.push({type:"close"})};j.b=function(a,b){return{x:m*(a*this.a[0][0]+b*this.a[1][0]+this.a[2][0])-A,y:m*(a*this.a[0][1]+b*this.a[1][1]+this.a[2][1])-A}};j.save=function(){var a={};N(this,a);
18
+ this.k.push(a);this.m.push(this.a);this.a=G(J(),this.a)};j.restore=function(){N(this.k.pop(),this);this.a=this.m.pop()};j.translate=function(a,b){var c=[[1,0,0],[0,1,0],[a,b,1]];this.a=G(c,this.a)};j.rotate=function(a){var b=M(a),c=L(a),d=[[b,c,0],[-c,b,0],[0,0,1]];this.a=G(d,this.a)};j.scale=function(a,b){this.d*=a;this.e*=b;var c=[[a,0,0],[0,b,0],[0,0,1]];this.a=G(c,this.a)};j.clip=function(){};j.arcTo=function(){};j.createPattern=function(){return new P};function H(a){this.p=a;this.n=0;this.o=
19
+ 0;this.h=[];this.i={x:0,y:0}}H.prototype.addColorStop=function(a,b){b=O(b);this.h.push({offset:1-a,color:b})};function P(){}G_vmlCanvasManager=Q;CanvasRenderingContext2D=K;CanvasGradient=H;CanvasPattern=P})()};
@@ -0,0 +1 @@
1
+ JS={extend:function(a,b){b=b||{};for(var c in b){if(a[c]===b[c])continue;a[c]=b[c]}return a},makeFunction:function(){return function(){return this.initialize?(this.initialize.apply(this,arguments)||this):this}},makeBridge:function(a){var b=function(){};b.prototype=a.prototype;return new b},delegate:function(a,b){return function(){return this[a][b].apply(this[a],arguments)}},bind:function(){var a=JS.array(arguments),b=a.shift(),c=a.shift()||null;return function(){return b.apply(c,a.concat(JS.array(arguments)))}},callsSuper:function(a){return a.SUPER===undefined?a.SUPER=/\bcallSuper\b/.test(a.toString()):a.SUPER},mask:function(a){var b=a.toString().replace(/callSuper/g,'super');a.toString=function(){return b};return a},array:function(a){if(!a)return[];if(a.toArray)return a.toArray();var b=a.length,c=[];while(b--)c[b]=a[b];return c},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},isFn:function(a){return a instanceof Function},ignore:function(a,b){return/^(include|extend)$/.test(a)&&typeof b==='object'}};JS.Module=JS.makeFunction();JS.extend(JS.Module.prototype,{initialize:function(a,b){b=b||{};this.__mod__=this;this.__inc__=[];this.__fns__={};this.__dep__=[];this.__res__=b._1||null;this.include(a||{})},define:function(a,b,c){c=c||{};this.__fns__[a]=b;if(JS.Module._0&&c._0&&JS.isFn(b))JS.Module._0(a,c._0);var d=this.__dep__.length;while(d--)this.__dep__[d].resolve()},instanceMethod:function(a){var b=this.lookup(a).pop();return JS.isFn(b)?b:null},include:function(a,b,c){if(!a)return c&&this.resolve();b=b||{};var d=a.include,f=a.extend,e,g,j,h,i=b._4||this;if(a.__inc__&&a.__fns__){this.__inc__.push(a);a.__dep__.push(this);if(b._2)a.extended&&a.extended(b._2);else a.included&&a.included(i)}else{if(b._5){for(h in a){if(JS.ignore(h,a[h]))continue;this.define(h,a[h],{_0:i||b._2||this})}}else{if(typeof d==='object'){e=[].concat(d);for(g=0,j=e.length;g<j;g++)i.include(e[g],b)}if(typeof f==='object'){e=[].concat(f);for(g=0,j=e.length;g<j;g++)i.extend(e[g],false);i.extend()}b._5=true;return i.include(a,b,c)}}c&&this.resolve()},includes:function(a){if(Object===a||this===a||this.__res__===a.prototype)return true;var b=this.__inc__.length;while(b--){if(this.__inc__[b].includes(a))return true}return false},ancestors:function(a){a=a||[];for(var b=0,c=this.__inc__.length;b<c;b++)this.__inc__[b].ancestors(a);var d=(this.__res__||{}).klass,f=(d&&this.__res__===d.prototype)?d:this;if(JS.indexOf(a,f)===-1)a.push(f);return a},lookup:function(a){var b=this.ancestors(),c=[],d,f,e;for(d=0,f=b.length;d<f;d++){e=b[d].__mod__.__fns__[a];if(e)c.push(e)}return c},make:function(a,b){if(!JS.isFn(b)||!JS.callsSuper(b))return b;var c=this;return function(){return c.chain(this,a,arguments)}},chain:JS.mask(function(c,d,f){var e=this.lookup(d),g=e.length-1,j=c.callSuper,h=JS.array(f),i;c.callSuper=function(){var a=arguments.length;while(a--)h[a]=arguments[a];g-=1;var b=e[g].apply(c,h);g+=1;return b};i=e.pop().apply(c,h);j?c.callSuper=j:delete c.callSuper;return i}),resolve:function(a){var a=a||this,b=a.__res__,c,d,f,e;if(a===this){c=this.__dep__.length;while(c--)this.__dep__[c].resolve()}if(!b)return;for(c=0,d=this.__inc__.length;c<d;c++)this.__inc__[c].resolve(a);for(f in this.__fns__){e=a.make(f,this.__fns__[f]);if(b[f]!==e)b[f]=e}}});JS.ObjectMethods=new JS.Module({__eigen__:function(){if(this.__meta__)return this.__meta__;var a=this.__meta__=new JS.Module({},{_1:this});a.include(this.klass.__mod__);return a},extend:function(a,b){return this.__eigen__().include(a,{_2:this},b!==false)},isA:function(a){return this.__eigen__().includes(a)},method:function(a){var b=this,c=b.__mcache__=b.__mcache__||{};if((c[a]||{}).fn===b[a])return c[a].bd;return(c[a]={fn:b[a],bd:JS.bind(b[a],b)}).bd}});JS.Class=JS.makeFunction();JS.extend(JS.Class.prototype=JS.makeBridge(JS.Module),{initialize:function(a,b){var c=JS.extend(JS.makeFunction(),this);c.klass=c.constructor=this.klass;if(!JS.isFn(a)){b=a;a=Object}c.inherit(a);c.include(b,null,false);c.resolve();do{a.inherited&&a.inherited(c)}while(a=a.superclass);return c},inherit:function(a){this.superclass=a;if(this.__eigen__){this.__eigen__().include(a.__eigen__?a.__eigen__():new JS.Module(a.prototype));this.__meta__.resolve()}this.subclasses=[];(a.subclasses||[]).push(this);var b=this.prototype=JS.makeBridge(a);b.klass=b.constructor=this;this.__mod__=new JS.Module({},{_1:this.prototype});this.include(JS.ObjectMethods,null,false);if(a!==Object)this.include(a.__mod__||new JS.Module(a.prototype,{_1:a.prototype}),null,false)},include:function(a,b,c){if(!a)return;var d=this.__mod__,b=b||{};b._4=this;return d.include(a,b,c!==false)},extend:function(a){if(!this.callSuper)return;this.callSuper();var b=this.subclasses.length;while(b--)this.subclasses[b].extend()},define:function(){var a=this.__mod__;a.define.apply(a,arguments);a.resolve()},includes:JS.delegate('__mod__','includes'),ancestors:JS.delegate('__mod__','ancestors'),resolve:JS.delegate('__mod__','resolve')});JS.Module=JS.extend(new JS.Class(JS.Module.prototype),JS.ObjectMethods.__fns__);JS.Module.include(JS.ObjectMethods);JS.Class=JS.extend(new JS.Class(JS.Module,JS.Class.prototype),JS.ObjectMethods.__fns__);JS.Module.klass=JS.Module.constructor=JS.Class.klass=JS.Class.constructor=JS.Class;JS.Module.extend({_3:[],methodAdded:function(a,b){this._3.push([a,b])},_0:function(a,b){var c=this._3,d=c.length;while(d--)c[d][0].call(c[d][1]||null,a,b)}});JS.extend(JS,{Interface:new JS.Class({initialize:function(d){this.test=function(a,b){var c=d.length;while(c--){if(!JS.isFn(a[d[c]]))return b?d[c]:false}return true}},extend:{ensure:function(){var a=JS.array(arguments),b=a.shift(),c,d;while(c=a.shift()){d=c.test(b,true);if(d!==true)throw new Error('object does not implement '+d+'()');}}}}),Singleton:new JS.Class({initialize:function(a,b){return new(new JS.Class(a,b))}})});
@@ -153,37 +153,6 @@ describe MetricFu::Configuration do
153
153
  :formater => "text"}
154
154
  end
155
155
 
156
- it 'should set @graph_theme to {
157
- :colors => %w(orange purple green white red blue pink yellow),
158
- :marker_color => "blue",
159
- :background_colors => %w(white white)}' do
160
- @config.instance_variable_get(:@graph_theme).
161
- should == { :colors => %w(orange purple green white red blue pink yellow),
162
- :marker_color => "blue",
163
- :background_colors => %w(white white) }
164
- end
165
-
166
- it 'should set @graph_font to the path to the font directory' do
167
- @config.instance_variable_get(:@graph_font).
168
- should include(File.join('vendor', '_fonts', 'monaco.ttf'))
169
- end
170
-
171
- it 'should set @graph_title_font_size to 12' do
172
- @config.instance_variable_get(:@graph_title_font_size).should eql(12)
173
- end
174
-
175
- it 'should set @graph_legend_box_size to 12' do
176
- @config.instance_variable_get(:@graph_legend_box_size).should eql(12)
177
- end
178
-
179
- it 'should set @graph_legend_box_size to 10' do
180
- @config.instance_variable_get(:@graph_legend_font_size).should eql(10)
181
- end
182
-
183
- it 'should set @graph_marker_font_size to 10' do
184
- @config.instance_variable_get(:@graph_marker_font_size).should eql(10)
185
- end
186
-
187
156
  describe 'if #rails? is true ' do
188
157
  before(:each) do
189
158
  @config.stub!(:rails?).and_return(true)
@@ -15,10 +15,10 @@ describe MetricFu::Graph do
15
15
  @graph = MetricFu::Graph.new
16
16
  end
17
17
 
18
- describe "responding to #add" do
18
+ describe "responding to #add with gchart enabled" do
19
19
  it 'should instantiate a grapher and push it to clazz' do
20
- @graph.clazz.should_receive(:push).with(an_instance_of(RcovGrapher))
21
- @graph.add("rcov")
20
+ @graph.clazz.should_receive(:push).with(an_instance_of(RcovGchartGrapher))
21
+ @graph.add("rcov", 'gchart')
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe "Bluff graphers responding to #graph!" do
4
+ it "should write chart file" do
5
+ MetricFu.configuration
6
+ graphs = {}
7
+ MetricFu::AVAILABLE_GRAPHS.each do |graph|
8
+ graphs[graph] = MetricFu.const_get("#{graph.to_s.capitalize}BluffGrapher").new
9
+ end
10
+ graphs.each do |key, val|
11
+ val.graph!
12
+ lambda{ File.open(File.join(MetricFu.output_directory, "#{key.to_s.downcase}.js")) }.should_not raise_error
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ describe "Gchart graphers responding to #graph!" do
4
+ MetricFu::AVAILABLE_GRAPHS.each do |metric|
5
+ it "should write chart file for #{metric}" do
6
+ MetricFu.configuration
7
+ grapher = MetricFu.const_get("#{metric.to_s.capitalize}GchartGrapher").new
8
+ grapher.flog_average, grapher.top_five_percent_average = [7.0],[20.0] if metric == :flog #googlecharts gem has problems with [[],[]] as data
9
+ grapher.graph!
10
+ lambda{ File.open(File.join(MetricFu.output_directory, "#{metric.to_s.downcase}.png")) }.should_not raise_error
11
+ end
12
+ end
13
+ end
@@ -21,7 +21,7 @@ describe FlayGrapher do
21
21
  describe "responding to #get_metrics" do
22
22
  before(:each) do
23
23
  @metrics = YAML::load(File.open(File.join(File.dirname(__FILE__), "..", "resources", "yml", "20090630.yml")))
24
- @date = "01022003"
24
+ @date = "1/2"
25
25
  end
26
26
 
27
27
  it "should push 476 to flay_score" do
@@ -30,15 +30,8 @@ describe FlayGrapher do
30
30
  end
31
31
 
32
32
  it "should update labels with the date" do
33
- @flay_grapher.labels.should_receive(:update).with({ 0 => "01022003" })
33
+ @flay_grapher.labels.should_receive(:update).with({ 0 => "1/2" })
34
34
  @flay_grapher.get_metrics(@metrics, @date)
35
35
  end
36
36
  end
37
-
38
- describe "responding to #graph!" do
39
- it "should write flay.png" do
40
- @flay_grapher.graph!
41
- lambda{ File.open(File.join(MetricFu.output_directory, 'flay.png')) }.should_not raise_error
42
- end
43
- end
44
37
  end
@@ -23,7 +23,7 @@ describe MetricFu::FlogGrapher do
23
23
  describe "responding to #get_metrics" do
24
24
  before(:each) do
25
25
  @metrics = YAML::load(File.open(File.join(File.dirname(__FILE__), "..", "resources", "yml", "20090630.yml")))
26
- @date = "01022003"
26
+ @date = "1/2"
27
27
  end
28
28
 
29
29
  it "should push to top_five_percent_average" do
@@ -38,24 +38,8 @@ describe MetricFu::FlogGrapher do
38
38
  end
39
39
 
40
40
  it "should update labels with the date" do
41
- @flog_grapher.labels.should_receive(:update).with({ 0 => "01022003" })
41
+ @flog_grapher.labels.should_receive(:update).with({ 0 => "1/2" })
42
42
  @flog_grapher.get_metrics(@metrics, @date)
43
43
  end
44
44
  end
45
-
46
- describe "responding to #graph!" do
47
- it "should write flog.png" do
48
- @flog_grapher.graph!
49
- lambda{ File.open(File.join(MetricFu.output_directory, 'flog.png')) }.should_not raise_error
50
- end
51
-
52
- it "should not fall over when given empty results" do
53
- gruff_line = Gruff::Line.new(MetricFu.graph_size)
54
- gruff_line.stub!(:write)
55
- Gruff::Line.stub!(:new).and_return(gruff_line)
56
- metrics_hash = { :flog => {:average => 0, :pages => [], :total => 0} }
57
- @flog_grapher.get_metrics(metrics_hash ,"20090629")
58
- @flog_grapher.graph!
59
- end
60
- end
61
45
  end
@@ -21,7 +21,7 @@ describe RcovGrapher do
21
21
  describe "responding to #get_metrics" do
22
22
  before(:each) do
23
23
  @metrics = YAML::load(File.open(File.join(File.dirname(__FILE__), "..", "resources", "yml", "20090630.yml")))
24
- @date = "01022003"
24
+ @date = "1/2"
25
25
  end
26
26
 
27
27
  it "should push 49.6 to rcov_percent" do
@@ -30,15 +30,8 @@ describe RcovGrapher do
30
30
  end
31
31
 
32
32
  it "should update labels with the date" do
33
- @rcov_grapher.labels.should_receive(:update).with({ 0 => "01022003" })
33
+ @rcov_grapher.labels.should_receive(:update).with({ 0 => "1/2" })
34
34
  @rcov_grapher.get_metrics(@metrics, @date)
35
35
  end
36
36
  end
37
-
38
- describe "responding to #graph!" do
39
- it "should write rcov.png" do
40
- @rcov_grapher.graph!
41
- lambda{ File.open(File.join(MetricFu.output_directory, 'rcov.png')) }.should_not raise_error
42
- end
43
- end
44
37
  end
@@ -21,7 +21,7 @@ describe ReekGrapher do
21
21
  describe "responding to #get_metrics" do
22
22
  before(:each) do
23
23
  @metrics = YAML::load(File.open(File.join(File.dirname(__FILE__), "..", "resources", "yml", "20090630.yml")))
24
- @date = "01022003"
24
+ @date = "1/2"
25
25
  end
26
26
 
27
27
  it "should set a hash of code smells to reek_count" do
@@ -39,15 +39,8 @@ describe ReekGrapher do
39
39
  end
40
40
 
41
41
  it "should update labels with the date" do
42
- @reek_grapher.labels.should_receive(:update).with({ 0 => "01022003" })
42
+ @reek_grapher.labels.should_receive(:update).with({ 0 => "1/2" })
43
43
  @reek_grapher.get_metrics(@metrics, @date)
44
44
  end
45
45
  end
46
-
47
- describe "responding to #graph!" do
48
- it "should write reek.png" do
49
- @reek_grapher.graph!
50
- lambda{ File.open(File.join(MetricFu.output_directory, 'reek.png')) }.should_not raise_error
51
- end
52
- end
53
46
  end
@@ -21,7 +21,7 @@ describe RoodiGrapher do
21
21
  describe "responding to #get_metrics" do
22
22
  before(:each) do
23
23
  @metrics = YAML::load(File.open(File.join(File.dirname(__FILE__), "..", "resources", "yml", "20090630.yml")))
24
- @date = "01022003"
24
+ @date = "1/2"
25
25
  end
26
26
 
27
27
  it "should push 13 to roodi_count" do
@@ -30,15 +30,8 @@ describe RoodiGrapher do
30
30
  end
31
31
 
32
32
  it "should update labels with the date" do
33
- @roodi_grapher.labels.should_receive(:update).with({ 0 => "01022003" })
33
+ @roodi_grapher.labels.should_receive(:update).with({ 0 => "1/2" })
34
34
  @roodi_grapher.get_metrics(@metrics, @date)
35
35
  end
36
36
  end
37
-
38
- describe "responding to #graph!" do
39
- it "should write rcov.png" do
40
- @roodi_grapher.graph!
41
- lambda{ File.open(File.join(MetricFu.output_directory, 'roodi.png')) }.should_not raise_error
42
- end
43
- end
44
37
  end
data/tasks/metric_fu.rake CHANGED
@@ -12,7 +12,7 @@ namespace :metrics do
12
12
  "#{Time.now.strftime("%Y%m%d")}.yml")
13
13
  MetricFu.report.save_templatized_report
14
14
 
15
- MetricFu.graphs.each {|graph| MetricFu.graph.add(graph) }
15
+ MetricFu.graphs.each {|graph| MetricFu.graph.add(graph, MetricFu.graph_engine) }
16
16
  MetricFu.graph.generate
17
17
 
18
18
  if MetricFu.report.open_in_browser?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metric_fu
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jake Scruggs
@@ -11,11 +11,12 @@ authors:
11
11
  - Grant McInnes
12
12
  - Nick Quaranto
13
13
  - "\xC3\x89douard Bri\xC3\xA8re"
14
+ - Carl Youngblood
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2009-12-14 00:00:00 -06:00
19
+ date: 2010-01-09 00:00:00 -06:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
@@ -39,7 +40,7 @@ dependencies:
39
40
  version: 2.2.0
40
41
  version:
41
42
  - !ruby/object:Gem::Dependency
42
- name: relevance-rcov
43
+ name: rcov
43
44
  type: :runtime
44
45
  version_requirement:
45
46
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,14 +50,14 @@ dependencies:
49
50
  version: 0.8.3.3
50
51
  version:
51
52
  - !ruby/object:Gem::Dependency
52
- name: mojombo-chronic
53
+ name: chronic
53
54
  type: :runtime
54
55
  version_requirement:
55
56
  version_requirements: !ruby/object:Gem::Requirement
56
57
  requirements:
57
58
  - - ">="
58
59
  - !ruby/object:Gem::Version
59
- version: 0.3.0
60
+ version: 0.2.3
60
61
  version:
61
62
  description: Code metrics from Flog, Flay, RCov, Saikuro, Churn, Reek, Roodi and Rails' stats task
62
63
  email: jake.scruggs@gmail.com
@@ -88,6 +89,8 @@ files:
88
89
  - lib/generators/roodi.rb
89
90
  - lib/generators/saikuro.rb
90
91
  - lib/generators/stats.rb
92
+ - lib/graphs/engines/bluff.rb
93
+ - lib/graphs/engines/gchart.rb
91
94
  - lib/graphs/flay_grapher.rb
92
95
  - lib/graphs/flog_grapher.rb
93
96
  - lib/graphs/grapher.rb
@@ -110,6 +113,9 @@ files:
110
113
  - lib/templates/awesome/roodi.html.erb
111
114
  - lib/templates/awesome/saikuro.html.erb
112
115
  - lib/templates/awesome/stats.html.erb
116
+ - lib/templates/javascripts/bluff-min.js
117
+ - lib/templates/javascripts/excanvas.js
118
+ - lib/templates/javascripts/js-class.js
113
119
  - lib/templates/standard/churn.html.erb
114
120
  - lib/templates/standard/default.css
115
121
  - lib/templates/standard/flay.html.erb
@@ -167,9 +173,10 @@ test_files:
167
173
  - spec/generators/reek_spec.rb
168
174
  - spec/generators/saikuro_spec.rb
169
175
  - spec/generators/stats_spec.rb
176
+ - spec/graphs/engines/bluff_spec.rb
177
+ - spec/graphs/engines/gchart_spec.rb
170
178
  - spec/graphs/flay_grapher_spec.rb
171
179
  - spec/graphs/flog_grapher_spec.rb
172
- - spec/graphs/grapher_spec.rb
173
180
  - spec/graphs/rcov_grapher_spec.rb
174
181
  - spec/graphs/reek_grapher_spec.rb
175
182
  - spec/graphs/roodi_grapher_spec.rb
@@ -1,9 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
-
3
- describe Grapher do
4
- it "should blow up if gruff is not availible" do
5
- Grapher.should_receive(:require).and_raise(LoadError)
6
- Grapher.should_receive(:puts).with(/config\.graphs/)
7
- lambda {Grapher.new}.should raise_error(LoadError)
8
- end
9
- end