open System
open System.Diagnostics

type State = { x: float; y: float; vx: float; vy: float }

let calculateNextState currentState dt =
    // Stałe grawitacyjne
    let g = 9.81

    // Obliczenia metodą Verleta
    let ax = 0.0  // Zakładamy brak przyspieszenia poziomego
    let ay = -g   // Przyspieszenie pionowe (ujemne ze względu na kierunek w górę)

    let nextVx = currentState.vx + ax * dt
    let nextVy = currentState.vy + ay * dt

    let nextX = currentState.x + currentState.vx * dt + 0.5 * ax * dt * dt
    let nextY = currentState.y + currentState.vy * dt + 0.5 * ay * dt * dt

    { x = nextX; y = nextY; vx = nextVx; vy = nextVy }

let simulateProjectileMotion initialPosition initialVelocity dt numSteps =
    let rec simulate state step =
        if step >= numSteps then
            state
        else
            let nextState = calculateNextState state dt
            simulate nextState (step + 1)

    simulate { x = initialPosition.x; y = initialPosition.y; vx = initialVelocity.vx; vy = initialVelocity.vy } 0

// Pomiar czasu
let stopwatch = Stopwatch.StartNew()

// Przykład użycia
let initialPosition = { x = 0.0; y = 0.0;vx = 20.0; vy = 10.0 }
let initialVelocity = { x = 0.0; y = 0.0;vx = 20.0; vy = 10.0 }
let dt = 0.1
let numSteps = 10000

let finalState = simulateProjectileMotion initialPosition initialVelocity dt numSteps

stopwatch.Stop()

printfn "Współrzędne końcowe: x = %f, y = %f" finalState.x finalState.y
printfn "Czas wykonania: %f ms" (float stopwatch.ElapsedMilliseconds)
