Вопрос

Допустим, у меня около 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)
Это было полезно?

Решение

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

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

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

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

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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top