|
import gradio as gr |
|
import random |
|
import string |
|
import time |
|
from collections import defaultdict |
|
|
|
def generate_student_id(): |
|
return ''.join(random.choices(string.ascii_letters + string.digits, k=12)) |
|
|
|
def update_student_state(students, class_id, student_id, color): |
|
if class_id not in students: |
|
students[class_id] = {} |
|
students[class_id][student_id] = {"color": color} |
|
return students, f"Status updated to {color}" |
|
|
|
def submit_question(questions, class_id, student_id, question): |
|
if class_id not in questions: |
|
questions[class_id] = [] |
|
questions[class_id].append({"student_id": student_id, "question": question}) |
|
return questions, "Question submitted successfully" |
|
|
|
def get_class_stats(students, questions, class_id): |
|
if class_id not in students: |
|
return "No data available for this class." |
|
|
|
class_students = students[class_id] |
|
total_students = len(class_students) |
|
active_students = sum(1 for s in class_students.values() if s["color"] != "inactive") |
|
color_counts = {"green": 0, "yellow": 0, "red": 0} |
|
|
|
for student in class_students.values(): |
|
if student["color"] in color_counts: |
|
color_counts[student["color"]] += 1 |
|
|
|
color_fractions = {color: count / (active_students or 1) for color, count in color_counts.items()} |
|
|
|
color_chart = f""" |
|
<div style="width: 100%; height: 60px; display: flex;"> |
|
<div style="width: {color_fractions['red']*100}%; background-color: #ff6b6b;"></div> |
|
<div style="width: {color_fractions['yellow']*100}%; background-color: #feca57;"></div> |
|
<div style="width: {color_fractions['green']*100}%; background-color: #5cd85c;"></div> |
|
</div> |
|
""" |
|
stats_text = f""" |
|
<h3>Class Statistics</h3> |
|
<p>Total Students: {total_students}</p> |
|
<p>Active Students: {active_students}</p> |
|
""" |
|
questions_text = "<h3>Student Questions</h3>" |
|
for q in questions.get(class_id, []): |
|
questions_text += f"<p><strong>Student {q['student_id'][:4]}...</strong>: {q['question']}</p>" |
|
|
|
return f"{color_chart}<br>{stats_text}<br>{questions_text}" |
|
|
|
def create_interface(): |
|
with gr.Blocks(theme=gr.themes.Soft()) as app: |
|
students = gr.State({}) |
|
questions = gr.State({}) |
|
class_id = gr.State("") |
|
student_id = gr.State("") |
|
|
|
gr.Markdown("# Fastcups") |
|
|
|
with gr.Tab("Setup"): |
|
class_input = gr.Textbox(label="Enter Class ID") |
|
setup_button = gr.Button("Set Class ID") |
|
|
|
with gr.Tab("Student"): |
|
gr.Markdown("## Student Interface") |
|
status = gr.Textbox(label="Current Status", interactive=False) |
|
with gr.Row(): |
|
color_buttons = [ |
|
gr.Button("π’ I'm following along", variant="primary"), |
|
gr.Button("π‘ I need clarification", variant="secondary"), |
|
gr.Button("π΄ I'm lost, please stop", variant="stop") |
|
] |
|
question_input = gr.Textbox(label="Ask a question") |
|
submit_button = gr.Button("Submit Question") |
|
question_status = gr.Textbox(label="Question Status", interactive=False) |
|
|
|
with gr.Tab("Teacher"): |
|
gr.Markdown("## Teacher Interface") |
|
stats_html = gr.HTML() |
|
refresh_button = gr.Button("Refresh Stats") |
|
|
|
def setup_class(class_id_input): |
|
return class_id_input, generate_student_id() |
|
|
|
setup_button.click(setup_class, inputs=[class_input], outputs=[class_id, student_id]) |
|
|
|
for button, color in zip(color_buttons, ["green", "yellow", "red"]): |
|
button.click( |
|
update_student_state, |
|
inputs=[students, class_id, student_id, gr.State(color)], |
|
outputs=[students, status] |
|
) |
|
|
|
submit_button.click( |
|
submit_question, |
|
inputs=[questions, class_id, student_id, question_input], |
|
outputs=[questions, question_status] |
|
) |
|
|
|
refresh_button.click( |
|
get_class_stats, |
|
inputs=[students, questions, class_id], |
|
outputs=[stats_html] |
|
) |
|
|
|
|
|
gr.HTML('<script>setInterval(function(){ document.querySelector("button[aria-label=\'Refresh Stats\']").click(); }, 5000);</script>') |
|
|
|
return app |
|
|
|
if __name__ == "__main__": |
|
app = create_interface() |
|
app.launch() |