Last active
May 2, 2024 17:59
-
-
Save bradkrane/36fa3a549e94c208418b4a76ce751ba7 to your computer and use it in GitHub Desktop.
Estimates Remaining Quantity/Time of Doses using Weight
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Doses Remaining Estimator</title> | |
</head> | |
<body> | |
<h2>Doses Remaining Estimator</h2> | |
<form> | |
<label for="emptyWeight">Bottle weight (g):</label> | |
<input type="number" id="emptyWeight" required><br><br> | |
<label for="capWeight">Cap weight (g):</label> | |
<input type="number" id="capWeight"><br><br> | |
<label for="includeCap">Include Cap weight:</label> | |
<input type="checkbox" id="includeCap"><br><br> | |
<label for="doseWeight">Avg. Weight of Dose (g):</label> | |
<input type="number" id="doseWeight" required step="any"><br><br> | |
<label for="dosesPerDay">Avg. dose/d (N.n):</label> | |
<input type="number" id="dosesPerDay"><br><br> | |
<label for="currentWeight">Current Weight of Bottle with Doses (and optionally with cap) (g):</label> | |
<input type="number" id="currentWeight" required><br><br> | |
<button type="button" onclick="calculateAndUpdate()">Calculate Estimates</button> | |
</form> | |
<br> | |
<h3>Estimated Doses Remaining: <span id="dosesRemaining">0</span></h3> | |
<h3>Estimated Days Remaining: <span id="daysRemaining">0</span></h3> | |
<script> | |
function calculateAndUpdate() { | |
const emptyWeight = parseFloat(document.getElementById('emptyWeight').value) || 0; | |
const capWeight = parseFloat(document.getElementById('capWeight').value) || 0; | |
const doseWeight = parseFloat(document.getElementById('doseWeight').value); | |
let currentWeight = parseFloat(document.getElementById('currentWeight').value) || 0; | |
const includeCap = document.getElementById('includeCap').checked; | |
const dosesPerDay = parseFloat(document.getElementById('dosesPerDay').value); | |
// Always update URL with current state | |
const params = new URLSearchParams({ | |
emptyWeight: emptyWeight, | |
capWeight: capWeight || '', | |
doseWeight: doseWeight || '', | |
includeCap: includeCap, | |
dosesPerDay: dosesPerDay || '', | |
currentWeight: currentWeight, | |
}); | |
// weight or other key params needed my not be specified yet so bail on calc | |
if((!doseWeight && !dosesPerDay) || !currentWeight) return; | |
if(includeCap) currentWeight -= capWeight; | |
const weightOfDoses = currentWeight - emptyWeight; | |
let numberOfDoses = null; | |
if(doseWeight) { | |
numberOfDoses = Math.round(weightOfDoses / doseWeight) | |
document.getElementById('dosesRemaining').textContent = numberOfDoses; | |
} | |
if(dosesPerDay && numberOfDoses) | |
document.getElementById('daysRemaining').textContent = Math.floor(Math.floor(numberOfDoses / dosesPerDay)); | |
window.history.replaceState({}, '', `${location.pathname}?${params}`); | |
} | |
function populateFieldsFromURL() { | |
const params = new URLSearchParams(window.location.search); | |
document.querySelectorAll('input').forEach(input => { | |
const paramValue = params.get(input.id); | |
if (input.type === 'checkbox') | |
input.checked = paramValue === 'true'; | |
else if (input.type === 'number') | |
input.value = paramValue ? parseFloat(paramValue) : ''; | |
else | |
input.value = paramValue || ''; | |
}) | |
calculateAndUpdate(); | |
} | |
// if press 'enter' on input run calc | |
document.querySelectorAll('input').forEach(input => { | |
input.addEventListener('keypress', function(event) { | |
if (event.key === "Enter") { | |
event.preventDefault(); | |
calculateAndUpdate(); | |
} | |
}); | |
}); | |
function autoFocusFirstEmptyInput() { | |
const inputs = document.querySelectorAll('input[type="number"], input[type="text"]'); | |
for (let input of inputs) { | |
if (input.value === '') { | |
input.focus(); | |
return; | |
} | |
} | |
} | |
window.onload = function() { | |
populateFieldsFromURL(); | |
autoFocusFirstEmptyInput(); | |
}; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment