mirror of
https://github.com/tomgi/git_stats.git
synced 2024-12-22 13:32:17 +01:00
chart generation splitted to classes
This commit is contained in:
parent
cf27a2967b
commit
a69446bed3
25 changed files with 348 additions and 93 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
21
lib/git_stats/stats_view/charts/activity_charts.rb
Normal file
21
lib/git_stats/stats_view/charts/activity_charts.rb
Normal 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
|
25
lib/git_stats/stats_view/charts/authors_charts.rb
Normal file
25
lib/git_stats/stats_view/charts/authors_charts.rb
Normal 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
|
46
lib/git_stats/stats_view/charts/chart.rb
Normal file
46
lib/git_stats/stats_view/charts/chart.rb
Normal 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
|
30
lib/git_stats/stats_view/charts/charts.rb
Normal file
30
lib/git_stats/stats_view/charts/charts.rb
Normal 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
|
62
lib/git_stats/stats_view/charts/repo_charts.rb
Normal file
62
lib/git_stats/stats_view/charts/repo_charts.rb
Normal 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
|
|
@ -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
|
|
@ -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
|
||||||
|
|
21
spec/stats_view/charts/activity_charts_spec.rb
Normal file
21
spec/stats_view/charts/activity_charts_spec.rb
Normal 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
|
28
spec/stats_view/charts/authors_charts_spec.rb
Normal file
28
spec/stats_view/charts/authors_charts_spec.rb
Normal 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
|
69
spec/stats_view/charts/repo_charts_spec.rb
Normal file
69
spec/stats_view/charts/repo_charts_spec.rb
Normal 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
|
|
@ -1 +1 @@
|
||||||
= high_chart("by_hour", by_hour)
|
= high_chart("activity_by_hour", charts.activity_by_hour)
|
|
@ -1 +1 @@
|
||||||
= high_chart("by_wday", by_wday)
|
= high_chart("by_authors_wday", charts.by_authors_wday)
|
|
@ -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)
|
|
@ -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)
|
Loading…
Reference in a new issue