diff --git a/app/controllers/conductor/satistics_controller.rb b/app/controllers/conductor/satistics_controller.rb
new file mode 100644
index 0000000..cabc9a9
--- /dev/null
+++ b/app/controllers/conductor/satistics_controller.rb
@@ -0,0 +1,20 @@
+require 'rails/code_statistics'
+
+STATS_DIRECTORIES = [
+ %w(Controllers app/controllers),
+ %w(Helpers app/helpers),
+ %w(Models app/models),
+ %w(Libraries lib/),
+ %w(APIs app/apis),
+ %w(Integration\ tests test/integration),
+ %w(Functional\ tests test/functional),
+ %w(Unit\ tests test/unit)
+].collect { |name, dir| [ name, "#{Rails.root}/#{dir}" ] }.select { |name, dir| File.directory?(dir) }
+
+module Conductor
+ class StatisticsController < ApplicationController
+ def index
+ @stats = Conductor::CodeStatistics.new(*STATS_DIRECTORIES)
+ end
+ end
+end
diff --git a/app/models/conductor/code_statistics.rb b/app/models/conductor/code_statistics.rb
new file mode 100644
index 0000000..ea9491d
--- /dev/null
+++ b/app/models/conductor/code_statistics.rb
@@ -0,0 +1,89 @@
+TEST_TYPES = %w(Units Functionals Unit\ tests Functional\ tests Integration\ tests)
+module Conductor
+ class CodeStatistics #:nodoc:
+ attr_reader :pairs
+
+ def initialize(*pairs)
+ @pairs = pairs
+ end
+
+ def lines
+ @pairs.collect do |pair|
+ line(pair.first, statistics[pair.first])
+ end
+ end
+
+ def total_line
+ line("Total", calculate_total)
+ end
+
+ def statistics
+ @pairs.inject({}) do |stats, pair|
+ stats[pair.first] = calculate_directory_statistics(pair.last)
+ stats
+ end
+ end
+
+ def calculate_directory_statistics(directory, pattern = /.*\.rb$/)
+ stats = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
+
+ Dir.foreach(directory) do |file_name|
+ if File.stat(directory + "/" + file_name).directory? and (/^\./ !~ file_name)
+ newstats = calculate_directory_statistics(directory + "/" + file_name, pattern)
+ stats.each { |k, v| stats[k] += newstats[k] }
+ end
+
+ next unless file_name =~ pattern
+
+ f = File.open(directory + "/" + file_name)
+
+ while line = f.gets
+ stats["lines"] += 1
+ stats["classes"] += 1 if line =~ /class [A-Z]/
+ stats["methods"] += 1 if line =~ /def [a-z]/
+ stats["codelines"] += 1 unless line =~ /^\s*$/ || line =~ /^\s*#/
+ end
+ end
+
+ stats
+ end
+
+ def calculate_total
+ total = { "lines" => 0, "codelines" => 0, "classes" => 0, "methods" => 0 }
+ statistics.each_value { |pair| pair.each { |k, v| total[k] += v } }
+ total
+ end
+
+ def code_loc
+ code_loc = 0
+ statistics.each { |k, v| code_loc += v['codelines'] unless TEST_TYPES.include? k }
+ code_loc
+ end
+
+ def tests_loc
+ test_loc = 0
+ statistics.each { |k, v| test_loc += v['codelines'] if TEST_TYPES.include? k }
+ test_loc
+ end
+
+ def line(name, statistics)
+ m_over_c = (statistics["methods"] / statistics["classes"]) rescue m_over_c = 0
+ loc_over_m = (statistics["codelines"] / statistics["methods"]) - 2 rescue loc_over_m = 0
+
+ {
+ :name => name,
+ :lines => statistics["lines"],
+ :codelines => statistics["codelines"],
+ :classes => statistics["classes"],
+ :methods => statistics["methods"],
+ :m_over_c => m_over_c,
+ :loc_over_m => loc_over_m
+ }
+ end
+
+ def code_to_test
+ tests_loc.to_f/code_loc
+ end
+
+ end
+end
diff --git a/app/views/conductor/statistics/index.html.erb b/app/views/conductor/statistics/index.html.erb
new file mode 100644
index 0000000..5232199
--- /dev/null
+++ b/app/views/conductor/statistics/index.html.erb
@@ -0,0 +1,46 @@
+
Statistics
+
+
+
+ | Name |
+ Lines |
+ LOC |
+ Classes |
+ Methods |
+ M/C |
+ LOC/M |
+
+ <% @stats.lines.each do |line| %>
+
+ | <%= line[:name] %> |
+ <%= line[:lines] %> |
+ <%= line[:codelines] %> |
+ <%= line[:classes] %> |
+ <%= line[:methods] %> |
+ <%= line[:m_over_c] %> |
+ <%= line[:loc_over_m] %> |
+
+ <% end %>
+
+ <%
+ if @stats.pairs.length > 1
+ line = @stats.total_line
+ %>
+
+ | <%= line[:name] %> |
+ <%= line[:lines] %> |
+ <%= line[:codelines] %> |
+ <%= line[:classes] %> |
+ <%= line[:methods] %> |
+ <%= line[:m_over_c] %> |
+ <%= line[:loc_over_m] %> |
+
+ <% end %>
+
+
+
+
+| Code LOC | <%= @stats.code_loc %> |
+| Test LOC | <%= @stats.tests_loc %> |
+| Code to Test Ratio | 1:<%= @stats.code_to_test %> |
+
diff --git a/app/views/layouts/conductor/application.html.erb b/app/views/layouts/conductor/application.html.erb
index 5a5f112..1598b47 100644
--- a/app/views/layouts/conductor/application.html.erb
+++ b/app/views/layouts/conductor/application.html.erb
@@ -47,7 +47,7 @@
- <%= link_to("Routes", conductor_routes_path) %>
- <%= link_to("Annotations", conductor_annotations_path) %>
- - Statistics
+ - <%= link_to("Statistics", conductor_statistics_path) %>
diff --git a/config/routes.rb b/config/routes.rb
index 3350034..fa9028f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,5 @@
Rails.application.routes.draw do
namespace :conductor do
- resources :scaffolds, :routes, :annotations
+ resources :scaffolds, :routes, :annotations, :statistics
end
end
diff --git a/public/stylesheets/conductor.css b/public/stylesheets/conductor.css
index 23ade11..d5e3c2d 100644
--- a/public/stylesheets/conductor.css
+++ b/public/stylesheets/conductor.css
@@ -100,4 +100,16 @@ a:hover {
}
#sidebar ul.links li {
margin-bottom: 5px;
-}
\ No newline at end of file
+}
+
+tr.statistic th {
+ text-align: left;
+}
+
+tr.statistic th {
+ text-align: left;
+}
+
+tr.statistic td {
+ text-align: right;
+}