metrics.py 4.33 KB
Newer Older
1
""" Controllers for building metrics tables
2 3

"""
4
import json
5 6
import re

7
from plugin_dbui import inline_alert, Selector
8
from pydal.helpers.methods import smart_query
9
from reporting_tools import get_converter, repr_team_project
10

11
MSG_NO_METRIC = "Please select a metric...."
12

13 14 15 16 17

def index():
    """Main Controller handling metrics.

    """
18 19
    publications = db.publications

20 21 22
    # get the user constraint.
    # the selector fields year_start, year_end, id_lists are excluded
    # from the selector query.
23 24
    tpl = ('author', 'year_start', 'year_end', 'id_metrics')
    selector = Selector(virtdb.metric_selector, exclude_fields=tpl)
25

26
    # protection
27
    if not selector.id_metrics:
28
        return inline_alert(T("Error"), T(MSG_NO_METRIC))
29

30 31 32
    # retrieve metric data
    metric = db.metrics[selector.id_metrics]

33
    # database fields corresponding to the axes
34 35
    fields, orderby = {}, {}
    for el in ('vertical', 'horizontal'):
36

37 38 39
        axis = metric["axis_%s" % el]
        granularity = metric["granularity_%s" % el]
        direction = metric["direction_%s" % el]
40

41
        field = db[axis][granularity]
42 43 44

        fields[el] = field
        orderby[el] = ~field if direction == 'DESC' else field
45

46 47
    # query directive to count publications including
    # foreign key constraints and user requirements
48
    # related to team, project and year
49
    query = selector.query(publications)
50

51
    if metric.conditions:
52 53
        q_conditions = smart_query(publications, metric.conditions)
        query &= q_conditions
54

55
    if selector.year_start and not selector.year_end:
56
        query &= (publications.year == selector.year_start)
57

58
    elif selector.year_start and selector.year_end:
59 60 61 62 63 64 65
        q_start = publications.year >= selector.year_start
        q_end =  publications.year <= selector.year_end
        query &= ((q_start) & (q_end))

    if selector.author:
        q_author = publications.authors_institute.contains(selector.author)
        query &= q_author
66

67
    # get the label along the x and y axis
68 69 70 71 72
    labels = {}
    for el in ('vertical', 'horizontal'):
        labels[el] = []
        for row in db(query).select(fields[el], distinct=True, orderby=orderby[el]):
            labels[el].append(row[fields[el]])
73 74 75 76 77 78 79

    # protection empty data
    if len(labels['horizontal']) == 0 and len(labels['vertical']) == 0:
        return dict(cfg_store=json.dumps({}),
                    team_project=repr_team_project(db, selector),
                    selector=selector)

80 81
    # the fields configuration of the Ext.data.ArrayStore
    cfg = dict(fields=[], data=[])
82

83 84
    # first column contains labels for the vertical axis
    cfg['fields'].append({'name': fields['vertical'].name, 'type': 'string'})
85

86 87
    # one column for each horizontal label
    for el in labels['horizontal']:
88 89
        cfg['fields'].append({'name': str(el), 'type': 'int'})

90
    # last column contains the sum of the row
91
    cfg['fields'].append({'name': T('Total'), 'type': 'int'})
92

93 94
    # fill the data block of the Ext.data.Array.Store
    # transform (x, y count) data point into a row of values
95
    # sum the content of the row
96
    count = publications.id.count()
97 98 99
    rows =  db(query).select(fields['vertical'],
                             fields['horizontal'],
                             count,
100 101
                             groupby=(fields['vertical'], fields['horizontal']),
                             orderby=(orderby['vertical'], orderby['horizontal']))
102

103
    key = None
104
    for row in rows:
105

106 107
        if row[fields['vertical']] != key:
            key = row[fields['vertical']]
108
            cfg['data'].append([key])
109
            cfg['data'][-1].extend(['']*(len(labels['horizontal']) + 1))
110
            cfg['data'][-1][-1] = 0
111

112
        i = labels['horizontal'].index(row[fields['horizontal']]) + 1
113 114
        cfg['data'][-1][i] = row[count]
        cfg['data'][-1][-1] += row[count]
115

116
    # Substitute axis label
117
    cvt_labels = get_converter(metric)
118

119
    # label for the horizontal axis
120 121 122
    for i in range(len(cfg['data'][0])):
        if cfg['data'][0][i] in cvt_labels:
            cfg['data'][0][i] = cvt_labels[cfg['data'][0][i]]
123

124
    # label for the vertical axis
125 126 127
    for i in range(len(cfg['data'])):
        if cfg['data'][i][0] in cvt_labels:
            cfg['data'][i][0] = cvt_labels[cfg['data'][i][0]]
128 129

    return dict(cfg_store=json.dumps(cfg),
130 131
                team_project=repr_team_project(db, selector),
                selector=selector)