{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
-- Functions for rendering ticky sample information
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE QuasiQuotes #-}
module Eventlog.Ticky (tickyTab, renderTicky) where

import qualified Data.Map as Map
import Data.Word

import qualified Data.Text as T
--import Text.Blaze.Html
import qualified Text.Blaze.Html5            as H
import Text.Blaze.Html5 as H
    ( preEscapedToHtml,
      toHtml,
      dataAttribute,
      Html,
      (!),
      code,
      div,
      script,
      table,
      td,
      th,
      thead,
      tr )
import Text.Blaze.Html5.Attributes as A
    ( class_, id )

import Eventlog.Types
import Text.RawString.QQ
import Data.Fixed
import Control.Monad

import Data.List (foldl', sortBy)
import Data.Ord

renderTicky :: Word64 -> Map.Map TickyCounterId TickyCounter
                      -> Map.Map InfoTablePtr InfoTableLoc
                      -> [TickySample] -> (Double, Html)
renderTicky :: Word64
-> Map TickyCounterId TickyCounter
-> Map InfoTablePtr InfoTableLoc
-> [TickySample]
-> (Double, Html)
renderTicky Word64
total_allocs Map TickyCounterId TickyCounter
counters Map InfoTablePtr InfoTableLoc
ipes [TickySample]
samples = (Double
percentage_ticked, Bool
-> Map
     TickyCounterId
     (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
-> Html
renderTickyInfo (Bool -> Bool
not (Map InfoTablePtr InfoTableLoc -> Bool
forall k a. Map k a -> Bool
Map.null Map InfoTablePtr InfoTableLoc
ipes)) Map
  TickyCounterId
  (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
joined_with_ipe)
  where
    percentage_ticked :: Double
percentage_ticked = Word64 -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (Map TickyCounterId Word64 -> Word64
forall a. Num a => Map TickyCounterId a -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((AccumStats -> Word64)
-> Map TickyCounterId AccumStats -> Map TickyCounterId Word64
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map AccumStats -> Word64
allocs Map TickyCounterId AccumStats
accum_samples)) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Word64 -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Word64
total_allocs
    joined_with_ipe :: Map
  TickyCounterId
  (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
joined_with_ipe   = (TickyCounterId
 -> (TickyCounter, AccumStats, Double) -> InfoTablePtr)
-> Map TickyCounterId (TickyCounter, AccumStats, Double)
-> Map InfoTablePtr InfoTableLoc
-> Map
     TickyCounterId
     (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
forall k a.
(k -> a -> InfoTablePtr)
-> Map k a
-> Map InfoTablePtr InfoTableLoc
-> Map k (InfoTableLocStatus, a)
mkClosureInfo (\TickyCounterId
_ (TickyCounter
v, AccumStats
_, Double
_) -> TickyCounter -> InfoTablePtr
tickyCtrInfo TickyCounter
v) Map TickyCounterId (TickyCounter, AccumStats, Double)
joined_data Map InfoTablePtr InfoTableLoc
ipes

    joined_data :: Map TickyCounterId (TickyCounter, AccumStats, Double)
joined_data   = (TickyCounterId
 -> TickyCounter
 -> AccumStats
 -> Maybe (TickyCounter, AccumStats, Double))
-> (Map TickyCounterId TickyCounter
    -> Map TickyCounterId (TickyCounter, AccumStats, Double))
-> (Map TickyCounterId AccumStats
    -> Map TickyCounterId (TickyCounter, AccumStats, Double))
-> Map TickyCounterId TickyCounter
-> Map TickyCounterId AccumStats
-> Map TickyCounterId (TickyCounter, AccumStats, Double)
forall k a b c.
Ord k =>
(k -> a -> b -> Maybe c)
-> (Map k a -> Map k c)
-> (Map k b -> Map k c)
-> Map k a
-> Map k b
-> Map k c
Map.mergeWithKey (\TickyCounterId
_ TickyCounter
b AccumStats
c -> (TickyCounter, AccumStats, Double)
-> Maybe (TickyCounter, AccumStats, Double)
forall a. a -> Maybe a
Just (TickyCounter
b, AccumStats
c, Word64 -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac (AccumStats -> Word64
allocs AccumStats
c) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Word64 -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Word64
total_allocs)) (Map TickyCounterId (TickyCounter, AccumStats, Double)
-> Map TickyCounterId TickyCounter
-> Map TickyCounterId (TickyCounter, AccumStats, Double)
forall a b. a -> b -> a
const Map TickyCounterId (TickyCounter, AccumStats, Double)
forall a. Monoid a => a
mempty) (Map TickyCounterId (TickyCounter, AccumStats, Double)
-> Map TickyCounterId AccumStats
-> Map TickyCounterId (TickyCounter, AccumStats, Double)
forall a b. a -> b -> a
const Map TickyCounterId (TickyCounter, AccumStats, Double)
forall a. Monoid a => a
mempty) Map TickyCounterId TickyCounter
counters Map TickyCounterId AccumStats
accum_samples
    accum_samples :: Map TickyCounterId AccumStats
accum_samples = [TickySample] -> Map TickyCounterId AccumStats
accumulateSamples [TickySample]
samples


data AccumStats = AccumStats { AccumStats -> Word64
entries :: !Word64, AccumStats -> Word64
allocs :: !Word64, AccumStats -> Word64
allocd :: !Word64, AccumStats -> [(Double, Word64, Word64)]
series :: ![(Double, Word64 {- allocd -},   Word64 {- entries -})] } deriving Int -> AccumStats -> ShowS
[AccumStats] -> ShowS
AccumStats -> String
(Int -> AccumStats -> ShowS)
-> (AccumStats -> String)
-> ([AccumStats] -> ShowS)
-> Show AccumStats
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AccumStats -> ShowS
showsPrec :: Int -> AccumStats -> ShowS
$cshow :: AccumStats -> String
show :: AccumStats -> String
$cshowList :: [AccumStats] -> ShowS
showList :: [AccumStats] -> ShowS
Show

emptyAccumStats :: AccumStats
emptyAccumStats :: AccumStats
emptyAccumStats = Word64
-> Word64 -> Word64 -> [(Double, Word64, Word64)] -> AccumStats
AccumStats Word64
0 Word64
0 Word64
0 []

insertSample :: TickySample -> AccumStats -> AccumStats
insertSample :: TickySample -> AccumStats -> AccumStats
insertSample (TickySample Word64
_ids Word64
entries Word64
allocs Word64
allocd Double
time) (AccumStats Word64
aentries Word64
aalloc Word64
aallocd [(Double, Word64, Word64)]
aseries ) =
  (Word64
-> Word64 -> Word64 -> [(Double, Word64, Word64)] -> AccumStats
AccumStats (Word64
aentries Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
entries) (Word64
aalloc Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
allocs) (Word64
allocd Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
aallocd) ((Double
time, Word64
allocd Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
aallocd, Word64
aentries Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
entries ) (Double, Word64, Word64)
-> [(Double, Word64, Word64)] -> [(Double, Word64, Word64)]
forall a. a -> [a] -> [a]
: [(Double, Word64, Word64)]
aseries))

initStats :: TickySample -> AccumStats
initStats :: TickySample -> AccumStats
initStats = (TickySample -> AccumStats -> AccumStats)
-> AccumStats -> TickySample -> AccumStats
forall a b c. (a -> b -> c) -> b -> a -> c
flip TickySample -> AccumStats -> AccumStats
insertSample AccumStats
emptyAccumStats

accumulateSamples ::  [TickySample] -> Map.Map TickyCounterId AccumStats
accumulateSamples :: [TickySample] -> Map TickyCounterId AccumStats
accumulateSamples [TickySample]
samples =
  (Map TickyCounterId AccumStats
 -> TickySample -> Map TickyCounterId AccumStats)
-> Map TickyCounterId AccumStats
-> [TickySample]
-> Map TickyCounterId AccumStats
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Map TickyCounterId AccumStats
smap TickySample
ts -> (AccumStats -> AccumStats -> AccumStats)
-> TickyCounterId
-> AccumStats
-> Map TickyCounterId AccumStats
-> Map TickyCounterId AccumStats
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith (\AccumStats
_new AccumStats
old -> TickySample -> AccumStats -> AccumStats
insertSample TickySample
ts AccumStats
old) (Word64 -> TickyCounterId
TickyCounterId (Word64 -> TickyCounterId) -> Word64 -> TickyCounterId
forall a b. (a -> b) -> a -> b
$ TickySample -> Word64
tickyCtrSampleId TickySample
ts) (TickySample -> AccumStats
initStats TickySample
ts) Map TickyCounterId AccumStats
smap) Map TickyCounterId AccumStats
forall k a. Map k a
Map.empty
  ((TickySample -> TickySample -> Ordering)
-> [TickySample] -> [TickySample]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((TickySample -> Double) -> TickySample -> TickySample -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing TickySample -> Double
tickySampleTime) [TickySample]
samples)


tickyTab :: TickyProfileData -> Html
tickyTab :: TickyProfileData -> Html
tickyTab (TickyProfileData Word64
total Double
ticked_percen Html
v) = do
    Html -> Html
H.div (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
class_ AttributeValue
"row" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
      Html -> Html
H.div (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
class_ AttributeValue
"column" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
        Html
"Total Allocations: "
        Html -> Html
code (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html -> Html
forall a. ToMarkup a => a -> Html
toHtml (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Word64 -> Html
forall a. ToMarkup a => a -> Html
toHtml Word64
total
      Html -> Html
H.div (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
class_ AttributeValue
"column cheader" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
        Html
"Allocations Ticked (%): "
        Html -> Html
code (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html -> Html
forall a. ToMarkup a => a -> Html
toHtml (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ String -> Html
forall a. ToMarkup a => a -> Html
toHtml (Fixed E2 -> String
render  (Fixed E2 -> String) -> Fixed E2 -> String
forall a b. (a -> b) -> a -> b
$ Double -> Fixed E2
trunc (Double
ticked_percen Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100))
    Html -> Html
H.div (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
class_ AttributeValue
"row" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
          Html -> Html
H.div (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
A.id AttributeValue
"table" (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
class_ AttributeValue
"tabviz" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html
v

-- Table rendering
trunc :: Double -> Fixed E2
trunc :: Double -> Fixed E2
trunc = Double -> Fixed E2
forall a b. (Real a, Fractional b) => a -> b
realToFrac
render :: Fixed E2 -> String
render :: Fixed E2 -> String
render = Bool -> Fixed E2 -> String
forall {k} (a :: k). HasResolution a => Bool -> Fixed a -> String
showFixed Bool
True


renderTickyInfo :: Bool
                  -> Map.Map TickyCounterId (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
                  -> Html
renderTickyInfo :: Bool
-> Map
     TickyCounterId
     (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
-> Html
renderTickyInfo Bool
with_ipe Map
  TickyCounterId
  (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
ticky_samples = do
  Html -> Html
H.table (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
A.id AttributeValue
"closure_table" (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! AttributeValue -> Attribute
A.class_ AttributeValue
"table table-striped closureTable" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
    Html -> Html
H.thead (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html -> Html
H.tr (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html
headFoot
--      H.th "Profile"
--      numTh "n"
    ((InfoTableLocStatus, (TickyCounter, AccumStats, Double))
 -> Html -> Html)
-> Html
-> Map
     TickyCounterId
     (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
-> Html
forall a b k. (a -> b -> b) -> b -> Map k a -> b
Map.foldr (\(InfoTableLocStatus, (TickyCounter, AccumStats, Double))
a Html
res -> (InfoTableLocStatus, (TickyCounter, AccumStats, Double)) -> Html
renderEntry (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
a Html -> Html -> Html
forall a b. MarkupM a -> MarkupM b -> MarkupM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Html
res) (Html
forall a. Monoid a => a
mempty :: Html) Map
  TickyCounterId
  (InfoTableLocStatus, (TickyCounter, AccumStats, Double))
ticky_samples
    Html -> Html
H.tfoot (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html -> Html
H.tr (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html
headFoot
  Html -> Html
H.script (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Text -> Html
forall a. ToMarkup a => a -> Html
preEscapedToHtml (Bool -> Text
initTable Bool
with_ipe)
  where
    headFoot :: Html
headFoot = do
      Html -> Html
H.th Html
"Label"
      Html -> Html
H.th Html
"FVs"
      Html -> Html
H.th Html
"Args"
      Bool -> Html -> Html
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
with_ipe) (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
        Html -> Html
H.th Html
"Description"
        Html -> Html
H.th Html
"CTy"
        Html -> Html
H.th Html
"Type"
        Html -> Html
H.th Html
"Module"
        Html -> Html
H.th Html
"Loc"
      Html -> Html
numTh Html
"Allocs"
      Html -> Html
numTh Html
"Allocs (%)"
      Html -> Html
numTh Html
"Allocd"
      Html -> Html
numTh Html
"Allocd #"
      Html -> Html
numTh Html
"Entries"
      Html -> Html
numTh Html
"Allocs/Entries"
      Html -> Html
numTh Html
"Allocd #/Entries"
--      numTh "Chart"
    numTh :: Html -> Html
numTh Html
lbl = Html -> Html
H.th (Html -> Html) -> Attribute -> Html -> Html
forall h. Attributable h => h -> Attribute -> h
! Tag -> AttributeValue -> Attribute
H.dataAttribute Tag
"sortas" AttributeValue
"numeric" (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ Html
lbl

    renderInfoTableLoc :: InfoTableLoc -> Html
    renderInfoTableLoc :: InfoTableLoc -> Html
renderInfoTableLoc (InfoTableLoc Text
table_name ClosureType
cd Text
tydesc Text
_lbl Text
m Text
sloc) = do
      Html -> Html
H.td (Text -> Html
forall a. ToMarkup a => a -> Html
toHtml Text
table_name)
      Html -> Html
H.td (String -> Html
forall a. ToMarkup a => a -> Html
toHtml (forall a. Show a => a -> String
show @ClosureType ClosureType
cd))
      Html -> Html
H.td (Text -> Html
forall a. ToMarkup a => a -> Html
preEscapedToHtml Text
tydesc) -- Don't escape this as the ellipsis plugin does it.
      Html -> Html
H.td (Text -> Html
forall a. ToMarkup a => a -> Html
toHtml Text
m)
      Html -> Html
H.td (Text -> Html
forall a. ToMarkup a => a -> Html
toHtml Text
sloc)


    renderInfoTableLocStatus :: InfoTableLocStatus -> Html
    renderInfoTableLocStatus :: InfoTableLocStatus -> Html
renderInfoTableLocStatus InfoTableLocStatus
_ | Bool -> Bool
not Bool
with_ipe = Html
forall a. Monoid a => a
mempty
    renderInfoTableLocStatus InfoTableLocStatus
itls =
      case InfoTableLocStatus
itls of
        Here InfoTableLoc
itl -> InfoTableLoc -> Html
renderInfoTableLoc InfoTableLoc
itl
        InfoTableLocStatus
Missing  -> Html
emptyItlColumns
        InfoTableLocStatus
None -> Html
forall a. Monoid a => a
mempty

    emptyItlColumns :: Html
emptyItlColumns = do
      Html -> Html
H.td Html
""
      Html -> Html
H.td Html
""
      Html -> Html
H.td Html
""
      Html -> Html
H.td Html
""
      Html -> Html
H.td Html
""


    renderEntry :: (InfoTableLocStatus, (TickyCounter, AccumStats, Double)) -> Html
    renderEntry :: (InfoTableLocStatus, (TickyCounter, AccumStats, Double)) -> Html
renderEntry (InfoTableLocStatus
loc, ((TickyCounter Word64
_id Word16
_arity TickyCounterArgs
kinds Text
label InfoTablePtr
_), AccumStats {[(Double, Word64, Word64)]
Word64
allocs :: AccumStats -> Word64
entries :: AccumStats -> Word64
allocd :: AccumStats -> Word64
series :: AccumStats -> [(Double, Word64, Word64)]
entries :: Word64
allocs :: Word64
allocd :: Word64
series :: [(Double, Word64, Word64)]
..}, Double
percent)) = do
      let fvs :: String
fvs = TickyCounterArgs -> String
tickyCounterFVs TickyCounterArgs
kinds
          ticky_args :: String
ticky_args = TickyCounterArgs -> String
tickyCounterArgs TickyCounterArgs
kinds
          size :: Int
size = Int -> Int -> Int
closureSize (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
fvs) (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
ticky_args)
          alloc_no :: Int
alloc_no = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
allocd Int -> Int -> Int
forall a. Integral a => a -> a -> a
`Prelude.div` Int
size
      Html -> Html
H.tr (Html -> Html) -> Html -> Html
forall a b. (a -> b) -> a -> b
$ do
--            H.td (renderSpark (getBandValues n (ts, bs)))
            Html -> Html
H.td (Text -> Html
forall a. ToMarkup a => a -> Html
toHtml Text
label)
            Html -> Html
H.td (String -> Html
forall a. ToMarkup a => a -> Html
toHtml String
fvs)
            Html -> Html
H.td (String -> Html
forall a. ToMarkup a => a -> Html
toHtml String
ticky_args)
            InfoTableLocStatus -> Html
renderInfoTableLocStatus InfoTableLocStatus
loc
            Html -> Html
H.td (Word64 -> Html
forall a. ToMarkup a => a -> Html
toHtml Word64
allocs)
            Html -> Html
H.td (String -> Html
forall a. ToMarkup a => a -> Html
toHtml (String -> Html) -> String -> Html
forall a b. (a -> b) -> a -> b
$ Fixed E2 -> String
render (Fixed E2 -> String) -> Fixed E2 -> String
forall a b. (a -> b) -> a -> b
$ Double -> Fixed E2
trunc (Double
percent Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
100))
            Html -> Html
H.td (Word64 -> Html
forall a. ToMarkup a => a -> Html
toHtml Word64
allocd)
            Html -> Html
H.td (Int -> Html
forall a. ToMarkup a => a -> Html
toHtml Int
alloc_no)
            Html -> Html
H.td (Word64 -> Html
forall a. ToMarkup a => a -> Html
toHtml Word64
entries)
            Html -> Html
H.td (Word64 -> Html
forall a. ToMarkup a => a -> Html
toHtml (case Word64
entries of
                            Word64
0 -> Word64
0
                            Word64
_ -> Word64
allocs Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`Prelude.div` Word64
entries))
            Html -> Html
H.td (case Word64
entries of
                            Word64
0 -> Html
"NaN"
                            Word64
_ ->
                              case Word64
allocd of
                                Word64
0 -> Html
"None"
                                Word64
_ -> String -> Html
forall a. ToMarkup a => a -> Html
toHtml (Fixed E2 -> String
render (Double -> Fixed E2
trunc (Word64 -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Word64
entries Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac Int
alloc_no))))
--            H.td (toHtml (renderSpark size series))
--            H.td mempty

closureSize :: Int -> Int -> Int
closureSize :: Int -> Int -> Int
closureSize Int
fvs Int
cl_args
  -- THUNK, HEADER = 2
  | Int
cl_args Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
fvs) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8
  | Bool
otherwise  = (Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
fvs) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8


initTable :: Bool -> T.Text
initTable :: Bool -> Text
initTable Bool
ipe =

  Text
"var ipe = " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (if Bool
ipe then Text
"true" else Text
"false") Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
";\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
  Text
[r|// Setup - add a text input to each footer cell
    $(document).ready(function(){
    $('.closureTable tfoot th').each( function () {
        var title = $(this).text();
//       if (! ($(this).data("sortas") == "numeric")){
          $(this).html( '<input type="text" style="width:100%"; placeholder="Search"/>' );
//        }
//        else {
//          $(this).html('')
//        }
    } );

    function init_spark(){

      $('.linechart').sparkline('html', { enableTagOptions: true, tagOptionPrefix: 'allocd-',  tagValuesAttribute: 'data-allocd' });
      $('.linechart').sparkline('html', { composite: true, lineColor: 'red', enableTagOptions: true, tagOptionPrefix: 'entries-', tagValuesAttribute: 'data-entries' });
      $.sparkline_display_visible();
    }

    // DataTable
    var table = $('.closureTable').DataTable({
        "order": [[ ipe ? 8 : 3, "desc" ]],
        "autoWidth": true,
        "dom": 'Bfrtip',
        "buttons": [
            {
                text: 'TSV',
                extend: 'csvHtml5',
                fieldSeparator: '\t',
                extension: '.tsv'
            }
        ],
        "columnDefs": [
          { "orderSequence": ["desc", "asc"],  "targets": (ipe ? [8,9,10,11,12,13,14] : [ 3,4,5,6,7,8,9])}
          , {"render": $.fn.dataTable.render.ellipsis( 30, true, false ), "targets": (ipe ? [5] : []) }
          ],

        "deferRender" : true,
        initComplete: function () {
            // Apply the search
            $(".closureTable").removeAttr("hidden");
            this.api().columns().every( function () {
                var that = this;
                $( 'input', this.footer() ).on( 'blur', function () {
                    if ( that.search() !== this.value ) {
                        that
                            .search( this.value )
                            .draw();
                    }
                } );
        $.fn.sparkline.defaults.common.chartRangeMin = 0;
        $.fn.sparkline.defaults.common.width = 200;
        init_spark();
            } );
        }
    });
    table.on( 'draw', function () {
        init_spark();
    } );
    })
    |]


{-
getBandValues :: Int
            -> (UArray Int Double, UArray (Int, Int) Double)
            -> [(Double, Double)]
getBandValues k (ts, vs) =
  let (t1, tn) = bounds ts
      go i = flip map [t1 .. tn] $ \t -> ((ts A.! t), (vs A.! (i, t)))

  in go k
  -}