Repository navigation
Expand file tree
/
Copy pathmodels.py
More file actions
194 lines (163 loc) · 7.14 KB
/
Copy pathmodels.py
File metadata and controls
194 lines (163 loc) · 7.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum, Float, Boolean
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from database import Base
from passlib.context import CryptContext
import logging
import enum
from datetime import datetime
logger = logging.getLogger(__name__)
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
class ExamType(enum.Enum):
NTPC = "NTPC"
GROUP_D = "GROUP D"
JE = "JE"
SSC = "SSC"
CGL = "CGL"
class ExamStage(enum.Enum):
CBT1 = "CBT 1"
CBT2 = "CBT 2"
CBT3 = "CBT 3"
PET = "PET"
DV = "DV"
TIER_1 = "Tier 1"
TIER_2 = "Tier 2"
TIER_3 = "Tier 3"
TIER_4 = "Tier 4"
class Subject(enum.Enum):
GENERAL_AWARENESS = "General Awareness"
ARITHMETIC = "Arithmetic"
GENERAL_INTELLIGENCE = "General Intelligence & Reasoning"
BASIC_SCIENCE = "Basic Science & Engineering"
TECHNICAL_ABILITIES = "Technical Abilities"
REASONING = "Reasoning"
LOGICAL_REASONING = "Logical Reasoning"
GENERAL_SCIENCE = "General Science"
MATHEMATICS = "Mathematics"
SCIENCE = "Science"
CURRENT_AFFAIRS = "Current Affairs"
HISTORY = "History"
GEOGRAPHY = "Geography"
POLITY = "Polity"
BIOLOGY = "Biology"
CHEMISTRY = "Chemistry"
INDIAN_CULTURE = "Indian Culture"
ENVIRONMENT = "Environment"
COMPUTER = "Computer"
RAILWAY_AWARENESS = "Railway Awareness"
INTERNATIONAL_AFFAIRS = "International Affairs"
BANKING = "Banking"
SCIENCE_AND_TECH = "Science and Tech"
PHYSICS = "Physics"
ENGLISH_GRAMMAR = "English Grammar"
class DifficultyLevel(enum.Enum):
EASY = "Easy"
MODERATE = "Moderate"
HARD = "Hard"
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True, nullable=False)
username = Column(String, unique=True, index=True, nullable=False)
hashed_password = Column(String, nullable=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
def set_password(self, password: str):
"""Hash and set the user's password"""
try:
if not password:
raise ValueError("Password cannot be empty")
if len(password) < 6:
raise ValueError("Password must be at least 6 characters long")
self.hashed_password = pwd_context.hash(password)
logger.info("Password hashed successfully")
except Exception as e:
logger.error(f"Error hashing password: {str(e)}")
raise ValueError(f"Error hashing password: {str(e)}")
def verify_password(self, password: str) -> bool:
"""Verify the user's password"""
try:
if not password or not self.hashed_password:
logger.warning("Password or hashed_password is empty")
return False
is_valid = pwd_context.verify(password, self.hashed_password)
if not is_valid:
logger.warning("Invalid password")
return is_valid
except Exception as e:
logger.error(f"Error verifying password: {str(e)}")
return False
class Question(Base):
__tablename__ = "questions"
id = Column(Integer, primary_key=True, index=True)
question_text = Column(Text, nullable=False)
option_a = Column(Text, nullable=False)
option_b = Column(Text, nullable=False)
option_c = Column(Text, nullable=False)
option_d = Column(Text, nullable=False)
correct_answer = Column(String(1), nullable=False) # A, B, C, or D
explanation = Column(Text)
# Diagram/Image related fields
has_diagram = Column(Boolean, default=False)
diagram_description = Column(Text) # Description of the diagram for accessibility
# Metadata
year = Column(Integer, nullable=False)
exam_type = Column(Enum(ExamType), nullable=False)
exam_stage = Column(Enum(ExamStage), nullable=False)
subject = Column(Enum(Subject), nullable=False)
topic = Column(String(100)) # Optional topic within subject
# Additional metadata
difficulty_level = Column(Enum(DifficultyLevel), default=DifficultyLevel.MODERATE)
source = Column(String(255)) # Source of the question (e.g., "Previous Year Paper", "Practice Set")
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
tags = relationship("QuestionTag", back_populates="question")
images = relationship("QuestionImage", back_populates="question")
class Tag(Base):
__tablename__ = "tags"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(50), unique=True, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
questions = relationship("QuestionTag", back_populates="tag")
class QuestionTag(Base):
__tablename__ = "question_tags"
question_id = Column(Integer, ForeignKey("questions.id"), primary_key=True)
tag_id = Column(Integer, ForeignKey("tags.id"), primary_key=True)
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
question = relationship("Question", back_populates="tags")
tag = relationship("Tag", back_populates="questions")
class UserProgress(Base):
__tablename__ = "user_progress"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, nullable=False) # Foreign key to your user table
question_id = Column(Integer, ForeignKey("questions.id"), nullable=False)
is_correct = Column(Integer, nullable=False) # 1 for correct, 0 for incorrect
time_taken = Column(Float) # Time taken to answer in seconds
attempted_at = Column(DateTime, default=datetime.utcnow)
# Relationships
question = relationship("Question")
class QuestionStatistics(Base):
__tablename__ = "question_statistics"
question_id = Column(Integer, ForeignKey("questions.id"), primary_key=True)
total_attempts = Column(Integer, default=0)
correct_attempts = Column(Integer, default=0)
average_time = Column(Float, default=0.0)
last_updated = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
question = relationship("Question")
class QuestionImage(Base):
__tablename__ = "question_images"
id = Column(Integer, primary_key=True, index=True)
question_id = Column(Integer, ForeignKey("questions.id"), nullable=False)
image_path = Column(String(255), nullable=False) # Path to the stored image
image_type = Column(String(50)) # Type of image (e.g., "diagram", "graph", "table")
caption = Column(Text) # Optional caption for the image
display_order = Column(Integer, default=0) # Order in which to display multiple images
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
question = relationship("Question", back_populates="images")