@task(rate_limit='600/m', ignore_result=True)
def redo_ranks(run_id):
	from brabeion import badges
	
	logger = redo_ranks.get_logger()
	try:
		user_run = Run.objects.get(pk=run_id)
	except Run.DoesNotExist:
		logger.error("[R- /U- /M- ] Run not found (pk={0}).".format(run_id))
		return False
	map_obj = user_run.map
	if user_run.user == None:
		logger.info("[R-{0}/U- /M-{1}] Anonymous run, not"
			" processing the rank.".format(run_id, map_obj.id))
		return
	user_best = BestRun.objects.get(map=map_obj, user=user_run.user)
	if not user_best.run_id == user_run.id:
		logger.info("[R-{0}/U-{1}/M-{2}] Not best run,"
			" not processing the rank.".format(run_id, user_run.user_id, map_obj.id))
		return
	runs = BestRun.objects.filter(map=map_obj)
	# ranked = player that receives points for his place
	ranked_count = len(BestRun.SCORING)
	# exclude banned users from scoring
	ranked = runs.exclude(user__is_active=False)[:ranked_count]
	try:
		if user_run.time >= ranked[ranked_count-1].run.time:
			logger.info("[R-{0}/U-{1}/M-{2}] Run won't affect scoring,"
				" not processing the rank.".format(run_id, user_run.user_id, map_obj.id))
			return
	except __HOLE__:
		pass
	old_rank = user_run.user.profile.map_position(map_obj.id)
	new_rank = None
	i = 0
	for run in ranked:
		run.points = BestRun.SCORING[i]
		run.save()
		# FIXME it's 3 AM, sorry for that
		run.user.profile.points = BestRun.objects.filter(user=run.user).aggregate(
			Sum('points')
		)['points__sum'] or 0
		run.user.profile.save()
		i += 1
		if user_run.user_id == run.user_id:
			new_rank = i
	runs.exclude(id__in=ranked.values_list('id', flat=True)).update(
		points=0
	)
	badges.possibly_award_badge("rank_processed",
		user=user_run.user)
	logger.info("[R-{0}/U-{1}/M-{2}] {3}'s new map rank is {4} (was: {5})." \
		.format(run_id, user_run.user_id, map_obj.id, user_run.user,
			new_rank, old_rank))
dataset/ETHPy150Open chaosk/teerace/teerace/race/tasks.py/redo_ranks