将获得的积分转换为玩的小时数(与数学相关)
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));
});
我需要使用简单的 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));
});