@@ -60,7 +60,6 @@ func isBotAuthor(author string) bool {
6060// Uses library functions from pkg/github and pkg/cost for fetching, sampling,
6161// and extrapolation - all functionality is available to external clients.
6262func analyzeRepository (ctx context.Context , owner , repo string , sampleSize , days int , cfg cost.Config , token string , dataSource string ) error {
63-
6463 // Calculate since date
6564 since := time .Now ().AddDate (0 , 0 , - days )
6665
@@ -283,28 +282,13 @@ func analyzeOrganization(ctx context.Context, org string, sampleSize, days int,
283282 // Count unique authors across all PRs (not just samples)
284283 totalAuthors := github .CountUniqueAuthors (prs )
285284
286- // Count open PRs across all unique repos in the organization
287- uniqueRepos := make (map [string ]bool )
288- for _ , pr := range prs {
289- repoKey := pr .Owner + "/" + pr .Repo
290- uniqueRepos [repoKey ] = true
291- }
292-
293- totalOpenPRs := 0
294- for repoKey := range uniqueRepos {
295- parts := strings .SplitN (repoKey , "/" , 2 )
296- if len (parts ) != 2 {
297- continue
298- }
299- owner , repo := parts [0 ], parts [1 ]
300- openCount , err := github .CountOpenPRsInRepo (ctx , owner , repo , token )
301- if err != nil {
302- slog .Warn ("Failed to count open PRs for repo" , "repo" , repoKey , "error" , err )
303- continue
304- }
305- totalOpenPRs += openCount
285+ // Count open PRs across the entire organization with a single query
286+ totalOpenPRs , err := github .CountOpenPRsInOrg (ctx , org , token )
287+ if err != nil {
288+ slog .Warn ("Failed to count open PRs in organization, using 0" , "error" , err )
289+ totalOpenPRs = 0
306290 }
307- slog .Info ("Counted total open PRs across organization" , "open_prs " , totalOpenPRs , "repos " , len ( uniqueRepos ) )
291+ slog .Info ("Counted total open PRs across organization" , "org " , org , "open_prs " , totalOpenPRs )
308292
309293 // Extrapolate costs from samples using library function
310294 extrapolated := cost .ExtrapolateFromSamples (breakdowns , len (prs ), totalAuthors , totalOpenPRs , actualDays , cfg )
@@ -433,14 +417,18 @@ func printExtrapolatedResults(title string, days int, ext *cost.ExtrapolatedBrea
433417 fmt .Printf (" Development Costs (%d PRs, %s total LOC)\n " , ext .HumanPRs , totalLOCStr )
434418 fmt .Println (" ────────────────────────────────────────" )
435419
420+ // Calculate average events and sessions
421+ avgAuthorEvents := float64 (ext .AuthorEvents ) / float64 (ext .TotalPRs )
422+ avgAuthorSessions := float64 (ext .AuthorSessions ) / float64 (ext .TotalPRs )
423+
436424 fmt .Printf (" New Development $%10s %s (%s LOC)\n " ,
437425 formatWithCommas (avgAuthorNewCodeCost ), formatTimeUnit (avgAuthorNewCodeHours ), newLOCStr )
438426 fmt .Printf (" Adaptation $%10s %s (%s LOC)\n " ,
439427 formatWithCommas (avgAuthorAdaptationCost ), formatTimeUnit (avgAuthorAdaptationHours ), modifiedLOCStr )
440- fmt .Printf (" GitHub Activity $%10s %s\n " ,
441- formatWithCommas (avgAuthorGitHubCost ), formatTimeUnit (avgAuthorGitHubHours ))
442- fmt .Printf (" Context Switching $%10s %s\n " ,
443- formatWithCommas (avgAuthorGitHubContextCost ), formatTimeUnit (avgAuthorGitHubContextHours ))
428+ fmt .Printf (" GitHub Activity $%10s %s (%.1f events) \n " ,
429+ formatWithCommas (avgAuthorGitHubCost ), formatTimeUnit (avgAuthorGitHubHours ), avgAuthorEvents )
430+ fmt .Printf (" Context Switching $%10s %s (%.1f sessions) \n " ,
431+ formatWithCommas (avgAuthorGitHubContextCost ), formatTimeUnit (avgAuthorGitHubContextHours ), avgAuthorSessions )
444432
445433 // Show bot PR LOC even though cost is $0
446434 if ext .BotPRs > 0 {
@@ -457,18 +445,23 @@ func printExtrapolatedResults(title string, days int, ext *cost.ExtrapolatedBrea
457445
458446 // Participants section (if any participants)
459447 if ext .ParticipantTotalCost > 0 {
448+ avgParticipantEvents := float64 (ext .ParticipantEvents ) / float64 (ext .TotalPRs )
449+ avgParticipantSessions := float64 (ext .ParticipantSessions ) / float64 (ext .TotalPRs )
450+
451+ avgParticipantReviews := float64 (ext .ParticipantReviews ) / float64 (ext .TotalPRs )
452+
460453 fmt .Println (" Participant Costs" )
461454 fmt .Println (" ─────────────────" )
462455 if avgParticipantReviewCost > 0 {
463- fmt .Printf (" Review Activity $%10s %s\n " ,
464- formatWithCommas (avgParticipantReviewCost ), formatTimeUnit (avgParticipantReviewHours ))
456+ fmt .Printf (" Review Activity $%10s %s (%.1f reviews) \n " ,
457+ formatWithCommas (avgParticipantReviewCost ), formatTimeUnit (avgParticipantReviewHours ), avgParticipantReviews )
465458 }
466459 if avgParticipantGitHubCost > 0 {
467- fmt .Printf (" GitHub Activity $%10s %s\n " ,
468- formatWithCommas (avgParticipantGitHubCost ), formatTimeUnit (avgParticipantGitHubHours ))
460+ fmt .Printf (" GitHub Activity $%10s %s (%.1f events) \n " ,
461+ formatWithCommas (avgParticipantGitHubCost ), formatTimeUnit (avgParticipantGitHubHours ), avgParticipantEvents )
469462 }
470- fmt .Printf (" Context Switching $%10s %s\n " ,
471- formatWithCommas (avgParticipantContextCost ), formatTimeUnit (avgParticipantContextHours ))
463+ fmt .Printf (" Context Switching $%10s %s (%.1f sessions) \n " ,
464+ formatWithCommas (avgParticipantContextCost ), formatTimeUnit (avgParticipantContextHours ), avgParticipantSessions )
472465 fmt .Println (" ──────────" )
473466 participantPct := (avgParticipantTotalCost / avgTotalCost ) * 100
474467 fmt .Printf (" Subtotal $%10s %s (%.1f%%)\n " ,
@@ -533,8 +526,9 @@ func printExtrapolatedResults(title string, days int, ext *cost.ExtrapolatedBrea
533526 formatWithCommas (avgFutureMergeCost ), formatTimeUnit (avgFutureMergeHours ), ext .FutureMergePRCount )
534527 }
535528 if ext .FutureContextCost > 0.01 {
536- fmt .Printf (" Context Switching $%10s %s\n " ,
537- formatWithCommas (avgFutureContextCost ), formatTimeUnit (avgFutureContextHours ))
529+ avgFutureContextSessions := float64 (ext .FutureContextSessions ) / float64 (ext .TotalPRs )
530+ fmt .Printf (" Context Switching $%10s %s (%.1f sessions)\n " ,
531+ formatWithCommas (avgFutureContextCost ), formatTimeUnit (avgFutureContextHours ), avgFutureContextSessions )
538532 }
539533 avgFutureCost := avgCodeChurnCost + avgFutureReviewCost + avgFutureMergeCost + avgFutureContextCost
540534 avgFutureHours := avgCodeChurnHours + avgFutureReviewHours + avgFutureMergeHours + avgFutureContextHours
@@ -589,10 +583,10 @@ func printExtrapolatedResults(title string, days int, ext *cost.ExtrapolatedBrea
589583 formatWithCommas (ext .AuthorNewCodeCost ), formatTimeUnit (ext .AuthorNewCodeHours ), totalNewLOCStr )
590584 fmt .Printf (" Adaptation $%10s %s (%s LOC)\n " ,
591585 formatWithCommas (ext .AuthorAdaptationCost ), formatTimeUnit (ext .AuthorAdaptationHours ), totalModifiedLOCStr )
592- fmt .Printf (" GitHub Activity $%10s %s\n " ,
593- formatWithCommas (ext .AuthorGitHubCost ), formatTimeUnit (ext .AuthorGitHubHours ))
594- fmt .Printf (" Context Switching $%10s %s\n " ,
595- formatWithCommas (ext .AuthorGitHubContextCost ), formatTimeUnit (ext .AuthorGitHubContextHours ))
586+ fmt .Printf (" GitHub Activity $%10s %s (%d events) \n " ,
587+ formatWithCommas (ext .AuthorGitHubCost ), formatTimeUnit (ext .AuthorGitHubHours ), ext . AuthorEvents )
588+ fmt .Printf (" Context Switching $%10s %s (%d sessions) \n " ,
589+ formatWithCommas (ext .AuthorGitHubContextCost ), formatTimeUnit (ext .AuthorGitHubContextHours ), ext . AuthorSessions )
596590
597591 // Show bot PR LOC even though cost is $0
598592 if ext .BotPRs > 0 {
@@ -612,15 +606,15 @@ func printExtrapolatedResults(title string, days int, ext *cost.ExtrapolatedBrea
612606 fmt .Println (" Participant Costs" )
613607 fmt .Println (" ─────────────────" )
614608 if ext .ParticipantReviewCost > 0 {
615- fmt .Printf (" Review Activity $%10s %s\n " ,
616- formatWithCommas (ext .ParticipantReviewCost ), formatTimeUnit (ext .ParticipantReviewHours ))
609+ fmt .Printf (" Review Activity $%10s %s (%d reviews) \n " ,
610+ formatWithCommas (ext .ParticipantReviewCost ), formatTimeUnit (ext .ParticipantReviewHours ), ext . ParticipantReviews )
617611 }
618612 if ext .ParticipantGitHubCost > 0 {
619- fmt .Printf (" GitHub Activity $%10s %s\n " ,
620- formatWithCommas (ext .ParticipantGitHubCost ), formatTimeUnit (ext .ParticipantGitHubHours ))
613+ fmt .Printf (" GitHub Activity $%10s %s (%d events) \n " ,
614+ formatWithCommas (ext .ParticipantGitHubCost ), formatTimeUnit (ext .ParticipantGitHubHours ), ext . ParticipantEvents )
621615 }
622- fmt .Printf (" Context Switching $%10s %s\n " ,
623- formatWithCommas (ext .ParticipantContextCost ), formatTimeUnit (ext .ParticipantContextHours ))
616+ fmt .Printf (" Context Switching $%10s %s (%d sessions) \n " ,
617+ formatWithCommas (ext .ParticipantContextCost ), formatTimeUnit (ext .ParticipantContextHours ), ext . ParticipantSessions )
624618 fmt .Println (" ──────────" )
625619 pct = (ext .ParticipantTotalCost / ext .TotalCost ) * 100
626620 fmt .Printf (" Subtotal $%10s %s (%.1f%%)\n " ,
@@ -681,8 +675,8 @@ func printExtrapolatedResults(title string, days int, ext *cost.ExtrapolatedBrea
681675 formatWithCommas (ext .FutureMergeCost ), formatTimeUnit (ext .FutureMergeHours ), ext .FutureMergePRCount )
682676 }
683677 if ext .FutureContextCost > 0.01 {
684- fmt .Printf (" Context Switching $%10s %s\n " ,
685- formatWithCommas (ext .FutureContextCost ), formatTimeUnit (ext .FutureContextHours ))
678+ fmt .Printf (" Context Switching $%10s %s (%d sessions) \n " ,
679+ formatWithCommas (ext .FutureContextCost ), formatTimeUnit (ext .FutureContextHours ), ext . FutureContextSessions )
686680 }
687681 extFutureCost := ext .CodeChurnCost + ext .FutureReviewCost + ext .FutureMergeCost + ext .FutureContextCost
688682 extFutureHours := ext .CodeChurnHours + ext .FutureReviewHours + ext .FutureMergeHours + ext .FutureContextHours
0 commit comments