Untitled

 avatar
unknown
plain_text
10 months ago
11 kB
4
Indexable
import React, { useState, useEffect } from 'react';

function GeolocationTracker() {
    const [isCollecting, setIsCollecting] = useState(true);
    const [startTime, setStartTime] = useState(null);
    const [lastTime, setLastTime] = useState(null);
    const [distance, setDistance] = useState(0);
    const [startPosition, setStartPosition] = useState(null);
    const [lastPosition, setLastPosition] = useState(null);
    const [speed, setSpeed] = useState(0);
    const [accelerationY, setAccelerationY] = useState(0);
    const [accuracy, setAccuracy] = useState(null);
    const [isDriving, setIsDriving] = useState(false);
    const [currentTime, setCurrentTime] = useState(0);
    const [speedProfile, setSpeedProfile] = useState([]);

    useEffect(() => {
        if (!isCollecting) return;

        const watchId = navigator.geolocation.watchPosition(
            function(position) {
                const currentTime = new Date().getTime();
                if (!startTime) {
                    setStartTime(currentTime);
                    setLastTime(currentTime);
                    setStartPosition({ latitude: position.coords.latitude, longitude: position.coords.longitude });
                    setLastPosition({ latitude: position.coords.latitude, longitude: position.coords.longitude });
                } else {
                    const deltaTime = (currentTime - lastTime) / 1000; // in seconds
                    const currentDistance = calculateDistance(lastPosition.latitude, lastPosition.longitude, position.coords.latitude, position.coords.longitude);
                    setDistance(distance + currentDistance);
                    const currentSpeed = currentDistance / deltaTime;
                    setSpeed(currentSpeed);
                    setLastTime(currentTime);
                    setLastPosition({ latitude: position.coords.latitude, longitude: position.coords.longitude });

                    // Add data to speed profile
                    setSpeedProfile(prevProfile => [...prevProfile, { time: currentTime, speed: currentSpeed, distance: distance }]);
                }
                setAccuracy(position.coords.accuracy);
                setIsDriving(position.coords.speed > 0.1); // Assuming speed > 0.1 m/s indicates driving
            },
            function(error) {
                console.error('Error getting geolocation:', error);
            },
            {
                maximumAge: 0,
                enableHighAccuracy: true
            }
        );

        const handleMotionEvent = (event) => {
            setAccelerationY(event.accelerationIncludingGravity.y);
        };

        window.addEventListener('devicemotion', handleMotionEvent);

        const intervalId = setInterval(() => {
            setCurrentTime((new Date().getTime() - startTime) / 1000);
        }, 1000);

        return () => {
            clearInterval(intervalId);
            navigator.geolocation.clearWatch(watchId);
            window.removeEventListener('devicemotion', handleMotionEvent);
        };
    }, [isCollecting, startTime, lastTime, distance, lastPosition]);

    const calculateDistance = (lat1, lon1, lat2, lon2) => {
        const R = 6371e3; // metres
        const φ1 = (lat1 * Math.PI) / 180; // φ, λ in radians
        const φ2 = (lat2 * Math.PI) / 180;
        const Δφ = ((lat2 - lat1) * Math.PI) / 180;
        const Δλ = ((lon2 - lon1) * Math.PI) / 180;

        const a =
            Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
            Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
        const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return R * c; // in meters
    };

    const clearData = () => {
        setIsCollecting(false);
        setStartTime(null);
        setLastTime(null);
        setDistance(0);
        setStartPosition(null);
        setLastPosition(null);
        setSpeed(0);
        setAccelerationY(0);
        setAccuracy(null);
        setIsDriving(false);
        setCurrentTime(0);
        setSpeedProfile([]);
    };

    const restartCollecting = () => {
        setIsCollecting(true);
        setStartTime(null);
        setLastTime(null);
        setDistance(0);
        setStartPosition(null);
        setLastPosition(null);
        setSpeed(0);
        setAccelerationY(0);
        setAccuracy(null);
        setIsDriving(false);
        setCurrentTime(0);
        setSpeedProfile([]);
    };

    return (
        <div style={styles.overlay}>
            <div className="container" style={styles.container}>
                <h2 style={{color:'white'}}>Speed Coach</h2>
                <table style={styles.table}>
                    <tbody>
                    <tr style={styles.row}>
                        <td style={styles.label}>State:</td>
                        <td style={styles.data}>{isDriving ? 'Driving' : 'Standing'}</td>
                    </tr>
                    <tr style={styles.row}>
                        <td style={styles.label}>GPS Speed:</td>
                        <td style={styles.data}>{speed.toFixed(2)} m/s</td>
                    </tr>
                    <tr style={styles.row}>
                        <td style={styles.label}>Y Acceleration:</td>
                        <td style={styles.data}>{accelerationY.toFixed(2)}</td>
                    </tr>
                    {/*<tr style={styles.row}>*/}
                    {/*    <td style={styles.label}>GPS Position:</td>*/}
                    {/*    <td style={styles.data}>*/}
                    {/*        {`lat: ${lastPosition?.latitude?.toFixed(6) || 'N/A'}, lng: ${lastPosition?.longitude?.toFixed(6) || 'N/A'}`}*/}
                    {/*    </td>*/}
                    {/*</tr>*/}
                    <tr style={styles.row}>
                        <td style={styles.label}>GPS Accuracy:</td>
                        <td style={styles.data}>{accuracy ? `${accuracy} meters` : 'N/A'}</td>
                    </tr>
                    <tr style={styles.row}>
                        <td style={styles.label}>Distance from start:</td>
                        <td style={styles.data}>{distance.toFixed(2)} meters</td>
                    </tr>
                    </tbody>
                </table>
                {/*<div style={styles.listViewContainer}>*/}
                {/*    <div style={styles.listView}>*/}
                {/*        <div style={styles.listViewItem}>*/}
                {/*            <p>Speed Profile Seconds</p>*/}
                {/*            {speedProfile.map((entry, index) => (*/}
                {/*                <p key={index}>{entry.time.toFixed(2)}</p>*/}
                {/*            ))}*/}
                {/*        </div>*/}
                {/*        <div style={styles.listViewItem}>*/}
                {/*            <p>km/h</p>*/}
                {/*            {speedProfile.map((entry, index) => (*/}
                {/*                <p key={index}>{((entry.speed * 3600) /*/}
                {/*                    1000).toFixed(2)}</p>*/}
                {/*            ))}*/}
                {/*        </div>*/}
                {/*        <div style={styles.listViewItem}>*/}
                {/*            <p>m</p>*/}
                {/*            {speedProfile.map((entry, index) => (*/}
                {/*                <p key={index}>{entry.distance.toFixed(2)}</p>*/}
                {/*            ))}*/}
                {/*        </div>*/}
                {/*    </div>*/}
                {/*</div>*/}
                <div style={styles.listViewContainer}>
                    <div style={styles.listViewHeader}>
                        <p>Speed Profile Seconds</p>
                        <p>km/h</p>
                        <p>m</p>
                    </div>
                    <div style={styles.listView}>
                        <div style={styles.listViewItem}>
                            {speedProfile.map((entry, index) => (
                                <p key={index}>{entry.time.toFixed(2)}</p>
                            ))}
                        </div>
                        <div style={styles.listViewItem}>
                            {speedProfile.map((entry, index) => (
                                <p key={index}>{((entry.speed * 3600) /
                                    1000).toFixed(2)}</p>
                            ))}
                        </div>
                        <div style={styles.listViewItem}>
                            {speedProfile.map((entry, index) => (
                                <p key={index}>{entry.distance.toFixed(2)}</p>
                            ))}
                        </div>
                    </div>
                </div>

            </div>

            <button
                style={styles.button}
                onClick={isCollecting ? clearData : restartCollecting}
            >
                {isCollecting ? 'Clear' : 'Restart'}
            </button>
        </div>
    );
}

const styles = {
    overlay: {
        position: 'fixed',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%',
        backgroundColor: 'black',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        flexDirection: 'column',
        color: 'white',
    },
    container: {
        backgroundColor: 'rgba(38,38,38,255)',
        padding: '20px',
        borderRadius: '8px',
        width: '90%',
        maxWidth: '400px',
        textAlign: 'center',
        marginBottom: '20px',
    },
    table: {
        width: '100%',
        borderCollapse: 'collapse',
        marginBottom: '20px',
        color: 'white',
    },
    row: {
        borderBottom: '1px solid rgba(0, 0, 0, 0.1)',
    },
    label: {
        textAlign: 'left',
        padding: '10px',
        fontWeight: 'bold',
    },
    data: {
        textAlign: 'right',
        padding: '10px',
    },
    button: {
        marginTop: '20px',
        padding: '10px 20px',
        backgroundColor: 'purple',
        color: '#fff',
        border: 'none',
        borderRadius: '5px',
        cursor: 'pointer',
        fontWeight: 'bold',
    },
    listViewContainer: {
        width: '90%',
        maxWidth: '400px',
        backgroundColor: 'rgba(38,38,38,255)',
        padding: '20px',
        borderRadius: '8px',
        textAlign: 'center',
        color: 'white',
        height: '150px',
        overflowY: 'auto', // Add this line
        position: 'relative', // Add this line
    },
    listViewHeader: {
        display: 'flex',
        top: '0', // Add this line
        backgroundColor: 'rgba(38,38,38,255)', // Add this line
        padding: '10px 0', // Add this line
        justifyContent: 'space-between',
        overflow:'false'
    },
    listView: {
        display: 'flex',
        justifyContent: 'space-between',
     },
    listViewItem: {
        flex: 1,
        justifyContent: 'space-between',

    },
};

export default GeolocationTracker;
Editor is loading...
Leave a Comment