mirror of
https://github.com/lukaszraczylo/git-velocity.git
synced 2026-06-18 03:43:56 +00:00
150 lines
5.5 KiB
JavaScript
150 lines
5.5 KiB
JavaScript
// Achievement category mappings and utilities
|
|
|
|
// Define achievement categories and their tier ordering (highest tier last)
|
|
const achievementCategories = {
|
|
// Commits
|
|
'commit': ['commit-1', 'commit-10', 'commit-50', 'commit-100', 'commit-500', 'commit-1000'],
|
|
// PRs opened
|
|
'pr': ['pr-1', 'pr-10', 'pr-25', 'pr-50', 'pr-100', 'pr-250'],
|
|
// Reviews
|
|
'review': ['review-1', 'review-10', 'review-25', 'review-50', 'review-100', 'review-250'],
|
|
// Review comments
|
|
'comment': ['comment-10', 'comment-50', 'comment-100', 'comment-250', 'comment-500'],
|
|
// Lines added
|
|
'lines-added': ['lines-added-100', 'lines-added-1000', 'lines-added-5000', 'lines-added-10000', 'lines-added-50000'],
|
|
// Lines deleted
|
|
'lines-deleted': ['lines-deleted-100', 'lines-deleted-500', 'lines-deleted-1000', 'lines-deleted-5000', 'lines-deleted-10000'],
|
|
// Review time
|
|
'review-time': ['review-time-24h', 'review-time-4h', 'review-time-1h'],
|
|
// Multi-repo
|
|
'repo': ['repo-2', 'repo-5', 'repo-10'],
|
|
// Unique reviewees
|
|
'reviewees': ['reviewees-3', 'reviewees-10', 'reviewees-25'],
|
|
// Large PRs
|
|
'large-pr': ['large-pr-500', 'large-pr-1000', 'large-pr-5000'],
|
|
// Small PRs
|
|
'small-pr': ['small-pr-5', 'small-pr-10', 'small-pr-25', 'small-pr-50'],
|
|
// Perfect PRs
|
|
'perfect-pr': ['perfect-pr-1', 'perfect-pr-5', 'perfect-pr-10', 'perfect-pr-25'],
|
|
// Active days
|
|
'active': ['active-7', 'active-30', 'active-60', 'active-100'],
|
|
// Streaks
|
|
'streak': ['streak-3', 'streak-7', 'streak-14', 'streak-30'],
|
|
// Work week streaks
|
|
'workweek': ['workweek-3', 'workweek-5', 'workweek-10', 'workweek-20'],
|
|
// Early bird
|
|
'earlybird': ['earlybird-10', 'earlybird-25', 'earlybird-50', 'earlybird-100'],
|
|
// Night owl
|
|
'nightowl': ['nightowl-10', 'nightowl-25', 'nightowl-50', 'nightowl-100'],
|
|
// Midnight coder
|
|
'midnight': ['midnight-5', 'midnight-10', 'midnight-25', 'midnight-50'],
|
|
// Weekend warrior
|
|
'weekend': ['weekend-5', 'weekend-10', 'weekend-25', 'weekend-50'],
|
|
// Out of hours
|
|
'ooh': ['ooh-10', 'ooh-25', 'ooh-50', 'ooh-100'],
|
|
// Documentation added
|
|
'docs': ['docs-100', 'docs-500', 'docs-1000', 'docs-2500', 'docs-5000'],
|
|
// Documentation deleted
|
|
'docs-del': ['docs-del-50', 'docs-del-200', 'docs-del-500', 'docs-del-1000', 'docs-del-2500'],
|
|
// Issues opened
|
|
'issue': ['issue-1', 'issue-5', 'issue-10', 'issue-25', 'issue-50'],
|
|
// Issues closed
|
|
'issue-close': ['issue-close-1', 'issue-close-5', 'issue-close-10', 'issue-close-25', 'issue-close-50'],
|
|
// Issue comments
|
|
'issue-comment': ['issue-comment-5', 'issue-comment-10', 'issue-comment-25', 'issue-comment-50', 'issue-comment-100'],
|
|
// Issue references in commits
|
|
'issue-ref': ['issue-ref-5', 'issue-ref-10', 'issue-ref-25', 'issue-ref-50', 'issue-ref-100'],
|
|
}
|
|
|
|
// Get the category for an achievement ID
|
|
export function getAchievementCategory(achievementId) {
|
|
for (const [category, tiers] of Object.entries(achievementCategories)) {
|
|
if (tiers.includes(achievementId)) {
|
|
return category
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
|
|
// Get the tier index within a category (higher = better)
|
|
export function getAchievementTier(achievementId) {
|
|
const category = getAchievementCategory(achievementId)
|
|
if (!category) return -1
|
|
return achievementCategories[category].indexOf(achievementId)
|
|
}
|
|
|
|
/**
|
|
* Filter achievements to show only the highest tier in each category
|
|
* @param {string[]} achievements - Array of achievement IDs
|
|
* @returns {string[]} - Filtered array with only highest tier per category
|
|
*/
|
|
export function getHighestTierAchievements(achievements) {
|
|
if (!achievements || !achievements.length) return []
|
|
|
|
// Group achievements by category, keeping only the highest tier
|
|
const highestByCategory = {}
|
|
|
|
for (const achievementId of achievements) {
|
|
const category = getAchievementCategory(achievementId)
|
|
if (!category) {
|
|
// Unknown achievement, keep it
|
|
highestByCategory[achievementId] = { id: achievementId, tier: -1 }
|
|
continue
|
|
}
|
|
|
|
const tier = getAchievementTier(achievementId)
|
|
|
|
if (!highestByCategory[category] || tier > highestByCategory[category].tier) {
|
|
highestByCategory[category] = { id: achievementId, tier }
|
|
}
|
|
}
|
|
|
|
// Return just the achievement IDs, sorted by tier (highest first)
|
|
return Object.values(highestByCategory)
|
|
.sort((a, b) => b.tier - a.tier)
|
|
.map(item => item.id)
|
|
}
|
|
|
|
/**
|
|
* Get a priority score for sorting achievements (higher = more impressive)
|
|
* Categories are weighted to show most impressive achievements first
|
|
*/
|
|
const categoryPriority = {
|
|
'commit': 10,
|
|
'pr': 9,
|
|
'review': 8,
|
|
'lines-added': 7,
|
|
'perfect-pr': 6,
|
|
'issue': 5.5,
|
|
'issue-close': 5.4,
|
|
'streak': 5,
|
|
'active': 4,
|
|
'issue-ref': 3.5,
|
|
'issue-comment': 3.2,
|
|
'review-time': 3,
|
|
'docs': 2,
|
|
}
|
|
|
|
export function getAchievementPriority(achievementId) {
|
|
const category = getAchievementCategory(achievementId)
|
|
const basePriority = categoryPriority[category] || 0
|
|
const tier = getAchievementTier(achievementId)
|
|
// Combine category priority with tier (tier adds 0.1 per level)
|
|
return basePriority + (tier * 0.1)
|
|
}
|
|
|
|
/**
|
|
* Get highest tier achievements, sorted by importance
|
|
* @param {string[]} achievements - Array of achievement IDs
|
|
* @param {number} limit - Maximum number to return
|
|
* @returns {string[]} - Filtered and sorted array
|
|
*/
|
|
export function getTopAchievements(achievements, limit = 6) {
|
|
const highest = getHighestTierAchievements(achievements)
|
|
|
|
// Sort by priority (most impressive first)
|
|
highest.sort((a, b) => getAchievementPriority(b) - getAchievementPriority(a))
|
|
|
|
return highest.slice(0, limit)
|
|
}
|