Commit 1c5b2a51 authored by randx's avatar randx

Stats page

parent ca54d43f
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
//= require modernizr //= require modernizr
//= require chosen-jquery //= require chosen-jquery
//= require raphael //= require raphael
//= require g.raphael-min
//= require g.bar-min
//= require branch-graph //= require branch-graph
//= require ace-src-noconflict/ace //= require ace-src-noconflict/ace
//= require_tree . //= require_tree .
...@@ -31,3 +31,11 @@ ul { ...@@ -31,3 +31,11 @@ ul {
} }
} }
} }
ol, ul {
&.styled {
li {
padding:2px;
}
}
}
...@@ -16,6 +16,11 @@ class RepositoriesController < ProjectResourceController ...@@ -16,6 +16,11 @@ class RepositoriesController < ProjectResourceController
@tags = @project.tags @tags = @project.tags
end end
def stats
@stats = Gitlab::GitStats.new(@project.repo, @project.root_ref)
@graph = @stats.graph
end
def archive def archive
unless can?(current_user, :download_code, @project) unless can?(current_user, :download_code, @project)
render_404 and return render_404 and return
......
...@@ -16,6 +16,11 @@ ...@@ -16,6 +16,11 @@
Tags Tags
%span.badge= @project.tags.length %span.badge= @project.tags.length
= nav_link(controller: :repositories, action: :stats) do
= link_to stats_project_repository_path(@project) do
Stats
- if current_controller?(:commits) && current_user.private_token - if current_controller?(:commits) && current_user.private_token
%li.right %li.right
%span.rss-icon %span.rss-icon
......
= render "commits/head"
.row
.span5
%h4
Stats for #{@project.root_ref}:
%p
%b Total commits:
%span= @stats.commits_count
%p
%b Total files:
%span= @stats.files_count
%p
%b Authors:
%span= @stats.authors_count
%br
%div#activity-chart
.span7
%h4 Top 100 Committers:
%ol.styled
- @stats.authors[0...100].each do |author|
%li
= image_tag gravatar_icon(author.email, 16), class: 'avatar s16'
= author.name
%small.light= author.email
.right
= author.commits
:javascript
$(function(){
var labels = [#{@graph.labels.to_json}];
var r = Raphael('activity-chart');
r.text(160, 10, "Commit activity for last #{@graph.weeks} weeks").attr({ font: "13px sans-serif" });
r.barchart(
10, 10, 400, 160,
[[#{@graph.commits.join(', ')}]]
).label(labels, true);
})
...@@ -128,6 +128,7 @@ Gitlab::Application.routes.draw do ...@@ -128,6 +128,7 @@ Gitlab::Application.routes.draw do
member do member do
get "branches" get "branches"
get "tags" get "tags"
get "stats"
get "archive" get "archive"
end end
end end
......
...@@ -157,7 +157,7 @@ ActiveRecord::Schema.define(:version => 20121026114600) do ...@@ -157,7 +157,7 @@ ActiveRecord::Schema.define(:version => 20121026114600) do
create_table "users", :force => true do |t| create_table "users", :force => true do |t|
t.string "email", :default => "", :null => false t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "encrypted_password", :default => "", :null => false
t.string "reset_password_token" t.string "reset_password_token"
t.datetime "reset_password_sent_at" t.datetime "reset_password_sent_at"
t.datetime "remember_created_at" t.datetime "remember_created_at"
......
module Gitlab
class GitStats
attr_accessor :repo, :ref
def initialize repo, ref
@repo, @ref = repo, ref
end
def authors
@authors ||= collect_authors
end
def commits_count
@commits_count ||= repo.commit_count(ref)
end
def files_count
repo.git.sh("git ls-tree -r --name-only #{ref} | wc -l").first.to_i
end
def authors_count
authors.size
end
def graph
@graph ||= build_graph
end
protected
def collect_authors
shortlog = repo.git.shortlog({:e => true, :s => true }, ref)
authors = []
lines = shortlog.split("\n")
lines.each do |line|
data = line.split("\t")
commits = data.first
author = Grit::Actor.from_string(data.last)
authors << OpenStruct.new(
name: author.name,
email: author.email,
commits: commits.to_i
)
end
authors.sort_by(&:commits).reverse
end
def build_graph n = 4
from, to = (Date.today - n.weeks), Date.today
format = "--pretty=format:'%h|%at|%ai|%aE'"
commits_strings = repo.git.sh("git rev-list --since #{from.to_s(:date)} #{format} #{ref} | grep -v commit")[0].split("\n")
commits_dates = commits_strings.map do |string|
data = string.split("|")
date = data[2]
Time.parse(date).to_date.to_s(:date)
end
commits_per_day = from.upto(to).map do |day|
commits_dates.count(day.to_date.to_s(:date))
end
OpenStruct.new(
labels: from.upto(to).map { |day| day.stamp('Aug 23') },
commits: commits_per_day,
weeks: n
)
end
end
end
/*!
* g.Raphael 0.5 - Charting library, based on Raphaël
*
* Copyright (c) 2009 Dmitry Baranovskiy (http://g.raphaeljs.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/
(function(){var f=Math.min,a=Math.max;function e(o,m,h,p,j,k,l,i){var s,n={round:"round",sharp:"sharp",soft:"soft",square:"square"};if((j&&!p)||(!j&&!h)){return l?"":i.path()}k=n[k]||"square";p=Math.round(p);h=Math.round(h);o=Math.round(o);m=Math.round(m);switch(k){case"round":if(!j){var g=~~(p/2);if(h<g){g=h;s=["M",o+0.5,m+0.5-~~(p/2),"l",0,0,"a",g,~~(p/2),0,0,1,0,p,"l",0,0,"z"]}else{s=["M",o+0.5,m+0.5-g,"l",h-g,0,"a",g,g,0,1,1,0,p,"l",g-h,0,"z"]}}else{g=~~(h/2);if(p<g){g=p;s=["M",o-~~(h/2),m,"l",0,0,"a",~~(h/2),g,0,0,1,h,0,"l",0,0,"z"]}else{s=["M",o-g,m,"l",0,g-p,"a",g,g,0,1,1,h,0,"l",0,p-g,"z"]}}break;case"sharp":if(!j){var q=~~(p/2);s=["M",o,m+q,"l",0,-p,a(h-q,0),0,f(q,h),q,-f(q,h),q+(q*2<p),"z"]}else{q=~~(h/2);s=["M",o+q,m,"l",-h,0,0,-a(p-q,0),q,-f(q,p),q,f(q,p),q,"z"]}break;case"square":if(!j){s=["M",o,m+~~(p/2),"l",0,-p,h,0,0,p,"z"]}else{s=["M",o+~~(h/2),m,"l",1-h,0,0,-p,h-1,0,"z"]}break;case"soft":if(!j){g=f(h,Math.round(p/5));s=["M",o+0.5,m+0.5-~~(p/2),"l",h-g,0,"a",g,g,0,0,1,g,g,"l",0,p-g*2,"a",g,g,0,0,1,-g,g,"l",g-h,0,"z"]}else{g=f(Math.round(h/5),p);s=["M",o-~~(h/2),m,"l",0,g-p,"a",g,g,0,0,1,g,-g,"l",h-2*g,0,"a",g,g,0,0,1,g,g,"l",0,p-g,"z"]}}if(l){return s.join(",")}else{return i.path(s)}}function d(l,J,H,g,m,V,D){D=D||{};var z=this,W=D.type||"square",u=parseFloat(D.gutter||"20%"),T=l.set(),E=l.set(),n=l.set(),B=l.set(),F=Math.max.apply(Math,V),U=[],I=0,M=D.colors||z.colors,A=V.length;if(Raphael.is(V[0],"array")){F=[];I=A;A=0;for(var R=V.length;R--;){E.push(l.set());F.push(Math.max.apply(Math,V[R]));A=Math.max(A,V[R].length)}if(D.stacked){for(var R=A;R--;){var r=0;for(var Q=V.length;Q--;){r+=+V[Q][R]||0}U.push(r)}}for(var R=V.length;R--;){if(V[R].length<A){for(var Q=A;Q--;){V[R].push(0)}}}F=Math.max.apply(Math,D.stacked?U:F)}F=(D.to)||F;var K=g/(A*(100+u)+u)*100,k=K*u/100,p=D.vgutter==null?20:D.vgutter,C=[],q=J+k,o=(m-2*p)/F;if(!D.stretch){k=Math.round(k);K=Math.floor(K)}!D.stacked&&(K/=I||1);for(var R=0;R<A;R++){C=[];for(var Q=0;Q<(I||1);Q++){var S=Math.round((I?V[Q][R]:V[R])*o),t=H+m-p-S,O=e(Math.round(q+K/2),t+S,K,S,true,W,null,l).attr({stroke:"none",fill:M[I?Q:R]});if(I){E[Q].push(O)}else{E.push(O)}O.y=t;O.x=Math.round(q+K/2);O.w=K;O.h=S;O.value=I?V[Q][R]:V[R];if(!D.stacked){q+=K}else{C.push(O)}}if(D.stacked){var P;B.push(P=l.rect(C[0].x-C[0].w/2,H,K,m).attr(z.shim));P.bars=l.set();var v=0;for(var L=C.length;L--;){C[L].toFront()}for(var L=0,w=C.length;L<w;L++){var O=C[L],G,S=(v+O.value)*o,N=e(O.x,H+m-p-!!v*0.5,K,S,true,W,1,l);P.bars.push(O);v&&O.attr({path:N});O.h=S;O.y=H+m-p-!!v*0.5-S;n.push(G=l.rect(O.x-O.w/2,O.y,K,O.value*o).attr(z.shim));G.bar=O;G.value=O.value;v+=O.value}q+=K}q+=k}B.toFront();q=J+k;if(!D.stacked){for(var R=0;R<A;R++){for(var Q=0;Q<(I||1);Q++){var G;n.push(G=l.rect(Math.round(q),H+p,K,m-p).attr(z.shim));G.bar=I?E[Q][R]:E[R];G.value=G.bar.value;q+=K}q+=k}}T.label=function(y,Z){y=y||[];this.labels=l.set();var aa,h=-Infinity;if(D.stacked){for(var x=0;x<A;x++){var X=0;for(var s=0;s<(I||1);s++){X+=I?V[s][x]:V[x];if(s==I-1){var ab=z.labelise(y[x],X,F);aa=l.text(E[s][x].x,H+m-p/2,ab).attr(z.txtattr).attr({fill:D.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[x*(I||1)+s]);var Y=aa.getBBox();if(Y.x-7<h){aa.remove()}else{this.labels.push(aa);h=Y.x+Y.width}}}}}else{for(var x=0;x<A;x++){for(var s=0;s<(I||1);s++){var ab=z.labelise(I?y[s]&&y[s][x]:y[x],I?V[s][x]:V[x],F);aa=l.text(E[s][x].x-k/2,Z?H+m-p/2:E[s][x].y-10,ab).attr(z.txtattr).attr({fill:D.legendcolor||"#000","text-anchor":"start"}).insertBefore(n[x*(I||1)+s]);var Y=aa.getBBox();if(Y.x-7<h){aa.remove()}else{this.labels.push(aa);h=Y.x+Y.width}}}}return this};T.hover=function(i,h){B.hide();n.show();n.mouseover(i).mouseout(h);return this};T.hoverColumn=function(i,h){n.hide();B.show();h=h||function(){};B.mouseover(i).mouseout(h);return this};T.click=function(h){B.hide();n.show();n.click(h);return this};T.each=function(j){if(!Raphael.is(j,"function")){return this}for(var h=n.length;h--;){j.call(n[h])}return this};T.eachColumn=function(j){if(!Raphael.is(j,"function")){return this}for(var h=B.length;h--;){j.call(B[h])}return this};T.clickColumn=function(h){n.hide();B.show();B.click(h);return this};T.push(E,n,B);T.bars=E;T.covers=n;return T}function b(w,v,u,I,F,l,B){B=B||{};var h=this,n=B.type||"square",o=parseFloat(B.gutter||"20%"),D=w.set(),H=w.set(),q=w.set(),L=w.set(),T=Math.max.apply(Math,l),g=[],J=0,t=B.colors||h.colors,O=l.length;if(Raphael.is(l[0],"array")){T=[];J=O;O=0;for(var N=l.length;N--;){H.push(w.set());T.push(Math.max.apply(Math,l[N]));O=Math.max(O,l[N].length)}if(B.stacked){for(var N=O;N--;){var z=0;for(var M=l.length;M--;){z+=+l[M][N]||0}g.push(z)}}for(var N=l.length;N--;){if(l[N].length<O){for(var M=O;M--;){l[N].push(0)}}}T=Math.max.apply(Math,B.stacked?g:T)}T=(B.to)||T;var Q=Math.floor(F/(O*(100+o)+o)*100),r=Math.floor(Q*o/100),p=[],k=u+r,m=(I-1)/T;!B.stacked&&(Q/=J||1);for(var N=0;N<O;N++){p=[];for(var M=0;M<(J||1);M++){var S=J?l[M][N]:l[N],P=e(v,k+Q/2,Math.round(S*m),Q-1,false,n,null,w).attr({stroke:"none",fill:t[J?M:N]});if(J){H[M].push(P)}else{H.push(P)}P.x=v+Math.round(S*m);P.y=k+Q/2;P.w=Math.round(S*m);P.h=Q;P.value=+S;if(!B.stacked){k+=Q}else{p.push(P)}}if(B.stacked){var A=w.rect(v,p[0].y-p[0].h/2,I,Q).attr(h.shim);L.push(A);A.bars=w.set();var E=0;for(var C=p.length;C--;){p[C].toFront()}for(var C=0,K=p.length;C<K;C++){var P=p[C],R,S=Math.round((E+P.value)*m),G=e(v,P.y,S,Q-1,false,n,1,w);A.bars.push(P);E&&P.attr({path:G});P.w=S;P.x=v+S;q.push(R=w.rect(v+E*m,P.y-P.h/2,P.value*m,Q).attr(h.shim));R.bar=P;E+=P.value}k+=Q}k+=r}L.toFront();k=u+r;if(!B.stacked){for(var N=0;N<O;N++){for(var M=0;M<(J||1);M++){var R=w.rect(v,k,I,Q).attr(h.shim);q.push(R);R.bar=J?H[M][N]:H[N];R.value=R.bar.value;k+=Q}k+=r}}D.label=function(Z,W){Z=Z||[];this.labels=w.set();for(var V=0;V<O;V++){for(var U=0;U<J;U++){var y=h.labelise(J?Z[U]&&Z[U][V]:Z[V],J?l[U][V]:l[V],T),Y=W?H[U][V].x-Q/2+3:v+5,x=W?"end":"start",s;this.labels.push(s=w.text(Y,H[U][V].y,y).attr(h.txtattr).attr({fill:B.legendcolor||"#000","text-anchor":"start"}).insertBefore(q[0]));if(s.getBBox().x<v+5){s.attr({x:v+5,"text-anchor":"start"})}else{H[U][V].label=s}}}return this};D.hover=function(j,i){L.hide();q.show();i=i||function(){};q.mouseover(j).mouseout(i);return this};D.hoverColumn=function(j,i){q.hide();L.show();i=i||function(){};L.mouseover(j).mouseout(i);return this};D.each=function(s){if(!Raphael.is(s,"function")){return this}for(var j=q.length;j--;){s.call(q[j])}return this};D.eachColumn=function(s){if(!Raphael.is(s,"function")){return this}for(var j=L.length;j--;){s.call(L[j])}return this};D.click=function(i){L.hide();q.show();q.click(i);return this};D.clickColumn=function(i){q.hide();L.show();L.click(i);return this};D.push(H,q,L);D.bars=H;D.covers=q;return D}var c=function(){};c.prototype=Raphael.g;b.prototype=d.prototype=new c;Raphael.fn.hbarchart=function(h,l,j,g,i,k){return new b(this,h,l,j,g,i,k)};Raphael.fn.barchart=function(h,l,j,g,i,k){return new d(this,h,l,j,g,i,k)}})();
\ No newline at end of file
/*!
* g.Raphael 0.51 - Charting library, based on Raphaël
*
* Copyright (c) 2009-2012 Dmitry Baranovskiy (http://g.raphaeljs.com)
* Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/
Raphael.el.popup=function(d,a,b,f){var e=this.paper||this[0].paper,c,g,i,h;if(e){switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}d=null==d?"up":d;a=a||5;c=this.getBBox();b="number"==typeof b?b:g?c.x+c.width/2:c.x;f="number"==typeof f?f:g?c.y+c.height/2:c.y;i=Math.max(c.width/2-a,0);h=Math.max(c.height/2-a,0);this.translate(b-c.x-(g?c.width/2:0),f-c.y-(g?c.height/2:0));c=this.getBBox();b={up:["M",b,f,"l",-a,-a,-i,0,"a",a,a,0,0,1,-a,-a,"l",0,-c.height,"a",a,a,0,0,
1,a,-a,"l",2*a+2*i,0,"a",a,a,0,0,1,a,a,"l",0,c.height,"a",a,a,0,0,1,-a,a,"l",-i,0,"z"].join(),down:["M",b,f,"l",a,a,i,0,"a",a,a,0,0,1,a,a,"l",0,c.height,"a",a,a,0,0,1,-a,a,"l",-(2*a+2*i),0,"a",a,a,0,0,1,-a,-a,"l",0,-c.height,"a",a,a,0,0,1,a,-a,"l",i,0,"z"].join(),left:["M",b,f,"l",-a,a,0,h,"a",a,a,0,0,1,-a,a,"l",-c.width,0,"a",a,a,0,0,1,-a,-a,"l",0,-(2*a+2*h),"a",a,a,0,0,1,a,-a,"l",c.width,0,"a",a,a,0,0,1,a,a,"l",0,h,"z"].join(),right:["M",b,f,"l",a,-a,0,-h,"a",a,a,0,0,1,a,-a,"l",c.width,0,"a",a,
a,0,0,1,a,a,"l",0,2*a+2*h,"a",a,a,0,0,1,-a,a,"l",-c.width,0,"a",a,a,0,0,1,-a,-a,"l",0,-h,"z"].join()};a={up:{x:-!g*(c.width/2),y:2*-a-(g?c.height/2:c.height)},down:{x:-!g*(c.width/2),y:2*a+(g?c.height/2:c.height)},left:{x:2*-a-(g?c.width/2:c.width),y:-!g*(c.height/2)},right:{x:2*a+(g?c.width/2:c.width),y:-!g*(c.height/2)}}[d];this.translate(a.x,a.y);return e.path(b[d]).attr({fill:"#000",stroke:"none"}).insertBefore(this.node?this:this[0])}};
Raphael.el.tag=function(d,a,b,f){var e=this.paper||this[0].paper;if(e){var e=e.path().attr({fill:"#000",stroke:"#000"}),c=this.getBBox(),g,i,h;switch(this.type){case "text":case "circle":case "ellipse":h=!0;break;default:h=!1}d=d||0;b="number"==typeof b?b:h?c.x+c.width/2:c.x;f="number"==typeof f?f:h?c.y+c.height/2:c.y;a=null==a?5:a;i=0.5522*a;c.height>=2*a?e.attr({path:["M",b,f+a,"a",a,a,0,1,1,0,2*-a,a,a,0,1,1,0,2*a,"m",0,2*-a-3,"a",a+3,a+3,0,1,0,0,2*(a+3),"L",b+a+3,f+c.height/2+3,"l",c.width+6,0,
0,-c.height-6,-c.width-6,0,"L",b,f-a-3].join()}):(g=Math.sqrt(Math.pow(a+3,2)-Math.pow(c.height/2+3,2)),e.attr({path:["M",b,f+a,"c",-i,0,-a,i-a,-a,-a,0,-i,a-i,-a,a,-a,i,0,a,a-i,a,a,0,i,i-a,a,-a,a,"M",b+g,f-c.height/2-3,"a",a+3,a+3,0,1,0,0,c.height+6,"l",a+3-g+c.width+6,0,0,-c.height-6,"L",b+g,f-c.height/2-3].join()}));d=360-d;e.rotate(d,b,f);this.attrs?(this.attr(this.attrs.x?"x":"cx",b+a+3+(!h?"text"==this.type?c.width:0:c.width/2)).attr("y",h?f:f-c.height/2),this.rotate(d,b,f),90<d&&270>d&&this.attr(this.attrs.x?
"x":"cx",b-a-3-(!h?c.width:c.width/2)).rotate(180,b,f)):90<d&&270>d?(this.translate(b-c.x-c.width-a-3,f-c.y-c.height/2),this.rotate(d-180,c.x+c.width+a+3,c.y+c.height/2)):(this.translate(b-c.x+a+3,f-c.y-c.height/2),this.rotate(d,c.x-a-3,c.y+c.height/2));return e.insertBefore(this.node?this:this[0])}};
Raphael.el.drop=function(d,a,b){var f=this.getBBox(),e=this.paper||this[0].paper,c,g;if(e){switch(this.type){case "text":case "circle":case "ellipse":c=!0;break;default:c=!1}d=d||0;a="number"==typeof a?a:c?f.x+f.width/2:f.x;b="number"==typeof b?b:c?f.y+f.height/2:f.y;g=Math.max(f.width,f.height)+Math.min(f.width,f.height);e=e.path(["M",a,b,"l",g,0,"A",0.4*g,0.4*g,0,1,0,a+0.7*g,b-0.7*g,"z"]).attr({fill:"#000",stroke:"none"}).rotate(22.5-d,a,b);d=(d+90)*Math.PI/180;a=a+g*Math.sin(d)-(c?0:f.width/2);
d=b+g*Math.cos(d)-(c?0:f.height/2);this.attrs?this.attr(this.attrs.x?"x":"cx",a).attr(this.attrs.y?"y":"cy",d):this.translate(a-f.x,d-f.y);return e.insertBefore(this.node?this:this[0])}};
Raphael.el.flag=function(d,a,b){var f=this.paper||this[0].paper;if(f){var f=f.path().attr({fill:"#000",stroke:"#000"}),e=this.getBBox(),c=e.height/2,g;switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}d=d||0;a="number"==typeof a?a:g?e.x+e.width/2:e.x;b="number"==typeof b?b:g?e.y+e.height/2:e.y;f.attr({path:["M",a,b,"l",c+3,-c-3,e.width+6,0,0,e.height+6,-e.width-6,0,"z"].join()});d=360-d;f.rotate(d,a,b);this.attrs?(this.attr(this.attrs.x?"x":"cx",a+c+3+(!g?"text"==
this.type?e.width:0:e.width/2)).attr("y",g?b:b-e.height/2),this.rotate(d,a,b),90<d&&270>d&&this.attr(this.attrs.x?"x":"cx",a-c-3-(!g?e.width:e.width/2)).rotate(180,a,b)):90<d&&270>d?(this.translate(a-e.x-e.width-c-3,b-e.y-e.height/2),this.rotate(d-180,e.x+e.width+c+3,e.y+e.height/2)):(this.translate(a-e.x+c+3,b-e.y-e.height/2),this.rotate(d,e.x-c-3,e.y+e.height/2));return f.insertBefore(this.node?this:this[0])}};
Raphael.el.label=function(){var d=this.getBBox(),a=this.paper||this[0].paper,b=Math.min(20,d.width+10,d.height+10)/2;if(a)return a.rect(d.x-b/2,d.y-b/2,d.width+b,d.height+b,b).attr({stroke:"none",fill:"#000"}).insertBefore(this.node?this:this[0])};
Raphael.el.blob=function(d,a,b){var f=this.getBBox(),e=Math.PI/180,c=this.paper||this[0].paper,g,i;if(c){switch(this.type){case "text":case "circle":case "ellipse":g=!0;break;default:g=!1}c=c.path().attr({fill:"#000",stroke:"none"});d=(+d+1?d:45)+90;i=Math.min(f.height,f.width);var a="number"==typeof a?a:g?f.x+f.width/2:f.x,b="number"==typeof b?b:g?f.y+f.height/2:f.y,h=Math.max(f.width+i,25*i/12),j=Math.max(f.height+i,25*i/12);g=a+i*Math.sin((d-22.5)*e);var o=b+i*Math.cos((d-22.5)*e),l=a+i*Math.sin((d+
22.5)*e),d=b+i*Math.cos((d+22.5)*e),e=(l-g)/2;i=(d-o)/2;var h=h/2,j=j/2,n=-Math.sqrt(Math.abs(h*h*j*j-h*h*i*i-j*j*e*e)/(h*h*i*i+j*j*e*e));i=n*h*i/j+(l+g)/2;e=n*-j*e/h+(d+o)/2;c.attr({x:i,y:e,path:["M",a,b,"L",l,d,"A",h,j,0,1,1,g,o,"z"].join()});this.translate(i-f.x-f.width/2,e-f.y-f.height/2);return c.insertBefore(this.node?this:this[0])}};Raphael.fn.label=function(d,a,b){var f=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return f.push(b.label(),b)};
Raphael.fn.popup=function(d,a,b,f,e){var c=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return c.push(b.popup(f,e),b)};Raphael.fn.tag=function(d,a,b,f,e){var c=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return c.push(b.tag(f,e),b)};Raphael.fn.flag=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.flag(f),b)};Raphael.fn.drop=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.drop(f),b)};
Raphael.fn.blob=function(d,a,b,f){var e=this.set(),b=this.text(d,a,b).attr(Raphael.g.txtattr);return e.push(b.blob(f),b)};Raphael.el.lighter=function(d){var d=d||2,a=[this.attrs.fill,this.attrs.stroke];this.fs=this.fs||[a[0],a[1]];a[0]=Raphael.rgb2hsb(Raphael.getRGB(a[0]).hex);a[1]=Raphael.rgb2hsb(Raphael.getRGB(a[1]).hex);a[0].b=Math.min(a[0].b*d,1);a[0].s/=d;a[1].b=Math.min(a[1].b*d,1);a[1].s/=d;this.attr({fill:"hsb("+[a[0].h,a[0].s,a[0].b]+")",stroke:"hsb("+[a[1].h,a[1].s,a[1].b]+")"});return this};
Raphael.el.darker=function(d){var d=d||2,a=[this.attrs.fill,this.attrs.stroke];this.fs=this.fs||[a[0],a[1]];a[0]=Raphael.rgb2hsb(Raphael.getRGB(a[0]).hex);a[1]=Raphael.rgb2hsb(Raphael.getRGB(a[1]).hex);a[0].s=Math.min(a[0].s*d,1);a[0].b/=d;a[1].s=Math.min(a[1].s*d,1);a[1].b/=d;this.attr({fill:"hsb("+[a[0].h,a[0].s,a[0].b]+")",stroke:"hsb("+[a[1].h,a[1].s,a[1].b]+")"});return this};Raphael.el.resetBrightness=function(){this.fs&&(this.attr({fill:this.fs[0],stroke:this.fs[1]}),delete this.fs);return this};
(function(){var d=["lighter","darker","resetBrightness"],a="popup tag flag label drop blob".split(" "),b;for(b in a)(function(a){Raphael.st[a]=function(){return Raphael.el[a].apply(this,arguments)}})(a[b]);for(b in d)(function(a){Raphael.st[a]=function(){for(var b=0;b<this.length;b++)this[b][a].apply(this[b],arguments);return this}})(d[b])})();
Raphael.g={shim:{stroke:"none",fill:"#000","fill-opacity":0},txtattr:{font:"12px Arial, sans-serif",fill:"#fff"},colors:function(){for(var d=[0.6,0.2,0.05,0.1333,0.75,0],a=[],b=0;10>b;b++)b<d.length?a.push("hsb("+d[b]+",.75, .75)"):a.push("hsb("+d[b-d.length]+", 1, .5)");return a}(),snapEnds:function(d,a,b){function f(a){return 0.25>Math.abs(a-0.5)?~~a+0.5:Math.round(a)}var e=d,c=a;if(e==c)return{from:e,to:c,power:0};var e=(c-e)/b,g=c=~~e,b=0;if(c){for(;g;)b--,g=~~(e*Math.pow(10,b))/Math.pow(10,b);
b++}else{if(0==e||!isFinite(e))b=1;else for(;!c;)b=b||1,c=~~(e*Math.pow(10,b))/Math.pow(10,b),b++;b&&b--}c=f(a*Math.pow(10,b))/Math.pow(10,b);c<a&&(c=f((a+0.5)*Math.pow(10,b))/Math.pow(10,b));e=f((d-(0<b?0:0.5))*Math.pow(10,b))/Math.pow(10,b);return{from:e,to:c,power:b}},axis:function(d,a,b,f,e,c,g,i,h,j,o){var j=null==j?2:j,h=h||"t",c=c||10,o=arguments[arguments.length-1],l="|"==h||" "==h?["M",d+0.5,a,"l",0,0.001]:1==g||3==g?["M",d+0.5,a,"l",0,-b]:["M",d,a+0.5,"l",b,0],n=this.snapEnds(f,e,c),p=n.from,
t=n.to,m=n.power,u=0,v={font:"11px 'Fontin Sans', Fontin-Sans, sans-serif"},n=o.set(),t=(t-p)/c,k=p,r=0<m?m:0,s=b/c;if(1==+g||3==+g){m=a;for(p=(g-1?1:-1)*(j+3+!!(g-1));m>=a-b;)"-"!=h&&" "!=h&&(l=l.concat(["M",d-("+"==h||"|"==h?j:2*!(g-1)*j),m+0.5,"l",2*j+1,0])),n.push(o.text(d+p,m,i&&i[u++]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v).attr({"text-anchor":g-1?"start":"end"})),k+=t,m-=s;Math.round(m+s-(a-b))&&("-"!=h&&" "!=h&&(l=l.concat(["M",d-("+"==h||"|"==h?j:2*!(g-1)*j),a-b+0.5,"l",2*j+1,0])),n.push(o.text(d+
p,a-b,i&&i[u]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v).attr({"text-anchor":g-1?"start":"end"})))}else{for(var k=p,r=(0<m)*m,p=(g?-1:1)*(j+9+!g),m=d,s=b/c,q=0,w=0;m<=d+b;)"-"!=h&&" "!=h&&(l=l.concat(["M",m+0.5,a-("+"==h?j:2*!!g*j),"l",0,2*j+1])),n.push(q=o.text(m,a+p,i&&i[u++]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v)),q=q.getBBox(),w>=q.x-5?n.pop(n.length-1).remove():w=q.x+q.width,k+=t,m+=s;Math.round(m-s-d-b)&&("-"!=h&&" "!=h&&(l=l.concat(["M",d+b+0.5,a-("+"==h?j:2*!!g*j),"l",0,2*j+1])),n.push(o.text(d+
b,a+p,i&&i[u]||(Math.round(k)==k?k:+k.toFixed(r))).attr(v)))}l=o.path(l);l.text=n;l.all=o.set([l,n]);l.remove=function(){this.text.remove();this.constructor.prototype.remove.call(this)};return l},labelise:function(d,a,b){return d?(d+"").replace(/(##+(?:\.#+)?)|(%%+(?:\.%+)?)/g,function(d,e,c){if(e)return(+a).toFixed(e.replace(/^#+\.?/g,"").length);if(c)return(100*a/b).toFixed(c.replace(/^%+\.?/g,"").length)+"%"}):(+a).toFixed(0)}};
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment