将获得的积分转换为玩的小时数(与数学相关)

Converting points gained to hours played (Math related)

我需要使用简单的 JavaScript 将一定数量的经验值转换为一定数量的固定费率的游玩小时数。

例如:

一个玩家有1,129,518经验值。

每小时获得的经验值取决于已经拥有的经验值。他们会这样安排:

0 点以上经验:8,000 xp/h

2,107 经验以上:20,000 xp/h

101,333 经验以上:45,000 xp/h

1,210,421 经验以上:68,500 xp/h

13,034,431 经验以上:75,000 xp/h

我正在努力寻找一种方法来使用这些 xp 比率将给定数量的经验值转换为玩游戏的小时数,使用至少有点优雅 Javascript。

我最终得到了一堆令人困惑的 if/else 语句,这些语句最终由于数学错误而失败。

有没有数学高手可以帮助我?谢谢

代码示例:我会从这里开始

 if(xp === 0){
    return 0;
}else if( 2107 >= xp > 0){
    const result = (xp/8000).toFixed(1);
    return result;
}else if(101333 >= xp > 2107){
    const result = ((2107/8000) + ((xp-2107)/20000)).toFixed(1);
    return result;
}else if(1210421 >= xp > 101333){
    ...
}

如您所见,如果有很多不同的层,它很快就会失控。

首先,你应该这样写你的 if 语句:

if( 2107 >= xp && xp > 0){
    ...
}

接下来,尝试将 XP 视为 XP 的桶,每个桶具有不同的 value/price。从最有价值的桶到最不值钱的桶,并为每个桶计算小时数并减去用于计算这些小时数的 XP 量。

您可以在 while 循环中执行此操作:

let hours = 0;
while(XP > 0)
{
  // figure out bucket you are in, your if statements are fine for that.
  let value = 0;
  let lowerBoundary = 0;
  if( 101333 >= xp && xp > 2107){
    value = 20000;
    lowerBoundary = 2107;
    // you need lower boundary to figure out how many XP you used in this bucket.
  }
  // else if...
  const usedInBucket = XP - lowerBoundary;
  hours += usedInBucket / value; // simply calculate hours needed
  XP -= usedInBucket;
}

这是我想出的:

const steps = [{
    min: 0,
    val: 8000
  },
  {
    min: 2107,
    val: 20000
  },
  {
    min: 101333,
    val: 45000
  },
  {
    min: 1210421,
    val: 68500
  },
  {
    min: 13034431,
    val: 75000
  },
].sort((a, b) => b.min - a.min);

//using for loop
function xpToHours(xp = 0) {
  let h = 0;
  steps.forEach(s => {
    let amt = Math.max(xp - s.min, 0);
    h += amt * s.val;
    xp -= amt;
  });
  return h;
}

//using reduce
function xpToHours2(xp = 0) {
  return steps.reduce((h, s) => {
    let amt = Math.max(xp - s.min, 0);
    xp -= amt;
    return h + amt * s.val;
  }, 0)
}


[0, 1000, 2000, 3000, 1000000].forEach(xp => console.log(xp, xpToHours(xp)));
[0, 1000, 2000, 3000, 1000000].forEach(xp => console.log(xp, xpToHours2(xp)));

说明:

steps 只是一个包含不同阶段的数组。按最小xp从高到低排序

然后我们只是迭代这个数组计算amt这是当前最高阶段用完的xp。因此,所需时间为 amt * currentstep.val,xp 将减少下一阶段的计算量。

最简单的方法是使用排序的范围数组和 Array.prototype.find

// Make sure this is sorted desc
const expRanges = [{
    above: 101333,
    xph: 45000
  },
  {
    above: 2107,
    xph: 20000
  },
  {
    above: 0,
    xph: 8000
  }
];

function findExpPerHour(xp) {
  return expRanges.find(range => range.above < xp).xph;
}

// TESTS
const playerExpTests = [{
  name: "P1",
  xp: 12
}, {
  name: "P2",
  xp: 12000
}, {
  name: "P3",
  xp: 200000
}, {
  name: "P4",
  xp: 99999999
}];

playerExpTests.forEach(p => {
  console.log(p.name, "Exp per hour:", findExpPerHour(p.xp));
});