Sto pensando al modo migliore per progettare un sistema di risultati da utilizzare sul mio sito. La struttura del database può essere trovata nel modo migliore per dire 3 o più record consecutivi mancanti e questo thread è davvero un'estensione per ottenere le idee dagli sviluppatori.
Il problema che ho con un sacco di discorsi su badge / sistemi di realizzazione su questo sito Web è proprio questo: sono solo chiacchiere e niente codice. Dove sono gli esempi effettivi di implementazione del codice?
Propongo qui un progetto a cui spero le persone possano contribuire e, si spera, creare un buon progetto per la codifica di sistemi di realizzazione estensibili. Non sto dicendo che questo sia il migliore, tutt'altro, ma è un possibile blocco di partenza.
Sentiti libero di contribuire con le tue idee.
la mia idea di progettazione del sistema
Sembra che il consenso generale sia quello di creare un "sistema basato su eventi" - ogni volta che si verifica un evento noto come la creazione, l'eliminazione di un post, ecc. Chiama la classe dell'evento in questo modo
$event->trigger('POST_CREATED', array('id' => 8));
La classe dell'evento quindi scopre quali badge sono "in ascolto" per questo evento, quindi su requires
quel file e crea un'istanza di quella classe, in questo modo:
require '/badges/' . $file;
$badge = new $class;
Quindi chiama l'evento predefinito passando i dati ricevuti quando è trigger
stato chiamato;
$badge->default_event($data);
i badge
È qui che avviene la vera magia. ogni badge ha una propria query / logica per determinare se un badge deve essere assegnato. Ogni badge è esposto ad esempio in questo formato:
class Badge_Name extends Badge
{
const _BADGE_500 = 'POST_500';
const _BADGE_300 = 'POST_300';
const _BADGE_100 = 'POST_100';
function get_user_post_count()
{
$escaped_user_id = mysql_real_escape_string($this->user_id);
$r = mysql_query("SELECT COUNT(*) FROM posts
WHERE userid='$escaped_user_id'");
if ($row = mysql_fetch_row($r))
{
return $row[0];
}
return 0;
}
function default_event($data)
{
$post_count = $this->get_user_post_count();
$this->try_award($post_count);
}
function try_award($post_count)
{
if ($post_count > 500)
{
$this->award(self::_BADGE_500);
}
else if ($post_count > 300)
{
$this->award(self::_BADGE_300);
}
else if ($post_count > 100)
{
$this->award(self::_BADGE_100);
}
}
}
award
La funzione proviene da una classe estesa Badge
che fondamentalmente controlla per vedere se l'utente ha già ricevuto quel badge, in caso contrario aggiornerà la tabella db badge. La classe badge si occupa anche di recuperare tutti i badge per un utente e di restituirli in un array, ecc. (Così i badge possono essere visualizzati ad esempio sul profilo utente)
e quando il sistema viene implementato per la prima volta su un sito già attivo?
C'è anche una query di lavoro "cron" che può essere aggiunta a ciascun badge. Il motivo è che quando il sistema di badge è stato implementato e avviato per la prima volta, i badge che avrebbero dovuto essere già guadagnati non sono stati ancora assegnati perché si tratta di un sistema basato su eventi. Quindi un lavoro CRON viene eseguito su richiesta per ogni badge per assegnare tutto ciò che deve essere. Ad esempio, il lavoro CRON per quanto sopra sarebbe simile a:
class Badge_Name_Cron extends Badge_Name
{
function cron_job()
{
$r = mysql_query('SELECT COUNT(*) as post_count, user_id FROM posts');
while ($obj = mysql_fetch_object($r))
{
$this->user_id = $obj->user_id; //make sure we're operating on the right user
$this->try_award($obj->post_count);
}
}
}
Poiché la classe cron precedente estende la classe badge principale, può riutilizzare la funzione logica try_award
Il motivo per cui creo una query specializzata per questo è anche se potremmo "simulare" eventi precedenti, cioè passare attraverso ogni post degli utenti e attivare la classe dell'evento come $event->trigger()
se fosse molto lento, specialmente per molti badge. Quindi creiamo invece una query ottimizzata.
quale utente ottiene il premio? tutto sulla premiazione di altri utenti in base all'evento
La funzione di Badge
classe award
agisce su user_id
: verrà sempre assegnato il premio. Per impostazione predefinita, il badge viene assegnato alla persona che HA CAUSATO l'evento, ovvero l'ID utente della sessione (questo è vero per la default_event
funzione, anche se il lavoro CRON ovviamente passa attraverso tutti gli utenti e premia gli utenti separati)
Quindi, facciamo un esempio, su un sito Web di sfida di codifica gli utenti inviano la loro voce di codifica. L'amministratore quindi giudica le voci e, una volta completate, pubblica i risultati nella pagina della sfida affinché tutti possano vederli. Quando ciò accade, viene chiamato un evento POSTED_RESULTS.
Se vuoi assegnare badge per gli utenti per tutte le voci pubblicate, diciamo, se fossero classificate tra le prime 5, dovresti usare il cron job (anche se a mente questo verrà aggiornato per tutti gli utenti, non solo per quella sfida i risultati sono stati pubblicati per)
Se vuoi indirizzare un'area più specifica da aggiornare con il cron job, vediamo se esiste un modo per aggiungere parametri di filtro nell'oggetto cron job e ottenere la funzione cron_job per usarli. Per esempio:
class Badge_Top5 extends Badge
{
const _BADGE_NAME = 'top5';
function try_award($position)
{
if ($position <= 5)
{
$this->award(self::_BADGE_NAME);
}
}
}
class Badge_Top5_Cron extends Badge_Top5
{
function cron_job($challenge_id = 0)
{
$where = '';
if ($challenge_id)
{
$escaped_challenge_id = mysql_real_escape_string($challenge_id);
$where = "WHERE challenge_id = '$escaped_challenge_id'";
}
$r = mysql_query("SELECT position, user_id
FROM challenge_entries
$where");
while ($obj = mysql_fetch_object($r))
{
$this->user_id = $obj->user_id; //award the correct user!
$this->try_award($obj->position);
}
}
La funzione cron continuerà a funzionare anche se il parametro non viene fornito.