Отзыв бейджа нижнего уровня при получении более высокого?

Как исключить права на получение значка нижнего уровня, если уже выдан значок более высокого уровня? Цель — выдавать пользователю только значок наивысшего уровня, на который он имеет право…

Предположим, у меня есть 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 или аналогичное условие, хотя я пока не тестировал это :slight_smile:)

И тогда при выполнении запроса бейдж за 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 проверками на дисквалификацию в отношении значков более высокого уровня.

Это очень интересный момент, о котором я не подумал. :slightly_smiling_face: Двойственная природа действительно делает ситуацию немного более щекотливой. :thinking:

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