/** * Deterministic “live” metrics per product id — stable across refresh/build. */ export type ProductTestimonial = { handle: string; text: string; rating: number; daysAgo: number; }; export type ProductSocialMetrics = { avgRating: number; reviewCount: number; purchaseCount: number; /** Decorative hook — looks like marketplace activity */ boughtLast24h: number; testimonials: ProductTestimonial[]; }; function hash32(s: string): number { let h = 2166136261; for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619); } return h >>> 0; } function pick(arr: T[], seed: number): T { return arr[seed % arr.length]!; } const HANDLE_SUFFIXES = [ "_void", "Buyer", "anon_op", "ledger_rat", "EU_mix", "PacificMesh", "tor_only", "no_logs_99", "ghost_cart", "relay_7", ]; const SNIPPETS: { text: string; r: number }[] = [ { text: "Sealed exactly as pictured. Seller answered in under an hour.", r: 5 }, { text: "Third order from this stall — consistent every time.", r: 5 }, { text: "A bit slow on weekend but tracking matched mirror policy.", r: 4 }, { text: "PGP match checked out. Product matches batch notes.", r: 5 }, { text: "Pricey vs clearnet dupes but opsec packaging is on point.", r: 4 }, { text: "Had a dispute; escrow released after proof — fair outcome.", r: 4 }, { text: "Arrived faster than quoted. Will re-up next drop.", r: 5 }, { text: "Not for everyone but description was honest — no BS.", r: 4 }, { text: "Comms terse but professional. Goods matched listing.", r: 5 }, { text: "Verified canary before order — same fingerprint as hub post.", r: 5 }, { text: "Mixed feelings on shipping lane but item intact.", r: 4 }, { text: "Solid vendor thread history. SKU lived up to hype.", r: 5 }, ]; export function getProductSocialMetrics(productId: string): ProductSocialMetrics { const h = hash32(productId); const h2 = hash32(`${productId}:reviews`); const h3 = hash32(`${productId}:buyers`); const avgRating = Math.round((4.05 + (h % 90) / 100) * 100) / 100; const reviewCount = 24 + (h2 % 1_247); const purchaseCount = 180 + (h3 % 24_500); const boughtLast24h = 8 + (h2 % 214); let i1 = h % SNIPPETS.length; let i2 = (h2 + 5) % SNIPPETS.length; if (i2 === i1) i2 = (i2 + 1) % SNIPPETS.length; let i3 = (h3 + 11) % SNIPPETS.length; if (i3 === i1 || i3 === i2) i3 = (i3 + 1) % SNIPPETS.length; if (i3 === i1) i3 = (i3 + 1) % SNIPPETS.length; const t1 = SNIPPETS[i1]!; const t2 = SNIPPETS[i2]!; const t3 = SNIPPETS[i3]!; const mkHandle = (seed: number) => { const base = pick(["x", "q", "v", "k", "m", "s", "z", "r"], seed); return `${base}${(seed % 900) + 100}${pick(HANDLE_SUFFIXES, seed + 11)}`; }; const testimonials: ProductTestimonial[] = [ { handle: mkHandle(h), text: t1.text, rating: t1.r, daysAgo: 1 + (h % 6), }, { handle: mkHandle(h2), text: t2.text, rating: t2.r, daysAgo: 7 + (h2 % 20), }, { handle: mkHandle(h3), text: t3.text, rating: t3.r, daysAgo: 14 + (h3 % 45), }, ]; return { avgRating, reviewCount, purchaseCount, boughtLast24h, testimonials, }; }