130 lines
5.0 KiB
Python
130 lines
5.0 KiB
Python
from pathlib import Path
|
|
import PyPDF2
|
|
from typing import Dict, List, Optional
|
|
from pydantic import BaseModel
|
|
from modules.pdf_utils import PDFUtils
|
|
|
|
class TestAnalysis(BaseModel):
|
|
overall_score: float
|
|
section_scores: Dict[str, float]
|
|
feedback: str
|
|
recommendations: List[str]
|
|
detailed_analysis: Optional[Dict] = None
|
|
|
|
class TestAnalyzer:
|
|
def __init__(self, api_key: str):
|
|
self.api_key = api_key
|
|
|
|
def extract_text_from_pdf(self, pdf_file: Path) -> str:
|
|
"""
|
|
Extract text content from a PDF file
|
|
"""
|
|
if not pdf_file.exists():
|
|
raise FileNotFoundError(f"PDF file not found: {pdf_file}")
|
|
|
|
text = ""
|
|
with open(pdf_file, 'rb') as file:
|
|
pdf_reader = PyPDF2.PdfReader(file)
|
|
for page in pdf_reader.pages:
|
|
text += page.extract_text() + "\n"
|
|
|
|
return text
|
|
|
|
def analyze_test(self, pdf_content: str, marks_data: Dict, mode: str = 'detailed') -> TestAnalysis:
|
|
"""
|
|
Analyze a test and generate feedback based on marks data
|
|
"""
|
|
# Calculate overall score
|
|
total_marks = sum(marks_data.values())
|
|
max_marks = len(marks_data) * 100 # Assuming each question is out of 100
|
|
overall_score = (total_marks / max_marks) * 100
|
|
|
|
# Calculate section scores (group by first part of question number)
|
|
section_scores = {}
|
|
for question, marks in marks_data.items():
|
|
section = question.split('.')[0]
|
|
if section not in section_scores:
|
|
section_scores[section] = []
|
|
section_scores[section].append(marks)
|
|
|
|
# Calculate average for each section
|
|
for section, marks in section_scores.items():
|
|
section_scores[section] = sum(marks) / len(marks)
|
|
|
|
# Generate feedback
|
|
feedback = self._generate_feedback(overall_score, section_scores)
|
|
|
|
# Generate recommendations
|
|
recommendations = self._generate_recommendations(section_scores)
|
|
|
|
# Create detailed analysis if requested
|
|
detailed_analysis = None
|
|
if mode == 'detailed':
|
|
detailed_analysis = {
|
|
'question_analysis': self._analyze_questions(pdf_content, marks_data),
|
|
'strengths': self._identify_strengths(section_scores),
|
|
'weaknesses': self._identify_weaknesses(section_scores)
|
|
}
|
|
|
|
return TestAnalysis(
|
|
overall_score=overall_score,
|
|
section_scores=section_scores,
|
|
feedback=feedback,
|
|
recommendations=recommendations,
|
|
detailed_analysis=detailed_analysis
|
|
)
|
|
|
|
def _generate_feedback(self, overall_score: float, section_scores: Dict[str, float]) -> str:
|
|
"""
|
|
Generate feedback based on overall score and section scores
|
|
"""
|
|
if overall_score >= 90:
|
|
return "Excellent performance! You have demonstrated a strong understanding of the material."
|
|
elif overall_score >= 80:
|
|
return "Very good performance. You have a solid grasp of most concepts."
|
|
elif overall_score >= 70:
|
|
return "Good performance. You understand the main concepts but could improve in some areas."
|
|
elif overall_score >= 60:
|
|
return "Satisfactory performance. You have a basic understanding but need to work on several areas."
|
|
else:
|
|
return "Needs improvement. Focus on understanding the fundamental concepts better."
|
|
|
|
def _generate_recommendations(self, section_scores: Dict[str, float]) -> List[str]:
|
|
"""
|
|
Generate recommendations based on section scores
|
|
"""
|
|
recommendations = []
|
|
for section, score in section_scores.items():
|
|
if score < 70:
|
|
recommendations.append(f"Focus on improving your understanding of Section {section}")
|
|
elif score < 80:
|
|
recommendations.append(f"Review Section {section} to strengthen your knowledge")
|
|
|
|
if not recommendations:
|
|
recommendations.append("Continue practicing to maintain your strong performance")
|
|
|
|
return recommendations
|
|
|
|
def _analyze_questions(self, pdf_content: str, marks_data: Dict) -> Dict:
|
|
"""
|
|
Analyze individual questions
|
|
"""
|
|
question_analysis = {}
|
|
for question, marks in marks_data.items():
|
|
question_analysis[question] = {
|
|
'score': marks,
|
|
'performance': 'excellent' if marks >= 90 else 'good' if marks >= 70 else 'needs_improvement'
|
|
}
|
|
return question_analysis
|
|
|
|
def _identify_strengths(self, section_scores: Dict[str, float]) -> List[str]:
|
|
"""
|
|
Identify strong sections
|
|
"""
|
|
return [f"Section {section}" for section, score in section_scores.items() if score >= 80]
|
|
|
|
def _identify_weaknesses(self, section_scores: Dict[str, float]) -> List[str]:
|
|
"""
|
|
Identify weak sections
|
|
"""
|
|
return [f"Section {section}" for section, score in section_scores.items() if score < 70] |