Source code for timApp.lecture.lectureanswer

import json
from json import JSONDecodeError
from typing import Optional

from sqlalchemy import func
from sqlalchemy.orm import lazyload

from timApp.lecture.lecture import Lecture
from timApp.timdb.sqa import db
from timApp.user.user import User


[docs]def unshuffle_lectureanswer( answer: list[list[str]], question_type: str, row_count: int, rand_arr: list[int] ) -> list[list[str]]: if question_type == "matrix" or question_type == "true-false": unshuffled_ans = [[] for x in range(row_count)] for i, pos in enumerate(rand_arr): unshuffled_ans[pos - 1] = answer[i] else: unshuffled_ans = [[]] for choice in answer[0]: unshuffled_ans[0].append(str(rand_arr[int(choice) - 1])) return unshuffled_ans
[docs]class LectureAnswer(db.Model): __tablename__ = "lectureanswer" answer_id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("useraccount.id"), nullable=False) question_id = db.Column( db.Integer, db.ForeignKey("askedquestion.asked_id"), nullable=False ) lecture_id = db.Column( db.Integer, db.ForeignKey("lecture.lecture_id"), nullable=False ) answer = db.Column(db.Text, nullable=False) answered_on = db.Column(db.DateTime(timezone=True), nullable=False) points = db.Column(db.Float) asked_question = db.relationship( "AskedQuestion", back_populates="answers", lazy="joined" ) user = db.relationship("User", back_populates="lectureanswers", lazy="joined")
[docs] @staticmethod def get_by_id(ans_id: int) -> Optional["LectureAnswer"]: return LectureAnswer.query.get(ans_id)
[docs] def get_parsed_answer(self): # If lecture question's rows are randomized, it will be saved as a dict # containing additional information about how the answerer saw the question. # e.g {"c": [["2"]], "order": [4, 3, 5], "rows": 5, "question_type": "radio-vertical"} try: ans = json.loads(self.answer) if isinstance(ans, dict): ans = unshuffle_lectureanswer( ans.get("c"), ans.get("question_type"), ans.get("rows"), ans.get("order"), ) except (JSONDecodeError, IndexError): ans = [] return ans
[docs] def to_json(self, include_question=True, include_user=True): ans = self.get_parsed_answer() result = { "answer": ans, "answer_id": self.answer_id, "answered_on": self.answered_on, "points": self.points, } if include_question: result["asked_question"] = self.asked_question else: result["asked_id"] = self.question_id if include_user: result["user"] = self.user else: result["user_id"] = self.user_id return result
[docs]def get_totals( lecture: Lecture, user: User | None = None ) -> list[tuple[User, float, int]]: q = User.query if user: q = q.filter_by(id=user.id) q = ( q.join(LectureAnswer) .options(lazyload(User.groups)) .filter_by(lecture_id=lecture.lecture_id) .group_by(User.id) .order_by(User.name) .with_entities(User, func.sum(LectureAnswer.points), func.count()) ) return q.all()