buzzbandit commited on
Commit
ff717eb
Β·
verified Β·
1 Parent(s): ce0378e

fix missing convenience buttons

Browse files
Files changed (1) hide show
  1. app.py +58 -41
app.py CHANGED
@@ -44,15 +44,13 @@ def load_cached_embeddings():
44
  with open(META_FILE, "r", encoding="utf-8") as f:
45
  meta = json.load(f)
46
  if meta.get("items_mtime") != ITEM_FILE_MTIME:
47
- print("⚠️ items.json changed β€” rebuilding category embeddings.")
48
  return None, None
49
  with open(ALIASES_FILE, "r", encoding="utf-8") as f:
50
  aliases = json.load(f)
51
  embeds = torch.load(EMB_FILE)
52
  print("βœ… Loaded cached category embeddings.")
53
  return aliases, embeds
54
- except Exception as e:
55
- print(f"⚠️ Cache load failed: {e}")
56
  return None, None
57
 
58
  def save_cached_embeddings(aliases, embeds):
@@ -62,7 +60,6 @@ def save_cached_embeddings(aliases, embeds):
62
  torch.save(embeds, EMB_FILE)
63
  with open(META_FILE, "w", encoding="utf-8") as f:
64
  json.dump({"items_mtime": ITEM_FILE_MTIME, "time": time.time()}, f)
65
- print("πŸ’Ύ Cached category embeddings saved.")
66
  except Exception as e:
67
  print(f"⚠️ Cache save failed: {e}")
68
 
@@ -70,17 +67,11 @@ def auto_alias_categories(embedder, all_categories, all_item_names, top_k=6, thr
70
  print("πŸ€– Building category aliases dynamically...")
71
  cat_embs = {c: embedder.encode(c, convert_to_tensor=True) for c in all_categories}
72
  item_embs = {i: embedder.encode(i, convert_to_tensor=True) for i in all_item_names}
73
-
74
  aliases = {}
75
  for cat, cat_emb in cat_embs.items():
76
  sims = {i: float(util.cos_sim(cat_emb, emb)) for i, emb in item_embs.items()}
77
- top_related = [
78
- i for i, s in sorted(sims.items(), key=lambda x: x[1], reverse=True)[:top_k]
79
- if s > threshold
80
- ]
81
  aliases[cat] = list(set([cat] + top_related))
82
- preview = ", ".join(top_related[:3])
83
- print(f" 🧩 {cat:<10} β†’ {len(top_related)} aliases ({preview})")
84
  return aliases
85
 
86
  CATEGORY_ALIASES, CATEGORY_EMBEDS = load_cached_embeddings()
@@ -121,11 +112,10 @@ def normalize_country_query(q: str) -> str | None:
121
 
122
  # ---------------- Helpers ----------------
123
  def parse_freeform_query(text: str):
124
- """Supports 'plushies in uk' and 'uk plushies'."""
125
  if not text:
126
  return "", ""
127
  text = text.strip().lower()
128
- m = re.match(r"(.+?)\s+in\s+(.+)", text, flags=re.IGNORECASE)
129
  if m:
130
  return m.group(1).strip(), m.group(2).strip()
131
  parts = text.split()
@@ -137,7 +127,6 @@ def parse_freeform_query(text: str):
137
  return first, second
138
  return text, ""
139
 
140
- # ---------------- Semantic Match ----------------
141
  def semantic_match(query, top_k=15):
142
  if not query:
143
  return {"category": None, "items": []}
@@ -166,9 +155,8 @@ def fetch_yata(force_refresh=False):
166
  _cache.update({
167
  "data": data,
168
  "timestamp": time.time(),
169
- "last_update": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) # UTC ISO
170
  })
171
- print(f"βœ… Fetched YATA data at {_cache['last_update']}")
172
  return data, _cache["last_update"]
173
  except Exception as e:
174
  print(f"❌ Fetch error: {e}")
@@ -186,7 +174,6 @@ def get_live_categories(data):
186
 
187
  # ---------------- Core logic ----------------
188
  def query_inventory(query_text="", category="", country_name="", capacity=10, refresh=False):
189
- print(f"πŸ”Ž Query received: '{query_text}', category='{category}', country='{country_name}', cap={capacity}")
190
  data, last_update = fetch_yata(force_refresh=refresh)
191
  rows = []
192
  parsed_item, parsed_country = parse_freeform_query(query_text)
@@ -201,10 +188,9 @@ def query_inventory(query_text="", category="", country_name="", capacity=10, re
201
  code = code_raw.upper()
202
  cname = COUNTRY_NAMES.get(code, code)
203
  if country_name:
204
- if user_code:
205
- if code != user_code:
206
- continue
207
- elif country_name.lower() not in cname.lower():
208
  continue
209
  update_ts = cdata.get("update")
210
  update_str = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(update_ts)) if update_ts else "Unknown"
@@ -213,16 +199,11 @@ def query_inventory(query_text="", category="", country_name="", capacity=10, re
213
  itype = ITEM_TO_TYPE.get(iname, "").lower()
214
  qty = item.get("quantity", 0)
215
  cost = item.get("cost", 0)
216
- if item_term:
217
- item_ok = (
218
- item_term.lower() in iname.lower()
219
- or iname in semantic_items
220
- or (semantic_category and itype == semantic_category.lower())
221
- )
222
- elif category:
223
- item_ok = category.lower() == itype
224
- else:
225
- item_ok = True
226
  if item_ok:
227
  rows.append({
228
  "Country": cname,
@@ -247,24 +228,62 @@ def run_query(query_text, category, country, capacity, refresh):
247
  live_categories = get_live_categories(data)
248
  return df, ts, gr.update(choices=[""] + live_categories)
249
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  # ---------------- Gradio UI ----------------
251
- with gr.Blocks(title="🧳 Torn Inventory Viewer") as iface:
252
- gr.Markdown("## 🧳 Torn Inventory Viewer")
253
- gr.Markdown("_Search Torn YATA travel stocks β€” timestamps shown in your local timezone._")
254
 
255
- query_box = gr.Textbox(label="Search (semantic, e.g. 'flowers in England')", elem_id="qbox")
256
- category_drop = gr.Dropdown(label="Category (optional exact match)", choices=[""] + ALL_CATEGORIES, elem_id="catdrop")
257
- country_box = gr.Textbox(label="Country (optional, e.g. UK, Cayman, Japan)", elem_id="countrybox")
258
- capacity_slider = gr.Number(label="Travel Capacity", value=10, minimum=5, maximum=88, precision=0, elem_id="cap_num")
259
  refresh_check = gr.Checkbox(label="Force refresh (ignore cache)", value=False)
260
 
 
 
 
 
 
 
 
261
  result_df = gr.Dataframe(label="Results")
262
  meta_box = gr.Textbox(label="Metadata / Last Update")
263
-
264
  run_btn = gr.Button("πŸ” Search / Refresh")
 
265
  run_btn.click(run_query, inputs=[query_box, category_drop, country_box, capacity_slider, refresh_check],
266
  outputs=[result_df, meta_box, category_drop])
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  # --- JS for local time conversion ---
269
  gr.HTML("""
270
  <script>
@@ -291,9 +310,7 @@ with gr.Blocks(title="🧳 Torn Inventory Viewer") as iface:
291
  """)
292
 
293
  try:
294
- print("βœ… App initialized successfully β€” launching UI...")
295
  iface.launch()
296
  except Exception as e:
297
  import traceback
298
- print("❌ Application failed to start:")
299
  traceback.print_exc()
 
44
  with open(META_FILE, "r", encoding="utf-8") as f:
45
  meta = json.load(f)
46
  if meta.get("items_mtime") != ITEM_FILE_MTIME:
 
47
  return None, None
48
  with open(ALIASES_FILE, "r", encoding="utf-8") as f:
49
  aliases = json.load(f)
50
  embeds = torch.load(EMB_FILE)
51
  print("βœ… Loaded cached category embeddings.")
52
  return aliases, embeds
53
+ except Exception:
 
54
  return None, None
55
 
56
  def save_cached_embeddings(aliases, embeds):
 
60
  torch.save(embeds, EMB_FILE)
61
  with open(META_FILE, "w", encoding="utf-8") as f:
62
  json.dump({"items_mtime": ITEM_FILE_MTIME, "time": time.time()}, f)
 
63
  except Exception as e:
64
  print(f"⚠️ Cache save failed: {e}")
65
 
 
67
  print("πŸ€– Building category aliases dynamically...")
68
  cat_embs = {c: embedder.encode(c, convert_to_tensor=True) for c in all_categories}
69
  item_embs = {i: embedder.encode(i, convert_to_tensor=True) for i in all_item_names}
 
70
  aliases = {}
71
  for cat, cat_emb in cat_embs.items():
72
  sims = {i: float(util.cos_sim(cat_emb, emb)) for i, emb in item_embs.items()}
73
+ top_related = [i for i, s in sorted(sims.items(), key=lambda x: x[1], reverse=True)[:top_k] if s > threshold]
 
 
 
74
  aliases[cat] = list(set([cat] + top_related))
 
 
75
  return aliases
76
 
77
  CATEGORY_ALIASES, CATEGORY_EMBEDS = load_cached_embeddings()
 
112
 
113
  # ---------------- Helpers ----------------
114
  def parse_freeform_query(text: str):
 
115
  if not text:
116
  return "", ""
117
  text = text.strip().lower()
118
+ m = re.match(r"(.+?)\\s+in\\s+(.+)", text, flags=re.IGNORECASE)
119
  if m:
120
  return m.group(1).strip(), m.group(2).strip()
121
  parts = text.split()
 
127
  return first, second
128
  return text, ""
129
 
 
130
  def semantic_match(query, top_k=15):
131
  if not query:
132
  return {"category": None, "items": []}
 
155
  _cache.update({
156
  "data": data,
157
  "timestamp": time.time(),
158
+ "last_update": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
159
  })
 
160
  return data, _cache["last_update"]
161
  except Exception as e:
162
  print(f"❌ Fetch error: {e}")
 
174
 
175
  # ---------------- Core logic ----------------
176
  def query_inventory(query_text="", category="", country_name="", capacity=10, refresh=False):
 
177
  data, last_update = fetch_yata(force_refresh=refresh)
178
  rows = []
179
  parsed_item, parsed_country = parse_freeform_query(query_text)
 
188
  code = code_raw.upper()
189
  cname = COUNTRY_NAMES.get(code, code)
190
  if country_name:
191
+ if user_code and code != user_code:
192
+ continue
193
+ elif not user_code and country_name.lower() not in cname.lower():
 
194
  continue
195
  update_ts = cdata.get("update")
196
  update_str = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(update_ts)) if update_ts else "Unknown"
 
199
  itype = ITEM_TO_TYPE.get(iname, "").lower()
200
  qty = item.get("quantity", 0)
201
  cost = item.get("cost", 0)
202
+ item_ok = (
203
+ (item_term and (item_term.lower() in iname.lower() or iname in semantic_items or (semantic_category and itype == semantic_category.lower())))
204
+ or (category and category.lower() == itype)
205
+ or (not item_term and not category)
206
+ )
 
 
 
 
 
207
  if item_ok:
208
  rows.append({
209
  "Country": cname,
 
228
  live_categories = get_live_categories(data)
229
  return df, ts, gr.update(choices=[""] + live_categories)
230
 
231
+ def run_multi(searches, capacity):
232
+ dfs = []
233
+ for q in searches:
234
+ df, _ = query_inventory(q, "", "", capacity, False)
235
+ dfs.append(df)
236
+ merged = pd.concat(dfs, ignore_index=True)
237
+ total = pd.DataFrame([{
238
+ "Country": "β€”", "Item": "TOTAL", "Category": "",
239
+ "Quantity": merged["Quantity"].replace(",", "", regex=True).astype(float).sum(),
240
+ "Cost": "", "Max Capacity Cost": "", "Updated": ""
241
+ }])
242
+ merged = pd.concat([merged, total])
243
+ return merged, f"Last update: {time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())}"
244
+
245
  # ---------------- Gradio UI ----------------
246
+ with gr.Blocks(title="🧳 Torn Foreign Stocks") as iface:
247
+ gr.Markdown("## 🧳 Torn Foreign Stocks")
248
+ gr.Markdown("_Search YATA's foreign stocks data_")
249
 
250
+ query_box = gr.Textbox(label="Search (semantic, e.g. 'flowers in England')")
251
+ category_drop = gr.Dropdown(label="Category (optional exact match)", choices=[""] + ALL_CATEGORIES)
252
+ country_box = gr.Textbox(label="Country (optional, e.g. UK, Cayman, Japan)")
253
+ capacity_slider = gr.Number(label="Travel Capacity", value=10, minimum=5, maximum=88, precision=0)
254
  refresh_check = gr.Checkbox(label="Force refresh (ignore cache)", value=False)
255
 
256
+ with gr.Row():
257
+ btn_short = gr.Button("🌸 Flushies (short haul)")
258
+ btn_medium = gr.Button("🧸 Flushies (medium haul)")
259
+ btn_long = gr.Button("🎁 Flushies (long haul)")
260
+ btn_xanax = gr.Button("πŸ’Š Xanax (SA)")
261
+ btn_temps = gr.Button("🧨 Temps")
262
+
263
  result_df = gr.Dataframe(label="Results")
264
  meta_box = gr.Textbox(label="Metadata / Last Update")
 
265
  run_btn = gr.Button("πŸ” Search / Refresh")
266
+
267
  run_btn.click(run_query, inputs=[query_box, category_drop, country_box, capacity_slider, refresh_check],
268
  outputs=[result_df, meta_box, category_drop])
269
 
270
+ btn_short.click(lambda c: run_multi(["flowers in mexico", "flowers in cayman islands", "flowers in canada",
271
+ "plushies in mexico", "plushies in cayman islands", "plushies in canada"], c),
272
+ inputs=[capacity_slider], outputs=[result_df, meta_box])
273
+ btn_medium.click(lambda c: run_multi(["flowers in hawaii", "flowers in united kingdom", "flowers in argentina",
274
+ "flowers in switzerland", "flowers in japan",
275
+ "plushies in hawaii", "plushies in united kingdom", "plushies in argentina",
276
+ "plushies in switzerland", "plushies in japan"], c),
277
+ inputs=[capacity_slider], outputs=[result_df, meta_box])
278
+ btn_long.click(lambda c: run_multi(["flowers in uae", "flowers in china", "flowers in south africa",
279
+ "plushies in uae", "plushies in china", "plushies in south africa"], c),
280
+ inputs=[capacity_slider], outputs=[result_df, meta_box])
281
+ btn_xanax.click(lambda c: run_multi(["xanax in south africa"], c),
282
+ inputs=[capacity_slider], outputs=[result_df, meta_box])
283
+ btn_temps.click(lambda c: run_multi(["tear gas in argentina", "smoke grenade in south africa",
284
+ "flash grenade in switzerland"], c),
285
+ inputs=[capacity_slider], outputs=[result_df, meta_box])
286
+
287
  # --- JS for local time conversion ---
288
  gr.HTML("""
289
  <script>
 
310
  """)
311
 
312
  try:
 
313
  iface.launch()
314
  except Exception as e:
315
  import traceback
 
316
  traceback.print_exc()