stratux (empty) → 0.0.1
raw patch · 11 files changed
+736/−0 lines, 11 filesdep +QuickCheckdep +aesondep +basebuild-type:Customsetup-changed
Dependencies added: QuickCheck, aeson, base, bytestring, directory, doctest, filepath, lens, scientific, template-haskell, time
Files
- LICENCE +27/−0
- Setup.lhs +44/−0
- changelog.md +3/−0
- src/Data/Aviation/Stratux.hs +5/−0
- src/Data/Aviation/Stratux/Types.hs +8/−0
- src/Data/Aviation/Stratux/Types/EmitterCategory.hs +147/−0
- src/Data/Aviation/Stratux/Types/IcaoAddr.hs +82/−0
- src/Data/Aviation/Stratux/Types/TargetType.hs +126/−0
- src/Data/Aviation/Stratux/Types/Traffic.hs +186/−0
- stratux.cabal +76/−0
- test/doctests.hs +32/−0
+ LICENCE view
@@ -0,0 +1,27 @@+Copyright 2016 Tony Morris++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.lhs view
@@ -0,0 +1,44 @@+#!/usr/bin/env runhaskell+\begin{code}+{-# OPTIONS_GHC -Wall #-}+module Main (main) where++import Data.List ( nub )+import Data.Version ( showVersion )+import Distribution.Package ( PackageName(PackageName), PackageId, InstalledPackageId, packageVersion, packageName )+import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) )+import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )+import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )+import Distribution.Simple.BuildPaths ( autogenModulesDir )+import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )+import Distribution.Simple.LocalBuildInfo ( withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )+import Distribution.Verbosity ( Verbosity )+import System.FilePath ( (</>) )++main :: IO ()+main = defaultMainWithHooks simpleUserHooks+ { buildHook = \pkg lbi hooks flags -> do+ generateBuildModule (fromFlag (buildVerbosity flags)) pkg lbi+ buildHook simpleUserHooks pkg lbi hooks flags+ }++generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()+generateBuildModule verbosity pkg lbi = do+ let dir = autogenModulesDir lbi+ createDirectoryIfMissingVerbose verbosity True dir+ withLibLBI pkg lbi $ \_ libcfg -> do+ withTestLBI pkg lbi $ \suite suitecfg -> do+ rewriteFile (dir </> "Build_" ++ testName suite ++ ".hs") $ unlines+ [ "module Build_" ++ testName suite ++ " where"+ , "deps :: [String]"+ , "deps = " ++ (show $ formatdeps (testDeps libcfg suitecfg))+ ]+ where+ formatdeps = map (formatone . snd)+ formatone p = case packageName p of+ PackageName n -> n ++ "-" ++ showVersion (packageVersion p)++testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]+testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys++\end{code}
+ changelog.md view
@@ -0,0 +1,3 @@+0.0.1++Initial.
+ src/Data/Aviation/Stratux.hs view
@@ -0,0 +1,5 @@+module Data.Aviation.Stratux(+ module S+) where++import Data.Aviation.Stratux.Types as S
+ src/Data/Aviation/Stratux/Types.hs view
@@ -0,0 +1,8 @@+module Data.Aviation.Stratux.Types(+ module T+) where++import Data.Aviation.Stratux.Types.EmitterCategory as T+import Data.Aviation.Stratux.Types.IcaoAddr as T+import Data.Aviation.Stratux.Types.TargetType as T+import Data.Aviation.Stratux.Types.Traffic as T
+ src/Data/Aviation/Stratux/Types/EmitterCategory.hs view
@@ -0,0 +1,147 @@+{-# LANGUAGE TemplateHaskell #-}++module Data.Aviation.Stratux.Types.EmitterCategory(+ EmitterCategory(..)+, AsEmitterCategory(..)+, AsEmitterCategoryNum(..)+) where++import Control.Category(Category(id))+import Control.Lens(Prism', prism', makeClassyPrisms, (^?), ( # ))+import Control.Monad(mzero, Monad(return))+import Data.Aeson(FromJSON(parseJSON), ToJSON(toJSON), Value(Number), withScientific)+import Data.Eq(Eq)+import Data.Maybe(Maybe(Just, Nothing))+import Data.Ord(Ord)+import Data.Scientific(Scientific)+import Prelude(Show, Num)++-- $setup+-- >>> :set -XOverloadedStrings+-- >>> import Control.Lens+-- >>> import Data.Aeson(decode, encode)+-- >>> import Data.Maybe(Maybe)+-- >>> import Prelude++-- https://i.imgur.com/cXYhzZM.png+data EmitterCategory = -- 0 to 7+ NoEmitterCategory+ | Light -- < 15500lb+ | Small -- 15500-75000lb+ | Large -- 75000-300000lb+ | HighVortexLarge -- B757+ | Heavy -- > 300000lb+ | HighPerformance -- >5G accel @ > 400KIAS+ | Rotorcraft+ deriving (Eq, Ord, Show)++makeClassyPrisms ''EmitterCategory++class AsEmitterCategoryNum a where+ _EmitterCategoryNum ::+ (Num a, Eq a) =>+ Prism'+ a+ EmitterCategory++instance AsEmitterCategoryNum EmitterCategory where+ _EmitterCategoryNum =+ id++-- |+--+-- >>> _EmitterCategoryNum # NoEmitterCategory :: Scientific+-- 0.0+--+-- >>> _EmitterCategoryNum # Light :: Scientific+-- 1.0+--+-- >>> _EmitterCategoryNum # HighVortexLarge :: Scientific+-- 4.0+--+-- >>> _EmitterCategoryNum # Rotorcraft :: Scientific+-- 7.0+instance AsEmitterCategoryNum Scientific where+ _EmitterCategoryNum =+ emitterCategoryNum++emitterCategoryNum ::+ (Num a, Eq a) =>+ Prism'+ a+ EmitterCategory+emitterCategoryNum =+ prism'+ (\t -> case t of+ NoEmitterCategory ->+ 0+ Light ->+ 1+ Small ->+ 2+ Large ->+ 3+ HighVortexLarge ->+ 4+ Heavy ->+ 5+ HighPerformance ->+ 6+ Rotorcraft ->+ 7) + (\n -> case n of+ 0 ->+ Just NoEmitterCategory+ 1 ->+ Just Light+ 2 ->+ Just Small+ 3 -> + Just Large+ 4 ->+ Just HighVortexLarge+ 5 ->+ Just Heavy+ 6 ->+ Just HighPerformance+ 7 ->+ Just Rotorcraft+ _ ->+ Nothing)++-- |+--+-- >>> decode "0" :: Maybe EmitterCategory+-- Just NoEmitterCategory+--+-- >>> decode "1" :: Maybe EmitterCategory+-- Just Light+--+-- >>> decode "4" :: Maybe EmitterCategory+-- Just HighVortexLarge+--+-- >>> decode "7" :: Maybe EmitterCategory+-- Just Rotorcraft+instance FromJSON EmitterCategory where+ parseJSON =+ withScientific "EmitterCategory" (\n -> case n ^? _EmitterCategoryNum of+ Nothing ->+ mzero+ Just t ->+ return t)+-- |+--+-- >>> encode NoEmitterCategory+-- "0"+--+-- >>> encode Light+-- "1"+--+-- >>> encode HighVortexLarge+-- "4"+--+-- >>> encode Rotorcraft+-- "7"+instance ToJSON EmitterCategory where+ toJSON c =+ Number (_EmitterCategoryNum # c)
+ src/Data/Aviation/Stratux/Types/IcaoAddr.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE TemplateHaskell #-}++module Data.Aviation.Stratux.Types.IcaoAddr(+ IcaoAddr(..)+, HasIcaoAddr(..)+, HasWord8s(..)+) where++import Control.Applicative(Applicative((<*>)))+import Control.Category(Category(id))+import Control.Lens(makeClassy, Traversal')+import Control.Monad(Monad(return))+import Data.Aeson(FromJSON(parseJSON), ToJSON(toJSON), Value(Number), withScientific)+import Data.Bits(shiftR, shiftL, (.|.), (.&.))+import Data.Eq(Eq)+import Data.Functor((<$>))+import Data.Ord(Ord)+import Data.Word(Word8, Word)+import Prelude(floor, fromIntegral, Show, Num((*)))++-- $setup+-- >>> :set -XOverloadedStrings+-- >>> import Control.Lens+-- >>> import Data.Aeson(decode, encode)+-- >>> import Data.Maybe(Maybe)+-- >>> import Prelude++data IcaoAddr =+ IcaoAddr {+ _icaoAddrWord0 :: Word8+ , _icaoAddrWord1 :: Word8+ , _icaoAddrWord2 :: Word8+ } deriving (Eq, Ord, Show)++makeClassy ''IcaoAddr++-- |+--+-- >>> decode "8153826" :: Maybe IcaoAddr+-- Just (IcaoAddr {_icaoAddrWord0 = 124, _icaoAddrWord1 = 106, _icaoAddrWord2 = 226})+--+-- >>> decode "66051" :: Maybe IcaoAddr+-- Just (IcaoAddr {_icaoAddrWord0 = 1, _icaoAddrWord1 = 2, _icaoAddrWord2 = 3})+instance FromJSON IcaoAddr where+ parseJSON =+ withScientific "IcaoAddr" (\i ->+ let r :: Word+ r = floor i+ w n = fromIntegral (shiftR r (n * 8) .&. 255)+ in return (IcaoAddr (w 2) (w 1) (w 0)))++-- |+--+-- >>> encode (IcaoAddr 1 2 3)+-- "66051"+--+-- >>> encode (IcaoAddr 124 106 226)+-- "8153826"+instance ToJSON IcaoAddr where+ toJSON (IcaoAddr w0 w1 w2) =+ Number (fromIntegral (shiftL (shiftL (fromIntegral w0 :: Word) 8 .|. fromIntegral w1) 8 .|. fromIntegral w2)) ++-- |+--+-- >>> _Word8s %~ (+1) $ IcaoAddr 124 106 226+-- IcaoAddr {_icaoAddrWord0 = 125, _icaoAddrWord1 = 107, _icaoAddrWord2 = 227}+--+-- >>> _Word8s %~ (+1) $ IcaoAddr 1 2 3+-- IcaoAddr {_icaoAddrWord0 = 2, _icaoAddrWord1 = 3, _icaoAddrWord2 = 4}+class HasWord8s a where+ _Word8s ::+ Traversal'+ a+ Word8++instance HasWord8s Word8 where+ _Word8s =+ id++instance HasWord8s IcaoAddr where+ _Word8s f (IcaoAddr w0 w1 w2) =+ IcaoAddr <$> f w0 <*> f w1 <*> f w2
+ src/Data/Aviation/Stratux/Types/TargetType.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE TemplateHaskell #-}++module Data.Aviation.Stratux.Types.TargetType(+ TargetType(..)+, AsTargetType(..)+, AsTargetTypeNum(..)+) where++import Control.Category(Category(id))+import Control.Lens(makeClassyPrisms, Prism', prism', (^?), ( # ))+import Control.Monad(Monad(return), mzero)+import Data.Aeson(FromJSON(parseJSON), ToJSON(toJSON), Value(Number), withScientific)+import Data.Eq(Eq)+import Data.Maybe+import Data.Ord(Ord)+import Data.Scientific(Scientific)+import Prelude(Num, Show)++-- $setup+-- >>> :set -XOverloadedStrings+-- >>> import Control.Lens+-- >>> import Data.Aeson(decode, encode)+-- >>> import Data.Maybe(Maybe)+-- >>> import Prelude++data TargetType =+ ModeS+ | Adsb+ | Adsr+ | TisbS+ | Tisb+ deriving (Eq, Ord, Show)++makeClassyPrisms ''TargetType++class AsTargetTypeNum a where+ _TargetTypeNum ::+ (Num a, Eq a) =>+ Prism'+ a+ TargetType++instance AsTargetTypeNum TargetType where+ _TargetTypeNum =+ id++-- |+--+-- >>> _TargetTypeNum # ModeS :: Scientific+-- 0.0+--+-- >>> _TargetTypeNum # Adsb :: Scientific+-- 1.0+--+-- >>> _TargetTypeNum # Tisb :: Scientific+-- 4.0+instance AsTargetTypeNum Scientific where+ _TargetTypeNum =+ targetTypeNum++targetTypeNum ::+ (Num a, Eq a) =>+ Prism'+ a+ TargetType+targetTypeNum =+ prism'+ (\t -> case t of+ ModeS ->+ 0+ Adsb ->+ 1+ Adsr ->+ 2+ TisbS ->+ 3+ Tisb ->+ 4) + (\n -> case n of+ 0 ->+ Just ModeS+ 1 ->+ Just Adsb+ 2 ->+ Just Adsr+ 3 -> + Just TisbS+ 4 ->+ Just Tisb+ _ ->+ Nothing)++-- |+--+-- >>> decode "0" :: Maybe TargetType+-- Just ModeS+--+-- >>> decode "1" :: Maybe TargetType+-- Just Adsb+--+-- >>> decode "4" :: Maybe TargetType+-- Just Tisb+--+-- >>> decode "5" :: Maybe TargetType+-- Nothing+instance FromJSON TargetType where+ parseJSON =+ withScientific "TargetType" (\n -> case n ^? targetTypeNum of+ Nothing ->+ mzero+ Just t ->+ return t)++-- |+--+-- >>> encode ModeS+-- "0"+--+-- >>> encode Adsb+-- "1"+--+-- >>> encode Tisb+-- "4"+instance ToJSON TargetType where+ toJSON c =+ Number (targetTypeNum # c)
+ src/Data/Aviation/Stratux/Types/Traffic.hs view
@@ -0,0 +1,186 @@+ {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}++module Data.Aviation.Stratux.Types.Traffic(+ Traffic(..)+, HasTraffic(..)+, HasUTCTimes(..)+) where++import Control.Applicative(Applicative((<*>)))+import Control.Category(Category((.), id))+import Control.Lens(makeClassy, lens, Traversal')+import Data.Aviation.Stratux.Types.EmitterCategory(EmitterCategory)+import Data.Aviation.Stratux.Types.IcaoAddr(IcaoAddr, HasIcaoAddr(icaoAddr), HasWord8s(_Word8s))+import Data.Aviation.Stratux.Types.TargetType(TargetType)+import Data.Aeson(FromJSON(parseJSON), ToJSON(toJSON), (.:), withObject, (.=), object)+import Data.Bool(Bool)+import Data.Eq(Eq)+import Data.Int(Int)+import Data.Functor((<$>))+import Data.Ord(Ord)+import Data.String(String)+import Data.Time(UTCTime)+import Prelude(Double, Show)++-- $setup+-- >>> :set -XOverloadedStrings+-- >>> import Control.Lens+-- >>> import Data.Aeson(decode, encode)+-- >>> import Data.Maybe(Maybe)+-- >>> import Prelude+-- >>> import Data.Aviation.Stratux.Types.EmitterCategory+-- >>> import Data.Aviation.Stratux.Types.IcaoAddr+-- >>> import Data.Aviation.Stratux.Types.TargetType+-- >>> import Data.Time+++-- https://i.imgur.com/nOqGbfr.png+data Traffic =+ Traffic {+ icaoAddrTraffic :: IcaoAddr+ , _tail :: String -- tail+ , _emitterCategory :: EmitterCategory+ , _onGround :: Bool -- on-ground+ , _addressType :: Int -- address type+ , _targetType :: TargetType+ , _signalLevel :: Double -- signal level+ , _positionValid :: Bool -- position valid+ , _latitude :: Double -- latitude+ , _longitude :: Double -- longitude+ , _altitude :: Int -- altitude+ , _gnssDiffFromBaroAlt :: Int -- GNSS altitude above WGS84 datum+ , _altIsGnss :: Bool -- AltIsGNSS, Pressure alt = 0; GNSS alt = 1+ , _navigationIntegrityCategory :: Int -- Navigation Integrity Category.+ , _navigationAccuracyCategoryForPosition :: Int -- Navigation Accuracy Category for Position+ , _track :: Int -- Track degrees true+ , _speed :: Int -- speed (knots)+ , _speedValid :: Bool -- speed valid+ , _verticalVelocity :: Int -- Vertical velocity (feet/minute)+ , _timestamp :: UTCTime -- Timestamp+ , _age :: Double -- age+ , _lastSeen :: UTCTime -- last seen+ , _lastAltitude :: UTCTime -- last altitude+ , _lastGnssDiff :: UTCTime -- last GNSS diff+ , _lastGnssDiffAltitude :: Int -- last GNSS diff altitude+ , _lastSpeed :: UTCTime -- last speed+ , _lastSource :: Int -- last source+ , _extrapolatedPosition :: Bool -- extrapolated position+ , _bearing :: Double -- Bearing in degrees true to traffic from ownship, if it can be calculated.+ , _distanceToTrafficFromOwnship :: Double -- Distance to traffic from ownship, if it can be calculated.+ } deriving (Eq, Ord, Show)++makeClassy ''Traffic++-- |+--+-- >>> decode "{\"Icao_addr\":8153826,\"Tail\":\"SVY22\",\"Emitter_category\":1,\"OnGround\":false,\"Addr_type\":0,\"TargetType\":1,\"SignalLevel\":-30.920514783877277,\"Position_valid\":true,\"Lat\":-27.501154,\"Lng\":153.21422,\"Alt\":12500,\"GnssDiffFromBaroAlt\":650,\"AltIsGNSS\":false,\"NIC\":8,\"NACp\":9,\"Track\":89,\"Speed\":205,\"Speed_valid\":true,\"Vvel\":0,\"Timestamp\":\"2016-05-24T01:13:18.189Z\",\"Age\":40.8,\"Last_seen\":\"0001-01-01T03:30:38.2Z\",\"Last_alt\":\"0001-01-01T03:30:38.55Z\",\"Last_GnssDiff\":\"0001-01-01T03:30:36.75Z\",\"Last_GnssDiffAlt\":12500,\"Last_speed\":\"0001-01-01T03:30:36.75Z\",\"Last_source\":1,\"ExtrapolatedPosition\":false,\"Bearing\":0,\"Distance\":0}" :: Maybe Traffic+-- Just (Traffic {icaoAddrTraffic = IcaoAddr {_icaoAddrWord0 = 124, _icaoAddrWord1 = 106, _icaoAddrWord2 = 226}, _tail = "SVY22", _emitterCategory = Light, _onGround = False, _addressType = 0, _targetType = Adsb, _signalLevel = -30.920514783877277, _positionValid = True, _latitude = -27.501154, _longitude = 153.21422, _altitude = 12500, _gnssDiffFromBaroAlt = 650, _altIsGnss = False, _navigationIntegrityCategory = 8, _navigationAccuracyCategoryForPosition = 9, _track = 89, _speed = 205, _speedValid = True, _verticalVelocity = 0, _timestamp = 2016-05-24 01:13:18.189 UTC, _age = 40.8, _lastSeen = 0001-01-01 03:30:38.2 UTC, _lastAltitude = 0001-01-01 03:30:38.55 UTC, _lastGnssDiff = 0001-01-01 03:30:36.75 UTC, _lastGnssDiffAltitude = 12500, _lastSpeed = 0001-01-01 03:30:36.75 UTC, _lastSource = 1, _extrapolatedPosition = False, _bearing = 0.0, _distanceToTrafficFromOwnship = 0.0})+instance FromJSON Traffic where+ parseJSON =+ withObject "Traffic" (\x -> + Traffic <$>+ x .: "Icao_addr" <*>+ x .: "Tail" <*>+ x .: "Emitter_category" <*>+ x .: "OnGround" <*>+ x .: "Addr_type" <*>+ x .: "TargetType" <*>+ x .: "SignalLevel" <*>+ x .: "Position_valid" <*>+ x .: "Lat" <*>+ x .: "Lng" <*>+ x .: "Alt" <*>+ x .: "GnssDiffFromBaroAlt" <*>+ x .: "AltIsGNSS" <*>+ x .: "NIC" <*>+ x .: "NACp" <*>+ x .: "Track" <*>+ x .: "Speed" <*>+ x .: "Speed_valid" <*>+ x .: "Vvel" <*>+ x .: "Timestamp" <*>+ x .: "Age" <*>+ x .: "Last_seen" <*>+ x .: "Last_alt" <*>+ x .: "Last_GnssDiff" <*>+ x .: "Last_GnssDiffAlt" <*>+ x .: "Last_speed" <*>+ x .: "Last_source" <*>+ x .: "ExtrapolatedPosition" <*>+ x .: "Bearing" <*>+ x .: "Distance")++-- |+--+-- >>> toJSON (Traffic (IcaoAddr 124 106 226) "SVY22" Light False 0 Adsb (-30.920514783877277) True (-27.501154) 153.21422 12500 650 False 8 9 89 205 True 0 (UTCTime (fromGregorian 1 1 1) 3597) 40.8 (UTCTime (fromGregorian 1 1 1) 259) (UTCTime (fromGregorian 1 1 1) 23) (UTCTime (fromGregorian 1 1 1) 597) 12500 (UTCTime (fromGregorian 2016 5 24) 237) 1 False 0.0 0.0)+-- Object (fromList [("OnGround",Bool False),("Bearing",Number 0.0),("ExtrapolatedPosition",Bool False),("NIC",Number 8.0),("Last_alt",String "0001-01-01T00:00:23Z"),("Track",Number 89.0),("Last_speed",String "2016-05-24T00:03:57Z"),("GnssDiffFromBaroAlt",Number 650.0),("Last_seen",String "0001-01-01T00:04:19Z"),("Icao_addr",Number 8153826.0),("SignalLevel",Number -30.920514783877277),("Distance",Number 0.0),("Age",Number 40.8),("Speed_valid",Bool True),("TargetType",Number 1.0),("Lat",Number -27.501154),("Vvel",Number 0.0),("NACp",Number 9.0),("Addr_type",Number 0.0),("Speed",Number 205.0),("AltIsGNSS",Bool False),("Lng",Number 153.21422),("Tail",String "SVY22"),("Last_GnssDiffAlt",Number 12500.0),("Position_valid",Bool True),("Last_source",Number 1.0),("Timestamp",String "0001-01-01T00:59:57Z"),("Last_GnssDiff",String "0001-01-01T00:09:57Z"),("Alt",Number 12500.0),("Emitter_category",Number 1.0)])+instance ToJSON Traffic where+ toJSON (Traffic icaoAddr_ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) =+ object [+ "Icao_addr" .= icaoAddr_+ , "Tail" .= tail_+ , "Emitter_category" .= emitterCategory_+ , "OnGround" .= onGround_+ , "Addr_type" .= addressType_+ , "TargetType" .= targetType_+ , "SignalLevel" .= signalLevel_+ , "Position_valid" .= positionValid_+ , "Lat" .= latitude_+ , "Lng" .= longitude_+ , "Alt" .= altitude_+ , "GnssDiffFromBaroAlt" .= gnssDiffFromBaroAlt_+ , "AltIsGNSS" .= altIsGnss_+ , "NIC" .= navigationIntegrityCategory_+ , "NACp" .= navigationAccuracyCategoryForPosition_+ , "Track" .= track_+ , "Speed" .= speed_+ , "Speed_valid" .= speedValid_+ , "Vvel" .= verticalVelocity_+ , "Timestamp" .= timestamp_+ , "Age" .= age_+ , "Last_seen" .= lastSeen_+ , "Last_alt" .= lastAltitude_+ , "Last_GnssDiff" .= lastGnssDiff_+ , "Last_GnssDiffAlt" .= lastGnssDiffAltitude_+ , "Last_speed" .= lastSpeed_+ , "Last_source" .= lastSource_+ , "ExtrapolatedPosition" .= extrapolatedPosition_+ , "Bearing" .= bearing_+ , "Distance" .= distanceToTrafficFromOwnship_+ ]++instance HasIcaoAddr Traffic where+ icaoAddr =+ lens+ (\(Traffic x _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _) -> x)+ (\(Traffic _ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) x -> Traffic x tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_)++instance HasWord8s Traffic where+ _Word8s =+ icaoAddr . _Word8s++class HasUTCTimes a where+ utcTimes ::+ Traversal' + a+ UTCTime++instance HasUTCTimes UTCTime where+ utcTimes =+ id++-- |+--+-- >>> (utcTimes %~ addUTCTime 1) (UTCTime (fromGregorian 1 1 1) 600)+-- 0001-01-01 00:10:01 UTC+instance HasUTCTimes Traffic where+ utcTimes f (Traffic icaoAddr_ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp_ age_ lastSeen_ lastAltitude_ lastGnssDiff_ lastGnssDiffAltitude_ lastSpeed_ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) =+ (\timestamp__ lastSeen__ lastAltitude__ lastGnssDiff__ lastSpeed__ -> + Traffic icaoAddr_ tail_ emitterCategory_ onGround_ addressType_ targetType_ signalLevel_ positionValid_ latitude_ longitude_ altitude_ gnssDiffFromBaroAlt_ altIsGnss_ navigationIntegrityCategory_ navigationAccuracyCategoryForPosition_ track_ speed_ speedValid_ verticalVelocity_ timestamp__ age_ lastSeen__ lastAltitude__ lastGnssDiff__ lastGnssDiffAltitude_ lastSpeed__ lastSource_ extrapolatedPosition_ bearing_ distanceToTrafficFromOwnship_) <$>+ f timestamp_ <*>+ f lastSeen_ <*>+ f lastAltitude_ <*>+ f lastGnssDiff_ <*>+ f lastSpeed_+
+ stratux.cabal view
@@ -0,0 +1,76 @@+name: stratux+version: 0.0.1+license: BSD3+license-file: LICENCE+author: Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>+maintainer: Tony Morris+copyright: Copyright (C) 2016 Tony Morris+synopsis: A library for stratux+category: Development+description: A library for reading JSON output from stratux http://stratux.me/+homepage: https://github.com/tonymorris/stratux+bug-reports: https://github.com/tonymorris/stratux/issues+cabal-version: >= 1.10+build-type: Custom+extra-source-files: changelog.md++source-repository head+ type: git+ location: git@github.com:tonymorris/stratux.git++flag small_base+ description: Choose the new, split-up base package.++library+ default-language:+ Haskell2010++ build-depends:+ base < 5 && >= 3+ , lens >= 4.0 + , aeson >= 0.11 + , time >= 1.4+ , bytestring >= 0.10 + , scientific >= 0.3 ++ ghc-options:+ -Wall++ default-extensions:+ NoImplicitPrelude++ hs-source-dirs:+ src++ exposed-modules:+ Data.Aviation.Stratux+ Data.Aviation.Stratux.Types+ Data.Aviation.Stratux.Types.EmitterCategory+ Data.Aviation.Stratux.Types.IcaoAddr+ Data.Aviation.Stratux.Types.TargetType+ Data.Aviation.Stratux.Types.Traffic++test-suite doctests+ type:+ exitcode-stdio-1.0++ main-is:+ doctests.hs++ default-language:+ Haskell2010++ build-depends:+ base < 5 && >= 3+ , doctest >= 0.9.7+ , filepath >= 1.3+ , directory >= 1.1+ , QuickCheck >= 2.0+ , template-haskell >= 2.8++ ghc-options:+ -Wall+ -threaded++ hs-source-dirs:+ test
+ test/doctests.hs view
@@ -0,0 +1,32 @@+module Main where++import Build_doctests (deps)+import Control.Applicative+import Control.Monad+import Data.List+import System.Directory+import System.FilePath+import Test.DocTest++main ::+ IO ()+main =+ getSources >>= \sources -> doctest $+ "-isrc"+ : "-idist/build/autogen"+ : "-optP-include"+ : "-optPdist/build/autogen/cabal_macros.h"+ : "-hide-all-packages"+ : map ("-package="++) deps ++ sources++getSources :: IO [FilePath]+getSources = filter (isSuffixOf ".hs") <$> go "src"+ where+ go dir = do+ (dirs, files) <- getFilesAndDirectories dir+ (files ++) . concat <$> mapM go dirs++getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])+getFilesAndDirectories dir = do+ c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir+ (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c