ProfSule commited on
Commit
232b230
Β·
verified Β·
1 Parent(s): ad8672d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +368 -120
app.py CHANGED
@@ -10,199 +10,431 @@ openai.api_key = "sk-or-v1-4ac3f2f731286b1fbbd02cdcf07c548cf9b9ff13c1ace9c333822
10
 
11
  class ScienceTalkGame:
12
  def __init__(self):
 
13
  self.reset_session()
14
 
15
  def reset_session(self):
16
  self.session = {
17
- "engagement_scores": {"Maya": 3, "Jamal": 4, "Aisha": 2, "Emma": 4},
18
  "teaching_points": 0,
19
  "choices_made": [],
20
  "current_scenario": "grade2_plants",
21
  "turn_count": 0
22
  }
 
23
 
24
- def get_current_scenario(self):
25
  return {
26
- "title": "🌱 Grade 2: Plant Investigation",
27
- "setup": """Your 2nd grade students are examining classroom plants. Some are healthy and green, others are yellow and droopy. You've gathered them for a science talk to explore what they notice.""",
28
- "learning_goals": "Students will observe plant differences, share ideas about plant needs, and connect to their cultural knowledge about plants.",
29
- "students": {
30
- "Maya": "Mexican-American, bilingual, has grandmother's gardening knowledge, sometimes shy about sharing in English",
31
- "Jamal": "African-American, urban background, very curious and asks lots of questions, eager to share",
32
- "Aisha": "Somali-American, thoughtful observer, needs processing time, connects to family farming knowledge",
33
- "Emma": "White suburban, enthusiastic about science, has science books at home, sometimes dominates discussions"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
  }
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  def generate_student_responses(self, teacher_input):
38
  scenario = self.get_current_scenario()
39
 
40
- # Create context-aware prompt based on engagement levels
41
- engagement_context = []
42
- for student, level in self.session["engagement_scores"].items():
43
- if level >= 4:
44
- engagement_context.append(f"{student} is highly engaged and eager to participate")
45
- elif level >= 3:
46
- engagement_context.append(f"{student} is moderately engaged")
47
- elif level >= 2:
48
- engagement_context.append(f"{student} is somewhat hesitant but paying attention")
 
 
49
  else:
50
- engagement_context.append(f"{student} is disengaged and may not participate")
 
 
 
51
 
52
- prompt = f"""You are role-playing four 2nd grade students (age 7-8) in a science discussion about plants. Respond as all four students would, showing their different personalities and backgrounds:
53
-
54
- **Maya**: Mexican-American, bilingual, her grandmother has a big garden with vegetables and herbs. Sometimes mixes Spanish words, a bit shy but has valuable knowledge to share.
55
-
56
- **Jamal**: African-American, lives in the city, very curious and energetic, asks lots of "what if" questions, eager to share observations.
57
-
58
- **Aisha**: Somali-American, family has farming background, thoughtful and observant, needs a moment to process before speaking, often makes connections to family experiences.
59
 
60
- **Emma**: White suburban, has lots of science books, enthusiastic but sometimes talks over others, uses formal science vocabulary.
61
 
62
- Current engagement levels: {', '.join(engagement_context)}
 
63
 
64
  The teacher just said: "{teacher_input}"
65
 
66
- Respond as each student would, showing their authentic 2nd grade thinking, cultural backgrounds, and current engagement levels. Format your response as:
67
 
68
- **Maya:** [her response]
69
- **Jamal:** [his response]
70
- **Aisha:** [her response]
71
- **Emma:** [her response]
72
 
73
- Make the responses feel natural for 7-year-olds discussing plants they're looking at."""
74
 
75
  try:
76
  response = openai.ChatCompletion.create(
77
  model="openai/gpt-3.5-turbo",
78
  messages=[{"role": "user", "content": prompt}],
79
  temperature=0.8,
80
- max_tokens=400
81
  )
82
  return response.choices[0].message.content
83
  except Exception as e:
84
  return f"**Error generating student responses:** {str(e)}\n\nPlease check your OpenRouter API key configuration."
85
 
86
- def generate_teaching_choices(self, context=""):
87
- """Generate contextual teaching choices based on the situation"""
 
 
 
88
  base_choices = [
89
- "🌟 Build on cultural knowledge: Ask Maya about her grandmother's gardening wisdom",
90
- "🀝 Create inclusive space: Make sure all students get a chance to share their thinking",
91
- "πŸ”¬ Promote investigation: Guide students to plan how they could test their ideas",
92
- "βš–οΈ Manage participation: Redirect from dominant voices to quieter students"
93
  ]
94
 
95
- # Add scenario-specific choices
96
- contextual_choices = [
97
- "🌱 Connect to home experiences: Ask what students notice about plants where they live",
98
- "πŸ’­ Support thinking time: Give students a moment to observe before sharing",
99
- "πŸ—£οΈ Encourage peer discussion: Have students share ideas with a partner first",
100
- "πŸ“Š Document observations: Help students record what they notice systematically"
101
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
- # Randomly select 4 choices to keep it fresh
104
- all_choices = base_choices + contextual_choices
105
- return random.sample(all_choices, 4)
106
 
107
  def assess_teaching_choice(self, choice_text):
108
- """Assess the pedagogical quality of the teaching choice"""
109
  feedback = ""
110
  points = 0
111
  engagement_impact = {}
112
 
113
- # Analyze choice for different pedagogical moves
114
  choice_lower = choice_text.lower()
 
115
 
116
- if "cultural" in choice_lower or "grandmother" in choice_lower:
117
- feedback = "🌟 Excellent! You're building on Maya's cultural assets. This validates her family knowledge and shows other students that diverse knowledge is valued in science."
 
118
  points = 3
119
- engagement_impact = {"Maya": 2, "Aisha": 1} # Cultural validation helps both students
120
-
121
- elif "inclusive" in choice_lower or "all students" in choice_lower:
 
 
 
122
  feedback = "βœ… Great equity move! Creating space for all voices helps build a classroom community where everyone's thinking is valued."
123
  points = 2
124
- engagement_impact = {"Aisha": 2, "Maya": 1} # Helps quieter students
125
-
126
- elif "investigation" in choice_lower or "test" in choice_lower:
127
- feedback = "πŸ”¬ Good scientific thinking! You're helping students engage in authentic science practices."
128
- points = 2
129
- engagement_impact = {"Jamal": 1, "Emma": 1} # Appeals to curious students
130
-
131
- elif "manage" in choice_lower or "redirect" in choice_lower:
132
- feedback = "βš–οΈ Important facilitation move! Managing participation ensures equitable discourse."
133
- points = 2
134
- engagement_impact = {"Emma": -1, "Aisha": 2, "Maya": 1} # Redistributes participation
135
-
136
- elif "home" in choice_lower or "where they live" in choice_lower:
137
- feedback = "🏠 Nice connection! Linking to students' lived experiences makes science relevant and accessible."
138
- points = 2
139
- engagement_impact = {"Maya": 1, "Aisha": 1, "Jamal": 1}
140
-
141
- elif "thinking time" in choice_lower or "moment to" in choice_lower:
142
- feedback = "πŸ’­ Thoughtful move! Wait time benefits all students, especially those who need processing time."
143
  points = 2
144
- engagement_impact = {"Aisha": 2, "Maya": 1}
145
-
146
- elif "peer discussion" in choice_lower or "partner" in choice_lower:
147
- feedback = "πŸ—£οΈ Smart strategy! Peer talk builds confidence before whole-group sharing."
 
 
 
148
  points = 2
149
- engagement_impact = {"Maya": 1, "Aisha": 1}
150
-
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  else:
152
  feedback = "Consider how this choice supports equitable participation and builds on student thinking."
153
  points = 1
154
- engagement_impact = {}
155
 
156
  return feedback, points, engagement_impact
157
 
158
  def update_engagement(self, impact_dict):
159
  """Update student engagement based on teaching choices"""
160
  for student, change in impact_dict.items():
161
- current = self.session["engagement_scores"][student]
162
- new_score = max(1, min(5, current + change)) # Keep between 1-5
163
- self.session["engagement_scores"][student] = new_score
 
164
 
165
  def get_engagement_display(self):
166
  """Create visual representation of student engagement"""
 
167
  display = "## πŸ“Š Student Engagement Levels\n\n"
168
- for student, score in self.session["engagement_scores"].items():
 
 
169
  stars = "⭐" * score + "β˜†" * (5-score)
170
- display += f"**{student}:** {stars} ({score}/5)\n\n"
 
171
  return display
172
 
173
  def get_scenario_info(self):
174
  scenario = self.get_current_scenario()
175
- return f"""## {scenario['title']}
 
 
176
 
177
  **Situation:** {scenario['setup']}
178
 
 
 
179
  **Learning Goals:** {scenario['learning_goals']}
180
 
181
- **Your Students:**
182
- - **Maya:** {scenario['students']['Maya']}
183
- - **Jamal:** {scenario['students']['Jamal']}
184
- - **Aisha:** {scenario['students']['Aisha']}
185
- - **Emma:** {scenario['students']['Emma']}
186
- """
 
 
 
 
187
 
188
  # Initialize game
189
  game = ScienceTalkGame()
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  def start_new_session():
192
- """Reset the game for a new session"""
193
  game.reset_session()
194
  scenario_info = game.get_scenario_info()
195
  engagement_display = game.get_engagement_display()
196
- welcome_msg = """## Welcome to Science Talk Adventure! 🌟
197
 
198
- You're about to practice facilitating an equitable science discussion with a diverse group of 2nd graders. Your goal is to:
199
 
200
- 1. **Include all student voices** - especially those who might be hesitant to share
201
- 2. **Build on cultural assets** - honor the knowledge students bring from home
202
- 3. **Promote scientific thinking** - help students observe, question, and investigate
203
  4. **Manage participation** - ensure discussions are equitable
204
 
205
- **To begin:** Type what you would say to start the science talk, then click 'Send Response'."""
206
 
207
  return scenario_info, engagement_display, welcome_msg, f"**Teaching Points:** {game.session['teaching_points']}", ""
208
 
@@ -220,25 +452,20 @@ def process_teacher_input(teacher_input):
220
  for i, choice in enumerate(choices, 1):
221
  choice_display += f"**Option {i}:** {choice}\n\n"
222
 
223
- # Update turn count
224
  game.session["turn_count"] += 1
225
-
226
  return student_response, choice_display, ""
227
 
228
  def handle_teaching_choice(choice_num):
229
  """Process the selected teaching choice"""
230
  if choice_num < 1 or choice_num > 4:
231
- return "Please select a valid choice (1-4).", "", ""
232
 
233
- # Get the choice (this is simplified - in full version, we'd track the actual choices)
234
- choice_options = game.generate_teaching_choices()
235
- if choice_num <= len(choice_options):
236
- selected_choice = choice_options[choice_num - 1]
237
 
238
- # Assess the choice
239
  feedback, points, engagement_impact = game.assess_teaching_choice(selected_choice)
240
 
241
- # Update game state
242
  game.session["teaching_points"] += points
243
  game.update_engagement(engagement_impact)
244
  game.session["choices_made"].append({
@@ -247,7 +474,6 @@ def handle_teaching_choice(choice_num):
247
  "turn": game.session["turn_count"]
248
  })
249
 
250
- # Create response
251
  updated_engagement = game.get_engagement_display()
252
  points_display = f"**Teaching Points:** {game.session['teaching_points']}"
253
 
@@ -258,18 +484,27 @@ def handle_teaching_choice(choice_num):
258
  # Create Gradio interface
259
  def create_interface():
260
  with gr.Blocks(title="Science Talk Adventure", theme=gr.themes.Soft()) as interface:
261
- gr.Markdown("# 🌱 Science Talk Adventure: Practice Equitable Science Discussions")
262
- gr.Markdown("*An interactive simulation for preservice elementary teachers*")
263
 
264
  with gr.Row():
265
  with gr.Column(scale=2):
 
 
 
 
 
 
 
 
 
266
  scenario_info = gr.Markdown(game.get_scenario_info())
267
 
268
  conversation_area = gr.Markdown("*Students will respond here after you speak...*")
269
 
270
  teacher_input = gr.Textbox(
271
  label="πŸ’¬ What do you say to your students?",
272
- placeholder="Type your response here... (e.g., 'What do you notice about these plants?')",
273
  lines=3
274
  )
275
 
@@ -290,17 +525,30 @@ def create_interface():
290
  points_display = gr.Markdown(f"**Teaching Points:** {game.session['teaching_points']}")
291
 
292
  gr.Markdown("---")
293
- restart_btn = gr.Button("πŸ”„ Start New Session", variant="outline")
294
 
295
  gr.Markdown("""
296
  ### πŸ’‘ Tips for Success:
297
  - **Listen for cultural knowledge** students share
298
  - **Create wait time** for all students to think
299
- - **Build on student ideas** rather than immediately correcting
300
- - **Notice who's participating** and who might need encouragement
 
 
 
 
 
 
 
301
  """)
302
 
303
  # Event handlers
 
 
 
 
 
 
304
  restart_btn.click(
305
  start_new_session,
306
  outputs=[scenario_info, engagement_display, conversation_area, points_display, feedback_display]
 
10
 
11
  class ScienceTalkGame:
12
  def __init__(self):
13
+ self.scenarios = self.load_all_scenarios()
14
  self.reset_session()
15
 
16
  def reset_session(self):
17
  self.session = {
18
+ "engagement_scores": {},
19
  "teaching_points": 0,
20
  "choices_made": [],
21
  "current_scenario": "grade2_plants",
22
  "turn_count": 0
23
  }
24
+ self.update_engagement_for_scenario()
25
 
26
+ def load_all_scenarios(self):
27
  return {
28
+ "grade2_plants": {
29
+ "title": "🌱 Grade 2: Plant Investigation",
30
+ "ngss_standard": "2-LS2-1: Environmental Plant Needs",
31
+ "setup": "Your 2nd grade students are examining classroom plants. Some are healthy and green, others are yellow and droopy.",
32
+ "phenomenon": "Why do some plants in our classroom look different from others?",
33
+ "learning_goals": "Students observe plant differences, share ideas about plant needs, and connect to cultural knowledge about plants.",
34
+ "students": {
35
+ "Maya": {
36
+ "background": "Mexican-American, bilingual, family has vegetable garden",
37
+ "cultural_assets": "Grandmother's traditional gardening knowledge, Spanish plant names",
38
+ "communication_style": "Sometimes shy in English, mixes languages naturally",
39
+ "science_thinking": "Connects plants to family cooking and traditional remedies",
40
+ "base_engagement": 3
41
+ },
42
+ "Jamal": {
43
+ "background": "African-American, urban environment, curious observer",
44
+ "cultural_assets": "Community garden experience, street tree observations",
45
+ "communication_style": "Energetic, asks lots of 'what if' questions",
46
+ "science_thinking": "Makes connections to neighborhood observations",
47
+ "base_engagement": 4
48
+ },
49
+ "Aisha": {
50
+ "background": "Somali-American, family farming background from Somalia",
51
+ "cultural_assets": "Traditional ecological knowledge, seasonal farming wisdom",
52
+ "communication_style": "Thoughtful, needs processing time before sharing",
53
+ "science_thinking": "Compares to farming practices from home country",
54
+ "base_engagement": 2
55
+ },
56
+ "Emma": {
57
+ "background": "White suburban, science-enthusiastic family",
58
+ "cultural_assets": "Access to science books and nature documentaries",
59
+ "communication_style": "Eager to share, uses formal science vocabulary",
60
+ "science_thinking": "References books and shows, sometimes dominates",
61
+ "base_engagement": 4
62
+ }
63
+ }
64
+ },
65
+
66
+ "grade4_energy": {
67
+ "title": "⚑ Grade 4: Energy Transfer Investigation",
68
+ "ngss_standard": "4-PS3-2: Energy Transfer",
69
+ "setup": "Students tested different spoon materials in hot cocoa and noticed some got hot while others stayed cool.",
70
+ "phenomenon": "Why do metal spoons get hot in hot cocoa but wooden spoons don't?",
71
+ "learning_goals": "Students explore energy transfer, connect to family cooking knowledge, and investigate material properties.",
72
+ "students": {
73
+ "Diego": {
74
+ "background": "Mexican-American, father works in auto mechanics",
75
+ "cultural_assets": "Family knowledge about tools, metal work, cooking traditions",
76
+ "communication_style": "Enthusiastic, mixes Spanish and English",
77
+ "science_thinking": "Connects to mechanical work and traditional cooking methods",
78
+ "base_engagement": 4
79
+ },
80
+ "Keisha": {
81
+ "background": "African-American, practical problem-solver, urban environment",
82
+ "cultural_assets": "Family cooking traditions, observational skills from city life",
83
+ "communication_style": "Direct, logical, asks practical questions",
84
+ "science_thinking": "Focuses on real-world applications and problem-solving",
85
+ "base_engagement": 4
86
+ },
87
+ "Ryan": {
88
+ "background": "White rural, family farm and workshop experience",
89
+ "cultural_assets": "Traditional craftsmanship, agricultural knowledge, tool use",
90
+ "communication_style": "Methodical, references family work experiences",
91
+ "science_thinking": "Connects to farming and workshop applications",
92
+ "base_engagement": 3
93
+ },
94
+ "Zara": {
95
+ "background": "Somali-American, moved from Somalia, multilingual",
96
+ "cultural_assets": "International perspective, traditional cooking methods",
97
+ "communication_style": "Careful with English, thoughtful responses",
98
+ "science_thinking": "Compares to practices from different countries",
99
+ "base_engagement": 2
100
+ }
101
+ }
102
+ },
103
+
104
+ "kindergarten_weather": {
105
+ "title": "β˜€οΈ Kindergarten: Weather Watchers",
106
+ "ngss_standard": "K-ESS2-1: Weather Patterns",
107
+ "setup": "Students noticed that puddles from yesterday's rain have disappeared, and they're curious about where the water went.",
108
+ "phenomenon": "Why do puddles disappear on sunny days?",
109
+ "learning_goals": "Students observe weather changes, share family weather knowledge, and explore water in the environment.",
110
+ "students": {
111
+ "Aaliyah": {
112
+ "background": "African-American, urban, walks to school daily",
113
+ "cultural_assets": "Daily weather observations, neighborhood knowledge",
114
+ "communication_style": "Animated storyteller, uses gestures",
115
+ "science_thinking": "Makes connections between daily observations",
116
+ "base_engagement": 4
117
+ },
118
+ "JosΓ©": {
119
+ "background": "Mexican-American, recent immigrant, bilingual family",
120
+ "cultural_assets": "Traditional weather prediction methods from Mexico",
121
+ "communication_style": "Thoughtful, mixes Spanish and English",
122
+ "science_thinking": "Connects to traditional weather wisdom",
123
+ "base_engagement": 3
124
+ },
125
+ "Emma": {
126
+ "background": "White suburban, science-enthusiastic family",
127
+ "cultural_assets": "Science books and weather apps at home",
128
+ "communication_style": "Eager, uses weather vocabulary from books",
129
+ "science_thinking": "References weather facts from media",
130
+ "base_engagement": 4
131
+ },
132
+ "Kai": {
133
+ "background": "Mixed Asian/Pacific Islander, military family, moved frequently",
134
+ "cultural_assets": "Experience with different climates and weather patterns",
135
+ "communication_style": "Observant but hesitant to share",
136
+ "science_thinking": "Compares weather across different locations",
137
+ "base_engagement": 2
138
+ }
139
+ }
140
+ },
141
+
142
+ "grade5_ecosystems": {
143
+ "title": "🌍 Grade 5: Community Ecosystem Scientists",
144
+ "ngss_standard": "5-LS2-1: Environmental Matter Cycling",
145
+ "setup": "Students visited the community garden and noticed different areas have different plants, insects, and soil conditions.",
146
+ "phenomenon": "Why do different areas of the community garden have different living things?",
147
+ "learning_goals": "Students explore ecosystem interactions, connect to community knowledge, and investigate matter cycling.",
148
+ "students": {
149
+ "Amara": {
150
+ "background": "Somali-American, family farming background",
151
+ "cultural_assets": "Traditional ecological knowledge, crop rotation understanding",
152
+ "communication_style": "Thoughtful, connects to family farming wisdom",
153
+ "science_thinking": "Sees connections between traditional and scientific knowledge",
154
+ "base_engagement": 3
155
+ },
156
+ "Carlos": {
157
+ "background": "Mexican-American, grandmother has large garden",
158
+ "cultural_assets": "Traditional companion planting, medicinal plants knowledge",
159
+ "communication_style": "Enthusiastic about sharing family knowledge",
160
+ "science_thinking": "Integrates traditional ecological practices with science",
161
+ "base_engagement": 4
162
+ },
163
+ "Destiny": {
164
+ "background": "African-American, urban nature observer",
165
+ "cultural_assets": "City ecosystem observations, community garden participation",
166
+ "communication_style": "Curious, asks detailed questions",
167
+ "science_thinking": "Notices patterns in urban environments",
168
+ "base_engagement": 4
169
+ },
170
+ "Tyler": {
171
+ "background": "White rural, hunting and outdoor experience",
172
+ "cultural_assets": "Wildlife observation, forest ecology knowledge",
173
+ "communication_style": "Practical, references outdoor experiences",
174
+ "science_thinking": "Understands predator-prey relationships and cycles",
175
+ "base_engagement": 3
176
+ },
177
+ "Mei": {
178
+ "background": "Chinese-American, recently arrived, family gardening",
179
+ "cultural_assets": "Traditional Chinese gardening, vermiculture knowledge",
180
+ "communication_style": "Hesitant with English, rich knowledge to share",
181
+ "science_thinking": "Brings international gardening perspectives",
182
+ "base_engagement": 2
183
+ }
184
+ }
185
  }
186
  }
187
 
188
+ def update_engagement_for_scenario(self):
189
+ """Set engagement scores based on current scenario"""
190
+ scenario = self.scenarios[self.session["current_scenario"]]
191
+ self.session["engagement_scores"] = {}
192
+ for student_name, student_data in scenario["students"].items():
193
+ self.session["engagement_scores"][student_name] = student_data["base_engagement"]
194
+
195
+ def get_current_scenario(self):
196
+ return self.scenarios[self.session["current_scenario"]]
197
+
198
+ def change_scenario(self, scenario_key):
199
+ """Switch to a different scenario"""
200
+ if scenario_key in self.scenarios:
201
+ self.session["current_scenario"] = scenario_key
202
+ self.session["teaching_points"] = 0
203
+ self.session["choices_made"] = []
204
+ self.session["turn_count"] = 0
205
+ self.update_engagement_for_scenario()
206
+ return True
207
+ return False
208
+
209
  def generate_student_responses(self, teacher_input):
210
  scenario = self.get_current_scenario()
211
 
212
+ # Create detailed context for each student
213
+ student_contexts = []
214
+ for student_name, student_data in scenario["students"].items():
215
+ engagement_level = self.session["engagement_scores"][student_name]
216
+
217
+ if engagement_level >= 4:
218
+ engagement_desc = "highly engaged and eager to participate"
219
+ elif engagement_level >= 3:
220
+ engagement_desc = "moderately engaged and willing to share"
221
+ elif engagement_level >= 2:
222
+ engagement_desc = "somewhat hesitant but paying attention"
223
  else:
224
+ engagement_desc = "disengaged and unlikely to participate"
225
+
226
+ context = f"""**{student_name}**: {student_data['background']}. {student_data['cultural_assets']}. {student_data['communication_style']}. Currently {engagement_desc}."""
227
+ student_contexts.append(context)
228
 
229
+ prompt = f"""You are role-playing elementary students in a science discussion. The scenario is: {scenario['title']} - {scenario['setup']}
 
 
 
 
 
 
230
 
231
+ The scientific phenomenon being explored: {scenario['phenomenon']}
232
 
233
+ Students in this discussion:
234
+ {chr(10).join(student_contexts)}
235
 
236
  The teacher just said: "{teacher_input}"
237
 
238
+ Respond as each student would, showing their authentic thinking, cultural backgrounds, and current engagement levels. Make responses feel natural for their grade level. Format your response as:
239
 
240
+ **[Student Name]:** [their response]
 
 
 
241
 
242
+ For each student response, show their personality, cultural knowledge, communication style, and current engagement level. Some students might not respond if they're disengaged."""
243
 
244
  try:
245
  response = openai.ChatCompletion.create(
246
  model="openai/gpt-3.5-turbo",
247
  messages=[{"role": "user", "content": prompt}],
248
  temperature=0.8,
249
+ max_tokens=500
250
  )
251
  return response.choices[0].message.content
252
  except Exception as e:
253
  return f"**Error generating student responses:** {str(e)}\n\nPlease check your OpenRouter API key configuration."
254
 
255
+ def generate_teaching_choices(self, scenario_context=""):
256
+ """Generate contextual teaching choices based on current scenario"""
257
+ scenario = self.get_current_scenario()
258
+
259
+ # Base equity-focused choices
260
  base_choices = [
261
+ "🌟 Build on cultural knowledge: Ask students about family/community knowledge related to this topic",
262
+ "🀝 Create inclusive space: Make sure quieter students get a chance to share their thinking",
263
+ "πŸ”¬ Promote scientific investigation: Guide students to plan how they could test their ideas",
264
+ "βš–οΈ Manage participation: Redirect conversation to include less dominant voices"
265
  ]
266
 
267
+ # Scenario-specific choices
268
+ scenario_specific = {
269
+ "grade2_plants": [
270
+ "🌱 Connect to home gardens: Ask about plants students have at home",
271
+ "πŸ’­ Support language learners: Encourage students to share plant names in their home languages",
272
+ "πŸ—£οΈ Facilitate peer discussion: Have students share observations with a partner first",
273
+ "πŸ“Š Document thinking: Help students draw or record what they notice"
274
+ ],
275
+ "grade4_energy": [
276
+ "πŸ”§ Connect to family work: Ask about tools and materials families use",
277
+ "🍳 Explore cooking connections: Discuss heat transfer in family cooking traditions",
278
+ "πŸ§ͺ Design investigations: Help students plan controlled tests of materials",
279
+ "🌑️ Make predictions: Ask students to predict what will happen with different materials"
280
+ ],
281
+ "kindergarten_weather": [
282
+ "🌀️ Share weather observations: Ask about weather patterns students notice",
283
+ "🏠 Connect to daily life: Discuss how weather affects what families do",
284
+ "πŸ‘οΈ Use senses: Encourage students to describe what they see, feel, smell",
285
+ "πŸ“… Track patterns: Help students think about when they've seen this before"
286
+ ],
287
+ "grade5_ecosystems": [
288
+ "🌿 Explore traditional knowledge: Ask about family farming or gardening practices",
289
+ "πŸ”„ Investigate cycles: Help students trace matter through the ecosystem",
290
+ "🀝 Community connections: Discuss how people are part of the ecosystem",
291
+ "πŸ“‹ Systematic observation: Guide students to organize their observations"
292
+ ]
293
+ }
294
+
295
+ # Combine base and scenario-specific choices
296
+ current_specific = scenario_specific.get(self.session["current_scenario"], [])
297
+ all_choices = base_choices + current_specific
298
 
299
+ # Return 4 random choices to keep it fresh
300
+ return random.sample(all_choices, min(4, len(all_choices)))
 
301
 
302
  def assess_teaching_choice(self, choice_text):
303
+ """Enhanced assessment based on scenario context"""
304
  feedback = ""
305
  points = 0
306
  engagement_impact = {}
307
 
 
308
  choice_lower = choice_text.lower()
309
+ scenario = self.get_current_scenario()
310
 
311
+ # Assess different types of teaching moves
312
+ if any(keyword in choice_lower for keyword in ["cultural", "family", "community", "home"]):
313
+ feedback = "🌟 Excellent! You're building on students' cultural assets. This validates their family knowledge and shows that diverse perspectives are valued in science."
314
  points = 3
315
+ # Boost engagement for students with strong cultural assets
316
+ for student_name, student_data in scenario["students"].items():
317
+ if "traditional" in student_data["cultural_assets"].lower() or "family" in student_data["cultural_assets"].lower():
318
+ engagement_impact[student_name] = engagement_impact.get(student_name, 0) + 2
319
+
320
+ elif any(keyword in choice_lower for keyword in ["inclusive", "quieter", "all students", "everyone"]):
321
  feedback = "βœ… Great equity move! Creating space for all voices helps build a classroom community where everyone's thinking is valued."
322
  points = 2
323
+ # Boost engagement for lower-engaged students
324
+ for student_name, engagement in self.session["engagement_scores"].items():
325
+ if engagement <= 3:
326
+ engagement_impact[student_name] = engagement_impact.get(student_name, 0) + 2
327
+
328
+ elif any(keyword in choice_lower for keyword in ["investigate", "test", "plan", "scientific"]):
329
+ feedback = "πŸ”¬ Good scientific thinking! You're helping students engage in authentic science practices and develop investigative skills."
 
 
 
 
 
 
 
 
 
 
 
 
330
  points = 2
331
+ # Boost engagement for science-oriented students
332
+ for student_name, student_data in scenario["students"].items():
333
+ if "science" in student_data["science_thinking"].lower():
334
+ engagement_impact[student_name] = engagement_impact.get(student_name, 0) + 1
335
+
336
+ elif any(keyword in choice_lower for keyword in ["manage", "redirect", "less dominant"]):
337
+ feedback = "βš–οΈ Important facilitation move! Managing participation ensures equitable discourse and gives space for all students to contribute."
338
  points = 2
339
+ # Reduce dominance, increase participation for others
340
+ for student_name, engagement in self.session["engagement_scores"].items():
341
+ if engagement >= 4:
342
+ engagement_impact[student_name] = engagement_impact.get(student_name, 0) - 1
343
+ else:
344
+ engagement_impact[student_name] = engagement_impact.get(student_name, 0) + 1
345
+
346
+ elif any(keyword in choice_lower for keyword in ["language", "home languages", "spanish", "multilingual"]):
347
+ feedback = "πŸ—£οΈ Wonderful! Supporting multilingual learners by honoring their home languages strengthens both their science learning and cultural identity."
348
+ points = 3
349
+ # Major boost for multilingual students
350
+ for student_name, student_data in scenario["students"].items():
351
+ if "bilingual" in student_data["background"].lower() or "language" in student_data["communication_style"].lower():
352
+ engagement_impact[student_name] = engagement_impact.get(student_name, 0) + 3
353
+
354
  else:
355
  feedback = "Consider how this choice supports equitable participation and builds on student thinking."
356
  points = 1
 
357
 
358
  return feedback, points, engagement_impact
359
 
360
  def update_engagement(self, impact_dict):
361
  """Update student engagement based on teaching choices"""
362
  for student, change in impact_dict.items():
363
+ if student in self.session["engagement_scores"]:
364
+ current = self.session["engagement_scores"][student]
365
+ new_score = max(1, min(5, current + change))
366
+ self.session["engagement_scores"][student] = new_score
367
 
368
  def get_engagement_display(self):
369
  """Create visual representation of student engagement"""
370
+ scenario = self.get_current_scenario()
371
  display = "## πŸ“Š Student Engagement Levels\n\n"
372
+
373
+ for student_name, score in self.session["engagement_scores"].items():
374
+ student_info = scenario["students"][student_name]
375
  stars = "⭐" * score + "β˜†" * (5-score)
376
+ display += f"**{student_name}** ({student_info['background'].split(',')[0]}): {stars} ({score}/5)\n\n"
377
+
378
  return display
379
 
380
  def get_scenario_info(self):
381
  scenario = self.get_current_scenario()
382
+
383
+ info = f"""## {scenario['title']}
384
+ **NGSS Standard:** {scenario['ngss_standard']}
385
 
386
  **Situation:** {scenario['setup']}
387
 
388
+ **Phenomenon:** {scenario['phenomenon']}
389
+
390
  **Learning Goals:** {scenario['learning_goals']}
391
 
392
+ **Your Students:**"""
393
+
394
+ for student_name, student_data in scenario["students"].items():
395
+ info += f"\n- **{student_name}:** {student_data['background']} - {student_data['cultural_assets']}"
396
+
397
+ return info
398
+
399
+ def get_available_scenarios(self):
400
+ """Return list of available scenarios for selection"""
401
+ return [(key, data["title"]) for key, data in self.scenarios.items()]
402
 
403
  # Initialize game
404
  game = ScienceTalkGame()
405
 
406
+ def change_scenario(scenario_choice):
407
+ """Handle scenario change"""
408
+ # Extract scenario key from the choice (format: "key: title")
409
+ scenario_key = scenario_choice.split(":")[0].strip()
410
+
411
+ if game.change_scenario(scenario_key):
412
+ scenario_info = game.get_scenario_info()
413
+ engagement_display = game.get_engagement_display()
414
+ points_display = f"**Teaching Points:** {game.session['teaching_points']}"
415
+ welcome_msg = f"""## Welcome to {game.get_current_scenario()['title']}! 🌟
416
+
417
+ **Instructions:** Type what you would say to start this science discussion, then click 'Send Response' to see how your students react."""
418
+
419
+ return scenario_info, engagement_display, welcome_msg, points_display, "", ""
420
+ else:
421
+ return "Error changing scenario", "", "", "", "", ""
422
+
423
  def start_new_session():
424
+ """Reset the current scenario"""
425
  game.reset_session()
426
  scenario_info = game.get_scenario_info()
427
  engagement_display = game.get_engagement_display()
428
+ welcome_msg = f"""## Welcome to {game.get_current_scenario()['title']}! 🌟
429
 
430
+ You're about to practice facilitating an equitable science discussion. Your goals:
431
 
432
+ 1. **Include all student voices** - especially those who might be hesitant
433
+ 2. **Build on cultural assets** - honor knowledge students bring from home
434
+ 3. **Promote scientific thinking** - help students observe, question, investigate
435
  4. **Manage participation** - ensure discussions are equitable
436
 
437
+ **To begin:** Type what you would say to start the science talk."""
438
 
439
  return scenario_info, engagement_display, welcome_msg, f"**Teaching Points:** {game.session['teaching_points']}", ""
440
 
 
452
  for i, choice in enumerate(choices, 1):
453
  choice_display += f"**Option {i}:** {choice}\n\n"
454
 
 
455
  game.session["turn_count"] += 1
 
456
  return student_response, choice_display, ""
457
 
458
  def handle_teaching_choice(choice_num):
459
  """Process the selected teaching choice"""
460
  if choice_num < 1 or choice_num > 4:
461
+ return "Please select a valid choice.", "", ""
462
 
463
+ choices = game.generate_teaching_choices()
464
+ if choice_num <= len(choices):
465
+ selected_choice = choices[choice_num - 1]
 
466
 
 
467
  feedback, points, engagement_impact = game.assess_teaching_choice(selected_choice)
468
 
 
469
  game.session["teaching_points"] += points
470
  game.update_engagement(engagement_impact)
471
  game.session["choices_made"].append({
 
474
  "turn": game.session["turn_count"]
475
  })
476
 
 
477
  updated_engagement = game.get_engagement_display()
478
  points_display = f"**Teaching Points:** {game.session['teaching_points']}"
479
 
 
484
  # Create Gradio interface
485
  def create_interface():
486
  with gr.Blocks(title="Science Talk Adventure", theme=gr.themes.Soft()) as interface:
487
+ gr.Markdown("# 🌱 Science Talk Adventure: Multi-Scenario Practice")
488
+ gr.Markdown("*Practice equitable science discussions across multiple grade levels and topics*")
489
 
490
  with gr.Row():
491
  with gr.Column(scale=2):
492
+ # Scenario selection
493
+ scenario_choices = [f"{key}: {data['title']}" for key, data in game.scenarios.items()]
494
+ scenario_selector = gr.Dropdown(
495
+ choices=scenario_choices,
496
+ value=f"{game.session['current_scenario']}: {game.get_current_scenario()['title']}",
497
+ label="🎭 Choose Your Scenario",
498
+ interactive=True
499
+ )
500
+
501
  scenario_info = gr.Markdown(game.get_scenario_info())
502
 
503
  conversation_area = gr.Markdown("*Students will respond here after you speak...*")
504
 
505
  teacher_input = gr.Textbox(
506
  label="πŸ’¬ What do you say to your students?",
507
+ placeholder="Type your response here...",
508
  lines=3
509
  )
510
 
 
525
  points_display = gr.Markdown(f"**Teaching Points:** {game.session['teaching_points']}")
526
 
527
  gr.Markdown("---")
528
+ restart_btn = gr.Button("πŸ”„ Restart Current Scenario", variant="outline")
529
 
530
  gr.Markdown("""
531
  ### πŸ’‘ Tips for Success:
532
  - **Listen for cultural knowledge** students share
533
  - **Create wait time** for all students to think
534
+ - **Build on student ideas** rather than correcting immediately
535
+ - **Notice participation patterns** and include all voices
536
+ - **Connect to students' lived experiences**
537
+
538
+ ### 🎯 Available Scenarios:
539
+ - **Kindergarten:** Weather patterns and observations
540
+ - **Grade 2:** Plant growth and needs
541
+ - **Grade 4:** Energy transfer in everyday materials
542
+ - **Grade 5:** Community ecosystem interactions
543
  """)
544
 
545
  # Event handlers
546
+ scenario_selector.change(
547
+ change_scenario,
548
+ inputs=[scenario_selector],
549
+ outputs=[scenario_info, engagement_display, conversation_area, points_display, feedback_display, choices_display]
550
+ )
551
+
552
  restart_btn.click(
553
  start_new_session,
554
  outputs=[scenario_info, engagement_display, conversation_area, points_display, feedback_display]