{-# LANGUAGE BangPatterns #-}
module RemoteExecutable (remoteExecutable) where
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Lazy.Char8 as BLC
import Data.List (foldl')
import Data.Maybe
import Control.Distributed.Task.Types.TaskTypes
remoteExecutable :: Task
remoteExecutable = calculateRatio
--remoteExecutable = map $ flip BLC.append $ BLC.pack " appended"
calculateRatio :: [BL.ByteString] -> [BL.ByteString]
calculateRatio = (:[]) . BLC.pack . show . divideRatio . foldl' (flip countHits) (0, 0) . parseEntries
where
divideRatio :: (Int, Int) -> Double
divideRatio (hits, count) = fromIntegral hits / (fromIntegral count)
countHits :: Entry -> (Int, Int) -> (Int, Int)
-- especially hits are important to evaluate strict here to avoid building up of costly to store thunks, containing entries (count is affected to a lesser degree)
countHits e (!hits, !count) = (hits + if isHit e then 1 else 0, count+1)
isHit :: Entry -> Bool
isHit (_, _, vs) = maybe False notEmpty $ lookup (BLC.pack "searchCrit") vs
where
notEmpty :: BL.ByteString -> Bool
notEmpty = (>0) . (read :: String -> Int) . BLC.unpack
parseEntries :: [BL.ByteString] -> [Entry]
parseEntries = catMaybes . map parseEntry
type Entry = (BL.ByteString, BL.ByteString, [(BL.ByteString, BL.ByteString)])
--nlrkwldbji|3101692061|xlerb:uubqpnce|searchCrit:0|longerAttr:nspixnozidyqweu|other:lju|otherRandomNam:tndhdno|otherRandomName2:dgkkj|otherRandomName3:yrdwgww|last:xvofbj
parseEntry :: BL.ByteString -> Maybe Entry
parseEntry str =
let cells = BLC.split '|' str
in if length cells < 2
then Nothing
else Just (cells !! 0, cells !! 1, catMaybes $ map parseValue $ drop 2 cells)
where
parseValue val = let kv = BLC.split ':' val in if length kv /= 2 then Nothing else Just (kv !! 0, kv !! 1)