mirror of
https://github.com/th30d4y/OpenLearnX.git
synced 2026-05-26 19:26:33 +00:00
202 lines
6.6 KiB
Python
202 lines
6.6 KiB
Python
from flask import Blueprint, request, jsonify, current_app
|
|
import jwt
|
|
from datetime import datetime
|
|
import random
|
|
|
|
bp = Blueprint('test', __name__)
|
|
|
|
def get_user_from_token(token):
|
|
"""Extract user from JWT token"""
|
|
try:
|
|
payload = jwt.decode(
|
|
token,
|
|
current_app.config['SECRET_KEY'],
|
|
algorithms=['HS256']
|
|
)
|
|
return payload['user_id']
|
|
except:
|
|
return None
|
|
|
|
@bp.route('/start', methods=['POST'])
|
|
async def start_test():
|
|
"""Start a new test session"""
|
|
token = request.headers.get('Authorization', '').replace('Bearer ', '')
|
|
user_id = get_user_from_token(token)
|
|
|
|
if not user_id:
|
|
return jsonify({"error": "Authentication required"}), 401
|
|
|
|
data = request.get_json()
|
|
subject = data.get('subject', 'General')
|
|
|
|
mongo_service = current_app.config['MONGO_SERVICE']
|
|
|
|
# Create test session
|
|
session = await mongo_service.create_test_session(user_id, subject)
|
|
|
|
# Get first question
|
|
questions = await mongo_service.get_questions_by_difficulty(2, 1) # Start with medium
|
|
|
|
if not questions:
|
|
return jsonify({"error": "No questions available"}), 404
|
|
|
|
question = questions[0]
|
|
session['questions'].append(str(question['_id']))
|
|
await mongo_service.update_test_session(str(session['_id']), {
|
|
'questions': session['questions'],
|
|
'current_question': 0
|
|
})
|
|
|
|
return jsonify({
|
|
"session_id": str(session['_id']),
|
|
"question": {
|
|
"id": str(question['_id']),
|
|
"question": question['question'],
|
|
"options": question['options'],
|
|
"subject": question['subject'],
|
|
"difficulty": question['difficulty']
|
|
},
|
|
"question_number": 1,
|
|
"total_questions": 10
|
|
})
|
|
|
|
@bp.route('/answer', methods=['POST'])
|
|
async def submit_answer():
|
|
"""Submit answer and get feedback"""
|
|
token = request.headers.get('Authorization', '').replace('Bearer ', '')
|
|
user_id = get_user_from_token(token)
|
|
|
|
if not user_id:
|
|
return jsonify({"error": "Authentication required"}), 401
|
|
|
|
data = request.get_json()
|
|
session_id = data.get('session_id')
|
|
question_id = data.get('question_id')
|
|
answer = data.get('answer')
|
|
|
|
mongo_service = current_app.config['MONGO_SERVICE']
|
|
|
|
# Get session and question
|
|
session = await mongo_service.get_test_session(session_id)
|
|
question = await mongo_service.questions.find_one({"_id": question_id})
|
|
|
|
if not session or not question:
|
|
return jsonify({"error": "Invalid session or question"}), 404
|
|
|
|
# Check answer
|
|
is_correct = answer == question['correct_answer']
|
|
confidence_score = random.uniform(0.7, 0.95) if is_correct else random.uniform(0.1, 0.4)
|
|
|
|
# Update session
|
|
if 'answers' not in session:
|
|
session['answers'] = []
|
|
|
|
answer_record = {
|
|
'question_id': question_id,
|
|
'answer': answer,
|
|
'correct': is_correct,
|
|
'timestamp': datetime.utcnow()
|
|
}
|
|
session['answers'].append(answer_record)
|
|
|
|
# Calculate current score
|
|
correct_answers = sum(1 for a in session['answers'] if a['correct'])
|
|
current_score = correct_answers / len(session['answers'])
|
|
|
|
# Update difficulty for next question
|
|
current_difficulty = session.get('current_difficulty', 2)
|
|
if is_correct and confidence_score > 0.8:
|
|
current_difficulty = min(5, current_difficulty + 1)
|
|
elif not is_correct and confidence_score < 0.3:
|
|
current_difficulty = max(1, current_difficulty - 1)
|
|
|
|
await mongo_service.update_test_session(session_id, {
|
|
'answers': session['answers'],
|
|
'score': current_score,
|
|
'current_difficulty': current_difficulty
|
|
})
|
|
|
|
# Prepare response
|
|
feedback = {
|
|
"correct": is_correct,
|
|
"confidence_score": round(confidence_score, 2),
|
|
"explanation": question['explanation'],
|
|
"correct_answer": question['options'][question['correct_answer']],
|
|
"current_score": round(current_score * 100, 1),
|
|
"total_answered": len(session['answers'])
|
|
}
|
|
|
|
# Get next question if test not complete
|
|
next_question = None
|
|
if len(session['answers']) < 10: # 10 questions per test
|
|
questions = await mongo_service.get_questions_by_difficulty(current_difficulty, 1)
|
|
if questions:
|
|
next_q = questions[0]
|
|
session['questions'].append(str(next_q['_id']))
|
|
await mongo_service.update_test_session(session_id, {
|
|
'questions': session['questions']
|
|
})
|
|
|
|
next_question = {
|
|
"id": str(next_q['_id']),
|
|
"question": next_q['question'],
|
|
"options": next_q['options'],
|
|
"subject": next_q['subject'],
|
|
"difficulty": next_q['difficulty']
|
|
}
|
|
else:
|
|
# Test completed
|
|
await mongo_service.update_test_session(session_id, {
|
|
'completed': True,
|
|
'completed_at': datetime.utcnow()
|
|
})
|
|
|
|
# Update user stats
|
|
await mongo_service.users.update_one(
|
|
{"_id": user_id},
|
|
{
|
|
"$inc": {"total_tests": 1, "total_score": current_score},
|
|
"$set": {f"competency_scores.{session['subject']}": current_score}
|
|
}
|
|
)
|
|
|
|
response = {
|
|
"feedback": feedback,
|
|
"test_completed": len(session['answers']) >= 10
|
|
}
|
|
|
|
if next_question:
|
|
response['next_question'] = next_question
|
|
response['question_number'] = len(session['answers']) + 1
|
|
|
|
return jsonify(response)
|
|
|
|
@bp.route('/sessions/<user_id>', methods=['GET'])
|
|
async def get_user_sessions(user_id):
|
|
"""Get user's test sessions"""
|
|
token = request.headers.get('Authorization', '').replace('Bearer ', '')
|
|
token_user_id = get_user_from_token(token)
|
|
|
|
if not token_user_id or token_user_id != user_id:
|
|
return jsonify({"error": "Unauthorized"}), 403
|
|
|
|
mongo_service = current_app.config['MONGO_SERVICE']
|
|
|
|
sessions = await mongo_service.test_sessions.find(
|
|
{"user_id": user_id}
|
|
).sort("created_at", -1).limit(20).to_list(length=20)
|
|
|
|
# Format sessions for response
|
|
formatted_sessions = []
|
|
for session in sessions:
|
|
formatted_sessions.append({
|
|
"id": str(session['_id']),
|
|
"subject": session['subject'],
|
|
"score": session.get('score', 0),
|
|
"completed": session.get('completed', False),
|
|
"questions_answered": len(session.get('answers', [])),
|
|
"created_at": session['created_at'].isoformat()
|
|
})
|
|
|
|
return jsonify({"sessions": formatted_sessions})
|