Justxd22 commited on
Commit
9e48922
Β·
1 Parent(s): 82f32a6

feat: Enhance evidence handling and formatting in game logic

Browse files
Files changed (3) hide show
  1. TODO.md +5 -0
  2. app.py +96 -6
  3. ui/static/js/game_logic.js +39 -4
TODO.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ - Highlight selected suspect card
2
+ - make the rounds/points improve
3
+ - pre-generate suspects cartoony potraits
4
+ - find the texture missing
5
+ - remove scroll bars
app.py CHANGED
@@ -97,19 +97,17 @@ class GameSession:
97
  kwargs = {}
98
  if tool_name == "get_location":
99
  kwargs = {"phone_number": arg}
100
- elif tool_name == "get_footage":
101
- kwargs = {"location": arg}
102
  elif tool_name == "call_alibi":
103
  kwargs = {"phone_number": arg}
104
  elif tool_name == "get_dna_test":
105
  kwargs = {"evidence_id": arg}
 
 
106
 
107
  result = self.game.use_tool(tool_name, **kwargs)
108
 
109
- evidence_data = {
110
- "title": f"Tool: {tool_name}",
111
- "description": str(result)
112
- }
113
 
114
  return {
115
  "action": "add_evidence",
@@ -118,6 +116,98 @@ class GameSession:
118
 
119
  return None
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  session = GameSession()
122
 
123
  # --- Gradio App ---
 
97
  kwargs = {}
98
  if tool_name == "get_location":
99
  kwargs = {"phone_number": arg}
 
 
100
  elif tool_name == "call_alibi":
101
  kwargs = {"phone_number": arg}
102
  elif tool_name == "get_dna_test":
103
  kwargs = {"evidence_id": arg}
104
+ elif tool_name == "get_footage":
105
+ kwargs = {"location": arg}
106
 
107
  result = self.game.use_tool(tool_name, **kwargs)
108
 
109
+ # Format the result nicely
110
+ evidence_data = format_tool_response(tool_name, arg, result, self.game.scenario)
 
 
111
 
112
  return {
113
  "action": "add_evidence",
 
116
 
117
  return None
118
 
119
+ def format_tool_response(tool_name, arg, result, scenario):
120
+ """Formats tool output into HTML and finds associated suspect."""
121
+ suspect_id = None
122
+ suspect_name = None
123
+ html = ""
124
+ title = f"Tool: {tool_name}"
125
+
126
+ # Helpers to find suspect
127
+ def find_by_phone(phone):
128
+ clean_input = "".join(filter(str.isdigit, str(phone)))
129
+ for s in scenario["suspects"]:
130
+ s_phone = "".join(filter(str.isdigit, str(s.get("phone_number", ""))))
131
+ if clean_input and s_phone.endswith(clean_input):
132
+ return s
133
+ return None
134
+
135
+ def find_by_name(name):
136
+ for s in scenario["suspects"]:
137
+ if s["name"].lower() == name.lower():
138
+ return s
139
+ return None
140
+
141
+ # Logic per tool
142
+ if tool_name == "get_location":
143
+ suspect = find_by_phone(arg)
144
+ if suspect:
145
+ suspect_id = suspect["id"]
146
+ suspect_name = suspect["name"]
147
+ title = f"πŸ“ Location Data"
148
+
149
+ if "history" in result:
150
+ html += "<ul>"
151
+ for entry in result["history"]:
152
+ html += f"<li>{entry}</li>"
153
+ html += "</ul>"
154
+ elif "description" in result:
155
+ html += f"<div><strong>Time:</strong> {result.get('timestamp')}</div>"
156
+ html += f"<div><strong>Loc:</strong> {result.get('description')}</div>"
157
+ elif "error" in result:
158
+ html += f"<div style='color:red'>{result['error']}</div>"
159
+ else:
160
+ html += str(result)
161
+
162
+ elif tool_name == "call_alibi":
163
+ suspect = find_by_phone(arg)
164
+ if suspect:
165
+ suspect_id = suspect["id"]
166
+ suspect_name = suspect["name"]
167
+ title = f"πŸ“ž Alibi Check"
168
+
169
+ if "error" in result:
170
+ html += f"<div style='color:red'>{result['error']}</div>"
171
+ else:
172
+ html += f"<div><strong>Contact:</strong> {result.get('contact_name')}</div>"
173
+ html += f"<div style='margin-top:5px; font-style:italic;'>\"{result.get('response')}\"</div>"
174
+ html += f"<div style='font-size:0.8em; color:#555'>Confidence: {result.get('confidence')}</div>"
175
+
176
+ elif tool_name == "get_dna_test":
177
+ title = "🧬 DNA Result"
178
+ if "primary_match" in result and result["primary_match"] != "Unknown":
179
+ suspect = find_by_name(result["primary_match"])
180
+ if suspect:
181
+ suspect_id = suspect["id"]
182
+ suspect_name = suspect["name"]
183
+
184
+ if "error" in result:
185
+ html += f"<div style='color:red'>{result['error']}</div>"
186
+ else:
187
+ html += f"<div><strong>Match:</strong> {result.get('primary_match')}</div>"
188
+ html += f"<div><strong>Confidence:</strong> {result.get('confidence')}</div>"
189
+ html += f"<div><strong>Notes:</strong> {result.get('notes')}</div>"
190
+
191
+ elif tool_name == "get_footage":
192
+ title = "πŸ“Ή Security Footage"
193
+ if "error" in result:
194
+ html += f"<div style='color:red'>{result['error']}</div>"
195
+ else:
196
+ html += f"<div><strong>Cam:</strong> {result.get('location')}</div>"
197
+ html += f"<div><strong>Time:</strong> {result.get('time_range')}</div>"
198
+ html += f"<div><strong>Visible:</strong> {', '.join(result.get('visible_people', []))}</div>"
199
+ html += f"<div><strong>Detail:</strong> {result.get('key_details')}</div>"
200
+
201
+ else:
202
+ html = str(result)
203
+
204
+ return {
205
+ "title": title,
206
+ "html_content": html,
207
+ "suspect_id": suspect_id,
208
+ "suspect_name": suspect_name
209
+ }
210
+
211
  session = GameSession()
212
 
213
  # --- Gradio App ---
ui/static/js/game_logic.js CHANGED
@@ -201,15 +201,50 @@ function sendUserMessage() {
201
  function addEvidenceToBoard(evidenceData, fixedX = null, fixedY = null) {
202
  const board = document.getElementById('evidence-board');
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  const item = document.createElement('div');
205
  item.className = 'evidence-item';
 
 
 
 
206
  if (evidenceData.type === 'file') {
207
  item.classList.add('case-file');
208
  item.innerHTML = evidenceData.description;
209
  } else {
 
 
 
 
 
 
210
  item.innerHTML = `
211
- <strong>${evidenceData.title || "Evidence"}</strong><br>
212
- ${evidenceData.description || "No details."}
 
 
 
213
  `;
214
  }
215
 
@@ -220,8 +255,8 @@ function addEvidenceToBoard(evidenceData, fixedX = null, fixedY = null) {
220
  y = fixedY;
221
  item.style.transform = 'rotate(-2deg)'; // Slight tilt for files
222
  } else {
223
- x = Math.floor(Math.random() * (board.clientWidth - 200));
224
- y = Math.floor(Math.random() * (board.clientHeight - 100));
225
  item.style.transform = `rotate(${Math.random() * 10 - 5}deg)`;
226
  }
227
 
 
201
  function addEvidenceToBoard(evidenceData, fixedX = null, fixedY = null) {
202
  const board = document.getElementById('evidence-board');
203
 
204
+ // Grouping Logic
205
+ if (evidenceData.suspect_id) {
206
+ const existingCard = document.querySelector(`.evidence-item[data-suspect-id="${evidenceData.suspect_id}"]`);
207
+ if (existingCard) {
208
+ const contentDiv = existingCard.querySelector('.evidence-content');
209
+ const newEntry = document.createElement('div');
210
+ newEntry.style.marginTop = "10px";
211
+ newEntry.style.borderTop = "1px dashed #888";
212
+ newEntry.style.paddingTop = "5px";
213
+ newEntry.innerHTML = `
214
+ <div style="font-size:0.9em; font-weight:bold; color:#555;">${evidenceData.title}</div>
215
+ ${evidenceData.html_content || evidenceData.description}
216
+ `;
217
+ contentDiv.appendChild(newEntry);
218
+
219
+ // Flash effect to show update
220
+ existingCard.style.backgroundColor = "#fff";
221
+ setTimeout(() => existingCard.style.backgroundColor = "var(--paper-color)", 300);
222
+ return;
223
+ }
224
+ }
225
+
226
  const item = document.createElement('div');
227
  item.className = 'evidence-item';
228
+ if (evidenceData.suspect_id) {
229
+ item.dataset.suspectId = evidenceData.suspect_id;
230
+ }
231
+
232
  if (evidenceData.type === 'file') {
233
  item.classList.add('case-file');
234
  item.innerHTML = evidenceData.description;
235
  } else {
236
+ // Standard Card Format
237
+ let header = evidenceData.title || "Evidence";
238
+ if (evidenceData.suspect_name) {
239
+ header = `πŸ“Œ ${evidenceData.suspect_name}`;
240
+ }
241
+
242
  item.innerHTML = `
243
+ <div style="border-bottom: 2px solid var(--ink-color); margin-bottom: 5px; font-weight: bold;">${header}</div>
244
+ <div class="evidence-content">
245
+ ${evidenceData.suspect_name ? `<div style="font-size:0.9em; font-weight:bold; color:#555;">${evidenceData.title}</div>` : ''}
246
+ ${evidenceData.html_content || evidenceData.description}
247
+ </div>
248
  `;
249
  }
250
 
 
255
  y = fixedY;
256
  item.style.transform = 'rotate(-2deg)'; // Slight tilt for files
257
  } else {
258
+ x = Math.floor(Math.random() * (board.clientWidth - 250));
259
+ y = Math.floor(Math.random() * (board.clientHeight - 150));
260
  item.style.transform = `rotate(${Math.random() * 10 - 5}deg)`;
261
  }
262