refactor: Move calculator to main js
This commit is contained in:
		@@ -1,85 +0,0 @@
 | 
			
		||||
const MINIMUM_BASE_AREA = 0.5;
 | 
			
		||||
const MINIMUM_AREA_THREE_RATS = 1.5;
 | 
			
		||||
const AREA_PER_ADDITIONAL_RAT = 0.25;
 | 
			
		||||
const MAXIMUM_FALL_HEIGHT = 0.5;
 | 
			
		||||
const MINIMUM_LENGTH_LONG_SIDE = 0.8;
 | 
			
		||||
const MINIMUM_LENGTH_SHORT_SIDE = 0.5;
 | 
			
		||||
const MINIMUM_FLOOR_HEIGHT = 0.3;
 | 
			
		||||
 | 
			
		||||
const FAILED_BASE_AREA = "base_area";
 | 
			
		||||
const FAILED_OVERALL_AREA = "overall_area";
 | 
			
		||||
const FAILED_FALL_HEIGHT = "fall_height";
 | 
			
		||||
const FAILED_NUM_RATS = "num_rats";
 | 
			
		||||
const FAILED_MINIMUM_LENGTH_LONG_SIDE = "length_long_side";
 | 
			
		||||
const FAILED_MINIMUM_LENGTH_SHORT_SIDE= "length_short_side";
 | 
			
		||||
const FAILED_FLOOR_HEIGHT = "floor_height"
 | 
			
		||||
 | 
			
		||||
const FAIL_CRITERIA = {
 | 
			
		||||
    [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_FALL_HEIGHT]: `Die mögliche Fallhöhe darf nicht mehr als ${(MAXIMUM_FALL_HEIGHT * 100).toFixed(0)}cm betragen.`,
 | 
			
		||||
    [FAILED_FLOOR_HEIGHT]: `Der Mindestabstand zwischen Ebenen muss ${(MINIMUM_FLOOR_HEIGHT * 100).toFixed(0)}cm betragen.`,
 | 
			
		||||
    [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 * 100).toFixed(0)}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 * 100).toFixed(0)}cm lang sein.`,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Dimensions {
 | 
			
		||||
    constructor(width, depth, height) {
 | 
			
		||||
        this.width = width;
 | 
			
		||||
        this.depth = depth;
 | 
			
		||||
        this.height = height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toString() {
 | 
			
		||||
        return `${this.width}x${this.depth}x${this.height}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static fromDict(data) {
 | 
			
		||||
        const { width, depth,  height } = data;
 | 
			
		||||
        return new Dimensions(width, depth, height);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function overallAreaNeeded(numOfRats) {
 | 
			
		||||
    if (numOfRats < 3 || numOfRats > 15) {
 | 
			
		||||
        throw new Error("This formula works only from 3 to 15 rats");
 | 
			
		||||
    }
 | 
			
		||||
    return MINIMUM_AREA_THREE_RATS + (numOfRats - 3) * AREA_PER_ADDITIONAL_RAT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function cageCheck(dimensions, numRats, numFullFloors) {
 | 
			
		||||
    let failedCriteria = {};
 | 
			
		||||
 | 
			
		||||
    if (numRats < 2 || numRats > 15) {
 | 
			
		||||
        failedCriteria[FAILED_NUM_RATS] = FAIL_CRITERIA[FAILED_NUM_RATS];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const baseArea = dimensions.depth * dimensions.width;
 | 
			
		||||
    if (baseArea < MINIMUM_BASE_AREA) {
 | 
			
		||||
        failedCriteria[FAILED_BASE_AREA] = FAIL_CRITERIA[FAILED_BASE_AREA];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const areaNeeded = overallAreaNeeded(numRats);
 | 
			
		||||
    if (baseArea * numFullFloors < areaNeeded) {
 | 
			
		||||
        failedCriteria[FAILED_OVERALL_AREA] = FAIL_CRITERIA[FAILED_OVERALL_AREA];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.height / numFullFloors > MAXIMUM_FALL_HEIGHT) {
 | 
			
		||||
        failedCriteria[FAILED_FALL_HEIGHT] = FAIL_CRITERIA[FAILED_FALL_HEIGHT];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.width < MINIMUM_LENGTH_LONG_SIDE && dimensions.depth < MINIMUM_LENGTH_LONG_SIDE) {
 | 
			
		||||
        failedCriteria[FAILED_MINIMUM_LENGTH_LONG_SIDE] = FAIL_CRITERIA[FAILED_MINIMUM_LENGTH_LONG_SIDE];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.width < MINIMUM_LENGTH_SHORT_SIDE || dimensions.depth < MINIMUM_LENGTH_SHORT_SIDE) {
 | 
			
		||||
        failedCriteria[FAILED_MINIMUM_LENGTH_SHORT_SIDE] = FAIL_CRITERIA[FAILED_MINIMUM_LENGTH_SHORT_SIDE];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.height / numFullFloors < MINIMUM_FLOOR_HEIGHT) {
 | 
			
		||||
        failedCriteria[FAILED_FLOOR_HEIGHT] = FAIL_CRITERIA[FAILED_FLOOR_HEIGHT];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return failedCriteria;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										203
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								src/index.js
									
									
									
									
									
								
							@@ -1,3 +1,153 @@
 | 
			
		||||
import i18next from "i18next";
 | 
			
		||||
import LanguageDetector from "i18next-browser-languagedetector";
 | 
			
		||||
import HttpApi from "i18next-http-backend";
 | 
			
		||||
 | 
			
		||||
/////////////////
 | 
			
		||||
// TRANSLATION //
 | 
			
		||||
/////////////////
 | 
			
		||||
 | 
			
		||||
async function initI18next() {
 | 
			
		||||
    // We use() the backend and await it to load
 | 
			
		||||
    // the translations from the network
 | 
			
		||||
    await i18next
 | 
			
		||||
        .use(HttpApi)
 | 
			
		||||
        .use(LanguageDetector)
 | 
			
		||||
        .init({
 | 
			
		||||
            lng: "en",
 | 
			
		||||
            supportedLngs: ["en", "de"],
 | 
			
		||||
            nonExplicitSupportedLngs: true,
 | 
			
		||||
            fallbackLng: "en",
 | 
			
		||||
            debug: true,
 | 
			
		||||
            backend: {
 | 
			
		||||
                loadPath: "/lang/{{lng}}.json",
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function translatePageElements() {
 | 
			
		||||
    const translatableElements = document.querySelectorAll(
 | 
			
		||||
        "[data-i18n-key]",
 | 
			
		||||
    );
 | 
			
		||||
    translatableElements.forEach((el) => {
 | 
			
		||||
        const key = el.getAttribute("data-i18n-key");
 | 
			
		||||
        el.innerHTML = i18next.t(key);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// ...
 | 
			
		||||
 | 
			
		||||
function bindLocaleSwitcher(initialValue) {
 | 
			
		||||
    const switcher = document.querySelector(
 | 
			
		||||
        "[data-i18n-switcher]",
 | 
			
		||||
    );
 | 
			
		||||
    switcher.value = initialValue;
 | 
			
		||||
    switcher.onchange = (e) => {
 | 
			
		||||
        i18next
 | 
			
		||||
            .changeLanguage(e.target.value)
 | 
			
		||||
            .then(translatePageElements);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(async function () {
 | 
			
		||||
    await initI18next();
 | 
			
		||||
    translatePageElements();
 | 
			
		||||
    bindLocaleSwitcher(i18next.resolvedLanguage);
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
////////////////
 | 
			
		||||
// CALCULATOR //
 | 
			
		||||
////////////////
 | 
			
		||||
 | 
			
		||||
const MINIMUM_BASE_AREA = 0.5;
 | 
			
		||||
const MINIMUM_AREA_THREE_RATS = 1.5;
 | 
			
		||||
const AREA_PER_ADDITIONAL_RAT = 0.25;
 | 
			
		||||
const MAXIMUM_FALL_HEIGHT = 0.5;
 | 
			
		||||
const MINIMUM_LENGTH_LONG_SIDE = 0.8;
 | 
			
		||||
const MINIMUM_LENGTH_SHORT_SIDE = 0.5;
 | 
			
		||||
const MINIMUM_FLOOR_HEIGHT = 0.3;
 | 
			
		||||
 | 
			
		||||
const FAILED_BASE_AREA = "base_area";
 | 
			
		||||
const FAILED_OVERALL_AREA = "overall_area";
 | 
			
		||||
const FAILED_FALL_HEIGHT = "fall_height";
 | 
			
		||||
const FAILED_NUM_RATS = "num_rats";
 | 
			
		||||
const FAILED_MINIMUM_LENGTH_LONG_SIDE = "length_long_side";
 | 
			
		||||
const FAILED_MINIMUM_LENGTH_SHORT_SIDE= "length_short_side";
 | 
			
		||||
const FAILED_FLOOR_HEIGHT = "floor_height"
 | 
			
		||||
 | 
			
		||||
const FAIL_CRITERIA = {
 | 
			
		||||
    [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_FALL_HEIGHT]: `Die mögliche Fallhöhe darf nicht mehr als ${(MAXIMUM_FALL_HEIGHT * 100).toFixed(0)}cm betragen.`,
 | 
			
		||||
    [FAILED_FLOOR_HEIGHT]: `Der Mindestabstand zwischen Ebenen muss ${(MINIMUM_FLOOR_HEIGHT * 100).toFixed(0)}cm betragen.`,
 | 
			
		||||
    [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 * 100).toFixed(0)}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 * 100).toFixed(0)}cm lang sein.`,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Dimensions {
 | 
			
		||||
    constructor(width, depth, height) {
 | 
			
		||||
        this.width = width;
 | 
			
		||||
        this.depth = depth;
 | 
			
		||||
        this.height = height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toString() {
 | 
			
		||||
        return `${this.width}x${this.depth}x${this.height}`;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static fromDict(data) {
 | 
			
		||||
        const { width, depth,  height } = data;
 | 
			
		||||
        return new Dimensions(width, depth, height);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function overallAreaNeeded(numOfRats) {
 | 
			
		||||
    if (numOfRats < 3 || numOfRats > 15) {
 | 
			
		||||
        throw new Error("This formula works only from 3 to 15 rats");
 | 
			
		||||
    }
 | 
			
		||||
    return MINIMUM_AREA_THREE_RATS + (numOfRats - 3) * AREA_PER_ADDITIONAL_RAT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function cageCheck(dimensions, numRats, numFullFloors) {
 | 
			
		||||
    let failedCriteria = {};
 | 
			
		||||
 | 
			
		||||
    if (numRats < 2 || numRats > 15) {
 | 
			
		||||
        failedCriteria[FAILED_NUM_RATS] = FAIL_CRITERIA[FAILED_NUM_RATS];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const baseArea = dimensions.depth * dimensions.width;
 | 
			
		||||
    if (baseArea < MINIMUM_BASE_AREA) {
 | 
			
		||||
        failedCriteria[FAILED_BASE_AREA] = FAIL_CRITERIA[FAILED_BASE_AREA];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const areaNeeded = overallAreaNeeded(numRats);
 | 
			
		||||
    if (baseArea * numFullFloors < areaNeeded) {
 | 
			
		||||
        failedCriteria[FAILED_OVERALL_AREA] = FAIL_CRITERIA[FAILED_OVERALL_AREA];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.height / numFullFloors > MAXIMUM_FALL_HEIGHT) {
 | 
			
		||||
        failedCriteria[FAILED_FALL_HEIGHT] = FAIL_CRITERIA[FAILED_FALL_HEIGHT];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.width < MINIMUM_LENGTH_LONG_SIDE && dimensions.depth < MINIMUM_LENGTH_LONG_SIDE) {
 | 
			
		||||
        failedCriteria[FAILED_MINIMUM_LENGTH_LONG_SIDE] = FAIL_CRITERIA[FAILED_MINIMUM_LENGTH_LONG_SIDE];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.width < MINIMUM_LENGTH_SHORT_SIDE || dimensions.depth < MINIMUM_LENGTH_SHORT_SIDE) {
 | 
			
		||||
        failedCriteria[FAILED_MINIMUM_LENGTH_SHORT_SIDE] = FAIL_CRITERIA[FAILED_MINIMUM_LENGTH_SHORT_SIDE];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (dimensions.height / numFullFloors < MINIMUM_FLOOR_HEIGHT) {
 | 
			
		||||
        failedCriteria[FAILED_FLOOR_HEIGHT] = FAIL_CRITERIA[FAILED_FLOOR_HEIGHT];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return failedCriteria;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//////////////////////////
 | 
			
		||||
// DOCUMENT INTERACTION //
 | 
			
		||||
//////////////////////////
 | 
			
		||||
 | 
			
		||||
const inputDecreaseFloorNum = document.getElementById("decreaseFloorNum");
 | 
			
		||||
inputDecreaseFloorNum.onclick = decreaseFloorNum;
 | 
			
		||||
 | 
			
		||||
@@ -141,56 +291,3 @@ function increaseFloorNum() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
update();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import i18next from "i18next";
 | 
			
		||||
import LanguageDetector from "i18next-browser-languagedetector";
 | 
			
		||||
import HttpApi from "i18next-http-backend";
 | 
			
		||||
 | 
			
		||||
async function initI18next() {
 | 
			
		||||
    // We use() the backend and await it to load
 | 
			
		||||
    // the translations from the network
 | 
			
		||||
    await i18next
 | 
			
		||||
        .use(HttpApi)
 | 
			
		||||
        .use(LanguageDetector)
 | 
			
		||||
        .init({
 | 
			
		||||
            lng: "en",
 | 
			
		||||
            supportedLngs: ["en", "de"],
 | 
			
		||||
            nonExplicitSupportedLngs: true,
 | 
			
		||||
            fallbackLng: "en",
 | 
			
		||||
            debug: true,
 | 
			
		||||
            backend: {
 | 
			
		||||
                loadPath: "/lang/{{lng}}.json",
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function translatePageElements() {
 | 
			
		||||
    const translatableElements = document.querySelectorAll(
 | 
			
		||||
        "[data-i18n-key]",
 | 
			
		||||
    );
 | 
			
		||||
    translatableElements.forEach((el) => {
 | 
			
		||||
        const key = el.getAttribute("data-i18n-key");
 | 
			
		||||
        el.innerHTML = i18next.t(key);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// ...
 | 
			
		||||
 | 
			
		||||
function bindLocaleSwitcher(initialValue) {
 | 
			
		||||
    const switcher = document.querySelector(
 | 
			
		||||
        "[data-i18n-switcher]",
 | 
			
		||||
    );
 | 
			
		||||
    switcher.value = initialValue;
 | 
			
		||||
    switcher.onchange = (e) => {
 | 
			
		||||
        i18next
 | 
			
		||||
            .changeLanguage(e.target.value)
 | 
			
		||||
            .then(translatePageElements);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
(async function () {
 | 
			
		||||
    await initI18next();
 | 
			
		||||
    translatePageElements();
 | 
			
		||||
    bindLocaleSwitcher(i18next.resolvedLanguage);
 | 
			
		||||
})();
 | 
			
		||||
		Reference in New Issue
	
	Block a user