Widget:Calculator/Bad Luck
<style>
- luck-calculator-form { margin-top: 10px; max-width: 360px; }
- luck-calculator-form label,
- luck-calculator-form input,
- luck-calculator-form button { display: block; box-sizing: border-box; border-radius: 4px; width: 100%; }
- luck-calculator-form label { margin: 8px 0 4px; font-weight: bold; }
- luck-calculator-form input { background-color: var(--bg-main, #1e1f22); color: var(--text-main, #b6b4b2); border: 1px solid var(--border-color-base, #2d2d2d); padding: 8px 10px; font-size: 14px; }
- luck-calculator-form button { background-color: var(--theme-color-accent-base, #2ecc71); color: white; border: none; padding: 8px 12px; margin-top: 15px; cursor: pointer; font-size: 16px; transition: background-color 0.2s; }
- luck-calculator-form button:hover { background-color: var(--theme-color-accent-hover, #27ae60); }
.luck-results-box { margin-top: 20px; padding: 15px; background-color: var(--bg-secondary, #1a1a1a); color: var(--text-main, #ccc); border: 1px solid var(--border-color-base, #333); border-radius: 5px; line-height: 1.5; } .luck-results-box b { color: var(--text-bright, #fff); } .luck-results-box table { width: 100%; margin-top: 15px; border-collapse: collapse; font-size: 13px; } .luck-results-box th, .luck-results-box td { padding: 6px 8px; text-align: left; border-bottom: 1px solid var(--border-color-base, #333); } .luck-results-box tr:last-child td { border-bottom: none; } .luck-results-box th { color: var(--text-bright, #fff); } </style> <form id="luck-calculator-form">
<label for="dropRateInput">Drop Rate</label> <input id="dropRateInput" type="text" placeholder="e.g., 1/1000, 0.1%, or 0.001" /> <label for="attemptsInput">Number of Attempts</label> <input id="attemptsInput" type="text" placeholder="e.g., 5000" /> <button type="submit">Calculate</button>
</form> <script> document.getElementById("luck-calculator-form").addEventListener("submit", handleCalculation); function parseDropRate(input) {
const cleanInput = input.trim().replace(/^~/, ).replace(/,/g, ); if (cleanInput.endsWith("%")) { const parsed = parseFloat(cleanInput.slice(0, -1)); return isNaN(parsed) ? NaN : parsed / 100; } if (cleanInput.includes("/")) { const [numStr, denomStr] = cleanInput.split("/"); const num = parseFloat(numStr); const denom = parseFloat(denomStr); if (!isNaN(num) && !isNaN(denom) && denom > 0) return num / denom; return NaN; } const parsed = parseFloat(cleanInput); return isNaN(parsed) ? NaN : parsed;
} function generateDropChanceTable(p) {
const targetChances = [10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99];
let html = `
To achieve a specific chance for a 1 in ${Math.round(1/p).toLocaleString()} drop, you would need:
targetChances.forEach(chance => { const attempts = Math.log(1 - (chance / 100)) / Math.log(1 - p);html += ``;
});html += "
Chance | Required Attempts |
---|---|
${chance}% | ${Math.ceil(attempts).toLocaleString()} |
";
return html;
} function handleCalculation(event) {
event.preventDefault(); const dropRateStr = document.getElementById("dropRateInput").value; const attemptsStr = document.getElementById("attemptsInput").value; const resultBox = document.getElementById("luck-result"); const p = parseDropRate(dropRateStr); const attempts = parseInt(attemptsStr.replace(/,/g, ).trim(), 10); if (isNaN(p) || p <= 0 || p >= 1 || isNaN(attempts) || attempts <= 0) { resultBox.innerHTML = "Please enter a valid drop rate and number of attempts."; resultBox.style.display = "block"; return; } const noDropProb = Math.pow(1 - p, attempts); const dryPercent = noDropProb * 100; const inverseChance = 1 / noDropProb; const resultText = `${dryPercent.toFixed(4)}% of players would be this dry or drier. That's roughly 1 in ${Math.round(inverseChance).toLocaleString()} players.` + generateDropChanceTable(p); resultBox.innerHTML = resultText; resultBox.style.display = "block";
} </script>