Commit 522cdd21 by Miles Steele

refactor distributions (minor)

parent 0d6a12fd
...@@ -5,7 +5,9 @@ Profile Distributions ...@@ -5,7 +5,9 @@ Profile Distributions
from django.db.models import Count from django.db.models import Count
from student.models import CourseEnrollment, UserProfile from student.models import CourseEnrollment, UserProfile
AVAILABLE_PROFILE_FEATURES = ['gender', 'level_of_education', 'year_of_birth'] _EASY_CHOICE_FEATURES = ('gender', 'level_of_education')
_OPEN_CHOICE_FEATURES = ('year_of_birth',)
AVAILABLE_PROFILE_FEATURES = _EASY_CHOICE_FEATURES + _OPEN_CHOICE_FEATURES
def profile_distribution(course_id, feature): def profile_distribution(course_id, feature):
...@@ -26,24 +28,16 @@ def profile_distribution(course_id, feature): ...@@ -26,24 +28,16 @@ def profile_distribution(course_id, feature):
OPEN_CHOICE - choices with a larger domain e.g. year_of_birth OPEN_CHOICE - choices with a larger domain e.g. year_of_birth
""" """
EASY_CHOICE_FEATURES = ['gender', 'level_of_education']
OPEN_CHOICE_FEATURES = ['year_of_birth']
def raise_not_implemented():
raise NotImplementedError("feature requested not implemented but is advertised in AVAILABLE_PROFILE_FEATURES {}" .format(feature))
feature_results = {} feature_results = {}
if not feature in AVAILABLE_PROFILE_FEATURES: if not feature in AVAILABLE_PROFILE_FEATURES:
raise ValueError("unsupported feature requested for distribution '{}'".format(feature)) raise ValueError("unsupported feature requested for distribution '{}'".format(feature))
if feature in EASY_CHOICE_FEATURES: if feature in _EASY_CHOICE_FEATURES:
if feature == 'gender': if feature == 'gender':
raw_choices = UserProfile.GENDER_CHOICES raw_choices = UserProfile.GENDER_CHOICES
elif feature == 'level_of_education': elif feature == 'level_of_education':
raw_choices = UserProfile.LEVEL_OF_EDUCATION_CHOICES raw_choices = UserProfile.LEVEL_OF_EDUCATION_CHOICES
else:
raise raise_not_implemented()
choices = [(short, full) for (short, full) in raw_choices] + [('no_data', 'No Data')] choices = [(short, full) for (short, full) in raw_choices] + [('no_data', 'No Data')]
...@@ -53,14 +47,12 @@ def profile_distribution(course_id, feature): ...@@ -53,14 +47,12 @@ def profile_distribution(course_id, feature):
count = CourseEnrollment.objects.filter(course_id=course_id, user__profile__gender=short).count() count = CourseEnrollment.objects.filter(course_id=course_id, user__profile__gender=short).count()
elif feature == 'level_of_education': elif feature == 'level_of_education':
count = CourseEnrollment.objects.filter(course_id=course_id, user__profile__level_of_education=short).count() count = CourseEnrollment.objects.filter(course_id=course_id, user__profile__level_of_education=short).count()
else:
raise raise_not_implemented()
data[short] = count data[short] = count
feature_results['data'] = data feature_results['data'] = data
feature_results['type'] = 'EASY_CHOICE' feature_results['type'] = 'EASY_CHOICE'
feature_results['display_names'] = dict(choices) feature_results['display_names'] = dict(choices)
elif feature in OPEN_CHOICE_FEATURES: elif feature in _OPEN_CHOICE_FEATURES:
profiles = UserProfile.objects.filter(user__courseenrollment__course_id=course_id) profiles = UserProfile.objects.filter(user__courseenrollment__course_id=course_id)
query_distribution = profiles.values(feature).annotate(Count(feature)).order_by() query_distribution = profiles.values(feature).annotate(Count(feature)).order_by()
# query_distribution is of the form [{'featureval': 'value1', 'featureval__count': 4}, {'featureval': 'value2', 'featureval__count': 2}, ...] # query_distribution is of the form [{'featureval': 'value1', 'featureval__count': 4}, {'featureval': 'value2', 'featureval__count': 2}, ...]
...@@ -77,7 +69,5 @@ def profile_distribution(course_id, feature): ...@@ -77,7 +69,5 @@ def profile_distribution(course_id, feature):
feature_results['data'] = distribution feature_results['data'] = distribution
feature_results['type'] = 'OPEN_CHOICE' feature_results['type'] = 'OPEN_CHOICE'
else:
raise raise_not_implemented()
return feature_results return feature_results
...@@ -14,10 +14,10 @@ class TestAnalyticsDistributions(TestCase): ...@@ -14,10 +14,10 @@ class TestAnalyticsDistributions(TestCase):
def setUp(self): def setUp(self):
self.course_id = 'some/robot/course/id' self.course_id = 'some/robot/course/id'
self.users = tuple(UserFactory( self.users = [UserFactory(
profile__gender=['m', 'f', 'o'][i % 3], profile__gender=['m', 'f', 'o'][i % 3],
profile__year_of_birth=i + 1930 profile__year_of_birth=i + 1930
) for i in xrange(30)) ) for i in xrange(30)]
self.ces = tuple(CourseEnrollment.objects.create(course_id=self.course_id, user=user) for user in self.users) self.ces = tuple(CourseEnrollment.objects.create(course_id=self.course_id, user=user) for user in self.users)
...@@ -27,13 +27,6 @@ class TestAnalyticsDistributions(TestCase): ...@@ -27,13 +27,6 @@ class TestAnalyticsDistributions(TestCase):
self.assertNotIn(feature, AVAILABLE_PROFILE_FEATURES) self.assertNotIn(feature, AVAILABLE_PROFILE_FEATURES)
profile_distribution(self.course_id, feature) profile_distribution(self.course_id, feature)
@raises(NotImplementedError)
def test_profile_distribution_not_implemented_feature(self):
feature = 'ROBOT_DO_NOT_USE_FEATURE'
AVAILABLE_PROFILE_FEATURES.append(feature)
self.assertIn(feature, AVAILABLE_PROFILE_FEATURES)
profile_distribution(self.course_id, feature)
def test_profile_distribution_easy_choice(self): def test_profile_distribution_easy_choice(self):
feature = 'gender' feature = 'gender'
self.assertIn(feature, AVAILABLE_PROFILE_FEATURES) self.assertIn(feature, AVAILABLE_PROFILE_FEATURES)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment