{-# OPTIONS_GHC -Wall #-}

module Main where

import Graphics.Gnuplot.Simple
import Physics.Learn

--type StateTuple = (Double,Vec,Vec)
--type AccelerationFunction = StateTuple -> Vec

--eulerCromerSolution :: Double -> AccelerationFunction
--                    -> StateTuple -> StateTuple
--eulerCromerSolution

-- vertical direction is y direction
earthSurfaceGravity :: OneParticleAccelerationFunction
earthSurfaceGravity _state = vec 0 (-g) 0

g :: Double
g = 9.81

projectileTuples :: Double -> Double
                 -> OneParticleAccelerationFunction
                 -> [OneParticleSystemState]
projectileTuples v0 theta af
    = oneParticleRungeKuttaSolution af 0.01
      (0, St (cart 0 0 0) (vec vx0 vy0 0))
      where
        vx0 = v0 * cos theta
        vy0 = v0 * sin theta

yCoord :: Position -> Double
yCoord r = y
    where
      (_,y,_) = cartesianCoordinates r

inAir :: [OneParticleSystemState] -> [OneParticleSystemState]
inAir = takeWhile (\(_,St r _) -> yCoord r >= 0)

initialProjState :: Double -> Double -> OneParticleSystemState
initialProjState v0 theta
    = (0, St (cart 0 0 0) (vec vx0 vy0 0))
      where
        vx0 = v0 * cos theta
        vy0 = v0 * sin theta

-- air resistance quadratic in the speed
surfaceGravityAirResistance :: Double -> Double
                            -> OneParticleAccelerationFunction
surfaceGravityAirResistance m b (_t,St _r v)
    = netForce ^/ m
      where
        netForce      = gravity ^+^ airResistance
        gravity       = vec 0 (-m * g) 0
        airResistance = ((-b) * magnitude v) *^ v

trajectory :: [OneParticleSystemState] -> [(Double,Double)]
trajectory sts = [(x,y) | (_,St r _) <- sts, let (x,y,_) = cartesianCoordinates r]

traj :: Double -> [(Double,Double)]
traj b = trajectory $ inAir
         $ oneParticleRungeKuttaSolution
               (surfaceGravityAirResistance 2 b)
               0.01
               (initialProjState 30 (pi/6))

main :: IO ()
main = plotPathsStyle
       [Title "Trajectories of 2-kg object, initial speed 30 m/s, angle 30 degrees"
       ,XLabel "Range (m)"
       ,YLabel "Height (m)"
       ,PNG "learn-physics-Projectile.png"
       ] [(defaultStyle {lineSpec = CustomStyle [LineTitle "No air resistance"]}, traj 0)
         ,(defaultStyle {lineSpec = CustomStyle [LineTitle "Drag 0.01 kg/m"]}, traj 0.01)
         ,(defaultStyle {lineSpec = CustomStyle [LineTitle "Drag 0.02 kg/m"]}, traj 0.02)
         ] >> putStrLn "output sent to file learn-physics-Projectile.png"

