packages feed

unscramble-0.3: Unscramble/Output.hs

module Unscramble.Output (
    display
) where

import Control.Lens
import qualified Data.HashMap as H
import Data.List
import Data.Ord
import Text.Printf
import Unscramble.Types

-- words are already sorted by score
display :: [(Score, String, [Coordinate])]
        -> Grid
        -> Multiplier
        -> ScrambleOpts
        -> IO ()
display xs g m (ScrambleOpts _ _ ds)
     | ds == OneLine = (showTotal >>) $ mapM_ (\x -> putStr ((_2 ^$ x) ++ " ")) xs
     | ds == Chunked = (showTotal >>) $ mapM_ (\ns -> do
         mapM_ (displayGrid g m) ns
         putStrLn "\nPress enter for more, or ctrl-c to quit."
         getLine) $ chunk xs
    where
        showTotal = do
            let points = sum . map (_1 ^$) $ xs
            printf "%d total words for %d points.\n" (length xs) points
        chunk (a:b:c:es) = [a,b,c]:chunk es
        chunk x = [x]
display _ _ _ (ScrambleOpts _ _ _) = error "what?"

displayGrid :: Grid
            -> Multiplier
            -> (Score, String, [Coordinate])
            -> IO ()
displayGrid (Grid _ gs) (Multiplier dl dw tl tw) (sc, word, cs)
        = (putStrLn ("\n\27[1m" ++ word ++ "\27[0m: " ++ show sc) >>)
        . mapM_ (putStr . render) $ idxs
    where
        max' = fst . maximumBy (comparing fst) $ H.keys gs
        idxs = [(a,b) | a <- [0..max'], b <- [0..max']]
        render n
            | head cs == n = "\27[44m" ++ pad letter n True ++ "\27[49m" ++ nl
            | n `elem` cs = "\27[107m" ++ pad letter n True ++ "\27[49m" ++ nl
            | otherwise = pad letter n False ++ nl
            where
                letter = H.findWithDefault undefined n gs
                nl = if snd n == max' then "\n" else ""
        pad [x] n t = " " ++ highlight [x] n t ++ " "
        pad x n t = ' ':highlight x n t
        highlight x n t
            | n `elem` dl = "\27[36;1m" ++ x ++ "\27[39;22m"
            | Just n == dw = "\27[31;1m" ++ x ++ "\27[39;22m"
            | n `elem` tl = "\27[32;1m" ++ x ++ "\27[39;22m"
            | Just n == tw = "\27[33;1m" ++ x ++ "\27[39;22m"
            | t = "\27[30m" ++ x ++ "\27[39;22m"
            | otherwise = x