improvements jan2025 (#9)

* feat(scoring): add tests bonus and fix average calculations

- [x] Add CommitsWithTests metric to track commits with test file changes
- [x] Add TestsBonus to score breakdown (15 points per commit with tests)
- [x] Fix AvgTimeToMerge calculation to use count of PRs with valid data
- [x] Fix AvgReviewTime calculation to use count of reviews with valid data
- [x] Fix AvgPRSize calculation to only include merged PRs
- [x] Add trackActivityDay helper to deduplicate activity tracking code
- [x] Track activity days for PR creation, reviews, and issue comments
- [x] Separate issue close tracking from issue open tracking
- [x] Update early bird window from 5am-9am to 6am-9am
- [x] Add time-based multipliers to velocity timeline scoring
- [x] Update GraphQL query to fetch OPEN, MERGED, CLOSED PRs
- [x] Fix PR filtering logic to handle all PR states correctly
- [x] Improve watch handlers in Vue components to prevent double-loading
- [x] Fix formatDuration to handle zero and negative values
- [x] Update scoring documentation to include Tests component

* refactor: use standard library and consolidate constants

- [x] Replace custom contains function with slices.Contains
- [x] Remove duplicate contains function implementations
- [x] Extract magic numbers to named constants in formatters
- [x] Create constants composable for app-wide values
- [x] Add ESLint configuration with browser globals
- [x] Add lint npm scripts to package.json
- [x] Reorder Vue template attributes for consistency
- [x] Remove unused variable in AchievementProgress
- [x] Add pnpm lock file
This commit is contained in:
2026-01-13 11:39:35 +00:00
committed by GitHub
parent a23915c620
commit 7ba4d438dd
22 changed files with 2490 additions and 186 deletions
+16 -8
View File
@@ -1,13 +1,21 @@
// Number formatting thresholds
const ONE_MILLION = 1_000_000
const ONE_THOUSAND = 1_000
// Time conversion constants
const MINUTES_PER_HOUR = 60
const HOURS_PER_DAY = 24
/**
* Format a number with K/M suffixes for large values
*/
export function formatNumber(n) {
if (n === null || n === undefined) return '0'
if (n >= 1000000) {
return (n / 1000000).toFixed(1) + 'M'
if (n >= ONE_MILLION) {
return (n / ONE_MILLION).toFixed(1) + 'M'
}
if (n >= 1000) {
return (n / 1000).toFixed(1) + 'K'
if (n >= ONE_THOUSAND) {
return (n / ONE_THOUSAND).toFixed(1) + 'K'
}
return String(n)
}
@@ -16,14 +24,14 @@ export function formatNumber(n) {
* Format hours as a human-readable duration
*/
export function formatDuration(hours) {
if (hours === null || hours === undefined) return '-'
if (hours === null || hours === undefined || hours <= 0) return '-'
if (hours < 1) {
return Math.round(hours * 60) + 'm'
return Math.round(hours * MINUTES_PER_HOUR) + 'm'
}
if (hours < 24) {
if (hours < HOURS_PER_DAY) {
return hours.toFixed(1) + 'h'
}
return (hours / 24).toFixed(1) + 'd'
return (hours / HOURS_PER_DAY).toFixed(1) + 'd'
}
/**