This PR mainly refactors the code by extracting a "core" package which is then used by the "backend" and "frontend" apps. Apart from this the PR also contains several smaller changes like fixing dependabot, upgrading dependencies, aligned "package.json" files, added tests, ... addresses step 1 of #32 closes #136 --------- Co-authored-by: Marco Pasqualetti <marco.pasqualetti@live.com>
87 lines
2.3 KiB
JavaScript
87 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 };
|