chart generation splitted to classes

This commit is contained in:
Tomasz Gieniusz 2012-10-20 00:30:00 +02:00
parent cf27a2967b
commit a69446bed3
25 changed files with 348 additions and 93 deletions

View file

@ -18,7 +18,7 @@ module GitStats
end end
def files_by_extension_count def files_by_extension_count
@files_by_extension ||= Hash[files_by_extension.map { |ext, files| [ext, files.count] }] @files_by_extension_count ||= Hash[files_by_extension.map { |ext, files| [ext, files.count] }]
end end
def lines_by_extension def lines_by_extension

View file

@ -36,6 +36,30 @@ module GitStats
commits.map(&:date).minmax commits.map(&:date).minmax
end end
def files_count_each_day
@files_count_each_day ||= commits_period_range.map { |day|
files_count_at day
}
end
def files_count_at(day)
last_commit_at(day).try(:files_count) || 0
end
def lines_count_each_day
@lines_count_each_day ||= commits_period_range.map { |day|
lines_count_at day
}
end
def lines_count_at(day)
last_commit_at(day).try(:lines_count) || 0
end
def last_commit_at(day)
commits.reverse.find { |c| c.date < day }
end
def last_commit def last_commit
commits.last commits.last
end end
@ -105,6 +129,11 @@ module GitStats
command_observers.each { |o| o.call(command, result) } command_observers.each { |o| o.call(command, result) }
end end
def commits_period_range
period = commits_period.map(&:midnight)
period.first.upto (period.last + 1.day)
end
end end
end end
end end

View file

@ -0,0 +1,21 @@
module GitStats
module StatsView
module Charts
class ActivityCharts
def initialize(activity)
@activity = activity
end
def activity_by_hour
Chart.new do |f|
f.type "column"
f.title "Commits"
f.x_categories (0..23)
f.y_text 'Commits'
f.series(name: "commits", data: @activity.by_hour.to_key_indexed_array)
end
end
end
end
end
end

View file

@ -0,0 +1,25 @@
module GitStats
module StatsView
module Charts
class AuthorsCharts
def initialize(authors)
@authors = authors
end
def by_authors_wday
Chart.new do |c|
c.type "column"
c.title 'by_wday_authors'
c.x_categories Date::ABBR_DAYNAMES
c.y_text 'y_text'
c.default_legend
@authors.each do |author|
c.series(name: author.email, data: author.activity.by_wday.to_key_indexed_array)
end
end
end
end
end
end
end

View file

@ -0,0 +1,46 @@
module GitStats
module StatsView
module Charts
class Chart
def method_missing(name, *args, &block)
@chart.send(name, *args, &block)
end
def initialize
@chart = LazyHighCharts::HighChart.new('graph')
yield self if block_given?
end
def type(type)
@chart.chart(type: type)
end
def x_categories(categories)
@chart.xAxis(categories: categories)
end
def y_text(text)
@chart.yAxis(min: 0, title: {text: text})
end
def title(title)
@chart.title(text: title)
end
def default_legend
legend(
layout: 'vertical',
backgroundColor: '#FFFFFF',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 70,
floating: true,
shadow: true
)
end
end
end
end
end

View file

@ -0,0 +1,30 @@
module GitStats
module StatsView
module Charts
class All
delegate :files_by_extension, :lines_by_extension, :files_by_date, :lines_by_date, to: :repo_charts
delegate :by_authors_wday, to: :authors_charts
delegate :activity_by_hour, to: :activity_charts
attr_reader :repo
def initialize(repo)
@repo = repo
end
def repo_charts
@repo_charts ||= Charts::RepoCharts.new(repo)
end
def authors_charts
@authors_charts ||= Charts::AuthorsCharts.new(repo.authors)
end
def activity_charts
@activity_charts ||= Charts::ActivityCharts.new(repo.activity)
end
end
end
end
end

View file

@ -0,0 +1,62 @@
module GitStats
module StatsView
module Charts
class RepoCharts
def initialize(repo)
@repo = repo
end
def files_by_extension
Chart.new do |f|
f.type "column"
f.title "files by extension"
f.x_categories @repo.files_by_extension_count.keys
f.y_text 'Commits'
f.series(name: "commits", data: @repo.files_by_extension_count.values)
end
end
def lines_by_extension
Chart.new do |f|
f.type "column"
f.title "lines by extension"
f.x_categories @repo.lines_by_extension.keys
f.y_text 'Commits'
f.series(name: "commits", data: @repo.lines_by_extension.values)
end
end
def files_by_date
Chart.new do |f|
f.title "Files"
f.type "datetime"
f.y_text 'Commits'
f.series(
type: "area",
name: "commits",
pointInterval: 1.day * 1000,
pointStart: @repo.commits.first.date.to_i * 1000,
data: @repo.files_count_each_day
)
end
end
def lines_by_date
Chart.new do |f|
f.title "Files"
f.type "datetime"
f.y_text 'Commits'
f.series(
type: "area",
name: "commits",
pointInterval: 1.day * 1000,
pointStart: @repo.commits.first.date.to_i * 1000,
data: @repo.lines_count_each_day
)
end
end
end
end
end
end

View file

@ -3,100 +3,16 @@ module GitStats
class ViewData class ViewData
include ActionView::Helpers::TagHelper include ActionView::Helpers::TagHelper
include LazyHighCharts::LayoutHelper include LazyHighCharts::LayoutHelper
attr_reader :repo attr_reader :repo
def initialize(repo) def initialize(repo)
@repo = repo @repo = repo
end end
def by_wday def charts
@by_wday ||= LazyHighCharts::HighChart.new('graph') do |f| @charts ||= Charts::All.new(repo)
f.chart(type: "column")
f.title(text: "Commits")
f.xAxis(categories: Date::ABBR_DAYNAMES)
f.yAxis(min: 0, title: {text: 'Commits'})
f.legend(
layout: 'vertical',
backgroundColor: '#FFFFFF',
align: 'left',
verticalAlign: 'top',
x: 100,
y: 70,
floating: true,
shadow: true
)
repo.authors.each do |email, author|
f.series(name: email, data: author.activity.by_wday.to_key_indexed_array)
end
end
end end
def by_hour
@by_hour ||= LazyHighCharts::HighChart.new('graph') do |f|
f.chart(type: "column")
f.title(text: "Commits")
f.xAxis(categories: (0..23))
f.yAxis(min: 0, title: {text: 'Commits'})
f.series(name: "commits", data: repo.activity.by_hour.to_key_indexed_array)
end
end
def files_by_extension
@files_by_extension ||= LazyHighCharts::HighChart.new('graph') do |f|
f.chart(type: "column")
f.title(text: "files by extension")
f.xAxis(categories: repo.commits.last.files_by_extension.keys)
f.yAxis(min: 0, title: {text: 'Commits'})
f.series(name: "commits", data: repo.commits.last.files_by_extension.values.map(&:count))
end
end
def lines_by_extension
@lines_by_extension ||= LazyHighCharts::HighChart.new('graph') do |f|
f.chart(type: "column")
f.title(text: "files by extension")
f.xAxis(categories: repo.commits.last.lines_by_extension.keys)
f.yAxis(min: 0, title: {text: 'Commits'})
f.series(name: "commits", data: repo.commits.last.lines_by_extension.values)
end
end
def files_by_date
@files_by_date ||= LazyHighCharts::HighChart.new('graph') do |f|
f.title(text: "Files")
f.xAxis(type: "datetime")
f.yAxis(min: 0, title: {text: 'Commits'})
rcommits = repo.commits.reverse
f.series(
type: "area",
name: "commits",
pointInterval: 1.day * 1000,
pointStart: repo.commits.first.date.to_i * 1000,
data: repo.commits.first.date.midnight.upto((repo.commits.last.date + 1.day).midnight).map { |day|
rcommits.find { |c| c.date < day }.files_count rescue 0
}
)
end
end
def lines_by_date
@lines_by_date ||= LazyHighCharts::HighChart.new('graph') do |f|
f.title(text: "Files")
f.xAxis(type: "datetime")
f.yAxis(min: 0, title: {text: 'Commits'})
rcommits = repo.commits.reverse
f.series(
type: "area",
name: "commits",
pointInterval: 1.day * 1000,
pointStart: repo.commits.first.date.to_i * 1000,
data: repo.commits.first.date.midnight.upto((repo.commits.last.date + 1.day).midnight).map { |day|
rcommits.find { |c| c.date < day }.lines_count rescue 0
}
)
end
end
end end
end end
end end

View file

@ -30,6 +30,14 @@ describe GitStats::GitData::Repo do
repo.files_count.should == 6 repo.files_count.should == 6
end end
it 'should count files by date' do
repo.files_count_each_day.should == [0, 3, 3, 5, 5, 5, 6, 6, 6]
end
it 'should count lines by date' do
repo.lines_count_each_day.should == [0, 11, 11, 1014, 1014, 1014, 1114, 1114, 1114]
end
it 'should count all lines in repo' do it 'should count all lines in repo' do
repo.lines_count.should == 1114 repo.lines_count.should == 1114
end end

View file

@ -0,0 +1,21 @@
require 'spec_helper'
describe GitStats::StatsView::Charts::ActivityCharts do
let(:charts) { GitStats::StatsView::Charts::All.new(repo) }
context 'activity_by_hour chart' do
let(:activity) { double(by_hour: double(to_key_indexed_array: 'result')) }
let(:repo) { double(activity: activity) }
let(:chart) { charts.activity_charts.activity_by_hour }
it 'should be a column chart' do
chart.should be_a GitStats::StatsView::Charts::Chart
chart.options[:chart][:type].should == "column"
end
it 'should have 1 data series with activity by_hour' do
chart.should have(1).data
chart.data.first[:data].should == activity.by_hour.to_key_indexed_array
end
end
end

View file

@ -0,0 +1,28 @@
require 'spec_helper'
describe GitStats::StatsView::Charts::AuthorsCharts do
let(:charts) { GitStats::StatsView::Charts::All.new(repo) }
context 'by_authors_wday chart' do
let(:authors) { [
double(email: "email1", activity: double(by_wday: double(to_key_indexed_array: "result1"))),
double(email: "email2", activity: double(by_wday: double(to_key_indexed_array: "result2")))
] }
let(:repo) { double(authors: authors) }
let(:chart) { charts.authors_charts.by_authors_wday }
it 'should be a column chart' do
chart.should be_a GitStats::StatsView::Charts::Chart
chart.options[:chart][:type].should == "column"
end
it 'should have 2 data series with authors activity by_wday' do
chart.should have(2).data
chart.data[0][:data].should == "result1"
chart.data[0][:name].should == "email1"
chart.data[1][:data].should == "result2"
chart.data[1][:name].should == "email2"
end
end
end

View file

@ -0,0 +1,69 @@
require 'spec_helper'
describe GitStats::StatsView::Charts::RepoCharts do
let(:charts) { GitStats::StatsView::Charts::All.new(repo) }
context 'files_by_extension chart' do
let(:repo) { double(files_by_extension_count: {'.rb' => 5, '.txt' => 3}) }
let(:chart) { charts.repo_charts.files_by_extension }
it 'should be a column chart' do
chart.should be_a GitStats::StatsView::Charts::Chart
chart.options[:chart][:type].should == "column"
end
it 'should have 1 data series with files_by_extension_count' do
chart.should have(1).data
chart.options[:xAxis][:categories].should == %w(.rb .txt)
chart.data[0][:data].should == [5, 3]
end
end
context 'lines_by_extension chart' do
let(:repo) { double(lines_by_extension: {'.rb' => 50, '.txt' => 30}) }
let(:chart) { charts.repo_charts.lines_by_extension }
it 'should be a column chart' do
chart.should be_a GitStats::StatsView::Charts::Chart
chart.options[:chart][:type].should == "column"
end
it 'should have 1 data series with lines_by_extension' do
chart.should have(1).data
chart.options[:xAxis][:categories].should == %w(.rb .txt)
chart.data[0][:data].should == [50, 30]
end
end
context 'files_by_date chart' do
let(:repo) { double(commits: [double(date: 5)], files_count_each_day: [10, 15, 12, 20]) }
let(:chart) { charts.repo_charts.files_by_date }
it 'should be a datetime chart' do
chart.should be_a GitStats::StatsView::Charts::Chart
chart.options[:chart][:type].should == "datetime"
end
it 'should have 1 data series with files_by_date' do
chart.should have(1).data
chart.data[0][:data].should == [10, 15, 12, 20]
chart.data[0][:pointStart].should == 5000
end
end
context 'lines_by_date chart' do
let(:repo) { double(commits: [double(date: 6)], lines_count_each_day: [100, 150, 120, 200]) }
let(:chart) { charts.repo_charts.lines_by_date }
it 'should be a datetime chart' do
chart.should be_a GitStats::StatsView::Charts::Chart
chart.options[:chart][:type].should == "datetime"
end
it 'should have 1 data series with lines_by_date' do
chart.should have(1).data
chart.data[0][:data].should == [100, 150, 120, 200]
chart.data[0][:pointStart].should == 6000
end
end
end

View file

@ -1 +1 @@
= high_chart("by_hour", by_hour) = high_chart("activity_by_hour", charts.activity_by_hour)

View file

@ -1 +1 @@
= high_chart("by_wday", by_wday) = high_chart("by_authors_wday", charts.by_authors_wday)

View file

@ -1,2 +1,2 @@
= high_chart("files_by_date", files_by_date) = high_chart("files_by_date", charts.files_by_date)
= high_chart("files_by_extension", files_by_extension) = high_chart("files_by_extension", charts.files_by_extension)

View file

@ -1,2 +1,2 @@
= high_chart("lines_by_date", lines_by_date) = high_chart("lines_by_date", charts.lines_by_date)
= high_chart("lines_by_extension", lines_by_extension) = high_chart("lines_by_extension", charts.lines_by_extension)