Skip to content

Commit

Permalink
Fixes and addons for evaluation modules
Browse files Browse the repository at this point in the history
  • Loading branch information
lexqt committed May 13, 2012
1 parent 5a2a08a commit 2bc5f9c
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 47 deletions.
1 change: 1 addition & 0 deletions trac/evaluation/api/__init__.py
Expand Up @@ -2,6 +2,7 @@
from trac.evaluation.api.scale import *
from trac.evaluation.api.area import *
from trac.evaluation.api.model import *
from trac.evaluation.api.util import *
from trac.evaluation.api import varlib
from trac.evaluation.api.components import *
from trac.user.api import UserRole
3 changes: 3 additions & 0 deletions trac/evaluation/api/error.py
Expand Up @@ -13,3 +13,6 @@ class DataNotReadyError(EvalSourceError):
'''Exception for the cases when some data is not yet
ready for processing (e.g. not collected yet)'''

class MissedQueryArgumentsError(EvalSourceError):
'''Exception for the cases when some mandatory
arguments to perform source query are not set'''
34 changes: 24 additions & 10 deletions trac/evaluation/api/model.py
Expand Up @@ -184,6 +184,7 @@ def get_enum_value(self, type_, value):



DEBUG = False

class ModelVariable(object):

Expand Down Expand Up @@ -232,6 +233,8 @@ def get(self):
except EvalModelError:
raise
except Exception, e:
if DEBUG:
raise
msg = exception_to_unicode(e)
raise EvalModelError(_('Error occurred while getting variable value: %(msg)s', msg=msg))
return value
Expand Down Expand Up @@ -427,11 +430,16 @@ def __init__(self, model):
# Base implementation for query area setup methods
# may be overriden

def project(self, pid):
def reset(self):
self._state = {
'area': None,
}
return self

def project(self, project_id):
s = self._state
# if s['area'] != SubjectArea.USER:
s['area'] = SubjectArea.PROJECT
s['project_id'] = pid
s['project_id'] = project_id
return self

def user(self, username):
Expand All @@ -441,28 +449,34 @@ def user(self, username):
})
return self

def group(self, gid):
def group(self, group_id):
self._state.update({
'area': SubjectArea.GROUP,
'group_id': gid
'group_id': group_id
})
return self

def syllabus(self, sid):
def syllabus(self, syllabus_id):
self._state.update({
'area': SubjectArea.SYLLABUS,
'syllabus_id': sid
'syllabus_id': syllabus_id
})
return self

def milestone(self, milestone):
self._state['milestone'] = milestone
def milestone(self, milestone_name):
self._state['milestone'] = milestone_name
return self

# Util methods

def check_state(self, *args):
'''Check if all specified args defined in the state'''
'''Check if all specified args defined (not None) in the state'''
s = self._state
return all(map(lambda x: x is not None, [s.get(k) for k in args]))

def check_state_and_raise(self, *args):
'''Call `check_state` and raise exception on false'''
check = self.check_state(*args)
if not check:
raise MissedQueryArgumentsError(_('Some mandatory arguments for model source query are missed.'))

7 changes: 6 additions & 1 deletion trac/evaluation/api/scale.py
@@ -1,4 +1,4 @@

from trac.util.translation import _

__all__ = ['Scale', 'NominalScale', 'BooleanScale',
'OrdinalScale', 'IntervalScale', 'RatioScale',
Expand Down Expand Up @@ -110,14 +110,19 @@ def prepare_rendered_value(scale, value):
def is_scale(cls):
return isinstance(scale, cls)

# transform scale
if is_scale(UnityScale):
# convert to percents
scale = PercentScale(integer=False)
value = scale.get(value * 100)

# convert to string
if is_scale(PercentScale):
if scale.type is float:
value = ('%.2f'%value).rstrip('0').rstrip('.')
return u'{0}%'.format(value)
elif is_scale(BooleanScale):
value = _('Yes') if value else _('No')
return value

return unicode(value)
43 changes: 43 additions & 0 deletions trac/evaluation/api/util.py
@@ -0,0 +1,43 @@
from trac.util.translation import _
from trac.evaluation.api.error import EvalModelError

def get_enum_equivalents(model, type_, values):
'''Transform `values` list of `type_` enum items
to the list of enum numeric equivalents using
specified evaluation `model`.
'''
return map(lambda v: model.get_enum_value(type_, v), values)

def revert_enum(model, type_, value):
'''Revert numeric equivalent of `type_` enum item
back to original enum value.
If there is no exact match, round `value` to the closest
having equivalent.'''
m = model.ENUM_MAP
if type_ not in m:
raise EvalModelError(_('There is no mapping for %(type_)s values',
type_=type_))
m = m[type_]
mr = {v: k for (k, v) in m.iteritems() if k != '*'}
if value in mr:
return mr[value]
vals = sorted(mr.keys())
if not vals:
raise EvalModelError(_('No equivalent for enum value found'))
p = vals[0]
n = vals[-1]
for v in vals:
if v < value:
p = v
else:
break # first not less
for v in reversed(vals):
if v > value:
n = v
else:
break # first not greater
if abs(value-p) < abs(value-n):
return mr[p]
else:
return mr[n]

6 changes: 4 additions & 2 deletions trac/evaluation/api/varlib.py
Expand Up @@ -2,6 +2,8 @@
SubjectArea, ClusterArea, \
RatioScale
from trac.evaluation.sources import tktsrc
from trac.user.api import UserRole



class CountTickets(ModelVariable):
Expand Down Expand Up @@ -117,7 +119,7 @@ def process_results(self, results, msum, team_size):
`results`: <user_data> for user area
{ 'user1': <user_data>, ... } for project area
`msum`: sum that should be distributed among team members
`team_size`: project team size
`team_size`: project team size (developers count)
For contents of <user_data> - see `with_authors`.
'''
raise NotImplementedError
Expand All @@ -132,7 +134,7 @@ def _get(self):
all_completed=self.all_completed,
only_approved=self.only_approved)
msum = minfo.get_team_eval_sum(syllabus_id=self.model.syllabus_id)
team_size = uinfo.project(s['project_id']).team_size()
team_size = uinfo.project(s['project_id']).role(UserRole.DEVELOPER).count()
value = self.process_results(vals, msum, team_size)
return value

Expand Down
1 change: 1 addition & 0 deletions trac/evaluation/project.py
Expand Up @@ -110,6 +110,7 @@ def do_project_eval(self, req):
'alias': name,
'label': crit['label'],
'description': crit['description'],
'scale': crit['scale'],
'value': datavalues[name],
'order': crit['order'],
}
Expand Down

0 comments on commit 2bc5f9c

Please sign in to comment.