Skip to content
Snippets Groups Projects
Commit 6e346aab authored by Martin Mareš's avatar Martin Mareš
Browse files

Home: Statistics on unread threads are shown to students, too

The implementation turned out to be surprisingly tricky.

Closes #61.
parent bbdd3b4a
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
from flask import g, request, url_for, render_template, redirect, session, flash from flask import g, request, url_for, render_template, redirect, session, flash
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from sqlalchemy import select, update, and_, or_ from sqlalchemy import select, update, and_, or_, union, literal
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
import sqlalchemy.sql.functions as func import sqlalchemy.sql.functions as func
from typing import Dict, List, Tuple from typing import Dict, List, Tuple
...@@ -21,35 +21,62 @@ def index(): ...@@ -21,35 +21,62 @@ def index():
sess = db.get_session() sess = db.get_session()
semesters, enrolls, enrolls_by_sem = list_courses(True) semesters, enrolls, enrolls_by_sem = list_courses(True)
# For now, we calculate new post statictics only for teachers. course_ids_teacher = set(e.course.cid for e in enrolls if e.is_teacher)
# It would be nice to extend it to students when we verify that course_ids_student = set(e.course.cid for e in enrolls if not e.is_teacher)
# the performance is reasonable. For students, we will need to course_ids = course_ids_teacher | course_ids_student
# limit target uids to g.uid and -1 (and probably mix these two
# together).
course_ids = set(e.course.cid for e in enrolls if e.is_teacher)
if course_ids: if course_ids:
mtime_subq = ( mtime_subqs = []
seen_subqs = []
if course_ids_teacher:
# Consider non-global posts in all threads of the course
mtime_subqs.append(
select(db.Topic.cid, db.Post.tid, db.Post.target_uid, func.max(db.Post.created).label('last_created'), func.max(db.Post.modified).label('last_modified')) select(db.Topic.cid, db.Post.tid, db.Post.target_uid, func.max(db.Post.created).label('last_created'), func.max(db.Post.modified).label('last_modified'))
.select_from(db.Post) .select_from(db.Post)
.join(db.Topic) .join(db.Topic)
.filter(db.Topic.cid.in_(course_ids)) .filter(db.Topic.cid.in_(course_ids_teacher))
.filter(db.Post.target_uid >= 0)
.filter(db.Post.author_uid >= 0) .filter(db.Post.author_uid >= 0)
.filter(db.Post.target_uid >= 0)
.group_by(db.Topic.cid, db.Post.tid, db.Post.target_uid) .group_by(db.Topic.cid, db.Post.tid, db.Post.target_uid)
.subquery()
) )
seen_subq = ( # Consider acknowledges by all teachers of the course
seen_subqs.append(
select(db.Seen.tid, db.Seen.target_uid, func.max(db.Seen.seen).label('last_seen')) select(db.Seen.tid, db.Seen.target_uid, func.max(db.Seen.seen).label('last_seen'))
.select_from(db.Seen) .select_from(db.Seen)
.join(db.Topic, db.Topic.tid == db.Seen.tid) .join(db.Topic, db.Topic.tid == db.Seen.tid)
.join(db.Enroll, and_(db.Enroll.cid == db.Topic.cid, db.Enroll.uid == db.Seen.observer_uid)) .join(db.Enroll, and_(db.Enroll.cid == db.Topic.cid, db.Enroll.uid == db.Seen.observer_uid))
.filter(db.Enroll.cid.in_(course_ids)) .filter(db.Enroll.cid.in_(course_ids_teacher))
.filter(db.Enroll.is_teacher == True) .filter(db.Enroll.is_teacher == True)
.group_by(db.Seen.tid, db.Seen.target_uid) .group_by(db.Seen.tid, db.Seen.target_uid)
.subquery()
) )
if course_ids_student:
# Consider only global posts and posts in my threads, all in public topics only
mtime_subqs.append(
select(db.Topic.cid, db.Post.tid, literal(g.uid).label('target_uid'), func.max(db.Post.created).label('last_created'), func.max(db.Post.modified).label('last_modified'))
.select_from(db.Post)
.join(db.Topic)
.filter(db.Topic.cid.in_(course_ids_student))
.filter(db.Topic.public == True)
.filter(db.Post.author_uid >= 0)
.filter(db.Post.target_uid.in_((g.uid, -1)))
.group_by(db.Topic.cid, db.Post.tid)
)
# Consider only my acknowledges
seen_subqs.append(
select(db.Seen.tid, literal(g.uid).label('target_uid'), func.max(db.Seen.seen).label('last_seen'))
.select_from(db.Seen)
.join(db.Topic, db.Topic.tid == db.Seen.tid)
.filter(db.Seen.observer_uid == g.uid)
.filter(db.Topic.cid.in_(course_ids_student))
.group_by(db.Seen.tid)
)
mtime_subq = union(*mtime_subqs).subquery()
seen_subq = union(*seen_subqs).subquery()
new_post_counts = sess.execute( new_post_counts = sess.execute(
select(mtime_subq.c.cid, func.count()) select(mtime_subq.c.cid, func.count())
.select_from(mtime_subq) .select_from(mtime_subq)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment