Domanda

Diciamo che ho circa 1.000.000 utenti. Voglio sapere quale posizione qualsiasi utente è in, e che gli utenti sono intorno a lui. Un utente può ottenere un nuovo risultato in qualsiasi momento, e se avesse potuto vedere il suo aggiornamento in piedi, che sarebbe meraviglioso.

Onestamente, ogni modo penso di fare questo sarebbe terribilmente costoso nel tempo e / o la memoria. Idee? La mia idea più vicino finora è quello di ordinare gli utenti non in linea e costruire secchi percentili, ma che non può mostrare un utente la sua esatta posizione.

Alcuni codice, se questo ti aiuta a Django persone:

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)
È stato utile?

Soluzione

Credo che Counterstrike risolve questo richiedendo agli utenti di incontrare una soglia minima per diventare classificato - avete solo bisogno di ordinare con precisione il 10% o qualsiasi altra cosa

.

Se si desidera ordinare tutti, considera che non c'è bisogno di ordinarli perfettamente: ordinarli a 2 cifre significative. Con 1M utenti si potrebbe aggiornare la classifica per i primi 100 utenti in tempo reale, i prossimi 1000 utenti al più vicino 10, poi le masse l'approssimazione di 1% o 10%. Non sarà saltare da un posto 500.000 a mettere 99 in un round.

Il suo senso per ottenere il contesto di 10 utente sopra e sotto posto 500.000 -. L'ordinamento delle masse sarà incredibilmente nervosa di giro in giro a causa della distribuzione esponenziale

Modifica: Date un'occhiata alla SO leaderboard . Andare a pagina href="https://stackoverflow.com/users?page=500"> su 2500 (circa 20 ° percentile). Esiste un punto a dire le persone con rep '157' che le 10 persone su entrambi i lati di loro hanno anche rep '157'? Salterai 20 posti in entrambi i casi, se il vostro rappresentante di sale o scende di un punto. Più estremo, è che in questo momento le 1056 pagine di fondo (su 2538), o la parte inferiore 42% degli utenti, sono legati con rep 1. si ottiene un punto in più, e si alzò di scatto 1055 . Che è più o meno un aumento di 37.000 di rango. Potrebbe essere cool per dire loro "si può battere 37k persone se si ottiene un punto in più!" ma lo fa indipendentemente dal numero di cifre significative del numero 37k ha?

Non c'è alcun valore a conoscere i vostri coetanei su una scala fino a quando sei già al top, perché ovunque, ma la parte superiore, c'è un numero enorme di loro.

Altri suggerimenti

Un milione non è tanto, vorrei provare nel modo più semplice prima. Se la proprietà punti è la cosa che si sta ordinando il che ha bisogno di essere una colonna del database. Poi si può solo fare un conteggio di punti superiore alla persona in questione per ottenere il rango. Per ottenere altre persone vicino a una persona in questione si fa una query di persone con punti più elevati e in ordine crescente limite al numero di persone che si desidera.

La cosa più difficile sarà il calcolo dei punti di salvataggio. È necessario utilizzare l'ora corrente come un moltiplicatore bonus. Un punto deve ora trasformarsi in un numero che è inferiore a 1 punto 5 giorni. Se gli utenti guadagnano punti spesso è necessario creare una coda per gestire il carico.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top