¿Cómo excluir los derechos de una insignia personalizada si ya se ha concedido un nivel superior? El objetivo es conceder solo el nivel más alto para el que un usuario es elegible…
Digamos que tengo 3 insignias:
Nivel 1: 5 Me gusta dados, 5 recibidos
Nivel 2: 100 Me gusta dados, 100 recibidos
Nivel 3: 250 Me gusta dados, 250 recibidos
El código a continuación es para el Nivel 2. Otros niveles no tienen nada diferente aparte del número ‘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))
En la configuración de /admin/badges/BADGE-ID, simplemente marca la opción Ejecutar consulta de revocación diariamente. La insignia se eliminará si ya no cumplen los criterios SQL.
También podrías querer que se actualicen Diariamente para que la concesión/revocación ocurran aproximadamente al mismo tiempo (medianoche hora local de tu instancia, creo).
¿Esto también necesitaría una línea adicional en la SQL de la insignia para equilibrarlo? Algo como:
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))
(posiblemente usar un BETWEEN o similar, aunque aún no lo he probado )
Y luego, cuando se ejecute la consulta, otorgará la insignia por 100 Me gusta la primera vez, la ignorará para los 101 a 249, y luego la revocará en 250 (donde la siguiente insignia se hará cargo).
Actualización: He practicado un poco con BETWEEN, y algo como esto parece capturar a todas las personas adecuadas en la prueba de muestra:
SELECT us.user_id
FROM user_stats AS us
WHERE us.likes_received BETWEEN 100 AND 249
ORDER BY us.likes_received DESC
Así que algo como esto debería funcionar si se convierte en una insignia activada:
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))
Esto es casi perfecto. Puede ocurrir un evento poco común: el usuario entrega demasiado en ‘dado’ mientras se queda corto en ‘recibido’ (o viceversa), por lo que la insignia podría perderse antes de que se conceda la siguiente (rutina de revocación).
Investigué y descubrí una propiedad interesante: something.badge_id = 123 donde ‘something’ es la variable definida por el usuario y ‘123’ el ID de otra insignia. Lo intentaré y complementaré las SQL originales de Nivel 1 y Nivel 2 con comprobaciones de descalificación contra las insignias de nivel superior.