{-# LANGUAGE FlexibleInstances #-}

-- |
-- Module      : OAlg.Control.Verbose
-- Description : verbosity on showing
-- Copyright   : (c) Erich Gut
-- License     : BSD3
-- Maintainer  : zerich.gut@gmail.com
--
-- verbosity on showing.
module OAlg.Control.Verbose
  (
    -- * Verbose
    Verbose(..), Verbosity(..)
  , vshowStr, mnString, vshowList, mnList

    -- * Percent
  , Percent(..), showPercent
  )
  where

import Control.Monad (join)

import OAlg.Data.Show

--------------------------------------------------------------------------------
-- Verbose -

-- | kinds of verbosity.
data Verbosity
  = Low | Middle | High | Full | Pretty deriving (Int -> Verbosity -> ShowS
[Verbosity] -> ShowS
Verbosity -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Verbosity] -> ShowS
$cshowList :: [Verbosity] -> ShowS
show :: Verbosity -> String
$cshow :: Verbosity -> String
showsPrec :: Int -> Verbosity -> ShowS
$cshowsPrec :: Int -> Verbosity -> ShowS
Show,Verbosity -> Verbosity -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Verbosity -> Verbosity -> Bool
$c/= :: Verbosity -> Verbosity -> Bool
== :: Verbosity -> Verbosity -> Bool
$c== :: Verbosity -> Verbosity -> Bool
Eq,Eq Verbosity
Verbosity -> Verbosity -> Bool
Verbosity -> Verbosity -> Ordering
Verbosity -> Verbosity -> Verbosity
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Verbosity -> Verbosity -> Verbosity
$cmin :: Verbosity -> Verbosity -> Verbosity
max :: Verbosity -> Verbosity -> Verbosity
$cmax :: Verbosity -> Verbosity -> Verbosity
>= :: Verbosity -> Verbosity -> Bool
$c>= :: Verbosity -> Verbosity -> Bool
> :: Verbosity -> Verbosity -> Bool
$c> :: Verbosity -> Verbosity -> Bool
<= :: Verbosity -> Verbosity -> Bool
$c<= :: Verbosity -> Verbosity -> Bool
< :: Verbosity -> Verbosity -> Bool
$c< :: Verbosity -> Verbosity -> Bool
compare :: Verbosity -> Verbosity -> Ordering
$ccompare :: Verbosity -> Verbosity -> Ordering
Ord,Int -> Verbosity
Verbosity -> Int
Verbosity -> [Verbosity]
Verbosity -> Verbosity
Verbosity -> Verbosity -> [Verbosity]
Verbosity -> Verbosity -> Verbosity -> [Verbosity]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Verbosity -> Verbosity -> Verbosity -> [Verbosity]
$cenumFromThenTo :: Verbosity -> Verbosity -> Verbosity -> [Verbosity]
enumFromTo :: Verbosity -> Verbosity -> [Verbosity]
$cenumFromTo :: Verbosity -> Verbosity -> [Verbosity]
enumFromThen :: Verbosity -> Verbosity -> [Verbosity]
$cenumFromThen :: Verbosity -> Verbosity -> [Verbosity]
enumFrom :: Verbosity -> [Verbosity]
$cenumFrom :: Verbosity -> [Verbosity]
fromEnum :: Verbosity -> Int
$cfromEnum :: Verbosity -> Int
toEnum :: Int -> Verbosity
$ctoEnum :: Int -> Verbosity
pred :: Verbosity -> Verbosity
$cpred :: Verbosity -> Verbosity
succ :: Verbosity -> Verbosity
$csucc :: Verbosity -> Verbosity
Enum,Verbosity
forall a. a -> a -> Bounded a
maxBound :: Verbosity
$cmaxBound :: Verbosity
minBound :: Verbosity
$cminBound :: Verbosity
Bounded)

-- | shows @a@ in the context of verbosity.
class Show a => Verbose a where
  -- | the default implementation is: @vshow v a = vshowStr ('mnString' v) (show a)@
  vshow :: Verbosity -> a -> String
  vshow Verbosity
v a
a = Maybe Int -> ShowS
vshowStr (Verbosity -> Maybe Int
mnString Verbosity
v) (forall a. Show a => a -> String
show a
a)

{-
mmax :: Maybe Int -> Int -> Maybe Int
mmax ma b = ma >>= \i -> return (max b i)
-}

--------------------------------------------------------------------------------
-- vshowStr -

-- | default length for a string representation in context of verbosity.
mnString :: Verbosity -> Maybe Int
mnString :: Verbosity -> Maybe Int
mnString Verbosity
Low    = forall a. a -> Maybe a
Just Int
10
mnString Verbosity
Middle = forall a. a -> Maybe a
Just Int
20
mnString Verbosity
High   = forall a. a -> Maybe a
Just Int
40
mnString Verbosity
_      = forall a. Maybe a
Nothing

-- | verbosely showing a string by the given length.
--
-- __Example__
--
-- >>> vshowStr (Just 3) "123456789"
-- "123.."
--
-- >>> vshowStr Nothing "123456789"
-- "123456789"
vshowStr :: Maybe Int -> String -> String
vshowStr :: Maybe Int -> ShowS
vshowStr Maybe Int
mi String
str = case Maybe Int
mi of
    Just Int
n  -> String
str' forall a. [a] -> [a] -> [a]
++ forall {a}. [a] -> String
dots String
r where (String
str',String
r) = forall a. Int -> [a] -> ([a], [a])
splitAt Int
n String
str
    Maybe Int
Nothing -> String
str
  where dots :: [a] -> String
dots [] = []
        dots [a]
_  = String
".."

--------------------------------------------------------------------------------
-- vshowList -

-- | default number of entries for a list representation in context of verbosity.
mnList :: Verbosity -> Maybe Int
mnList :: Verbosity -> Maybe Int
mnList Verbosity
Low    = forall a. a -> Maybe a
Just Int
2
mnList Verbosity
Middle = forall a. a -> Maybe a
Just Int
10
mnList Verbosity
High   = forall a. a -> Maybe a
Just Int
100
mnList Verbosity
_      = forall a. Maybe a
Nothing

-- | verbosely showing a list by the given length.
--
-- __Examples__
--
-- >>> vshowList Full (Just 3) "[" "]" "abcdef"
-- "['a','b','c'..]"
--
-- >>> vshowList Low (Just 3) "{" "}" ["abcdef","ghijklmn","op","qrst","uvwxyz"]
-- "{['a','b'..],['g','h'..],['o','p']..}"
vshowList :: Verbose a 
          => Verbosity
          -> Maybe Int
          -> String -> String
          -> [a]
          -> String
vshowList :: forall a.
Verbose a =>
Verbosity -> Maybe Int -> String -> String -> [a] -> String
vshowList Verbosity
v Maybe Int
mn String
db String
de [a]
xs
  = String
db forall a. [a] -> [a] -> [a]
++ forall {a}. Verbose a => Maybe Int -> [a] -> String
vslst' Maybe Int
mn [a]
xs forall a. [a] -> [a] -> [a]
++ String
de
    where dots :: [a] -> String
dots [] = String
""
          dots [a]
_  = String
".."
          
          vslst' :: Maybe Int -> [a] -> String
vslst' Maybe Int
mn' [a]
xs' = case Maybe Int
mn' of
              Just Int
n  -> (forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ forall a. a -> [a] -> [a]
tween String
"," forall a b. (a -> b) -> a -> b
$ [String]
ss') forall a. [a] -> [a] -> [a]
++ forall {a}. [a] -> String
dots [String]
r where ([String]
ss',[String]
r) = forall a. Int -> [a] -> ([a], [a])
splitAt Int
n [String]
ss
              Maybe Int
Nothing -> forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ forall a. a -> [a] -> [a]
tween String
"," forall a b. (a -> b) -> a -> b
$ [String]
ss
            where ss :: [String]
ss = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v)  [a]
xs'

instance Verbose Char where
  vshow :: Verbosity -> Char -> String
vshow Verbosity
_ = forall a. Show a => a -> String
show

mnIntegrals :: Verbosity -> Maybe Int
mnIntegrals :: Verbosity -> Maybe Int
mnIntegrals Verbosity
Low    = forall a. a -> Maybe a
Just Int
3
mnIntegrals Verbosity
Middle = forall a. a -> Maybe a
Just Int
5
mnIntegrals Verbosity
High   = forall a. a -> Maybe a
Just Int
7
mnIntegrals Verbosity
_      = forall a. Maybe a
Nothing

----------------------------------------
-- Some instances -

instance Verbose Int where
  vshow :: Verbosity -> Int -> String
vshow Verbosity
v Int
n = Maybe Int -> ShowS
vshowStr (Verbosity -> Maybe Int
mnIntegrals Verbosity
v) (forall a. Show a => a -> String
show Int
n)

instance Verbose Integer where
  vshow :: Verbosity -> Integer -> String
vshow Verbosity
v Integer
n = Maybe Int -> ShowS
vshowStr (Verbosity -> Maybe Int
mnIntegrals Verbosity
v) (forall a. Show a => a -> String
show Integer
n)

instance Verbose a => Verbose [a] where
  vshow :: Verbosity -> [a] -> String
vshow Verbosity
v = forall a.
Verbose a =>
Verbosity -> Maybe Int -> String -> String -> [a] -> String
vshowList Verbosity
v (Verbosity -> Maybe Int
mnList Verbosity
v) String
"[" String
"]"

instance Verbose Double

----------------------------------------
-- Verbose - Tuple -

vshowTuple :: [String] -> String
vshowTuple :: [String] -> String
vshowTuple [String]
ss = String
"(" forall a. [a] -> [a] -> [a]
++ (forall (m :: * -> *) a. Monad m => m (m a) -> m a
join forall a b. (a -> b) -> a -> b
$ forall a. a -> [a] -> [a]
tween String
"," [String]
ss) forall a. [a] -> [a] -> [a]
++ String
")"

instance Verbose () where
  vshow :: Verbosity -> () -> String
vshow Verbosity
_ ()
_ = [String] -> String
vshowTuple []

instance (Verbose a,Verbose b) => Verbose (a,b) where
  vshow :: Verbosity -> (a, b) -> String
vshow Verbosity
v (a
a,b
b) = [String] -> String
vshowTuple [forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v a
a,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v b
b]

instance (Verbose a,Verbose b,Verbose c) => Verbose (a,b,c) where
  vshow :: Verbosity -> (a, b, c) -> String
vshow Verbosity
v (a
a,b
b,c
c) = [String] -> String
vshowTuple [forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v a
a,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v b
b,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v c
c]

instance (Verbose a,Verbose b,Verbose c,Verbose d) => Verbose (a,b,c,d) where
  vshow :: Verbosity -> (a, b, c, d) -> String
vshow Verbosity
v (a
a,b
b,c
c,d
d) = [String] -> String
vshowTuple [forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v a
a,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v b
b,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v c
c,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v d
d]

instance (Verbose a,Verbose b,Verbose c,Verbose d, Verbose e) => Verbose (a,b,c,d,e) where
  vshow :: Verbosity -> (a, b, c, d, e) -> String
vshow Verbosity
v (a
a,b
b,c
c,d
d,e
e) = [String] -> String
vshowTuple [forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v a
a,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v b
b,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v c
c,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v d
d,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v e
e]

instance (Verbose a,Verbose b,Verbose c,Verbose d, Verbose e,Verbose f)
  => Verbose (a,b,c,d,e,f) where
  vshow :: Verbosity -> (a, b, c, d, e, f) -> String
vshow Verbosity
v (a
a,b
b,c
c,d
d,e
e,f
f)
    = [String] -> String
vshowTuple [forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v a
a,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v b
b,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v c
c,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v d
d,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v e
e,forall a. Verbose a => Verbosity -> a -> String
vshow Verbosity
v f
f]


--------------------------------------------------------------------------------
-- Percent -

-- | tagging for showing percentage of a 'Double'.
newtype Percent x = Percent x deriving Int -> Percent x -> ShowS
forall x. Show x => Int -> Percent x -> ShowS
forall x. Show x => [Percent x] -> ShowS
forall x. Show x => Percent x -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Percent x] -> ShowS
$cshowList :: forall x. Show x => [Percent x] -> ShowS
show :: Percent x -> String
$cshow :: forall x. Show x => Percent x -> String
showsPrec :: Int -> Percent x -> ShowS
$cshowsPrec :: forall x. Show x => Int -> Percent x -> ShowS
Show

nPercent :: Verbosity -> Int
nPercent :: Verbosity -> Int
nPercent Verbosity
Low    = Int
0
nPercent Verbosity
Middle = Int
2
nPercent Verbosity
_      = Int
4

instance Verbose (Percent Double) where
  vshow :: Verbosity -> Percent Double -> String
vshow Verbosity
v (Percent Double
x) = Int -> Double -> String
showPercent (Verbosity -> Int
nPercent Verbosity
v) Double
x

--------------------------------------------------------------------------------
-- showPercent -

-- | showing a double as percent with the given precision.
--
-- __Example__
--
-- >>> showPercent 2 0.912837
-- " 91.28%"
showPercent :: Int -> Double -> String
showPercent :: Int -> Double -> String
showPercent Int
n Double
d = String
sprc forall a. [a] -> [a] -> [a]
++ (if Int
0 forall a. Ord a => a -> a -> Bool
< Int
n then String
"." forall a. [a] -> [a] -> [a]
++ String
sprm else String
"") forall a. [a] -> [a] -> [a]
++ String
"%"
  where n' :: Double
n'        = Double
10 forall a. Floating a => a -> a -> a
** forall a. Enum a => Int -> a
toEnum Int
n
        (Integer
prc,Double
prm) = (forall a b. (RealFrac a, Integral b) => a -> (b, a)
properFraction :: Double -> (Integer,Double))
                    ((forall a. Enum a => Int -> a
toEnum forall a b. (a -> b) -> a -> b
$ forall a b. (RealFrac a, Integral b) => a -> b
round forall a b. (a -> b) -> a -> b
$ (Double
100 forall a. Num a => a -> a -> a
* Double
n' forall a. Num a => a -> a -> a
* Double
d)) forall a. Fractional a => a -> a -> a
/ Double
n')
        sprc' :: String
sprc'     = forall a. Show a => a -> String
show Integer
prc
        sprc :: String
sprc      = let dgs :: Int
dgs = forall (t :: * -> *) a. Foldable t => t a -> Int
length String
sprc' in (forall a. Int -> [a] -> [a]
take (Int
3 forall a. Num a => a -> a -> a
- Int
dgs) forall a b. (a -> b) -> a -> b
$ forall a. a -> [a]
repeat forall a b. (a -> b) -> a -> b
$ Char
' ') forall a. [a] -> [a] -> [a]
++ String
sprc'

        sprm' :: String
sprm'     = (forall a. Show a => a -> String
show :: Integer -> String) forall a b. (a -> b) -> a -> b
$ forall a b. (RealFrac a, Integral b) => a -> b
floor forall a b. (a -> b) -> a -> b
$ (Double
n' forall a. Num a => a -> a -> a
* Double
prm)
        sprm :: String
sprm      = let dgs :: Int
dgs = forall (t :: * -> *) a. Foldable t => t a -> Int
length String
sprm' in String
sprm' forall a. [a] -> [a] -> [a]
++ (forall a. Int -> [a] -> [a]
take (Int
n forall a. Num a => a -> a -> a
- Int
dgs) forall a b. (a -> b) -> a -> b
$ forall a. a -> [a]
repeat forall a b. (a -> b) -> a -> b
$ Char
'0')