fork download
  1. <!DOCTYPE html>
  2. <html lang="ja">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>遮断ダメージ計算ツール</title>
  6. <style>
  7. body { font-family: sans-serif; padding: 20px; }
  8. label { display: block; margin-top: 10px; }
  9. input { width: 220px; }
  10.  
  11. button {
  12. margin-top: 20px;
  13. font-size: 20px;
  14. padding: 12px 30px;
  15. background-color: #007BFF;
  16. color: white;
  17. border: none;
  18. border-radius: 8px;
  19. cursor: pointer;
  20. transition: background-color 0.3s ease;
  21. }
  22.  
  23. button:hover {
  24. background-color: #0056b3;
  25. }
  26.  
  27. #result, #formula {
  28. margin-top: 20px;
  29. white-space: pre-line;
  30. background: #f9f9f9;
  31. padding: 10px;
  32. border-radius: 5px;
  33. border: 1px solid #ccc;
  34. }
  35. </style>
  36. </head>
  37. <body>
  38. <h2>遮断ダメージ計算ツール</h2>
  39.  
  40. <label>最大HP: <input type="text" id="hp" value="0"></label>
  41. <label>受けるダメージ: <input type="text" id="damage" value="0"></label>
  42. <label>被ダメージ減少(%カット): <input type="text" id="reduction" value="0"></label>
  43. <label>遮断ライン(HPの何%を超えた分に遮断適用): <input type="text" id="aPercent" value="0"></label>
  44. <label>遮断率(超過部分のダメージを何%遮断): <input type="text" id="blockRate" value="0"></label>
  45.  
  46. <button onclick="calculate()">計算</button>
  47.  
  48. <div id="result"></div>
  49. <div id="formula"></div>
  50.  
  51. <script>
  52. function parseMixedNumber(input) {
  53. const units = { '億': 100000000, '万': 10000 };
  54. let total = 0;
  55. let matched = false;
  56.  
  57. for (let unit in units) {
  58. const regex = new RegExp('(\\d+(?:\\.\\d+)?)' + unit);
  59. const match = input.match(regex);
  60. if (match) {
  61. total += parseFloat(match[1]) * units[unit];
  62. input = input.replace(match[0], '');
  63. matched = true;
  64. }
  65. }
  66.  
  67. if (input.match(/[一二三四五六七八九〇十百千万億]/)) {
  68. total += kanjiToNumber(input);
  69. matched = true;
  70. } else if (input.trim().length > 0) {
  71. total += parseFloat(input);
  72. matched = true;
  73. }
  74.  
  75. return matched ? total : NaN;
  76. }
  77.  
  78. function kanjiToNumber(kanji) {
  79. const nums = { '〇': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9 };
  80. const units = { '十': 10, '百': 100, '千': 1000 };
  81. const bigUnits = { '万': 10000, '億': 100000000 };
  82. let total = 0;
  83.  
  84. const parseSection = (str) => {
  85. let n = 0, temp = 0;
  86. for (let c of str) {
  87. if (nums[c] !== undefined) {
  88. temp = nums[c];
  89. } else if (units[c]) {
  90. n += (temp || 1) * units[c];
  91. temp = 0;
  92. }
  93. }
  94. return n + temp;
  95. };
  96.  
  97. let tmp = kanji;
  98. for (let unit in bigUnits) {
  99. const idx = tmp.indexOf(unit);
  100. if (idx !== -1) {
  101. const left = tmp.slice(0, idx);
  102. total += parseSection(left) * bigUnits[unit];
  103. tmp = tmp.slice(idx + 1);
  104. }
  105. }
  106.  
  107. total += parseSection(tmp);
  108. return total;
  109. }
  110.  
  111. function formatNumber(num) {
  112. if (num >= 100000000) return (num / 100000000).toFixed(2).replace(/\.00$/, '') + "億";
  113. if (num >= 10000) return (num / 10000).toFixed(2).replace(/\.00$/, '') + "万";
  114. return num.toLocaleString();
  115. }
  116.  
  117. function calculate() {
  118. const hp = parseMixedNumber(document.getElementById("hp").value);
  119. let damage = parseMixedNumber(document.getElementById("damage").value);
  120. const originalDamage = damage;
  121. const reductionRate = parseFloat(document.getElementById("reduction").value) / 100 || 0;
  122. const aPercent = parseFloat(document.getElementById("aPercent").value) / 100 || 0;
  123. const blockRate = parseFloat(document.getElementById("blockRate").value) / 100 || 0;
  124.  
  125. if (isNaN(hp) || isNaN(damage)) {
  126. document.getElementById("result").innerText = "HPまたはダメージが無効です。";
  127. document.getElementById("formula").innerText = "";
  128. return;
  129. }
  130.  
  131. damage = damage * (1 - reductionRate);
  132. const threshold = hp * aPercent;
  133. const excess = Math.max(0, damage - threshold);
  134. const blockedDamage = excess * (1 - blockRate);
  135. const nonBlockedDamage = damage - excess;
  136. const totalDamage = nonBlockedDamage + blockedDamage;
  137. const resultHP = hp - totalDamage;
  138.  
  139. const attackCount = totalDamage > 0 ? (hp / totalDamage) : Infinity;
  140. const attackCountDisplay = attackCount === Infinity ? "∞" : attackCount.toFixed(3);
  141.  
  142. const finalBlockRate = (1 - (totalDamage / originalDamage)) * 100;
  143. const finalBlockRateDisplay = isFinite(finalBlockRate) ? finalBlockRate.toFixed(2) + "%" : "0%";
  144.  
  145. document.getElementById("result").innerText =
  146. `受けたダメージ: ${formatNumber(totalDamage)}\n残りHP: ${formatNumber(resultHP)}\n` +
  147. `最終遮断率: ${finalBlockRateDisplay}\n` +
  148. `このダメージでHPを0以下にするには 約 ${attackCountDisplay} 回攻撃が必要`;
  149.  
  150. document.getElementById("formula").innerText =
  151. `計算詳細:
  152. 最大HP: ${formatNumber(hp)}
  153. 受けるダメージ(初期): ${formatNumber(originalDamage)}
  154. 被ダメージ減少: ${(reductionRate * 100).toFixed(1)}% → ${formatNumber(damage)}
  155. 遮断発動ライン: ${formatNumber(threshold)}(${(aPercent * 100).toFixed(1)}%
  156. 超過ダメージ: ${formatNumber(excess)}
  157. 遮断率: ${(blockRate * 100).toFixed(1)}%
  158. 遮断後の超過ダメージ: ${formatNumber(blockedDamage)}
  159. 非遮断ダメージ: ${formatNumber(nonBlockedDamage)}
  160. 合計ダメージ: ${formatNumber(totalDamage)}
  161. 最終遮断率(元のダメージと比較): ${finalBlockRateDisplay}
  162. 残りHP: ${formatNumber(hp)} - ${formatNumber(totalDamage)} = ${formatNumber(resultHP)}
  163. HPを0以下にするのに必要な攻撃回数: 約 ${attackCountDisplay} 回`;
  164. }
  165. </script>
  166. </body>
  167. </html>
Success #stdin #stdout 0.03s 25904KB
stdin
Standard input is empty
stdout
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>遮断ダメージ計算ツール</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    label { display: block; margin-top: 10px; }
    input { width: 220px; }

    button {
      margin-top: 20px;
      font-size: 20px;
      padding: 12px 30px;
      background-color: #007BFF;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
      transition: background-color 0.3s ease;
    }

    button:hover {
      background-color: #0056b3;
    }

    #result, #formula {
      margin-top: 20px;
      white-space: pre-line;
      background: #f9f9f9;
      padding: 10px;
      border-radius: 5px;
      border: 1px solid #ccc;
    }
  </style>
</head>
<body>
  <h2>遮断ダメージ計算ツール</h2>

  <label>最大HP: <input type="text" id="hp" value="0"></label>
  <label>受けるダメージ: <input type="text" id="damage" value="0"></label>
  <label>被ダメージ減少(%カット): <input type="text" id="reduction" value="0"></label>
  <label>遮断ライン(HPの何%を超えた分に遮断適用): <input type="text" id="aPercent" value="0"></label>
  <label>遮断率(超過部分のダメージを何%遮断): <input type="text" id="blockRate" value="0"></label>

  <button onclick="calculate()">計算</button>

  <div id="result"></div>
  <div id="formula"></div>

  <script>
    function parseMixedNumber(input) {
      const units = { '億': 100000000, '万': 10000 };
      let total = 0;
      let matched = false;

      for (let unit in units) {
        const regex = new RegExp('(\\d+(?:\\.\\d+)?)' + unit);
        const match = input.match(regex);
        if (match) {
          total += parseFloat(match[1]) * units[unit];
          input = input.replace(match[0], '');
          matched = true;
        }
      }

      if (input.match(/[一二三四五六七八九〇十百千万億]/)) {
        total += kanjiToNumber(input);
        matched = true;
      } else if (input.trim().length > 0) {
        total += parseFloat(input);
        matched = true;
      }

      return matched ? total : NaN;
    }

    function kanjiToNumber(kanji) {
      const nums = { '〇': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9 };
      const units = { '十': 10, '百': 100, '千': 1000 };
      const bigUnits = { '万': 10000, '億': 100000000 };
      let total = 0;

      const parseSection = (str) => {
        let n = 0, temp = 0;
        for (let c of str) {
          if (nums[c] !== undefined) {
            temp = nums[c];
          } else if (units[c]) {
            n += (temp || 1) * units[c];
            temp = 0;
          }
        }
        return n + temp;
      };

      let tmp = kanji;
      for (let unit in bigUnits) {
        const idx = tmp.indexOf(unit);
        if (idx !== -1) {
          const left = tmp.slice(0, idx);
          total += parseSection(left) * bigUnits[unit];
          tmp = tmp.slice(idx + 1);
        }
      }

      total += parseSection(tmp);
      return total;
    }

    function formatNumber(num) {
      if (num >= 100000000) return (num / 100000000).toFixed(2).replace(/\.00$/, '') + "億";
      if (num >= 10000) return (num / 10000).toFixed(2).replace(/\.00$/, '') + "万";
      return num.toLocaleString();
    }

    function calculate() {
      const hp = parseMixedNumber(document.getElementById("hp").value);
      let damage = parseMixedNumber(document.getElementById("damage").value);
      const originalDamage = damage;
      const reductionRate = parseFloat(document.getElementById("reduction").value) / 100 || 0;
      const aPercent = parseFloat(document.getElementById("aPercent").value) / 100 || 0;
      const blockRate = parseFloat(document.getElementById("blockRate").value) / 100 || 0;

      if (isNaN(hp) || isNaN(damage)) {
        document.getElementById("result").innerText = "HPまたはダメージが無効です。";
        document.getElementById("formula").innerText = "";
        return;
      }

      damage = damage * (1 - reductionRate);
      const threshold = hp * aPercent;
      const excess = Math.max(0, damage - threshold);
      const blockedDamage = excess * (1 - blockRate);
      const nonBlockedDamage = damage - excess;
      const totalDamage = nonBlockedDamage + blockedDamage;
      const resultHP = hp - totalDamage;

      const attackCount = totalDamage > 0 ? (hp / totalDamage) : Infinity;
      const attackCountDisplay = attackCount === Infinity ? "∞" : attackCount.toFixed(3);

      const finalBlockRate = (1 - (totalDamage / originalDamage)) * 100;
      const finalBlockRateDisplay = isFinite(finalBlockRate) ? finalBlockRate.toFixed(2) + "%" : "0%";

      document.getElementById("result").innerText =
        `受けたダメージ: ${formatNumber(totalDamage)}\n残りHP: ${formatNumber(resultHP)}\n` +
        `最終遮断率: ${finalBlockRateDisplay}\n` +
        `このダメージでHPを0以下にするには 約 ${attackCountDisplay} 回攻撃が必要`;

      document.getElementById("formula").innerText =
        `計算詳細:
最大HP: ${formatNumber(hp)}
受けるダメージ(初期): ${formatNumber(originalDamage)}
被ダメージ減少: ${(reductionRate * 100).toFixed(1)}% → ${formatNumber(damage)}
遮断発動ライン: ${formatNumber(threshold)}(${(aPercent * 100).toFixed(1)}%)
超過ダメージ: ${formatNumber(excess)}
遮断率: ${(blockRate * 100).toFixed(1)}%
遮断後の超過ダメージ: ${formatNumber(blockedDamage)}
非遮断ダメージ: ${formatNumber(nonBlockedDamage)}
合計ダメージ: ${formatNumber(totalDamage)}
最終遮断率(元のダメージと比較): ${finalBlockRateDisplay}
残りHP: ${formatNumber(hp)} - ${formatNumber(totalDamage)} = ${formatNumber(resultHP)}
HPを0以下にするのに必要な攻撃回数: 約 ${attackCountDisplay} 回`;
    }
  </script>
</body>
</html>