Estoy pensando en la mejor manera de diseñar un sistema de logros para usar en mi sitio. La estructura de la base de datos se puede encontrar en Best way to tell 3 or more consecutive records missing y este hilo es realmente una extensión para obtener las ideas de los desarrolladores.La mejor manera de programar el sistema de Logros
El problema que tengo con muchas conversaciones sobre insignias/sistemas de logros en este sitio web es simplemente eso: todo es hablar y no tener código. ¿Dónde están los ejemplos reales de implementación del código?
Propongo aquí un diseño que espero que las personas puedan contribuir y, con suerte, crear un buen diseño para codificar sistemas de logros extensibles. No digo que esto sea lo mejor, ni mucho menos, pero es un posible bloqueo inicial.
Por favor, siéntete libre de aportar tus ideas.
mi idea de diseño del sistema
Parece que el consenso general es crear un "sistema basado en eventos" - cada vez que un evento conocido se produce como un poste está creado, eliminado, etc que llama el clase de evento como tal ..
$event->trigger('POST_CREATED', array('id' => 8));
La clase de evento y luego se entera de lo insignias están "escuchando" para este evento, entonces requires
ese archivo, y crea una instancia de esa clase, así:
require '/badges/' . $file;
$badge = new $class;
Llama al evento predeterminado que pasa los datos recibidos cuando se llamó trigger
;
$badge->default_event($data);
las insignias
Ésta es entonces donde sucede la magia real. cada insignia tiene su propia consulta/lógica para determinar si se debe otorgar una insignia. Cada insignia se establece en, por ejemplo, este 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
función proviene de una clase extendida Badge
que básicamente comprueba si el usuario ya ha concedido ser esa placa, si no, se actualizará la tabla db insignia. La clase de insignia también se encarga de recuperar todas las insignias para un usuario y devolverlas en una matriz, etc. (para que las insignias se muestren en el perfil del usuario)
¿Qué ocurre cuando el sistema se implementa por primera vez en un sitio en vivo?
También hay una consulta de trabajo "cron" que se puede agregar a cada insignia. La razón de esto es porque cuando el sistema de credenciales se implementa y se inicia por primera vez, las insignias que ya deberían haberse ganado no se han adjudicado porque este es un sistema basado en eventos. Por lo tanto, se ejecuta a demanda un trabajo CRON para que cada insignia otorgue todo lo que debe ser. Por ejemplo, el trabajo de cron para lo anterior se vería así:
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);
}
}
}
medida que la clase cron anterior se extiende la clase principal insignia, se puede volver a utilizar la función lógica try_award
La razón por la cual se crea una especializada la consulta para esto es a pesar de que podríamos "simular" eventos anteriores, es decir,Revisar cada publicación de usuario y activar la clase de evento como $event->trigger()
sería muy lento, especialmente para muchas insignias. Entonces creamos una consulta optimizada.
¿qué usuario recibe el premio? todo sobre la adjudicación de otros usuarios sobre la base de caso
Los Badge
clase award
función actúa sobre user_id
- que siempre se les dará el premio. Por defecto, la insignia se otorga a la persona que CAUSÓ el evento, es decir, la identificación de usuario de la sesión (esto es cierto para la función default_event
, aunque el trabajo CRON obviamente enlaza a todos los usuarios y adjudica a usuarios separados)
Así que tomemos un ejemplo, en un sitio web de desafío de codificación, los usuarios envían su entrada de codificación. El administrador juzga las entradas y, cuando se completa, publica los resultados en la página de desafío para que todos lo vean. Cuando esto sucede, se llama a un evento POSTED_RESULTS.
Si desea otorgar insignias para los usuarios de todas las entradas publicadas, digamos que si se clasificaron dentro de las 5 principales, debería usar el trabajo cron (aunque sin tener en cuenta esto se actualizará para todos los usuarios, no solo para ese desafío se publicaron los resultados para)
Si desea apuntar a un área más específica para actualizar con el trabajo cron, veamos si hay una manera de agregar parámetros de filtrado en el objeto cron job, y obtener el cron_job función para usarlos. Por ejemplo:
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 función cron seguirá funcionando incluso si el parámetro no se suministra.
Relacionados (tal vez duplicados): http://stackoverflow.com/questions/1744747/achievements-badges-system – Gordon
Está relacionado pero no duplicado. Por favor, lea el segundo párrafo. "El problema que tengo con muchas conversaciones sobre insignias/sistemas de logros en este sitio web es simplemente eso: todo es hablar y no tener código. ¿Dónde están los ejemplos de implementación del código?" –
, escribir código de trabajo solo es factible hasta cierto punto. Diría que es normal que las personas te den la teoría solamente, una vez que cualquier implementación sea demasiado compleja. – Gordon