Added old site
This commit is contained in:
parent
0b0c3f8e36
commit
655d8b0dc8
135
App_old.js
135
App_old.js
|
@ -1,135 +0,0 @@
|
||||||
import React, {useState} from 'react';
|
|
||||||
import {StyleSheet, Text, View, Button, TextInput, Dimensions, StatusBar} from 'react-native';
|
|
||||||
import { LineChart} from 'react-native-chart-kit';
|
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
|
||||||
import PropValueCard from './components/PropValueCard'
|
|
||||||
|
|
||||||
|
|
||||||
export default function App() {
|
|
||||||
const [outputText, setOutputText] = useState('This is the first text');
|
|
||||||
|
|
||||||
const [flag, setFlag] = useState(false);
|
|
||||||
|
|
||||||
const initialState = [];
|
|
||||||
for(let i=0; i < 100; ++i) {
|
|
||||||
initialState.push( Math.random() * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
const [graphData, setGraphData] = useState(initialState);
|
|
||||||
|
|
||||||
const makeNewGraphData = () => {
|
|
||||||
setGraphData( oldGraphData => {
|
|
||||||
console.log("Before", oldGraphData)
|
|
||||||
oldGraphData.pop();
|
|
||||||
oldGraphData.unshift(Math.random() * 100);
|
|
||||||
console.log("After", oldGraphData);
|
|
||||||
return oldGraphData.slice();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
const makeNewGraphData2 = () => {
|
|
||||||
graphData.pop();
|
|
||||||
graphData.unshift(Math.random() * 100);
|
|
||||||
setGraphData(graphData);
|
|
||||||
};
|
|
||||||
|
|
||||||
let tutorial = (
|
|
||||||
<View style={{padding: 50}}>
|
|
||||||
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
|
|
||||||
<TextInput
|
|
||||||
style={{width: '70%', borderColor: 'black', borderWidth: 1, padding: 5}}
|
|
||||||
placeholder="Course goal"
|
|
||||||
/>
|
|
||||||
<Button title="ADD"/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Text style={{fontSize: 50}}>Text1
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
let mine = (
|
|
||||||
<View style={styles.container}>
|
|
||||||
<View style={styles.view1}><Text>View1</Text></View>
|
|
||||||
<View style={styles.view2}><Text>View2</Text></View>
|
|
||||||
<View style={styles.view3}><Text>View3 </Text><TextInput/></View>
|
|
||||||
|
|
||||||
<View>
|
|
||||||
<Text>{flag ? "Text1" : "Text2"}</Text>
|
|
||||||
<Button title="Subba app is dat" onPress={() => setFlag(!flag)}/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
let graph = (
|
|
||||||
<View>
|
|
||||||
<StatusBar hidden={true} />
|
|
||||||
|
|
||||||
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
|
|
||||||
<PropValueCard label="Züge" value="1234"/>
|
|
||||||
<PropValueCard label="Bahnen" value="30"/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View style={{justifyContent: 'center', alignItems: 'center', flexDirection:'row'}}>
|
|
||||||
<LineChart
|
|
||||||
data={{
|
|
||||||
datasets: [{
|
|
||||||
data: graphData
|
|
||||||
}]
|
|
||||||
}}
|
|
||||||
width={Dimensions.get('window').width - 30} // from react-native
|
|
||||||
height={180}
|
|
||||||
chartConfig={{
|
|
||||||
backgroundColor: '#e26a00',
|
|
||||||
backgroundGradientFrom: '#fb8c00',
|
|
||||||
backgroundGradientTo: '#ffa726',
|
|
||||||
decimalPlaces: 0, // optional, defaults to 2dp
|
|
||||||
color: (opacity = 1) => `rgba(255, 255, 255, 0.8)`,
|
|
||||||
style: {
|
|
||||||
borderRadius: 16
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
borderRadius: 16,
|
|
||||||
}}
|
|
||||||
bezier
|
|
||||||
withDots={false}
|
|
||||||
withInnerLines={false}
|
|
||||||
withOuterLines={false}
|
|
||||||
withVerticalLabel={false}
|
|
||||||
withHorizontalLabels={true}
|
|
||||||
fromZero={true}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View>
|
|
||||||
<Button title="UUUND nochmal" onPress={makeNewGraphData}/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
padding: 50,
|
|
||||||
backgroundColor: '#7573ee',
|
|
||||||
//alignItems: 'center',
|
|
||||||
//justifyContent: 'center',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
view1: {
|
|
||||||
backgroundColor: 'green',
|
|
||||||
height: 300
|
|
||||||
},
|
|
||||||
view2: {
|
|
||||||
backgroundColor: 'blue',
|
|
||||||
height: 100,
|
|
||||||
},
|
|
||||||
view3: {
|
|
||||||
backgroundColor: 'white',
|
|
||||||
height: 25
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -0,0 +1,252 @@
|
||||||
|
<!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>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,59 @@
|
||||||
|
import SimpleHTTPServer
|
||||||
|
class CORSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
|
def send_head(self):
|
||||||
|
"""Common code for GET and HEAD commands.
|
||||||
|
This sends the response code and MIME headers.
|
||||||
|
Return value is either a file object (which has to be copied
|
||||||
|
to the outputfile by the caller unless the command was HEAD,
|
||||||
|
and must be closed by the caller under all circumstances), or
|
||||||
|
None, in which case the caller has nothing further to do.
|
||||||
|
"""
|
||||||
|
path = self.translate_path(self.path)
|
||||||
|
f = None
|
||||||
|
if os.path.isdir(path):
|
||||||
|
if not self.path.endswith('/'):
|
||||||
|
# redirect browser - doing basically what apache does
|
||||||
|
self.send_response(301)
|
||||||
|
self.send_header("Location", self.path + "/")
|
||||||
|
self.end_headers()
|
||||||
|
return None
|
||||||
|
for index in "index.html", "index.htm":
|
||||||
|
index = os.path.join(path, index)
|
||||||
|
if os.path.exists(index):
|
||||||
|
path = index
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return self.list_directory(path)
|
||||||
|
ctype = self.guess_type(path)
|
||||||
|
try:
|
||||||
|
# Always read in binary mode. Opening files in text mode may cause
|
||||||
|
# newline translations, making the actual size of the content
|
||||||
|
# transmitted *less* than the content-length!
|
||||||
|
f = open(path, 'rb')
|
||||||
|
except IOError:
|
||||||
|
self.send_error(404, "File not found")
|
||||||
|
return None
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", ctype)
|
||||||
|
fs = os.fstat(f.fileno())
|
||||||
|
self.send_header("Content-Length", str(fs[6]))
|
||||||
|
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
|
||||||
|
self.send_header("Access-Control-Allow-Origin", "*")
|
||||||
|
self.end_headers()
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import os
|
||||||
|
import SocketServer
|
||||||
|
|
||||||
|
PORT = 31339
|
||||||
|
|
||||||
|
Handler = CORSHTTPRequestHandler
|
||||||
|
#Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
|
||||||
|
|
||||||
|
httpd = SocketServer.TCPServer(("", PORT), Handler)
|
||||||
|
|
||||||
|
print "serving at port", PORT
|
||||||
|
httpd.serve_forever()
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# encoding: utf-8
|
||||||
|
"""Use instead of `python3 -m http.server` when you need CORS"""
|
||||||
|
|
||||||
|
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
||||||
|
|
||||||
|
|
||||||
|
class CORSRequestHandler(SimpleHTTPRequestHandler):
|
||||||
|
def end_headers(self):
|
||||||
|
self.send_header('Access-Control-Allow-Origin', '*')
|
||||||
|
self.send_header('Access-Control-Allow-Methods', 'GET')
|
||||||
|
self.send_header('Cache-Control', 'no-store, no-cache, must-revalidate')
|
||||||
|
return super(CORSRequestHandler, self).end_headers()
|
||||||
|
|
||||||
|
|
||||||
|
httpd = HTTPServer(('0.0.0.0', 8003), CORSRequestHandler)
|
||||||
|
print("serving on http://localhost:8003/")
|
||||||
|
httpd.serve_forever()
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"background_color": "blue",
|
||||||
|
"description": "Measures force on pool trainer",
|
||||||
|
"display": "fullscreen",
|
||||||
|
"name": "SwimTrainer",
|
||||||
|
"short_name": "SwimTrainer",
|
||||||
|
"start_url": "/"
|
||||||
|
}
|
Loading…
Reference in New Issue