module ParkBench.Pretty
(
R (..),
Cellular (..),
BytesCell (..),
BytesPerSecondCell (..),
IncomparablePercentageCell (..),
IncomparableWord3Cell (..),
NanosecondsCell (..),
NumberCell (..),
NumberCell' (..),
PercentageCell (..),
PercentageCell' (..),
rowMaker,
Table (..),
renderTable,
RowGroup (..),
Row (..),
Cell (..),
isEmptyCell,
Color (..),
)
where
import Data.List.NonEmpty (NonEmpty (..))
import Data.Maybe
import Data.Ord (Down (..))
import Data.String (IsString (..))
import qualified Data.Text as Text
import ParkBench.Builder (Builder)
import qualified ParkBench.Builder as Builder
import ParkBench.Prelude
import qualified ParkBench.Terminal as Terminal
data R a b
= R Cell (a -> Maybe b)
class Ord a => Cellular a where
cellDelta :: a -> a -> Double
cellString :: a -> Builder
newtype BytesCell
= BytesCell Double
deriving (BytesCell -> BytesCell -> Bool
(BytesCell -> BytesCell -> Bool)
-> (BytesCell -> BytesCell -> Bool) -> Eq BytesCell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BytesCell -> BytesCell -> Bool
$c/= :: BytesCell -> BytesCell -> Bool
== :: BytesCell -> BytesCell -> Bool
$c== :: BytesCell -> BytesCell -> Bool
Eq) via Double
deriving (Eq BytesCell
Eq BytesCell
-> (BytesCell -> BytesCell -> Ordering)
-> (BytesCell -> BytesCell -> Bool)
-> (BytesCell -> BytesCell -> Bool)
-> (BytesCell -> BytesCell -> Bool)
-> (BytesCell -> BytesCell -> Bool)
-> (BytesCell -> BytesCell -> BytesCell)
-> (BytesCell -> BytesCell -> BytesCell)
-> Ord BytesCell
BytesCell -> BytesCell -> Bool
BytesCell -> BytesCell -> Ordering
BytesCell -> BytesCell -> BytesCell
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 :: BytesCell -> BytesCell -> BytesCell
$cmin :: BytesCell -> BytesCell -> BytesCell
max :: BytesCell -> BytesCell -> BytesCell
$cmax :: BytesCell -> BytesCell -> BytesCell
>= :: BytesCell -> BytesCell -> Bool
$c>= :: BytesCell -> BytesCell -> Bool
> :: BytesCell -> BytesCell -> Bool
$c> :: BytesCell -> BytesCell -> Bool
<= :: BytesCell -> BytesCell -> Bool
$c<= :: BytesCell -> BytesCell -> Bool
< :: BytesCell -> BytesCell -> Bool
$c< :: BytesCell -> BytesCell -> Bool
compare :: BytesCell -> BytesCell -> Ordering
$ccompare :: BytesCell -> BytesCell -> Ordering
$cp1Ord :: Eq BytesCell
Ord) via Down Double
instance Cellular BytesCell where
cellDelta :: BytesCell -> BytesCell -> Double
cellDelta = (Double -> Double -> Double) -> BytesCell -> BytesCell -> Double
coerce Double -> Double -> Double
doubleDelta
cellString :: BytesCell -> Builder
cellString (BytesCell Double
r) = Double -> Builder
Builder.bytes4 Double
r
newtype BytesPerSecondCell
= BytesPerSecondCell Double
deriving (BytesPerSecondCell -> BytesPerSecondCell -> Bool
(BytesPerSecondCell -> BytesPerSecondCell -> Bool)
-> (BytesPerSecondCell -> BytesPerSecondCell -> Bool)
-> Eq BytesPerSecondCell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
$c/= :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
== :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
$c== :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
Eq) via Double
deriving (Eq BytesPerSecondCell
Eq BytesPerSecondCell
-> (BytesPerSecondCell -> BytesPerSecondCell -> Ordering)
-> (BytesPerSecondCell -> BytesPerSecondCell -> Bool)
-> (BytesPerSecondCell -> BytesPerSecondCell -> Bool)
-> (BytesPerSecondCell -> BytesPerSecondCell -> Bool)
-> (BytesPerSecondCell -> BytesPerSecondCell -> Bool)
-> (BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell)
-> (BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell)
-> Ord BytesPerSecondCell
BytesPerSecondCell -> BytesPerSecondCell -> Bool
BytesPerSecondCell -> BytesPerSecondCell -> Ordering
BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell
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 :: BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell
$cmin :: BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell
max :: BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell
$cmax :: BytesPerSecondCell -> BytesPerSecondCell -> BytesPerSecondCell
>= :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
$c>= :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
> :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
$c> :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
<= :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
$c<= :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
< :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
$c< :: BytesPerSecondCell -> BytesPerSecondCell -> Bool
compare :: BytesPerSecondCell -> BytesPerSecondCell -> Ordering
$ccompare :: BytesPerSecondCell -> BytesPerSecondCell -> Ordering
$cp1Ord :: Eq BytesPerSecondCell
Ord) via Down Double
instance Cellular BytesPerSecondCell where
cellDelta :: BytesPerSecondCell -> BytesPerSecondCell -> Double
cellDelta = (Double -> Double -> Double)
-> BytesPerSecondCell -> BytesPerSecondCell -> Double
coerce Double -> Double -> Double
doubleDelta
cellString :: BytesPerSecondCell -> Builder
cellString (BytesPerSecondCell Double
r) = Double -> Builder
prettyBytesPerSecond Double
r
prettyBytesPerSecond :: Double -> Builder
prettyBytesPerSecond :: Double -> Builder
prettyBytesPerSecond Double
r =
if Builder -> Bool
Builder.null Builder
s
then Builder
Builder.empty
else Builder
s Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"/s"
where
s :: Builder
s = Double -> Builder
Builder.bytes4 Double
r
newtype IncomparablePercentageCell
= IncomparablePercentageCell Double
deriving (IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
(IncomparablePercentageCell -> IncomparablePercentageCell -> Bool)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> Bool)
-> Eq IncomparablePercentageCell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
$c/= :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
== :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
$c== :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
Eq) via Double
deriving (Eq IncomparablePercentageCell
Eq IncomparablePercentageCell
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> Ordering)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> Bool)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> Bool)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> Bool)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> Bool)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell)
-> (IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell)
-> Ord IncomparablePercentageCell
IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
IncomparablePercentageCell
-> IncomparablePercentageCell -> Ordering
IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell
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 :: IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell
$cmin :: IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell
max :: IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell
$cmax :: IncomparablePercentageCell
-> IncomparablePercentageCell -> IncomparablePercentageCell
>= :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
$c>= :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
> :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
$c> :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
<= :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
$c<= :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
< :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
$c< :: IncomparablePercentageCell -> IncomparablePercentageCell -> Bool
compare :: IncomparablePercentageCell
-> IncomparablePercentageCell -> Ordering
$ccompare :: IncomparablePercentageCell
-> IncomparablePercentageCell -> Ordering
$cp1Ord :: Eq IncomparablePercentageCell
Ord) via Down Double
instance Cellular IncomparablePercentageCell where
cellDelta :: IncomparablePercentageCell -> IncomparablePercentageCell -> Double
cellDelta IncomparablePercentageCell
_ IncomparablePercentageCell
_ = Double
0
cellString :: IncomparablePercentageCell -> Builder
cellString (IncomparablePercentageCell Double
r) = Double -> Builder
Builder.percentage Double
r
newtype NumberCell
= NumberCell Double
deriving (NumberCell -> NumberCell -> Bool
(NumberCell -> NumberCell -> Bool)
-> (NumberCell -> NumberCell -> Bool) -> Eq NumberCell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NumberCell -> NumberCell -> Bool
$c/= :: NumberCell -> NumberCell -> Bool
== :: NumberCell -> NumberCell -> Bool
$c== :: NumberCell -> NumberCell -> Bool
Eq) via Double
deriving (Eq NumberCell
Eq NumberCell
-> (NumberCell -> NumberCell -> Ordering)
-> (NumberCell -> NumberCell -> Bool)
-> (NumberCell -> NumberCell -> Bool)
-> (NumberCell -> NumberCell -> Bool)
-> (NumberCell -> NumberCell -> Bool)
-> (NumberCell -> NumberCell -> NumberCell)
-> (NumberCell -> NumberCell -> NumberCell)
-> Ord NumberCell
NumberCell -> NumberCell -> Bool
NumberCell -> NumberCell -> Ordering
NumberCell -> NumberCell -> NumberCell
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 :: NumberCell -> NumberCell -> NumberCell
$cmin :: NumberCell -> NumberCell -> NumberCell
max :: NumberCell -> NumberCell -> NumberCell
$cmax :: NumberCell -> NumberCell -> NumberCell
>= :: NumberCell -> NumberCell -> Bool
$c>= :: NumberCell -> NumberCell -> Bool
> :: NumberCell -> NumberCell -> Bool
$c> :: NumberCell -> NumberCell -> Bool
<= :: NumberCell -> NumberCell -> Bool
$c<= :: NumberCell -> NumberCell -> Bool
< :: NumberCell -> NumberCell -> Bool
$c< :: NumberCell -> NumberCell -> Bool
compare :: NumberCell -> NumberCell -> Ordering
$ccompare :: NumberCell -> NumberCell -> Ordering
$cp1Ord :: Eq NumberCell
Ord) via Down Double
instance Cellular NumberCell where
cellDelta :: NumberCell -> NumberCell -> Double
cellDelta = (Double -> Double -> Double) -> NumberCell -> NumberCell -> Double
coerce Double -> Double -> Double
doubleDelta
cellString :: NumberCell -> Builder
cellString (NumberCell Double
r) = Double -> Builder
Builder.double4 Double
r
newtype NumberCell'
= NumberCell' Double
deriving (NumberCell' -> NumberCell' -> Bool
(NumberCell' -> NumberCell' -> Bool)
-> (NumberCell' -> NumberCell' -> Bool) -> Eq NumberCell'
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NumberCell' -> NumberCell' -> Bool
$c/= :: NumberCell' -> NumberCell' -> Bool
== :: NumberCell' -> NumberCell' -> Bool
$c== :: NumberCell' -> NumberCell' -> Bool
Eq, Eq NumberCell'
Eq NumberCell'
-> (NumberCell' -> NumberCell' -> Ordering)
-> (NumberCell' -> NumberCell' -> Bool)
-> (NumberCell' -> NumberCell' -> Bool)
-> (NumberCell' -> NumberCell' -> Bool)
-> (NumberCell' -> NumberCell' -> Bool)
-> (NumberCell' -> NumberCell' -> NumberCell')
-> (NumberCell' -> NumberCell' -> NumberCell')
-> Ord NumberCell'
NumberCell' -> NumberCell' -> Bool
NumberCell' -> NumberCell' -> Ordering
NumberCell' -> NumberCell' -> NumberCell'
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 :: NumberCell' -> NumberCell' -> NumberCell'
$cmin :: NumberCell' -> NumberCell' -> NumberCell'
max :: NumberCell' -> NumberCell' -> NumberCell'
$cmax :: NumberCell' -> NumberCell' -> NumberCell'
>= :: NumberCell' -> NumberCell' -> Bool
$c>= :: NumberCell' -> NumberCell' -> Bool
> :: NumberCell' -> NumberCell' -> Bool
$c> :: NumberCell' -> NumberCell' -> Bool
<= :: NumberCell' -> NumberCell' -> Bool
$c<= :: NumberCell' -> NumberCell' -> Bool
< :: NumberCell' -> NumberCell' -> Bool
$c< :: NumberCell' -> NumberCell' -> Bool
compare :: NumberCell' -> NumberCell' -> Ordering
$ccompare :: NumberCell' -> NumberCell' -> Ordering
$cp1Ord :: Eq NumberCell'
Ord) via Double
deriving (Ord NumberCell'
Ord NumberCell'
-> (NumberCell' -> NumberCell' -> Double)
-> (NumberCell' -> Builder)
-> Cellular NumberCell'
NumberCell' -> Builder
NumberCell' -> NumberCell' -> Double
forall a.
Ord a -> (a -> a -> Double) -> (a -> Builder) -> Cellular a
cellString :: NumberCell' -> Builder
$ccellString :: NumberCell' -> Builder
cellDelta :: NumberCell' -> NumberCell' -> Double
$ccellDelta :: NumberCell' -> NumberCell' -> Double
$cp1Cellular :: Ord NumberCell'
Cellular) via NumberCell
newtype NanosecondsCell
= NanosecondsCell Double
deriving (NanosecondsCell -> NanosecondsCell -> Bool
(NanosecondsCell -> NanosecondsCell -> Bool)
-> (NanosecondsCell -> NanosecondsCell -> Bool)
-> Eq NanosecondsCell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NanosecondsCell -> NanosecondsCell -> Bool
$c/= :: NanosecondsCell -> NanosecondsCell -> Bool
== :: NanosecondsCell -> NanosecondsCell -> Bool
$c== :: NanosecondsCell -> NanosecondsCell -> Bool
Eq) via Double
deriving (Eq NanosecondsCell
Eq NanosecondsCell
-> (NanosecondsCell -> NanosecondsCell -> Ordering)
-> (NanosecondsCell -> NanosecondsCell -> Bool)
-> (NanosecondsCell -> NanosecondsCell -> Bool)
-> (NanosecondsCell -> NanosecondsCell -> Bool)
-> (NanosecondsCell -> NanosecondsCell -> Bool)
-> (NanosecondsCell -> NanosecondsCell -> NanosecondsCell)
-> (NanosecondsCell -> NanosecondsCell -> NanosecondsCell)
-> Ord NanosecondsCell
NanosecondsCell -> NanosecondsCell -> Bool
NanosecondsCell -> NanosecondsCell -> Ordering
NanosecondsCell -> NanosecondsCell -> NanosecondsCell
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 :: NanosecondsCell -> NanosecondsCell -> NanosecondsCell
$cmin :: NanosecondsCell -> NanosecondsCell -> NanosecondsCell
max :: NanosecondsCell -> NanosecondsCell -> NanosecondsCell
$cmax :: NanosecondsCell -> NanosecondsCell -> NanosecondsCell
>= :: NanosecondsCell -> NanosecondsCell -> Bool
$c>= :: NanosecondsCell -> NanosecondsCell -> Bool
> :: NanosecondsCell -> NanosecondsCell -> Bool
$c> :: NanosecondsCell -> NanosecondsCell -> Bool
<= :: NanosecondsCell -> NanosecondsCell -> Bool
$c<= :: NanosecondsCell -> NanosecondsCell -> Bool
< :: NanosecondsCell -> NanosecondsCell -> Bool
$c< :: NanosecondsCell -> NanosecondsCell -> Bool
compare :: NanosecondsCell -> NanosecondsCell -> Ordering
$ccompare :: NanosecondsCell -> NanosecondsCell -> Ordering
$cp1Ord :: Eq NanosecondsCell
Ord) via Down Double
instance Cellular NanosecondsCell where
cellDelta :: NanosecondsCell -> NanosecondsCell -> Double
cellDelta = (Double -> Double -> Double)
-> NanosecondsCell -> NanosecondsCell -> Double
coerce Double -> Double -> Double
doubleDelta
cellString :: NanosecondsCell -> Builder
cellString (NanosecondsCell Double
r) = Double -> Builder
Builder.nanos4 Double
r
newtype PercentageCell
= PercentageCell Double
deriving (PercentageCell -> PercentageCell -> Bool
(PercentageCell -> PercentageCell -> Bool)
-> (PercentageCell -> PercentageCell -> Bool) -> Eq PercentageCell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PercentageCell -> PercentageCell -> Bool
$c/= :: PercentageCell -> PercentageCell -> Bool
== :: PercentageCell -> PercentageCell -> Bool
$c== :: PercentageCell -> PercentageCell -> Bool
Eq) via Double
deriving (Eq PercentageCell
Eq PercentageCell
-> (PercentageCell -> PercentageCell -> Ordering)
-> (PercentageCell -> PercentageCell -> Bool)
-> (PercentageCell -> PercentageCell -> Bool)
-> (PercentageCell -> PercentageCell -> Bool)
-> (PercentageCell -> PercentageCell -> Bool)
-> (PercentageCell -> PercentageCell -> PercentageCell)
-> (PercentageCell -> PercentageCell -> PercentageCell)
-> Ord PercentageCell
PercentageCell -> PercentageCell -> Bool
PercentageCell -> PercentageCell -> Ordering
PercentageCell -> PercentageCell -> PercentageCell
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 :: PercentageCell -> PercentageCell -> PercentageCell
$cmin :: PercentageCell -> PercentageCell -> PercentageCell
max :: PercentageCell -> PercentageCell -> PercentageCell
$cmax :: PercentageCell -> PercentageCell -> PercentageCell
>= :: PercentageCell -> PercentageCell -> Bool
$c>= :: PercentageCell -> PercentageCell -> Bool
> :: PercentageCell -> PercentageCell -> Bool
$c> :: PercentageCell -> PercentageCell -> Bool
<= :: PercentageCell -> PercentageCell -> Bool
$c<= :: PercentageCell -> PercentageCell -> Bool
< :: PercentageCell -> PercentageCell -> Bool
$c< :: PercentageCell -> PercentageCell -> Bool
compare :: PercentageCell -> PercentageCell -> Ordering
$ccompare :: PercentageCell -> PercentageCell -> Ordering
$cp1Ord :: Eq PercentageCell
Ord) via Down Double
instance Cellular PercentageCell where
cellDelta :: PercentageCell -> PercentageCell -> Double
cellDelta = (Double -> Double -> Double)
-> PercentageCell -> PercentageCell -> Double
coerce Double -> Double -> Double
doubleDelta
cellString :: PercentageCell -> Builder
cellString (PercentageCell Double
r) = Double -> Builder
Builder.percentage Double
r
prettyDelta :: Double -> Builder
prettyDelta :: Double -> Builder
prettyDelta Double
n
| Double
n Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= Double
1 = Double -> Builder
Builder.double4 (Double
n Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"x"
| Double
n Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= -Double
0.5 = Double -> Builder
Builder.double4 (-Double
1 Double -> Double -> Double
`divideDouble` (Double
n Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1)) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"x"
| Bool
otherwise = Double -> Builder
Builder.percentage Double
n
newtype PercentageCell'
= PercentageCell' Double
deriving (PercentageCell' -> PercentageCell' -> Bool
(PercentageCell' -> PercentageCell' -> Bool)
-> (PercentageCell' -> PercentageCell' -> Bool)
-> Eq PercentageCell'
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PercentageCell' -> PercentageCell' -> Bool
$c/= :: PercentageCell' -> PercentageCell' -> Bool
== :: PercentageCell' -> PercentageCell' -> Bool
$c== :: PercentageCell' -> PercentageCell' -> Bool
Eq, Eq PercentageCell'
Eq PercentageCell'
-> (PercentageCell' -> PercentageCell' -> Ordering)
-> (PercentageCell' -> PercentageCell' -> Bool)
-> (PercentageCell' -> PercentageCell' -> Bool)
-> (PercentageCell' -> PercentageCell' -> Bool)
-> (PercentageCell' -> PercentageCell' -> Bool)
-> (PercentageCell' -> PercentageCell' -> PercentageCell')
-> (PercentageCell' -> PercentageCell' -> PercentageCell')
-> Ord PercentageCell'
PercentageCell' -> PercentageCell' -> Bool
PercentageCell' -> PercentageCell' -> Ordering
PercentageCell' -> PercentageCell' -> PercentageCell'
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 :: PercentageCell' -> PercentageCell' -> PercentageCell'
$cmin :: PercentageCell' -> PercentageCell' -> PercentageCell'
max :: PercentageCell' -> PercentageCell' -> PercentageCell'
$cmax :: PercentageCell' -> PercentageCell' -> PercentageCell'
>= :: PercentageCell' -> PercentageCell' -> Bool
$c>= :: PercentageCell' -> PercentageCell' -> Bool
> :: PercentageCell' -> PercentageCell' -> Bool
$c> :: PercentageCell' -> PercentageCell' -> Bool
<= :: PercentageCell' -> PercentageCell' -> Bool
$c<= :: PercentageCell' -> PercentageCell' -> Bool
< :: PercentageCell' -> PercentageCell' -> Bool
$c< :: PercentageCell' -> PercentageCell' -> Bool
compare :: PercentageCell' -> PercentageCell' -> Ordering
$ccompare :: PercentageCell' -> PercentageCell' -> Ordering
$cp1Ord :: Eq PercentageCell'
Ord) via Double
deriving (Ord PercentageCell'
Ord PercentageCell'
-> (PercentageCell' -> PercentageCell' -> Double)
-> (PercentageCell' -> Builder)
-> Cellular PercentageCell'
PercentageCell' -> Builder
PercentageCell' -> PercentageCell' -> Double
forall a.
Ord a -> (a -> a -> Double) -> (a -> Builder) -> Cellular a
cellString :: PercentageCell' -> Builder
$ccellString :: PercentageCell' -> Builder
cellDelta :: PercentageCell' -> PercentageCell' -> Double
$ccellDelta :: PercentageCell' -> PercentageCell' -> Double
$cp1Cellular :: Ord PercentageCell'
Cellular) via PercentageCell
newtype IncomparableWord3Cell
= IncomparableWord3Cell Word64
deriving (IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
(IncomparableWord3Cell -> IncomparableWord3Cell -> Bool)
-> (IncomparableWord3Cell -> IncomparableWord3Cell -> Bool)
-> Eq IncomparableWord3Cell
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
$c/= :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
== :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
$c== :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
Eq) via Word64
deriving (Eq IncomparableWord3Cell
Eq IncomparableWord3Cell
-> (IncomparableWord3Cell -> IncomparableWord3Cell -> Ordering)
-> (IncomparableWord3Cell -> IncomparableWord3Cell -> Bool)
-> (IncomparableWord3Cell -> IncomparableWord3Cell -> Bool)
-> (IncomparableWord3Cell -> IncomparableWord3Cell -> Bool)
-> (IncomparableWord3Cell -> IncomparableWord3Cell -> Bool)
-> (IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell)
-> (IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell)
-> Ord IncomparableWord3Cell
IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
IncomparableWord3Cell -> IncomparableWord3Cell -> Ordering
IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell
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 :: IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell
$cmin :: IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell
max :: IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell
$cmax :: IncomparableWord3Cell
-> IncomparableWord3Cell -> IncomparableWord3Cell
>= :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
$c>= :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
> :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
$c> :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
<= :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
$c<= :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
< :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
$c< :: IncomparableWord3Cell -> IncomparableWord3Cell -> Bool
compare :: IncomparableWord3Cell -> IncomparableWord3Cell -> Ordering
$ccompare :: IncomparableWord3Cell -> IncomparableWord3Cell -> Ordering
$cp1Ord :: Eq IncomparableWord3Cell
Ord) via Down Word64
instance Cellular IncomparableWord3Cell where
cellDelta :: IncomparableWord3Cell -> IncomparableWord3Cell -> Double
cellDelta IncomparableWord3Cell
_ IncomparableWord3Cell
_ = Double
0
cellString :: IncomparableWord3Cell -> Builder
cellString (IncomparableWord3Cell Word64
r) = Word64 -> Builder
Builder.word3 Word64
r
doubleDelta :: Double -> Double -> Double
doubleDelta :: Double -> Double -> Double
doubleDelta Double
v1 Double
v2 =
(Double
v2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
v1) Double -> Double -> Double
`divideDouble` Double
v1
rowMaker :: forall a. NonEmpty a -> (forall b. Cellular b => R a b -> Row)
rowMaker :: NonEmpty a -> forall b. Cellular b => R a b -> Row
rowMaker (a
summary0 :| [a]
summaries0) (R Cell
name (a -> Maybe b
f :: a -> Maybe b)) =
if (Cell -> Bool) -> [Cell] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Cell -> Bool
isEmptyCell [Cell]
cols
then Row
EmptyRow
else [Cell] -> Row
Row (Cell
name Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: [Cell]
cols)
where
cols :: [Cell]
cols :: [Cell]
cols =
Cell -> (b -> Cell) -> Maybe b -> Cell
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Cell
EmptyCell (Color -> Text -> Cell
Cell Color
White (Text -> Cell) -> (b -> Text) -> b -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.build (Builder -> Text) -> (b -> Builder) -> b -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Builder
forall a. Cellular a => a -> Builder
cellString) (a -> Maybe b
f a
summary0) Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Maybe b -> [a] -> [Cell]
makeCols (a -> Maybe b
f a
summary0) [a]
summaries0
makeCols :: Maybe b -> [a] -> [Cell]
makeCols :: Maybe b -> [a] -> [Cell]
makeCols Maybe b
s0 = \case
[] ->
case [a]
summaries0 of
[] -> []
[a]
_ ->
case (a -> Maybe b
f a
summary0, a -> Maybe b
f ([a] -> a
forall a. [a] -> a
last [a]
summaries0)) of
(Just b
v0, Just b
v1) -> [b -> b -> Cell
delta b
v0 b
v1]
(Maybe b, Maybe b)
_ -> []
a
s1 : [a]
ss ->
case (Maybe b
s0, a -> Maybe b
f a
s1) of
(Maybe b
Nothing, Just b
v1) -> Cell
EmptyCell Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Color -> Text -> Cell
Cell Color
White (Builder -> Text
Builder.build (b -> Builder
forall a. Cellular a => a -> Builder
cellString b
v1)) Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Maybe b -> [a] -> [Cell]
makeCols (b -> Maybe b
forall a. a -> Maybe a
Just b
v1) [a]
ss
(Just b
v0, Just b
v1) -> b -> b -> Cell
delta b
v0 b
v1 Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Color -> Text -> Cell
Cell Color
White (Builder -> Text
Builder.build (b -> Builder
forall a. Cellular a => a -> Builder
cellString b
v1)) Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Maybe b -> [a] -> [Cell]
makeCols (b -> Maybe b
forall a. a -> Maybe a
Just b
v1) [a]
ss
(Maybe b
_, Maybe b
Nothing) -> Cell
EmptyCell Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Cell
EmptyCell Cell -> [Cell] -> [Cell]
forall a. a -> [a] -> [a]
: Maybe b -> [a] -> [Cell]
makeCols Maybe b
forall a. Maybe a
Nothing [a]
ss
delta :: b -> b -> Cell
delta :: b -> b -> Cell
delta b
v1 b
v2 =
if Builder -> Bool
Builder.null (b -> Builder
forall a. Cellular a => a -> Builder
cellString b
v1) Bool -> Bool -> Bool
|| Builder -> Bool
Builder.null (b -> Builder
forall a. Cellular a => a -> Builder
cellString b
v2)
then Cell
EmptyCell
else Builder -> Cell
colorize (Double -> Builder
prettyDelta (b -> b -> Double
forall a. Cellular a => a -> a -> Double
cellDelta b
v1 b
v2))
where
colorize :: Builder -> Cell
colorize :: Builder -> Cell
colorize =
( case b -> b -> Ordering
forall a. Ord a => a -> a -> Ordering
compare b
v1 b
v2 of
Ordering
LT -> Color -> Text -> Cell
Cell Color
Green
Ordering
EQ -> Color -> Text -> Cell
Cell Color
White
Ordering
GT -> Color -> Text -> Cell
Cell Color
Red
)
(Text -> Cell) -> (Builder -> Text) -> Builder -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.build
data Table
= Table ![Cell] ![RowGroup]
data RowGroup
= RowGroup {-# UNPACK #-} !Text ![Row]
data Row
=
Row ![Cell]
| EmptyRow
data Cell
= EmptyCell
| Cell !Color {-# UNPACK #-} !Text
cellBuilder :: Cell -> Builder
cellBuilder :: Cell -> Builder
cellBuilder = \case
Cell
EmptyCell -> Builder
Builder.empty
Cell Color
color (Text -> Builder
Builder.t -> Builder
s) ->
case Color
color of
Color
Blue -> Builder -> Builder
Terminal.blue Builder
s
Color
Green -> Builder -> Builder
Terminal.green Builder
s
Color
Red -> Builder -> Builder
Terminal.red Builder
s
Color
White -> Builder
s
cellWidth :: Cell -> Int
cellWidth :: Cell -> Int
cellWidth = \case
Cell Color
_ Text
s -> Text -> Int
Text.length Text
s
Cell
EmptyCell -> Int
0
instance IsString Cell where
fromString :: String -> Cell
fromString =
Color -> Text -> Cell
Cell Color
White (Text -> Cell) -> (String -> Text) -> String -> Cell
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack
data Color
= Blue
| Green
| Red
| White
isEmptyCell :: Cell -> Bool
isEmptyCell :: Cell -> Bool
isEmptyCell = \case
Cell Color
_ Text
s -> Text -> Bool
Text.null Text
s
Cell
EmptyCell -> Bool
True
data Align
= AlignLeft
| AlignRight
renderTable :: Table -> Builder
renderTable :: Table -> Builder
renderTable (Table [Cell]
labels [RowGroup]
rowGroups) =
(Builder
header Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
: (RowGroup -> Maybe Builder) -> [RowGroup] -> [Builder]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe RowGroup -> Maybe Builder
renderRowGroup [RowGroup]
rowGroups [Builder] -> [Builder] -> [Builder]
forall a. [a] -> [a] -> [a]
++ [Builder
footer]) [Builder] -> Builder -> Builder
`Builder.sepBy` Char -> Builder
Builder.c Char
'\n'
where
header :: Builder
header :: Builder
header =
Char -> Builder
Builder.c Char
'┌'
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ((((Int, Cell) -> Builder) -> [(Int, Cell)] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map (Align -> Char -> (Int, Cell) -> Builder
renderCell Align
AlignLeft Char
'─') ([Int] -> [Cell] -> [(Int, Cell)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Int -> Int) -> [Int] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) [Int]
widths) [Cell]
labels)) [Builder] -> Builder -> Builder
`Builder.sepBy` Char -> Builder
Builder.c Char
'┬')
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
Builder.c Char
'┐'
footer :: Builder
footer :: Builder
footer =
Char -> Builder
Builder.c Char
'└'
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (((Int -> Builder) -> [Int] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
n -> Int -> Char -> Builder
Builder.cs (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) Char
'─') [Int]
widths) [Builder] -> Builder -> Builder
`Builder.sepBy` Char -> Builder
Builder.c Char
'┴')
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
Builder.c Char
'┘'
renderRowGroup :: RowGroup -> Maybe Builder
renderRowGroup :: RowGroup -> Maybe Builder
renderRowGroup (RowGroup Text
label [Row]
rows) =
case (Row -> Maybe Builder) -> [Row] -> [Builder]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Row -> Maybe Builder
renderRow [Row]
rows of
[] -> Maybe Builder
forall a. Maybe a
Nothing
[Builder]
s -> Builder -> Maybe Builder
forall a. a -> Maybe a
Just ((Builder
line Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
: [Builder]
s) [Builder] -> Builder -> Builder
`Builder.sepBy` Char -> Builder
Builder.c Char
'\n')
where
line :: Builder
line =
Char -> Builder
Builder.c Char
'├'
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\ESC[1m\ESC[97m"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Text -> Builder
Builder.t ((Char -> Char) -> Text -> Text
Text.map Char -> Char
dash Text
label)
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\ESC[39m\ESC[22m"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Int -> Char -> Builder
Builder.cs ([Int] -> Int
forall a. [a] -> a
head [Int]
widths Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Text -> Int
Text.length Text
label) Char
'─'
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (Int -> Builder) -> [Int] -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Int
n -> Char -> Builder
Builder.c Char
'┼' Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Int -> Char -> Builder
Builder.cs (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
2) Char
'─') ([Int] -> [Int]
forall a. [a] -> [a]
tail [Int]
widths)
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Char -> Builder
Builder.c Char
'┤'
dash :: Char -> Char
dash :: Char -> Char
dash = \case
Char
' ' -> Char
'─'
Char
c -> Char
c
renderRow :: Row -> Maybe Builder
renderRow :: Row -> Maybe Builder
renderRow = \case
Row [Cell]
row -> Builder -> Maybe Builder
forall a. a -> Maybe a
Just (Builder
"│ " Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ((((Int, Cell) -> Builder) -> [(Int, Cell)] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map (Align -> Char -> (Int, Cell) -> Builder
renderCell Align
AlignRight Char
' ') ([Int] -> [Cell] -> [(Int, Cell)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
widths [Cell]
row)) [Builder] -> Builder -> Builder
`Builder.sepBy` Builder
" │ ") Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
" │")
Row
EmptyRow -> Maybe Builder
forall a. Maybe a
Nothing
renderCell :: Align -> Char -> (Int, Cell) -> Builder
renderCell :: Align -> Char -> (Int, Cell) -> Builder
renderCell Align
align Char
bg (Int
n, Cell
cell) =
case Align
align of
Align
AlignLeft -> Cell -> Builder
cellBuilder Cell
cell Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
padding
Align
AlignRight -> Builder
padding Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Cell -> Builder
cellBuilder Cell
cell
where
padding :: Builder
padding = Int -> Char -> Builder
Builder.cs (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Cell -> Int
cellWidth Cell
cell) Char
bg
widths :: [Int]
widths :: [Int]
widths =
([Int] -> RowGroup -> [Int]) -> [Int] -> [RowGroup] -> [Int]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' [Int] -> RowGroup -> [Int]
step0 ((Cell -> Int) -> [Cell] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
1 (Int -> Int) -> (Cell -> Int) -> Cell -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cell -> Int
cellWidth) [Cell]
labels) [RowGroup]
rowGroups
where
step0 :: [Int] -> RowGroup -> [Int]
step0 :: [Int] -> RowGroup -> [Int]
step0 [Int]
acc (RowGroup Text
label [Row]
rows) =
([Int] -> Row -> [Int]) -> [Int] -> [Row] -> [Int]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Text -> [Int] -> Row -> [Int]
step1 Text
label) [Int]
acc [Row]
rows
step1 :: Text -> [Int] -> Row -> [Int]
step1 :: Text -> [Int] -> Row -> [Int]
step1 Text
label [Int]
acc = \case
Row [] -> String -> [Int]
forall a. HasCallStack => String -> a
error String
"empty row"
Row (Cell
col : [Cell]
cols) -> (Int -> Int -> Int) -> [Int] -> [Int] -> [Int]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max (Text -> Int
Text.length Text
label) (Cell -> Int
cellWidth Cell
col) Int -> [Int] -> [Int]
forall a. a -> [a] -> [a]
: (Cell -> Int) -> [Cell] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Cell -> Int
cellWidth [Cell]
cols) [Int]
acc
Row
EmptyRow -> [Int]
acc