# std groupviews colors

colors = { 'lightblue'   : "#A6CEE3", 'darkblue'   : "#1F77B4",
           'lightgreen'  : "#B2DF8A", 'darkgreen'  : "#33A02C",
           'lightred'    : "#FB9A99", 'darkred'    : "#E31A1C",
           'lightorange' : "#FDBF6F", 'darkorange' : "#FF7F00",
           'stdgray'     : "#d8d8d8", 'purple'     : "#790EAD",
           'black'       : "#000000"  }

colormap = { 0 : 'darkorange',
             1 : 'lightorange',
             2 : 'darkred',
             3 : 'lightred',
             4 : 'darkgreen',
             5 : 'lightgreen',
             6 : 'darkblue',
             7 : 'lightblue'
             }

# for reference : ranges of the RRAs
# base step size 60 sec
# step  1 :  60 sec x 1600 points : 1600 min : 26,67 hr : 1.11 days
# step  2 : 120 sec x 1200 points : 2400 min : 40    hr : 1,67 days
# step 10 : 600 sec x 1800 points : 18 000 min : 300 hr : 12,5 days
# step 30 : 1800 sec x 2500 points : 75 000 min : 1250 hr : 52.08 days
# step 120 : 7200 sec x 1000 points : 120 000 min : 2000 hr : 83.33 days
# step 480 : 28800 sec x 1000 points : 480 000 min : 8000 hr : 333.33 days
# step 1440 : 86400 sec x 3650 points : 3650 days : 10 years

# resolutions of RRAs

# 1 :     60 sec :    1 min
# 2 :    120 sec :    2 min
# 3 :    600 sec :   10 min
# 4 :  1 800 sec :   30 min
# 5 :  7 200 sec :  120 min :  2 hr
# 6 : 28 800 sec :  480 min :  8 hr
# 7 : 86 400 sec : 1440 min : 24 hr : 1 day

NUMQS = 27                      # number of quarters for "alltime" plot

pdefs = {
    'hour' : {
        'range' : 24*3600,
        'res'   : 60,
        'timeargs' : [ '-s', 'n-200min',  '-e', 'n' ],
        'small' : {
            'width'  : 200,
            'height' : 125,
            'opts' : ['--x-grid', 'MINUTE:20:HOUR:1:HOUR:1:0:%H:00' ]
        },
        'large' : {
            'width'  : 800,
            'height' : 500,
            'opts' : [ ],
        },
    },
    'day' : {
        'range' : 24*3600,
        'res'   : 60,
        'timeargs' : [ '-s', 'n-2000min',  '-e', 'n' ],
        'small' : {
            'width'  : 200,
            'height' : 125,
            'opts' : ['--x-grid', 'HOUR:6:DAY:1:HOUR:12:0:%a %H:00' ]
        },
        'large' : {
            'width'  : 1000,
            'height' : 625,
            'opts' : [ ],
        },
    },
        
    'week' : {
        'range' : 7*24*3600,
        'res'   : 600,
        'timeargs' : [ '-s', 'n-288hr',  '-e', 'n' ],
        'small' : {
            'width'  : 576,
            'height' : 125,
            'opts' : [ ]
        },
        'large' : {
            'width'  : 1728,
            'height' : 375,
            'opts' : ['-n', 'DEFAULT:16' ],
        },
    },
        
    'month' : {
##     # note the construction "repr(576*n)" here --- this is because the plot is
##     # (a multiple of) 576 pixels, and 120 min is one of the RRAs, so choosing
##     # a lower limit of 576*120 gives us a plot with one pixel per RRA bin.
        'range' : 31*24*3600,
        'res'   : 1800,
        'timeargs' : [ '-s', 'n-'+repr(576*120)+'min',  '-e', 'n'],
        'small' : {
            'width'  : 576,
            'height' : 105,
            'opts' : [ ]
        },
        'large' : {
            'width'  : 2304,
            'height' : 420,
            'opts' : [ '-n', 'DEFAULT:18:', '--x-grid',
                       'HOUR:12:DAY:1:DAY:3:86400:%d-%b' ]
        },
    },
    'year' : {
        'range' : 365*24*3600,
        'res'   : 86400,
        'timeargs' : [ '-s', 'n-'+repr(576*1440)+'min',  '-e', 'n'],
        'small' : {
            'width'  : 576,
            'height' : 105,
            'opts' : [ ]
        },
        'large' : {
            'width'  : 2304,
            'height' : 420,
            'opts' : [ ],
        },
    },
        
## # adjusting for nice plot ... now 12/4 of a year
    
    'alltime' : {
        'range' : NUMQS*365*24*3600/4,
        'res'   : 86400,
        'timeargs' : [ '-s', 'n-'+repr(NUMQS*365*1440/4)+'min',  '-e', 'n'],
        'small' : {
            'width'  : 576,
            'height' : 105,
            'opts'   : ['--x-grid', 'MONTH:3:YEAR:1:YEAR:1:31536000:%Y' ]
        },
        'large' : {
            'width'  : 2304,
            'height' : 420,
            'opts' : [ '--x-grid', 'MONTH:1:YEAR:1:MONTH:3:2592000:%b-%Y']
        }
    }
}

import rrdtool
import time

### function definitions

def getfracs(groupsdict, totaldb, range, resolu):

    now=int(time.mktime(time.localtime()))
    end = (now / resolu) * resolu
    start  = end - range + resolu  # adding resolu avoids worry about off by one?
    # first do total capacity (need for dividing into each component result)

    tup = rrdtool.fetch(totaldb[1],'AVERAGE','-r', repr(resolu),
                        '-s', repr(start), '-e', repr(end))
    vallist = [0] # start with zero, in case no vals returned, get zero as answer
    for tup2 in tup[2]:
        val = tup2[0]
        if val:
            vallist.append(val)

    # put numbers in meaningful units now.  after summing vallist,
    # result is an
    # sum over the time range, of data averages over "resolu"
    # ... native resolution is in minutes, so multiplying by
    # (resolu / 60) puts the answer in core-minutes; dividing by
    # the number of minutes in the range gives the average number
    # of cores occupied, over the range

    totval = sum(vallist) * (resolu / 60) / ( (end-start) / 60. )

    ### now find same for each component

    tgroup = dict() # structure tgroup[groupname] = averages over interval

    for group in groupsdict:
        tup = rrdtool.fetch(groupsdict[group][1],'AVERAGE','-r', repr(resolu),
                            '-s', repr(start), '-e', repr(end))
        vallist = [0] # start with zero, in case no vals returned, get zero as answer
        for tup2 in tup[2]:
            val = tup2[0]
            if val:
                vallist.append(val)

        tgroup[group] = sum(vallist) * (resolu / 60) / ( (end-start) / 60. )

    pgroup = dict()              # percentages over interval
    if totval == 0.0 : return
    for g in tgroup.keys():
        pgroup[g] = 100*tgroup[g]/totval
    
    return (tgroup, pgroup)

def getqueued(groupsdict, range, resolu):

    now=int(time.mktime(time.localtime()))
    end = (now / resolu) * resolu
    start  = end - range + resolu  # adding resolu avoids worry about off by one?

    tgroup = dict() # structure tgroup[groupname] = averages over interval

    for group in groupsdict:
        tup = rrdtool.fetch(groupsdict[group][1],'AVERAGE','-r', repr(resolu),
                            '-s', repr(start), '-e', repr(end))
        vallist = [0] # start with zero, in case no vals returned, get zero as answer
        for tup2 in tup[2]:
            val = tup2[0]
            if val:
                vallist.append(val)

    # put numbers in meaningful units now.  after summing vallist,
    # result is an
    # sum over the time range, of data averages over "resolu"
    # ... native resolution is in minutes, so multiplying by
    # (resolu / 60) puts the answer in core-minutes; dividing by
    # the number of minutes in the range gives the average number
    # of cores occupied, over the range

        tgroup[group] = sum(vallist) * (resolu / 60) / ( (end-start) / 60. )

    return tgroup

class Plot:
    def __init__(self):
        self.bands = list()
        self.lines = None  # optional
        self.labels = None # optional
        self.colors = list()
        self.datafile = dict()
        self.size = None
        self.opts = None
        self.range = None
    def generate(self, file=None):
        data_defs = list()
        for group in self.bands + self.lines:
            data_defs.append('DEF:%s=%s:%s:AVERAGE' % (group, self.datafile[group][1], self.datafile[group][0]))

        plot_defs = list()
        if not self.labels:
            self.labels = dict()
            for g in self.bands + self.lines:
                self.labels[g] = g
        for g in self.bands:
            plot_defs.append('AREA:%s%s:%s\\n:STACK' % (g, self.colors[g], self.labels[g]))
        for g in self.lines:
            plot_defs.append('LINE:%s%s:%s\\n' % (g, self.colors[g], self.labels[g]))

        dbtype = 'run'
        timetag = 'tst'
        ranktype = 'tstrank'
        psize = 'tstp'
        pargs = [ self.plotfile ] + \
          ['--imgformat', 'PNG', '--legend-position=east', \
           '--legend-direction=bottomup', '-l', '0'] + \
           ['--width', str(self.width), '--height', str(self.height) ] + \
           self.opts + self.timeargs + [data_defs + plot_defs]
           
           
        rrdtool.graph( *pargs )
