Separate statistics functions from main.js
This commit is contained in:
parent
cc1e1fa50c
commit
a1804e6ea2
79
main.js
79
main.js
|
@ -4,6 +4,7 @@ const fs = require('fs')
|
||||||
const Gitlab = require('gitlab/dist/es5').default
|
const Gitlab = require('gitlab/dist/es5').default
|
||||||
const klaw = require('klaw-sync')
|
const klaw = require('klaw-sync')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const { avgTime, freqUsers, labelsAlphabet } = require('./statistics')
|
||||||
|
|
||||||
const api = new Gitlab({
|
const api = new Gitlab({
|
||||||
token: config.token
|
token: config.token
|
||||||
|
@ -162,84 +163,28 @@ function createStatistics() {
|
||||||
statistics += `${opened.length} issues were opened and `
|
statistics += `${opened.length} issues were opened and `
|
||||||
statistics += `${closed.length} issues were closed.\n\n`
|
statistics += `${closed.length} issues were closed.\n\n`
|
||||||
|
|
||||||
const averageOpenPerDay = (opened.length / 30).toFixed(2)
|
statistics += `An average of ${(opened.length / 30).toFixed(2)} issues were opened `
|
||||||
const averageClosePerDay = (closed.length / 30).toFixed(2)
|
statistics += `and ${(closed.length / 30).toFixed(2)} issues were closed each day.\n\n`
|
||||||
statistics += `An average of ${averageOpenPerDay} issues were opened `
|
|
||||||
statistics += `and ${averageClosePerDay} issues were closed each day.\n\n`
|
|
||||||
|
|
||||||
let averageClosedDays
|
statistics += `The average time to close issues was ${avgTime(closed, 'days')} days `
|
||||||
let averageClosedHours
|
statistics += `or ${avgTime(closed, 'hours')} hours.\n\n`
|
||||||
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)
|
|
||||||
|
|
||||||
|
const topUsers = freqUsers(opened, 3)
|
||||||
statistics += 'Top 3 issue creators:\n\n'
|
statistics += 'Top 3 issue creators:\n\n'
|
||||||
for (const user of mostFrequent) {
|
for (const user in topUsers) {
|
||||||
statistics += `* [${user}](https://gitlab.com/${user}) `
|
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 = {}
|
let labels = labelsAlphabet(opened, true)
|
||||||
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])
|
|
||||||
|
|
||||||
statistics += '\nAmount of labels assigned to currently open issues:\n\n'
|
statistics += '\nAmount of labels assigned to currently open issues:\n\n'
|
||||||
|
for (const label in labels) {
|
||||||
for (const label in labelsOrdered) {
|
|
||||||
statistics += `* [${label}](https://gitlab.com/tildes/tildes/issues?state=opened&label_name%5B%5D=${label.replace(' ', '+')}): ${labels[label]} times.\n`
|
statistics += `* [${label}](https://gitlab.com/tildes/tildes/issues?state=opened&label_name%5B%5D=${label.replace(' ', '+')}): ${labels[label]} times.\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
labels = {}
|
labels = labelsAlphabet(closed, false)
|
||||||
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])
|
|
||||||
|
|
||||||
statistics += '\nAmount of labels assigned to closed issues:\n\n'
|
statistics += '\nAmount of labels assigned to closed issues:\n\n'
|
||||||
|
for (const label in labels) {
|
||||||
for (const label in labelsOrdered) {
|
|
||||||
statistics += `* [${label}](https://gitlab.com/tildes/tildes/issues?state=closed&label_name%5B%5D=${label.replace(' ', '+')}): ${labels[label]} times.\n`
|
statistics += `* [${label}](https://gitlab.com/tildes/tildes/issues?state=closed&label_name%5B%5D=${label.replace(' ', '+')}): ${labels[label]} times.\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
Reference in New Issue