גיימיפיקציה והזמנות

בעת שימוש בתוסף Gamification, נקודות ניתנות עבור הזמנות שמומשו.
קל לנצל זאת לרעה על ידי שליחת הזמנות ומימושן באמצעות חשבון כפול (מזויף).
כאשר חשבון מזויף כזה מוסר על ידי מנהל המערכת, ההתנהגות של תוסף ה-gamification (ומערכת ההזמנות) תלויה באופן שליחת ההזמנה.

  • אם ההזמנה קשורה לכתובת דוא"ל ספציפית והמשתמש מוסר, אזי גם רשומות ה-invite וגם רשומות ה-user_invite נמחקות(!) לצמיתות. בפעם הבאה שהג’וב Sidekiq UpdateScoresFor* יפעל, תוסף ה-gamification ינכה שוב את הנקודות שהוענקו מהניקוד.

  • אם ההזמנה לא קשורה לכתובת דוא"ל ספציפית והמשתמש מוסר, אזי רשומת ה-invited_users תוסר, אך רשומת ה-invite תישאר. הערך redemption_count לא יקטן. זה הגיוני מנקודת מבט אחת מכיוון שמימוש ההזמנה התרחש, למרות שהמשתמש הוסר לאחר מכן. אבל תוסף ה-Gamification משתמש ב-redemption_count כדי לחשב את הניקוד, כך שהנקודות לא ינוכו.

תוך כדי ניפוי באגים, גיליתי גם שעבודת הניקוד תתייחס רק להזמנות שגילן פחות מ-10 ימים. אז אם הזמנה ממומשת לאחר 11 יום, לא יוענקו נקודות כלל. עמדתי לומר 'אני מניח שצריך להסתכל על updated_at במקום על created_at אבל כאשר ספירת המימוש עבור ההזמנה גדלה, חותמת הזמן updated_at לא מטופלת.

11 לייקים

Would something along these lines work better (adjusted to fit the scorable query format - this is a test one for the data explorer :slight_smile:):

-- [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

When a user is deleted it clears them from the invited_users table, so would no longer be in the count. If the deletion happened within 10 days then it would auto-corrected, if longer then it would need a manual score refresh.

Using the redeemed_at date would account for those invites which were created longer than 10 days ago.

AND iu.user_id <> i.invited_by_id would also exclude self invites.

Joining in the users table and adding AND u.created_at > iu.redeemed_at would also exclude inviting existing users.

3 לייקים

That would be a good approach, except for one thing:

This does not work well. Sometimes the user is created slightly before the redemption took place. No idea why. Mostly tenths of seconds, but I found a few of tens of seconds as well.

Tested on a real database.

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

לייק 1

That’s interesting. I definitely didn’t account for that. :slight_smile:

Would adding a small buffer like AND u.created_at + INTERVAL '1 SECOND' > iu.redeemed_at compensate for that without impacting it too much?

I find this a bit too much “black magic” since we don’t know what is causing the delay.

I suspect the delay is caused by a large sidekiq queue or something similar and although the majority is under one second, about 3% is in the range of 0:00:01 - 0:15:00 (one second to 15 minutes).

And half a percent is in the order of days, which seems the kind of abuse we’re trying to prevent. So although this is effective, it would be doing more bad than good because of the amount of false positives.

2 לייקים

This should resolve it:

לייק 1

This feels like a different feature request vs bug. (cc @Falco )

This topic was automatically closed after 3 days. New replies are no longer allowed.