fix(plugins/isocalendar): algorithm improvements for date ranges (#759) [skip ci]
This commit is contained in:
@@ -13,33 +13,22 @@ export default async function({login, data, graphql, q, imports, queries, accoun
|
|||||||
const now = new Date()
|
const now = new Date()
|
||||||
const start = new Date(now)
|
const start = new Date(now)
|
||||||
if (duration === "full-year")
|
if (duration === "full-year")
|
||||||
start.setFullYear(now.getFullYear() - 1)
|
start.setUTCFullYear(now.getUTCFullYear() - 1)
|
||||||
else
|
else
|
||||||
start.setHours(-24 * 180)
|
start.setUTCHours(-180 * 24)
|
||||||
|
|
||||||
//Compute padding to ensure last row is complete
|
//Ensure start day is a sunday, and that time is set to 00:00:00.000
|
||||||
const padding = new Date(start)
|
if (start.getUTCDay())
|
||||||
padding.setHours(-14 * 24)
|
start.setUTCHours(-start.getUTCDay() * 24)
|
||||||
|
start.setUTCMilliseconds(0)
|
||||||
|
start.setUTCSeconds(0)
|
||||||
|
start.setUTCMinutes(0)
|
||||||
|
start.setUTCHours(0)
|
||||||
|
|
||||||
//Retrieve contribution calendar from graphql api
|
//Compute contribution calendar, highest contributions in a day, streaks and average commits per day
|
||||||
console.debug(`metrics/compute/${login}/plugins > isocalendar > querying api`)
|
|
||||||
const calendar = {}
|
|
||||||
for (const [name, from, to] of [["padding", padding, start], ["weeks", start, now]]) {
|
|
||||||
console.debug(`metrics/compute/${login}/plugins > isocalendar > loading ${name} from "${from.toISOString()}" to "${to.toISOString()}"`)
|
|
||||||
const {user:{calendar:{contributionCalendar:{weeks}}}} = await graphql(queries.isocalendar.calendar({login, from:from.toISOString(), to:to.toISOString()}))
|
|
||||||
calendar[name] = weeks
|
|
||||||
}
|
|
||||||
|
|
||||||
//Apply padding
|
|
||||||
console.debug(`metrics/compute/${login}/plugins > isocalendar > applying padding`)
|
|
||||||
const firstweek = calendar.weeks[0].contributionDays
|
|
||||||
const padded = calendar.padding.flatMap(({contributionDays}) => contributionDays).filter(({date}) => !firstweek.map(({date}) => date).includes(date))
|
|
||||||
while (firstweek.length < 7)
|
|
||||||
firstweek.unshift(padded.pop())
|
|
||||||
|
|
||||||
//Compute the highest contributions in a day, streaks and average commits per day
|
|
||||||
console.debug(`metrics/compute/${login}/plugins > isocalendar > computing stats`)
|
console.debug(`metrics/compute/${login}/plugins > isocalendar > computing stats`)
|
||||||
const {streak, max, average} = await statistics({login, data, graphql, queries})
|
const calendar = {weeks:[]}
|
||||||
|
const {streak, max, average} = await statistics({login, graphql, queries, start, end:now, calendar})
|
||||||
const reference = Math.max(...calendar.weeks.flatMap(({contributionDays}) => contributionDays.map(({contributionCount}) => contributionCount)))
|
const reference = Math.max(...calendar.weeks.flatMap(({contributionDays}) => contributionDays.map(({contributionCount}) => contributionCount)))
|
||||||
|
|
||||||
//Compute SVG
|
//Compute SVG
|
||||||
@@ -91,20 +80,30 @@ export default async function({login, data, graphql, q, imports, queries, accoun
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**Compute max and current streaks */
|
/**Compute max and current streaks */
|
||||||
async function statistics({login, data, graphql, queries}) {
|
async function statistics({login, graphql, queries, start, end, calendar}) {
|
||||||
let average = 0, max = 0, streak = {max:0, current:0}, values = []
|
let average = 0, max = 0, streak = {max:0, current:0}, values = []
|
||||||
const now = new Date()
|
|
||||||
for (let from = new Date(data.user.createdAt); from < now;) {
|
|
||||||
//Load contribution calendar
|
//Load contribution calendar
|
||||||
|
for (let from = new Date(start); from < end;) {
|
||||||
|
//Set date range
|
||||||
let to = new Date(from)
|
let to = new Date(from)
|
||||||
to.setFullYear(to.getFullYear() + 1)
|
to.setUTCHours(+4 * 7 * 24)
|
||||||
if (to > now)
|
if (to > end)
|
||||||
to = now
|
to = end
|
||||||
console.debug(`metrics/compute/${login}/plugins > isocalendar > loading calendar from "${from.toISOString()}" to "${to.toISOString()}"`)
|
//Ensure that date ranges are not overlapping by setting it to previous day at 23:59:59.999
|
||||||
const {user:{calendar:{contributionCalendar:{weeks}}}} = await graphql(queries.isocalendar.calendar({login, from:from.toISOString(), to:to.toISOString()}))
|
const dto = new Date(to)
|
||||||
from = to
|
dto.setUTCHours(-1)
|
||||||
|
dto.setUTCMinutes(59)
|
||||||
|
dto.setUTCSeconds(59)
|
||||||
|
dto.setUTCMilliseconds(999)
|
||||||
|
//Fetch data from api
|
||||||
|
console.debug(`metrics/compute/${login}/plugins > isocalendar > loading calendar from "${from.toISOString()}" to "${dto.toISOString()}"`)
|
||||||
|
const {user:{calendar:{contributionCalendar:{weeks}}}} = await graphql(queries.isocalendar.calendar({login, from:from.toISOString(), to:dto.toISOString()}))
|
||||||
|
calendar.weeks.push(...weeks)
|
||||||
|
//Set next date range start
|
||||||
|
from = new Date(to)
|
||||||
|
}
|
||||||
//Compute streaks
|
//Compute streaks
|
||||||
for (const week of weeks) {
|
for (const week of calendar.weeks) {
|
||||||
for (const day of week.contributionDays) {
|
for (const day of week.contributionDays) {
|
||||||
values.push(day.contributionCount)
|
values.push(day.contributionCount)
|
||||||
max = Math.max(max, day.contributionCount)
|
max = Math.max(max, day.contributionCount)
|
||||||
@@ -112,7 +111,7 @@ async function statistics({login, data, graphql, queries}) {
|
|||||||
streak.max = Math.max(streak.max, streak.current)
|
streak.max = Math.max(streak.max, streak.current)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
//Compute average
|
||||||
average = (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2).replace(/[.]0+$/, "")
|
average = (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2).replace(/[.]0+$/, "")
|
||||||
return {streak, max, average}
|
return {streak, max, average}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user