From 312c5cb815f343cfef9a6b0a9a6aa54fac97b93a Mon Sep 17 00:00:00 2001 From: Rene Fichtmueller Date: Sat, 28 Mar 2026 01:00:52 +1300 Subject: [PATCH] fix: hype cycle findTechnology matched wrong tech (1G instead of 1.6T) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit findTechnology used loose includes() matching — '1.6T OSFP-XD' matched '1G SFP' first because query contained '1'. Now matches exact name first, then by speed prefix with proper unit parsing (G/T). --- packages/api/src/hype-cycle/norton-bass.ts | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/api/src/hype-cycle/norton-bass.ts b/packages/api/src/hype-cycle/norton-bass.ts index 35fa45f..a501622 100644 --- a/packages/api/src/hype-cycle/norton-bass.ts +++ b/packages/api/src/hype-cycle/norton-bass.ts @@ -458,11 +458,27 @@ export function computeAllHypeCycles( } export function findTechnology(query: string): TechGeneration | undefined { - const q = query.toLowerCase(); + const q = query.toLowerCase().trim(); const allTechs = [...TECH_GENERATIONS, ...SPECIAL_TECHS]; - return allTechs.find((t) => - t.name.toLowerCase().includes(q) || - q.includes(t.speedGbps.toString()) || - q.includes(t.formFactor.toLowerCase()) - ); + + // 1. Exact name match + const exact = allTechs.find((t) => t.name.toLowerCase() === q); + if (exact) return exact; + + // 2. Name contains query or query contains name + const nameMatch = allTechs.find((t) => t.name.toLowerCase().includes(q)); + if (nameMatch) return nameMatch; + + // 3. Fuzzy: match by speed prefix (e.g. "400G", "1.6T", "800G") + const speedMatch = q.match(/^(\d+(?:\.\d+)?)\s*(g|t)\b/i); + if (speedMatch) { + const num = parseFloat(speedMatch[1]); + const unit = speedMatch[2].toLowerCase(); + const targetGbps = unit === "t" ? num * 1000 : num; + const found = allTechs.find((t) => t.speedGbps === targetGbps); + if (found) return found; + } + + // 4. Match by form factor + return allTechs.find((t) => q.includes(t.formFactor.toLowerCase())); }