-
+
- = Helper\a(t('Back to the board'), 'board', 'show', array('project_id' => $project['id'])) ?> +
diff --git a/app/Controller/Analytic.php b/app/Controller/Analytic.php
new file mode 100644
index 000000000..68177c832
--- /dev/null
+++ b/app/Controller/Analytic.php
@@ -0,0 +1,56 @@
+projectPermission->getAllowedProjects($this->acl->getUserId());
+ $params['analytic_content_for_layout'] = $this->template->load($template, $params);
+
+ return $this->template->layout('analytic/layout', $params);
+ }
+
+ /**
+ * Show task distribution graph
+ *
+ * @access public
+ */
+ public function repartition()
+ {
+ $project = $this->getProject();
+ $metrics = $this->projectAnalytic->getTaskRepartition($project['id']);
+
+ if ($this->request->isAjax()) {
+ $this->response->json(array(
+ 'metrics' => $metrics,
+ 'labels' => array(
+ 'column_title' => t('Column'),
+ 'nb_tasks' => t('Number of tasks'),
+ )
+ ));
+ }
+ else {
+ $this->response->html($this->layout('analytic/repartition', array(
+ 'project' => $project,
+ 'metrics' => $metrics,
+ 'title' => t('Task repartition for "%s"', $project['name']),
+ )));
+ }
+ }
+}
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
index c0483aa11..7eb75b072 100644
--- a/app/Controller/Base.php
+++ b/app/Controller/Base.php
@@ -26,6 +26,7 @@ use Model\LastLogin;
* @property \Model\Notification $notification
* @property \Model\Project $project
* @property \Model\ProjectPermission $projectPermission
+ * @property \Model\ProjectAnalytic $projectAnalytic
* @property \Model\SubTask $subTask
* @property \Model\Task $task
* @property \Model\TaskHistory $taskHistory
diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php
index 8701cf3d9..590f25121 100644
--- a/app/Locale/da_DK/translations.php
+++ b/app/Locale/da_DK/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php
index e47e55c1e..807118d8f 100644
--- a/app/Locale/de_DE/translations.php
+++ b/app/Locale/de_DE/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php
index 72c2e32fe..25df8acf4 100644
--- a/app/Locale/es_ES/translations.php
+++ b/app/Locale/es_ES/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php
index 7711773be..517430ea6 100644
--- a/app/Locale/fi_FI/translations.php
+++ b/app/Locale/fi_FI/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php
index 05756a93c..3afa53ce9 100644
--- a/app/Locale/fr_FR/translations.php
+++ b/app/Locale/fr_FR/translations.php
@@ -565,4 +565,10 @@ return array(
'Columns' => 'Colonnes',
'Task' => 'Tâche',
'Your are not member of any project.' => 'Vous n\'êtes membre d\'aucun projet.',
+ 'Percentage' => 'Pourcentage',
+ 'Number of tasks' => 'Nombre de tâches',
+ 'Task distribution' => 'Répartition des tâches',
+ 'Reportings' => 'Rapports',
+ 'Task repartition for "%s"' => 'Répartition des tâches pour « %s »',
+ 'Analytics' => 'Analytique',
);
diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php
index 64beacabe..81ccbd863 100644
--- a/app/Locale/it_IT/translations.php
+++ b/app/Locale/it_IT/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php
index 3d9c8440d..2fdfb3d6f 100644
--- a/app/Locale/ja_JP/translations.php
+++ b/app/Locale/ja_JP/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php
index 19befac77..45253fe1e 100644
--- a/app/Locale/pl_PL/translations.php
+++ b/app/Locale/pl_PL/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php
index 627447839..778bfd3a6 100644
--- a/app/Locale/pt_BR/translations.php
+++ b/app/Locale/pt_BR/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php
index b5c73a8f7..f2eaca630 100644
--- a/app/Locale/ru_RU/translations.php
+++ b/app/Locale/ru_RU/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php
index 39cbff16c..4f9d815a5 100644
--- a/app/Locale/sv_SE/translations.php
+++ b/app/Locale/sv_SE/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php
index eefbdcf39..8a1c8b357 100644
--- a/app/Locale/th_TH/translations.php
+++ b/app/Locale/th_TH/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php
index 7db09c595..3d45532a6 100644
--- a/app/Locale/zh_CN/translations.php
+++ b/app/Locale/zh_CN/translations.php
@@ -565,4 +565,10 @@ return array(
// 'Columns' => '',
// 'Task' => '',
// 'Your are not member of any project.' => '',
+ // 'Percentage' => '',
+ // 'Number of tasks' => '',
+ // 'Task distribution' => '',
+ // 'Reportings' => '',
+ // 'Task repartition for "%s"' => '',
+ // 'Analytics' => '',
);
diff --git a/app/Model/Acl.php b/app/Model/Acl.php
index 9a6866d37..52957130b 100644
--- a/app/Model/Acl.php
+++ b/app/Model/Acl.php
@@ -41,6 +41,7 @@ class Acl extends Base
'task' => array('show', 'create', 'save', 'edit', 'update', 'close', 'open', 'duplicate', 'remove', 'description', 'move', 'copy', 'time'),
'category' => array('index', 'save', 'edit', 'update', 'confirm', 'remove'),
'action' => array('index', 'event', 'params', 'create', 'confirm', 'remove'),
+ 'analytic' => array('repartition'),
);
/**
diff --git a/app/Model/ProjectAnalytic.php b/app/Model/ProjectAnalytic.php
new file mode 100644
index 000000000..ccd2c4c99
--- /dev/null
+++ b/app/Model/ProjectAnalytic.php
@@ -0,0 +1,43 @@
+board->getColumns($project_id);
+
+ foreach ($columns as $column) {
+
+ $nb_tasks = $this->taskFinder->countByColumnId($project_id, $column['id']);
+ $total += $nb_tasks;
+
+ $metrics[] = array(
+ 'column_title' => $column['title'],
+ 'nb_tasks' => $nb_tasks,
+ );
+ }
+
+ foreach ($metrics as &$metric) {
+ $metric['percentage'] = round(($metric['nb_tasks'] * 100) / $total, 2);
+ }
+
+ return $metrics;
+ }
+}
diff --git a/app/Template/analytic/layout.php b/app/Template/analytic/layout.php
new file mode 100644
index 000000000..2dd7a4f50
--- /dev/null
+++ b/app/Template/analytic/layout.php
@@ -0,0 +1,18 @@
+= Helper\js('assets/js/d3.v3.4.8.min.js') ?>
+= Helper\js('assets/js/dimple.v2.1.0.min.js') ?>
+
+
+
+
| = t('Column') ?> | += t('Number of tasks') ?> | += t('Percentage') ?> | +
|---|---|---|
| + = Helper\escape($metric['column_title']) ?> + | ++ = $metric['nb_tasks'] ?> + | ++ = n($metric['percentage']) ?>% + | +
= t('Sorry, I didn\'t found this information in my database!') ?>
diff --git a/app/Template/board_index.php b/app/Template/board_index.php index d15d455f1..e478680f8 100644 --- a/app/Template/board_index.php +++ b/app/Template/board_index.php @@ -24,6 +24,10 @@ = Helper\a(t('Activity'), 'project', 'activity', array('project_id' => $current_project_id)) ?> +=i.length)return n;var e=[],u=a[r++];return n.forEach(function(n,u){e.push({key:n,values:t(u,r)})}),u?e.sort(function(n,t){return u(n.key,t.key)}):e}var r,e,u={},i=[],a=[];return u.map=function(t,r){return n(r,t,0)},u.entries=function(r){return t(n(Bo.map,r,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return r=n,u},u.rollup=function(n){return e=n,u},u},Bo.set=function(n){var t=new h;if(n)for(var r=0,e=n.length;e>r;++r)t.add(n[r]);return t},i(h,{has:a,add:function(n){return this[sa+n]=!0,n},remove:function(n){return n=sa+n,n in this&&delete this[n]},values:s,size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===la&&n.call(this,t.substring(1))}}),Bo.behavior={},Bo.rebind=function(n,t){for(var r,e=1,u=arguments.length;++e=0&&(e=n.substring(r+1),n=n.substring(0,r)),n)return arguments.length<2?this[n].on(e):this[n].on(e,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(e,null);return this}},Bo.event=null,Bo.requote=function(n){return n.replace(ha,"\\$&")};var ha=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,ga={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var r in t)n[r]=t[r]},pa=function(n,t){return t.querySelector(n)},va=function(n,t){return t.querySelectorAll(n)},da=Ko[p(Ko,"matchesSelector")],ma=function(n,t){return da.call(n,t)};"function"==typeof Sizzle&&(pa=function(n,t){return Sizzle(n,t)[0]||null},va=Sizzle,ma=Sizzle.matchesSelector),Bo.selection=function(){return _a};var ya=Bo.selection.prototype=[];ya.select=function(n){var t,r,e,u,i=[];n=b(n);for(var o=-1,a=this.length;++o=0&&(r=n.substring(0,t),n=n.substring(t+1)),xa.hasOwnProperty(r)?{space:xa[r],local:n}:n}},ya.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var r=this.node();return n=Bo.ns.qualify(n),n.local?r.getAttributeNS(n.space,n.local):r.getAttribute(n)}for(t in n)this.each(S(t,n[t]));return this}return this.each(S(n,t))},ya.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var r=this.node(),e=(n=A(n)).length,u=-1;if(t=r.classList){for(;++u =0?n.substring(0,t):n,e=t>=0?n.substring(t+1):"in";return r=es.get(r)||rs,e=us.get(e)||At,yu(e(r.apply(null,Jo.call(arguments,1))))},Bo.interpolateHcl=Lu,Bo.interpolateHsl=Tu,Bo.interpolateLab=qu,Bo.interpolateRound=Ru,Bo.transform=function(n){var t=Go.createElementNS(Bo.ns.prefix.svg,"g");return(Bo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var r=t.transform.baseVal.consolidate()}return new Du(r?r.matrix:is)})(n)},Du.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var is={a:1,b:0,c:0,d:1,e:0,f:0};Bo.interpolateTransform=Hu,Bo.layout={},Bo.layout.bundle=function(){return function(n){for(var t=[],r=-1,e=n.length;++rl;){var e=n.charCodeAt(l++),a=1;if(10===e)u=!0;else if(13===e)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(e!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var e,u,i={},o={},a=[],s=n.length,l=0,f=0;(e=r())!==o;){for(var h=[];e!==i&&e!==o;)h.push(e),e=r();(!t||(h=t(h,f++)))&&a.push(h)}return a},r.format=function(t){if(Array.isArray(t[0]))return r.formatRows(t);var e=new h,u=[];return t.forEach(function(n){for(var t in n)e.has(t)||u.push(e.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},r.formatRows=function(n){return n.map(i).join("\n")},r},Bo.csv=Bo.dsv(",","text/csv"),Bo.tsv=Bo.dsv(" ","text/tab-separated-values"),Bo.touch=function(n,t,r){if(arguments.length<3&&(r=t,t=x().changedTouches),t)for(var e,u=0,i=t.length;i>u;++u)if((e=t[u]).identifier===r)return Z(n,e)};var Xa,Ba,Ja,Wa,Ga,Ka=Qo[p(Qo,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Bo.timer=function(n,t,r){var e=arguments.length;2>e&&(t=0),3>e&&(r=Date.now());var u=r+t,i={c:n,t:u,f:!1,n:null};Ba?Ba.n=i:Xa=i,Ba=i,Ja||(Wa=clearTimeout(Wa),Ja=1,Ka(Lt))},Bo.timer.flush=function(){Tt(),qt()},Bo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Qa=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Dt);Bo.formatPrefix=function(n,t){var r=0;return n&&(0>n&&(n*=-1),t&&(n=Bo.round(n,Rt(n,t))),r=1+Math.floor(1e-12+Math.log(n)/Math.LN10),r=Math.max(-24,Math.min(24,3*Math.floor((r-1)/3)))),Qa[8+r/3]};var nc=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,tc=Bo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Bo.round(n,Rt(n,t))).toFixed(Math.max(0,Math.min(20,Rt(n*(1+1e-15),t))))}}),rc=Bo.time={},ec=Date;jt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){uc.setUTCDate.apply(this._,arguments)},setDay:function(){uc.setUTCDay.apply(this._,arguments)},setFullYear:function(){uc.setUTCFullYear.apply(this._,arguments)},setHours:function(){uc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){uc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){uc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){uc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){uc.setUTCSeconds.apply(this._,arguments)},setTime:function(){uc.setTime.apply(this._,arguments)}};var uc=Date.prototype;rc.year=Ht(function(n){return n=rc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),rc.years=rc.year.range,rc.years.utc=rc.year.utc.range,rc.day=Ht(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),rc.days=rc.day.range,rc.days.utc=rc.day.utc.range,rc.dayOfYear=function(n){var t=rc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var r=rc[n]=Ht(function(n){return(n=rc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var r=rc.year(n).getDay();return Math.floor((rc.dayOfYear(n)+(r+t)%7)/7)-(r!==t)});rc[n+"s"]=r.range,rc[n+"s"].utc=r.utc.range,rc[n+"OfYear"]=function(n){var r=rc.year(n).getDay();return Math.floor((rc.dayOfYear(n)+(r+t)%7)/7)}}),rc.week=rc.sunday,rc.weeks=rc.sunday.range,rc.weeks.utc=rc.sunday.utc.range,rc.weekOfYear=rc.sundayOfYear;var ic={"-":"",_:" ",0:"0"},oc=/^\s*\d+/,ac=/^%/;Bo.locale=function(n){return{numberFormat:Pt(n),timeFormat:Ot(n)}};var cc=Bo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Bo.format=cc.numberFormat,Bo.geo={},cr.prototype={s:0,t:0,add:function(n){sr(n,this.t,sc),sr(sc.s,this.s,this),this.s?this.t+=sc.t:this.s=sc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var sc=new cr;Bo.geo.stream=function(n,t){n&&lc.hasOwnProperty(n.type)?lc[n.type](n,t):lr(n,t)};var lc={Feature:function(n,t){lr(n.geometry,t)},FeatureCollection:function(n,t){for(var r=n.features,e=-1,u=r.length;++en?4*ka+n:n,pc.lineStart=pc.lineEnd=pc.point=v}};Bo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,r){var e=pr([t*za,r*za]);if(m){var u=dr(m,e),i=[u[1],-u[0],0],o=dr(i,u);xr(o),o=Mr(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=ca(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>r&&(f=r),r>g&&(g=r);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,r);m=e,p=t}function r(){_.point=t}function e(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,r){if(m){var e=n-p;y+=ca(e)>180?e+(e>0?360:-360):e}else v=n,d=r;pc.point(n,r),t(n,r)}function i(){pc.lineStart()}function o(){u(v,d),pc.lineEnd(),ca(y)>Ca&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n=s,h=e>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=lu()),f?u=s:a=s,h?o=l:c=l,i(n,t,r,e,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=Et(a),M=Et(c);if(null!=t)v=t,d=r,m=e,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.xt;++t)(e=m[t]).index=t,e.weight=0;for(t=0;l>t;++t)e=y[t],"number"==typeof e.source&&(e.source=m[e.source]),"number"==typeof e.target&&(e.target=m[e.target]),++e.source.weight,++e.target.weight;for(t=0;c>t;++t)e=m[t],isNaN(e.x)&&(e.x=n("x",p)),isNaN(e.y)&&(e.y=n("y",v)),isNaN(e.px)&&(e.px=e.x),isNaN(e.py)&&(e.py=e.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return r||(r=Bo.behavior.drag().origin(At).on("dragstart.force",Vu).on("drag.force",t).on("dragend.force",$u)),arguments.length?(this.on("mouseover.force",Xu).on("mouseout.force",Bu).call(r),void 0):r},Bo.rebind(a,c,"on")};var os=20,as=1,cs=1/0;Bo.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(s=r.call(n,i,i.depth))&&(c=s.length)){for(var c,s,l;--c>=0;)o.push(l=s[c]),l.parent=i,l.depth=i.depth+1;e&&(i.value=0),i.children=s}else e&&(i.value=+e.call(n,i,i.depth)||0),delete i.children;return Ku(u,function(n){var r,u;t&&(r=n.children)&&r.sort(t),e&&(u=n.parent)&&(u.value+=n.value)}),a}var t=ti,r=Qu,e=ni;return n.sort=function(r){return arguments.length?(t=r,n):t},n.children=function(t){return arguments.length?(r=t,n):r},n.value=function(t){return arguments.length?(e=t,n):e},n.revalue=function(t){return e&&(Gu(t,function(n){n.children&&(n.value=0)}),Ku(t,function(t){var r;t.children||(t.value=+e.call(n,t,t.depth)||0),(r=t.parent)&&(r.value+=t.value)})),t},n},Bo.layout.partition=function(){function n(t,r,e,u){var i=t.children;if(t.x=r,t.y=t.depth*u,t.dx=e,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(e=t.value?e/t.value:0;++s