根据参赛作品数量计算奖牌数量

Calculate number of medals based on number of entries

我有一个应用会根据输入的次数奖励用户。

然后它会永远重复这个循环,始终是 10 的倍数。

1-9 应显示每个级别的进度,每十个条目开始下一级别。 1是10%,9是90%,不显示100%,直接进入下一关

我显示了当前关卡的进度条,当前关卡的完成百分比,用户要去的关卡的图标。目前所有这些都正确显示。

我面临的问题是我还显示了每个级别的计数,该计数仅在 44 个条目(包括 44 个条目)内是正确的。 45号开始出问题了。

请查看以下内容或on jsfiddle并随时编辑。

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));

这不是最有效的解决方案,但至少它对于任意数量的条目都是 100% 准确的。

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));