Compare commits

..
Author SHA1 Message Date
anuraghazra a726e8dbaf chore: added funding link
Test / build (push) Canceled after 0s
2020-07-16 14:02:15 +05:30
Anurag Hazra 817f736b4e Merge pull request #61 from JounQin/patch-1
chore: remove redundant codes
2020-07-15 20:37:42 +05:30
Anurag Hazra 987fb0c30d Merge pull request #49 from anuraghazra/ranking-algo
improve: improved rating algorithm wip

fix: fixed #39
2020-07-15 20:10:53 +05:30
anuraghazra 96d37c706f fix: fixed stars count #39 & fixed progressbar percentage
Test / build (push) Canceled after 0s
2020-07-15 20:00:22 +05:30
anuraghazra 3a24ad62b1 Merge branch 'master' into ranking-algo 2020-07-15 19:47:07 +05:30
Anurag Hazra 989079e4fd Merge pull request #64 from anuraghazra/fix-nolang
fix: fixed repo card breaking in absence of primaryLanguage
2020-07-15 19:39:40 +05:30
anuraghazra 20bddc3a0c fix: fixed repo card breaking in absence of primaryLanguage
Test / build (push) Canceled after 0s
2020-07-15 19:37:04 +05:30
JounQin 95f1233ab9 chore: rebase from master 2020-07-15 21:55:04 +08:00
JounQin 1a53fb9a84 Merge branch 'master' into patch-1 2020-07-15 21:41:48 +08:00
Anurag Hazra 19bacf780a Merge pull request #63 from anuraghazra/fix-rank-alignment
design: fixed rank alignment
2020-07-15 19:01:39 +05:30
anuraghazra 89bb8fea42 design: fixed rank alignment 2020-07-15 18:59:38 +05:30
Anurag Hazra 0bade9be77 Merge pull request #62 from anuraghazra/fix-queryparams
fix: query param booleans
2020-07-15 18:34:19 +05:30
JounQin 579ed2bab8 chore: remove redundant codes
`axios` is Promise based, there is no need to wrap it into a Promise constructor again
2020-07-15 20:22:06 +08:00
anuraghazra 2658a8737d improve: improved rating algorithm wip 2020-07-14 14:08:57 +05:30
8 changed files with 111 additions and 67 deletions
+12
View File
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: ["https://www.paypal.me/anuraghazra"] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+7 -5
View File
@@ -1,6 +1,7 @@
<p align="center">
<h2 align="center">GitHub Readme Stats</h2>
<p align="center">Get dynamically generated GitHub stats on your readmes!</p>
</p>
<p align="center">
<a href="https://github.com/anuraghazra/github-readme-stats/actions">
@@ -22,6 +23,7 @@
<a href="https://github.com/anuraghazra/github-readme-stats/issues">Request Feature</a>
</p>
</p>
<p align="center">Loved the project? Please consider <a href="https://www.paypal.me/anuraghazra">donating</a> to help it improve!
# Features
@@ -151,18 +153,18 @@ Since the GitHub API only allows 5k requests per hour, it is possible that my `h
1. Go to [vercel.com](https://vercel.com/)
1. Click on `Log in`
![](https://files.catbox.moe/tct1wg.png)
![](https://files.catbox.moe/tct1wg.png)
1. Sign in with GitHub by pressing `Continue with GitHub`
![](https://files.catbox.moe/btd78j.jpeg)
![](https://files.catbox.moe/btd78j.jpeg)
1. Sign into GitHub and allow access to all repositories, if prompted
1. Fork this repo
1. Go back to your [Vercel dashboard](https://vercel.com/dashboard)
1. Select `Import Project`
![](https://files.catbox.moe/qckos0.png)
![](https://files.catbox.moe/qckos0.png)
1. Select `Import Git Repository`
![](https://files.catbox.moe/pqub9q.png)
![](https://files.catbox.moe/pqub9q.png)
1. Select root and keep everything as is, just add your environment variable named GITHUB_TOKEN (as shown), which will contain a personal access token (PAT), which you can easily create [here](https://github.com/settings/tokens/new) (leave everything as is, just name it something, it can be anything you want)
![](https://files.catbox.moe/caem5b.png)
![](https://files.catbox.moe/caem5b.png)
1. Click deploy, and you're good to go. See your domains to use the API!
</details>
+60 -19
View File
@@ -1,3 +1,21 @@
// https://stackoverflow.com/a/5263759/10629172
function normalcdf(mean, sigma, to) {
var z = (to - mean) / Math.sqrt(2 * sigma * sigma);
var t = 1 / (1 + 0.3275911 * Math.abs(z));
var a1 = 0.254829592;
var a2 = -0.284496736;
var a3 = 1.421413741;
var a4 = -1.453152027;
var a5 = 1.061405429;
var erf =
1 - ((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * Math.exp(-z * z);
var sign = 1;
if (z < 0) {
sign = -1;
}
return (1 / 2) * (1 + sign * erf);
}
function calculateRank({
totalRepos,
totalCommits,
@@ -13,12 +31,24 @@ function calculateRank({
const STARS_OFFSET = 0.75;
const PRS_OFFSET = 0.5;
const FOLLOWERS_OFFSET = 0.45;
const REPO_OFFSET = 1;
const FIRST_STEP = 0;
const SECOND_STEP = 5;
const THIRD_STEP = 20;
const FOURTH_STEP = 50;
const FIFTH_STEP = 130;
const ALL_OFFSETS =
CONTRIBS_OFFSET +
ISSUES_OFFSET +
STARS_OFFSET +
PRS_OFFSET +
FOLLOWERS_OFFSET +
REPO_OFFSET;
const RANK_S_VALUE = 1;
const RANK_DOUBLE_A_VALUE = 25;
const RANK_A2_VALUE = 45;
const RANK_A3_VALUE = 60;
const RANK_B_VALUE = 100;
const TOTAL_VALUES =
RANK_S_VALUE + RANK_A2_VALUE + RANK_A3_VALUE + RANK_B_VALUE;
// prettier-ignore
const score = (
@@ -27,26 +57,37 @@ function calculateRank({
issues * ISSUES_OFFSET +
stargazers * STARS_OFFSET +
prs * PRS_OFFSET +
followers * FOLLOWERS_OFFSET
) / totalRepos;
followers * FOLLOWERS_OFFSET +
totalRepos * REPO_OFFSET
) / 100;
const normalizedScore = normalcdf(score, TOTAL_VALUES, ALL_OFFSETS) * 100;
let level = "";
if (score == FIRST_STEP) {
level = "B";
} else if (score > FIRST_STEP && score <= SECOND_STEP) {
level = "B+";
} else if (score > SECOND_STEP && score <= THIRD_STEP) {
level = "A";
} else if (score > THIRD_STEP && score <= FOURTH_STEP) {
level = "A+";
} else if (score > FOURTH_STEP && score <= FIFTH_STEP) {
level = "A++";
} else if (score > FIFTH_STEP) {
if (normalizedScore < RANK_S_VALUE) {
level = "S+";
}
if (
normalizedScore >= RANK_S_VALUE &&
normalizedScore < RANK_DOUBLE_A_VALUE
) {
level = "S";
}
if (
normalizedScore >= RANK_DOUBLE_A_VALUE &&
normalizedScore < RANK_A2_VALUE
) {
level = "A++";
}
if (normalizedScore >= RANK_A2_VALUE && normalizedScore < RANK_A3_VALUE) {
level = "A+";
}
if (normalizedScore >= RANK_A3_VALUE && normalizedScore < RANK_B_VALUE) {
level = "B+";
}
return { level, score };
return { level, score: normalizedScore };
}
module.exports = calculateRank;
+1 -1
View File
@@ -26,7 +26,7 @@ const fetcher = (variables, token) => {
followers {
totalCount
}
repositories(first: 100, orderBy: { direction: DESC, field: STARGAZERS }) {
repositories(first: 100, ownerAffiliations: OWNER, isFork: false, orderBy: {direction: DESC, field: STARGAZERS}) {
totalCount
nodes {
stargazers {
+11 -14
View File
@@ -1,23 +1,24 @@
const { kFormatter, encodeHTML, isValidHexColor } = require("../src/utils");
const { kFormatter, encodeHTML, fallbackColor } = require("../src/utils");
const renderRepoCard = (repo, options = {}) => {
const { name, description, primaryLanguage, stargazers, forkCount } = repo;
const { title_color, icon_color, text_color, bg_color } = options;
const langName = primaryLanguage ? primaryLanguage.name : "Unspecified";
const langColor = primaryLanguage ? primaryLanguage.color : "#333";
const height = 120;
const shiftText = primaryLanguage.name.length > 15 ? 0 : 30;
const shiftText = langName.length > 15 ? 0 : 30;
let desc = description || "No description provided";
if (desc.length > 55) {
desc = `${description.slice(0, 55)}..`;
}
const titleColor =
(isValidHexColor(title_color) && `#${title_color}`) || "#2f80ed";
const iconColor =
(isValidHexColor(icon_color) && `#${icon_color}`) || "#586069";
const textColor = (isValidHexColor(text_color) && `#${text_color}`) || "#333";
const bgColor = (isValidHexColor(bg_color) && `#${bg_color}`) || "#FFFEFE";
const titleColor = fallbackColor(title_color, "#2f80ed");
const iconColor = fallbackColor(icon_color, "#586069");
const textColor = fallbackColor(text_color, "#333");
const bgColor = fallbackColor(bg_color, "#FFFEFE");
const totalStars = kFormatter(stargazers.totalCount);
const totalForks = kFormatter(forkCount);
@@ -38,12 +39,8 @@ const renderRepoCard = (repo, options = {}) => {
<text class="description" x="25" y="70">${encodeHTML(desc)}</text>
<g transform="translate(30, 100)">
<circle data-testid="lang-color" cx="0" cy="-5" r="6" fill="${
primaryLanguage.color
}" />
<text data-testid="lang" class="gray" x="15">${
primaryLanguage.name
}</text>
<circle data-testid="lang-color" cx="0" cy="-5" r="6" fill="${langColor}" />
<text data-testid="lang" class="gray" x="15">${langName}</text>
</g>
<g transform="translate(${155 - shiftText}, 100)">
+9 -16
View File
@@ -1,4 +1,4 @@
const { kFormatter, isValidHexColor } = require("../src/utils");
const { kFormatter, fallbackColor } = require("../src/utils");
const getStyles = require("./getStyles");
const createTextNode = ({ icon, label, value, id, index, lineHeight }) => {
@@ -43,12 +43,10 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
const lheight = parseInt(line_height);
const titleColor =
(isValidHexColor(title_color) && `#${title_color}`) || "#2f80ed";
const iconColor =
(isValidHexColor(icon_color) && `#${icon_color}`) || "#4c71f2";
const textColor = (isValidHexColor(text_color) && `#${text_color}`) || "#333";
const bgColor = (isValidHexColor(bg_color) && `#${bg_color}`) || "#FFFEFE";
const titleColor = fallbackColor(title_color, "#2f80ed");
const iconColor = fallbackColor(icon_color, "#4c71f2");
const textColor = fallbackColor(text_color, "#333");
const bgColor = fallbackColor(bg_color, "#FFFEFE");
const STATS = {
stars: {
@@ -118,7 +116,7 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
<circle class="rank-circle-rim" cx="-10" cy="8" r="40" />
<circle class="rank-circle" cx="-10" cy="8" r="40" />
<text
x="0"
x="${rank.level.length === 1 ? "-4" : "0"}"
y="0"
alignment-baseline="central"
dominant-baseline="central"
@@ -129,14 +127,9 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
</text>
</g>`;
// re-adjust circle progressbar's value until the ranking algo is improved
let progress = rank.score;
if (rank.score > 86) {
progress = (40 + rank.score) * 0.6;
}
if (rank.score < 40) {
progress = 40 + rank.score;
}
// the better user's score the the rank will be closer to zero so
// subtracting 100 to get the progress in 100%
let progress = 100 - rank.score;
const styles = getStyles({
titleColor,
+10 -11
View File
@@ -43,18 +43,16 @@ function parseBoolean(value) {
}
}
function fallbackColor(color, fallbackColor) {
return (isValidHexColor(color) && `#${color}`) || fallbackColor;
}
function request(data, headers) {
return new Promise((resolve, reject) => {
axios({
url: "https://api.github.com/graphql",
method: "post",
headers: {
...headers,
},
data,
})
.then((response) => resolve(response))
.catch((error) => reject(error));
return axios({
url: "https://api.github.com/graphql",
method: "post",
headers,
data,
});
}
@@ -65,4 +63,5 @@ module.exports = {
isValidHexColor,
request,
parseBoolean,
fallbackColor,
};
+1 -1
View File
@@ -13,6 +13,6 @@ describe("Test calculateRank", () => {
prs: 300,
issues: 200,
})
).toStrictEqual({ level: "S+", score: 192.13 });
).toStrictEqual({ level: "A+", score: 49.16605417270399 });
});
});