Реализация наград и рейтинга пользователей

191
27 августа 2018, 19:50

Вопрос довольно абстрактный:

Стоит задача реализации рейтинга и наград пользователей сайта. За определенные действия на сайте пользователь получает награду и определенное количество рейтинга. Приведу примеры наград:

Собственно вопрос: как грамотно реализовать такой функционал?

Вижу 2 способа:

  1. при определенных действиях пользователя определять, выполнены ли условия для получения той или иной награды, запоминать в базе, что этот пользователь получил награду, а рейтинг пересчитывать исходя из того, какие награды он получил (будет таблица rewards с полями id, name, icon, rating), просто складывать значения поля rating

  2. для каждого пользователя в таблице users хранить текущее значение рейтинга и наращивать это поле по мере получения новых наград

И вижу здесь одну проблему:

допустим пользователь получил награду, например, за 100-й лайк к своей записи (в БД создалась запись о том что данный пользователь имеет эту награду), потом один из тех кто поставил лайк убирает его, и уже становится не 100, а 99 лайков. Как отслеживать подобные ситуации?

И, опять же, по примеру выше, в какой момент лучше проверять выполнение условий этой награды? Можно такие проверки делать каждый раз, когда кто-то ставит лайк (делать запрос в БД и проверять, нет ли в списке его записей такой, которую лайкнули не менее 100 раз. Но может есть другие, более правильные, варианты?

Буду рад любому совету или замечанию по данному вопросу, заранее благодарю! ;)

Answer 1
Предлагаю такую структуру данных:

Для метрик:

Создать таблицу с метриками:

+----------+----------+-----+----------+
| users_id | metric_x | ... | metric_y |
+----------+----------+-----+----------+
|        1 |       10 | ... |      310 |
|        2 |       34 | ... |      103 |
+----------+----------+-----+----------+

Либо в более нормализованном виде (но за 1 запрос будет уже не строка, а список):

+----------+------------+----------+
| users_id |       name |    value |
+----------+------------+----------+
|        1 |          1 |       10 |
|        1 |          2 |      310 |
|        2 |          1 |       34 |
|        2 |          2 |      103 |
+----------+------------+----------+

Для достижений:

Ссылка на пользователя и на достижение (можно в список достижений уже поместить фото, описание, и если достижений не много можно хранить их в массиве)

+----------+-----------------+
| users_id |  achievement_id |
+----------+-----------------+
|        1 |               1 |
|        1 |               2 |
|        2 |               1 |
|        3 |               8 |
+----------+-----------------+

Таблица с достижениями (многоточие означают информацию о достижении):

и поле metric_id говорят какая метрика и value и когда достижение будет выполнено, но у этого примера есть ограничения его скорей всего будет сложно использовать например для достижений по 2 метрикам или достижениям который зависят от достижений и скорей всего стоит отказать от достижений или объединить их с метриками.

+----+-----+------------+-------+
| id | ... |  metric_id | value |
+----+-----+------------+-------+
|  1 | ... |          1 |   300 |
|  2 | ... |          2 |   200 |
|  3 | ... |          1 |    50 |
+----+-----+------------+-------+

И тригеры которые будут вызываться при нужных действиях:

И пример псевдокода (использую нормализованную таблицу для метрик):

public function trigger_update($user_id, $metric_id, $metric_value, $achievement) { 
    $sql = "UPDATE metric SET value = value + {$metric_value} 
            WHERE users_id = {$user_id} AND name = {$metric_id}";
    // выполнения запроса и получения элемента 
    $metic_value = sql_query($sql).commit();
    $sql = "SELECT * FROM achievement WHERE id = {$achievement} AND metric_id = {$metric_id} AND value >= ${value}";
    if (sql_query($sql).commit() !== Null){          
        $sql = "INSERT INTO users_achievement (users_id, achievement_id) VALUES ({$user_id}, {$achievement});"
        // и да, нужен индекс что-бы записи были уникальны 
        // и тут нужны обработка исключений или select что-бы нормально реагировать на то что у человека уже есть данное достижение. 
        sql_query($sql).commit();
        push_user($user_id, $metric_value);  // и метод уведомления
    }
}

p.s.

И достижения можно хранить в массиве и их условие, и не использовать для этих целей базу, из плюсов нет лишних запросов в БД, из минусов нет возможности быстро их менять.

READ ALSO
Ошибка подключения!

Ошибка подключения!

Здравствуйте уважаемые ветераны PHP и обычные пользователиСтолкнулся с проблемой подключения, пишу Вам что бы разобраться как ее решить )

208
Смена контента при клике jQuery

Смена контента при клике jQuery

Есть массив php в который занесен контент

201
SMS регистрация и авторизация

SMS регистрация и авторизация

Необходимо реализовать на сайте регистрацию и авторизацию через смсИнтересует часть касающаяся логики процесса на стороне сайта

184