diff --git a/pygit/chart.py b/pygit/chart.py index 8abff8a..022900a 100644 --- a/pygit/chart.py +++ b/pygit/chart.py @@ -4,57 +4,90 @@ import cairo from django.conf import settings -width,height = 900,150 pl,pr,py = 10,30,17 def chart_path(data): - return "/media/charts/chart_%s.png" % hash(data) - -def make_one_chart(y,color,cx,step_x,scale_y): - cx.set_source_rgb(*color) - cx.new_path() - cx.move_to(pl,int(height-y[0]*scale_y-py)) - cur_x = pl - for d in y: - cx.line_to(int(cur_x),int(height-d*scale_y-py)) - cur_x += step_x - cx.stroke() - -def make_chart(labels,dataset,colors,out_path): - n = len(dataset[0])-1 - step_x = float(width-pl-pr)/n - surf = cairo.ImageSurface(cairo.FORMAT_ARGB32,width,height) - cx = cairo.Context(surf) - M = max(map(max,dataset)) - - for i in range(len(dataset)): - data = dataset[i] - color = colors[i] - scale_y = float(height-2*py)/M - make_one_chart(data,color,cx,step_x,scale_y) - - cx.set_source_rgb(0.9,0.9,0.9) - cx.set_line_width(1) - cur_x = pl - for i in range(len(data)): - cx.move_to(cur_x,height-py) - cx.line_to(cur_x,py) - cx.stroke() - cur_x += step_x - cx.set_source_rgb(0,0,0) - cur_x = pl - for i in range(len(dataset[0])): - label = labels[i] - cx.move_to(cur_x,int(height-py/2)) - cx.show_text(label) - cur_x += step_x - cx.move_to(pl,height-py) - cx.line_to(width-pr,height-py) - cx.stroke() - surf.write_to_png(out_path) - -def chart(labels,dataset): - path = chart_path((tuple(labels),tuple(map(tuple,dataset)))) - if not exists(settings.ROOT+path): - make_chart(labels,dataset,settings.COLORS,settings.ROOT+path) - return "<img src='%s'/>" % path + return + +class Place(object): + def __init__(self,cx,x0,y0,width,height): + self.cx = cx + self.x0 = x0 + self.y0 = y0 + self.width = width + self.height = height + self.x_ticks = None + + def set_scale(self,x_ticks,y_max): + self.x_ticks = x_ticks + self.y_max = y_max + self.step_x = float(self.width)/x_ticks + self.scale_y = float(self.height)/float(self.y_max) + + def translate(self,x,y): + return int(self.x0+x*self.step_x), int(self.y0-y*self.scale_y) + + def move_to(self,x,y): + self.cx.move_to(*self.translate(x,y)) + + def line_to(self,x,y): + self.cx.line_to(*self.translate(x,y)) + +class Chart(object): + def __init__(self,width,height,n=1): + self.n_places = n + self.width = width + self.height = height + self.surf = cairo.ImageSurface(cairo.FORMAT_ARGB32,width,height) + self.cx = cairo.Context(self.surf) + self.hash = 0 + place_height = float(self.height)/n + self.places = [] + self.cx.set_source_rgb(1,1,1) + self.cx.rectangle(0,0,width,height) + self.cx.fill() + for i in range(n): + place = Place(self.cx,pl,height-place_height*i-py, width-pl-pr, place_height-2*py) + self.places.append(place) + + def draw(self,lst,color=(0.9,0.2,0.2),place=0): + pc = self.places[place] + pc.set_scale(len(lst)-1,max(lst)) + pc.cx.new_path() + pc.cx.set_source_rgb(*color) + pc.move_to(0,lst[0]) + for i in range(len(lst)): + pc.line_to(i,lst[i]) + pc.cx.stroke() + self.hash += hash(tuple(lst)) + + def labels(self,lst): + step_x = (self.width-pl-pr)/(len(lst)-1) + self.cx.set_source_rgb(0,0,0) + for pc in self.places: + pc.move_to(0,0) + pc.line_to(len(lst)-1,0) + pc.cx.stroke() + cur_x = pl + self.cx.set_source_rgb(0.9,0.9,0.9) + for i in range(len(lst)): + self.cx.move_to(cur_x, self.height-py) + self.cx.line_to(cur_x, py) + self.cx.stroke() + cur_x += step_x + cur_x = pl + self.cx.set_source_rgb(0,0,0) + for i in range(len(lst)): + label = lst[i] + self.cx.move_to(cur_x, int(self.height-py/2)) + self.cx.show_text(label) + cur_x += step_x + self.hash += hash(tuple(lst)) + + def finish(self): + path = "/media/charts/chart_%s.png" % self.hash + root = "/home/portnov/www/projects" + if not exists(root+path): + self.surf.write_to_png(root+path) + print root+path + return "<img src='%s'/>" % path diff --git a/pygit/chart_test.py b/pygit/chart_test.py new file mode 100755 index 0000000..62d55a3 --- /dev/null +++ b/pygit/chart_test.py @@ -0,0 +1,10 @@ +#!/usr/bin/python + +from chart import Chart +c = Chart(900,150,n=2) +c.draw([1,5,3,2,7],place=0) +c.draw([2,4,3,5,6],place=0,color=(0.2,0.9,0.2)) +c.draw([1,3,7,2,1],place=1,color=(0.2,0.2,0.9)) +c.labels(['1','2','3','4','5']) +c.finish() + diff --git a/pygit/views.py b/pygit/views.py index 00dcf3b..0c2dfa5 100644 --- a/pygit/views.py +++ b/pygit/views.py @@ -7,7 +7,7 @@ from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse import pygit -from chart import chart +from chart import Chart sys.path.append(dirname(dirname(__file__))) from mgmt.views import render_it @@ -35,14 +35,19 @@ def one_repo(request,rid,branch='master'): cs = pygit.commits(rid,branch) dirs,files = pygit.root_tree(rid,branch) dates,n_commits,files_s,lines = pygit.commits_stats(rid,branch) - cht = chart(dates,[n_commits,files_s,lines]) + cht = Chart(900,200,n=2) + cht.draw(n_commits,place=0,color=(0.9,0.9,0.2)) + cht.draw(files_s,place=1,color=(0.2,0.2,0.9)) + cht.draw(lines,place=1,color=(0.2,0.9,0.2)) + cht.labels(dates) + chart = cht.finish() return render_it('repo.html', {'description': dsc, 'rid': rid, 'current_branch': branch, 'branches': brs, 'tags': tags, - 'activity_chart': cht, + 'activity_chart': chart, 'commits': cs, 'dirs': dirs, 'files': files},