From a1804e6ea21cd11333bfeeb57674cc02403238ec Mon Sep 17 00:00:00 2001 From: Bauke Date: Tue, 26 Jun 2018 19:26:53 +0200 Subject: [PATCH] Separate statistics functions from main.js --- main.js | 79 ++++++++------------------------------------------- statistics.js | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 67 deletions(-) create mode 100644 statistics.js diff --git a/main.js b/main.js index ebc511a..fe2d248 100644 --- a/main.js +++ b/main.js @@ -4,6 +4,7 @@ const fs = require('fs') const Gitlab = require('gitlab/dist/es5').default const klaw = require('klaw-sync') const path = require('path') +const { avgTime, freqUsers, labelsAlphabet } = require('./statistics') const api = new Gitlab({ token: config.token @@ -162,84 +163,28 @@ function createStatistics() { statistics += `${opened.length} issues were opened and ` statistics += `${closed.length} issues were closed.\n\n` - const averageOpenPerDay = (opened.length / 30).toFixed(2) - const averageClosePerDay = (closed.length / 30).toFixed(2) - statistics += `An average of ${averageOpenPerDay} issues were opened ` - statistics += `and ${averageClosePerDay} issues were closed each day.\n\n` + statistics += `An average of ${(opened.length / 30).toFixed(2)} issues were opened ` + statistics += `and ${(closed.length / 30).toFixed(2)} issues were closed each day.\n\n` - let averageClosedDays - let averageClosedHours - for (const file of closed) { - const issue = require(file.path) - const openedAt = new Date(issue.created_at) - const closedAt = new Date(issue.closed_at) - const diffDays = (closedAt - openedAt) / (1000 * 60 * 60 * 24) - const diffHours = (closedAt - openedAt) / (1000 * 60 * 60) - - averageClosedDays = (typeof averageClosedDays === 'undefined') - ? averageClosedDays = diffDays - : averageClosedDays += diffDays - averageClosedHours = (typeof averageClosedHours === 'undefined') - ? averageClosedHours = diffHours - : averageClosedHours += diffHours - } - averageClosedDays = (averageClosedDays / closed.length).toFixed(2) - averageClosedHours = (averageClosedHours / closed.length).toFixed(2) - - statistics += `The average time to close issues was ${averageClosedDays} days ` - statistics += `or ${averageClosedHours} hours.\n\n` - - let _mostFrequent = {} - for (const file of opened) { - const issue = require(file.path) - if (typeof _mostFrequent[issue.author.username] === 'undefined') _mostFrequent[issue.author.username] = 1 - else _mostFrequent[issue.author.username]++ - } - - let mostFrequent = Object.keys(_mostFrequent) - mostFrequent.sort((a, b) => _mostFrequent[b] - _mostFrequent[a]) - mostFrequent = mostFrequent.slice(0, 3) + statistics += `The average time to close issues was ${avgTime(closed, 'days')} days ` + statistics += `or ${avgTime(closed, 'hours')} hours.\n\n` + const topUsers = freqUsers(opened, 3) statistics += 'Top 3 issue creators:\n\n' - for (const user of mostFrequent) { + for (const user in topUsers) { statistics += `* [${user}](https://gitlab.com/${user}) ` - statistics += `with [${_mostFrequent[user]} issues created](https://gitlab.com/tildes/tildes/issues?state=all&author_username=${user}).\n` + statistics += `with [${topUsers[user]} issues created](https://gitlab.com/tildes/tildes/issues?state=all&author_username=${user}).\n` } - let labels = {} - for (const file of opened) { - const issue = require(file.path) - if (issue.closed_at !== null) continue - for (const label of issue.labels) { - if (typeof labels[label] === 'undefined') labels[label] = 1 - else labels[label]++ - } - } - - let labelsOrdered = {} - Object.keys(labels).sort().forEach(label => labelsOrdered[label] = labels[label]) - + let labels = labelsAlphabet(opened, true) statistics += '\nAmount of labels assigned to currently open issues:\n\n' - - for (const label in labelsOrdered) { + for (const label in labels) { statistics += `* [${label}](https://gitlab.com/tildes/tildes/issues?state=opened&label_name%5B%5D=${label.replace(' ', '+')}): ${labels[label]} times.\n` } - labels = {} - for (const file of closed) { - const issue = require(file.path) - for (const label of issue.labels) { - if (typeof labels[label] === 'undefined') labels[label] = 1 - else labels[label]++ - } - } - - labelsOrdered = {} - Object.keys(labels).sort().forEach(label => labelsOrdered[label] = labels[label]) - + labels = labelsAlphabet(closed, false) statistics += '\nAmount of labels assigned to closed issues:\n\n' - - for (const label in labelsOrdered) { + for (const label in labels) { statistics += `* [${label}](https://gitlab.com/tildes/tildes/issues?state=closed&label_name%5B%5D=${label.replace(' ', '+')}): ${labels[label]} times.\n` } diff --git a/statistics.js b/statistics.js new file mode 100644 index 0000000..4ad0e76 --- /dev/null +++ b/statistics.js @@ -0,0 +1,76 @@ +/** + * @function avgTime + * @description Returns the average time it takes to close an issue in hours or days. + * @param {Array} data Array with paths leading to GitLab Issue .json files + * @param {string} time 'hours' or 'days' + */ + +function avgTime(data, time) { + if (time !== 'hours' && time !== 'days') return Error('avgTime(data, time): time should be "hours" or "days"') + let avg + for (const file of data) { + const issue = require(file.path) + const openDate = new Date(issue.created_at) + const closeDate = new Date(issue.closed_at) + let diff + if (time === 'days') diff = (closeDate - openDate) / (1000 * 60 * 60 * 24) + else if (time === 'hours') diff = (closeDate - openDate) / (1000 * 60 * 60) + avg = (typeof avg === 'undefined') + ? avg = diff + : avg += diff + } + return (avg / data.length).toFixed(2) +} + +/** + * @function freqUsers + * @description Returns the top X issue creators. + * @param {Array} data Array with paths leading to GitLab Issue .json files + * @param {number} maxUsers Maximum amount of users to return, defaults to 3 + * @returns {Object} + */ + +function freqUsers(data, maxUsers) { + if (typeof maxUsers === 'undefined') maxUsers = 3 + let userCounts = {} + for (const file of data) { + const issue = require(file.path) + if (typeof userCounts[issue.author.username] === 'undefined') userCounts[issue.author.username] = 1 + else userCounts[issue.author.username]++ + } + const sortedArray = Object.keys(userCounts).sort((a, b) => userCounts[b] - userCounts[a]) + const sortedObject = {} + for (let i = 0; i < maxUsers; i++) { + if (typeof sortedArray[i] === 'undefined') break + sortedObject[sortedArray[i]] = userCounts[sortedArray[i]] + } + return sortedObject +} + +/** + * @function labelsAlphabet + * @description Returns all labels found in alphabetical order with their amount. + * @param {Array} data Array with paths leading to GitLab Issue .json files + * @param {boolean} checkNull Boolean whether or not to check if closed_at is null (for currently open issues) + * @returns {Object} + */ + +function labelsAlphabet(data, checkNull) { + if (typeof checkNull === 'undefined') checkNull = false + const labels = {} + for (const file of data) { + const issue = require(file.path) + if (checkNull && issue.closed_at !== null) continue + for (const label of issue.labels) { + if (typeof labels[label] === 'undefined') labels[label] = 1 + else labels[label]++ + } + } + const labelsOrdered = {} + Object.keys(labels).sort().forEach(label => labelsOrdered[label] = labels[label]) + return labelsOrdered +} + +exports.avgTime = avgTime +exports.freqUsers = freqUsers +exports.labelsAlphabet = labelsAlphabet