feat: add basic telemetry
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
moanos [he/him] 2025-04-16 23:34:54 +02:00
parent 9cde2502e2
commit 560f578b26
5 changed files with 88 additions and 12 deletions

10
package-lock.json generated
View File

@ -10,6 +10,7 @@
"license": "AGPL-3.0-or-later",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"@telemetrydeck/sdk": "^2.0.4",
"bulma": "^1.0.3",
"i18next": "^23.12.2",
"i18next-browser-languagedetector": "^8.0.0",
@ -934,6 +935,15 @@
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@telemetrydeck/sdk": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@telemetrydeck/sdk/-/sdk-2.0.4.tgz",
"integrity": "sha512-x4S83AqSo6wvLJ6nRYdyJEqd9qmblUdBgsTRrjH5z++b9pnf2NMc8NpVAa48KIB1pRuP/GTGzXxVYdNoie/DVg==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",

View File

@ -31,11 +31,12 @@
"webpack-dev-server": "^5.0.4"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"@telemetrydeck/sdk": "^2.0.4",
"bulma": "^1.0.3",
"i18next": "^23.12.2",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.5.2",
"sass-migrator": "^2.3.1",
"@fortawesome/fontawesome-free": "^6.7.2"
"sass-migrator": "^2.3.1"
}
}

View File

@ -1,7 +1,12 @@
import {td} from './telemetry';
document.addEventListener('DOMContentLoaded', () => {
// Functions to open and close a modal
function openModal($el) {
$el.classList.add('is-active');
td.signal("Modal.open", {
modal: $el.id
});
}
function closeModal($el) {

View File

@ -7,6 +7,7 @@ import '@fortawesome/fontawesome-free/js/regular';
import '@fortawesome/fontawesome-free/js/brands';
import './feedback.js';
import './main.scss';
import {td} from './telemetry';
/////////////////
// TRANSLATION //
@ -349,13 +350,26 @@ function updateCageCheck() {
const height = inputHeight.value
const dimensions = new Dimensions(width / 100, depth / 100, height / 100);
const validator = new Validator();
const failed_checks = validator.cageCheck(dimensions, ratSlider.value, fullFloorNum.value);
const numRats = ratSlider.value;
const numFullFloors = fullFloorNum.value;
const failed_checks = validator.cageCheck(dimensions, numRats,);
let resultsDiv = document.getElementById("resultsDiv");
const result = getResultFromChecks(failed_checks);
resultsDiv.innerHTML = "";
resultsDiv.appendChild(result);
// Send telemetry
td.signal("Update.CageCheck", {
width: width,
depth: depth,
height: height,
numRats: numRats,
numFullFloors: numFullFloors
});
}
function updateCageCalc() {
@ -363,8 +377,11 @@ function updateCageCalc() {
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 minimumOverallArea = validator.overallAreaNeeded(numRats);
criteria[CRITERIA_OVERALL_AREA] = i18next.t('overall-area', {
"numRats": numRats,
"minimumOverallArea": minimumOverallArea
});
let resultsDiv = document.getElementById("cageCalcResultsDiv");
@ -373,18 +390,25 @@ function updateCageCalc() {
resultsDiv.innerHTML = "";
resultsDiv.appendChild(result);
// Send telemetry
td.signal("Update.CageCalc", {
numRats: numRats,
});
}
function updateNumRatsCalculator() {
const width = numRatsCalculatorInputWidth.value
const depth = numRatsCalculatorInputDepth.value
const height = numRatsCalculatorInputHeight.value
const width = numRatsCalculatorInputWidth.value;
const depth = numRatsCalculatorInputDepth.value;
const height = numRatsCalculatorInputHeight.value;
const numFullFloors = numRatsNumFullFloors.value;
const dimensions = new Dimensions(width / 100, depth / 100, height / 100);
const validator = new Validator();
const failed_checks = validator.failCageNumberIndependent(dimensions, fullFloorNum.value);
const failed_checks = validator.failCageNumberIndependent(dimensions, numFullFloors);
let overallArea = validator.getOverallArea(dimensions, numRatsNumFullFloors.value);
let overallArea = validator.getOverallArea(dimensions, );
let allowedNumRats;
try {
allowedNumRats = validator.allowedNumberOfRats(overallArea);
@ -404,6 +428,14 @@ function updateNumRatsCalculator() {
p.textContent = i18next.t("cage-for-x-rats", {"num_rats": allowedNumRats});
resultsDiv.appendChild(p);
resultsDiv.appendChild(result);
}
const validator = new Validator();
// Send telemetry
td.signal("Update.NumRatsCalc", {
width: width,
depth: depth,
height: height,
numFullFloors: numFullFloors
});
}

28
src/telemetry.js Normal file
View File

@ -0,0 +1,28 @@
import TelemetryDeck from '@telemetrydeck/sdk';
///////////////
// TELEMETRY //
///////////////
// Telemetry Deck only collects fully anonymized data!
function getOrCreateUUID() {
let cookie = document.cookie.split(";").some((item) => item.trim().startsWith("id="));
if (
cookie
) {
return cookie.split("=")[1];
} else {
let uuid =crypto.randomUUID();
const days = 365;
const expires = new Date(Date.now() + days * 864e5).toUTCString();
document.cookie = `id=${uuid}; expires=${expires}`;
return uuid;
}
}
export const td = new TelemetryDeck({
appID: '4A88C6F5-2BDE-489E-9834-34D89FD5473F',
clientUser: getOrCreateUUID()
});