0

I have the following HTML file where I want a number level within 50% of a given target (the "Level" field) to be input into the "Attribute" field

<!DOCTYPE html>

<html>
    <body>
        <input type = "number" name = "playerLevel" onchange = "populateAttributes()" id = "playerLevel">
        <label for = "playerLevel">Level</label>
    </body>

    <br>

    <tr>
        <td><input type = "number" id = "attributeScore"></td>
        <label for = "attribute">Attribute</label>
    </tr>

    <script src = "script.js"></script>
</html>

And I have the following Javascript code to generate random numbers

function generateRandomLevel(targetLevel)
{
    const target = targetLevel; // The target around which the random levels are generated
    const range = 0.5;  // 0.5 => 50% deviation from target and so on
    const upperLevelLimit = Math.round(target + target * range);    // Target + 50% deviation
    const lowerLevelLimit = Math.round(target - target * range);    // Target - 50% deviation
    let x = parseInt(Math.random() * (upperLevelLimit - lowerLevelLimit) + lowerLevelLimit);    // Generate Level within 50% of target
    return x;
}

function populateAttributes()
{
    let y = generateRandomLevel(document.getElementById("playerLevel").value);  // Passes the value of "playerLevel" to the random nunber generator
    document.getElementById("attributeScore").value = y;    // Set the value inside "playerLevel" to the random number generated
}

However, when I update the "Level" field, I get numbers totally out of range of the target like 72 incase of entering 10 into the "Level" field.

Does anyone know why this happens?

When I run the random number generator as a standalone, it works just fine, i.e

function generateRandomLevel(playerLevel)
{
    const target = playerLevel;
    const range = 0.5;
    const upperLevelLimit = Math.round(target + target * range);
    const lowerLevelLimit = Math.round(target - target * range);
    let x = parseInt(Math.random() * (upperLevelLimit - lowerLevelLimit) + lowerLevelLimit);
    return x;
}

console.log(generateRandomLevel(10));
MDK
  • 19
  • 3
  • [Adding two numbers concatenates them instead of calculating the sum](https://stackoverflow.com/questions/14496531/adding-two-numbers-concatenates-them-instead-of-calculating-the-sum) – Ivar Jul 24 '23 at 11:36
  • As has been pointed out, this is not HTML specific, it's that element in HTML are strings, and in your standalone example it will do the same if you pass a string, -> `generateRandomLevel("10")` To make your function handle this case, just do -> `const target = Number(playerLevel);` – Keith Jul 24 '23 at 11:38

2 Answers2

1

change this document.getElementById("playerLevel").valueAsNumber to use valueAsNumber

function generateRandomLevel(targetLevel)
{
    const target = targetLevel; // The target around which the random levels are generated
    const range = 0.5;  // 0.5 => 50% deviation from target and so on
    const upperLevelLimit = Math.round(target + target * range);    // Target + 50% deviation
    const lowerLevelLimit = Math.round(target - target * range);    // Target - 50% deviation
    let x = parseInt(Math.random() * (upperLevelLimit - lowerLevelLimit) + lowerLevelLimit);    // Generate Level within 50% of target
    return x;
}

function populateAttributes()
{
    let y = generateRandomLevel(document.getElementById("playerLevel").valueAsNumber);  // Passes the value of "playerLevel" to the random nunber generator
    document.getElementById("attributeScore").value = y;    // Set the value inside "playerLevel" to the random number generated
}

because value is treated as a string

Dean Van Greunen
  • 5,060
  • 2
  • 14
  • 28
1

This is happening because the value property from an <input> will always be a string. You need to parse the value to a number with parseInt(targetLevel, 10);

See the below that does this, but also logs out the type and value.

This is a problem because doing math on strings actually does work in JavaScript and you can get weird results like this. For example 5 + 5 will produce 10 as you'd expect, but "5" + "5" will produce "55" and "55" * 0.5 will produce 52.3 - this is where your strangeness is coming from

Math.round("5" + "5" * 0.5) //53
Math.round(5 + 5 * 0.5) //8

function generateRandomLevel(targetLevel) {
  console.log(typeof targetLevel, targetLevel);
  const target = parseInt(targetLevel, 10); // The target around which the random levels are generated
  console.log(typeof target, target);
  const range = 0.5;  // 0.5 => 50% deviation from target and so on
  const upperLevelLimit = Math.round(target + target * range);    // Target + 50% deviation
  const lowerLevelLimit = Math.round(target - target * range);    // Target - 50% deviation
  let x = parseInt(Math.random() * (upperLevelLimit - lowerLevelLimit) + lowerLevelLimit);    // Generate Level within 50% of target
  return x;
}

function populateAttributes() {
  let y = generateRandomLevel(document.getElementById("playerLevel").value);  // Passes the value of "playerLevel" to the random nunber generator
  document.getElementById("attributeScore").value = y;    // Set the value inside "playerLevel" to the random number generated
}
<input type = "number" name = "playerLevel" onchange = "populateAttributes()" id = "playerLevel">
<label for = "playerLevel">Level</label>

<br/><br/>

<input type = "number" id = "attributeScore">
<label for = "attribute">Attribute</label>
Chris Barr
  • 29,851
  • 23
  • 95
  • 135