Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tools/migrations/26-01-27--add_daily_streak.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE user ADD COLUMN daily_streak INT NOT NULL DEFAULT 0;
1 change: 1 addition & 0 deletions zeeguu/api/endpoints/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@
from . import crawl_stats
from . import user_stats
from . import session_history
from . import daily_streak
12 changes: 12 additions & 0 deletions zeeguu/api/endpoints/bookmarks_and_words.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,18 @@ def practiced_user_word_count_this_week():
return json_result(count)


@api.route("/exercises_completed_this_week", methods=["GET"])
@cross_domain
@requires_session
def exercises_completed_this_week():
"""
Returns the total number of exercises the user has completed this week.
"""
user = User.find_by_id(flask.g.user_id)
count = user.exercises_completed_this_week()
return json_result(count)


@api.route("/past_contexts/<int:user_word_id>", methods=["GET"])
@cross_domain
@requires_session
Expand Down
14 changes: 14 additions & 0 deletions zeeguu/api/endpoints/daily_streak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import flask

from zeeguu.api.utils.json_result import json_result
from zeeguu.api.utils.route_wrappers import cross_domain, requires_session
from . import api
from ...core.model import User


@api.route("/daily_streak", methods=["GET"])
@cross_domain
@requires_session
def get_daily_streak():
user = User.find_by_id(flask.g.user_id)
return json_result({"daily_streak": user.daily_streak or 0})
34 changes: 34 additions & 0 deletions zeeguu/core/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class User(db.Model):
created_at = db.Column(db.DateTime, nullable=True)
last_seen = db.Column(db.DateTime, nullable=True)
creation_platform = db.Column(db.SmallInteger, nullable=True)
daily_streak = db.Column(db.Integer, default=0)

def __init__(
self,
Expand Down Expand Up @@ -335,6 +336,31 @@ def practiced_user_words_count_this_week(self):

return result

def exercises_completed_this_week(self):
"""
Returns the total number of exercises completed this week.
"""
from zeeguu.core.model.user_word import UserWord
from zeeguu.core.model.exercise import Exercise
from zeeguu.core.model.phrase import Phrase
from zeeguu.core.model.meaning import Meaning

today = datetime.date.today()
start_of_week = today - datetime.timedelta(days=today.weekday())

result = (
db.session.query(Exercise)
.join(UserWord, Exercise.user_word_id == UserWord.id)
.join(Meaning, UserWord.meaning_id == Meaning.id)
.join(Phrase, Meaning.origin_id == Phrase.id)
.filter(UserWord.user_id == self.id)
.filter(Exercise.time >= start_of_week)
.filter(Phrase.language_id == self.learned_language_id)
.count()
)

return result

def liked_articles(self):
from zeeguu.core.model.user_article import UserArticle

Expand All @@ -353,11 +379,19 @@ def active_during_recent(self, days: int = 30):
def update_last_seen_if_needed(self, session=None):
"""
Update last_seen timestamp, but only once per day to minimize database writes.
Also maintains the daily_streak counter.
"""
now = datetime.datetime.now()

# Only update if last_seen is None or it's a different day
if not self.last_seen or self.last_seen.date() < now.date():
if not self.last_seen:
self.daily_streak = 1
elif self.last_seen.date() == now.date() - datetime.timedelta(days=1):
self.daily_streak = (self.daily_streak or 0) + 1
else:
self.daily_streak = 1

self.last_seen = now
if session:
session.add(self)
Expand Down