← back to Dw Yolo Loop
scripts/zero-sample-sweep/zero-sample-sweep-v2.mjs
69 lines
// zero-sample-sweep-v2 — READ-ONLY, $0. Cycle 68 (officer-specified P1 sizing).
// v1 FAILED coverage: global /products.json caps at page 100 (~25k of ~74k) and the
// known 111 RL $0-Sample positives sit BEYOND that cap → v1 found 0 and its own negative
// control flagged "RL not reproduced". v2 enumerates the catalog by COLLECTION (the 572
// collections collectively cover the catalog), pages each, DEDUPES products by id, and
// classifies by the P1 signature: single-variant + title~"Sample" + price $0 + available.
// NEGATIVE CONTROL (hard gate): must reproduce RL ~111; if it doesn't, coverage is still
// incomplete and the total is a LOWER BOUND (stated as such).
// EXCLUDES Phillip Jeffries.
const WWW='https://www.designerwallcoverings.com';
const UA='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36';
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
async function get(u){for(let a=0;a<5;a++){const r=await fetch(u,{headers:{'User-Agent':UA}});if(r.status===429){await sleep(2500*(a+1));continue;}return{status:r.status,text:await r.text()};}return{status:429,text:''};}
const PJ=/phillip[- ]?jeffries/i;
const isSample=t=>/sample/i.test(t||'');
function classify(p){ const vs=p.variants||[]; if(vs.length!==1) return 'multi'; const price=parseFloat(vs[0].price); if(isNaN(price)) return 'multi';
if(!isSample(vs[0].title)) return price===0?'zero-nonsample':'ok-single';
if(price===0) return 'zero-sample'; if(price===4.25) return 'ok-425'; return 'abnormal-sample'; }
// collection handles from the en collections sitemap
const idx=await get(`${WWW}/sitemap.xml`);
const collMaps=[...idx.text.matchAll(/<loc>([^<]+sitemap_collections_\d+\.xml[^<]*)<\/loc>/g)].map(m=>m[1].replace(/&/g,'&')).filter(u=>!/\/en-(ca|gb)\//.test(u));
let colls=[]; for(const sm of collMaps){ const x=await get(sm); colls.push(...[...x.text.matchAll(/<loc>[^<]*\/collections\/([^<\/?]+)/g)].map(m=>m[1])); }
colls=[...new Set(colls)];
console.log(`=== zero-sample-sweep-v2 (READ-ONLY, $0) ===\nenumerating ${colls.length} collections, deduped by product id (PJ excluded)\n`);
const seen=new Map(); // id -> classification (dedupe across collections)
const vendorOf=new Map();
let reqs=0, collDone=0;
for(const h of colls){
let page=1;
while(page<=12){
const r=await get(`${WWW}/collections/${h}/products.json?limit=250&page=${page}`); reqs++;
let ps=[]; try{ps=JSON.parse(r.text).products||[];}catch{break;}
if(ps.length===0) break;
for(const p of ps){ if(PJ.test(p.vendor||'')) continue; if(!seen.has(p.id)){ seen.set(p.id,classify(p)); vendorOf.set(p.id,p.vendor||'(none)'); } }
page++; await sleep(120);
}
collDone++;
if(collDone%80===0){ let zs=0; for(const c of seen.values()) if(c==='zero-sample')zs++; console.log(` ${collDone}/${colls.length} collections | unique products=${seen.size} | zero-sample=${zs}`); }
}
// tally
let zeroSample=0, abnormal=0, zeroNon=0, ok425=0, okSingle=0, multi=0;
const vendZero={}, vendAbn={};
for(const [id,c] of seen){ const v=vendorOf.get(id);
if(c==='zero-sample'){ zeroSample++; vendZero[v]=(vendZero[v]||0)+1; }
else if(c==='abnormal-sample'){ abnormal++; vendAbn[v]=(vendAbn[v]||0)+1; }
else if(c==='zero-nonsample') zeroNon++;
else if(c==='ok-425') ok425++; else if(c==='ok-single') okSingle++; else multi++;
}
console.log(`\n=== RESULTS (unique products across all collections: ${seen.size}; HTTP reqs: ${reqs}) ===`);
console.log(` ZERO-SAMPLE (P1 free-checkout signature): ${zeroSample}`);
console.log(` abnormal-sample (single Sample, non-$0/non-$4.25): ${abnormal}`);
console.log(` zero-NONsample (single $0, not titled Sample): ${zeroNon}`);
console.log(` ok $4.25 sample: ${ok425} | ok single: ${okSingle} | multi: ${multi}`);
console.log(`\n vendors with ZERO-SAMPLE bug:`);
Object.entries(vendZero).sort((a,b)=>b[1]-a[1]).forEach(([v,n])=>console.log(` ${v}: ${n}`));
if(Object.keys(vendAbn).length){ console.log(` vendors with abnormal-sample price:`); Object.entries(vendAbn).sort((a,b)=>b[1]-a[1]).slice(0,12).forEach(([v,n])=>console.log(` ${v}: ${n}`)); }
const rl=Object.entries(vendZero).filter(([v])=>/ralph/i.test(v)).reduce((s,[,n])=>s+n,0);
console.log(`\n-- NEGATIVE CONTROL (coverage gate) --`);
console.log(` Ralph Lauren zero-sample reproduced: ${rl} (c67 found 111) → ${rl>=100?'COVERAGE OK — total is a credible fleet count':rl>0?'PARTIAL — total is a LOWER BOUND':'FAILED — RL not covered, total unreliable'}`);
console.log(` unique products covered: ${seen.size} of ~74k (${(100*seen.size/74000).toFixed(0)}%)`);
import fs from 'fs';
fs.writeFileSync('/tmp/zero-sample-sweep-v2.json',JSON.stringify({ts:new Date().toISOString(),collections:colls.length,uniqueProducts:seen.size,reqs,zeroSample,abnormal,zeroNon,ok425,okSingle,multi,vendZero,vendAbn,rlReproduced:rl},null,2));
console.log('\nwrote /tmp/zero-sample-sweep-v2.json');