Skip to content
This repository has been archived by the owner on May 24, 2019. It is now read-only.

Optimize compute_ranks by assuming users contribute to the same country again. #287

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 31 additions & 10 deletions leaderboard/contributors/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections import defaultdict
import operator

from bulk_update.helper import bulk_update
Expand Down Expand Up @@ -67,28 +68,48 @@ def _compute_ranks(cls, contributions):
(rank.contributor_id, rank.country_id): rank
for rank in ContributorRank.objects.all()
}
countries = Country.objects.all()

contributor_prior_countries = defaultdict(set)
for contributor_id, country_id in contributor_ranks.keys():
if country_id is not None:
contributor_prior_countries[contributor_id].add(country_id)

countries = (Country.objects.order_by('-area')
.only('id', 'geometry').all())
prepared_countries = dict([(country.id, country.geometry.prepared)
for country in countries])

for contribution in contributions:
# Each contribution counts towards the rank in the country in which
# it was made, as well as the global rank for that contributor.

contribution_country = None
contribution_country_id = None

# Attempt to find a country which contains the observation point
for country in countries:
if country.geometry.contains(contribution.point):
contribution_country = country
# Check if the contribution is in one of the countries the
# contributor has contributed to before.
for country_id in contributor_prior_countries.get(
contribution.contributor_id, ()):

prepared = prepared_countries.get(country_id)
if prepared and prepared.contains(contribution.point):
contribution_country_id = country_id
break

# Attempt to find a country which contains the observation point
if contribution_country_id is None:
for country_id, prepared in prepared_countries.items():
if prepared.contains(contribution.point):
contribution_country_id = country_id
break

# If no point was found, find the nearest country
if contribution_country is None:
contribution_country = sorted([
if contribution_country_id is None:
contribution_country_id = sorted([
(country.geometry.distance(contribution.point), country)
for country in countries
])[0][1]
])[0][1].id

for country_id in (contribution_country.id, None):
for country_id in (contribution_country_id, None):
rank_key = (contribution.contributor_id, country_id)
contributor_rank = contributor_ranks.get(rank_key, None)

Expand Down