-- | Module providing helpful tips about minimizing the complexity of the chosen data structure module Advice ( adviceDS, printAdvice, adviceDS', printAdvice' ) where import Defs.Util import Defs.Structures import Recommend import Data.List -- | Type for advice data data Advice = Advice { advisedDS :: Structure, -- ^ Structure to be advised reducedOperations :: [OperationName], -- ^ Operations on which the structure is better than the recommended one operations :: [OperationName] -- ^ Original operations (we can get recommendations from them) } deriving Show -- | Checks if structure @s1@ is not worse than structure @s2@ on operations @opns@ notWorse :: Structure -> Structure -> [OperationName] -> Bool notWorse s1 s2 opns = compareDS s1 s2 opns /= LT -- | Checks if the structure @s1@ is better than the structure @s2@ on operations @opns@ better :: Structure -> Structure -> [OperationName] -> Bool better s1 s2 opns | s1 == s2 = True | otherwise = compareDS s1 s2 opns == GT -- | Checks if the structure @s1@ is better than each of the structures in @ss@ on operations @opns@ betterThanEach :: Structure -> [Structure] -> [OperationName] -> Bool betterThanEach s1 ss opns = all (\s2-> better s1 s2 opns) ss -- | Removes already recommended data structures @recs@ from the advised structures filterAdviceForRecommended :: [Structure] -> [Advice] -> [Advice] filterAdviceForRecommended recs = filter (\(Advice ds _ _) -> ds `notElem` recs) -- | Returns advice data for operations @opns@ and at most @n@ operations to forget about adviceDS' :: Integer -> [OperationName] -> [Advice] adviceDS' n opns = let recOrig = recommendAllDs opns opnsSeqs = sequencesOfLen opns (genericLength opns - n) recSeqs = concatMap (\sq -> map (\x -> Advice x sq opns) $ filter (\ds-> betterThanEach ds recOrig sq) (recommendAllDs sq)) opnsSeqs in filterAdviceForRecommended recOrig recSeqs -- | Returns advice data for operations @opns@ adviceDS :: [OperationName] -> [Advice] adviceDS = adviceDS' 1 -- | Pretty prints effects of 'adviceDS'' printAdvice' :: (String -> IO ()) -> Integer -> [OperationName] -> IO () printAdvice' output n opns = do yellowColor let adv = adviceDS' n opns let rec = recommendAllDs opns if length rec == 1 then do output "Currently, the recommended data structure is: " cyanColor output $ (getDSName $ head rec) ++ "\n" yellowColor else do output "Currently, the recommended data structures are: " cyanColor output $ (foldl (\str ds -> (str ++ ", " ++ getDSName ds)) "" rec) ++ "\n" yellowColor mapM_ (printAdviceStructure output) adv resetColor -- | Prints one 'Advice' element printAdviceStructure :: (String -> IO ()) -> Advice -> IO() printAdviceStructure output (Advice s betterOpns opns) = do output "You could use " greenColor output $ getDSName s yellowColor output ", if you removed the following operations:\n" redColor output $ concatMap (\opn -> "* " ++ show opn ++ "\n") (opns \\ betterOpns) resetColor -- | Pretty prints effects of 'adviceDS' printAdvice :: (String -> IO ()) -> [OperationName] -> IO () printAdvice output = printAdvice' output 1