File size: 4,424 Bytes
8f0fa74
 
 
 
 
 
 
 
08348fb
 
8f0fa74
 
08348fb
8f0fa74
 
 
 
 
 
08348fb
8f0fa74
08348fb
 
8f0fa74
08348fb
 
8f0fa74
08348fb
 
8f0fa74
 
08348fb
8f0fa74
 
 
 
 
 
08348fb
 
 
 
 
 
 
 
 
 
 
 
8f0fa74
 
08348fb
 
 
 
8f0fa74
08348fb
 
 
 
 
 
 
 
 
 
8f0fa74
 
 
08348fb
 
 
 
8f0fa74
08348fb
 
 
 
8f0fa74
 
08348fb
8f0fa74
 
 
 
 
 
 
 
 
 
 
 
 
08348fb
 
8f0fa74
 
08348fb
8f0fa74
 
 
 
 
08348fb
 
8f0fa74
08348fb
 
8f0fa74
08348fb
 
8f0fa74
08348fb
 
8f0fa74
08348fb
 
8f0fa74
 
08348fb
8f0fa74
 
 
08348fb
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
# ==============================================
# models.py (v2025-final)
# ==============================================

from sqlalchemy import Column, Integer, String, Text, Boolean, ForeignKey
from sqlalchemy.orm import relationship
import json

# db.py์—์„œ ์ƒ์„ฑํ•œ Base ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
from db import Base   

# ----------------------------------------------
# Question ๋ชจ๋ธ
# ----------------------------------------------
class Question(Base):
    __tablename__ = "questions"

    id = Column(Integer, primary_key=True, autoincrement=True)

    # ๋ฌธ์ œ ์งˆ๋ฌธ (๊ธฐ์กด ์ด๋ฆ„ ์œ ์ง€)
    stem = Column(Text, nullable=False)
    
    # ์ •๋‹ต (๋‹จ์ˆœ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€๊ฒฝ๋˜์–ด๋„ "A", "B" ๋˜๋Š” "1", "2" ๊ฐ™์€ ์ธ๋ฑ์Šค ํ‚ค ์ €์žฅ)
    answer = Column(String(255))
    
    # ํ•ด์„ค
    explanation = Column(Text)
    
    # ๋ฌธ์ œ ์œ ํ˜• (MCQ: ๊ฐ๊ด€์‹)
    question_type = Column(String(50), default="MCQ")

    # ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ
    page = Column(Integer)
    category = Column(String(100))
    subcategory = Column(String(100))
    code = Column(Text)
    source = Column(String(255))

    # -------------------------------------------------------
    # [๋ฐ์ดํ„ฐ ๊ตฌ์กฐ ๋ณ€๊ฒฝ ํ•ต์‹ฌ]
    # ๊ธฐ์กด: [{"key": "A", "text": "๋‚ด์šฉ"}]
    # ๋ณ€๊ฒฝ: ["๋‚ด์šฉ1", "๋‚ด์šฉ2", "๋‚ด์šฉ3"] (๋‹จ์ˆœ ๋ฌธ์ž์—ด ๋ฆฌ์ŠคํŠธ)
    # -------------------------------------------------------
    options_json = Column(Text, default="[]") 
    pairs = Column(Text, default="{}")
    sequence = Column(Text, default="[]")

    # -------------------------------------------------------
    # Helper Methods (JSON ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”)
    # -------------------------------------------------------

    def set_options(self, options):
        """
        ๋ฆฌ์ŠคํŠธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ JSON ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
        Input ์˜ˆ์‹œ: ["EC2", "S3", "Lambda"]
        """
        try:
            if options is None:
                self.options_json = "[]"
            elif isinstance(options, (list, dict)):
                # ensure_ascii=False: ํ•œ๊ธ€ ๊นจ์ง ๋ฐฉ์ง€
                self.options_json = json.dumps(options, ensure_ascii=False)
            else:
                # ๋ฌธ์ž์—ด๋กœ ๋“ค์–ด์˜ค๋ฉด ๊ทธ๋Œ€๋กœ ์ €์žฅ ์‹œ๋„ ํ˜น์€ ๋ฆฌ์ŠคํŠธ๋กœ ๊ฐ์‹ธ๊ธฐ
                self.options_json = json.dumps([str(options)], ensure_ascii=False)
        except Exception as e:
            print(f"Error setting options: {e}")
            self.options_json = "[]"

    def get_options(self):
        """
        ์ €์žฅ๋œ JSON ๋ฌธ์ž์—ด์„ ํŒŒ์ด์ฌ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
        Return ์˜ˆ์‹œ: ["EC2", "S3", "Lambda"]
        """
        try:
            if not self.options_json:
                return []
            return json.loads(self.options_json)
        except Exception:
            return []

    # (์ถ”๊ฐ€) pairs, sequence ์ฒ˜๋ฆฌ๋„ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์•ˆ์ •์„ฑ ํ™•๋ณด
    def get_pairs(self):
        try:
            return json.loads(self.pairs) if self.pairs else {}
        except:
            return {}

    def get_sequence(self):
        try:
            return json.loads(self.sequence) if self.sequence else []
        except:
            return []

    def __repr__(self):
        return f"<Question id={self.id} type={self.question_type} stem={self.stem[:20]}...>"


# ----------------------------------------------
# Attempt ๋ชจ๋ธ (์‚ฌ์šฉ์ž ํ’€์ด ๊ธฐ๋ก)
# ----------------------------------------------
class Attempt(Base):
    __tablename__ = "attempts"

    id = Column(Integer, primary_key=True, autoincrement=True)
    
    # ์‚ฌ์šฉ์ž ID (๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์ด ์—†๋‹ค๋ฉด guest ํ˜น์€ ๋ธŒ๋ผ์šฐ์ € ์ง€๋ฌธ ๋“ฑ ์‚ฌ์šฉ)
    user_id = Column(String(100), nullable=False, default="guest")
    
    # ๋ฌธ์ œ ID (FK)
    question_id = Column(Integer, ForeignKey("questions.id"))
    
    # ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๋‹ต (ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์ƒ์„ฑํ•œ Key: "A", "B", "1" ๋“ฑ)
    chosen = Column(String(10))
    
    # ์ •๋‹ต ์—ฌ๋ถ€
    correct = Column(Boolean, default=False)
    
    # ์˜ค๋‹ต ๋…ธํŠธ ์œ ํ˜• (wrong: ํ‹€๋ฆผ, bookmark: ์ค‘์š” ํ‘œ์‹œ ๋“ฑ)
    note_type = Column(String(20), default="wrong")

    # ๊ด€๊ณ„ ์„ค์ • (Attempt.question ์œผ๋กœ ๋ฌธ์ œ ์ •๋ณด ์ ‘๊ทผ ๊ฐ€๋Šฅ)
    question = relationship("Question", backref="attempts")

    def __repr__(self):
        return f"<Attempt q={self.question_id}, user={self.user_id}, correct={self.correct}>"