Created
July 4, 2014 21:27
-
-
Save jcla1/addb4ab8a20aef2fb862 to your computer and use it in GitHub Desktop.
Haskell activity log script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Data.Function (on) | |
import Data.List (sort, sortBy, groupBy, nub) | |
import Data.List.Utils (replace) | |
import Data.Ord (comparing) | |
import Data.Either (rights) | |
import Control.Monad (liftM) | |
import System.Environment (getArgs) | |
import Text.Parsec.Error (ParseError) | |
import qualified Text.CSV as CSV | |
validPrograms = ["Google Chrome", "Sublime Text 2", "iTerm", "Finder", "Activity Monitor"] | |
-- Maximum time difference between two usages of a program, | |
-- so that these usages would be counted in the same interval, in seconds. | |
maxIntervalDiff = 360 | |
-- Minimum duration of usage of a program to be accounted for in the line-up | |
minUsage = 720 | |
main = do | |
activityRecords <- liftM (concatMap init . rights) getCSVs | |
putStrLn $ processActivityRecords activityRecords | |
getCSVs :: IO [Either ParseError CSV.CSV] | |
getCSVs = mapM CSV.parseCSVFromFile =<< getArgs | |
processActivityRecords :: CSV.CSV -> String | |
processActivityRecords rs = concatRecords otherPrograms allPrograms | |
where | |
concatRecords = (++) `on` flip (++) "\n" . postpareCSV | |
allPrograms = intervalsToCSV "All Programs" allProgramIntervals | |
allProgramIntervals = | |
timesToInterval . | |
sort . | |
nub $ | |
concatMap snd programTimes | |
otherPrograms = | |
concatMap (uncurry intervalsToCSV) . | |
filterPrograms $ | |
mapTimesToInterval programTimes | |
programTimes = | |
cleanGroups . | |
groupBy ((==) `on` fst) . | |
sortBy (comparing fst) $ | |
toProgramTime rs | |
filterPrograms = filterMinUsage . filterValidPrograms | |
postpareCSV :: CSV.CSV -> String | |
postpareCSV = removeQuotes . CSV.printCSV | |
intervalsToCSV :: String -> [(Int, Int)] -> CSV.CSV | |
intervalsToCSV name = map (uncurry (intervalToCSV name)) | |
intervalToCSV :: String -> Int -> Int -> CSV.Record | |
intervalToCSV name s e = [show s, show e, show (e - s), name] | |
mapTimesToInterval :: [(String, [Int])] -> [(String, [(Int, Int)])] | |
mapTimesToInterval = map (\ x -> (fst x, timesToInterval $ snd x)) | |
timesToInterval :: [Int] -> [(Int, Int)] | |
timesToInterval (x:xs) = foldl concatIntervals [(x, x)] xs | |
where | |
concatIntervals (i:is) t = makeInterval i t ++ is | |
makeInterval (start, end) t | |
| t > end && t - end <= maxIntervalDiff = [(start, t)] | |
| start /= end = [(t, t), (start, end)] | |
| otherwise = [(t, t)] | |
filterValidPrograms :: [(String, a)] -> [(String, a)] | |
filterValidPrograms = filter (\ x -> fst x `elem` validPrograms) | |
filterMinUsage :: [(a, [(Int, Int)])] -> [(a, [(Int, Int)])] | |
filterMinUsage = filter (\ (_, is) -> intervalsToDuration is >= minUsage) | |
intervalsToDuration :: [(Int, Int)] -> Int | |
intervalsToDuration = foldl (\ acc (a, b) -> acc + b - a) 0 | |
toProgramTime :: CSV.CSV -> [(String, Int)] | |
toProgramTime = map (\ r -> (r !! 3, adjustTime r)) | |
adjustTime :: CSV.Record -> Int | |
adjustTime (t:tz:_) = (read t :: Int) + case tz of | |
"CEST" -> 7200 | |
"CET" -> 3600 | |
removeQuotes :: String -> String | |
removeQuotes = replace "\"" "" | |
cleanGroups :: [[(a, b)]] -> [(a, [b])] | |
cleanGroups = map (\ x -> (fst $ head x, map snd x)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1404508051 | CEST | 0 | Google Chrome | 1 | 1 | 15 | 24.4 | |
---|---|---|---|---|---|---|---|---|
1404508067 | CEST | 1 | iTerm | 1 | 0 | 15 | 24.3 | |
1404508080 | CEST | 0 | iTerm | 1 | 0 | 15 | 24.3 | |
1404508095 | CEST | 0 | iTerm | 1 | 0 | 15 | 24.3 | |
1404508111 | CEST | 0 | Google Chrome | 1 | 1 | 15 | 24.3 | |
1404508126 | CEST | 0 | iTerm | 1 | 0 | 14 | 24.3 | |
1404508140 | CEST | 0 | iTerm | 1 | 0 | 14 | 24.3 | |
1404508155 | CEST | 0 | Google Chrome | 1 | 1 | 14 | 24.3 | |
1404508170 | CEST | 0 | iTerm | 1 | 0 | 14 | 24.3 | |
1404508186 | CEST | 1 | iTerm | 1 | 0 | 14 | 24.1 | |
1404508200 | CEST | 0 | iTerm | 1 | 0 | 14 | 24.1 | |
1404508216 | CEST | 0 | iTerm | 1 | 0 | 14 | 24.1 | |
1404508231 | CEST | 0 | iTerm | 1 | 0 | 14 | 24.1 | |
1404508247 | CEST | 0 | iTerm | 1 | 0 | 14 | 23.9 | |
1404508260 | CEST | 0 | iTerm | 1 | 0 | 14 | 23.9 | |
1404508275 | CEST | 3 | iTerm | 1 | 0 | 14 | 23.9 | |
1404508291 | CEST | 0 | Google Chrome | 1 | 1 | 14 | 23.9 | |
1404508306 | CEST | 0 | iTerm | 1 | 0 | 14 | 23.8 | |
1404508320 | CEST | 0 | iTerm | 1 | 0 | 14 | 23.8 | |
1404508335 | CEST | 0 | iTerm | 1 | 0 | 14 | 23.8 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment