11import { githubGraphQL } from "../api/api.js" ;
2- import { GitHubContribution } from "../types/types.js" ;
2+ import { GitHubContribution , MonthlyContribution } from "../types/types.js" ;
33
44export const getGitHubContributions = async (
55 username : string ,
@@ -140,23 +140,124 @@ const CONTRIBUTIONS_QUERY = `
140140 }
141141` ;
142142
143+ interface ContributionDay {
144+ contributionCount : number ;
145+ date : string ;
146+ color : string ;
147+ }
148+
143149interface ContributionResponse {
144150 user : {
145151 contributionsCollection : {
146152 contributionCalendar : {
147153 totalContributions : number ;
148154 weeks : Array < {
149- contributionDays : Array < {
150- contributionCount : number ;
151- date : string ;
152- color : string ;
153- } > ;
155+ contributionDays : Array < ContributionDay > ;
154156 } > ;
155157 } ;
156158 } ;
157159 } ;
158160}
159161
162+ interface StreakData {
163+ count : number ;
164+ startDate : string ;
165+ endDate : string ;
166+ }
167+
168+ const calcStreakStats = (
169+ days : ContributionDay [ ]
170+ ) : { longestStreak : StreakData ; activeDays : number } => {
171+ let longestStreak : StreakData = { count : 0 , startDate : "" , endDate : "" } ;
172+
173+ let tempStreak : StreakData = { count : 0 , startDate : "" , endDate : "" } ;
174+
175+ // ensure chronological order
176+ const sortedDays = [ ...days ] . sort (
177+ ( a , b ) => new Date ( a . date ) . getTime ( ) - new Date ( b . date ) . getTime ( )
178+ ) ;
179+ const activeDays = sortedDays . filter (
180+ ( day ) => day . contributionCount > 0
181+ ) . length ;
182+
183+ sortedDays . forEach ( ( day ) => {
184+ if ( day . contributionCount > 0 ) {
185+ if ( tempStreak . count === 0 ) {
186+ tempStreak . startDate = day . date ;
187+ }
188+ tempStreak . count ++ ;
189+ tempStreak . endDate = day . date ;
190+
191+ if ( tempStreak . count > longestStreak . count ) {
192+ longestStreak = { ...tempStreak } ;
193+ }
194+ } else {
195+ tempStreak = { count : 0 , startDate : "" , endDate : "" } ;
196+ }
197+ } ) ;
198+
199+ return { longestStreak, activeDays } ;
200+ } ;
201+
202+ const monthNames = [
203+ "January" ,
204+ "February" ,
205+ "March" ,
206+ "April" ,
207+ "May" ,
208+ "June" ,
209+ "July" ,
210+ "August" ,
211+ "September" ,
212+ "October" ,
213+ "November" ,
214+ "December"
215+ ] ;
216+
217+ const getEffectiveMonth = ( days : ContributionDay [ ] , totalCommit : number ) => {
218+ const monthlyCounts = new Array ( 12 ) . fill ( 0 ) ;
219+ days . forEach ( ( day ) => {
220+ const monthlyIndex = new Date ( day . date ) . getUTCMonth ( ) ;
221+ monthlyCounts [ monthlyIndex ] += day . contributionCount ;
222+ } ) ;
223+
224+ let maxCount = - 1 ;
225+ let maxIndex = 0 ;
226+
227+ monthlyCounts . forEach ( ( count , index ) => {
228+ if ( count > maxCount ) {
229+ maxCount = count ;
230+ maxIndex = index ;
231+ }
232+ } ) ;
233+
234+ return {
235+ index : maxIndex ,
236+ name : monthNames [ maxIndex ] ,
237+ contributionCounts : maxCount ,
238+ percent :
239+ totalCommit > 0 ? Math . round ( ( maxCount / totalCommit ) * 1000 ) / 10 : 0
240+ } ;
241+ } ;
242+
243+ export const getMonthlyContributions = (
244+ days : ContributionDay [ ] ,
245+ totalCommit : number
246+ ) : MonthlyContribution [ ] => {
247+ const monthlyCounts = new Array ( 12 ) . fill ( 0 ) ;
248+ days . forEach ( ( day ) => {
249+ const monthlyIndex = new Date ( day . date ) . getUTCMonth ( ) ;
250+ monthlyCounts [ monthlyIndex ] += day . contributionCount ;
251+ } ) ;
252+
253+ return monthlyCounts . map ( ( count , index ) => ( {
254+ index,
255+ name : monthNames [ index ] ,
256+ contributionCounts : count ,
257+ percent : totalCommit > 0 ? Math . round ( ( count / totalCommit ) * 1000 ) / 10 : 0
258+ } ) ) ;
259+ } ;
260+
160261export const getGitHubYearlyContributions = async (
161262 username : string ,
162263 year : number ,
@@ -175,9 +276,17 @@ export const getGitHubYearlyContributions = async (
175276
176277 const dailyData = calendar . weeks . flatMap ( ( week ) => week . contributionDays ) ;
177278
279+ const streakStats = calcStreakStats ( dailyData ) ;
280+ const effectiveMonth = getEffectiveMonth (
281+ dailyData ,
282+ calendar . totalContributions
283+ ) ;
284+
178285 return {
179286 year,
180287 totalContributions : calendar . totalContributions ,
181- days : dailyData
288+ days : dailyData ,
289+ streakStats,
290+ effectiveMonth
182291 } ;
183- } ;
292+ } ;
0 commit comments