def user_problem_exp_view(request, problem_id): curr_exp = Experience(request.user) try: difficulty = ProblemDifficulty.objects.get(problem=problem_id) problem_exp = difficulty.experience except ProblemDifficulty.DoesNotExist: problem_exp = 0 new_exp = Experience(level=curr_exp.current_level, experience=curr_exp.current_experience + problem_exp) if new_exp.current_level == curr_exp.current_level: exp_diff_percent = \ ((new_exp.current_experience - curr_exp.current_experience) / curr_exp.required_experience_to_lvlup) * 100 else: whole_levels = \ (new_exp.current_level - curr_exp.current_level - 1) * 100 from_curr = \ 100 - ((curr_exp.current_experience / curr_exp.required_experience_to_lvlup) * 100) to_expected = (new_exp.current_experience / new_exp.required_experience_to_lvlup) * 100 exp_diff_percent = whole_levels + from_curr + to_expected return JsonResponse({ 'current_exp': (curr_exp.current_experience / curr_exp.required_experience_to_lvlup) * 100, 'current_lvl': curr_exp.current_level, 'exp_to_add': exp_diff_percent })
def test_experience_basic(self): # Yeah I guess not that much testing can be done here self.assertRaises(ValueError, Experience.exp_to_lvl, -1) self.assertRaises(ValueError, Experience.exp_to_lvl, 0) self.assertEquals(Experience.exp_to_lvl(1), ExpMultiplier) self.assertEquals(Experience.exp_to_lvl(2), ExpBase * ExpMultiplier) self.assertEquals( Experience.exp_to_lvl(SoftCapLevel + 1), Experience.exp_to_lvl(SoftCapLevel) + LinearMultiplier)
def test_experience_basic(self): # Yeah I guess not that much testing can be done here self.assertRaises(ValueError, Experience.exp_to_lvl, -1) self.assertRaises(ValueError, Experience.exp_to_lvl, 0) self.assertEquals(Experience.exp_to_lvl(1), ExpMultiplier) self.assertEquals(Experience.exp_to_lvl(2), ExpBase * ExpMultiplier) self.assertEquals( Experience.exp_to_lvl(SoftCapLevel + 1), Experience.exp_to_lvl(SoftCapLevel) + LinearMultiplier )
def _experience_widget(user, size): exp = Experience(user) percentage = exp.current_experience \ / float(exp.required_experience_to_lvlup) is_big = (size == 'big') outer_radius = LARGE_WIDGET_OUTER_RADIUS if is_big \ else SMALL_WIDGET_OUTER_RADIUS angle = 2 * math.pi * percentage endX = outer_radius * math.sin(angle) endY = outer_radius * (1 - math.cos(angle)) end = str(endX) + ' ' + str(endY) large_arc_flag = '1' if percentage > 0.5 else '0' center = str(outer_radius) + ' ' + str(outer_radius) arc_parameters = center + ' 0 ' + large_arc_flag + ' 1 ' + end return { 'percentage': percentage, 'level': exp.current_level, 'inner_radius': LARGE_WIDGET_INNER_RADIUS, 'outer_radius': outer_radius, 'diameter': outer_radius * 2, 'size': size, 'arc_parameters': arc_parameters }
def test_experience_from_pair(self): test_user = User.objects.get(username='******') experience = Experience(level=0, experience=ExpMultiplier + 2) self.assertEquals(experience.level_exp_tuple, (1, 2)) self.assertEquals(experience.current_level, 1) self.assertEquals(experience.current_experience, 2) self.assertRaises(ValueError, experience.force_recalculate) experience2 = Experience(level=0, experience=ExpMultiplier - 1) self.assertEquals(experience2.level_exp_tuple, (0, ExpMultiplier - 1)) self.assertRaises(ValueError, Experience, user=test_user, level=1) self.assertRaises(ValueError, Experience, user=test_user, experience=1) self.assertRaises(ValueError, Experience, user=test_user, level=1, experience=1)
def test_experience_counter(self): url = reverse('view_current_profile') url_other = reverse('view_profile', args=['test_user2']) self.client.login(username='******') response = self.client.get(url) self.assertIn('0</text>', response.content) self.assertIn('Level: 0', response.content) self.assertIn('0%', response.content) response = self.client.get(url_other) self.assertIn('0</text>', response.content) self.assertIn('Level: 0', response.content) self.assertIn('0%', response.content) exp_to_lvl = Experience.exp_to_lvl class TrivialSource(ExperienceSource): def get_experience(self, user): if user.username == 'test_user': return exp_to_lvl(1) + 10 else: return exp_to_lvl(1) + exp_to_lvl(2) + 10 def force_recalculate(self, user): pass try: Experience.add_experience_source(TrivialSource()) response = self.client.get(url) self.assertIn('1</text>', response.content) self.assertIn('Level: 1', response.content) self.assertIn('Experience: %d%%' % (100 * 10 / exp_to_lvl(2)), response.content) response = self.client.get(url_other) self.assertIn('2</text>', response.content) self.assertIn('Level: 2', response.content) self.assertIn('Experience: %d%%' % (100 * 10 / exp_to_lvl(3)), response.content) finally: Experience.clear_experience_sources()
def test_softcap(self): class ConstSource(ExperienceSource): """ This source always returns the same value """ def __init__(self, value): self.value = value def get_experience(self, user): return self.value def force_recalculate(self, user): pass def total_exp_to_lvl(level): total = 0 for i in xrange(1, level + 1): total += Experience.exp_to_lvl(i) return total try: Experience.add_experience_source( ConstSource(total_exp_to_lvl(SoftCapLevel))) test_user = User.objects.get(username='******') exp = Experience(test_user) self.assertEquals(exp.current_level, SoftCapLevel) self.assertEquals( exp.required_experience_to_lvlup, Experience.exp_to_lvl(SoftCapLevel) + LinearMultiplier) Experience.add_experience_source( ConstSource(Experience.exp_to_lvl((SoftCapLevel + 1)))) self.assertEquals( exp.required_experience_to_lvlup, Experience.exp_to_lvl(SoftCapLevel) + 2 * LinearMultiplier) finally: Experience.clear_experience_sources()
def test_softcap(self): class ConstSource(ExperienceSource): """ This source always returns the same value """ def __init__(self, value): self.value = value def get_experience(self, user): return self.value def force_recalculate(self, user): pass def total_exp_to_lvl(level): total = 0 for i in xrange(1, level + 1): total += Experience.exp_to_lvl(i) return total try: Experience.add_experience_source( ConstSource(total_exp_to_lvl(SoftCapLevel)) ) test_user = User.objects.get(username='******') exp = Experience(test_user) self.assertEquals(exp.current_level, SoftCapLevel) self.assertEquals( exp.required_experience_to_lvlup, Experience.exp_to_lvl(SoftCapLevel) + LinearMultiplier ) Experience.add_experience_source( ConstSource(Experience.exp_to_lvl((SoftCapLevel + 1))) ) self.assertEquals( exp.required_experience_to_lvlup, Experience.exp_to_lvl(SoftCapLevel) + 2*LinearMultiplier ) finally: Experience.clear_experience_sources()
def test_experience_counter(self): url = reverse("view_current_profile") url_other = reverse("view_profile", args=["test_user2"]) self.client.login(username="******") response = self.client.get(url) self.assertIn("0</text>", response.content) self.assertIn("Level: 0", response.content) self.assertIn("0%", response.content) response = self.client.get(url_other) self.assertIn("0</text>", response.content) self.assertIn("Level: 0", response.content) self.assertIn("0%", response.content) exp_to_lvl = Experience.exp_to_lvl class TrivialSource(ExperienceSource): def get_experience(self, user): if user.username == "test_user": return exp_to_lvl(1) + 10 else: return exp_to_lvl(1) + exp_to_lvl(2) + 10 def force_recalculate(self, user): pass try: Experience.add_experience_source(TrivialSource()) response = self.client.get(url) self.assertIn("1</text>", response.content) self.assertIn("Level: 1", response.content) self.assertIn("Experience: %d%%" % (100 * 10 / exp_to_lvl(2)), response.content) response = self.client.get(url_other) self.assertIn("2</text>", response.content) self.assertIn("Level: 2", response.content) self.assertIn("Experience: %d%%" % (100 * 10 / exp_to_lvl(3)), response.content) finally: Experience.clear_experience_sources()
def profile_view(request, username=None): shown_user = None if username is None: shown_user = request.user else: shown_user = get_object_or_404(User.objects, username=username) exp = Experience(shown_user) friends = UserFriends(request.user) is_friend = friends.is_friends_with(shown_user) pending_incoming_friendship_request = friends.has_request_from(shown_user) sent_friendship_request = friends.sent_request_to(shown_user) has_portal = False if 'oioioi.portals' in settings.INSTALLED_APPS: from oioioi.portals.models import Portal if Portal.objects.filter(owner=shown_user).exists(): has_portal = True sections = [] for func in profile_registry.items: response = func(request, shown_user) if isinstance(response, HttpResponseRedirect): return response if isinstance(response, TemplateResponse): sections.append(response.render().content) else: sections.append(response) return TemplateResponse( request, 'gamification/profile.html', { 'shown_user': shown_user, 'is_my_friend': is_friend, 'exp': exp, 'exp_percentage': int(100 * exp.current_experience / exp.required_experience_to_lvlup), 'has_portal': has_portal, 'pending_incoming_friendship_request': pending_incoming_friendship_request, 'sent_friendship_request': sent_friendship_request, 'sections': sections })
def test_problem_source(self): try: Experience.add_experience_source(PROBLEM_EXPERIENCE_SOURCE) user = User.objects.get(username='******') # test_user has solved a trivial task user_exp = Experience(user) user_exp.force_recalculate() self.assertEquals(user_exp.current_level, 0) self.assertEquals(user_exp.current_experience, Lvl1TaskExp) # Update on problem difficulty change pd = ProblemDifficulty.objects.get(problem__id=10) pd.difficulty = DIFFICULTY.EASY pd.save() self.assertEquals(user_exp.current_level, 1) self.assertEquals(user_exp.current_experience, 0) finally: Experience.clear_experience_sources()
def test_problem_source(self): try: Experience.add_experience_source(PROBLEM_EXPERIENCE_SOURCE) user = User.objects.get(username="******") # test_user has solved a trivial task user_exp = Experience(user) user_exp.force_recalculate() self.assertEquals(user_exp.current_level, 0) self.assertEquals(user_exp.current_experience, Lvl1TaskExp) # Update on problem difficulty change pd = ProblemDifficulty.objects.get(problem__id=10) pd.difficulty = DIFFICULTY.EASY pd.save() self.assertEquals(user_exp.current_level, 1) self.assertEquals(user_exp.current_experience, 0) finally: Experience.clear_experience_sources()
def suggest_task(self, user): """Returns a problem object as a suggestion for the user or None if no suggestion can be returned """ if not user.is_authenticated(): return None user_level = Experience(user).current_level if user_level >= SuggestLvl5From: qset = get_problems_by_difficulty(DIFFICULTY.IMPOSSIBLE) elif user_level >= SuggestLvl4From: qset = get_problems_by_difficulty(DIFFICULTY.HARD) elif user_level >= SuggestLvl3From: qset = get_problems_by_difficulty(DIFFICULTY.MEDIUM) elif user_level >= SuggestLvl2From: qset = get_problems_by_difficulty(DIFFICULTY.EASY) else: qset = get_problems_by_difficulty(DIFFICULTY.TRIVIAL) try: return qset.filter(is_public=True).order_by('?').first() except Problem.DoesNotExist: return None
def test_experience_with_sources(self): class TestSource(ExperienceSource): """ This class simulates desync with real experience, initially get_experience() returns one value, but after force_recalculate() return totally different one """ def __init__(self, initial, after_recalc): self.value = initial self.recalc = after_recalc def get_experience(self, user): return self.value def force_recalculate(self, user): self.value = self.recalc # To level up to lvl 1 you need the ExpMultiplier experience test_source = TestSource(1, ExpMultiplier) test_source1 = TestSource(3, 1) try: Experience.add_experience_source(test_source) Experience.add_experience_source(test_source1) test_user = User.objects.get(username='******') exp = Experience(test_user) self.assertEquals(exp.current_experience, 4) self.assertEquals(exp.current_level, 0) self.assertEquals(exp.required_experience_to_lvlup, ExpMultiplier) self.assertEquals(exp.level_exp_tuple, (0, 4)) exp.force_recalculate() self.assertEquals(exp.current_experience, 1) self.assertEquals(exp.current_level, 1) self.assertEquals(exp.required_experience_to_lvlup, ExpBase * ExpMultiplier) self.assertEquals(exp.level_exp_tuple, (1, 1)) Experience.clear_experience_sources() self.assertEquals(exp.level_exp_tuple, (0, 0)) finally: Experience.clear_experience_sources()
def setUp(self): self._backup_experience_sources = Experience._sources Experience.clear_experience_sources()
def total_exp_to_lvl(level): total = 0 for i in xrange(1, level + 1): total += Experience.exp_to_lvl(i) return total
def test_experience_with_sources(self): class TestSource(ExperienceSource): """ This class simulates desync with real experience, initially get_experience() returns one value, but after force_recalculate() return totally different one """ def __init__(self, initial, after_recalc): self.value = initial self.recalc = after_recalc def get_experience(self, user): return self.value def force_recalculate(self, user): self.value = self.recalc # To level up to lvl 1 you need the ExpMultiplier experience test_source = TestSource(1, ExpMultiplier) test_source1 = TestSource(3, 1) try: Experience.add_experience_source(test_source) Experience.add_experience_source(test_source1) test_user = User.objects.get(username='******') exp = Experience(test_user) self.assertEquals(exp.current_experience, 4) self.assertEquals(exp.current_level, 0) self.assertEquals( exp.required_experience_to_lvlup, ExpMultiplier ) self.assertEquals(exp.level_exp_tuple, (0, 4)) exp.force_recalculate() self.assertEquals(exp.current_experience, 1) self.assertEquals(exp.current_level, 1) self.assertEquals( exp.required_experience_to_lvlup, ExpBase*ExpMultiplier ) self.assertEquals(exp.level_exp_tuple, (1, 1)) Experience.clear_experience_sources() self.assertEquals(exp.level_exp_tuple, (0, 0)) finally: Experience.clear_experience_sources()