<commit_before>module Simulation where

import Geographical
import Primitives
import Time

import qualified Prelude
import Data.Time
import Numeric.Units.Dimensional.Prelude
import Text.Printf (printf)

class AdvanceTime a where
  advanceBy :: Time' -> a -> a

data Simulation = Simulation {
  simTime :: UTCTime,
  simVessels :: [Vessel]
}

instance Show Simulation where
  show s = printf "Simulation\n\
                  \  Time: %s\n\
                  \  Vessels: %s" t v
    where t = show (simTime s)
          v = show (simVessels s)

instance AdvanceTime Simulation where
  advanceBy t s =
    s { simTime = addTime t (simTime s),
        simVessels = map (advanceBy t) (simVessels s) }

newSimulation :: UTCTime -> Simulation
newSimulation utc = Simulation {
  simTime = utc,
  simVessels = []
}

addVessel :: Simulation -> Simulation
addVessel = updateVessels (\vs -> newVessel : vs)

updateVessels :: ([Vessel] -> [Vessel]) -> Simulation -> Simulation
updateVessels f s = s { simVessels = f (simVessels s) }

updateFirstVessel :: (Vessel -> Vessel) -> Simulation -> Simulation
updateFirstVessel f = updateVessels update
  where update [] = []
        update (v:vs) = f v : vs

data Vessel = Vessel {
  vesPosition :: Geog,
  vesHeading :: Angle',
  vesRudder :: AngularVelocity',
  vesSpeed :: Velocity'
}

instance Show Vessel where
  show v = printf "Vessel Pos: %s Hdg: %.2f deg" p h
    where h = (vesHeading v) /~ degree
          p = show (vesPosition v)

instance AdvanceTime Vessel where
  advanceBy t v =
    v { vesPosition = translate dst hdg pos,
        vesHeading = hdg + (rdr * t) }
    where pos = vesPosition v
          hdg = vesHeading v
          rdr = vesRudder v
          spd = vesSpeed v
          dst = spd * t

newVessel :: Vessel
newVessel = Vessel {
  vesPosition = mkGeog 32 116,
  vesHeading = 0 *~ degree,
  vesRudder  = 2 *~ (degree / second),
  vesSpeed   = 5 *~ knot
}<commit_msg>Added implementation of NFData for Vessel and Simulation<commit_after>{-# LANGUAGE TemplateHaskell #-}

module Simulation where

import Geographical
import Primitives
import Time

import qualified Prelude
import Data.Time
import Data.DeriveTH
import Data.Derive.NFData
import Text.Printf (printf)
import Control.Parallel.Strategies
import Numeric.Units.Dimensional.Prelude

class AdvanceTime a where
  advanceBy :: Time' -> a -> a

data Simulation = Simulation {
  simTime :: UTCTime,
  simVessels :: [Vessel]
}

instance Show Simulation where
  show s = printf "Simulation\n\
                  \  Time: %s\n\
                  \  Vessels: %s" t v
    where t = show (simTime s)
          v = show (simVessels s)

instance AdvanceTime Simulation where
  advanceBy t s =
    s { simTime = addTime t (simTime s),
        simVessels = map (advanceBy t) (simVessels s) }

newSimulation :: UTCTime -> Simulation
newSimulation utc = Simulation {
  simTime = utc,
  simVessels = []
}

addVessel :: Simulation -> Simulation
addVessel = updateVessels (\vs -> newVessel : vs)

updateVessels :: ([Vessel] -> [Vessel]) -> Simulation -> Simulation
updateVessels f s = s { simVessels = f (simVessels s) }

updateFirstVessel :: (Vessel -> Vessel) -> Simulation -> Simulation
updateFirstVessel f = updateVessels update
  where update [] = []
        update (v:vs) = f v : vs

data Vessel = Vessel {
  vesPosition :: Geog,
  vesHeading :: Angle',
  vesRudder :: AngularVelocity',
  vesSpeed :: Velocity'
}

instance Show Vessel where
  show v = printf "Vessel Pos: %s Hdg: %.2f deg" p h
    where h = (vesHeading v) /~ degree
          p = show (vesPosition v)

instance AdvanceTime Vessel where
  advanceBy t v =
    v { vesPosition = translate dst hdg pos,
        vesHeading = hdg + (rdr * t) }
    where pos = vesPosition v
          hdg = vesHeading v
          rdr = vesRudder v
          spd = vesSpeed v
          dst = spd * t

newVessel :: Vessel
newVessel = Vessel {
  vesPosition = mkGeog 32 116,
  vesHeading = 0 *~ degree,
  vesRudder  = 2 *~ (degree / second),
  vesSpeed   = 5 *~ knot
}

$(derive makeNFData ''Vessel)
$(derive makeNFData ''Simulation)
{'fraction_non_alphanumeric': 0.0993621197252208, 'fraction_numerical': 0.004416094210009814, 'mean_word_length': 2.84985835694051, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1011141', 'n_tokens_mistral': 1471, 'n_tokens_neox': 1372, 'n_words': 438}