Example #1
0
def generate_aggregate(blocs=[], motion_ids=[], filters={}):
    keys = set(blocs)

    spec = dict(filters)
    if len(motion_ids):
      spec['motion.motion_id'] = {'$in': motion_ids}
      keys.add('motion.motion_id')

    options = get_options()

    data = {}
    # Aggregate on the server.
    for cell in votes.group(keys, spec, {"votes": {}, 'num_votes': 0}, REDUCE):

        key = repr([cell.get(k) for k in set(keys)])
        if not key in data:
            data[key] = {
                'counts': defaultdict(int),
                'bloc': {},
                'stats': {
                    'num_motions': 0,
                    'num_votes': 0
                }
            }

        for option in options:
            v = cell.get('votes').get(option, 0)
            data[key]['counts'][option] += v
        
        for k, v in cell.items():
            if k in blocs:
                data[key]['bloc'][k] = v

        data[key]['motion_id'] = cell.get('motion.motion_id')
        data[key]['stats']['num_motions'] += 1
        data[key]['stats']['num_votes'] += cell['num_votes']

    return data.values()
Example #2
0
def generate_stances(blocs=[], issue_ids=[], filters={}):
    keys = set(blocs)
    _filt = {}
    if len(issue_ids):
        _filt = {'_id': {'$in': [ObjectId(i) for i in issue_ids]}}
    issue_objs = list(issues.find(_filt))

    motion_issues = defaultdict(list)
    for issue in issue_objs:
        for motion in issue.get('motions', []):
            motion_issues[motion['motion_id']].append((issue, motion))

    spec = dict(filters)
    spec['motion.motion_id'] = {'$in': motion_issues.keys()}
    keys.add('motion.motion_id')

    options = get_options()

    data = {}
    # Aggregate on the server.
    for cell in votes.group(keys, spec, {"votes": {}, 'num_votes': 0}, REDUCE):

        # Aggregate by issue locally.
        for issue, mdata in motion_issues.get(cell.get('motion.motion_id')):

            # Output cell key.
            key = repr([issue.get('_id')] + [cell.get(k) for k in set(blocs)])
            if not key in data:
                data[key] = {
                    'issue': issue,
                    'counts': defaultdict(int),
                    'weighted': defaultdict(int),
                    'bloc': {},
                    'stats': {
                        'num_motions': 0,
                        'num_votes': 0,
                        'max_score': 0,
                        'min_score': 0
                    }
                }

            for option in options:
                v = cell.get('votes').get(option, 0)
                data[key]['counts'][option] += v
                data[key]['weighted'][option] += v * get_weight(mdata, option)
            
            for k, v in cell.items():
                if k in blocs:
                    data[key]['bloc'][k] = v

            data[key]['stats']['num_motions'] += 1
            data[key]['stats']['num_votes'] += cell['num_votes']

            weights = map(lambda x: get_weight(mdata, x), options)
            data[key]['stats']['max_score'] += cell['num_votes'] * max(weights)
            data[key]['stats']['min_score'] += cell['num_votes'] * min(weights)

    blocs = []
    for bloc in data.values():
        # determine the full range of available values:
        value_range = bloc['stats']['max_score'] - bloc['stats']['min_score']

        # sum up 'yes' and 'no' values:
        bloc_value = sum(bloc['weighted'].values())

        # make the bloc value fall in between 0 and value_range
        normalized_value = bloc_value + (bloc['stats']['min_score'] * -1)

        # calculate a score based on the normalized value and the value range
        bloc['match'] = normalized_value / max(1, value_range)
        blocs.append(bloc)
    return blocs