Skip to content

Commit 602d9ff

Browse files
committed
Merge value modeling improvements from targeting-bugfixes while preserving diagnostics
- Added recalculate targets functionality with save all button - Enhanced time-saved chart with dynamic Y-axis and target lines - Fixed type issues in target-calculation-service.ts using parseFloat for string conversions - Simplified status.service.ts repositories API call - Added value-modeling-explanation.md documentation - Maintained all diagnostic functionality and type safety
1 parent 9f21f23 commit 602d9ff

3 files changed

Lines changed: 103 additions & 15 deletions

File tree

backend/src/services/status.service.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export interface StatusType {
1111
};
1212
installations: {
1313
installation: Endpoints["GET /app/installations"]["response"]["data"][0]
14-
repos: Endpoints["GET /installation/repositories"]["response"]["data"]["repositories"];
14+
repos: Endpoints["GET /app/installations"]["response"]["data"];
1515
}[];
1616
surveyCount: number;
1717
auth?: {
@@ -56,12 +56,10 @@ class StatusService {
5656

5757
status.installations = [];
5858
for (const installation of app.github.installations) {
59-
const repos = await installation.octokit.paginate<Endpoints["GET /installation/repositories"]["response"]["data"]["repositories"][0]>(
60-
installation.installation.repositories_url
61-
);
59+
const repos = await installation.octokit.request(installation.installation.repositories_url);
6260
status.installations.push({
6361
installation: installation.installation,
64-
repos: repos
62+
repos: repos.data.repositories
6563
});
6664
}
6765

backend/src/services/target-calculation-service.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,8 @@ RESULT:
702702
const userTimeSavings = distinctUsers.map(userId => {
703703
const userSurveys = this.surveysWeekly.filter(survey => survey.userId === userId);
704704
const totalPercent = userSurveys.reduce((sum, survey) => {
705-
const percentTimeSaved = typeof survey.percentTimeSaved === 'number' ? survey.percentTimeSaved : 0;
705+
// Always parse percentTimeSaved as float
706+
const percentTimeSaved = survey.percentTimeSaved != null ? parseFloat(survey.percentTimeSaved as any) : 0;
706707
return sum + percentTimeSaved;
707708
}, 0);
708709
return totalPercent / userSurveys.length; // Average percent time saved per user
@@ -711,17 +712,17 @@ RESULT:
711712
// Average across all users
712713
const avgPercentTimeSaved = userTimeSavings.reduce((sum, percent) => sum + percent, 0) / userTimeSavings.length;
713714

714-
// Convert settings values to numbers
715-
const hoursPerYear = typeof this.settings.hoursPerYear === 'number' ? this.settings.hoursPerYear : 2000;
716-
const percentCoding = typeof this.settings.percentCoding === 'number' ? this.settings.percentCoding : 50;
715+
// Convert settings values to numbers (parse from string if needed)
716+
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;
717+
const percentCoding = this.settings.percentCoding != null ? parseFloat(this.settings.percentCoding as any) : 50;
717718

718719
// Calculate weekly hours saved based on settings and average percent
719720
const weeklyHours = hoursPerYear / 50; // Assuming 50 working weeks
720721
const weeklyDevHours = weeklyHours * (percentCoding / 100);
721722
const avgWeeklyTimeSaved = weeklyDevHours * (avgPercentTimeSaved / 100);
722723

723724
// Calculate max based on settings
724-
const maxPercentTimeSaved = typeof this.settings.percentTimeSaved === 'number' ? this.settings.percentTimeSaved : 20;
725+
const maxPercentTimeSaved = this.settings.percentTimeSaved != null ? parseFloat(this.settings.percentTimeSaved as any) : 20;
725726
const maxWeeklyTimeSaved = weeklyDevHours * (maxPercentTimeSaved / 100);
726727

727728
const result = {
@@ -785,11 +786,11 @@ RESULT:
785786
const adoptedDevs = this.calculateAdoptedDevs().current;
786787
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current;
787788

788-
// Ensure all values are properly typed as numbers
789-
const hoursPerYear = typeof this.settings.hoursPerYear === 'number' ? this.settings.hoursPerYear : 2000;
789+
// Always parse settings values as numbers (from string if needed)
790+
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;
790791
const weeksInYear = Math.round(hoursPerYear / 40) || 50; // Calculate weeks and ensure it's a number
791792

792-
const devCostPerYear = typeof this.settings.devCostPerYear === 'number' ? this.settings.devCostPerYear : 0;
793+
const devCostPerYear = this.settings.devCostPerYear != null ? parseFloat(this.settings.devCostPerYear as any) : 0;
793794
const hourlyRate = devCostPerYear > 0 ? (devCostPerYear / hoursPerYear) : 50;
794795

795796
const annualSavings = weeklyTimeSavedHrs * weeksInYear * hourlyRate * adoptedDevs;
@@ -824,8 +825,8 @@ RESULT:
824825
const adoptedDevs = this.calculateAdoptedDevs().current;
825826
const weeklyTimeSavedHrs = this.calculateWeeklyTimeSavedHrs().current;
826827

827-
// Convert hours per year to number
828-
const hoursPerYear = typeof this.settings.hoursPerYear === 'number' ? this.settings.hoursPerYear : 2000;
828+
// Always parse hours per year as number
829+
const hoursPerYear = this.settings.hoursPerYear != null ? parseFloat(this.settings.hoursPerYear as any) : 2000;
829830
const hoursPerWeek = hoursPerYear / 50 || 40; // Default to 40 if undefined
830831

831832
// Calculate productivity boost factor (not percentage)
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Value Modeling & Targeting Documentation
2+
3+
This document outlines the rationale and logic behind the calculated metrics and targets used in the "Value Modeling & Targeting" dashboard. Each section corresponds to a category of metrics displayed in the dashboard.
4+
5+
## Org Metrics
6+
7+
### Seats
8+
- **Logic**: Based on the average total active seats (licenses) across top 10 recent days for the organization.
9+
- **Max**: Set to known total developer headcount.
10+
11+
### Adopted Devs
12+
- **Logic**: Average of total active developers using AI tooling (e.g. Copilot) from top 10 recent days for the organization.
13+
- **Max**: Total known developer count.
14+
15+
### Monthly Devs Reporting Time Savings
16+
- **Logic**: Count of distinct users who responded to time-savings surveys in past 30 days.
17+
- **Target**: Double the current, indicating intent to increase reporting.
18+
19+
### % of Seats Reporting Time Savings
20+
- **Logic**: (Monthly reporting users / total seats) * 100.
21+
- **Purpose**: Shows how broadly time savings are captured.
22+
23+
### % of Seats Adopted
24+
- **Logic**: (Adopted Devs / Total Seats) * 100.
25+
- **Use**: Adoption penetration relative to seat assignments.
26+
27+
### % of Max Adopted
28+
- **Logic**: (Adopted Devs / Total Developer Count) * 100.
29+
- **Use**: Indicates potential ceiling for adoption.
30+
31+
## Daily User Metrics
32+
33+
### Daily IDE Suggestions
34+
- **Logic**: Averaged from last 5 valid daily records.
35+
- **Target/Max**: Calibrated based on observed high-performing usage.
36+
37+
### Daily IDE Acceptances
38+
- **Logic**: Suggestions * 30% (default assumed acceptance rate).
39+
- **Target/Max**: Reflects healthy usage from productive orgs.
40+
41+
### Daily IDE Chat Turns
42+
- **Logic**: Average of chat turns per day per user from recent week.
43+
- **Target/Max**: Reflects healthy usage from productive orgs.
44+
45+
### Daily Dot-Com Chats
46+
- **Logic**: Chat Turns * 33% (estimated portion on dot-com).
47+
- **Target**: Not yet set pending more data.
48+
49+
### Weekly PR Summaries
50+
- **Logic**: Total PR summaries / daily active users from last week.
51+
52+
### Weekly Time Saved
53+
- **Logic**: Weekly average from time savings reports per developer.
54+
- **Calculation**:
55+
```
56+
const weeklyHours = hoursPerYear / 50; // Assuming 50 working weeks
57+
const weeklyDevHours = weeklyHours * (percentCoding / 100);
58+
const avgWeeklyTimeSaved = weeklyDevHours * (avgPercentTimeSaved / 100);
59+
```
60+
61+
## Calculated Impacts
62+
63+
### Monthly Time Savings (hrs)
64+
- **Formula**: Adopted Devs * Weekly Time Saved * 4.
65+
- **Max**: 80 hours/month * total seats (full work month).
66+
67+
### Annual Time Savings (Dollars)
68+
- **Formula**: Weekly Time Saved * 50 weeks * $100/hr * Adopted Devs.
69+
- **Note**: $100/hr is assumed average developer cost.
70+
71+
### Productivity / Throughput Boost
72+
- **Formula**: ((40 + Weekly Time Saved) / 40 - 1) * 100.
73+
- **Purpose**: Estimates effective increase in output per dev.
74+
75+
## Source of Calculations
76+
77+
All calculations were derived from one or more of:
78+
- Recent metric exports (5 most recent days)
79+
- Monthly time-savings surveys
80+
- Developer seat and activity data
81+
- Assumed baselines (e.g., 40-hr weeks, $100/hr, 70% acceptance)
82+
83+
Targets are either:
84+
- Reflective of past top 10 org benchmarks
85+
- Strategically aspirational (2x current, known limits)
86+
87+
This model provides a structured framework for tracking usage, estimating impact, and guiding adoption investments.
88+
89+
> Edits can include notes on thresholds, cohort segmentation, or more nuanced modeling (e.g., p50/p90 range breakdowns).

0 commit comments

Comments
 (0)