1
0
mirror of https://github.com/beestat/app.git synced 2025-05-31 04:06:32 -04:00

234 lines
7.2 KiB
JavaScript

/**
* Parent score card.
*/
beestat.component.card.score = function() {
var self = this;
/*
* Debounce so that multiple setting changes don't re-trigger the same
* event. This fires on the trailing edge so that all changes are accounted
* for when rerendering.
*/
var data_change_function = beestat.debounce(function() {
self.rerender();
}, 10);
beestat.dispatcher.addEventListener(
'cache.data.comparison_scores_' + this.type_,
data_change_function
);
beestat.component.card.apply(this, arguments);
this.layer_.register_loader(beestat.home_comparisons.get_comparison_scores);
};
beestat.extend(beestat.component.card.score, beestat.component.card);
/**
* Decorate
*
* @param {rocket.Elements} parent
*/
beestat.component.card.score.prototype.decorate_contents_ = function(parent) {
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
var thermostat_group = beestat.cache.thermostat_group[
thermostat.thermostat_group_id
];
if (
beestat.cache.data['comparison_scores_' + this.type_] === undefined
) {
// Height buffer so the cards don't resize after they load.
parent.appendChild($.createElement('div')
.style('height', '166px')
.innerHTML(' '));
this.show_loading_('Calculating');
} else {
var percentile;
if (
thermostat_group.temperature_profile[this.type_] !== undefined &&
beestat.cache.data['comparison_scores_' + this.type_].length > 2
) {
percentile = this.get_percentile_(
thermostat_group.temperature_profile[this.type_].score,
beestat.cache.data['comparison_scores_' + this.type_]
);
} else {
percentile = null;
}
var color;
if (percentile > 70) {
color = beestat.style.color.green.base;
} else if (percentile > 50) {
color = beestat.style.color.yellow.base;
} else if (percentile > 25) {
color = beestat.style.color.orange.base;
} else if (percentile !== null) {
color = beestat.style.color.red.base;
} else {
color = '#fff';
}
var container = $.createElement('div')
.style({
'text-align': 'center',
'position': 'relative',
'margin-top': beestat.style.size.gutter
});
parent.appendChild(container);
var percentile_text;
var percentile_font_size;
var percentile_color;
if (percentile !== null) {
percentile_text = '';
percentile_font_size = 48;
percentile_color = '#fff';
} else if (
thermostat_group['system_type_' + this.type_] === null ||
thermostat_group['system_type_' + this.type_] === 'none'
) {
percentile_text = 'None';
percentile_font_size = 16;
percentile_color = beestat.style.color.gray.base;
} else {
percentile_text = 'Insufficient data';
percentile_font_size = 16;
percentile_color = beestat.style.color.yellow.base;
}
var percentile_div = $.createElement('div')
.innerText(percentile_text)
.style({
'position': 'absolute',
'top': '50%',
'left': '50%',
'transform': 'translate(-50%, -50%)',
'font-size': percentile_font_size,
'font-weight': beestat.style.font_weight.light,
'color': percentile_color
});
container.appendChild(percentile_div);
var stroke = 3;
var size = 150;
var diameter = size - stroke;
var radius = diameter / 2;
var circumference = Math.PI * diameter;
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('height', size);
svg.setAttribute('width', size);
svg.style.transform = 'rotate(-90deg)';
container.appendChild(svg);
var background = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
background.setAttribute('cx', (size / 2));
background.setAttribute('cy', (size / 2));
background.setAttribute('r', radius);
background.setAttribute('stroke', beestat.style.color.bluegray.dark);
background.setAttribute('stroke-width', stroke);
background.setAttribute('fill', 'none');
svg.appendChild(background);
var stroke_dasharray = circumference;
var stroke_dashoffset_initial = stroke_dasharray;
var stroke_dashoffset_final = stroke_dasharray * (1 - (percentile / 100));
var foreground = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
foreground.style.transition = 'stroke-dashoffset 1s ease';
foreground.setAttribute('cx', (size / 2));
foreground.setAttribute('cy', (size / 2));
foreground.setAttribute('r', radius);
foreground.setAttribute('stroke', color);
foreground.setAttribute('stroke-width', stroke);
foreground.setAttribute('stroke-linecap', 'round');
foreground.setAttribute('stroke-dasharray', stroke_dasharray);
foreground.setAttribute('stroke-dashoffset', stroke_dashoffset_initial);
foreground.setAttribute('fill', 'none');
svg.appendChild(foreground);
/*
* For some reason the render event (which is timeout 0) doesn't work well
* here.
*/
setTimeout(function() {
foreground.setAttribute('stroke-dashoffset', stroke_dashoffset_final);
if (percentile !== null) {
$.step(
function(percentage, sine) {
var calculated_percentile = Math.round(percentile * sine);
percentile_div.innerText(calculated_percentile);
},
1000,
null,
30
);
}
}, 100);
}
};
/**
* Get the percentile rank of a score in a set of scores.
*
* @param {number} score
* @param {array} scores
*
* @return {number} The percentile rank.
*/
beestat.component.card.score.prototype.get_percentile_ = function(score, scores) {
var n = scores.length;
var below = 0;
scores.forEach(function(s) {
if (s < score) {
below++;
}
});
return Math.round(below / n * 100);
};
/**
* Decorate the menu.
*
* @param {rocket.Elements} parent
*/
beestat.component.card.score.prototype.decorate_top_right_ = function(parent) {
var self = this;
var menu = (new beestat.component.menu()).render(parent);
menu.add_menu_item(new beestat.component.menu_item()
.set_text('Help')
.set_icon('help_circle')
.set_callback(function() {
window.open('https://www.notion.so/Comparison-Scores-144d5dafbc6c43f7bc72341120717d8a');
}));
};
/**
* Get subtitle.
*
* @return {string} The subtitle.
*/
beestat.component.card.score.prototype.get_subtitle_ = function() {
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
var thermostat_group = beestat.cache.thermostat_group[
thermostat.thermostat_group_id
];
if (
beestat.cache.data['comparison_scores_' + this.type_] !== undefined &&
beestat.cache.data['comparison_scores_' + this.type_].length > 2 &&
thermostat_group.temperature_profile[this.type_] !== null
) {
return 'Comparing to ' + Number(beestat.cache.data['comparison_scores_' + this.type_].length).toLocaleString() + ' Homes';
}
return 'N/A';
};