Files
github-stats-extended/apps/backend/src/calculateRank.js
T
Marco Pasqualettiandmartin-mfg 8c065b473f feat: setup monorepo using pnpm (#20)
* tests: fix float problems and PAT problem

* extend CONTRIBUTING.md

* extend build documentation, add GH action, fix build on MacOS

* fix build on Vercel

* update .gitignore and CONTRIBUTING.md

* feat: begin work on monorepo

* chore(actions/basic-build): use pnpm

* fix: vercel-deploy

* docs: updates with new folders

* chore: apply PR review comments

---------

Co-authored-by: martin-mfg <2026226+martin-mfg@users.noreply.github.com>
2026-01-19 14:11:58 +01:00

88 lines
2.3 KiB
JavaScript

/**
* Calculates the exponential cdf.
*
* @param {number} x The value.
* @returns {number} The exponential cdf.
*/
function exponential_cdf(x) {
return 1 - 2 ** -x;
}
/**
* Calculates the log normal cdf.
*
* @param {number} x The value.
* @returns {number} The log normal cdf.
*/
function log_normal_cdf(x) {
// approximation
return x / (1 + x);
}
/**
* Calculates the users rank.
*
* @param {object} params Parameters on which the user's rank depends.
* @param {boolean} params.all_commits Whether `include_all_commits` was used.
* @param {number} params.commits Number of commits.
* @param {number} params.prs The number of pull requests.
* @param {number} params.issues The number of issues.
* @param {number} params.reviews The number of reviews.
* @param {number} params.repos Total number of repos.
* @param {number} params.stars The number of stars.
* @param {number} params.followers The number of followers.
* @returns {{ level: string, percentile: number }} The users rank.
*/
function calculateRank({
all_commits,
commits,
prs,
issues,
reviews,
// eslint-disable-next-line no-unused-vars
repos, // unused
stars,
followers,
}) {
const COMMITS_MEDIAN = all_commits ? 1000 : 250,
COMMITS_WEIGHT = 2;
const PRS_MEDIAN = 50,
PRS_WEIGHT = 3;
const ISSUES_MEDIAN = 25,
ISSUES_WEIGHT = 1;
const REVIEWS_MEDIAN = 2,
REVIEWS_WEIGHT = 1;
const STARS_MEDIAN = 50,
STARS_WEIGHT = 4;
const FOLLOWERS_MEDIAN = 10,
FOLLOWERS_WEIGHT = 1;
const TOTAL_WEIGHT =
COMMITS_WEIGHT +
PRS_WEIGHT +
ISSUES_WEIGHT +
REVIEWS_WEIGHT +
STARS_WEIGHT +
FOLLOWERS_WEIGHT;
const THRESHOLDS = [1, 12.5, 25, 37.5, 50, 62.5, 75, 87.5, 100];
const LEVELS = ["S", "A+", "A", "A-", "B+", "B", "B-", "C+", "C"];
const rank =
1 -
(COMMITS_WEIGHT * exponential_cdf(commits / COMMITS_MEDIAN) +
PRS_WEIGHT * exponential_cdf(prs / PRS_MEDIAN) +
ISSUES_WEIGHT * exponential_cdf(issues / ISSUES_MEDIAN) +
REVIEWS_WEIGHT * exponential_cdf(reviews / REVIEWS_MEDIAN) +
STARS_WEIGHT * log_normal_cdf(stars / STARS_MEDIAN) +
FOLLOWERS_WEIGHT * log_normal_cdf(followers / FOLLOWERS_MEDIAN)) /
TOTAL_WEIGHT;
const level = LEVELS[THRESHOLDS.findIndex((t) => rank * 100 <= t)];
return { level, percentile: rank * 100 };
}
export { calculateRank };
export default calculateRank;