diff options
author | Gerardo Zamudio <gerardozamudio@users.noreply.github.com> | 2016-02-24 23:48:50 -0600 |
---|---|---|
committer | Gerardo Zamudio <gerardozamudio@users.noreply.github.com> | 2016-02-24 23:48:50 -0600 |
commit | e4de6b3898b64b26d29aff31f21df5fda8055686 (patch) | |
tree | 575f8a65440f291d70a070d168eafca8c82a6459 /app/Analytic | |
parent | d9ffbea174ea6524d0a22f8375ca8b3aa04a3c96 (diff) | |
parent | a6540bc604c837d92c9368540c145606723e97f7 (diff) |
Merge pull request #1 from fguillot/master
Update from upstream
Diffstat (limited to 'app/Analytic')
-rw-r--r-- | app/Analytic/AverageLeadCycleTimeAnalytic.php | 114 | ||||
-rw-r--r-- | app/Analytic/AverageTimeSpentColumnAnalytic.php | 153 | ||||
-rw-r--r-- | app/Analytic/EstimatedTimeComparisonAnalytic.php | 50 | ||||
-rw-r--r-- | app/Analytic/TaskDistributionAnalytic.php | 48 | ||||
-rw-r--r-- | app/Analytic/UserDistributionAnalytic.php | 56 |
5 files changed, 421 insertions, 0 deletions
diff --git a/app/Analytic/AverageLeadCycleTimeAnalytic.php b/app/Analytic/AverageLeadCycleTimeAnalytic.php new file mode 100644 index 00000000..fd85f864 --- /dev/null +++ b/app/Analytic/AverageLeadCycleTimeAnalytic.php @@ -0,0 +1,114 @@ +<?php + +namespace Kanboard\Analytic; + +use Kanboard\Core\Base; +use Kanboard\Model\Task; + +/** + * Average Lead and Cycle Time + * + * @package analytic + * @author Frederic Guillot + */ +class AverageLeadCycleTimeAnalytic extends Base +{ + /** + * Build report + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function build($project_id) + { + $stats = array( + 'count' => 0, + 'total_lead_time' => 0, + 'total_cycle_time' => 0, + 'avg_lead_time' => 0, + 'avg_cycle_time' => 0, + ); + + $tasks = $this->getTasks($project_id); + + foreach ($tasks as &$task) { + $stats['count']++; + $stats['total_lead_time'] += $this->calculateLeadTime($task); + $stats['total_cycle_time'] += $this->calculateCycleTime($task); + } + + $stats['avg_lead_time'] = $this->calculateAverage($stats, 'total_lead_time'); + $stats['avg_cycle_time'] = $this->calculateAverage($stats, 'total_cycle_time'); + + return $stats; + } + + /** + * Calculate average + * + * @access private + * @param array &$stats + * @param string $field + * @return float + */ + private function calculateAverage(array &$stats, $field) + { + if ($stats['count'] > 0) { + return (int) ($stats[$field] / $stats['count']); + } + + return 0; + } + + /** + * Calculate lead time + * + * @access private + * @param array &$task + * @return integer + */ + private function calculateLeadTime(array &$task) + { + $end = $task['date_completed'] ?: time(); + $start = $task['date_creation']; + + return $end - $start; + } + + /** + * Calculate cycle time + * + * @access private + * @param array &$task + * @return integer + */ + private function calculateCycleTime(array &$task) + { + if (empty($task['date_started'])) { + return 0; + } + + $end = $task['date_completed'] ?: time(); + $start = $task['date_started']; + + return $end - $start; + } + + /** + * Get the 1000 last created tasks + * + * @access private + * @return array + */ + private function getTasks($project_id) + { + return $this->db + ->table(Task::TABLE) + ->columns('date_completed', 'date_creation', 'date_started') + ->eq('project_id', $project_id) + ->desc('id') + ->limit(1000) + ->findAll(); + } +} diff --git a/app/Analytic/AverageTimeSpentColumnAnalytic.php b/app/Analytic/AverageTimeSpentColumnAnalytic.php new file mode 100644 index 00000000..bef55419 --- /dev/null +++ b/app/Analytic/AverageTimeSpentColumnAnalytic.php @@ -0,0 +1,153 @@ +<?php + +namespace Kanboard\Analytic; + +use Kanboard\Core\Base; +use Kanboard\Model\Task; + +/** + * Average Time Spent by Column + * + * @package analytic + * @author Frederic Guillot + */ +class AverageTimeSpentColumnAnalytic extends Base +{ + /** + * Build report + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function build($project_id) + { + $stats = $this->initialize($project_id); + + $this->processTasks($stats, $project_id); + $this->calculateAverage($stats); + + return $stats; + } + + /** + * Initialize default values for each column + * + * @access private + * @param integer $project_id + * @return array + */ + private function initialize($project_id) + { + $stats = array(); + $columns = $this->column->getList($project_id); + + foreach ($columns as $column_id => $column_title) { + $stats[$column_id] = array( + 'count' => 0, + 'time_spent' => 0, + 'average' => 0, + 'title' => $column_title, + ); + } + + return $stats; + } + + /** + * Calculate time spent for each tasks for each columns + * + * @access private + * @param array $stats + * @param integer $project_id + */ + private function processTasks(array &$stats, $project_id) + { + $tasks = $this->getTasks($project_id); + + foreach ($tasks as &$task) { + foreach ($this->getTaskTimeByColumns($task) as $column_id => $time_spent) { + if (isset($stats[$column_id])) { + $stats[$column_id]['count']++; + $stats[$column_id]['time_spent'] += $time_spent; + } + } + } + } + + /** + * Calculate averages + * + * @access private + * @param array $stats + */ + private function calculateAverage(array &$stats) + { + foreach ($stats as &$column) { + $this->calculateColumnAverage($column); + } + } + + /** + * Calculate column average + * + * @access private + * @param array $column + */ + private function calculateColumnAverage(array &$column) + { + if ($column['count'] > 0) { + $column['average'] = (int) ($column['time_spent'] / $column['count']); + } + } + + /** + * Get time spent for each column for a given task + * + * @access private + * @param array $task + * @return array + */ + private function getTaskTimeByColumns(array &$task) + { + $columns = $this->transition->getTimeSpentByTask($task['id']); + + if (! isset($columns[$task['column_id']])) { + $columns[$task['column_id']] = 0; + } + + $columns[$task['column_id']] += $this->getTaskTimeSpentInCurrentColumn($task); + + return $columns; + } + + /** + * Calculate time spent of a task in the current column + * + * @access private + * @param array $task + */ + private function getTaskTimeSpentInCurrentColumn(array &$task) + { + $end = $task['date_completed'] ?: time(); + return $end - $task['date_moved']; + } + + /** + * Fetch the last 1000 tasks + * + * @access private + * @param integer $project_id + * @return array + */ + private function getTasks($project_id) + { + return $this->db + ->table(Task::TABLE) + ->columns('id', 'date_completed', 'date_moved', 'column_id') + ->eq('project_id', $project_id) + ->desc('id') + ->limit(1000) + ->findAll(); + } +} diff --git a/app/Analytic/EstimatedTimeComparisonAnalytic.php b/app/Analytic/EstimatedTimeComparisonAnalytic.php new file mode 100644 index 00000000..490bcd50 --- /dev/null +++ b/app/Analytic/EstimatedTimeComparisonAnalytic.php @@ -0,0 +1,50 @@ +<?php + +namespace Kanboard\Analytic; + +use Kanboard\Core\Base; +use Kanboard\Model\Task; + +/** + * Estimated/Spent Time Comparison + * + * @package analytic + * @author Frederic Guillot + */ +class EstimatedTimeComparisonAnalytic extends Base +{ + /** + * Build report + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function build($project_id) + { + $rows = $this->db->table(Task::TABLE) + ->columns('SUM(time_estimated) AS time_estimated', 'SUM(time_spent) AS time_spent', 'is_active') + ->eq('project_id', $project_id) + ->groupBy('is_active') + ->findAll(); + + $metrics = array( + 'open' => array( + 'time_spent' => 0, + 'time_estimated' => 0, + ), + 'closed' => array( + 'time_spent' => 0, + 'time_estimated' => 0, + ), + ); + + foreach ($rows as $row) { + $key = $row['is_active'] == Task::STATUS_OPEN ? 'open' : 'closed'; + $metrics[$key]['time_spent'] = $row['time_spent']; + $metrics[$key]['time_estimated'] = $row['time_estimated']; + } + + return $metrics; + } +} diff --git a/app/Analytic/TaskDistributionAnalytic.php b/app/Analytic/TaskDistributionAnalytic.php new file mode 100644 index 00000000..838652e3 --- /dev/null +++ b/app/Analytic/TaskDistributionAnalytic.php @@ -0,0 +1,48 @@ +<?php + +namespace Kanboard\Analytic; + +use Kanboard\Core\Base; + +/** + * Task Distribution + * + * @package analytic + * @author Frederic Guillot + */ +class TaskDistributionAnalytic extends Base +{ + /** + * Build report + * + * @access public + * @param integer $project_id Project id + * @return array + */ + public function build($project_id) + { + $metrics = array(); + $total = 0; + $columns = $this->column->getAll($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, + ); + } + + if ($total === 0) { + return array(); + } + + foreach ($metrics as &$metric) { + $metric['percentage'] = round(($metric['nb_tasks'] * 100) / $total, 2); + } + + return $metrics; + } +} diff --git a/app/Analytic/UserDistributionAnalytic.php b/app/Analytic/UserDistributionAnalytic.php new file mode 100644 index 00000000..e1815f9c --- /dev/null +++ b/app/Analytic/UserDistributionAnalytic.php @@ -0,0 +1,56 @@ +<?php + +namespace Kanboard\Analytic; + +use Kanboard\Core\Base; + +/** + * User Distribution + * + * @package analytic + * @author Frederic Guillot + */ +class UserDistributionAnalytic extends Base +{ + /** + * Build Report + * + * @access public + * @param integer $project_id + * @return array + */ + public function build($project_id) + { + $metrics = array(); + $total = 0; + $tasks = $this->taskFinder->getAll($project_id); + $users = $this->projectUserRole->getAssignableUsersList($project_id); + + foreach ($tasks as $task) { + $user = isset($users[$task['owner_id']]) ? $users[$task['owner_id']] : $users[0]; + $total++; + + if (! isset($metrics[$user])) { + $metrics[$user] = array( + 'nb_tasks' => 0, + 'percentage' => 0, + 'user' => $user, + ); + } + + $metrics[$user]['nb_tasks']++; + } + + if ($total === 0) { + return array(); + } + + foreach ($metrics as &$metric) { + $metric['percentage'] = round(($metric['nb_tasks'] * 100) / $total, 2); + } + + ksort($metrics); + + return array_values($metrics); + } +} |