2009-09-08 1 views
8

Допустим, у меня около 1 000 000 пользователей. Я хочу узнать, в какой позиции находится данный пользователь, и какие пользователи вокруг него. Пользователь может получить новое достижение в любое время, и если бы он мог видеть его постоянное обновление, это было бы замечательно.Django: Как создать таблицу лидеров

Честно говоря, всякий раз, когда я думаю об этом, это будет ужасно дорого во времени и/или памяти. Идеи? Моя самая близкая идея пока заключается в том, чтобы заказывать пользователей в автономном режиме и создавать процентильные ведра, но это не может показать пользователю его точное положение.

Некоторые код, если это помогает Джанго людей:

class Alias(models.Model) : 
    awards = models.ManyToManyField('Award', through='Achiever') 

    @property 
    def points(self) : 
     p = cache.get('alias_points_' + str(self.id)) 
     if p is not None : return p 

     points = 0 
     for a in self.achiever_set.all() : 
      points += a.award.points * a.count 

     cache.set('alias_points_' + str(self.id), points, 60 * 60) # 1 hour 
     return points 

class Award(MyBaseModel): 
    owner_points = models.IntegerField(help_text="A non-normalized point value. Very subjective but try to be consistent. Should be proporional. 2x points = 2x effort (or skill)") 
    true_points = models.FloatField(help_text="The true value of this award. Recalculated with a cron job. Based on number of people who won it", editable=False, null=True) 

    @property 
    def points(self) : 
     if self.true_points : 
      # blend true_points into real points over 30 days 
      age = datetime.now() - self.created 
      blend_days = 30 
      if age > timedelta(days=blend_days) : 
       age = timedelta(days=blend_days) 
      num_days = 1.0 * age.days/blend_days 
      r = self.true_points * num_days + self.owner_points * (1 - num_days) 
      return int(r * 10)/10.0 

     else : 
      return self.owner_points 


class Achiever(MyBaseModel): 
    award = models.ForeignKey(Award) 
    alias = models.ForeignKey(Alias) 
    count = models.IntegerField(default=1) 

ответ

4

Я думаю, что Counterstrike решает эту проблему, требуя от пользователей, чтобы удовлетворить минимальный порог, чтобы стать ранг - вам нужно только точно сортировать первые 10% или что-то ,

Если вы хотите отсортировать все, считайте, что вам не нужно их сортировать в порядке: соберите их до 2 значащих цифр. С 1M пользователями вы можете обновить таблицу лидеров для 100 лучших пользователей в режиме реального времени, следующих 1000 пользователей до ближайших 10, затем массы до ближайших 1% или 10%. Вы не будете прыгать с места 500 000 на 99 очков за один раунд.

Бессмысленно, чтобы получить 10 контекстов пользователя выше и ниже места 500 000 - упорядочение масс будет невероятно нервным от кругового к раунду из-за экспоненциального распределения.

Редактировать: Взгляните на SO leaderboard. Теперь перейдите к page 500 из 2500 (примерно 20 процентов). Есть ли смысл говорить людям с репрезентацией «157», что 10 человек по обе стороны от них также имеют репутацию «157»? Вы будете прыгать 20 мест в любом случае, если ваш представитель поднимается или опускается. Более экстремальным является то, что прямо сейчас нижние 1056 страниц (из 2538), или нижние 42% пользователей, связаны с rep 1. у вас есть еще одна точка, и вы вскочили 1055 pages. Это примерно 37 000 человек. Было бы здорово сказать им: «Вы можете победить 37 тысяч человек, если получите еще один момент!» но имеет ли значение, сколько значительных цифр имеет номер 37k?

Нет никакой ценности, зная своих сверстников на лестнице, пока вы не будете наверху, потому что в любом месте, кроме вершины, их подавляющее количество.

+0

Кто-то, пожалуйста, отредактируйте это, чтобы быть более четкими, им придется спать. –

+0

Я пытался дать пользователям цель, показывая им людей над ними, чтобы бить, но не слишком далеко, чтобы быть недостижимым. –

+0

джиттер в нижней части дистрибутива будет настолько велик, что даже поднявшись или опустившись на 1 пункт, вы опуститесь или получите несколько тысяч мест из 1M. вы должны оценить, как выглядит ваше распределение баллов. –

0

Один миллион не так много, я бы попробовал это простым способом. Если свойство points - это то, что вы сортируете, это должно быть столбцом базы данных. Тогда вы можете просто сделать счет очков больше, чем человек, о котором идет речь, чтобы получить звание. Чтобы получить других людей рядом с человеком, о котором идет речь, вы делаете запрос людей с более высокими очками и сортируете по возрастанию, ограничиваете его количеством людей, которых хотите.

Незначительная вещь будет вычислять точки сохранения. Вы должны использовать текущее время в качестве бонусного множителя. Одна точка теперь должна превратиться в число, которое составляет менее 1 пункта через 5 дней. Если ваши пользователи часто набирают очки, вам нужно будет создать очередь для обработки нагрузки.

 Смежные вопросы

  • Нет связанных вопросов^_^