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 +11 -0
- data/lib/base/base_template.rb +1 -2
- data/lib/base/configuration.rb +2 -12
- data/lib/base/graph.rb +4 -3
- data/lib/graphs/engines/bluff.rb +85 -0
- data/lib/graphs/engines/gchart.rb +119 -0
- data/lib/graphs/flay_grapher.rb +4 -19
- data/lib/graphs/flog_grapher.rb +13 -24
- data/lib/graphs/grapher.rb +3 -11
- data/lib/graphs/rcov_grapher.rb +0 -14
- data/lib/graphs/reek_grapher.rb +10 -22
- data/lib/graphs/roodi_grapher.rb +4 -18
- data/lib/metric_fu.rb +5 -4
- data/lib/templates/awesome/awesome_template.rb +7 -0
- data/lib/templates/awesome/flay.html.erb +7 -1
- data/lib/templates/awesome/flog.html.erb +7 -1
- data/lib/templates/awesome/layout.html.erb +3 -0
- data/lib/templates/awesome/rcov.html.erb +7 -1
- data/lib/templates/awesome/reek.html.erb +7 -1
- data/lib/templates/awesome/roodi.html.erb +7 -1
- data/lib/templates/javascripts/bluff-min.js +1 -0
- data/lib/templates/javascripts/excanvas.js +19 -0
- data/lib/templates/javascripts/js-class.js +1 -0
- data/spec/base/configuration_spec.rb +0 -31
- data/spec/base/graph_spec.rb +3 -3
- data/spec/graphs/engines/bluff_spec.rb +15 -0
- data/spec/graphs/engines/gchart_spec.rb +13 -0
- data/spec/graphs/flay_grapher_spec.rb +2 -9
- data/spec/graphs/flog_grapher_spec.rb +2 -18
- data/spec/graphs/rcov_grapher_spec.rb +2 -9
- data/spec/graphs/reek_grapher_spec.rb +2 -9
- data/spec/graphs/roodi_grapher_spec.rb +2 -9
- data/tasks/metric_fu.rake +1 -1
- metadata +13 -6
- data/spec/graphs/grapher_spec.rb +0 -9
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
|
data/lib/base/base_template.rb
CHANGED
data/lib/base/configuration.rb
CHANGED
@@ -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
|
-
@
|
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,
|
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
|
data/lib/graphs/flay_grapher.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
9
|
+
@flay_score = []
|
10
|
+
@labels = {}
|
12
11
|
end
|
13
12
|
|
14
13
|
def get_metrics(metrics, date)
|
15
|
-
|
16
|
-
|
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
|
data/lib/graphs/flog_grapher.rb
CHANGED
@@ -6,30 +6,15 @@ module MetricFu
|
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
super
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
@flog_average = []
|
10
|
+
@labels = {}
|
11
|
+
@top_five_percent_average =[]
|
12
12
|
end
|
13
13
|
|
14
14
|
def get_metrics(metrics, date)
|
15
|
-
|
16
|
-
|
17
|
-
|
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 =
|
46
|
-
|
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
|
data/lib/graphs/grapher.rb
CHANGED
@@ -1,19 +1,11 @@
|
|
1
1
|
module MetricFu
|
2
2
|
class Grapher
|
3
3
|
def initialize
|
4
|
-
self.class.
|
4
|
+
self.class.require_graphing_gem
|
5
5
|
end
|
6
6
|
|
7
|
-
def self.
|
8
|
-
|
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
|
data/lib/graphs/rcov_grapher.rb
CHANGED
@@ -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
|
data/lib/graphs/reek_grapher.rb
CHANGED
@@ -6,39 +6,27 @@ module MetricFu
|
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
super
|
9
|
-
|
10
|
-
|
9
|
+
@reek_count = {}
|
10
|
+
@labels = {}
|
11
11
|
end
|
12
12
|
|
13
13
|
def get_metrics(metrics, date)
|
14
|
-
counter =
|
15
|
-
|
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
|
-
|
21
|
-
|
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
|
data/lib/graphs/roodi_grapher.rb
CHANGED
@@ -6,27 +6,13 @@ module MetricFu
|
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
super
|
9
|
-
|
10
|
-
|
9
|
+
@roodi_count = []
|
10
|
+
@labels = {}
|
11
11
|
end
|
12
12
|
|
13
13
|
def get_metrics(metrics, date)
|
14
|
-
|
15
|
-
|
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
|
9
|
-
template_dir
|
10
|
-
graph_dir
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|
data/spec/base/graph_spec.rb
CHANGED
@@ -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(
|
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 = "
|
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 => "
|
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 = "
|
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 => "
|
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 = "
|
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 => "
|
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 = "
|
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 => "
|
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 = "
|
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 => "
|
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.
|
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:
|
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:
|
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:
|
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
|
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
|
data/spec/graphs/grapher_spec.rb
DELETED
@@ -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
|