feat: Add cage calc that shows requirements for a number of rats
This commit is contained in:
		@@ -8,8 +8,8 @@
 | 
				
			|||||||
  "depth-cm": "Tiefe (cm)",
 | 
					  "depth-cm": "Tiefe (cm)",
 | 
				
			||||||
  "height-cm": "Höhe (cm)",
 | 
					  "height-cm": "Höhe (cm)",
 | 
				
			||||||
  "full-floors": "Vollebenen",
 | 
					  "full-floors": "Vollebenen",
 | 
				
			||||||
  "number-of-rats": "Anzahl an Ratten",
 | 
					 | 
				
			||||||
  "result": "Ergebnis",
 | 
					  "result": "Ergebnis",
 | 
				
			||||||
 | 
					  "number-of-rats": "Anzahl an Ratten",
 | 
				
			||||||
  "change-language": "Sprache ändern",
 | 
					  "change-language": "Sprache ändern",
 | 
				
			||||||
  "failed-base-area": "Die Mindestgrundfläche des Käfigs muss {{ MINIMUM_BASE_AREA }}m² (also z.B. 100x50cm) betragen.",
 | 
					  "failed-base-area": "Die Mindestgrundfläche des Käfigs muss {{ MINIMUM_BASE_AREA }}m² (also z.B. 100x50cm) betragen.",
 | 
				
			||||||
  "failed-overall-area": "Die Gesamtfläche im Käfig ist zu klein.",
 | 
					  "failed-overall-area": "Die Gesamtfläche im Käfig ist zu klein.",
 | 
				
			||||||
@@ -18,6 +18,12 @@
 | 
				
			|||||||
  "failed-num-rats": "Es müssen mindestens 3 Ratten zusammenleben, Paarhaltung ist nicht artgerecht.",
 | 
					  "failed-num-rats": "Es müssen mindestens 3 Ratten zusammenleben, Paarhaltung ist nicht artgerecht.",
 | 
				
			||||||
  "failed-minimum-length-long-side": "Die lange Seite des Käfig muss mindestens {{ minimum_length_long_side }}cm lang sein um Rennen zu ermöglichen.",
 | 
					  "failed-minimum-length-long-side": "Die lange Seite des Käfig muss mindestens {{ minimum_length_long_side }}cm lang sein um Rennen zu ermöglichen.",
 | 
				
			||||||
  "failed-minimum-length-short-side": "Die kurze Seite des Käfig muss mindestens {{ minimum_length_short_side }}cm lang sein.",
 | 
					  "failed-minimum-length-short-side": "Die kurze Seite des Käfig muss mindestens {{ minimum_length_short_side }}cm lang sein.",
 | 
				
			||||||
 | 
					  "base-area": "Die Mindestgrundfläche des Käfigs muss {{ MINIMUM_BASE_AREA }}m² betragen.",
 | 
				
			||||||
 | 
					  "fall-height": "Die mögliche Fallhöhe darf nicht mehr als {{ maximum_fall_height }}cm betragen.",
 | 
				
			||||||
 | 
					  "floor-height": "Der Mindestabstand zwischen Ebenen muss {{ minimum_floor_height }}cm betragen.",
 | 
				
			||||||
 | 
					  "minimum-length-long-side": "Die lange Seite des Käfig muss mindestens {{ minimum_length_long_side }}cm lang sein um Rennen zu ermöglichen.",
 | 
				
			||||||
 | 
					  "minimum-length-short-side": "Die kurze Seite des Käfig muss mindestens {{ minimum_length_short_side }}cm lang sein.",
 | 
				
			||||||
  "cage-complies-with-all-criteria": "Der Käfig erfüllt alle Kriterien!",
 | 
					  "cage-complies-with-all-criteria": "Der Käfig erfüllt alle Kriterien!",
 | 
				
			||||||
  "cage-for-x-rats": "Käfig für {{ num_rats }} Ratten"
 | 
					  "cage-for-x-rats": "Käfig für {{ num_rats }} Ratten",
 | 
				
			||||||
 | 
					  "overall-area": "Die Gesamtfläche für {{ numRats }} Ratten muss mindestens {{ minimumOverallArea }}m² betragen."
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,8 +8,8 @@
 | 
				
			|||||||
  "depth-cm": "Depth (cm)",
 | 
					  "depth-cm": "Depth (cm)",
 | 
				
			||||||
  "height-cm": "Height (cm)",
 | 
					  "height-cm": "Height (cm)",
 | 
				
			||||||
  "full-floors": "Full floors",
 | 
					  "full-floors": "Full floors",
 | 
				
			||||||
  "number-of-rats": "Number of Rats",
 | 
					 | 
				
			||||||
  "result": "Result",
 | 
					  "result": "Result",
 | 
				
			||||||
 | 
					  "number-of-rats": "Number of Rats",
 | 
				
			||||||
  "change-language": "Change language",
 | 
					  "change-language": "Change language",
 | 
				
			||||||
  "failed-base-area": "The base area of the cage must not be below {{ MINIMUM_BASE_AREA }}m².",
 | 
					  "failed-base-area": "The base area of the cage must not be below {{ MINIMUM_BASE_AREA }}m².",
 | 
				
			||||||
  "failed-overall-area": "The overall area in the cage is to small.",
 | 
					  "failed-overall-area": "The overall area in the cage is to small.",
 | 
				
			||||||
@@ -18,6 +18,12 @@
 | 
				
			|||||||
  "failed-num-rats": "Rats must live in a group of at least three rats, pairs or lone rats are not species-appropriate.",
 | 
					  "failed-num-rats": "Rats must live in a group of at least three rats, pairs or lone rats are not species-appropriate.",
 | 
				
			||||||
  "failed-minimum-length-long-side": "The long side of the cage must be at least {{ minimum_length_long_side }}cm long to enable running.",
 | 
					  "failed-minimum-length-long-side": "The long side of the cage must be at least {{ minimum_length_long_side }}cm long to enable running.",
 | 
				
			||||||
  "failed-minimum-length-short-side": "The short side of the cage must be at least {{ minimum_length_short_side }}cm.",
 | 
					  "failed-minimum-length-short-side": "The short side of the cage must be at least {{ minimum_length_short_side }}cm.",
 | 
				
			||||||
 | 
					  "base-area": "The base area of the cage must not be below {{ MINIMUM_BASE_AREA }}m².",
 | 
				
			||||||
 | 
					  "fall-height": "The possible fall height between floors must not be above {{ maximum_fall_height }}cm.",
 | 
				
			||||||
 | 
					  "floor-height": "The height between floors must be above {{ minimum_floor_height }}cm.",
 | 
				
			||||||
 | 
					  "minimum-length-long-side": "The long side of the cage must be at least {{ minimum_length_long_side }}cm long to enable running.",
 | 
				
			||||||
 | 
					  "minimum-length-short-side": "The short side of the cage must be at least {{ minimum_length_short_side }}cm.",
 | 
				
			||||||
  "cage-complies-with-all-criteria": "This cage complies with all criteria!",
 | 
					  "cage-complies-with-all-criteria": "This cage complies with all criteria!",
 | 
				
			||||||
  "cage-for-x-rats": "Cage for {{ num_rats }} rats"
 | 
					  "cage-for-x-rats": "Cage for {{ num_rats }} rats",
 | 
				
			||||||
 | 
					  "overall-area": "The overall area in the cage must be above {{ minimumOverallArea }}m² for {{ numRats }} rats."
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -119,7 +119,29 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="" data-content-id="2">
 | 
					    <div class="" data-content-id="2">
 | 
				
			||||||
        <p>Here is a list of cages you can get.</p>
 | 
					        <div class="card">
 | 
				
			||||||
 | 
					            <div class="card-content">
 | 
				
			||||||
 | 
					                <h2 class="title is-4"><label data-i18n="number-of-rats"
 | 
				
			||||||
 | 
					                                              for="cage-calc">Anzahl der Ratten</label></h2>
 | 
				
			||||||
 | 
					                <form id="cage-calc">
 | 
				
			||||||
 | 
					                    <div class="column">
 | 
				
			||||||
 | 
					                        <label id="cageCalcLabelNumRats" for="cageCalcNumRats"></label>
 | 
				
			||||||
 | 
					                        <input type="range" min="3" max="15" value="4" class="slider" id="cageCalcNumRats">
 | 
				
			||||||
 | 
					                        <img class="inline-icon" src="assets/img/logo_transparent.png" alt="Kleine Ratte">
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </form>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="card-footer is-fullwidth">
 | 
				
			||||||
 | 
					                <div class="card result-card" id="cage-calc-result-card">
 | 
				
			||||||
 | 
					                    <div class="card-header">
 | 
				
			||||||
 | 
					                        <h2 class="card-header-title is-3 is-centered" data-i18n="result">Ergebnis</h2>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div class="card-content">
 | 
				
			||||||
 | 
					                        <div id="cageCalcResultsDiv"></div>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="" data-content-id="3">
 | 
					    <div class="" data-content-id="3">
 | 
				
			||||||
        <div class="card">
 | 
					        <div class="card">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								src/index.js
									
									
									
									
									
								
							@@ -71,7 +71,6 @@ function bindLocaleSwitcher(initialValue) {
 | 
				
			|||||||
//////////
 | 
					//////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
function initTabs(tabs, tabContent, activationClass) {
 | 
					function initTabs(tabs, tabContent, activationClass) {
 | 
				
			||||||
    tabs.forEach((tab) => {
 | 
					    tabs.forEach((tab) => {
 | 
				
			||||||
        tab.addEventListener('click', (e) => {
 | 
					        tab.addEventListener('click', (e) => {
 | 
				
			||||||
@@ -122,13 +121,21 @@ const MINIMUM_LENGTH_LONG_SIDE = 0.8;
 | 
				
			|||||||
const MINIMUM_LENGTH_SHORT_SIDE = 0.5;
 | 
					const MINIMUM_LENGTH_SHORT_SIDE = 0.5;
 | 
				
			||||||
const MINIMUM_FLOOR_HEIGHT = 0.25;
 | 
					const MINIMUM_FLOOR_HEIGHT = 0.25;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const FAILED_BASE_AREA = "base_area";
 | 
					const FAILED_BASE_AREA = "failed_base_area";
 | 
				
			||||||
const FAILED_OVERALL_AREA = "overall_area";
 | 
					const FAILED_OVERALL_AREA = "failed_overall_area";
 | 
				
			||||||
const FAILED_FALL_HEIGHT = "fall_height";
 | 
					const FAILED_FALL_HEIGHT = "failed_fall_height";
 | 
				
			||||||
const FAILED_NUM_RATS = "num_rats";
 | 
					const FAILED_NUM_RATS = "failed_num_rats";
 | 
				
			||||||
const FAILED_MINIMUM_LENGTH_LONG_SIDE = "length_long_side";
 | 
					const FAILED_MINIMUM_LENGTH_LONG_SIDE = "failed_length_long_side";
 | 
				
			||||||
const FAILED_MINIMUM_LENGTH_SHORT_SIDE = "length_short_side";
 | 
					const FAILED_MINIMUM_LENGTH_SHORT_SIDE = "failed_length_short_side";
 | 
				
			||||||
const FAILED_FLOOR_HEIGHT = "floor_height"
 | 
					const FAILED_FLOOR_HEIGHT = "failed_floor_height"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CRITERIA_BASE_AREA = "base_area";
 | 
				
			||||||
 | 
					const CRITERIA_FALL_HEIGHT = "fall_height";
 | 
				
			||||||
 | 
					const CRITERIA_MINIMUM_LENGTH_LONG_SIDE = "length_long_side";
 | 
				
			||||||
 | 
					const CRITERIA_MINIMUM_LENGTH_SHORT_SIDE = "length_short_side";
 | 
				
			||||||
 | 
					const CRITERIA_FLOOR_HEIGHT = "floor_height"
 | 
				
			||||||
 | 
					const CRITERIA_OVERALL_AREA = "overall_area"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Validator {
 | 
					class Validator {
 | 
				
			||||||
@@ -142,6 +149,13 @@ class Validator {
 | 
				
			|||||||
            [FAILED_MINIMUM_LENGTH_LONG_SIDE]: i18next.t("failed-minimum-length-long-side", {"minimum_length_long_side": (MINIMUM_LENGTH_LONG_SIDE * 100).toFixed(0)}),
 | 
					            [FAILED_MINIMUM_LENGTH_LONG_SIDE]: i18next.t("failed-minimum-length-long-side", {"minimum_length_long_side": (MINIMUM_LENGTH_LONG_SIDE * 100).toFixed(0)}),
 | 
				
			||||||
            [FAILED_MINIMUM_LENGTH_SHORT_SIDE]: i18next.t("failed-minimum-length-short-side", {"minimum_length_short_side": (MINIMUM_LENGTH_SHORT_SIDE * 100).toFixed(0)}),
 | 
					            [FAILED_MINIMUM_LENGTH_SHORT_SIDE]: i18next.t("failed-minimum-length-short-side", {"minimum_length_short_side": (MINIMUM_LENGTH_SHORT_SIDE * 100).toFixed(0)}),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        this.STATIC_CRITERIA = {
 | 
				
			||||||
 | 
					            [CRITERIA_BASE_AREA]: i18next.t('base-area', {"MINIMUM_BASE_AREA": MINIMUM_BASE_AREA}),
 | 
				
			||||||
 | 
					            [CRITERIA_FALL_HEIGHT]: i18next.t("fall-height", {"maximum_fall_height": (MAXIMUM_FALL_HEIGHT * 100).toFixed(0)}),
 | 
				
			||||||
 | 
					            [CRITERIA_FLOOR_HEIGHT]: i18next.t("floor-height", {"minimum_floor_height": (MINIMUM_FLOOR_HEIGHT * 100).toFixed(0)}),
 | 
				
			||||||
 | 
					            [CRITERIA_MINIMUM_LENGTH_LONG_SIDE]: i18next.t("minimum-length-long-side", {"minimum_length_long_side": (MINIMUM_LENGTH_LONG_SIDE * 100).toFixed(0)}),
 | 
				
			||||||
 | 
					            [CRITERIA_MINIMUM_LENGTH_SHORT_SIDE]: i18next.t("minimum-length-short-side", {"minimum_length_short_side": (MINIMUM_LENGTH_SHORT_SIDE * 100).toFixed(0)}),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    overallAreaNeeded(numOfRats) {
 | 
					    overallAreaNeeded(numOfRats) {
 | 
				
			||||||
@@ -155,8 +169,8 @@ class Validator {
 | 
				
			|||||||
        /*
 | 
					        /*
 | 
				
			||||||
        Calculates the number of rats that are allowed for a certain overall area.
 | 
					        Calculates the number of rats that are allowed for a certain overall area.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        let result = 3.0 + (overallArea-MINIMUM_AREA_THREE_RATS) / AREA_PER_ADDITIONAL_RAT;
 | 
					        let result = 3.0 + (overallArea - MINIMUM_AREA_THREE_RATS) / AREA_PER_ADDITIONAL_RAT;
 | 
				
			||||||
        console.log(`Area left: ${overallArea-MINIMUM_AREA_THREE_RATS}`);
 | 
					        console.log(`Area left: ${overallArea - MINIMUM_AREA_THREE_RATS}`);
 | 
				
			||||||
        console.log(`Result: ${result}`);
 | 
					        console.log(`Result: ${result}`);
 | 
				
			||||||
        if (result < 3) {
 | 
					        if (result < 3) {
 | 
				
			||||||
            throw new Error("Cages must be for three rats or more");
 | 
					            throw new Error("Cages must be for three rats or more");
 | 
				
			||||||
@@ -243,6 +257,10 @@ class Dimensions {
 | 
				
			|||||||
// DOCUMENT INTERACTION //
 | 
					// DOCUMENT INTERACTION //
 | 
				
			||||||
//////////////////////////
 | 
					//////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///////
 | 
				
			||||||
 | 
					// 1 //
 | 
				
			||||||
 | 
					///////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const numRatsCalculatorInputWidth = document.getElementById("num-rats-width");
 | 
					const numRatsCalculatorInputWidth = document.getElementById("num-rats-width");
 | 
				
			||||||
numRatsCalculatorInputWidth.onchange = updateNumRatsCalculator;
 | 
					numRatsCalculatorInputWidth.onchange = updateNumRatsCalculator;
 | 
				
			||||||
const numRatsCalculatorInputDepth = document.getElementById("num-rats-depth");
 | 
					const numRatsCalculatorInputDepth = document.getElementById("num-rats-depth");
 | 
				
			||||||
@@ -255,6 +273,23 @@ numRatsNumFullFloors.oninput = function () {
 | 
				
			|||||||
    updateNumRatsCalculator();
 | 
					    updateNumRatsCalculator();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///////
 | 
				
			||||||
 | 
					// 2 //
 | 
				
			||||||
 | 
					///////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let cageCalcLabelNumRats = document.getElementById("cageCalcLabelNumRats");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let cageCalcRatSlider = document.getElementById("cageCalcNumRats");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cageCalcRatSlider.oninput = function () {
 | 
				
			||||||
 | 
					    updateCageCalc();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					///////
 | 
				
			||||||
 | 
					// 3 //
 | 
				
			||||||
 | 
					///////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const inputWidth = document.getElementById("width");
 | 
					const inputWidth = document.getElementById("width");
 | 
				
			||||||
inputWidth.onchange = updateCageCheck;
 | 
					inputWidth.onchange = updateCageCheck;
 | 
				
			||||||
@@ -295,6 +330,18 @@ function getResultFromChecks(checks) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function formatCriteria(criteria) {
 | 
				
			||||||
 | 
					    const ul = document.createElement('ul');
 | 
				
			||||||
 | 
					    for (const key in criteria) {
 | 
				
			||||||
 | 
					        const li = document.createElement('li');
 | 
				
			||||||
 | 
					        li.textContent = `☑️ ` + criteria[key];
 | 
				
			||||||
 | 
					        ul.appendChild(li);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ul;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function updateCageCheck() {
 | 
					function updateCageCheck() {
 | 
				
			||||||
    labelNumRats.innerHTML = i18next.t("cage-for-x-rats", {"num_rats": ratSlider.value});
 | 
					    labelNumRats.innerHTML = i18next.t("cage-for-x-rats", {"num_rats": ratSlider.value});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -312,6 +359,23 @@ function updateCageCheck() {
 | 
				
			|||||||
    resultsDiv.appendChild(result);
 | 
					    resultsDiv.appendChild(result);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function updateCageCalc() {
 | 
				
			||||||
 | 
					    let numRats = cageCalcRatSlider.value
 | 
				
			||||||
 | 
					    cageCalcLabelNumRats.innerHTML = i18next.t("cage-for-x-rats", {"num_rats": numRats});
 | 
				
			||||||
 | 
					    const validator = new Validator();
 | 
				
			||||||
 | 
					    let criteria = validator.STATIC_CRITERIA;
 | 
				
			||||||
 | 
					    let minimumOverallArea = validator.overallAreaNeeded(cageCalcRatSlider.value);
 | 
				
			||||||
 | 
					    criteria[CRITERIA_OVERALL_AREA] = i18next.t('overall-area', {"numRats": numRats, "minimumOverallArea": minimumOverallArea});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let resultsDiv = document.getElementById("cageCalcResultsDiv");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const result = formatCriteria(criteria);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    resultsDiv.innerHTML = "";
 | 
				
			||||||
 | 
					    resultsDiv.appendChild(result);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function updateNumRatsCalculator() {
 | 
					function updateNumRatsCalculator() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const width = numRatsCalculatorInputWidth.value
 | 
					    const width = numRatsCalculatorInputWidth.value
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,10 @@ body {
 | 
				
			|||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.inline-icon {
 | 
				
			||||||
 | 
					  height: 1.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Import the Google Font
 | 
					// Import the Google Font
 | 
				
			||||||
@import url("https://fonts.googleapis.com/css?family=Nunito:400,700");
 | 
					@import url("https://fonts.googleapis.com/css?family=Nunito:400,700");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user