Conversation
Previously, the daily streak was updated on ANY authenticated API call (via the @requires_session decorator), causing streaks to continue even when users just opened the app without practicing. Changes: - Add reset_streak_if_broken() to UserLanguage - resets streak to 0 if user hasn't practiced in 2+ days (called on login) - Change @requires_session to call reset_streak_if_broken() instead of update_streak_if_needed() - only resets broken streaks, doesn't increment - Add update_user_streak() helper function for practice endpoints - Add streak updates to actual practice endpoints: - /report_exercise_outcome (completing exercises) - /reading_session_start (starting to read) - /listening_session_start (starting to listen) - /get_one_translation (translating words while reading) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Saves max_streak and max_streak_date before resetting daily_streak, so users can see their all-time best even after breaking a streak. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| MODIFY username VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_bin; | ||
|
|
||
| -- This is maybe needed | ||
| SET SQL_SAFE_UPDATES = 0; |
There was a problem hiding this comment.
Is it needed to disable the safe updates?
It was needed the local database, is it also needed in prod?
| zeeguu.core.model.db.session.add(user) | ||
| zeeguu.core.model.db.session.commit() | ||
| return "OK" | ||
| except ValueError as e: |
There was a problem hiding this comment.
Maybe some comments here that describe the error cases and when/why they happen?
There was a problem hiding this comment.
Should we log the errors too?
There was a problem hiding this comment.
I think the new docs might be enough, but we probably should add the logging
zeeguu/core/model/user_avatar.py
Outdated
|
|
||
|
|
||
| class UserAvatar(db.Model): | ||
| """ |
There was a problem hiding this comment.
I descriptive comment here
There was a problem hiding this comment.
We looked at some of the other models and they don't really use top-level docs, I think the comments on the methods should be enough
Updated the name of the badge svgs to match the theme colors
There was a problem hiding this comment.
Hi folks, I started reviewing your code, and spent the last 1h trying to make sense of the DB model for badges. This means that the model is not clear enough.
I left you some comments in there. Please look at them, and propose a new DB model that takes them into account.
You don't have to reimplement just yet. Maybe propose a new design and let's discuss it first. Don't overthink the format — a simple text description is enough:
- activity_type: id, metric (e.g. TRANSLATED_WORDS), description
- badge: id, activity_type_id, level, threshold, name ("Word Wizard"), icon
... etc.
|
|
||
| CREATE TABLE badge ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| code VARCHAR(100) NOT NULL, |
There was a problem hiding this comment.
What's a badge 'code'? Add a comment for the definition of a column with such a generic name.
There was a problem hiding this comment.
now i see, so "code" is the thing that you're measuring, e.g. "TRANSLATED_WORDS". it should be called measured_activity or metric.
| @@ -0,0 +1,40 @@ | |||
| -- tools/migrations/26-02-19--add_badge_and_user_badge_tables.sql | |||
|
|
|||
| CREATE TABLE badge ( | |||
There was a problem hiding this comment.
this is not a badge. it's a "badge category". e.g. "reading streak" is not a badge, it's rather a badge family or a badge category. or badge class. or am I wrong/
| UNIQUE(code) | ||
| ); | ||
|
|
||
| CREATE TABLE badge_level ( |
There was a problem hiding this comment.
this is the actual. badge I think?
| CREATE TABLE badge ( | ||
| id INT AUTO_INCREMENT PRIMARY KEY, | ||
| code VARCHAR(100) NOT NULL, | ||
| name VARCHAR(100) NOT NULL, |
There was a problem hiding this comment.
This is a bit too limited, isn't it? Because now all the badges I get for reading will have the same name. Or am I wrong? I don't think with that current design we can do something like:
- Level 1 (10 words): "Word Curious"
- Level 2 (100 words): "Translation Enthusiast"
- Level 3 (500 words): "Lexical Leader"
- Level 4 (1000 words): "Word Wizard"
- Level 5 (2500 words): "Polyglot Machine"
This would make a lot of sense, wouldn't it?
And it shouldn't be a big change.
| target_value INT NOT NULL, | ||
| icon_name VARCHAR(255), | ||
| UNIQUE(badge_id, level), | ||
| FOREIGN KEY (badge_id) REFERENCES badge(id) |
There was a problem hiding this comment.
This design works well for counter-based badges, but keep in mind it doesn't naturally support one-off badges like "completed your first article" or "set up your profile." For those you'd have to create a badge with a single level where target_value = 1 which works mechanically but is a hack. Is this intentional? If this is meant to be the badge system long-term, it's worth thinking about now.
| FOREIGN KEY (badge_id) REFERENCES badge(id) | ||
| ); | ||
|
|
||
| CREATE TABLE user_badge_level ( |
There was a problem hiding this comment.
this is a badge that the user achieves, should be named user_badge. that will be natural if you rename the tables above too.
| FOREIGN KEY (badge_level_id) REFERENCES badge_level(id) | ||
| ); | ||
|
|
||
| CREATE TABLE user_badge_progress ( |
There was a problem hiding this comment.
this is also confusing - my impression is that this is not a user_badge progress but rather, a user_metric -- that tracks "how many words has this user translaterd". the fact that the 'metric badges' read from this table does not make this table a badge table. also, this makes again more sense if instead of 'badge_id' you'd say "badge_family_id"... Although, this also feels wrong. I guess this kind of suggests that our top table could become an "activity_type". especially if it loses the name which moves to the individuyal "badge".
Gamification of Zeeguu
In this PR we have added the backend for features such as friends, friend streak, badges, friend leaderboard, classroom leaderboard.
In one image we have added:

Database changes
See changes in
tools/migration26-02-19--add_badges.sql26-02-24-a-add_username.sql26-02-24-b-add_username.py26-02-24--friendship_system.sql26-02-26--add_max_streak_to_user_language.sql26-02-28--insert_default_badges.sql26-02-28--add_user_avatar.sqlWe have added new tables:
Testing added
test_friends.py(core/model)test_friends.py(api)test_badges.pyIssues and dicussions
Also see sub issues
Breakdown PRs of features
Gamification feature flag
Friends and Profile
Badges
Leaderboards
Gamification Feature - Branch Summary
This branch introduces a social and gamification layer to the Zeeguu platform, including a Friend System, Badge System, User Avatars, and Usernames.
Database Migrations
26-02-19--add_badges.sqlbadge,badge_level,user_badge_level, anduser_badge_progresstables26-02-24-a-add_username.sqlusernamecolumn to theusertable (unique, case-sensitive, UTF-8)26-02-24-b-add_username.pyadjective_noun1234usernames for all existing users26-02-24--friendship_system.sqlfriendandfriend_requeststables26-02-26--add_max_streak_to_user_language.sqlmax_streakandmax_streak_datecolumns touser_language; seeds from existingdaily_streakvalues26-02-28--insert_default_badges.sqlbadgeandbadge_level26-03-13--add_user_avatar.sqluser_avatartableNew Database Tables
friendStores accepted friendships between two users. Each row represents a directional link (
user_id→friend_id). Tracks:friend_streak— incremented when both friends practice on the same dayfriend_streak_last_updated— timestamp of the last streak updatedeleted_at— soft delete supportfriend_requestsStores pending friend requests from a sender to a receiver, with timestamps for creation (
created_at) and response (responded_at).badgeDefines available badges, each identified by a unique
code(e.g.TRANSLATED_WORDS,STREAK_COUNT).badge_levelDefines the levels (1–5) for each badge with a
target_valuethreshold and an optionalicon_name.user_badge_levelRecords which badge levels a user has achieved, with
achieved_attimestamp and anis_shownflag to track whether the achievement notification has been displayed.user_badge_progressTracks a user's current progress value toward each badge (e.g. number of words translated, current streak length).
user_avatarStores a user's avatar configuration:
image_name,character_color, andbackground_color.New Models
Friend(zeeguu/core/model/friend.py) — Friendship record with streak logic.update_friend_streak()checks both users' most recent practice date across all languages and increments or resets accordingly.FriendRequest(zeeguu/core/model/friend_request.py) — Manages the full friend request lifecycle: send, accept, reject, and delete.Badge/BadgeLevel(zeeguu/core/model/badge.py,badge_level.py) — Badge definitions and tiered levels withBadgeCodeenum for type-safe references.UserBadgeLevel(zeeguu/core/model/user_badge_level.py) — Tracks achieved badge levels per user, with helper to mark all unseen achievements as shown.UserBadgeProgress(zeeguu/core/model/user_badge_progress.py) — Tracks per-user progress metrics for each badge.UserAvatar(zeeguu/core/model/user_avatar.py) — Stores and updates a user's avatar style (image, character color, background color).Badge System
A new
zeeguu/core/badges/badge_progress.pymodule provides two functions used throughout the codebase:increment_badge_progress(session, badge_code, user_id, increment=1)— increments a user's progress counter and automatically awards any newly unlocked badge levels.update_badge_progress(session, badge_code, user_id, current_value)— overwrites the progress value (used for absolute metrics like streak count).Badge progress is hooked into existing core actions:
TRANSLATED_WORDSCORRECT_EXERCISESCOMPLETED_AUDIO_LESSONSSTREAK_COUNTLEARNED_WORDSREAD_ARTICLESThe
NUMBER_OF_FRIENDSbadge is defined and seeded but progress is tracked separately via the friend system.Default badges seeded (7 badges × 5 levels each):
New API Endpoints
Friend System (
/zeeguu/api/endpoints/friends.py)/get_friends/get_friends/<username>/get_number_of_received_friend_requests/get_received_friend_requests/get_sent_friend_requests/send_friend_request/delete_friend_request/accept_friend_request/reject_friend_request/unfriend/search_usersFriend responses include: user name/username, friendship details (including
friend_streak), avatar, and language streak info.Badge System (
/zeeguu/api/endpoints/badges.py)/badges/badges/<username>/badges/count_not_shown/badges/update_not_shownUser Profile Updates (extended in
/zeeguu/api/endpoints/user.py)PUT /update_accountnow also acceptsusername,avatar_image_name,avatar_character_color, andavatar_background_colorto let users customize their public identity.Changes to Existing Models
Userusernamefield — unique, case-sensitive (UTF-8 bin collation), max 50 chars.adjective_noun1234format (e.g.brave_tiger5678), supporting up to ~3.6M unique combinations.@validates("username").UserLanguagemax_streakandmax_streak_datecolumns.max_streakis automatically updated wheneverdaily_streakexceeds the previous maximum.