Ich denke über den besten Weg nach, ein Leistungssystem für die Verwendung auf meiner Website zu entwerfen. Die Datenbankstruktur finden Sie unter Bester Weg, um 3 oder mehr fehlende aufeinanderfolgende Datensätze zu erkennen, und dieser Thread ist wirklich eine Erweiterung, um die Ideen von Entwicklern zu erhalten.
Das Problem, das ich mit vielen Gesprächen über Abzeichen / Leistungssysteme auf dieser Website habe, ist genau das - es ist alles Gerede und kein Code. Wo sind die tatsächlichen Beispiele für die Codeimplementierung?
Ich schlage hier ein Design vor, zu dem die Leute hoffentlich beitragen und hoffentlich ein gutes Design für die Codierung erweiterbarer Leistungssysteme erstellen können. Ich sage nicht, dass dies das Beste ist, weit davon entfernt, aber es ist ein möglicher Startblock.
Bitte zögern Sie nicht, Ihre Ideen einzubringen.
meine Systemdesign-Idee
Es scheint, dass der allgemeine Konsens darin besteht, ein "ereignisbasiertes System" zu erstellen - wenn ein bekanntes Ereignis auftritt, wie ein Beitrag erstellt, gelöscht usw. wird, wird die Ereignisklasse wie folgt aufgerufen.
$event->trigger('POST_CREATED', array('id' => 8));
Die Ereignisklasse findet dann heraus, welche Badges auf dieses Ereignis "warten", dann auf diese requires
Datei und erstellt eine Instanz dieser Klasse wie folgt:
require '/badges/' . $file;
$badge = new $class;
Anschließend wird das Standardereignis trigger
aufgerufen, das die beim Aufruf empfangenen Daten übergibt .
$badge->default_event($data);
die Abzeichen
Hier geschieht dann die wahre Magie. Jedes Abzeichen hat eine eigene Abfrage / Logik, um zu bestimmen, ob ein Abzeichen vergeben werden soll. Jedes Abzeichen ist zB in folgendem Format angegeben:
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
Die Funktion stammt aus einer erweiterten Klasse, Badge
die im Grunde prüft, ob dem Benutzer dieses Badge bereits zuerkannt wurde. Wenn nicht, wird die Badge-DB-Tabelle aktualisiert. Die Ausweisklasse kümmert sich auch darum, alle Ausweise für einen Benutzer abzurufen und in einem Array usw. zurückzugeben (so können Ausweise z. B. im Benutzerprofil angezeigt werden).
Was ist, wenn das System zum ersten Mal auf einer bereits aktiven Site implementiert wird?
Es gibt auch eine "Cron" -Jobabfrage, die jedem Ausweis hinzugefügt werden kann. Der Grund dafür ist, dass bei der erstmaligen Implementierung und Initiierung des Ausweissystems die bereits erworbenen Ausweise noch nicht vergeben wurden, da es sich um ein ereignisbasiertes System handelt. Daher wird bei Bedarf für jedes Abzeichen ein CRON-Job ausgeführt, um alles zu vergeben, was erforderlich ist. Zum Beispiel würde der CRON-Job für das Obige folgendermaßen aussehen:
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);
}
}
}
Da die obige Cron-Klasse die Haupt-Badge-Klasse erweitert, kann sie die Logikfunktion wiederverwenden try_award
Der Grund, warum ich eine spezielle Abfrage dafür erstelle, ist, dass wir frühere Ereignisse "simulieren" könnten, dh jeden Benutzerbeitrag durchgehen und die Ereignisklasse auslösen, als $event->trigger()
wäre sie sehr langsam, insbesondere für viele Abzeichen. Also erstellen wir stattdessen eine optimierte Abfrage.
Welcher Benutzer erhält die Auszeichnung? Alles über die Vergabe anderer Benutzer basierend auf dem Ereignis
Die Badge
Klassenfunktion award
wirkt auf user_id
- sie erhalten immer die Auszeichnung. Standardmäßig wird der Ausweis an die Person vergeben, die das Ereignis verursacht hat, dh die Sitzungsbenutzer-ID (dies gilt für die default_event
Funktion, obwohl der CRON-Job offensichtlich alle Benutzer durchläuft und separate Benutzer vergibt).
Nehmen wir also ein Beispiel für eine Codierungs-Challenge-Website, auf der Benutzer ihren Codierungseintrag einreichen. Der Administrator beurteilt dann die Einträge und veröffentlicht die Ergebnisse nach Abschluss auf der Herausforderungsseite, damit alle sie sehen können. In diesem Fall wird ein POSTED_RESULTS-Ereignis aufgerufen.
Wenn Sie für alle veröffentlichten Einträge Ausweise für Benutzer vergeben möchten, sollten Sie beispielsweise den Cron-Job verwenden, wenn diese unter den Top 5 stehen (obwohl dies nicht nur für diese Herausforderung, sondern auch für alle Benutzer aktualisiert wird Ergebnisse wurden veröffentlicht für)
Wenn Sie auf einen bestimmten Bereich abzielen möchten, der mit dem Cron-Job aktualisiert werden soll, prüfen Sie, ob es eine Möglichkeit gibt, dem Cron-Jobobjekt Filterparameter hinzuzufügen, und lassen Sie die Funktion cron_job diese verwenden. Beispielsweise:
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);
}
}
Die Cron-Funktion funktioniert auch dann noch, wenn der Parameter nicht angegeben wird.