Я думаю про найкращий спосіб розробити систему досягнень для використання на моєму сайті. Структуру бази даних можна знайти в найкращому способі повідомити про відсутність 3 або більше послідовних записів, і цей потік справді є розширенням для отримання ідей від розробників.
Проблема, з якою я багато розмовляю про значки / системи досягнень на цьому веб-сайті, полягає саме в цьому - це все розмови і відсутність коду. Де фактичні приклади реалізації коду?
Тут я пропоную дизайн, який, я сподіваюся, міг би зробити свій внесок і, сподіваюся, створити хороший дизайн для кодування розширюваних систем досягнень. Я не кажу, що це найкраще, далеко не так, але це можливий стартовий блок.
Будь ласка, не соромтеся внести свої ідеї.
моя ідея дизайну системи
Здається, загальним консенсусом є створення "системи, заснованої на подіях" - всякий раз, коли відома подія відбувається, як повідомлення створюється, видаляється тощо, він викликає клас подій так ...
$event->trigger('POST_CREATED', array('id' => 8));
Клас подій потім з’ясовує, які значки «прослуховують» для цієї події, потім цей requires
файл і створює екземпляр цього класу приблизно так:
require '/badges/' . $file;
$badge = new $class;
Потім вона викликає подію за замовчуванням, передаючи дані, отримані при виклику trigger
;
$badge->default_event($data);
значки
Тоді тут відбувається справжня магія. кожен знак має власний запит / логіку, щоб визначити, чи слід присвоювати значок. Кожен значок викладено, наприклад, у такому форматі:
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
Функція походить від розширеного класу, Badge
який в основному перевіряє, чи користувач вже отримав цей значок, якщо ні, то оновить таблицю значків db. Клас значків також бере на себе отримання всіх значків користувача та повернення їх у масиві тощо (тому значки можуть відображатися, наприклад, у профілі користувача)
як щодо того, коли система вперше впроваджується на вже діючому сайті?
Існує також запит на роботу "cron", який можна додати до кожного значка. Причиною цього є те, що коли система значків вперше впроваджується та ініціюється, значки, які вже мали бути зароблені, ще не присуджуються, оскільки це система, заснована на подіях. Тож робота CRON проводиться на вимогу кожного значка, щоб нагородити все, що потрібно. Наприклад, робота CRON для вищезазначеного буде виглядати так:
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);
}
}
}
Оскільки вищезазначений клас cron розширює основний клас значків, він може повторно використовувати логічну функцію try_award
Причина, по якій я створюю для цього спеціалізований запит, полягає в тому, що ми могли б "імітувати" попередні події, тобто переглядати кожну публікацію користувача та запускати клас подій, як би $event->trigger()
це було дуже повільно, особливо для багатьох значків. Тому ми замість цього створюємо оптимізований запит.
який користувач отримує нагороду? все про нагородження інших користувачів на основі події
Функція Badge
класу award
діє user_id
- вони завжди отримають нагороду. За замовчуванням значок присуджується особі, яка ВИКОНИЛА подію, тобто ідентифікатор користувача сеансу (це справедливо для default_event
функції, хоча завдання CRON, очевидно, циклічно переглядає всіх користувачів та нагороджує окремих користувачів)
Отже, давайте візьмемо приклад, на веб-сайті, що викликає кодування, користувачі подають свої записи щодо кодування. Потім адміністратор розглядає записи, а після завершення публікує результати на сторінці виклику, щоб усі бачили. Коли це трапляється, викликається подія POSTED_RESULTS.
Якщо ви хочете нагородити значки для користувачів за всі опубліковані записи, скажімо, якщо вони потрапили в топ-5, вам слід використовувати завдання cron (хоча, маючи на увазі, це буде оновлено для всіх користувачів, а не лише для цього завдання) результати були опубліковані для)
Якщо ви хочете націлити на більш конкретну область для оновлення за допомогою завдання cron, давайте подивимось, чи є спосіб додати параметри фільтрації в об’єкт завдання cron, і отримати функцію cron_job для їх використання. Наприклад:
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);
}
}
Функція cron все одно працюватиме, навіть якщо параметр не вказаний.