2009-09-08 17 views
8

Digamos que tengo alrededor de 1,000,000 de usuarios. Quiero saber en qué posición se encuentra cualquier usuario y qué usuarios lo rodean. Un usuario puede obtener un nuevo logro en cualquier momento, y si pudiera ver su actualización permanente, sería maravilloso.Django: Cómo crear una clasificación

Honestamente, cada forma de pensar que haré esto sería tremendamente costosa en tiempo y/o memoria. Ideas? Mi idea más cercana hasta ahora es ordenar a los usuarios fuera de línea y acumular cubos de percentiles, pero eso no le puede mostrar al usuario su posición exacta.

algún código por si eso ayuda a que la gente 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) 

Respuesta

4

Creo Counterstrike resuelve este solicitando a los usuarios para satisfacer un umbral mínimo para convertirse clasificado - sólo tiene que ordenar con exactitud el 10% o lo que sea .

Si desea clasificar a todos, considere que no necesita ordenarlos a la perfección: ordénelos en 2 figuras significativas. Con los usuarios de 1M, podrías actualizar la tabla de líderes para los 100 mejores usuarios en tiempo real, los siguientes 1000 usuarios para acercarlos a los 10 más cercanos, y luego las masas para el 1% o 10% más cercano. No saltarás del lugar 500,000 para colocar 99 en una ronda.

No tiene sentido obtener el contexto de 10 usuarios por encima y por debajo de 500,000 - el orden de las masas será increíblemente inestable de ronda a ronda debido a la distribución exponencial.

Editar: Eche un vistazo a SO leaderboard. Ahora vaya a page 500 de 2500 (aproximadamente 20 percentil). ¿Tiene algún sentido decirle a la gente con el representante '157' que las 10 personas de cada lado también tienen el representante '157'? Saltará 20 lugares de cualquier manera si su representante sube o baja un punto. Más extremo, es que en este momento las 1056 páginas inferiores (de 2538), o el 42% inferior de los usuarios, están vinculados con la rep 1. obtienes un punto más, y saltaste a 1055 pages. Que es aproximadamente un aumento de 37,000 en rango. Puede ser genial decirles "¡puedes vencer a 37 mil personas si obtienes un punto más!" pero, ¿importa cuántas cifras significativas tiene el número 37k?

No hay ningún valor en conocer a tus compañeros en una escalera hasta que ya estés en la parte superior, porque en cualquier lugar excepto en la parte superior, hay una cantidad abrumadora de ellos.

+0

Alguien por favor edítelo para que sea más elocuente, me voy a la cama. –

+0

Intentaba darles a los usuarios un objetivo mostrándoles a las personas que estaban por encima de ellos que latir, pero no demasiado lejos como para ser inalcanzable. –

+0

el jitter hacia la parte inferior de la distribución será tan grande que incluso subiendo o bajando 1 punto caerá u obtendrá varios miles de lugares de 1M. Deberías medir cómo se ve tu distribución de puntajes. –

0

Un millón no es tanto, lo probaría de la manera fácil primero. Si la propiedad de puntos es lo que está ordenando, debe ser una columna de base de datos. Entonces puedes hacer un recuento de puntos mayor que la persona en cuestión para obtener el rango. Para acercar a otras personas a una persona en cuestión, haga una consulta de personas con puntos más altos y ordene el límite ascendente al número de personas que desee.

Lo complicado será calcular los puntos en guardar. Necesita usar la hora actual como un multiplicador de bonificación. Ahora es necesario que un punto se convierta en un número que está a menos de 1 punto dentro de 5 días. Si sus usuarios ganan puntos con frecuencia, deberá crear una cola para manejar la carga.

Cuestiones relacionadas