packages feed

task-distribution-0.1.0.0: app/RemoteExecutable.hs

{-# 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)