Enhace activity chart: make it to show number of commits, changed files and changed files per day. TODO: legend.

portnov [2008-06-11 11:16:12]
Enhace activity chart: make it to show number of commits, changed files and changed files per day. TODO: legend.
Filename
pygit/chart.py
pygit/pygit.py
pygit/views.py
diff --git a/pygit/chart.py b/pygit/chart.py
index 8c4b6e2..94f3beb 100644
--- a/pygit/chart.py
+++ b/pygit/chart.py
@@ -6,27 +6,36 @@ width,height = 600,100
 pl,pr,py = 10,30,17
 root = "/home/portnov/www/projects/"

+COLORS = [(0.9,0.9,0.5),
+          (0.2,0.2,0.9),
+          (0.2,0.9,0.2)]
+
 def chart_path(data):
-  return "/media/charts/chart_%s.png" % hash(tuple(data))
+  return "/media/charts/chart_%s.png" % hash(data)

-def make_chart(data,out_path):
-  surf = cairo.ImageSurface(cairo.FORMAT_ARGB32,width,height)
-  cx = cairo.Context(surf)
-  y = [d[1] for d in data]
-  M = max(y)
-  n = len(data)-1
-  scale_y = float(height-2*py)/M
-  step_x = float(width-pl-pr)/n
-  cx.set_source_rgb(0.9,0.9,0.5)
+def make_one_chart(y,color,cx,step_x,scale_y):
+  cx.set_source_rgb(*color)
   cx.new_path()
-  cx.move_to(pl,height-py)
+  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.line_to(width-pr,height-py)
-  cx.close_path()
-  cx.fill()
+  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)
+
+  for i in range(len(dataset)):
+    data = dataset[i]
+    color = colors[i]
+    M = max(data)
+    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
@@ -37,15 +46,18 @@ def make_chart(data,out_path):
     cur_x += step_x
   cx.set_source_rgb(0,0,0)
   cur_x = pl
-  for i in range(len(data)):
-    label = data[i][0]
+  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(data):
-  path = chart_path(data)
+def chart(labels,dataset):
+  path = chart_path((tuple(labels),tuple(map(tuple,dataset))))
   if not exists(root+path):
-    make_chart(data,root+path)
+    make_chart(labels,dataset,COLORS,root+path)
   return "<img src='%s'/>" % path
diff --git a/pygit/pygit.py b/pygit/pygit.py
index f0988d1..62e5b08 100644
--- a/pygit/pygit.py
+++ b/pygit/pygit.py
@@ -108,13 +108,49 @@ def uniq(lst):
   r.append((prev,count))
   return r

-def commits_stats(rid,branch='master'):
+def group_by_date(lst):
+  "[Commit] -> [(date,Commit)]"
   def date(tp):
     y,m,d = tp
     return "%d.%d" % (d,m)
+  d = [(c.authored_date[:3], c) for c in lst]
+  d.sort()
+  d = [(date(e[0]),e[1]) for e in d]
+  prev = d[0][0]
+  group = []
+  r = []
+  for dt,cm in d:
+    if dt == prev:
+      group.append(cm)
+    else:
+      r.append((dt,group))
+      del group
+      group = []
+    prev = dt
+#   r.append((prev,group))
+  return r
+
+def stats_sum(lst):
+  "[Commit] -> dict(lines=?, files=?)"
+  r = {'lines': 0, 'files': 0}
+  for cm in lst:
+    try:
+      r['lines'] += cm.stats.total['lines']
+      r['files'] += cm.stats.total['files']
+    except ValueError:
+      pass
+  return r
+
+def commits_stats(rid,branch='master'):
   r = open_repo(rid)
-  d = [c.authored_date[:3] for c in r.commits(branch,max_count=100)]
-  return [(date(t[0]),t[1]) for t in uniq(d)][:20]
+  d = r.commits(branch,max_count=100)
+  grp = group_by_date(d)
+  dates = [g[0] for g in grp]
+  n_commits = [len(g[1]) for g in grp]
+  stats = [stats_sum(g[1]) for g in grp]
+  files = [s['files'] for s in stats]
+  lines = [s['lines'] for s in stats]
+  return dates,n_commits,files,lines

 def commit_stats(rid,cid):
   r = open_repo(rid)
diff --git a/pygit/views.py b/pygit/views.py
index 776cdfc..a2ca5b9 100644
--- a/pygit/views.py
+++ b/pygit/views.py
@@ -33,7 +33,9 @@ def one_repo(request,rid,branch='master'):
   tags = pygit.tags(rid)
   cs  = pygit.commits(rid,branch)
   dirs,files = pygit.root_tree(rid,branch)
-  cht = chart(pygit.commits_stats(rid,branch))
+  dates,n_commits,files_s,lines = pygit.commits_stats(rid,branch)
+  cht = chart(dates,[n_commits,files_s,lines])
+#   cht = chart(pygit.commits_stats(rid,branch))
   return render_it('repo.html',
       {'description': dsc,
        'rid': rid,
ViewGit