swimtracker-app/old-site/main.html

253 lines
8.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SwimTrainer</title>
<!-- plot.ly -->
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<!-- chart.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
<!-- Materialize -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<!-- MsgPack -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/msgpack5/4.2.0/msgpack5.js"></script>
<link rel="manifest" href="swimtrainer.webmanifest">
</head>
<body>
<nav class="blue " role="navigation">
<div class="nav-wrapper container"><a id="logo-container" href="#" class="brand-logo">SwimTrainer</a>
</div>
</nav>
<div class="container">
<div class="row">
<div class="row">
<div class="col s4 center-align">
<h5>Bahnen</h5>
<h1><span id="lanes"></span></h1>
</div>
<div class="col s4 center-align">
<h5>Züge</h5>
<h1><span id="peaks"></span></h1>
</div>
<div class="col s4 center-align">
<a class="waves-effect waves-light btn-large" onclick="reload()">Neu laden</a>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<canvas id="plotCanvas"></canvas>
</div>
</div>
<div class="row">
<div class="col s3">
</div>
<div class="col s6">
<div class="container">
<div class="row">
<div class="col s6"><label>Seconds</label></div>
<div class="col s6"> <input type="number" id="seconds" min="30" max="3600" value="120"> </div>
</div>
<div class="row">
<div class="col s6"><label>Threshold</label></div>
<div class="col s6"> <input type="number" id="threshold" min="100" max="60000" value="2000"> </div>
</div>
<div class="row">
<div class="col s6"><label>y max</label></div>
<div class="col s6"> <input type="number" id="ymax" min="1000" max="60000" value="4000"> </div>
</div>
<div class="row">
<div class="btn red white-text waves-effect waves-light" id="clickMe" type="button" onclick="save();">
<i class="material-icons left">save</i>
Speichern
</div>
</div>
</div>
</div>
</div>
</div>
<script>
const url = 'http://smartswim/api/session/data';
// ------------------ MsgPack --------------------------------------------------------------
var msgpack = msgpack5();
msgpack.registerDecoder(0xd1, function (byteArr) {
function typedArrayToBuffer(array) {
return array.buffer.slice(array.byteOffset, array.byteLength + array.byteOffset)
}
return new Int16Array(typedArrayToBuffer(byteArr));
});
function countPeaks(array, threshold=500)
{
var result = 0;
var lastMin = 0;
for(var i = 1; i < array.length - 2; i++)
{
var current = array[i].y;
var last = array[i-1].y;
var next = array[i+1].y;
if(current > next && current > last && (current - lastMin) > threshold) {
result += 1;
lastMin = array[i].y;
}
lastMin = Math.min(lastMin, array[i].y);
}
return result;
}
// ------------------ Plot data -------------------------------------------------------------
var ctx = document.getElementById('plotCanvas').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: [],
backgroundColor: '#2196f388',
color: 'blue'
}]
},
options: {color: ['red']}
});
var appendToPlotArray = function (typedTimeArr, typedValueArr, currentTime) {
var plotArray = chart.data.datasets[0].data;
// remove last element, pop on empty is ok
plotArray.pop();
for (var i = 0; i < typedValueArr.length; ++i) {
plotArray.push({x: typedTimeArr[i], y: typedValueArr[i]});
}
plotArray.push({x: currentTime, y: plotArray[plotArray.length - 1].y});
var secondsToShow = parseInt( document.getElementById("seconds").value );
var yMax = parseInt( document.getElementById("ymax").value );
chart.options = {
legend: {
display: false
},
elements: {
point: {
radius: 2
},
line: {
tension: 0 // disables bezier curves
}
},
scales: {
xAxes: [{
ticks: {
min: plotArray[plotArray.length - 1].x - secondsToShow * 10,
max: plotArray[plotArray.length - 1].x
},
type: 'linear',
display: false
}],
yAxes: [{
ticks: {
min: 0,
max: yMax
},
type: 'linear'
}],
}
};
chart.data.datasets[0].data = plotArray;
chart.update();
};
var reload = function() {
chart.data.datasets[0].data = [];
};
/*
var appendToPlot = function (typedTimeArr, typedValueArr, currentTime)
{
return;
// remove last element, pop on empty is ok
plotData.x.pop();
plotData.y.pop();
var timeArr = Array.prototype.slice.call(typedTimeArr);
var valueArr = Array.prototype.slice.call(typedValueArr);
plotData.x = plotData.x.concat(timeArr);
plotData.y = plotData.y.concat(valueArr);
// add last element
plotData.x.push(currentTime);
plotData.y.push(plotData.y[plotData.y.length - 1]);
var plotObj = document.getElementById('plot');
Plotly.purge(plotObj);
Plotly.plot(plotObj, [plotData]);
};*/
var updateRunning = false;
var update = function ()
{
if( updateRunning === true ) {
//console.log("Skipping update, because update is running");
return;
}
var oReq = new XMLHttpRequest();
var startIndex = chart.data.datasets[0].data.length;
if (startIndex > 0) {
startIndex -= 1;
}
oReq.open("GET", url + "?startIndex=" + startIndex, true);
oReq.responseType = "arraybuffer";
//console.log("-> Query, startIndex=", startIndex);
oReq.onload = function (oEvent) {
var arrayBuffer = oReq.response; // Note: not oReq.responseText
if (arrayBuffer) {
var decoded = msgpack.decode(arrayBuffer);
//console.log("-> Finished query", startIndex, "#old:", chart.data.datasets[0].data.length,
// "#new:", decoded['values'].length);
appendToPlotArray(decoded['timestamps'], decoded['values'], decoded['currentTime']);
//console.log("-> After unpack", chart.data.datasets[0].data.length);
var peakThreshold = parseInt( document.getElementById("threshold").value );
var peaks = countPeaks(chart.data.datasets[0].data, peakThreshold);
document.getElementById("peaks").textContent = peaks;
document.getElementById("lanes").textContent = (peaks / 30).toFixed(1);
}
updateRunning = false;
};
oReq.send(null);
updateRunning = true;
};
update();
setInterval(update, 1000);
</script>
</body>
</html>