def test_contribution_set_frozen_during_rank_computation(self): contributor = ContributorFactory() country = CountryFactory() self.assertEqual(Contribution.objects.count(), 0) for i in range(3): self.create_contribution(contributor, country) self.assertEqual(Contribution.objects.count(), 3) contributions = list(Contribution.objects.all().select_related()) self.assertEqual(Contribution.objects.count(), 3) for i in range(3): self.create_contribution(contributor, country) self.assertEqual(Contribution.objects.count(), 6) ContributorRank._compute_ranks(contributions) self.assertEqual( ContributorRank.objects.get(contributor=contributor, country=None).observations, 3) self.assertEqual(Contribution.objects.count(), 3)
def test_leaderboard_is_paginated(self): today = datetime.date.today() country = CountryFactory() page_size = settings.REST_FRAMEWORK['PAGE_SIZE'] for i in range(page_size + 1): contributor = ContributorFactory() Contribution( contributor=contributor, date=today, observations=1, point=country.geometry.point_on_surface, ).save() # Create the contributor ranks ContributorRank.compute_ranks() response = self.client.get(reverse('leaders-global-list')) self.assertEqual(response.status_code, 200) contributors_data = json.loads(response.content) self.assertEqual(len(contributors_data['results']), page_size) response = self.client.get( reverse('leaders-global-list'), {'offset': page_size}, ) self.assertEqual(response.status_code, 200) contributors_data = json.loads(response.content) self.assertEqual(len(contributors_data['results']), 1)
def test_compute_ranks_matches_point_to_nearest_country(self): contributor = ContributorFactory() # Create a dummy country to find a point outside existing countries dummy_country = CountryFactory() point_outside_countries = dummy_country.geometry.point_on_surface dummy_country.delete() # The point is outside all existing countries self.assertFalse( Country.objects.filter( geometry__contains=point_outside_countries).exists()) # The point is closer to country2 self.assertGreater( self.country1.geometry.distance(point_outside_countries), self.country2.geometry.distance(point_outside_countries), ) ContributionFactory( contributor=contributor, point=point_outside_countries) self.assertFalse( ContributorRank.objects.filter(contributor=contributor).exists()) ContributorRank.compute_ranks() self.assertTrue( ContributorRank.objects.filter( contributor=contributor, country=self.country2).exists()) self.assertFalse( ContributorRank.objects.filter( contributor=contributor, country=self.country1).exists())
def setUp(self): # There are two countries self.country1 = CountryFactory() self.country2 = CountryFactory() # And there are three contributors self.contributor1 = ContributorFactory() self.contributor2 = ContributorFactory() # Contributor3 makes no contributions self.contributor3 = ContributorFactory() # Contributor1 contributes 2 times to self.country1 for i in range(2): self.create_contribution(self.contributor1, self.country1) # Contributor1 contributes 5 times to self.country2 for i in range(5): self.create_contribution(self.contributor1, self.country2) # Contributor2 contributes 3 times to self.country1 for i in range(3): self.create_contribution(self.contributor2, self.country1) # Contributor2 contributes 3 times to self.country2 for i in range(3): self.create_contribution(self.contributor2, self.country2) # Compute the global and country ranks ContributorRank.compute_ranks()
def test_compute_ranks_matches_point_to_nearest_country(self): contributor = ContributorFactory() # Create a dummy country to find a point outside existing countries dummy_country = CountryFactory() point_outside_countries = dummy_country.geometry.point_on_surface dummy_country.delete() # The point is outside all existing countries self.assertFalse( Country.objects.filter( geometry__contains=point_outside_countries).exists()) # The point is closer to country2 self.assertGreater( self.country1.geometry.distance(point_outside_countries), self.country2.geometry.distance(point_outside_countries), ) ContributionFactory(contributor=contributor, point=point_outside_countries) self.assertFalse( ContributorRank.objects.filter(contributor=contributor).exists()) ContributorRank.compute_ranks() self.assertTrue( ContributorRank.objects.filter(contributor=contributor, country=self.country2).exists()) self.assertFalse( ContributorRank.objects.filter(contributor=contributor, country=self.country1).exists())
def test_sums_for_each_contributor_and_orders_by_observations(self): today = datetime.date.today() country1 = CountryFactory() country2 = CountryFactory() contributor1 = ContributorFactory() for i in range(3): Contribution( contributor=contributor1, date=today, observations=1, point=country1.geometry.point_on_surface, ).save() contributor2 = ContributorFactory() for i in range(4): Contribution( contributor=contributor2, date=today, observations=1, point=country2.geometry.point_on_surface, ).save() # Create a contributor with no contributions # who should not appearin the leaderboard ContributorFactory() # Create the contributor ranks ContributorRank.compute_ranks() response = self.client.get(reverse('leaders-global-list')) self.assertEqual(response.status_code, 200) contributors_data = json.loads(response.content) self.assertEqual(contributors_data, { 'count': 2, 'previous': None, 'results': [ { 'uid': contributor2.uid, 'name': contributor2.name, 'observations': 4, 'rank': 1, }, { 'uid': contributor1.uid, 'name': contributor1.name, 'observations': 3, 'rank': 2, } ], 'next': None, })
def test_filters_by_country(self): today = datetime.date.today() contributor = ContributorFactory() country1 = CountryFactory() country2 = CountryFactory() contribution1 = Contribution( contributor=contributor, date=today, observations=1, point=country1.geometry.point_on_surface, ) contribution1.save() contribution2 = Contribution( contributor=contributor, date=today, observations=1, point=country1.geometry.point_on_surface, ) contribution2.save() contribution3 = Contribution( contributor=contributor, date=today, observations=1, point=country2.geometry.point_on_surface, ) contribution3.save() # Create the contributor ranks ContributorRank.compute_ranks() response = self.client.get( reverse( 'leaders-country-list', kwargs={'country_id': country1.iso2} ) ) self.assertEqual(response.status_code, 200) contributors_data = json.loads(response.content) self.assertEqual(contributors_data, { 'count': 1, 'previous': None, 'results': [{ 'uid': contributor.uid, 'name': contributor.name, 'observations': 2, 'rank': 1, }], 'next': None, })
def test_compute_ranks_removes_observations_when_complete(self): self.assertEqual(Contribution.objects.count(), 0) for i in range(3): self.create_contribution(self.contributor1, self.country1) self.assertEqual(Contribution.objects.count(), 3) ContributorRank.compute_ranks() self.assertEqual(Contribution.objects.count(), 0)
def test_new_contributions_updates_existing_ranks(self): self.assertEqual(ContributorRank.objects.count(), 6) self.create_contribution(self.contributor1, self.country1) ContributorRank.compute_ranks() self.assertEqual(ContributorRank.objects.count(), 6) rank = ContributorRank.objects.get(contributor=self.contributor1, country=self.country1) self.assertEqual(rank.observations, 3)
def test_get_leader_profile_returns_ranks_and_observations(self): today = datetime.date.today() contributor = ContributorFactory() country1 = CountryFactory() country2 = CountryFactory() for country in (country1, country2): for i in range(3): Contribution.objects.create( contributor=contributor, date=today, observations=1, point=country.geometry.point_on_surface, ) # Create the contributor ranks ContributorRank.compute_ranks() response = self.client.get( reverse( 'leaders-profile', kwargs={'uid': contributor.uid}, ), ) self.assertEqual(response.status_code, 200) profile_data = json.loads(response.content) self.assertEqual(profile_data['uid'], contributor.uid) self.assertEqual(profile_data['name'], contributor.name) self.assertEqual(len(profile_data['ranks']), 3) self.assertIn({ 'country': None, 'observations': 6, 'rank': 1 }, profile_data['ranks']) self.assertIn({ 'country': { 'iso2': country1.iso2, 'name': country1.name, }, 'observations': 3, 'rank': 1 }, profile_data['ranks']) self.assertIn({ 'country': { 'iso2': country2.iso2, 'name': country2.name, }, 'observations': 3, 'rank': 1 }, profile_data['ranks'])
def test_new_contributions_updates_existing_ranks(self): self.assertEqual(ContributorRank.objects.count(), 6) self.create_contribution(self.contributor1, self.country1) ContributorRank.compute_ranks() self.assertEqual(ContributorRank.objects.count(), 6) rank = ContributorRank.objects.get( contributor=self.contributor1, country=self.country1) self.assertEqual(rank.observations, 3)
def test_compute_ranks_updates_existing_ranks(self): self.assertEqual(ContributorRank.objects.get( country=None, contributor=self.contributor1).rank, 1) self.assertEqual(ContributorRank.objects.get( country=None, contributor=self.contributor2).rank, 2) ContributionFactory(contributor=self.contributor2, observations=10) ContributorRank.compute_ranks() self.assertEqual(ContributorRank.objects.get( country=None, contributor=self.contributor1).rank, 2) self.assertEqual(ContributorRank.objects.get( country=None, contributor=self.contributor2).rank, 1)
def test_list_countries_returns_country_data(self): today = datetime.date.today() countries = [CountryFactory() for i in range(3)] # A country with no contributions should not appear # in the results CountryFactory() for country in countries: for contributor_i in range(3): contributor = ContributorFactory() for contribution_i in range(10): Contribution.objects.create( contributor=contributor, country=country, date=today, observations=1, ) ContributorRank.compute_ranks() response = self.client.get(reverse('countries-list')) self.assertEqual(response.status_code, 200) countries_data = json.loads(response.content) self.assertEqual(len(countries_data), len(countries)) for country in countries: self.assertIn( { 'iso2': country.iso2, 'name': country.name, 'observations': 30, 'leaders_url': reverse( 'leaders-country-list', kwargs={'country_id': country.iso2}, ), }, countries_data)
def test_compute_ranks_updates_existing_ranks(self): self.assertEqual( ContributorRank.objects.get(country=None, contributor=self.contributor1).rank, 1) self.assertEqual( ContributorRank.objects.get(country=None, contributor=self.contributor2).rank, 2) ContributionFactory(contributor=self.contributor2, observations=10) ContributorRank.compute_ranks() self.assertEqual( ContributorRank.objects.get(country=None, contributor=self.contributor1).rank, 2) self.assertEqual( ContributorRank.objects.get(country=None, contributor=self.contributor2).rank, 1)
def test_list_countries_returns_country_data(self): today = datetime.date.today() countries = [CountryFactory() for i in range(3)] # A country with no contributions should not appear # in the results CountryFactory() for country in countries: for contributor_i in range(3): contributor = ContributorFactory() for contribution_i in range(10): Contribution.objects.create( contributor=contributor, point=country.geometry.point_on_surface, date=today, observations=1, ) ContributorRank.compute_ranks() response = self.client.get(reverse('countries-list')) self.assertEqual(response.status_code, 200) countries_data = json.loads(response.content) self.assertEqual(len(countries_data), len(countries)) for country in countries: self.assertIn({ 'iso2': country.iso2, 'name': country.name, 'observations': 30, 'leaders_url': reverse( 'leaders-country-list', kwargs={'country_id': country.iso2}, ), }, countries_data)
def test_contribution_set_frozen_during_rank_computation(self): contributor = ContributorFactory() country = CountryFactory() self.assertEqual(Contribution.objects.count(), 0) for i in range(3): self.create_contribution(contributor, country) self.assertEqual(Contribution.objects.count(), 3) contributions = list(Contribution.objects.all().select_related()) self.assertEqual(Contribution.objects.count(), 3) for i in range(3): self.create_contribution(contributor, country) self.assertEqual(Contribution.objects.count(), 6) ContributorRank._compute_ranks(contributions) self.assertEqual(ContributorRank.objects.get( contributor=contributor, country=None).observations, 3) self.assertEqual(Contribution.objects.count(), 3)
def handle(self, *args, **options): ContributorRank.compute_ranks()