Files
tlt-gps-replay/public/index.html

167 lines
6.2 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>tlt-gps-replay</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<style>
#map { height: 900px; }
.leaflet-control-custom { background: white; border: 1px solid #ccc; padding: 5px; }
#controlPanel {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
#fileInfo {
margin-left: 10px;
}
</style>
</head>
<body>
<a href="https://github.com/eetnaviation/tlt-gps-replay"><h1>TLT-GPS-REPLAY</h1></a>
<p>If you want to supply your own files, please download the app from github and run it yourself. Link in title.</p>
<p>This site only stores the last 7 days. If there are less files, it probably hasn't ran for 7 days yet to fill up the slots.</p>
<p id="intervalMessage">Playback speed: PAUSED</p>
<div id="map"></div>
<div id="controlPanel">
<button id="playButton">Play</button>
<label for="speedSlider">Speed:</label>
<p><-- FASTER</p>
<input type="range" id="speedSlider" min="10" max="31" value="31">
<span id="speedDisplay">31ms</span>
<p>--> SLOWER</p>
<div id="fileInfo">
<span id="fileName">No file</span> - <span id="fileTimestamp">N/A</span>
</div>
</div>
<div id="datetimeControl" style="margin-top: 10px;">
<label for="datetimeSlider">Select Date/Time:</label><br>
<input type="range" id="datetimeSlider" min="0" max="0" value="0" style="width: 100%;">
<div><span id="datetimeDisplay">N/A</span></div>
</div>
<p id="statusMessage">No files loaded</p>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script>
const map = L.map('map').setView([59.43041, 24.75924], 13);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors | TLT-GPS-REPLAY made by eetnaviation (VELEND.EU)'
}).addTo(map);
let gpsData = [];
let markers = {};
let currentFileIndex = 0;
let intervalId;
let intervalInt = 31;
const datetimeSlider = document.getElementById('datetimeSlider');
const datetimeDisplay = document.getElementById('datetimeDisplay');
fetch('/gps-files')
.then(response => response.json())
.then(files => {
gpsData = files;
if (gpsData.length > 0) {
datetimeSlider.max = gpsData.length - 1;
datetimeSlider.value = 0;
datetimeDisplay.textContent = gpsData[0].timestamp;
loadGPSData(0);
}
updateProgress();
});
function loadGPSData(index) {
if (index >= gpsData.length) return;
const file = gpsData[index];
document.getElementById('fileName').textContent = file.name;
document.getElementById('fileTimestamp').textContent = file.timestamp;
fetch(`/gps/${file.name}`)
.then(response => response.text())
.then(data => {
const lines = data.split('\n').slice(1);
lines.forEach(line => {
const [type, lineNum, lon, lat, , , tak, , , destination] = line.split(',');
if (lon && lat) {
const icon = type == 2 ? 'bus.png' : (type == 1 ? 'troll.png' : 'tram.png');
if (!markers[tak]) {
markers[tak] = L.marker([lat / 1000000, lon / 1000000], { icon: L.icon({ iconUrl: icon }) })
.bindPopup(`<b>Line:</b> ${lineNum}<br><b>TAK:</b> ${tak}<br><b>Destination:</b> ${destination}`)
.addTo(map);
} else {
markers[tak].setLatLng([lat / 1000000, lon / 1000000]);
}
}
});
updateProgress();
});
}
function updateProgress() {
document.getElementById('statusMessage').textContent = `${currentFileIndex + 1}/${gpsData.length} files done`;
}
document.getElementById('playButton').addEventListener('click', () => {
const playButton = document.getElementById('playButton');
const statusMessage = document.getElementById('statusMessage');
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
playButton.textContent = 'Play';
statusMessage.textContent = '';
intervalMessage.textContent = 'Playback speed: PAUSED';
} else {
intervalMessage.textContent = 'Playback speed: ' + intervalInt + 'ms';
intervalId = setInterval(() => {
loadGPSData(currentFileIndex);
datetimeSlider.value = currentFileIndex;
datetimeDisplay.textContent = gpsData[currentFileIndex]?.timestamp || 'N/A';
currentFileIndex++;
if (currentFileIndex >= gpsData.length) {
clearInterval(intervalId);
intervalId = null;
playButton.textContent = 'Play';
statusMessage.textContent = 'Files ended';
}
}, intervalInt);
playButton.textContent = 'Pause';
}
});
const speedSlider = document.getElementById('speedSlider');
const speedDisplay = document.getElementById('speedDisplay');
speedSlider.addEventListener('input', () => {
intervalInt = parseInt(speedSlider.value);
speedDisplay.textContent = intervalInt + 'ms';
if (intervalId) {
clearInterval(intervalId);
intervalId = setInterval(() => {
loadGPSData(currentFileIndex);
datetimeSlider.value = currentFileIndex;
datetimeDisplay.textContent = gpsData[currentFileIndex]?.timestamp || 'N/A';
currentFileIndex++;
if (currentFileIndex >= gpsData.length) {
clearInterval(intervalId);
intervalId = null;
document.getElementById('playButton').textContent = 'Play';
document.getElementById('statusMessage').textContent = 'Files ended';
}
}, intervalInt);
intervalMessage.textContent = 'Playback speed: ' + intervalInt + 'ms';
}
});
datetimeSlider.addEventListener('input', () => {
const index = parseInt(datetimeSlider.value);
currentFileIndex = index;
datetimeDisplay.textContent = gpsData[index]?.timestamp || 'N/A';
loadGPSData(index);
});
</script>
</body>
</html>