Skip to content
Closed
Changes from 2 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
61 changes: 56 additions & 5 deletions server/jobs/export_grades.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import io
import csv
import datetime as dt
from collections import defaultdict

from sqlalchemy import func

from server import jobs
from server.models import Course, Enrollment, ExternalFile, db
from server.models import Course, Enrollment, ExternalFile, db, GroupMember, Score
from server.utils import encode_id, local_time
from server.constants import STUDENT_ROLE

Expand Down Expand Up @@ -50,11 +53,11 @@ def get_headers(assignments):
headers.extend(new_headers)
return headers, new_assignments

def export_student_grades(student, assignments):

def export_student_grades(student, assignments, all_scores):
student_row = [student.user.email, student.sid]
for assign in assignments:
status = assign.user_status(student.user)
scores = {s.kind.lower(): s.score for s in status.scores}
scores = all_scores[assign.id][student.user.id]
scores = score_policy(scores)
score_types = get_score_types(assign)
for score_type in score_types:
Expand All @@ -65,6 +68,48 @@ def export_student_grades(student, assignments):
return student_row


def collect_all_scores(assignments, user_ids):
all_scores = {}

for assign in assignments:
scores = (
db.session.query(Score.user_id, Score.kind, func.max(Score.score))
.filter(
Score.user_id.in_(user_ids),
Score.assignment_id == assign.id,
Score.archived == False,
)
.group_by(Score.user_id, Score.kind)
.order_by(Score.score)
.all()
)

members = GroupMember.query.filter(
Comment thread
kavigupta marked this conversation as resolved.
Outdated
GroupMember.assignment_id == assign.id,
GroupMember.status == 'active'
).all()

group_lookup = {}
for member in members:
if member.group_id not in group_lookup:
group_lookup[member.group_id] = []
group_lookup[member.group_id].append(member.user_id)

user_scores = defaultdict(lambda: defaultdict(int))
for user_id, kind, score in scores:
user_scores[user_id][kind] = score

for group in group_lookup.values():
best_scores = defaultdict(int)
for user_id in group:
for kind, score in user_scores[user_id].items():
best_scores[kind] = max(best_scores[kind], score)
for user_id in group:
user_scores[user_id] = best_scores

all_scores[assign.id] = user_scores
return all_scores

@jobs.background_job
def export_grades():
logger = jobs.get_job_logger()
Expand All @@ -83,12 +128,18 @@ def export_grades():
logger.info('')

total_students = len(students)

users = [student.user for student in students]
user_ids = [user.id for user in users]

all_scores = collect_all_scores(assignments, user_ids)

with io.StringIO() as f:
writer = csv.writer(f)
writer.writerow(headers) # write headers

for i, student in enumerate(students, start=1):
row = export_student_grades(student, assignments)
row = export_student_grades(student, assignments, all_scores)
writer.writerow(row)
if i % 50 == 0:
logger.info('Exported {}/{}'.format(i, total_students))
Expand Down