Doublexp doubleskill.png Double Exp & Skill: Matar monstros rende o dobro de pontos de experiência. O progresso de skills é duas vezes mais rápido! Doublexp doubleskill.png
Bone Overlord.gif The Roost of the Graveborn Quest Spoiler!
Domine Graveborn: todos os bosses e mecânicas ilustradas!
Saiba mais ➔
Winter Tree.png Winter Update 2025
Acompanhe tudo sobre o Winter Update 2025!
Saiba mais ➔
Stag.gif The Order of the Stag Quest Spoiler!
Conheça Isle of Ada: sua quest, missões secundárias e todos os bosses!
Saiba mais ➔

MediaWiki:Common.js/blessing.js: mudanças entre as edições

De Tibia Wiki - A Enciclopédia do Tibia
Ir para navegação Ir para pesquisar
 
(10 revisões intermediárias por 2 usuários não estão sendo mostradas)
Linha 1: Linha 1:
const BLESSINGS = 'Blessings';
<pre id="calc_blessing_html">
const BLOCK = 'block';
<div style="display: flex; flex-flow: column wrap; align-items: center">
const DESCONTOS = 'Descontos';
        <div class="calc_bg" style="display: flex; flex-flow: column wrap; align-items: center">
            <div class="calc_header">
                <div class="calc_border_bottom">
                    <div>Informe o seu level:</div>
                    <div id="level-input-wrapper"></div>
                </div>
            </div>
            <div id="blessing-results" style="padding: 0.75rem">
                <div id="blessing-cost"></div>
                <div id="blessing-discount"></div>
                <div id="blessing-total"></div>
            </div>
        </div>
        <span class="span-version" style="padding: 0.75rem">© TibiaWiki.com.br - Versão 4.0</span>
</div>
</pre>
<pre id="calc_blessing_js">
const BLESSINGS_HEADING = 'Blessings';
const DISCOUNTS_HEADING = 'Descontos';
const TOTALS_HEADING = 'Totais';
const ENHANCED = 'enhanced';
const ENHANCED = 'enhanced';
const INPUT = 'input';
const INQUISITION = 'inquisition';
const KEYDOWN = 'keydown';
const NONE = 'none';
const PHOENIX_EGG = 'phoenixEgg';
const PILGRIMAGE = 'pilgrimage';
const REGULAR = 'regular';
const REGULAR = 'regular';
const TOTAIS = 'Totais';
const TWIST_OF_FATE = 'twist';
const TWIST_OF_FATE = 'twist';
const ID_BLESSING = {
const ID = {
   cost: 'blessing-cost',
   cost: 'blessing-cost',
   discount: 'blessing-discount',
   discount: 'blessing-discount',
   levelInput: 'blessing-level-input',
   levelInput: 'blessing-level-input',
  levelInputWrapper: 'level-input-wrapper',
   results: 'blessing-results',
   results: 'blessing-results',
   total: 'blessing-total',
   total: 'blessing-total',
}
};
 
const BLESSING = {
const BLESSING = {
   regular: {
   regular: {
     maxLevel: 120,
     amount: 5,
     maxLevelScalingValue: 75,
     baseValue: 2000,
     maxUnit: 5,
     levelCeil: 120,
     minLevel: 30,
     levelFloor: 30,
     minLevelScalingValue: 200,
     scaleAboveCeil: 75,
     minValue: 2000,
     scaleAboveFloor: 200,
   },
   },
   enhanced: {
   enhanced: {
     maxLevel: 120,
     amount: 2,
     maxLevelScalingValue: 100,
     baseValue: 2600,
     maxUnit: 2,
     levelCeil: 120,
     minLevel: 30,
     levelFloor: 30,
     minLevelScalingValue: 260,
     scaleAboveCeil: 100,
     minValue: 2600,
     scaleAboveFloor: 260,
   },
   },
   twist: {
   twist: {
     maxLevel: 270,
     baseValue: 2000,
     minLevel: 30,
     levelCeil: 270,
     minLevelScalingValue: 200,
     levelFloor: 30,
     minValue: 2000,
     scaleAboveFloor: 200,
   },
   },
   inquisition: {
   inquisition: {
     minLevel: 100,
     baseValue: 88000,
     minValue: 88000,
     levelFloor: 100,
     scalingFactor: 1.1,
     scaleAboveFloor: 1.1,
   },
   },
};
};
const DISCOUNT = {
const DISCOUNT = {
   phoenixEgg: 0.1,
   phoenixEgg: 0.1,
   pilgrimage: {
   pilgrimage: {
     maxUnit: 5,
     amount: 5,
     minValue: 1000,
     baseValue: 1000,
   },
   },
};
};


const calcBlessing = (level, type, maxUnit = 1) => {
const calcNormalBlessingValue = (
   const { maxLevel, maxLevelScalingValue, minLevel, minLevelScalingValue, minValue } =
  level,
  baseValue,
  levelCeil,
  levelFloor,
  scaleAboveFloor,
  scaleAboveCeil,
  amount
) => {
  const maxValue = baseValue + scaleAboveFloor * (levelCeil - levelFloor);
  return level > levelCeil
    ? (maxValue + scaleAboveCeil * (level - levelCeil)) * amount
    : level > levelFloor
    ? (baseValue + scaleAboveFloor * (level - levelFloor)) * amount
    : baseValue * amount;
};
 
const calcTwistBlessingValue = (
  level,
  baseValue,
  levelCeil,
  levelFloor,
  scaleAboveFloor,
  amount
) => {
  const maxValue = baseValue + scaleAboveFloor * (levelCeil - levelFloor);
  return level > levelCeil
    ? maxValue * amount
    : level > levelFloor
    ? (baseValue + scaleAboveFloor * (level - levelFloor)) * amount
    : baseValue * amount;
};
 
const calcBlessingValue = (level, type, amount = 1) => {
   const { baseValue, levelCeil, levelFloor, scaleAboveFloor, scaleAboveCeil } =
     BLESSING[type];
     BLESSING[type];
  const maxValue = minValue + minLevelScalingValue * (maxLevel - minLevel);


   switch (type) {
   switch (type) {
     case ENHANCED:
     case ENHANCED:
     case REGULAR:
     case REGULAR:
       switch (true) {
       return calcNormalBlessingValue(
         case level > maxLevel:
         level,
          return (maxValue + maxLevelScalingValue * (level - maxLevel)) * maxUnit;
        baseValue,
         case level > minLevel:
        levelCeil,
          return (minValue + minLevelScalingValue * (level - minLevel)) * maxUnit;
        levelFloor,
      }
        scaleAboveFloor,
        scaleAboveCeil,
         amount
      );
     case TWIST_OF_FATE:
     case TWIST_OF_FATE:
       switch (true) {
       return calcTwistBlessingValue(
         case level > maxLevel:
         level,
          return maxValue * maxUnit;
        baseValue,
         case level > minLevel:
        levelCeil,
          return (minValue + minLevelScalingValue * (level - minLevel)) * maxUnit;
        levelFloor,
      }
        scaleAboveFloor,
         amount
      );
     default:
     default:
       return minValue * maxUnit;
       return baseValue * amount;
   }
   }
};
};


const calcInquisitionBlessing = (level) => {
const calcInqBlessingValue = (level) => {
   const { maxUnit } = BLESSING.regular;
   const { amount } = BLESSING.regular;
   const { minLevel, minValue, scalingFactor } = BLESSING.inquisition;
   const { baseValue, levelFloor, scaleAboveFloor } = BLESSING.inquisition;


   if (level >= minLevel) {
   if (level >= levelFloor) {
     return Math.round(calcBlessing(level, REGULAR, maxUnit) * scalingFactor);
     return Math.round(calcBlessingValue(level, REGULAR, amount) * scaleAboveFloor);
   }
   }


   return minValue * maxUnit;
   return baseValue * amount;
};
 
const calcPhxEggDiscount = (level) => {
  return Math.round(calcBlessingValue(level, REGULAR) * DISCOUNT.phoenixEgg);
};
};


const calcDiscountPhoenixEgg = (level) =>
const renderLevelInput = () => {
   Math.round(calcBlessing(level, REGULAR) * DISCOUNT.phoenixEgg);
   const levelInputWrapper = document.querySelector(`#${ID.levelInputWrapper}`);


const toggleResultsDisplay = (level) => {
  const input = document.createElement('input');
   const resultsOutput = document.querySelector(`#${ID_BLESSING.results}`);
  input.id = 'blessing-level-input';
  input.type = 'text';
  input.name = 'level';
  input.min = '0';
  input.max = '9999';
  input.maxLength = '4';
  input.value = '0';
  input.addEventListener('click', () => (input.value = ''));
  input.addEventListener('blur', () => (input.value = !input.value ? '0' : input.value));
 
  if (levelInputWrapper !== null) {
    levelInputWrapper.appendChild(input);
  }
};
 
const setResultsVisibility = (level) => {
   const resultsOutput = document.querySelector(`#${ID.results}`);


   if (level === '' || level === 0) {
   if (level === '' || level === 0) {
     resultsOutput.style.display = NONE;
     resultsOutput.style.display = 'none';
     return;
     return;
   }
   }
   resultsOutput.style.display = BLOCK;
   resultsOutput.style.display = 'block';
};
};


const handleResultsDisplay = (heading, messages, elementId) => {
const renderResults = (heading, messages, elementId) => {
   const resultsList = messages.map((message) => `<li>${message}</li>`);
   const resultsList = messages.map((message) => `<li>${message}</li>`);
   const resultsOutput = document.querySelector(`#${elementId}`);
   const resultsOutput = document.querySelector(`#${elementId}`);
   resultsOutput.innerHTML = `<p>${heading}:</p><ul>${resultsList.join('')}</ul>`;
  // <h3>${heading}</h3> commented out until we have a proper CSS for it
   resultsOutput.innerHTML = `<h3><b style="border-bottom: 1px solid black; display: block; width: 100%;">${heading}</b></h3><ul style="list-style: none;
    text-align: left;">${resultsList.join('')}</ul><br>`;
};
};


const handleKeyDown = (event) => {
const handleKeyDown = (event) => {
   if (
   const allowedKeys = [
     event.keyCode === 8 ||
    'Escape',
     event.keyCode === 9 ||
     'Tab',
     event.keyCode === 13 ||
     'ArrowLeft',
     event.keyCode === 27 ||
     'ArrowRight',
     event.keyCode === 46 ||
     'Home',
     (event.keyCode >= 35 && event.keyCode <= 39) ||
     'End',
     (event.keyCode === 65 && event.ctrlKey === true)
     'Backspace',
   ) {
     'Delete',
    return;
   ];
  }
 
   if (
   if (!allowedKeys.includes(event.code) && isNaN(parseInt(event.key))) {
    event.shiftKey ||
    ((event.keyCode < 48 || event.keyCode > 57) &&
      (event.keyCode < 96 || event.keyCode > 105))
  ) {
     event.preventDefault();
     event.preventDefault();
   }
   }
Linha 136: Linha 202:


const handleInput = (level) => {
const handleInput = (level) => {
   toggleResultsDisplay(level);
   setResultsVisibility(level);


   const enhancedAll = calcBlessing(level, ENHANCED, BLESSING.enhanced.maxUnit);
   const enhancedAll = calcBlessingValue(level, ENHANCED, BLESSING.enhanced.amount);
   const enhancedUnit = calcBlessing(level, ENHANCED);
   const enhancedUnit = calcBlessingValue(level, ENHANCED);
   const inquisitionUnit = calcInquisitionBlessing(level);
   const inquisitionUnit = calcInqBlessingValue(level);
   const phoenixUnit = calcDiscountPhoenixEgg(level);
   const phoenixUnit = calcPhxEggDiscount(level);
   const pilgrimageAll = DISCOUNT.pilgrimage.minValue * DISCOUNT.pilgrimage.maxUnit;
   const pilgrimageAll = DISCOUNT.pilgrimage.baseValue * DISCOUNT.pilgrimage.amount;
   const pilgrimageUnit = DISCOUNT.pilgrimage.minValue;
   const pilgrimageUnit = DISCOUNT.pilgrimage.baseValue;
   const regularAll = calcBlessing(level, REGULAR, BLESSING.regular.maxUnit);
   const regularAll = calcBlessingValue(level, REGULAR, BLESSING.regular.amount);
   const regularUnit = calcBlessing(level, REGULAR);
   const regularUnit = calcBlessingValue(level, REGULAR);
   const twistUnit = calcBlessing(level, TWIST_OF_FATE);
   const twistUnit = calcBlessingValue(level, TWIST_OF_FATE);
   const twistPlusEnhanced = twistUnit + enhancedAll;
   const twistPlusEnhanced = twistUnit + enhancedAll;
   const inquisitionPlusEnhanced = inquisitionUnit + enhancedAll;
   const inquisitionPlusEnhanced = inquisitionUnit + enhancedAll;
Linha 153: Linha 219:
   const allMinusDiscounts = allMinusPhoenix - pilgrimageAll;
   const allMinusDiscounts = allMinusPhoenix - pilgrimageAll;


   const messageFor = {
   const resultFor = {
     blessing: {
     blessing: {
       regular: `Regulares: ${regularUnit.toLocaleString()} gold coins (cada), <b>${regularAll.toLocaleString()} gold coins</b> (total);`,
       regular: [
       enhanced: `Aprimoradas: ${enhancedUnit.toLocaleString()} gold coins (cada), <b>${enhancedAll.toLocaleString()} gold coins</b> (total);`,
        // <a href="/wiki/Blessings#Bênçãos_Comuns"><b>Regulares</b></a>  commented out until we have a proper CSS for it
       twist: `Twist of Fate (protege as 5 regulares em caso de morte por PvP): <b>${twistUnit.toLocaleString()} gold coins</b>;`,
        `<b>Regulares</b> = `,
        `${regularUnit.toLocaleString()} gold coins (cada), `,
        `<b>${regularAll.toLocaleString()} gold coins</b> (total);`,
      ].join(''),
       enhanced: [
        // <a href="/wiki/Blessings#Bênçãos_Melhoradas"><b>Aprimoradas</b></a>  commented out until we have a proper CSS for it
        `<b>Aprimoradas</b> = `,
        `${enhancedUnit.toLocaleString()} gold coins (cada), `,
        `<b>${enhancedAll.toLocaleString()} gold coins</b> (total);`,
      ].join(''),
       twist: [
        // <a href="/wiki/Twist_of_Fate"><b>Twist of Fate</b></a>  commented out until we have a proper CSS for it
        `<b>Twist of Fate</b> <i>(protege as 5 regulares em caso de morte por PvP)</i> = `,
        `<b>${twistUnit.toLocaleString()} gold coins</b>;`,
      ].join(''),
     },
     },
     discount: {
     discount: {
       phoenixEgg: `Phoenix Egg: <b>${phoenixUnit.toLocaleString()} gold coins</b>;`,
      // <a href="/wiki/Phoenix_Egg"><b>Phoenix Egg</b></a>  commented out until we have a proper CSS for it
       pilgrimage: `Pilgrimage of Ashes (apenas 1x): ${pilgrimageUnit.toLocaleString()} gold coins (cada), <b>${pilgrimageAll.toLocaleString()} gold coins</b> (total);`,
       phoenixEgg: `<b>Phoenix Egg</b> = <b>${phoenixUnit.toLocaleString()} gold coins</b>;`,
       pilgrimage: [
        // <a href="/wiki/Pilgrimage_of_Ashes_Quest"><b>Pilgrimage of Ashes</b></a>  commented out until we have a proper CSS for it
        `<b>Pilgrimage of Ashes</b> <i>(apenas 1x)</i> = `,
        `${pilgrimageUnit.toLocaleString()} gold coins (cada), `,
        `<b>${pilgrimageAll.toLocaleString()} gold coins</b> (total);`,
      ].join(''),
     },
     },
     total: {
     total: {
       twistPlusEnhanced: `Twist of Fate + Aprimoradas: <b>${twistPlusEnhanced.toLocaleString()} gold coins</b>;`,
       twistPlusEnhanced: [
       normal: `Normais (Regulares + Aprimoradas): <b>${allBlessings.toLocaleString()} gold coins</b>;`,
        `<b>Twist of Fate</b> + <b>Aprimoradas</b> = `,
       normalMinusDiscounts: `Normais - descontos: <b>${allMinusPhoenix.toLocaleString()} gold coins</b> (Phoenix Egg), <b>${allMinusDiscounts.toLocaleString()} gold coins</b> (Phoenix Egg + Pilgrimage);`,
        `<b>${twistPlusEnhanced.toLocaleString()} gold coins</b>;`,
      ].join(''),
       normal: [
        `<b>Normais</b> <i>(regulares + aprimoradas)</i> = `,
        `<b>${allBlessings.toLocaleString()} gold coins</b>;`,
      ].join(''),
       normalMinusDiscounts: [
        `<b>Normais</b> - <b>Descontos</b> = `,
        `${allMinusPhoenix.toLocaleString()} gold coins (phoenix egg), `,
        `<b>${allMinusDiscounts.toLocaleString()} gold coins</b> (phoenix egg e pilgrimage);`,
      ].join(''),
     },
     },
   };
   };


   if (level >= BLESSING.inquisition.minLevel) {
   if (level >= BLESSING.inquisition.levelFloor) {
     messageFor.blessing.inquisition = `Inquisition: (vale pelas 5 regulares): <b>${inquisitionUnit.toLocaleString()} gold coins</b>.`;
     resultFor.blessing.inquisition = [
     messageFor.total.inquisitionPlusEnhanced = `Inquisition + Aprimoradas: <b>${inquisitionPlusEnhanced.toLocaleString()} gold coins</b>.`;
      // <a href="/wiki/Blessing_of_the_Inquisition"><b>Inquisition</b></a>  commented out until we have a proper CSS for it
      `<b>Inquisition</b> <i>(vale pelas 5 regulares)</i> = `,
      `<b>${inquisitionUnit.toLocaleString()} gold coins</b>.`,
    ].join('');
     resultFor.total.inquisitionPlusEnhanced = [
      `<b>Inquisition</b> + <b>Aprimoradas</b> = `,
      `<b>${inquisitionPlusEnhanced.toLocaleString()} gold coins</b>.`,
    ].join('');
   }
   }


   const messagesForBlessings = Object.values(messageFor.blessing);
   const resultsForBlessings = Object.values(resultFor.blessing);
   handleResultsDisplay(BLESSINGS, messagesForBlessings, ID_BLESSING.cost);
   renderResults(BLESSINGS_HEADING, resultsForBlessings, ID.cost);


   const messagesForDiscounts = Object.values(messageFor.discount);
   const resultsForDiscounts = Object.values(resultFor.discount);
   handleResultsDisplay(DESCONTOS, messagesForDiscounts, ID_BLESSING.discount);
   renderResults(DISCOUNTS_HEADING, resultsForDiscounts, ID.discount);


   const messagesForTotals = Object.values(messageFor.total);
   const resultsForTotals = Object.values(resultFor.total);
   handleResultsDisplay(TOTAIS, messagesForTotals, ID_BLESSING.total);
   renderResults(TOTALS_HEADING, resultsForTotals, ID.total);
};
};


window.onload = () => {
$(document).ready(function() {
   const levelInput = document.querySelector(`#${ID_BLESSING.levelInput}`);
  renderLevelInput();
  toggleResultsDisplay(levelInput.value);
   const levelInput = document.querySelector(`#${ID.levelInput}`);
   levelInput.addEventListener(KEYDOWN, (event) => handleKeyDown(event));
   levelInput.addEventListener('keydown', (event) => handleKeyDown(event));
   levelInput.addEventListener(INPUT, ({ target: { value } }) => handleInput(value));
   levelInput.addEventListener('input', ({ target: { value } }) => handleInput(value));
};
});
</pre>

Edição atual tal como às 14h51min de 5 de setembro de 2023

<pre id="calc_blessing_html">
<div style="display: flex; flex-flow: column wrap; align-items: center">
        <div class="calc_bg" style="display: flex; flex-flow: column wrap; align-items: center">
            <div class="calc_header">
                <div class="calc_border_bottom">
                    <div>Informe o seu level:</div>
                    <div id="level-input-wrapper"></div>
                </div>
            </div>
            <div id="blessing-results" style="padding: 0.75rem">
                <div id="blessing-cost"></div>
                <div id="blessing-discount"></div>
                <div id="blessing-total"></div>
            </div>
        </div>
        <span class="span-version" style="padding: 0.75rem">© TibiaWiki.com.br - Versão 4.0</span>
</div>
</pre>
<pre id="calc_blessing_js">
const BLESSINGS_HEADING = 'Blessings';
const DISCOUNTS_HEADING = 'Descontos';
const TOTALS_HEADING = 'Totais';
const ENHANCED = 'enhanced';
const REGULAR = 'regular';
const TWIST_OF_FATE = 'twist';
const ID = {
  cost: 'blessing-cost',
  discount: 'blessing-discount',
  levelInput: 'blessing-level-input',
  levelInputWrapper: 'level-input-wrapper',
  results: 'blessing-results',
  total: 'blessing-total',
};
const BLESSING = {
  regular: {
    amount: 5,
    baseValue: 2000,
    levelCeil: 120,
    levelFloor: 30,
    scaleAboveCeil: 75,
    scaleAboveFloor: 200,
  },
  enhanced: {
    amount: 2,
    baseValue: 2600,
    levelCeil: 120,
    levelFloor: 30,
    scaleAboveCeil: 100,
    scaleAboveFloor: 260,
  },
  twist: {
    baseValue: 2000,
    levelCeil: 270,
    levelFloor: 30,
    scaleAboveFloor: 200,
  },
  inquisition: {
    baseValue: 88000,
    levelFloor: 100,
    scaleAboveFloor: 1.1,
  },
};
const DISCOUNT = {
  phoenixEgg: 0.1,
  pilgrimage: {
    amount: 5,
    baseValue: 1000,
  },
};

const calcNormalBlessingValue = (
  level,
  baseValue,
  levelCeil,
  levelFloor,
  scaleAboveFloor,
  scaleAboveCeil,
  amount
) => {
  const maxValue = baseValue + scaleAboveFloor * (levelCeil - levelFloor);
  return level > levelCeil
    ? (maxValue + scaleAboveCeil * (level - levelCeil)) * amount
    : level > levelFloor
    ? (baseValue + scaleAboveFloor * (level - levelFloor)) * amount
    : baseValue * amount;
};

const calcTwistBlessingValue = (
  level,
  baseValue,
  levelCeil,
  levelFloor,
  scaleAboveFloor,
  amount
) => {
  const maxValue = baseValue + scaleAboveFloor * (levelCeil - levelFloor);
  return level > levelCeil
    ? maxValue * amount
    : level > levelFloor
    ? (baseValue + scaleAboveFloor * (level - levelFloor)) * amount
    : baseValue * amount;
};

const calcBlessingValue = (level, type, amount = 1) => {
  const { baseValue, levelCeil, levelFloor, scaleAboveFloor, scaleAboveCeil } =
    BLESSING[type];

  switch (type) {
    case ENHANCED:
    case REGULAR:
      return calcNormalBlessingValue(
        level,
        baseValue,
        levelCeil,
        levelFloor,
        scaleAboveFloor,
        scaleAboveCeil,
        amount
      );
    case TWIST_OF_FATE:
      return calcTwistBlessingValue(
        level,
        baseValue,
        levelCeil,
        levelFloor,
        scaleAboveFloor,
        amount
      );
    default:
      return baseValue * amount;
  }
};

const calcInqBlessingValue = (level) => {
  const { amount } = BLESSING.regular;
  const { baseValue, levelFloor, scaleAboveFloor } = BLESSING.inquisition;

  if (level >= levelFloor) {
    return Math.round(calcBlessingValue(level, REGULAR, amount) * scaleAboveFloor);
  }

  return baseValue * amount;
};

const calcPhxEggDiscount = (level) => {
  return Math.round(calcBlessingValue(level, REGULAR) * DISCOUNT.phoenixEgg);
};

const renderLevelInput = () => {
  const levelInputWrapper = document.querySelector(`#${ID.levelInputWrapper}`);

  const input = document.createElement('input');
  input.id = 'blessing-level-input';
  input.type = 'text';
  input.name = 'level';
  input.min = '0';
  input.max = '9999';
  input.maxLength = '4';
  input.value = '0';
  input.addEventListener('click', () => (input.value = ''));
  input.addEventListener('blur', () => (input.value = !input.value ? '0' : input.value));

  if (levelInputWrapper !== null) {
    levelInputWrapper.appendChild(input);
  }
};

const setResultsVisibility = (level) => {
  const resultsOutput = document.querySelector(`#${ID.results}`);

  if (level === '' || level === 0) {
    resultsOutput.style.display = 'none';
    return;
  }
  resultsOutput.style.display = 'block';
};

const renderResults = (heading, messages, elementId) => {
  const resultsList = messages.map((message) => `<li>${message}</li>`);
  const resultsOutput = document.querySelector(`#${elementId}`);
  // <h3>${heading}</h3> commented out until we have a proper CSS for it
  resultsOutput.innerHTML = `<h3><b style="border-bottom: 1px solid black; display: block; width: 100%;">${heading}</b></h3><ul style="list-style: none;
    text-align: left;">${resultsList.join('')}</ul><br>`;
};

const handleKeyDown = (event) => {
  const allowedKeys = [
    'Escape',
    'Tab',
    'ArrowLeft',
    'ArrowRight',
    'Home',
    'End',
    'Backspace',
    'Delete',
  ];

  if (!allowedKeys.includes(event.code) && isNaN(parseInt(event.key))) {
    event.preventDefault();
  }
};

const handleInput = (level) => {
  setResultsVisibility(level);

  const enhancedAll = calcBlessingValue(level, ENHANCED, BLESSING.enhanced.amount);
  const enhancedUnit = calcBlessingValue(level, ENHANCED);
  const inquisitionUnit = calcInqBlessingValue(level);
  const phoenixUnit = calcPhxEggDiscount(level);
  const pilgrimageAll = DISCOUNT.pilgrimage.baseValue * DISCOUNT.pilgrimage.amount;
  const pilgrimageUnit = DISCOUNT.pilgrimage.baseValue;
  const regularAll = calcBlessingValue(level, REGULAR, BLESSING.regular.amount);
  const regularUnit = calcBlessingValue(level, REGULAR);
  const twistUnit = calcBlessingValue(level, TWIST_OF_FATE);
  const twistPlusEnhanced = twistUnit + enhancedAll;
  const inquisitionPlusEnhanced = inquisitionUnit + enhancedAll;
  const allBlessings = regularAll + enhancedAll;
  const allMinusPhoenix = allBlessings - phoenixUnit;
  const allMinusDiscounts = allMinusPhoenix - pilgrimageAll;

  const resultFor = {
    blessing: {
      regular: [
        // <a href="/wiki/Blessings#Bênçãos_Comuns"><b>Regulares</b></a>  commented out until we have a proper CSS for it
        `<b>Regulares</b> = `,
        `${regularUnit.toLocaleString()} gold coins (cada), `,
        `<b>${regularAll.toLocaleString()} gold coins</b> (total);`,
      ].join(''),
      enhanced: [
        // <a href="/wiki/Blessings#Bênçãos_Melhoradas"><b>Aprimoradas</b></a>  commented out until we have a proper CSS for it
        `<b>Aprimoradas</b> = `,
        `${enhancedUnit.toLocaleString()} gold coins (cada), `,
        `<b>${enhancedAll.toLocaleString()} gold coins</b> (total);`,
      ].join(''),
      twist: [
        // <a href="/wiki/Twist_of_Fate"><b>Twist of Fate</b></a>  commented out until we have a proper CSS for it
        `<b>Twist of Fate</b> <i>(protege as 5 regulares em caso de morte por PvP)</i> = `,
        `<b>${twistUnit.toLocaleString()} gold coins</b>;`,
      ].join(''),
    },
    discount: {
      // <a href="/wiki/Phoenix_Egg"><b>Phoenix Egg</b></a>  commented out until we have a proper CSS for it
      phoenixEgg: `<b>Phoenix Egg</b> = <b>${phoenixUnit.toLocaleString()} gold coins</b>;`,
      pilgrimage: [
        // <a href="/wiki/Pilgrimage_of_Ashes_Quest"><b>Pilgrimage of Ashes</b></a>  commented out until we have a proper CSS for it
        `<b>Pilgrimage of Ashes</b> <i>(apenas 1x)</i> = `,
        `${pilgrimageUnit.toLocaleString()} gold coins (cada), `,
        `<b>${pilgrimageAll.toLocaleString()} gold coins</b> (total);`,
      ].join(''),
    },
    total: {
      twistPlusEnhanced: [
        `<b>Twist of Fate</b> + <b>Aprimoradas</b> = `,
        `<b>${twistPlusEnhanced.toLocaleString()} gold coins</b>;`,
      ].join(''),
      normal: [
        `<b>Normais</b> <i>(regulares + aprimoradas)</i> = `,
        `<b>${allBlessings.toLocaleString()} gold coins</b>;`,
      ].join(''),
      normalMinusDiscounts: [
        `<b>Normais</b> - <b>Descontos</b> = `,
        `${allMinusPhoenix.toLocaleString()} gold coins (phoenix egg), `,
        `<b>${allMinusDiscounts.toLocaleString()} gold coins</b> (phoenix egg e pilgrimage);`,
      ].join(''),
    },
  };

  if (level >= BLESSING.inquisition.levelFloor) {
    resultFor.blessing.inquisition = [
      // <a href="/wiki/Blessing_of_the_Inquisition"><b>Inquisition</b></a>  commented out until we have a proper CSS for it
      `<b>Inquisition</b> <i>(vale pelas 5 regulares)</i> = `,
      `<b>${inquisitionUnit.toLocaleString()} gold coins</b>.`,
    ].join('');
    resultFor.total.inquisitionPlusEnhanced = [
      `<b>Inquisition</b> + <b>Aprimoradas</b> = `,
      `<b>${inquisitionPlusEnhanced.toLocaleString()} gold coins</b>.`,
    ].join('');
  }

  const resultsForBlessings = Object.values(resultFor.blessing);
  renderResults(BLESSINGS_HEADING, resultsForBlessings, ID.cost);

  const resultsForDiscounts = Object.values(resultFor.discount);
  renderResults(DISCOUNTS_HEADING, resultsForDiscounts, ID.discount);

  const resultsForTotals = Object.values(resultFor.total);
  renderResults(TOTALS_HEADING, resultsForTotals, ID.total);
};

$(document).ready(function() {
  renderLevelInput();
  const levelInput = document.querySelector(`#${ID.levelInput}`);
  levelInput.addEventListener('keydown', (event) => handleKeyDown(event));
  levelInput.addEventListener('input', ({ target: { value } }) => handleInput(value));
});
</pre>