rattletrap 4.1.2 → 5.0.0
raw patch · 16 files changed
+303/−52 lines, 16 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Rattletrap: [rigidBodyStateAttributeUnknown1] :: RigidBodyStateAttribute -> Maybe Bool
- Rattletrap: [rigidBodyStateAttributeUnknown2] :: RigidBodyStateAttribute -> Maybe Bool
- Rattletrap.Type.RigidBodyStateAttribute: [rigidBodyStateAttributeUnknown1] :: RigidBodyStateAttribute -> Maybe Bool
- Rattletrap.Type.RigidBodyStateAttribute: [rigidBodyStateAttributeUnknown2] :: RigidBodyStateAttribute -> Maybe Bool
+ Rattletrap.Decode.Quaternion: decodeQuaternionBits :: DecodeBits Quaternion
+ Rattletrap.Decode.Rotation: decodeRotationBits :: (Int, Int, Int) -> DecodeBits Rotation
+ Rattletrap.Encode.Quaternion: putQuaternion :: Quaternion -> BitPut ()
+ Rattletrap.Encode.Rotation: putRotation :: Rotation -> BitPut ()
+ Rattletrap.Type.Quaternion: ComponentW :: Component
+ Rattletrap.Type.Quaternion: ComponentX :: Component
+ Rattletrap.Type.Quaternion: ComponentY :: Component
+ Rattletrap.Type.Quaternion: ComponentZ :: Component
+ Rattletrap.Type.Quaternion: Quaternion :: Double -> Double -> Double -> Double -> Quaternion
+ Rattletrap.Type.Quaternion: [quaternionW] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: [quaternionX] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: [quaternionY] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: [quaternionZ] :: Quaternion -> Double
+ Rattletrap.Type.Quaternion: compressPart :: Double -> CompressedWord
+ Rattletrap.Type.Quaternion: data Component
+ Rattletrap.Type.Quaternion: data Quaternion
+ Rattletrap.Type.Quaternion: decompressPart :: CompressedWord -> Double
+ Rattletrap.Type.Quaternion: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance GHC.Classes.Eq Rattletrap.Type.Quaternion.Component
+ Rattletrap.Type.Quaternion: instance GHC.Classes.Eq Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance GHC.Classes.Ord Rattletrap.Type.Quaternion.Component
+ Rattletrap.Type.Quaternion: instance GHC.Classes.Ord Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: instance GHC.Show.Show Rattletrap.Type.Quaternion.Component
+ Rattletrap.Type.Quaternion: instance GHC.Show.Show Rattletrap.Type.Quaternion.Quaternion
+ Rattletrap.Type.Quaternion: maxComponent :: Quaternion -> Component
+ Rattletrap.Type.Quaternion: maxCompressedValue :: Word
+ Rattletrap.Type.Quaternion: toPart :: Double -> Double -> Double -> Double
+ Rattletrap.Type.Quaternion: toQuaternion :: Component -> Double -> Double -> Double -> Quaternion
+ Rattletrap.Type.Rotation: RotationCompressedWordVector :: CompressedWordVector -> Rotation
+ Rattletrap.Type.Rotation: RotationQuaternion :: Quaternion -> Rotation
+ Rattletrap.Type.Rotation: data Rotation
+ Rattletrap.Type.Rotation: instance Data.Aeson.Types.FromJSON.FromJSON Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance Data.Aeson.Types.ToJSON.ToJSON Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance GHC.Classes.Eq Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance GHC.Classes.Ord Rattletrap.Type.Rotation.Rotation
+ Rattletrap.Type.Rotation: instance GHC.Show.Show Rattletrap.Type.Rotation.Rotation
- Rattletrap: RigidBodyStateAttribute :: Bool -> Vector -> Maybe Bool -> CompressedWordVector -> Maybe Bool -> Maybe Vector -> Maybe Vector -> RigidBodyStateAttribute
+ Rattletrap: RigidBodyStateAttribute :: Bool -> Vector -> Rotation -> Maybe Vector -> Maybe Vector -> RigidBodyStateAttribute
- Rattletrap: [rigidBodyStateAttributeRotation] :: RigidBodyStateAttribute -> CompressedWordVector
+ Rattletrap: [rigidBodyStateAttributeRotation] :: RigidBodyStateAttribute -> Rotation
- Rattletrap.Decode.CompressedWordVector: decodeCompressedWordVectorBits :: (Int, Int, Int) -> DecodeBits CompressedWordVector
+ Rattletrap.Decode.CompressedWordVector: decodeCompressedWordVectorBits :: DecodeBits CompressedWordVector
- Rattletrap.Type.RigidBodyStateAttribute: RigidBodyStateAttribute :: Bool -> Vector -> Maybe Bool -> CompressedWordVector -> Maybe Bool -> Maybe Vector -> Maybe Vector -> RigidBodyStateAttribute
+ Rattletrap.Type.RigidBodyStateAttribute: RigidBodyStateAttribute :: Bool -> Vector -> Rotation -> Maybe Vector -> Maybe Vector -> RigidBodyStateAttribute
- Rattletrap.Type.RigidBodyStateAttribute: [rigidBodyStateAttributeRotation] :: RigidBodyStateAttribute -> CompressedWordVector
+ Rattletrap.Type.RigidBodyStateAttribute: [rigidBodyStateAttributeRotation] :: RigidBodyStateAttribute -> Rotation
Files
- library/Rattletrap/Data.hs +9/−1
- library/Rattletrap/Decode/CompressedWordVector.hs +7/−7
- library/Rattletrap/Decode/Quaternion.hs +26/−0
- library/Rattletrap/Decode/Replay.hs +12/−1
- library/Rattletrap/Decode/RigidBodyStateAttribute.hs +2/−4
- library/Rattletrap/Decode/Rotation.hs +14/−0
- library/Rattletrap/Encode/Quaternion.hs +41/−0
- library/Rattletrap/Encode/RigidBodyStateAttribute.hs +2/−4
- library/Rattletrap/Encode/Rotation.hs +15/−0
- library/Rattletrap/Type/Quaternion.hs +100/−0
- library/Rattletrap/Type/RigidBodyStateAttribute.hs +2/−4
- library/Rattletrap/Type/Rotation.hs +17/−0
- library/Rattletrap/Utility/Bytes.hs +6/−1
- package.yaml +3/−1
- rattletrap.cabal +11/−5
- tests/Main.hs +36/−24
library/Rattletrap/Data.hs view
@@ -1,4 +1,11 @@-module Rattletrap.Data where+module Rattletrap.Data+ ( rawParentClasses+ , rawClassesWithLocation+ , rawClassesWithRotation+ , rawObjectClasses+ , rawAttributeTypes+ , rawCrc32Table+ ) where import Rattletrap.Type.AttributeType @@ -123,6 +130,7 @@ , ("Archetypes.GameEvent.GameEvent_Season:CarArchetype", "TAGame.Car_TA") , ("Archetypes.GameEvent.GameEvent_Season", "TAGame.GameEvent_Season_TA") , ("Archetypes.GameEvent.GameEvent_Soccar", "TAGame.GameEvent_Soccar_TA")+ , ("Archetypes.GameEvent.GameEvent_SoccarLan", "TAGame.GameEvent_Soccar_TA") , ("Archetypes.GameEvent.GameEvent_SoccarPrivate", "TAGame.GameEvent_SoccarPrivate_TA") , ("Archetypes.GameEvent.GameEvent_SoccarSplitscreen", "TAGame.GameEvent_SoccarSplitscreen_TA") , ("Archetypes.SpecialPickups.SpecialPickup_BallFreeze", "TAGame.SpecialPickup_BallFreeze_TA")
library/Rattletrap/Decode/CompressedWordVector.hs view
@@ -6,12 +6,12 @@ import Rattletrap.Decode.CompressedWord import Rattletrap.Type.CompressedWordVector -decodeCompressedWordVectorBits :: (Int, Int, Int) -> DecodeBits CompressedWordVector-decodeCompressedWordVectorBits version =+decodeCompressedWordVectorBits :: DecodeBits CompressedWordVector+decodeCompressedWordVectorBits = CompressedWordVector- <$> decodeCompressedWordBits (limit version)- <*> decodeCompressedWordBits (limit version)- <*> decodeCompressedWordBits (limit version)+ <$> decodeCompressedWordBits limit+ <*> decodeCompressedWordBits limit+ <*> decodeCompressedWordBits limit -limit :: (Int, Int, Int) -> Word-limit version = if version >= (868, 22, 7) then 262144 else 65536+limit :: Word+limit = 65536
+ library/Rattletrap/Decode/Quaternion.hs view
@@ -0,0 +1,26 @@+module Rattletrap.Decode.Quaternion+ ( decodeQuaternionBits+ )+where++import Rattletrap.Decode.Common+import Rattletrap.Decode.CompressedWord+import Rattletrap.Type.CompressedWord+import Rattletrap.Type.Quaternion++decodeQuaternionBits :: DecodeBits Quaternion+decodeQuaternionBits =+ toQuaternion <$> decodeComponent <*> decodePart <*> decodePart <*> decodePart++decodeComponent :: DecodeBits Component+decodeComponent = do+ x <- decodeCompressedWordBits 3+ case compressedWordValue x of+ 0 -> pure ComponentX+ 1 -> pure ComponentY+ 2 -> pure ComponentZ+ 3 -> pure ComponentW+ y -> fail ("invalid component: " <> show y)++decodePart :: DecodeBits Double+decodePart = decompressPart <$> decodeCompressedWordBits maxCompressedValue
library/Rattletrap/Decode/Replay.hs view
@@ -30,8 +30,19 @@ getVersion header = ( fromIntegral (word32leValue (headerEngineVersion header)) , fromIntegral (word32leValue (headerLicenseeVersion header))- , maybe 0 (fromIntegral . word32leValue) (headerPatchVersion header)+ , getPatchVersion header )++getPatchVersion :: Header -> Int+getPatchVersion header = case headerPatchVersion header of+ Just version -> fromIntegral (word32leValue version)+ Nothing ->+ case dictionaryLookup (toStr "MatchType") (headerProperties header) of+ -- This is an ugly, ugly hack to handle replays from season 2 of RLCS.+ -- See `decodeSpawnedReplicationBits` and #85.+ Just Property { propertyValue = PropertyValueName str }+ | fromStr str == "Lan" -> -1+ _ -> 0 getNumFrames :: Header -> Int getNumFrames header =
library/Rattletrap/Decode/RigidBodyStateAttribute.hs view
@@ -3,7 +3,7 @@ ) where import Rattletrap.Decode.Common-import Rattletrap.Decode.CompressedWordVector+import Rattletrap.Decode.Rotation import Rattletrap.Decode.Vector import Rattletrap.Type.RigidBodyStateAttribute @@ -12,8 +12,6 @@ sleeping <- getBool RigidBodyStateAttribute sleeping <$> decodeVectorBits version- <*> decodeWhen (version >= (868, 22, 7)) getBool- <*> decodeCompressedWordVectorBits version- <*> decodeWhen (version >= (868, 22, 7)) getBool+ <*> decodeRotationBits version <*> decodeWhen (not sleeping) (decodeVectorBits version) <*> decodeWhen (not sleeping) (decodeVectorBits version)
+ library/Rattletrap/Decode/Rotation.hs view
@@ -0,0 +1,14 @@+module Rattletrap.Decode.Rotation+ ( decodeRotationBits+ )+where++import Rattletrap.Decode.Common+import Rattletrap.Decode.CompressedWordVector+import Rattletrap.Decode.Quaternion+import Rattletrap.Type.Rotation++decodeRotationBits :: (Int, Int, Int) -> DecodeBits Rotation+decodeRotationBits version = if version >= (868, 22, 7)+ then RotationQuaternion <$> decodeQuaternionBits+ else RotationCompressedWordVector <$> decodeCompressedWordVectorBits
+ library/Rattletrap/Encode/Quaternion.hs view
@@ -0,0 +1,41 @@+module Rattletrap.Encode.Quaternion+ ( putQuaternion+ )+where++import Rattletrap.Encode.CompressedWord+import Rattletrap.Type.CompressedWord+import Rattletrap.Type.Quaternion++import qualified Data.Binary.Bits.Put as BinaryBits++putQuaternion :: Quaternion -> BinaryBits.BitPut ()+putQuaternion q = do+ let c = maxComponent q+ putComponent c+ case c of+ ComponentX -> putParts (quaternionY q) (quaternionZ q) (quaternionW q)+ ComponentY -> putParts (quaternionX q) (quaternionZ q) (quaternionW q)+ ComponentZ -> putParts (quaternionX q) (quaternionY q) (quaternionW q)+ ComponentW -> putParts (quaternionX q) (quaternionY q) (quaternionZ q)++putComponent :: Component -> BinaryBits.BitPut ()+putComponent component = putCompressedWord+ (CompressedWord+ 3+ (case component of+ ComponentX -> 0+ ComponentY -> 1+ ComponentZ -> 2+ ComponentW -> 3+ )+ )++putParts :: Double -> Double -> Double -> BinaryBits.BitPut ()+putParts a b c = do+ putPart a+ putPart b+ putPart c++putPart :: Double -> BinaryBits.BitPut ()+putPart = putCompressedWord . compressPart
library/Rattletrap/Encode/RigidBodyStateAttribute.hs view
@@ -2,7 +2,7 @@ ( putRigidBodyStateAttribute ) where -import Rattletrap.Encode.CompressedWordVector+import Rattletrap.Encode.Rotation import Rattletrap.Encode.Vector import Rattletrap.Type.RigidBodyStateAttribute @@ -12,10 +12,8 @@ putRigidBodyStateAttribute rigidBodyStateAttribute = do BinaryBits.putBool (rigidBodyStateAttributeSleeping rigidBodyStateAttribute) putVector (rigidBodyStateAttributeLocation rigidBodyStateAttribute)- maybe (pure ()) BinaryBits.putBool (rigidBodyStateAttributeUnknown1 rigidBodyStateAttribute)- putCompressedWordVector+ putRotation (rigidBodyStateAttributeRotation rigidBodyStateAttribute)- maybe (pure ()) BinaryBits.putBool (rigidBodyStateAttributeUnknown2 rigidBodyStateAttribute) case rigidBodyStateAttributeLinearVelocity rigidBodyStateAttribute of Nothing -> pure () Just linearVelocity -> putVector linearVelocity
+ library/Rattletrap/Encode/Rotation.hs view
@@ -0,0 +1,15 @@+module Rattletrap.Encode.Rotation+ ( putRotation+ )+where++import Rattletrap.Encode.CompressedWordVector+import Rattletrap.Encode.Quaternion+import Rattletrap.Type.Rotation++import qualified Data.Binary.Bits.Put as BinaryBits++putRotation :: Rotation -> BinaryBits.BitPut ()+putRotation r = case r of+ RotationCompressedWordVector cwv -> putCompressedWordVector cwv+ RotationQuaternion q -> putQuaternion q
+ library/Rattletrap/Type/Quaternion.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE TemplateHaskell #-}++module Rattletrap.Type.Quaternion+ ( Quaternion(..)+ , Component(..)+ , toQuaternion+ , toPart+ , compressPart+ , decompressPart+ , maxComponent+ , maxCompressedValue+ )+where++import Rattletrap.Type.Common+import Rattletrap.Type.CompressedWord++import qualified Data.Maybe as Maybe++data Quaternion = Quaternion+ { quaternionX :: Double+ , quaternionY :: Double+ , quaternionZ :: Double+ , quaternionW :: Double+ } deriving (Eq, Ord, Show)++$(deriveJson ''Quaternion)++data Component+ = ComponentX+ | ComponentY+ | ComponentZ+ | ComponentW+ deriving (Eq, Ord, Show)++toQuaternion :: Component -> Double -> Double -> Double -> Quaternion+toQuaternion component a b c =+ let d = toPart a b c+ in+ case component of+ ComponentX -> Quaternion d a b c+ ComponentY -> Quaternion a d b c+ ComponentZ -> Quaternion a b d c+ ComponentW -> Quaternion a b c d++toPart :: Double -> Double -> Double -> Double+toPart a b c = sqrt (1 - (a * a) - (b * b) - (c * c))++compressPart :: Double -> CompressedWord+compressPart =+ CompressedWord maxCompressedValue+ . round+ . (* wordToDouble maxCompressedValue)+ . (+ 0.5)+ . (/ 2.0)+ . (/ maxValue)++decompressPart :: CompressedWord -> Double+decompressPart x =+ (* maxValue)+ . (* 2.0)+ . subtract 0.5+ . (/ wordToDouble (compressedWordLimit x))+ . wordToDouble+ $ compressedWordValue x++maxComponent :: Quaternion -> Component+maxComponent quaternion+ = let+ x = quaternionX quaternion+ y = quaternionY quaternion+ z = quaternionZ quaternion+ w = quaternionW quaternion+ parts =+ [(x, ComponentX), (y, ComponentY), (z, ComponentZ), (w, ComponentW)]+ biggestPart = maximum parts+ roundTrip = decompressPart . compressPart+ computedPart = Maybe.fromMaybe+ biggestPart+ (Maybe.listToMaybe+ (filter (\(value, _) -> value /= roundTrip value) parts)+ )+ in snd+ (if (biggestPart == computedPart)+ || (abs (fst biggestPart - fst computedPart) > 0.00001)+ then biggestPart+ else computedPart+ )++numBits :: Word+numBits = 18++wordToDouble :: Word -> Double+wordToDouble = fromIntegral++maxCompressedValue :: Word+maxCompressedValue = (2 ^ numBits) - 1++maxValue :: Double+maxValue = 1.0 / sqrt 2.0
library/Rattletrap/Type/RigidBodyStateAttribute.hs view
@@ -5,15 +5,13 @@ ) where import Rattletrap.Type.Common-import Rattletrap.Type.CompressedWordVector+import Rattletrap.Type.Rotation import Rattletrap.Type.Vector data RigidBodyStateAttribute = RigidBodyStateAttribute { rigidBodyStateAttributeSleeping :: Bool , rigidBodyStateAttributeLocation :: Vector- , rigidBodyStateAttributeUnknown1 :: Maybe Bool- , rigidBodyStateAttributeRotation :: CompressedWordVector- , rigidBodyStateAttributeUnknown2 :: Maybe Bool+ , rigidBodyStateAttributeRotation :: Rotation , rigidBodyStateAttributeLinearVelocity :: Maybe Vector , rigidBodyStateAttributeAngularVelocity :: Maybe Vector } deriving (Eq, Ord, Show)
+ library/Rattletrap/Type/Rotation.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE TemplateHaskell #-}++module Rattletrap.Type.Rotation+ ( Rotation(..)+ )+where++import Rattletrap.Type.Common+import Rattletrap.Type.Quaternion+import Rattletrap.Type.CompressedWordVector++data Rotation+ = RotationCompressedWordVector CompressedWordVector+ | RotationQuaternion Quaternion+ deriving (Eq, Ord, Show)++$(deriveJson ''Rotation)
library/Rattletrap/Utility/Bytes.hs view
@@ -1,4 +1,9 @@-module Rattletrap.Utility.Bytes where+module Rattletrap.Utility.Bytes+ ( encodeLatin1+ , padBytes+ , reverseByte+ , reverseBytes+ ) where import qualified Data.Bits as Bits import qualified Data.ByteString.Lazy as LazyBytes
package.yaml view
@@ -1,5 +1,5 @@ name: rattletrap-version: 4.1.2+version: 5.0.0 category: Game description: Rattletrap parses and generates Rocket League replays.@@ -31,7 +31,9 @@ ghc-options: - -optP -Wno-nonportable-include-path # https://github.com/haskell/cabal/issues/4739 - -Weverything+ - -Wno-all-missed-specialisations - -Wno-implicit-prelude+ - -Wno-missing-exported-signatures # https://ghc.haskell.org/trac/ghc/ticket/14794 - -Wno-missing-import-lists - -Wno-safe - -Wno-unsafe
rattletrap.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: f97575be8798337622664b2f229d5417b0e7e29fefe6a61109a65cb02abb3208+-- hash: 9ba2a9aa65fbdd16f1e3edc2524f922e6ffb9e794cd408c41397f03c5cb37ad8 name: rattletrap-version: 4.1.2+version: 5.0.0 synopsis: Parse and generate Rocket League replays. description: Rattletrap parses and generates Rocket League replays. category: Game@@ -85,6 +85,7 @@ Rattletrap.Decode.ProductAttribute Rattletrap.Decode.Property Rattletrap.Decode.PropertyValue+ Rattletrap.Decode.Quaternion Rattletrap.Decode.QWordAttribute Rattletrap.Decode.RemoteId Rattletrap.Decode.Replay@@ -92,6 +93,7 @@ Rattletrap.Decode.ReplicationValue Rattletrap.Decode.ReservationAttribute Rattletrap.Decode.RigidBodyStateAttribute+ Rattletrap.Decode.Rotation Rattletrap.Decode.Section Rattletrap.Decode.SpawnedReplication Rattletrap.Decode.StatEventAttribute@@ -155,6 +157,7 @@ Rattletrap.Encode.ProductAttribute Rattletrap.Encode.Property Rattletrap.Encode.PropertyValue+ Rattletrap.Encode.Quaternion Rattletrap.Encode.QWordAttribute Rattletrap.Encode.RemoteId Rattletrap.Encode.Replay@@ -162,6 +165,7 @@ Rattletrap.Encode.ReplicationValue Rattletrap.Encode.ReservationAttribute Rattletrap.Encode.RigidBodyStateAttribute+ Rattletrap.Encode.Rotation Rattletrap.Encode.Section Rattletrap.Encode.SpawnedReplication Rattletrap.Encode.StatEventAttribute@@ -228,6 +232,7 @@ Rattletrap.Type.ProductAttribute Rattletrap.Type.Property Rattletrap.Type.PropertyValue+ Rattletrap.Type.Quaternion Rattletrap.Type.QWordAttribute Rattletrap.Type.RemoteId Rattletrap.Type.Replay@@ -235,6 +240,7 @@ Rattletrap.Type.ReplicationValue Rattletrap.Type.ReservationAttribute Rattletrap.Type.RigidBodyStateAttribute+ Rattletrap.Type.Rotation Rattletrap.Type.Section Rattletrap.Type.SpawnedReplication Rattletrap.Type.StatEventAttribute@@ -256,7 +262,7 @@ Paths_rattletrap hs-source-dirs: library- ghc-options: -optP -Wno-nonportable-include-path -Weverything -Wno-implicit-prelude -Wno-missing-import-lists -Wno-safe -Wno-unsafe+ ghc-options: -optP -Wno-nonportable-include-path -Weverything -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-safe -Wno-unsafe build-depends: aeson >=1.2.4 && <1.5 , aeson-pretty >=0.8.5 && <0.9@@ -279,7 +285,7 @@ Paths_rattletrap hs-source-dirs: executables- ghc-options: -optP -Wno-nonportable-include-path -Weverything -Wno-implicit-prelude -Wno-missing-import-lists -Wno-safe -Wno-unsafe -rtsopts -threaded+ ghc-options: -optP -Wno-nonportable-include-path -Weverything -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-safe -Wno-unsafe -rtsopts -threaded build-depends: aeson >=1.2.4 && <1.5 , aeson-pretty >=0.8.5 && <0.9@@ -306,7 +312,7 @@ Paths_rattletrap hs-source-dirs: tests- ghc-options: -optP -Wno-nonportable-include-path -Weverything -Wno-implicit-prelude -Wno-missing-import-lists -Wno-safe -Wno-unsafe -rtsopts -threaded+ ghc-options: -optP -Wno-nonportable-include-path -Weverything -Wno-all-missed-specialisations -Wno-implicit-prelude -Wno-missing-exported-signatures -Wno-missing-import-lists -Wno-safe -Wno-unsafe -rtsopts -threaded build-depends: HUnit >=1.6.0 && <1.7 , aeson >=1.2.4 && <1.5
tests/Main.hs view
@@ -1,17 +1,26 @@-import Control.Exception (displayException, try)-import Control.Monad (unless)-import Data.ByteString.Lazy (readFile)-import Prelude hiding (readFile)-import Rattletrap.Console.Main (rattletrap)-import System.FilePath (addExtension, joinPath)-import System.IO.Temp (withSystemTempDirectory)-import Text.Printf (printf)+module Main+ ( main+ )+where +import qualified Control.Monad as Monad+import qualified Data.ByteString.Lazy as Bytes+import qualified Rattletrap.Console.Main as Rattletrap+import qualified System.Exit as Exit+import qualified System.FilePath as Path+import qualified System.IO.Temp as Temp import qualified Test.HUnit as Test -main :: IO Test.Counts-main = withSystemTempDirectory "rattletrap-" (Test.runTestTT . toTests)+main :: IO ()+main = Temp.withSystemTempDirectory "rattletrap-" (runTests . toTests) +runTests :: Test.Test -> IO ()+runTests test = do+ result <- Test.runTestTT test+ Monad.when+ (Test.errors result > 0 || Test.failures result > 0)+ Exit.exitFailure+ toTests :: FilePath -> Test.Test toTests directory = Test.TestList (fmap (toTest directory) replays) @@ -21,23 +30,23 @@ (Test.TestCase (toAssertion directory uuid)) toLabel :: String -> String -> String-toLabel = printf "%s: %s"+toLabel uuid name = uuid <> ": " <> name toAssertion :: FilePath -> String -> Test.Assertion toAssertion directory uuid = do- let inputFile = joinPath ["replays", addExtension uuid ".replay"]- result <- try (readFile inputFile)- case result of- Left problem -> putStrLn (displayException (problem :: IOError))- Right input -> do- let jsonFile = joinPath [directory, addExtension uuid ".json"]- rattletrap "" ["--compact", "--input", inputFile, "--output", jsonFile]- let outputFile = joinPath [directory, addExtension uuid ".replay"]- rattletrap "" ["--input", jsonFile, "--output", outputFile]- output <- readFile outputFile- unless- (output == input)- (Test.assertFailure "output does not match input")+ let+ inputFile = Path.joinPath ["replays", Path.addExtension uuid ".replay"]+ jsonFile = Path.joinPath [directory, Path.addExtension uuid ".json"]+ outputFile = Path.joinPath [directory, Path.addExtension uuid ".replay"]+ input <- Bytes.readFile inputFile+ Rattletrap.rattletrap+ ""+ ["--compact", "--input", inputFile, "--output", jsonFile]+ Rattletrap.rattletrap "" ["--input", jsonFile, "--output", outputFile]+ output <- Bytes.readFile outputFile+ Monad.unless+ (output == input)+ (Test.assertFailure "output does not match input") replays :: [(String, String)] replays =@@ -64,11 +73,13 @@ , ("3381", "patch 1.37") , ("372d", "a camera yaw attribute") , ("387f", "a frozen attribute")+ , ("3abd", "rlcs") , ("3ea1", "a custom team name") , ("4126", "a game mode after Neo Tokyo") , ("42f0", "reservations after Neo Tokyo") , ("504e", "some messages") , ("520e", "no pickup attribute")+ , ("524f", "quat edge case") , ("52aa", "a match-ending attribute") , ("540d", "a demolish attribute") , ("551c", "private match settings")@@ -101,6 +112,7 @@ , ("c837", "a spectator") , ("cc4c", "after Starbase ARC") , ("d044", "hoops mutators")+ , ("d236", "rlcs s2") , ("d428", "a private hockey match") , ("d7fb", "an explosion attribute") , ("db70", "new lag indicator")