{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module MyLib where
import Data.Aeson
import Data.Aeson.Text
import qualified Data.ByteString as BS
import Data.Either
import Data.Int (Int64)
import qualified Data.Text.Lazy as T
import Data.Time
import GHC.Generics
import System.AtomicWrite.Writer.LazyText
import System.Directory (
XdgDirectory (XdgData),
createDirectoryIfMissing,
doesFileExist,
getXdgDirectory,
)
someFunc :: IO ()
someFunc :: IO ()
someFunc = FilePath -> IO ()
putStrLn FilePath
"someFunc"
data Run = Run
{ Run -> UTCTime
tstamp :: !UTCTime
, Run -> Text
cmdline :: !T.Text
, Run -> Text
cwd :: !T.Text
, Run -> Double
runTime :: !Double
, Run -> Double
cpuTime :: !Double
, Run -> Int64
cpuCycles :: !Int64
}
deriving (Int -> Run -> ShowS
[Run] -> ShowS
Run -> FilePath
(Int -> Run -> ShowS)
-> (Run -> FilePath) -> ([Run] -> ShowS) -> Show Run
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Run -> ShowS
showsPrec :: Int -> Run -> ShowS
$cshow :: Run -> FilePath
show :: Run -> FilePath
$cshowList :: [Run] -> ShowS
showList :: [Run] -> ShowS
Show, Run -> Run -> Bool
(Run -> Run -> Bool) -> (Run -> Run -> Bool) -> Eq Run
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Run -> Run -> Bool
== :: Run -> Run -> Bool
$c/= :: Run -> Run -> Bool
/= :: Run -> Run -> Bool
Eq, Eq Run
Eq Run =>
(Run -> Run -> Ordering)
-> (Run -> Run -> Bool)
-> (Run -> Run -> Bool)
-> (Run -> Run -> Bool)
-> (Run -> Run -> Bool)
-> (Run -> Run -> Run)
-> (Run -> Run -> Run)
-> Ord Run
Run -> Run -> Bool
Run -> Run -> Ordering
Run -> Run -> Run
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Run -> Run -> Ordering
compare :: Run -> Run -> Ordering
$c< :: Run -> Run -> Bool
< :: Run -> Run -> Bool
$c<= :: Run -> Run -> Bool
<= :: Run -> Run -> Bool
$c> :: Run -> Run -> Bool
> :: Run -> Run -> Bool
$c>= :: Run -> Run -> Bool
>= :: Run -> Run -> Bool
$cmax :: Run -> Run -> Run
max :: Run -> Run -> Run
$cmin :: Run -> Run -> Run
min :: Run -> Run -> Run
Ord, (forall x. Run -> Rep Run x)
-> (forall x. Rep Run x -> Run) -> Generic Run
forall x. Rep Run x -> Run
forall x. Run -> Rep Run x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Run -> Rep Run x
from :: forall x. Run -> Rep Run x
$cto :: forall x. Rep Run x -> Run
to :: forall x. Rep Run x -> Run
Generic, [Run] -> Value
[Run] -> Encoding
Run -> Value
Run -> Encoding
(Run -> Value)
-> (Run -> Encoding)
-> ([Run] -> Value)
-> ([Run] -> Encoding)
-> ToJSON Run
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: Run -> Value
toJSON :: Run -> Value
$ctoEncoding :: Run -> Encoding
toEncoding :: Run -> Encoding
$ctoJSONList :: [Run] -> Value
toJSONList :: [Run] -> Value
$ctoEncodingList :: [Run] -> Encoding
toEncodingList :: [Run] -> Encoding
ToJSON, Value -> Parser [Run]
Value -> Parser Run
(Value -> Parser Run) -> (Value -> Parser [Run]) -> FromJSON Run
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser Run
parseJSON :: Value -> Parser Run
$cparseJSONList :: Value -> Parser [Run]
parseJSONList :: Value -> Parser [Run]
FromJSON)
data Runs = Runs
{ Runs -> [Run]
rs :: ![Run]
}
deriving (Int -> Runs -> ShowS
[Runs] -> ShowS
Runs -> FilePath
(Int -> Runs -> ShowS)
-> (Runs -> FilePath) -> ([Runs] -> ShowS) -> Show Runs
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Runs -> ShowS
showsPrec :: Int -> Runs -> ShowS
$cshow :: Runs -> FilePath
show :: Runs -> FilePath
$cshowList :: [Runs] -> ShowS
showList :: [Runs] -> ShowS
Show, Runs -> Runs -> Bool
(Runs -> Runs -> Bool) -> (Runs -> Runs -> Bool) -> Eq Runs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Runs -> Runs -> Bool
== :: Runs -> Runs -> Bool
$c/= :: Runs -> Runs -> Bool
/= :: Runs -> Runs -> Bool
Eq, Eq Runs
Eq Runs =>
(Runs -> Runs -> Ordering)
-> (Runs -> Runs -> Bool)
-> (Runs -> Runs -> Bool)
-> (Runs -> Runs -> Bool)
-> (Runs -> Runs -> Bool)
-> (Runs -> Runs -> Runs)
-> (Runs -> Runs -> Runs)
-> Ord Runs
Runs -> Runs -> Bool
Runs -> Runs -> Ordering
Runs -> Runs -> Runs
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Runs -> Runs -> Ordering
compare :: Runs -> Runs -> Ordering
$c< :: Runs -> Runs -> Bool
< :: Runs -> Runs -> Bool
$c<= :: Runs -> Runs -> Bool
<= :: Runs -> Runs -> Bool
$c> :: Runs -> Runs -> Bool
> :: Runs -> Runs -> Bool
$c>= :: Runs -> Runs -> Bool
>= :: Runs -> Runs -> Bool
$cmax :: Runs -> Runs -> Runs
max :: Runs -> Runs -> Runs
$cmin :: Runs -> Runs -> Runs
min :: Runs -> Runs -> Runs
Ord, (forall x. Runs -> Rep Runs x)
-> (forall x. Rep Runs x -> Runs) -> Generic Runs
forall x. Rep Runs x -> Runs
forall x. Runs -> Rep Runs x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Runs -> Rep Runs x
from :: forall x. Runs -> Rep Runs x
$cto :: forall x. Rep Runs x -> Runs
to :: forall x. Rep Runs x -> Runs
Generic, [Runs] -> Value
[Runs] -> Encoding
Runs -> Value
Runs -> Encoding
(Runs -> Value)
-> (Runs -> Encoding)
-> ([Runs] -> Value)
-> ([Runs] -> Encoding)
-> ToJSON Runs
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: Runs -> Value
toJSON :: Runs -> Value
$ctoEncoding :: Runs -> Encoding
toEncoding :: Runs -> Encoding
$ctoJSONList :: [Runs] -> Value
toJSONList :: [Runs] -> Value
$ctoEncodingList :: [Runs] -> Encoding
toEncodingList :: [Runs] -> Encoding
ToJSON, Value -> Parser [Runs]
Value -> Parser Runs
(Value -> Parser Runs) -> (Value -> Parser [Runs]) -> FromJSON Runs
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
$cparseJSON :: Value -> Parser Runs
parseJSON :: Value -> Parser Runs
$cparseJSONList :: Value -> Parser [Runs]
parseJSONList :: Value -> Parser [Runs]
FromJSON)
readSandWatchData :: IO Runs
readSandWatchData :: IO Runs
readSandWatchData = do
FilePath
sandWatchDataFile <- IO FilePath
getSandWatchFilePath
Bool
dataExists <- FilePath -> IO Bool
doesFileExist FilePath
sandWatchDataFile
if Bool -> Bool
not Bool
dataExists
then Runs -> IO Runs
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Runs -> IO Runs) -> Runs -> IO Runs
forall a b. (a -> b) -> a -> b
$ [Run] -> Runs
Runs []
else do
ByteString
contents <- FilePath -> IO ByteString
BS.readFile FilePath
sandWatchDataFile
Runs -> IO Runs
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Runs -> IO Runs) -> Runs -> IO Runs
forall a b. (a -> b) -> a -> b
$ Runs -> Either FilePath Runs -> Runs
forall b a. b -> Either a b -> b
fromRight ([Run] -> Runs
Runs []) (ByteString -> Either FilePath Runs
forall a. FromJSON a => ByteString -> Either FilePath a
eitherDecodeStrict ByteString
contents)
writeSandWatchData :: Runs -> IO ()
writeSandWatchData :: Runs -> IO ()
writeSandWatchData Runs
rs' = do
FilePath
sandWatchDataFile <- IO FilePath
getSandWatchFilePath
FilePath -> Text -> IO ()
atomicWriteFile FilePath
sandWatchDataFile (Runs -> Text
forall a. ToJSON a => a -> Text
encodeToLazyText Runs
rs')
getSandWatchFilePath :: IO FilePath
getSandWatchFilePath :: IO FilePath
getSandWatchFilePath = do
FilePath
sandWatchDir <- XdgDirectory -> FilePath -> IO FilePath
getXdgDirectory XdgDirectory
XdgData FilePath
"sandwatch"
Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True FilePath
sandWatchDir
FilePath -> IO FilePath
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FilePath -> IO FilePath) -> FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
sandWatchDir FilePath -> ShowS
forall a. Semigroup a => a -> a -> a
<> FilePath
"/runs"
filterByCWD :: Runs -> T.Text -> Runs
filterByCWD :: Runs -> Text -> Runs
filterByCWD Runs
runs Text
thiscwd = [Run] -> Runs
Runs ([Run] -> Runs) -> [Run] -> Runs
forall a b. (a -> b) -> a -> b
$ (Run -> Bool) -> [Run] -> [Run]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Run
r -> Text -> Text
T.strip Text
thiscwd Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Run -> Text
cwd Run
r) (Runs -> [Run]
rs Runs
runs)
filterByFirstWord :: Runs -> T.Text -> Runs
filterByFirstWord :: Runs -> Text -> Runs
filterByFirstWord Runs
runs Text
thiscmdline = [Run] -> Runs
Runs ([Run] -> Runs) -> [Run] -> Runs
forall a b. (a -> b) -> a -> b
$ (Run -> Bool) -> [Run] -> [Run]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Run
r -> Text -> Text
fstWord Text
thiscmdline Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text -> Text
fstWord (Run -> Text
cmdline Run
r)) (Runs -> [Run]
rs Runs
runs)
where
fstWord :: Text -> Text
fstWord = (Text, Text) -> Text
forall a b. (a, b) -> a
fst ((Text, Text) -> Text) -> (Text -> (Text, Text)) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
T.breakOn Text
" "
filterByFirstNWords :: Runs -> Int -> T.Text -> Runs
filterByFirstNWords :: Runs -> Int -> Text -> Runs
filterByFirstNWords Runs
runs Int
n Text
thiscmdline = [Run] -> Runs
Runs ([Run] -> Runs) -> [Run] -> Runs
forall a b. (a -> b) -> a -> b
$ (Run -> Bool) -> [Run] -> [Run]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Run
r -> Int -> Text -> [Text]
fstWords Int
n Text
thiscmdline [Text] -> [Text] -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Text -> [Text]
fstWords Int
n (Run -> Text
cmdline Run
r)) (Runs -> [Run]
rs Runs
runs)
where
fstWords :: Int -> Text -> [Text]
fstWords Int
n' Text
c = Int -> [Text] -> [Text]
forall a. Int -> [a] -> [a]
take Int
n' ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$ HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
T.splitOn Text
" " Text
c
guessTime :: Int -> Runs -> Run -> Double
guessTime :: Int -> Runs -> Run -> Double
guessTime Int
n Runs
pastruns Run
thisrun = Double
avgWallSeconds
where
runsInThisDir :: Runs
runsInThisDir = Runs -> Text -> Runs
filterByCWD Runs
pastruns (Run -> Text
cwd Run
thisrun)
runsMatchingNWords :: Runs
runsMatchingNWords = Runs -> Int -> Text -> Runs
filterByFirstNWords Runs
runsInThisDir Int
n (Run -> Text
cmdline Run
thisrun)
wallTimes :: [Double]
wallTimes = Run -> Double
runTime (Run -> Double) -> [Run] -> [Double]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Runs -> [Run]
rs Runs
runsMatchingNWords
avgWallSeconds :: Double
avgWallSeconds = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Double]
wallTimes Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Double] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Double]
wallTimes)