You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
8.5 KiB
228 lines
8.5 KiB
import json
|
|
import os
|
|
import uuid
|
|
import requests
|
|
from flask import Blueprint, request, jsonify, g, url_for
|
|
from uuid import UUID
|
|
from db.model import db, User, Course, Enrollment,Chat, Quiz, QuizAttempt
|
|
from utils.auth import auth_required
|
|
import requests
|
|
from config import SPAM_SCORE_THRESHOLD, AI_SPAM_SERVICES_MICROSERVICE, USER_UPLOADS_DIR, AI_QUIZ_SERVICES_MICROSERVICE
|
|
from sqlalchemy import desc, select, and_
|
|
|
|
quiz = Blueprint('quiz', __name__)
|
|
|
|
|
|
@quiz.route('/generate')
|
|
@auth_required()
|
|
def generate_quiz():
|
|
try:
|
|
course_id: uuid.UUID = uuid.UUID(request.form['course_id'])
|
|
current_page: int = int(request.form['page'])
|
|
except KeyError:
|
|
return jsonify({'message': 'course_id and page must be specified'}), 401
|
|
enrollment_record: Enrollment = db.session.execute(
|
|
select(Enrollment).where(and_(
|
|
Enrollment.courseID == course_id,
|
|
Enrollment.userID == g.current_user.id)
|
|
)
|
|
).scalar()
|
|
if not enrollment_record:
|
|
return jsonify({"error": "You are not enrolled in this course."}), 403
|
|
if current_page > enrollment_record.course.totalPages or current_page < 1:
|
|
return jsonify({
|
|
'message': 'Page range out of bound. No such page'
|
|
}), 404
|
|
# Everything is alright, now get the text in current page and generate quiz
|
|
current_page_text: str = ''
|
|
with open(
|
|
os.path.join(
|
|
USER_UPLOADS_DIR,
|
|
enrollment_record.course.serverFilename+"_parts",
|
|
f"{current_page}.txt")
|
|
) as f:
|
|
current_page_text = f.read()
|
|
quiz_data_resp = requests.post(AI_QUIZ_SERVICES_MICROSERVICE, json={"string_message": current_page_text})
|
|
if quiz_data_resp.status_code != 200:
|
|
return jsonify({"error": "Failed to make quiz request."}), 500
|
|
quiz_data = quiz_data_resp.json()
|
|
# Insert the quiz into table
|
|
rows: list[Quiz] = []
|
|
for quiz_item in quiz_data['questions']:
|
|
rows.append(
|
|
Quiz(
|
|
creatorUserID=g.current_user.id,
|
|
creatorUser=g.current_user,
|
|
quiz_attempts=[],
|
|
courseID=course_id,
|
|
course=enrollment_record.course,
|
|
quizQuestion=quiz_item['question'],
|
|
quizAnswers=json.dumps(quiz_item['options']),
|
|
quizCorrectAnswer=quiz_item['correct_answer']
|
|
)
|
|
)
|
|
db.session.add_all(rows)
|
|
db.session.commit()
|
|
return jsonify({'message': 'quizzes were generated for the current page'})
|
|
|
|
@quiz.route('/get/personalIncomplete')
|
|
@auth_required()
|
|
def get_incomplete_quiz():
|
|
try:
|
|
course_id: uuid.UUID = uuid.UUID(request.form['course_id'])
|
|
except KeyError:
|
|
return jsonify({'message': 'course_id must be specified'}), 401
|
|
quiz_rows: list[Quiz] = db.session.execute(select(Quiz).where(
|
|
and_(Quiz.creatorUserID == g.current_user.id, Quiz.creatorHasAttempted == False)
|
|
)).scalars()
|
|
data: list = []
|
|
for quiz_row in quiz_rows:
|
|
data.append(
|
|
{
|
|
'id': quiz_row.id,
|
|
'isActive': quiz_row.isActive,
|
|
'creationDate': quiz_row.creationDate,
|
|
'quizAnswers': quiz_row.quizAnswers,
|
|
'quizQuestion': quiz_row.quizQuestion,
|
|
'course': {
|
|
'id': quiz_row.course.id,
|
|
'name': quiz_row.course.name,
|
|
'description': quiz_row.course.description
|
|
},
|
|
'creator': {
|
|
'id': quiz_row.creatorUserID,
|
|
'firstName': quiz_row.creatorUser.firstName,
|
|
'lastName': quiz_row.creatorUser.lastName,
|
|
'username': quiz_row.creatorUser.username,
|
|
'pfpFilename': url_for('send_file', filename=quiz_row.creatorUser.pfpFilename)
|
|
}
|
|
}
|
|
)
|
|
return jsonify({
|
|
'count': len(data),
|
|
'data': data
|
|
}), 200
|
|
|
|
|
|
@quiz.route('/get/allComplete')
|
|
@auth_required()
|
|
def get_complete_quiz():
|
|
try:
|
|
course_id: uuid.UUID = uuid.UUID(request.form['course_id'])
|
|
except KeyError:
|
|
return jsonify({'message': 'course_id must be specified'}), 401
|
|
quiz_attempts: list[QuizAttempt] = db.session.execute(
|
|
select(QuizAttempt).where(and_(
|
|
QuizAttempt.userID == g.current_user.id,
|
|
Course.id == course_id
|
|
))).scalars() # IF THIS DOES NOT WORK, ADD COURSE IF TO QUIZ_ATTEMPT TABLE ITSELF
|
|
completes: list = []
|
|
for attempt in quiz_attempts:
|
|
quiz_row: Quiz = attempt.quiz
|
|
completes.append(
|
|
{
|
|
'id': attempt.id,
|
|
'quizID': quiz_row.id,
|
|
'isActive': quiz_row.isActive,
|
|
'creationDate': quiz_row.creationDate,
|
|
'quizAnswers': quiz_row.quizAnswers,
|
|
'quizQuestion': quiz_row.quizQuestion,
|
|
'userAnswer': attempt.userAnswer,
|
|
'quizCorrectAnswer': quiz_row.quizCorrectAnswer,
|
|
'isCorrect': attempt.isCorrect,
|
|
'course': {
|
|
'id': quiz_row.course.id,
|
|
'name': quiz_row.course.name,
|
|
'description': quiz_row.course.description
|
|
},
|
|
'creator': {
|
|
'id': quiz_row.creatorUserID,
|
|
'firstName': quiz_row.creatorUser.firstName,
|
|
'lastName': quiz_row.creatorUser.lastName,
|
|
'username': quiz_row.creatorUser.username,
|
|
'pfpFilename': url_for('send_file', filename=quiz_row.creatorUser.pfpFilename)
|
|
}
|
|
}
|
|
)
|
|
return jsonify({
|
|
'count': len(completes),
|
|
'data': completes
|
|
}), 200
|
|
|
|
|
|
@quiz.route('/submit',methods=['POST'])
|
|
@auth_required()
|
|
def submit_quiz():
|
|
try:
|
|
answer: str = request.form['answer'].strip()
|
|
quiz_id: uuid.UUID = uuid.UUID(request.form['quiz_id'])
|
|
except KeyError:
|
|
return jsonify({'message': 'course_id and answer must be specified'}), 401
|
|
quiz_already_attempted: QuizAttempt = db.session.execute(select(QuizAttempt).where(
|
|
and_(QuizAttempt.quizID == quiz_id, QuizAttempt.userID == g.current_user.id )
|
|
)).scalar()
|
|
if quiz_already_attempted:
|
|
return jsonify({'message': 'Already attempted this quiz'}), 401
|
|
quiz_row: Quiz = db.session.execute(select(Quiz).where(Quiz.id == quiz_id)).scalar()
|
|
if not quiz_row:
|
|
return jsonify({'message': 'Quiz does not exist'}), 404
|
|
valid_answers: list = json.loads(quiz_row.quizAnswers)
|
|
is_correct: bool = False
|
|
if answer not in valid_answers:
|
|
return jsonify({'message': 'No such choice of answer given'}), 404
|
|
if answer == quiz_row.quizCorrectAnswer:
|
|
is_correct = True
|
|
new_attempt: QuizAttempt = QuizAttempt(
|
|
userID=g.current_user.id,
|
|
user=g.current_user,
|
|
quizID=quiz_id,
|
|
quiz=quiz_row,
|
|
userAnswer=answer,
|
|
isCorrect=int(is_correct)
|
|
)
|
|
db.session.add(new_attempt)
|
|
|
|
if quiz_row.creatorUser.id == g.current_user.id:
|
|
quiz_row.creatorHasAttempted = True
|
|
|
|
db.session.commit()
|
|
return jsonify({
|
|
'message': 'Answer submitted',
|
|
'isCorrect': is_correct,
|
|
'attemptID': new_attempt.id,
|
|
'quizID': quiz_row.id,
|
|
'quizAnswers': quiz_row.quizAnswers,
|
|
'quizQuestion': quiz_row.quizQuestion,
|
|
'quizCorrectAnswer': quiz_row.quizCorrectAnswer,
|
|
'userAnswer': answer
|
|
})
|
|
|
|
@quiz.route('/quizData')
|
|
@auth_required()
|
|
def get_quiz_info():
|
|
try:
|
|
quiz_id: uuid.UUID = uuid.UUID(request.args['quiz_id'])
|
|
except KeyError:
|
|
return jsonify({'message': 'quiz_id must be specified'}), 401
|
|
quiz_row: Quiz = db.session.execute(select(Quiz).where(Quiz.id == quiz_id)).scalar()
|
|
if not quiz_row:
|
|
return jsonify({'message': 'Quiz does not exist'}), 404
|
|
return jsonify({
|
|
'id': quiz_row.id,
|
|
'isActive': quiz_row.isActive,
|
|
'creationDate': quiz_row.creationDate,
|
|
'quizAnswers': quiz_row.quizAnswers,
|
|
'quizQuestion': quiz_row.quizQuestion,
|
|
'course': {
|
|
'id': quiz_row.course.id,
|
|
'name': quiz_row.course.name,
|
|
'description': quiz_row.course.description
|
|
},
|
|
'creator': {
|
|
'id': quiz_row.creatorUserID,
|
|
'firstName': quiz_row.creatorUser.firstName,
|
|
'lastName': quiz_row.creatorUser.lastName,
|
|
'username': quiz_row.creatorUser.username,
|
|
'pfpFilename': url_for('send_file', filename=quiz_row.creatorUser.pfpFilename)
|
|
}
|
|
}), 200 |