Spaces:
Sleeping
Sleeping
Fetching metadata from the HF Docker repository...
Ctrl+K
- src Update src/ocr_utils.py
- 1.52 kB Duplicate from streamlit/streamlit-template-space
- 525 Bytes Update Dockerfile
- 435 Bytes initial commit
- 3.04 kB Update ocr_utils.py
- 118 Bytes Update requirements.txt
- 0 Bytes # GoodFind β Simple Online Demo (Docker/Streamlit one-file) import streamlit as st import base64 from datetime import datetime st.set_page_config(page_title="GoodFind (Simple)", page_icon="π") st.title("π GoodFind β Simple Online Demo") st.caption("Zero-setup demo (no OCR/ML). Enter items & prices; I estimate fees/shipping and rank by profit.") # Simple keyword table (no external deps) PRICE_TABLE = { "wii": 85, "playstation": 120, "ps2": 75, "ps3": 110, "ps4": 160, "ps5": 350, "iphone": 240, "macbook": 450, "aeron": 500, "pyrex": 120, "le creuset": 240, "kitchenaid": 220, "bose": 140, "walkman": 95, "marantz": 400, "yeti": 18, "dansko": 40, "coach": 65, "levi": 28, "seiko": 95, "all-clad": 55, } DEFAULT_RESALE = 45.0 def quick_estimate(title: str) -> float: t = (title or "").lower() best = None for k, v in PRICE_TABLE.items(): if k in t: best = max(best or 0, v) return float(best if best else DEFAULT_RESALE) def score_deal(predicted_resale: float, ask: float, fee_rate: float = 0.13, ship: float = 12.0): fees = predicted_resale * fee_rate net = predicted_resale - fees - ship profit = net - ask margin = (profit / ask) if ask > 0 else 0.0 if profit >= 50 and margin >= 0.8: label = "Home Run" elif profit >= 25 and margin >= 0.5: label = "Great" elif profit >= 10 and margin >= 0.3: label = "Good" elif profit >= 5: label = "Meh" else: label = "Pass" return {"fees": round(fees, 2), "net_after_fees": round(net, 2), "profit": round(profit, 2), "margin": round(margin, 2), "label": label} # CSS for hover labels st.markdown(""" <style> .img-wrap{position:relative; display:inline-block; margin:8px; max-width:100%;} .img-wrap img{display:block; max-width:100%; height:auto; border-radius:6px; border:1px solid rgba(0,0,0,0.1);} .hover-label{ position:absolute; left:8px; top:8px; padding:4px 8px; border-radius:4px; background:rgba(0,0,0,0.65); color:#fff; font-size:0.9rem; opacity:0; transition:opacity .15s; pointer-events:none; } .img-wrap:hover .hover-label{opacity:1;} </style> """, unsafe_allow_html=True) tab1, tab2 = st.tabs(["Single check", "Group scan (manual)"]) # Single check with tab1: st.subheader("Quick deal check") title = st.text_input("Item title", placeholder="e.g., Nintendo Wii bundle with games") c1, c2, c3 = st.columns(3) with c1: ask = st.number_input("Asking price ($)", min_value=0.0, step=1.0, value=10.0) with c2: fees_rate = st.slider("Fees rate", 0.05, 0.20, 0.13, 0.01) with c3: ship = st.slider("Shipping estimate ($)", 0.0, 30.0, 12.0, 1.0) if st.button("Evaluate deal", type="primary"): resale = quick_estimate(title) s = score_deal(resale, ask, fees_rate, ship) st.markdown(f"### Estimated resale: **${resale:.2f}**") st.markdown(f"**Verdict:** {s['label']}") st.write({ "Fees ($)": s["fees"], "Net after fees+ship ($)": s["net_after_fees"], "Profit ($)": s["profit"], "Margin on ask": s["margin"], }) # Group scan (manual) with tab2: st.subheader("Group scan: upload photos, type names & prices") st.caption("No OCR in this simple demo. Enter a short name + price for each photo; I'll rank by profit.") fees_rate_g = st.slider("Fees rate (apply to all)", 0.05, 0.20, 0.13, 0.01, key="fees_group") ship_g = st.slider("Shipping estimate ($, apply to all)", 0.0, 30.0, 12.0, 1.0, key="ship_group") photos = st.file_uploader("Upload photos", type=["jpg","jpeg","png","webp"], accept_multiple_files=True) items = [] if photos: for i, img in enumerate(photos): data = img.read() with st.expander(f"Photo {i+1}"): st.image(data, use_column_width=True) c1, c2 = st.columns([2,1]) with c1: name = st.text_input(f"Item name #{i+1}", placeholder="e.g., Bose QC35 headphones", key=f"name_{i}") with c2: price_txt = st.text_input(f"Asking price #{i+1} ($)", placeholder="e.g., 25.00", key=f"price_{i}") items.append((name, price_txt, data, img.type or "image/jpeg")) if st.button("Evaluate group", type="primary"): rows = [] gallery_blocks = [] for idx, (name, price_txt, data, mime) in enumerate(items): if not (name and name.strip()): name = f"Item {idx+1}" try: ask_i = float(price_txt) if price_txt.strip() else 0.0 except: ask_i = 0.0 resale = quick_estimate(name) s = score_deal(resale, ask_i, fees_rate_g, ship_g) rows.append({"title": name, "ask": ask_i, "resale": resale, **s}) b64 = base64.b64encode(data).decode("utf-8") gallery_blocks.append(f""" <div class="img-wrap" title="{name}"> <img src="data:{mime};base64,{b64}" alt="{name}"/> <span class="hover-label">{name}</span> </div> """) if rows: rows.sort(key=lambda r: (r["profit"], r["resale"]), reverse=True) st.markdown("### Ranked results") st.table([ {"Title": r["title"], "Ask ($)": f"{r['ask']:.2f}", "Est. resale ($)": f"{r['resale']:.2f}", "Profit ($)": f"{r['profit']:.2f}", "Margin": f"{r['margin']:.2f}", "Verdict": r["label"]} for r in rows ]) top = rows[0] st.success(f"Top pick: **{top['title']}** β resale ${top['resale']:.0f}, profit ${top['profit']:.0f} ({top['label']})") st.markdown("### Hover over each image to see the item name") st.markdown("".join(gallery_blocks), unsafe_allow_html=True)
- 6.56 kB Update valuation