forked from mirrored/github-readme-stats
Compare commits
1
Commits
rank
..
fix_e2e_rank
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14373a0c4d |
+29
-25
@@ -1,10 +1,5 @@
|
|||||||
function exponential_cdf(x) {
|
function expsf(x, lambda = 1) {
|
||||||
return 1 - 2 ** -x;
|
return 2 ** (-lambda * x);
|
||||||
}
|
|
||||||
|
|
||||||
function log_normal_cdf(x) {
|
|
||||||
// approximation
|
|
||||||
return x / (1 + x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +13,7 @@ function log_normal_cdf(x) {
|
|||||||
* @param {number} params.repos Total number of repos.
|
* @param {number} params.repos Total number of repos.
|
||||||
* @param {number} params.stars The number of stars.
|
* @param {number} params.stars The number of stars.
|
||||||
* @param {number} params.followers The number of followers.
|
* @param {number} params.followers The number of followers.
|
||||||
* @returns {{level: string, percentile: number}}} The users rank.
|
* @returns {{level: string, score: number}}} The users rank.
|
||||||
*/
|
*/
|
||||||
function calculateRank({
|
function calculateRank({
|
||||||
all_commits,
|
all_commits,
|
||||||
@@ -29,15 +24,15 @@ function calculateRank({
|
|||||||
stars,
|
stars,
|
||||||
followers,
|
followers,
|
||||||
}) {
|
}) {
|
||||||
const COMMITS_MEDIAN = all_commits ? 1000 : 250,
|
const COMMITS_MEAN = all_commits ? 1000 : 250,
|
||||||
COMMITS_WEIGHT = 2;
|
COMMITS_WEIGHT = 2;
|
||||||
const PRS_MEDIAN = 50,
|
const PRS_MEAN = 50,
|
||||||
PRS_WEIGHT = 3;
|
PRS_WEIGHT = 3;
|
||||||
const ISSUES_MEDIAN = 25,
|
const ISSUES_MEAN = 25,
|
||||||
ISSUES_WEIGHT = 1;
|
ISSUES_WEIGHT = 1;
|
||||||
const STARS_MEDIAN = 50,
|
const STARS_MEAN = 250,
|
||||||
STARS_WEIGHT = 4;
|
STARS_WEIGHT = 4;
|
||||||
const FOLLOWERS_MEDIAN = 10,
|
const FOLLOWERS_MEAN = 25,
|
||||||
FOLLOWERS_WEIGHT = 1;
|
FOLLOWERS_WEIGHT = 1;
|
||||||
|
|
||||||
const TOTAL_WEIGHT =
|
const TOTAL_WEIGHT =
|
||||||
@@ -47,21 +42,30 @@ function calculateRank({
|
|||||||
STARS_WEIGHT +
|
STARS_WEIGHT +
|
||||||
FOLLOWERS_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 =
|
const rank =
|
||||||
1 -
|
(COMMITS_WEIGHT * expsf(commits, 1 / COMMITS_MEAN) +
|
||||||
(COMMITS_WEIGHT * exponential_cdf(commits / COMMITS_MEDIAN) +
|
PRS_WEIGHT * expsf(prs, 1 / PRS_MEAN) +
|
||||||
PRS_WEIGHT * exponential_cdf(prs / PRS_MEDIAN) +
|
ISSUES_WEIGHT * expsf(issues, 1 / ISSUES_MEAN) +
|
||||||
ISSUES_WEIGHT * exponential_cdf(issues / ISSUES_MEDIAN) +
|
STARS_WEIGHT * expsf(stars, 1 / STARS_MEAN) +
|
||||||
STARS_WEIGHT * log_normal_cdf(stars / STARS_MEDIAN) +
|
FOLLOWERS_WEIGHT * expsf(followers, 1 / FOLLOWERS_MEAN)) /
|
||||||
FOLLOWERS_WEIGHT * log_normal_cdf(followers / FOLLOWERS_MEDIAN)) /
|
TOTAL_WEIGHT;
|
||||||
TOTAL_WEIGHT;
|
|
||||||
|
|
||||||
const level = LEVELS[THRESHOLDS.findIndex((t) => rank * 100 <= t)];
|
const RANK_S_PLUS = 0.025;
|
||||||
|
const RANK_S = 0.1;
|
||||||
|
const RANK_A_PLUS = 0.25;
|
||||||
|
const RANK_A = 0.5;
|
||||||
|
const RANK_B_PLUS = 0.75;
|
||||||
|
|
||||||
return { level: level, percentile: rank * 100 };
|
const level = (() => {
|
||||||
|
if (rank <= RANK_S_PLUS) return "S+";
|
||||||
|
if (rank <= RANK_S) return "S";
|
||||||
|
if (rank <= RANK_A_PLUS) return "A+";
|
||||||
|
if (rank <= RANK_A) return "A";
|
||||||
|
if (rank <= RANK_B_PLUS) return "B+";
|
||||||
|
return "B";
|
||||||
|
})();
|
||||||
|
|
||||||
|
return { level, score: rank * 100 };
|
||||||
}
|
}
|
||||||
|
|
||||||
export { calculateRank };
|
export { calculateRank };
|
||||||
|
|||||||
@@ -209,8 +209,9 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
|
|||||||
hide_rank ? 0 : 150,
|
hide_rank ? 0 : 150,
|
||||||
);
|
);
|
||||||
|
|
||||||
// the lower the user's percentile the better
|
// the better user's score the the rank will be closer to zero so
|
||||||
const progress = 100 - rank.percentile;
|
// subtracting 100 to get the progress in 100%
|
||||||
|
const progress = 100 - rank.score;
|
||||||
const cssStyles = getStyles({
|
const cssStyles = getStyles({
|
||||||
titleColor,
|
titleColor,
|
||||||
ringColor,
|
ringColor,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ const MIN_CARD_WIDTH = 280;
|
|||||||
const DEFAULT_LANGS_COUNT = 5;
|
const DEFAULT_LANGS_COUNT = 5;
|
||||||
const DEFAULT_LANG_COLOR = "#858585";
|
const DEFAULT_LANG_COLOR = "#858585";
|
||||||
const CARD_PADDING = 25;
|
const CARD_PADDING = 25;
|
||||||
const COMPACT_LAYOUT_BASE_HEIGHT = 90;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("../fetchers/types").Lang} Lang
|
* @typedef {import("../fetchers/types").Lang} Lang
|
||||||
@@ -102,7 +101,7 @@ const getCircleLength = (radius) => {
|
|||||||
* @returns {number} Card height.
|
* @returns {number} Card height.
|
||||||
*/
|
*/
|
||||||
const calculateCompactLayoutHeight = (totalLangs) => {
|
const calculateCompactLayoutHeight = (totalLangs) => {
|
||||||
return COMPACT_LAYOUT_BASE_HEIGHT + Math.round(totalLangs / 2) * 25;
|
return 90 + Math.round(totalLangs / 2) * 25;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -655,19 +654,6 @@ const renderDonutLayout = (langs, width, totalLanguageSize) => {
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the no coding activity SVG node.
|
|
||||||
*
|
|
||||||
* @param {{color: string, text: string, layout: import("./types").TopLangOptions["layout"]}} The function prop
|
|
||||||
*/
|
|
||||||
const noLanguagesDataNode = ({ color, text, layout }) => {
|
|
||||||
return `
|
|
||||||
<text x="${
|
|
||||||
layout === "pie" || layout === "donut-vertical" ? CARD_PADDING : 0
|
|
||||||
}" y="11" class="stat bold" fill="${color}">${text}</text>
|
|
||||||
`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders card that display user's most frequently used programming languages.
|
* Renders card that display user's most frequently used programming languages.
|
||||||
*
|
*
|
||||||
@@ -713,24 +699,8 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
: card_width;
|
: card_width;
|
||||||
let height = calculateNormalLayoutHeight(langs.length);
|
let height = calculateNormalLayoutHeight(langs.length);
|
||||||
|
|
||||||
// returns theme based colors with proper overrides and defaults
|
|
||||||
const colors = getCardColors({
|
|
||||||
title_color,
|
|
||||||
text_color,
|
|
||||||
bg_color,
|
|
||||||
border_color,
|
|
||||||
theme,
|
|
||||||
});
|
|
||||||
|
|
||||||
let finalLayout = "";
|
let finalLayout = "";
|
||||||
if (langs.length === 0) {
|
if (layout === "pie") {
|
||||||
height = COMPACT_LAYOUT_BASE_HEIGHT;
|
|
||||||
finalLayout = noLanguagesDataNode({
|
|
||||||
color: colors.textColor,
|
|
||||||
text: i18n.t("langcard.nodata"),
|
|
||||||
layout,
|
|
||||||
});
|
|
||||||
} else if (layout === "pie") {
|
|
||||||
height = calculatePieLayoutHeight(langs.length);
|
height = calculatePieLayoutHeight(langs.length);
|
||||||
finalLayout = renderPieLayout(langs, totalLanguageSize);
|
finalLayout = renderPieLayout(langs, totalLanguageSize);
|
||||||
} else if (layout === "donut-vertical") {
|
} else if (layout === "donut-vertical") {
|
||||||
@@ -754,6 +724,15 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
|
finalLayout = renderNormalLayout(langs, width, totalLanguageSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns theme based colors with proper overrides and defaults
|
||||||
|
const colors = getCardColors({
|
||||||
|
title_color,
|
||||||
|
text_color,
|
||||||
|
bg_color,
|
||||||
|
border_color,
|
||||||
|
theme,
|
||||||
|
});
|
||||||
|
|
||||||
const card = new Card({
|
const card = new Card({
|
||||||
customTitle: custom_title,
|
customTitle: custom_title,
|
||||||
defaultTitle: i18n.t("langcard.title"),
|
defaultTitle: i18n.t("langcard.title"),
|
||||||
@@ -785,14 +764,6 @@ const renderTopLanguages = (topLangs, options = {}) => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.stat {
|
|
||||||
font: 600 14px 'Segoe UI', Ubuntu, "Helvetica Neue", Sans-Serif; fill: ${colors.textColor};
|
|
||||||
}
|
|
||||||
@supports(-moz-appearance: auto) {
|
|
||||||
/* Selector detects Firefox */
|
|
||||||
.stat { font-size:12px; }
|
|
||||||
}
|
|
||||||
.bold { font-weight: 700 }
|
|
||||||
.lang-name {
|
.lang-name {
|
||||||
font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
|
font: 400 11px "Segoe UI", Ubuntu, Sans-Serif;
|
||||||
fill: ${colors.textColor};
|
fill: ${colors.textColor};
|
||||||
|
|||||||
@@ -106,7 +106,6 @@
|
|||||||
"Cypher": "#34c0eb",
|
"Cypher": "#34c0eb",
|
||||||
"Cython": "#fedf5b",
|
"Cython": "#fedf5b",
|
||||||
"D": "#ba595e",
|
"D": "#ba595e",
|
||||||
"D2": "#526ee8",
|
|
||||||
"DM": "#447265",
|
"DM": "#447265",
|
||||||
"Dafny": "#FFEC25",
|
"Dafny": "#FFEC25",
|
||||||
"Darcs Patch": "#8eff23",
|
"Darcs Patch": "#8eff23",
|
||||||
@@ -186,7 +185,6 @@
|
|||||||
"Go": "#00ADD8",
|
"Go": "#00ADD8",
|
||||||
"Go Checksums": "#00ADD8",
|
"Go Checksums": "#00ADD8",
|
||||||
"Go Module": "#00ADD8",
|
"Go Module": "#00ADD8",
|
||||||
"Go Workspace": "#00ADD8",
|
|
||||||
"Godot Resource": "#355570",
|
"Godot Resource": "#355570",
|
||||||
"Golo": "#88562A",
|
"Golo": "#88562A",
|
||||||
"Gosu": "#82937f",
|
"Gosu": "#82937f",
|
||||||
@@ -286,7 +284,6 @@
|
|||||||
"Lua": "#000080",
|
"Lua": "#000080",
|
||||||
"MATLAB": "#e16737",
|
"MATLAB": "#e16737",
|
||||||
"MAXScript": "#00a6a6",
|
"MAXScript": "#00a6a6",
|
||||||
"MDX": "#fcb32c",
|
|
||||||
"MLIR": "#5EC8DB",
|
"MLIR": "#5EC8DB",
|
||||||
"MQL4": "#62A8D6",
|
"MQL4": "#62A8D6",
|
||||||
"MQL5": "#4A76B8",
|
"MQL5": "#4A76B8",
|
||||||
@@ -333,12 +330,11 @@
|
|||||||
"Nu": "#c9df40",
|
"Nu": "#c9df40",
|
||||||
"NumPy": "#9C8AF9",
|
"NumPy": "#9C8AF9",
|
||||||
"Nunjucks": "#3d8137",
|
"Nunjucks": "#3d8137",
|
||||||
"Nushell": "#4E9906",
|
|
||||||
"OASv2-json": "#85ea2d",
|
"OASv2-json": "#85ea2d",
|
||||||
"OASv2-yaml": "#85ea2d",
|
"OASv2-yaml": "#85ea2d",
|
||||||
"OASv3-json": "#85ea2d",
|
"OASv3-json": "#85ea2d",
|
||||||
"OASv3-yaml": "#85ea2d",
|
"OASv3-yaml": "#85ea2d",
|
||||||
"OCaml": "#ef7a08",
|
"OCaml": "#3be133",
|
||||||
"ObjectScript": "#424893",
|
"ObjectScript": "#424893",
|
||||||
"Objective-C": "#438eff",
|
"Objective-C": "#438eff",
|
||||||
"Objective-C++": "#6866fb",
|
"Objective-C++": "#6866fb",
|
||||||
@@ -364,7 +360,6 @@
|
|||||||
"PLSQL": "#dad8d8",
|
"PLSQL": "#dad8d8",
|
||||||
"PLpgSQL": "#336790",
|
"PLpgSQL": "#336790",
|
||||||
"POV-Ray SDL": "#6bac65",
|
"POV-Ray SDL": "#6bac65",
|
||||||
"Pact": "#F7A8B8",
|
|
||||||
"Pan": "#cc0000",
|
"Pan": "#cc0000",
|
||||||
"Papyrus": "#6600cc",
|
"Papyrus": "#6600cc",
|
||||||
"Parrot": "#f3ca0a",
|
"Parrot": "#f3ca0a",
|
||||||
@@ -403,7 +398,6 @@
|
|||||||
"Quake": "#882233",
|
"Quake": "#882233",
|
||||||
"R": "#198CE7",
|
"R": "#198CE7",
|
||||||
"RAML": "#77d9fb",
|
"RAML": "#77d9fb",
|
||||||
"RBS": "#701516",
|
|
||||||
"RDoc": "#701516",
|
"RDoc": "#701516",
|
||||||
"REXX": "#d90e09",
|
"REXX": "#d90e09",
|
||||||
"RMarkdown": "#198ce7",
|
"RMarkdown": "#198ce7",
|
||||||
@@ -478,7 +472,6 @@
|
|||||||
"Swift": "#F05138",
|
"Swift": "#F05138",
|
||||||
"SystemVerilog": "#DAE1C2",
|
"SystemVerilog": "#DAE1C2",
|
||||||
"TI Program": "#A0AA87",
|
"TI Program": "#A0AA87",
|
||||||
"TL-Verilog": "#C40023",
|
|
||||||
"TLA": "#4b0079",
|
"TLA": "#4b0079",
|
||||||
"TOML": "#9c4221",
|
"TOML": "#9c4221",
|
||||||
"TSQL": "#e38c00",
|
"TSQL": "#e38c00",
|
||||||
@@ -519,7 +512,6 @@
|
|||||||
"Vyper": "#2980b9",
|
"Vyper": "#2980b9",
|
||||||
"Web Ontology Language": "#5b70bd",
|
"Web Ontology Language": "#5b70bd",
|
||||||
"WebAssembly": "#04133b",
|
"WebAssembly": "#04133b",
|
||||||
"WebAssembly Interface Type": "#6250e7",
|
|
||||||
"Whiley": "#d5c397",
|
"Whiley": "#d5c397",
|
||||||
"Wikitext": "#fc5757",
|
"Wikitext": "#fc5757",
|
||||||
"Windows Registry Entries": "#52d5ff",
|
"Windows Registry Entries": "#52d5ff",
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ const fetchStats = async (
|
|||||||
totalIssues: 0,
|
totalIssues: 0,
|
||||||
totalStars: 0,
|
totalStars: 0,
|
||||||
contributedTo: 0,
|
contributedTo: 0,
|
||||||
rank: { level: "C", percentile: 100 },
|
rank: { level: "B", score: 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = await statsFetcher(username);
|
let res = await statsFetcher(username);
|
||||||
|
|||||||
Vendored
+1
-1
@@ -22,7 +22,7 @@ export type StatsData = {
|
|||||||
totalIssues: number;
|
totalIssues: number;
|
||||||
totalStars: number;
|
totalStars: number;
|
||||||
contributedTo: number;
|
contributedTo: number;
|
||||||
rank: { level: string; percentile: number };
|
rank: { level: string; score: number };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Lang = {
|
export type Lang = {
|
||||||
|
|||||||
+1
-31
@@ -283,7 +283,7 @@ const langCardLocales = {
|
|||||||
np: "अधिक प्रयोग गरिएको भाषाहरू",
|
np: "अधिक प्रयोग गरिएको भाषाहरू",
|
||||||
el: "Οι περισσότερο χρησιμοποιούμενες γλώσσες",
|
el: "Οι περισσότερο χρησιμοποιούμενες γλώσσες",
|
||||||
ru: "Наиболее часто используемые языки",
|
ru: "Наиболее часто используемые языки",
|
||||||
"uk-ua": "Найчастіше використовувані мови",
|
"uk-ua": "Найбільш часто використовувані мови",
|
||||||
id: "Bahasa Yang Paling Banyak Digunakan",
|
id: "Bahasa Yang Paling Banyak Digunakan",
|
||||||
ml: "കൂടുതൽ ഉപയോഗിച്ച ഭാഷകൾ",
|
ml: "കൂടുതൽ ഉപയോഗിച്ച ഭാഷകൾ",
|
||||||
my: "Bahasa Paling Digunakan",
|
my: "Bahasa Paling Digunakan",
|
||||||
@@ -293,36 +293,6 @@ const langCardLocales = {
|
|||||||
vi: "Ngôn Ngữ Thường Sử Dụng",
|
vi: "Ngôn Ngữ Thường Sử Dụng",
|
||||||
se: "Mest använda språken",
|
se: "Mest använda språken",
|
||||||
},
|
},
|
||||||
"langcard.nodata": {
|
|
||||||
ar: "لا توجد بيانات لغات.",
|
|
||||||
cn: "沒有語言數據。",
|
|
||||||
"zh-tw": "沒有語言數據。",
|
|
||||||
cs: "Žádné jazykové údaje.",
|
|
||||||
de: "Keine Sprachdaten.",
|
|
||||||
bn: "কোন ভাষার ডেটা নেই।",
|
|
||||||
en: "No languages data.",
|
|
||||||
es: "Sin datos de idiomas.",
|
|
||||||
fr: "Aucune donnée sur les langues.",
|
|
||||||
hu: "Nincsenek nyelvi adatok.",
|
|
||||||
it: "Nessun dato sulle lingue.",
|
|
||||||
ja: "言語データがありません。",
|
|
||||||
kr: "언어 데이터가 없습니다.",
|
|
||||||
nl: "Ingen sprogdata.",
|
|
||||||
"pt-pt": "Sem dados de idiomas.",
|
|
||||||
"pt-br": "Sem dados de idiomas.",
|
|
||||||
np: "कुनै भाषा डाटा छैन।",
|
|
||||||
el: "Δεν υπάρχουν δεδομένα γλωσσών.",
|
|
||||||
ru: "Нет данных о языках.",
|
|
||||||
"uk-ua": "Немає даних про мови.",
|
|
||||||
id: "Tidak ada data bahasa.",
|
|
||||||
ml: "ഭാഷാ ഡാറ്റയില്ല.",
|
|
||||||
my: "Tiada data bahasa.",
|
|
||||||
sk: "Žiadne údaje o jazykoch.",
|
|
||||||
tr: "Dil verisi yok.",
|
|
||||||
pl: "Brak danych dotyczących języków.",
|
|
||||||
vi: "Không có dữ liệu ngôn ngữ.",
|
|
||||||
se: "Inga språkdata.",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const wakatimeCardLocales = {
|
const wakatimeCardLocales = {
|
||||||
|
|||||||
+25
-39
@@ -2,7 +2,7 @@ import "@testing-library/jest-dom";
|
|||||||
import { calculateRank } from "../src/calculateRank.js";
|
import { calculateRank } from "../src/calculateRank.js";
|
||||||
|
|
||||||
describe("Test calculateRank", () => {
|
describe("Test calculateRank", () => {
|
||||||
it("new user gets C rank", () => {
|
it("new user gets B rank", () => {
|
||||||
expect(
|
expect(
|
||||||
calculateRank({
|
calculateRank({
|
||||||
all_commits: false,
|
all_commits: false,
|
||||||
@@ -13,24 +13,10 @@ describe("Test calculateRank", () => {
|
|||||||
stars: 0,
|
stars: 0,
|
||||||
followers: 0,
|
followers: 0,
|
||||||
}),
|
}),
|
||||||
).toStrictEqual({ level: "C", percentile: 100 });
|
).toStrictEqual({ level: "B", score: 100 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("beginner user gets B- rank", () => {
|
it("average user gets A rank", () => {
|
||||||
expect(
|
|
||||||
calculateRank({
|
|
||||||
all_commits: false,
|
|
||||||
commits: 125,
|
|
||||||
prs: 25,
|
|
||||||
issues: 10,
|
|
||||||
repos: 0,
|
|
||||||
stars: 25,
|
|
||||||
followers: 5,
|
|
||||||
}),
|
|
||||||
).toStrictEqual({ level: "B-", percentile: 69.333868386557 });
|
|
||||||
});
|
|
||||||
|
|
||||||
it("median user gets B+ rank", () => {
|
|
||||||
expect(
|
expect(
|
||||||
calculateRank({
|
calculateRank({
|
||||||
all_commits: false,
|
all_commits: false,
|
||||||
@@ -38,13 +24,13 @@ describe("Test calculateRank", () => {
|
|||||||
prs: 50,
|
prs: 50,
|
||||||
issues: 25,
|
issues: 25,
|
||||||
repos: 0,
|
repos: 0,
|
||||||
stars: 50,
|
stars: 250,
|
||||||
followers: 10,
|
followers: 25,
|
||||||
}),
|
}),
|
||||||
).toStrictEqual({ level: "B+", percentile: 50 });
|
).toStrictEqual({ level: "A", score: 50 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("average user gets B+ rank (include_all_commits)", () => {
|
it("average user gets A rank (include_all_commits)", () => {
|
||||||
expect(
|
expect(
|
||||||
calculateRank({
|
calculateRank({
|
||||||
all_commits: true,
|
all_commits: true,
|
||||||
@@ -52,13 +38,13 @@ describe("Test calculateRank", () => {
|
|||||||
prs: 50,
|
prs: 50,
|
||||||
issues: 25,
|
issues: 25,
|
||||||
repos: 0,
|
repos: 0,
|
||||||
stars: 50,
|
stars: 250,
|
||||||
followers: 10,
|
followers: 25,
|
||||||
}),
|
}),
|
||||||
).toStrictEqual({ level: "B+", percentile: 50 });
|
).toStrictEqual({ level: "A", score: 50 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("advanced user gets A rank", () => {
|
it("more than average user gets A+ rank", () => {
|
||||||
expect(
|
expect(
|
||||||
calculateRank({
|
calculateRank({
|
||||||
all_commits: false,
|
all_commits: false,
|
||||||
@@ -66,13 +52,13 @@ describe("Test calculateRank", () => {
|
|||||||
prs: 100,
|
prs: 100,
|
||||||
issues: 50,
|
issues: 50,
|
||||||
repos: 0,
|
repos: 0,
|
||||||
stars: 200,
|
stars: 500,
|
||||||
followers: 40,
|
followers: 50,
|
||||||
}),
|
}),
|
||||||
).toStrictEqual({ level: "A", percentile: 22.72727272727273 });
|
).toStrictEqual({ level: "A+", score: 25 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("expert user gets A+ rank", () => {
|
it("expert user gets S rank", () => {
|
||||||
expect(
|
expect(
|
||||||
calculateRank({
|
calculateRank({
|
||||||
all_commits: false,
|
all_commits: false,
|
||||||
@@ -80,23 +66,23 @@ describe("Test calculateRank", () => {
|
|||||||
prs: 200,
|
prs: 200,
|
||||||
issues: 100,
|
issues: 100,
|
||||||
repos: 0,
|
repos: 0,
|
||||||
stars: 800,
|
stars: 1000,
|
||||||
followers: 160,
|
followers: 100,
|
||||||
}),
|
}),
|
||||||
).toStrictEqual({ level: "A+", percentile: 6.082887700534744 });
|
).toStrictEqual({ level: "S", score: 6.25 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sindresorhus gets S rank", () => {
|
it("ezyang gets S+ rank", () => {
|
||||||
expect(
|
expect(
|
||||||
calculateRank({
|
calculateRank({
|
||||||
all_commits: false,
|
all_commits: false,
|
||||||
commits: 1300,
|
commits: 1000,
|
||||||
prs: 1500,
|
prs: 4000,
|
||||||
issues: 4500,
|
issues: 2000,
|
||||||
repos: 0,
|
repos: 0,
|
||||||
stars: 600000,
|
stars: 5000,
|
||||||
followers: 50000,
|
followers: 2000,
|
||||||
}),
|
}),
|
||||||
).toStrictEqual({ level: "S", percentile: 0.49947889605312934 });
|
).toStrictEqual({ level: "S+", score: 1.1363983154296875 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ const STATS_DATA = {
|
|||||||
totalIssues: 1,
|
totalIssues: 1,
|
||||||
totalStars: 1,
|
totalStars: 1,
|
||||||
contributedTo: 1,
|
contributedTo: 1,
|
||||||
rank: {
|
rank: { level: "B", score: 98.50610674501908 },
|
||||||
level: "A+",
|
|
||||||
score: 50.88831151384285,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const LANGS_DATA = {
|
const LANGS_DATA = {
|
||||||
|
|||||||
Reference in New Issue
Block a user