vighnesh-shetty-vs commited on
Commit
36f4c80
·
1 Parent(s): b9ed0f0

Add updated files

Browse files
Files changed (1) hide show
  1. app.py +111 -24
app.py CHANGED
@@ -46,19 +46,83 @@ def get_stats_html(water, energy, points):
46
  """
47
 
48
  def get_drip_visuals(water_level):
 
 
 
 
 
49
  if water_level > 70:
50
- emoji, size, anim, glow, status = "💧", "120px", "float 3s ease-in-out infinite", "rgba(56,189,248,0.6)", "Plump & Hydrated"
 
 
 
 
 
 
 
 
 
 
 
51
  elif 30 <= water_level <= 70:
52
- emoji, size, anim, glow, status = "💧", "90px", "none", "rgba(56,189,248,0.3)", "Shrinking & Tired"
 
 
 
 
 
 
 
 
 
 
53
  elif water_level > 0:
54
- emoji, size, anim, glow, status = "🏜️", "70px", "none", "rgba(239,68,68,0.4)", "Cracked & Raspy"
 
 
 
 
 
 
 
 
 
 
 
55
  else:
56
- emoji, size, anim, glow, status = "💨", "50px", "none", "transparent", "Evaporated!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  return f"""
59
- <div class="drip-character" style="box-shadow: 0 0 40px {glow};">
60
- <div style="font-size: {size}; animation: {anim}; transition: all 0.5s ease;">{emoji}</div>
61
- <h3 style="margin: 10px 0 0 0; color: #e2e8f0; font-weight: 400; font-size: 1rem;">{status}</h3>
62
  </div>
63
  """
64
 
@@ -122,11 +186,11 @@ def process_query(user_input, selected_model, state):
122
  drip_ui = get_drip_visuals(state["water"])
123
  impact_ui = get_impact_cards(impact, category)
124
  audio_path = generate_audio(dialogue)
125
- feedback_text = f"### 🧠 **{category.upper()}** Detected on **{selected_model}**!\n*{dialogue}*"
126
 
127
  if state["points"] >= 500 or state["water"] <= 0:
128
  state["game_over"] = True
129
- return (state, stats_ui, drip_ui, audio_path, impact_ui, gr.update(value="## Game Over! Check your score."), gr.update(visible=False), gr.update(), gr.update(), gr.update(), gr.update())
130
 
131
  return (state, stats_ui, drip_ui, audio_path, impact_ui, gr.update(value=feedback_text), gr.update(visible=show_alts),
132
  gr.update(value=alt_choices[0]), gr.update(value=alt_choices[1]), gr.update(value=alt_choices[2]), gr.update(value=""))
@@ -148,14 +212,18 @@ def select_alternative(choice_text, state):
148
 
149
  return state, stats_ui, gr.update(value=msg), gr.update(visible=False)
150
 
 
 
151
  custom_css = """
152
  @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;500;700&display=swap');
153
  body, .gradio-container { background-color: #0B1120 !important; font-family: 'Outfit', sans-serif !important; color: #e2e8f0 !important; }
154
- .gradio-container { max-width: 900px !important; margin: auto; padding-top: 20px; }
155
  h1 { text-align: center; color: #38bdf8; text-shadow: 0 0 15px rgba(56, 189, 248, 0.5); font-size: 2.5em !important; margin-bottom: 5px !important;}
156
  .subtitle { text-align: center; color: #94a3b8; margin-bottom: 30px; font-weight: 300; }
 
 
157
  .stats-container { display: flex; gap: 15px; justify-content: space-between; margin-bottom: 20px; }
158
- .stat-card { flex: 1; padding: 15px; border-radius: 16px; text-align: center; background: rgba(30, 41, 59, 0.6); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.1); }
159
  .water-card { box-shadow: 0 4px 20px rgba(56, 189, 248, 0.15); border-top: 2px solid #38bdf8; }
160
  .energy-card { box-shadow: 0 4px 20px rgba(250, 204, 21, 0.15); border-top: 2px solid #facc15; }
161
  .points-card { box-shadow: 0 4px 20px rgba(52, 211, 153, 0.15); border-top: 2px solid #34d399; }
@@ -163,22 +231,37 @@ h1 { text-align: center; color: #38bdf8; text-shadow: 0 0 15px rgba(56, 189, 248
163
  .stat-value { font-size: 2em; font-weight: 700; color: white; }
164
  .progress-bar-bg { background: #1e293b; height: 8px; border-radius: 4px; margin-top: 10px; overflow: hidden; }
165
  .progress-bar-fill { background: linear-gradient(90deg, #0284c7, #38bdf8); height: 100%; transition: width 0.5s ease; }
166
- .drip-pod { background: rgba(15, 23, 42, 0.6); border-radius: 24px; border: 1px solid rgba(56, 189, 248, 0.2); padding: 30px 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; box-shadow: inset 0 0 40px rgba(0,0,0,0.5); }
167
- .drip-character { width: 160px; height: 160px; border-radius: 50%; background: radial-gradient(circle, rgba(56,189,248,0.15) 0%, transparent 70%); display: flex; flex-direction: column; align-items: center; justify-content: center; margin-bottom: 10px; }
168
- @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-15px); } 100% { transform: translateY(0px); } }
169
- .drip-audio { background: transparent !important; border: none !important; box-shadow: none !important; width: 100%; max-width: 300px; filter: invert(1) hue-rotate(180deg) brightness(1.5); }
 
 
 
 
 
 
 
 
 
 
 
 
170
  .input-row { align-items: stretch !important; margin: 10px 0; }
171
- .custom-textbox textarea { background: rgba(30, 41, 59, 0.8) !important; border: 1px solid #38bdf8 !important; color: white !important; font-size: 1.1em !important; border-radius: 12px !important; box-shadow: 0 0 15px rgba(56, 189, 248, 0.1) !important; padding: 15px !important; }
172
- .custom-btn { background: linear-gradient(135deg, #0284c7, #0ea5e9) !important; border: none !important; color: white !important; font-weight: bold !important; font-size: 1.1em !important; border-radius: 12px !important; transition: all 0.3s !important; height: 100%; }
173
  .custom-btn:hover { box-shadow: 0 0 20px rgba(56, 189, 248, 0.6) !important; transform: scale(1.02); }
 
 
174
  .impact-container { display: flex; gap: 20px; width: 100%; }
175
  .impact-card { flex: 1; padding: 20px; border-radius: 16px; border: 1px solid rgba(255,255,255,0.1); }
176
  .bad-impact { background: linear-gradient(180deg, rgba(127, 29, 29, 0.3), rgba(69, 10, 10, 0.5)); border-top: 3px solid #ef4444; }
177
  .good-impact { background: linear-gradient(180deg, rgba(20, 83, 45, 0.3), rgba(6, 78, 59, 0.5)); border-top: 3px solid #10b981; }
178
- .alt-group { padding: 20px; background: rgba(16, 185, 129, 0.05); border-radius: 16px; border: 1px dashed #10b981; margin-top: 20px;}
179
- .alt-card { background: rgba(30, 41, 59, 0.8) !important; border: 1px solid #10b981 !important; color: #a7f3d0 !important; height: 120px !important; border-radius: 16px !important; font-size: 1.1em !important; white-space: pre-wrap !important; transition: all 0.2s ease !important; cursor: pointer; display: flex; flex-direction: column; justify-content: center; align-items: center; box-shadow: 0 4px 15px rgba(0,0,0,0.3) !important;}
180
- .alt-card:hover { background: rgba(16, 185, 129, 0.2) !important; transform: translateY(-5px) !important; box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4) !important; color: white !important;}
181
- /* Dropdown styling for dark theme */
 
182
  .custom-dropdown { background: rgba(30, 41, 59, 0.8) !important; border: 1px solid #38bdf8 !important; border-radius: 12px !important; }
183
  """
184
 
@@ -194,22 +277,26 @@ with gr.Blocks(title="EcoQueryQuest") as demo:
194
  stats_html = gr.HTML(get_stats_html(100.0, 0.0, 0))
195
 
196
  with gr.Row():
 
197
  with gr.Column(scale=1, elem_classes=["drip-pod"]):
198
  drip_html = gr.HTML(get_drip_visuals(100))
199
  drip_audio = gr.Audio(label="Drip's Voice", autoplay=True, interactive=False, elem_classes=["drip-audio"])
 
200
 
 
201
  with gr.Column(scale=2):
202
  model_selector = gr.Dropdown(choices=list(MODELS.keys()), value="GPT-5.4", label="Select Target LLM Backend", elem_classes=["custom-dropdown"])
203
 
204
  with gr.Row(elem_classes=["input-row"]):
205
- user_input = gr.Textbox(show_label=False, placeholder="Type your query here...", elem_classes=["custom-textbox"], scale=4)
 
206
  submit_btn = gr.Button("Send Query", elem_classes=["custom-btn"], scale=1)
207
 
208
- drip_feedback = gr.Markdown("### Waiting for your first query...")
209
  impact_display = gr.HTML()
210
 
 
211
  with gr.Group(visible=False, elem_classes=["alt-group"]) as alternatives_group:
212
- gr.Markdown("<h3 style='text-align:center; color:#34d399; margin-bottom: 15px;'>🌱 Drip says: 'Quick! Pick a greener tool to earn points!'</h3>")
213
  with gr.Row():
214
  alt_btn_1 = gr.Button("", elem_classes=["alt-card"])
215
  alt_btn_2 = gr.Button("", elem_classes=["alt-card"])
 
46
  """
47
 
48
  def get_drip_visuals(water_level):
49
+ """Generates an animated SVG character whose expression changes with water level."""
50
+
51
+ # SVG Path for a classic water droplet
52
+ drop_path = "M 50,15 C 50,15 20,50 20,70 A 30,30 0 1,0 80,70 C 80,50 50,15 50,15 Z"
53
+
54
  if water_level > 70:
55
+ # Happy, Plump, Bouncing
56
+ color = "url(#blueGrad)"
57
+ anim = "bounce 2s infinite ease-in-out"
58
+ glow = "rgba(56,189,248,0.6)"
59
+ status = "Plump & Hydrated"
60
+ face = """
61
+ <circle cx="35" cy="60" r="4" fill="white"/>
62
+ <circle cx="65" cy="60" r="4" fill="white"/>
63
+ <path d="M 40,70 Q 50,80 60,70" stroke="white" stroke-width="3" fill="transparent" stroke-linecap="round"/>
64
+ <ellipse cx="25" cy="65" rx="5" ry="3" fill="rgba(255,255,255,0.3)"/>
65
+ <ellipse cx="75" cy="65" rx="5" ry="3" fill="rgba(255,255,255,0.3)"/>
66
+ """
67
  elif 30 <= water_level <= 70:
68
+ # Tired, Flat, Sweating
69
+ color = "#0ea5e9"
70
+ anim = "float 4s infinite ease-in-out"
71
+ glow = "rgba(56,189,248,0.3)"
72
+ status = "Shrinking & Tired"
73
+ face = """
74
+ <path d="M 30,60 Q 35,55 40,60" stroke="white" stroke-width="3" fill="transparent" stroke-linecap="round"/>
75
+ <path d="M 60,60 Q 65,55 70,60" stroke="white" stroke-width="3" fill="transparent" stroke-linecap="round"/>
76
+ <line x1="45" y1="72" x2="55" y2="72" stroke="white" stroke-width="3" stroke-linecap="round"/>
77
+ <path d="M 75,45 C 75,45 70,55 70,60 A 5,5 0 1,0 80,60 C 80,55 75,45 75,45 Z" fill="rgba(255,255,255,0.6)"/>
78
+ """
79
  elif water_level > 0:
80
+ # Overheating, Red, Cracked
81
+ color = "url(#redGrad)"
82
+ anim = "shake 0.5s infinite"
83
+ glow = "rgba(239,68,68,0.5)"
84
+ status = "Overheating & Raspy"
85
+ face = """
86
+ <line x1="30" y1="55" x2="40" y2="65" stroke="white" stroke-width="3" stroke-linecap="round"/>
87
+ <line x1="40" y1="55" x2="30" y2="65" stroke="white" stroke-width="3" stroke-linecap="round"/>
88
+ <line x1="60" y1="55" x2="70" y2="65" stroke="white" stroke-width="3" stroke-linecap="round"/>
89
+ <line x1="70" y1="55" x2="60" y2="65" stroke="white" stroke-width="3" stroke-linecap="round"/>
90
+ <path d="M 40,75 Q 45,70 50,75 T 60,75" stroke="white" stroke-width="3" fill="transparent" stroke-linecap="round"/>
91
+ """
92
  else:
93
+ # Ghost / Evaporated
94
+ color = "rgba(148, 163, 184, 0.5)"
95
+ anim = "floatUp 3s forwards"
96
+ glow = "transparent"
97
+ status = "Evaporated!"
98
+ drop_path = "M 30,80 Q 30,50 50,30 Q 70,50 70,80 Q 60,70 50,80 Q 40,70 30,80 Z" # Cloud/Ghost shape
99
+ face = """
100
+ <circle cx="40" cy="50" r="3" fill="white"/>
101
+ <circle cx="60" cy="50" r="3" fill="white"/>
102
+ <circle cx="50" cy="65" r="5" fill="transparent" stroke="white" stroke-width="2"/>
103
+ """
104
+
105
+ svg = f"""
106
+ <svg viewBox="0 0 100 100" style="width: 140px; height: 140px; filter: drop-shadow(0px 0px 15px {glow}); animation: {anim};">
107
+ <defs>
108
+ <linearGradient id="blueGrad" x1="0%" y1="0%" x2="0%" y2="100%">
109
+ <stop offset="0%" style="stop-color:#7dd3fc;stop-opacity:1" />
110
+ <stop offset="100%" style="stop-color:#0284c7;stop-opacity:1" />
111
+ </linearGradient>
112
+ <linearGradient id="redGrad" x1="0%" y1="0%" x2="0%" y2="100%">
113
+ <stop offset="0%" style="stop-color:#fca5a5;stop-opacity:1" />
114
+ <stop offset="100%" style="stop-color:#b91c1c;stop-opacity:1" />
115
+ </linearGradient>
116
+ </defs>
117
+ <path d="{drop_path}" fill="{color}"/>
118
+ {face}
119
+ </svg>
120
+ """
121
 
122
  return f"""
123
+ <div class="drip-character-container">
124
+ {svg}
125
+ <h3 style="margin: 15px 0 0 0; color: #e2e8f0; font-weight: 600; font-size: 1.1rem; text-align: center;">{status}</h3>
126
  </div>
127
  """
128
 
 
186
  drip_ui = get_drip_visuals(state["water"])
187
  impact_ui = get_impact_cards(impact, category)
188
  audio_path = generate_audio(dialogue)
189
+ feedback_text = f"<div class='feedback-box'>🧠 <strong>{category.upper()}</strong> Detected on {selected_model}!<br><br><em>\"{dialogue}\"</em></div>"
190
 
191
  if state["points"] >= 500 or state["water"] <= 0:
192
  state["game_over"] = True
193
+ return (state, stats_ui, drip_ui, audio_path, impact_ui, gr.update(value="<div class='feedback-box'>Game Over! Check your score.</div>"), gr.update(visible=False), gr.update(), gr.update(), gr.update(), gr.update())
194
 
195
  return (state, stats_ui, drip_ui, audio_path, impact_ui, gr.update(value=feedback_text), gr.update(visible=show_alts),
196
  gr.update(value=alt_choices[0]), gr.update(value=alt_choices[1]), gr.update(value=alt_choices[2]), gr.update(value=""))
 
212
 
213
  return state, stats_ui, gr.update(value=msg), gr.update(visible=False)
214
 
215
+
216
+ # --- UI Styling ---
217
  custom_css = """
218
  @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;500;700&display=swap');
219
  body, .gradio-container { background-color: #0B1120 !important; font-family: 'Outfit', sans-serif !important; color: #e2e8f0 !important; }
220
+ .gradio-container { max-width: 950px !important; margin: auto; padding-top: 20px; }
221
  h1 { text-align: center; color: #38bdf8; text-shadow: 0 0 15px rgba(56, 189, 248, 0.5); font-size: 2.5em !important; margin-bottom: 5px !important;}
222
  .subtitle { text-align: center; color: #94a3b8; margin-bottom: 30px; font-weight: 300; }
223
+
224
+ /* Dashboard */
225
  .stats-container { display: flex; gap: 15px; justify-content: space-between; margin-bottom: 20px; }
226
+ .stat-card { flex: 1; padding: 15px; border-radius: 16px; text-align: center; background: rgba(30, 41, 59, 0.6); border: 1px solid rgba(255,255,255,0.1); }
227
  .water-card { box-shadow: 0 4px 20px rgba(56, 189, 248, 0.15); border-top: 2px solid #38bdf8; }
228
  .energy-card { box-shadow: 0 4px 20px rgba(250, 204, 21, 0.15); border-top: 2px solid #facc15; }
229
  .points-card { box-shadow: 0 4px 20px rgba(52, 211, 153, 0.15); border-top: 2px solid #34d399; }
 
231
  .stat-value { font-size: 2em; font-weight: 700; color: white; }
232
  .progress-bar-bg { background: #1e293b; height: 8px; border-radius: 4px; margin-top: 10px; overflow: hidden; }
233
  .progress-bar-fill { background: linear-gradient(90deg, #0284c7, #38bdf8); height: 100%; transition: width 0.5s ease; }
234
+
235
+ /* SVG Animations */
236
+ @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-15px); } }
237
+ @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
238
+ @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
239
+ @keyframes floatUp { to { transform: translateY(-30px); opacity: 0; } }
240
+
241
+ /* Drip Pod Column */
242
+ .drip-pod { background: rgba(15, 23, 42, 0.6); border-radius: 24px; border: 1px solid rgba(56, 189, 248, 0.2); padding: 30px 20px; display: flex; flex-direction: column; align-items: center; box-shadow: inset 0 0 40px rgba(0,0,0,0.5); }
243
+ .drip-character-container { display: flex; flex-direction: column; align-items: center; justify-content: center; margin-bottom: 20px; min-height: 180px; }
244
+ .drip-audio { background: transparent !important; border: none !important; box-shadow: none !important; width: 100%; max-width: 300px; filter: invert(1) hue-rotate(180deg) brightness(1.5); margin-bottom: 15px;}
245
+
246
+ /* Feedback Text Moved to Left Column */
247
+ .feedback-box { background: rgba(56, 189, 248, 0.1); border-left: 4px solid #38bdf8; padding: 15px; border-radius: 8px; font-size: 1.05em; color: #e2e8f0; width: 100%; text-align: left; line-height: 1.4; box-sizing: border-box;}
248
+
249
+ /* Input Area */
250
  .input-row { align-items: stretch !important; margin: 10px 0; }
251
+ .custom-textbox textarea { background: rgba(30, 41, 59, 0.8) !important; border: 1px solid #38bdf8 !important; color: white !important; font-size: 1.1em !important; border-radius: 12px !important; box-shadow: inset 0 2px 10px rgba(0,0,0,0.3) !important; padding: 15px !important; resize: none !important; }
252
+ .custom-btn { background: linear-gradient(135deg, #0284c7, #0ea5e9) !important; border: none !important; color: white !important; font-weight: bold !important; font-size: 1.1em !important; border-radius: 12px !important; transition: all 0.3s !important; height: 100%; min-height: 85px; }
253
  .custom-btn:hover { box-shadow: 0 0 20px rgba(56, 189, 248, 0.6) !important; transform: scale(1.02); }
254
+
255
+ /* Impact Cards */
256
  .impact-container { display: flex; gap: 20px; width: 100%; }
257
  .impact-card { flex: 1; padding: 20px; border-radius: 16px; border: 1px solid rgba(255,255,255,0.1); }
258
  .bad-impact { background: linear-gradient(180deg, rgba(127, 29, 29, 0.3), rgba(69, 10, 10, 0.5)); border-top: 3px solid #ef4444; }
259
  .good-impact { background: linear-gradient(180deg, rgba(20, 83, 45, 0.3), rgba(6, 78, 59, 0.5)); border-top: 3px solid #10b981; }
260
+
261
+ /* Interactive Alternatives Group */
262
+ .alt-group { padding: 25px; background: linear-gradient(145deg, rgba(16, 185, 129, 0.05), rgba(6, 95, 70, 0.1)); border-radius: 20px; border: 1px solid rgba(16, 185, 129, 0.3); margin-top: 25px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);}
263
+ .alt-card { background: linear-gradient(145deg, #1e293b, #0f172a) !important; border: 1px solid #10b981 !important; color: #a7f3d0 !important; height: 130px !important; border-radius: 16px !important; font-size: 1.15em !important; font-weight: 500 !important; white-space: pre-wrap !important; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important; cursor: pointer; box-shadow: 0 4px 15px rgba(0,0,0,0.4) !important;}
264
+ .alt-card:hover { background: linear-gradient(145deg, #064e3b, #065f46) !important; transform: translateY(-8px) !important; box-shadow: 0 12px 30px rgba(16, 185, 129, 0.3) !important; color: white !important; border-color: #34d399 !important;}
265
  .custom-dropdown { background: rgba(30, 41, 59, 0.8) !important; border: 1px solid #38bdf8 !important; border-radius: 12px !important; }
266
  """
267
 
 
277
  stats_html = gr.HTML(get_stats_html(100.0, 0.0, 0))
278
 
279
  with gr.Row():
280
+ # LEFT COLUMN: Drip character, Audio, and Feedback Text
281
  with gr.Column(scale=1, elem_classes=["drip-pod"]):
282
  drip_html = gr.HTML(get_drip_visuals(100))
283
  drip_audio = gr.Audio(label="Drip's Voice", autoplay=True, interactive=False, elem_classes=["drip-audio"])
284
+ drip_feedback = gr.HTML("<div class='feedback-box'>Waiting for your first query...</div>")
285
 
286
+ # RIGHT COLUMN: Interactions and Impact Data
287
  with gr.Column(scale=2):
288
  model_selector = gr.Dropdown(choices=list(MODELS.keys()), value="GPT-5.4", label="Select Target LLM Backend", elem_classes=["custom-dropdown"])
289
 
290
  with gr.Row(elem_classes=["input-row"]):
291
+ # Changed lines=3 so the query displays nicely without being cut off
292
+ user_input = gr.Textbox(show_label=False, placeholder="Type your query here...\n(Press Shift+Enter for new line)", elem_classes=["custom-textbox"], scale=4, lines=3)
293
  submit_btn = gr.Button("Send Query", elem_classes=["custom-btn"], scale=1)
294
 
 
295
  impact_display = gr.HTML()
296
 
297
+ # BOTTOM: Beautiful Interactive Alternatives
298
  with gr.Group(visible=False, elem_classes=["alt-group"]) as alternatives_group:
299
+ gr.Markdown("<h3 style='text-align:center; color:#34d399; margin-bottom: 20px;'>🌱 Drip says: 'Quick! Pick a greener tool to earn points!'</h3>")
300
  with gr.Row():
301
  alt_btn_1 = gr.Button("", elem_classes=["alt-card"])
302
  alt_btn_2 = gr.Button("", elem_classes=["alt-card"])