module System.Taffybar.Information.CPU ( cpuLoad ) where

import Control.Concurrent ( threadDelay )
import System.IO ( IOMode(ReadMode), openFile, hGetLine, hClose )

procData :: IO [Double]
procData :: IO [Double]
procData = do
  h <- FilePath -> IOMode -> IO Handle
openFile FilePath
"/proc/stat" IOMode
ReadMode
  firstLine <- hGetLine h
  length firstLine `seq` return ()
  hClose h
  return (procParser firstLine)

procParser :: String -> [Double]
procParser :: FilePath -> [Double]
procParser = (FilePath -> Double) -> [FilePath] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> Double
forall a. Read a => FilePath -> a
read ([FilePath] -> [Double])
-> (FilePath -> [FilePath]) -> FilePath -> [Double]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [FilePath] -> [FilePath]
forall a. Int -> [a] -> [a]
drop Int
1 ([FilePath] -> [FilePath])
-> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
words

truncVal :: Double -> Double
truncVal :: Double -> Double
truncVal Double
v
  | Double -> Bool
forall a. RealFloat a => a -> Bool
isNaN Double
v Bool -> Bool -> Bool
|| Double
v Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.0 = Double
0.0
  | Bool
otherwise = Double
v

-- | Return a pair with (user time, system time, total time) (read
-- from /proc/stat).  The function waits for 50 ms between samples.
cpuLoad :: IO (Double, Double, Double)
cpuLoad :: IO (Double, Double, Double)
cpuLoad = do
  a <- IO [Double]
procData
  threadDelay 50000
  b <- procData
  let dif = (Double -> Double -> Double) -> [Double] -> [Double] -> [Double]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (-) [Double]
b [Double]
a
      tot = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Double]
dif
      pct = (Double -> Double) -> [Double] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
tot) [Double]
dif
      user = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Double] -> Double) -> [Double] -> Double
forall a b. (a -> b) -> a -> b
$ Int -> [Double] -> [Double]
forall a. Int -> [a] -> [a]
take Int
2 [Double]
pct
      system = [Double]
pct [Double] -> Int -> Double
forall a. HasCallStack => [a] -> Int -> a
!! Int
2
      t = Double
user Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
system
  return (truncVal user, truncVal system, truncVal t)