edi425-jeopardy / app.py
ProfSule's picture
Upload 2 files
e3f7d1b verified
import gradio as gr
from typing import Dict, List, Tuple
class JeopardyGame:
def __init__(self):
self.questions = {
"NGSS Standards": {
200: {
"question": "These are the three dimensions of learning in NGSS that work together to help children make sense of the world around us.",
"answer": "What are Disciplinary Core Ideas (DCIs), Science and Engineering Practices (SEPs), and Crosscutting Concepts (CCCs)?"
},
400: {
"question": "In the NGSS documents, this color represents Science and Engineering Practices, while orange represents Disciplinary Core Ideas.",
"answer": "What is blue?"
},
600: {
"question": "These standards are measurable and observable, providing the learning goals for what children should understand and be able to do.",
"answer": "What are performance expectations?"
},
800: {
"question": "These ideas, represented in green, are not specific to any one discipline but cut across all of them.",
"answer": "What are crosscutting concepts?"
},
1000: {
"question": "The performance expectations are written using this format: Grade-DCI-Number, such as 2-LS2-1, where LS refers to this specific Disciplinary Core Idea.",
"answer": "What is Life Sciences?"
}
},
"EDI425/525 Trivia": {
200: {
"question": "This member of our class, who created the jeopardy game, keeps giving you assignments.",
"answer": "Who is Sule/Dr. Aksoy?"
},
400: {
"question": "This first assignment required you to reflect on your personal experiences with science in and out of school.",
"answer": "What is a science autobiography?"
},
600: {
"question": "This major assignment involved creating a detailed plan for engaging your children in scientific discourse.",
"answer": "What is Science Talk Plan?"
},
800: {
"question": "This activity engaged you in sensemaking while exploring light phenomena in the dark room.",
"answer": "What is the colored shadows demo?"
},
1000: {
"question": "This short practice helps us develop a road map for a project-based science learning unit.",
"answer": "What is creating a driving question board?"
}
},
"SUNY Brockport": {
200: {
"question": "This online learning management system is used for submitting assignments and accessing course materials.",
"answer": "What is Brightspace?"
},
400: {
"question": "This is the official mascot of SUNY Brockport's athletic teams.",
"answer": "Who is Ellsworth the Golden Eagle?"
},
600: {
"question": "Brockport's campus sits on mile 288 of this historic waterway.",
"answer": "What is the Erie Canal?"
},
800: {
"question": "This place in Drake Memorial Library serves not artisanal but hot and necessary brew.",
"answer": "What is Pages Cafe?"
},
1000: {
"question": "This is the oldest building on the main campus, built in 1941.",
"answer": "What is Hartwell Hall?"
}
}
}
self.used_questions = set()
self.scores = {"Group 1": 0, "Group 2": 0, "Group 3": 0, "Group 4": 0}
self.current_question = None
self.current_value = 0
self.question_answered = False
def get_board_state(self) -> str:
"""Create the current board state as an HTML table"""
html = '<table style="width:100%; text-align:center; border-collapse: collapse;">'
html += '<tr style="background-color: #1e3a8a; color: white; font-weight: bold;">'
# Header row with categories
for category in self.questions.keys():
html += f'<th style="padding: 15px; border: 2px solid white;">{category}</th>'
html += '</tr>'
# Value rows
for value in [200, 400, 600, 800, 1000]:
html += '<tr>'
for category in self.questions.keys():
key = f"{category}-{value}"
if key in self.used_questions:
html += '<td style="padding: 20px; border: 2px solid #ccc; background-color: #e0e0e0; color: #999;">USED</td>'
else:
html += f'<td style="padding: 20px; border: 2px solid #ccc; background-color: #3b82f6; color: white; font-weight: bold; font-size: 1.2em;">${value}</td>'
html += '</tr>'
html += '</table>'
return html
def select_question(self, category: str, value: int) -> Tuple[str, str, str]:
"""Select a question and mark it as used"""
if not category or not value:
return "Please select both a category and value.", self.get_board_state(), self.get_scores()
key = f"{category}-{value}"
if key in self.used_questions:
return "This question has already been selected! Choose another.", self.get_board_state(), self.get_scores()
self.used_questions.add(key)
self.current_question = self.questions[category][value]
self.current_value = value
self.question_answered = False
question_text = f"### {category} for ${value}\n\n**{self.current_question['question']}**"
return question_text, self.get_board_state(), self.get_scores()
def check_answer(self, group: str, answer: str) -> Tuple[str, str, str]:
"""Check if the answer is correct and update scores"""
if not self.current_question:
return "Please select a question first!", self.get_board_state(), self.get_scores()
if self.question_answered:
return "This question has already been answered!", self.get_board_state(), self.get_scores()
if not answer or answer.strip() == "":
return "Please enter an answer!", self.get_board_state(), self.get_scores()
correct_answer = self.current_question['answer'].lower()
submitted_answer = answer.lower().strip()
# Extract key terms from the correct answer
key_terms = correct_answer.replace("what is", "").replace("what are", "").replace("who is", "").replace("?", "")
key_terms = key_terms.replace(",", "").replace(".", "").strip()
# Special handling for different types of answers
is_correct = False
# Check for NGSS terms
if "dci" in key_terms or "sep" in key_terms:
matches = 0
if "dci" in submitted_answer or "disciplinary core" in submitted_answer:
matches += 1
if "sep" in submitted_answer or "science and engineering" in submitted_answer:
matches += 1
if "ccc" in submitted_answer or "crosscutting" in submitted_answer:
matches += 1
is_correct = matches >= 2
# Check for name questions
elif "sule" in key_terms or "aksoy" in key_terms:
is_correct = "sule" in submitted_answer or "aksoy" in submitted_answer or "dr" in submitted_answer
# Check for answers with alternatives
elif "ellsworth" in key_terms or "golden eagle" in key_terms:
is_correct = "ellsworth" in submitted_answer or "golden eagle" in submitted_answer or "eagle" in submitted_answer
# Default checking
else:
important_words = [word for word in key_terms.split() if len(word) > 3]
if important_words:
matches = sum(1 for word in important_words if word in submitted_answer)
is_correct = matches >= max(1, len(important_words) * 0.5)
else:
is_correct = key_terms in submitted_answer
if is_correct:
self.scores[group] += self.current_value
result = f"βœ… **CORRECT!** {group} earns ${self.current_value}!\n\nCorrect answer: {self.current_question['answer']}"
else:
self.scores[group] -= self.current_value
result = f"❌ **INCORRECT!** {group} loses ${self.current_value}.\n\nCorrect answer: {self.current_question['answer']}"
self.question_answered = True
return result, self.get_board_state(), self.get_scores()
def get_scores(self) -> str:
"""Return current scores and microteaching order"""
sorted_scores = sorted(self.scores.items(), key=lambda x: x[1], reverse=True)
scores_text = "## πŸ† Current Standings\n\n"
scores_text += "### Microteaching Schedule:\n"
for i, (group, score) in enumerate(sorted_scores):
if i < 2:
scores_text += f"**Week 1:** {group} (${score})\n"
else:
scores_text += f"**Week 2:** {group} (${score})\n"
scores_text += "\n### Scores:\n"
for i, (group, score) in enumerate(sorted_scores, 1):
emoji = "πŸ₯‡" if i == 1 else "πŸ₯ˆ" if i == 2 else "πŸ₯‰" if i == 3 else "πŸ“Š"
scores_text += f"{emoji} {group}: ${score}\n"
return scores_text
def reset_game(self):
"""Reset the entire game"""
self.used_questions.clear()
self.scores = {"Group 1": 0, "Group 2": 0, "Group 3": 0, "Group 4": 0}
self.current_question = None
self.current_value = 0
self.question_answered = False
return "Game has been reset!", self.get_board_state(), self.get_scores()
# Initialize game
game = JeopardyGame()
# Create interface
with gr.Blocks(title="EDI425/525 Jeopardy") as demo:
gr.Markdown("# πŸŽ“ EDI425/525 Classroom Jeopardy\n### Determine your microteaching order through friendly competition!")
with gr.Row():
with gr.Column(scale=3):
gr.Markdown("## Game Board")
board_display = gr.HTML(value=game.get_board_state())
gr.Markdown("### Select a Question:")
with gr.Row():
category_select = gr.Dropdown(
choices=list(game.questions.keys()),
label="Category",
value="NGSS Standards"
)
value_select = gr.Dropdown(
choices=[200, 400, 600, 800, 1000],
label="Value",
value=200
)
select_btn = gr.Button("Select Question", variant="primary")
question_display = gr.Markdown(value="### Ready to play!\n\nSelect a category and value above.")
with gr.Column(scale=2):
scores_display = gr.Markdown(value=game.get_scores())
gr.Markdown("## Submit Answer")
group_select = gr.Dropdown(
choices=["Group 1", "Group 2", "Group 3", "Group 4"],
label="Your Group",
value="Group 1"
)
answer_input = gr.Textbox(
label="Your Answer",
placeholder="Remember: 'What is...?' or 'Who is...?'",
lines=2
)
submit_btn = gr.Button("Submit Answer", variant="primary")
result_display = gr.Markdown(value="")
reset_btn = gr.Button("Reset Game", variant="stop")
# Event handlers
select_btn.click(
fn=lambda cat, val: game.select_question(cat, val),
inputs=[category_select, value_select],
outputs=[question_display, board_display, scores_display]
)
submit_btn.click(
fn=lambda g, a: game.check_answer(g, a),
inputs=[group_select, answer_input],
outputs=[result_display, board_display, scores_display]
)
reset_btn.click(
fn=lambda: game.reset_game(),
outputs=[result_display, board_display, scores_display]
)
# Launch
if __name__ == "__main__":
demo.launch()