feat: add community contribution ranks
This commit is contained in:
98
apps/gamification/rules.py
Normal file
98
apps/gamification/rules.py
Normal file
@@ -0,0 +1,98 @@
|
||||
"""Stable scoring weights and derived lifetime rank/badge rules."""
|
||||
|
||||
POINTS = {
|
||||
"attendance": 30,
|
||||
"post": 20,
|
||||
"comment": 5,
|
||||
"like": 1,
|
||||
"save": 1,
|
||||
}
|
||||
|
||||
LEVELS = (
|
||||
{"id": "companion", "label": "همراه", "minimum_points": 0},
|
||||
{"id": "contributor", "label": "مشارکتگر", "minimum_points": 30},
|
||||
{"id": "ally", "label": "همیار", "minimum_points": 150},
|
||||
{"id": "influencer", "label": "اثرگذار", "minimum_points": 750},
|
||||
{"id": "pioneer", "label": "پیشرو", "minimum_points": 1500},
|
||||
)
|
||||
|
||||
ACTIVITY_BADGES = {
|
||||
"attendance": (
|
||||
{"threshold": 1, "label": "حضور اول", "description": "حضور تأییدشده در یک رویداد"},
|
||||
{"threshold": 5, "label": "همراه رویدادها", "description": "حضور تأییدشده در پنج رویداد"},
|
||||
{"threshold": 10, "label": "همیار رویدادها", "description": "حضور تأییدشده در ده رویداد"},
|
||||
{"threshold": 25, "label": "چهره آشنای رویدادها", "description": "حضور تأییدشده در بیستوپنج رویداد"},
|
||||
),
|
||||
"posts": (
|
||||
{"threshold": 1, "label": "نویسنده انجمن", "description": "انتشار یا همنویسندگی یک نوشته"},
|
||||
{"threshold": 5, "label": "نویسنده فعال", "description": "انتشار یا همنویسندگی پنج نوشته"},
|
||||
{"threshold": 10, "label": "نویسنده برجسته", "description": "انتشار یا همنویسندگی ده نوشته"},
|
||||
),
|
||||
"comments": (
|
||||
{"threshold": 5, "label": "اهل گفتوگو", "description": "پنج دیدگاه یا پاسخ تأییدشده"},
|
||||
{"threshold": 20, "label": "همراه گفتوگو", "description": "بیست دیدگاه یا پاسخ تأییدشده"},
|
||||
{"threshold": 50, "label": "صدای اثرگذار", "description": "پنجاه دیدگاه یا پاسخ تأییدشده"},
|
||||
),
|
||||
"likes": (
|
||||
{"threshold": 10, "label": "دستگرم", "description": "ده پسند دادهشده یا دریافتشده"},
|
||||
{"threshold": 50, "label": "محبوب انجمن", "description": "پنجاه پسند دادهشده یا دریافتشده"},
|
||||
{"threshold": 100, "label": "الهامبخش", "description": "صد پسند دادهشده یا دریافتشده"},
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def level_for_points(points: int) -> dict:
|
||||
points = max(0, int(points))
|
||||
return next(level for level in reversed(LEVELS) if points >= level["minimum_points"])
|
||||
|
||||
|
||||
def level_progress(points: int) -> dict:
|
||||
points = max(0, int(points))
|
||||
current_index = max(
|
||||
index for index, level in enumerate(LEVELS) if points >= level["minimum_points"]
|
||||
)
|
||||
current = LEVELS[current_index]
|
||||
next_level = LEVELS[current_index + 1] if current_index + 1 < len(LEVELS) else None
|
||||
|
||||
if next_level is None:
|
||||
return {
|
||||
"current_level": current,
|
||||
"next_level": None,
|
||||
"points_to_next": 0,
|
||||
"progress_percent": 100,
|
||||
}
|
||||
|
||||
span = next_level["minimum_points"] - current["minimum_points"]
|
||||
progress_points = points - current["minimum_points"]
|
||||
return {
|
||||
"current_level": current,
|
||||
"next_level": next_level,
|
||||
"points_to_next": next_level["minimum_points"] - points,
|
||||
"progress_percent": min(100, int(progress_points * 100 / span)),
|
||||
}
|
||||
|
||||
|
||||
def earned_badges(total_points: int, activity_counts: dict[str, int]) -> list[dict]:
|
||||
badges = []
|
||||
for level in LEVELS:
|
||||
if total_points >= level["minimum_points"]:
|
||||
badges.append({
|
||||
"id": f"level-{level['id']}",
|
||||
"category": "level",
|
||||
"label": level["label"],
|
||||
"description": f"سطح کلی با {level['minimum_points']} امتیاز",
|
||||
"threshold": level["minimum_points"],
|
||||
})
|
||||
|
||||
for category, levels in ACTIVITY_BADGES.items():
|
||||
count = max(0, int(activity_counts.get(category, 0)))
|
||||
badge_prefix = "post" if category == "posts" else category
|
||||
for badge_level in levels:
|
||||
threshold = badge_level["threshold"]
|
||||
if count >= threshold:
|
||||
badges.append({
|
||||
"id": f"{badge_prefix}-{threshold}",
|
||||
"category": category,
|
||||
**badge_level,
|
||||
})
|
||||
return badges
|
||||
Reference in New Issue
Block a user