Skip to content

Drag Race mode #2

Open
Open
@kbennett2000

Description

@kbennett2000

Remote control mode:

  • Enter timing session request
  • Check "Drag Race" option
  • Number of laps parameter is hidden, we will use 1
  • configure additional parameters:
  • START DELAY: how long to wait after the session request is picked up to start the timer
  • After start delay, play countdown beeps
  • Start timing session after the last beep
  • Stop timing session after motion is detected

Drag race sessions should be displayed differently:

  • Best Lap, Worst lap should be ignored (there is only one lap)

Component to measure 132 foot track?

  • Configurable track length? Default to 132?

PROTOTYPE:
https://claude.ai/chat/7a0e4310-d9b5-41dd-a21d-4f9d01e3bd7c

This implementation:

  • Uses GPS to mark start line
  • Continuously updates distance as user walks
  • Shows directional arrow to maintain straight line
  • Alerts when 132ft reached
  • Main limitation: GPS accuracy (typically ±15-50ft). Best results in open areas away from buildings.
import React, { useState, useEffect } from 'react';
import { MapPin, Navigation2 } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';

const TrackMeasurer = () => {
  const [startPosition, setStartPosition] = useState(null);
  const [currentPosition, setCurrentPosition] = useState(null);
  const [distance, setDistance] = useState(0);
  const [heading, setHeading] = useState(0);
  const TARGET_DISTANCE = 132; // feet

  // Calculate distance between two points using Haversine formula
  const calculateDistance = (lat1, lon1, lat2, lon2) => {
    const R = 20902231; // Earth radius in feet
    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;
  };

  const handleStartPosition = () => {
    if ('geolocation' in navigator) {
      navigator.geolocation.getCurrentPosition((position) => {
        setStartPosition({
          lat: position.coords.latitude,
          lon: position.coords.longitude
        });
      });
    }
  };

  useEffect(() => {
    let watchId;
    if (startPosition && 'geolocation' in navigator) {
      watchId = navigator.geolocation.watchPosition((position) => {
        const current = {
          lat: position.coords.latitude,
          lon: position.coords.longitude
        };
        setCurrentPosition(current);
        
        const dist = calculateDistance(
          startPosition.lat, 
          startPosition.lon,
          current.lat,
          current.lon
        );
        setDistance(dist);

        // Calculate heading
        const dLon = (current.lon - startPosition.lon) * Math.PI / 180;
        const y = Math.sin(dLon) * Math.cos(current.lat * Math.PI / 180);
        const x = Math.cos(startPosition.lat * Math.PI / 180) * Math.sin(current.lat * Math.PI / 180) -
                Math.sin(startPosition.lat * Math.PI / 180) * Math.cos(current.lat * Math.PI / 180) * Math.cos(dLon);
        const brng = Math.atan2(y, x) * 180 / Math.PI;
        setHeading((brng + 360) % 360);
      });
    }
    return () => {
      if (watchId) navigator.geolocation.clearWatch(watchId);
    };
  }, [startPosition]);

  return (
    <Card className="w-full max-w-md">
      <CardHeader>
        <CardTitle>RC Track Measurer</CardTitle>
      </CardHeader>
      <CardContent>
        <div className="flex flex-col items-center gap-4">
          {!startPosition ? (
            <button 
              onClick={handleStartPosition}
              className="flex items-center gap-2 px-4 py-2 bg-blue-500 text-white rounded-lg"
            >
              <MapPin size={20} />
              Mark Start Line
            </button>
          ) : (
            <div className="text-center space-y-4">
              <div className="flex items-center justify-center text-4xl">
                <Navigation2 
                  size={48}
                  style={{ transform: `rotate(${heading}deg)` }}
                  className="text-blue-500"
                />
              </div>
              <div className="space-y-2">
                <p className="text-2xl font-bold">
                  {distance.toFixed(1)} ft
                </p>
                <p className={`text-lg ${Math.abs(distance - TARGET_DISTANCE) < 1 ? 'text-green-500' : ''}`}>
                  {distance < TARGET_DISTANCE 
                    ? `Keep walking: ${(TARGET_DISTANCE - distance).toFixed(1)} ft to go`
                    : `Too far: ${(distance - TARGET_DISTANCE).toFixed(1)} ft past`}
                </p>
              </div>
            </div>
          )}
        </div>
      </CardContent>
    </Card>
  );
};

export default TrackMeasurer;

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions