عند استخدام إضافة Gamification، تُمنح النقاط مقابل الدعوات التي تم استبدالها.
يسهل إساءة استخدام هذا عن طريق إرسال الدعوات واستبدالها بحساب مكرر (وهمي).
عندما يقوم المسؤول بإزالة حساب وهمي كهذا، يعتمد سلوك إضافة gamification (ونظام الدعوات) على كيفية إرسال الدعوة.
إذا كانت الدعوة مرتبطة بعنوان بريد إلكتروني محدد وتمت إزالة المستخدم، فسيتم حذف سجلات invite وسجلات user_invite بشكل كامل (!). في المرة التالية التي يتم فيها تشغيل وظيفة Sidekiq UpdateScoresFor*، ستقوم إضافة gamification بخصم النقاط الممنوحة من النتيجة مرة أخرى.
إذا كانت الدعوة غير مرتبطة بعنوان بريد إلكتروني محدد وتمت إزالة المستخدم، فسيتم إزالة سجل invited_users، ولكن سيظل سجل invite موجودًا. لن يتم تقليل قيمة redemption_count. هذا منطقي من وجهة نظر معينة لأن استبدال الدعوة قد تم، على الرغم من إزالة المستخدم بعد ذلك. لكن إضافة Gamification تستخدم redemption_count لحساب النتيجة، لذلك لن يتم خصم النقاط.
أثناء تصحيح هذا، اكتشفت أيضًا أن وظيفة النتيجة ستنظر فقط في الدعوات التي يقل عمرها عن 10 أيام. لذا، إذا تم استبدال الدعوة بعد 11 يومًا، فلن يتم منح أي نقاط على الإطلاق. كنت سأقول 'أعتقد أنه يجب أن تنظر إلى updated_at بدلاً من created_at ولكن عندما يتم زيادة عدد مرات استبدال الدعوة، لا يتم لمس الطابع الزمني updated_at.
هل سينجح شيء من هذا القبيل (تم تعديله ليناسب تنسيق الاستعلام القابل للتسجيل - هذا اختبار لمستكشف البيانات ):
-- [params]
-- date :start_date
-- date :end_date
SELECT
invited_by_id AS user_id,
COUNT(*) AS user_invites,
COUNT(*) * 10 AS invite_score
FROM invited_users iu
JOIN invites i ON i.id = iu.invite_id
JOIN users u ON u.id = iu.user_id
WHERE iu.redeemed_at::date BETWEEN :start_date AND :end_date
AND iu.user_id <> i.invited_by_id
AND u.created_at > iu.redeemed_at
GROUP BY invited_by_id
ORDER BY user_invites DESC
عند حذف مستخدم، يتم مسحه من جدول invited_users، لذلك لن يكون ضمن العدد. إذا تم الحذف في غضون 10 أيام، فسيتم تصحيحه تلقائيًا، وإذا كان أطول من ذلك، فستحتاج إلى تحديث يدوي للدرجة.
سيأخذ استخدام تاريخ redeemed_at في الاعتبار تلك الدعوات التي تم إنشاؤها منذ أكثر من 10 أيام.
AND iu.user_id <> i.invited_by_id سيستبعد أيضًا الدعوات الذاتية.
الانضمام إلى جدول users وإضافة AND u.created_at > iu.redeemed_at سيستبعد أيضًا دعوة المستخدمين الحاليين.
هذا لا يعمل بشكل جيد. في بعض الأحيان يتم إنشاء المستخدم قبل فترة وجيزة من استرداد القسيمة. لا فكرة عن السبب. في الغالب أجزاء من الثانية، ولكن وجدت أيضًا عددًا قليلاً من عشرات الثواني.
تم الاختبار على قاعدة بيانات حقيقية.
select
iu.redeemed_at iu_AS redeemed_at,
u.created_at AS u_created_at,
u.created_at > iu.redeemed_at AS u_created_gt_iu_redeemed
from invited_users iu
left join users u on u.id = iu.user_id
where iu.redeemed_at is not null
order by iu.id desc;
iu_redeemed_at | u_created_at | u_created_gt_iu_redeemed
----------------------------+----------------------------+--------------------------
2023-09-08 00:00:47.557057 | 2023-09-08 00:00:48.376446 | t
2023-08-25 20:09:03.486362 | 2023-08-25 20:09:03.201357 | f
2023-08-15 23:38:32.271709 | 2023-08-15 23:38:33.570299 | t
2023-08-14 10:44:34.19912 | 2023-08-14 10:44:35.429371 | t
2023-08-12 13:41:10.428013 | 2023-08-12 13:41:11.733973 | t
2023-07-31 17:58:13.511289 | 2023-07-31 17:57:50.427111 | f
2023-07-23 00:56:33.455185 | 2023-07-23 00:55:47.999263 | f
2023-07-19 08:42:44.908096 | 2023-07-19 08:42:46.040201 | t
2023-06-30 09:11:38.829692 | 2023-06-30 09:11:39.618586 | t
2023-06-30 08:37:02.322192 | 2023-06-30 08:37:03.133769 | t
2023-06-29 16:24:01.705616 | 2023-06-29 16:24:02.55067 | t
2023-06-29 12:53:33.245688 | 2023-06-29 12:53:34.067159 | t
أجد هذا الأمر أقرب إلى “السحر الأسود” نظرًا لأننا لا نعرف ما الذي يسبب التأخير.
أشتبه في أن التأخير ناتج عن قائمة انتظار كبيرة في Sidekiq أو شيء مشابه، وعلى الرغم من أن الغالبية أقل من ثانية واحدة، إلا أن حوالي 3٪ تتراوح بين 0:00:01 - 0:15:00 (ثانية واحدة إلى 15 دقيقة).
ونصف بالمائة في حدود أيام، وهو ما يبدو من نوع الإساءة التي نحاول منعها. لذا، على الرغم من أن هذا فعال، إلا أنه سيؤدي إلى المزيد من النتائج السلبية الخاطئة أكثر من الفوائد.