Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,48 +1,159 @@
|
|
1 |
-
import requests
|
2 |
import streamlit as st
|
3 |
-
|
4 |
import os
|
|
|
|
|
5 |
|
6 |
-
#
|
7 |
-
|
|
|
8 |
|
9 |
-
#
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
13 |
|
|
|
|
|
|
|
|
|
14 |
|
15 |
-
#
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
else:
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
st.
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
import os
|
4 |
+
import logging
|
5 |
+
from src.SecondModule.module2 import SimilarQuestionGenerator, generate_similar_question
|
6 |
|
7 |
+
# ๋ก๊น
์ค์
|
8 |
+
logging.basicConfig(level=logging.INFO)
|
9 |
+
logger = logging.getLogger(__name__)
|
10 |
|
11 |
+
# Streamlit ํ์ด์ง ๊ธฐ๋ณธ ์ค์
|
12 |
+
st.set_page_config(
|
13 |
+
page_title="MisconcepTutor",
|
14 |
+
layout="wide",
|
15 |
+
initial_sidebar_state="expanded"
|
16 |
+
)
|
17 |
|
18 |
+
# ๊ฒฝ๋ก ์ค์
|
19 |
+
base_path = os.path.dirname(os.path.abspath(__file__))
|
20 |
+
data_path = os.path.join(base_path, 'Data')
|
21 |
+
misconception_csv_path = os.path.join(data_path, 'misconception_mapping.csv')
|
22 |
|
23 |
+
# ์ธ์
์ํ ์ด๊ธฐํ
|
24 |
+
if 'initialized' not in st.session_state:
|
25 |
+
st.session_state.initialized = True
|
26 |
+
st.session_state.wrong_questions = []
|
27 |
+
st.session_state.misconceptions = []
|
28 |
+
st.session_state.current_question_index = 0
|
29 |
+
st.session_state.generated_questions = []
|
30 |
+
st.session_state.current_step = 'initial'
|
31 |
+
st.session_state.selected_wrong_answer = None
|
32 |
+
st.session_state.questions = []
|
33 |
+
logger.info("Session state initialized")
|
34 |
+
|
35 |
+
# ๋ฌธ์ ์์ฑ๊ธฐ ์ด๊ธฐํ
|
36 |
+
@st.cache_resource
|
37 |
+
def load_question_generator():
|
38 |
+
if not os.path.exists(misconception_csv_path):
|
39 |
+
st.error(f"CSV ํ์ผ์ด ์กด์ฌํ์ง ์์ต๋๋ค: {misconception_csv_path}")
|
40 |
+
raise FileNotFoundError(f"CSV ํ์ผ์ด ์กด์ฌํ์ง ์์ต๋๋ค: {misconception_csv_path}")
|
41 |
+
return SimilarQuestionGenerator(misconception_csv_path=misconception_csv_path)
|
42 |
+
|
43 |
+
# CSV ๋ฐ์ดํฐ ๋ก๋
|
44 |
+
@st.cache_data
|
45 |
+
def load_data(data_file='/train.csv'):
|
46 |
+
try:
|
47 |
+
file_path = os.path.join(data_path, data_file.lstrip('/'))
|
48 |
+
df = pd.read_csv(file_path)
|
49 |
+
logger.info(f"Data loaded successfully from {file_path}")
|
50 |
+
return df
|
51 |
+
except FileNotFoundError:
|
52 |
+
st.error(f"ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค: {data_file}")
|
53 |
+
logger.error(f"File not found: {data_file}")
|
54 |
+
return None
|
55 |
+
|
56 |
+
# ํด์ฆ ์์
|
57 |
+
def start_quiz():
|
58 |
+
df = load_data()
|
59 |
+
if df is None or df.empty:
|
60 |
+
st.error("๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค. ๋ฐ์ดํฐ์
์ ํ์ธํด์ฃผ์ธ์.")
|
61 |
+
return
|
62 |
+
st.session_state.questions = df.sample(n=10, random_state=42)
|
63 |
+
st.session_state.current_step = 'quiz'
|
64 |
+
st.session_state.current_question_index = 0
|
65 |
+
st.session_state.wrong_questions = []
|
66 |
+
st.session_state.misconceptions = []
|
67 |
+
st.session_state.generated_questions = []
|
68 |
+
logger.info("Quiz started")
|
69 |
+
|
70 |
+
# ๋ต๋ณ ์ฒ๋ฆฌ
|
71 |
+
def handle_answer(answer, current_q):
|
72 |
+
if answer != current_q['CorrectAnswer']:
|
73 |
+
wrong_q_dict = current_q.to_dict()
|
74 |
+
st.session_state.wrong_questions.append(wrong_q_dict)
|
75 |
+
st.session_state.selected_wrong_answer = answer
|
76 |
+
|
77 |
+
misconception_key = f'Misconception{answer}Id'
|
78 |
+
misconception_id = current_q.get(misconception_key)
|
79 |
+
st.session_state.misconceptions.append(misconception_id)
|
80 |
|
81 |
+
st.session_state.current_question_index += 1
|
82 |
+
if st.session_state.current_question_index >= 10:
|
83 |
+
st.session_state.current_step = 'review'
|
84 |
+
|
85 |
+
# ๋ฉ์ธ ์ ํ๋ฆฌ์ผ์ด์
๋ก์ง
|
86 |
+
def main():
|
87 |
+
st.title("MisconcepTutor")
|
88 |
+
generator = load_question_generator()
|
89 |
+
|
90 |
+
if st.session_state.current_step == 'initial':
|
91 |
+
st.write("#### ํ์ต์ ์์ํ๊ฒ ์ต๋๋ค. 10๊ฐ์ ๋ฌธ์ ๋ฅผ ํ์ด๋ณผ๊น์?")
|
92 |
+
if st.button("ํ์ต ์์", key="start_quiz"):
|
93 |
+
start_quiz()
|
94 |
+
st.rerun()
|
95 |
+
|
96 |
+
elif st.session_state.current_step == 'quiz':
|
97 |
+
current_q = st.session_state.questions.iloc[st.session_state.current_question_index]
|
98 |
+
progress = st.session_state.current_question_index / 10
|
99 |
+
st.progress(progress)
|
100 |
+
st.write(f"### ๋ฌธ์ {st.session_state.current_question_index + 1}/10")
|
101 |
+
st.markdown("---")
|
102 |
+
st.write(current_q['QuestionText'])
|
103 |
+
|
104 |
+
col1, col2 = st.columns(2)
|
105 |
+
with col1:
|
106 |
+
if st.button(f"A) {current_q['AnswerAText']}", key="A"):
|
107 |
+
handle_answer('A', current_q)
|
108 |
+
st.rerun()
|
109 |
+
if st.button(f"C) {current_q['AnswerCText']}", key="C"):
|
110 |
+
handle_answer('C', current_q)
|
111 |
+
st.rerun()
|
112 |
+
with col2:
|
113 |
+
if st.button(f"B) {current_q['AnswerBText']}", key="B"):
|
114 |
+
handle_answer('B', current_q)
|
115 |
+
st.rerun()
|
116 |
+
if st.button(f"D) {current_q['AnswerDText']}", key="D"):
|
117 |
+
handle_answer('D', current_q)
|
118 |
+
st.rerun()
|
119 |
+
|
120 |
+
elif st.session_state.current_step == 'review':
|
121 |
+
st.write("### ํ์ต ๊ฒฐ๊ณผ")
|
122 |
+
col1, col2, col3 = st.columns(3)
|
123 |
+
col1.metric("์ด ๋ฌธ์ ์", 10)
|
124 |
+
col2.metric("๋ง์ ๋ฌธ์ ", 10 - len(st.session_state.wrong_questions))
|
125 |
+
col3.metric("ํ๋ฆฐ ๋ฌธ์ ", len(st.session_state.wrong_questions))
|
126 |
+
|
127 |
+
if len(st.session_state.wrong_questions) == 0:
|
128 |
+
st.balloons()
|
129 |
+
st.success("๐ ๋ชจ๋ ๋ฌธ์ ๋ฅผ ๋ง์ถ์
จ์ต๋๋ค!")
|
130 |
+
elif len(st.session_state.wrong_questions) <= 3:
|
131 |
+
st.success("์ ํ์
จ์ด์! ์กฐ๊ธ๋ง ๋ ์ฐ์ตํ๋ฉด ์๋ฒฝํด์ง ๊ฑฐ์์!")
|
132 |
else:
|
133 |
+
st.info("์ฒ์ฒํ ๊ฐ๋
์ ๋ณต์ตํด ๋ณด์ธ์. ์ฐ์ตํ๋ฉด ๋์์ง ๊ฒ๋๋ค.")
|
134 |
+
|
135 |
+
if st.session_state.wrong_questions:
|
136 |
+
st.write("### โ๏ธ ํ๋ฆฐ ๋ฌธ์ ๋ถ์")
|
137 |
+
for i, (wrong_q, misconception_id) in enumerate(zip(
|
138 |
+
st.session_state.wrong_questions, st.session_state.misconceptions
|
139 |
+
)):
|
140 |
+
with st.expander(f"๐ ํ๋ฆฐ ๋ฌธ์ #{i + 1}"):
|
141 |
+
st.write(wrong_q['QuestionText'])
|
142 |
+
st.write(f"โ
์ ๋ต: {wrong_q['CorrectAnswer']}")
|
143 |
+
if misconception_id:
|
144 |
+
misconception_text = generator.get_misconception_text(misconception_id)
|
145 |
+
st.info(f"Misconception: {misconception_text}")
|
146 |
+
if st.button(f"๐ ์ ์ฌ ๋ฌธ์ ํ๊ธฐ #{i + 1}", key=f"retry_{i}"):
|
147 |
+
new_question = generate_similar_question(wrong_q, misconception_id, generator)
|
148 |
+
if new_question:
|
149 |
+
st.write("### ๐ฏ ์ ์ฌ ๋ฌธ์ ")
|
150 |
+
st.write(new_question['question'])
|
151 |
+
for choice, text in new_question['choices'].items():
|
152 |
+
st.write(f"{choice}) {text}")
|
153 |
+
st.write(f"โ
์ ๋ต: {new_question['correct']}")
|
154 |
+
st.write(f"๐ ํด์ค: {new_question['explanation']}")
|
155 |
+
else:
|
156 |
+
st.error("์ ์ฌ ๋ฌธ์ ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.")
|
157 |
+
|
158 |
+
if __name__ == "__main__":
|
159 |
+
main()
|