//Setup export default async function({login, data, graphql, q, imports, queries, account}, {enabled = false, extras = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!q.isocalendar) || (!imports.metadata.plugins.isocalendar.enabled(enabled, {extras}))) return null //Load inputs let {duration} = imports.metadata.plugins.isocalendar.inputs({data, account, q}) //Compute start day const now = new Date() const start = new Date(now) if (duration === "full-year") start.setUTCFullYear(now.getUTCFullYear() - 1) else start.setUTCHours(-180 * 24) //Ensure start day is a sunday, and that time is set to 00:00:00.000 if (start.getUTCDay()) start.setUTCHours(-start.getUTCDay() * 24) start.setUTCMilliseconds(0) start.setUTCSeconds(0) start.setUTCMinutes(0) start.setUTCHours(0) //Compute contribution calendar, highest contributions in a day, streaks and average commits per day console.debug(`metrics/compute/${login}/plugins > isocalendar > computing stats`) 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))) //Compute SVG console.debug(`metrics/compute/${login}/plugins > isocalendar > computing svg render`) const size = 6 let i = 0, j = 0 let svg = ` ${ [1, 2].map(k => ` ${[..."RGB"].map(channel => ``).join("")} `) .join("") } ` //Iterate through weeks for (const week of calendar.weeks) { svg += `` j = 0 //Iterate through days for (const day of week.contributionDays) { const ratio = (day.contributionCount / reference) || 0 svg += ` ` j++ } svg += "" i++ } svg += "" //Results return {streak, max, average, svg, duration} } //Handle errors catch (error) { throw imports.format.error(error) } } /**Compute max and current streaks */ async function statistics({login, graphql, queries, start, end, calendar}) { let average = 0, max = 0, streak = {max: 0, current: 0}, values = [] //Load contribution calendar for (let from = new Date(start); from < end;) { //Set date range let to = new Date(from) to.setUTCHours(+4 * 7 * 24) if (to > end) to = end //Ensure that date ranges are not overlapping by setting it to previous day at 23:59:59.999 const dto = new Date(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 for (const week of calendar.weeks) { for (const day of week.contributionDays) { values.push(day.contributionCount) max = Math.max(max, day.contributionCount) streak.current = day.contributionCount ? streak.current + 1 : 0 streak.max = Math.max(streak.max, streak.current) } } //Compute average average = (values.reduce((a, b) => a + b, 0) / values.length).toFixed(2).replace(/[.]0+$/, "") return {streak, max, average} }