84 votes

Meilleur moyen de code système Réalisations

Je suis en train de penser à la meilleure façon de concevoir un système de succès pour l'utiliser sur mon site. La structure de base de données peut être trouvé à MySQL: la Meilleure façon de dire 3 ou plus consécutifs enregistrements manquants et ce fil est vraiment une extension pour obtenir les idées des développeurs.

Le problème que j'ai avec beaucoup de parler de badges/réalisation de systèmes sur ce site est juste que -- c'est parler et sans code. Où est le code réel, la mise en œuvre des exemples?

Je vous propose ici une conception que j'espère que les gens pourraient contribuer et nous espérons créer un bon design pour le codage extensible réalisation des systèmes. Je ne dis pas que c'est le meilleur, loin de là, mais c'est un départ possible de bloquer.

N'hésitez pas à apporter vos idées.


mon système d'idée de la conception

Il semble que le consensus général est de créer un "événement en fonction système" -- chaque fois qu'un événement connu se produit comme un poste est créé, supprimé, etc il appelle la classe d'événements comme si..

$event->trigger('POST_CREATED', array('id' => 8));

La classe event puis découvre ce que les badges sont "à l'écoute" pour cet événement, il requires le fichier, et crée une instance de cette classe, comme ceci:

require '/badges/' . $file;
$badge = new $class;

Il appelle ensuite l'événement par défaut de transmettre les données reçues lors de l' trigger a été appelé;

$badge->default_event($data);

les badges

C'est alors là que la vraie magie se produit. chaque badge a sa propre requête/logique pour déterminer si un badge devrait être accordée. Chaque badge est définie dans ce format:

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 de la fonction provient d'une classe étendue Badge qui, fondamentalement, vérifie si l'utilisateur a déjà décerné le badge, si non, va mettre à jour l'insigne de la table db. L'insigne de classe prend également soin de récupérer tous les badges pour l'utilisateur et de le retourner dans un tableau, etc (donc les badges peuvent être affichés sur le profil de l'utilisateur)

qu'en est-il du système est très d'abord mis en œuvre sur un site en ligne?

Il y a aussi un "cron" emploi requête qui peut être ajouté à chaque badge. La raison pour cela est parce que quand le système de badge est très d'abord mis en œuvre et initilaised, les badges qui aurait déjà été gagnés n'ont pas encore être accordé parce que c'est un événement à partir du système. Si une tâche est exécutée à la demande pour chaque badge à prix tout ce qui doit être. Par exemple, la tâche CRON pour le ci-dessus ressemblerait à:

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);
  }
 }

}

Comme ci-dessus cron classe étend la principale insigne de classe, il peut ré-utiliser la fonction logique, try_award

La raison pour laquelle j'ai créer un spécialisé requête pour c'est bien que l'on puisse "simuler" les événements précédents, c'est à dire passer par chaque utilisateur de poste et de déclencher l'événement de classe comme $event->trigger() il serait très lente, en particulier pour de nombreux badges. Nous avons donc au lieu de créer une optimisation de requête.

ce que l'utilisateur obtient le prix? tout à propos de l'attribution des autres utilisateurs sur la base de l'événement

L' Badge classe award fonction agit sur user_id -- ils seront toujours donné le prix. Par défaut, le badge est attribué à la personne qui a CAUSÉ l'événement de se produire c'est à dire l'utilisateur de la session id (ce qui est vrai pour l' default_event de la fonction, bien que la tâche CRON évidemment une boucle par tous les utilisateurs et les prix de séparer les utilisateurs)

Donc, nous allons prendre un exemple, sur un codage de site web du défi utilisateurs de soumettre leurs codage d'entrée. L'administrateur alors les juges les entrées et lorsqu'ils ont terminé, les résultats sont affichés pour le défi page pour que tous puissent les voir. Lorsque cela se produit, un POSTED_RESULTS événement est appelé.

Si vous voulez attribuer des badges pour les utilisateurs de toutes les écritures validées, permet de dire que, s'ils ont été classés dans le top 5, vous devez utiliser le cron job (bien que bare à l'esprit cette volonté de mise à jour pour tous les utilisateurs, pas seulement pour ce défi, les résultats ont été affichés pour)

Si vous souhaitez cibler une zone plus précise de mise à jour avec le cron job, nous allons voir si il existe un moyen d'ajouter des fonctions de filtrage des paramètres dans le cron objet de travail, et d'obtenir le cron_job la fonction à utiliser. Par exemple:

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 fonction cron fonctionne même si le paramètre n'est pas fourni.

9voto

Knubo Points 3020

J'ai mis en place un système de récompense une fois dans ce que vous appelez un document orienté base de données (c'était de la boue pour les joueurs). Quelques faits saillants de ma mise en œuvre, traduite dans le PHP et MySQL:

  • Tous les détails sur le badge est stocké dans les données des utilisateurs. Si vous utilisez MySQL, je l'aurais fait en sorte que ces données dans un enregistrement par l'utilisateur dans la base de données pour la performance.

  • Chaque fois que la personne en question fait quelque chose, le code déclenche le code de badge avec un drapeau, par exemple drapeau('POST_MESSAGE').

  • Un événement pourrait également déclencher un compteur, par exemple un nombre de postes. increase_count('POST_MESSAGE'). Ici, vous pourriez avoir un chèque (soit par un crochet, ou tout simplement d'avoir un test de cette méthode) que si le POST_MESSAGE nombre est > 300 alors vous devriez avoir la récompense d'un badge, par exemple: drapeau("300_POST").

  • Dans le drapeau de la méthode, j'avais mis le code pour récompenser les badges. Par exemple, si le Drapeau 300_POST est envoyé, puis le badge reward_badge("300_POST") doit être appelée.

  • Dans le drapeau de la méthode, vous devriez également avoir les utilisateurs précédents drapeaux présents. alors on peut dire que lorsque l'utilisateur a FIRST_COMMENT, FIRST_POST, FIRST_READ vous accordez badge("NOUVEL UTILISATEUR"), et quand vous obtenez 100_COMMENT, 100_POST, 300_READ vous pouvez accorder badge("EXPERIENCED_USER")

  • Tous ces drapeaux et insignes doivent être stockés en quelque sorte. L'utilisation d'une certaine façon, lorsque vous pensez que des drapeaux sous forme de bits. Si vous voulez que ce soit stockée vraiment efficace, vous pensez à eux aussi de bits et d'utiliser le code ci-dessous: (Ou vous pouvez simplement utiliser un nu-string "000000001111000" si vous ne voulez pas de cette complexité.

$achievments = 0;
$bits = sprintf("%032b", $achievements);

/* Set bit 10 */
$bits[10] = 1;

$achievements = bindec($bits);

print "Bits: $bits\n";
print "Achievements: $achievements\n";

/* Reload */

$bits = sprintf("%032b", $achievments);

/* Set bit 5 */
$bits[5] = 1;

$achievements = bindec($bits);

print "Bits: $bits\n";
print "Achievements: $achievements\n";
  • Une belle façon de stocker un document pour l'utilisateur est d'utiliser json et de stocker les données des utilisateurs dans une seule colonne de texte. Utilisation json_encode et json_decode pour stocker/récupérer les données.

  • Pour le suivi de l'activité sur certains des utilisateurs les données manipulées par un autre utilisateur, d'ajouter une structure de données sur l'élément et utiliser des compteurs. Par exemple, lire le nombre d'. Utilisez la même technique que celle décrite ci-dessus pour l'attribution de badges, mais la mise à jour devrait naturellement aller dans la possession d'utilisateurs. (Par exemple, l'article de lire 1000 fois badge).

2voto

Navraj Chohan Points 121

UserInfuser est un open source gamification plate-forme qui met en œuvre un retrait des badges/points de service. Vous pouvez consulter son API ici: http://code.google.com/p/userinfuser/wiki/API_Documentation

J'ai mis en place et a essayé de garder le nombre de fonctions minimales. Voici l'API pour un client php:

class UserInfuser($account, $api_key)
{
    public function get_user_data($user_id);
    public function update_user($user_id);
    public function award_badge($badge_id, $user_id);
    public function remove_badge($badge_id, $user_id);
    public function award_points($user_id, $points_awarded);
    public function award_badge_points($badge_id, $user_id, $points_awarded, $points_required);
    public function get_widget($user_id, $widget_type);
}

Le résultat final est de présenter les données de façon significative grâce à l'utilisation de widgets. Ces widgets comprennent: trophée cas, du classement, des jalons, des live, des notifications, de rang et points de.

La mise en œuvre de l'API peuvent être trouvés ici: http://code.google.com/p/userinfuser/source/browse/trunk/serverside/api/api.py

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X