#!/usr/bin/python """usage: gnome-points num-comments num-closed-bugs num-opened-bugs Compute GNOME Bugzilla points and linear estimate of required activity to go to the next point level.""" import sys, math if len(sys.argv) != 4: print >>sys.stderr, __doc__ sys.exit (1) # We work with plus-oned stats, as that make all formulas much simpler stats = [] for i in range (1, 4): stats.append (1+int(sys.argv[i])) activity_ratios = [x * 1. / stats[0] for x in stats] bases = [10, 2, 2] def bugzilla_points (comments, closed, opened): """Returns the GNOME Bugzilla points gathered, as a floating point.""" return sum ([math.log (x,y) for (x,y) in zip ([comments, closed, opened], bases)]) def points_derivative (comments, closed, opened): """Returns a tuple of partial derivatives of the bugzilla points to each component. The returned values are what you will gain if you contribute one more item of each kind.""" return [1./(x*math.log(y)) for (x,y) in zip ([comments, closed, opened], bases)] def comments_adjusted (comments, closed, opened): """Adjusts the number of comments by subtracting from it the number of closed and opened bugs, as they contribute a comment too.""" return [max(0, comments - closed - opened), closed, opened] points = bugzilla_points (*stats) print "Current points: %f" % points # points required for the next level target_points = math.ceil (points + .5) - .5 # linear interpolate target_comments = 2**(math.log(10,200)*(target_points-sum([math.log(x,2) for x in activity_ratios]))) target_stats = [int(math.ceil (target_comments * ratio)) for ratio in activity_ratios] diff_stats = [(x-y) for (x,y) in zip (target_stats, stats)] print "Need %s more to go to the next level (%f)" % (comments_adjusted (*diff_stats), bugzilla_points (*target_stats)) # TODO: the linear interpolate is almost as good as you can get. however, it # does overhit the target points because of the ceiling operations. it works # good enough when you have quite a bunch of each kind of stats, but not when # you have values (say) below 10. it should be changed to ceil one target at # a time, and readjusting the rest, and this should be done from the stat with # the highest derivated down to the lowest... sys.exit() # the following doesn't make any sense at this time, ignore # min-effort estimate point_derivs = points_derivative (*stats) point_to_effort_derivs = [(x*y) for (x,y) in zip(point_derivs, activity_ratios)] activity_ratios = [x / point_to_effort_derivs[0] for x in point_to_effort_derivs] target_comments = 2**(math.log(10,200)*(target_points-sum([math.log(x,2) for x in activity_ratios]))) target_stats = [int(math.ceil (target_comments * ratio)) for ratio in activity_ratios] diff_stats = [(x-y) for (x,y) in zip (target_stats, stats)] print "Min-effort estimate (incorrect):", comments_adjusted (*diff_stats)