{-# OPTIONS_GHC -Wall #-}

{-# LANGUAGE StrictData #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}


-- | Helper and Utility Functions
module Lib where

import           Data.Maybe
import           Data.List
import           Data.Text.Internal.Lazy        (empty)
import           Data.Text.Lazy                 (pack)
import           Data.Time.Clock                (getCurrentTime)
import           Data.Time.Format               (formatTime, defaultTimeLocale)
import           System.Directory
import           System.ProgressBar
import qualified Torch                     as T
import qualified Torch.Extensions          as T
-- import qualified Torch.Functional.Internal as T (where')

------------------------------------------------------------------------------
-- Data Types
------------------------------------------------------------------------------

-- | Available PDKs
data PDK = XH035    -- ^ X-Fab XH035 350nm Process
         | XH018    -- ^ X-Fab XH018 180nm Process
         | XT018    -- ^ X-Fab XT018 180nm Process
         | GPDK180  -- ^ Fictional Cadence GPDK180 GPDK 180nm Process
         | GPDK090  -- ^ Fictional Cadence GPDK090 GPDK 90nm Process
         | GPDK045  -- ^ Fictional Cadence GPDK045 GPDK 45nm Process
         | SKY130   -- ^ SkyWater SKY130 130nm Process
         | PTM130   -- ^ Fictional Predictive Technology Models PTM130 130nm Process
    deriving (PDK -> PDK -> Bool
(PDK -> PDK -> Bool) -> (PDK -> PDK -> Bool) -> Eq PDK
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PDK -> PDK -> Bool
$c/= :: PDK -> PDK -> Bool
== :: PDK -> PDK -> Bool
$c== :: PDK -> PDK -> Bool
Eq)

instance Show PDK where
  show :: PDK -> String
show PDK
XH035   = String
"xh035"
  show PDK
XH018   = String
"xh018"
  show PDK
XT018   = String
"xt018"
  show PDK
GPDK180 = String
"gpdk180"
  show PDK
GPDK090 = String
"gpdk090"
  show PDK
GPDK045 = String
"gpdk045"
  show PDK
SKY130  = String
"sky130"
  show PDK
PTM130  = String
"ptm130"

instance Read PDK where
  readsPrec :: Int -> ReadS PDK
readsPrec Int
_ String
"xh035"   = [(PDK
XH035, String
"")]
  readsPrec Int
_ String
"xh018"   = [(PDK
XH018, String
"")]
  readsPrec Int
_ String
"xt018"   = [(PDK
XT018, String
"")]
  readsPrec Int
_ String
"gpdk180" = [(PDK
GPDK180, String
"")]
  readsPrec Int
_ String
"gpdk090" = [(PDK
GPDK090, String
"")]
  readsPrec Int
_ String
"gpdk045" = [(PDK
GPDK045, String
"")]
  readsPrec Int
_ String
"sky130"  = [(PDK
SKY130, String
"")]
  readsPrec Int
_ String
"ptm130"  = [(PDK
PTM130, String
"")]
  readsPrec Int
_ String
_         = [(PDK, String)]
forall a. HasCallStack => a
undefined

-- | Device Types
data Device = NMOS -- ^ NMOS
            | PMOS -- ^ PMOS
    deriving (Device -> Device -> Bool
(Device -> Device -> Bool)
-> (Device -> Device -> Bool) -> Eq Device
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Device -> Device -> Bool
$c/= :: Device -> Device -> Bool
== :: Device -> Device -> Bool
$c== :: Device -> Device -> Bool
Eq)

instance Show Device where
  show :: Device -> String
show Device
NMOS = String
"nmos"
  show Device
PMOS = String
"pmos"

instance Read Device where
  readsPrec :: Int -> ReadS Device
readsPrec Int
_ String
"nmos" = [(Device
NMOS, String
"")]
  readsPrec Int
_ String
"pmos" = [(Device
PMOS, String
"")]
  readsPrec Int
_ String
_      = [(Device, String)]
forall a. HasCallStack => a
undefined

------------------------------------------------------------------------------
-- General
------------------------------------------------------------------------------

-- | First of Triple
fst3 :: (a,b,c) -> a
fst3 :: (a, b, c) -> a
fst3 (a
a,b
_,c
_) = a
a

-- | Uncurry triple
uncurry' :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry' :: (a -> b -> c -> d) -> (a, b, c) -> d
uncurry' a -> b -> c -> d
f (a
a,b
b,c
c) = a -> b -> c -> d
f a
a b
b c
c

-- | Create single element list from given element
singleton :: a -> [a]
singleton :: a -> [a]
singleton a
x = [a
x]

-- | Create a boolean mask from a subset of column names
boolMask :: [String] -> [String] -> [Bool]
boolMask :: [String] -> [String] -> [Bool]
boolMask [String]
sub = (String -> Bool) -> [String] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map (String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
sub)

-- | Create a boolean mask Tensor from a subset of column names
boolMask' :: [String] -> [String] -> T.Tensor
boolMask' :: [String] -> [String] -> Tensor
boolMask' [String]
sub [String]
set = [Bool] -> TensorOptions -> Tensor
forall a. TensorLike a => a -> TensorOptions -> Tensor
T.asTensor' ([String] -> [String] -> [Bool]
boolMask [String]
sub [String]
set) 
                  (TensorOptions -> Tensor) -> TensorOptions -> Tensor
forall a b. (a -> b) -> a -> b
$ DType -> TensorOptions -> TensorOptions
T.withDType DType
T.Bool TensorOptions
T.defaultOpts

-- | Create Integer Index for a subset of column names
intIdx :: [String] -> [String] -> [Int]
intIdx :: [String] -> [String] -> [Int]
intIdx [String]
set = Maybe [Int] -> [Int]
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe [Int] -> [Int])
-> ([String] -> Maybe [Int]) -> [String] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Maybe Int] -> Maybe [Int]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([Maybe Int] -> Maybe [Int])
-> ([String] -> [Maybe Int]) -> [String] -> Maybe [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Int -> Bool) -> [Maybe Int] -> [Maybe Int]
forall a. (a -> Bool) -> [a] -> [a]
filter Maybe Int -> Bool
forall a. Maybe a -> Bool
isJust ([Maybe Int] -> [Maybe Int])
-> ([String] -> [Maybe Int]) -> [String] -> [Maybe Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Maybe Int) -> [String] -> [Maybe Int]
forall a b. (a -> b) -> [a] -> [b]
map (String -> [String] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
`elemIndex` [String]
set)

-- | Create Integer Index Tensor for a subset of column names
intIdx' :: [String] -> [String] -> T.Tensor
intIdx' :: [String] -> [String] -> Tensor
intIdx' [String]
set [String]
sub = [Int] -> TensorOptions -> Tensor
forall a. TensorLike a => a -> TensorOptions -> Tensor
T.asTensor' ([String] -> [String] -> [Int]
intIdx [String]
set [String]
sub) 
                (TensorOptions -> Tensor) -> TensorOptions -> Tensor
forall a b. (a -> b) -> a -> b
$ DType -> TensorOptions -> TensorOptions
T.withDType DType
T.Int64 TensorOptions
T.defaultOpts

-- | Round Float Tensor to n digits
round :: Int -> T.Tensor -> T.Tensor
round :: Int -> Tensor -> Tensor
round Int
digits = (Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* (Tensor
1 Tensor -> Tensor -> Tensor
forall a. Fractional a => a -> a -> a
/ Tensor
d)) (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tensor -> Tensor
T.ceil (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* Tensor
d)
  where
    d :: Tensor
d = Float -> Tensor
forall a. TensorLike a => a -> Tensor
T.asTensor (Float -> Tensor) -> Float -> Tensor
forall a b. (a -> b) -> a -> b
$ Float
10 Float -> Float -> Float
forall a. Floating a => a -> a -> a
** (Int -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac Int
digits :: Float)

-- | (Re-) Shuffle batches
shuffleBatches :: Int -> T.Tensor -> T.Tensor -> IO ([T.Tensor], [T.Tensor])
shuffleBatches :: Int -> Tensor -> Tensor -> IO ([Tensor], [Tensor])
shuffleBatches Int
s Tensor
x Tensor
y = do
    Tensor
idx <- Tensor -> Int -> Bool -> IO Tensor
T.multinomialIO ([Float] -> Tensor
forall a. TensorLike a => a -> Tensor
T.asTensor @[Float] [ Float
0 .. Int -> Float
forall a b. (Real a, Fractional b) => a -> b
realToFrac Int
n Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
1]) Int
n Bool
False
    let x' :: [Tensor]
x' = Int -> Dim -> Tensor -> [Tensor]
T.split Int
s (Int -> Dim
T.Dim Int
0) (Tensor -> [Tensor]) -> (Tensor -> Tensor) -> Tensor -> [Tensor]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Device -> Tensor -> Tensor
forall a. HasTypes a Tensor => Device -> a -> a
T.toDevice Device
T.gpu (Tensor -> [Tensor]) -> Tensor -> [Tensor]
forall a b. (a -> b) -> a -> b
$ Int -> Tensor -> Tensor -> Tensor
T.indexSelect Int
0 Tensor
idx Tensor
x
        y' :: [Tensor]
y' = Int -> Dim -> Tensor -> [Tensor]
T.split Int
s (Int -> Dim
T.Dim Int
0) (Tensor -> [Tensor]) -> (Tensor -> Tensor) -> Tensor -> [Tensor]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Device -> Tensor -> Tensor
forall a. HasTypes a Tensor => Device -> a -> a
T.toDevice Device
T.gpu (Tensor -> [Tensor]) -> Tensor -> [Tensor]
forall a b. (a -> b) -> a -> b
$ Int -> Tensor -> Tensor -> Tensor
T.indexSelect Int
0 Tensor
idx Tensor
y
    ([Tensor], [Tensor]) -> IO ([Tensor], [Tensor])
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Tensor]
x', [Tensor]
y')
  where
    n :: Int
n = [Int] -> Int
forall a. [a] -> a
head ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ Tensor -> [Int]
T.shape Tensor
x

------------------------------------------------------------------------------
-- Scaling and Transforming
------------------------------------------------------------------------------

-- | Scale data to [0;1]
scale :: T.Tensor -> T.Tensor -> T.Tensor -> T.Tensor
scale :: Tensor -> Tensor -> Tensor -> Tensor
scale Tensor
xMin Tensor
xMax Tensor
x = (Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
- Tensor
xMin) Tensor -> Tensor -> Tensor
forall a. Fractional a => a -> a -> a
/ (Tensor
xMax Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
- Tensor
xMin)

-- | Un-Scale data from [0;1]
scale' :: T.Tensor -> T.Tensor -> T.Tensor -> T.Tensor
scale' :: Tensor -> Tensor -> Tensor -> Tensor
scale' Tensor
xMin Tensor
xMax Tensor
x = (Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* (Tensor
xMax Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
- Tensor
xMin)) Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
+ Tensor
xMin

-- | Apply log10 to masked data
trafo :: T.Tensor -> T.Tensor -> T.Tensor
trafo :: Tensor -> Tensor -> Tensor
trafo Tensor
b Tensor
x = Tensor
y Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
+ Tensor
y'
  where
    m :: Tensor
m  = DType -> Tensor -> Tensor
T.toDType DType
T.Float (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tensor -> Tensor -> Tensor
T.logicalAnd Tensor
b (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tensor -> Tensor -> Tensor
T.lt Tensor
0.0 (Tensor -> Tensor) -> Tensor -> Tensor
forall a b. (a -> b) -> a -> b
$ Tensor -> Tensor
T.abs Tensor
x 
    m' :: Tensor
m' = Tensor
1.0 Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
- Tensor
m
    o :: Tensor
o  = Tensor -> Tensor -> Tensor
T.mul Tensor
m' (Tensor -> Tensor) -> Tensor -> Tensor
forall a b. (a -> b) -> a -> b
$ Tensor -> Tensor
T.onesLike Tensor
x
    y :: Tensor
y  = Tensor -> Tensor
T.log10 (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tensor -> Tensor
T.abs (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tensor -> Tensor -> Tensor
T.add Tensor
o (Tensor -> Tensor) -> Tensor -> Tensor
forall a b. (a -> b) -> a -> b
$ Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* Tensor
m
    y' :: Tensor
y' = Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* Tensor
m'

-- | Apply pow10 to masked data
trafo' :: T.Tensor -> T.Tensor -> T.Tensor
trafo' :: Tensor -> Tensor -> Tensor
trafo' Tensor
b Tensor
x = Tensor
y Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
+ Tensor
y'
  where
    m :: Tensor
m  = DType -> Tensor -> Tensor
T.toDType DType
T.Float Tensor
b
    m' :: Tensor
m' = DType -> Tensor -> Tensor
T.toDType DType
T.Float (Tensor -> Tensor) -> Tensor -> Tensor
forall a b. (a -> b) -> a -> b
$ Tensor -> Tensor
T.logicalNot Tensor
b
    y :: Tensor
y  = Tensor -> Tensor -> Tensor
T.mul Tensor
m (Tensor -> Tensor) -> (Tensor -> Tensor) -> Tensor -> Tensor
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tensor -> Tensor
T.pow10 (Tensor -> Tensor) -> Tensor -> Tensor
forall a b. (a -> b) -> a -> b
$ Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* Tensor
m
    y' :: Tensor
y' = Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* Tensor
m'

-- | calculate gm from gm/Id and Id, input is [gm/Id, Id, fug, Vds, Vbs]
process :: T.Tensor -> T.Tensor
process :: Tensor -> Tensor
process Tensor
x = Dim -> [Tensor] -> Tensor
T.cat (Int -> Dim
T.Dim Int
1) [ Tensor
gm, Tensor
x ]
  where
    gm :: Tensor
gm = [Int] -> Tensor -> Tensor
T.reshape [-Int
1, Int
1] (Tensor -> Tensor) -> Tensor -> Tensor
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Tensor -> Tensor
T.select Int
1 Int
0 Tensor
x Tensor -> Tensor -> Tensor
forall a. Num a => a -> a -> a
* Int -> Int -> Tensor -> Tensor
T.select Int
1 Int
1 Tensor
x

------------------------------------------------------------------------------
-- Saving and Loading Tensors
------------------------------------------------------------------------------

-- | Default Column Names for stored Tensors
columnHeader :: [String]
columnHeader :: [String]
columnHeader = [ String
"W", String
"L", String
"M", String
"temp", String
"region"
               , String
"vds", String
"vgs", String
"vbs", String
"vth", String
"vdsat", String
"vearly"
               , String
"gm", String
"gds", String
"gmbs", String
"self_gain", String
"ron", String
"rout"
               , String
"id", String
"gmoverid", String
"fug", String
"betaeff", String
"pwr"
               , String
"cgg", String
"cgd", String
"cgs", String
"cgb"
               , String
"cdg", String
"cdd", String
"cds", String
"cdb"
               , String
"csg", String
"csd", String
"css", String
"csb"
               , String
"cbg", String
"cbd", String
"cbs", String
"cbb" ]

-- | Load a Pickled Tensor from file
loadTensor :: FilePath -> IO T.Tensor
loadTensor :: String -> IO Tensor
loadTensor String
path = do
    T.IVTensor Tensor
t <- String -> IO IValue
T.pickleLoad String
path
    Tensor -> IO Tensor
forall (f :: * -> *) a. Applicative f => a -> f a
pure Tensor
t

-- | Pickle a Tensor and Save to file
saveTensor :: T.Tensor -> FilePath -> IO ()
saveTensor :: Tensor -> String -> IO ()
saveTensor Tensor
t String
path = do
    let t' :: IValue
t' = Tensor -> IValue
T.IVTensor Tensor
t
    IValue -> String -> IO ()
T.pickleSave IValue
t' String
path

------------------------------------------------------------------------------
-- File System
------------------------------------------------------------------------------

-- | Current Timestamp as formatted string
currentTimeStamp :: String -> IO String
currentTimeStamp :: String -> IO String
currentTimeStamp String
format = TimeLocale -> String -> UTCTime -> String
forall t. FormatTime t => TimeLocale -> String -> t -> String
formatTime TimeLocale
defaultTimeLocale String
format (UTCTime -> String) -> IO UTCTime -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO UTCTime
getCurrentTime

-- | Current Timestamp with default formatting: "%Y%m%d-%H%M%S"
currentTimeStamp' :: IO String
currentTimeStamp' :: IO String
currentTimeStamp' = String -> IO String
currentTimeStamp String
"%Y%m%d-%H%M%S"

-- | Create a model archive directory for the given pdk and device type
createModelDir :: String -> String -> IO String
createModelDir :: String -> String -> IO String
createModelDir String
pdk' String
dev' = do
    String
path <- (String
path' String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> IO String -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO String
currentTimeStamp'
    Bool -> String -> IO ()
createDirectoryIfMissing Bool
True String
path
    String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
path
  where
    path' :: String
path' = String
"./models/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
pdk' String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
dev' String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"-"

-- | Just for the notebooks, to create a directory above
createModelDir' :: String -> String -> IO String
createModelDir' :: String -> String -> IO String
createModelDir' String
pdk' String
dev' = do
    String
path <- (String
path' String -> ShowS
forall a. [a] -> [a] -> [a]
++) ShowS -> IO String -> IO String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO String
currentTimeStamp'
    Bool -> String -> IO ()
createDirectoryIfMissing Bool
True String
path
    String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
path
  where
    path' :: String
path' = String
"../models/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
pdk' String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/" String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
dev' String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"-"

------------------------------------------------------------------------------
-- Command Line Argument Parser
------------------------------------------------------------------------------

-- | Command Line Arguments
data Args = Args { Args -> PDK
pdk  :: !PDK      -- ^ PDK
                 , Args -> Device
dev  :: !Device   -- ^ NMOS | PMOS
                 , Args -> String
dir  :: !FilePath -- ^ Path to Data
                 , Args -> Int
num  :: !Int      -- ^ Number of Epochs
                 , Args -> Int
reg  :: !Int      -- ^ Area of Operation
                 , Args -> Int
size :: !Int      -- ^ Batch Size
                 , Args -> Bool
exp  :: !Bool     -- ^ Experimental
                 } deriving (Int -> Args -> ShowS
[Args] -> ShowS
Args -> String
(Int -> Args -> ShowS)
-> (Args -> String) -> ([Args] -> ShowS) -> Show Args
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Args] -> ShowS
$cshowList :: [Args] -> ShowS
show :: Args -> String
$cshow :: Args -> String
showsPrec :: Int -> Args -> ShowS
$cshowsPrec :: Int -> Args -> ShowS
Show)

------------------------------------------------------------------------------
-- Progress Style
------------------------------------------------------------------------------

-- | Progress Bar Style for Training
trainStyle :: Int -> Style s
trainStyle :: Int -> Style s
trainStyle Int
epoch = Style :: forall s.
Text
-> Text
-> Char
-> Char
-> Char
-> Label s
-> Label s
-> ProgressBarWidth
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> OnComplete
-> Style s
Style { styleOpen :: Text
styleOpen          = Text
"╢"
                         , styleClose :: Text
styleClose         = Text
"╟"
                         , styleDone :: Char
styleDone          = Char
'█'
                         , styleCurrent :: Char
styleCurrent       = Char
'░'
                         , styleTodo :: Char
styleTodo          = Char
'░'
                         , stylePrefix :: Label s
stylePrefix        = Text -> Label s
forall s. Text -> Label s
msg (Text -> Label s) -> (String -> Text) -> String -> Label s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Label s) -> String -> Label s
forall a b. (a -> b) -> a -> b
$ String
"Training Epoch " 
                                                                String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
epoch
                         , stylePostfix :: Label s
stylePostfix       = Label s
forall s. Label s
percentage
                         , styleWidth :: ProgressBarWidth
styleWidth         = Int -> ProgressBarWidth
ConstantWidth Int
60
                         , styleEscapeOpen :: EscapeCode s
styleEscapeOpen    = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeClose :: EscapeCode s
styleEscapeClose   = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeDone :: EscapeCode s
styleEscapeDone    = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeCurrent :: EscapeCode s
styleEscapeCurrent = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeTodo :: EscapeCode s
styleEscapeTodo    = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapePrefix :: EscapeCode s
styleEscapePrefix  = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapePostfix :: EscapeCode s
styleEscapePostfix = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleOnComplete :: OnComplete
styleOnComplete    = OnComplete
WriteNewline
                         }

-- | Progress Bar Style for Validation
validStyle :: Int -> Style s
validStyle :: Int -> Style s
validStyle Int
epoch = Style :: forall s.
Text
-> Text
-> Char
-> Char
-> Char
-> Label s
-> Label s
-> ProgressBarWidth
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> EscapeCode s
-> OnComplete
-> Style s
Style { styleOpen :: Text
styleOpen          = Text
"╢"
                         , styleClose :: Text
styleClose         = Text
"╟"
                         , styleDone :: Char
styleDone          = Char
'█'
                         , styleCurrent :: Char
styleCurrent       = Char
'░'
                         , styleTodo :: Char
styleTodo          = Char
'░'
                         , stylePrefix :: Label s
stylePrefix        = Text -> Label s
forall s. Text -> Label s
msg (Text -> Label s) -> (String -> Text) -> String -> Label s
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> Label s) -> String -> Label s
forall a b. (a -> b) -> a -> b
$ String
"Validation Epoch " 
                                                                String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
epoch
                         , stylePostfix :: Label s
stylePostfix       = Label s
forall s. Label s
percentage
                         , styleWidth :: ProgressBarWidth
styleWidth         = Int -> ProgressBarWidth
ConstantWidth Int
60
                         , styleEscapeOpen :: EscapeCode s
styleEscapeOpen    = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeClose :: EscapeCode s
styleEscapeClose   = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeDone :: EscapeCode s
styleEscapeDone    = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeCurrent :: EscapeCode s
styleEscapeCurrent = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapeTodo :: EscapeCode s
styleEscapeTodo    = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapePrefix :: EscapeCode s
styleEscapePrefix  = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleEscapePostfix :: EscapeCode s
styleEscapePostfix = Text -> EscapeCode s
forall a b. a -> b -> a
const Text
empty
                         , styleOnComplete :: OnComplete
styleOnComplete    = OnComplete
WriteNewline
                         }