diff --git a/.gitignore b/.gitignore
index 438657a..b67f46b 100644
Binary files a/.gitignore and b/.gitignore differ
diff --git a/coverage/base.css b/coverage/base.css
new file mode 100644
index 0000000..f418035
--- /dev/null
+++ b/coverage/base.css
@@ -0,0 +1,224 @@
+body, html {
+ margin:0; padding: 0;
+ height: 100%;
+}
+body {
+ font-family: Helvetica Neue, Helvetica, Arial;
+ font-size: 14px;
+ color:#333;
+}
+.small { font-size: 12px; }
+*, *:after, *:before {
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing:border-box;
+ box-sizing:border-box;
+ }
+h1 { font-size: 20px; margin: 0;}
+h2 { font-size: 14px; }
+pre {
+ font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ margin: 0;
+ padding: 0;
+ -moz-tab-size: 2;
+ -o-tab-size: 2;
+ tab-size: 2;
+}
+a { color:#0074D9; text-decoration:none; }
+a:hover { text-decoration:underline; }
+.strong { font-weight: bold; }
+.space-top1 { padding: 10px 0 0 0; }
+.pad2y { padding: 20px 0; }
+.pad1y { padding: 10px 0; }
+.pad2x { padding: 0 20px; }
+.pad2 { padding: 20px; }
+.pad1 { padding: 10px; }
+.space-left2 { padding-left:55px; }
+.space-right2 { padding-right:20px; }
+.center { text-align:center; }
+.clearfix { display:block; }
+.clearfix:after {
+ content:'';
+ display:block;
+ height:0;
+ clear:both;
+ visibility:hidden;
+ }
+.fl { float: left; }
+@media only screen and (max-width:640px) {
+ .col3 { width:100%; max-width:100%; }
+ .hide-mobile { display:none!important; }
+}
+
+.quiet {
+ color: #7f7f7f;
+ color: rgba(0,0,0,0.5);
+}
+.quiet a { opacity: 0.7; }
+
+.fraction {
+ font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
+ font-size: 10px;
+ color: #555;
+ background: #E8E8E8;
+ padding: 4px 5px;
+ border-radius: 3px;
+ vertical-align: middle;
+}
+
+div.path a:link, div.path a:visited { color: #333; }
+table.coverage {
+ border-collapse: collapse;
+ margin: 10px 0 0 0;
+ padding: 0;
+}
+
+table.coverage td {
+ margin: 0;
+ padding: 0;
+ vertical-align: top;
+}
+table.coverage td.line-count {
+ text-align: right;
+ padding: 0 5px 0 20px;
+}
+table.coverage td.line-coverage {
+ text-align: right;
+ padding-right: 10px;
+ min-width:20px;
+}
+
+table.coverage td span.cline-any {
+ display: inline-block;
+ padding: 0 5px;
+ width: 100%;
+}
+.missing-if-branch {
+ display: inline-block;
+ margin-right: 5px;
+ border-radius: 3px;
+ position: relative;
+ padding: 0 4px;
+ background: #333;
+ color: yellow;
+}
+
+.skip-if-branch {
+ display: none;
+ margin-right: 10px;
+ position: relative;
+ padding: 0 4px;
+ background: #ccc;
+ color: white;
+}
+.missing-if-branch .typ, .skip-if-branch .typ {
+ color: inherit !important;
+}
+.coverage-summary {
+ border-collapse: collapse;
+ width: 100%;
+}
+.coverage-summary tr { border-bottom: 1px solid #bbb; }
+.keyline-all { border: 1px solid #ddd; }
+.coverage-summary td, .coverage-summary th { padding: 10px; }
+.coverage-summary tbody { border: 1px solid #bbb; }
+.coverage-summary td { border-right: 1px solid #bbb; }
+.coverage-summary td:last-child { border-right: none; }
+.coverage-summary th {
+ text-align: left;
+ font-weight: normal;
+ white-space: nowrap;
+}
+.coverage-summary th.file { border-right: none !important; }
+.coverage-summary th.pct { }
+.coverage-summary th.pic,
+.coverage-summary th.abs,
+.coverage-summary td.pct,
+.coverage-summary td.abs { text-align: right; }
+.coverage-summary td.file { white-space: nowrap; }
+.coverage-summary td.pic { min-width: 120px !important; }
+.coverage-summary tfoot td { }
+
+.coverage-summary .sorter {
+ height: 10px;
+ width: 7px;
+ display: inline-block;
+ margin-left: 0.5em;
+ background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
+}
+.coverage-summary .sorted .sorter {
+ background-position: 0 -20px;
+}
+.coverage-summary .sorted-desc .sorter {
+ background-position: 0 -10px;
+}
+.status-line { height: 10px; }
+/* yellow */
+.cbranch-no { background: yellow !important; color: #111; }
+/* dark red */
+.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
+.low .chart { border:1px solid #C21F39 }
+.highlighted,
+.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
+ background: #C21F39 !important;
+}
+/* medium red */
+.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
+/* light red */
+.low, .cline-no { background:#FCE1E5 }
+/* light green */
+.high, .cline-yes { background:rgb(230,245,208) }
+/* medium green */
+.cstat-yes { background:rgb(161,215,106) }
+/* dark green */
+.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
+.high .chart { border:1px solid rgb(77,146,33) }
+/* dark yellow (gold) */
+.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
+.medium .chart { border:1px solid #f9cd0b; }
+/* light yellow */
+.medium { background: #fff4c2; }
+
+.cstat-skip { background: #ddd; color: #111; }
+.fstat-skip { background: #ddd; color: #111 !important; }
+.cbranch-skip { background: #ddd !important; color: #111; }
+
+span.cline-neutral { background: #eaeaea; }
+
+.coverage-summary td.empty {
+ opacity: .5;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ line-height: 1;
+ color: #888;
+}
+
+.cover-fill, .cover-empty {
+ display:inline-block;
+ height: 12px;
+}
+.chart {
+ line-height: 0;
+}
+.cover-empty {
+ background: white;
+}
+.cover-full {
+ border-right: none !important;
+}
+pre.prettyprint {
+ border: none !important;
+ padding: 0 !important;
+ margin: 0 !important;
+}
+.com { color: #999 !important; }
+.ignore-none { color: #999; font-weight: normal; }
+
+.wrapper {
+ min-height: 100%;
+ height: auto !important;
+ height: 100%;
+ margin: 0 auto -48px;
+}
+.footer, .push {
+ height: 48px;
+}
diff --git a/coverage/block-navigation.js b/coverage/block-navigation.js
new file mode 100644
index 0000000..530d1ed
--- /dev/null
+++ b/coverage/block-navigation.js
@@ -0,0 +1,87 @@
+/* eslint-disable */
+var jumpToCode = (function init() {
+ // Classes of code we would like to highlight in the file view
+ var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
+
+ // Elements to highlight in the file listing view
+ var fileListingElements = ['td.pct.low'];
+
+ // We don't want to select elements that are direct descendants of another match
+ var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
+
+ // Selector that finds elements on the page to which we can jump
+ var selector =
+ fileListingElements.join(', ') +
+ ', ' +
+ notSelector +
+ missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
+
+ // The NodeList of matching elements
+ var missingCoverageElements = document.querySelectorAll(selector);
+
+ var currentIndex;
+
+ function toggleClass(index) {
+ missingCoverageElements
+ .item(currentIndex)
+ .classList.remove('highlighted');
+ missingCoverageElements.item(index).classList.add('highlighted');
+ }
+
+ function makeCurrent(index) {
+ toggleClass(index);
+ currentIndex = index;
+ missingCoverageElements.item(index).scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ inline: 'center'
+ });
+ }
+
+ function goToPrevious() {
+ var nextIndex = 0;
+ if (typeof currentIndex !== 'number' || currentIndex === 0) {
+ nextIndex = missingCoverageElements.length - 1;
+ } else if (missingCoverageElements.length > 1) {
+ nextIndex = currentIndex - 1;
+ }
+
+ makeCurrent(nextIndex);
+ }
+
+ function goToNext() {
+ var nextIndex = 0;
+
+ if (
+ typeof currentIndex === 'number' &&
+ currentIndex < missingCoverageElements.length - 1
+ ) {
+ nextIndex = currentIndex + 1;
+ }
+
+ makeCurrent(nextIndex);
+ }
+
+ return function jump(event) {
+ if (
+ document.getElementById('fileSearch') === document.activeElement &&
+ document.activeElement != null
+ ) {
+ // if we're currently focused on the search input, we don't want to navigate
+ return;
+ }
+
+ switch (event.which) {
+ case 78: // n
+ case 74: // j
+ goToNext();
+ break;
+ case 66: // b
+ case 75: // k
+ case 80: // p
+ goToPrevious();
+ break;
+ }
+ };
+})();
+window.addEventListener('keydown', jumpToCode);
diff --git a/coverage/clover.xml b/coverage/clover.xml
new file mode 100644
index 0000000..4d2dedb
--- /dev/null
+++ b/coverage/clover.xml
@@ -0,0 +1,219 @@
+
+
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+ +| 1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 | + +1x +5x +5x +5x + + +1x +4x +4x +4x +4x +4x + + + +1x +35x + + + + + + + + + + + + +35x + + +35x + + + + + + + + +35x + + + +35x +5x + + +35x +4x + + + + +35x +12x +12x +12x +12x +12x +5x +7x +1x + + + +35x +6x +6x +6x +6x +6x + + +35x +1x +1x + + +35x +5x +5x +5x + + +35x +1x +1x + + + +35x +2x +2x + + +35x +1x +1x + + +35x +1x +1x + + +35x +1x + + +35x +1x + + + +35x +1x +1x + + + +35x + + + + +35x +5x + +30x + + + + + +35x +2x + + +35x + + + + +2x + + + + +35x + +35x + + + + +35x + + + + +35x +5x + + + +35x +35x + + +35x + +26x +26x + +5x +5x + +4x +4x + + + + + +35x +5x +2x + +5x + + +5x + + + +5x +5x +5x + + + +35x + + + + + + + + + + +1x + + + +35x +4x +1x + +4x + + +4x +1x + +4x +1x +1x +1x + + + +35x + + + +35x +2x + + + +35x +35x + + + + +35x +9x + + + + + +7x +7x + + +9x +8x +8x + + + +35x +35x + + +35x +35x +76x +76x +64x +59x +59x + + +35x +9x + +9x +5x + + +9x + +9x +9x + + + + +35x + + +18x + +6x + + + +35x + + + + + + + + + + + + + + +35x + + + + + +3x + + + +35x + + + + +35x + + + + + +35x +1x + + +35x + + + + + + + + +35x + + + + | import matchLaptopClass from './matchLaptopClass'
+
+const forceAppleSpecs = (specs, scores) => {
+ specs.processor = 'Apple M1 / M2 / M3'
+ specs.gpu = 'Apple Silicon GPU (M1/M2/M3)'
+ scores.graphics = 0
+}
+
+const forceChromeSpecs = (specs) => {
+ specs.processor = 'Intel Celeron / MediaTek'
+ specs.ram = '4 GB o 8 GB'
+ specs.gpu = 'Gráficos integrados básicos'
+ specs.storage = '64 GB eMMC o 128 GB SSD'
+ specs.rationale.push('ChromeOS está pensado para tareas básicas con hardware modesto.')
+}
+
+
+const convertToSpecs = (answers) => {
+ const specs = {
+ processor: '',
+ ram: '',
+ storage: '',
+ gpu: '',
+ touchscreen: false,
+ portability: '',
+ os: '',
+ battery: '',
+ rationale: [],
+ warnings: []
+ }
+
+ specs.budget = answers.budget
+
+
+ const scores = {
+ performance: 0,
+ graphics: 0,
+ multitasking: 0,
+ portability: 0,
+ battery: 0,
+ storage: 0
+ }
+
+ const uses = answers.mainUse === 'full_use'
+ ? ['basics', 'entertainment', 'gaming', 'work_school', 'creating', 'family']
+ : answers.mainUse || []
+
+ if (answers.system === 'mac') {
+ forceAppleSpecs(specs, scores)
+ }
+
+ if (answers.system === 'chrome') {
+ forceChromeSpecs(specs)
+ }
+
+
+ // ==== 1. Scoring según uso ====
+ if (uses.includes('gaming')) {
+ scores.performance += 3.5
+ scores.graphics += 4.5
+ scores.storage += 1
+ specs.rationale.push('Para gaming se requiere GPU dedicada y CPU potente.')
+ if (answers.gamesType === 'complex') {
+ scores.graphics += 3
+ } else if (answers.gamesType === 'simple') {
+ scores.graphics += 1
+ }
+ }
+
+ if (uses.includes('creating') || answers.photoVideo === 'pro') {
+ scores.performance += 3
+ scores.graphics += 2.5
+ scores.multitasking += 2
+ scores.storage += 2
+ specs.rationale.push('Creación de contenido profesional requiere potencia y espacio.')
+ }
+
+ if (answers.photoVideo === 'basic') {
+ scores.graphics += 1
+ scores.storage += 1
+ }
+
+ if (uses.includes('work_school') || answers.workload === 'heavy') {
+ scores.performance += 2.5
+ scores.multitasking += 2.5
+ specs.rationale.push('Trabajo exigente necesita buena CPU y multitarea.')
+ }
+
+ if (uses.includes('family')) {
+ scores.multitasking += 1
+ specs.rationale.push('Uso compartido en casa requiere buena capacidad multitarea.')
+ }
+
+
+ if (answers.webBrowsing === 'heavy') {
+ scores.multitasking += 1.5
+ specs.rationale.push('Muchas pestañas requieren buena RAM.')
+ }
+
+ if (answers.location === 'mobile') {
+ scores.portability += 3
+ specs.rationale.push('Necesitas algo ligero y fácil de transportar.')
+ }
+
+ if (answers.importance === 'touch') {
+ specs.touchscreen = true
+ specs.rationale.push('Requiere pantalla táctil.')
+ }
+
+ if (answers.importance === 'security') {
+ specs.rationale.push('Prioritás seguridad. Buscamos modelos con lector de huellas o reconocimiento facial si es posible.')
+ }
+
+ if (answers.importance === 'portability') {
+ specs.rationale.push('Buscás un equipo liviano. Se prioriza que pese menos de 1.5 kg y tenga una pantalla de 14" o menor.')
+ }
+
+
+ if (answers.battery === 'yes') {
+ scores.battery += 3
+ specs.rationale.push('Priorizás batería de larga duración.')
+ }
+
+ // ==== 2. Especificaciones recomendadas ====
+ specs.processor =
+ scores.performance >= 6 ? 'Intel i7 / Ryzen 7' :
+ scores.performance >= 4 ? 'Intel i5 / Ryzen 5' :
+ 'Intel i3 / Ryzen 3 o Celeron'
+
+ if (answers.system === 'mac') {
+ specs.ram = scores.multitasking >= 4 ? '16 GB' : '8 GB'
+ } else {
+ specs.ram =
+ scores.multitasking >= 4 ? '16 GB' :
+ scores.multitasking >= 2 ? '12 GB' :
+ '8 GB'
+ }
+
+ if (answers.system === 'mac' && uses.includes('gaming')) {
+ specs.warnings.push('macOS no es compatible con la mayoría de juegos exigentes. Considerá Windows si es prioridad.')
+ }
+
+ if (answers.system === 'chrome' && (
+ answers.photoVideo === 'pro' ||
+ answers.workload === 'heavy' ||
+ uses.includes('gaming'))
+ ) {
+ specs.warnings.push('ChromeOS no es ideal para tareas pesadas o software profesional. Considerá Windows o macOS.')
+ }
+
+
+
+ specs.storage = scores.storage >= 2 ? '512 GB SSD' : '256 GB SSD'
+
+ Iif (specs.storage === '256 GB SSD' && uses.includes('creating')) {
+ specs.warnings.push('256 GB puede llenarse rápido con archivos de diseño o video. Considerá 512 GB o más.')
+ }
+
+
+ specs.gpu =
+ scores.graphics >= 4 ? 'NVIDIA RTX 3050 o superior' :
+ scores.graphics >= 2 ? 'Intel Iris Xe / Radeon Vega' :
+ 'Gráficos integrados básicos'
+ // Override para macOS: siempre Apple Silicon
+ if (answers.system === 'mac') {
+ specs.gpu = 'Apple integrada (M1/M2/M3) o Intel HD (modelos antiguos)'
+ }
+
+
+ specs.portability = scores.portability >= 3 ? 'Alta (menos de 1.5kg, 14")' : 'Media o baja'
+ specs.battery = scores.battery >= 3 ? 'Alta (8h o más)' : 'Media (4-7h)'
+
+ // ==== 3. Sistema operativo filtrado ====
+ switch (answers.system) {
+ case 'windows':
+ specs.os = 'Windows 11'
+ break
+ case 'mac':
+ specs.os = 'macOS'
+ break
+ case 'chrome':
+ specs.os = 'ChromeOS'
+ break
+ default:
+ specs.os = 'Windows 11'
+ }
+
+ // ==== 4. Validaciones cruzadas ====
+ if (specs.os === 'macOS') {
+ if (uses.includes('gaming')) {
+ specs.warnings.push('macOS no es ideal para juegos exigentes ni es compatible con la mayoría de títulos AAA. Recomendamos Windows.')
+ }
+ Iif (uses.includes('gaming') && answers.system === 'chrome') {
+ specs.warnings.unshift('⚠️ Elegiste "juegos exigentes" pero seleccionaste ChromeOS, que no soporta juegos avanzados. Recomendamos Windows si querés jugar títulos como GTA, FIFA o similares.')
+ }
+ Iif (specs.gpu.includes('RTX')) {
+ specs.warnings.push('Mac no usa GPUs dedicadas tipo RTX, sus chips integrados (M1/M2/M3) tienen gráficas propias.')
+ specs.gpu = 'Apple Silicon GPU (M1/M2/M3)'
+ }
+ Eif (specs.processor.includes('i7') || specs.processor.includes('Ryzen')) {
+ specs.processor = 'Apple M1 / M2 / M3'
+ specs.rationale.push('En macOS se usan procesadores Apple Silicon, no Intel/AMD tradicionales.')
+ }
+ }
+
+ if (
+ specs.os === 'macOS' &&
+ answers.budget === 'low' &&
+ (
+ uses.includes('gaming') ||
+ uses.includes('creating') ||
+ uses.includes('work_school') ||
+ answers.workload === 'heavy' ||
+ answers.photoVideo === 'pro'
+ )
+ ) {
+ specs.warnings.unshift('⚠️ Querés hacer cosas muy exigentes en una Mac, pero con menos de $5,000 MXN. No es viable. Recomendamos subir el presupuesto o considerar una laptop con Windows.')
+ }
+
+
+ if (specs.os === 'ChromeOS') {
+ if (answers.workload === 'heavy') {
+ specs.warnings.push('ChromeOS no es ideal para multitarea exigente ni software pesado.')
+ }
+ Iif (answers.photoVideo === 'pro') {
+ specs.warnings.push('ChromeOS no soporta software profesional como Photoshop o Premiere. Considerá Windows o macOS.')
+ }
+ if (uses.includes('gaming') && answers.gamesType === 'complex') {
+ specs.warnings.push('ChromeOS no puede ejecutar juegos complejos como GTA o FIFA.')
+ }
+ if (specs.gpu.includes('RTX') || specs.processor.includes('i7')) {
+ specs.warnings.push('ChromeOS no usa hardware de alto rendimiento como RTX o i7. Recomendamos evitar este OS si necesitás potencia.')
+ specs.gpu = 'Gráficos integrados básicos'
+ specs.processor = 'Intel Celeron / MediaTek'
+ }
+ }
+
+ Iif (answers.budget === 'low' && (specs.processor.includes('i5') || specs.ram === '16 GB')) {
+ specs.warnings.push('Tu presupuesto bajo podría no alcanzar para estas specs. Considerá ajustar prioridades o aumentar presupuesto.')
+ }
+
+ if (specs.gpu.includes('RTX') && answers.budget === 'low') {
+ specs.warnings.push('Una GPU RTX requiere un presupuesto medio o alto. Podrías no encontrar algo accesible con esas specs.')
+ }
+
+ // ==== 5. RAM recomendada vs real ====
+ const idealRam = scores.multitasking >= 4 ? '16 GB' : scores.multitasking >= 2 ? '12 GB' : '8 GB'
+ Iif (specs.ram !== idealRam) {
+ specs.warnings.push(`Idealmente deberías tener ${idealRam} de RAM para tu uso.`)
+ }
+
+ // ==== 6. Validación de coherencia interna de specs ====
+ if (specs.gpu.includes('RTX')) {
+ if (
+ !specs.processor.includes('i5') &&
+ !specs.processor.includes('i7') &&
+ !specs.processor.includes('Ryzen 5') &&
+ !specs.processor.includes('Ryzen 7')
+ ) {
+ specs.processor = 'Intel i5 / Ryzen 5'
+ specs.rationale.push('Se ajustó el procesador porque una GPU RTX requiere al menos un i5 o Ryzen 5.')
+ }
+
+ if (specs.ram !== '16 GB') {
+ specs.ram = '16 GB'
+ specs.rationale.push('Se ajustó la RAM porque una GPU RTX necesita al menos 16 GB para funcionar correctamente.')
+ }
+ }
+
+ const bestModels = matchLaptopClass(specs)
+ specs.laptopClass = bestModels // 👈 ya es un array de modelos
+
+
+ const osFilter = specs.os.toLowerCase()
+ specs.laptopClass = bestModels.filter(m => {
+ const name = m.name.toLowerCase()
+ if (osFilter.includes('chrome') && !name.includes('chromebook')) return false
+ if (osFilter.includes('macos') && !name.includes('macbook')) return false
+ Iif (osFilter.includes('windows') && name.includes('macbook')) return false
+ return true
+ }) || []
+
+if (specs.laptopClass.length === 0) {
+ let fallbackMsg = '⚠️ No encontramos laptops con ';
+
+ if (specs.os === 'ChromeOS') fallbackMsg += 'ChromeOS ';
+ else if (specs.os === 'macOS') fallbackMsg += 'macOS ';
+ else EfallbackMsg += 'el sistema operativo deseado ';
+
+ fallbackMsg += 'para tus necesidades. Mostramos opciones similares con Windows.';
+
+ specs.warnings.push(fallbackMsg);
+ specs.laptopClass = bestModels;
+}
+
+
+ // Verificación si el modelo tiene menos RAM que la recomendada
+ if (
+ Array.isArray(bestModels) &&
+ specs.ram === '12 GB' &&
+ bestModels.some(m => m.specs.toLowerCase().includes('8 gb'))
+ ) {
+ specs.warnings.push('Uno de los modelos sugeridos tiene 8 GB de RAM, que puede ser justo si hacés mucha multitarea.')
+ }
+
+ // ==== 7. Advertencia crítica por combinación inviable ====
+ Iif (
+ specs.os === 'ChromeOS' &&
+ answers.budget === 'low' &&
+ (
+ uses.includes('gaming') ||
+ uses.includes('creating') ||
+ uses.includes('work_school') ||
+ answers.workload === 'heavy' ||
+ answers.photoVideo === 'pro'
+ )
+ ) {
+ specs.warnings.unshift('⚠️ Estás solicitando tareas exigentes (edición, juegos, multitarea) en un sistema muy limitado (ChromeOS con presupuesto bajo). No es viable cumplir esos requerimientos con esta combinación. Recomendamos considerar Windows con mayor inversión.')
+ }
+
+
+ if (answers.budget === 'low' && (
+ scores.performance >= 4 ||
+ scores.graphics >= 2 ||
+ scores.multitasking >= 4 ||
+ uses.includes('creating')
+ )) {
+ specs.warnings.push('⚠️ Tu presupuesto bajo puede limitar el rendimiento que necesitás. Considerá ajustar prioridades o aumentar presupuesto.')
+ }
+
+ // === VALIDACIÓN DE USO CONTRADICTORIO ===
+ const isBasicUseOnly = Array.isArray(answers.mainUse)
+ ? answers.mainUse.length === 1 && answers.mainUse[0] === 'entertainment'
+ : answers.mainUse === 'entertainment'
+
+ const isDemandingUser =
+ answers.workload === 'heavy' ||
+ answers.photoVideo === 'pro' ||
+ scores.performance >= 4 ||
+ scores.multitasking >= 4 ||
+ scores.graphics >= 2.5
+
+ if (isBasicUseOnly && isDemandingUser) {
+ specs.warnings.unshift('⚠️ Elegiste un uso simple como "ver videos", pero tus respuestas indican tareas exigentes como edición o multitarea pesada. Considerá ajustar tu selección inicial para mejorar la recomendación.')
+ }
+
+ specs.flags = {
+ prioritizePortability: answers.importance === 'portability',
+ prioritizeSecurity: answers.importance === 'security',
+ prioritizeGaming: uses.includes('gaming'),
+ prioritizeScreenQuality: answers.photoVideo === 'pro'
+ }
+
+
+
+ return specs
+}
+
+export default convertToSpecs
+ |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+ +| File | ++ | Statements | ++ | Branches | ++ | Functions | ++ | Lines | ++ |
|---|---|---|---|---|---|---|---|---|---|
| convertToSpecs.jsx | +
+
+ |
+ 92.99% | +146/157 | +88.26% | +173/196 | +100% | +5/5 | +93.42% | +142/152 | +
| laptopModels.js | +
+
+ |
+ 100% | +3/3 | +100% | +0/0 | +100% | +1/1 | +100% | +3/3 | +
| matchLaptopClass.jsx | +
+
+ |
+ 89.39% | +59/66 | +87.64% | +78/89 | +100% | +6/6 | +97.95% | +48/49 | +
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+ +| 1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 | 2x +46x + +2x + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | const buildGoogleLink = (name) =>
+ `https://www.google.com/search?q=${encodeURIComponent(name + ' laptop')}`
+
+const laptopModels = [
+ {
+ id: "hp-stream-14",
+ name: "HP Stream 14",
+ use: "Estudiantes básicos, movilidad",
+ specs: "Intel Celeron N4120, 4 GB RAM, 64 GB SSD, 14” HD",
+ gpu: "Intel integrada",
+ price: "$4,199 MXN",
+ portability: "Alta",
+ image:
+ "https://www.notebookcheck.net/fileadmin/Notebooks/HP/Stream_14-ax002ng/2.jpg",
+ link: buildGoogleLink("HP Stream 14"),
+ },
+ {
+ id: "acer-aspire-go",
+ name: "Acer Aspire Go AG15",
+ use: "Uso general, estudiantes",
+ specs: "Intel Core i3, 8 GB RAM, 256 GB SSD, 15.6” FHD",
+ gpu: "Intel integrada",
+ price: "$5,999 MXN",
+ portability: "Media",
+ image:
+ "https://laptoping.com/specs/wp-content/uploads/2024/06/Acer-Aspire-Go-15-Slim-AG15-31P-3947.jpg",
+ link: buildGoogleLink("acer-aspire-go"),
+ },
+ {
+ id: "hp-victus-rtx3050",
+ name: "HP Victus RTX 3050",
+ use: "Gaming medio, tareas pesadas",
+ specs: "Intel i5 12450H, 32 GB RAM, 512 GB SSD, RTX 3050",
+ gpu: "RTX 3050",
+ price: "$14,999 MXN",
+ portability: "Media",
+ image:
+ "https://m.media-amazon.com/images/I/71XwPLUaKsL._AC_SL1500_.jpg",
+ link: buildGoogleLink("hp-victus-rtx3050"),
+ },
+ {
+ id: "macbook-air-m1",
+ name: "Apple MacBook Air M1",
+ use: "Creativos, portabilidad, estudiantes",
+ specs: "Apple M1, 8 GB RAM, 256 GB SSD, 13.3” Retina",
+ gpu: "M1",
+ price: "$13,999 MXN",
+ portability: "Alta",
+ image:
+ "https://th.bing.com/th/id/OIP.Q4muQjrfyxVhOB5PMwAF6gHaE8?cb=iwp2&rs=1&pid=ImgDetMainhttps://thangpro.vn/uploads/source/laptop/macbook/mac-air-m1/img-7707.jpg",
+ link: buildGoogleLink("macbook-air-m1"),
+ },
+ {
+ id: "asus-tuf-a15",
+ name: "ASUS TUF Gaming A15",
+ use: "Gaming alto, edición multimedia",
+ specs: "Ryzen 7, 8 GB RAM, 512 GB SSD, RTX 3050",
+ gpu: "RTX 3050",
+ price: "$16,339 MXN",
+ portability: "Media",
+ image:
+ "https://laptopmedia.com/wp-content/uploads/2021/01/2-40.jpg",
+ link: buildGoogleLink("asus-tuf-a15"),
+ },
+ {
+ id: "lenovo-chromebook-3",
+ name: "Lenovo Chromebook 3",
+ use: "Tareas básicas, navegación, Google Docs",
+ specs: "Intel Celeron N4020, 4 GB RAM, 64 GB eMMC, 14” HD",
+ gpu: "Intel integrada",
+ price: "$3,499 MXN",
+ portability: "Alta",
+ image:
+ "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6447/6447138_sd.jpg",
+ link: buildGoogleLink("lenovo-chromebook-3"),
+ },
+ {
+ id: "macbook-air-m2",
+ name: "Apple MacBook Air M2",
+ use: "Profesionales móviles, diseño, universidad",
+ specs: "Apple M2, 8 GB RAM, 256 GB SSD, 13.6” Retina",
+ gpu: "M2",
+ price: "$23,999 MXN",
+ portability: "Alta",
+ image:
+ "https://cdn.shopify.com/s/files/1/1706/9177/products/macbook-air-m2-midnight-custom-mac-bd_b82010cb-9405-4654-a165-9576a249e4e0.jpg",
+ link: buildGoogleLink("macbook-air-m2"),
+ },
+
+ {
+ id: "lenovo-gamer-rtx4070",
+ name: "Lenovo Legion RTX 4070",
+ use: "Gaming extremo, arquitectura, animación",
+ specs: "Intel i9, 32 GB RAM, 1TB SSD, RTX 4070",
+ gpu: "RTX 4070",
+ price: "$38,999 MXN",
+ portability: "Baja",
+ image:
+ "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6534/6534466ld.jpg",
+ link: buildGoogleLink("lenovo-gamer-rtx4070"),
+ },
+ {
+ id: "msi-gamer-rtx2060",
+ name: "MSI GF63 RTX 2060",
+ use: "Gaming clásico, edición semiprofesional",
+ specs: "Intel i5 10th Gen, 16 GB RAM, 512 GB SSD, RTX 2060",
+ gpu: "RTX 2060",
+ price: "$17,499 MXN",
+ portability: "Media",
+ image:
+ "https://i0.wp.com/phukienmaytinh.com.vn/wp-content/uploads/2020/02/MSI-GF63-3.jpg",
+ link: buildGoogleLink("msi-gamer-rtx2060"),
+ },
+ {
+ id: "huawei-matebook-d16-i5",
+ name: "Huawei MateBook D16",
+ use: "Trabajo exigente, multimedia, estudiantes",
+ specs: "Intel Core i5 13420H, 16 GB RAM, 1 TB SSD, 16\" FHD",
+ gpu: "Intel Iris Xe",
+ price: "$14,399 MXN",
+ portability: "Media",
+ image: "https://www.presse-citron.net/app/uploads/2021/05/DSC01401_DxO_PC.jpg",
+ link: buildGoogleLink("Huawei MateBook D16"),
+ },
+ {
+ id: "hp-pavilion-i7-1355u",
+ name: "HP Pavilion i7-1355U",
+ use: "Profesionales, multitarea avanzada, productividad",
+ specs: "Intel Core i7-1355U, 32 GB RAM, 1 TB SSD, 15.6\" FHD",
+ gpu: "Intel Iris Xe",
+ price: "$15,722 MXN",
+ portability: "Media",
+ image: "https://m.media-amazon.com/images/I/613hm2YD6mL._AC_.jpg",
+ link: buildGoogleLink("HP Pavilion i7-1355U"),
+ },
+ {
+ id: "msi-sword-16-i7",
+ name: "MSI Sword 16 HX",
+ use: "Gaming, edición profesional, exigencia gráfica",
+ specs: "Intel Core i7, 16 GB RAM, 1 TB SSD, 16\" FHD",
+ gpu: "RTX 4060",
+ price: "$33,999 MXN",
+ portability: "Media",
+ image: "https://storage-asset.msi.com/global/picture/image/feature/nb/2023_RPLS/sword16-hx-b14v/msi-sword16-display-new.png",
+ link: buildGoogleLink("MSI Sword 16 HX"),
+ },
+ {
+ id: "generic-intel-14",
+ name: "Laptop 14 Intel",
+ use: "Tareas básicas, ofimática, estudiantes",
+ specs: "Intel genérica, 8 GB RAM, 256 GB SSD, 14\" FHD",
+ gpu: "Intel integrada",
+ price: "$4,800 MXN",
+ portability: "Alta",
+ image: "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6425/6425056_rd.jpg",
+ link: buildGoogleLink("Laptop 14 Intel 256gb"),
+ },
+ {
+ id: "macbook-air-m4-512",
+ name: "MacBook Air M4 (512 GB)",
+ use: "Profesionales móviles, diseño, rendimiento alto",
+ specs: "Apple M4, 8 GB RAM, 512 GB SSD, 13” Retina",
+ gpu: "Apple Silicon",
+ price: "$30,950 MXN",
+ portability: "Alta",
+ image: "https://ipadizate.com/hero/2023/01/MacBook-Air-M2-Chip-Purple-Feature.jpg",
+ link: buildGoogleLink("MacBook Air M4 512 GB")
+ },
+ {
+ id: "acer-nitro-5-rtx4060",
+ name: "Acer Nitro 5 RTX 4060",
+ use: "Gaming exigente, edición profesional",
+ specs: "Intel Core i7-13620H, 16 GB RAM, 512 GB SSD, RTX 4060",
+ gpu: "RTX 4060",
+ price: "$20,642 MXN",
+ portability: "Media",
+ image: "https://www.notebookcheck.com/fileadmin/_processed_/9/2/csm_Acer_Nitro_5_RTX_4060_guenstigstes_gaming_notebook_deal_db9eae21d8.jpg",
+ link: buildGoogleLink("Acer Nitro 5 RTX 4060")
+ },
+ {
+ id: "hp-15-fd0999nr",
+ name: "HP 15-fd0999nr",
+ use: "Ofimática avanzada, estudiantes, productividad",
+ specs: "Intel Core i5-1235U, 16 GB RAM, 512 GB SSD, 15.6” FHD",
+ gpu: "Intel Iris Xe",
+ price: "$9,797 MXN",
+ portability: "Media",
+ image: "https://lidernotebooks.com.ar/wp-content/uploads/2024/10/HP-15-fd0999NR-Core-i5_0004_Capa-7.jpg",
+ link: buildGoogleLink("HP 15-fd0999nr")
+ },
+ {
+ id: "msi-gf63-gtx1650",
+ name: "MSI GF63 GTX 1650",
+ use: "Gaming básico, diseño ligero",
+ specs: "Intel Core i5-11400H, 8 GB RAM, 256 GB SSD, GTX 1650",
+ gpu: "GTX 1650",
+ price: "$11,999 MXN",
+ portability: "Media",
+ image: "https://laptop360.net/wp-content/uploads/2022/09/MSI-Gaming-GF63-Thin-11UC-3-1536x1152.jpg",
+ link: buildGoogleLink("MSI GF63 GTX 1650")
+ },
+ {
+ id: "lenovo-yoga-slim-7-ultra5",
+ name: "Lenovo Yoga Slim 7",
+ use: "Profesionales, estudiantes de ingeniería",
+ specs: "Intel Ultra 5 125H, 16 GB RAM, 1 TB SSD, 14” FHD",
+ gpu: "Intel integrada",
+ price: "$18,999 MXN",
+ portability: "Alta",
+ image: "https://cdn.mos.cms.futurecdn.net/4C7JXvghGrpY52MtBiN2cB.jpg",
+ link: buildGoogleLink("Lenovo Yoga Slim 7")
+ },
+ {
+ id: "machcreator-15n-i7",
+ name: "Laptop Machcreator 15N",
+ use: "Multitarea, trabajo profesional, estudiantes avanzados",
+ specs: "Intel Core i7 13620H, 16 GB RAM, 512 GB SSD, 15.6” FHD",
+ gpu: "Intel UHD Graphics",
+ price: "$14,553 MXN",
+ portability: "Media",
+ image: "https://global.machenike.com/cdn/shop/files/11_818b6222-59ce-4193-a68b-bbc8e043b8ef.jpg",
+ link: buildGoogleLink("Laptop Machcreator 15N i7"),
+},
+{
+ id: "machenike-l16pro-rtx4060",
+ name: "Machenike L16 Pro",
+ use: "Gaming exigente, edición profesional, multitarea avanzada",
+ specs: "Ryzen 7 7735H, 16 GB RAM DDR5, 1 TB SSD, 16” 2.5K 165Hz",
+ gpu: "Nvidia GeForce RTX 4060",
+ price: "$34,954 MXN",
+ portability: "Baja",
+ image: "https://http2.mlstatic.com/D_NQ_NP_875287-MLU73599603547_122023-O.webp",
+ link: buildGoogleLink("Machenike L16 Pro RTX 4060"),
+},
+{
+ id: "samsung-galaxy-book4-360",
+ name: "Samsung Galaxy Book4 360",
+ use: "Multimedia, productividad, uso general, estudiantes",
+ specs: "Intel Core 7 Series 1, 16 GB RAM LPDDR5, 512 GB SSD, 15.6” FHD táctil",
+ gpu: "Intel Graphics integrada",
+ price: "$22,999 MXN",
+ portability: "Alta",
+ image: "https://media-ik.croma.com/prod/https://media.croma.com/image/upload/v1708516453/Croma%20Assets/Computers%20Peripherals/Laptop/Images/305055_4_bsd9ja.png",
+ link: buildGoogleLink("Samsung Galaxy Book4 360"),
+},
+{
+ id: "topgro-n5-i3-mx230",
+ name: "Topgro N5",
+ use: "Ofimática, uso general, multimedia básica",
+ specs: "Intel Core i3-1005G1, 16 GB RAM DDR4, 512 GB SSD, NVIDIA GeForce MX230, 15.6” FHD",
+ gpu: "NVIDIA GeForce MX230 (2 GB GDDR5)",
+ price: "$6,935 MXN",
+ portability: "Media",
+ image: "https://m.media-amazon.com/images/I/71gXrO3lsqL._AC_.jpg",
+ link: buildGoogleLink("Topgro N5 i3 MX230"),
+},
+{
+ id: "vsap-n4020-14",
+ name: "VSAP Intel Celeron N4020",
+ use: "Ofimática, navegación, estudiantes",
+ specs: "Intel Celeron N4020, 8 GB RAM DDR4, 512 GB SSD, 14.1\" FHD",
+ gpu: "Intel UHD Graphics 600",
+ price: "$3,695 MXN",
+ portability: "Alta",
+ image: "https://static.wixstatic.com/media/c8ef56_df2decbc5ac442c28c399e2c9a2ee5e2~mv2.webp",
+ link: buildGoogleLink("VSAP Intel Celeron N4020"),
+},
+
+];
+
+export default laptopModels;
+ |
+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +
+ +| 1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 | + +2x +1200x + + +2x +794x + + +2x +57x +1311x +1311x +1311x + +1311x +1262x +1246x +184x +24x + + +1078x +1078x +1078x +870x +814x + + +20x + + +794x + +794x +745x +318x + +300x + + +57x +300x + +300x +300x + +300x +300x +300x +300x +300x +300x + +300x +4x + +300x +7x +7x + + + +300x +15x + + + + + + +4x + + + + + +300x + + + +300x + + +57x +529x + + +57x + + + + + | import laptopModels from './laptopModels'
+
+const normalize = (text) =>
+ text.toLowerCase()
+ .replace(/(intel|amd|apple|core|ryzen|graphics|nvidia|geforce|radeon|gpu)|\s+/gi, '')
+
+const parsePrice = (priceString) =>
+ parseInt(priceString.replace(/[^\d]/g, ''), 10)
+
+
+const matchLaptopClass = (specs) => {
+ const compatibleModels = laptopModels.filter(model => {
+ const modelGPU = model.gpu.toLowerCase()
+ const modelOS = model.use.toLowerCase()
+ const modelSpecs = model.specs.toLowerCase()
+
+ if (specs.os === 'ChromeOS' && modelGPU.includes('rtx')) return false
+ if (specs.os === 'ChromeOS' && specs.processor.toLowerCase().includes('i7')) return false
+ if (specs.os === 'macOS') {
+ if (!model.name.toLowerCase().includes('macbook')) return false
+ if (!model.gpu.toLowerCase().includes('m1') && !model.gpu.toLowerCase().includes('m2') && !model.gpu.toLowerCase().includes('m3')) return false
+ }
+
+ Iif (specs.os === 'macOS' && modelGPU.includes('rtx')) return false
+ Iif (modelOS.includes('chrome') && specs.gpu.toLowerCase().includes('rtx')) return false
+ if (specs.gpu.toLowerCase().includes('rtx') && !modelGPU.includes('rtx')) return false
+ if (specs.ram === '16 GB' && !modelSpecs.includes('16 gb')) return false
+ if (
+ (specs.processor.includes('i7') || specs.processor.includes('ryzen 7')) &&
+ !modelSpecs.includes('i7') && !modelSpecs.includes('ryzen 7')
+ ) return false
+
+ // ✅ Presupuesto
+ const price = parsePrice(model.price)
+
+ if (specs.budget === 'low' && price > 6000) return false
+ if (specs.budget === 'medium' && price > 13000) return false
+ if (specs.budget === 'high' && price < 13000) return false
+
+ return true
+ })
+
+ const scoredModels = compatibleModels.map(model => {
+ let score = 0
+
+ const modelSpecs = model.specs.toLowerCase()
+ const modelGPU = model.gpu.toLowerCase()
+
+ Iif (normalize(modelSpecs).includes(normalize(specs.processor))) score += 2
+ if (modelSpecs.includes(specs.ram.toLowerCase())) score += 2
+ Iif (normalize(modelGPU).includes(normalize(specs.gpu))) score += 2
+ if (modelSpecs.includes(specs.storage.toLowerCase())) score += 1
+ Iif (model.portability === specs.portability) score += 1
+ Iif (model.use.toLowerCase().includes(specs.os.toLowerCase())) score += 1
+
+ if (specs.flags?.prioritizePortability && model.portability === 'Alta') {
+ score += 1.5
+ }
+ if (specs.flags?.prioritizeGaming) {
+ Eif (modelGPU.includes('rtx') || modelGPU.includes('gtx') || modelGPU.includes('mx')) {
+ score += 1.5
+ }
+ }
+
+ if (specs.flags?.prioritizeScreenQuality) {
+ if (
+ modelSpecs.includes('2.5k') ||
+ modelSpecs.includes('retina') ||
+ modelSpecs.includes('qhd') ||
+ modelSpecs.includes('2560') ||
+ modelSpecs.includes('amoled')
+ ) {
+ score += 1.5
+ }
+ }
+
+
+
+ Iif (specs.flags?.prioritizeSecurity && model.specs.toLowerCase().includes('huella')) {
+ score += 1.5
+ }
+
+ return { ...model, matchScore: score }
+ })
+
+ const bestMatches = scoredModels
+ .sort((a, b) => b.matchScore - a.matchScore)
+ .slice(0, 3) // 👈 Cambia 3 por cuántas quieres mostrar
+
+ return bestMatches.length ? bestMatches : [{ name: "Clase genérica", specs: "" }]
+
+}
+
+export default matchLaptopClass
+ |