Commit db49ca7b authored by anuraghazra's avatar anuraghazra
Browse files

feat: added rankings

parent 8e8d7dd6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ module.exports = async (req, res) => {
    username,
    hide,
    hide_border,
    hide_rank,
    show_icons,
    line_height,
    title_color,
@@ -29,6 +30,7 @@ module.exports = async (req, res) => {
      hide: JSON.parse(hide || "[]"),
      show_icons,
      hide_border,
      hide_rank,
      line_height,
      title_color,
      icon_color,

src/calculateRank.js

0 → 100644
+52 −0
Original line number Diff line number Diff line
function calculateRank({
  totalRepos,
  totalCommits,
  contributions,
  followers,
  prs,
  issues,
  stargazers,
}) {
  const COMMITS_OFFSET = 1.65;
  const CONTRIBS_OFFSET = 1.65;
  const ISSUES_OFFSET = 1;
  const STARS_OFFSET = 0.75;
  const PRS_OFFSET = 0.5;
  const FOLLOWERS_OFFSET = 0.45;

  const FIRST_STEP = 0;
  const SECOND_STEP = 5;
  const THIRD_STEP = 20;
  const FOURTH_STEP = 50;
  const FIFTH_STEP = 130;

  // prettier-ignore
  const score = (
    totalCommits * COMMITS_OFFSET +
    contributions * CONTRIBS_OFFSET +
    issues * ISSUES_OFFSET +
    stargazers * STARS_OFFSET +
    prs * PRS_OFFSET +
    followers * FOLLOWERS_OFFSET
  ) / totalRepos;

  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) {
    level = "S+";
  }

  return { level, score };
}

module.exports = calculateRank;
+16 −0
Original line number Diff line number Diff line
const { request } = require("./utils");
const calculateRank = require("./calculateRank");
require("dotenv").config();

async function fetchStats(username) {
@@ -22,7 +23,11 @@ async function fetchStats(username) {
          issues(first: 100) {
            totalCount
          }
          followers {
            totalCount
          }
          repositories(first: 100, orderBy: { direction: DESC, field: STARGAZERS }) {
            totalCount
            nodes {
              stargazers {
                totalCount
@@ -42,6 +47,7 @@ async function fetchStats(username) {
    totalIssues: 0,
    totalStars: 0,
    contributedTo: 0,
    rank: "C",
  };

  if (res.data.errors) {
@@ -61,6 +67,16 @@ async function fetchStats(username) {
    return prev + curr.stargazers.totalCount;
  }, 0);

  stats.rank = calculateRank({
    totalCommits: stats.totalCommits,
    totalRepos: user.repositories.totalCount,
    followers: user.followers.totalCount,
    contributions: stats.contributedTo,
    stargazers: stats.totalStars,
    prs: stats.totalPRs,
    issues: stats.totalIssues,
  });

  return stats;
}

+56 −3
Original line number Diff line number Diff line
@@ -18,11 +18,13 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
    totalIssues,
    totalPRs,
    contributedTo,
    rank,
  } = stats;
  const {
    hide = [],
    show_icons = false,
    hide_border = false,
    hide_rank = false,
    line_height = 25,
    title_color,
    icon_color,
@@ -81,23 +83,74 @@ const renderStatsCard = (stats = {}, options = { hide: [] }) => {
    .filter((key) => !hide.includes(key))
    .map((key) => STAT_MAP[key]);

  const height = 45 + (statItems.length + 1) * lheight;
  // Calculate the card height depending on how many items there are
  // but if rank circle is visible clamp the minimum height to `150`
  const height = Math.max(
    45 + (statItems.length + 1) * lheight,
    hide_rank ? 0 : 150
  );

  const border = `
    <rect 
      data-testid="card-border"
      x="0.5"
      y="0.5"
      width="494"
      height="99%"
      rx="4.5"
      fill="${bgColor}"
      stroke="#E4E2E2"
    />
  `;

  const rankProgress = 180 + rank.score * 0.8;
  const rankCircle = hide_rank
    ? ""
    : `<g data-testid="rank-circle" transform="translate(400, ${
        height / 1.85
      })">
        <circle class="rank-circle" cx="-10" cy="8" r="40" />
        <text
          x="0"
          y="0"
          alignment-baseline="central"
          dominant-baseline="central"
          text-anchor="middle"
          class="rank-text"
          transform="translate(-5, 5)"
        >
          ${rank.level}
        </text>
      </g>`;

  const border = `<rect data-testid="card-border" x="0.5" y="0.5" width="494" height="99%" rx="4.5" fill="${bgColor}" stroke="#E4E2E2"/>`;
  return `
    <svg width="495" height="${height}" viewBox="0 0 495 ${height}" fill="none" xmlns="http://www.w3.org/2000/svg">
      <style>
      .header { font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${titleColor}; }
      .stat { font: 600 14px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor}; }
      .rank-text { font: 800 24px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor}; }
      .star-icon { font: 600 18px 'Segoe UI', Ubuntu, Sans-Serif; }
      .bold { font-weight: 700 }
      .icon {
        fill: ${iconColor};
        display: ${!!show_icons ? "block" : "none"};
      }
      .rank-circle {
        stroke-dashoffset: 30;
        stroke-dasharray: ${rankProgress};
        stroke: ${titleColor};
        fill: none;
        stroke-width: 6;
        stroke-linecap: round;
        opacity: 0.8;
        transform-origin: -10px 8px;
        transform: rotate(-90deg);
      }
      </style>
      ${hide_border ? "" : border}

      ${rankCircle}
      
      <text x="25" y="35" class="header">${name}'s GitHub Stats</text>
      <text y="45">
        ${statItems.toString().replace(/\,/gm, "")}
+13 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@ const MockAdapter = require("axios-mock-adapter");
const api = require("../api/index");
const renderStatsCard = require("../src/renderStatsCard");
const { renderError } = require("../src/utils");
const calculateRank = require("../src/calculateRank");

const stats = {
  name: "Anurag Hazra",
@@ -12,7 +13,17 @@ const stats = {
  totalIssues: 300,
  totalPRs: 400,
  contributedTo: 500,
  rank: null,
};
stats.rank = calculateRank({
  totalCommits: stats.totalCommits,
  totalRepos: 1,
  followers: 0,
  contributions: stats.contributedTo,
  stargazers: stats.totalStars,
  prs: stats.totalPRs,
  issues: stats.totalIssues,
});

const data = {
  data: {
@@ -22,7 +33,9 @@ const data = {
      contributionsCollection: { totalCommitContributions: stats.totalCommits },
      pullRequests: { totalCount: stats.totalPRs },
      issues: { totalCount: stats.totalIssues },
      followers: { totalCount: 0 },
      repositories: {
        totalCount: 1,
        nodes: [{ stargazers: { totalCount: 100 } }],
      },
    },
Loading