Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

333
Views
Calculate number of medals based on number of entries

I have an app that awards the user based upon number of entries made.

  • 10 entries = 1 bronze,
  • 20 entries = 1 bronze, 1 silver,
  • 30 entries = 1 bronze, 1 silver and 1 gold

It then repeats the cycle forever, always in multiples of 10.

  • 40 entries = 2 bronze, 1 silver, 1 gold
  • 50 entries = 2 silver, 2 silver, 1 gold
  • 60 entries = 2 gold, 2 bronze and 2 gold

1-9 should show in progress for each level, and every tenth entry begins the next level. 1 is 10%, 9 is 90 % and rather than show 100%, just go straight to the next level.

I show a progress bar for the current level, a percentage of complete for current level, the icon of the level the user is going for. All of those currently show correctly.

The issue I'm facing is I also show a count for each level, which is only correct up to and including 44 entries. The 45th is where things start to go wrong.

Please check out the below or on jsfiddle and feel free to edit.

const DENOMINATOR = 10;

const clamp = (value: number, min: number, max: number): number => {
    return Math.min(Math.max(value, min), max);
}

const calculateAwardsByEntryCount = (count: number) => {
  const maxLevels = 3 * DENOMINATOR;
  const modulus = count % maxLevels;
  const currentLevel = Math.max(0, Math.floor(modulus / DENOMINATOR) - 1);
  const nextLevel = Math.min(3, currentLevel + 1);
  const prestige = Math.ceil((count + 1) / maxLevels);
  const progress = ((modulus - DENOMINATOR * nextLevel) / DENOMINATOR) * 100;

  let bronze = 0;
  let silver = 0;
  let gold = 0;

  if (count >= DENOMINATOR) {
    bronze = count <= maxLevels ? 1 : Math.floor(modulus / (DENOMINATOR - 1)) * prestige;
  }

  if (count >= DENOMINATOR * 2 && bronze > 0) {
    silver = count <= maxLevels ? 1 : clamp(Math.ceil(modulus / (DENOMINATOR * 2 - 1)) * prestige, 0, bronze + 1);
  }

  if (count >= DENOMINATOR * 3 && silver > 0) {
    gold = count <= maxLevels ? 1 : clamp(Math.ceil((modulus / (DENOMINATOR * 3 - 1)) * prestige), 0, silver + 1);
  }

  return {
    achieved: {bronze, silver, gold},
    currentLevel,
    nextLevel,
    progress,
  }
}

console.log(calculateAwardsByEntryCount(45));

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

It's not exactly the most efficient solution, but at least it 100% accurate for any number of entries.

const DENOMINATOR = 10;

const calculateAwardsByEntryCount = (count: number) => {
  let remainingProgress = count;
  let currentLevel = null;
  let bronze = 0;
  let silver = 0;
  let gold = 0;

  for (remainingProgress; remainingProgress >= DENOMINATOR; remainingProgress -= DENOMINATOR) {
    switch (currentLevel) {
      case 1:
        currentLevel = 2;
        gold += 1;
        break;
      case 0:
        currentLevel = 1;
        silver += 1;
        break;
      default:
        currentLevel = 0;
        bronze += 1;
        break;
    }
  }


  if (currentLevel === null) {
    currentLevel = -1
  }
  
  const progress = (remainingProgress / DENOMINATOR) * 100;
  const nextLevel = currentLevel === 2 ? 0 : currentLevel + 1;

  return {
    achieved: {
      bronze,
      silver,
      gold
    },
    nextLevel,
    progress,
  };
}

console.log(calculateAwardsByEntryCount(9));
console.log(calculateAwardsByEntryCount(10));
console.log(calculateAwardsByEntryCount(20));
console.log(calculateAwardsByEntryCount(30));
console.log(calculateAwardsByEntryCount(35));
console.log(calculateAwardsByEntryCount(45));
console.log(calculateAwardsByEntryCount(55));
console.log(calculateAwardsByEntryCount(65));
console.log(calculateAwardsByEntryCount(75));

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!