Как исключить права на получение значка нижнего уровня, если уже выдан значок более высокого уровня? Цель — выдавать пользователю только значок наивысшего уровня, на который он имеет право…
Предположим, у меня есть 3 значка:
Уровень 1: 5 отданных лайков, 5 полученных
Уровень 2: 100 отданных лайков, 100 полученных
Уровень 3: 250 отданных лайков, 250 полученных
Ниже приведен код для Уровня 2. Для других уровней нет никаких отличий, кроме числа ‘100’
SELECT us.user_id, current_timestamp AS granted_at
FROM user_stats AS us
WHERE us.likes_received >= 100
AND us.likes_given >= 100
AND (:backfill OR us.user_id IN (:user_ids))
В настройках /admin/badges/BADGE-ID просто отметьте опцию Запускать запрос на отзыв ежедневно. Значок будет удален, если пользователи перестанут соответствовать критериям SQL.
Также рекомендуется включить опцию Обновлять ежедневно, чтобы выдача и отзыв происходили примерно в одно и то же время (около полуночи по местному времени вашего экземпляра, насколько я помню).
Не потребуется ли здесь также дополнительная строка в SQL для бейджа, чтобы сбалансировать его? Что-то вроде:
SELECT us.user_id, current_timestamp AS granted_at
FROM user_stats AS us
WHERE us.likes_received >= 100
AND us.likes_given >= 100
AND us.likes_given < 250
AND (:backfill OR us.user_id IN (:user_ids))
(возможно, использовать BETWEEN или аналогичное условие, хотя я пока не тестировал это )
И тогда при выполнении запроса бейдж за 100 лайков будет выдан в первый раз, пропущен для значений от 101 до 249, а затем отозван при достижении 250 (где следующий бейдж продолжит отсчёт).
Обновление: Я немного поэкспериментировал с BETWEEN, и что-то вроде этого, похоже, правильно определяет всех нужных пользователей в тестовом образце:
SELECT us.user_id
FROM user_stats AS us
WHERE us.likes_received BETWEEN 100 AND 249
ORDER BY us.likes_received DESC
Так что что-то вроде этого должно сработать, если преобразовать в триггерный бейдж:
SELECT us.user_id, current_timestamp AS granted_at
FROM user_stats AS us
WHERE us.likes_received BETWEEN 100 AND 249
AND us.likes_given BETWEEN 100 AND 249
AND (:backfill OR us.user_id IN (:user_ids))
Это почти идеально. Может произойти одно редкое событие: пользователь превышает лимит в ‘given’, но отстает в ‘received’ (или наоборот), из-за чего значок может быть отозван до получения следующего (процедура отзыва).
Я изучил ситуацию и обнаружил интересное свойство: something.badge_id = 123, где ‘something’ — переменная, определенная пользователем, а ‘123’ — идентификатор другого значка. Я попробую дополнить исходные SQL-запросы для уровня 1 и уровня 2 проверками на дисквалификацию в отношении значков более высокого уровня.