commit 69625650b100421fb66e0c53ea8dcf69e6d001a7
parent 77ad500002b44170b556dfac2d28afbfb38e7e33
Author: Dominik Schmidt <das1993@hotmail.com>
Date: Thu, 28 Jun 2018 23:58:01 +0000
Implement guess of time left until washing machine finished in web-interface
Diffstat:
www/index.cgi | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 78 insertions(+), 0 deletions(-)
diff --git a/www/index.cgi b/www/index.cgi
@@ -20,6 +20,9 @@ Content-Type: text/html
text-align:center;
font-size:x-large;
}
+ #status.off guessTime{
+ display:none;
+ }
#power{
font-size:xx-large;
}
@@ -43,6 +46,7 @@ Content-Type: text/html
<div id="status">
<div id="power"><img src="off.svg" /></div>
<div id="delta_t"></div>
+ <div id="guessTime"></div>
</div>
<div id="footer">
<a href="details.html">Details</a>
@@ -51,9 +55,11 @@ Content-Type: text/html
<!--
delta_t=${RTIME};
function updateDisplay(){
+ var g=document.getElementById("guessTime");
var dt=document.getElementById("delta_t");
var st=document.getElementById("status");
var txt="";
+ var txt2="";
var classn="";
if(delta_t < 0){
txt="since "+timeSince(-delta_t);
@@ -61,14 +67,86 @@ Content-Type: text/html
}
else{
txt="since "+timeSince(delta_t);
+ txt2="The crystal ball guesses: "+timeSince(Math.round(guessTimeLeft(delta_t)))+" left"
classn="on";
}
dt.textContent=txt;
+ g.textContent=txt2;
st.setAttribute("class",classn);
st.getElementsByTagName("img")[0].setAttribute("src",classn+".svg");
}
setInterval(function(){ if(delta_t>=0){delta_t++}else{delta_t--}; updateDisplay();}, 1000);
setInterval(function(){ readTextFile("print_delta_t.cgi", function(rawFile){delta_t = rawFile.responseText});}, 5*1000);
+ readTextFile("clusters", function(rawFile){parseClusters(rawFile.responseText);});
+ clusters=[];
+ function Cluster(apriori, mean, variance){
+ this.apriori=apriori;
+ this.mean=mean;
+ this.variance=variance;
+ }
+ function parseClusters(txt){
+ var lines=txt.split("\n");
+ clusters=[];
+ var sum=0;
+ for(var i=0; i<lines.length; i++){
+ var line=lines[i];
+ if(line.length==0) continue;
+ var spl=line.split("\t");
+ clusters.push(new Cluster(parseInt(spl[0]),parseFloat(spl[1]),parseFloat(spl[2])));
+ sum+=parseInt(spl[0]);
+ }
+ for(var i=0; i<clusters.length; i++){
+ clusters[i].apriori/=sum;
+ }
+ }
+
+ function guessTimeLeft(elapsed){
+ return guessTime(elapsed)-elapsed;
+ }
+
+ function guessTime(elapsed){
+ var expect=0;
+ var obsprior=observationPrior(elapsed);
+ for(var i=0; i<clusters.length; i++){
+ cluster=clusters[i];
+ var prior=(1-cluster.cdf(elapsed))*cluster.apriori/obsprior;
+ expect+=prior*Math.max(cluster.mean,elapsed);
+ }
+ return expect;
+ }
+
+ function observationPrior(elapsed){
+ var prior=0;
+ for(var i=0; i<clusters.length; i++){
+ cluster=clusters[i];
+ prior+=(1-cluster.cdf(elapsed))*cluster.apriori
+ }
+ return prior;
+ }
+
+ Cluster.prototype.cdf=function(to) {
+ variance=this.variance;
+ mean=this.mean;
+ var z = (to-mean)/Math.sqrt(2*variance);
+ var t = 1/(1+0.3275911*Math.abs(z));
+ var a1 = 0.254829592;
+ var a2 = -0.284496736;
+ var a3 = 1.421413741;
+ var a4 = -1.453152027;
+ var a5 = 1.061405429;
+ var erf = 1-(((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*Math.exp(-z*z);
+ var sign = 1;
+ if(z < 0){
+ sign = -1;
+ }
+ return (1/2)*(1+sign*erf);
+ }
+
+ Cluster.prototype.pdf=function(to){
+ mean=this.mean;
+ variance=this.variance;
+ return 1/(Math.sqrt(2*pi*variance))*Math.exp(-((to-mean)^2/(4*variance)));
+ }
function readTextFile(file, func){
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, true);