From 9cc06ca37bc7455934e4ddf3e2246bd068d7fe0e Mon Sep 17 00:00:00 2001 From: j Date: Mon, 13 Oct 2025 08:21:26 +1300 Subject: [PATCH] config: Add 34 files --- .gitignore | 20 +++ debug-benchmark.js | 75 ++++++++++ debug-benchmark2.js | 67 +++++++++ debug-pbtech.js | 82 +++++++++++ debug-pbtech2.js | 69 ++++++++++ debug-pbtech3.js | 77 +++++++++++ package.json | 18 +++ public/index.html | 291 +++++++++++++++++++++++++++++++++++++++ scrapers/cpubenchmark.js | 114 +++++++++++++++ scrapers/pbtech.js | 88 ++++++++++++ server.js | 87 ++++++++++++ test-14400f.js | 21 +++ test-5600.js | 31 +++++ test-all-matches.js | 53 +++++++ test-core-ultra.js | 26 ++++ test-matching.js | 38 +++++ test-xeon.js | 22 +++ 17 files changed, 1179 insertions(+) create mode 100644 .gitignore create mode 100644 debug-benchmark.js create mode 100644 debug-benchmark2.js create mode 100644 debug-pbtech.js create mode 100644 debug-pbtech2.js create mode 100644 debug-pbtech3.js create mode 100644 package.json create mode 100644 public/index.html create mode 100644 scrapers/cpubenchmark.js create mode 100644 scrapers/pbtech.js create mode 100644 server.js create mode 100644 test-14400f.js create mode 100644 test-5600.js create mode 100644 test-all-matches.js create mode 100644 test-core-ultra.js create mode 100644 test-matching.js create mode 100644 test-xeon.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d29a5ca --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +node_modules/ + +# Logs +*.log +npm-debug.log* + +# OS files +.DS_Store +Thumbs.db + +# IDE +.vscode/ +.idea/ +*.swp +*.swo + +# Environment variables +.env +.env.local diff --git a/debug-benchmark.js b/debug-benchmark.js new file mode 100644 index 0000000..2d7e05c --- /dev/null +++ b/debug-benchmark.js @@ -0,0 +1,75 @@ +const puppeteer = require('puppeteer'); + +async function debugBenchmark() { + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + console.log('Loading CPU benchmark page...'); + await page.goto('https://www.cpubenchmark.net/cpu_list.php', { + waitUntil: 'networkidle2', + timeout: 60000 + }); + + console.log('\n=== ANALYZING TABLE STRUCTURE ==='); + + const tableInfo = await page.evaluate(() => { + const tables = document.querySelectorAll('table'); + const rows = document.querySelectorAll('table tr'); + + // Get headers + const headerRow = document.querySelector('table tr'); + const headers = Array.from(headerRow?.querySelectorAll('th, td') || []) + .map(h => h.textContent.trim()); + + // Get first 5 data rows + const samples = []; + for (let i = 1; i < Math.min(6, rows.length); i++) { + const cells = rows[i].querySelectorAll('td'); + samples.push(Array.from(cells).map(c => c.textContent.trim())); + } + + // Search for Intel Core i7-14700 + const searchResults = []; + rows.forEach(row => { + const cells = row.querySelectorAll('td'); + if (cells.length >= 2) { + const name = cells[0]?.textContent?.trim(); + if (name && name.toLowerCase().includes('14700')) { + const score = cells[1]?.textContent?.trim(); + searchResults.push({ name, score }); + } + } + }); + + return { + tableCount: tables.length, + rowCount: rows.length, + headers: headers, + samples: samples, + search14700: searchResults + }; + }); + + console.log(`\nTables found: ${tableInfo.tableCount}`); + console.log(`Rows found: ${tableInfo.rowCount}`); + console.log(`\nHeaders: ${JSON.stringify(tableInfo.headers)}`); + + console.log('\nFirst 5 rows:'); + tableInfo.samples.forEach((row, i) => { + console.log(`Row ${i + 1}: ${JSON.stringify(row)}`); + }); + + console.log('\n=== SEARCH FOR 14700 CPUs ==='); + tableInfo.search14700.forEach(cpu => { + console.log(`${cpu.name}: ${cpu.score}`); + }); + + await browser.close(); +} + +debugBenchmark().catch(console.error); diff --git a/debug-benchmark2.js b/debug-benchmark2.js new file mode 100644 index 0000000..2556bee --- /dev/null +++ b/debug-benchmark2.js @@ -0,0 +1,67 @@ +const puppeteer = require('puppeteer'); + +async function debugBenchmark() { + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + console.log('Loading CPU benchmark page...'); + await page.goto('https://www.cpubenchmark.net/cpu_list.php', { + waitUntil: 'networkidle2', + timeout: 60000 + }); + + console.log('\n=== CHECKING MAIN TABLE ==='); + + const mainTable = await page.evaluate(() => { + // Find the main data table - it's usually the one with the most rows + const tables = Array.from(document.querySelectorAll('table')); + const mainTable = tables.reduce((largest, table) => { + const rowCount = table.querySelectorAll('tr').length; + const largestCount = largest?.querySelectorAll('tr').length || 0; + return rowCount > largestCount ? table : largest; + }); + + if (!mainTable) return null; + + // Get first row to understand structure + const firstDataRow = mainTable.querySelector('tr:nth-child(2), tbody tr:first-child'); + const cells = firstDataRow?.querySelectorAll('td, th'); + + const firstRowData = cells ? Array.from(cells).map(c => c.textContent.trim()) : []; + + // Try to extract data using different methods + const rows = mainTable.querySelectorAll('tr'); + const method1 = []; // Using td only + const method2 = []; // Using specific columns + + for (let i = 0; i < Math.min(5, rows.length); i++) { + const tds = rows[i].querySelectorAll('td'); + if (tds.length >= 2) { + method1.push({ + cpu: tds[0]?.textContent?.trim(), + score: tds[1]?.textContent?.trim() + }); + } + } + + return { + firstRowData, + method1 + }; + }); + + console.log('First row data:', mainTable.firstRowData); + console.log('\nMethod 1 (td[0] = name, td[1] = score):'); + mainTable.method1.forEach((row, i) => { + console.log(` ${i}: ${row.cpu} = ${row.score}`); + }); + + await browser.close(); +} + +debugBenchmark().catch(console.error); diff --git a/debug-pbtech.js b/debug-pbtech.js new file mode 100644 index 0000000..815752b --- /dev/null +++ b/debug-pbtech.js @@ -0,0 +1,82 @@ +const puppeteer = require('puppeteer'); + +async function debugPBTech() { + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + console.log('Loading PB Tech CPU page...'); + await page.goto('https://www.pbtech.co.nz/category/components/cpus', { + waitUntil: 'networkidle2', + timeout: 30000 + }); + + console.log('\n=== PAGE TITLE ==='); + const title = await page.title(); + console.log(title); + + console.log('\n=== EXTRACTING FIRST FEW PRODUCTS ==='); + + const products = await page.evaluate(() => { + const results = []; + + // Try to find all possible product containers + const selectors = [ + '.product-item', + '.product-card', + '[class*="product"]', + '.item', + 'article', + '[data-product-id]', + '.productbox', + '.productcard' + ]; + + for (const selector of selectors) { + const elements = document.querySelectorAll(selector); + if (elements.length > 0) { + results.push({ + selector: selector, + count: elements.length, + sample: elements[0]?.outerHTML?.substring(0, 500) + }); + } + } + + return results; + }); + + console.log('\nFound product containers:'); + products.forEach(p => { + console.log(`\nSelector: ${p.selector}`); + console.log(`Count: ${p.count}`); + console.log(`Sample HTML: ${p.sample}...`); + }); + + console.log('\n=== EXTRACTING DETAILED PRODUCT INFO ==='); + + const detailedInfo = await page.evaluate(() => { + // Get first product-like element + const product = document.querySelector('.product-item, .product-card, [class*="product"], .productbox, .productcard, article'); + + if (!product) return { error: 'No product found' }; + + return { + outerHTML: product.outerHTML.substring(0, 1500), + textContent: product.textContent.substring(0, 500), + classes: product.className, + id: product.id + }; + }); + + console.log('\nFirst product details:'); + console.log(JSON.stringify(detailedInfo, null, 2)); + + await browser.close(); +} + +debugPBTech().catch(console.error); diff --git a/debug-pbtech2.js b/debug-pbtech2.js new file mode 100644 index 0000000..d00e365 --- /dev/null +++ b/debug-pbtech2.js @@ -0,0 +1,69 @@ +const puppeteer = require('puppeteer'); + +async function debugPBTech() { + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + console.log('Loading PB Tech CPU page...'); + await page.goto('https://www.pbtech.co.nz/category/components/cpus', { + waitUntil: 'networkidle2', + timeout: 30000 + }); + + console.log('\n=== LOOKING FOR ACTUAL PRODUCT CARDS ==='); + + const info = await page.evaluate(() => { + // Look for cards/items that have both price and product ID + const buttons = document.querySelectorAll('[data-product-id]'); + const results = []; + + buttons.forEach((btn, index) => { + if (index >= 3) return; // Just first 3 + + const productId = btn.getAttribute('data-product-id'); + const price = btn.getAttribute('data-price'); + + // Try to find parent card/container + let parent = btn.closest('.card, .item, [class*="card"], article, .grid-item, .product-grid-item'); + if (!parent) { + parent = btn.parentElement?.parentElement?.parentElement; // Go up a few levels + } + + if (parent) { + const nameEl = parent.querySelector('h3, h4, h5, .title, [class*="title"], [class*="name"], a[title]'); + const priceEl = parent.querySelector('.price, [class*="price"], .cost'); + + results.push({ + productId: productId, + buttonPrice: price, + name: nameEl?.textContent?.trim() || nameEl?.getAttribute('title'), + priceText: priceEl?.textContent?.trim(), + parentHTML: parent.outerHTML.substring(0, 800), + parentClass: parent.className + }); + } + }); + + return results; + }); + + console.log('\nProduct details:'); + info.forEach((p, i) => { + console.log(`\n--- Product ${i + 1} ---`); + console.log(`Product ID: ${p.productId}`); + console.log(`Button Price: $${p.buttonPrice}`); + console.log(`Name: ${p.name}`); + console.log(`Price Text: ${p.priceText}`); + console.log(`Parent Class: ${p.parentClass}`); + console.log(`Parent HTML: ${p.parentHTML}...`); + }); + + await browser.close(); +} + +debugPBTech().catch(console.error); diff --git a/debug-pbtech3.js b/debug-pbtech3.js new file mode 100644 index 0000000..c27149c --- /dev/null +++ b/debug-pbtech3.js @@ -0,0 +1,77 @@ +const puppeteer = require('puppeteer'); + +async function debugPBTech() { + const browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + console.log('Loading PB Tech CPU page...'); + await page.goto('https://www.pbtech.co.nz/category/components/cpus', { + waitUntil: 'networkidle2', + timeout: 30000 + }); + + console.log('\n=== EXTRACTING PRODUCT INFO BETTER ==='); + + const info = await page.evaluate(() => { + const buttons = document.querySelectorAll('[data-product-id]'); + const results = []; + + buttons.forEach((btn, index) => { + if (index >= 3) return; + + const productId = btn.getAttribute('data-product-id'); + const price = btn.getAttribute('data-price'); + + // Go up several levels to find the card + let card = btn; + for (let i = 0; i < 10; i++) { + card = card.parentElement; + if (!card) break; + + // Check if this container has product info + const links = card.querySelectorAll('a'); + const hasProductLink = Array.from(links).some(a => + a.href && a.href.includes(productId) + ); + + if (hasProductLink) { + // Found the card! + const productLink = Array.from(links).find(a => a.href && a.href.includes(productId)); + + results.push({ + productId: productId, + price: price, + name: productLink?.textContent?.trim() || productLink?.title, + href: productLink?.href, + cardHTML: card.outerHTML.substring(0, 1200), + cardClass: card.className, + level: i + }); + break; + } + } + }); + + return results; + }); + + console.log('\nFound products:'); + info.forEach((p, i) => { + console.log(`\n--- Product ${i + 1} ---`); + console.log(`Product ID: ${p.productId}`); + console.log(`Price: $${p.price}`); + console.log(`Name: ${p.name}`); + console.log(`Link: ${p.href}`); + console.log(`Card level: ${p.level} parents up`); + console.log(`Card class: ${p.cardClass}`); + }); + + await browser.close(); +} + +debugPBTech().catch(console.error); diff --git a/package.json b/package.json new file mode 100644 index 0000000..ff3d743 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "cpu-price-performance", + "version": "1.0.0", + "description": "Compare CPUs from PB Tech NZ by performance per dollar", + "main": "server.js", + "scripts": { + "start": "node server.js", + "dev": "node server.js" + }, + "keywords": ["cpu", "benchmark", "price", "performance"], + "author": "", + "license": "MIT", + "dependencies": { + "express": "^4.18.2", + "puppeteer": "^24.15.0", + "cors": "^2.8.5" + } +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..d62d10f --- /dev/null +++ b/public/index.html @@ -0,0 +1,291 @@ + + + + + + CPU Performance per Dollar - PB Tech NZ + + + +
+

🏆 CPU Performance per Dollar

+

Compare CPUs from PB Tech NZ by performance per dollar

+ +
+ + +
+

📊 Analysis Progress

+
+
+ +
+

🎯 Results: Best Performance per Dollar

+
+
+
+
+ + + + diff --git a/scrapers/cpubenchmark.js b/scrapers/cpubenchmark.js new file mode 100644 index 0000000..e76000f --- /dev/null +++ b/scrapers/cpubenchmark.js @@ -0,0 +1,114 @@ +const puppeteer = require('puppeteer'); + +// Extract CPU model identifier with enough context to avoid false matches +function extractCPUModel(name) { + // Intel Core Ultra patterns: Core Ultra 5/7/9 XXXX + const ultraMatch = name.match(/\b(Core\s+Ultra\s+[579]\s+\w+[A-Z]?)\b/i); + if (ultraMatch) return ultraMatch[1]; + + // Intel patterns: Core i3-XXXX, Core i5-XXXX, etc. (include "Core" for specificity) + // Handle both "Core i5-14400F" and "Core i5 14400F" (with or without dash) + const intelMatch = name.match(/\b(Core\s+i[3579])-?\s*(\w+[A-Z]?)\b/i); + if (intelMatch) return `${intelMatch[1]}-${intelMatch[2]}`; + + // Intel Xeon patterns: Xeon Silver/Gold/Platinum XXXX + const xeonMatch = name.match(/\b(Xeon\s+(?:Silver|Gold|Platinum|Bronze)?\s*\w+[A-Z]?)\b/i); + if (xeonMatch) return xeonMatch[1]; + + // AMD Ryzen patterns: Ryzen X XXXXX (include series number for specificity) + const ryzenMatch = name.match(/\b(Ryzen\s+[3579]\s+\w+)/i); + if (ryzenMatch) return ryzenMatch[1]; + + // AMD Threadripper patterns: Threadripper XXXX + const threadripperMatch = name.match(/\b(Threadripper\s+\w+)/i); + if (threadripperMatch) return threadripperMatch[1]; + + return null; +} + +async function fetchBenchmarkData(progressCallback) { + let browser; + try { + progressCallback('Loading CPU benchmark database...'); + browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + const page = await browser.newPage(); + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + progressCallback('Fetching benchmark scores...'); + await page.goto('https://www.cpubenchmark.net/cpu_list.php', { + waitUntil: 'networkidle2', + timeout: 60000 + }); + + progressCallback('Parsing benchmark data...'); + + // Extract benchmark data from the table + const benchmarks = await page.evaluate(() => { + const data = {}; + const rows = document.querySelectorAll('table tr'); + + rows.forEach(row => { + const cells = row.querySelectorAll('td'); + if (cells.length >= 2) { + const cpuName = cells[0]?.textContent?.trim(); + const cpuMark = cells[1]?.textContent?.trim(); + + if (cpuName && cpuMark) { + const score = parseInt(cpuMark.replace(/,/g, '')); + if (!isNaN(score) && score > 0) { + data[cpuName] = score; + } + } + } + }); + + return data; + }); + + const count = Object.keys(benchmarks).length; + progressCallback(`Loaded ${count} CPU benchmarks`); + + await browser.close(); + return benchmarks; + + } catch (error) { + if (browser) { + await browser.close(); + } + progressCallback(`Error fetching benchmarks: ${error.message}`); + throw error; + } +} + +function findBenchmarkScore(cpuName, benchmarkData) { + // Try exact match first + if (benchmarkData[cpuName]) { + return benchmarkData[cpuName]; + } + + // Extract the CPU model identifier + const model = extractCPUModel(cpuName); + if (!model) return null; + + // Search for CPUs containing this model identifier + const modelLower = model.toLowerCase(); + + for (const [benchName, score] of Object.entries(benchmarkData)) { + const benchLower = benchName.toLowerCase(); + + // Check if the benchmark name contains the exact model + // Use word boundaries to avoid partial matches + const modelRegex = new RegExp(`\\b${modelLower.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i'); + if (modelRegex.test(benchLower)) { + return score; + } + } + + return null; +} + +module.exports = { fetchBenchmarkData, findBenchmarkScore }; diff --git a/scrapers/pbtech.js b/scrapers/pbtech.js new file mode 100644 index 0000000..2e296f0 --- /dev/null +++ b/scrapers/pbtech.js @@ -0,0 +1,88 @@ +const puppeteer = require('puppeteer'); + +async function scrapePBTechCPUs(progressCallback) { + let browser; + try { + progressCallback('Launching browser...'); + browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'] + }); + + progressCallback('Opening PB Tech CPU page...'); + const page = await browser.newPage(); + + // Set a realistic user agent + await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); + + progressCallback('Loading CPU listings...'); + await page.goto('https://www.pbtech.co.nz/category/components/cpus', { + waitUntil: 'networkidle2', + timeout: 30000 + }); + + progressCallback('Extracting CPU data...'); + + // Extract CPU data from the page + const cpus = await page.evaluate(() => { + const products = []; + + // Find all "Add to cart" buttons which have product data + const buttons = document.querySelectorAll('[data-product-id]'); + + buttons.forEach(btn => { + try { + const productId = btn.getAttribute('data-product-id'); + const price = parseFloat(btn.getAttribute('data-price')); + + // Find the product link that contains this product ID + let card = btn; + let name = null; + + // Go up the DOM tree to find the card containing the product link + for (let i = 0; i < 10; i++) { + card = card.parentElement; + if (!card) break; + + const links = card.querySelectorAll('a'); + const productLink = Array.from(links).find(a => + a.href && a.href.includes(productId) + ); + + if (productLink) { + name = productLink.textContent?.trim(); + break; + } + } + + if (name && price && !isNaN(price)) { + products.push({ + name: name, + price: price, + inStock: true, // If there's an "Add to cart" button, it's in stock + source: 'pbtech' + }); + } + } catch (err) { + // Skip problematic elements + } + }); + + return products; + }); + + progressCallback(`Found ${cpus.length} CPUs from PB Tech`); + + await browser.close(); + return cpus; + + } catch (error) { + if (browser) { + await browser.close(); + } + progressCallback(`Error scraping PB Tech: ${error.message}`); + throw error; + } +} + +module.exports = { scrapePBTechCPUs }; diff --git a/server.js b/server.js new file mode 100644 index 0000000..df53f0c --- /dev/null +++ b/server.js @@ -0,0 +1,87 @@ +const express = require('express'); +const cors = require('cors'); +const path = require('path'); +const { scrapePBTechCPUs } = require('./scrapers/pbtech'); +const { fetchBenchmarkData, findBenchmarkScore } = require('./scrapers/cpubenchmark'); + +const app = express(); +const PORT = process.env.PORT || 3000; + +app.use(cors()); +app.use(express.static('public')); + +// Server-Sent Events endpoint for real-time progress +app.get('/api/scrape', async (req, res) => { + // Set headers for SSE + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + + // Helper function to send progress updates + const sendProgress = (message) => { + res.write(`data: ${JSON.stringify({ type: 'progress', message })}\n\n`); + }; + + try { + sendProgress('Starting CPU comparison...'); + + // Fetch CPUs from PB Tech + sendProgress('Step 1/3: Fetching CPUs from PB Tech...'); + const cpus = await scrapePBTechCPUs(sendProgress); + + if (cpus.length === 0) { + sendProgress('No CPUs found on PB Tech. Please check the website.'); + res.write(`data: ${JSON.stringify({ type: 'error', message: 'No CPUs found' })}\n\n`); + res.end(); + return; + } + + // Fetch benchmark data + sendProgress('Step 2/3: Fetching CPU benchmarks...'); + const benchmarkData = await fetchBenchmarkData(sendProgress); + + // Match CPUs with benchmarks and calculate performance per dollar + sendProgress('Step 3/3: Calculating performance per dollar...'); + + const results = []; + for (let i = 0; i < cpus.length; i++) { + const cpu = cpus[i]; + const benchmark = findBenchmarkScore(cpu.name, benchmarkData); + + if (benchmark) { + const performancePerDollar = benchmark / cpu.price; + results.push({ + name: cpu.name, + price: cpu.price, + benchmark: benchmark, + performancePerDollar: performancePerDollar, + inStock: cpu.inStock + }); + } + + if ((i + 1) % 5 === 0) { + sendProgress(`Processed ${i + 1}/${cpus.length} CPUs...`); + } + } + + // Sort by performance per dollar (descending) + results.sort((a, b) => b.performancePerDollar - a.performancePerDollar); + + sendProgress(`Found ${results.length} CPUs with benchmark data!`); + sendProgress('Analysis complete!'); + + // Send final results + res.write(`data: ${JSON.stringify({ type: 'complete', data: results })}\n\n`); + res.end(); + + } catch (error) { + console.error('Scraping error:', error); + sendProgress(`Error: ${error.message}`); + res.write(`data: ${JSON.stringify({ type: 'error', message: error.message })}\n\n`); + res.end(); + } +}); + +app.listen(PORT, () => { + console.log(`Server running on http://localhost:${PORT}`); +}); diff --git a/test-14400f.js b/test-14400f.js new file mode 100644 index 0000000..089695a --- /dev/null +++ b/test-14400f.js @@ -0,0 +1,21 @@ +const { fetchBenchmarkData } = require('./scrapers/cpubenchmark'); + +async function test() { + const benchmarkData = await fetchBenchmarkData(console.log); + + console.log('\n=== Searching for 14400F ==='); + Object.keys(benchmarkData) + .filter(name => name.includes('14400')) + .forEach(name => { + console.log(`${name}: ${benchmarkData[name]}`); + }); + + console.log('\n=== Searching for 14700F ==='); + Object.keys(benchmarkData) + .filter(name => name.includes('14700')) + .forEach(name => { + console.log(`${name}: ${benchmarkData[name]}`); + }); +} + +test().catch(console.error); diff --git a/test-5600.js b/test-5600.js new file mode 100644 index 0000000..d20140b --- /dev/null +++ b/test-5600.js @@ -0,0 +1,31 @@ +const { fetchBenchmarkData, findBenchmarkScore } = require('./scrapers/cpubenchmark'); + +async function test5600() { + console.log('Fetching benchmark data...'); + const benchmarkData = await fetchBenchmarkData(console.log); + + const testCPU = "AMD Ryzen 5 5600 CPU 6 Core / 12 Thread - Max Boost 4.4GHz - 35MB Cache - AM4 Socket - 65W TDP - Heatsink Required"; + + console.log(`\nTesting: ${testCPU.substring(0, 50)}...`); + + const score = findBenchmarkScore(testCPU, benchmarkData); + console.log(`Found Score: ${score}`); + + // Check what CPUs have "5600" in them + console.log('\nAll CPUs with "5600" in name:'); + Object.keys(benchmarkData) + .filter(name => name.includes('5600')) + .forEach(name => { + console.log(` ${name}: ${benchmarkData[name]}`); + }); + + // Check specifically for Ryzen 5 5600 + console.log('\nCPUs with "Ryzen 5 5600":'); + Object.keys(benchmarkData) + .filter(name => name.includes('Ryzen 5 5600')) + .forEach(name => { + console.log(` ${name}: ${benchmarkData[name]}`); + }); +} + +test5600().catch(console.error); diff --git a/test-all-matches.js b/test-all-matches.js new file mode 100644 index 0000000..19b4298 --- /dev/null +++ b/test-all-matches.js @@ -0,0 +1,53 @@ +const { scrapePBTechCPUs } = require('./scrapers/pbtech'); +const { fetchBenchmarkData, findBenchmarkScore } = require('./scrapers/cpubenchmark'); + +async function testAllMatches() { + console.log('Fetching CPUs from PB Tech...'); + const cpus = await scrapePBTechCPUs(console.log); + + console.log('\nFetching benchmark data...'); + const benchmarkData = await fetchBenchmarkData(console.log); + + console.log(`\n=== Testing ${cpus.length} CPUs ===\n`); + + const matched = []; + const unmatched = []; + + cpus.forEach(cpu => { + const score = findBenchmarkScore(cpu.name, benchmarkData); + if (score) { + matched.push({ ...cpu, score }); + } else { + unmatched.push(cpu); + } + }); + + console.log(`✅ Matched: ${matched.length}/${cpus.length}`); + console.log(`❌ Unmatched: ${unmatched.length}/${cpus.length}\n`); + + if (unmatched.length > 0) { + console.log('=== UNMATCHED CPUs (first 10) ==='); + unmatched.slice(0, 10).forEach(cpu => { + console.log(`\nName: ${cpu.name.substring(0, 80)}`); + console.log(`Price: $${cpu.price}`); + + // Try to find similar CPUs in the benchmark database + const searchTerms = cpu.name.match(/\b(Ryzen|Core|Threadripper|Pentium|Celeron|Athlon)\s+\w+\s+\w+/i); + if (searchTerms) { + const similar = Object.keys(benchmarkData) + .filter(name => name.toLowerCase().includes(searchTerms[0].toLowerCase().split(' ')[0])) + .slice(0, 3); + if (similar.length > 0) { + console.log(`Similar in DB: ${similar.join(', ')}`); + } + } + }); + } + + console.log('\n=== SUCCESSFULLY MATCHED (first 10) ==='); + matched.slice(0, 10).forEach(cpu => { + console.log(`${cpu.name.substring(0, 60)}... → ${cpu.score} (${(cpu.score / cpu.price).toFixed(2)} perf/$)`); + }); +} + +testAllMatches().catch(console.error); diff --git a/test-core-ultra.js b/test-core-ultra.js new file mode 100644 index 0000000..757e38a --- /dev/null +++ b/test-core-ultra.js @@ -0,0 +1,26 @@ +const { fetchBenchmarkData } = require('./scrapers/cpubenchmark'); + +async function testCoreUltra() { + console.log('Fetching benchmark data...'); + const benchmarkData = await fetchBenchmarkData(console.log); + + console.log('\n=== Searching for Core Ultra CPUs ===\n'); + + // Search for different variations + const searches = ['Core Ultra', 'Ultra 5', 'Ultra 7', 'Ultra 9', '265K', '285K', '245K']; + + searches.forEach(search => { + const results = Object.keys(benchmarkData) + .filter(name => name.includes(search)) + .slice(0, 5); + + if (results.length > 0) { + console.log(`\n"${search}" found in:`); + results.forEach(name => { + console.log(` ${name}: ${benchmarkData[name]}`); + }); + } + }); +} + +testCoreUltra().catch(console.error); diff --git a/test-matching.js b/test-matching.js new file mode 100644 index 0000000..523f1fb --- /dev/null +++ b/test-matching.js @@ -0,0 +1,38 @@ +const { fetchBenchmarkData, findBenchmarkScore } = require('./scrapers/cpubenchmark'); + +async function testMatching() { + console.log('Fetching benchmark data...'); + + const benchmarkData = await fetchBenchmarkData(console.log); + + console.log(`\nLoaded ${Object.keys(benchmarkData).length} benchmarks\n`); + + // Test with sample CPU names from PB Tech + const testCPUs = [ + "AMD Ryzen 7 9800X3D CPU 8 Core / 16 Thread - 104MB Total Cache - AM5 Socket - 120W TDP - AMD Radeon Graphics - Heatsink Required", + "Intel Core i7-14700F CPU 20 Core (8P 12E) / 28 Thread - Max Boost 5.4GHz - 33MB Cache - LGA1700 Socket - 65W TDP - Heatsink Required", + "AMD Ryzen 5 9600X CPU 6 Core / 12 Thread - Max Boost 5.4GHz - 38MB Cache - AM5 Socket - 65W TDP - AMD Radeon Graphics - Heatsink Required", + "Intel Core i9-14900K CPU 24 Core (8P 16E) / 32 Thread - Max Boost 6.0GHz - 36MB Cache - LGA1700 Socket - 125W TDP - Intel UHD Graphics 770 - Heatsink Required" + ]; + + testCPUs.forEach(cpu => { + console.log(`\nPB Tech Name: ${cpu.substring(0, 60)}...`); + const score = findBenchmarkScore(cpu, benchmarkData); + console.log(`Found Score: ${score}`); + + // Also check what it should be + const cpuModel = cpu.match(/(?:Ryzen [579] \w+|Core i[3579]-\w+)/)?.[0]; + console.log(`Expected Model: ${cpuModel}`); + if (cpuModel) { + const exactMatches = Object.keys(benchmarkData) + .filter(name => name.includes(cpuModel)) + .slice(0, 3); + console.log(`Similar in database: ${exactMatches.join(', ')}`); + exactMatches.forEach(match => { + console.log(` - ${match}: ${benchmarkData[match]}`); + }); + } + }); +} + +testMatching().catch(console.error); diff --git a/test-xeon.js b/test-xeon.js new file mode 100644 index 0000000..5a90dfa --- /dev/null +++ b/test-xeon.js @@ -0,0 +1,22 @@ +const { fetchBenchmarkData } = require('./scrapers/cpubenchmark'); + +async function test() { + const benchmarkData = await fetchBenchmarkData(console.log); + + console.log('\n=== Searching for Xeon Silver 4510 ==='); + Object.keys(benchmarkData) + .filter(name => name.includes('4510')) + .forEach(name => { + console.log(`${name}: ${benchmarkData[name]}`); + }); + + console.log('\n=== Searching for "Xeon Silver" ==='); + Object.keys(benchmarkData) + .filter(name => name.includes('Xeon Silver')) + .slice(0, 10) + .forEach(name => { + console.log(`${name}: ${benchmarkData[name]}`); + }); +} + +test().catch(console.error);