youngtsai commited on
Commit
ece8cff
·
1 Parent(s): d24724f

all_in_one_button = gr.Button("Fetch Data and Generate Graph")

Browse files
Files changed (1) hide show
  1. app.py +139 -28
app.py CHANGED
@@ -58,8 +58,20 @@ for element in elements:
58
  else: # It's an edge
59
  nx_graph.add_edge(element['data']['source'], element['data']['target'])
60
 
 
 
 
 
 
 
 
 
 
 
61
  # Function to generate the graph in hierarchical layout
62
- def needs_analysis():
 
 
63
  nt = Network(directed=True)
64
  nt.from_nx(nx_graph)
65
  nt.repulsion(node_distance=120, central_gravity=0.0, spring_length=100, spring_strength=0.05, damping=0.09)
@@ -80,17 +92,22 @@ def needs_analysis():
80
  }
81
  }
82
  """)
83
- html = nt.generate_html()
84
  # Replace single quotes with double quotes in HTML
85
- html = html.replace("'", "\"")
86
- return f"""<iframe style="width: 100%; height: 600px;margin:0 auto" name="result" allow="midi; geolocation; microphone; camera;
87
  display-capture; encrypted-media;" sandbox="allow-modals allow-forms
88
  allow-scripts allow-same-origin allow-popups
89
  allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
90
- allowpaymentrequest="" frameborder="0" srcdoc='{html}'></iframe>"""
 
 
 
91
 
 
92
 
93
- def query_metabase(username, password, class_code, card_id, user_id):
 
94
  try:
95
  # 获取会话令牌
96
  session_response = requests.post(
@@ -121,20 +138,75 @@ def query_metabase(username, password, class_code, card_id, user_id):
121
 
122
  # 使用提供的 card_id 查询 Metabase 卡片
123
  query_response = requests.post(
124
- f'https://metabase.cloud.junyiacademy.org/api/card/{card_id}/query/json',
125
  headers={
126
  'Content-Type': 'application/json',
127
  'X-Metabase-Session': session_token
128
  },
129
  json=request_payload
130
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
- # 打印响应状态码和内容
133
- print(f"Response status code: {query_response.status_code}")
134
- print(f"Response content: {query_response.text}")
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
 
 
 
 
 
 
 
 
 
 
136
  query_response.raise_for_status()
137
- return query_response.json()
 
 
 
 
 
 
138
  except requests.RequestException as e:
139
  print(f"Failed to query Metabase card: {str(e)}")
140
  return {"error": f"Failed to query Metabase card: {str(e)}"}
@@ -142,34 +214,73 @@ def query_metabase(username, password, class_code, card_id, user_id):
142
  print(f"Error: {str(e)}")
143
  return {"error": str(e)}
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  with gr.Blocks() as app:
146
  gr.Markdown("# Metabase Query and Visualization")
147
 
148
  with gr.Row():
149
  username = gr.Textbox(label="Metabase Username", value="purpleice9765@msn.com")
150
  password = gr.Textbox(label="Metabase Password", type="password", value=METABASE_PASSWORD)
 
 
 
 
151
 
152
- with gr.Row():
153
- class_code = gr.Textbox(label="Class Code", value="class2")
154
- card_id = gr.Textbox(label="Card ID", value="6267")
155
- user_id = gr.Textbox(label="User ID", value="stu26")
156
-
157
- result = gr.JSON(label="Query Result")
158
- graph_html = gr.HTML()
159
 
160
- query_button = gr.Button("Fetch Data")
161
- graph_btn = gr.Button("Generate Graph")
 
162
 
163
- query_button.click(
164
- fn=query_metabase,
165
- inputs=[username, password, class_code, card_id, user_id],
166
- outputs=result
167
- )
168
 
169
- graph_btn.click(
170
- needs_analysis,
171
- inputs=None,
 
 
 
 
 
 
 
 
172
  outputs=graph_html
173
  )
174
 
175
  app.launch()
 
 
58
  else: # It's an edge
59
  nx_graph.add_edge(element['data']['source'], element['data']['target'])
60
 
61
+ def update_node_colors(result_data):
62
+ color_mapping = {'1': 'green', '0': 'red', 'default': 'orange'}
63
+ for node in nx_graph.nodes:
64
+ if node in result_data:
65
+ score = str(result_data[node])
66
+ color = color_mapping.get(score, color_mapping['default'])
67
+ else:
68
+ color = color_mapping['default']
69
+ nx_graph.nodes[node]['color'] = color
70
+
71
  # Function to generate the graph in hierarchical layout
72
+ def needs_analysis(topic_result=None, exercise_quiz_result=None):
73
+ if topic_result:
74
+ update_node_colors(topic_result)
75
  nt = Network(directed=True)
76
  nt.from_nx(nx_graph)
77
  nt.repulsion(node_distance=120, central_gravity=0.0, spring_length=100, spring_strength=0.05, damping=0.09)
 
92
  }
93
  }
94
  """)
95
+ map_html = nt.generate_html()
96
  # Replace single quotes with double quotes in HTML
97
+ map_html = map_html.replace("'", "\"")
98
+ html = f"""<iframe style="width: 100%; height: 600px;margin:0 auto" name="result" allow="midi; geolocation; microphone; camera;
99
  display-capture; encrypted-media;" sandbox="allow-modals allow-forms
100
  allow-scripts allow-same-origin allow-popups
101
  allow-top-navigation-by-user-activation allow-downloads" allowfullscreen=""
102
+ allowpaymentrequest="" frameborder="0" srcdoc='{map_html}'></iframe>"""
103
+
104
+ topic_table = generate_html_table(topic_result, exercise_quiz_result)
105
+ html += f"<h2>Topic Table</h2>{topic_table}"
106
 
107
+ return html
108
 
109
+
110
+ def query_metabase_topic(username, password, class_code, topic_card_id, user_id):
111
  try:
112
  # 获取会话令牌
113
  session_response = requests.post(
 
138
 
139
  # 使用提供的 card_id 查询 Metabase 卡片
140
  query_response = requests.post(
141
+ f'https://metabase.cloud.junyiacademy.org/api/card/{topic_card_id}/query/json',
142
  headers={
143
  'Content-Type': 'application/json',
144
  'X-Metabase-Session': session_token
145
  },
146
  json=request_payload
147
  )
148
+
149
+ query_response.raise_for_status()
150
+
151
+ # filter class_code and user_id
152
+ query_response = query_response.json()
153
+ query_response = [item for item in query_response if item['class_code'] == class_code and item['user_id'] == user_id]
154
+
155
+ return query_response[0] if query_response else {}
156
+ except requests.RequestException as e:
157
+ print(f"Failed to query Metabase card: {str(e)}")
158
+ return {"error": f"Failed to query Metabase card: {str(e)}"}
159
+ except Exception as e:
160
+ print(f"Error: {str(e)}")
161
+ return {"error": str(e)}
162
+
163
+ def query_metabase_exercise_quiz(username, password, class_code, exercise_card_id, user_id):
164
+ try:
165
+ # 获取会话令牌
166
+ session_response = requests.post(
167
+ 'https://metabase.cloud.junyiacademy.org/api/session',
168
+ headers={'Content-Type': 'application/json'},
169
+ json={'username': username, 'password': password}
170
+ )
171
+ session_response.raise_for_status()
172
+ session_token = session_response.json()['id']
173
+ print(f"Session token: {session_token}")
174
 
175
+ # 打印请求信息
176
+ request_payload = {
177
+ "parameters": [
178
+ {
179
+ "type": "category",
180
+ "target": ["variable", ["template-tag", "class_code"]],
181
+ "value": class_code
182
+ },
183
+ {
184
+ "type": "category",
185
+ "target": ["variable", ["template-tag", "user_id"]],
186
+ "value": user_id
187
+ }
188
+ ]
189
+ }
190
+ print(f"Request payload: {json.dumps(request_payload, indent=2)}")
191
 
192
+ # 使用提供的 card_id 查询 Metabase 卡片
193
+ query_response = requests.post(
194
+ f'https://metabase.cloud.junyiacademy.org/api/card/{exercise_card_id}/query/json',
195
+ headers={
196
+ 'Content-Type': 'application/json',
197
+ 'X-Metabase-Session': session_token
198
+ },
199
+ json=request_payload
200
+ )
201
+
202
  query_response.raise_for_status()
203
+
204
+ # filter class_code and user_id
205
+ query_response = query_response.json()
206
+ print(f"query_response: {query_response}")
207
+ query_response = [item for item in query_response if item['class_code'] == class_code and item['user_id'] == user_id]
208
+
209
+ return query_response
210
  except requests.RequestException as e:
211
  print(f"Failed to query Metabase card: {str(e)}")
212
  return {"error": f"Failed to query Metabase card: {str(e)}"}
 
214
  print(f"Error: {str(e)}")
215
  return {"error": str(e)}
216
 
217
+ def generate_html_table(result_data, exercise_quiz_result):
218
+ color_mapping = {'1': 'green', '0': 'red', 'default': 'orange'}
219
+ table_html = """
220
+ <table style='width:100%; border: 1px solid black; border-collapse: collapse;'>
221
+ <tr><th>ID</th><th>Name</th><th>Color</th><th>Exercise Results</th></tr>
222
+ """
223
+
224
+ for node in nx_graph.nodes:
225
+ name = nx_graph.nodes[node].get('title', node)
226
+ if node in result_data:
227
+ score = str(result_data[node])
228
+ color = color_mapping.get(score, color_mapping['default'])
229
+ else:
230
+ color = color_mapping['default']
231
+
232
+ exercise_results = [
233
+ f"<li>Quiz ID: {quiz['quiz_id']}, Correct: {quiz['is_correct']}, Time Taken: {quiz['total_time_taken']}, Hint Used: {quiz['is_hint_used']}</li>"
234
+ for quiz in exercise_quiz_result
235
+ if quiz['exercise_title'] == name and quiz['user_id'] == result_data['user_id'] and quiz['class_code'] == result_data['class_code']
236
+ ]
237
+ exercise_results_html = '<ul>' + ''.join(exercise_results) + '</ul>'
238
+
239
+ row_id = f"row-{node}"
240
+
241
+ table_html += f"""
242
+ <tr>
243
+ <td><a href='#{row_id}-details'>{node}</a></td><td>{name}</td><td style='background-color: {color};'>{color}</td><td>{exercise_results_html}</td>
244
+ </tr>
245
+ """
246
+
247
+ table_html += "</table>"
248
+ return table_html
249
+
250
+
251
  with gr.Blocks() as app:
252
  gr.Markdown("# Metabase Query and Visualization")
253
 
254
  with gr.Row():
255
  username = gr.Textbox(label="Metabase Username", value="purpleice9765@msn.com")
256
  password = gr.Textbox(label="Metabase Password", type="password", value=METABASE_PASSWORD)
257
+ class_code = gr.Textbox(label="Class Code", value="CAFSR")
258
+ topic_card_id = gr.Textbox(label="Card ID", value="6267")
259
+ exercise_card_id = gr.Textbox(label="Card ID", value="6284")
260
+ user_id = gr.Textbox(label="User ID", value="emdob01")
261
 
262
+ all_in_one_button = gr.Button("Fetch Data and Generate Graph")
 
 
 
 
 
 
263
 
264
+ with gr.Accordion(open=False):
265
+ topic_result = gr.JSON(label="Query Result")
266
+ exercise_quiz_result = gr.JSON(label="Quiz Query Result")
267
 
268
+ with gr.Row():
269
+ graph_html = gr.HTML()
 
 
 
270
 
271
+ all_in_one_button.click(
272
+ fn=query_metabase_topic,
273
+ inputs=[username, password, class_code, topic_card_id, user_id],
274
+ outputs=topic_result
275
+ ).then(
276
+ fn=query_metabase_exercise_quiz,
277
+ inputs=[username, password, class_code, exercise_card_id, user_id],
278
+ outputs=exercise_quiz_result
279
+ ).then(
280
+ fn=needs_analysis,
281
+ inputs=[topic_result, exercise_quiz_result],
282
  outputs=graph_html
283
  )
284
 
285
  app.launch()
286
+